wkeys.c
上传用户:tianjinjs
上传日期:2007-01-05
资源大小:309k
文件大小:7k
- /*
- * wkeys.c Read a keypress from the standard input. If it is an escape
- * code, return a special value.
- *
- * WARNING: possibly the most ugly code in this package!
- *
- * This file is part of the minicom communications package,
- * Copyright 1991-1995 Miquel van Smoorenburg.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
- #include "port.h"
- #include "minicom.h"
- #if KEY_KLUDGE && defined(linux)
- # include <sys/kd.h>
- # include <sys/ioctl.h>
- #endif
- /* If enabled, this will cause minicom to treat ESC [ A and
- * ESC O A the same (stupid VT100 two mode keyboards).
- */
- #define VT_KLUDGE 0
- static struct key _keys[NUM_KEYS];
- static int keys_in_buf;
- extern int setcbreak();
- /*
- * The following is an external pointer to the termcap info.
- * If it's NOT zero then the main program has already
- * read the termcap for us. No sense in doing it twice.
- */
- extern char *_tptr;
- static char erasechar;
- static int gotalrm;
- extern int errno;
- int pendingkeys = 0;
- int io_pending = 0;
- static char *func_key[] = {
- "", "k1", "k2", "k3", "k4", "k5", "k6", "k7", "k8", "k9", "k0",
- "kh", "kP", "ku", "kl", "kr", "kd", "kH", "kN", "kI", "kD",
- #ifdef _DGUX_SOURCE
- "kA", "kB", (char *)0 };
- #else
- "F1", "F2", (char *)0 };
- #endif
- #if KEY_KLUDGE
- /*
- * A VERY DIRTY HACK FOLLOWS:
- * This routine figures out if the tty we're using is a serial
- * device OR an IBM PC console. If we're using a console, we can
- * easily reckognize single escape-keys since escape sequences
- * always return > 1 characters from a read()
- */
- static int isconsole;
-
- static int testconsole()
- {
- /* For Linux it's easy to see if this is a VC. */
- int info;
- return( ioctl(0, KDGETLED, &info) == 0);
- }
- /*
- * Function to read chunks of data from fd 0 all at once
- */
- static int cread(c)
- char *c;
- {
- static char buf[32];
- static int idx = 0;
- static int lastread = 0;
- if (idx > 0 && idx < lastread) {
- *c = buf[idx++];
- keys_in_buf--;
- if (keys_in_buf == 0 && pendingkeys == 0) io_pending = 0;
- return(lastread);
- }
- idx = 0;
- do {
- lastread = read(0, buf, 32);
- keys_in_buf = lastread - 1;
- } while(lastread < 0 && errno == EINTR);
- *c = buf[0];
- if (lastread > 1) {
- idx = 1;
- io_pending++;
- }
- return(lastread);
- }
- #endif
- static void _initkeys()
- {
- int i;
- static char *cbuf, *tbuf;
- char *term;
- if (_tptr == CNULL) {
- if ((tbuf = (char *)malloc(512)) == CNULL ||
- (cbuf = (char *)malloc(2048)) == CNULL) {
- write(2, "Out of memory.n", 15);
- exit(1);
- }
- term = getenv("TERM");
- switch(tgetent(cbuf, term)) {
- case 0:
- write(2, "No termcap entry.n", 18);
- exit(1);
- case -1:
- write(2, "No /etc/termcap present!n", 25);
- exit(1);
- default:
- break;
- }
- _tptr = tbuf;
- }
- /* Initialize codes for special keys */
- for(i = 0; func_key[i]; i++) {
- if ((_keys[i].cap = tgetstr(func_key[i], &_tptr)) == CNULL)
- _keys[i].cap = "";
- _keys[i].len = strlen(_keys[i].cap);
- }
- #if KEY_KLUDGE
- isconsole = testconsole();
- #endif
- }
-
- /*
- * Dummy routine for the alarm signal
- */
- #ifndef _SELECT
- static void dummy()
- {
- gotalrm = 1;
- }
- #endif
-
- /*
- * Read a character from the keyboard.
- * Handle special characters too!
- */
- int wxgetch()
- {
- int f, g;
- int match = 1;
- int len;
- unsigned char c;
- static unsigned char mem[8];
- static int leftmem = 0;
- static int init = 0;
- int nfound = 0;
- int start_match;
- #if VT_KLUDGE
- char temp[8];
- #endif
- #ifdef _SELECT
- struct timeval timeout;
- fd_set readfds;
- static fd_set *nofds = (fd_set *)0;
- #endif
- if (init == 0) {
- _initkeys();
- init++;
- erasechar = setcbreak(3);
- }
- /* Some sequence still in memory ? */
- if (leftmem) {
- leftmem--;
- if (leftmem == 0) pendingkeys = 0;
- if (pendingkeys == 0 && keys_in_buf == 0) io_pending = 0;
- return(mem[leftmem]);
- }
- gotalrm = 0;
- pendingkeys = 0;
- for (len = 1; len < 8 && match; len++) {
- #ifdef _SELECT
- #if KEY_KLUDGE
- if (len > 1 && keys_in_buf == 0) {
- #else
- if (len > 1) {
- #endif
- timeout.tv_sec = 0;
- timeout.tv_usec = 400000; /* 400 ms */
- #ifdef FD_SET
- FD_ZERO(&readfds);
- FD_SET(0, &readfds);
- #else
- readfs = 1; /* First bit means file descriptor #0 */
- #endif
- #ifdef _HPUX_SOURCE
- /* HPUX prototype of select is mangled */
- nfound = select(1, (int *)&readfds,
- (int *)nofds, (int *)nofds, &timeout);
- #else
- nfound = select(1, &readfds, nofds, nofds, &timeout);
- #endif
- if (nfound == 0) {
- break;
- }
- }
- #else /* _SELECT */
- if (len > 1) {
- signal(SIGALRM, dummy);
- alarm(1);
- }
- #endif /* _SELECT */
- #if KEY_KLUDGE
- while((nfound = cread(&c)) < 0 && (errno == EINTR && !gotalrm))
- ;
- #else
- while ((nfound = read(0, &c, 1)) < 0 && (errno == EINTR && !gotalrm))
- ;
- #endif
- #ifndef _SELECT
- if (len > 1) alarm(0);
- #endif
- if (nfound < 1) break;
- if (len == 1) {
- /* Enter and erase have precedence over anything else */
- if (c == (unsigned char)'n')
- return c;
- if (c == (unsigned char)erasechar)
- return K_ERA;
- }
- #if KEY_KLUDGE
- /* Return single characters immideately */
- if (isconsole && nfound == 1 && len == 1) return(c);
- /* Another hack - detect the Meta Key. */
- if (isconsole && nfound == 2 && len == 1 &&
- c == 27 && escape == 27) {
- cread(&c);
- return(c + K_META);
- }
- #endif
- mem[len - 1] = c;
- match = 0;
- #if VT_KLUDGE
- /* Oh boy. Stupid vt100 2 mode keyboard. */
- strncpy(temp, mem, len);
- if (len > 1 && temp[0] == 27) {
- if (temp[1] == '[')
- temp[1] = 'O';
- else if (temp[1] == 'O')
- temp[1] = '[';
- }
- /* We now have an alternate string to check. */
- #endif
- start_match = 0;
- for (f = 0; f < NUM_KEYS; f++) {
- #if VT_KLUDGE
- if (_keys[f].len >= len &&
- (strncmp(_keys[f].cap, (char *)mem, len) == 0 ||
- strncmp(_keys[f].cap, (char *)temp, len) == 0)) {
- #else
- if (_keys[f].len >= len && strncmp(_keys[f].cap, (char *)mem, len) == 0){
- #endif
- match++;
- if (_keys[f].len == len) {
- return(f + KEY_OFFS);
- }
- }
- /* Does it match on first two chars? */
- if (_keys[f].len > 1 && len == 2 &&
- strncmp(_keys[f].cap, (char *)mem, 2) == 0) start_match++;
- }
- #if KEY_KLUDGE
- if (!isconsole)
- #endif
- #ifndef _MINIX /* Minix doesn't have ESC-c meta mode */
- /* See if this _might_ be a meta-key. */
- if (escape == 27 && !start_match && len == 2 && mem[0] == 27)
- return(c + K_META);
- #endif
- }
- /* No match. in len we have the number of characters + 1 */
- len--; /* for convenience */
- if (len == 1) return(mem[0]);
- /* Remember there are more keys waiting in the buffer */
- pendingkeys++;
- io_pending++;
- #ifndef _SELECT
- /* Pressing eg escape twice means escape */
- if (len == 2 && mem[0] == mem[1]) return(mem[0]);
- #endif
-
- /* Reverse the "mem" array */
- for(f = 0; f < len / 2; f++) {
- g = mem[f];
- mem[f] = mem[len - f - 1];
- mem[len - f - 1] = g;
- }
- leftmem = len - 1;
- return(mem[leftmem]);
- }