Logo Search packages:      
Sourcecode: beav version File versions  Download package

echo.c

/*
*       Echo line reading and writing.
* Common routines for reading
* and writing characters in the echo line area
* of the display screen. Used by the entire
* known universe.
*/
#include    "def.h"

void eerase ();
char ereply ();
char eread ();
void eformat ();
void eputi ();
void eputs ();
void eputc ();


extern char MSG_null[];
extern char MSG_y_n[];
extern char MSG_hex_dig[];
extern char MSG_hit_key[];

int epresf = FALSE;           /* Stuff in echo line flag. */

/*
* Erase the echo line.
*/
void
eerase ()
{
    writ_echo (MSG_null);     /* clear the echo line */
    epresf = FALSE;
}

/*
* Ask "yes" or "no" question.
* Return ABORT if the user answers the question
* with the abort ("^G") character. Return FALSE
* for "no" and TRUE for "yes". No formatting
* services are available.
*/
char
eyesno (sp)
    char *sp;
{

    register char s;
    char buf[NCOL];

    for (;;)
    {

      s = ereply (MSG_y_n, buf, sizeof (buf), sp);
      if (s == ABORT)
          return (ABORT);
      if (s != FALSE)
      {

          if (buf[0] == 'y' || buf[0] == 'Y')
            return (TRUE);
          if (buf[0] == 'n' || buf[0] == 'N')
            return (FALSE);
      }

    }

}

/*
* Write out a prompt, and read back a
* reply. The prompt is now written out with full "eprintf"
* formatting, although the arguments are in a rather strange
* place. This is always a new message, there is no auto
* completion, and the return is echoed as such.
*/
/* VARARGS3 */
char
ereply (fp, buf, nbuf, arg)
    char *fp;
    char *buf;
    int nbuf;
    char *arg;
{
    return (eread (fp, buf, nbuf, EFNEW | EFCR, arg));
}

/*
* This is the general "read input from the
* echo line" routine. The basic idea is that the prompt
* string "prompt" is written to the echo line, and a one
* line reply is read back into the supplied "buf" (with
* maximum length "len"). The "flag" contains EFNEW (a
* new prompt), an EFAUTO (autocomplete), or EFCR (echo
* the carriage return as CR).
*/
char
eread (fp, buf, nbuf, flag, ap)
    char *fp;
    char *buf;
    char *ap;
    int nbuf, flag;
{

    register int cpos;
    register SYMBOL *sp1;
    register SYMBOL *sp2;
    register int i;
    register int c;
    register int h;
    register int nhits;
    register int nxtra;
    register int bxtra;

    int quote_flag;

    quote_flag = 0;
    cpos = 0;
    if (kbdmop != NULL)
    {
      /* In a macro.      */
      while ((c = *kbdmop++) != '\0')
          buf[cpos++] = c;
      buf[cpos] = '\0';
      goto done;
    }

    if ((flag & EFNEW) != 0 || ttrow != nrow - 1)
    {

      ttcolor (CTEXT);
      ttmove (nrow - 1, 0);
      epresf = TRUE;
    }
    else
      eputc (' ');
    eformat (fp, ap);
    tteeol ();
    ttflush ();
    for (;;)
    {
      c = getkey ();
      if (c == ' ' && (flag & EFAUTO) != 0)
      {
          nhits = 0;
          nxtra = HUGE;
          for (h = 0; h < NSHASH; ++h)
          {
            sp1 = symbol[h];
            while (sp1 != NULL)
            {
                for (i = 0; i < cpos; ++i)
                {
                  if (buf[i] != sp1->s_name[i])
                      break;
                }

                if (i == cpos)
                {
                  if (nhits == 0)
                      sp2 = sp1;
                  ++nhits;
                  bxtra = getxtra (sp1, sp2, cpos);
                  if (bxtra < nxtra)
                      nxtra = bxtra;
                }

                sp1 = sp1->s_symp;
            }
          }

          if (nhits == 0)     /* No completion.   */
            continue;
          for (i = 0; i < nxtra && cpos < nbuf - 1; ++i)
          {
            c = sp2->s_name[cpos];
            buf[cpos++] = c;
            eputc (c);
          }

          ttflush ();
          if (nhits != 1)     /* Fake a CR if there   */
            continue;   /* is 1 choice.     */
          c = (KCTRL | 'M');
      }
      if (quote_flag)
      {
          c = c & 0x1f;
          quote_flag = 0;
      }


      switch (c)
      {
      case (KCTRL | 'Q'):
          quote_flag = 1;
          break;
      case (KCTRL | 'M'):     /* Return, done.    */
      case (KCTRL | 'J'):     /* Linefeed, done.  */
          buf[cpos] = '\0';
          if (kbdmip != NULL)
          {
            if (kbdmip + cpos + 1 > &kbdm[NKBDM - 3])
            {
                (void) ctrlg (FALSE, 0, KRANDOM);
                ttflush ();
                return (ABORT);
            }

            for (i = 0; i < cpos; ++i)
                *kbdmip++ = buf[i];
            *kbdmip++ = '\0';
          }

          if ((flag & EFCR) != 0)
          {
            ttputc (0x0D);
            ttflush ();
          }

          goto done;

      case (KCTRL | 'G'):     /* Bell, abort.     */
          eputc (0x07);
          (void) ctrlg (FALSE, 0, KRANDOM);
          ttflush ();
          return (ABORT);

      case 0x7F:        /* Rubout, erase.   */
      case (KCTRL | 'H'):     /* Backspace, erase.    */
          if (cpos != 0)
          {
            ttputc ('\b');
            ttputc (' ');
            ttputc ('\b');
            --ttcol;
            if (ISCTRL (buf[--cpos]) != FALSE)
            {
                ttputc ('\b');
                ttputc (' ');
                ttputc ('\b');
                --ttcol;
            }

            ttflush ();
          }
          break;

      case (KCTRL | 'U'):     /* C-U, kill line.  */
          while (cpos != 0)
          {
            ttputc ('\b');
            ttputc (' ');
            ttputc ('\b');
            --ttcol;
            if (ISCTRL (buf[--cpos]) != FALSE)
            {
                ttputc ('\b');
                ttputc (' ');
                ttputc ('\b');
                --ttcol;
            }

          }

          ttflush ();
          break;

      default:          /* All the rest.    */
          if ((cpos < nbuf - 1) && ((c & ~KCHAR) == 0))
          {
            buf[cpos++] = c;
            eputc (c);
            ttflush ();
          }
      }                 /* End switch */

    }

  done:
    if (buf[0] == '\0')
      return (FALSE);
    return (TRUE);
}

