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