Annotation of src/usr.bin/top/screen.c, Revision 1.8
1.8 ! deraadt 1: /* $OpenBSD: screen.c,v 1.7 2001/07/27 17:13:42 deraadt Exp $ */
1.1 downsj 2:
3: /*
4: * Top users/processes display for Unix
5: * Version 3
6: *
1.8 ! deraadt 7: * Copyright (c) 1984, 1989, William LeFebvre, Rice University
! 8: * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
1.1 downsj 9: *
1.8 ! deraadt 10: * Redistribution and use in source and binary forms, with or without
! 11: * modification, are permitted provided that the following conditions
! 12: * are met:
! 13: * 1. Redistributions of source code must retain the above copyright
! 14: * notice, this list of conditions and the following disclaimer.
! 15: * 2. Redistributions in binary form must reproduce the above copyright
! 16: * notice, this list of conditions and the following disclaimer in the
! 17: * documentation and/or other materials provided with the distribution.
! 18: *
! 19: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
! 20: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
! 21: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
! 22: * IN NO EVENT SHALL THE AUTHOR OR HIS EMPLOYER BE LIABLE FOR ANY DIRECT, INDIRECT,
! 23: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
! 24: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
! 25: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
! 26: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
! 27: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
! 28: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1 downsj 29: */
30:
31: /* This file contains the routines that interface to termcap and stty/gtty.
32: *
33: * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
34: *
35: * I put in code to turn on the TOSTOP bit while top was running, but I
36: * didn't really like the results. If you desire it, turn on the
37: * preprocessor variable "TOStop". --wnl
38: */
39:
1.2 downsj 40: #include <sys/types.h>
41: #include <sys/ioctl.h>
42: #include <stdio.h>
43: #include <stdlib.h>
1.3 millert 44: #include <string.h>
1.2 downsj 45: #include <term.h>
46: #include <termios.h>
47: #include <unistd.h>
48:
1.1 downsj 49: #include "top.h"
50: #include "screen.h"
51: #include "boolean.h"
52:
53: extern char *myname;
54:
55: int overstrike;
56: int screen_length;
57: int screen_width;
58: char ch_erase;
59: char ch_kill;
60: char smart_terminal;
61: char PC;
62: char string_buffer[1024];
63: char home[15];
64: char lower_left[15];
65: char *clear_line;
1.2 downsj 66: char *clear_scr;
1.1 downsj 67: char *clear_to_end;
68: char *cursor_motion;
69: char *start_standout;
70: char *end_standout;
71: char *terminal_init;
72: char *terminal_end;
73: short ospeed;
74:
75: static struct termios old_settings;
76: static struct termios new_settings;
1.2 downsj 77:
1.1 downsj 78: static char is_a_terminal = No;
79:
1.2 downsj 80: void init_termcap(interactive)
1.1 downsj 81:
82: int interactive;
83:
84: {
85: char *bufptr;
86: char *PCptr;
87: char *term_name;
88: int status;
89:
90: /* set defaults in case we aren't smart */
91: screen_width = MAX_COLS;
92: screen_length = 0;
93:
94: if (!interactive)
95: {
96: /* pretend we have a dumb terminal */
97: smart_terminal = No;
98: return;
99: }
100:
101: /* assume we have a smart terminal until proven otherwise */
102: smart_terminal = Yes;
103:
104: /* get the terminal name */
105: term_name = getenv("TERM");
106:
107: /* if there is no TERM, assume it's a dumb terminal */
108: /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
109: if (term_name == NULL)
110: {
111: smart_terminal = No;
112: return;
113: }
114:
115: /* now get the termcap entry */
1.2 downsj 116: if ((status = tgetent(NULL, term_name)) != 1)
1.1 downsj 117: {
118: if (status == -1)
119: {
120: fprintf(stderr, "%s: can't open termcap file\n", myname);
121: }
122: else
123: {
124: fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
125: myname, term_name);
126: }
127:
128: /* pretend it's dumb and proceed */
129: smart_terminal = No;
130: return;
131: }
132:
133: /* "hardcopy" immediately indicates a very stupid terminal */
134: if (tgetflag("hc"))
135: {
136: smart_terminal = No;
137: return;
138: }
139:
140: /* set up common terminal capabilities */
1.4 weingart 141: if ((screen_length = tgetnum("li")) <= Header_lines)
1.1 downsj 142: {
143: screen_length = smart_terminal = 0;
144: return;
145: }
146:
147: /* screen_width is a little different */
148: if ((screen_width = tgetnum("co")) == -1)
149: {
150: screen_width = 79;
151: }
152: else
153: {
154: screen_width -= 1;
155: }
156:
157: /* terminals that overstrike need special attention */
158: overstrike = tgetflag("os");
159:
160: /* initialize the pointer into the termcap string buffer */
161: bufptr = string_buffer;
162:
163: /* get "ce", clear to end */
164: if (!overstrike)
165: {
166: clear_line = tgetstr("ce", &bufptr);
167: }
168:
169: /* get necessary capabilities */
1.2 downsj 170: if ((clear_scr = tgetstr("cl", &bufptr)) == NULL ||
1.1 downsj 171: (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
172: {
173: smart_terminal = No;
174: return;
175: }
176:
177: /* get some more sophisticated stuff -- these are optional */
178: clear_to_end = tgetstr("cd", &bufptr);
179: terminal_init = tgetstr("ti", &bufptr);
180: terminal_end = tgetstr("te", &bufptr);
181: start_standout = tgetstr("so", &bufptr);
182: end_standout = tgetstr("se", &bufptr);
183:
184: /* pad character */
185: PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
186:
187: /* set convenience strings */
1.5 bitblt 188: (void) strncpy(home, tgoto(cursor_motion, 0, 0), sizeof (home) -1);
189: home[sizeof (home) -1] = 0;
1.1 downsj 190: /* (lower_left is set in get_screensize) */
191:
192: /* get the actual screen size with an ioctl, if needed */
193: /* This may change screen_width and screen_length, and it always
194: sets lower_left. */
195: get_screensize();
196:
197: /* if stdout is not a terminal, pretend we are a dumb terminal */
1.2 downsj 198: if (tcgetattr(STDOUT_FILENO, &old_settings) == -1)
1.1 downsj 199: {
200: smart_terminal = No;
201: }
202: }
203:
1.2 downsj 204: void init_screen()
1.1 downsj 205:
206: {
207: /* get the old settings for safe keeping */
1.2 downsj 208: if (tcgetattr(STDOUT_FILENO, &old_settings) != -1)
1.1 downsj 209: {
210: /* copy the settings so we can modify them */
211: new_settings = old_settings;
212:
213: /* turn off ICANON, character echo and tab expansion */
214: new_settings.c_lflag &= ~(ICANON|ECHO);
1.2 downsj 215: new_settings.c_oflag &= ~(OXTABS);
1.1 downsj 216: new_settings.c_cc[VMIN] = 1;
217: new_settings.c_cc[VTIME] = 0;
1.2 downsj 218: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
1.1 downsj 219:
220: /* remember the erase and kill characters */
221: ch_erase = old_settings.c_cc[VERASE];
222: ch_kill = old_settings.c_cc[VKILL];
223:
224: /* remember that it really is a terminal */
225: is_a_terminal = Yes;
226:
227: /* send the termcap initialization string */
228: putcap(terminal_init);
229: }
230:
231: if (!is_a_terminal)
232: {
233: /* not a terminal at all---consider it dumb */
234: smart_terminal = No;
235: }
236: }
237:
1.2 downsj 238: void end_screen()
1.1 downsj 239:
240: {
241: /* move to the lower left, clear the line and send "te" */
242: if (smart_terminal)
243: {
244: putcap(lower_left);
245: putcap(clear_line);
246: fflush(stdout);
247: putcap(terminal_end);
248: }
249:
250: /* if we have settings to reset, then do so */
251: if (is_a_terminal)
252: {
1.2 downsj 253: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &old_settings);
1.1 downsj 254: }
255: }
256:
1.2 downsj 257: void reinit_screen()
1.1 downsj 258:
259: {
260: /* install our settings if it is a terminal */
261: if (is_a_terminal)
262: {
1.2 downsj 263: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
1.1 downsj 264: }
265:
266: /* send init string */
267: if (smart_terminal)
268: {
269: putcap(terminal_init);
270: }
271: }
272:
1.2 downsj 273: void get_screensize()
1.1 downsj 274:
275: {
276: struct winsize ws;
277:
1.6 downsj 278: if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1)
1.1 downsj 279: {
280: if (ws.ws_row != 0)
281: {
282: screen_length = ws.ws_row;
283: }
284: if (ws.ws_col != 0)
285: {
286: screen_width = ws.ws_col - 1;
287: }
288: }
289:
1.5 bitblt 290: (void) strncpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
291: sizeof (lower_left) -1);
292: lower_left[sizeof(lower_left) -1] = 0;
1.1 downsj 293: }
294:
1.2 downsj 295: void standout(msg)
1.1 downsj 296:
297: char *msg;
298:
299: {
300: if (smart_terminal)
301: {
302: putcap(start_standout);
1.7 deraadt 303: if (fputs(msg, stdout) == EOF)
304: exit(1);
1.1 downsj 305: putcap(end_standout);
306: }
307: else
308: {
1.7 deraadt 309: if (fputs(msg, stdout) == EOF)
310: exit(1);
1.1 downsj 311: }
312: }
313:
1.2 downsj 314: void clear()
1.1 downsj 315:
316: {
317: if (smart_terminal)
318: {
1.2 downsj 319: putcap(clear_scr);
1.1 downsj 320: }
321: }
322:
1.2 downsj 323: int clear_eol(len)
1.1 downsj 324:
325: int len;
326:
327: {
328: if (smart_terminal && !overstrike && len > 0)
329: {
330: if (clear_line)
331: {
332: putcap(clear_line);
333: return(0);
334: }
335: else
336: {
337: while (len-- > 0)
338: {
1.7 deraadt 339: if (putchar(' ') == EOF)
340: exit(1);
1.1 downsj 341: }
342: return(1);
343: }
344: }
345: return(-1);
346: }
347:
1.2 downsj 348: void go_home()
1.1 downsj 349:
350: {
351: if (smart_terminal)
352: {
353: putcap(home);
354: }
355: }
356:
357: /* This has to be defined as a subroutine for tputs (instead of a macro) */
358:
1.2 downsj 359: int putstdout(ch)
1.1 downsj 360:
1.2 downsj 361: int ch;
1.1 downsj 362:
363: {
1.7 deraadt 364: int ret;
365:
366: ret = putchar(ch);
367: if (ret == EOF)
368: exit(1);
369: return (ret);
1.1 downsj 370: }
371: