[BACK]Return to echo.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Diff for /src/usr.bin/mg/echo.c between version 1.1 and 1.2

version 1.1, 2000/02/25 19:08:47 version 1.2, 2000/04/13 06:12:14
Line 6 
Line 6 
  * of the display screen. Used by the entire   * of the display screen. Used by the entire
  * known universe.   * known universe.
  */   */
 /*  
  * The varargs lint directive comments are 0 an attempt to get lint to shup  
  * up about CORRECT usage of varargs.h.  It won't.  
  */  
 #include        "def.h"  #include        "def.h"
 #include        "key.h"  #include        "key.h"
 #ifdef  LOCAL_VARARGS  #ifdef  __STDC__
 #include        "varargs.h"  #include        <stdarg.h>
 #else  #else
 #include        <varargs.h>  #include        <varargs.h>
 #endif  #endif
 #ifndef NO_MACRO  #ifndef NO_MACRO
 #  include      "macro.h"  #include        "macro.h"
 #endif  #endif
   
 static int      veread();  static VOID     eformat         __P((const char *, va_list));
 VOID            ewprintf();  static int      veread          __P((const char *, char *buf, int, int, va_list));
 static VOID     eformat();  static VOID     eputi           __P((int, int));
 static VOID     eputi();  static VOID     eputl           __P((long, int));
 static VOID     eputl();  static VOID     eputs           __P((char *));
 static VOID     eputs();  static VOID     eputc           __P((char));
 static VOID     eputc();  static int      complt          __P((int, int, char *, int));
 static int      complt();  static int      complt_list     __P((int, int, char *, int));
 static int      complt_list();  static LIST    *copy_list       __P((LIST *));
 LIST *          make_file_list();  static VOID     free_file_list  __P((LIST *));
 LIST *          copy_list();  
 char *          strrchr();  
 extern LIST *   complete_function_list();  
   
 int     epresf  = FALSE;                /* Stuff in echo line flag.     */  int             epresf = FALSE;         /* Stuff in echo line flag.      */
   
 extern          int tthue;  
   
 /*  /*
  * Erase the echo line.   * Erase the echo line.
  */   */
 VOID  VOID
 eerase() {  eerase()
   {
   
         ttcolor(CTEXT);          ttcolor(CTEXT);
         ttmove(nrow-1, 0);          ttmove(nrow - 1, 0);
         tteeol();          tteeol();
         ttflush();          ttflush();
         epresf = FALSE;          epresf = FALSE;
Line 58 
Line 51 
  * for "no" and TRUE for "yes". No formatting   * for "no" and TRUE for "yes". No formatting
  * services are available. No newline required.   * services are available. No newline required.
  */   */
 eyorn(sp) char *sp; {  int
         register int    s;  eyorn(sp)
           char  *sp;
   {
           int    s;
   
 #ifndef NO_MACRO  #ifndef NO_MACRO
         if(inmacro) return TRUE;          if (inmacro)
                   return TRUE;
 #endif  #endif
         ewprintf("%s? (y or n) ", sp);          ewprintf("%s? (y or n) ", sp);
         for (;;) {          for (;;) {
                 s = getkey(FALSE);                  s = getkey(FALSE);
                 if (s == 'y' || s == 'Y') return TRUE;                  if (s == 'y' || s == 'Y')
                 if (s == 'n' || s == 'N') return FALSE;                          return TRUE;
                 if (s == CCHR('G')) return ctrlg(FFRAND, 1);                  if (s == 'n' || s == 'N')
                           return FALSE;
                   if (s == CCHR('G'))
                           return ctrlg(FFRAND, 1);
                 ewprintf("Please answer y or n.  %s? (y or n) ", sp);                  ewprintf("Please answer y or n.  %s? (y or n) ", sp);
         }          }
         /*NOTREACHED*/          /* NOTREACHED */
 }  }
   
 /*  /*
  * Like eyorn, but for more important question. User must type either all of   * Like eyorn, but for more important question. User must type either all of
  * "yes" or "no", and the trainling newline.   * "yes" or "no", and the trainling newline.
  */   */
 eyesno(sp) char *sp; {  int
         register int    s;  eyesno(sp)
         char            buf[64];          char  *sp;
   {
           int    s;
           char   buf[64];
   
 #ifndef NO_MACRO  #ifndef NO_MACRO
         if(inmacro) return TRUE;          if (inmacro)
                   return TRUE;
 #endif  #endif
         s = ereply("%s? (yes or no) ", buf, sizeof(buf), sp);          s = ereply("%s? (yes or no) ", buf, sizeof(buf), sp);
         for (;;) {          for (;;) {
                 if (s == ABORT) return ABORT;                  if (s == ABORT)
                           return ABORT;
                 if (s != FALSE) {                  if (s != FALSE) {
 #ifndef NO_MACRO  #ifndef NO_MACRO
                         if (macrodef) {                          if (macrodef) {
                             LINE *lp = maclcur;                                  LINE           *lp = maclcur;
   
                             maclcur = lp->l_bp;                                  maclcur = lp->l_bp;
                             maclcur->l_fp = lp->l_fp;                                  maclcur->l_fp = lp->l_fp;
                             free((char *)lp);                                  free((char *) lp);
                         }                          }
 #endif  #endif
                         if ((buf[0] == 'y' || buf[0] == 'Y')                          if ((buf[0] == 'y' || buf[0] == 'Y')
                             &&  (buf[1] == 'e' || buf[1] == 'E')                              && (buf[1] == 'e' || buf[1] == 'E')
                             &&  (buf[2] == 's' || buf[2] == 'S')                              && (buf[2] == 's' || buf[2] == 'S')
                             &&  (buf[3] == '\0')) return TRUE;                              && (buf[3] == '\0'))
                                   return TRUE;
                         if ((buf[0] == 'n' || buf[0] == 'N')                          if ((buf[0] == 'n' || buf[0] == 'N')
                             &&  (buf[1] == 'o' || buf[0] == 'O')                              && (buf[1] == 'o' || buf[0] == 'O')
                             &&  (buf[2] == '\0')) return FALSE;                              && (buf[2] == '\0'))
                                   return FALSE;
                 }                  }
                 s = ereply("Please answer yes or no.  %s? (yes or no) ",                  s = ereply("Please answer yes or no.  %s? (yes or no) ",
                            buf, sizeof(buf), sp);                             buf, sizeof(buf), sp);
         }          }
         /*NOTREACHED*/          /* NOTREACHED */
 }  }
   
 /*  /*
  * Write out a prompt, and read back a   * Write out a prompt, and read back a
  * reply. The prompt is now written out with full "ewprintf"   * reply. The prompt is now written out with full "ewprintf"
Line 119 
Line 127 
  * place. This is always a new message, there is no auto   * place. This is always a new message, there is no auto
  * completion, and the return is echoed as such.   * completion, and the return is echoed as such.
  */   */
 /*VARARGS 0*/  /* VARARGS */
   int
   #ifdef __STDC__
   ereply(const char *fmt, char *buf, int nbuf, ...)
   #else
 ereply(va_alist)  ereply(va_alist)
 va_dcl          va_dcl
   #endif
 {  {
         va_list pvar;          va_list         ap;
         register char *fp, *buf;          int    i;
         register int nbuf;  #ifdef __STDC__
         register int i;          va_start(ap, nbuf);
   #else
           char  *fmt, *buf;
           int    nbuf;
   
         va_start(pvar);          va_start(ap);
         fp = va_arg(pvar, char *);          fmt = va_arg(ap, char *);
         buf = va_arg(pvar, char *);          buf = va_arg(ap, char *);
         nbuf = va_arg(pvar, int);          nbuf = va_arg(ap, int);
         i = veread(fp, buf, nbuf, EFNEW|EFCR, &pvar);  #endif
         va_end(pvar);          i = veread(fmt, buf, nbuf, EFNEW | EFCR, ap);
           va_end(ap);
         return i;          return i;
 }  }
   
Line 146 
Line 163 
  * new prompt), an EFFUNC (autocomplete), or EFCR (echo   * new prompt), an EFFUNC (autocomplete), or EFCR (echo
  * the carriage return as CR).   * the carriage return as CR).
  */   */
 /* VARARGS 0 */  /* VARARGS */
   int
   #ifdef __STDC__
   eread(const char *fmt, char *buf, int nbuf, int flag, ...)
   #else
 eread(va_alist)  eread(va_alist)
 va_dcl          char *fmt;
           char *buf;
           int nbuf;
           int flag;
           va_dcl
   #endif
 {  {
         va_list pvar;          int             i;
         char *fp, *buf;          va_list         ap;
         int nbuf, flag, i;  #ifdef __STDC__
         va_start(pvar);          va_start(ap, flag);
         fp   = va_arg(pvar, char *);  #else
         buf  = va_arg(pvar, char *);          char  *fmt, *buf;
         nbuf = va_arg(pvar, int);          int    nbuf;
         flag = va_arg(pvar, int);  
         i = veread(fp, buf, nbuf, flag, &pvar);          va_start(ap);
         va_end(pvar);          fmt = va_arg(ap, char *);
           buf = va_arg(ap, char *);
           nbuf = va_arg(ap, int);
           flag = va_arg(ap, int);
   #endif
           i = veread(fmt, buf, nbuf, flag, ap);
           va_end(ap);
         return i;          return i;
 }  }
   
 static veread(fp, buf, nbuf, flag, ap) char *fp; char *buf; va_list *ap; {  static int
         register int    cpos;  veread(fp, buf, nbuf, flag, ap)
         register int    i;          const char *fp;
         register int    c;          char       *buf;
           int         nbuf;
           int         flag;
           va_list     ap;
   {
           int         cpos;
           int         i;
           int         c;
   
 #ifndef NO_MACRO  #ifndef NO_MACRO
         if(inmacro) {          if (inmacro) {
             bcopy(maclcur->l_text, buf, maclcur->l_used);                  bcopy(maclcur->l_text, buf, maclcur->l_used);
             buf[maclcur->l_used] = '\0';                  buf[maclcur->l_used] = '\0';
             maclcur = maclcur->l_fp;                  maclcur = maclcur->l_fp;
             return TRUE;                  return TRUE;
         }          }
 #endif  #endif
         cpos = 0;          cpos = 0;
         if ((flag&EFNEW)!=0 || ttrow!=nrow-1) {          if ((flag & EFNEW) != 0 || ttrow != nrow - 1) {
                 ttcolor(CTEXT);                  ttcolor(CTEXT);
                 ttmove(nrow-1, 0);                  ttmove(nrow - 1, 0);
                 epresf = TRUE;                  epresf = TRUE;
         } else          } else
                 eputc(' ');                  eputc(' ');
Line 188 
Line 227 
         ttflush();          ttflush();
         for (;;) {          for (;;) {
                 c = getkey(FALSE);                  c = getkey(FALSE);
                 if ((flag&EFAUTO) != 0 && (c == ' ' || c == CCHR('I'))) {                  if ((flag & EFAUTO) != 0 && (c == ' ' || c == CCHR('I'))) {
                         cpos += complt(flag, c, buf, cpos);                          cpos += complt(flag, c, buf, cpos);
                         continue;                          continue;
                 }                  }
                 if ((flag&EFAUTO) != 0 && c == '?') {                  if ((flag & EFAUTO) != 0 && c == '?') {
                         complt_list(flag, c, buf, cpos);                          complt_list(flag, c, buf, cpos);
                         continue;                          continue;
                 }                  }
                 switch (c) {                  switch (c) {
                     case CCHR('J'):                  case CCHR('J'):
                         c = CCHR('M');          /* and continue         */                          c = CCHR('M');  /* and continue          */
                     case CCHR('M'):             /* Return, done.        */                  case CCHR('M'):/* Return, done.  */
                         if ((flag&EFFUNC) != 0) {                          if ((flag & EFFUNC) != 0) {
                                 if ((i = complt(flag, c, buf, cpos)) == 0)                                  if ((i = complt(flag, c, buf, cpos)) == 0)
                                         continue;                                          continue;
                                 if (i > 0) cpos += i;                                  if (i > 0)
                                           cpos += i;
                         }                          }
                         buf[cpos] = '\0';                          buf[cpos] = '\0';
                         if ((flag&EFCR) != 0) {                          if ((flag & EFCR) != 0) {
                                 ttputc(CCHR('M'));                                  ttputc(CCHR('M'));
                                 ttflush();                                  ttflush();
                         }                          }
 #ifndef NO_MACRO  #ifndef NO_MACRO
                         if(macrodef) {                          if (macrodef) {
                             LINE *lp;                                  LINE           *lp;
   
                             if((lp = lalloc(cpos)) == NULL) return FALSE;                                  if ((lp = lalloc(cpos)) == NULL)
                             lp->l_fp = maclcur->l_fp;                                          return FALSE;
                             maclcur->l_fp = lp;                                  lp->l_fp = maclcur->l_fp;
                             lp->l_bp = maclcur;                                  maclcur->l_fp = lp;
                             maclcur = lp;                                  lp->l_bp = maclcur;
                             bcopy(buf, lp->l_text, cpos);                                  maclcur = lp;
                                   bcopy(buf, lp->l_text, cpos);
                         }                          }
 #endif  #endif
                         goto done;                          goto done;
   
                     case CCHR('G'):             /* Bell, abort.         */                  case CCHR('G'): /* Bell, abort.          */
                         eputc(CCHR('G'));                          eputc(CCHR('G'));
                         (VOID) ctrlg(FFRAND, 0);                          (VOID) ctrlg(FFRAND, 0);
                         ttflush();                          ttflush();
                         return ABORT;                          return ABORT;
   
                     case CCHR('H'):                  case CCHR('H'):
                     case CCHR('?'):             /* Rubout, erase.       */                  case CCHR('?'): /* Rubout, erase.        */
                         if (cpos != 0) {                          if (cpos != 0) {
                                 ttputc('\b');                                  ttputc('\b');
                                 ttputc(' ');                                  ttputc(' ');
Line 247 
Line 288 
                         }                          }
                         break;                          break;
   
                     case CCHR('X'):             /* C-X                  */                  case CCHR('X'): /* C-X                   */
                     case CCHR('U'):             /* C-U, kill line.      */                  case CCHR('U'): /* C-U, kill line.       */
                         while (cpos != 0) {                          while (cpos != 0) {
                                 ttputc('\b');                                  ttputc('\b');
                                 ttputc(' ');                                  ttputc(' ');
Line 264 
Line 305 
                         ttflush();                          ttflush();
                         break;                          break;
   
                     case CCHR('W'):             /* C-W, kill to beginning of */                  case CCHR('W'): /* C-W, kill to beginning of */
                                                 /* previous word        */                          /* previous word         */
                         /* back up to first word character or beginning */                          /* back up to first word character or beginning */
                         while ((cpos > 0) && !ISWORD(buf[cpos - 1])) {                          while ((cpos > 0) && !ISWORD(buf[cpos - 1])) {
                                 ttputc('\b');                                  ttputc('\b');
Line 294 
Line 335 
                         ttflush();                          ttflush();
                         break;                          break;
   
                     case CCHR('\\'):                  case CCHR('\\'):
                     case CCHR('Q'):             /* C-Q, quote next      */                  case CCHR('Q'): /* C-Q, quote next       */
                         c = getkey(FALSE);      /* and continue         */                          c = getkey(FALSE);      /* and continue          */
                     default:                    /* All the rest.        */                  default:        /* All the rest.         */
                         if (cpos < nbuf-1) {                          if (cpos < nbuf - 1) {
                                 buf[cpos++] = (char) c;                                  buf[cpos++] = (char) c;
                                 eputc((char) c);                                  eputc((char) c);
                                 ttflush();                                  ttflush();
Line 311 
Line 352 
 /*  /*
  * do completion on a list of objects.   * do completion on a list of objects.
  */   */
 static int complt(flags, c, buf, cpos)  static int
 register char *buf;  complt(flags, c, buf, cpos)
 register int cpos;          int    flags;
           int    c;
           char  *buf;
           int    cpos;
 {  {
         register LIST   *lh, *lh2;          LIST  *lh, *lh2;
         LIST            *wholelist = NULL;          LIST  *wholelist = NULL;
         int             i, nxtra;          int    i, nxtra;
         int             nhits, bxtra;          int    nhits, bxtra;
         int             wflag = FALSE;          int    wflag = FALSE;
         int             msglen, nshown;          int    msglen, nshown;
         char            *msg;          char  *msg;
   
         if ((flags&EFFUNC) != 0) {          if ((flags & EFFUNC) != 0) {
             buf[cpos] = '\0';                  buf[cpos] = '\0';
             i = complete_function(buf, c);                  i = complete_function(buf, c);
             if(i>0) {                  if (i > 0) {
                 eputs(&buf[cpos]);                          eputs(&buf[cpos]);
                 ttflush();                          ttflush();
                 return i;                          return i;
             }                  }
             switch(i) {                  switch (i) {
                 case -3:                  case -3:
                     msg = " [Ambiguous]";                          msg = " [Ambiguous]";
                     break;                          break;
                 case -2:                  case -2:
                     i=0;                          i = 0;
                     msg = " [No match]";                          msg = " [No match]";
                     break;                          break;
                 case -1:                  case -1:
                 case 0:                  case 0:
                     return i;                          return i;
                 default:                  default:
                     msg = " [Internal error]";                          msg = " [Internal error]";
                     break;                          break;
             }                  }
         } else {          } else {
             if ((flags&EFBUF) != 0) lh = &(bheadp->b_list);                  if ((flags & EFBUF) != 0)
             else if ((flags&EFFILE) != 0) {                          lh = &(bheadp->b_list);
                 buf[cpos] = '\0';                  else if ((flags & EFFILE) != 0) {
                 wholelist = lh = make_file_list(buf,0);                          buf[cpos] = '\0';
             }                          wholelist = lh = make_file_list(buf, 0);
             else panic("broken complt call: flags");                  } else
                           panic("broken complt call: flags");
   
             if (c == ' ') wflag = TRUE;                  if (c == ' ')
             else if (c != '\t' && c != CCHR('M')) panic("broken complt call: c");                          wflag = TRUE;
                   else if (c != '\t' && c != CCHR('M'))
                           panic("broken complt call: c");
   
             nhits = 0;                  nhits = 0;
             nxtra = HUGE;                  nxtra = HUGE;
   
             while (lh != NULL) {                  while (lh != NULL) {
                 for (i=0; i<cpos; ++i) {                          for (i = 0; i < cpos; ++i) {
                         if (buf[i] != lh->l_name[i])                                  if (buf[i] != lh->l_name[i])
                                 break;                                          break;
                           }
                           if (i == cpos) {
                                   if (nhits == 0)
                                           lh2 = lh;
                                   ++nhits;
                                   if (lh->l_name[i] == '\0')
                                           nxtra = -1;
                                   else {
                                           bxtra = getxtra(lh, lh2, cpos, wflag);
                                           if (bxtra < nxtra)
                                                   nxtra = bxtra;
                                           lh2 = lh;
                                   }
                           }
                           lh = lh->l_next;
                 }                  }
                 if (i == cpos) {                  if (nhits == 0)
                         if (nhits == 0)                          msg = " [No match]";
                                 lh2 = lh;                  else if (nhits > 1 && nxtra == 0)
                         ++nhits;                          msg = " [Ambiguous]";
                         if (lh->l_name[i] == '\0') nxtra = -1;                  else {          /* Got a match, do it to it */
                         else {                          /*
                                 bxtra = getxtra(lh, lh2, cpos, wflag);                           * Being lazy - ought to check length, but all things
                                 if (bxtra < nxtra) nxtra = bxtra;                           * autocompleted have known types/lengths.
                                 lh2 = lh;                           */
                           if (nxtra < 0 && nhits > 1 && c == ' ')
                                   nxtra = 1;
                           for (i = 0; i < nxtra; ++i) {
                                   buf[cpos] = lh2->l_name[cpos];
                                   eputc(buf[cpos++]);
                         }                          }
                           ttflush();
                           free_file_list(wholelist);
                           if (nxtra < 0 && c != CCHR('M'))
                                   return 0;
                           return nxtra;
                 }                  }
                 lh = lh->l_next;  
             }  
             if (nhits == 0)  
                 msg = " [No match]";  
             else if (nhits > 1 && nxtra == 0)  
                 msg = " [Ambiguous]";  
             else {              /* Got a match, do it to it */  
                 /*  
                  * 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; ++i) {  
                         buf[cpos] = lh2->l_name[cpos];  
                         eputc(buf[cpos++]);  
                 }  
                 ttflush();  
                 free_file_list(wholelist);  
                 if (nxtra < 0 && c != CCHR('M')) return 0;  
                 return nxtra;  
             }  
         }          }
         /* wholelist is null if we are doing buffers.  want to free          /*
          * lists that were created for us, but not the buffer list! */           * 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);          free_file_list(wholelist);
         /* Set up backspaces, etc., being mindful of echo line limit */          /* Set up backspaces, etc., being mindful of echo line limit */
         msglen = strlen(msg);          msglen = strlen(msg);
         nshown = (ttcol + msglen + 2 > ncol) ?          nshown = (ttcol + msglen + 2 > ncol) ?
                         ncol - ttcol - 2 : msglen;                  ncol - ttcol - 2 : msglen;
         eputs(msg);          eputs(msg);
         ttcol -= (i = nshown);          /* update ttcol!                */          ttcol -= (i = nshown);  /* update ttcol!                 */
         while (i--)                     /* move back before msg         */          while (i--)             /* move back before msg          */
                 ttputc('\b');                  ttputc('\b');
         ttflush();                      /* display to user              */          ttflush();              /* display to user               */
         i = nshown;          i = nshown;
         while (i--)                     /* blank out    on next flush   */          while (i--)             /* blank out    on next flush    */
                 eputc(' ');                  eputc(' ');
         ttcol -= (i = nshown);          /* update ttcol on BS's         */          ttcol -= (i = nshown);  /* update ttcol on BS's          */
         while (i--)          while (i--)
                 ttputc('\b');           /* update ttcol again!          */                  ttputc('\b');   /* update ttcol again!           */
         return 0;          return 0;
 }  }
   
 /*  /*
  * do completion on a list of objects, listing instead of completing   * do completion on a list of objects, listing instead of completing
  */   */
 static int complt_list(flags, c, buf, cpos)  static int
 register char *buf;  complt_list(flags, c, buf, cpos)
 register int cpos;          int     flags;
           int     c;
           char   *buf;
           int     cpos;
 {  {
         register LIST   *lh, *lh2, *lh3;          LIST   *lh, *lh2, *lh3;
         LIST            *wholelist = NULL;          LIST   *wholelist = NULL;
         int             i,maxwidth,width;          int     i, maxwidth, width;
         int             preflen = 0;          int     preflen = 0;
         BUFFER          *bp;          BUFFER *bp;
         static VOID     findbind();          int     oldrow = ttrow;
         int             oldrow = ttrow;          int     oldcol = ttcol;
         int             oldcol = ttcol;          int     oldhue = tthue;
         int             oldhue = tthue;          char    linebuf[NCOL + 1];
         char            linebuf[NCOL+1];          char   *cp;
         char            *cp;  
   
         ttflush();          ttflush();
   
         /* the results are put into a help buffer */          /* the results are put into a help buffer */
   
         bp = bfind("*help*", TRUE);          bp = bfind("*help*", TRUE);
         if(bclear(bp) == FALSE) return FALSE;          if (bclear(bp) == FALSE)
                   return FALSE;
   
         {  /* this {} present for historical reasons */          {       /* this {} present for historical reasons */
   
 /*  
  * 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, c);  
             }  
             else if ((flags&EFFILE) != 0) {  
                 buf[cpos] = '\0';  
                 wholelist = lh = make_file_list(buf,1);  
                 /*                  /*
                  * we don't want to display stuff up to the / for file names                   * first get the list of objects.  This list may contain only
                  * preflen is the list of a prefix of what the user typed                   * the ones that complete what has been typed, or may be the
                  * that should not be displayed.                   * 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!
                  */                   */
                 cp = strrchr(buf,'/');                  if ((flags & EFBUF) != 0)
                 if (cp)                          wholelist = lh = copy_list(&(bheadp->b_list));
                     preflen = cp - buf + 1;                  else if ((flags & EFFUNC) != 0) {
             }                          buf[cpos] = '\0';
             else panic("broken complt call: flags");                          wholelist = lh = complete_function_list(buf, c);
                   } else if ((flags & EFFILE) != 0) {
                           buf[cpos] = '\0';
                           wholelist = lh = make_file_list(buf, 1);
                           /*
                            * 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 */                  /*
                    * Sort the list, since users expect to see it in alphabetic
             lh2 = lh;                   * order.
             while (lh2) {                   */
                 lh3 = lh2->l_next;                  lh2 = lh;
                 while (lh3) {                  while (lh2) {
                     if (strcmp(lh2->l_name, lh3->l_name) > 0) {                          lh3 = lh2->l_next;
                         cp = lh2->l_name;                          while (lh3) {
                         lh2->l_name = lh3->l_name;                                  if (strcmp(lh2->l_name, lh3->l_name) > 0) {
                         lh3->l_name = cp;                                          cp = lh2->l_name;
                     }                                          lh2->l_name = lh3->l_name;
                     lh3 = lh3->l_next;                                          lh3->l_name = cp;
                 }                                  }
                 lh2 = lh2->l_next;                                  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                   * First find max width of object to be displayed, so we can
  * fills, and then put into the help buffer.                   * put several on a line.
  */                   */
             cp = linebuf;                  maxwidth = 0;
             width = 0;                  lh2 = lh;
             lh2 = lh;                  while (lh2 != NULL) {
             while (lh2 != NULL) {                          for (i = 0; i < cpos; ++i) {
                 for (i=0; i<cpos; ++i) {                                  if (buf[i] != lh2->l_name[i])
                         if (buf[i] != lh2->l_name[i])                                          break;
                                 break;                          }
                           if (i == cpos) {
                                   width = strlen(lh2->l_name);
                                   if (width > maxwidth)
                                           maxwidth = width;
                           }
                           lh2 = lh2->l_next;
                 }                  }
                 if (i == cpos) {                  maxwidth += 1 - preflen;
                         if ((width + maxwidth) > ncol) {  
                                 *cp = 0;                  /*
                                 addline(bp,linebuf);                   * Now do the display.  objects are written into linebuf until
                                 cp = linebuf;                   * it fills, and then put into the help buffer.
                                 width = 0;                   */
                   cp = linebuf;
                   width = 0;
                   lh2 = lh;
                   while (lh2 != NULL) {
                           for (i = 0; i < cpos; ++i) {
                                   if (buf[i] != lh2->l_name[i])
                                           break;
                         }                          }
                         strcpy(cp,lh2->l_name+preflen);                          if (i == cpos) {
                         i = strlen(lh2->l_name+preflen);                                  if ((width + maxwidth) > ncol) {
                         cp += i;                                          *cp = 0;
                         for (; i < maxwidth; i++)                                          addline(bp, linebuf);
                                 *cp++ = ' ';                                          cp = linebuf;
                         width += maxwidth;                                          width = 0;
                                   }
                                   strcpy(cp, lh2->l_name + preflen);
                                   i = strlen(lh2->l_name + preflen);
                                   cp += i;
                                   for (; i < maxwidth; i++)
                                           *cp++ = ' ';
                                   width += maxwidth;
                           }
                           lh2 = lh2->l_next;
                 }                  }
                 lh2 = lh2->l_next;                  if (width > 0) {
             }                          *cp = 0;
             if (width > 0) {                          addline(bp, linebuf);
                 *cp = 0;                  }
                 addline(bp,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
          * note that we free lists only if they are put in wholelist           * the buffer list, obviously we don't want it freed.
          * 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);          free_file_list(wholelist);
         popbuftop(bp);   /* split the screen and put up the help buffer */          popbuftop(bp);          /* split the screen and put up the help
         update();        /* needed to make the new stuff actually appear */                                   * buffer */
         ttmove(oldrow,oldcol);  /* update leaves cursor in arbitrary place */          update();               /* needed to make the new stuff actually
         ttcolor(oldhue);  /* with arbitrary color */                                   * appear */
           ttmove(oldrow, oldcol); /* update leaves cursor in arbitrary place */
           ttcolor(oldhue);        /* with arbitrary color */
         ttflush();          ttflush();
         return 0;          return 0;
 }  }
Line 569 
Line 626 
  * Return the longest block of characters that can be   * Return the longest block of characters that can be
  * autocompleted at this point. Sometimes the two   * autocompleted at this point. Sometimes the two
  * symbols are the same, but this is normal.   * symbols are the same, but this is normal.
   */   */
 getxtra(lp1, lp2, cpos, wflag) register LIST *lp1, *lp2; register int wflag; {  int
         register int    i;  getxtra(lp1, lp2, cpos, wflag)
           LIST  *lp1, *lp2;
           int    cpos;
           int    wflag;
   {
           int    i;
   
         i = cpos;          i = cpos;
         for (;;) {          for (;;) {
                 if (lp1->l_name[i] != lp2->l_name[i]) break;                  if (lp1->l_name[i] != lp2->l_name[i])
                 if (lp1->l_name[i] == '\0') break;                          break;
                   if (lp1->l_name[i] == '\0')
                           break;
                 ++i;                  ++i;
                 if (wflag && !ISWORD(lp1->l_name[i-1])) break;                  if (wflag && !ISWORD(lp1->l_name[i - 1]))
                           break;
         }          }
         return (i - cpos);          return (i - cpos);
 }  }
Line 590 
Line 655 
  * echo line. The formatting is done by a call   * echo line. The formatting is done by a call
  * to the standard formatting routine.   * to the standard formatting routine.
  */   */
 /*VARARGS 0 */  /* VARARGS */
 VOID  VOID
   #ifdef __STDC__
   ewprintf(const char *fmt, ...)
   #else
 ewprintf(va_alist)  ewprintf(va_alist)
 va_dcl          va_dcl
   #endif
 {  {
         va_list pvar;          va_list         ap;
         register char *fp;  #ifndef __STDC__
           char          *fmt;
   #endif
   
 #ifndef NO_MACRO  #ifndef NO_MACRO
         if(inmacro) return;          if (inmacro)
                   return;
 #endif  #endif
         va_start(pvar);  #ifdef __STDC__
         fp = va_arg(pvar, char *);          va_start(ap, fmt);
   #else
           va_start(ap);
           fmt = va_arg(ap, char *);
   #endif
         ttcolor(CTEXT);          ttcolor(CTEXT);
         ttmove(nrow-1, 0);          ttmove(nrow - 1, 0);
         eformat(fp, &pvar);          eformat(fmt, ap);
         va_end(pvar);          va_end(ap);
         tteeol();          tteeol();
         ttflush();          ttflush();
         epresf = TRUE;          epresf = TRUE;
Line 623 
Line 699 
  */   */
 static VOID  static VOID
 eformat(fp, ap)  eformat(fp, ap)
 register char *fp;          const char  *fp;
 register va_list *ap;          va_list ap;
 {  {
         register int c;          int    c;
         char    kname[NKNAME];          char   kname[NKNAME];
         char    *keyname();          char  *cp;
         char    *cp;  
   
         while ((c = *fp++) != '\0') {          while ((c = *fp++) != '\0') {
                 if (c != '%')                  if (c != '%')
Line 638 
Line 713 
                         c = *fp++;                          c = *fp++;
                         switch (c) {                          switch (c) {
                         case 'c':                          case 'c':
                                 (VOID) keyname(kname, va_arg(*ap, int));                                  (VOID) keyname(kname, va_arg(ap, int));
                                 eputs(kname);                                  eputs(kname);
                                 break;                                  break;
   
                         case 'k':                          case 'k':
                                 cp = kname;                                  cp = kname;
                                 for(c=0; c < key.k_count; c++) {                                  for (c = 0; c < key.k_count; c++) {
                                     cp = keyname(cp, key.k_chars[c]);                                          cp = keyname(cp, key.k_chars[c]);
                                     *cp++ = ' ';                                          *cp++ = ' ';
                                 }                                  }
                                 *--cp = '\0';                                  *--cp = '\0';
                                 eputs(kname);                                  eputs(kname);
                                 break;                                  break;
   
                         case 'd':                          case 'd':
                                 eputi(va_arg(*ap, int), 10);                                  eputi(va_arg(ap, int), 10);
                                 break;                                  break;
   
                         case 'o':                          case 'o':
                                 eputi(va_arg(*ap, int), 8);                                  eputi(va_arg(ap, int), 8);
                                 break;                                  break;
   
                         case 's':                          case 's':
                                 eputs(va_arg(*ap, char *));                                  eputs(va_arg(ap, char *));
                                 break;                                  break;
   
                         case 'l':/* explicit longword */                          case 'l':       /* explicit longword */
                                 c = *fp++;                                  c = *fp++;
                                 switch(c) {                                  switch (c) {
                                 case 'd':                                  case 'd':
                                         eputl((long)va_arg(*ap, long), 10);                                          eputl((long) va_arg(ap, long), 10);
                                         break;                                          break;
                                 default:                                  default:
                                         eputc(c);                                          eputc(c);
Line 688 
Line 763 
  */   */
 static VOID  static VOID
 eputi(i, r)  eputi(i, r)
 register int i;          int    i;
 register int r;          int    r;
 {  {
         register int    q;          int    q;
   
         if(i<0) {          if (i < 0) {
             eputc('-');                  eputc('-');
             i = -i;                  i = -i;
         }          }
         if ((q=i/r) != 0)          if ((q = i / r) != 0)
                 eputi(q, r);                  eputi(q, r);
         eputc(i%r+'0');          eputc(i % r + '0');
 }  }
   
 /*  /*
Line 707 
Line 782 
  */   */
 static VOID  static VOID
 eputl(l, r)  eputl(l, r)
 register long l;          long   l;
 register int  r;          int    r;
 {  {
         register long   q;          long   q;
   
         if(l < 0) {          if (l < 0) {
             eputc('-');                  eputc('-');
             l = -l;                  l = -l;
         }          }
         if ((q=l/r) != 0)          if ((q = l / r) != 0)
                 eputl(q, r);                  eputl(q, r);
         eputc((int)(l%r)+'0');          eputc((int) (l % r) + '0');
 }  }
   
 /*  /*
Line 726 
Line 801 
  */   */
 static VOID  static VOID
 eputs(s)  eputs(s)
 register char *s;          char  *s;
 {  {
         register int    c;          int    c;
   
         while ((c = *s++) != '\0')          while ((c = *s++) != '\0')
                 eputc(c);                  eputc(c);
Line 741 
Line 816 
  */   */
 static VOID  static VOID
 eputc(c)  eputc(c)
 register char c;          char   c;
 {  {
         if (ttcol+2 < ncol) {  
           if (ttcol + 2 < ncol) {
                 if (ISCTRL(c)) {                  if (ISCTRL(c)) {
                         eputc('^');                          eputc('^');
                         c = CCHR(c);                          c = CCHR(c);
Line 753 
Line 829 
         }          }
 }  }
   
   static VOID
 free_file_list(lp)  free_file_list(lp)
   LIST *lp;          LIST *lp;
 {  {
 LIST *next;          LIST *next;
 while (lp) {  
         next = lp->l_next;          while (lp) {
         free(lp);                  next = lp->l_next;
         lp = next;                  free(lp);
                   lp = next;
           }
 }  }
 }  
   
 LIST *copy_list(lp)  static LIST *
   LIST *lp;  copy_list(lp)
           LIST *lp;
 {  {
 LIST *current,*last;          LIST *current, *last;
   
 last = NULL;          last = NULL;
 while(lp) {          while (lp) {
         current = (LIST *)malloc(sizeof(LIST));                  current = (LIST *) malloc(sizeof(LIST));
         current->l_next = last;                  current->l_next = last;
         current->l_name = lp->l_name;                  current->l_name = lp->l_name;
         last = (LIST *)current;                  last = (LIST *) current;
         lp = lp->l_next;                  lp = lp->l_next;
 }          }
 return(last);          return (last);
 }  }

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.2