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