[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.2

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