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