# 2.11BSD#431 - /usr/src/new/jove/ask.c

##### Functions

    EVexpand          X
    ask               X
    ask_file          X
    do_ask            X
    f_match           X
    fill_in           X
    minib_add         X
    real_ask          X
    yes_or_no_p       X

##### Variables

    AbortChar         X
    AskBuffer         X
    Asking            X
    BadExtensions     X
    CurAskPtr         X
    DispBadFs         X
    Minibuf           X
    private           X

##### Macros

    private           X

       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:         sprintf(prompt, ProcFmt);
     559: #ifdef F_COMPLETION
     560:     ans = real_ask("\r\n \t?", f_complete, pretty_name, prompt);
     561:     if (ans == 0)
     562:         complain((char *)0);
     563: #else
     564:     ans = ask(pretty_name, prompt);
     565: #endif
     566:     PathParse(ans, buf);
     567:
     568:     return buf;
     569: }

#### Defined functions

EVexpand defined in line 108; used 3 times

- in line 38, 50, 194

ask defined in line 261; used 32 times

- in line 564
- in /usr/src/new/jove/abbrev.c line 83-84(2), 319
- in /usr/src/new/jove/buf.c line 150, 366
- in /usr/src/new/jove/extend.c line 174, 475, 568, 645
- in /usr/src/new/jove/externs.h line 34, 641
- in /usr/src/new/jove/insert.c line 709
- in /usr/src/new/jove/io.c line 876
- in /usr/src/new/jove/iproc.c line 33, 280
- in /usr/src/new/jove/jove.c line 916, 970, 976
- in /usr/src/new/jove/macros.c line 223, 304
- in /usr/src/new/jove/misc.c line 260
- in /usr/src/new/jove/proc.c line 329, 416-417(2), 424, 432, 441, 728
- in /usr/src/new/jove/re.c line 909
- in /usr/src/new/jove/re1.c line 175, 346

ask_file defined in line 546; used 15 times

- in /usr/src/new/jove/abbrev.c line 268, 276
- in /usr/src/new/jove/buf.c line 164
- in /usr/src/new/jove/extend.c line 664, 886
- in /usr/src/new/jove/externs.h line 36, 643
- in /usr/src/new/jove/io.c line 316, 412, 667, 700, 865, 909
- in /usr/src/new/jove/macros.c line 273
- in /usr/src/new/jove/re1.c line 323

bad_extension defined in line 347; used 5 times

- in line 33, 45, 378, 419, 530

do_ask defined in line 285; used 8 times

- in /usr/src/new/jove/extend.c line 99, 674, 833
- in /usr/src/new/jove/externs.h line 39, 646
- in /usr/src/new/jove/mac.c line 1978
- in /usr/src/new/jove/macros.c line 298
- in /usr/src/new/jove/re1.c line 180

f_complete defined in line 460; used 3 times

- in line 32, 44, 560

f_match defined in line 371; used 3 times

- in line 491
- in /usr/src/new/jove/externs.h line 80, 687

fill_in defined in line 402; used 3 times

- in line 37, 49, 500

get_minibuf defined in line 73; used 4 times

- in line 28, 40, 96, 170

isdir defined in line 390; used 3 times

- in line 35, 47, 446

minib_add defined in line 90; used 3 times

- in /usr/src/new/jove/externs.h line 500, 1106
- in /usr/src/new/jove/jove.c line 784

real_ask defined in line 145; used 5 times

- in line 29, 41, 274, 299, 560

yes_or_no_p defined in line 304; used 4 times

- in /usr/src/new/jove/buf.c line 363
- in /usr/src/new/jove/externs.h line 116, 723
- in /usr/src/new/jove/misc.c line 265

#### Defined variables

AbortChar defined in line 58; used 5 times

- in line 197, 321
- in /usr/src/new/jove/misc.c line 203
- in /usr/src/new/jove/re1.c line 489
- in /usr/src/new/jove/vars.c line 13

AskBuffer defined in line 64; used 8 times

- in line 76-85(5), 171, 228-229(2)

Asking defined in line 61; used 10 times

- in line 190, 246, 318-320(2)
- in /usr/src/new/jove/macros.c line 387
- in /usr/src/new/jove/util.c line 506, 830
- in /usr/src/new/jove/wind.c line 149, 162, 317

BadExtensions defined in line 344; used 2 times

- in line 352
- in /usr/src/new/jove/vars.c line 25

CurAskPtr defined in line 63; used 12 times

- in line 100, 171-172(2), 204-209(8), 231

DispBadFs defined in line 340; used 4 times

- in line 377, 418, 529
- in /usr/src/new/jove/vars.c line 36

Minibuf defined in line 62; used 2 times

- in line 244, 256

fc_filebase defined in line 339; used 17 times

- in line 375, 383-385(4), 437-439(2), 471-488(10)

private defined in line 145; never used

#### Defined macros

private defined in line 55; used 14 times

- in line 23-48(9), 54, 63-64(2), 108, 402

Last modified: 1988-08-11 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1462 |