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