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