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 |
8 | typedef union keytab keytab; |
9 | |
10 | union 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 | |
22 | keytab *base[256] = { NULL256 }; |
23 | |
24 | /* |
25 | * Bind a key sequence to an action. |
26 | */ |
27 | void 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 | */ |
64 | static 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 | */ |
79 | void 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 | } |