/* bzflag
 * Copyright (c) 1993-2018 Tim Riker
 *
 * This package is free software;  you can redistribute it and/or
 * modify it under the terms of the license found in the file
 * named COPYING that should have accompanied this file.
 *
 * THIS PACKAGE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 */
#define _WIN32_WINDOWS 0x0500

#include "WinDisplay.h"
#include "WinWindow.h"
#include "resource.h"
#include "BzfEvent.h"
#include <stdio.h>
#include <string.h>
#include "StateDatabase.h"

class Resolution
{
public:
    int         width;
    int         height;
    int         refresh;
    int         depth;
};

static int      resolutionCompare(const void* _a, const void* _b)
{
    const Resolution* a = (const Resolution*)_a;
    const Resolution* b = (const Resolution*)_b;

    // test the stuff we actually care about
    if (a->width < b->width) return -1;
    if (a->width > b->width) return 1;
    if (a->height < b->height) return -1;
    if (a->height > b->height) return 1;
    if (a->refresh < b->refresh) return -1;
    if (a->refresh > b->refresh) return 1;
    if (a->depth < b->depth) return -1;
    if (a->depth > b->depth) return 1;

    // other info can be ordered arbitrarily
    return 0;
}

//
// WinDisplay::Rep
//

WinDisplay::Rep::Rep(const char*) : refCount(1),
    hInstance(NULL)
{
    // register our window class
    hInstance = GetModuleHandle(NULL);

    WNDCLASSEX wc;
    wc.cbSize     = sizeof(wc);
    wc.style      = CS_HREDRAW | CS_VREDRAW | CS_OWNDC;
    wc.lpfnWndProc    = (WNDPROC)windowProc;
    wc.cbClsExtra     = 0;
    wc.cbWndExtra     = 0;
    wc.hInstance      = hInstance;
    wc.hIcon      = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_BZICON));
    wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground  = (HBRUSH)GetStockObject(NULL_BRUSH);
    wc.lpszMenuName   = NULL;
    wc.lpszClassName  = "BZFLAG";
    wc.hIconSm        = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_BZICON));

    if (RegisterClassEx(&wc) == 0)
        hInstance = NULL;
}

WinDisplay::Rep::~Rep()
{
    // do nothing
}

void            WinDisplay::Rep::ref()
{
    refCount++;
}

void            WinDisplay::Rep::unref()
{
    if (--refCount <= 0) delete this;
}

LONG WINAPI     WinDisplay::Rep::windowProc(HWND hwnd, UINT msg,
        WPARAM wparam, LPARAM lparam)
{
    switch (msg)
    {
    case WM_DESTROY:
    {
        WinWindow* window = WinWindow::lookupWindow(hwnd);
        if (window && window->getHandle() == hwnd) window->onDestroy();
        break;
    }

    case WM_PAINT:
        ValidateRect(hwnd, NULL);
        return 0;

    case WM_QUERYNEWPALETTE:
    {
        WinWindow* window = WinWindow::lookupWindow(hwnd);
        if (window) return window->queryNewPalette();
        return 0;
    }

    case WM_PALETTECHANGED:
        if ((HWND)wparam != hwnd)
        {
            WinWindow* window = WinWindow::lookupWindow(hwnd);
            if (window) window->paletteChanged();
        }
        return 0;

    case WM_ACTIVATE:
    {
        if (BZDB.isTrue("Win32NoMin"))
            break;
        WinWindow* window = WinWindow::lookupWindow(hwnd);
        if (window)
        {
            if (LOWORD(wparam) == WA_INACTIVE)
            {
                if (window->deactivate())
                    PostMessage(hwnd, WM_APP + 1, (WPARAM)0, (LPARAM)0);
            }
            else
            {
                if (window->activate())
                    PostMessage(hwnd, WM_APP + 0, (WPARAM)0, (LPARAM)0);
            }
        }
        break;
    }

    case WM_DISPLAYCHANGE:
    {
        WinWindow* window = WinWindow::lookupWindow(hwnd);
        if (window && window->getHandle() == hwnd)
        {
            // recreate opengl context
            WinWindow::deactivateAll();
            WinWindow::reactivateAll();
        }
        break;
    }

    case WM_SYSCOMMAND:
        switch (wparam)
        {
        // disable screen saver and monitor power-saving mode
        case SC_SCREENSAVE:
        case SC_MONITORPOWER:
            return 0;
        }
        break;
    }

    return DefWindowProc(hwnd, msg, wparam, lparam);
}

