source: trunk/third/top/screen.c @ 9084

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