/* -*-c++-*- Producer - Copyright (C) 2001-2004  Don Burns
 *
 * This library is open source and may be redistributed and/or modified under
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * OpenSceneGraph Public License for more details.
 */

#ifndef PRODUCER_KEYBOARD
#define PRODUCER_KEYBOARD 1

#include <Producer/Export>
#include <Producer/Referenced>

#include <map>

#include <Producer/Types> 

#ifdef _X11_IMPLEMENTATION
#include <X11/keysym.h>
#endif




namespace Producer {

enum KeyboardKey {
    Key_Unknown,
    Key_Escape,
    Key_F1,
    Key_F2,
    Key_F3,
    Key_F4,
    Key_F5,
    Key_F6,
    Key_F7,
    Key_F8,
    Key_F9,
    Key_F10,
    Key_F11,
    Key_F12,
    Key_quoteleft,
    Key_1,
    Key_2,
    Key_3,
    Key_4,
    Key_5,
    Key_6,
    Key_7,
    Key_8,
    Key_9,
    Key_0,
    Key_minus,
    Key_equal,
    Key_BackSpace,
    Key_Tab,
    Key_A,
    Key_B,
    Key_C,
    Key_D,
    Key_E,
    Key_F,
    Key_G,
    Key_H ,
    Key_I,
    Key_J,
    Key_K,
    Key_L,
    Key_M,
    Key_N,
    Key_O,
    Key_P,
    Key_Q,
    Key_R,
    Key_S,
    Key_T,
    Key_U,
    Key_V,
    Key_W,
    Key_X,
    Key_Y,
    Key_Z,
    Key_bracketleft,
    Key_bracketright,
    Key_backslash,
    Key_Caps_Lock,
    Key_semicolon,
    Key_apostrophe,
    Key_Return,
    Key_Shift_L,
    Key_comma,
    Key_period,
    Key_slash,
    Key_Shift_R,
    Key_Control_L,
    Key_Super_L,
    Key_space,
    Key_Alt_L,
    Key_Alt_R,
    Key_Super_R,
    Key_Menu,
    Key_Control_R,
    Key_Print,
    Key_Scroll_Lock,
    Key_Pause,
    Key_Home,
    Key_Page_Up,
    Key_End,
    Key_Page_Down,
    Key_Delete,
    Key_Insert,
    Key_Left,
    Key_Up,
    Key_Right,
    Key_Down,
    Key_Num_Lock,
    Key_KP_Divide,
    Key_KP_Multiply,
    Key_KP_Subtract,
    Key_KP_Add,
    Key_KP_Home,
    Key_KP_Up,
    Key_KP_Page_Up,
    Key_KP_Left,
    Key_KP_Begin,
    Key_KP_Right,
    Key_KP_End,
    Key_KP_Down,
    Key_KP_Page_Down,
    Key_KP_Insert,
    Key_KP_Delete,
    Key_KP_Enter,
    Key_LAST_KEY
};

enum KeyModifier {
    KeyMod_NoModifier = 0x00000000,
    KeyMod_Shift      = 0x00010000,
    KeyMod_CapsLock   = 0x00020000,
    KeyMod_Control    = 0x00040000,
    KeyMod_NumLock    = 0x00080000,
    KeyMod_Alt        = 0x00100000,
    KeyMod_Super      = 0x00200000
};

enum KeyCharacter {
    KeyChar_Unknown             = 0x0000,
    KeyChar_space               = 0x020,
    KeyChar_exclam              = 0x021,
    KeyChar_quotedbl            = 0x022,
    KeyChar_numbersign          = 0x023,
    KeyChar_dollar              = 0x024,
    KeyChar_percent             = 0x025,
    KeyChar_ampersand           = 0x026,
    KeyChar_apostrophe          = 0x027,
    KeyChar_quoteright          = 0x027,
    KeyChar_parenleft           = 0x028,
    KeyChar_parenright          = 0x029,
    KeyChar_asterisk            = 0x02a,
    KeyChar_plus                = 0x02b,
    KeyChar_comma               = 0x02c,
    KeyChar_minus               = 0x02d,
    KeyChar_period              = 0x02e,
    KeyChar_slash               = 0x02f,
    KeyChar_0                   = 0x030,
    KeyChar_1                   = 0x031,
    KeyChar_2                   = 0x032,
    KeyChar_3                   = 0x033,
    KeyChar_4                   = 0x034,
    KeyChar_5                   = 0x035,
    KeyChar_6                   = 0x036,
    KeyChar_7                   = 0x037,
    KeyChar_8                   = 0x038,
    KeyChar_9                   = 0x039,
    KeyChar_colon               = 0x03a,
    KeyChar_semicolon           = 0x03b,
    KeyChar_less                = 0x03c,
    KeyChar_equal               = 0x03d,
    KeyChar_greater             = 0x03e,
    KeyChar_question            = 0x03f,
    KeyChar_at                  = 0x040,
    KeyChar_A                   = 0x041,
    KeyChar_B                   = 0x042,
    KeyChar_C                   = 0x043,
    KeyChar_D                   = 0x044,
    KeyChar_E                   = 0x045,
    KeyChar_F                   = 0x046,
    KeyChar_G                   = 0x047,
    KeyChar_H                   = 0x048,
    KeyChar_I                   = 0x049,
    KeyChar_J                   = 0x04a,
    KeyChar_K                   = 0x04b,
    KeyChar_L                   = 0x04c,
    KeyChar_M                   = 0x04d,
    KeyChar_N                   = 0x04e,
    KeyChar_O                   = 0x04f,
    KeyChar_P                   = 0x050,
    KeyChar_Q                   = 0x051,
    KeyChar_R                   = 0x052,
    KeyChar_S                   = 0x053,
    KeyChar_T                   = 0x054,
    KeyChar_U                   = 0x055,
    KeyChar_V                   = 0x056,
    KeyChar_W                   = 0x057,
    KeyChar_X                   = 0x058,
    KeyChar_Y                   = 0x059,
    KeyChar_Z                   = 0x05a,
    KeyChar_bracketleft         = 0x05b,
    KeyChar_backslash           = 0x05c,
    KeyChar_bracketright        = 0x05d,
    KeyChar_asciicircum         = 0x05e,
    KeyChar_underscore          = 0x05f,
    KeyChar_grave               = 0x060,
    KeyChar_quoteleft           = 0x060,
    KeyChar_a                   = 0x061,
    KeyChar_b                   = 0x062,
    KeyChar_c                   = 0x063,
    KeyChar_d                   = 0x064,
    KeyChar_e                   = 0x065,
    KeyChar_f                   = 0x066,
    KeyChar_g                   = 0x067,
    KeyChar_h                   = 0x068,
    KeyChar_i                   = 0x069,
    KeyChar_j                   = 0x06a,
    KeyChar_k                   = 0x06b,
    KeyChar_l                   = 0x06c,
    KeyChar_m                   = 0x06d,
    KeyChar_n                   = 0x06e,
    KeyChar_o                   = 0x06f,
    KeyChar_p                   = 0x070,
    KeyChar_q                   = 0x071,
    KeyChar_r                   = 0x072,
    KeyChar_s                   = 0x073,
    KeyChar_t                   = 0x074,
    KeyChar_u                   = 0x075,
    KeyChar_v                   = 0x076,
    KeyChar_w                   = 0x077,
    KeyChar_x                   = 0x078,
    KeyChar_y                   = 0x079,
    KeyChar_z                   = 0x07a,
    KeyChar_braceleft           = 0x07b,
    KeyChar_bar                 = 0x07c,
    KeyChar_braceright          = 0x07d,
    KeyChar_asciitilde          = 0x07e,
    KeyChar_nobreakspace        = 0x0a0,
    KeyChar_exclamdown          = 0x0a1,
    KeyChar_cent                = 0x0a2,
    KeyChar_sterling            = 0x0a3,
    KeyChar_currency            = 0x0a4,
    KeyChar_yen                 = 0x0a5,
    KeyChar_brokenbar           = 0x0a6,
    KeyChar_section             = 0x0a7,
    KeyChar_diaeresis           = 0x0a8,
    KeyChar_copyright           = 0x0a9,
    KeyChar_ordfeminine         = 0x0aa,
    KeyChar_guillemotleft       = 0x0ab,
    KeyChar_notsign             = 0x0ac,
    KeyChar_hyphen              = 0x0ad,
    KeyChar_registered          = 0x0ae,
    KeyChar_macron              = 0x0af,
    KeyChar_degree              = 0x0b0,
    KeyChar_plusminus           = 0x0b1,
    KeyChar_twosuperior         = 0x0b2,
    KeyChar_threesuperior       = 0x0b3,
    KeyChar_acute               = 0x0b4,
    KeyChar_mu                  = 0x0b5,
    KeyChar_paragraph           = 0x0b6,
    KeyChar_periodcentered      = 0x0b7,
    KeyChar_cedilla             = 0x0b8,
    KeyChar_onesuperior         = 0x0b9,
    KeyChar_masculine           = 0x0ba,
    KeyChar_guillemotright      = 0x0bb,
    KeyChar_onequarter          = 0x0bc,
    KeyChar_onehalf             = 0x0bd,
    KeyChar_threequarters       = 0x0be,
    KeyChar_questiondown        = 0x0bf,
    KeyChar_Agrave              = 0x0c0,
    KeyChar_Aacute              = 0x0c1,
    KeyChar_Acircumflex         = 0x0c2,
    KeyChar_Atilde              = 0x0c3,
    KeyChar_Adiaeresis          = 0x0c4,
    KeyChar_Aring               = 0x0c5,
    KeyChar_AE                  = 0x0c6,
    KeyChar_Ccedilla            = 0x0c7,
    KeyChar_Egrave              = 0x0c8,
    KeyChar_Eacute              = 0x0c9,
    KeyChar_Ecircumflex         = 0x0ca,
    KeyChar_Ediaeresis          = 0x0cb,
    KeyChar_Igrave              = 0x0cc,
    KeyChar_Iacute              = 0x0cd,
    KeyChar_Icircumflex         = 0x0ce,
    KeyChar_Idiaeresis          = 0x0cf,
    KeyChar_ETH                 = 0x0d0,
    KeyChar_Eth                 = 0x0d0,
    KeyChar_Ntilde              = 0x0d1,
    KeyChar_Ograve              = 0x0d2,
    KeyChar_Oacute              = 0x0d3,
    KeyChar_Ocircumflex         = 0x0d4,
    KeyChar_Otilde              = 0x0d5,
    KeyChar_Odiaeresis          = 0x0d6,
    KeyChar_multiply            = 0x0d7,
    KeyChar_Ooblique            = 0x0d8,
    KeyChar_Ugrave              = 0x0d9,
    KeyChar_Uacute              = 0x0da,
    KeyChar_Ucircumflex         = 0x0db,
    KeyChar_Udiaeresis          = 0x0dc,
    KeyChar_Yacute              = 0x0dd,
    KeyChar_THORN               = 0x0de,
    KeyChar_Thorn               = 0x0de,
    KeyChar_ssharp              = 0x0df,
    KeyChar_agrave              = 0x0e0,
    KeyChar_aacute              = 0x0e1,
    KeyChar_acircumflex         = 0x0e2,
    KeyChar_atilde              = 0x0e3,
    KeyChar_adiaeresis          = 0x0e4,
    KeyChar_aring               = 0x0e5,
    KeyChar_ae                  = 0x0e6,
    KeyChar_ccedilla            = 0x0e7,
    KeyChar_egrave              = 0x0e8,
    KeyChar_eacute              = 0x0e9,
    KeyChar_ecircumflex         = 0x0ea,
    KeyChar_ediaeresis          = 0x0eb,
    KeyChar_igrave              = 0x0ec,
    KeyChar_iacute              = 0x0ed,
    KeyChar_icircumflex         = 0x0ee,
    KeyChar_idiaeresis          = 0x0ef,
    KeyChar_eth                 = 0x0f0,
    KeyChar_ntilde              = 0x0f1,
    KeyChar_ograve              = 0x0f2,
    KeyChar_oacute              = 0x0f3,
    KeyChar_ocircumflex         = 0x0f4,
    KeyChar_otilde              = 0x0f5,
    KeyChar_odiaeresis          = 0x0f6,
    KeyChar_division            = 0x0f7,
    KeyChar_oslash              = 0x0f8,
    KeyChar_ugrave              = 0x0f9,
    KeyChar_uacute              = 0x0fa,
    KeyChar_ucircumflex         = 0x0fb,
    KeyChar_udiaeresis          = 0x0fc,
    KeyChar_yacute              = 0x0fd,
    KeyChar_thorn               = 0x0fe,
    KeyChar_ydiaeresis          = 0x0ff,
    KeyChar_BackSpace           = 0xFF08,
    KeyChar_Tab                 = 0xFF09,
    KeyChar_Linefeed            = 0xFF0A,
    KeyChar_Clear               = 0xFF0B,
    KeyChar_Return              = 0xFF0D,
    KeyChar_Pause               = 0xFF13,
    KeyChar_Scroll_Lock         = 0xFF14,
    KeyChar_Sys_Req             = 0xFF15,
    KeyChar_Escape              = 0xFF1B,
    KeyChar_Multi_key           = 0xFF20,
    KeyChar_Kanji               = 0xFF21,
    KeyChar_Muhenkan            = 0xFF22,
    KeyChar_Henkan_Mode         = 0xFF23,
    KeyChar_Henkan              = 0xFF23,
    KeyChar_Romaji              = 0xFF24,
    KeyChar_Hiragana            = 0xFF25,
    KeyChar_Katakana            = 0xFF26,
    KeyChar_Hiragana_Katakana   = 0xFF27,
    KeyChar_Zenkaku             = 0xFF28,
    KeyChar_Hankaku             = 0xFF29,
    KeyChar_Zenkaku_Hankaku     = 0xFF2A,
    KeyChar_Touroku             = 0xFF2B,
    KeyChar_Massyo              = 0xFF2C,
    KeyChar_Kana_Lock           = 0xFF2D,
    KeyChar_Kana_Shift          = 0xFF2E,
    KeyChar_Eisu_Shift          = 0xFF2F,
    KeyChar_Eisu_toggle         = 0xFF30,
    KeyChar_Codeinput           = 0xFF37,
    KeyChar_Kanji_Bangou        = 0xFF37,
    KeyChar_SingleCandidate     = 0xFF3C,
    KeyChar_MultipleCandidate   = 0xFF3D,
    KeyChar_Zen_Koho            = 0xFF3D,
    KeyChar_PreviousCandidate   = 0xFF3E,
    KeyChar_Mae_Koho            = 0xFF3E,
    KeyChar_Home                = 0xFF50,
    KeyChar_Left                = 0xFF51,
    KeyChar_Up                  = 0xFF52,
    KeyChar_Right               = 0xFF53,
    KeyChar_Down                = 0xFF54,
    KeyChar_Prior               = 0xFF55,
    KeyChar_Page_Up             = 0xFF55,
    KeyChar_Next                = 0xFF56,
    KeyChar_Page_Down           = 0xFF56,
    KeyChar_End                 = 0xFF57,
    KeyChar_Begin               = 0xFF58,
    KeyChar_Select              = 0xFF60,
    KeyChar_Print               = 0xFF61,
    KeyChar_Execute             = 0xFF62,
    KeyChar_Insert              = 0xFF63,
    KeyChar_Undo                = 0xFF65,
    KeyChar_Redo                = 0xFF66,
    KeyChar_Menu                = 0xFF67,
    KeyChar_Find                = 0xFF68,
    KeyChar_Cancel              = 0xFF69,
    KeyChar_Help                = 0xFF6A,
    KeyChar_Break               = 0xFF6B,
    KeyChar_Mode_switch         = 0xFF7E,
    KeyChar_script_switch       = 0xFF7E,
    KeyChar_kana_switch         = 0xFF7E,
    KeyChar_Arabic_switch       = 0xFF7E,
    KeyChar_Greek_switch        = 0xFF7E,
    KeyChar_Hebrew_switch       = 0xFF7E,
    KeyChar_Hangul_switch       = 0xFF7E,
    KeyChar_Num_Lock            = 0xFF7F,
    KeyChar_KP_Space            = 0xFF80,
    KeyChar_KP_Tab              = 0xFF89,
    KeyChar_KP_Enter            = 0xFF8D,
    KeyChar_KP_F1               = 0xFF91,
    KeyChar_KP_F2               = 0xFF92,
    KeyChar_KP_F3               = 0xFF93,
    KeyChar_KP_F4               = 0xFF94,
    KeyChar_KP_Home             = 0xFF95,
    KeyChar_KP_Left             = 0xFF96,
    KeyChar_KP_Up               = 0xFF97,
    KeyChar_KP_Right            = 0xFF98,
    KeyChar_KP_Down             = 0xFF99,
    KeyChar_KP_Prior            = 0xFF9A,
    KeyChar_KP_Page_Up          = 0xFF9A,
    KeyChar_KP_Next             = 0xFF9B,
    KeyChar_KP_Page_Down        = 0xFF9B,
    KeyChar_KP_End              = 0xFF9C,
    KeyChar_KP_Begin            = 0xFF9D,
    KeyChar_KP_Insert           = 0xFF9E,
    KeyChar_KP_Delete           = 0xFF9F,
    KeyChar_KP_Multiply         = 0xFFAA,
    KeyChar_KP_Add              = 0xFFAB,
    KeyChar_KP_Separator        = 0xFFAC,
    KeyChar_KP_Subtract         = 0xFFAD,
    KeyChar_KP_Decimal          = 0xFFAE,
    KeyChar_KP_Divide           = 0xFFAF,
    KeyChar_KP_0                = 0xFFB0,
    KeyChar_KP_1                = 0xFFB1,
    KeyChar_KP_2                = 0xFFB2,
    KeyChar_KP_3                = 0xFFB3,
    KeyChar_KP_4                = 0xFFB4,
    KeyChar_KP_5                = 0xFFB5,
    KeyChar_KP_6                = 0xFFB6,
    KeyChar_KP_7                = 0xFFB7,
    KeyChar_KP_8                = 0xFFB8,
    KeyChar_KP_9                = 0xFFB9,
    KeyChar_KP_Equal            = 0xFFBD,
    KeyChar_F1                  = 0xFFBE,
    KeyChar_F2                  = 0xFFBF,
    KeyChar_F3                  = 0xFFC0,
    KeyChar_F4                  = 0xFFC1,
    KeyChar_F5                  = 0xFFC2,
    KeyChar_F6                  = 0xFFC3,
    KeyChar_F7                  = 0xFFC4,
    KeyChar_F8                  = 0xFFC5,
    KeyChar_F9                  = 0xFFC6,
    KeyChar_F10                 = 0xFFC7,
    KeyChar_F11                 = 0xFFC8,
    KeyChar_L1                  = 0xFFC8,
    KeyChar_F12                 = 0xFFC9,
    KeyChar_L2                  = 0xFFC9,
    KeyChar_F13                 = 0xFFCA,
    KeyChar_L3                  = 0xFFCA,
    KeyChar_F14                 = 0xFFCB,
    KeyChar_L4                  = 0xFFCB,
    KeyChar_F15                 = 0xFFCC,
    KeyChar_L5                  = 0xFFCC,
    KeyChar_F16                 = 0xFFCD,
    KeyChar_L6                  = 0xFFCD,
    KeyChar_F17                 = 0xFFCE,
    KeyChar_L7                  = 0xFFCE,
    KeyChar_F18                 = 0xFFCF,
    KeyChar_L8                  = 0xFFCF,
    KeyChar_F19                 = 0xFFD0,
    KeyChar_L9                  = 0xFFD0,
    KeyChar_F20                 = 0xFFD1,
    KeyChar_L10                 = 0xFFD1,
    KeyChar_F21                 = 0xFFD2,
    KeyChar_R1                  = 0xFFD2,
    KeyChar_F22                 = 0xFFD3,
    KeyChar_R2                  = 0xFFD3,
    KeyChar_F23                 = 0xFFD4,
    KeyChar_R3                  = 0xFFD4,
    KeyChar_F24                 = 0xFFD5,
    KeyChar_R4                  = 0xFFD5,
    KeyChar_F25                 = 0xFFD6,
    KeyChar_R5                  = 0xFFD6,
    KeyChar_F26                 = 0xFFD7,
    KeyChar_R6                  = 0xFFD7,
    KeyChar_F27                 = 0xFFD8,
    KeyChar_R7                  = 0xFFD8,
    KeyChar_F28                 = 0xFFD9,
    KeyChar_R8                  = 0xFFD9,
    KeyChar_F29                 = 0xFFDA,
    KeyChar_R9                  = 0xFFDA,
    KeyChar_F30                 = 0xFFDB,
    KeyChar_R10                 = 0xFFDB,
    KeyChar_F31                 = 0xFFDC,
    KeyChar_R11                 = 0xFFDC,
    KeyChar_F32                 = 0xFFDD,
    KeyChar_R12                 = 0xFFDD,
    KeyChar_F33                 = 0xFFDE,
    KeyChar_R13                 = 0xFFDE,
    KeyChar_F34                 = 0xFFDF,
    KeyChar_R14                 = 0xFFDF,
    KeyChar_F35                 = 0xFFE0,
    KeyChar_R15                 = 0xFFE0,
    KeyChar_Shift_L             = 0xFFE1,
    KeyChar_Shift_R             = 0xFFE2,
    KeyChar_Control_L           = 0xFFE3,
    KeyChar_Control_R           = 0xFFE4,
    KeyChar_Caps_Lock           = 0xFFE5,
    KeyChar_Shift_Lock          = 0xFFE6,
    KeyChar_Meta_L              = 0xFFE7,
    KeyChar_Meta_R              = 0xFFE8,
    KeyChar_Alt_L               = 0xFFE9,
    KeyChar_Alt_R               = 0xFFEA,
    KeyChar_Super_L             = 0xFFEB,
    KeyChar_Super_R             = 0xFFEC,
    KeyChar_Hyper_L             = 0xFFED,
    KeyChar_Hyper_R             = 0xFFEE,
    KeyChar_Delete              = 0xFFFF
};

class PR_EXPORT KeyCombination
{
    public:
        KeyCombination(unsigned long keyModifier, KeyboardKey key):
                        _keyModifier(keyModifier),
                        _key(key)
                        {}

