Added stubs for AccessCheckByType, AddAuditAccessAce,
[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     SHORT ret;
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         TRACE("retrying with | 0xFE00\n");
1518         keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
1519     }
1520
1521     TRACE("'%c'(%#lx, %lu): got keycode %#.2x (%d)\n",
1522             cChar, keysym, keysym, keycode, keycode);
1523
1524     /* keycode -> (keyc2vkey) vkey */
1525     ret = keyc2vkey[keycode];
1526
1527     if (!keycode || !ret)
1528     {
1529         TRACE("keycode for '%c' not found, returning -1\n", cChar);
1530         return -1;
1531     }
1532
1533     index = -1;
1534     for (i = 0; i < 4; i++) /* find shift state */
1535     {
1536         if (TSXKeycodeToKeysym(display, keycode, i) == keysym)
1537         {
1538             index = i;
1539             break;
1540         }
1541     }
1542
1543     switch (index)
1544     {
1545         default:
1546         case -1:
1547             WARN("Keysym %lx not found while parsing the keycode table\n", keysym);
1548             return -1;
1549
1550         case 0: break;
1551         case 1: ret += 0x0100; break;
1552         case 2: ret += 0x0600; break;
1553         case 3: ret += 0x0700; break;
1554     }
1555     /*
1556       index : 0     adds 0x0000
1557       index : 1     adds 0x0100 (shift)
1558       index : ?     adds 0x0200 (ctrl)
1559       index : 2     adds 0x0600 (ctrl+alt)
1560       index : 3     adds 0x0700 (ctrl+alt+shift)
1561      */
1562
1563     TRACE(" ... returning %#.2x\n", ret);
1564     return ret;
1565 }
1566
1567 /***********************************************************************
1568  *              MapVirtualKey (X11DRV.@)
1569  */
1570 UINT X11DRV_MapVirtualKey(UINT wCode, UINT wMapType)
1571 {
1572     Display *display = thread_display();
1573
1574 #define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
1575
1576         TRACE("wCode=0x%x wMapType=%d ...\n", wCode,wMapType);
1577         switch(wMapType) {
1578                 case 0: { /* vkey-code to scan-code */
1579                         /* let's do vkey -> keycode -> scan */
1580                         int keyc;
1581                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1582                                 if ((keyc2vkey[keyc] & 0xFF) == wCode)
1583                                         returnMVK (keyc2scan[keyc] & 0xFF);
1584                         TRACE("returning no scan-code.\n");
1585                         return 0; }
1586
1587                 case 1: { /* scan-code to vkey-code */
1588                         /* let's do scan -> keycode -> vkey */
1589                         int keyc;
1590                         for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1591                                 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
1592                                         returnMVK (keyc2vkey[keyc] & 0xFF);
1593                         TRACE("returning no vkey-code.\n");
1594                         return 0; }
1595
1596                 case 2: { /* vkey-code to unshifted ANSI code */
1597                         /* we still don't know what "unshifted" means. in windows VK_W (0x57)
1598                          * returns 0x57, which is upercase 'W'. So we have to return the uppercase
1599                          * key.. Looks like something is wrong with the MS docs?
1600                          * This is only true for letters, for example VK_0 returns '0' not ')'.
1601                          * - hence we use the lock mask to ensure this happens.
1602                          */
1603                         /* let's do vkey -> keycode -> (XLookupString) ansi char */
1604                         XKeyEvent e;
1605                         KeySym keysym;
1606                         int keyc;
1607                         char s[2];
1608                         e.display = display;
1609
1610                         e.state = LockMask;
1611                         /* LockMask should behave exactly like caps lock - upercase
1612                          * the letter keys and thats about it. */
1613
1614                         wine_tsx11_lock();
1615
1616                         e.keycode = 0;
1617                         /* We exit on the first keycode found, to speed up the thing. */
1618                         for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
1619                         { /* Find a keycode that could have generated this virtual key */
1620                             if  ((keyc2vkey[keyc] & 0xFF) == wCode)
1621                             { /* We filter the extended bit, we don't know it */
1622                                 e.keycode = keyc; /* Store it temporarily */
1623                                 if ((EVENT_event_to_vkey(0,&e) & 0xFF) != wCode) {
1624                                     e.keycode = 0; /* Wrong one (ex: because of the NumLock
1625                                          state), so set it to 0, we'll find another one */
1626                                 }
1627                             }
1628                         }
1629
1630                         if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
1631                           e.keycode = XKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
1632
1633                         if (wCode==VK_DECIMAL)
1634                           e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
1635
1636                         if (!e.keycode)
1637                         {
1638                           WARN("Unknown virtual key %X !!! \n", wCode);
1639                           wine_tsx11_unlock();
1640                           return 0; /* whatever */
1641                         }
1642                         TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
1643
1644                         if (XLookupString(&e, s, 2, &keysym, NULL))
1645                         {
1646                             wine_tsx11_unlock();
1647                             returnMVK (*s);
1648                         }
1649
1650                         TRACE("returning no ANSI.\n");
1651                         wine_tsx11_unlock();
1652                         return 0;
1653                         }
1654
1655                 case 3:   /* **NT only** scan-code to vkey-code but distinguish between  */
1656                           /*             left and right  */
1657                           FIXME(" stub for NT\n");
1658                           return 0;
1659
1660                 default: /* reserved */
1661                         WARN("Unknown wMapType %d !\n", wMapType);
1662                         return 0;
1663         }
1664         return 0;
1665 }
1666
1667 /***********************************************************************
1668  *              GetKeyNameText (X11DRV.@)
1669  */
1670 INT X11DRV_GetKeyNameText(LONG lParam, LPSTR lpBuffer, INT nSize)
1671 {
1672   int vkey, ansi, scanCode;
1673   KeyCode keyc;
1674   int keyi;
1675   KeySym keys;
1676   char *name;
1677
1678   scanCode = lParam >> 16;
1679   scanCode &= 0x1ff;  /* keep "extended-key" flag with code */
1680
1681   /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
1682   vkey = X11DRV_MapVirtualKey(scanCode, 1);
1683
1684   /*  handle "don't care" bit (0x02000000) */
1685   if (!(lParam & 0x02000000)) {
1686     switch (vkey) {
1687          case VK_LSHIFT:
1688          case VK_RSHIFT:
1689                           vkey = VK_SHIFT;
1690                           break;
1691        case VK_LCONTROL:
1692        case VK_RCONTROL:
1693                           vkey = VK_CONTROL;
1694                           break;
1695           case VK_LMENU:
1696           case VK_RMENU:
1697                           vkey = VK_MENU;
1698                           break;
1699                default:
1700                           break;
1701     }
1702   }
1703
1704   ansi = X11DRV_MapVirtualKey(vkey, 2);
1705   TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
1706
1707   /* first get the name of the "regular" keys which is the Upper case
1708      value of the keycap imprint.                                     */
1709   if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
1710        (scanCode != 0x137) &&   /* PrtScn   */
1711        (scanCode != 0x135) &&   /* numpad / */
1712        (scanCode != 0x37 ) &&   /* numpad * */
1713        (scanCode != 0x4a ) &&   /* numpad - */
1714        (scanCode != 0x4e ) )    /* numpad + */
1715       {
1716         if ((nSize >= 2) && lpBuffer)
1717         {
1718         *lpBuffer = toupper((char)ansi);
1719           *(lpBuffer+1) = 0;
1720           return 1;
1721         }
1722      else
1723         return 0;
1724   }
1725
1726   /* FIXME: horrible hack to fix function keys. Windows reports scancode
1727             without "extended-key" flag. However Wine generates scancode
1728             *with* "extended-key" flag. Seems to occur *only* for the
1729             function keys. Soooo.. We will leave the table alone and
1730             fudge the lookup here till the other part is found and fixed!!! */
1731
1732   if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
1733        (scanCode == 0x157) || (scanCode == 0x158))
1734     scanCode &= 0xff;   /* remove "extended-key" flag for Fx keys */
1735
1736   /* let's do scancode -> keycode -> keysym -> String */
1737
1738   for (keyi=min_keycode; keyi<=max_keycode; keyi++)
1739       if ((keyc2scan[keyi]) == scanCode)
1740          break;
1741   if (keyi <= max_keycode)
1742   {
1743       keyc = (KeyCode) keyi;
1744       keys = TSXKeycodeToKeysym(thread_display(), keyc, 0);
1745       name = TSXKeysymToString(keys);
1746       TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
1747             scanCode, keyc, (int)keys, name);
1748       if (lpBuffer && nSize && name)
1749       {
1750           lstrcpynA(lpBuffer, name, nSize);
1751           return 1;
1752       }
1753   }
1754
1755   /* Finally issue FIXME for unknown keys   */
1756
1757   FIXME("(%08lx,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
1758   if (lpBuffer && nSize)
1759     *lpBuffer = 0;
1760   return 0;
1761 }
1762
1763 /***********************************************************************
1764  *              X11DRV_KEYBOARD_MapDeadKeysym
1765  */
1766 static char KEYBOARD_MapDeadKeysym(KeySym keysym)
1767 {
1768         switch (keysym)
1769             {
1770         /* symbolic ASCII is the same as defined in rfc1345 */
1771 #ifdef XK_dead_tilde
1772             case XK_dead_tilde :
1773 #endif
1774             case 0x1000FE7E : /* Xfree's XK_Dtilde */
1775                 return '~';     /* '? */
1776 #ifdef XK_dead_acute
1777             case XK_dead_acute :
1778 #endif
1779             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1780                 return 0xb4;    /* '' */
1781 #ifdef XK_dead_circumflex
1782             case XK_dead_circumflex:
1783 #endif
1784             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1785                 return '^';     /* '> */
1786 #ifdef XK_dead_grave
1787             case XK_dead_grave :
1788 #endif
1789             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1790                 return '`';     /* '! */
1791 #ifdef XK_dead_diaeresis
1792             case XK_dead_diaeresis :
1793 #endif
1794             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1795                 return 0xa8;    /* ': */
1796 #ifdef XK_dead_cedilla
1797             case XK_dead_cedilla :
1798                 return 0xb8;    /* ', */
1799 #endif
1800 #ifdef XK_dead_macron
1801             case XK_dead_macron :
1802                 return '-';     /* 'm isn't defined on iso-8859-x */
1803 #endif
1804 #ifdef XK_dead_breve
1805             case XK_dead_breve :
1806                 return 0xa2;    /* '( */
1807 #endif
1808 #ifdef XK_dead_abovedot
1809             case XK_dead_abovedot :
1810                 return 0xff;    /* '. */
1811 #endif
1812 #ifdef XK_dead_abovering
1813             case XK_dead_abovering :
1814                 return '0';     /* '0 isn't defined on iso-8859-x */
1815 #endif
1816 #ifdef XK_dead_doubleacute
1817             case XK_dead_doubleacute :
1818                 return 0xbd;    /* '" */
1819 #endif
1820 #ifdef XK_dead_caron
1821             case XK_dead_caron :
1822                 return 0xb7;    /* '< */
1823 #endif
1824 #ifdef XK_dead_ogonek
1825             case XK_dead_ogonek :
1826                 return 0xb2;    /* '; */
1827 #endif
1828 /* FIXME: I don't know this three.
1829             case XK_dead_iota :
1830                 return 'i';
1831             case XK_dead_voiced_sound :
1832                 return 'v';
1833             case XK_dead_semivoiced_sound :
1834                 return 's';
1835 */
1836             }
1837         TRACE("no character for dead keysym 0x%08lx\n",keysym);
1838         return 0;
1839 }
1840
1841 /***********************************************************************
1842  *              ToUnicode (X11DRV.@)
1843  *
1844  * The ToUnicode function translates the specified virtual-key code and keyboard
1845  * state to the corresponding Windows character or characters.
1846  *
1847  * If the specified key is a dead key, the return value is negative. Otherwise,
1848  * it is one of the following values:
1849  * Value        Meaning
1850  * 0    The specified virtual key has no translation for the current state of the keyboard.
1851  * 1    One Windows character was copied to the buffer.
1852  * 2    Two characters were copied to the buffer. This usually happens when a
1853  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
1854  *      be composed with the specified virtual key to form a single character.
1855  *
1856  * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
1857  *
1858  */
1859 INT X11DRV_ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
1860                      LPWSTR bufW, int bufW_size, UINT flags)
1861 {
1862     Display *display = thread_display();
1863     XKeyEvent e;
1864     KeySym keysym = 0;
1865     INT ret;
1866     int keyc;
1867     char lpChar[10];
1868     HWND focus;
1869     XIC xic;
1870
1871     if (scanCode & 0x8000)
1872     {
1873         TRACE("Key UP, doing nothing\n" );
1874         return 0;
1875     }
1876
1877     e.display = display;
1878     e.keycode = 0;
1879     e.state = 0;
1880     e.type = KeyPress;
1881
1882     focus = GetFocus();
1883     if (focus) focus = GetAncestor( focus, GA_ROOT );
1884     if (!focus) focus = GetActiveWindow();
1885     e.window = X11DRV_get_whole_window( focus );
1886     xic = X11DRV_get_ic( focus );
1887
1888     if (lpKeyState[VK_SHIFT] & 0x80)
1889     {
1890         TRACE("ShiftMask = %04x\n", ShiftMask);
1891         e.state |= ShiftMask;
1892     }
1893     if (lpKeyState[VK_CAPITAL] & 0x01)
1894     {
1895         TRACE("LockMask = %04x\n", LockMask);
1896         e.state |= LockMask;
1897     }
1898     if (lpKeyState[VK_CONTROL] & 0x80)
1899     {
1900         TRACE("ControlMask = %04x\n", ControlMask);
1901         e.state |= ControlMask;
1902     }
1903     if (lpKeyState[VK_NUMLOCK] & 0x01)
1904     {
1905         TRACE("NumLockMask = %04x\n", NumLockMask);
1906         e.state |= NumLockMask;
1907     }
1908
1909     /* Restore saved AltGr state */
1910     TRACE("AltGrMask = %04x\n", AltGrMask);
1911     e.state |= AltGrMask;
1912
1913     TRACE_(key)("(%04X, %04X) : faked state = 0x%04x\n",
1914                 virtKey, scanCode, e.state);
1915     wine_tsx11_lock();
1916     /* We exit on the first keycode found, to speed up the thing. */
1917     for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
1918       { /* Find a keycode that could have generated this virtual key */
1919           if  ((keyc2vkey[keyc] & 0xFF) == virtKey)
1920           { /* We filter the extended bit, we don't know it */
1921               e.keycode = keyc; /* Store it temporarily */
1922               if ((EVENT_event_to_vkey(xic,&e) & 0xFF) != virtKey) {
1923                   e.keycode = 0; /* Wrong one (ex: because of the NumLock
1924                          state), so set it to 0, we'll find another one */
1925               }
1926           }
1927       }
1928
1929     if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
1930         e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
1931
1932     if (virtKey==VK_DECIMAL)
1933         e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
1934
1935     if (!e.keycode && virtKey != VK_NONAME)
1936       {
1937         WARN("Unknown virtual key %X !!! \n",virtKey);
1938         wine_tsx11_unlock();
1939         return virtKey; /* whatever */
1940       }
1941     else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
1942
1943     TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
1944                 e.type, e.window, e.state, e.keycode);
1945
1946     if (xic)
1947         ret = XmbLookupString(xic, &e, lpChar, sizeof(lpChar), &keysym, NULL);
1948     else
1949         ret = XLookupString(&e, lpChar, sizeof(lpChar), &keysym, NULL);
1950     wine_tsx11_unlock();
1951
1952     if (ret == 0)
1953         {
1954         BYTE dead_char;
1955
1956         /* An ugly hack for EuroSign: X can't translate it to a character
1957            for some locales. */
1958         if (keysym == XK_EuroSign)
1959         {
1960             bufW[0] = 0x20AC;
1961             ret = 1;
1962             goto found;
1963         }
1964
1965         dead_char = KEYBOARD_MapDeadKeysym(keysym);
1966         if (dead_char)
1967             {
1968             MultiByteToWideChar(CP_UNIXCP, 0, &dead_char, 1, bufW, bufW_size);
1969             ret = -1;
1970             }
1971         else
1972             {
1973             char        *ksname;
1974
1975             ksname = TSXKeysymToString(keysym);
1976             if (!ksname)
1977                 ksname = "No Name";
1978             if ((keysym >> 8) != 0xff)
1979                 {
1980                 ERR("Please report: no char for keysym %04lX (%s) :\n",
1981                     keysym, ksname);
1982                 ERR("(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
1983                     virtKey, scanCode, e.keycode, e.state);
1984                 }
1985             }
1986         }
1987     else {  /* ret != 0 */
1988         /* We have a special case to handle : Shift + arrow, shift + home, ...
1989            X returns a char for it, but Windows doesn't. Let's eat it. */
1990         if (!(e.state & NumLockMask)  /* NumLock is off */
1991             && (e.state & ShiftMask) /* Shift is pressed */
1992             && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
1993         {
1994             lpChar[0] = 0;
1995             ret = 0;
1996         }
1997
1998         /* more areas where X returns characters but Windows does not
1999            CTRL + number or CTRL + symbol */
2000         if (e.state & ControlMask)
2001         {
2002             if (((keysym>=33) && (keysym < 'A')) ||
2003                 ((keysym > 'Z') && (keysym < 'a')))
2004             {
2005                 lpChar[0] = 0;
2006                 ret = 0;
2007             }
2008         }
2009
2010         /* We have another special case for delete key (XK_Delete) on an
2011          extended keyboard. X returns a char for it, but Windows doesn't */
2012         if (keysym == XK_Delete)
2013         {
2014             lpChar[0] = 0;
2015             ret = 0;
2016         }
2017         else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
2018                 && (keysym == XK_KP_Decimal))
2019         {
2020             lpChar[0] = 0;
2021             ret = 0;
2022         }
2023
2024         /* perform translation to unicode */
2025         if(ret)
2026         {
2027             TRACE_(key)("Translating char 0x%02x to unicode\n", *(BYTE *)lpChar);
2028             ret = MultiByteToWideChar(CP_UNIXCP, 0, lpChar, ret, bufW, bufW_size);
2029         }
2030     }
2031
2032 found:
2033     TRACE_(key)("ToUnicode about to return %d with char %x %s\n",
2034                 ret, (ret && bufW) ? bufW[0] : 0, bufW ? "" : "(no buffer)");
2035     return ret;
2036 }
2037
2038 /***********************************************************************
2039  *              Beep (X11DRV.@)
2040  */
2041 void X11DRV_Beep(void)
2042 {
2043   TSXBell(thread_display(), 0);
2044 }