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

1.8     ! deraadt     1: /*     $OpenBSD: screen.c,v 1.7 2001/07/27 17:13:42 deraadt Exp $      */
1.1       downsj      2:
                      3: /*
                      4:  *  Top users/processes display for Unix
                      5:  *  Version 3
                      6:  *
1.8     ! deraadt     7:  * Copyright (c) 1984, 1989, William LeFebvre, Rice University
        !             8:  * Copyright (c) 1989, 1990, 1992, William LeFebvre, Northwestern University
1.1       downsj      9:  *
1.8     ! deraadt    10:  * Redistribution and use in source and binary forms, with or without
        !            11:  * modification, are permitted provided that the following conditions
        !            12:  * are met:
        !            13:  * 1. Redistributions of source code must retain the above copyright
        !            14:  *    notice, this list of conditions and the following disclaimer.
        !            15:  * 2. Redistributions in binary form must reproduce the above copyright
        !            16:  *    notice, this list of conditions and the following disclaimer in the
        !            17:  *    documentation and/or other materials provided with the distribution.
        !            18:  *
        !            19:  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
        !            20:  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
        !            21:  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
        !            22:  * IN NO EVENT SHALL THE AUTHOR OR HIS EMPLOYER BE LIABLE FOR ANY DIRECT, INDIRECT,
        !            23:  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
        !            24:  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
        !            25:  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
        !            26:  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
        !            27:  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
        !            28:  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1       downsj     29:  */
                     30:
                     31: /*  This file contains the routines that interface to termcap and stty/gtty.
                     32:  *
                     33:  *  Paul Vixie, February 1987: converted to use ioctl() instead of stty/gtty.
                     34:  *
                     35:  *  I put in code to turn on the TOSTOP bit while top was running, but I
                     36:  *  didn't really like the results.  If you desire it, turn on the
                     37:  *  preprocessor variable "TOStop".   --wnl
                     38:  */
                     39:
1.2       downsj     40: #include <sys/types.h>
                     41: #include <sys/ioctl.h>
                     42: #include <stdio.h>
                     43: #include <stdlib.h>
1.3       millert    44: #include <string.h>
1.2       downsj     45: #include <term.h>
                     46: #include <termios.h>
                     47: #include <unistd.h>
                     48:
1.1       downsj     49: #include "top.h"
                     50: #include "screen.h"
                     51: #include "boolean.h"
                     52:
                     53: extern char *myname;
                     54:
                     55: int  overstrike;
                     56: int  screen_length;
                     57: int  screen_width;
                     58: char ch_erase;
                     59: char ch_kill;
                     60: char smart_terminal;
                     61: char PC;
                     62: char string_buffer[1024];
                     63: char home[15];
                     64: char lower_left[15];
                     65: char *clear_line;
1.2       downsj     66: char *clear_scr;
1.1       downsj     67: char *clear_to_end;
                     68: char *cursor_motion;
                     69: char *start_standout;
                     70: char *end_standout;
                     71: char *terminal_init;
                     72: char *terminal_end;
                     73: short ospeed;
                     74:
                     75: static struct termios old_settings;
                     76: static struct termios new_settings;
1.2       downsj     77:
1.1       downsj     78: static char is_a_terminal = No;
                     79:
1.2       downsj     80: void init_termcap(interactive)
1.1       downsj     81:
                     82: int interactive;
                     83:
                     84: {
                     85:     char *bufptr;
                     86:     char *PCptr;
                     87:     char *term_name;
                     88:     int status;
                     89:
                     90:     /* set defaults in case we aren't smart */
                     91:     screen_width = MAX_COLS;
                     92:     screen_length = 0;
                     93:
                     94:     if (!interactive)
                     95:     {
                     96:        /* pretend we have a dumb terminal */
                     97:        smart_terminal = No;
                     98:        return;
                     99:     }
                    100:
                    101:     /* assume we have a smart terminal until proven otherwise */
                    102:     smart_terminal = Yes;
                    103:
                    104:     /* get the terminal name */
                    105:     term_name = getenv("TERM");
                    106:
                    107:     /* if there is no TERM, assume it's a dumb terminal */
                    108:     /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
                    109:     if (term_name == NULL)
                    110:     {
                    111:        smart_terminal = No;
                    112:        return;
                    113:     }
                    114:
                    115:     /* now get the termcap entry */
1.2       downsj    116:     if ((status = tgetent(NULL, term_name)) != 1)
1.1       downsj    117:     {
                    118:        if (status == -1)
                    119:        {
                    120:            fprintf(stderr, "%s: can't open termcap file\n", myname);
                    121:        }
                    122:        else
                    123:        {
                    124:            fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
                    125:                    myname, term_name);
                    126:        }
                    127:
                    128:        /* pretend it's dumb and proceed */
                    129:        smart_terminal = No;
                    130:        return;
                    131:     }
                    132:
                    133:     /* "hardcopy" immediately indicates a very stupid terminal */
                    134:     if (tgetflag("hc"))
                    135:     {
                    136:        smart_terminal = No;
                    137:        return;
                    138:     }
                    139:
                    140:     /* set up common terminal capabilities */
