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