1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122
|
#include "tweak.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
typedef union keytab keytab;
union keytab {
enum {ACTION, EXTENDED} type;
struct {
int type;
keyact action;
} a;
struct {
int type;
keytab *extended[256];
} e;
};
keytab *base[256] = { NULL256 };
/*
* Bind a key sequence to an action.
*/
void bind_key (char *sequence, int len, keyact action) {
keytab *(*table)[256];
int k, i;
table = &base;
while (--len) {
k = (unsigned char) *sequence++;
if ( !(*table)[k] ) {
/*
* We must create an EXTENDED entry.
*/
(*table)[k] = malloc(sizeof(base[0]->e));
(*table)[k]->type = EXTENDED;
for (i=0; i<256; i++)
(*table)[k]->e.extended[i] = NULL;
} else if ( (*table)[k]->type == ACTION ) {
/*
* A subsequence is already bound: fail.
*/
return;
}
table = &(*table)[k]->e.extended;
}
k = (unsigned char) *sequence;
if ( !(*table)[k] ) {
/*
* We can bind the key.
*/
(*table)[k] = malloc(sizeof(base[0]->a));
(*table)[k]->type = ACTION;
(*table)[k]->a.action = action;
}
}
/*
* Format an ASCII code into a printable description of the key stroke.
*/
static void strkey (char *s, int k) {
k &= 255; /* force unsigned */
if (k==27)
strcpy(s, " ESC");
else if (k<32 || k==127)
sprintf(s, " ^%c", k ^ 64);
else if (k<127)
sprintf(s, " %c", k);
else
sprintf(s, " <0x%2X>", k);
}
/*
* Get and process a key stroke.
*/
void proc_key (void) {
keytab *kt;
#if defined(unix) && !defined(GO32)
if (update_required)
update();
safe_update = TRUE;
#endif
last_char = display_getkey();
#if defined(unix) && !defined(GO32)
safe_update = FALSE;
#endif
strcpy(message, "Unknown key sequence");
strkey(message+strlen(message), last_char);
kt = base[(unsigned char) last_char];
if (!kt) {
display_beep();
while (display_input_to_flush())
strkey(message+strlen(message), display_getkey());
return;
}
while (kt->type == EXTENDED) {
#if defined(unix) && !defined(GO32)
if (update_required)
update();
safe_update = TRUE;
#endif
last_char = display_getkey();
#if defined(unix) && !defined(GO32)
safe_update = FALSE;
#endif
strkey(message+strlen(message), last_char);
kt = kt->e.extended[(unsigned char) last_char];
if (!kt) {
display_beep();
while (display_input_to_flush())
strkey(message+strlen(message), display_getkey());
return;
}
}
message[0] = '\0'; /* clear the "unknown" message */
(*kt->a.action)();
}
|