1.4       weingart  141:     if ((screen_length = tgetnum("li")) <= Header_lines)
1.1       downsj    142:     {
                    143:        screen_length = smart_terminal = 0;
                    144:        return;
                    145:     }
                    146:
                    147:     /* screen_width is a little different */
                    148:     if ((screen_width = tgetnum("co")) == -1)
                    149:     {
                    150:        screen_width = 79;
                    151:     }
                    152:     else
                    153:     {
                    154:        screen_width -= 1;
                    155:     }
                    156:
                    157:     /* terminals that overstrike need special attention */
                    158:     overstrike = tgetflag("os");
                    159:
                    160:     /* initialize the pointer into the termcap string buffer */
                    161:     bufptr = string_buffer;
                    162:
                    163:     /* get "ce", clear to end */
                    164:     if (!overstrike)
                    165:     {
                    166:        clear_line = tgetstr("ce", &bufptr);
                    167:     }
                    168:
                    169:     /* get necessary capabilities */
1.2       downsj    170:     if ((clear_scr  = tgetstr("cl", &bufptr)) == NULL ||
1.1       downsj    171:        (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
                    172:     {
                    173:        smart_terminal = No;
                    174:        return;
                    175:     }
                    176:
                    177:     /* get some more sophisticated stuff -- these are optional */
                    178:     clear_to_end   = tgetstr("cd", &bufptr);
                    179:     terminal_init  = tgetstr("ti", &bufptr);
                    180:     terminal_end   = tgetstr("te", &bufptr);
                    181:     start_standout = tgetstr("so", &bufptr);
                    182:     end_standout   = tgetstr("se", &bufptr);
                    183:
                    184:     /* pad character */
                    185:     PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
                    186:
                    187:     /* set convenience strings */
1.5       bitblt    188:     (void) strncpy(home, tgoto(cursor_motion, 0, 0), sizeof (home) -1);
                    189:     home[sizeof (home) -1] = 0;
1.1       downsj    190:     /* (lower_left is set in get_screensize) */
                    191:
                    192:     /* get the actual screen size with an ioctl, if needed */
                    193:     /* This may change screen_width and screen_length, and it always
                    194:        sets lower_left. */
                    195:     get_screensize();
                    196:
                    197:     /* if stdout is not a terminal, pretend we are a dumb terminal */
1.2       downsj    198:     if (tcgetattr(STDOUT_FILENO, &old_settings) == -1)
1.1       downsj    199:     {
                    200:        smart_terminal = No;
                    201:     }
                    202: }
                    203:
1.2       downsj    204: void init_screen()
1.1       downsj    205:
                    206: {
                    207:     /* get the old settings for safe keeping */
1.2       downsj    208:     if (tcgetattr(STDOUT_FILENO, &old_settings) != -1)
1.1       downsj    209:     {
                    210:        /* copy the settings so we can modify them */
                    211:        new_settings = old_settings;
                    212:
                    213:        /* turn off ICANON, character echo and tab expansion */
                    214:        new_settings.c_lflag &= ~(ICANON|ECHO);
1.2       downsj    215:        new_settings.c_oflag &= ~(OXTABS);
1.1       downsj    216:        new_settings.c_cc[VMIN] = 1;
                    217:        new_settings.c_cc[VTIME] = 0;
1.2       downsj    218:        (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
1.1       downsj    219:
                    220:        /* remember the erase and kill characters */
                    221:        ch_erase = old_settings.c_cc[VERASE];
                    222:        ch_kill  = old_settings.c_cc[VKILL];
                    223:
                    224:        /* remember that it really is a terminal */
                    225:        is_a_terminal = Yes;
                    226:
                    227:        /* send the termcap initialization string */
                    228:        putcap(terminal_init);
                    229:     }
                    230:
                    231:     if (!is_a_terminal)
                    232:     {
                    233:        /* not a terminal at all---consider it dumb */
                    234:        smart_terminal = No;
                    235:     }
                    236: }
                    237:
1.2       downsj    238: void end_screen()
1.1       downsj    239:
                    240: {
                    241:     /* move to the lower left, clear the line and send "te" */
                    242:     if (smart_terminal)
                    243:     {
                    244:        putcap(lower_left);
                    245:        putcap(clear_line);
                    246:        fflush(stdout);
                    247:        putcap(terminal_end);
                    248:     }
                    249:
                    250:     /* if we have settings to reset, then do so */
                    251:     if (is_a_terminal)
                    252:     {
1.2       downsj    253:        (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &old_settings);
1.1       downsj    254:     }
                    255: }
                    256:
1.2       downsj    257: void reinit_screen()
1.1       downsj    258:
                    259: {
                    260:     /* install our settings if it is a terminal */
                    261:     if (is_a_terminal)
                    262:     {
1.2       downsj    263:        (void) tcsetattr(STDOUT_FILENO, TCSADRAIN, &new_settings);
1.1       downsj    264:     }
                    265:
                    266:     /* send init string */
                    267:     if (smart_terminal)
                    268:     {
                    269:        putcap(terminal_init);
                    270:     }
                    271: }
                    272:
1.2       downsj    273: void get_screensize()
1.1       downsj    274:
                    275: {
                    276:     struct winsize ws;
                    277:
1.6       downsj    278:     if (ioctl (STDOUT_FILENO, TIOCGWINSZ, &ws) != -1)
1.1       downsj    279:     {
                    280:        if (ws.ws_row != 0)
                    281:        {
                    282:            screen_length = ws.ws_row;
                    283:        }
                    284:        if (ws.ws_col != 0)
                    285:        {
                    286:            screen_width = ws.ws_col - 1;
                    287:        }
                    288:     }
                    289:
1.5       bitblt    290:     (void) strncpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1),
                    291:                   sizeof (lower_left) -1);
                    292:     lower_left[sizeof(lower_left) -1] = 0;
1.1       downsj    293: }
                    294:
