Replace "Registry Explorer" by "Registry Editor" in about dialog.
[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 (setxkbmap ee) */
395 static const char main_key_ET[MAIN_LEN][4] =
396 {
397  "·~","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","´`",
398  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","üÜ","õÕ",
399  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*",
400  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
401  "<>"
402 };
403
404 /*** Canadian French keyboard layout */
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     Status status;
1065     char buf[24];
1066
1067     if (xic)
1068         XmbLookupString(xic, e, buf, sizeof(buf), &keysym, &status);
1069     else
1070         XLookupString(e, buf, sizeof(buf), &keysym, NULL);
1071
1072     if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (keysym != 0xFFAF)
1073         && (e->state & NumLockMask))
1074         /* Only the Keypad keys 0-9 and . send different keysyms
1075          * depending on the NumLock state */
1076         return nonchar_key_vkey[keysym & 0xFF];
1077
1078     TRACE_(key)("e->keycode = %x\n", e->keycode);
1079
1080     return keyc2vkey[e->keycode];
1081 }
1082
1083 static BOOL NumState=FALSE, CapsState=FALSE;
1084
1085
1086 /***********************************************************************
1087  *           X11DRV_send_keyboard_input
1088  */
1089 void X11DRV_send_keyboard_input( WORD wVk, WORD wScan, DWORD dwFlags, DWORD time,
1090                                  DWORD dwExtraInfo, UINT injected_flags )
1091 {
1092     UINT message;
1093     KEYLP keylp;
1094     KBDLLHOOKSTRUCT hook;
1095
1096     keylp.lp2 = 0;
1097     keylp.lp1.count = 1;
1098     keylp.lp1.code = wScan;
1099     keylp.lp1.extended = (dwFlags & KEYEVENTF_EXTENDEDKEY) != 0;
1100     keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
1101                                 * don't remember where I read it - AK */
1102                                 /* it's '1' under windows, when a dialog box appears
1103                                  * and you press one of the underlined keys - DF*/
1104
1105     /* note that there is a test for all this */
1106     if (dwFlags & KEYEVENTF_KEYUP )
1107     {
1108         message = WM_KEYUP;
1109         if ((key_state_table[VK_MENU] & 0x80) &&
1110             ((wVk == VK_MENU) || (wVk == VK_CONTROL) || !(key_state_table[VK_CONTROL] & 0x80)))
1111         {
1112             if( TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */
1113                 (wVk != VK_MENU)) /* <ALT>-down...<something else>-up */
1114                 message = WM_SYSKEYUP;
1115             TrackSysKey = 0;
1116         }
1117         key_state_table[wVk] &= ~0x80;
1118         keylp.lp1.previous = 1;
1119         keylp.lp1.transition = 1;
1120     }
1121     else
1122     {
1123         keylp.lp1.previous = (key_state_table[wVk] & 0x80) != 0;
1124         keylp.lp1.transition = 0;
1125         if (!(key_state_table[wVk] & 0x80)) key_state_table[wVk] ^= 0x01;
1126         key_state_table[wVk] |= 0xc0;
1127
1128         message = WM_KEYDOWN;
1129         if ((key_state_table[VK_MENU] & 0x80) && !(key_state_table[VK_CONTROL] & 0x80))
1130         {
1131             message = WM_SYSKEYDOWN;
1132             TrackSysKey = wVk;
1133         }
1134     }
1135
1136     keylp.lp1.context = (key_state_table[VK_MENU] & 0x80) != 0; /* 1 if alt */
1137
1138     TRACE_(key)(" wParam=%04x, lParam=%08lx, InputKeyState=%x\n",
1139                 wVk, keylp.lp2, key_state_table[wVk] );
1140
1141     hook.vkCode      = wVk;
1142     hook.scanCode    = wScan;
1143     hook.flags       = (keylp.lp2 >> 24) | injected_flags;
1144     hook.time        = time;
1145     hook.dwExtraInfo = dwExtraInfo;
1146     if (HOOK_CallHooks( WH_KEYBOARD_LL, HC_ACTION, message, (LPARAM)&hook, TRUE )) return;
1147
1148     SERVER_START_REQ( send_message )
1149     {
1150         req->id       = (injected_flags & LLKHF_INJECTED) ? 0 : GetCurrentThreadId();
1151         req->type     = MSG_HARDWARE;
1152         req->flags    = 0;
1153         req->win      = 0;
1154         req->msg      = message;
1155         req->wparam   = wVk;
1156         req->lparam   = keylp.lp2;
1157         req->x        = cursor_pos.x;
1158         req->y        = cursor_pos.y;
1159         req->time     = time;
1160         req->info     = dwExtraInfo;
1161         req->timeout  = -1;
1162         req->callback = NULL;
1163         wine_server_call( req );
1164     }
1165     SERVER_END_REQ;
1166 }
1167
1168
1169 /**********************************************************************
1170  *              KEYBOARD_GenerateMsg
1171  *
1172  * Generate Down+Up messages when NumLock or CapsLock is pressed.
1173  *
1174  * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
1175  *
1176  */
1177 static void KEYBOARD_GenerateMsg( WORD vkey, WORD scan, int Evtype, DWORD event_time )
1178 {
1179   BOOL * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
1180   DWORD up, down;
1181
1182   if (*State) {
1183     /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
1184        don't treat it. It's from the same key press. Then the state goes to ON.
1185        And from there, a 'release' event will switch off the toggle key. */
1186     *State=FALSE;
1187     TRACE("INTERM : don't treat release of toggle key. key_state_table[%#x] = %#x\n",
1188           vkey,key_state_table[vkey]);
1189   } else
1190     {
1191         down = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0);
1192         up = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0) | KEYEVENTF_KEYUP;
1193         if ( key_state_table[vkey] & 0x1 ) /* it was ON */
1194           {
1195             if (Evtype!=KeyPress)
1196               {
1197                 TRACE("ON + KeyRelease => generating DOWN and UP messages.\n");
1198                 X11DRV_send_keyboard_input( vkey, scan, down, event_time, 0, 0 );
1199                 X11DRV_send_keyboard_input( vkey, scan, up, event_time, 0, 0 );
1200                 *State=FALSE;
1201                 key_state_table[vkey] &= ~0x01; /* Toggle state to off. */
1202               }
1203           }
1204         else /* it was OFF */
1205           if (Evtype==KeyPress)
1206             {
1207               TRACE("OFF + Keypress => generating DOWN and UP messages.\n");
1208               X11DRV_send_keyboard_input( vkey, scan, down, event_time, 0, 0 );
1209               X11DRV_send_keyboard_input( vkey, scan, up, event_time, 0, 0 );
1210               *State=TRUE; /* Goes to intermediary state before going to ON */
1211               key_state_table[vkey] |= 0x01; /* Toggle state to on. */
1212             }
1213     }
1214 }
1215
1216 /***********************************************************************
1217  *           KEYBOARD_UpdateOneState
1218  *
1219  * Updates internal state for <vkey>, depending on key <state> under X
1220  *
1221  */
1222 inline static void KEYBOARD_UpdateOneState ( int vkey, int state, DWORD time )
1223 {
1224     /* Do something if internal table state != X state for keycode */
1225     if (((key_state_table[vkey] & 0x80)!=0) != state)
1226     {
1227         TRACE("Adjusting state for vkey %#.2x. State before %#.2x\n",
1228               vkey, key_state_table[vkey]);
1229
1230         /* Fake key being pressed inside wine */
1231         X11DRV_send_keyboard_input( vkey, 0, state? 0 : KEYEVENTF_KEYUP, time, 0, 0 );
1232
1233         TRACE("State after %#.2x\n",key_state_table[vkey]);
1234     }
1235 }
1236
1237 /***********************************************************************
1238  *           X11DRV_KeymapNotify
1239  *
1240  * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
1241  *
1242  * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
1243  * from wine to another application and back.
1244  * Toggle keys are handled in HandleEvent.
1245  */
1246 void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
1247 {
1248     int i, j, alt, control, shift;
1249     DWORD time = GetCurrentTime();
1250
1251     alt = control = shift = 0;
1252     for (i = 0; i < 32; i++)
1253     {
1254         if (!event->xkeymap.key_vector[i]) continue;
1255         for (j = 0; j < 8; j++)
1256         {
1257             if (!(event->xkeymap.key_vector[i] & (1<<j))) continue;
1258             switch(keyc2vkey[(i * 8) + j] & 0xff)
1259             {
1260             case VK_MENU:    alt = 1; break;
1261             case VK_CONTROL: control = 1; break;
1262             case VK_SHIFT:   shift = 1; break;
1263             }
1264         }
1265     }
1266     KEYBOARD_UpdateOneState( VK_MENU, alt, time );
1267     KEYBOARD_UpdateOneState( VK_CONTROL, control, time );
1268     KEYBOARD_UpdateOneState( VK_SHIFT, shift, time );
1269 }
1270
1271 /***********************************************************************
1272  *           X11DRV_KeyEvent
1273  *
1274  * Handle a X key event
1275  */
1276 void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
1277 {
1278     XKeyEvent *event = &xev->xkey;
1279     char Str[24];
1280     KeySym keysym = 0;
1281     WORD vkey = 0, bScan;
1282     DWORD dwFlags;
1283     int ascii_chars;
1284     XIC xic = X11DRV_get_ic( hwnd );
1285     DWORD event_time = EVENT_x11_time_to_win32_time(event->time);
1286     Status status = 0;
1287
1288     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
1289                 event->type, event->window, event->state, event->keycode);
1290
1291     wine_tsx11_lock();
1292     if (xic)
1293         ascii_chars = XmbLookupString(xic, event, Str, sizeof(Str), &keysym, &status);
1294     else
1295         ascii_chars = XLookupString(event, Str, sizeof(Str), &keysym, NULL);
1296     wine_tsx11_unlock();
1297
1298     /* Ignore some unwanted events */
1299     if ((keysym >= XK_ISO_Lock && keysym <= XK_ISO_Last_Group_Lock) ||
1300          keysym == XK_Mode_switch)
1301     {
1302         wine_tsx11_lock();
1303         TRACE("Ignoring %s keyboard event\n", XKeysymToString(keysym));
1304         wine_tsx11_unlock();
1305         return;
1306     }
1307
1308     TRACE_(key)("state = %X nbyte = %d, status 0x%x\n", event->state, ascii_chars, status);
1309
1310     if (status == XBufferOverflow)
1311         ERR("Buffer Overflow need %i!\n",ascii_chars);
1312
1313     if (status == XLookupChars)
1314     {
1315         X11DRV_XIMLookupChars( Str, ascii_chars );
1316         return;
1317     }
1318
1319     /* If XKB extensions are used, the state mask for AltGr will use the group
1320        index instead of the modifier mask. The group index is set in bits
1321        13-14 of the state field in the XKeyEvent structure. So if AltGr is
1322        pressed, look if the group index is different than 0. From XKB
1323        extension documentation, the group index for AltGr should be 2
1324        (event->state = 0x2000). It's probably better to not assume a
1325        predefined group index and find it dynamically
1326
1327        Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
1328     /* Save also all possible modifier states. */
1329     AltGrMask = event->state & (0x6000 | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
1330
1331     Str[ascii_chars] = '\0';
1332     if (TRACE_ON(key)){
1333         char    *ksname;
1334
1335         wine_tsx11_lock();
1336         ksname = XKeysymToString(keysym);
1337         wine_tsx11_unlock();
1338         if (!ksname)
1339           ksname = "No Name";
1340         TRACE_(key)("%s : keysym=%lX (%s), # of chars=%d / 0x%02x / '%s'\n",
1341                     (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
1342                     keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
1343     }
1344
1345     wine_tsx11_lock();
1346     vkey = EVENT_event_to_vkey(xic,event);
1347     /* X returns keycode 0 for composed characters */
1348     if (!vkey && ascii_chars) vkey = VK_NONAME;
1349     wine_tsx11_unlock();
1350
1351     TRACE_(key)("keycode 0x%x converted to vkey 0x%x\n",
1352                 event->keycode, vkey);
1353
1354    if (vkey)
1355    {
1356     switch (vkey & 0xff)
1357     {
1358     case VK_NUMLOCK:
1359       KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, event->type, event_time );
1360       break;
1361     case VK_CAPITAL:
1362       TRACE("Caps Lock event. (type %d). State before : %#.2x\n",event->type,key_state_table[vkey]);
1363       KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, event->type, event_time );
1364       TRACE("State after : %#.2x\n",key_state_table[vkey]);
1365       break;
1366     default:
1367         /* Adjust the NUMLOCK state if it has been changed outside wine */
1368         if (!(key_state_table[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
1369           {
1370             TRACE("Adjusting NumLock state.\n");
1371             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyPress, event_time );
1372             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyRelease, event_time );
1373           }
1374         /* Adjust the CAPSLOCK state if it has been changed outside wine */
1375         if (!(key_state_table[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
1376           {
1377               TRACE("Adjusting Caps Lock state.\n");
1378             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyPress, event_time );
1379             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyRelease, event_time );
1380           }
1381         /* Not Num nor Caps : end of intermediary states for both. */
1382         NumState = FALSE;
1383         CapsState = FALSE;
1384
1385         bScan = keyc2scan[event->keycode] & 0xFF;
1386         TRACE_(key)("bScan = 0x%02x.\n", bScan);
1387
1388         dwFlags = 0;
1389         if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
1390         if ( vkey & 0x100 )              dwFlags |= KEYEVENTF_EXTENDEDKEY;
1391
1392         X11DRV_send_keyboard_input( vkey & 0xff, bScan, dwFlags, event_time, 0, 0 );
1393     }
1394    }
1395 }
1396
1397 /**********************************************************************
1398  *              X11DRV_KEYBOARD_DetectLayout
1399  *
1400  * Called from X11DRV_InitKeyboard
1401  *  This routine walks through the defined keyboard layouts and selects
1402  *  whichever matches most closely.
1403  * X11 lock must be held.
1404  */
1405 static void
1406 X11DRV_KEYBOARD_DetectLayout (void)
1407 {
1408   Display *display = thread_display();
1409   unsigned current, match, mismatch, seq, i, syms;
1410   int score, keyc, key, pkey, ok;
1411   KeySym keysym;
1412   const char (*lkey)[MAIN_LEN][4];
1413   unsigned max_seq = 0;
1414   int max_score = 0, ismatch = 0;
1415   char ckey[4] =
1416   {0, 0, 0, 0};
1417
1418   syms = keysyms_per_keycode;
1419   if (syms > 4) {
1420     WARN("%d keysyms per keycode not supported, set to 4\n", syms);
1421     syms = 4;
1422   }
1423   for (current = 0; main_key_tab[current].comment; current++) {
1424     TRACE("Attempting to match against \"%s\"\n", main_key_tab[current].comment);
1425     match = 0;
1426     mismatch = 0;
1427     score = 0;
1428     seq = 0;
1429     lkey = main_key_tab[current].key;
1430     pkey = -1;
1431     for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1432       /* get data for keycode from X server */
1433       for (i = 0; i < syms; i++) {
1434         keysym = XKeycodeToKeysym (display, keyc, i);
1435         /* Allow both one-byte and two-byte national keysyms */
1436         if ((keysym < 0x8000) && (keysym != ' '))
1437         {
1438 #ifdef HAVE_XKB
1439             if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
1440 #endif
1441             {
1442                 TRACE("XKB could not translate keysym %ld\n", keysym);
1443                 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1444                  * with appropriate ShiftMask and Mode_switch, use XLookupString
1445                  * to get character in the local encoding.
1446                  */
1447                 ckey[i] = keysym & 0xFF;
1448             }
1449         }
1450         else {
1451           ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1452         }
1453       }
1454       if (ckey[0]) {
1455         /* search for a match in layout table */
1456         /* right now, we just find an absolute match for defined positions */
1457         /* (undefined positions are ignored, so if it's defined as "3#" in */
1458         /* the table, it's okay that the X server has "3#£", for example) */
1459         /* however, the score will be higher for longer matches */
1460         for (key = 0; key < MAIN_LEN; key++) {
1461           for (ok = 0, i = 0; (ok >= 0) && (i < syms); i++) {
1462             if ((*lkey)[key][i] && ((*lkey)[key][i] == ckey[i]))
1463               ok++;
1464             if ((*lkey)[key][i] && ((*lkey)[key][i] != ckey[i]))
1465               ok = -1;
1466           }
1467           if (ok > 0) {
1468             score += ok;
1469             break;
1470           }
1471         }
1472         /* count the matches and mismatches */
1473         if (ok > 0) {
1474           match++;
1475           /* and how much the keycode order matches */
1476           if (key > pkey) seq++;
1477           pkey = key;
1478         } else {
1479           /* print spaces instead of \0's */
1480           for (i = 0; i < sizeof(ckey); i++) if (!ckey[i]) ckey[i] = ' ';
1481           TRACE_(key)("mismatch for keysym 0x%04lX, keycode %d, got %c%c%c%c\n",
1482                       keysym, keyc, ckey[0], ckey[1], ckey[2], ckey[3]);
1483           mismatch++;
1484           score -= syms;
1485         }
1486       }
1487     }
1488     TRACE("matches=%d, mismatches=%d, seq=%d, score=%d\n",
1489            match, mismatch, seq, score);
1490     if ((score > max_score) ||
1491         ((score == max_score) && (seq > max_seq))) {
1492       /* best match so far */
1493       kbd_layout = current;
1494       max_score = score;
1495       max_seq = seq;
1496       ismatch = !mismatch;
1497     }
1498   }
1499   /* we're done, report results if necessary */
1500   if (!ismatch)
1501     WARN("Using closest match (%s) for scan/virtual codes mapping.\n",
1502         main_key_tab[kbd_layout].comment);
1503
1504   TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment);
1505 }
1506
1507 /**********************************************************************
1508  *              X11DRV_InitKeyboard
1509  */
1510 void X11DRV_InitKeyboard(void)
1511 {
1512     Display *display = thread_display();
1513     KeySym *ksp;
1514     XModifierKeymap *mmp;
1515     KeySym keysym;
1516     KeyCode *kcp;
1517     XKeyEvent e2;
1518     WORD scan, vkey, OEMvkey;
1519     int keyc, i, keyn, syms;
1520     char ckey[4]={0,0,0,0};
1521     const char (*lkey)[MAIN_LEN][4];
1522
1523     wine_tsx11_lock();
1524     XDisplayKeycodes(display, &min_keycode, &max_keycode);
1525     ksp = XGetKeyboardMapping(display, min_keycode,
1526                               max_keycode + 1 - min_keycode, &keysyms_per_keycode);
1527     /* We are only interested in keysyms_per_keycode.
1528        There is no need to hold a local copy of the keysyms table */
1529     XFree(ksp);
1530
1531     mmp = XGetModifierMapping(display);
1532     kcp = mmp->modifiermap;
1533     for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
1534     {
1535         int j;
1536
1537         for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
1538             if (*kcp)
1539             {
1540                 int k;
1541
1542                 for (k = 0; k < keysyms_per_keycode; k += 1)
1543                     if (XKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
1544                     {
1545                         NumLockMask = 1 << i;
1546                         TRACE_(key)("NumLockMask is %x\n", NumLockMask);
1547                     }
1548             }
1549     }
1550     XFreeModifiermap(mmp);
1551
1552     /* Detect the keyboard layout */
1553     X11DRV_KEYBOARD_DetectLayout();
1554     lkey = main_key_tab[kbd_layout].key;
1555     syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode;
1556
1557     /* Now build two conversion arrays :
1558      * keycode -> vkey + scancode + extended
1559      * vkey + extended -> keycode */
1560
1561     e2.display = display;
1562     e2.state = 0;
1563
1564     OEMvkey = VK_OEM_8; /* next is available.  */
1565     for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1566     {
1567         char buf[30];
1568         int have_chars;
1569
1570         keysym = 0;
1571         e2.keycode = (KeyCode)keyc;
1572         have_chars = XLookupString(&e2, buf, sizeof(buf), &keysym, NULL);
1573         vkey = 0; scan = 0;
1574         if (keysym)  /* otherwise, keycode not used */
1575         {
1576             if ((keysym >> 8) == 0xFF)         /* non-character key */
1577             {
1578                 vkey = nonchar_key_vkey[keysym & 0xff];
1579                 scan = nonchar_key_scan[keysym & 0xff];
1580                 /* set extended bit when necessary */
1581                 if (scan & 0x100) vkey |= 0x100;
1582             } else if (keysym == 0x20) {                 /* Spacebar */
1583                 vkey = VK_SPACE;
1584                 scan = 0x39;
1585             } else if (have_chars) {
1586               /* we seem to need to search the layout-dependent scancodes */
1587               int maxlen=0,maxval=-1,ok;
1588               for (i=0; i<syms; i++) {
1589                 keysym = XKeycodeToKeysym(display, keyc, i);
1590                 if ((keysym<0x8000) && (keysym!=' '))
1591                 {
1592 #ifdef HAVE_XKB
1593                     if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
1594 #endif
1595                     {
1596                         /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1597                          * with appropriate ShiftMask and Mode_switch, use XLookupString
1598                          * to get character in the local encoding.
1599                          */
1600                         ckey[i] = keysym & 0xFF;
1601                     }
1602                 } else {
1603                   ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1604                 }
1605               }
1606               /* find key with longest match streak */
1607               for (keyn=0; keyn<MAIN_LEN; keyn++) {
1608                 for (ok=(*lkey)[keyn][i=0]; ok&&(i<4); i++)
1609                   if ((*lkey)[keyn][i] && (*lkey)[keyn][i]!=ckey[i]) ok=0;
1610                 if (ok||(i>maxlen)) {
1611                   maxlen=i; maxval=keyn;
1612                 }
1613                 if (ok) break;
1614               }
1615               if (maxval>=0) {
1616                 /* got it */
1617                 const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan;
1618                 const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey;
1619                 scan = (*lscan)[maxval];
1620                 vkey = (*lvkey)[maxval];
1621               }
1622             }
1623 #if 0 /* this breaks VK_OEM_x VKeys in some layout tables by inserting
1624        * a VK code into a not appropriate place.
1625        */
1626             /* find a suitable layout-dependent VK code */
1627             /* (most Winelib apps ought to be able to work without layout tables!) */
1628             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1629             {
1630                 keysym = XLookupKeysym(&e2, i);
1631                 if ((keysym >= VK_0 && keysym <= VK_9)
1632                     || (keysym >= VK_A && keysym <= VK_Z)) {
1633                     vkey = keysym;
1634                 }
1635             }
1636
1637             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1638             {
1639                 keysym = XLookupKeysym(&e2, i);
1640                 switch (keysym)
1641                 {
1642                 case ';':             vkey = VK_OEM_1; break;
1643                 case '/':             vkey = VK_OEM_2; break;
1644                 case '`':             vkey = VK_OEM_3; break;
1645                 case '[':             vkey = VK_OEM_4; break;
1646                 case '\\':            vkey = VK_OEM_5; break;
1647                 case ']':             vkey = VK_OEM_6; break;
1648                 case '\'':            vkey = VK_OEM_7; break;
1649                 case ',':             vkey = VK_OEM_COMMA; break;
1650                 case '.':             vkey = VK_OEM_PERIOD; break;
1651                 case '-':             vkey = VK_OEM_MINUS; break;
1652                 case '+':             vkey = VK_OEM_PLUS; break;
1653                 }
1654             }
1655
1656             if (!vkey)
1657             {
1658                 /* Others keys: let's assign OEM virtual key codes in the allowed range,
1659                  * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
1660                 switch (++OEMvkey)
1661                 {
1662                 case 0xc1 : OEMvkey=0xdb; break;
1663                 case 0xe5 : OEMvkey=0xe9; break;
1664                 case 0xf6 : OEMvkey=0xf5; WARN("No more OEM vkey available!\n");
1665                 }
1666
1667                 vkey = OEMvkey;
1668
1669                 if (TRACE_ON(keyboard))
1670                 {
1671                     TRACE("OEM specific virtual key %X assigned to keycode %X:\n",
1672                                      OEMvkey, e2.keycode);
1673                     TRACE("(");
1674                     for (i = 0; i < keysyms_per_keycode; i += 1)
1675                     {
1676                         char    *ksname;
1677
1678                         keysym = XLookupKeysym(&e2, i);
1679                         ksname = XKeysymToString(keysym);
1680                         if (!ksname)
1681                             ksname = "NoSymbol";
1682                         TRACE( "%lX (%s) ", keysym, ksname);
1683                     }
1684                     TRACE(")\n");
1685                 }
1686             }
1687 #endif
1688         }
1689         TRACE("keycode %04x => vkey %04x\n", e2.keycode, vkey);
1690         keyc2vkey[e2.keycode] = vkey;
1691         keyc2scan[e2.keycode] = scan;
1692     } /* for */
1693
1694     /* If some keys still lack scancodes, assign some arbitrary ones to them now */
1695     for (scan = 0x60, keyc = min_keycode; keyc <= max_keycode; keyc++)
1696       if (keyc2vkey[keyc]&&!keyc2scan[keyc]) {
1697         char *ksname;
1698         keysym = XKeycodeToKeysym(display, keyc, 0);
1699         ksname = XKeysymToString(keysym);
1700         if (!ksname) ksname = "NoSymbol";
1701
1702         /* should make sure the scancode is unassigned here, but >=0x60 currently always is */
1703
1704         TRACE_(key)("assigning scancode %02x to unidentified keycode %02x (%s)\n",scan,keyc,ksname);
1705         keyc2scan[keyc]=scan++;
1706       }
1707
1708     /* Now store one keycode for each modifier. Used to simulate keypresses. */
1709     kcControl = XKeysymToKeycode(display, XK_Control_L);
1710     kcAlt = XKeysymToKeycode(display, XK_Alt_L);
1711     if (!kcAlt) kcAlt = XKeysymToKeycode(display, XK_Meta_L);
1712     kcShift = XKeysymToKeycode(display, XK_Shift_L);
1713     kcNumLock = XKeysymToKeycode(display, XK_Num_Lock);
1714     kcCapsLock = XKeysymToKeycode(display, XK_Caps_Lock);
1715     wine_tsx11_unlock();
1716 }
1717
1718
1719 /**********************************************************************
1720  *              GetAsyncKeyState (X11DRV.@)
1721  */
1722 SHORT X11DRV_GetAsyncKeyState(INT key)
1723 {
1724     SHORT retval = ((key_state_table[key] & 0x40) ? 0x0001 : 0) |
1725                    ((key_state_table[key] & 0x80) ? 0x8000 : 0);
1726     key_state_table[key] &= ~0x40;
1727     TRACE_(key)("(%x) -> %x\n", key, retval);
1728     return retval;
1729 }
1730
1731
1732 /***********************************************************************
1733  *              GetKeyboardLayoutList (X11DRV.@)
1734  */
1735 UINT X11DRV_GetKeyboardLayoutList(INT size, HKL *hkl)
1736 {
1737     INT i;
1738
1739     TRACE("%d, %p\n", size, hkl);
1740
1741     if (!size)
1742     {
1743         size = 4096; /* hope we will never have that many */
1744         hkl = NULL;
1745     }
1746
1747     for (i = 0; main_key_tab[i].comment && (i < size); i++)
1748     {
1749         if (hkl)
1750         {
1751             DWORD layout = main_key_tab[i].lcid;
1752             LANGID langid;
1753
1754             /* see comment for GetKeyboardLayout */
1755             langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1756             if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1757                 layout |= 0xe001 << 16; /* FIXME */
1758             else
1759                 layout |= layout << 16;
1760
1761             hkl[i] = (HKL)layout;
1762         }
1763     }
1764     return i;
1765 }
1766
1767
1768 /***********************************************************************
1769  *              GetKeyboardLayout (X11DRV.@)
1770  */
1771 HKL X11DRV_GetKeyboardLayout(DWORD dwThreadid)
1772 {
1773     DWORD layout;
1774     LANGID langid;
1775
1776     if (dwThreadid && dwThreadid != GetCurrentThreadId())
1777         FIXME("couldn't return keyboard layout for thread %04lx\n", dwThreadid);
1778
1779 #if 0
1780     layout = main_key_tab[kbd_layout].lcid;
1781 #else
1782     /* FIXME:
1783      * Winword uses return value of GetKeyboardLayout as a codepage
1784      * to translate ANSI keyboard messages to unicode. But we have
1785      * a problem with it: for instance Polish keyboard layout is
1786      * identical to the US one, and therefore instead of the Polish
1787      * locale id we return the US one.
1788      */
1789     layout = GetUserDefaultLCID();
1790 #endif
1791     /* 
1792      * Microsoft Office expects this value to be something specific
1793      * for Japanese and Korean Windows with an IME the value is 0xe001
1794      * We should probably check to see if an IME exists and if so then
1795      * set this word properly.
1796      */
1797     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1798     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1799         layout |= 0xe001 << 16; /* FIXME */
1800     else
1801         layout |= layout << 16;
1802
1803     return (HKL)layout;
1804 }
1805
1806
1807 /***********************************************************************
1808  *              GetKeyboardLayoutName (X11DRV.@)
1809  */
1810 BOOL X11DRV_GetKeyboardLayoutName(LPWSTR name)
1811 {
1812     static const WCHAR formatW[] = {'%','0','8','l','x',0};
1813     DWORD layout;
1814     LANGID langid;
1815
1816     layout = main_key_tab[kbd_layout].lcid;
1817     /* see comment for GetKeyboardLayout */
1818     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1819     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1820         layout |= 0xe001 << 16; /* FIXME */
1821     else
1822         layout |= layout << 16;
1823
1824     sprintfW(name, formatW, layout);
1825     TRACE("returning %s\n", debugstr_w(name));
1826     return TRUE;
1827 }
1828
1829
1830 /***********************************************************************
1831  *              LoadKeyboardLayout (X11DRV.@)
1832  */
1833 HKL X11DRV_LoadKeyboardLayout(LPCWSTR name, UINT flags)
1834 {
1835     FIXME("%s, %04x: stub!\n", debugstr_w(name), flags);
1836     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1837     return 0;
1838 }
1839
1840
1841 /***********************************************************************
1842  *              UnloadKeyboardLayout (X11DRV.@)
1843  */
1844 BOOL X11DRV_UnloadKeyboardLayout(HKL hkl)
1845 {
1846     FIXME("%p: stub!\n", hkl);
1847     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1848     return FALSE;
1849 }
1850
1851
1852 /***********************************************************************
1853  *              ActivateKeyboardLayout (X11DRV.@)
1854  */
1855 HKL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags)
1856 {
1857     FIXME("%p, %04x: stub!\n", hkl, flags);
1858     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1859     return 0;
1860 }
1861
1862
1863 /***********************************************************************
1864  *           X11DRV_MappingNotify
1865  */
1866 void X11DRV_MappingNotify( HWND dummy, XEvent *event )
1867 {
1868     HWND hwnd;
1869
1870     wine_tsx11_lock();
1871     XRefreshKeyboardMapping(&event->xmapping);
1872     wine_tsx11_unlock();
1873     X11DRV_InitKeyboard();
1874
1875     hwnd = GetFocus();
1876     if (!hwnd) hwnd = GetActiveWindow();
1877     PostMessageW(hwnd, WM_INPUTLANGCHANGEREQUEST,
1878                  0 /*FIXME*/, (LPARAM)X11DRV_GetKeyboardLayout(0));
1879 }
1880
1881
1882 /***********************************************************************
1883  *              VkKeyScanEx (X11DRV.@)
1884  *
1885  * Note: Windows ignores HKL parameter and uses current active layout instead
1886  */
1887 SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
1888 {
1889     Display *display = thread_display();
1890     KeyCode keycode;
1891     KeySym keysym;
1892     int i, index;
1893     CHAR cChar;
1894     SHORT ret;
1895
1896     /* FIXME: what happens if wChar is not a Latin1 character and CP_UNIXCP
1897      * is UTF-8 (multibyte encoding)?
1898      */
1899     if (!WideCharToMultiByte(CP_UNIXCP, 0, &wChar, 1, &cChar, 1, NULL, NULL))
1900     {
1901         WARN("no translation from unicode to CP_UNIXCP for 0x%02x\n", wChar);
1902         return -1;
1903     }
1904
1905     TRACE("wChar 0x%02x -> cChar '%c'\n", wChar, cChar);
1906
1907     /* char->keysym (same for ANSI chars) */
1908     keysym = (unsigned char)cChar; /* (!) cChar is signed */
1909     if (keysym <= 27) keysym += 0xFF00; /* special chars : return, backspace... */
1910
1911     wine_tsx11_lock();
1912     keycode = XKeysymToKeycode(display, keysym);  /* keysym -> keycode */
1913     if (!keycode)
1914     {
1915         if (keysym >= 0xFF00) /* Windows returns 0x0240 + cChar in this case */
1916         {
1917             ret = 0x0240 + cChar; /* 0x0200 indicates a control character */
1918             TRACE(" ... returning ctrl char %#.2x\n", ret);
1919             wine_tsx11_unlock();
1920             return ret;
1921         }
1922         /* It didn't work ... let's try with deadchar code. */
1923         TRACE("retrying with | 0xFE00\n");
1924         keycode = XKeysymToKeycode(display, keysym | 0xFE00);
1925     }
1926     wine_tsx11_unlock();
1927
1928     TRACE("'%c'(%#lx, %lu): got keycode %#.2x (%d)\n",
1929             cChar, keysym, keysym, keycode, keycode);
1930
1931     /* keycode -> (keyc2vkey) vkey */
1932     ret = keyc2vkey[keycode];
1933
1934     if (!keycode || !ret)
1935     {
1936         TRACE("keycode for '%c' not found, returning -1\n", cChar);
1937         return -1;
1938     }
1939
1940     index = -1;
1941     wine_tsx11_lock();
1942     for (i = 0; i < 4; i++) /* find shift state */
1943     {
1944         if (XKeycodeToKeysym(display, keycode, i) == keysym)
1945         {
1946             index = i;
1947             break;
1948         }
1949     }
1950     wine_tsx11_unlock();
1951
1952     switch (index)
1953     {
1954         default:
1955         case -1:
1956             WARN("Keysym %lx not found while parsing the keycode table\n", keysym);
1957             return -1;
1958
1959         case 0: break;
1960         case 1: ret += 0x0100; break;
1961         case 2: ret += 0x0600; break;
1962         case 3: ret += 0x0700; break;
1963     }
1964     /*
1965       index : 0     adds 0x0000
1966       index : 1     adds 0x0100 (shift)
1967       index : ?     adds 0x0200 (ctrl)
1968       index : 2     adds 0x0600 (ctrl+alt)
1969       index : 3     adds 0x0700 (ctrl+alt+shift)
1970      */
1971
1972     TRACE(" ... returning %#.2x\n", ret);
1973     return ret;
1974 }
1975
1976 /***********************************************************************
1977  *              MapVirtualKeyEx (X11DRV.@)
1978  */
1979 UINT X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
1980 {
1981     Display *display = thread_display();
1982
1983 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
1984
1985     TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl);
1986     if (hkl != X11DRV_GetKeyboardLayout(0))
1987         FIXME("keyboard layout %p is not supported\n", hkl);
1988
1989         switch(wMapType) {
1990                 case 0: { /* vkey-code to scan-code */
1991                         /* let's do vkey -> keycode -> scan */
1992                         int keyc;
1993                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1994                                 if ((keyc2vkey[keyc] & 0xFF) == wCode)
1995                                         returnMVK (keyc2scan[keyc] & 0xFF);
1996                         TRACE("returning no scan-code.\n");
1997                         return 0; }
1998
1999                 case 1: { /* scan-code to vkey-code */
2000                         /* let's do scan -> keycode -> vkey */
2001                         int keyc;
2002                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
2003                                 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
2004                                         returnMVK (keyc2vkey[keyc] & 0xFF);
2005                         TRACE("returning no vkey-code.\n");
2006                         return 0; }
2007
2008                 case 2: { /* vkey-code to unshifted ANSI code */
2009                         /* we still don't know what "unshifted" means. in windows VK_W (0x57)
2010                          * returns 0x57, which is upercase 'W'. So we have to return the uppercase
2011                          * key.. Looks like something is wrong with the MS docs?
2012                          * This is only true for letters, for example VK_0 returns '0' not ')'.
2013                          * - hence we use the lock mask to ensure this happens.
2014                          */
2015                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
2016                         XKeyEvent e;
2017                         KeySym keysym;
2018                         int keyc;
2019                         char s[2];
2020                         e.display = display;
2021
2022                         e.state = LockMask;
2023                         /* LockMask should behave exactly like caps lock - upercase
2024                          * the letter keys and thats about it. */
2025
2026                         wine_tsx11_lock();
2027
2028                         e.keycode = 0;
2029                         /* We exit on the first keycode found, to speed up the thing. */
2030                         for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2031                         { /* Find a keycode that could have generated this virtual key */
2032                             if  ((keyc2vkey[keyc] & 0xFF) == wCode)
2033                             { /* We filter the extended bit, we don't know it */
2034                                 e.keycode = keyc; /* Store it temporarily */
2035                                 if ((EVENT_event_to_vkey(0,&e) & 0xFF) != wCode) {
2036                                     e.keycode = 0; /* Wrong one (ex: because of the NumLock
2037                                          state), so set it to 0, we'll find another one */
2038                                 }
2039                             }
2040                         }
2041
2042                         if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
2043                           e.keycode = XKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
2044
2045                         if (wCode==VK_DECIMAL)
2046                           e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2047
2048                         if (!e.keycode)
2049                         {
2050                           WARN("Unknown virtual key %X !!! \n", wCode);
2051                           wine_tsx11_unlock();
2052                           return 0; /* whatever */
2053                         }
2054                         TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2055
2056                         if (XLookupString(&e, s, 2, &keysym, NULL))
2057                         {
2058                             wine_tsx11_unlock();
2059                             returnMVK (*s);
2060                         }
2061
2062                         TRACE("returning no ANSI.\n");
2063                         wine_tsx11_unlock();
2064                         return 0;
2065                         }
2066
2067                 case 3:   /* **NT only** scan-code to vkey-code but distinguish between  */
2068                           /*             left and right  */
2069                           FIXME(" stub for NT\n");
2070                           return 0;
2071
2072                 default: /* reserved */
2073                         WARN("Unknown wMapType %d !\n", wMapType);
2074                         return 0;
2075         }
2076         return 0;
2077 }
2078
2079 /***********************************************************************
2080  *              GetKeyNameText (X11DRV.@)
2081  */
2082 INT X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
2083 {
2084   int vkey, ansi, scanCode;
2085   KeyCode keyc;
2086   int keyi;
2087   KeySym keys;
2088   char *name;
2089
2090   scanCode = lParam >> 16;
2091   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
2092
2093   /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
2094   vkey = X11DRV_MapVirtualKeyEx(scanCode, 1, X11DRV_GetKeyboardLayout(0));
2095
2096   /*  handle "don't care" bit (0x02000000) */
2097   if (!(lParam & 0x02000000)) {
2098     switch (vkey) {
2099          case VK_LSHIFT:
2100          case VK_RSHIFT:
2101                           vkey = VK_SHIFT;
2102                           break;
2103        case VK_LCONTROL:
2104        case VK_RCONTROL:
2105                           vkey = VK_CONTROL;
2106                           break;
2107           case VK_LMENU:
2108           case VK_RMENU:
2109                           vkey = VK_MENU;
2110                           break;
2111                default:
2112                           break;
2113     }
2114   }
2115
2116   ansi = X11DRV_MapVirtualKeyEx(vkey, 2, X11DRV_GetKeyboardLayout(0));
2117   TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
2118
2119   /* first get the name of the "regular" keys which is the Upper case
2120      value of the keycap imprint.                                     */
2121   if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
2122        (scanCode != 0x137) &&   /* PrtScn   */
2123        (scanCode != 0x135) &&   /* numpad / */
2124        (scanCode != 0x37 ) &&   /* numpad * */
2125        (scanCode != 0x4a ) &&   /* numpad - */
2126        (scanCode != 0x4e ) )    /* numpad + */
2127       {
2128         if ((nSize >= 2) && lpBuffer)
2129         {
2130           *lpBuffer = toupperW((WCHAR)ansi);
2131           *(lpBuffer+1) = 0;
2132           return 1;
2133         }
2134      else
2135         return 0;
2136   }
2137
2138   /* FIXME: horrible hack to fix function keys. Windows reports scancode
2139             without "extended-key" flag. However Wine generates scancode
2140             *with* "extended-key" flag. Seems to occur *only* for the
2141             function keys. Soooo.. We will leave the table alone and
2142             fudge the lookup here till the other part is found and fixed!!! */
2143
2144   if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
2145        (scanCode == 0x157) || (scanCode == 0x158))
2146     scanCode &= 0xff;   /* remove "extended-key" flag for Fx keys */
2147
2148   /* let's do scancode -> keycode -> keysym -> String */
2149
2150   for (keyi=min_keycode; keyi<=max_keycode; keyi++)
2151       if ((keyc2scan[keyi]) == scanCode)
2152          break;
2153   if (keyi <= max_keycode)
2154   {
2155       wine_tsx11_lock();
2156       keyc = (KeyCode) keyi;
2157       keys = XKeycodeToKeysym(thread_display(), keyc, 0);
2158       name = XKeysymToString(keys);
2159       wine_tsx11_unlock();
2160       TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
2161             scanCode, keyc, (int)keys, name);
2162       if (lpBuffer && nSize && name)
2163       {
2164           MultiByteToWideChar(CP_UNIXCP, 0, name, -1, lpBuffer, nSize);
2165           lpBuffer[nSize - 1] = 0;
2166           return 1;
2167       }
2168   }
2169
2170   /* Finally issue FIXME for unknown keys   */
2171
2172   FIXME("(%08lx,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
2173   if (lpBuffer && nSize)
2174     *lpBuffer = 0;
2175   return 0;
2176 }
2177
2178 /***********************************************************************
2179  *              X11DRV_KEYBOARD_MapDeadKeysym
2180  */
2181 static char KEYBOARD_MapDeadKeysym(KeySym keysym)
2182 {
2183         switch (keysym)
2184             {
2185         /* symbolic ASCII is the same as defined in rfc1345 */
2186 #ifdef XK_dead_tilde
2187             case XK_dead_tilde :
2188 #endif
2189             case 0x1000FE7E : /* Xfree's XK_Dtilde */
2190                 return '~';     /* '? */
2191 #ifdef XK_dead_acute
2192             case XK_dead_acute :
2193 #endif
2194             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
2195                 return 0xb4;    /* '' */
2196 #ifdef XK_dead_circumflex
2197             case XK_dead_circumflex:
2198 #endif
2199             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
2200                 return '^';     /* '> */
2201 #ifdef XK_dead_grave
2202             case XK_dead_grave :
2203 #endif
2204             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
2205                 return '`';     /* '! */
2206 #ifdef XK_dead_diaeresis
2207             case XK_dead_diaeresis :
2208 #endif
2209             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
2210                 return 0xa8;    /* ': */
2211 #ifdef XK_dead_cedilla
2212             case XK_dead_cedilla :
2213                 return 0xb8;    /* ', */
2214 #endif
2215 #ifdef XK_dead_macron
2216             case XK_dead_macron :
2217                 return '-';     /* 'm isn't defined on iso-8859-x */
2218 #endif
2219 #ifdef XK_dead_breve
2220             case XK_dead_breve :
2221                 return 0xa2;    /* '( */
2222 #endif
2223 #ifdef XK_dead_abovedot
2224             case XK_dead_abovedot :
2225                 return 0xff;    /* '. */
2226 #endif
2227 #ifdef XK_dead_abovering
2228             case XK_dead_abovering :
2229                 return '0';     /* '0 isn't defined on iso-8859-x */
2230 #endif
2231 #ifdef XK_dead_doubleacute
2232             case XK_dead_doubleacute :
2233                 return 0xbd;    /* '" */
2234 #endif
2235 #ifdef XK_dead_caron
2236             case XK_dead_caron :
2237                 return 0xb7;    /* '< */
2238 #endif
2239 #ifdef XK_dead_ogonek
2240             case XK_dead_ogonek :
2241                 return 0xb2;    /* '; */
2242 #endif
2243 /* FIXME: I don't know this three.
2244             case XK_dead_iota :
2245                 return 'i';
2246             case XK_dead_voiced_sound :
2247                 return 'v';
2248             case XK_dead_semivoiced_sound :
2249                 return 's';
2250 */
2251             }
2252         TRACE("no character for dead keysym 0x%08lx\n",keysym);
2253         return 0;
2254 }
2255
2256 /***********************************************************************
2257  *              ToUnicodeEx (X11DRV.@)
2258  *
2259  * The ToUnicode function translates the specified virtual-key code and keyboard
2260  * state to the corresponding Windows character or characters.
2261  *
2262  * If the specified key is a dead key, the return value is negative. Otherwise,
2263  * it is one of the following values:
2264  * Value        Meaning
2265  * 0    The specified virtual key has no translation for the current state of the keyboard.
2266  * 1    One Windows character was copied to the buffer.
2267  * 2    Two characters were copied to the buffer. This usually happens when a
2268  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
2269  *      be composed with the specified virtual key to form a single character.
2270  *
2271  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
2272  *
2273  */
2274 INT X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
2275                      LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
2276 {
2277     Display *display = thread_display();
2278     XKeyEvent e;
2279     KeySym keysym = 0;
2280     INT ret;
2281     int keyc;
2282     char lpChar[10];
2283     HWND focus;
2284     XIC xic;
2285     Status status;
2286
2287     if (scanCode & 0x8000)
2288     {
2289         TRACE("Key UP, doing nothing\n" );
2290         return 0;
2291     }
2292
2293     if (hkl != X11DRV_GetKeyboardLayout(0))
2294         FIXME("keyboard layout %p is not supported\n", hkl);
2295
2296     if ((lpKeyState[VK_MENU] & 0x80) && (lpKeyState[VK_CONTROL] & 0x80))
2297     {
2298         TRACE("Ctrl+Alt+[key] won't generate a character\n");
2299         return 0;
2300     }
2301
2302     e.display = display;
2303     e.keycode = 0;
2304     e.state = 0;
2305     e.type = KeyPress;
2306
2307     focus = GetFocus();
2308     if (focus) focus = GetAncestor( focus, GA_ROOT );
2309     if (!focus) focus = GetActiveWindow();
2310     e.window = X11DRV_get_whole_window( focus );
2311     xic = X11DRV_get_ic( focus );
2312
2313     if (lpKeyState[VK_SHIFT] & 0x80)
2314     {
2315         TRACE("ShiftMask = %04x\n", ShiftMask);
2316         e.state |= ShiftMask;
2317     }
2318     if (lpKeyState[VK_CAPITAL] & 0x01)
2319     {
2320         TRACE("LockMask = %04x\n", LockMask);
2321         e.state |= LockMask;
2322     }
2323     if (lpKeyState[VK_CONTROL] & 0x80)
2324     {
2325         TRACE("ControlMask = %04x\n", ControlMask);
2326         e.state |= ControlMask;
2327     }
2328     if (lpKeyState[VK_NUMLOCK] & 0x01)
2329     {
2330         TRACE("NumLockMask = %04x\n", NumLockMask);
2331         e.state |= NumLockMask;
2332     }
2333
2334     /* Restore saved AltGr state */
2335     TRACE("AltGrMask = %04x\n", AltGrMask);
2336     e.state |= AltGrMask;
2337
2338     TRACE_(key)("(%04X, %04X) : faked state = 0x%04x\n",
2339                 virtKey, scanCode, e.state);
2340     wine_tsx11_lock();
2341     /* We exit on the first keycode found, to speed up the thing. */
2342     for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2343       { /* Find a keycode that could have generated this virtual key */
2344           if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
2345           { /* We filter the extended bit, we don't know it */
2346               e.keycode = keyc; /* Store it temporarily */
2347               if ((EVENT_event_to_vkey(xic,&e) & 0xFF) != virtKey) {
2348                   e.keycode = 0; /* Wrong one (ex: because of the NumLock
2349                          state), so set it to 0, we'll find another one */
2350               }
2351           }
2352       }
2353
2354     if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
2355         e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
2356
2357     if (virtKey==VK_DECIMAL)
2358         e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2359
2360     if (!e.keycode && virtKey != VK_NONAME)
2361       {
2362         WARN("Unknown virtual key %X !!! \n",virtKey);
2363         wine_tsx11_unlock();
2364         return virtKey; /* whatever */
2365       }
2366     else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2367
2368     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
2369                 e.type, e.window, e.state, e.keycode);
2370
2371     if (xic)
2372         ret = XmbLookupString(xic, &e, lpChar, sizeof(lpChar), &keysym, &status);
2373     else
2374         ret = XLookupString(&e, lpChar, sizeof(lpChar), &keysym, NULL);
2375     wine_tsx11_unlock();
2376
2377     if (ret == 0)
2378     {
2379         char dead_char;
2380
2381 #ifdef XK_EuroSign
2382         /* An ugly hack for EuroSign: X can't translate it to a character
2383            for some locales. */
2384         if (keysym == XK_EuroSign)
2385         {
2386             bufW[0] = 0x20AC;
2387             ret = 1;
2388             goto found;
2389         }
2390 #endif
2391         /* Special case: X turns shift-tab into ISO_Left_Tab. */
2392         /* Here we change it back. */
2393         if (keysym == XK_ISO_Left_Tab)
2394         {
2395             bufW[0] = 0x09;
2396             ret = 1;
2397             goto found;
2398         }
2399
2400         dead_char = KEYBOARD_MapDeadKeysym(keysym);
2401         if (dead_char)
2402             {
2403             MultiByteToWideChar(CP_UNIXCP, 0, &dead_char, 1, bufW, bufW_size);
2404             ret = -1;
2405             }
2406         else
2407             {
2408             char        *ksname;
2409
2410             wine_tsx11_lock();
2411             ksname = XKeysymToString(keysym);
2412             wine_tsx11_unlock();
2413             if (!ksname)
2414                 ksname = "No Name";
2415             if ((keysym >> 8) != 0xff)
2416                 {
2417                 ERR("Please report: no char for keysym %04lX (%s) :\n",
2418                     keysym, ksname);
2419                 ERR("(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
2420                     virtKey, scanCode, e.keycode, e.state);
2421                 }
2422             }
2423         }
2424     else {  /* ret != 0 */
2425         /* We have a special case to handle : Shift + arrow, shift + home, ...
2426            X returns a char for it, but Windows doesn't. Let's eat it. */
2427         if (!(e.state & NumLockMask)  /* NumLock is off */
2428             && (e.state & ShiftMask) /* Shift is pressed */
2429             && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
2430         {
2431             lpChar[0] = 0;
2432             ret = 0;
2433         }
2434
2435         /* more areas where X returns characters but Windows does not
2436            CTRL + number or CTRL + symbol */
2437         if (e.state & ControlMask)
2438         {
2439             if (((keysym>=33) && (keysym < 'A')) ||
2440                 ((keysym > 'Z') && (keysym < 'a')))
2441             {
2442                 lpChar[0] = 0;
2443                 ret = 0;
2444             }
2445         }
2446
2447         /* We have another special case for delete key (XK_Delete) on an
2448          extended keyboard. X returns a char for it, but Windows doesn't */
2449         if (keysym == XK_Delete)
2450         {
2451             lpChar[0] = 0;
2452             ret = 0;
2453         }
2454         else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
2455                 && (keysym == XK_KP_Decimal))
2456         {
2457             lpChar[0] = 0;
2458             ret = 0;
2459         }
2460
2461         /* perform translation to unicode */
2462         if(ret)
2463         {
2464             TRACE_(key)("Translating char 0x%02x to unicode\n", *(BYTE *)lpChar);
2465             ret = MultiByteToWideChar(CP_UNIXCP, 0, lpChar, ret, bufW, bufW_size);
2466         }
2467     }
2468
2469 found:
2470     TRACE_(key)("ToUnicode about to return %d with char %x %s\n",
2471                 ret, (ret && bufW) ? bufW[0] : 0, bufW ? "" : "(no buffer)");
2472     return ret;
2473 }
2474
2475 /***********************************************************************
2476  *              Beep (X11DRV.@)
2477  */
2478 void X11DRV_Beep(void)
2479 {
2480     wine_tsx11_lock();
2481     XBell(thread_display(), 0);
2482     wine_tsx11_unlock();
2483 }