Fixed some issues found by winapi_check.
[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
31 #include "ts_xlib.h"
32 #include "ts_xresource.h"
33 #include "ts_xutil.h"
34 #ifdef HAVE_XKB
35 #include <X11/XKBlib.h>
36 #endif
37
38 #include <ctype.h>
39 #include <string.h>
40
41 #include "windef.h"
42 #include "wingdi.h"
43 #include "wine/winuser16.h"
44 #include "winnls.h"
45 #include "win.h"
46 #include "x11drv.h"
47 #include "wine/debug.h"
48
49 WINE_DEFAULT_DEBUG_CHANNEL(keyboard);
50 WINE_DECLARE_DEBUG_CHANNEL(key);
51 WINE_DECLARE_DEBUG_CHANNEL(dinput);
52
53 int min_keycode, max_keycode, keysyms_per_keycode;
54 WORD keyc2vkey[256], keyc2scan[256];
55
56 static LPBYTE pKeyStateTable;
57 static int NumLockMask, AltGrMask; /* mask in the XKeyEvent state */
58 static int kcControl, kcAlt, kcShift, kcNumLock, kcCapsLock; /* keycodes */
59 #ifdef HAVE_XKB
60 static int is_xkb, xkb_opcode, xkb_event, xkb_error;
61 #endif
62
63 static char KEYBOARD_MapDeadKeysym(KeySym keysym);
64
65 /* Keyboard translation tables */
66 #define MAIN_LEN 48
67 static const WORD main_key_scan_qwerty[MAIN_LEN] =
68 {
69 /* this is my (102-key) keyboard layout, sorry if it doesn't quite match yours */
70  /* `    1    2    3    4    5    6    7    8    9    0    -    = */
71    0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
72  /* q    w    e    r    t    y    u    i    o    p    [    ] */
73    0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
74  /* a    s    d    f    g    h    j    k    l    ;    '    \ */
75    0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
76  /* z    x    c    v    b    n    m    ,    .    / */
77    0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
78    0x56 /* the 102nd key (actually to the right of l-shift) */
79 };
80
81 static const WORD main_key_scan_dvorak[MAIN_LEN] =
82 {
83  /* `    1    2    3    4    5    6    7    8    9    0    [    ] */
84    0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x1A,0x1B,
85  /* '    ,    .    p    y    f    g    c    r    l    /    = */
86    0x28,0x33,0x34,0x19,0x15,0x21,0x22,0x2E,0x13,0x26,0x35,0x0D,
87  /* a    o    e    u    i    d    h    t    n    s    -    \ */
88    0x1E,0x18,0x12,0x16,0x17,0x20,0x23,0x14,0x31,0x1F,0x0C,0x2B,
89  /* ;    q    j    k    x    b    m    w    v    z */
90    0x27,0x10,0x24,0x25,0x2D,0x30,0x32,0x11,0x2F,0x2C,
91    0x56 /* the 102nd key (actually to the right of l-shift) */
92 };
93
94 static const WORD main_key_vkey_qwerty[MAIN_LEN] =
95 {
96 /* NOTE: this layout must concur with the scan codes layout above */
97    VK_OEM_3,VK_1,VK_2,VK_3,VK_4,VK_5,VK_6,VK_7,VK_8,VK_9,VK_0,VK_OEM_MINUS,VK_OEM_PLUS,
98    VK_Q,VK_W,VK_E,VK_R,VK_T,VK_Y,VK_U,VK_I,VK_O,VK_P,VK_OEM_4,VK_OEM_6,
99    VK_A,VK_S,VK_D,VK_F,VK_G,VK_H,VK_J,VK_K,VK_L,VK_OEM_1,VK_OEM_7,VK_OEM_5,
100    VK_Z,VK_X,VK_C,VK_V,VK_B,VK_N,VK_M,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
101    VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
102 };
103
104 static const WORD main_key_vkey_azerty[MAIN_LEN] =
105 {
106 /* NOTE: this layout must concur with the scan codes layout above */
107    VK_OEM_7,VK_1,VK_2,VK_3,VK_4,VK_5,VK_6,VK_7,VK_8,VK_9,VK_0,VK_OEM_4,VK_OEM_PLUS,
108    VK_A,VK_Z,VK_E,VK_R,VK_T,VK_Y,VK_U,VK_I,VK_O,VK_P,VK_OEM_6,VK_OEM_1,
109    VK_Q,VK_S,VK_D,VK_F,VK_G,VK_H,VK_J,VK_K,VK_L,VK_M,VK_OEM_3,VK_OEM_5,
110    VK_W,VK_X,VK_C,VK_V,VK_B,VK_N,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,VK_OEM_8,
111    VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
112 };
113
114 static const WORD main_key_vkey_dvorak[MAIN_LEN] =
115 {
116 /* NOTE: this layout must concur with the scan codes layout above */
117    VK_OEM_3,VK_1,VK_2,VK_3,VK_4,VK_5,VK_6,VK_7,VK_8,VK_9,VK_0,VK_OEM_4,VK_OEM_6,
118    VK_OEM_7,VK_OEM_COMMA,VK_OEM_PERIOD,VK_P,VK_Y,VK_F,VK_G,VK_C,VK_R,VK_L,VK_OEM_2,VK_OEM_PLUS,
119    VK_A,VK_O,VK_E,VK_U,VK_I,VK_D,VK_H,VK_T,VK_N,VK_S,VK_OEM_MINUS,VK_OEM_5,
120    VK_OEM_1,VK_Q,VK_J,VK_K,VK_X,VK_B,VK_M,VK_W,VK_V,VK_Z,
121    VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
122 };
123
124 /* FIXME: add other layouts, such as German QWERTZ */
125
126 /*** DEFINE YOUR NEW LANGUAGE-SPECIFIC MAPPINGS BELOW, SEE EXISTING TABLES */
127
128 /* the VK mappings for the main keyboard will be auto-assigned as before,
129    so what we have here is just the character tables */
130 /* order: Normal, Shift, AltGr, Shift-AltGr */
131 /* We recommend you write just what is guaranteed to be correct (i.e. what's
132    written on the keycaps), not the bunch of special characters behind AltGr
133    and Shift-AltGr if it can vary among different X servers */
134 /* Remember that your 102nd key (to the right of l-shift) should be on a
135    separate line, see existing tables */
136 /* If Wine fails to match your new table, use -debugmsg +key to find out why */
137 /* Remember to also add your new table to the layout index table far below! */
138
139 /*** German Logitech Desktop Pro keyboard layout */
140 static const char main_key_DE_logitech[MAIN_LEN][4] =
141 {
142  "^\xb0","1!","2\"","3\xa7","4$","5%","6&","7/{","8([","9)]","0=}","\xdf?\\","'`",
143  "qQ@","wW","eE","rR","tT","zZ","uU","iI","oO","pP","\xfc\xdc","+*~",
144  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","\xf6\xd6","\xe4\xc4","#'",
145  "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
146  "<>|"
147 };
148
149 /*** United States keyboard layout (mostly contributed by Uwe Bonnes) */
150 static const char main_key_US[MAIN_LEN][4] =
151 {
152  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
153  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
154  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
155  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?"
156 };
157
158 /*** United States keyboard layout (phantom key version) */
159 /* (XFree86 reports the <> key even if it's not physically there) */
160 static const char main_key_US_phantom[MAIN_LEN][4] =
161 {
162  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
163  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
164  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
165  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
166  "<>" /* the phantom key */
167 };
168
169 /*** United States keyboard layout (dvorak version) */
170 static const char main_key_US_dvorak[MAIN_LEN][4] =
171 {
172  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","[{","]}",
173  "'\"",",<",".>","pP","yY","fF","gG","cC","rR","lL","/?","=+",
174  "aA","oO","eE","uU","iI","dD","hH","tT","nN","sS","-_","\\|",
175  ";:","qQ","jJ","kK","xX","bB","mM","wW","vV","zZ"
176 };
177
178 /*** British keyboard layout */
179 static const char main_key_UK[MAIN_LEN][4] =
180 {
181  "`","1!","2\"","3£","4$","5%","6^","7&","8*","9(","0)","-_","=+",
182  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
183  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'@","#~",
184  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
185  "\\|"
186 };
187
188 /*** French keyboard layout (contributed by Eric Pouech) */
189 static const char main_key_FR[MAIN_LEN][4] =
190 {
191  "²","&1","é2~","\"3#","'4{","(5[","-6|","è7","_8\\","ç9^±","à0@",")°]","=+}",
192  "aA","zZ","eE","rR","tT","yY","uU","iI","oO","pP","^¨","$£¤",
193  "qQ","sSß","dD","fF","gG","hH","jJ","kK","lL","mM","ù%","*µ",
194  "wW","xX","cC","vV","bB","nN",",?",";.",":/","!§",
195  "<>"
196 };
197
198 /*** Icelandic keyboard layout (contributed by Ríkharður Egilsson) */
199 static const char main_key_IS[MAIN_LEN][4] =
200 {
201  "°","1!","2\"","3#","4$","5%","6&","7/{","8([","9)]","0=}","öÖ\\","-_",
202  "qQ@","wW","eE","rR","tT","yY","uU","iI","oO","pP","ðÐ","'?~",
203  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","æÆ","´^","+*`",
204  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","þÞ",
205  "<>|"
206 };
207
208 /*** German keyboard layout (contributed by Ulrich Weigand) */
209 static const char main_key_DE[MAIN_LEN][4] =
210 {
211  "^°","1!","2\"²","3§³","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","'`",
212  "qQ@","wW","eE\80","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
213  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#´",
214  "yY","xX","cC","vV","bB","nN","mMµ",",;",".:","-_",
215  "<>|"
216 };
217
218 /*** German keyboard layout without dead keys */
219 static const char main_key_DE_nodead[MAIN_LEN][4] =
220 {
221  "^°","1!","2\"","3§","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","´",
222  "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
223  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
224  "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
225  "<>"
226 };
227
228 /*** German keyboard layout without dead keys 105 Keys (contributed by Matthias Fechner)*/
229 static const char main_key_DE_nodead_105[MAIN_LEN][4] =
230 {
231  "^°","1!","2\"²","3§³","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","'`",
232  "qQ@","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
233  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
234  "<>|","yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
235 };
236
237 /*** Swiss German keyboard layout (contributed by Jonathan Naylor) */
238 static const char main_key_SG[MAIN_LEN][4] =
239 {
240  "§°","1+|","2\"@","3*#","4ç","5%","6&¬","7/¦","8(¢","9)","0=","'?´","^`~",
241  "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üè[","¨!]",
242  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öé","äà{","$£}",
243  "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
244  "<>\\"
245 };
246
247 /*** Swiss French keyboard layout (contributed by Philippe Froidevaux) */
248 static const char main_key_SF[MAIN_LEN][4] =
249 {
250  "§°","1+|","2\"@","3*#","4ç","5%","6&¬","7/¦","8(¢","9)","0=","'?´","^`~",
251  "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","èü[","¨!]",
252  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","éö","àä{","$£}",
253  "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
254  "<>\\"
255 };
256
257 /*** Norwegian keyboard layout (contributed by Ove Kåven) */
258 static const char main_key_NO[MAIN_LEN][4] =
259 {
260  "|§","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?","\\`´",
261  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^~",
262  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","øØ","æÆ","'*",
263  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
264  "<>"
265 };
266
267 /*** Danish keyboard layout (contributed by Bertho Stultiens) */
268 static const char main_key_DA[MAIN_LEN][4] =
269 {
270  "½§","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?","´`|",
271  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^~",
272  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","æÆ","øØ","'*",
273  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
274  "<>\\"
275 };
276
277 /*** Swedish keyboard layout (contributed by Peter Bortas) */
278 static const char main_key_SE[MAIN_LEN][4] =
279 {
280  "§½","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?\\","´`",
281  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^~",
282  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*",
283  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
284  "<>|"
285 };
286
287 /*** Estonian keyboard layout (contributed by Raul Metsma zombi82@hot.ee) */
288 static const char main_key_ET[MAIN_LEN][4] =
289 {
290  " ~","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?\\","´`",
291  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","üÜ","õÕ§",
292  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*½",
293  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
294  "<>|"
295 };
296
297 /*** Canadian French keyboard layout */
298 static const char main_key_CF[MAIN_LEN][4] =
299 {
300  "#|\\","1!±","2\"@","3/£","4$¢","5%¤","6?¬","7&¦","8*²","9(³","0)¼","-_½","=+¾",
301  "qQ","wW","eE","rR","tT","yY","uU","iI","oO§","pP¶","^^[","¸¨]",
302  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:~","``{","<>}",
303  "zZ","xX","cC","vV","bB","nN","mM",",'-",".","éÉ",
304  "«»°"
305 };
306
307 /*** Portuguese keyboard layout */
308 static const char main_key_PT[MAIN_LEN][4] =
309 {
310  "\\¦","1!","2\"@","3#£","4$§","5%","6&","7/{","8([","9)]","0=}","'?","«»",
311  "qQ",  "wW","eE",  "rR", "tT", "yY", "uU", "iI", "oO", "pP", "+*\\¨","\\'\\`",
312  "aA",  "sS","dD",  "fF", "gG", "hH", "jJ", "kK", "lL", "çÇ", "ºª", "\\~\\^",
313  "zZ",  "xX","cC",  "vV", "bB", "nN", "mM", ",;", ".:", "-_",
314  "<>"
315 };
316
317 /*** Italian keyboard layout */
318 static const char main_key_IT[MAIN_LEN][4] =
319 {
320  "\\|","1!¹","2\"²","3£³","4$¼","5%½","6&¾","7/{","8([","9)]","0=}","'?`","ì^~",
321  "qQ@","wW","eE","rR","tT","yY","uU","iI","oOø","pPþ","èé[","+*]",
322  "aA","sSß","dDð","fF","gG","hH","jJ","kK","lL","òç@","à°#","ù§",
323  "zZ","xX","cC","vV","bB","nN","mMµ",",;",".:·","-_",
324  "<>|"
325 };
326
327 /*** Finnish keyboard layout */
328 static const char main_key_FI[MAIN_LEN][4] =
329 {
330  "","1!","2\"@","3#","4$","5%","6&","7/{","8([","9)]","0=}","+?\\","\'`",
331  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","","\"^~",
332  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","","","'*",
333  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
334  "<>|"
335 };
336
337 /*** Bulgarian bds keyboard layout */
338 static const char main_key_BG_bds[MAIN_LEN][4] =
339 {
340  "`~()","1!","2@2?","3#3+","4$4\"","5%","6^6=","7&7:","8*8/","9(","0)","-_-I","=+.V",
341  "qQ,û","wWóÓ","eEåÅ","rRèÈ","tTøØ","yYùÙ","uUêÊ","iIñÑ","oOäÄ","pPçÇ","[{öÖ","]};",
342  "aAüÜ","sSÿß","dDàÀ","fFîÎ","gGæÆ","hHãÃ","jJòÒ","kKíÍ","lLâÂ",";:ìÌ","'\"÷×","\\|'Û",
343  "zZþÞ","xXéÉ","cCúÚ","vVýÝ","bBôÔ","nNõÕ","mMïÏ",",<ðÐ",".>ëË","/?áÁ",
344  "<>" /* the phantom key */
345 };
346
347 /*** Bulgarian phonetic keyboard layout */
348 static const char main_key_BG_phonetic[MAIN_LEN][4] =
349 {
350  "`~÷×","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
351  "qQÿß","wWâÂ","eEåÅ","rRðÐ","tTòÒ","yYúÚ","uUóÓ","iIèÈ","oOîÎ","pPïÏ","[{øØ","]}ùÙ",
352  "aAàÀ","sSñÑ","dDäÄ","fFôÔ","gGãÃ","hHõÕ","jJéÉ","kKêÊ","lLëË",";:","'\"","\\|þÞ",
353  "zZçÇ","xXüÜ","cCöÖ","vVæÆ","bBáÁ","nNíÍ","mMìÌ",",<",".>","/?",
354  "<>" /* the phantom key */
355 };
356
357 /*** Russian keyboard layout (contributed by Pavel Roskin) */
358 static const char main_key_RU[MAIN_LEN][4] =
359 {
360  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
361  "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}ßÿ",
362  "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|",
363  "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?"
364 };
365
366 /*** Russian keyboard layout (phantom key version) */
367 static const char main_key_RU_phantom[MAIN_LEN][4] =
368 {
369  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
370  "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}ßÿ",
371  "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|",
372  "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?",
373  "<>" /* the phantom key */
374 };
375
376 /*** Russian keyboard layout KOI8-R */
377 static const char main_key_RU_koi8r[MAIN_LEN][4] =
378 {
379  "()","1!","2\"","3/","4$","5:","6,","7.","8;","9?","0%","-_","=+",
380  "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","ßÿ",
381  "Ææ","Ùù","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","Üü","\\|",
382  "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà","/?",
383  "<>" /* the phantom key */
384 };
385
386 /*** Ukrainian keyboard layout KOI8-U */
387 static const char main_key_UA[MAIN_LEN][4] =
388 {
389  "`~­½","1!1!","2@2\"","3#3'","4$4*","5%5:","6^6,","7&7.","8*8;","9(9(","0)0)","-_-_","=+=+",
390  "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}§·",
391  "aAÆæ","sS¦¶","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"¤´","\\|\\|",
392  "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?/?",
393  "<>" /* the phantom key */
394 };
395
396 /*** Spanish keyboard layout (contributed by José Marcos López) */
397 static const char main_key_ES[MAIN_LEN][4] =
398 {
399  "ºª\\","1!|","2\"@","3·#","4$","5%","6&¬","7/","8(","9)","0=","'?","¡¿",
400  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","`^[","+*]",
401  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ñÑ","'¨{","çÇ}",
402  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
403  "<>"
404 };
405
406 /*** Belgian keyboard layout ***/
407 static const char main_key_BE[MAIN_LEN][4] =
408 {
409  "","&1|","é2@","\"3#","'4","(5","§6^","è7","!8","ç9{","à0}",")°","-_",
410  "aA","zZ","eE¤","rR","tT","yY","uU","iI","oO","pP","^¨[","$*]",
411  "qQ","sSß","dD","fF","gG","hH","jJ","kK","lL","mM","ù%´","µ£`",
412  "wW","xX","cC","vV","bB","nN",",?",";.",":/","=+~",
413  "<>\\"
414 };
415
416 /*** Hungarian keyboard layout (contributed by Zoltán Kovács) */
417 static const char main_key_HU[MAIN_LEN][4] =
418 {
419  "0§","1'~","2\"·","3+^","4!¢","5%°","6/²","7=`","8(ÿ","9)´","öÖ½","üܨ","óÓ¸",
420  "qQ\\","wW|","eE","rR","tT","zZ","uU","iIÍ","oOø","pP","õÕ÷","úÚ×",
421  "aA","sSð","dDÐ","fF[","gG]","hH","jJí","kK³","lL£","éÉ$","áÁß","ûÛ¤",
422  "yY>","xX#","cC&","vV@","bB{","nN}","mM",",?;",".:·","-_*",
423  "íÍ<"
424 };
425
426 /*** Polish (programmer's) keyboard layout ***/
427 static const char main_key_PL[MAIN_LEN][4] =
428 {
429  "`~","1!","2@","3#","4$","5%","6^","7&§","8*","9(","0)","-_","=+",
430  "qQ","wW","eEêÊ","rR","tT","yY","uU","iI","oOóÓ","pP","[{","]}",
431  "aA±¡","sS¶¦","dD","fF","gG","hH","jJ","kK","lL³£",";:","'\"","\\|",
432  "zZ¿¯","xX¼¬","cCæÆ","vV","bB","nNñÑ","mM",",<",".>","/?",
433  "<>|"
434 };
435
436 /*** Slovenian keyboard layout by Rok Mandeljc <rok.mandeljc@gimb.org> ***/
437 static const char main_key_SI[MAIN_LEN][4] =
438 {
439  "¸¨","1!","2\"·","3#^","4$¢","5%°","6&²","7/`","8(ÿ","9)´","0=½","'?¨","+*¸",
440  "qQ\\","wW|","eE","rR","tT","zZ","uU","iI","oO","pP","¹©÷","ðÐ×",
441  "aA","sS","dD","fF[","gG]","hH","jJ","kK³","lL£","èÈ","æÆß","¾®¤",
442  "yY","xX","cC","vV@","bB{","nN}","mM§",",;",".:","-_",
443  "<>"
444 };
445
446 /*** Croatian keyboard layout specific for me <jelly@srk.fer.hr> ***/
447 static const char main_key_HR_jelly[MAIN_LEN][4] =
448 {
449  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
450  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{¹©","]}ðÐ",
451  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:èÈ","'\"æÆ","\\|¾®",
452  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
453  "<>|"
454 };
455
456 /*** Croatian keyboard layout ***/
457 static const char main_key_HR[MAIN_LEN][4] =
458 {
459  "¸¨","1!","2\"·","3#^","4$¢","5%°","6&²","7/`","8(ÿ","9)´","0=½","'?¨","+*¸",
460  "qQ\\","wW|","eE","rR","tT","zZ","uU","iI","oO","pP","¹©÷","ðÐ×",
461  "aA","sS","dD","fF[","gG]","hH","jJ","kK³","lL£","èÈ","æÆß","¾®¤",
462  "yY","xX","cC","vV@","bB{","nN}","mM§",",;",".:","-_/",
463  "<>"
464 };
465
466 /*** Japanese 106 keyboard layout ***/
467 static const char main_key_JA_jp106[MAIN_LEN][4] =
468 {
469  "1!","2\"","3#","4$","5%","6&","7'","8(","9)","0~","-=","^~","\\|",
470  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","@`","[{",
471  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";+",":*","]}",
472  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
473  "\\_",
474 };
475
476 /*** Japanese pc98x1 keyboard layout ***/
477 static const char main_key_JA_pc98x1[MAIN_LEN][4] =
478 {
479  "1!","2\"","3#","4$","5%","6&","7'","8(","9)","0","-=","^`","\\|",
480  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","@~","[{",
481  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";+",":*","]}",
482  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
483  "\\_",
484 };
485
486 /*** Brazilian ABNT-2 keyboard layout (contributed by Raul Gomes Fernandes) */
487 static const char main_key_PT_br[MAIN_LEN][4] =
488 {
489  "'\"","1!","2@","3#","4$","5%","6¨","7&","8*","9(","0)","-_","=+",
490  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","´`","[{",
491  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","çÇ","~^","]}",
492  "zZ","xX","cC","vV","bB","nN","mM",",<",".>",";:","/?"
493 };
494
495 /*** US international keyboard layout (contributed by Gustavo Noronha (kov@debian.org)) */
496 static const char main_key_US_intl[MAIN_LEN][4] =
497 {
498   "`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+", "\\|",
499   "qQ", "wW", "eE", "rR", "tT", "yY", "uU", "iI", "oO", "pP", "[{", "]}",
500   "aA", "sS", "dD", "fF", "gG", "hH", "jJ", "kK", "lL", ";:", "'\"",
501   "zZ", "xX", "cC", "vV", "bB", "nN", "mM", ",<", ".>", "/?"
502 };
503
504 /*** Slovak keyboard layout (see cssk_ibm(sk_qwerty) in xkbsel)
505   - dead_abovering replaced with degree - no symbol in iso8859-2
506   - brokenbar replaced with bar                                 */
507 static const char main_key_SK[MAIN_LEN][4] =
508 {
509  ";0","+1","µ2","¹3","è4","»5","¾6","ý7","á8","í9","é0","=%","'v",
510  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","ú/","ä(",
511  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ô\"","§!","ò)",
512  "zZ","xX","cC","vV","bB","nN","mM",",?",".:","-_",
513  "<>"
514 };
515
516 /*** Slovak and Czech (programmer's) keyboard layout (see cssk_dual(cs_sk_ucw)) */
517 static const char main_key_SK_prog[MAIN_LEN][4] =
518 {
519  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
520  "qQäÄ","wWìÌ","eEéÉ","rRøØ","tT»«","yYýÝ","uUùÙ","iIíÍ","oOóÓ","pPöÖ","[{","]}",
521  "aAáÁ","sS¹©","dDïÏ","fFëË","gGàÀ","hHúÚ","jJüÜ","kKôÔ","lLµ¥",";:","'\"","\\|",
522  "zZ¾®","xX¤","cCèÈ","vVçÇ","bB","nNòÒ","mMåÅ",",<",".>","/?",
523  "<>"
524 };
525
526 /*** Czech keyboard layout (see cssk_ibm(cs_qwerty) in xkbsel) */
527 static const char main_key_CS[MAIN_LEN][4] =
528 {
529  ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0½)","=%","",
530  "qQ\\","wW|","eE","rR","tT","yY","uU","iI","oO","pP","ú/[{",")(]}",
531  "aA","sSð","dDÐ","fF[","gG]","hH","jJ","kK³","lL£","ù\"$","§!ß","¨'",
532  "zZ>","xX#","cC&","vV@","bB{","nN}","mM",",?<",".:>","-_*",
533  "<>\\|"
534 };
535
536 /*** Latin American keyboard layout (contributed by Gabriel Orlando Garcia) */
537 static const char main_key_LA[MAIN_LEN][4] =
538 {
539  "|°¬","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?\\","¡¿",
540  "qQ@","wW","eE","rR","tT","yY","uU","iI","oO","pP","´¨","+*~",
541  "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ñÑ","{[^","}]`",
542  "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
543  "<>"
544 };
545
546 /*** Lithuanian (Baltic) keyboard layout (contributed by Nerijus Baliûnas) */
547 static const char main_key_LT_B[MAIN_LEN][4] =
548 {
549  "`~","àÀ","èÈ","æÆ","ëË","áÁ","ðÐ","øØ","ûÛ","((","))","-_","þÞ",
550  "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
551  "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
552  "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?"
553 };
554
555 /*** Turkish keyboard Layout */
556 static const char main_key_TK[MAIN_LEN][4] =
557 {
558 "\"é","1!","2'","3^#","4+$","5%","6&","7/{","8([","9)]","0=}","*?\\","-_",
559 "qQ@","wW","eE","rR","tT","yY","uU","ýIî","oO","pP","ðÐ","üÜ~",
560 "aAæ","sSß","dD","fF","gG","hH","jJ","kK","lL","þÞ","iÝ",",;`",
561 "zZ","xX","cC","vV","bB","nN","mM","öÖ","çÇ",".:"
562 };
563
564 /*** Israeli keyboard layout */
565 static const char main_key_IL[MAIN_LEN][4] =
566 {
567  "`~;","1!1","2@2","3#3","4$4","5%5","6^6","7&7","8*8","9(9","0)0","-_-","=+=",
568  "qQ/","wW'","eE÷","rRø","tTà","yYè","uUå","iIï","oOí","pPô","[{[","]}]",
569  "aAù","sSã","dDâ","fFë","gGò","hHé","jJç","kKì","lLê",";:ó","\'\",","\\|\\",
570  "zZæ","xXñ","cCá","vVä","bBð","nNî","mMö",",<ú",".>õ","/?."
571 };
572
573 /*** Greek keyboard layout (contributed by Kriton Kyrimis <kyrimis@cti.gr>)
574   Greek characters for "wW" and "sS" are omitted to not produce a mismatch
575   message since they have different characters in gr and el XFree86 layouts. */
576 static const char main_key_EL[MAIN_LEN][4] =
577 {
578  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
579  "qQ;:","wW","eEåÅ","rRñÑ","tTôÔ","yYõÕ","uUèÈ","iIéÉ","oOïÏ","pPðÐ","[{","]}",
580  "aAáÁ","sS","dDäÄ","fFöÖ","gGãÃ","hHçÇ","jJîÎ","kKêÊ","lLëË",";:´¨","'\"","\\|",
581  "zZæÆ","xX÷×","cCøØ","vVùÙ","bBâÂ","nNíÍ","mMìÌ",",<",".>","/?",
582  "<>"
583 };
584
585 /*** VNC keyboard layout */
586 static const WORD main_key_scan_vnc[MAIN_LEN] =
587 {
588    0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x1A,0x1B,0x27,0x28,0x29,0x33,0x34,0x35,0x2B,
589    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,
590    0x56
591 };
592
593 static const WORD main_key_vkey_vnc[MAIN_LEN] =
594 {
595    VK_1,VK_2,VK_3,VK_4,VK_5,VK_6,VK_7,VK_8,VK_9,VK_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,
596    VK_A,VK_B,VK_C,VK_D,VK_E,VK_F,VK_G,VK_H,VK_I,VK_J,VK_K,VK_L,VK_M,VK_N,VK_O,VK_P,VK_Q,VK_R,VK_S,VK_T,VK_U,VK_V,VK_W,VK_X,VK_Y,VK_Z,
597    VK_OEM_102
598 };
599
600 static const char main_key_vnc[MAIN_LEN][4] =
601 {
602  "1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+","[{","]}",";:","'\"","`~",",<",".>","/?","\\|",
603  "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"
604 };
605
606 /*** Layout table. Add your keyboard mappings to this list */
607 static const struct {
608     const char *comment;
609     const UINT layout_cp; /* Code page for this layout */
610     const char (*key)[MAIN_LEN][4];
611     const WORD (*scan)[MAIN_LEN]; /* scan codes mapping */
612     const WORD (*vkey)[MAIN_LEN]; /* virtual key codes mapping */
613 } main_key_tab[]={
614  {"United States keyboard layout", 28591, &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty},
615  {"United States keyboard layout (phantom key version)", 28591, &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
616  {"United States keyboard layout (dvorak)", 28591, &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak},
617  {"British keyboard layout", 28591, &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
618  {"German keyboard layout", 28591, &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwerty},
619  {"German keyboard layout without dead keys", 28591, &main_key_DE_nodead, &main_key_scan_qwerty, &main_key_vkey_qwerty},
620  {"German keyboard layout for logitech desktop pro", 28591, &main_key_DE_logitech,  &main_key_scan_qwerty, &main_key_vkey_qwerty},
621  {"German keyboard layout without dead keys 105", 28591, &main_key_DE_nodead_105, &main_key_scan_qwerty, &main_key_vkey_qwerty},
622  {"Swiss German keyboard layout", 28591, &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwerty},
623  {"Swedish keyboard layout", 28591, &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty},
624  {"Estonian keyboard layout", 28591, &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty},
625  {"Norwegian keyboard layout", 28591, &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty},
626  {"Danish keyboard layout", 28591, &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
627  {"French keyboard layout", 28591, &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty},
628  {"Canadian French keyboard layout", 28591, &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
629  {"Belgian keyboard layout", 28591, &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty},
630  {"Swiss French keyboard layout", 28591, &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
631  {"Portuguese keyboard layout", 28591, &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
632  {"Brazilian ABNT-2 keyboard layout", 28591, &main_key_PT_br, &main_key_scan_qwerty, &main_key_vkey_qwerty},
633  {"United States International keyboard layout", 28591, &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
634  {"Finnish keyboard layout", 28591, &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
635  {"Bulgarian bds keyboard layout", 1251, &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty},
636  {"Bulgarian phonetic keyboard layout", 1251, &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
637  {"Russian keyboard layout", 20866, &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
638  {"Russian keyboard layout (phantom key version)", 20866, &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
639  {"Russian keyboard layout KOI8-R", 20866, &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty},
640  {"Ukrainian keyboard layout KOI8-U", 20866, &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
641  {"Spanish keyboard layout", 28591, &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty},
642  {"Italian keyboard layout", 28591, &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
643  {"Icelandic keyboard layout", 28591, &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
644  {"Hungarian keyboard layout", 28592, &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
645  {"Polish (programmer's) keyboard layout", 28592, &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
646  {"Slovenian keyboard layout", 28592, &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
647  {"Croatian keyboard layout", 28592, &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwerty},
648  {"Croatian keyboard layout (specific)", 28592, &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
649  {"Japanese 106 keyboard layout", 932, &main_key_JA_jp106, &main_key_scan_qwerty, &main_key_vkey_qwerty},
650  {"Japanese pc98x1 keyboard layout", 932, &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
651  {"Slovak keyboard layout", 28592, &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
652  {"Slovak and Czech keyboard layout without dead keys", 28592, &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
653  {"Czech keyboard layout", 28592, &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
654  {"Latin American keyboard layout", 28591, &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
655  {"Lithuanian (Baltic) keyboard layout", 28603, &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty},
656  {"Turkish keyboard layout", 28599, &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
657  {"Israeli keyboard layout", 28598, &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
658  {"VNC keyboard layout", 28591, &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc},
659  {"Greek keyboard layout", 28597, &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
660
661  {NULL, 0, NULL, NULL, NULL} /* sentinel */
662 };
663 static unsigned kbd_layout=0; /* index into above table of layouts */
664
665 /* maybe more of these scancodes should be extended? */
666                 /* extended must be set for ALT_R, CTRL_R,
667                    INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
668                    keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
669                 /* FIXME should we set extended bit for NumLock ? My
670                  * Windows does ... DF */
671                 /* Yes, to distinguish based on scan codes, also
672                    for PrtScn key ... GA */
673
674 static const WORD nonchar_key_vkey[256] =
675 {
676     /* unused */
677     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF00 */
678     /* special keys */
679     VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
680     0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
681     0, 0, 0, VK_ESCAPE, 0, 0, 0, 0,                             /* FF18 */
682     /* unused */
683     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF20 */
684     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF28 */
685     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF30 */
686     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF38 */
687     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF40 */
688     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF48 */
689     /* cursor keys */
690     VK_HOME, VK_LEFT, VK_UP, VK_RIGHT,                          /* FF50 */
691     VK_DOWN, VK_PRIOR, VK_NEXT, VK_END,
692     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF58 */
693     /* misc keys */
694     VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
695     VK_CANCEL, VK_HELP, VK_CANCEL, VK_CANCEL, 0, 0, 0, 0,       /* FF68 */
696     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF70 */
697     /* keypad keys */
698     0, 0, 0, 0, 0, 0, 0, VK_NUMLOCK,                            /* FF78 */
699     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
700     0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
701     0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP,                     /* FF90 */
702     VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT,                       /* FF98 */
703     VK_END, 0, VK_INSERT, VK_DELETE,
704     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
705     0, 0, VK_MULTIPLY, VK_ADD,                                  /* FFA8 */
706     VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE,
707     VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,             /* FFB0 */
708     VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
709     VK_NUMPAD8, VK_NUMPAD9, 0, 0, 0, 0,                         /* FFB8 */
710     /* function keys */
711     VK_F1, VK_F2,
712     VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
713     VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, 0, 0,       /* FFC8 */
714     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFD0 */
715     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFD8 */
716     /* modifier keys */
717     0, VK_SHIFT, VK_SHIFT, VK_CONTROL,                          /* FFE0 */
718     VK_CONTROL, VK_CAPITAL, 0, VK_MENU,
719     VK_MENU, VK_MENU, VK_MENU, 0, 0, 0, 0, 0,                   /* FFE8 */
720     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFF0 */
721     0, 0, 0, 0, 0, 0, 0, VK_DELETE                              /* FFF8 */
722 };
723
724 static const WORD nonchar_key_scan[256] =
725 {
726     /* unused */
727     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF00 */
728     /* special keys */
729     0x0E, 0x0F, 0x00, /*?*/ 0, 0x00, 0x1C, 0x00, 0x00,           /* FF08 */
730     0x00, 0x00, 0x00, 0x45, 0x46, 0x00, 0x00, 0x00,              /* FF10 */
731     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,              /* FF18 */
732     /* unused */
733     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF20 */
734     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF28 */
735     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF30 */
736     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF38 */
737     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF40 */
738     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF48 */
739     /* cursor keys */
740     0x147, 0x14B, 0x148, 0x14D, 0x150, 0x149, 0x151, 0x14F,      /* FF50 */
741     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF58 */
742     /* misc keys */
743     /*?*/ 0, 0x137, /*?*/ 0, 0x152, 0x00, 0x00, 0x00, 0x00,      /* FF60 */
744     /*?*/ 0, /*?*/ 0, 0x38, 0x146, 0x00, 0x00, 0x00, 0x00,       /* FF68 */
745     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF70 */
746     /* keypad keys */
747     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x138, 0x145,            /* FF78 */
748     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF80 */
749     0x00, 0x00, 0x00, 0x00, 0x00, 0x11C, 0x00, 0x00,             /* FF88 */
750     0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4B, 0x48,              /* FF90 */
751     0x4D, 0x50, 0x49, 0x51, 0x4F, 0x4C, 0x52, 0x53,              /* FF98 */
752     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFA0 */
753     0x00, 0x00, 0x37, 0x4E, /*?*/ 0, 0x4A, 0x53, 0x135,          /* FFA8 */
754     0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47,              /* FFB0 */
755     0x48, 0x49, 0x00, 0x00, 0x00, 0x00,                          /* FFB8 */
756     /* function keys */
757     0x3B, 0x3C,
758     0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44,              /* FFC0 */
759     0x57, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFC8 */
760     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFD0 */
761     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFD8 */
762     /* modifier keys */
763     0x00, 0x2A, 0x36, 0x1D, 0x11D, 0x3A, 0x00, 0x38,             /* FFE0 */
764     0x138, 0x38, 0x138, 0x00, 0x00, 0x00, 0x00, 0x00,            /* FFE8 */
765     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFF0 */
766     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x153              /* FFF8 */
767 };
768
769
770 /* Returns the Windows virtual key code associated with the X event <e> */
771 static WORD EVENT_event_to_vkey( XKeyEvent *e)
772 {
773     KeySym keysym;
774
775     TSXLookupString(e, NULL, 0, &keysym, NULL);
776
777     if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (keysym != 0xFFAF)
778         && (e->state & NumLockMask))
779         /* Only the Keypad keys 0-9 and . send different keysyms
780          * depending on the NumLock state */
781         return nonchar_key_vkey[keysym & 0xFF];
782
783     return keyc2vkey[e->keycode];
784 }
785
786 static BOOL NumState=FALSE, CapsState=FALSE;
787
788
789 /***********************************************************************
790  *           send_keyboard_input
791  */
792 static void send_keyboard_input( WORD wVk, WORD wScan, DWORD dwFlags, DWORD time )
793 {
794     INPUT input;
795
796     input.type             = WINE_INTERNAL_INPUT_KEYBOARD;
797     input.u.ki.wVk         = wVk;
798     input.u.ki.wScan       = wScan;
799     input.u.ki.dwFlags     = dwFlags;
800     input.u.ki.time        = time;
801     input.u.ki.dwExtraInfo = 0;
802     SendInput( 1, &input, sizeof(input) );
803 }
804
805
806 /**********************************************************************
807  *              KEYBOARD_GenerateMsg
808  *
809  * Generate Down+Up messages when NumLock or CapsLock is pressed.
810  *
811  * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
812  *
813  */
814 static void KEYBOARD_GenerateMsg( WORD vkey, WORD scan, int Evtype, DWORD event_time )
815 {
816   BOOL * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
817   DWORD up, down;
818
819   if (*State) {
820     /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
821        don't treat it. It's from the same key press. Then the state goes to ON.
822        And from there, a 'release' event will switch off the toggle key. */
823     *State=FALSE;
824     TRACE("INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,pKeyStateTable[vkey]);
825   } else
826     {
827         down = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0);
828         up = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0) | KEYEVENTF_KEYUP;
829         if ( pKeyStateTable[vkey] & 0x1 ) /* it was ON */
830           {
831             if (Evtype!=KeyPress)
832               {
833                 TRACE("ON + KeyRelease => generating DOWN and UP messages.\n");
834                 send_keyboard_input( vkey, scan, down, event_time );
835                 send_keyboard_input( vkey, scan, up, event_time );
836                 *State=FALSE;
837                 pKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */
838               }
839           }
840         else /* it was OFF */
841           if (Evtype==KeyPress)
842             {
843               TRACE("OFF + Keypress => generating DOWN and UP messages.\n");
844               send_keyboard_input( vkey, scan, down, event_time );
845               send_keyboard_input( vkey, scan, up, event_time );
846               *State=TRUE; /* Goes to intermediary state before going to ON */
847               pKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
848             }
849     }
850 }
851
852 /***********************************************************************
853  *           KEYBOARD_UpdateOneState
854  *
855  * Updates internal state for <vkey>, depending on key <state> under X
856  *
857  */
858 inline static void KEYBOARD_UpdateOneState ( int vkey, int state, DWORD time )
859 {
860     /* Do something if internal table state != X state for keycode */
861     if (((pKeyStateTable[vkey] & 0x80)!=0) != state)
862     {
863         TRACE("Adjusting state for vkey %#.2x. State before %#.2x \n",
864               vkey, pKeyStateTable[vkey]);
865
866         /* Fake key being pressed inside wine */
867         send_keyboard_input( vkey, 0, state? 0 : KEYEVENTF_KEYUP, time );
868
869         TRACE("State after %#.2x \n",pKeyStateTable[vkey]);
870     }
871 }
872
873 /***********************************************************************
874  *           X11DRV_KeymapNotify
875  *
876  * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
877  *
878  * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
879  * from wine to another application and back.
880  * Toggle keys are handled in HandleEvent.
881  */
882 void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event )
883 {
884     int i, j, alt, control, shift;
885     DWORD time = GetCurrentTime();
886
887     alt = control = shift = 0;
888     for (i = 0; i < 32; i++)
889     {
890         if (!event->key_vector[i]) continue;
891         for (j = 0; j < 8; j++)
892         {
893             if (!(event->key_vector[i] & (1<<j))) continue;
894             switch(keyc2vkey[(i * 8) + j] & 0xff)
895             {
896             case VK_MENU:    alt = 1; break;
897             case VK_CONTROL: control = 1; break;
898             case VK_SHIFT:   shift = 1; break;
899             }
900         }
901     }
902     KEYBOARD_UpdateOneState( VK_MENU, alt, time );
903     KEYBOARD_UpdateOneState( VK_CONTROL, control, time );
904     KEYBOARD_UpdateOneState( VK_SHIFT, shift, time );
905 }
906
907 /***********************************************************************
908  *           X11DRV_KeyEvent
909  *
910  * Handle a X key event
911  */
912 void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event )
913 {
914     char Str[24];
915     KeySym keysym;
916     WORD vkey = 0, bScan;
917     DWORD dwFlags;
918     int ascii_chars;
919
920     DWORD event_time = event->time - X11DRV_server_startticks;
921
922     /* this allows support for dead keys */
923     if ((event->keycode >> 8) == 0x10)
924         event->keycode=(event->keycode & 0xff);
925
926     ascii_chars = TSXLookupString(event, Str, sizeof(Str), &keysym, NULL);
927
928     /* Ignore some unwanted events */
929     if (keysym == XK_ISO_Prev_Group ||
930         keysym == XK_ISO_Next_Group ||
931         keysym == XK_Mode_switch)
932     {
933         TRACE("Ignoring %s keyboard event\n", TSXKeysymToString(keysym));
934         return;
935     }
936
937     TRACE_(key)("state = %X\n", event->state);
938
939     /* If XKB extensions is used, the state mask for AltGr will used the group
940        index instead of the modifier mask. The group index is set in bits
941        13-14 of the state field in the XKeyEvent structure. So if AltGr is
942        pressed, look if the group index is diferent than 0. From XKB
943        extension documentation, the group index should for AltGr should
944        be 2 (event->state = 0x2000). It's probably better to not assume a
945        predefined group index and find it dynamically
946
947        Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
948     AltGrMask = event->state & 0x6000;
949
950     Str[ascii_chars] = '\0';
951     if (TRACE_ON(key)){
952         char    *ksname;
953
954         ksname = TSXKeysymToString(keysym);
955         if (!ksname)
956           ksname = "No Name";
957         TRACE_(key)("%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
958                     (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
959                     keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
960     }
961
962     vkey = EVENT_event_to_vkey(event);
963
964     TRACE_(key)("keycode 0x%x converted to vkey 0x%x\n",
965                 event->keycode, vkey);
966
967    if (vkey)
968    {
969     switch (vkey & 0xff)
970     {
971     case VK_NUMLOCK:
972       KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, event->type, event_time );
973       break;
974     case VK_CAPITAL:
975       TRACE("Caps Lock event. (type %d). State before : %#.2x\n",event->type,pKeyStateTable[vkey]);
976       KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, event->type, event_time );
977       TRACE("State after : %#.2x\n",pKeyStateTable[vkey]);
978       break;
979     default:
980         /* Adjust the NUMLOCK state if it has been changed outside wine */
981         if (!(pKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
982           {
983             TRACE("Adjusting NumLock state. \n");
984             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyPress, event_time );
985             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyRelease, event_time );
986           }
987         /* Adjust the CAPSLOCK state if it has been changed outside wine */
988         if (!(pKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
989           {
990               TRACE("Adjusting Caps Lock state.\n");
991             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyPress, event_time );
992             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyRelease, event_time );
993           }
994         /* Not Num nor Caps : end of intermediary states for both. */
995         NumState = FALSE;
996         CapsState = FALSE;
997
998         bScan = keyc2scan[event->keycode] & 0xFF;
999         TRACE_(key)("bScan = 0x%02x.\n", bScan);
1000
1001         dwFlags = 0;
1002         if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
1003         if ( vkey & 0x100 )              dwFlags |= KEYEVENTF_EXTENDEDKEY;
1004
1005         send_keyboard_input( vkey & 0xff, bScan, dwFlags, event_time );
1006     }
1007    }
1008 }
1009
1010 /**********************************************************************
1011  *              X11DRV_KEYBOARD_DetectLayout
1012  *
1013  * Called from X11DRV_InitKeyboard
1014  *  This routine walks through the defined keyboard layouts and selects
1015  *  whichever matches most closely.
1016  */
1017 static void
1018 X11DRV_KEYBOARD_DetectLayout (void)
1019 {
1020   Display *display = thread_display();
1021   unsigned current, match, mismatch, seq;
1022   int score, keyc, i, key, pkey, ok, syms;
1023   KeySym keysym;
1024   const char (*lkey)[MAIN_LEN][4];
1025   unsigned max_seq = 0;
1026   int max_score = 0, ismatch = 0;
1027   char ckey[4] =
1028   {0, 0, 0, 0};
1029
1030   syms = keysyms_per_keycode;
1031   if (syms > 4) {
1032     WARN("%d keysyms per keycode not supported, set to 4\n", syms);
1033     syms = 4;
1034   }
1035   for (current = 0; main_key_tab[current].comment; current++) {
1036     TRACE("Attempting to match against \"%s\"\n", main_key_tab[current].comment);
1037     match = 0;
1038     mismatch = 0;
1039     score = 0;
1040     seq = 0;
1041     lkey = main_key_tab[current].key;
1042     pkey = -1;
1043     for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1044       /* get data for keycode from X server */
1045       for (i = 0; i < syms; i++) {
1046         keysym = TSXKeycodeToKeysym (display, keyc, i);
1047         /* Allow both one-byte and two-byte national keysyms */
1048         if ((keysym < 0x8000) && (keysym != ' '))
1049           ckey[i] = keysym & 0xFF;
1050         else {
1051           ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1052         }
1053       }
1054       if (ckey[0]) {
1055         /* search for a match in layout table */
1056         /* right now, we just find an absolute match for defined positions */
1057         /* (undefined positions are ignored, so if it's defined as "3#" in */
1058         /* the table, it's okay that the X server has "3#£", for example) */
1059         /* however, the score will be higher for longer matches */
1060         for (key = 0; key < MAIN_LEN; key++) {
1061           for (ok = 0, i = 0; (ok >= 0) && (i < syms); i++) {
1062             if ((*lkey)[key][i] && ((*lkey)[key][i] == ckey[i]))
1063               ok++;
1064             if ((*lkey)[key][i] && ((*lkey)[key][i] != ckey[i]))
1065               ok = -1;
1066           }
1067           if (ok > 0) {
1068             score += ok;
1069             break;
1070           }
1071         }
1072         /* count the matches and mismatches */
1073         if (ok > 0) {
1074           match++;
1075           /* and how much the keycode order matches */
1076           if (key > pkey) seq++;
1077           pkey = key;
1078         } else {
1079           TRACE_(key)("mismatch for keycode %d, character %c\n", keyc,
1080                  ckey[0]);
1081           mismatch++;
1082           score -= syms;
1083         }
1084       }
1085     }
1086     TRACE("matches=%d, mismatches=%d, seq=%d, score=%d\n",
1087            match, mismatch, seq, score);
1088     if ((score > max_score) ||
1089         ((score == max_score) && (seq > max_seq))) {
1090       /* best match so far */
1091       kbd_layout = current;
1092       max_score = score;
1093       max_seq = seq;
1094       ismatch = !mismatch;
1095     }
1096   }
1097   /* we're done, report results if necessary */
1098   if (!ismatch) {
1099     FIXME(
1100            "Your keyboard layout was not found!\n"
1101            "Using closest match instead (%s) for scancode mapping.\n"
1102            "Please define your layout in windows/x11drv/keyboard.c and submit them\n"
1103            "to us for inclusion into future Wine releases.\n"
1104            "See the Wine User Guide, chapter \"Keyboard\" for more information.\n",
1105            main_key_tab[kbd_layout].comment);
1106   }
1107
1108   TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment);
1109 }
1110
1111 /**********************************************************************
1112  *              InitKeyboard (X11DRV.@)
1113  */
1114 void X11DRV_InitKeyboard( BYTE *key_state_table )
1115 {
1116 #ifdef HAVE_XKB
1117     int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion;
1118 #endif
1119     Display *display = thread_display();
1120     KeySym *ksp;
1121     XModifierKeymap *mmp;
1122     KeySym keysym;
1123     KeyCode *kcp;
1124     XKeyEvent e2;
1125     WORD scan, vkey, OEMvkey;
1126     int keyc, i, keyn, syms;
1127     char ckey[4]={0,0,0,0};
1128     const char (*lkey)[MAIN_LEN][4];
1129
1130     pKeyStateTable = key_state_table;
1131
1132 #ifdef HAVE_XKB
1133     wine_tsx11_lock();
1134     is_xkb = XkbQueryExtension(display,
1135                                &xkb_opcode, &xkb_event, &xkb_error,
1136                                &xkb_major, &xkb_minor);
1137     if (is_xkb) {
1138         /* we have XKB, approximate Windows behaviour */
1139         XkbSetDetectableAutoRepeat(display, True, NULL);
1140     }
1141     wine_tsx11_unlock();
1142 #endif
1143     TSXDisplayKeycodes(display, &min_keycode, &max_keycode);
1144     ksp = TSXGetKeyboardMapping(display, min_keycode,
1145                               max_keycode + 1 - min_keycode, &keysyms_per_keycode);
1146     /* We are only interested in keysyms_per_keycode.
1147        There is no need to hold a local copy of the keysyms table */
1148     TSXFree(ksp);
1149     mmp = TSXGetModifierMapping(display);
1150     kcp = mmp->modifiermap;
1151     for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
1152     {
1153         int j;
1154
1155         for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
1156             if (*kcp)
1157             {
1158                 int k;
1159
1160                 for (k = 0; k < keysyms_per_keycode; k += 1)
1161                     if (TSXKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
1162                     {
1163                         NumLockMask = 1 << i;
1164                         TRACE_(key)("NumLockMask is %x\n", NumLockMask);
1165                     }
1166             }
1167     }
1168     TSXFreeModifiermap(mmp);
1169
1170     /* Detect the keyboard layout */
1171     X11DRV_KEYBOARD_DetectLayout();
1172     lkey = main_key_tab[kbd_layout].key;
1173     syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode;
1174
1175     /* Now build two conversion arrays :
1176      * keycode -> vkey + scancode + extended
1177      * vkey + extended -> keycode */
1178
1179     e2.display = display;
1180     e2.state = 0;
1181
1182     OEMvkey = VK_OEM_7; /* next is available.  */
1183     for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1184     {
1185         e2.keycode = (KeyCode)keyc;
1186         TSXLookupString(&e2, NULL, 0, &keysym, NULL);
1187         vkey = 0; scan = 0;
1188         if (keysym)  /* otherwise, keycode not used */
1189         {
1190             if ((keysym >> 8) == 0xFF)         /* non-character key */
1191             {
1192                 vkey = nonchar_key_vkey[keysym & 0xff];
1193                 scan = nonchar_key_scan[keysym & 0xff];
1194                 /* set extended bit when necessary */
1195                 if (scan & 0x100) vkey |= 0x100;
1196             } else if (keysym == 0x20) {                 /* Spacebar */
1197                 vkey = VK_SPACE;
1198                 scan = 0x39;
1199             } else {
1200               /* we seem to need to search the layout-dependent scancodes */
1201               int maxlen=0,maxval=-1,ok;
1202               for (i=0; i<syms; i++) {
1203                 keysym = TSXKeycodeToKeysym(display, keyc, i);
1204                 if ((keysym<0x800) && (keysym!=' ')) {
1205                   ckey[i] = keysym & 0xFF;
1206                 } else {
1207                   ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1208                 }
1209               }
1210               /* find key with longest match streak */
1211               for (keyn=0; keyn<MAIN_LEN; keyn++) {
1212                 for (ok=(*lkey)[keyn][i=0]; ok&&(i<4); i++)
1213                   if ((*lkey)[keyn][i] && (*lkey)[keyn][i]!=ckey[i]) ok=0;
1214                 if (ok||(i>maxlen)) {
1215                   maxlen=i; maxval=keyn;
1216                 }
1217                 if (ok) break;
1218               }
1219               if (maxval>=0) {
1220                 /* got it */
1221                 const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan;
1222                 const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey;
1223                 scan = (*lscan)[maxval];
1224                 vkey = (*lvkey)[maxval];
1225               }
1226             }
1227
1228             /* find a suitable layout-dependent VK code */
1229             /* (most Winelib apps ought to be able to work without layout tables!) */
1230             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1231             {
1232                 keysym = TSXLookupKeysym(&e2, i);
1233                 if ((keysym >= VK_0 && keysym <= VK_9)
1234                     || (keysym >= VK_A && keysym <= VK_Z)) {
1235                     vkey = keysym;
1236                 }
1237             }
1238
1239             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1240             {
1241                 keysym = TSXLookupKeysym(&e2, i);
1242                 switch (keysym)
1243                 {
1244                 case ';':             vkey = VK_OEM_1; break;
1245                 case '/':             vkey = VK_OEM_2; break;
1246                 case '`':             vkey = VK_OEM_3; break;
1247                 case '[':             vkey = VK_OEM_4; break;
1248                 case '\\':            vkey = VK_OEM_5; break;
1249                 case ']':             vkey = VK_OEM_6; break;
1250                 case '\'':            vkey = VK_OEM_7; break;
1251                 case ',':             vkey = VK_OEM_COMMA; break;
1252                 case '.':             vkey = VK_OEM_PERIOD; break;
1253                 case '-':             vkey = VK_OEM_MINUS; break;
1254                 case '+':             vkey = VK_OEM_PLUS; break;
1255                 }
1256             }
1257
1258             if (!vkey)
1259             {
1260                 /* Others keys: let's assign OEM virtual key codes in the allowed range,
1261                  * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
1262                 switch (++OEMvkey)
1263                 {
1264                 case 0xc1 : OEMvkey=0xdb; break;
1265                 case 0xe5 : OEMvkey=0xe9; break;
1266                 case 0xf6 : OEMvkey=0xf5; WARN("No more OEM vkey available!\n");
1267                 }
1268
1269                 vkey = OEMvkey;
1270
1271                 if (TRACE_ON(keyboard))
1272                 {
1273                     TRACE("OEM specific virtual key %X assigned to keycode %X:\n",
1274                                      OEMvkey, e2.keycode);
1275                     TRACE("(");
1276                     for (i = 0; i < keysyms_per_keycode; i += 1)
1277                     {
1278                         char    *ksname;
1279
1280                         keysym = TSXLookupKeysym(&e2, i);
1281                         ksname = TSXKeysymToString(keysym);
1282                         if (!ksname)
1283                             ksname = "NoSymbol";
1284                         DPRINTF( "%lX (%s) ", keysym, ksname);
1285                     }
1286                     DPRINTF(")\n");
1287                 }
1288             }
1289         }
1290         keyc2vkey[e2.keycode] = vkey;
1291         keyc2scan[e2.keycode] = scan;
1292     } /* for */
1293
1294     /* If some keys still lack scancodes, assign some arbitrary ones to them now */
1295     for (scan = 0x60, keyc = min_keycode; keyc <= max_keycode; keyc++)
1296       if (keyc2vkey[keyc]&&!keyc2scan[keyc]) {
1297         char *ksname;
1298         keysym = TSXKeycodeToKeysym(display, keyc, 0);
1299         ksname = TSXKeysymToString(keysym);
1300         if (!ksname) ksname = "NoSymbol";
1301
1302         /* should make sure the scancode is unassigned here, but >=0x60 currently always is */
1303
1304         TRACE_(key)("assigning scancode %02x to unidentified keycode %02x (%s)\n",scan,keyc,ksname);
1305         keyc2scan[keyc]=scan++;
1306       }
1307
1308     /* Now store one keycode for each modifier. Used to simulate keypresses. */
1309     kcControl = TSXKeysymToKeycode(display, XK_Control_L);
1310     kcAlt = TSXKeysymToKeycode(display, XK_Alt_L);
1311     if (!kcAlt) kcAlt = TSXKeysymToKeycode(display, XK_Meta_L);
1312     kcShift = TSXKeysymToKeycode(display, XK_Shift_L);
1313     kcNumLock = TSXKeysymToKeycode(display, XK_Num_Lock);
1314     kcCapsLock = TSXKeysymToKeycode(display, XK_Caps_Lock);
1315 }
1316
1317
1318 /***********************************************************************
1319  *           X11DRV_MappingNotify
1320  */
1321 void X11DRV_MappingNotify( XMappingEvent *event )
1322 {
1323     TSXRefreshKeyboardMapping(event);
1324     X11DRV_InitKeyboard( pKeyStateTable );
1325 }
1326
1327
1328 /***********************************************************************
1329  *              VkKeyScan (X11DRV.@)
1330  */
1331 WORD X11DRV_VkKeyScan(CHAR cChar)
1332 {
1333         Display *display = thread_display();
1334         KeyCode keycode;
1335         KeySym keysym;
1336         int i,index;
1337         int highbyte=0;
1338
1339         /* char->keysym (same for ANSI chars) */
1340         keysym=(unsigned char) cChar;/* (!) cChar is signed */
1341         if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
1342
1343         keycode = TSXKeysymToKeycode(display, keysym);  /* keysym -> keycode */
1344         if (!keycode)
1345         { /* It didn't work ... let's try with deadchar code. */
1346           keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
1347         }
1348
1349         TRACE("VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
1350               cChar,keysym,keysym,keycode);
1351
1352         if (keycode)
1353           {
1354             for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
1355               if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i;
1356             switch (index) {
1357             case -1 :
1358               WARN("Keysym %lx not found while parsing the keycode table\n",keysym); break;
1359             case 0 : break;
1360             case 1 : highbyte = 0x0100; break;
1361             case 2 : highbyte = 0x0600; break;
1362             case 3 : highbyte = 0x0700; break;
1363             default : ERR("index %d found by XKeycodeToKeysym. please report! \n",index);
1364             }
1365             /*
1366               index : 0     adds 0x0000
1367               index : 1     adds 0x0100 (shift)
1368               index : ?     adds 0x0200 (ctrl)
1369               index : 2     adds 0x0600 (ctrl+alt)
1370               index : 3     adds 0x0700 (ctrl+alt+shift)
1371              */
1372           }
1373         TRACE(" ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
1374         return keyc2vkey[keycode]+highbyte;   /* keycode -> (keyc2vkey) vkey */
1375 }
1376
1377 /***********************************************************************
1378  *              MapVirtualKey (X11DRV.@)
1379  */
1380 UINT X11DRV_MapVirtualKey(UINT wCode, UINT wMapType)
1381 {
1382     Display *display = thread_display();
1383
1384 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
1385
1386         TRACE("MapVirtualKey wCode=0x%x wMapType=%d ... \n", wCode,wMapType);
1387         switch(wMapType) {
1388                 case 0: { /* vkey-code to scan-code */
1389                         /* let's do vkey -> keycode -> scan */
1390                         int keyc;
1391                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1392                                 if ((keyc2vkey[keyc] & 0xFF) == wCode)
1393                                         returnMVK (keyc2scan[keyc] & 0xFF);
1394                         TRACE("returning no scan-code.\n");
1395                         return 0; }
1396
1397                 case 1: { /* scan-code to vkey-code */
1398                         /* let's do scan -> keycode -> vkey */
1399                         int keyc;
1400                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1401                                 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
1402                                         returnMVK (keyc2vkey[keyc] & 0xFF);
1403                         TRACE("returning no vkey-code.\n");
1404                         return 0; }
1405
1406                 case 2: { /* vkey-code to unshifted ANSI code */
1407                         /* we still don't know what "unshifted" means. in windows VK_W (0x57)
1408                          * returns 0x57, which is upercase 'W'. So we have to return the uppercase
1409                          * key.. Looks like something is wrong with the MS docs?
1410                          * This is only true for letters, for example VK_0 returns '0' not ')'.
1411                          * - hence we use the lock mask to ensure this happens.
1412                          */
1413                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
1414                         XKeyEvent e;
1415                         KeySym keysym;
1416                         int keyc;
1417                         char s[2];
1418                         e.display = display;
1419
1420                         e.state = LockMask;
1421                         /* LockMask should behave exactly like caps lock - upercase
1422                          * the letter keys and thats about it. */
1423
1424                         e.keycode = 0;
1425                         /* We exit on the first keycode found, to speed up the thing. */
1426                         for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
1427                         { /* Find a keycode that could have generated this virtual key */
1428                             if  ((keyc2vkey[keyc] & 0xFF) == wCode)
1429                             { /* We filter the extended bit, we don't know it */
1430                                 e.keycode = keyc; /* Store it temporarily */
1431                                 if ((EVENT_event_to_vkey(&e) & 0xFF) != wCode) {
1432                                     e.keycode = 0; /* Wrong one (ex: because of the NumLock
1433                                          state), so set it to 0, we'll find another one */
1434                                 }
1435                             }
1436                         }
1437
1438                         if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
1439                           e.keycode = TSXKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
1440
1441                         if (wCode==VK_DECIMAL)
1442                           e.keycode = TSXKeysymToKeycode(e.display, XK_KP_Decimal);
1443
1444                         if (!e.keycode)
1445                         {
1446                           WARN("Unknown virtual key %X !!! \n", wCode);
1447                           return 0; /* whatever */
1448                         }
1449                         TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
1450
1451                         if (TSXLookupString(&e, s, 2, &keysym, NULL))
1452                           returnMVK (*s);
1453
1454                         TRACE("returning no ANSI.\n");
1455                         return 0;
1456                         }
1457
1458                 case 3:   /* **NT only** scan-code to vkey-code but distinguish between  */
1459                           /*             left and right  */
1460                           FIXME(" stub for NT\n");
1461                           return 0;
1462
1463                 default: /* reserved */
1464                         WARN("Unknown wMapType %d !\n", wMapType);
1465                         return 0;
1466         }
1467         return 0;
1468 }
1469
1470 /***********************************************************************
1471  *              GetKeyNameText (X11DRV.@)
1472  */
1473 INT X11DRV_GetKeyNameText(LONG lParam, LPSTR lpBuffer, INT nSize)
1474 {
1475   int vkey, ansi, scanCode;
1476   KeyCode keyc;
1477   int keyi;
1478   KeySym keys;
1479   char *name;
1480
1481   scanCode = lParam >> 16;
1482   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
1483
1484   /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
1485   vkey = X11DRV_MapVirtualKey(scanCode, 1);
1486
1487   /*  handle "don't care" bit (0x02000000) */
1488   if (!(lParam & 0x02000000)) {
1489     switch (vkey) {
1490          case VK_LSHIFT:
1491          case VK_RSHIFT:
1492                           vkey = VK_SHIFT;
1493                           break;
1494        case VK_LCONTROL:
1495        case VK_RCONTROL:
1496                           vkey = VK_CONTROL;
1497                           break;
1498           case VK_LMENU:
1499           case VK_RMENU:
1500                           vkey = VK_MENU;
1501                           break;
1502                default:
1503                           break;
1504     }
1505   }
1506
1507   ansi = X11DRV_MapVirtualKey(vkey, 2);
1508   TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
1509
1510   /* first get the name of the "regular" keys which is the Upper case
1511      value of the keycap imprint.                                     */
1512   if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
1513        (scanCode != 0x137) &&   /* PrtScn   */
1514        (scanCode != 0x135) &&   /* numpad / */
1515        (scanCode != 0x37 ) &&   /* numpad * */
1516        (scanCode != 0x4a ) &&   /* numpad - */
1517        (scanCode != 0x4e ) )    /* numpad + */
1518       {
1519         if ((nSize >= 2) && lpBuffer)
1520         {
1521         *lpBuffer = toupper((char)ansi);
1522           *(lpBuffer+1) = 0;
1523           return 1;
1524         }
1525      else
1526         return 0;
1527   }
1528
1529   /* FIXME: horrible hack to fix function keys. Windows reports scancode
1530             without "extended-key" flag. However Wine generates scancode
1531             *with* "extended-key" flag. Seems to occur *only* for the
1532             function keys. Soooo.. We will leave the table alone and
1533             fudge the lookup here till the other part is found and fixed!!! */
1534
1535   if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
1536        (scanCode == 0x157) || (scanCode == 0x158))
1537     scanCode &= 0xff;   /* remove "extended-key" flag for Fx keys */
1538
1539   /* let's do scancode -> keycode -> keysym -> String */
1540
1541   for (keyi=min_keycode; keyi<=max_keycode; keyi++)
1542       if ((keyc2scan[keyi]) == scanCode)
1543          break;
1544   if (keyi <= max_keycode)
1545   {
1546       keyc = (KeyCode) keyi;
1547       keys = TSXKeycodeToKeysym(thread_display(), keyc, 0);
1548       name = TSXKeysymToString(keys);
1549       TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
1550             scanCode, keyc, (int)keys, name);
1551       if (lpBuffer && nSize && name)
1552       {
1553           lstrcpynA(lpBuffer, name, nSize);
1554           return 1;
1555       }
1556   }
1557
1558   /* Finally issue FIXME for unknown keys   */
1559
1560   FIXME("(%08lx,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
1561   if (lpBuffer && nSize)
1562     *lpBuffer = 0;
1563   return 0;
1564 }
1565
1566 /***********************************************************************
1567  *              X11DRV_KEYBOARD_MapDeadKeysym
1568  */
1569 static char KEYBOARD_MapDeadKeysym(KeySym keysym)
1570 {
1571         switch (keysym)
1572             {
1573         /* symbolic ASCII is the same as defined in rfc1345 */
1574 #ifdef XK_dead_tilde
1575             case XK_dead_tilde :
1576 #endif
1577             case 0x1000FE7E : /* Xfree's XK_Dtilde */
1578                 return '~';     /* '? */
1579 #ifdef XK_dead_acute
1580             case XK_dead_acute :
1581 #endif
1582             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1583                 return 0xb4;    /* '' */
1584 #ifdef XK_dead_circumflex
1585             case XK_dead_circumflex:
1586 #endif
1587             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1588                 return '^';     /* '> */
1589 #ifdef XK_dead_grave
1590             case XK_dead_grave :
1591 #endif
1592             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1593                 return '`';     /* '! */
1594 #ifdef XK_dead_diaeresis
1595             case XK_dead_diaeresis :
1596 #endif
1597             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1598                 return 0xa8;    /* ': */
1599 #ifdef XK_dead_cedilla
1600             case XK_dead_cedilla :
1601                 return 0xb8;    /* ', */
1602 #endif
1603 #ifdef XK_dead_macron
1604             case XK_dead_macron :
1605                 return '-';     /* 'm isn't defined on iso-8859-x */
1606 #endif
1607 #ifdef XK_dead_breve
1608             case XK_dead_breve :
1609                 return 0xa2;    /* '( */
1610 #endif
1611 #ifdef XK_dead_abovedot
1612             case XK_dead_abovedot :
1613                 return 0xff;    /* '. */
1614 #endif
1615 #ifdef XK_dead_abovering
1616             case XK_dead_abovering :
1617                 return '0';     /* '0 isn't defined on iso-8859-x */
1618 #endif
1619 #ifdef XK_dead_doubleacute
1620             case XK_dead_doubleacute :
1621                 return 0xbd;    /* '" */
1622 #endif
1623 #ifdef XK_dead_caron
1624             case XK_dead_caron :
1625                 return 0xb7;    /* '< */
1626 #endif
1627 #ifdef XK_dead_ogonek
1628             case XK_dead_ogonek :
1629                 return 0xb2;    /* '; */
1630 #endif
1631 /* FIXME: I don't know this three.
1632             case XK_dead_iota :
1633                 return 'i';
1634             case XK_dead_voiced_sound :
1635                 return 'v';
1636             case XK_dead_semivoiced_sound :
1637                 return 's';
1638 */
1639             }
1640         TRACE("no character for dead keysym 0x%08lx\n",keysym);
1641         return 0;
1642 }
1643
1644 /***********************************************************************
1645  *              ToUnicode (X11DRV.@)
1646  *
1647  * The ToUnicode function translates the specified virtual-key code and keyboard
1648  * state to the corresponding Windows character or characters.
1649  *
1650  * If the specified key is a dead key, the return value is negative. Otherwise,
1651  * it is one of the following values:
1652  * Value        Meaning
1653  * 0    The specified virtual key has no translation for the current state of the keyboard.
1654  * 1    One Windows character was copied to the buffer.
1655  * 2    Two characters were copied to the buffer. This usually happens when a
1656  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
1657  *      be composed with the specified virtual key to form a single character.
1658  *
1659  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
1660  *
1661  */
1662 INT X11DRV_ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
1663                      LPWSTR bufW, int bufW_size, UINT flags)
1664 {
1665     Display *display = thread_display();
1666     XKeyEvent e;
1667     KeySym keysym;
1668     INT ret;
1669     int keyc;
1670     BYTE lpChar[2];
1671
1672     if (scanCode & 0x8000)
1673     {
1674         TRACE("Key UP, doing nothing\n" );
1675         return 0;
1676     }
1677     e.display = display;
1678     e.keycode = 0;
1679     e.state = 0;
1680     if (lpKeyState[VK_SHIFT] & 0x80)
1681     {
1682         TRACE("ShiftMask = %04x\n", ShiftMask);
1683         e.state |= ShiftMask;
1684     }
1685     if (lpKeyState[VK_CAPITAL] & 0x01)
1686     {
1687         TRACE("LockMask = %04x\n", LockMask);
1688         e.state |= LockMask;
1689     }
1690     if (lpKeyState[VK_CONTROL] & 0x80)
1691     {
1692         TRACE("ControlMask = %04x\n", ControlMask);
1693         e.state |= ControlMask;
1694     }
1695     if (lpKeyState[VK_NUMLOCK] & 0x01)
1696     {
1697         TRACE("NumLockMask = %04x\n", NumLockMask);
1698         e.state |= NumLockMask;
1699     }
1700
1701     /* Restore saved AltGr state */
1702     TRACE("AltGrMask = %04x\n", AltGrMask);
1703     e.state |= AltGrMask;
1704
1705     TRACE_(key)("(%04X, %04X) : faked state = %X\n",
1706                 virtKey, scanCode, e.state);
1707     /* We exit on the first keycode found, to speed up the thing. */
1708     for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
1709       { /* Find a keycode that could have generated this virtual key */
1710           if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
1711           { /* We filter the extended bit, we don't know it */
1712               e.keycode = keyc; /* Store it temporarily */
1713               if ((EVENT_event_to_vkey(&e) & 0xFF) != virtKey) {
1714                   e.keycode = 0; /* Wrong one (ex: because of the NumLock
1715                          state), so set it to 0, we'll find another one */
1716               }
1717           }
1718       }
1719
1720     if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1721         e.keycode = TSXKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1722
1723     if (virtKey==VK_DECIMAL)
1724         e.keycode = TSXKeysymToKeycode(e.display, XK_KP_Decimal);
1725
1726     if (!e.keycode)
1727       {
1728         WARN("Unknown virtual key %X !!! \n",virtKey);
1729         return virtKey; /* whatever */
1730       }
1731     else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
1732
1733     ret = TSXLookupString(&e, (LPVOID)lpChar, 2, &keysym, NULL);
1734     if (ret == 0)
1735         {
1736         BYTE dead_char;
1737
1738         dead_char = KEYBOARD_MapDeadKeysym(keysym);
1739         if (dead_char)
1740             {
1741             MultiByteToWideChar(main_key_tab[kbd_layout].layout_cp, 0, &dead_char, 1, bufW, bufW_size);
1742             ret = -1;
1743             }
1744         else
1745             {
1746             char        *ksname;
1747
1748             ksname = TSXKeysymToString(keysym);
1749             if (!ksname)
1750                 ksname = "No Name";
1751             if ((keysym >> 8) != 0xff)
1752                 {
1753                 ERR("Please report: no char for keysym %04lX (%s) :\n",
1754                     keysym, ksname);
1755                 ERR("(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
1756                     virtKey, scanCode, e.keycode, e.state);
1757                 }
1758             }
1759         }
1760     else {  /* ret != 0 */
1761         /* We have a special case to handle : Shift + arrow, shift + home, ...
1762            X returns a char for it, but Windows doesn't. Let's eat it. */
1763         if (!(e.state & NumLockMask)  /* NumLock is off */
1764             && (e.state & ShiftMask) /* Shift is pressed */
1765             && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
1766         {
1767             *(char*)lpChar = 0;
1768             ret = 0;
1769         }
1770
1771         /* more areas where X returns characters but Windows does not
1772            CTRL + number or CTRL + symbol*/
1773         if (e.state & ControlMask)
1774         {
1775             if (((keysym>=33) && (keysym < 'A')) ||
1776                 ((keysym > 'Z') && (keysym < 'a')))
1777             {
1778                 *(char*)lpChar = 0;
1779                 ret = 0;
1780             }
1781         }
1782
1783         /* We have another special case for delete key (XK_Delete) on an
1784          extended keyboard. X returns a char for it, but Windows doesn't */
1785         if (keysym == XK_Delete)
1786         {
1787             *(char*)lpChar = 0;
1788             ret = 0;
1789         }
1790         else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
1791                 && (keysym == XK_KP_Decimal))
1792         {
1793             *(char*)lpChar = 0;
1794             ret = 0;
1795         }
1796
1797         /* perform translation to unicode */
1798         if(ret)
1799         {
1800             TRACE_(key)("Translating char 0x%02x from code page %d to unicode\n",
1801                 *(BYTE *)lpChar, main_key_tab[kbd_layout].layout_cp);
1802             ret = MultiByteToWideChar(main_key_tab[kbd_layout].layout_cp, 0, (LPCSTR)lpChar, ret, bufW, bufW_size);
1803         }
1804     }
1805
1806     TRACE_(key)("ToUnicode about to return %d with char %x %s\n",
1807                 ret, bufW ? bufW[0] : 0, bufW ? "" : "(no buffer)");
1808     return ret;
1809 }
1810
1811 /***********************************************************************
1812  *              Beep (X11DRV.@)
1813  */
1814 void X11DRV_Beep(void)
1815 {
1816   TSXBell(thread_display(), 0);
1817 }