Sync usage with man page.
[netbsd-mini2440.git] / external / bsd / top / dist / screen.c
blobbf1e50c44ee7b32236944aaacd11b30ed6864228
1 /*
2 * Copyright (c) 1984 through 2008, William LeFebvre
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above
12 * copyright notice, this list of conditions and the following disclaimer
13 * in the documentation and/or other materials provided with the
14 * distribution.
16 * * Neither the name of William LeFebvre nor the names of other
17 * contributors may be used to endorse or promote products derived from
18 * this software without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
34 * Top users/processes display for Unix
35 * Version 3
38 /* This file contains the routines that interface to termcap and stty/gtty.
40 * Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
42 * I put in code to turn on the TOSTOP bit while top was running, but I
43 * didn't really like the results. If you desire it, turn on the
44 * preprocessor variable "TOStop". --wnl
47 #include "os.h"
48 #include "top.h"
50 #if HAVE_CURSES_H && HAVE_TERM_H
51 #include <curses.h>
52 #include <term.h>
53 #else
54 #if HAVE_TERMCAP_H
55 #include <termcap.h>
56 #else
57 #if HAVE_CURSES_H
58 #include <curses.h>
59 #endif
60 #endif
61 #endif
63 #if !HAVE_DECL_TPUTS
64 int tputs(const char *, int, int (*)(int));
65 #endif
66 #if !HAVE_DECL_TGOTO
67 char *tgoto(const char *, int, int);
68 #endif
69 #if !HAVE_DECL_TGETENT
70 int tgetent(const char *, char *);
71 #endif
72 #if !HAVE_DECL_TGETFLAG
73 int tgetflag(const char *);
74 #endif
75 #if !HAVE_DECL_TGETNUM
76 int tgetnum(const char *);
77 #endif
78 #if !HAVE_DECL_TGETSTR
79 char *tgetstr(const char *, char **);
80 #endif
82 #include <sys/ioctl.h>
83 #ifdef CBREAK
84 # include <sgtty.h>
85 # define USE_SGTTY
86 #else
87 # ifdef TCGETA
88 # define USE_TERMIO
89 # include <termio.h>
90 # else
91 # define USE_TERMIOS
92 # include <termios.h>
93 # endif
94 #endif
95 #if defined(USE_TERMIO) || defined(USE_TERMIOS)
96 # ifndef TAB3
97 # ifdef OXTABS
98 # define TAB3 OXTABS
99 # else
100 # define TAB3 0
101 # endif
102 # endif
103 #endif
105 #include "screen.h"
106 #include "boolean.h"
108 #define putcap(str) ((str) != NULL ? (void)tputs(str, 1, putstdout) : (void)0)
110 extern char *myname;
112 char ch_erase;
113 char ch_kill;
114 char ch_werase;
115 char smart_terminal;
116 int screen_length;
117 int screen_width;
119 char PC;
121 static int tc_overstrike;
122 static char termcap_buf[1024];
123 static char string_buffer[1024];
124 static char home[15];
125 static char lower_left[15];
126 static char *tc_clear_line;
127 static char *tc_clear_screen;
128 static char *tc_clear_to_end;
129 static char *tc_cursor_motion;
130 static char *tc_start_standout;
131 static char *tc_end_standout;
132 static char *terminal_init;
133 static char *terminal_end;
135 #ifdef USE_SGTTY
136 static struct sgttyb old_settings;
137 static struct sgttyb new_settings;
138 #endif
139 #ifdef USE_TERMIO
140 static struct termio old_settings;
141 static struct termio new_settings;
142 #endif
143 #ifdef USE_TERMIOS
144 static struct termios old_settings;
145 static struct termios new_settings;
146 #endif
147 static char is_a_terminal = No;
148 #ifdef TOStop
149 static int old_lword;
150 static int new_lword;
151 #endif
153 #define STDIN 0
154 #define STDOUT 1
155 #define STDERR 2
157 /* This has to be defined as a subroutine for tputs (instead of a macro) */
159 static int
160 putstdout(TPUTS_PUTC_ARGTYPE ch)
163 return putchar((int)ch);
166 void
167 screen_getsize()
171 #ifdef TIOCGWINSZ
173 struct winsize ws;
175 if (ioctl (1, TIOCGWINSZ, &ws) != -1)
177 if (ws.ws_row != 0)
179 screen_length = ws.ws_row;
181 if (ws.ws_col != 0)
183 screen_width = ws.ws_col - 1;
187 #else
188 #ifdef TIOCGSIZE
190 struct ttysize ts;
192 if (ioctl (1, TIOCGSIZE, &ts) != -1)
194 if (ts.ts_lines != 0)
196 screen_length = ts.ts_lines;
198 if (ts.ts_cols != 0)
200 screen_width = ts.ts_cols - 1;
204 #endif /* TIOCGSIZE */
205 #endif /* TIOCGWINSZ */
207 (void) strcpy(lower_left, tgoto(tc_cursor_motion, 0, screen_length - 1));
211 screen_readtermcap(int interactive)
214 char *bufptr;
215 char *PCptr;
216 char *term_name;
217 int status;
219 /* set defaults in case we aren't smart */
220 screen_width = MAX_COLS;
221 screen_length = 0;
223 if (interactive == No)
225 /* pretend we have a dumb terminal */
226 smart_terminal = No;
227 return No;
230 /* assume we have a smart terminal until proven otherwise */
231 smart_terminal = Yes;
233 /* get the terminal name */
234 term_name = getenv("TERM");
236 /* if there is no TERM, assume it's a dumb terminal */
237 /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
238 if (term_name == NULL)
240 smart_terminal = No;
241 return No;
244 /* now get the termcap entry */
245 if ((status = tgetent(termcap_buf, term_name)) != 1)
247 if (status == -1)
249 fprintf(stderr, "%s: can't open termcap file\n", myname);
251 else
253 fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
254 myname, term_name);
257 /* pretend it's dumb and proceed */
258 smart_terminal = No;
259 return No;
262 /* "hardcopy" immediately indicates a very stupid terminal */
263 if (tgetflag("hc"))
265 smart_terminal = No;
266 return No;
269 /* set up common terminal capabilities */
270 if ((screen_length = tgetnum("li")) <= 0)
272 screen_length = smart_terminal = 0;
273 return No;
276 /* screen_width is a little different */
277 if ((screen_width = tgetnum("co")) == -1)
279 screen_width = 79;
281 else
283 screen_width -= 1;
286 /* terminals that overstrike need special attention */
287 tc_overstrike = tgetflag("os");
289 /* initialize the pointer into the termcap string buffer */
290 bufptr = string_buffer;
292 /* get "ce", clear to end */
293 if (!tc_overstrike)
295 tc_clear_line = tgetstr("ce", &bufptr);
298 /* get necessary capabilities */
299 if ((tc_clear_screen = tgetstr("cl", &bufptr)) == NULL ||
300 (tc_cursor_motion = tgetstr("cm", &bufptr)) == NULL)
302 smart_terminal = No;
303 return No;
306 /* get some more sophisticated stuff -- these are optional */
307 tc_clear_to_end = tgetstr("cd", &bufptr);
308 terminal_init = tgetstr("ti", &bufptr);
309 terminal_end = tgetstr("te", &bufptr);
310 tc_start_standout = tgetstr("so", &bufptr);
311 tc_end_standout = tgetstr("se", &bufptr);
313 /* pad character */
314 PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
316 /* set convenience strings */
317 (void) strcpy(home, tgoto(tc_cursor_motion, 0, 0));
318 /* (lower_left is set in screen_getsize) */
320 /* get the actual screen size with an ioctl, if needed */
321 /* This may change screen_width and screen_length, and it always
322 sets lower_left. */
323 screen_getsize();
325 /* if stdout is not a terminal, pretend we are a dumb terminal */
326 #ifdef USE_SGTTY
327 if (ioctl(STDOUT, TIOCGETP, &old_settings) == -1)
329 smart_terminal = No;
331 #endif
332 #ifdef USE_TERMIO
333 if (ioctl(STDOUT, TCGETA, &old_settings) == -1)
335 smart_terminal = No;
337 #endif
338 #ifdef USE_TERMIOS
339 if (tcgetattr(STDOUT, &old_settings) == -1)
341 smart_terminal = No;
343 #endif
345 return smart_terminal;
348 void
349 screen_init()
352 /* get the old settings for safe keeping */
353 #ifdef USE_SGTTY
354 if (ioctl(STDOUT, TIOCGETP, &old_settings) != -1)
356 /* copy the settings so we can modify them */
357 new_settings = old_settings;
359 /* turn on CBREAK and turn off character echo and tab expansion */
360 new_settings.sg_flags |= CBREAK;
361 new_settings.sg_flags &= ~(ECHO|XTABS);
362 (void) ioctl(STDOUT, TIOCSETP, &new_settings);
364 /* remember the erase and kill characters */
365 ch_erase = old_settings.sg_erase;
366 ch_kill = old_settings.sg_kill;
367 ch_werase = old_settings.sg_werase;
369 #ifdef TOStop
370 /* get the local mode word */
371 (void) ioctl(STDOUT, TIOCLGET, &old_lword);
373 /* modify it */
374 new_lword = old_lword | LTOSTOP;
375 (void) ioctl(STDOUT, TIOCLSET, &new_lword);
376 #endif
377 /* remember that it really is a terminal */
378 is_a_terminal = Yes;
380 /* send the termcap initialization string */
381 putcap(terminal_init);
383 #endif
384 #ifdef USE_TERMIO
385 if (ioctl(STDOUT, TCGETA, &old_settings) != -1)
387 /* copy the settings so we can modify them */
388 new_settings = old_settings;
390 /* turn off ICANON, character echo and tab expansion */
391 new_settings.c_lflag &= ~(ICANON|ECHO);
392 new_settings.c_oflag &= ~(TAB3);
393 new_settings.c_cc[VMIN] = 1;
394 new_settings.c_cc[VTIME] = 0;
395 (void) ioctl(STDOUT, TCSETA, &new_settings);
397 /* remember the erase and kill characters */
398 ch_erase = old_settings.c_cc[VERASE];
399 ch_kill = old_settings.c_cc[VKILL];
400 ch_werase = old_settings.c_cc[VWERASE];
402 /* remember that it really is a terminal */
403 is_a_terminal = Yes;
405 /* send the termcap initialization string */
406 putcap(terminal_init);
408 #endif
409 #ifdef USE_TERMIOS
410 if (tcgetattr(STDOUT, &old_settings) != -1)
412 /* copy the settings so we can modify them */
413 new_settings = old_settings;
415 /* turn off ICANON, character echo and tab expansion */
416 new_settings.c_lflag &= ~(ICANON|ECHO);
417 new_settings.c_oflag &= ~(TAB3);
418 new_settings.c_cc[VMIN] = 1;
419 new_settings.c_cc[VTIME] = 0;
420 (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
422 /* remember the erase and kill characters */
423 ch_erase = old_settings.c_cc[VERASE];
424 ch_kill = old_settings.c_cc[VKILL];
425 ch_werase = old_settings.c_cc[VWERASE];
427 /* remember that it really is a terminal */
428 is_a_terminal = Yes;
430 /* send the termcap initialization string */
431 putcap(terminal_init);
433 #endif
435 if (!is_a_terminal)
437 /* not a terminal at all---consider it dumb */
438 smart_terminal = No;
442 void
443 screen_end()
446 /* move to the lower left, clear the line and send "te" */
447 if (smart_terminal)
449 putcap(lower_left);
450 putcap(tc_clear_line);
451 fflush(stdout);
452 putcap(terminal_end);
455 /* if we have settings to reset, then do so */
456 if (is_a_terminal)
458 #ifdef USE_SGTTY
459 (void) ioctl(STDOUT, TIOCSETP, &old_settings);
460 #ifdef TOStop
461 (void) ioctl(STDOUT, TIOCLSET, &old_lword);
462 #endif
463 #endif
464 #ifdef USE_TERMIO
465 (void) ioctl(STDOUT, TCSETA, &old_settings);
466 #endif
467 #ifdef USE_TERMIOS
468 (void) tcsetattr(STDOUT, TCSADRAIN, &old_settings);
469 #endif
473 void
474 screen_reinit()
477 /* install our settings if it is a terminal */
478 if (is_a_terminal)
480 #ifdef USE_SGTTY
481 (void) ioctl(STDOUT, TIOCSETP, &new_settings);
482 #ifdef TOStop
483 (void) ioctl(STDOUT, TIOCLSET, &new_lword);
484 #endif
485 #endif
486 #ifdef USE_TERMIO
487 (void) ioctl(STDOUT, TCSETA, &new_settings);
488 #endif
489 #ifdef USE_TERMIOS
490 (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
491 #endif
494 /* send init string */
495 if (smart_terminal)
497 putcap(terminal_init);
501 void
502 screen_move(int x, int y)
505 tputs(tgoto(tc_cursor_motion, x, y), 1, putstdout);
508 void
509 screen_standout(const char *msg)
512 if (smart_terminal)
514 putcap(tc_start_standout);
515 fputs(msg, stdout);
516 putcap(tc_end_standout);
518 else
520 fputs(msg, stdout);
524 void
525 screen_clear(void)
528 if (smart_terminal)
530 putcap(tc_clear_screen);
535 screen_cte(void)
538 if (smart_terminal)
540 if (tc_clear_to_end)
542 putcap(tc_clear_to_end);
543 return(Yes);
546 return(No);
549 void
550 screen_cleareol(int len)
553 int i;
555 if (smart_terminal && !tc_overstrike && len > 0)
557 if (tc_clear_line)
559 putcap(tc_clear_line);
560 return;
562 else
564 i = 0;
565 while (i++ < 0)
567 putchar(' ');
569 i = 0;
570 while (i++ < 0)
572 putchar('\b');
574 return;
577 return;
580 void
581 screen_home(void)
584 if (smart_terminal)
586 putcap(home);