xref: /minix3/external/bsd/top/dist/display.c (revision b89261ba018da33f0bd8cd05f5a1fe9e7a9c837b)
1*b89261baSDavid van Moolenbroek /*
2*b89261baSDavid van Moolenbroek  * Copyright (c) 1984 through 2008, William LeFebvre
3*b89261baSDavid van Moolenbroek  * All rights reserved.
4*b89261baSDavid van Moolenbroek  *
5*b89261baSDavid van Moolenbroek  * Redistribution and use in source and binary forms, with or without
6*b89261baSDavid van Moolenbroek  * modification, are permitted provided that the following conditions are met:
7*b89261baSDavid van Moolenbroek  *
8*b89261baSDavid van Moolenbroek  *     * Redistributions of source code must retain the above copyright
9*b89261baSDavid van Moolenbroek  * notice, this list of conditions and the following disclaimer.
10*b89261baSDavid van Moolenbroek  *
11*b89261baSDavid van Moolenbroek  *     * Redistributions in binary form must reproduce the above
12*b89261baSDavid van Moolenbroek  * copyright notice, this list of conditions and the following disclaimer
13*b89261baSDavid van Moolenbroek  * in the documentation and/or other materials provided with the
14*b89261baSDavid van Moolenbroek  * distribution.
15*b89261baSDavid van Moolenbroek  *
16*b89261baSDavid van Moolenbroek  *     * Neither the name of William LeFebvre nor the names of other
17*b89261baSDavid van Moolenbroek  * contributors may be used to endorse or promote products derived from
18*b89261baSDavid van Moolenbroek  * this software without specific prior written permission.
19*b89261baSDavid van Moolenbroek  *
20*b89261baSDavid van Moolenbroek  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21*b89261baSDavid van Moolenbroek  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22*b89261baSDavid van Moolenbroek  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23*b89261baSDavid van Moolenbroek  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24*b89261baSDavid van Moolenbroek  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25*b89261baSDavid van Moolenbroek  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26*b89261baSDavid van Moolenbroek  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27*b89261baSDavid van Moolenbroek  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28*b89261baSDavid van Moolenbroek  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29*b89261baSDavid van Moolenbroek  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30*b89261baSDavid van Moolenbroek  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31*b89261baSDavid van Moolenbroek  */
32*b89261baSDavid van Moolenbroek 
33*b89261baSDavid van Moolenbroek /*
34*b89261baSDavid van Moolenbroek  *  Top users/processes display for Unix
35*b89261baSDavid van Moolenbroek  *  Version 3
36*b89261baSDavid van Moolenbroek  */
37*b89261baSDavid van Moolenbroek 
38*b89261baSDavid van Moolenbroek /*
39*b89261baSDavid van Moolenbroek  *  This file contains the routines that display information on the screen.
40*b89261baSDavid van Moolenbroek  *  Each section of the screen has two routines:  one for initially writing
41*b89261baSDavid van Moolenbroek  *  all constant and dynamic text, and one for only updating the text that
42*b89261baSDavid van Moolenbroek  *  changes.  The prefix "i_" is used on all the "initial" routines and the
43*b89261baSDavid van Moolenbroek  *  prefix "u_" is used for all the "updating" routines.
44*b89261baSDavid van Moolenbroek  *
45*b89261baSDavid van Moolenbroek  *  ASSUMPTIONS:
46*b89261baSDavid van Moolenbroek  *        None of the "i_" routines use any of the termcap capabilities.
47*b89261baSDavid van Moolenbroek  *        In this way, those routines can be safely used on terminals that
48*b89261baSDavid van Moolenbroek  *        have minimal (or nonexistant) terminal capabilities.
49*b89261baSDavid van Moolenbroek  *
50*b89261baSDavid van Moolenbroek  *        The routines should be called in this order:  *_loadave, *_uptime,
51*b89261baSDavid van Moolenbroek  *        i_timeofday, *_procstates, *_cpustates, *_memory, *_swap,
52*b89261baSDavid van Moolenbroek  *        *_message, *_header, *_process, *_endscreen.
53*b89261baSDavid van Moolenbroek  */
54*b89261baSDavid van Moolenbroek 
55*b89261baSDavid van Moolenbroek #include "os.h"
56*b89261baSDavid van Moolenbroek #include <ctype.h>
57*b89261baSDavid van Moolenbroek #include <stdarg.h>
58*b89261baSDavid van Moolenbroek #include <sys/types.h>
59*b89261baSDavid van Moolenbroek #include <sys/uio.h>
60*b89261baSDavid van Moolenbroek #include <unistd.h>
61*b89261baSDavid van Moolenbroek 
62*b89261baSDavid van Moolenbroek #include "top.h"
63*b89261baSDavid van Moolenbroek #include "machine.h"
64*b89261baSDavid van Moolenbroek #include "screen.h"		/* interface to screen package */
65*b89261baSDavid van Moolenbroek #include "layout.h"		/* defines for screen position layout */
66*b89261baSDavid van Moolenbroek #include "display.h"
67*b89261baSDavid van Moolenbroek #include "boolean.h"
68*b89261baSDavid van Moolenbroek #include "utils.h"
69*b89261baSDavid van Moolenbroek 
70*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
71*b89261baSDavid van Moolenbroek #include "color.h"
72*b89261baSDavid van Moolenbroek #endif
73*b89261baSDavid van Moolenbroek 
74*b89261baSDavid van Moolenbroek #define CURSOR_COST 8
75*b89261baSDavid van Moolenbroek 
76*b89261baSDavid van Moolenbroek #define MESSAGE_DISPLAY_TIME 5
77*b89261baSDavid van Moolenbroek 
78*b89261baSDavid van Moolenbroek /* imported from screen.c */
79*b89261baSDavid van Moolenbroek extern int overstrike;
80*b89261baSDavid van Moolenbroek 
81*b89261baSDavid van Moolenbroek static int lmpid = -1;
82*b89261baSDavid van Moolenbroek static int display_width = MAX_COLS;
83*b89261baSDavid van Moolenbroek static int ncpu = 0;
84*b89261baSDavid van Moolenbroek 
85*b89261baSDavid van Moolenbroek /* cursor positions of key points on the screen are maintained here */
86*b89261baSDavid van Moolenbroek /* layout.h has static definitions, but we may change our minds on some
87*b89261baSDavid van Moolenbroek    of the positions as we make decisions about what needs to be displayed */
88*b89261baSDavid van Moolenbroek 
89*b89261baSDavid van Moolenbroek static int x_lastpid = X_LASTPID;
90*b89261baSDavid van Moolenbroek static int y_lastpid = Y_LASTPID;
91*b89261baSDavid van Moolenbroek static int x_loadave = X_LOADAVE;
92*b89261baSDavid van Moolenbroek static int y_loadave = Y_LOADAVE;
93*b89261baSDavid van Moolenbroek static int x_minibar = X_MINIBAR;
94*b89261baSDavid van Moolenbroek static int y_minibar = Y_MINIBAR;
95*b89261baSDavid van Moolenbroek static int x_uptime = X_UPTIME;
96*b89261baSDavid van Moolenbroek static int y_uptime = Y_UPTIME;
97*b89261baSDavid van Moolenbroek static int x_procstate = X_PROCSTATE;
98*b89261baSDavid van Moolenbroek static int y_procstate = Y_PROCSTATE;
99*b89261baSDavid van Moolenbroek static int x_cpustates = X_CPUSTATES;
100*b89261baSDavid van Moolenbroek static int y_cpustates = Y_CPUSTATES;
101*b89261baSDavid van Moolenbroek static int x_kernel = X_KERNEL;
102*b89261baSDavid van Moolenbroek static int y_kernel = Y_KERNEL;
103*b89261baSDavid van Moolenbroek static int x_mem = X_MEM;
104*b89261baSDavid van Moolenbroek static int y_mem = Y_MEM;
105*b89261baSDavid van Moolenbroek static int x_swap = X_SWAP;
106*b89261baSDavid van Moolenbroek static int y_swap = Y_SWAP;
107*b89261baSDavid van Moolenbroek static int y_message = Y_MESSAGE;
108*b89261baSDavid van Moolenbroek static int x_header = X_HEADER;
109*b89261baSDavid van Moolenbroek static int y_header = Y_HEADER;
110*b89261baSDavid van Moolenbroek static int x_idlecursor = X_IDLECURSOR;
111*b89261baSDavid van Moolenbroek static int y_idlecursor = Y_IDLECURSOR;
112*b89261baSDavid van Moolenbroek static int y_procs = Y_PROCS;
113*b89261baSDavid van Moolenbroek 
114*b89261baSDavid van Moolenbroek /* buffer and colormask that describes the content of the screen */
115*b89261baSDavid van Moolenbroek /* these are singly dimensioned arrays -- the row boundaries are
116*b89261baSDavid van Moolenbroek    determined on the fly.
117*b89261baSDavid van Moolenbroek */
118*b89261baSDavid van Moolenbroek static char *screenbuf = NULL;
119*b89261baSDavid van Moolenbroek static char *colorbuf = NULL;
120*b89261baSDavid van Moolenbroek static char scratchbuf[MAX_COLS];
121*b89261baSDavid van Moolenbroek static int bufsize = 0;
122*b89261baSDavid van Moolenbroek static int multi = 0;
123*b89261baSDavid van Moolenbroek 
124*b89261baSDavid van Moolenbroek /* lineindex tells us where the beginning of a line is in the buffer */
125*b89261baSDavid van Moolenbroek #define lineindex(l) ((l)*MAX_COLS)
126*b89261baSDavid van Moolenbroek 
127*b89261baSDavid van Moolenbroek /* screen's cursor */
128*b89261baSDavid van Moolenbroek static int curr_x, curr_y;
129*b89261baSDavid van Moolenbroek static int curr_color;
130*b89261baSDavid van Moolenbroek 
131*b89261baSDavid van Moolenbroek /* virtual cursor */
132*b89261baSDavid van Moolenbroek static int virt_x, virt_y;
133*b89261baSDavid van Moolenbroek 
134*b89261baSDavid van Moolenbroek static const char **procstate_names;
135*b89261baSDavid van Moolenbroek static const char **cpustate_names;
136*b89261baSDavid van Moolenbroek static const char **memory_names;
137*b89261baSDavid van Moolenbroek static const char **swap_names;
138*b89261baSDavid van Moolenbroek static const char **kernel_names;
139*b89261baSDavid van Moolenbroek 
140*b89261baSDavid van Moolenbroek static int num_procstates;
141*b89261baSDavid van Moolenbroek static int num_cpustates;
142*b89261baSDavid van Moolenbroek static int num_memory;
143*b89261baSDavid van Moolenbroek static int num_swap;
144*b89261baSDavid van Moolenbroek static int num_kernel;
145*b89261baSDavid van Moolenbroek 
146*b89261baSDavid van Moolenbroek static int *lprocstates;
147*b89261baSDavid van Moolenbroek static int *lcpustates;
148*b89261baSDavid van Moolenbroek 
149*b89261baSDavid van Moolenbroek static int *cpustate_columns;
150*b89261baSDavid van Moolenbroek static int cpustate_total_length;
151*b89261baSDavid van Moolenbroek 
152*b89261baSDavid van Moolenbroek static int header_status = Yes;
153*b89261baSDavid van Moolenbroek 
154*b89261baSDavid van Moolenbroek /* pending messages are stored in a circular buffer, where message_first
155*b89261baSDavid van Moolenbroek    is the next one to display, and message_last is the last one
156*b89261baSDavid van Moolenbroek    in the buffer.  Counters wrap around at MAX_MESSAGES.  The buffer is
157*b89261baSDavid van Moolenbroek    empty when message_first == message_last and full when
158*b89261baSDavid van Moolenbroek    message_last + 1 == message_first.  The pointer message_current holds
159*b89261baSDavid van Moolenbroek    the message currently being displayed, or "" if there is none.
160*b89261baSDavid van Moolenbroek */
161*b89261baSDavid van Moolenbroek #define MAX_MESSAGES 16
162*b89261baSDavid van Moolenbroek static char *message_buf[MAX_MESSAGES];
163*b89261baSDavid van Moolenbroek static int message_first = 0;
164*b89261baSDavid van Moolenbroek static int message_last = 0;
165*b89261baSDavid van Moolenbroek static struct timeval message_time = {0, 0};
166*b89261baSDavid van Moolenbroek static char *message_current = NULL;
167*b89261baSDavid van Moolenbroek static int message_length = 0;
168*b89261baSDavid van Moolenbroek static int message_hold = 1;
169*b89261baSDavid van Moolenbroek static int message_barrier = No;
170*b89261baSDavid van Moolenbroek 
171*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
172*b89261baSDavid van Moolenbroek static int load_cidx[3];
173*b89261baSDavid van Moolenbroek static int header_cidx;
174*b89261baSDavid van Moolenbroek static int *cpustate_cidx;
175*b89261baSDavid van Moolenbroek static int *memory_cidx;
176*b89261baSDavid van Moolenbroek static int *swap_cidx;
177*b89261baSDavid van Moolenbroek static int *kernel_cidx;
178*b89261baSDavid van Moolenbroek #else
179*b89261baSDavid van Moolenbroek #define memory_cidx NULL
180*b89261baSDavid van Moolenbroek #define swap_cidx NULL
181*b89261baSDavid van Moolenbroek #define kernel_cidx NULL
182*b89261baSDavid van Moolenbroek #endif
183*b89261baSDavid van Moolenbroek 
184*b89261baSDavid van Moolenbroek 
185*b89261baSDavid van Moolenbroek /* internal support routines */
186*b89261baSDavid van Moolenbroek 
187*b89261baSDavid van Moolenbroek /*
188*b89261baSDavid van Moolenbroek  * static int string_count(char **pp)
189*b89261baSDavid van Moolenbroek  *
190*b89261baSDavid van Moolenbroek  * Pointer "pp" points to an array of string pointers, which is
191*b89261baSDavid van Moolenbroek  * terminated by a NULL.  Return the number of string pointers in
192*b89261baSDavid van Moolenbroek  * this array.
193*b89261baSDavid van Moolenbroek  */
194*b89261baSDavid van Moolenbroek 
195*b89261baSDavid van Moolenbroek static int
string_count(const char ** pp)196*b89261baSDavid van Moolenbroek string_count(const char **pp)
197*b89261baSDavid van Moolenbroek 
198*b89261baSDavid van Moolenbroek {
199*b89261baSDavid van Moolenbroek     register int cnt = 0;
200*b89261baSDavid van Moolenbroek 
201*b89261baSDavid van Moolenbroek     if (pp != NULL)
202*b89261baSDavid van Moolenbroek     {
203*b89261baSDavid van Moolenbroek 	while (*pp++ != NULL)
204*b89261baSDavid van Moolenbroek 	{
205*b89261baSDavid van Moolenbroek 	    cnt++;
206*b89261baSDavid van Moolenbroek 	}
207*b89261baSDavid van Moolenbroek     }
208*b89261baSDavid van Moolenbroek     return(cnt);
209*b89261baSDavid van Moolenbroek }
210*b89261baSDavid van Moolenbroek 
211*b89261baSDavid van Moolenbroek void
display_clear(void)212*b89261baSDavid van Moolenbroek display_clear(void)
213*b89261baSDavid van Moolenbroek 
214*b89261baSDavid van Moolenbroek {
215*b89261baSDavid van Moolenbroek     dprintf("display_clear\n");
216*b89261baSDavid van Moolenbroek     screen_clear();
217*b89261baSDavid van Moolenbroek     memzero(screenbuf, bufsize);
218*b89261baSDavid van Moolenbroek     memzero(colorbuf, bufsize);
219*b89261baSDavid van Moolenbroek     curr_x = curr_y = 0;
220*b89261baSDavid van Moolenbroek }
221*b89261baSDavid van Moolenbroek 
222*b89261baSDavid van Moolenbroek /*
223*b89261baSDavid van Moolenbroek  * void display_move(int x, int y)
224*b89261baSDavid van Moolenbroek  *
225*b89261baSDavid van Moolenbroek  * Efficiently move the cursor to x, y.  This assumes the cursor is
226*b89261baSDavid van Moolenbroek  * currently located at curr_x, curr_y, and will only use cursor
227*b89261baSDavid van Moolenbroek  * addressing when it is less expensive than overstriking what's
228*b89261baSDavid van Moolenbroek  * already on the screen.
229*b89261baSDavid van Moolenbroek  */
230*b89261baSDavid van Moolenbroek 
231*b89261baSDavid van Moolenbroek static void
display_move(int x,int y)232*b89261baSDavid van Moolenbroek display_move(int x, int y)
233*b89261baSDavid van Moolenbroek 
234*b89261baSDavid van Moolenbroek {
235*b89261baSDavid van Moolenbroek     char buff[128];
236*b89261baSDavid van Moolenbroek     char *p;
237*b89261baSDavid van Moolenbroek     char *bufp;
238*b89261baSDavid van Moolenbroek     char *colorp;
239*b89261baSDavid van Moolenbroek     int cnt = 0;
240*b89261baSDavid van Moolenbroek     int color = curr_color;
241*b89261baSDavid van Moolenbroek 
242*b89261baSDavid van Moolenbroek     dprintf("display_move(%d, %d): curr_x %d, curr_y %d\n", x, y, curr_x, curr_y);
243*b89261baSDavid van Moolenbroek 
244*b89261baSDavid van Moolenbroek     /* are we in a position to do this without cursor addressing? */
245*b89261baSDavid van Moolenbroek     if (curr_y < y || (curr_y == y && curr_x <= x))
246*b89261baSDavid van Moolenbroek     {
247*b89261baSDavid van Moolenbroek 	/* start buffering up what it would take to move there by rewriting
248*b89261baSDavid van Moolenbroek 	   what's on the screen */
249*b89261baSDavid van Moolenbroek 	cnt = CURSOR_COST;
250*b89261baSDavid van Moolenbroek 	p = buff;
251*b89261baSDavid van Moolenbroek 
252*b89261baSDavid van Moolenbroek 	/* one newline for every line */
253*b89261baSDavid van Moolenbroek 	while (cnt > 0 && curr_y < y)
254*b89261baSDavid van Moolenbroek 	{
255*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
256*b89261baSDavid van Moolenbroek 	    if (color != 0)
257*b89261baSDavid van Moolenbroek 	    {
258*b89261baSDavid van Moolenbroek 		p = strcpyend(p, color_setstr(0));
259*b89261baSDavid van Moolenbroek 		color = 0;
260*b89261baSDavid van Moolenbroek 		cnt -= 5;
261*b89261baSDavid van Moolenbroek 	    }
262*b89261baSDavid van Moolenbroek #endif
263*b89261baSDavid van Moolenbroek 	    *p++ = '\n';
264*b89261baSDavid van Moolenbroek 	    curr_y++;
265*b89261baSDavid van Moolenbroek 	    curr_x = 0;
266*b89261baSDavid van Moolenbroek 	    cnt--;
267*b89261baSDavid van Moolenbroek 	}
268*b89261baSDavid van Moolenbroek 
269*b89261baSDavid van Moolenbroek 	/* write whats in the screenbuf */
270*b89261baSDavid van Moolenbroek 	bufp = &screenbuf[lineindex(curr_y) + curr_x];
271*b89261baSDavid van Moolenbroek 	colorp = &colorbuf[lineindex(curr_y) + curr_x];
272*b89261baSDavid van Moolenbroek 	while (cnt > 0 && curr_x < x)
273*b89261baSDavid van Moolenbroek 	{
274*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
275*b89261baSDavid van Moolenbroek 	    if (color != *colorp)
276*b89261baSDavid van Moolenbroek 	    {
277*b89261baSDavid van Moolenbroek 		color = *colorp;
278*b89261baSDavid van Moolenbroek 		p = strcpyend(p, color_setstr(color));
279*b89261baSDavid van Moolenbroek 		cnt -= 5;
280*b89261baSDavid van Moolenbroek 	    }
281*b89261baSDavid van Moolenbroek #endif
282*b89261baSDavid van Moolenbroek 	    if ((*p = *bufp) == '\0')
283*b89261baSDavid van Moolenbroek 	    {
284*b89261baSDavid van Moolenbroek 		/* somwhere on screen we haven't been before */
285*b89261baSDavid van Moolenbroek 		*p = *bufp = ' ';
286*b89261baSDavid van Moolenbroek 	    }
287*b89261baSDavid van Moolenbroek 	    p++;
288*b89261baSDavid van Moolenbroek 	    bufp++;
289*b89261baSDavid van Moolenbroek 	    colorp++;
290*b89261baSDavid van Moolenbroek 	    curr_x++;
291*b89261baSDavid van Moolenbroek 	    cnt--;
292*b89261baSDavid van Moolenbroek 	}
293*b89261baSDavid van Moolenbroek     }
294*b89261baSDavid van Moolenbroek 
295*b89261baSDavid van Moolenbroek     /* move the cursor */
296*b89261baSDavid van Moolenbroek     if (cnt > 0)
297*b89261baSDavid van Moolenbroek     {
298*b89261baSDavid van Moolenbroek 	/* screen rewrite is cheaper */
299*b89261baSDavid van Moolenbroek 	*p = '\0';
300*b89261baSDavid van Moolenbroek 	fputs(buff, stdout);
301*b89261baSDavid van Moolenbroek 	curr_color = color;
302*b89261baSDavid van Moolenbroek     }
303*b89261baSDavid van Moolenbroek     else
304*b89261baSDavid van Moolenbroek     {
305*b89261baSDavid van Moolenbroek 	screen_move(x, y);
306*b89261baSDavid van Moolenbroek     }
307*b89261baSDavid van Moolenbroek 
308*b89261baSDavid van Moolenbroek     /* update our position */
309*b89261baSDavid van Moolenbroek     curr_x = x;
310*b89261baSDavid van Moolenbroek     curr_y = y;
311*b89261baSDavid van Moolenbroek }
312*b89261baSDavid van Moolenbroek 
313*b89261baSDavid van Moolenbroek /*
314*b89261baSDavid van Moolenbroek  * display_write(int x, int y, int newcolor, int eol, char *new)
315*b89261baSDavid van Moolenbroek  *
316*b89261baSDavid van Moolenbroek  * Optimized write to the display.  This writes characters to the
317*b89261baSDavid van Moolenbroek  * screen in a way that optimizes the number of characters actually
318*b89261baSDavid van Moolenbroek  * sent, by comparing what is being written to what is already on
319*b89261baSDavid van Moolenbroek  * the screen (according to screenbuf and colorbuf).  The string to
320*b89261baSDavid van Moolenbroek  * write is "new", the first character of "new" should appear at
321*b89261baSDavid van Moolenbroek  * screen position x, y.  If x is -1 then "new" begins wherever the
322*b89261baSDavid van Moolenbroek  * cursor is currently positioned.  The string is written with color
323*b89261baSDavid van Moolenbroek  * "newcolor".  If "eol" is true then the remainder of the line is
324*b89261baSDavid van Moolenbroek  * cleared.  It is expected that "new" will have no newlines and no
325*b89261baSDavid van Moolenbroek  * escape sequences.
326*b89261baSDavid van Moolenbroek  */
327*b89261baSDavid van Moolenbroek 
328*b89261baSDavid van Moolenbroek static void
display_write(int x,int y,int newcolor,int eol,const char * new)329*b89261baSDavid van Moolenbroek display_write(int x, int y, int newcolor, int eol, const char *new)
330*b89261baSDavid van Moolenbroek 
331*b89261baSDavid van Moolenbroek {
332*b89261baSDavid van Moolenbroek     char *bufp;
333*b89261baSDavid van Moolenbroek     char *colorp;
334*b89261baSDavid van Moolenbroek     int ch;
335*b89261baSDavid van Moolenbroek     int diff;
336*b89261baSDavid van Moolenbroek 
337*b89261baSDavid van Moolenbroek     dprintf("display_write(%d, %d, %d, %d, \"%s\")\n",
338*b89261baSDavid van Moolenbroek 	    x, y, newcolor, eol, new);
339*b89261baSDavid van Moolenbroek 
340*b89261baSDavid van Moolenbroek     /* dumb terminal handling here */
341*b89261baSDavid van Moolenbroek     if (!smart_terminal)
342*b89261baSDavid van Moolenbroek     {
343*b89261baSDavid van Moolenbroek 	if (x != -1)
344*b89261baSDavid van Moolenbroek 	{
345*b89261baSDavid van Moolenbroek 	    /* make sure we are on the right line */
346*b89261baSDavid van Moolenbroek 	    while (curr_y < y)
347*b89261baSDavid van Moolenbroek 	    {
348*b89261baSDavid van Moolenbroek 		putchar('\n');
349*b89261baSDavid van Moolenbroek 		curr_y++;
350*b89261baSDavid van Moolenbroek 		curr_x = 0;
351*b89261baSDavid van Moolenbroek 	    }
352*b89261baSDavid van Moolenbroek 
353*b89261baSDavid van Moolenbroek 	    /* make sure we are on the right column */
354*b89261baSDavid van Moolenbroek 	    while (curr_x < x)
355*b89261baSDavid van Moolenbroek 	    {
356*b89261baSDavid van Moolenbroek 		putchar(' ');
357*b89261baSDavid van Moolenbroek 		curr_x++;
358*b89261baSDavid van Moolenbroek 	    }
359*b89261baSDavid van Moolenbroek 	}
360*b89261baSDavid van Moolenbroek 
361*b89261baSDavid van Moolenbroek 	/* write */
362*b89261baSDavid van Moolenbroek 	fputs(new, stdout);
363*b89261baSDavid van Moolenbroek 	curr_x += strlen(new);
364*b89261baSDavid van Moolenbroek 
365*b89261baSDavid van Moolenbroek 	return;
366*b89261baSDavid van Moolenbroek     }
367*b89261baSDavid van Moolenbroek 
368*b89261baSDavid van Moolenbroek     /* adjust for "here" */
369*b89261baSDavid van Moolenbroek     if (x == -1)
370*b89261baSDavid van Moolenbroek     {
371*b89261baSDavid van Moolenbroek 	x = virt_x;
372*b89261baSDavid van Moolenbroek 	y = virt_y;
373*b89261baSDavid van Moolenbroek     }
374*b89261baSDavid van Moolenbroek     else
375*b89261baSDavid van Moolenbroek     {
376*b89261baSDavid van Moolenbroek 	virt_x = x;
377*b89261baSDavid van Moolenbroek 	virt_y = y;
378*b89261baSDavid van Moolenbroek     }
379*b89261baSDavid van Moolenbroek 
380*b89261baSDavid van Moolenbroek     /* a pointer to where we start */
381*b89261baSDavid van Moolenbroek     bufp = &screenbuf[lineindex(y) + x];
382*b89261baSDavid van Moolenbroek     colorp = &colorbuf[lineindex(y) + x];
383*b89261baSDavid van Moolenbroek 
384*b89261baSDavid van Moolenbroek     /* main loop */
385*b89261baSDavid van Moolenbroek     while ((ch = *new++) != '\0')
386*b89261baSDavid van Moolenbroek     {
387*b89261baSDavid van Moolenbroek 	/* if either character or color are different, an update is needed */
388*b89261baSDavid van Moolenbroek 	/* but only when the screen is wide enough */
389*b89261baSDavid van Moolenbroek 	if (x < display_width && (ch != *bufp || newcolor != *colorp))
390*b89261baSDavid van Moolenbroek 	{
391*b89261baSDavid van Moolenbroek 	    /* check cursor */
392*b89261baSDavid van Moolenbroek 	    if (y != curr_y || x != curr_x)
393*b89261baSDavid van Moolenbroek 	    {
394*b89261baSDavid van Moolenbroek 		/* have to move the cursor */
395*b89261baSDavid van Moolenbroek 		display_move(x, y);
396*b89261baSDavid van Moolenbroek 	    }
397*b89261baSDavid van Moolenbroek 
398*b89261baSDavid van Moolenbroek 	    /* write character */
399*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
400*b89261baSDavid van Moolenbroek 	    if (curr_color != newcolor)
401*b89261baSDavid van Moolenbroek 	    {
402*b89261baSDavid van Moolenbroek 		fputs(color_setstr(newcolor), stdout);
403*b89261baSDavid van Moolenbroek 		curr_color = newcolor;
404*b89261baSDavid van Moolenbroek 	    }
405*b89261baSDavid van Moolenbroek #endif
406*b89261baSDavid van Moolenbroek 	    putchar(ch);
407*b89261baSDavid van Moolenbroek 	    *bufp = ch;
408*b89261baSDavid van Moolenbroek 	    *colorp = curr_color;
409*b89261baSDavid van Moolenbroek 	    curr_x++;
410*b89261baSDavid van Moolenbroek 	}
411*b89261baSDavid van Moolenbroek 
412*b89261baSDavid van Moolenbroek 	/* move */
413*b89261baSDavid van Moolenbroek 	x++;
414*b89261baSDavid van Moolenbroek 	virt_x++;
415*b89261baSDavid van Moolenbroek 	bufp++;
416*b89261baSDavid van Moolenbroek 	colorp++;
417*b89261baSDavid van Moolenbroek     }
418*b89261baSDavid van Moolenbroek 
419*b89261baSDavid van Moolenbroek     /* eol handling */
420*b89261baSDavid van Moolenbroek     if (eol && *bufp != '\0')
421*b89261baSDavid van Moolenbroek     {
422*b89261baSDavid van Moolenbroek 	dprintf("display_write: clear-eol (bufp = \"%s\")\n", bufp);
423*b89261baSDavid van Moolenbroek 	/* make sure we are color 0 */
424*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
425*b89261baSDavid van Moolenbroek 	if (curr_color != 0)
426*b89261baSDavid van Moolenbroek 	{
427*b89261baSDavid van Moolenbroek 	    fputs(color_setstr(0), stdout);
428*b89261baSDavid van Moolenbroek 	    curr_color = 0;
429*b89261baSDavid van Moolenbroek 	}
430*b89261baSDavid van Moolenbroek #endif
431*b89261baSDavid van Moolenbroek 
432*b89261baSDavid van Moolenbroek 	/* make sure we are at the end */
433*b89261baSDavid van Moolenbroek 	if (x != curr_x || y != curr_y)
434*b89261baSDavid van Moolenbroek 	{
435*b89261baSDavid van Moolenbroek 	    screen_move(x, y);
436*b89261baSDavid van Moolenbroek 	    curr_x = x;
437*b89261baSDavid van Moolenbroek 	    curr_y = y;
438*b89261baSDavid van Moolenbroek 	}
439*b89261baSDavid van Moolenbroek 
440*b89261baSDavid van Moolenbroek 	/* clear to end */
441*b89261baSDavid van Moolenbroek 	screen_cleareol(strlen(bufp));
442*b89261baSDavid van Moolenbroek 
443*b89261baSDavid van Moolenbroek 	/* clear out whats left of this line's buffer */
444*b89261baSDavid van Moolenbroek 	diff = display_width - x;
445*b89261baSDavid van Moolenbroek 	if (diff > 0)
446*b89261baSDavid van Moolenbroek 	{
447*b89261baSDavid van Moolenbroek 	    memzero(bufp, diff);
448*b89261baSDavid van Moolenbroek 	    memzero(colorp, diff);
449*b89261baSDavid van Moolenbroek 	}
450*b89261baSDavid van Moolenbroek     }
451*b89261baSDavid van Moolenbroek }
452*b89261baSDavid van Moolenbroek 
453*b89261baSDavid van Moolenbroek static void
display_fmt(int x,int y,int newcolor,int eol,const char * fmt,...)454*b89261baSDavid van Moolenbroek display_fmt(int x, int y, int newcolor, int eol, const char *fmt, ...)
455*b89261baSDavid van Moolenbroek 
456*b89261baSDavid van Moolenbroek {
457*b89261baSDavid van Moolenbroek     va_list argp;
458*b89261baSDavid van Moolenbroek 
459*b89261baSDavid van Moolenbroek     va_start(argp, fmt);
460*b89261baSDavid van Moolenbroek 
461*b89261baSDavid van Moolenbroek     vsnprintf(scratchbuf, MAX_COLS, fmt, argp);
462*b89261baSDavid van Moolenbroek     display_write(x, y, newcolor, eol, scratchbuf);
463*b89261baSDavid van Moolenbroek }
464*b89261baSDavid van Moolenbroek 
465*b89261baSDavid van Moolenbroek static void
display_cte(void)466*b89261baSDavid van Moolenbroek display_cte(void)
467*b89261baSDavid van Moolenbroek 
468*b89261baSDavid van Moolenbroek {
469*b89261baSDavid van Moolenbroek     int len;
470*b89261baSDavid van Moolenbroek     int y;
471*b89261baSDavid van Moolenbroek     char *p;
472*b89261baSDavid van Moolenbroek     int need_clear = 0;
473*b89261baSDavid van Moolenbroek 
474*b89261baSDavid van Moolenbroek     /* is there anything out there that needs to be cleared? */
475*b89261baSDavid van Moolenbroek     p = &screenbuf[lineindex(virt_y) + virt_x];
476*b89261baSDavid van Moolenbroek     if (*p != '\0')
477*b89261baSDavid van Moolenbroek     {
478*b89261baSDavid van Moolenbroek 	need_clear = 1;
479*b89261baSDavid van Moolenbroek     }
480*b89261baSDavid van Moolenbroek     else
481*b89261baSDavid van Moolenbroek     {
482*b89261baSDavid van Moolenbroek 	/* this line is clear, what about the rest? */
483*b89261baSDavid van Moolenbroek 	y = virt_y;
484*b89261baSDavid van Moolenbroek 	while (++y < screen_length)
485*b89261baSDavid van Moolenbroek 	{
486*b89261baSDavid van Moolenbroek 	    if (screenbuf[lineindex(y)] != '\0')
487*b89261baSDavid van Moolenbroek 	    {
488*b89261baSDavid van Moolenbroek 		need_clear = 1;
489*b89261baSDavid van Moolenbroek 		break;
490*b89261baSDavid van Moolenbroek 	    }
491*b89261baSDavid van Moolenbroek 	}
492*b89261baSDavid van Moolenbroek     }
493*b89261baSDavid van Moolenbroek 
494*b89261baSDavid van Moolenbroek     if (need_clear)
495*b89261baSDavid van Moolenbroek     {
496*b89261baSDavid van Moolenbroek 	dprintf("display_cte: clearing\n");
497*b89261baSDavid van Moolenbroek 
498*b89261baSDavid van Moolenbroek 	/* we will need this later */
499*b89261baSDavid van Moolenbroek 	len = lineindex(virt_y) + virt_x;
500*b89261baSDavid van Moolenbroek 
501*b89261baSDavid van Moolenbroek 	/* move to x and y, then clear to end */
502*b89261baSDavid van Moolenbroek 	display_move(virt_x, virt_y);
503*b89261baSDavid van Moolenbroek 	if (!screen_cte())
504*b89261baSDavid van Moolenbroek 	{
505*b89261baSDavid van Moolenbroek 	    /* screen has no clear to end, so do it by hand */
506*b89261baSDavid van Moolenbroek 	    p = &screenbuf[len];
507*b89261baSDavid van Moolenbroek 	    len = strlen(p);
508*b89261baSDavid van Moolenbroek 	    if (len > 0)
509*b89261baSDavid van Moolenbroek 	    {
510*b89261baSDavid van Moolenbroek 		screen_cleareol(len);
511*b89261baSDavid van Moolenbroek 	    }
512*b89261baSDavid van Moolenbroek 	    while (++virt_y < screen_length)
513*b89261baSDavid van Moolenbroek 	    {
514*b89261baSDavid van Moolenbroek 		display_move(0, virt_y);
515*b89261baSDavid van Moolenbroek 		p = &screenbuf[lineindex(virt_y)];
516*b89261baSDavid van Moolenbroek 		len = strlen(p);
517*b89261baSDavid van Moolenbroek 		if (len > 0)
518*b89261baSDavid van Moolenbroek 		{
519*b89261baSDavid van Moolenbroek 		    screen_cleareol(len);
520*b89261baSDavid van Moolenbroek 		}
521*b89261baSDavid van Moolenbroek 	    }
522*b89261baSDavid van Moolenbroek 	}
523*b89261baSDavid van Moolenbroek 
524*b89261baSDavid van Moolenbroek 	/* clear the screenbuf */
525*b89261baSDavid van Moolenbroek 	memzero(&screenbuf[len], bufsize - len);
526*b89261baSDavid van Moolenbroek 	memzero(&colorbuf[len], bufsize - len);
527*b89261baSDavid van Moolenbroek     }
528*b89261baSDavid van Moolenbroek }
529*b89261baSDavid van Moolenbroek 
530*b89261baSDavid van Moolenbroek static void
summary_format(int x,int y,int * numbers,const char ** names,int * cidx)531*b89261baSDavid van Moolenbroek summary_format(int x, int y, int *numbers, const char **names, int *cidx)
532*b89261baSDavid van Moolenbroek 
533*b89261baSDavid van Moolenbroek {
534*b89261baSDavid van Moolenbroek     register int num;
535*b89261baSDavid van Moolenbroek     register const char *thisname;
536*b89261baSDavid van Moolenbroek     register const char *lastname = NULL;
537*b89261baSDavid van Moolenbroek     register int color;
538*b89261baSDavid van Moolenbroek 
539*b89261baSDavid van Moolenbroek     /* format each number followed by its string */
540*b89261baSDavid van Moolenbroek     while ((thisname = *names++) != NULL)
541*b89261baSDavid van Moolenbroek     {
542*b89261baSDavid van Moolenbroek 	/* get the number to format */
543*b89261baSDavid van Moolenbroek 	num = *numbers++;
544*b89261baSDavid van Moolenbroek 	color = 0;
545*b89261baSDavid van Moolenbroek 
546*b89261baSDavid van Moolenbroek 	/* display only non-zero numbers */
547*b89261baSDavid van Moolenbroek 	if (num != 0)
548*b89261baSDavid van Moolenbroek 	{
549*b89261baSDavid van Moolenbroek 	    /* write the previous name */
550*b89261baSDavid van Moolenbroek 	    if (lastname != NULL)
551*b89261baSDavid van Moolenbroek 	    {
552*b89261baSDavid van Moolenbroek 		display_write(-1, -1, 0, 0, lastname);
553*b89261baSDavid van Moolenbroek 	    }
554*b89261baSDavid van Moolenbroek 
555*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
556*b89261baSDavid van Moolenbroek 	    if (cidx != NULL)
557*b89261baSDavid van Moolenbroek 	    {
558*b89261baSDavid van Moolenbroek 		/* choose a color */
559*b89261baSDavid van Moolenbroek 		color = color_test(*cidx++, num);
560*b89261baSDavid van Moolenbroek 	    }
561*b89261baSDavid van Moolenbroek #endif
562*b89261baSDavid van Moolenbroek 
563*b89261baSDavid van Moolenbroek 	    /* write this number if positive */
564*b89261baSDavid van Moolenbroek 	    if (num > 0)
565*b89261baSDavid van Moolenbroek 	    {
566*b89261baSDavid van Moolenbroek 		display_write(x, y, color, 0, itoa(num));
567*b89261baSDavid van Moolenbroek 	    }
568*b89261baSDavid van Moolenbroek 
569*b89261baSDavid van Moolenbroek 	    /* defer writing this name */
570*b89261baSDavid van Moolenbroek 	    lastname = thisname;
571*b89261baSDavid van Moolenbroek 
572*b89261baSDavid van Moolenbroek 	    /* next iteration will not start at x, y */
573*b89261baSDavid van Moolenbroek 	    x = y = -1;
574*b89261baSDavid van Moolenbroek 	}
575*b89261baSDavid van Moolenbroek     }
576*b89261baSDavid van Moolenbroek 
577*b89261baSDavid van Moolenbroek     /* if the last string has a separator on the end, it has to be
578*b89261baSDavid van Moolenbroek        written with care */
579*b89261baSDavid van Moolenbroek     if (lastname != NULL)
580*b89261baSDavid van Moolenbroek     {
581*b89261baSDavid van Moolenbroek 	if ((num = strlen(lastname)) > 1 &&
582*b89261baSDavid van Moolenbroek 	    lastname[num-2] == ',' && lastname[num-1] == ' ')
583*b89261baSDavid van Moolenbroek 	{
584*b89261baSDavid van Moolenbroek 	    display_fmt(-1, -1, 0, 1, "%.*s", num-2, lastname);
585*b89261baSDavid van Moolenbroek 	}
586*b89261baSDavid van Moolenbroek 	else
587*b89261baSDavid van Moolenbroek 	{
588*b89261baSDavid van Moolenbroek 	    display_write(-1, -1, 0, 1, lastname);
589*b89261baSDavid van Moolenbroek 	}
590*b89261baSDavid van Moolenbroek     }
591*b89261baSDavid van Moolenbroek }
592*b89261baSDavid van Moolenbroek 
593*b89261baSDavid van Moolenbroek static void
summary_format_memory(int x,int y,long * numbers,const char ** names,int * cidx)594*b89261baSDavid van Moolenbroek summary_format_memory(int x, int y, long *numbers, const char **names, int *cidx)
595*b89261baSDavid van Moolenbroek 
596*b89261baSDavid van Moolenbroek {
597*b89261baSDavid van Moolenbroek     register long num;
598*b89261baSDavid van Moolenbroek     register int color;
599*b89261baSDavid van Moolenbroek     register const char *thisname;
600*b89261baSDavid van Moolenbroek     register const char *lastname = NULL;
601*b89261baSDavid van Moolenbroek 
602*b89261baSDavid van Moolenbroek     /* format each number followed by its string */
603*b89261baSDavid van Moolenbroek     while ((thisname = *names++) != NULL)
604*b89261baSDavid van Moolenbroek     {
605*b89261baSDavid van Moolenbroek 	/* get the number to format */
606*b89261baSDavid van Moolenbroek 	num = *numbers++;
607*b89261baSDavid van Moolenbroek 	color = 0;
608*b89261baSDavid van Moolenbroek 
609*b89261baSDavid van Moolenbroek 	/* display only non-zero numbers */
610*b89261baSDavid van Moolenbroek 	if (num != 0)
611*b89261baSDavid van Moolenbroek 	{
612*b89261baSDavid van Moolenbroek 	    /* write the previous name */
613*b89261baSDavid van Moolenbroek 	    if (lastname != NULL)
614*b89261baSDavid van Moolenbroek 	    {
615*b89261baSDavid van Moolenbroek 		display_write(-1, -1, 0, 0, lastname);
616*b89261baSDavid van Moolenbroek 	    }
617*b89261baSDavid van Moolenbroek 
618*b89261baSDavid van Moolenbroek 	    /* defer writing this name */
619*b89261baSDavid van Moolenbroek 	    lastname = thisname;
620*b89261baSDavid van Moolenbroek 
621*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
622*b89261baSDavid van Moolenbroek 	    /* choose a color */
623*b89261baSDavid van Moolenbroek 	    color = color_test(*cidx++, num);
624*b89261baSDavid van Moolenbroek #endif
625*b89261baSDavid van Moolenbroek 
626*b89261baSDavid van Moolenbroek 	    /* is this number in kilobytes? */
627*b89261baSDavid van Moolenbroek 	    if (thisname[0] == 'K')
628*b89261baSDavid van Moolenbroek 	    {
629*b89261baSDavid van Moolenbroek 		display_write(x, y, color, 0, format_k(num));
630*b89261baSDavid van Moolenbroek 		lastname++;
631*b89261baSDavid van Moolenbroek 	    }
632*b89261baSDavid van Moolenbroek 	    else
633*b89261baSDavid van Moolenbroek 	    {
634*b89261baSDavid van Moolenbroek 		display_write(x, y, color, 0, itoa((int)num));
635*b89261baSDavid van Moolenbroek 	    }
636*b89261baSDavid van Moolenbroek 
637*b89261baSDavid van Moolenbroek 	    /* next iteration will not start at x, y */
638*b89261baSDavid van Moolenbroek 	    x = y = -1;
639*b89261baSDavid van Moolenbroek 	}
640*b89261baSDavid van Moolenbroek     }
641*b89261baSDavid van Moolenbroek 
642*b89261baSDavid van Moolenbroek     /* if the last string has a separator on the end, it has to be
643*b89261baSDavid van Moolenbroek        written with care */
644*b89261baSDavid van Moolenbroek     if (lastname != NULL)
645*b89261baSDavid van Moolenbroek     {
646*b89261baSDavid van Moolenbroek 	if ((num = strlen(lastname)) > 1 &&
647*b89261baSDavid van Moolenbroek 	    lastname[num-2] == ',' && lastname[num-1] == ' ')
648*b89261baSDavid van Moolenbroek 	{
649*b89261baSDavid van Moolenbroek 	    display_fmt(-1, -1, 0, 1, "%.*s", num-2, lastname);
650*b89261baSDavid van Moolenbroek 	}
651*b89261baSDavid van Moolenbroek 	else
652*b89261baSDavid van Moolenbroek 	{
653*b89261baSDavid van Moolenbroek 	    display_write(-1, -1, 0, 1, lastname);
654*b89261baSDavid van Moolenbroek 	}
655*b89261baSDavid van Moolenbroek     }
656*b89261baSDavid van Moolenbroek }
657*b89261baSDavid van Moolenbroek 
658*b89261baSDavid van Moolenbroek /*
659*b89261baSDavid van Moolenbroek  * int display_resize()
660*b89261baSDavid van Moolenbroek  *
661*b89261baSDavid van Moolenbroek  * Reallocate buffer space needed by the display package to accomodate
662*b89261baSDavid van Moolenbroek  * a new screen size.  Must be called whenever the screen's size has
663*b89261baSDavid van Moolenbroek  * changed.  Returns the number of lines available for displaying
664*b89261baSDavid van Moolenbroek  * processes or -1 if there was a problem allocating space.
665*b89261baSDavid van Moolenbroek  */
666*b89261baSDavid van Moolenbroek 
667*b89261baSDavid van Moolenbroek int
display_resize()668*b89261baSDavid van Moolenbroek display_resize()
669*b89261baSDavid van Moolenbroek 
670*b89261baSDavid van Moolenbroek {
671*b89261baSDavid van Moolenbroek     register int top_lines;
672*b89261baSDavid van Moolenbroek     register int newsize;
673*b89261baSDavid van Moolenbroek 
674*b89261baSDavid van Moolenbroek     /* calculate the current dimensions */
675*b89261baSDavid van Moolenbroek     /* if operating in "dumb" mode, we only need one line */
676*b89261baSDavid van Moolenbroek     top_lines = smart_terminal ? screen_length : 1;
677*b89261baSDavid van Moolenbroek 
678*b89261baSDavid van Moolenbroek     /* we don't want more than MAX_COLS columns, since the machine-dependent
679*b89261baSDavid van Moolenbroek        modules make static allocations based on MAX_COLS and we don't want
680*b89261baSDavid van Moolenbroek        to run off the end of their buffers */
681*b89261baSDavid van Moolenbroek     display_width = screen_width;
682*b89261baSDavid van Moolenbroek     if (display_width >= MAX_COLS)
683*b89261baSDavid van Moolenbroek     {
684*b89261baSDavid van Moolenbroek 	display_width = MAX_COLS - 1;
685*b89261baSDavid van Moolenbroek     }
686*b89261baSDavid van Moolenbroek 
687*b89261baSDavid van Moolenbroek     /* see how much space we need */
688*b89261baSDavid van Moolenbroek     newsize = top_lines * (MAX_COLS + 1);
689*b89261baSDavid van Moolenbroek 
690*b89261baSDavid van Moolenbroek     /* reallocate only if we need more than we already have */
691*b89261baSDavid van Moolenbroek     if (newsize > bufsize)
692*b89261baSDavid van Moolenbroek     {
693*b89261baSDavid van Moolenbroek 	/* deallocate any previous buffer that may have been there */
694*b89261baSDavid van Moolenbroek 	if (screenbuf != NULL)
695*b89261baSDavid van Moolenbroek 	{
696*b89261baSDavid van Moolenbroek 	    free(screenbuf);
697*b89261baSDavid van Moolenbroek 	}
698*b89261baSDavid van Moolenbroek 	if (colorbuf != NULL)
699*b89261baSDavid van Moolenbroek 	{
700*b89261baSDavid van Moolenbroek 	    free(colorbuf);
701*b89261baSDavid van Moolenbroek 	}
702*b89261baSDavid van Moolenbroek 
703*b89261baSDavid van Moolenbroek 	/* allocate space for the screen and color buffers */
704*b89261baSDavid van Moolenbroek 	bufsize = newsize;
705*b89261baSDavid van Moolenbroek 	screenbuf = ecalloc(bufsize, sizeof(char));
706*b89261baSDavid van Moolenbroek 	colorbuf = ecalloc(bufsize, sizeof(char));
707*b89261baSDavid van Moolenbroek 	if (screenbuf == NULL || colorbuf == NULL)
708*b89261baSDavid van Moolenbroek 	{
709*b89261baSDavid van Moolenbroek 	    /* oops! */
710*b89261baSDavid van Moolenbroek 	    return(-1);
711*b89261baSDavid van Moolenbroek 	}
712*b89261baSDavid van Moolenbroek     }
713*b89261baSDavid van Moolenbroek     else
714*b89261baSDavid van Moolenbroek     {
715*b89261baSDavid van Moolenbroek 	/* just clear them out */
716*b89261baSDavid van Moolenbroek 	memzero(screenbuf, bufsize);
717*b89261baSDavid van Moolenbroek 	memzero(colorbuf, bufsize);
718*b89261baSDavid van Moolenbroek     }
719*b89261baSDavid van Moolenbroek 
720*b89261baSDavid van Moolenbroek     /* for dumb terminals, pretend like we can show any amount */
721*b89261baSDavid van Moolenbroek     if (!smart_terminal)
722*b89261baSDavid van Moolenbroek 	return Largest;
723*b89261baSDavid van Moolenbroek 
724*b89261baSDavid van Moolenbroek     /* adjust total lines on screen to lines available for procs */
725*b89261baSDavid van Moolenbroek     if (top_lines < y_procs)
726*b89261baSDavid van Moolenbroek 	top_lines = 0;
727*b89261baSDavid van Moolenbroek     else
728*b89261baSDavid van Moolenbroek 	top_lines -= y_procs;
729*b89261baSDavid van Moolenbroek 
730*b89261baSDavid van Moolenbroek     /* return number of lines available */
731*b89261baSDavid van Moolenbroek     return top_lines;
732*b89261baSDavid van Moolenbroek }
733*b89261baSDavid van Moolenbroek 
734*b89261baSDavid van Moolenbroek int
display_lines()735*b89261baSDavid van Moolenbroek display_lines()
736*b89261baSDavid van Moolenbroek 
737*b89261baSDavid van Moolenbroek {
738*b89261baSDavid van Moolenbroek     return(smart_terminal ? screen_length : Largest);
739*b89261baSDavid van Moolenbroek }
740*b89261baSDavid van Moolenbroek 
741*b89261baSDavid van Moolenbroek int
display_columns()742*b89261baSDavid van Moolenbroek display_columns()
743*b89261baSDavid van Moolenbroek 
744*b89261baSDavid van Moolenbroek {
745*b89261baSDavid van Moolenbroek     return(display_width);
746*b89261baSDavid van Moolenbroek }
747*b89261baSDavid van Moolenbroek 
748*b89261baSDavid van Moolenbroek /*
749*b89261baSDavid van Moolenbroek  * int display_init(struct statics *statics)
750*b89261baSDavid van Moolenbroek  *
751*b89261baSDavid van Moolenbroek  * Initialize the display system based on information in the statics
752*b89261baSDavid van Moolenbroek  * structure.  Returns the number of lines available for displaying
753*b89261baSDavid van Moolenbroek  * processes or -1 if there was an error.
754*b89261baSDavid van Moolenbroek  */
755*b89261baSDavid van Moolenbroek 
756*b89261baSDavid van Moolenbroek int
display_setmulti(int m)757*b89261baSDavid van Moolenbroek display_setmulti(int m)
758*b89261baSDavid van Moolenbroek {
759*b89261baSDavid van Moolenbroek     int i;
760*b89261baSDavid van Moolenbroek     if (m == multi)
761*b89261baSDavid van Moolenbroek 	return 0;
762*b89261baSDavid van Moolenbroek     if ((multi = m) != 0) {
763*b89261baSDavid van Moolenbroek 	for (i = 1; i < ncpu; i++)
764*b89261baSDavid van Moolenbroek 	{
765*b89261baSDavid van Moolenbroek 	    /* adjust screen placements */
766*b89261baSDavid van Moolenbroek 	    y_kernel++;
767*b89261baSDavid van Moolenbroek 	    y_mem++;
768*b89261baSDavid van Moolenbroek 	    y_swap++;
769*b89261baSDavid van Moolenbroek 	    y_message++;
770*b89261baSDavid van Moolenbroek 	    y_header++;
771*b89261baSDavid van Moolenbroek 	    y_idlecursor++;
772*b89261baSDavid van Moolenbroek 	    y_procs++;
773*b89261baSDavid van Moolenbroek 	}
774*b89261baSDavid van Moolenbroek 	return -(ncpu - 1);
775*b89261baSDavid van Moolenbroek     } else {
776*b89261baSDavid van Moolenbroek 	for (i = 1; i < ncpu; i++)
777*b89261baSDavid van Moolenbroek 	{
778*b89261baSDavid van Moolenbroek 	    /* adjust screen placements */
779*b89261baSDavid van Moolenbroek 	    y_kernel--;
780*b89261baSDavid van Moolenbroek 	    y_mem--;
781*b89261baSDavid van Moolenbroek 	    y_swap--;
782*b89261baSDavid van Moolenbroek 	    y_message--;
783*b89261baSDavid van Moolenbroek 	    y_header--;
784*b89261baSDavid van Moolenbroek 	    y_idlecursor--;
785*b89261baSDavid van Moolenbroek 	    y_procs--;
786*b89261baSDavid van Moolenbroek 	}
787*b89261baSDavid van Moolenbroek 	return (ncpu - 1);
788*b89261baSDavid van Moolenbroek     }
789*b89261baSDavid van Moolenbroek }
790*b89261baSDavid van Moolenbroek 
791*b89261baSDavid van Moolenbroek int
display_init(struct statics * statics,int percpuinfo)792*b89261baSDavid van Moolenbroek display_init(struct statics *statics, int percpuinfo)
793*b89261baSDavid van Moolenbroek 
794*b89261baSDavid van Moolenbroek {
795*b89261baSDavid van Moolenbroek     register int top_lines;
796*b89261baSDavid van Moolenbroek     register const char **pp;
797*b89261baSDavid van Moolenbroek     register char *p;
798*b89261baSDavid van Moolenbroek     register int *ip;
799*b89261baSDavid van Moolenbroek     register int i;
800*b89261baSDavid van Moolenbroek 
801*b89261baSDavid van Moolenbroek     /* certain things may influence the screen layout,
802*b89261baSDavid van Moolenbroek        so look at those first */
803*b89261baSDavid van Moolenbroek 
804*b89261baSDavid van Moolenbroek     ncpu = statics->ncpu ? statics->ncpu : 1;
805*b89261baSDavid van Moolenbroek     /* a kernel line shifts parts of the display down */
806*b89261baSDavid van Moolenbroek     kernel_names = statics->kernel_names;
807*b89261baSDavid van Moolenbroek     if ((num_kernel = string_count(kernel_names)) > 0)
808*b89261baSDavid van Moolenbroek     {
809*b89261baSDavid van Moolenbroek 	/* adjust screen placements */
810*b89261baSDavid van Moolenbroek 	y_mem++;
811*b89261baSDavid van Moolenbroek 	y_swap++;
812*b89261baSDavid van Moolenbroek 	y_message++;
813*b89261baSDavid van Moolenbroek 	y_header++;
814*b89261baSDavid van Moolenbroek 	y_idlecursor++;
815*b89261baSDavid van Moolenbroek 	y_procs++;
816*b89261baSDavid van Moolenbroek     }
817*b89261baSDavid van Moolenbroek 
818*b89261baSDavid van Moolenbroek     (void)display_setmulti(percpuinfo);
819*b89261baSDavid van Moolenbroek 
820*b89261baSDavid van Moolenbroek     /* a swap line shifts parts of the display down one */
821*b89261baSDavid van Moolenbroek     swap_names = statics->swap_names;
822*b89261baSDavid van Moolenbroek     if ((num_swap = string_count(swap_names)) > 0)
823*b89261baSDavid van Moolenbroek     {
824*b89261baSDavid van Moolenbroek 	/* adjust screen placements */
825*b89261baSDavid van Moolenbroek 	y_message++;
826*b89261baSDavid van Moolenbroek 	y_header++;
827*b89261baSDavid van Moolenbroek 	y_idlecursor++;
828*b89261baSDavid van Moolenbroek 	y_procs++;
829*b89261baSDavid van Moolenbroek     }
830*b89261baSDavid van Moolenbroek 
831*b89261baSDavid van Moolenbroek     /* call resize to do the dirty work */
832*b89261baSDavid van Moolenbroek     top_lines = display_resize();
833*b89261baSDavid van Moolenbroek 
834*b89261baSDavid van Moolenbroek     /* only do the rest if we need to */
835*b89261baSDavid van Moolenbroek     if (top_lines > -1)
836*b89261baSDavid van Moolenbroek     {
837*b89261baSDavid van Moolenbroek 	/* save pointers and allocate space for names */
838*b89261baSDavid van Moolenbroek 	procstate_names = statics->procstate_names;
839*b89261baSDavid van Moolenbroek 	num_procstates = string_count(procstate_names);
840*b89261baSDavid van Moolenbroek 	lprocstates = ecalloc(num_procstates, sizeof(int));
841*b89261baSDavid van Moolenbroek 
842*b89261baSDavid van Moolenbroek 	cpustate_names = statics->cpustate_names;
843*b89261baSDavid van Moolenbroek 	num_cpustates = string_count(cpustate_names);
844*b89261baSDavid van Moolenbroek 	lcpustates = ecalloc(num_cpustates, sizeof(int) * ncpu);
845*b89261baSDavid van Moolenbroek 	cpustate_columns = ecalloc(num_cpustates, sizeof(int));
846*b89261baSDavid van Moolenbroek 	memory_names = statics->memory_names;
847*b89261baSDavid van Moolenbroek 	num_memory = string_count(memory_names);
848*b89261baSDavid van Moolenbroek 
849*b89261baSDavid van Moolenbroek 	/* calculate starting columns where needed */
850*b89261baSDavid van Moolenbroek 	cpustate_total_length = 0;
851*b89261baSDavid van Moolenbroek 	pp = cpustate_names;
852*b89261baSDavid van Moolenbroek 	ip = cpustate_columns;
853*b89261baSDavid van Moolenbroek 	while (*pp != NULL)
854*b89261baSDavid van Moolenbroek 	{
855*b89261baSDavid van Moolenbroek 	    *ip++ = cpustate_total_length;
856*b89261baSDavid van Moolenbroek 	    if ((i = strlen(*pp++)) > 0)
857*b89261baSDavid van Moolenbroek 	    {
858*b89261baSDavid van Moolenbroek 		cpustate_total_length += i + 8;
859*b89261baSDavid van Moolenbroek 	    }
860*b89261baSDavid van Moolenbroek 	}
861*b89261baSDavid van Moolenbroek 	cpustate_total_length -= 2;
862*b89261baSDavid van Moolenbroek     }
863*b89261baSDavid van Moolenbroek 
864*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
865*b89261baSDavid van Moolenbroek     /* set up color tags for loadavg */
866*b89261baSDavid van Moolenbroek     load_cidx[0] = color_tag("1min");
867*b89261baSDavid van Moolenbroek     load_cidx[1] = color_tag("5min");
868*b89261baSDavid van Moolenbroek     load_cidx[2] = color_tag("15min");
869*b89261baSDavid van Moolenbroek 
870*b89261baSDavid van Moolenbroek     /* find header color */
871*b89261baSDavid van Moolenbroek     header_cidx = color_tag("header");
872*b89261baSDavid van Moolenbroek 
873*b89261baSDavid van Moolenbroek     /* color tags for cpu states */
874*b89261baSDavid van Moolenbroek     cpustate_cidx = emalloc(num_cpustates * sizeof(int));
875*b89261baSDavid van Moolenbroek     i = 0;
876*b89261baSDavid van Moolenbroek     p = strcpyend(scratchbuf, "cpu.");
877*b89261baSDavid van Moolenbroek     while (i < num_cpustates)
878*b89261baSDavid van Moolenbroek     {
879*b89261baSDavid van Moolenbroek 	strcpy(p, cpustate_names[i]);
880*b89261baSDavid van Moolenbroek 	cpustate_cidx[i++] = color_tag(scratchbuf);
881*b89261baSDavid van Moolenbroek     }
882*b89261baSDavid van Moolenbroek 
883*b89261baSDavid van Moolenbroek     /* color tags for kernel */
884*b89261baSDavid van Moolenbroek     if (num_kernel > 0)
885*b89261baSDavid van Moolenbroek     {
886*b89261baSDavid van Moolenbroek 	kernel_cidx = emalloc(num_kernel * sizeof(int));
887*b89261baSDavid van Moolenbroek 	i = 0;
888*b89261baSDavid van Moolenbroek 	p = strcpyend(scratchbuf, "kernel.");
889*b89261baSDavid van Moolenbroek 	while (i < num_kernel)
890*b89261baSDavid van Moolenbroek 	{
891*b89261baSDavid van Moolenbroek 	    strcpy(p, homogenize(kernel_names[i]+1));
892*b89261baSDavid van Moolenbroek 	    kernel_cidx[i++] = color_tag(scratchbuf);
893*b89261baSDavid van Moolenbroek 	}
894*b89261baSDavid van Moolenbroek     }
895*b89261baSDavid van Moolenbroek 
896*b89261baSDavid van Moolenbroek     /* color tags for memory */
897*b89261baSDavid van Moolenbroek     memory_cidx = emalloc(num_memory * sizeof(int));
898*b89261baSDavid van Moolenbroek     i = 0;
899*b89261baSDavid van Moolenbroek     p = strcpyend(scratchbuf, "memory.");
900*b89261baSDavid van Moolenbroek     while (i < num_memory)
901*b89261baSDavid van Moolenbroek     {
902*b89261baSDavid van Moolenbroek 	strcpy(p, homogenize(memory_names[i]+1));
903*b89261baSDavid van Moolenbroek 	memory_cidx[i++] = color_tag(scratchbuf);
904*b89261baSDavid van Moolenbroek     }
905*b89261baSDavid van Moolenbroek 
906*b89261baSDavid van Moolenbroek     /* color tags for swap */
907*b89261baSDavid van Moolenbroek     if (num_swap > 0)
908*b89261baSDavid van Moolenbroek     {
909*b89261baSDavid van Moolenbroek 	swap_cidx = emalloc(num_swap * sizeof(int));
910*b89261baSDavid van Moolenbroek 	i = 0;
911*b89261baSDavid van Moolenbroek 	p = strcpyend(scratchbuf, "swap.");
912*b89261baSDavid van Moolenbroek 	while (i < num_swap)
913*b89261baSDavid van Moolenbroek 	{
914*b89261baSDavid van Moolenbroek 	    strcpy(p, homogenize(swap_names[i]+1));
915*b89261baSDavid van Moolenbroek 	    swap_cidx[i++] = color_tag(scratchbuf);
916*b89261baSDavid van Moolenbroek 	}
917*b89261baSDavid van Moolenbroek     }
918*b89261baSDavid van Moolenbroek #endif
919*b89261baSDavid van Moolenbroek 
920*b89261baSDavid van Moolenbroek     /* return number of lines available (or error) */
921*b89261baSDavid van Moolenbroek     return(top_lines);
922*b89261baSDavid van Moolenbroek }
923*b89261baSDavid van Moolenbroek 
924*b89261baSDavid van Moolenbroek static void
pr_loadavg(double avg,int i)925*b89261baSDavid van Moolenbroek pr_loadavg(double avg, int i)
926*b89261baSDavid van Moolenbroek 
927*b89261baSDavid van Moolenbroek {
928*b89261baSDavid van Moolenbroek     int color = 0;
929*b89261baSDavid van Moolenbroek 
930*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
931*b89261baSDavid van Moolenbroek     color = color_test(load_cidx[i], (int)(avg * 100));
932*b89261baSDavid van Moolenbroek #endif
933*b89261baSDavid van Moolenbroek     display_fmt(x_loadave + X_LOADAVEWIDTH * i, y_loadave, color, 0,
934*b89261baSDavid van Moolenbroek 		avg < 10.0 ? " %5.2f" : " %5.1f", avg);
935*b89261baSDavid van Moolenbroek     display_write(-1, -1, 0, 0, (i < 2 ? "," : ";"));
936*b89261baSDavid van Moolenbroek }
937*b89261baSDavid van Moolenbroek 
938*b89261baSDavid van Moolenbroek void
i_loadave(int mpid,double * avenrun)939*b89261baSDavid van Moolenbroek i_loadave(int mpid, double *avenrun)
940*b89261baSDavid van Moolenbroek 
941*b89261baSDavid van Moolenbroek {
942*b89261baSDavid van Moolenbroek     register int i;
943*b89261baSDavid van Moolenbroek 
944*b89261baSDavid van Moolenbroek     /* mpid == -1 implies this system doesn't have an _mpid */
945*b89261baSDavid van Moolenbroek     if (mpid != -1)
946*b89261baSDavid van Moolenbroek     {
947*b89261baSDavid van Moolenbroek 	display_fmt(0, 0, 0, 0,
948*b89261baSDavid van Moolenbroek 		    "last pid: %5d;  load avg:", mpid);
949*b89261baSDavid van Moolenbroek 	x_loadave = X_LOADAVE;
950*b89261baSDavid van Moolenbroek     }
951*b89261baSDavid van Moolenbroek     else
952*b89261baSDavid van Moolenbroek     {
953*b89261baSDavid van Moolenbroek 	display_write(0, 0, 0, 0, "load averages:");
954*b89261baSDavid van Moolenbroek 	x_loadave = X_LOADAVE - X_LASTPIDWIDTH;
955*b89261baSDavid van Moolenbroek     }
956*b89261baSDavid van Moolenbroek     for (i = 0; i < 3; i++)
957*b89261baSDavid van Moolenbroek     {
958*b89261baSDavid van Moolenbroek 	pr_loadavg(avenrun[i], i);
959*b89261baSDavid van Moolenbroek     }
960*b89261baSDavid van Moolenbroek 
961*b89261baSDavid van Moolenbroek     lmpid = mpid;
962*b89261baSDavid van Moolenbroek }
963*b89261baSDavid van Moolenbroek 
964*b89261baSDavid van Moolenbroek void
u_loadave(int mpid,double * avenrun)965*b89261baSDavid van Moolenbroek u_loadave(int mpid, double *avenrun)
966*b89261baSDavid van Moolenbroek 
967*b89261baSDavid van Moolenbroek {
968*b89261baSDavid van Moolenbroek     register int i;
969*b89261baSDavid van Moolenbroek 
970*b89261baSDavid van Moolenbroek     if (mpid != -1)
971*b89261baSDavid van Moolenbroek     {
972*b89261baSDavid van Moolenbroek 	/* change screen only when value has really changed */
973*b89261baSDavid van Moolenbroek 	if (mpid != lmpid)
974*b89261baSDavid van Moolenbroek 	{
975*b89261baSDavid van Moolenbroek 	    display_fmt(x_lastpid, y_lastpid, 0, 0,
976*b89261baSDavid van Moolenbroek 			"%5d", mpid);
977*b89261baSDavid van Moolenbroek 	    lmpid = mpid;
978*b89261baSDavid van Moolenbroek 	}
979*b89261baSDavid van Moolenbroek     }
980*b89261baSDavid van Moolenbroek 
981*b89261baSDavid van Moolenbroek     /* display new load averages */
982*b89261baSDavid van Moolenbroek     for (i = 0; i < 3; i++)
983*b89261baSDavid van Moolenbroek     {
984*b89261baSDavid van Moolenbroek 	pr_loadavg(avenrun[i], i);
985*b89261baSDavid van Moolenbroek     }
986*b89261baSDavid van Moolenbroek }
987*b89261baSDavid van Moolenbroek 
988*b89261baSDavid van Moolenbroek static char minibar_buffer[64];
989*b89261baSDavid van Moolenbroek #define MINIBAR_WIDTH 20
990*b89261baSDavid van Moolenbroek 
991*b89261baSDavid van Moolenbroek void
i_minibar(int (* formatter)(char *,int))992*b89261baSDavid van Moolenbroek i_minibar(int (*formatter)(char *, int))
993*b89261baSDavid van Moolenbroek {
994*b89261baSDavid van Moolenbroek     (void)((*formatter)(minibar_buffer, MINIBAR_WIDTH));
995*b89261baSDavid van Moolenbroek 
996*b89261baSDavid van Moolenbroek     display_write(x_minibar, y_minibar, 0, 0, minibar_buffer);
997*b89261baSDavid van Moolenbroek }
998*b89261baSDavid van Moolenbroek 
999*b89261baSDavid van Moolenbroek void
u_minibar(int (* formatter)(char *,int))1000*b89261baSDavid van Moolenbroek u_minibar(int (*formatter)(char *, int))
1001*b89261baSDavid van Moolenbroek {
1002*b89261baSDavid van Moolenbroek     (void)((*formatter)(minibar_buffer, MINIBAR_WIDTH));
1003*b89261baSDavid van Moolenbroek 
1004*b89261baSDavid van Moolenbroek     display_write(x_minibar, y_minibar, 0, 0, minibar_buffer);
1005*b89261baSDavid van Moolenbroek }
1006*b89261baSDavid van Moolenbroek 
1007*b89261baSDavid van Moolenbroek static int uptime_days;
1008*b89261baSDavid van Moolenbroek static int uptime_hours;
1009*b89261baSDavid van Moolenbroek static int uptime_mins;
1010*b89261baSDavid van Moolenbroek static int uptime_secs;
1011*b89261baSDavid van Moolenbroek 
1012*b89261baSDavid van Moolenbroek void
i_uptime(time_t * bt,time_t * tod)1013*b89261baSDavid van Moolenbroek i_uptime(time_t *bt, time_t *tod)
1014*b89261baSDavid van Moolenbroek 
1015*b89261baSDavid van Moolenbroek {
1016*b89261baSDavid van Moolenbroek     time_t uptime;
1017*b89261baSDavid van Moolenbroek 
1018*b89261baSDavid van Moolenbroek     if (*bt != -1)
1019*b89261baSDavid van Moolenbroek     {
1020*b89261baSDavid van Moolenbroek 	uptime = *tod - *bt;
1021*b89261baSDavid van Moolenbroek 	uptime += 30;
1022*b89261baSDavid van Moolenbroek 	uptime_days = uptime / 86400;
1023*b89261baSDavid van Moolenbroek 	uptime %= 86400;
1024*b89261baSDavid van Moolenbroek 	uptime_hours = uptime / 3600;
1025*b89261baSDavid van Moolenbroek 	uptime %= 3600;
1026*b89261baSDavid van Moolenbroek 	uptime_mins = uptime / 60;
1027*b89261baSDavid van Moolenbroek 	uptime_secs = uptime % 60;
1028*b89261baSDavid van Moolenbroek 
1029*b89261baSDavid van Moolenbroek 	/*
1030*b89261baSDavid van Moolenbroek 	 *  Display the uptime.
1031*b89261baSDavid van Moolenbroek 	 */
1032*b89261baSDavid van Moolenbroek 
1033*b89261baSDavid van Moolenbroek 	display_fmt(x_uptime, y_uptime, 0, 0,
1034*b89261baSDavid van Moolenbroek 		    "  up %d+%02d:%02d:%02d",
1035*b89261baSDavid van Moolenbroek 		    uptime_days, uptime_hours, uptime_mins, uptime_secs);
1036*b89261baSDavid van Moolenbroek     }
1037*b89261baSDavid van Moolenbroek }
1038*b89261baSDavid van Moolenbroek 
1039*b89261baSDavid van Moolenbroek void
u_uptime(time_t * bt,time_t * tod)1040*b89261baSDavid van Moolenbroek u_uptime(time_t *bt, time_t *tod)
1041*b89261baSDavid van Moolenbroek 
1042*b89261baSDavid van Moolenbroek {
1043*b89261baSDavid van Moolenbroek     i_uptime(bt, tod);
1044*b89261baSDavid van Moolenbroek }
1045*b89261baSDavid van Moolenbroek 
1046*b89261baSDavid van Moolenbroek 
1047*b89261baSDavid van Moolenbroek void
i_timeofday(time_t * tod)1048*b89261baSDavid van Moolenbroek i_timeofday(time_t *tod)
1049*b89261baSDavid van Moolenbroek 
1050*b89261baSDavid van Moolenbroek {
1051*b89261baSDavid van Moolenbroek     /*
1052*b89261baSDavid van Moolenbroek      *  Display the current time.
1053*b89261baSDavid van Moolenbroek      *  "ctime" always returns a string that looks like this:
1054*b89261baSDavid van Moolenbroek      *
1055*b89261baSDavid van Moolenbroek      *	Sun Sep 16 01:03:52 1973
1056*b89261baSDavid van Moolenbroek      *  012345678901234567890123
1057*b89261baSDavid van Moolenbroek      *	          1         2
1058*b89261baSDavid van Moolenbroek      *
1059*b89261baSDavid van Moolenbroek      *  We want indices 11 thru 18 (length 8).
1060*b89261baSDavid van Moolenbroek      */
1061*b89261baSDavid van Moolenbroek 
1062*b89261baSDavid van Moolenbroek     int x;
1063*b89261baSDavid van Moolenbroek 
1064*b89261baSDavid van Moolenbroek     /* where on the screen do we start? */
1065*b89261baSDavid van Moolenbroek     x = (smart_terminal ? screen_width : 79) - 8;
1066*b89261baSDavid van Moolenbroek 
1067*b89261baSDavid van Moolenbroek     /* but don't bump in to uptime */
1068*b89261baSDavid van Moolenbroek     if (x < x_uptime + 19)
1069*b89261baSDavid van Moolenbroek     {
1070*b89261baSDavid van Moolenbroek 	x = x_uptime + 19;
1071*b89261baSDavid van Moolenbroek     }
1072*b89261baSDavid van Moolenbroek 
1073*b89261baSDavid van Moolenbroek     /* display it */
1074*b89261baSDavid van Moolenbroek     display_fmt(x, 0, 0, 1, "%-8.8s", &(ctime(tod)[11]));
1075*b89261baSDavid van Moolenbroek }
1076*b89261baSDavid van Moolenbroek 
1077*b89261baSDavid van Moolenbroek static int ltotal = 0;
1078*b89261baSDavid van Moolenbroek static int lthreads = 0;
1079*b89261baSDavid van Moolenbroek 
1080*b89261baSDavid van Moolenbroek /*
1081*b89261baSDavid van Moolenbroek  *  *_procstates(total, brkdn, names) - print the process summary line
1082*b89261baSDavid van Moolenbroek  */
1083*b89261baSDavid van Moolenbroek 
1084*b89261baSDavid van Moolenbroek 
1085*b89261baSDavid van Moolenbroek void
i_procstates(int total,int * brkdn,int threads)1086*b89261baSDavid van Moolenbroek i_procstates(int total, int *brkdn, int threads)
1087*b89261baSDavid van Moolenbroek 
1088*b89261baSDavid van Moolenbroek {
1089*b89261baSDavid van Moolenbroek     /* write current number of processes and remember the value */
1090*b89261baSDavid van Moolenbroek     display_fmt(0, y_procstate, 0, 0,
1091*b89261baSDavid van Moolenbroek 		"%d %s: ", total, threads ? "threads" : "processes");
1092*b89261baSDavid van Moolenbroek     ltotal = total;
1093*b89261baSDavid van Moolenbroek 
1094*b89261baSDavid van Moolenbroek     /* remember where the summary starts */
1095*b89261baSDavid van Moolenbroek     x_procstate = virt_x;
1096*b89261baSDavid van Moolenbroek 
1097*b89261baSDavid van Moolenbroek     if (total > 0)
1098*b89261baSDavid van Moolenbroek     {
1099*b89261baSDavid van Moolenbroek 	/* format and print the process state summary */
1100*b89261baSDavid van Moolenbroek 	summary_format(-1, -1, brkdn, procstate_names, NULL);
1101*b89261baSDavid van Moolenbroek 
1102*b89261baSDavid van Moolenbroek 	/* save the numbers for next time */
1103*b89261baSDavid van Moolenbroek 	memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
1104*b89261baSDavid van Moolenbroek 	lthreads = threads;
1105*b89261baSDavid van Moolenbroek     }
1106*b89261baSDavid van Moolenbroek }
1107*b89261baSDavid van Moolenbroek 
1108*b89261baSDavid van Moolenbroek void
u_procstates(int total,int * brkdn,int threads)1109*b89261baSDavid van Moolenbroek u_procstates(int total, int *brkdn, int threads)
1110*b89261baSDavid van Moolenbroek 
1111*b89261baSDavid van Moolenbroek {
1112*b89261baSDavid van Moolenbroek     /* if threads state has changed, do a full update */
1113*b89261baSDavid van Moolenbroek     if (lthreads != threads)
1114*b89261baSDavid van Moolenbroek     {
1115*b89261baSDavid van Moolenbroek 	i_procstates(total, brkdn, threads);
1116*b89261baSDavid van Moolenbroek 	return;
1117*b89261baSDavid van Moolenbroek     }
1118*b89261baSDavid van Moolenbroek 
1119*b89261baSDavid van Moolenbroek     /* update number of processes only if it has changed */
1120*b89261baSDavid van Moolenbroek     if (ltotal != total)
1121*b89261baSDavid van Moolenbroek     {
1122*b89261baSDavid van Moolenbroek 	display_fmt(0, y_procstate, 0, 0,
1123*b89261baSDavid van Moolenbroek 		    "%d", total);
1124*b89261baSDavid van Moolenbroek 
1125*b89261baSDavid van Moolenbroek 	/* if number of digits differs, rewrite the label */
1126*b89261baSDavid van Moolenbroek 	if (digits(total) != digits(ltotal))
1127*b89261baSDavid van Moolenbroek 	{
1128*b89261baSDavid van Moolenbroek 	    display_fmt(-1, -1, 0, 0, " %s: ", threads ? "threads" : "processes");
1129*b89261baSDavid van Moolenbroek 	    x_procstate = virt_x;
1130*b89261baSDavid van Moolenbroek 	}
1131*b89261baSDavid van Moolenbroek 
1132*b89261baSDavid van Moolenbroek 	/* save new total */
1133*b89261baSDavid van Moolenbroek 	ltotal = total;
1134*b89261baSDavid van Moolenbroek     }
1135*b89261baSDavid van Moolenbroek 
1136*b89261baSDavid van Moolenbroek     /* see if any of the state numbers has changed */
1137*b89261baSDavid van Moolenbroek     if (total > 0 && memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0)
1138*b89261baSDavid van Moolenbroek     {
1139*b89261baSDavid van Moolenbroek 	/* format and update the line */
1140*b89261baSDavid van Moolenbroek 	summary_format(x_procstate, y_procstate, brkdn, procstate_names, NULL);
1141*b89261baSDavid van Moolenbroek 	memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
1142*b89261baSDavid van Moolenbroek     }
1143*b89261baSDavid van Moolenbroek }
1144*b89261baSDavid van Moolenbroek 
1145*b89261baSDavid van Moolenbroek /*
1146*b89261baSDavid van Moolenbroek  *  *_cpustates(states, names) - print the cpu state percentages
1147*b89261baSDavid van Moolenbroek  */
1148*b89261baSDavid van Moolenbroek 
1149*b89261baSDavid van Moolenbroek /* cpustates_tag() calculates the correct tag to use to label the line */
1150*b89261baSDavid van Moolenbroek 
1151*b89261baSDavid van Moolenbroek static char *
cpustates_tag(int c)1152*b89261baSDavid van Moolenbroek cpustates_tag(int c)
1153*b89261baSDavid van Moolenbroek 
1154*b89261baSDavid van Moolenbroek {
1155*b89261baSDavid van Moolenbroek     unsigned width, u;
1156*b89261baSDavid van Moolenbroek 
1157*b89261baSDavid van Moolenbroek     static char fmttag[100];
1158*b89261baSDavid van Moolenbroek 
1159*b89261baSDavid van Moolenbroek     const char *short_tag = !multi || ncpu <= 1 ? "CPU: " : "CPU%0*d: ";
1160*b89261baSDavid van Moolenbroek     const char *long_tag = !multi || ncpu <= 1 ?
1161*b89261baSDavid van Moolenbroek 	"CPU states: " : "CPU%0*d states: ";
1162*b89261baSDavid van Moolenbroek 
1163*b89261baSDavid van Moolenbroek     for (width = 0, u = ncpu - 1; u > 0; u /= 10) {
1164*b89261baSDavid van Moolenbroek 	++width;
1165*b89261baSDavid van Moolenbroek     }
1166*b89261baSDavid van Moolenbroek     /* if length + strlen(long_tag) > screen_width, then we have to
1167*b89261baSDavid van Moolenbroek        use the shorter tag */
1168*b89261baSDavid van Moolenbroek 
1169*b89261baSDavid van Moolenbroek     snprintf(fmttag, sizeof(fmttag), long_tag, width, c);
1170*b89261baSDavid van Moolenbroek 
1171*b89261baSDavid van Moolenbroek     if (cpustate_total_length + (signed)strlen(fmttag)  > screen_width) {
1172*b89261baSDavid van Moolenbroek     	snprintf(fmttag, sizeof(fmttag), short_tag, width, c);
1173*b89261baSDavid van Moolenbroek     }
1174*b89261baSDavid van Moolenbroek 
1175*b89261baSDavid van Moolenbroek     /* set x_cpustates accordingly then return result */
1176*b89261baSDavid van Moolenbroek     x_cpustates = strlen(fmttag);
1177*b89261baSDavid van Moolenbroek     return(fmttag);
1178*b89261baSDavid van Moolenbroek }
1179*b89261baSDavid van Moolenbroek 
1180*b89261baSDavid van Moolenbroek void
i_cpustates(int * states)1181*b89261baSDavid van Moolenbroek i_cpustates(int *states)
1182*b89261baSDavid van Moolenbroek 
1183*b89261baSDavid van Moolenbroek {
1184*b89261baSDavid van Moolenbroek     int value;
1185*b89261baSDavid van Moolenbroek     const char **names;
1186*b89261baSDavid van Moolenbroek     const char *thisname;
1187*b89261baSDavid van Moolenbroek     int *colp;
1188*b89261baSDavid van Moolenbroek     int color = 0;
1189*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
1190*b89261baSDavid van Moolenbroek     int *cidx;
1191*b89261baSDavid van Moolenbroek #endif
1192*b89261baSDavid van Moolenbroek     int c, i;
1193*b89261baSDavid van Moolenbroek 
1194*b89261baSDavid van Moolenbroek     if (multi == 0 && ncpu > 1)
1195*b89261baSDavid van Moolenbroek     {
1196*b89261baSDavid van Moolenbroek 	for (c = 1; c < ncpu; c++)
1197*b89261baSDavid van Moolenbroek 	    for (i = 0; i < num_cpustates; i++)
1198*b89261baSDavid van Moolenbroek 		states[i] += states[c * num_cpustates + i];
1199*b89261baSDavid van Moolenbroek 	for (i = 0; i < num_cpustates; i++)
1200*b89261baSDavid van Moolenbroek 	    states[i] /= ncpu;
1201*b89261baSDavid van Moolenbroek     }
1202*b89261baSDavid van Moolenbroek 
1203*b89261baSDavid van Moolenbroek     for (c = 0; c < (multi ? ncpu : 1); c++)
1204*b89261baSDavid van Moolenbroek     {
1205*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
1206*b89261baSDavid van Moolenbroek     	cidx = cpustate_cidx;
1207*b89261baSDavid van Moolenbroek #endif
1208*b89261baSDavid van Moolenbroek 
1209*b89261baSDavid van Moolenbroek 	/* print tag */
1210*b89261baSDavid van Moolenbroek 	display_write(0, y_cpustates + c, 0, 0, cpustates_tag(c));
1211*b89261baSDavid van Moolenbroek 	colp = cpustate_columns;
1212*b89261baSDavid van Moolenbroek 
1213*b89261baSDavid van Moolenbroek 	/* now walk thru the names and print the line */
1214*b89261baSDavid van Moolenbroek 	for (i = 0, names = cpustate_names; ((thisname = *names++) != NULL);)
1215*b89261baSDavid van Moolenbroek 	{
1216*b89261baSDavid van Moolenbroek 	    if (*thisname != '\0')
1217*b89261baSDavid van Moolenbroek 	    {
1218*b89261baSDavid van Moolenbroek 		/* retrieve the value and remember it */
1219*b89261baSDavid van Moolenbroek 		value = *states;
1220*b89261baSDavid van Moolenbroek 
1221*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
1222*b89261baSDavid van Moolenbroek 		/* determine color number to use */
1223*b89261baSDavid van Moolenbroek 		color = color_test(*cidx++, value/10);
1224*b89261baSDavid van Moolenbroek #endif
1225*b89261baSDavid van Moolenbroek 
1226*b89261baSDavid van Moolenbroek 		/* if percentage is >= 1000, print it as 100% */
1227*b89261baSDavid van Moolenbroek 		display_fmt(x_cpustates + *colp, y_cpustates + c,
1228*b89261baSDavid van Moolenbroek 			    color, 0,
1229*b89261baSDavid van Moolenbroek 			    (value >= 1000 ? "%4.0f%% %s%s" : "%4.1f%% %s%s"),
1230*b89261baSDavid van Moolenbroek 			    ((float)value)/10.,
1231*b89261baSDavid van Moolenbroek 			    thisname,
1232*b89261baSDavid van Moolenbroek 			    *names != NULL ? ", " : "");
1233*b89261baSDavid van Moolenbroek 
1234*b89261baSDavid van Moolenbroek 	    }
1235*b89261baSDavid van Moolenbroek 	    /* increment */
1236*b89261baSDavid van Moolenbroek 	    colp++;
1237*b89261baSDavid van Moolenbroek 	    states++;
1238*b89261baSDavid van Moolenbroek 	}
1239*b89261baSDavid van Moolenbroek     }
1240*b89261baSDavid van Moolenbroek 
1241*b89261baSDavid van Moolenbroek     /* copy over values into "last" array */
1242*b89261baSDavid van Moolenbroek     memcpy(lcpustates, states, num_cpustates * sizeof(int) * ncpu);
1243*b89261baSDavid van Moolenbroek }
1244*b89261baSDavid van Moolenbroek 
1245*b89261baSDavid van Moolenbroek void
u_cpustates(int * states)1246*b89261baSDavid van Moolenbroek u_cpustates(int *states)
1247*b89261baSDavid van Moolenbroek 
1248*b89261baSDavid van Moolenbroek {
1249*b89261baSDavid van Moolenbroek     int value;
1250*b89261baSDavid van Moolenbroek     const char **names;
1251*b89261baSDavid van Moolenbroek     const char *thisname;
1252*b89261baSDavid van Moolenbroek     int *lp;
1253*b89261baSDavid van Moolenbroek     int *colp;
1254*b89261baSDavid van Moolenbroek     int color = 0;
1255*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
1256*b89261baSDavid van Moolenbroek     int *cidx;
1257*b89261baSDavid van Moolenbroek #endif
1258*b89261baSDavid van Moolenbroek     int c, i;
1259*b89261baSDavid van Moolenbroek 
1260*b89261baSDavid van Moolenbroek     lp = lcpustates;
1261*b89261baSDavid van Moolenbroek 
1262*b89261baSDavid van Moolenbroek     if (multi == 0 && ncpu > 1)
1263*b89261baSDavid van Moolenbroek     {
1264*b89261baSDavid van Moolenbroek 	for (c = 1; c < ncpu; c++)
1265*b89261baSDavid van Moolenbroek 	    for (i = 0; i < num_cpustates; i++)
1266*b89261baSDavid van Moolenbroek 		states[i] += states[c * num_cpustates + i];
1267*b89261baSDavid van Moolenbroek 	for (i = 0; i < num_cpustates; i++)
1268*b89261baSDavid van Moolenbroek 	    states[i] /= ncpu;
1269*b89261baSDavid van Moolenbroek     }
1270*b89261baSDavid van Moolenbroek 
1271*b89261baSDavid van Moolenbroek     for (c = 0; c < (multi ? ncpu : 1); c++)
1272*b89261baSDavid van Moolenbroek     {
1273*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
1274*b89261baSDavid van Moolenbroek     	cidx = cpustate_cidx;
1275*b89261baSDavid van Moolenbroek #endif
1276*b89261baSDavid van Moolenbroek 	colp = cpustate_columns;
1277*b89261baSDavid van Moolenbroek 	/* we could be much more optimal about this */
1278*b89261baSDavid van Moolenbroek 	for (names = cpustate_names; (thisname = *names++) != NULL;)
1279*b89261baSDavid van Moolenbroek 	{
1280*b89261baSDavid van Moolenbroek 	    if (*thisname != '\0')
1281*b89261baSDavid van Moolenbroek 	    {
1282*b89261baSDavid van Moolenbroek 		/* did the value change since last time? */
1283*b89261baSDavid van Moolenbroek 		if (*lp != *states)
1284*b89261baSDavid van Moolenbroek 		{
1285*b89261baSDavid van Moolenbroek 		    /* yes, change it */
1286*b89261baSDavid van Moolenbroek 		    /* retrieve value and remember it */
1287*b89261baSDavid van Moolenbroek 		    value = *states;
1288*b89261baSDavid van Moolenbroek 
1289*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
1290*b89261baSDavid van Moolenbroek 		    /* determine color number to use */
1291*b89261baSDavid van Moolenbroek 		    color = color_test(*cidx, value/10);
1292*b89261baSDavid van Moolenbroek #endif
1293*b89261baSDavid van Moolenbroek 
1294*b89261baSDavid van Moolenbroek 		    /* if percentage is >= 1000, print it as 100% */
1295*b89261baSDavid van Moolenbroek 		    display_fmt(x_cpustates + *colp, y_cpustates + c, color, 0,
1296*b89261baSDavid van Moolenbroek 				(value >= 1000 ? "%4.0f" : "%4.1f"),
1297*b89261baSDavid van Moolenbroek 				((double)value)/10.);
1298*b89261baSDavid van Moolenbroek 
1299*b89261baSDavid van Moolenbroek 		    /* remember it for next time */
1300*b89261baSDavid van Moolenbroek 		    *lp = value;
1301*b89261baSDavid van Moolenbroek 		}
1302*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
1303*b89261baSDavid van Moolenbroek 		cidx++;
1304*b89261baSDavid van Moolenbroek #endif
1305*b89261baSDavid van Moolenbroek 	    }
1306*b89261baSDavid van Moolenbroek 
1307*b89261baSDavid van Moolenbroek 	    /* increment and move on */
1308*b89261baSDavid van Moolenbroek 	    lp++;
1309*b89261baSDavid van Moolenbroek 	    states++;
1310*b89261baSDavid van Moolenbroek 	    colp++;
1311*b89261baSDavid van Moolenbroek 	}
1312*b89261baSDavid van Moolenbroek     }
1313*b89261baSDavid van Moolenbroek }
1314*b89261baSDavid van Moolenbroek 
1315*b89261baSDavid van Moolenbroek void
z_cpustates()1316*b89261baSDavid van Moolenbroek z_cpustates()
1317*b89261baSDavid van Moolenbroek 
1318*b89261baSDavid van Moolenbroek {
1319*b89261baSDavid van Moolenbroek     register int i, c;
1320*b89261baSDavid van Moolenbroek     register const char **names = cpustate_names;
1321*b89261baSDavid van Moolenbroek     register const char *thisname;
1322*b89261baSDavid van Moolenbroek     register int *lp;
1323*b89261baSDavid van Moolenbroek 
1324*b89261baSDavid van Moolenbroek     /* print tag */
1325*b89261baSDavid van Moolenbroek     for (c = 0; c < (multi ? ncpu : 1); c++)
1326*b89261baSDavid van Moolenbroek     {
1327*b89261baSDavid van Moolenbroek 	display_write(0, y_cpustates + c, 0, 0, cpustates_tag(c));
1328*b89261baSDavid van Moolenbroek 
1329*b89261baSDavid van Moolenbroek 	for (i = 0, names = cpustate_names; (thisname = *names++) != NULL;)
1330*b89261baSDavid van Moolenbroek 	{
1331*b89261baSDavid van Moolenbroek 	    if (*thisname != '\0')
1332*b89261baSDavid van Moolenbroek 	    {
1333*b89261baSDavid van Moolenbroek 		display_fmt(-1, -1, 0, 0, "%s    %% %s", i++ == 0 ? "" : ", ",
1334*b89261baSDavid van Moolenbroek 			    thisname);
1335*b89261baSDavid van Moolenbroek 	    }
1336*b89261baSDavid van Moolenbroek 	}
1337*b89261baSDavid van Moolenbroek     }
1338*b89261baSDavid van Moolenbroek 
1339*b89261baSDavid van Moolenbroek     /* fill the "last" array with all -1s, to insure correct updating */
1340*b89261baSDavid van Moolenbroek     lp = lcpustates;
1341*b89261baSDavid van Moolenbroek     i = num_cpustates * ncpu;
1342*b89261baSDavid van Moolenbroek     while (--i >= 0)
1343*b89261baSDavid van Moolenbroek     {
1344*b89261baSDavid van Moolenbroek 	*lp++ = -1;
1345*b89261baSDavid van Moolenbroek     }
1346*b89261baSDavid van Moolenbroek }
1347*b89261baSDavid van Moolenbroek 
1348*b89261baSDavid van Moolenbroek /*
1349*b89261baSDavid van Moolenbroek  *  *_kernel(stats) - print "Kernel: " followed by the kernel summary string
1350*b89261baSDavid van Moolenbroek  *
1351*b89261baSDavid van Moolenbroek  *  Assumptions:  cursor is on "lastline", the previous line
1352*b89261baSDavid van Moolenbroek  */
1353*b89261baSDavid van Moolenbroek 
1354*b89261baSDavid van Moolenbroek void
i_kernel(int * stats)1355*b89261baSDavid van Moolenbroek i_kernel(int *stats)
1356*b89261baSDavid van Moolenbroek 
1357*b89261baSDavid van Moolenbroek {
1358*b89261baSDavid van Moolenbroek     if (num_kernel > 0)
1359*b89261baSDavid van Moolenbroek     {
1360*b89261baSDavid van Moolenbroek 	display_write(0, y_kernel, 0, 0, "Kernel: ");
1361*b89261baSDavid van Moolenbroek 
1362*b89261baSDavid van Moolenbroek 	/* format and print the kernel summary */
1363*b89261baSDavid van Moolenbroek 	summary_format(x_kernel, y_kernel, stats, kernel_names, kernel_cidx);
1364*b89261baSDavid van Moolenbroek     }
1365*b89261baSDavid van Moolenbroek }
1366*b89261baSDavid van Moolenbroek 
1367*b89261baSDavid van Moolenbroek void
u_kernel(int * stats)1368*b89261baSDavid van Moolenbroek u_kernel(int *stats)
1369*b89261baSDavid van Moolenbroek 
1370*b89261baSDavid van Moolenbroek {
1371*b89261baSDavid van Moolenbroek     if (num_kernel > 0)
1372*b89261baSDavid van Moolenbroek     {
1373*b89261baSDavid van Moolenbroek 	/* format the new line */
1374*b89261baSDavid van Moolenbroek 	summary_format(x_kernel, y_kernel, stats, kernel_names, kernel_cidx);
1375*b89261baSDavid van Moolenbroek     }
1376*b89261baSDavid van Moolenbroek }
1377*b89261baSDavid van Moolenbroek 
1378*b89261baSDavid van Moolenbroek /*
1379*b89261baSDavid van Moolenbroek  *  *_memory(stats) - print "Memory: " followed by the memory summary string
1380*b89261baSDavid van Moolenbroek  *
1381*b89261baSDavid van Moolenbroek  *  Assumptions:  cursor is on "lastline", the previous line
1382*b89261baSDavid van Moolenbroek  */
1383*b89261baSDavid van Moolenbroek 
1384*b89261baSDavid van Moolenbroek void
i_memory(long * stats)1385*b89261baSDavid van Moolenbroek i_memory(long *stats)
1386*b89261baSDavid van Moolenbroek 
1387*b89261baSDavid van Moolenbroek {
1388*b89261baSDavid van Moolenbroek     display_write(0, y_mem, 0, 0, "Memory: ");
1389*b89261baSDavid van Moolenbroek 
1390*b89261baSDavid van Moolenbroek     /* format and print the memory summary */
1391*b89261baSDavid van Moolenbroek     summary_format_memory(x_mem, y_mem, stats, memory_names, memory_cidx);
1392*b89261baSDavid van Moolenbroek }
1393*b89261baSDavid van Moolenbroek 
1394*b89261baSDavid van Moolenbroek void
u_memory(long * stats)1395*b89261baSDavid van Moolenbroek u_memory(long *stats)
1396*b89261baSDavid van Moolenbroek 
1397*b89261baSDavid van Moolenbroek {
1398*b89261baSDavid van Moolenbroek     /* format the new line */
1399*b89261baSDavid van Moolenbroek     summary_format_memory(x_mem, y_mem, stats, memory_names, memory_cidx);
1400*b89261baSDavid van Moolenbroek }
1401*b89261baSDavid van Moolenbroek 
1402*b89261baSDavid van Moolenbroek /*
1403*b89261baSDavid van Moolenbroek  *  *_swap(stats) - print "Swap: " followed by the swap summary string
1404*b89261baSDavid van Moolenbroek  *
1405*b89261baSDavid van Moolenbroek  *  Assumptions:  cursor is on "lastline", the previous line
1406*b89261baSDavid van Moolenbroek  *
1407*b89261baSDavid van Moolenbroek  *  These functions only print something when num_swap > 0
1408*b89261baSDavid van Moolenbroek  */
1409*b89261baSDavid van Moolenbroek 
1410*b89261baSDavid van Moolenbroek void
i_swap(long * stats)1411*b89261baSDavid van Moolenbroek i_swap(long *stats)
1412*b89261baSDavid van Moolenbroek 
1413*b89261baSDavid van Moolenbroek {
1414*b89261baSDavid van Moolenbroek     if (num_swap > 0)
1415*b89261baSDavid van Moolenbroek     {
1416*b89261baSDavid van Moolenbroek 	/* print the tag */
1417*b89261baSDavid van Moolenbroek 	display_write(0, y_swap, 0, 0, "Swap: ");
1418*b89261baSDavid van Moolenbroek 
1419*b89261baSDavid van Moolenbroek 	/* format and print the swap summary */
1420*b89261baSDavid van Moolenbroek 	summary_format_memory(x_swap, y_swap, stats, swap_names, swap_cidx);
1421*b89261baSDavid van Moolenbroek     }
1422*b89261baSDavid van Moolenbroek }
1423*b89261baSDavid van Moolenbroek 
1424*b89261baSDavid van Moolenbroek void
u_swap(long * stats)1425*b89261baSDavid van Moolenbroek u_swap(long *stats)
1426*b89261baSDavid van Moolenbroek 
1427*b89261baSDavid van Moolenbroek {
1428*b89261baSDavid van Moolenbroek     if (num_swap > 0)
1429*b89261baSDavid van Moolenbroek     {
1430*b89261baSDavid van Moolenbroek 	/* format the new line */
1431*b89261baSDavid van Moolenbroek 	summary_format_memory(x_swap, y_swap, stats, swap_names, swap_cidx);
1432*b89261baSDavid van Moolenbroek     }
1433*b89261baSDavid van Moolenbroek }
1434*b89261baSDavid van Moolenbroek 
1435*b89261baSDavid van Moolenbroek /*
1436*b89261baSDavid van Moolenbroek  *  *_message() - print the next pending message line, or erase the one
1437*b89261baSDavid van Moolenbroek  *                that is there.
1438*b89261baSDavid van Moolenbroek  *
1439*b89261baSDavid van Moolenbroek  *  Note that u_message is (currently) the same as i_message.
1440*b89261baSDavid van Moolenbroek  *
1441*b89261baSDavid van Moolenbroek  *  Assumptions:  lastline is consistent
1442*b89261baSDavid van Moolenbroek  */
1443*b89261baSDavid van Moolenbroek 
1444*b89261baSDavid van Moolenbroek /*
1445*b89261baSDavid van Moolenbroek  *  i_message is funny because it gets its message asynchronously (with
1446*b89261baSDavid van Moolenbroek  *	respect to screen updates).  Messages are taken out of the
1447*b89261baSDavid van Moolenbroek  *      circular message_buf and displayed one at a time.
1448*b89261baSDavid van Moolenbroek  */
1449*b89261baSDavid van Moolenbroek 
1450*b89261baSDavid van Moolenbroek void
i_message(struct timeval * now)1451*b89261baSDavid van Moolenbroek i_message(struct timeval *now)
1452*b89261baSDavid van Moolenbroek 
1453*b89261baSDavid van Moolenbroek {
1454*b89261baSDavid van Moolenbroek     struct timeval my_now;
1455*b89261baSDavid van Moolenbroek     int i = 0;
1456*b89261baSDavid van Moolenbroek 
1457*b89261baSDavid van Moolenbroek     dprintf("i_message(%08x)\n", now);
1458*b89261baSDavid van Moolenbroek 
1459*b89261baSDavid van Moolenbroek     /* if now is NULL we have to get it ourselves */
1460*b89261baSDavid van Moolenbroek     if (now == NULL)
1461*b89261baSDavid van Moolenbroek     {
1462*b89261baSDavid van Moolenbroek 	time_get(&my_now);
1463*b89261baSDavid van Moolenbroek 	now = &my_now;
1464*b89261baSDavid van Moolenbroek     }
1465*b89261baSDavid van Moolenbroek 
1466*b89261baSDavid van Moolenbroek     /* now that we have been called, messages no longer need to be held */
1467*b89261baSDavid van Moolenbroek     message_hold = 0;
1468*b89261baSDavid van Moolenbroek 
1469*b89261baSDavid van Moolenbroek     dprintf("i_message: now %d, message_time %d\n",
1470*b89261baSDavid van Moolenbroek 	    now->tv_sec, message_time.tv_sec);
1471*b89261baSDavid van Moolenbroek 
1472*b89261baSDavid van Moolenbroek     if (smart_terminal)
1473*b89261baSDavid van Moolenbroek     {
1474*b89261baSDavid van Moolenbroek 	/* is it time to change the message? */
1475*b89261baSDavid van Moolenbroek 	if (timercmp(now, &message_time, > ))
1476*b89261baSDavid van Moolenbroek 	{
1477*b89261baSDavid van Moolenbroek 	    /* yes, free the current message */
1478*b89261baSDavid van Moolenbroek 	    dprintf("i_message: timer expired\n");
1479*b89261baSDavid van Moolenbroek 	    if (message_current != NULL)
1480*b89261baSDavid van Moolenbroek 	    {
1481*b89261baSDavid van Moolenbroek 		free(message_current);
1482*b89261baSDavid van Moolenbroek 		message_current = NULL;
1483*b89261baSDavid van Moolenbroek 	    }
1484*b89261baSDavid van Moolenbroek 
1485*b89261baSDavid van Moolenbroek 	    /* is there a new message to be displayed? */
1486*b89261baSDavid van Moolenbroek 	    if (message_first != message_last)
1487*b89261baSDavid van Moolenbroek 	    {
1488*b89261baSDavid van Moolenbroek 		/* move index to next message */
1489*b89261baSDavid van Moolenbroek 		if (++message_first == MAX_MESSAGES) message_first = 0;
1490*b89261baSDavid van Moolenbroek 
1491*b89261baSDavid van Moolenbroek 		/* make the next message the current one */
1492*b89261baSDavid van Moolenbroek 		message_current = message_buf[message_first];
1493*b89261baSDavid van Moolenbroek 
1494*b89261baSDavid van Moolenbroek 		/* show it */
1495*b89261baSDavid van Moolenbroek 		dprintf("i_message: showing \"%s\"\n", message_current);
1496*b89261baSDavid van Moolenbroek 		display_move(0, y_message);
1497*b89261baSDavid van Moolenbroek 		screen_standout(message_current);
1498*b89261baSDavid van Moolenbroek 		i = strlen(message_current);
1499*b89261baSDavid van Moolenbroek 
1500*b89261baSDavid van Moolenbroek 		/* set the expiration timer */
1501*b89261baSDavid van Moolenbroek 		message_time = *now;
1502*b89261baSDavid van Moolenbroek 		message_time.tv_sec += MESSAGE_DISPLAY_TIME;
1503*b89261baSDavid van Moolenbroek 
1504*b89261baSDavid van Moolenbroek 		/* clear the rest of the line */
1505*b89261baSDavid van Moolenbroek 		screen_cleareol(message_length - i);
1506*b89261baSDavid van Moolenbroek 		putchar('\r');
1507*b89261baSDavid van Moolenbroek 		message_length = i;
1508*b89261baSDavid van Moolenbroek 	    }
1509*b89261baSDavid van Moolenbroek 	    else
1510*b89261baSDavid van Moolenbroek 	    {
1511*b89261baSDavid van Moolenbroek 		/* just clear what was there before, if anything */
1512*b89261baSDavid van Moolenbroek 		if (message_length > 0)
1513*b89261baSDavid van Moolenbroek 		{
1514*b89261baSDavid van Moolenbroek 		    display_move(0, y_message);
1515*b89261baSDavid van Moolenbroek 		    screen_cleareol(message_length);
1516*b89261baSDavid van Moolenbroek 		    putchar('\r');
1517*b89261baSDavid van Moolenbroek 		    message_length = 0;
1518*b89261baSDavid van Moolenbroek 		}
1519*b89261baSDavid van Moolenbroek 	    }
1520*b89261baSDavid van Moolenbroek 	}
1521*b89261baSDavid van Moolenbroek     }
1522*b89261baSDavid van Moolenbroek }
1523*b89261baSDavid van Moolenbroek 
1524*b89261baSDavid van Moolenbroek void
u_message(struct timeval * now)1525*b89261baSDavid van Moolenbroek u_message(struct timeval *now)
1526*b89261baSDavid van Moolenbroek 
1527*b89261baSDavid van Moolenbroek {
1528*b89261baSDavid van Moolenbroek     i_message(now);
1529*b89261baSDavid van Moolenbroek }
1530*b89261baSDavid van Moolenbroek 
1531*b89261baSDavid van Moolenbroek static int header_length;
1532*b89261baSDavid van Moolenbroek 
1533*b89261baSDavid van Moolenbroek /*
1534*b89261baSDavid van Moolenbroek  *  *_header(text) - print the header for the process area
1535*b89261baSDavid van Moolenbroek  *
1536*b89261baSDavid van Moolenbroek  *  Assumptions:  cursor is on the previous line and lastline is consistent
1537*b89261baSDavid van Moolenbroek  */
1538*b89261baSDavid van Moolenbroek 
1539*b89261baSDavid van Moolenbroek void
i_header(char * text)1540*b89261baSDavid van Moolenbroek i_header(char *text)
1541*b89261baSDavid van Moolenbroek 
1542*b89261baSDavid van Moolenbroek {
1543*b89261baSDavid van Moolenbroek     int header_color = 0;
1544*b89261baSDavid van Moolenbroek 
1545*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
1546*b89261baSDavid van Moolenbroek     header_color = color_test(header_cidx, 0);
1547*b89261baSDavid van Moolenbroek #endif
1548*b89261baSDavid van Moolenbroek     header_length = strlen(text);
1549*b89261baSDavid van Moolenbroek     if (header_status)
1550*b89261baSDavid van Moolenbroek     {
1551*b89261baSDavid van Moolenbroek 	display_write(x_header, y_header, header_color, 1, text);
1552*b89261baSDavid van Moolenbroek     }
1553*b89261baSDavid van Moolenbroek }
1554*b89261baSDavid van Moolenbroek 
1555*b89261baSDavid van Moolenbroek /*ARGSUSED*/
1556*b89261baSDavid van Moolenbroek void
u_header(char * text)1557*b89261baSDavid van Moolenbroek u_header(char *text)
1558*b89261baSDavid van Moolenbroek 
1559*b89261baSDavid van Moolenbroek {
1560*b89261baSDavid van Moolenbroek     int header_color = 0;
1561*b89261baSDavid van Moolenbroek 
1562*b89261baSDavid van Moolenbroek #ifdef ENABLE_COLOR
1563*b89261baSDavid van Moolenbroek     header_color = color_test(header_cidx, 0);
1564*b89261baSDavid van Moolenbroek #endif
1565*b89261baSDavid van Moolenbroek     display_write(x_header, y_header, header_color, 1,
1566*b89261baSDavid van Moolenbroek 		  header_status ? text : "");
1567*b89261baSDavid van Moolenbroek }
1568*b89261baSDavid van Moolenbroek 
1569*b89261baSDavid van Moolenbroek /*
1570*b89261baSDavid van Moolenbroek  *  *_process(line, thisline) - print one process line
1571*b89261baSDavid van Moolenbroek  *
1572*b89261baSDavid van Moolenbroek  *  Assumptions:  lastline is consistent
1573*b89261baSDavid van Moolenbroek  */
1574*b89261baSDavid van Moolenbroek 
1575*b89261baSDavid van Moolenbroek void
i_process(int line,char * thisline)1576*b89261baSDavid van Moolenbroek i_process(int line, char *thisline)
1577*b89261baSDavid van Moolenbroek 
1578*b89261baSDavid van Moolenbroek {
1579*b89261baSDavid van Moolenbroek     /* truncate the line to conform to our current screen width */
1580*b89261baSDavid van Moolenbroek     thisline[display_width] = '\0';
1581*b89261baSDavid van Moolenbroek 
1582*b89261baSDavid van Moolenbroek     /* write the line out */
1583*b89261baSDavid van Moolenbroek     display_write(0, y_procs + line, 0, 1, thisline);
1584*b89261baSDavid van Moolenbroek }
1585*b89261baSDavid van Moolenbroek 
1586*b89261baSDavid van Moolenbroek void
u_process(int line,char * new_line)1587*b89261baSDavid van Moolenbroek u_process(int line, char *new_line)
1588*b89261baSDavid van Moolenbroek 
1589*b89261baSDavid van Moolenbroek {
1590*b89261baSDavid van Moolenbroek     i_process(line, new_line);
1591*b89261baSDavid van Moolenbroek }
1592*b89261baSDavid van Moolenbroek 
1593*b89261baSDavid van Moolenbroek void
i_endscreen()1594*b89261baSDavid van Moolenbroek i_endscreen()
1595*b89261baSDavid van Moolenbroek 
1596*b89261baSDavid van Moolenbroek {
1597*b89261baSDavid van Moolenbroek     if (smart_terminal)
1598*b89261baSDavid van Moolenbroek     {
1599*b89261baSDavid van Moolenbroek 	/* move the cursor to a pleasant place */
1600*b89261baSDavid van Moolenbroek 	display_move(x_idlecursor, y_idlecursor);
1601*b89261baSDavid van Moolenbroek     }
1602*b89261baSDavid van Moolenbroek     else
1603*b89261baSDavid van Moolenbroek     {
1604*b89261baSDavid van Moolenbroek 	/* separate this display from the next with some vertical room */
1605*b89261baSDavid van Moolenbroek 	fputs("\n\n", stdout);
1606*b89261baSDavid van Moolenbroek     }
1607*b89261baSDavid van Moolenbroek     fflush(stdout);
1608*b89261baSDavid van Moolenbroek }
1609*b89261baSDavid van Moolenbroek 
1610*b89261baSDavid van Moolenbroek void
u_endscreen()1611*b89261baSDavid van Moolenbroek u_endscreen()
1612*b89261baSDavid van Moolenbroek 
1613*b89261baSDavid van Moolenbroek {
1614*b89261baSDavid van Moolenbroek     if (smart_terminal)
1615*b89261baSDavid van Moolenbroek     {
1616*b89261baSDavid van Moolenbroek 	/* clear-to-end the display */
1617*b89261baSDavid van Moolenbroek 	display_cte();
1618*b89261baSDavid van Moolenbroek 
1619*b89261baSDavid van Moolenbroek 	/* move the cursor to a pleasant place */
1620*b89261baSDavid van Moolenbroek 	display_move(x_idlecursor, y_idlecursor);
1621*b89261baSDavid van Moolenbroek 	fflush(stdout);
1622*b89261baSDavid van Moolenbroek     }
1623*b89261baSDavid van Moolenbroek     else
1624*b89261baSDavid van Moolenbroek     {
1625*b89261baSDavid van Moolenbroek 	/* separate this display from the next with some vertical room */
1626*b89261baSDavid van Moolenbroek 	fputs("\n\n", stdout);
1627*b89261baSDavid van Moolenbroek     }
1628*b89261baSDavid van Moolenbroek }
1629*b89261baSDavid van Moolenbroek 
1630*b89261baSDavid van Moolenbroek void
display_header(int t)1631*b89261baSDavid van Moolenbroek display_header(int t)
1632*b89261baSDavid van Moolenbroek 
1633*b89261baSDavid van Moolenbroek {
1634*b89261baSDavid van Moolenbroek     header_status = t != 0;
1635*b89261baSDavid van Moolenbroek }
1636*b89261baSDavid van Moolenbroek 
1637*b89261baSDavid van Moolenbroek void
message_mark(void)1638*b89261baSDavid van Moolenbroek message_mark(void)
1639*b89261baSDavid van Moolenbroek 
1640*b89261baSDavid van Moolenbroek {
1641*b89261baSDavid van Moolenbroek     message_barrier = Yes;
1642*b89261baSDavid van Moolenbroek }
1643*b89261baSDavid van Moolenbroek 
1644*b89261baSDavid van Moolenbroek void
message_expire(void)1645*b89261baSDavid van Moolenbroek message_expire(void)
1646*b89261baSDavid van Moolenbroek 
1647*b89261baSDavid van Moolenbroek {
1648*b89261baSDavid van Moolenbroek     message_time.tv_sec = 0;
1649*b89261baSDavid van Moolenbroek     message_time.tv_usec = 0;
1650*b89261baSDavid van Moolenbroek }
1651*b89261baSDavid van Moolenbroek 
1652*b89261baSDavid van Moolenbroek static void
message_flush(void)1653*b89261baSDavid van Moolenbroek message_flush(void)
1654*b89261baSDavid van Moolenbroek 
1655*b89261baSDavid van Moolenbroek {
1656*b89261baSDavid van Moolenbroek     message_first = message_last;
1657*b89261baSDavid van Moolenbroek     message_time.tv_sec = 0;
1658*b89261baSDavid van Moolenbroek     message_time.tv_usec = 0;
1659*b89261baSDavid van Moolenbroek }
1660*b89261baSDavid van Moolenbroek 
1661*b89261baSDavid van Moolenbroek /*
1662*b89261baSDavid van Moolenbroek  * void new_message_v(char *msgfmt, va_list ap)
1663*b89261baSDavid van Moolenbroek  *
1664*b89261baSDavid van Moolenbroek  * Display a message in the message area.  This function takes a va_list for
1665*b89261baSDavid van Moolenbroek  * the arguments.  Safe to call before display_init.  This function only
1666*b89261baSDavid van Moolenbroek  * queues a message for display, and allowed for multiple messages to be
1667*b89261baSDavid van Moolenbroek  * queued.  The i_message function drains the queue and actually writes the
1668*b89261baSDavid van Moolenbroek  * messages on the display.
1669*b89261baSDavid van Moolenbroek  */
1670*b89261baSDavid van Moolenbroek 
1671*b89261baSDavid van Moolenbroek 
1672*b89261baSDavid van Moolenbroek static void
new_message_v(const char * msgfmt,va_list ap)1673*b89261baSDavid van Moolenbroek new_message_v(const char *msgfmt, va_list ap)
1674*b89261baSDavid van Moolenbroek 
1675*b89261baSDavid van Moolenbroek {
1676*b89261baSDavid van Moolenbroek     int i;
1677*b89261baSDavid van Moolenbroek     int empty;
1678*b89261baSDavid van Moolenbroek     char msg[MAX_COLS];
1679*b89261baSDavid van Moolenbroek 
1680*b89261baSDavid van Moolenbroek     /* if message_barrier is active, remove all pending messages */
1681*b89261baSDavid van Moolenbroek     if (message_barrier)
1682*b89261baSDavid van Moolenbroek     {
1683*b89261baSDavid van Moolenbroek 	message_flush();
1684*b89261baSDavid van Moolenbroek 	message_barrier = No;
1685*b89261baSDavid van Moolenbroek     }
1686*b89261baSDavid van Moolenbroek 
1687*b89261baSDavid van Moolenbroek     /* first, format the message */
1688*b89261baSDavid van Moolenbroek     (void) vsnprintf(msg, sizeof(msg), msgfmt, ap);
1689*b89261baSDavid van Moolenbroek 
1690*b89261baSDavid van Moolenbroek     /* where in the buffer will it go? */
1691*b89261baSDavid van Moolenbroek     i = message_last + 1;
1692*b89261baSDavid van Moolenbroek     if (i >= MAX_MESSAGES) i = 0;
1693*b89261baSDavid van Moolenbroek 
1694*b89261baSDavid van Moolenbroek     /* make sure the buffer is not full */
1695*b89261baSDavid van Moolenbroek     if (i != message_first)
1696*b89261baSDavid van Moolenbroek     {
1697*b89261baSDavid van Moolenbroek 	/* insert it in to message_buf */
1698*b89261baSDavid van Moolenbroek 	message_buf[i] = estrdup(msg);
1699*b89261baSDavid van Moolenbroek 	dprintf("new_message_v: new message inserted in slot %d\n", i);
1700*b89261baSDavid van Moolenbroek 
1701*b89261baSDavid van Moolenbroek 	/* remember if the buffer is empty and set the index */
1702*b89261baSDavid van Moolenbroek 	empty = message_last == message_first;
1703*b89261baSDavid van Moolenbroek 	message_last = i;
1704*b89261baSDavid van Moolenbroek 
1705*b89261baSDavid van Moolenbroek 	/* is message_buf otherwise empty and have we started displaying? */
1706*b89261baSDavid van Moolenbroek 	if (empty && !message_hold)
1707*b89261baSDavid van Moolenbroek 	{
1708*b89261baSDavid van Moolenbroek 	    /* we can display the message now */
1709*b89261baSDavid van Moolenbroek 	    i_message(NULL);
1710*b89261baSDavid van Moolenbroek 	}
1711*b89261baSDavid van Moolenbroek     }
1712*b89261baSDavid van Moolenbroek }
1713*b89261baSDavid van Moolenbroek 
1714*b89261baSDavid van Moolenbroek /*
1715*b89261baSDavid van Moolenbroek  * void new_message(int type, char *msgfmt, ...)
1716*b89261baSDavid van Moolenbroek  *
1717*b89261baSDavid van Moolenbroek  * Display a message in the message area.  It is safe to call this function
1718*b89261baSDavid van Moolenbroek  * before display_init.  Messages logged before the display is drawn will be
1719*b89261baSDavid van Moolenbroek  * held and displayed later.
1720*b89261baSDavid van Moolenbroek  */
1721*b89261baSDavid van Moolenbroek 
1722*b89261baSDavid van Moolenbroek void
new_message(const char * msgfmt,...)1723*b89261baSDavid van Moolenbroek new_message(const char *msgfmt, ...)
1724*b89261baSDavid van Moolenbroek 
1725*b89261baSDavid van Moolenbroek {
1726*b89261baSDavid van Moolenbroek     va_list ap;
1727*b89261baSDavid van Moolenbroek 
1728*b89261baSDavid van Moolenbroek     va_start(ap, msgfmt);
1729*b89261baSDavid van Moolenbroek     new_message_v(msgfmt, ap);
1730*b89261baSDavid van Moolenbroek     va_end(ap);
1731*b89261baSDavid van Moolenbroek }
1732*b89261baSDavid van Moolenbroek 
1733*b89261baSDavid van Moolenbroek /*
1734*b89261baSDavid van Moolenbroek  * void message_error(char *msgfmt, ...)
1735*b89261baSDavid van Moolenbroek  *
1736*b89261baSDavid van Moolenbroek  * Put an error message in the message area.  It is safe to call this function
1737*b89261baSDavid van Moolenbroek  * before display_init.  Messages logged before the display is drawn will be
1738*b89261baSDavid van Moolenbroek  * held and displayed later.
1739*b89261baSDavid van Moolenbroek  */
1740*b89261baSDavid van Moolenbroek 
1741*b89261baSDavid van Moolenbroek void
message_error(const char * msgfmt,...)1742*b89261baSDavid van Moolenbroek message_error(const char *msgfmt, ...)
1743*b89261baSDavid van Moolenbroek 
1744*b89261baSDavid van Moolenbroek {
1745*b89261baSDavid van Moolenbroek     va_list ap;
1746*b89261baSDavid van Moolenbroek 
1747*b89261baSDavid van Moolenbroek     va_start(ap, msgfmt);
1748*b89261baSDavid van Moolenbroek     new_message_v(msgfmt, ap);
1749*b89261baSDavid van Moolenbroek     fflush(stdout);
1750*b89261baSDavid van Moolenbroek     va_end(ap);
1751*b89261baSDavid van Moolenbroek }
1752*b89261baSDavid van Moolenbroek 
1753*b89261baSDavid van Moolenbroek /*
1754*b89261baSDavid van Moolenbroek  * void message_clear()
1755*b89261baSDavid van Moolenbroek  *
1756*b89261baSDavid van Moolenbroek  * Clear message area and flush all pending messages.
1757*b89261baSDavid van Moolenbroek  */
1758*b89261baSDavid van Moolenbroek 
1759*b89261baSDavid van Moolenbroek void
message_clear()1760*b89261baSDavid van Moolenbroek message_clear()
1761*b89261baSDavid van Moolenbroek 
1762*b89261baSDavid van Moolenbroek {
1763*b89261baSDavid van Moolenbroek     /* remove any existing message */
1764*b89261baSDavid van Moolenbroek     if (message_current != NULL)
1765*b89261baSDavid van Moolenbroek     {
1766*b89261baSDavid van Moolenbroek 	display_move(0, y_message);
1767*b89261baSDavid van Moolenbroek 	screen_cleareol(message_length);
1768*b89261baSDavid van Moolenbroek 	free(message_current);
1769*b89261baSDavid van Moolenbroek 	message_current = 0;
1770*b89261baSDavid van Moolenbroek     }
1771*b89261baSDavid van Moolenbroek 
1772*b89261baSDavid van Moolenbroek     /* flush all pending messages */
1773*b89261baSDavid van Moolenbroek     message_flush();
1774*b89261baSDavid van Moolenbroek }
1775*b89261baSDavid van Moolenbroek 
1776*b89261baSDavid van Moolenbroek /*
1777*b89261baSDavid van Moolenbroek  * void message_prompt_v(int so, char *msgfmt, va_list ap)
1778*b89261baSDavid van Moolenbroek  *
1779*b89261baSDavid van Moolenbroek  * Place a prompt in the message area.  A prompt is different from a
1780*b89261baSDavid van Moolenbroek  * message as follows: it is displayed immediately, overwriting any
1781*b89261baSDavid van Moolenbroek  * message that may already be there, it may be highlighted in standout
1782*b89261baSDavid van Moolenbroek  * mode (if "so" is true), the cursor is left to rest at the end of the
1783*b89261baSDavid van Moolenbroek  * prompt.  This call causes all pending messages to be flushed.
1784*b89261baSDavid van Moolenbroek  */
1785*b89261baSDavid van Moolenbroek 
1786*b89261baSDavid van Moolenbroek static void
message_prompt_v(int so,const char * msgfmt,va_list ap)1787*b89261baSDavid van Moolenbroek message_prompt_v(int so, const char *msgfmt, va_list ap)
1788*b89261baSDavid van Moolenbroek 
1789*b89261baSDavid van Moolenbroek {
1790*b89261baSDavid van Moolenbroek     char msg[MAX_COLS];
1791*b89261baSDavid van Moolenbroek     int i;
1792*b89261baSDavid van Moolenbroek 
1793*b89261baSDavid van Moolenbroek     /* clear out the message buffer */
1794*b89261baSDavid van Moolenbroek     message_flush();
1795*b89261baSDavid van Moolenbroek 
1796*b89261baSDavid van Moolenbroek     /* format the message */
1797*b89261baSDavid van Moolenbroek     i = vsnprintf(msg, sizeof(msg), msgfmt, ap);
1798*b89261baSDavid van Moolenbroek 
1799*b89261baSDavid van Moolenbroek     /* this goes over any existing message */
1800*b89261baSDavid van Moolenbroek     display_move(0, y_message);
1801*b89261baSDavid van Moolenbroek 
1802*b89261baSDavid van Moolenbroek     /* clear the entire line */
1803*b89261baSDavid van Moolenbroek     screen_cleareol(message_length);
1804*b89261baSDavid van Moolenbroek 
1805*b89261baSDavid van Moolenbroek     /* show the prompt */
1806*b89261baSDavid van Moolenbroek     if (so)
1807*b89261baSDavid van Moolenbroek     {
1808*b89261baSDavid van Moolenbroek 	screen_standout(msg);
1809*b89261baSDavid van Moolenbroek     }
1810*b89261baSDavid van Moolenbroek     else
1811*b89261baSDavid van Moolenbroek     {
1812*b89261baSDavid van Moolenbroek 	fputs(msg, stdout);
1813*b89261baSDavid van Moolenbroek     }
1814*b89261baSDavid van Moolenbroek 
1815*b89261baSDavid van Moolenbroek     /* make it all visible */
1816*b89261baSDavid van Moolenbroek     fflush(stdout);
1817*b89261baSDavid van Moolenbroek 
1818*b89261baSDavid van Moolenbroek     /* even though we dont keep a copy of the prompt, track its length */
1819*b89261baSDavid van Moolenbroek     message_length = i < MAX_COLS ? i : MAX_COLS;
1820*b89261baSDavid van Moolenbroek }
1821*b89261baSDavid van Moolenbroek 
1822*b89261baSDavid van Moolenbroek /*
1823*b89261baSDavid van Moolenbroek  * void message_prompt(char *msgfmt, ...)
1824*b89261baSDavid van Moolenbroek  *
1825*b89261baSDavid van Moolenbroek  * Place a prompt in the message area (see message_prompt_v).
1826*b89261baSDavid van Moolenbroek  */
1827*b89261baSDavid van Moolenbroek 
1828*b89261baSDavid van Moolenbroek void
message_prompt(const char * msgfmt,...)1829*b89261baSDavid van Moolenbroek message_prompt(const char *msgfmt, ...)
1830*b89261baSDavid van Moolenbroek 
1831*b89261baSDavid van Moolenbroek {
1832*b89261baSDavid van Moolenbroek     va_list ap;
1833*b89261baSDavid van Moolenbroek 
1834*b89261baSDavid van Moolenbroek     va_start(ap, msgfmt);
1835*b89261baSDavid van Moolenbroek     message_prompt_v(Yes, msgfmt, ap);
1836*b89261baSDavid van Moolenbroek     va_end(ap);
1837*b89261baSDavid van Moolenbroek }
1838*b89261baSDavid van Moolenbroek 
1839*b89261baSDavid van Moolenbroek void
message_prompt_plain(const char * msgfmt,...)1840*b89261baSDavid van Moolenbroek message_prompt_plain(const char *msgfmt, ...)
1841*b89261baSDavid van Moolenbroek 
1842*b89261baSDavid van Moolenbroek {
1843*b89261baSDavid van Moolenbroek     va_list ap;
1844*b89261baSDavid van Moolenbroek 
1845*b89261baSDavid van Moolenbroek     va_start(ap, msgfmt);
1846*b89261baSDavid van Moolenbroek     message_prompt_v(No, msgfmt, ap);
1847*b89261baSDavid van Moolenbroek     va_end(ap);
1848*b89261baSDavid van Moolenbroek }
1849*b89261baSDavid van Moolenbroek 
1850*b89261baSDavid van Moolenbroek /*
1851*b89261baSDavid van Moolenbroek  * int readline(char *buffer, int size, int numeric)
1852*b89261baSDavid van Moolenbroek  *
1853*b89261baSDavid van Moolenbroek  * Read a line of input from the terminal.  The line is placed in
1854*b89261baSDavid van Moolenbroek  * "buffer" not to exceed "size".  If "numeric" is true then the input
1855*b89261baSDavid van Moolenbroek  * can only consist of digits.  This routine handles all character
1856*b89261baSDavid van Moolenbroek  * editing while keeping the terminal in cbreak mode.  If "numeric"
1857*b89261baSDavid van Moolenbroek  * is true then the number entered is returned.  Otherwise the number
1858*b89261baSDavid van Moolenbroek  * of character read in to "buffer" is returned.
1859*b89261baSDavid van Moolenbroek  */
1860*b89261baSDavid van Moolenbroek 
1861*b89261baSDavid van Moolenbroek int
readline(char * buffer,int size,int numeric)1862*b89261baSDavid van Moolenbroek readline(char *buffer, int size, int numeric)
1863*b89261baSDavid van Moolenbroek 
1864*b89261baSDavid van Moolenbroek {
1865*b89261baSDavid van Moolenbroek     register char *ptr = buffer;
1866*b89261baSDavid van Moolenbroek     register char ch;
1867*b89261baSDavid van Moolenbroek     register char cnt = 0;
1868*b89261baSDavid van Moolenbroek 
1869*b89261baSDavid van Moolenbroek     /* allow room for null terminator */
1870*b89261baSDavid van Moolenbroek     size -= 1;
1871*b89261baSDavid van Moolenbroek 
1872*b89261baSDavid van Moolenbroek     /* read loop */
1873*b89261baSDavid van Moolenbroek     while ((fflush(stdout), read(0, ptr, 1) > 0))
1874*b89261baSDavid van Moolenbroek     {
1875*b89261baSDavid van Moolenbroek 	/* newline or return means we are done */
1876*b89261baSDavid van Moolenbroek 	if ((ch = *ptr) == '\n' || ch == '\r')
1877*b89261baSDavid van Moolenbroek 	{
1878*b89261baSDavid van Moolenbroek 	    break;
1879*b89261baSDavid van Moolenbroek 	}
1880*b89261baSDavid van Moolenbroek 
1881*b89261baSDavid van Moolenbroek 	/* handle special editing characters */
1882*b89261baSDavid van Moolenbroek 	if (ch == ch_kill)
1883*b89261baSDavid van Moolenbroek 	{
1884*b89261baSDavid van Moolenbroek 	    /* return null string */
1885*b89261baSDavid van Moolenbroek 	    *buffer = '\0';
1886*b89261baSDavid van Moolenbroek 	    putchar('\r');
1887*b89261baSDavid van Moolenbroek 	    return(-1);
1888*b89261baSDavid van Moolenbroek 	}
1889*b89261baSDavid van Moolenbroek 	else if (ch == ch_werase)
1890*b89261baSDavid van Moolenbroek 	{
1891*b89261baSDavid van Moolenbroek 	    /* erase previous word */
1892*b89261baSDavid van Moolenbroek 	    if (cnt <= 0)
1893*b89261baSDavid van Moolenbroek 	    {
1894*b89261baSDavid van Moolenbroek 		/* none to erase! */
1895*b89261baSDavid van Moolenbroek 		putchar('\7');
1896*b89261baSDavid van Moolenbroek 	    }
1897*b89261baSDavid van Moolenbroek 	    else
1898*b89261baSDavid van Moolenbroek 	    {
1899*b89261baSDavid van Moolenbroek 		/*
1900*b89261baSDavid van Moolenbroek 		 * First: remove all spaces till the first-non-space
1901*b89261baSDavid van Moolenbroek 		 * Second: remove all non-spaces till the first-space
1902*b89261baSDavid van Moolenbroek 		 */
1903*b89261baSDavid van Moolenbroek 		while(cnt > 0 && ptr[-1] == ' ')
1904*b89261baSDavid van Moolenbroek 		{
1905*b89261baSDavid van Moolenbroek 		    fputs("\b \b", stdout);
1906*b89261baSDavid van Moolenbroek 		    ptr--;
1907*b89261baSDavid van Moolenbroek 		    cnt--;
1908*b89261baSDavid van Moolenbroek 		}
1909*b89261baSDavid van Moolenbroek 		while(cnt > 0 && ptr[-1] != ' ')
1910*b89261baSDavid van Moolenbroek 		{
1911*b89261baSDavid van Moolenbroek 		    fputs("\b \b", stdout);
1912*b89261baSDavid van Moolenbroek 		    ptr--;
1913*b89261baSDavid van Moolenbroek 		    cnt--;
1914*b89261baSDavid van Moolenbroek 		}
1915*b89261baSDavid van Moolenbroek 	    }
1916*b89261baSDavid van Moolenbroek 	}
1917*b89261baSDavid van Moolenbroek 	else if (ch == ch_erase)
1918*b89261baSDavid van Moolenbroek 	{
1919*b89261baSDavid van Moolenbroek 	    /* erase previous character */
1920*b89261baSDavid van Moolenbroek 	    if (cnt <= 0)
1921*b89261baSDavid van Moolenbroek 	    {
1922*b89261baSDavid van Moolenbroek 		/* none to erase! */
1923*b89261baSDavid van Moolenbroek 		putchar('\7');
1924*b89261baSDavid van Moolenbroek 	    }
1925*b89261baSDavid van Moolenbroek 	    else
1926*b89261baSDavid van Moolenbroek 	    {
1927*b89261baSDavid van Moolenbroek 		fputs("\b \b", stdout);
1928*b89261baSDavid van Moolenbroek 		ptr--;
1929*b89261baSDavid van Moolenbroek 		cnt--;
1930*b89261baSDavid van Moolenbroek 	    }
1931*b89261baSDavid van Moolenbroek 	}
1932*b89261baSDavid van Moolenbroek 	/* check for character validity and buffer overflow */
1933*b89261baSDavid van Moolenbroek 	else if (cnt == size || (numeric && !isdigit((int)ch)) ||
1934*b89261baSDavid van Moolenbroek 		!isprint((int)ch))
1935*b89261baSDavid van Moolenbroek 	{
1936*b89261baSDavid van Moolenbroek 	    /* not legal */
1937*b89261baSDavid van Moolenbroek 	    putchar('\7');
1938*b89261baSDavid van Moolenbroek 	}
1939*b89261baSDavid van Moolenbroek 	else
1940*b89261baSDavid van Moolenbroek 	{
1941*b89261baSDavid van Moolenbroek 	    /* echo it and store it in the buffer */
1942*b89261baSDavid van Moolenbroek 	    putchar(ch);
1943*b89261baSDavid van Moolenbroek 	    ptr++;
1944*b89261baSDavid van Moolenbroek 	    cnt++;
1945*b89261baSDavid van Moolenbroek 	}
1946*b89261baSDavid van Moolenbroek     }
1947*b89261baSDavid van Moolenbroek 
1948*b89261baSDavid van Moolenbroek     /* all done -- null terminate the string */
1949*b89261baSDavid van Moolenbroek     *ptr = '\0';
1950*b89261baSDavid van Moolenbroek 
1951*b89261baSDavid van Moolenbroek     /* add response length to message_length */
1952*b89261baSDavid van Moolenbroek     message_length += cnt;
1953*b89261baSDavid van Moolenbroek 
1954*b89261baSDavid van Moolenbroek     /* return either inputted number or string length */
1955*b89261baSDavid van Moolenbroek     putchar('\r');
1956*b89261baSDavid van Moolenbroek     return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
1957*b89261baSDavid van Moolenbroek }
1958*b89261baSDavid van Moolenbroek 
1959*b89261baSDavid van Moolenbroek void
display_pagerstart()1960*b89261baSDavid van Moolenbroek display_pagerstart()
1961*b89261baSDavid van Moolenbroek 
1962*b89261baSDavid van Moolenbroek {
1963*b89261baSDavid van Moolenbroek     display_clear();
1964*b89261baSDavid van Moolenbroek }
1965*b89261baSDavid van Moolenbroek 
1966*b89261baSDavid van Moolenbroek void
display_pagerend()1967*b89261baSDavid van Moolenbroek display_pagerend()
1968*b89261baSDavid van Moolenbroek 
1969*b89261baSDavid van Moolenbroek {
1970*b89261baSDavid van Moolenbroek     char ch;
1971*b89261baSDavid van Moolenbroek 
1972*b89261baSDavid van Moolenbroek     screen_standout("Hit any key to continue: ");
1973*b89261baSDavid van Moolenbroek     fflush(stdout);
1974*b89261baSDavid van Moolenbroek     (void) read(0, &ch, 1);
1975*b89261baSDavid van Moolenbroek }
1976*b89261baSDavid van Moolenbroek 
1977*b89261baSDavid van Moolenbroek void
display_pager(const char * fmt,...)1978*b89261baSDavid van Moolenbroek display_pager(const char *fmt, ...)
1979*b89261baSDavid van Moolenbroek 
1980*b89261baSDavid van Moolenbroek {
1981*b89261baSDavid van Moolenbroek     va_list ap;
1982*b89261baSDavid van Moolenbroek 
1983*b89261baSDavid van Moolenbroek     int ch;
1984*b89261baSDavid van Moolenbroek     char readch;
1985*b89261baSDavid van Moolenbroek     char buffer[MAX_COLS];
1986*b89261baSDavid van Moolenbroek     char *data;
1987*b89261baSDavid van Moolenbroek 
1988*b89261baSDavid van Moolenbroek     /* format into buffer */
1989*b89261baSDavid van Moolenbroek     va_start(ap, fmt);
1990*b89261baSDavid van Moolenbroek     (void) vsnprintf(buffer, MAX_COLS, fmt, ap);
1991*b89261baSDavid van Moolenbroek     va_end(ap);
1992*b89261baSDavid van Moolenbroek     data = buffer;
1993*b89261baSDavid van Moolenbroek 
1994*b89261baSDavid van Moolenbroek     while ((ch = *data++) != '\0')
1995*b89261baSDavid van Moolenbroek     {
1996*b89261baSDavid van Moolenbroek 	putchar(ch);
1997*b89261baSDavid van Moolenbroek 	if (ch == '\n')
1998*b89261baSDavid van Moolenbroek 	{
1999*b89261baSDavid van Moolenbroek 	    if (++curr_y >= screen_length - 1)
2000*b89261baSDavid van Moolenbroek 	    {
2001*b89261baSDavid van Moolenbroek 		screen_standout("...More...");
2002*b89261baSDavid van Moolenbroek 		fflush(stdout);
2003*b89261baSDavid van Moolenbroek 		(void) read(0, &readch, 1);
2004*b89261baSDavid van Moolenbroek 		putchar('\r');
2005*b89261baSDavid van Moolenbroek 		switch(readch)
2006*b89261baSDavid van Moolenbroek 		{
2007*b89261baSDavid van Moolenbroek 		case '\r':
2008*b89261baSDavid van Moolenbroek 		case '\n':
2009*b89261baSDavid van Moolenbroek 		    curr_y--;
2010*b89261baSDavid van Moolenbroek 		    break;
2011*b89261baSDavid van Moolenbroek 
2012*b89261baSDavid van Moolenbroek 		case 'q':
2013*b89261baSDavid van Moolenbroek 		    return;
2014*b89261baSDavid van Moolenbroek 
2015*b89261baSDavid van Moolenbroek 		default:
2016*b89261baSDavid van Moolenbroek 		    curr_y = 0;
2017*b89261baSDavid van Moolenbroek 		}
2018*b89261baSDavid van Moolenbroek 	    }
2019*b89261baSDavid van Moolenbroek 	}
2020*b89261baSDavid van Moolenbroek     }
2021*b89261baSDavid van Moolenbroek }
2022