[BACK]Return to screen.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / top

Annotation of src/usr.bin/top/screen.c, Revision 1.5

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