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