//
// WinDisplay
//

WinDisplay::WinDisplay(const char* displayName, const char*) :
    rep(NULL),
    hwnd(NULL),
    fullWidth(0),
    fullHeight(0),
    resolutions(NULL),
    translated(false),
    charCode(0)
{
    rep = new Rep(displayName);

    // get resolutions
    if (isValid() && !isFullScreenOnly())
    {
        int numModes, currentMode;
        ResInfo** resInfo = getVideoFormats(numModes, currentMode);

        // if no modes then make default
        if (!resInfo)
        {
            HDC hDC = GetDC(GetDesktopWindow());
            resInfo = new ResInfo*[1];
            resInfo[0] = new ResInfo("default",
                                     GetDeviceCaps(hDC, HORZRES),
                                     GetDeviceCaps(hDC, VERTRES), 0);
            ReleaseDC(GetDesktopWindow(), hDC);
            numModes = 1;
            currentMode = 0;
        }

        // register modes
        initResolutions(resInfo, numModes, currentMode);
    }
}

WinDisplay::~WinDisplay()
{
    setDefaultResolution();
    delete[] resolutions;
    rep->unref();
}

bool            WinDisplay::isFullScreenOnly() const
{
    return false;
}

int         WinDisplay::getFullWidth() const
{
    return fullWidth;
}

int         WinDisplay::getFullHeight() const
{
    return fullHeight;
}

bool            WinDisplay::isValid() const
{
    return rep->hInstance != NULL;
}

bool            WinDisplay::isEventPending() const
{
    MSG msg;
    return (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE) != 0);
}

bool WinDisplay::windowsEventToBZFEvent ( MSG &msg, BzfEvent& event ) const
{
    event.window = WinWindow::lookupWindow(msg.hwnd);
    switch (msg.message)
    {
    case WM_CLOSE:
    case WM_QUIT:
    case WM_SYSCOMMAND:
        if (msg.wParam != SC_CLOSE)
            break;
        event.type = BzfEvent::Quit;
        break;

    case WM_PAINT:
        event.type = BzfEvent::Redraw;
        ValidateRect(msg.hwnd, NULL);     // no more WM_PAINTs, please!
        break;

    case WM_SIZE:
        event.type = BzfEvent::Resize;
        event.resize.width = LOWORD(msg.lParam);
        event.resize.height = HIWORD(msg.lParam);
        break;

    case WM_MOUSEMOVE:
        event.type = BzfEvent::MouseMove;
        event.mouseMove.x = LOWORD(msg.lParam);
        event.mouseMove.y = HIWORD(msg.lParam);
        break;

    case WM_APP + 0:
        event.type = BzfEvent::Map;
        break;

    case WM_APP + 1:
        event.type = BzfEvent::Unmap;
        break;

    case WM_LBUTTONDOWN:
    case WM_MBUTTONDOWN:
    case WM_RBUTTONDOWN:
        event.type = BzfEvent::KeyDown;
        event.keyDown.ascii = 0;
        event.keyDown.shift = 0;
        switch (msg.message)
        {
        case WM_LBUTTONDOWN:
            event.keyDown.button = BzfKeyEvent::LeftMouse;
            break;
        case WM_MBUTTONDOWN:
            event.keyDown.button = BzfKeyEvent::MiddleMouse;
            break;
        case WM_RBUTTONDOWN:
            event.keyDown.button = BzfKeyEvent::RightMouse;
            break;
        default:
            return false;
        }
        break;

    case WM_LBUTTONUP:
    case WM_MBUTTONUP:
    case WM_RBUTTONUP:
        event.type = BzfEvent::KeyUp;
        event.keyUp.ascii = 0;
        event.keyUp.shift = 0;
        switch (msg.message)
        {
        case WM_LBUTTONUP:
            event.keyUp.button = BzfKeyEvent::LeftMouse;
            break;
        case WM_MBUTTONUP:
            event.keyUp.button = BzfKeyEvent::MiddleMouse;
            break;
        case WM_RBUTTONUP:
            event.keyUp.button = BzfKeyEvent::RightMouse;
            break;
        default:
            return false;
        }
        break;

    case WM_MOUSEWHEEL:
    {

        event.type = BzfEvent::KeyDown;
        event.keyDown.ascii = 0;
        event.keyDown.shift = 0;

        if (LOWORD(msg.wParam) == MK_SHIFT)
            event.keyDown.shift |= BzfKeyEvent::ShiftKey;
        if (LOWORD(msg.wParam) == MK_CONTROL)
            event.keyDown.shift |= BzfKeyEvent::ControlKey;
        if (LOWORD(msg.wParam) == MK_ALT)
            event.keyDown.shift |= BzfKeyEvent::AltKey;

        short field = HIWORD(msg.wParam);
        if (field > 0)
            event.keyDown.button  = BzfKeyEvent::WheelUp;
        else
            event.keyDown.button  = BzfKeyEvent::WheelDown;
    }
    break;

    case WM_KEYDOWN:
    case WM_SYSKEYDOWN:
        ((WinDisplay*)this)->translated = (bool)(TranslateMessage(&msg) != 0);
        if (!translated) ((WinDisplay*)this)->charCode = 0;
        if (isNastyKey(msg)) return false;
        DispatchMessage(&msg);
        event.type = BzfEvent::KeyDown;
        if (!getKey(msg, event.keyDown)) return false;
        break;

    case WM_KEYUP:
    case WM_SYSKEYUP:
    {
        ((WinDisplay*)this)->translated = (bool)(TranslateMessage(&msg) != 0);
        if (isNastyKey(msg)) return false;
        DispatchMessage(&msg);
        event.type = BzfEvent::KeyUp;
        if (!getKey(msg, event.keyUp)) return false;
        break;
    }

    default:
        TranslateMessage(&msg);
        DispatchMessage(&msg);
        return false;
    }
    return true;
}

