Annotation of 43BSDTahoe/new/jove/ask.c, revision 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 "termcap.h"
        !            10: #include "ctype.h"
        !            11: #include <signal.h>
        !            12: 
        !            13: #ifdef MAC
        !            14: #      include "mac.h"
        !            15: #else
        !            16: #      include <varargs.h>
        !            17: #      ifdef F_COMPLETION
        !            18: #      include <sys/stat.h>
        !            19: #      endif
        !            20: #endif /* MAC */
        !            21: 
        !            22: #ifdef MAC
        !            23: #      undef private
        !            24: #      define private
        !            25: #endif
        !            26: 
        !            27: #ifdef LINT_ARGS
        !            28: private Buffer * get_minibuf(void);
        !            29: private char * real_ask(char *, int (*)(), char *, char *);
        !            30: 
        !            31: private int
        !            32:        f_complete(int),
        !            33:        bad_extension(char *),
        !            34:        crush_bads(char **, int),
        !            35:        isdir(char *);
        !            36: private void
        !            37:        fill_in(char **, int),
        !            38:        EVexpand(void);
        !            39: #else
        !            40: private Buffer * get_minibuf();
        !            41: private char * real_ask();
        !            42: 
        !            43: private int
        !            44:        f_complete(),
        !            45:        bad_extension(),
        !            46:        crush_bads(),
        !            47:        isdir();
        !            48: private void
        !            49:        fill_in(),
        !            50:        EVexpand();
        !            51: #endif /* LINT_ARGS */
        !            52: 
        !            53: #ifdef MAC
        !            54: #      undef private
        !            55: #      define private static
        !            56: #endif
        !            57: 
        !            58: int    AbortChar = CTL('G'),
        !            59:        DoEVexpand = NO;        /* should we expand evironment variables? */
        !            60: 
        !            61: int    Asking = NO;
        !            62: char   Minibuf[LBSIZE];
        !            63: private Line   *CurAskPtr = 0; /* points at some line in mini-buffer */
        !            64: private Buffer *AskBuffer = 0; /* Askbuffer points to actual structure */
        !            65: 
        !            66: /* The way the mini-buffer works is this:  The first line of the mini-buffer
        !            67:    is where the user does his stuff.  The rest of the buffer contains
        !            68:    strings that the user often wants to use, for instance, file names, or
        !            69:    common search strings, etc.  If he types C-N or C-P while in ask(), we
        !            70:    bump the point up or down a line and extract the contents (we make sure
        !            71:    is somewhere in the mini-buffer). */
        !            72: 
        !            73: static Buffer *
        !            74: get_minibuf()
        !            75: {
        !            76:        if (AskBuffer) {                /* make sure ut still exists */
        !            77:                register Buffer *b;
        !            78: 
        !            79:                for (b = world; b != 0; b = b->b_next)
        !            80:                        if (b == AskBuffer)
        !            81:                                return b;
        !            82:        }
        !            83:        AskBuffer = do_select((Window *) 0, "*minibuf*");
        !            84:        AskBuffer->b_type = B_SCRATCH;
        !            85:        return AskBuffer;
        !            86: }
        !            87: 
        !            88: /* Add a string to the mini-buffer. */
        !            89: 
        !            90: void
        !            91: minib_add(str, movedown)
        !            92: char   *str;
        !            93: {
        !            94:        register Buffer *saveb = curbuf;
        !            95: 
        !            96:        SetBuf(get_minibuf());
        !            97:        LineInsert(1);
        !            98:        ins_str(str, NO);
        !            99:        if (movedown)
        !           100:                CurAskPtr = curline;
        !           101:        SetBuf(saveb);
        !           102: }
        !           103: 
        !           104: /* look for any substrings of the form $foo in linebuf, and expand
        !           105:    them according to their value in the environment (if possible) -
        !           106:    this munges all over curchar and linebuf without giving it a second
        !           107:    thought (I must be getting lazy in my old age) */
        !           108: private void
        !           109: EVexpand()
        !           110: {
        !           111:        register int    c;
        !           112:        register char   *lp = linebuf,
        !           113:                        *ep;
        !           114:        char    varname[128],
        !           115:                *vp,
        !           116:                *lp_start;
        !           117:        Mark    *m = MakeMark(curline, curchar, M_FLOATER);
        !           118: 
        !           119:        while (c = *lp++) {
        !           120:                if (c != '$')
        !           121:                        continue;
        !           122:                lp_start = lp - 1;      /* the $ */
        !           123:                vp = varname;
        !           124:                while (c = *lp++) {
        !           125:                        if (!isword(c))
        !           126:                                break;
        !           127:                        *vp++ = c;
        !           128:                }
        !           129:                *vp = '\0';
        !           130:                /* if we find an env. variable with the right
        !           131:                   name, we insert it in linebuf, and then delete
        !           132:                   the variable name that we're replacing - and
        !           133:                   then we continue in case there are others ... */
        !           134:                if (ep = getenv(varname)) {
        !           135:                        curchar = lp_start - linebuf;
        !           136:                        ins_str(ep, NO);
        !           137:                        del_char(FORWARD, strlen(varname) + 1);
        !           138:                        lp = linebuf + curchar;
        !           139:                }
        !           140:        }
        !           141:        ToMark(m);
        !           142:        DelMark(m);
        !           143: }
        !           144: 
        !           145: private char *
        !           146: real_ask(delim, d_proc, def, prompt)
        !           147: char   *delim,
        !           148:        *def,
        !           149:        *prompt;
        !           150: int    (*d_proc)();
        !           151: {
        !           152:        static int      InAsk = 0;
        !           153:        jmp_buf savejmp;
        !           154:        int     c,
        !           155:                prompt_len;
        !           156:        Buffer  *saveb = curbuf;
        !           157:        int     abort = 0,
        !           158:                no_typed = 0;
        !           159:        data_obj        *push_cmd = LastCmd;
        !           160:        int     o_a_v = arg_value(),
        !           161:                o_i_an_a = is_an_arg();
        !           162: #ifdef MAC
        !           163:                menus_off();
        !           164: #endif
        !           165: 
        !           166:        if (InAsk)
        !           167:                complain((char *) 0);
        !           168:        push_env(savejmp);
        !           169:        InAsk += 1;
        !           170:        SetBuf(get_minibuf());
        !           171:        if (!inlist(AskBuffer->b_first, CurAskPtr))
        !           172:                CurAskPtr = curline;
        !           173:        prompt_len = strlen(prompt);
        !           174:        ToFirst();      /* Beginning of buffer. */
        !           175:        linebuf[0] = '\0';
        !           176:        modify();
        !           177:        makedirty(curline);
        !           178: 
        !           179:        if (setjmp(mainjmp))
        !           180:                if (InJoverc) {         /* this is a kludge */
        !           181:                        abort = YES;
        !           182:                        goto cleanup;
        !           183:                }
        !           184: 
        !           185:        for (;;) {
        !           186:                clr_arg_value();
        !           187:                last_cmd = this_cmd;
        !           188:                init_strokes();
        !           189: cont:          s_mess("%s%s", prompt, linebuf);
        !           190:                Asking = curchar + prompt_len;
        !           191:                c = getch();
        !           192:                if ((c == EOF) || index(delim, c)) {
        !           193:                        if (DoEVexpand)
        !           194:                                EVexpand();
        !           195:                        if (d_proc == (int(*)())0 || (*d_proc)(c) == 0)
        !           196:                                goto cleanup;
        !           197:                } else if (c == AbortChar) {
        !           198:                        message("[Aborted]");
        !           199:                        abort = YES;
        !           200:                        goto cleanup;
        !           201:                } else switch (c) {
        !           202:                case CTL('N'):
        !           203:                case CTL('P'):
        !           204:                        if (CurAskPtr != 0) {
        !           205:                                int     n = (c == CTL('P') ? -arg_value() : arg_value());
        !           206:                                CurAskPtr = next_line(CurAskPtr, n);
        !           207:                                if (CurAskPtr == curbuf->b_first && CurAskPtr->l_next != 0)
        !           208:                                        CurAskPtr = CurAskPtr->l_next;
        !           209:                                (void) ltobuf(CurAskPtr, linebuf);
        !           210:                                modify();
        !           211:                                makedirty(curline);
        !           212:                                Eol();
        !           213:                                this_cmd = 0;
        !           214:                        }
        !           215:                        break;
        !           216: 
        !           217:                case CTL('R'):
        !           218:                        if (def)
        !           219:                                ins_str(def, NO);
        !           220:                        else
        !           221:                                rbell();
        !           222:                        break;
        !           223: 
        !           224:                default:
        !           225:                        dispatch(c);
        !           226:                        break;
        !           227:                }
        !           228:                if (curbuf != AskBuffer)
        !           229:                        SetBuf(AskBuffer);
        !           230:                if (curline != curbuf->b_first) {
        !           231:                        CurAskPtr = curline;
        !           232:                        curline = curbuf->b_first;      /* with whatever is in linebuf */
        !           233:                }
        !           234:                if (this_cmd == ARG_CMD)
        !           235:                        goto cont;
        !           236:        }
        !           237: cleanup:
        !           238:        pop_env(savejmp);
        !           239: 
        !           240:        LastCmd = push_cmd;
        !           241:        set_arg_value(o_a_v);
        !           242:        set_is_an_arg(o_i_an_a);
        !           243:        no_typed = (linebuf[0] == '\0');
        !           244:        strcpy(Minibuf, linebuf);
        !           245:        SetBuf(saveb);
        !           246:        InAsk = Asking = Interactive = NO;
        !           247:        if (!abort) {
        !           248:                if (!charp()) {
        !           249:                        Placur(ILI, 0);
        !           250:                        flusho();
        !           251:                }
        !           252:                if (no_typed)
        !           253:                        return 0;
        !           254:        } else
        !           255:                complain(mesgbuf);
        !           256:        return Minibuf;
        !           257: }
        !           258: 
        !           259: /* VARARGS2 */
        !           260: 
        !           261: char *
        !           262: ask(def, fmt, va_alist)
        !           263: char   *def,
        !           264:        *fmt;
        !           265: va_dcl
        !           266: {
        !           267:        char    prompt[128];
        !           268:        char    *ans;
        !           269:        va_list ap;
        !           270: 
        !           271:        va_start(ap);
        !           272:        format(prompt, sizeof prompt, fmt, ap);
        !           273:        va_end(ap);
        !           274:        ans = real_ask("\r\n", (int (*)()) 0, def, prompt);
        !           275:        if (ans == 0) {         /* Typed nothing. */
        !           276:                if (def == 0)
        !           277:                        complain("[No default]");
        !           278:                return def;
        !           279:        }
        !           280:        return ans;
        !           281: }
        !           282: 
        !           283: /* VARARGS1 */
        !           284: 
        !           285: char *
        !           286: do_ask(delim, d_proc, def, fmt, va_alist)
        !           287: char   *delim,
        !           288:        *def,
        !           289:        *fmt;
        !           290: int    (*d_proc)();
        !           291: va_dcl
        !           292: {
        !           293:        char    prompt[128];
        !           294:        va_list ap;
        !           295: 
        !           296:        va_start(ap);
        !           297:        format(prompt, sizeof prompt, fmt, ap);
        !           298:        va_end(ap);
        !           299:        return real_ask(delim, d_proc, def, prompt);
        !           300: }
        !           301: 
        !           302: /* VARARGS1 */
        !           303: 
        !           304: int
        !           305: yes_or_no_p(fmt, va_alist)
        !           306: char   *fmt;
        !           307: va_dcl
        !           308: {
        !           309:        char    prompt[128];
        !           310:        int     c;
        !           311:        va_list ap;
        !           312: 
        !           313:        va_start(ap);
        !           314:        format(prompt, sizeof prompt, fmt, ap);
        !           315:        va_end(ap);
        !           316:        for (;;) {
        !           317:                message(prompt);
        !           318:                Asking = strlen(prompt);        /* so redisplay works */
        !           319:                c = getch();
        !           320:                Asking = NO;
        !           321:                if (c == AbortChar)
        !           322:                        complain("[Aborted]");
        !           323:                switch (CharUpcase(c)) {
        !           324:                case 'Y':
        !           325:                        return YES;
        !           326: 
        !           327:                case 'N':
        !           328:                        return NO;
        !           329: 
        !           330:                default:
        !           331:                        add_mess("[Type Y or N]");
        !           332:                        SitFor(10);
        !           333:                }
        !           334:        }
        !           335:        /* NOTREACHED */
        !           336: }
        !           337: 
        !           338: #ifdef F_COMPLETION
        !           339: static char    *fc_filebase;
        !           340: int    DispBadFs = YES;        /* display bad file names? */
        !           341: #ifndef MSDOS
        !           342: char   BadExtensions[128] = ".o";
        !           343: #else /* MSDOS */
        !           344: char   BadExtensions[128] = ".obj .exe .com .bak .arc .lib .zoo";
        !           345: #endif /* MSDOS */
        !           346: 
        !           347: static
        !           348: bad_extension(name)
        !           349: char   *name;
        !           350: {
        !           351:        char    *ip,
        !           352:                *bads = BadExtensions;
        !           353:        int     namelen = strlen(name),
        !           354:                ext_len,
        !           355:                stop = 0;
        !           356: 
        !           357:        do {
        !           358:                if ((ip = index(bads, ' ')) == 0) {
        !           359:                        ip = bads + strlen(bads);
        !           360:                        stop = YES;
        !           361:                }
        !           362:                if ((ext_len = ip - bads) == 0)
        !           363:                        continue;
        !           364:                if ((ext_len < namelen) &&
        !           365:                    (strncmp(&name[namelen - ext_len], bads, ext_len) == 0))
        !           366:                        return YES;
        !           367:        } while ((bads = ip + 1), !stop);
        !           368:        return NO;
        !           369: }
        !           370: 
        !           371: int
        !           372: f_match(file)
        !           373: char   *file;
        !           374: {
        !           375:        int     len = strlen(fc_filebase);
        !           376: 
        !           377:        if (DispBadFs == NO)
        !           378:                if (bad_extension(file))
        !           379:                        return NO;
        !           380: 
        !           381:        return ((len == 0) ||
        !           382: #ifdef MSDOS
        !           383:                (casencmp(file, fc_filebase, strlen(fc_filebase)) == 0)
        !           384: #else
        !           385:                (strncmp(file, fc_filebase, strlen(fc_filebase)) == 0)
        !           386: #endif
        !           387:                );
        !           388: }
        !           389: 
        !           390: static
        !           391: isdir(name)
        !           392: char   *name;
        !           393: {
        !           394:        struct stat     stbuf;
        !           395:        char    filebuf[FILESIZE];
        !           396: 
        !           397:        PathParse(name, filebuf);
        !           398:        return ((stat(filebuf, &stbuf) != -1) &&
        !           399:                (stbuf.st_mode & S_IFDIR) == S_IFDIR);
        !           400: }
        !           401: 
        !           402: private void
        !           403: fill_in(dir_vec, n)
        !           404: register char  **dir_vec;
        !           405: {
        !           406:        int     minmatch = 0,
        !           407:                numfound = 0,
        !           408:                lastmatch = -1,
        !           409:                i,
        !           410:                the_same = TRUE, /* After filling in, are we the same
        !           411:                                    as when we were called? */
        !           412:                is_ntdir;       /* Is Newly Typed Directory name */
        !           413:        char    bads[128];
        !           414: 
        !           415:        for (i = 0; i < n; i++) {
        !           416:                /* if it's no, then we have already filtered them out
        !           417:                   in f_match() so there's no point in doing it again */
        !           418:                if (DispBadFs == YES) {
        !           419:                        if (bad_extension(dir_vec[i]))
        !           420:                                continue;
        !           421:                }
        !           422:                if (numfound)
        !           423:                        minmatch = min(minmatch,
        !           424:                                       numcomp(dir_vec[lastmatch], dir_vec[i]));
        !           425:                else
        !           426:                        minmatch = strlen(dir_vec[i]);
        !           427:                lastmatch = i;
        !           428:                numfound += 1;
        !           429:        }
        !           430:        /* Ugh.  Beware--this is hard to get right in a reasonable
        !           431:           manner.  Please excuse this code--it's past my bedtime. */
        !           432:        if (numfound == 0) {
        !           433:                rbell();
        !           434:                return;
        !           435:        }
        !           436:        Eol();
        !           437:        if (minmatch > strlen(fc_filebase)) {
        !           438:                the_same = FALSE;
        !           439:                null_ncpy(fc_filebase, dir_vec[lastmatch], minmatch);
        !           440:                Eol();
        !           441:                makedirty(curline);
        !           442:        }
        !           443:        is_ntdir = ((numfound == 1) &&
        !           444:                    (curchar > 0) &&
        !           445:                    (linebuf[curchar - 1] != '/') &&
        !           446:                    (isdir(linebuf)));
        !           447:        if (the_same && !is_ntdir) {
        !           448:                add_mess((n == 1) ? " [Unique]" : " [Ambiguous]");
        !           449:                SitFor(7);
        !           450:        }
        !           451:        if (is_ntdir)
        !           452:                insert_c('/', 1);
        !           453: }
        !           454: 
        !           455: extern int     alphacomp();
        !           456: 
        !           457: /* called from do_ask() when one of "\r\n ?" is typed.  Does the right
        !           458:    thing, depending on which. */
        !           459: 
        !           460: static
        !           461: f_complete(c)
        !           462: {
        !           463:        char    dir[FILESIZE],
        !           464:                **dir_vec;
        !           465:        int     nentries,
        !           466:                i;
        !           467: 
        !           468:        if (c == CR || c == LF)
        !           469:                return 0;       /* tells ask to return now */
        !           470: #ifndef MSDOS          /* kg */
        !           471:        if ((fc_filebase = rindex(linebuf, '/')) != 0) {
        !           472: #else /* MSDOS */
        !           473:        fc_filebase = rindex(linebuf, '/');
        !           474:        if (fc_filebase == (char *)0)
        !           475:                fc_filebase = rindex(linebuf, '\\');
        !           476:        if (fc_filebase == (char *)0)
        !           477:                fc_filebase = rindex(linebuf, ':');
        !           478:        if (fc_filebase != (char *)0) {
        !           479: #endif /* MSDOS */
        !           480:                char    tmp[FILESIZE];
        !           481: 
        !           482:                fc_filebase += 1;
        !           483:                null_ncpy(tmp, linebuf, (fc_filebase - linebuf));
        !           484:                if (tmp[0] == '\0')
        !           485:                        strcpy(tmp, "/");
        !           486:                PathParse(tmp, dir);
        !           487:        } else {                
        !           488:                fc_filebase = linebuf;
        !           489:                strcpy(dir, ".");
        !           490:        }
        !           491:        if ((nentries = scandir(dir, &dir_vec, f_match, alphacomp)) == -1) {
        !           492:                add_mess(" [Unknown directory: %s]", dir);
        !           493:                SitFor(7);
        !           494:                return 1;
        !           495:        }
        !           496:        if (nentries == 0) {
        !           497:                add_mess(" [No match]");
        !           498:                SitFor(7);
        !           499:        } else if (c == ' ' || c == '\t')
        !           500:                fill_in(dir_vec, nentries);
        !           501:        else {
        !           502:                /* we're a '?' */
        !           503:                int     maxlen = 0,
        !           504:                        ncols,
        !           505:                        col,
        !           506:                        lines,
        !           507:                        linespercol;
        !           508: 
        !           509:                TOstart("Completion", FALSE);   /* false means newline only on request */
        !           510:                Typeout("(! means file will not be chosen unless typed explicitly)");
        !           511:                Typeout((char *) 0);
        !           512:                Typeout("Possible completions (in %s):", dir);
        !           513:                Typeout((char *) 0);
        !           514: 
        !           515:                for (i = 0; i < nentries; i++)
        !           516:                        maxlen = max(strlen(dir_vec[i]), maxlen);
        !           517:                maxlen += 4;    /* pad each column with at least 4 spaces */
        !           518:                ncols = (CO - 2) / maxlen;
        !           519:                linespercol = 1 + (nentries / ncols);
        !           520: 
        !           521:                for (lines = 0; lines < linespercol; lines++) {
        !           522:                        for (col = 0; col < ncols; col++) {
        !           523:                                int     isbad,
        !           524:                                        which;
        !           525: 
        !           526:                                which = (col * linespercol) + lines;
        !           527:                                if (which >= nentries)
        !           528:                                        break;
        !           529:                                if (DispBadFs == YES)
        !           530:                                        isbad = bad_extension(dir_vec[which]);
        !           531:                                else
        !           532:                                        isbad = NO;
        !           533:                                Typeout("%s%-*s", isbad ? "!" : NullStr,
        !           534:                                        maxlen - isbad, dir_vec[which]);
        !           535:                        }
        !           536:                        Typeout((char *) 0);
        !           537:                }
        !           538:                TOstop();
        !           539:        }
        !           540:        freedir(&dir_vec, nentries);
        !           541:        return 1;
        !           542: }
        !           543: 
        !           544: #endif
        !           545: 
        !           546: char *
        !           547: ask_file(prmt, def, buf)
        !           548: char   *prmt,
        !           549:        *def,
        !           550:        *buf;
        !           551: {
        !           552:        char    *ans,
        !           553:                prompt[128],
        !           554:                *pretty_name = pr_name(def, YES);
        !           555:        if (prmt)
        !           556:                sprintf(prompt, prmt);
        !           557:        else {
        !           558:                if (def != 0 && *def != '\0')
        !           559:                        sprintf(prompt, ": %f (default %s) ", pretty_name);
        !           560:                else
        !           561:                        sprintf(prompt, ProcFmt);
        !           562:        }
        !           563: #ifdef F_COMPLETION
        !           564:        ans = real_ask("\r\n \t?", f_complete, pretty_name, prompt);
        !           565:        if (ans == 0 && (ans = pretty_name) == 0)
        !           566:                complain("[No default file name]");
        !           567: #else
        !           568:        ans = ask(pretty_name, prompt);
        !           569: #endif
        !           570:        PathParse(ans, buf);
        !           571: 
        !           572:        return buf;
        !           573: }

unix.superglobalmegacorp.com

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