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