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