This repository has been archived on 2024-04-08. You can view files and clone it, but cannot push or open issues or pull requests.
deb-goldedplus/goldlib/gcui/gkbdbase.cpp

2201 lines
63 KiB
C++

// 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$
// ------------------------------------------------------------------
// GCUI: Golded+ Character-oriented User Interface.
// Keyboard functions.
// ------------------------------------------------------------------
#include <gctype.h>
#include <gmemdbg.h>
#include <gkbdcode.h>
#include <gkbdbase.h>
#include <gmemall.h>
#include <stdlib.h>
#if defined(__OS2__)
#define INCL_BASE
#include <os2.h>
#endif
#ifdef __WIN32__
#include <windows.h>
extern OSVERSIONINFO WinVer;
#endif
#if defined(__UNIX__) && !defined(__USE_NCURSES__)
#include <gkbdunix.h>
#endif
#if defined(__DJGPP__)
#include <sys/farptr.h>
#endif
#if defined(__USE_NCURSES__)
#include <gcurses.h>
#endif
#if defined(__linux__)
#include <sys/ioctl.h>
#include <stdio.h>
#endif
#if defined(__BEOS__)
#include <InterfaceDefs.h>
#endif
// ------------------------------------------------------------------
#if defined(__USE_NCURSES__)
int curses_initialized = 0;
enum {
ARR_UP = 0,
ARR_DN,
ARR_RIT,
ARR_LFT
};
typedef int arrow_t;
enum {
MOD_SHIFT = 1,
MOD_ALT = 2,
MOD_CTRL = 4,
MOD_META = 8
};
typedef int modmask_t;
const modmask_t MOD_MIN = MOD_ALT;
const modmask_t MOD_MAX = MOD_ALT|MOD_CTRL|MOD_META|MOD_SHIFT;
typedef int modifier_t;
static modifier_t modifier(modmask_t mask) {
return mask + 1;
}
void gkbd_setarrow(modifier_t m, arrow_t a, int k);
void gkbd_setfnkeys(void);
#if defined(NCURSES_VERSION_MAJOR) && NCURSES_VERSION_MAJOR-0 >= 5
#define HAVE_EXTENDED_NAMES 1
#endif
//#define NO_MOD_DECFNK_XTERM_R7 1
//#define NO_MOD_RXVT 1
#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 = make_bool(osversion.dwPlatformId & VER_PLATFORM_WIN32_NT);
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(__USE_NCURSES__)
#ifdef HAVE_EXTENDED_NAMES
use_extended_names(TRUE);
#endif
for(modifier_t m = modifier(MOD_MIN); m <= modifier(MOD_MAX); m++) {
for(arrow_t a = ARR_UP; a <= ARR_LFT; a++) {
gkbd_setarrow(m, a, L_KEY_UNUSED);
}
}
gkbd_setarrow(modifier(MOD_ALT), ARR_UP, L_KEY_AUP);
gkbd_setarrow(modifier(MOD_ALT), ARR_DN, L_KEY_ADOWN);
gkbd_setarrow(modifier(MOD_ALT), ARR_RIT, L_KEY_ARIGHT);
gkbd_setarrow(modifier(MOD_ALT), ARR_LFT, L_KEY_ALEFT);
gkbd_setarrow(modifier(MOD_CTRL), ARR_UP, L_KEY_CUP);
gkbd_setarrow(modifier(MOD_CTRL), ARR_DN, L_KEY_CDOWN);
gkbd_setarrow(modifier(MOD_CTRL), ARR_RIT, L_KEY_CRIGHT);
gkbd_setarrow(modifier(MOD_CTRL), ARR_LFT, L_KEY_CLEFT);
gkbd_setfnkeys();
#endif
#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 <A> [SOH]
Key_C_B & 0xFF00u, // 0x3002 C <B> [STX]
Key_C_C & 0xFF00u, // 0x2E03 C <C> [ETX]
Key_C_D & 0xFF00u, // 0x2004 C <D> [EOT]
Key_C_E & 0xFF00u, // 0x1205 C <E> [ENQ]
Key_C_F & 0xFF00u, // 0x2106 C <F> [ACK]
Key_C_G & 0xFF00u, // 0x2207 C <G> [BEL]
Key_C_H & 0xFF00u, // 0x2308 C <H> [BS]
Key_C_I & 0xFF00u, // 0x1709 C <I> [HT]
Key_C_J & 0xFF00u, // 0x240A C <J> [LF]
Key_C_K & 0xFF00u, // 0x250B C <K> [VT]
Key_C_L & 0xFF00u, // 0x260C C <L> [FF]
Key_C_M & 0xFF00u, // 0x320D C <M> [CR]
Key_C_N & 0xFF00u, // 0x310E C <N> [SO]
Key_C_O & 0xFF00u, // 0x180F C <O> [SI]
Key_C_P & 0xFF00u, // 0x1910 C <P> [DLE]
Key_C_Q & 0xFF00u, // 0x1011 C <Q> [DC1]
Key_C_R & 0xFF00u, // 0x1312 C <R> [DC2]
Key_C_S & 0xFF00u, // 0x1F13 C <S> [DC3]
Key_C_T & 0xFF00u, // 0x1414 C <T> [DC4]
Key_C_U & 0xFF00u, // 0x1615 C <U> [NAK]
Key_C_V & 0xFF00u, // 0x2F16 C <V> [SYN]
Key_C_W & 0xFF00u, // 0x1117 C <W> [ETB]
Key_C_X & 0xFF00u, // 0x2D18 C <X> [CAN]
Key_C_Y & 0xFF00u, // 0x1519 C <Y> [EM]
Key_C_Z & 0xFF00u, // 0x2C1A C <Z> [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 <Space>
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 <A>
Key_S_B & 0xFF00u, // 0x3042 <B>
Key_S_C & 0xFF00u, // 0x2E43 <C>
Key_S_D & 0xFF00u, // 0x2044 <D>
Key_S_E & 0xFF00u, // 0x1245 <E>
Key_S_F & 0xFF00u, // 0x2146 <F>
Key_S_G & 0xFF00u, // 0x2247 <G>
Key_S_H & 0xFF00u, // 0x2348 <H>
Key_S_I & 0xFF00u, // 0x1749 <I>
Key_S_J & 0xFF00u, // 0x244A <J>
Key_S_K & 0xFF00u, // 0x254B <K>
Key_S_L & 0xFF00u, // 0x264C <L>
Key_S_M & 0xFF00u, // 0x324D <M>
Key_S_N & 0xFF00u, // 0x314E <N>
Key_S_O & 0xFF00u, // 0x184F <O>
Key_S_P & 0xFF00u, // 0x1950 <P>
Key_S_Q & 0xFF00u, // 0x1051 <Q>
Key_S_R & 0xFF00u, // 0x1352 <R>
Key_S_S & 0xFF00u, // 0x1F53 <S>
Key_S_T & 0xFF00u, // 0x1454 <T>
Key_S_U & 0xFF00u, // 0x1655 <U>
Key_S_V & 0xFF00u, // 0x2F56 <V>
Key_S_W & 0xFF00u, // 0x1157 <W>
Key_S_X & 0xFF00u, // 0x2D58 <X>
Key_S_Y & 0xFF00u, // 0x1559 <Y>
Key_S_Z & 0xFF00u, // 0x2C5A <Z>
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 <a>
Key_B & 0xFF00u, // 0x3062 <b>
Key_C & 0xFF00u, // 0x2E63 <c>
Key_D & 0xFF00u, // 0x2064 <d>
Key_E & 0xFF00u, // 0x1265 <e>
Key_F & 0xFF00u, // 0x2166 <f>
Key_G & 0xFF00u, // 0x2267 <g>
Key_H & 0xFF00u, // 0x2368 <h>
Key_I & 0xFF00u, // 0x1769 <i>
Key_J & 0xFF00u, // 0x246A <j>
Key_K & 0xFF00u, // 0x256B <k>
Key_L & 0xFF00u, // 0x266C <l>
Key_M & 0xFF00u, // 0x326D <m>
Key_N & 0xFF00u, // 0x316E <n>
Key_O & 0xFF00u, // 0x186F <o>
Key_P & 0xFF00u, // 0x1970 <p>
Key_Q & 0xFF00u, // 0x1071 <q>
Key_R & 0xFF00u, // 0x1372 <r>
Key_S & 0xFF00u, // 0x1F73 <s>
Key_T & 0xFF00u, // 0x1474 <t>
Key_U & 0xFF00u, // 0x1675 <u>
Key_V & 0xFF00u, // 0x2F76 <v>
Key_W & 0xFF00u, // 0x1177 <w>
Key_X & 0xFF00u, // 0x2D78 <x>
Key_Y & 0xFF00u, // 0x1579 <y>
Key_Z & 0xFF00u, // 0x2C7A <z>
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 <BS> [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
Key_S_Dwn, // KEY_SF - terminfo Scroll forward == <Shift>+<Down arrow>
Key_S_Up, // KEY_SR - terminfo Scroll backward == <Shift>+<Up arrow>
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
Key_PgDn, // KEY_NEXT
-1, // KEY_OPEN
-1, // KEY_OPTIONS
Key_PgUp, // 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
Key_S_PgDn,// KEY_SNEXT
-1, // KEY_SOPTIONS
Key_S_PgUp,// 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
-1, // KEY_EVENT
// Gap for future curses versions
-1, //
-1, //
-1, //
-1, //
-1, //
-1, //
-1, //
-1, //
-1, //
-1, //
// xterm R7/DECFNK
Key_A_Up, // L_KEY_AUP
Key_A_Dwn, // L_KEY_ADOWN
Key_A_Rgt, // L_KEY_ARIGHT
Key_A_Lft, // L_KEY_ALEFT
Key_C_Up, // L_KEY_CUP
Key_C_Dwn, // L_KEY_CDOWN
Key_C_Rgt, // L_KEY_CRIGHT
Key_C_Lft, // L_KEY_CLEFT
-1 // L_KEY_UNUSED
};
void gkbd_setarrow(modifier_t m, arrow_t a, int k) {
#ifdef HAVE_EXTENDED_NAMES
// Modern terminfo have user-defined capabilities for modifier
// arrow
static const char * const enm[] = { "UP", "DN", "RIT", "LFT" };
char udcapname[8];
snprintf(udcapname, sizeof(udcapname), "k%s%d", enm[a], m);
char *tc = tigetstr(udcapname);
if(tc && tc != (char *)-1) {
define_key(tc, k);
}
#endif
#ifndef NO_MOD_DECFNK_XTERM_R7
// Need to disable <Ctrl>+<Shift>+<arrow>, etc.
// terminfo.src 1.554 2015/10/24 16:00:04
// Don't have any conflicts with /\\E\[1;[3-9][^,]*[ABCD]/
char decfnk[8];
snprintf(decfnk, sizeof(decfnk), "\033[1;%d%c", m, 'A' + a);
define_key(decfnk, k);
#endif
#ifndef NO_MOD_RXVT
// Conflicts with /\\EO[a-d]/ exist, check terminal name first
if(modifier(MOD_CTRL) == m && strstr(termname(), "rxvt")) {
char rxvt[4];
snprintf(rxvt, sizeof(rxvt), "\033O%c", 'a' + a);
define_key(rxvt, k);
}
#endif
}
void gkbd_setfnkeys() {
#ifndef OLD_SHIFT_FN
static const int mod_fn12_first = KEY_F(13) - KEY_MIN;
static const int mod_fn12_keys[] = { // Modern Fn keys
// KEY_F(13-24) - <Shift>+Fn xterm R7/Linux/FreeBSD/DECFNK
Key_S_F1, // KEY_F(13)
Key_S_F2, // KEY_F(14)
Key_S_F3, // KEY_F(15)
Key_S_F4, // KEY_F(16)
Key_S_F5, // KEY_F(17)
Key_S_F6, // KEY_F(18)
Key_S_F7, // KEY_F(19)
Key_S_F8, // KEY_F(20)
Key_S_F9, // KEY_F(21)
Key_S_F10, // KEY_F(22)
Key_S_F11, // KEY_F(23)
Key_S_F12, // KEY_F(24)
// KEY_F(25-36) - <Ctrl>+Fn xterm R7/DECFNK
Key_C_F1, // KEY_F(25)
Key_C_F2, // KEY_F(26)
Key_C_F3, // KEY_F(27)
Key_C_F4, // KEY_F(28)
Key_C_F5, // KEY_F(29)
Key_C_F6, // KEY_F(30)
Key_C_F7, // KEY_F(31)
Key_C_F8, // KEY_F(32)
Key_C_F9, // KEY_F(33)
Key_C_F10, // KEY_F(34)
Key_C_F11, // KEY_F(35)
Key_C_F12, // KEY_F(36)
// KEY_F(37-48) - <Ctrl>+<Shift>+Fn xterm R7/DECFNK
-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)
// KEY_F(49-60) - <Alt>+Fn xterm R7/DECFNK
Key_A_F1, // KEY_F(49)
Key_A_F2, // KEY_F(50)
Key_A_F3, // KEY_F(51)
Key_A_F4, // KEY_F(52)
Key_A_F5, // KEY_F(53)
Key_A_F6, // KEY_F(54)
Key_A_F7, // KEY_F(55)
Key_A_F8, // KEY_F(56)
Key_A_F9, // KEY_F(57)
Key_A_F10, // KEY_F(58)
Key_A_F11, // KEY_F(59)
Key_A_F12, // KEY_F(60)
// KEY_F(61-63) - <Alt>+<Shift>+Fn xterm R7/DECFNK
-1, // KEY_F(61)
-1, // KEY_F(62)
-1 // KEY_F(63)
};
static const char * const ort_fn10_term[] = {
"xterm-old",
"xterm-r5",
"xterm-r6",
"screen.xterm-r6",
"rxvt",
"screen.rxvt",
"putty",
"screen.putty",
"linux",
"screen.linux",
0
};
static const int ort_fn10_first = KEY_F(11) - KEY_MIN;
static const int ort_fn10_keys[] = { // Orthodox Fn keys
// <Shift> + F1-F10 generates F11-F20
Key_S_F1, // KEY_F(11)
Key_S_F2, // 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)
Key_C_F1, // KEY_F(23)
Key_C_F2, // KEY_F(24)
Key_C_F3, // KEY_F(25)
Key_C_F4, // KEY_F(26)
Key_C_F5, // KEY_F(27)
Key_C_F6, // KEY_F(28)
Key_C_F7, // KEY_F(29)
Key_C_F8, // KEY_F(30)
Key_C_F9, // KEY_F(31)
Key_C_F10, // KEY_F(32)
// <Ctrl>+<Shift> + F1-F10 generates <Ctrl>+F11-F20
-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)
Key_A_F1, // KEY_F(45)
Key_A_F2, // KEY_F(46)
Key_A_F3, // KEY_F(47)
Key_A_F4, // KEY_F(48)
Key_A_F5, // KEY_F(49)
Key_A_F6, // KEY_F(50)
Key_A_F7, // KEY_F(51)
Key_A_F8, // KEY_F(52)
Key_A_F9, // KEY_F(53)
Key_A_F10, // KEY_F(54)
// <Alt>+<Shift> + F1-F10 generates <Alt>+F11-F20
-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)
};
const char *term = termname();
for(int i = 0;
i < sizeof(mod_fn12_keys)/sizeof(mod_fn12_keys[0]);
i++) {
gkbd_curstable[mod_fn12_first+i] = mod_fn12_keys[i];
}
for(int j = 0; ort_fn10_term[j]; j++) {
if(0 == strncmp(ort_fn10_term[j], term, strlen(ort_fn10_term[j]))) {
for(int i = 0;
i < sizeof(ort_fn10_keys)/sizeof(ort_fn10_keys[0]);
i++) {
gkbd_curstable[ort_fn10_first+i] = ort_fn10_keys[i];
}
}
}
#endif
}
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 },
{ VK_APPS, Key_S_F10, Key_S_F10, Key_S_F10, -1 },
{ '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 ? ascii : -1;
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 (g_isupper(keycode) or (k->normal == -1))
c = ascii ? ascii : -1;
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
// TODO: move jcuken_koi8ru[] to configuration files
// Apple OS X, non-standard or phonetic Belorussian, Russian and
// Ukrainian keyboard need <Alt>+<national key> translation by
// terminal application
// <Alt>+<national key> translation by terminal application does not
// conflict with this code, because it produces the ASCII
// Esc-sequence, and this code only handles KOI8-RU Esc-sequence
gkey gkbd_alt_secondary_keyboard(int key)
{
const static char jcuken_koi8ru[] = {
#ifndef DONT_JCUKEN_ALT
// КОИ-8: ёйцукенгшщзхъфывапролджэячсмитьбю
0243, 0312, 0303, 0325, 0313, 0305, 0316, 0307,
0333, 0335, 0332, 0310, 0337, 0306, 0331, 0327,
0301, 0320, 0322, 0317, 0314, 0304, 0326, 0334,
0321, 0336, 0323, 0315, 0311, 0324, 0330, 0302,
0300,
// КОИ-8: ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ
0263, 0352, 0343, 0365, 0353, 0345, 0356, 0347,
0373, 0375, 0372, 0350, 0377, 0346, 0371, 0367,
0341, 0360, 0362, 0357, 0354, 0344, 0366, 0374,
0361, 0376, 0363, 0355, 0351, 0364, 0370, 0342,
0340,
// KOI8-RU: ўЎіІ
0256, 0276, 0246, 0266,
// KOI8-RU: їЇґҐєЄ
0247, 0267, 0255, 0275, 0244, 0264,
#endif
0
};
const static char qwerty_ascii[] =
// KOI8-R small keys
"`qwertyuiop[]asdfghjkl;'zxcvbnm,."
// KOI8-R keys with CapsLock
"`qwertyuiop[]asdfghjkl;'zxcvbnm,."
// KOI8-RU Belorussian
"oobb"
// KOI8-RU Ukranian
"]]\\\\''"
;
const char *pjk = strchr(jcuken_koi8ru, key);
// TODO: assert(sizeof(qwerty_ascii) <= sizeof(jcuken_koi8ru));
if(pjk and (pjk - jcuken_koi8ru < sizeof(qwerty_ascii))) {
int ac = qwerty_ascii[pjk - jcuken_koi8ru]&0377;
if(!g_isalpha(ac)) {
return 0;
}
return scancode_table[ac];
}
return 0;
}
// ------------------------------------------------------------------
// 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;
// TO_PORT_TAG: kbxget_raw(3)
#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_A_Up:
case Key_A_Dwn:
case Key_A_Rgt:
case Key_A_Lft:
key = ALT;
break;
case Key_C_Brk:
case Key_C_Up:
case Key_C_Dwn:
case Key_C_Rgt:
case Key_C_Lft:
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:
case Key_S_Dwn:
case Key_S_Up:
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(g_isalpha(key2)
and (0 <= key2)
and (key2 < sizeof(scancode_table)/sizeof(scancode_table[0])))
k = (scancode_table[key2]);
else if((key2 == '\010') or (key2 == KEY_BACKSPACE) or (key2 == '\177'))
k = Key_A_BS;
else if(key2 == '\011')
k = Key_A_Tab;
else if((key2 == '\015') or (key2 == KEY_ENTER))
k = Key_A_Ent;
else if(0 == (k = gkbd_alt_secondary_keyboard(key2))) {
// 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))
and (0 <= gkbd_curstable[key - KEY_MIN]))
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 if(key < KEY_MIN)
k = key;
else
return 0; // Incorrect or unsupported key don't ungetch()
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;
static gkey KeyCtrlState = 0;
if (mode == 3) {
return KeyCtrlState;
}
else 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;
}
}
if ((inp.EventType != MOUSE_EVENT) || (WinVer.dwPlatformId == VER_PLATFORM_WIN32_NT))
{
// 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 = make_bool(CKS & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED));
bool ctrl_pressed = make_bool(CKS & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED));
bool shift_pressed = make_bool(CKS & SHIFT_PRESSED);
bool special_key = false;
k = 0;
if(alt_pressed)
special_key = is_numpad_key(inp); // Alt-<numpad key>
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;
#if defined(__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;
}
}
}
#endif
// TO_PORT_TAG: kbxget_raw(3)
#if defined(__WIN32__)
KeyCtrlState = (gkey)(inp.Event.KeyEvent.dwControlKeyState & 0xFFFF);
#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"
bool gKeystacking = false;
int kbput(gkey xch)
{
if (gKeystacking)
{
if (gkbd.kbuf != NULL)
return -1;
gKeystacking = false;
}
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(g_isupper(ascii))
ascii = g_tolower(ascii);
return __keycode;
}
// ------------------------------------------------------------------