[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.24 and 1.25

version 1.24, 2007/03/30 19:21:19 version 1.25, 2007/05/29 00:56:56
Line 47 
Line 47 
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/sched.h>  #include <sys/sched.h>
   #include <curses.h>
   #include <errno.h>
 #include <stdio.h>  #include <stdio.h>
 #include <ctype.h>  #include <ctype.h>
 #include <err.h>  #include <err.h>
   #include <signal.h>
 #include <stdlib.h>  #include <stdlib.h>
 #include <string.h>  #include <string.h>
 #include <signal.h>  
 #include <term.h>  
 #include <unistd.h>  #include <unistd.h>
 #include <stdarg.h>  
   
 #include "screen.h"             /* interface to screen package */  #include "screen.h"             /* interface to screen package */
 #include "layout.h"             /* defines for screen position layout */  #include "layout.h"             /* defines for screen position layout */
Line 70 
Line 70 
 #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      lastline = 0;  
 static int      display_width = MAX_COLS;  static int      display_width = MAX_COLS;
   
 static char    *cpustates_tag(int);  static char    *cpustates_tag(int);
 static int      string_count(char **);  static int      string_count(char **);
 static void     summary_format(char *, size_t, int *, char **);  static void     summary_format(char *, size_t, int *, char **);
 static void     line_update(char *, char *, int, int);  static int      readlinedumb(char *, int, int);
   
 #define lineindex(l) ((l)*display_width)  #define lineindex(l) ((l)*display_width)
   
Line 112 
Line 110 
         OFF, ON, ERASE          OFF, ON, ERASE
 } header_status = ON;  } header_status = ON;
   
   static int
   empty(void)
   {
           return OK;
   }
   
   static int
   myfputs(const char *s)
   {
           return fputs(s, stdout);
   }
   
   static int (*addstrp)(const char *);
   static int (*printwp)(const char *, ...);
   static int (*standoutp)(void);
   static int (*standendp)(void);
   
 int  int
 display_resize(void)  display_resize(void)
 {  {
         int display_lines;          int display_lines;
   
         /* first, deallocate any previous buffer that may have been there */  
         if (screenbuf != NULL)  
                 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;
Line 134 
Line 145 
         if (display_width >= MAX_COLS)          if (display_width >= MAX_COLS)
                 display_width = MAX_COLS - 1;                  display_width = MAX_COLS - 1;
   
         /* now, allocate space for the screen buffer */  
         screenbuf = malloc(display_lines * display_width + 1);  
         if (screenbuf == NULL)  
                 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);
Line 150 
Line 156 
         int display_lines, *ip, i, cpu;          int display_lines, *ip, i, cpu;
         char **pp;          char **pp;
   
           if (smart_terminal) {
                   addstrp = addstr;
                   printwp = (int(*)(const char *, ...))printw;
                   standoutp = standout;
                   standendp = standend;
           } else {
                   addstrp = myfputs;
                   printwp = printf;
                   standoutp = empty;
                   standendp = empty;
           }
   
         y_mem = 2 + ncpu;          y_mem = 2 + ncpu;
         y_message = 3 + ncpu;          y_message = 3 + ncpu;
         y_header = 4 + ncpu;          y_header = 4 + ncpu;
Line 206 
Line 224 
 {  {
         int i;          int i;
   
         /* i_loadave also clears the screen, since it is first */          move(0, 0);
         clear();          clrtoeol();
   
         /* 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);                  printwp("last pid: %5ld;  ", (long) mpid);
   
         printf("load averages");          addstrp("load averages");
   
         for (i = 0; i < 3; i++)          for (i = 0; i < 3; i++)
                 printf("%c %5.2f", i == 0 ? ':' : ',', avenrun[i]);                  printwp("%c %5.2f", i == 0 ? ':' : ',', avenrun[i]);
   
         lmpid = mpid;          lmpid = mpid;
 }  }
   
 void  
 u_loadave(pid_t mpid, double *avenrun)  
 {  
         int i;  
   
         if (mpid != -1) {  
                 /* change screen only when value has really changed */  
                 if (mpid != lmpid) {  
                         Move_to(x_lastpid, y_lastpid);  
                         printf("%5ld", (long) mpid);  
                         lmpid = mpid;  
                 }  
                 /* i remembers x coordinate to move to */  
                 i = x_loadave;  
         } else  
                 i = x_loadave_nompid;  
   
         /* move into position for load averages */  
         Move_to(i, y_loadave);  
   
         /* display new load averages */  
         /* 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.   *  Display the current time.
  *  "ctime" always returns a string that looks like this:   *  "ctime" always returns a string that looks like this:
Line 263 
Line 255 
 {  {
   
         if (smart_terminal) {          if (smart_terminal) {
                 Move_to(screen_width - 8, 0);                  move(0, screen_width - 8);
         } else {          } else {
                 if (fputs("    ", stdout) == EOF)                  if (fputs("    ", stdout) == EOF)
                         exit(1);                          exit(1);
Line 272 
Line 264 
         {          {
                 char *foo;                  char *foo;
                 foo = ctime(tod);                  foo = ctime(tod);
                 if (fputs(foo, stdout) == EOF)                  addstrp(foo);
                         exit(1);  
         }          }
 #endif  #endif
         printf("%-8.8s\n", &(ctime(tod)[11]));          printwp("%-8.8s", &(ctime(tod)[11]));
         lastline = 1;          putn();
 }  }
   
 static int      ltotal = 0;  
 static char     procstates_buffer[MAX_COLS];  
   
 /*  /*
  *  *_procstates(total, brkdn, names) - print the process summary line   *  *_procstates(total, brkdn, names) - print the process summary line
  *   *
Line 293 
Line 281 
 i_procstates(int total, int *brkdn)  i_procstates(int total, int *brkdn)
 {  {
         int i;          int i;
           char procstates_buffer[MAX_COLS];
   
           move(1, 0);
           clrtoeol();
         /* write current number of processes and remember the value */          /* write current number of processes and remember the value */
         printf("%d processes:", total);          printwp("%d processes:", total);
         ltotal = total;  
   
         /* put out enough spaces to get to column 15 */          if (smart_terminal)
         i = digits(total);                  move(1, 15);
         while (i++ < 4) {          else {
                 if (putchar(' ') == EOF)                  /* put out enough spaces to get to column 15 */
                         exit(1);                  i = digits(total);
                   while (i++ < 4) {
                           if (putchar(' ') == EOF)
                                   exit(1);
                   }
         }          }
   
         /* format and print the process state summary */          /* format and print the process state summary */
         summary_format(procstates_buffer, sizeof(procstates_buffer), brkdn,          summary_format(procstates_buffer, sizeof(procstates_buffer), brkdn,
             procstate_names);              procstate_names);
         if (fputs(procstates_buffer, stdout) == EOF)  
                 exit(1);  
   
         /* save the numbers for next time */          addstrp(procstates_buffer);
         memcpy(lprocstates, brkdn, num_procstates * sizeof(int));          putn();
 }  }
   
 void  
 u_procstates(int total, int *brkdn)  
 {  
         static char new[MAX_COLS];  
         int i;  
   
         /* update number of processes only if it has changed */  
         if (ltotal != total) {  
                 /* move and overwrite */  
 #if (x_procstate == 0)  
                 Move_to(x_procstate, y_procstate);  
 #else  
                 /* cursor is already there...no motion needed */  
                 /* assert(lastline == 1); */  
 #endif  
                 printf("%d", total);  
   
                 /* if number of digits differs, rewrite the label */  
                 if (digits(total) != digits(ltotal)) {  
                         if (fputs(" processes:", stdout) == EOF)  
                                 exit(1);  
                         /* put out enough spaces to get to column 15 */  
                         i = digits(total);  
                         while (i++ < 4) {  
                                 if (putchar(' ') == EOF)  
                                         exit(1);  
                         }  
                         /* cursor may end up right where we want it!!! */  
                 }  
                 /* save new total */  
                 ltotal = total;  
         }  
         /* see if any of the state numbers has changed */  
         if (memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0) {  
                 /* format and update the line */  
                 summary_format(new, sizeof(new), brkdn, procstate_names);  
                 line_update(procstates_buffer, new, x_brkdn, y_brkdn);  
                 memcpy(lprocstates, brkdn, num_procstates * sizeof(int));  
         }  
 }  
   
 /*  /*
  *  *_cpustates(states, names) - print the cpu state percentages   *  *_cpustates(states, names) - print the cpu state percentages
  *   *
  *  Assumptions:  cursor is on the PREVIOUS line   *  Assumptions:  cursor is on the PREVIOUS line
  */   */
   
 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 *
