blob: b65dcbb4cdf7b629438ddd9668386e1b8fd84349 [file] [log] [blame]
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001/*
Ove Kaaven7173e1c1999-03-14 14:00:57 +00002 * X11 keyboard driver
Patrik Stridvalle35d6361998-12-07 09:13:40 +00003 *
4 * Copyright 1993 Bob Amstadt
Vincent Béron9a624912002-05-31 23:06:46 +00005 * Copyright 1996 Albrecht Kleine
Patrik Stridvalle35d6361998-12-07 09:13:40 +00006 * Copyright 1997 David Faure
7 * Copyright 1998 Morten Welinder
8 * Copyright 1998 Ulrich Weigand
Ove Kaaven7173e1c1999-03-14 14:00:57 +00009 * Copyright 1999 Ove Kåven
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000010 *
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation; either
14 * version 2.1 of the License, or (at your option) any later version.
15 *
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
20 *
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Patrik Stridvalle35d6361998-12-07 09:13:40 +000024 */
25
26#include "config.h"
27
Patrik Stridvalle35d6361998-12-07 09:13:40 +000028#include <X11/Xatom.h>
29#include <X11/keysym.h>
Patrik Stridvall3d511612000-04-25 19:55:35 +000030
Patrik Stridvalle35d6361998-12-07 09:13:40 +000031#include "ts_xlib.h"
Alexandre Julliarde9119c12002-09-24 18:36:51 +000032#include <X11/Xresource.h>
33#include <X11/Xutil.h>
Ove Kaavenc90fb252001-01-02 22:39:14 +000034#ifdef HAVE_XKB
35#include <X11/XKBlib.h>
36#endif
Patrik Stridvalle35d6361998-12-07 09:13:40 +000037
Patrik Stridvall3d511612000-04-25 19:55:35 +000038#include <ctype.h>
39#include <string.h>
40
Dimitrie O. Paun297f3d82003-01-07 20:36:20 +000041#define NONAMELESSUNION
42#define NONAMELESSSTRUCT
Jeremy Whited3e22d92000-02-10 19:03:02 +000043#include "windef.h"
44#include "wingdi.h"
Veksler Michaele94e3541999-03-22 12:41:26 +000045#include "wine/winuser16.h"
Ove Kaaven7173e1c1999-03-14 14:00:57 +000046#include "winnls.h"
Patrik Stridvall6cc47d42000-03-08 18:26:56 +000047#include "win.h"
Patrik Stridvalld96e1f11999-07-04 13:31:03 +000048#include "x11drv.h"
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000049#include "wine/debug.h"
Patrik Stridvalle35d6361998-12-07 09:13:40 +000050
Alexandre Julliard0799c1a2002-03-09 23:29:33 +000051WINE_DEFAULT_DEBUG_CHANNEL(keyboard);
52WINE_DECLARE_DEBUG_CHANNEL(key);
53WINE_DECLARE_DEBUG_CHANNEL(dinput);
Patrik Stridvalld96e1f11999-07-04 13:31:03 +000054
Patrik Stridvalle35d6361998-12-07 09:13:40 +000055int min_keycode, max_keycode, keysyms_per_keycode;
Ove Kaaven7173e1c1999-03-14 14:00:57 +000056WORD keyc2vkey[256], keyc2scan[256];
Patrik Stridvalle35d6361998-12-07 09:13:40 +000057
Alexandre Julliard4b626182001-10-17 17:50:02 +000058static LPBYTE pKeyStateTable;
Patrik Stridvalle35d6361998-12-07 09:13:40 +000059static int NumLockMask, AltGrMask; /* mask in the XKeyEvent state */
60static int kcControl, kcAlt, kcShift, kcNumLock, kcCapsLock; /* keycodes */
61
Marcus Meissner2199f6e1999-04-01 12:05:44 +000062static char KEYBOARD_MapDeadKeysym(KeySym keysym);
63
Patrik Stridvalle35d6361998-12-07 09:13:40 +000064/* Keyboard translation tables */
Mauro Carvalho Chehab9a1c52e2002-12-19 21:14:47 +000065#define MAIN_LEN 49
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +000066static const WORD main_key_scan_qwerty[MAIN_LEN] =
Ove Kaaven7173e1c1999-03-14 14:00:57 +000067{
68/* this is my (102-key) keyboard layout, sorry if it doesn't quite match yours */
Paul Rupec86e5c92002-04-08 20:15:32 +000069 /* ` 1 2 3 4 5 6 7 8 9 0 - = */
Ove Kaaven7173e1c1999-03-14 14:00:57 +000070 0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
Paul Rupec86e5c92002-04-08 20:15:32 +000071 /* q w e r t y u i o p [ ] */
Ove Kaaven7173e1c1999-03-14 14:00:57 +000072 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
Paul Rupec86e5c92002-04-08 20:15:32 +000073 /* a s d f g h j k l ; ' \ */
Ove Kaaven7173e1c1999-03-14 14:00:57 +000074 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
Paul Rupec86e5c92002-04-08 20:15:32 +000075 /* z x c v b n m , . / */
Ove Kaaven7173e1c1999-03-14 14:00:57 +000076 0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
Ove Kaaven44b71781999-03-15 15:24:32 +000077 0x56 /* the 102nd key (actually to the right of l-shift) */
Ove Kaaven7173e1c1999-03-14 14:00:57 +000078};
79
Mauro Carvalho Chehab9a1c52e2002-12-19 21:14:47 +000080static const WORD main_key_scan_abnt_qwerty[MAIN_LEN] =
81{
82 /* ` 1 2 3 4 5 6 7 8 9 0 - = */
83 0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,
84 /* q w e r t y u i o p [ ] */
85 0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1A,0x1B,
86 /* a s d f g h j k l ; ' \ */
87 0x1E,0x1F,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x2B,
88 /* \ z x c v b n m , . / */
89 0x5e,0x2C,0x2D,0x2E,0x2F,0x30,0x31,0x32,0x33,0x34,0x35,
90 0x56, /* the 102nd key (actually to the right of l-shift) */
91};
92
Paul Rupec86e5c92002-04-08 20:15:32 +000093static const WORD main_key_scan_dvorak[MAIN_LEN] =
94{
95 /* ` 1 2 3 4 5 6 7 8 9 0 [ ] */
96 0x29,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x1A,0x1B,
97 /* ' , . p y f g c r l / = */
98 0x28,0x33,0x34,0x19,0x15,0x21,0x22,0x2E,0x13,0x26,0x35,0x0D,
99 /* a o e u i d h t n s - \ */
100 0x1E,0x18,0x12,0x16,0x17,0x20,0x23,0x14,0x31,0x1F,0x0C,0x2B,
101 /* ; q j k x b m w v z */
102 0x27,0x10,0x24,0x25,0x2D,0x30,0x32,0x11,0x2F,0x2C,
103 0x56 /* the 102nd key (actually to the right of l-shift) */
104};
105
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +0000106static const WORD main_key_vkey_qwerty[MAIN_LEN] =
107{
Dmitry Timoshkovff81f932000-10-19 22:25:35 +0000108/* NOTE: this layout must concur with the scan codes layout above */
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +0000109 VK_OEM_3,VK_1,VK_2,VK_3,VK_4,VK_5,VK_6,VK_7,VK_8,VK_9,VK_0,VK_OEM_MINUS,VK_OEM_PLUS,
110 VK_Q,VK_W,VK_E,VK_R,VK_T,VK_Y,VK_U,VK_I,VK_O,VK_P,VK_OEM_4,VK_OEM_6,
111 VK_A,VK_S,VK_D,VK_F,VK_G,VK_H,VK_J,VK_K,VK_L,VK_OEM_1,VK_OEM_7,VK_OEM_5,
112 VK_Z,VK_X,VK_C,VK_V,VK_B,VK_N,VK_M,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
113 VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
114};
115
Mauro Carvalho Chehab9a1c52e2002-12-19 21:14:47 +0000116static const WORD main_key_vkey_abnt_qwerty[MAIN_LEN] =
117{
118/* NOTE: this layout must concur with the scan codes layout above */
119 VK_OEM_3,VK_1,VK_2,VK_3,VK_4,VK_5,VK_6,VK_7,VK_8,VK_9,VK_0,VK_OEM_MINUS,VK_OEM_PLUS,
120 VK_Q,VK_W,VK_E,VK_R,VK_T,VK_Y,VK_U,VK_I,VK_O,VK_P,VK_OEM_4,VK_OEM_6,
121 VK_A,VK_S,VK_D,VK_F,VK_G,VK_H,VK_J,VK_K,VK_L,VK_OEM_1,VK_OEM_8,VK_OEM_5,
122 VK_OEM_7,VK_Z,VK_X,VK_C,VK_V,VK_B,VK_N,VK_M,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,
123 VK_OEM_102, /* the 102nd key (actually to the right of l-shift) */
124};
125
Dmitry Timoshkovff81f932000-10-19 22:25:35 +0000126static const WORD main_key_vkey_azerty[MAIN_LEN] =
127{
128/* NOTE: this layout must concur with the scan codes layout above */
129 VK_OEM_7,VK_1,VK_2,VK_3,VK_4,VK_5,VK_6,VK_7,VK_8,VK_9,VK_0,VK_OEM_4,VK_OEM_PLUS,
130 VK_A,VK_Z,VK_E,VK_R,VK_T,VK_Y,VK_U,VK_I,VK_O,VK_P,VK_OEM_6,VK_OEM_1,
131 VK_Q,VK_S,VK_D,VK_F,VK_G,VK_H,VK_J,VK_K,VK_L,VK_M,VK_OEM_3,VK_OEM_5,
132 VK_W,VK_X,VK_C,VK_V,VK_B,VK_N,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,VK_OEM_8,
133 VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
134};
135
Paul Rupec86e5c92002-04-08 20:15:32 +0000136static const WORD main_key_vkey_dvorak[MAIN_LEN] =
137{
138/* NOTE: this layout must concur with the scan codes layout above */
139 VK_OEM_3,VK_1,VK_2,VK_3,VK_4,VK_5,VK_6,VK_7,VK_8,VK_9,VK_0,VK_OEM_4,VK_OEM_6,
140 VK_OEM_7,VK_OEM_COMMA,VK_OEM_PERIOD,VK_P,VK_Y,VK_F,VK_G,VK_C,VK_R,VK_L,VK_OEM_2,VK_OEM_PLUS,
141 VK_A,VK_O,VK_E,VK_U,VK_I,VK_D,VK_H,VK_T,VK_N,VK_S,VK_OEM_MINUS,VK_OEM_5,
142 VK_OEM_1,VK_Q,VK_J,VK_K,VK_X,VK_B,VK_M,VK_W,VK_V,VK_Z,
143 VK_OEM_102 /* the 102nd key (actually to the right of l-shift) */
144};
145
146/* FIXME: add other layouts, such as German QWERTZ */
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +0000147
Ove Kaaven7173e1c1999-03-14 14:00:57 +0000148/*** DEFINE YOUR NEW LANGUAGE-SPECIFIC MAPPINGS BELOW, SEE EXISTING TABLES */
149
Ove Kaaven44b71781999-03-15 15:24:32 +0000150/* the VK mappings for the main keyboard will be auto-assigned as before,
151 so what we have here is just the character tables */
Ove Kaaven7173e1c1999-03-14 14:00:57 +0000152/* order: Normal, Shift, AltGr, Shift-AltGr */
Ove Kaaven44b71781999-03-15 15:24:32 +0000153/* We recommend you write just what is guaranteed to be correct (i.e. what's
154 written on the keycaps), not the bunch of special characters behind AltGr
155 and Shift-AltGr if it can vary among different X servers */
156/* Remember that your 102nd key (to the right of l-shift) should be on a
157 separate line, see existing tables */
158/* If Wine fails to match your new table, use -debugmsg +key to find out why */
159/* Remember to also add your new table to the layout index table far below! */
Ove Kaaven7173e1c1999-03-14 14:00:57 +0000160
Axel Schmidt46a9db62002-03-11 01:12:07 +0000161/*** German Logitech Desktop Pro keyboard layout */
162static const char main_key_DE_logitech[MAIN_LEN][4] =
163{
164 "^\xb0","1!","2\"","3\xa7","4$","5%","6&","7/{","8([","9)]","0=}","\xdf?\\","'`",
165 "qQ@","wW","eE","rR","tT","zZ","uU","iI","oO","pP","\xfc\xdc","+*~",
166 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","\xf6\xd6","\xe4\xc4","#'",
167 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
168 "<>|"
169};
170
Ove Kaaven44b71781999-03-15 15:24:32 +0000171/*** United States keyboard layout (mostly contributed by Uwe Bonnes) */
Ove Kaaven7173e1c1999-03-14 14:00:57 +0000172static const char main_key_US[MAIN_LEN][4] =
173{
Ove Kaaven44b71781999-03-15 15:24:32 +0000174 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
175 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
176 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
177 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?"
Ove Kaaven7173e1c1999-03-14 14:00:57 +0000178};
179
Ove Kaavenfc091b22000-01-04 00:28:31 +0000180/*** United States keyboard layout (phantom key version) */
181/* (XFree86 reports the <> key even if it's not physically there) */
182static const char main_key_US_phantom[MAIN_LEN][4] =
183{
184 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
185 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
186 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"","\\|",
Mike McCormack88c5bc62000-09-04 20:19:27 +0000187 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
Ove Kaavenfc091b22000-01-04 00:28:31 +0000188 "<>" /* the phantom key */
189};
190
Paul Rupec86e5c92002-04-08 20:15:32 +0000191/*** United States keyboard layout (dvorak version) */
192static const char main_key_US_dvorak[MAIN_LEN][4] =
193{
194 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","[{","]}",
195 "'\"",",<",".>","pP","yY","fF","gG","cC","rR","lL","/?","=+",
196 "aA","oO","eE","uU","iI","dD","hH","tT","nN","sS","-_","\\|",
197 ";:","qQ","jJ","kK","xX","bB","mM","wW","vV","zZ"
198};
199
Huw D M Davies12eb5fd1999-03-17 15:29:35 +0000200/*** British keyboard layout */
201static const char main_key_UK[MAIN_LEN][4] =
202{
203 "`","1!","2\"","3£","4$","5%","6^","7&","8*","9(","0)","-_","=+",
204 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
205 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'@","#~",
206 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
207 "\\|"
208};
209
Ove Kaaven44b71781999-03-15 15:24:32 +0000210/*** French keyboard layout (contributed by Eric Pouech) */
211static const char main_key_FR[MAIN_LEN][4] =
212{
Sylvain Petreolle656dc7a2003-06-13 18:54:00 +0000213 "²","&1","é2~","\"3#","'4{","(5[","-6|","è7`","_8\\","ç9^±","à0@",")°]","=+}",
214 "aA","zZ","eE¿","rR","tT","yY","uU","iI","oO","pP","^¨","$£¤",
Ove Kaaven44b71781999-03-15 15:24:32 +0000215 "qQ","sSß","dD","fF","gG","hH","jJ","kK","lL","mM","ù%","*µ",
216 "wW","xX","cC","vV","bB","nN",",?",";.",":/","!§",
217 "<>"
218};
219
Rikhardur Egilsson365c54e1999-05-29 11:04:09 +0000220/*** Icelandic keyboard layout (contributed by Ríkharður Egilsson) */
221static const char main_key_IS[MAIN_LEN][4] =
222{
223 "°","1!","2\"","3#","4$","5%","6&","7/{","8([","9)]","0=}","öÖ\\","-_",
224 "qQ@","wW","eE","rR","tT","yY","uU","iI","oO","pP","ðÐ","'?~",
225 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","æÆ","´^","+*`",
226 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","þÞ",
227 "<>|"
228};
229
Ove Kaaven44b71781999-03-15 15:24:32 +0000230/*** German keyboard layout (contributed by Ulrich Weigand) */
231static const char main_key_DE[MAIN_LEN][4] =
232{
Johannes E. Schindelin0ba59092001-02-28 21:41:17 +0000233 "^°","1!","2\"²","3§³","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","'`",
234 "qQ@","wW","eE€","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
Ove Kaaven44b71781999-03-15 15:24:32 +0000235 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#´",
Johannes E. Schindelin0ba59092001-02-28 21:41:17 +0000236 "yY","xX","cC","vV","bB","nN","mMµ",",;",".:","-_",
237 "<>|"
Ove Kaaven44b71781999-03-15 15:24:32 +0000238};
239
Marcus Meissnere14deff1999-10-13 12:18:03 +0000240/*** German keyboard layout without dead keys */
241static const char main_key_DE_nodead[MAIN_LEN][4] =
242{
243 "^°","1!","2\"","3§","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","´",
244 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
245 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
246 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
247 "<>"
248};
249
Matthias Fechner94e9a6f2002-03-20 01:28:20 +0000250/*** German keyboard layout without dead keys 105 Keys (contributed by Matthias Fechner)*/
251static const char main_key_DE_nodead_105[MAIN_LEN][4] =
252{
253 "^°","1!","2\"²","3§³","4$","5%","6&","7/{","8([","9)]","0=}","ß?\\","'`",
254 "qQ@","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üÜ","+*~",
255 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","#'",
256 "<>|","yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
257};
258
Jonathan Naylora5a02271999-03-28 12:36:27 +0000259/*** Swiss German keyboard layout (contributed by Jonathan Naylor) */
260static const char main_key_SG[MAIN_LEN][4] =
261{
262 "§°","1+|","2\"@","3*#","4ç","5%","6&¬","7/¦","8(¢","9)","0=","'?´","^`~",
263 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","üè[","¨!]",
264 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öé","äà{","$£}",
265 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
266 "<>\\"
267};
268
Philippe Froidevauxc778d9b1999-06-22 19:01:14 +0000269/*** Swiss French keyboard layout (contributed by Philippe Froidevaux) */
270static const char main_key_SF[MAIN_LEN][4] =
271{
272 "§°","1+|","2\"@","3*#","4ç","5%","6&¬","7/¦","8(¢","9)","0=","'?´","^`~",
273 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","èü[","¨!]",
274 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","éö","àä{","$£}",
275 "yY","xX","cC","vV","bB","nN","mM",",;",".:","-_",
276 "<>\\"
277};
278
Ove Kaaven44b71781999-03-15 15:24:32 +0000279/*** Norwegian keyboard layout (contributed by Ove Kåven) */
Ove Kaaven7173e1c1999-03-14 14:00:57 +0000280static const char main_key_NO[MAIN_LEN][4] =
281{
282 "|§","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?","\\`´",
283 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^~",
284 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","øØ","æÆ","'*",
285 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
286 "<>"
287};
288
Ove Kaaven44b71781999-03-15 15:24:32 +0000289/*** Danish keyboard layout (contributed by Bertho Stultiens) */
290static const char main_key_DA[MAIN_LEN][4] =
291{
Bertho Stultiensff2b3691999-03-19 16:42:52 +0000292 "½§","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?","´`|",
Ove Kaaven44b71781999-03-15 15:24:32 +0000293 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^~",
294 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","æÆ","øØ","'*",
295 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
296 "<>\\"
297};
298
Peter Bortas1e24a081999-04-25 10:53:22 +0000299/*** Swedish keyboard layout (contributed by Peter Bortas) */
300static const char main_key_SE[MAIN_LEN][4] =
301{
302 "§½","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?\\","´`",
303 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","åÅ","¨^~",
304 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*",
305 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
306 "<>|"
307};
308
Raul Metsma77d6a072002-04-17 16:49:15 +0000309/*** Estonian keyboard layout (contributed by Raul Metsma zombi82@hot.ee) */
310static const char main_key_ET[MAIN_LEN][4] =
311{
312 " ~","1!","2\"@","3#£","4¤$","5%","6&","7/{","8([","9)]","0=}","+?\\","´`",
313 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","üÜ","õÕ§",
314 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","öÖ","äÄ","'*½",
315 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
316 "<>|"
317};
318
Robert Pouliot5574c991999-03-17 15:39:36 +0000319/*** Canadian French keyboard layout */
320static const char main_key_CF[MAIN_LEN][4] =
321{
Ivan De Saedeleer0e65a491999-08-04 14:28:03 +0000322 "#|\\","1!±","2\"@","3/£","4$¢","5%¤","6?¬","7&¦","8*²","9(³","0)¼","-_½","=+¾",
323 "qQ","wW","eE","rR","tT","yY","uU","iI","oO§","pP¶","^^[","¸¨]",
Robert Pouliot5574c991999-03-17 15:39:36 +0000324 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:~","``{","<>}",
Ivan De Saedeleer0e65a491999-08-04 14:28:03 +0000325 "zZ","xX","cC","vV","bB","nN","mM",",'-",".","éÉ",
Robert Pouliot4f278bd1999-03-21 15:46:34 +0000326 "«»°"
Robert Pouliot5574c991999-03-17 15:39:36 +0000327};
328
Bruno Afonsoe70b1831999-03-17 15:54:44 +0000329/*** Portuguese keyboard layout */
330static const char main_key_PT[MAIN_LEN][4] =
331{
332 "\\¦","1!","2\"@","3#£","4$§","5%","6&","7/{","8([","9)]","0=}","'?","«»",
333 "qQ", "wW","eE", "rR", "tT", "yY", "uU", "iI", "oO", "pP", "+*\\¨","\\'\\`",
334 "aA", "sS","dD", "fF", "gG", "hH", "jJ", "kK", "lL", "çÇ", "ºª", "\\~\\^",
335 "zZ", "xX","cC", "vV", "bB", "nN", "mM", ",;", ".:", "-_",
336 "<>"
337};
338
75793af1999-05-13 18:49:47 +0000339/*** Italian keyboard layout */
340static const char main_key_IT[MAIN_LEN][4] =
341{
Giovanni Pancottif708f542000-09-07 21:04:06 +0000342 "\\|","1!¹","2\"²","3£³","4$¼","5%½","6&¾","7/{","8([","9)]","0=}","'?`","ì^~",
343 "qQ@","wW","eE","rR","tT","yY","uU","iI","oOø","pPþ","èé[","+*]",
344 "aA","sSß","dDð","fF","gG","hH","jJ","kK","lL","òç@","à°#","ù§",
345 "zZ","xX","cC","vV","bB","nN","mMµ",",;",".:·","-_",
346 "<>|"
75793af1999-05-13 18:49:47 +0000347};
348
Kalevi J Hautaniemicc5d9241999-03-22 14:46:08 +0000349/*** Finnish keyboard layout */
350static const char main_key_FI[MAIN_LEN][4] =
351{
352 "","1!","2\"@","3#","4$","5%","6&","7/{","8([","9)]","0=}","+?\\","\'`",
353 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","","\"^~",
354 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","","","'*",
355 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
356 "<>|"
357};
358
Dmitry Timoshkov09b4c502002-06-22 01:10:37 +0000359/*** Bulgarian bds keyboard layout */
360static const char main_key_BG_bds[MAIN_LEN][4] =
361{
362 "`~()","1!","2@2?","3#3+","4$4\"","5%","6^6=","7&7:","8*8/","9(","0)","-_-I","=+.V",
363 "qQ,û","wWóÓ","eEåÅ","rRèÈ","tTøØ","yYùÙ","uUêÊ","iIñÑ","oOäÄ","pPçÇ","[{öÖ","]};",
364 "aAüÜ","sSÿß","dDàÀ","fFîÎ","gGæÆ","hHãÃ","jJòÒ","kKíÍ","lLâÂ",";:ìÌ","'\"÷×","\\|'Û",
365 "zZþÞ","xXéÉ","cCúÚ","vVýÝ","bBôÔ","nNõÕ","mMïÏ",",<ðÐ",".>ëË","/?áÁ",
366 "<>" /* the phantom key */
367};
368
369/*** Bulgarian phonetic keyboard layout */
370static const char main_key_BG_phonetic[MAIN_LEN][4] =
371{
372 "`~÷×","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
373 "qQÿß","wWâÂ","eEåÅ","rRðÐ","tTòÒ","yYúÚ","uUóÓ","iIèÈ","oOîÎ","pPïÏ","[{øØ","]}ùÙ",
374 "aAàÀ","sSñÑ","dDäÄ","fFôÔ","gGãÃ","hHõÕ","jJéÉ","kKêÊ","lLëË",";:","'\"","\\|þÞ",
375 "zZçÇ","xXüÜ","cCöÖ","vVæÆ","bBáÁ","nNíÍ","mMìÌ",",<",".>","/?",
376 "<>" /* the phantom key */
377};
378
Hleb Valoska8df5fc92002-08-27 18:16:06 +0000379/*** Belarusian standard keyboard layout (contributed by Hleb Valoska) */
380/*** It matches belarusian layout for XKB from Alexander Mikhailian */
381static const char main_key_BY[MAIN_LEN][4] =
382{
383 "`~£³","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
384 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oO®¾","pPÚú","[{Èè","]}''",
385 "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|/|",
386 "zZÑñ","xXÞþ","cCÓó","vVÍí","bB¦¶","nNÔô","mMØø",",<Ââ",".>Àà","/?.,", "<>|¦",
387};
388
389
Pavel Roskindbfdca81999-03-28 13:44:56 +0000390/*** Russian keyboard layout (contributed by Pavel Roskin) */
391static const char main_key_RU[MAIN_LEN][4] =
392{
393 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
394 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}ßÿ",
395 "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|",
396 "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?"
397};
398
Andriy Palamarchuk2bdbf302001-09-19 22:26:15 +0000399/*** Russian keyboard layout (phantom key version) */
400static const char main_key_RU_phantom[MAIN_LEN][4] =
401{
402 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
403 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}ßÿ",
404 "aAÆæ","sSÙù","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"Üü","\\|",
405 "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?",
406 "<>" /* the phantom key */
407};
408
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +0000409/*** Russian keyboard layout KOI8-R */
410static const char main_key_RU_koi8r[MAIN_LEN][4] =
411{
412 "()","1!","2\"","3/","4$","5:","6,","7.","8;","9?","0%","-_","=+",
413 "Êê","Ãã","Õõ","Ëë","Åå","Îî","Çç","Ûû","Ýý","Úú","Èè","ßÿ",
414 "Ææ","Ùù","×÷","Áá","Ðð","Òò","Ïï","Ìì","Ää","Öö","Üü","\\|",
415 "Ññ","Þþ","Óó","Íí","Éé","Ôô","Øø","Ââ","Àà","/?",
416 "<>" /* the phantom key */
417};
418
Andy Rysin872784f2001-09-10 23:15:26 +0000419/*** Ukrainian keyboard layout KOI8-U */
420static const char main_key_UA[MAIN_LEN][4] =
421{
422 "`~­½","1!1!","2@2\"","3#3'","4$4*","5%5:","6^6,","7&7.","8*8;","9(9(","0)0)","-_-_","=+=+",
423 "qQÊê","wWÃã","eEÕõ","rRËë","tTÅå","yYÎî","uUÇç","iIÛû","oOÝý","pPÚú","[{Èè","]}§·",
424 "aAÆæ","sS¦¶","dD×÷","fFÁá","gGÐð","hHÒò","jJÏï","kKÌì","lLÄä",";:Öö","'\"¤´","\\|\\|",
425 "zZÑñ","xXÞþ","cCÓó","vVÍí","bBÉé","nNÔô","mMØø",",<Ââ",".>Àà","/?/?",
426 "<>" /* the phantom key */
427};
428
José Marcos López05eb8b51999-04-04 12:44:42 +0000429/*** Spanish keyboard layout (contributed by José Marcos López) */
430static const char main_key_ES[MAIN_LEN][4] =
431{
Jeff Smith6f310132002-10-29 21:28:12 +0000432 "ºª\\","1!|","2\"@","3·#","4$~","5%","6&¬","7/","8(","9)","0=","'?","¡¿",
José Marcos López05eb8b51999-04-04 12:44:42 +0000433 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","`^[","+*]",
Jeff Smith6f310132002-10-29 21:28:12 +0000434 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ñÑ","´¨{","çÇ}",
José Marcos López05eb8b51999-04-04 12:44:42 +0000435 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
436 "<>"
437};
438
Pablo Saratxaga002106a1999-04-16 09:06:58 +0000439/*** Belgian keyboard layout ***/
440static const char main_key_BE[MAIN_LEN][4] =
441{
442 "","&1|","é2@","\"3#","'4","(5","§6^","è7","!8","ç9{","à0}",")°","-_",
443 "aA","zZ","eE¤","rR","tT","yY","uU","iI","oO","pP","^¨[","$*]",
444 "qQ","sSß","dD","fF","gG","hH","jJ","kK","lL","mM","ù%´","µ£`",
445 "wW","xX","cC","vV","bB","nN",",?",";.",":/","=+~",
446 "<>\\"
447};
448
Zoltan Kovacs3d4cabf1999-10-13 13:54:39 +0000449/*** Hungarian keyboard layout (contributed by Zoltán Kovács) */
450static const char main_key_HU[MAIN_LEN][4] =
451{
452 "0§","1'~","2\"·","3+^","4!¢","5%°","6/²","7=`","8(ÿ","9)´","öÖ½","üܨ","óÓ¸",
453 "qQ\\","wW|","eE","rR","tT","zZ","uU","iIÍ","oOø","pP","õÕ÷","úÚ×",
454 "aA","sSð","dDÐ","fF[","gG]","hH","jJí","kK³","lL£","éÉ$","áÁß","ûÛ¤",
455 "yY>","xX#","cC&","vV@","bB{","nN}","mM",",?;",".:·","-_*",
456 "íÍ<"
457};
458
Jaroslaw Piotr Sobieszek384a10d1999-11-04 02:02:05 +0000459/*** Polish (programmer's) keyboard layout ***/
460static const char main_key_PL[MAIN_LEN][4] =
461{
462 "`~","1!","2@","3#","4$","5%","6^","7&§","8*","9(","0)","-_","=+",
463 "qQ","wW","eEêÊ","rR","tT","yY","uU","iI","oOóÓ","pP","[{","]}",
464 "aA±¡","sS¶¦","dD","fF","gG","hH","jJ","kK","lL³£",";:","'\"","\\|",
465 "zZ¿¯","xX¼¬","cCæÆ","vV","bB","nNñÑ","mM",",<",".>","/?",
466 "<>|"
467};
468
Rok Mandeljc52bb6432002-06-21 20:14:15 +0000469/*** Slovenian keyboard layout by Rok Mandeljc <rok.mandeljc@gimb.org> ***/
470static const char main_key_SI[MAIN_LEN][4] =
471{
472 "¸¨","1!","2\"·","3#^","4$¢","5%°","6&²","7/`","8(ÿ","9)´","0=½","'?¨","+*¸",
473 "qQ\\","wW|","eE","rR","tT","zZ","uU","iI","oO","pP","¹©÷","ðÐ×",
474 "aA","sS","dD","fF[","gG]","hH","jJ","kK³","lL£","èÈ","æÆß","¾®¤",
475 "yY","xX","cC","vV@","bB{","nN}","mM§",",;",".:","-_",
476 "<>"
477};
478
Zoran Dzelajlija846880b2000-05-30 20:50:45 +0000479/*** Croatian keyboard layout specific for me <jelly@srk.fer.hr> ***/
480static const char main_key_HR_jelly[MAIN_LEN][4] =
481{
482 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
483 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{¹©","]}ðÐ",
484 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:èÈ","'\"æÆ","\\|¾®",
485 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
486 "<>|"
487};
488
489/*** Croatian keyboard layout ***/
490static const char main_key_HR[MAIN_LEN][4] =
491{
492 "¸¨","1!","2\"·","3#^","4$¢","5%°","6&²","7/`","8(ÿ","9)´","0=½","'?¨","+*¸",
493 "qQ\\","wW|","eE","rR","tT","zZ","uU","iI","oO","pP","¹©÷","ðÐ×",
494 "aA","sS","dD","fF[","gG]","hH","jJ","kK³","lL£","èÈ","æÆß","¾®¤",
495 "yY","xX","cC","vV@","bB{","nN}","mM§",",;",".:","-_/",
496 "<>"
497};
498
Hidenori Takeshima8097a262000-02-20 13:43:29 +0000499/*** Japanese 106 keyboard layout ***/
500static const char main_key_JA_jp106[MAIN_LEN][4] =
501{
502 "1!","2\"","3#","4$","5%","6&","7'","8(","9)","0~","-=","^~","\\|",
503 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","@`","[{",
504 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";+",":*","]}",
505 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
506 "\\_",
507};
508
509/*** Japanese pc98x1 keyboard layout ***/
510static const char main_key_JA_pc98x1[MAIN_LEN][4] =
511{
512 "1!","2\"","3#","4$","5%","6&","7'","8(","9)","0","-=","^`","\\|",
513 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","@~","[{",
514 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";+",":*","]}",
515 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?",
516 "\\_",
517};
518
Raul Fernandes9ed48c62000-07-16 15:40:29 +0000519/*** Brazilian ABNT-2 keyboard layout (contributed by Raul Gomes Fernandes) */
520static const char main_key_PT_br[MAIN_LEN][4] =
521{
Dmitry Timoshkovb6e3f492002-08-16 23:28:38 +0000522 "'\"","1!","2@","3#","4$","5%","6¨","7&","8*","9(","0)","-_","=+",
523 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","´`","[{",
Raul Fernandes9ed48c62000-07-16 15:40:29 +0000524 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","çÇ","~^","]}",
Mauro Carvalho Chehab9a1c52e2002-12-19 21:14:47 +0000525 "zZ","xX","cC","vV","bB","nN","mM",",<",".>",";:","/?",
526 "\\|"
527};
528
529/*** Brazilian ABNT-2 keyboard layout with <ALT GR> (contributed by Mauro Carvalho Chehab) */
530static const char main_key_PT_br_alt_gr[MAIN_LEN][4] =
531{
532 "'\"","1!9","2@2","3#3","4$#","5%\"","6(,","7&","8*","9(","0)","-_","=+'",
533 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","4`","[{*",
534 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","gG","~^","]}:",
535 "zZ","xX","cC","vV","bB","nN","mM",",<",".>",";:","/?0",
536 "\\|"
Raul Fernandes9ed48c62000-07-16 15:40:29 +0000537};
Hidenori Takeshima8097a262000-02-20 13:43:29 +0000538
Gustavo Noronha Silva (KoV)12a79232001-04-02 19:12:58 +0000539/*** US international keyboard layout (contributed by Gustavo Noronha (kov@debian.org)) */
540static const char main_key_US_intl[MAIN_LEN][4] =
541{
542 "`~", "1!", "2@", "3#", "4$", "5%", "6^", "7&", "8*", "9(", "0)", "-_", "=+", "\\|",
543 "qQ", "wW", "eE", "rR", "tT", "yY", "uU", "iI", "oO", "pP", "[{", "]}",
544 "aA", "sS", "dD", "fF", "gG", "hH", "jJ", "kK", "lL", ";:", "'\"",
545 "zZ", "xX", "cC", "vV", "bB", "nN", "mM", ",<", ".>", "/?"
546};
547
Peter Ivanyi1da3bef2000-10-31 01:19:11 +0000548/*** Slovak keyboard layout (see cssk_ibm(sk_qwerty) in xkbsel)
549 - dead_abovering replaced with degree - no symbol in iso8859-2
550 - brokenbar replaced with bar */
551static const char main_key_SK[MAIN_LEN][4] =
552{
Dmitry Timoshkov09b4c502002-06-22 01:10:37 +0000553 ";0","+1","µ2","¹3","è4","»5","¾6","ý7","á8","í9","é0","=%","'v",
554 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","ú/","ä(",
555 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ô\"","§!","ò)",
556 "zZ","xX","cC","vV","bB","nN","mM",",?",".:","-_",
557 "<>"
Peter Ivanyi1da3bef2000-10-31 01:19:11 +0000558};
559
Peter Mladek5dc7f132002-12-05 19:55:04 +0000560/*** Czech keyboard layout (setxkbmap cz) */
561static const char main_key_CZ[MAIN_LEN][4] =
562{
563 ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0","=%","´·",
564 "qQ","wW","eE","rR","tT","zZ","uU","iI","oO","pP","ú/",")(",
565 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ù\"","§!","¨'",
566 "yY","xX","cC","vV","bB","nN","mM",",?",".:","-_",
567 "\\"
568};
569
570/*** Czech keyboard layout (setxkbmap cz_qwerty) */
571static const char main_key_CZ_qwerty[MAIN_LEN][4] =
572{
573 ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0","=%","´·",
574 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","ú/",")(",
575 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ù\"","§!","¨'",
576 "zZ","xX","cC","vV","bB","nN","mM",",?",".:","-_",
577 "\\"
578};
579
Peter Ivanyi1da3bef2000-10-31 01:19:11 +0000580/*** Slovak and Czech (programmer's) keyboard layout (see cssk_dual(cs_sk_ucw)) */
581static const char main_key_SK_prog[MAIN_LEN][4] =
582{
583 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
584 "qQäÄ","wWìÌ","eEéÉ","rRøØ","tT»«","yYýÝ","uUùÙ","iIíÍ","oOóÓ","pPöÖ","[{","]}",
585 "aAáÁ","sS¹©","dDïÏ","fFëË","gGàÀ","hHúÚ","jJüÜ","kKôÔ","lLµ¥",";:","'\"","\\|",
586 "zZ¾®","xX¤","cCèÈ","vVçÇ","bB","nNòÒ","mMåÅ",",<",".>","/?",
587 "<>"
588};
589
590/*** Czech keyboard layout (see cssk_ibm(cs_qwerty) in xkbsel) */
591static const char main_key_CS[MAIN_LEN][4] =
592{
593 ";","+1","ì2","¹3","è4","ø5","¾6","ý7","á8","í9","é0½)","=%","",
594 "qQ\\","wW|","eE","rR","tT","yY","uU","iI","oO","pP","ú/[{",")(]}",
595 "aA","sSð","dDÐ","fF[","gG]","hH","jJ","kK³","lL£","ù\"$","§!ß","¨'",
596 "zZ>","xX#","cC&","vV@","bB{","nN}","mM",",?<",".:>","-_*",
597 "<>\\|"
598};
599
Gabriel Garciaa9774be2000-11-01 01:47:39 +0000600/*** Latin American keyboard layout (contributed by Gabriel Orlando Garcia) */
601static const char main_key_LA[MAIN_LEN][4] =
602{
Leonardo Quijano Vincenzi02078552003-01-24 00:47:08 +0000603 "|°¬","1!","2\"","3#","4$","5%","6&","7/","8(","9)","0=","'?\\","¿¡",
Gabriel Garciaa9774be2000-11-01 01:47:39 +0000604 "qQ@","wW","eE","rR","tT","yY","uU","iI","oO","pP","´¨","+*~",
605 "aA","sS","dD","fF","gG","hH","jJ","kK","lL","ñÑ","{[^","}]`",
606 "zZ","xX","cC","vV","bB","nN","mM",",;",".:","-_",
607 "<>"
608};
Hidenori Takeshima8097a262000-02-20 13:43:29 +0000609
Nerijus Baliunasc4b8b262000-11-11 00:34:32 +0000610/*** Lithuanian (Baltic) keyboard layout (contributed by Nerijus Baliûnas) */
611static const char main_key_LT_B[MAIN_LEN][4] =
612{
Nerijus Baliunas9f47e972002-10-10 23:30:13 +0000613 "`~","1àÀ","2èÈ","3æÆ","4ëË","5áÁ","6ðÐ","7øØ","8ûÛ","9¥(","0´)","-_","=þÞ","\\|",
Nerijus Baliunasc4b8b262000-11-11 00:34:32 +0000614 "qQ","wW","eE","rR","tT","yY","uU","iI","oO","pP","[{","]}",
Nerijus Baliunas9f47e972002-10-10 23:30:13 +0000615 "aA","sS","dD","fF","gG","hH","jJ","kK","lL",";:","'\"",
Nerijus Baliunasc4b8b262000-11-11 00:34:32 +0000616 "zZ","xX","cC","vV","bB","nN","mM",",<",".>","/?"
617};
618
Aric Stewarted6a7b42001-02-15 21:23:23 +0000619/*** Turkish keyboard Layout */
620static const char main_key_TK[MAIN_LEN][4] =
621{
622"\"é","1!","2'","3^#","4+$","5%","6&","7/{","8([","9)]","0=}","*?\\","-_",
623"qQ@","wW","eE","rR","tT","yY","uU","ýIî","oO","pP","ðÐ","üÜ~",
624"aAæ","sSß","dD","fF","gG","hH","jJ","kK","lL","þÞ","iÝ",",;`",
625"zZ","xX","cC","vV","bB","nN","mM","öÖ","çÇ",".:"
626};
627
Shachar Shemesh4b050942002-05-31 18:21:33 +0000628/*** Israeli keyboard layout */
629static const char main_key_IL[MAIN_LEN][4] =
630{
631 "`~;","1!1","2@2","3#3","4$4","5%5","6^6","7&7","8*8","9(9","0)0","-_-","=+=",
632 "qQ/","wW'","eE÷","rRø","tTà","yYè","uUå","iIï","oOí","pPô","[{[","]}]",
633 "aAù","sSã","dDâ","fFë","gGò","hHé","jJç","kKì","lLê",";:ó","\'\",","\\|\\",
634 "zZæ","xXñ","cCá","vVä","bBð","nNî","mMö",",<ú",".>õ","/?."
635};
636
Dmitry Timoshkovb6e3f492002-08-16 23:28:38 +0000637/*** Greek keyboard layout (contributed by Kriton Kyrimis <kyrimis@cti.gr>)
638 Greek characters for "wW" and "sS" are omitted to not produce a mismatch
639 message since they have different characters in gr and el XFree86 layouts. */
640static const char main_key_EL[MAIN_LEN][4] =
641{
642 "`~","1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+",
643 "qQ;:","wW","eEåÅ","rRñÑ","tTôÔ","yYõÕ","uUèÈ","iIéÉ","oOïÏ","pPðÐ","[{","]}",
644 "aAáÁ","sS","dDäÄ","fFöÖ","gGãÃ","hHçÇ","jJîÎ","kKêÊ","lLëË",";:´¨","'\"","\\|",
645 "zZæÆ","xX÷×","cCøØ","vVùÙ","bBâÂ","nNíÍ","mMìÌ",",<",".>","/?",
646 "<>"
647};
648
Dave Hawkes95d8c952002-02-15 18:21:16 +0000649/*** VNC keyboard layout */
650static const WORD main_key_scan_vnc[MAIN_LEN] =
651{
652 0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0A,0x0B,0x0C,0x0D,0x1A,0x1B,0x27,0x28,0x29,0x33,0x34,0x35,0x2B,
653 0x1E,0x30,0x2E,0x20,0x12,0x21,0x22,0x23,0x17,0x24,0x25,0x26,0x32,0x31,0x18,0x19,0x10,0x13,0x1F,0x14,0x16,0x2F,0x11,0x2D,0x15,0x2C,
654 0x56
655};
656
657static const WORD main_key_vkey_vnc[MAIN_LEN] =
658{
659 VK_1,VK_2,VK_3,VK_4,VK_5,VK_6,VK_7,VK_8,VK_9,VK_0,VK_OEM_MINUS,VK_OEM_PLUS,VK_OEM_4,VK_OEM_6,VK_OEM_1,VK_OEM_7,VK_OEM_3,VK_OEM_COMMA,VK_OEM_PERIOD,VK_OEM_2,VK_OEM_5,
660 VK_A,VK_B,VK_C,VK_D,VK_E,VK_F,VK_G,VK_H,VK_I,VK_J,VK_K,VK_L,VK_M,VK_N,VK_O,VK_P,VK_Q,VK_R,VK_S,VK_T,VK_U,VK_V,VK_W,VK_X,VK_Y,VK_Z,
661 VK_OEM_102
662};
663
664static const char main_key_vnc[MAIN_LEN][4] =
665{
666 "1!","2@","3#","4$","5%","6^","7&","8*","9(","0)","-_","=+","[{","]}",";:","'\"","`~",",<",".>","/?","\\|",
667 "aA","bB","cC","dD","eE","fF","gG","hH","iI","jJ","kK","lL","mM","nN","oO","pP","qQ","rR","sS","tT","uU","vV","wW","xX","yY","zZ"
668};
669
Ove Kaaven7173e1c1999-03-14 14:00:57 +0000670/*** Layout table. Add your keyboard mappings to this list */
Raul Fernandes9ed48c62000-07-16 15:40:29 +0000671static const struct {
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +0000672 const char *comment;
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +0000673 const char (*key)[MAIN_LEN][4];
674 const WORD (*scan)[MAIN_LEN]; /* scan codes mapping */
675 const WORD (*vkey)[MAIN_LEN]; /* virtual key codes mapping */
Ove Kaaven7173e1c1999-03-14 14:00:57 +0000676} main_key_tab[]={
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +0000677 {"United States keyboard layout", &main_key_US, &main_key_scan_qwerty, &main_key_vkey_qwerty},
678 {"United States keyboard layout (phantom key version)", &main_key_US_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
679 {"United States keyboard layout (dvorak)", &main_key_US_dvorak, &main_key_scan_dvorak, &main_key_vkey_dvorak},
680 {"British keyboard layout", &main_key_UK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
681 {"German keyboard layout", &main_key_DE, &main_key_scan_qwerty, &main_key_vkey_qwerty},
682 {"German keyboard layout without dead keys", &main_key_DE_nodead, &main_key_scan_qwerty, &main_key_vkey_qwerty},
683 {"German keyboard layout for logitech desktop pro", &main_key_DE_logitech, &main_key_scan_qwerty, &main_key_vkey_qwerty},
684 {"German keyboard layout without dead keys 105", &main_key_DE_nodead_105, &main_key_scan_qwerty, &main_key_vkey_qwerty},
685 {"Swiss German keyboard layout", &main_key_SG, &main_key_scan_qwerty, &main_key_vkey_qwerty},
686 {"Swedish keyboard layout", &main_key_SE, &main_key_scan_qwerty, &main_key_vkey_qwerty},
687 {"Estonian keyboard layout", &main_key_ET, &main_key_scan_qwerty, &main_key_vkey_qwerty},
688 {"Norwegian keyboard layout", &main_key_NO, &main_key_scan_qwerty, &main_key_vkey_qwerty},
689 {"Danish keyboard layout", &main_key_DA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
690 {"French keyboard layout", &main_key_FR, &main_key_scan_qwerty, &main_key_vkey_azerty},
691 {"Canadian French keyboard layout", &main_key_CF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
692 {"Belgian keyboard layout", &main_key_BE, &main_key_scan_qwerty, &main_key_vkey_azerty},
693 {"Swiss French keyboard layout", &main_key_SF, &main_key_scan_qwerty, &main_key_vkey_qwerty},
694 {"Portuguese keyboard layout", &main_key_PT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
695 {"Brazilian ABNT-2 keyboard layout", &main_key_PT_br, &main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
696 {"Brazilian ABNT-2 keyboard layout ALT GR", &main_key_PT_br_alt_gr,&main_key_scan_abnt_qwerty, &main_key_vkey_abnt_qwerty},
697 {"United States International keyboard layout", &main_key_US_intl, &main_key_scan_qwerty, &main_key_vkey_qwerty},
698 {"Finnish keyboard layout", &main_key_FI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
699 {"Bulgarian bds keyboard layout", &main_key_BG_bds, &main_key_scan_qwerty, &main_key_vkey_qwerty},
700 {"Bulgarian phonetic keyboard layout", &main_key_BG_phonetic, &main_key_scan_qwerty, &main_key_vkey_qwerty},
701 {"Belarusian keyboard layout", &main_key_BY, &main_key_scan_qwerty, &main_key_vkey_qwerty},
702 {"Russian keyboard layout", &main_key_RU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
703 {"Russian keyboard layout (phantom key version)", &main_key_RU_phantom, &main_key_scan_qwerty, &main_key_vkey_qwerty},
704 {"Russian keyboard layout KOI8-R", &main_key_RU_koi8r, &main_key_scan_qwerty, &main_key_vkey_qwerty},
705 {"Ukrainian keyboard layout KOI8-U", &main_key_UA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
706 {"Spanish keyboard layout", &main_key_ES, &main_key_scan_qwerty, &main_key_vkey_qwerty},
707 {"Italian keyboard layout", &main_key_IT, &main_key_scan_qwerty, &main_key_vkey_qwerty},
708 {"Icelandic keyboard layout", &main_key_IS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
709 {"Hungarian keyboard layout", &main_key_HU, &main_key_scan_qwerty, &main_key_vkey_qwerty},
710 {"Polish (programmer's) keyboard layout", &main_key_PL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
711 {"Slovenian keyboard layout", &main_key_SI, &main_key_scan_qwerty, &main_key_vkey_qwerty},
712 {"Croatian keyboard layout", &main_key_HR, &main_key_scan_qwerty, &main_key_vkey_qwerty},
713 {"Croatian keyboard layout (specific)", &main_key_HR_jelly, &main_key_scan_qwerty, &main_key_vkey_qwerty},
714 {"Japanese 106 keyboard layout", &main_key_JA_jp106, &main_key_scan_qwerty, &main_key_vkey_qwerty},
715 {"Japanese pc98x1 keyboard layout", &main_key_JA_pc98x1, &main_key_scan_qwerty, &main_key_vkey_qwerty},
716 {"Slovak keyboard layout", &main_key_SK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
717 {"Slovak and Czech keyboard layout without dead keys", &main_key_SK_prog, &main_key_scan_qwerty, &main_key_vkey_qwerty},
718 {"Czech keyboard layout", &main_key_CS, &main_key_scan_qwerty, &main_key_vkey_qwerty},
719 {"Czech keyboard layout cz", &main_key_CZ, &main_key_scan_qwerty, &main_key_vkey_qwerty},
720 {"Czech keyboard layout cz_qwerty", &main_key_CZ_qwerty, &main_key_scan_qwerty, &main_key_vkey_qwerty},
721 {"Latin American keyboard layout", &main_key_LA, &main_key_scan_qwerty, &main_key_vkey_qwerty},
722 {"Lithuanian (Baltic) keyboard layout", &main_key_LT_B, &main_key_scan_qwerty, &main_key_vkey_qwerty},
723 {"Turkish keyboard layout", &main_key_TK, &main_key_scan_qwerty, &main_key_vkey_qwerty},
724 {"Israeli keyboard layout", &main_key_IL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
725 {"VNC keyboard layout", &main_key_vnc, &main_key_scan_vnc, &main_key_vkey_vnc},
726 {"Greek keyboard layout", &main_key_EL, &main_key_scan_qwerty, &main_key_vkey_qwerty},
Ove Kaaven7173e1c1999-03-14 14:00:57 +0000727
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +0000728 {NULL, NULL, NULL, NULL} /* sentinel */
Ove Kaaven7173e1c1999-03-14 14:00:57 +0000729};
730static unsigned kbd_layout=0; /* index into above table of layouts */
731
732/* maybe more of these scancodes should be extended? */
733 /* extended must be set for ALT_R, CTRL_R,
734 INS, DEL, HOME, END, PAGE_UP, PAGE_DOWN, ARROW keys,
735 keypad / and keypad ENTER (SDK 3.1 Vol.3 p 138) */
736 /* FIXME should we set extended bit for NumLock ? My
737 * Windows does ... DF */
Guy Albertelli5bd55171999-09-03 12:39:29 +0000738 /* Yes, to distinguish based on scan codes, also
739 for PrtScn key ... GA */
740
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000741static const WORD nonchar_key_vkey[256] =
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000742{
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000743 /* unused */
744 0, 0, 0, 0, 0, 0, 0, 0, /* FF00 */
745 /* special keys */
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000746 VK_BACK, VK_TAB, 0, VK_CLEAR, 0, VK_RETURN, 0, 0, /* FF08 */
747 0, 0, 0, VK_PAUSE, VK_SCROLL, 0, 0, 0, /* FF10 */
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000748 0, 0, 0, VK_ESCAPE, 0, 0, 0, 0, /* FF18 */
749 /* unused */
750 0, 0, 0, 0, 0, 0, 0, 0, /* FF20 */
751 0, 0, 0, 0, 0, 0, 0, 0, /* FF28 */
752 0, 0, 0, 0, 0, 0, 0, 0, /* FF30 */
753 0, 0, 0, 0, 0, 0, 0, 0, /* FF38 */
754 0, 0, 0, 0, 0, 0, 0, 0, /* FF40 */
755 0, 0, 0, 0, 0, 0, 0, 0, /* FF48 */
756 /* cursor keys */
757 VK_HOME, VK_LEFT, VK_UP, VK_RIGHT, /* FF50 */
758 VK_DOWN, VK_PRIOR, VK_NEXT, VK_END,
759 0, 0, 0, 0, 0, 0, 0, 0, /* FF58 */
760 /* misc keys */
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000761 VK_SELECT, VK_SNAPSHOT, VK_EXECUTE, VK_INSERT, 0, 0, 0, 0, /* FF60 */
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000762 VK_CANCEL, VK_HELP, VK_CANCEL, VK_CANCEL, 0, 0, 0, 0, /* FF68 */
763 0, 0, 0, 0, 0, 0, 0, 0, /* FF70 */
764 /* keypad keys */
765 0, 0, 0, 0, 0, 0, 0, VK_NUMLOCK, /* FF78 */
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000766 0, 0, 0, 0, 0, 0, 0, 0, /* FF80 */
767 0, 0, 0, 0, 0, VK_RETURN, 0, 0, /* FF88 */
768 0, 0, 0, 0, 0, VK_HOME, VK_LEFT, VK_UP, /* FF90 */
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000769 VK_RIGHT, VK_DOWN, VK_PRIOR, VK_NEXT, /* FF98 */
770 VK_END, 0, VK_INSERT, VK_DELETE,
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000771 0, 0, 0, 0, 0, 0, 0, 0, /* FFA0 */
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000772 0, 0, VK_MULTIPLY, VK_ADD, /* FFA8 */
773 VK_SEPARATOR, VK_SUBTRACT, VK_DECIMAL, VK_DIVIDE,
774 VK_NUMPAD0, VK_NUMPAD1, VK_NUMPAD2, VK_NUMPAD3, /* FFB0 */
775 VK_NUMPAD4, VK_NUMPAD5, VK_NUMPAD6, VK_NUMPAD7,
776 VK_NUMPAD8, VK_NUMPAD9, 0, 0, 0, 0, /* FFB8 */
777 /* function keys */
778 VK_F1, VK_F2,
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000779 VK_F3, VK_F4, VK_F5, VK_F6, VK_F7, VK_F8, VK_F9, VK_F10, /* FFC0 */
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000780 VK_F11, VK_F12, VK_F13, VK_F14, VK_F15, VK_F16, 0, 0, /* FFC8 */
781 0, 0, 0, 0, 0, 0, 0, 0, /* FFD0 */
782 0, 0, 0, 0, 0, 0, 0, 0, /* FFD8 */
783 /* modifier keys */
784 0, VK_SHIFT, VK_SHIFT, VK_CONTROL, /* FFE0 */
785 VK_CONTROL, VK_CAPITAL, 0, VK_MENU,
786 VK_MENU, VK_MENU, VK_MENU, 0, 0, 0, 0, 0, /* FFE8 */
787 0, 0, 0, 0, 0, 0, 0, 0, /* FFF0 */
788 0, 0, 0, 0, 0, 0, 0, VK_DELETE /* FFF8 */
Ove Kaaven7173e1c1999-03-14 14:00:57 +0000789};
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000790
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000791static const WORD nonchar_key_scan[256] =
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000792{
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000793 /* unused */
794 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF00 */
795 /* special keys */
796 0x0E, 0x0F, 0x00, /*?*/ 0, 0x00, 0x1C, 0x00, 0x00, /* FF08 */
797 0x00, 0x00, 0x00, 0x45, 0x46, 0x00, 0x00, 0x00, /* FF10 */
798 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, /* FF18 */
799 /* unused */
800 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF20 */
801 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF28 */
802 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF30 */
803 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF38 */
804 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF40 */
805 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF48 */
806 /* cursor keys */
807 0x147, 0x14B, 0x148, 0x14D, 0x150, 0x149, 0x151, 0x14F, /* FF50 */
808 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF58 */
809 /* misc keys */
810 /*?*/ 0, 0x137, /*?*/ 0, 0x152, 0x00, 0x00, 0x00, 0x00, /* FF60 */
811 /*?*/ 0, /*?*/ 0, 0x38, 0x146, 0x00, 0x00, 0x00, 0x00, /* FF68 */
812 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF70 */
813 /* keypad keys */
814 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x138, 0x145, /* FF78 */
815 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FF80 */
816 0x00, 0x00, 0x00, 0x00, 0x00, 0x11C, 0x00, 0x00, /* FF88 */
817 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x4B, 0x48, /* FF90 */
818 0x4D, 0x50, 0x49, 0x51, 0x4F, 0x4C, 0x52, 0x53, /* FF98 */
819 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFA0 */
820 0x00, 0x00, 0x37, 0x4E, /*?*/ 0, 0x4A, 0x53, 0x135, /* FFA8 */
821 0x52, 0x4F, 0x50, 0x51, 0x4B, 0x4C, 0x4D, 0x47, /* FFB0 */
822 0x48, 0x49, 0x00, 0x00, 0x00, 0x00, /* FFB8 */
823 /* function keys */
824 0x3B, 0x3C,
825 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, /* FFC0 */
826 0x57, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFC8 */
827 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFD0 */
828 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFD8 */
829 /* modifier keys */
830 0x00, 0x2A, 0x36, 0x1D, 0x11D, 0x3A, 0x00, 0x38, /* FFE0 */
831 0x138, 0x38, 0x138, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFE8 */
832 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* FFF0 */
833 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x153 /* FFF8 */
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000834};
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000835
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000836
837/* Returns the Windows virtual key code associated with the X event <e> */
Alexandre Julliarde9119c12002-09-24 18:36:51 +0000838/* x11 lock must be held */
Alexandre Julliarde5fb9752003-01-23 01:29:58 +0000839static WORD EVENT_event_to_vkey( XIC xic, XKeyEvent *e)
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000840{
841 KeySym keysym;
842
Alexandre Julliarde5fb9752003-01-23 01:29:58 +0000843 if (xic)
844 XmbLookupString(xic, e, NULL, 0, &keysym, NULL);
845 else
846 XLookupString(e, NULL, 0, &keysym, NULL);
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000847
Vincent Béron9a624912002-05-31 23:06:46 +0000848 if ((keysym >= 0xFFAE) && (keysym <= 0xFFB9) && (keysym != 0xFFAF)
849 && (e->state & NumLockMask))
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000850 /* Only the Keypad keys 0-9 and . send different keysyms
851 * depending on the NumLock state */
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000852 return nonchar_key_vkey[keysym & 0xFF];
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000853
854 return keyc2vkey[e->keycode];
855}
856
Dmitry Timoshkovef546432001-10-02 17:17:31 +0000857static BOOL NumState=FALSE, CapsState=FALSE;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000858
Alexandre Julliard4b626182001-10-17 17:50:02 +0000859
860/***********************************************************************
861 * send_keyboard_input
862 */
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000863static void send_keyboard_input( WORD wVk, WORD wScan, DWORD dwFlags, DWORD time )
Alexandre Julliard4b626182001-10-17 17:50:02 +0000864{
865 INPUT input;
866
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000867 input.type = WINE_INTERNAL_INPUT_KEYBOARD;
Alexandre Julliard4b626182001-10-17 17:50:02 +0000868 input.u.ki.wVk = wVk;
869 input.u.ki.wScan = wScan;
870 input.u.ki.dwFlags = dwFlags;
871 input.u.ki.time = time;
872 input.u.ki.dwExtraInfo = 0;
873 SendInput( 1, &input, sizeof(input) );
874}
875
876
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000877/**********************************************************************
878 * KEYBOARD_GenerateMsg
879 *
880 * Generate Down+Up messages when NumLock or CapsLock is pressed.
881 *
882 * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
883 *
884 */
Alexandre Julliard4b626182001-10-17 17:50:02 +0000885static void KEYBOARD_GenerateMsg( WORD vkey, WORD scan, int Evtype, DWORD event_time )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000886{
Alexandre Julliarda3960291999-02-26 11:11:13 +0000887 BOOL * State = (vkey==VK_NUMLOCK? &NumState : &CapsState);
Guy Albertelli76d8abe1999-04-15 15:14:44 +0000888 DWORD up, down;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000889
890 if (*State) {
891 /* The INTERMEDIARY state means : just after a 'press' event, if a 'release' event comes,
892 don't treat it. It's from the same key press. Then the state goes to ON.
893 And from there, a 'release' event will switch off the toggle key. */
894 *State=FALSE;
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000895 TRACE("INTERM : don\'t treat release of toggle key. InputKeyStateTable[%#x] = %#x\n",vkey,pKeyStateTable[vkey]);
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000896 } else
897 {
Guy Albertelli76d8abe1999-04-15 15:14:44 +0000898 down = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0);
899 up = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0) | KEYEVENTF_KEYUP;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000900 if ( pKeyStateTable[vkey] & 0x1 ) /* it was ON */
901 {
902 if (Evtype!=KeyPress)
903 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000904 TRACE("ON + KeyRelease => generating DOWN and UP messages.\n");
Alexandre Julliard4b626182001-10-17 17:50:02 +0000905 send_keyboard_input( vkey, scan, down, event_time );
906 send_keyboard_input( vkey, scan, up, event_time );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000907 *State=FALSE;
Vincent Béron9a624912002-05-31 23:06:46 +0000908 pKeyStateTable[vkey] &= ~0x01; /* Toggle state to off. */
909 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000910 }
911 else /* it was OFF */
912 if (Evtype==KeyPress)
913 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +0000914 TRACE("OFF + Keypress => generating DOWN and UP messages.\n");
Alexandre Julliard4b626182001-10-17 17:50:02 +0000915 send_keyboard_input( vkey, scan, down, event_time );
916 send_keyboard_input( vkey, scan, up, event_time );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000917 *State=TRUE; /* Goes to intermediary state before going to ON */
918 pKeyStateTable[vkey] |= 0x01; /* Toggle state to on. */
919 }
920 }
921}
922
923/***********************************************************************
924 * KEYBOARD_UpdateOneState
925 *
926 * Updates internal state for <vkey>, depending on key <state> under X
927 *
928 */
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000929inline static void KEYBOARD_UpdateOneState ( int vkey, int state, DWORD time )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000930{
931 /* Do something if internal table state != X state for keycode */
932 if (((pKeyStateTable[vkey] & 0x80)!=0) != state)
933 {
Andreas Mohr6e256c722002-10-25 19:09:02 +0000934 TRACE("Adjusting state for vkey %#.2x. State before %#.2x\n",
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000935 vkey, pKeyStateTable[vkey]);
936
937 /* Fake key being pressed inside wine */
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000938 send_keyboard_input( vkey, 0, state? 0 : KEYEVENTF_KEYUP, time );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000939
Andreas Mohr6e256c722002-10-25 19:09:02 +0000940 TRACE("State after %#.2x\n",pKeyStateTable[vkey]);
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000941 }
942}
943
944/***********************************************************************
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000945 * X11DRV_KeymapNotify
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000946 *
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000947 * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000948 *
949 * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
950 * from wine to another application and back.
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000951 * Toggle keys are handled in HandleEvent.
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000952 */
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000953void X11DRV_KeymapNotify( HWND hwnd, XKeymapEvent *event )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000954{
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000955 int i, j, alt, control, shift;
956 DWORD time = GetCurrentTime();
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000957
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000958 alt = control = shift = 0;
959 for (i = 0; i < 32; i++)
960 {
961 if (!event->key_vector[i]) continue;
962 for (j = 0; j < 8; j++)
963 {
964 if (!(event->key_vector[i] & (1<<j))) continue;
965 switch(keyc2vkey[(i * 8) + j] & 0xff)
966 {
967 case VK_MENU: alt = 1; break;
968 case VK_CONTROL: control = 1; break;
969 case VK_SHIFT: shift = 1; break;
970 }
971 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000972 }
Alexandre Julliard32fb5802001-10-18 21:38:59 +0000973 KEYBOARD_UpdateOneState( VK_MENU, alt, time );
974 KEYBOARD_UpdateOneState( VK_CONTROL, control, time );
975 KEYBOARD_UpdateOneState( VK_SHIFT, shift, time );
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000976}
977
978/***********************************************************************
Alexandre Julliard4b626182001-10-17 17:50:02 +0000979 * X11DRV_KeyEvent
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000980 *
981 * Handle a X key event
982 */
Alexandre Julliard4b626182001-10-17 17:50:02 +0000983void X11DRV_KeyEvent( HWND hwnd, XKeyEvent *event )
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000984{
Vincent Béron9a624912002-05-31 23:06:46 +0000985 char Str[24];
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000986 KeySym keysym;
987 WORD vkey = 0, bScan;
988 DWORD dwFlags;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000989 int ascii_chars;
Alexandre Julliarde5fb9752003-01-23 01:29:58 +0000990 XIC xic = X11DRV_get_ic( hwnd );
Andreas Mohrc941eff2000-09-22 22:37:56 +0000991 DWORD event_time = event->time - X11DRV_server_startticks;
Patrik Stridvalle35d6361998-12-07 09:13:40 +0000992
993 /* this allows support for dead keys */
994 if ((event->keycode >> 8) == 0x10)
995 event->keycode=(event->keycode & 0xff);
996
Alexandre Julliarde9119c12002-09-24 18:36:51 +0000997 wine_tsx11_lock();
Alexandre Julliarde5fb9752003-01-23 01:29:58 +0000998 if (xic)
999 ascii_chars = XmbLookupString(xic, event, Str, sizeof(Str), &keysym, NULL);
1000 else
1001 ascii_chars = XLookupString(event, Str, sizeof(Str), &keysym, NULL);
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001002 wine_tsx11_unlock();
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001003
Andreas Mohrc941eff2000-09-22 22:37:56 +00001004 TRACE_(key)("state = %X\n", event->state);
Stephane Lussier0debf422000-04-13 16:00:08 +00001005
Andreas Mohr6e256c722002-10-25 19:09:02 +00001006 /* If XKB extensions are used, the state mask for AltGr will use the group
Stephane Lussier3e731da2000-04-14 14:09:20 +00001007 index instead of the modifier mask. The group index is set in bits
1008 13-14 of the state field in the XKeyEvent structure. So if AltGr is
Andreas Mohr6e256c722002-10-25 19:09:02 +00001009 pressed, look if the group index is different than 0. From XKB
1010 extension documentation, the group index for AltGr should be 2
1011 (event->state = 0x2000). It's probably better to not assume a
Stephane Lussier3e731da2000-04-14 14:09:20 +00001012 predefined group index and find it dynamically
Stephane Lussier0debf422000-04-13 16:00:08 +00001013
1014 Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
Dmitry Timoshkov965cbd22003-06-23 19:57:59 +00001015 /* Save also all possible modifier states. */
1016 AltGrMask = event->state & (0x6000 | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001017
1018 Str[ascii_chars] = '\0';
1019 if (TRACE_ON(key)){
1020 char *ksname;
1021
1022 ksname = TSXKeysymToString(keysym);
1023 if (!ksname)
1024 ksname = "No Name";
Vincent Béron9a624912002-05-31 23:06:46 +00001025 TRACE_(key)("%s : keysym=%lX (%s), ascii chars=%u / %X / '%s'\n",
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001026 (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
1027 keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001028 }
1029
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001030 wine_tsx11_lock();
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001031 vkey = EVENT_event_to_vkey(xic,event);
1032 /* X returns keycode 0 for composed characters */
1033 if (!vkey && ascii_chars) vkey = VK_NONAME;
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001034 wine_tsx11_unlock();
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001035
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001036 TRACE_(key)("keycode 0x%x converted to vkey 0x%x\n",
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001037 event->keycode, vkey);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001038
1039 if (vkey)
1040 {
1041 switch (vkey & 0xff)
1042 {
Vincent Béron9a624912002-05-31 23:06:46 +00001043 case VK_NUMLOCK:
Alexandre Julliard4b626182001-10-17 17:50:02 +00001044 KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, event->type, event_time );
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001045 break;
1046 case VK_CAPITAL:
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001047 TRACE("Caps Lock event. (type %d). State before : %#.2x\n",event->type,pKeyStateTable[vkey]);
Alexandre Julliard4b626182001-10-17 17:50:02 +00001048 KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, event->type, event_time );
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001049 TRACE("State after : %#.2x\n",pKeyStateTable[vkey]);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001050 break;
1051 default:
1052 /* Adjust the NUMLOCK state if it has been changed outside wine */
1053 if (!(pKeyStateTable[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
Vincent Béron9a624912002-05-31 23:06:46 +00001054 {
Andreas Mohr6e256c722002-10-25 19:09:02 +00001055 TRACE("Adjusting NumLock state.\n");
Alexandre Julliard4b626182001-10-17 17:50:02 +00001056 KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyPress, event_time );
1057 KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyRelease, event_time );
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001058 }
1059 /* Adjust the CAPSLOCK state if it has been changed outside wine */
1060 if (!(pKeyStateTable[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
1061 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001062 TRACE("Adjusting Caps Lock state.\n");
Alexandre Julliard4b626182001-10-17 17:50:02 +00001063 KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyPress, event_time );
1064 KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyRelease, event_time );
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001065 }
1066 /* Not Num nor Caps : end of intermediary states for both. */
1067 NumState = FALSE;
1068 CapsState = FALSE;
1069
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001070 bScan = keyc2scan[event->keycode] & 0xFF;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001071 TRACE_(key)("bScan = 0x%02x.\n", bScan);
Brian Gerst97847011998-12-07 15:44:54 +00001072
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001073 dwFlags = 0;
1074 if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
1075 if ( vkey & 0x100 ) dwFlags |= KEYEVENTF_EXTENDEDKEY;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001076
Alexandre Julliard4b626182001-10-17 17:50:02 +00001077 send_keyboard_input( vkey & 0xff, bScan, dwFlags, event_time );
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001078 }
1079 }
1080}
1081
1082/**********************************************************************
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001083 * X11DRV_KEYBOARD_DetectLayout
1084 *
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001085 * Called from X11DRV_InitKeyboard
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001086 * This routine walks through the defined keyboard layouts and selects
1087 * whichever matches most closely.
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001088 * X11 lock must be held.
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001089 */
Patrik Stridvall1ed4ecf1999-06-26 14:58:24 +00001090static void
Pavel Roskinf15d1801999-03-28 13:39:55 +00001091X11DRV_KEYBOARD_DetectLayout (void)
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001092{
Alexandre Julliard43230042001-05-16 19:52:29 +00001093 Display *display = thread_display();
Ove Kaaven787cf101999-04-03 11:18:58 +00001094 unsigned current, match, mismatch, seq;
1095 int score, keyc, i, key, pkey, ok, syms;
Pavel Roskinf15d1801999-03-28 13:39:55 +00001096 KeySym keysym;
1097 const char (*lkey)[MAIN_LEN][4];
Ove Kaaven787cf101999-04-03 11:18:58 +00001098 unsigned max_seq = 0;
Pavel Roskinf15d1801999-03-28 13:39:55 +00001099 int max_score = 0, ismatch = 0;
1100 char ckey[4] =
1101 {0, 0, 0, 0};
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001102
Pavel Roskinf15d1801999-03-28 13:39:55 +00001103 syms = keysyms_per_keycode;
1104 if (syms > 4) {
Francois Gougete76218d2001-05-09 17:31:31 +00001105 WARN("%d keysyms per keycode not supported, set to 4\n", syms);
Pavel Roskinf15d1801999-03-28 13:39:55 +00001106 syms = 4;
1107 }
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +00001108 for (current = 0; main_key_tab[current].comment; current++) {
1109 TRACE("Attempting to match against \"%s\"\n", main_key_tab[current].comment);
Pavel Roskinf15d1801999-03-28 13:39:55 +00001110 match = 0;
1111 mismatch = 0;
1112 score = 0;
Ove Kaaven787cf101999-04-03 11:18:58 +00001113 seq = 0;
Pavel Roskinf15d1801999-03-28 13:39:55 +00001114 lkey = main_key_tab[current].key;
Ove Kaaven787cf101999-04-03 11:18:58 +00001115 pkey = -1;
Pavel Roskinf15d1801999-03-28 13:39:55 +00001116 for (keyc = min_keycode; keyc <= max_keycode; keyc++) {
1117 /* get data for keycode from X server */
1118 for (i = 0; i < syms; i++) {
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001119 keysym = XKeycodeToKeysym (display, keyc, i);
Pavel Roskinf15d1801999-03-28 13:39:55 +00001120 /* Allow both one-byte and two-byte national keysyms */
Shachar Shemesh4b050942002-05-31 18:21:33 +00001121 if ((keysym < 0x8000) && (keysym != ' '))
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001122 {
1123#ifdef HAVE_XKB
Alexandre Julliard8d361bd2003-03-23 20:07:55 +00001124 if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001125#endif
1126 {
1127 TRACE("XKB could not translate keysym %ld\n", keysym);
1128 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1129 * with appropriate ShiftMask and Mode_switch, use XLookupString
1130 * to get character in the local encoding.
1131 */
1132 ckey[i] = keysym & 0xFF;
1133 }
1134 }
Marcus Meissner2199f6e1999-04-01 12:05:44 +00001135 else {
1136 ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1137 }
Pavel Roskinf15d1801999-03-28 13:39:55 +00001138 }
1139 if (ckey[0]) {
1140 /* search for a match in layout table */
1141 /* right now, we just find an absolute match for defined positions */
1142 /* (undefined positions are ignored, so if it's defined as "3#" in */
1143 /* the table, it's okay that the X server has "3#£", for example) */
1144 /* however, the score will be higher for longer matches */
1145 for (key = 0; key < MAIN_LEN; key++) {
1146 for (ok = 0, i = 0; (ok >= 0) && (i < syms); i++) {
1147 if ((*lkey)[key][i] && ((*lkey)[key][i] == ckey[i]))
1148 ok++;
1149 if ((*lkey)[key][i] && ((*lkey)[key][i] != ckey[i]))
1150 ok = -1;
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001151 }
Pavel Roskinf15d1801999-03-28 13:39:55 +00001152 if (ok > 0) {
1153 score += ok;
1154 break;
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001155 }
1156 }
Pavel Roskinf15d1801999-03-28 13:39:55 +00001157 /* count the matches and mismatches */
Ove Kaaven787cf101999-04-03 11:18:58 +00001158 if (ok > 0) {
Pavel Roskinf15d1801999-03-28 13:39:55 +00001159 match++;
Ove Kaaven787cf101999-04-03 11:18:58 +00001160 /* and how much the keycode order matches */
1161 if (key > pkey) seq++;
1162 pkey = key;
1163 } else {
Peter Mladek5dc7f132002-12-05 19:55:04 +00001164 TRACE_(key)("mismatch for keycode %d, character %c (%02x, %02x, %02x, %02x)\n", keyc, ckey[0], ckey[0], ckey[1], ckey[2], ckey[3]);
Pavel Roskinf15d1801999-03-28 13:39:55 +00001165 mismatch++;
1166 score -= syms;
1167 }
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001168 }
1169 }
Dave Hawkes95d8c952002-02-15 18:21:16 +00001170 TRACE("matches=%d, mismatches=%d, seq=%d, score=%d\n",
1171 match, mismatch, seq, score);
Ove Kaaven787cf101999-04-03 11:18:58 +00001172 if ((score > max_score) ||
1173 ((score == max_score) && (seq > max_seq))) {
Pavel Roskinf15d1801999-03-28 13:39:55 +00001174 /* best match so far */
1175 kbd_layout = current;
1176 max_score = score;
Ove Kaaven787cf101999-04-03 11:18:58 +00001177 max_seq = seq;
Pavel Roskinf15d1801999-03-28 13:39:55 +00001178 ismatch = !mismatch;
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001179 }
Pavel Roskinf15d1801999-03-28 13:39:55 +00001180 }
1181 /* we're done, report results if necessary */
1182 if (!ismatch) {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001183 FIXME(
Ove Kaaven787cf101999-04-03 11:18:58 +00001184 "Your keyboard layout was not found!\n"
Andreas Mohr8c2f4b12001-03-03 00:22:50 +00001185 "Using closest match instead (%s) for scancode mapping.\n"
Rein Klazes82b0a132003-04-16 23:10:21 +00001186 "Please define your layout in dlls/x11drv/keyboard.c and submit them\n"
Pavel Roskinf15d1801999-03-28 13:39:55 +00001187 "to us for inclusion into future Wine releases.\n"
Andriy Palamarchuk4ee65162001-09-17 19:07:56 +00001188 "See the Wine User Guide, chapter \"Keyboard\" for more information.\n",
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +00001189 main_key_tab[kbd_layout].comment);
Pavel Roskinf15d1801999-03-28 13:39:55 +00001190 }
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +00001191
1192 TRACE("detected layout is \"%s\"\n", main_key_tab[kbd_layout].comment);
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001193}
1194
1195/**********************************************************************
Patrik Stridvalldf75e892001-02-12 03:49:07 +00001196 * InitKeyboard (X11DRV.@)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001197 */
Alexandre Julliard4b626182001-10-17 17:50:02 +00001198void X11DRV_InitKeyboard( BYTE *key_state_table )
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001199{
Alexandre Julliard43230042001-05-16 19:52:29 +00001200 Display *display = thread_display();
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001201 KeySym *ksp;
1202 XModifierKeymap *mmp;
1203 KeySym keysym;
1204 KeyCode *kcp;
1205 XKeyEvent e2;
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001206 WORD scan, vkey, OEMvkey;
1207 int keyc, i, keyn, syms;
1208 char ckey[4]={0,0,0,0};
1209 const char (*lkey)[MAIN_LEN][4];
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001210
Alexandre Julliard4b626182001-10-17 17:50:02 +00001211 pKeyStateTable = key_state_table;
1212
Ove Kaavenc90fb252001-01-02 22:39:14 +00001213 wine_tsx11_lock();
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001214 XDisplayKeycodes(display, &min_keycode, &max_keycode);
1215 ksp = XGetKeyboardMapping(display, min_keycode,
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001216 max_keycode + 1 - min_keycode, &keysyms_per_keycode);
1217 /* We are only interested in keysyms_per_keycode.
1218 There is no need to hold a local copy of the keysyms table */
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001219 XFree(ksp);
1220
1221 mmp = XGetModifierMapping(display);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001222 kcp = mmp->modifiermap;
1223 for (i = 0; i < 8; i += 1) /* There are 8 modifier keys */
1224 {
1225 int j;
Vincent Béron9a624912002-05-31 23:06:46 +00001226
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001227 for (j = 0; j < mmp->max_keypermod; j += 1, kcp += 1)
1228 if (*kcp)
1229 {
1230 int k;
Vincent Béron9a624912002-05-31 23:06:46 +00001231
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001232 for (k = 0; k < keysyms_per_keycode; k += 1)
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001233 if (XKeycodeToKeysym(display, *kcp, k) == XK_Num_Lock)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001234 {
1235 NumLockMask = 1 << i;
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001236 TRACE_(key)("NumLockMask is %x\n", NumLockMask);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001237 }
1238 }
1239 }
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001240 XFreeModifiermap(mmp);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001241
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001242 /* Detect the keyboard layout */
1243 X11DRV_KEYBOARD_DetectLayout();
1244 lkey = main_key_tab[kbd_layout].key;
1245 syms = (keysyms_per_keycode > 4) ? 4 : keysyms_per_keycode;
1246
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001247 /* Now build two conversion arrays :
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001248 * keycode -> vkey + scancode + extended
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001249 * vkey + extended -> keycode */
1250
1251 e2.display = display;
1252 e2.state = 0;
1253
1254 OEMvkey = VK_OEM_7; /* next is available. */
1255 for (keyc = min_keycode; keyc <= max_keycode; keyc++)
1256 {
1257 e2.keycode = (KeyCode)keyc;
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001258 XLookupString(&e2, NULL, 0, &keysym, NULL);
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001259 vkey = 0; scan = 0;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001260 if (keysym) /* otherwise, keycode not used */
1261 {
1262 if ((keysym >> 8) == 0xFF) /* non-character key */
1263 {
Alexandre Julliard32fb5802001-10-18 21:38:59 +00001264 vkey = nonchar_key_vkey[keysym & 0xff];
1265 scan = nonchar_key_scan[keysym & 0xff];
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001266 /* set extended bit when necessary */
1267 if (scan & 0x100) vkey |= 0x100;
1268 } else if (keysym == 0x20) { /* Spacebar */
1269 vkey = VK_SPACE;
1270 scan = 0x39;
1271 } else {
1272 /* we seem to need to search the layout-dependent scancodes */
1273 int maxlen=0,maxval=-1,ok;
1274 for (i=0; i<syms; i++) {
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001275 keysym = XKeycodeToKeysym(display, keyc, i);
Alexandre Julliarda52b2772003-01-23 21:35:14 +00001276 if ((keysym<0x8000) && (keysym!=' '))
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001277 {
1278#ifdef HAVE_XKB
Alexandre Julliard8d361bd2003-03-23 20:07:55 +00001279 if (!use_xkb || !XkbTranslateKeySym(display, &keysym, 0, &ckey[i], 1, NULL))
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001280#endif
1281 {
1282 /* FIXME: query what keysym is used as Mode_switch, fill XKeyEvent
1283 * with appropriate ShiftMask and Mode_switch, use XLookupString
1284 * to get character in the local encoding.
1285 */
1286 ckey[i] = keysym & 0xFF;
1287 }
Ove Kaaven787cf101999-04-03 11:18:58 +00001288 } else {
1289 ckey[i] = KEYBOARD_MapDeadKeysym(keysym);
1290 }
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001291 }
1292 /* find key with longest match streak */
1293 for (keyn=0; keyn<MAIN_LEN; keyn++) {
1294 for (ok=(*lkey)[keyn][i=0]; ok&&(i<4); i++)
1295 if ((*lkey)[keyn][i] && (*lkey)[keyn][i]!=ckey[i]) ok=0;
1296 if (ok||(i>maxlen)) {
1297 maxlen=i; maxval=keyn;
1298 }
1299 if (ok) break;
1300 }
1301 if (maxval>=0) {
1302 /* got it */
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +00001303 const WORD (*lscan)[MAIN_LEN] = main_key_tab[kbd_layout].scan;
1304 const WORD (*lvkey)[MAIN_LEN] = main_key_tab[kbd_layout].vkey;
1305 scan = (*lscan)[maxval];
1306 vkey = (*lvkey)[maxval];
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001307 }
1308 }
1309
1310 /* find a suitable layout-dependent VK code */
1311 /* (most Winelib apps ought to be able to work without layout tables!) */
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001312 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1313 {
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001314 keysym = XLookupKeysym(&e2, i);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001315 if ((keysym >= VK_0 && keysym <= VK_9)
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001316 || (keysym >= VK_A && keysym <= VK_Z)) {
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001317 vkey = keysym;
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001318 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001319 }
1320
1321 for (i = 0; (i < keysyms_per_keycode) && (!vkey); i++)
1322 {
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001323 keysym = XLookupKeysym(&e2, i);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001324 switch (keysym)
1325 {
1326 case ';': vkey = VK_OEM_1; break;
1327 case '/': vkey = VK_OEM_2; break;
1328 case '`': vkey = VK_OEM_3; break;
1329 case '[': vkey = VK_OEM_4; break;
1330 case '\\': vkey = VK_OEM_5; break;
1331 case ']': vkey = VK_OEM_6; break;
1332 case '\'': vkey = VK_OEM_7; break;
1333 case ',': vkey = VK_OEM_COMMA; break;
1334 case '.': vkey = VK_OEM_PERIOD; break;
1335 case '-': vkey = VK_OEM_MINUS; break;
1336 case '+': vkey = VK_OEM_PLUS; break;
1337 }
1338 }
1339
1340 if (!vkey)
1341 {
1342 /* Others keys: let's assign OEM virtual key codes in the allowed range,
1343 * that is ([0xba,0xc0], [0xdb,0xe4], 0xe6 (given up) et [0xe9,0xf5]) */
1344 switch (++OEMvkey)
1345 {
1346 case 0xc1 : OEMvkey=0xdb; break;
1347 case 0xe5 : OEMvkey=0xe9; break;
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001348 case 0xf6 : OEMvkey=0xf5; WARN("No more OEM vkey available!\n");
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001349 }
1350
1351 vkey = OEMvkey;
Vincent Béron9a624912002-05-31 23:06:46 +00001352
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001353 if (TRACE_ON(keyboard))
1354 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001355 TRACE("OEM specific virtual key %X assigned to keycode %X:\n",
Alexandre Julliard15de6151999-08-04 12:22:42 +00001356 OEMvkey, e2.keycode);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001357 TRACE("(");
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001358 for (i = 0; i < keysyms_per_keycode; i += 1)
1359 {
1360 char *ksname;
Vincent Béron9a624912002-05-31 23:06:46 +00001361
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001362 keysym = XLookupKeysym(&e2, i);
1363 ksname = XKeysymToString(keysym);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001364 if (!ksname)
1365 ksname = "NoSymbol";
Tony Lambregts2e24a142003-03-15 00:12:42 +00001366 TRACE( "%lX (%s) ", keysym, ksname);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001367 }
Tony Lambregts2e24a142003-03-15 00:12:42 +00001368 TRACE(")\n");
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001369 }
1370 }
1371 }
1372 keyc2vkey[e2.keycode] = vkey;
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001373 keyc2scan[e2.keycode] = scan;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001374 } /* for */
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001375
1376 /* If some keys still lack scancodes, assign some arbitrary ones to them now */
1377 for (scan = 0x60, keyc = min_keycode; keyc <= max_keycode; keyc++)
1378 if (keyc2vkey[keyc]&&!keyc2scan[keyc]) {
1379 char *ksname;
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001380 keysym = XKeycodeToKeysym(display, keyc, 0);
1381 ksname = XKeysymToString(keysym);
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001382 if (!ksname) ksname = "NoSymbol";
1383
1384 /* should make sure the scancode is unassigned here, but >=0x60 currently always is */
1385
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001386 TRACE_(key)("assigning scancode %02x to unidentified keycode %02x (%s)\n",scan,keyc,ksname);
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001387 keyc2scan[keyc]=scan++;
1388 }
1389
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001390 /* Now store one keycode for each modifier. Used to simulate keypresses. */
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001391 kcControl = XKeysymToKeycode(display, XK_Control_L);
1392 kcAlt = XKeysymToKeycode(display, XK_Alt_L);
1393 if (!kcAlt) kcAlt = XKeysymToKeycode(display, XK_Meta_L);
1394 kcShift = XKeysymToKeycode(display, XK_Shift_L);
1395 kcNumLock = XKeysymToKeycode(display, XK_Num_Lock);
1396 kcCapsLock = XKeysymToKeycode(display, XK_Caps_Lock);
1397 wine_tsx11_unlock();
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001398}
1399
Alexandre Julliard4b626182001-10-17 17:50:02 +00001400
1401/***********************************************************************
1402 * X11DRV_MappingNotify
1403 */
1404void X11DRV_MappingNotify( XMappingEvent *event )
1405{
1406 TSXRefreshKeyboardMapping(event);
1407 X11DRV_InitKeyboard( pKeyStateTable );
1408}
1409
1410
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001411/***********************************************************************
Patrik Stridvalldf75e892001-02-12 03:49:07 +00001412 * VkKeyScan (X11DRV.@)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001413 */
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001414WORD X11DRV_VkKeyScan(CHAR cChar)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001415{
Alexandre Julliard43230042001-05-16 19:52:29 +00001416 Display *display = thread_display();
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001417 KeyCode keycode;
Vincent Béron9a624912002-05-31 23:06:46 +00001418 KeySym keysym;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001419 int i,index;
1420 int highbyte=0;
1421
1422 /* char->keysym (same for ANSI chars) */
1423 keysym=(unsigned char) cChar;/* (!) cChar is signed */
1424 if (keysym<=27) keysym+=0xFF00;/*special chars : return, backspace...*/
Vincent Béron9a624912002-05-31 23:06:46 +00001425
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001426 keycode = TSXKeysymToKeycode(display, keysym); /* keysym -> keycode */
1427 if (!keycode)
1428 { /* It didn't work ... let's try with deadchar code. */
1429 keycode = TSXKeysymToKeycode(display, keysym | 0xFE00);
1430 }
1431
Andreas Mohr6e256c722002-10-25 19:09:02 +00001432 TRACE("'%c'(%#lx, %lu): got keycode %#.2x\n",
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001433 cChar,keysym,keysym,keycode);
Vincent Béron9a624912002-05-31 23:06:46 +00001434
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001435 if (keycode)
1436 {
1437 for (index=-1, i=0; (i<8) && (index<0); i++) /* find shift state */
1438 if (TSXKeycodeToKeysym(display,keycode,i)==keysym) index=i;
1439 switch (index) {
1440 case -1 :
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001441 WARN("Keysym %lx not found while parsing the keycode table\n",keysym); break;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001442 case 0 : break;
1443 case 1 : highbyte = 0x0100; break;
Huw D M Davies746706b1999-04-15 16:37:16 +00001444 case 2 : highbyte = 0x0600; break;
1445 case 3 : highbyte = 0x0700; break;
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001446 default : ERR("index %d found by XKeycodeToKeysym. please report! \n",index);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001447 }
1448 /*
1449 index : 0 adds 0x0000
1450 index : 1 adds 0x0100 (shift)
1451 index : ? adds 0x0200 (ctrl)
1452 index : 2 adds 0x0600 (ctrl+alt)
Huw D M Davies746706b1999-04-15 16:37:16 +00001453 index : 3 adds 0x0700 (ctrl+alt+shift)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001454 */
1455 }
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001456 TRACE(" ... returning %#.2x\n", keyc2vkey[keycode]+highbyte);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001457 return keyc2vkey[keycode]+highbyte; /* keycode -> (keyc2vkey) vkey */
1458}
1459
1460/***********************************************************************
Patrik Stridvalldf75e892001-02-12 03:49:07 +00001461 * MapVirtualKey (X11DRV.@)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001462 */
Alexandre Julliard4b626182001-10-17 17:50:02 +00001463UINT X11DRV_MapVirtualKey(UINT wCode, UINT wMapType)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001464{
Alexandre Julliard43230042001-05-16 19:52:29 +00001465 Display *display = thread_display();
1466
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001467#define returnMVK(value) { TRACE("returning 0x%x.\n",value); return value; }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001468
Andreas Mohr6e256c722002-10-25 19:09:02 +00001469 TRACE("wCode=0x%x wMapType=%d ...\n", wCode,wMapType);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001470 switch(wMapType) {
1471 case 0: { /* vkey-code to scan-code */
1472 /* let's do vkey -> keycode -> scan */
1473 int keyc;
1474 for (keyc=min_keycode; keyc<=max_keycode; keyc++)
1475 if ((keyc2vkey[keyc] & 0xFF) == wCode)
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001476 returnMVK (keyc2scan[keyc] & 0xFF);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001477 TRACE("returning no scan-code.\n");
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001478 return 0; }
1479
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001480 case 1: { /* scan-code to vkey-code */
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001481 /* let's do scan -> keycode -> vkey */
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001482 int keyc;
1483 for (keyc=min_keycode; keyc<=max_keycode; keyc++)
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001484 if ((keyc2scan[keyc] & 0xFF) == (wCode & 0xFF))
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001485 returnMVK (keyc2vkey[keyc] & 0xFF);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001486 TRACE("returning no vkey-code.\n");
Ove Kaaven7173e1c1999-03-14 14:00:57 +00001487 return 0; }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001488
1489 case 2: { /* vkey-code to unshifted ANSI code */
David Hammerton50e87682002-06-10 23:02:41 +00001490 /* we still don't know what "unshifted" means. in windows VK_W (0x57)
1491 * returns 0x57, which is upercase 'W'. So we have to return the uppercase
1492 * key.. Looks like something is wrong with the MS docs?
1493 * This is only true for letters, for example VK_0 returns '0' not ')'.
1494 * - hence we use the lock mask to ensure this happens.
1495 */
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001496 /* let's do vkey -> keycode -> (XLookupString) ansi char */
1497 XKeyEvent e;
1498 KeySym keysym;
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001499 int keyc;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001500 char s[2];
1501 e.display = display;
David Hammerton50e87682002-06-10 23:02:41 +00001502
1503 e.state = LockMask;
1504 /* LockMask should behave exactly like caps lock - upercase
1505 * the letter keys and thats about it. */
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001506
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001507 wine_tsx11_lock();
1508
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001509 e.keycode = 0;
1510 /* We exit on the first keycode found, to speed up the thing. */
1511 for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
1512 { /* Find a keycode that could have generated this virtual key */
1513 if ((keyc2vkey[keyc] & 0xFF) == wCode)
1514 { /* We filter the extended bit, we don't know it */
1515 e.keycode = keyc; /* Store it temporarily */
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001516 if ((EVENT_event_to_vkey(0,&e) & 0xFF) != wCode) {
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001517 e.keycode = 0; /* Wrong one (ex: because of the NumLock
1518 state), so set it to 0, we'll find another one */
1519 }
1520 }
1521 }
1522
1523 if ((wCode>=VK_NUMPAD0) && (wCode<=VK_NUMPAD9))
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001524 e.keycode = XKeysymToKeycode(e.display, wCode-VK_NUMPAD0+XK_KP_0);
Vincent Béron9a624912002-05-31 23:06:46 +00001525
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001526 if (wCode==VK_DECIMAL)
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001527 e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001528
1529 if (!e.keycode)
1530 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001531 WARN("Unknown virtual key %X !!! \n", wCode);
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001532 wine_tsx11_unlock();
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001533 return 0; /* whatever */
1534 }
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001535 TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001536
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001537 if (XLookupString(&e, s, 2, &keysym, NULL))
1538 {
1539 wine_tsx11_unlock();
1540 returnMVK (*s);
1541 }
Vincent Béron9a624912002-05-31 23:06:46 +00001542
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001543 TRACE("returning no ANSI.\n");
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001544 wine_tsx11_unlock();
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001545 return 0;
1546 }
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001547
1548 case 3: /* **NT only** scan-code to vkey-code but distinguish between */
1549 /* left and right */
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001550 FIXME(" stub for NT\n");
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001551 return 0;
1552
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001553 default: /* reserved */
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001554 WARN("Unknown wMapType %d !\n", wMapType);
Vincent Béron9a624912002-05-31 23:06:46 +00001555 return 0;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001556 }
1557 return 0;
1558}
1559
1560/***********************************************************************
Patrik Stridvalldf75e892001-02-12 03:49:07 +00001561 * GetKeyNameText (X11DRV.@)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001562 */
Alexandre Julliard4b626182001-10-17 17:50:02 +00001563INT X11DRV_GetKeyNameText(LONG lParam, LPSTR lpBuffer, INT nSize)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001564{
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001565 int vkey, ansi, scanCode;
Guy Albertelli5bd55171999-09-03 12:39:29 +00001566 KeyCode keyc;
Dave Hawkese58557c2001-11-20 18:49:38 +00001567 int keyi;
Guy Albertelli5bd55171999-09-03 12:39:29 +00001568 KeySym keys;
1569 char *name;
Vincent Béron9a624912002-05-31 23:06:46 +00001570
Guy Albertelli2031d6c1999-04-11 14:47:41 +00001571 scanCode = lParam >> 16;
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001572 scanCode &= 0x1ff; /* keep "extended-key" flag with code */
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001573
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001574 /* FIXME: should use MVK type 3 (NT version that distinguishes right and left */
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001575 vkey = X11DRV_MapVirtualKey(scanCode, 1);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001576
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001577 /* handle "don't care" bit (0x02000000) */
1578 if (!(lParam & 0x02000000)) {
1579 switch (vkey) {
1580 case VK_LSHIFT:
1581 case VK_RSHIFT:
1582 vkey = VK_SHIFT;
1583 break;
1584 case VK_LCONTROL:
1585 case VK_RCONTROL:
1586 vkey = VK_CONTROL;
1587 break;
1588 case VK_LMENU:
1589 case VK_RMENU:
1590 vkey = VK_MENU;
1591 break;
1592 default:
1593 break;
1594 }
1595 }
1596
Alexandre Julliard42d20f92000-08-10 01:16:19 +00001597 ansi = X11DRV_MapVirtualKey(vkey, 2);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001598 TRACE("scan 0x%04x, vkey 0x%04x, ANSI 0x%04x\n", scanCode, vkey, ansi);
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001599
Guy Albertelli5bd55171999-09-03 12:39:29 +00001600 /* first get the name of the "regular" keys which is the Upper case
1601 value of the keycap imprint. */
1602 if ( ((ansi >= 0x21) && (ansi <= 0x7e)) &&
1603 (scanCode != 0x137) && /* PrtScn */
1604 (scanCode != 0x135) && /* numpad / */
1605 (scanCode != 0x37 ) && /* numpad * */
1606 (scanCode != 0x4a ) && /* numpad - */
1607 (scanCode != 0x4e ) ) /* numpad + */
Guy Albertelli2031d6c1999-04-11 14:47:41 +00001608 {
1609 if ((nSize >= 2) && lpBuffer)
1610 {
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001611 *lpBuffer = toupper((char)ansi);
Guy Albertelli2031d6c1999-04-11 14:47:41 +00001612 *(lpBuffer+1) = 0;
1613 return 1;
Vincent Béron9a624912002-05-31 23:06:46 +00001614 }
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001615 else
1616 return 0;
Guy Albertelli2031d6c1999-04-11 14:47:41 +00001617 }
1618
Guy Albertelli5bd55171999-09-03 12:39:29 +00001619 /* FIXME: horrible hack to fix function keys. Windows reports scancode
1620 without "extended-key" flag. However Wine generates scancode
1621 *with* "extended-key" flag. Seems to occur *only* for the
1622 function keys. Soooo.. We will leave the table alone and
1623 fudge the lookup here till the other part is found and fixed!!! */
Guy Albertelli76d8abe1999-04-15 15:14:44 +00001624
Guy Albertelli5bd55171999-09-03 12:39:29 +00001625 if ( ((scanCode >= 0x13b) && (scanCode <= 0x144)) ||
1626 (scanCode == 0x157) || (scanCode == 0x158))
1627 scanCode &= 0xff; /* remove "extended-key" flag for Fx keys */
Guy Albertelli2031d6c1999-04-11 14:47:41 +00001628
Guy Albertelli5bd55171999-09-03 12:39:29 +00001629 /* let's do scancode -> keycode -> keysym -> String */
1630
Dave Hawkese58557c2001-11-20 18:49:38 +00001631 for (keyi=min_keycode; keyi<=max_keycode; keyi++)
1632 if ((keyc2scan[keyi]) == scanCode)
Guy Albertelli5bd55171999-09-03 12:39:29 +00001633 break;
Dave Hawkese58557c2001-11-20 18:49:38 +00001634 if (keyi <= max_keycode)
Guy Albertelli5bd55171999-09-03 12:39:29 +00001635 {
Dave Hawkese58557c2001-11-20 18:49:38 +00001636 keyc = (KeyCode) keyi;
Alexandre Julliard43230042001-05-16 19:52:29 +00001637 keys = TSXKeycodeToKeysym(thread_display(), keyc, 0);
Guy Albertelli5bd55171999-09-03 12:39:29 +00001638 name = TSXKeysymToString(keys);
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001639 TRACE("found scan=%04x keyc=%04x keysym=%04x string=%s\n",
1640 scanCode, keyc, (int)keys, name);
Guy Albertelli5bd55171999-09-03 12:39:29 +00001641 if (lpBuffer && nSize && name)
1642 {
Francois Gougetbaa9bf91999-12-27 05:24:06 +00001643 lstrcpynA(lpBuffer, name, nSize);
Guy Albertelli5bd55171999-09-03 12:39:29 +00001644 return 1;
1645 }
1646 }
1647
1648 /* Finally issue FIXME for unknown keys */
1649
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001650 FIXME("(%08lx,%p,%d): unsupported key, vkey=%04x, ansi=%04x\n",lParam,lpBuffer,nSize,vkey,ansi);
Guy Albertelli2031d6c1999-04-11 14:47:41 +00001651 if (lpBuffer && nSize)
1652 *lpBuffer = 0;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001653 return 0;
1654}
1655
1656/***********************************************************************
Marcus Meissner2199f6e1999-04-01 12:05:44 +00001657 * X11DRV_KEYBOARD_MapDeadKeysym
1658 */
1659static char KEYBOARD_MapDeadKeysym(KeySym keysym)
1660{
1661 switch (keysym)
1662 {
1663 /* symbolic ASCII is the same as defined in rfc1345 */
1664#ifdef XK_dead_tilde
1665 case XK_dead_tilde :
1666#endif
1667 case 0x1000FE7E : /* Xfree's XK_Dtilde */
1668 return '~'; /* '? */
1669#ifdef XK_dead_acute
1670 case XK_dead_acute :
1671#endif
1672 case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
1673 return 0xb4; /* '' */
1674#ifdef XK_dead_circumflex
1675 case XK_dead_circumflex:
1676#endif
1677 case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
1678 return '^'; /* '> */
1679#ifdef XK_dead_grave
1680 case XK_dead_grave :
1681#endif
1682 case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
1683 return '`'; /* '! */
1684#ifdef XK_dead_diaeresis
1685 case XK_dead_diaeresis :
1686#endif
1687 case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
1688 return 0xa8; /* ': */
1689#ifdef XK_dead_cedilla
1690 case XK_dead_cedilla :
1691 return 0xb8; /* ', */
1692#endif
1693#ifdef XK_dead_macron
1694 case XK_dead_macron :
1695 return '-'; /* 'm isn't defined on iso-8859-x */
1696#endif
1697#ifdef XK_dead_breve
1698 case XK_dead_breve :
1699 return 0xa2; /* '( */
1700#endif
1701#ifdef XK_dead_abovedot
1702 case XK_dead_abovedot :
1703 return 0xff; /* '. */
1704#endif
1705#ifdef XK_dead_abovering
1706 case XK_dead_abovering :
1707 return '0'; /* '0 isn't defined on iso-8859-x */
1708#endif
1709#ifdef XK_dead_doubleacute
1710 case XK_dead_doubleacute :
1711 return 0xbd; /* '" */
1712#endif
1713#ifdef XK_dead_caron
1714 case XK_dead_caron :
1715 return 0xb7; /* '< */
1716#endif
1717#ifdef XK_dead_ogonek
1718 case XK_dead_ogonek :
1719 return 0xb2; /* '; */
1720#endif
1721/* FIXME: I don't know this three.
1722 case XK_dead_iota :
Vincent Béron9a624912002-05-31 23:06:46 +00001723 return 'i';
Marcus Meissner2199f6e1999-04-01 12:05:44 +00001724 case XK_dead_voiced_sound :
1725 return 'v';
1726 case XK_dead_semivoiced_sound :
1727 return 's';
1728*/
1729 }
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001730 TRACE("no character for dead keysym 0x%08lx\n",keysym);
Marcus Meissner2199f6e1999-04-01 12:05:44 +00001731 return 0;
1732}
1733
1734/***********************************************************************
Patrik Stridvalldf75e892001-02-12 03:49:07 +00001735 * ToUnicode (X11DRV.@)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001736 *
Dmitry Timoshkov8a316342000-10-25 21:34:31 +00001737 * The ToUnicode function translates the specified virtual-key code and keyboard
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001738 * state to the corresponding Windows character or characters.
1739 *
1740 * If the specified key is a dead key, the return value is negative. Otherwise,
1741 * it is one of the following values:
1742 * Value Meaning
1743 * 0 The specified virtual key has no translation for the current state of the keyboard.
1744 * 1 One Windows character was copied to the buffer.
1745 * 2 Two characters were copied to the buffer. This usually happens when a
1746 * dead-key character (accent or diacritic) stored in the keyboard layout cannot
1747 * be composed with the specified virtual key to form a single character.
1748 *
1749 * FIXME : should do the above (return 2 for non matching deadchar+char combinations)
1750 *
1751 */
Dmitry Timoshkov8a316342000-10-25 21:34:31 +00001752INT X11DRV_ToUnicode(UINT virtKey, UINT scanCode, LPBYTE lpKeyState,
1753 LPWSTR bufW, int bufW_size, UINT flags)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001754{
Alexandre Julliard43230042001-05-16 19:52:29 +00001755 Display *display = thread_display();
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001756 XKeyEvent e;
1757 KeySym keysym;
Alexandre Julliarda3960291999-02-26 11:11:13 +00001758 INT ret;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001759 int keyc;
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001760 char lpChar[2];
1761 HWND focus;
1762 XIC xic;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001763
Ulrich Weigand175989d1999-03-10 13:28:30 +00001764 if (scanCode & 0x8000)
1765 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001766 TRACE("Key UP, doing nothing\n" );
Ulrich Weigand175989d1999-03-10 13:28:30 +00001767 return 0;
1768 }
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001769
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001770 e.display = display;
1771 e.keycode = 0;
1772 e.state = 0;
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001773 e.type = KeyPress;
1774
1775 focus = GetFocus();
1776 if (focus) focus = GetAncestor( focus, GA_ROOT );
1777 if (!focus) focus = GetActiveWindow();
1778 e.window = X11DRV_get_whole_window( focus );
1779 xic = X11DRV_get_ic( focus );
1780
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001781 if (lpKeyState[VK_SHIFT] & 0x80)
Dmitry Timoshkovf40fb642002-02-12 18:42:50 +00001782 {
1783 TRACE("ShiftMask = %04x\n", ShiftMask);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001784 e.state |= ShiftMask;
Dmitry Timoshkovf40fb642002-02-12 18:42:50 +00001785 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001786 if (lpKeyState[VK_CAPITAL] & 0x01)
Dmitry Timoshkovf40fb642002-02-12 18:42:50 +00001787 {
1788 TRACE("LockMask = %04x\n", LockMask);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001789 e.state |= LockMask;
Dmitry Timoshkovf40fb642002-02-12 18:42:50 +00001790 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001791 if (lpKeyState[VK_CONTROL] & 0x80)
Dmitry Timoshkovf40fb642002-02-12 18:42:50 +00001792 {
1793 TRACE("ControlMask = %04x\n", ControlMask);
Dmitry Timoshkovef546432001-10-02 17:17:31 +00001794 e.state |= ControlMask;
Dmitry Timoshkovf40fb642002-02-12 18:42:50 +00001795 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001796 if (lpKeyState[VK_NUMLOCK] & 0x01)
Dmitry Timoshkovf40fb642002-02-12 18:42:50 +00001797 {
1798 TRACE("NumLockMask = %04x\n", NumLockMask);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001799 e.state |= NumLockMask;
Dmitry Timoshkovf40fb642002-02-12 18:42:50 +00001800 }
Dmitry Timoshkovef546432001-10-02 17:17:31 +00001801
1802 /* Restore saved AltGr state */
Dmitry Timoshkovf40fb642002-02-12 18:42:50 +00001803 TRACE("AltGrMask = %04x\n", AltGrMask);
Dmitry Timoshkovef546432001-10-02 17:17:31 +00001804 e.state |= AltGrMask;
1805
Alexandre Julliard06c275a1999-05-02 14:32:27 +00001806 TRACE_(key)("(%04X, %04X) : faked state = %X\n",
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001807 virtKey, scanCode, e.state);
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001808 wine_tsx11_lock();
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001809 /* We exit on the first keycode found, to speed up the thing. */
1810 for (keyc=min_keycode; (keyc<=max_keycode) && (!e.keycode) ; keyc++)
1811 { /* Find a keycode that could have generated this virtual key */
1812 if ((keyc2vkey[keyc] & 0xFF) == virtKey)
1813 { /* We filter the extended bit, we don't know it */
1814 e.keycode = keyc; /* Store it temporarily */
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001815 if ((EVENT_event_to_vkey(xic,&e) & 0xFF) != virtKey) {
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001816 e.keycode = 0; /* Wrong one (ex: because of the NumLock
1817 state), so set it to 0, we'll find another one */
1818 }
1819 }
1820 }
1821
1822 if ((virtKey>=VK_NUMPAD0) && (virtKey<=VK_NUMPAD9))
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001823 e.keycode = XKeysymToKeycode(e.display, virtKey-VK_NUMPAD0+XK_KP_0);
Vincent Béron9a624912002-05-31 23:06:46 +00001824
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001825 if (virtKey==VK_DECIMAL)
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001826 e.keycode = XKeysymToKeycode(e.display, XK_KP_Decimal);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001827
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001828 if (!e.keycode && virtKey != VK_NONAME)
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001829 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001830 WARN("Unknown virtual key %X !!! \n",virtKey);
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001831 wine_tsx11_unlock();
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001832 return virtKey; /* whatever */
1833 }
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001834 else TRACE("Found keycode %d (0x%2X)\n",e.keycode,e.keycode);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001835
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001836 if (xic)
1837 ret = XmbLookupString(xic, &e, lpChar, 2, &keysym, NULL);
1838 else
1839 ret = XLookupString(&e, lpChar, 2, &keysym, NULL);
Alexandre Julliarde9119c12002-09-24 18:36:51 +00001840 wine_tsx11_unlock();
1841
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001842 if (ret == 0)
1843 {
Dmitry Timoshkov8a316342000-10-25 21:34:31 +00001844 BYTE dead_char;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001845
Marcus Meissner2199f6e1999-04-01 12:05:44 +00001846 dead_char = KEYBOARD_MapDeadKeysym(keysym);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001847 if (dead_char)
1848 {
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +00001849 MultiByteToWideChar(CP_UNIXCP, 0, &dead_char, 1, bufW, bufW_size);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001850 ret = -1;
1851 }
1852 else
1853 {
1854 char *ksname;
1855
1856 ksname = TSXKeysymToString(keysym);
1857 if (!ksname)
1858 ksname = "No Name";
1859 if ((keysym >> 8) != 0xff)
1860 {
Dimitrie O. Paundd03cc11999-12-08 03:56:23 +00001861 ERR("Please report: no char for keysym %04lX (%s) :\n",
1862 keysym, ksname);
1863 ERR("(virtKey=%X,scanCode=%X,keycode=%X,state=%X)\n",
1864 virtKey, scanCode, e.keycode, e.state);
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001865 }
1866 }
1867 }
Dmitry Timoshkov8a316342000-10-25 21:34:31 +00001868 else { /* ret != 0 */
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001869 /* We have a special case to handle : Shift + arrow, shift + home, ...
1870 X returns a char for it, but Windows doesn't. Let's eat it. */
Ove Kaaven50798442000-12-27 03:45:51 +00001871 if (!(e.state & NumLockMask) /* NumLock is off */
1872 && (e.state & ShiftMask) /* Shift is pressed */
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001873 && (keysym>=XK_KP_0) && (keysym<=XK_KP_9))
1874 {
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001875 lpChar[0] = 0;
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001876 ret = 0;
1877 }
Aric Stewart7ab63982000-11-08 04:29:42 +00001878
Vincent Béron9a624912002-05-31 23:06:46 +00001879 /* more areas where X returns characters but Windows does not
Andreas Mohr6e256c722002-10-25 19:09:02 +00001880 CTRL + number or CTRL + symbol */
Ove Kaaven50798442000-12-27 03:45:51 +00001881 if (e.state & ControlMask)
Aric Stewart7ab63982000-11-08 04:29:42 +00001882 {
Aric Stewartb7b4fd02000-11-28 23:57:38 +00001883 if (((keysym>=33) && (keysym < 'A')) ||
1884 ((keysym > 'Z') && (keysym < 'a')))
1885 {
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001886 lpChar[0] = 0;
Aric Stewartb7b4fd02000-11-28 23:57:38 +00001887 ret = 0;
1888 }
Aric Stewart7ab63982000-11-08 04:29:42 +00001889 }
Aric Stewartb7b4fd02000-11-28 23:57:38 +00001890
Stephane Lussier540a2271999-09-10 13:57:59 +00001891 /* We have another special case for delete key (XK_Delete) on an
1892 extended keyboard. X returns a char for it, but Windows doesn't */
1893 if (keysym == XK_Delete)
1894 {
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001895 lpChar[0] = 0;
Stephane Lussier540a2271999-09-10 13:57:59 +00001896 ret = 0;
1897 }
Dmitry Timoshkovb5f8b922000-10-25 21:58:48 +00001898 else if((lpKeyState[VK_SHIFT] & 0x80) /* Shift is pressed */
1899 && (keysym == XK_KP_Decimal))
1900 {
Alexandre Julliarde5fb9752003-01-23 01:29:58 +00001901 lpChar[0] = 0;
Dmitry Timoshkovb5f8b922000-10-25 21:58:48 +00001902 ret = 0;
1903 }
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +00001904
Dmitry Timoshkov8a316342000-10-25 21:34:31 +00001905 /* perform translation to unicode */
1906 if(ret)
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +00001907 {
Dmitry Timoshkov8a8d1b92003-07-09 04:22:57 +00001908 TRACE_(key)("Translating char 0x%02x to unicode\n", *(BYTE *)lpChar);
1909 ret = MultiByteToWideChar(CP_UNIXCP, 0, lpChar, ret, bufW, bufW_size);
Dmitry Timoshkov7b0bf0f2000-10-17 00:31:53 +00001910 }
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001911 }
1912
Dmitry Timoshkov8a316342000-10-25 21:34:31 +00001913 TRACE_(key)("ToUnicode about to return %d with char %x %s\n",
Dmitry Timoshkovc8ac4a22000-11-25 02:12:49 +00001914 ret, bufW ? bufW[0] : 0, bufW ? "" : "(no buffer)");
Patrik Stridvalle35d6361998-12-07 09:13:40 +00001915 return ret;
1916}
1917
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001918/***********************************************************************
Patrik Stridvalldf75e892001-02-12 03:49:07 +00001919 * Beep (X11DRV.@)
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001920 */
Dmitry Timoshkov8a316342000-10-25 21:34:31 +00001921void X11DRV_Beep(void)
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001922{
Alexandre Julliard43230042001-05-16 19:52:29 +00001923 TSXBell(thread_display(), 0);
Patrik Stridvallb87fe2e1999-04-01 08:16:08 +00001924}