4 * (C) 1992 Joseph H. Allen
6 * This file is part of JOE (Joe's Own Editor)
11 __RCSID("$MirOS: contrib/code/jupp/kbd.c,v 1.5 2017/12/02 02:07:28 tg Exp $");
23 KBD *mkkbd(KMAP *kmap)
25 KBD *kbd = (KBD *) joe_malloc(sizeof(KBD));
40 /* Process next key for KBD */
42 void *dokey(KBD *kbd, int n)
46 /* If we were passed a negative character */
50 /* kmap->keys[KEYS]; */
51 if ((size_t)n >= (size_t)(KEYS))
54 /* If we're starting from scratch, clear the keymap sequence buffer */
55 if (kbd->curmap == kbd->topmap)
58 if (kbd->curmap->keys[n].k == 1) { /* A prefix key was found */
59 kbd->seq[kbd->x++] = n;
60 kbd->curmap = kbd->curmap->keys[n].value.submap;
61 } else { /* A complete key sequence was entered or an unbound key was found */
62 bind = kbd->curmap->keys[n].value.bind;
63 /* kbd->seq[kbd->x++]=n; */
65 kbd->curmap = kbd->topmap;
70 /* Return key code for key name or -1 for syntax error */
72 static int keyval(unsigned char *s)
74 if (s[0] == '^' && s[1] && !s[2])
79 else if ((s[0] == 'S' || s[0] == 's')
80 && (s[1] == 'P' || s[1] == 'p') && !s[2])
82 else if (s[1] || !s[0])
85 return (unsigned char) s[0];
88 /* Create an empty keymap */
92 KMAP *kmap = (KMAP *) joe_calloc(sizeof(KMAP), 1);
97 /* Eliminate a keymap */
99 void rmkmap(KMAP *kmap)
105 for (x = 0; x != KEYS; ++x)
106 if (kmap->keys[x].k == 1)
107 rmkmap(kmap->keys[x].value.submap);
113 static unsigned char *range(unsigned char *seq, int *vv, int *ww)
118 for (x = 0; seq[x] && seq[x] != ' '; ++x) ; /* Skip to a space */
120 seq[x] = 0; /* Zero terminate the string */
121 v = keyval(seq); /* Get key */
125 seq[x] = c; /* Restore the space or 0 */
126 for (seq += x; *seq == ' '; ++seq) ; /* Skip over spaces */
128 /* Check for 'TO ' */
129 if ((seq[0] == 'T' || seq[0] == 't') && (seq[1] == 'O' || seq[1] == 'o') && seq[2] == ' ') {
130 for (seq += 2; *seq == ' '; ++seq) ; /* Skip over spaces */
131 for (x = 0; seq[x] && seq[x] != ' '; ++x) ; /* Skip to space */
133 seq[x] = 0; /* Zero terminate the string */
134 w = keyval(seq); /* Get key */
137 seq[x] = c; /* Restore the space or 0 */
138 for (seq += x; *seq == ' '; ++seq) ; /* Skip over spaces */
149 /* Add a binding to a keymap */
151 static KMAP *kbuild(CAP *cap, KMAP *kmap, unsigned char *seq, void *bind, int *err, unsigned char *capseq, int seql)
155 if (!seql && seq[0] == '.' && seq[1]) {
159 for (x = 0; seq[x] && seq[x] != ' '; ++x) ;
163 if (!strcmp(seq + 1, "ku")) {
166 } else if (!strcmp(seq + 1, "kd")) {
169 } else if (!strcmp(seq + 1, "kl")) {
172 } else if (!strcmp(seq + 1, "kr")) {
175 } else if (!strcmp(seq + 1, "kI")) {
178 } else if (!strcmp(seq + 1, "kD")) {
181 } else if (!strcmp(seq + 1, "kh")) {
184 } else if (!strcmp(seq + 1, "kH")) {
187 } else if (!strcmp(seq + 1, "kP")) {
190 } else if (!strcmp(seq + 1, "kN")) {
193 } else if (!strcmp(seq + 1, "k1")) {
196 } else if (!strcmp(seq + 1, "k2")) {
199 } else if (!strcmp(seq + 1, "k3")) {
202 } else if (!strcmp(seq + 1, "k4")) {
205 } else if (!strcmp(seq + 1, "k5")) {
208 } else if (!strcmp(seq + 1, "k6")) {
211 } else if (!strcmp(seq + 1, "k7")) {
214 } else if (!strcmp(seq + 1, "k8")) {
217 } else if (!strcmp(seq + 1, "k9")) {
220 } else if (!strcmp(seq + 1, "k0")) {
226 for (seq += x; *seq == ' '; ++seq) ;
229 s = jgetstr(cap, seq + 1);
231 if (s && (s = tcompile(cap, s, 0, 0, 0, 0))
232 && (sLEN(s) > 1 || (signed char)s[0] < 0)) {
235 for (seq += x; *seq == ' '; ++seq) ;
245 v = w = (unsigned char) *capseq++;
248 seq = range(seq, &v, &w);
256 kmap = mkkmap(); /* Create new keymap if 'kmap' was NULL */
258 /* Make bindings between v and w */
261 if (kmap->keys[v].k == 0)
262 kmap->keys[v].value.submap = NULL;
264 kmap->keys[v].value.submap = kbuild(cap, kmap->keys[v].value.bind, seq, bind, err, capseq, seql);
266 if (kmap->keys[v].k == 1)
267 rmkmap(kmap->keys[v].value.submap);
269 kmap->keys[v].value.bind =
270 /* This bit of code sticks the key value in the macro */
271 (v == w ? macstk(bind, v) : dupmacro(macstk(bind, v)));
278 int kadd(CAP *cap, KMAP *kmap, unsigned char *seq, void *bind)
282 kbuild(cap, kmap, seq, bind, &err, NULL, 0);
286 void kcpy(KMAP *dest, KMAP *src)
290 for (x = 0; x != KEYS; ++x)
291 if (src->keys[x].k == 1) {
292 if (dest->keys[x].k != 1) {
294 dest->keys[x].value.submap = mkkmap();
296 kcpy(dest->keys[x].value.submap, src->keys[x].value.submap);
297 } else if (src->keys[x].k == 0 && src->keys[x].value.bind) {
298 if (dest->keys[x].k == 1)
299 rmkmap(dest->keys[x].value.submap);
300 dest->keys[x].value.bind = src->keys[x].value.bind;
305 /* Remove a binding from a keymap */
307 int kdel(KMAP *kmap, unsigned char *seq)
312 seq = range(seq, &v, &w);
316 /* Clear bindings between v and w */
319 if (kmap->keys[v].k == 1) {
320 int r = kdel(kmap->keys[v].value.submap, seq);
326 if (kmap->keys[v].k == 1)
327 rmkmap(kmap->keys[v].value.submap);
329 kmap->keys[v].value.bind = NULL;