home *** CD-ROM | disk | FTP | other *** search
/ Big Green CD 8 / BGCD_8_Dev.iso / NEXTSTEP / UNIX / Utilities / top-0.5-MI / screen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-15  |  9.4 KB  |  495 lines

  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.  
  49. extern char *myname;
  50.  
  51. int putstdout();
  52.  
  53. int  overstrike;
  54. int  screen_length;
  55. int  screen_width;
  56. char ch_erase;
  57. char ch_kill;
  58. char smart_terminal;
  59. char PC;
  60. char *tgetstr();
  61. char *tgoto();
  62. char termcap_buf[1024];
  63. char string_buffer[1024];
  64. char home[15];
  65. char lower_left[15];
  66. char *clear_line;
  67. char *clear_screen;
  68. char *clear_to_end;
  69. char *cursor_motion;
  70. char *start_standout;
  71. char *end_standout;
  72. char *terminal_init;
  73. char *terminal_end;
  74. short ospeed;
  75.  
  76. #ifdef SGTTY
  77. static struct sgttyb old_settings;
  78. static struct sgttyb new_settings;
  79. #endif
  80. #ifdef TERMIO
  81. static struct termio old_settings;
  82. static struct termio new_settings;
  83. #endif
  84. #ifdef TERMIOS
  85. static struct termios old_settings;
  86. static struct termios new_settings;
  87. #endif
  88. static char is_a_terminal = No;
  89. #ifdef TOStop
  90. static int old_lword;
  91. static int new_lword;
  92. #endif
  93.  
  94. #define    STDIN    0
  95. #define    STDOUT    1
  96. #define    STDERR    2
  97.  
  98. init_termcap(interactive)
  99.  
  100. int 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.  
  236. init_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.  
  326. end_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.  
  356. reinit_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.  
  383. get_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.  
  426. standout(msg)
  427.  
  428. char *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.  
  443. clear()
  444.  
  445. {
  446.     if (smart_terminal)
  447.     {
  448.     putcap(clear_screen);
  449.     }
  450. }
  451.  
  452. clear_eol(len)
  453.  
  454. int 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.  
  476. go_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.  
  487. putstdout(ch)
  488.  
  489. char ch;
  490.  
  491. {
  492.     putchar(ch);
  493. }
  494.  
  495.