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

Diff for /src/usr.bin/top/display.c between version 1.13 and 1.14

version 1.13, 2003/06/13 04:29:59 version 1.14, 2003/06/13 21:52:24
Line 1 
Line 1 
 /*      $OpenBSD$       */  /* $OpenBSD$     */
   
 /*  /*
  *  Top users/processes display for Unix   *  Top users/processes display for Unix
Line 65 
Line 65 
 #include "utils.h"  #include "utils.h"
   
 #ifdef DEBUG  #ifdef DEBUG
 FILE *debug;  FILE           *debug;
 #endif  #endif
   
 static pid_t lmpid = 0;  static pid_t    lmpid = 0;
 static int last_hi = 0;         /* used in u_process and u_endscreen */  static int      last_hi = 0;    /* used in u_process and u_endscreen */
 static int lastline = 0;  static int      lastline = 0;
 static int display_width = MAX_COLS;  static int      display_width = MAX_COLS;
   
 static char *cpustates_tag(void);  static char    *cpustates_tag(void);
 static int string_count(char **);  static int      string_count(char **);
 static void summary_format(char *, int *, char **);  static void     summary_format(char *, int *, char **);
 static void line_update(char *, char *, int, int);  static void     line_update(char *, char *, int, int);
   
 #define lineindex(l) ((l)*display_width)  #define lineindex(l) ((l)*display_width)
   
 /* things initialized by display_init and used thruout */  /* things initialized by display_init and used thruout */
   
 /* buffer of proc information lines for display updating */  /* buffer of proc information lines for display updating */
 char *screenbuf = NULL;  char           *screenbuf = NULL;
   
 static char **procstate_names;  static char   **procstate_names;
 static char **cpustate_names;  static char   **cpustate_names;
 static char **memory_names;  static char   **memory_names;
   
 static int num_procstates;  static int      num_procstates;
 static int num_cpustates;  static int      num_cpustates;
 static int num_memory;  static int      num_memory;
   
 static int *lprocstates;  static int     *lprocstates;
 static int *lcpustates;  static int     *lcpustates;
 static int *lmemory;  static int     *lmemory;
   
 static int *cpustate_columns;  static int     *cpustate_columns;
 static int cpustate_total_length;  static int      cpustate_total_length;
   
 static enum { OFF, ON, ERASE } header_status = ON;  static enum {
           OFF, ON, ERASE
   } header_status = ON;
   
 static int string_count();  
 static void summary_format();  
 static void line_update();  
   
 int  int
 display_resize(void)  display_resize(void)
 {  {
     int display_lines;          int display_lines;
   
     /* first, deallocate any previous buffer that may have been there */          /* first, deallocate any previous buffer that may have been there */
     if (screenbuf != NULL)          if (screenbuf != NULL)
     {                  free(screenbuf);
         free(screenbuf);  
     }  
   
     /* calculate the current dimensions */          /* calculate the current dimensions */
     /* if operating in "dumb" mode, we only need one line */          /* if operating in "dumb" mode, we only need one line */
     display_lines = smart_terminal ? screen_length - Header_lines : 1;          display_lines = smart_terminal ? screen_length - Header_lines : 1;
   
     /* we don't want more than MAX_COLS columns, since the machine-dependent          /*
        modules make static allocations based on MAX_COLS and we don't want           * we don't want more than MAX_COLS columns, since the
        to run off the end of their buffers */           * machine-dependent modules make static allocations based on
     display_width = screen_width;           * MAX_COLS and we don't want to run off the end of their buffers
     if (display_width >= MAX_COLS)           */
     {          display_width = screen_width;
         display_width = MAX_COLS - 1;          if (display_width >= MAX_COLS)
     }                  display_width = MAX_COLS - 1;
   
     /* now, allocate space for the screen buffer */          /* now, allocate space for the screen buffer */
     screenbuf = (char *)malloc(display_lines * display_width);          screenbuf = (char *) malloc(display_lines * display_width);
     if (screenbuf == (char *)NULL)          if (screenbuf == (char *) NULL)
     {                  return (-1);
         /* oops! */  
         return(-1);  
     }  
   
     /* return number of lines available */          /* return number of lines available */
     /* for dumb terminals, pretend like we can show any amount */          /* for dumb terminals, pretend like we can show any amount */
     return(smart_terminal ? display_lines : Largest);          return (smart_terminal ? display_lines : Largest);
 }  }
   
 int  int
 display_init(struct statics *statics)  display_init(struct statics * statics)
 {  {
     int display_lines;          int display_lines, *ip, i;
     char **pp;          char **pp;
     int *ip;  
     int i;  
   
     /* call resize to do the dirty work */          /* call resize to do the dirty work */
     display_lines = display_resize();          display_lines = display_resize();
   
     /* only do the rest if we need to */          /* only do the rest if we need to */
     if (display_lines > -1)          if (display_lines > -1) {
     {                  /* save pointers and allocate space for names */
         /* save pointers and allocate space for names */                  procstate_names = statics->procstate_names;
         procstate_names = statics->procstate_names;                  num_procstates = string_count(procstate_names);
         num_procstates = string_count(procstate_names);                  lprocstates = (int *) malloc(num_procstates * sizeof(int));
         lprocstates = (int *)malloc(num_procstates * sizeof(int));  
   
         cpustate_names = statics->cpustate_names;                  cpustate_names = statics->cpustate_names;
         num_cpustates = string_count(cpustate_names);                  num_cpustates = string_count(cpustate_names);
         lcpustates = (int *)malloc(num_cpustates * sizeof(int));                  lcpustates = (int *) malloc(num_cpustates * sizeof(int));
         cpustate_columns = (int *)malloc(num_cpustates * sizeof(int));                  cpustate_columns = (int *) malloc(num_cpustates * sizeof(int));
   
         memory_names = statics->memory_names;                  memory_names = statics->memory_names;
         num_memory = string_count(memory_names);                  num_memory = string_count(memory_names);
         lmemory = (int *)malloc(num_memory * sizeof(int));                  lmemory = (int *) malloc(num_memory * sizeof(int));
   
         /* calculate starting columns where needed */                  /* calculate starting columns where needed */
         cpustate_total_length = 0;                  cpustate_total_length = 0;
         pp = cpustate_names;                  pp = cpustate_names;
         ip = cpustate_columns;                  ip = cpustate_columns;
         while (*pp != NULL)                  while (*pp != NULL) {
         {                          if ((i = strlen(*pp++)) > 0) {
             if ((i = strlen(*pp++)) > 0)                                  *ip++ = cpustate_total_length;
             {                                  cpustate_total_length += i + 8;
                 *ip++ = cpustate_total_length;                          }
                 cpustate_total_length += i + 8;                  }
             }  
         }          }
     }          /* return number of lines available */
           return (display_lines);
     /* return number of lines available */  
     return(display_lines);  
 }  }
   
 void  void
 i_loadave(pid_t mpid, double *avenrun)  i_loadave(pid_t mpid, double *avenrun)
 {  {
     int i;          int i;
   
     /* i_loadave also clears the screen, since it is first */          /* i_loadave also clears the screen, since it is first */
     clear();          clear();
   
     /* mpid == -1 implies this system doesn't have an _mpid */          /* mpid == -1 implies this system doesn't have an _mpid */
     if (mpid != -1)          if (mpid != -1)
     {                  printf("last pid: %5ld;  ", (long) mpid);
         printf("last pid: %5ld;  ", (long)mpid);  
     }  
   
     printf("load averages");          printf("load averages");
   
     for (i = 0; i < 3; i++)          for (i = 0; i < 3; i++)
     {                  printf("%c %5.2f", i == 0 ? ':' : ',', avenrun[i]);
         printf("%c %5.2f",  
             i == 0 ? ':' : ',',          lmpid = mpid;
             avenrun[i]);  
     }  
     lmpid = mpid;  
 }  }
   
 void  void
 u_loadave(pid_t mpid, double *avenrun)  u_loadave(pid_t mpid, double *avenrun)
 {  {
     int i;          int i;
   
     if (mpid != -1)          if (mpid != -1) {
     {                  /* change screen only when value has really changed */
         /* change screen only when value has really changed */                  if (mpid != lmpid) {
         if (mpid != lmpid)                          Move_to(x_lastpid, y_lastpid);
         {                          printf("%5ld", (long) mpid);
             Move_to(x_lastpid, y_lastpid);                          lmpid = mpid;
             printf("%5ld", (long)mpid);                  }
             lmpid = mpid;                  /* i remembers x coordinate to move to */
         }                  i = x_loadave;
           } else
                   i = x_loadave_nompid;
   
         /* i remembers x coordinate to move to */          /* move into position for load averages */
         i = x_loadave;          Move_to(i, y_loadave);
     }  
     else  
     {  
         i = x_loadave_nompid;  
     }  
   
     /* move into position for load averages */          /* display new load averages */
     Move_to(i, y_loadave);          /* we should optimize this and only display changes */
           for (i = 0; i < 3; i++)
     /* display new load averages */                  printf("%s%5.2f", i == 0 ? "" : ", ", avenrun[i]);
     /* we should optimize this and only display changes */  
     for (i = 0; i < 3; i++)  
     {  
         printf("%s%5.2f",  
             i == 0 ? "" : ", ",  
             avenrun[i]);  
     }  
 }  }
   
   /*
    *  Display the current time.
    *  "ctime" always returns a string that looks like this:
    *
    *      Sun Sep 16 01:03:52 1973
    *      012345678901234567890123
    *                1         2
    *
    *  We want indices 11 thru 18 (length 8).
    */
   
 void  void
 i_timeofday(time_t *tod)  i_timeofday(time_t * tod)
 {  {
     /*  
      *  Display the current time.  
      *  "ctime" always returns a string that looks like this:  
      *  
      *  Sun Sep 16 01:03:52 1973  
      *      012345678901234567890123  
      *            1         2  
      *  
      *  We want indices 11 thru 18 (length 8).  
      */  
   
     if (smart_terminal)          if (smart_terminal) {
     {                  Move_to(screen_width - 8, 0);
         Move_to(screen_width - 8, 0);          } else {
     }                  if (fputs("    ", stdout) == EOF)
     else                          exit(1);
     {          }
         if (fputs("    ", stdout) == EOF)  
             exit(1);  
     }  
 #ifdef DEBUG  #ifdef DEBUG
     {          {
         char *foo;                  char *foo;
         foo = ctime(tod);                  foo = ctime(tod);
         if (fputs(foo, stdout) == EOF)                  if (fputs(foo, stdout) == EOF)
             exit(1);                          exit(1);
     }          }
 #endif  #endif
     printf("%-8.8s\n", &(ctime(tod)[11]));          printf("%-8.8s\n", &(ctime(tod)[11]));
     lastline = 1;          lastline = 1;
 }  }
   
 static int ltotal = 0;  static int      ltotal = 0;
 static char procstates_buffer[128];  static char     procstates_buffer[128];
   
 /*  /*
  *  *_procstates(total, brkdn, names) - print the process summary line   *  *_procstates(total, brkdn, names) - print the process summary line
Line 294 
Line 264 
  *  Assumptions:  cursor is at the beginning of the line on entry   *  Assumptions:  cursor is at the beginning of the line on entry
  *                lastline is valid   *                lastline is valid
  */   */
   
 void  void
 i_procstates(int total, int *brkdn)  i_procstates(int total, int *brkdn)
 {  {
     int i;          int i;
   
     /* write current number of processes and remember the value */          /* write current number of processes and remember the value */
     printf("%d processes:", total);          printf("%d processes:", total);
     ltotal = total;          ltotal = total;
   
     /* put out enough spaces to get to column 15 */          /* put out enough spaces to get to column 15 */
     i = digits(total);          i = digits(total);
     while (i++ < 4)          while (i++ < 4) {
     {                  if (putchar(' ') == EOF)
         if (putchar(' ') == EOF)                          exit(1);
           }
   
           /* format and print the process state summary */
           summary_format(procstates_buffer, brkdn, procstate_names);
           if (fputs(procstates_buffer, stdout) == EOF)
                 exit(1);                  exit(1);
     }  
   
     /* format and print the process state summary */          /* save the numbers for next time */
     summary_format(procstates_buffer, brkdn, procstate_names);          memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
     if (fputs(procstates_buffer, stdout) == EOF)  
         exit(1);  
   
     /* save the numbers for next time */  
     memcpy(lprocstates, brkdn, num_procstates * sizeof(int));  
 }  }
   
 void  void
 u_procstates(int total, int *brkdn)  u_procstates(int total, int *brkdn)
 {  {
     static char new[128];          static char new[128];
     int i;          int i;
   
     /* update number of processes only if it has changed */          /* update number of processes only if it has changed */
     if (ltotal != total)          if (ltotal != total) {
     {                  /* move and overwrite */
         /* move and overwrite */  
 #if (x_procstate == 0)  #if (x_procstate == 0)
         Move_to(x_procstate, y_procstate);                  Move_to(x_procstate, y_procstate);
 #else  #else
         /* cursor is already there...no motion needed */                  /* cursor is already there...no motion needed */
         /* assert(lastline == 1); */                  /* assert(lastline == 1); */
 #endif  #endif
         printf("%d", total);                  printf("%d", total);
   
         /* if number of digits differs, rewrite the label */                  /* if number of digits differs, rewrite the label */
         if (digits(total) != digits(ltotal))                  if (digits(total) != digits(ltotal)) {
         {                          if (fputs(" processes:", stdout) == EOF)
             if (fputs(" processes:", stdout) == EOF)                                  exit(1);
                 exit(1);                          /* put out enough spaces to get to column 15 */
             /* put out enough spaces to get to column 15 */                          i = digits(total);
             i = digits(total);                          while (i++ < 4) {
             while (i++ < 4)                                  if (putchar(' ') == EOF)
             {                                          exit(1);
                 if (putchar(' ') == EOF)                          }
                     exit(1);                          /* cursor may end up right where we want it!!! */
             }                  }
             /* cursor may end up right where we want it!!! */                  /* save new total */
                   ltotal = total;
         }          }
           /* see if any of the state numbers has changed */
         /* save new total */          if (memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0) {
         ltotal = total;                  /* format and update the line */
     }                  summary_format(new, brkdn, procstate_names);
                   line_update(procstates_buffer, new, x_brkdn, y_brkdn);
     /* see if any of the state numbers has changed */                  memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
     if (memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0)          }
     {  
         /* format and update the line */  
         summary_format(new, brkdn, procstate_names);  
         line_update(procstates_buffer, new, x_brkdn, y_brkdn);  
         memcpy(lprocstates, brkdn, num_procstates * sizeof(int));  
     }  
 }  }
   
 /*  /*
Line 374 
Line 336 
  *  Assumptions:  cursor is on the PREVIOUS line   *  Assumptions:  cursor is on the PREVIOUS line
  */   */
   
 static int cpustates_column;  static int      cpustates_column;
   
 /* cpustates_tag() calculates the correct tag to use to label the line */  /* cpustates_tag() calculates the correct tag to use to label the line */
   
 static char *  static char *
 cpustates_tag(void)  cpustates_tag(void)
 {  {
     char *use;          static char *short_tag = "CPU: ";
           static char *long_tag = "CPU states: ";
           char *use;
   
     static char *short_tag = "CPU: ";          /*
     static char *long_tag = "CPU states: ";           * if length + strlen(long_tag) >= screen_width, then we have to use
            * the shorter tag (we subtract 2 to account for ": ")
            */
           if (cpustate_total_length + (int) strlen(long_tag) - 2 >= screen_width)
                   use = short_tag;
           else
                   use = long_tag;
   
     /* if length + strlen(long_tag) >= screen_width, then we have to          /* set cpustates_column accordingly then return result */
        use the shorter tag (we subtract 2 to account for ": ") */          cpustates_column = strlen(use);
     if (cpustate_total_length + (int)strlen(long_tag) - 2 >= screen_width)          return (use);
     {  
         use = short_tag;  
     }  
     else  
     {  
         use = long_tag;  
     }  
   
     /* set cpustates_column accordingly then return result */  
     cpustates_column = strlen(use);  
     return(use);  
 }  }
   
 void  void
 i_cpustates(int *states)  i_cpustates(int *states)
 {  {
     int i = 0;          int i = 0, value;
     int value;          char **names = cpustate_names, *thisname;
     char **names = cpustate_names;  
     char *thisname;  
   
     /* print tag and bump lastline */          /* print tag and bump lastline */
     printf("\n%s", cpustates_tag());          printf("\n%s", cpustates_tag());
     lastline++;          lastline++;
   
     /* now walk thru the names and print the line */          /* now walk thru the names and print the line */
     while ((thisname = *names++) != NULL)          while ((thisname = *names++) != NULL) {
     {                  if (*thisname != '\0') {
         if (*thisname != '\0')                          /* retrieve the value and remember it */
         {                          value = *states++;
             /* retrieve the value and remember it */  
             value = *states++;  
   
             /* if percentage is >= 1000, print it as 100% */                          /* if percentage is >= 1000, print it as 100% */
             printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),                          printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
                    i++ == 0 ? "" : ", ",                              i++ == 0 ? "" : ", ",
                    ((float)value)/10.,                              ((float) value) / 10.,
                    thisname);                              thisname);
                   }
         }          }
     }  
   
     /* copy over values into "last" array */          /* copy over values into "last" array */
     memcpy(lcpustates, states, num_cpustates * sizeof(int));          memcpy(lcpustates, states, num_cpustates * sizeof(int));
 }  }
   
 void  void
 u_cpustates(int *states)  u_cpustates(int *states)
 {  {
     int value;          char **names = cpustate_names, *thisname;
     char **names = cpustate_names;          int value, *lp, *colp;
     char *thisname;  
     int *lp;  
     int *colp;  
   
     Move_to(cpustates_column, y_cpustates);          Move_to(cpustates_column, y_cpustates);
     lastline = y_cpustates;          lastline = y_cpustates;
     lp = lcpustates;          lp = lcpustates;
     colp = cpustate_columns;          colp = cpustate_columns;
   
     /* we could be much more optimal about this */          /* we could be much more optimal about this */
     while ((thisname = *names++) != NULL)          while ((thisname = *names++) != NULL) {
     {                  if (*thisname != '\0') {
         if (*thisname != '\0')                          /* did the value change since last time? */
         {                          if (*lp != *states) {
             /* did the value change since last time? */                                  /* yes, move and change */
             if (*lp != *states)                                  Move_to(cpustates_column + *colp, y_cpustates);
             {                                  lastline = y_cpustates;
                 /* yes, move and change */  
                 Move_to(cpustates_column + *colp, y_cpustates);  
                 lastline = y_cpustates;  
   
                 /* retrieve value and remember it */                                  /* retrieve value and remember it */
                 value = *states;                                  value = *states;
   
                 /* if percentage is >= 1000, print it as 100% */                                  /* if percentage is >= 1000, print it as 100% */
                 printf((value >= 1000 ? "%4.0f" : "%4.1f"),                                  printf((value >= 1000 ? "%4.0f" : "%4.1f"),
                        ((double)value)/10.);                                      ((double) value) / 10.);
   
                 /* remember it for next time */                                  /* remember it for next time */
                 *lp = *states;                                  *lp = *states;
             }                          }
                   }
                   /* increment and move on */
                   lp++;
                   states++;
                   colp++;
         }          }
   
         /* increment and move on */  
         lp++;  
         states++;  
         colp++;  
     }  
 }  }
   
 void  void
 z_cpustates(void)  z_cpustates(void)
 {  {
     int i = 0;          char **names = cpustate_names, *thisname;
     char **names = cpustate_names;          int i = 0, *lp;
     char *thisname;  
     int *lp;  
   
     /* show tag and bump lastline */          /* show tag and bump lastline */
     printf("\n%s", cpustates_tag());          printf("\n%s", cpustates_tag());
     lastline++;          lastline++;
   
     while ((thisname = *names++) != NULL)          while ((thisname = *names++) != NULL) {
     {                  if (*thisname != '\0')
         if (*thisname != '\0')                          printf("%s    %% %s", i++ == 0 ? "" : ", ", thisname);
         {  
             printf("%s    %% %s", i++ == 0 ? "" : ", ", thisname);  
         }          }
     }  
   
     /* fill the "last" array with all -1s, to insure correct updating */          /* fill the "last" array with all -1s, to insure correct updating */
     lp = lcpustates;          lp = lcpustates;
     i = num_cpustates;          i = num_cpustates;
     while (--i >= 0)          while (--i >= 0)
     {                  *lp++ = -1;
         *lp++ = -1;  
     }  
 }  }
   
   static char     memory_buffer[MAX_COLS];
   
 /*  /*
  *  *_memory(stats) - print "Memory: " followed by the memory summary string   *  *_memory(stats) - print "Memory: " followed by the memory summary string
  *   *
  *  Assumptions:  cursor is on "lastline"   *  Assumptions:  cursor is on "lastline"
  *                for i_memory ONLY: cursor is on the previous line   *                for i_memory ONLY: cursor is on the previous line
  */   */
   
 static char memory_buffer[MAX_COLS];  
   
 void  void
 i_memory(int *stats)  i_memory(int *stats)
 {  {
     if (fputs("\nMemory: ", stdout) == EOF)          if (fputs("\nMemory: ", stdout) == EOF)
         exit(1);                  exit(1);
     lastline++;          lastline++;
   
     /* format and print the memory summary */          /* format and print the memory summary */
     summary_format(memory_buffer, stats, memory_names);          summary_format(memory_buffer, stats, memory_names);
     if (fputs(memory_buffer, stdout) == EOF)          if (fputs(memory_buffer, stdout) == EOF)
         exit(1);                  exit(1);
 }  }
   
 void  void
 u_memory(int *stats)  u_memory(int *stats)
 {  {
     static char new[MAX_COLS];          static char new[MAX_COLS];
   
     /* format the new line */          /* format the new line */
     summary_format(new, stats, memory_names);          summary_format(new, stats, memory_names);
     line_update(memory_buffer, new, x_mem, y_mem);          line_update(memory_buffer, new, x_mem, y_mem);
 }  }
   
 /*  /*
Line 554 
Line 494 
  *      respect to screen updates).   *      respect to screen updates).
  */   */
   
 static char next_msg[MAX_COLS + 5];  static char     next_msg[MAX_COLS + 5];
 static int msglen = 0;  static int      msglen = 0;
 /* Invariant: msglen is always the length of the message currently displayed  /*
    on the screen (even when next_msg doesn't contain that message). */   * Invariant: msglen is always the length of the message currently displayed
    * on the screen (even when next_msg doesn't contain that message).
    */
   
 void  void
 i_message(void)  i_message(void)
 {  {
     while (lastline < y_message)          while (lastline < y_message) {
     {                  if (fputc('\n', stdout) == EOF)
         if (fputc('\n', stdout) == EOF)                          exit(1);
             exit(1);                  lastline++;
         lastline++;          }
     }          if (next_msg[0] != '\0') {
     if (next_msg[0] != '\0')                  standout(next_msg);
     {                  msglen = strlen(next_msg);
         standout(next_msg);                  next_msg[0] = '\0';
         msglen = strlen(next_msg);          } else if (msglen > 0) {
         next_msg[0] = '\0';                  (void) clear_eol(msglen);
     }                  msglen = 0;
     else if (msglen > 0)          }
     {  
         (void) clear_eol(msglen);  
         msglen = 0;  
     }  
 }  }
   
 void  void
 u_message(void)  u_message(void)
 {  {
     i_message();          i_message();
 }  }
   
 static int header_length;  static int      header_length;
   
 /*  /*
  *  *_header(text) - print the header for the process area   *  *_header(text) - print the header for the process area
Line 598 
Line 536 
 void  void
 i_header(char *text)  i_header(char *text)
 {  {
     header_length = strlen(text);          header_length = strlen(text);
     if (header_status == ON)          if (header_status == ON) {
     {                  if (putchar('\n') == EOF)
         if (putchar('\n') == EOF)                          exit(1);
             exit(1);                  if (fputs(text, stdout) == EOF)
         if (fputs(text, stdout) == EOF)                          exit(1);
             exit(1);                  lastline++;
         lastline++;          } else if (header_status == ERASE) {
     }                  header_status = OFF;
     else if (header_status == ERASE)          }
     {  
         header_status = OFF;  
     }  
 }  }
   
 /*ARGSUSED*/  /* ARGSUSED */
 void  void
 u_header(char *text)  u_header(char *text)
 {  {
     if (header_status == ERASE)          if (header_status == ERASE) {
     {                  if (putchar('\n') == EOF)
         if (putchar('\n') == EOF)                          exit(1);
             exit(1);                  lastline++;
         lastline++;                  clear_eol(header_length);
         clear_eol(header_length);                  header_status = OFF;
         header_status = OFF;          }
     }  
 }  }
   
 /*  /*
Line 636 
Line 570 
 void  void
 i_process(int line, char *thisline)  i_process(int line, char *thisline)
 {  {
     char *p;          char *p, *base;
     char *base;  
   
     /* make sure we are on the correct line */          /* make sure we are on the correct line */
     while (lastline < y_procs + line)          while (lastline < y_procs + line) {
     {                  if (putchar('\n') == EOF)
         if (putchar('\n') == EOF)                          exit(1);
             exit(1);                  lastline++;
         lastline++;          }
     }  
   
     /* truncate the line to conform to our current screen width */          /* truncate the line to conform to our current screen width */
     thisline[display_width] = '\0';          thisline[display_width] = '\0';
   
     /* write the line out */          /* write the line out */
     if (fputs(thisline, stdout) == EOF)          if (fputs(thisline, stdout) == EOF)
         exit(1);                  exit(1);
   
     /* copy it in to our buffer */          /* copy it in to our buffer */
     base = smart_terminal ? screenbuf + lineindex(line) : screenbuf;          base = smart_terminal ? screenbuf + lineindex(line) : screenbuf;
     p = strecpy(base, thisline);          p = strecpy(base, thisline);
   
     /* zero fill the rest of it */          /* zero fill the rest of it */
     memset(p, 0, display_width - (p - base));          memset(p, 0, display_width - (p - base));
 }  }
   
 void  void
 u_process(int linenum, char *linebuf)  u_process(int linenum, char *linebuf)
 {  {
     char *optr;          int screen_line = linenum + Header_lines;
     int screen_line = linenum + Header_lines;          char *optr, *bufferline;
     char *bufferline;  
   
     /* remember a pointer to the current line in the screen buffer */          /* remember a pointer to the current line in the screen buffer */
     bufferline = &screenbuf[lineindex(linenum)];          bufferline = &screenbuf[lineindex(linenum)];
   
     /* truncate the line to conform to our current screen width */          /* truncate the line to conform to our current screen width */
     linebuf[display_width] = '\0';          linebuf[display_width] = '\0';
   
     /* is line higher than we went on the last display? */          /* is line higher than we went on the last display? */
     if (linenum >= last_hi)          if (linenum >= last_hi) {
     {                  /* yes, just ignore screenbuf and write it out directly */
         /* yes, just ignore screenbuf and write it out directly */                  /* get positioned on the correct line */
         /* get positioned on the correct line */                  if (screen_line - lastline == 1) {
         if (screen_line - lastline == 1)                          if (putchar('\n') == EOF)
         {                                  exit(1);
             if (putchar('\n') == EOF)                          lastline++;
                 exit(1);                  } else {
             lastline++;                          Move_to(0, screen_line);
         }                          lastline = screen_line;
         else                  }
         {  
             Move_to(0, screen_line);  
             lastline = screen_line;  
         }  
   
         /* now write the line */                  /* now write the line */
         if (fputs(linebuf, stdout) == EOF)                  if (fputs(linebuf, stdout) == EOF)
             exit(1);                          exit(1);
   
         /* copy it in to the buffer */                  /* copy it in to the buffer */
         optr = strecpy(bufferline, linebuf);                  optr = strecpy(bufferline, linebuf);
   
         /* zero fill the rest of it */                  /* zero fill the rest of it */
         memset(optr, 0, display_width - (optr - bufferline));                  memset(optr, 0, display_width - (optr - bufferline));
     }          } else {
     else                  line_update(bufferline, linebuf, 0, linenum + Header_lines);
     {          }
         line_update(bufferline, linebuf, 0, linenum + Header_lines);  
     }  
 }  }
   
 void  void
 u_endscreen(int hi)  u_endscreen(int hi)
 {  {
     int screen_line = hi + Header_lines;          int screen_line = hi + Header_lines, i;
     int i;  
   
     if (smart_terminal)          if (smart_terminal) {
     {                  if (hi < last_hi) {
         if (hi < last_hi)                          /* need to blank the remainder of the screen */
         {                          /*
             /* need to blank the remainder of the screen */                           * but only if there is any screen left below this
             /* but only if there is any screen left below this line */                           * line
             if (lastline + 1 < screen_length)                           */
             {                          if (lastline + 1 < screen_length) {
                 /* efficiently move to the end of currently displayed info */                                  /*
                 if (screen_line - lastline < 5)                                   * efficiently move to the end of currently
                 {                                   * displayed info
                     while (lastline < screen_line)                                   */
                     {                                  if (screen_line - lastline < 5) {
                         if (putchar('\n') == EOF)                                          while (lastline < screen_line) {
                             exit(1);                                                  if (putchar('\n') == EOF)
                         lastline++;                                                          exit(1);
                     }                                                  lastline++;
                 }                                          }
                 else                                  } else {
                 {                                          Move_to(0, screen_line);
                     Move_to(0, screen_line);                                          lastline = screen_line;
                     lastline = screen_line;                                  }
                 }  
   
                 if (clear_to_end)                                  if (clear_to_end) {
                 {                                          /* we can do this the easy way */
                     /* we can do this the easy way */                                          putcap(clear_to_end);
                     putcap(clear_to_end);                                  } else {
                                           /* use clear_eol on each line */
                                           i = hi;
                                           while ((void) clear_eol(strlen(&screenbuf[lineindex(i++)])), i < last_hi) {
                                                   if (putchar('\n') == EOF)
                                                           exit(1);
                                           }
                                   }
                           }
                 }                  }
                 else                  last_hi = hi;
                 {  
                     /* use clear_eol on each line */  
                     i = hi;  
                     while ((void) clear_eol(strlen(&screenbuf[lineindex(i++)])), i < last_hi)  
                     {  
                         if (putchar('\n') == EOF)  
                             exit(1);  
                     }  
                 }  
             }  
         }  
         last_hi = hi;  
   
         /* move the cursor to a pleasant place */                  /* move the cursor to a pleasant place */
         Move_to(x_idlecursor, y_idlecursor);                  Move_to(x_idlecursor, y_idlecursor);
         lastline = y_idlecursor;                  lastline = y_idlecursor;
     }          } else {
     else                  /*
     {                   * separate this display from the next with some vertical
         /* separate this display from the next with some vertical room */                   * room
         if (fputs("\n\n", stdout) == EOF)                   */
             exit(1);                  if (fputs("\n\n", stdout) == EOF)
     }                          exit(1);
           }
 }  }
   
 void  void
 display_header(int t)  display_header(int t)
 {  {
     if (t)          if (t) {
     {                  header_status = ON;
         header_status = ON;          } else if (header_status == ON) {
     }                  header_status = ERASE;
     else if (header_status == ON)          }
     {  
         header_status = ERASE;  
     }  
 }  }
   
 void  void
 new_message(int type, const char *msgfmt, ...)  new_message(int type, const char *msgfmt,...)
 {  {
     int i;          va_list ap;
     va_list ap;          int i;
   
     va_start(ap, msgfmt);          va_start(ap, msgfmt);
     /* first, format the message */          /* first, format the message */
     vsnprintf(next_msg, sizeof(next_msg), msgfmt, ap);          vsnprintf(next_msg, sizeof(next_msg), msgfmt, ap);
     va_end(ap);          va_end(ap);
   
     if (msglen > 0)          if (msglen > 0) {
     {                  /* message there already -- can we clear it? */
         /* message there already -- can we clear it? */                  if (!overstrike) {
         if (!overstrike)                          /* yes -- write it and clear to end */
         {                          i = strlen(next_msg);
             /* yes -- write it and clear to end */                          if ((type & MT_delayed) == 0) {
             i = strlen(next_msg);                                  if (type & MT_standout)
             if ((type & MT_delayed) == 0)                                          standout(next_msg);
             {                                  else {
                 if (type & MT_standout)                                          if (fputs(next_msg, stdout) == EOF)
                     standout(next_msg);                                                  exit(1);
                 else {                                  }
                     if (fputs(next_msg, stdout) == EOF)                                  (void) clear_eol(msglen - i);
                         exit(1);                                  msglen = i;
                                   next_msg[0] = '\0';
                           }
                 }                  }
                 (void) clear_eol(msglen - i);          } else {
                 msglen = i;                  if ((type & MT_delayed) == 0) {
                 next_msg[0] = '\0';                          if (type & MT_standout)
             }                                  standout(next_msg);
                           else {
                                   if (fputs(next_msg, stdout) == EOF)
                                           exit(1);
                           }
                           msglen = strlen(next_msg);
                           next_msg[0] = '\0';
                   }
         }          }
     }  
     else  
     {  
         if ((type & MT_delayed) == 0)  
         {  
             if (type & MT_standout)  
                 standout(next_msg);  
             else {  
                 if (fputs(next_msg, stdout) == EOF)  
                     exit(1);  
             }  
             msglen = strlen(next_msg);  
             next_msg[0] = '\0';  
         }  
     }  
 }  }
   
 void  void
 clear_message(void)  clear_message(void)
 {  {
     if (clear_eol(msglen) == 1)          if (clear_eol(msglen) == 1) {
     {                  if (putchar('\r') == EOF)
         if (putchar('\r') == EOF)                          exit(1);
             exit(1);          }
     }  
 }  }
   
 int  int
 readline(char *buffer, int size, int numeric)  readline(char *buffer, int size, int numeric)
 {  {
     char *ptr = buffer;          char *ptr = buffer, ch, cnt = 0, maxcnt = 0;
     char ch;  
     char cnt = 0;  
     char maxcnt = 0;  
   
     /* allow room for null terminator */          /* allow room for null terminator */
     size -= 1;          size -= 1;
   
     /* read loop */          /* read loop */
     while ((fflush(stdout), read(0, ptr, 1) > 0))          while ((fflush(stdout), read(0, ptr, 1) > 0)) {
     {                  /* newline means we are done */
         /* newline means we are done */                  if ((ch = *ptr) == '\n')
         if ((ch = *ptr) == '\n')                          break;
         {  
             break;  
         }  
   
         /* handle special editing characters */                  /* handle special editing characters */
         if (ch == ch_kill)                  if (ch == ch_kill) {
         {                          /* kill line -- account for overstriking */
             /* kill line -- account for overstriking */                          if (overstrike)
             if (overstrike)                                  msglen += maxcnt;
             {  
                 msglen += maxcnt;  
             }  
   
             /* return null string */                          /* return null string */
             *buffer = '\0';                          *buffer = '\0';
             if (putchar('\r') == EOF)                          if (putchar('\r') == EOF)
                 exit(1);                                  exit(1);
             return(-1);                          return (-1);
                   } else if (ch == ch_erase) {
                           /* erase previous character */
                           if (cnt <= 0) {
                                   /* none to erase! */
                                   if (putchar('\7') == EOF)
                                           exit(1);
                           } else {
                                   if (fputs("\b \b", stdout) == EOF)
                                           exit(1);
                                   ptr--;
                                   cnt--;
                           }
                   }
                   /* check for character validity and buffer overflow */
                   else if (cnt == size || (numeric && !isdigit(ch)) ||
                       !isprint(ch)) {
                           /* not legal */
                           if (putchar('\7') == EOF)
                                   exit(1);
                   } else {
                           /* echo it and store it in the buffer */
                           if (putchar(ch) == EOF)
                                   exit(1);
                           ptr++;
                           cnt++;
                           if (cnt > maxcnt)
                                   maxcnt = cnt;
                   }
         }          }
         else if (ch == ch_erase)  
         {  
             /* erase previous character */  
             if (cnt <= 0)  
             {  
                 /* none to erase! */  
                 if (putchar('\7') == EOF)  
                     exit(1);  
             }  
             else  
             {  
                 if (fputs("\b \b", stdout) == EOF)  
                     exit(1);  
                 ptr--;  
                 cnt--;  
             }  
         }  
         /* check for character validity and buffer overflow */  
         else if (cnt == size || (numeric && !isdigit(ch)) ||  
                 !isprint(ch))  
         {  
             /* not legal */  
             if (putchar('\7') == EOF)  
                 exit(1);  
         }  
         else  
         {  
             /* echo it and store it in the buffer */  
             if (putchar(ch) == EOF)  
                 exit(1);  
             ptr++;  
             cnt++;  
             if (cnt > maxcnt)  
             {  
                 maxcnt = cnt;  
             }  
         }  
     }  
   
     /* all done -- null terminate the string */          /* all done -- null terminate the string */
     *ptr = '\0';          *ptr = '\0';
   
     /* account for the extra characters in the message area */          /* account for the extra characters in the message area */
     /* (if terminal overstrikes, remember the furthest they went) */          /* (if terminal overstrikes, remember the furthest they went) */
     msglen += overstrike ? maxcnt : cnt;          msglen += overstrike ? maxcnt : cnt;
   
     /* return either inputted number or string length */          /* return either inputted number or string length */
     if (putchar('\r') == EOF)          if (putchar('\r') == EOF)
         exit(1);                  exit(1);
     return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);          return (cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
 }  }
   
 /* internal support routines */  /* internal support routines */
   
 static int  static int
 string_count(char **pp)  string_count(char **pp)
 {  {
     int cnt;          int cnt;
   
     cnt = 0;          cnt = 0;
     while (*pp++ != NULL)          while (*pp++ != NULL)
     {                  cnt++;
         cnt++;          return (cnt);
     }  
     return(cnt);  
 }  }
   
 static void  static void
 summary_format(char *str, int *numbers, char **names)  summary_format(char *str, int *numbers, char **names)
 {  {
     char *p;          char *p, *thisname;
     int num;          int num;
     char *thisname;  
   
     /* format each number followed by its string */          /* format each number followed by its string */
     p = str;          p = str;
     while ((thisname = *names++) != NULL)          while ((thisname = *names++) != NULL) {
     {                  /* get the number to format */
         /* get the number to format */                  num = *numbers++;
         num = *numbers++;  
   
         if (num >= 0)                  if (num >= 0) {
         {                          /* is this number in kilobytes? */
             /* is this number in kilobytes? */                          if (thisname[0] == 'K') {
             if (thisname[0] == 'K')                                  /* yes: format it as a memory value */
             {                                  p = strecpy(p, format_k(num));
                 /* yes: format it as a memory value */  
                 p = strecpy(p, format_k(num));  
   
                 /* skip over the K, since it was included by format_k */                                  /*
                 p = strecpy(p, thisname+1);                                   * skip over the K, since it was included by
             }                                   * format_k
             else if (num > 0)                                   */
             {                                  p = strecpy(p, thisname + 1);
                 p = strecpy(p, itoa(num));                          } else if (num > 0) {
                 p = strecpy(p, thisname);                                  p = strecpy(p, itoa(num));
             }                                  p = strecpy(p, thisname);
                           }
                   }
                   /* ignore negative numbers, but display corresponding string */
                   else
                           p = strecpy(p, thisname);
         }          }
   
         /* ignore negative numbers, but display corresponding string */          /* if the last two characters in the string are ", ", delete them */
         else          p -= 2;
         {          if (p >= str && p[0] == ',' && p[1] == ' ')
             p = strecpy(p, thisname);                  *p = '\0';
         }  
     }  
   
     /* if the last two characters in the string are ", ", delete them */  
     p -= 2;  
     if (p >= str && p[0] == ',' && p[1] == ' ')  
     {  
         *p = '\0';  
     }  
 }  }
   
 static void  static void
 line_update(char *old, char *new, int start, int line)  line_update(char *old, char *new, int start, int line)
 {  {
     int ch;          int ch, diff, newcol = start + 1, lastcol = start;
     int diff;          char cursor_on_line = No, *current;
     int newcol = start + 1;  
     int lastcol = start;  
     char cursor_on_line = No;  
     char *current;  
   
     /* compare the two strings and only rewrite what has changed */          /* compare the two strings and only rewrite what has changed */
     current = old;          current = old;
 #ifdef DEBUG  #ifdef DEBUG
     fprintf(debug, "line_update, starting at %d\n", start);          fprintf(debug, "line_update, starting at %d\n", start);
     fputs(old, debug);          fputs(old, debug);
     fputc('\n', debug);          fputc('\n', debug);
     fputs(new, debug);          fputs(new, debug);
     fputs("\n-\n", debug);          fputs("\n-\n", debug);
 #endif  #endif
   
     /* start things off on the right foot                   */          /* start things off on the right foot               */
     /* this is to make sure the invariants get set up right */          /* this is to make sure the invariants get set up right */
     if ((ch = *new++) != *old)          if ((ch = *new++) != *old) {
     {                  if (line - lastline == 1 && start == 0) {
         if (line - lastline == 1 && start == 0)                          if (putchar('\n') == EOF)
         {                                  exit(1);
             if (putchar('\n') == EOF)                  } else
                 exit(1);                          Move_to(start, line);
         }  
         else                  cursor_on_line = Yes;
         {  
             Move_to(start, line);  
         }  
         cursor_on_line = Yes;  
         if (putchar(ch) == EOF)  
             exit(1);  
         *old = ch;  
         lastcol = 1;  
     }  
     old++;  
   
     /*  
      *  main loop -- check each character.  If the old and new aren't the  
      *  same, then update the display.  When the distance from the  
      *  current cursor position to the new change is small enough,  
      *  the characters that belong there are written to move the  
      *  cursor over.  
      *  
      *  Invariants:  
      *      lastcol is the column where the cursor currently is sitting  
      *          (always one beyond the end of the last mismatch).  
      */  
     do          /* yes, a do...while */  
     {  
         if ((ch = *new++) != *old)  
         {  
             /* new character is different from old        */  
             /* make sure the cursor is on top of this character */  
             diff = newcol - lastcol;  
             if (diff > 0)  
             {  
                 /* some motion is required--figure out which is shorter */  
                 if (diff < 6 && cursor_on_line)  
                 {  
                     /* overwrite old stuff--get it out of the old buffer */  
                     printf("%.*s", diff, &current[lastcol-start]);  
                 }  
                 else  
                 {  
                     /* use cursor addressing */  
                     Move_to(newcol, line);  
                     cursor_on_line = Yes;  
                 }  
                 /* remember where the cursor is */  
                 lastcol = newcol + 1;  
             }  
             else  
             {  
                 /* already there, update position */  
                 lastcol++;  
             }  
   
             /* write what we need to */  
             if (ch == '\0')  
             {  
                 /* at the end--terminate with a clear-to-end-of-line */  
                 (void) clear_eol(strlen(old));  
             }  
             else  
             {  
                 /* write the new character */  
                 if (putchar(ch) == EOF)                  if (putchar(ch) == EOF)
                     exit(1);                          exit(1);
             }                  *old = ch;
             /* put the new character in the screen buffer */                  lastcol = 1;
             *old = ch;  
         }          }
   
         /* update working column and screen buffer pointer */  
         newcol++;  
         old++;          old++;
   
     } while (ch != '\0');  
   
     /* zero out the rest of the line buffer -- MUST BE DONE! */          /*
     diff = display_width - newcol;           *  main loop -- check each character.  If the old and new aren't the
     if (diff > 0)           *      same, then update the display.  When the distance from the
     {           *      current cursor position to the new change is small enough,
         memset(old, 0, diff);           *      the characters that belong there are written to move the
     }           *      cursor over.
            *
            *      Invariants:
            *          lastcol is the column where the cursor currently is sitting
            *              (always one beyond the end of the last mismatch).
            */
           do {
                   if ((ch = *new++) != *old) {
                           /* new character is different from old    */
                           /* make sure the cursor is on top of this character */
                           diff = newcol - lastcol;
                           if (diff > 0) {
                                   /*
                                    * some motion is required--figure out which
                                    * is shorter
                                    */
                                   if (diff < 6 && cursor_on_line) {
                                           /*
                                            * overwrite old stuff--get it out of
                                            * the old buffer
                                            */
                                           printf("%.*s", diff, &current[lastcol - start]);
                                   } else {
                                           /* use cursor addressing */
                                           Move_to(newcol, line);
                                           cursor_on_line = Yes;
                                   }
                                   /* remember where the cursor is */
                                   lastcol = newcol + 1;
                           } else {
                                   /* already there, update position */
                                   lastcol++;
                           }
   
     /* remember where the current line is */                          /* write what we need to */
     if (cursor_on_line)                          if (ch == '\0') {
     {                                  /*
         lastline = line;                                   * at the end--terminate with a
     }                                   * clear-to-end-of-line
                                    */
                                   (void) clear_eol(strlen(old));
                           } else {
                                   /* write the new character */
                                   if (putchar(ch) == EOF)
                                           exit(1);
                           }
                           /* put the new character in the screen buffer */
                           *old = ch;
                   }
                   /* update working column and screen buffer pointer */
                   newcol++;
                   old++;
           } while (ch != '\0');
   
           /* zero out the rest of the line buffer -- MUST BE DONE! */
           diff = display_width - newcol;
           if (diff > 0)
                   memset(old, 0, diff);
   
           /* remember where the current line is */
           if (cursor_on_line)
                   lastline = line;
 }  }
   
 /*  /*
Line 1113 
Line 977 
  *      characters into '?'.  Replacements are done in place and a pointer   *      characters into '?'.  Replacements are done in place and a pointer
  *      to the original buffer is returned.   *      to the original buffer is returned.
  */   */
   
 char *  char *
 printable(char *str)  printable(char *str)
 {  {
     char *ptr;          char *ptr, ch;
     char ch;  
   
     ptr = str;          ptr = str;
     while ((ch = *ptr) != '\0')          while ((ch = *ptr) != '\0') {
     {                  if (!isprint(ch))
         if (!isprint(ch))                          *ptr = '?';
         {                  ptr++;
             *ptr = '?';  
         }          }
         ptr++;          return (str);
     }  
     return(str);  
 }  }

Legend:
Removed from v.1.13  
changed lines
  Added in v.1.14