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