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