Annotation of src/usr.bin/top/screen.c, Revision 1.5
1.5 ! bitblt 1: /* $OpenBSD: screen.c,v 1.4 1997/09/16 19:25:00 weingart 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 */
1.5 ! bitblt 171: (void) strncpy(home, tgoto(cursor_motion, 0, 0), sizeof (home) -1);
! 172: home[sizeof (home) -1] = 0;
1.1 downsj 173: /* (lower_left is set in get_screensize) */
174:
175: /* get the actual screen size with an ioctl, if needed */
176: /* This may change screen_width and screen_length, and it always
177: sets lower_left. */
178: get_screensize();
179:
180: /* if stdout is not a terminal, pretend we are a dumb terminal */
1.2 downsj 181: if (tcgetattr(STDOUT_FILENO, &old_settings) == -1)
1.1 downsj 182: {
183: smart_terminal = No;
184: }
185: }
186:
1.2 downsj 187: void init_screen()
1.1 downsj 188:
189: {
190: /* get the old settings for safe keeping */
1.2 downsj 191: if (tcgetattr(STDOUT_FILENO, &old_settings) != -1)
1.1 downsj 192: {
193: /* copy the settings so we can modify them */
194: new_settings = old_settings;
195:
196: /* turn off ICANON, character echo and tab expansion */
197: new_settings.c_lflag &= ~(ICANON|ECHO);
1.2 downsj 198: new_settings.c_oflag &= ~(OXTABS);
1.1 downsj 199: new_settings.c_cc[VMIN] = 1;
200: new_settings.c_cc[VTIME] = 0;
1.2 downsj 201: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
1.1 downsj 202:
203: /* remember the erase and kill characters */
204: ch_erase = old_settings.c_cc[VERASE];
205: ch_kill = old_settings.c_cc[VKILL];
206:
207: /* remember that it really is a terminal */
208: is_a_terminal = Yes;
209:
210: /* send the termcap initialization string */
211: putcap(terminal_init);
212: }
213:
214: if (!is_a_terminal)
215: {
216: /* not a terminal at all---consider it dumb */
217: smart_terminal = No;
218: }
219: }
220:
1.2 downsj 221: void end_screen()
1.1 downsj 222:
223: {
224: /* move to the lower left, clear the line and send "te" */
225: if (smart_terminal)
226: {
227: putcap(lower_left);
228: putcap(clear_line);
229: fflush(stdout);
230: putcap(terminal_end);
231: }
232:
233: /* if we have settings to reset, then do so */
234: if (is_a_terminal)
235: {
1.2 downsj 236: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &old_settings);
1.1 downsj 237: }
238: }
239:
1.2 downsj 240: void reinit_screen()
1.1 downsj 241:
242: {
243: /* install our settings if it is a terminal */
244: if (is_a_terminal)
245: {
1.2 downsj 246: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
1.1 downsj 247: }
248:
249: /* send init string */
250: if (smart_terminal)
251: {
252: putcap(terminal_init);
253: }
254: }
255:
1.2 downsj 256: void get_screensize()
1.1 downsj 257:
258: {
259: struct winsize ws;
260:
1.2 downsj 261: if (ioctl (STDIN_FILENO, TIOCGWINSZ, &ws) != -1)
1.1 downsj 262: {
263: if (ws.ws_row != 0)
264: {
265: screen_length = ws.ws_row;
266: }
267: if (ws.ws_col != 0)
268: {
269: screen_width = ws.ws_col - 1;
270: }
271: }
272:
1.5 ! bitblt 273: (void) strncpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
! 274: sizeof (lower_left) -1);
! 275: lower_left[sizeof(lower_left) -1] = 0;
1.1 downsj 276: }
277:
1.2 downsj 278: void standout(msg)
1.1 downsj 279:
280: char *msg;
281:
282: {
283: if (smart_terminal)
284: {
285: putcap(start_standout);
286: fputs(msg, stdout);
287: putcap(end_standout);
288: }
289: else
290: {
291: fputs(msg, stdout);
292: }
293: }
294:
1.2 downsj 295: void clear()
1.1 downsj 296:
297: {
298: if (smart_terminal)
299: {
1.2 downsj 300: putcap(clear_scr);
1.1 downsj 301: }
302: }
303:
1.2 downsj 304: int clear_eol(len)
1.1 downsj 305:
306: int len;
307:
308: {
309: if (smart_terminal && !overstrike && len > 0)
310: {
311: if (clear_line)
312: {
313: putcap(clear_line);
314: return(0);
315: }
316: else
317: {
318: while (len-- > 0)
319: {
320: putchar(' ');
321: }
322: return(1);
323: }
324: }
325: return(-1);
326: }
327:
1.2 downsj 328: void go_home()
1.1 downsj 329:
330: {
331: if (smart_terminal)
332: {
333: putcap(home);
334: }
335: }
336:
337: /* This has to be defined as a subroutine for tputs (instead of a macro) */
338:
1.2 downsj 339: int putstdout(ch)
1.1 downsj 340:
1.2 downsj 341: int ch;
1.1 downsj 342:
343: {
1.2 downsj 344: return(putchar(ch));
1.1 downsj 345: }
346: