"Fossies" - the Fresh Open Source Software Archive 
Member "seed7/src/kbd_poll.c" (19 May 2020, 28684 Bytes) of package /linux/misc/seed7_05_20210223.tgz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "kbd_poll.c" see the
Fossies "Dox" file reference documentation.
1 /********************************************************************/
2 /* */
3 /* kbd_poll.c Driver for terminfo keyboard access using poll(). */
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_poll.c */
27 /* Changes: 1994, 2006, 2010, 2013 Thomas Mertes */
28 /* Content: Driver for terminfo keyboard access using poll(). */
29 /* */
30 /********************************************************************/
31
32 #include "version.h"
33
34 #ifdef USE_KBD_POLL
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 "poll.h"
70 #include "errno.h"
71
72 #include "os_decls.h"
73 #include "rtl_err.h"
74 #include "trm_drv.h"
75
76 #ifdef USE_TERMCAP
77 #include "cap_def.h"
78 #endif
79
80 #include "con_drv.h"
81
82 #undef EXTERN
83 #define EXTERN
84 #include "kbd_drv.h"
85
86
87 #undef TRACE_FKEYS
88
89
90 /* #define atexit(x) */
91
92 #define KEY_BUFFER_SIZE 20
93
94 static boolType utf8_mode = FALSE;
95 static ucharType key_buffer[KEY_BUFFER_SIZE];
96 static memSizeType key_buffer_size = 0;
97 extern boolType changes;
98 static struct termios term_descr;
99 static struct termios term_bak;
100
101 static boolType keybd_initialized = FALSE;
102
103
104 #define SIZE_KEY_TABLE 130
105
106 static const_cstriType key_table[SIZE_KEY_TABLE];
107 static char erase_ch[2];
108
109 static charType key_code[SIZE_KEY_TABLE] = {
110 /* 0 */ K_BS, K_BS, K_BACKTAB, K_PAD_CENTER, 0,
111 /* 5 */ 0, 0, K_DEL, K_DELLN, K_DOWN,
112 /* 10 */ K_INS, K_END, K_NL, 0, 0,
113 /* 15 */ K_HOME, 0, K_F1, K_F2, K_F3,
114 /* 20 */ K_F4, K_F5, K_F6, K_F7, K_F8,
115 /* 25 */ K_F9, K_F10, K_F11, K_F12, K_SFT_F1,
116 /* 30 */ K_SFT_F2, K_SFT_F3, K_SFT_F4, K_SFT_F5, K_SFT_F6,
117 /* 35 */ K_SFT_F7, K_SFT_F8, K_SFT_F9, K_SFT_F10, K_SFT_F11,
118 /* 40 */ K_SFT_F12, K_CTL_F1, K_CTL_F2, K_CTL_F3, K_CTL_F4,
119 /* 45 */ K_CTL_F5, K_CTL_F6, K_CTL_F7, K_CTL_F8, K_CTL_F9,
120 /* 50 */ K_CTL_F10, K_CTL_F11, K_CTL_F12, 0, 0,
121 /* 55 */ 0, 0, 0, 0, 0,
122 /* 60 */ 0, 0, 0, 0, 0,
123 /* 65 */ K_ALT_F1, K_ALT_F2, K_ALT_F3, K_ALT_F4, K_ALT_F5,
124 /* 70 */ K_ALT_F6, K_ALT_F7, K_ALT_F8, K_ALT_F9, K_ALT_F10,
125 /* 75 */ K_ALT_F11, K_ALT_F12, 0, 0, 0,
126 /* 80 */ K_HOME, K_INS, K_INSLN, K_LEFT, K_END,
127 /* 85 */ K_PGDN, K_PGUP, K_RIGHT, K_END, K_SCRLDN,
128 /* 90 */ K_SCRLUP, 0, K_UP, K_ALT_A, K_ALT_B,
129 /* 95 */ K_ALT_C, K_ALT_D, K_ALT_E, K_ALT_F, K_ALT_G,
130 /* 100 */ K_ALT_H, K_ALT_I, K_ALT_J, K_ALT_K, K_ALT_L,
131 /* 105 */ K_ALT_M, K_ALT_N, K_ALT_O, K_ALT_P, K_ALT_Q,
132 /* 110 */ K_ALT_R, K_ALT_S, K_ALT_T, K_ALT_U, K_ALT_V,
133 /* 115 */ K_ALT_W, K_ALT_X, K_ALT_Y, K_ALT_Z, K_ALT_0,
134 /* 120 */ K_ALT_1, K_ALT_2, K_ALT_3, K_ALT_4, K_ALT_5,
135 /* 125 */ K_ALT_6, K_ALT_7, K_ALT_8, K_ALT_9, K_DEL};
136
137
138
139 #ifdef OUT_OF_ORDER
140 static void show_term_descr (struct termios *curr_term_descr)
141
142 {
143 int pos;
144
145 /* show_term_descr */
146 printf("c_iflag=%x\n", curr_term_descr->c_iflag); /* input modes */
147 printf("c_oflag=%x\n", curr_term_descr->c_oflag); /* output modes */
148 printf("c_cflag=%x\n", curr_term_descr->c_cflag); /* control modes */
149 printf("c_lflag=%x\n", curr_term_descr->c_lflag); /* local modes */
150 for (pos = 0; pos < NCCS; pos++) {
151 printf("%d ", curr_term_descr->c_cc[pos]);
152 } /* for */
153 printf("\n");
154 printf("ECHO=%d\n", (curr_term_descr->c_lflag & ECHO) != 0);
155 printf("ECHOE=%d\n", (curr_term_descr->c_lflag & ECHOE) != 0);
156 printf("ECHOK=%d\n", (curr_term_descr->c_lflag & ECHOK) != 0);
157 printf("ECHONL=%d\n", (curr_term_descr->c_lflag & ECHONL) != 0);
158 printf("ICANON=%d\n", (curr_term_descr->c_lflag & ICANON) != 0);
159 printf("VINTR=%d\n", curr_term_descr->c_cc[VINTR]);
160 printf("VQUIT=%d\n", curr_term_descr->c_cc[VQUIT]);
161 printf("VSTOP=%d\n", curr_term_descr->c_cc[VSTOP]);
162 #ifdef VSTART
163 printf("VSTART=%d\n", curr_term_descr->c_cc[VSTART]);
164 #endif
165 #ifdef VSUSP
166 printf("VSUSP=%d\n", curr_term_descr->c_cc[VSUSP]);
167 #endif
168 printf("VMIN=%d\n", curr_term_descr->c_cc[VMIN]);
169 printf("VTIME=%d\n", curr_term_descr->c_cc[VTIME]);
170 } /* show_term_descr */
171 #endif
172
173
174
175 /**
176 * Determine if two termios structs are equal.
177 * Comparing with memcmp does not work correctly.
178 * Struct termios has data at and after &c_cc[NCCS].
179 * Therefore memcmp sees differences, even if the
180 * official fields of struct termios are equal.
181 * @return TRUE if the termios structs are equal,
182 * FALSE otherwise.
183 */
184 static boolType term_descr_equal (struct termios *term_descr1, struct termios *term_descr2)
185
186 {
187 int pos;
188 boolType equal;
189
190 /* term_descr_equal */
191 equal = term_descr1->c_iflag == term_descr2->c_iflag &&
192 term_descr1->c_oflag == term_descr2->c_oflag &&
193 term_descr1->c_cflag == term_descr2->c_cflag &&
194 term_descr1->c_lflag == term_descr2->c_lflag;
195 for (pos = 0; pos < NCCS; pos++) {
196 if (term_descr1->c_cc[pos] != term_descr2->c_cc[pos]) {
197 equal = FALSE;
198 } /* if */
199 } /* for */
200 return equal;
201 } /* term_descr_equal */
202
203
204
205 /**
206 * Change the terminal attributes to 'new_term_descr'.
207 * The function tcsetattr() returns success if any of the
208 * requested changes could be successfully carried out.
209 * If doing multiple changes it is necessary to check
210 * with tcgetattr(), that all changes have been performed
211 * successfully.
212 * @return TRUE if the change of the attributes was successful,
213 * FALSE otherwise.
214 */
215 static boolType tcset_term_descr (int file_no, struct termios *new_term_descr)
216
217 {
218 struct termios term_descr_check;
219 int trial = 0;
220 boolType succeeded = FALSE;
221
222 /* tcset_term_descr */
223 do {
224 trial++;
225 if (tcsetattr(file_no, TCSANOW, new_term_descr) == 0 &&
226 tcgetattr(file_no, &term_descr_check) == 0 &&
227 term_descr_equal(new_term_descr, &term_descr_check)) {
228 succeeded = TRUE;
229 } /* if */
230 } while (!succeeded && trial < 10);
231 /* show_term_descr(new_term_descr);
232 show_term_descr(&term_descr_check); */
233 /* printf("trial=%d\n", trial); */
234 return succeeded;
235 } /* tcset_term_descr */
236
237
238
239 static boolType read_char_if_present (ucharType *ch)
240
241 {
242 int file_no;
243 struct pollfd poll_fds[1];
244 int poll_result;
245 boolType result;
246
247 /* read_char_if_present */
248 file_no = fileno(stdin);
249 poll_fds[0].fd = file_no;
250 poll_fds[0].events = POLLIN | POLLPRI;
251 poll_result = poll(poll_fds, 1, 1000 /* milliseconds */);
252 if (poll_result == 1) {
253 /* printf("poll_fds[0].events = %04X\n", poll_fds[0].events);
254 printf("poll_fds[0].revents = %04X\n", poll_fds[0].revents); */
255 result = read(file_no, ch, 1) == 1;
256 } else {
257 result = FALSE;
258 } /* if */
259 #ifdef TRACE_FKEYS
260 printf("read_char_if_present: ch=%u, poll_result=%d, result=%s\n",
261 *ch, poll_result, result ? "TRUE" : "FALSE");
262 #endif
263 return result;
264 } /* read_char_if_present */
265
266
267
268 static charType read_utf8_key (void)
269
270 {
271 memSizeType len;
272 strElemType stri[6];
273 memSizeType dest_len;
274 charType key;
275
276 /* read_utf8_key */
277 if (key_buffer[0] <= 0xBF) {
278 /* key_buffer[0] range 0 to 191 */
279 /* ASCII chars + UTF-8 continuation bytes */
280 key = key_buffer[0];
281 if (key_buffer_size >= 2) {
282 memmove(key_buffer, &key_buffer[1], key_buffer_size - 1);
283 } /* if */
284 key_buffer_size--;
285 return key;
286 } else if (key_buffer[0] <= 0xDF) {
287 /* key_buffer[0] range 192 to 223 (leading bits 110.....) */
288 len = 2;
289 } else if (key_buffer[0] <= 0xEF) {
290 /* key_buffer[0] range 224 to 239 (leading bits 1110....) */
291 len = 3;
292 } else if (key_buffer[0] <= 0xF7) {
293 /* key_buffer[0] range 240 to 247 (leading bits 11110...) */
294 len = 4;
295 } else if (key_buffer[0] <= 0xFB) {
296 /* key_buffer[0] range 248 to 251 (leading bits 111110..) */
297 len = 5;
298 } else { /* if (key_buffer[0] <= 0xFF) { */
299 /* key_buffer[0] range 252 to 255 (leading bits 111111..) */
300 len = 6;
301 } /* if */
302 while (key_buffer_size < len) {
303 if (read_char_if_present(&key_buffer[key_buffer_size])) {
304 key_buffer[key_buffer_size + 1] = '\0';
305 } else {
306 key_buffer[key_buffer_size] = '\0';
307 } /* if */
308 if ((key_buffer[key_buffer_size] & 0xC0) != 0x80) {
309 /* key_buffer[key_buffer_size] not in range 128 to 191 (leading bits not 10......) */
310 key = key_buffer[0];
311 if (key_buffer_size >= 2) {
312 memmove(key_buffer, &key_buffer[1], key_buffer_size - 1);
313 } /* if */
314 key_buffer_size--;
315 return key;
316 } /* if */
317 key_buffer_size++;
318 } /* while */
319 if (utf8_to_stri(stri, &dest_len, key_buffer, len) == 0 && dest_len == 1) {
320 key = stri[0];
321 if (key_buffer_size > len) {
322 memmove(key_buffer, &key_buffer[len], key_buffer_size - len);
323 } /* if */
324 key_buffer_size -= len;
325 return key;
326 } else {
327 key = key_buffer[0];
328 if (key_buffer_size >= 2) {
329 memmove(key_buffer, &key_buffer[1], key_buffer_size - 1);
330 } /* if */
331 key_buffer_size--;
332 return key;
333 } /* if */
334 } /* read_utf8_key */
335
336
337
338 static void utf8_init (void)
339
340 {
341 char *s;
342
343 /* utf8_init */
344 if (((s = getenv("LC_ALL")) && *s) ||
345 ((s = getenv("LC_CTYPE")) && *s) ||
346 ((s = getenv("LANG")) && *s)) {
347 if (strstr(s, "UTF-8") || strstr(s, "utf8")) {
348 utf8_mode = TRUE;
349 } /* if */
350 } else {
351 utf8_mode = TRUE;
352 } /* if */
353 } /* utf8_init */
354
355
356
357 static void key_table_init (void)
358
359 {
360 int number;
361 int num2;
362
363 /* key_table_init */
364 /* fprintf(stderr, "keypad_xmit=\"%s\"\n", keypad_xmit); */
365 putcontrol(keypad_xmit); /* keypad_transmit_mode */
366 key_table[ 0] = erase_ch; /* K_BS */
367 /* printf("erase_ch %d\n", erase_ch[0]); */
368 if (key_backspace != NULL && strcmp(key_backspace, erase_ch) != 0) {
369 /* If the backspace character defined in the terminfo/termcap */
370 /* database is different from the erase character defined by */
371 /* the terminal device it is defined additionally as K_BS. */
372 key_table[ 1] = key_backspace; /* K_BS */
373 } else {
374 key_table[ 1] = NULL;
375 } /* if */
376 /* printf("key_backspace %d\n", key_backspace[0]); */
377 key_table[ 2] = key_btab; /* K_BACKTAB */
378 key_table[ 3] = key_b2; /* K_PAD_CENTER */
379 key_table[ 4] = key_catab;
380 key_table[ 5] = key_clear;
381 key_table[ 6] = key_ctab;
382 key_table[ 7] = key_dc; /* K_DEL */
383 key_table[ 8] = key_dl; /* K_DELLN */
384 key_table[ 9] = key_down; /* K_DOWN */
385 key_table[10] = key_eic; /* K_INS */
386 key_table[11] = key_end; /* K_END */
387 key_table[12] = key_enter; /* K_NL */
388 key_table[13] = key_eol;
389 key_table[14] = key_eos;
390 key_table[15] = key_home; /* K_HOME */
391 key_table[16] = key_f0;
392 key_table[17] = key_f1; /* K_F1 */
393 key_table[18] = key_f2; /* K_F2 */
394 key_table[19] = key_f3; /* K_F3 */
395 key_table[20] = key_f4; /* K_F4 */
396 key_table[21] = key_f5; /* K_F5 */
397 key_table[22] = key_f6; /* K_F6 */
398 key_table[23] = key_f7; /* K_F7 */
399 key_table[24] = key_f8; /* K_F8 */
400 key_table[25] = key_f9; /* K_F9 */
401 key_table[26] = key_f10; /* K_F10 */
402 key_table[27] = key_f11; /* K_F11 */
403 key_table[28] = key_f12; /* K_F12 */
404 key_table[29] = key_f13; /* K_SFT_F1 */
405 key_table[30] = key_f14; /* K_SFT_F2 */
406 key_table[31] = key_f15; /* K_SFT_F3 */
407 key_table[32] = key_f16; /* K_SFT_F4 */
408 key_table[33] = key_f17; /* K_SFT_F5 */
409 key_table[34] = key_f18; /* K_SFT_F6 */
410 key_table[35] = key_f19; /* K_SFT_F7 */
411 key_table[36] = key_f20; /* K_SFT_F8 */
412 key_table[37] = key_f21; /* K_SFT_F9 */
413 key_table[38] = key_f22; /* K_SFT_F10 */
414 key_table[39] = key_f23; /* K_SFT_F11 */
415 key_table[40] = key_f24; /* K_SFT_F12 */
416 key_table[41] = key_f25; /* K_CTL_F1 */
417 key_table[42] = key_f26; /* K_CTL_F2 */
418 key_table[43] = key_f27; /* K_CTL_F3 */
419 key_table[44] = key_f28; /* K_CTL_F4 */
420 key_table[45] = key_f29; /* K_CTL_F5 */
421 key_table[46] = key_f30; /* K_CTL_F6 */
422 key_table[47] = key_f31; /* K_CTL_F7 */
423 key_table[48] = key_f32; /* K_CTL_F8 */
424 key_table[49] = key_f33; /* K_CTL_F9 */
425 key_table[50] = key_f34; /* K_CTL_F10 */
426 key_table[51] = key_f35; /* K_CTL_F11 */
427 key_table[52] = key_f36; /* K_CTL_F12 */
428 key_table[53] = key_f37;
429 key_table[54] = key_f38;
430 key_table[55] = key_f39;
431 key_table[56] = key_f40;
432 key_table[57] = key_f41;
433 key_table[58] = key_f42;
434 key_table[59] = key_f43;
435 key_table[60] = key_f44;
436 key_table[61] = key_f45;
437 key_table[62] = key_f46;
438 key_table[63] = key_f47;
439 key_table[64] = key_f48;
440 key_table[65] = key_f49; /* K_ALT_F1 */
441 key_table[66] = key_f50; /* K_ALT_F2 */
442 key_table[67] = key_f51; /* K_ALT_F3 */
443 key_table[68] = key_f52; /* K_ALT_F4 */
444 key_table[69] = key_f53; /* K_ALT_F5 */
445 key_table[70] = key_f54; /* K_ALT_F6 */
446 key_table[71] = key_f55; /* K_ALT_F7 */
447 key_table[72] = key_f56; /* K_ALT_F8 */
448 key_table[73] = key_f57; /* K_ALT_F9 */
449 key_table[74] = key_f58; /* K_ALT_F10 */
450 key_table[75] = key_f59; /* K_ALT_F11 */
451 key_table[76] = key_f60; /* K_ALT_F12 */
452 key_table[77] = key_f61;
453 key_table[78] = key_f62;
454 key_table[79] = key_f63;
455 key_table[80] = key_find; /* K_HOME */
456 key_table[81] = key_ic; /* K_INS */
457 key_table[82] = key_il; /* K_INSLN */
458 key_table[83] = key_left; /* K_LEFT */
459 key_table[84] = key_ll; /* K_END */
460 key_table[85] = key_npage; /* K_PGDN */
461 key_table[86] = key_ppage; /* K_PGUP */
462 key_table[87] = key_right; /* K_RIGHT */
463 key_table[88] = key_select; /* K_END */
464 key_table[89] = key_sf; /* K_SCRLDN */
465 key_table[90] = key_sr; /* K_SCRLUP */
466 key_table[91] = key_stab;
467 key_table[92] = key_up; /* K_UP */
468 key_table[93] = "\033a"; /* K_ALT_A */
469 key_table[94] = "\033b"; /* K_ALT_B */
470 key_table[95] = "\033c"; /* K_ALT_C */
471 key_table[96] = "\033d"; /* K_ALT_D */
472 key_table[97] = "\033e"; /* K_ALT_E */
473 key_table[98] = "\033f"; /* K_ALT_F */
474 key_table[99] = "\033g"; /* K_ALT_G */
475 key_table[100] = "\033h"; /* K_ALT_H */
476 key_table[101] = "\033i"; /* K_ALT_I */
477 key_table[102] = "\033j"; /* K_ALT_J */
478 key_table[103] = "\033k"; /* K_ALT_K */
479 key_table[104] = "\033l"; /* K_ALT_L */
480 key_table[105] = "\033m"; /* K_ALT_M */
481 key_table[106] = "\033n"; /* K_ALT_N */
482 key_table[107] = "\033o"; /* K_ALT_O */
483 key_table[108] = "\033p"; /* K_ALT_P */
484 key_table[109] = "\033q"; /* K_ALT_Q */
485 key_table[110] = "\033r"; /* K_ALT_R */
486 key_table[111] = "\033s"; /* K_ALT_S */
487 key_table[112] = "\033t"; /* K_ALT_T */
488 key_table[113] = "\033u"; /* K_ALT_U */
489 key_table[114] = "\033v"; /* K_ALT_V */
490 key_table[115] = "\033w"; /* K_ALT_W */
491 key_table[116] = "\033x"; /* K_ALT_X */
492 key_table[117] = "\033y"; /* K_ALT_Y */
493 key_table[118] = "\033z"; /* K_ALT_Z */
494 key_table[119] = "\0330"; /* K_ALT_0 */
495 key_table[120] = "\0331"; /* K_ALT_1 */
496 key_table[121] = "\0332"; /* K_ALT_2 */
497 key_table[122] = "\0333"; /* K_ALT_3 */
498 key_table[123] = "\0334"; /* K_ALT_4 */
499 key_table[124] = "\0335"; /* K_ALT_5 */
500 key_table[125] = "\0336"; /* K_ALT_6 */
501 key_table[126] = "\0337"; /* K_ALT_7 */
502 key_table[127] = "\0338"; /* K_ALT_8 */
503 key_table[128] = "\0339"; /* K_ALT_9 */
504 key_table[129] = "\177"; /* K_DEL */
505 /* Some function key definitions start with a printable */
506 /* character. This makes absolutely no sense and confuses the */
507 /* function key recognition. Therefore such definitions are */
508 /* thrown out here. */
509 for (number = 0; number < SIZE_KEY_TABLE; number++) {
510 #ifdef TRACE_FKEYS
511 if (key_table[number] != NULL) {
512 const_cstriType ch_ptr;
513
514 fprintf(stderr, "key%d=\"", number);
515 ch_ptr = key_table[number];
516 while (*ch_ptr != '\0') {
517 if (*ch_ptr <= 31) {
518 fprintf(stderr, "^%c", *ch_ptr + '@');
519 } else if (*ch_ptr == '^' || *ch_ptr == '\\') {
520 fprintf(stderr, "%c%c", *ch_ptr, *ch_ptr);
521 } else if (*ch_ptr <= 126) {
522 fprintf(stderr, "%c", *ch_ptr);
523 } else {
524 fprintf(stderr, "\\%3o", *ch_ptr);
525 } /* if */
526 ch_ptr++;
527 } /* while */
528 fprintf(stderr, "\"\n");
529 } else {
530 fprintf(stderr, "key%d=NULL\n", number);
531 } /* if */
532 #endif
533 if (key_table[number] != NULL &&
534 key_table[number][0] >= ' ' && key_table[number][0] <= '~') {
535 /* fprintf(stderr, "key%d=\"%s\" thrown out\n",
536 number, key_table[number]); */
537 key_table[number] = NULL;
538 } /* if */
539 } /* for */
540 /* Sometimes there are double entries in the function key */
541 /* definitions. This makes absolutely no sense and confuses the */
542 /* function key recognition. Therefore such definitions are */
543 /* thrown out here. */
544 for (number = 0; number < SIZE_KEY_TABLE; number++) {
545 for (num2 = number + 1; num2 < SIZE_KEY_TABLE; num2++) {
546 if (key_table[number] != NULL && key_table[num2] != NULL &&
547 strcmp(key_table[number], key_table[num2]) == 0) {
548 /* fprintf(stderr, "key%d=kex%d=\"%s\"\n",
549 number, num2, key_table[number]); */
550 key_table[num2] = NULL;
551 } /* if */
552 } /* for */
553 } /* for */
554 } /* key_table_init */
555
556
557
558 void kbdShut (void)
559
560 { /* kbdShut */
561 if (keybd_initialized) {
562 tcset_term_descr(fileno(stdin), &term_bak);
563 if (caps_initialized) {
564 /* fprintf(stderr, "keypad_local=\"%s\"\n", keypad_local); */
565 putcontrol(keypad_local); /* out of keypad transmit mode */
566 } /* if */
567 keybd_initialized = FALSE;
568 } /* if */
569 } /* kbdShut */
570
571
572
573 static void kbd_init (void)
574
575 {
576 int file_no;
577
578 /* kbd_init */
579 if (!findTermDll()) {
580 logError(printf("kbd_init: findTermDll() failed.\n"););
581 } else {
582 if (!caps_initialized) {
583 getcaps();
584 } /* if */
585 file_no = fileno(stdin);
586 if (tcgetattr(file_no, &term_descr) != 0) {
587 printf("kbd_init: tcgetattr(%d, ...) failed, errno=%d\n",
588 file_no, errno);
589 printf("EBADF=%d EINTR=%d EINVAL=%d ENOTTY=%d EIO=%d\n",
590 EBADF, EINTR, EINVAL, ENOTTY, EIO);
591 } else {
592 memcpy(&term_bak, &term_descr, sizeof(struct termios));
593 erase_ch[0] = (char) term_descr.c_cc[VERASE];
594 erase_ch[1] = '\0';
595 /* printf("erase_ch %d\n", erase_ch[0]); */
596 term_descr.c_lflag &= (unsigned int) ~(ECHO | ECHOE | ECHOK | ECHONL | ICANON);
597 term_descr.c_cc[VINTR] = (cc_t) -1;
598 term_descr.c_cc[VQUIT] = (cc_t) -1;
599 term_descr.c_cc[VSTOP] = (cc_t) -1;
600 #ifdef VSTART
601 term_descr.c_cc[VSTART] = (cc_t) -1;
602 #endif
603 #ifdef VSUSP
604 term_descr.c_cc[VSUSP] = (cc_t) -1;
605 #endif
606 term_descr.c_cc[VMIN] = 1;
607 term_descr.c_cc[VTIME] = 0;
608 if (!tcset_term_descr(file_no, &term_descr)) {
609 printf("kbd_init: tcsetattr(%d, VMIN=1) failed, errno=%d\n",
610 file_no, errno);
611 printf("EBADF=%d EINTR=%d EINVAL=%d ENOTTY=%d EIO=%d\n",
612 EBADF, EINTR, EINVAL, ENOTTY, EIO);
613 } else {
614 keybd_initialized = TRUE;
615 atexit(kbdShut);
616 if (getcaps()) {
617 key_table_init();
618 } /* if */
619 utf8_init();
620 fflush(stdout);
621 } /* if */
622 } /* if */
623 } /* if */
624 } /* kbd_init */
625
626
627
628 boolType kbdKeyPressed (void)
629
630 {
631 struct pollfd poll_fds[1];
632 int poll_result;
633 boolType result;
634
635 /* kbdKeyPressed */
636 if (!keybd_initialized) {
637 kbd_init();
638 } /* if */
639 if (!keybd_initialized) {
640 logError(printf("kbdKeyPressed: kbd_init() failed to open the keyboard.\n"););
641 raise_error(FILE_ERROR);
642 result = FALSE;
643 } else if (key_buffer_size > 0) {
644 result = TRUE;
645 } else {
646 if (changes) {
647 conFlush();
648 } /* if */
649 poll_fds[0].fd = fileno(stdin);
650 poll_fds[0].events = POLLIN | POLLPRI;
651 do {
652 poll_result = poll(poll_fds, 1, 0);
653 } while (unlikely(poll_result == -1 && errno == EINTR));
654 if (poll_result == 1) {
655 result = TRUE;
656 } else {
657 result = FALSE;
658 } /* if */
659 } /* if */
660 return result;
661 } /* kbdKeyPressed */
662
663
664
665 charType kbdGetc (void)
666
667 {
668 memSizeType read_result;
669 int exact_match_count;
670 int exact_matched_key;
671 int partial_match_count;
672 size_t partial_match_len;
673 int partial_matched_key;
674 int number;
675 size_t len;
676 charType result;
677
678 /* kbdGetc */
679 if (!keybd_initialized) {
680 kbd_init();
681 } /* if */
682 if (!keybd_initialized) {
683 logError(printf("kbdGetc: kbd_init() failed to open the keyboard.\n"););
684 raise_error(FILE_ERROR);
685 result = (charType) EOF;
686 } else {
687 if (changes) {
688 conFlush();
689 } /* if */
690 if (key_buffer_size == 0) {
691 read_result = (memSizeType) read(fileno(stdin), &key_buffer, KEY_BUFFER_SIZE);
692 /* printf("kbdGetc: read_result=%ld", read_result); */
693 if (read_result == 0 || read_result == (memSizeType) (-1)) {
694 return (charType) EOF;
695 } else {
696 key_buffer_size = read_result;
697 } /* if */
698 } /* if */
699 #ifdef TRACE_FKEYS
700 printf("key_buffer:\n");
701 for (number = 0; number < key_buffer_size; number++) {
702 if (key_buffer[number] == '\\') {
703 printf("\\\\");
704 } else if (key_buffer[number] >= ' ' && key_buffer[number] <= '~') {
705 printf("%c", key_buffer[number]);
706 } else {
707 printf("\\%u\\", key_buffer[number]);
708 } /* if */
709 } /* if */
710 printf("\n");
711 #endif
712 exact_match_count = 0;
713 exact_matched_key = 0;
714 partial_match_len = 0;
715 partial_match_count = 0;
716 partial_matched_key = 0;
717 for (number = 0; number < SIZE_KEY_TABLE; number++) {
718 if (key_table[number] != NULL) {
719 len = strlen(key_table[number]);
720 if (key_buffer_size >= len &&
721 memcmp(key_table[number], key_buffer, len) == 0) {
722 if (key_buffer_size == len) {
723 exact_match_count++;
724 exact_matched_key = number;
725 } else if (len > partial_match_len) {
726 partial_match_len = len;
727 partial_match_count = 1;
728 partial_matched_key = number;
729 } else if (len == partial_match_len) {
730 partial_match_count++;
731 partial_matched_key = number;
732 } /* if */
733 } /* if */
734 } /* if */
735 } /* for */
736 if (exact_match_count == 1) {
737 /* Exact match means: */
738 /* All characters in key_buffer are used. */
739 key_buffer_size = 0;
740 result = key_code[exact_matched_key];
741 } else if (partial_match_count == 1) {
742 /* Partial match means: */
743 /* Not all characters in key_buffer are used. */
744 len = strlen(key_table[partial_matched_key]);
745 /* Preserve the characters of the next key(s). */
746 memmove(key_buffer, &key_buffer[len], key_buffer_size - len);
747 key_buffer_size -= len;
748 result = key_code[partial_matched_key];
749 } else if (key_buffer[0] == '\033') {
750 if (key_buffer_size == 1) {
751 /* It is assumed that read() reads all characters of */
752 /* an encoded key. Therefore a single escape character */
753 /* cannot be part of a larger escape sequence. If */
754 /* escape sequences can be ripped apart this function */
755 /* will not work correct. */
756 result = K_ESC;
757 key_buffer_size = 0;
758 } else if (key_buffer[1] == '\033') {
759 /* It is assumed that no key encoding starts with two */
760 /* escape characters. */
761 result = K_ESC;
762 /* Preserve the characters of the next key(s). */
763 memmove(key_buffer, &key_buffer[1], key_buffer_size - 1);
764 key_buffer_size--;
765 } else {
766 /* The check for key encodings did not find an unique result. */
767 result = K_UNDEF;
768 key_buffer_size = 0;
769 } /* if */
770 } else {
771 if (utf8_mode) {
772 result = read_utf8_key();
773 } else {
774 result = key_buffer[0];
775 if (key_buffer_size >= 2) {
776 /* Preserve the characters of the next key(s). */
777 memmove(key_buffer, &key_buffer[1], key_buffer_size - 1);
778 } /* if */
779 key_buffer_size--;
780 } /* if */
781 } /* if */
782 } /* if */
783 return result;
784 } /* kbdGetc */
785
786
787
788 charType kbdRawGetc (void)
789
790 {
791 ucharType ch;
792 charType result;
793
794 /* kbdRawRead */
795 if (!keybd_initialized) {
796 kbd_init();
797 } /* if */
798 if (!keybd_initialized) {
799 logError(printf("kbdRawGetc: kbd_init() failed to open the keyboard.\n"););
800 raise_error(FILE_ERROR);
801 result = (charType) EOF;
802 } else if (key_buffer_size > 0) {
803 result = key_buffer[0];
804 if (key_buffer_size >= 2) {
805 memmove(key_buffer, &key_buffer[1], key_buffer_size - 1);
806 } /* if */
807 key_buffer_size--;
808 } else {
809 if (changes) {
810 conFlush();
811 } /* if */
812 if (read(fileno(stdin), &ch, 1) != 1) {
813 result = (charType) EOF;
814 } else {
815 result = (charType) ch;
816 } /* if */
817 } /* if */
818 /* fprintf(stderr, "<%d>", result); */
819 return result;
820 } /* kbdRawRead */
821
822 #endif