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