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