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