home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 2 / 2873 / echo.c next >
Encoding:
C/C++ Source or Header  |  1991-02-28  |  9.2 KB  |  429 lines

  1. /*
  2. *       Echo line reading and writing.
  3. * Common routines for reading
  4. * and writing characters in the echo line area
  5. * of the display screen. Used by the entire
  6. * known universe.
  7. */
  8. #include    "def.h"
  9.  
  10. void    eerase ();
  11. char    ereply ();
  12. char    eread ();
  13. void    eformat ();
  14. void    eputi ();
  15. void    eputs ();
  16. void    eputc ();
  17.  
  18.  
  19. extern    char    MSG_null[];
  20. extern    char    MSG_y_n[];
  21. extern    char    MSG_hex_dig[];
  22.  
  23. #include    "lintfunc.dec"
  24. int     epresf = FALSE;         /* Stuff in echo line flag. */
  25.  
  26. /*
  27. * Erase the echo line.
  28. */
  29. void eerase ()
  30. {
  31.     writ_echo (MSG_null);  /* clear the echo line */
  32.     epresf = FALSE;
  33. }
  34.  
  35.  
  36. /*
  37. * Ask "yes" or "no" question.
  38. * Return ABORT if the user answers the question
  39. * with the abort ("^G") character. Return FALSE
  40. * for "no" and TRUE for "yes". No formatting
  41. * services are available.
  42. */
  43. char    eyesno (sp)
  44. char   *sp;
  45. {
  46.  
  47.     register char   s;
  48.     char    buf[64];
  49.  
  50.     for (;;)
  51.         {
  52.  
  53.         s = ereply (MSG_y_n, buf, sizeof (buf), sp);
  54.         if (s == ABORT)
  55.             return (ABORT);
  56.         if (s != FALSE)
  57.             {
  58.  
  59.             if (buf[0] == 'y' || buf[0] == 'Y')
  60.                 return (TRUE);
  61.             if (buf[0] == 'n' || buf[0] == 'N')
  62.                 return (FALSE);
  63.             }
  64.  
  65.         }
  66.  
  67. }
  68.  
  69.  
  70. /*
  71. * Write out a prompt, and read back a
  72. * reply. The prompt is now written out with full "eprintf"
  73. * formatting, although the arguments are in a rather strange
  74. * place. This is always a new message, there is no auto
  75. * completion, and the return is echoed as such.
  76. */
  77. /* VARARGS3 */
  78. char    ereply (fp, buf, nbuf, arg)
  79. char   *fp;
  80. char   *buf;
  81. int     nbuf;
  82. char   *arg;
  83. {
  84.     return (eread (fp, buf, nbuf, EFNEW | EFCR, arg));
  85. }
  86.  
  87.  
  88. /*
  89. * This is the general "read input from the
  90. * echo line" routine. The basic idea is that the prompt
  91. * string "prompt" is written to the echo line, and a one
  92. * line reply is read back into the supplied "buf" (with
  93. * maximum length "len"). The "flag" contains EFNEW (a
  94. * new prompt), an EFAUTO (autocomplete), or EFCR (echo
  95. * the carriage return as CR).
  96. */
  97. char    eread (fp, buf, nbuf, flag, ap)
  98. char   *fp;
  99. char   *buf;
  100. char   *ap;
  101. {
  102.  
  103.     register int    cpos;
  104.     register    SYMBOL * sp1;
  105.     register    SYMBOL * sp2;
  106.     register int    i;
  107.     register int    c;
  108.     register int    h;
  109.     register int    nhits;
  110.     register int    nxtra;
  111.     register int    bxtra;
  112.  
  113.     int     quote_flag;
  114.  
  115.     quote_flag = 0;
  116.     cpos = 0;
  117.     if (kbdmop != NULL)
  118.         {
  119.     /* In a macro.      */
  120.         while ((c = *kbdmop++) != '\0')
  121.             buf[cpos++] = c;
  122.         buf[cpos] = '\0';
  123.         goto done;
  124.         }
  125.  
  126.     if ((flag & EFNEW) != 0 || ttrow != nrow - 1)
  127.         {
  128.  
  129.         ttcolor (CTEXT);
  130.         ttmove (nrow - 1, 0);
  131.         epresf = TRUE;
  132.         }
  133.     else
  134.         eputc (' ');
  135.     eformat (fp, ap);
  136.     tteeol ();
  137.     ttflush ();
  138.     for (;;)
  139.         {
  140.         c = getkey ();
  141.         if (c == ' ' && (flag & EFAUTO) != 0)
  142.             {
  143.             nhits = 0;
  144.             nxtra = HUGE;
  145.             for (h = 0; h < NSHASH; ++h)
  146.                 {
  147.                 sp1 = symbol[h];
  148.                 while (sp1 != NULL)
  149.                     {
  150.                     for (i = 0; i < cpos; ++i)
  151.                         {
  152.                         if (buf[i] != sp1 -> s_name[i])
  153.                             break;
  154.                         }
  155.  
  156.                     if (i == cpos)
  157.                         {
  158.                         if (nhits == 0)
  159.                             sp2 = sp1;
  160.                         ++nhits;
  161.                         bxtra = getxtra (sp1, sp2, cpos);
  162.                         if (bxtra < nxtra)
  163.                             nxtra = bxtra;
  164.                         }
  165.  
  166.                     sp1 = sp1 -> s_symp;
  167.                     }
  168.                 }
  169.  
  170.             if (nhits == 0)     /* No completion.   */
  171.                 continue;
  172.             for (i = 0; i < nxtra && cpos < nbuf - 1; ++i)
  173.                 {
  174.                 c = sp2 -> s_name[cpos];
  175.                 buf[cpos++] = c;
  176.                 eputc (c);
  177.                 }
  178.  
  179.             ttflush ();
  180.             if (nhits != 1)     /* Fake a CR if there   */
  181.                 continue;       /* is 1 choice.     */
  182.             c = (KCTRL | 'M');
  183.             }
  184.         if (quote_flag)
  185.             {
  186.             c = c & 0x1f;
  187.             quote_flag = 0;
  188.             }
  189.  
  190.  
  191.         switch (c)
  192.             {
  193.             case (KCTRL | 'Q'): 
  194.                 quote_flag = 1;
  195.                 break;
  196.             case (KCTRL | 'M'): /* Return, done.    */
  197.                 buf[cpos] = '\0';
  198.                 if (kbdmip != NULL)
  199.                     {
  200.                     if (kbdmip + cpos + 1 > &kbdm[NKBDM - 3])
  201.                         {
  202.                         (void) ctrlg (FALSE, 0, KRANDOM);
  203.                         ttflush ();
  204.                         return (ABORT);
  205.                         }
  206.  
  207.                     for (i = 0; i < cpos; ++i)
  208.                         *kbdmip++ = buf[i];
  209.                     *kbdmip++ = '\0';
  210.                     }
  211.  
  212.                 if ((flag & EFCR) != 0)
  213.                     {
  214.                     ttputc (0x0D);
  215.                     ttflush ();
  216.                     }
  217.  
  218.                 goto done;
  219.  
  220.             case (KCTRL | 'G'): /* Bell, abort.     */
  221.                 eputc (0x07);
  222.                 (void) ctrlg (FALSE, 0, KRANDOM);
  223.                 ttflush ();
  224.                 return (ABORT);
  225.  
  226.             case 0x7F:          /* Rubout, erase.   */
  227.             case (KCTRL | 'H'): /* Backspace, erase.    */
  228.                 if (cpos != 0)
  229.                     {
  230.                     ttputc ('\b');
  231.                     ttputc (' ');
  232.                     ttputc ('\b');
  233.                     --ttcol;
  234.                     if (ISCTRL (buf[--cpos]) != FALSE)
  235.                         {
  236.                         ttputc ('\b');
  237.                         ttputc (' ');
  238.                         ttputc ('\b');
  239.                         --ttcol;
  240.                         }
  241.  
  242.                     ttflush ();
  243.                     }
  244.                 break;
  245.  
  246.             case (KCTRL | 'U'): /* C-U, kill line.  */
  247.                 while (cpos != 0)
  248.                     {
  249.                     ttputc ('\b');
  250.                     ttputc (' ');
  251.                     ttputc ('\b');
  252.                     --ttcol;
  253.                     if (ISCTRL (buf[--cpos]) != FALSE)
  254.                         {
  255.                         ttputc ('\b');
  256.                         ttputc (' ');
  257.                         ttputc ('\b');
  258.                         --ttcol;
  259.                         }
  260.  
  261.                     }
  262.  
  263.                 ttflush ();
  264.                 break;
  265.  
  266.             default:            /* All the rest.    */
  267.                 if ((cpos < nbuf - 1) && ((c & ~KCHAR) == 0))
  268.                     {
  269.                     buf[cpos++] = c;
  270.                     eputc (c);
  271.                     ttflush ();
  272.                     }
  273.             }                   /* End switch */
  274.  
  275.         }
  276.  
  277. done: 
  278.     if (buf[0] == '\0')
  279.         return (FALSE);
  280.     return (TRUE);
  281. }
  282.  
  283.  
  284. /*
  285. * The "sp1" and "sp2" point to extended command
  286. * symbol table entries. The "cpos" is a horizontal position
  287. * in the name. Return the longest block of characters that can
  288. * be autocompleted at this point. Sometimes the two symbols
  289. * are the same, but this is normal.
  290. */
  291. int     getxtra (sp1, sp2, cpos)
  292. SYMBOL * sp1;
  293. SYMBOL * sp2;
  294. {
  295.  
  296.     register int    i;
  297.  
  298.     i = cpos;
  299.     for (;;)
  300.         {
  301.  
  302.         if (sp1 -> s_name[i] != sp2 -> s_name[i])
  303.             break;
  304.         if (sp1 -> s_name[i] == '\0')
  305.             break;
  306.         ++i;
  307.         }
  308.  
  309.     return (i - cpos);
  310. }
  311.  
  312. /*
  313. * Printf style formatting. This is
  314. * called by both "eprintf" and "ereply", to provide
  315. * formatting services to their clients. The move to the
  316. * start of the echo line, and the erase to the end of
  317. * the echo line, is done by the caller.
  318. */
  319. void eformat (fp, ap)
  320. char  *fp;
  321. char  *ap;
  322. {
  323.  
  324.     register int    c;
  325.  
  326.     while ((c = *fp++) != '\0')
  327.         {
  328.  
  329.         if (c != '%')
  330.             eputc (c);
  331.         else
  332.             {
  333.  
  334.             c = *fp++;
  335.             switch (c)
  336.                 {
  337.  
  338.                 case 'd': 
  339.                     eputi (*(int *) ap, 10);
  340.                     ap += sizeof (int);
  341.                     break;
  342.  
  343.                 case 'x':       /* krw */
  344.                     eputi (*(int *) ap, 16);
  345.                     ap += sizeof (int);
  346.                     break;
  347.  
  348.                 case 'o': 
  349.                     eputi (*(int *) ap, 8);
  350.                     ap += sizeof (int);
  351.                     break;
  352.  
  353.                 case 's': 
  354.                     eputs (ap);
  355.                     ap += sizeof (char *);
  356.                     break;
  357.  
  358.                 default: 
  359.                     eputc (c);
  360.                 }
  361.  
  362.             }
  363.  
  364.         }
  365.  
  366. }
  367.  
  368.  
  369. /*
  370. * Put integer, in radix "r".
  371. */
  372. void eputi (i, r)
  373. int    i;
  374. int    r;
  375. {
  376.     static char *convert =
  377.     {
  378.         MSG_hex_dig
  379.     }
  380.                ;
  381.  
  382.     register int    q;
  383.  
  384.     if ((q = i / r) != 0)
  385.         eputi (q, r);
  386.     eputc (convert[i % r]);
  387.  
  388. }
  389.  
  390.  
  391. /*
  392. * Put string.
  393. */
  394. void eputs (s)
  395. char  *s;
  396. {
  397.     register int    c;
  398.  
  399.     while ((c = *s++) != '\0')
  400.         eputc (c);
  401. }
  402.  
  403.  
  404. /*
  405. * Put character. Watch for
  406. * control characters, and for the line
  407. * getting too long.
  408. */
  409. void eputc (c)
  410. int    c;
  411. {
  412.  
  413.     if (ttcol < ncol)
  414.         {
  415.  
  416.         if (ISCTRL (c) != FALSE)
  417.             {
  418.  
  419.             eputc ('^');
  420.             c ^= 0x40;
  421.             }
  422.  
  423.         ttputc (c);
  424.         ++ttcol;
  425.         }
  426.  
  427. }
  428.  
  429.