//======================================================================== // GLFW - An OpenGL framework // File: dos_keyboard.c // Platform: DOS // API version: 2.6 // WWW: http://glfw.sourceforge.net //------------------------------------------------------------------------ // Copyright (c) 2002-2006 Camilla Berglund // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any damages // arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must not // claim that you wrote the original software. If you use this software // in a product, an acknowledgment in the product documentation would // be appreciated but is not required. // // 2. Altered source versions must be plainly marked as such, and must not // be misrepresented as being the original software. // // 3. This notice may not be removed or altered from any source // distribution. // //======================================================================== #include "internal.h" //======================================================================== // Most of the code in this source file is based on two sources of // information: // 1) The Allegro DOS keyboard driver (allegro\src\dos\dkeybd.c) // 2) The document "IBM PC KEYBOARD INFORMATION FOR SOFTWARE DEVELOPERS" // by Chris Giese. //======================================================================== //======================================================================== // Unicode in GLFW for DOS // ======================= // // Keyboard mapping tables in GLFW for DOS use Unicode encoding. The codes // are 16-bit unsigned integers, and thus do not cover the entire Unicode // standard (but a great deal is covered). // // Keys or characters that are not supported by GLFW (for instance the // PrtScr or Windows keys that are found on most PC keyboards) are coded // with 0xFFFF ("not a character" according to the Unicode standard). // // GLFW special keys, as defined in glfw.h (e.g. GLFW_KEY_LSHIFT) are // encoded in the private area of the Unicode standard (i.e. codes in the // range E000-F8FF). The encoding is as follows: // // unicode = 0xE000 + glfw_key - GLFW_KEY_SPECIAL; // // Every key in the keyboard matrix has a description consisting of four // entries: Normal, Shift, Caps, and AltGr. //======================================================================== //======================================================================== // Definitions //======================================================================== // Keyboard interrupt number #define KEYB_IRQ 1 // Qualifier flags #define QUAL_SCROLOCK 0x0001 // Same bits as for controller cmd 0xED #define QUAL_NUMLOCK 0x0002 // (set leds) #define QUAL_CAPSLOCK 0x0004 // --"-- #define QUAL_LSHIFT 0x0008 #define QUAL_RSHIFT 0x0010 #define QUAL_LALT 0x0020 #define QUAL_RALT 0x0040 #define QUAL_LCTRL 0x0080 #define QUAL_RCTRL 0x0100 // Qualifier groups #define QUAL_MODIFIERS (QUAL_LSHIFT|QUAL_RSHIFT|QUAL_LALT|QUAL_RALT|\ QUAL_LCTRL|QUAL_RCTRL) #define QUAL_LEDS (QUAL_SCROLOCK|QUAL_NUMLOCK|QUAL_CAPSLOCK) // Additional non-GLFW keys, defined here for internal processing only #define GLFW_KEY_CAPSLOCK (GLFW_KEY_SPECIAL+0x0200) #define GLFW_KEY_NUMLOCK (GLFW_KEY_SPECIAL+0x0201) #define GLFW_KEY_SCROLOCK (GLFW_KEY_SPECIAL+0x0202) #define GLFW_KEY_PAUSE (GLFW_KEY_SPECIAL+0x0203) // Keymap entry definition struct key { unsigned short Normal, Caps, Shift, AltGr; }; // Keymap entry macros #define NOCHAR(x) {x+0xDF00,x+0xDF00,x+0xDF00,x+0xDF00} #define UNDEFINED {0xFFFF,0xFFFF,0xFFFF,0xFFFF} //======================================================================== // Global variables //======================================================================== static struct { int volatile KeyEnhanced, KeyPauseLoop, Qualifiers; int LedsOK; int Interrupt; } _glfwKeyDrv; static int _glfwKeyboardInstalled = 0; //======================================================================== // scancode_to_key_us[] - Mapping table for US keyboard layout (XT) //======================================================================== static struct key scancode_to_key_us[256] = { /* Standard hardware scancodes */ /* 0x00 */ UNDEFINED, NOCHAR(GLFW_KEY_ESC), /* 0x02 */ {'1','1','!',0xFFFF}, {'2','2','@',0xFFFF}, /* 0x04 */ {'3','3','#',0xFFFF}, {'4','4','$',0xFFFF}, /* 0x06 */ {'5','5','%',0xFFFF}, {'6','6','^',0xFFFF}, /* 0x08 */ {'7','7','&',0xFFFF}, {'8','8','*',0xFFFF}, /* 0x0A */ {'9','9','(',0xFFFF}, {'0','0',')',0xFFFF}, /* 0x0C */ {'-','-','_',0xFFFF}, {'=','=','+',0xFFFF}, /* 0x0E */ NOCHAR(GLFW_KEY_BACKSPACE), NOCHAR(GLFW_KEY_TAB), /* 0x10 */ {'q','Q','Q',0xFFFF}, {'w','W','W',0xFFFF}, /* 0x12 */ {'e','E','E',0xFFFF}, {'r','R','R',0xFFFF}, /* 0x14 */ {'t','T','T',0xFFFF}, {'y','Y','Y',0xFFFF}, /* 0x16 */ {'u','U','U',0xFFFF}, {'i','I','I',0xFFFF}, /* 0x18 */ {'o','O','O',0xFFFF}, {'p','P','P',0xFFFF}, /* 0x1A */ {'[','[','{',0xFFFF}, {']',']','}',0xFFFF}, /* 0x1C */ NOCHAR(GLFW_KEY_ENTER), NOCHAR(GLFW_KEY_LCTRL), /* 0x1E */ {'a','A','A',0xFFFF}, {'s','S','S',0xFFFF}, /* 0x20 */ {'d','D','D',0xFFFF}, {'f','F','F',0xFFFF}, /* 0x22 */ {'g','G','G',0xFFFF}, {'h','H','H',0xFFFF}, /* 0x24 */ {'j','J','J',0xFFFF}, {'k','K','K',0xFFFF}, /* 0x26 */ {'l','L','L',0xFFFF}, {';',';',':',0xFFFF}, /* 0x28 */ {'\'','\'','"',0xFFFF}, {'\\','\\','|',0xFFFF}, /* 0x2A */ NOCHAR(GLFW_KEY_LSHIFT), {'\\','\\','|',0xFFFF}, /* 0x2C */ {'z','Z','Z',0xFFFF}, {'x','X','X',0xFFFF}, /* 0x2E */ {'c','C','C',0xFFFF}, {'v','V','V',0xFFFF}, /* 0x30 */ {'b','B','B',0xFFFF}, {'n','N','N',0xFFFF}, /* 0x32 */ {'m','M','M',0xFFFF}, {',',',','<',0xFFFF}, /* 0x34 */ {'.','.','>',0xFFFF}, {'/','/','?',0xFFFF}, /* 0x36 */ NOCHAR(GLFW_KEY_RSHIFT), NOCHAR(GLFW_KEY_KP_MULTIPLY), /* 0x38 */ NOCHAR(GLFW_KEY_LALT), {' ',' ',' ',0xFFFF}, /* 0x3A */ NOCHAR(GLFW_KEY_CAPSLOCK), NOCHAR(GLFW_KEY_F1), /* 0x3C */ NOCHAR(GLFW_KEY_F2), NOCHAR(GLFW_KEY_F3), /* 0x3E */ NOCHAR(GLFW_KEY_F4), NOCHAR(GLFW_KEY_F5), /* 0x40 */ NOCHAR(GLFW_KEY_F6), NOCHAR(GLFW_KEY_F7), /* 0x42 */ NOCHAR(GLFW_KEY_F8), NOCHAR(GLFW_KEY_F9), /* 0x44 */ NOCHAR(GLFW_KEY_F10), NOCHAR(GLFW_KEY_NUMLOCK), /* 0x46 */ NOCHAR(GLFW_KEY_SCROLOCK), NOCHAR(GLFW_KEY_KP_7), /* 0x48 */ NOCHAR(GLFW_KEY_KP_8), NOCHAR(GLFW_KEY_KP_9), /* 0x4A */ NOCHAR(GLFW_KEY_KP_SUBTRACT), NOCHAR(GLFW_KEY_KP_4), /* 0x4C */ NOCHAR(GLFW_KEY_KP_5), NOCHAR(GLFW_KEY_KP_6), /* 0x4E */ NOCHAR(GLFW_KEY_KP_ADD), NOCHAR(GLFW_KEY_KP_1), /* 0x50 */ NOCHAR(GLFW_KEY_KP_2), NOCHAR(GLFW_KEY_KP_3), /* 0x52 */ NOCHAR(GLFW_KEY_KP_0), NOCHAR(GLFW_KEY_KP_DECIMAL), /* 0x54 */ UNDEFINED, /* PRTSCR */ UNDEFINED, /* 0x56 */ {'\\','\\','|',0xFFFF}, NOCHAR(GLFW_KEY_F11), /* 0x58 */ NOCHAR(GLFW_KEY_F12), UNDEFINED, /* 0x5A */ UNDEFINED, UNDEFINED, /* LWIN */ /* 0x5C */ UNDEFINED, /* RWIN */ UNDEFINED, /* MENU */ /* 0x5E */ UNDEFINED, UNDEFINED, /* 0x60 */ UNDEFINED, UNDEFINED, /* 0x62 */ UNDEFINED, UNDEFINED, /* 0x64 */ UNDEFINED, UNDEFINED, /* 0x66 */ UNDEFINED, UNDEFINED, /* 0x68 */ UNDEFINED, UNDEFINED, /* 0x6A */ UNDEFINED, UNDEFINED, /* 0x6C */ UNDEFINED, UNDEFINED, /* 0x6E */ UNDEFINED, UNDEFINED, /* 0x70 */ UNDEFINED, /* KANA */ UNDEFINED, /* 0x72 */ UNDEFINED, UNDEFINED, /* ABNT_C1 */ /* 0x74 */ UNDEFINED, UNDEFINED, /* 0x76 */ UNDEFINED, UNDEFINED, /* 0x78 */ UNDEFINED, UNDEFINED, /* CONVERT */ /* 0x7A */ UNDEFINED, UNDEFINED, /* NOCONVERT */ /* 0x7C */ UNDEFINED, UNDEFINED, /* YEN */ /* 0x7E */ UNDEFINED, UNDEFINED, /* Extended hardware scancodes (index=scancode+0x80) */ /* 0xE000 */ UNDEFINED, NOCHAR(GLFW_KEY_ESC), /* 0xE002 */ {'1','1','!',0xFFFF}, {'2','2','@',0xFFFF}, /* 0xE004 */ {'3','3','#',0xFFFF}, {'4','4','$',0xFFFF}, /* 0xE006 */ {'5','5','%',0xFFFF}, {'6','6','^',0xFFFF}, /* 0xE008 */ {'7','7','&',0xFFFF}, {'8','8','*',0xFFFF}, /* 0xE00A */ {'9','9','(',0xFFFF}, {'0','0',')',0xFFFF}, /* 0xE00C */ {'-','-','_',0xFFFF}, {'=','=','+',0xFFFF}, /* 0xE00E */ NOCHAR(GLFW_KEY_BACKSPACE), NOCHAR(GLFW_KEY_TAB), /* 0xE010 */ UNDEFINED, /* CIRCUMFLEX */ UNDEFINED, /* AT */ /* 0xE012 */ UNDEFINED, /* COLON2 */ {'r','R','R',0xFFFF}, /* 0xE014 */ UNDEFINED, /* KANJI */ {'y','Y','Y',0xFFFF}, /* 0xE016 */ {'u','U','U',0xFFFF}, {'i','I','I',0xFFFF}, /* 0xE018 */ {'o','O','O',0xFFFF}, {'p','P','P',0xFFFF}, /* 0xE01A */ {'[','[','{',0xFFFF}, {']',']','}',0xFFFF}, /* 0xE01C */ NOCHAR(GLFW_KEY_KP_ENTER), NOCHAR(GLFW_KEY_RCTRL), /* 0xE01E */ {'a','A','A',0xFFFF}, {'s','S','S',0xFFFF}, /* 0xE020 */ {'d','D','D',0xFFFF}, {'f','F','F',0xFFFF}, /* 0xE022 */ {'g','G','G',0xFFFF}, {'h','H','H',0xFFFF}, /* 0xE024 */ {'j','J','J',0xFFFF}, {'k','K','K',0xFFFF}, /* 0xE026 */ {'l','L','L',0xFFFF}, {';',';',':',0xFFFF}, /* 0xE028 */ {'\'','\'','"',0xFFFF}, {'`','`','~',0xFFFF}, /* 0xE02A */ UNDEFINED, {'\\','\\','|',0xFFFF}, /* 0xE02C */ {'z','Z','Z',0xFFFF}, {'x','X','X',0xFFFF}, /* 0xE02E */ {'c','C','C',0xFFFF}, {'v','V','V',0xFFFF}, /* 0xE030 */ {'b','B','B',0xFFFF}, {'n','N','N',0xFFFF}, /* 0xE032 */ {'m','M','M',0xFFFF}, {',',',','<',0xFFFF}, /* 0xE034 */ {'.','.','>',0xFFFF}, NOCHAR(GLFW_KEY_KP_DIVIDE), /* 0xE036 */ UNDEFINED, UNDEFINED, /* PRTSCR */ /* 0xE038 */ NOCHAR(GLFW_KEY_RALT), {' ',' ',' ',0xFFFF}, /* 0xE03A */ NOCHAR(GLFW_KEY_CAPSLOCK), NOCHAR(GLFW_KEY_F1), /* 0xE03C */ NOCHAR(GLFW_KEY_F2), NOCHAR(GLFW_KEY_F3), /* 0xE03E */ NOCHAR(GLFW_KEY_F4), NOCHAR(GLFW_KEY_F5), /* 0xE040 */ NOCHAR(GLFW_KEY_F6), NOCHAR(GLFW_KEY_F7), /* 0xE042 */ NOCHAR(GLFW_KEY_F8), NOCHAR(GLFW_KEY_F9), /* 0xE044 */ NOCHAR(GLFW_KEY_F10), NOCHAR(GLFW_KEY_NUMLOCK), /* 0xE046 */ NOCHAR(GLFW_KEY_PAUSE), NOCHAR(GLFW_KEY_HOME), /* 0xE048 */ NOCHAR(GLFW_KEY_UP), NOCHAR(GLFW_KEY_PAGEUP), /* 0xE04A */ NOCHAR(GLFW_KEY_KP_SUBTRACT), NOCHAR(GLFW_KEY_LEFT), /* 0xE04C */ NOCHAR(GLFW_KEY_KP_5), NOCHAR(GLFW_KEY_RIGHT), /* 0xE04E */ NOCHAR(GLFW_KEY_KP_ADD), NOCHAR(GLFW_KEY_END), /* 0xE050 */ NOCHAR(GLFW_KEY_DOWN), NOCHAR(GLFW_KEY_PAGEDOWN), /* 0xE052 */ NOCHAR(GLFW_KEY_INSERT), NOCHAR(GLFW_KEY_DEL), /* 0xE054 */ UNDEFINED, /* PRTSCR */ UNDEFINED, /* 0xE056 */ {'\\','\\','|',0xFFFF}, NOCHAR(GLFW_KEY_F11), /* 0xE058 */ NOCHAR(GLFW_KEY_F12), UNDEFINED, /* 0xE05A */ UNDEFINED, UNDEFINED, /* LWIN */ /* 0xE05C */ UNDEFINED, /* RWIN */ UNDEFINED, /* MENU */ /* 0xE05E */ UNDEFINED, UNDEFINED, /* 0xE060 */ UNDEFINED, UNDEFINED, /* 0xE062 */ UNDEFINED, UNDEFINED, /* 0xE064 */ UNDEFINED, UNDEFINED, /* 0xE066 */ UNDEFINED, UNDEFINED, /* 0xE068 */ UNDEFINED, UNDEFINED, /* 0xE06A */ UNDEFINED, UNDEFINED, /* 0xE06C */ UNDEFINED, UNDEFINED, /* 0xE06E */ UNDEFINED, UNDEFINED, /* 0xE070 */ UNDEFINED, UNDEFINED, /* 0xE072 */ UNDEFINED, UNDEFINED, /* 0xE074 */ UNDEFINED, UNDEFINED, /* 0xE076 */ UNDEFINED, UNDEFINED, /* 0xE078 */ UNDEFINED, UNDEFINED, /* 0xE07A */ UNDEFINED, UNDEFINED, /* 0xE07C */ UNDEFINED, UNDEFINED, /* 0xE07E */ UNDEFINED, UNDEFINED }; //************************************************************************ //**** Keyboard Decoding ************************************************* //************************************************************************ //======================================================================== // _glfwMapRawKey() - Map a raw scancode to a Unicode character //======================================================================== static int _glfwMapRawKey( int scancode, int qualifiers ) { struct key *keyvals; int keycode; // Get possible key codings for this scancode keyvals = &scancode_to_key_us[ scancode ]; // Select Unicode code depending on qualifiers if( qualifiers & QUAL_RALT ) { keycode = keyvals->AltGr; } else if( qualifiers & (QUAL_LSHIFT|QUAL_RSHIFT) ) { if( (qualifiers & QUAL_CAPSLOCK) && (keyvals->Normal != keyvals->Caps) ) { keycode = keyvals->Normal; } else { keycode = keyvals->Shift; } } else if( qualifiers & QUAL_CAPSLOCK ) { keycode = keyvals->Caps; } else { keycode = keyvals->Normal; } // Special interpretations if( keycode >= 0xE000 && keycode <= 0xE8FF ) { keycode = -(keycode - 0xE000 + GLFW_KEY_SPECIAL); } else if( keycode == 0xFFFF ) { keycode = 0; } return keycode; } ENDOFUNC(_glfwMapRawKey) //======================================================================== // _glfwCreateKeyEvent() - Add a keyboard event to the event FIFO //======================================================================== static void _glfwCreateKeyEvent( int scancode, int qualifiers, int action ) { _GLFWdosevent event; struct key_event *key = &event.Key; // Create event key->Type = _GLFW_DOS_KEY_EVENT; key->Key = _glfwMapRawKey( scancode, qualifiers ); key->KeyNoMod = _glfwMapRawKey( scancode, QUAL_CAPSLOCK ); key->Action = action; // Post event _glfwPostDOSEvent( &event ); } ENDOFUNC(_glfwCreateKeyEvent) //************************************************************************ //**** Keyboard Communication ******************************************** //************************************************************************ //======================================================================== // _glfwWaitForReadReady() / _glfwWaitForWriteReady() // Wait for the keyboard controller to set the ready-for-read/write bit //======================================================================== static int _glfwWaitForReadReady( void ) { int timeout = 16384; while( (timeout>0) && (!(inportb(0x64)&1)) ) timeout--; return timeout > 0; } ENDOFUNC(_glfwWaitForReadReady) static int _glfwWaitForWriteReady( void ) { int timeout = 4096; while( (timeout>0) && (inportb(0x64)&2) ) timeout--; return timeout > 0; } ENDOFUNC(_glfwWaitForWriteReady) //======================================================================== // _glfwSendKeyboardByte() - Send a byte to the keyboard controller //======================================================================== static int _glfwSendKeyboardByte( unsigned char data ) { int resends = 4; int timeout, ret; do { if( !_glfwWaitForWriteReady() ) return 0; outportb( 0x60, data ); timeout = 4096; while( --timeout > 0 ) { if( !_glfwWaitForReadReady() ) return 0; ret = inportb( 0x60 ); if( ret == 0xFA ) return 1; if( ret == 0xFE ) break; } } while( (resends-- > 0) && (timeout > 0) ); return 0; } ENDOFUNC(_glfwSendKeyboardByte) //======================================================================== // _glfwSendKeyboardCommand() - Send a command sequence to the keyboard //======================================================================== static int _glfwSendKeyboardCommand( unsigned char *cmd, int count ) { int i, ok = 1; // Force atomic keyboard communication session if( !_glfwKeyDrv.Interrupt ) DISABLE(); // Send command sequence for( i = 0; i < count; ++ i ) { if( !_glfwSendKeyboardByte( cmd[i] ) ) { ok = 0; break; } } // Send "clear output buffer, enable keyboard" _glfwSendKeyboardByte( 0xF4 ); if( !_glfwKeyDrv.Interrupt ) ENABLE(); return ok; } ENDOFUNC(_glfwSendKeyboardCommand) //************************************************************************ //**** Miscellaneous Handling ******************************************** //************************************************************************ //======================================================================== // _glfwUpdateLeds() - Update keyboard leds //======================================================================== static void _glfwUpdateLeds( int qualifiers ) { unsigned char cmd[2]; cmd[0] = 0xED; cmd[1] = qualifiers & 7; _glfwSendKeyboardCommand( cmd, 2 ); } ENDOFUNC(_glfwUpdateLeds) //************************************************************************ //**** Keyboard Interrupt Handler **************************************** //************************************************************************ //======================================================================== // _glfwHandleCode() - Handle new scancode event //======================================================================== static void _glfwHandleCode( int scancode, int keypress ) { if( scancode == GLFW_KEY_PAUSE && keypress ) { // Pause _glfwCreateKeyEvent( GLFW_KEY_PAUSE, 0, GLFW_PRESS ); } else if( scancode ) { int tmp, qualifier; // Check if this is a qualifier key tmp = scancode_to_key_us[scancode].Normal; tmp += GLFW_KEY_SPECIAL - 0xE000; if( tmp == GLFW_KEY_LSHIFT ) qualifier = QUAL_LSHIFT; else if( tmp == GLFW_KEY_RSHIFT ) qualifier = QUAL_RSHIFT; else if( tmp == GLFW_KEY_LCTRL ) qualifier = QUAL_LCTRL; else if( tmp == GLFW_KEY_RCTRL ) qualifier = QUAL_RCTRL; else if( tmp == GLFW_KEY_LALT ) qualifier = QUAL_LALT; else if( tmp == GLFW_KEY_RALT ) qualifier = QUAL_RALT; else if( tmp == GLFW_KEY_NUMLOCK ) qualifier = QUAL_NUMLOCK; else if( tmp == GLFW_KEY_SCROLOCK ) qualifier = QUAL_SCROLOCK; else if( tmp == GLFW_KEY_CAPSLOCK ) qualifier = QUAL_CAPSLOCK; else qualifier = 0; if( keypress ) { // Key press if( qualifier & QUAL_MODIFIERS ) { _glfwKeyDrv.Qualifiers |= qualifier; } if( !(qualifier & QUAL_LEDS) ) { _glfwCreateKeyEvent( scancode, _glfwKeyDrv.Qualifiers, GLFW_PRESS ); } else { _glfwKeyDrv.Qualifiers ^= qualifier; _glfwUpdateLeds( _glfwKeyDrv.Qualifiers ); } } else { // Key release if( qualifier & QUAL_MODIFIERS ) { _glfwKeyDrv.Qualifiers &= ~qualifier; } if( !(qualifier & QUAL_LEDS) ) { _glfwCreateKeyEvent( scancode, _glfwKeyDrv.Qualifiers, GLFW_RELEASE ); } } } } ENDOFUNC(_glfwHandleCode) //======================================================================== // _glfwKeyInterrupt() - Keyboard interrupt routine //======================================================================== static int _glfwKeyInterrupt( void ) { unsigned char keycode, scancode; _glfwKeyDrv.Interrupt ++; keycode = inportb( 0x60 ); if( keycode <= 0xE1 ) { if( _glfwKeyDrv.KeyPauseLoop ) { if( ! --_glfwKeyDrv.KeyPauseLoop ) _glfwHandleCode( GLFW_KEY_PAUSE, 1 ); } else { switch( keycode ) { case 0xE0: _glfwKeyDrv.KeyEnhanced = 1; break; case 0xE1: _glfwKeyDrv.KeyPauseLoop = 5; break; default: scancode = keycode & 0x7F; if( _glfwKeyDrv.KeyEnhanced ) { scancode |= 0x80; _glfwKeyDrv.KeyEnhanced = 0; } _glfwHandleCode( scancode, !(keycode & 0x80) ); } } } _glfwKeyDrv.Interrupt --; if( ((keycode==0x4F) || (keycode==0x53)) && (_glfwKeyDrv.Qualifiers & QUAL_LCTRL) && (_glfwKeyDrv.Qualifiers & QUAL_RALT) ) { // Hack alert: // Only SIGINT (but not Ctrl-Break) calls the destructors and will // safely clean up asm( "movb $0x79,%%al\n\t" "call ___djgpp_hw_exception\n\t" : : : "%eax", "%ebx", "%ecx", "%edx", "%esi", "%edi", "memory" ); } asm( "inb $0x61,%%al\n\t" "movb %%al,%%ah\n\t" "orb $0x80,%%al\n\t" "outb %%al,$0x61\n\t" "xchgb %%al,%%ah\n\t" "outb %%al,$0x61\n\t" "movb $0x20,%%al\n\t" "outb %%al,$0x20\n\t" : : : "%eax" ); return 0; } ENDOFUNC(_glfwKeyInterrupt) //************************************************************************ //**** Keyboard driver interface functions **** //************************************************************************ //======================================================================== // _glfwInitKeyboard() - Initialize keyboard driver //======================================================================== int _glfwInitKeyboard( void ) { int s1, s2, s3; if( _glfwKeyboardInstalled ) { return 0; } // Init keyboard state _glfwKeyDrv.LedsOK = 1; _glfwKeyDrv.Interrupt = 0; _glfwKeyDrv.KeyEnhanced = 0; _glfwKeyDrv.KeyPauseLoop = 0; // Lock data buffers LOCKDATA(_glfwKeyboardInstalled); LOCKDATA(_glfwKeyDrv); LOCKDATA(scancode_to_key_us); // Lock functions LOCKFUNC(_glfwMapRawKey); LOCKFUNC(_glfwCreateKeyEvent); LOCKFUNC(_glfwWaitForReadReady); LOCKFUNC(_glfwWaitForWriteReady); LOCKFUNC(_glfwSendKeyboardByte); LOCKFUNC(_glfwSendKeyboardCommand); LOCKFUNC(_glfwUpdateLeds); LOCKFUNC(_glfwHandleCode); LOCKFUNC(_glfwKeyInterrupt); _farsetsel( __djgpp_dos_sel ); _farnspokew( 0x41c, _farnspeekw(0x41a) ); // Get current state of key qualifiers s1 = _farnspeekb( 0x417 ); s2 = _farnspeekb( 0x418 ); s3 = _farnspeekb( 0x496 ); _glfwKeyDrv.Qualifiers = 0; if( s1 & 1 ) _glfwKeyDrv.Qualifiers |= QUAL_RSHIFT; if( s1 & 2 ) _glfwKeyDrv.Qualifiers |= QUAL_LSHIFT; if( s2 & 1 ) _glfwKeyDrv.Qualifiers |= QUAL_LCTRL; if( s2 & 2 ) _glfwKeyDrv.Qualifiers |= QUAL_LALT; if( s3 & 4 ) _glfwKeyDrv.Qualifiers |= QUAL_RCTRL; if( s3 & 8 ) _glfwKeyDrv.Qualifiers |= QUAL_RALT; if( s1 & 16 ) _glfwKeyDrv.Qualifiers |= QUAL_SCROLOCK; if( s1 & 32 ) _glfwKeyDrv.Qualifiers |= QUAL_NUMLOCK; if( s1 & 64 ) _glfwKeyDrv.Qualifiers |= QUAL_CAPSLOCK; _glfwUpdateLeds( _glfwKeyDrv.Qualifiers ); // Install keyboard interrupt handler if( _glfwInstallDOSIrq( KEYB_IRQ, _glfwKeyInterrupt ) ) { return 0; } _glfwKeyboardInstalled = 1; return 1; } //======================================================================== // _glfwTerminateKeyboard() - Terminate keyboard driver //======================================================================== void _glfwTerminateKeyboard( void ) { int s1, s2, s3; if( !_glfwKeyboardInstalled ) { return; } _glfwKeyboardInstalled = 0; // Uninstall keyboard interrupt handler _glfwRemoveDOSIrq( KEYB_IRQ ); _farsetsel( __djgpp_dos_sel ); _farnspokew( 0x41c, _farnspeekw(0x41a) ); // Set current state of key qualifiers s1 = _farnspeekb( 0x417 ) & 0x80; s2 = _farnspeekb( 0x418 ) & 0xFC; s3 = _farnspeekb( 0x496 ) & 0xF3; if(_glfwKeyDrv.Qualifiers & QUAL_RSHIFT) s1 |= 1; if(_glfwKeyDrv.Qualifiers & QUAL_LSHIFT) s1 |= 2; if(_glfwKeyDrv.Qualifiers & QUAL_LCTRL) {s2 |= 1; s1 |= 4;} if(_glfwKeyDrv.Qualifiers & QUAL_LALT) {s2 |= 2; s1 |= 8;} if(_glfwKeyDrv.Qualifiers & QUAL_RCTRL) {s3 |= 4; s1 |= 4;} if(_glfwKeyDrv.Qualifiers & QUAL_RALT) {s3 |= 8; s1 |= 8;} if(_glfwKeyDrv.Qualifiers & QUAL_SCROLOCK) s1 |= 16; if(_glfwKeyDrv.Qualifiers & QUAL_NUMLOCK) s1 |= 32; if(_glfwKeyDrv.Qualifiers & QUAL_CAPSLOCK) s1 |= 64; _farnspokeb( 0x417, s1 ); _farnspokeb( 0x418, s2 ); _farnspokeb( 0x496, s3 ); _glfwUpdateLeds( _glfwKeyDrv.Qualifiers ); }