xref: /freebsd-src/usr.bin/top/display.c (revision b7f62c6042f8b4b322d9fa20a8c6a81a9a58c164)
13be6ef06SEitan Adler /*
23be6ef06SEitan Adler  *  Top users/processes display for Unix
33be6ef06SEitan Adler  *  Version 3
43be6ef06SEitan Adler  *
53be6ef06SEitan Adler  *  This program may be freely redistributed,
63be6ef06SEitan Adler  *  but this entire comment MUST remain intact.
73be6ef06SEitan Adler  *
83be6ef06SEitan Adler  *  Copyright (c) 1984, 1989, William LeFebvre, Rice University
93be6ef06SEitan Adler  *  Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
103be6ef06SEitan Adler  */
113be6ef06SEitan Adler 
123be6ef06SEitan Adler /*
133be6ef06SEitan Adler  *  This file contains the routines that display information on the screen.
143be6ef06SEitan Adler  *  Each section of the screen has two routines:  one for initially writing
153be6ef06SEitan Adler  *  all constant and dynamic text, and one for only updating the text that
163be6ef06SEitan Adler  *  changes.  The prefix "i_" is used on all the "initial" routines and the
173be6ef06SEitan Adler  *  prefix "u_" is used for all the "updating" routines.
183be6ef06SEitan Adler  *
193be6ef06SEitan Adler  *  ASSUMPTIONS:
203be6ef06SEitan Adler  *        None of the "i_" routines use any of the termcap capabilities.
213be6ef06SEitan Adler  *        In this way, those routines can be safely used on terminals that
223be6ef06SEitan Adler  *        have minimal (or nonexistant) terminal capabilities.
233be6ef06SEitan Adler  *
243be6ef06SEitan Adler  *        The routines are called in this order:  *_loadave, i_timeofday,
253be6ef06SEitan Adler  *        *_procstates, *_cpustates, *_memory, *_message, *_header,
263be6ef06SEitan Adler  *        *_process, u_endscreen.
273be6ef06SEitan Adler  */
283be6ef06SEitan Adler 
298d0d2676SEitan Adler #include <sys/cdefs.h>
30eae589f1SEitan Adler #include <sys/resource.h>
313be6ef06SEitan Adler #include <sys/time.h>
323be6ef06SEitan Adler 
33cffee2bcSEitan Adler #include <assert.h>
343be6ef06SEitan Adler #include <ctype.h>
3517be5f23SEitan Adler #include <err.h>
361d6a4ba3SEitan Adler #include <stdarg.h>
370b2f6ed1SEitan Adler #include <stdbool.h>
38caee4883SEitan Adler #include <stdlib.h>
398d0d2676SEitan Adler #include <stdio.h>
40caee4883SEitan Adler #include <string.h>
413be6ef06SEitan Adler #include <termcap.h>
423be6ef06SEitan Adler #include <time.h>
433be6ef06SEitan Adler #include <unistd.h>
443be6ef06SEitan Adler 
453be6ef06SEitan Adler #include "screen.h"		/* interface to screen package */
463be6ef06SEitan Adler #include "layout.h"		/* defines for screen position layout */
473be6ef06SEitan Adler #include "display.h"
483be6ef06SEitan Adler #include "top.h"
493be6ef06SEitan Adler #include "machine.h"		/* we should eliminate this!!! */
503be6ef06SEitan Adler #include "utils.h"
513be6ef06SEitan Adler 
523be6ef06SEitan Adler #ifdef DEBUG
533be6ef06SEitan Adler FILE *debug;
543be6ef06SEitan Adler #endif
553be6ef06SEitan Adler 
563be6ef06SEitan Adler static int lmpid = 0;
573be6ef06SEitan Adler static int last_hi = 0;		/* used in u_process and u_endscreen */
583be6ef06SEitan Adler static int lastline = 0;
593be6ef06SEitan Adler 
600a59db87SDaichi GOTO #define lineindex(l) ((l)*screen_width)
613be6ef06SEitan Adler 
623be6ef06SEitan Adler 
633be6ef06SEitan Adler /* things initialized by display_init and used thruout */
643be6ef06SEitan Adler 
653be6ef06SEitan Adler /* buffer of proc information lines for display updating */
66a5ca08edSEitan Adler static char *screenbuf = NULL;
673be6ef06SEitan Adler 
689f8096e3SEitan Adler static const char * const *procstate_names;
699f8096e3SEitan Adler static const char * const *cpustate_names;
709f8096e3SEitan Adler static const char * const *memory_names;
719f8096e3SEitan Adler static const char * const *arc_names;
729f8096e3SEitan Adler static const char * const *carc_names;
739f8096e3SEitan Adler static const char * const *swap_names;
743be6ef06SEitan Adler 
753be6ef06SEitan Adler static int num_procstates;
763be6ef06SEitan Adler static int num_cpustates;
773be6ef06SEitan Adler static int num_memory;
783be6ef06SEitan Adler static int num_swap;
793be6ef06SEitan Adler 
803be6ef06SEitan Adler static int *lprocstates;
813be6ef06SEitan Adler static int *lcpustates;
823be6ef06SEitan Adler static int *lmemory;
833be6ef06SEitan Adler static int *lswap;
843be6ef06SEitan Adler 
853be6ef06SEitan Adler static int num_cpus;
863be6ef06SEitan Adler static int *cpustate_columns;
873be6ef06SEitan Adler static int cpustate_total_length;
883be6ef06SEitan Adler static int cpustates_column;
893be6ef06SEitan Adler 
903be6ef06SEitan Adler static enum { OFF, ON, ERASE } header_status = ON;
913be6ef06SEitan Adler 
92eae589f1SEitan Adler static void summary_format(char *, int *, const char * const *);
93666cf873SEitan Adler static void line_update(char *, char *, int, int);
943be6ef06SEitan Adler 
950a59db87SDaichi GOTO static int setup_buffer_bufsiz = 0;
960a59db87SDaichi GOTO static char * setup_buffer(char *, int);
970a59db87SDaichi GOTO 
983be6ef06SEitan Adler int  x_lastpid =	10;
993be6ef06SEitan Adler int  y_lastpid =	0;
1003be6ef06SEitan Adler int  x_loadave =	33;
1013be6ef06SEitan Adler int  x_loadave_nompid =	15;
1023be6ef06SEitan Adler int  y_loadave =	0;
1033be6ef06SEitan Adler int  x_procstate =	0;
1043be6ef06SEitan Adler int  y_procstate =	1;
1053be6ef06SEitan Adler int  x_brkdn =		15;
1063be6ef06SEitan Adler int  y_brkdn =		1;
1073be6ef06SEitan Adler int  x_mem =		5;
1083be6ef06SEitan Adler int  y_mem =		3;
1093be6ef06SEitan Adler int  x_arc =		5;
1103be6ef06SEitan Adler int  y_arc =		4;
1113be6ef06SEitan Adler int  x_carc =		5;
1123be6ef06SEitan Adler int  y_carc =		5;
1133be6ef06SEitan Adler int  x_swap =		6;
1143be6ef06SEitan Adler int  y_swap =		4;
1153be6ef06SEitan Adler int  y_message =	5;
1163be6ef06SEitan Adler int  x_header =		0;
1173be6ef06SEitan Adler int  y_header =		6;
1183be6ef06SEitan Adler int  x_idlecursor =	0;
1193be6ef06SEitan Adler int  y_idlecursor =	5;
1203be6ef06SEitan Adler int  y_procs =		7;
1213be6ef06SEitan Adler 
1223be6ef06SEitan Adler int  y_cpustates =	2;
1233be6ef06SEitan Adler int  Header_lines =	7;
1243be6ef06SEitan Adler 
125f6234b51SEitan Adler int
display_resize(void)126f6234b51SEitan Adler display_resize(void)
1273be6ef06SEitan Adler {
12898c299e0SEitan Adler     int lines;
1293be6ef06SEitan Adler 
1303be6ef06SEitan Adler     /* first, deallocate any previous buffer that may have been there */
1313be6ef06SEitan Adler     if (screenbuf != NULL)
1323be6ef06SEitan Adler     {
1333be6ef06SEitan Adler 	free(screenbuf);
1343be6ef06SEitan Adler     }
1353be6ef06SEitan Adler 
1363be6ef06SEitan Adler     /* calculate the current dimensions */
1373be6ef06SEitan Adler     /* if operating in "dumb" mode, we only need one line */
1383be6ef06SEitan Adler     lines = smart_terminal ? screen_length - Header_lines : 1;
1393be6ef06SEitan Adler 
1403be6ef06SEitan Adler     if (lines < 0)
1413be6ef06SEitan Adler 	lines = 0;
1423be6ef06SEitan Adler 
1433be6ef06SEitan Adler     /* now, allocate space for the screen buffer */
1440a59db87SDaichi GOTO     screenbuf = calloc(lines, screen_width);
1454fedcd49SEitan Adler     if (screenbuf == NULL)
1463be6ef06SEitan Adler     {
1473be6ef06SEitan Adler 	/* oops! */
1483be6ef06SEitan Adler 	return(-1);
1493be6ef06SEitan Adler     }
1503be6ef06SEitan Adler 
1513be6ef06SEitan Adler     /* return number of lines available */
1523be6ef06SEitan Adler     /* for dumb terminals, pretend like we can show any amount */
1533be6ef06SEitan Adler     return(smart_terminal ? lines : Largest);
1543be6ef06SEitan Adler }
1553be6ef06SEitan Adler 
1561de63842SEitan Adler int
display_updatecpus(struct statics * statics)1571de63842SEitan Adler display_updatecpus(struct statics *statics)
1583be6ef06SEitan Adler {
15998c299e0SEitan Adler     int lines;
16098c299e0SEitan Adler     int i;
1613be6ef06SEitan Adler 
1623be6ef06SEitan Adler     /* call resize to do the dirty work */
1633be6ef06SEitan Adler     lines = display_resize();
1643be6ef06SEitan Adler     if (pcpu_stats)
1653be6ef06SEitan Adler 		num_cpus = statics->ncpus;
1663be6ef06SEitan Adler     else
1673be6ef06SEitan Adler 		num_cpus = 1;
1683be6ef06SEitan Adler     cpustates_column = 5;	/* CPU: */
1696e0632dbSEitan Adler     if (num_cpus > 1) {
1706e0632dbSEitan Adler 		cpustates_column += 1 + digits(num_cpus); /* CPU #: */
1716e0632dbSEitan Adler 	}
1723be6ef06SEitan Adler 
1733be6ef06SEitan Adler     /* fill the "last" array with all -1s, to insure correct updating */
1746e0632dbSEitan Adler 	for (i = 0; i < num_cpustates * num_cpus; ++i) {
1756e0632dbSEitan Adler 		lcpustates[i] = -1;
1763be6ef06SEitan Adler     }
1773be6ef06SEitan Adler 
1783be6ef06SEitan Adler     return(lines);
1793be6ef06SEitan Adler }
1803be6ef06SEitan Adler 
1811de63842SEitan Adler int
display_init(struct statics * statics)1821de63842SEitan Adler display_init(struct statics * statics)
1833be6ef06SEitan Adler {
18498c299e0SEitan Adler     int lines;
185d0f687d3SDimitry Andric     const char * const *pp;
18698c299e0SEitan Adler     int *ip;
18798c299e0SEitan Adler     int i;
1883be6ef06SEitan Adler 
1893be6ef06SEitan Adler     lines = display_updatecpus(statics);
1903be6ef06SEitan Adler 
1913be6ef06SEitan Adler     /* only do the rest if we need to */
1923be6ef06SEitan Adler     if (lines > -1)
1933be6ef06SEitan Adler     {
1943be6ef06SEitan Adler 	/* save pointers and allocate space for names */
1953be6ef06SEitan Adler 	procstate_names = statics->procstate_names;
196eae589f1SEitan Adler 	num_procstates = 8;
197cffee2bcSEitan Adler 	assert(num_procstates > 0);
1984fedcd49SEitan Adler 	lprocstates = calloc(num_procstates, sizeof(int));
1993be6ef06SEitan Adler 
2003be6ef06SEitan Adler 	cpustate_names = statics->cpustate_names;
2013be6ef06SEitan Adler 
2023be6ef06SEitan Adler 	swap_names = statics->swap_names;
203eae589f1SEitan Adler 	num_swap = 7;
204cffee2bcSEitan Adler 	assert(num_swap > 0);
2054fedcd49SEitan Adler 	lswap = calloc(num_swap, sizeof(int));
206eae589f1SEitan Adler 	num_cpustates = CPUSTATES;
207cffee2bcSEitan Adler 	assert(num_cpustates > 0);
2084fedcd49SEitan Adler 	lcpustates = calloc(num_cpustates * sizeof(int), statics->ncpus);
2094fedcd49SEitan Adler 	cpustate_columns = calloc(num_cpustates, sizeof(int));
2103be6ef06SEitan Adler 
2113be6ef06SEitan Adler 	memory_names = statics->memory_names;
212eae589f1SEitan Adler 	num_memory = 7;
213cffee2bcSEitan Adler 	assert(num_memory > 0);
2144fedcd49SEitan Adler 	lmemory = calloc(num_memory, sizeof(int));
2153be6ef06SEitan Adler 
2163be6ef06SEitan Adler 	arc_names = statics->arc_names;
2173be6ef06SEitan Adler 	carc_names = statics->carc_names;
2183be6ef06SEitan Adler 
2193be6ef06SEitan Adler 	/* calculate starting columns where needed */
2203be6ef06SEitan Adler 	cpustate_total_length = 0;
2213be6ef06SEitan Adler 	pp = cpustate_names;
2223be6ef06SEitan Adler 	ip = cpustate_columns;
2233be6ef06SEitan Adler 	while (*pp != NULL)
2243be6ef06SEitan Adler 	{
2253be6ef06SEitan Adler 	    *ip++ = cpustate_total_length;
2263be6ef06SEitan Adler 	    if ((i = strlen(*pp++)) > 0)
2273be6ef06SEitan Adler 	    {
2283be6ef06SEitan Adler 		cpustate_total_length += i + 8;
2293be6ef06SEitan Adler 	    }
2303be6ef06SEitan Adler 	}
2313be6ef06SEitan Adler     }
2323be6ef06SEitan Adler 
2333be6ef06SEitan Adler     /* return number of lines available */
2343be6ef06SEitan Adler     return(lines);
2353be6ef06SEitan Adler }
2363be6ef06SEitan Adler 
2373be6ef06SEitan Adler void
i_loadave(int mpid,double avenrun[])238f6234b51SEitan Adler i_loadave(int mpid, double avenrun[])
2393be6ef06SEitan Adler {
24098c299e0SEitan Adler     int i;
2413be6ef06SEitan Adler 
2423be6ef06SEitan Adler     /* i_loadave also clears the screen, since it is first */
2433be6ef06SEitan Adler     top_clear();
2443be6ef06SEitan Adler 
2453be6ef06SEitan Adler     /* mpid == -1 implies this system doesn't have an _mpid */
2463be6ef06SEitan Adler     if (mpid != -1)
2473be6ef06SEitan Adler     {
2483be6ef06SEitan Adler 	printf("last pid: %5d;  ", mpid);
2493be6ef06SEitan Adler     }
2503be6ef06SEitan Adler 
2513be6ef06SEitan Adler     printf("load averages");
2523be6ef06SEitan Adler 
2533be6ef06SEitan Adler     for (i = 0; i < 3; i++)
2543be6ef06SEitan Adler     {
255*b7f62c60SPiotr Kubaj 	printf("%c %7.2f",
2563be6ef06SEitan Adler 	    i == 0 ? ':' : ',',
2573be6ef06SEitan Adler 	    avenrun[i]);
2583be6ef06SEitan Adler     }
2593be6ef06SEitan Adler     lmpid = mpid;
2603be6ef06SEitan Adler }
2613be6ef06SEitan Adler 
2623be6ef06SEitan Adler void
u_loadave(int mpid,double * avenrun)263f6234b51SEitan Adler u_loadave(int mpid, double *avenrun)
2643be6ef06SEitan Adler {
26598c299e0SEitan Adler     int i;
2663be6ef06SEitan Adler 
2673be6ef06SEitan Adler     if (mpid != -1)
2683be6ef06SEitan Adler     {
2693be6ef06SEitan Adler 	/* change screen only when value has really changed */
2703be6ef06SEitan Adler 	if (mpid != lmpid)
2713be6ef06SEitan Adler 	{
2723be6ef06SEitan Adler 	    Move_to(x_lastpid, y_lastpid);
2733be6ef06SEitan Adler 	    printf("%5d", mpid);
2743be6ef06SEitan Adler 	    lmpid = mpid;
2753be6ef06SEitan Adler 	}
2763be6ef06SEitan Adler 
2773be6ef06SEitan Adler 	/* i remembers x coordinate to move to */
2783be6ef06SEitan Adler 	i = x_loadave;
2793be6ef06SEitan Adler     }
2803be6ef06SEitan Adler     else
2813be6ef06SEitan Adler     {
2823be6ef06SEitan Adler 	i = x_loadave_nompid;
2833be6ef06SEitan Adler     }
2843be6ef06SEitan Adler 
2853be6ef06SEitan Adler     /* move into position for load averages */
2863be6ef06SEitan Adler     Move_to(i, y_loadave);
2873be6ef06SEitan Adler 
2883be6ef06SEitan Adler     /* display new load averages */
2893be6ef06SEitan Adler     /* we should optimize this and only display changes */
2903be6ef06SEitan Adler     for (i = 0; i < 3; i++)
2913be6ef06SEitan Adler     {
292*b7f62c60SPiotr Kubaj 	printf("%s%7.2f",
2933be6ef06SEitan Adler 	    i == 0 ? "" : ", ",
2943be6ef06SEitan Adler 	    avenrun[i]);
2953be6ef06SEitan Adler     }
2963be6ef06SEitan Adler }
2973be6ef06SEitan Adler 
2983be6ef06SEitan Adler void
i_timeofday(time_t * tod)299f6234b51SEitan Adler i_timeofday(time_t *tod)
3003be6ef06SEitan Adler {
3013be6ef06SEitan Adler     /*
3023be6ef06SEitan Adler      *  Display the current time.
3033be6ef06SEitan Adler      *  "ctime" always returns a string that looks like this:
3043be6ef06SEitan Adler      *
3053be6ef06SEitan Adler      *	Sun Sep 16 01:03:52 1973
3063be6ef06SEitan Adler      *      012345678901234567890123
3073be6ef06SEitan Adler      *	          1         2
3083be6ef06SEitan Adler      *
3093be6ef06SEitan Adler      *  We want indices 11 thru 18 (length 8).
3103be6ef06SEitan Adler      */
3113be6ef06SEitan Adler 
3123be6ef06SEitan Adler     if (smart_terminal)
3133be6ef06SEitan Adler     {
3143be6ef06SEitan Adler 	Move_to(screen_width - 8, 0);
3153be6ef06SEitan Adler     }
3163be6ef06SEitan Adler     else
3173be6ef06SEitan Adler     {
3183be6ef06SEitan Adler 	fputs("    ", stdout);
3193be6ef06SEitan Adler     }
3203be6ef06SEitan Adler #ifdef DEBUG
3213be6ef06SEitan Adler     {
3223be6ef06SEitan Adler 	char *foo;
3233be6ef06SEitan Adler 	foo = ctime(tod);
3243be6ef06SEitan Adler 	fputs(foo, stdout);
3253be6ef06SEitan Adler     }
3263be6ef06SEitan Adler #endif
3273be6ef06SEitan Adler     printf("%-8.8s\n", &(ctime(tod)[11]));
3283be6ef06SEitan Adler     lastline = 1;
3293be6ef06SEitan Adler }
3303be6ef06SEitan Adler 
3313be6ef06SEitan Adler static int ltotal = 0;
3320a59db87SDaichi GOTO static char *procstates_buffer = NULL;
3333be6ef06SEitan Adler 
3343be6ef06SEitan Adler /*
3353be6ef06SEitan Adler  *  *_procstates(total, brkdn, names) - print the process summary line
3363be6ef06SEitan Adler  *
3373be6ef06SEitan Adler  *  Assumptions:  cursor is at the beginning of the line on entry
3383be6ef06SEitan Adler  *		  lastline is valid
3393be6ef06SEitan Adler  */
3403be6ef06SEitan Adler 
3413be6ef06SEitan Adler void
i_procstates(int total,int * brkdn)342f6234b51SEitan Adler i_procstates(int total, int *brkdn)
3433be6ef06SEitan Adler {
34498c299e0SEitan Adler     int i;
3453be6ef06SEitan Adler 
3460a59db87SDaichi GOTO     procstates_buffer = setup_buffer(procstates_buffer, 0);
3470a59db87SDaichi GOTO 
3483be6ef06SEitan Adler     /* write current number of processes and remember the value */
34904354d57SMark Johnston     printf("%d %s:", total, ps.thread ? "threads" : "processes");
3503be6ef06SEitan Adler     ltotal = total;
3513be6ef06SEitan Adler 
3523be6ef06SEitan Adler     /* put out enough spaces to get to column 15 */
3533be6ef06SEitan Adler     i = digits(total);
35404354d57SMark Johnston     while (i++ < (ps.thread ? 6 : 4))
3553be6ef06SEitan Adler     {
3563be6ef06SEitan Adler 	putchar(' ');
3573be6ef06SEitan Adler     }
3583be6ef06SEitan Adler 
3593be6ef06SEitan Adler     /* format and print the process state summary */
3603be6ef06SEitan Adler     summary_format(procstates_buffer, brkdn, procstate_names);
3613be6ef06SEitan Adler     fputs(procstates_buffer, stdout);
3623be6ef06SEitan Adler 
3633be6ef06SEitan Adler     /* save the numbers for next time */
3643be6ef06SEitan Adler     memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
3653be6ef06SEitan Adler }
3663be6ef06SEitan Adler 
3673be6ef06SEitan Adler void
u_procstates(int total,int * brkdn)368f6234b51SEitan Adler u_procstates(int total, int *brkdn)
3693be6ef06SEitan Adler {
3700a59db87SDaichi GOTO     static char *new = NULL;
37198c299e0SEitan Adler     int i;
3723be6ef06SEitan Adler 
3730a59db87SDaichi GOTO     new = setup_buffer(new, 0);
3740a59db87SDaichi GOTO 
3753be6ef06SEitan Adler     /* update number of processes only if it has changed */
3763be6ef06SEitan Adler     if (ltotal != total)
3773be6ef06SEitan Adler     {
3783be6ef06SEitan Adler 	/* move and overwrite */
37959c50d82SEitan Adler 	if (x_procstate == 0) {
3803be6ef06SEitan Adler 	    Move_to(x_procstate, y_procstate);
38159c50d82SEitan Adler 	}
38259c50d82SEitan Adler 	else {
3833be6ef06SEitan Adler 	    /* cursor is already there...no motion needed */
38459c50d82SEitan Adler 	    assert(lastline == 1);
38559c50d82SEitan Adler 	}
3863be6ef06SEitan Adler 	printf("%d", total);
3873be6ef06SEitan Adler 
3883be6ef06SEitan Adler 	/* if number of digits differs, rewrite the label */
3893be6ef06SEitan Adler 	if (digits(total) != digits(ltotal))
3903be6ef06SEitan Adler 	{
39104354d57SMark Johnston 	    printf(" %s:", ps.thread ? "threads" : "processes");
3923be6ef06SEitan Adler 	    /* put out enough spaces to get to column 15 */
3933be6ef06SEitan Adler 	    i = digits(total);
39404354d57SMark Johnston 	    while (i++ < (ps.thread ? 6 : 4))
3953be6ef06SEitan Adler 	    {
3963be6ef06SEitan Adler 		putchar(' ');
3973be6ef06SEitan Adler 	    }
3983be6ef06SEitan Adler 	    /* cursor may end up right where we want it!!! */
3993be6ef06SEitan Adler 	}
4003be6ef06SEitan Adler 
4013be6ef06SEitan Adler 	/* save new total */
4023be6ef06SEitan Adler 	ltotal = total;
4033be6ef06SEitan Adler     }
4043be6ef06SEitan Adler 
4053be6ef06SEitan Adler     /* see if any of the state numbers has changed */
4063be6ef06SEitan Adler     if (memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0)
4073be6ef06SEitan Adler     {
4083be6ef06SEitan Adler 	/* format and update the line */
4093be6ef06SEitan Adler 	summary_format(new, brkdn, procstate_names);
4103be6ef06SEitan Adler 	line_update(procstates_buffer, new, x_brkdn, y_brkdn);
4113be6ef06SEitan Adler 	memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
4123be6ef06SEitan Adler     }
4133be6ef06SEitan Adler }
4143be6ef06SEitan Adler 
4153be6ef06SEitan Adler void
i_cpustates(int * states)416f6234b51SEitan Adler i_cpustates(int *states)
4173be6ef06SEitan Adler {
41898c299e0SEitan Adler     int i = 0;
41998c299e0SEitan Adler     int value;
420eae589f1SEitan Adler     const char * const *names;
421eae589f1SEitan Adler     const char *thisname;
42208092a9bSDaichi GOTO     int *hstates = states;
4233be6ef06SEitan Adler     int cpu;
4243be6ef06SEitan Adler 
4253be6ef06SEitan Adler for (cpu = 0; cpu < num_cpus; cpu++) {
4263be6ef06SEitan Adler     names = cpustate_names;
4273be6ef06SEitan Adler 
4283be6ef06SEitan Adler     /* print tag and bump lastline */
4293be6ef06SEitan Adler     if (num_cpus == 1)
4303be6ef06SEitan Adler 	printf("\nCPU: ");
4313be6ef06SEitan Adler     else {
4323be6ef06SEitan Adler 	value = printf("\nCPU %d: ", cpu);
4333be6ef06SEitan Adler 	while (value++ <= cpustates_column)
4343be6ef06SEitan Adler 		printf(" ");
4353be6ef06SEitan Adler     }
4363be6ef06SEitan Adler     lastline++;
4373be6ef06SEitan Adler 
4383be6ef06SEitan Adler     /* now walk thru the names and print the line */
4393be6ef06SEitan Adler     while ((thisname = *names++) != NULL)
4403be6ef06SEitan Adler     {
4413be6ef06SEitan Adler 	if (*thisname != '\0')
4423be6ef06SEitan Adler 	{
4433be6ef06SEitan Adler 	    /* retrieve the value and remember it */
4443be6ef06SEitan Adler 	    value = *states++;
4453be6ef06SEitan Adler 
4463be6ef06SEitan Adler 	    /* if percentage is >= 1000, print it as 100% */
4473be6ef06SEitan Adler 	    printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"),
4483be6ef06SEitan Adler 		   (i++ % num_cpustates) == 0 ? "" : ", ",
4493be6ef06SEitan Adler 		   ((float)value)/10.,
4503be6ef06SEitan Adler 		   thisname);
4513be6ef06SEitan Adler 	}
4523be6ef06SEitan Adler     }
4533be6ef06SEitan Adler }
4543be6ef06SEitan Adler 
4553be6ef06SEitan Adler     /* copy over values into "last" array */
45608092a9bSDaichi GOTO     states = hstates;
4573be6ef06SEitan Adler     memcpy(lcpustates, states, num_cpustates * sizeof(int) * num_cpus);
4583be6ef06SEitan Adler }
4593be6ef06SEitan Adler 
4603be6ef06SEitan Adler void
u_cpustates(int * states)461f6234b51SEitan Adler u_cpustates(int *states)
4623be6ef06SEitan Adler {
46398c299e0SEitan Adler     int value;
464d408c8f7SEitan Adler     const char * const *names;
465d408c8f7SEitan Adler     const char *thisname;
46608092a9bSDaichi GOTO     int *hstates = states;
46798c299e0SEitan Adler     int *lp;
46898c299e0SEitan Adler     int *colp;
4693be6ef06SEitan Adler     int cpu;
4703be6ef06SEitan Adler 
4713be6ef06SEitan Adler for (cpu = 0; cpu < num_cpus; cpu++) {
4723be6ef06SEitan Adler     names = cpustate_names;
4733be6ef06SEitan Adler 
4743be6ef06SEitan Adler     Move_to(cpustates_column, y_cpustates + cpu);
4753be6ef06SEitan Adler     lastline = y_cpustates + cpu;
4763be6ef06SEitan Adler     lp = lcpustates + (cpu * num_cpustates);
4773be6ef06SEitan Adler     colp = cpustate_columns;
4783be6ef06SEitan Adler 
4793be6ef06SEitan Adler     /* we could be much more optimal about this */
4803be6ef06SEitan Adler     while ((thisname = *names++) != NULL)
4813be6ef06SEitan Adler     {
4823be6ef06SEitan Adler 	if (*thisname != '\0')
4833be6ef06SEitan Adler 	{
4843be6ef06SEitan Adler 	    /* did the value change since last time? */
4853be6ef06SEitan Adler 	    if (*lp != *states)
4863be6ef06SEitan Adler 	    {
4873be6ef06SEitan Adler 		/* yes, move and change */
4883be6ef06SEitan Adler 		Move_to(cpustates_column + *colp, y_cpustates + cpu);
4893be6ef06SEitan Adler 		lastline = y_cpustates + cpu;
4903be6ef06SEitan Adler 
4913be6ef06SEitan Adler 		/* retrieve value and remember it */
4923be6ef06SEitan Adler 		value = *states;
4933be6ef06SEitan Adler 
4943be6ef06SEitan Adler 		/* if percentage is >= 1000, print it as 100% */
4953be6ef06SEitan Adler 		printf((value >= 1000 ? "%4.0f" : "%4.1f"),
4963be6ef06SEitan Adler 		       ((double)value)/10.);
4973be6ef06SEitan Adler 
4983be6ef06SEitan Adler 		/* remember it for next time */
4993be6ef06SEitan Adler 		*lp = value;
5003be6ef06SEitan Adler 	    }
5013be6ef06SEitan Adler 	}
5023be6ef06SEitan Adler 
5033be6ef06SEitan Adler 	/* increment and move on */
5043be6ef06SEitan Adler 	lp++;
5053be6ef06SEitan Adler 	states++;
5063be6ef06SEitan Adler 	colp++;
5073be6ef06SEitan Adler     }
5083be6ef06SEitan Adler }
50908092a9bSDaichi GOTO 
51008092a9bSDaichi GOTO     states = hstates;
5113be6ef06SEitan Adler }
5123be6ef06SEitan Adler 
5133be6ef06SEitan Adler void
z_cpustates(void)514f6234b51SEitan Adler z_cpustates(void)
5153be6ef06SEitan Adler {
51698c299e0SEitan Adler     int i = 0;
517d0f687d3SDimitry Andric     const char * const *names;
518d0f687d3SDimitry Andric     const char *thisname;
5193be6ef06SEitan Adler     int cpu, value;
5203be6ef06SEitan Adler 
5213be6ef06SEitan Adler     for (cpu = 0; cpu < num_cpus; cpu++) {
5223be6ef06SEitan Adler 	    names = cpustate_names;
5233be6ef06SEitan Adler 
5243be6ef06SEitan Adler 	    /* show tag and bump lastline */
5253be6ef06SEitan Adler 	    if (num_cpus == 1)
5263be6ef06SEitan Adler 		    printf("\nCPU: ");
5273be6ef06SEitan Adler 	    else {
5283be6ef06SEitan Adler 		    value = printf("\nCPU %d: ", cpu);
5293be6ef06SEitan Adler 		    while (value++ <= cpustates_column)
5303be6ef06SEitan Adler 			    printf(" ");
5313be6ef06SEitan Adler 	    }
5323be6ef06SEitan Adler 	    lastline++;
5333be6ef06SEitan Adler 
5343be6ef06SEitan Adler 	    while ((thisname = *names++) != NULL)
5353be6ef06SEitan Adler 	    {
5363be6ef06SEitan Adler 		    if (*thisname != '\0')
5373be6ef06SEitan Adler 		    {
5383be6ef06SEitan Adler 			    printf("%s    %% %s", (i++ % num_cpustates) == 0 ? "" : ", ", thisname);
5393be6ef06SEitan Adler 		    }
5403be6ef06SEitan Adler 	    }
5413be6ef06SEitan Adler     }
5423be6ef06SEitan Adler 
5433be6ef06SEitan Adler     /* fill the "last" array with all -1s, to insure correct updating */
5446e0632dbSEitan Adler 	for (i = 0; i < num_cpustates * num_cpus; ++i) {
5456e0632dbSEitan Adler 		lcpustates[i] = -1;
5466e0632dbSEitan Adler     }
5473be6ef06SEitan Adler }
5483be6ef06SEitan Adler 
5493be6ef06SEitan Adler /*
5503be6ef06SEitan Adler  *  *_memory(stats) - print "Memory: " followed by the memory summary string
5513be6ef06SEitan Adler  *
5523be6ef06SEitan Adler  *  Assumptions:  cursor is on "lastline"
5533be6ef06SEitan Adler  *                for i_memory ONLY: cursor is on the previous line
5543be6ef06SEitan Adler  */
5553be6ef06SEitan Adler 
5560a59db87SDaichi GOTO static char *memory_buffer = NULL;
5573be6ef06SEitan Adler 
5583be6ef06SEitan Adler void
i_memory(int * stats)5591b7645c6SEitan Adler i_memory(int *stats)
5603be6ef06SEitan Adler {
5610a59db87SDaichi GOTO     memory_buffer = setup_buffer(memory_buffer, 0);
5620a59db87SDaichi GOTO 
5633be6ef06SEitan Adler     fputs("\nMem: ", stdout);
5643be6ef06SEitan Adler     lastline++;
5653be6ef06SEitan Adler 
5663be6ef06SEitan Adler     /* format and print the memory summary */
5673be6ef06SEitan Adler     summary_format(memory_buffer, stats, memory_names);
5683be6ef06SEitan Adler     fputs(memory_buffer, stdout);
5693be6ef06SEitan Adler }
5703be6ef06SEitan Adler 
5713be6ef06SEitan Adler void
u_memory(int * stats)5721b7645c6SEitan Adler u_memory(int *stats)
5733be6ef06SEitan Adler {
5740a59db87SDaichi GOTO     static char *new = NULL;
5750a59db87SDaichi GOTO 
5760a59db87SDaichi GOTO     new = setup_buffer(new, 0);
5773be6ef06SEitan Adler 
5783be6ef06SEitan Adler     /* format the new line */
5793be6ef06SEitan Adler     summary_format(new, stats, memory_names);
5803be6ef06SEitan Adler     line_update(memory_buffer, new, x_mem, y_mem);
5813be6ef06SEitan Adler }
5823be6ef06SEitan Adler 
5833be6ef06SEitan Adler /*
5843be6ef06SEitan Adler  *  *_arc(stats) - print "ARC: " followed by the ARC summary string
5853be6ef06SEitan Adler  *
5863be6ef06SEitan Adler  *  Assumptions:  cursor is on "lastline"
5873be6ef06SEitan Adler  *                for i_arc ONLY: cursor is on the previous line
5883be6ef06SEitan Adler  */
5890a59db87SDaichi GOTO static char *arc_buffer = NULL;
5903be6ef06SEitan Adler 
5913be6ef06SEitan Adler void
i_arc(int * stats)592a5ca08edSEitan Adler i_arc(int *stats)
5933be6ef06SEitan Adler {
5940a59db87SDaichi GOTO     arc_buffer = setup_buffer(arc_buffer, 0);
5950a59db87SDaichi GOTO 
5963be6ef06SEitan Adler     if (arc_names == NULL)
5973be6ef06SEitan Adler 	return;
5983be6ef06SEitan Adler 
5993be6ef06SEitan Adler     fputs("\nARC: ", stdout);
6003be6ef06SEitan Adler     lastline++;
6013be6ef06SEitan Adler 
6023be6ef06SEitan Adler     /* format and print the memory summary */
6033be6ef06SEitan Adler     summary_format(arc_buffer, stats, arc_names);
6043be6ef06SEitan Adler     fputs(arc_buffer, stdout);
6053be6ef06SEitan Adler }
6063be6ef06SEitan Adler 
6073be6ef06SEitan Adler void
u_arc(int * stats)608f6234b51SEitan Adler u_arc(int *stats)
6093be6ef06SEitan Adler {
6100a59db87SDaichi GOTO     static char *new = NULL;
6110a59db87SDaichi GOTO 
6120a59db87SDaichi GOTO     new = setup_buffer(new, 0);
6133be6ef06SEitan Adler 
6143be6ef06SEitan Adler     if (arc_names == NULL)
6153be6ef06SEitan Adler 	return;
6163be6ef06SEitan Adler 
6173be6ef06SEitan Adler     /* format the new line */
6183be6ef06SEitan Adler     summary_format(new, stats, arc_names);
6193be6ef06SEitan Adler     line_update(arc_buffer, new, x_arc, y_arc);
6203be6ef06SEitan Adler }
6213be6ef06SEitan Adler 
6223be6ef06SEitan Adler 
6233be6ef06SEitan Adler /*
6243be6ef06SEitan Adler  *  *_carc(stats) - print "Compressed ARC: " followed by the summary string
6253be6ef06SEitan Adler  *
6263be6ef06SEitan Adler  *  Assumptions:  cursor is on "lastline"
6273be6ef06SEitan Adler  *                for i_carc ONLY: cursor is on the previous line
6283be6ef06SEitan Adler  */
6290a59db87SDaichi GOTO static char *carc_buffer = NULL;
6303be6ef06SEitan Adler 
6313be6ef06SEitan Adler void
i_carc(int * stats)632a5ca08edSEitan Adler i_carc(int *stats)
6333be6ef06SEitan Adler {
6340a59db87SDaichi GOTO     carc_buffer = setup_buffer(carc_buffer, 0);
6350a59db87SDaichi GOTO 
6363be6ef06SEitan Adler     if (carc_names == NULL)
6373be6ef06SEitan Adler 	return;
6383be6ef06SEitan Adler 
6393be6ef06SEitan Adler     fputs("\n     ", stdout);
6403be6ef06SEitan Adler     lastline++;
6413be6ef06SEitan Adler 
6423be6ef06SEitan Adler     /* format and print the memory summary */
6433be6ef06SEitan Adler     summary_format(carc_buffer, stats, carc_names);
6443be6ef06SEitan Adler     fputs(carc_buffer, stdout);
6453be6ef06SEitan Adler }
6463be6ef06SEitan Adler 
6473be6ef06SEitan Adler void
u_carc(int * stats)648f6234b51SEitan Adler u_carc(int *stats)
6493be6ef06SEitan Adler {
6500a59db87SDaichi GOTO     static char *new = NULL;
6510a59db87SDaichi GOTO 
6520a59db87SDaichi GOTO     new = setup_buffer(new, 0);
6533be6ef06SEitan Adler 
6543be6ef06SEitan Adler     if (carc_names == NULL)
6553be6ef06SEitan Adler 	return;
6563be6ef06SEitan Adler 
6573be6ef06SEitan Adler     /* format the new line */
6583be6ef06SEitan Adler     summary_format(new, stats, carc_names);
6593be6ef06SEitan Adler     line_update(carc_buffer, new, x_carc, y_carc);
6603be6ef06SEitan Adler }
6613be6ef06SEitan Adler 
6623be6ef06SEitan Adler /*
6633be6ef06SEitan Adler  *  *_swap(stats) - print "Swap: " followed by the swap summary string
6643be6ef06SEitan Adler  *
6653be6ef06SEitan Adler  *  Assumptions:  cursor is on "lastline"
6663be6ef06SEitan Adler  *                for i_swap ONLY: cursor is on the previous line
6673be6ef06SEitan Adler  */
6683be6ef06SEitan Adler 
6690a59db87SDaichi GOTO static char *swap_buffer = NULL;
6703be6ef06SEitan Adler 
6713be6ef06SEitan Adler void
i_swap(int * stats)672a5ca08edSEitan Adler i_swap(int *stats)
6733be6ef06SEitan Adler {
6740a59db87SDaichi GOTO     swap_buffer = setup_buffer(swap_buffer, 0);
6750a59db87SDaichi GOTO 
6762984a716SAllan Jude     if (swap_names == NULL)
6772984a716SAllan Jude 	    return;
6782984a716SAllan Jude 
6793be6ef06SEitan Adler     fputs("\nSwap: ", stdout);
6803be6ef06SEitan Adler     lastline++;
6813be6ef06SEitan Adler 
6823be6ef06SEitan Adler     /* format and print the swap summary */
6833be6ef06SEitan Adler     summary_format(swap_buffer, stats, swap_names);
6843be6ef06SEitan Adler     fputs(swap_buffer, stdout);
6853be6ef06SEitan Adler }
6863be6ef06SEitan Adler 
6873be6ef06SEitan Adler void
u_swap(int * stats)688a5ca08edSEitan Adler u_swap(int *stats)
6893be6ef06SEitan Adler {
6900a59db87SDaichi GOTO     static char *new = NULL;
6910a59db87SDaichi GOTO 
6920a59db87SDaichi GOTO     new = setup_buffer(new, 0);
6933be6ef06SEitan Adler 
6942984a716SAllan Jude     if (swap_names == NULL)
6952984a716SAllan Jude 	    return;
6962984a716SAllan Jude 
6973be6ef06SEitan Adler     /* format the new line */
6983be6ef06SEitan Adler     summary_format(new, stats, swap_names);
6993be6ef06SEitan Adler     line_update(swap_buffer, new, x_swap, y_swap);
7003be6ef06SEitan Adler }
7013be6ef06SEitan Adler 
7023be6ef06SEitan Adler /*
7033be6ef06SEitan Adler  *  *_message() - print the next pending message line, or erase the one
7043be6ef06SEitan Adler  *                that is there.
7053be6ef06SEitan Adler  *
7063be6ef06SEitan Adler  *  Note that u_message is (currently) the same as i_message.
7073be6ef06SEitan Adler  *
7083be6ef06SEitan Adler  *  Assumptions:  lastline is consistent
7093be6ef06SEitan Adler  */
7103be6ef06SEitan Adler 
7113be6ef06SEitan Adler /*
7123be6ef06SEitan Adler  *  i_message is funny because it gets its message asynchronously (with
7133be6ef06SEitan Adler  *	respect to screen updates).
7143be6ef06SEitan Adler  */
7153be6ef06SEitan Adler 
7165c48c1eeSDaichi GOTO #define NEXT_MSG_ADDLEN 5
7170a59db87SDaichi GOTO static char *next_msg = NULL;
7183be6ef06SEitan Adler static int msglen = 0;
7193be6ef06SEitan Adler /* Invariant: msglen is always the length of the message currently displayed
7203be6ef06SEitan Adler    on the screen (even when next_msg doesn't contain that message). */
7213be6ef06SEitan Adler 
7223be6ef06SEitan Adler void
i_message(void)723f6234b51SEitan Adler i_message(void)
7243be6ef06SEitan Adler {
7255c48c1eeSDaichi GOTO     next_msg = setup_buffer(next_msg, NEXT_MSG_ADDLEN);
726a5ca08edSEitan Adler 
7273be6ef06SEitan Adler     while (lastline < y_message)
7283be6ef06SEitan Adler     {
7293be6ef06SEitan Adler 	fputc('\n', stdout);
7303be6ef06SEitan Adler 	lastline++;
7313be6ef06SEitan Adler     }
7323be6ef06SEitan Adler     if (next_msg[0] != '\0')
7333be6ef06SEitan Adler     {
7343be6ef06SEitan Adler 	top_standout(next_msg);
7353be6ef06SEitan Adler 	msglen = strlen(next_msg);
7363be6ef06SEitan Adler 	next_msg[0] = '\0';
7373be6ef06SEitan Adler     }
7383be6ef06SEitan Adler     else if (msglen > 0)
7393be6ef06SEitan Adler     {
7403be6ef06SEitan Adler 	(void) clear_eol(msglen);
7413be6ef06SEitan Adler 	msglen = 0;
7423be6ef06SEitan Adler     }
7433be6ef06SEitan Adler }
7443be6ef06SEitan Adler 
7453be6ef06SEitan Adler void
u_message(void)746f6234b51SEitan Adler u_message(void)
7473be6ef06SEitan Adler {
7483be6ef06SEitan Adler     i_message();
7493be6ef06SEitan Adler }
7503be6ef06SEitan Adler 
7513be6ef06SEitan Adler static int header_length;
7523be6ef06SEitan Adler 
7533be6ef06SEitan Adler /*
7543be6ef06SEitan Adler  * Trim a header string to the current display width and return a newly
7553be6ef06SEitan Adler  * allocated area with the trimmed header.
7563be6ef06SEitan Adler  */
7573be6ef06SEitan Adler 
758d0f687d3SDimitry Andric char *
trim_header(const char * text)7599f8096e3SEitan Adler trim_header(const char *text)
7603be6ef06SEitan Adler {
7613be6ef06SEitan Adler 	char *s;
7623be6ef06SEitan Adler 	int width;
7633be6ef06SEitan Adler 
7643be6ef06SEitan Adler 	s = NULL;
7650a59db87SDaichi GOTO 	width = screen_width;
7663be6ef06SEitan Adler 	header_length = strlen(text);
7673be6ef06SEitan Adler 	if (header_length >= width) {
7689f8096e3SEitan Adler 		s = strndup(text, width);
7693be6ef06SEitan Adler 		if (s == NULL)
7703be6ef06SEitan Adler 			return (NULL);
7713be6ef06SEitan Adler 	}
7723be6ef06SEitan Adler 	return (s);
7733be6ef06SEitan Adler }
7743be6ef06SEitan Adler 
7753be6ef06SEitan Adler /*
7763be6ef06SEitan Adler  *  *_header(text) - print the header for the process area
7773be6ef06SEitan Adler  *
7783be6ef06SEitan Adler  *  Assumptions:  cursor is on the previous line and lastline is consistent
7793be6ef06SEitan Adler  */
7803be6ef06SEitan Adler 
7813be6ef06SEitan Adler void
i_header(const char * text)7829f8096e3SEitan Adler i_header(const char *text)
7833be6ef06SEitan Adler {
784eae589f1SEitan Adler     char *s;
7853be6ef06SEitan Adler 
7863be6ef06SEitan Adler     s = trim_header(text);
7873be6ef06SEitan Adler     if (s != NULL)
7883be6ef06SEitan Adler 	text = s;
7893be6ef06SEitan Adler 
7903be6ef06SEitan Adler     if (header_status == ON)
7913be6ef06SEitan Adler     {
7923be6ef06SEitan Adler 	putchar('\n');
7933be6ef06SEitan Adler 	fputs(text, stdout);
7943be6ef06SEitan Adler 	lastline++;
7953be6ef06SEitan Adler     }
7963be6ef06SEitan Adler     else if (header_status == ERASE)
7973be6ef06SEitan Adler     {
7983be6ef06SEitan Adler 	header_status = OFF;
7993be6ef06SEitan Adler     }
8003be6ef06SEitan Adler     free(s);
8013be6ef06SEitan Adler }
8023be6ef06SEitan Adler 
8033be6ef06SEitan Adler void
u_header(const char * text __unused)8049f8096e3SEitan Adler u_header(const char *text __unused)
8053be6ef06SEitan Adler {
8063be6ef06SEitan Adler 
8073be6ef06SEitan Adler     if (header_status == ERASE)
8083be6ef06SEitan Adler     {
8093be6ef06SEitan Adler 	putchar('\n');
8103be6ef06SEitan Adler 	lastline++;
8113be6ef06SEitan Adler 	clear_eol(header_length);
8123be6ef06SEitan Adler 	header_status = OFF;
8133be6ef06SEitan Adler     }
8143be6ef06SEitan Adler }
8153be6ef06SEitan Adler 
8163be6ef06SEitan Adler /*
8173be6ef06SEitan Adler  *  *_process(line, thisline) - print one process line
8183be6ef06SEitan Adler  *
8193be6ef06SEitan Adler  *  Assumptions:  lastline is consistent
8203be6ef06SEitan Adler  */
8213be6ef06SEitan Adler 
8223be6ef06SEitan Adler void
i_process(int line,char * thisline)823f6234b51SEitan Adler i_process(int line, char *thisline)
8243be6ef06SEitan Adler {
82598c299e0SEitan Adler     char *p;
82698c299e0SEitan Adler     char *base;
8273be6ef06SEitan Adler 
8283be6ef06SEitan Adler     /* make sure we are on the correct line */
8293be6ef06SEitan Adler     while (lastline < y_procs + line)
8303be6ef06SEitan Adler     {
8313be6ef06SEitan Adler 	putchar('\n');
8323be6ef06SEitan Adler 	lastline++;
8333be6ef06SEitan Adler     }
8343be6ef06SEitan Adler 
8353be6ef06SEitan Adler     /* truncate the line to conform to our current screen width */
8367362ea6dSDimitry Andric     int len = strlen(thisline);
8377362ea6dSDimitry Andric     if (screen_width < len)
8387362ea6dSDimitry Andric     {
8390a59db87SDaichi GOTO 	thisline[screen_width] = '\0';
8407362ea6dSDimitry Andric     }
8413be6ef06SEitan Adler 
8423be6ef06SEitan Adler     /* write the line out */
8433be6ef06SEitan Adler     fputs(thisline, stdout);
8443be6ef06SEitan Adler 
8453be6ef06SEitan Adler     /* copy it in to our buffer */
8463be6ef06SEitan Adler     base = smart_terminal ? screenbuf + lineindex(line) : screenbuf;
847b274c68aSEitan Adler     p = stpcpy(base, thisline);
8483be6ef06SEitan Adler 
8493be6ef06SEitan Adler     /* zero fill the rest of it */
8507362ea6dSDimitry Andric     if (p - base < screen_width)
8517362ea6dSDimitry Andric     {
8520a59db87SDaichi GOTO 	memset(p, 0, screen_width - (p - base));
8533be6ef06SEitan Adler     }
8547362ea6dSDimitry Andric }
8553be6ef06SEitan Adler 
8563be6ef06SEitan Adler void
u_process(int line,char * newline)857f6234b51SEitan Adler u_process(int line, char *newline)
8583be6ef06SEitan Adler {
85998c299e0SEitan Adler     char *optr;
86098c299e0SEitan Adler     int screen_line = line + Header_lines;
86198c299e0SEitan Adler     char *bufferline;
8623be6ef06SEitan Adler 
8633be6ef06SEitan Adler     /* remember a pointer to the current line in the screen buffer */
8643be6ef06SEitan Adler     bufferline = &screenbuf[lineindex(line)];
8653be6ef06SEitan Adler 
8663be6ef06SEitan Adler     /* truncate the line to conform to our current screen width */
8677362ea6dSDimitry Andric     int len = strlen(newline);
8687362ea6dSDimitry Andric     if (screen_width < len)
8697362ea6dSDimitry Andric     {
8700a59db87SDaichi GOTO 	newline[screen_width] = '\0';
8717362ea6dSDimitry Andric     }
8723be6ef06SEitan Adler 
8733be6ef06SEitan Adler     /* is line higher than we went on the last display? */
8743be6ef06SEitan Adler     if (line >= last_hi)
8753be6ef06SEitan Adler     {
8763be6ef06SEitan Adler 	/* yes, just ignore screenbuf and write it out directly */
8773be6ef06SEitan Adler 	/* get positioned on the correct line */
8783be6ef06SEitan Adler 	if (screen_line - lastline == 1)
8793be6ef06SEitan Adler 	{
8803be6ef06SEitan Adler 	    putchar('\n');
8813be6ef06SEitan Adler 	    lastline++;
8823be6ef06SEitan Adler 	}
8833be6ef06SEitan Adler 	else
8843be6ef06SEitan Adler 	{
8853be6ef06SEitan Adler 	    Move_to(0, screen_line);
8863be6ef06SEitan Adler 	    lastline = screen_line;
8873be6ef06SEitan Adler 	}
8883be6ef06SEitan Adler 
8893be6ef06SEitan Adler 	/* now write the line */
8903be6ef06SEitan Adler 	fputs(newline, stdout);
8913be6ef06SEitan Adler 
8923be6ef06SEitan Adler 	/* copy it in to the buffer */
893b274c68aSEitan Adler 	optr = stpcpy(bufferline, newline);
8943be6ef06SEitan Adler 
8953be6ef06SEitan Adler 	/* zero fill the rest of it */
8967362ea6dSDimitry Andric 	if (optr - bufferline < screen_width)
8977362ea6dSDimitry Andric 	{
8980a59db87SDaichi GOTO 	    memset(optr, 0, screen_width - (optr - bufferline));
8993be6ef06SEitan Adler 	}
9007362ea6dSDimitry Andric     }
9013be6ef06SEitan Adler     else
9023be6ef06SEitan Adler     {
9033be6ef06SEitan Adler 	line_update(bufferline, newline, 0, line + Header_lines);
9043be6ef06SEitan Adler     }
9053be6ef06SEitan Adler }
9063be6ef06SEitan Adler 
9073be6ef06SEitan Adler void
u_endscreen(int hi)908f6234b51SEitan Adler u_endscreen(int hi)
9093be6ef06SEitan Adler {
91098c299e0SEitan Adler     int screen_line = hi + Header_lines;
91198c299e0SEitan Adler     int i;
9123be6ef06SEitan Adler 
9133be6ef06SEitan Adler     if (smart_terminal)
9143be6ef06SEitan Adler     {
9153be6ef06SEitan Adler 	if (hi < last_hi)
9163be6ef06SEitan Adler 	{
9173be6ef06SEitan Adler 	    /* need to blank the remainder of the screen */
9183be6ef06SEitan Adler 	    /* but only if there is any screen left below this line */
9193be6ef06SEitan Adler 	    if (lastline + 1 < screen_length)
9203be6ef06SEitan Adler 	    {
9213be6ef06SEitan Adler 		/* efficiently move to the end of currently displayed info */
9223be6ef06SEitan Adler 		if (screen_line - lastline < 5)
9233be6ef06SEitan Adler 		{
9243be6ef06SEitan Adler 		    while (lastline < screen_line)
9253be6ef06SEitan Adler 		    {
9263be6ef06SEitan Adler 			putchar('\n');
9273be6ef06SEitan Adler 			lastline++;
9283be6ef06SEitan Adler 		    }
9293be6ef06SEitan Adler 		}
9303be6ef06SEitan Adler 		else
9313be6ef06SEitan Adler 		{
9323be6ef06SEitan Adler 		    Move_to(0, screen_line);
9333be6ef06SEitan Adler 		    lastline = screen_line;
9343be6ef06SEitan Adler 		}
9353be6ef06SEitan Adler 
9363be6ef06SEitan Adler 		if (clear_to_end)
9373be6ef06SEitan Adler 		{
9383be6ef06SEitan Adler 		    /* we can do this the easy way */
9393be6ef06SEitan Adler 		    putcap(clear_to_end);
9403be6ef06SEitan Adler 		}
9413be6ef06SEitan Adler 		else
9423be6ef06SEitan Adler 		{
9433be6ef06SEitan Adler 		    /* use clear_eol on each line */
9443be6ef06SEitan Adler 		    i = hi;
9453be6ef06SEitan Adler 		    while ((void) clear_eol(strlen(&screenbuf[lineindex(i++)])), i < last_hi)
9463be6ef06SEitan Adler 		    {
9473be6ef06SEitan Adler 			putchar('\n');
9483be6ef06SEitan Adler 		    }
9493be6ef06SEitan Adler 		}
9503be6ef06SEitan Adler 	    }
9513be6ef06SEitan Adler 	}
9523be6ef06SEitan Adler 	last_hi = hi;
9533be6ef06SEitan Adler 
9543be6ef06SEitan Adler 	/* move the cursor to a pleasant place */
9553be6ef06SEitan Adler 	Move_to(x_idlecursor, y_idlecursor);
9563be6ef06SEitan Adler 	lastline = y_idlecursor;
9573be6ef06SEitan Adler     }
9583be6ef06SEitan Adler     else
9593be6ef06SEitan Adler     {
9603be6ef06SEitan Adler 	/* separate this display from the next with some vertical room */
9613be6ef06SEitan Adler 	fputs("\n\n", stdout);
9623be6ef06SEitan Adler     }
9633be6ef06SEitan Adler }
9643be6ef06SEitan Adler 
9653be6ef06SEitan Adler void
display_header(int t)966666cf873SEitan Adler display_header(int t)
9673be6ef06SEitan Adler {
968666cf873SEitan Adler 
9693be6ef06SEitan Adler     if (t)
9703be6ef06SEitan Adler     {
9713be6ef06SEitan Adler 	header_status = ON;
9723be6ef06SEitan Adler     }
9733be6ef06SEitan Adler     else if (header_status == ON)
9743be6ef06SEitan Adler     {
9753be6ef06SEitan Adler 	header_status = ERASE;
9763be6ef06SEitan Adler     }
9773be6ef06SEitan Adler }
9783be6ef06SEitan Adler 
9793be6ef06SEitan Adler void
new_message(int type,const char * msgfmt,...)980960a7f39SEitan Adler new_message(int type, const char *msgfmt, ...)
9813be6ef06SEitan Adler {
9821d6a4ba3SEitan Adler     va_list args;
9831d6a4ba3SEitan Adler     size_t i;
9841d6a4ba3SEitan Adler 
9851d6a4ba3SEitan Adler     va_start(args, msgfmt);
9863be6ef06SEitan Adler 
9873be6ef06SEitan Adler     /* first, format the message */
9885c48c1eeSDaichi GOTO     vsnprintf(next_msg, setup_buffer_bufsiz + NEXT_MSG_ADDLEN,
9895c48c1eeSDaichi GOTO 		    msgfmt, args);
9903be6ef06SEitan Adler 
991dfa5eb70SEitan Adler     va_end(args);
992dfa5eb70SEitan Adler 
9933be6ef06SEitan Adler     if (msglen > 0)
9943be6ef06SEitan Adler     {
9953be6ef06SEitan Adler 	/* message there already -- can we clear it? */
9963be6ef06SEitan Adler 	if (!overstrike)
9973be6ef06SEitan Adler 	{
9983be6ef06SEitan Adler 	    /* yes -- write it and clear to end */
9993be6ef06SEitan Adler 	    i = strlen(next_msg);
10003be6ef06SEitan Adler 	    if ((type & MT_delayed) == 0)
10013be6ef06SEitan Adler 	    {
100259c50d82SEitan Adler 			if (type & MT_standout) {
100359c50d82SEitan Adler 				top_standout(next_msg);
100459c50d82SEitan Adler 			} else {
10053be6ef06SEitan Adler 				fputs(next_msg, stdout);
100659c50d82SEitan Adler 			}
100759c50d82SEitan Adler 			clear_eol(msglen - i);
10083be6ef06SEitan Adler 			msglen = i;
10093be6ef06SEitan Adler 			next_msg[0] = '\0';
10103be6ef06SEitan Adler 	    }
10113be6ef06SEitan Adler 	}
10123be6ef06SEitan Adler     }
10133be6ef06SEitan Adler     else
10143be6ef06SEitan Adler     {
10153be6ef06SEitan Adler 	if ((type & MT_delayed) == 0)
10163be6ef06SEitan Adler 	{
101759c50d82SEitan Adler 		if (type & MT_standout) {
101859c50d82SEitan Adler 			top_standout(next_msg);
101959c50d82SEitan Adler 		} else {
102059c50d82SEitan Adler 			fputs(next_msg, stdout);
102159c50d82SEitan Adler 		}
10223be6ef06SEitan Adler 	    msglen = strlen(next_msg);
10233be6ef06SEitan Adler 	    next_msg[0] = '\0';
10243be6ef06SEitan Adler 	}
10253be6ef06SEitan Adler     }
10263be6ef06SEitan Adler }
10273be6ef06SEitan Adler 
10283be6ef06SEitan Adler void
clear_message(void)1029f6234b51SEitan Adler clear_message(void)
10303be6ef06SEitan Adler {
10313be6ef06SEitan Adler     if (clear_eol(msglen) == 1)
10323be6ef06SEitan Adler     {
10333be6ef06SEitan Adler 	putchar('\r');
10343be6ef06SEitan Adler     }
10353be6ef06SEitan Adler }
10363be6ef06SEitan Adler 
10373be6ef06SEitan Adler int
readline(char * buffer,int size,int numeric)1038f6234b51SEitan Adler readline(char *buffer, int size, int numeric)
10393be6ef06SEitan Adler {
104098c299e0SEitan Adler     char *ptr = buffer;
104198c299e0SEitan Adler     char ch;
104298c299e0SEitan Adler     char cnt = 0;
104398c299e0SEitan Adler     char maxcnt = 0;
10443be6ef06SEitan Adler 
10453be6ef06SEitan Adler     /* allow room for null terminator */
10463be6ef06SEitan Adler     size -= 1;
10473be6ef06SEitan Adler 
10483be6ef06SEitan Adler     /* read loop */
10493be6ef06SEitan Adler     while ((fflush(stdout), read(0, ptr, 1) > 0))
10503be6ef06SEitan Adler     {
10513be6ef06SEitan Adler 	/* newline means we are done */
10523be6ef06SEitan Adler 	if ((ch = *ptr) == '\n' || ch == '\r')
10533be6ef06SEitan Adler 	{
10543be6ef06SEitan Adler 	    break;
10553be6ef06SEitan Adler 	}
10563be6ef06SEitan Adler 
10573be6ef06SEitan Adler 	/* handle special editing characters */
10583be6ef06SEitan Adler 	if (ch == ch_kill)
10593be6ef06SEitan Adler 	{
10603be6ef06SEitan Adler 	    /* kill line -- account for overstriking */
10613be6ef06SEitan Adler 	    if (overstrike)
10623be6ef06SEitan Adler 	    {
10633be6ef06SEitan Adler 		msglen += maxcnt;
10643be6ef06SEitan Adler 	    }
10653be6ef06SEitan Adler 
10663be6ef06SEitan Adler 	    /* return null string */
10673be6ef06SEitan Adler 	    *buffer = '\0';
10683be6ef06SEitan Adler 	    putchar('\r');
10693be6ef06SEitan Adler 	    return(-1);
10703be6ef06SEitan Adler 	}
10713be6ef06SEitan Adler 	else if (ch == ch_erase)
10723be6ef06SEitan Adler 	{
10733be6ef06SEitan Adler 	    /* erase previous character */
10743be6ef06SEitan Adler 	    if (cnt <= 0)
10753be6ef06SEitan Adler 	    {
10763be6ef06SEitan Adler 		/* none to erase! */
10773be6ef06SEitan Adler 		putchar('\7');
10783be6ef06SEitan Adler 	    }
10793be6ef06SEitan Adler 	    else
10803be6ef06SEitan Adler 	    {
10813be6ef06SEitan Adler 		fputs("\b \b", stdout);
10823be6ef06SEitan Adler 		ptr--;
10833be6ef06SEitan Adler 		cnt--;
10843be6ef06SEitan Adler 	    }
10853be6ef06SEitan Adler 	}
10863be6ef06SEitan Adler 	/* check for character validity and buffer overflow */
10873be6ef06SEitan Adler 	else if (cnt == size || (numeric && !isdigit(ch)) ||
10883be6ef06SEitan Adler 		!isprint(ch))
10893be6ef06SEitan Adler 	{
10903be6ef06SEitan Adler 	    /* not legal */
10913be6ef06SEitan Adler 	    putchar('\7');
10923be6ef06SEitan Adler 	}
10933be6ef06SEitan Adler 	else
10943be6ef06SEitan Adler 	{
10953be6ef06SEitan Adler 	    /* echo it and store it in the buffer */
10963be6ef06SEitan Adler 	    putchar(ch);
10973be6ef06SEitan Adler 	    ptr++;
10983be6ef06SEitan Adler 	    cnt++;
10993be6ef06SEitan Adler 	    if (cnt > maxcnt)
11003be6ef06SEitan Adler 	    {
11013be6ef06SEitan Adler 		maxcnt = cnt;
11023be6ef06SEitan Adler 	    }
11033be6ef06SEitan Adler 	}
11043be6ef06SEitan Adler     }
11053be6ef06SEitan Adler 
11063be6ef06SEitan Adler     /* all done -- null terminate the string */
11073be6ef06SEitan Adler     *ptr = '\0';
11083be6ef06SEitan Adler 
11093be6ef06SEitan Adler     /* account for the extra characters in the message area */
11103be6ef06SEitan Adler     /* (if terminal overstrikes, remember the furthest they went) */
11113be6ef06SEitan Adler     msglen += overstrike ? maxcnt : cnt;
11123be6ef06SEitan Adler 
11133be6ef06SEitan Adler     /* return either inputted number or string length */
11143be6ef06SEitan Adler     putchar('\r');
11153be6ef06SEitan Adler     return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
11163be6ef06SEitan Adler }
11173be6ef06SEitan Adler 
11183be6ef06SEitan Adler /* internal support routines */
11193be6ef06SEitan Adler 
11201de63842SEitan Adler static void
summary_format(char * str,int * numbers,const char * const * names)11211de63842SEitan Adler summary_format(char *str, int *numbers, const char * const *names)
11223be6ef06SEitan Adler {
112398c299e0SEitan Adler     char *p;
112498c299e0SEitan Adler     int num;
1125eae589f1SEitan Adler     const char *thisname;
11263be6ef06SEitan Adler     char rbuf[6];
11273be6ef06SEitan Adler 
11283be6ef06SEitan Adler     /* format each number followed by its string */
11293be6ef06SEitan Adler     p = str;
11303be6ef06SEitan Adler     while ((thisname = *names++) != NULL)
11313be6ef06SEitan Adler     {
11323be6ef06SEitan Adler 	/* get the number to format */
11333be6ef06SEitan Adler 	num = *numbers++;
11343be6ef06SEitan Adler 
11353be6ef06SEitan Adler 	/* display only non-zero numbers */
11363be6ef06SEitan Adler 	if (num > 0)
11373be6ef06SEitan Adler 	{
11383be6ef06SEitan Adler 	    /* is this number in kilobytes? */
11393be6ef06SEitan Adler 	    if (thisname[0] == 'K')
11403be6ef06SEitan Adler 	    {
11413be6ef06SEitan Adler 		/* yes: format it as a memory value */
1142b274c68aSEitan Adler 		p = stpcpy(p, format_k(num));
11433be6ef06SEitan Adler 
11443be6ef06SEitan Adler 		/* skip over the K, since it was included by format_k */
1145b274c68aSEitan Adler 		p = stpcpy(p, thisname+1);
11463be6ef06SEitan Adler 	    }
11473be6ef06SEitan Adler 	    /* is this number a ratio? */
11483be6ef06SEitan Adler 	    else if (thisname[0] == ':')
11493be6ef06SEitan Adler 	    {
11503be6ef06SEitan Adler 		(void) snprintf(rbuf, sizeof(rbuf), "%.2f",
11513be6ef06SEitan Adler 		    (float)*(numbers - 2) / (float)num);
1152b274c68aSEitan Adler 		p = stpcpy(p, rbuf);
1153b274c68aSEitan Adler 		p = stpcpy(p, thisname);
11543be6ef06SEitan Adler 	    }
11553be6ef06SEitan Adler 	    else
11563be6ef06SEitan Adler 	    {
1157b274c68aSEitan Adler 		p = stpcpy(p, itoa(num));
1158b274c68aSEitan Adler 		p = stpcpy(p, thisname);
11593be6ef06SEitan Adler 	    }
11603be6ef06SEitan Adler 	}
11613be6ef06SEitan Adler 
11623be6ef06SEitan Adler 	/* ignore negative numbers, but display corresponding string */
11633be6ef06SEitan Adler 	else if (num < 0)
11643be6ef06SEitan Adler 	{
1165b274c68aSEitan Adler 	    p = stpcpy(p, thisname);
11663be6ef06SEitan Adler 	}
11673be6ef06SEitan Adler     }
11683be6ef06SEitan Adler 
11693be6ef06SEitan Adler     /* if the last two characters in the string are ", ", delete them */
11703be6ef06SEitan Adler     p -= 2;
11713be6ef06SEitan Adler     if (p >= str && p[0] == ',' && p[1] == ' ')
11723be6ef06SEitan Adler     {
11733be6ef06SEitan Adler 	*p = '\0';
11743be6ef06SEitan Adler     }
11753be6ef06SEitan Adler }
11763be6ef06SEitan Adler 
1177f6234b51SEitan Adler static void
line_update(char * old,char * new,int start,int line)1178f6234b51SEitan Adler line_update(char *old, char *new, int start, int line)
11793be6ef06SEitan Adler {
118098c299e0SEitan Adler     int ch;
118198c299e0SEitan Adler     int diff;
118298c299e0SEitan Adler     int newcol = start + 1;
118398c299e0SEitan Adler     int lastcol = start;
11840b2f6ed1SEitan Adler     char cursor_on_line = false;
11853be6ef06SEitan Adler     char *current;
11863be6ef06SEitan Adler 
11873be6ef06SEitan Adler     /* compare the two strings and only rewrite what has changed */
11883be6ef06SEitan Adler     current = old;
11893be6ef06SEitan Adler #ifdef DEBUG
11903be6ef06SEitan Adler     fprintf(debug, "line_update, starting at %d\n", start);
11913be6ef06SEitan Adler     fputs(old, debug);
11923be6ef06SEitan Adler     fputc('\n', debug);
11933be6ef06SEitan Adler     fputs(new, debug);
11943be6ef06SEitan Adler     fputs("\n-\n", debug);
11953be6ef06SEitan Adler #endif
11963be6ef06SEitan Adler 
11973be6ef06SEitan Adler     /* start things off on the right foot		    */
11983be6ef06SEitan Adler     /* this is to make sure the invariants get set up right */
11993be6ef06SEitan Adler     if ((ch = *new++) != *old)
12003be6ef06SEitan Adler     {
12013be6ef06SEitan Adler 	if (line - lastline == 1 && start == 0)
12023be6ef06SEitan Adler 	{
12033be6ef06SEitan Adler 	    putchar('\n');
12043be6ef06SEitan Adler 	}
12053be6ef06SEitan Adler 	else
12063be6ef06SEitan Adler 	{
12073be6ef06SEitan Adler 	    Move_to(start, line);
12083be6ef06SEitan Adler 	}
12090b2f6ed1SEitan Adler 	cursor_on_line = true;
12103be6ef06SEitan Adler 	putchar(ch);
12113be6ef06SEitan Adler 	*old = ch;
1212281bdc30SDimitry Andric 	lastcol = start + 1;
12133be6ef06SEitan Adler     }
12143be6ef06SEitan Adler     old++;
12153be6ef06SEitan Adler 
12163be6ef06SEitan Adler     /*
12173be6ef06SEitan Adler      *  main loop -- check each character.  If the old and new aren't the
12183be6ef06SEitan Adler      *	same, then update the display.  When the distance from the
12193be6ef06SEitan Adler      *	current cursor position to the new change is small enough,
12203be6ef06SEitan Adler      *	the characters that belong there are written to move the
12213be6ef06SEitan Adler      *	cursor over.
12223be6ef06SEitan Adler      *
12233be6ef06SEitan Adler      *	Invariants:
12243be6ef06SEitan Adler      *	    lastcol is the column where the cursor currently is sitting
12253be6ef06SEitan Adler      *		(always one beyond the end of the last mismatch).
12263be6ef06SEitan Adler      */
12273be6ef06SEitan Adler     do		/* yes, a do...while */
12283be6ef06SEitan Adler     {
12293be6ef06SEitan Adler 	if ((ch = *new++) != *old)
12303be6ef06SEitan Adler 	{
12313be6ef06SEitan Adler 	    /* new character is different from old	  */
12323be6ef06SEitan Adler 	    /* make sure the cursor is on top of this character */
12333be6ef06SEitan Adler 	    diff = newcol - lastcol;
12343be6ef06SEitan Adler 	    if (diff > 0)
12353be6ef06SEitan Adler 	    {
12363be6ef06SEitan Adler 		/* some motion is required--figure out which is shorter */
12373be6ef06SEitan Adler 		if (diff < 6 && cursor_on_line)
12383be6ef06SEitan Adler 		{
12393be6ef06SEitan Adler 		    /* overwrite old stuff--get it out of the old buffer */
12403be6ef06SEitan Adler 		    printf("%.*s", diff, &current[lastcol-start]);
12413be6ef06SEitan Adler 		}
12423be6ef06SEitan Adler 		else
12433be6ef06SEitan Adler 		{
12443be6ef06SEitan Adler 		    /* use cursor addressing */
12453be6ef06SEitan Adler 		    Move_to(newcol, line);
12460b2f6ed1SEitan Adler 		    cursor_on_line = true;
12473be6ef06SEitan Adler 		}
12483be6ef06SEitan Adler 		/* remember where the cursor is */
12493be6ef06SEitan Adler 		lastcol = newcol + 1;
12503be6ef06SEitan Adler 	    }
12513be6ef06SEitan Adler 	    else
12523be6ef06SEitan Adler 	    {
12533be6ef06SEitan Adler 		/* already there, update position */
12543be6ef06SEitan Adler 		lastcol++;
12553be6ef06SEitan Adler 	    }
12563be6ef06SEitan Adler 
12573be6ef06SEitan Adler 	    /* write what we need to */
12583be6ef06SEitan Adler 	    if (ch == '\0')
12593be6ef06SEitan Adler 	    {
12603be6ef06SEitan Adler 		/* at the end--terminate with a clear-to-end-of-line */
12613be6ef06SEitan Adler 		(void) clear_eol(strlen(old));
12623be6ef06SEitan Adler 	    }
12633be6ef06SEitan Adler 	    else
12643be6ef06SEitan Adler 	    {
12653be6ef06SEitan Adler 		/* write the new character */
12663be6ef06SEitan Adler 		putchar(ch);
12673be6ef06SEitan Adler 	    }
12683be6ef06SEitan Adler 	    /* put the new character in the screen buffer */
12693be6ef06SEitan Adler 	    *old = ch;
12703be6ef06SEitan Adler 	}
12713be6ef06SEitan Adler 
12723be6ef06SEitan Adler 	/* update working column and screen buffer pointer */
12733be6ef06SEitan Adler 	newcol++;
12743be6ef06SEitan Adler 	old++;
12753be6ef06SEitan Adler 
12763be6ef06SEitan Adler     } while (ch != '\0');
12773be6ef06SEitan Adler 
12783be6ef06SEitan Adler     /* zero out the rest of the line buffer -- MUST BE DONE! */
12790a59db87SDaichi GOTO     diff = screen_width - newcol;
12803be6ef06SEitan Adler     if (diff > 0)
12813be6ef06SEitan Adler     {
12828d0d2676SEitan Adler 	memset(old, 0, diff);
12833be6ef06SEitan Adler     }
12843be6ef06SEitan Adler 
12853be6ef06SEitan Adler     /* remember where the current line is */
12863be6ef06SEitan Adler     if (cursor_on_line)
12873be6ef06SEitan Adler     {
12883be6ef06SEitan Adler 	lastline = line;
12893be6ef06SEitan Adler     }
12903be6ef06SEitan Adler }
12913be6ef06SEitan Adler 
12923be6ef06SEitan Adler void
i_uptime(struct timeval * bt,time_t * tod)1293f6234b51SEitan Adler i_uptime(struct timeval *bt, time_t *tod)
12943be6ef06SEitan Adler {
12953be6ef06SEitan Adler     time_t uptime;
12963be6ef06SEitan Adler     int days, hrs, mins, secs;
12973be6ef06SEitan Adler 
12983be6ef06SEitan Adler     if (bt->tv_sec != -1) {
12993be6ef06SEitan Adler 	uptime = *tod - bt->tv_sec;
13003be6ef06SEitan Adler 	days = uptime / 86400;
13013be6ef06SEitan Adler 	uptime %= 86400;
13023be6ef06SEitan Adler 	hrs = uptime / 3600;
13033be6ef06SEitan Adler 	uptime %= 3600;
13043be6ef06SEitan Adler 	mins = uptime / 60;
13053be6ef06SEitan Adler 	secs = uptime % 60;
13063be6ef06SEitan Adler 
13073be6ef06SEitan Adler 	/*
13083be6ef06SEitan Adler 	 *  Display the uptime.
13093be6ef06SEitan Adler 	 */
13103be6ef06SEitan Adler 
13113be6ef06SEitan Adler 	if (smart_terminal)
13123be6ef06SEitan Adler 	{
13133be6ef06SEitan Adler 	    Move_to((screen_width - 24) - (days > 9 ? 1 : 0), 0);
13143be6ef06SEitan Adler 	}
13153be6ef06SEitan Adler 	else
13163be6ef06SEitan Adler 	{
13173be6ef06SEitan Adler 	    fputs(" ", stdout);
13183be6ef06SEitan Adler 	}
13193be6ef06SEitan Adler 	printf(" up %d+%02d:%02d:%02d", days, hrs, mins, secs);
13203be6ef06SEitan Adler     }
13213be6ef06SEitan Adler }
13220a59db87SDaichi GOTO 
1323fc8ae86aSPhilip Paeps void
i_battery(int nbat,int batt)1324fc8ae86aSPhilip Paeps i_battery(int nbat, int batt)
1325fc8ae86aSPhilip Paeps {
1326fc8ae86aSPhilip Paeps 
1327fc8ae86aSPhilip Paeps 	if (nbat > 0) {
1328fc8ae86aSPhilip Paeps 		printf("; battery: %d%%", batt);
1329fc8ae86aSPhilip Paeps 	}
1330fc8ae86aSPhilip Paeps }
1331fc8ae86aSPhilip Paeps 
1332281bdc30SDimitry Andric #define SETUPBUFFER_MIN_SCREENWIDTH 80
13335c48c1eeSDaichi GOTO #define SETUPBUFFER_REQUIRED_ADDBUFSIZ 2
13345c48c1eeSDaichi GOTO 
13350a59db87SDaichi GOTO static char *
setup_buffer(char * buffer,int addlen)13360a59db87SDaichi GOTO setup_buffer(char *buffer, int addlen)
13370a59db87SDaichi GOTO {
1338c26e2e37SDimitry Andric     size_t len, old_len;
1339c26e2e37SDimitry Andric     char *new_buffer;
13400a59db87SDaichi GOTO 
13410a59db87SDaichi GOTO     setup_buffer_bufsiz = screen_width;
1342281bdc30SDimitry Andric     if (setup_buffer_bufsiz < SETUPBUFFER_MIN_SCREENWIDTH)
1343281bdc30SDimitry Andric     {
1344281bdc30SDimitry Andric 	setup_buffer_bufsiz = SETUPBUFFER_MIN_SCREENWIDTH;
1345281bdc30SDimitry Andric     }
1346281bdc30SDimitry Andric 
1347281bdc30SDimitry Andric     len = setup_buffer_bufsiz + addlen + SETUPBUFFER_REQUIRED_ADDBUFSIZ;
1348c26e2e37SDimitry Andric     new_buffer = calloc(len, sizeof(char));
1349c26e2e37SDimitry Andric     if (new_buffer == NULL)
1350281bdc30SDimitry Andric     {
135117be5f23SEitan Adler 	errx(4, "can't allocate sufficient memory");
13520a59db87SDaichi GOTO     }
1353c26e2e37SDimitry Andric     if (buffer != NULL)
1354c26e2e37SDimitry Andric     {
1355c26e2e37SDimitry Andric 	old_len = strlen(buffer);
1356c26e2e37SDimitry Andric 	memcpy(new_buffer, buffer, old_len < len - 1 ? old_len : len - 1);
1357c26e2e37SDimitry Andric 	free(buffer);
1358c26e2e37SDimitry Andric     }
13590a59db87SDaichi GOTO 
1360c26e2e37SDimitry Andric     return new_buffer;
13610a59db87SDaichi GOTO }
1362