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