winex11: Made local constant static.
[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( event->xmapping.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_init_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_init_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     {
2058         case MAPVK_VK_TO_VSC: /* vkey-code to scan-code */
2059         case MAPVK_VK_TO_VSC_EX:
2060         {
2061             int keyc;
2062
2063             switch (wCode)
2064             {
2065                 case VK_SHIFT: wCode = VK_LSHIFT; break;
2066                 case VK_CONTROL: wCode = VK_LCONTROL; break;
2067                 case VK_MENU: wCode = VK_LMENU; break;
2068             }
2069
2070             /* let's do vkey -> keycode -> scan */
2071             for (keyc = min_keycode; keyc <= max_keycode; keyc++)
2072                 if ((keyc2vkey[keyc] & 0xFF) == wCode) break;
2073
2074             if (keyc > max_keycode)
2075             {
2076                 TRACE("returning no scan-code.\n");
2077                 return 0;
2078             }
2079             returnMVK (keyc2scan[keyc] & 0xFF);
2080         }
2081         case MAPVK_VSC_TO_VK: /* scan-code to vkey-code */
2082         case MAPVK_VSC_TO_VK_EX:
2083         {
2084             int keyc;
2085             UINT vkey = 0;
2086
2087             /* let's do scan -> keycode -> vkey */
2088             for (keyc = min_keycode; keyc <= max_keycode; keyc++)
2089                 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
2090                 {
2091                     vkey = keyc2vkey[keyc] & 0xFF;
2092                     /* Only stop if it's not a numpad vkey; otherwise keep
2093                        looking for a potential better vkey. */
2094                     if (vkey && (vkey < VK_NUMPAD0 || VK_DIVIDE < vkey))
2095                         break;
2096                 }
2097
2098             if (vkey == 0)
2099             {
2100                 TRACE("returning no vkey-code.\n");
2101                 return 0;
2102             }
2103
2104             if (wMapType == MAPVK_VSC_TO_VK)
2105                 switch (vkey)
2106                 {
2107                     case VK_LSHIFT:
2108                     case VK_RSHIFT:
2109                         vkey = VK_SHIFT; break;
2110                     case VK_LCONTROL:
2111                     case VK_RCONTROL:
2112                         vkey = VK_CONTROL; break;
2113                     case VK_LMENU:
2114                     case VK_RMENU:
2115                         vkey = VK_MENU; break;
2116                 }
2117
2118             returnMVK (vkey);
2119         }
2120                 case MAPVK_VK_TO_CHAR: /* vkey-code to unshifted ANSI code */
2121                 {
2122                         /* we still don't know what "unshifted" means. in windows VK_W (0x57)
2123                          * returns 0x57, which is upercase 'W'. So we have to return the uppercase
2124                          * key.. Looks like something is wrong with the MS docs?
2125                          * This is only true for letters, for example VK_0 returns '0' not ')'.
2126                          * - hence we use the lock mask to ensure this happens.
2127                          */
2128                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
2129                         XKeyEvent e;
2130                         KeySym keysym;
2131                         int keyc, len;
2132                         char s[10];
2133
2134                         e.display = display;
2135                         e.state = 0;
2136                         e.keycode = 0;
2137
2138                         wine_tsx11_lock();
2139
2140                         /* We exit on the first keycode found, to speed up the thing. */
2141                         for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2142                         { /* Find a keycode that could have generated this virtual key */
2143                             if  ((keyc2vkey[keyc] & 0xFF) == wCode)
2144                             { /* We filter the extended bit, we don't know it */
2145                                 e.keycode = keyc; /* Store it temporarily */
2146                                 if ((EVENT_event_to_vkey(0,&e) & 0xFF) != wCode) {
2147                                     e.keycode = 0; /* Wrong one (ex: because of the NumLock
2148                                          state), so set it to 0, we'll find another one */
2149                                 }
2150                             }
2151                         }
2152
2153                         if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
2154                           e.keycode = XKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
2155
2156                         if (wCode==VK_DECIMAL)
2157                           e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2158
2159                         if (!e.keycode)
2160                         {
2161                           WARN("Unknown virtual key %X !!!\n", wCode);
2162                           wine_tsx11_unlock();
2163                           return 0; /* whatever */
2164                         }
2165                         TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2166
2167                         len = XLookupString(&e, s, sizeof(s), &keysym, NULL);
2168                         wine_tsx11_unlock();
2169
2170                         if (len)
2171                         {
2172                             WCHAR wch;
2173                             if (MultiByteToWideChar(CP_UNIXCP, 0, s, len, &wch, 1))
2174                                 returnMVK(toupperW(wch));
2175                         }
2176                         TRACE("returning no ANSI.\n");
2177                         return 0;
2178                 }
2179                 default: /* reserved */
2180                         FIXME("Unknown wMapType %d !\n", wMapType);
2181                         return 0;
2182         }
2183         return 0;
2184 }
2185
2186 /***********************************************************************
2187  *              GetKeyNameText (X11DRV.@)
2188  */
2189 INT X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
2190 {
2191   Display *display = thread_init_display();
2192   int vkey, ansi, scanCode;
2193   KeyCode keyc;
2194   int keyi;
2195   KeySym keys;
2196   char *name;
2197
2198   scanCode = lParam >> 16;
2199   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
2200
2201   vkey = X11DRV_MapVirtualKeyEx(scanCode, MAPVK_VSC_TO_VK_EX, X11DRV_GetKeyboardLayout(0));
2202
2203   /*  handle "don't care" bit (0x02000000) */
2204   if (!(lParam & 0x02000000)) {
2205     switch (vkey) {
2206          case VK_RSHIFT:
2207                           /* R-Shift is "special" - it is an extended key with separate scan code */
2208                           scanCode |= 0x100;
2209          case VK_LSHIFT:
2210                           vkey = VK_SHIFT;
2211                           break;
2212        case VK_LCONTROL:
2213        case VK_RCONTROL:
2214                           vkey = VK_CONTROL;
2215                           break;
2216           case VK_LMENU:
2217           case VK_RMENU:
2218                           vkey = VK_MENU;
2219                           break;
2220     }
2221   }
2222
2223   ansi = X11DRV_MapVirtualKeyEx(vkey, MAPVK_VK_TO_CHAR, X11DRV_GetKeyboardLayout(0));
2224   TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
2225
2226   /* first get the name of the "regular" keys which is the Upper case
2227      value of the keycap imprint.                                     */
2228   if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
2229        (scanCode != 0x137) &&   /* PrtScn   */
2230        (scanCode != 0x135) &&   /* numpad / */
2231        (scanCode != 0x37 ) &&   /* numpad * */
2232        (scanCode != 0x4a ) &&   /* numpad - */
2233        (scanCode != 0x4e ) )    /* numpad + */
2234       {
2235         if ((nSize >= 2) && lpBuffer)
2236         {
2237           *lpBuffer = toupperW((WCHAR)ansi);
2238           *(lpBuffer+1) = 0;
2239           return 1;
2240         }
2241      else
2242         return 0;
2243   }
2244
2245   /* FIXME: horrible hack to fix function keys. Windows reports scancode
2246             without "extended-key" flag. However Wine generates scancode
2247             *with* "extended-key" flag. Seems to occur *only* for the
2248             function keys. Soooo.. We will leave the table alone and
2249             fudge the lookup here till the other part is found and fixed!!! */
2250
2251   if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
2252        (scanCode == 0x157) || (scanCode == 0x158))
2253     scanCode &= 0xff;   /* remove "extended-key" flag for Fx keys */
2254
2255   /* let's do scancode -> keycode -> keysym -> String */
2256
2257   for (keyi=min_keycode; keyi<=max_keycode; keyi++)
2258       if ((keyc2scan[keyi]) == scanCode)
2259          break;
2260   if (keyi <= max_keycode)
2261   {
2262       wine_tsx11_lock();
2263       keyc = (KeyCode) keyi;
2264       keys = XKeycodeToKeysym(display, keyc, 0);
2265       name = XKeysymToString(keys);
2266       wine_tsx11_unlock();
2267       TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
2268             scanCode, keyc, (int)keys, name);
2269       if (lpBuffer && nSize && name)
2270       {
2271           MultiByteToWideChar(CP_UNIXCP, 0, name, -1, lpBuffer, nSize);
2272           lpBuffer[nSize - 1] = 0;
2273           return 1;
2274       }
2275   }
2276
2277   /* Finally issue WARN for unknown keys   */
2278
2279   WARN("(%08x,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
2280   if (lpBuffer && nSize)
2281     *lpBuffer = 0;
2282   return 0;
2283 }
2284
2285 /***********************************************************************
2286  *              X11DRV_KEYBOARD_MapDeadKeysym
2287  */
2288 static char KEYBOARD_MapDeadKeysym(KeySym keysym)
2289 {
2290         switch (keysym)
2291             {
2292         /* symbolic ASCII is the same as defined in rfc1345 */
2293 #ifdef XK_dead_tilde
2294             case XK_dead_tilde :
2295 #endif
2296             case 0x1000FE7E : /* Xfree's XK_Dtilde */
2297                 return '~';     /* '? */
2298 #ifdef XK_dead_acute
2299             case XK_dead_acute :
2300 #endif
2301             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
2302                 return 0xb4;    /* '' */
2303 #ifdef XK_dead_circumflex
2304             case XK_dead_circumflex:
2305 #endif
2306             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
2307                 return '^';     /* '> */
2308 #ifdef XK_dead_grave
2309             case XK_dead_grave :
2310 #endif
2311             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
2312                 return '`';     /* '! */
2313 #ifdef XK_dead_diaeresis
2314             case XK_dead_diaeresis :
2315 #endif
2316             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
2317                 return 0xa8;    /* ': */
2318 #ifdef XK_dead_cedilla
2319             case XK_dead_cedilla :
2320                 return 0xb8;    /* ', */
2321 #endif
2322 #ifdef XK_dead_macron
2323             case XK_dead_macron :
2324                 return '-';     /* 'm isn't defined on iso-8859-x */
2325 #endif
2326 #ifdef XK_dead_breve
2327             case XK_dead_breve :
2328                 return 0xa2;    /* '( */
2329 #endif
2330 #ifdef XK_dead_abovedot
2331             case XK_dead_abovedot :
2332                 return 0xff;    /* '. */
2333 #endif
2334 #ifdef XK_dead_abovering
2335             case XK_dead_abovering :
2336                 return '0';     /* '0 isn't defined on iso-8859-x */
2337 #endif
2338 #ifdef XK_dead_doubleacute
2339             case XK_dead_doubleacute :
2340                 return 0xbd;    /* '" */
2341 #endif
2342 #ifdef XK_dead_caron
2343             case XK_dead_caron :
2344                 return 0xb7;    /* '< */
2345 #endif
2346 #ifdef XK_dead_ogonek
2347             case XK_dead_ogonek :
2348                 return 0xb2;    /* '; */
2349 #endif
2350 /* FIXME: I don't know this three.
2351             case XK_dead_iota :
2352                 return 'i';
2353             case XK_dead_voiced_sound :
2354                 return 'v';
2355             case XK_dead_semivoiced_sound :
2356                 return 's';
2357 */
2358             }
2359         TRACE("no character for dead keysym 0x%08lx\n",keysym);
2360         return 0;
2361 }
2362
2363 /***********************************************************************
2364  *              ToUnicodeEx (X11DRV.@)
2365  *
2366  * The ToUnicode function translates the specified virtual-key code and keyboard
2367  * state to the corresponding Windows character or characters.
2368  *
2369  * If the specified key is a dead key, the return value is negative. Otherwise,
2370  * it is one of the following values:
2371  * Value        Meaning
2372  * 0    The specified virtual key has no translation for the current state of the keyboard.
2373  * 1    One Windows character was copied to the buffer.
2374  * 2    Two characters were copied to the buffer. This usually happens when a
2375  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
2376  *      be composed with the specified virtual key to form a single character.
2377  *
2378  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
2379  *
2380  */
2381 INT X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
2382                      LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
2383 {
2384     Display *display = thread_init_display();
2385     XKeyEvent e;
2386     KeySym keysym = 0;
2387     INT ret;
2388     int keyc;
2389     char lpChar[10];
2390     HWND focus;
2391     XIC xic;
2392     Status status = 0;
2393
2394     if (scanCode & 0x8000)
2395     {
2396         TRACE("Key UP, doing nothing\n" );
2397         return 0;
2398     }
2399
2400     if (hkl != X11DRV_GetKeyboardLayout(0))
2401         FIXME("keyboard layout %p is not supported\n", hkl);
2402
2403     if ((lpKeyState[VK_MENU] & 0x80) && (lpKeyState[VK_CONTROL] & 0x80))
2404     {
2405         TRACE("Ctrl+Alt+[key] won't generate a character\n");
2406         return 0;
2407     }
2408
2409     e.display = display;
2410     e.keycode = 0;
2411     e.state = 0;
2412     e.type = KeyPress;
2413
2414     focus = GetFocus();
2415     if (focus) focus = GetAncestor( focus, GA_ROOT );
2416     if (!focus) focus = GetActiveWindow();
2417     e.window = X11DRV_get_whole_window( focus );
2418     xic = X11DRV_get_ic( focus );
2419
2420     if (lpKeyState[VK_SHIFT] & 0x80)
2421     {
2422         TRACE("ShiftMask = %04x\n", ShiftMask);
2423         e.state |= ShiftMask;
2424     }
2425     if (lpKeyState[VK_CAPITAL] & 0x01)
2426     {
2427         TRACE("LockMask = %04x\n", LockMask);
2428         e.state |= LockMask;
2429     }
2430     if (lpKeyState[VK_CONTROL] & 0x80)
2431     {
2432         TRACE("ControlMask = %04x\n", ControlMask);
2433         e.state |= ControlMask;
2434     }
2435     if (lpKeyState[VK_NUMLOCK] & 0x01)
2436     {
2437         TRACE("NumLockMask = %04x\n", NumLockMask);
2438         e.state |= NumLockMask;
2439     }
2440
2441     /* Restore saved AltGr state */
2442     TRACE("AltGrMask = %04x\n", AltGrMask);
2443     e.state |= AltGrMask;
2444
2445     TRACE_(key)("(%04X, %04X) : faked state = 0x%04x\n",
2446                 virtKey, scanCode, e.state);
2447     wine_tsx11_lock();
2448     /* We exit on the first keycode found, to speed up the thing. */
2449     for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2450       { /* Find a keycode that could have generated this virtual key */
2451           if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
2452           { /* We filter the extended bit, we don't know it */
2453               e.keycode = keyc; /* Store it temporarily */
2454               if ((EVENT_event_to_vkey(xic,&e) & 0xFF) != virtKey) {
2455                   e.keycode = 0; /* Wrong one (ex: because of the NumLock
2456                          state), so set it to 0, we'll find another one */
2457               }
2458           }
2459       }
2460
2461     if (virtKey >= VK_LEFT && virtKey <= VK_DOWN)
2462         e.keycode = XKeysymToKeycode(e.display, virtKey - VK_LEFT + XK_Left);
2463
2464     if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
2465         e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
2466
2467     if (virtKey==VK_DECIMAL)
2468         e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2469
2470     if (virtKey==VK_SEPARATOR)
2471         e.keycode = XKeysymToKeycode(e.display, XK_KP_Separator);
2472
2473     if (!e.keycode && virtKey != VK_NONAME)
2474       {
2475         WARN("Unknown virtual key %X !!!\n", virtKey);
2476         wine_tsx11_unlock();
2477         return 0;
2478       }
2479     else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2480
2481     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
2482                 e.type, e.window, e.state, e.keycode);
2483
2484     /* Clients should pass only KeyPress events to XmbLookupString,
2485      * e.type was set to KeyPress above.
2486      */
2487     if (xic)
2488         ret = XmbLookupString(xic, &e, lpChar, sizeof(lpChar), &keysym, &status);
2489     else
2490         ret = XLookupString(&e, lpChar, sizeof(lpChar), &keysym, NULL);
2491     wine_tsx11_unlock();
2492
2493     TRACE_(key)("nbyte = %d, status 0x%x\n", ret, status);
2494
2495     if (status == XBufferOverflow)
2496         ERR("Buffer Overflow need %d!\n", ret);
2497
2498     if (TRACE_ON(key))
2499     {
2500         const char *ksname;
2501
2502         wine_tsx11_lock();
2503         ksname = XKeysymToString(keysym);
2504         wine_tsx11_unlock();
2505         if (!ksname) ksname = "No Name";
2506         TRACE_(key)("%s : keysym=%lX (%s), # of chars=%d / %s\n",
2507                     (e.type == KeyPress) ? "KeyPress" : "KeyRelease",
2508                     keysym, ksname, ret, debugstr_an(lpChar, ret));
2509     }
2510
2511     if (ret == 0)
2512     {
2513         char dead_char;
2514
2515 #ifdef XK_EuroSign
2516         /* An ugly hack for EuroSign: X can't translate it to a character
2517            for some locales. */
2518         if (keysym == XK_EuroSign)
2519         {
2520             bufW[0] = 0x20AC;
2521             ret = 1;
2522             goto found;
2523         }
2524 #endif
2525         /* Special case: X turns shift-tab into ISO_Left_Tab. */
2526         /* Here we change it back. */
2527         if (keysym == XK_ISO_Left_Tab)
2528         {
2529             bufW[0] = 0x09;
2530             ret = 1;
2531             goto found;
2532         }
2533
2534         dead_char = KEYBOARD_MapDeadKeysym(keysym);
2535         if (dead_char)
2536         {
2537             MultiByteToWideChar(CP_UNIXCP, 0, &dead_char, 1, bufW, bufW_size);
2538             ret = -1;
2539             goto found;
2540         }
2541
2542         if (keysym >= 0x01000100 && keysym <= 0x0100ffff)
2543         {
2544             /* Unicode direct mapping */
2545             bufW[0] = keysym & 0xffff;
2546             ret = 1;
2547             goto found;
2548         }
2549         else if ((keysym >> 8) == 0x1008FF) {
2550             bufW[0] = 0;
2551             ret = 0;
2552             goto found;
2553         }
2554         else
2555             {
2556             const char *ksname;
2557
2558             wine_tsx11_lock();
2559             ksname = XKeysymToString(keysym);
2560             wine_tsx11_unlock();
2561             if (!ksname)
2562                 ksname = "No Name";
2563             if ((keysym >> 8) != 0xff)
2564                 {
2565                 WARN("no char for keysym %04lX (%s) :\n",
2566                     keysym, ksname);
2567                 WARN("virtKey=%X, scanCode=%X, keycode=%X, state=%X\n",
2568                     virtKey, scanCode, e.keycode, e.state);
2569                 }
2570             }
2571         }
2572     else {  /* ret != 0 */
2573         /* We have a special case to handle : Shift + arrow, shift + home, ...
2574            X returns a char for it, but Windows doesn't. Let's eat it. */
2575         if (!(e.state & NumLockMask)  /* NumLock is off */
2576             && (e.state & ShiftMask) /* Shift is pressed */
2577             && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
2578         {
2579             lpChar[0] = 0;
2580             ret = 0;
2581         }
2582
2583         /* more areas where X returns characters but Windows does not
2584            CTRL + number or CTRL + symbol */
2585         if (e.state & ControlMask)
2586         {
2587             if (((keysym>=33) && (keysym < 'A')) ||
2588                 ((keysym > 'Z') && (keysym < 'a')))
2589             {
2590                 lpChar[0] = 0;
2591                 ret = 0;
2592             }
2593         }
2594
2595         /* We have another special case for delete key (XK_Delete) on an
2596          extended keyboard. X returns a char for it, but Windows doesn't */
2597         if (keysym == XK_Delete)
2598         {
2599             lpChar[0] = 0;
2600             ret = 0;
2601         }
2602         else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
2603                 && (keysym == XK_KP_Decimal))
2604         {
2605             lpChar[0] = 0;
2606             ret = 0;
2607         }
2608         else if((lpKeyState[VK_CONTROL] & 0x80) /* Control is pressed */
2609                 && (keysym == XK_Return || keysym == XK_KP_Enter))
2610         {
2611             lpChar[0] = '\n';
2612             ret = 1;
2613         }
2614
2615         /* Hack to detect an XLookupString hard-coded to Latin1 */
2616         if (ret == 1 && keysym >= 0x00a0 && keysym <= 0x00ff && (BYTE)lpChar[0] == keysym)
2617         {
2618             bufW[0] = (BYTE)lpChar[0];
2619             goto found;
2620         }
2621
2622         /* perform translation to unicode */
2623         if(ret)
2624         {
2625             TRACE_(key)("Translating char 0x%02x to unicode\n", *(BYTE *)lpChar);
2626             ret = MultiByteToWideChar(CP_UNIXCP, 0, lpChar, ret, bufW, bufW_size);
2627         }
2628     }
2629
2630 found:
2631     TRACE_(key)("ToUnicode about to return %d with char %x %s\n",
2632                 ret, (ret && bufW) ? bufW[0] : 0, bufW ? "" : "(no buffer)");
2633     return ret;
2634 }
2635
2636 /***********************************************************************
2637  *              Beep (X11DRV.@)
2638  */
2639 void X11DRV_Beep(void)
2640 {
2641     wine_tsx11_lock();
2642     XBell(gdi_display, 0);
2643     wine_tsx11_unlock();
2644 }