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