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