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