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