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