x11drv: Properly handle VK_LMENU input.
[wine] / dlls / x11drv / keyboard.c
1 /*
2  * X11 keyboard driver
3  *
4  * Copyright 1993 Bob Amstadt
5  * Copyright 1996 Albrecht Kleine
6  * Copyright 1997 David Faure
7  * Copyright 1998 Morten Welinder
8  * Copyright 1998 Ulrich Weigand
9  * Copyright 1999 Ove Kåven
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
24  */
25
26 #include "config.h"
27
28 #include <X11/Xatom.h>
29 #include <X11/keysym.h>
30 #include <X11/Xlib.h>
31 #include <X11/Xresource.h>
32 #include <X11/Xutil.h>
33 #ifdef HAVE_XKB
34 #include <X11/XKBlib.h>
35 #endif
36
37 #include <ctype.h>
38 #include <stdarg.h>
39 #include <string.h>
40
41 #define NONAMELESSUNION
42 #define NONAMELESSSTRUCT
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wingdi.h"
46 #include "winuser.h"
47 #include "wine/winuser16.h"
48 #include "winnls.h"
49 #include "win.h"
50 #include "x11drv.h"
51 #include "wine/server.h"
52 #include "wine/unicode.h"
53 #include "wine/debug.h"
54
55 WINE_DEFAULT_DEBUG_CHANNEL(keyboard);
56 WINE_DECLARE_DEBUG_CHANNEL(key);
57
58 typedef union
59 {
60     struct
61     {
62 #ifndef BITFIELDS_BIGENDIAN
63         unsigned long count : 16;
64 #endif
65         unsigned long code : 8;
66         unsigned long extended : 1;
67         unsigned long unused : 2;
68         unsigned long win_internal : 2;
69         unsigned long context : 1;
70         unsigned long previous : 1;
71         unsigned long transition : 1;
72 #ifdef BITFIELDS_BIGENDIAN
73         unsigned long count : 16;
74 #endif
75     } lp1;
76     unsigned long lp2;
77 } KEYLP;
78
79 /* key state table bits:
80   0x80 -> key is pressed
81   0x40 -> key got pressed since last time
82   0x01 -> key is toggled
83 */
84 BYTE key_state_table[256];
85
86 static BYTE TrackSysKey = 0; /* determine whether ALT key up will cause a WM_SYSKEYUP
87                                 or a WM_KEYUP message */
88
89 static int min_keycode, max_keycode, keysyms_per_keycode;
90 static WORD keyc2vkey[256], keyc2scan[256];
91
92 static int NumLockMask, AltGrMask; /* mask in the XKeyEvent state */
93 static int kcControl, kcAlt, kcShift, kcNumLock, kcCapsLock; /* keycodes */
94
95 static char KEYBOARD_MapDeadKeysym(KeySym keysym);
96
97 /* Keyboard translation tables */
98 #define MAIN_LEN 49
99 static const WORD main_key_scan_qwerty[MAIN_LEN] =
100 {
101 /* this is my (102-key) keyboard layout, sorry if it doesn't quite match yours */
102  /* `    1    2    3    4    5    6    7    8    9    0    -    = */
103    0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
104  /* q    w    e    r    t    y    u    i    o    p    [    ] */
105    0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
106  /* a    s    d    f    g    h    j    k    l    ;    '    \ */
107    0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
108  /* z    x    c    v    b    n    m    ,    .    / */
109    0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
110    0x56 /* the 102nd key (actually to the right of l-shift) */
111 };
112
113 static const WORD main_key_scan_abnt_qwerty[MAIN_LEN] =
114 {
115  /* `    1    2    3    4    5    6    7    8    9    0    -    = */
116    0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
117  /* q    w    e    r    t    y    u    i    o    p    [    ] */
118    0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
119  /* a    s    d    f    g    h    j    k    l    ;    '    \ */
120    0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
121  /* \      z    x    c    v    b    n    m    ,    .    / */
122    0x5e,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
123    0x56, /* the 102nd key (actually to the right of l-shift) */
124 };
125
126 static const WORD main_key_scan_dvorak[MAIN_LEN] =
127 {
128  /* `    1    2    3    4    5    6    7    8    9    0    [    ] */
129    0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x1A,0x1B,
130  /* '    ,    .    p    y    f    g    c    r    l    /    = */
131    0x28,0x33,0x34,0x19,0x15,0x21,0x22,0x2E,0x13,0x26,0x35,0x0D,
132  /* a    o    e    u    i    d    h    t    n    s    -    \ */
133    0x1E,0x18,0x12,0x16,0x17,0x20,0x23,0x14,0x31,0x1F,0x0C,0x2B,
134  /* ;    q    j    k    x    b    m    w    v    z */
135    0x27,0x10,0x24,0x25,0x2D,0x30,0x32,0x11,0x2F,0x2C,
136    0x56 /* the 102nd key (actually to the right of l-shift) */
137 };
138
139 static const WORD main_key_scan_qwerty_jp106[MAIN_LEN] =
140 {
141   /* this is my (106-key) keyboard layout, sorry if it doesn't quite match yours */
142  /* 1    2    3    4    5    6    7    8    9    0    -    ^    \ */
143    0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x29,
144  /* q    w    e    r    t    y    u    i    o    p    @    [ */
145    0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
146  /* a    s    d    f    g    h    j    k    l    ;    :    ] */
147    0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
148  /* z    x    c    v    b    n    m    ,    .    / */
149    0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
150    0x56 /* the 102nd key (actually to the right of l-shift) */
151 };
152
153
154 static const WORD main_key_vkey_qwerty[MAIN_LEN] =
155 {
156 /* NOTE: this layout must concur with the scan codes layout above */
157    VK_OEM_3,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS,VK_OEM_PLUS,
158    'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_4,VK_OEM_6,
159    'A','S','D','F','G','H','J','K','L',VK_OEM_1,VK_OEM_7,VK_OEM_5,
160    'Z','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
161    VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
162 };
163
164 static const WORD main_key_vkey_qwerty_jp106[MAIN_LEN] =
165 {
166 /* NOTE: this layout must concur with the scan codes layout above */
167    '1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS,VK_OEM_PLUS,VK_OEM_3,
168    'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_4,VK_OEM_6,
169    'A','S','D','F','G','H','J','K','L',VK_OEM_1,VK_OEM_7,VK_OEM_5,
170    'Z','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
171    VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
172 };
173
174 static const WORD main_key_vkey_qwerty_v2[MAIN_LEN] =
175 {
176 /* NOTE: this layout must concur with the scan codes layout above */
177    VK_OEM_5,'1','2','3','4','5','6','7','8','9','0',VK_OEM_PLUS,VK_OEM_4,
178    'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_6,VK_OEM_1,
179    'A','S','D','F','G','H','J','K','L',VK_OEM_3,VK_OEM_7,VK_OEM_2,
180    'Z','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_MINUS,
181    VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
182 };
183
184 static const WORD main_key_vkey_qwertz[MAIN_LEN] =
185 {
186 /* NOTE: this layout must concur with the scan codes layout above */
187    VK_OEM_3,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS,VK_OEM_PLUS,
188    'Q','W','E','R','T','Z','U','I','O','P',VK_OEM_4,VK_OEM_6,
189    'A','S','D','F','G','H','J','K','L',VK_OEM_1,VK_OEM_7,VK_OEM_5,
190    'Y','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
191    VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
192 };
193
194 static const WORD main_key_vkey_qwertz_105[MAIN_LEN] =
195 {
196 /* NOTE: this layout must concur with the scan codes layout above */
197    VK_OEM_3,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS,VK_OEM_PLUS,
198    'Q','W','E','R','T','Z','U','I','O','P',VK_OEM_4,VK_OEM_6,
199    'A','S','D','F','G','H','J','K','L',VK_OEM_1,VK_OEM_7,VK_OEM_5,
200    VK_OEM_102,'Y','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2
201 };
202
203 static const WORD main_key_vkey_abnt_qwerty[MAIN_LEN] =
204 {
205 /* NOTE: this layout must concur with the scan codes layout above */
206    VK_OEM_3,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS,VK_OEM_PLUS,
207    'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_4,VK_OEM_6,
208    'A','S','D','F','G','H','J','K','L',VK_OEM_1,VK_OEM_8,VK_OEM_5,
209    VK_OEM_7,'Z','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
210    VK_OEM_102, /* the 102nd key (actually to the right of l-shift) */
211 };
212
213 static const WORD main_key_vkey_azerty[MAIN_LEN] =
214 {
215 /* NOTE: this layout must concur with the scan codes layout above */
216    VK_OEM_7,'1','2','3','4','5','6','7','8','9','0',VK_OEM_4,VK_OEM_PLUS,
217    'A','Z','E','R','T','Y','U','I','O','P',VK_OEM_6,VK_OEM_1,
218    'Q','S','D','F','G','H','J','K','L','M',VK_OEM_3,VK_OEM_5,
219    'W','X','C','V','B','N',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,VK_OEM_8,
220    VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
221 };
222
223 static const WORD main_key_vkey_dvorak[MAIN_LEN] =
224 {
225 /* NOTE: this layout must concur with the scan codes layout above */
226    VK_OEM_3,'1','2','3','4','5','6','7','8','9','0',VK_OEM_4,VK_OEM_6,
227    VK_OEM_7,VK_OEM_COMMA,VK_OEM_PERIOD,'P','Y','F','G','C','R','L',VK_OEM_2,VK_OEM_PLUS,
228    'A','O','E','U','I','D','H','T','N','S',VK_OEM_MINUS,VK_OEM_5,
229    VK_OEM_1,'Q','J','K','X','B','M','W','V','Z',
230    VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
231 };
232
233 /*** DEFINE YOUR NEW LANGUAGE-SPECIFIC MAPPINGS BELOW, SEE EXISTING TABLES */
234
235 /* the VK mappings for the main keyboard will be auto-assigned as before,
236    so what we have here is just the character tables */
237 /* order: Normal, Shift, AltGr, Shift-AltGr */
238 /* We recommend you write just what is guaranteed to be correct (i.e. what's
239    written on the keycaps), not the bunch of special characters behind AltGr
240    and Shift-AltGr if it can vary among different X servers */
241 /* Remember that your 102nd key (to the right of l-shift) should be on a
242    separate line, see existing tables */
243 /* If Wine fails to match your new table, use WINEDEBUG=+key to find out why */
244 /* Remember to also add your new table to the layout index table far below! */
245
246 /*** German Logitech Desktop Pro keyboard layout */
247 static const char main_key_DE_logitech[MAIN_LEN][4] =
248 {
249  "^\xb0","1!","2\"","3\xa7","4$","5%","6&","7/{","8([","9)]","0=}","\xdf?\\","'`",
250  "qQ@","wW","eE","rR","tT","zZ","uU","iI","oO","pP","\xfc\xdc","+*~",
251  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","\xf6\xd6","\xe4\xc4","#'",
252  "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
253  "<>|"
254 };
255
256 /*** United States keyboard layout (mostly contributed by Uwe Bonnes) */
257 static const char main_key_US[MAIN_LEN][4] =
258 {
259  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
260  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
261  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
262  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?"
263 };
264
265 /*** United States keyboard layout (phantom key version) */
266 /* (XFree86 reports the <> key even if it's not physically there) */
267 static const char main_key_US_phantom[MAIN_LEN][4] =
268 {
269  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
270  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
271  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
272  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
273  "<>" /* the phantom key */
274 };
275
276 /*** United States keyboard layout (dvorak version) */
277 static const char main_key_US_dvorak[MAIN_LEN][4] =
278 {
279  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","[{","]}",
280  "'\"",",<",".>","pP","yY","fF","gG","cC","rR","lL","/?","=+",
281  "aA","oO","eE","uU","iI","dD","hH","tT","nN","sS","-_","\\|",
282  ";:","qQ","jJ","kK","xX","bB","mM","wW","vV","zZ"
283 };
284
285 /*** British keyboard layout */
286 static const char main_key_UK[MAIN_LEN][4] =
287 {
288  "`","1!","2\"","3£","4$","5%","6^","7&","8*","9(","0)","-_","=+",
289  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
290  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'@","#~",
291  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
292  "\\|"
293 };
294
295 /*** French keyboard layout (setxkbmap fr) */
296 static const char main_key_FR[MAIN_LEN][4] =
297 {
298  "²","&1","é2","\"3","'4","(5","-6","è7","_8","ç9","à0",")°","=+",
299  "aA","zZ","eE","rR","tT","yY","uU","iI","oO","pP","^¨","$£",
300  "qQ","sS","dD","fF","gG","hH","jJ","kK","lL","mM","ù%","*µ",
301  "wW","xX","cC","vV","bB","nN",",?",";.",":/","!§",
302  "<>"
303 };
304
305 /*** Icelandic keyboard layout (setxkbmap is) */
306 static const char main_key_IS[MAIN_LEN][4] =
307 {
308  "°","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","öÖ","-_",
309  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","ðÐ","'?",
310  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","æÆ","´Ä","+*",
311  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","þÞ",
312  "<>"
313 };
314
315 /*** German keyboard layout (setxkbmap de) */
316 static const char main_key_DE[MAIN_LEN][4] =
317 {
318  "^°","1!","2\"","3§","4$","5%","6&","7/","8(","9)","0=","ß?","´`",
319  "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*",
320  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
321  "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
322  "<>|"
323 };
324
325 /*** German keyboard layout without dead keys */
326 static const char main_key_DE_nodead[MAIN_LEN][4] =
327 {
328  "^°","1!","2\"","3§","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","´",
329  "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
330  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
331  "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
332  "<>"
333 };
334
335 /*** German keyboard layout without dead keys 105 Keys (contributed by Matthias Fechner)*/
336 static const char main_key_DE_nodead_105[MAIN_LEN][4] =
337 {
338  "^°","1!","2\"²","3§³","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","'`",
339  "qQ@","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
340  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
341  "<>|","yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
342 };
343
344 /*** Swiss German keyboard layout (setxkbmap ch -variant de) */
345 static const char main_key_SG[MAIN_LEN][4] =
346 {
347  "§°","1+","2\"","3*","4ç","5%","6&","7/","8(","9)","0=","'?","^`",
348  "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üè","¨!",
349  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öé","äà","$£",
350  "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
351  "<>"
352 };
353
354 /*** Swiss French keyboard layout (setxkbmap ch -variant fr) */
355 static const char main_key_SF[MAIN_LEN][4] =
356 {
357  "§°","1+","2\"","3*","4ç","5%","6&","7/","8(","9)","0=","'?","^`",
358  "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","èü","¨!",
359  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","éö","àä","$£",
360  "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
361  "<>"
362 };
363
364 /*** Norwegian keyboard layout (contributed by Ove Kåven) */
365 static const char main_key_NO[MAIN_LEN][4] =
366 {
367  "|§","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?","\\`´",
368  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^~",
369  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","øØ","æÆ","'*",
370  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
371  "<>"
372 };
373
374 /*** Danish keyboard layout (setxkbmap dk) */
375 static const char main_key_DA[MAIN_LEN][4] =
376 {
377  "½§","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","´`",
378  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^",
379  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","æÆ","øØ","'*",
380  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
381  "<>"
382 };
383
384 /*** Swedish keyboard layout (setxkbmap se) */
385 static const char main_key_SE[MAIN_LEN][4] =
386 {
387  "§½","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","´`",
388  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^",
389  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*",
390  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
391  "<>"
392 };
393
394 /*** Estonian keyboard layout (setxkbmap ee) */
395 static const char main_key_ET[MAIN_LEN][4] =
396 {
397  "·~","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","´`",
398  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","üÜ","õÕ",
399  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*",
400  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
401  "<>"
402 };
403
404 /*** Canadian French keyboard layout (setxkbmap ca_enhanced) */
405 static const char main_key_CF[MAIN_LEN][4] =
406 {
407  "#|\\","1!±","2\"@","3/£","4$¢","5%¤","6?¬","7&¦","8*²","9(³","0)¼","-_½","=+¾",
408  "qQ","wW","eE","rR","tT","yY","uU","iI","oO§","pP¶","^^[","¸¨]",
409  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:~","``{","<>}",
410  "zZ","xX","cC","vV","bB","nN","mM",",'-",".","éÉ",
411  "«»°"
412 };
413
414 /*** Canadian French keyboard layout (setxkbmap ca -variant fr) */
415 static const char main_key_CA_fr[MAIN_LEN][4] =
416 {
417  "#|","1!","2\"","3/","4$","5%","6?","7&","8*","9(","0)","-_","=+",
418  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","^^","¸¨",
419  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","``","<>",
420  "zZ","xX","cC","vV","bB","nN","mM",",'",".","éÉ",
421  "«»"
422 };
423
424 /*** Canadian keyboard layout (setxkbmap ca) */
425 static const char main_key_CA[MAIN_LEN][4] =
426 {
427  "/\\","1!¹¡","2@²","3#³£","4$¼¤","5%½","6?¾","7&","8*","9(","0)","-_","=+",
428  "qQ","wW","eE","rR","tT","yY","uU","iI","oOøØ","pPþÞ","^¨¨","çÇ~",
429  "aAæÆ","sSߧ","dDðÐ","fF","gG","hH","jJ","kK","lL",";:´","èÈ","àÀ",
430  "zZ","xX","cC¢©","vV","bB","nN","mMµº",",'",".\"·÷","éÉ",
431  "ùÙ"
432 };
433
434 /*** Portuguese keyboard layout (setxkbmap pt) */
435 static const char main_key_PT[MAIN_LEN][4] =
436 {
437  "\\|","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","«»",
438  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","+*","´`",
439  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","çÇ","ºª","~^",
440  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
441  "<>"
442 };
443
444 /*** Italian keyboard layout (setxkbmap it) */
445 static const char main_key_IT[MAIN_LEN][4] =
446 {
447  "\\|","1!","2\"","3£","4$","5%","6&","7/","8(","9)","0=","'?","ì^",
448  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","èé","+*",
449  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","òç","à°","ù§",
450  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
451  "<>"
452 };
453
454 /*** Finnish keyboard layout (setxkbmap fi) */
455 static const char main_key_FI[MAIN_LEN][4] =
456 {
457  "§½","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","´`",
458  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^",
459  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*",
460  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
461  "<>"
462 };
463
464 /*** Bulgarian bds keyboard layout */
465 static const char main_key_BG_bds[MAIN_LEN][4] =
466 {
467  "`~()","1!","2@2?","3#3+","4$4\"","5%","6^6=","7&7:","8*8/","9(","0)","-_-I","=+.V",
468  "qQ,û","wWóÓ","eEåÅ","rRèÈ","tTøØ","yYùÙ","uUêÊ","iIñÑ","oOäÄ","pPçÇ","[{öÖ","]};",
469  "aAüÜ","sSÿß","dDàÀ","fFîÎ","gGæÆ","hHãÃ","jJòÒ","kKíÍ","lLâÂ",";:ìÌ","'\"÷×","\\|'Û",
470  "zZþÞ","xXéÉ","cCúÚ","vVýÝ","bBôÔ","nNõÕ","mMïÏ",",<ðÐ",".>ëË","/?áÁ",
471  "<>" /* the phantom key */
472 };
473
474 /*** Bulgarian phonetic keyboard layout */
475 static const char main_key_BG_phonetic[MAIN_LEN][4] =
476 {
477  "`~÷×","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
478  "qQÿß","wWâÂ","eEåÅ","rRðÐ","tTòÒ","yYúÚ","uUóÓ","iIèÈ","oOîÎ","pPïÏ","[{øØ","]}ùÙ",
479  "aAàÀ","sSñÑ","dDäÄ","fFôÔ","gGãÃ","hHõÕ","jJéÉ","kKêÊ","lLëË",";:","'\"","\\|þÞ",
480  "zZçÇ","xXüÜ","cCöÖ","vVæÆ","bBáÁ","nNíÍ","mMìÌ",",<",".>","/?",
481  "<>" /* the phantom key */
482 };
483
484 /*** Belarusian standard keyboard layout (contributed by Hleb Valoska) */
485 /*** It matches belarusian layout for XKB from Alexander Mikhailian    */
486 static const char main_key_BY[MAIN_LEN][4] =
487 {
488  "`~£³","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
489  "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oO®¾","pPÚú","[{Èè","]}''",
490  "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|/|",
491  "zZÑñ","xXÞþ","cCÓó","vVÍí","bB¦¶","nNÔô","mMØø",",<Ââ",".>Àà","/?.,", "<>|¦",
492 };
493
494
495 /*** Russian keyboard layout (contributed by Pavel Roskin) */
496 static const char main_key_RU[MAIN_LEN][4] =
497 {
498  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
499  "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}ßÿ",
500  "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|",
501  "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?"
502 };
503
504 /*** Russian keyboard layout (phantom key version) */
505 static const char main_key_RU_phantom[MAIN_LEN][4] =
506 {
507  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
508  "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}ßÿ",
509  "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|",
510  "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?",
511  "<>" /* the phantom key */
512 };
513
514 /*** Russian keyboard layout KOI8-R */
515 static const char main_key_RU_koi8r[MAIN_LEN][4] =
516 {
517  "()","1!","2\"","3/","4$","5:","6,","7.","8;","9?","0%","-_","=+",
518  "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","ßÿ",
519  "Ææ","Ùù","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","Üü","\\|",
520  "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà","/?",
521  "<>" /* the phantom key */
522 };
523
524 /*** Russian keyboard layout cp1251 */
525 static const char main_key_RU_cp1251[MAIN_LEN][4] =
526 {
527  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
528  "qQéÉ","wWöÖ","eEóÓ","rRêÊ","tTåÅ","yYíÍ","uUãÃ","iIøØ","oOùÙ","pPçÇ","[{õÕ","]}úÚ",
529  "aAôÔ","sSûÛ","dDâÂ","fFàÀ","gGïÏ","hHðÐ","jJîÎ","kKëË","lLäÄ",";:æÆ","'\"ýÝ","\\|",
530  "zZÿß","xX÷×","cCñÑ","vVìÌ","bBèÈ","nNòÒ","mMüÜ",",<áÁ",".>þÞ","/?",
531  "<>" /* the phantom key */
532 };
533
534 /*** Russian phonetic keyboard layout */
535 static const char main_key_RU_phonetic[MAIN_LEN][4] =
536 {
537  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
538  "qQÑñ","wW×÷","eEÅå","rRÒò","tTÔô","yYÙù","uUÕõ","iIÉé","oOÏï","pPÐð","[{Ûû","]}Ýý",
539  "aAÁá","sSÓó","dDÄä","fFÆæ","gGÇç","hHÈè","jJÊê","kKËë","lLÌì",";:","'\"","\\|",
540  "zZÚú","xXØø","cCÃã","vVÖö","bBÂâ","nNÎî","mMÍí",",<",".>","/?",
541  "<>" /* the phantom key */
542 };
543
544 /*** Ukrainian keyboard layout KOI8-U */
545 static const char main_key_UA[MAIN_LEN][4] =
546 {
547  "`~­½","1!1!","2@2\"","3#3'","4$4*","5%5:","6^6,","7&7.","8*8;","9(9(","0)0)","-_-_","=+=+",
548  "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}§·",
549  "aAÆæ","sS¦¶","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"¤´","\\|\\|",
550  "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?/?",
551  "<>" /* the phantom key */
552 };
553
554 /*** Ukrainian keyboard layout KOI8-U by O. Nykyforchyn */
555 /***  (as it appears on most of keyboards sold today)   */
556 static const char main_key_UA_std[MAIN_LEN][4] =
557 {
558  "­½","1!","2\"","3'","4;","5%","6:","7?","8*","9(","0)","-_","=+",
559  "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","§·",
560  "Ææ","¦¶","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","¤´","\\/",
561  "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà",".,",
562  "<>" /* the phantom key */
563 };
564
565 /*** Russian keyboard layout KOI8-R (pair to the previous) */
566 static const char main_key_RU_std[MAIN_LEN][4] =
567 {
568  "£³","1!","2\"","3'","4;","5%","6:","7?","8*","9(","0)","-_","=+",
569  "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","ßÿ",
570  "Ææ","Ùù","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","Üü","\\/",
571  "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà",".,",
572  "<>" /* the phantom key */
573 };
574
575 /*** Spanish keyboard layout (setxkbmap es) */
576 static const char main_key_ES[MAIN_LEN][4] =
577 {
578  "ºª","1!","2\"","3·","4$","5%","6&","7/","8(","9)","0=","'?","¡¿",
579  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","`^","+*",
580  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ñÑ","´¨","çÇ",
581  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
582  "<>"
583 };
584
585 /*** Belgian keyboard layout ***/
586 static const char main_key_BE[MAIN_LEN][4] =
587 {
588  "","&1|","é2@","\"3#","'4","(5","§6^","è7","!8","ç9{","à0}",")°","-_",
589  "aA","zZ","eE¤","rR","tT","yY","uU","iI","oO","pP","^¨[","$*]",
590  "qQ","sSß","dD","fF","gG","hH","jJ","kK","lL","mM","ù%´","µ£`",
591  "wW","xX","cC","vV","bB","nN",",?",";.",":/","=+~",
592  "<>\\"
593 };
594
595 /*** Hungarian keyboard layout (setxkbmap hu) */
596 static const char main_key_HU[MAIN_LEN][4] =
597 {
598  "0§","1'","2\"","3+","4!","5%","6/","7=","8(","9)","öÖ","üÜ","óÓ",
599  "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","õÕ","úÚ",
600  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","éÉ","áÁ","ûÛ",
601  "yY","xX","cC","vV","bB","nN","mM",",?",".:","-_",
602  "íÍ"
603 };
604
605 /*** Polish (programmer's) keyboard layout ***/
606 static const char main_key_PL[MAIN_LEN][4] =
607 {
608  "`~","1!","2@","3#","4$","5%","6^","7&§","8*","9(","0)","-_","=+",
609  "qQ","wW","eEêÊ","rR","tT","yY","uU","iI","oOóÓ","pP","[{","]}",
610  "aA±¡","sS¶¦","dD","fF","gG","hH","jJ","kK","lL³£",";:","'\"","\\|",
611  "zZ¿¯","xX¼¬","cCæÆ","vV","bB","nNñÑ","mM",",<",".>","/?",
612  "<>|"
613 };
614
615 /*** Slovenian keyboard layout (setxkbmap si) ***/
616 static const char main_key_SI[MAIN_LEN][4] =
617 {
618  "¸¨","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","+*",
619  "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","¹©","ðÐ",
620  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","èÈ","æÆ","¾®",
621  "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
622  "<>"
623 };
624
625 /*** Serbian keyboard layout (setxkbmap sr) ***/
626 static const char main_key_SR[MAIN_LEN][4] =
627 {
628  "`~","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","+*",
629  "©¹","ªº","Åå","Òò","Ôô","Úú","Õõ","Éé","Ïï","Ðð","Ûû","[]",
630  "Áá","Óó","Ää","Ææ","Çç","Èè","¨¸","Ëë","Ìì","Þþ","«»","-_",
631  "¡±","¯¿","Ãã","×÷","Ââ","Îî","Íí",",;",".:","Öö",
632  "<>" /* the phantom key */
633 };
634
635 /*** Serbian keyboard layout (setxkbmap us,sr) ***/
636 static const char main_key_US_SR[MAIN_LEN][4] =
637 {
638  "`~","1!","2@2\"","3#","4$","5%","6^6&","7&7/","8*8(","9(9)","0)0=","-_'?","=++*",
639  "qQ©¹","wWªº","eEÅå","rRÒò","tTÔô","yYÚú","uUÕõ","iIÉé","oOÏï","pPÐð","[{Ûû","]}[]",
640  "aAÁá","sSÓó","dDÄä","fFÆæ","gGÇç","hHÈè","jJ¨¸","kKËë","lLÌì",";:Þþ","'\"«»","\\|-_",
641  "zZ¡±","xX¯¿","cCÃã","vV×÷","bBÂâ","nNÎî","mMÍí",",<,;",".>.:","/?Öö",
642  "<>" /* the phantom key */
643 };
644
645 /*** Croatian keyboard layout specific for me <jelly@srk.fer.hr> ***/
646 static const char main_key_HR_jelly[MAIN_LEN][4] =
647 {
648  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
649  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{¹©","]}ðÐ",
650  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:èÈ","'\"æÆ","\\|¾®",
651  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
652  "<>|"
653 };
654
655 /*** Croatian keyboard layout (setxkbmap hr) ***/
656 static const char main_key_HR[MAIN_LEN][4] =
657 {
658  "¸¨","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","+*",
659  "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","¹©","ðÐ",
660  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","èÈ","æÆ","¾®",
661  "yY","xX","cC","vV","bB","nN","mM",",;",".:","/?",
662  "<>"
663 };
664
665 /*** Japanese 106 keyboard layout ***/
666 static const char main_key_JA_jp106[MAIN_LEN][4] =
667 {
668  "1!","2\"","3#","4$","5%","6&","7'","8(","9)","0~","-=","^~","\\|",
669  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","@`","[{",
670  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";+",":*","]}",
671  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
672  "\\_",
673 };
674
675 /*** Japanese pc98x1 keyboard layout ***/
676 static const char main_key_JA_pc98x1[MAIN_LEN][4] =
677 {
678  "1!","2\"","3#","4$","5%","6&","7'","8(","9)","0","-=","^`","\\|",
679  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","@~","[{",
680  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";+",":*","]}",
681  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
682  "\\_",
683 };
684
685 /*** Brazilian ABNT-2 keyboard layout (contributed by Raul Gomes Fernandes) */
686 static const char main_key_PT_br[MAIN_LEN][4] =
687 {
688  "'\"","1!","2@","3#","4$","5%","6¨","7&","8*","9(","0)","-_","=+",
689  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","´`","[{",
690  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","çÇ","~^","]}",
691  "\\|","zZ","xX","cC","vV","bB","nN","mM",",<",".>",";:","/?",
692 };
693
694 /*** Brazilian ABNT-2 keyboard layout with <ALT GR> (contributed by Mauro Carvalho Chehab) */
695 static const char main_key_PT_br_alt_gr[MAIN_LEN][4] =
696 {
697  "'\"","1!9","2@2","3#3","4$#","5%\"","6(,","7&","8*","9(","0)","-_","=+'",
698  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","4`","[{*",
699  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","gG","~^","]}:",
700  "\\|","zZ","xX","cC","vV","bB","nN","mM",",<",".>",";:","/?0"
701 };
702
703 /*** US international keyboard layout (contributed by Gustavo Noronha (kov@debian.org)) */
704 static const char main_key_US_intl[MAIN_LEN][4] =
705 {
706   "`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+", "\\|",
707   "qQ", "wW", "eE", "rR", "tT", "yY", "uU", "iI", "oO", "pP", "[{", "]}",
708   "aA", "sS", "dD", "fF", "gG", "hH", "jJ", "kK", "lL", ";:", "'\"",
709   "zZ", "xX", "cC", "vV", "bB", "nN", "mM", ",<", ".>", "/?"
710 };
711
712 /*** Slovak keyboard layout (see cssk_ibm(sk_qwerty) in xkbsel)
713   - dead_abovering replaced with degree - no symbol in iso8859-2
714   - brokenbar replaced with bar                                 */
715 static const char main_key_SK[MAIN_LEN][4] =
716 {
717  ";0","+1","µ2","¹3","è4","»5","¾6","ý7","á8","í9","é0","=%","'v",
718  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","ú/","ä(",
719  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ô\"","§!","ò)",
720  "zZ","xX","cC","vV","bB","nN","mM",",?",".:","-_",
721  "<>"
722 };
723
724 /*** Czech keyboard layout (setxkbmap cz) */
725 static const char main_key_CZ[MAIN_LEN][4] =
726 {
727  ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0","=%","´·",
728  "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","ú/",")(",
729  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ù\"","§!","¨'",
730  "yY","xX","cC","vV","bB","nN","mM",",?",".:","-_",
731  "\\"
732 };
733
734 /*** Czech keyboard layout (setxkbmap cz_qwerty) */
735 static const char main_key_CZ_qwerty[MAIN_LEN][4] =
736 {
737  ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0","=%","´·",
738  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","ú/",")(",
739  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ù\"","§!","¨'",
740  "zZ","xX","cC","vV","bB","nN","mM",",?",".:","-_",
741  "\\"
742 };
743
744 /*** Slovak and Czech (programmer's) keyboard layout (see cssk_dual(cs_sk_ucw)) */
745 static const char main_key_SK_prog[MAIN_LEN][4] =
746 {
747  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
748  "qQäÄ","wWìÌ","eEéÉ","rRøØ","tT»«","yYýÝ","uUùÙ","iIíÍ","oOóÓ","pPöÖ","[{","]}",
749  "aAáÁ","sS¹©","dDïÏ","fFëË","gGàÀ","hHúÚ","jJüÜ","kKôÔ","lLµ¥",";:","'\"","\\|",
750  "zZ¾®","xX¤","cCèÈ","vVçÇ","bB","nNòÒ","mMåÅ",",<",".>","/?",
751  "<>"
752 };
753
754 /*** Czech keyboard layout (see cssk_ibm(cs_qwerty) in xkbsel) */
755 static const char main_key_CS[MAIN_LEN][4] =
756 {
757  ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0½)","=%","",
758  "qQ\\","wW|","eE","rR","tT","yY","uU","iI","oO","pP","ú/[{",")(]}",
759  "aA","sSð","dDÐ","fF[","gG]","hH","jJ","kK³","lL£","ù\"$","§!ß","¨'",
760  "zZ>","xX#","cC&","vV@","bB{","nN}","mM",",?<",".:>","-_*",
761  "<>\\|"
762 };
763
764 /*** Latin American keyboard layout (contributed by Gabriel Orlando Garcia) */
765 static const char main_key_LA[MAIN_LEN][4] =
766 {
767  "|°","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","¿¡",
768  "qQ@","wW","eE","rR","tT","yY","uU","iI","oO","pP","´¨","+*",
769  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ñÑ","{[^","}]",
770  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
771  "<>"
772 };
773
774 /*** Lithuanian (Baltic) keyboard layout (pc/lt in XFree86 4.3.0, contributed by Nerijus Baliûnas) */
775 static const char main_key_LT_B[MAIN_LEN][4] =
776 {
777  "`~","àÀ","èÈ","æÆ","ëË","áÁ","ðÐ","øØ","ûÛ","¥(","´)","-_","þÞ","\\|",
778  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
779  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"",
780  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?"
781 };
782
783 /*** Turkish keyboard Layout */
784 static const char main_key_TK[MAIN_LEN][4] =
785 {
786 "\"é","1!","2'","3^#","4+$","5%","6&","7/{","8([","9)]","0=}","*?\\","-_",
787 "qQ@","wW","eE","rR","tT","yY","uU","ýIî","oO","pP","ðÐ","üÜ~",
788 "aAæ","sSß","dD","fF","gG","hH","jJ","kK","lL","þÞ","iÝ",",;`",
789 "zZ","xX","cC","vV","bB","nN","mM","öÖ","çÇ",".:"
790 };
791
792 /*** Turkish keyboard layout (setxkbmap tr) */
793 static const char main_key_TR[MAIN_LEN][4] =
794 {
795 "\"\\","1!","2'","3^","4+","5%","6&","7/","8(","9)","0=","*?","-_",
796 "qQ","wW","eE","rR","tT","yY","uU","\xb9I","oO","pP","\xbb\xab","üÜ",
797 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","\xba\xaa","i\0",",;",
798 "zZ","xX","cC","vV","bB","nN","mM","öÖ","çÇ",".:",
799 "<>"
800 };
801
802 /*** Turkish F keyboard layout (setxkbmap trf) */
803 static const char main_key_TR_F[MAIN_LEN][4] =
804 {
805 "+*","1!","2\"","3^#","4$","5%","6&","7'","8(","9)","0=","/?","-_",
806 "fF","gG","\xbb\xab","\xb9I","oO","dD","rR","nN","hH","pP","qQ","wW",
807 "uU","i\0","eE","aA","üÜ","tT","kK","mM","lL","yY","\xba\xaa","xX",
808 "jJ","öÖ","vV","cC","çÇ","zZ","sS","bB",".:",",;",
809 "<>"
810 };
811
812 /*** Israelian keyboard layout (setxkbmap us,il) */
813 static const char main_key_IL[MAIN_LEN][4] =
814 {
815  "`~;","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
816  "qQ/","wW'","eE÷","rRø","tTà","yYè","uUå","iIï","oOí","pPô","[{","]}",
817  "aAù","sSã","dDâ","fFë","gGò","hHé","jJç","kKì","lLê",";:ó","\'\",","\\|",
818  "zZæ","xXñ","cCá","vVä","bBð","nNî","mMö",",<ú",".>õ","/?.",
819  "<>"
820 };
821
822 /*** Israelian phonetic keyboard layout (setxkbmap us,il_phonetic) */
823 static const char main_key_IL_phonetic[MAIN_LEN][4] =
824 {
825  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
826  "qQ÷","wWå","eEà","rRø","tTú","yYò","uUå","iIé","oOñ","pPô","[{","]}",
827  "aAà","sSù","dDã","fFô","gGâ","hHä","jJé","kKë","lLì",";:","'\"","\\|",
828  "zZæ","xXç","cCö","vVå","bBá","nNð","mMî",",<",".>","/?",
829  "<>"
830 };
831
832 /*** Israelian Saharon keyboard layout (setxkbmap -symbols "us(pc105)+il_saharon") */
833 static const char main_key_IL_saharon[MAIN_LEN][4] =
834 {
835  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
836  "qQ÷","wWñ","eE","rRø","tTè","yYã","uU","iI","oO","pPô","[{","]}",
837  "aAà","sSå","dDì","fFú","gGâ","hHä","jJù","kKë","lLé",";:","'\"","\\|",
838  "zZæ","xXç","cCö","vVò","bBá","nNð","mMî",",<",".>","/?",
839  "<>"
840 };
841
842 /*** Greek keyboard layout (contributed by Kriton Kyrimis <kyrimis@cti.gr>)
843   Greek characters for "wW" and "sS" are omitted to not produce a mismatch
844   message since they have different characters in gr and el XFree86 layouts. */
845 static const char main_key_EL[MAIN_LEN][4] =
846 {
847  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
848  "qQ;:","wW","eEåÅ","rRñÑ","tTôÔ","yYõÕ","uUèÈ","iIéÉ","oOïÏ","pPðÐ","[{","]}",
849  "aAáÁ","sS","dDäÄ","fFöÖ","gGãÃ","hHçÇ","jJîÎ","kKêÊ","lLëË",";:´¨","'\"","\\|",
850  "zZæÆ","xX÷×","cCøØ","vVùÙ","bBâÂ","nNíÍ","mMìÌ",",<",".>","/?",
851  "<>"
852 };
853
854 /*** Thai (Kedmanee) keyboard layout by Supphachoke Suntiwichaya <mrchoke@opentle.org> */
855 static const char main_key_th[MAIN_LEN][4] =
856 {
857  "`~_%","1!å+","2@/ñ","3#-ò","4$Àó","5%¶ô","6^ØÙ","7&Öß","8*¤õ","9(µö","0)¨÷","-_¢ø","=+ªù",
858  "qQæð","wWä\"","eEÓ®","rR¾±","tTи","yYÑí","uUÕê","iIó","oO¹Ï","pP­","[{º°","]}Å,",
859  "aA¿Ä","sS˦","dD¡¯","fF´â","gGà¬","hHéç","jJèë","kKÒÉ","lLÊÈ",";:Ç«","\'\"§.","\\|£¥",
860  "zZ¼(","xX»)","cCá©","vVÍÎ","bBÚ","nN×ì","mM·?",",<Á²",".>ãÌ","/?½Æ"
861 }; 
862
863 /*** VNC keyboard layout */
864 static const WORD main_key_scan_vnc[MAIN_LEN] =
865 {
866    0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x1A,0x1B,0x27,0x28,0x29,0x33,0x34,0x35,0x2B,
867    0x1E,0x30,0x2E,0x20,0x12,0x21,0x22,0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18,0x19,0x10,0x13,0x1F,0x14,0x16,0x2F,0x11,0x2D,0x15,0x2C,
868    0x56
869 };
870
871 static const WORD main_key_vkey_vnc[MAIN_LEN] =
872 {
873    '1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS,VK_OEM_PLUS,VK_OEM_4,VK_OEM_6,VK_OEM_1,VK_OEM_7,VK_OEM_3,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,VK_OEM_5,
874    'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
875    VK_OEM_102
876 };
877
878 static const char main_key_vnc[MAIN_LEN][4] =
879 {
880  "1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+","[{","]}",";:","'\"","`~",",<",".>","/?","\\|",
881  "aA","bB","cC","dD","eE","fF","gG","hH","iI","jJ","kK","lL","mM","nN","oO","pP","qQ","rR","sS","tT","uU","vV","wW","xX","yY","zZ"
882 };
883
884 /*** Dutch keyboard layout (setxkbmap nl) ***/
885 static const char main_key_NL[MAIN_LEN][4] =
886 {
887  "@§","1!","2\"","3#","4$","5%","6&","7_","8(","9)","0'","/?","°~",
888  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","¨~","*|",
889  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","+±","'`","<>",
890  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-=",
891  "[]"
892 };
893
894
895
896 /*** Layout table. Add your keyboard mappings to this list */
897 static const struct {
898     LCID lcid; /* input locale identifier, look for LOCALE_ILANGUAGE
899                  in the appropriate dlls/kernel/nls/.nls file */
900     const char *comment;
901     const char (*key)[MAIN_LEN][4];
902     const WORD (*scan)[MAIN_LEN]; /* scan codes mapping */
903     const WORD (*vkey)[MAIN_LEN]; /* virtual key codes mapping */
904 } main_key_tab[]={
905  {0x0409, "United States keyboard layout", &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty},
906  {0x0409, "United States keyboard layout (phantom key version)", &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
907  {0x0409, "United States keyboard layout (dvorak)", &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak},
908  {0x0409, "United States International keyboard layout", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
909  {0x0809, "British keyboard layout", &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
910  {0x0407, "German keyboard layout", &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwertz},
911  {0x0407, "German keyboard layout without dead keys", &main_key_DE_nodead, &main_key_scan_qwerty, &main_key_vkey_qwertz},
912  {0x0407, "German keyboard layout for logitech desktop pro", &main_key_DE_logitech,  &main_key_scan_qwerty, &main_key_vkey_qwertz},
913  {0x0407, "German keyboard layout without dead keys 105", &main_key_DE_nodead_105, &main_key_scan_qwerty, &main_key_vkey_qwertz_105},
914  {0x0807, "Swiss German keyboard layout", &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwertz},
915  {0x100c, "Swiss French keyboard layout", &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwertz},
916  {0x041d, "Swedish keyboard layout", &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty_v2},
917  {0x0425, "Estonian keyboard layout", &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty},
918  {0x0414, "Norwegian keyboard layout", &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty},
919  {0x0406, "Danish keyboard layout", &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
920  {0x040c, "French keyboard layout", &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty},
921  {0x0c0c, "Canadian French keyboard layout", &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
922  {0x0c0c, "Canadian French keyboard layout (CA_fr)", &main_key_CA_fr, &main_key_scan_qwerty, &main_key_vkey_qwerty},
923  {0x0c0c, "Canadian keyboard layout", &main_key_CA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
924  {0x080c, "Belgian keyboard layout", &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty},
925  {0x0816, "Portuguese keyboard layout", &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
926  {0x0416, "Brazilian ABNT-2 keyboard layout", &main_key_PT_br, &main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
927  {0x0416, "Brazilian ABNT-2 keyboard layout ALT GR", &main_key_PT_br_alt_gr,&main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
928  {0x040b, "Finnish keyboard layout", &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
929  {0x0402, "Bulgarian bds keyboard layout", &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty},
930  {0x0402, "Bulgarian phonetic keyboard layout", &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
931  {0x0423, "Belarusian keyboard layout", &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty},
932  {0x0419, "Russian keyboard layout", &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
933  {0x0419, "Russian keyboard layout (phantom key version)", &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
934  {0x0419, "Russian keyboard layout KOI8-R", &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty},
935  {0x0419, "Russian keyboard layout cp1251", &main_key_RU_cp1251, &main_key_scan_qwerty, &main_key_vkey_qwerty},
936  {0x0419, "Russian phonetic keyboard layout", &main_key_RU_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
937  {0x0422, "Ukrainian keyboard layout KOI8-U", &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
938  {0x0422, "Ukrainian keyboard layout (standard)", &main_key_UA_std, &main_key_scan_qwerty, &main_key_vkey_qwerty},
939  {0x0419, "Russian keyboard layout (standard)", &main_key_RU_std, &main_key_scan_qwerty, &main_key_vkey_qwerty},
940  {0x040a, "Spanish keyboard layout", &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty},
941  {0x0410, "Italian keyboard layout", &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
942  {0x040f, "Icelandic keyboard layout", &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
943  {0x040e, "Hungarian keyboard layout", &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwertz},
944  {0x0415, "Polish (programmer's) keyboard layout", &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
945  {0x0424, "Slovenian keyboard layout", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwertz},
946  {0x0c1a, "Serbian keyboard layout sr", &main_key_SR, &main_key_scan_qwerty, &main_key_vkey_qwerty}, /* LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC */
947  {0x0c1a, "Serbian keyboard layout us,sr", &main_key_US_SR, &main_key_scan_qwerty, &main_key_vkey_qwerty}, /* LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC */
948  {0x041a, "Croatian keyboard layout", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwertz},
949  {0x041a, "Croatian keyboard layout (specific)", &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
950  {0x0411, "Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty_jp106, &main_key_vkey_qwerty_jp106},
951  {0x0411, "Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
952  {0x041b, "Slovak keyboard layout", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
953  {0x041b, "Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
954  {0x0405, "Czech keyboard layout", &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
955  {0x0405, "Czech keyboard layout cz", &main_key_CZ, &main_key_scan_qwerty, &main_key_vkey_qwertz},
956  {0x0405, "Czech keyboard layout cz_qwerty", &main_key_CZ_qwerty, &main_key_scan_qwerty, &main_key_vkey_qwerty},
957  {0x040a, "Latin American keyboard layout", &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
958  {0x0427, "Lithuanian (Baltic) keyboard layout", &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty},
959  {0x041f, "Turkish keyboard layout", &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
960  {0x041f, "Turkish keyboard layout tr", &main_key_TR, &main_key_scan_qwerty, &main_key_vkey_qwerty},
961  {0x041f, "Turkish keyboard layout trf", &main_key_TR_F, &main_key_scan_qwerty, &main_key_vkey_qwerty},
962  {0x040d, "Israelian keyboard layout", &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
963  {0x040d, "Israelian phonetic keyboard layout", &main_key_IL_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
964  {0x040d, "Israelian Saharon keyboard layout", &main_key_IL_saharon, &main_key_scan_qwerty, &main_key_vkey_qwerty},
965  {0x0409, "VNC keyboard layout", &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc},
966  {0x0408, "Greek keyboard layout", &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
967  {0x041e, "Thai (Kedmanee)  keyboard layout", &main_key_th, &main_key_scan_qwerty, &main_key_vkey_qwerty},
968  {0x0413, "Dutch keyboard layout", &main_key_NL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
969
970  {0, NULL, NULL, NULL, NULL} /* sentinel */
971 };
972 static unsigned kbd_layout=0; /* index into above table of layouts */
973
974 /* maybe more of these scancodes should be extended? */
975                 /* extended must be set for ALT_R, CTRL_R,
976                    INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
977                    keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
978                 /* FIXME should we set extended bit for NumLock ? My
979                  * Windows does ... DF */
980                 /* Yes, to distinguish based on scan codes, also
981                    for PrtScn key ... GA */
982
983 static const WORD nonchar_key_vkey[256] =
984 {
985     /* unused */
986     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF00 */
987     /* special keys */
988     VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
989     0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
990     0, 0, 0, VK_ESCAPE, 0, 0, 0, 0,                             /* FF18 */
991     /* unused */
992     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF20 */
993     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF28 */
994     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF30 */
995     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF38 */
996     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF40 */
997     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF48 */
998     /* cursor keys */
999     VK_HOME, VK_LEFT, VK_UP, VK_RIGHT,                          /* FF50 */
1000     VK_DOWN, VK_PRIOR, VK_NEXT, VK_END,
1001     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF58 */
1002     /* misc keys */
1003     VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
1004     VK_CANCEL, VK_HELP, VK_CANCEL, VK_CANCEL, 0, 0, 0, 0,       /* FF68 */
1005     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF70 */
1006     /* keypad keys */
1007     0, 0, 0, 0, 0, 0, 0, VK_NUMLOCK,                            /* FF78 */
1008     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
1009     0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
1010     0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP,                     /* FF90 */
1011     VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT,                       /* FF98 */
1012     VK_END, VK_CLEAR, VK_INSERT, VK_DELETE,
1013     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
1014     0, 0, VK_MULTIPLY, VK_ADD,                                  /* FFA8 */
1015     VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE,
1016     VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,             /* FFB0 */
1017     VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
1018     VK_NUMPAD8, VK_NUMPAD9, 0, 0, 0, 0,                         /* FFB8 */
1019     /* function keys */
1020     VK_F1, VK_F2,
1021     VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
1022     VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, 0, 0,       /* FFC8 */
1023     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFD0 */
1024     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFD8 */
1025     /* modifier keys */
1026     0, VK_SHIFT, VK_SHIFT, VK_CONTROL,                          /* FFE0 */
1027     VK_CONTROL, VK_CAPITAL, 0, VK_MENU,
1028     VK_MENU, VK_MENU, VK_MENU, 0, 0, 0, 0, 0,                   /* FFE8 */
1029     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFF0 */
1030     0, 0, 0, 0, 0, 0, 0, VK_DELETE                              /* FFF8 */
1031 };
1032
1033 static const WORD nonchar_key_scan[256] =
1034 {
1035     /* unused */
1036     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF00 */
1037     /* special keys */
1038     0x0E, 0x0F, 0x00, /*?*/ 0, 0x00, 0x1C, 0x00, 0x00,           /* FF08 */
1039     0x00, 0x00, 0x00, 0x45, 0x46, 0x00, 0x00, 0x00,              /* FF10 */
1040     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,              /* FF18 */
1041     /* unused */
1042     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF20 */
1043     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF28 */
1044     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF30 */
1045     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF38 */
1046     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF40 */
1047     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF48 */
1048     /* cursor keys */
1049     0x147, 0x14B, 0x148, 0x14D, 0x150, 0x149, 0x151, 0x14F,      /* FF50 */
1050     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF58 */
1051     /* misc keys */
1052     /*?*/ 0, 0x137, /*?*/ 0, 0x152, 0x00, 0x00, 0x00, 0x00,      /* FF60 */
1053     /*?*/ 0, /*?*/ 0, 0x38, 0x146, 0x00, 0x00, 0x00, 0x00,       /* FF68 */
1054     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF70 */
1055     /* keypad keys */
1056     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x138, 0x145,            /* FF78 */
1057     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF80 */
1058     0x00, 0x00, 0x00, 0x00, 0x00, 0x11C, 0x00, 0x00,             /* FF88 */
1059     0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4B, 0x48,              /* FF90 */
1060     0x4D, 0x50, 0x49, 0x51, 0x4F, 0x4C, 0x52, 0x53,              /* FF98 */
1061     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFA0 */
1062     0x00, 0x00, 0x37, 0x4E, 0x53, 0x4A, 0x53, 0x135,             /* FFA8 */
1063     0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47,              /* FFB0 */
1064     0x48, 0x49, 0x00, 0x00, 0x00, 0x00,                          /* FFB8 */
1065     /* function keys */
1066     0x3B, 0x3C,
1067     0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44,              /* FFC0 */
1068     0x57, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFC8 */
1069     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFD0 */
1070     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFD8 */
1071     /* modifier keys */
1072     0x00, 0x2A, 0x36, 0x1D, 0x11D, 0x3A, 0x00, 0x38,             /* FFE0 */
1073     0x138, 0x38, 0x138, 0x00, 0x00, 0x00, 0x00, 0x00,            /* FFE8 */
1074     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFF0 */
1075     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x153              /* FFF8 */
1076 };
1077
1078
1079 /* Returns the Windows virtual key code associated with the X event <e> */
1080 /* x11 lock must be held */
1081 static WORD EVENT_event_to_vkey( XIC xic, XKeyEvent *e)
1082 {
1083     KeySym keysym = 0;
1084     Status status;
1085     char buf[24];
1086
1087     if (xic)
1088         XmbLookupString(xic, e, buf, sizeof(buf), &keysym, &status);
1089     else
1090         XLookupString(e, buf, sizeof(buf), &keysym, NULL);
1091
1092     if ((e->state & NumLockMask) &&
1093         (keysym == XK_KP_Separator || keysym == XK_KP_Decimal ||
1094          (keysym >= XK_KP_0 && keysym <= XK_KP_9)))
1095         /* Only the Keypad keys 0-9 and . send different keysyms
1096          * depending on the NumLock state */
1097         return nonchar_key_vkey[keysym & 0xFF];
1098
1099     TRACE_(key)("e->keycode = %x\n", e->keycode);
1100
1101     return keyc2vkey[e->keycode];
1102 }
1103
1104 static BOOL NumState=FALSE, CapsState=FALSE;
1105
1106
1107 /***********************************************************************
1108  *           X11DRV_send_keyboard_input
1109  */
1110 void X11DRV_send_keyboard_input( WORD wVk, WORD wScan, DWORD dwFlags, DWORD time,
1111                                  DWORD dwExtraInfo, UINT injected_flags )
1112 {
1113     UINT message;
1114     KEYLP keylp;
1115     KBDLLHOOKSTRUCT hook;
1116     WORD wVkStripped;
1117
1118     /* strip left/right for menu, control, shift */
1119     if (wVk == VK_LMENU || wVk == VK_RMENU)
1120         wVkStripped = VK_MENU;
1121     else if (wVk == VK_LCONTROL || wVk == VK_RCONTROL)
1122         wVkStripped = VK_CONTROL;
1123     else if (wVk == VK_LSHIFT || wVk == VK_RSHIFT)
1124         wVkStripped = VK_SHIFT;
1125     else
1126         wVkStripped = wVk;
1127
1128     keylp.lp2 = 0;
1129     keylp.lp1.count = 1;
1130     keylp.lp1.code = wScan;
1131     keylp.lp1.extended = (dwFlags & KEYEVENTF_EXTENDEDKEY) != 0;
1132     keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
1133                                 * don't remember where I read it - AK */
1134                                 /* it's '1' under windows, when a dialog box appears
1135                                  * and you press one of the underlined keys - DF*/
1136
1137     /* note that there is a test for all this */
1138     if (dwFlags & KEYEVENTF_KEYUP )
1139     {
1140         message = WM_KEYUP;
1141         if ((key_state_table[VK_MENU] & 0x80) &&
1142             ((wVkStripped == VK_MENU) || (wVkStripped == VK_CONTROL)
1143              || !(key_state_table[VK_CONTROL] & 0x80)))
1144         {
1145             if( TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */
1146                 (wVkStripped != VK_MENU)) /* <ALT>-down...<something else>-up */
1147                 message = WM_SYSKEYUP;
1148             TrackSysKey = 0;
1149         }
1150         key_state_table[wVk] &= ~0x80;
1151         key_state_table[wVkStripped] &= ~0x80;
1152         keylp.lp1.previous = 1;
1153         keylp.lp1.transition = 1;
1154     }
1155     else
1156     {
1157         keylp.lp1.previous = (key_state_table[wVk] & 0x80) != 0;
1158         keylp.lp1.transition = 0;
1159         if (!(key_state_table[wVk] & 0x80)) key_state_table[wVk] ^= 0x01;
1160         key_state_table[wVk] |= 0xc0;
1161         key_state_table[wVkStripped] |= 0xc0;
1162
1163         message = WM_KEYDOWN;
1164         if ((key_state_table[VK_MENU] & 0x80) && !(key_state_table[VK_CONTROL] & 0x80))
1165         {
1166             message = WM_SYSKEYDOWN;
1167             TrackSysKey = wVkStripped;
1168         }
1169     }
1170
1171     keylp.lp1.context = (key_state_table[VK_MENU] & 0x80) != 0; /* 1 if alt */
1172
1173     TRACE_(key)(" wParam=%04x, lParam=%08lx, InputKeyState=%x\n",
1174                 wVk, keylp.lp2, key_state_table[wVk] );
1175
1176     hook.vkCode      = wVk;
1177     hook.scanCode    = wScan;
1178     hook.flags       = (keylp.lp2 >> 24) | injected_flags;
1179     hook.time        = time;
1180     hook.dwExtraInfo = dwExtraInfo;
1181     if (HOOK_CallHooks( WH_KEYBOARD_LL, HC_ACTION, message, (LPARAM)&hook, TRUE )) return;
1182
1183     SERVER_START_REQ( send_message )
1184     {
1185         req->id       = (injected_flags & LLKHF_INJECTED) ? 0 : GetCurrentThreadId();
1186         req->type     = MSG_HARDWARE;
1187         req->flags    = 0;
1188         req->win      = 0;
1189         req->msg      = message;
1190         req->wparam   = wVk;
1191         req->lparam   = keylp.lp2;
1192         req->x        = cursor_pos.x;
1193         req->y        = cursor_pos.y;
1194         req->time     = time;
1195         req->info     = dwExtraInfo;
1196         req->timeout  = -1;
1197         req->callback = NULL;
1198         wine_server_call( req );
1199     }
1200     SERVER_END_REQ;
1201 }
1202
1203
1204 /**********************************************************************
1205  *              KEYBOARD_GenerateMsg
1206  *
1207  * Generate Down+Up messages when NumLock or CapsLock is pressed.
1208  *
1209  * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
1210  *
1211  */
1212 static void KEYBOARD_GenerateMsg( WORD vkey, WORD scan, int Evtype, DWORD event_time )
1213 {
1214   BOOL * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
1215   DWORD up, down;
1216
1217   if (*State) {
1218     /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
1219        don't treat it. It's from the same key press. Then the state goes to ON.
1220        And from there, a 'release' event will switch off the toggle key. */
1221     *State=FALSE;
1222     TRACE("INTERM : don't treat release of toggle key. key_state_table[%#x] = %#x\n",
1223           vkey,key_state_table[vkey]);
1224   } else
1225     {
1226         down = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0);
1227         up = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0) | KEYEVENTF_KEYUP;
1228         if ( key_state_table[vkey] & 0x1 ) /* it was ON */
1229           {
1230             if (Evtype!=KeyPress)
1231               {
1232                 TRACE("ON + KeyRelease => generating DOWN and UP messages.\n");
1233                 X11DRV_send_keyboard_input( vkey, scan, down, event_time, 0, 0 );
1234                 X11DRV_send_keyboard_input( vkey, scan, up, event_time, 0, 0 );
1235                 *State=FALSE;
1236                 key_state_table[vkey] &= ~0x01; /* Toggle state to off. */
1237               }
1238           }
1239         else /* it was OFF */
1240           if (Evtype==KeyPress)
1241             {
1242               TRACE("OFF + Keypress => generating DOWN and UP messages.\n");
1243               X11DRV_send_keyboard_input( vkey, scan, down, event_time, 0, 0 );
1244               X11DRV_send_keyboard_input( vkey, scan, up, event_time, 0, 0 );
1245               *State=TRUE; /* Goes to intermediary state before going to ON */
1246               key_state_table[vkey] |= 0x01; /* Toggle state to on. */
1247             }
1248     }
1249 }
1250
1251 /***********************************************************************
1252  *           KEYBOARD_UpdateOneState
1253  *
1254  * Updates internal state for <vkey>, depending on key <state> under X
1255  *
1256  */
1257 inline static void KEYBOARD_UpdateOneState ( int vkey, int state, DWORD time )
1258 {
1259     /* Do something if internal table state != X state for keycode */
1260     if (((key_state_table[vkey] & 0x80)!=0) != state)
1261     {
1262         TRACE("Adjusting state for vkey %#.2x. State before %#.2x\n",
1263               vkey, key_state_table[vkey]);
1264
1265         /* Fake key being pressed inside wine */
1266         X11DRV_send_keyboard_input( vkey, 0, state? 0 : KEYEVENTF_KEYUP, time, 0, 0 );
1267
1268         TRACE("State after %#.2x\n",key_state_table[vkey]);
1269     }
1270 }
1271
1272 /***********************************************************************
1273  *           X11DRV_KeymapNotify
1274  *
1275  * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
1276  *
1277  * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
1278  * from wine to another application and back.
1279  * Toggle keys are handled in HandleEvent.
1280  */
1281 void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
1282 {
1283     int i, j, alt, control, shift;
1284     DWORD time = GetCurrentTime();
1285
1286     alt = control = shift = 0;
1287     for (i = 0; i < 32; i++)
1288     {
1289         if (!event->xkeymap.key_vector[i]) continue;
1290         for (j = 0; j < 8; j++)
1291         {
1292             if (!(event->xkeymap.key_vector[i] & (1<<j))) continue;
1293             switch(keyc2vkey[(i * 8) + j] & 0xff)
1294             {
1295             case VK_MENU:    alt = 1; break;
1296             case VK_CONTROL: control = 1; break;
1297             case VK_SHIFT:   shift = 1; break;
1298             }
1299         }
1300     }
1301     KEYBOARD_UpdateOneState( VK_MENU, alt, time );
1302     KEYBOARD_UpdateOneState( VK_CONTROL, control, time );
1303     KEYBOARD_UpdateOneState( VK_SHIFT, shift, time );
1304 }
1305
1306 /***********************************************************************
1307  *           X11DRV_KeyEvent
1308  *
1309  * Handle a X key event
1310  */
1311 void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
1312 {
1313     XKeyEvent *event = &xev->xkey;
1314     char Str[24];
1315     KeySym keysym = 0;
1316     WORD vkey = 0, bScan;
1317     DWORD dwFlags;
1318     int ascii_chars;
1319     XIC xic = X11DRV_get_ic( hwnd );
1320     DWORD event_time = EVENT_x11_time_to_win32_time(event->time);
1321     Status status = 0;
1322
1323     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
1324                 event->type, event->window, event->state, event->keycode);
1325
1326     wine_tsx11_lock();
1327     if (xic)
1328         ascii_chars = XmbLookupString(xic, event, Str, sizeof(Str), &keysym, &status);
1329     else
1330         ascii_chars = XLookupString(event, Str, sizeof(Str), &keysym, NULL);
1331     wine_tsx11_unlock();
1332
1333     /* Ignore some unwanted events */
1334     if ((keysym >= XK_ISO_Lock && keysym <= XK_ISO_Last_Group_Lock) ||
1335          keysym == XK_Mode_switch)
1336     {
1337         wine_tsx11_lock();
1338         TRACE("Ignoring %s keyboard event\n", XKeysymToString(keysym));
1339         wine_tsx11_unlock();
1340         return;
1341     }
1342
1343     TRACE_(key)("state = %X nbyte = %d, status 0x%x\n", event->state, ascii_chars, status);
1344
1345     if (status == XBufferOverflow)
1346         ERR("Buffer Overflow need %i!\n",ascii_chars);
1347
1348     if (status == XLookupChars)
1349     {
1350         X11DRV_XIMLookupChars( Str, ascii_chars );
1351         return;
1352     }
1353
1354     /* If XKB extensions are used, the state mask for AltGr will use the group
1355        index instead of the modifier mask. The group index is set in bits
1356        13-14 of the state field in the XKeyEvent structure. So if AltGr is
1357        pressed, look if the group index is different than 0. From XKB
1358        extension documentation, the group index for AltGr should be 2
1359        (event->state = 0x2000). It's probably better to not assume a
1360        predefined group index and find it dynamically
1361
1362        Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
1363     /* Save also all possible modifier states. */
1364     AltGrMask = event->state & (0x6000 | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
1365
1366     Str[ascii_chars] = '\0';
1367     if (TRACE_ON(key)){
1368         char    *ksname;
1369
1370         wine_tsx11_lock();
1371         ksname = XKeysymToString(keysym);
1372         wine_tsx11_unlock();
1373         if (!ksname)
1374           ksname = "No Name";
1375         TRACE_(key)("%s : keysym=%lX (%s), # of chars=%d / 0x%02x / '%s'\n",
1376                     (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
1377                     keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
1378     }
1379
1380     wine_tsx11_lock();
1381     vkey = EVENT_event_to_vkey(xic,event);
1382     /* X returns keycode 0 for composed characters */
1383     if (!vkey && ascii_chars) vkey = VK_NONAME;
1384     wine_tsx11_unlock();
1385
1386     TRACE_(key)("keycode 0x%x converted to vkey 0x%x\n",
1387                 event->keycode, vkey);
1388
1389    if (vkey)
1390    {
1391     switch (vkey & 0xff)
1392     {
1393     case VK_NUMLOCK:
1394       KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, event->type, event_time );
1395       break;
1396     case VK_CAPITAL:
1397       TRACE("Caps Lock event. (type %d). State before : %#.2x\n",event->type,key_state_table[vkey]);
1398       KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, event->type, event_time );
1399       TRACE("State after : %#.2x\n",key_state_table[vkey]);
1400       break;
1401     default:
1402         /* Adjust the NUMLOCK state if it has been changed outside wine */
1403         if (!(key_state_table[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
1404           {
1405             TRACE("Adjusting NumLock state.\n");
1406             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyPress, event_time );
1407             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyRelease, event_time );
1408           }
1409         /* Adjust the CAPSLOCK state if it has been changed outside wine */
1410         if (!(key_state_table[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
1411           {
1412               TRACE("Adjusting Caps Lock state.\n");
1413             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyPress, event_time );
1414             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyRelease, event_time );
1415           }
1416         /* Not Num nor Caps : end of intermediary states for both. */
1417         NumState = FALSE;
1418         CapsState = FALSE;
1419
1420         bScan = keyc2scan[event->keycode] & 0xFF;
1421         TRACE_(key)("bScan = 0x%02x.\n", bScan);
1422
1423         dwFlags = 0;
1424         if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
1425         if ( vkey & 0x100 )              dwFlags |= KEYEVENTF_EXTENDEDKEY;
1426
1427         X11DRV_send_keyboard_input( vkey & 0xff, bScan, dwFlags, event_time, 0, 0 );
1428     }
1429    }
1430 }
1431
1432 /**********************************************************************
1433  *              X11DRV_KEYBOARD_DetectLayout
1434  *
1435  * Called from X11DRV_InitKeyboard
1436  *  This routine walks through the defined keyboard layouts and selects
1437  *  whichever matches most closely.
1438  * X11 lock must be held.
1439  */
1440 static void
1441 X11DRV_KEYBOARD_DetectLayout (void)
1442 {
1443   Display *display = thread_display();
1444   unsigned current, match, mismatch, seq, i, syms;
1445   int score, keyc, key, pkey, ok;
1446   KeySym keysym;
1447   const char (*lkey)[MAIN_LEN][4];
1448   unsigned max_seq = 0;
1449   int max_score = 0, ismatch = 0;
1450   char ckey[4] =
1451   {0, 0, 0, 0};
1452
1453   syms = keysyms_per_keycode;
1454   if (syms > 4) {
1455     WARN("%d keysyms per keycode not supported, set to 4\n", syms);
1456     syms = 4;
1457   }
1458   for (current = 0; main_key_tab[current].comment; current++) {
1459     TRACE("Attempting to match against \"%s\"\n", main_key_tab[current].comment);
1460     match = 0;
1461     mismatch = 0;
1462     score = 0;
1463     seq = 0;
1464     lkey = main_key_tab[current].key;
1465     pkey = -1;
1466     for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1467       /* get data for keycode from X server */
1468       for (i = 0; i < syms; i++) {
1469         keysym = XKeycodeToKeysym (display, keyc, i);
1470         /* Allow both one-byte and two-byte national keysyms */
1471         if ((keysym < 0x8000) && (keysym != ' '))
1472         {
1473 #ifdef HAVE_XKB
1474             if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
1475 #endif
1476             {
1477                 TRACE("XKB could not translate keysym %ld\n", keysym);
1478                 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1479                  * with appropriate ShiftMask and Mode_switch, use XLookupString
1480                  * to get character in the local encoding.
1481                  */
1482                 ckey[i] = keysym & 0xFF;
1483             }
1484         }
1485         else {
1486           ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1487         }
1488       }
1489       if (ckey[0]) {
1490         /* search for a match in layout table */
1491         /* right now, we just find an absolute match for defined positions */
1492         /* (undefined positions are ignored, so if it's defined as "3#" in */
1493         /* the table, it's okay that the X server has "3#£", for example) */
1494         /* however, the score will be higher for longer matches */
1495         for (key = 0; key < MAIN_LEN; key++) {
1496           for (ok = 0, i = 0; (ok >= 0) && (i < syms); i++) {
1497             if ((*lkey)[key][i] && ((*lkey)[key][i] == ckey[i]))
1498               ok++;
1499             if ((*lkey)[key][i] && ((*lkey)[key][i] != ckey[i]))
1500               ok = -1;
1501           }
1502           if (ok > 0) {
1503             score += ok;
1504             break;
1505           }
1506         }
1507         /* count the matches and mismatches */
1508         if (ok > 0) {
1509           match++;
1510           /* and how much the keycode order matches */
1511           if (key > pkey) seq++;
1512           pkey = key;
1513         } else {
1514           /* print spaces instead of \0's */
1515           for (i = 0; i < sizeof(ckey); i++) if (!ckey[i]) ckey[i] = ' ';
1516           TRACE_(key)("mismatch for keysym 0x%04lX, keycode %d, got %c%c%c%c\n",
1517                       keysym, keyc, ckey[0], ckey[1], ckey[2], ckey[3]);
1518           mismatch++;
1519           score -= syms;
1520         }
1521       }
1522     }
1523     TRACE("matches=%d, mismatches=%d, seq=%d, score=%d\n",
1524            match, mismatch, seq, score);
1525     if ((score > max_score) ||
1526         ((score == max_score) && (seq > max_seq))) {
1527       /* best match so far */
1528       kbd_layout = current;
1529       max_score = score;
1530       max_seq = seq;
1531       ismatch = !mismatch;
1532     }
1533   }
1534   /* we're done, report results if necessary */
1535   if (!ismatch)
1536     WARN("Using closest match (%s) for scan/virtual codes mapping.\n",
1537         main_key_tab[kbd_layout].comment);
1538
1539   TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment);
1540 }
1541
1542 /**********************************************************************
1543  *              X11DRV_InitKeyboard
1544  */
1545 void X11DRV_InitKeyboard(void)
1546 {
1547     Display *display = thread_display();
1548     KeySym *ksp;
1549     XModifierKeymap *mmp;
1550     KeySym keysym;
1551     KeyCode *kcp;
1552     XKeyEvent e2;
1553     WORD scan, vkey, OEMvkey;
1554     int keyc, i, keyn, syms;
1555     char ckey[4]={0,0,0,0};
1556     const char (*lkey)[MAIN_LEN][4];
1557
1558     wine_tsx11_lock();
1559     XDisplayKeycodes(display, &min_keycode, &max_keycode);
1560     ksp = XGetKeyboardMapping(display, min_keycode,
1561                               max_keycode + 1 - min_keycode, &keysyms_per_keycode);
1562     /* We are only interested in keysyms_per_keycode.
1563        There is no need to hold a local copy of the keysyms table */
1564     XFree(ksp);
1565
1566     mmp = XGetModifierMapping(display);
1567     kcp = mmp->modifiermap;
1568     for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
1569     {
1570         int j;
1571
1572         for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
1573             if (*kcp)
1574             {
1575                 int k;
1576
1577                 for (k = 0; k < keysyms_per_keycode; k += 1)
1578                     if (XKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
1579                     {
1580                         NumLockMask = 1 << i;
1581                         TRACE_(key)("NumLockMask is %x\n", NumLockMask);
1582                     }
1583             }
1584     }
1585     XFreeModifiermap(mmp);
1586
1587     /* Detect the keyboard layout */
1588     X11DRV_KEYBOARD_DetectLayout();
1589     lkey = main_key_tab[kbd_layout].key;
1590     syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode;
1591
1592     /* Now build two conversion arrays :
1593      * keycode -> vkey + scancode + extended
1594      * vkey + extended -> keycode */
1595
1596     e2.display = display;
1597     e2.state = 0;
1598
1599     OEMvkey = VK_OEM_8; /* next is available.  */
1600     for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1601     {
1602         char buf[30];
1603         int have_chars;
1604
1605         keysym = 0;
1606         e2.keycode = (KeyCode)keyc;
1607         have_chars = XLookupString(&e2, buf, sizeof(buf), &keysym, NULL);
1608         vkey = 0; scan = 0;
1609         if (keysym)  /* otherwise, keycode not used */
1610         {
1611             if ((keysym >> 8) == 0xFF)         /* non-character key */
1612             {
1613                 vkey = nonchar_key_vkey[keysym & 0xff];
1614                 scan = nonchar_key_scan[keysym & 0xff];
1615                 /* set extended bit when necessary */
1616                 if (scan & 0x100) vkey |= 0x100;
1617             } else if (keysym == 0x20) {                 /* Spacebar */
1618                 vkey = VK_SPACE;
1619                 scan = 0x39;
1620             } else if (have_chars) {
1621               /* we seem to need to search the layout-dependent scancodes */
1622               int maxlen=0,maxval=-1,ok;
1623               for (i=0; i<syms; i++) {
1624                 keysym = XKeycodeToKeysym(display, keyc, i);
1625                 if ((keysym<0x8000) && (keysym!=' '))
1626                 {
1627 #ifdef HAVE_XKB
1628                     if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
1629 #endif
1630                     {
1631                         /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1632                          * with appropriate ShiftMask and Mode_switch, use XLookupString
1633                          * to get character in the local encoding.
1634                          */
1635                         ckey[i] = keysym & 0xFF;
1636                     }
1637                 } else {
1638                   ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1639                 }
1640               }
1641               /* find key with longest match streak */
1642               for (keyn=0; keyn<MAIN_LEN; keyn++) {
1643                 for (ok=(*lkey)[keyn][i=0]; ok&&(i<4); i++)
1644                   if ((*lkey)[keyn][i] && (*lkey)[keyn][i]!=ckey[i]) ok=0;
1645                 if (ok||(i>maxlen)) {
1646                   maxlen=i; maxval=keyn;
1647                 }
1648                 if (ok) break;
1649               }
1650               if (maxval>=0) {
1651                 /* got it */
1652                 const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan;
1653                 const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey;
1654                 scan = (*lscan)[maxval];
1655                 vkey = (*lvkey)[maxval];
1656               }
1657             }
1658 #if 0 /* this breaks VK_OEM_x VKeys in some layout tables by inserting
1659        * a VK code into a not appropriate place.
1660        */
1661             /* find a suitable layout-dependent VK code */
1662             /* (most Winelib apps ought to be able to work without layout tables!) */
1663             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1664             {
1665                 keysym = XLookupKeysym(&e2, i);
1666                 if ((keysym >= VK_0 && keysym <= VK_9)
1667                     || (keysym >= VK_A && keysym <= VK_Z)) {
1668                     vkey = keysym;
1669                 }
1670             }
1671
1672             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1673             {
1674                 keysym = XLookupKeysym(&e2, i);
1675                 switch (keysym)
1676                 {
1677                 case ';':             vkey = VK_OEM_1; break;
1678                 case '/':             vkey = VK_OEM_2; break;
1679                 case '`':             vkey = VK_OEM_3; break;
1680                 case '[':             vkey = VK_OEM_4; break;
1681                 case '\\':            vkey = VK_OEM_5; break;
1682                 case ']':             vkey = VK_OEM_6; break;
1683                 case '\'':            vkey = VK_OEM_7; break;
1684                 case ',':             vkey = VK_OEM_COMMA; break;
1685                 case '.':             vkey = VK_OEM_PERIOD; break;
1686                 case '-':             vkey = VK_OEM_MINUS; break;
1687                 case '+':             vkey = VK_OEM_PLUS; break;
1688                 }
1689             }
1690
1691             if (!vkey)
1692             {
1693                 /* Others keys: let's assign OEM virtual key codes in the allowed range,
1694                  * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
1695                 switch (++OEMvkey)
1696                 {
1697                 case 0xc1 : OEMvkey=0xdb; break;
1698                 case 0xe5 : OEMvkey=0xe9; break;
1699                 case 0xf6 : OEMvkey=0xf5; WARN("No more OEM vkey available!\n");
1700                 }
1701
1702                 vkey = OEMvkey;
1703
1704                 if (TRACE_ON(keyboard))
1705                 {
1706                     TRACE("OEM specific virtual key %X assigned to keycode %X:\n",
1707                                      OEMvkey, e2.keycode);
1708                     TRACE("(");
1709                     for (i = 0; i < keysyms_per_keycode; i += 1)
1710                     {
1711                         char    *ksname;
1712
1713                         keysym = XLookupKeysym(&e2, i);
1714                         ksname = XKeysymToString(keysym);
1715                         if (!ksname)
1716                             ksname = "NoSymbol";
1717                         TRACE( "%lX (%s) ", keysym, ksname);
1718                     }
1719                     TRACE(")\n");
1720                 }
1721             }
1722 #endif
1723         }
1724         TRACE("keycode %04x => vkey %04x\n", e2.keycode, vkey);
1725         keyc2vkey[e2.keycode] = vkey;
1726         keyc2scan[e2.keycode] = scan;
1727     } /* for */
1728
1729     /* If some keys still lack scancodes, assign some arbitrary ones to them now */
1730     for (scan = 0x60, keyc = min_keycode; keyc <= max_keycode; keyc++)
1731       if (keyc2vkey[keyc]&&!keyc2scan[keyc]) {
1732         char *ksname;
1733         keysym = XKeycodeToKeysym(display, keyc, 0);
1734         ksname = XKeysymToString(keysym);
1735         if (!ksname) ksname = "NoSymbol";
1736
1737         /* should make sure the scancode is unassigned here, but >=0x60 currently always is */
1738
1739         TRACE_(key)("assigning scancode %02x to unidentified keycode %02x (%s)\n",scan,keyc,ksname);
1740         keyc2scan[keyc]=scan++;
1741       }
1742
1743     /* Now store one keycode for each modifier. Used to simulate keypresses. */
1744     kcControl = XKeysymToKeycode(display, XK_Control_L);
1745     kcAlt = XKeysymToKeycode(display, XK_Alt_L);
1746     if (!kcAlt) kcAlt = XKeysymToKeycode(display, XK_Meta_L);
1747     kcShift = XKeysymToKeycode(display, XK_Shift_L);
1748     kcNumLock = XKeysymToKeycode(display, XK_Num_Lock);
1749     kcCapsLock = XKeysymToKeycode(display, XK_Caps_Lock);
1750     wine_tsx11_unlock();
1751 }
1752
1753
1754 /**********************************************************************
1755  *              GetAsyncKeyState (X11DRV.@)
1756  */
1757 SHORT X11DRV_GetAsyncKeyState(INT key)
1758 {
1759     SHORT retval = ((key_state_table[key] & 0x40) ? 0x0001 : 0) |
1760                    ((key_state_table[key] & 0x80) ? 0x8000 : 0);
1761     key_state_table[key] &= ~0x40;
1762     TRACE_(key)("(%x) -> %x\n", key, retval);
1763     return retval;
1764 }
1765
1766
1767 /***********************************************************************
1768  *              GetKeyboardLayoutList (X11DRV.@)
1769  */
1770 UINT X11DRV_GetKeyboardLayoutList(INT size, HKL *hkl)
1771 {
1772     INT i;
1773
1774     TRACE("%d, %p\n", size, hkl);
1775
1776     if (!size)
1777     {
1778         size = 4096; /* hope we will never have that many */
1779         hkl = NULL;
1780     }
1781
1782     for (i = 0; main_key_tab[i].comment && (i < size); i++)
1783     {
1784         if (hkl)
1785         {
1786             ULONG_PTR layout = main_key_tab[i].lcid;
1787             LANGID langid;
1788
1789             /* see comment for GetKeyboardLayout */
1790             langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1791             if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1792                 layout |= 0xe001 << 16; /* FIXME */
1793             else
1794                 layout |= layout << 16;
1795
1796             hkl[i] = (HKL)layout;
1797         }
1798     }
1799     return i;
1800 }
1801
1802
1803 /***********************************************************************
1804  *              GetKeyboardLayout (X11DRV.@)
1805  */
1806 HKL X11DRV_GetKeyboardLayout(DWORD dwThreadid)
1807 {
1808     ULONG_PTR layout;
1809     LANGID langid;
1810
1811     if (dwThreadid && dwThreadid != GetCurrentThreadId())
1812         FIXME("couldn't return keyboard layout for thread %04lx\n", dwThreadid);
1813
1814 #if 0
1815     layout = main_key_tab[kbd_layout].lcid;
1816 #else
1817     /* FIXME:
1818      * Winword uses return value of GetKeyboardLayout as a codepage
1819      * to translate ANSI keyboard messages to unicode. But we have
1820      * a problem with it: for instance Polish keyboard layout is
1821      * identical to the US one, and therefore instead of the Polish
1822      * locale id we return the US one.
1823      */
1824     layout = GetUserDefaultLCID();
1825 #endif
1826     /* 
1827      * Microsoft Office expects this value to be something specific
1828      * for Japanese and Korean Windows with an IME the value is 0xe001
1829      * We should probably check to see if an IME exists and if so then
1830      * set this word properly.
1831      */
1832     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1833     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1834         layout |= 0xe001 << 16; /* FIXME */
1835     else
1836         layout |= layout << 16;
1837
1838     return (HKL)layout;
1839 }
1840
1841
1842 /***********************************************************************
1843  *              GetKeyboardLayoutName (X11DRV.@)
1844  */
1845 BOOL X11DRV_GetKeyboardLayoutName(LPWSTR name)
1846 {
1847     static const WCHAR formatW[] = {'%','0','8','l','x',0};
1848     DWORD layout;
1849     LANGID langid;
1850
1851     layout = main_key_tab[kbd_layout].lcid;
1852     /* see comment for GetKeyboardLayout */
1853     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1854     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1855         layout |= 0xe001 << 16; /* FIXME */
1856     else
1857         layout |= layout << 16;
1858
1859     sprintfW(name, formatW, layout);
1860     TRACE("returning %s\n", debugstr_w(name));
1861     return TRUE;
1862 }
1863
1864
1865 /***********************************************************************
1866  *              LoadKeyboardLayout (X11DRV.@)
1867  */
1868 HKL X11DRV_LoadKeyboardLayout(LPCWSTR name, UINT flags)
1869 {
1870     FIXME("%s, %04x: stub!\n", debugstr_w(name), flags);
1871     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1872     return 0;
1873 }
1874
1875
1876 /***********************************************************************
1877  *              UnloadKeyboardLayout (X11DRV.@)
1878  */
1879 BOOL X11DRV_UnloadKeyboardLayout(HKL hkl)
1880 {
1881     FIXME("%p: stub!\n", hkl);
1882     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1883     return FALSE;
1884 }
1885
1886
1887 /***********************************************************************
1888  *              ActivateKeyboardLayout (X11DRV.@)
1889  */
1890 HKL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags)
1891 {
1892     FIXME("%p, %04x: stub!\n", hkl, flags);
1893     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1894     return 0;
1895 }
1896
1897
1898 /***********************************************************************
1899  *           X11DRV_MappingNotify
1900  */
1901 void X11DRV_MappingNotify( HWND dummy, XEvent *event )
1902 {
1903     HWND hwnd;
1904
1905     wine_tsx11_lock();
1906     XRefreshKeyboardMapping(&event->xmapping);
1907     wine_tsx11_unlock();
1908     X11DRV_InitKeyboard();
1909
1910     hwnd = GetFocus();
1911     if (!hwnd) hwnd = GetActiveWindow();
1912     PostMessageW(hwnd, WM_INPUTLANGCHANGEREQUEST,
1913                  0 /*FIXME*/, (LPARAM)X11DRV_GetKeyboardLayout(0));
1914 }
1915
1916
1917 /***********************************************************************
1918  *              VkKeyScanEx (X11DRV.@)
1919  *
1920  * Note: Windows ignores HKL parameter and uses current active layout instead
1921  */
1922 SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
1923 {
1924     Display *display = thread_display();
1925     KeyCode keycode;
1926     KeySym keysym;
1927     int i, index;
1928     CHAR cChar;
1929     SHORT ret;
1930
1931     /* FIXME: what happens if wChar is not a Latin1 character and CP_UNIXCP
1932      * is UTF-8 (multibyte encoding)?
1933      */
1934     if (!WideCharToMultiByte(CP_UNIXCP, 0, &wChar, 1, &cChar, 1, NULL, NULL))
1935     {
1936         WARN("no translation from unicode to CP_UNIXCP for 0x%02x\n", wChar);
1937         return -1;
1938     }
1939
1940     TRACE("wChar 0x%02x -> cChar '%c'\n", wChar, cChar);
1941
1942     /* char->keysym (same for ANSI chars) */
1943     keysym = (unsigned char)cChar; /* (!) cChar is signed */
1944     if (keysym <= 27) keysym += 0xFF00; /* special chars : return, backspace... */
1945
1946     wine_tsx11_lock();
1947     keycode = XKeysymToKeycode(display, keysym);  /* keysym -> keycode */
1948     if (!keycode)
1949     {
1950         if (keysym >= 0xFF00) /* Windows returns 0x0240 + cChar in this case */
1951         {
1952             ret = 0x0240 + cChar; /* 0x0200 indicates a control character */
1953             TRACE(" ... returning ctrl char %#.2x\n", ret);
1954             wine_tsx11_unlock();
1955             return ret;
1956         }
1957         /* It didn't work ... let's try with deadchar code. */
1958         TRACE("retrying with | 0xFE00\n");
1959         keycode = XKeysymToKeycode(display, keysym | 0xFE00);
1960     }
1961     wine_tsx11_unlock();
1962
1963     TRACE("'%c'(%#lx, %lu): got keycode %#.2x (%d)\n",
1964             cChar, keysym, keysym, keycode, keycode);
1965
1966     /* keycode -> (keyc2vkey) vkey */
1967     ret = keyc2vkey[keycode];
1968
1969     if (!keycode || !ret)
1970     {
1971         TRACE("keycode for '%c' not found, returning -1\n", cChar);
1972         return -1;
1973     }
1974
1975     index = -1;
1976     wine_tsx11_lock();
1977     for (i = 0; i < 4; i++) /* find shift state */
1978     {
1979         if (XKeycodeToKeysym(display, keycode, i) == keysym)
1980         {
1981             index = i;
1982             break;
1983         }
1984     }
1985     wine_tsx11_unlock();
1986
1987     switch (index)
1988     {
1989         default:
1990         case -1:
1991             WARN("Keysym %lx not found while parsing the keycode table\n", keysym);
1992             return -1;
1993
1994         case 0: break;
1995         case 1: ret += 0x0100; break;
1996         case 2: ret += 0x0600; break;
1997         case 3: ret += 0x0700; break;
1998     }
1999     /*
2000       index : 0     adds 0x0000
2001       index : 1     adds 0x0100 (shift)
2002       index : ?     adds 0x0200 (ctrl)
2003       index : 2     adds 0x0600 (ctrl+alt)
2004       index : 3     adds 0x0700 (ctrl+alt+shift)
2005      */
2006
2007     TRACE(" ... returning %#.2x\n", ret);
2008     return ret;
2009 }
2010
2011 /***********************************************************************
2012  *              MapVirtualKeyEx (X11DRV.@)
2013  */
2014 UINT X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
2015 {
2016     Display *display = thread_display();
2017
2018 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
2019
2020     TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl);
2021     if (hkl != X11DRV_GetKeyboardLayout(0))
2022         FIXME("keyboard layout %p is not supported\n", hkl);
2023
2024         switch(wMapType) {
2025                 case 0: { /* vkey-code to scan-code */
2026                         /* let's do vkey -> keycode -> scan */
2027                         int keyc;
2028                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
2029                                 if ((keyc2vkey[keyc] & 0xFF) == wCode)
2030                                         returnMVK (keyc2scan[keyc] & 0xFF);
2031                         TRACE("returning no scan-code.\n");
2032                         return 0; }
2033
2034                 case 1: { /* scan-code to vkey-code */
2035                         /* let's do scan -> keycode -> vkey */
2036                         int keyc;
2037                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
2038                                 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
2039                                         returnMVK (keyc2vkey[keyc] & 0xFF);
2040                         TRACE("returning no vkey-code.\n");
2041                         return 0; }
2042
2043                 case 2: { /* vkey-code to unshifted ANSI code */
2044                         /* we still don't know what "unshifted" means. in windows VK_W (0x57)
2045                          * returns 0x57, which is upercase 'W'. So we have to return the uppercase
2046                          * key.. Looks like something is wrong with the MS docs?
2047                          * This is only true for letters, for example VK_0 returns '0' not ')'.
2048                          * - hence we use the lock mask to ensure this happens.
2049                          */
2050                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
2051                         XKeyEvent e;
2052                         KeySym keysym;
2053                         int keyc;
2054                         char s[2];
2055                         e.display = display;
2056
2057                         e.state = LockMask;
2058                         /* LockMask should behave exactly like caps lock - upercase
2059                          * the letter keys and thats about it. */
2060
2061                         wine_tsx11_lock();
2062
2063                         e.keycode = 0;
2064                         /* We exit on the first keycode found, to speed up the thing. */
2065                         for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2066                         { /* Find a keycode that could have generated this virtual key */
2067                             if  ((keyc2vkey[keyc] & 0xFF) == wCode)
2068                             { /* We filter the extended bit, we don't know it */
2069                                 e.keycode = keyc; /* Store it temporarily */
2070                                 if ((EVENT_event_to_vkey(0,&e) & 0xFF) != wCode) {
2071                                     e.keycode = 0; /* Wrong one (ex: because of the NumLock
2072                                          state), so set it to 0, we'll find another one */
2073                                 }
2074                             }
2075                         }
2076
2077                         if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
2078                           e.keycode = XKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
2079
2080                         if (wCode==VK_DECIMAL)
2081                           e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2082
2083                         if (!e.keycode)
2084                         {
2085                           WARN("Unknown virtual key %X !!!\n", wCode);
2086                           wine_tsx11_unlock();
2087                           return 0; /* whatever */
2088                         }
2089                         TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2090
2091                         if (XLookupString(&e, s, 2, &keysym, NULL))
2092                         {
2093                             wine_tsx11_unlock();
2094                             returnMVK (*s);
2095                         }
2096
2097                         TRACE("returning no ANSI.\n");
2098                         wine_tsx11_unlock();
2099                         return 0;
2100                         }
2101
2102                 case 3:   /* **NT only** scan-code to vkey-code but distinguish between  */
2103                           /*             left and right  */
2104                           FIXME(" stub for NT\n");
2105                           return 0;
2106
2107                 default: /* reserved */
2108                         WARN("Unknown wMapType %d !\n", wMapType);
2109                         return 0;
2110         }
2111         return 0;
2112 }
2113
2114 /***********************************************************************
2115  *              GetKeyNameText (X11DRV.@)
2116  */
2117 INT X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
2118 {
2119   int vkey, ansi, scanCode;
2120   KeyCode keyc;
2121   int keyi;
2122   KeySym keys;
2123   char *name;
2124
2125   scanCode = lParam >> 16;
2126   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
2127
2128   /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
2129   vkey = X11DRV_MapVirtualKeyEx(scanCode, 1, X11DRV_GetKeyboardLayout(0));
2130
2131   /*  handle "don't care" bit (0x02000000) */
2132   if (!(lParam & 0x02000000)) {
2133     switch (vkey) {
2134          case VK_LSHIFT:
2135          case VK_RSHIFT:
2136                           vkey = VK_SHIFT;
2137                           break;
2138        case VK_LCONTROL:
2139        case VK_RCONTROL:
2140                           vkey = VK_CONTROL;
2141                           break;
2142           case VK_LMENU:
2143           case VK_RMENU:
2144                           vkey = VK_MENU;
2145                           break;
2146                default:
2147                           break;
2148     }
2149   }
2150
2151   ansi = X11DRV_MapVirtualKeyEx(vkey, 2, X11DRV_GetKeyboardLayout(0));
2152   TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
2153
2154   /* first get the name of the "regular" keys which is the Upper case
2155      value of the keycap imprint.                                     */
2156   if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
2157        (scanCode != 0x137) &&   /* PrtScn   */
2158        (scanCode != 0x135) &&   /* numpad / */
2159        (scanCode != 0x37 ) &&   /* numpad * */
2160        (scanCode != 0x4a ) &&   /* numpad - */
2161        (scanCode != 0x4e ) )    /* numpad + */
2162       {
2163         if ((nSize >= 2) && lpBuffer)
2164         {
2165           *lpBuffer = toupperW((WCHAR)ansi);
2166           *(lpBuffer+1) = 0;
2167           return 1;
2168         }
2169      else
2170         return 0;
2171   }
2172
2173   /* FIXME: horrible hack to fix function keys. Windows reports scancode
2174             without "extended-key" flag. However Wine generates scancode
2175             *with* "extended-key" flag. Seems to occur *only* for the
2176             function keys. Soooo.. We will leave the table alone and
2177             fudge the lookup here till the other part is found and fixed!!! */
2178
2179   if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
2180        (scanCode == 0x157) || (scanCode == 0x158))
2181     scanCode &= 0xff;   /* remove "extended-key" flag for Fx keys */
2182
2183   /* let's do scancode -> keycode -> keysym -> String */
2184
2185   for (keyi=min_keycode; keyi<=max_keycode; keyi++)
2186       if ((keyc2scan[keyi]) == scanCode)
2187          break;
2188   if (keyi <= max_keycode)
2189   {
2190       wine_tsx11_lock();
2191       keyc = (KeyCode) keyi;
2192       keys = XKeycodeToKeysym(thread_display(), keyc, 0);
2193       name = XKeysymToString(keys);
2194       wine_tsx11_unlock();
2195       TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
2196             scanCode, keyc, (int)keys, name);
2197       if (lpBuffer && nSize && name)
2198       {
2199           MultiByteToWideChar(CP_UNIXCP, 0, name, -1, lpBuffer, nSize);
2200           lpBuffer[nSize - 1] = 0;
2201           return 1;
2202       }
2203   }
2204
2205   /* Finally issue FIXME for unknown keys   */
2206
2207   FIXME("(%08lx,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
2208   if (lpBuffer && nSize)
2209     *lpBuffer = 0;
2210   return 0;
2211 }
2212
2213 /***********************************************************************
2214  *              X11DRV_KEYBOARD_MapDeadKeysym
2215  */
2216 static char KEYBOARD_MapDeadKeysym(KeySym keysym)
2217 {
2218         switch (keysym)
2219             {
2220         /* symbolic ASCII is the same as defined in rfc1345 */
2221 #ifdef XK_dead_tilde
2222             case XK_dead_tilde :
2223 #endif
2224             case 0x1000FE7E : /* Xfree's XK_Dtilde */
2225                 return '~';     /* '? */
2226 #ifdef XK_dead_acute
2227             case XK_dead_acute :
2228 #endif
2229             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
2230                 return 0xb4;    /* '' */
2231 #ifdef XK_dead_circumflex
2232             case XK_dead_circumflex:
2233 #endif
2234             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
2235                 return '^';     /* '> */
2236 #ifdef XK_dead_grave
2237             case XK_dead_grave :
2238 #endif
2239             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
2240                 return '`';     /* '! */
2241 #ifdef XK_dead_diaeresis
2242             case XK_dead_diaeresis :
2243 #endif
2244             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
2245                 return 0xa8;    /* ': */
2246 #ifdef XK_dead_cedilla
2247             case XK_dead_cedilla :
2248                 return 0xb8;    /* ', */
2249 #endif
2250 #ifdef XK_dead_macron
2251             case XK_dead_macron :
2252                 return '-';     /* 'm isn't defined on iso-8859-x */
2253 #endif
2254 #ifdef XK_dead_breve
2255             case XK_dead_breve :
2256                 return 0xa2;    /* '( */
2257 #endif
2258 #ifdef XK_dead_abovedot
2259             case XK_dead_abovedot :
2260                 return 0xff;    /* '. */
2261 #endif
2262 #ifdef XK_dead_abovering
2263             case XK_dead_abovering :
2264                 return '0';     /* '0 isn't defined on iso-8859-x */
2265 #endif
2266 #ifdef XK_dead_doubleacute
2267             case XK_dead_doubleacute :
2268                 return 0xbd;    /* '" */
2269 #endif
2270 #ifdef XK_dead_caron
2271             case XK_dead_caron :
2272                 return 0xb7;    /* '< */
2273 #endif
2274 #ifdef XK_dead_ogonek
2275             case XK_dead_ogonek :
2276                 return 0xb2;    /* '; */
2277 #endif
2278 /* FIXME: I don't know this three.
2279             case XK_dead_iota :
2280                 return 'i';
2281             case XK_dead_voiced_sound :
2282                 return 'v';
2283             case XK_dead_semivoiced_sound :
2284                 return 's';
2285 */
2286             }
2287         TRACE("no character for dead keysym 0x%08lx\n",keysym);
2288         return 0;
2289 }
2290
2291 /***********************************************************************
2292  *              ToUnicodeEx (X11DRV.@)
2293  *
2294  * The ToUnicode function translates the specified virtual-key code and keyboard
2295  * state to the corresponding Windows character or characters.
2296  *
2297  * If the specified key is a dead key, the return value is negative. Otherwise,
2298  * it is one of the following values:
2299  * Value        Meaning
2300  * 0    The specified virtual key has no translation for the current state of the keyboard.
2301  * 1    One Windows character was copied to the buffer.
2302  * 2    Two characters were copied to the buffer. This usually happens when a
2303  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
2304  *      be composed with the specified virtual key to form a single character.
2305  *
2306  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
2307  *
2308  */
2309 INT X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
2310                      LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
2311 {
2312     Display *display = thread_display();
2313     XKeyEvent e;
2314     KeySym keysym = 0;
2315     INT ret;
2316     int keyc;
2317     char lpChar[10];
2318     HWND focus;
2319     XIC xic;
2320     Status status;
2321
2322     if (scanCode & 0x8000)
2323     {
2324         TRACE("Key UP, doing nothing\n" );
2325         return 0;
2326     }
2327
2328     if (hkl != X11DRV_GetKeyboardLayout(0))
2329         FIXME("keyboard layout %p is not supported\n", hkl);
2330
2331     if ((lpKeyState[VK_MENU] & 0x80) && (lpKeyState[VK_CONTROL] & 0x80))
2332     {
2333         TRACE("Ctrl+Alt+[key] won't generate a character\n");
2334         return 0;
2335     }
2336
2337     e.display = display;
2338     e.keycode = 0;
2339     e.state = 0;
2340     e.type = KeyPress;
2341
2342     focus = GetFocus();
2343     if (focus) focus = GetAncestor( focus, GA_ROOT );
2344     if (!focus) focus = GetActiveWindow();
2345     e.window = X11DRV_get_whole_window( focus );
2346     xic = X11DRV_get_ic( focus );
2347
2348     if (lpKeyState[VK_SHIFT] & 0x80)
2349     {
2350         TRACE("ShiftMask = %04x\n", ShiftMask);
2351         e.state |= ShiftMask;
2352     }
2353     if (lpKeyState[VK_CAPITAL] & 0x01)
2354     {
2355         TRACE("LockMask = %04x\n", LockMask);
2356         e.state |= LockMask;
2357     }
2358     if (lpKeyState[VK_CONTROL] & 0x80)
2359     {
2360         TRACE("ControlMask = %04x\n", ControlMask);
2361         e.state |= ControlMask;
2362     }
2363     if (lpKeyState[VK_NUMLOCK] & 0x01)
2364     {
2365         TRACE("NumLockMask = %04x\n", NumLockMask);
2366         e.state |= NumLockMask;
2367     }
2368
2369     /* Restore saved AltGr state */
2370     TRACE("AltGrMask = %04x\n", AltGrMask);
2371     e.state |= AltGrMask;
2372
2373     TRACE_(key)("(%04X, %04X) : faked state = 0x%04x\n",
2374                 virtKey, scanCode, e.state);
2375     wine_tsx11_lock();
2376     /* We exit on the first keycode found, to speed up the thing. */
2377     for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2378       { /* Find a keycode that could have generated this virtual key */
2379           if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
2380           { /* We filter the extended bit, we don't know it */
2381               e.keycode = keyc; /* Store it temporarily */
2382               if ((EVENT_event_to_vkey(xic,&e) & 0xFF) != virtKey) {
2383                   e.keycode = 0; /* Wrong one (ex: because of the NumLock
2384                          state), so set it to 0, we'll find another one */
2385               }
2386           }
2387       }
2388
2389     if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
2390         e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
2391
2392     if (virtKey==VK_DECIMAL)
2393         e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2394
2395     if (virtKey==VK_SEPARATOR)
2396         e.keycode = XKeysymToKeycode(e.display, XK_KP_Separator);
2397
2398     if (!e.keycode && virtKey != VK_NONAME)
2399       {
2400         WARN("Unknown virtual key %X !!!\n", virtKey);
2401         wine_tsx11_unlock();
2402         return virtKey; /* whatever */
2403       }
2404     else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2405
2406     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
2407                 e.type, e.window, e.state, e.keycode);
2408
2409     if (xic)
2410         ret = XmbLookupString(xic, &e, lpChar, sizeof(lpChar), &keysym, &status);
2411     else
2412         ret = XLookupString(&e, lpChar, sizeof(lpChar), &keysym, NULL);
2413     wine_tsx11_unlock();
2414
2415     if (ret == 0)
2416     {
2417         char dead_char;
2418
2419 #ifdef XK_EuroSign
2420         /* An ugly hack for EuroSign: X can't translate it to a character
2421            for some locales. */
2422         if (keysym == XK_EuroSign)
2423         {
2424             bufW[0] = 0x20AC;
2425             ret = 1;
2426             goto found;
2427         }
2428 #endif
2429         /* Special case: X turns shift-tab into ISO_Left_Tab. */
2430         /* Here we change it back. */
2431         if (keysym == XK_ISO_Left_Tab)
2432         {
2433             bufW[0] = 0x09;
2434             ret = 1;
2435             goto found;
2436         }
2437
2438         dead_char = KEYBOARD_MapDeadKeysym(keysym);
2439         if (dead_char)
2440             {
2441             MultiByteToWideChar(CP_UNIXCP, 0, &dead_char, 1, bufW, bufW_size);
2442             ret = -1;
2443             }
2444         else
2445             {
2446             char        *ksname;
2447
2448             wine_tsx11_lock();
2449             ksname = XKeysymToString(keysym);
2450             wine_tsx11_unlock();
2451             if (!ksname)
2452                 ksname = "No Name";
2453             if ((keysym >> 8) != 0xff)
2454                 {
2455                 ERR("Please report: no char for keysym %04lX (%s) :\n",
2456                     keysym, ksname);
2457                 ERR("(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
2458                     virtKey, scanCode, e.keycode, e.state);
2459                 }
2460             }
2461         }
2462     else {  /* ret != 0 */
2463         /* We have a special case to handle : Shift + arrow, shift + home, ...
2464            X returns a char for it, but Windows doesn't. Let's eat it. */
2465         if (!(e.state & NumLockMask)  /* NumLock is off */
2466             && (e.state & ShiftMask) /* Shift is pressed */
2467             && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
2468         {
2469             lpChar[0] = 0;
2470             ret = 0;
2471         }
2472
2473         /* more areas where X returns characters but Windows does not
2474            CTRL + number or CTRL + symbol */
2475         if (e.state & ControlMask)
2476         {
2477             if (((keysym>=33) && (keysym < 'A')) ||
2478                 ((keysym > 'Z') && (keysym < 'a')))
2479             {
2480                 lpChar[0] = 0;
2481                 ret = 0;
2482             }
2483         }
2484
2485         /* We have another special case for delete key (XK_Delete) on an
2486          extended keyboard. X returns a char for it, but Windows doesn't */
2487         if (keysym == XK_Delete)
2488         {
2489             lpChar[0] = 0;
2490             ret = 0;
2491         }
2492         else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
2493                 && (keysym == XK_KP_Decimal))
2494         {
2495             lpChar[0] = 0;
2496             ret = 0;
2497         }
2498
2499         /* perform translation to unicode */
2500         if(ret)
2501         {
2502             TRACE_(key)("Translating char 0x%02x to unicode\n", *(BYTE *)lpChar);
2503             ret = MultiByteToWideChar(CP_UNIXCP, 0, lpChar, ret, bufW, bufW_size);
2504         }
2505     }
2506
2507 found:
2508     TRACE_(key)("ToUnicode about to return %d with char %x %s\n",
2509                 ret, (ret && bufW) ? bufW[0] : 0, bufW ? "" : "(no buffer)");
2510     return ret;
2511 }
2512
2513 /***********************************************************************
2514  *              Beep (X11DRV.@)
2515  */
2516 void X11DRV_Beep(void)
2517 {
2518     wine_tsx11_lock();
2519     XBell(thread_display(), 0);
2520     wine_tsx11_unlock();
2521 }