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