Keep track of per-column information inside the listview.
[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 /*** Slovak and Czech (programmer's) keyboard layout (see cssk_dual(cs_sk_ucw)) */
528 static const char main_key_SK_prog[MAIN_LEN][4] =
529 {
530  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
531  "qQäÄ","wWìÌ","eEéÉ","rRøØ","tT»«","yYýÝ","uUùÙ","iIíÍ","oOóÓ","pPöÖ","[{","]}",
532  "aAáÁ","sS¹©","dDïÏ","fFëË","gGàÀ","hHúÚ","jJüÜ","kKôÔ","lLµ¥",";:","'\"","\\|",
533  "zZ¾®","xX¤","cCèÈ","vVçÇ","bB","nNòÒ","mMåÅ",",<",".>","/?",
534  "<>"
535 };
536
537 /*** Czech keyboard layout (see cssk_ibm(cs_qwerty) in xkbsel) */
538 static const char main_key_CS[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 /*** Latin American keyboard layout (contributed by Gabriel Orlando Garcia) */
548 static const char main_key_LA[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 /*** Lithuanian (Baltic) keyboard layout (contributed by Nerijus Baliûnas) */
558 static const char main_key_LT_B[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 /*** Turkish keyboard Layout */
567 static const char main_key_TK[MAIN_LEN][4] =
568 {
569 "\"é","1!","2'","3^#","4+$","5%","6&","7/{","8([","9)]","0=}","*?\\","-_",
570 "qQ@","wW","eE","rR","tT","yY","uU","ýIî","oO","pP","ðÐ","üÜ~",
571 "aAæ","sSß","dD","fF","gG","hH","jJ","kK","lL","þÞ","iÝ",",;`",
572 "zZ","xX","cC","vV","bB","nN","mM","öÖ","çÇ",".:"
573 };
574
575 /*** Israeli keyboard layout */
576 static const char main_key_IL[MAIN_LEN][4] =
577 {
578  "`~;","1!1","2@2","3#3","4$4","5%5","6^6","7&7","8*8","9(9","0)0","-_-","=+=",
579  "qQ/","wW'","eE÷","rRø","tTà","yYè","uUå","iIï","oOí","pPô","[{[","]}]",
580  "aAù","sSã","dDâ","fFë","gGò","hHé","jJç","kKì","lLê",";:ó","\'\",","\\|\\",
581  "zZæ","xXñ","cCá","vVä","bBð","nNî","mMö",",<ú",".>õ","/?."
582 };
583
584 /*** Greek keyboard layout (contributed by Kriton Kyrimis <kyrimis@cti.gr>)
585   Greek characters for "wW" and "sS" are omitted to not produce a mismatch
586   message since they have different characters in gr and el XFree86 layouts. */
587 static const char main_key_EL[MAIN_LEN][4] =
588 {
589  "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
590  "qQ;:","wW","eEåÅ","rRñÑ","tTôÔ","yYõÕ","uUèÈ","iIéÉ","oOïÏ","pPðÐ","[{","]}",
591  "aAáÁ","sS","dDäÄ","fFöÖ","gGãÃ","hHçÇ","jJîÎ","kKêÊ","lLëË",";:´¨","'\"","\\|",
592  "zZæÆ","xX÷×","cCøØ","vVùÙ","bBâÂ","nNíÍ","mMìÌ",",<",".>","/?",
593  "<>"
594 };
595
596 /*** VNC keyboard layout */
597 static const WORD main_key_scan_vnc[MAIN_LEN] =
598 {
599    0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x1A,0x1B,0x27,0x28,0x29,0x33,0x34,0x35,0x2B,
600    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,
601    0x56
602 };
603
604 static const WORD main_key_vkey_vnc[MAIN_LEN] =
605 {
606    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,
607    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,
608    VK_OEM_102
609 };
610
611 static const char main_key_vnc[MAIN_LEN][4] =
612 {
613  "1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+","[{","]}",";:","'\"","`~",",<",".>","/?","\\|",
614  "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"
615 };
616
617 /*** Layout table. Add your keyboard mappings to this list */
618 static const struct {
619     const char *comment;
620     const UINT layout_cp; /* Code page for this layout */
621     const char (*key)[MAIN_LEN][4];
622     const WORD (*scan)[MAIN_LEN]; /* scan codes mapping */
623     const WORD (*vkey)[MAIN_LEN]; /* virtual key codes mapping */
624 } main_key_tab[]={
625  {"United States keyboard layout", 28591, &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty},
626  {"United States keyboard layout (phantom key version)", 28591, &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
627  {"United States keyboard layout (dvorak)", 28591, &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak},
628  {"British keyboard layout", 28591, &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
629  {"German keyboard layout", 28591, &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwerty},
630  {"German keyboard layout without dead keys", 28591, &main_key_DE_nodead, &main_key_scan_qwerty, &main_key_vkey_qwerty},
631  {"German keyboard layout for logitech desktop pro", 28591, &main_key_DE_logitech,  &main_key_scan_qwerty, &main_key_vkey_qwerty},
632  {"German keyboard layout without dead keys 105", 28591, &main_key_DE_nodead_105, &main_key_scan_qwerty, &main_key_vkey_qwerty},
633  {"Swiss German keyboard layout", 28591, &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwerty},
634  {"Swedish keyboard layout", 28591, &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty},
635  {"Estonian keyboard layout", 28591, &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty},
636  {"Norwegian keyboard layout", 28591, &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty},
637  {"Danish keyboard layout", 28591, &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
638  {"French keyboard layout", 28591, &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty},
639  {"Canadian French keyboard layout", 28591, &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
640  {"Belgian keyboard layout", 28591, &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty},
641  {"Swiss French keyboard layout", 28591, &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
642  {"Portuguese keyboard layout", 28591, &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
643  {"Brazilian ABNT-2 keyboard layout", 28591, &main_key_PT_br, &main_key_scan_qwerty, &main_key_vkey_qwerty},
644  {"United States International keyboard layout", 28591, &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
645  {"Finnish keyboard layout", 28591, &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
646  {"Bulgarian bds keyboard layout", 1251, &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty},
647  {"Bulgarian phonetic keyboard layout", 1251, &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
648  {"Belarusian keyboard layout", 1251, &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty},
649  {"Russian keyboard layout", 20866, &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
650  {"Russian keyboard layout (phantom key version)", 20866, &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
651  {"Russian keyboard layout KOI8-R", 20866, &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty},
652  {"Ukrainian keyboard layout KOI8-U", 20866, &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
653  {"Spanish keyboard layout", 28591, &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty},
654  {"Italian keyboard layout", 28591, &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
655  {"Icelandic keyboard layout", 28591, &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
656  {"Hungarian keyboard layout", 28592, &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
657  {"Polish (programmer's) keyboard layout", 28592, &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
658  {"Slovenian keyboard layout", 28592, &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
659  {"Croatian keyboard layout", 28592, &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwerty},
660  {"Croatian keyboard layout (specific)", 28592, &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
661  {"Japanese 106 keyboard layout", 932, &main_key_JA_jp106, &main_key_scan_qwerty, &main_key_vkey_qwerty},
662  {"Japanese pc98x1 keyboard layout", 932, &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
663  {"Slovak keyboard layout", 28592, &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
664  {"Slovak and Czech keyboard layout without dead keys", 28592, &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
665  {"Czech keyboard layout", 28592, &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
666  {"Latin American keyboard layout", 28591, &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
667  {"Lithuanian (Baltic) keyboard layout", 28603, &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty},
668  {"Turkish keyboard layout", 28599, &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
669  {"Israeli keyboard layout", 28598, &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
670  {"VNC keyboard layout", 28591, &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc},
671  {"Greek keyboard layout", 28597, &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
672
673  {NULL, 0, NULL, NULL, NULL} /* sentinel */
674 };
675 static unsigned kbd_layout=0; /* index into above table of layouts */
676
677 /* maybe more of these scancodes should be extended? */
678                 /* extended must be set for ALT_R, CTRL_R,
679                    INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
680                    keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
681                 /* FIXME should we set extended bit for NumLock ? My
682                  * Windows does ... DF */
683                 /* Yes, to distinguish based on scan codes, also
684                    for PrtScn key ... GA */
685
686 static const WORD nonchar_key_vkey[256] =
687 {
688     /* unused */
689     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF00 */
690     /* special keys */
691     VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0,           /* FF08 */
692     0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0,                      /* FF10 */
693     0, 0, 0, VK_ESCAPE, 0, 0, 0, 0,                             /* FF18 */
694     /* unused */
695     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF20 */
696     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF28 */
697     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF30 */
698     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF38 */
699     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF40 */
700     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF48 */
701     /* cursor keys */
702     VK_HOME, VK_LEFT, VK_UP, VK_RIGHT,                          /* FF50 */
703     VK_DOWN, VK_PRIOR, VK_NEXT, VK_END,
704     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF58 */
705     /* misc keys */
706     VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0,  /* FF60 */
707     VK_CANCEL, VK_HELP, VK_CANCEL, VK_CANCEL, 0, 0, 0, 0,       /* FF68 */
708     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF70 */
709     /* keypad keys */
710     0, 0, 0, 0, 0, 0, 0, VK_NUMLOCK,                            /* FF78 */
711     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FF80 */
712     0, 0, 0, 0, 0, VK_RETURN, 0, 0,                             /* FF88 */
713     0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP,                     /* FF90 */
714     VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT,                       /* FF98 */
715     VK_END, 0, VK_INSERT, VK_DELETE,
716     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFA0 */
717     0, 0, VK_MULTIPLY, VK_ADD,                                  /* FFA8 */
718     VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE,
719     VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3,             /* FFB0 */
720     VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
721     VK_NUMPAD8, VK_NUMPAD9, 0, 0, 0, 0,                         /* FFB8 */
722     /* function keys */
723     VK_F1, VK_F2,
724     VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10,    /* FFC0 */
725     VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, 0, 0,       /* FFC8 */
726     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFD0 */
727     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFD8 */
728     /* modifier keys */
729     0, VK_SHIFT, VK_SHIFT, VK_CONTROL,                          /* FFE0 */
730     VK_CONTROL, VK_CAPITAL, 0, VK_MENU,
731     VK_MENU, VK_MENU, VK_MENU, 0, 0, 0, 0, 0,                   /* FFE8 */
732     0, 0, 0, 0, 0, 0, 0, 0,                                     /* FFF0 */
733     0, 0, 0, 0, 0, 0, 0, VK_DELETE                              /* FFF8 */
734 };
735
736 static const WORD nonchar_key_scan[256] =
737 {
738     /* unused */
739     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF00 */
740     /* special keys */
741     0x0E, 0x0F, 0x00, /*?*/ 0, 0x00, 0x1C, 0x00, 0x00,           /* FF08 */
742     0x00, 0x00, 0x00, 0x45, 0x46, 0x00, 0x00, 0x00,              /* FF10 */
743     0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00,              /* FF18 */
744     /* unused */
745     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF20 */
746     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF28 */
747     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF30 */
748     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF38 */
749     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF40 */
750     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF48 */
751     /* cursor keys */
752     0x147, 0x14B, 0x148, 0x14D, 0x150, 0x149, 0x151, 0x14F,      /* FF50 */
753     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF58 */
754     /* misc keys */
755     /*?*/ 0, 0x137, /*?*/ 0, 0x152, 0x00, 0x00, 0x00, 0x00,      /* FF60 */
756     /*?*/ 0, /*?*/ 0, 0x38, 0x146, 0x00, 0x00, 0x00, 0x00,       /* FF68 */
757     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF70 */
758     /* keypad keys */
759     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x138, 0x145,            /* FF78 */
760     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FF80 */
761     0x00, 0x00, 0x00, 0x00, 0x00, 0x11C, 0x00, 0x00,             /* FF88 */
762     0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4B, 0x48,              /* FF90 */
763     0x4D, 0x50, 0x49, 0x51, 0x4F, 0x4C, 0x52, 0x53,              /* FF98 */
764     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFA0 */
765     0x00, 0x00, 0x37, 0x4E, /*?*/ 0, 0x4A, 0x53, 0x135,          /* FFA8 */
766     0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47,              /* FFB0 */
767     0x48, 0x49, 0x00, 0x00, 0x00, 0x00,                          /* FFB8 */
768     /* function keys */
769     0x3B, 0x3C,
770     0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44,              /* FFC0 */
771     0x57, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFC8 */
772     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFD0 */
773     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFD8 */
774     /* modifier keys */
775     0x00, 0x2A, 0x36, 0x1D, 0x11D, 0x3A, 0x00, 0x38,             /* FFE0 */
776     0x138, 0x38, 0x138, 0x00, 0x00, 0x00, 0x00, 0x00,            /* FFE8 */
777     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,              /* FFF0 */
778     0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x153              /* FFF8 */
779 };
780
781
782 /* Returns the Windows virtual key code associated with the X event <e> */
783 /* x11 lock must be held */
784 static WORD EVENT_event_to_vkey( XKeyEvent *e)
785 {
786     KeySym keysym;
787
788     XLookupString(e, NULL, 0, &keysym, NULL);
789
790     if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (keysym != 0xFFAF)
791         && (e->state & NumLockMask))
792         /* Only the Keypad keys 0-9 and . send different keysyms
793          * depending on the NumLock state */
794         return nonchar_key_vkey[keysym & 0xFF];
795
796     return keyc2vkey[e->keycode];
797 }
798
799 static BOOL NumState=FALSE, CapsState=FALSE;
800
801
802 /***********************************************************************
803  *           send_keyboard_input
804  */
805 static void send_keyboard_input( WORD wVk, WORD wScan, DWORD dwFlags, DWORD time )
806 {
807     INPUT input;
808
809     input.type             = WINE_INTERNAL_INPUT_KEYBOARD;
810     input.u.ki.wVk         = wVk;
811     input.u.ki.wScan       = wScan;
812     input.u.ki.dwFlags     = dwFlags;
813     input.u.ki.time        = time;
814     input.u.ki.dwExtraInfo = 0;
815     SendInput( 1, &input, sizeof(input) );
816 }
817
818
819 /**********************************************************************
820  *              KEYBOARD_GenerateMsg
821  *
822  * Generate Down+Up messages when NumLock or CapsLock is pressed.
823  *
824  * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
825  *
826  */
827 static void KEYBOARD_GenerateMsg( WORD vkey, WORD scan, int Evtype, DWORD event_time )
828 {
829   BOOL * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
830   DWORD up, down;
831
832   if (*State) {
833     /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
834        don't treat it. It's from the same key press. Then the state goes to ON.
835        And from there, a 'release' event will switch off the toggle key. */
836     *State=FALSE;
837     TRACE("INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,pKeyStateTable[vkey]);
838   } else
839     {
840         down = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0);
841         up = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0) | KEYEVENTF_KEYUP;
842         if ( pKeyStateTable[vkey] & 0x1 ) /* it was ON */
843           {
844             if (Evtype!=KeyPress)
845               {
846                 TRACE("ON + KeyRelease => generating DOWN and UP messages.\n");
847                 send_keyboard_input( vkey, scan, down, event_time );
848                 send_keyboard_input( vkey, scan, up, event_time );
849                 *State=FALSE;
850                 pKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */
851               }
852           }
853         else /* it was OFF */
854           if (Evtype==KeyPress)
855             {
856               TRACE("OFF + Keypress => generating DOWN and UP messages.\n");
857               send_keyboard_input( vkey, scan, down, event_time );
858               send_keyboard_input( vkey, scan, up, event_time );
859               *State=TRUE; /* Goes to intermediary state before going to ON */
860               pKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
861             }
862     }
863 }
864
865 /***********************************************************************
866  *           KEYBOARD_UpdateOneState
867  *
868  * Updates internal state for <vkey>, depending on key <state> under X
869  *
870  */
871 inline static void KEYBOARD_UpdateOneState ( int vkey, int state, DWORD time )
872 {
873     /* Do something if internal table state != X state for keycode */
874     if (((pKeyStateTable[vkey] & 0x80)!=0) != state)
875     {
876         TRACE("Adjusting state for vkey %#.2x. State before %#.2x \n",
877               vkey, pKeyStateTable[vkey]);
878
879         /* Fake key being pressed inside wine */
880         send_keyboard_input( vkey, 0, state? 0 : KEYEVENTF_KEYUP, time );
881
882         TRACE("State after %#.2x \n",pKeyStateTable[vkey]);
883     }
884 }
885
886 /***********************************************************************
887  *           X11DRV_KeymapNotify
888  *
889  * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
890  *
891  * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
892  * from wine to another application and back.
893  * Toggle keys are handled in HandleEvent.
894  */
895 void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event )
896 {
897     int i, j, alt, control, shift;
898     DWORD time = GetCurrentTime();
899
900     alt = control = shift = 0;
901     for (i = 0; i < 32; i++)
902     {
903         if (!event->key_vector[i]) continue;
904         for (j = 0; j < 8; j++)
905         {
906             if (!(event->key_vector[i] & (1<<j))) continue;
907             switch(keyc2vkey[(i * 8) + j] & 0xff)
908             {
909             case VK_MENU:    alt = 1; break;
910             case VK_CONTROL: control = 1; break;
911             case VK_SHIFT:   shift = 1; break;
912             }
913         }
914     }
915     KEYBOARD_UpdateOneState( VK_MENU, alt, time );
916     KEYBOARD_UpdateOneState( VK_CONTROL, control, time );
917     KEYBOARD_UpdateOneState( VK_SHIFT, shift, time );
918 }
919
920 /***********************************************************************
921  *           X11DRV_KeyEvent
922  *
923  * Handle a X key event
924  */
925 void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event )
926 {
927     char Str[24];
928     KeySym keysym;
929     WORD vkey = 0, bScan;
930     DWORD dwFlags;
931     int ascii_chars;
932
933     DWORD event_time = event->time - X11DRV_server_startticks;
934
935     /* this allows support for dead keys */
936     if ((event->keycode >> 8) == 0x10)
937         event->keycode=(event->keycode & 0xff);
938
939     wine_tsx11_lock();
940     ascii_chars = XLookupString(event, Str, sizeof(Str), &keysym, NULL);
941     wine_tsx11_unlock();
942
943     /* Ignore some unwanted events */
944     if (keysym == XK_ISO_Prev_Group ||
945         keysym == XK_ISO_Next_Group ||
946         keysym == XK_Mode_switch)
947     {
948         TRACE("Ignoring %s keyboard event\n", TSXKeysymToString(keysym));
949         return;
950     }
951
952     TRACE_(key)("state = %X\n", event->state);
953
954     /* If XKB extensions is used, the state mask for AltGr will used the group
955        index instead of the modifier mask. The group index is set in bits
956        13-14 of the state field in the XKeyEvent structure. So if AltGr is
957        pressed, look if the group index is diferent than 0. From XKB
958        extension documentation, the group index should for AltGr should
959        be 2 (event->state = 0x2000). It's probably better to not assume a
960        predefined group index and find it dynamically
961
962        Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
963     AltGrMask = event->state & 0x6000;
964
965     Str[ascii_chars] = '\0';
966     if (TRACE_ON(key)){
967         char    *ksname;
968
969         ksname = TSXKeysymToString(keysym);
970         if (!ksname)
971           ksname = "No Name";
972         TRACE_(key)("%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
973                     (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
974                     keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
975     }
976
977     wine_tsx11_lock();
978     vkey = EVENT_event_to_vkey(event);
979     wine_tsx11_unlock();
980
981     TRACE_(key)("keycode 0x%x converted to vkey 0x%x\n",
982                 event->keycode, vkey);
983
984    if (vkey)
985    {
986     switch (vkey & 0xff)
987     {
988     case VK_NUMLOCK:
989       KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, event->type, event_time );
990       break;
991     case VK_CAPITAL:
992       TRACE("Caps Lock event. (type %d). State before : %#.2x\n",event->type,pKeyStateTable[vkey]);
993       KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, event->type, event_time );
994       TRACE("State after : %#.2x\n",pKeyStateTable[vkey]);
995       break;
996     default:
997         /* Adjust the NUMLOCK state if it has been changed outside wine */
998         if (!(pKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
999           {
1000             TRACE("Adjusting NumLock state. \n");
1001             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyPress, event_time );
1002             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyRelease, event_time );
1003           }
1004         /* Adjust the CAPSLOCK state if it has been changed outside wine */
1005         if (!(pKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
1006           {
1007               TRACE("Adjusting Caps Lock state.\n");
1008             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyPress, event_time );
1009             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyRelease, event_time );
1010           }
1011         /* Not Num nor Caps : end of intermediary states for both. */
1012         NumState = FALSE;
1013         CapsState = FALSE;
1014
1015         bScan = keyc2scan[event->keycode] & 0xFF;
1016         TRACE_(key)("bScan = 0x%02x.\n", bScan);
1017
1018         dwFlags = 0;
1019         if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
1020         if ( vkey & 0x100 )              dwFlags |= KEYEVENTF_EXTENDEDKEY;
1021
1022         send_keyboard_input( vkey & 0xff, bScan, dwFlags, event_time );
1023     }
1024    }
1025 }
1026
1027 /**********************************************************************
1028  *              X11DRV_KEYBOARD_DetectLayout
1029  *
1030  * Called from X11DRV_InitKeyboard
1031  *  This routine walks through the defined keyboard layouts and selects
1032  *  whichever matches most closely.
1033  * X11 lock must be held.
1034  */
1035 static void
1036 X11DRV_KEYBOARD_DetectLayout (void)
1037 {
1038   Display *display = thread_display();
1039   unsigned current, match, mismatch, seq;
1040   int score, keyc, i, key, pkey, ok, syms;
1041   KeySym keysym;
1042   const char (*lkey)[MAIN_LEN][4];
1043   unsigned max_seq = 0;
1044   int max_score = 0, ismatch = 0;
1045   char ckey[4] =
1046   {0, 0, 0, 0};
1047
1048   syms = keysyms_per_keycode;
1049   if (syms > 4) {
1050     WARN("%d keysyms per keycode not supported, set to 4\n", syms);
1051     syms = 4;
1052   }
1053   for (current = 0; main_key_tab[current].comment; current++) {
1054     TRACE("Attempting to match against \"%s\"\n", main_key_tab[current].comment);
1055     match = 0;
1056     mismatch = 0;
1057     score = 0;
1058     seq = 0;
1059     lkey = main_key_tab[current].key;
1060     pkey = -1;
1061     for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1062       /* get data for keycode from X server */
1063       for (i = 0; i < syms; i++) {
1064         keysym = XKeycodeToKeysym (display, keyc, i);
1065         /* Allow both one-byte and two-byte national keysyms */
1066         if ((keysym < 0x8000) && (keysym != ' '))
1067           ckey[i] = keysym & 0xFF;
1068         else {
1069           ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1070         }
1071       }
1072       if (ckey[0]) {
1073         /* search for a match in layout table */
1074         /* right now, we just find an absolute match for defined positions */
1075         /* (undefined positions are ignored, so if it's defined as "3#" in */
1076         /* the table, it's okay that the X server has "3#£", for example) */
1077         /* however, the score will be higher for longer matches */
1078         for (key = 0; key < MAIN_LEN; key++) {
1079           for (ok = 0, i = 0; (ok >= 0) && (i < syms); i++) {
1080             if ((*lkey)[key][i] && ((*lkey)[key][i] == ckey[i]))
1081               ok++;
1082             if ((*lkey)[key][i] && ((*lkey)[key][i] != ckey[i]))
1083               ok = -1;
1084           }
1085           if (ok > 0) {
1086             score += ok;
1087             break;
1088           }
1089         }
1090         /* count the matches and mismatches */
1091         if (ok > 0) {
1092           match++;
1093           /* and how much the keycode order matches */
1094           if (key > pkey) seq++;
1095           pkey = key;
1096         } else {
1097           TRACE_(key)("mismatch for keycode %d, character %c\n", keyc,
1098                  ckey[0]);
1099           mismatch++;
1100           score -= syms;
1101         }
1102       }
1103     }
1104     TRACE("matches=%d, mismatches=%d, seq=%d, score=%d\n",
1105            match, mismatch, seq, score);
1106     if ((score > max_score) ||
1107         ((score == max_score) && (seq > max_seq))) {
1108       /* best match so far */
1109       kbd_layout = current;
1110       max_score = score;
1111       max_seq = seq;
1112       ismatch = !mismatch;
1113     }
1114   }
1115   /* we're done, report results if necessary */
1116   if (!ismatch) {
1117     FIXME(
1118            "Your keyboard layout was not found!\n"
1119            "Using closest match instead (%s) for scancode mapping.\n"
1120            "Please define your layout in windows/x11drv/keyboard.c and submit them\n"
1121            "to us for inclusion into future Wine releases.\n"
1122            "See the Wine User Guide, chapter \"Keyboard\" for more information.\n",
1123            main_key_tab[kbd_layout].comment);
1124   }
1125
1126   TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment);
1127 }
1128
1129 /**********************************************************************
1130  *              InitKeyboard (X11DRV.@)
1131  */
1132 void X11DRV_InitKeyboard( BYTE *key_state_table )
1133 {
1134 #ifdef HAVE_XKB
1135     int xkb_major = XkbMajorVersion, xkb_minor = XkbMinorVersion;
1136 #endif
1137     Display *display = thread_display();
1138     KeySym *ksp;
1139     XModifierKeymap *mmp;
1140     KeySym keysym;
1141     KeyCode *kcp;
1142     XKeyEvent e2;
1143     WORD scan, vkey, OEMvkey;
1144     int keyc, i, keyn, syms;
1145     char ckey[4]={0,0,0,0};
1146     const char (*lkey)[MAIN_LEN][4];
1147
1148     pKeyStateTable = key_state_table;
1149
1150     wine_tsx11_lock();
1151 #ifdef HAVE_XKB
1152     is_xkb = XkbQueryExtension(display,
1153                                &xkb_opcode, &xkb_event, &xkb_error,
1154                                &xkb_major, &xkb_minor);
1155     if (is_xkb) {
1156         /* we have XKB, approximate Windows behaviour */
1157         XkbSetDetectableAutoRepeat(display, True, NULL);
1158     }
1159 #endif
1160     XDisplayKeycodes(display, &min_keycode, &max_keycode);
1161     ksp = XGetKeyboardMapping(display, min_keycode,
1162                               max_keycode + 1 - min_keycode, &keysyms_per_keycode);
1163     /* We are only interested in keysyms_per_keycode.
1164        There is no need to hold a local copy of the keysyms table */
1165     XFree(ksp);
1166
1167     mmp = XGetModifierMapping(display);
1168     kcp = mmp->modifiermap;
1169     for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
1170     {
1171         int j;
1172
1173         for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
1174             if (*kcp)
1175             {
1176                 int k;
1177
1178                 for (k = 0; k < keysyms_per_keycode; k += 1)
1179                     if (XKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
1180                     {
1181                         NumLockMask = 1 << i;
1182                         TRACE_(key)("NumLockMask is %x\n", NumLockMask);
1183                     }
1184             }
1185     }
1186     XFreeModifiermap(mmp);
1187
1188     /* Detect the keyboard layout */
1189     X11DRV_KEYBOARD_DetectLayout();
1190     lkey = main_key_tab[kbd_layout].key;
1191     syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode;
1192
1193     /* Now build two conversion arrays :
1194      * keycode -> vkey + scancode + extended
1195      * vkey + extended -> keycode */
1196
1197     e2.display = display;
1198     e2.state = 0;
1199
1200     OEMvkey = VK_OEM_7; /* next is available.  */
1201     for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1202     {
1203         e2.keycode = (KeyCode)keyc;
1204         XLookupString(&e2, NULL, 0, &keysym, NULL);
1205         vkey = 0; scan = 0;
1206         if (keysym)  /* otherwise, keycode not used */
1207         {
1208             if ((keysym >> 8) == 0xFF)         /* non-character key */
1209             {
1210                 vkey = nonchar_key_vkey[keysym & 0xff];
1211                 scan = nonchar_key_scan[keysym & 0xff];
1212                 /* set extended bit when necessary */
1213                 if (scan & 0x100) vkey |= 0x100;
1214             } else if (keysym == 0x20) {                 /* Spacebar */
1215                 vkey = VK_SPACE;
1216                 scan = 0x39;
1217             } else {
1218               /* we seem to need to search the layout-dependent scancodes */
1219               int maxlen=0,maxval=-1,ok;
1220               for (i=0; i<syms; i++) {
1221                 keysym = XKeycodeToKeysym(display, keyc, i);
1222                 if ((keysym<0x800) && (keysym!=' ')) {
1223                   ckey[i] = keysym & 0xFF;
1224                 } else {
1225                   ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1226                 }
1227               }
1228               /* find key with longest match streak */
1229               for (keyn=0; keyn<MAIN_LEN; keyn++) {
1230                 for (ok=(*lkey)[keyn][i=0]; ok&&(i<4); i++)
1231                   if ((*lkey)[keyn][i] && (*lkey)[keyn][i]!=ckey[i]) ok=0;
1232                 if (ok||(i>maxlen)) {
1233                   maxlen=i; maxval=keyn;
1234                 }
1235                 if (ok) break;
1236               }
1237               if (maxval>=0) {
1238                 /* got it */
1239                 const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan;
1240                 const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey;
1241                 scan = (*lscan)[maxval];
1242                 vkey = (*lvkey)[maxval];
1243               }
1244             }
1245
1246             /* find a suitable layout-dependent VK code */
1247             /* (most Winelib apps ought to be able to work without layout tables!) */
1248             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1249             {
1250                 keysym = XLookupKeysym(&e2, i);
1251                 if ((keysym >= VK_0 && keysym <= VK_9)
1252                     || (keysym >= VK_A && keysym <= VK_Z)) {
1253                     vkey = keysym;
1254                 }
1255             }
1256
1257             for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1258             {
1259                 keysym = XLookupKeysym(&e2, i);
1260                 switch (keysym)
1261                 {
1262                 case ';':             vkey = VK_OEM_1; break;
1263                 case '/':             vkey = VK_OEM_2; break;
1264                 case '`':             vkey = VK_OEM_3; break;
1265                 case '[':             vkey = VK_OEM_4; break;
1266                 case '\\':            vkey = VK_OEM_5; break;
1267                 case ']':             vkey = VK_OEM_6; break;
1268                 case '\'':            vkey = VK_OEM_7; break;
1269                 case ',':             vkey = VK_OEM_COMMA; break;
1270                 case '.':             vkey = VK_OEM_PERIOD; break;
1271                 case '-':             vkey = VK_OEM_MINUS; break;
1272                 case '+':             vkey = VK_OEM_PLUS; break;
1273                 }
1274             }
1275
1276             if (!vkey)
1277             {
1278                 /* Others keys: let's assign OEM virtual key codes in the allowed range,
1279                  * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
1280                 switch (++OEMvkey)
1281                 {
1282                 case 0xc1 : OEMvkey=0xdb; break;
1283                 case 0xe5 : OEMvkey=0xe9; break;
1284                 case 0xf6 : OEMvkey=0xf5; WARN("No more OEM vkey available!\n");
1285                 }
1286
1287                 vkey = OEMvkey;
1288
1289                 if (TRACE_ON(keyboard))
1290                 {
1291                     TRACE("OEM specific virtual key %X assigned to keycode %X:\n",
1292                                      OEMvkey, e2.keycode);
1293                     TRACE("(");
1294                     for (i = 0; i < keysyms_per_keycode; i += 1)
1295                     {
1296                         char    *ksname;
1297
1298                         keysym = XLookupKeysym(&e2, i);
1299                         ksname = XKeysymToString(keysym);
1300                         if (!ksname)
1301                             ksname = "NoSymbol";
1302                         DPRINTF( "%lX (%s) ", keysym, ksname);
1303                     }
1304                     DPRINTF(")\n");
1305                 }
1306             }
1307         }
1308         keyc2vkey[e2.keycode] = vkey;
1309         keyc2scan[e2.keycode] = scan;
1310     } /* for */
1311
1312     /* If some keys still lack scancodes, assign some arbitrary ones to them now */
1313     for (scan = 0x60, keyc = min_keycode; keyc <= max_keycode; keyc++)
1314       if (keyc2vkey[keyc]&&!keyc2scan[keyc]) {
1315         char *ksname;
1316         keysym = XKeycodeToKeysym(display, keyc, 0);
1317         ksname = XKeysymToString(keysym);
1318         if (!ksname) ksname = "NoSymbol";
1319
1320         /* should make sure the scancode is unassigned here, but >=0x60 currently always is */
1321
1322         TRACE_(key)("assigning scancode %02x to unidentified keycode %02x (%s)\n",scan,keyc,ksname);
1323         keyc2scan[keyc]=scan++;
1324       }
1325
1326     /* Now store one keycode for each modifier. Used to simulate keypresses. */
1327     kcControl = XKeysymToKeycode(display, XK_Control_L);
1328     kcAlt = XKeysymToKeycode(display, XK_Alt_L);
1329     if (!kcAlt) kcAlt = XKeysymToKeycode(display, XK_Meta_L);
1330     kcShift = XKeysymToKeycode(display, XK_Shift_L);
1331     kcNumLock = XKeysymToKeycode(display, XK_Num_Lock);
1332     kcCapsLock = XKeysymToKeycode(display, XK_Caps_Lock);
1333     wine_tsx11_unlock();
1334 }
1335
1336
1337 /***********************************************************************
1338  *           X11DRV_MappingNotify
1339  */
1340 void X11DRV_MappingNotify( XMappingEvent *event )
1341 {
1342     TSXRefreshKeyboardMapping(event);
1343     X11DRV_InitKeyboard( pKeyStateTable );
1344 }
1345
1346
1347 /***********************************************************************
1348  *              VkKeyScan (X11DRV.@)
1349  */
1350 WORD X11DRV_VkKeyScan(CHAR cChar)
1351 {
1352         Display *display = thread_display();
1353         KeyCode keycode;
1354         KeySym keysym;
1355         int i,index;
1356         int highbyte=0;
1357
1358         /* char->keysym (same for ANSI chars) */
1359         keysym=(unsigned char) cChar;/* (!) cChar is signed */
1360         if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
1361
1362         keycode = TSXKeysymToKeycode(display, keysym);  /* keysym -> keycode */
1363         if (!keycode)
1364         { /* It didn't work ... let's try with deadchar code. */
1365           keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
1366         }
1367
1368         TRACE("VkKeyScan '%c'(%#lx, %lu): got keycode %#.2x\n",
1369               cChar,keysym,keysym,keycode);
1370
1371         if (keycode)
1372           {
1373             for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
1374               if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i;
1375             switch (index) {
1376             case -1 :
1377               WARN("Keysym %lx not found while parsing the keycode table\n",keysym); break;
1378             case 0 : break;
1379             case 1 : highbyte = 0x0100; break;
1380             case 2 : highbyte = 0x0600; break;
1381             case 3 : highbyte = 0x0700; break;
1382             default : ERR("index %d found by XKeycodeToKeysym. please report! \n",index);
1383             }
1384             /*
1385               index : 0     adds 0x0000
1386               index : 1     adds 0x0100 (shift)
1387               index : ?     adds 0x0200 (ctrl)
1388               index : 2     adds 0x0600 (ctrl+alt)
1389               index : 3     adds 0x0700 (ctrl+alt+shift)
1390              */
1391           }
1392         TRACE(" ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
1393         return keyc2vkey[keycode]+highbyte;   /* keycode -> (keyc2vkey) vkey */
1394 }
1395
1396 /***********************************************************************
1397  *              MapVirtualKey (X11DRV.@)
1398  */
1399 UINT X11DRV_MapVirtualKey(UINT wCode, UINT wMapType)
1400 {
1401     Display *display = thread_display();
1402
1403 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
1404
1405         TRACE("MapVirtualKey wCode=0x%x wMapType=%d ... \n", wCode,wMapType);
1406         switch(wMapType) {
1407                 case 0: { /* vkey-code to scan-code */
1408                         /* let's do vkey -> keycode -> scan */
1409                         int keyc;
1410                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1411                                 if ((keyc2vkey[keyc] & 0xFF) == wCode)
1412                                         returnMVK (keyc2scan[keyc] & 0xFF);
1413                         TRACE("returning no scan-code.\n");
1414                         return 0; }
1415
1416                 case 1: { /* scan-code to vkey-code */
1417                         /* let's do scan -> keycode -> vkey */
1418                         int keyc;
1419                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1420                                 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
1421                                         returnMVK (keyc2vkey[keyc] & 0xFF);
1422                         TRACE("returning no vkey-code.\n");
1423                         return 0; }
1424
1425                 case 2: { /* vkey-code to unshifted ANSI code */
1426                         /* we still don't know what "unshifted" means. in windows VK_W (0x57)
1427                          * returns 0x57, which is upercase 'W'. So we have to return the uppercase
1428                          * key.. Looks like something is wrong with the MS docs?
1429                          * This is only true for letters, for example VK_0 returns '0' not ')'.
1430                          * - hence we use the lock mask to ensure this happens.
1431                          */
1432                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
1433                         XKeyEvent e;
1434                         KeySym keysym;
1435                         int keyc;
1436                         char s[2];
1437                         e.display = display;
1438
1439                         e.state = LockMask;
1440                         /* LockMask should behave exactly like caps lock - upercase
1441                          * the letter keys and thats about it. */
1442
1443                         wine_tsx11_lock();
1444
1445                         e.keycode = 0;
1446                         /* We exit on the first keycode found, to speed up the thing. */
1447                         for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
1448                         { /* Find a keycode that could have generated this virtual key */
1449                             if  ((keyc2vkey[keyc] & 0xFF) == wCode)
1450                             { /* We filter the extended bit, we don't know it */
1451                                 e.keycode = keyc; /* Store it temporarily */
1452                                 if ((EVENT_event_to_vkey(&e) & 0xFF) != wCode) {
1453                                     e.keycode = 0; /* Wrong one (ex: because of the NumLock
1454                                          state), so set it to 0, we'll find another one */
1455                                 }
1456                             }
1457                         }
1458
1459                         if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
1460                           e.keycode = XKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
1461
1462                         if (wCode==VK_DECIMAL)
1463                           e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
1464
1465                         if (!e.keycode)
1466                         {
1467                           WARN("Unknown virtual key %X !!! \n", wCode);
1468                           wine_tsx11_unlock();
1469                           return 0; /* whatever */
1470                         }
1471                         TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
1472
1473                         if (XLookupString(&e, s, 2, &keysym, NULL))
1474                         {
1475                             wine_tsx11_unlock();
1476                             returnMVK (*s);
1477                         }
1478
1479                         TRACE("returning no ANSI.\n");
1480                         wine_tsx11_unlock();
1481                         return 0;
1482                         }
1483
1484                 case 3:   /* **NT only** scan-code to vkey-code but distinguish between  */
1485                           /*             left and right  */
1486                           FIXME(" stub for NT\n");
1487                           return 0;
1488
1489                 default: /* reserved */
1490                         WARN("Unknown wMapType %d !\n", wMapType);
1491                         return 0;
1492         }
1493         return 0;
1494 }
1495
1496 /***********************************************************************
1497  *              GetKeyNameText (X11DRV.@)
1498  */
1499 INT X11DRV_GetKeyNameText(LONG lParam, LPSTR lpBuffer, INT nSize)
1500 {
1501   int vkey, ansi, scanCode;
1502   KeyCode keyc;
1503   int keyi;
1504   KeySym keys;
1505   char *name;
1506
1507   scanCode = lParam >> 16;
1508   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
1509
1510   /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
1511   vkey = X11DRV_MapVirtualKey(scanCode, 1);
1512
1513   /*  handle "don't care" bit (0x02000000) */
1514   if (!(lParam & 0x02000000)) {
1515     switch (vkey) {
1516          case VK_LSHIFT:
1517          case VK_RSHIFT:
1518                           vkey = VK_SHIFT;
1519                           break;
1520        case VK_LCONTROL:
1521        case VK_RCONTROL:
1522                           vkey = VK_CONTROL;
1523                           break;
1524           case VK_LMENU:
1525           case VK_RMENU:
1526                           vkey = VK_MENU;
1527                           break;
1528                default:
1529                           break;
1530     }
1531   }
1532
1533   ansi = X11DRV_MapVirtualKey(vkey, 2);
1534   TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
1535
1536   /* first get the name of the "regular" keys which is the Upper case
1537      value of the keycap imprint.                                     */
1538   if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
1539        (scanCode != 0x137) &&   /* PrtScn   */
1540        (scanCode != 0x135) &&   /* numpad / */
1541        (scanCode != 0x37 ) &&   /* numpad * */
1542        (scanCode != 0x4a ) &&   /* numpad - */
1543        (scanCode != 0x4e ) )    /* numpad + */
1544       {
1545         if ((nSize >= 2) && lpBuffer)
1546         {
1547         *lpBuffer = toupper((char)ansi);
1548           *(lpBuffer+1) = 0;
1549           return 1;
1550         }
1551      else
1552         return 0;
1553   }
1554
1555   /* FIXME: horrible hack to fix function keys. Windows reports scancode
1556             without "extended-key" flag. However Wine generates scancode
1557             *with* "extended-key" flag. Seems to occur *only* for the
1558             function keys. Soooo.. We will leave the table alone and
1559             fudge the lookup here till the other part is found and fixed!!! */
1560
1561   if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
1562        (scanCode == 0x157) || (scanCode == 0x158))
1563     scanCode &= 0xff;   /* remove "extended-key" flag for Fx keys */
1564
1565   /* let's do scancode -> keycode -> keysym -> String */
1566
1567   for (keyi=min_keycode; keyi<=max_keycode; keyi++)
1568       if ((keyc2scan[keyi]) == scanCode)
1569          break;
1570   if (keyi <= max_keycode)
1571   {
1572       keyc = (KeyCode) keyi;
1573       keys = TSXKeycodeToKeysym(thread_display(), keyc, 0);
1574       name = TSXKeysymToString(keys);
1575       TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
1576             scanCode, keyc, (int)keys, name);
1577       if (lpBuffer && nSize && name)
1578       {
1579           lstrcpynA(lpBuffer, name, nSize);
1580           return 1;
1581       }
1582   }
1583
1584   /* Finally issue FIXME for unknown keys   */
1585
1586   FIXME("(%08lx,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
1587   if (lpBuffer && nSize)
1588     *lpBuffer = 0;
1589   return 0;
1590 }
1591
1592 /***********************************************************************
1593  *              X11DRV_KEYBOARD_MapDeadKeysym
1594  */
1595 static char KEYBOARD_MapDeadKeysym(KeySym keysym)
1596 {
1597         switch (keysym)
1598             {
1599         /* symbolic ASCII is the same as defined in rfc1345 */
1600 #ifdef XK_dead_tilde
1601             case XK_dead_tilde :
1602 #endif
1603             case 0x1000FE7E : /* Xfree's XK_Dtilde */
1604                 return '~';     /* '? */
1605 #ifdef XK_dead_acute
1606             case XK_dead_acute :
1607 #endif
1608             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1609                 return 0xb4;    /* '' */
1610 #ifdef XK_dead_circumflex
1611             case XK_dead_circumflex:
1612 #endif
1613             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1614                 return '^';     /* '> */
1615 #ifdef XK_dead_grave
1616             case XK_dead_grave :
1617 #endif
1618             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1619                 return '`';     /* '! */
1620 #ifdef XK_dead_diaeresis
1621             case XK_dead_diaeresis :
1622 #endif
1623             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1624                 return 0xa8;    /* ': */
1625 #ifdef XK_dead_cedilla
1626             case XK_dead_cedilla :
1627                 return 0xb8;    /* ', */
1628 #endif
1629 #ifdef XK_dead_macron
1630             case XK_dead_macron :
1631                 return '-';     /* 'm isn't defined on iso-8859-x */
1632 #endif
1633 #ifdef XK_dead_breve
1634             case XK_dead_breve :
1635                 return 0xa2;    /* '( */
1636 #endif
1637 #ifdef XK_dead_abovedot
1638             case XK_dead_abovedot :
1639                 return 0xff;    /* '. */
1640 #endif
1641 #ifdef XK_dead_abovering
1642             case XK_dead_abovering :
1643                 return '0';     /* '0 isn't defined on iso-8859-x */
1644 #endif
1645 #ifdef XK_dead_doubleacute
1646             case XK_dead_doubleacute :
1647                 return 0xbd;    /* '" */
1648 #endif
1649 #ifdef XK_dead_caron
1650             case XK_dead_caron :
1651                 return 0xb7;    /* '< */
1652 #endif
1653 #ifdef XK_dead_ogonek
1654             case XK_dead_ogonek :
1655                 return 0xb2;    /* '; */
1656 #endif
1657 /* FIXME: I don't know this three.
1658             case XK_dead_iota :
1659                 return 'i';
1660             case XK_dead_voiced_sound :
1661                 return 'v';
1662             case XK_dead_semivoiced_sound :
1663                 return 's';
1664 */
1665             }
1666         TRACE("no character for dead keysym 0x%08lx\n",keysym);
1667         return 0;
1668 }
1669
1670 /***********************************************************************
1671  *              ToUnicode (X11DRV.@)
1672  *
1673  * The ToUnicode function translates the specified virtual-key code and keyboard
1674  * state to the corresponding Windows character or characters.
1675  *
1676  * If the specified key is a dead key, the return value is negative. Otherwise,
1677  * it is one of the following values:
1678  * Value        Meaning
1679  * 0    The specified virtual key has no translation for the current state of the keyboard.
1680  * 1    One Windows character was copied to the buffer.
1681  * 2    Two characters were copied to the buffer. This usually happens when a
1682  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
1683  *      be composed with the specified virtual key to form a single character.
1684  *
1685  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
1686  *
1687  */
1688 INT X11DRV_ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
1689                      LPWSTR bufW, int bufW_size, UINT flags)
1690 {
1691     Display *display = thread_display();
1692     XKeyEvent e;
1693     KeySym keysym;
1694     INT ret;
1695     int keyc;
1696     BYTE lpChar[2];
1697
1698     if (scanCode & 0x8000)
1699     {
1700         TRACE("Key UP, doing nothing\n" );
1701         return 0;
1702     }
1703     e.display = display;
1704     e.keycode = 0;
1705     e.state = 0;
1706     if (lpKeyState[VK_SHIFT] & 0x80)
1707     {
1708         TRACE("ShiftMask = %04x\n", ShiftMask);
1709         e.state |= ShiftMask;
1710     }
1711     if (lpKeyState[VK_CAPITAL] & 0x01)
1712     {
1713         TRACE("LockMask = %04x\n", LockMask);
1714         e.state |= LockMask;
1715     }
1716     if (lpKeyState[VK_CONTROL] & 0x80)
1717     {
1718         TRACE("ControlMask = %04x\n", ControlMask);
1719         e.state |= ControlMask;
1720     }
1721     if (lpKeyState[VK_NUMLOCK] & 0x01)
1722     {
1723         TRACE("NumLockMask = %04x\n", NumLockMask);
1724         e.state |= NumLockMask;
1725     }
1726
1727     /* Restore saved AltGr state */
1728     TRACE("AltGrMask = %04x\n", AltGrMask);
1729     e.state |= AltGrMask;
1730
1731     TRACE_(key)("(%04X, %04X) : faked state = %X\n",
1732                 virtKey, scanCode, e.state);
1733     wine_tsx11_lock();
1734     /* We exit on the first keycode found, to speed up the thing. */
1735     for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
1736       { /* Find a keycode that could have generated this virtual key */
1737           if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
1738           { /* We filter the extended bit, we don't know it */
1739               e.keycode = keyc; /* Store it temporarily */
1740               if ((EVENT_event_to_vkey(&e) & 0xFF) != virtKey) {
1741                   e.keycode = 0; /* Wrong one (ex: because of the NumLock
1742                          state), so set it to 0, we'll find another one */
1743               }
1744           }
1745       }
1746
1747     if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1748         e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1749
1750     if (virtKey==VK_DECIMAL)
1751         e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
1752
1753     if (!e.keycode)
1754       {
1755         WARN("Unknown virtual key %X !!! \n",virtKey);
1756         wine_tsx11_unlock();
1757         return virtKey; /* whatever */
1758       }
1759     else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
1760
1761     ret = XLookupString(&e, (LPVOID)lpChar, 2, &keysym, NULL);
1762     wine_tsx11_unlock();
1763
1764     if (ret == 0)
1765         {
1766         BYTE dead_char;
1767
1768         dead_char = KEYBOARD_MapDeadKeysym(keysym);
1769         if (dead_char)
1770             {
1771             MultiByteToWideChar(main_key_tab[kbd_layout].layout_cp, 0, &dead_char, 1, bufW, bufW_size);
1772             ret = -1;
1773             }
1774         else
1775             {
1776             char        *ksname;
1777
1778             ksname = TSXKeysymToString(keysym);
1779             if (!ksname)
1780                 ksname = "No Name";
1781             if ((keysym >> 8) != 0xff)
1782                 {
1783                 ERR("Please report: no char for keysym %04lX (%s) :\n",
1784                     keysym, ksname);
1785                 ERR("(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
1786                     virtKey, scanCode, e.keycode, e.state);
1787                 }
1788             }
1789         }
1790     else {  /* ret != 0 */
1791         /* We have a special case to handle : Shift + arrow, shift + home, ...
1792            X returns a char for it, but Windows doesn't. Let's eat it. */
1793         if (!(e.state & NumLockMask)  /* NumLock is off */
1794             && (e.state & ShiftMask) /* Shift is pressed */
1795             && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
1796         {
1797             *(char*)lpChar = 0;
1798             ret = 0;
1799         }
1800
1801         /* more areas where X returns characters but Windows does not
1802            CTRL + number or CTRL + symbol*/
1803         if (e.state & ControlMask)
1804         {
1805             if (((keysym>=33) && (keysym < 'A')) ||
1806                 ((keysym > 'Z') && (keysym < 'a')))
1807             {
1808                 *(char*)lpChar = 0;
1809                 ret = 0;
1810             }
1811         }
1812
1813         /* We have another special case for delete key (XK_Delete) on an
1814          extended keyboard. X returns a char for it, but Windows doesn't */
1815         if (keysym == XK_Delete)
1816         {
1817             *(char*)lpChar = 0;
1818             ret = 0;
1819         }
1820         else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
1821                 && (keysym == XK_KP_Decimal))
1822         {
1823             *(char*)lpChar = 0;
1824             ret = 0;
1825         }
1826
1827         /* perform translation to unicode */
1828         if(ret)
1829         {
1830             TRACE_(key)("Translating char 0x%02x from code page %d to unicode\n",
1831                 *(BYTE *)lpChar, main_key_tab[kbd_layout].layout_cp);
1832             ret = MultiByteToWideChar(main_key_tab[kbd_layout].layout_cp, 0, (LPCSTR)lpChar, ret, bufW, bufW_size);
1833         }
1834     }
1835
1836     TRACE_(key)("ToUnicode about to return %d with char %x %s\n",
1837                 ret, bufW ? bufW[0] : 0, bufW ? "" : "(no buffer)");
1838     return ret;
1839 }
1840
1841 /***********************************************************************
1842  *              Beep (X11DRV.@)
1843  */
1844 void X11DRV_Beep(void)
1845 {
1846   TSXBell(thread_display(), 0);
1847 }