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