bool            WinDisplay::peekEvent(BzfEvent& event) const
{
    MSG msg;
    if (PeekMessage(&msg, NULL, 0, 0,0) == -1) return false;
    return windowsEventToBZFEvent(msg,event);
}

bool            WinDisplay::getEvent(BzfEvent& event) const
{
    MSG msg;
    if (GetMessage(&msg, NULL, 0, 0) == -1) return false;
    return windowsEventToBZFEvent(msg,event);
}

void            WinDisplay::getModState(bool &shift, bool &ctrl, bool &alt)
{
    shift = (GetKeyState(VK_SHIFT) < 0);
    ctrl  = (GetKeyState(VK_CONTROL) < 0);
    alt   = (GetKeyState(VK_MENU) < 0);
}

bool            WinDisplay::getKey(const MSG& msg,
                                   BzfKeyEvent& key) const
{
    key.shift = 0;
    if (GetKeyState(VK_SHIFT) < 0)    key.shift |= BzfKeyEvent::ShiftKey;
    if (GetKeyState(VK_CONTROL) < 0)  key.shift |= BzfKeyEvent::ControlKey;
    if (GetKeyState(VK_MENU) < 0)     key.shift |= BzfKeyEvent::AltKey;

    if (translated)
    {
        MSG cmsg;
        if (PeekMessage(&cmsg, NULL, 0, 0, PM_NOREMOVE) &&
                (cmsg.message == WM_CHAR || cmsg.message == WM_SYSCHAR))
        {
            GetMessage(&cmsg, NULL, 0, 0);
            ((WinDisplay*)this)->charCode = (char)(TCHAR)cmsg.wParam;
        }
        else
            ((WinDisplay*)this)->charCode = 0;
    }

    if (charCode != 0)
        key.ascii = charCode;
    else if ((GetKeyState(VK_SHIFT) < 0) == (GetKeyState(VK_CAPITAL) < 0))
        key.ascii = asciiMap[(int)msg.wParam];
    else
        key.ascii = asciiShiftMap[(int)msg.wParam];
    key.button = buttonMap[(int)msg.wParam];
    if (key.button == BzfKeyEvent::Delete) key.ascii = 0;
    return (key.ascii != 0 || key.button != 0);
}

bool            WinDisplay::isNastyKey(const MSG& msg) const
{
    switch (msg.wParam)
    {
    case VK_LWIN:
    case VK_RWIN:
        // disable windows keys
        return true;

    case VK_ESCAPE:
        // disable ctrl+escape (which pops up the start menu)
        if (GetKeyState(VK_CONTROL) < 0)
            return true;
        break;
    }
    return false;
}

bool            WinDisplay::setDefaultResolution() const
{
    ChangeDisplaySettings(0, 0);
    return true;
}

