Annotation of src/usr.bin/top/screen.c, Revision 1.2
1.2 ! downsj 1: /* $OpenBSD: screen.c,v 1.1 1997/08/14 14:00:24 downsj Exp $ */
1.1 downsj 2:
3: /*
4: * Top users/processes display for Unix
5: * Version 3
6: *
7: * This program may be freely redistributed,
8: * but this entire comment MUST remain intact.
9: *
10: * Copyright (c) 1984, 1989, William LeFebvre, Rice University
11: * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
12: */
13:
14: /* This file contains the routines that interface to termcap and stty/gtty.
15: *
16: * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
17: *
18: * I put in code to turn on the TOSTOP bit while top was running, but I
19: * didn't really like the results. If you desire it, turn on the
20: * preprocessor variable "TOStop". --wnl
21: */
22:
1.2 ! downsj 23: #include <sys/types.h>
! 24: #include <sys/ioctl.h>
! 25: #include <stdio.h>
! 26: #include <stdlib.h>
! 27: #include <term.h>
! 28: #include <termios.h>
! 29: #include <unistd.h>
! 30:
1.1 downsj 31: #include "top.h"
32: #include "screen.h"
33: #include "boolean.h"
34:
35: extern char *myname;
36:
37: int overstrike;
38: int screen_length;
39: int screen_width;
40: char ch_erase;
41: char ch_kill;
42: char smart_terminal;
43: char PC;
44: char string_buffer[1024];
45: char home[15];
46: char lower_left[15];
47: char *clear_line;
1.2 ! downsj 48: char *clear_scr;
1.1 downsj 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;
55: short ospeed;
56:
57: static struct termios old_settings;
58: static struct termios new_settings;
1.2 ! downsj 59:
1.1 downsj 60: static char is_a_terminal = No;
61:
1.2 ! downsj 62: void init_termcap(interactive)
1.1 downsj 63:
64: int interactive;
65:
66: {
67: char *bufptr;
68: char *PCptr;
69: char *term_name;
70: int status;
71:
72: /* set defaults in case we aren't smart */
73: screen_width = MAX_COLS;
74: screen_length = 0;
75:
76: if (!interactive)
77: {
78: /* pretend we have a dumb terminal */
79: smart_terminal = No;
80: return;
81: }
82:
83: /* assume we have a smart terminal until proven otherwise */
84: smart_terminal = Yes;
85:
86: /* get the terminal name */
87: term_name = getenv("TERM");
88:
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)
92: {
93: smart_terminal = No;
94: return;
95: }
96:
97: /* now get the termcap entry */
1.2 ! downsj 98: if ((status = tgetent(NULL, term_name)) != 1)
1.1 downsj 99: {
100: if (status == -1)
101: {
102: fprintf(stderr, "%s: can't open termcap file\n", myname);
103: }
104: else
105: {
106: fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
107: myname, term_name);
108: }
109:
110: /* pretend it's dumb and proceed */
111: smart_terminal = No;
112: return;
113: }
114:
115: /* "hardcopy" immediately indicates a very stupid terminal */
116: if (tgetflag("hc"))
117: {
118: smart_terminal = No;
119: return;
120: }
121:
122: /* set up common terminal capabilities */
123: if ((screen_length = tgetnum("li")) <= 0)
124: {
125: screen_length = smart_terminal = 0;
126: return;
127: }
128:
129: /* screen_width is a little different */
130: if ((screen_width = tgetnum("co")) == -1)
131: {
132: screen_width = 79;
133: }
134: else
135: {
136: screen_width -= 1;
137: }
138:
139: /* terminals that overstrike need special attention */
140: overstrike = tgetflag("os");
141:
142: /* initialize the pointer into the termcap string buffer */
143: bufptr = string_buffer;
144:
145: /* get "ce", clear to end */
146: if (!overstrike)
147: {
148: clear_line = tgetstr("ce", &bufptr);
149: }
150:
151: /* get necessary capabilities */
1.2 ! downsj 152: if ((clear_scr = tgetstr("cl", &bufptr)) == NULL ||
1.1 downsj 153: (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
154: {
155: smart_terminal = No;
156: return;
157: }
158:
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);
165:
166: /* pad character */
167: PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
168:
169: /* set convenience strings */
170: (void) strcpy(home, tgoto(cursor_motion, 0, 0));
171: /* (lower_left is set in get_screensize) */
172:
173: /* get the actual screen size with an ioctl, if needed */
174: /* This may change screen_width and screen_length, and it always
175: sets lower_left. */
176: get_screensize();
177:
178: /* if stdout is not a terminal, pretend we are a dumb terminal */
1.2 ! downsj 179: if (tcgetattr(STDOUT_FILENO, &old_settings) == -1)
1.1 downsj 180: {
181: smart_terminal = No;
182: }
183: }
184:
1.2 ! downsj 185: void init_screen()
1.1 downsj 186:
187: {
188: /* get the old settings for safe keeping */
1.2 ! downsj 189: if (tcgetattr(STDOUT_FILENO, &old_settings) != -1)
1.1 downsj 190: {
191: /* copy the settings so we can modify them */
192: new_settings = old_settings;
193:
194: /* turn off ICANON, character echo and tab expansion */
195: new_settings.c_lflag &= ~(ICANON|ECHO);
1.2 ! downsj 196: new_settings.c_oflag &= ~(OXTABS);
1.1 downsj 197: new_settings.c_cc[VMIN] = 1;
198: new_settings.c_cc[VTIME] = 0;
1.2 ! downsj 199: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
1.1 downsj 200:
201: /* remember the erase and kill characters */
202: ch_erase = old_settings.c_cc[VERASE];
203: ch_kill = old_settings.c_cc[VKILL];
204:
205: /* remember that it really is a terminal */
206: is_a_terminal = Yes;
207:
208: /* send the termcap initialization string */
209: putcap(terminal_init);
210: }
211:
212: if (!is_a_terminal)
213: {
214: /* not a terminal at all---consider it dumb */
215: smart_terminal = No;
216: }
217: }
218:
1.2 ! downsj 219: void end_screen()
1.1 downsj 220:
221: {
222: /* move to the lower left, clear the line and send "te" */
223: if (smart_terminal)
224: {
225: putcap(lower_left);
226: putcap(clear_line);
227: fflush(stdout);
228: putcap(terminal_end);
229: }
230:
231: /* if we have settings to reset, then do so */
232: if (is_a_terminal)
233: {
1.2 ! downsj 234: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &old_settings);
1.1 downsj 235: }
236: }
237:
1.2 ! downsj 238: void reinit_screen()
1.1 downsj 239:
240: {
241: /* install our settings if it is a terminal */
242: if (is_a_terminal)
243: {
1.2 ! downsj 244: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
1.1 downsj 245: }
246:
247: /* send init string */
248: if (smart_terminal)
249: {
250: putcap(terminal_init);
251: }
252: }
253:
1.2 ! downsj 254: void get_screensize()
1.1 downsj 255:
256: {
257: struct winsize ws;
258:
1.2 ! downsj 259: if (ioctl (STDIN_FILENO, TIOCGWINSZ, &ws) != -1)
1.1 downsj 260: {
261: if (ws.ws_row != 0)
262: {
263: screen_length = ws.ws_row;
264: }
265: if (ws.ws_col != 0)
266: {
267: screen_width = ws.ws_col - 1;
268: }
269: }
270:
271: (void) strcpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1));
272: }
273:
1.2 ! downsj 274: void standout(msg)
1.1 downsj 275:
276: char *msg;
277:
278: {
279: if (smart_terminal)
280: {
281: putcap(start_standout);
282: fputs(msg, stdout);
283: putcap(end_standout);
284: }
285: else
286: {
287: fputs(msg, stdout);
288: }
289: }
290:
1.2 ! downsj 291: void clear()
1.1 downsj 292:
293: {
294: if (smart_terminal)
295: {
1.2 ! downsj 296: putcap(clear_scr);
1.1 downsj 297: }
298: }
299:
1.2 ! downsj 300: int clear_eol(len)
1.1 downsj 301:
302: int len;
303:
304: {
305: if (smart_terminal && !overstrike && len > 0)
306: {
307: if (clear_line)
308: {
309: putcap(clear_line);
310: return(0);
311: }
312: else
313: {
314: while (len-- > 0)
315: {
316: putchar(' ');
317: }
318: return(1);
319: }
320: }
321: return(-1);
322: }
323:
1.2 ! downsj 324: void go_home()
1.1 downsj 325:
326: {
327: if (smart_terminal)
328: {
329: putcap(home);
330: }
331: }
332:
333: /* This has to be defined as a subroutine for tputs (instead of a macro) */
334:
1.2 ! downsj 335: int putstdout(ch)
1.1 downsj 336:
1.2 ! downsj 337: int ch;
1.1 downsj 338:
339: {
1.2 ! downsj 340: return(putchar(ch));
1.1 downsj 341: }
342: