home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 8 / FreshFishVol8-CD1.bin / gnu / src / baseline / jove-4.14.6.lha / jove-4.14.6 / ask.c < prev    next >
C/C++ Source or Header  |  1992-01-10  |  12KB  |  567 lines

  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 "chars.h"
  12. #include "disp.h"
  13. #include "fp.h"
  14. #include "scandir.h"
  15.  
  16. #include <signal.h>
  17.  
  18. #ifdef    MAC
  19. # include "mac.h"
  20. #else    /* !MAC */
  21. # ifdef    STDARGS
  22. #  include <stdarg.h>
  23. # else
  24. #  include <varargs.h>
  25. # endif
  26. # ifdef    F_COMPLETION
  27. #  include <sys/stat.h>
  28. # endif
  29. #endif    /* !MAC */
  30.  
  31. int    AbortChar = CTL('G');
  32. bool    DoEVexpand = NO;    /* should we expand evironment variables? */
  33.  
  34. bool    Asking = NO;
  35. int    AskingWidth;
  36.  
  37. char    Minibuf[LBSIZE];
  38. private Line    *CurAskPtr = NULL;    /* points at some line in mini-buffer */
  39. private Buffer    *AskBuffer = NULL;    /* Askbuffer points to actual structure */
  40.  
  41. /* The way the mini-buffer works is this:  The first line of the mini-buffer
  42.    is where the user does his stuff.  The rest of the buffer contains
  43.    strings that the user often wants to use, for instance, file names, or
  44.    common search strings, etc.  If he types C-N or C-P while in ask(), we
  45.    bump the point up or down a line and extract the contents (we make sure
  46.    is somewhere in the mini-buffer). */
  47.  
  48. private Buffer *
  49. get_minibuf()
  50. {
  51.     if (AskBuffer) {        /* make sure ut still exists */
  52.         register Buffer    *b;
  53.  
  54.         for (b = world; b != NULL; b = b->b_next)
  55.             if (b == AskBuffer)
  56.                 return b;
  57.     }
  58.     AskBuffer = do_select((Window *)NULL, "*minibuf*");
  59.     AskBuffer->b_type = B_SCRATCH;
  60.     return AskBuffer;
  61. }
  62.  
  63. /* Add a string to the mini-buffer. */
  64.  
  65. void
  66. minib_add(str, movedown)
  67. char    *str;
  68. bool    movedown;
  69. {
  70.     register Buffer    *saveb = curbuf;
  71.  
  72.     SetBuf(get_minibuf());
  73.     LineInsert(1);
  74.     ins_str(str, NO);
  75.     if (movedown)
  76.         CurAskPtr = curline;
  77.     SetBuf(saveb);
  78. }
  79.  
  80. /* look for any substrings of the form $foo in linebuf, and expand
  81.    them according to their value in the environment (if possible) -
  82.    this munges all over curchar and linebuf without giving it a second
  83.    thought (I must be getting lazy in my old age) */
  84. private void
  85. EVexpand()
  86. {
  87.     register int    c;
  88.     register char    *lp = linebuf,
  89.             *ep;
  90.     char    varname[128],
  91.         *vp,
  92.         *lp_start;
  93.     Mark    *m = MakeMark(curline, curchar, M_FLOATER);
  94.  
  95.     while ((c = *lp++) != '\0') {
  96.         if (c != '$')
  97.             continue;
  98.         lp_start = lp - 1;    /* the $ */
  99.         vp = varname;
  100.         while ((c = *lp++) != '\0') {
  101.             if (!jisword(c))
  102.                 break;
  103.             *vp++ = c;
  104.         }
  105.         *vp = '\0';
  106.         /* if we find an env. variable with the right
  107.            name, we insert it in linebuf, and then delete
  108.            the variable name that we're replacing - and
  109.            then we continue in case there are others ... */
  110.         if ((ep = getenv(varname)) != NULL) {
  111.             curchar = lp_start - linebuf;
  112.             ins_str(ep, NO);
  113.             del_char(FORWARD, (int)strlen(varname) + 1, NO);
  114.             lp = linebuf + curchar;
  115.         }
  116.     }
  117.     ToMark(m);
  118.     DelMark(m);
  119. }
  120.  
  121. bool    InRealAsk = NO;
  122.  
  123. private char *
  124. real_ask(delim, d_proc, def, prompt)
  125. char    *delim,
  126.     *def,
  127.     *prompt;
  128. bool    (*d_proc) proto((int));
  129. {
  130.     jmp_buf    savejmp;
  131.     int    c,
  132.         prompt_len;
  133.     Buffer    *saveb = curbuf;
  134.     volatile int    aborted = NO;
  135.     int    no_typed = NO;
  136.     data_obj    *push_cmd = LastCmd;
  137.     int    o_a_v = arg_value(),
  138.         o_i_an_a = is_an_arg();
  139. #ifdef    MAC
  140.         menus_off();
  141. #endif
  142.  
  143.     if (InRealAsk)
  144.         complain((char *) NULL);
  145.     push_env(savejmp);
  146.     InRealAsk = YES;
  147.     SetBuf(get_minibuf());
  148.     if (!inlist(AskBuffer->b_first, CurAskPtr))
  149.         CurAskPtr = curline;
  150.     prompt_len = strlen(prompt);
  151.     ToFirst();    /* Beginning of buffer. */
  152.     linebuf[0] = '\0';
  153.     modify();
  154.     makedirty(curline);
  155.  
  156.     if (setjmp(mainjmp)) {
  157.         if (InJoverc) {        /* this is a kludge */
  158.             aborted = YES;
  159.             goto cleanup;
  160.         }
  161.     }
  162.  
  163.     for (;;) {
  164.         clr_arg_value();
  165.         last_cmd = this_cmd;
  166.         init_strokes();
  167. cont:
  168.         s_mess("%s%s", prompt, linebuf);
  169.         Asking = YES;
  170.         AskingWidth = curchar + prompt_len;
  171.         c = getch();
  172.  
  173.         if ((c == EOF) || (c != '\0' && strchr(delim, c) != NULL)) {
  174.             if (DoEVexpand)
  175.                 EVexpand();
  176.             if (d_proc == (bool(*) proto((int)))NULL || !(*d_proc)(c))
  177.                 break;
  178.         } else if (c == AbortChar) {
  179.             message("[Aborted]");
  180.             aborted = YES;
  181.             break;
  182.         } else switch (c) {
  183.         case CTL('N'):
  184.         case CTL('P'):
  185.             case CTL('U'):          /* Allow ^U as a synonym for ^P */
  186.             if (CurAskPtr != NULL) {
  187.                 int    n = (c == CTL('P') ? -arg_value() : arg_value());
  188.                 CurAskPtr = next_line(CurAskPtr, n);
  189.                 if (CurAskPtr == curbuf->b_first && CurAskPtr->l_next != NULL)
  190.                     CurAskPtr = CurAskPtr->l_next;
  191.                 (void) ltobuf(CurAskPtr, linebuf);
  192.                 modify();
  193.                 makedirty(curline);
  194.                 Eol();
  195.                 this_cmd = 0;
  196.             }
  197.             break;
  198.  
  199.         case CTL('R'):
  200.             if (def)
  201.                 ins_str(def, NO);
  202.             else
  203.                 rbell();
  204.             break;
  205.  
  206.         default:
  207.             dispatch(c);
  208.             break;
  209.         }
  210.         if (curbuf != AskBuffer)
  211.             SetBuf(AskBuffer);
  212.         if (curline != curbuf->b_first) {
  213.             CurAskPtr = curline;
  214.             curline = curbuf->b_first;    /* with whatever is in linebuf */
  215.         }
  216.         if (this_cmd == ARG_CMD)
  217.             goto cont;
  218.     }
  219. cleanup:
  220.     pop_env(savejmp);
  221.  
  222.     LastCmd = push_cmd;
  223.     set_arg_value(o_a_v);
  224.     set_is_an_arg(o_i_an_a);
  225.     no_typed = (linebuf[0] == '\0');
  226.     strcpy(Minibuf, linebuf);
  227.     SetBuf(saveb);
  228.     InRealAsk = Asking = Interactive = NO;
  229.     if (!aborted) {
  230.         if (!charp()) {
  231.             Placur(ILI, 0);
  232.             flushscreen();
  233.         }
  234.         if (no_typed)
  235.             return NULL;
  236.     } else
  237.         complain(mesgbuf);
  238.     return Minibuf;
  239. }
  240.  
  241. #ifdef    STDARGS
  242.     char *
  243. ask(char *def, char *fmt,...)
  244. #else
  245.     /*VARARGS2*/ char *
  246. ask(def, fmt, va_alist)
  247.     char    *def,
  248.         *fmt;
  249.     va_dcl
  250. #endif
  251. {
  252.     char    prompt[128];
  253.     char    *ans;
  254.     va_list    ap;
  255.  
  256.     va_init(ap, fmt);
  257.     format(prompt, sizeof prompt, fmt, ap);
  258.     va_end(ap);
  259.     ans = real_ask("\r\n", (bool (*) proto((int))) NULL, def, prompt);
  260.     if (ans == NULL) {        /* Typed nothing. */
  261.         if (def == NULL)
  262.             complain("[No default]");
  263.         return def;
  264.     }
  265.     return ans;
  266. }
  267.  
  268. #ifdef    STDARGS
  269. char *
  270. do_ask(char *delim, bool (*d_proc) proto((int)), char *def, const char *fmt,...)
  271. #else
  272. /*VARARGS4*/ char *
  273. do_ask(delim, d_proc, def, fmt, va_alist)
  274.     char    *delim,
  275.         *def;
  276.     const char    *fmt;
  277.     bool    (*d_proc) proto((int));
  278.     va_dcl
  279. #endif
  280. {
  281.     char    prompt[128];
  282.     va_list    ap;
  283.  
  284.     va_init(ap, fmt);
  285.     format(prompt, sizeof prompt, fmt, ap);
  286.     va_end(ap);
  287.     return real_ask(delim, d_proc, def, prompt);
  288. }
  289.  
  290. #ifdef    STDARGS
  291.     int
  292. yes_or_no_p(char *fmt, ...)
  293. #else
  294.     /*VARARGS1*/ int
  295. yes_or_no_p(fmt, va_alist)
  296.     char    *fmt;
  297.     va_dcl
  298. #endif
  299. {
  300.     char    prompt[128];
  301.     int    c;
  302.     va_list    ap;
  303.  
  304.     va_init(ap, fmt);
  305.     format(prompt, sizeof prompt, fmt, ap);
  306.     va_end(ap);
  307.     for (;;) {
  308.         message(prompt);
  309.         Asking = YES;    /* so redisplay works */
  310.         AskingWidth = strlen(prompt);
  311.         c = getch();
  312.         Asking = NO;
  313.         if (c == AbortChar)
  314.             complain("[Aborted]");
  315.         switch (CharUpcase(c)) {
  316.         case 'Y':
  317.             return YES;
  318.  
  319.         case 'N':
  320.             return NO;
  321.  
  322.         default:
  323.             add_mess("[Type Y or N]");
  324.             SitFor(10);
  325.         }
  326.     }
  327.     /* NOTREACHED */
  328. }
  329.  
  330. #ifdef    F_COMPLETION
  331.  
  332. private char    *fc_filebase;
  333. bool    DispBadFs = YES;    /* display bad file names? */
  334. # ifndef    MSDOS
  335. char    BadExtensions[128] = ".o";
  336. # else    /* MSDOS */
  337. char    BadExtensions[128] = ".obj .exe .com .bak .arc .lib .zoo";
  338. # endif    /* MSDOS */
  339.  
  340. private int
  341. bad_extension(name)
  342. char    *name;
  343. {
  344.     char    *ip,
  345.         *bads;
  346.     size_t    namelen = strlen(name),
  347.         ext_len;
  348.  
  349. #ifdef    UNIX
  350.     if (strcmp(name, ".")==0 || strcmp(name, "..")==0)
  351.         return YES;
  352. #endif
  353.     for (ip=bads=BadExtensions; *ip!='\0'; bads = ip+1) {
  354.         if ((ip = strchr(bads, ' ')) == NULL)
  355.             ip = bads + strlen(bads);
  356.         ext_len = ip - bads;
  357.         if (ext_len != 0 && ext_len < namelen &&
  358.             (strncmp(&name[namelen - ext_len], bads, ext_len) == 0))
  359.             return YES;
  360.     }
  361.     return NO;
  362. }
  363.  
  364. private int
  365. f_match(file)
  366. char    *file;
  367. {
  368.     int    len = strlen(fc_filebase);
  369.  
  370.     if (!DispBadFs && bad_extension(file))
  371.         return NO;
  372.  
  373.     return ((len == 0) ||
  374. #ifdef    MSDOS
  375.         (casencmp(file, fc_filebase, strlen(fc_filebase)) == 0)
  376. #else
  377.         (strncmp(file, fc_filebase, strlen(fc_filebase)) == 0)
  378. #endif
  379.         );
  380. }
  381.  
  382. private int
  383. isdir(name)
  384. char    *name;
  385. {
  386.     struct stat    stbuf;
  387.     char    filebuf[FILESIZE];
  388.  
  389.     PathParse(name, filebuf);
  390.     return ((stat(filebuf, &stbuf) != -1) &&
  391.         (stbuf.st_mode & S_IFDIR) == S_IF