#include "os.h"
#include <ctype.h>
#include <stdarg.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <unistd.h>
#include "top.h"
#include "machine.h"
#include "screen.h"
#include "layout.h"
#include "display.h"
#include "boolean.h"
#include "utils.h"
#ifdef ENABLE_COLOR
#include "color.h"
#endif
#define CURSOR_COST 8
#define MESSAGE_DISPLAY_TIME 5
extern int overstrike;
static int lmpid = -1;
static int display_width = MAX_COLS;
static int x_lastpid = X_LASTPID;
static int y_lastpid = Y_LASTPID;
static int x_loadave = X_LOADAVE;
static int y_loadave = Y_LOADAVE;
static int x_minibar = X_MINIBAR;
static int y_minibar = Y_MINIBAR;
static int x_uptime = X_UPTIME;
static int y_uptime = Y_UPTIME;
static int x_procstate = X_PROCSTATE;
static int y_procstate = Y_PROCSTATE;
static int x_cpustates = X_CPUSTATES;
static int y_cpustates = Y_CPUSTATES;
static int x_kernel = X_KERNEL;
static int y_kernel = Y_KERNEL;
static int x_mem = X_MEM;
static int y_mem = Y_MEM;
static int x_swap = X_SWAP;
static int y_swap = Y_SWAP;
static int y_message = Y_MESSAGE;
static int x_header = X_HEADER;
static int y_header = Y_HEADER;
static int x_idlecursor = X_IDLECURSOR;
static int y_idlecursor = Y_IDLECURSOR;
static int y_procs = Y_PROCS;
static char *screenbuf = NULL;
static char *colorbuf = NULL;
static char scratchbuf[MAX_COLS];
static int bufsize = 0;
#define lineindex(l) ((l)*MAX_COLS)
static int curr_x, curr_y;
static int curr_color;
static int virt_x, virt_y;
static char **procstate_names;
static char **cpustate_names;
static char **memory_names;
static char **swap_names;
static char **kernel_names;
static int num_procstates;
static int num_cpustates;
static int num_memory;
static int num_swap;
static int num_kernel;
static int *lprocstates;
static int *lcpustates;
static int *cpustate_columns;
static int cpustate_total_length;
static int header_status = Yes;
#define MAX_MESSAGES 16
static char *message_buf[MAX_MESSAGES];
static int message_first = 0;
static int message_last = 0;
static struct timeval message_time = {0, 0};
static char *message_current = NULL;
static int message_length = 0;
static int message_hold = 1;
static int message_barrier = No;
#ifdef ENABLE_COLOR
static int load_cidx[3];
static int header_cidx;
static int *cpustate_cidx;
static int *memory_cidx;
static int *swap_cidx;
static int *kernel_cidx;
#else
#define memory_cidx NULL
#define swap_cidx NULL
#define kernel_cidx NULL
#endif
static int
string_count(char **pp)
{
register int cnt = 0;
if (pp != NULL)
{
while (*pp++ != NULL)
{
cnt++;
}
}
return(cnt);
}
void
display_clear()
{
dprintf("display_clear\n");
screen_clear();
memzero(screenbuf, bufsize);
memzero(colorbuf, bufsize);
curr_x = curr_y = 0;
}
void
display_move(int x, int y)
{
char buff[128];
char *p;
char *bufp;
char *colorp;
int cnt = 0;
int color = curr_color;
dprintf("display_move(%d, %d): curr_x %d, curr_y %d\n", x, y, curr_x, curr_y);
if (curr_y < y || (curr_y == y && curr_x <= x))
{
cnt = CURSOR_COST;
p = buff;
while (cnt > 0 && curr_y < y)
{
#ifdef ENABLE_COLOR
if (color != 0)
{
p = strcpyend(p, color_setstr(0));
color = 0;
cnt -= 5;
}
#endif
*p++ = '\n';
curr_y++;
curr_x = 0;
cnt--;
}
bufp = &screenbuf[lineindex(curr_y) + curr_x];
colorp = &colorbuf[lineindex(curr_y) + curr_x];
while (cnt > 0 && curr_x < x)
{
#ifdef ENABLE_COLOR
if (color != *colorp)
{
color = *colorp;
p = strcpyend(p, color_setstr(color));
cnt -= 5;
}
#endif
if ((*p = *bufp) == '\0')
{
*p = *bufp = ' ';
}
p++;
bufp++;
colorp++;
curr_x++;
cnt--;
}
}
if (cnt > 0)
{
*p = '\0';
fputs(buff, stdout);
curr_color = color;
}
else
{
screen_move(x, y);
}
curr_x = x;
curr_y = y;
}
void
display_write(int x, int y, int newcolor, int eol, char *new)
{
char *bufp;
char *colorp;
int ch;
int diff;
dprintf("display_write(%d, %d, %d, %d, \"%s\")\n",
x, y, newcolor, eol, new);
if (!smart_terminal)
{
if (x != -1)
{
while (curr_y < y)
{
putchar('\n');
curr_y++;
curr_x = 0;
}
while (curr_x < x)
{
putchar(' ');
curr_x++;
}
}
fputs(new, stdout);
curr_x += strlen(new);
return;
}
if (x == -1)
{
x = virt_x;
y = virt_y;
}
else
{
virt_x = x;
virt_y = y;
}
bufp = &screenbuf[lineindex(y) + x];
colorp = &colorbuf[lineindex(y) + x];
while ((ch = *new++) != '\0')
{
if (y < (smart_terminal ? screen_length : Largest) && x < display_width &&
(ch != *bufp || newcolor != *colorp))
{
if (y != curr_y || x != curr_x)
{
display_move(x, y);
}
#ifdef ENABLE_COLOR
if (curr_color != newcolor)
{
fputs(color_setstr(newcolor), stdout);
curr_color = newcolor;
}
#endif
putchar(ch);
*bufp = ch;
*colorp = curr_color;
curr_x++;
}
x++;
virt_x++;
bufp++;
colorp++;
}
if (eol && *bufp != '\0')
{
dprintf("display_write: clear-eol (bufp = \"%s\")\n", bufp);
#ifdef ENABLE_COLOR
if (curr_color != 0)
{
fputs(color_setstr(0), stdout);
curr_color = 0;
}
#endif
if (x != curr_x || y != curr_y)
{
screen_move(x, y);
curr_x = x;
curr_y = y;
}
screen_cleareol(strlen(bufp));
diff = display_width - x;
if (diff > 0)
{
memzero(bufp, diff);
memzero(colorp, diff);
}
}
}
void
display_fmt(int x, int y, int newcolor, int eol, char *fmt, ...)
{
va_list argp;
va_start(argp, fmt);
vsnprintf(scratchbuf, MAX_COLS, fmt, argp);
display_write(x, y, newcolor, eol, scratchbuf);
}
void
display_cte()
{
int len;
int y;
char *p;
int need_clear = 0;
p = &screenbuf[lineindex(virt_y) + virt_x];
if (*p != '\0')
{
need_clear = 1;
}
else
{
y = virt_y;
while (++y < screen_length)
{
if (screenbuf[lineindex(y)] != '\0')
{
need_clear = 1;
break;
}
}
}
if (need_clear)
{
dprintf("display_cte: clearing\n");
len = lineindex(virt_y) + virt_x;
display_move(virt_x, virt_y);
if (!screen_cte())
{
p = &screenbuf[len];
len = strlen(p);
if (len > 0)
{
screen_cleareol(len);
}
while (++virt_y < screen_length)
{
display_move(0, virt_y);
p = &screenbuf[lineindex(virt_y)];
len = strlen(p);
if (len > 0)
{
screen_cleareol(len);
}
}
}
memzero(&screenbuf[len], bufsize - len);
memzero(&colorbuf[len], bufsize - len);
}
}
static void
summary_format(int x, int y, int *numbers, char **names, int *cidx)
{
register int num;
register char *thisname;
register char *lastname = NULL;
register int color;
while ((thisname = *names++) != NULL)
{
num = *numbers++;
color = 0;
if (num != 0)
{
if (lastname != NULL)
{
display_write(-1, -1, 0, 0, lastname);
}
#ifdef ENABLE_COLOR
if (cidx != NULL)
{
color = color_test(*cidx++, num);
}
#endif
if (num > 0)
{
display_write(x, y, color, 0, itoa(num));
}
lastname = thisname;
x = y = -1;
}
}
if (lastname != NULL)
{
if ((num = strlen(lastname)) > 1 &&
lastname[num-2] == ',' && lastname[num-1] == ' ')
{
display_fmt(-1, -1, 0, 1, "%.*s", num-2, lastname);
}
else
{
display_write(-1, -1, 0, 1, lastname);
}
}
}
static void
summary_format_memory(int x, int y, long *numbers, char **names, int *cidx)
{
register long num;
register int color;
register char *thisname;
register char *lastname = NULL;
while ((thisname = *names++) != NULL)
{
num = *numbers++;
color = 0;
if (num != 0)
{
if (lastname != NULL)
{
display_write(-1, -1, 0, 0, lastname);
}
lastname = thisname;
#ifdef ENABLE_COLOR
color = color_test(*cidx++, num);
#endif
if (thisname[0] == 'K')
{
display_write(x, y, color, 0, format_k(num));
lastname++;
}
else
{
display_write(x, y, color, 0, itoa((int)num));
}
x = y = -1;
}
}
if (lastname != NULL)
{
if ((num = strlen(lastname)) > 1 &&
lastname[num-2] == ',' && lastname[num-1] == ' ')
{
display_fmt(-1, -1, 0, 1, "%.*s", num-2, lastname);
}
else
{
display_write(-1, -1, 0, 1, lastname);
}
}
}
int
display_resize()
{
register int top_lines;
register int newsize;
top_lines = smart_terminal ? screen_length : 1;
display_width = screen_width;
if (display_width >= MAX_COLS)
{
display_width = MAX_COLS - 1;
}
newsize = top_lines * (MAX_COLS + 1);
if (newsize > bufsize)
{
if (screenbuf != NULL)
{
free(screenbuf);
}
if (colorbuf != NULL)
{
free(colorbuf);
}
bufsize = newsize;
screenbuf = (char *)calloc(bufsize, sizeof(char));
colorbuf = (char *)calloc(bufsize, sizeof(char));
if (screenbuf == NULL || colorbuf == NULL)
{
return(-1);
}
}
else
{
memzero(screenbuf, bufsize);
memzero(colorbuf, bufsize);
}
if (top_lines > y_procs)
top_lines -= y_procs;
else
top_lines = 0;
return(smart_terminal ? top_lines : Largest);
}
int
display_lines()
{
return(smart_terminal ? screen_length : Largest);
}
int
display_columns()
{
return(display_width);
}
int
display_init(struct statics *statics)
{
register int top_lines;
register char **pp;
register char *p;
register int *ip;
register int i;
if (enable_ncpus != 0 && n_cpus > 1)
{
y_mem = y_mem + n_cpus -1;
y_swap = y_swap + n_cpus -1;
y_message = y_message + n_cpus -1;
y_header = y_header + n_cpus -1;
y_idlecursor = y_idlecursor + n_cpus -1;
y_procs = y_procs + n_cpus -1;
}
kernel_names = statics->kernel_names;
if ((num_kernel = string_count(kernel_names)) > 0)
{
y_mem++;
y_swap++;
y_message++;
y_header++;
y_idlecursor++;
y_procs++;
}
swap_names = statics->swap_names;
if ((num_swap = string_count(swap_names)) > 0)
{
y_message++;
y_header++;
y_idlecursor++;
y_procs++;
}
top_lines = display_resize();
procstate_names = statics->procstate_names;
num_procstates = string_count(procstate_names);
lprocstates = (int *)calloc(num_procstates, sizeof(int));
cpustate_names = statics->cpustate_names;
num_cpustates = string_count(cpustate_names);
lcpustates = (int *)calloc(num_cpustates, sizeof(int));
cpustate_columns = (int *)calloc(num_cpustates, sizeof(int));
memory_names = statics->memory_names;
num_memory = string_count(memory_names);
cpustate_total_length = 0;
pp = cpustate_names;
ip = cpustate_columns;
while (*pp != NULL)
{
*ip++ = cpustate_total_length;
if ((i = strlen(*pp++)) > 0)
{
cpustate_total_length += i + 8;
}
}
#ifdef ENABLE_COLOR
load_cidx[0] = color_tag("1min");
load_cidx[1] = color_tag("5min");
load_cidx[2] = color_tag("15min");
header_cidx = color_tag("header");
cpustate_cidx = (int *)malloc(num_cpustates * sizeof(int));
i = 0;
p = strcpyend(scratchbuf, "cpu.");
while (i < num_cpustates)
{
strcpy(p, cpustate_names[i]);
cpustate_cidx[i++] = color_tag(scratchbuf);
}
if (num_kernel > 0)
{
kernel_cidx = (int *)malloc(num_kernel * sizeof(int));
i = 0;
p = strcpyend(scratchbuf, "kernel.");
while (i < num_kernel)
{
strcpy(p, homogenize(kernel_names[i]+1));
kernel_cidx[i++] = color_tag(scratchbuf);
}
}
memory_cidx = (int *)malloc(num_memory * sizeof(int));
i = 0;
p = strcpyend(scratchbuf, "memory.");
while (i < num_memory)
{
strcpy(p, homogenize(memory_names[i]+1));
memory_cidx[i++] = color_tag(scratchbuf);
}
if (num_swap > 0)
{
swap_cidx = (int *)malloc(num_swap * sizeof(int));
i = 0;
p = strcpyend(scratchbuf, "swap.");
while (i < num_swap)
{
strcpy(p, homogenize(swap_names[i]+1));
swap_cidx[i++] = color_tag(scratchbuf);
}
}
#endif
return(top_lines);
}
static void
pr_loadavg(double avg, int i)
{
int color = 0;
#ifdef ENABLE_COLOR
color = color_test(load_cidx[i], (int)(avg * 100));
#endif
display_fmt(x_loadave + X_LOADAVEWIDTH * i, y_loadave, color, 0,
avg < 10.0 ? " %5.2f" : " %5.1f", avg);
display_write(-1, -1, 0, 0, (i < 2 ? "," : ";"));
}
void
i_loadave(int mpid, double *avenrun)
{
register int i;
if (mpid != -1)
{
display_fmt(0, 0, 0, 0,
"last pid: %5d; load avg:", mpid);
x_loadave = X_LOADAVE;
}
else
{
display_write(0, 0, 0, 0, "load averages:");
x_loadave = X_LOADAVE - X_LASTPIDWIDTH;
}
for (i = 0; i < 3; i++)
{
pr_loadavg(avenrun[i], i);
}
lmpid = mpid;
}
void
u_loadave(int mpid, double *avenrun)
{
register int i;
if (mpid != -1)
{
if (mpid != lmpid)
{
display_fmt(x_lastpid, y_lastpid, 0, 0,
"%5d", mpid);
lmpid = mpid;
}
}
for (i = 0; i < 3; i++)
{
pr_loadavg(avenrun[i], i);
}
}
static char minibar_buffer[64];
#define MINIBAR_WIDTH 20
void
i_minibar(int (*formatter)(char *, int))
{
(void)((*formatter)(minibar_buffer, MINIBAR_WIDTH));
display_write(x_minibar, y_minibar, 0, 0, minibar_buffer);
}
void
u_minibar(int (*formatter)(char *, int))
{
(void)((*formatter)(minibar_buffer, MINIBAR_WIDTH));
display_write(x_minibar, y_minibar, 0, 0, minibar_buffer);
}
static int uptime_days;
static int uptime_hours;
static int uptime_mins;
static int uptime_secs;
void
i_uptime(time_t uptime)
{
uptime += 30;
uptime_days = uptime / 86400;
uptime %= 86400;
uptime_hours = uptime / 3600;
uptime %= 3600;
uptime_mins = uptime / 60;
uptime_secs = uptime % 60;
display_fmt(x_uptime, y_uptime, 0, 0,
" up %d+%02d:%02d:%02d",
uptime_days, uptime_hours, uptime_mins, uptime_secs);
}
void
u_uptime(time_t uptime)
{
i_uptime(uptime);
}
void
i_timeofday(time_t *tod)
{
int x;
x = (smart_terminal ? screen_width : 79) - 8;
if (x < x_uptime + 19)
{
x = x_uptime + 19;
}
display_fmt(x, 0, 0, 1, "%-8.8s", &(ctime(tod)[11]));
}
static int ltotal = 0;
static int lthreads = 0;
void
i_procstates(int total, int *brkdn, int threads)
{
display_fmt(0, y_procstate, 0, 0,
"%d %s: ", total, threads ? "threads" : "processes");
ltotal = total;
x_procstate = virt_x;
if (total > 0)
{
summary_format(-1, -1, brkdn, procstate_names, NULL);
memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
lthreads = threads;
}
}
void
u_procstates(int total, int *brkdn, int threads)
{
if (lthreads != threads)
{
i_procstates(total, brkdn, threads);
return;
}
if (ltotal != total)
{
display_fmt(0, y_procstate, 0, 0,
"%d", total);
if (digits(total) != digits(ltotal))
{
display_fmt(-1, -1, 0, 0, " %s: ", threads ? "threads" : "processes");
x_procstate = virt_x;
}
ltotal = total;
}
if (total > 0 && memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0)
{
summary_format(x_procstate, y_procstate, brkdn, procstate_names, NULL);
memcpy(lprocstates, brkdn, num_procstates * sizeof(int));
}
}
char *
cpustates_tag()
{
register char *use;
static char *short_tag = "CPU: ";
static char *long_tag = "CPU states: ";
if (cpustate_total_length + (int)strlen(long_tag) - 2 >= screen_width)
{
use = short_tag;
}
else
{
use = long_tag;
}
x_cpustates = strlen(use);
return(use);
}
void
i_cpustates(int *states)
{
int value;
char **names;
char *thisname;
int *colp;
int color = 0;
int cpu;
#ifdef ENABLE_COLOR
int *cidx = cpustate_cidx;
#endif
names = cpustate_names;
colp = cpustate_columns;
if (enable_ncpus !=0 && n_cpus > 1) {
for (cpu = 0; cpu < n_cpus; ++cpu) {
int y_pos = y_cpustates;
y_pos = y_pos + cpu;
colp = cpustate_columns;
names = cpustate_names;
display_write(0, y_cpustates+cpu, 0, 0, cpustates_tag());
while ((thisname = *names++) != NULL) {
if (*thisname != '\0') {
value = *states;
#ifdef ENABLE_COLOR
color = color_test(*cidx++, value/10);
#endif
display_fmt(x_cpustates + *colp, y_pos,
color, 0,
(value >= 1000 ? "%4.0f%% %s%s" : "%4.1f%% %s%s"),
((float)value)/10.,
thisname,
*names != NULL ? ", " : "");
}
colp++;
states++;
}
memcpy(lcpustates, states, num_cpustates * sizeof(int));
}
} else {
display_write(0, y_cpustates, 0, 0, cpustates_tag());
while ((thisname = *names++) != NULL)
{
if (*thisname != '\0')
{
value = *states;
#ifdef ENABLE_COLOR
color = color_test(*cidx++, value/10);
#endif
display_fmt(x_cpustates + *colp, y_cpustates,
color, 0,
(value >= 1000 ? "%4.0f%% %s%s" : "%4.1f%% %s%s"),
((float)value)/10.,
thisname,
*names != NULL ? ", " : "");
}
colp++;
states++;
}
memcpy(lcpustates, states, num_cpustates * sizeof(int));
}
}
void
u_cpustates(int *states)
{
int value;
char **names = cpustate_names;
char *thisname;
int *lp;
int *colp;
int color = 0;
int cpu;
#ifdef ENABLE_COLOR
int *cidx = cpustate_cidx;
#endif
if (enable_ncpus != 0 && n_cpus > 1 ) {
for (cpu = 0; cpu < n_cpus; ++cpu) {
lp = lcpustates;
int y_pos = y_cpustates;
y_pos = y_pos + cpu;
colp = cpustate_columns;
char **names = cpustate_names;
while ((thisname = *names++) != NULL) {
if (*thisname != '\0') {
value = *states;
#ifdef ENABLE_COLOR
color = color_test(*cidx, value/10);
#endif
display_fmt(x_cpustates + *colp, y_pos, color, 0,
(value >= 1000 ? "%4.0f" : "%4.1f"),
((double)value)/10.);
#ifdef ENABLE_COLOR
cidx++;
#endif
}
lp++;
states++;
colp++;
}
}
} else {
lp = lcpustates;
colp = cpustate_columns;
while ((thisname = *names++) != NULL)
{
if (*thisname != '\0')
{
if (*lp != *states)
{
value = *states;
#ifdef ENABLE_COLOR
color = color_test(*cidx, value/10);
#endif
display_fmt(x_cpustates + *colp, y_cpustates, color, 0,
(value >= 1000 ? "%4.0f" : "%4.1f"),
((double)value)/10.);
*lp = value;
}
#ifdef ENABLE_COLOR
cidx++;
#endif
}
lp++;
states++;
colp++;
}
}
}
void
z_cpustates()
{
register int i = 0;
register char **names = cpustate_names;
register char *thisname;
register int *lp;
int cpu;
if (enable_ncpus != 0 && n_cpus > 1) {
for (cpu = 0; cpu < n_cpus; ++cpu) {
display_write(0, y_cpustates + cpu, 0, 0, cpustates_tag());
char **names = cpustate_names;
i = 0;
while ((thisname = *names++) != NULL) {
if (*thisname != '\0') {
display_fmt(-1, -1, 0, 0, "%s %% %s", i++ == 0 ? "" : ", ",
thisname);
}
}
lp = lcpustates;
i = num_cpustates;
while (--i >= 0) {
*lp++ = -1;
}
}
} else {
display_write(0, y_cpustates, 0, 0, cpustates_tag());
while ((thisname = *names++) != NULL)
{
if (*thisname != '\0')
{
display_fmt(-1, -1, 0, 0, "%s %% %s", i++ == 0 ? "" : ", ",
thisname);
}
}
lp = lcpustates;
i = num_cpustates;
while (--i >= 0)
{
*lp++ = -1;
}
}
}
void
i_kernel(int *stats)
{
if (num_kernel > 0)
{
display_write(0, y_kernel, 0, 0, "Kernel: ");
summary_format(x_kernel, y_kernel, stats, kernel_names, kernel_cidx);
}
}
void
u_kernel(int *stats)
{
if (num_kernel > 0)
{
summary_format(x_kernel, y_kernel, stats, kernel_names, kernel_cidx);
}
}
void
i_memory(long *stats)
{
display_write(0, y_mem, 0, 0, "Memory: ");
summary_format_memory(x_mem, y_mem, stats, memory_names, memory_cidx);
}
void
u_memory(long *stats)
{
summary_format_memory(x_mem, y_mem, stats, memory_names, memory_cidx);
}
void
i_swap(long *stats)
{
if (num_swap > 0)
{
display_write(0, y_swap, 0, 0, "Swap: ");
summary_format_memory(x_swap, y_swap, stats, swap_names, swap_cidx);
}
}
void
u_swap(long *stats)
{
if (num_swap > 0)
{
summary_format_memory(x_swap, y_swap, stats, swap_names, swap_cidx);
}
}
void
i_message(struct timeval *now)
{
struct timeval my_now;
int i = 0;
dprintf("i_message(%08x)\n", now);
if (now == NULL)
{
time_get(&my_now);
now = &my_now;
}
message_hold = 0;
dprintf("i_message: now %d, message_time %d\n",
now->tv_sec, message_time.tv_sec);
if (smart_terminal)
{
if (timercmp(now, &message_time, > ))
{
dprintf("i_message: timer expired\n");
if (message_current != NULL)
{
free(message_current);
message_current = NULL;
}
if (message_first != message_last)
{
if (++message_first == MAX_MESSAGES) message_first = 0;
message_current = message_buf[message_first];
dprintf("i_message: showing \"%s\"\n", message_current);
display_move(0, y_message);
screen_standout(message_current);
i = strlen(message_current);
message_time = *now;
message_time.tv_sec += MESSAGE_DISPLAY_TIME;
screen_cleareol(message_length - i);
putchar('\r');
message_length = i;
}
else
{
if (message_length > 0)
{
display_move(0, y_message);
screen_cleareol(message_length);
putchar('\r');
message_length = 0;
}
}
}
}
}
void
u_message(struct timeval *now)
{
i_message(now);
}
static int header_length;
void
i_header(char *text)
{
int header_color = 0;
#ifdef ENABLE_COLOR
header_color = color_test(header_cidx, 0);
#endif
header_length = strlen(text);
if (header_status)
{
display_write(x_header, y_header, header_color, 1, text);
}
}
void
u_header(char *text)
{
int header_color = 0;
#ifdef ENABLE_COLOR
header_color = color_test(header_cidx, 0);
#endif
display_write(x_header, y_header, header_color, 1,
header_status ? text : "");
}
void
i_process(int line, char *thisline)
{
thisline[display_width] = '\0';
display_write(0, y_procs + line, 0, 1, thisline);
}
void
u_process(int line, char *new_line)
{
i_process(line, new_line);
}
void
i_endscreen()
{
if (smart_terminal)
{
display_move(x_idlecursor, y_idlecursor);
}
else
{
fputs("\n\n", stdout);
}
fflush(stdout);
}
void
u_endscreen()
{
if (smart_terminal)
{
display_cte();
display_move(x_idlecursor, y_idlecursor);
fflush(stdout);
}
else
{
fputs("\n\n", stdout);
}
}
void
display_header(int t)
{
header_status = t != 0;
}
void
message_mark()
{
message_barrier = Yes;
}
void
message_expire()
{
message_time.tv_sec = 0;
message_time.tv_usec = 0;
}
void
message_flush()
{
message_first = message_last;
message_time.tv_sec = 0;
message_time.tv_usec = 0;
}
void
new_message_v(char *msgfmt, va_list ap)
{
int i;
int empty;
char msg[MAX_COLS];
if (message_barrier)
{
message_flush();
message_barrier = No;
}
(void) vsnprintf(msg, sizeof(msg), msgfmt, ap);
i = message_last + 1;
if (i >= MAX_MESSAGES) i = 0;
if (i != message_first)
{
message_buf[i] = strdup(msg);
dprintf("new_message_v: new message inserted in slot %d\n", i);
empty = message_last == message_first;
message_last = i;
if (empty && !message_hold)
{
i_message(NULL);
}
}
}
void
new_message(char *msgfmt, ...)
{
va_list ap;
va_start(ap, msgfmt);
new_message_v(msgfmt, ap);
va_end(ap);
}
void
message_error(char *msgfmt, ...)
{
va_list ap;
va_start(ap, msgfmt);
new_message_v(msgfmt, ap);
fflush(stdout);
va_end(ap);
}
void
message_clear()
{
if (message_current != NULL)
{
display_move(0, y_message);
screen_cleareol(message_length);
free(message_current);
message_current = NULL;
}
message_flush();
}
void
message_prompt_v(int so, char *msgfmt, va_list ap)
{
char msg[MAX_COLS];
int i;
message_flush();
i = vsnprintf(msg, sizeof(msg), msgfmt, ap);
display_move(0, y_message);
screen_cleareol(message_length);
if (so)
{
screen_standout(msg);
}
else
{
fputs(msg, stdout);
}
fflush(stdout);
message_length = i < MAX_COLS ? i : MAX_COLS;
}
void
message_prompt(char *msgfmt, ...)
{
va_list ap;
va_start(ap, msgfmt);
message_prompt_v(Yes, msgfmt, ap);
va_end(ap);
}
void
message_prompt_plain(char *msgfmt, ...)
{
va_list ap;
va_start(ap, msgfmt);
message_prompt_v(No, msgfmt, ap);
va_end(ap);
}
int
readline(char *buffer, int size, int numeric)
{
register char *ptr = buffer;
register char ch;
register char cnt = 0;
size -= 1;
while ((fflush(stdout), read(0, ptr, 1) > 0))
{
if ((ch = *ptr) == '\n' || ch == '\r')
{
break;
}
if (ch == ch_kill)
{
*buffer = '\0';
putchar('\r');
return(-1);
}
else if (ch == ch_werase)
{
if (cnt <= 0)
{
putchar('\7');
}
else
{
while(cnt > 0 && ptr[-1] == ' ')
{
fputs("\b \b", stdout);
ptr--;
cnt--;
}
while(cnt > 0 && ptr[-1] != ' ')
{
fputs("\b \b", stdout);
ptr--;
cnt--;
}
}
}
else if (ch == ch_erase)
{
if (cnt <= 0)
{
putchar('\7');
}
else
{
fputs("\b \b", stdout);
ptr--;
cnt--;
}
}
else if (cnt == size || (numeric && !isdigit((int)ch)) ||
!isprint((int)ch))
{
putchar('\7');
}
else
{
putchar(ch);
ptr++;
cnt++;
}
}
*ptr = '\0';
message_length += cnt;
putchar('\r');
return(cnt == 0 ? -1 : numeric ? atoi(buffer) : cnt);
}
void
display_pagerstart()
{
display_clear();
}
void
display_pagerend()
{
char ch;
screen_standout("Hit any key to continue: ");
fflush(stdout);
(void) read(0, &ch, 1);
}
void
display_pager(char *fmt, ...)
{
va_list ap;
int ch;
char readch;
char buffer[MAX_COLS];
char *data;
va_start(ap, fmt);
(void) vsnprintf(buffer, MAX_COLS, fmt, ap);
va_end(ap);
data = buffer;
while ((ch = *data++) != '\0')
{
putchar(ch);
if (ch == '\n')
{
if (++curr_y >= screen_length - 1)
{
screen_standout("...More...");
fflush(stdout);
(void) read(0, &readch, 1);
putchar('\r');
switch(readch)
{
case '\r':
case '\n':
curr_y--;
break;
case 'q':
return;
default:
curr_y = 0;
}
}
}
}
}