Line 397 
Line 346 
                         i = asprintf(&tag, "CPU%.*d states: ", cpulen, cpu);                          i = asprintf(&tag, "CPU%.*d states: ", cpulen, cpu);
                 if (i == -1)                  if (i == -1)
                         tag = NULL;                          tag = NULL;
                 else {                  else
                         cpustates_column = strlen(tag);  
                         old_width = screen_width;                          old_width = screen_width;
                 }  
         }          }
         return (tag);          return (tag);
 }  }
Line 413 
Line 360 
         char **names = cpustate_names, *thisname;          char **names = cpustate_names, *thisname;
   
         for (cpu = 0; cpu < ncpu; cpu++) {          for (cpu = 0; cpu < ncpu; cpu++) {
                   move(2 + cpu, 0);
                   clrtoeol();
                 /* print tag and bump lastline */                  /* print tag and bump lastline */
                 printf("\n%s", cpustates_tag(cpu));                  addstrp(cpustates_tag(cpu));
                 lastline++;  
   
                 /* now walk thru the names and print the line */                  /* now walk thru the names and print the line */
                 names = cpustate_names;                  names = cpustate_names;
Line 427 
Line 375 
                                 value = *states++;                                  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" :                                  printwp((value >= 1000 ? "%s%4.0f%% %s" :
                                     "%s%4.1f%% %s"), i++ == 0 ? "" : ", ",                                      "%s%4.1f%% %s"), i++ == 0 ? "" : ", ",
                                     ((float) value) / 10., thisname);                                      ((float) value) / 10., thisname);
                         }                          }
                 }                  }
                   putn();
                 /* copy over values into "last" array */  
                 memcpy(lcpustates[cpu], ostates, num_cpustates * sizeof(int64_t));  
         }          }
 }  }
   
 void  
 u_cpustates(int64_t *ostates)  
 {  
         char **names, *thisname;  
         int cpu, value, *colp;  
         int64_t *lp, *states;  
   
         for (cpu = 0; cpu < ncpu; cpu++) {  
                 lastline = y_cpustates + cpu;  
                 states = ostates + (CPUSTATES * cpu);  
                 Move_to(cpustates_column, lastline);  
                 lp = lcpustates[cpu];  
                 colp = cpustate_columns;  
   
                 /* we could be much more optimal about this */  
                 names = cpustate_names;  
                 while ((thisname = *names++) != NULL) {  
                         if (*thisname != '\0') {  
                                 /* did the value change since last time? */  
                                 if (*lp != *states) {  
                                         /* yes, move and change */  
                                         lastline = y_cpustates + cpu;  
                                         Move_to(cpustates_column + *colp,  
                                             lastline);  
   
                                         /* retrieve value and remember it */  
                                         value = *states;  
   
                                         /* if percentage is >= 1000,  
                                          * print it as 100%  
                                          */  
                                         printf((value >= 1000 ? "%4.0f" :  
                                             "%4.1f"), ((double) value) / 10.);  
   
                                         /* remember it for next time */  
                                         *lp = *states;  
                                 }  
                         }  
                         /* increment and move on */  
                         lp++;  
                         states++;  
                         colp++;  
                 }  
         }  
 }  
   
 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
  *   *