        unsigned long operator()() {return _keyModifier | _key;}

    private:
        unsigned long  _keyModifier;
        KeyboardKey    _key;
};


class PR_EXPORT Keyboard : public Producer::Referenced
{
    public:
        Keyboard(); 
        void *operator new( size_t size );
        static Keyboard *getSingleton();
        void mapKey( KeyCombination keyCombo, KeyCharacter keyChar );

        static bool isSpecialKey(KeyCharacter keychar );

        friend class KeyboardMouseImplementation;
        friend class RenderSurface;

    protected:
        virtual ~Keyboard() {}

    private:
        static Keyboard *theKeyboard;
        void _initKeyboardKeyMap();
        void _initKeyCharMap();
        unsigned long _keyModifier;
        std::map <KeySymbol,KeyboardKey> _keymap;
        std::map <unsigned long, KeyCharacter> _charmap;

#ifdef _X11_IMPLEMENTATION
        KeyCharacter xkeyEventToKeyChar(Display *dpy, XKeyEvent &ev);
#endif

#ifdef _WIN32_IMPLEMENTATION
        KeyCharacter win32KeyEventToKeyChar( LPARAM lParam, WPARAM wParam );
#endif

#ifdef _OSX_CGL_IMPLEMENTATION
        KeyCharacter Keyboard::akeyEventToKeyChar(unsigned long key);
#endif
};

class PR_EXPORT KeyboardProxy
{
    public:
        KeyboardProxy() { Keyboard::getSingleton(); }
};

}

#endif
