]> pd.if.org Git - pd_readline/blobdiff - mg/echo.c
Getting close to a basic working readline now.
[pd_readline] / mg / echo.c
diff --git a/mg/echo.c b/mg/echo.c
deleted file mode 100644 (file)
index ce173f6..0000000
--- a/mg/echo.c
+++ /dev/null
@@ -1,964 +0,0 @@
-/*     $OpenBSD: echo.c,v 1.50 2012/04/12 04:47:59 lum Exp $   */
-
-/* This file is in the public domain. */
-
-/*
- *     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"
-#include "key.h"
-#include "macro.h"
-
-#include "funmap.h"
-
-#include <stdarg.h>
-#include <term.h>
-
-static char    *veread(const char *, char *, size_t, int, va_list);
-static int      complt(int, int, char *, size_t, int, int *);
-static int      complt_list(int, char *, int);
-static void     eformat(const char *, va_list);
-static void     eputi(int, int);
-static void     eputl(long, int);
-static void     eputs(const char *);
-static void     eputc(char);
-static struct list     *copy_list(struct list *);
-
-int            epresf = FALSE;         /* stuff in echo line flag */
-
-/*
- * Erase the echo line.
- */
-void
-eerase(void)
-{
-       ttcolor(CTEXT);
-       ttmove(nrow - 1, 0);
-       tteeol();
-       ttflush();
-       epresf = FALSE;
-}
-
-/*
- * Ask a "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.  No newline
- * required.
- */
-int
-eyorn(const char *sp)
-{
-       int      s;
-
-       if (inmacro)
-               return (TRUE);
-
-       ewprintf("%s? (y or n) ", sp);
-       for (;;) {
-               s = getkey(FALSE);
-               if (s == 'y' || s == 'Y' || s == ' ')
-                       return (TRUE);
-               if (s == 'n' || s == 'N' || s == CCHR('M'))
-                       return (FALSE);
-               if (s == CCHR('G'))
-                       return (ctrlg(FFRAND, 1));
-               ewprintf("Please answer y or n.  %s? (y or n) ", sp);
-       }
-       /* NOTREACHED */
-}
-
-/*
- * Like eyorn, but for more important questions.  User must type all of
- * "yes" or "no" and the trailing newline.
- */
-int
-eyesno(const char *sp)
-{
-       char     buf[64], *rep;
-
-       if (inmacro)
-               return (TRUE);
-
-       rep = eread("%s? (yes or no) ", buf, sizeof(buf),
-           EFNUL | EFNEW | EFCR, sp);
-       for (;;) {
-               if (rep == NULL)
-                       return (ABORT);
-               if (rep[0] != '\0') {
-                       if (macrodef) {
-                               struct line     *lp = maclcur;
-
-                               maclcur = lp->l_bp;
-                               maclcur->l_fp = lp->l_fp;
-                               free(lp);
-                       }
-                       if ((rep[0] == 'y' || rep[0] == 'Y') &&
-                           (rep[1] == 'e' || rep[1] == 'E') &&
-                           (rep[2] == 's' || rep[2] == 'S') &&
-                           (rep[3] == '\0'))
-                               return (TRUE);
-                       if ((rep[0] == 'n' || rep[0] == 'N') &&
-                           (rep[1] == 'o' || rep[0] == 'O') &&
-                           (rep[2] == '\0'))
-                               return (FALSE);
-               }
-               rep = eread("Please answer yes or no.  %s? (yes or no) ",
-                   buf, sizeof(buf), EFNUL | EFNEW | EFCR, sp);
-       }
-       /* NOTREACHED */
-}
-
-/*
- * 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").
- * XXX: When checking for an empty return value, always check rep, *not* buf
- * as buf may be freed in pathological cases.
- */
-/* VARARGS */
-char *
-eread(const char *fmt, char *buf, size_t nbuf, int flag, ...)
-{
-       va_list  ap;
-       char    *rep;
-
-       va_start(ap, flag);
-       rep = veread(fmt, buf, nbuf, flag, ap);
-       va_end(ap);
-       return (rep);
-}
-
-static char *
-veread(const char *fp, char *buf, size_t nbuf, int flag, va_list ap)
-{
-       int      dynbuf = (buf == NULL);
-       int      cpos, epos;            /* cursor, end position in buf */
-       int      c, i, y;
-       int      cplflag = FALSE;       /* display completion list */
-       int      cwin = FALSE;          /* completion list created */
-       int      mr = 0;                /* match left arrow */
-       int      ml = 0;                /* match right arrow */
-       int      esc = 0;               /* position in esc pattern */
-       struct buffer   *bp;                    /* completion list buffer */
-       struct mgwin    *wp;                    /* window for compl list */
-       int      match;                 /* esc match found */
-       int      cc, rr;                /* saved ttcol, ttrow */
-       char    *ret;                   /* return value */
-
-       static char emptyval[] = "";    /* XXX hackish way to return err msg*/
-
-       if (inmacro) {
-               if (dynbuf) {
-                       if ((buf = malloc(maclcur->l_used + 1)) == NULL)
-                               return (NULL);
-               } else if (maclcur->l_used >= nbuf)
-                       return (NULL);
-               bcopy(maclcur->l_text, buf, maclcur->l_used);
-               buf[maclcur->l_used] = '\0';
-               maclcur = maclcur->l_fp;
-               return (buf);
-       }
-       epos = cpos = 0;
-       ml = mr = esc = 0;
-       cplflag = FALSE;
-
-       if ((flag & EFNEW) != 0 || ttrow != nrow - 1) {
-               ttcolor(CTEXT);
-               ttmove(nrow - 1, 0);
-               epresf = TRUE;
-       } else
-               eputc(' ');
-       eformat(fp, ap);
-       if ((flag & EFDEF) != 0) {
-               if (buf == NULL)
-                       return (NULL);
-               eputs(buf);
-               epos = cpos += strlen(buf);
-       }
-       tteeol();
-       ttflush();
-       for (;;) {
-               c = getkey(FALSE);
-               if ((flag & EFAUTO) != 0 && (c == ' ' || c == CCHR('I'))) {
-                       if (cplflag == TRUE) {
-                               complt_list(flag, buf, cpos);
-                               cwin = TRUE;
-                       } else if (complt(flag, c, buf, nbuf, epos, &i) == TRUE) {
-                               cplflag = TRUE;
-                               epos += i;
-                               cpos = epos;
-                       }
-                       continue;
-               }
-               cplflag = FALSE;
-
-               if (esc > 0) { /* ESC sequence started */
-                       match = 0;
-                       if (ml == esc && key_left[ml] && c == key_left[ml]) {
-                               match++;
-                               if (key_left[++ml] == '\0') {
-                                       c = CCHR('B');
-                                       esc = 0;
-                               }
-                       }
-                       if (mr == esc && key_right[mr] && c == key_right[mr]) {
-                               match++;
-                               if (key_right[++mr] == '\0') {
-                                       c = CCHR('F');
-                                       esc = 0;
-                               }
-                       }
-                       if (match == 0) {
-                               esc = 0;
-                               continue;
-                               /* hack. how do we know esc pattern is done? */
-                       }
-                       if (esc > 0) {
-                               esc++;
-                               continue;
-                       }
-               }
-               switch (c) {
-               case CCHR('A'): /* start of line */
-                       while (cpos > 0) {
-                               if (ISCTRL(buf[--cpos]) != FALSE) {
-                                       ttputc('\b');
-                                       --ttcol;
-                               }
-                               ttputc('\b');
-                               --ttcol;
-                       }
-                       ttflush();
-                       break;
-               case CCHR('D'):
-                       if (cpos != epos) {
-                               tteeol();
-                               y = buf[cpos];
-                               epos--;
-                               rr = ttrow;
-                               cc = ttcol;
-                               for (i = cpos; i < epos; i++) {
-                                       buf[i] = buf[i + 1];
-                                       eputc(buf[i]);
-                               }
-                               ttmove(rr, cc);
-                               ttflush();
-                       }
-                       break;
-               case CCHR('E'): /* end of line */
-                       while (cpos < epos) {
-                               eputc(buf[cpos++]);
-                       }
-                       ttflush();
-                       break;
-               case CCHR('B'): /* back */
-                       if (cpos > 0) {
-                               if (ISCTRL(buf[--cpos]) != FALSE) {
-                                       ttputc('\b');
-                                       --ttcol;
-                               }
-                               ttputc('\b');
-                               --ttcol;
-                               ttflush();
-                       }
-                       break;
-               case CCHR('F'): /* forw */
-                       if (cpos < epos) {
-                               eputc(buf[cpos++]);
-                               ttflush();
-                       }
-                       break;
-               case CCHR('Y'): /* yank from kill buffer */
-                       i = 0;
-                       while ((y = kremove(i++)) >= 0 && y != '\n') {
-                               int t;
-                               if (dynbuf && epos + 1 >= nbuf) {
-                                       void *newp;
-                                       size_t newsize = epos + epos + 16;
-                                       if ((newp = realloc(buf, newsize))
-                                           == NULL)
-                                               goto memfail;
-                                       buf = newp;
-                                       nbuf = newsize;
-                               }
-                               if (!dynbuf && epos + 1 >= nbuf) {
-                                       ewprintf("Line too long");
-                                       return (emptyval);
-                               }
-                               for (t = epos; t > cpos; t--)
-                                       buf[t] = buf[t - 1];
-                               buf[cpos++] = (char)y;
-                               epos++;
-                               eputc((char)y);
-                               cc = ttcol;
-                               rr = ttrow;
-                               for (t = cpos; t < epos; t++)
-                                       eputc(buf[t]);
-                               ttmove(rr, cc);
-                       }
-                       ttflush();
-                       break;
-               case CCHR('K'): /* copy here-EOL to kill buffer */
-                       kdelete();
-                       for (i = cpos; i < epos; i++)
-                               kinsert(buf[i], KFORW);
-                       tteeol();
-                       epos = cpos;
-                       ttflush();
-                       break;
-               case CCHR('['):
-                       ml = mr = esc = 1;
-                       break;
-               case CCHR('J'):
-                       c = CCHR('M');
-                       /* FALLTHROUGH */
-               case CCHR('M'):                 /* return, done */
-                       /* if there's nothing in the minibuffer, abort */
-                       if (epos == 0 && !(flag & EFNUL)) {
-                               (void)ctrlg(FFRAND, 0);
-                               ttflush();
-                               return (NULL);
-                       }
-                       if ((flag & EFFUNC) != 0) {
-                               if (complt(flag, c, buf, nbuf, epos, &i)
-                                   == FALSE)
-                                       continue;
-                               if (i > 0)
-                                       epos += i;
-                       }
-                       buf[epos] = '\0';
-                       if ((flag & EFCR) != 0) {
-                               ttputc(CCHR('M'));
-                               ttflush();
-                       }
-                       if (macrodef) {
-                               struct line     *lp;
-
-                               if ((lp = lalloc(cpos)) == NULL)
-                                       goto memfail;
-                               lp->l_fp = maclcur->l_fp;
-                               maclcur->l_fp = lp;
-                               lp->l_bp = maclcur;
-                               maclcur = lp;
-                               bcopy(buf, lp->l_text, cpos);
-                       }
-                       ret = buf;
-                       goto done;
-               case CCHR('G'):                 /* bell, abort */
-                       eputc(CCHR('G'));
-                       (void)ctrlg(FFRAND, 0);
-                       ttflush();
-                       ret = NULL;
-                       goto done;
-               case CCHR('H'):                 /* rubout, erase */
-               case CCHR('?'):
-                       if (cpos != 0) {
-                               y = buf[--cpos];
-                               epos--;
-                               ttputc('\b');
-                               ttcol--;
-                               if (ISCTRL(y) != FALSE) {
-                                       ttputc('\b');
-                                       ttcol--;
-                               }
-                               rr = ttrow;
-                               cc = ttcol;
-                               for (i = cpos; i < epos; i++) {
-                                       buf[i] = buf[i + 1];
-                                       eputc(buf[i]);
-                               }
-                               ttputc(' ');
-                               if (ISCTRL(y) != FALSE) {
-                                       ttputc(' ');
-                                       ttputc('\b');
-                               }
-                               ttputc('\b');
-                               ttmove(rr, cc);
-                               ttflush();
-                       }
-                       break;
-               case CCHR('X'):                 /* kill line */
-               case CCHR('U'):
-                       while (cpos != 0) {
-                               ttputc('\b');
-                               ttputc(' ');
-                               ttputc('\b');
-                               --ttcol;
-                               if (ISCTRL(buf[--cpos]) != FALSE) {
-                                       ttputc('\b');
-                                       ttputc(' ');
-                                       ttputc('\b');
-                                       --ttcol;
-                               }
-                               epos--;
-                       }
-                       ttflush();
-                       break;
-               case CCHR('W'):                 /* kill to beginning of word */
-                       while ((cpos > 0) && !ISWORD(buf[cpos - 1])) {
-                               ttputc('\b');
-                               ttputc(' ');
-                               ttputc('\b');
-                               --ttcol;
-                               if (ISCTRL(buf[--cpos]) != FALSE) {
-                                       ttputc('\b');
-                                       ttputc(' ');
-                                       ttputc('\b');
-                                       --ttcol;
-                               }
-                               epos--;
-                       }
-                       while ((cpos > 0) && ISWORD(buf[cpos - 1])) {
-                               ttputc('\b');
-                               ttputc(' ');
-                               ttputc('\b');
-                               --ttcol;
-                               if (ISCTRL(buf[--cpos]) != FALSE) {
-                                       ttputc('\b');
-                                       ttputc(' ');
-                                       ttputc('\b');
-                                       --ttcol;
-                               }
-                               epos--;
-                       }
-                       ttflush();
-                       break;
-               case CCHR('\\'):
-               case CCHR('Q'):                 /* quote next */
-                       c = getkey(FALSE);
-                       /* FALLTHROUGH */
-               default:
-                       if (dynbuf && epos + 1 >= nbuf) {
-                               void *newp;
-                               size_t newsize = epos + epos + 16;
-                               if ((newp = realloc(buf, newsize)) == NULL)
-                                       goto memfail;
-                               buf = newp;
-                               nbuf = newsize;
-                       }
-                       if (!dynbuf && epos + 1 >= nbuf) {
-                               ewprintf("Line too long");
-                               return (emptyval);
-                       }
-                       for (i = epos; i > cpos; i--)
-                               buf[i] = buf[i - 1];
-                       buf[cpos++] = (char)c;
-                       epos++;
-                       eputc((char)c);
-                       cc = ttcol;
-                       rr = ttrow;
-                       for (i = cpos; i < epos; i++)
-                               eputc(buf[i]);
-                       ttmove(rr, cc);
-                       ttflush();
-               }
-       }
-done:
-       if (cwin == TRUE) {
-               /* blow away cpltion window */
-               bp = bfind("*Completions*", TRUE);
-               if ((wp = popbuf(bp, WEPHEM)) != NULL) {
-                       if (wp->w_flag & WEPHEM) {
-                               curwp = wp;
-                               delwind(FFRAND, 1);
-                       } else {
-                               killbuffer(bp);
-                       }
-               }
-       }
-       return (ret);
-memfail:
-       if (dynbuf && buf)
-               free(buf);
-       ewprintf("Out of memory");
-       return (emptyval);
-}
-
-/*
- * Do completion on a list of objects.
- * c is SPACE, TAB, or CR
- * return TRUE if matched (or partially matched)
- * FALSE is result is ambiguous,
- * ABORT on error.
- */
-static int
-complt(int flags, int c, char *buf, size_t nbuf, int cpos, int *nx)
-{
-       struct list     *lh, *lh2;
-       struct list     *wholelist = NULL;
-       int      i, nxtra, nhits, bxtra, msglen, nshown;
-       int      wflag = FALSE;
-       char    *msg;
-
-       lh = lh2 = NULL;
-
-       if ((flags & EFFUNC) != 0) {
-               buf[cpos] = '\0';
-               wholelist = lh = complete_function_list(buf);
-       } else if ((flags & EFBUF) != 0) {
-               lh = &(bheadp->b_list);
-       } else if ((flags & EFFILE) != 0) {
-               buf[cpos] = '\0';
-               wholelist = lh = make_file_list(buf);
-       } else
-               panic("broken complt call: flags");
-
-       if (c == ' ')
-               wflag = TRUE;
-       else if (c != '\t' && c != CCHR('M'))
-               panic("broken complt call: c");
-
-       nhits = 0;
-       nxtra = HUGE;
-
-       for (; lh != NULL; lh = lh->l_next) {
-               if (memcmp(buf, lh->l_name, cpos) != 0)
-                       continue;
-               if (nhits == 0)
-                       lh2 = lh;
-               ++nhits;
-               if (lh->l_name[cpos] == '\0')
-                       nxtra = -1; /* exact match */
-               else {
-                       bxtra = getxtra(lh, lh2, cpos, wflag);
-                       if (bxtra < nxtra)
-                               nxtra = bxtra;
-                       lh2 = lh;
-               }
-       }
-       if (nhits == 0)
-               msg = " [No match]";
-       else if (nhits > 1 && nxtra == 0)
-               msg = " [Ambiguous. Ctrl-G to cancel]";
-       else {
-               /*
-                * Being lazy - ought to check length, but all things
-                * autocompleted have known types/lengths.
-                */
-               if (nxtra < 0 && nhits > 1 && c == ' ')
-                       nxtra = 1; /* ??? */
-               for (i = 0; i < nxtra && cpos < nbuf; ++i) {
-                       buf[cpos] = lh2->l_name[cpos];
-                       eputc(buf[cpos++]);
-               }
-               /* XXX should grow nbuf */
-               ttflush();
-               free_file_list(wholelist);
-               *nx = nxtra;
-               if (nxtra < 0 && c != CCHR('M')) /* exact */
-                       *nx = 0;
-               return (TRUE);
-       }
-
-       /*
-        * wholelist is NULL if we are doing buffers.  Want to free lists
-        * that were created for us, but not the buffer list!
-        */
-       free_file_list(wholelist);
-
-       /* Set up backspaces, etc., being mindful of echo line limit. */
-       msglen = strlen(msg);
-       nshown = (ttcol + msglen + 2 > ncol) ?
-               ncol - ttcol - 2 : msglen;
-       eputs(msg);
-       ttcol -= (i = nshown);  /* update ttcol!                 */
-       while (i--)             /* move back before msg          */
-               ttputc('\b');
-       ttflush();              /* display to user               */
-       i = nshown;
-       while (i--)             /* blank out on next flush       */
-               eputc(' ');
-       ttcol -= (i = nshown);  /* update ttcol on BS's          */
-       while (i--)
-               ttputc('\b');   /* update ttcol again!           */
-       *nx = nxtra;
-       return ((nhits > 0) ? TRUE : FALSE);
-}
-
-/*
- * Do completion on a list of objects, listing instead of completing.
- */
-static int
-complt_list(int flags, char *buf, int cpos)
-{
-       struct list     *lh, *lh2, *lh3;
-       struct list     *wholelist = NULL;
-       struct buffer   *bp;
-       int      i, maxwidth, width;
-       int      preflen = 0;
-       int      oldrow = ttrow;
-       int      oldcol = ttcol;
-       int      oldhue = tthue;
-       char     *linebuf;
-       size_t   linesize, len;
-       char *cp;
-
-       lh = NULL;
-
-       ttflush();
-
-       /* The results are put into a completion buffer. */
-       bp = bfind("*Completions*", TRUE);
-       if (bclear(bp) == FALSE)
-               return (FALSE);
-
-       /*
-        * First get the list of objects.  This list may contain only
-        * the ones that complete what has been typed, or may be the
-        * whole list of all objects of this type.  They are filtered
-        * later in any case.  Set wholelist if the list has been
-        * cons'ed up just for us, so we can free it later.  We have
-        * to copy the buffer list for this function even though we
-        * didn't for complt.  The sorting code does destructive
-        * changes to the list, which we don't want to happen to the
-        * main buffer list!
-        */
-       if ((flags & EFBUF) != 0)
-               wholelist = lh = copy_list(&(bheadp->b_list));
-       else if ((flags & EFFUNC) != 0) {
-               buf[cpos] = '\0';
-               wholelist = lh = complete_function_list(buf);
-       } else if ((flags & EFFILE) != 0) {
-               buf[cpos] = '\0';
-               wholelist = lh = make_file_list(buf);
-               /*
-                * We don't want to display stuff up to the / for file
-                * names preflen is the list of a prefix of what the
-                * user typed that should not be displayed.
-                */
-               cp = strrchr(buf, '/');
-               if (cp)
-                       preflen = cp - buf + 1;
-       } else
-               panic("broken complt call: flags");
-
-       /*
-        * Sort the list, since users expect to see it in alphabetic
-        * order.
-        */
-       lh2 = lh;
-       while (lh2 != NULL) {
-               lh3 = lh2->l_next;
-               while (lh3 != NULL) {
-                       if (strcmp(lh2->l_name, lh3->l_name) > 0) {
-                               cp = lh2->l_name;
-                               lh2->l_name = lh3->l_name;
-                               lh3->l_name = cp;
-                       }
-                       lh3 = lh3->l_next;
-               }
-               lh2 = lh2->l_next;
-       }
-
-       /*
-        * First find max width of object to be displayed, so we can
-        * put several on a line.
-        */
-       maxwidth = 0;
-       lh2 = lh;
-       while (lh2 != NULL) {
-               for (i = 0; i < cpos; ++i) {
-                       if (buf[i] != lh2->l_name[i])
-                               break;
-               }
-               if (i == cpos) {
-                       width = strlen(lh2->l_name);
-                       if (width > maxwidth)
-                               maxwidth = width;
-               }
-               lh2 = lh2->l_next;
-       }
-       maxwidth += 1 - preflen;
-
-       /*
-        * Now do the display.  Objects are written into linebuf until
-        * it fills, and then put into the help buffer.
-        */
-       linesize = MAX(ncol, maxwidth) + 1;
-       if ((linebuf = malloc(linesize)) == NULL)
-               return (FALSE);
-       width = 0;
-
-       /*
-        * We're going to strlcat() into the buffer, so it has to be
-        * NUL terminated.
-        */
-       linebuf[0] = '\0';
-       for (lh2 = lh; lh2 != NULL; lh2 = lh2->l_next) {
-               for (i = 0; i < cpos; ++i) {
-                       if (buf[i] != lh2->l_name[i])
-                               break;
-               }
-               /* if we have a match */
-               if (i == cpos) {
-                       /* if it wraps */
-                       if ((width + maxwidth) > ncol) {
-                               addline(bp, linebuf);
-                               linebuf[0] = '\0';
-                               width = 0;
-                       }
-                       len = strlcat(linebuf, lh2->l_name + preflen,
-                           linesize);
-                       width += maxwidth;
-                       if (len < width && width < linesize) {
-                               /* pad so the objects nicely line up */
-                               memset(linebuf + len, ' ',
-                                   maxwidth - strlen(lh2->l_name + preflen));
-                               linebuf[width] = '\0';
-                       }
-               }
-       }
-       if (width > 0)
-               addline(bp, linebuf);
-       free(linebuf);
-
-       /*
-        * Note that we free lists only if they are put in wholelist lists
-        * that were built just for us should be freed.  However when we use
-        * the buffer list, obviously we don't want it freed.
-        */
-       free_file_list(wholelist);
-       popbuftop(bp, WEPHEM);  /* split the screen and put up the help
-                                * buffer */
-       update();               /* needed to make the new stuff actually
-                                * appear */
-       ttmove(oldrow, oldcol); /* update leaves cursor in arbitrary place */
-       ttcolor(oldhue);        /* with arbitrary color */
-       ttflush();
-       return (0);
-}
-
-/*
- * The "lp1" and "lp2" point to list structures.  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(struct list *lp1, struct list *lp2, int cpos, int wflag)
-{
-       int     i;
-
-       i = cpos;
-       for (;;) {
-               if (lp1->l_name[i] != lp2->l_name[i])
-                       break;
-               if (lp1->l_name[i] == '\0')
-                       break;
-               ++i;
-               if (wflag && !ISWORD(lp1->l_name[i - 1]))
-                       break;
-       }
-       return (i - cpos);
-}
-
-/*
- * Special "printf" for the echo line.  Each call to "ewprintf" starts a
- * new line in the echo area, and ends with an erase to end of the echo
- * line.  The formatting is done by a call to the standard formatting
- * routine.
- */
-/* VARARGS */
-void
-ewprintf(const char *fmt, ...)
-{
-       va_list  ap;
-
-       if (inmacro)
-               return;
-
-       va_start(ap, fmt);
-       ttcolor(CTEXT);
-       ttmove(nrow - 1, 0);
-       eformat(fmt, ap);
-       va_end(ap);
-       tteeol();
-       ttflush();
-       epresf = TRUE;
-}
-
-/*
- * Printf style formatting. This is called by both "ewprintf" 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. 
- * %c prints the "name" of the supplied character.
- * %k prints the name of the current key (and takes no arguments).
- * %d prints a decimal integer
- * %o prints an octal integer
- * %p prints a pointer
- * %s prints a string
- * %ld prints a long word
- * Anything else is echoed verbatim
- */
-static void
-eformat(const char *fp, va_list ap)
-{
-       char    kname[NKNAME], tmp[100], *cp;
-       int     c;
-
-       while ((c = *fp++) != '\0') {
-               if (c != '%')
-                       eputc(c);
-               else {
-                       c = *fp++;
-                       switch (c) {
-                       case 'c':
-                               getkeyname(kname, sizeof(kname),
-                                   va_arg(ap, int));
-                               eputs(kname);
-                               break;
-
-                       case 'k':
-                               for (cp = kname, c = 0; c < key.k_count; c++) {
-                                       if (c)
-                                               *cp++ = ' ';
-                                       cp = getkeyname(cp, sizeof(kname) -
-                                           (cp - kname) - 1, key.k_chars[c]);
-                               }
-                               eputs(kname);
-                               break;
-
-                       case 'd':
-                               eputi(va_arg(ap, int), 10);
-                               break;
-
-                       case 'o':
-                               eputi(va_arg(ap, int), 8);
-                               break;
-
-                       case 'p':
-                               snprintf(tmp, sizeof(tmp), "%p",
-                                   va_arg(ap, void *));
-                               eputs(tmp);
-                               break;
-
-                       case 's':
-                               eputs(va_arg(ap, char *));
-                               break;
-
-                       case 'l':
-                               /* explicit longword */
-                               c = *fp++;
-                               switch (c) {
-                               case 'd':
-                                       eputl(va_arg(ap, long), 10);
-                                       break;
-                               default:
-                                       eputc(c);
-                                       break;
-                               }
-                               break;
-
-                       default:
-                               eputc(c);
-                       }
-               }
-       }
-}
-
-/*
- * Put integer, in radix "r".
- */
-static void
-eputi(int i, int r)
-{
-       int      q;
-
-       if (i < 0) {
-               eputc('-');
-               i = -i;
-       }
-       if ((q = i / r) != 0)
-               eputi(q, r);
-       eputc(i % r + '0');
-}
-
-/*
- * Put long, in radix "r".
- */
-static void
-eputl(long l, int r)
-{
-       long     q;
-
-       if (l < 0) {
-               eputc('-');
-               l = -l;
-       }
-       if ((q = l / r) != 0)
-               eputl(q, r);
-       eputc((int)(l % r) + '0');
-}
-
-/*
- * Put string.
- */
-static void
-eputs(const char *s)
-{
-       int      c;
-
-       while ((c = *s++) != '\0')
-               eputc(c);
-}
-
-/*
- * Put character.  Watch for control characters, and for the line getting
- * too long.
- */
-static void
-eputc(char c)
-{
-       if (ttcol + 2 < ncol) {
-               if (ISCTRL(c)) {
-                       eputc('^');
-                       c = CCHR(c);
-               }
-               ttputc(c);
-               ++ttcol;
-       }
-}
-
-void
-free_file_list(struct list *lp)
-{
-       struct list     *next;
-
-       while (lp) {
-               next = lp->l_next;
-               free(lp->l_name);
-               free(lp);
-               lp = next;
-       }
-}
-
-static struct list *
-copy_list(struct list *lp)
-{
-       struct list     *current, *last, *nxt;
-
-       last = NULL;
-       while (lp) {
-               current = malloc(sizeof(struct list));
-               if (current == NULL) {
-                       /* Free what we have allocated so far */
-                       for (current = last; current; current = nxt) {
-                               nxt = current->l_next;
-                               free(current->l_name);
-                               free(current);
-                       }
-                       return (NULL);
-               }
-               current->l_next = last;
-               current->l_name = strdup(lp->l_name);
-               last = current;
-               lp = lp->l_next;
-       }
-       return (last);
-}