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