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