home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / editor / beav / echo.c < prev    next >
C/C++ Source or Header  |  1994-01-30  |  8KB  |  453 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. bool ereply ();
  12. bool 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. extern char MSG_hit_key[];
  23.  
  24. int epresf = FALSE;        /* Stuff in echo line flag. */
  25.  
  26. /*
  27. * Erase the echo line.
  28. */
  29. void
  30. eerase ()
  31. {
  32.     writ_echo (MSG_null);    /* clear the echo line */
  33.     epresf = FALSE;
  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. bool
  44. eyesno (sp)
  45.     char *sp;
  46. {
  47.  
  48.     register bool s;
  49.     char buf[NCOL];
  50.  
  51.     for (;;)
  52.     {
  53.  
  54.     s = ereply (MSG_y_n, buf, sizeof (buf), sp);
  55.     if (s == ABORT)
  56.         return (ABORT);
  57.     if (s != FALSE)
  58.     {
  59.  
  60.         if (buf[0] == 'y' || buf[0] == 'Y')
  61.         return (TRUE);
  62.         if (buf[0] == 'n' || buf[0] == 'N')
  63.         return (FALSE);
  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. bool
  79. ereply (fp, buf, nbuf, arg)
  80.     char *fp;
  81.     char *buf;
  82.     int nbuf;
  83.     char *arg;
  84. {
  85.     return (eread (fp, buf, nbuf, EFNEW | EFCR, arg));
  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. bool
  98. eread (fp, buf, nbuf, flag, ap)
  99.     char *fp;
  100.     char *buf;
  101.     char *ap;
  102.     int nbuf, flag;
  103. {
  104.  
  105.     register int cpos;
  106.     register SYMBOL *sp1;
  107.     register SYMBOL *sp2;
  108.     register int i;
  109.     register int c;
  110.     register int h;
  111.     register int nhits;
  112.     register int nxtra;
  113.     register int bxtra;
  114.  
  115.     int quote_flag;
  116.  
  117.     quote_flag = 0;
  118.     cpos = 0;
  119.     if (kbdmop != NULL)
  120.     {
  121.     /* In a macro.      */
  122.     while ((c = *kbdmop++) != '\0')
  123.         buf[cpos++] = c;
  124.     buf[cpos] = '\0';
  125.     goto done;
  126.     }
  127.  
  128.     if ((flag & EFNEW) != 0 || ttrow != nrow - 1)
  129.     {
  130.  
  131.     ttcolor (CTEXT);
  132.     ttmove (nrow - 1, 0);
  133.     epresf = TRUE;
  134.     }
  135.     else
  136.     eputc (' ');
  137.     eformat (fp, ap);
  138.     tteeol ();
  139.     ttflush ();
  140.     for (;;)
  141.     {
  142.     c = getkey ();
  143.     if (c == ' ' && (flag & EFAUTO) != 0)
  144.     {
  145.         nhits = 0;
  146.         nxtra = HUGE;
  147.         for (h = 0; h < NSHASH; ++h)
  148.         {
  149.         sp1 = symbol[h];
  150.         while (sp1 != NULL)
  151.         {
  152.             for (i = 0; i < cpos; ++i)
  153.             {
  154.             if (buf[i] != sp1->s_name[i])
  155.                 break;
  156.             }
  157.  
  158.             if (i == cpos)
  159.             {
  160.             if (nhits == 0)
  161.                 sp2 = sp1;
  162.             ++nhits;
  163.             bxtra = getxtra (sp1, sp2, cpos);
  164.             if (bxtra < nxtra)
  165.                 nxtra = bxtra;
  166.             }
  167.  
  168.             sp1 = sp1->s_symp;
  169.         }
  170.         }
  171.  
  172.         if (nhits == 0)    /* No completion.   */
  173.         continue;
  174.         for (i = 0; i < nxtra && cpos < nbuf - 1; ++i)
  175.         {
  176.         c = sp2->s_name[cpos];
  177.         buf[cpos++] = c;
  178.         eputc (c);
  179.         }
  180.  
  181.         ttflush ();
  182.         if (nhits != 1)    /* Fake a CR if there   */
  183.         continue;    /* is 1 choice.     */
  184.         c = (KCTRL | 'M');
  185.     }
  186.     if (quote_flag)
  187.     {
  188.         c = c & 0x1f;
  189.         quote_flag = 0;
  190.     }
  191.  
  192.  
  193.     switch (c)
  194.     {
  195.     case (KCTRL | 'Q'):
  196.         quote_flag = 1;
  197.         break;
  198.     case (KCTRL | 'M'):    /* Return, done.    */
  199.         case (KCTRL | 'J'):    /* Linefeed, done.  */
  200.         buf[cpos] = '\0';
  201.         if (kbdmip != NULL)
  202.         {
  203.         if (kbdmip + cpos + 1 > &kbdm[NKBDM - 3])
  204.         {
  205.             (void) ctrlg (FALSE, 0, KRANDOM);
  206.             ttflush ();
  207.             return (ABORT);
  208.         }
  209.  
  210.         for (i = 0; i < cpos; ++i)
  211.             *kbdmip++ = buf[i];
  212.         *kbdmip++ = '\0';
  213.         }
  214.  
  215.         if ((flag & EFCR) != 0)
  216.         {
  217.         ttputc (0x0D);
  218.         ttflush ();
  219.         }
  220.  
  221.         goto done;
  222.  
  223.     case (KCTRL | 'G'):    /* Bell, abort.     */
  224.         eputc (0x07);
  225.         (void) ctrlg (FALSE, 0, KRANDOM);
  226.         ttflush ();
  227.         return (ABORT);
  228.  
  229.     case 0x7F:        /* Rubout, erase.   */
  230.     case (KCTRL | 'H'):    /* Backspace, erase.    */
  231.         if (cpos != 0)
  232.         {
  233.         ttputc ('\b');
  234.         ttputc (' ');
  235.         ttputc ('\b');
  236.         --ttcol;
  237.         if (ISCTRL (buf[--cpos]) != FALSE)
  238.         {
  239.             ttputc ('\b');
  240.             ttputc (' ');
  241.             ttputc ('\b');
  242.             --ttcol;
  243.         }
  244.  
  245.         ttflush ();
  246.         }
  247.         break;
  248.  
  249.     case (KCTRL | 'U'):    /* C-U, kill line.  */
  250.         while (cpos != 0)
  251.         {
  252.         ttputc ('\b');
  253.         ttputc (' ');
  254.         ttputc ('\b');
  255.         --ttcol;
  256.         if (ISCTRL (buf[--cpos]) != FALSE)
  257.         {
  258.             ttputc ('\b');
  259.             ttputc (' ');
  260.             ttputc ('\b');
  261.             --ttcol;
  262.         }
  263.  
  264.         }
  265.  
  266.         ttflush ();
  267.         break;
  268.  
  269.     default:        /* All the rest.    */
  270.         if ((cpos < nbuf - 1) && ((c & ~KCHAR) == 0))
  271.         {
  272.         buf[cpos++] = c;
  273.         eputc (c);
  274.         ttflush ();
  275.         }
  276.     }            /* End switch */
  277.  
  278.     }
  279.  
  280.   done:
  281.     if (buf[0] == '\0')
  282.     return (FALSE);
  283.     return (TRUE);
  284. }
  285.  
  286. /*
  287. * The "sp1" and "sp2" point to extended command
  288. * symbol table entries. The "cpos" is a horizontal position
  289. * in the name. Return the longest block of characters that can
  290. * be autocompleted at this point. Sometimes the two symbols
  291. * are the same, but this is normal.
  292. */
  293. int
  294. getxtra (sp1, sp2, cpos)
  295.     SYMBOL *sp1;
  296.     SYMBOL *sp2;
  297.     int cpos;
  298. {
  299.  
  300.     register int i;
  301.  
  302.     i = cpos;
  303.     for (;;)
  304.     {
  305.  
  306.     if (sp1->s_name[i] != sp2->s_name[i])
  307.         break;
  308.     if (sp1->s_name[i] == '\0')
  309.         break;
  310.     ++i;
  311.     }
  312.  
  313.     return (i - cpos);
  314. }
  315.  
  316. /*
  317. * Printf style formatting. This is
  318. * called by both "eprintf" and "ereply", to provide
  319. * formatting services to their clients. The move to the
  320. * start of the echo line, and the erase to the end of
  321. * the echo line, is done by the caller.
  322. */
  323. void
  324. eformat (fp, ap)
  325.     char *fp;
  326.     char *ap;
  327. {
  328.  
  329.     register int c;
  330.  
  331.     while ((c = *fp++) != '\0')
  332.     {
  333.  
  334.     if (c != '%')
  335.         eputc (c);
  336.     else
  337.     {
  338.  
  339.         c = *fp++;
  340.         switch (c)
  341.         {
  342.  
  343.         case 'd':
  344.         eputi (*(int *) ap, 10);
  345.         ap += sizeof (int);
  346.         break;
  347.  
  348.         case 'x':        /* krw */
  349.         eputi (*(int *) ap, 16);
  350.         ap += sizeof (int);
  351.         break;
  352.  
  353.         case 'o':
  354.         eputi (*(int *) ap, 8);
  355.         ap += sizeof (int);
  356.         break;
  357.  
  358.         case 's':
  359.         eputs (ap);
  360.         ap += sizeof (char *);
  361.         break;
  362.  
  363.         default:
  364.         eputc (c);
  365.         }
  366.  
  367.     }
  368.  
  369.     }
  370.  
  371. }
  372.  
  373. /*
  374. * Put integer, in radix "r".
  375. */
  376. void
  377. eputi (i, r)
  378.     int i;
  379.     int r;
  380. {
  381.     static char *convert =
  382.     {
  383.     MSG_hex_dig
  384.     };
  385.  
  386.  
  387.     register int q;
  388.  
  389.     if ((q = i / r) != 0)
  390.     eputi (q, r);
  391.     eputc (convert[i % r]);
  392.  
  393. }
  394.  
  395. /*
  396. * Put string.
  397. */
  398. void
  399. eputs (s)
  400.     char *s;
  401. {
  402.     register int c;
  403.  
  404.     while ((c = *s++) != '\0')
  405.     eputc (c);
  406. }
  407.  
  408. /*
  409. * Put character. Watch for
  410. * control characters, and for the line
  411. * getting too long.
  412. */
  413. void
  414. eputc (c)
  415.     int c;
  416. {
  417.  
  418.     if (ttcol < ncol)
  419.     {
  420.  
  421.     if (ISCTRL (c) != FALSE)
  422.     {
  423.  
  424.         eputc ('^');
  425.         c ^= 0x40;
  426.     }
  427.  
  428.     ttputc (c);
  429.     ++ttcol;
  430.     }
  431.  
  432. }
  433.  
  434. /*
  435.  *   Print warning message and wait for the user to hit a key.
  436.  */
  437. void
  438. err_echo (buf)
  439.     char *buf;
  440. {
  441.     char ch[NCOL * 2];
  442.  
  443.     strcpy (ch, buf);
  444.     strcat (ch, MSG_hit_key);
  445.     writ_echo (ch);
  446.     ttbeep ();
  447.     while (ttgetc () != CTL_G);
  448.     {
  449.     ttbeep ();
  450.     ttflush ();
  451.     }
  452. }
  453.