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