VirtualBox

source: vbox/trunk/src/VBox/Frontends/VirtualBox/src/linux/keyboard.c@ 5049

Last change on this file since 5049 was 5049, checked in by vboxsync, 17 years ago

Added support for the British international keyboard to the Linux host GUI

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 112.9 KB
Line 
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
24 */
25
26/* our master define to make this module usable outside of Wine */
27#define OUTOFWINE
28
29#ifdef OUTOFWINE
30#include "keyboard_outofwine.h"
31/* I don't see any advantage for us of using Xkb here. The only effect of it in
32 the code is to cause the keyboard symbols we are looking up to be translated
33 according to the locale, so that we potentially need additional look-up tables
34 for ambiguous situations (or the translation can fail if the combination of
35 locale and keyboard does not match). */
36int use_xkb = 0;
37#endif /* OUTOFWINE defined */
38
39#ifndef OUTOFWINE
40#include "config.h"
41#endif /* OUTOFWINE not defined */
42
43#include <X11/Xatom.h>
44#include <X11/keysym.h>
45#include <X11/Xlib.h>
46#include <X11/Xresource.h>
47#include <X11/Xutil.h>
48#ifdef HAVE_X11_XKBLIB_H
49#include <X11/XKBlib.h>
50#endif
51
52#include <ctype.h>
53#include <stdarg.h>
54#include <string.h>
55
56#ifndef OUTOFWINE
57#define NONAMELESSUNION
58#define NONAMELESSSTRUCT
59#include "windef.h"
60#include "winbase.h"
61#include "wingdi.h"
62#include "winuser.h"
63#include "wine/winuser16.h"
64#include "winnls.h"
65#include "win.h"
66#include "x11drv.h"
67#include "wine/server.h"
68#include "wine/unicode.h"
69#include "wine/debug.h"
70
71WINE_DEFAULT_DEBUG_CHANNEL(keyboard);
72WINE_DECLARE_DEBUG_CHANNEL(key);
73
74typedef union
75{
76 struct
77 {
78#ifndef BITFIELDS_BIGENDIAN
79 unsigned long count : 16;
80#endif
81 unsigned long code : 8;
82 unsigned long extended : 1;
83 unsigned long unused : 2;
84 unsigned long win_internal : 2;
85 unsigned long context : 1;
86 unsigned long previous : 1;
87 unsigned long transition : 1;
88#ifdef BITFIELDS_BIGENDIAN
89 unsigned long count : 16;
90#endif
91 } lp1;
92 unsigned long lp2;
93} KEYLP;
94
95/* key state table bits:
96 0x80 -> key is pressed
97 0x40 -> key got pressed since last time
98 0x01 -> key is toggled
99*/
100BYTE key_state_table[256];
101
102static BYTE TrackSysKey = 0; /* determine whether ALT key up will cause a WM_SYSKEYUP
103 or a WM_KEYUP message */
104#endif
105
106static int min_keycode, max_keycode, keysyms_per_keycode;
107
108#ifndef OUTOFWINE
109static WORD keyc2vkey[256], keyc2scan[256];
110
111static int NumLockMask, AltGrMask; /* mask in the XKeyEvent state */
112static int kcControl, kcAlt, kcShift, kcNumLock, kcCapsLock; /* keycodes */
113#else
114static WORD keyc2scan[256];
115#endif
116
117static char KEYBOARD_MapDeadKeysym(KeySym keysym);
118
119/* Keyboard translation tables */
120#define MAIN_LEN 49
121static const WORD main_key_scan_qwerty[MAIN_LEN] =
122{
123/* this is my (102-key) keyboard layout, sorry if it doesn't quite match yours */
124 /* ` 1 2 3 4 5 6 7 8 9 0 - = */
125 0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
126 /* q w e r t y u i o p [ ] */
127 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
128 /* a s d f g h j k l ; ' \ */
129 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
130 /* z x c v b n m , . / */
131 0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
132 0x56 /* the 102nd key (actually to the right of l-shift) */
133};
134
135static const WORD main_key_scan_abnt_qwerty[MAIN_LEN] =
136{
137 /* ` 1 2 3 4 5 6 7 8 9 0 - = */
138 0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
139 /* q w e r t y u i o p [ ] */
140 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
141 /* a s d f g h j k l ; ' \ */
142 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
143#ifndef OUTOFWINE
144 /* \ z x c v b n m , . / */
145 0x5e,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
146 0x56, /* the 102nd key (actually to the right of l-shift) */
147#else
148/* innotek FIX */
149 /* \ z x c v b n m , . / */
150 0x56,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
151 0x73, /* the extra key on the Brazilian keyboard. */
152#endif
153};
154
155#ifndef OUTOFWINE
156/* innotek FIX - a dvorak keyboard uses standard scan codes. */
157static const WORD main_key_scan_dvorak[MAIN_LEN] =
158{
159 /* ` 1 2 3 4 5 6 7 8 9 0 [ ] */
160 0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x1A,0x1B,
161 /* ' , . p y f g c r l / = */
162 0x28,0x33,0x34,0x19,0x15,0x21,0x22,0x2E,0x13,0x26,0x35,0x0D,
163 /* a o e u i d h t n s - \ */
164 0x1E,0x18,0x12,0x16,0x17,0x20,0x23,0x14,0x31,0x1F,0x0C,0x2B,
165 /* ; q j k x b m w v z */
166 0x27,0x10,0x24,0x25,0x2D,0x30,0x32,0x11,0x2F,0x2C,
167 0x56 /* the 102nd key (actually to the right of l-shift) */
168};
169#endif
170
171#ifdef OUTOFWINE
172/* Not FIXed as it should still work, even though it is completely unnecessary. */
173/* What is this supposed to be? This is just the same as the qwerty layout, with one key
174 in a different place. */
175#endif
176static const WORD main_key_scan_qwerty_jp106[MAIN_LEN] =
177{
178 /* this is my (106-key) keyboard layout, sorry if it doesn't quite match yours */
179 /* 1 2 3 4 5 6 7 8 9 0 - ^ \ */
180 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x29,
181 /* q w e r t y u i o p @ [ */
182 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
183 /* a s d f g h j k l ; : ] */
184 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
185 /* z x c v b n m , . / */
186 0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
187 0x56 /* the 102nd key (actually to the right of l-shift) */
188};
189
190
191static const WORD main_key_vkey_qwerty[MAIN_LEN] =
192{
193/* NOTE: this layout must concur with the scan codes layout above */
194 VK_OEM_3,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS,VK_OEM_PLUS,
195 'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_4,VK_OEM_6,
196 'A','S','D','F','G','H','J','K','L',VK_OEM_1,VK_OEM_7,VK_OEM_5,
197 'Z','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
198 VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
199};
200
201static const WORD main_key_vkey_qwerty_jp106[MAIN_LEN] =
202{
203/* NOTE: this layout must concur with the scan codes layout above */
204 '1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS,VK_OEM_PLUS,VK_OEM_3,
205 'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_4,VK_OEM_6,
206 'A','S','D','F','G','H','J','K','L',VK_OEM_1,VK_OEM_7,VK_OEM_5,
207 'Z','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
208 VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
209};
210
211static const WORD main_key_vkey_qwerty_v2[MAIN_LEN] =
212{
213/* NOTE: this layout must concur with the scan codes layout above */
214 VK_OEM_5,'1','2','3','4','5','6','7','8','9','0',VK_OEM_PLUS,VK_OEM_4,
215 'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_6,VK_OEM_1,
216 'A','S','D','F','G','H','J','K','L',VK_OEM_3,VK_OEM_7,VK_OEM_2,
217 'Z','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_MINUS,
218 VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
219};
220
221static const WORD main_key_vkey_qwertz[MAIN_LEN] =
222{
223/* NOTE: this layout must concur with the scan codes layout above */
224 VK_OEM_3,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS,VK_OEM_PLUS,
225 'Q','W','E','R','T','Z','U','I','O','P',VK_OEM_4,VK_OEM_6,
226 'A','S','D','F','G','H','J','K','L',VK_OEM_1,VK_OEM_7,VK_OEM_5,
227 'Y','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
228 VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
229};
230
231static const WORD main_key_vkey_qwertz_105[MAIN_LEN] =
232{
233/* NOTE: this layout must concur with the scan codes layout above */
234 VK_OEM_3,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS,VK_OEM_PLUS,
235 'Q','W','E','R','T','Z','U','I','O','P',VK_OEM_4,VK_OEM_6,
236 'A','S','D','F','G','H','J','K','L',VK_OEM_1,VK_OEM_7,VK_OEM_5,
237 VK_OEM_102,'Y','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2
238};
239
240static const WORD main_key_vkey_abnt_qwerty[MAIN_LEN] =
241{
242/* NOTE: this layout must concur with the scan codes layout above */
243 VK_OEM_3,'1','2','3','4','5','6','7','8','9','0',VK_OEM_MINUS,VK_OEM_PLUS,
244 'Q','W','E','R','T','Y','U','I','O','P',VK_OEM_4,VK_OEM_6,
245 'A','S','D','F','G','H','J','K','L',VK_OEM_1,VK_OEM_8,VK_OEM_5,
246 VK_OEM_7,'Z','X','C','V','B','N','M',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
247 VK_OEM_102, /* the 102nd key (actually to the right of l-shift) */
248};
249
250static const WORD main_key_vkey_azerty[MAIN_LEN] =
251{
252/* NOTE: this layout must concur with the scan codes layout above */
253 VK_OEM_7,'1','2','3','4','5','6','7','8','9','0',VK_OEM_4,VK_OEM_PLUS,
254 'A','Z','E','R','T','Y','U','I','O','P',VK_OEM_6,VK_OEM_1,
255 'Q','S','D','F','G','H','J','K','L','M',VK_OEM_3,VK_OEM_5,
256 'W','X','C','V','B','N',VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,VK_OEM_8,
257 VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
258};
259
260static const WORD main_key_vkey_dvorak[MAIN_LEN] =
261{
262/* NOTE: this layout must concur with the scan codes layout above */
263 VK_OEM_3,'1','2','3','4','5','6','7','8','9','0',VK_OEM_4,VK_OEM_6,
264 VK_OEM_7,VK_OEM_COMMA,VK_OEM_PERIOD,'P','Y','F','G','C','R','L',VK_OEM_2,VK_OEM_PLUS,
265 'A','O','E','U','I','D','H','T','N','S',VK_OEM_MINUS,VK_OEM_5,
266 VK_OEM_1,'Q','J','K','X','B','M','W','V','Z',
267 VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
268};
269
270/*** DEFINE YOUR NEW LANGUAGE-SPECIFIC MAPPINGS BELOW, SEE EXISTING TABLES */
271
272/* the VK mappings for the main keyboard will be auto-assigned as before,
273 so what we have here is just the character tables */
274/* order: Normal, Shift, AltGr, Shift-AltGr */
275/* We recommend you write just what is guaranteed to be correct (i.e. what's
276 written on the keycaps), not the bunch of special characters behind AltGr
277 and Shift-AltGr if it can vary among different X servers */
278/* Remember that your 102nd key (to the right of l-shift) should be on a
279 separate line, see existing tables */
280/* If Wine fails to match your new table, use WINEDEBUG=+key to find out why */
281/* Remember to also add your new table to the layout index table far below! */
282
283#ifndef OUTOFWINE
284/*** German Logitech Desktop Pro keyboard layout */
285static const char main_key_DE_logitech[MAIN_LEN][4] =
286{
287 "^\xb0","1!","2\"","3\xa7","4$","5%","6&","7/{","8([","9)]","0=}","\xdf?\\","'`",
288 "qQ@","wW","eE","rR","tT","zZ","uU","iI","oO","pP","\xfc\xdc","+*~",
289 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","\xf6\xd6","\xe4\xc4","#'",
290 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
291 "<>|"
292};
293#endif
294
295/*** United States keyboard layout (mostly contributed by Uwe Bonnes) */
296static const char main_key_US[MAIN_LEN][4] =
297{
298 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
299 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
300 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
301 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?"
302};
303
304/*** United States keyboard layout (phantom key version) */
305/* (XFree86 reports the <> key even if it's not physically there) */
306static const char main_key_US_phantom[MAIN_LEN][4] =
307{
308 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
309 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
310 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
311 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
312 "<>" /* the phantom key */
313};
314
315/*** United States keyboard layout (dvorak version) */
316static const char main_key_US_dvorak[MAIN_LEN][4] =
317{
318 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","[{","]}",
319 "'\"",",<",".>","pP","yY","fF","gG","cC","rR","lL","/?","=+",
320 "aA","oO","eE","uU","iI","dD","hH","tT","nN","sS","-_","\\|",
321 ";:","qQ","jJ","kK","xX","bB","mM","wW","vV","zZ"
322};
323
324#ifdef OUTOFWINE
325/* innotek FIX */
326/*** United States keyboard layout (dvorak version with phantom key) */
327static const char main_key_US_dvorak_phantom[MAIN_LEN][4] =
328{
329 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","[{","]}",
330 "'\"",",<",".>","pP","yY","fF","gG","cC","rR","lL","/?","=+",
331 "aA","oO","eE","uU","iI","dD","hH","tT","nN","sS","-_","\\|",
332 ";:","qQ","jJ","kK","xX","bB","mM","wW","vV","zZ",
333 "<>" /* the phantom key */
334};
335#endif
336
337/*** British keyboard layout */
338static const char main_key_UK[MAIN_LEN][4] =
339{
340 "`","1!","2\"","3£","4$","5%","6^","7&","8*","9(","0)","-_","=+",
341 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
342 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'@","#~",
343 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
344 "\\|"
345};
346
347#ifdef OUTOFWINE
348
349/*** British international keyboard layout */
350static const char main_key_UK_intl[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#endif
360
361/*** French keyboard layout (setxkbmap fr) */
362static const char main_key_FR[MAIN_LEN][4] =
363{
364 "²","&1","é2","\"3","'4","(5","-6","è7","_8","ç9","à0",")°","=+",
365 "aA","zZ","eE","rR","tT","yY","uU","iI","oO","pP","^¨","$£",
366 "qQ","sS","dD","fF","gG","hH","jJ","kK","lL","mM","ù%","*µ",
367 "wW","xX","cC","vV","bB","nN",",?",";.",":/","!§",
368 "<>"
369};
370
371/*** Icelandic keyboard layout (setxkbmap is) */
372static const char main_key_IS[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 "<>"
379};
380
381/*** German keyboard layout (setxkbmap de) */
382static const char main_key_DE[MAIN_LEN][4] =
383{
384 "^°","1!","2\"","3§","4$","5%","6&","7/","8(","9)","0=","ß?","´`",
385 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*",
386 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
387 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
388#ifndef OUTOFWINE
389 "<>|"
390#else
391 "<>"
392#endif
393};
394
395#ifndef OUTOFWINE
396/*** German keyboard layout without dead keys */
397static const char main_key_DE_nodead[MAIN_LEN][4] =
398{
399 "^°","1!","2\"","3§","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","´",
400 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
401 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
402 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
403 "<>"
404};
405#endif
406
407/*** German keyboard layout without dead keys 105 Keys (contributed by Matthias Fechner)*/
408static const char main_key_DE_nodead_105[MAIN_LEN][4] =
409{
410 "^°","1!","2\"²","3§³","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","'`",
411 "qQ@","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
412 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
413 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_", "<>|"
414};
415
416/*** Swiss German keyboard layout (setxkbmap ch -variant de) */
417static const char main_key_SG[MAIN_LEN][4] =
418{
419 "§°","1+","2\"","3*","4ç","5%","6&","7/","8(","9)","0=","'?","^`",
420 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üè","¨!",
421 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öé","äà","$£",
422 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
423 "<>"
424};
425
426/*** Swiss French keyboard layout (setxkbmap ch -variant fr) */
427static const char main_key_SF[MAIN_LEN][4] =
428{
429 "§°","1+","2\"","3*","4ç","5%","6&","7/","8(","9)","0=","'?","^`",
430 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","èü","¨!",
431 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","éö","àä","$£",
432 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
433 "<>"
434};
435
436#ifndef OUTOFWINE
437/*** Norwegian keyboard layout (contributed by Ove Kåven) */
438static const char main_key_NO[MAIN_LEN][4] =
439{
440 "|§","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?","\\`´",
441 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^~",
442 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","øØ","æÆ","'*",
443 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
444 "<>"
445};
446#else
447/* innotek FIX */
448/*** Norwegian keyboard layout (contributed by Ove Kåven) */
449static const char main_key_NO[MAIN_LEN][4] =
450{
451 "|§","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","\\`",
452 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^",
453 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","øØ","æÆ","'",
454 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
455 "<>"
456};
457#endif
458
459/*** Danish keyboard layout (setxkbmap dk) */
460static const char main_key_DA[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/*** Swedish keyboard layout (setxkbmap se) */
470static const char main_key_SE[MAIN_LEN][4] =
471{
472 "§½","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","´`",
473 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^",
474 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*",
475 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
476 "<>"
477};
478
479/*** Estonian keyboard layout (setxkbmap ee) */
480static const char main_key_ET[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#ifndef OUTOFWINE
490/*** Canadian French keyboard layout (setxkbmap ca_enhanced) */
491static const char main_key_CF[MAIN_LEN][4] =
492{
493 "#|\\","1!±","2\"@","3/£","4$¢","5%¤","6?¬","7&¦","8*²","9(³","0)¼","-_½","=+¾",
494 "qQ","wW","eE","rR","tT","yY","uU","iI","oO§","pP¶","^^[","¸¨]",
495 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:~","``{","<>}",
496 "zZ","xX","cC","vV","bB","nN","mM",",'-",".","éÉ",
497 "«»°"
498};
499#endif
500
501/*** Canadian French keyboard layout (setxkbmap ca -variant fr) */
502static const char main_key_CA_fr[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#ifndef OUTOFWINE
512/*** Canadian keyboard layout (setxkbmap ca) */
513static const char main_key_CA[MAIN_LEN][4] =
514{
515 "/\\","1!¹¡","2@²","3#³£","4$¼¤","5%½","6?¾","7&","8*","9(","0)","-_","=+",
516 "qQ","wW","eE","rR","tT","yY","uU","iI","oOøØ","pPþÞ","^¨¨","çÇ~",
517 "aAæÆ","sSߧ","dDðÐ","fF","gG","hH","jJ","kK","lL",";:´","èÈ","àÀ",
518 "zZ","xX","cC¢©","vV","bB","nN","mMµº",",'",".\"·÷","éÉ",
519 "ùÙ"
520};
521#else
522/*** Canadian keyboard layout (setxkbmap ca) */
523static const char main_key_CA[MAIN_LEN][4] =
524{
525 "/\\","1!","2@","3#","4$","5%","6?","7&","8*","9(","0)","-_","=+",
526 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","^¨","çÇ",
527 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","èÈ","àÀ",
528 "zZ","xX","cC","vV","bB","nN","mM",",'",".\"","éÉ",
529 "ùÙ"
530};
531#endif
532
533/*** Portuguese keyboard layout (setxkbmap pt) */
534static const char main_key_PT[MAIN_LEN][4] =
535{
536 "\\|","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","«»",
537 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","+*","´`",
538 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","çÇ","ºª","~^",
539 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
540 "<>"
541};
542
543/*** Italian keyboard layout (setxkbmap it) */
544static const char main_key_IT[MAIN_LEN][4] =
545{
546 "\\|","1!","2\"","3£","4$","5%","6&","7/","8(","9)","0=","'?","ì^",
547 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","èé","+*",
548 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","òç","à°","ù§",
549 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
550 "<>"
551};
552
553/*** Finnish keyboard layout (setxkbmap fi) */
554static const char main_key_FI[MAIN_LEN][4] =
555{
556 "§½","1!","2\"","3#","4¤","5%","6&","7/","8(","9)","0=","+?","´`",
557 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^",
558 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*",
559 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
560 "<>"
561};
562
563#ifndef OUTOFWINE
564/*** Bulgarian bds keyboard layout */
565static const char main_key_BG_bds[MAIN_LEN][4] =
566{
567 "`~()","1!","2@2?","3#3+","4$4\"","5%","6^6=","7&7:","8*8/","9(","0)","-_-I","=+.V",
568 "qQ,û","wWóÓ","eEåÅ","rRèÈ","tTøØ","yYùÙ","uUêÊ","iIñÑ","oOäÄ","pPçÇ","[{öÖ","]};",
569 "aAüÜ","sSÿß","dDàÀ","fFîÎ","gGæÆ","hHãÃ","jJòÒ","kKíÍ","lLâÂ",";:ìÌ","'\"÷×","\\|'Û",
570 "zZþÞ","xXéÉ","cCúÚ","vVýÝ","bBôÔ","nNõÕ","mMïÏ",",<ðÐ",".>ëË","/?áÁ",
571 "<>" /* the phantom key */
572};
573
574/*** Bulgarian phonetic keyboard layout */
575static const char main_key_BG_phonetic[MAIN_LEN][4] =
576{
577 "`~÷×","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
578 "qQÿß","wWâÂ","eEåÅ","rRðÐ","tTòÒ","yYúÚ","uUóÓ","iIèÈ","oOîÎ","pPïÏ","[{øØ","]}ùÙ",
579 "aAàÀ","sSñÑ","dDäÄ","fFôÔ","gGãÃ","hHõÕ","jJéÉ","kKêÊ","lLëË",";:","'\"","\\|þÞ",
580 "zZçÇ","xXüÜ","cCöÖ","vVæÆ","bBáÁ","nNíÍ","mMìÌ",",<",".>","/?",
581 "<>" /* the phantom key */
582};
583
584/*** Belarusian standard keyboard layout (contributed by Hleb Valoska) */
585/*** It matches belarusian layout for XKB from Alexander Mikhailian */
586static const char main_key_BY[MAIN_LEN][4] =
587{
588 "`~£³","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
589 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oO®¾","pPÚú","[{Èè","]}''",
590 "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|/|",
591 "zZÑñ","xXÞþ","cCÓó","vVÍí","bB¦¶","nNÔô","mMØø",",<Ââ",".>Àà","/?.,", "<>|¦",
592};
593#else
594/*** Bulgarian bds keyboard layout */
595static const char main_key_BG_bds[MAIN_LEN][4] =
596{
597 "()","1!","2?","3+","4\"","5%","6=","7:","8/","9\xa9","0\xb0","-I",".V",
598 ",\xd9","\xd5\xf5","\xc5\xe5","\xc9\xe9","\xdb\xfb","\xdd\xfd","\xcb\xeb","\xd3\xf3","\xc4\xe4","\xda\xfa","\xc3\xe3",";\xa7",
599 "\xd8\xf8","\xd1\xf1","\xc1\xe1","\xcf\xef","\xd6\xf6","\xc7\xe7","\xd4\xf4","\xce\xee","\xd7\xf7","\xcd\xed","\xde\xfe","'\xf9",
600 "\xc0\xe0","\xca\xea","\xdf\xff","\xdc\xfc","\xc6\xe6","\xc8\xe8","\xd0\xf0","\xd2\xf2","\xcc\xec","\xc2\xe2",
601 "<>" /* the phantom key */
602};
603
604/*** Bulgarian phonetic keyboard layout */
605static const char main_key_BG_phonetic[MAIN_LEN][4] =
606{
607 "\xde\xfe","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
608 "\xd1\xf1","\xd7\xf7","\xc5\xe5","\xd2\xf2","\xd4\xf4","\xdf\xff","\xd5\xf5","\xc9\xe9","\xcf\xef","\xd0\xf0","\xdb\xfb","\xdd\xfd",
609 "\xc1\xe1","\xd3\xf3","\xc4\xe4","\xc6\xe6","\xc7\xe7","\xc8\xe8","\xca\xea","\xcb\xeb","\xcc\xec",";:","'\"","\xc0\xe0",
610 "\xda\xfa","\xd8\xf8","\xc3\xe3","\xd6\xf6","\xc2\xe2","\xce\xee","\xcd\xed",",<",".>","/?",
611 "<>" /* the phantom key */
612};
613
614/*** Belarusian standard keyboard layout (contributed by Hleb Valoska) */
615/*** It matches belarusian layout for XKB from Alexander Mikhailian */
616static const char main_key_BY[MAIN_LEN][4] =
617{
618 "£³","1!","2\"","3#","4;","5%","6:","7?","8*","9(","0)","-_","=+",
619 "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","®¾","Úú","Èè","''",
620 "Ææ","Ùù","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","Üü","/|",
621 "Ññ","Þþ","Óó","Íí","¦¶","Ôô","Øø","Ââ","Àà",".,", "|¦",
622};
623#endif
624
625
626#ifndef OUTOFWINE
627/*** Russian keyboard layout (contributed by Pavel Roskin) */
628static const char main_key_RU[MAIN_LEN][4] =
629{
630 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
631 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}ßÿ",
632 "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|",
633 "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?"
634};
635
636/*** Russian keyboard layout (phantom key version) */
637static const char main_key_RU_phantom[MAIN_LEN][4] =
638{
639 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
640 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}ßÿ",
641 "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|",
642 "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?",
643 "<>" /* the phantom key */
644};
645
646/*** Russian keyboard layout KOI8-R */
647static const char main_key_RU_koi8r[MAIN_LEN][4] =
648{
649 "()","1!","2\"","3/","4$","5:","6,","7.","8;","9?","0%","-_","=+",
650 "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","ßÿ",
651 "Ææ","Ùù","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","Üü","\\|",
652 "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà","/?",
653 "<>" /* the phantom key */
654};
655#else
656/*** Russian keyboard layout KOI8-R */
657static const char main_key_RU_koi8r[MAIN_LEN][4] =
658{
659 "£³","1!","2\"","3#","4*","5:","6,","7.","8;","9(","0)","-_","=+",
660 "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","ßÿ",
661 "Ææ","Ùù","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","Üü","\\|",
662 "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà","/?",
663 "/|" /* the phantom key */
664};
665#endif
666
667#ifndef OUTOFWINE
668/*** Russian keyboard layout cp1251 */
669static const char main_key_RU_cp1251[MAIN_LEN][4] =
670{
671 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
672 "qQéÉ","wWöÖ","eEóÓ","rRêÊ","tTåÅ","yYíÍ","uUãÃ","iIøØ","oOùÙ","pPçÇ","[{õÕ","]}úÚ",
673 "aAôÔ","sSûÛ","dDâÂ","fFàÀ","gGïÏ","hHðÐ","jJîÎ","kKëË","lLäÄ",";:æÆ","'\"ýÝ","\\|",
674 "zZÿß","xX÷×","cCñÑ","vVìÌ","bBèÈ","nNòÒ","mMüÜ",",<áÁ",".>þÞ","/?",
675 "<>" /* the phantom key */
676};
677
678/*** Russian phonetic keyboard layout */
679static const char main_key_RU_phonetic[MAIN_LEN][4] =
680{
681 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
682 "qQÑñ","wW×÷","eEÅå","rRÒò","tTÔô","yYÙù","uUÕõ","iIÉé","oOÏï","pPÐð","[{Ûû","]}Ýý",
683 "aAÁá","sSÓó","dDÄä","fFÆæ","gGÇç","hHÈè","jJÊê","kKËë","lLÌì",";:","'\"","\\|",
684 "zZÚú","xXØø","cCÃã","vVÖö","bBÂâ","nNÎî","mMÍí",",<",".>","/?",
685 "<>" /* the phantom key */
686};
687#else
688/*** Russian phonetic keyboard layout */
689static const char main_key_RU_phonetic[MAIN_LEN][4] =
690{
691 "Àà","1!","2@","3£","4³","5ß","6ÿ","7&","8*","9(","0)","-_","Þþ",
692 "Ññ","×÷","Åå","Òò","Ôô","Ùù","Õõ","Éé","Ïï","Ðð","Ûû","Ýý",
693 "Áá","Óó","Ää","Ææ","Çç","Èè","Êê","Ëë","Ìì",";:","'\"","Üü",
694 "Úú","Øø","Ãã","Öö","Ââ","Îî","Íí",",<",".>","/?",
695 "|¦" /* the phantom key */
696};
697#endif
698
699#ifndef OUTOFWINE
700/*** Ukrainian keyboard layout KOI8-U */
701static const char main_key_UA[MAIN_LEN][4] =
702{
703 "`~­½","1!1!","2@2\"","3#3'","4$4*","5%5:","6^6,","7&7.","8*8;","9(9(","0)0)","-_-_","=+=+",
704 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}§·",
705 "aAÆæ","sS¦¶","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"¤´","\\|\\|",
706 "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?/?",
707 "<>" /* the phantom key */
708};
709#else
710/*** Ukrainian keyboard layout KOI8-U */
711static const char main_key_UA[MAIN_LEN][4] =
712{
713 "­½","1!","2\"","3#","4*","5:","6,","7.","8;","9(","0)","-_","=+",
714 "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","§·",
715 "Ææ","¦¶","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","¤´","\\|",
716 "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà","/?",
717 "<>" /* the phantom key */
718};
719#endif
720
721/*** Ukrainian keyboard layout KOI8-U by O. Nykyforchyn */
722/*** (as it appears on most of keyboards sold today) */
723static const char main_key_UA_std[MAIN_LEN][4] =
724{
725 "­½","1!","2\"","3'","4;","5%","6:","7?","8*","9(","0)","-_","=+",
726 "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","§·",
727 "Ææ","¦¶","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","¤´","\\/",
728 "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà",".,",
729 "<>" /* the phantom key */
730};
731
732/*** Russian keyboard layout KOI8-R (pair to the previous) */
733static const char main_key_RU_std[MAIN_LEN][4] =
734{
735 "£³","1!","2\"","3'","4;","5%","6:","7?","8*","9(","0)","-_","=+",
736 "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","ßÿ",
737 "Ææ","Ùù","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","Üü","\\/",
738 "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà",".,",
739 "<>" /* the phantom key */
740};
741
742/*** Spanish keyboard layout (setxkbmap es) */
743static const char main_key_ES[MAIN_LEN][4] =
744{
745 "ºª","1!","2\"","3·","4$","5%","6&","7/","8(","9)","0=","'?","¡¿",
746 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","`^","+*",
747 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ñÑ","´¨","çÇ",
748 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
749 "<>"
750};
751
752/*** Belgian keyboard layout ***/
753static const char main_key_BE[MAIN_LEN][4] =
754{
755#ifndef OUTOFWINE
756 "","&1|","é2@","\"3#","'4","(5","§6^","è7","!8","ç9{","à0}",")°","-_",
757 "aA","zZ","eE¤","rR","tT","yY","uU","iI","oO","pP","^¨[","$*]",
758 "qQ","sSß","dD","fF","gG","hH","jJ","kK","lL","mM","ù%´","µ£`",
759 "wW","xX","cC","vV","bB","nN",",?",";.",":/","=+~",
760 "<>\\"
761#else
762/* innotek FIX */
763/* I wonder how much of this Wine code has been properly tested? There are many
764 seemingly duplicate layouts, and while many specify three or four keysyms per
765 key, the code choked on all keys in this layout containing more than two
766 keysyms. I suspect that many of these maps only work by luck. */
767 "²³","&1","é2","\"3","'4","(5","§6","è7","!8","ç9","à0",")°","-_",
768 "aA","zZ","eE","rR","tT","yY","uU","iI","oO","pP","^¨","$*",
769 "qQ","sS","dD","fF","gG","hH","jJ","kK","lL","mM","ù%","µ£",
770 "wW","xX","cC","vV","bB","nN",",?",";.",":/","=+",
771 "<>"
772#endif
773};
774
775/*** Hungarian keyboard layout (setxkbmap hu) */
776static const char main_key_HU[MAIN_LEN][4] =
777{
778 "0§","1'","2\"","3+","4!","5%","6/","7=","8(","9)","öÖ","üÜ","óÓ",
779 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","õÕ","úÚ",
780 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","éÉ","áÁ","ûÛ",
781 "yY","xX","cC","vV","bB","nN","mM",",?",".:","-_",
782 "íÍ"
783};
784
785/*** Polish (programmer's) keyboard layout ***/
786static const char main_key_PL[MAIN_LEN][4] =
787{
788 "`~","1!","2@","3#","4$","5%","6^","7&§","8*","9(","0)","-_","=+",
789 "qQ","wW","eEêÊ","rR","tT","yY","uU","iI","oOóÓ","pP","[{","]}",
790 "aA±¡","sS¶¦","dD","fF","gG","hH","jJ","kK","lL³£",";:","'\"","\\|",
791 "zZ¿¯","xX¼¬","cCæÆ","vV","bB","nNñÑ","mM",",<",".>","/?",
792 "<>|"
793};
794
795/*** Slovenian keyboard layout (setxkbmap si) ***/
796static const char main_key_SI[MAIN_LEN][4] =
797{
798 "¸¨","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","+*",
799 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","¹©","ðÐ",
800 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","èÈ","æÆ","¾®",
801 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
802 "<>"
803};
804
805/*** Serbian keyboard layout (setxkbmap sr) ***/
806static const char main_key_SR[MAIN_LEN][4] =
807{
808 "`~","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","+*",
809 "©¹","ªº","Åå","Òò","Ôô","Úú","Õõ","Éé","Ïï","Ðð","Ûû","[]",
810 "Áá","Óó","Ää","Ææ","Çç","Èè","¨¸","Ëë","Ìì","Þþ","«»","-_",
811 "¡±","¯¿","Ãã","×÷","Ââ","Îî","Íí",",;",".:","Öö",
812 "<>" /* the phantom key */
813};
814
815/*** Serbian keyboard layout (setxkbmap us,sr) ***/
816static const char main_key_US_SR[MAIN_LEN][4] =
817{
818 "`~","1!","2@2\"","3#","4$","5%","6^6&","7&7/","8*8(","9(9)","0)0=","-_'?","=++*",
819 "qQ©¹","wWªº","eEÅå","rRÒò","tTÔô","yYÚú","uUÕõ","iIÉé","oOÏï","pPÐð","[{Ûû","]}[]",
820 "aAÁá","sSÓó","dDÄä","fFÆæ","gGÇç","hHÈè","jJ¨¸","kKËë","lLÌì",";:Þþ","'\"«»","\\|-_",
821 "zZ¡±","xX¯¿","cCÃã","vV×÷","bBÂâ","nNÎî","mMÍí",",<,;",".>.:","/?Öö",
822 "<>" /* the phantom key */
823};
824
825/*** Croatian keyboard layout specific for me <jelly@srk.fer.hr> ***/
826static const char main_key_HR_jelly[MAIN_LEN][4] =
827{
828 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
829 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{¹©","]}ðÐ",
830 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:èÈ","'\"æÆ","\\|¾®",
831 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
832 "<>|"
833};
834
835/*** Croatian keyboard layout (setxkbmap hr) ***/
836static const char main_key_HR[MAIN_LEN][4] =
837{
838 "¸¨","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","+*",
839 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","¹©","ðÐ",
840 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","èÈ","æÆ","¾®",
841 "yY","xX","cC","vV","bB","nN","mM",",;",".:","/?",
842 "<>"
843};
844
845/*** Japanese 106 keyboard layout ***/
846static const char main_key_JA_jp106[MAIN_LEN][4] =
847{
848 "1!","2\"","3#","4$","5%","6&","7'","8(","9)","0~","-=","^~","\\|",
849 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","@`","[{",
850 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";+",":*","]}",
851 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
852 "\\_",
853};
854
855/*** Japanese pc98x1 keyboard layout ***/
856static const char main_key_JA_pc98x1[MAIN_LEN][4] =
857{
858 "1!","2\"","3#","4$","5%","6&","7'","8(","9)","0","-=","^`","\\|",
859 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","@~","[{",
860 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";+",":*","]}",
861 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
862 "\\_",
863};
864
865/*** Brazilian ABNT-2 keyboard layout (contributed by Raul Gomes Fernandes) */
866static const char main_key_PT_br[MAIN_LEN][4] =
867{
868 "'\"","1!","2@","3#","4$","5%","6¨","7&","8*","9(","0)","-_","=+",
869 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","´`","[{",
870 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","çÇ","~^","]}",
871 "\\|","zZ","xX","cC","vV","bB","nN","mM",",<",".>",";:","/?",
872};
873
874/*** Brazilian ABNT-2 keyboard layout with <ALT GR> (contributed by Mauro Carvalho Chehab) */
875static const char main_key_PT_br_alt_gr[MAIN_LEN][4] =
876{
877 "'\"","1!9","2@2","3#3","4$#","5%\"","6(,","7&","8*","9(","0)","-_","=+'",
878 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","4`","[{*",
879 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","gG","~^","]}:",
880 "\\|","zZ","xX","cC","vV","bB","nN","mM",",<",".>",";:","/?0"
881};
882
883#ifndef OUTOFWINE
884/*** US international keyboard layout (contributed by Gustavo Noronha (kov@debian.org)) */
885static const char main_key_US_intl[MAIN_LEN][4] =
886{
887 "`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+", "\\|",
888 "qQ", "wW", "eE", "rR", "tT", "yY", "uU", "iI", "oO", "pP", "[{", "]}",
889 "aA", "sS", "dD", "fF", "gG", "hH", "jJ", "kK", "lL", ";:", "'\"",
890 "zZ", "xX", "cC", "vV", "bB", "nN", "mM", ",<", ".>", "/?"
891};
892#else
893/* innotek FIX */
894/*** US international keyboard layout (contributed by Gustavo Noronha (kov@debian.org)) */
895static const char main_key_US_intl[MAIN_LEN][4] =
896{
897 "`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+",
898 "qQ", "wW", "eE", "rR", "tT", "yY", "uU", "iI", "oO", "pP", "[{", "]}",
899 "aA", "sS", "dD", "fF", "gG", "hH", "jJ", "kK", "lL", ";:", "´¨",
900 "\\|", "zZ", "xX", "cC", "vV", "bB", "nN", "mM", ",<", ".>", "/?"
901};
902
903/*** US international keyboard layout with phantom key (contributed by Gustavo Noronha (kov@debian.org)) */
904static const char main_key_US_intl_phantom[MAIN_LEN][4] =
905{
906 "`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+",
907 "qQ", "wW", "eE", "rR", "tT", "yY", "uU", "iI", "oO", "pP", "[{", "]}",
908 "aA", "sS", "dD", "fF", "gG", "hH", "jJ", "kK", "lL", ";:", "´¨",
909 "\\|", "zZ", "xX", "cC", "vV", "bB", "nN", "mM", ",<", ".>", "/?",
910 "<>" /* the phantom key */
911};
912#endif
913
914/*** Slovak keyboard layout (see cssk_ibm(sk_qwerty) in xkbsel)
915 - dead_abovering replaced with degree - no symbol in iso8859-2
916 - brokenbar replaced with bar */
917static const char main_key_SK[MAIN_LEN][4] =
918{
919 ";0","+1","µ2","¹3","è4","»5","¾6","ý7","á8","í9","é0","=%","'v",
920 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","ú/","ä(",
921 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",\"","§!","ò)",
922 "zZ","xX","cC","vV","bB","nN","mM",",?",".:","-_",
923 "<>"
924};
925
926/*** Czech keyboard layout (setxkbmap cz) */
927static const char main_key_CZ[MAIN_LEN][4] =
928{
929 ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0","=%","´·",
930 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","ú/",")(",
931 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",\"","§!","¨'",
932 "yY","xX","cC","vV","bB","nN","mM",",?",".:","-_",
933 "\\"
934};
935
936/*** Czech keyboard layout (setxkbmap cz_qwerty) */
937static const char main_key_CZ_qwerty[MAIN_LEN][4] =
938{
939 ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0","=%","´·",
940 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","ú/",")(",
941 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",\"","§!","¨'",
942 "zZ","xX","cC","vV","bB","nN","mM",",?",".:","-_",
943 "\\"
944};
945
946/*** Slovak and Czech (programmer's) keyboard layout (see cssk_dual(cs_sk_ucw)) */
947static const char main_key_SK_prog[MAIN_LEN][4] =
948{
949 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
950 "qQäÄ","wWìÌ","eEéÉ","rRøØ","tT»«","yYýÝ","uUùÙ","iIíÍ","oOóÓ","pPöÖ","[{","]}",
951 "aAáÁ","sS¹©","dDïÏ","fFëË","gGàÀ","hHúÚ","jJüÜ","kKôÔ","lLµ¥",";:","'\"","\\|",
952 "zZ¾®","xX¤","cCèÈ","vVçÇ","bB","nNòÒ","mMåÅ",",<",".>","/?",
953 "<>"
954};
955
956/*** Czech keyboard layout (see cssk_ibm(cs_qwerty) in xkbsel) */
957static const char main_key_CS[MAIN_LEN][4] =
958{
959 ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0½)","=%","",
960 "qQ\\","wW|","eE","rR","tT","yY","uU","iI","oO","pP","ú/[{",")(]}",
961 "aA","sSð","dDÐ","fF[","gG]","hH","jJ","kK³","lL£",\"$","§!ß","¨'",
962 "zZ>","xX#","cC&","vV@","bB{","nN}","mM",",?<",".:>","-_*",
963 "<>\\|"
964};
965
966/*** Latin American keyboard layout (contributed by Gabriel Orlando Garcia) */
967static const char main_key_LA[MAIN_LEN][4] =
968{
969 "|°","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?","¿¡",
970 "qQ@","wW","eE","rR","tT","yY","uU","iI","oO","pP","´¨","+*",
971 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ñÑ","{[^","}]",
972 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
973 "<>"
974};
975
976/*** Lithuanian keyboard layout (setxkbmap lt) */
977static const char main_key_LT_B[MAIN_LEN][4] =
978{
979 "`~","àÀ","èÈ","æÆ","ëË","áÁ","ðÐ","øØ","ûÛ","¥(","´)","-_","þÞ","\\|",
980 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
981 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"",
982 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
983 "ª¬"
984};
985
986/*** Turkish keyboard Layout */
987static const char main_key_TK[MAIN_LEN][4] =
988{
989"\"é","1!","2'","3^#","4+$","5%","6&","7/{","8([","9)]","0=}","*?\\","-_",
990"qQ@","wW","eE","rR","tT","yY","uU","ýIî","oO","pP","ðÐ","üÜ~",
991"aAæ","sSß","dD","fF","gG","hH","jJ","kK","lL","þÞ","iÝ",",;`",
992"zZ","xX","cC","vV","bB","nN","mM","öÖ","çÇ",".:"
993};
994
995/*** Turkish keyboard layout (setxkbmap tr) */
996static const char main_key_TR[MAIN_LEN][4] =
997{
998"\"\\","1!","2'","3^","4+","5%","6&","7/","8(","9)","0=","*?","-_",
999"qQ","wW","eE","rR","tT","yY","uU","\xb9I","oO","pP","\xbb\xab","üÜ",
1000"aA","sS","dD","fF","gG","hH","jJ","kK","lL","\xba\xaa","i\0",",;",
1001"zZ","xX","cC","vV","bB","nN","mM","öÖ","çÇ",".:",
1002"<>"
1003};
1004
1005/*** Turkish F keyboard layout (setxkbmap trf) */
1006static const char main_key_TR_F[MAIN_LEN][4] =
1007{
1008"+*","1!","2\"","3^#","4$","5%","6&","7'","8(","9)","0=","/?","-_",
1009"fF","gG","\xbb\xab","\xb9I","oO","dD","rR","nN","hH","pP","qQ","wW",
1010"uU","i\0","eE","aA","üÜ","tT","kK","mM","lL","yY","\xba\xaa","xX",
1011"jJ","öÖ","vV","cC","çÇ","zZ","sS","bB",".:",",;",
1012"<>"
1013};
1014
1015/*** Israelian keyboard layout (setxkbmap us,il) */
1016static const char main_key_IL[MAIN_LEN][4] =
1017{
1018 "`~;","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
1019 "qQ/","wW'","eE÷","rRø","tTà","yYè","uUå","iIï","oOí","pPô","[{","]}",
1020 "aAù","sSã","dDâ","fFë","gGò","hHé","jJç","kKì","lLê",";:ó","\'\",","\\|",
1021 "zZæ","xXñ","cCá","vVä","bBð","nNî","mMö",",<ú",".>õ","/?.",
1022 "<>"
1023};
1024
1025/*** Israelian phonetic keyboard layout (setxkbmap us,il_phonetic) */
1026static const char main_key_IL_phonetic[MAIN_LEN][4] =
1027{
1028 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
1029 "qQ÷","wWå","eEà","rRø","tTú","yYò","uUå","iIé","oOñ","pPô","[{","]}",
1030 "aAà","sSù","dDã","fFô","gGâ","hHä","jJé","kKë","lLì",";:","'\"","\\|",
1031 "zZæ","xXç","cCö","vVå","bBá","nNð","mMî",",<",".>","/?",
1032 "<>"
1033};
1034
1035/*** Israelian Saharon keyboard layout (setxkbmap -symbols "us(pc105)+il_saharon") */
1036static const char main_key_IL_saharon[MAIN_LEN][4] =
1037{
1038 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
1039 "qQ÷","wWñ","eE","rRø","tTè","yYã","uU","iI","oO","pPô","[{","]}",
1040 "aAà","sSå","dDì","fFú","gGâ","hHä","jJù","kKë","lLé",";:","'\"","\\|",
1041 "zZæ","xXç","cCö","vVò","bBá","nNð","mMî",",<",".>","/?",
1042 "<>"
1043};
1044
1045/*** Greek keyboard layout (contributed by Kriton Kyrimis <kyrimis@cti.gr>)
1046 Greek characters for "wW" and "sS" are omitted to not produce a mismatch
1047 message since they have different characters in gr and el XFree86 layouts. */
1048static const char main_key_EL[MAIN_LEN][4] =
1049{
1050 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
1051 "qQ;:","wW","eEåÅ","rRñÑ","tTôÔ","yYõÕ","uUèÈ","iIéÉ","oOïÏ","pPðÐ","[{","]}",
1052 "aAáÁ","sS","dDäÄ","fFöÖ","gGãÃ","hHçÇ","jJîÎ","kKêÊ","lLëË",";:´¨","'\"","\\|",
1053 "zZæÆ","xX÷×","cCøØ","vVùÙ","bBâÂ","nNíÍ","mMìÌ",",<",".>","/?",
1054 "<>"
1055};
1056
1057#ifndef OUTOFWINE
1058/*** Thai (Kedmanee) keyboard layout by Supphachoke Suntiwichaya <mrchoke@opentle.org> */
1059static const char main_key_th[MAIN_LEN][4] =
1060{
1061 "`~_%","1!å+","2@/ñ","3#-ò","4$Àó","5%¶ô","6^ØÙ","7&Öß","8*¤õ","9(µö","0)¨÷","-_¢ø","=+ªù",
1062 "qQæð","wWä\"","eEÓ®","rR¾±","tTи","yYÑí","uUÕê","iIó","oO¹Ï","pP­","[{º°","]}Å,",
1063 "aA¿Ä","sS˦","dD¡¯","fF´â","gGà¬","hHéç","jJèë","kKÒÉ","lLÊÈ",";:Ç«","\'\"§.","\\|£¥",
1064 "zZ¼(","xX»)","cCá©","vVÍÎ","bBÚ","nN×ì","mM·?",",<Á²",".>ãÌ","/?½Æ"
1065};
1066#else
1067/*** Thai (Kedmanee) keyboard layout by Supphachoke Suntiwichaya <mrchoke@opentle.org> */
1068static const char main_key_th[MAIN_LEN][4] =
1069{
1070 "_%","å+","/ñ","-ò","Àó","¶ô","ØÙ","Öß","¤õ","µö","¨÷","¢ø","ªù",
1071 "æð",\"","Ó®","¾±","и","Ñí","Õê","ó","¹Ï","­","º°","Å,",
1072 "¿Ä","˦","¡¯","´â","à¬","éç","èë","ÒÉ","ÊÈ","Ç«","§.","£¥",
1073 "¼(","»)","á©","ÍÎ","\xd4\xda","×ì","·?","Á²","ãÌ","½Æ",
1074 "<>" /* The phantom key. */
1075};
1076#endif
1077
1078/*** VNC keyboard layout */
1079static const WORD main_key_scan_vnc[MAIN_LEN] =
1080{
1081 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x1A,0x1B,0x27,0x28,0x29,0x33,0x34,0x35,0x2B,
1082 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,
1083 0x56
1084};
1085
1086static const WORD main_key_vkey_vnc[MAIN_LEN] =
1087{
1088 '1','2','3','4','5','6','7','8','9','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,
1089 'A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z',
1090 VK_OEM_102
1091};
1092
1093static const char main_key_vnc[MAIN_LEN][4] =
1094{
1095 "1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+","[{","]}",";:","'\"","`~",",<",".>","/?","\\|",
1096 "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"
1097};
1098
1099/*** Dutch keyboard layout (setxkbmap nl) ***/
1100static const char main_key_NL[MAIN_LEN][4] =
1101{
1102 "@§","1!","2\"","3#","4$","5%","6&","7_","8(","9)","0'","/?","°~",
1103 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","¨~","*|",
1104 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","+±","'`","<>",
1105 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-=",
1106 "[]"
1107};
1108
1109
1110
1111/*** Layout table. Add your keyboard mappings to this list */
1112static const struct {
1113 LCID lcid; /* input locale identifier, look for LOCALE_ILANGUAGE
1114 in the appropriate dlls/kernel/nls/.nls file */
1115 const char *comment;
1116 const char (*key)[MAIN_LEN][4];
1117 const WORD (*scan)[MAIN_LEN]; /* scan codes mapping */
1118 const WORD (*vkey)[MAIN_LEN]; /* virtual key codes mapping */
1119} main_key_tab[]={
1120 {0x0409, "United States keyboard layout", &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1121 {0x0409, "United States keyboard layout (phantom key version)", &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1122#ifndef OUTOFWINE
1123 {0x0409, "United States keyboard layout (dvorak)", &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak},
1124 {0x0409, "United States International keyboard layout", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1125#else
1126/* innotek FIX */
1127 {0x0409, "United States keyboard layout (dvorak)", &main_key_US_dvorak, &main_key_scan_qwerty, &main_key_vkey_dvorak},
1128 {0x0409, "United States keyboard layout (dvorak, phantom key version)", &main_key_US_dvorak_phantom, &main_key_scan_qwerty, &main_key_vkey_dvorak},
1129 {0x0409, "United States International keyboard layout", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1130 {0x0409, "United States International keyboard layout (phantom key version)", &main_key_US_intl_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1131#endif
1132 {0x0809, "British keyboard layout", &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1133#ifdef OUTOFWINE
1134 {0x0809, "British international keyboard layout", &main_key_UK_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1135#endif
1136 {0x0407, "German keyboard layout", &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwertz},
1137#ifndef OUTOFWINE
1138 {0x0407, "German keyboard layout without dead keys", &main_key_DE_nodead, &main_key_scan_qwerty, &main_key_vkey_qwertz},
1139 {0x0407, "German keyboard layout for logitech desktop pro", &main_key_DE_logitech, &main_key_scan_qwerty, &main_key_vkey_qwertz},
1140#endif
1141 {0x0407, "German keyboard layout without dead keys 105", &main_key_DE_nodead_105, &main_key_scan_qwerty, &main_key_vkey_qwertz_105},
1142 {0x0807, "Swiss German keyboard layout", &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwertz},
1143 {0x100c, "Swiss French keyboard layout", &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwertz},
1144 {0x041d, "Swedish keyboard layout", &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty_v2},
1145 {0x0425, "Estonian keyboard layout", &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1146 {0x0414, "Norwegian keyboard layout", &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1147 {0x0406, "Danish keyboard layout", &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1148 {0x040c, "French keyboard layout", &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty},
1149#ifndef OUTOFWINE
1150 {0x0c0c, "Canadian French keyboard layout", &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1151#endif
1152 {0x0c0c, "Canadian French keyboard layout (CA_fr)", &main_key_CA_fr, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1153 {0x0c0c, "Canadian keyboard layout", &main_key_CA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1154 {0x080c, "Belgian keyboard layout", &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty},
1155 {0x0816, "Portuguese keyboard layout", &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1156 {0x0416, "Brazilian ABNT-2 keyboard layout", &main_key_PT_br, &main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
1157 {0x0416, "Brazilian ABNT-2 keyboard layout ALT GR", &main_key_PT_br_alt_gr,&main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
1158 {0x040b, "Finnish keyboard layout", &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1159 {0x0402, "Bulgarian bds keyboard layout", &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1160 {0x0402, "Bulgarian phonetic keyboard layout", &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1161 {0x0423, "Belarusian keyboard layout", &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1162#ifndef OUTOFWINE
1163 {0x0419, "Russian keyboard layout", &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1164 {0x0419, "Russian keyboard layout (phantom key version)", &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1165#endif
1166 {0x0419, "Russian keyboard layout KOI8-R", &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1167#ifndef OUTOFWINE
1168 {0x0419, "Russian keyboard layout cp1251", &main_key_RU_cp1251, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1169#endif
1170 {0x0419, "Russian phonetic keyboard layout", &main_key_RU_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1171 {0x0422, "Ukrainian keyboard layout KOI8-U", &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1172 {0x0422, "Ukrainian keyboard layout (standard)", &main_key_UA_std, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1173 {0x0419, "Russian keyboard layout (standard)", &main_key_RU_std, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1174 {0x040a, "Spanish keyboard layout", &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1175 {0x0410, "Italian keyboard layout", &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1176 {0x040f, "Icelandic keyboard layout", &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1177 {0x040e, "Hungarian keyboard layout", &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwertz},
1178 {0x0415, "Polish (programmer's) keyboard layout", &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1179 {0x0424, "Slovenian keyboard layout", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwertz},
1180 {0x0c1a, "Serbian keyboard layout sr", &main_key_SR, &main_key_scan_qwerty, &main_key_vkey_qwerty}, /* LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC */
1181 {0x0c1a, "Serbian keyboard layout us,sr", &main_key_US_SR, &main_key_scan_qwerty, &main_key_vkey_qwerty}, /* LANG_SERBIAN,SUBLANG_SERBIAN_CYRILLIC */
1182 {0x041a, "Croatian keyboard layout", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwertz},
1183 {0x041a, "Croatian keyboard layout (specific)", &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1184 {0x0411, "Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty_jp106, &main_key_vkey_qwerty_jp106},
1185 {0x0411, "Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1186 {0x041b, "Slovak keyboard layout", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1187 {0x041b, "Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1188 {0x0405, "Czech keyboard layout", &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1189 {0x0405, "Czech keyboard layout cz", &main_key_CZ, &main_key_scan_qwerty, &main_key_vkey_qwertz},
1190 {0x0405, "Czech keyboard layout cz_qwerty", &main_key_CZ_qwerty, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1191 {0x040a, "Latin American keyboard layout", &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1192 {0x0427, "Lithuanian (Baltic) keyboard layout", &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1193 {0x041f, "Turkish keyboard layout", &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1194 {0x041f, "Turkish keyboard layout tr", &main_key_TR, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1195 {0x041f, "Turkish keyboard layout trf", &main_key_TR_F, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1196 {0x040d, "Israelian keyboard layout", &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1197 {0x040d, "Israelian phonetic keyboard layout", &main_key_IL_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1198 {0x040d, "Israelian Saharon keyboard layout", &main_key_IL_saharon, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1199 {0x0409, "VNC keyboard layout", &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc},
1200 {0x0408, "Greek keyboard layout", &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1201 {0x041e, "Thai (Kedmanee) keyboard layout", &main_key_th, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1202 {0x0413, "Dutch keyboard layout", &main_key_NL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
1203
1204 {0, NULL, NULL, NULL, NULL} /* sentinel */
1205};
1206static unsigned kbd_layout=0; /* index into above table of layouts */
1207
1208/* maybe more of these scancodes should be extended? */
1209 /* extended must be set for ALT_R, CTRL_R,
1210 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
1211 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
1212 /* FIXME should we set extended bit for NumLock ? My
1213 * Windows does ... DF */
1214 /* Yes, to distinguish based on scan codes, also
1215 for PrtScn key ... GA */
1216
1217#ifndef OUTOFWINE
1218static const WORD nonchar_key_vkey[256] =
1219{
1220 /* unused */
1221 0, 0, 0, 0, 0, 0, 0, 0, /* FF00 */
1222 /* special keys */
1223 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
1224 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
1225 0, 0, 0, VK_ESCAPE, 0, 0, 0, 0, /* FF18 */
1226 /* unused */
1227 0, 0, 0, 0, 0, 0, 0, 0, /* FF20 */
1228 0, 0, 0, 0, 0, 0, 0, 0, /* FF28 */
1229 0, 0, 0, 0, 0, 0, 0, 0, /* FF30 */
1230 0, 0, 0, 0, 0, 0, 0, 0, /* FF38 */
1231 0, 0, 0, 0, 0, 0, 0, 0, /* FF40 */
1232 0, 0, 0, 0, 0, 0, 0, 0, /* FF48 */
1233 /* cursor keys */
1234 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, /* FF50 */
1235 VK_DOWN, VK_PRIOR, VK_NEXT, VK_END,
1236 0, 0, 0, 0, 0, 0, 0, 0, /* FF58 */
1237 /* misc keys */
1238 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0,0,0, VK_APPS, /* FF60 */
1239 0, VK_CANCEL, VK_HELP, VK_CANCEL, 0, 0, 0, 0, /* FF68 */
1240 0, 0, 0, 0, 0, 0, 0, 0, /* FF70 */
1241 /* keypad keys */
1242 0, 0, 0, 0, 0, 0, 0, VK_NUMLOCK, /* FF78 */
1243 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
1244 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
1245 0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP, /* FF90 */
1246 VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, /* FF98 */
1247 VK_END, VK_CLEAR, VK_INSERT, VK_DELETE,
1248 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
1249 0, 0, VK_MULTIPLY, VK_ADD, /* FFA8 */
1250 VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE,
1251 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, /* FFB0 */
1252 VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
1253 VK_NUMPAD8, VK_NUMPAD9, 0, 0, 0, VK_OEM_NEC_EQUAL, /* FFB8 */
1254 /* function keys */
1255 VK_F1, VK_F2,
1256 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
1257 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, 0, 0, /* FFC8 */
1258 0, 0, 0, 0, 0, 0, 0, 0, /* FFD0 */
1259 0, 0, 0, 0, 0, 0, 0, 0, /* FFD8 */
1260 /* modifier keys */
1261 0, VK_SHIFT, VK_SHIFT, VK_CONTROL, /* FFE0 */
1262 VK_CONTROL, VK_CAPITAL, 0, VK_MENU,
1263 VK_MENU, VK_MENU, VK_MENU, 0, 0, 0, 0, 0, /* FFE8 */
1264 0, 0, 0, 0, 0, 0, 0, 0, /* FFF0 */
1265 0, 0, 0, 0, 0, 0, 0, VK_DELETE /* FFF8 */
1266};
1267#endif /* OUTOFWINE not defined */
1268
1269static const WORD nonchar_key_scan[256] =
1270{
1271 /* unused */
1272 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF00 */
1273 /* special keys */
1274 0x0E, 0x0F, 0x00, /*?*/ 0, 0x00, 0x1C, 0x00, 0x00, /* FF08 */
1275 0x00, 0x00, 0x00, 0x45, 0x46, 0x00, 0x00, 0x00, /* FF10 */
1276 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, /* FF18 */
1277 /* unused */
1278 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF20 */
1279 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF28 */
1280 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF30 */
1281 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF38 */
1282 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF40 */
1283 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF48 */
1284 /* cursor keys */
1285 0x147, 0x14B, 0x148, 0x14D, 0x150, 0x149, 0x151, 0x14F, /* FF50 */
1286 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF58 */
1287 /* misc keys */
1288#ifdef OUTOFWINE
1289/* innotek FIX */
1290 /*?*/ 0, 0x137, /*?*/ 0, 0x152, 0x00, 0x00, 0x00, 0x15D, /* FF60 */
1291#else
1292 /*?*/ 0, 0x137, /*?*/ 0, 0x152, 0x00, 0x00, 0x00, 0x00, /* FF60 */
1293#endif
1294 /*?*/ 0, /*?*/ 0, 0x38, 0x146, 0x00, 0x00, 0x00, 0x00, /* FF68 */
1295 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF70 */
1296 /* keypad keys */
1297 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x138, 0x145, /* FF78 */
1298 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF80 */
1299 0x00, 0x00, 0x00, 0x00, 0x00, 0x11C, 0x00, 0x00, /* FF88 */
1300 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4B, 0x48, /* FF90 */
1301 0x4D, 0x50, 0x49, 0x51, 0x4F, 0x4C, 0x52, 0x53, /* FF98 */
1302 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFA0 */
1303#ifdef OUTOFWINE
1304/* innotek FIX */
1305 0x00, 0x00, 0x37, 0x4E, 0x53, 0x4A, 0x7e, 0x135, /* FFA8 */
1306#else
1307 0x00, 0x00, 0x37, 0x4E, 0x53, 0x4A, 0x53, 0x135, /* FFA8 */
1308#endif
1309 0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47, /* FFB0 */
1310 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, /* FFB8 */
1311 /* function keys */
1312 0x3B, 0x3C,
1313 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, /* FFC0 */
1314 0x57, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFC8 */
1315 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFD0 */
1316 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFD8 */
1317 /* modifier keys */
1318 0x00, 0x2A, 0x36, 0x1D, 0x11D, 0x3A, 0x00, 0x38, /* FFE0 */
1319#ifdef OUTOFWINE
1320/* innotek FIX */
1321 0x138, 0x38, 0x138, 0x15B, 0x15C, 0x00, 0x00, 0x00, /* FFE8 */
1322#else
1323 0x138, 0x38, 0x138, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFE8 */
1324#endif
1325 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFF0 */
1326 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x153 /* FFF8 */
1327};
1328
1329#ifndef OUTOFWINE
1330static const WORD xfree86_vendor_key_vkey[256] =
1331{
1332 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF00 */
1333 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF08 */
1334 0, VK_VOLUME_DOWN, VK_VOLUME_MUTE, VK_VOLUME_UP, /* 1008FF10 */
1335 VK_MEDIA_PLAY_PAUSE, VK_MEDIA_STOP,
1336 VK_MEDIA_PREV_TRACK, VK_MEDIA_NEXT_TRACK,
1337 0, VK_LAUNCH_MAIL, 0, VK_BROWSER_SEARCH, /* 1008FF18 */
1338 0, 0, 0, VK_BROWSER_HOME,
1339 0, 0, 0, 0, 0, 0, VK_BROWSER_BACK, VK_BROWSER_FORWARD, /* 1008FF20 */
1340 VK_BROWSER_STOP, VK_BROWSER_REFRESH, 0, 0, 0, 0, 0, 0, /* 1008FF28 */
1341 VK_BROWSER_FAVORITES, 0, VK_LAUNCH_MEDIA_SELECT, 0, /* 1008FF30 */
1342 0, 0, 0, 0,
1343 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF38 */
1344 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF40 */
1345 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF48 */
1346 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF50 */
1347 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF58 */
1348 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF60 */
1349 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF68 */
1350 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF70 */
1351 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF78 */
1352 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF80 */
1353 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF88 */
1354 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF90 */
1355 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF98 */
1356 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFA0 */
1357 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFA8 */
1358 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFB0 */
1359 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFB8 */
1360 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFC0 */
1361 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFC8 */
1362 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFD0 */
1363 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFD8 */
1364 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFE0 */
1365 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFE8 */
1366 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFF0 */
1367 0, 0, 0, 0, 0, 0, 0, 0 /* 1008FFF8 */
1368};
1369#else /* OUTOFWINE defined */
1370/* innotek FIX */
1371/* This list was put together using /usr/include/X11/XF86keysym.h and
1372 http://www.win.tue.nl/~aeb/linux/kbd/scancodes-6.html. It has not yet
1373 been extensively tested. The scancodes are those used by MicroSoft
1374 keyboards. */
1375static const WORD xfree86_vendor_key_scan[256] =
1376{
1377 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF00 */
1378 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF08 */
1379 /* Vol- Mute Vol+ Play Stop Track- Track+ */
1380 0, 0x12e, 0x120, 0x130, 0x122, 0x124, 0x110, 0x119, /* 1008FF10 */
1381 /* Home E-mail Search */
1382 0x132, 0x16c, 0, 0x165, 0, 0, 0, 0, /* 1008FF18 */
1383 /* Calndr PwrDown Back Forward */
1384 0x115, 0x15e, 0, 0, 0, 0, 0x16a, 0x169, /* 1008FF20 */
1385 /* Stop Refresh Power Wake Sleep */
1386 0x168, 0x167, 0x15e, 0x163, 0, 0, 0, 0x15f, /* 1008FF28 */
1387 /* Favrts Pause Media MyComp */
1388 0x166, 0x122, 0x16d, 0x16b, 0, 0, 0, 0, /* 1008FF30 */
1389 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF38 */
1390 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF40 */
1391 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF48 */
1392 /* AppL AppR Calc Close Copy */
1393 0x109, 0x11e, 0, 0, 0x121, 0, 0x140, 0x118, /* 1008FF50 */
1394 /* Cut Docmnts Excel */
1395 0x117, 0, 0, 0x105, 0x114, 0, 0, 0, /* 1008FF58 */
1396 /* LogOff */
1397 0, 0x116, 0, 0, 0, 0, 0, 0, /* 1008FF60 */
1398 /* OffcHm Open Paste */
1399 0, 0, 0x13c, 0x13f, 0, 0x10a, 0, 0, /* 1008FF68 */
1400 /* Reply Refresh Save */
1401 0, 0, 0x141, 0x167, 0, 0, 0, 0x157, /* 1008FF70 */
1402 /* ScrlUp ScrlDn Send Spell TaskPane */
1403 0x10b, 0x18b, 0, 0x143, 0x123, 0, 0, 0x13d, /* 1008FF78 */
1404 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF80 */
1405 /* Word */
1406 0, 0x113, 0, 0, 0, 0, 0, 0, /* 1008FF88 */
1407 /* MailFwd MyPics MyMusic*/
1408 0x142, 0x164, 0x13c, 0, 0, 0, 0, 0, /* 1008FF90 */
1409 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FF98 */
1410 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFA0 */
1411 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFA8 */
1412 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFB0 */
1413 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFB8 */
1414 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFC0 */
1415 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFC8 */
1416 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFD0 */
1417 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFD8 */
1418 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFE0 */
1419 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFE8 */
1420 0, 0, 0, 0, 0, 0, 0, 0, /* 1008FFF0 */
1421 0, 0, 0, 0, 0, 0, 0, 0 /* 1008FFF8 */
1422};
1423#endif /* OUTOFWINE defined */
1424
1425#ifndef OUTOFWINE
1426/* Returns the Windows virtual key code associated with the X event <e> */
1427/* x11 lock must be held */
1428static WORD EVENT_event_to_vkey( XIC xic, XKeyEvent *e)
1429{
1430 KeySym keysym = 0;
1431 Status status;
1432 char buf[24];
1433
1434 /* Clients should pass only KeyPress events to XmbLookupString */
1435 if (xic && e->type == KeyPress)
1436 XmbLookupString(xic, e, buf, sizeof(buf), &keysym, &status);
1437 else
1438 XLookupString(e, buf, sizeof(buf), &keysym, NULL);
1439
1440 if ((e->state & NumLockMask) &&
1441 (keysym == XK_KP_Separator || keysym == XK_KP_Decimal ||
1442 (keysym >= XK_KP_0 && keysym <= XK_KP_9)))
1443 /* Only the Keypad keys 0-9 and . send different keysyms
1444 * depending on the NumLock state */
1445 return nonchar_key_vkey[keysym & 0xFF];
1446
1447 TRACE_(key)("e->keycode = %x\n", e->keycode);
1448
1449 return keyc2vkey[e->keycode];
1450}
1451
1452static BOOL NumState=FALSE, CapsState=FALSE;
1453
1454
1455/***********************************************************************
1456 * X11DRV_send_keyboard_input
1457 */
1458void X11DRV_send_keyboard_input( WORD wVk, WORD wScan, DWORD dwFlags, DWORD time,
1459 DWORD dwExtraInfo, UINT injected_flags )
1460{
1461 UINT message;
1462 KEYLP keylp;
1463 KBDLLHOOKSTRUCT hook;
1464 WORD wVkStripped;
1465
1466 wVk = LOBYTE(wVk);
1467
1468 /* strip left/right for menu, control, shift */
1469 if (wVk == VK_LMENU || wVk == VK_RMENU)
1470 wVkStripped = VK_MENU;
1471 else if (wVk == VK_LCONTROL || wVk == VK_RCONTROL)
1472 wVkStripped = VK_CONTROL;
1473 else if (wVk == VK_LSHIFT || wVk == VK_RSHIFT)
1474 wVkStripped = VK_SHIFT;
1475 else
1476 wVkStripped = wVk;
1477
1478 keylp.lp2 = 0;
1479 keylp.lp1.count = 1;
1480 keylp.lp1.code = wScan;
1481 keylp.lp1.extended = (dwFlags & KEYEVENTF_EXTENDEDKEY) != 0;
1482 keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
1483 * don't remember where I read it - AK */
1484 /* it's '1' under windows, when a dialog box appears
1485 * and you press one of the underlined keys - DF*/
1486
1487 /* note that there is a test for all this */
1488 if (dwFlags & KEYEVENTF_KEYUP )
1489 {
1490 message = WM_KEYUP;
1491 if ((key_state_table[VK_MENU] & 0x80) &&
1492 ((wVkStripped == VK_MENU) || (wVkStripped == VK_CONTROL)
1493 || !(key_state_table[VK_CONTROL] & 0x80)))
1494 {
1495 if( TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */
1496 (wVkStripped != VK_MENU)) /* <ALT>-down...<something else>-up */
1497 message = WM_SYSKEYUP;
1498 TrackSysKey = 0;
1499 }
1500 key_state_table[wVk] &= ~0x80;
1501 key_state_table[wVkStripped] &= ~0x80;
1502 keylp.lp1.previous = 1;
1503 keylp.lp1.transition = 1;
1504 }
1505 else
1506 {
1507 keylp.lp1.previous = (key_state_table[wVk] & 0x80) != 0;
1508 keylp.lp1.transition = 0;
1509 if (!(key_state_table[wVk] & 0x80)) key_state_table[wVk] ^= 0x01;
1510 key_state_table[wVk] |= 0xc0;
1511 key_state_table[wVkStripped] |= 0xc0;
1512
1513 message = WM_KEYDOWN;
1514 if ((key_state_table[VK_MENU] & 0x80) && !(key_state_table[VK_CONTROL] & 0x80))
1515 {
1516 message = WM_SYSKEYDOWN;
1517 TrackSysKey = wVkStripped;
1518 }
1519 }
1520
1521 keylp.lp1.context = (key_state_table[VK_MENU] & 0x80) != 0; /* 1 if alt */
1522
1523 TRACE_(key)(" wParam=%04x, lParam=%08lx, InputKeyState=%x\n",
1524 wVk, keylp.lp2, key_state_table[wVk] );
1525
1526 hook.vkCode = wVk;
1527 hook.scanCode = wScan;
1528 hook.flags = (keylp.lp2 >> 24) | injected_flags;
1529 hook.time = time;
1530 hook.dwExtraInfo = dwExtraInfo;
1531 if (HOOK_CallHooks( WH_KEYBOARD_LL, HC_ACTION, message, (LPARAM)&hook, TRUE )) return;
1532
1533 SERVER_START_REQ( send_hardware_message )
1534 {
1535 req->id = (injected_flags & LLKHF_INJECTED) ? 0 : GetCurrentThreadId();
1536 req->win = 0;
1537 req->msg = message;
1538 req->wparam = wVk;
1539 req->lparam = keylp.lp2;
1540 req->x = cursor_pos.x;
1541 req->y = cursor_pos.y;
1542 req->time = time;
1543 req->info = dwExtraInfo;
1544 wine_server_call( req );
1545 }
1546 SERVER_END_REQ;
1547}
1548
1549
1550/**********************************************************************
1551 * KEYBOARD_GenerateMsg
1552 *
1553 * Generate Down+Up messages when NumLock or CapsLock is pressed.
1554 *
1555 * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
1556 *
1557 */
1558static void KEYBOARD_GenerateMsg( WORD vkey, WORD scan, int Evtype, DWORD event_time )
1559{
1560 BOOL * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
1561 DWORD up, down;
1562
1563 if (*State) {
1564 /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
1565 don't treat it. It's from the same key press. Then the state goes to ON.
1566 And from there, a 'release' event will switch off the toggle key. */
1567 *State=FALSE;
1568 TRACE("INTERM : don't treat release of toggle key. key_state_table[%#x] = %#x\n",
1569 vkey,key_state_table[vkey]);
1570 } else
1571 {
1572 down = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0);
1573 up = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0) | KEYEVENTF_KEYUP;
1574 if ( key_state_table[vkey] & 0x1 ) /* it was ON */
1575 {
1576 if (Evtype!=KeyPress)
1577 {
1578 TRACE("ON + KeyRelease => generating DOWN and UP messages.\n");
1579 X11DRV_send_keyboard_input( vkey, scan, down, event_time, 0, 0 );
1580 X11DRV_send_keyboard_input( vkey, scan, up, event_time, 0, 0 );
1581 *State=FALSE;
1582 key_state_table[vkey] &= ~0x01; /* Toggle state to off. */
1583 }
1584 }
1585 else /* it was OFF */
1586 if (Evtype==KeyPress)
1587 {
1588 TRACE("OFF + Keypress => generating DOWN and UP messages.\n");
1589 X11DRV_send_keyboard_input( vkey, scan, down, event_time, 0, 0 );
1590 X11DRV_send_keyboard_input( vkey, scan, up, event_time, 0, 0 );
1591 *State=TRUE; /* Goes to intermediary state before going to ON */
1592 key_state_table[vkey] |= 0x01; /* Toggle state to on. */
1593 }
1594 }
1595}
1596
1597/***********************************************************************
1598 * KEYBOARD_UpdateOneState
1599 *
1600 * Updates internal state for <vkey>, depending on key <state> under X
1601 *
1602 */
1603inline static void KEYBOARD_UpdateOneState ( int vkey, int state, DWORD time )
1604{
1605 /* Do something if internal table state != X state for keycode */
1606 if (((key_state_table[vkey] & 0x80)!=0) != state)
1607 {
1608 TRACE("Adjusting state for vkey %#.2x. State before %#.2x\n",
1609 vkey, key_state_table[vkey]);
1610
1611 /* Fake key being pressed inside wine */
1612 X11DRV_send_keyboard_input( vkey, 0, state? 0 : KEYEVENTF_KEYUP, time, 0, 0 );
1613
1614 TRACE("State after %#.2x\n",key_state_table[vkey]);
1615 }
1616}
1617
1618/***********************************************************************
1619 * X11DRV_KeymapNotify
1620 *
1621 * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
1622 *
1623 * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
1624 * from wine to another application and back.
1625 * Toggle keys are handled in HandleEvent.
1626 */
1627void X11DRV_KeymapNotify( HWND hwnd, XEvent *event )
1628{
1629 int i, j, alt, control, shift;
1630 DWORD time = GetCurrentTime();
1631
1632 alt = control = shift = 0;
1633 /* the minimum keycode is always greater or equal to 8, so we can
1634 * skip the first 8 values, hence start at 1
1635 */
1636 for (i = 1; i < 32; i++)
1637 {
1638 if (!event->xkeymap.key_vector[i]) continue;
1639 for (j = 0; j < 8; j++)
1640 {
1641 if (!(event->xkeymap.key_vector[i] & (1<<j))) continue;
1642 switch(keyc2vkey[(i * 8) + j] & 0xff)
1643 {
1644 case VK_MENU: alt = 1; break;
1645 case VK_CONTROL: control = 1; break;
1646 case VK_SHIFT: shift = 1; break;
1647 }
1648 }
1649 }
1650 KEYBOARD_UpdateOneState( VK_MENU, alt, time );
1651 KEYBOARD_UpdateOneState( VK_CONTROL, control, time );
1652 KEYBOARD_UpdateOneState( VK_SHIFT, shift, time );
1653}
1654
1655/***********************************************************************
1656 * X11DRV_KeyEvent
1657 *
1658 * Handle a X key event
1659 */
1660void X11DRV_KeyEvent( HWND hwnd, XEvent *xev )
1661{
1662 XKeyEvent *event = &xev->xkey;
1663 char Str[24];
1664 KeySym keysym = 0;
1665 WORD vkey = 0, bScan;
1666 DWORD dwFlags;
1667 int ascii_chars;
1668 XIC xic = X11DRV_get_ic( hwnd );
1669 DWORD event_time = EVENT_x11_time_to_win32_time(event->time);
1670 Status status = 0;
1671
1672 TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
1673 event->type, event->window, event->state, event->keycode);
1674
1675 wine_tsx11_lock();
1676 /* Clients should pass only KeyPress events to XmbLookupString */
1677 if (xic && event->type == KeyPress)
1678 ascii_chars = XmbLookupString(xic, event, Str, sizeof(Str), &keysym, &status);
1679 else
1680 ascii_chars = XLookupString(event, Str, sizeof(Str), &keysym, NULL);
1681 wine_tsx11_unlock();
1682
1683 TRACE_(key)("state = %X nbyte = %d, status 0x%x\n", event->state, ascii_chars, status);
1684
1685 if (status == XBufferOverflow)
1686 ERR("Buffer Overflow need %i!\n",ascii_chars);
1687
1688 if (status == XLookupChars)
1689 {
1690 X11DRV_XIMLookupChars( Str, ascii_chars );
1691 return;
1692 }
1693
1694 /* If XKB extensions are used, the state mask for AltGr will use the group
1695 index instead of the modifier mask. The group index is set in bits
1696 13-14 of the state field in the XKeyEvent structure. So if AltGr is
1697 pressed, look if the group index is different than 0. From XKB
1698 extension documentation, the group index for AltGr should be 2
1699 (event->state = 0x2000). It's probably better to not assume a
1700 predefined group index and find it dynamically
1701
1702 Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
1703 /* Save also all possible modifier states. */
1704 AltGrMask = event->state & (0x6000 | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
1705
1706 Str[ascii_chars] = '\0';
1707 if (TRACE_ON(key)){
1708 const char *ksname;
1709
1710 wine_tsx11_lock();
1711 ksname = XKeysymToString(keysym);
1712 wine_tsx11_unlock();
1713 if (!ksname)
1714 ksname = "No Name";
1715 TRACE_(key)("%s : keysym=%lX (%s), # of chars=%d / 0x%02x / '%s'\n",
1716 (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
1717 keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
1718 }
1719
1720 wine_tsx11_lock();
1721 vkey = EVENT_event_to_vkey(xic,event);
1722 /* X returns keycode 0 for composed characters */
1723 if (!vkey && ascii_chars) vkey = VK_NONAME;
1724 wine_tsx11_unlock();
1725
1726 TRACE_(key)("keycode 0x%x converted to vkey 0x%x\n",
1727 event->keycode, vkey);
1728
1729 if (vkey)
1730 {
1731 switch (vkey & 0xff)
1732 {
1733 case VK_NUMLOCK:
1734 KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, event->type, event_time );
1735 break;
1736 case VK_CAPITAL:
1737 TRACE("Caps Lock event. (type %d). State before : %#.2x\n",event->type,key_state_table[vkey]);
1738 KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, event->type, event_time );
1739 TRACE("State after : %#.2x\n",key_state_table[vkey]);
1740 break;
1741 default:
1742 /* Adjust the NUMLOCK state if it has been changed outside wine */
1743 if (!(key_state_table[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
1744 {
1745 TRACE("Adjusting NumLock state.\n");
1746 KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyPress, event_time );
1747 KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyRelease, event_time );
1748 }
1749 /* Adjust the CAPSLOCK state if it has been changed outside wine */
1750 if (!(key_state_table[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
1751 {
1752 TRACE("Adjusting Caps Lock state.\n");
1753 KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyPress, event_time );
1754 KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyRelease, event_time );
1755 }
1756 /* Not Num nor Caps : end of intermediary states for both. */
1757 NumState = FALSE;
1758 CapsState = FALSE;
1759
1760 bScan = keyc2scan[event->keycode] & 0xFF;
1761 TRACE_(key)("bScan = 0x%02x.\n", bScan);
1762
1763 dwFlags = 0;
1764 if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
1765 if ( vkey & 0x100 ) dwFlags |= KEYEVENTF_EXTENDEDKEY;
1766
1767 X11DRV_send_keyboard_input( vkey & 0xff, bScan, dwFlags, event_time, 0, 0 );
1768 }
1769 }
1770}
1771
1772#else /* OUTOFWINE defined */
1773
1774void X11DRV_KeyEvent(Display *dpy, XEvent *xev, WINEKEYBOARDINFO *wKbInfo)
1775{
1776 XKeyEvent *event = &xev->xkey;
1777 wKbInfo->wScan = keyc2scan[event->keycode] & 0xFF;
1778 wKbInfo->dwFlags = keyc2scan[event->keycode] >> 8;
1779}
1780
1781#endif /* OUTOFWINE defined */
1782
1783/**********************************************************************
1784 * X11DRV_KEYBOARD_DetectLayout
1785 *
1786 * Called from X11DRV_InitKeyboard
1787 * This routine walks through the defined keyboard layouts and selects
1788 * whichever matches most closely.
1789 * X11 lock must be held.
1790 */
1791#ifndef OUTOFWINE
1792static void
1793X11DRV_KEYBOARD_DetectLayout (void)
1794#else
1795static void
1796X11DRV_KEYBOARD_DetectLayout (Display *display)
1797#endif
1798{
1799#ifndef OUTOFWINE
1800 Display *display = thread_display();
1801#endif
1802 unsigned current, match, mismatch, seq, i, syms;
1803 int score, keyc, key, pkey, ok;
1804 KeySym keysym = 0;
1805 const char (*lkey)[MAIN_LEN][4];
1806 unsigned max_seq = 0;
1807 int max_score = 0, ismatch = 0;
1808 char ckey[256][4];
1809#ifdef OUTOFWINE
1810/* innotek FIX */
1811 /* The Wine algorithm is incapable of distinguishing the dvorak and the querty layout,
1812 which have the same keys in a different sequence. Based on the assumption that
1813 scan codes are laid out more or less sequentially, we keep a track of how many
1814 of our detected scan codes are out of order as an additional matching criterium. */
1815 int misorder, last_match, least_misorder = 256;
1816#endif
1817
1818 syms = keysyms_per_keycode;
1819 if (syms > 4) {
1820 WARN("%d keysyms per keycode not supported, set to 4\n", syms);
1821 syms = 4;
1822 }
1823
1824 memset( ckey, 0, sizeof(ckey) );
1825 for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1826 /* get data for keycode from X server */
1827 for (i = 0; i < syms; i++) {
1828 if (!(keysym = XKeycodeToKeysym (display, keyc, i))) continue;
1829 /* Allow both one-byte and two-byte national keysyms */
1830 if ((keysym < 0x8000) && (keysym != ' '))
1831 {
1832#ifdef HAVE_XKB
1833 if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[keyc][i], 1, NULL))
1834#endif
1835 {
1836#ifndef OUTOFWINE
1837 TRACE("XKB could not translate keysym %ld\n", keysym);
1838#endif
1839 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1840 * with appropriate ShiftMask and Mode_switch, use XLookupString
1841 * to get character in the local encoding.
1842 */
1843 ckey[keyc][i] = keysym & 0xFF;
1844 }
1845 }
1846 else {
1847 ckey[keyc][i] = KEYBOARD_MapDeadKeysym(keysym);
1848 }
1849 }
1850 }
1851
1852 for (current = 0; main_key_tab[current].comment; current++) {
1853 TRACE("Attempting to match against \"%s\"\n", main_key_tab[current].comment);
1854 match = 0;
1855 mismatch = 0;
1856 score = 0;
1857 seq = 0;
1858 lkey = main_key_tab[current].key;
1859 pkey = -1;
1860#ifdef OUTOFWINE
1861/* innotek FIX - dvorak layout */
1862 last_match = 0;
1863 misorder = 0;
1864#endif
1865 for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1866 if (ckey[keyc][0]) {
1867 /* search for a match in layout table */
1868 /* right now, we just find an absolute match for defined positions */
1869 /* (undefined positions are ignored, so if it's defined as "3#" in */
1870 /* the table, it's okay that the X server has "3#£", for example) */
1871 /* however, the score will be higher for longer matches */
1872 for (key = 0; key < MAIN_LEN; key++) {
1873 for (ok = 0, i = 0; (ok >= 0) && (i < syms); i++) {
1874 if ((*lkey)[key][i] && ((*lkey)[key][i] == ckey[keyc][i]))
1875 ok++;
1876 if ((*lkey)[key][i] && ((*lkey)[key][i] != ckey[keyc][i]))
1877 ok = -1;
1878 }
1879 if (ok > 0) {
1880 score += ok;
1881#ifdef OUTOFWINE
1882/* innotek FIX - dvorak layout */
1883 if (key < last_match)
1884 {
1885 ++misorder;
1886 }
1887 last_match = key;
1888#endif
1889 break;
1890 }
1891 }
1892 /* count the matches and mismatches */
1893 if (ok > 0) {
1894 match++;
1895 /* and how much the keycode order matches */
1896 if (key > pkey) seq++;
1897 pkey = key;
1898 } else {
1899 /* print spaces instead of \0's */
1900 char str[5];
1901 for (i = 0; i < 4; i++) str[i] = ckey[keyc][i] ? ckey[keyc][i] : ' ';
1902 str[4] = 0;
1903#ifndef OUTOFWINE
1904 TRACE_(key)("mismatch for keysym 0x%04lX, keycode %d, got %s\n", keysym, keyc, str );
1905#else
1906 TRACE_(key)("mismatch for keycode %d, got %s (0x%.2hx 0x%.2hx)\n",
1907 keyc, str, str[0], str[1]);
1908#endif
1909 mismatch++;
1910 score -= syms;
1911 }
1912 }
1913 }
1914#ifndef OUTOFWINE
1915 TRACE("matches=%d, mismatches=%d, seq=%d, score=%d\n",
1916 match, mismatch, seq, score);
1917 if ((score > max_score) ||
1918 ((score == max_score) && (seq > max_seq))) {
1919#else
1920/* innotek FIX - dvorak layout */
1921 TRACE("matches=%d, mismatches=%d, seq=%d, score=%d, misorder = %d\n",
1922 match, mismatch, seq, score, misorder);
1923 if ((score > max_score) ||
1924 ((score == max_score) && (seq > max_seq)) ||
1925 ((score == max_score) && (seq == max_seq) &&
1926 (misorder < least_misorder))) {
1927#endif
1928 /* best match so far */
1929 kbd_layout = current;
1930 max_score = score;
1931 max_seq = seq;
1932 ismatch = !mismatch;
1933#ifdef OUTOFWINE
1934/* innotek FIX - dvorak layout */
1935 least_misorder = misorder;
1936#endif
1937 }
1938 }
1939 /* we're done, report results if necessary */
1940 if (!ismatch)
1941 WARN("Using closest match (%s) for scan/virtual codes mapping.\n",
1942 main_key_tab[kbd_layout].comment);
1943
1944 TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment);
1945}
1946
1947/**********************************************************************
1948 * X11DRV_InitKeyboard
1949 */
1950#ifndef OUTOFWINE
1951void X11DRV_InitKeyboard(void)
1952#else
1953void X11DRV_InitKeyboard(Display *display)
1954#endif
1955{
1956#ifndef OUTOFWINE
1957 Display *display = thread_display();
1958 KeySym *ksp;
1959 XModifierKeymap *mmp;
1960 KeySym keysym;
1961 KeyCode *kcp;
1962 XKeyEvent e2;
1963 WORD scan, vkey, OEMvkey;
1964#else
1965 KeySym *ksp;
1966 KeySym keysym;
1967 XKeyEvent e2;
1968 WORD scan;
1969#endif
1970 int keyc, i, keyn, syms;
1971 char ckey[4]={0,0,0,0};
1972 const char (*lkey)[MAIN_LEN][4];
1973#ifndef OUTOFWINE
1974 char vkey_used[256] = { 0 };
1975#endif
1976
1977 wine_tsx11_lock();
1978 XDisplayKeycodes(display, &min_keycode, &max_keycode);
1979 ksp = XGetKeyboardMapping(display, min_keycode,
1980 max_keycode + 1 - min_keycode, &keysyms_per_keycode);
1981 /* We are only interested in keysyms_per_keycode.
1982 There is no need to hold a local copy of the keysyms table */
1983 XFree(ksp);
1984
1985#ifndef OUTOFWINE
1986 mmp = XGetModifierMapping(display);
1987 kcp = mmp->modifiermap;
1988 for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
1989 {
1990 int j;
1991
1992 for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
1993 if (*kcp)
1994 {
1995 int k;
1996
1997 for (k = 0; k < keysyms_per_keycode; k += 1)
1998 if (XKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
1999 {
2000 NumLockMask = 1 << i;
2001 TRACE_(key)("NumLockMask is %x\n", NumLockMask);
2002 }
2003 }
2004 }
2005 XFreeModifiermap(mmp);
2006
2007 /* Detect the keyboard layout */
2008 X11DRV_KEYBOARD_DetectLayout();
2009#else
2010 /* Detect the keyboard layout */
2011 X11DRV_KEYBOARD_DetectLayout(display);
2012#endif
2013 lkey = main_key_tab[kbd_layout].key;
2014 syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode;
2015
2016 /* Now build two conversion arrays :
2017 * keycode -> vkey + scancode + extended
2018 * vkey + extended -> keycode */
2019
2020 e2.display = display;
2021 e2.state = 0;
2022
2023#ifndef OUTOFWINE
2024 OEMvkey = VK_OEM_8; /* next is available. */
2025 memset(keyc2vkey, 0, sizeof(keyc2vkey));
2026#endif
2027 for (keyc = min_keycode; keyc <= max_keycode; keyc++)
2028 {
2029 char buf[30];
2030 int have_chars;
2031
2032 keysym = 0;
2033 e2.keycode = (KeyCode)keyc;
2034 have_chars = XLookupString(&e2, buf, sizeof(buf), &keysym, NULL);
2035#ifndef OUTOFWINE
2036 vkey = 0; scan = 0;
2037#else
2038 scan = 0;
2039#endif
2040 if (keysym) /* otherwise, keycode not used */
2041 {
2042 if ((keysym >> 8) == 0xFF) /* non-character key */
2043 {
2044#ifndef OUTOFWINE
2045 vkey = nonchar_key_vkey[keysym & 0xff];
2046#endif
2047 scan = nonchar_key_scan[keysym & 0xff];
2048 /* set extended bit when necessary */
2049#ifndef OUTOFWINE
2050 if (scan & 0x100) vkey |= 0x100;
2051#endif
2052 } else if ((keysym >> 8) == 0x1008FF) { /* XFree86 vendor keys */
2053#ifndef OUTOFWINE
2054 vkey = xfree86_vendor_key_vkey[keysym & 0xff];
2055 /* All vendor keys are extended with a scan code of 0 per testing on WinXP */
2056 scan = 0x100;
2057 vkey |= 0x100;
2058#else
2059/* innotek FIX - multimedia/internet keys */
2060 /* @michael: this needs to be tested and completed some day. */
2061 scan = xfree86_vendor_key_scan[keysym & 0xff];
2062#endif
2063 } else if (keysym == 0x20) { /* Spacebar */
2064#ifndef OUTOFWINE
2065 vkey = VK_SPACE;
2066#endif
2067 scan = 0x39;
2068#ifdef OUTOFWINE
2069/* innotek FIX - AltGr support */
2070 } else if (keysym == 0xFE03) { /* ISO level3 shift, aka AltGr */
2071 scan = 0x138;
2072#endif /* OUTOFWINE defined */
2073 } else if (have_chars) {
2074 /* we seem to need to search the layout-dependent scancodes */
2075 int maxlen=0,maxval=-1,ok;
2076 for (i=0; i<syms; i++) {
2077 keysym = XKeycodeToKeysym(display, keyc, i);
2078 if ((keysym<0x8000) && (keysym!=' '))
2079 {
2080#ifdef HAVE_XKB
2081 if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
2082#endif
2083 {
2084 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
2085 * with appropriate ShiftMask and Mode_switch, use XLookupString
2086 * to get character in the local encoding.
2087 */
2088 ckey[i] = keysym & 0xFF;
2089 }
2090 } else {
2091 ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
2092 }
2093 }
2094 /* find key with longest match streak */
2095 for (keyn=0; keyn<MAIN_LEN; keyn++) {
2096 for (ok=(*lkey)[keyn][i=0]; ok&&(i<4); i++)
2097 if ((*lkey)[keyn][i] && (*lkey)[keyn][i]!=ckey[i]) ok=0;
2098 if (!ok) i--; /* we overshot */
2099 if (ok||(i>maxlen)) {
2100 maxlen=i; maxval=keyn;
2101 }
2102 if (ok) break;
2103 }
2104 if (maxval>=0) {
2105 /* got it */
2106#ifndef OUTOFWINE
2107 const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan;
2108 const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey;
2109 scan = (*lscan)[maxval];
2110 vkey = (*lvkey)[maxval];
2111#else
2112 const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan;
2113 scan = (*lscan)[maxval];
2114#endif
2115 }
2116 }
2117 }
2118#ifndef OUTOFWINE
2119 TRACE("keycode %04x => vkey %04x\n", e2.keycode, vkey);
2120 keyc2vkey[e2.keycode] = vkey;
2121 keyc2scan[e2.keycode] = scan;
2122 if ((vkey & 0xff) && vkey_used[(vkey & 0xff)])
2123 WARN("vkey %04x is being used by more than one keycode\n", vkey);
2124 vkey_used[(vkey & 0xff)] = 1;
2125#else
2126 keyc2scan[e2.keycode] = scan;
2127#endif
2128 } /* for */
2129
2130#ifndef OUTOFWINE
2131#define VKEY_IF_NOT_USED(vkey) (vkey_used[(vkey)] ? 0 : (vkey_used[(vkey)] = 1, (vkey)))
2132 for (keyc = min_keycode; keyc <= max_keycode; keyc++)
2133 {
2134 vkey = keyc2vkey[keyc] & 0xff;
2135 if (vkey)
2136 continue;
2137
2138 e2.keycode = (KeyCode)keyc;
2139 keysym = XLookupKeysym(&e2, 0);
2140 if (!keysym)
2141 continue;
2142
2143 /* find a suitable layout-dependent VK code */
2144 /* (most Winelib apps ought to be able to work without layout tables!) */
2145 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
2146 {
2147 keysym = XLookupKeysym(&e2, i);
2148 if ((keysym >= XK_0 && keysym <= XK_9)
2149 || (keysym >= XK_A && keysym <= XK_Z)) {
2150 vkey = VKEY_IF_NOT_USED(keysym);
2151 }
2152 }
2153
2154 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
2155 {
2156 keysym = XLookupKeysym(&e2, i);
2157 switch (keysym)
2158 {
2159 case ';': vkey = VKEY_IF_NOT_USED(VK_OEM_1); break;
2160 case '/': vkey = VKEY_IF_NOT_USED(VK_OEM_2); break;
2161 case '`': vkey = VKEY_IF_NOT_USED(VK_OEM_3); break;
2162 case '[': vkey = VKEY_IF_NOT_USED(VK_OEM_4); break;
2163 case '\\': vkey = VKEY_IF_NOT_USED(VK_OEM_5); break;
2164 case ']': vkey = VKEY_IF_NOT_USED(VK_OEM_6); break;
2165 case '\'': vkey = VKEY_IF_NOT_USED(VK_OEM_7); break;
2166 case ',': vkey = VKEY_IF_NOT_USED(VK_OEM_COMMA); break;
2167 case '.': vkey = VKEY_IF_NOT_USED(VK_OEM_PERIOD); break;
2168 case '-': vkey = VKEY_IF_NOT_USED(VK_OEM_MINUS); break;
2169 case '+': vkey = VKEY_IF_NOT_USED(VK_OEM_PLUS); break;
2170 }
2171 }
2172
2173 if (!vkey)
2174 {
2175 /* Others keys: let's assign OEM virtual key codes in the allowed range,
2176 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
2177 do
2178 {
2179 switch (++OEMvkey)
2180 {
2181 case 0xc1 : OEMvkey=0xdb; break;
2182 case 0xe5 : OEMvkey=0xe9; break;
2183 case 0xf6 : OEMvkey=0xf5; WARN("No more OEM vkey available!\n");
2184 }
2185 } while (OEMvkey < 0xf5 && vkey_used[OEMvkey]);
2186
2187 vkey = VKEY_IF_NOT_USED(OEMvkey);
2188
2189 if (TRACE_ON(keyboard))
2190 {
2191 TRACE("OEM specific virtual key %X assigned to keycode %X:\n",
2192 OEMvkey, e2.keycode);
2193 TRACE("(");
2194 for (i = 0; i < keysyms_per_keycode; i += 1)
2195 {
2196 const char *ksname;
2197
2198 keysym = XLookupKeysym(&e2, i);
2199 ksname = XKeysymToString(keysym);
2200 if (!ksname)
2201 ksname = "NoSymbol";
2202 TRACE( "%lX (%s) ", keysym, ksname);
2203 }
2204 TRACE(")\n");
2205 }
2206 }
2207
2208 if (vkey)
2209 {
2210 TRACE("keycode %04x => vkey %04x\n", e2.keycode, vkey);
2211 keyc2vkey[e2.keycode] = vkey;
2212 }
2213 } /* for */
2214#undef VKEY_IF_NOT_USED
2215
2216 /* If some keys still lack scancodes, assign some arbitrary ones to them now */
2217 for (scan = 0x60, keyc = min_keycode; keyc <= max_keycode; keyc++)
2218 if (keyc2vkey[keyc]&&!keyc2scan[keyc]) {
2219 const char *ksname;
2220 keysym = XKeycodeToKeysym(display, keyc, 0);
2221 ksname = XKeysymToString(keysym);
2222 if (!ksname) ksname = "NoSymbol";
2223
2224 /* should make sure the scancode is unassigned here, but >=0x60 currently always is */
2225
2226 TRACE_(key)("assigning scancode %02x to unidentified keycode %02x (%s)\n",scan,keyc,ksname);
2227 keyc2scan[keyc]=scan++;
2228 }
2229
2230 /* Now store one keycode for each modifier. Used to simulate keypresses. */
2231 kcControl = XKeysymToKeycode(display, XK_Control_L);
2232 kcAlt = XKeysymToKeycode(display, XK_Alt_L);
2233 if (!kcAlt) kcAlt = XKeysymToKeycode(display, XK_Meta_L);
2234 kcShift = XKeysymToKeycode(display, XK_Shift_L);
2235 kcNumLock = XKeysymToKeycode(display, XK_Num_Lock);
2236 kcCapsLock = XKeysymToKeycode(display, XK_Caps_Lock);
2237#endif /* OUTOFWINE not defined */
2238 wine_tsx11_unlock();
2239}
2240
2241#ifndef OUTOFWINE
2242/**********************************************************************
2243 * GetAsyncKeyState (X11DRV.@)
2244 */
2245SHORT X11DRV_GetAsyncKeyState(INT key)
2246{
2247 SHORT retval;
2248
2249 X11DRV_MsgWaitForMultipleObjectsEx( 0, NULL, 0, QS_KEY, 0 );
2250
2251 retval = ((key_state_table[key] & 0x40) ? 0x0001 : 0) |
2252 ((key_state_table[key] & 0x80) ? 0x8000 : 0);
2253 key_state_table[key] &= ~0x40;
2254 TRACE_(key)("(%x) -> %x\n", key, retval);
2255 return retval;
2256}
2257
2258
2259/***********************************************************************
2260 * GetKeyboardLayoutList (X11DRV.@)
2261 */
2262UINT X11DRV_GetKeyboardLayoutList(INT size, HKL *hkl)
2263{
2264 INT i;
2265
2266 TRACE("%d, %p\n", size, hkl);
2267
2268 if (!size)
2269 {
2270 size = 4096; /* hope we will never have that many */
2271 hkl = NULL;
2272 }
2273
2274 for (i = 0; main_key_tab[i].comment && (i < size); i++)
2275 {
2276 if (hkl)
2277 {
2278 ULONG_PTR layout = main_key_tab[i].lcid;
2279 LANGID langid;
2280
2281 /* see comment for GetKeyboardLayout */
2282 langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
2283 if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
2284 layout |= 0xe001 << 16; /* FIXME */
2285 else
2286 layout |= layout << 16;
2287
2288 hkl[i] = (HKL)layout;
2289 }
2290 }
2291 return i;
2292}
2293
2294
2295/***********************************************************************
2296 * GetKeyboardLayout (X11DRV.@)
2297 */
2298HKL X11DRV_GetKeyboardLayout(DWORD dwThreadid)
2299{
2300 ULONG_PTR layout;
2301 LANGID langid;
2302
2303 if (dwThreadid && dwThreadid != GetCurrentThreadId())
2304 FIXME("couldn't return keyboard layout for thread %04x\n", dwThreadid);
2305
2306#if 0
2307 layout = main_key_tab[kbd_layout].lcid;
2308#else
2309 /* FIXME:
2310 * Winword uses return value of GetKeyboardLayout as a codepage
2311 * to translate ANSI keyboard messages to unicode. But we have
2312 * a problem with it: for instance Polish keyboard layout is
2313 * identical to the US one, and therefore instead of the Polish
2314 * locale id we return the US one.
2315 */
2316 layout = GetUserDefaultLCID();
2317#endif
2318 /*
2319 * Microsoft Office expects this value to be something specific
2320 * for Japanese and Korean Windows with an IME the value is 0xe001
2321 * We should probably check to see if an IME exists and if so then
2322 * set this word properly.
2323 */
2324 langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
2325 if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
2326 layout |= 0xe001 << 16; /* FIXME */
2327 else
2328 layout |= layout << 16;
2329
2330 return (HKL)layout;
2331}
2332
2333
2334/***********************************************************************
2335 * GetKeyboardLayoutName (X11DRV.@)
2336 */
2337BOOL X11DRV_GetKeyboardLayoutName(LPWSTR name)
2338{
2339 static const WCHAR formatW[] = {'%','0','8','l','x',0};
2340 DWORD layout;
2341 LANGID langid;
2342
2343 layout = main_key_tab[kbd_layout].lcid;
2344 /* see comment for GetKeyboardLayout */
2345 langid = PRIMARYLANGID(LANGIDFROMLCID(layout));
2346 if (langid == LANG_CHINESE || langid == LANG_JAPANESE || langid == LANG_KOREAN)
2347 layout |= 0xe001 << 16; /* FIXME */
2348 else
2349 layout |= layout << 16;
2350
2351 sprintfW(name, formatW, layout);
2352 TRACE("returning %s\n", debugstr_w(name));
2353 return TRUE;
2354}
2355
2356
2357/***********************************************************************
2358 * LoadKeyboardLayout (X11DRV.@)
2359 */
2360HKL X11DRV_LoadKeyboardLayout(LPCWSTR name, UINT flags)
2361{
2362 FIXME("%s, %04x: stub!\n", debugstr_w(name), flags);
2363 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2364 return 0;
2365}
2366
2367
2368/***********************************************************************
2369 * UnloadKeyboardLayout (X11DRV.@)
2370 */
2371BOOL X11DRV_UnloadKeyboardLayout(HKL hkl)
2372{
2373 FIXME("%p: stub!\n", hkl);
2374 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2375 return FALSE;
2376}
2377
2378
2379/***********************************************************************
2380 * ActivateKeyboardLayout (X11DRV.@)
2381 */
2382HKL X11DRV_ActivateKeyboardLayout(HKL hkl, UINT flags)
2383{
2384 FIXME("%p, %04x: stub!\n", hkl, flags);
2385 SetLastError(ERROR_CALL_NOT_IMPLEMENTED);
2386 return 0;
2387}
2388
2389
2390/***********************************************************************
2391 * X11DRV_MappingNotify
2392 */
2393void X11DRV_MappingNotify( HWND dummy, XEvent *event )
2394{
2395 HWND hwnd;
2396
2397 wine_tsx11_lock();
2398 XRefreshKeyboardMapping(&event->xmapping);
2399 wine_tsx11_unlock();
2400 X11DRV_InitKeyboard();
2401
2402 hwnd = GetFocus();
2403 if (!hwnd) hwnd = GetActiveWindow();
2404 PostMessageW(hwnd, WM_INPUTLANGCHANGEREQUEST,
2405 0 /*FIXME*/, (LPARAM)X11DRV_GetKeyboardLayout(0));
2406}
2407
2408
2409/***********************************************************************
2410 * VkKeyScanEx (X11DRV.@)
2411 *
2412 * Note: Windows ignores HKL parameter and uses current active layout instead
2413 */
2414SHORT X11DRV_VkKeyScanEx(WCHAR wChar, HKL hkl)
2415{
2416 Display *display = thread_display();
2417 KeyCode keycode;
2418 KeySym keysym;
2419 int i, index;
2420 CHAR cChar;
2421 SHORT ret;
2422
2423 /* FIXME: what happens if wChar is not a Latin1 character and CP_UNIXCP
2424 * is UTF-8 (multibyte encoding)?
2425 */
2426 if (!WideCharToMultiByte(CP_UNIXCP, 0, &wChar, 1, &cChar, 1, NULL, NULL))
2427 {
2428 WARN("no translation from unicode to CP_UNIXCP for 0x%02x\n", wChar);
2429 return -1;
2430 }
2431
2432 TRACE("wChar 0x%02x -> cChar '%c'\n", wChar, cChar);
2433
2434 /* char->keysym (same for ANSI chars) */
2435 keysym = (unsigned char)cChar; /* (!) cChar is signed */
2436 if (keysym <= 27) keysym += 0xFF00; /* special chars : return, backspace... */
2437
2438 wine_tsx11_lock();
2439 keycode = XKeysymToKeycode(display, keysym); /* keysym -> keycode */
2440 if (!keycode)
2441 {
2442 if (keysym >= 0xFF00) /* Windows returns 0x0240 + cChar in this case */
2443 {
2444 ret = 0x0240 + cChar; /* 0x0200 indicates a control character */
2445 TRACE(" ... returning ctrl char %#.2x\n", ret);
2446 wine_tsx11_unlock();
2447 return ret;
2448 }
2449 /* It didn't work ... let's try with deadchar code. */
2450 TRACE("retrying with | 0xFE00\n");
2451 keycode = XKeysymToKeycode(display, keysym | 0xFE00);
2452 }
2453 wine_tsx11_unlock();
2454
2455 TRACE("'%c'(%#lx, %lu): got keycode %#.2x (%d)\n",
2456 cChar, keysym, keysym, keycode, keycode);
2457
2458 /* keycode -> (keyc2vkey) vkey */
2459 ret = keyc2vkey[keycode];
2460
2461 if (!keycode || !ret)
2462 {
2463 TRACE("keycode for '%c' not found, returning -1\n", cChar);
2464 return -1;
2465 }
2466
2467 index = -1;
2468 wine_tsx11_lock();
2469 for (i = 0; i < 4; i++) /* find shift state */
2470 {
2471 if (XKeycodeToKeysym(display, keycode, i) == keysym)
2472 {
2473 index = i;
2474 break;
2475 }
2476 }
2477 wine_tsx11_unlock();
2478
2479 switch (index)
2480 {
2481 default:
2482 case -1:
2483 WARN("Keysym %lx not found while parsing the keycode table\n", keysym);
2484 return -1;
2485
2486 case 0: break;
2487 case 1: ret += 0x0100; break;
2488 case 2: ret += 0x0600; break;
2489 case 3: ret += 0x0700; break;
2490 }
2491 /*
2492 index : 0 adds 0x0000
2493 index : 1 adds 0x0100 (shift)
2494 index : ? adds 0x0200 (ctrl)
2495 index : 2 adds 0x0600 (ctrl+alt)
2496 index : 3 adds 0x0700 (ctrl+alt+shift)
2497 */
2498
2499 TRACE(" ... returning %#.2x\n", ret);
2500 return ret;
2501}
2502
2503/***********************************************************************
2504 * MapVirtualKeyEx (X11DRV.@)
2505 */
2506UINT X11DRV_MapVirtualKeyEx(UINT wCode, UINT wMapType, HKL hkl)
2507{
2508 Display *display = thread_display();
2509
2510#define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
2511
2512 TRACE("wCode=0x%x, wMapType=%d, hkl %p\n", wCode, wMapType, hkl);
2513 if (hkl != X11DRV_GetKeyboardLayout(0))
2514 FIXME("keyboard layout %p is not supported\n", hkl);
2515
2516 switch(wMapType) {
2517 case 0: { /* vkey-code to scan-code */
2518 /* let's do vkey -> keycode -> scan */
2519 int keyc;
2520 for (keyc=min_keycode; keyc<=max_keycode; keyc++)
2521 if ((keyc2vkey[keyc] & 0xFF) == wCode)
2522 returnMVK (keyc2scan[keyc] & 0xFF);
2523 TRACE("returning no scan-code.\n");
2524 return 0; }
2525
2526 case 1: { /* scan-code to vkey-code */
2527 /* let's do scan -> keycode -> vkey */
2528 int keyc;
2529 for (keyc=min_keycode; keyc<=max_keycode; keyc++)
2530 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
2531 returnMVK (keyc2vkey[keyc] & 0xFF);
2532 TRACE("returning no vkey-code.\n");
2533 return 0; }
2534
2535 case 2: { /* vkey-code to unshifted ANSI code */
2536 /* we still don't know what "unshifted" means. in windows VK_W (0x57)
2537 * returns 0x57, which is upercase 'W'. So we have to return the uppercase
2538 * key.. Looks like something is wrong with the MS docs?
2539 * This is only true for letters, for example VK_0 returns '0' not ')'.
2540 * - hence we use the lock mask to ensure this happens.
2541 */
2542 /* let's do vkey -> keycode -> (XLookupString) ansi char */
2543 XKeyEvent e;
2544 KeySym keysym;
2545 int keyc;
2546 char s[2];
2547 e.display = display;
2548
2549 e.state = LockMask;
2550 /* LockMask should behave exactly like caps lock - upercase
2551 * the letter keys and thats about it. */
2552
2553 wine_tsx11_lock();
2554
2555 e.keycode = 0;
2556 /* We exit on the first keycode found, to speed up the thing. */
2557 for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2558 { /* Find a keycode that could have generated this virtual key */
2559 if ((keyc2vkey[keyc] & 0xFF) == wCode)
2560 { /* We filter the extended bit, we don't know it */
2561 e.keycode = keyc; /* Store it temporarily */
2562 if ((EVENT_event_to_vkey(0,&e) & 0xFF) != wCode) {
2563 e.keycode = 0; /* Wrong one (ex: because of the NumLock
2564 state), so set it to 0, we'll find another one */
2565 }
2566 }
2567 }
2568
2569 if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
2570 e.keycode = XKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
2571
2572 if (wCode==VK_DECIMAL)
2573 e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2574
2575 if (!e.keycode)
2576 {
2577 WARN("Unknown virtual key %X !!!\n", wCode);
2578 wine_tsx11_unlock();
2579 return 0; /* whatever */
2580 }
2581 TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2582
2583 if (XLookupString(&e, s, 2, &keysym, NULL))
2584 {
2585 wine_tsx11_unlock();
2586 returnMVK (*s);
2587 }
2588
2589 TRACE("returning no ANSI.\n");
2590 wine_tsx11_unlock();
2591 return 0;
2592 }
2593
2594 case 3: /* **NT only** scan-code to vkey-code but distinguish between */
2595 /* left and right */
2596 FIXME(" stub for NT\n");
2597 return 0;
2598
2599 default: /* reserved */
2600 WARN("Unknown wMapType %d !\n", wMapType);
2601 return 0;
2602 }
2603 return 0;
2604}
2605
2606/***********************************************************************
2607 * GetKeyNameText (X11DRV.@)
2608 */
2609INT X11DRV_GetKeyNameText(LONG lParam, LPWSTR lpBuffer, INT nSize)
2610{
2611 int vkey, ansi, scanCode;
2612 KeyCode keyc;
2613 int keyi;
2614 KeySym keys;
2615 char *name;
2616
2617 scanCode = lParam >> 16;
2618 scanCode &= 0x1ff; /* keep "extended-key" flag with code */
2619
2620 /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
2621 vkey = X11DRV_MapVirtualKeyEx(scanCode, 1, X11DRV_GetKeyboardLayout(0));
2622
2623 /* handle "don't care" bit (0x02000000) */
2624 if (!(lParam & 0x02000000)) {
2625 switch (vkey) {
2626 case VK_LSHIFT:
2627 case VK_RSHIFT:
2628 vkey = VK_SHIFT;
2629 break;
2630 case VK_LCONTROL:
2631 case VK_RCONTROL:
2632 vkey = VK_CONTROL;
2633 break;
2634 case VK_LMENU:
2635 case VK_RMENU:
2636 vkey = VK_MENU;
2637 break;
2638 default:
2639 break;
2640 }
2641 }
2642
2643 ansi = X11DRV_MapVirtualKeyEx(vkey, 2, X11DRV_GetKeyboardLayout(0));
2644 TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
2645
2646 /* first get the name of the "regular" keys which is the Upper case
2647 value of the keycap imprint. */
2648 if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
2649 (scanCode != 0x137) && /* PrtScn */
2650 (scanCode != 0x135) && /* numpad / */
2651 (scanCode != 0x37 ) && /* numpad * */
2652 (scanCode != 0x4a ) && /* numpad - */
2653 (scanCode != 0x4e ) ) /* numpad + */
2654 {
2655 if ((nSize >= 2) && lpBuffer)
2656 {
2657 *lpBuffer = toupperW((WCHAR)ansi);
2658 *(lpBuffer+1) = 0;
2659 return 1;
2660 }
2661 else
2662 return 0;
2663 }
2664
2665 /* FIXME: horrible hack to fix function keys. Windows reports scancode
2666 without "extended-key" flag. However Wine generates scancode
2667 *with* "extended-key" flag. Seems to occur *only* for the
2668 function keys. Soooo.. We will leave the table alone and
2669 fudge the lookup here till the other part is found and fixed!!! */
2670
2671 if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
2672 (scanCode == 0x157) || (scanCode == 0x158))
2673 scanCode &= 0xff; /* remove "extended-key" flag for Fx keys */
2674
2675 /* let's do scancode -> keycode -> keysym -> String */
2676
2677 for (keyi=min_keycode; keyi<=max_keycode; keyi++)
2678 if ((keyc2scan[keyi]) == scanCode)
2679 break;
2680 if (keyi <= max_keycode)
2681 {
2682 wine_tsx11_lock();
2683 keyc = (KeyCode) keyi;
2684 keys = XKeycodeToKeysym(thread_display(), keyc, 0);
2685 name = XKeysymToString(keys);
2686 wine_tsx11_unlock();
2687 TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
2688 scanCode, keyc, (int)keys, name);
2689 if (lpBuffer && nSize && name)
2690 {
2691 MultiByteToWideChar(CP_UNIXCP, 0, name, -1, lpBuffer, nSize);
2692 lpBuffer[nSize - 1] = 0;
2693 return 1;
2694 }
2695 }
2696
2697 /* Finally issue WARN for unknown keys */
2698
2699 WARN("(%08x,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
2700 if (lpBuffer && nSize)
2701 *lpBuffer = 0;
2702 return 0;
2703}
2704#endif /* OUTOFWINE not defined */
2705
2706/***********************************************************************
2707 * X11DRV_KEYBOARD_MapDeadKeysym
2708 */
2709static char KEYBOARD_MapDeadKeysym(KeySym keysym)
2710{
2711 switch (keysym)
2712 {
2713 /* symbolic ASCII is the same as defined in rfc1345 */
2714#ifdef XK_dead_tilde
2715 case XK_dead_tilde :
2716#endif
2717 case 0x1000FE7E : /* Xfree's XK_Dtilde */
2718 return '~'; /* '? */
2719#ifdef XK_dead_acute
2720 case XK_dead_acute :
2721#endif
2722 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
2723 return (char)0xb4; /* '' */
2724#ifdef XK_dead_circumflex
2725 case XK_dead_circumflex:
2726#endif
2727 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
2728 return '^'; /* '> */
2729#ifdef XK_dead_grave
2730 case XK_dead_grave :
2731#endif
2732 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
2733 return '`'; /* '! */
2734#ifdef XK_dead_diaeresis
2735 case XK_dead_diaeresis :
2736#endif
2737 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
2738 return (char)0xa8; /* ': */
2739#ifdef XK_dead_cedilla
2740 case XK_dead_cedilla :
2741 return (char)0xb8; /* ', */
2742#endif
2743#ifdef XK_dead_macron
2744 case XK_dead_macron :
2745 return '-'; /* 'm isn't defined on iso-8859-x */
2746#endif
2747#ifdef XK_dead_breve
2748 case XK_dead_breve :
2749 return (char)0xa2; /* '( */
2750#endif
2751#ifdef XK_dead_abovedot
2752 case XK_dead_abovedot :
2753 return (char)0xff; /* '. */
2754#endif
2755#ifdef XK_dead_abovering
2756 case XK_dead_abovering :
2757 return '0'; /* '0 isn't defined on iso-8859-x */
2758#endif
2759#ifdef XK_dead_doubleacute
2760 case XK_dead_doubleacute :
2761 return (char)0xbd; /* '" */
2762#endif
2763#ifdef XK_dead_caron
2764 case XK_dead_caron :
2765 return (char)0xb7; /* '< */
2766#endif
2767#ifdef XK_dead_ogonek
2768 case XK_dead_ogonek :
2769 return (char)0xb2; /* '; */
2770#endif
2771/* FIXME: I don't know this three.
2772 case XK_dead_iota :
2773 return 'i';
2774 case XK_dead_voiced_sound :
2775 return 'v';
2776 case XK_dead_semivoiced_sound :
2777 return 's';
2778*/
2779 }
2780 TRACE("no character for dead keysym 0x%08lx\n",keysym);
2781 return 0;
2782}
2783
2784#ifndef OUTOFWINE
2785/***********************************************************************
2786 * ToUnicodeEx (X11DRV.@)
2787 *
2788 * The ToUnicode function translates the specified virtual-key code and keyboard
2789 * state to the corresponding Windows character or characters.
2790 *
2791 * If the specified key is a dead key, the return value is negative. Otherwise,
2792 * it is one of the following values:
2793 * Value Meaning
2794 * 0 The specified virtual key has no translation for the current state of the keyboard.
2795 * 1 One Windows character was copied to the buffer.
2796 * 2 Two characters were copied to the buffer. This usually happens when a
2797 * dead-key character (accent or diacritic) stored in the keyboard layout cannot
2798 * be composed with the specified virtual key to form a single character.
2799 *
2800 * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
2801 *
2802 */
2803INT X11DRV_ToUnicodeEx(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
2804 LPWSTR bufW, int bufW_size, UINT flags, HKL hkl)
2805{
2806 Display *display = thread_display();
2807 XKeyEvent e;
2808 KeySym keysym = 0;
2809 INT ret;
2810 int keyc;
2811 char lpChar[10];
2812 HWND focus;
2813 XIC xic;
2814 Status status;
2815
2816 if (scanCode & 0x8000)
2817 {
2818 TRACE("Key UP, doing nothing\n" );
2819 return 0;
2820 }
2821
2822 if (hkl != X11DRV_GetKeyboardLayout(0))
2823 FIXME("keyboard layout %p is not supported\n", hkl);
2824
2825 if ((lpKeyState[VK_MENU] & 0x80) && (lpKeyState[VK_CONTROL] & 0x80))
2826 {
2827 TRACE("Ctrl+Alt+[key] won't generate a character\n");
2828 return 0;
2829 }
2830
2831 e.display = display;
2832 e.keycode = 0;
2833 e.state = 0;
2834 e.type = KeyPress;
2835
2836 focus = GetFocus();
2837 if (focus) focus = GetAncestor( focus, GA_ROOT );
2838 if (!focus) focus = GetActiveWindow();
2839 e.window = X11DRV_get_whole_window( focus );
2840 xic = X11DRV_get_ic( focus );
2841
2842 if (lpKeyState[VK_SHIFT] & 0x80)
2843 {
2844 TRACE("ShiftMask = %04x\n", ShiftMask);
2845 e.state |= ShiftMask;
2846 }
2847 if (lpKeyState[VK_CAPITAL] & 0x01)
2848 {
2849 TRACE("LockMask = %04x\n", LockMask);
2850 e.state |= LockMask;
2851 }
2852 if (lpKeyState[VK_CONTROL] & 0x80)
2853 {
2854 TRACE("ControlMask = %04x\n", ControlMask);
2855 e.state |= ControlMask;
2856 }
2857 if (lpKeyState[VK_NUMLOCK] & 0x01)
2858 {
2859 TRACE("NumLockMask = %04x\n", NumLockMask);
2860 e.state |= NumLockMask;
2861 }
2862
2863 /* Restore saved AltGr state */
2864 TRACE("AltGrMask = %04x\n", AltGrMask);
2865 e.state |= AltGrMask;
2866
2867 TRACE_(key)("(%04X, %04X) : faked state = 0x%04x\n",
2868 virtKey, scanCode, e.state);
2869 wine_tsx11_lock();
2870 /* We exit on the first keycode found, to speed up the thing. */
2871 for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
2872 { /* Find a keycode that could have generated this virtual key */
2873 if ((keyc2vkey[keyc] & 0xFF) == virtKey)
2874 { /* We filter the extended bit, we don't know it */
2875 e.keycode = keyc; /* Store it temporarily */
2876 if ((EVENT_event_to_vkey(xic,&e) & 0xFF) != virtKey) {
2877 e.keycode = 0; /* Wrong one (ex: because of the NumLock
2878 state), so set it to 0, we'll find another one */
2879 }
2880 }
2881 }
2882
2883 if (virtKey >= VK_LEFT && virtKey <= VK_DOWN)
2884 e.keycode = XKeysymToKeycode(e.display, virtKey - VK_LEFT + XK_Left);
2885
2886 if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
2887 e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
2888
2889 if (virtKey==VK_DECIMAL)
2890 e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
2891
2892 if (virtKey==VK_SEPARATOR)
2893 e.keycode = XKeysymToKeycode(e.display, XK_KP_Separator);
2894
2895 if (!e.keycode && virtKey != VK_NONAME)
2896 {
2897 WARN("Unknown virtual key %X !!!\n", virtKey);
2898 wine_tsx11_unlock();
2899 return 0;
2900 }
2901 else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
2902
2903 TRACE_(key)("type %d, window %lx, state 0x%04x, keycode 0x%04x\n",
2904 e.type, e.window, e.state, e.keycode);
2905
2906 /* Clients should pass only KeyPress events to XmbLookupString,
2907 * e.type was set to KeyPress above.
2908 */
2909 if (xic)
2910 ret = XmbLookupString(xic, &e, lpChar, sizeof(lpChar), &keysym, &status);
2911 else
2912 ret = XLookupString(&e, lpChar, sizeof(lpChar), &keysym, NULL);
2913 wine_tsx11_unlock();
2914
2915 if (ret == 0)
2916 {
2917 char dead_char;
2918
2919#ifdef XK_EuroSign
2920 /* An ugly hack for EuroSign: X can't translate it to a character
2921 for some locales. */
2922 if (keysym == XK_EuroSign)
2923 {
2924 bufW[0] = 0x20AC;
2925 ret = 1;
2926 goto found;
2927 }
2928#endif
2929 /* Special case: X turns shift-tab into ISO_Left_Tab. */
2930 /* Here we change it back. */
2931 if (keysym == XK_ISO_Left_Tab)
2932 {
2933 bufW[0] = 0x09;
2934 ret = 1;
2935 goto found;
2936 }
2937
2938 dead_char = KEYBOARD_MapDeadKeysym(keysym);
2939 if (dead_char)
2940 {
2941 MultiByteToWideChar(CP_UNIXCP, 0, &dead_char, 1, bufW, bufW_size);
2942 ret = -1;
2943 goto found;
2944 }
2945
2946 if (keysym >= 0x01000100 && keysym <= 0x0100ffff)
2947 {
2948 /* Unicode direct mapping */
2949 bufW[0] = keysym & 0xffff;
2950 ret = 1;
2951 goto found;
2952 }
2953 else if ((keysym >> 8) == 0x1008FF) {
2954 bufW[0] = 0;
2955 ret = 0;
2956 goto found;
2957 }
2958 else
2959 {
2960 const char *ksname;
2961
2962 wine_tsx11_lock();
2963 ksname = XKeysymToString(keysym);
2964 wine_tsx11_unlock();
2965 if (!ksname)
2966 ksname = "No Name";
2967 if ((keysym >> 8) != 0xff)
2968 {
2969 WARN("no char for keysym %04lX (%s) :\n",
2970 keysym, ksname);
2971 WARN("virtKey=%X, scanCode=%X, keycode=%X, state=%X\n",
2972 virtKey, scanCode, e.keycode, e.state);
2973 }
2974 }
2975 }
2976 else { /* ret != 0 */
2977 /* We have a special case to handle : Shift + arrow, shift + home, ...
2978 X returns a char for it, but Windows doesn't. Let's eat it. */
2979 if (!(e.state & NumLockMask) /* NumLock is off */
2980 && (e.state & ShiftMask) /* Shift is pressed */
2981 && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
2982 {
2983 lpChar[0] = 0;
2984 ret = 0;
2985 }
2986
2987 /* more areas where X returns characters but Windows does not
2988 CTRL + number or CTRL + symbol */
2989 if (e.state & ControlMask)
2990 {
2991 if (((keysym>=33) && (keysym < 'A')) ||
2992 ((keysym > 'Z') && (keysym < 'a')))
2993 {
2994 lpChar[0] = 0;
2995 ret = 0;
2996 }
2997 }
2998
2999 /* We have another special case for delete key (XK_Delete) on an
3000 extended keyboard. X returns a char for it, but Windows doesn't */
3001 if (keysym == XK_Delete)
3002 {
3003 lpChar[0] = 0;
3004 ret = 0;
3005 }
3006 else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
3007 && (keysym == XK_KP_Decimal))
3008 {
3009 lpChar[0] = 0;
3010 ret = 0;
3011 }
3012
3013 /* Hack to detect an XLookupString hard-coded to Latin1 */
3014 if (ret == 1 && keysym >= 0x00a0 && keysym <= 0x00ff && (BYTE)lpChar[0] == keysym)
3015 {
3016 bufW[0] = (BYTE)lpChar[0];
3017 goto found;
3018 }
3019
3020 /* perform translation to unicode */
3021 if(ret)
3022 {
3023 TRACE_(key)("Translating char 0x%02x to unicode\n", *(BYTE *)lpChar);
3024 ret = MultiByteToWideChar(CP_UNIXCP, 0, lpChar, ret, bufW, bufW_size);
3025 }
3026 }
3027
3028found:
3029 TRACE_(key)("ToUnicode about to return %d with char %x %s\n",
3030 ret, (ret && bufW) ? bufW[0] : 0, bufW ? "" : "(no buffer)");
3031 return ret;
3032}
3033
3034/***********************************************************************
3035 * Beep (X11DRV.@)
3036 */
3037void X11DRV_Beep(void)
3038{
3039 wine_tsx11_lock();
3040 XBell(thread_display(), 0);
3041 wine_tsx11_unlock();
3042}
3043#else /* OUTOFWINE defined */
3044int X11DRV_GetKeysymsPerKeycode()
3045{
3046 return keysyms_per_keycode;
3047}
3048#endif /* OUTOFWINE defined */
Note: See TracBrowser for help on using the repository browser.

© 2023 Oracle
ContactPrivacy policyTerms of Use