1 //  This may look like C code, but it is really -*- C++ -*-
2 
3 //  ------------------------------------------------------------------
4 //  The Goldware Library
5 //  Copyright (C) 1990-1999 Odinn Sorensen
6 //  Copyright (C) 1999-2000 Alexander S. Aganichev
7 //  Copyright (C) 2000 Jacobo Tarrio
8 //  ------------------------------------------------------------------
9 //  This library is free software; you can redistribute it and/or
10 //  modify it under the terms of the GNU Library General Public
11 //  License as published by the Free Software Foundation; either
12 //  version 2 of the License, or (at your option) any later version.
13 //
14 //  This library is distributed in the hope that it will be useful,
15 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
16 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17 //  Library General Public License for more details.
18 //
19 //  You should have received a copy of the GNU Library General Public
20 //  License along with this program; if not, write to the Free
21 //  Software Foundation, Inc., 59 Temple Place, Suite 330, Boston,
22 //  MA 02111-1307, USA
23 //  ------------------------------------------------------------------
24 //  $Id: gkbdbase.cpp,v 1.3 2015/12/03 20:42:18 spanevin Exp $
25 //  ------------------------------------------------------------------
26 //  GCUI: Golded+ Character-oriented User Interface.
27 //  Keyboard functions.
28 //  ------------------------------------------------------------------
29 
30 #include <gctype.h>
31 #include <gmemdbg.h>
32 #include <gkbdcode.h>
33 #include <gkbdbase.h>
34 #include <gmemall.h>
35 
36 #include <stdlib.h>
37 
38 #if defined(__OS2__)
39 #define INCL_BASE
40 #include <os2.h>
41 #endif
42 
43 #ifdef __WIN32__
44 #include <windows.h>
45 extern OSVERSIONINFO WinVer;
46 #endif
47 
48 #if defined(__UNIX__) && !defined(__USE_NCURSES__)
49 #include <gkbdunix.h>
50 #endif
51 
52 #if defined(__DJGPP__)
53 #include <sys/farptr.h>
54 #endif
55 
56 #if defined(__USE_NCURSES__)
57 #include <gcurses.h>
58 #endif
59 
60 #if defined(__linux__)
61 #include <sys/ioctl.h>
62 #include <stdio.h>
63 #endif
64 
65 #if defined(__BEOS__)
66 #include <InterfaceDefs.h>
67 #endif
68 
69 //  ------------------------------------------------------------------
70 
71 #if defined(__USE_NCURSES__)
72 int curses_initialized = 0;
73 
74 enum {
75     ARR_UP = 0,
76     ARR_DN,
77     ARR_RIT,
78     ARR_LFT
79 };
80 
81 typedef int arrow_t;
82 
83 enum {
84     MOD_SHIFT = 1,
85     MOD_ALT = 2,
86     MOD_CTRL = 4,
87     MOD_META = 8
88 };
89 
90 typedef int modmask_t;
91 
92 const modmask_t MOD_MIN = MOD_ALT;
93 const modmask_t MOD_MAX = MOD_ALT|MOD_CTRL|MOD_META|MOD_SHIFT;
94 
95 typedef int modifier_t;
96 
modifier(modmask_t mask)97 static modifier_t modifier(modmask_t mask) {
98     return mask + 1;
99 }
100 
101 void gkbd_setarrow(modifier_t m, arrow_t a, int k);
102 void gkbd_setfnkeys(void);
103 
104     #if defined(NCURSES_VERSION_MAJOR) && NCURSES_VERSION_MAJOR-0 >= 5
105 	#define HAVE_EXTENDED_NAMES 1
106     #endif
107     //#define NO_MOD_DECFNK_XTERM_R7 1
108     //#define NO_MOD_RXVT 1
109 #endif
110 
111 
112 //  ------------------------------------------------------------------
113 
114 #if defined(__WIN32__)
115 #define KBD_TEXTMODE (ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_WINDOW_INPUT | ENABLE_MOUSE_INPUT)
116 #endif
117 
118 
119 //  ------------------------------------------------------------------
120 //  Global keyboard data
121 
122 #if defined(__WIN32__) && !defined(__USE_NCURSES__)
123 HANDLE gkbd_hin;
124 DWORD  gkbd_kbdmode;
125 int    gkbd_nt;
126 #endif
127 
128 GKbd gkbd;
129 
130 int blanked = false;
131 
132 bool right_alt_same_as_left = false;
133 
134 //  ------------------------------------------------------------------
135 //  Keyboard Class Initializer
136 
Init()137 void GKbd::Init() {
138 
139   #if defined(__USE_NCURSES__)
140 
141   // Both screen and keyboard must be initialized at once
142   if(0 == (curses_initialized++)) {
143     initscr();
144     raw();
145     noecho();
146     nonl();
147     intrflush(stdscr, FALSE);
148     keypad(stdscr, TRUE);
149   }
150 
151   // WARNING: this might break with an old version of ncurses, or
152   // with another implementation of curses. I'm putting it here because
153   // it is quote useful most of the time :-) For other implementations of
154   // curses, you might have to compile curses yourself to achieve this.  -jt
155   #if defined(NCURSES_VERSION)
156   if(not getenv("ESCDELAY")) // If not specified by user via environment, set
157     ESCDELAY = 50; // ms, slow for a 300bps terminal, fast for humans :-)
158   #endif
159   // For more ncurses-dependent code, look at the gkbd_curstable array
160   // and at the kbxget_raw() function  -jt
161 
162   #elif defined(__OS2__)
163 
164   KBDINFO kbstInfo;
165   kbstInfo.cb = sizeof(kbstInfo);
166   KbdGetStatus(&kbstInfo, 0);
167   kbstInfo.fsMask = (USHORT)((kbstInfo.fsMask & 0xFFF7) | 0x0004);
168   KbdSetStatus(&kbstInfo, 0);
169 
170   #elif defined(__WIN32__)
171 
172   OSVERSIONINFO osversion;
173   osversion.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
174   GetVersionEx(&osversion);
175   gkbd_nt = make_bool(osversion.dwPlatformId & VER_PLATFORM_WIN32_NT);
176   gkbd_hin = CreateFile("CONIN$", GENERIC_READ | GENERIC_WRITE,
177                          FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
178                          OPEN_EXISTING, 0, NULL);
179   GetConsoleMode(gkbd_hin, &gkbd_kbdmode);
180   if(gkbd_kbdmode & KBD_TEXTMODE)
181     SetConsoleMode(gkbd_hin, gkbd_kbdmode & ~KBD_TEXTMODE);
182 
183   #elif defined(__UNIX__)
184 
185   gkbd_tty_init();
186 
187   #endif
188 }
189 
190 
191 //  ------------------------------------------------------------------
192 //  Keyboard Class constructor
193 
GKbd()194 GKbd::GKbd() {
195 
196   kbuf = NULL;
197   onkey  = NULL;
198   curronkey = NULL;
199   inmenu = 0;
200   source = 0;
201   polling = 0;
202   tickinterval = 0;
203   tickpress = tickvalue = gclock();
204   tickfunc = NULL;
205   inidle = 0;
206   quitall = NO;
207 
208   // Detect enhanced keyboard by checking bit 4 at 0x00000496
209   #if defined(__USE_NCURSES__)
210   extkbd = true;
211   #elif defined(__DJGPP__)
212   extkbd = _farpeekb (_dos_ds, 0x0496) & (1 << 4);
213   #elif defined(__MSDOS__)
214   extkbd = *((byte*)0x0496) & (1 << 4);
215   #elif defined(__OS2__) || defined(__WIN32__)
216   extkbd = true;
217   #endif
218 
219   Init();
220 
221   #if defined(__USE_NCURSES__)
222     #ifdef HAVE_EXTENDED_NAMES
223 	use_extended_names(TRUE);
224     #endif
225 
226     for(modifier_t m = modifier(MOD_MIN); m <= modifier(MOD_MAX); m++) {
227 	for(arrow_t a = ARR_UP; a <= ARR_LFT; a++) {
228 	    gkbd_setarrow(m, a, L_KEY_UNUSED);
229 	}
230     }
231 
232     gkbd_setarrow(modifier(MOD_ALT),  ARR_UP,  L_KEY_AUP);
233     gkbd_setarrow(modifier(MOD_ALT),  ARR_DN,  L_KEY_ADOWN);
234     gkbd_setarrow(modifier(MOD_ALT),  ARR_RIT, L_KEY_ARIGHT);
235     gkbd_setarrow(modifier(MOD_ALT),  ARR_LFT, L_KEY_ALEFT);
236 
237     gkbd_setarrow(modifier(MOD_CTRL), ARR_UP,  L_KEY_CUP);
238     gkbd_setarrow(modifier(MOD_CTRL), ARR_DN,  L_KEY_CDOWN);
239     gkbd_setarrow(modifier(MOD_CTRL), ARR_RIT, L_KEY_CRIGHT);
240     gkbd_setarrow(modifier(MOD_CTRL), ARR_LFT, L_KEY_CLEFT);
241 
242     gkbd_setfnkeys();
243   #endif
244   #if defined(__UNIX__) && !defined(__USE_NCURSES__) && !defined(__BEOS__)
245 
246   gkbd_keymap_init();
247 
248   char escseq[2];
249   escseq[1] = NUL;
250   for(int n=0; n<256; n++) {
251     escseq[0] = (char)n;
252     if(n == 0x7F or n == 0x08)
253       gkbd_define_keysym(escseq, Key_BS);
254     else if(n == 0x09)
255       gkbd_define_keysym(escseq, Key_Tab);
256     else if(n == 0x0D)
257       gkbd_define_keysym(escseq, Key_Ent);
258     else
259       gkbd_define_keysym(escseq, (n < 128) ? (scancode_table[n]|n) : n);
260   }
261 
262   gkbd_define_keysym("^@", 0);
263 
264   gkbd_define_keysym("\033[A", Key_Up);
265   gkbd_define_keysym("\033[B", Key_Dwn);
266   gkbd_define_keysym("\033[C", Key_Rgt);
267   gkbd_define_keysym("\033[D", Key_Lft);
268 
269   gkbd_define_keysym("\033[[W", Key_C_Up);
270   gkbd_define_keysym("\033[[Z", Key_C_Dwn);
271   gkbd_define_keysym("\033[[Y", Key_C_Rgt);
272   gkbd_define_keysym("\033[[X", Key_C_Lft);
273 
274   gkbd_define_keysym("\033[1~", Key_Home);
275   gkbd_define_keysym("\033[7~", Key_Home);
276   gkbd_define_keysym("\033[H",  Key_Home);
277   gkbd_define_keysym("\033[2~", Key_Ins);
278   gkbd_define_keysym("\033[3~", Key_Del);
279   gkbd_define_keysym("\033[4~", Key_End);
280   gkbd_define_keysym("\033[8~", Key_End);
281   gkbd_define_keysym("\033[F",  Key_End);
282   gkbd_define_keysym("\033[5~", Key_PgUp);
283   gkbd_define_keysym("\033[6~", Key_PgDn);
284 
285   gkbd_define_keysym("\033[[A", Key_F1);
286   gkbd_define_keysym("\033[[B", Key_F2);
287   gkbd_define_keysym("\033[[C", Key_F3);
288   gkbd_define_keysym("\033[[D", Key_F4);
289   gkbd_define_keysym("\033[[E", Key_F5);
290   gkbd_define_keysym("\033[17~", Key_F6);
291   gkbd_define_keysym("\033[18~", Key_F7);
292   gkbd_define_keysym("\033[19~", Key_F8);
293   gkbd_define_keysym("\033[20~", Key_F9);
294   gkbd_define_keysym("\033[21~", Key_F10);
295 
296   gkbd_define_keysym("\033[23~", Key_S_F1);
297   gkbd_define_keysym("\033[24~", Key_S_F2);
298   gkbd_define_keysym("\033[25~", Key_S_F3);
299   gkbd_define_keysym("\033[26~", Key_S_F4);
300   gkbd_define_keysym("\033[28~", Key_S_F5);
301   gkbd_define_keysym("\033[29~", Key_S_F6);
302   gkbd_define_keysym("\033[31~", Key_S_F7);
303   gkbd_define_keysym("\033[32~", Key_S_F8);
304   gkbd_define_keysym("\033[33~", Key_S_F9);
305   gkbd_define_keysym("\033[34~", Key_S_F10);
306 
307   gkbd_define_keysym("\033""0", Key_A_0);
308   gkbd_define_keysym("\033""1", Key_A_1);
309   gkbd_define_keysym("\033""2", Key_A_2);
310   gkbd_define_keysym("\033""3", Key_A_3);
311   gkbd_define_keysym("\033""4", Key_A_4);
312   gkbd_define_keysym("\033""5", Key_A_5);
313   gkbd_define_keysym("\033""6", Key_A_6);
314   gkbd_define_keysym("\033""7", Key_A_7);
315   gkbd_define_keysym("\033""8", Key_A_8);
316   gkbd_define_keysym("\033""9", Key_A_9);
317 
318   gkbd_define_keysym("\033a", Key_A_A);
319   gkbd_define_keysym("\033b", Key_A_B);
320   gkbd_define_keysym("\033c", Key_A_C);
321   gkbd_define_keysym("\033d", Key_A_D);
322   gkbd_define_keysym("\033e", Key_A_E);
323   gkbd_define_keysym("\033f", Key_A_F);
324   gkbd_define_keysym("\033g", Key_A_G);
325   gkbd_define_keysym("\033h", Key_A_H);
326   gkbd_define_keysym("\033i", Key_A_I);
327   gkbd_define_keysym("\033j", Key_A_J);
328   gkbd_define_keysym("\033k", Key_A_K);
329   gkbd_define_keysym("\033l", Key_A_L);
330   gkbd_define_keysym("\033m", Key_A_M);
331   gkbd_define_keysym("\033n", Key_A_N);
332   gkbd_define_keysym("\033o", Key_A_O);
333   gkbd_define_keysym("\033p", Key_A_P);
334   gkbd_define_keysym("\033q", Key_A_Q);
335   gkbd_define_keysym("\033r", Key_A_R);
336   gkbd_define_keysym("\033s", Key_A_S);
337   gkbd_define_keysym("\033t", Key_A_T);
338   gkbd_define_keysym("\033u", Key_A_U);
339   gkbd_define_keysym("\033v", Key_A_V);
340   gkbd_define_keysym("\033w", Key_A_W);
341   gkbd_define_keysym("\033x", Key_A_X);
342   gkbd_define_keysym("\033y", Key_A_Y);
343   gkbd_define_keysym("\033z", Key_A_Z);
344 
345   gkbd_define_keysym("^?", Key_BS);
346   gkbd_define_keysym("\033\x7F", Key_A_BS);
347   gkbd_define_keysym("\033\x0D", Key_A_Ent);
348   gkbd_define_keysym("\033\x09", Key_A_Tab);
349 
350   #elif defined(__BEOS__)
351 
352   gkbd_keymap_init();
353 
354   char escseq[2];
355   escseq[1] = NUL;
356   for(int n=0; n<256; n++) {
357     escseq[0] = (char)n;
358     if(n == 0x08)
359       gkbd_define_keysym(escseq, Key_BS);
360     else if(n == 0x09)
361       gkbd_define_keysym(escseq, Key_Tab);
362     else if(n == 0x0D)
363       gkbd_define_keysym(escseq, Key_Ent);
364     else if(n == 0x7F)
365       gkbd_define_keysym(escseq, Key_Del); // ?????
366     else
367       gkbd_define_keysym(escseq, (n < 128) ? (scancode_table[n]|n) : n);
368   }
369 
370   // gkbd_define_keysym("^@", 0); ?????????
371 
372   gkbd_define_keysym("\033[A", Key_Up);
373   gkbd_define_keysym("\033[B", Key_Dwn);
374   gkbd_define_keysym("\033[C", Key_Rgt);
375   gkbd_define_keysym("\033[D", Key_Lft);
376 
377   gkbd_define_keysym("\033[1~", Key_Home);
378   gkbd_define_keysym("\033[2~", Key_Ins);
379   gkbd_define_keysym("\033[4~", Key_End);
380   gkbd_define_keysym("\033[5~", Key_PgUp);
381   gkbd_define_keysym("\033[6~", Key_PgDn);
382 
383   // gkbd_define_keysym("\033[3~", Key_Del);
384 
385   gkbd_define_keysym("\033[11~", Key_F1);
386   gkbd_define_keysym("\033[12~", Key_F2);
387   gkbd_define_keysym("\033[13~", Key_F3);
388   gkbd_define_keysym("\033[14~", Key_F4);
389   gkbd_define_keysym("\033[15~", Key_F5);
390   gkbd_define_keysym("\033[16~", Key_F6);
391   gkbd_define_keysym("\033[17~", Key_F7);
392   gkbd_define_keysym("\033[18~", Key_F8);
393   gkbd_define_keysym("\033[19~", Key_F9);
394   gkbd_define_keysym("\033[20~", Key_F10);
395 
396 /*
397   gkbd_define_keysym("\033\x7F", Key_A_BS);
398   gkbd_define_keysym("\033\x0D", Key_A_Ent);
399   gkbd_define_keysym("\033\x09", Key_A_Tab);
400 */
401 
402   #endif
403 }
404 
405 
406 //  ------------------------------------------------------------------
407 //  Keyboard Class destructor
408 
~GKbd()409 GKbd::~GKbd() {
410 
411   #if defined(__USE_NCURSES__)
412 
413   if(0 == (--curses_initialized))
414     endwin();
415 
416   #elif defined(__WIN32__)
417 
418   if(gkbd_kbdmode & KBD_TEXTMODE)
419     SetConsoleMode(gkbd_hin, gkbd_kbdmode);
420 
421   #elif defined(__UNIX__)
422 
423   gkbd_keymap_reset();
424   gkbd_tty_reset();
425 
426   #endif
427 }
428 
429 
430 //  ------------------------------------------------------------------
431 //  Local table for scancode()
432 
433 gkey scancode_table[] = {
434 
435   Key_C_2   & 0xFF00u,     //  0x0300          C <2 @>     [NUL]
436   Key_C_A   & 0xFF00u,     //  0x1E01          C <A>       [SOH]
437   Key_C_B   & 0xFF00u,     //  0x3002          C <B>       [STX]
438   Key_C_C   & 0xFF00u,     //  0x2E03          C <C>       [ETX]
439   Key_C_D   & 0xFF00u,     //  0x2004          C <D>       [EOT]
440   Key_C_E   & 0xFF00u,     //  0x1205          C <E>       [ENQ]
441   Key_C_F   & 0xFF00u,     //  0x2106          C <F>       [ACK]
442   Key_C_G   & 0xFF00u,     //  0x2207          C <G>       [BEL]
443   Key_C_H   & 0xFF00u,     //  0x2308          C <H>       [BS]
444   Key_C_I   & 0xFF00u,     //  0x1709          C <I>       [HT]
445   Key_C_J   & 0xFF00u,     //  0x240A          C <J>       [LF]
446   Key_C_K   & 0xFF00u,     //  0x250B          C <K>       [VT]
447   Key_C_L   & 0xFF00u,     //  0x260C          C <L>       [FF]
448   Key_C_M   & 0xFF00u,     //  0x320D          C <M>       [CR]
449   Key_C_N   & 0xFF00u,     //  0x310E          C <N>       [SO]
450   Key_C_O   & 0xFF00u,     //  0x180F          C <O>       [SI]
451   Key_C_P   & 0xFF00u,     //  0x1910          C <P>       [DLE]
452   Key_C_Q   & 0xFF00u,     //  0x1011          C <Q>       [DC1]
453   Key_C_R   & 0xFF00u,     //  0x1312          C <R>       [DC2]
454   Key_C_S   & 0xFF00u,     //  0x1F13          C <S>       [DC3]
455   Key_C_T   & 0xFF00u,     //  0x1414          C <T>       [DC4]
456   Key_C_U   & 0xFF00u,     //  0x1615          C <U>       [NAK]
457   Key_C_V   & 0xFF00u,     //  0x2F16          C <V>       [SYN]
458   Key_C_W   & 0xFF00u,     //  0x1117          C <W>       [ETB]
459   Key_C_X   & 0xFF00u,     //  0x2D18          C <X>       [CAN]
460   Key_C_Y   & 0xFF00u,     //  0x1519          C <Y>       [EM]
461   Key_C_Z   & 0xFF00u,     //  0x2C1A          C <Z>       [SUB]
462   Key_Esc   & 0xFF00u,     //  0x011B          C <[ {>     [ESC] (was: 0x1A1B)
463   Key_C_Bsl & 0xFF00u,     //  0x2B1C          C <\ |>     [FS]
464   Key_C_Rbr & 0xFF00u,     //  0x1B1D          C <] }>     [GS]
465   Key_C_6   & 0xFF00u,     //  0x071E          C <7 &>     [RS]
466   Key_C_Min & 0xFF00u,     //  0x0C1F          C <- _>
467   Key_Space & 0xFF00u,     //  0x3920            <Space>
468   Key_S_1   & 0xFF00u,     //  0x0221          <1 !>
469   Key_S_Quo & 0xFF00u,     //  0x2822          <' ">
470   Key_S_3   & 0xFF00u,     //  0x0423          <3 #>
471   Key_S_4   & 0xFF00u,     //  0x0524          <4 $>
472   Key_S_5   & 0xFF00u,     //  0x0625          <5 %>
473   Key_S_7   & 0xFF00u,     //  0x0826          <7 &>
474   Key_Quo   & 0xFF00u,     //  0x2827          <'>
475   Key_S_9   & 0xFF00u,     //  0x0A28          <9 (>
476   Key_S_0   & 0xFF00u,     //  0x0B29          <0 )>
477   Key_S_8   & 0xFF00u,     //  0x092A          <8 *>
478   Key_S_Equ & 0xFF00u,     //  0x0D2B          <= +>
479   Key_Com   & 0xFF00u,     //  0x332C            <,>
480   Key_Min   & 0xFF00u,     //  0x0C2D          <->
481   Key_Dot   & 0xFF00u,     //  0x342E            <.>
482   Key_Sls   & 0xFF00u,     //  0x352F          </>
483   Key_0     & 0xFF00u,     //  0x0B30          <0>
484   Key_1     & 0xFF00u,     //  0x0231          <1>
485   Key_2     & 0xFF00u,     //  0x0332          <2>
486   Key_3     & 0xFF00u,     //  0x0433          <3>
487   Key_4     & 0xFF00u,     //  0x0534          <4>
488   Key_5     & 0xFF00u,     //  0x0635          <5>
489   Key_6     & 0xFF00u,     //  0x0736          <6>
490   Key_7     & 0xFF00u,     //  0x0837          <7>
491   Key_8     & 0xFF00u,     //  0x0938          <8>
492   Key_9     & 0xFF00u,     //  0x0A39          <9>
493   Key_S_Smi & 0xFF00u,     //  0x273A          <; :>
494   Key_Smi   & 0xFF00u,     //  0x273B          <;>
495   Key_S_Com & 0xFF00u,     //  0x333C          <, >>
496   Key_Equ   & 0xFF00u,     //  0x0D3D          <=>
497   Key_S_Dot & 0xFF00u,     //  0x343E          <. <>
498   Key_S_Sls & 0xFF00u,     //  0x353F          </ ?>
499   Key_S_2   & 0xFF00u,     //  0x0340          <2 @>
500   Key_S_A   & 0xFF00u,     //  0x1E41          <A>
501   Key_S_B   & 0xFF00u,     //  0x3042          <B>
502   Key_S_C   & 0xFF00u,     //  0x2E43          <C>
503   Key_S_D   & 0xFF00u,     //  0x2044          <D>
504   Key_S_E   & 0xFF00u,     //  0x1245          <E>
505   Key_S_F   & 0xFF00u,     //  0x2146          <F>
506   Key_S_G   & 0xFF00u,     //  0x2247          <G>
507   Key_S_H   & 0xFF00u,     //  0x2348          <H>
508   Key_S_I   & 0xFF00u,     //  0x1749          <I>
509   Key_S_J   & 0xFF00u,     //  0x244A          <J>
510   Key_S_K   & 0xFF00u,     //  0x254B          <K>
511   Key_S_L   & 0xFF00u,     //  0x264C          <L>
512   Key_S_M   & 0xFF00u,     //  0x324D          <M>
513   Key_S_N   & 0xFF00u,     //  0x314E          <N>
514   Key_S_O   & 0xFF00u,     //  0x184F          <O>
515   Key_S_P   & 0xFF00u,     //  0x1950          <P>
516   Key_S_Q   & 0xFF00u,     //  0x1051          <Q>
517   Key_S_R   & 0xFF00u,     //  0x1352          <R>
518   Key_S_S   & 0xFF00u,     //  0x1F53          <S>
519   Key_S_T   & 0xFF00u,     //  0x1454          <T>
520   Key_S_U   & 0xFF00u,     //  0x1655          <U>
521   Key_S_V   & 0xFF00u,     //  0x2F56          <V>
522   Key_S_W   & 0xFF00u,     //  0x1157          <W>
523   Key_S_X   & 0xFF00u,     //  0x2D58          <X>
524   Key_S_Y   & 0xFF00u,     //  0x1559          <Y>
525   Key_S_Z   & 0xFF00u,     //  0x2C5A          <Z>
526   Key_Lbr   & 0xFF00u,     //  0x1A5B          <[>
527   Key_Bsl   & 0xFF00u,     //  0x2B5C          <\>
528   Key_Rbr   & 0xFF00u,     //  0x1B5D          <]>
529   Key_S_6   & 0xFF00u,     //  0x075E          <6 ^>
530   Key_S_Min & 0xFF00u,     //  0x0C5F          <- _>
531   Key_Grv   & 0xFF00u,     //  0x2960          <`>
532   Key_A     & 0xFF00u,     //  0x1E61          <a>
533   Key_B     & 0xFF00u,     //  0x3062          <b>
534   Key_C     & 0xFF00u,     //  0x2E63          <c>
535   Key_D     & 0xFF00u,     //  0x2064          <d>
536   Key_E     & 0xFF00u,     //  0x1265          <e>
537   Key_F     & 0xFF00u,     //  0x2166          <f>
538   Key_G     & 0xFF00u,     //  0x2267          <g>
539   Key_H     & 0xFF00u,     //  0x2368          <h>
540   Key_I     & 0xFF00u,     //  0x1769          <i>
541   Key_J     & 0xFF00u,     //  0x246A          <j>
542   Key_K     & 0xFF00u,     //  0x256B          <k>
543   Key_L     & 0xFF00u,     //  0x266C          <l>
544   Key_M     & 0xFF00u,     //  0x326D          <m>
545   Key_N     & 0xFF00u,     //  0x316E          <n>
546   Key_O     & 0xFF00u,     //  0x186F          <o>
547   Key_P     & 0xFF00u,     //  0x1970          <p>
548   Key_Q     & 0xFF00u,     //  0x1071          <q>
549   Key_R     & 0xFF00u,     //  0x1372          <r>
550   Key_S     & 0xFF00u,     //  0x1F73          <s>
551   Key_T     & 0xFF00u,     //  0x1474          <t>
552   Key_U     & 0xFF00u,     //  0x1675          <u>
553   Key_V     & 0xFF00u,     //  0x2F76          <v>
554   Key_W     & 0xFF00u,     //  0x1177          <w>
555   Key_X     & 0xFF00u,     //  0x2D78          <x>
556   Key_Y     & 0xFF00u,     //  0x1579          <y>
557   Key_Z     & 0xFF00u,     //  0x2C7A          <z>
558   Key_S_Lbr & 0xFF00u,     //  0x1A7B          <[ {>
559   Key_S_Bsl & 0xFF00u,     //  0x2B7C          <\ |>
560   Key_S_Rbr & 0xFF00u,     //  0x1B7D          <] }>
561   Key_S_Grv & 0xFF00u,     //  0x297E          <` ~>
562   Key_C_BS  & 0xFF00u      //  0x0E7F          C <BS>      [RUB]
563 };
564 
565 
566 //  ------------------------------------------------------------------
567 //  Returns the scan code of an ASCII character
568 
scancode(gkey ch)569 byte scancode(gkey ch) {
570 
571   if(KCodAsc(ch) <= 127)
572     return (byte)(scancode_table[KCodAsc(ch)] >> 8);
573   return 0;
574 }
575 
576 
577 //  ------------------------------------------------------------------
578 //  Translate scancode for ASCII keys
579 
keyscanxlat(gkey k)580 gkey keyscanxlat(gkey k) {
581 
582   // Only translate ASCII keys
583   if(KCodAsc(k)) {
584 
585     // Check for certain ctrl-keys
586     switch(KCodAsc(k)) {
587 
588       case 0x08:  // CtrlH or BackSpace                     23/0E
589         if(k == Key_BS)
590           return k;
591         else
592           break;
593 
594       case 0x09:  // CtrlI or Tab                           17/0F
595         if(k == Key_Tab)
596           return k;
597         else
598           break;
599 
600       case 0x0A:  // CtrlJ or CtrlEnter or GreyCtrlEnter    24/1C/E0
601       case 0x0D:  // CtrlM or Enter or GreyEnter            32/1C/E0
602         // First, translate Numpad-Enter to main Enter...
603         if(k == Key_EntG)
604           k = Key_Ent;
605         else if(k == Key_C_EntG)
606           k = Key_C_Ent;
607         else if(k == Key_A_EntG)
608           k = Key_A_Ent;
609         // ...and now return if main Enter
610         if((k == Key_Ent) or (k == Key_C_Ent) or (k == Key_A_Ent))
611           return k;
612         else
613           break;
614 
615       case 0x1B:  // Ctrl[ or Esc                           1A/01
616         if(k == Key_Esc)
617           return k;
618         else
619           break;
620 
621       // asa: Not sure that the following case is required:
622       // Key_S_3 == 0x0423, Key_C_U == 0x1615
623       case 0x15: // CtrlU or Shift3 (on german keyboards)   16/04
624         if(KCodScn(k) == 0x04)
625           return k;
626         break;
627 
628       case 0xE0: // Check for extended key and fix it if necessary
629         if(KCodScn(k)) {
630           KCodAsc(k) = 0x00;
631           return k;
632         }
633         break;
634     }
635 
636     // Translate scancode of ASCII key to a known value
637     if (KCodAsc(k) <= 127)
638       return (gkey)(scancode_table[KCodAsc(k)] | KCodAsc(k));
639     else
640       return (gkey)(KCodAsc(k));
641   }
642 
643   return k;
644 }
645 
646 
647 //  ------------------------------------------------------------------
648 //  The following tables map curses keyboard codes to BIOS keyboard
649 //  values.
650 
651 #if defined(__USE_NCURSES__)
652 
653 // This might not work with something other than ncurses... :-(
654 // If you ever port it to other curses implementation, remember
655 // that it might have to be changed to another data structure, or
656 // the array might have to be filled in another manner...
657 
658 int gkbd_curstable[] = {
659   Key_C_Brk, //  KEY_BREAK
660   Key_Dwn,   //  KEY_DOWN
661   Key_Up,    //  KEY_UP
662   Key_Lft,   //  KEY_LEFT
663   Key_Rgt,   //  KEY_RIGHT
664   Key_Home,  //  KEY_HOME
665   Key_BS,    //  KEY_BACKSPACE
666   -1,        //  KEY_F0
667   Key_F1,    //  KEY_F(1)
668   Key_F2,    //  KEY_F(2)
669   Key_F3,    //  KEY_F(3)
670   Key_F4,    //  KEY_F(4)
671   Key_F5,    //  KEY_F(5)
672   Key_F6,    //  KEY_F(6)
673   Key_F7,    //  KEY_F(7)
674   Key_F8,    //  KEY_F(8)
675   Key_F9,    //  KEY_F(9)
676   Key_F10,   //  KEY_F(10)
677   Key_F11,   //  KEY_F(11)
678   Key_F12,   //  KEY_F(12)
679   Key_S_F3,  //  KEY_F(13)
680   Key_S_F4,  //  KEY_F(14)
681   Key_S_F5,  //  KEY_F(15)
682   Key_S_F6,  //  KEY_F(16)
683   Key_S_F7,  //  KEY_F(17)
684   Key_S_F8,  //  KEY_F(18)
685   Key_S_F9,  //  KEY_F(19)
686   Key_S_F10, //  KEY_F(20)
687   Key_S_F11, //  KEY_F(21)
688   Key_S_F12, //  KEY_F(22)
689   -1,        //  KEY_F(23)
690   -1,        //  KEY_F(24)
691   -1,        //  KEY_F(25)
692   -1,        //  KEY_F(26)
693   -1,        //  KEY_F(27)
694   -1,        //  KEY_F(28)
695   -1,        //  KEY_F(29)
696   -1,        //  KEY_F(30)
697   -1,        //  KEY_F(31)
698   -1,        //  KEY_F(32)
699   -1,        //  KEY_F(33)
700   -1,        //  KEY_F(34)
701   -1,        //  KEY_F(35)
702   -1,        //  KEY_F(36)
703   -1,        //  KEY_F(37)
704   -1,        //  KEY_F(38)
705   -1,        //  KEY_F(39)
706   -1,        //  KEY_F(40)
707   -1,        //  KEY_F(41)
708   -1,        //  KEY_F(42)
709   -1,        //  KEY_F(43)
710   -1,        //  KEY_F(44)
711   -1,        //  KEY_F(45)
712   -1,        //  KEY_F(46)
713   -1,        //  KEY_F(47)
714   -1,        //  KEY_F(48)
715   -1,        //  KEY_F(49)
716   -1,        //  KEY_F(50)
717   -1,        //  KEY_F(51)
718   -1,        //  KEY_F(52)
719   -1,        //  KEY_F(53)
720   -1,        //  KEY_F(54)
721   -1,        //  KEY_F(55)
722   -1,        //  KEY_F(56)
723   -1,        //  KEY_F(57)
724   -1,        //  KEY_F(58)
725   -1,        //  KEY_F(59)
726   -1,        //  KEY_F(60)
727   -1,        //  KEY_F(61)
728   -1,        //  KEY_F(62)
729   -1,        //  KEY_F(63)
730   -1,        //  KEY_DL
731   -1,        //  KEY_IL
732   Key_Del,   //  KEY_DC
733   Key_Ins,   //  KEY_IC
734   Key_Ins,   //  KEY_EIC
735   -1,        //  KEY_CLEAR
736   -1,        //  KEY_EOS
737   -1,        //  KEY_EOL
738   Key_S_Dwn, //  KEY_SF - terminfo Scroll forward == <Shift>+<Down arrow>
739   Key_S_Up,  //  KEY_SR - terminfo Scroll backward == <Shift>+<Up arrow>
740   Key_PgDn,  //  KEY_NPAGE
741   Key_PgUp,  //  KEY_PPAGE
742   Key_Tab,   //  KEY_STAB
743   -1,        //  KEY_CTAB
744   -1,        //  KEY_CATAB
745   Key_Ent,   //  KEY_ENTER
746   -1,        //  KEY_SRESET
747   -1,        //  KEY_RESET
748   -1,        //  KEY_PRINT
749   Key_End,   //  KEY_LL (hmm... this should be lower left)
750   Key_Home,  //  KEY_A1
751   Key_PgUp,  //  KEY_A3
752   Key_5Num,  //  KEY_B2
753   Key_End,   //  KEY_C1
754   Key_PgDn,  //  KEY_C3
755   Key_S_Tab, //  KEY_BTAB
756   Key_Home,  //  KEY_BEG
757   -1,        //  KEY_CANCEL
758   -1,        //  KEY_CLOSE
759   -1,        //  KEY_COMMAND
760   -1,        //  KEY_COPY
761   -1,        //  KEY_CREATE
762   Key_End,   //  KEY_END
763   -1,        //  KEY_EXIT
764   -1,        //  KEY_FIND
765   -1,        //  KEY_HELP
766   -1,        //  KEY_MARK
767   -1,        //  KEY_MESSAGE
768   -1,        //  KEY_MOVE
769   Key_PgDn,  //  KEY_NEXT
770   -1,        //  KEY_OPEN
771   -1,        //  KEY_OPTIONS
772   Key_PgUp,  //  KEY_PREVIOUS
773   -1,        //  KEY_REDO
774   -1,        //  KEY_REFERENCE
775   -1,        //  KEY_REFRESH
776   -1,        //  KEY_REPLACE
777   -1,        //  KEY_RESTART
778   -1,        //  KEY_RESUME
779   -1,        //  KEY_SAVE
780   Key_S_Home,//  KEY_SBEG
781   -1,        //  KEY_SCANCEL
782   -1,        //  KEY_SCOMMAND
783   -1,        //  KEY_SCOPY
784   -1,        //  KEY_SCREATE
785   Key_S_Del, //  KEY_SDC
786   -1,        //  KEY_SDL
787   -1,        //  KEY_SELECT
788   Key_S_End, //  KEY_SEND
789   -1,        //  KEY_SEOL
790   -1,        //  KEY_SEXIT
791   -1,        //  KEY_SFIND
792   -1,        //  KEY_SHELP
793   Key_S_Home,//  KEY_SHOME
794   Key_S_Ins, //  KEY_SIC
795   Key_S_Lft, //  KEY_SLEFT
796   -1,        //  KEY_SMESSAGE
797   -1,        //  KEY_SMOVE
798   Key_S_PgDn,//  KEY_SNEXT
799   -1,        //  KEY_SOPTIONS
800   Key_S_PgUp,//  KEY_SPREVIOUS
801   -1,        //  KEY_SPRINT
802   -1,        //  KEY_SREDO
803   -1,        //  KEY_SREPLACE
804   Key_S_Rgt, //  KEY_SRIGHT
805   -1,        //  KEY_SRSUME
806   -1,        //  KEY_SSAVE
807   -1,        //  KEY_SSUSPEND
808   -1,        //  KEY_SUNDO
809   -1,        //  KEY_SUSPEND
810   -1,        //  KEY_UNDO
811   -1,        //  KEY_MOUSE
812   -1,        //  KEY_RESIZE
813   -1,	     //  KEY_EVENT
814     // Gap for future curses versions
815   -1,	     //
816   -1,	     //
817   -1,	     //
818   -1,	     //
819   -1,	     //
820   -1,	     //
821   -1,	     //
822   -1,	     //
823   -1,	     //
824   -1,	     //
825     // xterm R7/DECFNK
826   Key_A_Up,  //  L_KEY_AUP
827   Key_A_Dwn, //  L_KEY_ADOWN
828   Key_A_Rgt, //  L_KEY_ARIGHT
829   Key_A_Lft, //  L_KEY_ALEFT
830   Key_C_Up,  //  L_KEY_CUP
831   Key_C_Dwn, //  L_KEY_CDOWN
832   Key_C_Rgt, //  L_KEY_CRIGHT
833   Key_C_Lft, //  L_KEY_CLEFT
834   -1         //  L_KEY_UNUSED
835 };
836 
gkbd_setarrow(modifier_t m,arrow_t a,int k)837 void gkbd_setarrow(modifier_t m, arrow_t a, int k) {
838     #ifdef HAVE_EXTENDED_NAMES
839 	// Modern terminfo have user-defined capabilities for modifier
840 	// arrow
841 
842 	static const char * const enm[] = { "UP", "DN", "RIT", "LFT" };
843 	char udcapname[8];
844 
845 	snprintf(udcapname, sizeof(udcapname), "k%s%d", enm[a], m);
846 
847 	char *tc = tigetstr(udcapname);
848 
849 	if(tc && tc != (char *)-1) {
850 	    define_key(tc, k);
851 	}
852     #endif
853     #ifndef NO_MOD_DECFNK_XTERM_R7
854     	// Need to disable <Ctrl>+<Shift>+<arrow>, etc.
855 
856     	// terminfo.src 1.554 2015/10/24 16:00:04
857 	// Don't have any conflicts with /\\E\[1;[3-9][^,]*[ABCD]/
858 
859 	char decfnk[8];
860 
861 	snprintf(decfnk, sizeof(decfnk), "\033[1;%d%c", m, 'A' + a);
862 	define_key(decfnk, k);
863     #endif
864     #ifndef NO_MOD_RXVT
865     	// Conflicts with /\\EO[a-d]/ exist, check terminal name first
866 
867 	if(modifier(MOD_CTRL) == m && strstr(termname(), "rxvt")) {
868 	    char rxvt[4];
869 
870 	    snprintf(rxvt, sizeof(rxvt), "\033O%c", 'a' + a);
871 	    define_key(rxvt, k);
872 	}
873     #endif
874 }
875 
gkbd_setfnkeys()876 void gkbd_setfnkeys() {
877 #ifndef OLD_SHIFT_FN
878   static const int mod_fn12_first = KEY_F(13) - KEY_MIN;
879 
880   static const int mod_fn12_keys[] = { // Modern Fn keys
881 	  // KEY_F(13-24) - <Shift>+Fn xterm R7/Linux/FreeBSD/DECFNK
882 	Key_S_F1,  //  KEY_F(13)
883 	Key_S_F2,  //  KEY_F(14)
884 	Key_S_F3,  //  KEY_F(15)
885 	Key_S_F4,  //  KEY_F(16)
886 	Key_S_F5,  //  KEY_F(17)
887 	Key_S_F6,  //  KEY_F(18)
888 	Key_S_F7,  //  KEY_F(19)
889 	Key_S_F8,  //  KEY_F(20)
890 	Key_S_F9,  //  KEY_F(21)
891 	Key_S_F10, //  KEY_F(22)
892 	Key_S_F11, //  KEY_F(23)
893 	Key_S_F12, //  KEY_F(24)
894 
895 	  // KEY_F(25-36) - <Ctrl>+Fn xterm R7/DECFNK
896 	Key_C_F1,  //  KEY_F(25)
897 	Key_C_F2,  //  KEY_F(26)
898 	Key_C_F3,  //  KEY_F(27)
899 	Key_C_F4,  //  KEY_F(28)
900 	Key_C_F5,  //  KEY_F(29)
901 	Key_C_F6,  //  KEY_F(30)
902 	Key_C_F7,  //  KEY_F(31)
903 	Key_C_F8,  //  KEY_F(32)
904 	Key_C_F9,  //  KEY_F(33)
905 	Key_C_F10, //  KEY_F(34)
906 	Key_C_F11, //  KEY_F(35)
907 	Key_C_F12, //  KEY_F(36)
908 
909 	  // KEY_F(37-48) - <Ctrl>+<Shift>+Fn xterm R7/DECFNK
910 	-1,        //  KEY_F(37)
911 	-1,        //  KEY_F(38)
912 	-1,        //  KEY_F(39)
913 	-1,        //  KEY_F(40)
914 	-1,        //  KEY_F(41)
915 	-1,        //  KEY_F(42)
916 	-1,        //  KEY_F(43)
917 	-1,        //  KEY_F(44)
918 	-1,        //  KEY_F(45)
919 	-1,        //  KEY_F(46)
920 	-1,        //  KEY_F(47)
921 	-1,        //  KEY_F(48)
922 
923 	  // KEY_F(49-60) - <Alt>+Fn xterm R7/DECFNK
924 	Key_A_F1,  //  KEY_F(49)
925 	Key_A_F2,  //  KEY_F(50)
926 	Key_A_F3,  //  KEY_F(51)
927 	Key_A_F4,  //  KEY_F(52)
928 	Key_A_F5,  //  KEY_F(53)
929 	Key_A_F6,  //  KEY_F(54)
930 	Key_A_F7,  //  KEY_F(55)
931 	Key_A_F8,  //  KEY_F(56)
932 	Key_A_F9,  //  KEY_F(57)
933 	Key_A_F10, //  KEY_F(58)
934 	Key_A_F11, //  KEY_F(59)
935 	Key_A_F12, //  KEY_F(60)
936 
937 	  // KEY_F(61-63) - <Alt>+<Shift>+Fn xterm R7/DECFNK
938 	-1,        //  KEY_F(61)
939 	-1,        //  KEY_F(62)
940 	-1         //  KEY_F(63)
941       };
942 
943   static const char * const ort_fn10_term[] = {
944 	"xterm-old",
945 	"xterm-r5",
946 	"xterm-r6",
947 	"screen.xterm-r6",
948 	"rxvt",
949 	"screen.rxvt",
950 	"putty",
951 	"screen.putty",
952 	"linux",
953 	"screen.linux",
954 	0
955       };
956 
957   static const int ort_fn10_first = KEY_F(11) - KEY_MIN;
958 
959   static const int ort_fn10_keys[] = { // Orthodox Fn keys
960 		// <Shift> + F1-F10 generates F11-F20
961 	Key_S_F1,  //  KEY_F(11)
962 	Key_S_F2,  //  KEY_F(12)
963 	Key_S_F3,  //  KEY_F(13)
964 	Key_S_F4,  //  KEY_F(14)
965 	Key_S_F5,  //  KEY_F(15)
966 	Key_S_F6,  //  KEY_F(16)
967 	Key_S_F7,  //  KEY_F(17)
968 	Key_S_F8,  //  KEY_F(18)
969 	Key_S_F9,  //  KEY_F(19)
970 	Key_S_F10, //  KEY_F(20)
971 
972 	Key_S_F11, //  KEY_F(21)
973 	Key_S_F12, //  KEY_F(22)
974 
975 	Key_C_F1,  //  KEY_F(23)
976 	Key_C_F2,  //  KEY_F(24)
977 	Key_C_F3,  //  KEY_F(25)
978 	Key_C_F4,  //  KEY_F(26)
979 	Key_C_F5,  //  KEY_F(27)
980 	Key_C_F6,  //  KEY_F(28)
981 	Key_C_F7,  //  KEY_F(29)
982 	Key_C_F8,  //  KEY_F(30)
983 	Key_C_F9,  //  KEY_F(31)
984 	Key_C_F10, //  KEY_F(32)
985 
986 		// <Ctrl>+<Shift> + F1-F10 generates  <Ctrl>+F11-F20
987 	-1,        //  KEY_F(33)
988 	-1,        //  KEY_F(34)
989 	-1,        //  KEY_F(35)
990 	-1,        //  KEY_F(36)
991 	-1,        //  KEY_F(37)
992 	-1,        //  KEY_F(38)
993 	-1,        //  KEY_F(39)
994 	-1,        //  KEY_F(40)
995 	-1,        //  KEY_F(41)
996 	-1,        //  KEY_F(42)
997 
998 	-1,        //  KEY_F(43)
999 	-1,        //  KEY_F(44)
1000 
1001 	Key_A_F1,  //  KEY_F(45)
1002 	Key_A_F2,  //  KEY_F(46)
1003 	Key_A_F3,  //  KEY_F(47)
1004 	Key_A_F4,  //  KEY_F(48)
1005 	Key_A_F5,  //  KEY_F(49)
1006 	Key_A_F6,  //  KEY_F(50)
1007 	Key_A_F7,  //  KEY_F(51)
1008 	Key_A_F8,  //  KEY_F(52)
1009 	Key_A_F9,  //  KEY_F(53)
1010 	Key_A_F10, //  KEY_F(54)
1011 
1012 		// <Alt>+<Shift> + F1-F10 generates  <Alt>+F11-F20
1013 	-1,        //  KEY_F(55)
1014 	-1,        //  KEY_F(56)
1015 	-1,        //  KEY_F(57)
1016 	-1,        //  KEY_F(58)
1017 	-1,        //  KEY_F(59)
1018 	-1,        //  KEY_F(60)
1019 	-1,        //  KEY_F(61)
1020 	-1,        //  KEY_F(62)
1021 	-1         //  KEY_F(63)
1022       };
1023 
1024     const char *term = termname();
1025 
1026     for(int i = 0;
1027 	    i < sizeof(mod_fn12_keys)/sizeof(mod_fn12_keys[0]);
1028 	    i++) {
1029 	gkbd_curstable[mod_fn12_first+i] = mod_fn12_keys[i];
1030     }
1031     for(int j = 0; ort_fn10_term[j]; j++) {
1032 	if(0 == strncmp(ort_fn10_term[j], term, strlen(ort_fn10_term[j]))) {
1033 	    for(int i = 0;
1034 		    i < sizeof(ort_fn10_keys)/sizeof(ort_fn10_keys[0]);
1035 		    i++) {
1036 		gkbd_curstable[ort_fn10_first+i] = ort_fn10_keys[i];
1037 	    }
1038 	}
1039     }
1040 #endif
1041 }
1042 
gkbd_cursgetch(int mode)1043 int gkbd_cursgetch(int mode) {
1044 
1045   int key;
1046 #ifndef BUGGY_NCURSES
1047   nodelay(stdscr, mode);
1048 #else
1049   wtimeout(stdscr, mode ? 0 : -1);
1050 #endif
1051   key = getch();
1052 #ifndef BUGGY_NCURSES
1053   nodelay(stdscr, FALSE);
1054 #else
1055   wtimeout(stdscr, -1);
1056 #endif
1057 
1058   return key;
1059 }
1060 
1061 
1062 //  ------------------------------------------------------------------
1063 //  The following table maps NT virtual keycodes to PC BIOS keyboard
1064 //  values.  For each virtual keycode there are four possible BIOS
1065 //  values: normal, shift, Ctrl, and ALT.  Key combinations that have
1066 //  no BIOS equivalent have a value of -1, and are ignored.  Extended
1067 //  (non-ASCII) key values have bit 8 set to 1 using the EXT macro.
1068 
1069 #elif defined(__WIN32__)
1070 
1071 #define EXT(key)    ((key)|0x10000)
1072 #define ISEXT(val)  ((val)&0x10000)
1073 #define EXTVAL(val) ((val)&0xFF)
1074 
1075 struct kbd {
1076   int keycode;            // virtual keycode
1077   int normal;             // BIOS keycode - normal
1078   int shift;              // BIOS keycode - Shift-
1079   int ctrl;               // BIOS keycode - Ctrl-
1080   int alt;                // BIOS keycode - Alt-
1081 } __gkbd_nt2b_table [] =
1082 {
1083 
1084 //  ------------------------------------------------------------------
1085 //  Virtual key   Normal      Shift       Control     Alt
1086 
1087   { VK_BACK,      Key_BS,     Key_BS,     Key_C_BS,   Key_A_BS },
1088   { VK_TAB,       Key_Tab,    Key_S_Tab,  Key_C_Tab,  Key_A_Tab },
1089   { VK_RETURN,    Key_Ent,    Key_Ent,    Key_C_Ent,  Key_A_Ent },
1090   { VK_ESCAPE,    Key_Esc,    Key_Esc,    Key_Esc,    Key_A_Esc },
1091   { VK_SPACE,     -1,         -1,         Key_Space,  Key_Space },
1092   { VK_APPS,      Key_S_F10,  Key_S_F10,  Key_S_F10,  -1        },
1093 
1094   { '0',          Key_0,      Key_S_0,    -1,         Key_A_0 },
1095   { '1',          Key_1,      Key_S_1,    -1,         Key_A_1 },
1096   { '2',          Key_2,      Key_S_2,    Key_C_2,    Key_A_2 },
1097   { '3',          Key_3,      Key_S_3,    -1,         Key_A_3 },
1098   { '4',          Key_4,      Key_S_4,    -1,         Key_A_4 },
1099   { '5',          Key_5,      Key_S_5,    -1,         Key_A_5 },
1100   { '6',          Key_6,      Key_S_6,    Key_C_6,    Key_A_6 },
1101   { '7',          Key_7,      Key_S_7,    -1,         Key_A_7 },
1102   { '8',          Key_8,      Key_S_8,    -1,         Key_A_8 },
1103   { '9',          Key_9,      Key_S_9,    -1,         Key_A_9 },
1104   { 'A',          Key_A,      Key_S_A,    Key_C_A,    Key_A_A },
1105   { 'B',          Key_B,      Key_S_B,    Key_C_B,    Key_A_B },
1106   { 'C',          Key_C,      Key_S_C,    Key_C_C,    Key_A_C },
1107   { 'D',          Key_D,      Key_S_D,    Key_C_D,    Key_A_D },
1108   { 'E',          Key_E,      Key_S_E,    Key_C_E,    Key_A_E },
1109   { 'F',          Key_F,      Key_S_F,    Key_C_F,    Key_A_F },
1110   { 'G',          Key_G,      Key_S_G,    Key_C_G,    Key_A_G },
1111   { 'H',          Key_H,      Key_S_H,    Key_C_H,    Key_A_H },
1112   { 'I',          Key_I,      Key_S_I,    Key_C_I,    Key_A_I },
1113   { 'J',          Key_J,      Key_S_J,    Key_C_J,    Key_A_J },
1114   { 'K',          Key_K,      Key_S_K,    Key_C_K,    Key_A_K },
1115   { 'L',          Key_L,      Key_S_L,    Key_C_L,    Key_A_L },
1116   { 'M',          Key_M,      Key_S_M,    Key_C_M,    Key_A_M },
1117   { 'N',          Key_N,      Key_S_N,    Key_C_N,    Key_A_N },
1118   { 'O',          Key_O,      Key_S_O,    Key_C_O,    Key_A_O },
1119   { 'P',          Key_P,      Key_S_P,    Key_C_P,    Key_A_P },
1120   { 'Q',          Key_Q,      Key_S_Q,    Key_C_Q,    Key_A_Q },
1121   { 'R',          Key_R,      Key_S_R,    Key_C_R,    Key_A_R },
1122   { 'S',          Key_S,      Key_S_S,    Key_C_S,    Key_A_S },
1123   { 'T',          Key_T,      Key_S_T,    Key_C_T,    Key_A_T },
1124   { 'U',          Key_U,      Key_S_U,    Key_C_U,    Key_A_U },
1125   { 'V',          Key_V,      Key_S_V,    Key_C_V,    Key_A_V },
1126   { 'W',          Key_W,      Key_S_W,    Key_C_W,    Key_A_W },
1127   { 'X',          Key_X,      Key_S_X,    Key_C_X,    Key_A_X },
1128   { 'Y',          Key_Y,      Key_S_Y,    Key_C_Y,    Key_A_Y },
1129   { 'Z',          Key_Z,      Key_S_Z,    Key_C_Z,    Key_A_Z },
1130 
1131   { VK_PRIOR,     Key_PgUp,   Key_S_PgUp, Key_C_PgUp, Key_A_PgUp },
1132   { VK_NEXT,      Key_PgDn,   Key_S_PgDn, Key_C_PgDn, Key_A_PgDn },
1133   { VK_END,       Key_End,    Key_S_End,  Key_C_End,  Key_A_End },
1134   { VK_HOME,      Key_Home,   Key_S_Home, Key_C_Home, Key_A_Home },
1135   { VK_LEFT,      Key_Lft,    Key_S_Lft,  Key_C_Lft,  Key_A_Lft },
1136   { VK_UP,        Key_Up,     Key_S_Up,   Key_C_Up,   Key_A_Up },
1137   { VK_RIGHT,     Key_Rgt,    Key_S_Rgt,  Key_C_Rgt,  Key_A_Rgt },
1138   { VK_DOWN,      Key_Dwn,    Key_S_Dwn,  Key_C_Dwn,  Key_A_Dwn },
1139   { VK_INSERT,    Key_Ins,    Key_S_Ins,  Key_C_Ins,  Key_A_Ins },
1140   { VK_DELETE,    Key_Del,    Key_S_Del,  Key_C_Del,  Key_A_Del },
1141   { VK_CLEAR,     Key_5Num,   Key_S_5Num, Key_C_5Num, Key_A_5Num },
1142   { VK_NUMPAD0,   Key_0,      Key_S_Ins,  Key_C_Ins,  -1 },
1143   { VK_NUMPAD1,   Key_1,      Key_S_End,  Key_C_End,  -1 },
1144   { VK_NUMPAD2,   Key_2,      Key_S_Dwn,  Key_C_Dwn,  -1 },
1145   { VK_NUMPAD3,   Key_3,      Key_S_PgDn, Key_C_PgDn, -1 },
1146   { VK_NUMPAD4,   Key_4,      Key_S_Lft,  Key_C_Lft,  -1 },
1147   { VK_NUMPAD5,   Key_5,      Key_S_5Num, Key_C_5Num, -1 },
1148   { VK_NUMPAD6,   Key_6,      Key_S_Rgt,  Key_C_Rgt,  -1 },
1149   { VK_NUMPAD7,   Key_7,      Key_S_Home, Key_C_Home, -1 },
1150   { VK_NUMPAD8,   Key_8,      Key_S_Up,   Key_C_Up,   -1 },
1151   { VK_NUMPAD9,   Key_9,      Key_S_PgUp, Key_C_PgUp, -1 },
1152   { VK_MULTIPLY,  Key_Multi,  Key_Multi,  Key_Multi,  Key_Multi },
1153   { VK_ADD,       Key_Plus,   Key_Plus,   Key_Plus,   Key_Plus },
1154   { VK_SUBTRACT,  Key_Minus,  Key_Minus,  Key_Minus,  Key_Minus },
1155   { VK_DECIMAL,   -1,         -1,         Key_C_Del,  Key_A_Del },
1156   { VK_DIVIDE,    Key_Sls,    Key_Sls,    Key_Sls,    Key_Sls },
1157   { VK_F1,        Key_F1,     Key_S_F1,   Key_C_F1,   Key_A_F1 },
1158   { VK_F2,        Key_F2,     Key_S_F2,   Key_C_F2,   Key_A_F2 },
1159   { VK_F3,        Key_F3,     Key_S_F3,   Key_C_F3,   Key_A_F3 },
1160   { VK_F4,        Key_F4,     Key_S_F4,   Key_C_F4,   Key_A_F4 },
1161   { VK_F5,        Key_F5,     Key_S_F5,   Key_C_F5,   Key_A_F5 },
1162   { VK_F6,        Key_F6,     Key_S_F6,   Key_C_F6,   Key_A_F6 },
1163   { VK_F7,        Key_F7,     Key_S_F7,   Key_C_F7,   Key_A_F7 },
1164   { VK_F8,        Key_F8,     Key_S_F8,   Key_C_F8,   Key_A_F8 },
1165   { VK_F9,        Key_F9,     Key_S_F9,   Key_C_F9,   Key_A_F9 },
1166   { VK_F10,       Key_F10,    Key_S_F10,  Key_C_F10,  Key_A_F10 },
1167   { VK_F11,       Key_F11,    Key_S_F11,  Key_C_F11,  Key_A_F11 },
1168   { VK_F12,       Key_F12,    Key_S_F12,  Key_C_F12,  Key_A_F12 },
1169 
1170   { -1,           -1,         -1,         -1,         -1 }  // THE END
1171 };
1172 
1173 
1174 //  ------------------------------------------------------------------
1175 
is_oem_key(int keycode)1176 bool is_oem_key(int keycode)
1177 {
1178   switch(keycode)
1179   {
1180     // OEM specific keys
1181     case 0x2a:
1182     case 0xba: case 0xbb: case 0xbc: case 0xbd: case 0xbe:
1183     case 0xbf: case 0xc0:
1184     case 0xdb: case 0xdc: case 0xdd: case 0xde: case 0xdf:
1185     case 0xe0: case 0xe1: case 0xe2: case 0xe3: case 0xe4:
1186     case 0xe6:
1187     case 0xe9: case 0xea: case 0xeb: case 0xec: case 0xed:
1188     case 0xef: case 0xf0: case 0xf1: case 0xf2: case 0xf3:
1189     case 0xf4: case 0xf5:
1190       return true;
1191 
1192     default:
1193       return false;
1194   }
1195 }
1196 
1197 
1198 //  ------------------------------------------------------------------
1199 
gkbd_nt2bios(INPUT_RECORD & inp)1200 int gkbd_nt2bios(INPUT_RECORD& inp) {
1201 
1202   int keycode = inp.Event.KeyEvent.wVirtualKeyCode;
1203   int state   = inp.Event.KeyEvent.dwControlKeyState;
1204   int ascii   = inp.Event.KeyEvent.uChar.AsciiChar;
1205 
1206   // Look up the virtual keycode in the table. Ignore unrecognized keys.
1207 
1208   kbd* k = &__gkbd_nt2b_table[0];
1209   while((keycode != k->keycode) and (k->keycode != -1))
1210     k++;
1211   if(k->keycode == -1) {  // value not in table
1212     return ascii ? ascii : -1;
1213   }
1214 
1215   // Check the state of the shift keys. ALT has highest
1216   // priority, followed by Control, followed by Shift.
1217   // Select the appropriate table entry based on shift state.
1218 
1219   int c;
1220   if(state & (RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED))
1221     c = k->alt;
1222   else if(state & (RIGHT_CTRL_PRESSED | LEFT_CTRL_PRESSED))
1223     c = k->ctrl;
1224   else if(state & SHIFT_PRESSED)
1225   {
1226     if (k->shift == -1)
1227       c = ascii ? ascii : -1;
1228     else
1229       c = k->shift;
1230   }
1231   else {
1232     // If it is a letter key, use the ASCII value supplied
1233     // by NT to take into account the CapsLock state.
1234     if (g_isupper(keycode) or (k->normal == -1))
1235       c = ascii ? ascii : -1;
1236     else
1237       c = k->normal;
1238   }
1239 
1240   if (c != -1)
1241   {
1242     if (ascii and not (right_alt_same_as_left ? (state & (LEFT_ALT_PRESSED | RIGHT_ALT_PRESSED)) : (state & LEFT_ALT_PRESSED)))
1243       if (isalnum(keycode))
1244         return (ascii == ' ') ? Key_Space : ascii;
1245     if (ISEXT(c))
1246       return EXTVAL(c) << 8;
1247   }
1248 
1249   return c;
1250 }
1251 
1252 //  ------------------------------------------------------------------
1253 
is_numpad_key(const INPUT_RECORD & inp)1254 bool is_numpad_key(const INPUT_RECORD& inp) {
1255 
1256   if(not (inp.Event.KeyEvent.dwControlKeyState & ENHANCED_KEY)) {
1257     switch(inp.Event.KeyEvent.wVirtualKeyCode) {
1258       case VK_CLEAR:
1259       case VK_PRIOR:
1260       case VK_NEXT:
1261       case VK_END:
1262       case VK_HOME:
1263       case VK_LEFT:
1264       case VK_UP:
1265       case VK_RIGHT:
1266       case VK_DOWN:
1267       case VK_INSERT:
1268       case VK_DELETE:
1269       case VK_NUMPAD0:
1270       case VK_NUMPAD1:
1271       case VK_NUMPAD2:
1272       case VK_NUMPAD3:
1273       case VK_NUMPAD4:
1274       case VK_NUMPAD5:
1275       case VK_NUMPAD6:
1276       case VK_NUMPAD7:
1277       case VK_NUMPAD8:
1278       case VK_NUMPAD9:
1279         return true;
1280     }
1281   }
1282   return false;
1283 }
1284 
1285 
1286 //  ------------------------------------------------------------------
1287 //  Numpad translation table
1288 
1289 #elif defined(__MSDOS__) || defined(__OS2__)
1290 
1291 const word numpad_keys[] = {
1292   0x4737, 0x4838, 0x4939, 0x0000,
1293   0x4B34, 0x0000, 0x4D36, 0x0000,
1294   0x4F31, 0x5032, 0x5133,
1295   0x5230, 0x532e
1296 };
1297 
1298 #endif
1299 
1300 #if defined(__linux__)
linux_cui_key(gkey k)1301 bool linux_cui_key(gkey k) {
1302   switch(k) {
1303     case Key_Dwn:
1304     case Key_Up:
1305     case Key_Lft:
1306     case Key_Rgt:
1307     case Key_Home:
1308     case Key_Del:
1309     case Key_Ins:
1310     case Key_PgDn:
1311     case Key_PgUp:
1312     case Key_End:
1313       return true;
1314   }
1315   return false;
1316 }
1317 #endif
1318 
1319 #if defined(__BEOS__)
BeOSShiftState()1320 int BeOSShiftState()
1321 {
1322   int shift = 0;
1323   uint32 mods = modifiers();
1324   if(mods&B_LEFT_SHIFT_KEY)  shift |= LSHIFT;
1325   if(mods&B_RIGHT_SHIFT_KEY) shift |= RSHIFT;
1326   if(mods&B_CONTROL_KEY)     shift |= GCTRL;
1327   if(mods&B_OPTION_KEY)      shift |= ALT;
1328   return shift;
1329 }
1330 #endif
1331 
1332 // TODO: move jcuken_koi8ru[] to configuration files
1333 
1334 //       Apple OS X, non-standard or phonetic Belorussian, Russian and
1335 //       Ukrainian keyboard need <Alt>+<national key> translation by
1336 //       terminal application
1337 
1338 //	 <Alt>+<national key> translation by terminal application does not
1339 //	 conflict with this code, because it produces the ASCII
1340 //	 Esc-sequence, and this code only handles KOI8-RU Esc-sequence
1341 
gkbd_alt_secondary_keyboard(int key)1342 gkey gkbd_alt_secondary_keyboard(int key)
1343 {
1344     const static char jcuken_koi8ru[] =  {
1345 #ifndef DONT_JCUKEN_ALT
1346 		// КОИ-8: ёйцукенгшщзхъфывапролджэячсмитьбю
1347 	    0243, 0312, 0303, 0325, 0313, 0305, 0316, 0307,
1348 	    0333, 0335, 0332, 0310, 0337, 0306, 0331, 0327,
1349 	    0301, 0320, 0322, 0317, 0314, 0304, 0326, 0334,
1350 	    0321, 0336, 0323, 0315, 0311, 0324, 0330, 0302,
1351 	    0300,
1352 
1353 		// КОИ-8: ЁЙЦУКЕНГШЩЗХЪФЫВАПРОЛДЖЭЯЧСМИТЬБЮ
1354 	    0263, 0352, 0343, 0365, 0353, 0345, 0356, 0347,
1355 	    0373, 0375, 0372, 0350, 0377, 0346, 0371, 0367,
1356 	    0341, 0360, 0362, 0357, 0354, 0344, 0366, 0374,
1357 	    0361, 0376, 0363, 0355, 0351, 0364, 0370, 0342,
1358 	    0340,
1359 
1360 		// KOI8-RU: ўЎіІ
1361 	    0256, 0276, 0246, 0266,
1362 
1363 	    	// KOI8-RU: їЇґҐєЄ
1364 	    0247, 0267, 0255, 0275, 0244, 0264,
1365 #endif
1366 	    0
1367 	};
1368     const static char qwerty_ascii[] =
1369 		// KOI8-R small keys
1370 	    "`qwertyuiop[]asdfghjkl;'zxcvbnm,."
1371 		// KOI8-R keys with CapsLock
1372 	    "`qwertyuiop[]asdfghjkl;'zxcvbnm,."
1373 		// KOI8-RU Belorussian
1374 	    "oobb"
1375 		// KOI8-RU Ukranian
1376 	    "]]\\\\''"
1377 	;
1378     const char *pjk = strchr(jcuken_koi8ru, key);
1379     // TODO: assert(sizeof(qwerty_ascii) <= sizeof(jcuken_koi8ru));
1380     if(pjk and (pjk - jcuken_koi8ru < sizeof(qwerty_ascii))) {
1381       int ac = qwerty_ascii[pjk - jcuken_koi8ru]&0377;
1382 
1383       if(!g_isalpha(ac)) {
1384 	  return 0;
1385       }
1386       return scancode_table[ac];
1387     }
1388     return 0;
1389 }
1390 
1391 //  ------------------------------------------------------------------
1392 //  Get key stroke
1393 
kbxget_raw(int mode)1394 gkey kbxget_raw(int mode) {
1395 //  mode - =0 - wait for key is pressed (returns code)
1396 //         =1 - test if keystroke is available (returns code if YES,
1397 //              otherwise returns 0)
1398 //         =2 - return Shifts key status
1399   gkey k;
1400 
1401 //  TO_PORT_TAG: kbxget_raw(3)
1402   #if defined(__USE_NCURSES__)
1403 
1404   int key;
1405   if(mode == 2) {
1406     // We can't do much but we can at least this :-)
1407     k = kbxget_raw(1);
1408     key = 0;
1409     switch(k) {
1410       case Key_A_Up:
1411       case Key_A_Dwn:
1412       case Key_A_Rgt:
1413       case Key_A_Lft:
1414         key = ALT;
1415         break;
1416       case Key_C_Brk:
1417       case Key_C_Up:
1418       case Key_C_Dwn:
1419       case Key_C_Rgt:
1420       case Key_C_Lft:
1421         key = GCTRL;
1422         break;
1423       case Key_S_Tab:
1424       case Key_S_Home:
1425       case Key_S_Del:
1426       case Key_S_Ins:
1427       case Key_S_Lft:
1428       case Key_S_Rgt:
1429       case Key_S_End:
1430       case Key_S_Dwn:
1431       case Key_S_Up:
1432         key = LSHIFT;
1433         break;
1434     }
1435     return key;
1436   }
1437 
1438   // Get keystroke
1439   key = gkbd_cursgetch(mode);
1440   if(key == ERR)
1441     return 0;
1442 
1443   // Prefix for Meta-key or Alt-key sequences
1444   if(key == 27) {
1445     int key2 = gkbd_cursgetch(TRUE);
1446     // If no key follows, it is no Meta- or Alt- seq, but a single Esc
1447     if(key2 == ERR)
1448       k = Key_Esc;
1449     // Compute the right keycode for the alt sequence
1450     else if((key2 >= '1') and (key2 <= '9'))
1451       k = 0x7800 + ((key2 - '1') << 8);
1452     else if(key2 == '0')
1453       k = 0x8100;
1454     else if(g_isalpha(key2)
1455 	    and (0 <= key2)
1456 	    and (key2 < sizeof(scancode_table)/sizeof(scancode_table[0])))
1457       k = (scancode_table[key2]);
1458     else if((key2 == '\010') or (key2 == KEY_BACKSPACE) or (key2 == '\177'))
1459       k = Key_A_BS;
1460     else if(key2 == '\011')
1461       k = Key_A_Tab;
1462     else if((key2 == '\015') or (key2 == KEY_ENTER))
1463       k = Key_A_Ent;
1464     else if(0 == (k = gkbd_alt_secondary_keyboard(key2))) {
1465       // No correct Alt-sequence; ungetch last key and return Esc
1466       if (mode != 1)
1467         ungetch(key2);
1468       k = Key_Esc;
1469     }
1470 
1471     if((key2 != ERR) and (mode == 1))
1472       ungetch(key2);
1473   }
1474   // Curses sequence; lookup in nice table above
1475   else if((key >= KEY_MIN)
1476 	    and (key <= KEY_MIN+sizeof(gkbd_curstable)/sizeof(int))
1477 	    and (0 <= gkbd_curstable[key - KEY_MIN]))
1478     k = (gkbd_curstable[key - KEY_MIN]);
1479   else if(key == '\015')
1480     k = Key_Ent;
1481   else if(key == '\011')
1482     k = Key_Tab;
1483   else if(key == '\000')
1484     k = Key_Space;
1485   else if(key < KEY_MIN)
1486     k = key;
1487   else
1488     return 0;	// Incorrect or unsupported key don't ungetch()
1489 
1490   if(mode == 1)
1491     ungetch(key);
1492 
1493   #elif defined(__MSDOS__)
1494 
1495   if(gkbd.extkbd)
1496     mode |= 0x10;
1497 
1498   i86 cpu;
1499   cpu.ah((byte)mode);
1500   cpu.genint(0x16);
1501   if(mode & 0x01)
1502     if(cpu.flags() & 0x40)   // if ZF is set, no key is available
1503       return 0;
1504   k = (gkey)cpu.ax();
1505 
1506   if((mode & ~0x10) == 0) {
1507     if((KCodAsc(k) == 0xE0) and (KCodScn(k) != 0)) {
1508       if(kbxget_raw(2) & (LSHIFT | RSHIFT)) {
1509         KCodAsc(k) = 0;
1510         KCodScn(k) |= 0x80;
1511       }
1512     }
1513     else
1514       switch(KCodScn(k)) {
1515         case 0x47:
1516         case 0x48:
1517         case 0x49:
1518         case 0x4B:
1519         case 0x4D:
1520         case 0x4F:
1521         case 0x50:
1522         case 0x51:
1523         case 0x52:
1524         case 0x53:
1525           {
1526             int shifts = kbxget_raw(2);
1527             if(shifts & (LSHIFT | RSHIFT)) {
1528               if(shifts & NUMLOCK)
1529                 KCodAsc(k) = 0;
1530               else {
1531                 KCodAsc(k) = 0;
1532                 KCodScn(k) |= 0x80;
1533               }
1534             }
1535           }
1536           break;
1537         default:
1538           break;
1539       }
1540   }
1541 
1542   // If you test shift/alt/ctrl status with bios calls (e.g., using
1543   // bioskey (2) or bioskey (0x12)) then you should also use bios calls
1544   // for testing for keys.  This can be done with by bioskey (1) or
1545   // bioskey (0x11).  Failing to do so can cause trouble in multitasking
1546   // environments like DESQview/X. (Taken from DJGPP documentation)
1547   if((mode & 0x02) == 1)
1548     kbxget_raw(1);
1549 
1550   #elif defined(__OS2__)
1551 
1552   KBDKEYINFO kb;
1553   mode &= 0xF;
1554   if(mode == 0)
1555     KbdCharIn(&kb, IO_WAIT, 0);
1556   else if(mode == 2) {
1557     KbdPeek(&kb, 0);
1558     if(kb.fbStatus)
1559       return (gkey)(kb.fsState & (RSHIFT|LSHIFT|GCTRL|ALT));
1560     else
1561       return 0;
1562   }
1563   else {
1564     KbdPeek(&kb, 0);
1565     if(!(kb.fbStatus & 0x40))
1566       return 0;
1567   }
1568   KCodScn(k) = kb.chScan;
1569   KCodAsc(k) = kb.chChar;
1570   if(0x000 == KCodKey(k))
1571     return KEY_BRK;
1572   if(0xE0 == KCodScn(k))
1573     KCodScn(k) = 0x1C;
1574   else {
1575     if(0xE0 == KCodAsc(k)) {
1576       // If key on the alphanumeric part then don't touch it.
1577       // This need to enter for example, russian 'p' char (code 0xe0)
1578       if(KCodScn(k) >= 0x38) {
1579         KCodAsc(k) = 0x00;
1580         if(kb.fsState & (LSHIFT | RSHIFT))
1581           KCodScn(k) |= 0x80;
1582       }
1583       else
1584         KCodScn(k) = 0x00;
1585     }
1586     else
1587       switch(KCodScn(k)) {
1588         case 0x47:
1589         case 0x48:
1590         case 0x49:
1591         case 0x4B:
1592         case 0x4D:
1593         case 0x4F:
1594         case 0x50:
1595         case 0x51:
1596         case 0x52:
1597         case 0x53:
1598           if(kb.fsState & (LSHIFT | RSHIFT)) {
1599             if(kb.fsState & NUMLOCK)
1600               KCodAsc(k) = 0;
1601             else {
1602               KCodAsc(k) = 0;
1603               KCodScn(k) |= 0x80;
1604             }
1605           }
1606           break;
1607         default:
1608           break;
1609       }
1610   }
1611 
1612   #elif defined(__WIN32__)
1613 
1614   INPUT_RECORD inp;
1615   DWORD nread;
1616   static gkey KeyCtrlState = 0;
1617 
1618   if (mode == 3) {
1619     return KeyCtrlState;
1620   }
1621   else if(mode == 2) {
1622     return 0;
1623   }
1624   else if(mode & 0x01) {
1625 
1626     // Peek at next key
1627     k = 0;
1628     PeekConsoleInput(gkbd_hin, &inp, 1, &nread);
1629     if(nread) {
1630       if((inp.EventType == KEY_EVENT) and inp.Event.KeyEvent.bKeyDown) {
1631         int kc = gkbd_nt2bios(inp);
1632         if((kc != -1) or is_oem_key(inp.Event.KeyEvent.wVirtualKeyCode)) {
1633           k = (gkey)kc;
1634           return k;
1635         }
1636       }
1637 
1638       if ((inp.EventType != MOUSE_EVENT) || (WinVer.dwPlatformId == VER_PLATFORM_WIN32_NT))
1639       {
1640         // Discard other events
1641         ReadConsoleInput(gkbd_hin, &inp, 1, &nread);
1642       }
1643     }
1644   }
1645   else {
1646 
1647     DWORD &CKS = inp.Event.KeyEvent.dwControlKeyState;
1648     WORD &VKC = inp.Event.KeyEvent.wVirtualKeyCode;
1649     char &ascii = inp.Event.KeyEvent.uChar.AsciiChar;
1650 
1651     while(1) {
1652 
1653       PeekConsoleInput(gkbd_hin, &inp, 1, &nread);
1654       if(not nread) {
1655         WaitForSingleObject(gkbd_hin, 1000);
1656         continue;
1657       }
1658 
1659       if((inp.EventType == KEY_EVENT) and inp.Event.KeyEvent.bKeyDown) {
1660         bool alt_pressed = make_bool(CKS & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED));
1661         bool ctrl_pressed = make_bool(CKS & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED));
1662         bool shift_pressed = make_bool(CKS & SHIFT_PRESSED);
1663         bool special_key = false;
1664 
1665         k = 0;
1666 
1667         if(alt_pressed)
1668           special_key = is_numpad_key(inp); // Alt-<numpad key>
1669         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))
1670           special_key = true; // It is alphanumeric key under Win9x
1671         if(special_key) {
1672           ReadConsole(gkbd_hin, &ascii, 1, &nread, NULL);
1673           if(alt_pressed) {
1674             k = (gkey)ascii;
1675             break;
1676           }
1677         }
1678         else {
1679           ReadConsoleInput(gkbd_hin, &inp, 1, &nread);
1680         }
1681 
1682         // Fix Win9x anomaly
1683         if((CKS & NUMLOCK_ON) and not (CKS & ENHANCED_KEY) and (VKC == VK_DELETE))
1684           VKC = VK_DECIMAL;
1685 
1686         switch(VKC) {
1687           // Not meanful keys
1688           case VK_SHIFT:
1689           case VK_CONTROL:
1690           case VK_MENU:
1691           case VK_CAPITAL:
1692           case VK_NUMLOCK:
1693           case VK_SCROLL:
1694             break;
1695 
1696           case VK_NUMPAD0:
1697           case VK_NUMPAD1:
1698           case VK_NUMPAD2:
1699           case VK_NUMPAD3:
1700           case VK_NUMPAD4:
1701           case VK_NUMPAD5:
1702           case VK_NUMPAD6:
1703           case VK_NUMPAD7:
1704           case VK_NUMPAD8:
1705           case VK_NUMPAD9:
1706             if(shift_pressed) {
1707               WORD keytrans[10][2] = {
1708                 {VK_NUMPAD0, VK_INSERT},
1709                 {VK_NUMPAD1, VK_END},
1710                 {VK_NUMPAD2, VK_DOWN},
1711                 {VK_NUMPAD3, VK_NEXT},
1712                 {VK_NUMPAD4, VK_LEFT},
1713                 {VK_NUMPAD5, VK_CLEAR},
1714                 {VK_NUMPAD6, VK_RIGHT},
1715                 {VK_NUMPAD7, VK_HOME},
1716                 {VK_NUMPAD8, VK_UP},
1717                 {VK_NUMPAD9, VK_PRIOR},
1718               };
1719               for(int i = 0; i < 10; i++)
1720                 if(VKC == keytrans[i][0]) {
1721                   VKC = keytrans[i][1];
1722                   break;
1723                 }
1724             }
1725             // fall through
1726           default:
1727             {
1728               int kc = gkbd_nt2bios(inp);
1729               if(kc != -1)
1730                 k = (gkey)kc;
1731             }
1732             break;
1733         }
1734         if(k != 0)
1735           break;
1736       }
1737       else {
1738         // Discard other events
1739         ReadConsoleInput(gkbd_hin, &inp, 1, &nread);
1740       }
1741     }
1742   }
1743 
1744   #elif defined(__UNIX__)
1745 
1746   if(mode == 2) {
1747     int key;
1748     #if defined(__linux__)
1749     // Under Linux we could use TIOCLINUX fn. 6 to read shift states on console
1750     // Of course it is very unportable but should produce good results :-)
1751     key = 6;
1752     if(ioctl(fileno(stdin), TIOCLINUX, &key) == -1)
1753     #endif
1754       key = 0;
1755     #ifdef __BEOS__
1756     key = BeOSShiftState();
1757     #endif
1758     return key;
1759   }
1760   else if(mode & 0x01) {
1761 
1762     // Peek at next key
1763     return gkbd_input_pending() ? 0xFFFF : 0;
1764   }
1765   else {
1766 
1767     k = gkbd_getmappedkey();
1768   }
1769 
1770   #endif
1771 
1772   #ifdef __linux__
1773   if(linux_cui_key(k)) {
1774     // Under Linux we could use TIOCLINUX fn. 6 to read shift states on console
1775     // Of course it is very unportable but should produce good results :-)
1776     int shifts = 6;
1777     if(ioctl(fileno(stdin), TIOCLINUX, &shifts) == -1)
1778       shifts = 0;
1779     if(shifts & (LSHIFT | RSHIFT))
1780       KCodScn(k) |= 0x80;
1781     else if(shifts & GCTRL) {
1782       switch(k) {
1783         case Key_Ins:
1784           k = Key_C_Ins;
1785           break;
1786         case Key_Del:
1787           k = Key_C_Del;
1788           break;
1789         case Key_Dwn:
1790           k = Key_C_Dwn;
1791           break;
1792         case Key_Up:
1793           k = Key_C_Up;
1794           break;
1795         case Key_Lft:
1796           k = Key_C_Lft;
1797           break;
1798         case Key_Rgt:
1799           k = Key_C_Rgt;
1800           break;
1801         case Key_Home:
1802           k = Key_C_Home;
1803           break;
1804         case Key_PgDn:
1805           k = Key_C_PgDn;
1806           break;
1807         case Key_PgUp:
1808           k = Key_C_PgUp;
1809           break;
1810         case Key_End:
1811           k = Key_C_End;
1812           break;
1813       }
1814     }
1815   } else if(k == Key_BS) {
1816     // Under Linux we could use TIOCLINUX fn. 6 to read shift states on console
1817     // Of course it is very unportable but should produce good results :-)
1818     int shifts = 6;
1819     if(ioctl(fileno(stdin), TIOCLINUX, &shifts) == -1)
1820       shifts = 0;
1821     if(shifts & ALT)
1822       k = Key_A_BS;
1823     else if(shifts & GCTRL)
1824       k = Key_C_BS;
1825   }
1826   #elif __BEOS__
1827   {
1828     int shifts = BeOSShiftState();
1829     if(shifts & (ALT))
1830       switch(k){
1831         case Key_0: k=Key_A_0; break;
1832         case Key_1: k=Key_A_1; break;
1833         case Key_2: k=Key_A_2; break;
1834         case Key_3: k=Key_A_3; break;
1835         case Key_4: k=Key_A_4; break;
1836         case Key_5: k=Key_A_5; break;
1837         case Key_6: k=Key_A_6; break;
1838         case Key_7: k=Key_A_7; break;
1839         case Key_8: k=Key_A_8; break;
1840         case Key_9: k=Key_A_9; break;
1841         case Key_A: k=Key_A_A; break;
1842         case Key_B: k=Key_A_B; break;
1843         case Key_C: k=Key_A_C; break;
1844         case Key_D: k=Key_A_D; break;
1845         case Key_E: k=Key_A_E; break;
1846         case Key_F: k=Key_A_F; break;
1847         case Key_G: k=Key_A_G; break;
1848         case Key_H: k=Key_A_H; break;
1849         case Key_I: k=Key_A_I; break;
1850         case Key_J: k=Key_A_J; break;
1851         case Key_K: k=Key_A_K; break;
1852         case Key_L: k=Key_A_L; break;
1853         case Key_M: k=Key_A_M; break;
1854         case Key_N: k=Key_A_N; break;
1855         case Key_O: k=Key_A_O; break;
1856         case Key_P: k=Key_A_P; break;
1857         case Key_Q: k=Key_A_Q; break;
1858         case Key_R: k=Key_A_R; break;
1859         case Key_S: k=Key_A_S; break;
1860         case Key_T: k=Key_A_T; break;
1861         case Key_U: k=Key_A_U; break;
1862         case Key_V: k=Key_A_V; break;
1863         case Key_W: k=Key_A_W; break;
1864         case Key_X: k=Key_A_X; break;
1865         case Key_Y: k=Key_A_Y; break;
1866         case Key_Z: k=Key_A_Z; break;
1867         case Key_F1: k=Key_A_F1; break;
1868         case Key_F2: k=Key_A_F2; break;
1869         case Key_F3: k=Key_A_F3; break;
1870         case Key_F4: k=Key_A_F4; break;
1871         case Key_F5: k=Key_A_F5; break;
1872         case Key_F6: k=Key_A_F6; break;
1873         case Key_F7: k=Key_A_F7; break;
1874         case Key_F8: k=Key_A_F8; break;
1875         case Key_F9: k=Key_A_F9; break;
1876         case Key_F10: k=Key_A_F10; break;
1877         case Key_F11: k=Key_A_F11; break;
1878         case Key_F12: k=Key_A_F12; break;
1879         case Key_BS:  k=Key_A_BS; break;
1880         case Key_Ent: k=Key_A_Ent; break;
1881         case Key_Tab: k=Key_A_Tab; break;
1882         case Key_Dwn: k = Key_A_Dwn; break;
1883         case Key_Up:  k = Key_A_Up;  break;
1884         case Key_Lft: k = Key_A_Lft; break;
1885         case Key_Rgt: k = Key_A_Rgt; break;
1886         case Key_Home: k = Key_A_Home; break;
1887         case Key_PgDn: k = Key_A_PgDn; break;
1888         case Key_PgUp: k = Key_A_PgUp; break;
1889         case Key_End: k = Key_A_End; break;
1890         // case Key_: k=Key_A_; break;
1891         default: break;
1892       }
1893     else if(shifts & (LSHIFT | RSHIFT))
1894       switch(k){
1895         case Key_F1: k=Key_S_F1; break;
1896         case Key_F2: k=Key_S_F2; break;
1897         case Key_F3: k=Key_S_F3; break;
1898         case Key_F4: k=Key_S_F4; break;
1899         case Key_F5: k=Key_S_F5; break;
1900         case Key_F6: k=Key_S_F6; break;
1901         case Key_F7: k=Key_S_F7; break;
1902         case Key_F8: k=Key_S_F8; break;
1903         case Key_F9: k=Key_S_F9; break;
1904         case Key_F10: k=Key_S_F10; break;
1905         case Key_F11: k=Key_S_F11; break;
1906         case Key_F12: k=Key_S_F12; break;
1907         case Key_Tab: k=Key_S_Tab; break;
1908         default: KCodScn(k) |= 0x80; break;
1909       }
1910     else if(shifts & GCTRL) {
1911       switch(k) {
1912         case Key_Ent: k = Key_C_Ent; break;
1913         case Key_Ins: k = Key_C_Ins; break;
1914         case Key_Del: k = Key_C_Del; break;
1915         case Key_Dwn: k = Key_C_Dwn; break;
1916         case Key_Up:  k = Key_C_Up;  break;
1917         case Key_Lft: k = Key_C_Lft; break;
1918         case Key_Rgt: k = Key_C_Rgt; break;
1919         case Key_Home: k = Key_C_Home; break;
1920         case Key_PgDn: k = Key_C_PgDn; break;
1921         case Key_PgUp: k = Key_C_PgUp; break;
1922         case Key_End: k = Key_C_End; break;
1923         case Key_BS: k = Key_C_BS; break;
1924         case Key_F1: k=Key_C_F1; break;
1925         case Key_F2: k=Key_C_F2; break;
1926         case Key_F3: k=Key_C_F3; break;
1927         case Key_F4: k=Key_C_F4; break;
1928         case Key_F5: k=Key_C_F5; break;
1929         case Key_F6: k=Key_C_F6; break;
1930         case Key_F7: k=Key_C_F7; break;
1931         case Key_F8: k=Key_C_F8; break;
1932         case Key_F9: k=Key_C_F9; break;
1933         case Key_F10: k=Key_C_F10; break;
1934         case Key_F11: k=Key_C_F11; break;
1935         case Key_F12: k=Key_C_F12; break;
1936       }
1937     }
1938   }
1939   #endif
1940 
1941 //  TO_PORT_TAG: kbxget_raw(3)
1942 #if defined(__WIN32__)
1943   KeyCtrlState = (gkey)(inp.Event.KeyEvent.dwControlKeyState & 0xFFFF);
1944 #endif
1945   return k;
1946 }
1947 
1948 
1949 //  ------------------------------------------------------------------
1950 //  Get key stroke
1951 
kbxget(int mode)1952 gkey kbxget(int mode) {
1953 
1954   return keyscanxlat(kbxget_raw(mode));
1955 }
1956 
1957 
1958 //  ------------------------------------------------------------------
1959 //  Returns keycode of waiting key or zero if none
1960 
kbxhit()1961 gkey kbxhit() {
1962 
1963   return kbxget(0x01);
1964 }
1965 
1966 
1967 //  ------------------------------------------------------------------
1968 //  Clears internal keyboard buffer
1969 
kbclear()1970 void kbclear() {
1971 
1972   while(gkbd.kbuf != NULL) {
1973 
1974     KBuf *kbuf = gkbd.kbuf->next;
1975     throw_free(gkbd.kbuf);
1976     gkbd.kbuf = kbuf;
1977   }
1978 }
1979 
1980 
1981 //  ------------------------------------------------------------------
1982 //  Clear keyboard buffer
1983 
clearkeys()1984 void clearkeys() {
1985 
1986   while(kbxhit())
1987     kbxget(0x00);
1988 }
1989 
1990 
1991 //  ------------------------------------------------------------------
1992 //  Puts a keystroke into the CXL keyboard "buffer"
1993 
1994 bool gKeystacking = false;
1995 
kbput(gkey xch)1996 int kbput(gkey xch)
1997 {
1998   if (gKeystacking)
1999   {
2000     if (gkbd.kbuf != NULL)
2001       return -1;
2002 
2003     gKeystacking = false;
2004   }
2005 
2006   KBuf* kbuf;
2007   KBuf* temp;
2008 
2009   // allocate space for another keypress record
2010   kbuf=(KBuf*)throw_malloc(sizeof(KBuf));
2011 
2012   // find last record in linked list
2013   if((temp=gkbd.kbuf)!=NULL)
2014     for(;temp->next!=NULL;temp=temp->next);
2015 
2016   // add new record to end of linked list
2017   kbuf->next=NULL;
2018   kbuf->prev=temp;
2019   if(temp != NULL)
2020     temp->next=kbuf;
2021 
2022   // add keypress info to new record
2023   kbuf->xch=xch;
2024 
2025   // if kbuf pointer was NULL, point it to new record
2026   if(gkbd.kbuf == NULL)
2027     gkbd.kbuf=kbuf;
2028 
2029   // return normally
2030   return 0;
2031 }
2032 
2033 
2034 //  ------------------------------------------------------------------
2035 //  Put keys into the real keyboard buffer
2036 
kbput_(gkey xch)2037 gkey kbput_(gkey xch) {
2038 
2039   #if defined(__MSDOS__)
2040 
2041   #if defined(__DJGPP__)
2042   if(gkbd.extkbd) {
2043     i86 cpu;
2044 
2045     cpu.ah(0x05);
2046     cpu.cx((word)xch);
2047     cpu.genint(0x16);
2048   }
2049   else {
2050   #endif
2051 
2052   #define BufStart (word)peek(0x40,0x80)
2053   #define BufEnd   (word)peek(0x40,0x82)
2054   #define BufHead  (word)peek(0x40,0x1A)
2055   #define BufTail  (word)peek(0x40,0x1C)
2056   #define BufTail_(a) poke(0x40,0x1C,(word)(a))
2057 
2058   word OldBufTail;
2059 
2060   OldBufTail = BufTail;
2061   if(BufTail == BufEnd-2)
2062     BufTail_(BufStart);
2063   else
2064     BufTail_(BufTail+2);
2065 
2066   if(BufTail == BufHead)
2067     BufTail_(OldBufTail);
2068   else {
2069     poke(0x40, OldBufTail, xch);
2070   }
2071 
2072   #if defined(__DJGPP__)
2073   }
2074   #endif
2075 
2076   #endif
2077 
2078   return xch;
2079 }
2080 
2081 
2082 //  ------------------------------------------------------------------
2083 //  Put keys into the real keyboard buffer
2084 
kbputs_(char * str)2085 void kbputs_(char* str) {
2086 
2087   char* p;
2088 
2089   for(p=str; *p ;p++)
2090     kbput_(gkey((scancode(*p)<<8)|*p));
2091 }
2092 
2093 
2094 //  ------------------------------------------------------------------
2095 //  Change defined "on-key" list pointer
2096 
chgonkey(KBnd * list)2097 KBnd* chgonkey(KBnd* list) {
2098 
2099   KBnd* temp;
2100 
2101   temp = gkbd.onkey;
2102   gkbd.onkey = list;
2103 
2104   return temp;
2105 }
2106 
2107 
2108 //  ------------------------------------------------------------------
2109 //  Frees all active onkey definitions from memory
2110 
freonkey()2111 void freonkey() {
2112 
2113   KBnd* temp;
2114 
2115   // free all onkey records in linked list
2116   while(gkbd.onkey!=NULL) {
2117     temp = gkbd.onkey->prev;
2118     throw_free(gkbd.onkey);
2119     gkbd.onkey = temp;
2120   }
2121 }
2122 
2123 
2124 //  ------------------------------------------------------------------
2125 //  Attaches/detaches a key to a function
2126 
setonkey(gkey keycode,VfvCP func,gkey pass)2127 int setonkey(gkey keycode, VfvCP func, gkey pass) {
2128 
2129   // search for a keycode that is already defined
2130   KBnd* onkey = gkbd.onkey;
2131   while(onkey) {
2132     if(onkey->keycode == keycode)
2133       break;
2134     onkey = onkey->prev;
2135   }
2136 
2137   // check to see if a key detachment is being requested
2138   if(func == NULL) {
2139 
2140     // if no defined onkey was found, then error
2141     if(onkey == NULL)
2142       return 2;
2143 
2144     // delete record from linked list
2145     KBnd* prev = onkey->prev;
2146     KBnd* next = onkey->next;
2147     if(prev)
2148       prev->next = next;
2149     if(next)
2150       next->prev = prev;
2151     if(onkey == gkbd.onkey)
2152       gkbd.onkey = prev;
2153 
2154     // free memory allocated for deleted record
2155     throw_free(onkey);
2156   }
2157   else {
2158 
2159     // if key was found, change func pointer
2160     // otherwise create a new onkey record
2161     if(onkey)
2162       onkey->func = func;
2163     else {
2164 
2165       // allocate memory for new record
2166       onkey = (KBnd*)throw_malloc(sizeof(KBnd));
2167       if(onkey == NULL)
2168         return 1;
2169 
2170       // add new record to linked list
2171       if(gkbd.onkey)
2172         gkbd.onkey->next = onkey;
2173       onkey->prev = gkbd.onkey;
2174       onkey->next = NULL;
2175       gkbd.onkey = onkey;
2176 
2177       // save info in onkey record
2178       gkbd.onkey->keycode = keycode;
2179       gkbd.onkey->func = func;
2180       gkbd.onkey->pass = pass;
2181     }
2182   }
2183 
2184   // return normally
2185   return 0;
2186 }
2187 
2188 
2189 //  ------------------------------------------------------------------
2190 
key_tolower(gkey __keycode)2191 gkey key_tolower(gkey __keycode) {
2192 
2193   byte &ascii = KCodAsc(__keycode);
2194   if(g_isupper(ascii))
2195     ascii = g_tolower(ascii);
2196   return __keycode;
2197 }
2198 
2199 
2200 //  ------------------------------------------------------------------
2201