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