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