"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