|
|
1.1 ! root 1: /*************************************************************************** ! 2: * This program is Copyright (C) 1986, 1987, 1988 by Jonathan Payne. JOVE * ! 3: * is provided to you without charge, and with no warranty. You may give * ! 4: * away copies of JOVE, including sources, provided that this notice is * ! 5: * included in all the files. * ! 6: ***************************************************************************/ ! 7: ! 8: #include "jove.h" ! 9: #include "io.h" ! 10: #include "termcap.h" ! 11: #include "ctype.h" ! 12: #ifdef JOB_CONTROL ! 13: # include <signal.h> ! 14: #endif ! 15: ! 16: #ifdef MAC ! 17: # include "mac.h" ! 18: #else ! 19: # include <varargs.h> ! 20: #endif ! 21: ! 22: #ifdef MSDOS ! 23: #include <process.h> ! 24: #endif ! 25: ! 26: #ifdef MAC ! 27: # undef private ! 28: # define private ! 29: #endif ! 30: ! 31: #ifdef LINT_ARGS ! 32: private void ! 33: fb_aux(data_obj *, data_obj **, char *, char *), ! 34: find_binds(data_obj *, char *), ! 35: vpr_aux(struct variable *, char *); ! 36: #else ! 37: private void ! 38: fb_aux(), ! 39: find_binds(), ! 40: vpr_aux(); ! 41: #endif /* LINT_ARGS */ ! 42: ! 43: #ifdef MAC ! 44: # undef private ! 45: # define private static ! 46: #endif ! 47: ! 48: ! 49: int InJoverc = 0; ! 50: ! 51: extern int getch(), ! 52: getchar(); ! 53: ! 54: /* Auto execute code */ ! 55: ! 56: #define NEXECS 20 ! 57: ! 58: private struct { ! 59: char *a_pattern; ! 60: data_obj *a_cmd; ! 61: } AutoExecs[NEXECS] = {0}; ! 62: ! 63: private int ExecIndex = 0; ! 64: ! 65: /* Command auto-execute. */ ! 66: ! 67: void ! 68: CAutoExec() ! 69: { ! 70: DefAutoExec(findcom); ! 71: } ! 72: ! 73: /* Macro auto-execute. */ ! 74: ! 75: void ! 76: MAutoExec() ! 77: { ! 78: DefAutoExec(findmac); ! 79: } ! 80: ! 81: /* VARARGS0 */ ! 82: ! 83: void ! 84: DefAutoExec(proc) ! 85: #ifdef LINT_ARGS ! 86: data_obj *(*proc)(char *); ! 87: #else ! 88: data_obj *(*proc)(); ! 89: #endif ! 90: { ! 91: data_obj *d; ! 92: char *pattern; ! 93: int i; ! 94: ! 95: if (ExecIndex >= NEXECS) ! 96: complain("Too many auto-executes, max %d.", NEXECS); ! 97: if ((d = (*proc)(ProcFmt)) == 0) ! 98: return; ! 99: pattern = do_ask("\r\n", (int (*)()) 0, (char *) 0, ": %f %s ", d->Name); ! 100: if (pattern != 0) ! 101: for (i = 0; i < ExecIndex; i++) ! 102: if ((AutoExecs[i].a_cmd == d) && ! 103: (strcmp(pattern, AutoExecs[i].a_pattern) == 0)) ! 104: return; /* eliminate duplicates */ ! 105: AutoExecs[ExecIndex].a_pattern = copystr(pattern); ! 106: AutoExecs[ExecIndex].a_cmd = d; ! 107: ExecIndex += 1; ! 108: } ! 109: ! 110: /* DoAutoExec: NEW and OLD are file names, and if NEW and OLD aren't the ! 111: same kind of file (i.e., match the same pattern) or OLD is 0 and it ! 112: matches, OR if the pattern is 0 (none was specified) then, we execute ! 113: the command associated with that kind of file. */ ! 114: ! 115: void ! 116: DoAutoExec(new, old) ! 117: register char *new, ! 118: *old; ! 119: { ! 120: register int i; ! 121: ! 122: set_arg_value(1); ! 123: for (i = 0; i < ExecIndex; i++) ! 124: if ((AutoExecs[i].a_pattern == 0) || ! 125: ((new != 0 && LookingAt(AutoExecs[i].a_pattern, new, 0)) && ! 126: (old == 0 || !LookingAt(AutoExecs[i].a_pattern, old, 0)))) ! 127: ExecCmd(AutoExecs[i].a_cmd); ! 128: } ! 129: ! 130: void ! 131: BindAKey() ! 132: { ! 133: BindSomething(findcom); ! 134: } ! 135: ! 136: void ! 137: BindMac() ! 138: { ! 139: BindSomething(findmac); ! 140: } ! 141: ! 142: extern void EscPrefix(), ! 143: CtlxPrefix(), ! 144: MiscPrefix(); ! 145: ! 146: data_obj ** ! 147: IsPrefix(cp) ! 148: data_obj *cp; ! 149: { ! 150: #ifdef MAC ! 151: void (*proc)(); ! 152: #else ! 153: int (*proc)(); ! 154: #endif ! 155: ! 156: if (cp == 0 || (cp->Type & TYPEMASK) != FUNCTION) ! 157: return 0; ! 158: proc = ((struct cmd *) cp)->c_proc; ! 159: if (proc == EscPrefix) ! 160: return pref1map; ! 161: if (proc == CtlxPrefix) ! 162: return pref2map; ! 163: if (proc == MiscPrefix) ! 164: return miscmap; ! 165: return 0; ! 166: } ! 167: ! 168: void ! 169: UnbindC() ! 170: { ! 171: char *keys; ! 172: data_obj **map = mainmap; ! 173: ! 174: keys = ask((char *) 0, ProcFmt); ! 175: for (;;) { ! 176: if (keys[1] == '\0') ! 177: break; ! 178: if ((map = IsPrefix(map[*keys])) == 0) ! 179: break; ! 180: keys += 1; ! 181: } ! 182: if (keys[1] != 0) ! 183: complain("That's not a legitimate key sequence."); ! 184: map[keys[0]] = 0; ! 185: } ! 186: ! 187: int ! 188: addgetc() ! 189: { ! 190: int c; ! 191: ! 192: if (!InJoverc) { ! 193: Asking = strlen(mesgbuf); ! 194: c = getch(); ! 195: Asking = 0; ! 196: add_mess("%p ", c); ! 197: } else { ! 198: c = getch(); ! 199: if (c == '\n') ! 200: return EOF; /* this isn't part of the sequence */ ! 201: else if (c == '\\') { ! 202: if ((c = getch()) == LF) ! 203: complain("[Premature end of line]"); ! 204: } else if (c == '^') { ! 205: if ((c = getch()) == '?') ! 206: c = RUBOUT; ! 207: else if (isalpha(c) || index("@[\\]^_", c)) ! 208: c = CTL(c); ! 209: else ! 210: complain("[Unknown control character]"); ! 211: } ! 212: } ! 213: return c; ! 214: } ! 215: ! 216: void ! 217: BindWMap(map, lastkey, cmd) ! 218: data_obj **map, ! 219: *cmd; ! 220: { ! 221: data_obj **nextmap; ! 222: int c; ! 223: ! 224: c = addgetc(); ! 225: if (c == EOF) { ! 226: if (lastkey == EOF) ! 227: complain("[Empty key sequence]"); ! 228: complain("[Premature end of key sequence]"); ! 229: } else { ! 230: if (nextmap = IsPrefix(map[c])) ! 231: BindWMap(nextmap, c, cmd); ! 232: else { ! 233: map[c] = cmd; ! 234: #ifdef MAC ! 235: ((struct cmd *) cmd)->c_key = c; /* see about_j() in mac.c */ ! 236: if(map == mainmap) ((struct cmd *) cmd)->c_map = F_MAINMAP; ! 237: else if(map == pref1map) ((struct cmd *) cmd)->c_map = F_PREF1MAP; ! 238: else if(map == pref2map) ((struct cmd *) cmd)->c_map = F_PREF2MAP; ! 239: #endif ! 240: } ! 241: } ! 242: } ! 243: ! 244: /* VARARGS0 */ ! 245: ! 246: void ! 247: BindSomething(proc) ! 248: #ifdef LINT_ARGS ! 249: data_obj *(*proc)(char *); ! 250: #else ! 251: data_obj *(*proc)(); ! 252: #endif ! 253: { ! 254: data_obj *d; ! 255: ! 256: if ((d = (*proc)(ProcFmt)) == 0) ! 257: return; ! 258: s_mess(": %f %s ", d->Name); ! 259: BindWMap(mainmap, EOF, d); ! 260: } ! 261: ! 262: /* Describe key */ ! 263: ! 264: void ! 265: DescWMap(map, key) ! 266: data_obj **map; ! 267: { ! 268: data_obj *cp = map[key], ! 269: **prefp; ! 270: ! 271: if (cp == 0) ! 272: add_mess("is unbound."); ! 273: else if (prefp = IsPrefix(cp)) ! 274: DescWMap(prefp, addgetc()); ! 275: else ! 276: add_mess("is bound to %s.", cp->Name); ! 277: } ! 278: ! 279: void ! 280: KeyDesc() ! 281: { ! 282: s_mess(ProcFmt); ! 283: DescWMap(mainmap, addgetc()); ! 284: } ! 285: ! 286: void ! 287: DescCom() ! 288: { ! 289: data_obj *dp; ! 290: char pattern[100], ! 291: doc_type[40], ! 292: *the_type, ! 293: *file = CmdDb; ! 294: File *fp; ! 295: int is_var; ! 296: ! 297: if (!strcmp(LastCmd->Name, "describe-variable")) { ! 298: dp = (data_obj *) findvar(ProcFmt); ! 299: the_type = "Variable"; ! 300: is_var = YES; ! 301: } else { ! 302: dp = (data_obj *) findcom(ProcFmt); ! 303: the_type = "Command"; ! 304: is_var = NO; ! 305: } ! 306: if (dp == 0) ! 307: return; ! 308: fp = open_file(file, iobuff, F_READ, COMPLAIN, QUIET); ! 309: Placur(ILI, 0); ! 310: flusho(); ! 311: sprintf(pattern, "^:entry \"%s\" \"\\([^\"]*\\)\"", dp->Name); ! 312: TOstart("Help", TRUE); ! 313: for (;;) { ! 314: if (f_gets(fp, genbuf, LBSIZE) == EOF) { ! 315: Typeout("There is no documentation for \"%s\".", dp->Name); ! 316: goto outahere; ! 317: } ! 318: if ((strncmp(genbuf, ":entry", 6) == 0) && ! 319: (LookingAt(pattern, genbuf, 0))) { ! 320: char type[64]; ! 321: ! 322: putmatch(1, type, sizeof type); ! 323: if (strcmp(type, the_type) == 0) ! 324: break; ! 325: } ! 326: } ! 327: /* found it ... let's print it */ ! 328: putmatch(1, doc_type, sizeof doc_type); ! 329: if (is_var == YES) ! 330: Typeout(dp->Name); ! 331: else { ! 332: char binding[128]; ! 333: ! 334: find_binds(dp, binding); ! 335: if (blnkp(binding)) ! 336: Typeout("To invoke %s, type \"ESC X %s<cr>\".", ! 337: dp->Name, ! 338: dp->Name); ! 339: else ! 340: Typeout("Type \"%s\" to invoke %s.", binding, dp->Name); ! 341: } ! 342: Typeout(""); ! 343: while (f_gets(fp, genbuf, LBSIZE) != EOF) ! 344: if (strncmp(genbuf, ":entry", 6) == 0) ! 345: goto outahere; ! 346: else ! 347: Typeout("%s", genbuf); ! 348: outahere: ! 349: f_close(fp); ! 350: TOstop(); ! 351: } ! 352: ! 353: void ! 354: DescBindings() ! 355: { ! 356: extern void Typeout(); ! 357: ! 358: TOstart("Key Bindings", TRUE); ! 359: DescMap(mainmap, NullStr); ! 360: TOstop(); ! 361: } ! 362: ! 363: extern int specialmap; ! 364: ! 365: void ! 366: DescMap(map, pref) ! 367: data_obj **map; ! 368: char *pref; ! 369: { ! 370: int c1, ! 371: c2 = 0, ! 372: numbetween; ! 373: char keydescbuf[40]; ! 374: data_obj **prefp; ! 375: ! 376: #ifdef IBMPC ! 377: specialmap = (map == miscmap); ! 378: #endif ! 379: ! 380: for (c1 = 0; c1 < NCHARS && c2 < NCHARS; c1 = c2 + 1) { ! 381: c2 = c1; ! 382: if (map[c1] == 0) ! 383: continue; ! 384: while (++c2 < NCHARS && map[c1] == map[c2]) ! 385: ; ! 386: c2 -= 1; ! 387: numbetween = c2 - c1; ! 388: if (numbetween == 1) ! 389: sprintf(keydescbuf, "%s {%p,%p}", pref, c1, c2); ! 390: else if (numbetween == 0) ! 391: sprintf(keydescbuf, "%s %p", pref, c1); ! 392: else ! 393: sprintf(keydescbuf, "%s [%p-%p]", pref, c1, c2); ! 394: if ((prefp = IsPrefix(map[c1])) && (prefp != map)) ! 395: DescMap(prefp, keydescbuf); ! 396: else ! 397: Typeout("%-18s%s", keydescbuf, map[c1]->Name); ! 398: } ! 399: } ! 400: ! 401: private void ! 402: find_binds(dp, buf) ! 403: data_obj *dp; ! 404: char *buf; ! 405: { ! 406: char *endp; ! 407: ! 408: buf[0] = '\0'; ! 409: fb_aux(dp, mainmap, (char *) 0, buf); ! 410: endp = buf + strlen(buf) - 2; ! 411: if ((endp > buf) && (strcmp(endp, ", ") == 0)) ! 412: *endp = '\0'; ! 413: } ! 414: ! 415: private void ! 416: fb_aux(cp, map, prefix, buf) ! 417: register data_obj *cp, ! 418: **map; ! 419: char *buf, ! 420: *prefix; ! 421: { ! 422: int c1, ! 423: c2; ! 424: char *bufp = buf + strlen(buf), ! 425: prefbuf[20]; ! 426: data_obj **prefp; ! 427: ! 428: #ifdef IBMPC ! 429: specialmap = (map == miscmap); ! 430: #endif ! 431: ! 432: for (c1 = c2 = 0; c1 < NCHARS && c2 < NCHARS; c1 = c2 + 1) { ! 433: c2 = c1; ! 434: if (map[c1] == cp) { ! 435: while (++c2 < NCHARS && map[c1] == map[c2]) ! 436: ; ! 437: c2 -= 1; ! 438: if (prefix) ! 439: sprintf(bufp, "%s ", prefix); ! 440: bufp += strlen(bufp); ! 441: switch (c2 - c1) { ! 442: case 0: ! 443: sprintf(bufp, "%p, ", c1); ! 444: break; ! 445: ! 446: case 1: ! 447: sprintf(bufp, "{%p,%p}, ", c1, c2); ! 448: break; ! 449: ! 450: default: ! 451: sprintf(bufp, "[%p-%p], ", c1, c2); ! 452: break; ! 453: } ! 454: } ! 455: if ((prefp = IsPrefix(map[c1])) && (prefp != map)) { ! 456: sprintf(prefbuf, "%p", c1); ! 457: fb_aux(cp, prefp, prefbuf, bufp); ! 458: } ! 459: bufp += strlen(bufp); ! 460: } ! 461: } ! 462: ! 463: void ! 464: Apropos() ! 465: { ! 466: register struct cmd *cp; ! 467: register struct macro *m; ! 468: register struct variable *v; ! 469: char *ans; ! 470: int anyfs = NO, ! 471: anyvs = NO, ! 472: anyms = NO; ! 473: char buf[256]; ! 474: ! 475: ans = ask((char *) 0, ": %f (keyword) "); ! 476: TOstart("Help", TRUE); ! 477: for (cp = commands; cp->Name != 0; cp++) ! 478: if (sindex(ans, cp->Name)) { ! 479: if (anyfs == 0) { ! 480: Typeout("Commands"); ! 481: Typeout("--------"); ! 482: } ! 483: find_binds((data_obj *) cp, buf); ! 484: if (buf[0]) ! 485: Typeout(": %-35s(%s)", cp->Name, buf); ! 486: else ! 487: Typeout(": %s", cp->Name); ! 488: anyfs = YES; ! 489: } ! 490: if (anyfs) ! 491: Typeout(NullStr); ! 492: for (v = variables; v->Name != 0; v++) ! 493: if (sindex(ans, v->Name)) { ! 494: if (anyvs == 0) { ! 495: Typeout("Variables"); ! 496: Typeout("---------"); ! 497: } ! 498: anyvs = YES; ! 499: vpr_aux(v, buf); ! 500: Typeout(": set %-26s%s", v->Name, buf); ! 501: } ! 502: if (anyvs) ! 503: Typeout(NullStr); ! 504: for (m = macros; m != 0; m = m->m_nextm) ! 505: if (sindex(ans, m->Name)) { ! 506: if (anyms == 0) { ! 507: Typeout("Macros"); ! 508: Typeout("------"); ! 509: } ! 510: anyms = YES; ! 511: find_binds((data_obj *) m, buf); ! 512: if (buf[0]) ! 513: Typeout(": %-35s(%s)", m->Name, buf); ! 514: else ! 515: Typeout(": %-35s%s", "execute-macro", m->Name); ! 516: } ! 517: TOstop(); ! 518: } ! 519: ! 520: void ! 521: Extend() ! 522: { ! 523: data_obj *d; ! 524: ! 525: if (d = findcom(": ")) ! 526: ExecCmd(d); ! 527: } ! 528: ! 529: /* Read a positive integer from CP. It must be in base BASE, and ! 530: complains if it isn't. If allints is nonzero, all the characters ! 531: in the string must be integers or we return -1; otherwise we stop ! 532: reading at the first nondigit. */ ! 533: ! 534: int ! 535: chr_to_int(cp, base, allints, result) ! 536: register char *cp; ! 537: register int *result; ! 538: { ! 539: register int c; ! 540: int value = 0, ! 541: sign; ! 542: ! 543: if ((c = *cp) == '-') { ! 544: sign = -1; ! 545: cp += 1; ! 546: } else ! 547: sign = 1; ! 548: while (c = *cp++) { ! 549: if (!isdigit(c)) { ! 550: if (allints == YES) ! 551: return INT_BAD; ! 552: break; ! 553: } ! 554: c = c - '0'; ! 555: if (c >= base) ! 556: complain("You must specify in base %d.", base); ! 557: value = value * base + c; ! 558: } ! 559: *result = value * sign; ! 560: return INT_OKAY; ! 561: } ! 562: ! 563: int ! 564: ask_int(prompt, base) ! 565: char *prompt; ! 566: int base; ! 567: { ! 568: char *val = ask((char *) 0, prompt); ! 569: int value; ! 570: ! 571: if (chr_to_int(val, base, YES, &value) == INT_BAD) ! 572: complain("That's not a number!"); ! 573: return value; ! 574: } ! 575: ! 576: private void ! 577: vpr_aux(vp, buf) ! 578: register struct variable *vp; ! 579: char *buf; ! 580: { ! 581: switch (vp->v_flags & V_TYPEMASK) { ! 582: case V_BASE10: ! 583: sprintf(buf, "%d", *(vp->v_value)); ! 584: break; ! 585: ! 586: case V_BASE8: ! 587: sprintf(buf, "%o", *(vp->v_value)); ! 588: break; ! 589: ! 590: case V_BOOL: ! 591: sprintf(buf, (*(vp->v_value)) ? "on" : "off"); ! 592: break; ! 593: ! 594: case V_STRING: ! 595: case V_FILENAME: ! 596: sprintf(buf, "%s", (char *) vp->v_value); ! 597: break; ! 598: ! 599: case V_CHAR: ! 600: sprintf(buf, "%p", *(vp->v_value)); ! 601: break; ! 602: } ! 603: } ! 604: ! 605: void ! 606: PrVar() ! 607: { ! 608: struct variable *vp; ! 609: char prbuf[256]; ! 610: ! 611: if ((vp = (struct variable *) findvar(ProcFmt)) == 0) ! 612: return; ! 613: vpr_aux(vp, prbuf); ! 614: s_mess(": %f %s => %s", vp->Name, prbuf); ! 615: } ! 616: ! 617: void ! 618: SetVar() ! 619: { ! 620: struct variable *vp; ! 621: char *prompt; ! 622: ! 623: if ((vp = (struct variable *) findvar(ProcFmt)) == 0) ! 624: return; ! 625: prompt = sprint(": %f %s ", vp->Name); ! 626: ! 627: switch (vp->v_flags & V_TYPEMASK) { ! 628: case V_BASE10: ! 629: case V_BASE8: ! 630: { ! 631: int value; ! 632: ! 633: value = ask_int(prompt, ((vp->v_flags & V_TYPEMASK) == V_BASE10) ! 634: ? 10 : 8); ! 635: *(vp->v_value) = value; ! 636: break; ! 637: } ! 638: ! 639: case V_BOOL: ! 640: { ! 641: char *def = *(vp->v_value) ? "off" : "on", ! 642: *on_off; ! 643: int value; ! 644: ! 645: on_off = ask(def, prompt); ! 646: if (casecmp(on_off, "on") == 0) ! 647: value = ON; ! 648: else if (casecmp(on_off, "off") == 0) ! 649: value = OFF; ! 650: else ! 651: complain("Boolean variables must be ON or OFF."); ! 652: *(vp->v_value) = value; ! 653: #ifdef MAC ! 654: MarkVar(vp,-1,0); /* mark the menu item */ ! 655: #endif ! 656: s_mess("%s%s", prompt, value ? "on" : "off"); ! 657: break; ! 658: } ! 659: ! 660: case V_FILENAME: ! 661: { ! 662: char fbuf[FILESIZE]; ! 663: ! 664: sprintf(&prompt[strlen(prompt)], "(default %s) ", vp->v_value); ! 665: (void) ask_file(prompt, (char *) vp->v_value, fbuf); ! 666: strcpy((char *) vp->v_value, fbuf); ! 667: break; ! 668: } ! 669: ! 670: case V_STRING: ! 671: { ! 672: char *str; ! 673: ! 674: /* Do_ask() so you can set string to "" if you so desire. */ ! 675: str = do_ask("\r\n", (int (*)()) 0, (char *) vp->v_value, prompt); ! 676: if (str == 0) ! 677: str = NullStr; ! 678: strcpy((char *) vp->v_value, str); ! 679: /* ... and hope there is enough room. */ ! 680: break; ! 681: } ! 682: case V_CHAR: ! 683: f_mess(prompt); ! 684: *(vp->v_value) = addgetc(); ! 685: break; ! 686: ! 687: } ! 688: if (vp->v_flags & V_MODELINE) ! 689: UpdModLine = YES; ! 690: if (vp->v_flags & V_CLRSCREEN) { ! 691: #ifdef IBMPC ! 692: setcolor(Fgcolor, Bgcolor); ! 693: #endif /* IBMPC */ ! 694: ClAndRedraw(); ! 695: } ! 696: if (vp->v_flags & V_TTY_RESET) ! 697: tty_reset(); ! 698: } ! 699: ! 700: /* Command completion - possible is an array of strings, prompt is ! 701: the prompt to use, and flags are ... well read jove.h. ! 702: ! 703: If flags are RET_STATE, and the user hits <return> what they typed ! 704: so far is in the Minibuf string. */ ! 705: ! 706: private char **Possible; ! 707: private int comp_value, ! 708: comp_flags; ! 709: ! 710: int ! 711: aux_complete(c) ! 712: { ! 713: int command, ! 714: length, ! 715: i; ! 716: ! 717: if (comp_flags & CASEIND) { ! 718: char *lp; ! 719: ! 720: for (lp = linebuf; *lp != '\0'; lp++) ! 721: #if (defined(IBMPC) || defined(MAC)) ! 722: lower(lp); ! 723: #else ! 724: if (isupper(*lp)) ! 725: *lp = tolower(*lp); ! 726: #endif ! 727: } ! 728: switch (c) { ! 729: case EOF: ! 730: comp_value = -1; ! 731: return 0; ! 732: ! 733: case '\r': ! 734: case '\n': ! 735: command = match(Possible, linebuf); ! 736: if (command >= 0) { ! 737: comp_value = command; ! 738: return 0; /* tells ask to stop */ ! 739: } ! 740: if (eolp() && bolp()) { ! 741: comp_value = NULLSTRING; ! 742: return 0; ! 743: } ! 744: if (comp_flags & RET_STATE) { ! 745: comp_value = command; ! 746: return 0; ! 747: } ! 748: if (InJoverc) ! 749: complain("[\"%s\" unknown]", linebuf); ! 750: rbell(); ! 751: break; ! 752: ! 753: case '\t': ! 754: case ' ': ! 755: { ! 756: int minmatch = 1000, ! 757: maxmatch = 0, ! 758: numfound = 0, ! 759: lastmatch = -1, ! 760: length = strlen(linebuf); ! 761: ! 762: for (i = 0; Possible[i] != 0; i++) { ! 763: int this_len; ! 764: ! 765: this_len = numcomp(Possible[i], linebuf); ! 766: maxmatch = max(maxmatch, this_len); ! 767: if (this_len >= length) { ! 768: if (numfound) ! 769: minmatch = min(minmatch, numcomp(Possible[lastmatch], Possible[i])); ! 770: else ! 771: minmatch = strlen(Possible[i]); ! 772: numfound += 1; ! 773: lastmatch = i; ! 774: if (strcmp(linebuf, Possible[i]) == 0) ! 775: break; ! 776: } ! 777: } ! 778: ! 779: if (numfound == 0) { ! 780: rbell(); ! 781: if (InJoverc) ! 782: complain("[\"%s\" unknown]", linebuf); ! 783: /* If we're not in the .joverc then ! 784: let's do something helpful for the ! 785: user. */ ! 786: if (maxmatch < length) { ! 787: char *cp; ! 788: ! 789: cp = linebuf + maxmatch; ! 790: *cp = 0; ! 791: Eol(); ! 792: } ! 793: break; ! 794: } ! 795: if (c != '\t' && numfound == 1) { ! 796: comp_value = lastmatch; ! 797: return 0; ! 798: } ! 799: null_ncpy(linebuf, Possible[lastmatch], minmatch); ! 800: Eol(); ! 801: if (minmatch == length) /* No difference */ ! 802: rbell(); ! 803: break; ! 804: } ! 805: ! 806: case '?': ! 807: if (InJoverc) ! 808: complain((char *) 0); ! 809: /* kludge: in case we're using UseBuffers, in which case ! 810: linebuf gets written all over */ ! 811: strcpy(Minibuf, linebuf); ! 812: length = strlen(Minibuf); ! 813: TOstart("Completion", TRUE); /* for now ... */ ! 814: for (i = 0; Possible[i]; i++) ! 815: if (numcomp(Possible[i], Minibuf) >= length) { ! 816: Typeout(Possible[i]); ! 817: if (TOabort != 0) ! 818: break; ! 819: } ! 820: ! 821: TOstop(); ! 822: break; ! 823: } ! 824: return !FALSE; ! 825: } ! 826: ! 827: int ! 828: complete(possible, prompt, flags) ! 829: register char *possible[]; ! 830: char *prompt; ! 831: { ! 832: Possible = possible; ! 833: comp_flags = flags; ! 834: (void) do_ask("\r\n \t?", aux_complete, NullStr, prompt); ! 835: return comp_value; ! 836: } ! 837: ! 838: int ! 839: match(choices, what) ! 840: register char **choices, ! 841: *what; ! 842: { ! 843: register int len; ! 844: int i, ! 845: found = 0, ! 846: save, ! 847: exactmatch = -1; ! 848: ! 849: len = strlen(what); ! 850: if (len == 0) ! 851: return NULLSTRING; ! 852: for (i = 0; choices[i]; i++) { ! 853: if (strncmp(what, choices[i], len) == 0) { ! 854: if (strcmp(what, choices[i]) == 0) ! 855: exactmatch = i; ! 856: save = i; ! 857: found += 1; /* found one */ ! 858: } ! 859: } ! 860: ! 861: if (found == 0) ! 862: save = ORIGINAL; ! 863: else if (found > 1) { ! 864: if (exactmatch != -1) ! 865: save = exactmatch; ! 866: else ! 867: save = AMBIGUOUS; ! 868: } ! 869: ! 870: return save; ! 871: } ! 872: ! 873: void ! 874: Source() ! 875: { ! 876: char *com, *getenv(), ! 877: buf[FILESIZE]; ! 878: ! 879: #ifndef MSDOS ! 880: sprintf(buf, "%s/.joverc", getenv("HOME")); ! 881: #else /* MSDOS */ ! 882: if (com = getenv("JOVERC")) ! 883: strcpy(buf, com); ! 884: else ! 885: strcpy(buf, Joverc); ! 886: #endif /* MSDOS */ ! 887: com = ask_file((char *) 0, buf, buf); ! 888: if (joverc(buf) == 0) ! 889: complain(IOerr("read", com)); ! 890: } ! 891: ! 892: void ! 893: BufPos() ! 894: { ! 895: register Line *lp = curbuf->b_first; ! 896: register int i, ! 897: dotline; ! 898: long dotchar, ! 899: nchars; ! 900: ! 901: for (i = nchars = 0; lp != 0; i++, lp = lp->l_next) { ! 902: if (lp == curline) { ! 903: dotchar = nchars + curchar; ! 904: dotline = i + 1; ! 905: } ! 906: nchars += length(lp) + (lp->l_next != 0); /* include the NL */ ! 907: } ! 908: ! 909: s_mess("[\"%s\" line %d/%d, char %D/%D (%d%%), cursor = %d/%d]", ! 910: filename(curbuf), dotline, i, dotchar, nchars, ! 911: (nchars == 0) ? 100 : (int) (((long) dotchar * 100) / nchars), ! 912: calc_pos(linebuf, curchar), ! 913: calc_pos(linebuf, strlen(linebuf))); ! 914: } ! 915: ! 916: #define IF_UNBOUND -1 ! 917: #define IF_TRUE 1 ! 918: #define IF_FALSE !IF_TRUE ! 919: ! 920: #ifndef MAC ! 921: int ! 922: do_if(cmd) ! 923: char *cmd; ! 924: { ! 925: #ifdef MSDOS ! 926: int status; ! 927: #else ! 928: int pid, ! 929: status; ! 930: #endif /* MSDOS */ ! 931: #ifndef MSDOS ! 932: ! 933: switch (pid = fork()) { ! 934: case -1: ! 935: complain("[Fork failed: if]"); ! 936: ! 937: case 0: ! 938: { ! 939: #endif /* MSDOS */ ! 940: char *args[12], ! 941: *cp = cmd, ! 942: **ap = args; ! 943: ! 944: *ap++ = cmd; ! 945: for (;;) { ! 946: if ((cp = index(cp, ' ')) == 0) ! 947: break; ! 948: *cp++ = '\0'; ! 949: *ap++ = cp; ! 950: } ! 951: *ap = 0; ! 952: ! 953: #ifndef MSDOS ! 954: close(0); /* we want reads to fail */ ! 955: /* close(1); but not writes or ioctl's ! 956: close(2); */ ! 957: #else /* MSDOS */ ! 958: if ((status = spawnvp(0, args[0], args)) < 0) ! 959: complain("[Spawn failed: if]"); ! 960: #endif /* MSDOS */ ! 961: ! 962: #ifndef MSDOS ! 963: (void) execvp(args[0], args); ! 964: _exit(-10); /* signals exec error (see below) */ ! 965: } ! 966: } ! 967: #ifdef IPROCS ! 968: sighold(SIGCHLD); ! 969: #endif ! 970: dowait(pid, &status); ! 971: #ifdef IPROCS ! 972: sigrelse(SIGCHLD); ! 973: #endif ! 974: if (status == -10) ! 975: complain("[Exec failed]"); ! 976: if (status < 0) ! 977: complain("[Exit %d]", status); ! 978: #endif /* MSDOS */ ! 979: return (status == 0); /* 0 means successful */ ! 980: } ! 981: #endif /* MAC */ ! 982: ! 983: int ! 984: joverc(file) ! 985: char *file; ! 986: { ! 987: char buf[LBSIZE], ! 988: lbuf[LBSIZE]; ! 989: int lnum = 0, ! 990: eof = FALSE; ! 991: jmp_buf savejmp; ! 992: int IfStatus = IF_UNBOUND; ! 993: File *fp; ! 994: ! 995: fp = open_file(file, buf, F_READ, !COMPLAIN, QUIET); ! 996: if (fp == NIL) ! 997: return NO; /* joverc returns an integer */ ! 998: ! 999: /* Catch any errors, here, and do the right thing with them, ! 1000: and then restore the error handle to whoever did a setjmp ! 1001: last. */ ! 1002: ! 1003: InJoverc += 1; ! 1004: push_env(savejmp); ! 1005: if (setjmp(mainjmp)) { ! 1006: Buffer *savebuf = curbuf; ! 1007: ! 1008: SetBuf(do_select((Window *) 0, "RC errors")); ! 1009: ins_str(sprint("%s:%d:%s\t%s\n", pr_name(file, YES), lnum, lbuf, mesgbuf), NO); ! 1010: unmodify(); ! 1011: SetBuf(savebuf); ! 1012: Asking = 0; ! 1013: } ! 1014: if (!eof) do { ! 1015: eof = (f_gets(fp, lbuf, sizeof lbuf) == EOF); ! 1016: lnum += 1; ! 1017: if (lbuf[0] == '#') /* a comment */ ! 1018: continue; ! 1019: #ifndef MAC ! 1020: if (casencmp(lbuf, "if", 2) == 0) { ! 1021: char cmd[128]; ! 1022: ! 1023: if (IfStatus != IF_UNBOUND) ! 1024: complain("[Cannot have nested if's]"); ! 1025: if (LookingAt("if[ \t]*\\(.*\\)$", lbuf, 0) == 0) ! 1026: complain("[If syntax error]"); ! 1027: putmatch(1, cmd, sizeof cmd); ! 1028: IfStatus = do_if(cmd) ? IF_TRUE : IF_FALSE; ! 1029: continue; ! 1030: } else if (casencmp(lbuf, "else", 4) == 0) { ! 1031: if (IfStatus == IF_UNBOUND) ! 1032: complain("[Unexpected `else']"); ! 1033: IfStatus = !IfStatus; ! 1034: continue; ! 1035: } else if (casencmp(lbuf, "endif", 5) == 0) { ! 1036: if (IfStatus == IF_UNBOUND) ! 1037: complain("[Unexpected `endif']"); ! 1038: IfStatus = IF_UNBOUND; ! 1039: continue; ! 1040: } ! 1041: #endif ! 1042: if (IfStatus == IF_FALSE) ! 1043: continue; ! 1044: (void) strcat(lbuf, "\n"); ! 1045: Inputp = lbuf; ! 1046: while (*Inputp == ' ' || *Inputp == '\t') ! 1047: Inputp += 1; /* skip white space */ ! 1048: Extend(); ! 1049: } while (!eof); ! 1050: ! 1051: f_close(fp); ! 1052: pop_env(savejmp); ! 1053: Inputp = 0; ! 1054: Asking = 0; ! 1055: InJoverc -= 1; ! 1056: if (IfStatus != IF_UNBOUND) ! 1057: complain("[Missing endif]"); ! 1058: return 1; ! 1059: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.