From 1b6e5b491ae717eb096a7d4a68df9f772de577ae Mon Sep 17 00:00:00 2001
From: Lars-Dominik Braun <lars@6xq.net>
Date: Sun, 13 Sep 2020 12:47:51 +0200
Subject: winkbd: Make Windows driver compileable with MingGW

Automate the process via GitHub Actions as well.  kbd.h can be
simplified.

Fixes #11.
---
 .github/workflows/ci.yml      |    4 +-
 README.rst                    |   25 +-
 gen.sh                        |   18 +-
 lulua/data/winkbd/build.ninja |   32 +
 lulua/data/winkbd/kbd.h       | 2478 +++++++++++++++++++++++++++++++++++++++++
 lulua/data/winkbd/keyboard.c  |    1 -
 lulua/data/winkbd/keyboard.rc |    8 +-
 lulua/data/winkbd/linker.ld   |   36 +
 lulua/data/winkbd/make.bat    |   22 -
 lulua/render.py               |    5 +-
 10 files changed, 2571 insertions(+), 58 deletions(-)
 create mode 100644 lulua/data/winkbd/build.ninja
 create mode 100644 lulua/data/winkbd/kbd.h
 create mode 100644 lulua/data/winkbd/linker.ld
 delete mode 100755 lulua/data/winkbd/make.bat

diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 8886753..eb34f05 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -18,7 +18,7 @@ jobs:
         python-version: ${{ matrix.python-version }}
     - name: Install dependencies
       run: |
-        sudo apt install ninja-build libxml2-dev libxslt1-dev
+        sudo apt install ninja-build libxml2-dev libxslt1-dev mingw-w64
         pip install .
         pip install flake8 pytest pytest-cov
     - name: Lint with flake8
@@ -37,7 +37,7 @@ jobs:
       # Due to the lack of corpora, we can’t run the entire thing here.
       run: |
         ./gen.sh > build.ninja
-        ninja _build/report/ar-lulua.svg _build/report/ar-lulua.xmodmap
+        ninja _build/report/ar-lulua.svg _build/report/ar-lulua.xmodmap _build/report/ar-lulua-w64.zip
     - name: Upload results
       uses: actions/upload-artifact@v2
       with:
diff --git a/README.rst b/README.rst
index 6ed53eb..7234524 100644
--- a/README.rst
+++ b/README.rst
@@ -51,9 +51,10 @@ issues. Also the following software is required:
 
 - Python/`PyPy 3`_
 - Ninja_ (for the build process)
-- GNU autotools and a C compiler (for ``3rdparty/osmctools``)
+- GNU autotools and a host C compiler (for ``3rdparty/osmctools``)
 - GNU bash and zip (for ``makezip.sh``)
 - librsvg (``rsvg-convert`` is used to create PDF’s from SVG images)
+- MinGW (to compile the Windows keyboard driver)
 
 .. _Ninja: https://ninja-build.org/
 
@@ -68,28 +69,6 @@ to run the analysis and create pretty pictures as well as statistics in
 
 .. _me: lars+lulua@6xq.net
 
-Building Windows drivers
-------------------------
-
-There is no easy way to build Windows keyboard drivers, but the following
-instructions have worked in the past:
-
-.. code:: bash
-
-    ninja _build/_temp/winkbd/customization.h
-
-Share the folder `doc/_temp/winkbd` with a Windows system, install `Microsoft
-Keyboard Layout Creator 1.4`_ (MSKLC; the Windows Driver Kit (WDK) would work
-too, but is much larger), adjust ``make.bat`` pointing to your MSKLC
-installation and run it. This should generate two directories, ``System32`` and
-``SysWOW64``, which must be copied back to `_build/_temp/winkbd`. Then run:
-
-.. code:: bash
-
-    ninja _build/report/ar-lulua-w64.zip
-
-.. _Microsoft Keyboard Layout Creator 1.4: https://www.microsoft.com/en-us/download/details.aspx?id=22339
-
 Acknowledgements
 ----------------
 
diff --git a/gen.sh b/gen.sh
index 490a198..5f4878d 100755
--- a/gen.sh
+++ b/gen.sh
@@ -108,9 +108,6 @@ rule report
 rule cp
     command = cp \$in \$out
 
-rule cpR
-    command = cp -R \$in \$out
-
 rule gz
     command = gzip -c \$in > \$out
 
@@ -123,6 +120,9 @@ rule zipR
 rule render-winkbd
     command = lulua-render -l ar-lulua winkbd \$out
 
+rule ninjaC
+    command = ninja -C \$dir
+
 ### build targets ###
 build \$reportdir: mkdir
 build \$reportdir/fonts: mkdir
@@ -142,9 +142,19 @@ build \$reportdir/fonts/IBMPlexSansArabic-Thin.woff2: cp \$fontdir/IBMPlexSansAr
 build \$osmconvert: configure-make 3rdparty/osmctools
 
 # windows drivers
-build \$tempdir/winkbd: cpR lulua/data/winkbd
+build \$tempdir/winkbd: mkdir lulua/data/winkbd
+EOF
+# Create dependencies for the non-customized files
+for f in $(ls lulua/data/winkbd/); do
+    echo "build \$tempdir/winkbd/$f: cp lulua/data/winkbd/$f || \$tempdir/winkbd"
+    w64infiles+=" \$tempdir/winkbd/$f"
+done
+w64infiles+=" \$tempdir/winkbd/customization.h"
+cat <<EOF
 build \$tempdir/winkbd/customization.h: render-winkbd || \$tempdir/winkbd
 build \$tempdir/ar-lulua-w64: mkdir
+build \$tempdir/winkbd/System32/kbdarlulua.dll \$tempdir/winkbd/SysWOW64/kbdarlulua.dll: ninjaC | $w64infiles
+    dir = \$tempdir/winkbd
 EOF
 
 w64zipfile="System32/kbdarlulua.dll SysWOW64/kbdarlulua.dll README.txt lulua.reg install.bat"
