// This may look like C code, but it is really -*- C++ -*- // ------------------------------------------------------------------ // The Goldware Library // Copyright (C) 1990-1999 Odinn Sorensen // Copyright (C) 1999-2000 Alexander S. Aganichev // Copyright (C) 2000 Jacobo Tarrio // ------------------------------------------------------------------ // This library is free software; you can redistribute it and/or // modify it under the terms of the GNU Library General Public // License as published by the Free Software Foundation; either // version 2 of the License, or (at your option) any later version. // // 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 GNU // Library General Public License for more details. // // You should have received a copy of the GNU Library General Public // License along with this program; if not, write to the Free // Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, // MA 02111-1307, USA // ------------------------------------------------------------------ // $Id$ // ------------------------------------------------------------------ // Keyboard functions. // ------------------------------------------------------------------ #include #include #include #include #include #include #if defined(__OS2__) #define INCL_BASE #include #endif #ifdef __WIN32__ #include #endif #if defined(__UNIX__) && !defined(__USE_NCURSES__) #include #endif #if defined(__DJGPP__) #include #endif #if defined(__USE_NCURSES__) #include #endif #if defined(__linux__) #include #include #endif #if defined(__BEOS__) #include #endif // ------------------------------------------------------------------ #if defined(__USE_NCURSES__) int curses_initialized = 0; #endif // ------------------------------------------------------------------ #if defined(__WIN32__) #define KBD_TEXTMODE (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT) #endif // ------------------------------------------------------------------ // Global keyboard data #if defined(__WIN32__) && !defined(__USE_NCURSES__) HANDLE gkbd_hin; DWORD gkbd_kbdmode; int gkbd_nt; #endif GKbd gkbd; int blanked = false; bool right_alt_same_as_left = false; // ------------------------------------------------------------------ // Keyboard Class Initializer void GKbd::Init() { #if defined(__USE_NCURSES__) // Both screen and keyboard must be initialized at once if(0 == (curses_initialized++)) { initscr(); raw(); noecho(); nonl(); intrflush(stdscr, FALSE); keypad(stdscr, TRUE); } // WARNING: this might break with an old version of ncurses, or // with another implementation of curses. I'm putting it here because // it is quote useful most of the time :-) For other implementations of // curses, you might have to compile curses yourself to achieve this. -jt #if defined(NCURSES_VERSION) if(not getenv("ESCDELAY")) // If not specified by user via environment, set ESCDELAY = 50; // ms, slow for a 300bps terminal, fast for humans :-) #endif // For more ncurses-dependent code, look at the gkbd_curstable array // and at the kbxget_raw() function -jt #elif defined(__OS2__) KBDINFO kbstInfo; kbstInfo.cb = sizeof(kbstInfo); KbdGetStatus(&kbstInfo, 0); kbstInfo.fsMask = (USHORT)((kbstInfo.fsMask & 0xFFF7) | 0x0004); KbdSetStatus(&kbstInfo, 0); #elif defined(__WIN32__) OSVERSIONINFO osversion; osversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osversion); gkbd_nt = (osversion.dwPlatformId & VER_PLATFORM_WIN32_NT) ? true : false; gkbd_hin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL); GetConsoleMode(gkbd_hin, &gkbd_kbdmode); if(gkbd_kbdmode & KBD_TEXTMODE) SetConsoleMode(gkbd_hin, gkbd_kbdmode & ~KBD_TEXTMODE); #elif defined(__UNIX__) gkbd_tty_init(); #endif } // ------------------------------------------------------------------ // Keyboard Class constructor GKbd::GKbd() { kbuf = NULL; onkey = NULL; curronkey = NULL; inmenu = 0; source = 0; polling = 0; tickinterval = 0; tickpress = tickvalue = gclock(); tickfunc = NULL; inidle = 0; quitall = NO; // Detect enhanced keyboard by checking bit 4 at 0x00000496 #if defined(__USE_NCURSES__) extkbd = true; #elif defined(__DJGPP__) extkbd = _farpeekb (_dos_ds, 0x0496) & (1 << 4); #elif defined(__MSDOS__) extkbd = *((byte*)0x0496) & (1 << 4); #elif defined(__OS2__) || defined(__WIN32__) extkbd = true; #endif Init(); #if defined(__UNIX__) && !defined(__USE_NCURSES__) && !defined(__BEOS__) gkbd_keymap_init(); char escseq[2]; escseq[1] = NUL; for(int n=0; n<256; n++) { escseq[0] = (char)n; if(n == 0x7F or n == 0x08) gkbd_define_keysym(escseq, Key_BS); else if(n == 0x09) gkbd_define_keysym(escseq, Key_Tab); else if(n == 0x0D) gkbd_define_keysym(escseq, Key_Ent); else gkbd_define_keysym(escseq, (n < 128) ? (scancode_table[n]|n) : n); } gkbd_define_keysym("^@", 0); gkbd_define_keysym("\033[A", Key_Up); gkbd_define_keysym("\033[B", Key_Dwn); gkbd_define_keysym("\033[C", Key_Rgt); gkbd_define_keysym("\033[D", Key_Lft); gkbd_define_keysym("\033[[W", Key_C_Up); gkbd_define_keysym("\033[[Z", Key_C_Dwn); gkbd_define_keysym("\033[[Y", Key_C_Rgt); gkbd_define_keysym("\033[[X", Key_C_Lft); gkbd_define_keysym("\033[1~", Key_Home); gkbd_define_keysym("\033[7~", Key_Home); gkbd_define_keysym("\033[H", Key_Home); gkbd_define_keysym("\033[2~", Key_Ins); gkbd_define_keysym("\033[3~", Key_Del); gkbd_define_keysym("\033[4~", Key_End); gkbd_define_keysym("\033[8~", Key_End); gkbd_define_keysym("\033[F", Key_End); gkbd_define_keysym("\033[5~", Key_PgUp); gkbd_define_keysym("\033[6~", Key_PgDn); gkbd_define_keysym("\033[[A", Key_F1); gkbd_define_keysym("\033[[B", Key_F2); gkbd_define_keysym("\033[[C", Key_F3); gkbd_define_keysym("\033[[D", Key_F4); gkbd_define_keysym("\033[[E", Key_F5); gkbd_define_keysym("\033[17~", Key_F6); gkbd_define_keysym("\033[18~", Key_F7); gkbd_define_keysym("\033[19~", Key_F8); gkbd_define_keysym("\033[20~", Key_F9); gkbd_define_keysym("\033[21~", Key_F10); gkbd_define_keysym("\033[23~", Key_S_F1); gkbd_define_keysym("\033[24~", Key_S_F2); gkbd_define_keysym("\033[25~", Key_S_F3); gkbd_define_keysym("\033[26~", Key_S_F4); gkbd_define_keysym("\033[28~", Key_S_F5); gkbd_define_keysym("\033[29~", Key_S_F6); gkbd_define_keysym("\033[31~", Key_S_F7); gkbd_define_keysym("\033[32~", Key_S_F8); gkbd_define_keysym("\033[33~", Key_S_F9); gkbd_define_keysym("\033[34~", Key_S_F10); gkbd_define_keysym("\033""0", Key_A_0); gkbd_define_keysym("\033""1", Key_A_1); gkbd_define_keysym("\033""2", Key_A_2); gkbd_define_keysym("\033""3", Key_A_3); gkbd_define_keysym("\033""4", Key_A_4); gkbd_define_keysym("\033""5", Key_A_5); gkbd_define_keysym("\033""6", Key_A_6); gkbd_define_keysym("\033""7", Key_A_7); gkbd_define_keysym("\033""8", Key_A_8); gkbd_define_keysym("\033""9", Key_A_9); gkbd_define_keysym("\033a", Key_A_A); gkbd_define_keysym("\033b", Key_A_B); gkbd_define_keysym("\033c", Key_A_C); gkbd_define_keysym("\033d", Key_A_D); gkbd_define_keysym("\033e", Key_A_E); gkbd_define_keysym("\033f", Key_A_F); gkbd_define_keysym("\033g", Key_A_G); gkbd_define_keysym("\033h", Key_A_H); gkbd_define_keysym("\033i", Key_A_I); gkbd_define_keysym("\033j", Key_A_J); gkbd_define_keysym("\033k", Key_A_K); gkbd_define_keysym("\033l", Key_A_L); gkbd_define_keysym("\033m", Key_A_M); gkbd_define_keysym("\033n", Key_A_N); gkbd_define_keysym("\033o", Key_A_O); gkbd_define_keysym("\033p", Key_A_P); gkbd_define_keysym("\033q", Key_A_Q); gkbd_define_keysym("\033r", Key_A_R); gkbd_define_keysym("\033s", Key_A_S); gkbd_define_keysym("\033t", Key_A_T); gkbd_define_keysym("\033u", Key_A_U); gkbd_define_keysym("\033v", Key_A_V); gkbd_define_keysym("\033w", Key_A_W); gkbd_define_keysym("\033x", Key_A_X); gkbd_define_keysym("\033y", Key_A_Y); gkbd_define_keysym("\033z", Key_A_Z); gkbd_define_keysym("^?", Key_BS); gkbd_define_keysym("\033\x7F", Key_A_BS); gkbd_define_keysym("\033\x0D", Key_A_Ent); gkbd_define_keysym("\033\x09", Key_A_Tab); #elif defined(__BEOS__) gkbd_keymap_init(); char escseq[2]; escseq[1] = NUL; for(int n=0; n<256; n++) { escseq[0] = (char)n; if(n == 0x08) gkbd_define_keysym(escseq, Key_BS); else if(n == 0x09) gkbd_define_keysym(escseq, Key_Tab); else if(n == 0x0D) gkbd_define_keysym(escseq, Key_Ent); else if(n == 0x7F) gkbd_define_keysym(escseq, Key_Del); // ????? else gkbd_define_keysym(escseq, (n < 128) ? (scancode_table[n]|n) : n); } // gkbd_define_keysym("^@", 0); ????????? gkbd_define_keysym("\033[A", Key_Up); gkbd_define_keysym("\033[B", Key_Dwn); gkbd_define_keysym("\033[C", Key_Rgt); gkbd_define_keysym("\033[D", Key_Lft); gkbd_define_keysym("\033[1~", Key_Home); gkbd_define_keysym("\033[2~", Key_Ins); gkbd_define_keysym("\033[4~", Key_End); gkbd_define_keysym("\033[5~", Key_PgUp); gkbd_define_keysym("\033[6~", Key_PgDn); // gkbd_define_keysym("\033[3~", Key_Del); gkbd_define_keysym("\033[11~", Key_F1); gkbd_define_keysym("\033[12~", Key_F2); gkbd_define_keysym("\033[13~", Key_F3); gkbd_define_keysym("\033[14~", Key_F4); gkbd_define_keysym("\033[15~", Key_F5); gkbd_define_keysym("\033[16~", Key_F6); gkbd_define_keysym("\033[17~", Key_F7); gkbd_define_keysym("\033[18~", Key_F8); gkbd_define_keysym("\033[19~", Key_F9); gkbd_define_keysym("\033[20~", Key_F10); /* gkbd_define_keysym("\033\x7F", Key_A_BS); gkbd_define_keysym("\033\x0D", Key_A_Ent); gkbd_define_keysym("\033\x09", Key_A_Tab); */ #endif } // ------------------------------------------------------------------ // Keyboard Class destructor GKbd::~GKbd() { #if defined(__USE_NCURSES__) if(0 == (--curses_initialized)) endwin(); #elif defined(__WIN32__) if(gkbd_kbdmode & KBD_TEXTMODE) SetConsoleMode(gkbd_hin, gkbd_kbdmode); #elif defined(__UNIX__) gkbd_keymap_reset(); gkbd_tty_reset(); #endif } // ------------------------------------------------------------------ // Local table for scancode() gkey scancode_table[] = { Key_C_2 & 0xFF00u, // 0x0300 C <2 @> [NUL] Key_C_A & 0xFF00u, // 0x1E01 C [SOH] Key_C_B & 0xFF00u, // 0x3002 C [STX] Key_C_C & 0xFF00u, // 0x2E03 C [ETX] Key_C_D & 0xFF00u, // 0x2004 C [EOT] Key_C_E & 0xFF00u, // 0x1205 C [ENQ] Key_C_F & 0xFF00u, // 0x2106 C [ACK] Key_C_G & 0xFF00u, // 0x2207 C [BEL] Key_C_H & 0xFF00u, // 0x2308 C [BS] Key_C_I & 0xFF00u, // 0x1709 C [HT] Key_C_J & 0xFF00u, // 0x240A C [LF] Key_C_K & 0xFF00u, // 0x250B C [VT] Key_C_L & 0xFF00u, // 0x260C C [FF] Key_C_M & 0xFF00u, // 0x320D C [CR] Key_C_N & 0xFF00u, // 0x310E C [SO] Key_C_O & 0xFF00u, // 0x180F C [SI] Key_C_P & 0xFF00u, // 0x1910 C

