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