diff --git a/lulua/data/winkbd/build.ninja b/lulua/data/winkbd/build.ninja
new file mode 100644
index 0000000..4b80e3d
--- /dev/null
+++ b/lulua/data/winkbd/build.ninja
@@ -0,0 +1,32 @@
+# based on https://github.com/reactos/reactos/blob/893a3c9d030fd8b078cbd747eeefd3f6ce57e560/dll/keyboard/CMakeLists.txt
+imageBase=0x5FFF0000
+ldflags=-shared -nostartfiles -nodefaultlibs -s -Wl,--subsystem,native:5.01 -Wl,--image-base,$imageBase -Wl,-entry,0 -Wl,-T,linker.ld
+cflags=
+
+rule mkdir
+    command = mkdir -p $out
+    description = mkdir $out
+
+rule res
+    command = x86_64-w64-mingw32-windres --target=$target $in $out
+    description = res $out
+
+rule cc
+    command = x86_64-w64-mingw32-gcc -m$bits $cflags $ldflags -o $out $in
+    description = cc $out
+
+build System32/kbdarlulua.dll: cc keyboard.c keyboard.def rc64.o | linker.ld || System32
+    bits = 64
+
+build SysWOW64/kbdarlulua.dll: cc keyboard.c keyboard.def rc32.o | linker.ld || SysWOW64
+    bits = 32
+
+build rc64.o: res keyboard.rc
+    target = pe-x86-64
+
+build rc32.o: res keyboard.rc
+    target = pe-i386
+
+build System32: mkdir
+build SysWOW64: mkdir
+
diff --git a/lulua/data/winkbd/kbd.h b/lulua/data/winkbd/kbd.h
new file mode 100644
index 0000000..1c7478c
--- /dev/null
+++ b/lulua/data/winkbd/kbd.h
@@ -0,0 +1,2478 @@
+/****************************** Module Header ******************************\
+* Module Name: kbd.h
+*
+* Copyright (c) Microsoft Corporation. All rights reserved.
+*
+* Keyboard table values that form the basis for languages and keyboard types.
+* The basis is US, kbd type 4 - all others are a variation on this.
+* This file is included by all kbd**.h files.
+*
+* History:
+@@BEGIN_DDKSPLIT
+* 10-Jan-1991 GregoryW
+* 23-Apr-1991 IanJa         VSC_TO_VK _* macros from oemtab.c
+@@END_DDKSPLIT
+\***************************************************************************/
+
+#ifndef _KBD_
+#define _KBD_
+
+#include <wchar.h>
+
+typedef void VOID;
+typedef unsigned char BYTE;
+typedef unsigned short WORD;
+typedef unsigned short USHORT;
+typedef unsigned long DWORD;
+typedef unsigned long DWORD_PTR;
+typedef unsigned long ULONG;
+typedef long LONG;
+typedef unsigned int UINT;
+typedef int INT;
+typedef wchar_t WCHAR;
+#define MAKELONG(a, b)      ((LONG)(((WORD)(((DWORD_PTR)(a)) & 0xffff)) | ((DWORD)((WORD)(((DWORD_PTR)(b)) & 0xffff))) << 16))
+
+/*
+ * Virtual Keys, Standard Set
+ */
+#define VK_LBUTTON        0x01
+#define VK_RBUTTON        0x02
+#define VK_CANCEL         0x03
+#define VK_MBUTTON        0x04    /* NOT contiguous with L & RBUTTON */
+
+#if(_WIN32_WINNT >= 0x0500)
+#define VK_XBUTTON1       0x05    /* NOT contiguous with L & RBUTTON */
+#define VK_XBUTTON2       0x06    /* NOT contiguous with L & RBUTTON */
+#endif /* _WIN32_WINNT >= 0x0500 */
+
+/*
+ * 0x07 : unassigned
+ */
+
+#define VK_BACK           0x08
+#define VK_TAB            0x09
+
+/*
+ * 0x0A - 0x0B : reserved
+ */
+
+#define VK_CLEAR          0x0C
+#define VK_RETURN         0x0D
+
+#define VK_SHIFT          0x10
+#define VK_CONTROL        0x11
+#define VK_MENU           0x12
+#define VK_PAUSE          0x13
+#define VK_CAPITAL        0x14
+
+#define VK_KANA           0x15
+#define VK_HANGEUL        0x15  /* old name - should be here for compatibility */
+#define VK_HANGUL         0x15
+#define VK_JUNJA          0x17
+#define VK_FINAL          0x18
+#define VK_HANJA          0x19
+#define VK_KANJI          0x19
+
+#define VK_ESCAPE         0x1B
+
+#define VK_CONVERT        0x1C
+#define VK_NONCONVERT     0x1D
+#define VK_ACCEPT         0x1E
+#define VK_MODECHANGE     0x1F
+
+#define VK_SPACE          0x20
+#define VK_PRIOR          0x21
+#define VK_NEXT           0x22
+#define VK_END            0x23
+#define VK_HOME           0x24
+#define VK_LEFT           0x25
+#define VK_UP             0x26
+#define VK_RIGHT          0x27
+#define VK_DOWN           0x28
+#define VK_SELECT         0x29
+#define VK_PRINT          0x2A
+#define VK_EXECUTE        0x2B
+#define VK_SNAPSHOT       0x2C
+#define VK_INSERT         0x2D
+#define VK_DELETE         0x2E
+#define VK_HELP           0x2F
+
+/*
+ * VK_0 - VK_9 are the same as ASCII '0' - '9' (0x30 - 0x39)
+ * 0x40 : unassigned
+ * VK_A - VK_Z are the same as ASCII 'A' - 'Z' (0x41 - 0x5A)
+ */
+
+#define VK_LWIN           0x5B
+#define VK_RWIN           0x5C
+#define VK_APPS           0x5D
+
+/*
+ * 0x5E : reserved
+ */
+
+#define VK_SLEEP          0x5F
+
+#define VK_NUMPAD0        0x60
+#define VK_NUMPAD1        0x61
+#define VK_NUMPAD2        0x62
+#define VK_NUMPAD3        0x63
+#define VK_NUMPAD4        0x64
+#define VK_NUMPAD5        0x65
+#define VK_NUMPAD6        0x66
+#define VK_NUMPAD7        0x67
+#define VK_NUMPAD8        0x68
+#define VK_NUMPAD9        0x69
+#define VK_MULTIPLY       0x6A
+#define VK_ADD            0x6B
+#define VK_SEPARATOR      0x6C
+#define VK_SUBTRACT       0x6D
+#define VK_DECIMAL        0x6E
+#define VK_DIVIDE         0x6F
+#define VK_F1             0x70
+#define VK_F2             0x71
+#define VK_F3             0x72
+#define VK_F4             0x73
+#define VK_F5             0x74
+#define VK_F6             0x75
+#define VK_F7             0x76
+#define VK_F8             0x77
+#define VK_F9             0x78
+#define VK_F10            0x79
+#define VK_F11            0x7A
+#define VK_F12            0x7B
+#define VK_F13            0x7C
+#define VK_F14            0x7D
+#define VK_F15            0x7E
+#define VK_F16            0x7F
+#define VK_F17            0x80
+#define VK_F18            0x81
+#define VK_F19            0x82
+#define VK_F20            0x83
+#define VK_F21            0x84
+#define VK_F22            0x85
+#define VK_F23            0x86
+#define VK_F24            0x87
+
+/*
+ * 0x88 - 0x8F : unassigned
+ */
+
+#define VK_NUMLOCK        0x90
+#define VK_SCROLL         0x91
+
+/*
+ * NEC PC-9800 kbd definitions
+ */
+#define VK_OEM_NEC_EQUAL  0x92   // '=' key on numpad
+
+/*
+ * Fujitsu/OASYS kbd definitions
+ */
+#define VK_OEM_FJ_JISHO   0x92   // 'Dictionary' key
+#define VK_OEM_FJ_MASSHOU 0x93   // 'Unregister word' key
+#define VK_OEM_FJ_TOUROKU 0x94   // 'Register word' key
+#define VK_OEM_FJ_LOYA    0x95   // 'Left OYAYUBI' key
+#define VK_OEM_FJ_ROYA    0x96   // 'Right OYAYUBI' key
+
+/*
+ * 0x97 - 0x9F : unassigned
+ */
+
+/*
+ * VK_L* & VK_R* - left and right Alt, Ctrl and Shift virtual keys.
+ * Used only as parameters to GetAsyncKeyState() and GetKeyState().
+ * No other API or message will distinguish left and right keys in this way.
+ */
+#define VK_LSHIFT         0xA0
+#define VK_RSHIFT         0xA1
+#define VK_LCONTROL       0xA2
+#define VK_RCONTROL       0xA3
+#define VK_LMENU          0xA4
+#define VK_RMENU          0xA5
+
+#if(_WIN32_WINNT >= 0x0500)
+#define VK_BROWSER_BACK        0xA6
+#define VK_BROWSER_FORWARD     0xA7
+#define VK_BROWSER_REFRESH     0xA8
+#define VK_BROWSER_STOP        0xA9
+#define VK_BROWSER_SEARCH      0xAA
+#define VK_BROWSER_FAVORITES   0xAB
+#define VK_BROWSER_HOME        0xAC
+
+#define VK_VOLUME_MUTE         0xAD
+#define VK_VOLUME_DOWN         0xAE
+#define VK_VOLUME_UP           0xAF
+#define VK_MEDIA_NEXT_TRACK    0xB0
+#define VK_MEDIA_PREV_TRACK    0xB1
+#define VK_MEDIA_STOP          0xB2
+#define VK_MEDIA_PLAY_PAUSE    0xB3
+#define VK_LAUNCH_MAIL         0xB4
+#define VK_LAUNCH_MEDIA_SELECT 0xB5
+#define VK_LAUNCH_APP1         0xB6
+#define VK_LAUNCH_APP2         0xB7
+
+#endif /* _WIN32_WINNT >= 0x0500 */
+
+/*
+ * 0xB8 - 0xB9 : reserved
+ */
+
+#define VK_OEM_1          0xBA   // ';:' for US
+#define VK_OEM_PLUS       0xBB   // '+' any country
+#define VK_OEM_COMMA      0xBC   // ',' any country
+#define VK_OEM_MINUS      0xBD   // '-' any country
+#define VK_OEM_PERIOD     0xBE   // '.' any country
+#define VK_OEM_2          0xBF   // '/?' for US
+#define VK_OEM_3          0xC0   // '`~' for US
+
+/*
+ * 0xC1 - 0xD7 : reserved
+ */
+
+/*
+ * 0xD8 - 0xDA : unassigned
+ */
+
+#define VK_OEM_4          0xDB  //  '[{' for US
+#define VK_OEM_5          0xDC  //  '\|' for US
+#define VK_OEM_6          0xDD  //  ']}' for US
+#define VK_OEM_7          0xDE  //  ''"' for US
+#define VK_OEM_8          0xDF
+
+/*
+ * 0xE0 : reserved
+ */
+
+/*
+ * Various extended or enhanced keyboards
+ */
+#define VK_OEM_AX         0xE1  //  'AX' key on Japanese AX kbd
+#define VK_OEM_102        0xE2  //  "<>" or "\|" on RT 102-key kbd.
+#define VK_ICO_HELP       0xE3  //  Help key on ICO
+#define VK_ICO_00         0xE4  //  00 key on ICO
+
+#if(WINVER >= 0x0400)
+#define VK_PROCESSKEY     0xE5
+#endif /* WINVER >= 0x0400 */
+
+#define VK_ICO_CLEAR      0xE6
+
+
+#if(_WIN32_WINNT >= 0x0500)
+#define VK_PACKET         0xE7
+#endif /* _WIN32_WINNT >= 0x0500 */
+
+/*
+ * 0xE8 : unassigned
+ */
+
+/*
+ * Nokia/Ericsson definitions
+ */
+#define VK_OEM_RESET      0xE9
+#define VK_OEM_JUMP       0xEA
+#define VK_OEM_PA1        0xEB
+#define VK_OEM_PA2        0xEC
+#define VK_OEM_PA3        0xED
+#define VK_OEM_WSCTRL     0xEE
+#define VK_OEM_CUSEL      0xEF
+#define VK_OEM_ATTN       0xF0
+#define VK_OEM_FINISH     0xF1
+#define VK_OEM_COPY       0xF2
+#define VK_OEM_AUTO       0xF3
+#define VK_OEM_ENLW       0xF4
+#define VK_OEM_BACKTAB    0xF5
+
+#define VK_ATTN           0xF6
+#define VK_CRSEL          0xF7
+#define VK_EXSEL          0xF8
+#define VK_EREOF          0xF9
+#define VK_PLAY           0xFA
+#define VK_ZOOM           0xFB
+#define VK_NONAME         0xFC
+#define VK_PA1            0xFD
+#define VK_OEM_CLEAR      0xFE
+
+/*
+ * 0xFF : reserved
+ */
+
+
+#if defined(BUILD_WOW6432)
+    #define KBD_LONG_POINTER __ptr64
+#else
+    #define KBD_LONG_POINTER
+#endif
+
+
+/****************************************************************************\
+*
+* Keyboard Layers.   Used in kdb??.dll and in usersrv.dll
+*
+\****************************************************************************/
+
+/*
+ * KE.usFlaggedVk values, also used in the keyboard layer tables.
+ */
+#define KBDEXT        (USHORT)0x0100
+#define KBDMULTIVK    (USHORT)0x0200
+#define KBDSPECIAL    (USHORT)0x0400
+#define KBDNUMPAD     (USHORT)0x0800
+#define KBDUNICODE    (USHORT)0x1000
+#define KBDINJECTEDVK (USHORT)0x2000
+#if (NTDDI_VERSION >= NTDDI_WINXP)
+#define KBDMAPPEDVK   (USHORT)0x4000
+#endif
+#define KBDBREAK      (USHORT)0x8000
+
+/*
+ * Key message lParam bits
+ */
+#define EXTENDED_BIT   0x01000000
+#define DONTCARE_BIT   0x02000000
+#define FAKE_KEYSTROKE 0x02000000
+#define ALTNUMPAD_BIT  0x04000000 // copied from windows\inc\wincon.w
+
+/*
+ * Keyboard Shift State defines. These correspond to the bit mask defined
+ * by the VkKeyScan() API.
+ */
+#define KBDBASE        0
+#define KBDSHIFT       1
+#define KBDCTRL        2
+#define KBDALT         4
+// three symbols KANA, ROYA, LOYA are for FE
+#define KBDKANA        8
+#define KBDROYA        0x10
+#define KBDLOYA        0x20
+#define KBDGRPSELTAP   0x80
+
+/*
+ * Handy diacritics
+ */
+#define GRAVE           0x0300
+#define ACUTE           0x0301
+#define CIRCUMFLEX      0x0302
+#define TILDE           0x0303
+#define MACRON          0x0304
+#define OVERSCORE       0x0305
+#define BREVE           0x0306
+#define DOT_ABOVE       0x0307
+#define UMLAUT          0x0308
+#define DIARESIS        UMLAUT
+#define HOOK_ABOVE      0x0309
+#define RING            0x030A
+#define DOUBLE_ACUTE    0x030B
+#define HACEK           0x030C
+
+#define CEDILLA         0x0327
+#define OGONEK          0x0328
+#define TONOS           0x0384
+#define DIARESIS_TONOS  0x0385
+
+
+#define wszGRAVE           L"\x0300"
+#define wszACUTE           L"\x0301"
+#define wszCIRCUMFLEX      L"\x0302"
+#define wszTILDE           L"\x0303"
+#define wszMACRON          L"\x0304"
+#define wszOVERSCORE       L"\x0305"
+#define wszBREVE           L"\x0306"
+#define wszDOT_ABOVE       L"\x0307"
+#define wszUMLAUT          L"\x0308"
+#define wszHOOK_ABOVE      L"\x0309"
+#define wszRING            L"\x030A"
+#define wszDOUBLE_ACUTE    L"\x030B"
+#define wszHACEK           L"\x030C"
+
+#define wszCEDILLA         L"\x0327"
+#define wszOGONEK          L"\x0328"
+#define wszTONOS           L"\x0384"
+#define wszDIARESIS_TONOS  L"\x0385"
+
+#define IDS_FROM_SCANCODE(prefix, base) \
+        (0xc000 + ((0x ## prefix) >= 0xE0 ? 0x100 : 0) + (0x ## base))
+
+/***************************************************************************\
+* MODIFIER KEYS
+*
+* All keyboards have "Modifier" keys which are used to alter the behaviour of
+* some of the other keys.  These shifter keys are usually:
+*   Shift  (left and/or right Shift key)
+*   Ctrl   (left and/or right Ctrl key)
+*   Alt    (left and/or right Alt key)
+*   AltGr  (right Alt key only)
+*
+* NOTE:
+*   All keyboards use the Shift key.
+*   All keyboards use a Ctrl key to generate ASCII control characters.
+*   All keyboards with a number pad use the Alt key and the NumPad to
+*     generate characters by number.
+*   Keyboards using AltGr as a Modifier Key usually translate the Virtual
+*     ScanCode to Virtual Keys VK_CTRL + VK_ALT at input time: the Modifier
+*     tables should be written to treat Ctrl + Alt as a valid shifter
+*     key combination in these cases.
+*
+* By holding down 0 or more of these Modifier keys, a "shift state" is
+* obtained : the shift state may affect the translation of Virtual Scancodes
+* to Virtual Keys and/or the translation of Virtuals Key to Characters.
+*
+* EXAMPLES:
+*
+* Each key on a particular keyboard may be marked with up to five different
+* characters in five different positions:
+*
+*              .-------.
+*             /|       |\
+*            : | 2   4 | :
+*            | |       | |
+*            | |       | |
+*            | | 1   3 | |
+*            | |_______| |
+*            | /       \ |
+*            |/    5    \|
+*            `-----------'
+*
+* A key may also be able to generate a character that is not marked on it:
+* these are ASCII Control chars, lower-case letters and/or "invisible keys".
+*                                                  .-------.
+*      An example of an "Invisible Key":          /|       |\
+*                                                : | >     | :
+*  The German M24 keyboard 2 should produce the  | |       | |
+*  '|' character when ALT SHIFT is is held down  | |       | |
+*  while the '<' key (shown here) is pressed:    | | <   \ | |
+*  This keyboard has four other invisible        | |_______| |
+*  characters.  France, Italy and Spain also     | /       \ |
+*  support invisible characters on the M24       |/         \|
+*  Keyboard 2 with ALT SHIFT depressed.          `-----------'
+*
+* The keyboard table must list the keys that contribute to it's shift state,
+* and indicate which combinations are valid.  This is done with
+*    aCharModifiers[]  - convert combinations of Modifier Keys to Bitmasks.
+* and
+*    aModification[];  - convert Modifier Bitmasks to enumerated Modifications
+*
+* AN EXAMPLE OF VALID AND INVALID MODIFIER KEY COMBINATIONS
+*
+*    The US English keyboard has 3 Modifier keys:
+*      Shift (left or right); Ctrl (left or right); and Alt (left or right).
+*
+*    The only valid combinations of these Modifier Keys are:
+*      none pressed      : Character at position (1) on the key.
+*      Shift             : Character at position (2) on the key.
+*      Ctrl              : Ascii Control characters
+*      Shift + Ctrl      : Ascii Control characters
+*      Alt               : Character-by-number on the numpad
+*
+*    The invalid combinations (that do not generate any characters) are:
+*      Shift + Alt
+*      Alt + Ctrl
+*      Shift + Alt + Ctrl
+*
+* Something (???) :
+* -----------------
+*      Modifier keys              Character produced
+*      -------------------------  ------------------
+*   0  No shifter key depressed   position 1
+*   1  Shift key is depressed     position 2
+*   2  AltGr (r.h. Alt) depressed position 4 or 5 (whichever is marked)
+*
+* However, note that 3 shifter keys (SHIFT, can be combined in a
+* characters, depending on the Keyboards
+* Consider the following keyboards:
+*
+*     .-------.            STRANGE KBD         PECULIAR KBD
+*    /|       |\           ==================  ==================
+*   : | 2   4 | :    1   -
+*   | |       | |    2   - SHIFT               SHIFT
+*   | |       | |    3   - MENU                MENU
+*   | | 1   3 | |    4   - SHIFT + MENU        SHIFT + MENU
+*   | |_______| |    5   -    no such keys     CTRL  + MENU
+*   | /       \ |
+*   |/    5    \|
+*   `-----------'
+* Both STRANGE and PECULIAR keyboards could have aVkToBits[] =
+*   { VK_SHIFT  , KBDSHIFT }, // 0x01
+*   { VK_CONTROL, KBDCTRL  }, // 0x02
+*   { VK_MENU   , KBDALT   }, // 0x04
+*   { 0,          0        }
+*
+* The STRANGE keyboard has 4 distinct shift states, while the PECULIAR kbd
+* has 5.  However, note that 3 shifter bits can be combined in a
+* total of 2^3 == 8 ways.  Each such combination must be related to one (or
+* none) of the enumerated shift states.
+* Each shifter key combination can be represented by three binary bits:
+*  Bit 0  is set if VK_SHIFT is down
+*  Bit 1  is set if VK_CONTROL is down
+*  Bit 2  is set if VK_MENU is down
+*
+* Example: If the STRANGE keyboard generates no characters in combination
+* when just the ALT key is held down, nor when the SHIFT, CTRL and ALT keys
+* are all held down, then the tables might look like this:
+*
+*                                VK_MENU,
+*                        VK_CTRL,                    0
+*    };
+*    aModification[] = {
+*        0,            //   0       0       0     = 000  <none>
+*        1,            //   0       0       1     = 001  SHIFT
+*        SHFT_INVALID, //   0       1       0     = 010  ALT
+*        2,            //   0       1       1     = 011  SHIFT ALT
+*        3,            //   1       0       0     = 100  CTRL
+*        4,            //   1       0       1     = 101  SHIFT CTRL
+*        5,            //   1       1       0     = 110  CTRL ALT
+*        SHFT_INVALID  //   1       1       1     = 111  SHIFT CTRL ALT
+*    };
+*
+*
+\***************************************************************************/
+
+/***************************************************************************\
+* VK_TO_BIT - associate a Virtual Key with a Modifier bitmask.
+*
+* Vk        - the Virtual key (eg: VK_SHIFT, VK_RMENU, VK_CONTROL etc.)
+*             Special Values:
+*                0        null terminator
+* ModBits   - a combination of KBDALT, KBDCTRL, KBDSHIFT and kbd-specific bits
+*             Any kbd-specific shift bits must be the lowest-order bits other
+*             than KBDSHIFT, KBDCTRL and KBDALT (0, 1 & 2)
+*
+* Those languages that use AltGr (VK_RMENU) to shift keys convert it to
+* CTRL+ALT with the KBDSPECIAL bit in the ausVK[] entry for VK_RMENU
+* and by having an entry in aVkToPfnOem[] to simulate the right Vk sequence.
+*
+\***************************************************************************/
+typedef struct {
+    BYTE Vk;
+    BYTE ModBits;
+} VK_TO_BIT, *KBD_LONG_POINTER PVK_TO_BIT;
+
+/***************************************************************************\
+* pModNumber  - a table to map shift bits to enumerated shift states
+*
+* Table attributes: Ordered table
+*
+* Maps all possible shifter key combinations to an enumerated shift state.
+* The size of the table depends on the value of the highest order bit used
+* in aCharModifiers[*].ModBits
+*
+* Special values for aModification[*]
+*   SHFT_INVALID - no characters produced with this shift state.
+LATER: (ianja) no SHFT_CTRL - control characters encoded in tables like others
+*   SHFT_CTRL    - standard control character production (all keyboards must
+*                  be able to produce CTRL-C == 0x0003 etc.)
+*   Other        - enumerated shift state (not less than 0)
+*
+* This table is indexed by the Modifier Bits to obtain an Modification Number.
+*
+*                        CONTROL MENU SHIFT
+*
+*    aModification[] = {
+*        0,            //   0     0     0     = 000  <none>
+*        1,            //   0     0     1     = 001  SHIFT
+*        SHFT_INVALID, //   0     1     0     = 010  ALT
+*        2,            //   0     1     1     = 011  SHIFT ALT
+*        3,            //   1     0     0     = 100  CTRL
+*        4,            //   1     0     1     = 101  SHIFT CTRL
+*        5,            //   1     1     0     = 110  CTRL ALT
+*        SHFT_INVALID  //   1     1     1     = 111  SHIFT CTRL ALT
+*    };
+*
+\***************************************************************************/
+
+#pragma warning(push)
+#pragma warning(disable : 4200) // zero-sized array in struct/union
+
+typedef struct {
+    PVK_TO_BIT pVkToBit;     // Virtual Keys -> Mod bits
+    WORD       wMaxModBits;  // max Modification bit combination value
+    BYTE       ModNumber[];  // Mod bits -> Modification Number
+} MODIFIERS, *KBD_LONG_POINTER PMODIFIERS;
+
+#pragma warning(pop)
+
+
+#define SHFT_INVALID 0x0F
+
+/***************************************************************************\
+* VSC_VK     - Associate a Virtual Scancode with a Virtual Key
+*  Vsc - Virtual Scancode
+*  Vk  - Virtual Key | flags
+* Used by VKFromVSC() for scancodes prefixed 0xE0 or 0xE1
+\***************************************************************************/
+typedef struct _VSC_VK {
+    BYTE Vsc;
+    USHORT Vk;
+} VSC_VK, *KBD_LONG_POINTER PVSC_VK;
+
+/***************************************************************************\
+* VK_VSC     - Associate a Virtual Key with a Virtual Scancode
+*  Vk  - Virtual Key
+*  Vsc - Virtual Scancode
+* Used by MapVirtualKey for Virtual Keys not appearing in ausVK[]
+\***************************************************************************/
+typedef struct _VK_VSC {
+    BYTE Vk;
+    BYTE Vsc;
+} VK_VSC, *KBD_LONG_POINTER PVK_VSC;
+
+/***************************************************************************\
+*
+* VK_TO_WCHARS<n> - Associate a Virtual Key with <n> UNICODE characters
+*
+* VirtualKey  - The Virtual Key.
+* wch[]       - An array of characters, one for each shift state that
+*               applies to the specified Virtual Key.
+*
+* Special values for VirtualKey:
+*    -1        - This entry contains dead chars for the previous entry
+*    0         - Terminates a VK_TO_WCHARS[] table
+*
+* Special values for Attributes:
+*    CAPLOK    - The CAPS-LOCK key affects this key like SHIFT
+*    SGCAPS    - CapsLock uppercases the unshifted char (Swiss-German)
+*
+* Special values for wch[*]:
+*    WCH_NONE  - No character is generated by pressing this key with the
+*                current shift state.
+*    WCH_DEAD  - The character is a dead-key: the next VK_TO_WCHARS[] entry
+*                will contain the values of the dead characters (diaresis)
+*                that can be produced by the Virtual Key.
+*    WCH_LGTR  - The character is a ligature.  The characters generated by
+*                this keystroke are found in the ligature table.
+*
+\***************************************************************************/
+#define WCH_NONE 0xF000
+#define WCH_DEAD 0xF001
+#define WCH_LGTR 0xF002
+
+#define CAPLOK      0x01
+#define SGCAPS      0x02
+#define CAPLOKALTGR 0x04
+// KANALOK is for FE
+#define KANALOK     0x08
+#define GRPSELTAP   0x80
+
+/*
+ * Macro for VK to WCHAR with "n" shift states
+ */
+#define TYPEDEF_VK_TO_WCHARS(n) typedef struct _VK_TO_WCHARS##n {  \
+                                    BYTE  VirtualKey;      \
+                                    BYTE  Attributes;      \
+                                    WCHAR wch[n];          \
+                                } VK_TO_WCHARS##n, *KBD_LONG_POINTER PVK_TO_WCHARS##n;
+
+/*
+ * To facilitate coding the table scanning routine.
+ */
+
+/*
+ * Table element types (for various numbers of shift states), used
+ * to facilitate static initializations of tables.
+ * VK_TO_WCHARS1 and PVK_TO_WCHARS1 may be used as the generic type
+ */
+TYPEDEF_VK_TO_WCHARS(1) // VK_TO_WCHARS1, *PVK_TO_WCHARS1;
+TYPEDEF_VK_TO_WCHARS(2) // VK_TO_WCHARS2, *PVK_TO_WCHARS2;
+TYPEDEF_VK_TO_WCHARS(3) // VK_TO_WCHARS3, *PVK_TO_WCHARS3;
+TYPEDEF_VK_TO_WCHARS(4) // VK_TO_WCHARS4, *PVK_TO_WCHARS4;
+TYPEDEF_VK_TO_WCHARS(5) // VK_TO_WCHARS5, *PVK_TO_WCHARS5;
+TYPEDEF_VK_TO_WCHARS(6) // VK_TO_WCHARS6, *PVK_TO_WCHARS5;
+TYPEDEF_VK_TO_WCHARS(7) // VK_TO_WCHARS7, *PVK_TO_WCHARS7;
+// these three (8,9,10) are for FE
+TYPEDEF_VK_TO_WCHARS(8) // VK_TO_WCHARS8, *PVK_TO_WCHARS8;
+TYPEDEF_VK_TO_WCHARS(9) // VK_TO_WCHARS9, *PVK_TO_WCHARS9;
+TYPEDEF_VK_TO_WCHARS(10) // VK_TO_WCHARS10, *PVK_TO_WCHARS10;
+
+/***************************************************************************\
+*
+* VK_TO_WCHAR_TABLE - Describe a table of VK_TO_WCHARS1
+*
+* pVkToWchars     - points to the table.
+* nModifications  - the number of shift-states supported by this table.
+*                   (this is the number of elements in pVkToWchars[*].wch[])
+*
+* A keyboard may have several such tables: all keys with the same number of
+*    shift-states are grouped together in one table.
+*
+* Special values for pVktoWchars:
+*     NULL     - Terminates a VK_TO_WCHAR_TABLE[] list.
+*
+\***************************************************************************/
+
+typedef struct _VK_TO_WCHAR_TABLE {
+    PVK_TO_WCHARS1 pVkToWchars;
+    BYTE           nModifications;
+    BYTE           cbSize;
+} VK_TO_WCHAR_TABLE, *KBD_LONG_POINTER PVK_TO_WCHAR_TABLE;
+
+/***************************************************************************\
+*
+* Dead Key (diaresis) tables
+*
+\***************************************************************************/
+typedef struct {
+    DWORD  dwBoth;  // diacritic & char
+    WCHAR  wchComposed;
+    USHORT uFlags;
+} DEADKEY, *KBD_LONG_POINTER PDEADKEY;
+
+#define DEADTRANS(ch, accent, comp, flags) { MAKELONG(ch, accent), comp, flags}
+
+/*
+ * Bit values for uFlags
+ */
+#define DKF_DEAD  0x0001
+
+/***************************************************************************\
+*
+* Ligature table
+*
+\***************************************************************************/
+/*
+ * Macro for ligature with "n" characters
+ */
+#define TYPEDEF_LIGATURE(n) typedef struct _LIGATURE##n {     \
+                                    BYTE  VirtualKey;         \
+                                    WORD  ModificationNumber; \
+                                    WCHAR wch[n];             \
+                                } LIGATURE##n, *KBD_LONG_POINTER PLIGATURE##n;
+
+/*
+ * To facilitate coding the table scanning routine.
+ */
+
+/*
+ * Table element types (for various numbers of ligatures), used
+ * to facilitate static initializations of tables.
+ *
+ * LIGATURE1 and PLIGATURE1 are used as the generic type
+ */
+TYPEDEF_LIGATURE(1) // LIGATURE1, *PLIGATURE1;
+TYPEDEF_LIGATURE(2) // LIGATURE2, *PLIGATURE2;
+TYPEDEF_LIGATURE(3) // LIGATURE3, *PLIGATURE3;
+TYPEDEF_LIGATURE(4) // LIGATURE4, *PLIGATURE4;
+TYPEDEF_LIGATURE(5) // LIGATURE5, *PLIGATURE5;
+
+/***************************************************************************\
+* VSC_LPWSTR - associate a Virtual Scancode with a Text string
+*
+* Uses:
+*   GetKeyNameText(), aKeyNames[]  Map virtual scancode to name of key
+*
+\***************************************************************************/
+typedef struct {
+    BYTE   vsc;
+    WCHAR *KBD_LONG_POINTER pwsz;
+} VSC_LPWSTR, *KBD_LONG_POINTER PVSC_LPWSTR;
+
+typedef WCHAR *KBD_LONG_POINTER DEADKEY_LPWSTR;
+
+/*
+ * Along with ligature support we're adding a proper version number.
+ * The previous version number (actually just unused bits...) was
+ * always zero.  The version number will live in the high word of
+ * fLocaleFlags.
+ */
+#define KBD_VERSION         1
+#define GET_KBD_VERSION(p)  (HIWORD((p)->fLocaleFlags))
+
+/*
+ * Attributes such as AltGr, LRM_RLM, ShiftLock are stored in the the low word
+ * of fLocaleFlags (layout specific) or in gdwKeyboardAttributes (all layouts)
+ */
+#define KLLF_ALTGR       0x0001
+#define KLLF_SHIFTLOCK   0x0002
+#define KLLF_LRM_RLM     0x0004
+
+/*
+ * Some attributes are per-layout (specific to an individual layout), some
+ * attributes are per-user (apply globally to all layouts).  Some are both.
+ */
+#define KLLF_LAYOUT_ATTRS (KLLF_SHIFTLOCK | KLLF_ALTGR | KLLF_LRM_RLM)
+#define KLLF_GLOBAL_ATTRS (KLLF_SHIFTLOCK)
+
+/*
+ * Flags passed in to the KeyboardLayout API (KLF_*) as can be converted to
+ * internal (KLLF_*) attributes:
+ */
+#define KLL_ATTR_FROM_KLF(x)         ((x) >> 15)
+#define KLL_LAYOUT_ATTR_FROM_KLF(x)  (KLL_ATTR_FROM_KLF(x) & KLLF_LAYOUT_ATTRS)
+#define KLL_GLOBAL_ATTR_FROM_KLF(x)  (KLL_ATTR_FROM_KLF(x) & KLLF_GLOBAL_ATTRS)
+
+/*
+ * If KLF_SHIFTLOCK & KLF_LRM_RLM are defined, we can check the KLLF_* values
+ */
+#ifdef KLF_SHIFTLOCK
+#if KLLF_SHIFTLOCK != KLL_ATTR_FROM_KLF(KLF_SHIFTLOCK)
+    #error KLLF_SHIFTLOCK != KLL_ATTR_FROM_KLF(KLF_SHIFTLOCK)
+#endif
+#endif // KLF_SHIFTLOCK
+#ifdef KLF_LRM_RLM
+#if KLLF_LRM_RLM != KLL_ATTR_FROM_KLF(KLF_LRM_RLM)
+    #error KLLF_LRM_RLM != KLL_ATTR_FROM_KLF(KLF_LRM_RLM)
+#endif
+#endif // KLF_LRM_RLM
+
+/***************************************************************************\
+* KBDTABLES
+*
+* This structure describes all the tables that implement the keyboard layer.
+*
+* When switching to a new layer, we get a new KBDTABLES structure: all key
+* processing tables are accessed indirectly through this structure.
+*
+\***************************************************************************/
+
+typedef struct tagKbdLayer {
+    /*
+     * Modifier keys
+     */
+    PMODIFIERS pCharModifiers;
+
+    /*
+     * Characters
+     */
+    PVK_TO_WCHAR_TABLE pVkToWcharTable;  // ptr to tbl of ptrs to tbl
+
+    /*
+     * Diacritics
+     */
+    PDEADKEY pDeadKey;
+
+    /*
+     * Names of Keys
+     */
+    PVSC_LPWSTR pKeyNames;
+    PVSC_LPWSTR pKeyNamesExt;
+    WCHAR *KBD_LONG_POINTER *KBD_LONG_POINTER pKeyNamesDead;
+
+    /*
+     * Scan codes to Virtual Keys
+     */
+    USHORT  *KBD_LONG_POINTER pusVSCtoVK;
+    BYTE    bMaxVSCtoVK;
+    PVSC_VK pVSCtoVK_E0;  // Scancode has E0 prefix
+    PVSC_VK pVSCtoVK_E1;  // Scancode has E1 prefix
+
+    /*
+     * Locale-specific special processing
+     */
+    DWORD fLocaleFlags;
+
+    /*
+     * Ligatures
+     */
+    BYTE       nLgMax;
+    BYTE       cbLgEntry;
+    PLIGATURE1 pLigature;
+
+#if (NTDDI_VERSION >= NTDDI_WINXP)
+
+    /*
+     * Type and subtype. These are optional.
+     */
+    DWORD      dwType;     // Keyboard Type
+    DWORD      dwSubType;  // Keyboard SubType: may contain OemId
+
+#endif
+
+} KBDTABLES, *KBD_LONG_POINTER PKBDTABLES;
+
+/*
+ * FarEast-specific special...
+ */
+typedef struct _VK_FUNCTION_PARAM {
+    BYTE  NLSFEProcIndex;
+    ULONG NLSFEProcParam;
+} VK_FPARAM, *KBD_LONG_POINTER PVK_FPARAM;
+
+typedef struct _VK_TO_FUNCTION_TABLE {
+    BYTE Vk;
+    BYTE NLSFEProcType;
+    BYTE NLSFEProcCurrent;
+    // Index[0] : Base
+    // Index[1] : Shift
+    // Index[2] : Control
+    // Index[3] : Shift+Control
+    // Index[4] : Alt
+    // Index[5] : Shift+Alt
+    // Index[6] : Control+Alt
+    // Index[7] : Shift+Control+Alt
+    BYTE NLSFEProcSwitch;   // 8 bits
+    VK_FPARAM NLSFEProc[8];
+    VK_FPARAM NLSFEProcAlt[8];
+} VK_F, *KBD_LONG_POINTER PVK_F;
+
+typedef struct tagKbdNlsLayer {
+    USHORT OEMIdentifier;
+    USHORT LayoutInformation;
+    UINT  NumOfVkToF;
+    PVK_F pVkToF;
+    //
+    // The pusMouseVKey array provides a translation from the virtual key
+    // value to an index.  The index is used to select the appropriate
+    // routine to process the virtual key, as well as to select extra
+    // information that is used by this routine during its processing.
+    // If this value is NULL, following default will be used.
+    //
+    // ausMouseVKey[] = {
+    //     VK_CLEAR,           // Numpad 5: Click active button
+    //     VK_PRIOR,           // Numpad 9: Up & Right
+    //     VK_NEXT,            // Numpad 3: Down & Right
+    //     VK_END,             // Numpad 1: Down & Left
+    //     VK_HOME,            // Numpad 7: Up & Left
+    //     VK_LEFT,            // Numpad 4: Left
+    //     VK_UP,              // Numpad 8: Up
+    //     VK_RIGHT,           // Numpad 6: Right
+    //     VK_DOWN,            // Numpad 2: Down
+    //     VK_INSERT,          // Numpad 0: Active button down
+    //     VK_DELETE,          // Numpad .: Active button up
+    //     VK_MULTIPLY,        // Numpad *: Select both buttons
+    //     VK_ADD,             // Numpad +: Double click active button
+    //     VK_SUBTRACT,        // Numpad -: Select right button
+    //     VK_DEVIDE|KBDEXT,   // Numpad /: Select left button
+    //     VK_NUMLOCK|KBDEXT}; // Num Lock
+    //
+    INT     NumOfMouseVKey;
+    USHORT *KBD_LONG_POINTER pusMouseVKey;
+} KBDNLSTABLES, *KBD_LONG_POINTER PKBDNLSTABLES;
+
+#if (NTDDI_VERSION >= NTDDI_WINXP)
+/*
+ * The maximum number of layout tables in a DLL
+ */
+#define KBDTABLE_MULTI_MAX  (8)
+
+/*
+ * Multiple keyboard layout table in a DLL
+ */
+typedef struct tagKBDTABLE_DESC {
+    WCHAR wszDllName[32];
+    DWORD dwType;     // Keyboard type ID
+    DWORD dwSubType;  // Combined SubType ID (OEMID : SubType)
+} KBDTABLE_DESC, *KBD_LONG_POINTER PKBDTABLE_DESC;
+
+typedef struct tagKBDTABLE_MULTI {
+    UINT nTables;
+    KBDTABLE_DESC aKbdTables[KBDTABLE_MULTI_MAX];
+} KBDTABLE_MULTI, *KBD_LONG_POINTER PKBDTABLE_MULTI;
+
+
+/*
+ * Format of the registry value for the Dynamic Layout Switching
+ */
+typedef struct tagKBD_TYPE_INFO {
+    DWORD dwVersion;
+    DWORD dwType;
+    DWORD dwSubType;
+} KBD_TYPE_INFO, *PKBD_TYPE_INFO;
+
+//
+// Keyboard type
+//
+#define KEYBOARD_TYPE_GENERIC_101   (4)
+//
+// Keyboard Type = 7 : Japanese Keyboard
+// Keyboard Type = 8 : Korean Keyboard
+//
+#define KEYBOARD_TYPE_JAPAN (7)
+#define KEYBOARD_TYPE_KOREA (8)
+
+// Unknown keyboard type
+#define KEYBOARD_TYPE_UNKNOWN   (0x51)
+
+#endif
+
+
+//
+// OEM Ids - KBDNLSTABLES.OEMIdentifier
+//
+// PSS ID Number: Q130054
+// Article last modified on 05-16-1995
+//
+// 3.10 1.20 | 3.50 1.20
+// WINDOWS   | WINDOWS NT
+//
+// ---------------------------------------------------------------------
+// The information in this article applies to:
+// - Microsoft Windows Software Development Kit (SDK) for Windows
+//   version 3.1
+// - Microsoft Win32 Software Development Kit (SDK) version 3.5
+// - Microsoft Win32s version 1.2
+// ---------------------------------------------------------------------
+// SUMMARY
+// =======
+// Because of the variety of computer manufacturers (NEC, Fujitsu, IBMJ, and
+// so on) in Japan, sometimes Windows-based applications need to know which
+// OEM (original equipment manufacturer) manufactured the computer that is
+// running the application. This article explains how.
+//
+// MORE INFORMATION
+// ================
+// There is no documented way to detect the manufacturer of the computer that
+// is currently running an application. However, a Windows-based application
+// can detect the type of OEM Windows by using the return value of the
+// GetKeyboardType() function.
+//
+// If an application uses the GetKeyboardType API, it can get OEM ID by
+// specifying "1" (keyboard subtype) as argument of the function. Each OEM ID
+// is listed here:
+//
+// OEM Windows       OEM ID
+// ------------------------------
+// Microsoft         00H (DOS/V)
+// all AX            01H
+// EPSON             04H
+// Fujitsu           05H
+// IBMJ              07H
+// Matsushita        0AH
+// NEC               0DH
+// Toshiba           12H
+//
+// Application programs can use these OEM IDs to distinguish the type of OEM
+// Windows. Note, however, that this method is not documented, so Microsoft
+// may not support it in the future version of Windows.
+//
+// As a rule, application developers should write hardware-independent code,
+// especially when making Windows-based applications. If they need to make a
+// hardware-dependent application, they must prepare the separated program
+// file for each different hardware architecture.
+//
+// Additional reference words: 3.10 1.20 3.50 1.20 kbinf
+// KBCategory: kbhw
+// KBSubcategory: wintldev
+// =============================================================================
+// Copyright (c) Microsoft Corporation. All rights reserved.
+//
+#define NLSKBD_OEM_MICROSOFT          0x00
+#define NLSKBD_OEM_AX                 0x01
+#define NLSKBD_OEM_EPSON              0x04
+#define NLSKBD_OEM_FUJITSU            0x05
+#define NLSKBD_OEM_IBM                0x07
+#define NLSKBD_OEM_MATSUSHITA         0x0A
+#define NLSKBD_OEM_NEC                0x0D
+#define NLSKBD_OEM_TOSHIBA            0x12
+#define NLSKBD_OEM_DEC                0x18 // only NT
+//
+// Microsoft (default) - keyboards hardware/layout
+//
+#define MICROSOFT_KBD_101_TYPE           0
+#define MICROSOFT_KBD_AX_TYPE            1
+#define MICROSOFT_KBD_106_TYPE           2
+#define MICROSOFT_KBD_002_TYPE           3
+#define MICROSOFT_KBD_001_TYPE           4
+#define MICROSOFT_KBD_FUNC              12
+//
+// AX consortium - keyboards hardware/layout
+//
+#define AX_KBD_DESKTOP_TYPE              1
+//
+// Fujitsu - keyboards hardware/layout
+//
+#define FMR_KBD_JIS_TYPE                 0
+#define FMR_KBD_OASYS_TYPE               1
+#define FMV_KBD_OASYS_TYPE               2
+//
+// NEC - keyboards hardware/layout
+//
+#define NEC_KBD_NORMAL_TYPE              1
+#define NEC_KBD_N_MODE_TYPE              2
+#define NEC_KBD_H_MODE_TYPE              3
+#define NEC_KBD_LAPTOP_TYPE              4
+#define NEC_KBD_106_TYPE                 5
+//
+// Toshiba - keyboards hardware/layout
+//
+#define TOSHIBA_KBD_DESKTOP_TYPE        13
+#define TOSHIBA_KBD_LAPTOP_TYPE         15
+//
+// DEC - keyboards hardware/layout
+//
+#define DEC_KBD_ANSI_LAYOUT_TYPE         1 // only NT
+#define DEC_KBD_JIS_LAYOUT_TYPE          2 // only NT
+
+#if (NTDDI_VERSION >= NTDDI_WINXP)
+//
+// Korean keyboard subtype
+//
+#define MICROSOFT_KBD_101A_TYPE         MICROSOFT_KBD_101_TYPE
+#define MICROSOFT_KBD_101B_TYPE         4
+#define MICROSOFT_KBD_101C_TYPE         5
+#define MICROSOFT_KBD_103_TYPE          6
+#endif
+
+//
+// Keyboard layout information - KBDNLSTABLE.LayoutInformation
+//
+
+//
+// If this flag is on, System sends notification to keyboard
+// drivers (leyout/kernel mode). when IME (Input-Mehod-Editor)
+// status become changed.
+//
+#define NLSKBD_INFO_SEND_IME_NOTIFICATION  0x0001
+
+//
+// If this flag is on, System will use VK_HOME/VK_KANA instead of
+// VK_NUMLOCK/VK_SCROLL for Accessibility toggle keys.
+// + Typically, NEC PC-9800 Series will use this bit, because
+//   they does not have 'NumLock' and 'ScrollLock' keys.
+//
+#define NLSKBD_INFO_ACCESSIBILITY_KEYMAP   0x0002
+
+//
+// If this flag is on, System will return 101 or 106 Japanese
+// keyboard type/subtype id, when GetKeyboardType() is called.
+//
+#define NLSKBD_INFO_EMURATE_101_KEYBOARD   0x0010
+#define NLSKBD_INFO_EMURATE_106_KEYBOARD   0x0020
+
+//
+// Keyboard layout function types
+//
+// - VK_F.NLSFEProcType
+//
+#define KBDNLS_TYPE_NULL      0
+#define KBDNLS_TYPE_NORMAL    1
+#define KBDNLS_TYPE_TOGGLE    2
+
+//
+// - VK_F.NLSFEProcCurrent
+//
+#define KBDNLS_INDEX_NORMAL   1
+#define KBDNLS_INDEX_ALT      2
+
+//
+// - VK_F.NLSFEProc[]
+//
+#define KBDNLS_NULL             0 // Invalid function
+#define KBDNLS_NOEVENT          1 // Drop keyevent
+#define KBDNLS_SEND_BASE_VK     2 // Send Base VK_xxx
+#define KBDNLS_SEND_PARAM_VK    3 // Send Parameter VK_xxx
+#define KBDNLS_KANALOCK         4 // VK_KANA (with hardware lock)
+#define KBDNLS_ALPHANUM         5 // VK_DBE_ALPHANUMERIC
+#define KBDNLS_HIRAGANA         6 // VK_DBE_HIRAGANA
+#define KBDNLS_KATAKANA         7 // VK_DBE_KATAKANA
+#define KBDNLS_SBCSDBCS         8 // VK_DBE_SBCSCHAR/VK_DBE_DBCSCHAR
+#define KBDNLS_ROMAN            9 // VK_DBE_ROMAN/VK_DBE_NOROMAN
+#define KBDNLS_CODEINPUT       10 // VK_DBE_CODEINPUT/VK_DBE_NOCODEINPUT
+#define KBDNLS_HELP_OR_END     11 // VK_HELP or VK_END [NEC PC-9800 Only]
+#define KBDNLS_HOME_OR_CLEAR   12 // VK_HOME or VK_CLEAR [NEC PC-9800 Only]
+#define KBDNLS_NUMPAD          13 // VK_NUMPAD? for Numpad key [NEC PC-9800 Only]
+#define KBDNLS_KANAEVENT       14 // VK_KANA [Fujitsu FMV oyayubi Only]
+#define KBDNLS_CONV_OR_NONCONV 15 // VK_CONVERT and VK_NONCONVERT [Fujitsu FMV oyayubi Only]
+
+#if (NTDDI_VERSION < NTDDI_WINXP)
+//
+// Keyboard Type = 7 : Japanese Keyboard
+// Keyboard Type = 8 : Korean Keyboard
+//
+#define JAPANESE_KEYBOARD(Id)  ((Id).Type == 7)
+#define KOREAN_KEYBOARD(Id)    ((Id).Type == 8)
+
+#else
+
+#define JAPANESE_KEYBOARD(Id)  ((Id).Type == KEYBOARD_TYPE_JAPAN)
+#define KOREAN_KEYBOARD(Id)    ((Id).Type == KEYBOARD_TYPE_KOREA)
+
+#endif
+
+// Fujitsu Oyayubi-shift keyboard
+#define FUJITSU_KBD_CONSOLE(Id)  (JAPANESE_KEYBOARD(Id) && \
+                                  (Id).Subtype == ((NLSKBD_OEM_FUJITSU<<4)|FMV_KBD_OASYS_TYPE))
+        // This number 0x00020002 is registered in registry key as
+        // HKLM\System\CurrentControlSet\Control\Terminal Server\KeyboardType Mapping\JPN
+#define FUJITSU_KBD_REMOTE(Id)   (JAPANESE_KEYBOARD(Id) && \
+                                  (Id).SubType == 0x00020002)
+
+#define KBD_LAYOUT_LANG(hkl)    (PRIMARYLANGID(HandleToUlong(hkl)))
+
+#define JAPANESE_KBD_LAYOUT(hkl)    (KBD_LAYOUT_LANG(hkl) == LANG_JAPANESE)
+#define KOREAN_KBD_LAYOUT(hkl)      (KBD_LAYOUT_LANG(hkl) == LANG_KOREAN)
+
+// end of FE specific
+
+/***************************************************************************\
+* Macros for ausVK[] values (used below)
+*
+* These macros prefix each argument with VK_ to produce the name of a Virtual
+* Key defined in "winuser.h" (eg: ESCAPE becomes VK_ESCAPE).
+\***************************************************************************/
+#ifndef KBD_TYPE
+#define KBD_TYPE 4
+#endif
+
+/*
+ * _NE() selects the Virtual Key according to keyboard type
+ */
+#if   (KBD_TYPE == 1)
+#define _NE(v1,v2,v3,v4,v5,v6) (VK_##v1)
+#elif (KBD_TYPE == 2)
+#define _NE(v1,v2,v3,v4,v5,v6) (VK_##v2)
+#elif (KBD_TYPE == 3)
+#define _NE(v1,v2,v3,v4,v5,v6) (VK_##v3)
+#elif (KBD_TYPE == 4)
+#define _NE(v1,v2,v3,v4,v5,v6) (VK_##v4)
+#elif (KBD_TYPE == 5)
+#define _NE(v1,v2,v3,v4,v5,v6) (VK_##v5)
+#elif (KBD_TYPE == 6)
+#define _NE(v1,v2,v3,v4,v5,v6) (VK_##v6)
+#elif (KBD_TYPE == 7)
+#define _NE(v7,v8,v16,v10,v11,v12,v13) (VK_##v7)
+#elif (KBD_TYPE == 8)
+#define _NE(v7,v8,v16,v10,v11,v12,v13) (VK_##v8)
+#elif (KBD_TYPE == 10)
+#define _NE(v7,v8,v16,v10,v11,v12,v13) (VK_##v10)
+#elif (KBD_TYPE == 11)
+#define _NE(v7,v8,v16,v10,v11,v12,v13) (VK_##v11)
+#elif (KBD_TYPE == 12)
+#define _NE(v7,v8,v16,v10,v11,v12,v13) (VK_##v12)
+#elif (KBD_TYPE == 13)
+#define _NE(v7,v8,v16,v10,v11,v12,v13) (VK_##v13)
+#elif (KBD_TYPE == 16)
+#define _NE(v7,v8,v16,v10,v11,v12,v13) (VK_##v16)
+#elif (KBD_TYPE == 20)
+#define _NE(v20,v21,v22)           (VK_##v20)
+#elif (KBD_TYPE == 21)
+#define _NE(v20,v21,v22)           (VK_##v21)
+#elif (KBD_TYPE == 22)
+#define _NE(v20,v21,v22)           (VK_##v22)
+#elif (KBD_TYPE == 30)
+#define _NE(v30,v33,v34)           (VK_##v30)
+#elif (KBD_TYPE == 33)
+#define _NE(v30,v33,v34)           (VK_##v33)
+#elif (KBD_TYPE == 34)
+#define _NE(v30,v33,v34)           (VK_##v34)
+#elif (KBD_TYPE == 40)
+#define _NE(v40,v41)               (VK_##v40)
+#elif (KBD_TYPE == 41)
+#define _NE(v40,v41)               (VK_##v41)
+#endif
+
+/*
+ * _EQ() selects the same Virtual Key for all keyboard types
+ */
+#if   (KBD_TYPE <= 6)
+#define _EQ(         v4      ) (VK_##v4)
+#elif (KBD_TYPE >= 7) && (KBD_TYPE <= 16)
+#define _EQ(   v8            ) (VK_##v8)
+#elif (KBD_TYPE > 20) && (KBD_TYPE <= 22)
+#define _EQ(v20              ) (VK_##v20)
+#elif (KBD_TYPE >= 30) && (KBD_TYPE <= 34)
+#define _EQ(         v30     ) (VK_##v30)
+#elif (KBD_TYPE == 37)
+#define _EQ(         v37     ) (VK_##v37)
+#elif (KBD_TYPE >= 40) && (KBD_TYPE <= 41)
+#define _EQ( v40             ) (VK_##v40)
+#endif
+
+/*
+ * A bit of trickery for virtual key names 'A' to 'Z' and '0' to '9' so
+ * that they are not converted to a VK_* name.
+ * With this macro, VK_'A' equates to 'A' etc.
+ */
+#define VK_
+#define VK__none_   0xFF
+#define VK_ABNT_C1  0xC1
+#define VK_ABNT_C2  0xC2
+
+#if (KBD_TYPE <= 6)
+/***************************************************************************\
+* T** - Values for ausVK[] (Virtual Scan Code to Virtual Key conversion)
+*
+* These values are for Scancode Set 3 and the USA.
+* Other languages substitute their own values where required (files kbd**.h)
+*
+* Six sets of keyboards are supported, according to KBD_TYPE:
+*
+* KBD_TYPE   Keyboard (examples)
+* ========   =======================================================
+*    1       AT&T '301' & '302'; Olivetti 83-key; PC-XT 84-key; etc.
+*    2       Olivetti M24 102-key
+*    3       HP Vectra (DIN); Olivetti 86-key; etc.
+*    4 *     Enhanced 101/102-key; Olivetti A; etc.
+*    5       Nokia (Ericsson) type 5 (1050, etc.)
+*    6       Nokia (Ericsson) type 6 (9140)
+*
+* * If KBD_TYPE is not defined, the default is type 4.
+*
+* KB3270 comments refers to KB 3270 keyboards in native emulation mode (DIP
+* switches all OFF), and the Scancode Map used to convert its scancodes to
+* standard scancode set 1.
+*    KB3270 <= 57      - this entry is reached by mapping from scancode 0x57
+*                        to an arbitrary scancode: the VK is what counts
+*    KB3270 => HOME    - this scancode is mapped to the scancode for VK_HOME
+*    KB3270            - no mapping involved, a scancode for KB3270 only
+*
+* _EQ() : all keyboard types have the same virtual key for this scancode
+* _NE() : different virtual keys for this scancode, depending on kbd type
+*
+*     +------+ +--------+--------+--------+--------+--------+--------+
+*     | Scan | |  kbd   |  kbd   |  kbd   |  kbd   |  kbd   |  kbd   |
+*     | code | | type 1 | type 2 | type 3 | type 4 | type 5 | type 6 |
+\****+-------+-+--------+--------+--------+--------+--------+--------+******/
+#define T00 _EQ(                           _none_                    )
+#define T01 _EQ(                           ESCAPE                    )
+#define T02 _EQ(                           '1'                       )
+#define T03 _EQ(                           '2'                       )
+#define T04 _EQ(                           '3'                       )
+#define T05 _EQ(                           '4'                       )
+#define T06 _EQ(                           '5'                       )
+#define T07 _EQ(                           '6'                       )
+#define T08 _EQ(                           '7'                       )
+#define T09 _EQ(                           '8'                       )
+#define T0A _EQ(                           '9'                       )
+#define T0B _EQ(                           '0'                       )
+#define T0C _EQ(                           OEM_MINUS                 )
+#define T0D _NE(OEM_PLUS,OEM_4,   OEM_PLUS,OEM_PLUS,OEM_PLUS,OEM_PLUS)
+#define T0E _EQ(                           BACK                      )
+#define T0F _EQ(                           TAB                       )
+#define T10 _EQ(                           'Q'                       )
+#define T11 _EQ(                           'W'                       )
+#define T12 _EQ(                           'E'                       )
+#define T13 _EQ(                           'R'                       )
+#define T14 _EQ(                           'T'                       )
+#define T15 _EQ(                           'Y'                       )
+#define T16 _EQ(                           'U'                       )
+#define T17 _EQ(                           'I'                       )
+#define T18 _EQ(                           'O'                       )
+#define T19 _EQ(                           'P'                       )
+#define T1A _NE(OEM_4,   OEM_6,   OEM_4,   OEM_4,   OEM_4,   OEM_4   )
+#define T1B _NE(OEM_6,   OEM_1,   OEM_6,   OEM_6,   OEM_6,   OEM_6   )
+#define T1C _EQ(                           RETURN                    )
+#define T1D _EQ(                           LCONTROL                  )
+#define T1E _EQ(                           'A'                       )
+#define T1F _EQ(                           'S'                       )
+#define T20 _EQ(                           'D'                       )
+#define T21 _EQ(                           'F'                       )
+#define T22 _EQ(                           'G'                       )
+#define T23 _EQ(                           'H'                       )
+#define T24 _EQ(                           'J'                       )
+#define T25 _EQ(                           'K'                       )
+#define T26 _EQ(                           'L'                       )
+#define T27 _NE(OEM_1,   OEM_PLUS,OEM_1,   OEM_1,   OEM_1,   OEM_1   )
+#define T28 _NE(OEM_7,   OEM_3,   OEM_7,   OEM_7,   OEM_3,   OEM_3   )
+#define T29 _NE(OEM_3,   OEM_7,   OEM_3,   OEM_3,   OEM_7,   OEM_7   )
+#define T2A _EQ(                           LSHIFT                    )
+#define T2B _EQ(                           OEM_5                     )
+#define T2C _EQ(                           'Z'                       )
+#define T2D _EQ(                           'X'                       )
+#define T2E _EQ(                           'C'                       )
+#define T2F _EQ(                           'V'                       )
+#define T30 _EQ(                           'B'                       )
+#define T31 _EQ(                           'N'                       )
+#define T32 _EQ(                           'M'                       )
+#define T33 _EQ(                           OEM_COMMA                 )
+#define T34 _EQ(                           OEM_PERIOD                )
+#define T35 _EQ(                           OEM_2                     )
+#define T36 _EQ(                           RSHIFT                    )
+#define T37 _EQ(                           MULTIPLY                  )
+#define T38 _EQ(                           LMENU                     )
+#define T39 _EQ(                           ' '                       )
+#define T3A _EQ(                           CAPITAL                   )
+#define T3B _EQ(                           F1                        )
+#define T3C _EQ(                           F2                        )
+#define T3D _EQ(                           F3                        )
+#define T3E _EQ(                           F4                        )
+#define T3F _EQ(                           F5                        )
+#define T40 _EQ(                           F6                        )
+#define T41 _EQ(                           F7                        )
+#define T42 _EQ(                           F8                        )
+#define T43 _EQ(                           F9                        )
+#define T44 _EQ(                           F10                       )
+#define T45 _EQ(                           NUMLOCK                   )
+#define T46 _EQ(                           SCROLL                    )
+#define T47 _EQ(                           HOME                      )
+#define T48 _EQ(                           UP                        )
+#define T49 _EQ(                           PRIOR                     )
+#define T4A _EQ(                           SUBTRACT                  )
+#define T4B _EQ(                           LEFT                      )
+#define T4C _EQ(                           CLEAR                     )
+#define T4D _EQ(                           RIGHT                     )
+#define T4E _EQ(                           ADD                       )
+#define T4F _EQ(                           END                       )
+#define T50 _EQ(                           DOWN                      )
+#define T51 _EQ(                           NEXT                      )
+#define T52 _EQ(                           INSERT                    )
+#define T53 _EQ(                           DELETE                    )
+#define T54 _EQ(                           SNAPSHOT                  )
+#define T55 _EQ(                           _none_                    ) // KB3270 => DOWN
+#define T56 _NE(OEM_102, HELP,    OEM_102, OEM_102, _none_,  OEM_PA2 ) // KB3270 => LEFT
+#define T57 _NE(F11,     RETURN,  F11,     F11,     _none_,  HELP    ) // KB3270 => ZOOM
+#define T58 _NE(F12,     LEFT,    F12,     F12,     _none_,  OEM_102 ) // KB3270 => HELP
+#define T59 _EQ(                           CLEAR                     )
+#define T5A _EQ(                           OEM_WSCTRL                )// WSCtrl
+#define T5B _EQ(                           OEM_FINISH                )// Finish
+#define T5C _EQ(                           OEM_JUMP                  )// Jump
+#define T5D _EQ(                           EREOF                     )
+#define T5E _EQ(                           OEM_BACKTAB               ) // KB3270 <= 7E
+#define T5F _EQ(                           OEM_AUTO                  ) // KB3270
+#define T60 _EQ(                           _none_                    )
+#define T61 _EQ(                           _none_                    )
+#define T62 _EQ(                           ZOOM                      ) // KB3270 <= 57
+#define T63 _EQ(                           HELP                      ) // KB3270 <= 58
+#define T64 _EQ(                           F13                       )
+#define T65 _EQ(                           F14                       )
+#define T66 _EQ(                           F15                       )
+#define T67 _EQ(                           F16                       )
+#define T68 _EQ(                           F17                       )
+#define T69 _EQ(                           F18                       )
+#define T6A _EQ(                           F19                       )
+#define T6B _EQ(                           F20                       )
+#define T6C _EQ(                           F21                       )
+#define T6D _EQ(                           F22                       )
+#define T6E _EQ(                           F23                       )
+#define T6F _EQ(                           OEM_PA3                   ) // KB3270
+#define T70 _EQ(                           _none_                    )
+#define T71 _EQ(                           OEM_RESET                 ) // KB3270
+#define T72 _EQ(                           _none_                    )
+#define T73 _EQ(                           ABNT_C1                   )
+#define T74 _EQ(                           _none_                    )
+#define T75 _EQ(                           _none_                    ) // KB3270 => RETURN
+#define T76 _EQ(                           F24                       )
+#define T77 _EQ(                           _none_                    ) // KB3270 => HOME
+#define T78 _EQ(                           _none_                    ) // KB3270 => UP
+#define T79 _EQ(                           _none_                    ) // KB3270 => DELETE
+#define T7A _EQ(                           _none_                    ) // KB3270 => INSERT
+#define T7B _EQ(                           OEM_PA1                   ) // KB3270
+#define T7C _EQ(                           TAB                       ) // KB3270 => TAB
+#define T7D _EQ(                           _none_                    ) // KB3270 => RIGHT
+#define T7E _EQ(                           ABNT_C2                   ) // KB3270 => BACKTAB
+#define T7F _EQ(                           OEM_PA2                   ) // KB3270
+
+#define X10 _EQ(                           MEDIA_PREV_TRACK          ) // SpeedRacer
+#define X19 _EQ(                           MEDIA_NEXT_TRACK          ) // SpeedRacer
+#define X1C _EQ(                           RETURN                    )
+#define X1D _EQ(                           RCONTROL                  )
+#define X20 _EQ(                           VOLUME_MUTE               ) // SpeedRacer
+#define X21 _EQ(                           LAUNCH_APP2               ) // SpeedRacer (Calculator?)
+#define X22 _EQ(                           MEDIA_PLAY_PAUSE          ) // SpeedRacer
+#define X24 _EQ(                           MEDIA_STOP                ) // SpeedRacer
+#define X2E _EQ(                           VOLUME_DOWN               ) // SpeedRacer
+#define X30 _EQ(                           VOLUME_UP                 ) // SpeedRacer
+#define X32 _EQ(                           BROWSER_HOME              ) // SpeedRacer
+#define X35 _EQ(                           DIVIDE                    )
+#define X37 _EQ(                           SNAPSHOT                  )
+#define X38 _EQ(                           RMENU                     )
+#define X46 _EQ(                           CANCEL                    )
+#define X47 _EQ(                           HOME                      )
+#define X48 _EQ(                           UP                        )
+#define X49 _EQ(                           PRIOR                     )
+#define X4B _EQ(                           LEFT                      )
+#define X4D _EQ(                           RIGHT                     )
+#define X4F _EQ(                           END                       )
+#define X50 _EQ(                           DOWN                      )
+#define X51 _NE(NEXT,    F1,      NEXT,    NEXT,    _none_, OEM_PA2  )
+#define X52 _EQ(                           INSERT                    )
+#define X53 _EQ(                           DELETE                    )
+#define X5B _EQ(                           LWIN                      )
+#define X5C _EQ(                           RWIN                      )
+#define X5D _EQ(                           APPS                      )
+#define X5E _EQ(                           POWER                     )
+#define X5F _EQ(                           SLEEP                     ) // SpeedRacer
+#define X65 _EQ(                           BROWSER_SEARCH            ) // SpeedRacer
+#define X66 _EQ(                           BROWSER_FAVORITES         ) // SpeedRacer
+#define X67 _EQ(                           BROWSER_REFRESH           ) // SpeedRacer
+#define X68 _EQ(                           BROWSER_STOP              ) // SpeedRacer
+#define X69 _EQ(                           BROWSER_FORWARD           ) // SpeedRacer
+#define X6A _EQ(                           BROWSER_BACK              ) // SpeedRacer
+#define X6B _EQ(                           LAUNCH_APP1               ) // SpeedRacer (my computer?)
+#define X6C _EQ(                           LAUNCH_MAIL               ) // SpeedRacer
+#define X6D _EQ(                           LAUNCH_MEDIA_SELECT       ) // SpeedRacer
+
+
+        /*
+         * The break key is sent to us as E1,LCtrl,NumLock
+         * We must convert the E1+LCtrl to BREAK, then ignore the Numlock
+         */
+#define Y1D _EQ(                           PAUSE                     )
+
+#elif (KBD_TYPE >= 7) && (KBD_TYPE <= 16)
+/***********************************************************************************\
+* T** - Values for ausVK[] (Virtual Scan Code to Virtual Key conversion)
+*
+* Three sets of keyboards are supported, according to KBD_TYPE:
+*
+* KBD_TYPE   Keyboard (examples)
+* ========   =====================================
+*    7       Japanese IBM type 002 keyboard.
+*    8 *     Japanese OADG (106) keyboard.
+*   10       Korean 101 (type A) keyboard.
+*   11       Korean 101 (type B) keyboard.
+*   12       Korean 101 (type C) keyboard.
+*   13       Korean 103 keyboard.
+*   16       Japanese AX keyboard.
+*
+*     +------+ +----------+----------+----------+----------+----------+----------+----------+
+*     | Scan | |   kbd    |   kbd    |   kbd    |   kbd    |   kbd    |   kbd    |   kbd    |
+*     | code | |  type 7  |  type 8  |  type 16 |  type 10 |  type 11 |  type 12 |  type 13 |
+\****+-------+-+----------+----------+----------+----------+----------+----------+----------+*/
+#define T00 _EQ(           _none_                                                           )
+#define T01 _EQ(           ESCAPE                                                           )
+#define T02 _EQ(           '1'                                                              )
+#define T03 _EQ(           '2'                                                              )
+#define T04 _EQ(           '3'                                                              )
+#define T05 _EQ(           '4'                                                              )
+#define T06 _EQ(           '5'                                                              )
+#define T07 _EQ(           '6'                                                              )
+#define T08 _EQ(           '7'                                                              )
+#define T09 _EQ(           '8'                                                              )
+#define T0A _EQ(           '9'                                                              )
+#define T0B _EQ(           '0'                                                              )
+#define T0C _EQ(           OEM_MINUS                                                        )
+#define T0D _NE(OEM_7,     OEM_7,     OEM_PLUS,  OEM_PLUS,  OEM_PLUS,  OEM_PLUS,  OEM_PLUS  )
+#define T0E _EQ(           BACK                                                             )
+#define T0F _EQ(           TAB                                                              )
+#define T10 _EQ(           'Q'                                                              )
+#define T11 _EQ(           'W'                                                              )
+#define T12 _EQ(           'E'                                                              )
+#define T13 _EQ(           'R'                                                              )
+#define T14 _EQ(           'T'                                                              )
+#define T15 _EQ(           'Y'                                                              )
+#define T16 _EQ(           'U'                                                              )
+#define T17 _EQ(           'I'                                                              )
+#define T18 _EQ(           'O'                                                              )
+#define T19 _EQ(           'P'                                                              )
+#define T1A _NE(OEM_4,     OEM_3,     OEM_4,     OEM_4,     OEM_4,     OEM_4,     OEM_4     )
+#define T1B _NE(OEM_6,     OEM_4,     OEM_6,     OEM_6,     OEM_6,     OEM_6,     OEM_6     )
+#define T1C _EQ(           RETURN                                                           )
+#define T1D _EQ(           LCONTROL                                                         )
+#define T1E _EQ(           'A'                                                              )
+#define T1F _EQ(           'S'                                                              )
+#define T20 _EQ(           'D'                                                              )
+#define T21 _EQ(           'F'                                                              )
+#define T22 _EQ(           'G'                                                              )
+#define T23 _EQ(           'H'                                                              )
+#define T24 _EQ(           'J'                                                              )
+#define T25 _EQ(           'K'                                                              )
+#define T26 _EQ(           'L'                                                              )
+#define T27 _NE(OEM_PLUS,  OEM_PLUS,  OEM_1,     OEM_1,     OEM_1,     OEM_1,     OEM_1     )
+#define T28 _NE(OEM_1,     OEM_1,     OEM_7,     OEM_7,     OEM_7,     OEM_7,     OEM_7     )
+#define T29 _NE(OEM_3,     DBE_SBCSCHAR,OEM_3,   OEM_3,     OEM_3,     OEM_3,     OEM_3     )
+#define T2A _EQ(           LSHIFT                                                           )
+#define T2B _NE(OEM_5,     OEM_6,     OEM_5,     OEM_5,     OEM_5,     OEM_5,     OEM_5     )
+#define T2C _EQ(           'Z'                                                              )
+#define T2D _EQ(           'X'                                                              )
+#define T2E _EQ(           'C'                                                              )
+#define T2F _EQ(           'V'                                                              )
+#define T30 _EQ(           'B'                                                              )
+#define T31 _EQ(           'N'                                                              )
+#define T32 _EQ(           'M'                                                              )
+#define T33 _EQ(           OEM_COMMA                                                        )
+#define T34 _EQ(           OEM_PERIOD                                                       )
+#define T35 _EQ(           OEM_2                                                            )
+#define T36 _EQ(           RSHIFT                                                           )
+#define T37 _EQ(           MULTIPLY                                                         )
+#define T38 _EQ(           LMENU                                                            )
+#define T39 _EQ(           ' '                                                              )
+#define T3A _NE(DBE_ALPHANUMERIC,DBE_ALPHANUMERIC,CAPITAL,CAPITAL,CAPITAL,CAPITAL,CAPITAL   )
+#define T3B _EQ(           F1                                                               )
+#define T3C _EQ(           F2                                                               )
+#define T3D _EQ(           F3                                                               )
+#define T3E _EQ(           F4                                                               )
+#define T3F _EQ(           F5                                                               )
+#define T40 _EQ(           F6                                                               )
+#define T41 _EQ(           F7                                                               )
+#define T42 _EQ(           F8                                                               )
+#define T43 _EQ(           F9                                                               )
+#define T44 _EQ(           F10                                                              )
+#define T45 _EQ(           NUMLOCK                                                          )
+#define T46 _EQ(           SCROLL                                                           )
+#define T47 _EQ(           HOME                                                             )
+#define T48 _EQ(           UP                                                               )
+#define T49 _EQ(           PRIOR                                                            )
+#define T4A _EQ(           SUBTRACT                                                         )
+#define T4B _EQ(           LEFT                                                             )
+#define T4C _EQ(           CLEAR                                                            )
+#define T4D _EQ(           RIGHT                                                            )
+#define T4E _EQ(           ADD                                                              )
+#define T4F _EQ(           END                                                              )
+#define T50 _EQ(           DOWN                                                             )
+#define T51 _EQ(           NEXT                                                             )
+#define T52 _EQ(           INSERT                                                           )
+#define T53 _EQ(           DELETE                                                           )
+#define T54 _EQ(           SNAPSHOT                                                         )
+#define T55 _EQ(           _none_                                                           )
+#define T56 _NE(_none_,    _none_,    OEM_102,   OEM_102,   OEM_102,   OEM_102,   OEM_102   )
+#define T57 _EQ(           F11                                                              )
+#define T58 _EQ(           F12                                                              )
+#define T59 _EQ(           CLEAR                                                            )
+#define T5A _NE(NONAME,    NONAME,    NONCONVERT,OEM_WSCTRL,OEM_WSCTRL,OEM_WSCTRL,OEM_WSCTRL)
+#define T5B _NE(NONAME,    NONAME,    CONVERT,   OEM_FINISH,OEM_FINISH,OEM_FINISH,OEM_FINISH)
+#define T5C _NE(NONAME,    NONAME,    OEM_AX,    OEM_JUMP,  OEM_JUMP,  OEM_JUMP,  OEM_JUMP  )
+#define T5D _EQ(           EREOF                                                            )
+#define T5E _NE(_none_,    _none_,    _none_,    OEM_BACKTAB,OEM_BACKTAB,OEM_BACKTAB,OEM_BACKTAB)
+#define T5F _NE(NONAME,    NONAME,    NONAME,    OEM_AUTO,  OEM_AUTO,  OEM_AUTO,  OEM_AUTO  )
+#define T60 _EQ(           _none_                                                           )
+#define T61 _NE(_none_,    _none_,    _none_,    ZOOM,      ZOOM,      ZOOM,      ZOOM      )
+#define T62 _NE(_none_,    _none_,    _none_,    HELP,      HELP,      HELP,      HELP      )
+#define T63 _EQ(           _none_                                                           )
+#define T64 _EQ(           F13                                                              )
+#define T65 _EQ(           F14                                                              )
+#define T66 _EQ(           F15                                                              )
+#define T67 _EQ(           F16                                                              )
+#define T68 _EQ(           F17                                                              )
+#define T69 _EQ(           F18                                                              )
+#define T6A _EQ(           F19                                                              )
+#define T6B _EQ(           F20                                                              )
+#define T6C _EQ(           F21                                                              )
+#define T6D _EQ(           F22                                                              )
+#define T6E _EQ(           F23                                                              )
+#define T6F _NE(_none_,    _none_,    _none_,    OEM_PA3,   OEM_PA3,   OEM_PA3,   OEM_PA3   )
+#define T70 _NE(DBE_KATAKANA,DBE_HIRAGANA,_none_,_none_,    _none_,    _none_,    _none_    )
+#define T71 _NE(_none_,    _none_,    _none_,    OEM_RESET, OEM_RESET, OEM_RESET, OEM_RESET )
+#define T72 _EQ(           _none_                                                           )
+#define T73 _NE(OEM_102,   OEM_102,   _none_,    ABNT_C1,   ABNT_C1,   ABNT_C1,   ABNT_C1   )
+#define T74 _EQ(           _none_                                                           )
+#define T75 _EQ(           _none_                                                           )
+#define T76 _EQ(           F24                                                              )
+#define T77 _NE(DBE_SBCSCHAR,_none_,  _none_,    _none_,    _none_,    _none_,    _none_    )
+#define T78 _EQ(           _none_                                                           )
+#define T79 _NE(CONVERT,   CONVERT,   _none_,    _none_,    _none_,    _none_,    _none_    )
+#define T7A _EQ(           _none_                                                           )
+#define T7B _NE(NONCONVERT,NONCONVERT,_none_,    OEM_PA1,   OEM_PA1,   OEM_PA1,   OEM_PA1   )
+#define T7C _EQ(           TAB                                                              )
+#define T7D _NE(_none_,    OEM_5,     _none_,    _none_,    _none_,    _none_,    _none_    )
+#define T7E _EQ(           ABNT_C2                                                          )
+#define T7F _EQ(           OEM_PA2                                                          )
+
+#define X10 _EQ(           MEDIA_PREV_TRACK                                                 ) // SpeedRacer
+#define X19 _EQ(           MEDIA_NEXT_TRACK                                                 ) // SpeedRacer
+#define X1C _EQ(           RETURN                                                           )
+#define X1D _NE(RCONTROL,  RCONTROL,DBE_KATAKANA,HANJA,     HANGEUL,   RCONTROL,  RCONTROL  )
+#define X20 _EQ(           VOLUME_MUTE                                                      ) // SpeedRacer
+#define X21 _EQ(           LAUNCH_APP2                                                      ) // SpeedRacer
+#define X22 _EQ(           MEDIA_PLAY_PAUSE                                                 ) // SpeedRacer
+#define X24 _EQ(           MEDIA_STOP                                                       ) // SpeedRacer
+#define X2E _EQ(           VOLUME_DOWN                                                      ) // SpeedRacer
+#define X30 _EQ(           VOLUME_UP                                                        ) // SpeedRacer
+#define X32 _EQ(           BROWSER_HOME                                                     ) // SpeedRacer
+#define X33 _NE(OEM_8,     _none_,    _none_,    _none_,    _none_,    _none_,    _none_    )
+#define X35 _EQ(           DIVIDE                                                           )
+#define X37 _EQ(           SNAPSHOT                                                         )
+#define X38 _NE(DBE_HIRAGANA,RMENU,   KANJI,     HANGEUL,   HANJA,     RMENU,     RMENU     )
+#define X42 _EQ(           _none_                                                           )
+#define X43 _EQ(           _none_                                                           )
+#define X44 _EQ(           _none_                                                           )
+#define X46 _EQ(           CANCEL                                                           )
+#define X47 _EQ(           HOME                                                             )
+#define X48 _EQ(           UP                                                               )
+#define X49 _EQ(           PRIOR                                                            )
+#define X4B _EQ(           LEFT                                                             )
+#define X4D _EQ(           RIGHT                                                            )
+#define X4F _EQ(           END                                                              )
+#define X50 _EQ(           DOWN                                                             )
+#define X51 _EQ(           NEXT                                                             )
+#define X52 _EQ(           INSERT                                                           )
+#define X53 _EQ(           DELETE                                                           )
+#define X5B _EQ(           LWIN                                                             )
+#define X5C _EQ(           RWIN                                                             )
+#define X5D _EQ(           APPS                                                             )
+#define X5E _EQ(           POWER                                                            )
+#define X5F _EQ(           SLEEP                                                            )
+#define X65 _EQ(           BROWSER_SEARCH                                                   ) // SpeedRacer
+#define X66 _EQ(           BROWSER_FAVORITES                                                ) // SpeedRacer
+#define X67 _EQ(           BROWSER_REFRESH                                                  ) // SpeedRacer
+#define X68 _EQ(           BROWSER_STOP                                                     ) // SpeedRacer
+#define X69 _EQ(           BROWSER_FORWARD                                                  ) // SpeedRacer
+#define X6A _EQ(           BROWSER_BACK                                                     ) // SpeedRacer
+#define X6B _EQ(           LAUNCH_APP1                                                      ) // SpeedRacer
+#define X6C _EQ(           LAUNCH_MAIL                                                      ) // SpeedRacer
+#define X6D _EQ(           LAUNCH_MEDIA_SELECT                                              ) // SpeedRacer
+#define XF1 _NE(_none_,    _none_,    _none_,    HANJA,     HANJA,     HANJA,     HANJA     )
+#define XF2 _NE(_none_,    _none_,    _none_,    HANGEUL,   HANGEUL,   HANGEUL,   HANGEUL   )
+
+        /*
+         * The break key is sent to us as E1,LCtrl,NumLock
+         * We must convert the E1+LCtrl to BREAK, then ignore the Numlock
+         */
+#define Y1D _EQ(           PAUSE                                                            )
+
+#elif (KBD_TYPE > 20) && (KBD_TYPE <= 22)
+/***********************************************************************\
+* T** - Values for ausVK[] (Virtual Scan Code to Virtual Key conversion)
+*
+* Three sets of keyboards are supported, according to KBD_TYPE:
+*
+* KBD_TYPE   Keyboard (examples)
+* ========   =====================================
+*   20       Fujitsu FMR JIS keyboard.
+*   21       Fujitsu FMR OYAYUBI keyboard.
+*   22 *     Fujitsu FMV OYAYUBI keyboard.
+*
+*     +------+ +----------+----------+----------+
+*     | Scan | |  kbd     |  kbd     |  kbd     |
+*     | code | | type 20  | type 21  | type 22  |
+\****+-------+-+----------+----------+----------+***********************/
+#define T00 _EQ(                      _none_    )
+#define T01 _EQ(                      ESCAPE    )
+#define T02 _EQ(                      '1'       )
+#define T03 _EQ(                      '2'       )
+#define T04 _EQ(                      '3'       )
+#define T05 _EQ(                      '4'       )
+#define T06 _EQ(                      '5'       )
+#define T07 _EQ(                      '6'       )
+#define T08 _EQ(                      '7'       )
+#define T09 _EQ(                      '8'       )
+#define T0A _EQ(                      '9'       )
+#define T0B _EQ(                      '0'       )
+#define T0C _EQ(                      OEM_MINUS )
+#define T0D _EQ(                      OEM_7     )
+#define T0E _NE(OEM_5,     OEM_5,     BACK      )
+#define T0F _NE(BACK,      BACK,      TAB       )
+#define T10 _NE(TAB,       TAB,       'Q'       )
+#define T11 _NE('Q',       'Q',       'W'       )
+#define T12 _NE('W',       'W',       'E'       )
+#define T13 _NE('E',       'E',       'R'       )
+#define T14 _NE('R',       'R',       'T'       )
+#define T15 _NE('T',       'T',       'Y'       )
+#define T16 _NE('Y',       'Y',       'U'       )
+#define T17 _NE('U',       'U',       'I'       )
+#define T18 _NE('I',       'I',       'O'       )
+#define T19 _NE('O',       'O',       'P'       )
+#define T1A _NE('P',       'P',       OEM_3     )
+#define T1B _NE(OEM_3,     OEM_3,     OEM_4     )
+#define T1C _NE(OEM_4,     OEM_4,     RETURN    )
+#define T1D _NE(RETURN,    RETURN,    LCONTROL  )
+#define T1E _EQ(                      'A'       )
+#define T1F _EQ(                      'S'       )
+#define T20 _EQ(                      'D'       )
+#define T21 _EQ(                      'F'       )
+#define T22 _EQ(                      'G'       )
+#define T23 _EQ(                      'H'       )
+#define T24 _EQ(                      'J'       )
+#define T25 _EQ(                      'K'       )
+#define T26 _EQ(                      'L'       )
+#define T27 _EQ(                      OEM_PLUS  )
+#define T28 _EQ(                      OEM_1     )
+#define T29 _NE(OEM_6,     OEM_6,     DBE_SBCSCHAR)
+#define T2A _NE('Z',       'Z',       LSHIFT    )
+#define T2B _NE('X',       'X',       OEM_6     )
+#define T2C _NE('C',       'C',       'Z'       )
+#define T2D _NE('V',       'V',       'X'       )
+#define T2E _NE('B',       'B',       'C'       )
+#define T2F _NE('N',       'N',       'V'       )
+#define T30 _NE('M',       'M',       'B'       )
+#define T31 _NE(OEM_COMMA, OEM_COMMA, 'N'       )
+#define T32 _NE(OEM_PERIOD,OEM_PERIOD,'M'       )
+#define T33 _NE(OEM_2,     OEM_2,     OEM_COMMA )
+#define T34 _NE(OEM_8,     OEM_8,     OEM_PERIOD)
+#define T35 _NE(' ',       ' ',       OEM_2     )
+#define T36 _NE(MULTIPLY,  MULTIPLY,  RSHIFT    )
+#define T37 _NE(DIVIDE,    DIVIDE,    MULTIPLY  )
+#define T38 _NE(ADD,       ADD,       LMENU     )
+#define T39 _NE(SUBTRACT,  SUBTRACT,  ' '       )
+#define T3A _NE(NUMPAD7,   NUMPAD7,   DBE_ALPHANUMERIC)
+#define T3B _NE(NUMPAD8,   NUMPAD8,   F1        )
+#define T3C _NE(NUMPAD9,   NUMPAD9,   F2        )
+#define T3D _NE(EQUAL,     EQUAL,     F3        )
+#define T3E _NE(NUMPAD4,   NUMPAD4,   F4        )
+#define T3F _NE(NUMPAD5,   NUMPAD5,   F5        )
+#define T40 _NE(NUMPAD6,   NUMPAD6,   F6        )
+#define T41 _NE(SEPARATOR, SEPARATOR, F7        )
+#define T42 _NE(NUMPAD1,   NUMPAD1,   F8        )
+#define T43 _NE(NUMPAD2,   NUMPAD2,   F9        )
+#define T44 _NE(NUMPAD3,   NUMPAD3,   F10       )
+#define T45 _NE(RETURN,    RETURN,    NUMLOCK   )
+#define T46 _NE(NUMPAD0,   NUMPAD0,   SCROLL    )
+#define T47 _NE(DECIMAL,   DECIMAL,   HOME      )
+#define T48 _NE(INSERT,    INSERT,    UP        )
+#define T49 _NE(OEM_00,    OEM_00,    PRIOR     )
+#define T4A _NE(OEM_000,   OEM_000,   SUBTRACT  )
+#define T4B _NE(DELETE,    DELETE,    LEFT      )
+#define T4C _NE(_none_,    _none_,    CLEAR     )
+#define T4D _NE(UP,        UP,        RIGHT     )
+#define T4E _NE(HOME,      HOME,      ADD       )
+#define T4F _NE(LEFT,      LEFT,      END       )
+#define T50 _EQ(                      DOWN      )
+#define T51 _NE(RIGHT,     RIGHT,     NEXT      )
+#define T52 _NE(LCONTROL,  LCONTROL,  INSERT    )
+#define T53 _NE(LSHIFT,    LSHIFT,    DELETE    )
+#define T54 _NE(_none_,    _none_,    SNAPSHOT  )
+#define T55 _NE(CAPITAL,   _none_,    _none_    )
+#define T56 _NE(DBE_HIRAGANA,_none_,  _none_    )
+#define T57 _NE(NONCONVERT,NONCONVERT,F11       )
+#define T58 _NE(CONVERT,   CONVERT,   F12       )
+#define T59 _NE(KANJI,     KANJI,     CLEAR     )
+#define T5A _NE(DBE_KATAKANA,_none_,  NONAME    )
+#define T5B _NE(F12,       F12,       NONAME    )
+#define T5C _NE(LMENU,     LMENU,     NONAME    )
+#define T5D _NE(F1,        F1,        EREOF     )
+#define T5E _NE(F2,        F2,        _none_    )
+#define T5F _NE(F3,        F3,        NONAME    )
+#define T60 _NE(F4,        F4,        _none_    )
+#define T61 _NE(F5,        F5,        _none_    )
+#define T62 _NE(F6,        F6,        _none_    )
+#define T63 _NE(F7,        F7,        _none_    )
+#define T64 _NE(F8,        F8,        F13       )
+#define T65 _NE(F9,        F9,        F14       )
+#define T66 _NE(F10,       F10,       F15       )
+#define T67 _NE(_none_,    OEM_LOYA,  F16       )
+#define T68 _NE(_none_,    OEM_ROYA,  F17       )
+#define T69 _NE(F11,       F11,       F18       )
+#define T6A _NE(_none_,    DBE_ALPHANUMERIC,F19 )
+#define T6B _NE(OEM_JISHO, OEM_JISHO, F20       )
+#define T6C _NE(OEM_MASSHOU,OEM_MASSHOU,F21     )
+#define T6D _NE(_none_,    _none_,    F22       )
+#define T6E _NE(PRIOR,     PRIOR,     F23       )
+#define T6F _NE(_none_,    DBE_KATAKANA,_none_  )
+#define T70 _NE(NEXT,      NEXT,      DBE_HIRAGANA)
+#define T71 _EQ(                      _none_    )
+#define T72 _NE(CANCEL,    CANCEL,    _none_    )
+#define T73 _NE(EXECUTE,   EXECUTE,   OEM_102   )
+#define T74 _NE(F13,       F13,       _none_    )
+#define T75 _NE(F14,       F14,       _none_    )
+#define T76 _NE(F15,       F15,       F24       )
+#define T77 _NE(F16,       F16,       _none_    )
+#define T78 _NE(CLEAR,     CLEAR,     _none_    )
+#define T79 _NE(HELP,      HELP,      CONVERT   )
+#define T7A _NE(END,       END,       _none_    )
+#define T7B _NE(SCROLL,    SCROLL,    NONCONVERT)
+#define T7C _NE(PAUSE,     PAUSE,     TAB       )
+#define T7D _NE(SNAPSHOT,  SNAPSHOT,  OEM_5     )
+#define T7E _NE(_none_,    _none_,    ABNT_C2   )
+#define T7F _NE(_none_,    _none_,    OEM_PA2   )
+
+#define X1C _NE(_none_,    _none_,    RETURN    )
+#define X1D _NE(_none_,    _none_,    RCONTROL  )
+#define X33 _EQ(                      _none_    )
+#define X35 _NE(_none_,    _none_,    DIVIDE    )
+#define X37 _NE(_none_,    _none_,    SNAPSHOT  )
+#define X38 _NE(_none_,    _none_,    RMENU     )
+#define X42 _EQ(                      _none_    )
+#define X43 _EQ(                      _none_    )
+#define X44 _EQ(                      _none_    )
+#define X46 _NE(_none_,    _none_,    CANCEL    )
+#define X47 _NE(_none_,    _none_,    HOME      )
+#define X48 _NE(_none_,    _none_,    UP        )
+#define X49 _NE(_none_,    _none_,    PRIOR     )
+#define X4B _NE(_none_,    _none_,    LEFT      )
+#define X4D _NE(_none_,    _none_,    RIGHT     )
+#define X4F _NE(_none_,    _none_,    END       )
+#define X50 _NE(_none_,    _none_,    DOWN      )
+#define X51 _NE(_none_,    _none_,    NEXT      )
+#define X52 _NE(_none_,    _none_,    INSERT    )
+#define X53 _NE(_none_,    _none_,    DELETE    )
+#define X5B _NE(_none_,    _none_,    LWIN      )
+#define X5C _NE(_none_,    _none_,    RWIN      )
+#define X5D _NE(_none_,    _none_,    APPS      )
+#define X5E _EQ(                      POWER     )
+#define X5F _EQ(                      SLEEP     )
+#define X60 _NE(SCROLL,    SCROLL,    _none_    )
+#define X61 _NE(HOME,      HOME,      _none_    )
+#define X62 _NE(END,       END,       _none_    )
+#define X63 _EQ(                      _none_    )
+#define X64 _EQ(                      _none_    )
+#define X65 _EQ(                      _none_    )
+#define X66 _EQ(                      _none_    )
+#define X6D _NE(OEM_TOUROKU,OEM_TOUROKU,_none_  )
+#define X71 _NE(DBE_SBCSCHAR,DBE_SBCSCHAR,_none_)
+#define X74 _EQ(                      _none_    )
+#define X75 _EQ(                      _none_    )
+#define X76 _EQ(                      _none_    )
+#define X77 _EQ(                      _none_    )
+#define X78 _EQ(                      _none_    )
+#define X79 _EQ(                      _none_    )
+#define X7A _EQ(                      _none_    )
+#define X7B _EQ(                      _none_    )
+
+        /*
+         * The break key is sent to us as E1,LCtrl,NumLock
+         * We must convert the E1+LCtrl to BREAK, then ignore the Numlock
+         * which must be ignored.  Alternatively, translate Ctrl-Numlock
+         * to break, but don't let the CTRL through as a WM_KEYUP/DOWN) ?
+         */
+#define Y1D _EQ(              PAUSE             )
+
+#elif (KBD_TYPE >= 30) && (KBD_TYPE <= 34)
+/***********************************************************************\
+* T** - Values for ausVK[] (Virtual Scan Code to Virtual Key conversion)
+*
+* Three sets of keyboards are supported, according to KBD_TYPE:
+*
+* KBD_TYPE   Keyboard (examples)
+* ========   =====================================
+*   30 *     NEC PC-9800 Normal Keyboard.
+*   31       NEC PC-9800 Document processor Keyboard.  - not supported on NT5
+*   32       NEC PC-9800 106 Keyboard. - same as KBD_TYPE 8
+*   33       NEC PC-9800 for Hydra: PC-9800 Keyboard on Windows NT 5.0.
+*            NEC PC-98NX for Hydra: PC-9800 Keyboard on Windows 95/NT.
+*   34       NEC PC-9800 for Hydra: PC-9800 Keyboard on Windows NT 3.51/4.0.
+*
+*     +------+ +----------+----------+----------+
+*     | Scan | |   kbd    |   kbd    |   kbd    |
+*     | code | |  type 30 |  type 33 |  type 34 |
+\****+-------+-+----------+----------+----------+***********************/
+#define T00 _EQ(_none_                          )
+#define T01 _EQ(ESCAPE                          )
+#define T02 _EQ('1'                             )
+#define T03 _EQ('2'                             )
+#define T04 _EQ('3'                             )
+#define T05 _EQ('4'                             )
+#define T06 _EQ('5'                             )
+#define T07 _EQ('6'                             )
+#define T08 _EQ('7'                             )
+#define T09 _EQ('8'                             )
+#define T0A _EQ('9'                             )
+#define T0B _EQ('0'                             )
+#define T0C _EQ(OEM_MINUS                       )
+#define T0D _NE(OEM_7,     OEM_7,     OEM_PLUS  )
+#define T0E _EQ(BACK                            )
+#define T0F _EQ(TAB                             )
+#define T10 _EQ('Q'                             )
+#define T11 _EQ('W'                             )
+#define T12 _EQ('E'                             )
+#define T13 _EQ('R'                             )
+#define T14 _EQ('T'                             )
+#define T15 _EQ('Y'                             )
+#define T16 _EQ('U'                             )
+#define T17 _EQ('I'                             )
+#define T18 _EQ('O'                             )
+#define T19 _EQ('P'                             )
+#define T1A _NE(OEM_3,     OEM_3,     OEM_4     )
+#define T1B _NE(OEM_4,     OEM_4,     OEM_6     )
+#define T1C _EQ(RETURN                          )
+#define T1D _EQ(LCONTROL                        )
+#define T1E _EQ('A'                             )
+#define T1F _EQ('S'                             )
+#define T20 _EQ('D'                             )
+#define T21 _EQ('F'                             )
+#define T22 _EQ('G'                             )
+#define T23 _EQ('H'                             )
+#define T24 _EQ('J'                             )
+#define T25 _EQ('K'                             )
+#define T26 _EQ('L'                             )
+#define T27 _NE(OEM_PLUS,  OEM_PLUS,  OEM_1     )
+#define T28 _NE(OEM_1,     OEM_1,     OEM_7     )
+#define T29 _NE(DBE_SBCSCHAR, \
+                           DBE_SBCSCHAR, \
+                                      OEM_3     )
+#define T2A _EQ(LSHIFT                          )
+#define T2B _NE(OEM_6,     OEM_6,     OEM_5     )
+#define T2C _EQ('Z'                             )
+#define T2D _EQ('X'                             )
+#define T2E _EQ('C'                             )
+#define T2F _EQ('V'                             )
+#define T30 _EQ('B'                             )
+#define T31 _EQ('N'                             )
+#define T32 _EQ('M'                             )
+#define T33 _EQ(OEM_COMMA                       )
+#define T34 _EQ(OEM_PERIOD                      )
+#define T35 _EQ(OEM_2                           )
+#define T36 _EQ(RSHIFT                          )
+#define T37 _EQ(MULTIPLY                        )
+#define T38 _EQ(LMENU                           )
+#define T39 _EQ(' '                             )
+#define T3A _EQ(CAPITAL                         )
+#define T3B _EQ(F1                              )
+#define T3C _EQ(F2                              )
+#define T3D _EQ(F3                              )
+#define T3E _EQ(F4                              )
+#define T3F _EQ(F5                              )
+#define T40 _EQ(F6                              )
+#define T41 _EQ(F7                              )
+#define T42 _EQ(F8                              )
+#define T43 _EQ(F9                              )
+#define T44 _EQ(F10                             )
+#define T45 _EQ(NUMLOCK                         )
+#define T46 _EQ(SCROLL                          )
+#define T47 _EQ(HOME                            )
+#define T48 _EQ(UP                              )
+#define T49 _EQ(PRIOR                           )
+#define T4A _EQ(SUBTRACT                        )
+#define T4B _EQ(LEFT                            )
+#define T4C _EQ(CLEAR                           )
+#define T4D _EQ(RIGHT                           )
+#define T4E _EQ(ADD                             )
+#define T4F _EQ(END                             )
+#define T50 _EQ(DOWN                            )
+#define T51 _EQ(NEXT                            )
+#define T52 _EQ(INSERT                          )
+#define T53 _EQ(DELETE                          )
+#define T54 _EQ(SNAPSHOT                        )
+#define T55 _NE(_none_,    _none_,    OEM_8     )
+#define T56 _EQ(_none_                          )
+#define T57 _EQ(F11                             )
+#define T58 _EQ(F12                             )
+#define T59 _EQ(OEM_NEC_EQUAL                   )
+#define T5A _NE(NONAME,    NONAME,    NONCONVERT)
+#define T5B _NE(_none_,    _none_,    NONAME    )
+#define T5C _EQ(SEPARATOR                       )
+#define T5D _EQ(F13                             )
+#define T5E _EQ(F14                             )
+#define T5F _EQ(F15                             )
+#define T60 _EQ(_none_                          )
+#define T61 _EQ(_none_                          )
+#define T62 _EQ(_none_                          )
+#define T63 _EQ(_none_                          )
+#define T64 _NE(_none_,    _none_,    F13       )
+#define T65 _NE(_none_,    _none_,    F14       )
+#define T66 _NE(_none_,    _none_,    F15       )
+#define T67 _NE(_none_,    _none_,    F16       )
+#define T68 _NE(_none_,    _none_,    F17       )
+#define T69 _NE(_none_,    _none_,    F18       )
+#define T6A _NE(_none_,    _none_,    F19       )
+#define T6B _NE(_none_,    _none_,    F20       )
+#define T6C _NE(_none_,    _none_,    F21       )
+#define T6D _NE(_none_,    _none_,    F22       )
+#define T6E _NE(_none_,    _none_,    F23       )
+#define T6F _EQ(_none_                          )
+#define T70 _NE(KANA,      KANA,      DBE_HIRAGANA)
+#define T71 _EQ(_none_                          )
+#define T72 _EQ(_none_                          )
+#define T73 _NE(OEM_8,     OEM_8,     _none_    )
+#define T74 _NE(_none_,    OEM_NEC_EQUAL, \
+                                      _none_    )
+#define T75 _NE(_none_,    SEPARATOR, _none_    )
+#define T76 _NE(_none_,    _none_,    F24       )
+#define T77 _NE(_none_,    _none_,    DBE_SBCSCHAR)
+#define T78 _EQ(_none_                          )
+#define T79 _EQ(CONVERT                         )
+#define T7A _EQ(_none_                          )
+#define T7B _EQ(NONCONVERT                      )
+#define T7C _NE(TAB,       _none_,    _none_    )
+#define T7D _NE(OEM_5,     OEM_5,     _none_    )
+#define T7E _NE(ABNT_C2,   ABNT_C2,   _none_    )
+#define T7F _NE(OEM_PA2,   OEM_PA2,   _none_    )
+
+#define X1C _EQ(RETURN                          )
+#define X1D _NE(RCONTROL,  RCONTROL,  KANA      )
+#define X33 _EQ(_none_                          )
+#define X35 _EQ(DIVIDE                          )
+#define X37 _EQ(SNAPSHOT                        )
+#define X38 _NE(_none_,    _none_,    KANJI     )
+#define X42 _NE(_none_,    _none_,    RCONTROL  )
+#define X43 _NE(_none_,    _none_,    RMENU     )
+#define X44 _EQ(_none_                          )
+#define X46 _EQ(CANCEL                          )
+#define X47 _EQ(HOME                            )
+#define X48 _EQ(UP                              )
+#define X49 _EQ(PRIOR                           )
+#define X4B _EQ(LEFT                            )
+#define X4D _EQ(RIGHT                           )
+#define X4F _EQ(END                             )
+#define X50 _EQ(DOWN                            )
+#define X51 _EQ(NEXT                            )
+#define X52 _EQ(INSERT                          )
+#define X53 _EQ(DELETE                          )
+#define X5B _EQ(LWIN                            )
+#define X5C _EQ(RWIN                            )
+#define X5D _EQ(APPS                            )
+#define X5E _EQ(POWER                           )
+#define X5F _EQ(SLEEP                           )
+#define X60 _EQ(_none_                          )
+#define X61 _EQ(_none_                          )
+#define X62 _EQ(_none_                          )
+#define X63 _EQ(_none_                          )
+#define X64 _EQ(_none_                          )
+#define X65 _EQ(_none_                          )
+#define X66 _EQ(_none_                          )
+#define X6D _EQ(_none_                          )
+#define X71 _EQ(_none_                          )
+#define X74 _EQ(_none_                          )
+#define X75 _EQ(_none_                          )
+#define X76 _EQ(_none_                          )
+#define X77 _EQ(_none_                          )
+#define X78 _EQ(_none_                          )
+#define X79 _EQ(_none_                          )
+#define X7A _EQ(_none_                          )
+#define X7B _EQ(_none_                          )
+        /*
+         * The break key is sent to us as E1,LCtrl,NumLock
+         * We must convert the E1+LCtrl to BREAK, then ignore the Numlock
+         * which must be ignored.  Alternatively, translate Ctrl-Numlock
+         * to break, but don't let the CTRL through as a WM_KEYUP/DOWN) ?
+         */
+#define Y1D _EQ(PAUSE                          )
+
+#elif (KBD_TYPE == 37)
+/***********************************************************************\
+* T** - Values for ausVK[] (Virtual Scan Code to Virtual Key conversion)
+*
+* Three sets of keyboards are supported, according to KBD_TYPE:
+*
+* KBD_TYPE   Keyboard (examples)
+* ========   =====================================
+*   37 *     NEC PC-9800 for Hydra: PC-9800 Keyboard on Windows 95.
+*
+*     +------+ +----------+
+*     | Scan | |   kbd    |
+*     | code | |  type 37 |
+\****+-------+-+----------+*********************************************/
+#define T00 _EQ(ESCAPE    )
+#define T01 _EQ('1'       )
+#define T02 _EQ('2'       )
+#define T03 _EQ('3'       )
+#define T04 _EQ('4'       )
+#define T05 _EQ('5'       )
+#define T06 _EQ('6'       )
+#define T07 _EQ('7'       )
+#define T08 _EQ('8'       )
+#define T09 _EQ('9'       )
+#define T0A _EQ('0'       )
+#define T0B _EQ(OEM_MINUS )
+#define T0C _EQ(OEM_7     )
+#define T0D _EQ(OEM_5     )
+#define T0E _EQ(BACK      )
+#define T0F _EQ(TAB       )
+#define T10 _EQ('Q'       )
+#define T11 _EQ('W'       )
+#define T12 _EQ('E'       )
+#define T13 _EQ('R'       )
+#define T14 _EQ('T'       )
+#define T15 _EQ('Y'       )
+#define T16 _EQ('U'       )
+#define T17 _EQ('I'       )
+#define T18 _EQ('O'       )
+#define T19 _EQ('P'       )
+#define T1A _EQ(OEM_3     )
+#define T1B _EQ(OEM_4     )
+#define T1C _EQ(RETURN    )
+#define T1D _EQ('A'       )
+#define T1E _EQ('S'       )
+#define T1F _EQ('D'       )
+#define T20 _EQ('F'       )
+#define T21 _EQ('G'       )
+#define T22 _EQ('H'       )
+#define T23 _EQ('J'       )
+#define T24 _EQ('K'       )
+#define T25 _EQ('L'       )
+#define T26 _EQ(OEM_PLUS  )
+#define T27 _EQ(OEM_1     )
+#define T28 _EQ(OEM_6     )
+#define T29 _EQ('Z'       )
+#define T2A _EQ('X'       )
+#define T2B _EQ('C'       )
+#define T2C _EQ('V'       )
+#define T2D _EQ('B'       )
+#define T2E _EQ('N'       )
+#define T2F _EQ('M'       )
+#define T30 _EQ(OEM_COMMA )
+#define T31 _EQ(OEM_PERIOD)
+#define T32 _EQ(OEM_2     )
+#define T33 _EQ(OEM_8     )
+#define T34 _EQ(' '       )
+#define T35 _EQ(CONVERT   )
+#define T36 _EQ(NEXT      )
+#define T37 _EQ(PRIOR     )
+#define T38 _EQ(INSERT    )
+#define T39 _EQ(DELETE    )
+#define T3A _EQ(UP        )
+#define T3B _EQ(LEFT      )
+#define T3C _EQ(RIGHT     )
+#define T3D _EQ(DOWN      )
+#define T3E _EQ(HOME      )
+#define T3F _EQ(END       )
+#define T40 _EQ(SUBTRACT  )
+#define T41 _EQ(DIVIDE    )
+#define T42 _EQ(NUMPAD7   )
+#define T43 _EQ(NUMPAD8   )
+#define T44 _EQ(NUMPAD9   )
+#define T45 _EQ(MULTIPLY  )
+#define T46 _EQ(NUMPAD4   )
+#define T47 _EQ(NUMPAD5   )
+#define T48 _EQ(NUMPAD6   )
+#define T49 _EQ(ADD       )
+#define T4A _EQ(NUMPAD1   )
+#define T4B _EQ(NUMPAD2   )
+#define T4C _EQ(NUMPAD3   )
+#define T4D _EQ(OEM_NEC_EQUAL)
+#define T4E _EQ(NUMPAD0   )
+#define T4F _EQ(SEPARATOR )
+#define T50 _EQ(DECIMAL   )
+#define T51 _EQ(NONCONVERT)
+#define T52 _EQ(F11       )
+#define T53 _EQ(F12       )
+#define T54 _EQ(F13       )
+#define T55 _EQ(F14       )
+#define T56 _EQ(F15       )
+#define T57 _EQ(_none_    )
+#define T58 _EQ(_none_    )
+#define T59 _EQ(_none_    )
+#define T5A _EQ(_none_    )
+#define T5B _EQ(_none_    )
+#define T5C _EQ(RETURN    )
+#define T5D _EQ(_none_    )
+#define T5E _EQ(_none_    )
+#define T5F _EQ(_none_    )
+#define T60 _EQ(CANCEL    )
+#define T61 _EQ(SNAPSHOT  )
+#define T62 _EQ(F1        )
+#define T63 _EQ(F2        )
+#define T64 _EQ(F3        )
+#define T65 _EQ(F4        )
+#define T66 _EQ(F5        )
+#define T67 _EQ(F6        )
+#define T68 _EQ(F7        )
+#define T69 _EQ(F8        )
+#define T6A _EQ(F9        )
+#define T6B _EQ(F10       )
+#define T6C _EQ(_none_    )
+#define T6D _EQ(_none_    )
+#define T6E _EQ(_none_    )
+#define T6F _EQ(_none_    )
+#define T70 _EQ(LSHIFT    )
+#define T71 _EQ(CAPITAL   )
+#define T72 _EQ(KANA      )
+#define T73 _EQ(LMENU     )
+#define T74 _EQ(LCONTROL  )
+#define T75 _EQ(_none_    )
+#define T76 _EQ(_none_    )
+#define T77 _EQ(LWIN      )
+#define T78 _EQ(RWIN      )
+#define T79 _EQ(APPS      )
+#define T7A _EQ(_none_    )
+#define T7B _EQ(_none_    )
+#define T7C _EQ(_none_    )
+#define T7D _EQ(RSHIFT    )
+#define T7E _EQ(ABNT_C2   )
+#define T7F _EQ(OEM_PA2   )
+
+        /*
+         * The break key is sent to us as E1,LCtrl,NumLock
+         * We must conevrt the E1+LCtrl to BREAK, then ignore the Numlock
+         * which must be ignored.  Alternatively, translate Ctrl-Numlock
+         * to break, but don't let the CTRL through as a WM_KEYUP/DOWN) ?
+         */
+#define Y1D _EQ(PAUSE    )
+
+#elif (KBD_TYPE >= 40) && (KBD_TYPE <= 41)
+/***********************************************************************\
+* T** - Values for ausVK[] (Virtual Scan Code to Virtual Key conversion)
+*
+* Two sets of keyboards are supported, according to KBD_TYPE:
+*
+* KBD_TYPE   Keyboard (examples)
+* ========   =====================================
+*   40 *     DEC LK411-JJ (JIS  layout) keyboard
+*   41       DEC LK411-AJ (ANSI layout) keyboard
+*
+*     +------+ +-----------+-----------+
+*     | Scan | |    kbd    |    kbd    |
+*     | code | |  LK411-JJ |  LK411-AJ |
+\*****+------+-+-----------+-----------+********************************/
+#define T00 _EQ(        _none_            )
+#define T01 _EQ(        ESCAPE            )
+#define T02 _EQ(        '1'               )
+#define T03 _EQ(        '2'               )
+#define T04 _EQ(        '3'               )
+#define T05 _EQ(        '4'               )
+#define T06 _EQ(        '5'               )
+#define T07 _EQ(        '6'               )
+#define T08 _EQ(        '7'               )
+#define T09 _EQ(        '8'               )
+#define T0A _EQ(        '9'               )
+#define T0B _EQ(        '0'               )
+#define T0C _EQ(        OEM_MINUS         )
+#define T0D _NE( OEM_7,      OEM_PLUS     ) // "^"/"="
+#define T0E _EQ(        BACK              )
+#define T0F _EQ(        TAB               )
+#define T10 _EQ(        'Q'               )
+#define T11 _EQ(        'W'               )
+#define T12 _EQ(        'E'               )
+#define T13 _EQ(        'R'               )
+#define T14 _EQ(        'T'               )
+#define T15 _EQ(        'Y'               )
+#define T16 _EQ(        'U'               )
+#define T17 _EQ(        'I'               )
+#define T18 _EQ(        'O'               )
+#define T19 _EQ(        'P'               )
+#define T1A _NE( OEM_3,      OEM_4        ) // "@"/"["
+#define T1B _NE( OEM_4,      OEM_6        ) // "["/"]"
+#define T1C _EQ(        RETURN            )
+#define T1D _EQ(        LCONTROL          )
+#define T1E _EQ(        'A'               )
+#define T1F _EQ(        'S'               )
+#define T20 _EQ(        'D'               )
+#define T21 _EQ(        'F'               )
+#define T22 _EQ(        'G'               )
+#define T23 _EQ(        'H'               )
+#define T24 _EQ(        'J'               )
+#define T25 _EQ(        'K'               )
+#define T26 _EQ(        'L'               )
+#define T27 _NE( OEM_PLUS,   OEM_1        ) // ";"
+#define T28 _NE( OEM_1,      OEM_7        ) // ":"/"'"
+#define T29 _NE( _none_,     DBE_SBCSCHAR ) // LK411AJ uses "<>" as SBCS/DBCS key
+#define T2A _EQ(        LSHIFT            )
+#define T2B _NE( OEM_6,      OEM_5        ) // "]"/"\"
+#define T2C _EQ(        'Z'               )
+#define T2D _EQ(        'X'               )
+#define T2E _EQ(        'C'               )
+#define T2F _EQ(        'V'               )
+#define T30 _EQ(        'B'               )
+#define T31 _EQ(        'N'               )
+#define T32 _EQ(        'M'               )
+#define T33 _EQ(        OEM_COMMA         )
+#define T34 _EQ(        OEM_PERIOD        )
+#define T35 _EQ(        OEM_2             ) // "/"
+#define T36 _EQ(        RSHIFT            )
+#define T37 _EQ(        MULTIPLY          ) // PF3 : "*"
+#define T38 _EQ(        LMENU             ) // Alt(Left)
+#define T39 _EQ(        ' '               ) // Space
+#define T3A _EQ(        CAPITAL           ) // LOCK : Caps Lock
+#define T3B _EQ(        F1                )
+#define T3C _EQ(        F2                )
+#define T3D _EQ(        F3                )
+#define T3E _EQ(        F4                )
+#define T3F _EQ(        F5                )
+#define T40 _EQ(        F6                )
+#define T41 _EQ(        F7                )
+#define T42 _EQ(        F8                )
+#define T43 _EQ(        F9                )
+#define T44 _EQ(        F10               )
+#define T45 _EQ(        NUMLOCK           ) // PF1 : Num Lock
+#define T46 _EQ(        SCROLL            ) // F19 : Scroll Lock
+#define T47 _EQ(        HOME              ) // KP7 : Home
+#define T48 _EQ(        UP                ) // KP8 : Up
+#define T49 _EQ(        PRIOR             ) // KP9 : Page Up
+#define T4A _EQ(        SUBTRACT          ) // PF4 : "-"
+#define T4B _EQ(        LEFT              ) // KP4 : Left
+#define T4C _EQ(        CLEAR             ) // KP5 : Clear
+#define T4D _EQ(        RIGHT             ) // KP6 : Right
+#define T4E _EQ(        ADD               ) // KP, : Add
+#define T4F _EQ(        END               ) // KP1 : End
+#define T50 _EQ(        DOWN              ) // KP2 : Down
+#define T51 _EQ(        NEXT              ) // KP3 : Next
+#define T52 _EQ(        INSERT            ) // KP0 : Ins
+#define T53 _EQ(        DELETE            ) // KP. : Del
+#define T54 _EQ(        SNAPSHOT          )
+#define T55 _EQ(        _none_            )
+#define T56 _EQ(        _none_            )
+#define T57 _EQ(        F11               )
+#define T58 _EQ(        F12               )
+#define T59 _EQ(        _none_            )
+#define T5A _EQ(        _none_            )
+#define T5B _EQ(        _none_            )
+#define T5C _EQ(        _none_            )
+#define T5D _EQ(        _none_            )
+#define T5E _EQ(        _none_            )
+#define T5F _EQ(        _none_            )
+#define T60 _EQ(        _none_            )
+#define T61 _EQ(        _none_            )
+#define T62 _EQ(        _none_            )
+#define T63 _EQ(        _none_            )
+#define T64 _EQ(        _none_            )
+#define T65 _EQ(        _none_            )
+#define T66 _EQ(        _none_            )
+#define T67 _EQ(        _none_            )
+#define T68 _EQ(        _none_            )
+#define T69 _EQ(        _none_            )
+#define T6A _EQ(        _none_            )
+#define T6B _EQ(        _none_            )
+#define T6C _EQ(        _none_            )
+#define T6D _EQ(        _none_            )
+#define T6E _EQ(        _none_            )
+#define T6F _EQ(        _none_            )
+#define T70 _EQ(       DBE_HIRAGANA       ) // Hiragana/Katakana
+#define T71 _EQ(        _none_            )
+#define T72 _EQ(        _none_            )
+#define T73 _NE( OEM_102,     _none_      ) // LK411JJ, Katakana "Ro"
+#define T74 _EQ(        _none_            )
+#define T75 _EQ(        _none_            )
+#define T76 _EQ(        _none_            )
+#define T77 _EQ(        _none_            )
+#define T78 _EQ(        _none_            )
+#define T79 _EQ(        CONVERT           ) // Henkan
+#define T7A _EQ(        _none_            )
+#define T7B _EQ(        NONCONVERT        ) // Mu-Henkan
+#define T7C _EQ(        _none_            )
+#define T7D _NE( OEM_5,       _none_      ) // LK411JJ, Yen(Back-slash)
+#define T7E _EQ(        _none_            )
+#define T7F _EQ(        _none_            )
+
+#define X0F _EQ(        KANA              ) // Kana
+#define X1C _EQ(        RETURN            ) // Enter
+#define X1D _EQ(        RCONTROL          ) // Comp : Right Control
+#define X33 _EQ(        _none_            )
+#define X35 _EQ(        DIVIDE            ) // PF2: "/"
+#define X37 _EQ(        SNAPSHOT          ) // F18: PrintScreen
+#define X38 _EQ(        RMENU             ) // Alt(Right)
+#define X3D _EQ(        F13               )
+#define X3E _EQ(        F14               )
+#define X3F _EQ(        F15               ) // Help : F15
+#define X40 _EQ(        F16               ) // Do :   F16
+#define X41 _EQ(        F17               )
+#define X42 _EQ(        _none_            )
+#define X43 _EQ(        _none_            )
+#define X44 _EQ(        _none_            )
+#define X46 _EQ(        CANCEL            )
+#define X47 _EQ(        HOME              ) // Find : HOME
+#define X48 _EQ(        UP                )
+#define X49 _EQ(        PRIOR             ) // Prev : PageUp
+#define X4B _EQ(        LEFT              )
+#define X4D _EQ(        RIGHT             )
+#define X4E _EQ(        ADD               ) // KP- (Minus but "Add")
+#define X4F _EQ(        END               ) // Select : END
+#define X50 _EQ(        DOWN              )
+#define X51 _EQ(        NEXT              ) // Next : PageDown
+#define X52 _EQ(        INSERT            )
+#define X53 _EQ(        DELETE            ) // Remove
+#define X5B _EQ(        _none_            )
+#define X5C _EQ(        _none_            )
+#define X5D _EQ(        _none_            )
+#define X5E _EQ(        POWER             )
+#define X5F _EQ(        SLEEP             )
+        /*
+         * The break key is sent to us as E1,LCtrl,NumLock
+         * We must convert the E1+LCtrl to BREAK, then ignore the Numlock
+         */
+#define Y1D _EQ(        PAUSE             )
+
+#endif // KBD_TYPE
+
+#define SCANCODE_LSHIFT      0x2A
+#define SCANCODE_RSHIFT      0x36
+#define SCANCODE_CTRL        0x1D
+#define SCANCODE_ALT         0x38
+#define SCANCODE_SIMULATED   (FAKE_KEYSTROKE >> 16)
+
+#define SCANCODE_NUMPAD_FIRST 0x47
+#define SCANCODE_NUMPAD_LAST  0x52
+
+#define SCANCODE_LWIN         0x5B
+#define SCANCODE_RWIN         0x5C
+
+#define SCANCODE_THAI_LAYOUT_TOGGLE 0x29
+
+
+//@@BEGIN_DDKSPLIT
+/*
+ * Hydra FarEast
+ */
+
+/*
+ * Structure for client keyboard information
+ */
+typedef struct _CLIENTKEYBOARDTYPE {
+    ULONG Type;
+    ULONG SubType;
+    ULONG FunctionKey;
+} CLIENTKEYBOARDTYPE, *KBD_LONG_POINTER PCLIENTKEYBOARDTYPE;
+//@@END_DDKSPLIT
+
+#if (NTDDI_VERSION >= NTDDI_WINXP)
+//@@BEGIN_DDKSPLIT
+#if !defined(VK_DBE_ALPHANUMERIC)
+//@@END_DDKSPLIT
+#define VK_DBE_ALPHANUMERIC              0x0f0
+#define VK_DBE_KATAKANA                  0x0f1
+#define VK_DBE_HIRAGANA                  0x0f2
+#define VK_DBE_SBCSCHAR                  0x0f3
+#define VK_DBE_DBCSCHAR                  0x0f4
+#define VK_DBE_ROMAN                     0x0f5
+#define VK_DBE_NOROMAN                   0x0f6
+#define VK_DBE_ENTERWORDREGISTERMODE     0x0f7
+#define VK_DBE_ENTERIMECONFIGMODE        0x0f8
+#define VK_DBE_FLUSHSTRING               0x0f9
+#define VK_DBE_CODEINPUT                 0x0fa
+#define VK_DBE_NOCODEINPUT               0x0fb
+#define VK_DBE_DETERMINESTRING           0x0fc
+#define VK_DBE_ENTERDLGCONVERSIONMODE    0x0fd
+//@@BEGIN_DDKSPLIT
+#endif
+//@@END_DDKSPLIT
+
+#endif
+
+#endif // _KBD_
diff --git a/lulua/data/winkbd/keyboard.c b/lulua/data/winkbd/keyboard.c
index dcc89c3..3398bd7 100644
--- a/lulua/data/winkbd/keyboard.c
+++ b/lulua/data/winkbd/keyboard.c
@@ -7,7 +7,6 @@
 * KBDTOOL v3.40 - Created  Sat Jan 04 14:19:07 2020
 \***************************************************************************/
 
