VirtualBox

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

Last change on this file since 2529 was 2529, checked in by vboxsync, 18 years ago

Reactivated and updated the Wine keyboard code for VirtualBox on remote X11 displays

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette