|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* wkeys.c Read a keypress from the standard input. If it is an escape
|
|
Packit |
15a96c |
* code, return a special value.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* WARNING: possibly the most ugly code in this package!
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* This file is part of the minicom communications package,
|
|
Packit |
15a96c |
* Copyright 1991-1995 Miquel van Smoorenburg.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* This program is free software; you can redistribute it and/or
|
|
Packit |
15a96c |
* modify it under the terms of the GNU General Public License
|
|
Packit |
15a96c |
* as published by the Free Software Foundation; either version
|
|
Packit |
15a96c |
* 2 of the License, or (at your option) any later version.
|
|
Packit |
15a96c |
*
|
|
Packit |
15a96c |
* You should have received a copy of the GNU General Public License along
|
|
Packit |
15a96c |
* with this program; if not, write to the Free Software Foundation, Inc.,
|
|
Packit |
15a96c |
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
#ifdef HAVE_CONFIG_H
|
|
Packit |
15a96c |
#include <config.h>
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#include <strings.h>
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#include "port.h"
|
|
Packit |
15a96c |
#include "minicom.h"
|
|
Packit |
15a96c |
#include "intl.h"
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#if KEY_KLUDGE && defined(linux)
|
|
Packit |
15a96c |
# include <sys/kd.h>
|
|
Packit |
15a96c |
# include <sys/ioctl.h>
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* If enabled, this will cause minicom to treat ESC [ A and
|
|
Packit |
15a96c |
* ESC O A the same (stupid VT100 two mode keyboards).
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
#define VT_KLUDGE 0
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static struct key _keys[NUM_KEYS];
|
|
Packit |
15a96c |
static int keys_in_buf;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static char erasechar;
|
|
Packit |
15a96c |
static int gotalrm;
|
|
Packit |
15a96c |
int pendingkeys = 0;
|
|
Packit |
15a96c |
int io_pending = 0;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#ifndef NCURSES_CONST
|
|
Packit |
15a96c |
#define NCURSES_CONST
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static NCURSES_CONST char *func_key[] = {
|
|
Packit |
15a96c |
"", "k1", "k2", "k3", "k4", "k5", "k6", "k7", "k8", "k9", "k0",
|
|
Packit |
15a96c |
"kh", "kP", "ku", "kl", "kr", "kd", "kH", "kN", "kI", "kD",
|
|
Packit |
15a96c |
"F1", "F2", NULL };
|
|
Packit |
15a96c |
#if KEY_KLUDGE
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* A VERY DIRTY HACK FOLLOWS:
|
|
Packit |
15a96c |
* This routine figures out if the tty we're using is a serial
|
|
Packit |
15a96c |
* device OR an IBM PC console. If we're using a console, we can
|
|
Packit |
15a96c |
* easily reckognize single escape-keys since escape sequences
|
|
Packit |
15a96c |
* always return > 1 characters from a read()
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
static int isconsole;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static int testconsole(void)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
/* For Linux it's easy to see if this is a VC. */
|
|
Packit |
15a96c |
int info;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
return ioctl(0, KDGETLED, &info) == 0;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Function to read chunks of data from fd 0 all at once
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static int cread(char *c)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
static char buf[32];
|
|
Packit |
15a96c |
static int idx = 0;
|
|
Packit |
15a96c |
static int lastread = 0;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (idx > 0 && idx < lastread) {
|
|
Packit |
15a96c |
*c = buf[idx++];
|
|
Packit |
15a96c |
keys_in_buf--;
|
|
Packit |
15a96c |
if (keys_in_buf == 0 && pendingkeys == 0)
|
|
Packit |
15a96c |
io_pending = 0;
|
|
Packit |
15a96c |
return lastread;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
idx = 0;
|
|
Packit |
15a96c |
do {
|
|
Packit |
15a96c |
lastread = read(0, buf, 32);
|
|
Packit |
15a96c |
keys_in_buf = lastread - 1;
|
|
Packit |
15a96c |
} while (lastread < 0 && errno == EINTR);
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
*c = buf[0];
|
|
Packit |
15a96c |
if (lastread > 1) {
|
|
Packit |
15a96c |
idx = 1;
|
|
Packit |
15a96c |
io_pending++;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
return lastread;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
static void _initkeys(void)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
int i;
|
|
Packit |
15a96c |
static char *cbuf, *tbuf;
|
|
Packit |
15a96c |
char *term;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (_tptr == NULL) {
|
|
Packit |
15a96c |
if ((tbuf = (char *)malloc(512)) == NULL ||
|
|
Packit |
15a96c |
(cbuf = (char *)malloc(2048)) == NULL) {
|
|
Packit |
15a96c |
fprintf(stderr, _("Out of memory.\n"));
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
term = getenv("TERM");
|
|
Packit |
15a96c |
switch (tgetent(cbuf, term)) {
|
|
Packit |
15a96c |
case 0:
|
|
Packit |
15a96c |
fprintf(stderr, _("No termcap entry.\n"));
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
case -1:
|
|
Packit |
15a96c |
fprintf(stderr, _("No /etc/termcap present!\n"));
|
|
Packit |
15a96c |
exit(1);
|
|
Packit |
15a96c |
default:
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
_tptr = tbuf;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
/* Initialize codes for special keys */
|
|
Packit |
15a96c |
for (i = 0; func_key[i]; i++) {
|
|
Packit |
15a96c |
if ((_keys[i].cap = tgetstr(func_key[i], &_tptr)) == NULL)
|
|
Packit |
15a96c |
_keys[i].cap = "";
|
|
Packit |
15a96c |
_keys[i].len = strlen(_keys[i].cap);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
#if KEY_KLUDGE
|
|
Packit |
15a96c |
isconsole = testconsole();
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/*
|
|
Packit |
15a96c |
* Read a character from the keyboard.
|
|
Packit |
15a96c |
* Handle special characters too!
|
|
Packit |
15a96c |
*/
|
|
Packit |
15a96c |
int wxgetch(void)
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
int f, g;
|
|
Packit |
15a96c |
int match = 1;
|
|
Packit |
15a96c |
int len;
|
|
Packit |
15a96c |
char c;
|
|
Packit |
15a96c |
static unsigned char mem[8];
|
|
Packit |
15a96c |
static int leftmem = 0;
|
|
Packit |
15a96c |
static int init = 0;
|
|
Packit |
15a96c |
int nfound = 0;
|
|
Packit |
15a96c |
int start_match;
|
|
Packit |
15a96c |
#if VT_KLUDGE
|
|
Packit |
15a96c |
char temp[8];
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
struct timeval timeout;
|
|
Packit |
15a96c |
fd_set readfds;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (init == 0) {
|
|
Packit |
15a96c |
_initkeys();
|
|
Packit |
15a96c |
init++;
|
|
Packit |
15a96c |
erasechar = setcbreak(3);
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* Some sequence still in memory ? */
|
|
Packit |
15a96c |
if (leftmem > 0) {
|
|
Packit |
15a96c |
leftmem--;
|
|
Packit |
15a96c |
if (leftmem == 0)
|
|
Packit |
15a96c |
pendingkeys = 0;
|
|
Packit |
15a96c |
if (pendingkeys == 0 && keys_in_buf == 0)
|
|
Packit |
15a96c |
io_pending = 0;
|
|
Packit |
15a96c |
return mem[leftmem];
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
gotalrm = 0;
|
|
Packit |
15a96c |
pendingkeys = 0;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
for (len = 1; len < 8 && match; len++) {
|
|
Packit |
15a96c |
#if KEY_KLUDGE
|
|
Packit |
15a96c |
if (len > 1 && keys_in_buf == 0)
|
|
Packit |
15a96c |
#else
|
|
Packit |
15a96c |
if (len > 1)
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
timeout.tv_sec = 0;
|
|
Packit |
15a96c |
timeout.tv_usec = 400000; /* 400 ms */
|
|
Packit |
15a96c |
FD_ZERO(&readfds);
|
|
Packit |
15a96c |
FD_SET(0, &readfds);
|
|
Packit |
15a96c |
if (!(nfound = select(1, &readfds, NULL, NULL, &timeout)))
|
|
Packit |
15a96c |
break;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
#if KEY_KLUDGE
|
|
Packit |
15a96c |
while ((nfound = cread(&c)) < 0 && (errno == EINTR && !gotalrm))
|
|
Packit |
15a96c |
;
|
|
Packit |
15a96c |
#else
|
|
Packit |
15a96c |
while ((nfound = read(0, &c, 1)) < 0 && (errno == EINTR && !gotalrm))
|
|
Packit |
15a96c |
;
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (nfound < 1)
|
|
Packit |
15a96c |
return EOF;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
if (len == 1) {
|
|
Packit |
15a96c |
/* Enter and erase have precedence over anything else */
|
|
Packit |
15a96c |
if (c == '\n')
|
|
Packit |
15a96c |
return c;
|
|
Packit |
15a96c |
if (c == erasechar)
|
|
Packit |
15a96c |
return K_ERA;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
#if KEY_KLUDGE
|
|
Packit |
15a96c |
/* Return single characters immideately */
|
|
Packit |
15a96c |
if (isconsole && nfound == 1 && len == 1)
|
|
Packit |
15a96c |
return c;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* Another hack - detect the Meta Key. */
|
|
Packit |
15a96c |
if (isconsole && nfound == 2 && len == 1 && c == 27 && escape == 27) {
|
|
Packit |
15a96c |
cread(&c);
|
|
Packit |
15a96c |
return c + K_META;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
mem[len - 1] = c;
|
|
Packit |
15a96c |
match = 0;
|
|
Packit |
15a96c |
#if VT_KLUDGE
|
|
Packit |
15a96c |
/* Oh boy. Stupid vt100 2 mode keyboard. */
|
|
Packit |
15a96c |
strncpy(temp, mem, len);
|
|
Packit |
15a96c |
if (len > 1 && temp[0] == 27) {
|
|
Packit |
15a96c |
if (temp[1] == '[')
|
|
Packit |
15a96c |
temp[1] = 'O';
|
|
Packit |
15a96c |
else if (temp[1] == 'O')
|
|
Packit |
15a96c |
temp[1] = '[';
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
/* We now have an alternate string to check. */
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
start_match = 0;
|
|
Packit |
15a96c |
for (f = 0; f < NUM_KEYS; f++) {
|
|
Packit |
15a96c |
#if VT_KLUDGE
|
|
Packit |
15a96c |
if (_keys[f].len >= len &&
|
|
Packit |
15a96c |
(strncmp(_keys[f].cap, (char *)mem, len) == 0 ||
|
|
Packit |
15a96c |
strncmp(_keys[f].cap, (char *)temp, len) == 0))
|
|
Packit |
15a96c |
#else
|
|
Packit |
15a96c |
if (_keys[f].len >= len &&
|
|
Packit |
15a96c |
strncmp(_keys[f].cap, (char *)mem, len) == 0)
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
{
|
|
Packit |
15a96c |
match++;
|
|
Packit |
15a96c |
if (_keys[f].len == len) {
|
|
Packit |
15a96c |
return f + KEY_OFFS;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
/* Does it match on first two chars? */
|
|
Packit |
15a96c |
if (_keys[f].len > 1 && len == 2 &&
|
|
Packit |
15a96c |
strncmp(_keys[f].cap, (char *)mem, 2) == 0)
|
|
Packit |
15a96c |
start_match++;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
#if KEY_KLUDGE
|
|
Packit |
15a96c |
if (!isconsole)
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
#ifndef _MINIX /* Minix doesn't have ESC-c meta mode */
|
|
Packit |
15a96c |
/* See if this _might_ be a meta-key. */
|
|
Packit |
15a96c |
if (escape == 27 && !start_match && len == 2 && mem[0] == 27)
|
|
Packit |
15a96c |
return c + K_META;
|
|
Packit |
15a96c |
#endif
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
/* No match. in len we have the number of characters + 1 */
|
|
Packit |
15a96c |
len--; /* for convenience */
|
|
Packit |
15a96c |
if (len == 1)
|
|
Packit |
15a96c |
return mem[0];
|
|
Packit |
15a96c |
/* Remember there are more keys waiting in the buffer */
|
|
Packit |
15a96c |
pendingkeys++;
|
|
Packit |
15a96c |
io_pending++;
|
|
Packit |
15a96c |
|
|
Packit |
15a96c |
/* Reverse the "mem" array */
|
|
Packit |
15a96c |
for (f = 0; f < len / 2; f++) {
|
|
Packit |
15a96c |
g = mem[f];
|
|
Packit |
15a96c |
mem[f] = mem[len - f - 1];
|
|
Packit |
15a96c |
mem[len - f - 1] = g;
|
|
Packit |
15a96c |
}
|
|
Packit |
15a96c |
leftmem = len - 1;
|
|
Packit |
15a96c |
return mem[leftmem];
|
|
Packit |
15a96c |
}
|