Annotation of src/usr.bin/mg/extend.c, Revision 1.1
1.1 ! deraadt 1: /*
! 2: * Extended (M-X) commands, rebinding, and
! 3: * startup file processing.
! 4: */
! 5: #include "def.h"
! 6: #include "kbd.h"
! 7:
! 8: #ifndef NO_MACRO
! 9: #include "macro.h"
! 10: #endif
! 11:
! 12: #ifdef FKEYS
! 13: #include "key.h"
! 14: #ifndef NO_STARTUP
! 15: #ifndef BINDKEY
! 16: #define BINDKEY /* bindkey is used by FKEYS startup code */
! 17: #endif
! 18: #endif
! 19: #endif
! 20:
! 21: extern char *strncpy();
! 22: extern int rescan();
! 23:
! 24: /* insert a string, mainly for use from macros (created by selfinsert) */
! 25: /*ARGSUSED*/
! 26: insert(f, n)
! 27: int f, n;
! 28: {
! 29: register char *cp;
! 30: char buf[128];
! 31: #ifndef NO_MACRO
! 32: register int count;
! 33: int c;
! 34:
! 35: if(inmacro) {
! 36: while(--n >= 0) {
! 37: for(count = 0; count < maclcur->l_used; count++) {
! 38: if((((c=maclcur->l_text[count]) == '\n') ? lnewline()
! 39: : linsert(1, c)) != TRUE) return FALSE;
! 40: }
! 41: }
! 42: maclcur = maclcur->l_fp;
! 43: return TRUE;
! 44: }
! 45: if(n==1) thisflag |= CFINS; /* CFINS means selfinsert can tack on end */
! 46: #endif
! 47: if(eread("Insert: ", buf, sizeof(buf), EFNEW) == FALSE) return FALSE;
! 48: while(--n >= 0) {
! 49: cp = buf;
! 50: while(*cp) {
! 51: if(((*cp == '\n') ? lnewline() : linsert(1, *cp)) != TRUE)
! 52: return FALSE;
! 53: cp++;
! 54: }
! 55: }
! 56: return TRUE;
! 57: }
! 58:
! 59: /*
! 60: * Bind a key to a function. Cases range from the trivial (replacing an
! 61: * existing binding) to the extremly complex (creating a new prefix in a
! 62: * map_element that already has one, so the map_element must be split,
! 63: * but the keymap doesn't have enough room for another map_element, so
! 64: * the keymap is reallocated). No attempt is made to reclaim space no
! 65: * longer used, if this is a problem flags must be added to indicate
! 66: * malloced verses static storage in both keymaps and map_elements.
! 67: * Structure assignments would come in real handy, but K&R based compilers
! 68: * don't have them. Care is taken so running out of memory will leave
! 69: * the keymap in a usable state.
! 70: */
! 71: static int remap(curmap, c, funct, pref_map)
! 72: register KEYMAP *curmap;/* pointer to the map being changed */
! 73: int c; /* character being changed */
! 74: PF funct; /* function being changed to */
! 75: KEYMAP *pref_map; /* if funct==prefix, map to bind to or NULL for new */
! 76: /* extern MAP_ELEMENT *ele; must be set before calling */
! 77: {
! 78: register int i;
! 79: int n1, n2, nold;
! 80: KEYMAP *mp;
! 81: PF *pfp;
! 82: MAP_ELEMENT *mep;
! 83: static KEYMAP *realocmap();
! 84:
! 85: if(ele >= &curmap->map_element[curmap->map_num] || c < ele->k_base) {
! 86: if(ele > &curmap->map_element[0] && (funct!=prefix ||
! 87: (ele-1)->k_prefmap==NULL)) {
! 88: n1 = c - (ele-1)->k_num;
! 89: } else n1 = HUGE;
! 90: if(ele < &curmap->map_element[curmap->map_num] && (funct!=prefix ||
! 91: ele->k_prefmap==NULL)) {
! 92: n2 = ele->k_base - c;
! 93: } else n2 = HUGE;
! 94: if(n1 <= MAPELEDEF && n1 <= n2) {
! 95: ele--;
! 96: if((pfp = (PF *)malloc((unsigned)(c - ele->k_base+1)
! 97: * sizeof(PF))) == NULL) {
! 98: ewprintf("Out of memory");
! 99: return FALSE;
! 100: }
! 101: nold = ele->k_num - ele->k_base + 1;
! 102: for(i=0; i < nold; i++)
! 103: pfp[i] = ele->k_funcp[i];
! 104: while(--n1) pfp[i++] = curmap->map_default;
! 105: pfp[i] = funct;
! 106: ele->k_num = c;
! 107: ele->k_funcp = pfp;
! 108: } else if(n2 <= MAPELEDEF) {
! 109: if((pfp = (PF *)malloc((unsigned)(ele->k_num - c + 1)
! 110: * sizeof(PF))) == NULL) {
! 111: ewprintf("Out of memory");
! 112: return FALSE;
! 113: }
! 114: nold = ele->k_num - ele->k_base + 1;
! 115: for(i=0; i < nold; i++)
! 116: pfp[i+n2] = ele->k_funcp[i];
! 117: while(--n2) pfp[n2] = curmap->map_default;
! 118: pfp[0] = funct;
! 119: ele->k_base = c;
! 120: ele->k_funcp = pfp;
! 121: } else {
! 122: if(curmap->map_num >= curmap->map_max &&
! 123: (curmap = realocmap(curmap)) == NULL) return FALSE;
! 124: if((pfp = (PF *)malloc(sizeof(PF))) == NULL) {
! 125: ewprintf("Out of memory");
! 126: return FALSE;
! 127: }
! 128: pfp[0] = funct;
! 129: for(mep = &curmap->map_element[curmap->map_num]; mep > ele; mep--) {
! 130: mep->k_base = (mep-1)->k_base;
! 131: mep->k_num = (mep-1)->k_num;
! 132: mep->k_funcp = (mep-1)->k_funcp;
! 133: mep->k_prefmap = (mep-1)->k_prefmap;
! 134: }
! 135: ele->k_base = c;
! 136: ele->k_num = c;
! 137: ele->k_funcp = pfp;
! 138: ele->k_prefmap = NULL;
! 139: curmap->map_num++;
! 140: }
! 141: if(funct == prefix) {
! 142: if(pref_map != NULL) {
! 143: ele->k_prefmap = pref_map;
! 144: } else {
! 145: if((mp = (KEYMAP *)malloc(sizeof(KEYMAP) +
! 146: (MAPINIT-1)*sizeof(MAP_ELEMENT))) == NULL) {
! 147: ewprintf("Out of memory");
! 148: ele->k_funcp[c - ele->k_base] = curmap->map_default;
! 149: return FALSE;
! 150: }
! 151: mp->map_num = 0;
! 152: mp->map_max = MAPINIT;
! 153: mp->map_default = rescan;
! 154: ele->k_prefmap = mp;
! 155: }
! 156: }
! 157: } else {
! 158: n1 = c - ele->k_base;
! 159: if(ele->k_funcp[n1] == funct && (funct!=prefix || pref_map==NULL ||
! 160: pref_map==ele->k_prefmap))
! 161: return TRUE; /* no change */
! 162: if(funct!=prefix || ele->k_prefmap==NULL) {
! 163: if(ele->k_funcp[n1] == prefix)
! 164: ele->k_prefmap = (KEYMAP *)NULL;
! 165: ele->k_funcp[n1] = funct; /* easy case */
! 166: if(funct==prefix) {
! 167: if(pref_map!=NULL)
! 168: ele->k_prefmap = pref_map;
! 169: else {
! 170: if((mp = (KEYMAP *)malloc(sizeof(KEYMAP) +
! 171: (MAPINIT-1)*sizeof(MAP_ELEMENT))) == NULL) {
! 172: ewprintf("Out of memory");
! 173: ele->k_funcp[c - ele->k_base] = curmap->map_default;
! 174: return FALSE;
! 175: }
! 176: mp->map_num = 0;
! 177: mp->map_max = MAPINIT;
! 178: mp->map_default = rescan;
! 179: ele->k_prefmap = mp;
! 180: }
! 181: }
! 182: } else {
! 183: /* this case is the splits */
! 184: /* determine which side of the break c goes on */
! 185: /* 0 = after break; 1 = before break */
! 186: n2 = 1;
! 187: for(i=0; n2 && i < n1; i++)
! 188: n2 &= ele->k_funcp[i] != prefix;
! 189: if(curmap->map_num >= curmap->map_max &&
! 190: (curmap = realocmap(curmap)) == NULL) return FALSE;
! 191: if((pfp = (PF *)malloc((unsigned)(ele->k_num - c + !n2)
! 192: * sizeof(PF))) == NULL) {
! 193: ewprintf("Out of memory");
! 194: return FALSE;
! 195: }
! 196: ele->k_funcp[n1] = prefix;
! 197: for(i=n1+n2; i <= ele->k_num - ele->k_base; i++)
! 198: pfp[i-n1-n2] = ele->k_funcp[i];
! 199: for(mep = &curmap->map_element[curmap->map_num]; mep > ele; mep--) {
! 200: mep->k_base = (mep-1)->k_base;
! 201: mep->k_num = (mep-1)->k_num;
! 202: mep->k_funcp = (mep-1)->k_funcp;
! 203: mep->k_prefmap = (mep-1)->k_prefmap;
! 204: }
! 205: ele->k_num = c - !n2;
! 206: (ele+1)->k_base = c + n2;
! 207: (ele+1)->k_funcp = pfp;
! 208: ele += !n2;
! 209: ele->k_prefmap = NULL;
! 210: curmap->map_num++;
! 211: if(pref_map == NULL) {
! 212: if((mp = (KEYMAP *)malloc(sizeof(KEYMAP) +
! 213: (MAPINIT-1)*sizeof(MAP_ELEMENT))) == NULL) {
! 214: ewprintf("Out of memory");
! 215: ele->k_funcp[c - ele->k_base] = curmap->map_default;
! 216: return FALSE;
! 217: }
! 218: mp->map_num = 0;
! 219: mp->map_max = MAPINIT;
! 220: mp->map_default = rescan;
! 221: ele->k_prefmap = mp;
! 222: } else ele->k_prefmap = pref_map;
! 223: }
! 224: }
! 225: return TRUE;
! 226: }
! 227:
! 228: /* reallocate a keymap, used above */
! 229: static KEYMAP *realocmap(curmap)
! 230: register KEYMAP *curmap;
! 231: {
! 232: register KEYMAP *mp;
! 233: register int i;
! 234: static VOID fixmap();
! 235: extern int nmaps;
! 236:
! 237: if((mp = (KEYMAP *)malloc((unsigned)(sizeof(KEYMAP)+
! 238: (curmap->map_max+(MAPGROW-1))*sizeof(MAP_ELEMENT)))) == NULL) {
! 239: ewprintf("Out of memory");
! 240: return NULL;
! 241: }
! 242: mp->map_num = curmap->map_num;
! 243: mp->map_max = curmap->map_max + MAPGROW;
! 244: mp->map_default = curmap->map_default;
! 245: for(i=curmap->map_num; i--; ) {
! 246: mp->map_element[i].k_base = curmap->map_element[i].k_base;
! 247: mp->map_element[i].k_num = curmap->map_element[i].k_num;
! 248: mp->map_element[i].k_funcp = curmap->map_element[i].k_funcp;
! 249: mp->map_element[i].k_prefmap = curmap->map_element[i].k_prefmap;
! 250: }
! 251: for(i=nmaps; i--; ) {
! 252: if(map_table[i].p_map == curmap) map_table[i].p_map = mp;
! 253: else fixmap(curmap, mp, map_table[i].p_map);
! 254: }
! 255: ele = &mp->map_element[ele - &curmap->map_element[0]];
! 256: return mp;
! 257: }
! 258:
! 259: /* fix references to a reallocated keymap (recursive) */
! 260: static VOID fixmap(curmap, mp, mt)
! 261: register KEYMAP *mt;
! 262: register KEYMAP *curmap;
! 263: KEYMAP *mp;
! 264: {
! 265: register int i;
! 266:
! 267: for(i = mt->map_num; i--; ) {
! 268: if(mt->map_element[i].k_prefmap != NULL) {
! 269: if(mt->map_element[i].k_prefmap == curmap)
! 270: mt->map_element[i].k_prefmap = mp;
! 271: else fixmap(curmap, mp, mt->map_element[i].k_prefmap);
! 272: }
! 273: }
! 274: }
! 275:
! 276: /*
! 277: * do the input for local-set-key, global-set-key and define-key
! 278: * then call remap to do the work.
! 279: */
! 280:
! 281: static int dobind(curmap, p, unbind)
! 282: register KEYMAP *curmap;
! 283: char *p;
! 284: int unbind;
! 285: {
! 286: PF funct;
! 287: char prompt[80];
! 288: char *pep;
! 289: int c;
! 290: int s;
! 291: KEYMAP *pref_map = NULL;
! 292:
! 293: #ifndef NO_MACRO
! 294: if(macrodef) {
! 295: /* keystrokes arn't collected. Not hard, but pretty useless */
! 296: /* would not work for function keys in any case */
! 297: ewprintf("Can't rebind key in macro");
! 298: return FALSE;
! 299: }
! 300: #ifndef NO_STARTUP
! 301: if(inmacro) {
! 302: for(s=0; s < maclcur->l_used - 1; s++) {
! 303: if(doscan(curmap, c=CHARMASK(maclcur->l_text[s])) != prefix) {
! 304: if(remap(curmap, c, prefix, (KEYMAP *)NULL) != TRUE) {
! 305: return FALSE;
! 306: }
! 307: }
! 308: curmap = ele->k_prefmap;
! 309: }
! 310: (VOID) doscan(curmap, c=maclcur->l_text[s]);
! 311: maclcur = maclcur->l_fp;
! 312: } else {
! 313: #endif
! 314: #endif
! 315: (VOID) strcpy(prompt, p);
! 316: pep = prompt + strlen(prompt);
! 317: for(;;) {
! 318: ewprintf("%s", prompt);
! 319: pep[-1] = ' ';
! 320: pep = keyname(pep, c = getkey(FALSE));
! 321: if(doscan(curmap,c) != prefix) break;
! 322: *pep++ = '-';
! 323: *pep = '\0';
! 324: curmap = ele->k_prefmap;
! 325: }
! 326: #ifndef NO_STARTUP
! 327: }
! 328: #endif
! 329: if(unbind) funct = rescan;
! 330: else {
! 331: if ((s=eread("%s to command: ", prompt, 80, EFFUNC|EFNEW, prompt))
! 332: != TRUE) return s;
! 333: if (((funct = name_function(prompt)) == prefix) ?
! 334: (pref_map = name_map(prompt)) == NULL : funct==NULL) {
! 335: ewprintf("[No match]");
! 336: return FALSE;
! 337: }
! 338: }
! 339: return remap(curmap, c, funct, pref_map);
! 340: }
! 341:
! 342: /*
! 343: * bindkey: bind key sequence to a function in
! 344: * the specified map. Used by excline so it can bind function keys.
! 345: * To close to release to change calling sequence, should just pass
! 346: * KEYMAP *curmap rather than KEYMAP **mapp.
! 347: */
! 348: #ifdef BINDKEY
! 349: bindkey(mapp, fname, keys, kcount)
! 350: KEYMAP **mapp;
! 351: char *fname;
! 352: KCHAR *keys;
! 353: int kcount;
! 354: {
! 355: KEYMAP *curmap = *mapp;
! 356: PF funct;
! 357: int c;
! 358: KEYMAP *pref_map = NULL;
! 359:
! 360: if(fname == NULL) funct = rescan;
! 361: else if (((funct = name_function(fname)) == prefix) ?
! 362: (pref_map = name_map(fname)) == NULL : funct==NULL) {
! 363: ewprintf("[No match: %s]", fname);
! 364: return FALSE;
! 365: }
! 366: while(--kcount) {
! 367: if(doscan(curmap, c = *keys++) != prefix) {
! 368: if(remap(curmap, c, prefix, (KEYMAP *)NULL) != TRUE)
! 369: return FALSE;
! 370: }
! 371: curmap = ele->k_prefmap;
! 372: }
! 373: (VOID) doscan(curmap, c = *keys);
! 374: return remap(curmap, c, funct, pref_map);
! 375: }
! 376: #endif
! 377:
! 378: /*
! 379: * This function modifies the fundamental keyboard map.
! 380: */
! 381: /*ARGSUSED*/
! 382: bindtokey(f, n)
! 383: {
! 384: return dobind(map_table[0].p_map, "Global set key: ", FALSE);
! 385: }
! 386:
! 387: /*
! 388: * This function modifies the current mode's keyboard map.
! 389: */
! 390: /*ARGSUSED*/
! 391: localbind(f, n)
! 392: {
! 393: return dobind(curbp->b_modes[curbp->b_nmodes]->p_map, "Local set key: ",
! 394: FALSE);
! 395: }
! 396:
! 397: /*
! 398: * This function redefines a key in any keymap.
! 399: */
! 400: /*ARGSUSED*/
! 401: define_key(f, n)
! 402: {
! 403: static char buf[48] = "Define key map: ";
! 404: MAPS *mp;
! 405: char *strncat();
! 406:
! 407: buf[16] = '\0';
! 408: if(eread(buf, &buf[16], 48 - 16, EFNEW) != TRUE) return FALSE;
! 409: if((mp = name_mode(&buf[16])) == NULL) {
! 410: ewprintf("Unknown map %s", &buf[16]);
! 411: return FALSE;
! 412: }
! 413: (VOID) strncat(&buf[16], " key: ", 48-16-1);
! 414: return dobind(mp->p_map, buf, FALSE);
! 415: }
! 416:
! 417: unbindtokey(f, n)
! 418: int f, n;
! 419: {
! 420: return dobind(map_table[0].p_map, "Global unset key: ", TRUE);
! 421: }
! 422:
! 423: localunbind(f, n)
! 424: int f, n;
! 425: {
! 426: return dobind(curbp->b_modes[curbp->b_nmodes]->p_map, "Local unset key: ",
! 427: TRUE);
! 428: }
! 429:
! 430: /*
! 431: * Extended command. Call the message line
! 432: * routine to read in the command name and apply autocompletion
! 433: * to it. When it comes back, look the name up in the symbol table
! 434: * and run the command if it is found.
! 435: * Print an error if there is anything wrong.
! 436: */
! 437: extend(f, n)
! 438: {
! 439: PF funct;
! 440: int s;
! 441: char xname[NXNAME];
! 442:
! 443: if(!(f & FFARG)) s = eread("M-x ", xname, NXNAME, EFNEW|EFFUNC);
! 444: else s = eread("%d M-x ", xname, NXNAME, EFNEW|EFFUNC, n);
! 445: if(s != TRUE) return s;
! 446: if((funct = name_function(xname)) != NULL) {
! 447: #ifndef NO_MACRO
! 448: if(macrodef) {
! 449: LINE *lp = maclcur;
! 450: macro[macrocount-1].m_funct = funct;
! 451: maclcur = lp->l_bp;
! 452: maclcur->l_fp = lp->l_fp;
! 453: free((char *)lp);
! 454: }
! 455: #endif
! 456: return (*funct)(f, n);
! 457: }
! 458: ewprintf("[No match]");
! 459: return FALSE;
! 460: }
! 461:
! 462: #ifndef NO_STARTUP
! 463: /*
! 464: * Define the commands needed to do startup-file processing.
! 465: * This code is mostly a kludge just so we can get startup-file processing.
! 466: *
! 467: * If you're serious about having this code, you should rewrite it.
! 468: * To wit:
! 469: * It has lots of funny things in it to make the startup-file look
! 470: * like a GNU startup file; mostly dealing with parens and semicolons.
! 471: * This should all vanish.
! 472: *
! 473: * We define eval-expression because it's easy. It can make
! 474: * *-set-key or define-key set an arbitrary key sequence, so it isn't
! 475: * useless.
! 476: */
! 477:
! 478: /*
! 479: * evalexpr - get one line from the user, and run it.
! 480: */
! 481: /*ARGSUSED*/
! 482: evalexpr(f, n)
! 483: {
! 484: int s;
! 485: char exbuf[128];
! 486:
! 487: if ((s = ereply("Eval: ", exbuf, 128)) != TRUE)
! 488: return s;
! 489: return excline(exbuf);
! 490: }
! 491: /*
! 492: * evalbuffer - evaluate the current buffer as line commands. Useful
! 493: * for testing startup files.
! 494: */
! 495: /*ARGSUSED*/
! 496: evalbuffer(f, n)
! 497: {
! 498: register LINE *lp;
! 499: register BUFFER *bp = curbp;
! 500: register int s;
! 501: static char excbuf[128];
! 502:
! 503: for (lp = lforw(bp->b_linep); lp != bp->b_linep; lp = lforw(lp)) {
! 504: if (llength(lp) >= 128) return FALSE;
! 505: (VOID) strncpy(excbuf, ltext(lp), llength(lp));
! 506: excbuf[llength(lp)] = '\0'; /* make sure it's terminated */
! 507: if ((s = excline(excbuf)) != TRUE) return s;
! 508: }
! 509: return TRUE;
! 510: }
! 511: /*
! 512: * evalfile - go get a file and evaluate it as line commands. You can
! 513: * go get your own startup file if need be.
! 514: */
! 515: /*ARGSUSED*/
! 516: evalfile(f, n)
! 517: {
! 518: register int s;
! 519: char fname[NFILEN];
! 520:
! 521: if ((s = ereply("Load file: ", fname, NFILEN)) != TRUE)
! 522: return s;
! 523: return load(fname);
! 524: }
! 525:
! 526: /*
! 527: * load - go load the file name we got passed.
! 528: */
! 529: load(fname) char *fname; {
! 530: int s = TRUE;
! 531: int nbytes;
! 532: char excbuf[128];
! 533:
! 534: if ((fname = adjustname(fname)) == NULL)
! 535: return FALSE; /* just to be careful */
! 536:
! 537: if (ffropen(fname, (BUFFER *) NULL) != FIOSUC) return FALSE;
! 538: while ((s = ffgetline(excbuf, sizeof(excbuf)-1, &nbytes)) == FIOSUC) {
! 539: excbuf[nbytes] = '\0';
! 540: if (excline(excbuf) != TRUE) {
! 541: s = FIOERR;
! 542: ewprintf("Error loading file %s", fname);
! 543: break;
! 544: }
! 545: }
! 546: (VOID) ffclose((BUFFER *) NULL);
! 547: excbuf[nbytes] = '\0';
! 548: if(s!=FIOEOF || (nbytes && excline(excbuf)!=TRUE))
! 549: return FALSE;
! 550: return TRUE;
! 551: }
! 552:
! 553: /*
! 554: * excline - run a line from a load file or eval-expression.
! 555: * if FKEYS is defined, duplicate functionallity of dobind so function
! 556: * key values don't have to fit in type char.
! 557: */
! 558: excline(line)
! 559: register char *line;
! 560: {
! 561: register char *funcp, *argp = NULL;
! 562: register int c;
! 563: int status;
! 564: int f, n;
! 565: LINE *lp, *np;
! 566: PF fp;
! 567: #ifdef FKEYS
! 568: int bind;
! 569: KEYMAP *curmap;
! 570: MAPS *mp;
! 571: #define BINDARG 0 /* this arg is key to bind (local/global set key) */
! 572: #define BINDNO 1 /* not binding or non-quoted BINDARG */
! 573: #define BINDNEXT 2 /* next arg " (define-key) */
! 574: #define BINDDO 3 /* already found key to bind */
! 575: #define BINDEXT 1 /* space for trailing \0 */
! 576: #else
! 577: #define BINDEXT 0
! 578: #endif
! 579: PF name_function();
! 580: LINE *lalloc();
! 581: static char *skipwhite(), *parsetoken();
! 582:
! 583: if(macrodef || inmacro) {
! 584: ewprintf("Not now!");
! 585: return FALSE;
! 586: }
! 587:
! 588: f = 0;
! 589: n = 1;
! 590: funcp = skipwhite(line);
! 591: if (*funcp == '\0') return TRUE; /* No error on blank lines */
! 592: line = parsetoken(funcp);
! 593: if (*line != '\0') {
! 594: *line++ = '\0';
! 595: line = skipwhite(line);
! 596: if ((*line >= '0' && *line <= '9') || *line == '-') {
! 597: argp = line;
! 598: line = parsetoken(line);
! 599: }
! 600: }
! 601:
! 602: if (argp != NULL) {
! 603: f = FFARG;
! 604: n = atoi(argp);
! 605: }
! 606: if((fp = name_function(funcp)) == NULL) {
! 607: ewprintf("Unknown function: %s", funcp);
! 608: return FALSE;
! 609: }
! 610: #ifdef FKEYS
! 611: if(fp == bindtokey || fp == unbindtokey) {
! 612: bind = BINDARG;
! 613: curmap = map_table[0].p_map;
! 614: } else if(fp == localbind || fp == localunbind) {
! 615: bind = BINDARG;
! 616: curmap = curbp->b_modes[curbp->b_nmodes]->p_map;
! 617: } else if(fp == define_key) bind = BINDNEXT;
! 618: else bind = BINDNO;
! 619: #endif
! 620: /* Pack away all the args now... */
! 621: if((np = lalloc(0))==FALSE) return FALSE;
! 622: np->l_fp = np->l_bp = maclcur = np;
! 623: while (*line != '\0') {
! 624: argp = skipwhite(line);
! 625: if (*argp == '\0') break;
! 626: line = parsetoken(argp);
! 627: if (*argp != '"') {
! 628: if (*argp == '\'') ++argp;
! 629: if((lp = lalloc((int)(line-argp)+BINDEXT))==NULL) {
! 630: status = FALSE;
! 631: goto cleanup;
! 632: }
! 633: bcopy(argp, ltext(lp), (int)(line-argp));
! 634: #ifdef FKEYS
! 635: lp->l_used--; /* don't count BINDEXT! */
! 636: if(bind == BINDARG) bind = BINDNO;
! 637: #endif
! 638: } else { /* Quoted strings special */
! 639: ++argp;
! 640: #ifdef FKEYS
! 641: if(bind != BINDARG) {
! 642: #endif
! 643: if((lp = lalloc((int)(line-argp)+BINDEXT))==NULL) {
! 644: status = FALSE;
! 645: goto cleanup;
! 646: }
! 647: lp->l_used = 0;
! 648: #ifdef FKEYS
! 649: } else {
! 650: key.k_count = 0;
! 651: }
! 652: #endif
! 653: while (*argp != '"' && *argp != '\0') {
! 654: if (*argp != '\\') c = *argp++;
! 655: else {
! 656: switch(*++argp) {
! 657: case 't': case 'T':
! 658: c = CCHR('I');
! 659: break;
! 660: case 'n': case 'N':
! 661: c = CCHR('J');
! 662: break;
! 663: case 'r': case 'R':
! 664: c = CCHR('M');
! 665: break;
! 666: case 'e': case 'E':
! 667: c = CCHR('[');
! 668: break;
! 669: case '^':
! 670: /* split into two statements due to bug in OSK cpp */
! 671: c = CHARMASK(*++argp);
! 672: c = ISLOWER(c) ?
! 673: CCHR(TOUPPER(c)) : CCHR(c);
! 674: break;
! 675: case '0': case '1': case '2': case '3':
! 676: case '4': case '5': case '6': case '7':
! 677: c = *argp - '0';
! 678: if(argp[1] <= '7' && argp[1] >= '0') {
! 679: c <<= 3;
! 680: c += *++argp - '0';
! 681: if(argp[1] <= '7' && argp[1] >= '0') {
! 682: c <<= 3;
! 683: c += *++argp - '0';
! 684: }
! 685: }
! 686: break;
! 687: #ifdef FKEYS
! 688: case 'f': case 'F':
! 689: c = *++argp - '0';
! 690: if(ISDIGIT(argp[1])) {
! 691: c *= 10;
! 692: c += *++argp - '0';
! 693: }
! 694: c += KFIRST;
! 695: break;
! 696: #endif
! 697: default:
! 698: c = CHARMASK(*argp);
! 699: break;
! 700: }
! 701: argp++;
! 702: }
! 703: #ifdef FKEYS
! 704: if(bind == BINDARG)
! 705: key.k_chars[key.k_count++] = c;
! 706: else
! 707: #endif
! 708: lp->l_text[lp->l_used++] = c;
! 709: }
! 710: if(*line) line++;
! 711: }
! 712: #ifdef FKEYS
! 713: switch(bind) {
! 714: case BINDARG:
! 715: bind = BINDDO;
! 716: break;
! 717: case BINDNEXT:
! 718: lp->l_text[lp->l_used] = '\0';
! 719: if((mp = name_mode(lp->l_text)) == NULL) {
! 720: ewprintf("No such mode: %s", lp->l_text);
! 721: status = FALSE;
! 722: free((char *)lp);
! 723: goto cleanup;
! 724: }
! 725: curmap = mp->p_map;
! 726: free((char *)lp);
! 727: bind = BINDARG;
! 728: break;
! 729: default:
! 730: #endif
! 731: lp->l_fp = np->l_fp;
! 732: lp->l_bp = np;
! 733: np->l_fp = lp;
! 734: np = lp;
! 735: #ifdef FKEYS
! 736: }
! 737: #endif
! 738: }
! 739: #ifdef FKEYS
! 740: switch(bind) {
! 741: default:
! 742: ewprintf("Bad args to set key");
! 743: status = FALSE;
! 744: break;
! 745: case BINDDO:
! 746: if(fp != unbindtokey && fp != localunbind) {
! 747: lp->l_text[lp->l_used] = '\0';
! 748: status = bindkey(&curmap, lp->l_text, key.k_chars, key.k_count);
! 749: } else status = bindkey(&curmap, (char *)NULL, key.k_chars, key.k_count);
! 750: break;
! 751: case BINDNO:
! 752: #endif
! 753: inmacro = TRUE;
! 754: maclcur = maclcur->l_fp;
! 755: status = (*fp)(f, n);
! 756: inmacro = FALSE;
! 757: #ifdef FKEYS
! 758: }
! 759: #endif
! 760: cleanup:
! 761: lp = maclcur->l_fp;
! 762: while(lp!=maclcur) {
! 763: np = lp->l_fp;
! 764: free((char *)lp);
! 765: lp = np;
! 766: }
! 767: free((char *)lp);
! 768: return status;
! 769: }
! 770:
! 771: /*
! 772: * a pair of utility functions for the above
! 773: */
! 774: static char *
! 775: skipwhite(s)
! 776: register char *s;
! 777: {
! 778: while(*s == ' ' || *s == '\t' || *s == ')' || *s == '(') s++;
! 779: if (*s == ';') *s = '\0' ;
! 780: return s;
! 781: }
! 782:
! 783: static char *
! 784: parsetoken(s)
! 785: register char *s;
! 786: {
! 787: if (*s != '"') {
! 788: while(*s && *s!=' ' && *s!='\t' && *s!=')' && *s!='(') s++;
! 789: if(*s==';') *s='\0';
! 790: } else
! 791: do { /* Strings get special treatment */
! 792: /* Beware: You can \ out the end of the string! */
! 793: if (*s == '\\') ++s;
! 794: } while (*++s != '"' && *s != '\0');
! 795: return s;
! 796: }
! 797: #endif