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