1 /* $OpenBSD: screen.c,v 1.19 2008/09/24 18:53:55 chl Exp $ */ 2 3 /* 4 * Top users/processes display for Unix 5 * Version 3 6 * 7 * Copyright (c) 1984, 1989, William LeFebvre, Rice University 8 * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University 9 * 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. 29 */ 30 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 39 */ 40 41 #include <sys/types.h> 42 #include <sys/ioctl.h> 43 #include <curses.h> 44 #include <err.h> 45 #include <stdio.h> 46 #include <stdlib.h> 47 #include <term.h> 48 #include <unistd.h> 49 50 #include "top.h" 51 #include "screen.h" 52 #include "boolean.h" 53 54 int screen_length, screen_width; 55 char ch_erase, ch_kill, smart_terminal; 56 57 static struct termios old_settings, new_settings; 58 static char is_a_terminal = No; 59 60 void 61 init_termcap(int interactive) 62 { 63 char *term_name; 64 int status; 65 66 /* set defaults in case we aren't smart */ 67 screen_width = MAX_COLS; 68 screen_length = 0; 69 70 if (!interactive) { 71 /* pretend we have a dumb terminal */ 72 smart_terminal = No; 73 return; 74 } 75 /* assume we have a smart terminal until proven otherwise */ 76 smart_terminal = Yes; 77 78 /* get the terminal name */ 79 term_name = getenv("TERM"); 80 81 /* if there is no TERM, assume it's a dumb terminal */ 82 /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */ 83 if (term_name == NULL) { 84 smart_terminal = No; 85 return; 86 } 87 88 /* now get the termcap entry */ 89 if ((status = tgetent(NULL, term_name)) != 1) { 90 if (status == -1) 91 warnx("can't open termcap file"); 92 else 93 warnx("no termcap entry for a `%s' terminal", term_name); 94 95 /* pretend it's dumb and proceed */ 96 smart_terminal = No; 97 return; 98 } 99 100 /* "hardcopy" immediately indicates a very stupid terminal */ 101 if (tgetflag("hc")) { 102 smart_terminal = No; 103 return; 104 } 105 106 /* set up common terminal capabilities */ 107 if ((screen_length = tgetnum("li")) <= Header_lines) { 108 screen_length = smart_terminal = 0; 109 return; 110 } 111 112 /* screen_width is a little different */ 113 if ((screen_width = tgetnum("co")) == -1) 114 screen_width = 79; 115 else 116 screen_width -= 1; 117 118 /* get necessary capabilities */ 119 if (tgetstr("cl", NULL) == NULL || tgetstr("cm", NULL) == NULL) { 120 smart_terminal = No; 121 return; 122 } 123 124 /* get the actual screen size with an ioctl, if needed */ 125 /* 126 * This may change screen_width and screen_length, and it always sets 127 * lower_left. 128 */ 129 get_screensize(); 130 131 /* if stdout is not a terminal, pretend we are a dumb terminal */ 132 if (tcgetattr(STDOUT_FILENO, &old_settings) == -1) 133 smart_terminal = No; 134 } 135 136 void 137 init_screen(void) 138 { 139 /* get the old settings for safe keeping */ 140 if (tcgetattr(STDOUT_FILENO, &old_settings) != -1) { 141 /* copy the settings so we can modify them */ 142 new_settings = old_settings; 143 /* turn off ICANON, character echo and tab expansion */ 144 new_settings.c_lflag &= ~(ICANON | ECHO); 145 new_settings.c_oflag &= ~(OXTABS); 146 new_settings.c_cc[VMIN] = 1; 147 new_settings.c_cc[VTIME] = 0; 148 149 (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings); 150 /* remember the erase and kill characters */ 151 ch_erase = old_settings.c_cc[VERASE]; 152 ch_kill = old_settings.c_cc[VKILL]; 153 154 is_a_terminal = Yes; 155 #if 0 156 /* send the termcap initialization string */ 157 putcap(terminal_init); 158 #endif 159 } 160 if (!is_a_terminal) { 161 /* not a terminal at all---consider it dumb */ 162 smart_terminal = No; 163 } 164 165 if (smart_terminal) 166 initscr(); 167 } 168 169 void 170 end_screen(void) 171 { 172 if (smart_terminal) { 173 move(screen_length-1, 0); 174 clrtoeol(); 175 refresh(); 176 endwin(); 177 } 178 if (is_a_terminal) 179 (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &old_settings); 180 } 181 182 void 183 reinit_screen(void) 184 { 185 #if 0 186 /* install our settings if it is a terminal */ 187 if (is_a_terminal) 188 (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings); 189 190 /* send init string */ 191 if (smart_terminal) 192 putcap(terminal_init); 193 #endif 194 } 195 196 void 197 get_screensize(void) 198 { 199 struct winsize ws; 200 201 if (ioctl(STDOUT_FILENO, TIOCGWINSZ, &ws) != -1) { 202 if (ws.ws_row != 0) 203 screen_length = ws.ws_row; 204 if (ws.ws_col != 0) 205 screen_width = ws.ws_col - 1; 206 } 207 } 208 209 void 210 go_home(void) 211 { 212 if (smart_terminal) { 213 move(0, 0); 214 refresh(); 215 } 216 } 217