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