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