dplayx: Tests for CreateGroup.
[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, 0x138, 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 Str[24];
1356     KeySym keysym = 0;
1357     WORD vkey = 0, bScan;
1358     DWORD dwFlags;
1359     int ascii_chars;
1360     XIC xic = X11DRV_get_ic( hwnd );
1361     DWORD event_time = EVENT_x11_time_to_win32_time(event->time);
1362     Status status = 0;
1363
1364     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
1365                 event->type, event->window, event->state, event->keycode);
1366
1367     wine_tsx11_lock();
1368     /* Clients should pass only KeyPress events to XmbLookupString */
1369     if (xic && event->type == KeyPress)
1370         ascii_chars = XmbLookupString(xic, event, Str, sizeof(Str), &keysym, &status);
1371     else
1372         ascii_chars = XLookupString(event, Str, sizeof(Str), &keysym, NULL);
1373     wine_tsx11_unlock();
1374
1375     TRACE_(key)("nbyte = %d, status 0x%x\n", ascii_chars, status);
1376
1377     if (status == XBufferOverflow)
1378         ERR("Buffer Overflow need %i!\n",ascii_chars);
1379
1380     if (status == XLookupChars)
1381     {
1382         X11DRV_XIMLookupChars( Str, ascii_chars );
1383         return;
1384     }
1385
1386     /* If XKB extensions are used, the state mask for AltGr will use the group
1387        index instead of the modifier mask. The group index is set in bits
1388        13-14 of the state field in the XKeyEvent structure. So if AltGr is
1389        pressed, look if the group index is different than 0. From XKB
1390        extension documentation, the group index for AltGr should be 2
1391        (event->state = 0x2000). It's probably better to not assume a
1392        predefined group index and find it dynamically
1393
1394        Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
1395     /* Save also all possible modifier states. */
1396     AltGrMask = event->state & (0x6000 | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
1397
1398     if (TRACE_ON(key)){
1399         const char *ksname;
1400
1401         wine_tsx11_lock();
1402         ksname = XKeysymToString(keysym);
1403         wine_tsx11_unlock();
1404         if (!ksname)
1405           ksname = "No Name";
1406         TRACE_(key)("%s : keysym=%lX (%s), # of chars=%d / %s\n",
1407                     (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
1408                     keysym, ksname, ascii_chars, debugstr_an(Str, ascii_chars));
1409     }
1410
1411     wine_tsx11_lock();
1412     vkey = EVENT_event_to_vkey(xic,event);
1413     /* X returns keycode 0 for composed characters */
1414     if (!vkey && ascii_chars) vkey = VK_NONAME;
1415     wine_tsx11_unlock();
1416
1417     TRACE_(key)("keycode 0x%x converted to vkey 0x%x\n",
1418                 event->keycode, vkey);
1419
1420     if (!vkey) return;
1421
1422     dwFlags = 0;
1423     if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
1424     if ( vkey & 0x100 )              dwFlags |= KEYEVENTF_EXTENDEDKEY;
1425
1426
1427     /* Note: X sets the below states on key down and clears them on key up.
1428        Windows triggers them on key down. */
1429
1430     /* Adjust the CAPSLOCK state if it has been changed outside wine */
1431     if (!(key_state_table[VK_CAPITAL] & 0x01) != !(event->state & LockMask) &&
1432         vkey != VK_CAPITAL)
1433     {
1434         TRACE("Adjusting CapsLock state (%#.2x)\n", key_state_table[VK_CAPITAL]);
1435         update_lock_state(VK_CAPITAL, 0x3A, event_time);
1436     }
1437
1438     /* Adjust the NUMLOCK state if it has been changed outside wine */
1439     if (!(key_state_table[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask) &&
1440         (vkey & 0xff) != VK_NUMLOCK)
1441     {
1442         TRACE("Adjusting NumLock state (%#.2x)\n", key_state_table[VK_NUMLOCK]);
1443         update_lock_state(VK_NUMLOCK, 0x45, event_time);
1444     }
1445
1446     /* Adjust the SCROLLLOCK state if it has been changed outside wine */
1447     if (!(key_state_table[VK_SCROLL] & 0x01) != !(event->state & ScrollLockMask) &&
1448         vkey != VK_SCROLL)
1449     {
1450         TRACE("Adjusting ScrLock state (%#.2x)\n", key_state_table[VK_SCROLL]);
1451         update_lock_state(VK_SCROLL, 0x46, event_time);
1452     }
1453
1454     bScan = keyc2scan[event->keycode] & 0xFF;
1455     TRACE_(key)("bScan = 0x%02x.\n", bScan);
1456
1457     X11DRV_send_keyboard_input( vkey & 0xff, bScan, dwFlags, event_time, 0, 0 );
1458 }
1459
1460 /**********************************************************************
1461  *              X11DRV_KEYBOARD_DetectLayout
1462  *
1463  * Called from X11DRV_InitKeyboard
1464  *  This routine walks through the defined keyboard layouts and selects
1465  *  whichever matches most closely.
1466  * X11 lock must be held.
1467  */
1468 static void
1469 X11DRV_KEYBOARD_DetectLayout( Display *display )
1470 {
1471   unsigned current, match, mismatch, seq, i, syms;
1472   int score, keyc, key, pkey, ok;
1473   KeySym keysym = 0;
1474   const char (*lkey)[MAIN_LEN][4];
1475   unsigned max_seq = 0;
1476   int max_score = 0, ismatch = 0;
1477   char ckey[256][4];
1478
1479   syms = keysyms_per_keycode;
1480   if (syms > 4) {
1481     WARN("%d keysyms per keycode not supported, set to 4\n", syms);
1482     syms = 4;
1483   }
1484
1485   memset( ckey, 0, sizeof(ckey) );
1486   for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1487       /* get data for keycode from X server */
1488       for (i = 0; i < syms; i++) {
1489         if (!(keysym = XKeycodeToKeysym (display, keyc, i))) continue;
1490         /* Allow both one-byte and two-byte national keysyms */
1491         if ((keysym < 0x8000) && (keysym != ' '))
1492         {
1493 #ifdef HAVE_XKB
1494             if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[keyc][i], 1, NULL))
1495 #endif
1496             {
1497                 TRACE("XKB could not translate keysym %ld\n", keysym);
1498                 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1499                  * with appropriate ShiftMask and Mode_switch, use XLookupString
1500                  * to get character in the local encoding.
1501                  */
1502                 ckey[keyc][i] = keysym & 0xFF;
1503             }
1504         }
1505         else {
1506           ckey[keyc][i] = KEYBOARD_MapDeadKeysym(keysym);
1507         }
1508       }
1509   }
1510
1511   for (current = 0; main_key_tab[current].comment; current++) {
1512     TRACE("Attempting to match against \"%s\"\n", main_key_tab[current].comment);
1513     match = 0;
1514     mismatch = 0;
1515     score = 0;
1516     seq = 0;
1517     lkey = main_key_tab[current].key;
1518     pkey = -1;
1519     for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1520       if (ckey[keyc][0]) {
1521         /* search for a match in layout table */
1522         /* right now, we just find an absolute match for defined positions */
1523         /* (undefined positions are ignored, so if it's defined as "3#" in */
1524         /* the table, it's okay that the X server has "3#£", for example) */
1525         /* however, the score will be higher for longer matches */
1526         for (key = 0; key < MAIN_LEN; key++) {
1527           for (ok = 0, i = 0; (ok >= 0) && (i < syms); i++) {
1528             if ((*lkey)[key][i] && ((*lkey)[key][i] == ckey[keyc][i]))
1529               ok++;
1530             if ((*lkey)[key][i] && ((*lkey)[key][i] != ckey[keyc][i]))
1531               ok = -1;
1532           }
1533           if (ok > 0) {
1534             score += ok;
1535             break;
1536           }
1537         }
1538         /* count the matches and mismatches */
1539         if (ok > 0) {
1540           match++;
1541           /* and how much the keycode order matches */
1542           if (key > pkey) seq++;
1543           pkey = key;
1544         } else {
1545           /* print spaces instead of \0's */
1546           char str[5];
1547           for (i = 0; i < 4; i++) str[i] = ckey[keyc][i] ? ckey[keyc][i] : ' ';
1548           str[4] = 0;
1549           TRACE_(key)("mismatch for keysym 0x%04lX, keycode %d, got %s\n", keysym, keyc, str );
1550           mismatch++;
1551           score -= syms;
1552         }
1553       }
1554     }
1555     TRACE("matches=%d, mismatches=%d, seq=%d, score=%d\n",
1556            match, mismatch, seq, score);
1557     if ((score > max_score) ||
1558         ((score == max_score) && (seq > max_seq))) {
1559       /* best match so far */
1560       kbd_layout = current;
1561       max_score = score;
1562       max_seq = seq;
1563       ismatch = !mismatch;
1564     }
1565   }
1566   /* we're done, report results if necessary */
1567   if (!ismatch)
1568     WARN("Using closest match (%s) for scan/virtual codes mapping.\n",
1569         main_key_tab[kbd_layout].comment);
1570
1571   TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment);
1572 }
1573
1574 /**********************************************************************
1575  *              X11DRV_InitKeyboard
1576  */
1577 void X11DRV_InitKeyboard( Display *display )
1578 {
1579     KeySym *ksp;
1580     XModifierKeymap *mmp;
1581     KeySym keysym;
1582     KeyCode *kcp;
1583     XKeyEvent e2;
1584     WORD scan, vkey, OEMvkey;
1585     int keyc, i, keyn, syms;
1586     char ckey[4]={0,0,0,0};
1587     const char (*lkey)[MAIN_LEN][4];
1588     char vkey_used[256] = { 0 };
1589
1590     wine_tsx11_lock();
1591     XDisplayKeycodes(display, &min_keycode, &max_keycode);
1592     ksp = XGetKeyboardMapping(display, min_keycode,
1593                               max_keycode + 1 - min_keycode, &keysyms_per_keycode);
1594     /* We are only interested in keysyms_per_keycode.
1595        There is no need to hold a local copy of the keysyms table */
1596     XFree(ksp);
1597
1598     mmp = XGetModifierMapping(display);
1599     kcp = mmp->modifiermap;
1600     for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
1601     {
1602         int j;
1603
1604         for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
1605             if (*kcp)
1606             {
1607                 int k;
1608
1609                 for (k = 0; k < keysyms_per_keycode; k += 1)
1610                     if (XKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
1611                     {
1612                         NumLockMask = 1 << i;
1613                         TRACE_(key)("NumLockMask is %x\n", NumLockMask);
1614                     }
1615                     else if (XKeycodeToKeysym(display, *kcp, k) == XK_Scroll_Lock)
1616                     {
1617                         ScrollLockMask = 1 << i;
1618                         TRACE_(key)("ScrollLockMask is %x\n", ScrollLockMask);
1619                     }
1620             }
1621     }
1622     XFreeModifiermap(mmp);
1623
1624     /* Detect the keyboard layout */
1625     X11DRV_KEYBOARD_DetectLayout( display );
1626     lkey = main_key_tab[kbd_layout].key;
1627     syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode;
1628
1629     /* Now build two conversion arrays :
1630      * keycode -> vkey + scancode + extended
1631      * vkey + extended -> keycode */
1632
1633     e2.display = display;
1634     e2.state = 0;
1635
1636     OEMvkey = VK_OEM_8; /* next is available.  */
1637     memset(keyc2vkey, 0, sizeof(keyc2vkey));
1638     for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1639     {
1640         char buf[30];
1641         int have_chars;
1642
1643         keysym = 0;
1644         e2.keycode = (KeyCode)keyc;
1645         have_chars = XLookupString(&e2, buf, sizeof(buf), &keysym, NULL);
1646         vkey = 0; scan = 0;
1647         if (keysym)  /* otherwise, keycode not used */
1648         {
1649             if ((keysym >> 8) == 0xFF)         /* non-character key */
1650             {
1651                 vkey = nonchar_key_vkey[keysym & 0xff];
1652                 scan = nonchar_key_scan[keysym & 0xff];
1653                 /* set extended bit when necessary */
1654                 if (scan & 0x100) vkey |= 0x100;
1655             } else if ((keysym >> 8) == 0x1008FF) { /* XFree86 vendor keys */
1656                 vkey = xfree86_vendor_key_vkey[keysym & 0xff];
1657                 /* All vendor keys are extended with a scan code of 0 per testing on WinXP */
1658                 scan = 0x100;
1659                 vkey |= 0x100;
1660             } else if (keysym == 0x20) {                 /* Spacebar */
1661                 vkey = VK_SPACE;
1662                 scan = 0x39;
1663             } else if (have_chars) {
1664               /* we seem to need to search the layout-dependent scancodes */
1665               int maxlen=0,maxval=-1,ok;
1666               for (i=0; i<syms; i++) {
1667                 keysym = XKeycodeToKeysym(display, keyc, i);
1668                 if ((keysym<0x8000) && (keysym!=' '))
1669                 {
1670 #ifdef HAVE_XKB
1671                     if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
1672 #endif
1673                     {
1674                         /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1675                          * with appropriate ShiftMask and Mode_switch, use XLookupString
1676                          * to get character in the local encoding.
1677                          */
1678                         ckey[i] = keysym & 0xFF;
1679                     }
1680                 } else {
1681                   ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1682                 }
1683               }
1684               /* find key with longest match streak */
1685               for (keyn=0; keyn<MAIN_LEN; keyn++) {
1686                 for (ok=(*lkey)[keyn][i=0]; ok&&(i<4); i++)
1687                   if ((*lkey)[keyn][i] && (*lkey)[keyn][i]!=ckey[i]) ok=0;
1688                 if (!ok) i--; /* we overshot */
1689                 if (ok||(i>maxlen)) {
1690                   maxlen=i; maxval=keyn;
1691                 }
1692                 if (ok) break;
1693               }
1694               if (maxval>=0) {
1695                 /* got it */
1696                 const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan;
1697                 const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey;
1698                 scan = (*lscan)[maxval];
1699                 vkey = (*lvkey)[maxval];
1700               }
1701             }
1702         }
1703         TRACE("keycode %04x => vkey %04x\n", e2.keycode, vkey);
1704         keyc2vkey[e2.keycode] = vkey;
1705         keyc2scan[e2.keycode] = scan;
1706         if ((vkey & 0xff) && vkey_used[(vkey & 0xff)])
1707             WARN("vkey %04x is being used by more than one keycode\n", vkey);
1708         vkey_used[(vkey & 0xff)] = 1;
1709     } /* for */
1710
1711 #define VKEY_IF_NOT_USED(vkey) (vkey_used[(vkey)] ? 0 : (vkey_used[(vkey)] = 1, (vkey)))
1712     for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1713     {
1714         vkey = keyc2vkey[keyc] & 0xff;
1715         if (vkey)
1716             continue;
1717
1718         e2.keycode = (KeyCode)keyc;
1719         keysym = XLookupKeysym(&e2, 0);
1720         if (!keysym)
1721            continue;
1722
1723         /* find a suitable layout-dependent VK code */
1724         /* (most Winelib apps ought to be able to work without layout tables!) */
1725         for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1726         {
1727             keysym = XLookupKeysym(&e2, i);
1728             if ((keysym >= XK_0 && keysym <= XK_9)
1729                 || (keysym >= XK_A && keysym <= XK_Z)) {
1730                 vkey = VKEY_IF_NOT_USED(keysym);
1731             }
1732         }
1733
1734         for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1735         {
1736             keysym = XLookupKeysym(&e2, i);
1737             switch (keysym)
1738             {
1739             case ';':             vkey = VKEY_IF_NOT_USED(VK_OEM_1); break;
1740             case '/':             vkey = VKEY_IF_NOT_USED(VK_OEM_2); break;
1741             case '`':             vkey = VKEY_IF_NOT_USED(VK_OEM_3); break;
1742             case '[':             vkey = VKEY_IF_NOT_USED(VK_OEM_4); break;
1743             case '\\':            vkey = VKEY_IF_NOT_USED(VK_OEM_5); break;
1744             case ']':             vkey = VKEY_IF_NOT_USED(VK_OEM_6); break;
1745             case '\'':            vkey = VKEY_IF_NOT_USED(VK_OEM_7); break;
1746             case ',':             vkey = VKEY_IF_NOT_USED(VK_OEM_COMMA); break;
1747             case '.':             vkey = VKEY_IF_NOT_USED(VK_OEM_PERIOD); break;
1748             case '-':             vkey = VKEY_IF_NOT_USED(VK_OEM_MINUS); break;
1749             case '+':             vkey = VKEY_IF_NOT_USED(VK_OEM_PLUS); break;
1750             }
1751         }
1752
1753         if (!vkey)
1754         {
1755             /* Others keys: let's assign OEM virtual key codes in the allowed range,
1756              * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
1757             do
1758             {
1759                 switch (++OEMvkey)
1760                 {
1761                 case 0xc1 : OEMvkey=0xdb; break;
1762                 case 0xe5 : OEMvkey=0xe9; break;
1763                 case 0xf6 : OEMvkey=0xf5; WARN("No more OEM vkey available!\n");
1764                 }
1765             } while (OEMvkey < 0xf5 && vkey_used[OEMvkey]);
1766
1767             vkey = VKEY_IF_NOT_USED(OEMvkey);
1768
1769             if (TRACE_ON(keyboard))
1770             {
1771                 TRACE("OEM specific virtual key %X assigned to keycode %X:\n",
1772                                  OEMvkey, e2.keycode);
1773                 TRACE("(");
1774                 for (i = 0; i < keysyms_per_keycode; i += 1)
1775                 {
1776                     const char *ksname;
1777
1778                     keysym = XLookupKeysym(&e2, i);
1779                     ksname = XKeysymToString(keysym);
1780                     if (!ksname)
1781                         ksname = "NoSymbol";
1782                     TRACE( "%lX (%s) ", keysym, ksname);
1783                 }
1784                 TRACE(")\n");
1785             }
1786         }
1787
1788         if (vkey)
1789         {
1790             TRACE("keycode %04x => vkey %04x\n", e2.keycode, vkey);
1791             keyc2vkey[e2.keycode] = vkey;
1792         }
1793     } /* for */
1794 #undef VKEY_IF_NOT_USED
1795
1796     /* If some keys still lack scancodes, assign some arbitrary ones to them now */
1797     for (scan = 0x60, keyc = min_keycode; keyc <= max_keycode; keyc++)
1798       if (keyc2vkey[keyc]&&!keyc2scan[keyc]) {
1799         const char *ksname;
1800         keysym = XKeycodeToKeysym(display, keyc, 0);
1801         ksname = XKeysymToString(keysym);
1802         if (!ksname) ksname = "NoSymbol";
1803
1804         /* should make sure the scancode is unassigned here, but >=0x60 currently always is */
1805
1806         TRACE_(key)("assigning scancode %02x to unidentified keycode %02x (%s)\n",scan,keyc,ksname);
1807         keyc2scan[keyc]=scan++;
1808       }
1809
1810     wine_tsx11_unlock();
1811 }
1812
1813
1814 /**********************************************************************
1815  *              GetAsyncKeyState (X11DRV.@)
1816  */
1817 SHORT X11DRV_GetAsyncKeyState(INT key)
1818 {
1819     SHORT retval;
1820
1821     /* Photoshop livelocks unless mouse events are included here */
1822     X11DRV_MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_KEY | QS_MOUSE, 0 );
1823
1824     retval = ((key_state_table[key] & 0x40) ? 0x0001 : 0) |
1825              ((key_state_table[key] & 0x80) ? 0x8000 : 0);
1826     key_state_table[key] &= ~0x40;
1827     TRACE_(key)("(%x) -> %x\n", key, retval);
1828     return retval;
1829 }
1830
1831
1832 /***********************************************************************
1833  *              GetKeyboardLayoutList (X11DRV.@)
1834  */
1835 UINT X11DRV_GetKeyboardLayoutList(INT size, HKL *hkl)
1836 {
1837     INT i;
1838
1839     TRACE("%d, %p\n", size, hkl);
1840
1841     if (!size)
1842     {
1843         size = 4096; /* hope we will never have that many */
1844         hkl = NULL;
1845     }
1846
1847     for (i = 0; main_key_tab[i].comment && (i < size); i++)
1848     {
1849         if (hkl)
1850         {
1851             ULONG_PTR layout = main_key_tab[i].lcid;
1852             LANGID langid;
1853
1854             /* see comment for GetKeyboardLayout */
1855             langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1856             if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1857                 layout |= 0xe001 << 16; /* FIXME */
1858             else
1859                 layout |= layout << 16;
1860
1861             hkl[i] = (HKL)layout;
1862         }
1863     }
1864     return i;
1865 }
1866
1867
1868 /***********************************************************************
1869  *              GetKeyboardLayout (X11DRV.@)
1870  */
1871 HKL X11DRV_GetKeyboardLayout(DWORD dwThreadid)
1872 {
1873     ULONG_PTR layout;
1874     LANGID langid;
1875
1876     if (dwThreadid && dwThreadid != GetCurrentThreadId())
1877         FIXME("couldn't return keyboard layout for thread %04x\n", dwThreadid);
1878
1879 #if 0
1880     layout = main_key_tab[kbd_layout].lcid;
1881 #else
1882     /* FIXME:
1883      * Winword uses return value of GetKeyboardLayout as a codepage
1884      * to translate ANSI keyboard messages to unicode. But we have
1885      * a problem with it: for instance Polish keyboard layout is
1886      * identical to the US one, and therefore instead of the Polish
1887      * locale id we return the US one.
1888      */
1889     layout = GetUserDefaultLCID();
1890 #endif
1891     /* 
1892      * Microsoft Office expects this value to be something specific
1893      * for Japanese and Korean Windows with an IME the value is 0xe001
1894      * We should probably check to see if an IME exists and if so then
1895      * set this word properly.
1896      */
1897     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1898     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1899         layout |= 0xe001 << 16; /* FIXME */
1900     else
1901         layout |= layout << 16;
1902
1903     return (HKL)layout;
1904 }
1905
1906
1907 /***********************************************************************
1908  *              GetKeyboardLayoutName (X11DRV.@)
1909  */
1910 BOOL X11DRV_GetKeyboardLayoutName(LPWSTR name)
1911 {
1912     static const WCHAR formatW[] = {'%','0','8','l','x',0};
1913     DWORD layout;
1914     LANGID langid;
1915
1916     layout = main_key_tab[kbd_layout].lcid;
1917     /* see comment for GetKeyboardLayout */
1918     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1919     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1920         layout |= 0xe001 << 16; /* FIXME */
1921     else
1922         layout |= layout << 16;
1923
1924     sprintfW(name, formatW, layout);
1925     TRACE("returning %s\n", debugstr_w(name));
1926     return TRUE;
1927 }
1928
1929
1930 /***********************************************************************
1931  *              LoadKeyboardLayout (X11DRV.@)
1932  */
1933 HKL X11DRV_LoadKeyboardLayout(LPCWSTR name, UINT flags)
1934 {
1935     FIXME("%s, %04x: stub!\n", debugstr_w(name), flags);
1936     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1937     return 0;
1938 }
1939
1940
1941 /***********************************************************************
1942  *              UnloadKeyboardLayout (X11DRV.@)
1943  */
1944 BOOL X11DRV_UnloadKeyboardLayout(HKL hkl)
1945 {
1946     FIXME("%p: stub!\n", hkl);
1947     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1948     return FALSE;
1949 }
1950
1951
1952 /***********************************************************************
1953  *              ActivateKeyboardLayout (X11DRV.@)
1954  */
1955 HKL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags)
1956 {
1957     FIXME("%p, %04x: stub!\n", hkl, flags);
1958     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1959     return 0;
1960 }
1961
1962
1963 /***********************************************************************
1964  *           X11DRV_MappingNotify
1965  */
1966 void X11DRV_MappingNotify( HWND dummy, XEvent *event )
1967 {
1968     HWND hwnd;
1969
1970     wine_tsx11_lock();
1971     XRefreshKeyboardMapping(&event->xmapping);
1972     wine_tsx11_unlock();
1973     X11DRV_InitKeyboard( event->xmapping.display );
1974
1975     hwnd = GetFocus();
1976     if (!hwnd) hwnd = GetActiveWindow();
1977     PostMessageW(hwnd, WM_INPUTLANGCHANGEREQUEST,
1978                  0 /*FIXME*/, (LPARAM)X11DRV_GetKeyboardLayout(0));
1979 }
1980
1981
1982 /***********************************************************************
1983  *              VkKeyScanEx (X11DRV.@)
1984  *
1985  * Note: Windows ignores HKL parameter and uses current active layout instead
1986  */
1987 SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
1988 {
1989     Display *display = thread_init_display();
1990     KeyCode keycode;
1991     KeySym keysym;
1992     int i, index;
1993     CHAR cChar;
1994     SHORT ret;
1995
1996     /* FIXME: what happens if wChar is not a Latin1 character and CP_UNIXCP
1997      * is UTF-8 (multibyte encoding)?
1998      */
1999     if (!WideCharToMultiByte(CP_UNIXCP, 0, &wChar, 1, &cChar, 1, NULL, NULL))
2000     {
2001         WARN("no translation from unicode to CP_UNIXCP for 0x%02x\n", wChar);
2002         return -1;
2003     }
2004
2005     TRACE("wChar 0x%02x -> cChar '%c'\n", wChar, cChar);
2006
2007     /* char->keysym (same for ANSI chars) */
2008     keysym = (unsigned char)cChar; /* (!) cChar is signed */
2009     if (keysym <= 27) keysym += 0xFF00; /* special chars : return, backspace... */
2010
2011     wine_tsx11_lock();
2012     keycode = XKeysymToKeycode(display, keysym);  /* keysym -> keycode */
2013     if (!keycode)
2014     {
2015         if (keysym >= 0xFF00) /* Windows returns 0x0240 + cChar in this case */
2016         {
2017             ret = 0x0240 + cChar; /* 0x0200 indicates a control character */
2018             TRACE(" ... returning ctrl char %#.2x\n", ret);
2019             wine_tsx11_unlock();
2020             return ret;
2021         }
2022         /* It didn't work ... let's try with deadchar code. */
2023         TRACE("retrying with | 0xFE00\n");
2024         keycode = XKeysymToKeycode(display, keysym | 0xFE00);
2025     }
2026     wine_tsx11_unlock();
2027
2028     TRACE("'%c'(%#lx, %lu): got keycode %#.2x (%d)\n",
2029             cChar, keysym, keysym, keycode, keycode);
2030
2031     /* keycode -> (keyc2vkey) vkey */
2032     ret = keyc2vkey[keycode];
2033
2034     if (!keycode || !ret)
2035     {
2036         TRACE("keycode for '%c' not found, returning -1\n", cChar);
2037         return -1;
2038     }
2039
2040     index = -1;
2041     wine_tsx11_lock();
2042     for (i = 0; i < 4; i++) /* find shift state */
2043     {
2044         if (XKeycodeToKeysym(display, keycode, i) == keysym)
2045         {
2046             index = i;
2047             break;
2048         }
2049     }
2050     wine_tsx11_unlock();
2051
2052     switch (index)
2053     {
2054         default:
2055         case -1:
2056             WARN("Keysym %lx not found while parsing the keycode table\n", keysym);
2057             return -1;
2058
2059         case 0: break;
2060         case 1: ret += 0x0100; break;
2061         case 2: ret += 0x0600; break;
2062         case 3: ret += 0x0700; break;
2063     }
2064     /*
2065       index : 0     adds 0x0000
2066       index : 1     adds 0x0100 (shift)
2067       index : ?     adds 0x0200 (ctrl)
2068       index : 2     adds 0x0600 (ctrl+alt)
2069       index : 3     adds 0x0700 (ctrl+alt+shift)
2070      */
2071
2072     TRACE(" ... returning %#.2x\n", ret);
2073     return ret;
2074 }
2075
2076 /***********************************************************************
2077  *              MapVirtualKeyEx (X11DRV.@)
2078  */
2079 UINT X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
2080 {
2081     Display *display = thread_init_display();
2082
2083 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
2084
2085     TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl);
2086     if (hkl != X11DRV_GetKeyboardLayout(0))
2087         FIXME("keyboard layout %p is not supported\n", hkl);
2088
2089     switch(wMapType)
2090     {
2091         case MAPVK_VK_TO_VSC: /* vkey-code to scan-code */
2092         case MAPVK_VK_TO_VSC_EX:
2093         {
2094             int keyc;
2095
2096             switch (wCode)
2097             {
2098                 case VK_SHIFT: wCode = VK_LSHIFT; break;
2099                 case VK_CONTROL: wCode = VK_LCONTROL; break;
2100                 case VK_MENU: wCode = VK_LMENU; break;
2101             }
2102
2103             /* let's do vkey -> keycode -> scan */
2104             for (keyc = min_keycode; keyc <= max_keycode; keyc++)
2105                 if ((keyc2vkey[keyc] & 0xFF) == wCode) break;
2106
2107             if (keyc > max_keycode)
2108             {
2109                 TRACE("returning no scan-code.\n");
2110                 return 0;
2111             }
2112             returnMVK (keyc2scan[keyc] & 0xFF);
2113         }
2114         case MAPVK_VSC_TO_VK: /* scan-code to vkey-code */
2115         case MAPVK_VSC_TO_VK_EX:
2116         {
2117             int keyc;
2118             UINT vkey = 0;
2119
2120             /* let's do scan -> keycode -> vkey */
2121             for (keyc = min_keycode; keyc <= max_keycode; keyc++)
2122                 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
2123                 {
2124                     vkey = keyc2vkey[keyc] & 0xFF;
2125                     /* Only stop if it's not a numpad vkey; otherwise keep
2126                        looking for a potential better vkey. */
2127                     if (vkey && (vkey < VK_NUMPAD0 || VK_DIVIDE < vkey))
2128                         break;
2129                 }
2130
2131             if (vkey == 0)
2132             {
2133                 TRACE("returning no vkey-code.\n");
2134                 return 0;
2135             }
2136
2137             if (wMapType == MAPVK_VSC_TO_VK)
2138                 switch (vkey)
2139                 {
2140                     case VK_LSHIFT:
2141                     case VK_RSHIFT:
2142                         vkey = VK_SHIFT; break;
2143                     case VK_LCONTROL:
2144                     case VK_RCONTROL:
2145                         vkey = VK_CONTROL; break;
2146                     case VK_LMENU:
2147                     case VK_RMENU:
2148                         vkey = VK_MENU; break;
2149                 }
2150
2151             returnMVK (vkey);
2152         }
2153                 case MAPVK_VK_TO_CHAR: /* vkey-code to unshifted ANSI code */
2154                 {
2155                         /* we still don't know what "unshifted" means. in windows VK_W (0x57)
2156                          * returns 0x57, which is upercase 'W'. So we have to return the uppercase
2157                          * key.. Looks like something is wrong with the MS docs?
2158                          * This is only true for letters, for example VK_0 returns '0' not ')'.
2159                          * - hence we use the lock mask to ensure this happens.
2160                          */
2161                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
2162                         XKeyEvent e;
2163                         KeySym keysym;
2164                         int keyc, len;
2165                         char s[10];
2166
2167                         e.display = display;
2168                         e.state = 0;
2169                         e.keycode = 0;
2170
2171                         wine_tsx11_lock();
2172
2173                         /* We exit on the first keycode found, to speed up the thing. */
2174                         for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2175                         { /* Find a keycode that could have generated this virtual key */
2176                             if  ((keyc2vkey[keyc] & 0xFF) == wCode)
2177                             { /* We filter the extended bit, we don't know it */
2178                                 e.keycode = keyc; /* Store it temporarily */
2179                                 if ((EVENT_event_to_vkey(0,&e) & 0xFF) != wCode) {
2180                                     e.keycode = 0; /* Wrong one (ex: because of the NumLock
2181                                          state), so set it to 0, we'll find another one */
2182                                 }
2183                             }
2184                         }
2185
2186                         if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
2187                           e.keycode = XKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
2188
2189                         if (wCode==VK_DECIMAL)
2190                           e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2191
2192                         if (!e.keycode)
2193                         {
2194                           WARN("Unknown virtual key %X !!!\n", wCode);
2195                           wine_tsx11_unlock();
2196                           return 0; /* whatever */
2197                         }
2198                         TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2199
2200                         len = XLookupString(&e, s, sizeof(s), &keysym, NULL);
2201                         wine_tsx11_unlock();
2202
2203                         if (len)
2204                         {
2205                             WCHAR wch;
2206                             if (MultiByteToWideChar(CP_UNIXCP, 0, s, len, &wch, 1))
2207                                 returnMVK(toupperW(wch));
2208                         }
2209                         TRACE("returning no ANSI.\n");
2210                         return 0;
2211                 }
2212                 default: /* reserved */
2213                         FIXME("Unknown wMapType %d !\n", wMapType);
2214                         return 0;
2215         }
2216         return 0;
2217 }
2218
2219 /***********************************************************************
2220  *              GetKeyNameText (X11DRV.@)
2221  */
2222 INT X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
2223 {
2224   Display *display = thread_init_display();
2225   int vkey, ansi, scanCode;
2226   KeyCode keyc;
2227   int keyi;
2228   KeySym keys;
2229   char *name;
2230
2231   scanCode = lParam >> 16;
2232   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
2233
2234   vkey = X11DRV_MapVirtualKeyEx(scanCode, MAPVK_VSC_TO_VK_EX, X11DRV_GetKeyboardLayout(0));
2235
2236   /*  handle "don't care" bit (0x02000000) */
2237   if (!(lParam & 0x02000000)) {
2238     switch (vkey) {
2239          case VK_RSHIFT:
2240                           /* R-Shift is "special" - it is an extended key with separate scan code */
2241                           scanCode |= 0x100;
2242          case VK_LSHIFT:
2243                           vkey = VK_SHIFT;
2244                           break;
2245        case VK_LCONTROL:
2246        case VK_RCONTROL:
2247                           vkey = VK_CONTROL;
2248                           break;
2249           case VK_LMENU:
2250           case VK_RMENU:
2251                           vkey = VK_MENU;
2252                           break;
2253     }
2254   }
2255
2256   ansi = X11DRV_MapVirtualKeyEx(vkey, MAPVK_VK_TO_CHAR, X11DRV_GetKeyboardLayout(0));
2257   TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
2258
2259   /* first get the name of the "regular" keys which is the Upper case
2260      value of the keycap imprint.                                     */
2261   if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
2262        (scanCode != 0x137) &&   /* PrtScn   */
2263        (scanCode != 0x135) &&   /* numpad / */
2264        (scanCode != 0x37 ) &&   /* numpad * */
2265        (scanCode != 0x4a ) &&   /* numpad - */
2266        (scanCode != 0x4e ) )    /* numpad + */
2267       {
2268         if ((nSize >= 2) && lpBuffer)
2269         {
2270           *lpBuffer = toupperW((WCHAR)ansi);
2271           *(lpBuffer+1) = 0;
2272           return 1;
2273         }
2274      else
2275         return 0;
2276   }
2277
2278   /* FIXME: horrible hack to fix function keys. Windows reports scancode
2279             without "extended-key" flag. However Wine generates scancode
2280             *with* "extended-key" flag. Seems to occur *only* for the
2281             function keys. Soooo.. We will leave the table alone and
2282             fudge the lookup here till the other part is found and fixed!!! */
2283
2284   if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
2285        (scanCode == 0x157) || (scanCode == 0x158))
2286     scanCode &= 0xff;   /* remove "extended-key" flag for Fx keys */
2287
2288   /* let's do scancode -> keycode -> keysym -> String */
2289
2290   for (keyi=min_keycode; keyi<=max_keycode; keyi++)
2291       if ((keyc2scan[keyi]) == scanCode)
2292          break;
2293   if (keyi <= max_keycode)
2294   {
2295       wine_tsx11_lock();
2296       keyc = (KeyCode) keyi;
2297       keys = XKeycodeToKeysym(display, keyc, 0);
2298       name = XKeysymToString(keys);
2299       wine_tsx11_unlock();
2300       TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
2301             scanCode, keyc, (int)keys, name);
2302       if (lpBuffer && nSize && name)
2303       {
2304           MultiByteToWideChar(CP_UNIXCP, 0, name, -1, lpBuffer, nSize);
2305           lpBuffer[nSize - 1] = 0;
2306           return 1;
2307       }
2308   }
2309
2310   /* Finally issue WARN for unknown keys   */
2311
2312   WARN("(%08x,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
2313   if (lpBuffer && nSize)
2314     *lpBuffer = 0;
2315   return 0;
2316 }
2317
2318 /***********************************************************************
2319  *              X11DRV_KEYBOARD_MapDeadKeysym
2320  */
2321 static char KEYBOARD_MapDeadKeysym(KeySym keysym)
2322 {
2323         switch (keysym)
2324             {
2325         /* symbolic ASCII is the same as defined in rfc1345 */
2326 #ifdef XK_dead_tilde
2327             case XK_dead_tilde :
2328 #endif
2329             case 0x1000FE7E : /* Xfree's XK_Dtilde */
2330                 return '~';     /* '? */
2331 #ifdef XK_dead_acute
2332             case XK_dead_acute :
2333 #endif
2334             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
2335                 return 0xb4;    /* '' */
2336 #ifdef XK_dead_circumflex
2337             case XK_dead_circumflex:
2338 #endif
2339             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
2340                 return '^';     /* '> */
2341 #ifdef XK_dead_grave
2342             case XK_dead_grave :
2343 #endif
2344             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
2345                 return '`';     /* '! */
2346 #ifdef XK_dead_diaeresis
2347             case XK_dead_diaeresis :
2348 #endif
2349             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
2350                 return 0xa8;    /* ': */
2351 #ifdef XK_dead_cedilla
2352             case XK_dead_cedilla :
2353                 return 0xb8;    /* ', */
2354 #endif
2355 #ifdef XK_dead_macron
2356             case XK_dead_macron :
2357                 return '-';     /* 'm isn't defined on iso-8859-x */
2358 #endif
2359 #ifdef XK_dead_breve
2360             case XK_dead_breve :
2361                 return 0xa2;    /* '( */
2362 #endif
2363 #ifdef XK_dead_abovedot
2364             case XK_dead_abovedot :
2365                 return 0xff;    /* '. */
2366 #endif
2367 #ifdef XK_dead_abovering
2368             case XK_dead_abovering :
2369                 return '0';     /* '0 isn't defined on iso-8859-x */
2370 #endif
2371 #ifdef XK_dead_doubleacute
2372             case XK_dead_doubleacute :
2373                 return 0xbd;    /* '" */
2374 #endif
2375 #ifdef XK_dead_caron
2376             case XK_dead_caron :
2377                 return 0xb7;    /* '< */
2378 #endif
2379 #ifdef XK_dead_ogonek
2380             case XK_dead_ogonek :
2381                 return 0xb2;    /* '; */
2382 #endif
2383 /* FIXME: I don't know this three.
2384             case XK_dead_iota :
2385                 return 'i';
2386             case XK_dead_voiced_sound :
2387                 return 'v';
2388             case XK_dead_semivoiced_sound :
2389                 return 's';
2390 */
2391             }
2392         TRACE("no character for dead keysym 0x%08lx\n",keysym);
2393         return 0;
2394 }
2395
2396 /***********************************************************************
2397  *              ToUnicodeEx (X11DRV.@)
2398  *
2399  * The ToUnicode function translates the specified virtual-key code and keyboard
2400  * state to the corresponding Windows character or characters.
2401  *
2402  * If the specified key is a dead key, the return value is negative. Otherwise,
2403  * it is one of the following values:
2404  * Value        Meaning
2405  * 0    The specified virtual key has no translation for the current state of the keyboard.
2406  * 1    One Windows character was copied to the buffer.
2407  * 2    Two characters were copied to the buffer. This usually happens when a
2408  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
2409  *      be composed with the specified virtual key to form a single character.
2410  *
2411  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
2412  *
2413  */
2414 INT X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
2415                      LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
2416 {
2417     Display *display = thread_init_display();
2418     XKeyEvent e;
2419     KeySym keysym = 0;
2420     INT ret;
2421     int keyc;
2422     char lpChar[10];
2423     HWND focus;
2424     XIC xic;
2425     Status status = 0;
2426
2427     if (scanCode & 0x8000)
2428     {
2429         TRACE("Key UP, doing nothing\n" );
2430         return 0;
2431     }
2432
2433     if (hkl != X11DRV_GetKeyboardLayout(0))
2434         FIXME("keyboard layout %p is not supported\n", hkl);
2435
2436     if ((lpKeyState[VK_MENU] & 0x80) && (lpKeyState[VK_CONTROL] & 0x80))
2437     {
2438         TRACE("Ctrl+Alt+[key] won't generate a character\n");
2439         return 0;
2440     }
2441
2442     e.display = display;
2443     e.keycode = 0;
2444     e.state = 0;
2445     e.type = KeyPress;
2446
2447     focus = GetFocus();
2448     if (focus) focus = GetAncestor( focus, GA_ROOT );
2449     if (!focus) focus = GetActiveWindow();
2450     e.window = X11DRV_get_whole_window( focus );
2451     xic = X11DRV_get_ic( focus );
2452
2453     if (lpKeyState[VK_SHIFT] & 0x80)
2454     {
2455         TRACE("ShiftMask = %04x\n", ShiftMask);
2456         e.state |= ShiftMask;
2457     }
2458     if (lpKeyState[VK_CAPITAL] & 0x01)
2459     {
2460         TRACE("LockMask = %04x\n", LockMask);
2461         e.state |= LockMask;
2462     }
2463     if (lpKeyState[VK_CONTROL] & 0x80)
2464     {
2465         TRACE("ControlMask = %04x\n", ControlMask);
2466         e.state |= ControlMask;
2467     }
2468     if (lpKeyState[VK_NUMLOCK] & 0x01)
2469     {
2470         TRACE("NumLockMask = %04x\n", NumLockMask);
2471         e.state |= NumLockMask;
2472     }
2473
2474     /* Restore saved AltGr state */
2475     TRACE("AltGrMask = %04x\n", AltGrMask);
2476     e.state |= AltGrMask;
2477
2478     TRACE_(key)("(%04X, %04X) : faked state = 0x%04x\n",
2479                 virtKey, scanCode, e.state);
2480     wine_tsx11_lock();
2481     /* We exit on the first keycode found, to speed up the thing. */
2482     for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2483       { /* Find a keycode that could have generated this virtual key */
2484           if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
2485           { /* We filter the extended bit, we don't know it */
2486               e.keycode = keyc; /* Store it temporarily */
2487               if ((EVENT_event_to_vkey(xic,&e) & 0xFF) != virtKey) {
2488                   e.keycode = 0; /* Wrong one (ex: because of the NumLock
2489                          state), so set it to 0, we'll find another one */
2490               }
2491           }
2492       }
2493
2494     if (virtKey >= VK_LEFT && virtKey <= VK_DOWN)
2495         e.keycode = XKeysymToKeycode(e.display, virtKey - VK_LEFT + XK_Left);
2496
2497     if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
2498         e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
2499
2500     if (virtKey==VK_DECIMAL)
2501         e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2502
2503     if (virtKey==VK_SEPARATOR)
2504         e.keycode = XKeysymToKeycode(e.display, XK_KP_Separator);
2505
2506     if (!e.keycode && virtKey != VK_NONAME)
2507       {
2508         WARN("Unknown virtual key %X !!!\n", virtKey);
2509         wine_tsx11_unlock();
2510         return 0;
2511       }
2512     else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2513
2514     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
2515                 e.type, e.window, e.state, e.keycode);
2516
2517     /* Clients should pass only KeyPress events to XmbLookupString,
2518      * e.type was set to KeyPress above.
2519      */
2520     if (xic)
2521         ret = XmbLookupString(xic, &e, lpChar, sizeof(lpChar), &keysym, &status);
2522     else
2523         ret = XLookupString(&e, lpChar, sizeof(lpChar), &keysym, NULL);
2524     wine_tsx11_unlock();
2525
2526     TRACE_(key)("nbyte = %d, status 0x%x\n", ret, status);
2527
2528     if (status == XBufferOverflow)
2529         ERR("Buffer Overflow need %d!\n", ret);
2530
2531     if (TRACE_ON(key))
2532     {
2533         const char *ksname;
2534
2535         wine_tsx11_lock();
2536         ksname = XKeysymToString(keysym);
2537         wine_tsx11_unlock();
2538         if (!ksname) ksname = "No Name";
2539         TRACE_(key)("%s : keysym=%lX (%s), # of chars=%d / %s\n",
2540                     (e.type == KeyPress) ? "KeyPress" : "KeyRelease",
2541                     keysym, ksname, ret, debugstr_an(lpChar, ret));
2542     }
2543
2544     if (ret == 0)
2545     {
2546         char dead_char;
2547
2548 #ifdef XK_EuroSign
2549         /* An ugly hack for EuroSign: X can't translate it to a character
2550            for some locales. */
2551         if (keysym == XK_EuroSign)
2552         {
2553             bufW[0] = 0x20AC;
2554             ret = 1;
2555             goto found;
2556         }
2557 #endif
2558         /* Special case: X turns shift-tab into ISO_Left_Tab. */
2559         /* Here we change it back. */
2560         if (keysym == XK_ISO_Left_Tab)
2561         {
2562             bufW[0] = 0x09;
2563             ret = 1;
2564             goto found;
2565         }
2566
2567         dead_char = KEYBOARD_MapDeadKeysym(keysym);
2568         if (dead_char)
2569         {
2570             MultiByteToWideChar(CP_UNIXCP, 0, &dead_char, 1, bufW, bufW_size);
2571             ret = -1;
2572             goto found;
2573         }
2574
2575         if (keysym >= 0x01000100 && keysym <= 0x0100ffff)
2576         {
2577             /* Unicode direct mapping */
2578             bufW[0] = keysym & 0xffff;
2579             ret = 1;
2580             goto found;
2581         }
2582         else if ((keysym >> 8) == 0x1008FF) {
2583             bufW[0] = 0;
2584             ret = 0;
2585             goto found;
2586         }
2587         else
2588             {
2589             const char *ksname;
2590
2591             wine_tsx11_lock();
2592             ksname = XKeysymToString(keysym);
2593             wine_tsx11_unlock();
2594             if (!ksname)
2595                 ksname = "No Name";
2596             if ((keysym >> 8) != 0xff)
2597                 {
2598                 WARN("no char for keysym %04lX (%s) :\n",
2599                     keysym, ksname);
2600                 WARN("virtKey=%X, scanCode=%X, keycode=%X, state=%X\n",
2601                     virtKey, scanCode, e.keycode, e.state);
2602                 }
2603             }
2604         }
2605     else {  /* ret != 0 */
2606         /* We have a special case to handle : Shift + arrow, shift + home, ...
2607            X returns a char for it, but Windows doesn't. Let's eat it. */
2608         if (!(e.state & NumLockMask)  /* NumLock is off */
2609             && (e.state & ShiftMask) /* Shift is pressed */
2610             && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
2611         {
2612             lpChar[0] = 0;
2613             ret = 0;
2614         }
2615
2616         /* more areas where X returns characters but Windows does not
2617            CTRL + number or CTRL + symbol */
2618         if (e.state & ControlMask)
2619         {
2620             if (((keysym>=33) && (keysym < 'A')) ||
2621                 ((keysym > 'Z') && (keysym < 'a')))
2622             {
2623                 lpChar[0] = 0;
2624                 ret = 0;
2625             }
2626         }
2627
2628         /* We have another special case for delete key (XK_Delete) on an
2629          extended keyboard. X returns a char for it, but Windows doesn't */
2630         if (keysym == XK_Delete)
2631         {
2632             lpChar[0] = 0;
2633             ret = 0;
2634         }
2635         else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
2636                 && (keysym == XK_KP_Decimal))
2637         {
2638             lpChar[0] = 0;
2639             ret = 0;
2640         }
2641         else if((lpKeyState[VK_CONTROL] & 0x80) /* Control is pressed */
2642                 && (keysym == XK_Return || keysym == XK_KP_Enter))
2643         {
2644             lpChar[0] = '\n';
2645             ret = 1;
2646         }
2647
2648         /* Hack to detect an XLookupString hard-coded to Latin1 */
2649         if (ret == 1 && keysym >= 0x00a0 && keysym <= 0x00ff && (BYTE)lpChar[0] == keysym)
2650         {
2651             bufW[0] = (BYTE)lpChar[0];
2652             goto found;
2653         }
2654
2655         /* perform translation to unicode */
2656         if(ret)
2657         {
2658             TRACE_(key)("Translating char 0x%02x to unicode\n", *(BYTE *)lpChar);
2659             ret = MultiByteToWideChar(CP_UNIXCP, 0, lpChar, ret, bufW, bufW_size);
2660         }
2661     }
2662
2663 found:
2664     TRACE_(key)("ToUnicode about to return %d with char %x %s\n",
2665                 ret, (ret && bufW) ? bufW[0] : 0, bufW ? "" : "(no buffer)");
2666     return ret;
2667 }
2668
2669 /***********************************************************************
2670  *              Beep (X11DRV.@)
2671  */
2672 void X11DRV_Beep(void)
2673 {
2674     wine_tsx11_lock();
2675     XBell(gdi_display, 0);
2676     wine_tsx11_unlock();
2677 }