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