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