riched20: Fix one more memory leak.
[wine] / dlls / winex11.drv / keyboard.c
1 /*
2  * X11 keyboard driver
3  *
4  * Copyright 1993 Bob Amstadt
5  * Copyright 1996 Albrecht Kleine
6  * Copyright 1997 David Faure
7  * Copyright 1998 Morten Welinder
8  * Copyright 1998 Ulrich Weigand
9  * Copyright 1999 Ove Kåven
10  *
11  * This library is free software; you can redistribute it and/or
12  * modify it under the terms of the GNU Lesser General Public
13  * License as published by the Free Software Foundation; either
14  * version 2.1 of the License, or (at your option) any later version.
15  *
16  * This library is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
19  * Lesser General Public License for more details.
20  *
21  * You should have received a copy of the GNU Lesser General Public
22  * License along with this library; if not, write to the Free Software
23  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25
26 #include "config.h"
27
28 #include <X11/Xatom.h>
29 #include <X11/keysym.h>
30 #include <X11/Xlib.h>
31 #include <X11/Xresource.h>
32 #include <X11/Xutil.h>
33 #ifdef HAVE_X11_XKBLIB_H
34 #include <X11/XKBlib.h>
35 #endif
36
37 #include <ctype.h>
38 #include <stdarg.h>
39 #include <string.h>
40
41 #define NONAMELESSUNION
42 #define NONAMELESSSTRUCT
43 #include "windef.h"
44 #include "winbase.h"
45 #include "wingdi.h"
46 #include "winuser.h"
47 #include "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 (setxkbmap fr) */
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 (setxkbmap ch -variant fr) */
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%","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 keyboard layout (setxkbmap lt) */
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
784 /*** Turkish keyboard Layout */
785 static const char main_key_TK[MAIN_LEN][4] =
786 {
787 "\"é","1!","2'","3^#","4+$","5%","6&","7/{","8([","9)]","0=}","*?\\","-_",
788 "qQ@","wW","eE","rR","tT","yY","uU","ýIî","oO","pP","ðÐ","üÜ~",
789 "aAæ","sSß","dD","fF","gG","hH","jJ","kK","lL","þÞ","iÝ",",;`",
790 "zZ","xX","cC","vV","bB","nN","mM","öÖ","çÇ",".:"
791 };
792
793 /*** Turkish keyboard layout (setxkbmap tr) */
794 static const char main_key_TR[MAIN_LEN][4] =
795 {
796 "\"\\","1!","2'","3^","4+","5%","6&","7/","8(","9)","0=","*?","-_",
797 "qQ","wW","eE","rR","tT","yY","uU","\xb9I","oO","pP","\xbb\xab","üÜ",
798 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","\xba\xaa","i\0",",;",
799 "zZ","xX","cC","vV","bB","nN","mM","öÖ","çÇ",".:",
800 "<>"
801 };
802
803 /*** Turkish F keyboard layout (setxkbmap trf) */
804 static const char main_key_TR_F[MAIN_LEN][4] =
805 {
806 "+*","1!","2\"","3^#","4$","5%","6&","7'","8(","9)","0=","/?","-_",
807 "fF","gG","\xbb\xab","\xb9I","oO","dD","rR","nN","hH","pP","qQ","wW",
808 "uU","i\0","eE","aA","üÜ","tT","kK","mM","lL","yY","\xba\xaa","xX",
809 "jJ","öÖ","vV","cC","çÇ","zZ","sS","bB",".:",",;",
810 "<>"
811 };
812
813 /*** Israelian keyboard layout (setxkbmap us,il) */
814 static const char main_key_IL[MAIN_LEN][4] =
815 {
816  "`~;","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
817  "qQ/","wW'","eE÷","rRø","tTà","yYè","uUå","iIï","oOí","pPô","[{","]}",
818  "aAù","sSã","dDâ","fFë","gGò","hHé","jJç","kKì","lLê",";:ó","\'\",","\\|",
819  "zZæ","xXñ","cCá","vVä","bBð","nNî","mMö",",<ú",".>õ","/?.",
820  "<>"
821 };
822
823 /*** Israelian phonetic keyboard layout (setxkbmap us,il_phonetic) */
824 static const char main_key_IL_phonetic[MAIN_LEN][4] =
825 {
826  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
827  "qQ÷","wWå","eEà","rRø","tTú","yYò","uUå","iIé","oOñ","pPô","[{","]}",
828  "aAà","sSù","dDã","fFô","gGâ","hHä","jJé","kKë","lLì",";:","'\"","\\|",
829  "zZæ","xXç","cCö","vVå","bBá","nNð","mMî",",<",".>","/?",
830  "<>"
831 };
832
833 /*** Israelian Saharon keyboard layout (setxkbmap -symbols "us(pc105)+il_saharon") */
834 static const char main_key_IL_saharon[MAIN_LEN][4] =
835 {
836  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
837  "qQ÷","wWñ","eE","rRø","tTè","yYã","uU","iI","oO","pPô","[{","]}",
838  "aAà","sSå","dDì","fFú","gGâ","hHä","jJù","kKë","lLé",";:","'\"","\\|",
839  "zZæ","xXç","cCö","vVò","bBá","nNð","mMî",",<",".>","/?",
840  "<>"
841 };
842
843 /*** Greek keyboard layout (contributed by Kriton Kyrimis <kyrimis@cti.gr>)
844   Greek characters for "wW" and "sS" are omitted to not produce a mismatch
845   message since they have different characters in gr and el XFree86 layouts. */
846 static const char main_key_EL[MAIN_LEN][4] =
847 {
848  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
849  "qQ;:","wW","eEåÅ","rRñÑ","tTôÔ","yYõÕ","uUèÈ","iIéÉ","oOïÏ","pPðÐ","[{","]}",
850  "aAáÁ","sS","dDäÄ","fFöÖ","gGãÃ","hHçÇ","jJîÎ","kKêÊ","lLëË",";:´¨","'\"","\\|",
851  "zZæÆ","xX÷×","cCøØ","vVùÙ","bBâÂ","nNíÍ","mMìÌ",",<",".>","/?",
852  "<>"
853 };
854
855 /*** Thai (Kedmanee) keyboard layout by Supphachoke Suntiwichaya <mrchoke@opentle.org> */
856 static const char main_key_th[MAIN_LEN][4] =
857 {
858  "`~_%","1!å+","2@/ñ","3#-ò","4$Àó","5%¶ô","6^ØÙ","7&Öß","8*¤õ","9(µö","0)¨÷","-_¢ø","=+ªù",
859  "qQæð","wWä\"","eEÓ®","rR¾±","tTи","yYÑí","uUÕê","iIó","oO¹Ï","pP­","[{º°","]}Å,",
860  "aA¿Ä","sS˦","dD¡¯","fF´â","gGà¬","hHéç","jJèë","kKÒÉ","lLÊÈ",";:Ç«","\'\"§.","\\|£¥",
861  "zZ¼(","xX»)","cCá©","vVÍÎ","bBÚ","nN×ì","mM·?",",<Á²",".>ãÌ","/?½Æ"
862 }; 
863
864 /*** VNC keyboard layout */
865 static const WORD main_key_scan_vnc[MAIN_LEN] =
866 {
867    0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x1A,0x1B,0x27,0x28,0x29,0x33,0x34,0x35,0x2B,
868    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,
869    0x56
870 };
871
872 static const WORD main_key_vkey_vnc[MAIN_LEN] =
873 {
874    '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,
875    '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',
876    VK_OEM_102
877 };
878
879 static const char main_key_vnc[MAIN_LEN][4] =
880 {
881  "1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+","[{","]}",";:","'\"","`~",",<",".>","/?","\\|",
882  "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"
883 };
884
885 /*** Dutch keyboard layout (setxkbmap nl) ***/
886 static const char main_key_NL[MAIN_LEN][4] =
887 {
888  "@§","1!","2\"","3#","4$","5%","6&","7_","8(","9)","0'","/?","°~",
889  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","¨~","*|",
890  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","+±","'`","<>",
891  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-=",
892  "[]"
893 };
894
895
896
897 /*** Layout table. Add your keyboard mappings to this list */
898 static const struct {
899     LCID lcid; /* input locale identifier, look for LOCALE_ILANGUAGE
900                  in the appropriate dlls/kernel/nls/.nls file */
901     const char *comment;
902     const char (*key)[MAIN_LEN][4];
903     const WORD (*scan)[MAIN_LEN]; /* scan codes mapping */
904     const WORD (*vkey)[MAIN_LEN]; /* virtual key codes mapping */
905 } main_key_tab[]={
906  {0x0409, "United States keyboard layout", &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty},
907  {0x0409, "United States keyboard layout (phantom key version)", &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
908  {0x0409, "United States keyboard layout (dvorak)", &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak},
909  {0x0409, "United States International keyboard layout", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
910  {0x0809, "British keyboard layout", &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
911  {0x0407, "German keyboard layout", &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwertz},
912  {0x0407, "German keyboard layout without dead keys", &main_key_DE_nodead, &main_key_scan_qwerty, &main_key_vkey_qwertz},
913  {0x0407, "German keyboard layout for logitech desktop pro", &main_key_DE_logitech,  &main_key_scan_qwerty, &main_key_vkey_qwertz},
914  {0x0407, "German keyboard layout without dead keys 105", &main_key_DE_nodead_105, &main_key_scan_qwerty, &main_key_vkey_qwertz_105},
915  {0x0807, "Swiss German keyboard layout", &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwertz},
916  {0x100c, "Swiss French keyboard layout", &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwertz},
917  {0x041d, "Swedish keyboard layout", &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty_v2},
918  {0x0425, "Estonian keyboard layout", &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty},
919  {0x0414, "Norwegian keyboard layout", &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty},
920  {0x0406, "Danish keyboard layout", &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
921  {0x040c, "French keyboard layout", &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty},
922  {0x0c0c, "Canadian French keyboard layout", &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
923  {0x0c0c, "Canadian French keyboard layout (CA_fr)", &main_key_CA_fr, &main_key_scan_qwerty, &main_key_vkey_qwerty},
924  {0x0c0c, "Canadian keyboard layout", &main_key_CA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
925  {0x080c, "Belgian keyboard layout", &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty},
926  {0x0816, "Portuguese keyboard layout", &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
927  {0x0416, "Brazilian ABNT-2 keyboard layout", &main_key_PT_br, &main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
928  {0x0416, "Brazilian ABNT-2 keyboard layout ALT GR", &main_key_PT_br_alt_gr,&main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
929  {0x040b, "Finnish keyboard layout", &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
930  {0x0402, "Bulgarian bds keyboard layout", &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty},
931  {0x0402, "Bulgarian phonetic keyboard layout", &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
932  {0x0423, "Belarusian keyboard layout", &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty},
933  {0x0419, "Russian keyboard layout", &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
934  {0x0419, "Russian keyboard layout (phantom key version)", &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
935  {0x0419, "Russian keyboard layout KOI8-R", &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty},
936  {0x0419, "Russian keyboard layout cp1251", &main_key_RU_cp1251, &main_key_scan_qwerty, &main_key_vkey_qwerty},
937  {0x0419, "Russian phonetic keyboard layout", &main_key_RU_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
938  {0x0422, "Ukrainian keyboard layout KOI8-U", &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
939  {0x0422, "Ukrainian keyboard layout (standard)", &main_key_UA_std, &main_key_scan_qwerty, &main_key_vkey_qwerty},
940  {0x0419, "Russian keyboard layout (standard)", &main_key_RU_std, &main_key_scan_qwerty, &main_key_vkey_qwerty},
941  {0x040a, "Spanish keyboard layout", &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty},
942  {0x0410, "Italian keyboard layout", &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
943  {0x040f, "Icelandic keyboard layout", &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
944  {0x040e, "Hungarian keyboard layout", &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwertz},
945  {0x0415, "Polish (programmer's) keyboard layout", &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
946  {0x0424, "Slovenian keyboard layout", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwertz},
947  {0x0c1a, "Serbian keyboard layout sr", &main_key_SR, &main_key_scan_qwerty, &main_key_vkey_qwerty}, /* LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC */
948  {0x0c1a, "Serbian keyboard layout us,sr", &main_key_US_SR, &main_key_scan_qwerty, &main_key_vkey_qwerty}, /* LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC */
949  {0x041a, "Croatian keyboard layout", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwertz},
950  {0x041a, "Croatian keyboard layout (specific)", &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
951  {0x0411, "Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty_jp106, &main_key_vkey_qwerty_jp106},
952  {0x0411, "Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
953  {0x041b, "Slovak keyboard layout", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
954  {0x041b, "Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
955  {0x0405, "Czech keyboard layout", &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
956  {0x0405, "Czech keyboard layout cz", &main_key_CZ, &main_key_scan_qwerty, &main_key_vkey_qwertz},
957  {0x0405, "Czech keyboard layout cz_qwerty", &main_key_CZ_qwerty, &main_key_scan_qwerty, &main_key_vkey_qwerty},
958  {0x040a, "Latin American keyboard layout", &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
959  {0x0427, "Lithuanian (Baltic) keyboard layout", &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty},
960  {0x041f, "Turkish keyboard layout", &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
961  {0x041f, "Turkish keyboard layout tr", &main_key_TR, &main_key_scan_qwerty, &main_key_vkey_qwerty},
962  {0x041f, "Turkish keyboard layout trf", &main_key_TR_F, &main_key_scan_qwerty, &main_key_vkey_qwerty},
963  {0x040d, "Israelian keyboard layout", &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
964  {0x040d, "Israelian phonetic keyboard layout", &main_key_IL_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
965  {0x040d, "Israelian Saharon keyboard layout", &main_key_IL_saharon, &main_key_scan_qwerty, &main_key_vkey_qwerty},
966  {0x0409, "VNC keyboard layout", &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc},
967  {0x0408, "Greek keyboard layout", &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
968  {0x041e, "Thai (Kedmanee)  keyboard layout", &main_key_th, &main_key_scan_qwerty, &main_key_vkey_qwerty},
969  {0x0413, "Dutch keyboard layout", &main_key_NL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
970
971  {0, NULL, NULL, NULL, NULL} /* sentinel */
972 };
973 static unsigned kbd_layout=0; /* index into above table of layouts */
974
975 /* maybe more of these scancodes should be extended? */
976                 /* extended must be set for ALT_R, CTRL_R,
977                    INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
978                    keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
979                 /* FIXME should we set extended bit for NumLock ? My
980                  * Windows does ... DF */
981                 /* Yes, to distinguish based on scan codes, also
982                    for PrtScn key ... GA */
983
984 static const WORD nonchar_key_vkey[256] =
985 {
986     /* unused */
987     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF00 */
988     /* special keys */
989     VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
990     0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
991     0, 0, 0, VK_ESCAPE, 0, 0, 0, 0,                             /* FF18 */
992     /* unused */
993     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF20 */
994     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF28 */
995     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF30 */
996     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF38 */
997     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF40 */
998     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF48 */
999     /* cursor keys */
1000     VK_HOME, VK_LEFT, VK_UP, VK_RIGHT,                          /* FF50 */
1001     VK_DOWN, VK_PRIOR, VK_NEXT, VK_END,
1002     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF58 */
1003     /* misc keys */
1004     VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
1005     VK_CANCEL, VK_HELP, VK_CANCEL, VK_CANCEL, 0, 0, 0, 0,       /* FF68 */
1006     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF70 */
1007     /* keypad keys */
1008     0, 0, 0, 0, 0, 0, 0, VK_NUMLOCK,                            /* FF78 */
1009     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
1010     0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
1011     0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP,                     /* FF90 */
1012     VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT,                       /* FF98 */
1013     VK_END, VK_CLEAR, VK_INSERT, VK_DELETE,
1014     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
1015     0, 0, VK_MULTIPLY, VK_ADD,                                  /* FFA8 */
1016     VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE,
1017     VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,             /* FFB0 */
1018     VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
1019     VK_NUMPAD8, VK_NUMPAD9, 0, 0, 0, 0,                         /* FFB8 */
1020     /* function keys */
1021     VK_F1, VK_F2,
1022     VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
1023     VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, 0, 0,       /* FFC8 */
1024     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFD0 */
1025     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFD8 */
1026     /* modifier keys */
1027     0, VK_SHIFT, VK_SHIFT, VK_CONTROL,                          /* FFE0 */
1028     VK_CONTROL, VK_CAPITAL, 0, VK_MENU,
1029     VK_MENU, VK_MENU, VK_MENU, 0, 0, 0, 0, 0,                   /* FFE8 */
1030     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFF0 */
1031     0, 0, 0, 0, 0, 0, 0, VK_DELETE                              /* FFF8 */
1032 };
1033
1034 static const WORD nonchar_key_scan[256] =
1035 {
1036     /* unused */
1037     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF00 */
1038     /* special keys */
1039     0x0E, 0x0F, 0x00, /*?*/ 0, 0x00, 0x1C, 0x00, 0x00,           /* FF08 */
1040     0x00, 0x00, 0x00, 0x45, 0x46, 0x00, 0x00, 0x00,              /* FF10 */
1041     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,              /* FF18 */
1042     /* unused */
1043     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF20 */
1044     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF28 */
1045     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF30 */
1046     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF38 */
1047     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF40 */
1048     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF48 */
1049     /* cursor keys */
1050     0x147, 0x14B, 0x148, 0x14D, 0x150, 0x149, 0x151, 0x14F,      /* FF50 */
1051     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF58 */
1052     /* misc keys */
1053     /*?*/ 0, 0x137, /*?*/ 0, 0x152, 0x00, 0x00, 0x00, 0x00,      /* FF60 */
1054     /*?*/ 0, /*?*/ 0, 0x38, 0x146, 0x00, 0x00, 0x00, 0x00,       /* FF68 */
1055     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF70 */
1056     /* keypad keys */
1057     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x138, 0x145,            /* FF78 */
1058     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF80 */
1059     0x00, 0x00, 0x00, 0x00, 0x00, 0x11C, 0x00, 0x00,             /* FF88 */
1060     0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4B, 0x48,              /* FF90 */
1061     0x4D, 0x50, 0x49, 0x51, 0x4F, 0x4C, 0x52, 0x53,              /* FF98 */
1062     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFA0 */
1063     0x00, 0x00, 0x37, 0x4E, 0x53, 0x4A, 0x53, 0x135,             /* FFA8 */
1064     0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47,              /* FFB0 */
1065     0x48, 0x49, 0x00, 0x00, 0x00, 0x00,                          /* FFB8 */
1066     /* function keys */
1067     0x3B, 0x3C,
1068     0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44,              /* FFC0 */
1069     0x57, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFC8 */
1070     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFD0 */
1071     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFD8 */
1072     /* modifier keys */
1073     0x00, 0x2A, 0x36, 0x1D, 0x11D, 0x3A, 0x00, 0x38,             /* FFE0 */
1074     0x138, 0x38, 0x138, 0x00, 0x00, 0x00, 0x00, 0x00,            /* FFE8 */
1075     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFF0 */
1076     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x153              /* FFF8 */
1077 };
1078
1079
1080 /* Returns the Windows virtual key code associated with the X event <e> */
1081 /* x11 lock must be held */
1082 static WORD EVENT_event_to_vkey( XIC xic, XKeyEvent *e)
1083 {
1084     KeySym keysym = 0;
1085     Status status;
1086     char buf[24];
1087
1088     if (xic)
1089         XmbLookupString(xic, e, buf, sizeof(buf), &keysym, &status);
1090     else
1091         XLookupString(e, buf, sizeof(buf), &keysym, NULL);
1092
1093     if ((e->state & NumLockMask) &&
1094         (keysym == XK_KP_Separator || keysym == XK_KP_Decimal ||
1095          (keysym >= XK_KP_0 && keysym <= XK_KP_9)))
1096         /* Only the Keypad keys 0-9 and . send different keysyms
1097          * depending on the NumLock state */
1098         return nonchar_key_vkey[keysym & 0xFF];
1099
1100     TRACE_(key)("e->keycode = %x\n", e->keycode);
1101
1102     return keyc2vkey[e->keycode];
1103 }
1104
1105 static BOOL NumState=FALSE, CapsState=FALSE;
1106
1107
1108 /***********************************************************************
1109  *           X11DRV_send_keyboard_input
1110  */
1111 void X11DRV_send_keyboard_input( WORD wVk, WORD wScan, DWORD dwFlags, DWORD time,
1112                                  DWORD dwExtraInfo, UINT injected_flags )
1113 {
1114     UINT message;
1115     KEYLP keylp;
1116     KBDLLHOOKSTRUCT hook;
1117     WORD wVkStripped;
1118
1119     wVk = LOBYTE(wVk);
1120
1121     /* strip left/right for menu, control, shift */
1122     if (wVk == VK_LMENU || wVk == VK_RMENU)
1123         wVkStripped = VK_MENU;
1124     else if (wVk == VK_LCONTROL || wVk == VK_RCONTROL)
1125         wVkStripped = VK_CONTROL;
1126     else if (wVk == VK_LSHIFT || wVk == VK_RSHIFT)
1127         wVkStripped = VK_SHIFT;
1128     else
1129         wVkStripped = wVk;
1130
1131     keylp.lp2 = 0;
1132     keylp.lp1.count = 1;
1133     keylp.lp1.code = wScan;
1134     keylp.lp1.extended = (dwFlags & KEYEVENTF_EXTENDEDKEY) != 0;
1135     keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
1136                                 * don't remember where I read it - AK */
1137                                 /* it's '1' under windows, when a dialog box appears
1138                                  * and you press one of the underlined keys - DF*/
1139
1140     /* note that there is a test for all this */
1141     if (dwFlags & KEYEVENTF_KEYUP )
1142     {
1143         message = WM_KEYUP;
1144         if ((key_state_table[VK_MENU] & 0x80) &&
1145             ((wVkStripped == VK_MENU) || (wVkStripped == VK_CONTROL)
1146              || !(key_state_table[VK_CONTROL] & 0x80)))
1147         {
1148             if( TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */
1149                 (wVkStripped != VK_MENU)) /* <ALT>-down...<something else>-up */
1150                 message = WM_SYSKEYUP;
1151             TrackSysKey = 0;
1152         }
1153         key_state_table[wVk] &= ~0x80;
1154         key_state_table[wVkStripped] &= ~0x80;
1155         keylp.lp1.previous = 1;
1156         keylp.lp1.transition = 1;
1157     }
1158     else
1159     {
1160         keylp.lp1.previous = (key_state_table[wVk] & 0x80) != 0;
1161         keylp.lp1.transition = 0;
1162         if (!(key_state_table[wVk] & 0x80)) key_state_table[wVk] ^= 0x01;
1163         key_state_table[wVk] |= 0xc0;
1164         key_state_table[wVkStripped] |= 0xc0;
1165
1166         message = WM_KEYDOWN;
1167         if ((key_state_table[VK_MENU] & 0x80) && !(key_state_table[VK_CONTROL] & 0x80))
1168         {
1169             message = WM_SYSKEYDOWN;
1170             TrackSysKey = wVkStripped;
1171         }
1172     }
1173
1174     keylp.lp1.context = (key_state_table[VK_MENU] & 0x80) != 0; /* 1 if alt */
1175
1176     TRACE_(key)(" wParam=%04x, lParam=%08lx, InputKeyState=%x\n",
1177                 wVk, keylp.lp2, key_state_table[wVk] );
1178
1179     hook.vkCode      = wVk;
1180     hook.scanCode    = wScan;
1181     hook.flags       = (keylp.lp2 >> 24) | injected_flags;
1182     hook.time        = time;
1183     hook.dwExtraInfo = dwExtraInfo;
1184     if (HOOK_CallHooks( WH_KEYBOARD_LL, HC_ACTION, message, (LPARAM)&hook, TRUE )) return;
1185
1186     SERVER_START_REQ( send_hardware_message )
1187     {
1188         req->id       = (injected_flags & LLKHF_INJECTED) ? 0 : GetCurrentThreadId();
1189         req->win      = 0;
1190         req->msg      = message;
1191         req->wparam   = wVk;
1192         req->lparam   = keylp.lp2;
1193         req->x        = cursor_pos.x;
1194         req->y        = cursor_pos.y;
1195         req->time     = time;
1196         req->info     = dwExtraInfo;
1197         wine_server_call( req );
1198     }
1199     SERVER_END_REQ;
1200 }
1201
1202
1203 /**********************************************************************
1204  *              KEYBOARD_GenerateMsg
1205  *
1206  * Generate Down+Up messages when NumLock or CapsLock is pressed.
1207  *
1208  * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
1209  *
1210  */
1211 static void KEYBOARD_GenerateMsg( WORD vkey, WORD scan, int Evtype, DWORD event_time )
1212 {
1213   BOOL * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
1214   DWORD up, down;
1215
1216   if (*State) {
1217     /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
1218        don't treat it. It's from the same key press. Then the state goes to ON.
1219        And from there, a 'release' event will switch off the toggle key. */
1220     *State=FALSE;
1221     TRACE("INTERM : don't treat release of toggle key. key_state_table[%#x] = %#x\n",
1222           vkey,key_state_table[vkey]);
1223   } else
1224     {
1225         down = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0);
1226         up = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0) | KEYEVENTF_KEYUP;
1227         if ( key_state_table[vkey] & 0x1 ) /* it was ON */
1228           {
1229             if (Evtype!=KeyPress)
1230               {
1231                 TRACE("ON + KeyRelease => generating DOWN and UP messages.\n");
1232                 X11DRV_send_keyboard_input( vkey, scan, down, event_time, 0, 0 );
1233                 X11DRV_send_keyboard_input( vkey, scan, up, event_time, 0, 0 );
1234                 *State=FALSE;
1235                 key_state_table[vkey] &= ~0x01; /* Toggle state to off. */
1236               }
1237           }
1238         else /* it was OFF */
1239           if (Evtype==KeyPress)
1240             {
1241               TRACE("OFF + Keypress => generating DOWN and UP messages.\n");
1242               X11DRV_send_keyboard_input( vkey, scan, down, event_time, 0, 0 );
1243               X11DRV_send_keyboard_input( vkey, scan, up, event_time, 0, 0 );
1244               *State=TRUE; /* Goes to intermediary state before going to ON */
1245               key_state_table[vkey] |= 0x01; /* Toggle state to on. */
1246             }
1247     }
1248 }
1249
1250 /***********************************************************************
1251  *           KEYBOARD_UpdateOneState
1252  *
1253  * Updates internal state for <vkey>, depending on key <state> under X
1254  *
1255  */
1256 inline static void KEYBOARD_UpdateOneState ( int vkey, int state, DWORD time )
1257 {
1258     /* Do something if internal table state != X state for keycode */
1259     if (((key_state_table[vkey] & 0x80)!=0) != state)
1260     {
1261         TRACE("Adjusting state for vkey %#.2x. State before %#.2x\n",
1262               vkey, key_state_table[vkey]);
1263
1264         /* Fake key being pressed inside wine */
1265         X11DRV_send_keyboard_input( vkey, 0, state? 0 : KEYEVENTF_KEYUP, time, 0, 0 );
1266
1267         TRACE("State after %#.2x\n",key_state_table[vkey]);
1268     }
1269 }
1270
1271 /***********************************************************************
1272  *           X11DRV_KeymapNotify
1273  *
1274  * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
1275  *
1276  * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
1277  * from wine to another application and back.
1278  * Toggle keys are handled in HandleEvent.
1279  */
1280 void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
1281 {
1282     int i, j, alt, control, shift;
1283     DWORD time = GetCurrentTime();
1284
1285     alt = control = shift = 0;
1286     /* the minimum keycode is always greater or equal to 8, so we can
1287      * skip the first 8 values, hence start at 1
1288      */
1289     for (i = 1; i < 32; i++)
1290     {
1291         if (!event->xkeymap.key_vector[i]) continue;
1292         for (j = 0; j < 8; j++)
1293         {
1294             if (!(event->xkeymap.key_vector[i] & (1<<j))) continue;
1295             switch(keyc2vkey[(i * 8) + j] & 0xff)
1296             {
1297             case VK_MENU:    alt = 1; break;
1298             case VK_CONTROL: control = 1; break;
1299             case VK_SHIFT:   shift = 1; break;
1300             }
1301         }
1302     }
1303     KEYBOARD_UpdateOneState( VK_MENU, alt, time );
1304     KEYBOARD_UpdateOneState( VK_CONTROL, control, time );
1305     KEYBOARD_UpdateOneState( VK_SHIFT, shift, time );
1306 }
1307
1308 /***********************************************************************
1309  *           X11DRV_KeyEvent
1310  *
1311  * Handle a X key event
1312  */
1313 void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
1314 {
1315     XKeyEvent *event = &xev->xkey;
1316     char Str[24];
1317     KeySym keysym = 0;
1318     WORD vkey = 0, bScan;
1319     DWORD dwFlags;
1320     int ascii_chars;
1321     XIC xic = X11DRV_get_ic( hwnd );
1322     DWORD event_time = EVENT_x11_time_to_win32_time(event->time);
1323     Status status = 0;
1324
1325     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
1326                 event->type, event->window, event->state, event->keycode);
1327
1328     wine_tsx11_lock();
1329     if (xic)
1330         ascii_chars = XmbLookupString(xic, event, Str, sizeof(Str), &keysym, &status);
1331     else
1332         ascii_chars = XLookupString(event, Str, sizeof(Str), &keysym, NULL);
1333     wine_tsx11_unlock();
1334
1335     /* Ignore some unwanted events */
1336     if ((keysym >= XK_ISO_Lock && keysym <= XK_ISO_Last_Group_Lock) ||
1337          keysym == XK_Mode_switch)
1338     {
1339         wine_tsx11_lock();
1340         TRACE("Ignoring %s keyboard event\n", XKeysymToString(keysym));
1341         wine_tsx11_unlock();
1342         return;
1343     }
1344
1345     TRACE_(key)("state = %X nbyte = %d, status 0x%x\n", event->state, ascii_chars, status);
1346
1347     if (status == XBufferOverflow)
1348         ERR("Buffer Overflow need %i!\n",ascii_chars);
1349
1350     if (status == XLookupChars)
1351     {
1352         X11DRV_XIMLookupChars( Str, ascii_chars );
1353         return;
1354     }
1355
1356     /* If XKB extensions are used, the state mask for AltGr will use the group
1357        index instead of the modifier mask. The group index is set in bits
1358        13-14 of the state field in the XKeyEvent structure. So if AltGr is
1359        pressed, look if the group index is different than 0. From XKB
1360        extension documentation, the group index for AltGr should be 2
1361        (event->state = 0x2000). It's probably better to not assume a
1362        predefined group index and find it dynamically
1363
1364        Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
1365     /* Save also all possible modifier states. */
1366     AltGrMask = event->state & (0x6000 | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
1367
1368     Str[ascii_chars] = '\0';
1369     if (TRACE_ON(key)){
1370         const char *ksname;
1371
1372         wine_tsx11_lock();
1373         ksname = XKeysymToString(keysym);
1374         wine_tsx11_unlock();
1375         if (!ksname)
1376           ksname = "No Name";
1377         TRACE_(key)("%s : keysym=%lX (%s), # of chars=%d / 0x%02x / '%s'\n",
1378                     (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
1379                     keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
1380     }
1381
1382     wine_tsx11_lock();
1383     vkey = EVENT_event_to_vkey(xic,event);
1384     /* X returns keycode 0 for composed characters */
1385     if (!vkey && ascii_chars) vkey = VK_NONAME;
1386     wine_tsx11_unlock();
1387
1388     TRACE_(key)("keycode 0x%x converted to vkey 0x%x\n",
1389                 event->keycode, vkey);
1390
1391    if (vkey)
1392    {
1393     switch (vkey & 0xff)
1394     {
1395     case VK_NUMLOCK:
1396       KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, event->type, event_time );
1397       break;
1398     case VK_CAPITAL:
1399       TRACE("Caps Lock event. (type %d). State before : %#.2x\n",event->type,key_state_table[vkey]);
1400       KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, event->type, event_time );
1401       TRACE("State after : %#.2x\n",key_state_table[vkey]);
1402       break;
1403     default:
1404         /* Adjust the NUMLOCK state if it has been changed outside wine */
1405         if (!(key_state_table[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
1406           {
1407             TRACE("Adjusting NumLock state.\n");
1408             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyPress, event_time );
1409             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyRelease, event_time );
1410           }
1411         /* Adjust the CAPSLOCK state if it has been changed outside wine */
1412         if (!(key_state_table[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
1413           {
1414               TRACE("Adjusting Caps Lock state.\n");
1415             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyPress, event_time );
1416             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyRelease, event_time );
1417           }
1418         /* Not Num nor Caps : end of intermediary states for both. */
1419         NumState = FALSE;
1420         CapsState = FALSE;
1421
1422         bScan = keyc2scan[event->keycode] & 0xFF;
1423         TRACE_(key)("bScan = 0x%02x.\n", bScan);
1424
1425         dwFlags = 0;
1426         if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
1427         if ( vkey & 0x100 )              dwFlags |= KEYEVENTF_EXTENDEDKEY;
1428
1429         X11DRV_send_keyboard_input( vkey & 0xff, bScan, dwFlags, event_time, 0, 0 );
1430     }
1431    }
1432 }
1433
1434 /**********************************************************************
1435  *              X11DRV_KEYBOARD_DetectLayout
1436  *
1437  * Called from X11DRV_InitKeyboard
1438  *  This routine walks through the defined keyboard layouts and selects
1439  *  whichever matches most closely.
1440  * X11 lock must be held.
1441  */
1442 static void
1443 X11DRV_KEYBOARD_DetectLayout (void)
1444 {
1445   Display *display = thread_display();
1446   unsigned current, match, mismatch, seq, i, syms;
1447   int score, keyc, key, pkey, ok;
1448   KeySym keysym = 0;
1449   const char (*lkey)[MAIN_LEN][4];
1450   unsigned max_seq = 0;
1451   int max_score = 0, ismatch = 0;
1452   char ckey[4] =
1453   {0, 0, 0, 0};
1454
1455   syms = keysyms_per_keycode;
1456   if (syms > 4) {
1457     WARN("%d keysyms per keycode not supported, set to 4\n", syms);
1458     syms = 4;
1459   }
1460   for (current = 0; main_key_tab[current].comment; current++) {
1461     TRACE("Attempting to match against \"%s\"\n", main_key_tab[current].comment);
1462     match = 0;
1463     mismatch = 0;
1464     score = 0;
1465     seq = 0;
1466     lkey = main_key_tab[current].key;
1467     pkey = -1;
1468     for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1469       /* get data for keycode from X server */
1470       for (i = 0; i < syms; i++) {
1471         keysym = XKeycodeToKeysym (display, keyc, i);
1472         /* Allow both one-byte and two-byte national keysyms */
1473         if ((keysym < 0x8000) && (keysym != ' '))
1474         {
1475 #ifdef HAVE_XKB
1476             if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
1477 #endif
1478             {
1479                 TRACE("XKB could not translate keysym %ld\n", keysym);
1480                 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1481                  * with appropriate ShiftMask and Mode_switch, use XLookupString
1482                  * to get character in the local encoding.
1483                  */
1484                 ckey[i] = keysym & 0xFF;
1485             }
1486         }
1487         else {
1488           ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1489         }
1490       }
1491       if (ckey[0]) {
1492         /* search for a match in layout table */
1493         /* right now, we just find an absolute match for defined positions */
1494         /* (undefined positions are ignored, so if it's defined as "3#" in */
1495         /* the table, it's okay that the X server has "3#£", for example) */
1496         /* however, the score will be higher for longer matches */
1497         for (key = 0; key < MAIN_LEN; key++) {
1498           for (ok = 0, i = 0; (ok >= 0) && (i < syms); i++) {
1499             if ((*lkey)[key][i] && ((*lkey)[key][i] == ckey[i]))
1500               ok++;
1501             if ((*lkey)[key][i] && ((*lkey)[key][i] != ckey[i]))
1502               ok = -1;
1503           }
1504           if (ok > 0) {
1505             score += ok;
1506             break;
1507           }
1508         }
1509         /* count the matches and mismatches */
1510         if (ok > 0) {
1511           match++;
1512           /* and how much the keycode order matches */
1513           if (key > pkey) seq++;
1514           pkey = key;
1515         } else {
1516           /* print spaces instead of \0's */
1517           for (i = 0; i < sizeof(ckey); i++) if (!ckey[i]) ckey[i] = ' ';
1518           TRACE_(key)("mismatch for keysym 0x%04lX, keycode %d, got %c%c%c%c\n",
1519                       keysym, keyc, ckey[0], ckey[1], ckey[2], ckey[3]);
1520           mismatch++;
1521           score -= syms;
1522         }
1523       }
1524     }
1525     TRACE("matches=%d, mismatches=%d, seq=%d, score=%d\n",
1526            match, mismatch, seq, score);
1527     if ((score > max_score) ||
1528         ((score == max_score) && (seq > max_seq))) {
1529       /* best match so far */
1530       kbd_layout = current;
1531       max_score = score;
1532       max_seq = seq;
1533       ismatch = !mismatch;
1534     }
1535   }
1536   /* we're done, report results if necessary */
1537   if (!ismatch)
1538     WARN("Using closest match (%s) for scan/virtual codes mapping.\n",
1539         main_key_tab[kbd_layout].comment);
1540
1541   TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment);
1542 }
1543
1544 /**********************************************************************
1545  *              X11DRV_InitKeyboard
1546  */
1547 void X11DRV_InitKeyboard(void)
1548 {
1549     Display *display = thread_display();
1550     KeySym *ksp;
1551     XModifierKeymap *mmp;
1552     KeySym keysym;
1553     KeyCode *kcp;
1554     XKeyEvent e2;
1555     WORD scan, vkey, OEMvkey;
1556     int keyc, i, keyn, syms;
1557     char ckey[4]={0,0,0,0};
1558     const char (*lkey)[MAIN_LEN][4];
1559
1560     wine_tsx11_lock();
1561     XDisplayKeycodes(display, &min_keycode, &max_keycode);
1562     ksp = XGetKeyboardMapping(display, min_keycode,
1563                               max_keycode + 1 - min_keycode, &keysyms_per_keycode);
1564     /* We are only interested in keysyms_per_keycode.
1565        There is no need to hold a local copy of the keysyms table */
1566     XFree(ksp);
1567
1568     mmp = XGetModifierMapping(display);
1569     kcp = mmp->modifiermap;
1570     for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
1571     {
1572         int j;
1573
1574         for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
1575             if (*kcp)
1576             {
1577                 int k;
1578
1579                 for (k = 0; k < keysyms_per_keycode; k += 1)
1580                     if (XKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
1581                     {
1582                         NumLockMask = 1 << i;
1583                         TRACE_(key)("NumLockMask is %x\n", NumLockMask);
1584                     }
1585             }
1586     }
1587     XFreeModifiermap(mmp);
1588
1589     /* Detect the keyboard layout */
1590     X11DRV_KEYBOARD_DetectLayout();
1591     lkey = main_key_tab[kbd_layout].key;
1592     syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode;
1593
1594     /* Now build two conversion arrays :
1595      * keycode -> vkey + scancode + extended
1596      * vkey + extended -> keycode */
1597
1598     e2.display = display;
1599     e2.state = 0;
1600
1601     OEMvkey = VK_OEM_8; /* next is available.  */
1602     for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1603     {
1604         char buf[30];
1605         int have_chars;
1606
1607         keysym = 0;
1608         e2.keycode = (KeyCode)keyc;
1609         have_chars = XLookupString(&e2, buf, sizeof(buf), &keysym, NULL);
1610         vkey = 0; scan = 0;
1611         if (keysym)  /* otherwise, keycode not used */
1612         {
1613             if ((keysym >> 8) == 0xFF)         /* non-character key */
1614             {
1615                 vkey = nonchar_key_vkey[keysym & 0xff];
1616                 scan = nonchar_key_scan[keysym & 0xff];
1617                 /* set extended bit when necessary */
1618                 if (scan & 0x100) vkey |= 0x100;
1619             } else if (keysym == 0x20) {                 /* Spacebar */
1620                 vkey = VK_SPACE;
1621                 scan = 0x39;
1622             } else if (have_chars) {
1623               /* we seem to need to search the layout-dependent scancodes */
1624               int maxlen=0,maxval=-1,ok;
1625               for (i=0; i<syms; i++) {
1626                 keysym = XKeycodeToKeysym(display, keyc, i);
1627                 if ((keysym<0x8000) && (keysym!=' '))
1628                 {
1629 #ifdef HAVE_XKB
1630                     if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
1631 #endif
1632                     {
1633                         /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1634                          * with appropriate ShiftMask and Mode_switch, use XLookupString
1635                          * to get character in the local encoding.
1636                          */
1637                         ckey[i] = keysym & 0xFF;
1638                     }
1639                 } else {
1640                   ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1641                 }
1642               }
1643               /* find key with longest match streak */
1644               for (keyn=0; keyn<MAIN_LEN; keyn++) {
1645                 for (ok=(*lkey)[keyn][i=0]; ok&&(i<4); i++)
1646                   if ((*lkey)[keyn][i] && (*lkey)[keyn][i]!=ckey[i]) ok=0;
1647                 if (ok||(i>maxlen)) {
1648                   maxlen=i; maxval=keyn;
1649                 }
1650                 if (ok) break;
1651               }
1652               if (maxval>=0) {
1653                 /* got it */
1654                 const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan;
1655                 const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey;
1656                 scan = (*lscan)[maxval];
1657                 vkey = (*lvkey)[maxval];
1658               }
1659             }
1660 #if 0 /* this breaks VK_OEM_x VKeys in some layout tables by inserting
1661        * a VK code into a not appropriate place.
1662        */
1663             /* find a suitable layout-dependent VK code */
1664             /* (most Winelib apps ought to be able to work without layout tables!) */
1665             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1666             {
1667                 keysym = XLookupKeysym(&e2, i);
1668                 if ((keysym >= VK_0 && keysym <= VK_9)
1669                     || (keysym >= VK_A && keysym <= VK_Z)) {
1670                     vkey = keysym;
1671                 }
1672             }
1673
1674             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1675             {
1676                 keysym = XLookupKeysym(&e2, i);
1677                 switch (keysym)
1678                 {
1679                 case ';':             vkey = VK_OEM_1; break;
1680                 case '/':             vkey = VK_OEM_2; break;
1681                 case '`':             vkey = VK_OEM_3; break;
1682                 case '[':             vkey = VK_OEM_4; break;
1683                 case '\\':            vkey = VK_OEM_5; break;
1684                 case ']':             vkey = VK_OEM_6; break;
1685                 case '\'':            vkey = VK_OEM_7; break;
1686                 case ',':             vkey = VK_OEM_COMMA; break;
1687                 case '.':             vkey = VK_OEM_PERIOD; break;
1688                 case '-':             vkey = VK_OEM_MINUS; break;
1689                 case '+':             vkey = VK_OEM_PLUS; break;
1690                 }
1691             }
1692
1693             if (!vkey)
1694             {
1695                 /* Others keys: let's assign OEM virtual key codes in the allowed range,
1696                  * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
1697                 switch (++OEMvkey)
1698                 {
1699                 case 0xc1 : OEMvkey=0xdb; break;
1700                 case 0xe5 : OEMvkey=0xe9; break;
1701                 case 0xf6 : OEMvkey=0xf5; WARN("No more OEM vkey available!\n");
1702                 }
1703
1704                 vkey = OEMvkey;
1705
1706                 if (TRACE_ON(keyboard))
1707                 {
1708                     TRACE("OEM specific virtual key %X assigned to keycode %X:\n",
1709                                      OEMvkey, e2.keycode);
1710                     TRACE("(");
1711                     for (i = 0; i < keysyms_per_keycode; i += 1)
1712                     {
1713                         const char *ksname;
1714
1715                         keysym = XLookupKeysym(&e2, i);
1716                         ksname = XKeysymToString(keysym);
1717                         if (!ksname)
1718                             ksname = "NoSymbol";
1719                         TRACE( "%lX (%s) ", keysym, ksname);
1720                     }
1721                     TRACE(")\n");
1722                 }
1723             }
1724 #endif
1725         }
1726         TRACE("keycode %04x => vkey %04x\n", e2.keycode, vkey);
1727         keyc2vkey[e2.keycode] = vkey;
1728         keyc2scan[e2.keycode] = scan;
1729     } /* for */
1730
1731     /* If some keys still lack scancodes, assign some arbitrary ones to them now */
1732     for (scan = 0x60, keyc = min_keycode; keyc <= max_keycode; keyc++)
1733       if (keyc2vkey[keyc]&&!keyc2scan[keyc]) {
1734         const char *ksname;
1735         keysym = XKeycodeToKeysym(display, keyc, 0);
1736         ksname = XKeysymToString(keysym);
1737         if (!ksname) ksname = "NoSymbol";
1738
1739         /* should make sure the scancode is unassigned here, but >=0x60 currently always is */
1740
1741         TRACE_(key)("assigning scancode %02x to unidentified keycode %02x (%s)\n",scan,keyc,ksname);
1742         keyc2scan[keyc]=scan++;
1743       }
1744
1745     /* Now store one keycode for each modifier. Used to simulate keypresses. */
1746     kcControl = XKeysymToKeycode(display, XK_Control_L);
1747     kcAlt = XKeysymToKeycode(display, XK_Alt_L);
1748     if (!kcAlt) kcAlt = XKeysymToKeycode(display, XK_Meta_L);
1749     kcShift = XKeysymToKeycode(display, XK_Shift_L);
1750     kcNumLock = XKeysymToKeycode(display, XK_Num_Lock);
1751     kcCapsLock = XKeysymToKeycode(display, XK_Caps_Lock);
1752     wine_tsx11_unlock();
1753 }
1754
1755
1756 /**********************************************************************
1757  *              GetAsyncKeyState (X11DRV.@)
1758  */
1759 SHORT X11DRV_GetAsyncKeyState(INT key)
1760 {
1761     SHORT retval = ((key_state_table[key] & 0x40) ? 0x0001 : 0) |
1762                    ((key_state_table[key] & 0x80) ? 0x8000 : 0);
1763     key_state_table[key] &= ~0x40;
1764     TRACE_(key)("(%x) -> %x\n", key, retval);
1765     return retval;
1766 }
1767
1768
1769 /***********************************************************************
1770  *              GetKeyboardLayoutList (X11DRV.@)
1771  */
1772 UINT X11DRV_GetKeyboardLayoutList(INT size, HKL *hkl)
1773 {
1774     INT i;
1775
1776     TRACE("%d, %p\n", size, hkl);
1777
1778     if (!size)
1779     {
1780         size = 4096; /* hope we will never have that many */
1781         hkl = NULL;
1782     }
1783
1784     for (i = 0; main_key_tab[i].comment && (i < size); i++)
1785     {
1786         if (hkl)
1787         {
1788             ULONG_PTR layout = main_key_tab[i].lcid;
1789             LANGID langid;
1790
1791             /* see comment for GetKeyboardLayout */
1792             langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1793             if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1794                 layout |= 0xe001 << 16; /* FIXME */
1795             else
1796                 layout |= layout << 16;
1797
1798             hkl[i] = (HKL)layout;
1799         }
1800     }
1801     return i;
1802 }
1803
1804
1805 /***********************************************************************
1806  *              GetKeyboardLayout (X11DRV.@)
1807  */
1808 HKL X11DRV_GetKeyboardLayout(DWORD dwThreadid)
1809 {
1810     ULONG_PTR layout;
1811     LANGID langid;
1812
1813     if (dwThreadid && dwThreadid != GetCurrentThreadId())
1814         FIXME("couldn't return keyboard layout for thread %04x\n", dwThreadid);
1815
1816 #if 0
1817     layout = main_key_tab[kbd_layout].lcid;
1818 #else
1819     /* FIXME:
1820      * Winword uses return value of GetKeyboardLayout as a codepage
1821      * to translate ANSI keyboard messages to unicode. But we have
1822      * a problem with it: for instance Polish keyboard layout is
1823      * identical to the US one, and therefore instead of the Polish
1824      * locale id we return the US one.
1825      */
1826     layout = GetUserDefaultLCID();
1827 #endif
1828     /* 
1829      * Microsoft Office expects this value to be something specific
1830      * for Japanese and Korean Windows with an IME the value is 0xe001
1831      * We should probably check to see if an IME exists and if so then
1832      * set this word properly.
1833      */
1834     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1835     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1836         layout |= 0xe001 << 16; /* FIXME */
1837     else
1838         layout |= layout << 16;
1839
1840     return (HKL)layout;
1841 }
1842
1843
1844 /***********************************************************************
1845  *              GetKeyboardLayoutName (X11DRV.@)
1846  */
1847 BOOL X11DRV_GetKeyboardLayoutName(LPWSTR name)
1848 {
1849     static const WCHAR formatW[] = {'%','0','8','l','x',0};
1850     DWORD layout;
1851     LANGID langid;
1852
1853     layout = main_key_tab[kbd_layout].lcid;
1854     /* see comment for GetKeyboardLayout */
1855     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1856     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1857         layout |= 0xe001 << 16; /* FIXME */
1858     else
1859         layout |= layout << 16;
1860
1861     sprintfW(name, formatW, layout);
1862     TRACE("returning %s\n", debugstr_w(name));
1863     return TRUE;
1864 }
1865
1866
1867 /***********************************************************************
1868  *              LoadKeyboardLayout (X11DRV.@)
1869  */
1870 HKL X11DRV_LoadKeyboardLayout(LPCWSTR name, UINT flags)
1871 {
1872     FIXME("%s, %04x: stub!\n", debugstr_w(name), flags);
1873     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1874     return 0;
1875 }
1876
1877
1878 /***********************************************************************
1879  *              UnloadKeyboardLayout (X11DRV.@)
1880  */
1881 BOOL X11DRV_UnloadKeyboardLayout(HKL hkl)
1882 {
1883     FIXME("%p: stub!\n", hkl);
1884     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1885     return FALSE;
1886 }
1887
1888
1889 /***********************************************************************
1890  *              ActivateKeyboardLayout (X11DRV.@)
1891  */
1892 HKL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags)
1893 {
1894     FIXME("%p, %04x: stub!\n", hkl, flags);
1895     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1896     return 0;
1897 }
1898
1899
1900 /***********************************************************************
1901  *           X11DRV_MappingNotify
1902  */
1903 void X11DRV_MappingNotify( HWND dummy, XEvent *event )
1904 {
1905     HWND hwnd;
1906
1907     wine_tsx11_lock();
1908     XRefreshKeyboardMapping(&event->xmapping);
1909     wine_tsx11_unlock();
1910     X11DRV_InitKeyboard();
1911
1912     hwnd = GetFocus();
1913     if (!hwnd) hwnd = GetActiveWindow();
1914     PostMessageW(hwnd, WM_INPUTLANGCHANGEREQUEST,
1915                  0 /*FIXME*/, (LPARAM)X11DRV_GetKeyboardLayout(0));
1916 }
1917
1918
1919 /***********************************************************************
1920  *              VkKeyScanEx (X11DRV.@)
1921  *
1922  * Note: Windows ignores HKL parameter and uses current active layout instead
1923  */
1924 SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
1925 {
1926     Display *display = thread_display();
1927     KeyCode keycode;
1928     KeySym keysym;
1929     int i, index;
1930     CHAR cChar;
1931     SHORT ret;
1932
1933     /* FIXME: what happens if wChar is not a Latin1 character and CP_UNIXCP
1934      * is UTF-8 (multibyte encoding)?
1935      */
1936     if (!WideCharToMultiByte(CP_UNIXCP, 0, &wChar, 1, &cChar, 1, NULL, NULL))
1937     {
1938         WARN("no translation from unicode to CP_UNIXCP for 0x%02x\n", wChar);
1939         return -1;
1940     }
1941
1942     TRACE("wChar 0x%02x -> cChar '%c'\n", wChar, cChar);
1943
1944     /* char->keysym (same for ANSI chars) */
1945     keysym = (unsigned char)cChar; /* (!) cChar is signed */
1946     if (keysym <= 27) keysym += 0xFF00; /* special chars : return, backspace... */
1947
1948     wine_tsx11_lock();
1949     keycode = XKeysymToKeycode(display, keysym);  /* keysym -> keycode */
1950     if (!keycode)
1951     {
1952         if (keysym >= 0xFF00) /* Windows returns 0x0240 + cChar in this case */
1953         {
1954             ret = 0x0240 + cChar; /* 0x0200 indicates a control character */
1955             TRACE(" ... returning ctrl char %#.2x\n", ret);
1956             wine_tsx11_unlock();
1957             return ret;
1958         }
1959         /* It didn't work ... let's try with deadchar code. */
1960         TRACE("retrying with | 0xFE00\n");
1961         keycode = XKeysymToKeycode(display, keysym | 0xFE00);
1962     }
1963     wine_tsx11_unlock();
1964
1965     TRACE("'%c'(%#lx, %lu): got keycode %#.2x (%d)\n",
1966             cChar, keysym, keysym, keycode, keycode);
1967
1968     /* keycode -> (keyc2vkey) vkey */
1969     ret = keyc2vkey[keycode];
1970
1971     if (!keycode || !ret)
1972     {
1973         TRACE("keycode for '%c' not found, returning -1\n", cChar);
1974         return -1;
1975     }
1976
1977     index = -1;
1978     wine_tsx11_lock();
1979     for (i = 0; i < 4; i++) /* find shift state */
1980     {
1981         if (XKeycodeToKeysym(display, keycode, i) == keysym)
1982         {
1983             index = i;
1984             break;
1985         }
1986     }
1987     wine_tsx11_unlock();
1988
1989     switch (index)
1990     {
1991         default:
1992         case -1:
1993             WARN("Keysym %lx not found while parsing the keycode table\n", keysym);
1994             return -1;
1995
1996         case 0: break;
1997         case 1: ret += 0x0100; break;
1998         case 2: ret += 0x0600; break;
1999         case 3: ret += 0x0700; break;
2000     }
2001     /*
2002       index : 0     adds 0x0000
2003       index : 1     adds 0x0100 (shift)
2004       index : ?     adds 0x0200 (ctrl)
2005       index : 2     adds 0x0600 (ctrl+alt)
2006       index : 3     adds 0x0700 (ctrl+alt+shift)
2007      */
2008
2009     TRACE(" ... returning %#.2x\n", ret);
2010     return ret;
2011 }
2012
2013 /***********************************************************************
2014  *              MapVirtualKeyEx (X11DRV.@)
2015  */
2016 UINT X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
2017 {
2018     Display *display = thread_display();
2019
2020 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
2021
2022     TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl);
2023     if (hkl != X11DRV_GetKeyboardLayout(0))
2024         FIXME("keyboard layout %p is not supported\n", hkl);
2025
2026         switch(wMapType) {
2027                 case 0: { /* vkey-code to scan-code */
2028                         /* let's do vkey -> keycode -> scan */
2029                         int keyc;
2030                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
2031                                 if ((keyc2vkey[keyc] & 0xFF) == wCode)
2032                                         returnMVK (keyc2scan[keyc] & 0xFF);
2033                         TRACE("returning no scan-code.\n");
2034                         return 0; }
2035
2036                 case 1: { /* scan-code to vkey-code */
2037                         /* let's do scan -> keycode -> vkey */
2038                         int keyc;
2039                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
2040                                 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
2041                                         returnMVK (keyc2vkey[keyc] & 0xFF);
2042                         TRACE("returning no vkey-code.\n");
2043                         return 0; }
2044
2045                 case 2: { /* vkey-code to unshifted ANSI code */
2046                         /* we still don't know what "unshifted" means. in windows VK_W (0x57)
2047                          * returns 0x57, which is upercase 'W'. So we have to return the uppercase
2048                          * key.. Looks like something is wrong with the MS docs?
2049                          * This is only true for letters, for example VK_0 returns '0' not ')'.
2050                          * - hence we use the lock mask to ensure this happens.
2051                          */
2052                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
2053                         XKeyEvent e;
2054                         KeySym keysym;
2055                         int keyc;
2056                         char s[2];
2057                         e.display = display;
2058
2059                         e.state = LockMask;
2060                         /* LockMask should behave exactly like caps lock - upercase
2061                          * the letter keys and thats about it. */
2062
2063                         wine_tsx11_lock();
2064
2065                         e.keycode = 0;
2066                         /* We exit on the first keycode found, to speed up the thing. */
2067                         for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2068                         { /* Find a keycode that could have generated this virtual key */
2069                             if  ((keyc2vkey[keyc] & 0xFF) == wCode)
2070                             { /* We filter the extended bit, we don't know it */
2071                                 e.keycode = keyc; /* Store it temporarily */
2072                                 if ((EVENT_event_to_vkey(0,&e) & 0xFF) != wCode) {
2073                                     e.keycode = 0; /* Wrong one (ex: because of the NumLock
2074                                          state), so set it to 0, we'll find another one */
2075                                 }
2076                             }
2077                         }
2078
2079                         if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
2080                           e.keycode = XKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
2081
2082                         if (wCode==VK_DECIMAL)
2083                           e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2084
2085                         if (!e.keycode)
2086                         {
2087                           WARN("Unknown virtual key %X !!!\n", wCode);
2088                           wine_tsx11_unlock();
2089                           return 0; /* whatever */
2090                         }
2091                         TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2092
2093                         if (XLookupString(&e, s, 2, &keysym, NULL))
2094                         {
2095                             wine_tsx11_unlock();
2096                             returnMVK (*s);
2097                         }
2098
2099                         TRACE("returning no ANSI.\n");
2100                         wine_tsx11_unlock();
2101                         return 0;
2102                         }
2103
2104                 case 3:   /* **NT only** scan-code to vkey-code but distinguish between  */
2105                           /*             left and right  */
2106                           FIXME(" stub for NT\n");
2107                           return 0;
2108
2109                 default: /* reserved */
2110                         WARN("Unknown wMapType %d !\n", wMapType);
2111                         return 0;
2112         }
2113         return 0;
2114 }
2115
2116 /***********************************************************************
2117  *              GetKeyNameText (X11DRV.@)
2118  */
2119 INT X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
2120 {
2121   int vkey, ansi, scanCode;
2122   KeyCode keyc;
2123   int keyi;
2124   KeySym keys;
2125   char *name;
2126
2127   scanCode = lParam >> 16;
2128   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
2129
2130   /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
2131   vkey = X11DRV_MapVirtualKeyEx(scanCode, 1, X11DRV_GetKeyboardLayout(0));
2132
2133   /*  handle "don't care" bit (0x02000000) */
2134   if (!(lParam & 0x02000000)) {
2135     switch (vkey) {
2136          case VK_LSHIFT:
2137          case VK_RSHIFT:
2138                           vkey = VK_SHIFT;
2139                           break;
2140        case VK_LCONTROL:
2141        case VK_RCONTROL:
2142                           vkey = VK_CONTROL;
2143                           break;
2144           case VK_LMENU:
2145           case VK_RMENU:
2146                           vkey = VK_MENU;
2147                           break;
2148                default:
2149                           break;
2150     }
2151   }
2152
2153   ansi = X11DRV_MapVirtualKeyEx(vkey, 2, X11DRV_GetKeyboardLayout(0));
2154   TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
2155
2156   /* first get the name of the "regular" keys which is the Upper case
2157      value of the keycap imprint.                                     */
2158   if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
2159        (scanCode != 0x137) &&   /* PrtScn   */
2160        (scanCode != 0x135) &&   /* numpad / */
2161        (scanCode != 0x37 ) &&   /* numpad * */
2162        (scanCode != 0x4a ) &&   /* numpad - */
2163        (scanCode != 0x4e ) )    /* numpad + */
2164       {
2165         if ((nSize >= 2) && lpBuffer)
2166         {
2167           *lpBuffer = toupperW((WCHAR)ansi);
2168           *(lpBuffer+1) = 0;
2169           return 1;
2170         }
2171      else
2172         return 0;
2173   }
2174
2175   /* FIXME: horrible hack to fix function keys. Windows reports scancode
2176             without "extended-key" flag. However Wine generates scancode
2177             *with* "extended-key" flag. Seems to occur *only* for the
2178             function keys. Soooo.. We will leave the table alone and
2179             fudge the lookup here till the other part is found and fixed!!! */
2180
2181   if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
2182        (scanCode == 0x157) || (scanCode == 0x158))
2183     scanCode &= 0xff;   /* remove "extended-key" flag for Fx keys */
2184
2185   /* let's do scancode -> keycode -> keysym -> String */
2186
2187   for (keyi=min_keycode; keyi<=max_keycode; keyi++)
2188       if ((keyc2scan[keyi]) == scanCode)
2189          break;
2190   if (keyi <= max_keycode)
2191   {
2192       wine_tsx11_lock();
2193       keyc = (KeyCode) keyi;
2194       keys = XKeycodeToKeysym(thread_display(), keyc, 0);
2195       name = XKeysymToString(keys);
2196       wine_tsx11_unlock();
2197       TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
2198             scanCode, keyc, (int)keys, name);
2199       if (lpBuffer && nSize && name)
2200       {
2201           MultiByteToWideChar(CP_UNIXCP, 0, name, -1, lpBuffer, nSize);
2202           lpBuffer[nSize - 1] = 0;
2203           return 1;
2204       }
2205   }
2206
2207   /* Finally issue FIXME for unknown keys   */
2208
2209   FIXME("(%08x,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
2210   if (lpBuffer && nSize)
2211     *lpBuffer = 0;
2212   return 0;
2213 }
2214
2215 /***********************************************************************
2216  *              X11DRV_KEYBOARD_MapDeadKeysym
2217  */
2218 static char KEYBOARD_MapDeadKeysym(KeySym keysym)
2219 {
2220         switch (keysym)
2221             {
2222         /* symbolic ASCII is the same as defined in rfc1345 */
2223 #ifdef XK_dead_tilde
2224             case XK_dead_tilde :
2225 #endif
2226             case 0x1000FE7E : /* Xfree's XK_Dtilde */
2227                 return '~';     /* '? */
2228 #ifdef XK_dead_acute
2229             case XK_dead_acute :
2230 #endif
2231             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
2232                 return 0xb4;    /* '' */
2233 #ifdef XK_dead_circumflex
2234             case XK_dead_circumflex:
2235 #endif
2236             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
2237                 return '^';     /* '> */
2238 #ifdef XK_dead_grave
2239             case XK_dead_grave :
2240 #endif
2241             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
2242                 return '`';     /* '! */
2243 #ifdef XK_dead_diaeresis
2244             case XK_dead_diaeresis :
2245 #endif
2246             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
2247                 return 0xa8;    /* ': */
2248 #ifdef XK_dead_cedilla
2249             case XK_dead_cedilla :
2250                 return 0xb8;    /* ', */
2251 #endif
2252 #ifdef XK_dead_macron
2253             case XK_dead_macron :
2254                 return '-';     /* 'm isn't defined on iso-8859-x */
2255 #endif
2256 #ifdef XK_dead_breve
2257             case XK_dead_breve :
2258                 return 0xa2;    /* '( */
2259 #endif
2260 #ifdef XK_dead_abovedot
2261             case XK_dead_abovedot :
2262                 return 0xff;    /* '. */
2263 #endif
2264 #ifdef XK_dead_abovering
2265             case XK_dead_abovering :
2266                 return '0';     /* '0 isn't defined on iso-8859-x */
2267 #endif
2268 #ifdef XK_dead_doubleacute
2269             case XK_dead_doubleacute :
2270                 return 0xbd;    /* '" */
2271 #endif
2272 #ifdef XK_dead_caron
2273             case XK_dead_caron :
2274                 return 0xb7;    /* '< */
2275 #endif
2276 #ifdef XK_dead_ogonek
2277             case XK_dead_ogonek :
2278                 return 0xb2;    /* '; */
2279 #endif
2280 /* FIXME: I don't know this three.
2281             case XK_dead_iota :
2282                 return 'i';
2283             case XK_dead_voiced_sound :
2284                 return 'v';
2285             case XK_dead_semivoiced_sound :
2286                 return 's';
2287 */
2288             }
2289         TRACE("no character for dead keysym 0x%08lx\n",keysym);
2290         return 0;
2291 }
2292
2293 /***********************************************************************
2294  *              ToUnicodeEx (X11DRV.@)
2295  *
2296  * The ToUnicode function translates the specified virtual-key code and keyboard
2297  * state to the corresponding Windows character or characters.
2298  *
2299  * If the specified key is a dead key, the return value is negative. Otherwise,
2300  * it is one of the following values:
2301  * Value        Meaning
2302  * 0    The specified virtual key has no translation for the current state of the keyboard.
2303  * 1    One Windows character was copied to the buffer.
2304  * 2    Two characters were copied to the buffer. This usually happens when a
2305  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
2306  *      be composed with the specified virtual key to form a single character.
2307  *
2308  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
2309  *
2310  */
2311 INT X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
2312                      LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
2313 {
2314     Display *display = thread_display();
2315     XKeyEvent e;
2316     KeySym keysym = 0;
2317     INT ret;
2318     int keyc;
2319     char lpChar[10];
2320     HWND focus;
2321     XIC xic;
2322     Status status;
2323
2324     if (scanCode & 0x8000)
2325     {
2326         TRACE("Key UP, doing nothing\n" );
2327         return 0;
2328     }
2329
2330     if (hkl != X11DRV_GetKeyboardLayout(0))
2331         FIXME("keyboard layout %p is not supported\n", hkl);
2332
2333     if ((lpKeyState[VK_MENU] & 0x80) && (lpKeyState[VK_CONTROL] & 0x80))
2334     {
2335         TRACE("Ctrl+Alt+[key] won't generate a character\n");
2336         return 0;
2337     }
2338
2339     e.display = display;
2340     e.keycode = 0;
2341     e.state = 0;
2342     e.type = KeyPress;
2343
2344     focus = GetFocus();
2345     if (focus) focus = GetAncestor( focus, GA_ROOT );
2346     if (!focus) focus = GetActiveWindow();
2347     e.window = X11DRV_get_whole_window( focus );
2348     xic = X11DRV_get_ic( focus );
2349
2350     if (lpKeyState[VK_SHIFT] & 0x80)
2351     {
2352         TRACE("ShiftMask = %04x\n", ShiftMask);
2353         e.state |= ShiftMask;
2354     }
2355     if (lpKeyState[VK_CAPITAL] & 0x01)
2356     {
2357         TRACE("LockMask = %04x\n", LockMask);
2358         e.state |= LockMask;
2359     }
2360     if (lpKeyState[VK_CONTROL] & 0x80)
2361     {
2362         TRACE("ControlMask = %04x\n", ControlMask);
2363         e.state |= ControlMask;
2364     }
2365     if (lpKeyState[VK_NUMLOCK] & 0x01)
2366     {
2367         TRACE("NumLockMask = %04x\n", NumLockMask);
2368         e.state |= NumLockMask;
2369     }
2370
2371     /* Restore saved AltGr state */
2372     TRACE("AltGrMask = %04x\n", AltGrMask);
2373     e.state |= AltGrMask;
2374
2375     TRACE_(key)("(%04X, %04X) : faked state = 0x%04x\n",
2376                 virtKey, scanCode, e.state);
2377     wine_tsx11_lock();
2378     /* We exit on the first keycode found, to speed up the thing. */
2379     for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2380       { /* Find a keycode that could have generated this virtual key */
2381           if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
2382           { /* We filter the extended bit, we don't know it */
2383               e.keycode = keyc; /* Store it temporarily */
2384               if ((EVENT_event_to_vkey(xic,&e) & 0xFF) != virtKey) {
2385                   e.keycode = 0; /* Wrong one (ex: because of the NumLock
2386                          state), so set it to 0, we'll find another one */
2387               }
2388           }
2389       }
2390
2391     if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
2392         e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
2393
2394     if (virtKey==VK_DECIMAL)
2395         e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2396
2397     if (virtKey==VK_SEPARATOR)
2398         e.keycode = XKeysymToKeycode(e.display, XK_KP_Separator);
2399
2400     if (!e.keycode && virtKey != VK_NONAME)
2401       {
2402         WARN("Unknown virtual key %X !!!\n", virtKey);
2403         wine_tsx11_unlock();
2404         return virtKey; /* whatever */
2405       }
2406     else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2407
2408     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
2409                 e.type, e.window, e.state, e.keycode);
2410
2411     if (xic)
2412         ret = XmbLookupString(xic, &e, lpChar, sizeof(lpChar), &keysym, &status);
2413     else
2414         ret = XLookupString(&e, lpChar, sizeof(lpChar), &keysym, NULL);
2415     wine_tsx11_unlock();
2416
2417     if (ret == 0)
2418     {
2419         char dead_char;
2420
2421 #ifdef XK_EuroSign
2422         /* An ugly hack for EuroSign: X can't translate it to a character
2423            for some locales. */
2424         if (keysym == XK_EuroSign)
2425         {
2426             bufW[0] = 0x20AC;
2427             ret = 1;
2428             goto found;
2429         }
2430 #endif
2431         /* Special case: X turns shift-tab into ISO_Left_Tab. */
2432         /* Here we change it back. */
2433         if (keysym == XK_ISO_Left_Tab)
2434         {
2435             bufW[0] = 0x09;
2436             ret = 1;
2437             goto found;
2438         }
2439
2440         dead_char = KEYBOARD_MapDeadKeysym(keysym);
2441         if (dead_char)
2442             {
2443             MultiByteToWideChar(CP_UNIXCP, 0, &dead_char, 1, bufW, bufW_size);
2444             ret = -1;
2445             }
2446         else
2447             {
2448             const char *ksname;
2449
2450             wine_tsx11_lock();
2451             ksname = XKeysymToString(keysym);
2452             wine_tsx11_unlock();
2453             if (!ksname)
2454                 ksname = "No Name";
2455             if ((keysym >> 8) != 0xff)
2456                 {
2457                 ERR("Please report: no char for keysym %04lX (%s) :\n",
2458                     keysym, ksname);
2459                 ERR("(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
2460                     virtKey, scanCode, e.keycode, e.state);
2461                 }
2462             }
2463         }
2464     else {  /* ret != 0 */
2465         /* We have a special case to handle : Shift + arrow, shift + home, ...
2466            X returns a char for it, but Windows doesn't. Let's eat it. */
2467         if (!(e.state & NumLockMask)  /* NumLock is off */
2468             && (e.state & ShiftMask) /* Shift is pressed */
2469             && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
2470         {
2471             lpChar[0] = 0;
2472             ret = 0;
2473         }
2474
2475         /* more areas where X returns characters but Windows does not
2476            CTRL + number or CTRL + symbol */
2477         if (e.state & ControlMask)
2478         {
2479             if (((keysym>=33) && (keysym < 'A')) ||
2480                 ((keysym > 'Z') && (keysym < 'a')))
2481             {
2482                 lpChar[0] = 0;
2483                 ret = 0;
2484             }
2485         }
2486
2487         /* We have another special case for delete key (XK_Delete) on an
2488          extended keyboard. X returns a char for it, but Windows doesn't */
2489         if (keysym == XK_Delete)
2490         {
2491             lpChar[0] = 0;
2492             ret = 0;
2493         }
2494         else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
2495                 && (keysym == XK_KP_Decimal))
2496         {
2497             lpChar[0] = 0;
2498             ret = 0;
2499         }
2500
2501         /* perform translation to unicode */
2502         if(ret)
2503         {
2504             TRACE_(key)("Translating char 0x%02x to unicode\n", *(BYTE *)lpChar);
2505             ret = MultiByteToWideChar(CP_UNIXCP, 0, lpChar, ret, bufW, bufW_size);
2506         }
2507     }
2508
2509 found:
2510     TRACE_(key)("ToUnicode about to return %d with char %x %s\n",
2511                 ret, (ret && bufW) ? bufW[0] : 0, bufW ? "" : "(no buffer)");
2512     return ret;
2513 }
2514
2515 /***********************************************************************
2516  *              Beep (X11DRV.@)
2517  */
2518 void X11DRV_Beep(void)
2519 {
2520     wine_tsx11_lock();
2521     XBell(thread_display(), 0);
2522     wine_tsx11_unlock();
2523 }