bool            WinDisplay::doSetResolution(int index)
{
    // try setting the format
    Resolution& format = resolutions[index];
    DEVMODE dm;
    memset(&dm, 0, sizeof(dm));
    dm.dmSize      = sizeof(dm);
    dm.dmPelsWidth    = format.width;
    dm.dmPelsHeight       = format.height;
    dm.dmBitsPerPel       = format.depth;
    dm.dmDisplayFrequency = format.refresh;
    dm.dmFields      = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL;
    if (dm.dmDisplayFrequency != 0)
        dm.dmFields |= DM_DISPLAYFREQUENCY;

    // test the change before really doing it
    if (ChangeDisplaySettings(&dm, CDS_FULLSCREEN | CDS_TEST) !=
            DISP_CHANGE_SUCCESSFUL)
        return false;

    // deactivate windows before resolution change.  if we don't do this
    // then the app will almost certainly crash in the OpenGL driver.
    WinWindow::deactivateAll();

    // change resolution
    const bool changed = (ChangeDisplaySettings(&dm, CDS_FULLSCREEN) ==
                          DISP_CHANGE_SUCCESSFUL);

    // reactivate previously deactivated window after change
    WinWindow::reactivateAll();

    return changed;
}

BzfDisplay::ResInfo**   WinDisplay::getVideoFormats(
    int& numModes, int& currentMode)
{
    HDC hDC = GetDC(GetDesktopWindow());

    // get the current display depth
    const bool changeDepth = canChangeDepth();
    int currentDepth = GetDeviceCaps(hDC, BITSPIXEL) * GetDeviceCaps(hDC, PLANES);

    // count the resolutions
    int i, j = 0;
    typedef struct     //On WinXP, DEVMODE buffer overruns are occuring, if the DEVMODE data structure
    {
        //is not up to date. You need to compile with the new header files
        DEVMODE dm;    //Using old headers, Buffer is 148, but the data returned is 156, causing stack corruption
        byte fudge[30];//Throw some fudge in here so that it works even with old headers
    } SlopDEVMODE;
    SlopDEVMODE dm;
    DEVMODE *pdm = &dm.dm;

    memset( pdm, 0, sizeof(DEVMODE));
    pdm->dmSize = sizeof(DEVMODE);
    while (EnumDisplaySettings(NULL, j, pdm))
        j++;

    // allocate space for resolutions
    int numResolutions = j;
    resolutions = new Resolution[numResolutions];

    // enumerate all resolutions.  note that we might throw some
    // resolutions away, so resolutions may be bigger than necessary.
    for (i = j = 0; EnumDisplaySettings(NULL, j, pdm); j++)
    {
        // convert frequency of 1 to 0 (meaning the default)
        if ((pdm->dmFields & DM_DISPLAYFREQUENCY) && pdm->dmDisplayFrequency == 1)
            pdm->dmDisplayFrequency = 0;

        // ignore formats of different depth if we can't change depth
        if (!changeDepth && (int)pdm->dmBitsPerPel != currentDepth)
            continue;

        // ignore formats we know won't work
        if (pdm->dmPelsWidth < 640 || pdm->dmPelsHeight < 400 || pdm->dmBitsPerPel < 8)
            continue;

        // fill in format
        Resolution r;
        r.width = pdm->dmPelsWidth;
        r.height = pdm->dmPelsHeight;
        r.refresh = pdm->dmDisplayFrequency;
        r.depth = pdm->dmBitsPerPel;

        // do we already have an equivalent format already?
        int k;
        for (k = 0; k < i; ++k)
            if (resolutionCompare(&r, resolutions + k) == 0)
                break;
        if (k < i)
            continue;

        // add format
        resolutions[i++] = r;
    }
    numResolutions = i;

    // now sort resolutions
    qsort(resolutions, numResolutions, sizeof(resolutions[0]), resolutionCompare);

    // find current format
    int current = -1;
    const int currentWidth = GetDeviceCaps(hDC, HORZRES);
    const int currentHeight = GetDeviceCaps(hDC, VERTRES);
    for (i = numResolutions - 1; i >= 0; i--)
    {
        const Resolution* r = resolutions + i;
        if (r->width == currentWidth &&
                r->height == currentHeight &&
                r->depth == currentDepth)
        {
            // FIXME -- compare display refresh rate
            current = i;
            break;
        }
    }

    // make ResInfo list if we found the current format
    ResInfo** resInfo = NULL;
    if (current != -1)
    {
        char name[80];
        resInfo = new ResInfo*[numResolutions];
        for (i = 0; i < numResolutions; i++)
        {
            const Resolution* r = resolutions + i;
            if (r->refresh == 0)
                sprintf(name, "%dx%d %d bits", r->width, r->height, r->depth);
            else
                sprintf(name, "%dx%d @%dHz %d bits", r->width, r->height,
                        r->refresh, r->depth);
            resInfo[i] = new ResInfo(name, r->width, r->height, r->refresh);
        }
    }

    // done with desktop DC
    ReleaseDC(GetDesktopWindow(), hDC);

    // return modes
    numModes = numResolutions;
    currentMode = current;
    return resInfo;
}

