Annotation of src/usr.bin/top/screen.c, Revision 1.14
1.14 ! deraadt 1: /* $OpenBSD: screen.c,v 1.13 2003/06/16 17:24:44 millert 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:
1.10 deraadt 31: /*
32: * This file contains the routines that interface to termcap and stty/gtty.
1.14 ! deraadt 33: *
1.10 deraadt 34: * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
1.14 ! deraadt 35: *
1.10 deraadt 36: * I put in code to turn on the TOSTOP bit while top was running, but I didn't
37: * really like the results. If you desire it, turn on the preprocessor
38: * variable "TOStop". --wnl
1.1 downsj 39: */
40:
1.2 downsj 41: #include <sys/types.h>
42: #include <sys/ioctl.h>
1.13 millert 43: #include <err.h>
1.2 downsj 44: #include <stdio.h>
45: #include <stdlib.h>
1.3 millert 46: #include <string.h>
1.2 downsj 47: #include <term.h>
48: #include <termios.h>
49: #include <unistd.h>
50:
1.1 downsj 51: #include "top.h"
52: #include "screen.h"
53: #include "boolean.h"
54:
1.12 deraadt 55: int overstrike, screen_length, screen_width;
56: char ch_erase, ch_kill, smart_terminal, PC;
57: char string_buffer[1024], home[15], lower_left[15];
58: char *clear_line, *clear_scr, *clear_to_end;
59: char *cursor_motion, *start_standout, *end_standout;
60: char *terminal_init, *terminal_end;
61: short ospeed;
1.1 downsj 62:
1.12 deraadt 63: static struct termios old_settings, new_settings;
1.1 downsj 64:
1.12 deraadt 65: static char is_a_terminal = No;
1.1 downsj 66:
1.9 pvalchev 67: void
68: init_termcap(int interactive)
1.1 downsj 69: {
1.10 deraadt 70: char *bufptr, *PCptr, *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: /* pretend we have a dumb terminal */
79: smart_terminal = No;
80: return;
81: }
82: /* assume we have a smart terminal until proven otherwise */
83: smart_terminal = Yes;
84:
85: /* get the terminal name */
86: term_name = getenv("TERM");
87:
88: /* if there is no TERM, assume it's a dumb terminal */
89: /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
90: if (term_name == NULL) {
91: smart_terminal = No;
92: return;
93: }
94:
95: /* now get the termcap entry */
96: if ((status = tgetent(NULL, term_name)) != 1) {
97: if (status == -1)
1.12 deraadt 98: warnx("can't open termcap file");
1.10 deraadt 99: else
1.12 deraadt 100: warnx("no termcap entry for a `%s' terminal", term_name);
1.10 deraadt 101:
102: /* pretend it's dumb and proceed */
103: smart_terminal = No;
104: return;
1.1 downsj 105: }
1.10 deraadt 106:
107: /* "hardcopy" immediately indicates a very stupid terminal */
108: if (tgetflag("hc")) {
109: smart_terminal = No;
110: return;
111: }
112: /* set up common terminal capabilities */
113: if ((screen_length = tgetnum("li")) <= Header_lines) {
114: screen_length = smart_terminal = 0;
115: return;
116: }
117:
118: /* screen_width is a little different */
119: if ((screen_width = tgetnum("co")) == -1)
120: screen_width = 79;
1.1 downsj 121: else
1.10 deraadt 122: screen_width -= 1;
123:
124: /* terminals that overstrike need special attention */
125: overstrike = tgetflag("os");
126:
127: /* initialize the pointer into the termcap string buffer */
128: bufptr = string_buffer;
129:
130: /* get "ce", clear to end */
131: if (!overstrike) {
132: clear_line = tgetstr("ce", &bufptr);
133: }
134: /* get necessary capabilities */
135: if ((clear_scr = tgetstr("cl", &bufptr)) == NULL ||
136: (cursor_motion = tgetstr("cm", &bufptr)) == NULL) {
137: smart_terminal = No;
138: return;
139: }
140: /* get some more sophisticated stuff -- these are optional */
141: clear_to_end = tgetstr("cd", &bufptr);
142: terminal_init = tgetstr("ti", &bufptr);
143: terminal_end = tgetstr("te", &bufptr);
144: start_standout = tgetstr("so", &bufptr);
145: end_standout = tgetstr("se", &bufptr);
146:
147: /* pad character */
148: PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
149:
150: /* set convenience strings */
151: (void) strlcpy(home, tgoto(cursor_motion, 0, 0), sizeof(home));
152: /* (lower_left is set in get_screensize) */
153:
154: /* get the actual screen size with an ioctl, if needed */
155: /*
156: * This may change screen_width and screen_length, and it always sets
157: * lower_left.
158: */
159: get_screensize();
160:
161: /* if stdout is not a terminal, pretend we are a dumb terminal */
162: if (tcgetattr(STDOUT_FILENO, &old_settings) == -1)
163: smart_terminal = No;
1.1 downsj 164: }
165:
1.9 pvalchev 166: void
167: init_screen(void)
1.1 downsj 168: {
1.10 deraadt 169: /* get the old settings for safe keeping */
170: if (tcgetattr(STDOUT_FILENO, &old_settings) != -1) {
171: /* copy the settings so we can modify them */
172: new_settings = old_settings;
173:
174: /* turn off ICANON, character echo and tab expansion */
175: new_settings.c_lflag &= ~(ICANON | ECHO);
176: new_settings.c_oflag &= ~(OXTABS);
177: new_settings.c_cc[VMIN] = 1;
178: new_settings.c_cc[VTIME] = 0;
179: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
180:
181: /* remember the erase and kill characters */
182: ch_erase = old_settings.c_cc[VERASE];
183: ch_kill = old_settings.c_cc[VKILL];
184:
185: /* remember that it really is a terminal */
186: is_a_terminal = Yes;
187:
188: /* send the termcap initialization string */
189: putcap(terminal_init);
190: }
191: if (!is_a_terminal) {
192: /* not a terminal at all---consider it dumb */
193: smart_terminal = No;
194: }
1.1 downsj 195: }
196:
1.9 pvalchev 197: void
198: end_screen(void)
1.1 downsj 199: {
1.10 deraadt 200: /* move to the lower left, clear the line and send "te" */
201: if (smart_terminal) {
202: putcap(lower_left);
203: putcap(clear_line);
204: fflush(stdout);
205: putcap(terminal_end);
206: }
207:
208: /* if we have settings to reset, then do so */
209: if (is_a_terminal)
210: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &old_settings);
1.1 downsj 211: }
212:
1.9 pvalchev 213: void
214: reinit_screen(void)
1.1 downsj 215: {
1.10 deraadt 216: /* install our settings if it is a terminal */
217: if (is_a_terminal)
218: (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
219:
220: /* send init string */
221: if (smart_terminal)
222: putcap(terminal_init);
1.1 downsj 223: }
224:
1.9 pvalchev 225: void
226: get_screensize(void)
1.1 downsj 227: {
1.10 deraadt 228: struct winsize ws;
1.1 downsj 229:
1.10 deraadt 230: if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) {
231: if (ws.ws_row != 0)
232: screen_length = ws.ws_row;
233: if (ws.ws_col != 0)
234: screen_width = ws.ws_col - 1;
235: }
236: (void) strlcpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
237: sizeof(lower_left));
1.1 downsj 238: }
239:
1.9 pvalchev 240: void
241: standout(char *msg)
1.1 downsj 242: {
1.10 deraadt 243: if (smart_terminal) {
244: putcap(start_standout);
245: if (fputs(msg, stdout) == EOF)
246: exit(1);
247: putcap(end_standout);
248: } else {
249: if (fputs(msg, stdout) == EOF)
250: exit(1);
251: }
1.1 downsj 252: }
253:
1.14 ! deraadt 254: void
! 255: clear(void)
1.1 downsj 256: {
1.10 deraadt 257: if (smart_terminal)
258: putcap(clear_scr);
1.1 downsj 259: }
260:
1.9 pvalchev 261: int
262: clear_eol(int len)
1.1 downsj 263: {
1.10 deraadt 264: if (smart_terminal && !overstrike && len > 0) {
265: if (clear_line) {
266: putcap(clear_line);
267: return (0);
268: } else {
269: while (len-- > 0) {
270: if (putchar(' ') == EOF)
271: exit(1);
272: }
273: return (1);
274: }
1.1 downsj 275: }
1.10 deraadt 276: return (-1);
1.1 downsj 277: }
278:
1.9 pvalchev 279: void
280: go_home(void)
1.1 downsj 281: {
1.10 deraadt 282: if (smart_terminal)
283: putcap(home);
1.1 downsj 284: }
285:
286: /* This has to be defined as a subroutine for tputs (instead of a macro) */
1.9 pvalchev 287: int
288: putstdout(int ch)
1.1 downsj 289: {
1.10 deraadt 290: int ret;
1.7 deraadt 291:
1.10 deraadt 292: ret = putchar(ch);
293: if (ret == EOF)
294: exit(1);
295: return (ret);
1.1 downsj 296: }