Line 495 
Line 393 
 void  void
 i_memory(int *stats)  i_memory(int *stats)
 {  {
         if (fputs("\nMemory: ", stdout) == EOF)          char memory_buffer[MAX_COLS];
                 exit(1);  
         lastline++;  
   
           move(y_mem, 0);
           clrtoeol();
           addstrp("Memory: ");
   
         /* format and print the memory summary */          /* format and print the memory summary */
         summary_format(memory_buffer, sizeof(memory_buffer), stats,          summary_format(memory_buffer, sizeof(memory_buffer), stats,
             memory_names);              memory_names);
         if (fputs(memory_buffer, stdout) == EOF)          addstrp(memory_buffer);
                 exit(1);          putn();
 }  }
   
 void  
 u_memory(int *stats)  
 {  
         static char new[MAX_COLS];  
   
         /* format the new line */  
         summary_format(new, sizeof(new), stats, memory_names);  
         line_update(memory_buffer, new, x_mem, y_mem);  
 }  
   
 /*  /*
  *  *_message() - print the next pending message line, or erase the one   *  *_message() - print the next pending message line, or erase the one
  *                that is there.   *                that is there.
Line 540 
Line 430 
 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++;
         }          }
           */
           move(y_message, 0);
         if (next_msg[0] != '\0') {          if (next_msg[0] != '\0') {
                 standout(next_msg);                  standoutp();
                   addstrp(next_msg);
                   standendp();
                   clrtoeol();
                 msglen = strlen(next_msg);                  msglen = strlen(next_msg);
                 next_msg[0] = '\0';                  next_msg[0] = '\0';
         } else if (msglen > 0) {          } else if (msglen > 0) {
                 (void) clear_eol(msglen);                  clrtoeol();
                 msglen = 0;                  msglen = 0;
         }          }
 }  }
   
 void  
 u_message(void)  
 {  
         i_message();  
 }  
   
 static int      header_length;  static int      header_length;
   
 /*  /*
Line 574 
Line 464 
 {  {
         header_length = strlen(text);          header_length = strlen(text);
         if (header_status == ON) {          if (header_status == ON) {
                 if (putchar('\n') == EOF)                  if (!smart_terminal) {
                         exit(1);                          putn();
                 if (fputs(text, stdout) == EOF)                          if (fputs(text, stdout) == EOF)
                         exit(1);                                  exit(1);
                 lastline++;                          putn();
                   } else {
                           move(y_header, 0);
                           clrtoeol();
                           addstrp(text);
                   }
         } else if (header_status == ERASE) {          } else if (header_status == ERASE) {
                 header_status = OFF;                  header_status = OFF;
         }          }
 }  }
   
 /* ARGSUSED */  
 void  
 u_header(char *text)  
 {  
         if (header_status == ERASE) {  
                 if (putchar('\n') == EOF)  
                         exit(1);  
                 lastline++;  
                 clear_eol(header_length);  
                 header_status = OFF;  
         }  
 }  
   
 /*  /*
  *  *_process(line, thisline) - print one process line   *  *_process(line, thisline) - print one process line
  *   *
Line 604 
Line 486 
  */   */
   
 void  void
 i_process(int line, char *thisline)  i_process(int line, char *thisline, int hl)
 {  {
         char *base;  
         size_t len;  
   
         /* make sure we are on the correct line */          /* make sure we are on the correct line */
         while (lastline < y_procs + line) {          move(y_procs + line, 0);
                 if (putchar('\n') == EOF)  
                         exit(1);  
                 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 (hl && smart_terminal)
                 exit(1);                  standoutp();
           addstrp(thisline);
         /* copy it in to our buffer */          if (hl && smart_terminal)
         base = smart_terminal ? screenbuf + lineindex(line) : screenbuf;                  standendp();
         len = strlcpy(base, thisline, display_width);          putn();
         if (len < (size_t)display_width) {          clrtoeol();
                 /* zero fill the rest of it */  
                 memset(base + len, 0, display_width - len);  
         }  
 }  }
   
 void  void
 u_process(int linenum, char *linebuf)  
 {  
         int screen_line = linenum + Header_lines;  
         char *bufferline;  
         size_t len;  
   
         /* remember a pointer to the current line in the screen buffer */  
         bufferline = &screenbuf[lineindex(linenum)];  
   
         /* truncate the line to conform to our current screen width */  
         linebuf[display_width] = '\0';  
         bufferline[display_width] = '\0';  
   
         /* is line higher than we went on the last display? */  
         if (linenum >= last_hi) {  
                 /* yes, just ignore screenbuf and write it out directly */  
                 /* get positioned on the correct line */  
                 if (screen_line - lastline == 1) {  
                         if (putchar('\n') == EOF)  
                                 exit(1);  
                         lastline++;  
                 } else {  
                         Move_to(0, screen_line);  
                         lastline = screen_line;  
                 }  
   
                 /* now write the line */  
                 if (fputs(linebuf, stdout) == EOF)  
                         exit(1);  
   
                 /* copy it in to the buffer */  
                 len = strlcpy(bufferline, linebuf, display_width);  
                 if (len < (size_t)display_width) {  
                         /* zero fill the rest of it */  
                         memset(bufferline + len, 0, display_width - len);  
                 }  
         } else {  
                 line_update(bufferline, linebuf, 0, linenum + Header_lines);  
         }  
 }  
   
 void  
 u_endscreen(int hi)  u_endscreen(int hi)
 {  {
         int screen_line = hi + Header_lines, i;  
   
         if (smart_terminal) {          if (smart_terminal) {
                 if (hi < last_hi) {                  clrtobot();
                         /* need to blank the remainder of the screen */  
                         /*  
                          * but only if there is any screen left below this  
                          * line  
                          */  
                         if (lastline + 1 < screen_length) {  
                                 /*  
                                  * efficiently move to the end of currently  
                                  * displayed info  
                                  */  
                                 if (screen_line - lastline < 5) {  
                                         while (lastline < screen_line) {  
                                                 if (putchar('\n') == EOF)  
                                                         exit(1);  
                                                 lastline++;  
                                         }  
                                 } else {  
                                         Move_to(0, screen_line);  
                                         lastline = screen_line;  
                                 }  
   
                                 if (clear_to_end) {  
                                         /* we can do this the easy way */  
                                         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);  
                                         }  
                                 }  
                         }  
                 }  
                 last_hi = hi;  
   
                 /* move the cursor to a pleasant place */                  /* move the cursor to a pleasant place */
                 Move_to(x_idlecursor, y_idlecursor);                  move(y_idlecursor, x_idlecursor);
                 lastline = y_idlecursor;  
         } else {          } else {
                 /*                  /*
                  * separate this display from the next with some vertical                   * separate this display from the next with some vertical
Line 753 
Line 544 
   
         if (msglen > 0) {          if (msglen > 0) {
                 /* message there already -- can we clear it? */                  /* message there already -- can we clear it? */
                 if (!overstrike) {                  /* yes -- write it and clear to end */
                         /* yes -- write it and clear to end */                  i = strlen(next_msg);
                         i = strlen(next_msg);                  if ((type & MT_delayed) == 0) {
                         if ((type & MT_delayed) == 0) {                          move(y_message, 0);
                                 if (type & MT_standout)                          if (type & MT_standout)
                                         standout(next_msg);                                  standoutp();
                                 else {                          addstrp(next_msg);
                                         if (fputs(next_msg, stdout) == EOF)                          if (type & MT_standout)
                                                 exit(1);                                  standendp();
                                 }                          clrtoeol();
                                 (void) clear_eol(msglen - i);                          msglen = i;
                                 msglen = i;                          next_msg[0] = '\0';
                                 next_msg[0] = '\0';  
                         }  
                 }                  }
         } else {          } else {
                 if ((type & MT_delayed) == 0) {                  if ((type & MT_delayed) == 0) {
                           move(y_message, 0);
                         if (type & MT_standout)                          if (type & MT_standout)
                                 standout(next_msg);                                  standoutp();
                         else {                          addstrp(next_msg);
                                 if (fputs(next_msg, stdout) == EOF)                          if (type & MT_standout)
                                         exit(1);                                  standendp();
                         }                          clrtoeol();
                         msglen = strlen(next_msg);                          msglen = strlen(next_msg);
                         next_msg[0] = '\0';                          next_msg[0] = '\0';
                 }                  }
         }          }
           if (smart_terminal)
                   refresh();
 }  }
   
 void  void
 clear_message(void)  clear_message(void)
 {  {
         if (clear_eol(msglen) == 1) {          move(y_message, 0);
                 if (putchar('\r') == EOF)          clrtoeol();
                         exit(1);  
         }  
 }  }
   
 int  
 readline(char *buffer, int size, int numeric)  static int
   readlinedumb(char *buffer, int size, int numeric)
 {  {
         char *ptr = buffer, ch, cnt = 0, maxcnt = 0;          char *ptr = buffer, ch, cnt = 0, maxcnt = 0;
         extern volatile sig_atomic_t leaveflag;          extern volatile sig_atomic_t leaveflag;
Line 815 
Line 606 
   
                 /* handle special editing characters */                  /* handle special editing characters */
                 if (ch == ch_kill) {                  if (ch == ch_kill) {
                         /* kill line -- account for overstriking */  
                         if (overstrike)  
                                 msglen += maxcnt;  
   
                         /* return null string */                          /* return null string */
                         *buffer = '\0';                          *buffer = '\0';
                         if (putchar('\r') == EOF)                          putr();
                                 exit(1);  
                         return (-1);                          return (-1);
                 } else if (ch == ch_erase) {                  } else if (ch == ch_erase) {
                         /* erase previous character */                          /* erase previous character */
Line 858 
Line 644 
         *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) */          msglen += cnt;
         msglen += overstrike ? maxcnt : cnt;  
   
         /* return either inputted number or string length */          /* return either inputted number or string length */
         if (putchar('\r') == EOF)          putr();
                 exit(1);  
         return (cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);          return (cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
 }  }
   
   int
   readline(char *buffer, int size, int numeric)
   {
           size_t cnt;
   
           /* allow room for null terminator */
           size -= 1;
   
           if (smart_terminal)
                   getnstr(buffer, size);
           else
                   return readlinedumb(buffer, size, numeric);
   
           cnt = strlen(buffer);
           if (cnt > 0 && buffer[cnt - 1] == '\n')
                   buffer[cnt - 1] = '\0';
           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)
Line 934 
Line 737 
                 *p = '\0';                  *p = '\0';
 }  }
   
 static void  
 line_update(char *old, char *new, int start, int line)  
 {  
         int ch, diff, newcol = start + 1, lastcol = start;  
         char cursor_on_line = No, *current;  
   
         /* compare the two strings and only rewrite what has changed */  
         current = old;  
 #ifdef DEBUG  
         fprintf(debug, "line_update, starting at %d\n", start);  
         fputs(old, debug);  
         fputc('\n', debug);  
         fputs(new, debug);  
         fputs("\n-\n", debug);  
 #endif  
   
         /* start things off on the right foot               */  
         /* this is to make sure the invariants get set up right */  
         if ((ch = *new++) != *old) {  
                 if (line - lastline == 1 && start == 0) {  
                         if (putchar('\n') == EOF)  
                                 exit(1);  
                 } else  
                         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 {  
                 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)  
                                         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;  
 }  
   
 /*  /*
  *  printable(str) - make the string pointed to by "str" into one that is   *  printable(str) - make the string pointed to by "str" into one that is
  *      printable (i.e.: all ascii), by converting all non-printable   *      printable (i.e.: all ascii), by converting all non-printable
Line 1054 
Line 755 
                 ptr++;                  ptr++;
         }          }
         return (str);          return (str);
   }
   
   
   /*
    *  show_help() - display the help screen; invoked in response to
    *              either 'h' or '?'.
    */
   void
   show_help(void)
   {
           if (smart_terminal) {
                   clear();
                   nl();
           }
           printwp("These single-character commands are available:\n"
               "\n"
               "^L           - redraw screen\n"
               "+            - reset any g, p, or u filters\n"
               "C            - toggle the display of command line arguments\n"
               "d count      - show `count' displays, then exit\n"
               "e            - list errors generated by last \"kill\" or \"renice\" command\n"
               "h | ?        - help; show this text\n"
               "g string     - filter on command name (g+ selects all commands)\n"
               "I | i        - toggle the display of idle processes\n"
               "k [-sig] pid - send signal `-sig' to process `pid'\n"
               "n|# count    - show `count' processes\n"
               "o field      - specify sort order (size, res, cpu, time, pri)\n"
               "P pid        - highlight process `pid' (P+ switches highlighting off)\n"
               "p pid        - display process by `pid' (p+ selects all processes)\n"
               "q            - quit\n"
               "r count pid  - renice process `pid' to nice value `count'\n"
               "S            - toggle the display of system processes\n"
               "s time       - change delay between displays to `time' seconds\n"
               "T            - toggle the display of threads\n"
               "u user       - display processes for `user' (u+ selects all users)\n"
               "\n");
   
           if (smart_terminal) {
                   nonl();
                   refresh();
           }
   }
   
   /*
    *  show_errors() - display on stdout the current log of errors.
    */
   void
   show_errors(void)
   {
           struct errs *errp = errs;
           int cnt = 0;
   
           if (smart_terminal) {
                   clear();
                   nl();
           }
           printwp("%d error%s:\n\n", errcnt, errcnt == 1 ? "" : "s");
           while (cnt++ < errcnt) {
                   printf("%5s: %s\n", errp->arg,
                       errp->err == 0 ? "Not a number" : strerror(errp->err));
                   errp++;
           }
           if (smart_terminal) {
                   nonl();
                   refresh();
           }
   }
   
   void
   anykey(void)
   {
           int ch;
           size_t len;
   
           standoutp();
           addstrp("Hit any key to continue: ");
           standendp();
           if (smart_terminal)
                   refresh();
           else
                   fflush(stdout);
           while (1) {
                   len = read(STDIN_FILENO, &ch, 1);
                   if (len == -1 && errno == EINTR)
                           continue;
                   if (len == 0)
                           exit(1);
                   break;
           }
 }  }

Legend:
Removed from v.1.24  
changed lines
  Added in v.1.25