-#include <windows.h>
 #include "kbd.h"
 #include "keyboard.h"
 
diff --git a/lulua/data/winkbd/keyboard.rc b/lulua/data/winkbd/keyboard.rc
index ca9ef38..891861f 100644
--- a/lulua/data/winkbd/keyboard.rc
+++ b/lulua/data/winkbd/keyboard.rc
@@ -1,7 +1,7 @@
 #include "winver.h"
 1 VERSIONINFO
- FILEVERSION       1,0,0,04
- PRODUCTVERSION    1,0,0,04
+ FILEVERSION       1,0,0,05
+ PRODUCTVERSION    1,0,0,05
  FILEFLAGSMASK 0x3fL
  FILEFLAGS 0x0L
 FILEOS 0x40004L
@@ -14,12 +14,12 @@ BEGIN
        BEGIN
            VALUE "CompanyName",     "6xq.net\0"
            VALUE "FileDescription", "Ergonomic Arabic Keyboard Layout lulua\0"
-           VALUE "FileVersion",     "0.4\0"
+           VALUE "FileVersion",     "0.5\0"
            VALUE "InternalName",    "kbdarlulua\0"
            VALUE "ProductName","lulua\0"
            VALUE "LegalCopyright",  "see https://opensource.org/licenses/MIT\0"
            VALUE "OriginalFilename","kbdarlulua\0"
