1 /* $MirOS: contrib/code/jupp/kbd.c,v 1.4 2017/01/10 19:16:27 tg Exp $ */
5 * (C) 1992 Joseph H. Allen
7 * This file is part of JOE (Joe's Own Editor)
22 KBD *mkkbd(KMAP *kmap)
24 KBD *kbd = (KBD *) joe_malloc(sizeof(KBD));
39 /* Process next key for KBD */
41 void *dokey(KBD *kbd, int n)
45 /* If we were passed a negative character */
49 /* kmap->keys[KEYS]; */
50 if ((size_t)n >= (size_t)(KEYS))
53 /* If we're starting from scratch, clear the keymap sequence buffer */
54 if (kbd->curmap == kbd->topmap)
57 if (kbd->curmap->keys[n].k == 1) { /* A prefix key was found */
58 kbd->seq[kbd->x++] = n;
59 kbd->curmap = kbd->curmap->keys[n].value.submap;
60 } else { /* A complete key sequence was entered or an unbound key was found */
61 bind = kbd->curmap->keys[n].value.bind;
62 /* kbd->seq[kbd->x++]=n; */
64 kbd->curmap = kbd->topmap;
69 /* Return key code for key name or -1 for syntax error */
71 static int keyval(unsigned char *s)
73 if (s[0] == '^' && s[1] && !s[2])
78 else if ((s[0] == 'S' || s[0] == 's')
79 && (s[1] == 'P' || s[1] == 'p') && !s[2])
81 else if (s[1] || !s[0])
84 return (unsigned char) s[0];
87 /* Create an empty keymap */
91 KMAP *kmap = (KMAP *) joe_calloc(sizeof(KMAP), 1);
96 /* Eliminate a keymap */
98 void rmkmap(KMAP *kmap)
104 for (x = 0; x != KEYS; ++x)
105 if (kmap->keys[x].k == 1)
106 rmkmap(kmap->keys[x].value.submap);
112 static unsigned char *range(unsigned char *seq, int *vv, int *ww)
117 for (x = 0; seq[x] && seq[x] != ' '; ++x) ; /* Skip to a space */
119 seq[x] = 0; /* Zero terminate the string */
120 v = keyval(seq); /* Get key */
124 seq[x] = c; /* Restore the space or 0 */
125 for (seq += x; *seq == ' '; ++seq) ; /* Skip over spaces */
127 /* Check for 'TO ' */
128 if ((seq[0] == 'T' || seq[0] == 't') && (seq[1] == 'O' || seq[1] == 'o') && seq[2] == ' ') {
129 for (seq += 2; *seq == ' '; ++seq) ; /* Skip over spaces */
130 for (x = 0; seq[x] && seq[x] != ' '; ++x) ; /* Skip to space */
132 seq[x] = 0; /* Zero terminate the string */
133 w = keyval(seq); /* Get key */
136 seq[x] = c; /* Restore the space or 0 */
137 for (seq += x; *seq == ' '; ++seq) ; /* Skip over spaces */
148 /* Add a binding to a keymap */
150 static KMAP *kbuild(CAP *cap, KMAP *kmap, unsigned char *seq, void *bind, int *err, unsigned char *capseq, int seql)
154 if (!seql && seq[0] == '.' && seq[1]) {
158 for (x = 0; seq[x] && seq[x] != ' '; ++x) ;
162 if (!strcmp(seq + 1, "ku")) {
165 } else if (!strcmp(seq + 1, "kd")) {
168 } else if (!strcmp(seq + 1, "kl")) {
171 } else if (!strcmp(seq + 1, "kr")) {
174 } else if (!strcmp(seq + 1, "kI")) {
177 } else if (!strcmp(seq + 1, "kD")) {
180 } else if (!strcmp(seq + 1, "kh")) {
183 } else if (!strcmp(seq + 1, "kH")) {
186 } else if (!strcmp(seq + 1, "kP")) {
189 } else if (!strcmp(seq + 1, "kN")) {
192 } else if (!strcmp(seq + 1, "k1")) {
195 } else if (!strcmp(seq + 1, "k2")) {
198 } else if (!strcmp(seq + 1, "k3")) {
201 } else if (!strcmp(seq + 1, "k4")) {
204 } else if (!strcmp(seq + 1, "k5")) {
207 } else if (!strcmp(seq + 1, "k6")) {
210 } else if (!strcmp(seq + 1, "k7")) {
213 } else if (!strcmp(seq + 1, "k8")) {
216 } else if (!strcmp(seq + 1, "k9")) {
219 } else if (!strcmp(seq + 1, "k0")) {
225 for (seq += x; *seq == ' '; ++seq) ;
228 s = jgetstr(cap, seq + 1);
230 if (s && (s = tcompile(cap, s, 0, 0, 0, 0))
231 && (sLEN(s) > 1 || (signed char)s[0] < 0)) {
234 for (seq += x; *seq == ' '; ++seq) ;
244 v = w = (unsigned char) *capseq++;
247 seq = range(seq, &v, &w);
255 kmap = mkkmap(); /* Create new keymap if 'kmap' was NULL */
257 /* Make bindings between v and w */
260 if (kmap->keys[v].k == 0)
261 kmap->keys[v].value.submap = NULL;
263 kmap->keys[v].value.submap = kbuild(cap, kmap->keys[v].value.bind, seq, bind, err, capseq, seql);
265 if (kmap->keys[v].k == 1)
266 rmkmap(kmap->keys[v].value.submap);
268 kmap->keys[v].value.bind =
269 /* This bit of code sticks the key value in the macro */
270 (v == w ? macstk(bind, v) : dupmacro(macstk(bind, v)));
277 int kadd(CAP *cap, KMAP *kmap, unsigned char *seq, void *bind)
281 kbuild(cap, kmap, seq, bind, &err, NULL, 0);
285 void kcpy(KMAP *dest, KMAP *src)
289 for (x = 0; x != KEYS; ++x)
290 if (src->keys[x].k == 1) {
291 if (dest->keys[x].k != 1) {
293 dest->keys[x].value.submap = mkkmap();
295 kcpy(dest->keys[x].value.submap, src->keys[x].value.submap);
296 } else if (src->keys[x].k == 0 && src->keys[x].value.bind) {
297 if (dest->keys[x].k == 1)
298 rmkmap(dest->keys[x].value.submap);
299 dest->keys[x].value.bind = src->keys[x].value.bind;
304 /* Remove a binding from a keymap */
306 int kdel(KMAP *kmap, unsigned char *seq)
311 seq = range(seq, &v, &w);
315 /* Clear bindings between v and w */
318 if (kmap->keys[v].k == 1) {
319 int r = kdel(kmap->keys[v].value.submap, seq);
325 if (kmap->keys[v].k == 1)
326 rmkmap(kmap->keys[v].value.submap);
328 kmap->keys[v].value.bind = NULL;