Permalink
Fetching contributors…
Cannot retrieve contributors at this time
265 lines (245 sloc) 5.87 KB
/*
** Copyright (C) 1991, 1997 Free Software Foundation, Inc.
**
** This file is part of TACK.
**
** TACK 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, or (at your option)
** any later version.
**
** TACK is distributed in the hope that it will be useful,
** but WITHOUT ANY WARRANTY; without even the implied warranty of
** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
** GNU General Public License for more details.
**
** You should have received a copy of the GNU General Public License
** along with TACK; see the file COPYING. If not, write to
** the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
** Boston, MA 02110-1301, USA
*/
/* scan mode keyboard support */
#include <tack.h>
MODULE_ID("$Id: scan.c,v 1.8 2009/12/26 21:29:01 tom Exp $")
unsigned scan_max; /* length of longest scan code */
char **scan_up, **scan_down, **scan_name;
unsigned *scan_tested, *scan_length;
static unsigned *scan_value;
static unsigned shift_state;
static char *str;
static int debug_char_count;
#define SHIFT_KEY 0x100
#define CONTROL_KEY 0x200
#define META_KEY 0x400
#define CAPS_LOCK 0x800
static const struct {
const char *name;
unsigned type;
} scan_special[] = {
{"<shift>", SHIFT_KEY},
{"<left shift>", SHIFT_KEY},
{"<right shift>", SHIFT_KEY},
{"<control>", CONTROL_KEY},
{"<left control>", CONTROL_KEY},
{"<right control>", CONTROL_KEY},
{"<meta>", META_KEY},
{"<left meta>", META_KEY},
{"<right meta>", META_KEY},
{"<caps lock>", CAPS_LOCK},
{"<tab>", '\t'},
{"<space>", ' '},
{"<return>", '\r'},
{"<linefeed>", '\n'},
{"<formfeed>", '\f'},
{"<backspace>", '\b'},
{0, 0}
};
static void
scan_blanks(void)
{ /* scan past the white space */
while (*str == ' ' || *str == '\t')
str++;
}
static char *
smash(void)
{ /* convert a string to hex */
char *s, *t;
int ch, i, j;
t = s = str;
for (i = 0; (ch = *str); str++) {
if (ch >= '0' && ch <= '9')
j = ch - '0';
else if (ch >= 'a' && ch <= 'f')
j = 10 - 'a' + ch;
else if (ch >= 'A' && ch <= 'F')
j = 10 - 'A' + ch;
else if (ch == ' ' || ch == '\t')
break;
else
continue;
if (i) {
*s = (char) (*s | j);
s++;
} else
*s = (char) (j << 4);
i ^= 1;
}
*s = '\0';
return t;
}
void
scan_init(char *fn)
{ /* read the scan mode key definitions */
char *s, *sl;
FILE *fp;
int ch, i, j;
unsigned len;
char home[512];
if ((str = getenv("HOME")))
strcpy(home, str);
else
home[0] = '\0';
fp = NULL;
if ((str = getenv("KEYBOARD"))) {
if (!(fp = fopen(str, "r")) && home[0]) {
sprintf(temp, "%s/.scan.%s", home, str);
fp = fopen(temp, "r");
}
}
if (!fp) {
sprintf(temp, ".scan.%s", fn);
fp = fopen(temp, "r");
}
if (!fp && home[0]) {
sprintf(temp, "%s/.scan.%s", home, fn);
fp = fopen(temp, "r");
}
if (!fp) {
ptext("Unable to open scanfile: ");
ptextln(temp);
bye_kids(EXIT_FAILURE);
return;
}
/*
scan file format:
<down value> <up value> <name>
values are in hex. <name> may be any string of characters
*/
scan_up = (char **) malloc(sizeof(char *) * MAX_SCAN);
scan_down = (char **) malloc(sizeof(char *) * MAX_SCAN);
scan_name = (char **) malloc(sizeof(char *) * MAX_SCAN);
scan_tested = (unsigned *) malloc(sizeof(unsigned *) * MAX_SCAN);
scan_length = (unsigned *) malloc(sizeof(unsigned *) * MAX_SCAN);
scan_value = (unsigned *) malloc(sizeof(unsigned *) * MAX_SCAN);
scan_up[0] = scan_down[0] = scan_name[0] = (char *) 0;
str = (char *) malloc(4096); /* buffer space */
sl = str + 4000; /* an upper limit */
scan_max = 1;
for (i = 0;;) {
for (s = str; (ch = getc(fp)) != EOF;) {
if (ch == '\n' || ch == '\r')
break;
*s++ = (char) ch;
}
*s++ = '\0';
if (ch == EOF)
break;
if (*str == '#' || *str == '\0')
continue;
scan_down[i] = smash();
scan_blanks();
scan_up[i] = smash();
scan_blanks();
scan_name[i] = str;
scan_length[i] = strlen(scan_down[i]);
len = strlen(scan_up[i]) + scan_length[i];
if (len > scan_max)
scan_max = len;
scan_value[i] = UChar(scan_name[i][0]);
if (scan_name[i][1]) /* multi-character name */
for (j = 0; scan_special[j].name; j++) {
if (!strcmp(scan_name[i], scan_special[j].name)) {
scan_value[i] = scan_special[j].type;
break;
}
}
i++;
if (str > sl) {
str = (char *) malloc(4096);
sl = str + 4000;
} else
str = s;
}
fclose(fp);
#ifdef notdef
for (i = 0; scan_down[i]; i++) {
put_str(hex_expand_to(scan_down[i], 3));
put_str(hex_expand_to(scan_up[i], 3));
put_str(" ");
put_str(scan_name[i]);
put_crlf();
}
(void) wait_here();
#endif
}
int
scan_key(void)
{ /* read a key and translate scan mode to
ASCII */
unsigned i;
int j, ch;
char buf[64];
for (i = 1;; i++) {
ch = getchar();
if (ch == EOF)
return EOF;
if (debug_fp) {
fprintf(debug_fp, "%02X ", ch);
debug_char_count += 3;
if (debug_char_count > 72) {
fprintf(debug_fp, "\n");
debug_char_count = 0;
}
}
buf[i - 1] = (char) ch;
buf[i] = '\0';
if (buf[0] & 0x80) { /* scan up */
for (j = 0; scan_up[j]; j++) {
if (i == scan_length[j] &&
!strcmp(buf, scan_up[j])) {
i = 0;
shift_state &= ~scan_value[j];
break;
}
}
continue;
}
for (j = 0; scan_down[j]; j++) {
if (i == scan_length[j] && !strcmp(buf, scan_down[j])) {
i = 0;
shift_state |= scan_value[j];
ch = (int) scan_value[j];
if (ch == CAPS_LOCK)
shift_state ^= SHIFT_KEY;
if (ch >= 256)
break;
if (shift_state & SHIFT_KEY) {
if (ch >= 0x60)
ch -= 0x20;
else if (ch >= 0x30 && ch <= 0x3f)
ch -= 0x10;
}
if (shift_state & CONTROL_KEY) {
if ((ch | 0x20) >= 0x60 &&
(ch | 0x20) <= 0x7f)
ch = (ch | 0x20) - 0x60;
}
if (shift_state & META_KEY)
ch |= 0x80;
return ch;
}
}
if (i > scan_max)
i = 1;
}
}