/*
* The "sp1" and "sp2" point to extended command
* symbol table entries. The "cpos" is a horizontal position
* in the name. Return the longest block of characters that can
* be autocompleted at this point. Sometimes the two symbols
* are the same, but this is normal.
*/
int
getxtra (sp1, sp2, cpos)
    SYMBOL *sp1;
    SYMBOL *sp2;
    int cpos;
{

    register int i;

    i = cpos;
    for (;;)
    {

      if (sp1->s_name[i] != sp2->s_name[i])
          break;
      if (sp1->s_name[i] == '\0')
          break;
      ++i;
    }

    return (i - cpos);
}

/*
* Printf style formatting. This is
* called by both "eprintf" and "ereply", to provide
* formatting services to their clients. The move to the
* start of the echo line, and the erase to the end of
* the echo line, is done by the caller.
*/
void
eformat (fp, ap)
    char *fp;
    char *ap;
{

    register int c;

    while ((c = *fp++) != '\0')
    {

      if (c != '%')
          eputc (c);
      else
      {

          c = *fp++;
          switch (c)
          {

          case 'd':
            eputi (*(int *) ap, 10);
            ap += sizeof (int);
            break;

          case 'x':           /* krw */
            eputi (*(int *) ap, 16);
            ap += sizeof (int);
            break;

          case 'o':
            eputi (*(int *) ap, 8);
            ap += sizeof (int);
            break;

          case 's':
            eputs (ap);
            ap += sizeof (char *);
            break;

          default:
            eputc (c);
          }

      }

    }

}

/*
* Put integer, in radix "r".
*/
void
eputi (i, r)
    int i;
    int r;
{
    static char *convert =
    {
      MSG_hex_dig
    };


    register int q;

    if ((q = i / r) != 0)
      eputi (q, r);
    eputc (convert[i % r]);

}

/*
* Put string.
*/
void
eputs (s)
    char *s;
{
    register int c;

    while ((c = *s++) != '\0')
      eputc (c);
}

/*
* Put character. Watch for
* control characters, and for the line
* getting too long.
*/
void
eputc (c)
    int c;
{

    if (ttcol < ncol)
    {

      if (ISCTRL (c) != FALSE)
      {

          eputc ('^');
          c ^= 0x40;
      }

      ttputc (c);
      ++ttcol;
    }

}

/*
 *   Print warning message and wait for the user to hit a key.
 */
void
err_echo (buf)
    char *buf;
{
    char ch[NCOL * 2];

    strcpy (ch, buf);
    strcat (ch, MSG_hit_key);
    writ_echo (ch);
    ttbeep ();
    while (ttgetc () != CTL_G);
    {
      ttbeep ();
      ttflush ();
    }
}

Generated by  Doxygen 1.6.0   Back to index