#define OSR2_BUILD_NUMBER 1111
bool            WinDisplay::canChangeDepth()
{
    // not all versions of windows change dynamically change bit depth.
    // NT 4.0 and 95 OSR2 can and we assume anything later then them
    // will too.
    OSVERSIONINFO vinfo;
    vinfo.dwOSVersionInfoSize = sizeof(vinfo);
    if (!GetVersionEx(&vinfo))
        return false;
    if (vinfo.dwMajorVersion > 4)
        return true;
    if (vinfo.dwMajorVersion == 4)
    {
        if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_NT)
            return true;
        if (vinfo.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS &&
                LOWORD(vinfo.dwBuildNumber) >= OSR2_BUILD_NUMBER)
            return true;
    }
    return false;
}

const int       WinDisplay::asciiMap[] =
{
    0,          // no VK_ code
    0,          // VK_LBUTTON
    0,          // VK_RBUTTON
    0,          // VK_CANCEL
    0,          // VK_MBUTTON
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    8,          // VK_BACK
    9,          // VK_TAB
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_CLEAR
    13,         // VK_RETURN
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_SHIFT
    0,          // VK_CONTROL
    0,          // VK_MENU
    0,          // VK_PAUSE
    0,          // VK_CAPITAL
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    27,         // VK_ESCAPE
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    ' ',            // VK_SPACE
    0,          // VK_PRIOR
    0,          // VK_NEXT
    0,          // VK_END
    0,          // VK_HOME
    0,          // VK_LEFT
    0,          // VK_UP
    0,          // VK_RIGHT
    0,          // VK_DOWN
    0,          // VK_SELECT
    0,          // VK_PRINT
    0,          // VK_EXECUTE
    0,          // VK_SNAPSHOT
    0,          // VK_INSERT
    127,            // VK_DELETE
    0,          // VK_HELP
    '0',            // VK_0
    '1',            // VK_1
    '2',            // VK_2
    '3',            // VK_3
    '4',            // VK_4
    '5',            // VK_5
    '6',            // VK_6
    '7',            // VK_7
    '8',            // VK_8
    '9',            // VK_9
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    'A',            // VK_A
    'B',            // VK_B
    'C',            // VK_C
    'D',            // VK_D
    'E',            // VK_E
    'F',            // VK_F
    'G',            // VK_G
    'H',            // VK_H
    'I',            // VK_I
    'J',            // VK_J
    'K',            // VK_K
    'L',            // VK_L
    'M',            // VK_M
    'N',            // VK_N
    'O',            // VK_O
    'P',            // VK_P
    'Q',            // VK_Q
    'R',            // VK_R
    'S',            // VK_S
    'T',            // VK_T
    'U',            // VK_U
    'V',            // VK_V
    'W',            // VK_W
    'X',            // VK_X
    'Y',            // VK_Y
    'Z',            // VK_Z
    0,          // VK_LWIN
    0,          // VK_RWIN
    0,          // VK_APPS
    0,          // no VK_ code
    0,          // no VK_ code
    '0',            // VK_NUMPAD0
    '1',            // VK_NUMPAD1
    '2',            // VK_NUMPAD2
    '3',            // VK_NUMPAD3
    '4',            // VK_NUMPAD4
    '5',            // VK_NUMPAD5
    '6',            // VK_NUMPAD6
    '7',            // VK_NUMPAD7
    '8',            // VK_NUMPAD8
    '9',            // VK_NUMPAD9
    '*',            // VK_MULTIPLY
    '+',            // VK_ADD
    0,          // VK_SEPARATOR
    '-',            // VK_SUBTRACT
    '.',            // VK_DECIMAL
    '/',            // VK_DIVIDE
    0,          // VK_F1
    0,          // VK_F2
    0,          // VK_F3
    0,          // VK_F4
    0,          // VK_F5
    0,          // VK_F6
    0,          // VK_F7
    0,          // VK_F8
    0,          // VK_F9
    0,          // VK_F10
    0,          // VK_F11
    0,          // VK_F12
    0,          // VK_F13
    0,          // VK_F14
    0,          // VK_F15
    0,          // VK_F16
    0,          // VK_F17
    0,          // VK_F18
    0,          // VK_F19
    0,          // VK_F20
    0,          // VK_F21
    0,          // VK_F22
    0,          // VK_F23
    0,          // VK_F24
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_NUMLOCK
    0,          // VK_SCROLL
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_LSHIFT
    0,          // VK_RSHIFT
    0,          // VK_LCONTROL
    0,          // VK_RCONTROL
    0,          // VK_LMENU
    0,          // VK_RMENU
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    ';',            // no VK_ code
    '=',            // no VK_ code
    ',',            // no VK_ code
    '-',            // no VK_ code
    '.',            // no VK_ code
    '/',            // no VK_ code
    '`',            // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    '[',            // no VK_ code
    '\\',           // no VK_ code
    ']',            // no VK_ code
    '\'',           // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_PROCESSKEY
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_ATTN
    0,          // VK_CRSEL
    0,          // VK_EXSEL
    0,          // VK_EREOF
    0,          // VK_PLAY
    0,          // VK_ZOOM
    0,          // VK_NONAME
    0,          // VK_PA1
    0,          // VK_OEM_CLEAR
    0           // no VK_ code
};

