1 /********************************************************************/
2 /* */
3 /* kbd_inf.c Driver for terminfo keyboard access. */
4 /* Copyright (C) 1989 - 2013 Thomas Mertes */
5 /* */
6 /* This file is part of the Seed7 Runtime Library. */
7 /* */
8 /* The Seed7 Runtime Library is free software; you can */
9 /* redistribute it and/or modify it under the terms of the GNU */
10 /* Lesser General Public License as published by the Free Software */
11 /* Foundation; either version 2.1 of the License, or (at your */
12 /* option) any later version. */
13 /* */
14 /* The Seed7 Runtime Library is distributed in the hope that it */
15 /* will be useful, but WITHOUT ANY WARRANTY; without even the */
16 /* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR */
17 /* PURPOSE. See the GNU Lesser General Public License for more */
18 /* details. */
19 /* */
20 /* You should have received a copy of the GNU Lesser General */
21 /* Public License along with this program; if not, write to the */
22 /* Free Software Foundation, Inc., 51 Franklin Street, */
23 /* Fifth Floor, Boston, MA 02110-1301, USA. */
24 /* */
25 /* Module: Seed7 Runtime Library */
26 /* File: seed7/src/kbd_inf.c */
27 /* Changes: 1994, 2006, 2010, 2013 Thomas Mertes */
28 /* Content: Driver for terminfo keyboard access. */
29 /* */
30 /********************************************************************/
31
32 #include "version.h"
33
34 #ifdef USE_KBD_INF
35 #include "stdlib.h"
36 #include "stdio.h"
37 #include "string.h"
38 #include "time.h"
39
40 #if UNISTD_H_PRESENT
41 #include "unistd.h"
42 #endif
43
44 #include "common.h"
45 #include "striutl.h"
46
47 #ifdef TERM_INCLUDE
48 #include TERM_INCLUDE
49 #ifdef HAS_TERMIOS_H
50 #include "termios.h"
51 #endif
52 #else
53 #ifdef INCL_CURSES_BEFORE_TERM
54 /* The following include is necessary for RM Machines. */
55 #include "curses.h"
56 #endif
57
58 #include "termios.h"
59
60 #ifdef USE_TERMINFO
61 #ifdef INCL_NCURSES_TERM
62 #include "ncurses/term.h"
63 #else
64 #include "term.h"
65 #endif
66 #endif
67 #endif
68
69 #include "errno.h"
70
71 #include "os_decls.h"
72 #include "rtl_err.h"
73 #include "trm_drv.h"
74
75 #ifdef USE_TERMCAP
76 #include "cap_def.h"
77 #endif
78
79 #include "con_drv.h"
80
81 #undef EXTERN
82 #define EXTERN
83 #include "kbd_drv.h"
84
85
86 #undef TRACE_FKEYS
87
88
89 /* #define atexit(x) */
90
91
92 static boolType utf8_mode = FALSE;
93 static boolType key_buffer_filled = FALSE;
94 static int last_key;
95 extern boolType changes;
96 static struct termios term_descr;
97 static struct termios term_bak;
98
99 static boolType keybd_initialized = FALSE;
100
101
102 #define SIZE_KEY_TABLE 131
103
104 static const_cstriType key_table[SIZE_KEY_TABLE];
105 static char erase_ch[2];
106
107 static charType key_code[SIZE_KEY_TABLE] = {
108 /* 0 */ K_BS, K_BS, K_BACKTAB, K_PAD_CENTER, 0,
109 /* 5 */ 0, 0, K_DEL, K_DELLN, K_DOWN,
110 /* 10 */ K_INS, K_END, K_NL, 0, 0,
111 /* 15 */ K_HOME, 0, K_F1, K_F2, K_F3,
112 /* 20 */ K_F4, K_F5, K_F6, K_F7, K_F8,
113 /* 25 */ K_F9, K_F10, K_F11, K_F12, K_SFT_F1,
114 /* 30 */ K_SFT_F2, K_SFT_F3, K_SFT_F4, K_SFT_F5, K_SFT_F6,
115 /* 35 */ K_SFT_F7, K_SFT_F8, K_SFT_F9, K_SFT_F10, K_SFT_F11,
116 /* 40 */ K_SFT_F12, K_CTL_F1, K_CTL_F2, K_CTL_F3, K_CTL_F4,
117 /* 45 */ K_CTL_F5, K_CTL_F6, K_CTL_F7, K_CTL_F8, K_CTL_F9,
118 /* 50 */ K_CTL_F10, K_CTL_F11, K_CTL_F12, 0, 0,
119 /* 55 */ 0, 0, 0, 0, 0,
120 /* 60 */ 0, 0, 0, 0, 0,
121 /* 65 */ K_ALT_F1, K_ALT_F2, K_ALT_F3, K_ALT_F4, K_ALT_F5,
122 /* 70 */ K_ALT_F6, K_ALT_F7, K_ALT_F8, K_ALT_F9, K_ALT_F10,
123 /* 75 */ K_ALT_F11, K_ALT_F12, 0, 0, 0,
124 /* 80 */ K_HOME, K_INS, K_INSLN, K_LEFT, K_END,
125 /* 85 */ K_PGDN, K_PGUP, K_RIGHT, K_END, K_SCRLDN,
126 /* 90 */ K_SCRLUP, 0, K_UP, K_ALT_A, K_ALT_B,
127 /* 95 */ K_ALT_C, K_ALT_D, K_ALT_E, K_ALT_F, K_ALT_G,
128 /* 100 */ K_ALT_H, K_ALT_I, K_ALT_J, K_ALT_K, K_ALT_L,
129 /* 105 */ K_ALT_M, K_ALT_N, K_ALT_O, K_ALT_P, K_ALT_Q,
130 /* 110 */ K_ALT_R, K_ALT_S, K_ALT_T, K_ALT_U, K_ALT_V,
131 /* 115 */ K_ALT_W, K_ALT_X, K_ALT_Y, K_ALT_Z, K_ALT_0,
132 /* 120 */ K_ALT_1, K_ALT_2, K_ALT_3, K_ALT_4, K_ALT_5,
133 /* 125 */ K_ALT_6, K_ALT_7, K_ALT_8, K_ALT_9, K_ESC,
134 /* 130 */ K_DEL};
135
136
137
138 #ifdef OUT_OF_ORDER
show_term_descr(struct termios * curr_term_descr)139 static void show_term_descr (struct termios *curr_term_descr)
140
141 {
142 int pos;
143
144 /* show_term_descr */
145 printf("c_iflag=%x\n", curr_term_descr->c_iflag); /* input modes */
146 printf("c_oflag=%x\n", curr_term_descr->c_oflag); /* output modes */
147 printf("c_cflag=%x\n", curr_term_descr->c_cflag); /* control modes */
148 printf("c_lflag=%x\n", curr_term_descr->c_lflag); /* local modes */
149 for (pos = 0; pos < NCCS; pos++) {
150 printf("%d ", curr_term_descr->c_cc[pos]);
151 } /* for */
152 printf("\n");
153 printf("ECHO=%d\n", (curr_term_descr->c_lflag & ECHO) != 0);
154 printf("ECHOE=%d\n", (curr_term_descr->c_lflag & ECHOE) != 0);
155 printf("ECHOK=%d\n", (curr_term_descr->c_lflag & ECHOK) != 0);
156 printf("ECHONL=%d\n", (curr_term_descr->c_lflag & ECHONL) != 0);
157 printf("ICANON=%d\n", (curr_term_descr->c_lflag & ICANON) != 0);
158 printf("VINTR=%d\n", curr_term_descr->c_cc[VINTR]);
159 printf("VQUIT=%d\n", curr_term_descr->c_cc[VQUIT]);
160 printf("VSTOP=%d\n", curr_term_descr->c_cc[VSTOP]);
161 #ifdef VSTART
162 printf("VSTART=%d\n", curr_term_descr->c_cc[VSTART]);
163 #endif
164 #ifdef VSUSP
165 printf("VSUSP=%d\n", curr_term_descr->c_cc[VSUSP]);
166 #endif
167 printf("VMIN=%d\n", curr_term_descr->c_cc[VMIN]);
168 printf("VTIME=%d\n", curr_term_descr->c_cc[VTIME]);
169 } /* show_term_descr */
170 #endif
171
172
173
174 /**
175 * Determine if two termios structs are equal.
176 * Comparing with memcmp does not work correctly.
177 * Struct termios has data at and after &c_cc[NCCS].
178 * Therefore memcmp sees differences, even if the
179 * official fields of struct termios are equal.
180 * @return TRUE if the termios structs are equal,
181 * FALSE otherwise.
182 */
term_descr_equal(struct termios * term_descr1,struct termios * term_descr2)183 static boolType term_descr_equal (struct termios *term_descr1, struct termios *term_descr2)
184
185 {
186 int pos;
187 boolType equal;
188
189 /* term_descr_equal */
190 equal = term_descr1->c_iflag == term_descr2->c_iflag &&
191 term_descr1->c_oflag == term_descr2->c_oflag &&
192 term_descr1->c_cflag == term_descr2->c_cflag &&
193 term_descr1->c_lflag == term_descr2->c_lflag;
194 for (pos = 0; pos < NCCS; pos++) {
195 if (term_descr1->c_cc[pos] != term_descr2->c_cc[pos]) {
196 equal = FALSE;
197 } /* if */
198 } /* for */
199 return equal;
200 } /* term_descr_equal */
201
202
203
204 /**
205 * Change the terminal attributes to 'new_term_descr'.
206 * The function tcsetattr() returns success if any of the
207 * requested changes could be successfully carried out.
208 * If doing multiple changes it is necessary to check
209 * with tcgetattr(), that all changes have been performed
210 * successfully.
211 * @return TRUE if the change of the attributes was successful,
212 * FALSE otherwise.
213 */
tcset_term_descr(int file_no,struct termios * new_term_descr)214 static boolType tcset_term_descr (int file_no, struct termios *new_term_descr)
215
216 {
217 struct termios term_descr_check;
218 int trial = 0;
219 boolType succeeded = FALSE;
220
221 /* tcset_term_descr */
222 do {
223 trial++;
224 if (tcsetattr(file_no, TCSANOW, new_term_descr) == 0 &&
225 tcgetattr(file_no, &term_descr_check) == 0 &&
226 term_descr_equal(new_term_descr, &term_descr_check)) {
227 succeeded = TRUE;
228 } /* if */
229 } while (!succeeded && trial < 10);
230 /* show_term_descr(new_term_descr);
231 show_term_descr(&term_descr_check); */
232 /* printf("trial=%d\n", trial); */
233 return succeeded;
234 } /* tcset_term_descr */
235
236
237
238 /**
239 * Change the terminal attributes 'vmin' and 'vtime'.
240 * The function tcsetattr() returns success if any of the
241 * requested changes could be successfully carried out.
242 * If doing multiple changes it is necessary to check
243 * with tcgetattr(), that all changes have been performed
244 * successfully.
245 * @return TRUE if the change of the attributes was successful,
246 * FALSE otherwise.
247 */
tcset_vmin_vtime(int file_no,int vmin,int vtime)248 static boolType tcset_vmin_vtime (int file_no, int vmin, int vtime)
249
250 {
251 struct termios term_descr_check;
252 int trial = 0;
253 boolType succeeded = FALSE;
254
255 /* tcset_vmin_vtime */
256 term_descr.c_cc[VMIN] = (cc_t) vmin;
257 term_descr.c_cc[VTIME] = (cc_t) vtime;
258 do {
259 trial++;
260 if (tcsetattr(file_no, TCSANOW, &term_descr) == 0 &&
261 tcgetattr(file_no, &term_descr_check) == 0 &&
262 term_descr_check.c_cc[VMIN] == vmin &&
263 term_descr_check.c_cc[VTIME] == vtime) {
264 succeeded = TRUE;
265 } /* if */
266 } while (!succeeded && trial < 10);
267 return succeeded;
268 } /* tcset_vmin_vtime */
269
270
271
read_char_if_present(ucharType * ch)272 static boolType read_char_if_present (ucharType *ch)
273
274 {
275 int file_no;
276 boolType result;
277
278 /* read_char_if_present */
279 file_no = fileno(stdin);
280 tcset_vmin_vtime(file_no, 0, 10); /* Time in units of 0.1 seconds */
281 result = read(file_no, ch, 1) == 1;
282 tcset_vmin_vtime(file_no, 1, 0);
283 return result;
284 } /* read_char_if_present */
285
286
287
consume_chars_present(void)288 static void consume_chars_present (void)
289
290 {
291 int file_no;
292 ucharType ch;
293
294 /* consume_chars_present */
295 file_no = fileno(stdin);
296 tcset_vmin_vtime(file_no, 0, 0);
297 while (read(file_no, &ch, 1) == 1) {
298 /* printf("consume: %d\n", ch); */
299 } /* while */
300 tcset_vmin_vtime(file_no, 1, 0);
301 } /* consume_chars_present */
302
303
304
read_utf8_key(ustriType ustri,size_t ustri_len)305 static charType read_utf8_key (ustriType ustri, size_t ustri_len)
306
307 {
308 memSizeType len;
309 strElemType stri[6];
310 memSizeType dest_len;
311
312 /* read_utf8_key */
313 if (ustri[0] <= 0x7F) {
314 if (ustri_len == 1) {
315 return ustri[0];
316 } else { /* ustri_len == 2 */
317 last_key = ustri[1];
318 key_buffer_filled = TRUE;
319 return ustri[0];
320 } /* if */
321 } else if ((ustri[0] & 0xE0) == 0xC0) {
322 len = 2;
323 } else if ((ustri[0] & 0xF0) == 0xE0) {
324 len = 3;
325 } else if ((ustri[0] & 0xF8) == 0xF0) {
326 len = 4;
327 } else if ((ustri[0] & 0xFC) == 0xF8) {
328 len = 5;
329 } else if ((ustri[0] & 0xFC) == 0xFC) {
330 len = 6;
331 } else {
332 if (ustri_len == 1) {
333 return ustri[0];
334 } else { /* ustri_len == 2 */
335 last_key = ustri[1];
336 key_buffer_filled = TRUE;
337 return ustri[0];
338 } /* if */
339 } /* if */
340 if (ustri_len == 2 && (ustri[1] & 0xC0) != 0x80) {
341 last_key = ustri[1];
342 key_buffer_filled = TRUE;
343 return ustri[0];
344 } else {
345 while (ustri_len < len) {
346 if (read_char_if_present(&ustri[ustri_len])) {
347 ustri[ustri_len + 1] = '\0';
348 } else {
349 ustri[ustri_len] = '\0';
350 } /* if */
351 if (ustri[ustri_len] == '\0') {
352 if (ustri_len == 1) {
353 return ustri[0];
354 } else {
355 return K_UNDEF;
356 } /* if */
357 } else if ((ustri[ustri_len] & 0xC0) != 0x80) {
358 last_key = ustri[ustri_len];
359 key_buffer_filled = TRUE;
360 if (ustri_len == 1) {
361 return ustri[0];
362 } else {
363 return K_UNDEF;
364 } /* if */
365 } /* if */
366 ustri_len++;
367 } /* while */
368 if (utf8_to_stri(stri, &dest_len, ustri, len) == 0 &&
369 dest_len == 1) {
370 return stri[0];
371 } else {
372 return K_UNDEF;
373 } /* if */
374 } /* if */
375 } /* read_utf8_key */
376
377
378
read_f_key(charType actual_char)379 static charType read_f_key (charType actual_char)
380
381 {
382 char in_buffer[101];
383 static char last_partial_match[101];
384 static time_t last_partial_time = 0;
385 size_t pos;
386 int exact_match;
387 int partial_match;
388 int number;
389 size_t len;
390 int key_number;
391 charType result;
392
393 /* read_f_key */
394 if (last_partial_time != 0) {
395 if (time(NULL) - last_partial_time < 5) {
396 /* If the previous call of read_f_key was at most 5 seconds */
397 /* ago and the function key was recognised with a partial */
398 /* match and a timeout the following check is done. It is */
399 /* checked if the new character together with the */
400 /* characters from the partial match of the previous call */
401 /* of read_f_key are a possible begin of a function key. In */
402 /* this case it was wrong that the previous call of */
403 /* read_f_key submits the function key found with a partial */
404 /* match and a timeout. Hopefully the function key did not */
405 /* damage something. Normally the function key deliverd in */
406 /* such a case is the escape key. For that reason escape */
407 /* should not start any dangerous function. Terminating a */
408 /* function with escape should be safe. The following */
409 /* actions are done to avoid further damage. As long as */
410 /* characters are already typed in they are read and */
411 /* discarded. If no more characters are present in the */
412 /* input queue the function returns K_NULLCMD. The */
413 /* K_NULLCMD should do nothing in every application. */
414 /* fprintf(stderr, "<possible garbage keys>"); */
415 pos = strlen(last_partial_match);
416 last_partial_match[pos] = (char) actual_char;
417 last_partial_match[pos + 1] = '\0';
418 pos++;
419 key_number = 0;
420 exact_match = 0;
421 partial_match = 0;
422 for (number = 0; number < SIZE_KEY_TABLE; number++) {
423 if (key_table[number] != NULL) {
424 len = strlen(key_table[number]);
425 if (pos <= len) {
426 if (strncmp(key_table[number], last_partial_match,
427 pos) == 0) {
428 if (pos == len) {
429 exact_match++;
430 key_number = number;
431 } else {
432 partial_match++;
433 } /* if */
434 } /* if */
435 } /* if */
436 } /* if */
437 } /* for */
438 if (exact_match != 0 || partial_match != 0) {
439 #ifdef TRACE_FKEYS
440 printf("exact %d partial %d - consume_chars_present\n",
441 exact_match, partial_match);
442 #endif
443 consume_chars_present();
444 last_partial_time = 0;
445 return K_NULLCMD;
446 } /* if */
447 } /* if */
448 last_partial_time = 0;
449 } /* if */
450 in_buffer[0] = (char) actual_char;
451 in_buffer[1] = '\0';
452 pos = 1;
453 do {
454 key_number = 0;
455 exact_match = 0;
456 partial_match = 0;
457 for (number = 0; number < SIZE_KEY_TABLE; number++) {
458 if (key_table[number] != NULL) {
459 len = strlen(key_table[number]);
460 if (pos <= len) {
461 if (strncmp(key_table[number], in_buffer,
462 pos) == 0) {
463 if (pos == len) {
464 exact_match++;
465 key_number = number;
466 } else {
467 partial_match++;
468 } /* if */
469 } /* if */
470 } /* if */
471 } /* if */
472 } /* for */
473 #ifdef TRACE_FKEYS
474 { char *cha = in_buffer;
475 printf("key match \"");
476 while (*cha != 0) {
477 if (*cha == '\"' || *cha == '\\') {
478 printf("\%c", *cha);
479 } else if (*cha >= ' ' && *cha <= '~') {
480 printf("%c", *cha);
481 } else {
482 printf("\\%d\\", (int) *cha);
483 } /* if */
484 cha++;
485 } /* while */
486 printf("\" exact %d partial %d\n", exact_match, partial_match);
487 }
488 #endif
489 if (exact_match == 0) {
490 if (partial_match != 0) {
491 if (read(fileno(stdin), &in_buffer[pos], 1) != 1) {
492 in_buffer[pos] = (char) EOF;
493 } /* if */
494 in_buffer[pos + 1] = '\0';
495 } /* if */
496 } else {
497 if (partial_match != 0) {
498 if (read_char_if_present((ucharType *) &in_buffer[pos])) {
499 in_buffer[pos + 1] = '\0';
500 } else {
501 strcpy(last_partial_match, in_buffer);
502 last_partial_time = time(NULL);
503 partial_match = 0;
504 } /* if */
505 } /* if */
506 } /* if */
507 pos++;
508 } while (partial_match != 0 && pos < 100);
509 if (exact_match == 1) {
510 result = key_code[key_number];
511 } else {
512 if (pos == 2 || pos == 3) {
513 if (utf8_mode) {
514 result = read_utf8_key((ustriType) in_buffer, pos - 1);
515 } else {
516 if (pos == 2) {
517 result = actual_char;
518 } else { /* if (pos == 3) { */
519 last_key = in_buffer[1];
520 key_buffer_filled = TRUE;
521 result = actual_char;
522 } /* if */
523 } /* if */
524 } else {
525 result = K_UNDEF;
526 } /* if */
527 } /* if */
528 return result;
529 } /* read_f_key */
530
531
532
utf8_init(void)533 static void utf8_init (void)
534
535 {
536 char *s;
537
538 /* utf8_init */
539 if (((s = getenv("LC_ALL")) && *s) ||
540 ((s = getenv("LC_CTYPE")) && *s) ||
541 ((s = getenv("LANG")) && *s)) {
542 if (strstr(s, "UTF-8") || strstr(s, "utf8")) {
543 utf8_mode = TRUE;
544 } /* if */
545 } else {
546 utf8_mode = TRUE;
547 } /* if */
548 } /* utf8_init */
549
550
551
key_table_init(void)552 static void key_table_init (void)
553
554 {
555 int number;
556 int num2;
557
558 /* key_table_init */
559 /* fprintf(stderr, "keypad_xmit=\"%s\"\n", keypad_xmit); */
560 putcontrol(keypad_xmit); /* keypad_transmit_mode */
561 key_table[ 0] = erase_ch; /* K_BS */
562 /* printf("erase_ch %d\n", erase_ch[0]); */
563 if (key_backspace != NULL && strcmp(key_backspace, erase_ch) != 0) {
564 /* If the backspace character defined in the terminfo/termcap */
565 /* database is different from the erase character defined by */
566 /* the terminal device it is defined additionally as K_BS. */
567 key_table[ 1] = key_backspace; /* K_BS */
568 } else {
569 key_table[ 1] = NULL;
570 } /* if */
571 /* printf("key_backspace %d\n", key_backspace[0]); */
572 key_table[ 2] = key_btab; /* K_BACKTAB */
573 key_table[ 3] = key_b2; /* K_PAD_CENTER */
574 key_table[ 4] = key_catab;
575 key_table[ 5] = key_clear;
576 key_table[ 6] = key_ctab;
577 key_table[ 7] = key_dc; /* K_DEL */
578 key_table[ 8] = key_dl; /* K_DELLN */
579 key_table[ 9] = key_down; /* K_DOWN */
580 key_table[10] = key_eic; /* K_INS */
581 key_table[11] = key_end; /* K_END */
582 key_table[12] = key_enter; /* K_NL */
583 key_table[13] = key_eol;
584 key_table[14] = key_eos;
585 key_table[15] = key_home; /* K_HOME */
586 key_table[16] = key_f0;
587 key_table[17] = key_f1; /* K_F1 */
588 key_table[18] = key_f2; /* K_F2 */
589 key_table[19] = key_f3; /* K_F3 */
590 key_table[20] = key_f4; /* K_F4 */
591 key_table[21] = key_f5; /* K_F5 */
592 key_table[22] = key_f6; /* K_F6 */
593 key_table[23] = key_f7; /* K_F7 */
594 key_table[24] = key_f8; /* K_F8 */
595 key_table[25] = key_f9; /* K_F9 */
596 key_table[26] = key_f10; /* K_F10 */
597 key_table[27] = key_f11; /* K_F11 */
598 key_table[28] = key_f12; /* K_F12 */
599 key_table[29] = key_f13; /* K_SFT_F1 */
600 key_table[30] = key_f14; /* K_SFT_F2 */
601 key_table[31] = key_f15; /* K_SFT_F3 */
602 key_table[32] = key_f16; /* K_SFT_F4 */
603 key_table[33] = key_f17; /* K_SFT_F5 */
604 key_table[34] = key_f18; /* K_SFT_F6 */
605 key_table[35] = key_f19; /* K_SFT_F7 */
606 key_table[36] = key_f20; /* K_SFT_F8 */
607 key_table[37] = key_f21; /* K_SFT_F9 */
608 key_table[38] = key_f22; /* K_SFT_F10 */
609 key_table[39] = key_f23; /* K_SFT_F11 */
610 key_table[40] = key_f24; /* K_SFT_F12 */
611 key_table[41] = key_f25; /* K_CTL_F1 */
612 key_table[42] = key_f26; /* K_CTL_F2 */
613 key_table[43] = key_f27; /* K_CTL_F3 */
614 key_table[44] = key_f28; /* K_CTL_F4 */
615 key_table[45] = key_f29; /* K_CTL_F5 */
616 key_table[46] = key_f30; /* K_CTL_F6 */
617 key_table[47] = key_f31; /* K_CTL_F7 */
618 key_table[48] = key_f32; /* K_CTL_F8 */
619 key_table[49] = key_f33; /* K_CTL_F9 */
620 key_table[50] = key_f34; /* K_CTL_F10 */
621 key_table[51] = key_f35; /* K_CTL_F11 */
622 key_table[52] = key_f36; /* K_CTL_F12 */
623 key_table[53] = key_f37;
624 key_table[54] = key_f38;
625 key_table[55] = key_f39;
626 key_table[56] = key_f40;
627 key_table[57] = key_f41;
628 key_table[58] = key_f42;
629 key_table[59] = key_f43;
630 key_table[60] = key_f44;
631 key_table[61] = key_f45;
632 key_table[62] = key_f46;
633 key_table[63] = key_f47;
634 key_table[64] = key_f48;
635 key_table[65] = key_f49; /* K_ALT_F1 */
636 key_table[66] = key_f50; /* K_ALT_F2 */
637 key_table[67] = key_f51; /* K_ALT_F3 */
638 key_table[68] = key_f52; /* K_ALT_F4 */
639 key_table[69] = key_f53; /* K_ALT_F5 */
640 key_table[70] = key_f54; /* K_ALT_F6 */
641 key_table[71] = key_f55; /* K_ALT_F7 */
642 key_table[72] = key_f56; /* K_ALT_F8 */
643 key_table[73] = key_f57; /* K_ALT_F9 */
644 key_table[74] = key_f58; /* K_ALT_F10 */
645 key_table[75] = key_f59; /* K_ALT_F11 */
646 key_table[76] = key_f60; /* K_ALT_F12 */
647 key_table[77] = key_f61;
648 key_table[78] = key_f62;
649 key_table[79] = key_f63;
650 key_table[80] = key_find; /* K_HOME */
651 key_table[81] = key_ic; /* K_INS */
652 key_table[82] = key_il; /* K_INSLN */
653 key_table[83] = key_left; /* K_LEFT */
654 key_table[84] = key_ll; /* K_END */
655 key_table[85] = key_npage; /* K_PGDN */
656 key_table[86] = key_ppage; /* K_PGUP */
657 key_table[87] = key_right; /* K_RIGHT */
658 key_table[88] = key_select; /* K_END */
659 key_table[89] = key_sf; /* K_SCRLDN */
660 key_table[90] = key_sr; /* K_SCRLUP */
661 key_table[91] = key_stab;
662 key_table[92] = key_up; /* K_UP */
663 key_table[93] = "\033a"; /* K_ALT_A */
664 key_table[94] = "\033b"; /* K_ALT_B */
665 key_table[95] = "\033c"; /* K_ALT_C */
666 key_table[96] = "\033d"; /* K_ALT_D */
667 key_table[97] = "\033e"; /* K_ALT_E */
668 key_table[98] = "\033f"; /* K_ALT_F */
669 key_table[99] = "\033g"; /* K_ALT_G */
670 key_table[100] = "\033h"; /* K_ALT_H */
671 key_table[101] = "\033i"; /* K_ALT_I */
672 key_table[102] = "\033j"; /* K_ALT_J */
673 key_table[103] = "\033k"; /* K_ALT_K */
674 key_table[104] = "\033l"; /* K_ALT_L */
675 key_table[105] = "\033m"; /* K_ALT_M */
676 key_table[106] = "\033n"; /* K_ALT_N */
677 key_table[107] = "\033o"; /* K_ALT_O */
678 key_table[108] = "\033p"; /* K_ALT_P */
679 key_table[109] = "\033q"; /* K_ALT_Q */
680 key_table[110] = "\033r"; /* K_ALT_R */
681 key_table[111] = "\033s"; /* K_ALT_S */
682 key_table[112] = "\033t"; /* K_ALT_T */
683 key_table[113] = "\033u"; /* K_ALT_U */
684 key_table[114] = "\033v"; /* K_ALT_V */
685 key_table[115] = "\033w"; /* K_ALT_W */
686 key_table[116] = "\033x"; /* K_ALT_X */
687 key_table[117] = "\033y"; /* K_ALT_Y */
688 key_table[118] = "\033z"; /* K_ALT_Z */
689 key_table[119] = "\0330"; /* K_ALT_0 */
690 key_table[120] = "\0331"; /* K_ALT_1 */
691 key_table[121] = "\0332"; /* K_ALT_2 */
692 key_table[122] = "\0333"; /* K_ALT_3 */
693 key_table[123] = "\0334"; /* K_ALT_4 */
694 key_table[124] = "\0335"; /* K_ALT_5 */
695 key_table[125] = "\0336"; /* K_ALT_6 */
696 key_table[126] = "\0337"; /* K_ALT_7 */
697 key_table[127] = "\0338"; /* K_ALT_8 */
698 key_table[128] = "\0339"; /* K_ALT_9 */
699 key_table[129] = "\033"; /* K_ESC */
700 key_table[130] = "\177"; /* K_DEL */
701 /* Some function key definitions start with a printable */
702 /* character. This makes absolutely no sense and confuses the */
703 /* function key recognition. Therefore such definitions are */
704 /* thrown out here. */
705 for (number = 0; number < SIZE_KEY_TABLE; number++) {
706 #ifdef TRACE_FKEYS
707 if (key_table[number] != NULL) {
708 const_cstriType ch_ptr;
709
710 fprintf(stderr, "key%d=\"", number);
711 ch_ptr = key_table[number];
712 while (*ch_ptr != '\0') {
713 if (*ch_ptr <= 31) {
714 fprintf(stderr, "^%c", *ch_ptr + '@');
715 } else if (*ch_ptr == '^' || *ch_ptr == '\\') {
716 fprintf(stderr, "%c%c", *ch_ptr, *ch_ptr);
717 } else if (*ch_ptr <= 126) {
718 fprintf(stderr, "%c", *ch_ptr);
719 } else {
720 fprintf(stderr, "\\%3o", *ch_ptr);
721 } /* if */
722 ch_ptr++;
723 } /* while */
724 fprintf(stderr, "\"\n");
725 } else {
726 fprintf(stderr, "key%d=NULL\n", number);
727 } /* if */
728 #endif
729 if (key_table[number] != NULL &&
730 key_table[number][0] >= ' ' && key_table[number][0] <= '~') {
731 /* fprintf(stderr, "key%d=\"%s\" thrown out\n",
732 number, key_table[number]); */
733 key_table[number] = NULL;
734 } /* if */
735 } /* for */
736 /* Sometimes there are double entries in the function key */
737 /* definitions. This makes absolutely no sense and confuses the */
738 /* function key recognition. Therefore such definitions are */
739 /* thrown out here. */
740 for (number = 0; number < SIZE_KEY_TABLE; number++) {
741 for (num2 = number + 1; num2 < SIZE_KEY_TABLE; num2++) {
742 if (key_table[number] != NULL && key_table[num2] != NULL &&
743 strcmp(key_table[number], key_table[num2]) == 0) {
744 /* fprintf(stderr, "key%d=kex%d=\"%s\"\n",
745 number, num2, key_table[number]); */
746 key_table[num2] = NULL;
747 } /* if */
748 } /* for */
749 } /* for */
750 } /* key_table_init */
751
752
753
kbdShut(void)754 void kbdShut (void)
755
756 { /* kbdShut */
757 if (keybd_initialized) {
758 tcset_term_descr(fileno(stdin), &term_bak);
759 if (caps_initialized) {
760 /* fprintf(stderr, "keypad_local=\"%s\"\n", keypad_local); */
761 putcontrol(keypad_local); /* out of keypad transmit mode */
762 } /* if */
763 keybd_initialized = FALSE;
764 } /* if */
765 } /* kbdShut */
766
767
768
kbd_init(void)769 static void kbd_init (void)
770
771 {
772 int file_no;
773
774 /* kbd_init */
775 if (!findTermDll()) {
776 logError(printf("kbd_init: findTermDll() failed.\n"););
777 } else {
778 if (!caps_initialized) {
779 getcaps();
780 } /* if */
781 file_no = fileno(stdin);
782 if (tcgetattr(file_no, &term_descr) != 0) {
783 printf("kbd_init: tcgetattr(%d, ...) failed:\n"
784 "errno=%d\nerror: %s\n",
785 file_no, errno, strerror(errno));
786 } else {
787 /* show_term_descr(&term_descr); */
788 memcpy(&term_bak, &term_descr, sizeof(struct termios));
789 erase_ch[0] = (char) term_descr.c_cc[VERASE];
790 erase_ch[1] = '\0';
791 /* printf("erase_ch %d\n", erase_ch[0]); */
792 term_descr.c_lflag &= (unsigned int) ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON);
793 term_descr.c_cc[VINTR] = (cc_t) -1;
794 term_descr.c_cc[VQUIT] = (cc_t) -1;
795 term_descr.c_cc[VSTOP] = (cc_t) -1;
796 #ifdef VSTART
797 term_descr.c_cc[VSTART] = (cc_t) -1;
798 #endif
799 #ifdef VSUSP
800 term_descr.c_cc[VSUSP] = (cc_t) -1;
801 #endif
802 term_descr.c_cc[VMIN] = 1;
803 term_descr.c_cc[VTIME] = 0;
804 if (!tcset_term_descr(file_no, &term_descr)) {
805 printf("kbd_init: tcsetattr(%d, VMIN=1) failed:\n"
806 "errno=%d\nerror: %s\n",
807 file_no, errno, strerror(errno));
808 /* show_term_descr(&term_descr); */
809 } else {
810 keybd_initialized = TRUE;
811 atexit(kbdShut);
812 if (getcaps()) {
813 key_table_init();
814 } /* if */
815 utf8_init();
816 fflush(stdout);
817 } /* if */
818 } /* if */
819 } /* if */
820 } /* kbd_init */
821
822
823
kbdKeyPressed(void)824 boolType kbdKeyPressed (void)
825
826 {
827 int file_no;
828 char buffer;
829 boolType result;
830
831 /* kbdKeyPressed */
832 if (!keybd_initialized) {
833 kbd_init();
834 } /* if */
835 if (!keybd_initialized) {
836 logError(printf("kbdKeyPressed: kbd_init() failed to open the keyboard.\n"););
837 raise_error(FILE_ERROR);
838 result = FALSE;
839 } else if (key_buffer_filled) {
840 result = TRUE;
841 } else {
842 if (changes) {
843 conFlush();
844 } /* if */
845 file_no = fileno(stdin);
846 if (!tcset_vmin_vtime(file_no, 0, 0)) {
847 printf("kbdKeyPressed: tcsetattr(%d, VMIN=0) failed:\n"
848 "errno=%d\nerror: %s\n",
849 file_no, errno, strerror(errno));
850 result = FALSE;
851 } else {
852 if (read(file_no, &buffer, 1) == 1) {
853 result = TRUE;
854 last_key = buffer;
855 key_buffer_filled = TRUE;
856 } else {
857 result = FALSE;
858 } /* if */
859 if (!tcset_vmin_vtime(file_no, 1, 0)) {
860 printf("kbdKeyPressed: tcsetattr(%d, VMIN=1) failed:\n"
861 "errno=%d\nerror: %s\n",
862 file_no, errno, strerror(errno));
863 } /* if */
864 } /* if */
865 } /* if */
866 return result;
867 } /* kbdKeyPressed */
868
869
870
kbdGetc(void)871 charType kbdGetc (void)
872
873 {
874 ucharType ch;
875 charType result;
876
877 /* kbdGetc */
878 if (!keybd_initialized) {
879 kbd_init();
880 } /* if */
881 if (!keybd_initialized) {
882 logError(printf("kbdGetc: kbd_init() failed to open the keyboard.\n"););
883 raise_error(FILE_ERROR);
884 result = (charType) EOF;
885 } else if (key_buffer_filled) {
886 key_buffer_filled = FALSE;
887 result = (charType) last_key;
888 } else {
889 if (changes) {
890 conFlush();
891 } /* if */
892 if (read(fileno(stdin), &ch, 1) != 1) {
893 result = (charType) EOF;
894 } else {
895 result = (charType) ch;
896 } /* if */
897 } /* if */
898 result = read_f_key(result);
899 /* fprintf(stderr, "<%d>", result); */
900 return result;
901 } /* kbdGetc */
902
903
904
kbdRawGetc(void)905 charType kbdRawGetc (void)
906
907 {
908 ucharType ch;
909 charType result;
910
911 /* kbdRawRead */
912 if (!keybd_initialized) {
913 kbd_init();
914 } /* if */
915 if (!keybd_initialized) {
916 logError(printf("kbdRawGetc: kbd_init() failed to open the keyboard.\n"););
917 raise_error(FILE_ERROR);
918 result = (charType) EOF;
919 } else if (key_buffer_filled) {
920 key_buffer_filled = FALSE;
921 result = ((charType) last_key) & 0xFF;
922 } else {
923 if (changes) {
924 conFlush();
925 } /* if */
926 if (read(fileno(stdin), &ch, 1) != 1) {
927 result = (charType) EOF;
928 } else {
929 result = (charType) ch;
930 } /* if */
931 } /* if */
932 /* fprintf(stderr, "<%d>", result); */
933 return result;
934 } /* kbdRawRead */
935
936 #endif
937