BUS_CONFIG_INTR takes 2 devices now: parent and child
[dragonfly.git] / contrib / top / screen.c
blob8429c62722180c9d6bedae2e32066060080d8622
1 /*
2 * Top users/processes display for Unix
3 * Version 3
5 * This program may be freely redistributed,
6 * but this entire comment MUST remain intact.
8 * Copyright (c) 1984, 1989, William LeFebvre, Rice University
9 * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
11 * $FreeBSD: src/contrib/top/screen.c,v 1.2.6.1 2000/09/20 02:27:57 jkh Exp $
12 * $DragonFly: src/contrib/top/screen.c,v 1.2 2003/06/17 04:24:07 dillon Exp $
15 /* This file contains the routines that interface to termcap and stty/gtty.
17 * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
19 * I put in code to turn on the TOSTOP bit while top was running, but I
20 * didn't really like the results. If you desire it, turn on the
21 * preprocessor variable "TOStop". --wnl
24 #include "os.h"
25 #include "top.h"
27 #include <sys/ioctl.h>
28 #include <curses.h>
29 #include <term.h>
30 #include <termios.h>
31 #include "screen.h"
32 #include "boolean.h"
34 extern char *myname;
36 int overstrike;
37 int screen_length;
38 int screen_width;
39 char ch_erase;
40 char ch_kill;
41 char smart_terminal;
42 char PC;
43 char termcap_buf[1024];
44 char string_buffer[1024];
45 char home[15];
46 char lower_left[15];
47 char *clear_line;
48 char *clear_the_screen;
49 char *clear_to_end;
50 char *cursor_motion;
51 char *start_standout;
52 char *end_standout;
53 char *terminal_init;
54 char *terminal_end;
56 static struct termios old_settings;
57 static struct termios new_settings;
58 static char is_a_terminal = No;
60 #define STDIN 0
61 #define STDOUT 1
62 #define STDERR 2
64 void
65 init_termcap(int interactive)
67 char *bufptr;
68 char *PCptr;
69 char *term_name;
70 int status;
72 /* set defaults in case we aren't smart */
73 screen_width = MAX_COLS;
74 screen_length = 0;
76 if (!interactive)
78 /* pretend we have a dumb terminal */
79 smart_terminal = No;
80 return;
83 /* assume we have a smart terminal until proven otherwise */
84 smart_terminal = Yes;
86 /* get the terminal name */
87 term_name = getenv("TERM");
89 /* if there is no TERM, assume it's a dumb terminal */
90 /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
91 if (term_name == NULL)
93 smart_terminal = No;
94 return;
97 /* now get the termcap entry */
98 if ((status = tgetent(termcap_buf, term_name)) != 1)
100 if (status == -1)
102 fprintf(stderr, "%s: can't open termcap file\n", myname);
104 else
106 fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
107 myname, term_name);
110 /* pretend it's dumb and proceed */
111 smart_terminal = No;
112 return;
115 /* "hardcopy" immediately indicates a very stupid terminal */
116 if (tgetflag("hc"))
118 smart_terminal = No;
119 return;
122 /* set up common terminal capabilities */
123 if ((screen_length = tgetnum("li")) <= 0)
125 screen_length = smart_terminal = 0;
126 return;
129 /* screen_width is a little different */
130 if ((screen_width = tgetnum("co")) == -1)
132 screen_width = 79;
134 else
136 screen_width -= 1;
139 /* terminals that overstrike need special attention */
140 overstrike = tgetflag("os");
142 /* initialize the pointer into the termcap string buffer */
143 bufptr = string_buffer;
145 /* get "ce", clear to end */
146 if (!overstrike)
148 clear_line = tgetstr("ce", &bufptr);
151 /* get necessary capabilities */
152 if ((clear_the_screen = tgetstr("cl", &bufptr)) == NULL ||
153 (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
155 smart_terminal = No;
156 return;
159 /* get some more sophisticated stuff -- these are optional */
160 clear_to_end = tgetstr("cd", &bufptr);
161 terminal_init = tgetstr("ti", &bufptr);
162 terminal_end = tgetstr("te", &bufptr);
163 start_standout = tgetstr("so", &bufptr);
164 end_standout = tgetstr("se", &bufptr);
166 /* pad character */
167 PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
169 /* set convenience strings */
170 (void) strncpy(home, tgoto(cursor_motion, 0, 0), sizeof(home) - 1);
171 home[sizeof(home) - 1] = '\0';
172 /* (lower_left is set in get_screensize) */
174 /* get the actual screen size with an ioctl, if needed */
175 /* This may change screen_width and screen_length, and it always
176 sets lower_left. */
177 get_screensize();
179 /* if stdout is not a terminal, pretend we are a dumb terminal */
180 if (tcgetattr(STDOUT, &old_settings) == -1)
182 smart_terminal = No;
186 void
187 init_screen(void)
189 if (tcgetattr(STDOUT, &old_settings) != -1)
191 /* copy the settings so we can modify them */
192 new_settings = old_settings;
194 /* turn off ICANON, character echo and tab expansion */
195 new_settings.c_lflag &= ~(ICANON|ECHO);
196 new_settings.c_oflag &= ~(OXTABS);
197 new_settings.c_cc[VMIN] = 1;
198 new_settings.c_cc[VTIME] = 0;
199 (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
201 /* remember the erase and kill characters */
202 ch_erase = old_settings.c_cc[VERASE];
203 ch_kill = old_settings.c_cc[VKILL];
205 /* remember that it really is a terminal */
206 is_a_terminal = Yes;
208 /* send the termcap initialization string */
209 putcap(terminal_init);
212 if (!is_a_terminal)
214 /* not a terminal at all---consider it dumb */
215 smart_terminal = No;
219 void
220 end_screen(void)
222 /* move to the lower left, clear the line and send "te" */
223 if (smart_terminal)
225 putcap(lower_left);
226 putcap(clear_line);
227 fflush(stdout);
228 putcap(terminal_end);
231 /* if we have settings to reset, then do so */
232 if (is_a_terminal)
234 (void) tcsetattr(STDOUT, TCSADRAIN, &old_settings);
238 void
239 reinit_screen(void)
241 /* install our settings if it is a terminal */
242 if (is_a_terminal)
244 (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
247 /* send init string */
248 if (smart_terminal)
250 putcap(terminal_init);
254 void
255 get_screensize(void)
258 #ifdef TIOCGWINSZ
260 struct winsize ws;
262 if (ioctl (1, TIOCGWINSZ, &ws) != -1)
264 if (ws.ws_row != 0)
266 screen_length = ws.ws_row;
268 if (ws.ws_col != 0)
270 screen_width = ws.ws_col - 1;
274 #else
275 #ifdef TIOCGSIZE
277 struct ttysize ts;
279 if (ioctl (1, TIOCGSIZE, &ts) != -1)
281 if (ts.ts_lines != 0)
283 screen_length = ts.ts_lines;
285 if (ts.ts_cols != 0)
287 screen_width = ts.ts_cols - 1;
291 #endif /* TIOCGSIZE */
292 #endif /* TIOCGWINSZ */
294 (void) strncpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
295 sizeof(lower_left) - 1);
296 lower_left[sizeof(lower_left) - 1] = '\0';
299 void
300 dostandout(const char *msg)
302 if (smart_terminal)
304 putcap(start_standout);
305 fputs(msg, stdout);
306 putcap(end_standout);
308 else
310 fputs(msg, stdout);
314 void
315 clear_myscreen(void)
317 if (smart_terminal)
319 putcap(clear_screen);
324 clear_eol(int len)
326 if (smart_terminal && !overstrike && len > 0)
328 if (clear_line)
330 putcap(clear_line);
331 return(0);
333 else
335 while (len-- > 0)
337 putchar(' ');
339 return(1);
342 return(-1);
345 void
346 go_home(void)
348 if (smart_terminal)
350 putcap(home);
354 /* This has to be defined as a subroutine for tputs (instead of a macro) */
357 putstdout(int ch)
359 return(putchar(ch));