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