-           VALUE "ProductVersion",  "0.4\0"
+           VALUE "ProductVersion",  "0.5\0"
        END
    END
    BLOCK "VarFileInfo"
diff --git a/lulua/data/winkbd/linker.ld b/lulua/data/winkbd/linker.ld
new file mode 100644
index 0000000..e7d9669
--- /dev/null
+++ b/lulua/data/winkbd/linker.ld
@@ -0,0 +1,36 @@
+/* taken from https://github.com/reactos/reactos/blob/893a3c9d030fd8b078cbd747eeefd3f6ce57e560/dll/keyboard/kbdlayout.lds */
+SECTIONS
+{
+  .data __image_base__ + __section_alignment__ :
+  {
+    *(.data)
+    *(SORT(.data*))
+    *(.rdata)
+    *(SORT(.rdata*))
+    *(.text)
+    *(SORT(.text*))
+    *(.bss)
+    *(COMMON)
+  }
+
+  .rsrc BLOCK(__section_alignment__) :
+  {
+    *(.rsrc)
+    *(SORT(.rsrc*))
+  }
+
+  .reloc BLOCK(__section_alignment__) :
+  {
+    *(.reloc)
+  }
+
+  .edata BLOCK(__section_alignment__) :
+  {
+    *(.edata)
+  }
+
+  /DISCARD/ :
+  {
+    *(*)
+  }
+}
diff --git a/lulua/data/winkbd/make.bat b/lulua/data/winkbd/make.bat
deleted file mode 100755
index 4c66cc0..0000000
--- a/lulua/data/winkbd/make.bat
+++ /dev/null
@@ -1,22 +0,0 @@
-REM taken from https://levicki.net/articles/2006/09/29/HOWTO_Build_keyboard_layouts_for_Windows_x64.php
-
-SET OUTNAME=kbdarlulua
-SET MSKLC="C:\Program Files (x86)\Microsoft Keyboard Layout Creator 1.4"
-
-mkdir System32
-
-%MSKLC%\bin\i386\rc.exe -r -i%MSKLC%\inc -DSTD_CALL -DCONDITION_HANDLING=1 -DNT_UP=1 -DNT_INST=0 -DWIN32=100 -D_NT1X_=100 -DWINNT=1 -D_WIN32_WINNT=0x0502 /DWINVER=0x0502 -D_WIN32_IE=0x0600 -DWIN32_LEAN_AND_MEAN=1 -DDEVL=1 -DFPO=1 -DNDEBUG -l 409 -Fokeyboard.res keyboard.rc || exit /b
-
-REM build 64 bit
-%MSKLC%\bin\i386\amd64\cl.exe -nologo -I%MSKLC%\inc -DNOGDICAPMASKS -DNOWINMESSAGES -DNOWINSTYLES -DNOSYSMETRICS -DNOMENUS -DNOICONS -DNOSYSCOMMANDS -DNORASTEROPS -DNOSHOWWINDOW -DOEMRESOURCE -DNOATOM -DNOCLIPBOARD -DNOCOLOR -DNOCTLMGR -DNODRAWTEXT -DNOGDI -DNOKERNEL -DNONLS -DNOMB -DNOMEMMGR -DNOMETAFILE -DNOMINMAX -DNOMSG -DNOOPENFILE -DNOSCROLL -DNOSERVICE -DNOSOUND -DNOTEXTMETRIC -DNOWINOFFSETS -DNOWH -DNOCOMM -DNOKANJI -DNOHELP -DNOPROFILER -DNODEFERWINDOWPOS -DNOMCX -DWIN32_LEAN_AND_MEAN -DRoster -DSTD_CALL -D_WIN32_WINNT=0x0502 /c /Zp8 /Gy /W3 /WX /Gz /Gm- /EHs-c- /GR- /GF -Z7 /Zl /Oxs -Fokeyboard64.obj keyboard.c || exit /b
-
-REM XXX: why use the 32 bit linker here? the one in amd64\ does not work
-%MSKLC%\bin\i386\link.exe -nologo -base:0x5FFE0000 -merge:.edata=.data -merge:.rdata=.data -merge:.text=.data -merge:.bss=.data -section:.data,re -MERGE:_PAGE=PAGE -MERGE:_TEXT=.text -MACHINE:AMD64 -SECTION:INIT,d -OPT:REF -OPT:ICF -IGNORE:4039,4078 -noentry -dll -subsystem:native,5.2 -merge:.rdata=.text -PDBPATH:NONE -STACK:0x40000,0x1000 /opt:nowin98 -debugtype:cv,fixup -debug -osversion:5.2 -version:5.2 /release -def:keyboard.def -out:system32\%OUTNAME%.dll keyboard.res keyboard64.obj || exit /b
-
-REM and now 32 bit
-mkdir SysWOW64
-
-%MSKLC%\bin\i386\cl.exe -nologo -I%MSKLC%\inc -DBUILD_WOW6432 -DNOGDICAPMASKS -DNOWINMESSAGES -DNOWINSTYLES -DNOSYSMETRICS -DNOMENUS -DNOICONS -DNOSYSCOMMANDS -DNORASTEROPS -DNOSHOWWINDOW -DOEMRESOURCE -DNOATOM -DNOCLIPBOARD -DNOCOLOR -DNOCTLMGR -DNODRAWTEXT -DNOGDI -DNOKERNEL -DNONLS -DNOMB -DNOMEMMGR -DNOMETAFILE -DNOMINMAX -DNOMSG -DNOOPENFILE -DNOSCROLL -DNOSERVICE -DNOSOUND -DNOTEXTMETRIC -DNOWINOFFSETS -DNOWH -DNOCOMM -DNOKANJI -DNOHELP -DNOPROFILER -DNODEFERWINDOWPOS -DNOMCX -DWIN32_LEAN_AND_MEAN -DRoster -DSTD_CALL -D_WIN32_WINNT=0x0502 /c /Zp8 /Gy /W3 /WX /Gz /Gm- /EHs-c- /GR- /GF -Z7 /Zl /Oxs -Fokeyboard32.obj keyboard.c || exit /b
-
-%MSKLC%\bin\i386\link.exe -nologo -base:0x5FFF0000 -merge:.edata=.data -merge:.rdata=.data -merge:.text=.data -merge:.bss=.data -section:.data,re -MERGE:_PAGE=PAGE -MERGE:_TEXT=.text -MACHINE:IX86 -SECTION:INIT,d -OPT:REF -OPT:ICF -IGNORE:4039,4078 -noentry -dll -subsystem:native,5.2 -merge:.rdata=.text -PDBPATH:NONE -STACK:0x40000,0x1000 /opt:nowin98 -debugtype:cv,fixup -debug -osversion:5.2 -version:5.2 /release -def:keyboard.def -out:SysWOW64\%OUTNAME%.dll keyboard.res keyboard32.obj || exit /b
-
diff --git a/lulua/render.py b/lulua/render.py
index e195c99..78e2b17 100644
--- a/lulua/render.py
+++ b/lulua/render.py
@@ -667,8 +667,9 @@ def renderWinKbd (args):
             lines.append (f'#undef {k}')
             if len (v) == 1:
                 # character value if not symbolic
-                v = f"'{v}'"
-            lines.append (f'#define {k} _EQ({v})')
+                lines.append (f'#define {k} \'{v}\'')
+            else:
+                lines.append (f'#define {k} _EQ({v})')
         lines.append ('')
 
         lines.append ('#define VK_TO_WCH6 \\')
-- 
cgit v1.2.3