Key_S_Q & 0xFF00u, // 0x1051 Key_S_R & 0xFF00u, // 0x1352 Key_S_S & 0xFF00u, // 0x1F53 Key_S_T & 0xFF00u, // 0x1454 Key_S_U & 0xFF00u, // 0x1655 Key_S_V & 0xFF00u, // 0x2F56 Key_S_W & 0xFF00u, // 0x1157 Key_S_X & 0xFF00u, // 0x2D58 Key_S_Y & 0xFF00u, // 0x1559 Key_S_Z & 0xFF00u, // 0x2C5A Key_Lbr & 0xFF00u, // 0x1A5B <[> Key_Bsl & 0xFF00u, // 0x2B5C <\> Key_Rbr & 0xFF00u, // 0x1B5D <]> Key_S_6 & 0xFF00u, // 0x075E <6 ^> Key_S_Min & 0xFF00u, // 0x0C5F <- _> Key_Grv & 0xFF00u, // 0x2960 <`> Key_A & 0xFF00u, // 0x1E61 Key_B & 0xFF00u, // 0x3062 Key_C & 0xFF00u, // 0x2E63 Key_D & 0xFF00u, // 0x2064 Key_E & 0xFF00u, // 0x1265 Key_F & 0xFF00u, // 0x2166 Key_G & 0xFF00u, // 0x2267 Key_H & 0xFF00u, // 0x2368 Key_I & 0xFF00u, // 0x1769 Key_J & 0xFF00u, // 0x246A Key_K & 0xFF00u, // 0x256B Key_L & 0xFF00u, // 0x266C Key_M & 0xFF00u, // 0x326D Key_N & 0xFF00u, // 0x316E Key_O & 0xFF00u, // 0x186F Key_P & 0xFF00u, // 0x1970

