Annotation of src/usr.bin/mg/kbd.c, Revision 1.16
1.16 ! db 1: /* $OpenBSD: kbd.c,v 1.15 2004/02/01 22:26:40 vincent Exp $ */
1.4 niklas 2:
1.1 deraadt 3: /*
1.3 millert 4: * Terminal independent keyboard handling.
1.1 deraadt 5: */
6:
1.3 millert 7: #include "def.h"
8: #include "kbd.h"
9: #include "key.h"
1.1 deraadt 10:
11: #ifndef NO_MACRO
12: #include "macro.h"
1.3 millert 13: #endif /* !NO_MACRO */
1.1 deraadt 14:
1.3 millert 15: #ifdef DO_METAKEY
1.1 deraadt 16: #ifndef METABIT
17: #define METABIT 0x80
1.3 millert 18: #endif /* !METABIT */
19:
20: #ifndef NO_DPROMPT
21: #define PROMPTL 80
1.9 mickey 22: char prompt[PROMPTL] = "", *promptp = prompt;
1.3 millert 23: #endif /* !NO_DPROMPT */
1.1 deraadt 24:
1.3 millert 25: static int use_metakey = TRUE;
26: static int pushed = FALSE;
27: static int pushedc;
28:
29: MAP_ELEMENT *ele;
1.15 vincent 30:
31: struct key key;
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");
1.16 ! db 44: return (TRUE);
1.1 deraadt 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");
1.16 ! db 61: return (TRUE);
1.1 deraadt 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.16 ! db 122: return (c);
1.1 deraadt 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.16 ! db 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:
1.16 ! db 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)
1.16 ! db 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 */
1.16 ! db 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)
1.16 ! db 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 */
1.16 ! db 203: return ((*fp)(f, n));
1.2 millert 204: }
205: }
206: }
207: /* try previous mode */
208: if (--mode < 0)
1.16 ! db 209: return (ABORT);
1.2 millert 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)
1.16 ! db 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 */
1.16 ! db 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.16 ! db 236: int c, nn = 4;
1.2 millert 237:
238: if (f & FFUNIV)
239: nn *= n;
240: for (;;) {
241: key.k_chars[0] = c = getkey(TRUE);
242: key.k_count = 1;
243: if (c == '-')
1.16 ! db 244: return (negative_argument(f, nn));
1.2 millert 245: if (c >= '0' && c <= '9')
1.16 ! db 246: return (digit_argument(f, nn));
1.2 millert 247: curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.7 art 248: while ((funct = doscan(curmap, c, &curmap)) == NULL) {
1.2 millert 249: key.k_chars[key.k_count++] = c = getkey(TRUE);
250: }
251: if (funct != universal_argument) {
1.1 deraadt 252: #ifndef NO_MACRO
1.2 millert 253: if (macrodef && macrocount < MAXMACRO - 1) {
254: if (f & FFARG)
255: macrocount--;
256: macro[macrocount++].m_count = nn;
257: macro[macrocount++].m_funct = funct;
258: }
1.3 millert 259: #endif /* !NO_MACRO */
1.16 ! db 260: return ((*funct)(FFUNIV, nn));
1.2 millert 261: }
262: nn <<= 2;
1.1 deraadt 263: }
264: }
265:
1.2 millert 266: /* ARGSUSED */
267: int
1.14 vincent 268: digit_argument(int f, int n)
1.1 deraadt 269: {
1.3 millert 270: KEYMAP *curmap;
271: PF funct;
272: int nn, c;
1.2 millert 273:
274: nn = key.k_chars[key.k_count - 1] - '0';
275: for (;;) {
276: c = getkey(TRUE);
277: if (c < '0' || c > '9')
278: break;
279: nn *= 10;
280: nn += c - '0';
281: }
282: key.k_chars[0] = c;
1.1 deraadt 283: key.k_count = 1;
284: curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.7 art 285: while ((funct = doscan(curmap, c, &curmap)) == NULL) {
1.2 millert 286: key.k_chars[key.k_count++] = c = getkey(TRUE);
1.1 deraadt 287: }
288: #ifndef NO_MACRO
1.2 millert 289: if (macrodef && macrocount < MAXMACRO - 1) {
290: if (f & FFARG)
291: macrocount--;
292: else
293: macro[macrocount - 1].m_funct = universal_argument;
1.1 deraadt 294: macro[macrocount++].m_count = nn;
295: macro[macrocount++].m_funct = funct;
296: }
1.3 millert 297: #endif /* !NO_MACRO */
1.16 ! db 298: return ((*funct)(FFOTHARG, nn));
1.1 deraadt 299: }
300:
1.2 millert 301: int
1.14 vincent 302: negative_argument(int f, int n)
1.1 deraadt 303: {
1.3 millert 304: KEYMAP *curmap;
305: PF funct;
306: int c;
307: int nn = 0;
1.2 millert 308:
309: for (;;) {
310: c = getkey(TRUE);
311: if (c < '0' || c > '9')
312: break;
313: nn *= 10;
314: nn += c - '0';
315: }
316: if (nn)
317: nn = -nn;
318: else
319: nn = -n;
320: key.k_chars[0] = c;
321: key.k_count = 1;
322: curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
1.7 art 323: while ((funct = doscan(curmap, c, &curmap)) == NULL) {
1.2 millert 324: key.k_chars[key.k_count++] = c = getkey(TRUE);
325: }
1.1 deraadt 326: #ifndef NO_MACRO
1.2 millert 327: if (macrodef && macrocount < MAXMACRO - 1) {
328: if (f & FFARG)
329: macrocount--;
330: else
331: macro[macrocount - 1].m_funct = universal_argument;
332: macro[macrocount++].m_count = nn;
333: macro[macrocount++].m_funct = funct;
334: }
1.3 millert 335: #endif /* !NO_MACRO */
1.16 ! db 336: return ((*funct)(FFNEGARG, nn));
1.1 deraadt 337: }
338:
339: /*
340: * Insert a character. While defining a macro, create a "LINE" containing
341: * all inserted characters.
342: */
1.2 millert 343: int
1.14 vincent 344: selfinsert(int f, int n)
1.1 deraadt 345: {
346: #ifndef NO_MACRO
1.3 millert 347: LINE *lp;
348: #endif /* !NO_MACRO */
349: int c;
350: int count;
1.1 deraadt 351:
1.2 millert 352: if (n < 0)
1.16 ! db 353: return (FALSE);
1.2 millert 354: if (n == 0)
1.16 ! db 355: return (TRUE);
1.2 millert 356: c = key.k_chars[key.k_count - 1];
1.1 deraadt 357: #ifndef NO_MACRO
1.2 millert 358: if (macrodef && macrocount < MAXMACRO) {
359: if (f & FFARG)
360: macrocount -= 2;
1.3 millert 361:
362: /* last command was insert -- tack on the end */
363: if (lastflag & CFINS) {
1.2 millert 364: macrocount--;
1.11 vincent 365: /* Ensure the line can handle the new characters */
1.2 millert 366: if (maclcur->l_size < maclcur->l_used + n) {
1.11 vincent 367: if (lrealloc(maclcur, maclcur->l_used + n) ==
368: FALSE)
1.16 ! db 369: return (FALSE);
1.2 millert 370: }
1.11 vincent 371: maclcur->l_used += n;
372: /* Copy in the new data */
373: for (count = maclcur->l_used - n;
1.13 deraadt 374: count < maclcur->l_used; count++)
1.11 vincent 375: maclcur->l_text[count] = c;
1.2 millert 376: } else {
377: macro[macrocount - 1].m_funct = insert;
1.11 vincent 378: if ((lp = lalloc(n)) == NULL)
1.16 ! db 379: return (FALSE);
1.2 millert 380: lp->l_bp = maclcur;
381: lp->l_fp = maclcur->l_fp;
382: maclcur->l_fp = lp;
383: maclcur = lp;
384: for (count = 0; count < n; count++)
385: lp->l_text[count] = c;
386: }
387: thisflag |= CFINS;
388: }
1.3 millert 389: #endif /* !NO_MACRO */
1.2 millert 390: if (c == '\n') {
391: do {
392: count = lnewline();
393: } while (--n && count == TRUE);
1.16 ! db 394: return (count);
1.2 millert 395: }
1.3 millert 396:
397: /* overwrite mode */
398: if (curbp->b_flag & BFOVERWRITE) {
1.2 millert 399: lchange(WFEDIT);
400: while (curwp->w_doto < llength(curwp->w_dotp) && n--)
401: lputc(curwp->w_dotp, curwp->w_doto++, c);
402: if (n <= 0)
1.16 ! db 403: return (TRUE);
1.2 millert 404: }
1.16 ! db 405: return (linsert(n, c));
1.1 deraadt 406: }
407:
408: /*
1.16 ! db 409: * This could be implemented as a keymap with everything defined as self-insert.
1.1 deraadt 410: */
1.2 millert 411: int
1.14 vincent 412: quote(int f, int n)
1.1 deraadt 413: {
1.3 millert 414: int c;
1.1 deraadt 415:
1.2 millert 416: key.k_count = 1;
417: if ((key.k_chars[0] = getkey(TRUE)) >= '0' && key.k_chars[0] <= '7') {
418: key.k_chars[0] -= '0';
419: if ((c = getkey(TRUE)) >= '0' && c <= '7') {
420: key.k_chars[0] <<= 3;
421: key.k_chars[0] += c - '0';
422: if ((c = getkey(TRUE)) >= '0' && c <= '7') {
423: key.k_chars[0] <<= 3;
424: key.k_chars[0] += c - '0';
425: } else
426: ungetkey(c);
427: } else
428: ungetkey(c);
429: }
1.16 ! db 430: return (selfinsert(f, n));
1.1 deraadt 431: }