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