📄 display.c
字号:
/* * Top users/processes display for Unix * Version 3 * * This program may be freely redistributed, * but this entire comment MUST remain intact. * * Copyright (c) 1984, 1989, William LeFebvre, Rice University * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University *//* * This file contains the routines that display information on the screen. * Each section of the screen has two routines: one for initially writing * all constant and dynamic text, and one for only updating the text that * changes. The prefix "i_" is used on all the "initial" routines and the * prefix "u_" is used for all the "updating" routines. * * ASSUMPTIONS: * None of the "i_" routines use any of the termcap capabilities. * In this way, those routines can be safely used on terminals that * have minimal (or nonexistant) terminal capabilities. * * The routines are called in this order: *_loadave, i_timeofday, * *_procstates, *_cpustates, *_memory, *_message, *_header, * *_process, u_endscreen. */#include "os.h"#include <ctype.h>#include <time.h>#include "screen.h" /* interface to screen package */#include "layout.h" /* defines for screen position layout */#include "display.h"#include "top.h"#include "top.local.h"#include "boolean.h"#include "machine.h" /* we should eliminate this!!! */#include "utils.h"#ifdef DEBUGFILE *debug;#endif/* imported from screen.c */extern int overstrike;static int lmpid = 0;static int last_hi = 0; /* used in u_process and u_endscreen */static int lastline = 0;static int display_width = MAX_COLS;#define lineindex(l) ((l)*display_width)char *printable();/* things initialized by display_init and used thruout *//* buffer of proc information lines for display updating */char *screenbuf = NULL;static char **procstate_names;static char **cpustate_names;static char **memory_names;static int num_procstates;static int num_cpustates;static int num_memory;static int *lprocstates;static int *lcpustates;static int *lmemory;static int *cpustate_columns;static int cpustate_total_length;static enum { OFF, ON, ERASE } header_status = ON;static int string_count();static void summary_format();static void line_update();int display_resize(){ register int lines; /* first, deallocate any previous buffer that may have been there */ if (screenbuf != NULL) { free(screenbuf); } /* calculate the current dimensions */ /* if operating in "dumb" mode, we only need one line */ lines = smart_terminal ? screen_length - Header_lines : 1; /* we don't want more than MAX_COLS columns, since the machine-dependent modules make static allocations based on MAX_COLS and we don't want to run off the end of their buffers */ display_width = screen_width; if (display_width >= MAX_COLS) { display_width = MAX_COLS - 1; } /* now, allocate space for the screen buffer */ screenbuf = (char *)malloc(lines * display_width); if (screenbuf == (char *)NULL) { /* oops! */ return(-1); } /* return number of lines available */ /* for dumb terminals, pretend like we can show any amount */ return(smart_terminal ? lines : Largest);}int display_init(statics)struct statics *statics;{ register int lines; register char **pp; register int *ip; register int i; /* call resize to do the dirty work */ lines = display_resize(); /* only do the rest if we need to */ if (lines > -1) { /* save pointers and allocate space for names */ procstate_names = statics->procstate_names; num_procstates = string_count(procstate_names); lprocstates = (int *)malloc(num_procstates * sizeof(int)); cpustate_names = statics->cpustate_names; num_cpustates = string_count(cpustate_names); lcpustates = (int *)malloc(num_cpustates * sizeof(int)); cpustate_columns = (int *)malloc(num_cpustates * sizeof(int)); memory_names = statics->memory_names; num_memory = string_count(memory_names); lmemory = (int *)malloc(num_memory * sizeof(int)); /* calculate starting columns where needed */ 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; } } } /* return number of lines available */ return(lines);}i_loadave(mpid, avenrun)int mpid;double *avenrun;{ register int i; /* i_loadave also clears the screen, since it is first */ clear(); /* mpid == -1 implies this system doesn't have an _mpid */ if (mpid != -1) { printf("last pid: %5d; ", mpid); } printf("load averages"); for (i = 0; i < 3; i++) { printf("%c %5.2f", i == 0 ? ':' : ',', avenrun[i]); } lmpid = mpid;}u_loadave(mpid, avenrun)int mpid;double *avenrun;{ register int i; if (mpid != -1) { /* change screen only when value has really changed */ if (mpid != lmpid) { Move_to(x_lastpid, y_lastpid); printf("%5d", mpid); lmpid = mpid; } /* i remembers x coordinate to move to */ i = x_loadave; } else { i = x_loadave_nompid; } /* move into position for load averages */ Move_to(i, y_loadave); /* display new load averages */ /* we should optimize this and only display changes */ for (i = 0; i < 3; i++) { printf("%s%5.2f", i == 0 ? "" : ", ", avenrun[i]); }}i_timeofday(tod)time_t *tod;{ /* * Display the current time. * "ctime" always returns a string that looks like this: * * Sun Sep 16 01:03:52 1973 * 012345678901234567890123 * 1 2 * * We want indices 11 thru 18 (length 8). */ if (smart_terminal) { Move_to(screen_width - 8, 0); } else { fputs(" ", stdout); }#ifdef DEBUG { char *foo; foo = ctime(tod); fputs(foo, stdout); }#endif printf("%-8.8s\n", &(ctime(tod)[11])); lastline = 1;}static int ltotal = 0;static char procstates_buffer[MAX_COLS];/* * *_procstates(total, brkdn, names) - print the process summary line * * Assumptions: cursor is at the beginning of the line on entry * lastline is valid */i_procstates(total, brkdn)int total;int *brkdn;{ register int i; /* write current number of processes and remember the value */ printf("%d processes:", total); ltotal = total; /* put out enough spaces to get to column 15 */ i = digits(total); while (i++ < 4) { putchar(' '); } /* format and print the process state summary */ summary_format(procstates_buffer, brkdn, procstate_names); fputs(procstates_buffer, stdout); /* save the numbers for next time */ memcpy(lprocstates, brkdn, num_procstates * sizeof(int));}u_procstates(total, brkdn)int total;int *brkdn;{ static char new[MAX_COLS]; register int i; /* update number of processes only if it has changed */ if (ltotal != total) { /* move and overwrite */#if (x_procstate == 0) Move_to(x_procstate, y_procstate);#else /* cursor is already there...no motion needed */ /* assert(lastline == 1); */#endif printf("%d", total); /* if number of digits differs, rewrite the label */ if (digits(total) != digits(ltotal)) { fputs(" processes:", stdout); /* put out enough spaces to get to column 15 */ i = digits(total); while (i++ < 4) { putchar(' '); } /* cursor may end up right where we want it!!! */ } /* save new total */ ltotal = total; } /* see if any of the state numbers has changed */ if (memcmp(lprocstates, brkdn, num_procstates * sizeof(int)) != 0) { /* format and update the line */ summary_format(new, brkdn, procstate_names); line_update(procstates_buffer, new, x_brkdn, y_brkdn); memcpy(lprocstates, brkdn, num_procstates * sizeof(int)); }}/* * *_cpustates(states, names) - print the cpu state percentages * * Assumptions: cursor is on the PREVIOUS line */static int cpustates_column;/* cpustates_tag() calculates the correct tag to use to label the line */char *cpustates_tag(){ register char *use; static char *short_tag = "CPU: "; static char *long_tag = "CPU states: "; /* if length + strlen(long_tag) >= screen_width, then we have to use the shorter tag (we subtract 2 to account for ": ") */ if (cpustate_total_length + (int)strlen(long_tag) - 2 >= screen_width) { use = short_tag; } else { use = long_tag; } /* set cpustates_column accordingly then return result */ cpustates_column = strlen(use); return(use);}i_cpustates(states)register int *states;{ register int i = 0; register int value; register char **names = cpustate_names; register char *thisname; /* print tag and bump lastline */ printf("\n%s", cpustates_tag()); lastline++; /* now walk thru the names and print the line */ while ((thisname = *names++) != NULL) { if (*thisname != '\0') { /* retrieve the value and remember it */ value = *states++; /* if percentage is >= 1000, print it as 100% */ printf((value >= 1000 ? "%s%4.0f%% %s" : "%s%4.1f%% %s"), i++ == 0 ? "" : ", ", ((float)value)/10., thisname); } } /* copy over values into "last" array */ memcpy(lcpustates, states, num_cpustates * sizeof(int));}u_cpustates(states)register int *states;{ register int value; register char **names = cpustate_names; register char *thisname; register int *lp; register int *colp; Move_to(cpustates_column, y_cpustates); lastline = y_cpustates; lp = lcpustates; colp = cpustate_columns; /* we could be much more optimal about this */ while ((thisname = *names++) != NULL) { if (*thisname != '\0') { /* did the value change since last time? */ if (*lp != *states) { /* yes, move and change */ Move_to(cpustates_column + *colp, y_cpustates); lastline = y_cpustates; /* retrieve value and remember it */ value = *states; /* if percentage is >= 1000, print it as 100% */ printf((value >= 1000 ? "%4.0f" : "%4.1f"), ((double)value)/10.); /* remember it for next time */ *lp = value; } } /* increment and move on */ lp++; states++; colp++; }}z_cpustates(){ register int i = 0; register char **names = cpustate_names; register char *thisname; register int *lp; /* show tag and bump lastline */ printf("\n%s", cpustates_tag()); lastline++; while ((thisname = *names++) != NULL) { if (*thisname != '\0') { printf("%s %% %s", i++ == 0 ? "" : ", ", thisname); } } /* fill the "last" array with all -1s, to insure correct updating */ lp = lcpustates; i = num_cpustates; while (--i >= 0) { *lp++ = -1; }}/* * *_memory(stats) - print "Memory: " followed by the memory summary string * * Assumptions: cursor is on "lastline" * for i_memory ONLY: cursor is on the previous line */char memory_buffer[MAX_COLS];i_memory(stats)int *stats;{ fputs("\nMemory: ", stdout); lastline++; /* format and print the memory summary */ summary_format(memory_buffer, stats, memory_names); fputs(memory_buffer, stdout);}u_memory(stats)int *stats;{ static char new[MAX_COLS]; /* format the new line */ summary_format(new, stats, memory_names); line_update(memory_buffer, new, x_mem, y_mem);}/* * *_message() - print the next pending message line, or erase the one * that is there. * * Note that u_message is (currently) the same as i_message. * * Assumptions: lastline is consistent *//* * i_message is funny because it gets its message asynchronously (with * respect to screen updates). */static char next_msg[MAX_COLS + 5];static int msglen = 0;/* Invariant: msglen is always the length of the message currently displayed on the screen (even when next_msg doesn't contain that message). */i_message(){ while (lastline < y_message) { fputc('\n', stdout); lastline++; } if (next_msg[0] != '\0') { standout(next_msg); msglen = strlen(next_msg); next_msg[0] = '\0';
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -