user32: Fix GetKeyNameText returned length.
[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_LMENU,
1010     VK_RMENU, 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  *           set_async_key_state
1180  */
1181 static void set_async_key_state( const BYTE state[256] )
1182 {
1183     SERVER_START_REQ( set_key_state )
1184     {
1185         req->tid = GetCurrentThreadId();
1186         req->async = 1;
1187         wine_server_add_data( req, state, 256 );
1188         wine_server_call( req );
1189     }
1190     SERVER_END_REQ;
1191 }
1192
1193 static void update_key_state( BYTE *keystate, BYTE key, int down )
1194 {
1195     if (down)
1196     {
1197         if (!(keystate[key] & 0x80)) keystate[key] ^= 0x01;
1198         keystate[key] |= 0x80;
1199     }
1200     else keystate[key] &= ~0x80;
1201 }
1202
1203 /***********************************************************************
1204  *           X11DRV_KeymapNotify
1205  *
1206  * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
1207  *
1208  * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
1209  * from wine to another application and back.
1210  * Toggle keys are handled in HandleEvent.
1211  */
1212 void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
1213 {
1214     int i, j;
1215     BYTE keystate[256];
1216     WORD vkey;
1217     BOOL changed = FALSE;
1218     struct {
1219         WORD vkey;
1220         BOOL pressed;
1221     } modifiers[6]; /* VK_LSHIFT through VK_RMENU are contiguous */
1222
1223     if (!get_async_key_state( keystate )) return;
1224
1225     memset(modifiers, 0, sizeof(modifiers));
1226
1227     /* the minimum keycode is always greater or equal to 8, so we can
1228      * skip the first 8 values, hence start at 1
1229      */
1230     for (i = 1; i < 32; i++)
1231     {
1232         for (j = 0; j < 8; j++)
1233         {
1234             int m;
1235
1236             vkey = keyc2vkey[(i * 8) + j];
1237
1238             switch(vkey & 0xff)
1239             {
1240             case VK_LMENU:
1241             case VK_RMENU:
1242             case VK_LCONTROL:
1243             case VK_RCONTROL:
1244             case VK_LSHIFT:
1245             case VK_RSHIFT:
1246                 m = (vkey & 0xff) - VK_LSHIFT;
1247                 /* Take the vkey from the first keycode we encounter for this modifier */
1248                 if (!modifiers[m].vkey) modifiers[m].vkey = vkey;
1249                 if (event->xkeymap.key_vector[i] & (1<<j)) modifiers[m].pressed = TRUE;
1250                 break;
1251             }
1252         }
1253     }
1254
1255     for (vkey = VK_LSHIFT; vkey <= VK_RMENU; vkey++)
1256     {
1257         int m = vkey - VK_LSHIFT;
1258         if (modifiers[m].vkey && !(keystate[vkey] & 0x80) != !modifiers[m].pressed)
1259         {
1260             TRACE( "Adjusting state for vkey %#.2x. State before %#.2x\n",
1261                    modifiers[m].vkey, keystate[vkey]);
1262
1263             update_key_state( keystate, vkey, modifiers[m].pressed );
1264             changed = TRUE;
1265         }
1266     }
1267
1268     if (!changed) return;
1269
1270     update_key_state( keystate, VK_CONTROL, (keystate[VK_LCONTROL] | keystate[VK_RCONTROL]) & 0x80 );
1271     update_key_state( keystate, VK_MENU, (keystate[VK_LMENU] | keystate[VK_RMENU]) & 0x80 );
1272     update_key_state( keystate, VK_SHIFT, (keystate[VK_LSHIFT] | keystate[VK_RSHIFT]) & 0x80 );
1273     set_async_key_state( keystate );
1274 }
1275
1276 static void update_lock_state( HWND hwnd, WORD vkey, UINT state, DWORD time )
1277 {
1278     BYTE keystate[256];
1279
1280     /* Note: X sets the below states on key down and clears them on key up.
1281        Windows triggers them on key down. */
1282
1283     if (!get_async_key_state( keystate )) return;
1284
1285     /* Adjust the CAPSLOCK state if it has been changed outside wine */
1286     if (!(keystate[VK_CAPITAL] & 0x01) != !(state & LockMask) && vkey != VK_CAPITAL)
1287     {
1288         DWORD flags = 0;
1289         if (keystate[VK_CAPITAL] & 0x80) flags ^= KEYEVENTF_KEYUP;
1290         TRACE("Adjusting CapsLock state (%#.2x)\n", keystate[VK_CAPITAL]);
1291         X11DRV_send_keyboard_input( hwnd, VK_CAPITAL, 0x3a, flags, time );
1292         X11DRV_send_keyboard_input( hwnd, VK_CAPITAL, 0x3a, flags ^ KEYEVENTF_KEYUP, time );
1293     }
1294
1295     /* Adjust the NUMLOCK state if it has been changed outside wine */
1296     if (!(keystate[VK_NUMLOCK] & 0x01) != !(state & NumLockMask) && (vkey & 0xff) != VK_NUMLOCK)
1297     {
1298         DWORD flags = KEYEVENTF_EXTENDEDKEY;
1299         if (keystate[VK_NUMLOCK] & 0x80) flags ^= KEYEVENTF_KEYUP;
1300         TRACE("Adjusting NumLock state (%#.2x)\n", keystate[VK_NUMLOCK]);
1301         X11DRV_send_keyboard_input( hwnd, VK_NUMLOCK, 0x45, flags, time );
1302         X11DRV_send_keyboard_input( hwnd, VK_NUMLOCK, 0x45, flags ^ KEYEVENTF_KEYUP, time );
1303     }
1304
1305     /* Adjust the SCROLLLOCK state if it has been changed outside wine */
1306     if (!(keystate[VK_SCROLL] & 0x01) != !(state & ScrollLockMask) && vkey != VK_SCROLL)
1307     {
1308         DWORD flags = 0;
1309         if (keystate[VK_SCROLL] & 0x80) flags ^= KEYEVENTF_KEYUP;
1310         TRACE("Adjusting ScrLock state (%#.2x)\n", keystate[VK_SCROLL]);
1311         X11DRV_send_keyboard_input( hwnd, VK_SCROLL, 0x46, flags, time );
1312         X11DRV_send_keyboard_input( hwnd, VK_SCROLL, 0x46, flags ^ KEYEVENTF_KEYUP, time );
1313     }
1314 }
1315
1316 /***********************************************************************
1317  *           X11DRV_KeyEvent
1318  *
1319  * Handle a X key event
1320  */
1321 void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
1322 {
1323     XKeyEvent *event = &xev->xkey;
1324     char buf[24];
1325     char *Str = buf;
1326     KeySym keysym = 0;
1327     WORD vkey = 0, bScan;
1328     DWORD dwFlags;
1329     int ascii_chars;
1330     XIC xic = X11DRV_get_ic( hwnd );
1331     DWORD event_time = EVENT_x11_time_to_win32_time(event->time);
1332     Status status = 0;
1333
1334     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode %u\n",
1335                 event->type, event->window, event->state, event->keycode);
1336
1337     if (event->type == KeyPress) update_user_time( event->time );
1338
1339     wine_tsx11_lock();
1340     /* Clients should pass only KeyPress events to XmbLookupString */
1341     if (xic && event->type == KeyPress)
1342     {
1343         ascii_chars = XmbLookupString(xic, event, buf, sizeof(buf), &keysym, &status);
1344         TRACE_(key)("XmbLookupString needs %i byte(s)\n", ascii_chars);
1345         if (status == XBufferOverflow)
1346         {
1347             Str = HeapAlloc(GetProcessHeap(), 0, ascii_chars);
1348             if (Str == NULL)
1349             {
1350                 ERR_(key)("Failed to allocate memory!\n");
1351                 wine_tsx11_unlock();
1352                 return;
1353             }
1354             ascii_chars = XmbLookupString(xic, event, Str, ascii_chars, &keysym, &status);
1355         }
1356     }
1357     else
1358         ascii_chars = XLookupString(event, buf, sizeof(buf), &keysym, NULL);
1359     wine_tsx11_unlock();
1360
1361     TRACE_(key)("nbyte = %d, status %d\n", ascii_chars, status);
1362
1363     if (status == XLookupChars)
1364     {
1365         X11DRV_XIMLookupChars( Str, ascii_chars );
1366         if (buf != Str)
1367             HeapFree(GetProcessHeap(), 0, Str);
1368         return;
1369     }
1370
1371     /* If XKB extensions are used, the state mask for AltGr will use the group
1372        index instead of the modifier mask. The group index is set in bits
1373        13-14 of the state field in the XKeyEvent structure. So if AltGr is
1374        pressed, look if the group index is different than 0. From XKB
1375        extension documentation, the group index for AltGr should be 2
1376        (event->state = 0x2000). It's probably better to not assume a
1377        predefined group index and find it dynamically
1378
1379        Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
1380     /* Save also all possible modifier states. */
1381     AltGrMask = event->state & (0x6000 | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
1382
1383     if (TRACE_ON(key)){
1384         const char *ksname;
1385
1386         wine_tsx11_lock();
1387         ksname = XKeysymToString(keysym);
1388         wine_tsx11_unlock();
1389         if (!ksname)
1390           ksname = "No Name";
1391         TRACE_(key)("%s : keysym=%lx (%s), # of chars=%d / %s\n",
1392                     (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
1393                     keysym, ksname, ascii_chars, debugstr_an(Str, ascii_chars));
1394     }
1395     if (buf != Str)
1396         HeapFree(GetProcessHeap(), 0, Str);
1397
1398     wine_tsx11_lock();
1399     vkey = EVENT_event_to_vkey(xic,event);
1400     /* X returns keycode 0 for composed characters */
1401     if (!vkey && ascii_chars) vkey = VK_NONAME;
1402     wine_tsx11_unlock();
1403
1404     TRACE_(key)("keycode %u converted to vkey 0x%X\n",
1405                 event->keycode, vkey);
1406
1407     if (!vkey) return;
1408
1409     dwFlags = 0;
1410     if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
1411     if ( vkey & 0x100 )              dwFlags |= KEYEVENTF_EXTENDEDKEY;
1412
1413     update_lock_state( hwnd, vkey, event->state, event_time );
1414
1415     bScan = keyc2scan[event->keycode] & 0xFF;
1416     TRACE_(key)("bScan = 0x%02x.\n", bScan);
1417
1418     X11DRV_send_keyboard_input( hwnd, vkey & 0xff, bScan, dwFlags, event_time );
1419 }
1420
1421 /**********************************************************************
1422  *              X11DRV_KEYBOARD_DetectLayout
1423  *
1424  * Called from X11DRV_InitKeyboard
1425  *  This routine walks through the defined keyboard layouts and selects
1426  *  whichever matches most closely.
1427  * X11 lock must be held.
1428  */
1429 static void
1430 X11DRV_KEYBOARD_DetectLayout( Display *display )
1431 {
1432   unsigned current, match, mismatch, seq, i, syms;
1433   int score, keyc, key, pkey, ok;
1434   KeySym keysym = 0;
1435   const char (*lkey)[MAIN_LEN][4];
1436   unsigned max_seq = 0;
1437   int max_score = 0, ismatch = 0;
1438   char ckey[256][4];
1439
1440   syms = keysyms_per_keycode;
1441   if (syms > 4) {
1442     WARN("%d keysyms per keycode not supported, set to 4\n", syms);
1443     syms = 4;
1444   }
1445
1446   memset( ckey, 0, sizeof(ckey) );
1447   for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1448       /* get data for keycode from X server */
1449       for (i = 0; i < syms; i++) {
1450         if (!(keysym = keycode_to_keysym (display, keyc, i))) continue;
1451         /* Allow both one-byte and two-byte national keysyms */
1452         if ((keysym < 0x8000) && (keysym != ' '))
1453         {
1454 #ifdef HAVE_XKB
1455             if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[keyc][i], 1, NULL))
1456 #endif
1457             {
1458                 TRACE("XKB could not translate keysym %04lx\n", keysym);
1459                 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1460                  * with appropriate ShiftMask and Mode_switch, use XLookupString
1461                  * to get character in the local encoding.
1462                  */
1463                 ckey[keyc][i] = keysym & 0xFF;
1464             }
1465         }
1466         else {
1467           ckey[keyc][i] = KEYBOARD_MapDeadKeysym(keysym);
1468         }
1469       }
1470   }
1471
1472   for (current = 0; main_key_tab[current].comment; current++) {
1473     TRACE("Attempting to match against \"%s\"\n", main_key_tab[current].comment);
1474     match = 0;
1475     mismatch = 0;
1476     score = 0;
1477     seq = 0;
1478     lkey = main_key_tab[current].key;
1479     pkey = -1;
1480     for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1481       if (ckey[keyc][0]) {
1482         /* search for a match in layout table */
1483         /* right now, we just find an absolute match for defined positions */
1484         /* (undefined positions are ignored, so if it's defined as "3#" in */
1485         /* the table, it's okay that the X server has "3#£", for example) */
1486         /* however, the score will be higher for longer matches */
1487         for (key = 0; key < MAIN_LEN; key++) {
1488           for (ok = 0, i = 0; (ok >= 0) && (i < syms); i++) {
1489             if ((*lkey)[key][i] && ((*lkey)[key][i] == ckey[keyc][i]))
1490               ok++;
1491             if ((*lkey)[key][i] && ((*lkey)[key][i] != ckey[keyc][i]))
1492               ok = -1;
1493           }
1494           if (ok > 0) {
1495             score += ok;
1496             break;
1497           }
1498         }
1499         /* count the matches and mismatches */
1500         if (ok > 0) {
1501           match++;
1502           /* and how much the keycode order matches */
1503           if (key > pkey) seq++;
1504           pkey = key;
1505         } else {
1506           /* print spaces instead of \0's */
1507           char str[5];
1508           for (i = 0; i < 4; i++) str[i] = ckey[keyc][i] ? ckey[keyc][i] : ' ';
1509           str[4] = 0;
1510           TRACE_(key)("mismatch for keycode %u, got %s\n", keyc, str);
1511           mismatch++;
1512           score -= syms;
1513         }
1514       }
1515     }
1516     TRACE("matches=%d, mismatches=%d, seq=%d, score=%d\n",
1517            match, mismatch, seq, score);
1518     if ((score > max_score) ||
1519         ((score == max_score) && (seq > max_seq))) {
1520       /* best match so far */
1521       kbd_layout = current;
1522       max_score = score;
1523       max_seq = seq;
1524       ismatch = !mismatch;
1525     }
1526   }
1527   /* we're done, report results if necessary */
1528   if (!ismatch)
1529     WARN("Using closest match (%s) for scan/virtual codes mapping.\n",
1530         main_key_tab[kbd_layout].comment);
1531
1532   TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment);
1533 }
1534
1535 static HKL get_locale_kbd_layout(void)
1536 {
1537     ULONG_PTR layout;
1538     LANGID langid;
1539
1540     /* FIXME:
1541      *
1542      * layout = main_key_tab[kbd_layout].lcid;
1543      *
1544      * Winword uses return value of GetKeyboardLayout as a codepage
1545      * to translate ANSI keyboard messages to unicode. But we have
1546      * a problem with it: for instance Polish keyboard layout is
1547      * identical to the US one, and therefore instead of the Polish
1548      * locale id we return the US one.
1549      */
1550
1551     layout = GetUserDefaultLCID();
1552
1553     /*
1554      * Microsoft Office expects this value to be something specific
1555      * for Japanese and Korean Windows with an IME the value is 0xe001
1556      * We should probably check to see if an IME exists and if so then
1557      * set this word properly.
1558      */
1559     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1560     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1561         layout |= 0xe001 << 16; /* IME */
1562     else
1563         layout |= layout << 16;
1564
1565     return (HKL)layout;
1566 }
1567
1568 /***********************************************************************
1569  *     GetKeyboardLayoutName (X11DRV.@)
1570  */
1571 BOOL CDECL X11DRV_GetKeyboardLayoutName(LPWSTR name)
1572 {
1573     static const WCHAR formatW[] = {'%','0','8','x',0};
1574     DWORD layout;
1575
1576     layout = HandleToUlong( get_locale_kbd_layout() );
1577     if (HIWORD(layout) == LOWORD(layout)) layout = LOWORD(layout);
1578     sprintfW(name, formatW, layout);
1579     TRACE("returning %s\n", debugstr_w(name));
1580     return TRUE;
1581 }
1582
1583 static void set_kbd_layout_preload_key(void)
1584 {
1585     static const WCHAR preload[] =
1586         {'K','e','y','b','o','a','r','d',' ','L','a','y','o','u','t','\\','P','r','e','l','o','a','d',0};
1587     static const WCHAR one[] = {'1',0};
1588
1589     HKEY hkey;
1590     WCHAR layout[KL_NAMELENGTH];
1591
1592     if (RegCreateKeyExW(HKEY_CURRENT_USER, preload, 0, NULL, 0, KEY_ALL_ACCESS, NULL, &hkey, NULL))
1593         return;
1594
1595     if (!RegQueryValueExW(hkey, one, NULL, NULL, NULL, NULL))
1596     {
1597         RegCloseKey(hkey);
1598         return;
1599     }
1600     if (X11DRV_GetKeyboardLayoutName(layout))
1601         RegSetValueExW(hkey, one, 0, REG_SZ, (const BYTE *)layout, sizeof(layout));
1602
1603     RegCloseKey(hkey);
1604 }
1605
1606 /**********************************************************************
1607  *              X11DRV_InitKeyboard
1608  */
1609 void X11DRV_InitKeyboard( Display *display )
1610 {
1611     KeySym *ksp;
1612     XModifierKeymap *mmp;
1613     KeySym keysym;
1614     KeyCode *kcp;
1615     XKeyEvent e2;
1616     WORD scan, vkey;
1617     int keyc, i, keyn, syms;
1618     char ckey[4]={0,0,0,0};
1619     const char (*lkey)[MAIN_LEN][4];
1620     char vkey_used[256] = { 0 };
1621
1622     /* Ranges of OEM, function key, and character virtual key codes.
1623      * Don't include those handled specially in X11DRV_ToUnicodeEx and
1624      * X11DRV_MapVirtualKeyEx, like VK_NUMPAD0 - VK_DIVIDE. */
1625     static const struct {
1626         WORD first, last;
1627     } vkey_ranges[] = {
1628         { VK_OEM_1, VK_OEM_3 },
1629         { VK_OEM_4, VK_ICO_00 },
1630         { 0xe6, 0xe6 },
1631         { 0xe9, 0xf5 },
1632         { VK_OEM_NEC_EQUAL, VK_OEM_NEC_EQUAL },
1633         { VK_F1, VK_F24 },
1634         { 0x30, 0x39 }, /* VK_0 - VK_9 */
1635         { 0x41, 0x5a }, /* VK_A - VK_Z */
1636         { 0, 0 }
1637     };
1638     int vkey_range;
1639
1640     set_kbd_layout_preload_key();
1641
1642     wine_tsx11_lock();
1643     XDisplayKeycodes(display, &min_keycode, &max_keycode);
1644     ksp = XGetKeyboardMapping(display, min_keycode,
1645                               max_keycode + 1 - min_keycode, &keysyms_per_keycode);
1646     /* We are only interested in keysyms_per_keycode.
1647        There is no need to hold a local copy of the keysyms table */
1648     XFree(ksp);
1649
1650     mmp = XGetModifierMapping(display);
1651     kcp = mmp->modifiermap;
1652     for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
1653     {
1654         int j;
1655
1656         for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
1657             if (*kcp)
1658             {
1659                 int k;
1660
1661                 for (k = 0; k < keysyms_per_keycode; k += 1)
1662                     if (keycode_to_keysym(display, *kcp, k) == XK_Num_Lock)
1663                     {
1664                         NumLockMask = 1 << i;
1665                         TRACE_(key)("NumLockMask is %x\n", NumLockMask);
1666                     }
1667                     else if (keycode_to_keysym(display, *kcp, k) == XK_Scroll_Lock)
1668                     {
1669                         ScrollLockMask = 1 << i;
1670                         TRACE_(key)("ScrollLockMask is %x\n", ScrollLockMask);
1671                     }
1672             }
1673     }
1674     XFreeModifiermap(mmp);
1675
1676     /* Detect the keyboard layout */
1677     X11DRV_KEYBOARD_DetectLayout( display );
1678     lkey = main_key_tab[kbd_layout].key;
1679     syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode;
1680
1681     /* Now build two conversion arrays :
1682      * keycode -> vkey + scancode + extended
1683      * vkey + extended -> keycode */
1684
1685     e2.display = display;
1686     e2.state = 0;
1687     e2.type = KeyPress;
1688
1689     memset(keyc2vkey, 0, sizeof(keyc2vkey));
1690     for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1691     {
1692         char buf[30];
1693         int have_chars;
1694
1695         keysym = 0;
1696         e2.keycode = (KeyCode)keyc;
1697         have_chars = XLookupString(&e2, buf, sizeof(buf), &keysym, NULL);
1698         vkey = 0; scan = 0;
1699         if (keysym)  /* otherwise, keycode not used */
1700         {
1701             if ((keysym >> 8) == 0xFF)         /* non-character key */
1702             {
1703                 vkey = nonchar_key_vkey[keysym & 0xff];
1704                 scan = nonchar_key_scan[keysym & 0xff];
1705                 /* set extended bit when necessary */
1706                 if (scan & 0x100) vkey |= 0x100;
1707             } else if ((keysym >> 8) == 0x1008FF) { /* XFree86 vendor keys */
1708                 vkey = xfree86_vendor_key_vkey[keysym & 0xff];
1709                 /* All vendor keys are extended with a scan code of 0 per testing on WinXP */
1710                 scan = 0x100;
1711                 vkey |= 0x100;
1712             } else if (keysym == 0x20) {                 /* Spacebar */
1713                 vkey = VK_SPACE;
1714                 scan = 0x39;
1715             } else if (have_chars) {
1716               /* we seem to need to search the layout-dependent scancodes */
1717               int maxlen=0,maxval=-1,ok;
1718               for (i=0; i<syms; i++) {
1719                 keysym = keycode_to_keysym(display, keyc, i);
1720                 if ((keysym<0x8000) && (keysym!=' '))
1721                 {
1722 #ifdef HAVE_XKB
1723                     if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
1724 #endif
1725                     {
1726                         /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1727                          * with appropriate ShiftMask and Mode_switch, use XLookupString
1728                          * to get character in the local encoding.
1729                          */
1730                         ckey[i] = keysym & 0xFF;
1731                     }
1732                 } else {
1733                   ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1734                 }
1735               }
1736               /* find key with longest match streak */
1737               for (keyn=0; keyn<MAIN_LEN; keyn++) {
1738                 for (ok=(*lkey)[keyn][i=0]; ok&&(i<4); i++)
1739                   if ((*lkey)[keyn][i] && (*lkey)[keyn][i]!=ckey[i]) ok=0;
1740                 if (!ok) i--; /* we overshot */
1741                 if (ok||(i>maxlen)) {
1742                   maxlen=i; maxval=keyn;
1743                 }
1744                 if (ok) break;
1745               }
1746               if (maxval>=0) {
1747                 /* got it */
1748                 const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan;
1749                 const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey;
1750                 scan = (*lscan)[maxval];
1751                 vkey = (*lvkey)[maxval];
1752               }
1753             }
1754         }
1755         TRACE("keycode %u => vkey %04X\n", e2.keycode, vkey);
1756         keyc2vkey[e2.keycode] = vkey;
1757         keyc2scan[e2.keycode] = scan;
1758         if ((vkey & 0xff) && vkey_used[(vkey & 0xff)])
1759             WARN("vkey %04X is being used by more than one keycode\n", vkey);
1760         vkey_used[(vkey & 0xff)] = 1;
1761     } /* for */
1762
1763 #define VKEY_IF_NOT_USED(vkey) (vkey_used[(vkey)] ? 0 : (vkey_used[(vkey)] = 1, (vkey)))
1764     for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1765     {
1766         vkey = keyc2vkey[keyc] & 0xff;
1767         if (vkey)
1768             continue;
1769
1770         e2.keycode = (KeyCode)keyc;
1771         keysym = XLookupKeysym(&e2, 0);
1772         if (!keysym)
1773            continue;
1774
1775         /* find a suitable layout-dependent VK code */
1776         /* (most Winelib apps ought to be able to work without layout tables!) */
1777         for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1778         {
1779             keysym = XLookupKeysym(&e2, i);
1780             if ((keysym >= XK_0 && keysym <= XK_9)
1781                 || (keysym >= XK_A && keysym <= XK_Z)) {
1782                 vkey = VKEY_IF_NOT_USED(keysym);
1783             }
1784         }
1785
1786         for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1787         {
1788             keysym = XLookupKeysym(&e2, i);
1789             switch (keysym)
1790             {
1791             case ';':             vkey = VKEY_IF_NOT_USED(VK_OEM_1); break;
1792             case '/':             vkey = VKEY_IF_NOT_USED(VK_OEM_2); break;
1793             case '`':             vkey = VKEY_IF_NOT_USED(VK_OEM_3); break;
1794             case '[':             vkey = VKEY_IF_NOT_USED(VK_OEM_4); break;
1795             case '\\':            vkey = VKEY_IF_NOT_USED(VK_OEM_5); break;
1796             case ']':             vkey = VKEY_IF_NOT_USED(VK_OEM_6); break;
1797             case '\'':            vkey = VKEY_IF_NOT_USED(VK_OEM_7); break;
1798             case ',':             vkey = VKEY_IF_NOT_USED(VK_OEM_COMMA); break;
1799             case '.':             vkey = VKEY_IF_NOT_USED(VK_OEM_PERIOD); break;
1800             case '-':             vkey = VKEY_IF_NOT_USED(VK_OEM_MINUS); break;
1801             case '+':             vkey = VKEY_IF_NOT_USED(VK_OEM_PLUS); break;
1802             }
1803         }
1804
1805         if (vkey)
1806         {
1807             TRACE("keycode %u => vkey %04X\n", e2.keycode, vkey);
1808             keyc2vkey[e2.keycode] = vkey;
1809         }
1810     } /* for */
1811
1812     /* For any keycodes which still don't have a vkey, assign any spare
1813      * character, function key, or OEM virtual key code. */
1814     vkey_range = 0;
1815     vkey = vkey_ranges[vkey_range].first;
1816     for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1817     {
1818         if (keyc2vkey[keyc] & 0xff)
1819             continue;
1820
1821         e2.keycode = (KeyCode)keyc;
1822         keysym = XLookupKeysym(&e2, 0);
1823         if (!keysym)
1824            continue;
1825
1826         while (vkey && vkey_used[vkey])
1827         {
1828             if (vkey == vkey_ranges[vkey_range].last)
1829             {
1830                 vkey_range++;
1831                 vkey = vkey_ranges[vkey_range].first;
1832             }
1833             else
1834                 vkey++;
1835         }
1836
1837         if (!vkey)
1838         {
1839             WARN("No more vkeys available!\n");
1840             break;
1841         }
1842
1843         if (TRACE_ON(keyboard))
1844         {
1845             TRACE("spare virtual key %04X assigned to keycode %u:\n",
1846                              vkey, e2.keycode);
1847             TRACE("(");
1848             for (i = 0; i < keysyms_per_keycode; i += 1)
1849             {
1850                 const char *ksname;
1851
1852                 keysym = XLookupKeysym(&e2, i);
1853                 ksname = XKeysymToString(keysym);
1854                 if (!ksname)
1855                     ksname = "NoSymbol";
1856                 TRACE( "%lx (%s) ", keysym, ksname);
1857             }
1858             TRACE(")\n");
1859         }
1860
1861         TRACE("keycode %u => vkey %04X\n", e2.keycode, vkey);
1862         keyc2vkey[e2.keycode] = vkey;
1863         vkey_used[vkey] = 1;
1864     } /* for */
1865 #undef VKEY_IF_NOT_USED
1866
1867     /* If some keys still lack scancodes, assign some arbitrary ones to them now */
1868     for (scan = 0x60, keyc = min_keycode; keyc <= max_keycode; keyc++)
1869       if (keyc2vkey[keyc]&&!keyc2scan[keyc]) {
1870         const char *ksname;
1871         keysym = keycode_to_keysym(display, keyc, 0);
1872         ksname = XKeysymToString(keysym);
1873         if (!ksname) ksname = "NoSymbol";
1874
1875         /* should make sure the scancode is unassigned here, but >=0x60 currently always is */
1876
1877         TRACE_(key)("assigning scancode %02x to unidentified keycode %u (%s)\n",scan,keyc,ksname);
1878         keyc2scan[keyc]=scan++;
1879       }
1880
1881     wine_tsx11_unlock();
1882 }
1883
1884 static BOOL match_x11_keyboard_layout(HKL hkl)
1885 {
1886     const DWORD isIME = 0xE0000000;
1887     HKL xHkl = get_locale_kbd_layout();
1888
1889     /* if the layout is an IME, only match the low word (LCID) */
1890     if (((ULONG_PTR)hkl & isIME) == isIME)
1891         return (LOWORD(hkl) == LOWORD(xHkl));
1892     else
1893         return (hkl == xHkl);
1894 }
1895
1896 /**********************************************************************
1897  *              GetAsyncKeyState (X11DRV.@)
1898  */
1899 SHORT CDECL X11DRV_GetAsyncKeyState(INT key)
1900 {
1901     /* Photoshop livelocks unless mouse events are included here */
1902     X11DRV_MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_KEY | QS_MOUSE, 0 );
1903     return -1;
1904 }
1905
1906
1907 /***********************************************************************
1908  *              GetKeyboardLayout (X11DRV.@)
1909  */
1910 HKL CDECL X11DRV_GetKeyboardLayout(DWORD dwThreadid)
1911 {
1912     if (!dwThreadid || dwThreadid == GetCurrentThreadId())
1913     {
1914         struct x11drv_thread_data *thread_data = x11drv_thread_data();
1915         if (thread_data && thread_data->kbd_layout) return thread_data->kbd_layout;
1916     }
1917     else
1918         FIXME("couldn't return keyboard layout for thread %04x\n", dwThreadid);
1919
1920     return get_locale_kbd_layout();
1921 }
1922
1923
1924 /***********************************************************************
1925  *              LoadKeyboardLayout (X11DRV.@)
1926  */
1927 HKL CDECL X11DRV_LoadKeyboardLayout(LPCWSTR name, UINT flags)
1928 {
1929     FIXME("%s, %04x: stub!\n", debugstr_w(name), flags);
1930     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1931     return 0;
1932 }
1933
1934
1935 /***********************************************************************
1936  *              UnloadKeyboardLayout (X11DRV.@)
1937  */
1938 BOOL CDECL X11DRV_UnloadKeyboardLayout(HKL hkl)
1939 {
1940     FIXME("%p: stub!\n", hkl);
1941     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1942     return FALSE;
1943 }
1944
1945
1946 /***********************************************************************
1947  *              ActivateKeyboardLayout (X11DRV.@)
1948  */
1949 HKL CDECL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags)
1950 {
1951     HKL oldHkl = 0;
1952     struct x11drv_thread_data *thread_data = x11drv_init_thread_data();
1953
1954     FIXME("%p, %04x: semi-stub!\n", hkl, flags);
1955     if (flags & KLF_SETFORPROCESS)
1956     {
1957         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1958         FIXME("KLF_SETFORPROCESS not supported\n");
1959         return 0;
1960     }
1961
1962     if (flags)
1963         FIXME("flags %x not supported\n",flags);
1964
1965     if (hkl == (HKL)HKL_NEXT || hkl == (HKL)HKL_PREV)
1966     {
1967         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1968         FIXME("HKL_NEXT and HKL_PREV not supported\n");
1969         return 0;
1970     }
1971
1972     if (!match_x11_keyboard_layout(hkl))
1973     {
1974         SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1975         FIXME("setting keyboard of different locales not supported\n");
1976         return 0;
1977     }
1978
1979     oldHkl = thread_data->kbd_layout;
1980     if (!oldHkl) oldHkl = get_locale_kbd_layout();
1981
1982     thread_data->kbd_layout = hkl;
1983
1984     return oldHkl;
1985 }
1986
1987
1988 /***********************************************************************
1989  *           X11DRV_MappingNotify
1990  */
1991 void X11DRV_MappingNotify( HWND dummy, XEvent *event )
1992 {
1993     HWND hwnd;
1994
1995     wine_tsx11_lock();
1996     XRefreshKeyboardMapping(&event->xmapping);
1997     wine_tsx11_unlock();
1998     X11DRV_InitKeyboard( event->xmapping.display );
1999
2000     hwnd = GetFocus();
2001     if (!hwnd) hwnd = GetActiveWindow();
2002     PostMessageW(hwnd, WM_INPUTLANGCHANGEREQUEST,
2003                  0 /*FIXME*/, (LPARAM)X11DRV_GetKeyboardLayout(0));
2004 }
2005
2006
2007 /***********************************************************************
2008  *              VkKeyScanEx (X11DRV.@)
2009  *
2010  * Note: Windows ignores HKL parameter and uses current active layout instead
2011  */
2012 SHORT CDECL X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
2013 {
2014     Display *display = thread_init_display();
2015     KeyCode keycode;
2016     KeySym keysym;
2017     int i, index;
2018     CHAR cChar;
2019     SHORT ret;
2020
2021     /* FIXME: what happens if wChar is not a Latin1 character and CP_UNIXCP
2022      * is UTF-8 (multibyte encoding)?
2023      */
2024     if (!WideCharToMultiByte(CP_UNIXCP, 0, &wChar, 1, &cChar, 1, NULL, NULL))
2025     {
2026         WARN("no translation from unicode to CP_UNIXCP for 0x%02x\n", wChar);
2027         return -1;
2028     }
2029
2030     TRACE("wChar 0x%02x -> cChar '%c'\n", wChar, cChar);
2031
2032     /* char->keysym (same for ANSI chars) */
2033     keysym = (unsigned char)cChar; /* (!) cChar is signed */
2034     if (keysym <= 27) keysym += 0xFF00; /* special chars : return, backspace... */
2035
2036     wine_tsx11_lock();
2037     keycode = XKeysymToKeycode(display, keysym);  /* keysym -> keycode */
2038     if (!keycode)
2039     {
2040         if (keysym >= 0xFF00) /* Windows returns 0x0240 + cChar in this case */
2041         {
2042             ret = 0x0240 + cChar; /* 0x0200 indicates a control character */
2043             TRACE(" ... returning ctrl char %#.2x\n", ret);
2044             wine_tsx11_unlock();
2045             return ret;
2046         }
2047         /* It didn't work ... let's try with deadchar code. */
2048         TRACE("retrying with | 0xFE00\n");
2049         keycode = XKeysymToKeycode(display, keysym | 0xFE00);
2050     }
2051     wine_tsx11_unlock();
2052
2053     TRACE("'%c'(%lx): got keycode %u\n", cChar, keysym, keycode);
2054
2055     /* keycode -> (keyc2vkey) vkey */
2056     ret = keyc2vkey[keycode];
2057
2058     if (!keycode || !ret)
2059     {
2060         TRACE("keycode for '%c' not found, returning -1\n", cChar);
2061         return -1;
2062     }
2063
2064     index = -1;
2065     wine_tsx11_lock();
2066     for (i = 0; i < 4; i++) /* find shift state */
2067     {
2068         if (keycode_to_keysym(display, keycode, i) == keysym)
2069         {
2070             index = i;
2071             break;
2072         }
2073     }
2074     wine_tsx11_unlock();
2075
2076     switch (index)
2077     {
2078         default:
2079         case -1:
2080             WARN("Keysym %lx not found while parsing the keycode table\n", keysym);
2081             return -1;
2082
2083         case 0: break;
2084         case 1: ret += 0x0100; break;
2085         case 2: ret += 0x0600; break;
2086         case 3: ret += 0x0700; break;
2087     }
2088     /*
2089       index : 0     adds 0x0000
2090       index : 1     adds 0x0100 (shift)
2091       index : ?     adds 0x0200 (ctrl)
2092       index : 2     adds 0x0600 (ctrl+alt)
2093       index : 3     adds 0x0700 (ctrl+alt+shift)
2094      */
2095
2096     TRACE(" ... returning %#.2x\n", ret);
2097     return ret;
2098 }
2099
2100 /***********************************************************************
2101  *              MapVirtualKeyEx (X11DRV.@)
2102  */
2103 UINT CDECL X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
2104 {
2105     Display *display = thread_init_display();
2106
2107 #define returnMVK(value) do { TRACE("returning 0x%x.\n",value); return value; } while(0)
2108
2109     TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl);
2110     if (!match_x11_keyboard_layout(hkl))
2111         FIXME("keyboard layout %p is not supported\n", hkl);
2112
2113     switch(wMapType)
2114     {
2115         case MAPVK_VK_TO_VSC: /* vkey-code to scan-code */
2116         case MAPVK_VK_TO_VSC_EX:
2117         {
2118             int keyc;
2119
2120             switch (wCode)
2121             {
2122                 case VK_SHIFT: wCode = VK_LSHIFT; break;
2123                 case VK_CONTROL: wCode = VK_LCONTROL; break;
2124                 case VK_MENU: wCode = VK_LMENU; break;
2125             }
2126
2127             /* let's do vkey -> keycode -> scan */
2128             for (keyc = min_keycode; keyc <= max_keycode; keyc++)
2129                 if ((keyc2vkey[keyc] & 0xFF) == wCode) break;
2130
2131             if (keyc > max_keycode)
2132             {
2133                 TRACE("returning no scan-code.\n");
2134                 return 0;
2135             }
2136             returnMVK (keyc2scan[keyc] & 0xFF);
2137         }
2138         case MAPVK_VSC_TO_VK: /* scan-code to vkey-code */
2139         case MAPVK_VSC_TO_VK_EX:
2140         {
2141             int keyc;
2142             UINT vkey = 0;
2143
2144             /* let's do scan -> keycode -> vkey */
2145             for (keyc = min_keycode; keyc <= max_keycode; keyc++)
2146                 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
2147                 {
2148                     vkey = keyc2vkey[keyc] & 0xFF;
2149                     /* Only stop if it's not a numpad vkey; otherwise keep
2150                        looking for a potential better vkey. */
2151                     if (vkey && (vkey < VK_NUMPAD0 || VK_DIVIDE < vkey))
2152                         break;
2153                 }
2154
2155             if (vkey == 0)
2156             {
2157                 TRACE("returning no vkey-code.\n");
2158                 return 0;
2159             }
2160
2161             if (wMapType == MAPVK_VSC_TO_VK)
2162                 switch (vkey)
2163                 {
2164                     case VK_LSHIFT:
2165                     case VK_RSHIFT:
2166                         vkey = VK_SHIFT; break;
2167                     case VK_LCONTROL:
2168                     case VK_RCONTROL:
2169                         vkey = VK_CONTROL; break;
2170                     case VK_LMENU:
2171                     case VK_RMENU:
2172                         vkey = VK_MENU; break;
2173                 }
2174
2175             returnMVK (vkey);
2176         }
2177                 case MAPVK_VK_TO_CHAR: /* vkey-code to unshifted ANSI code */
2178                 {
2179                         /* we still don't know what "unshifted" means. in windows VK_W (0x57)
2180                          * returns 0x57, which is uppercase 'W'. So we have to return the uppercase
2181                          * key.. Looks like something is wrong with the MS docs?
2182                          * This is only true for letters, for example VK_0 returns '0' not ')'.
2183                          * - hence we use the lock mask to ensure this happens.
2184                          */
2185                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
2186                         XKeyEvent e;
2187                         KeySym keysym;
2188                         int keyc, len;
2189                         char s[10];
2190
2191                         e.display = display;
2192                         e.state = 0;
2193                         e.keycode = 0;
2194                         e.type = KeyPress;
2195
2196                         wine_tsx11_lock();
2197
2198                         /* We exit on the first keycode found, to speed up the thing. */
2199                         for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2200                         { /* Find a keycode that could have generated this virtual key */
2201                             if  ((keyc2vkey[keyc] & 0xFF) == wCode)
2202                             { /* We filter the extended bit, we don't know it */
2203                                 e.keycode = keyc; /* Store it temporarily */
2204                                 if ((EVENT_event_to_vkey(0,&e) & 0xFF) != wCode) {
2205                                     e.keycode = 0; /* Wrong one (ex: because of the NumLock
2206                                          state), so set it to 0, we'll find another one */
2207                                 }
2208                             }
2209                         }
2210
2211                         if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
2212                           e.keycode = XKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
2213
2214                         if (wCode==VK_DECIMAL)
2215                           e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2216
2217                         if (!e.keycode)
2218                         {
2219                           WARN("Unknown virtual key %X !!!\n", wCode);
2220                           wine_tsx11_unlock();
2221                           return 0; /* whatever */
2222                         }
2223                         TRACE("Found keycode %u\n",e.keycode);
2224
2225                         len = XLookupString(&e, s, sizeof(s), &keysym, NULL);
2226                         wine_tsx11_unlock();
2227
2228                         if (len)
2229                         {
2230                             WCHAR wch;
2231                             if (MultiByteToWideChar(CP_UNIXCP, 0, s, len, &wch, 1))
2232                                 returnMVK(toupperW(wch));
2233                         }
2234                         TRACE("returning no ANSI.\n");
2235                         return 0;
2236                 }
2237                 default: /* reserved */
2238                         FIXME("Unknown wMapType %d !\n", wMapType);
2239                         return 0;
2240         }
2241         return 0;
2242 }
2243
2244 /***********************************************************************
2245  *              GetKeyNameText (X11DRV.@)
2246  */
2247 INT CDECL X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
2248 {
2249   Display *display = thread_init_display();
2250   int vkey, ansi, scanCode;
2251   KeyCode keyc;
2252   int keyi;
2253   KeySym keys;
2254   char *name;
2255
2256   scanCode = lParam >> 16;
2257   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
2258
2259   vkey = X11DRV_MapVirtualKeyEx(scanCode, MAPVK_VSC_TO_VK_EX, X11DRV_GetKeyboardLayout(0));
2260
2261   /*  handle "don't care" bit (0x02000000) */
2262   if (!(lParam & 0x02000000)) {
2263     switch (vkey) {
2264          case VK_RSHIFT:
2265                           /* R-Shift is "special" - it is an extended key with separate scan code */
2266                           scanCode |= 0x100;
2267                           /* fall through */
2268          case VK_LSHIFT:
2269                           vkey = VK_SHIFT;
2270                           break;
2271        case VK_LCONTROL:
2272        case VK_RCONTROL:
2273                           vkey = VK_CONTROL;
2274                           break;
2275           case VK_LMENU:
2276           case VK_RMENU:
2277                           vkey = VK_MENU;
2278                           break;
2279     }
2280   }
2281
2282   ansi = X11DRV_MapVirtualKeyEx(vkey, MAPVK_VK_TO_CHAR, X11DRV_GetKeyboardLayout(0));
2283   TRACE("scan 0x%04x, vkey 0x%04X, ANSI 0x%04x\n", scanCode, vkey, ansi);
2284
2285   /* first get the name of the "regular" keys which is the Upper case
2286      value of the keycap imprint.                                     */
2287   if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
2288        (scanCode != 0x137) &&   /* PrtScn   */
2289        (scanCode != 0x135) &&   /* numpad / */
2290        (scanCode != 0x37 ) &&   /* numpad * */
2291        (scanCode != 0x4a ) &&   /* numpad - */
2292        (scanCode != 0x4e ) )    /* numpad + */
2293       {
2294         if (nSize >= 2)
2295         {
2296           *lpBuffer = toupperW((WCHAR)ansi);
2297           *(lpBuffer+1) = 0;
2298           return 1;
2299         }
2300      else
2301         return 0;
2302   }
2303
2304   /* FIXME: horrible hack to fix function keys. Windows reports scancode
2305             without "extended-key" flag. However Wine generates scancode
2306             *with* "extended-key" flag. Seems to occur *only* for the
2307             function keys. Soooo.. We will leave the table alone and
2308             fudge the lookup here till the other part is found and fixed!!! */
2309
2310   if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
2311        (scanCode == 0x157) || (scanCode == 0x158))
2312     scanCode &= 0xff;   /* remove "extended-key" flag for Fx keys */
2313
2314   /* let's do scancode -> keycode -> keysym -> String */
2315
2316   for (keyi=min_keycode; keyi<=max_keycode; keyi++)
2317       if ((keyc2scan[keyi]) == scanCode)
2318          break;
2319   if (keyi <= max_keycode)
2320   {
2321       INT rc;
2322
2323       wine_tsx11_lock();
2324       keyc = (KeyCode) keyi;
2325       keys = keycode_to_keysym(display, keyc, 0);
2326       name = XKeysymToString(keys);
2327       wine_tsx11_unlock();
2328
2329       if (name && (vkey == VK_SHIFT || vkey == VK_CONTROL || vkey == VK_MENU))
2330       {
2331           char* idx = strrchr(name, '_');
2332           if (idx && (strcasecmp(idx, "_r") == 0 || strcasecmp(idx, "_l") == 0))
2333           {
2334               TRACE("found scan=%04x keyc=%u keysym=%lx modified_string=%s\n",
2335                     scanCode, keyc, keys, debugstr_an(name,idx-name));
2336               rc = MultiByteToWideChar(CP_UNIXCP, 0, name, idx-name+1, lpBuffer, nSize);
2337               if (!rc) rc = nSize;
2338               lpBuffer[--rc] = 0;
2339               return rc;
2340           }
2341       }
2342
2343       if (name)
2344       {
2345           TRACE("found scan=%04x keyc=%u keysym=%04x vkey=%04x string=%s\n",
2346                 scanCode, keyc, (int)keys, vkey, debugstr_a(name));
2347           rc = MultiByteToWideChar(CP_UNIXCP, 0, name, -1, lpBuffer, nSize);
2348           if (!rc) rc = nSize;
2349           lpBuffer[--rc] = 0;
2350           return rc;
2351       }
2352   }
2353
2354   /* Finally issue WARN for unknown keys   */
2355
2356   WARN("(%08x,%p,%d): unsupported key, vkey=%04X, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
2357   *lpBuffer = 0;
2358   return 0;
2359 }
2360
2361 /***********************************************************************
2362  *              X11DRV_KEYBOARD_MapDeadKeysym
2363  */
2364 static char KEYBOARD_MapDeadKeysym(KeySym keysym)
2365 {
2366         switch (keysym)
2367             {
2368         /* symbolic ASCII is the same as defined in rfc1345 */
2369 #ifdef XK_dead_tilde
2370             case XK_dead_tilde :
2371 #endif
2372             case 0x1000FE7E : /* Xfree's XK_Dtilde */
2373                 return '~';     /* '? */
2374 #ifdef XK_dead_acute
2375             case XK_dead_acute :
2376 #endif
2377             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
2378                 return 0xb4;    /* '' */
2379 #ifdef XK_dead_circumflex
2380             case XK_dead_circumflex:
2381 #endif
2382             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
2383                 return '^';     /* '> */
2384 #ifdef XK_dead_grave
2385             case XK_dead_grave :
2386 #endif
2387             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
2388                 return '`';     /* '! */
2389 #ifdef XK_dead_diaeresis
2390             case XK_dead_diaeresis :
2391 #endif
2392             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
2393                 return 0xa8;    /* ': */
2394 #ifdef XK_dead_cedilla
2395             case XK_dead_cedilla :
2396                 return 0xb8;    /* ', */
2397 #endif
2398 #ifdef XK_dead_macron
2399             case XK_dead_macron :
2400                 return '-';     /* 'm isn't defined on iso-8859-x */
2401 #endif
2402 #ifdef XK_dead_breve
2403             case XK_dead_breve :
2404                 return 0xa2;    /* '( */
2405 #endif
2406 #ifdef XK_dead_abovedot
2407             case XK_dead_abovedot :
2408                 return 0xff;    /* '. */
2409 #endif
2410 #ifdef XK_dead_abovering
2411             case XK_dead_abovering :
2412                 return '0';     /* '0 isn't defined on iso-8859-x */
2413 #endif
2414 #ifdef XK_dead_doubleacute
2415             case XK_dead_doubleacute :
2416                 return 0xbd;    /* '" */
2417 #endif
2418 #ifdef XK_dead_caron
2419             case XK_dead_caron :
2420                 return 0xb7;    /* '< */
2421 #endif
2422 #ifdef XK_dead_ogonek
2423             case XK_dead_ogonek :
2424                 return 0xb2;    /* '; */
2425 #endif
2426 /* FIXME: I don't know this three.
2427             case XK_dead_iota :
2428                 return 'i';
2429             case XK_dead_voiced_sound :
2430                 return 'v';
2431             case XK_dead_semivoiced_sound :
2432                 return 's';
2433 */
2434             }
2435         TRACE("no character for dead keysym 0x%08lx\n",keysym);
2436         return 0;
2437 }
2438
2439 /***********************************************************************
2440  *              ToUnicodeEx (X11DRV.@)
2441  *
2442  * The ToUnicode function translates the specified virtual-key code and keyboard
2443  * state to the corresponding Windows character or characters.
2444  *
2445  * If the specified key is a dead key, the return value is negative. Otherwise,
2446  * it is one of the following values:
2447  * Value        Meaning
2448  * 0    The specified virtual key has no translation for the current state of the keyboard.
2449  * 1    One Windows character was copied to the buffer.
2450  * 2    Two characters were copied to the buffer. This usually happens when a
2451  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
2452  *      be composed with the specified virtual key to form a single character.
2453  *
2454  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
2455  *
2456  */
2457 INT CDECL X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, const BYTE *lpKeyState,
2458                              LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
2459 {
2460     Display *display = thread_init_display();
2461     XKeyEvent e;
2462     KeySym keysym = 0;
2463     INT ret;
2464     int keyc;
2465     char buf[10];
2466     char *lpChar = buf;
2467     HWND focus;
2468     XIC xic;
2469     Status status = 0;
2470
2471     if (scanCode & 0x8000)
2472     {
2473         TRACE_(key)("Key UP, doing nothing\n" );
2474         return 0;
2475     }
2476
2477     if (!match_x11_keyboard_layout(hkl))
2478         FIXME_(key)("keyboard layout %p is not supported\n", hkl);
2479
2480     if ((lpKeyState[VK_MENU] & 0x80) && (lpKeyState[VK_CONTROL] & 0x80))
2481     {
2482         TRACE_(key)("Ctrl+Alt+[key] won't generate a character\n");
2483         return 0;
2484     }
2485
2486     e.display = display;
2487     e.keycode = 0;
2488     e.state = 0;
2489     e.type = KeyPress;
2490
2491     focus = x11drv_thread_data()->last_xic_hwnd;
2492     if (!focus)
2493     {
2494         focus = GetFocus();
2495         if (focus) focus = GetAncestor( focus, GA_ROOT );
2496         if (!focus) focus = GetActiveWindow();
2497     }
2498     e.window = X11DRV_get_whole_window( focus );
2499     xic = X11DRV_get_ic( focus );
2500
2501     if (lpKeyState[VK_SHIFT] & 0x80)
2502     {
2503         TRACE_(key)("ShiftMask = %04x\n", ShiftMask);
2504         e.state |= ShiftMask;
2505     }
2506     if (lpKeyState[VK_CAPITAL] & 0x01)
2507     {
2508         TRACE_(key)("LockMask = %04x\n", LockMask);
2509         e.state |= LockMask;
2510     }
2511     if (lpKeyState[VK_CONTROL] & 0x80)
2512     {
2513         TRACE_(key)("ControlMask = %04x\n", ControlMask);
2514         e.state |= ControlMask;
2515     }
2516     if (lpKeyState[VK_NUMLOCK] & 0x01)
2517     {
2518         TRACE_(key)("NumLockMask = %04x\n", NumLockMask);
2519         e.state |= NumLockMask;
2520     }
2521
2522     /* Restore saved AltGr state */
2523     TRACE_(key)("AltGrMask = %04x\n", AltGrMask);
2524     e.state |= AltGrMask;
2525
2526     TRACE_(key)("(%04X, %04X) : faked state = 0x%04x\n",
2527                 virtKey, scanCode, e.state);
2528     wine_tsx11_lock();
2529     /* We exit on the first keycode found, to speed up the thing. */
2530     for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2531       { /* Find a keycode that could have generated this virtual key */
2532           if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
2533           { /* We filter the extended bit, we don't know it */
2534               e.keycode = keyc; /* Store it temporarily */
2535               if ((EVENT_event_to_vkey(xic,&e) & 0xFF) != virtKey) {
2536                   e.keycode = 0; /* Wrong one (ex: because of the NumLock
2537                          state), so set it to 0, we'll find another one */
2538               }
2539           }
2540       }
2541
2542     if (virtKey >= VK_LEFT && virtKey <= VK_DOWN)
2543         e.keycode = XKeysymToKeycode(e.display, virtKey - VK_LEFT + XK_Left);
2544
2545     if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
2546         e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
2547
2548     if (virtKey==VK_DECIMAL)
2549         e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2550
2551     if (virtKey==VK_SEPARATOR)
2552         e.keycode = XKeysymToKeycode(e.display, XK_KP_Separator);
2553
2554     if (!e.keycode && virtKey != VK_NONAME)
2555       {
2556         WARN_(key)("Unknown virtual key %X !!!\n", virtKey);
2557         wine_tsx11_unlock();
2558         return 0;
2559       }
2560     else TRACE_(key)("Found keycode %u\n",e.keycode);
2561
2562     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode %u\n",
2563                 e.type, e.window, e.state, e.keycode);
2564
2565     /* Clients should pass only KeyPress events to XmbLookupString,
2566      * e.type was set to KeyPress above.
2567      */
2568     if (xic)
2569     {
2570         ret = XmbLookupString(xic, &e, buf, sizeof(buf), &keysym, &status);
2571         TRACE_(key)("XmbLookupString needs %d byte(s)\n", ret);
2572         if (status == XBufferOverflow)
2573         {
2574             lpChar = HeapAlloc(GetProcessHeap(), 0, ret);
2575             if (lpChar == NULL)
2576             {
2577                 ERR_(key)("Failed to allocate memory!\n");
2578                 wine_tsx11_unlock();
2579                 return 0;
2580             }
2581             ret = XmbLookupString(xic, &e, lpChar, ret, &keysym, &status);
2582         }
2583     }
2584     else
2585         ret = XLookupString(&e, buf, sizeof(buf), &keysym, NULL);
2586     wine_tsx11_unlock();
2587
2588     TRACE_(key)("nbyte = %d, status 0x%x\n", ret, status);
2589
2590     if (TRACE_ON(key))
2591     {
2592         const char *ksname;
2593
2594         wine_tsx11_lock();
2595         ksname = XKeysymToString(keysym);
2596         wine_tsx11_unlock();
2597         if (!ksname) ksname = "No Name";
2598         TRACE_(key)("%s : keysym=%lx (%s), # of chars=%d / %s\n",
2599                     (e.type == KeyPress) ? "KeyPress" : "KeyRelease",
2600                     keysym, ksname, ret, debugstr_an(lpChar, ret));
2601     }
2602
2603     if (ret == 0)
2604     {
2605         char dead_char;
2606
2607 #ifdef XK_EuroSign
2608         /* An ugly hack for EuroSign: X can't translate it to a character
2609            for some locales. */
2610         if (keysym == XK_EuroSign)
2611         {
2612             bufW[0] = 0x20AC;
2613             ret = 1;
2614             goto found;
2615         }
2616 #endif
2617         /* Special case: X turns shift-tab into ISO_Left_Tab. */
2618         /* Here we change it back. */
2619         if (keysym == XK_ISO_Left_Tab && !(e.state & ControlMask))
2620         {
2621             bufW[0] = 0x09;
2622             ret = 1;
2623             goto found;
2624         }
2625
2626         dead_char = KEYBOARD_MapDeadKeysym(keysym);
2627         if (dead_char)
2628         {
2629             MultiByteToWideChar(CP_UNIXCP, 0, &dead_char, 1, bufW, bufW_size);
2630             ret = -1;
2631             goto found;
2632         }
2633
2634         if (keysym >= 0x01000100 && keysym <= 0x0100ffff)
2635         {
2636             /* Unicode direct mapping */
2637             bufW[0] = keysym & 0xffff;
2638             ret = 1;
2639             goto found;
2640         }
2641         else if ((keysym >> 8) == 0x1008FF) {
2642             bufW[0] = 0;
2643             ret = 0;
2644             goto found;
2645         }
2646         else
2647             {
2648             const char *ksname;
2649
2650             wine_tsx11_lock();
2651             ksname = XKeysymToString(keysym);
2652             wine_tsx11_unlock();
2653             if (!ksname)
2654                 ksname = "No Name";
2655             if ((keysym >> 8) != 0xff)
2656                 {
2657                 WARN_(key)("no char for keysym %04lx (%s) :\n",
2658                     keysym, ksname);
2659                 WARN_(key)("virtKey=%X, scanCode=%X, keycode=%u, state=%X\n",
2660                     virtKey, scanCode, e.keycode, e.state);
2661                 }
2662             }
2663         }
2664     else {  /* ret != 0 */
2665         /* We have a special case to handle : Shift + arrow, shift + home, ...
2666            X returns a char for it, but Windows doesn't. Let's eat it. */
2667         if (!(e.state & NumLockMask)  /* NumLock is off */
2668             && (e.state & ShiftMask) /* Shift is pressed */
2669             && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
2670         {
2671             lpChar[0] = 0;
2672             ret = 0;
2673         }
2674
2675         /* more areas where X returns characters but Windows does not
2676            CTRL + number or CTRL + symbol */
2677         if (e.state & ControlMask)
2678         {
2679             if (((keysym>=33) && (keysym < 'A')) ||
2680                 ((keysym > 'Z') && (keysym < 'a')) ||
2681                 (keysym == XK_Tab))
2682             {
2683                 lpChar[0] = 0;
2684                 ret = 0;
2685             }
2686         }
2687
2688         /* We have another special case for delete key (XK_Delete) on an
2689          extended keyboard. X returns a char for it, but Windows doesn't */
2690         if (keysym == XK_Delete)
2691         {
2692             lpChar[0] = 0;
2693             ret = 0;
2694         }
2695         else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
2696                 && (keysym == XK_KP_Decimal))
2697         {
2698             lpChar[0] = 0;
2699             ret = 0;
2700         }
2701         else if((lpKeyState[VK_CONTROL] & 0x80) /* Control is pressed */
2702                 && (keysym == XK_Return || keysym == XK_KP_Enter))
2703         {
2704             lpChar[0] = '\n';
2705             ret = 1;
2706         }
2707
2708         /* Hack to detect an XLookupString hard-coded to Latin1 */
2709         if (ret == 1 && keysym >= 0x00a0 && keysym <= 0x00ff && (BYTE)lpChar[0] == keysym)
2710         {
2711             bufW[0] = (BYTE)lpChar[0];
2712             goto found;
2713         }
2714
2715         /* perform translation to unicode */
2716         if(ret)
2717         {
2718             TRACE_(key)("Translating char 0x%02x to unicode\n", *(BYTE *)lpChar);
2719             ret = MultiByteToWideChar(CP_UNIXCP, 0, lpChar, ret, bufW, bufW_size);
2720         }
2721     }
2722
2723 found:
2724     if (buf != lpChar)
2725         HeapFree(GetProcessHeap(), 0, lpChar);
2726
2727     /* Null-terminate the buffer, if there's room.  MSDN clearly states that the
2728        caller must not assume this is done, but some programs (e.g. Audiosurf) do. */
2729     if (1 <= ret && ret < bufW_size)
2730         bufW[ret] = 0;
2731
2732     TRACE_(key)("returning %d with %s\n", ret, debugstr_wn(bufW, ret));
2733     return ret;
2734 }
2735
2736 /***********************************************************************
2737  *              Beep (X11DRV.@)
2738  */
2739 void CDECL X11DRV_Beep(void)
2740 {
2741     wine_tsx11_lock();
2742     XBell(gdi_display, 0);
2743     wine_tsx11_unlock();
2744 }