Key_Q & 0xFF00u, // 0x1071 Key_R & 0xFF00u, // 0x1372 Key_S & 0xFF00u, // 0x1F73 Key_T & 0xFF00u, // 0x1474 Key_U & 0xFF00u, // 0x1675 Key_V & 0xFF00u, // 0x2F76 Key_W & 0xFF00u, // 0x1177 Key_X & 0xFF00u, // 0x2D78 Key_Y & 0xFF00u, // 0x1579 Key_Z & 0xFF00u, // 0x2C7A Key_S_Lbr & 0xFF00u, // 0x1A7B <[ {> Key_S_Bsl & 0xFF00u, // 0x2B7C <\ |> Key_S_Rbr & 0xFF00u, // 0x1B7D <] }> Key_S_Grv & 0xFF00u, // 0x297E <` ~> Key_C_BS & 0xFF00u // 0x0E7F C [RUB] }; // ------------------------------------------------------------------ // Returns the scan code of an ASCII character byte scancode(gkey ch) { if(KCodAsc(ch) <= 127) return (byte)(scancode_table[KCodAsc(ch)] >> 8); return 0; } // ------------------------------------------------------------------ // Translate scancode for ASCII keys gkey keyscanxlat(gkey k) { // Only translate ASCII keys if(KCodAsc(k)) { // Check for certain ctrl-keys switch(KCodAsc(k)) { case 0x08: // CtrlH or BackSpace 23/0E if(k == Key_BS) return k; else break; case 0x09: // CtrlI or Tab 17/0F if(k == Key_Tab) return k; else break; case 0x0A: // CtrlJ or CtrlEnter or GreyCtrlEnter 24/1C/E0 case 0x0D: // CtrlM or Enter or GreyEnter 32/1C/E0 // First, translate Numpad-Enter to main Enter... if(k == Key_EntG) k = Key_Ent; else if(k == Key_C_EntG) k = Key_C_Ent; else if(k == Key_A_EntG) k = Key_A_Ent; // ...and now return if main Enter if((k == Key_Ent) or (k == Key_C_Ent) or (k == Key_A_Ent)) return k; else break; case 0x1B: // Ctrl[ or Esc 1A/01 if(k == Key_Esc) return k; else break; // asa: Not sure that the following case is required: // Key_S_3 == 0x0423, Key_C_U == 0x1615 case 0x15: // CtrlU or Shift3 (on german keyboards) 16/04 if(KCodScn(k) == 0x04) return k; break; case 0xE0: // Check for extended key and fix it if necessary if(KCodScn(k)) { KCodAsc(k) = 0x00; return k; } break; } // Translate scancode of ASCII key to a known value if (KCodAsc(k) <= 127) return (gkey)(scancode_table[KCodAsc(k)] | KCodAsc(k)); else return (gkey)(KCodAsc(k)); } return k; } // ------------------------------------------------------------------ // The following tables map curses keyboard codes to BIOS keyboard // values. #if defined(__USE_NCURSES__) // This might not work with something other than ncurses... :-( // If you ever port it to other curses implementation, remember // that it might have to be changed to another data structure, or // the array might have to be filled in another manner... int gkbd_curstable[] = { Key_C_Brk, // KEY_BREAK Key_Dwn, // KEY_DOWN Key_Up, // KEY_UP Key_Lft, // KEY_LEFT Key_Rgt, // KEY_RIGHT Key_Home, // KEY_HOME Key_BS, // KEY_BACKSPACE -1, // KEY_F0 Key_F1, // KEY_F(1) Key_F2, // KEY_F(2) Key_F3, // KEY_F(3) Key_F4, // KEY_F(4) Key_F5, // KEY_F(5) Key_F6, // KEY_F(6) Key_F7, // KEY_F(7) Key_F8, // KEY_F(8) Key_F9, // KEY_F(9) Key_F10, // KEY_F(10) Key_F11, // KEY_F(11) Key_F12, // KEY_F(12) Key_S_F3, // KEY_F(13) Key_S_F4, // KEY_F(14) Key_S_F5, // KEY_F(15) Key_S_F6, // KEY_F(16) Key_S_F7, // KEY_F(17) Key_S_F8, // KEY_F(18) Key_S_F9, // KEY_F(19) Key_S_F10, // KEY_F(20) Key_S_F11, // KEY_F(21) Key_S_F12, // KEY_F(22) -1, // KEY_F(23) -1, // KEY_F(24) -1, // KEY_F(25) -1, // KEY_F(26) -1, // KEY_F(27) -1, // KEY_F(28) -1, // KEY_F(29) -1, // KEY_F(30) -1, // KEY_F(31) -1, // KEY_F(32) -1, // KEY_F(33) -1, // KEY_F(34) -1, // KEY_F(35) -1, // KEY_F(36) -1, // KEY_F(37) -1, // KEY_F(38) -1, // KEY_F(39) -1, // KEY_F(40) -1, // KEY_F(41) -1, // KEY_F(42) -1, // KEY_F(43) -1, // KEY_F(44) -1, // KEY_F(45) -1, // KEY_F(46) -1, // KEY_F(47) -1, // KEY_F(48) -1, // KEY_F(49) -1, // KEY_F(50) -1, // KEY_F(51) -1, // KEY_F(52) -1, // KEY_F(53) -1, // KEY_F(54) -1, // KEY_F(55) -1, // KEY_F(56) -1, // KEY_F(57) -1, // KEY_F(58) -1, // KEY_F(59) -1, // KEY_F(60) -1, // KEY_F(61) -1, // KEY_F(62) -1, // KEY_F(63) -1, // KEY_DL -1, // KEY_IL Key_Del, // KEY_DC Key_Ins, // KEY_IC Key_Ins, // KEY_EIC -1, // KEY_CLEAR -1, // KEY_EOS -1, // KEY_EOL -1, // KEY_SF -1, // KEY_SR Key_PgDn, // KEY_NPAGE Key_PgUp, // KEY_PPAGE Key_Tab, // KEY_STAB -1, // KEY_CTAB -1, // KEY_CATAB Key_Ent, // KEY_ENTER -1, // KEY_SRESET -1, // KEY_RESET -1, // KEY_PRINT Key_End, // KEY_LL (hmm... this should be lower left) Key_Home, // KEY_A1 Key_PgUp, // KEY_A3 Key_5Num, // KEY_B2 Key_End, // KEY_C1 Key_PgDn, // KEY_C3 Key_S_Tab, // KEY_BTAB Key_Home, // KEY_BEG -1, // KEY_CANCEL -1, // KEY_CLOSE -1, // KEY_COMMAND -1, // KEY_COPY -1, // KEY_CREATE Key_End, // KEY_END -1, // KEY_EXIT -1, // KEY_FIND -1, // KEY_HELP -1, // KEY_MARK -1, // KEY_MESSAGE -1, // KEY_MOVE -1, // KEY_NEXT -1, // KEY_OPEN -1, // KEY_OPTIONS -1, // KEY_PREVIOUS -1, // KEY_REDO -1, // KEY_REFERENCE -1, // KEY_REFRESH -1, // KEY_REPLACE -1, // KEY_RESTART -1, // KEY_RESUME -1, // KEY_SAVE Key_S_Home,// KEY_SBEG -1, // KEY_SCANCEL -1, // KEY_SCOMMAND -1, // KEY_SCOPY -1, // KEY_SCREATE Key_S_Del, // KEY_SDC -1, // KEY_SDL -1, // KEY_SELECT Key_S_End, // KEY_SEND -1, // KEY_SEOL -1, // KEY_SEXIT -1, // KEY_SFIND -1, // KEY_SHELP Key_S_Home,// KEY_SHOME Key_S_Ins, // KEY_SIC Key_S_Lft, // KEY_SLEFT -1, // KEY_SMESSAGE -1, // KEY_SMOVE -1, // KEY_SNEXT -1, // KEY_SOPTIONS -1, // KEY_SPREVIOUS -1, // KEY_SPRINT -1, // KEY_SREDO -1, // KEY_SREPLACE Key_S_Rgt, // KEY_SRIGHT -1, // KEY_SRSUME -1, // KEY_SSAVE -1, // KEY_SSUSPEND -1, // KEY_SUNDO -1, // KEY_SUSPEND -1, // KEY_UNDO -1, // KEY_MOUSE -1 // KEY_RESIZE }; int gkbd_cursgetch(int mode) { int key; #ifndef BUGGY_NCURSES nodelay(stdscr, mode); #else wtimeout(stdscr, mode ? 0 : -1); #endif key = getch(); #ifndef BUGGY_NCURSES nodelay(stdscr, FALSE); #else wtimeout(stdscr, -1); #endif return key; } // ------------------------------------------------------------------ // The following table maps NT virtual keycodes to PC BIOS keyboard // values. For each virtual keycode there are four possible BIOS // values: normal, shift, Ctrl, and ALT. Key combinations that have // no BIOS equivalent have a value of -1, and are ignored. Extended // (non-ASCII) key values have bit 8 set to 1 using the EXT macro. #elif defined(__WIN32__) #define EXT(key) ((key)|0x10000) #define ISEXT(val) ((val)&0x10000) #define EXTVAL(val) ((val)&0xFF) struct kbd { int keycode; // virtual keycode int normal; // BIOS keycode - normal int shift; // BIOS keycode - Shift- int ctrl; // BIOS keycode - Ctrl- int alt; // BIOS keycode - Alt- } __gkbd_nt2b_table [] = { // ------------------------------------------------------------------ // Virtual key Normal Shift Control Alt { VK_BACK, Key_BS, Key_BS, Key_C_BS, Key_A_BS }, { VK_TAB, Key_Tab, Key_S_Tab, Key_C_Tab, Key_A_Tab }, { VK_RETURN, Key_Ent, Key_Ent, Key_C_Ent, Key_A_Ent }, { VK_ESCAPE, Key_Esc, Key_Esc, Key_Esc, Key_A_Esc }, { VK_SPACE, -1, -1, Key_Space, Key_Space }, { '0', Key_0, Key_S_0, -1, Key_A_0 }, { '1', Key_1, Key_S_1, -1, Key_A_1 }, { '2', Key_2, Key_S_2, Key_C_2, Key_A_2 }, { '3', Key_3, Key_S_3, -1, Key_A_3 }, { '4', Key_4, Key_S_4, -1, Key_A_4 }, { '5', Key_5, Key_S_5, -1, Key_A_5 }, { '6', Key_6, Key_S_6, Key_C_6, Key_A_6 }, { '7', Key_7, Key_S_7, -1, Key_A_7 }, { '8', Key_8, Key_S_8, -1, Key_A_8 }, { '9', Key_9, Key_S_9, -1, Key_A_9 }, { 'A', Key_A, Key_S_A, Key_C_A, Key_A_A }, { 'B', Key_B, Key_S_B, Key_C_B, Key_A_B }, { 'C', Key_C, Key_S_C, Key_C_C, Key_A_C }, { 'D', Key_D, Key_S_D, Key_C_D, Key_A_D }, { 'E', Key_E, Key_S_E, Key_C_E, Key_A_E }, { 'F', Key_F, Key_S_F, Key_C_F, Key_A_F }, { 'G', Key_G, Key_S_G, Key_C_G, Key_A_G }, { 'H', Key_H, Key_S_H, Key_C_H, Key_A_H }, { 'I', Key_I, Key_S_I, Key_C_I, Key_A_I }, { 'J', Key_J, Key_S_J, Key_C_J, Key_A_J }, { 'K', Key_K, Key_S_K, Key_C_K, Key_A_K }, { 'L', Key_L, Key_S_L, Key_C_L, Key_A_L }, { 'M', Key_M, Key_S_M, Key_C_M, Key_A_M }, { 'N', Key_N, Key_S_N, Key_C_N, Key_A_N }, { 'O', Key_O, Key_S_O, Key_C_O, Key_A_O }, { 'P', Key_P, Key_S_P, Key_C_P, Key_A_P }, { 'Q', Key_Q, Key_S_Q, Key_C_Q, Key_A_Q }, { 'R', Key_R, Key_S_R, Key_C_R, Key_A_R }, { 'S', Key_S, Key_S_S, Key_C_S, Key_A_S }, { 'T', Key_T, Key_S_T, Key_C_T, Key_A_T }, { 'U', Key_U, Key_S_U, Key_C_U, Key_A_U }, { 'V', Key_V, Key_S_V, Key_C_V, Key_A_V }, { 'W', Key_W, Key_S_W, Key_C_W, Key_A_W }, { 'X', Key_X, Key_S_X, Key_C_X, Key_A_X }, { 'Y', Key_Y, Key_S_Y, Key_C_Y, Key_A_Y }, { 'Z', Key_Z, Key_S_Z, Key_C_Z, Key_A_Z }, { VK_PRIOR, Key_PgUp, Key_S_PgUp, Key_C_PgUp, Key_A_PgUp }, { VK_NEXT, Key_PgDn, Key_S_PgDn, Key_C_PgDn, Key_A_PgDn }, { VK_END, Key_End, Key_S_End, Key_C_End, Key_A_End }, { VK_HOME, Key_Home, Key_S_Home, Key_C_Home, Key_A_Home }, { VK_LEFT, Key_Lft, Key_S_Lft, Key_C_Lft, Key_A_Lft }, { VK_UP, Key_Up, Key_S_Up, Key_C_Up, Key_A_Up }, { VK_RIGHT, Key_Rgt, Key_S_Rgt, Key_C_Rgt, Key_A_Rgt }, { VK_DOWN, Key_Dwn, Key_S_Dwn, Key_C_Dwn, Key_A_Dwn }, { VK_INSERT, Key_Ins, Key_S_Ins, Key_C_Ins, Key_A_Ins }, { VK_DELETE, Key_Del, Key_S_Del, Key_C_Del, Key_A_Del }, { VK_CLEAR, Key_5Num, Key_S_5Num, Key_C_5Num, Key_A_5Num }, { VK_NUMPAD0, Key_0, Key_S_Ins, Key_C_Ins, -1 }, { VK_NUMPAD1, Key_1, Key_S_End, Key_C_End, -1 }, { VK_NUMPAD2, Key_2, Key_S_Dwn, Key_C_Dwn, -1 }, { VK_NUMPAD3, Key_3, Key_S_PgDn, Key_C_PgDn, -1 }, { VK_NUMPAD4, Key_4, Key_S_Lft, Key_C_Lft, -1 }, { VK_NUMPAD5, Key_5, Key_S_5Num, Key_C_5Num, -1 }, { VK_NUMPAD6, Key_6, Key_S_Rgt, Key_C_Rgt, -1 }, { VK_NUMPAD7, Key_7, Key_S_Home, Key_C_Home, -1 }, { VK_NUMPAD8, Key_8, Key_S_Up, Key_C_Up, -1 }, { VK_NUMPAD9, Key_9, Key_S_PgUp, Key_C_PgUp, -1 }, { VK_MULTIPLY, Key_Multi, Key_Multi, Key_Multi, Key_Multi }, { VK_ADD, Key_Plus, Key_Plus, Key_Plus, Key_Plus }, { VK_SUBTRACT, Key_Minus, Key_Minus, Key_Minus, Key_Minus }, { VK_DECIMAL, -1, -1, Key_C_Del, Key_A_Del }, { VK_DIVIDE, Key_Sls, Key_Sls, Key_Sls, Key_Sls }, { VK_F1, Key_F1, Key_S_F1, Key_C_F1, Key_A_F1 }, { VK_F2, Key_F2, Key_S_F2, Key_C_F2, Key_A_F2 }, { VK_F3, Key_F3, Key_S_F3, Key_C_F3, Key_A_F3 }, { VK_F4, Key_F4, Key_S_F4, Key_C_F4, Key_A_F4 }, { VK_F5, Key_F5, Key_S_F5, Key_C_F5, Key_A_F5 }, { VK_F6, Key_F6, Key_S_F6, Key_C_F6, Key_A_F6 }, { VK_F7, Key_F7, Key_S_F7, Key_C_F7, Key_A_F7 }, { VK_F8, Key_F8, Key_S_F8, Key_C_F8, Key_A_F8 }, { VK_F9, Key_F9, Key_S_F9, Key_C_F9, Key_A_F9 }, { VK_F10, Key_F10, Key_S_F10, Key_C_F10, Key_A_F10 }, { VK_F11, Key_F11, Key_S_F11, Key_C_F11, Key_A_F11 }, { VK_F12, Key_F12, Key_S_F12, Key_C_F12, Key_A_F12 }, { -1, -1, -1, -1, -1 } // THE END }; // ------------------------------------------------------------------ bool is_oem_key(int keycode) { switch(keycode) { // OEM specific keys case 0x2a: case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe: case 0xbf: case 0xc0: case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf: case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4: case 0xe6: case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed: case 0xef: case 0xf0: case 0xf1: case 0xf2: case 0xf3: case 0xf4: case 0xf5: return true; default: return false; } } // ------------------------------------------------------------------ int gkbd_nt2bios(INPUT_RECORD& inp) { int keycode = inp.Event.KeyEvent.wVirtualKeyCode; int state = inp.Event.KeyEvent.dwControlKeyState; int ascii = inp.Event.KeyEvent.uChar.AsciiChar; // Look up the virtual keycode in the table. Ignore unrecognized keys. kbd* k = &__gkbd_nt2b_table[0]; while((keycode != k->keycode) and (k->keycode != -1)) k++; if(k->keycode == -1) { // value not in table return ascii ? ascii : -1; } // Check the state of the shift keys. ALT has highest // priority, followed by Control, followed by Shift. // Select the appropriate table entry based on shift state. int c; if(state & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) c = k->alt; else if(state & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED)) c = k->ctrl; else if(state & SHIFT_PRESSED) { if(k->shift == -1) c = ascii; else c = k->shift; } else { // If it is a letter key, use the ASCII value supplied // by NT to take into account the CapsLock state. if(isupper(keycode) or (k->normal == -1)) c = ascii; else c = k->normal; } if(c != -1) if(ascii and not (right_alt_same_as_left ? (state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) : (state & LEFT_ALT_PRESSED))) if(isalnum(keycode)) return (ascii == ' ') ? Key_Space : ascii; if(ISEXT(c)) return EXTVAL(c) << 8; return c; } // ------------------------------------------------------------------ bool is_numpad_key(const INPUT_RECORD& inp) { if(not (inp.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY)) { switch(inp.Event.KeyEvent.wVirtualKeyCode) { case VK_CLEAR: case VK_PRIOR: case VK_NEXT: case VK_END: case VK_HOME: case VK_LEFT: case VK_UP: case VK_RIGHT: case VK_DOWN: case VK_INSERT: case VK_DELETE: case VK_NUMPAD0: case VK_NUMPAD1: case VK_NUMPAD2: case VK_NUMPAD3: case VK_NUMPAD4: case VK_NUMPAD5: case VK_NUMPAD6: case VK_NUMPAD7: case VK_NUMPAD8: case VK_NUMPAD9: return true; } } return false; } // ------------------------------------------------------------------ // Numpad translation table #elif defined(__MSDOS__) || defined(__OS2__) const word numpad_keys[] = { 0x4737, 0x4838, 0x4939, 0x0000, 0x4B34, 0x0000, 0x4D36, 0x0000, 0x4F31, 0x5032, 0x5133, 0x5230, 0x532e }; #endif #if defined(__linux__) bool linux_cui_key(gkey k) { switch(k) { case Key_Dwn: case Key_Up: case Key_Lft: case Key_Rgt: case Key_Home: case Key_Del: case Key_Ins: case Key_PgDn: case Key_PgUp: case Key_End: return true; } return false; } #endif #if defined(__BEOS__) int BeOSShiftState() { int shift = 0; uint32 mods = modifiers(); if(mods&B_LEFT_SHIFT_KEY) shift |= LSHIFT; if(mods&B_RIGHT_SHIFT_KEY) shift |= RSHIFT; if(mods&B_CONTROL_KEY) shift |= GCTRL; if(mods&B_OPTION_KEY) shift |= ALT; return shift; } #endif // ------------------------------------------------------------------ // Get key stroke gkey kbxget_raw(int mode) { // mode - =0 - wait for key is pressed (returns code) // =1 - test if keystroke is available (returns code if YES, // otherwise returns 0) // =2 - return Shifts key status gkey k; #if defined(__USE_NCURSES__) int key; if(mode == 2) { // We can't do much but we can at least this :-) k = kbxget_raw(1); key = 0; switch(k) { case Key_C_Brk: key = GCTRL; break; case Key_S_Tab: case Key_S_Home: case Key_S_Del: case Key_S_Ins: case Key_S_Lft: case Key_S_Rgt: case Key_S_End: key = LSHIFT; break; } return key; } // Get keystroke key = gkbd_cursgetch(mode); if(key == ERR) return 0; // Prefix for Meta-key or Alt-key sequences if(key == 27) { int key2 = gkbd_cursgetch(TRUE); // If no key follows, it is no Meta- or Alt- seq, but a single Esc if(key2 == ERR) k = Key_Esc; // Compute the right keycode for the alt sequence else if((key2 >= '1') and (key2 <= '9')) k = 0x7800 + ((key2 - '1') << 8); else if(key2 == '0') k = 0x8100; else if(isalpha(key2)) k = (scancode_table[key2]); else if(key2 == '\010') k = Key_A_BS; else if(key2 == '\011') k = Key_A_Tab; else if(key2 == '\015') k = Key_A_Ent; else { // No correct Alt-sequence; ungetch last key and return Esc if (mode != 1) ungetch(key2); k = Key_Esc; } if((key2 != ERR) and (mode == 1)) ungetch(key2); } // Curses sequence; lookup in nice table above else if((key >= KEY_MIN) and (key <= KEY_MIN+sizeof(gkbd_curstable)/sizeof(int))) k = (gkbd_curstable[key - KEY_MIN]); else if(key == '\015') k = Key_Ent; else if(key == '\011') k = Key_Tab; else if(key == '\000') k = Key_Space; else k = key; if(mode == 1) ungetch(key); #elif defined(__MSDOS__) if(gkbd.extkbd) mode |= 0x10; i86 cpu; cpu.ah((byte)mode); cpu.genint(0x16); if(mode & 0x01) if(cpu.flags() & 0x40) // if ZF is set, no key is available return 0; k = (gkey)cpu.ax(); if((mode & ~0x10) == 0) { if((KCodAsc(k) == 0xE0) and (KCodScn(k) != 0)) { if(kbxget_raw(2) & (LSHIFT | RSHIFT)) { KCodAsc(k) = 0; KCodScn(k) |= 0x80; } } else switch(KCodScn(k)) { case 0x47: case 0x48: case 0x49: case 0x4B: case 0x4D: case 0x4F: case 0x50: case 0x51: case 0x52: case 0x53: { int shifts = kbxget_raw(2); if(shifts & (LSHIFT | RSHIFT)) { if(shifts & NUMLOCK) KCodAsc(k) = 0; else { KCodAsc(k) = 0; KCodScn(k) |= 0x80; } } } break; default: break; } } // If you test shift/alt/ctrl status with bios calls (e.g., using // bioskey (2) or bioskey (0x12)) then you should also use bios calls // for testing for keys. This can be done with by bioskey (1) or // bioskey (0x11). Failing to do so can cause trouble in multitasking // environments like DESQview/X. (Taken from DJGPP documentation) if((mode & 0x02) == 1) kbxget_raw(1); #elif defined(__OS2__) KBDKEYINFO kb; mode &= 0xF; if(mode == 0) KbdCharIn(&kb, IO_WAIT, 0); else if(mode == 2) { KbdPeek(&kb, 0); if(kb.fbStatus) return (gkey)(kb.fsState & (RSHIFT|LSHIFT|GCTRL|ALT)); else return 0; } else { KbdPeek(&kb, 0); if(!(kb.fbStatus & 0x40)) return 0; } KCodScn(k) = kb.chScan; KCodAsc(k) = kb.chChar; if(0x000 == KCodKey(k)) return KEY_BRK; if(0xE0 == KCodScn(k)) KCodScn(k) = 0x1C; else { if(0xE0 == KCodAsc(k)) { // If key on the alphanumeric part then don't touch it. // This need to enter for example, russian 'p' char (code 0xe0) if(KCodScn(k) >= 0x38) { KCodAsc(k) = 0x00; if(kb.fsState & (LSHIFT | RSHIFT)) KCodScn(k) |= 0x80; } else KCodScn(k) = 0x00; } else switch(KCodScn(k)) { case 0x47: case 0x48: case 0x49: case 0x4B: case 0x4D: case 0x4F: case 0x50: case 0x51: case 0x52: case 0x53: if(kb.fsState & (LSHIFT | RSHIFT)) { if(kb.fsState & NUMLOCK) KCodAsc(k) = 0; else { KCodAsc(k) = 0; KCodScn(k) |= 0x80; } } break; default: break; } } #elif defined(__WIN32__) INPUT_RECORD inp; DWORD nread; if(mode == 2) { return 0; } else if(mode & 0x01) { // Peek at next key k = 0; PeekConsoleInput(gkbd_hin, &inp, 1, &nread); if(nread) { if((inp.EventType == KEY_EVENT) and inp.Event.KeyEvent.bKeyDown) { int kc = gkbd_nt2bios(inp); if((kc != -1) or is_oem_key(inp.Event.KeyEvent.wVirtualKeyCode)) { k = (gkey)kc; return k; } } // Discard other events ReadConsoleInput(gkbd_hin, &inp, 1, &nread); } } else { DWORD &CKS = inp.Event.KeyEvent.dwControlKeyState; WORD &VKC = inp.Event.KeyEvent.wVirtualKeyCode; char &ascii = inp.Event.KeyEvent.uChar.AsciiChar; while(1) { PeekConsoleInput(gkbd_hin, &inp, 1, &nread); if(not nread) { WaitForSingleObject(gkbd_hin, 1000); continue; } if((inp.EventType == KEY_EVENT) and inp.Event.KeyEvent.bKeyDown) { bool alt_pressed = (CKS & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)) ? true : false; bool ctrl_pressed = (CKS & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)) ? true : false; bool shift_pressed = (CKS & SHIFT_PRESSED) ? true : false; bool special_key = false; k = 0; if(alt_pressed) special_key = is_numpad_key(inp); // Alt- else if(not gkbd_nt and not (CKS & ENHANCED_KEY) and not (VKC == VK_CLEAR) and (ascii and not ctrl_pressed) and not (iscntrl(ascii) and shift_pressed)) special_key = true; // It is alphanumeric key under Win9x if(special_key) { ReadConsole(gkbd_hin, &ascii, 1, &nread, NULL); if(alt_pressed) { k = (gkey)ascii; break; } } else { ReadConsoleInput(gkbd_hin, &inp, 1, &nread); } // Fix Win9x anomaly if((CKS & NUMLOCK_ON) and not (CKS & ENHANCED_KEY) and (VKC == VK_DELETE)) VKC = VK_DECIMAL; switch(VKC) { // Not meanful keys case VK_SHIFT: case VK_CONTROL: case VK_MENU: case VK_CAPITAL: case VK_NUMLOCK: case VK_SCROLL: break; case VK_NUMPAD0: case VK_NUMPAD1: case VK_NUMPAD2: case VK_NUMPAD3: case VK_NUMPAD4: case VK_NUMPAD5: case VK_NUMPAD6: case VK_NUMPAD7: case VK_NUMPAD8: case VK_NUMPAD9: if(shift_pressed) { WORD keytrans[10][2] = { {VK_NUMPAD0, VK_INSERT}, {VK_NUMPAD1, VK_END}, {VK_NUMPAD2, VK_DOWN}, {VK_NUMPAD3, VK_NEXT}, {VK_NUMPAD4, VK_LEFT}, {VK_NUMPAD5, VK_CLEAR}, {VK_NUMPAD6, VK_RIGHT}, {VK_NUMPAD7, VK_HOME}, {VK_NUMPAD8, VK_UP}, {VK_NUMPAD9, VK_PRIOR}, }; for(int i = 0; i < 10; i++) if(VKC == keytrans[i][0]) { VKC = keytrans[i][1]; break; } } // fall through default: { int kc = gkbd_nt2bios(inp); if(kc != -1) k = (gkey)kc; } break; } if(k != 0) break; } else { // Discard other events ReadConsoleInput(gkbd_hin, &inp, 1, &nread); } } } #elif defined(__UNIX__) if(mode == 2) { int key; #ifdef __linux__ // Under Linux we could use TIOCLINUX fn. 6 to read shift states on console // Of course it is very unportable but should produce good results :-) key = 6; if(ioctl(fileno(stdin), TIOCLINUX, &key) == -1) #endif key = 0; #ifdef __BEOS__ key = BeOSShiftState(); #endif return key; } else if(mode & 0x01) { // Peek at next key return gkbd_input_pending() ? 0xFFFF : 0; } else { k = gkbd_getmappedkey(); } #endif #ifdef __linux__ if(linux_cui_key(k)) { // Under Linux we could use TIOCLINUX fn. 6 to read shift states on console // Of course it is very unportable but should produce good results :-) int shifts = 6; if(ioctl(fileno(stdin), TIOCLINUX, &shifts) == -1) shifts = 0; if(shifts & (LSHIFT | RSHIFT)) KCodScn(k) |= 0x80; else if(shifts & GCTRL) { switch(k) { case Key_Ins: k = Key_C_Ins; break; case Key_Del: k = Key_C_Del; break; case Key_Dwn: k = Key_C_Dwn; break; case Key_Up: k = Key_C_Up; break; case Key_Lft: k = Key_C_Lft; break; case Key_Rgt: k = Key_C_Rgt; break; case Key_Home: k = Key_C_Home; break; case Key_PgDn: k = Key_C_PgDn; break; case Key_PgUp: k = Key_C_PgUp; break; case Key_End: k = Key_C_End; break; } } } else if(k == Key_BS) { // Under Linux we could use TIOCLINUX fn. 6 to read shift states on console // Of course it is very unportable but should produce good results :-) int shifts = 6; if(ioctl(fileno(stdin), TIOCLINUX, &shifts) == -1) shifts = 0; if(shifts & ALT) k = Key_A_BS; else if(shifts & GCTRL) k = Key_C_BS; } #elif __BEOS__ { int shifts = BeOSShiftState(); if(shifts & (ALT)) switch(k){ case Key_0: k=Key_A_0; break; case Key_1: k=Key_A_1; break; case Key_2: k=Key_A_2; break; case Key_3: k=Key_A_3; break; case Key_4: k=Key_A_4; break; case Key_5: k=Key_A_5; break; case Key_6: k=Key_A_6; break; case Key_7: k=Key_A_7; break; case Key_8: k=Key_A_8; break; case Key_9: k=Key_A_9; break; case Key_A: k=Key_A_A; break; case Key_B: k=Key_A_B; break; case Key_C: k=Key_A_C; break; case Key_D: k=Key_A_D; break; case Key_E: k=Key_A_E; break; case Key_F: k=Key_A_F; break; case Key_G: k=Key_A_G; break; case Key_H: k=Key_A_H; break; case Key_I: k=Key_A_I; break; case Key_J: k=Key_A_J; break; case Key_K: k=Key_A_K; break; case Key_L: k=Key_A_L; break; case Key_M: k=Key_A_M; break; case Key_N: k=Key_A_N; break; case Key_O: k=Key_A_O; break; case Key_P: k=Key_A_P; break; case Key_Q: k=Key_A_Q; break; case Key_R: k=Key_A_R; break; case Key_S: k=Key_A_S; break; case Key_T: k=Key_A_T; break; case Key_U: k=Key_A_U; break; case Key_V: k=Key_A_V; break; case Key_W: k=Key_A_W; break; case Key_X: k=Key_A_X; break; case Key_Y: k=Key_A_Y; break; case Key_Z: k=Key_A_Z; break; case Key_F1: k=Key_A_F1; break; case Key_F2: k=Key_A_F2; break; case Key_F3: k=Key_A_F3; break; case Key_F4: k=Key_A_F4; break; case Key_F5: k=Key_A_F5; break; case Key_F6: k=Key_A_F6; break; case Key_F7: k=Key_A_F7; break; case Key_F8: k=Key_A_F8; break; case Key_F9: k=Key_A_F9; break; case Key_F10: k=Key_A_F10; break; case Key_F11: k=Key_A_F11; break; case Key_F12: k=Key_A_F12; break; case Key_BS: k=Key_A_BS; break; case Key_Ent: k=Key_A_Ent; break; case Key_Tab: k=Key_A_Tab; break; case Key_Dwn: k = Key_A_Dwn; break; case Key_Up: k = Key_A_Up; break; case Key_Lft: k = Key_A_Lft; break; case Key_Rgt: k = Key_A_Rgt; break; case Key_Home: k = Key_A_Home; break; case Key_PgDn: k = Key_A_PgDn; break; case Key_PgUp: k = Key_A_PgUp; break; case Key_End: k = Key_A_End; break; // case Key_: k=Key_A_; break; default: break; } else if(shifts & (LSHIFT | RSHIFT)) switch(k){ case Key_F1: k=Key_S_F1; break; case Key_F2: k=Key_S_F2; break; case Key_F3: k=Key_S_F3; break; case Key_F4: k=Key_S_F4; break; case Key_F5: k=Key_S_F5; break; case Key_F6: k=Key_S_F6; break; case Key_F7: k=Key_S_F7; break; case Key_F8: k=Key_S_F8; break; case Key_F9: k=Key_S_F9; break; case Key_F10: k=Key_S_F10; break; case Key_F11: k=Key_S_F11; break; case Key_F12: k=Key_S_F12; break; case Key_Tab: k=Key_S_Tab; break; default: KCodScn(k) |= 0x80; break; } else if(shifts & GCTRL) { switch(k) { case Key_Ent: k = Key_C_Ent; break; case Key_Ins: k = Key_C_Ins; break; case Key_Del: k = Key_C_Del; break; case Key_Dwn: k = Key_C_Dwn; break; case Key_Up: k = Key_C_Up; break; case Key_Lft: k = Key_C_Lft; break; case Key_Rgt: k = Key_C_Rgt; break; case Key_Home: k = Key_C_Home; break; case Key_PgDn: k = Key_C_PgDn; break; case Key_PgUp: k = Key_C_PgUp; break; case Key_End: k = Key_C_End; break; case Key_BS: k = Key_C_BS; break; case Key_F1: k=Key_C_F1; break; case Key_F2: k=Key_C_F2; break; case Key_F3: k=Key_C_F3; break; case Key_F4: k=Key_C_F4; break; case Key_F5: k=Key_C_F5; break; case Key_F6: k=Key_C_F6; break; case Key_F7: k=Key_C_F7; break; case Key_F8: k=Key_C_F8; break; case Key_F9: k=Key_C_F9; break; case Key_F10: k=Key_C_F10; break; case Key_F11: k=Key_C_F11; break; case Key_F12: k=Key_C_F12; break; } } } /*else if(k == Key_BS) { // Under Linux we could use TIOCLINUX fn. 6 to read shift states on console // Of course it is very unportable but should produce good results :-) int shifts = 6; if(ioctl(fileno(stdin), TIOCLINUX, &shifts) == -1) shifts = 0; if(shifts & ALT) k = Key_A_BS; else if(shifts & GCTRL) k = Key_C_BS; }*/ #endif return k; } // ------------------------------------------------------------------ // Get key stroke gkey kbxget(int mode) { return keyscanxlat(kbxget_raw(mode)); } // ------------------------------------------------------------------ // Returns keycode of waiting key or zero if none gkey kbxhit() { return kbxget(0x01); } // ------------------------------------------------------------------ // Clears internal keyboard buffer void kbclear() { while(gkbd.kbuf != NULL) { KBuf *kbuf = gkbd.kbuf->next; throw_free(gkbd.kbuf); gkbd.kbuf = kbuf; } } // ------------------------------------------------------------------ // Clear keyboard buffer void clearkeys() { while(kbxhit()) kbxget(0x00); } // ------------------------------------------------------------------ // Puts a keystroke into the CXL keyboard "buffer" int kbput(gkey xch) { KBuf* kbuf; KBuf* temp; // allocate space for another keypress record kbuf=(KBuf*)throw_malloc(sizeof(KBuf)); // find last record in linked list if((temp=gkbd.kbuf)!=NULL) for(;temp->next!=NULL;temp=temp->next); // add new record to end of linked list kbuf->next=NULL; kbuf->prev=temp; if(temp != NULL) temp->next=kbuf; // add keypress info to new record kbuf->xch=xch; // if kbuf pointer was NULL, point it to new record if(gkbd.kbuf == NULL) gkbd.kbuf=kbuf; // return normally return 0; } // ------------------------------------------------------------------ // Put keys into the real keyboard buffer gkey kbput_(gkey xch) { #if defined(__MSDOS__) #if defined(__DJGPP__) if(gkbd.extkbd) { i86 cpu; cpu.ah(0x05); cpu.cx((word)xch); cpu.genint(0x16); } else { #endif #define BufStart (word)peek(0x40,0x80) #define BufEnd (word)peek(0x40,0x82) #define BufHead (word)peek(0x40,0x1A) #define BufTail (word)peek(0x40,0x1C) #define BufTail_(a) poke(0x40,0x1C,(word)(a)) word OldBufTail; OldBufTail = BufTail; if(BufTail == BufEnd-2) BufTail_(BufStart); else BufTail_(BufTail+2); if(BufTail == BufHead) BufTail_(OldBufTail); else { poke(0x40, OldBufTail, xch); } #if defined(__DJGPP__) } #endif #endif return xch; } // ------------------------------------------------------------------ // Put keys into the real keyboard buffer void kbputs_(char* str) { char* p; for(p=str; *p ;p++) kbput_(gkey((scancode(*p)<<8)|*p)); } // ------------------------------------------------------------------ // Change defined "on-key" list pointer KBnd* chgonkey(KBnd* list) { KBnd* temp; temp = gkbd.onkey; gkbd.onkey = list; return temp; } // ------------------------------------------------------------------ // Frees all active onkey definitions from memory void freonkey() { KBnd* temp; // free all onkey records in linked list while(gkbd.onkey!=NULL) { temp = gkbd.onkey->prev; throw_free(gkbd.onkey); gkbd.onkey = temp; } } // ------------------------------------------------------------------ // Attaches/detaches a key to a function int setonkey(gkey keycode, VfvCP func, gkey pass) { // search for a keycode that is already defined KBnd* onkey = gkbd.onkey; while(onkey) { if(onkey->keycode == keycode) break; onkey = onkey->prev; } // check to see if a key detachment is being requested if(func == NULL) { // if no defined onkey was found, then error if(onkey == NULL) return 2; // delete record from linked list KBnd* prev = onkey->prev; KBnd* next = onkey->next; if(prev) prev->next = next; if(next) next->prev = prev; if(onkey == gkbd.onkey) gkbd.onkey = prev; // free memory allocated for deleted record throw_free(onkey); } else { // if key was found, change func pointer // otherwise create a new onkey record if(onkey) onkey->func = func; else { // allocate memory for new record onkey = (KBnd*)throw_malloc(sizeof(KBnd)); if(onkey == NULL) return 1; // add new record to linked list if(gkbd.onkey) gkbd.onkey->next = onkey; onkey->prev = gkbd.onkey; onkey->next = NULL; gkbd.onkey = onkey; // save info in onkey record gkbd.onkey->keycode = keycode; gkbd.onkey->func = func; gkbd.onkey->pass = pass; } } // return normally return 0; } // ------------------------------------------------------------------ gkey key_tolower(gkey __keycode) { byte &ascii = KCodAsc(__keycode); if(isupper(ascii)) ascii = tolower(ascii); return __keycode; } // ------------------------------------------------------------------

