Annotation of 43BSDTahoe/new/jove/extend.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.