Annotation of src/usr.bin/mg/kbd.c, Revision 1.14
1.14 ! vincent 1: /* $OpenBSD: kbd.c,v 1.13 2002/02/21 15:27:29 deraadt Exp $ */
1.4 niklas 2:
1.1 deraadt 3: /*
1.3 millert 4: * Terminal independent keyboard handling.
1.1 deraadt 5: */
6:
7: #define EXTERN
1.3 millert 8:
9: #include "def.h"
10: #include "kbd.h"
11: #include "key.h"
1.1 deraadt 12:
13: #ifndef NO_MACRO
14: #include "macro.h"
1.3 millert 15: #endif /* !NO_MACRO */
1.1 deraadt 16:
1.3 millert 17: #ifdef DO_METAKEY
1.1 deraadt 18: #ifndef METABIT
19: #define METABIT 0x80
1.3 millert 20: #endif /* !METABIT */
21:
22: #ifndef NO_DPROMPT
23: #define PROMPTL 80
1.9 mickey 24: char prompt[PROMPTL] = "", *promptp = prompt;
1.3 millert 25: #endif /* !NO_DPROMPT */
1.1 deraadt 26:
1.3 millert 27: static int use_metakey = TRUE;
28: static int pushed = FALSE;
29: static int pushedc;
30:
31: MAP_ELEMENT *ele;
1.1 deraadt 32:
33: /*
34: * Toggle the value of use_metakey
35: */
1.2 millert 36: int
1.14 ! vincent 37: do_meta(int f, int n)
1.1 deraadt 38: {
1.2 millert 39: if (f & FFARG)
40: use_metakey = n > 0;
41: else
42: use_metakey = !use_metakey;
1.1 deraadt 43: ewprintf("Meta keys %sabled", use_metakey ? "en" : "dis");
44: return TRUE;
45: }
1.3 millert 46: #endif /* DO_METAKEY */
1.1 deraadt 47:
1.3 millert 48: #ifdef BSMAP
49: static int bs_map = BSMAP;
1.1 deraadt 50: /*
51: * Toggle backspace mapping
52: */
1.2 millert 53: int
1.14 ! vincent 54: bsmap(int f, int n)
1.1 deraadt 55: {
1.2 millert 56: if (f & FFARG)
57: bs_map = n > 0;
58: else
59: bs_map = !bs_map;
1.1 deraadt 60: ewprintf("Backspace mapping %sabled", bs_map ? "en" : "dis");
61: return TRUE;
62: }
1.3 millert 63: #endif /* BSMAP */
1.1 deraadt 64:
1.8 art 65: void
1.14 ! vincent 66: ungetkey(int c)
1.1 deraadt 67: {
1.3 millert 68: #ifdef DO_METAKEY
1.2 millert 69: if (use_metakey && pushed && c == CCHR('['))
70: pushedc |= METABIT;
1.1 deraadt 71: else
1.3 millert 72: #endif /* DO_METAKEY */
1.1 deraadt 73: pushedc = c;
74: pushed = TRUE;
75: }
76:
1.2 millert 77: int
1.14 ! vincent 78: getkey(int flag)
1.1 deraadt 79: {
1.3 millert 80: int c;
1.1 deraadt 81:
82: #ifndef NO_DPROMPT
1.2 millert 83: if (flag && !pushed) {
1.5 art 84: if (prompt[0] != '\0' && ttwait(2000)) {
1.3 millert 85: /* avoid problems with % */
86: ewprintf("%s", prompt);
87: /* put the cursor back */
88: update();
1.1 deraadt 89: epresf = KPROMPT;
90: }
1.2 millert 91: if (promptp > prompt)
92: *(promptp - 1) = ' ';
1.1 deraadt 93: }
1.3 millert 94: #endif /* !NO_DPROMPT */
1.2 millert 95: if (pushed) {
1.1 deraadt 96: c = pushedc;
97: pushed = FALSE;
1.2 millert 98: } else
1.12 deraadt 99: c = ttgetc();
1.3 millert 100: #ifdef BSMAP
1.2 millert 101: if (bs_map)
102: if (c == CCHR('H'))
103: c = CCHR('?');
104: else if (c == CCHR('?'))
105: c = CCHR('H');
1.3 millert 106: #endif /* BSMAP */
107: #ifdef DO_METAKEY
1.2 millert 108: if (use_metakey && (c & METABIT)) {
1.1 deraadt 109: pushedc = c & ~METABIT;
110: pushed = TRUE;
111: c = CCHR('[');
112: }
1.3 millert 113: #endif /* DO_METAKEY */
1.1 deraadt 114: #ifndef NO_DPROMPT
1.2 millert 115: if (flag && promptp < &prompt[PROMPTL - 5]) {
1.9 mickey 116: promptp = keyname(promptp,
117: sizeof(prompt) - (promptp - prompt) - 1, c);
1.2 millert 118: *promptp++ = '-';
119: *promptp = '\0';
1.1 deraadt 120: }
1.3 millert 121: #endif /* !NO_DPROMPT */
1.1 deraadt 122: return c;
123: }
124:
125: /*
126: * doscan scans a keymap for a keyboard character and returns a pointer
127: * to the function associated with that character. Sets ele to the
128: * keymap element the keyboard was found in as a side effect.
129: */
1.2 millert 130: PF
1.14 ! vincent 131: doscan(KEYMAP *map, int c, KEYMAP **newmap)
1.2 millert 132: {
1.3 millert 133: MAP_ELEMENT *elec = &map->map_element[0];
134: MAP_ELEMENT *last = &map->map_element[map->map_num];
1.7 art 135: PF ret;
1.1 deraadt 136:
1.2 millert 137: while (elec < last && c > elec->k_num)
138: elec++;
1.3 millert 139:
140: /* used by prefix and binding code */
141: ele = elec;
1.2 millert 142: if (elec >= last || c < elec->k_base)
1.7 art 143: ret = map->map_default;
144: else
145: ret = elec->k_funcp[c - elec->k_base];
146: if (ret == NULL && newmap != NULL)
147: *newmap = elec->k_prefmap;
148:
149: return ret;
1.1 deraadt 150: }
151:
1.2 millert 152: int
1.14 ! vincent 153: doin(void)
1.1 deraadt 154: {
1.3 millert 155: KEYMAP *curmap;
156: PF funct;
1.1 deraadt 157:
158: #ifndef NO_DPROMPT
1.2 millert 159: *(promptp = prompt) = '\0';
1.3 millert 160: #endif /* !NO_DPROMPT */
1.2 millert 161: curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
162: key.k_count = 0;
163: while ((funct = doscan(curmap, (key.k_chars[key.k_count++] =
1.7 art 164: getkey(TRUE)), &curmap)) == NULL)
165: /*nothing*/;
1.1 deraadt 166: #ifndef NO_MACRO
1.2 millert 167: if (macrodef && macrocount < MAXMACRO)
168: macro[macrocount++].m_funct = funct;
1.3 millert 169: #endif /* !NO_MACRO */
170: return (*funct)(0, 1);
1.1 deraadt 171: }
172:
1.2 millert 173: int
1.14 ! vincent 174: rescan(int f, int n)
1.1 deraadt 175: {
1.3 millert 176: int c;
177: KEYMAP *curmap;
178: int i;
179: PF fp = NULL;
180: int mode = curbp->b_nmodes;
1.2 millert 181:
182: for (;;) {
183: if (ISUPPER(key.k_chars[key.k_count - 1])) {
184: c = TOLOWER(key.k_chars[key.k_count - 1]);
185: curmap = curbp->b_modes[mode]->p_map;
186: for (i = 0; i < key.k_count - 1; i++) {
1.10 mickey 187: if ((fp = doscan(curmap, (key.k_chars[i]), &curmap))
1.6 art 188: != NULL)
1.2 millert 189: break;
190: }
1.6 art 191: if (fp == NULL) {
1.7 art 192: if ((fp = doscan(curmap, c, NULL)) == NULL)
1.2 millert 193: while ((fp = doscan(curmap,
194: key.k_chars[key.k_count++] =
1.7 art 195: getkey(TRUE), &curmap)) == NULL)
196: /*nothing*/;
1.2 millert 197: if (fp != rescan) {
198: #ifndef NO_MACRO
199: if (macrodef && macrocount <= MAXMACRO)
1.10 mickey 200: macro[macrocount - 1].m_funct
1.3 millert 201: = fp;
202: #endif /* !NO_MACRO */
203: return (*fp)(f, n);
1.2 millert 204: }
205: }
206: }
207: /* try previous mode */
208: if (--mode < 0)
209: return ABORT;
210: curmap = curbp->b_modes[mode]->p_map;
211: for (i = 0; i < key.k_count; i++) {
1.7 art 212: if ((fp = doscan(curmap, (key.k_chars[i]), &curmap)) != NULL)
1.2 millert 213: break;
214: }
1.6 art 215: if (fp == NULL) {
1.10 mickey 216: while ((fp = doscan(curmap, key.k_chars[i++] =
1.7 art 217: getkey(TRUE), &curmap)) == NULL)
218: /*nothing*/;
1.2 millert 219: key.k_count = i;
220: }
221: if (fp != rescan && i >= key.k_count - 1) {
1.1 deraadt 222: #ifndef NO_MACRO
1.2 millert 223: if (macrodef && macrocount <= MAXMACRO)
224: macro[macrocount - 1].m_funct = fp;
1.3 millert 225: #endif /* !NO_MACRO */
226: return (*fp)(f, n);
1.1 deraadt 227: }
228: }
1.2 millert 229: }
230:
231: int
1.14 ! vincent 232: universal_argument(int f, int n)
1.2 millert 233: {
1.3 millert 234: KEYMAP *curmap;
235: PF funct;
1.10 mickey 236: int c;
1.3 millert 237: int nn = 4;
1.2 millert 238:
239: if (f & FFUNIV)
240: nn *= n;
241: for (;;) {
242: key.k_chars[0] = c = getkey(TRUE);
243: key.k_count = 1;
244: if (c == '-')
245: return negative_argument(f, nn);
246: if (c >= '0' && c <= '9')
247: return digit_argument(f, nn);
248: curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.7 art 249: while ((funct = doscan(curmap, c, &curmap)) == NULL) {
1.2 millert 250: key.k_chars[key.k_count++] = c = getkey(TRUE);
251: }
252: if (funct != universal_argument) {
1.1 deraadt 253: #ifndef NO_MACRO
1.2 millert 254: if (macrodef && macrocount < MAXMACRO - 1) {
255: if (f & FFARG)
256: macrocount--;
257: macro[macrocount++].m_count = nn;
258: macro[macrocount++].m_funct = funct;
259: }
1.3 millert 260: #endif /* !NO_MACRO */
261: return (*funct)(FFUNIV, nn);
1.2 millert 262: }
263: nn <<= 2;
1.1 deraadt 264: }
265: }
266:
1.2 millert 267: /* ARGSUSED */
268: int
1.14 ! vincent 269: digit_argument(int f, int n)
1.1 deraadt 270: {
1.3 millert 271: KEYMAP *curmap;
272: PF funct;
273: int nn, c;
1.2 millert 274:
275: nn = key.k_chars[key.k_count - 1] - '0';
276: for (;;) {
277: c = getkey(TRUE);
278: if (c < '0' || c > '9')
279: break;
280: nn *= 10;
281: nn += c - '0';
282: }
283: key.k_chars[0] = c;
1.1 deraadt 284: key.k_count = 1;
285: curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.7 art 286: while ((funct = doscan(curmap, c, &curmap)) == NULL) {
1.2 millert 287: key.k_chars[key.k_count++] = c = getkey(TRUE);
1.1 deraadt 288: }
289: #ifndef NO_MACRO
1.2 millert 290: if (macrodef && macrocount < MAXMACRO - 1) {
291: if (f & FFARG)
292: macrocount--;
293: else
294: macro[macrocount - 1].m_funct = universal_argument;
1.1 deraadt 295: macro[macrocount++].m_count = nn;
296: macro[macrocount++].m_funct = funct;
297: }
1.3 millert 298: #endif /* !NO_MACRO */
299: return (*funct)(FFOTHARG, nn);
1.1 deraadt 300: }
301:
1.2 millert 302: int
1.14 ! vincent 303: negative_argument(int f, int n)
1.1 deraadt 304: {
1.3 millert 305: KEYMAP *curmap;
306: PF funct;
307: int c;
308: int nn = 0;
1.2 millert 309:
310: for (;;) {
311: c = getkey(TRUE);
312: if (c < '0' || c > '9')
313: break;
314: nn *= 10;
315: nn += c - '0';
316: }
317: if (nn)
318: nn = -nn;
319: else
320: nn = -n;
321: key.k_chars[0] = c;
322: key.k_count = 1;
323: curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.7 art 324: while ((funct = doscan(curmap, c, &curmap)) == NULL) {
1.2 millert 325: key.k_chars[key.k_count++] = c = getkey(TRUE);
326: }
1.1 deraadt 327: #ifndef NO_MACRO
1.2 millert 328: if (macrodef && macrocount < MAXMACRO - 1) {
329: if (f & FFARG)
330: macrocount--;
331: else
332: macro[macrocount - 1].m_funct = universal_argument;
333: macro[macrocount++].m_count = nn;
334: macro[macrocount++].m_funct = funct;
335: }
1.3 millert 336: #endif /* !NO_MACRO */
337: return (*funct)(FFNEGARG, nn);
1.1 deraadt 338: }
339:
340: /*
341: * Insert a character. While defining a macro, create a "LINE" containing
342: * all inserted characters.
343: */
1.2 millert 344: int
1.14 ! vincent 345: selfinsert(int f, int n)
1.1 deraadt 346: {
347: #ifndef NO_MACRO
1.3 millert 348: LINE *lp;
349: #endif /* !NO_MACRO */
350: int c;
351: int count;
1.1 deraadt 352:
1.2 millert 353: if (n < 0)
354: return FALSE;
355: if (n == 0)
356: return TRUE;
357: c = key.k_chars[key.k_count - 1];
1.1 deraadt 358: #ifndef NO_MACRO
1.2 millert 359: if (macrodef && macrocount < MAXMACRO) {
360: if (f & FFARG)
361: macrocount -= 2;
1.3 millert 362:
363: /* last command was insert -- tack on the end */
364: if (lastflag & CFINS) {
1.2 millert 365: macrocount--;
1.11 vincent 366: /* Ensure the line can handle the new characters */
1.2 millert 367: if (maclcur->l_size < maclcur->l_used + n) {
1.11 vincent 368: if (lrealloc(maclcur, maclcur->l_used + n) ==
369: FALSE)
1.2 millert 370: return FALSE;
371: }
1.11 vincent 372: maclcur->l_used += n;
373: /* Copy in the new data */
374: for (count = maclcur->l_used - n;
1.13 deraadt 375: count < maclcur->l_used; count++)
1.11 vincent 376: maclcur->l_text[count] = c;
1.2 millert 377: } else {
378: macro[macrocount - 1].m_funct = insert;
1.11 vincent 379: if ((lp = lalloc(n)) == NULL)
1.2 millert 380: return FALSE;
381: lp->l_bp = maclcur;
382: lp->l_fp = maclcur->l_fp;
383: maclcur->l_fp = lp;
384: maclcur = lp;
385: for (count = 0; count < n; count++)
386: lp->l_text[count] = c;
387: }
388: thisflag |= CFINS;
389: }
1.3 millert 390: #endif /* !NO_MACRO */
1.2 millert 391: if (c == '\n') {
392: do {
393: count = lnewline();
394: } while (--n && count == TRUE);
395: return count;
396: }
1.3 millert 397:
398: /* overwrite mode */
399: if (curbp->b_flag & BFOVERWRITE) {
1.2 millert 400: lchange(WFEDIT);
401: while (curwp->w_doto < llength(curwp->w_dotp) && n--)
402: lputc(curwp->w_dotp, curwp->w_doto++, c);
403: if (n <= 0)
404: return TRUE;
405: }
406: return linsert(n, c);
1.1 deraadt 407: }
408:
409: /*
1.3 millert 410: * This could be implemented as a keymap with everthing defined as self-insert.
1.1 deraadt 411: */
1.2 millert 412: int
1.14 ! vincent 413: quote(int f, int n)
1.1 deraadt 414: {
1.3 millert 415: int c;
1.1 deraadt 416:
1.2 millert 417: key.k_count = 1;
418: if ((key.k_chars[0] = getkey(TRUE)) >= '0' && key.k_chars[0] <= '7') {
419: key.k_chars[0] -= '0';
420: if ((c = getkey(TRUE)) >= '0' && c <= '7') {
421: key.k_chars[0] <<= 3;
422: key.k_chars[0] += c - '0';
423: if ((c = getkey(TRUE)) >= '0' && c <= '7') {
424: key.k_chars[0] <<= 3;
425: key.k_chars[0] += c - '0';
426: } else
427: ungetkey(c);
428: } else
429: ungetkey(c);
430: }
431: return selfinsert(f, n);
1.1 deraadt 432: }