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