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