wkeys.c
上传用户:tianjinjs
上传日期:2007-01-05
资源大小:309k
文件大小:7k
源码类别:

Modem编程

开发平台:

Unix_Linux

  1. /*
  2.  * wkeys.c Read a keypress from the standard input. If it is an escape
  3.  * code, return a special value.
  4.  *
  5.  * WARNING: possibly the most ugly code in this package!
  6.  *
  7.  * This file is part of the minicom communications package,
  8.  * Copyright 1991-1995 Miquel van Smoorenburg.
  9.  *
  10.  * This program is free software; you can redistribute it and/or
  11.  * modify it under the terms of the GNU General Public License
  12.  * as published by the Free Software Foundation; either version
  13.  * 2 of the License, or (at your option) any later version.
  14.  */
  15. #include "port.h"
  16. #include "minicom.h"
  17. #if KEY_KLUDGE && defined(linux)
  18. #  include <sys/kd.h>
  19. #  include <sys/ioctl.h>
  20. #endif
  21. /* If enabled, this will cause minicom to treat ESC [ A and
  22.  * ESC O A the same (stupid VT100 two mode keyboards).
  23.  */
  24. #define VT_KLUDGE 0
  25. static struct key _keys[NUM_KEYS];
  26. static int keys_in_buf;
  27. extern int setcbreak();
  28. /*
  29.  * The following is an external pointer to the termcap info.
  30.  * If it's NOT zero then the main program has already
  31.  * read the termcap for us. No sense in doing it twice.
  32.  */
  33. extern char *_tptr;
  34. static char erasechar;
  35. static int gotalrm;
  36. extern int errno;
  37. int pendingkeys = 0;
  38. int io_pending = 0;
  39. static char *func_key[] = { 
  40. "", "k1", "k2", "k3", "k4", "k5", "k6", "k7", "k8", "k9", "k0",
  41. "kh", "kP", "ku", "kl", "kr", "kd", "kH", "kN", "kI", "kD",
  42. #ifdef _DGUX_SOURCE
  43. "kA", "kB", (char *)0 };
  44. #else
  45. "F1", "F2", (char *)0 };
  46. #endif
  47. #if KEY_KLUDGE
  48. /*
  49.  * A VERY DIRTY HACK FOLLOWS:
  50.  * This routine figures out if the tty we're using is a serial
  51.  * device OR an IBM PC console. If we're using a console, we can
  52.  * easily reckognize single escape-keys since escape sequences
  53.  * always return > 1 characters from a read()
  54.  */
  55. static int isconsole;
  56.  
  57. static int testconsole()
  58. {
  59.   /* For Linux it's easy to see if this is a VC. */
  60.   int info;
  61.   return( ioctl(0, KDGETLED, &info) == 0);
  62. }
  63. /*
  64.  * Function to read chunks of data from fd 0 all at once
  65.  */
  66. static int cread(c)
  67. char *c;
  68. {
  69.   static char buf[32];
  70.   static int idx = 0;
  71.   static int lastread = 0;
  72.   if (idx > 0 && idx < lastread) {
  73.    *c = buf[idx++];
  74. keys_in_buf--;
  75. if (keys_in_buf == 0 && pendingkeys == 0) io_pending = 0;
  76.    return(lastread);
  77.   }
  78.   idx = 0;
  79.   do {
  80. lastread = read(0, buf, 32);
  81. keys_in_buf = lastread - 1;
  82.   } while(lastread < 0 && errno == EINTR);
  83.   *c = buf[0];
  84.   if (lastread > 1) {
  85. idx = 1;
  86. io_pending++;
  87.   }
  88.   return(lastread);
  89. }
  90. #endif
  91. static void _initkeys()
  92. {
  93.   int i;
  94.   static char *cbuf, *tbuf;
  95.   char *term;
  96.   if (_tptr == CNULL) {
  97. if ((tbuf = (char *)malloc(512)) == CNULL || 
  98. (cbuf = (char *)malloc(2048)) == CNULL) {
  99.    write(2, "Out of memory.n", 15);
  100.    exit(1);
  101. }
  102. term = getenv("TERM");
  103. switch(tgetent(cbuf, term)) {
  104.    case 0:
  105.    write(2, "No termcap entry.n", 18);
  106.    exit(1);
  107.    case -1:
  108.    write(2, "No /etc/termcap present!n", 25);
  109.    exit(1);
  110.    default:
  111.    break;
  112.    }
  113. _tptr = tbuf;
  114.   }
  115. /* Initialize codes for special keys */
  116.   for(i = 0; func_key[i]; i++) {
  117.    if ((_keys[i].cap = tgetstr(func_key[i], &_tptr)) == CNULL)
  118.    _keys[i].cap = "";
  119.    _keys[i].len = strlen(_keys[i].cap);
  120.   }
  121. #if KEY_KLUDGE
  122.   isconsole = testconsole();
  123. #endif
  124. }
  125.   
  126. /*
  127.  * Dummy routine for the alarm signal
  128.  */
  129. #ifndef _SELECT
  130. static void dummy()
  131. {
  132.   gotalrm = 1;
  133. }
  134. #endif
  135.   
  136. /*
  137.  * Read a character from the keyboard.
  138.  * Handle special characters too!
  139.  */
  140. int wxgetch()
  141. {
  142.   int f, g;
  143.   int match = 1;
  144.   int len;
  145.   unsigned char c;
  146.   static unsigned char mem[8];
  147.   static int leftmem = 0;
  148.   static int init = 0;
  149.   int nfound = 0;
  150.   int start_match;
  151. #if VT_KLUDGE
  152.   char temp[8];
  153. #endif
  154. #ifdef _SELECT
  155.   struct timeval timeout;
  156.   fd_set readfds;
  157.   static fd_set *nofds = (fd_set *)0;
  158. #endif
  159.   if (init == 0) {
  160.    _initkeys();
  161.    init++;
  162.    erasechar = setcbreak(3);
  163.   }
  164.   /* Some sequence still in memory ? */
  165.   if (leftmem) {
  166. leftmem--;
  167. if (leftmem == 0) pendingkeys = 0;
  168. if (pendingkeys == 0 && keys_in_buf == 0) io_pending = 0;
  169. return(mem[leftmem]);
  170.   }
  171.   gotalrm = 0;
  172.   pendingkeys = 0;
  173.   for (len = 1; len < 8 && match; len++) {
  174. #ifdef _SELECT
  175. #if KEY_KLUDGE
  176. if (len > 1 && keys_in_buf == 0) {
  177. #else
  178. if (len > 1) {
  179. #endif
  180. timeout.tv_sec = 0;
  181. timeout.tv_usec = 400000; /* 400 ms */
  182. #ifdef FD_SET
  183. FD_ZERO(&readfds);
  184. FD_SET(0, &readfds);
  185. #else
  186. readfs = 1; /* First bit means file descriptor #0 */
  187. #endif
  188. #ifdef _HPUX_SOURCE
  189. /* HPUX prototype of select is mangled */
  190. nfound = select(1, (int *)&readfds,
  191. (int *)nofds, (int *)nofds, &timeout);
  192. #else
  193. nfound = select(1, &readfds, nofds, nofds, &timeout);
  194. #endif
  195. if (nfound == 0) {
  196. break;
  197. }
  198. }
  199. #else /* _SELECT */
  200. if (len > 1) {
  201. signal(SIGALRM, dummy);
  202. alarm(1);
  203. }
  204. #endif /* _SELECT */
  205. #if KEY_KLUDGE
  206. while((nfound = cread(&c)) < 0 && (errno == EINTR && !gotalrm))
  207. ;
  208. #else
  209.    while ((nfound = read(0, &c, 1)) < 0 && (errno == EINTR && !gotalrm))
  210.    ;
  211. #endif
  212. #ifndef _SELECT
  213. if (len > 1) alarm(0);
  214. #endif
  215. if (nfound < 1) break;
  216.    if (len == 1) {
  217.    /* Enter and erase have precedence over anything else */
  218.     if (c == (unsigned char)'n')
  219.    return c;
  220. if (c == (unsigned char)erasechar)
  221. return K_ERA;
  222.    }
  223. #if KEY_KLUDGE
  224. /* Return single characters immideately */
  225. if (isconsole && nfound == 1 && len == 1) return(c);
  226. /* Another hack - detect the Meta Key. */
  227. if (isconsole && nfound == 2 && len == 1 &&
  228. c == 27 && escape == 27) {
  229. cread(&c);
  230. return(c + K_META);
  231. }
  232. #endif
  233.    mem[len - 1] = c;
  234.    match = 0;
  235. #if VT_KLUDGE
  236. /* Oh boy. Stupid vt100 2 mode keyboard. */
  237. strncpy(temp, mem, len);
  238. if (len > 1 && temp[0] == 27) {
  239. if (temp[1] == '[')
  240. temp[1] = 'O';
  241. else if (temp[1] == 'O')
  242. temp[1] = '[';
  243. }
  244. /* We now have an alternate string to check. */
  245. #endif
  246. start_match = 0;
  247.    for (f = 0; f < NUM_KEYS; f++) {
  248. #if VT_KLUDGE
  249.        if (_keys[f].len >= len &&
  250. (strncmp(_keys[f].cap, (char *)mem,  len) == 0 ||
  251.  strncmp(_keys[f].cap, (char *)temp, len) == 0)) {
  252. #else
  253.     if (_keys[f].len >= len && strncmp(_keys[f].cap, (char *)mem, len) == 0){
  254. #endif
  255.    match++;
  256.    if (_keys[f].len == len) {
  257.    return(f + KEY_OFFS);
  258.    }
  259.     }
  260.     /* Does it match on first two chars? */
  261.     if (_keys[f].len > 1 && len == 2 &&
  262. strncmp(_keys[f].cap, (char *)mem, 2) == 0) start_match++;
  263. }
  264. #if KEY_KLUDGE
  265. if (!isconsole)
  266. #endif
  267. #ifndef _MINIX /* Minix doesn't have ESC-c meta mode */
  268. /* See if this _might_ be a meta-key. */
  269. if (escape == 27 && !start_match && len == 2 && mem[0] == 27)
  270. return(c + K_META);
  271. #endif
  272.   }
  273.   /* No match. in len we have the number of characters + 1 */
  274.   len--; /* for convenience */
  275.   if (len == 1) return(mem[0]);
  276.   /* Remember there are more keys waiting in the buffer */
  277.   pendingkeys++;
  278.   io_pending++;
  279. #ifndef _SELECT
  280.   /* Pressing eg escape twice means escape */
  281.   if (len == 2 && mem[0] == mem[1]) return(mem[0]);
  282. #endif
  283.   
  284.   /* Reverse the "mem" array */
  285.   for(f = 0; f < len / 2; f++) {
  286.    g = mem[f];
  287.    mem[f] = mem[len - f - 1];
  288.    mem[len - f - 1] = g;
  289.   }
  290.   leftmem = len - 1;
  291.   return(mem[leftmem]);
  292. }