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