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