1.2       downsj    295: void standout(msg)
1.1       downsj    296:
                    297: char *msg;
                    298:
                    299: {
                    300:     if (smart_terminal)
                    301:     {
                    302:        putcap(start_standout);
1.7       deraadt   303:        if (fputs(msg, stdout) == EOF)
                    304:            exit(1);
1.1       downsj    305:        putcap(end_standout);
                    306:     }
                    307:     else
                    308:     {
1.7       deraadt   309:        if (fputs(msg, stdout) == EOF)
                    310:            exit(1);
1.1       downsj    311:     }
                    312: }
                    313:
1.2       downsj    314: void clear()
1.1       downsj    315:
                    316: {
                    317:     if (smart_terminal)
                    318:     {
1.2       downsj    319:        putcap(clear_scr);
1.1       downsj    320:     }
                    321: }
                    322:
1.2       downsj    323: int clear_eol(len)
1.1       downsj    324:
                    325: int len;
                    326:
                    327: {
                    328:     if (smart_terminal && !overstrike && len > 0)
                    329:     {
                    330:        if (clear_line)
                    331:        {
                    332:            putcap(clear_line);
                    333:            return(0);
                    334:        }
                    335:        else
                    336:        {
                    337:            while (len-- > 0)
                    338:            {
1.7       deraadt   339:                if (putchar(' ') == EOF)
                    340:                        exit(1);
1.1       downsj    341:            }
                    342:            return(1);
                    343:        }
                    344:     }
                    345:     return(-1);
                    346: }
                    347:
1.2       downsj    348: void go_home()
1.1       downsj    349:
                    350: {
                    351:     if (smart_terminal)
                    352:     {
                    353:        putcap(home);
                    354:     }
                    355: }
                    356:
                    357: /* This has to be defined as a subroutine for tputs (instead of a macro) */
                    358:
1.2       downsj    359: int putstdout(ch)
1.1       downsj    360:
1.2       downsj    361: int ch;
1.1       downsj    362:
                    363: {
1.7       deraadt   364:     int ret;
                    365:
                    366:     ret = putchar(ch);
                    367:     if (ret == EOF)
                    368:        exit(1);
                    369:     return (ret);
1.1       downsj    370: }
                    371: