]> CyberLeo.Net >> Repos - FreeBSD/stable/10.git/blob - contrib/top/screen.c
MFC r368207,368607:
[FreeBSD/stable/10.git] / contrib / 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 "os.h"
24 #include "top.h"
25
26 #include <sys/ioctl.h>
27 #ifdef CBREAK
28 # include <sgtty.h>
29 # define SGTTY
30 #else
31 # ifdef TCGETA
32 #  define TERMIO
33 #  include <termio.h>
34 # else
35 #  define TERMIOS
36 #  include <termios.h>
37 # endif
38 #endif
39 #if defined(TERMIO) || defined(TERMIOS)
40 # ifndef TAB3
41 #  ifdef OXTABS
42 #   define TAB3 OXTABS
43 #  else
44 #   define TAB3 0
45 #  endif
46 # endif
47 #endif
48 #include "screen.h"
49 #include "boolean.h"
50
51 extern char *myname;
52
53
54 int  overstrike;
55 int  screen_length;
56 int  screen_width;
57 char ch_erase;
58 char ch_kill;
59 char smart_terminal;
60 char PC;
61 char *tgetstr();
62 char *tgoto();
63 char termcap_buf[1024];
64 char string_buffer[1024];
65 char home[15];
66 char lower_left[15];
67 char *clear_line;
68 char *clear_screen;
69 char *clear_to_end;
70 char *cursor_motion;
71 char *start_standout;
72 char *end_standout;
73 char *terminal_init;
74 char *terminal_end;
75
76 #ifdef SGTTY
77 static struct sgttyb old_settings;
78 static struct sgttyb new_settings;
79 #endif
80 #ifdef TERMIO
81 static struct termio old_settings;
82 static struct termio new_settings;
83 #endif
84 #ifdef TERMIOS
85 static struct termios old_settings;
86 static struct termios new_settings;
87 #endif
88 static char is_a_terminal = No;
89 #ifdef TOStop
90 static int old_lword;
91 static int new_lword;
92 #endif
93
94 #define STDIN   0
95 #define STDOUT  1
96 #define STDERR  2
97
98 void
99 init_termcap(interactive)
100
101 int interactive;
102
103 {
104     char *bufptr;
105     char *PCptr;
106     char *term_name;
107     char *getenv();
108     int status;
109
110     /* set defaults in case we aren't smart */
111     screen_width = MAX_COLS;
112     screen_length = 0;
113
114     if (!interactive)
115     {
116         /* pretend we have a dumb terminal */
117         smart_terminal = No;
118         return;
119     }
120
121     /* assume we have a smart terminal until proven otherwise */
122     smart_terminal = Yes;
123
124     /* get the terminal name */
125     term_name = getenv("TERM");
126
127     /* if there is no TERM, assume it's a dumb terminal */
128     /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
129     if (term_name == NULL)
130     {
131         smart_terminal = No;
132         return;
133     }
134
135     /* now get the termcap entry */
136     if ((status = tgetent(termcap_buf, term_name)) != 1)
137     {
138         if (status == -1)
139         {
140             fprintf(stderr, "%s: can't open termcap file\n", myname);
141         }
142         else
143         {
144             fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
145                     myname, term_name);
146         }
147
148         /* pretend it's dumb and proceed */
149         smart_terminal = No;
150         return;
151     }
152
153     /* "hardcopy" immediately indicates a very stupid terminal */
154     if (tgetflag("hc"))
155     {
156         smart_terminal = No;
157         return;
158     }
159
160     /* set up common terminal capabilities */
161     if ((screen_length = tgetnum("li")) <= 0)
162     {
163         screen_length = smart_terminal = 0;
164         return;
165     }
166
167     /* screen_width is a little different */
168     if ((screen_width = tgetnum("co")) == -1)
169     {
170         screen_width = 79;
171     }
172     else
173     {
174         screen_width -= 1;
175     }
176
177     /* terminals that overstrike need special attention */
178     overstrike = tgetflag("os");
179
180     /* initialize the pointer into the termcap string buffer */
181     bufptr = string_buffer;
182
183     /* get "ce", clear to end */
184     if (!overstrike)
185     {
186         clear_line = tgetstr("ce", &bufptr);
187     }
188
189     /* get necessary capabilities */
190     if ((clear_screen  = tgetstr("cl", &bufptr)) == NULL ||
191         (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
192     {
193         smart_terminal = No;
194         return;
195     }
196
197     /* get some more sophisticated stuff -- these are optional */
198     clear_to_end   = tgetstr("cd", &bufptr);
199     terminal_init  = tgetstr("ti", &bufptr);
200     terminal_end   = tgetstr("te", &bufptr);
201     start_standout = tgetstr("so", &bufptr);
202     end_standout   = tgetstr("se", &bufptr);
203
204     /* pad character */
205     PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
206
207     /* set convenience strings */
208     (void) strncpy(home, tgoto(cursor_motion, 0, 0), sizeof(home) - 1);
209     home[sizeof(home) - 1] = '\0';
210     /* (lower_left is set in get_screensize) */
211
212     /* get the actual screen size with an ioctl, if needed */
213     /* This may change screen_width and screen_length, and it always
214        sets lower_left. */
215     get_screensize();
216
217     /* if stdout is not a terminal, pretend we are a dumb terminal */
218 #ifdef SGTTY
219     if (ioctl(STDOUT, TIOCGETP, &old_settings) == -1)
220     {
221         smart_terminal = No;
222     }
223 #endif
224 #ifdef TERMIO
225     if (ioctl(STDOUT, TCGETA, &old_settings) == -1)
226     {
227         smart_terminal = No;
228     }
229 #endif
230 #ifdef TERMIOS
231     if (tcgetattr(STDOUT, &old_settings) == -1)
232     {
233         smart_terminal = No;
234     }
235 #endif
236 }
237
238 void
239 init_screen()
240
241 {
242     /* get the old settings for safe keeping */
243 #ifdef SGTTY
244     if (ioctl(STDOUT, TIOCGETP, &old_settings) != -1)
245     {
246         /* copy the settings so we can modify them */
247         new_settings = old_settings;
248
249         /* turn on CBREAK and turn off character echo and tab expansion */
250         new_settings.sg_flags |= CBREAK;
251         new_settings.sg_flags &= ~(ECHO|XTABS);
252         (void) ioctl(STDOUT, TIOCSETP, &new_settings);
253
254         /* remember the erase and kill characters */
255         ch_erase = old_settings.sg_erase;
256         ch_kill  = old_settings.sg_kill;
257
258 #ifdef TOStop
259         /* get the local mode word */
260         (void) ioctl(STDOUT, TIOCLGET, &old_lword);
261
262         /* modify it */
263         new_lword = old_lword | LTOSTOP;
264         (void) ioctl(STDOUT, TIOCLSET, &new_lword);
265 #endif
266         /* remember that it really is a terminal */
267         is_a_terminal = Yes;
268
269         /* send the termcap initialization string */
270         putcap(terminal_init);
271     }
272 #endif
273 #ifdef TERMIO
274     if (ioctl(STDOUT, TCGETA, &old_settings) != -1)
275     {
276         /* copy the settings so we can modify them */
277         new_settings = old_settings;
278
279         /* turn off ICANON, character echo and tab expansion */
280         new_settings.c_lflag &= ~(ICANON|ECHO);
281         new_settings.c_oflag &= ~(TAB3);
282         new_settings.c_cc[VMIN] = 1;
283         new_settings.c_cc[VTIME] = 0;
284         (void) ioctl(STDOUT, TCSETA, &new_settings);
285
286         /* remember the erase and kill characters */
287         ch_erase = old_settings.c_cc[VERASE];
288         ch_kill  = old_settings.c_cc[VKILL];
289
290         /* remember that it really is a terminal */
291         is_a_terminal = Yes;
292
293         /* send the termcap initialization string */
294         putcap(terminal_init);
295     }
296 #endif
297 #ifdef TERMIOS
298     if (tcgetattr(STDOUT, &old_settings) != -1)
299     {
300         /* copy the settings so we can modify them */
301         new_settings = old_settings;
302
303         /* turn off ICANON, character echo and tab expansion */
304         new_settings.c_lflag &= ~(ICANON|ECHO);
305         new_settings.c_oflag &= ~(TAB3);
306         new_settings.c_cc[VMIN] = 1;
307         new_settings.c_cc[VTIME] = 0;
308         (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
309
310         /* remember the erase and kill characters */
311         ch_erase = old_settings.c_cc[VERASE];
312         ch_kill  = old_settings.c_cc[VKILL];
313
314         /* remember that it really is a terminal */
315         is_a_terminal = Yes;
316
317         /* send the termcap initialization string */
318         putcap(terminal_init);
319     }
320 #endif
321
322     if (!is_a_terminal)
323     {
324         /* not a terminal at all---consider it dumb */
325         smart_terminal = No;
326     }
327 }
328
329 void
330 end_screen()
331
332 {
333     /* move to the lower left, clear the line and send "te" */
334     if (smart_terminal)
335     {
336         putcap(lower_left);
337         putcap(clear_line);
338         fflush(stdout);
339         putcap(terminal_end);
340     }
341
342     /* if we have settings to reset, then do so */
343     if (is_a_terminal)
344     {
345 #ifdef SGTTY
346         (void) ioctl(STDOUT, TIOCSETP, &old_settings);
347 #ifdef TOStop
348         (void) ioctl(STDOUT, TIOCLSET, &old_lword);
349 #endif
350 #endif
351 #ifdef TERMIO
352         (void) ioctl(STDOUT, TCSETA, &old_settings);
353 #endif
354 #ifdef TERMIOS
355         (void) tcsetattr(STDOUT, TCSADRAIN, &old_settings);
356 #endif
357     }
358 }
359
360 void
361 reinit_screen()
362
363 {
364     /* install our settings if it is a terminal */
365     if (is_a_terminal)
366     {
367 #ifdef SGTTY
368         (void) ioctl(STDOUT, TIOCSETP, &new_settings);
369 #ifdef TOStop
370         (void) ioctl(STDOUT, TIOCLSET, &new_lword);
371 #endif
372 #endif
373 #ifdef TERMIO
374         (void) ioctl(STDOUT, TCSETA, &new_settings);
375 #endif
376 #ifdef TERMIOS
377         (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
378 #endif
379     }
380
381     /* send init string */
382     if (smart_terminal)
383     {
384         putcap(terminal_init);
385     }
386 }
387
388 void
389 get_screensize()
390
391 {
392
393 #ifdef TIOCGWINSZ
394
395     struct winsize ws;
396
397     if (ioctl (1, TIOCGWINSZ, &ws) != -1)
398     {
399         if (ws.ws_row != 0)
400         {
401             screen_length = ws.ws_row;
402         }
403         if (ws.ws_col != 0)
404         {
405             screen_width = ws.ws_col - 1;
406         }
407     }
408
409 #else
410 #ifdef TIOCGSIZE
411
412     struct ttysize ts;
413
414     if (ioctl (1, TIOCGSIZE, &ts) != -1)
415     {
416         if (ts.ts_lines != 0)
417         {
418             screen_length = ts.ts_lines;
419         }
420         if (ts.ts_cols != 0)
421         {
422             screen_width = ts.ts_cols - 1;
423         }
424     }
425
426 #endif /* TIOCGSIZE */
427 #endif /* TIOCGWINSZ */
428
429     (void) strncpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
430         sizeof(lower_left) - 1);
431     lower_left[sizeof(lower_left) - 1] = '\0';
432 }
433
434 void
435 standout(msg)
436
437 char *msg;
438
439 {
440     if (smart_terminal)
441     {
442         putcap(start_standout);
443         fputs(msg, stdout);
444         putcap(end_standout);
445     }
446     else
447     {
448         fputs(msg, stdout);
449     }
450 }
451
452 void
453 clear()
454
455 {
456     if (smart_terminal)
457     {
458         putcap(clear_screen);
459     }
460 }
461
462 int
463 clear_eol(len)
464
465 int len;
466
467 {
468     if (smart_terminal && !overstrike && len > 0)
469     {
470         if (clear_line)
471         {
472             putcap(clear_line);
473             return(0);
474         }
475         else
476         {
477             while (len-- > 0)
478             {
479                 putchar(' ');
480             }
481             return(1);
482         }
483     }
484     return(-1);
485 }
486
487 void
488 go_home()
489
490 {
491     if (smart_terminal)
492     {
493         putcap(home);
494     }
495 }
496
497 /* This has to be defined as a subroutine for tputs (instead of a macro) */
498
499 void
500 putstdout(ch)
501
502 char ch;
503
504 {
505     putchar(ch);
506 }
507