Added parser template and made AVISplitter use it.
[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 /*** Israelian keyboard layout (setxkbmap us,il) */
710 static const char main_key_IL[MAIN_LEN][4] =
711 {
712  "`~;","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
713  "qQ/","wW'","eE÷","rRø","tTà","yYè","uUå","iIï","oOí","pPô","[{","]}",
714  "aAù","sSã","dDâ","fFë","gGò","hHé","jJç","kKì","lLê",";:ó","\'\",","\\|",
715  "zZæ","xXñ","cCá","vVä","bBð","nNî","mMö",",<ú",".>õ","/?.",
716  "<>"
717 };
718
719 /*** Israelian phonetic keyboard layout (setxkbmap us,il_phonetic) */
720 static const char main_key_IL_phonetic[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 Saharon keyboard layout (setxkbmap -symbols "us(pc105)+il_saharon") */
730 static const char main_key_IL_saharon[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 /*** Greek keyboard layout (contributed by Kriton Kyrimis <kyrimis@cti.gr>)
740   Greek characters for "wW" and "sS" are omitted to not produce a mismatch
741   message since they have different characters in gr and el XFree86 layouts. */
742 static const char main_key_EL[MAIN_LEN][4] =
743 {
744  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
745  "qQ;:","wW","eEåÅ","rRñÑ","tTôÔ","yYõÕ","uUèÈ","iIéÉ","oOïÏ","pPðÐ","[{","]}",
746  "aAáÁ","sS","dDäÄ","fFöÖ","gGãÃ","hHçÇ","jJîÎ","kKêÊ","lLëË",";:´¨","'\"","\\|",
747  "zZæÆ","xX÷×","cCøØ","vVùÙ","bBâÂ","nNíÍ","mMìÌ",",<",".>","/?",
748  "<>"
749 };
750
751 /*** Thai (Kedmanee) keyboard layout by Supphachoke Suntiwichaya <mrchoke@opentle.org> */
752 static const char main_key_th[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 /*** VNC keyboard layout */
761 static const WORD main_key_scan_vnc[MAIN_LEN] =
762 {
763    0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x1A,0x1B,0x27,0x28,0x29,0x33,0x34,0x35,0x2B,
764    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,
765    0x56
766 };
767
768 static const WORD main_key_vkey_vnc[MAIN_LEN] =
769 {
770    '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,
771    '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',
772    VK_OEM_102
773 };
774
775 static const char main_key_vnc[MAIN_LEN][4] =
776 {
777  "1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+","[{","]}",";:","'\"","`~",",<",".>","/?","\\|",
778  "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"
779 };
780
781 /*** Dutch keyboard layout (setxkbmap nl) ***/
782 static const char main_key_NL[MAIN_LEN][4] =
783 {
784  "@§","1!","2\"","3#","4$","5%","6&","7_","8(","9)","0'","/?","°~",
785  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","¨~","*|",
786  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","+±","'`","<>",
787  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-=",
788  "[]"
789 };
790
791
792
793 /*** Layout table. Add your keyboard mappings to this list */
794 static const struct {
795     LCID lcid; /* input locale identifier, look for LOCALE_ILANGUAGE
796                  in the appropriate dlls/kernel/nls/.nls file */
797     const char *comment;
798     const char (*key)[MAIN_LEN][4];
799     const WORD (*scan)[MAIN_LEN]; /* scan codes mapping */
800     const WORD (*vkey)[MAIN_LEN]; /* virtual key codes mapping */
801 } main_key_tab[]={
802  {0x0409, "United States keyboard layout", &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty},
803  {0x0409, "United States keyboard layout (phantom key version)", &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
804  {0x0409, "United States keyboard layout (dvorak)", &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak},
805  {0x0409, "United States International keyboard layout", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
806  {0x0809, "British keyboard layout", &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
807  {0x0407, "German keyboard layout", &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwertz},
808  {0x0407, "German keyboard layout without dead keys", &main_key_DE_nodead, &main_key_scan_qwerty, &main_key_vkey_qwertz},
809  {0x0407, "German keyboard layout for logitech desktop pro", &main_key_DE_logitech,  &main_key_scan_qwerty, &main_key_vkey_qwertz},
810  {0x0407, "German keyboard layout without dead keys 105", &main_key_DE_nodead_105, &main_key_scan_qwerty, &main_key_vkey_qwertz_105},
811  {0x0807, "Swiss German keyboard layout", &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwertz},
812  {0x100c, "Swiss French keyboard layout", &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwertz},
813  {0x041d, "Swedish keyboard layout", &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty_v2},
814  {0x0425, "Estonian keyboard layout", &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty},
815  {0x0414, "Norwegian keyboard layout", &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty},
816  {0x0406, "Danish keyboard layout", &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
817  {0x040c, "French keyboard layout", &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty},
818  {0x0c0c, "Canadian French keyboard layout", &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
819  {0x0c0c, "Canadian CAN/CSA-Z243.200-92 keyboard layout", &main_key_CA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
820  {0x080c, "Belgian keyboard layout", &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty},
821  {0x0816, "Portuguese keyboard layout", &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
822  {0x0416, "Brazilian ABNT-2 keyboard layout", &main_key_PT_br, &main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
823  {0x0416, "Brazilian ABNT-2 keyboard layout ALT GR", &main_key_PT_br_alt_gr,&main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
824  {0x040b, "Finnish keyboard layout", &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
825  {0x0402, "Bulgarian bds keyboard layout", &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty},
826  {0x0402, "Bulgarian phonetic keyboard layout", &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
827  {0x0423, "Belarusian keyboard layout", &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty},
828  {0x0419, "Russian keyboard layout", &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
829  {0x0419, "Russian keyboard layout (phantom key version)", &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
830  {0x0419, "Russian keyboard layout KOI8-R", &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty},
831  {0x0419, "Russian keyboard layout cp1251", &main_key_RU_cp1251, &main_key_scan_qwerty, &main_key_vkey_qwerty},
832  {0x0419, "Russian phonetic keyboard layout", &main_key_RU_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
833  {0x0422, "Ukrainian keyboard layout KOI8-U", &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
834  {0x0422, "Ukrainian keyboard layout (standard)", &main_key_UA_std, &main_key_scan_qwerty, &main_key_vkey_qwerty},
835  {0x0419, "Russian keyboard layout (standard)", &main_key_RU_std, &main_key_scan_qwerty, &main_key_vkey_qwerty},
836  {0x040a, "Spanish keyboard layout", &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty},
837  {0x0410, "Italian keyboard layout", &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
838  {0x040f, "Icelandic keyboard layout", &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
839  {0x040e, "Hungarian keyboard layout", &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwertz},
840  {0x0415, "Polish (programmer's) keyboard layout", &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
841  {0x0424, "Slovenian keyboard layout", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwertz},
842  {0x041a, "Croatian keyboard layout", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwertz},
843  {0x041a, "Croatian keyboard layout (specific)", &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
844  {0x0411, "Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty, &main_key_vkey_qwerty},
845  {0x0411, "Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
846  {0x041b, "Slovak keyboard layout", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
847  {0x041b, "Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
848  {0x0405, "Czech keyboard layout", &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
849  {0x0405, "Czech keyboard layout cz", &main_key_CZ, &main_key_scan_qwerty, &main_key_vkey_qwertz},
850  {0x0405, "Czech keyboard layout cz_qwerty", &main_key_CZ_qwerty, &main_key_scan_qwerty, &main_key_vkey_qwerty},
851  {0x040a, "Latin American keyboard layout", &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
852  {0x0427, "Lithuanian (Baltic) keyboard layout", &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty},
853  {0x041f, "Turkish keyboard layout", &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
854  {0x040d, "Israelian keyboard layout", &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
855  {0x040d, "Israelian phonetic keyboard layout", &main_key_IL_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
856  {0x040d, "Israelian Saharon keyboard layout", &main_key_IL_saharon, &main_key_scan_qwerty, &main_key_vkey_qwerty},
857  {0x0409, "VNC keyboard layout", &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc},
858  {0x0408, "Greek keyboard layout", &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
859  {0x041e, "Thai (Kedmanee)  keyboard layout", &main_key_th, &main_key_scan_qwerty, &main_key_vkey_qwerty},
860  {0x0413, "Dutch keyboard layout", &main_key_NL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
861
862  {0, NULL, NULL, NULL, NULL} /* sentinel */
863 };
864 static unsigned kbd_layout=0; /* index into above table of layouts */
865
866 /* maybe more of these scancodes should be extended? */
867                 /* extended must be set for ALT_R, CTRL_R,
868                    INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
869                    keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
870                 /* FIXME should we set extended bit for NumLock ? My
871                  * Windows does ... DF */
872                 /* Yes, to distinguish based on scan codes, also
873                    for PrtScn key ... GA */
874
875 static const WORD nonchar_key_vkey[256] =
876 {
877     /* unused */
878     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF00 */
879     /* special keys */
880     VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
881     0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
882     0, 0, 0, VK_ESCAPE, 0, 0, 0, 0,                             /* FF18 */
883     /* unused */
884     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF20 */
885     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF28 */
886     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF30 */
887     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF38 */
888     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF40 */
889     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF48 */
890     /* cursor keys */
891     VK_HOME, VK_LEFT, VK_UP, VK_RIGHT,                          /* FF50 */
892     VK_DOWN, VK_PRIOR, VK_NEXT, VK_END,
893     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF58 */
894     /* misc keys */
895     VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
896     VK_CANCEL, VK_HELP, VK_CANCEL, VK_CANCEL, 0, 0, 0, 0,       /* FF68 */
897     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF70 */
898     /* keypad keys */
899     0, 0, 0, 0, 0, 0, 0, VK_NUMLOCK,                            /* FF78 */
900     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
901     0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
902     0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP,                     /* FF90 */
903     VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT,                       /* FF98 */
904     VK_END, VK_CLEAR, VK_INSERT, VK_DELETE,
905     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
906     0, 0, VK_MULTIPLY, VK_ADD,                                  /* FFA8 */
907     VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE,
908     VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,             /* FFB0 */
909     VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
910     VK_NUMPAD8, VK_NUMPAD9, 0, 0, 0, 0,                         /* FFB8 */
911     /* function keys */
912     VK_F1, VK_F2,
913     VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
914     VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, 0, 0,       /* FFC8 */
915     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFD0 */
916     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFD8 */
917     /* modifier keys */
918     0, VK_SHIFT, VK_SHIFT, VK_CONTROL,                          /* FFE0 */
919     VK_CONTROL, VK_CAPITAL, 0, VK_MENU,
920     VK_MENU, VK_MENU, VK_MENU, 0, 0, 0, 0, 0,                   /* FFE8 */
921     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFF0 */
922     0, 0, 0, 0, 0, 0, 0, VK_DELETE                              /* FFF8 */
923 };
924
925 static const WORD nonchar_key_scan[256] =
926 {
927     /* unused */
928     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF00 */
929     /* special keys */
930     0x0E, 0x0F, 0x00, /*?*/ 0, 0x00, 0x1C, 0x00, 0x00,           /* FF08 */
931     0x00, 0x00, 0x00, 0x45, 0x46, 0x00, 0x00, 0x00,              /* FF10 */
932     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,              /* FF18 */
933     /* unused */
934     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF20 */
935     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF28 */
936     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF30 */
937     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF38 */
938     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF40 */
939     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF48 */
940     /* cursor keys */
941     0x147, 0x14B, 0x148, 0x14D, 0x150, 0x149, 0x151, 0x14F,      /* FF50 */
942     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF58 */
943     /* misc keys */
944     /*?*/ 0, 0x137, /*?*/ 0, 0x152, 0x00, 0x00, 0x00, 0x00,      /* FF60 */
945     /*?*/ 0, /*?*/ 0, 0x38, 0x146, 0x00, 0x00, 0x00, 0x00,       /* FF68 */
946     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF70 */
947     /* keypad keys */
948     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x138, 0x145,            /* FF78 */
949     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF80 */
950     0x00, 0x00, 0x00, 0x00, 0x00, 0x11C, 0x00, 0x00,             /* FF88 */
951     0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4B, 0x48,              /* FF90 */
952     0x4D, 0x50, 0x49, 0x51, 0x4F, 0x4C, 0x52, 0x53,              /* FF98 */
953     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFA0 */
954     0x00, 0x00, 0x37, 0x4E, /*?*/ 0, 0x4A, 0x53, 0x135,          /* FFA8 */
955     0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47,              /* FFB0 */
956     0x48, 0x49, 0x00, 0x00, 0x00, 0x00,                          /* FFB8 */
957     /* function keys */
958     0x3B, 0x3C,
959     0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44,              /* FFC0 */
960     0x57, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFC8 */
961     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFD0 */
962     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFD8 */
963     /* modifier keys */
964     0x00, 0x2A, 0x36, 0x1D, 0x11D, 0x3A, 0x00, 0x38,             /* FFE0 */
965     0x138, 0x38, 0x138, 0x00, 0x00, 0x00, 0x00, 0x00,            /* FFE8 */
966     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFF0 */
967     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x153              /* FFF8 */
968 };
969
970
971 /* Returns the Windows virtual key code associated with the X event <e> */
972 /* x11 lock must be held */
973 static WORD EVENT_event_to_vkey( XIC xic, XKeyEvent *e)
974 {
975     KeySym keysym = 0;
976
977     if (xic)
978         XmbLookupString(xic, e, NULL, 0, &keysym, NULL);
979     else
980         XLookupString(e, NULL, 0, &keysym, NULL);
981
982     if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (keysym != 0xFFAF)
983         && (e->state & NumLockMask))
984         /* Only the Keypad keys 0-9 and . send different keysyms
985          * depending on the NumLock state */
986         return nonchar_key_vkey[keysym & 0xFF];
987
988     TRACE_(key)("e->keycode = %x\n", e->keycode);
989
990     return keyc2vkey[e->keycode];
991 }
992
993 static BOOL NumState=FALSE, CapsState=FALSE;
994
995
996 /***********************************************************************
997  *           send_keyboard_input
998  */
999 static void send_keyboard_input( WORD wVk, WORD wScan, DWORD dwFlags, DWORD time )
1000 {
1001     INPUT input;
1002
1003     input.type             = WINE_INTERNAL_INPUT_KEYBOARD;
1004     input.u.ki.wVk         = wVk;
1005     input.u.ki.wScan       = wScan;
1006     input.u.ki.dwFlags     = dwFlags;
1007     input.u.ki.time        = time;
1008     input.u.ki.dwExtraInfo = 0;
1009     SendInput( 1, &input, sizeof(input) );
1010 }
1011
1012
1013 /**********************************************************************
1014  *              KEYBOARD_GenerateMsg
1015  *
1016  * Generate Down+Up messages when NumLock or CapsLock is pressed.
1017  *
1018  * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
1019  *
1020  */
1021 static void KEYBOARD_GenerateMsg( WORD vkey, WORD scan, int Evtype, DWORD event_time )
1022 {
1023   BOOL * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
1024   DWORD up, down;
1025
1026   if (*State) {
1027     /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
1028        don't treat it. It's from the same key press. Then the state goes to ON.
1029        And from there, a 'release' event will switch off the toggle key. */
1030     *State=FALSE;
1031     TRACE("INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,pKeyStateTable[vkey]);
1032   } else
1033     {
1034         down = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0);
1035         up = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0) | KEYEVENTF_KEYUP;
1036         if ( pKeyStateTable[vkey] & 0x1 ) /* it was ON */
1037           {
1038             if (Evtype!=KeyPress)
1039               {
1040                 TRACE("ON + KeyRelease => generating DOWN and UP messages.\n");
1041                 send_keyboard_input( vkey, scan, down, event_time );
1042                 send_keyboard_input( vkey, scan, up, event_time );
1043                 *State=FALSE;
1044                 pKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */
1045               }
1046           }
1047         else /* it was OFF */
1048           if (Evtype==KeyPress)
1049             {
1050               TRACE("OFF + Keypress => generating DOWN and UP messages.\n");
1051               send_keyboard_input( vkey, scan, down, event_time );
1052               send_keyboard_input( vkey, scan, up, event_time );
1053               *State=TRUE; /* Goes to intermediary state before going to ON */
1054               pKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
1055             }
1056     }
1057 }
1058
1059 /***********************************************************************
1060  *           KEYBOARD_UpdateOneState
1061  *
1062  * Updates internal state for <vkey>, depending on key <state> under X
1063  *
1064  */
1065 inline static void KEYBOARD_UpdateOneState ( int vkey, int state, DWORD time )
1066 {
1067     /* Do something if internal table state != X state for keycode */
1068     if (((pKeyStateTable[vkey] & 0x80)!=0) != state)
1069     {
1070         TRACE("Adjusting state for vkey %#.2x. State before %#.2x\n",
1071               vkey, pKeyStateTable[vkey]);
1072
1073         /* Fake key being pressed inside wine */
1074         send_keyboard_input( vkey, 0, state? 0 : KEYEVENTF_KEYUP, time );
1075
1076         TRACE("State after %#.2x\n",pKeyStateTable[vkey]);
1077     }
1078 }
1079
1080 /***********************************************************************
1081  *           X11DRV_KeymapNotify
1082  *
1083  * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
1084  *
1085  * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
1086  * from wine to another application and back.
1087  * Toggle keys are handled in HandleEvent.
1088  */
1089 void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event )
1090 {
1091     int i, j, alt, control, shift;
1092     DWORD time = GetCurrentTime();
1093
1094     alt = control = shift = 0;
1095     for (i = 0; i < 32; i++)
1096     {
1097         if (!event->key_vector[i]) continue;
1098         for (j = 0; j < 8; j++)
1099         {
1100             if (!(event->key_vector[i] & (1<<j))) continue;
1101             switch(keyc2vkey[(i * 8) + j] & 0xff)
1102             {
1103             case VK_MENU:    alt = 1; break;
1104             case VK_CONTROL: control = 1; break;
1105             case VK_SHIFT:   shift = 1; break;
1106             }
1107         }
1108     }
1109     KEYBOARD_UpdateOneState( VK_MENU, alt, time );
1110     KEYBOARD_UpdateOneState( VK_CONTROL, control, time );
1111     KEYBOARD_UpdateOneState( VK_SHIFT, shift, time );
1112 }
1113
1114 /***********************************************************************
1115  *           X11DRV_KeyEvent
1116  *
1117  * Handle a X key event
1118  */
1119 void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event )
1120 {
1121     char Str[24];
1122     KeySym keysym = 0;
1123     WORD vkey = 0, bScan;
1124     DWORD dwFlags;
1125     int ascii_chars;
1126     XIC xic = X11DRV_get_ic( hwnd );
1127     DWORD event_time = EVENT_x11_time_to_win32_time(event->time);
1128     Status status = 0;
1129
1130     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
1131                 event->type, event->window, event->state, event->keycode);
1132
1133     wine_tsx11_lock();
1134     if (xic)
1135         ascii_chars = XmbLookupString(xic, event, Str, sizeof(Str), &keysym, &status);
1136     else
1137         ascii_chars = XLookupString(event, Str, sizeof(Str), &keysym, NULL);
1138     wine_tsx11_unlock();
1139
1140     /* Ignore some unwanted events */
1141     if ((keysym >= XK_ISO_Lock && keysym <= XK_ISO_Last_Group_Lock) ||
1142          keysym == XK_Mode_switch)
1143     {
1144         wine_tsx11_lock();
1145         TRACE("Ignoring %s keyboard event\n", XKeysymToString(keysym));
1146         wine_tsx11_unlock();
1147         return;
1148     }
1149
1150     TRACE_(key)("state = %X nbyte = %d, status 0x%x\n", event->state, ascii_chars, status);
1151
1152     if (status == XBufferOverflow)
1153         ERR("Buffer Overflow need %i!\n",ascii_chars);
1154
1155     if (status == XLookupChars)
1156     {
1157         X11DRV_XIMLookupChars( Str, ascii_chars );
1158         return;
1159     }
1160
1161     /* If XKB extensions are used, the state mask for AltGr will use the group
1162        index instead of the modifier mask. The group index is set in bits
1163        13-14 of the state field in the XKeyEvent structure. So if AltGr is
1164        pressed, look if the group index is different than 0. From XKB
1165        extension documentation, the group index for AltGr should be 2
1166        (event->state = 0x2000). It's probably better to not assume a
1167        predefined group index and find it dynamically
1168
1169        Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
1170     /* Save also all possible modifier states. */
1171     AltGrMask = event->state & (0x6000 | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
1172
1173     Str[ascii_chars] = '\0';
1174     if (TRACE_ON(key)){
1175         char    *ksname;
1176
1177         wine_tsx11_lock();
1178         ksname = XKeysymToString(keysym);
1179         wine_tsx11_unlock();
1180         if (!ksname)
1181           ksname = "No Name";
1182         TRACE_(key)("%s : keysym=%lX (%s), # of chars=%d / 0x%02x / '%s'\n",
1183                     (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
1184                     keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
1185     }
1186
1187     wine_tsx11_lock();
1188     vkey = EVENT_event_to_vkey(xic,event);
1189     /* X returns keycode 0 for composed characters */
1190     if (!vkey && ascii_chars) vkey = VK_NONAME;
1191     wine_tsx11_unlock();
1192
1193     TRACE_(key)("keycode 0x%x converted to vkey 0x%x\n",
1194                 event->keycode, vkey);
1195
1196    if (vkey)
1197    {
1198     switch (vkey & 0xff)
1199     {
1200     case VK_NUMLOCK:
1201       KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, event->type, event_time );
1202       break;
1203     case VK_CAPITAL:
1204       TRACE("Caps Lock event. (type %d). State before : %#.2x\n",event->type,pKeyStateTable[vkey]);
1205       KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, event->type, event_time );
1206       TRACE("State after : %#.2x\n",pKeyStateTable[vkey]);
1207       break;
1208     default:
1209         /* Adjust the NUMLOCK state if it has been changed outside wine */
1210         if (!(pKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
1211           {
1212             TRACE("Adjusting NumLock state.\n");
1213             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyPress, event_time );
1214             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyRelease, event_time );
1215           }
1216         /* Adjust the CAPSLOCK state if it has been changed outside wine */
1217         if (!(pKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
1218           {
1219               TRACE("Adjusting Caps Lock state.\n");
1220             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyPress, event_time );
1221             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyRelease, event_time );
1222           }
1223         /* Not Num nor Caps : end of intermediary states for both. */
1224         NumState = FALSE;
1225         CapsState = FALSE;
1226
1227         bScan = keyc2scan[event->keycode] & 0xFF;
1228         TRACE_(key)("bScan = 0x%02x.\n", bScan);
1229
1230         dwFlags = 0;
1231         if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
1232         if ( vkey & 0x100 )              dwFlags |= KEYEVENTF_EXTENDEDKEY;
1233
1234         send_keyboard_input( vkey & 0xff, bScan, dwFlags, event_time );
1235     }
1236    }
1237 }
1238
1239 /**********************************************************************
1240  *              X11DRV_KEYBOARD_DetectLayout
1241  *
1242  * Called from X11DRV_InitKeyboard
1243  *  This routine walks through the defined keyboard layouts and selects
1244  *  whichever matches most closely.
1245  * X11 lock must be held.
1246  */
1247 static void
1248 X11DRV_KEYBOARD_DetectLayout (void)
1249 {
1250   Display *display = thread_display();
1251   unsigned current, match, mismatch, seq, i, syms;
1252   int score, keyc, key, pkey, ok;
1253   KeySym keysym;
1254   const char (*lkey)[MAIN_LEN][4];
1255   unsigned max_seq = 0;
1256   int max_score = 0, ismatch = 0;
1257   char ckey[4] =
1258   {0, 0, 0, 0};
1259
1260   syms = keysyms_per_keycode;
1261   if (syms > 4) {
1262     WARN("%d keysyms per keycode not supported, set to 4\n", syms);
1263     syms = 4;
1264   }
1265   for (current = 0; main_key_tab[current].comment; current++) {
1266     TRACE("Attempting to match against \"%s\"\n", main_key_tab[current].comment);
1267     match = 0;
1268     mismatch = 0;
1269     score = 0;
1270     seq = 0;
1271     lkey = main_key_tab[current].key;
1272     pkey = -1;
1273     for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1274       /* get data for keycode from X server */
1275       for (i = 0; i < syms; i++) {
1276         keysym = XKeycodeToKeysym (display, keyc, i);
1277         /* Allow both one-byte and two-byte national keysyms */
1278         if ((keysym < 0x8000) && (keysym != ' '))
1279         {
1280 #ifdef HAVE_XKB
1281             if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
1282 #endif
1283             {
1284                 TRACE("XKB could not translate keysym %ld\n", keysym);
1285                 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1286                  * with appropriate ShiftMask and Mode_switch, use XLookupString
1287                  * to get character in the local encoding.
1288                  */
1289                 ckey[i] = keysym & 0xFF;
1290             }
1291         }
1292         else {
1293           ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1294         }
1295       }
1296       if (ckey[0]) {
1297         /* search for a match in layout table */
1298         /* right now, we just find an absolute match for defined positions */
1299         /* (undefined positions are ignored, so if it's defined as "3#" in */
1300         /* the table, it's okay that the X server has "3#£", for example) */
1301         /* however, the score will be higher for longer matches */
1302         for (key = 0; key < MAIN_LEN; key++) {
1303           for (ok = 0, i = 0; (ok >= 0) && (i < syms); i++) {
1304             if ((*lkey)[key][i] && ((*lkey)[key][i] == ckey[i]))
1305               ok++;
1306             if ((*lkey)[key][i] && ((*lkey)[key][i] != ckey[i]))
1307               ok = -1;
1308           }
1309           if (ok > 0) {
1310             score += ok;
1311             break;
1312           }
1313         }
1314         /* count the matches and mismatches */
1315         if (ok > 0) {
1316           match++;
1317           /* and how much the keycode order matches */
1318           if (key > pkey) seq++;
1319           pkey = key;
1320         } else {
1321           /* print spaces instead of \0's */
1322           for (i = 0; i < sizeof(ckey); i++) if (!ckey[i]) ckey[i] = ' ';
1323           TRACE_(key)("mismatch for keysym 0x%04lX, keycode %d, got %c%c%c%c\n",
1324                       keysym, keyc, ckey[0], ckey[1], ckey[2], ckey[3]);
1325           mismatch++;
1326           score -= syms;
1327         }
1328       }
1329     }
1330     TRACE("matches=%d, mismatches=%d, seq=%d, score=%d\n",
1331            match, mismatch, seq, score);
1332     if ((score > max_score) ||
1333         ((score == max_score) && (seq > max_seq))) {
1334       /* best match so far */
1335       kbd_layout = current;
1336       max_score = score;
1337       max_seq = seq;
1338       ismatch = !mismatch;
1339     }
1340   }
1341   /* we're done, report results if necessary */
1342   if (!ismatch)
1343     WARN("Using closest match (%s) for scan/virtual codes mapping.\n",
1344         main_key_tab[kbd_layout].comment);
1345
1346   TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment);
1347 }
1348
1349 /**********************************************************************
1350  *              InitKeyboard (X11DRV.@)
1351  */
1352 void X11DRV_InitKeyboard( BYTE *key_state_table )
1353 {
1354     Display *display = thread_display();
1355     KeySym *ksp;
1356     XModifierKeymap *mmp;
1357     KeySym keysym;
1358     KeyCode *kcp;
1359     XKeyEvent e2;
1360     WORD scan, vkey, OEMvkey;
1361     int keyc, i, keyn, syms;
1362     char ckey[4]={0,0,0,0};
1363     const char (*lkey)[MAIN_LEN][4];
1364
1365     pKeyStateTable = key_state_table;
1366
1367     wine_tsx11_lock();
1368     XDisplayKeycodes(display, &min_keycode, &max_keycode);
1369     ksp = XGetKeyboardMapping(display, min_keycode,
1370                               max_keycode + 1 - min_keycode, &keysyms_per_keycode);
1371     /* We are only interested in keysyms_per_keycode.
1372        There is no need to hold a local copy of the keysyms table */
1373     XFree(ksp);
1374
1375     mmp = XGetModifierMapping(display);
1376     kcp = mmp->modifiermap;
1377     for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
1378     {
1379         int j;
1380
1381         for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
1382             if (*kcp)
1383             {
1384                 int k;
1385
1386                 for (k = 0; k < keysyms_per_keycode; k += 1)
1387                     if (XKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
1388                     {
1389                         NumLockMask = 1 << i;
1390                         TRACE_(key)("NumLockMask is %x\n", NumLockMask);
1391                     }
1392             }
1393     }
1394     XFreeModifiermap(mmp);
1395
1396     /* Detect the keyboard layout */
1397     X11DRV_KEYBOARD_DetectLayout();
1398     lkey = main_key_tab[kbd_layout].key;
1399     syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode;
1400
1401     /* Now build two conversion arrays :
1402      * keycode -> vkey + scancode + extended
1403      * vkey + extended -> keycode */
1404
1405     e2.display = display;
1406     e2.state = 0;
1407
1408     OEMvkey = VK_OEM_8; /* next is available.  */
1409     for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1410     {
1411         char buf[30];
1412         int have_chars;
1413
1414         keysym = 0;
1415         e2.keycode = (KeyCode)keyc;
1416         have_chars = XLookupString(&e2, buf, sizeof(buf), &keysym, NULL);
1417         vkey = 0; scan = 0;
1418         if (keysym)  /* otherwise, keycode not used */
1419         {
1420             if ((keysym >> 8) == 0xFF)         /* non-character key */
1421             {
1422                 vkey = nonchar_key_vkey[keysym & 0xff];
1423                 scan = nonchar_key_scan[keysym & 0xff];
1424                 /* set extended bit when necessary */
1425                 if (scan & 0x100) vkey |= 0x100;
1426             } else if (keysym == 0x20) {                 /* Spacebar */
1427                 vkey = VK_SPACE;
1428                 scan = 0x39;
1429             } else if (have_chars) {
1430               /* we seem to need to search the layout-dependent scancodes */
1431               int maxlen=0,maxval=-1,ok;
1432               for (i=0; i<syms; i++) {
1433                 keysym = XKeycodeToKeysym(display, keyc, i);
1434                 if ((keysym<0x8000) && (keysym!=' '))
1435                 {
1436 #ifdef HAVE_XKB
1437                     if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
1438 #endif
1439                     {
1440                         /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1441                          * with appropriate ShiftMask and Mode_switch, use XLookupString
1442                          * to get character in the local encoding.
1443                          */
1444                         ckey[i] = keysym & 0xFF;
1445                     }
1446                 } else {
1447                   ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1448                 }
1449               }
1450               /* find key with longest match streak */
1451               for (keyn=0; keyn<MAIN_LEN; keyn++) {
1452                 for (ok=(*lkey)[keyn][i=0]; ok&&(i<4); i++)
1453                   if ((*lkey)[keyn][i] && (*lkey)[keyn][i]!=ckey[i]) ok=0;
1454                 if (ok||(i>maxlen)) {
1455                   maxlen=i; maxval=keyn;
1456                 }
1457                 if (ok) break;
1458               }
1459               if (maxval>=0) {
1460                 /* got it */
1461                 const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan;
1462                 const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey;
1463                 scan = (*lscan)[maxval];
1464                 vkey = (*lvkey)[maxval];
1465               }
1466             }
1467 #if 0 /* this breaks VK_OEM_x VKeys in some layout tables by inserting
1468        * a VK code into a not appropriate place.
1469        */
1470             /* find a suitable layout-dependent VK code */
1471             /* (most Winelib apps ought to be able to work without layout tables!) */
1472             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1473             {
1474                 keysym = XLookupKeysym(&e2, i);
1475                 if ((keysym >= VK_0 && keysym <= VK_9)
1476                     || (keysym >= VK_A && keysym <= VK_Z)) {
1477                     vkey = keysym;
1478                 }
1479             }
1480
1481             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1482             {
1483                 keysym = XLookupKeysym(&e2, i);
1484                 switch (keysym)
1485                 {
1486                 case ';':             vkey = VK_OEM_1; break;
1487                 case '/':             vkey = VK_OEM_2; break;
1488                 case '`':             vkey = VK_OEM_3; break;
1489                 case '[':             vkey = VK_OEM_4; break;
1490                 case '\\':            vkey = VK_OEM_5; break;
1491                 case ']':             vkey = VK_OEM_6; break;
1492                 case '\'':            vkey = VK_OEM_7; break;
1493                 case ',':             vkey = VK_OEM_COMMA; break;
1494                 case '.':             vkey = VK_OEM_PERIOD; break;
1495                 case '-':             vkey = VK_OEM_MINUS; break;
1496                 case '+':             vkey = VK_OEM_PLUS; break;
1497                 }
1498             }
1499
1500             if (!vkey)
1501             {
1502                 /* Others keys: let's assign OEM virtual key codes in the allowed range,
1503                  * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
1504                 switch (++OEMvkey)
1505                 {
1506                 case 0xc1 : OEMvkey=0xdb; break;
1507                 case 0xe5 : OEMvkey=0xe9; break;
1508                 case 0xf6 : OEMvkey=0xf5; WARN("No more OEM vkey available!\n");
1509                 }
1510
1511                 vkey = OEMvkey;
1512
1513                 if (TRACE_ON(keyboard))
1514                 {
1515                     TRACE("OEM specific virtual key %X assigned to keycode %X:\n",
1516                                      OEMvkey, e2.keycode);
1517                     TRACE("(");
1518                     for (i = 0; i < keysyms_per_keycode; i += 1)
1519                     {
1520                         char    *ksname;
1521
1522                         keysym = XLookupKeysym(&e2, i);
1523                         ksname = XKeysymToString(keysym);
1524                         if (!ksname)
1525                             ksname = "NoSymbol";
1526                         TRACE( "%lX (%s) ", keysym, ksname);
1527                     }
1528                     TRACE(")\n");
1529                 }
1530             }
1531 #endif
1532         }
1533         TRACE("keycode %04x => vkey %04x\n", e2.keycode, vkey);
1534         keyc2vkey[e2.keycode] = vkey;
1535         keyc2scan[e2.keycode] = scan;
1536     } /* for */
1537
1538     /* If some keys still lack scancodes, assign some arbitrary ones to them now */
1539     for (scan = 0x60, keyc = min_keycode; keyc <= max_keycode; keyc++)
1540       if (keyc2vkey[keyc]&&!keyc2scan[keyc]) {
1541         char *ksname;
1542         keysym = XKeycodeToKeysym(display, keyc, 0);
1543         ksname = XKeysymToString(keysym);
1544         if (!ksname) ksname = "NoSymbol";
1545
1546         /* should make sure the scancode is unassigned here, but >=0x60 currently always is */
1547
1548         TRACE_(key)("assigning scancode %02x to unidentified keycode %02x (%s)\n",scan,keyc,ksname);
1549         keyc2scan[keyc]=scan++;
1550       }
1551
1552     /* Now store one keycode for each modifier. Used to simulate keypresses. */
1553     kcControl = XKeysymToKeycode(display, XK_Control_L);
1554     kcAlt = XKeysymToKeycode(display, XK_Alt_L);
1555     if (!kcAlt) kcAlt = XKeysymToKeycode(display, XK_Meta_L);
1556     kcShift = XKeysymToKeycode(display, XK_Shift_L);
1557     kcNumLock = XKeysymToKeycode(display, XK_Num_Lock);
1558     kcCapsLock = XKeysymToKeycode(display, XK_Caps_Lock);
1559     wine_tsx11_unlock();
1560 }
1561
1562
1563 /***********************************************************************
1564  *              GetKeyboardLayoutList (X11DRV.@)
1565  */
1566 UINT X11DRV_GetKeyboardLayoutList(INT size, HKL *hkl)
1567 {
1568     INT i;
1569
1570     TRACE("%d, %p\n", size, hkl);
1571
1572     if (!size)
1573     {
1574         size = 4096; /* hope we will never have that many */
1575         hkl = NULL;
1576     }
1577
1578     for (i = 0; main_key_tab[i].comment && (i < size); i++)
1579     {
1580         if (hkl)
1581         {
1582             DWORD layout = main_key_tab[i].lcid;
1583             LANGID langid;
1584
1585             /* see comment for GetKeyboardLayout */
1586             langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1587             if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1588                 layout |= 0xe001 << 16; /* FIXME */
1589             else
1590                 layout |= layout << 16;
1591
1592             hkl[i] = (HKL)layout;
1593         }
1594     }
1595     return i;
1596 }
1597
1598
1599 /***********************************************************************
1600  *              GetKeyboardLayout (X11DRV.@)
1601  */
1602 HKL X11DRV_GetKeyboardLayout(DWORD dwThreadid)
1603 {
1604     DWORD layout;
1605     LANGID langid;
1606
1607     if (dwThreadid && dwThreadid != GetCurrentThreadId())
1608         FIXME("couldn't return keyboard layout for thread %04lx\n", dwThreadid);
1609
1610 #if 0
1611     layout = main_key_tab[kbd_layout].lcid;
1612 #else
1613     /* FIXME:
1614      * Winword uses return value of GetKeyboardLayout as a codepage
1615      * to translate ANSI keyboard messages to unicode. But we have
1616      * a problem with it: for instance Polish keyboard layout is
1617      * identical to the US one, and therefore instead of the Polish
1618      * locale id we return the US one.
1619      */
1620     layout = GetUserDefaultLCID();
1621 #endif
1622     /* 
1623      * Microsoft Office expects this value to be something specific
1624      * for Japanese and Korean Windows with an IME the value is 0xe001
1625      * We should probably check to see if an IME exists and if so then
1626      * set this word properly.
1627      */
1628     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1629     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1630         layout |= 0xe001 << 16; /* FIXME */
1631     else
1632         layout |= layout << 16;
1633
1634     return (HKL)layout;
1635 }
1636
1637
1638 /***********************************************************************
1639  *              GetKeyboardLayoutName (X11DRV.@)
1640  */
1641 BOOL X11DRV_GetKeyboardLayoutName(LPWSTR name)
1642 {
1643     static const WCHAR formatW[] = {'%','0','8','l','x',0};
1644     DWORD layout;
1645     LANGID langid;
1646
1647     layout = main_key_tab[kbd_layout].lcid;
1648     /* see comment for GetKeyboardLayout */
1649     langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
1650     if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
1651         layout |= 0xe001 << 16; /* FIXME */
1652     else
1653         layout |= layout << 16;
1654
1655     sprintfW(name, formatW, layout);
1656     TRACE("returning %s\n", debugstr_w(name));
1657     return TRUE;
1658 }
1659
1660
1661 /***********************************************************************
1662  *              LoadKeyboardLayout (X11DRV.@)
1663  */
1664 HKL X11DRV_LoadKeyboardLayout(LPCWSTR name, UINT flags)
1665 {
1666     FIXME("%s, %04x: stub!\n", debugstr_w(name), flags);
1667     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1668     return 0;
1669 }
1670
1671
1672 /***********************************************************************
1673  *              UnloadKeyboardLayout (X11DRV.@)
1674  */
1675 BOOL X11DRV_UnloadKeyboardLayout(HKL hkl)
1676 {
1677     FIXME("%p: stub!\n", hkl);
1678     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1679     return FALSE;
1680 }
1681
1682
1683 /***********************************************************************
1684  *              ActivateKeyboardLayout (X11DRV.@)
1685  */
1686 HKL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags)
1687 {
1688     FIXME("%p, %04x: stub!\n", hkl, flags);
1689     SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
1690     return 0;
1691 }
1692
1693
1694 /***********************************************************************
1695  *           X11DRV_MappingNotify
1696  */
1697 void X11DRV_MappingNotify( XMappingEvent *event )
1698 {
1699     HWND hwnd;
1700
1701     wine_tsx11_lock();
1702     XRefreshKeyboardMapping(event);
1703     wine_tsx11_unlock();
1704     X11DRV_InitKeyboard( pKeyStateTable );
1705
1706     hwnd = GetFocus();
1707     if (!hwnd) hwnd = GetActiveWindow();
1708     PostMessageW(hwnd, WM_INPUTLANGCHANGEREQUEST,
1709                  0 /*FIXME*/, (LPARAM)X11DRV_GetKeyboardLayout(0));
1710 }
1711
1712
1713 /***********************************************************************
1714  *              VkKeyScanEx (X11DRV.@)
1715  *
1716  * Note: Windows ignores HKL parameter and uses current active layout instead
1717  */
1718 SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
1719 {
1720     Display *display = thread_display();
1721     KeyCode keycode;
1722     KeySym keysym;
1723     int i, index;
1724     CHAR cChar;
1725     SHORT ret;
1726
1727     if (!WideCharToMultiByte(CP_UNIXCP, 0, &wChar, 1, &cChar, 1, NULL, NULL))
1728     {
1729         WARN("no translation from unicode to CP_UNIXCP for 0x%02x\n", wChar);
1730         return -1;
1731     }
1732
1733     TRACE("wChar 0x%02x -> cChar '%c'\n", wChar, cChar);
1734
1735     /* char->keysym (same for ANSI chars) */
1736     keysym = (unsigned char)cChar; /* (!) cChar is signed */
1737     if (keysym <= 27) keysym += 0xFF00; /* special chars : return, backspace... */
1738
1739     wine_tsx11_lock();
1740     keycode = XKeysymToKeycode(display, keysym);  /* keysym -> keycode */
1741     if (!keycode)
1742     { /* It didn't work ... let's try with deadchar code. */
1743         TRACE("retrying with | 0xFE00\n");
1744         keycode = XKeysymToKeycode(display, keysym | 0xFE00);
1745     }
1746     wine_tsx11_unlock();
1747
1748     TRACE("'%c'(%#lx, %lu): got keycode %#.2x (%d)\n",
1749             cChar, keysym, keysym, keycode, keycode);
1750
1751     /* keycode -> (keyc2vkey) vkey */
1752     ret = keyc2vkey[keycode];
1753
1754     if (!keycode || !ret)
1755     {
1756         TRACE("keycode for '%c' not found, returning -1\n", cChar);
1757         return -1;
1758     }
1759
1760     index = -1;
1761     wine_tsx11_lock();
1762     for (i = 0; i < 4; i++) /* find shift state */
1763     {
1764         if (XKeycodeToKeysym(display, keycode, i) == keysym)
1765         {
1766             index = i;
1767             break;
1768         }
1769     }
1770     wine_tsx11_unlock();
1771
1772     switch (index)
1773     {
1774         default:
1775         case -1:
1776             WARN("Keysym %lx not found while parsing the keycode table\n", keysym);
1777             return -1;
1778
1779         case 0: break;
1780         case 1: ret += 0x0100; break;
1781         case 2: ret += 0x0600; break;
1782         case 3: ret += 0x0700; break;
1783     }
1784     /*
1785       index : 0     adds 0x0000
1786       index : 1     adds 0x0100 (shift)
1787       index : ?     adds 0x0200 (ctrl)
1788       index : 2     adds 0x0600 (ctrl+alt)
1789       index : 3     adds 0x0700 (ctrl+alt+shift)
1790      */
1791
1792     TRACE(" ... returning %#.2x\n", ret);
1793     return ret;
1794 }
1795
1796 /***********************************************************************
1797  *              MapVirtualKeyEx (X11DRV.@)
1798  */
1799 UINT X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
1800 {
1801     Display *display = thread_display();
1802
1803 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
1804
1805     TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl);
1806     if (hkl != X11DRV_GetKeyboardLayout(0))
1807         FIXME("keyboard layout %p is not supported\n", hkl);
1808
1809         switch(wMapType) {
1810                 case 0: { /* vkey-code to scan-code */
1811                         /* let's do vkey -> keycode -> scan */
1812                         int keyc;
1813                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1814                                 if ((keyc2vkey[keyc] & 0xFF) == wCode)
1815                                         returnMVK (keyc2scan[keyc] & 0xFF);
1816                         TRACE("returning no scan-code.\n");
1817                         return 0; }
1818
1819                 case 1: { /* scan-code to vkey-code */
1820                         /* let's do scan -> keycode -> vkey */
1821                         int keyc;
1822                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1823                                 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
1824                                         returnMVK (keyc2vkey[keyc] & 0xFF);
1825                         TRACE("returning no vkey-code.\n");
1826                         return 0; }
1827
1828                 case 2: { /* vkey-code to unshifted ANSI code */
1829                         /* we still don't know what "unshifted" means. in windows VK_W (0x57)
1830                          * returns 0x57, which is upercase 'W'. So we have to return the uppercase
1831                          * key.. Looks like something is wrong with the MS docs?
1832                          * This is only true for letters, for example VK_0 returns '0' not ')'.
1833                          * - hence we use the lock mask to ensure this happens.
1834                          */
1835                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
1836                         XKeyEvent e;
1837                         KeySym keysym;
1838                         int keyc;
1839                         char s[2];
1840                         e.display = display;
1841
1842                         e.state = LockMask;
1843                         /* LockMask should behave exactly like caps lock - upercase
1844                          * the letter keys and thats about it. */
1845
1846                         wine_tsx11_lock();
1847
1848                         e.keycode = 0;
1849                         /* We exit on the first keycode found, to speed up the thing. */
1850                         for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
1851                         { /* Find a keycode that could have generated this virtual key */
1852                             if  ((keyc2vkey[keyc] & 0xFF) == wCode)
1853                             { /* We filter the extended bit, we don't know it */
1854                                 e.keycode = keyc; /* Store it temporarily */
1855                                 if ((EVENT_event_to_vkey(0,&e) & 0xFF) != wCode) {
1856                                     e.keycode = 0; /* Wrong one (ex: because of the NumLock
1857                                          state), so set it to 0, we'll find another one */
1858                                 }
1859                             }
1860                         }
1861
1862                         if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
1863                           e.keycode = XKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
1864
1865                         if (wCode==VK_DECIMAL)
1866                           e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
1867
1868                         if (!e.keycode)
1869                         {
1870                           WARN("Unknown virtual key %X !!! \n", wCode);
1871                           wine_tsx11_unlock();
1872                           return 0; /* whatever */
1873                         }
1874                         TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
1875
1876                         if (XLookupString(&e, s, 2, &keysym, NULL))
1877                         {
1878                             wine_tsx11_unlock();
1879                             returnMVK (*s);
1880                         }
1881
1882                         TRACE("returning no ANSI.\n");
1883                         wine_tsx11_unlock();
1884                         return 0;
1885                         }
1886
1887                 case 3:   /* **NT only** scan-code to vkey-code but distinguish between  */
1888                           /*             left and right  */
1889                           FIXME(" stub for NT\n");
1890                           return 0;
1891
1892                 default: /* reserved */
1893                         WARN("Unknown wMapType %d !\n", wMapType);
1894                         return 0;
1895         }
1896         return 0;
1897 }
1898
1899 /***********************************************************************
1900  *              GetKeyNameText (X11DRV.@)
1901  */
1902 INT X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
1903 {
1904   int vkey, ansi, scanCode;
1905   KeyCode keyc;
1906   int keyi;
1907   KeySym keys;
1908   char *name;
1909
1910   scanCode = lParam >> 16;
1911   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
1912
1913   /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
1914   vkey = X11DRV_MapVirtualKeyEx(scanCode, 1, X11DRV_GetKeyboardLayout(0));
1915
1916   /*  handle "don't care" bit (0x02000000) */
1917   if (!(lParam & 0x02000000)) {
1918     switch (vkey) {
1919          case VK_LSHIFT:
1920          case VK_RSHIFT:
1921                           vkey = VK_SHIFT;
1922                           break;
1923        case VK_LCONTROL:
1924        case VK_RCONTROL:
1925                           vkey = VK_CONTROL;
1926                           break;
1927           case VK_LMENU:
1928           case VK_RMENU:
1929                           vkey = VK_MENU;
1930                           break;
1931                default:
1932                           break;
1933     }
1934   }
1935
1936   ansi = X11DRV_MapVirtualKeyEx(vkey, 2, X11DRV_GetKeyboardLayout(0));
1937   TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
1938
1939   /* first get the name of the "regular" keys which is the Upper case
1940      value of the keycap imprint.                                     */
1941   if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
1942        (scanCode != 0x137) &&   /* PrtScn   */
1943        (scanCode != 0x135) &&   /* numpad / */
1944        (scanCode != 0x37 ) &&   /* numpad * */
1945        (scanCode != 0x4a ) &&   /* numpad - */
1946        (scanCode != 0x4e ) )    /* numpad + */
1947       {
1948         if ((nSize >= 2) && lpBuffer)
1949         {
1950           *lpBuffer = toupperW((WCHAR)ansi);
1951           *(lpBuffer+1) = 0;
1952           return 1;
1953         }
1954      else
1955         return 0;
1956   }
1957
1958   /* FIXME: horrible hack to fix function keys. Windows reports scancode
1959             without "extended-key" flag. However Wine generates scancode
1960             *with* "extended-key" flag. Seems to occur *only* for the
1961             function keys. Soooo.. We will leave the table alone and
1962             fudge the lookup here till the other part is found and fixed!!! */
1963
1964   if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
1965        (scanCode == 0x157) || (scanCode == 0x158))
1966     scanCode &= 0xff;   /* remove "extended-key" flag for Fx keys */
1967
1968   /* let's do scancode -> keycode -> keysym -> String */
1969
1970   for (keyi=min_keycode; keyi<=max_keycode; keyi++)
1971       if ((keyc2scan[keyi]) == scanCode)
1972          break;
1973   if (keyi <= max_keycode)
1974   {
1975       wine_tsx11_lock();
1976       keyc = (KeyCode) keyi;
1977       keys = XKeycodeToKeysym(thread_display(), keyc, 0);
1978       name = XKeysymToString(keys);
1979       wine_tsx11_unlock();
1980       TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
1981             scanCode, keyc, (int)keys, name);
1982       if (lpBuffer && nSize && name)
1983       {
1984           MultiByteToWideChar(CP_UNIXCP, 0, name, -1, lpBuffer, nSize);
1985           lpBuffer[nSize - 1] = 0;
1986           return 1;
1987       }
1988   }
1989
1990   /* Finally issue FIXME for unknown keys   */
1991
1992   FIXME("(%08lx,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
1993   if (lpBuffer && nSize)
1994     *lpBuffer = 0;
1995   return 0;
1996 }
1997
1998 /***********************************************************************
1999  *              X11DRV_KEYBOARD_MapDeadKeysym
2000  */
2001 static char KEYBOARD_MapDeadKeysym(KeySym keysym)
2002 {
2003         switch (keysym)
2004             {
2005         /* symbolic ASCII is the same as defined in rfc1345 */
2006 #ifdef XK_dead_tilde
2007             case XK_dead_tilde :
2008 #endif
2009             case 0x1000FE7E : /* Xfree's XK_Dtilde */
2010                 return '~';     /* '? */
2011 #ifdef XK_dead_acute
2012             case XK_dead_acute :
2013 #endif
2014             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
2015                 return 0xb4;    /* '' */
2016 #ifdef XK_dead_circumflex
2017             case XK_dead_circumflex:
2018 #endif
2019             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
2020                 return '^';     /* '> */
2021 #ifdef XK_dead_grave
2022             case XK_dead_grave :
2023 #endif
2024             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
2025                 return '`';     /* '! */
2026 #ifdef XK_dead_diaeresis
2027             case XK_dead_diaeresis :
2028 #endif
2029             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
2030                 return 0xa8;    /* ': */
2031 #ifdef XK_dead_cedilla
2032             case XK_dead_cedilla :
2033                 return 0xb8;    /* ', */
2034 #endif
2035 #ifdef XK_dead_macron
2036             case XK_dead_macron :
2037                 return '-';     /* 'm isn't defined on iso-8859-x */
2038 #endif
2039 #ifdef XK_dead_breve
2040             case XK_dead_breve :
2041                 return 0xa2;    /* '( */
2042 #endif
2043 #ifdef XK_dead_abovedot
2044             case XK_dead_abovedot :
2045                 return 0xff;    /* '. */
2046 #endif
2047 #ifdef XK_dead_abovering
2048             case XK_dead_abovering :
2049                 return '0';     /* '0 isn't defined on iso-8859-x */
2050 #endif
2051 #ifdef XK_dead_doubleacute
2052             case XK_dead_doubleacute :
2053                 return 0xbd;    /* '" */
2054 #endif
2055 #ifdef XK_dead_caron
2056             case XK_dead_caron :
2057                 return 0xb7;    /* '< */
2058 #endif
2059 #ifdef XK_dead_ogonek
2060             case XK_dead_ogonek :
2061                 return 0xb2;    /* '; */
2062 #endif
2063 /* FIXME: I don't know this three.
2064             case XK_dead_iota :
2065                 return 'i';
2066             case XK_dead_voiced_sound :
2067                 return 'v';
2068             case XK_dead_semivoiced_sound :
2069                 return 's';
2070 */
2071             }
2072         TRACE("no character for dead keysym 0x%08lx\n",keysym);
2073         return 0;
2074 }
2075
2076 /***********************************************************************
2077  *              ToUnicodeEx (X11DRV.@)
2078  *
2079  * The ToUnicode function translates the specified virtual-key code and keyboard
2080  * state to the corresponding Windows character or characters.
2081  *
2082  * If the specified key is a dead key, the return value is negative. Otherwise,
2083  * it is one of the following values:
2084  * Value        Meaning
2085  * 0    The specified virtual key has no translation for the current state of the keyboard.
2086  * 1    One Windows character was copied to the buffer.
2087  * 2    Two characters were copied to the buffer. This usually happens when a
2088  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
2089  *      be composed with the specified virtual key to form a single character.
2090  *
2091  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
2092  *
2093  */
2094 INT X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
2095                      LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
2096 {
2097     Display *display = thread_display();
2098     XKeyEvent e;
2099     KeySym keysym = 0;
2100     INT ret;
2101     int keyc;
2102     char lpChar[10];
2103     HWND focus;
2104     XIC xic;
2105
2106     if (scanCode & 0x8000)
2107     {
2108         TRACE("Key UP, doing nothing\n" );
2109         return 0;
2110     }
2111
2112     if (hkl != X11DRV_GetKeyboardLayout(0))
2113         FIXME("keyboard layout %p is not supported\n", hkl);
2114
2115     if ((lpKeyState[VK_MENU] & 0x80) && (lpKeyState[VK_CONTROL] & 0x80))
2116     {
2117         TRACE("Ctrl+Alt+[key] won't generate a character\n");
2118         return 0;
2119     }
2120
2121     e.display = display;
2122     e.keycode = 0;
2123     e.state = 0;
2124     e.type = KeyPress;
2125
2126     focus = GetFocus();
2127     if (focus) focus = GetAncestor( focus, GA_ROOT );
2128     if (!focus) focus = GetActiveWindow();
2129     e.window = X11DRV_get_whole_window( focus );
2130     xic = X11DRV_get_ic( focus );
2131
2132     if (lpKeyState[VK_SHIFT] & 0x80)
2133     {
2134         TRACE("ShiftMask = %04x\n", ShiftMask);
2135         e.state |= ShiftMask;
2136     }
2137     if (lpKeyState[VK_CAPITAL] & 0x01)
2138     {
2139         TRACE("LockMask = %04x\n", LockMask);
2140         e.state |= LockMask;
2141     }
2142     if (lpKeyState[VK_CONTROL] & 0x80)
2143     {
2144         TRACE("ControlMask = %04x\n", ControlMask);
2145         e.state |= ControlMask;
2146     }
2147     if (lpKeyState[VK_NUMLOCK] & 0x01)
2148     {
2149         TRACE("NumLockMask = %04x\n", NumLockMask);
2150         e.state |= NumLockMask;
2151     }
2152
2153     /* Restore saved AltGr state */
2154     TRACE("AltGrMask = %04x\n", AltGrMask);
2155     e.state |= AltGrMask;
2156
2157     TRACE_(key)("(%04X, %04X) : faked state = 0x%04x\n",
2158                 virtKey, scanCode, e.state);
2159     wine_tsx11_lock();
2160     /* We exit on the first keycode found, to speed up the thing. */
2161     for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2162       { /* Find a keycode that could have generated this virtual key */
2163           if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
2164           { /* We filter the extended bit, we don't know it */
2165               e.keycode = keyc; /* Store it temporarily */
2166               if ((EVENT_event_to_vkey(xic,&e) & 0xFF) != virtKey) {
2167                   e.keycode = 0; /* Wrong one (ex: because of the NumLock
2168                          state), so set it to 0, we'll find another one */
2169               }
2170           }
2171       }
2172
2173     if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
2174         e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
2175
2176     if (virtKey==VK_DECIMAL)
2177         e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2178
2179     if (!e.keycode && virtKey != VK_NONAME)
2180       {
2181         WARN("Unknown virtual key %X !!! \n",virtKey);
2182         wine_tsx11_unlock();
2183         return virtKey; /* whatever */
2184       }
2185     else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2186
2187     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
2188                 e.type, e.window, e.state, e.keycode);
2189
2190     if (xic)
2191         ret = XmbLookupString(xic, &e, lpChar, sizeof(lpChar), &keysym, NULL);
2192     else
2193         ret = XLookupString(&e, lpChar, sizeof(lpChar), &keysym, NULL);
2194     wine_tsx11_unlock();
2195
2196     if (ret == 0)
2197     {
2198         BYTE dead_char;
2199
2200 #ifdef XK_EuroSign
2201         /* An ugly hack for EuroSign: X can't translate it to a character
2202            for some locales. */
2203         if (keysym == XK_EuroSign)
2204         {
2205             bufW[0] = 0x20AC;
2206             ret = 1;
2207             goto found;
2208         }
2209 #endif
2210         /* Special case: X turns shift-tab into ISO_Left_Tab. */
2211         /* Here we change it back. */
2212         if (keysym == XK_ISO_Left_Tab)
2213         {
2214             bufW[0] = 0x09;
2215             ret = 1;
2216             goto found;
2217         }
2218
2219         dead_char = KEYBOARD_MapDeadKeysym(keysym);
2220         if (dead_char)
2221             {
2222             MultiByteToWideChar(CP_UNIXCP, 0, &dead_char, 1, bufW, bufW_size);
2223             ret = -1;
2224             }
2225         else
2226             {
2227             char        *ksname;
2228
2229             wine_tsx11_lock();
2230             ksname = XKeysymToString(keysym);
2231             wine_tsx11_unlock();
2232             if (!ksname)
2233                 ksname = "No Name";
2234             if ((keysym >> 8) != 0xff)
2235                 {
2236                 ERR("Please report: no char for keysym %04lX (%s) :\n",
2237                     keysym, ksname);
2238                 ERR("(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
2239                     virtKey, scanCode, e.keycode, e.state);
2240                 }
2241             }
2242         }
2243     else {  /* ret != 0 */
2244         /* We have a special case to handle : Shift + arrow, shift + home, ...
2245            X returns a char for it, but Windows doesn't. Let's eat it. */
2246         if (!(e.state & NumLockMask)  /* NumLock is off */
2247             && (e.state & ShiftMask) /* Shift is pressed */
2248             && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
2249         {
2250             lpChar[0] = 0;
2251             ret = 0;
2252         }
2253
2254         /* more areas where X returns characters but Windows does not
2255            CTRL + number or CTRL + symbol */
2256         if (e.state & ControlMask)
2257         {
2258             if (((keysym>=33) && (keysym < 'A')) ||
2259                 ((keysym > 'Z') && (keysym < 'a')))
2260             {
2261                 lpChar[0] = 0;
2262                 ret = 0;
2263             }
2264         }
2265
2266         /* We have another special case for delete key (XK_Delete) on an
2267          extended keyboard. X returns a char for it, but Windows doesn't */
2268         if (keysym == XK_Delete)
2269         {
2270             lpChar[0] = 0;
2271             ret = 0;
2272         }
2273         else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
2274                 && (keysym == XK_KP_Decimal))
2275         {
2276             lpChar[0] = 0;
2277             ret = 0;
2278         }
2279
2280         /* perform translation to unicode */
2281         if(ret)
2282         {
2283             TRACE_(key)("Translating char 0x%02x to unicode\n", *(BYTE *)lpChar);
2284             ret = MultiByteToWideChar(CP_UNIXCP, 0, lpChar, ret, bufW, bufW_size);
2285         }
2286     }
2287
2288 found:
2289     TRACE_(key)("ToUnicode about to return %d with char %x %s\n",
2290                 ret, (ret && bufW) ? bufW[0] : 0, bufW ? "" : "(no buffer)");
2291     return ret;
2292 }
2293
2294 /***********************************************************************
2295  *              Beep (X11DRV.@)
2296  */
2297 void X11DRV_Beep(void)
2298 {
2299     wine_tsx11_lock();
2300     XBell(thread_display(), 0);
2301     wine_tsx11_unlock();
2302 }