[DLE] Key_C_Q & 0xFF00u, // 0x1011 C [DC1] Key_C_R & 0xFF00u, // 0x1312 C [DC2] Key_C_S & 0xFF00u, // 0x1F13 C [DC3] Key_C_T & 0xFF00u, // 0x1414 C [DC4] Key_C_U & 0xFF00u, // 0x1615 C [NAK] Key_C_V & 0xFF00u, // 0x2F16 C [SYN] Key_C_W & 0xFF00u, // 0x1117 C [ETB] Key_C_X & 0xFF00u, // 0x2D18 C [CAN] Key_C_Y & 0xFF00u, // 0x1519 C [EM] Key_C_Z & 0xFF00u, // 0x2C1A C [SUB] Key_Esc & 0xFF00u, // 0x011B C <[ {> [ESC] (was: 0x1A1B) Key_C_Bsl & 0xFF00u, // 0x2B1C C <\ |> [FS] Key_C_Rbr & 0xFF00u, // 0x1B1D C <] }> [GS] Key_C_6 & 0xFF00u, // 0x071E C <7 &> [RS] Key_C_Min & 0xFF00u, // 0x0C1F C <- _> Key_Space & 0xFF00u, // 0x3920 Key_S_1 & 0xFF00u, // 0x0221 <1 !> Key_S_Quo & 0xFF00u, // 0x2822 <' "> Key_S_3 & 0xFF00u, // 0x0423 <3 #> Key_S_4 & 0xFF00u, // 0x0524 <4 $> Key_S_5 & 0xFF00u, // 0x0625 <5 %> Key_S_7 & 0xFF00u, // 0x0826 <7 &> Key_Quo & 0xFF00u, // 0x2827 <'> Key_S_9 & 0xFF00u, // 0x0A28 <9 (> Key_S_0 & 0xFF00u, // 0x0B29 <0 )> Key_S_8 & 0xFF00u, // 0x092A <8 *> Key_S_Equ & 0xFF00u, // 0x0D2B <= +> Key_Com & 0xFF00u, // 0x332C <,> Key_Min & 0xFF00u, // 0x0C2D <-> Key_Dot & 0xFF00u, // 0x342E <.> Key_Sls & 0xFF00u, // 0x352F Key_0 & 0xFF00u, // 0x0B30 <0> Key_1 & 0xFF00u, // 0x0231 <1> Key_2 & 0xFF00u, // 0x0332 <2> Key_3 & 0xFF00u, // 0x0433 <3> Key_4 & 0xFF00u, // 0x0534 <4> Key_5 & 0xFF00u, // 0x0635 <5> Key_6 & 0xFF00u, // 0x0736 <6> Key_7 & 0xFF00u, // 0x0837 <7> Key_8 & 0xFF00u, // 0x0938 <8> Key_9 & 0xFF00u, // 0x0A39 <9> Key_S_Smi & 0xFF00u, // 0x273A <; :> Key_Smi & 0xFF00u, // 0x273B <;> Key_S_Com & 0xFF00u, // 0x333C <, >> Key_Equ & 0xFF00u, // 0x0D3D <=> Key_S_Dot & 0xFF00u, // 0x343E <. <> Key_S_Sls & 0xFF00u, // 0x353F Key_S_2 & 0xFF00u, // 0x0340 <2 @> Key_S_A & 0xFF00u, // 0x1E41 Key_S_B & 0xFF00u, // 0x3042 Key_S_C & 0xFF00u, // 0x2E43 Key_S_D & 0xFF00u, // 0x2044 Key_S_E & 0xFF00u, // 0x1245 Key_S_F & 0xFF00u, // 0x2146 Key_S_G & 0xFF00u, // 0x2247 Key_S_H & 0xFF00u, // 0x2348 Key_S_I & 0xFF00u, // 0x1749 Key_S_J & 0xFF00u, // 0x244A Key_S_K & 0xFF00u, // 0x254B Key_S_L & 0xFF00u, // 0x264C Key_S_M & 0xFF00u, // 0x324D Key_S_N & 0xFF00u, // 0x314E Key_S_O & 0xFF00u, // 0x184F Key_S_P & 0xFF00u, // 0x1950