const int       WinDisplay::asciiShiftMap[] =
{
    0,          // no VK_ code
    0,          // VK_LBUTTON
    0,          // VK_RBUTTON
    0,          // VK_CANCEL
    0,          // VK_MBUTTON
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    8,          // VK_BACK
    9,          // VK_TAB
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_CLEAR
    13,         // VK_RETURN
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_SHIFT
    0,          // VK_CONTROL
    0,          // VK_MENU
    0,          // VK_PAUSE
    0,          // VK_CAPITAL
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    27,         // VK_ESCAPE
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    ' ',            // VK_SPACE
    0,          // VK_PRIOR
    0,          // VK_NEXT
    0,          // VK_END
    0,          // VK_HOME
    0,          // VK_LEFT
    0,          // VK_UP
    0,          // VK_RIGHT
    0,          // VK_DOWN
    0,          // VK_SELECT
    0,          // VK_PRINT
    0,          // VK_EXECUTE
    0,          // VK_SNAPSHOT
    0,          // VK_INSERT
    127,            // VK_DELETE
    0,          // VK_HELP
    ')',            // VK_0
    '!',            // VK_1
    '@',            // VK_2
    '#',            // VK_3
    '$',            // VK_4
    '%',            // VK_5
    '^',            // VK_6
    '&',            // VK_7
    '*',            // VK_8
    '(',            // VK_9
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    'a',            // VK_A
    'b',            // VK_B
    'c',            // VK_C
    'd',            // VK_D
    'e',            // VK_E
    'f',            // VK_F
    'g',            // VK_G
    'h',            // VK_H
    'i',            // VK_I
    'j',            // VK_J
    'k',            // VK_K
    'l',            // VK_L
    'm',            // VK_M
    'n',            // VK_N
    'o',            // VK_O
    'p',            // VK_P
    'q',            // VK_Q
    'r',            // VK_R
    's',            // VK_S
    't',            // VK_T
    'u',            // VK_U
    'v',            // VK_V
    'w',            // VK_W
    'x',            // VK_X
    'y',            // VK_Y
    'z',            // VK_Z
    0,          // VK_LWIN
    0,          // VK_RWIN
    0,          // VK_APPS
    0,          // no VK_ code
    0,          // no VK_ code
    '0',            // VK_NUMPAD0
    '1',            // VK_NUMPAD1
    '2',            // VK_NUMPAD2
    '3',            // VK_NUMPAD3
    '4',            // VK_NUMPAD4
    '5',            // VK_NUMPAD5
    '6',            // VK_NUMPAD6
    '7',            // VK_NUMPAD7
    '8',            // VK_NUMPAD8
    '9',            // VK_NUMPAD9
    '*',            // VK_MULTIPLY
    '+',            // VK_ADD
    0,          // VK_SEPARATOR
    '-',            // VK_SUBTRACT
    '.',            // VK_DECIMAL
    '/',            // VK_DIVIDE
    0,          // VK_F1
    0,          // VK_F2
    0,          // VK_F3
    0,          // VK_F4
    0,          // VK_F5
    0,          // VK_F6
    0,          // VK_F7
    0,          // VK_F8
    0,          // VK_F9
    0,          // VK_F10
    0,          // VK_F11
    0,          // VK_F12
    0,          // VK_F13
    0,          // VK_F14
    0,          // VK_F15
    0,          // VK_F16
    0,          // VK_F17
    0,          // VK_F18
    0,          // VK_F19
    0,          // VK_F20
    0,          // VK_F21
    0,          // VK_F22
    0,          // VK_F23
    0,          // VK_F24
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_NUMLOCK
    0,          // VK_SCROLL
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_LSHIFT
    0,          // VK_RSHIFT
    0,          // VK_LCONTROL
    0,          // VK_RCONTROL
    0,          // VK_LMENU
    0,          // VK_RMENU
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    ':',            // no VK_ code
    '+',            // no VK_ code
    '<',            // no VK_ code
    '_',            // no VK_ code
    '>',            // no VK_ code
    '?',            // no VK_ code
    '~',            // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    '{',            // no VK_ code
    '|',            // no VK_ code
    '}',            // no VK_ code
    '"',            // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_PROCESSKEY
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // no VK_ code
    0,          // VK_ATTN
    0,          // VK_CRSEL
    0,          // VK_EXSEL
    0,          // VK_EREOF
    0,          // VK_PLAY
    0,          // VK_ZOOM
    0,          // VK_NONAME
    0,          // VK_PA1
    0,          // VK_OEM_CLEAR
    0           // no VK_ code
};

