Annotation of 43BSD/contrib/jove/ask.c, revision 1.1

1.1     ! root        1: /*************************************************************************
        !             2:  * This program is copyright (C) 1985, 1986 by Jonathan Payne.  It is    *
        !             3:  * provided to you without charge for use only on a licensed Unix        *
        !             4:  * system.  You may copy JOVE provided that this notice is included with *
        !             5:  * the copy.  You may not sell copies of this program or versions        *
        !             6:  * modified for use on microcomputer systems, unless the copies are      *
        !             7:  * included with a Unix system distribution and the source is provided.  *
        !             8:  *************************************************************************/
        !             9: 
        !            10: #include "jove.h"
        !            11: #include "termcap.h"
        !            12: #include "ctype.h"
        !            13: #include <signal.h>
        !            14: #include <varargs.h>
        !            15: 
        !            16: #ifdef F_COMPLETION
        !            17: #      include <sys/stat.h>
        !            18: #endif
        !            19: 
        !            20: int    Asking = 0;
        !            21: char   Minibuf[LBSIZE];
        !            22: private Line   *CurAskPtr = 0; /* points at some line in mini-buffer */
        !            23: private Buffer *AskBuffer = 0; /* Askbuffer points to actual structure */
        !            24: 
        !            25: /* The way the mini-buffer works is this:  The first line of the mini-buffer
        !            26:    is where the user does his stuff.  The rest of the buffer contains
        !            27:    strings that the user often wants to use, for instance, file names, or
        !            28:    common search strings, etc.  If he types C-N or C-P while in ask(), we
        !            29:    bump the point up or down a line and extract the contents (we make sure
        !            30:    is somewhere in the mini-buffer). */
        !            31: 
        !            32: static Buffer *
        !            33: get_minibuf()
        !            34: {
        !            35:        if (AskBuffer)
        !            36:                return AskBuffer;
        !            37:        AskBuffer = do_select((Window *) 0, "Minibuf");
        !            38:        AskBuffer->b_type = B_SCRATCH;
        !            39:        return AskBuffer;
        !            40: }
        !            41: 
        !            42: /* Add a string to the mini-buffer. */
        !            43: 
        !            44: minib_add(str, movedown)
        !            45: char   *str;
        !            46: {
        !            47:        register Buffer *saveb = curbuf;
        !            48: 
        !            49:        SetBuf(get_minibuf());
        !            50:        LineInsert();
        !            51:        ins_str(str, NO);
        !            52:        if (movedown)
        !            53:                CurAskPtr = curline;
        !            54:        SetBuf(saveb);
        !            55: }
        !            56: 
        !            57: static char *
        !            58: real_ask(delim, d_proc, def, prompt)
        !            59: char   *delim,
        !            60:        *def,
        !            61:        *prompt;
        !            62: int    (*d_proc)();
        !            63: {
        !            64:        static int      InAsk = 0;
        !            65:        jmp_buf savejmp;
        !            66:        int     c,
        !            67:                prompt_len;
        !            68:        Buffer  *saveb = curbuf;
        !            69:        int     abort = 0,
        !            70:                no_typed = 0;
        !            71:        data_obj        *push_cmd = LastCmd;
        !            72:        int     o_exp = exp,
        !            73:                o_exp_p = exp_p;
        !            74: 
        !            75:        if (InAsk)
        !            76:                complain((char *) 0);
        !            77:        push_env(savejmp);
        !            78:        InAsk++;
        !            79:        SetBuf(get_minibuf());
        !            80:        if (!inlist(AskBuffer->b_first, CurAskPtr))
        !            81:                CurAskPtr = curline;
        !            82:        prompt_len = strlen(prompt);
        !            83:        ToFirst();      /* Beginning of buffer. */
        !            84:        linebuf[0] = '\0';
        !            85:        modify();
        !            86:        makedirty(curline);
        !            87: 
        !            88:        if (setjmp(mainjmp))
        !            89:                if (InJoverc) {         /* this is a kludge */
        !            90:                        abort++;
        !            91:                        goto cleanup;
        !            92:                }
        !            93: 
        !            94:        for (;;) {
        !            95:                exp = 1;
        !            96:                exp_p = 0;
        !            97:                last_cmd = this_cmd;
        !            98:                init_strokes();
        !            99: cont:          s_mess("%s%s", prompt, linebuf);
        !           100:                Asking = curchar + prompt_len;
        !           101:                c = getch();
        !           102:                if ((c == EOF) || index(delim, c)) {
        !           103:                        if (d_proc == 0 || (*d_proc)(c) == 0)
        !           104:                                goto cleanup;
        !           105:                } else switch (c) {
        !           106:                case CTL(G):
        !           107:                        message("[Aborted]");
        !           108:                        abort++;
        !           109:                        goto cleanup;
        !           110: 
        !           111:                case CTL(N):
        !           112:                case CTL(P):
        !           113:                        if (CurAskPtr != 0) {
        !           114:                                int     n = (c == CTL(P) ? -exp : exp);
        !           115: 
        !           116:                                CurAskPtr = next_line(CurAskPtr, n);
        !           117:                                if (CurAskPtr == curbuf->b_first && CurAskPtr->l_next != 0)
        !           118:                                        CurAskPtr = CurAskPtr->l_next;
        !           119:                                (void) ltobuf(CurAskPtr, linebuf);
        !           120:                                modify();
        !           121:                                makedirty(curline);
        !           122:                                Eol();
        !           123:                                this_cmd = 0;
        !           124:                        }
        !           125:                        break;
        !           126: 
        !           127:                case CTL(R):
        !           128:                        if (def)
        !           129:                                ins_str(def, NO);
        !           130:                        else
        !           131:                                rbell();
        !           132:                        break;
        !           133: 
        !           134:                default:
        !           135:                        dispatch(c);
        !           136:                        break;
        !           137:                }
        !           138:                if (curbuf != AskBuffer)
        !           139:                        SetBuf(AskBuffer);
        !           140:                if (curline != curbuf->b_first) {
        !           141:                        CurAskPtr = curline;
        !           142:                        curline = curbuf->b_first;      /* with whatever is in linebuf */
        !           143:                }
        !           144:                if (this_cmd == ARG_CMD)
        !           145:                        goto cont;
        !           146:        }
        !           147: cleanup:
        !           148:        pop_env(savejmp);
        !           149: 
        !           150:        LastCmd = push_cmd;
        !           151:        exp_p = o_exp_p;
        !           152:        exp = o_exp;
        !           153:        no_typed = (linebuf[0] == '\0');
        !           154:        strcpy(Minibuf, linebuf);
        !           155:        SetBuf(saveb);
        !           156:        InAsk = Asking = Interactive = 0;
        !           157:        if (!abort) {
        !           158:                if (!charp()) {
        !           159:                        Placur(ILI, 0);
        !           160:                        flusho();
        !           161:                }
        !           162:                if (no_typed)
        !           163:                        return 0;
        !           164:        } else
        !           165:                complain(mesgbuf);
        !           166:        return Minibuf;
        !           167: }
        !           168: 
        !           169: /* VARARGS2 */
        !           170: 
        !           171: char *
        !           172: ask(def, fmt, va_alist)
        !           173: char   *def,
        !           174:        *fmt;
        !           175: va_dcl
        !           176: {
        !           177:        char    prompt[128];
        !           178:        char    *ans;
        !           179:        va_list ap;
        !           180: 
        !           181:        va_start(ap);
        !           182:        format(prompt, sizeof prompt, fmt, ap);
        !           183:        va_end(ap);
        !           184:        ans = real_ask("\r\n", (int (*)()) 0, def, prompt);
        !           185:        if (ans == 0) {         /* Typed nothing. */
        !           186:                if (def == 0)
        !           187:                        complain("[No default]");
        !           188:                return def;
        !           189:        }
        !           190:        return ans;
        !           191: }
        !           192: 
        !           193: /* VARARGS2 */
        !           194: 
        !           195: char *
        !           196: do_ask(delim, d_proc, def, fmt, va_alist)
        !           197: char   *delim,
        !           198:        *def,
        !           199:        *fmt;
        !           200: int    (*d_proc)();
        !           201: va_dcl
        !           202: {
        !           203:        char    prompt[128];
        !           204:        va_list ap;
        !           205: 
        !           206:        va_start(ap);
        !           207:        format(prompt, sizeof prompt, fmt, ap);
        !           208:        va_end(ap);
        !           209:        return real_ask(delim, d_proc, def, prompt);
        !           210: }
        !           211: 
        !           212: #ifdef F_COMPLETION
        !           213: static char    *fc_filebase;
        !           214: char   BadExtensions[128] = ".o";
        !           215: 
        !           216: static
        !           217: bad_extension(name, bads)
        !           218: char   *name,
        !           219:        *bads;
        !           220: {
        !           221:        char    *ip;
        !           222:        int     namelen = strlen(name),
        !           223:                ext_len,
        !           224:                stop = 0;
        !           225: 
        !           226:        do {
        !           227:                if (ip = index(bads, ' '))
        !           228:                        *ip = 0;
        !           229:                else {
        !           230:                        ip = bads + strlen(bads);
        !           231:                        stop++;
        !           232:                }
        !           233:                if ((ext_len = ip - bads) == 0)
        !           234:                        continue;
        !           235:                if ((ext_len < namelen) &&
        !           236:                    (strcmp(&name[namelen - ext_len], bads) == 0))
        !           237:                        return YES;
        !           238:        } while ((bads = ip + 1), !stop);
        !           239:        return NO;
        !           240: }
        !           241: 
        !           242: f_match(file)
        !           243: char   *file;
        !           244: {
        !           245:        int     len = strlen(fc_filebase);
        !           246: 
        !           247:        return ((len == 0) ||
        !           248:                (strncmp(file, fc_filebase, strlen(fc_filebase)) == 0));
        !           249: }
        !           250: 
        !           251: static
        !           252: isdir(name)
        !           253: char   *name;
        !           254: {
        !           255:        struct stat     stbuf;
        !           256:        char    filebuf[FILESIZE];
        !           257: 
        !           258:        PathParse(name, filebuf);
        !           259:        return ((stat(filebuf, &stbuf) != -1) &&
        !           260:                (stbuf.st_mode & S_IFDIR) == S_IFDIR);
        !           261: }
        !           262: 
        !           263: static
        !           264: fill_in(dir_vec, n)
        !           265: register char  **dir_vec;
        !           266: {
        !           267:        int     minmatch = 0,
        !           268:                numfound = 0,
        !           269:                lastmatch = -1,
        !           270:                i,
        !           271:                the_same = TRUE, /* After filling in, are we the same
        !           272:                                    as when we were called? */
        !           273:                is_ntdir;       /* Is Newly Typed Directory name */
        !           274:        char    bads[128];
        !           275: 
        !           276:        for (i = 0; i < n; i++) {
        !           277:                strcpy(bads, BadExtensions);
        !           278:                /* bad_extension() is destructive */
        !           279:                if (bad_extension(dir_vec[i], bads))
        !           280:                        continue;
        !           281:                if (numfound)
        !           282:                        minmatch = min(minmatch,
        !           283:                                       numcomp(dir_vec[lastmatch], dir_vec[i]));
        !           284:                else
        !           285:                        minmatch = strlen(dir_vec[i]);
        !           286:                lastmatch = i;
        !           287:                numfound++;
        !           288:        }
        !           289:        /* Ugh.  Beware--this is hard to get right in a reasonable
        !           290:           manner.  Please excuse this code--it's past my bedtime. */
        !           291:        if (numfound == 0) {
        !           292:                rbell();
        !           293:                return;
        !           294:        }
        !           295:        Eol();
        !           296:        if (minmatch > strlen(fc_filebase)) {
        !           297:                the_same = FALSE;
        !           298:                null_ncpy(fc_filebase, dir_vec[lastmatch], minmatch);
        !           299:                Eol();
        !           300:                makedirty(curline);
        !           301:        }
        !           302:        is_ntdir = ((numfound == 1) &&
        !           303:                    (curchar > 0) &&
        !           304:                    (linebuf[curchar - 1] != '/') &&
        !           305:                    (isdir(linebuf)));
        !           306:        if (the_same && !is_ntdir) {
        !           307:                add_mess(n == 1 ? " [Unique]" : " [Ambiguous]");
        !           308:                (void) SitFor(7);
        !           309:        }
        !           310:        if (is_ntdir)
        !           311:                Insert('/');
        !           312: }
        !           313: 
        !           314: extern int     alphacomp();
        !           315: 
        !           316: /* called from do_ask() when one of "\r\n ?" is typed.  Does the right
        !           317:    thing, depending on which. */
        !           318: 
        !           319: static
        !           320: f_complete(c)
        !           321: {
        !           322:        char    dir[FILESIZE],
        !           323:                **dir_vec;
        !           324:        int     nentries,
        !           325:                i;
        !           326: 
        !           327:        if (c == CR || c == LF)
        !           328:                return 0;       /* tells ask to return now */
        !           329:        if ((fc_filebase = rindex(linebuf, '/')) != 0) {
        !           330:                char    tmp[FILESIZE];
        !           331: 
        !           332:                null_ncpy(tmp, linebuf, (++fc_filebase - linebuf));
        !           333:                if (tmp[0] == '\0')
        !           334:                        strcpy(tmp, "/");
        !           335:                PathParse(tmp, dir);
        !           336:        } else {                
        !           337:                fc_filebase = linebuf;
        !           338:                strcpy(dir, ".");
        !           339:        }
        !           340:        if ((nentries = scandir(dir, &dir_vec, f_match, alphacomp)) == -1) {
        !           341:                add_mess(" [Unknown directory: %s]", dir);
        !           342:                (void) SitFor(7);
        !           343:                return 1;
        !           344:        }
        !           345:        if (nentries == 0) {
        !           346:                add_mess(" [No match]");
        !           347:                (void) SitFor(7);
        !           348:        } else if (c == ' ')
        !           349:                fill_in(dir_vec, nentries);
        !           350:        else {
        !           351:                /* we're a '?' */
        !           352:                int     maxlen = 0,
        !           353:                        ncols,
        !           354:                        col,
        !           355:                        lines,
        !           356:                        linespercol;
        !           357: 
        !           358:                TOstart("Completion", FALSE);   /* false means newline only on request */
        !           359:                Typeout("(! means file will not be chosen unless typed explicitly)");
        !           360:                Typeout((char *) 0);
        !           361:                Typeout("Possible completions (in %s):", dir);
        !           362:                Typeout((char *) 0);
        !           363: 
        !           364:                for (i = 0; i < nentries; i++)
        !           365:                        maxlen = max(strlen(dir_vec[i]), maxlen);
        !           366:                maxlen += 4;    /* pad each column with at least 4 spaces */
        !           367:                ncols = (CO - 2) / maxlen;
        !           368:                linespercol = 1 + (nentries / ncols);
        !           369: 
        !           370:                for (lines = 0; lines < linespercol; lines++) {
        !           371:                        for (col = 0; col < ncols; col++) {
        !           372:                                int     isbad,
        !           373:                                        which;
        !           374:                                char    bads[128];
        !           375: 
        !           376:                                which = (col * linespercol) + lines;
        !           377:                                if (which >= nentries)
        !           378:                                        break;
        !           379:                                strcpy(bads, BadExtensions);
        !           380:                                isbad = bad_extension(dir_vec[which], bads);
        !           381:                                Typeout("%s%-*s", isbad ? "!" : NullStr,
        !           382:                                        maxlen - isbad, dir_vec[which]);
        !           383:                        }
        !           384:                        Typeout((char *) 0);
        !           385:                }
        !           386:                TOstop();
        !           387:        }
        !           388:        freedir(&dir_vec, nentries);
        !           389:        return 1;
        !           390: }
        !           391: 
        !           392: #endif
        !           393: 
        !           394: char *
        !           395: ask_file(def, buf)
        !           396: char   *def,
        !           397:        *buf;
        !           398: {
        !           399:        char    *ans,
        !           400:                prompt[128],
        !           401:                *pretty_name = pr_name(def);
        !           402: 
        !           403:        if (def != 0 && *def != '\0')
        !           404:                sprintf(prompt, ": %f (default %s) ", pretty_name);
        !           405:        else
        !           406:                sprintf(prompt, ProcFmt);
        !           407: #ifdef F_COMPLETION
        !           408:        ans = real_ask("\r\n ?", f_complete, pretty_name, prompt);
        !           409:        if (ans == 0 && (ans = pretty_name) == 0)
        !           410:                complain("[No default file name]");
        !           411: #else
        !           412:        ans = ask(pretty_name, prompt);
        !           413: #endif
        !           414:        PathParse(ans, buf);
        !           415: 
        !           416:        return buf;
        !           417: }

unix.superglobalmegacorp.com

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