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