const int       WinDisplay::buttonMap[] =
{
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_LBUTTON
    BzfKeyEvent::NoButton,  // VK_RBUTTON
    BzfKeyEvent::NoButton,  // VK_CANCEL
    BzfKeyEvent::NoButton,  // VK_MBUTTON
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_BACK
    BzfKeyEvent::NoButton,  // VK_TAB
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_CLEAR
    BzfKeyEvent::NoButton,  // VK_RETURN
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_SHIFT
    BzfKeyEvent::NoButton,  // VK_CONTROL
    BzfKeyEvent::NoButton,  // VK_MENU
    BzfKeyEvent::Pause, // VK_PAUSE
    BzfKeyEvent::NoButton,  // VK_CAPITAL
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_ESCAPE
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_SPACE
    BzfKeyEvent::PageUp,    // VK_PRIOR
    BzfKeyEvent::PageDown,  // VK_NEXT
    BzfKeyEvent::End,   // VK_END
    BzfKeyEvent::Home,  // VK_HOME
    BzfKeyEvent::Left,  // VK_LEFT
    BzfKeyEvent::Up,    // VK_UP
    BzfKeyEvent::Right, // VK_RIGHT
    BzfKeyEvent::Down,  // VK_DOWN
    BzfKeyEvent::NoButton,  // VK_SELECT
    BzfKeyEvent::NoButton,  // VK_PRINT
    BzfKeyEvent::NoButton,  // VK_EXECUTE
    BzfKeyEvent::NoButton,  // VK_SNAPSHOT
    BzfKeyEvent::Insert,    // VK_INSERT
    BzfKeyEvent::Delete,    // VK_DELETE
    BzfKeyEvent::NoButton,  // VK_HELP
    BzfKeyEvent::NoButton,  // VK_0
    BzfKeyEvent::NoButton,  // VK_1
    BzfKeyEvent::NoButton,  // VK_2
    BzfKeyEvent::NoButton,  // VK_3
    BzfKeyEvent::NoButton,  // VK_4
    BzfKeyEvent::NoButton,  // VK_5
    BzfKeyEvent::NoButton,  // VK_6
    BzfKeyEvent::NoButton,  // VK_7
    BzfKeyEvent::NoButton,  // VK_8
    BzfKeyEvent::NoButton,  // VK_9
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_A
    BzfKeyEvent::NoButton,  // VK_B
    BzfKeyEvent::NoButton,  // VK_C
    BzfKeyEvent::NoButton,  // VK_D
    BzfKeyEvent::NoButton,  // VK_E
    BzfKeyEvent::NoButton,  // VK_F
    BzfKeyEvent::NoButton,  // VK_G
    BzfKeyEvent::NoButton,  // VK_H
    BzfKeyEvent::NoButton,  // VK_I
    BzfKeyEvent::NoButton,  // VK_J
    BzfKeyEvent::NoButton,  // VK_K
    BzfKeyEvent::NoButton,  // VK_L
    BzfKeyEvent::NoButton,  // VK_M
    BzfKeyEvent::NoButton,  // VK_N
    BzfKeyEvent::NoButton,  // VK_O
    BzfKeyEvent::NoButton,  // VK_P
    BzfKeyEvent::NoButton,  // VK_Q
    BzfKeyEvent::NoButton,  // VK_R
    BzfKeyEvent::NoButton,  // VK_S
    BzfKeyEvent::NoButton,  // VK_T
    BzfKeyEvent::NoButton,  // VK_U
    BzfKeyEvent::NoButton,  // VK_V
    BzfKeyEvent::NoButton,  // VK_W
    BzfKeyEvent::NoButton,  // VK_X
    BzfKeyEvent::NoButton,  // VK_Y
    BzfKeyEvent::NoButton,  // VK_Z
    BzfKeyEvent::NoButton,  // VK_LWIN
    BzfKeyEvent::NoButton,  // VK_RWIN
    BzfKeyEvent::NoButton,  // VK_APPS
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_NUMPAD0
    BzfKeyEvent::NoButton,  // VK_NUMPAD1
    BzfKeyEvent::NoButton,  // VK_NUMPAD2
    BzfKeyEvent::NoButton,  // VK_NUMPAD3
    BzfKeyEvent::NoButton,  // VK_NUMPAD4
    BzfKeyEvent::NoButton,  // VK_NUMPAD5
    BzfKeyEvent::NoButton,  // VK_NUMPAD6
    BzfKeyEvent::NoButton,  // VK_NUMPAD7
    BzfKeyEvent::NoButton,  // VK_NUMPAD8
    BzfKeyEvent::NoButton,  // VK_NUMPAD9
    BzfKeyEvent::NoButton,  // VK_MULTIPLY
    BzfKeyEvent::NoButton,  // VK_ADD
    BzfKeyEvent::NoButton,  // VK_SEPARATOR
    BzfKeyEvent::NoButton,  // VK_SUBTRACT
    BzfKeyEvent::NoButton,  // VK_DECIMAL
    BzfKeyEvent::NoButton,  // VK_DIVIDE
    BzfKeyEvent::F1,    // VK_F1
    BzfKeyEvent::F2,    // VK_F2
    BzfKeyEvent::F3,    // VK_F3
    BzfKeyEvent::F4,    // VK_F4
    BzfKeyEvent::F5,    // VK_F5
    BzfKeyEvent::F6,    // VK_F6
    BzfKeyEvent::F7,    // VK_F7
    BzfKeyEvent::F8,    // VK_F8
    BzfKeyEvent::F9,    // VK_F9
    BzfKeyEvent::F10,   // VK_F10
    BzfKeyEvent::F11,   // VK_F11
    BzfKeyEvent::F12,   // VK_F12
    BzfKeyEvent::NoButton,  // VK_F13
    BzfKeyEvent::NoButton,  // VK_F14
    BzfKeyEvent::NoButton,  // VK_F15
    BzfKeyEvent::NoButton,  // VK_F16
    BzfKeyEvent::NoButton,  // VK_F17
    BzfKeyEvent::NoButton,  // VK_F18
    BzfKeyEvent::NoButton,  // VK_F19
    BzfKeyEvent::NoButton,  // VK_F20
    BzfKeyEvent::NoButton,  // VK_F21
    BzfKeyEvent::NoButton,  // VK_F22
    BzfKeyEvent::NoButton,  // VK_F23
    BzfKeyEvent::NoButton,  // VK_F24
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_NUMLOCK
    BzfKeyEvent::NoButton,  // VK_SCROLL
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_LSHIFT
    BzfKeyEvent::NoButton,  // VK_RSHIFT
    BzfKeyEvent::NoButton,  // VK_LCONTROL
    BzfKeyEvent::NoButton,  // VK_RCONTROL
    BzfKeyEvent::NoButton,  // VK_LMENU
    BzfKeyEvent::NoButton,  // VK_RMENU
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_PROCESSKEY
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // no VK_ code
    BzfKeyEvent::NoButton,  // VK_ATTN
    BzfKeyEvent::NoButton,  // VK_CRSEL
    BzfKeyEvent::NoButton,  // VK_EXSEL
    BzfKeyEvent::NoButton,  // VK_EREOF
    BzfKeyEvent::NoButton,  // VK_PLAY
    BzfKeyEvent::NoButton,  // VK_ZOOM
    BzfKeyEvent::NoButton,  // VK_NONAME
    BzfKeyEvent::NoButton,  // VK_PA1
    BzfKeyEvent::NoButton,  // VK_OEM_CLEAR
    BzfKeyEvent::NoButton   // no VK_ code
};

// Local Variables: ***
// mode: C++ ***
// tab-width: 4 ***
// c-basic-offset: 4 ***
// indent-tabs-mode: nil ***
// End: ***
// ex: shiftwidth=4 tabstop=4
