VirtualBox

Changeset 5507 in vbox


Ignore:
Timestamp:
Oct 26, 2007 10:18:10 AM (17 years ago)
Author:
vboxsync
Message:

GUI/Linux host: major update to the Wine keyboard code which should hopefully fix the remaining problems with it

Location:
trunk/src/VBox/Frontends/VirtualBox
Files:
1 edited
3 copied

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VirtualBox/Makefile.kmk

    r5359 r5507  
    6363VBoxKeyboard_TEMPLATE = VBOXR3
    6464VBoxKeyboard_SOURCES  = \
    65         src/linux/keyboard.c
     65        src/linux/keyboard-new.c
    6666
    6767
     
    183183ifeq ($(filter-out freebsd linux netbsd openbsd solaris,$(BUILD_TARGET)),) # X11
    184184VirtualBox_SOURCES += \
    185         src/linux/XKeyboard.cpp
     185        src/linux/XKeyboard-new.cpp
    186186endif
    187187
  • trunk/src/VBox/Frontends/VirtualBox/src/linux/XKeyboard-new.cpp

    r5497 r5507  
    1717 */
    1818
     19#define LOG_GROUP LOG_GROUP_GUI
     20
    1921#include <X11/Xlib.h>
    2022#include <XKeyboard.h>
     23#include <VBox/log.h>
     24#include "keyboard.h"
    2125
    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 */
     31static void printKey(Display *display, int keyc)
     32{
     33    bool was_escape = false;
    2934
    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 */
     76static void dumpLayout(Display *display)
    3277{
    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"));
    36123}
    37124
     
    47134bool initXKeyboard(Display *dpy)
    48135{
    49     X11DRV_InitKeyboard(dpy);
     136    int rc = X11DRV_InitKeyboard(dpy);
     137//    if (0 == rc)
     138    {
     139        dumpLayout(dpy);
     140    }
    50141    return true;
    51142}
     
    54145 * Translate an X server scancode to a PC keyboard scancode.
    55146 */
    56 void handleXKeyEvent(Display *dpy, XEvent *event, WINEKEYBOARDINFO *wineKbdInfo)
     147void handleXKeyEvent(Display *, XEvent *event, WINEKEYBOARDINFO *wineKbdInfo)
    57148{
    58149    // 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;
    60154}
    61155
     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 */
    62162int getKeysymsPerKeycode()
    63163{
    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;
    65167}
  • 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
    18/*
    29 * X11 keyboard driver
     
    2431 */
    2532
    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"
    4234
    4335#include <X11/Xatom.h>
     
    4638#include <X11/Xresource.h>
    4739#include <X11/Xutil.h>
    48 #ifdef HAVE_X11_XKBLIB_H
    49 #include <X11/XKBlib.h>
    50 #endif
    5140
    5241#include <ctype.h>
     
    5443#include <string.h>
    5544
    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
     45static 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
     58unsigned X11DRV_KeyEvent(KeyCode code)
    7559{
    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];
    145061}
    1451 
    1452 static BOOL NumState=FALSE, CapsState=FALSE;
    1453 
    1454 
    1455 /***********************************************************************
    1456  *           X11DRV_send_keyboard_input
    1457  */
    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     else
    1476         wVkStripped = wVk;
    1477 
    1478     keylp.lp2 = 0;
    1479     keylp.lp1.count = 1;
    1480     keylp.lp1.code = wScan;
    1481     keylp.lp1.extended = (dwFlags & KEYEVENTF_EXTENDEDKEY) != 0;
    1482     keylp.lp1.win_internal = 0; /* this has something to do with dialogs,
    1483                                 * don't remember where I read it - AK */
    1484                                 /* it's '1' under windows, when a dialog box appears
    1485                                  * and you press one of the underlined keys - DF*/
    1486 
    1487     /* note that there is a test for all this */
    1488     if (dwFlags & KEYEVENTF_KEYUP )
    1489     {
    1490         message = WM_KEYUP;
    1491         if ((key_state_table[VK_MENU] & 0x80) &&
    1492             ((wVkStripped == VK_MENU) || (wVkStripped == VK_CONTROL)
    1493              || !(key_state_table[VK_CONTROL] & 0x80)))
    1494         {
    1495             if( TrackSysKey == VK_MENU || /* <ALT>-down/<ALT>-up sequence */
    1496                 (wVkStripped != VK_MENU)) /* <ALT>-down...<something else>-up */
    1497                 message = WM_SYSKEYUP;
    1498             TrackSysKey = 0;
    1499         }
    1500         key_state_table[wVk] &= ~0x80;
    1501         key_state_table[wVkStripped] &= ~0x80;
    1502         keylp.lp1.previous = 1;
    1503         keylp.lp1.transition = 1;
    1504     }
    1505     else
    1506     {
    1507         keylp.lp1.previous = (key_state_table[wVk] & 0x80) != 0;
    1508         keylp.lp1.transition = 0;
    1509         if (!(key_state_table[wVk] & 0x80)) key_state_table[wVk] ^= 0x01;
    1510         key_state_table[wVk] |= 0xc0;
    1511         key_state_table[wVkStripped] |= 0xc0;
    1512 
    1513         message = WM_KEYDOWN;
    1514         if ((key_state_table[VK_MENU] & 0x80) && !(key_state_table[VK_CONTROL] & 0x80))
    1515         {
    1516             message = WM_SYSKEYDOWN;
    1517             TrackSysKey = wVkStripped;
    1518         }
    1519     }
    1520 
    1521     keylp.lp1.context = (key_state_table[VK_MENU] & 0x80) != 0; /* 1 if alt */
    1522 
    1523     TRACE_(key)(" wParam=%04x, lParam=%08lx, InputKeyState=%x\n",
    1524                 wVk, keylp.lp2, key_state_table[wVk] );
    1525 
    1526     hook.vkCode      = wVk;
    1527     hook.scanCode    = wScan;
    1528     hook.flags       = (keylp.lp2 >> 24) | injected_flags;
    1529     hook.time        = time;
    1530     hook.dwExtraInfo = dwExtraInfo;
    1531     if (HOOK_CallHooks( WH_KEYBOARD_LL, HC_ACTION, message, (LPARAM)&hook, TRUE )) return;
    1532 
    1533     SERVER_START_REQ( send_hardware_message )
    1534     {
    1535         req->id       = (injected_flags & LLKHF_INJECTED) ? 0 : GetCurrentThreadId();
    1536         req->win      = 0;
    1537         req->msg      = message;
    1538         req->wparam   = wVk;
    1539         req->lparam   = keylp.lp2;
    1540         req->x        = cursor_pos.x;
    1541         req->y        = cursor_pos.y;
    1542         req->time     = time;
    1543         req->info     = dwExtraInfo;
    1544         wine_server_call( req );
    1545     }
    1546     SERVER_END_REQ;
    1547 }
    1548 
    1549 
    1550 /**********************************************************************
    1551  *              KEYBOARD_GenerateMsg
    1552  *
    1553  * Generate Down+Up messages when NumLock or CapsLock is pressed.
    1554  *
    1555  * Convention : called with vkey only VK_NUMLOCK or VK_CAPITAL
    1556  *
    1557  */
    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   } else
    1571     {
    1572         down = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0);
    1573         up = (vkey==VK_NUMLOCK ? KEYEVENTF_EXTENDEDKEY : 0) | KEYEVENTF_KEYUP;
    1574         if ( key_state_table[vkey] & 0x1 ) /* it was ON */
    1575           {
    1576             if (Evtype!=KeyPress)
    1577               {
    1578                 TRACE("ON + KeyRelease => generating DOWN and UP messages.\n");
    1579                 X11DRV_send_keyboard_input( vkey, scan, down, event_time, 0, 0 );
    1580                 X11DRV_send_keyboard_input( vkey, scan, up, event_time, 0, 0 );
    1581                 *State=FALSE;
    1582                 key_state_table[vkey] &= ~0x01; /* Toggle state to off. */
    1583               }
    1584           }
    1585         else /* it was OFF */
    1586           if (Evtype==KeyPress)
    1587             {
    1588               TRACE("OFF + Keypress => generating DOWN and UP messages.\n");
    1589               X11DRV_send_keyboard_input( vkey, scan, down, event_time, 0, 0 );
    1590               X11DRV_send_keyboard_input( vkey, scan, up, event_time, 0, 0 );
    1591               *State=TRUE; /* Goes to intermediary state before going to ON */
    1592               key_state_table[vkey] |= 0x01; /* Toggle state to on. */
    1593             }
    1594     }
    1595 }
    1596 
    1597 /***********************************************************************
    1598  *           KEYBOARD_UpdateOneState
    1599  *
    1600  * Updates internal state for <vkey>, depending on key <state> under X
    1601  *
    1602  */
    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_KeymapNotify
    1620  *
    1621  * Update modifiers state (Ctrl, Alt, Shift) when window is activated.
    1622  *
    1623  * This handles the case where one uses Ctrl+... Alt+... or Shift+.. to switch
    1624  * from wine to another application and back.
    1625  * Toggle keys are handled in HandleEvent.
    1626  */
    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 can
    1634      * skip the first 8 values, hence start at 1
    1635      */
    1636     for (i = 1; i < 32; i++)
    1637     {
    1638         if (!event->xkeymap.key_vector[i]) continue;
    1639         for (j = 0; j < 8; j++)
    1640         {
    1641             if (!(event->xkeymap.key_vector[i] & (1<<j))) continue;
    1642             switch(keyc2vkey[(i * 8) + j] & 0xff)
    1643             {
    1644             case VK_MENU:    alt = 1; break;
    1645             case VK_CONTROL: control = 1; break;
    1646             case VK_SHIFT:   shift = 1; break;
    1647             }
    1648         }
    1649     }
    1650     KEYBOARD_UpdateOneState( VK_MENU, alt, time );
    1651     KEYBOARD_UpdateOneState( VK_CONTROL, control, time );
    1652     KEYBOARD_UpdateOneState( VK_SHIFT, shift, time );
    1653 }
    1654 
    1655 /***********************************************************************
    1656  *           X11DRV_KeyEvent
    1657  *
    1658  * Handle a X key event
    1659  */
    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     else
    1680         ascii_chars = XLookupString(event, Str, sizeof(Str), &keysym, NULL);
    1681     wine_tsx11_unlock();
    1682 
    1683     TRACE_(key)("state = %X nbyte = %d, status 0x%x\n", event->state, ascii_chars, status);
    1684 
    1685     if (status == XBufferOverflow)
    1686         ERR("Buffer Overflow need %i!\n",ascii_chars);
    1687 
    1688     if (status == XLookupChars)
    1689     {
    1690         X11DRV_XIMLookupChars( Str, ascii_chars );
    1691         return;
    1692     }
    1693 
    1694     /* If XKB extensions are used, the state mask for AltGr will use the group
    1695        index instead of the modifier mask. The group index is set in bits
    1696        13-14 of the state field in the XKeyEvent structure. So if AltGr is
    1697        pressed, look if the group index is different than 0. From XKB
    1698        extension documentation, the group index for AltGr should be 2
    1699        (event->state = 0x2000). It's probably better to not assume a
    1700        predefined group index and find it dynamically
    1701 
    1702        Ref: X Keyboard Extension: Library specification (section 14.1.1 and 17.1.1) */
    1703     /* Save also all possible modifier states. */
    1704     AltGrMask = event->state & (0x6000 | Mod1Mask | Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask);
    1705 
    1706     Str[ascii_chars] = '\0';
    1707     if (TRACE_ON(key)){
    1708         const char *ksname;
    1709 
    1710         wine_tsx11_lock();
    1711         ksname = XKeysymToString(keysym);
    1712         wine_tsx11_unlock();
    1713         if (!ksname)
    1714           ksname = "No Name";
    1715         TRACE_(key)("%s : keysym=%lX (%s), # of chars=%d / 0x%02x / '%s'\n",
    1716                     (event->type == KeyPress) ? "KeyPress" : "KeyRelease",
    1717                     keysym, ksname, ascii_chars, Str[0] & 0xff, Str);
    1718     }
    1719 
    1720     wine_tsx11_lock();
    1721     vkey = EVENT_event_to_vkey(xic,event);
    1722     /* X returns keycode 0 for composed characters */
    1723     if (!vkey && ascii_chars) vkey = VK_NONAME;
    1724     wine_tsx11_unlock();
    1725 
    1726     TRACE_(key)("keycode 0x%x converted to vkey 0x%x\n",
    1727                 event->keycode, vkey);
    1728 
    1729    if (vkey)
    1730    {
    1731     switch (vkey & 0xff)
    1732     {
    1733     case VK_NUMLOCK:
    1734       KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, event->type, event_time );
    1735       break;
    1736     case VK_CAPITAL:
    1737       TRACE("Caps Lock event. (type %d). State before : %#.2x\n",event->type,key_state_table[vkey]);
    1738       KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, event->type, event_time );
    1739       TRACE("State after : %#.2x\n",key_state_table[vkey]);
    1740       break;
    1741     default:
    1742         /* Adjust the NUMLOCK state if it has been changed outside wine */
    1743         if (!(key_state_table[VK_NUMLOCK] & 0x01) != !(event->state & NumLockMask))
    1744           {
    1745             TRACE("Adjusting NumLock state.\n");
    1746             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyPress, event_time );
    1747             KEYBOARD_GenerateMsg( VK_NUMLOCK, 0x45, KeyRelease, event_time );
    1748           }
    1749         /* Adjust the CAPSLOCK state if it has been changed outside wine */
    1750         if (!(key_state_table[VK_CAPITAL] & 0x01) != !(event->state & LockMask))
    1751           {
    1752               TRACE("Adjusting Caps Lock state.\n");
    1753             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyPress, event_time );
    1754             KEYBOARD_GenerateMsg( VK_CAPITAL, 0x3A, KeyRelease, event_time );
    1755           }
    1756         /* Not Num nor Caps : end of intermediary states for both. */
    1757         NumState = FALSE;
    1758         CapsState = FALSE;
    1759 
    1760         bScan = keyc2scan[event->keycode] & 0xFF;
    1761         TRACE_(key)("bScan = 0x%02x.\n", bScan);
    1762 
    1763         dwFlags = 0;
    1764         if ( event->type == KeyRelease ) dwFlags |= KEYEVENTF_KEYUP;
    1765         if ( vkey & 0x100 )              dwFlags |= KEYEVENTF_EXTENDEDKEY;
    1766 
    1767         X11DRV_send_keyboard_input( vkey & 0xff, bScan, dwFlags, event_time, 0, 0 );
    1768     }
    1769    }
    1770 }
    1771 
    1772 #else /* OUTOFWINE defined */
    1773 
    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 */
    178262
    178363/**********************************************************************
     
    178767 *  This routine walks through the defined keyboard layouts and selects
    178868 *  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 */
     76static int
     77X11DRV_KEYBOARD_DetectLayout (Display *display, int min_keycode,
     78                              int max_keycode)
    179879{
    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. */
    180688  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. */
    183595  memset( ckey, 0, sizeof(ckey) );
    183696  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;
    1860109      }
    1861110  }
    1862111
     112  /* Now scan the lookup tables, looking for one that is as close as
     113     possible to our current keycode to keysym mapping. */
    1863114  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;
    1864129    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 OUTOFWINE
    1872 /* innotek FIX - dvorak layout */
    1873     last_match = 0;
    1874     misorder = 0;
    1875 #endif
    1876130    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;
    1878136        /* 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;
    1901142          }
    1902143        }
    1903144        /* count the matches and mismatches */
    1904         if (ok > 0) {
     145        if (0 != ok) {
    1905146          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          }
    1908162          pkey = key;
    1909163        } else {
     164#ifdef DEBUG
    1910165          /* 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 */
    1922176        }
    1923177      }
    1924178    }
    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       ) {
    1939184      /* best match so far */
    1940185      kbd_layout = current;
    1941       max_score = score;
     186      max_score = match;
    1942187      max_seq = seq;
    1943       ismatch = !mismatch;
    1944 #ifdef OUTOFWINE
    1945 /* innotek FIX - dvorak layout */
    1946       least_misorder = misorder;
    1947 #endif
    1948188    }
    1949189  }
    1950190  /* 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;
    1956194}
    1957195
    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 */
     206int X11DRV_InitKeyboard(Display *display)
    1966207{
    1967 #ifndef OUTOFWINE
    1968     Display *display = thread_display();
    1969     KeySym *ksp;
    1970     XModifierKeymap *mmp;
    1971208    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
    1989216    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 OUTOFWINE
    1997     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);
    2017217
    2018218    /* 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);
    2024221    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
    2045226    for (keyc = min_keycode; keyc <= max_keycode; keyc++)
    2046227    {
    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);
    2056229        scan = 0;
    2057 #endif
    2058230        if (keysym)  /* otherwise, keycode not used */
    2059231        {
    2060232            if ((keysym >> 8) == 0xFF)         /* non-character key */
    2061233            {
    2062 #ifndef OUTOFWINE
    2063                 vkey = nonchar_key_vkey[keysym & 0xff];
    2064 #endif
    2065234                scan = nonchar_key_scan[keysym & 0xff];
    2066235                /* set extended bit when necessary */
    2067 #ifndef OUTOFWINE
    2068                 if (scan & 0x100) vkey |= 0x100;
    2069 #endif
    2070236            } else if ((keysym >> 8) == 0x1008FF) { /* XFree86 vendor keys */
    2071 #ifndef OUTOFWINE
    2072                 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 #else
    2077237/* innotek FIX - multimedia/internet keys */
    2078                 /* @michael: this needs to be tested and completed some day. */
    2079238                scan = xfree86_vendor_key_scan[keysym & 0xff];
    2080 #endif
    2081239            } else if (keysym == 0x20) {                 /* Spacebar */
    2082 #ifndef OUTOFWINE
    2083                 vkey = VK_SPACE;
    2084 #endif
    2085240                scan = 0x39;
    2086 #ifdef OUTOFWINE
    2087241/* innotek FIX - AltGr support */
    2088242            } else if (keysym == 0xFE03) {               /* ISO level3 shift, aka AltGr */
    2089243                scan = 0x138;
    2090 #endif /* OUTOFWINE defined */
    2091             } else if (have_chars) {
     244            } else {
     245              unsigned found = 0;
     246
    2092247              /* 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                }
    2111257              }
    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;
    2121262              }
    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 */
    2134277            }
    2135278        }
    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;
    2146280    } /* 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)
    2151291    {
    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;
    2257295}
    2258 
    2259 #ifndef OUTOFWINE
    2260 /**********************************************************************
    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             else
    2304                 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 0
    2325     layout = main_key_tab[kbd_layout].lcid;
    2326 #else
    2327     /* FIXME:
    2328      * Winword uses return value of GetKeyboardLayout as a codepage
    2329      * to translate ANSI keyboard messages to unicode. But we have
    2330      * a problem with it: for instance Polish keyboard layout is
    2331      * identical to the US one, and therefore instead of the Polish
    2332      * locale id we return the US one.
    2333      */
    2334     layout = GetUserDefaultLCID();
    2335 #endif
    2336     /*
    2337      * Microsoft Office expects this value to be something specific
    2338      * for Japanese and Korean Windows with an IME the value is 0xe001
    2339      * We should probably check to see if an IME exists and if so then
    2340      * 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     else
    2346         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     else
    2367         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_MappingNotify
    2410  */
    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 instead
    2431  */
    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_UNIXCP
    2442      * 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 0x0000
    2511       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 uppercase
    2556                          * 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 - upercase
    2569                          * 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 NumLock
    2582                                          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 case
    2665      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      else
    2680         return 0;
    2681   }
    2682 
    2683   /* FIXME: horrible hack to fix function keys. Windows reports scancode
    2684             without "extended-key" flag. However Wine generates scancode
    2685             *with* "extended-key" flag. Seems to occur *only* for the
    2686             function keys. Soooo.. We will leave the table alone and
    2687             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_MapDeadKeysym
    2726  */
    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_tilde
    2733             case XK_dead_tilde :
    2734 #endif
    2735             case 0x1000FE7E : /* Xfree's XK_Dtilde */
    2736                 return '~';     /* '? */
    2737 #ifdef XK_dead_acute
    2738             case XK_dead_acute :
    2739 #endif
    2740             case 0x1000FE27 : /* Xfree's XK_Dacute_accent */
    2741                 return (char)0xb4;      /* '' */
    2742 #ifdef XK_dead_circumflex
    2743             case XK_dead_circumflex:
    2744 #endif
    2745             case 0x1000FE5E : /* Xfree's XK_Dcircumflex_accent */
    2746                 return '^';     /* '> */
    2747 #ifdef XK_dead_grave
    2748             case XK_dead_grave :
    2749 #endif
    2750             case 0x1000FE60 : /* Xfree's XK_Dgrave_accent */
    2751                 return '`';     /* '! */
    2752 #ifdef XK_dead_diaeresis
    2753             case XK_dead_diaeresis :
    2754 #endif
    2755             case 0x1000FE22 : /* Xfree's XK_Ddiaeresis */
    2756                 return (char)0xa8;      /* ': */
    2757 #ifdef XK_dead_cedilla
    2758             case XK_dead_cedilla :
    2759                 return (char)0xb8;      /* ', */
    2760 #endif
    2761 #ifdef XK_dead_macron
    2762             case XK_dead_macron :
    2763                 return '-';     /* 'm isn't defined on iso-8859-x */
    2764 #endif
    2765 #ifdef XK_dead_breve
    2766             case XK_dead_breve :
    2767                 return (char)0xa2;      /* '( */
    2768 #endif
    2769 #ifdef XK_dead_abovedot
    2770             case XK_dead_abovedot :
    2771                 return (char)0xff;      /* '. */
    2772 #endif
    2773 #ifdef XK_dead_abovering
    2774             case XK_dead_abovering :
    2775                 return '0';     /* '0 isn't defined on iso-8859-x */
    2776 #endif
    2777 #ifdef XK_dead_doubleacute
    2778             case XK_dead_doubleacute :
    2779                 return (char)0xbd;      /* '" */
    2780 #endif
    2781 #ifdef XK_dead_caron
    2782             case XK_dead_caron :
    2783                 return (char)0xb7;      /* '< */
    2784 #endif
    2785 #ifdef XK_dead_ogonek
    2786             case XK_dead_ogonek :
    2787                 return (char)0xb2;      /* '; */
    2788 #endif
    2789 /* 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 OUTOFWINE
    2803 /***********************************************************************
    2804  *              ToUnicodeEx (X11DRV.@)
    2805  *
    2806  * The ToUnicode function translates the specified virtual-key code and keyboard
    2807  * 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        Meaning
    2812  * 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 a
    2815  *      dead-key character (accent or diacritic) stored in the keyboard layout cannot
    2816  *      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 NumLock
    2896                          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     else
    2930         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_EuroSign
    2938         /* An ugly hack for EuroSign: X can't translate it to a character
    2939            for some locales. */
    2940         if (keysym == XK_EuroSign)
    2941         {
    2942             bufW[0] = 0x20AC;
    2943             ret = 1;
    2944             goto found;
    2945         }
    2946 #endif
    2947         /* 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         else
    2977             {
    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 not
    3006            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 an
    3018          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  
    11/*
    2  * X11 keyboard driver definitions to use it outside wine
     2 * X11 keyboard driver interface
    33 *
    44 * This library is free software; you can redistribute it and/or
     
    2020#define __H_KEYBOARD_OUTOFWINE
    2121
    22 #define HAVE_X11_XKBLIB_H
     22#include <X11/Xlib.h>
    2323
    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
     32extern CCALL __attribute__((visibility("default"))) int X11DRV_InitKeyboard(Display *dpy);
     33extern CCALL __attribute__((visibility("default"))) unsigned X11DRV_KeyEvent(KeyCode code);
     34#else
     35extern CCALL int X11DRV_InitKeyboard(Display *dpy);
     36extern CCALL unsigned X11DRV_KeyEvent(KeyCode code);
    3137#endif
    3238
    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 _WINEKEYBOARDINFO
    39 {
    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_HIDDEN
    48 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 #else
    53 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 #endif
    58 
    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 0
    69 #define TRUE 1
    70 
    7139/* debug macros */
    72 #if 0
     40#if 0 && defined(DEBUG)
    7341# include <stdio.h>
    7442# define noop printf
    7543#else
     44#ifdef __cplusplus
     45inline static void noop(char *, ...)
     46#else
    7647inline static void noop(char *arg, ...)
     48#endif
    7749{
    7850}
     
    8759#define ERR noop
    8860
    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_XKB
    95 
    96 /*
    97  * x11drv.h
    98  */
    99 
    100 
    101 /*
    102  * user.h
    103  */
    104 
    105 
    106 /*
    107  * winuser.h
    108  */
    109 
    110 
    111 /* WM_KEYUP/DOWN/CHAR HIWORD(lParam) flags */
    112 #define KF_EXTENDED         0x0100
    113 #define KF_DLGMODE          0x0800
    114 #define KF_MENUMODE         0x1000
    115 #define KF_ALTDOWN          0x2000
    116 #define KF_REPEAT           0x4000
    117 #define KF_UP               0x8000
    118 
    119 /* Virtual key codes */
    120 #define VK_LBUTTON          0x01
    121 #define VK_RBUTTON          0x02
    122 #define VK_CANCEL           0x03
    123 #define VK_MBUTTON          0x04
    124 #define VK_XBUTTON1         0x05
    125 #define VK_XBUTTON2         0x06
    126 /*                          0x07  Undefined */
    127 #define VK_BACK             0x08
    128 #define VK_TAB              0x09
    129 /*                          0x0A-0x0B  Undefined */
    130 #define VK_CLEAR            0x0C
    131 #define VK_RETURN           0x0D
    132 /*                          0x0E-0x0F  Undefined */
    133 #define VK_SHIFT            0x10
    134 #define VK_CONTROL          0x11
    135 #define VK_MENU             0x12
    136 #define VK_PAUSE            0x13
    137 #define VK_CAPITAL          0x14
    138 
    139 #define VK_KANA             0x15
    140 #define VK_HANGEUL          0x15
    141 #define VK_HANGUL           0x15
    142 #define VK_JUNJA            0x17
    143 #define VK_FINAL            0x18
    144 #define VK_HANJA            0x19
    145 #define VK_KANJI            0x19
    146 
    147 /*                          0x1A       Undefined */
    148 #define VK_ESCAPE           0x1B
    149 
    150 #define VK_CONVERT          0x1C
    151 #define VK_NONCONVERT       0x1D
    152 #define VK_ACCEPT           0x1E
    153 #define VK_MODECHANGE       0x1F
    154 
    155 #define VK_SPACE            0x20
    156 #define VK_PRIOR            0x21
    157 #define VK_NEXT             0x22
    158 #define VK_END              0x23
    159 #define VK_HOME             0x24
    160 #define VK_LEFT             0x25
    161 #define VK_UP               0x26
    162 #define VK_RIGHT            0x27
    163 #define VK_DOWN             0x28
    164 #define VK_SELECT           0x29
    165 #define VK_PRINT            0x2A /* OEM specific in Windows 3.1 SDK */
    166 #define VK_EXECUTE          0x2B
    167 #define VK_SNAPSHOT         0x2C
    168 #define VK_INSERT           0x2D
    169 #define VK_DELETE           0x2E
    170 #define VK_HELP             0x2F
    171 /* 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             0x5B
    175 #define VK_RWIN             0x5C
    176 #define VK_APPS             0x5D
    177 /*                          0x5E Unassigned */
    178 #define VK_SLEEP            0x5F
    179 #define VK_NUMPAD0          0x60
    180 #define VK_NUMPAD1          0x61
    181 #define VK_NUMPAD2          0x62
    182 #define VK_NUMPAD3          0x63
    183 #define VK_NUMPAD4          0x64
    184 #define VK_NUMPAD5          0x65
    185 #define VK_NUMPAD6          0x66
    186 #define VK_NUMPAD7          0x67
    187 #define VK_NUMPAD8          0x68
    188 #define VK_NUMPAD9          0x69
    189 #define VK_MULTIPLY         0x6A
    190 #define VK_ADD              0x6B
    191 #define VK_SEPARATOR        0x6C
    192 #define VK_SUBTRACT         0x6D
    193 #define VK_DECIMAL          0x6E
    194 #define VK_DIVIDE           0x6F
    195 #define VK_F1               0x70
    196 #define VK_F2               0x71
    197 #define VK_F3               0x72
    198 #define VK_F4               0x73
    199 #define VK_F5               0x74
    200 #define VK_F6               0x75
    201 #define VK_F7               0x76
    202 #define VK_F8               0x77
    203 #define VK_F9               0x78
    204 #define VK_F10              0x79
    205 #define VK_F11              0x7A
    206 #define VK_F12              0x7B
    207 #define VK_F13              0x7C
    208 #define VK_F14              0x7D
    209 #define VK_F15              0x7E
    210 #define VK_F16              0x7F
    211 #define VK_F17              0x80
    212 #define VK_F18              0x81
    213 #define VK_F19              0x82
    214 #define VK_F20              0x83
    215 #define VK_F21              0x84
    216 #define VK_F22              0x85
    217 #define VK_F23              0x86
    218 #define VK_F24              0x87
    219 /*                          0x88-0x8F  Unassigned */
    220 #define VK_NUMLOCK          0x90
    221 #define VK_SCROLL           0x91
    222 #define VK_OEM_NEC_EQUAL    0x92
    223 #define VK_OEM_FJ_JISHO     0x92
    224 #define VK_OEM_FJ_MASSHOU   0x93
    225 #define VK_OEM_FJ_TOUROKU   0x94
    226 #define VK_OEM_FJ_LOYA      0x95
    227 #define VK_OEM_FJ_ROYA      0x96
    228 /*                          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           0xA0
    234 #define VK_RSHIFT           0xA1
    235 #define VK_LCONTROL         0xA2
    236 #define VK_RCONTROL         0xA3
    237 #define VK_LMENU            0xA4
    238 #define VK_RMENU            0xA5
    239 
    240 #define VK_BROWSER_BACK        0xA6
    241 #define VK_BROWSER_FORWARD     0xA7
    242 #define VK_BROWSER_REFRESH     0xA8
    243 #define VK_BROWSER_STOP        0xA9
    244 #define VK_BROWSER_SEARCH      0xAA
    245 #define VK_BROWSER_FAVORITES   0xAB
    246 #define VK_BROWSER_HOME        0xAC
    247 #define VK_VOLUME_MUTE         0xAD
    248 #define VK_VOLUME_DOWN         0xAE
    249 #define VK_VOLUME_UP           0xAF
    250 #define VK_MEDIA_NEXT_TRACK    0xB0
    251 #define VK_MEDIA_PREV_TRACK    0xB1
    252 #define VK_MEDIA_STOP          0xB2
    253 #define VK_MEDIA_PLAY_PAUSE    0xB3
    254 #define VK_LAUNCH_MAIL         0xB4
    255 #define VK_LAUNCH_MEDIA_SELECT 0xB5
    256 #define VK_LAUNCH_APP1         0xB6
    257 #define VK_LAUNCH_APP2         0xB7
    258 
    259 /*                          0xB8-0xB9  Unassigned */
    260 #define VK_OEM_1            0xBA
    261 #define VK_OEM_PLUS         0xBB
    262 #define VK_OEM_COMMA        0xBC
    263 #define VK_OEM_MINUS        0xBD
    264 #define VK_OEM_PERIOD       0xBE
    265 #define VK_OEM_2            0xBF
    266 #define VK_OEM_3            0xC0
    267 /*                          0xC1-0xDA  Unassigned */
    268 #define VK_OEM_4            0xDB
    269 #define VK_OEM_5            0xDC
    270 #define VK_OEM_6            0xDD
    271 #define VK_OEM_7            0xDE
    272 #define VK_OEM_8            0xDF
    273 /*                          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       0xE5
    279 
    280 /*                          0xE6       OEM specific */
    281 /*                          0xE7-0xE8  Unassigned */
    282 /*                          0xE9-0xF5  OEM specific */
    283 
    284 #define VK_ATTN             0xF6
    285 #define VK_CRSEL            0xF7
    286 #define VK_EXSEL            0xF8
    287 #define VK_EREOF            0xF9
    288 #define VK_PLAY             0xFA
    289 #define VK_ZOOM             0xFB
    290 #define VK_NONAME           0xFC
    291 #define VK_PA1              0xFD
    292 #define VK_OEM_CLEAR        0xFE
    293 
    294 /* ... */
    295 
    296   /* keybd_event flags */
    297 #define KEYEVENTF_EXTENDEDKEY        0x0001
    298 #define KEYEVENTF_KEYUP              0x0002
    299 
    300 /* end of winuser.h */
    301 
    302 
    30361#endif /* __H_KEYBOARD_OUTOFWINE */
Note: See TracChangeset for help on using the changeset viewer.

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