home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume27 / top-3.2 / part02 / screen.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-08  |  9.0 KB  |  468 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.  
  23. #include <sys/ioctl.h>
  24. #ifdef CBREAK
  25. # include <sgtty.h>
  26. # define SGTTY
  27. #else
  28. # ifdef TCGETA
  29. #  define TERMIO
  30. #  include <termio.h>
  31. # else
  32. #  define TERMIOS
  33. #  include <termios.h>
  34. # endif
  35. #endif
  36. #if defined(TERMIO) || defined(TERMIOS)
  37. # ifndef TAB3
  38. #  ifdef OXTABS
  39. #   define TAB3 OXTABS
  40. #  else
  41. #   define TAB3 0
  42. #  endif
  43. # endif
  44. #endif
  45. #include "screen.h"
  46. #include "boolean.h"
  47.  
  48. extern char *myname;
  49.  
  50. int putstdout();
  51.  
  52. int  overstrike;
  53. int  screen_length;
  54. int  screen_width;
  55. char ch_erase;
  56. char ch_kill;
  57. char smart_terminal;
  58. char PC;
  59. char *tgetstr();
  60. char *tgoto();
  61. char termcap_buf[1024];
  62. char string_buffer[1024];
  63. char home[15];
  64. char lower_left[15];
  65. char *clear_line;
  66. char *clear_screen;
  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. #ifdef SGTTY
  76. static struct sgttyb old_settings;
  77. static struct sgttyb new_settings;
  78. #endif
  79. #ifdef TERMIO
  80. static struct termio old_settings;
  81. static struct termio new_settings;
  82. #endif
  83. #ifdef TERMIOS
  84. static struct termios old_settings;
  85. static struct termios new_settings;
  86. #endif
  87. static char is_a_terminal = No;
  88. #ifdef TOStop
  89. static int old_lword;
  90. static int new_lword;
  91. #endif
  92.  
  93. #define    STDIN    0
  94. #define    STDOUT    1
  95. #define    STDERR    2
  96.  
  97. init_termcap()
  98.  
  99. {
  100.     char *bufptr;
  101.     char *PCptr;
  102.     char *term_name;
  103.     char *getenv();
  104.     int status;
  105.  
  106.     /* assume we have a smart terminal until proven otherwise */
  107.     smart_terminal = Yes;
  108.  
  109.     /* get the terminal name */
  110.     term_name = getenv("TERM");
  111.  
  112.     /* if there is no TERM, assume it's a dumb terminal */
  113.     /* patch courtesy of Sam Horrocks at telegraph.ics.uci.edu */
  114.     if (term_name == NULL)
  115.     {
  116.     smart_terminal = No;
  117.     return;
  118.     }
  119.  
  120.     /* now get the termcap entry */
  121.     if ((status = tgetent(termcap_buf, term_name)) != 1)
  122.     {
  123.     if (status == -1)
  124.     {
  125.         fprintf(stderr, "%s: can't open termcap file\n", myname);
  126.     }
  127.     else
  128.     {
  129.         fprintf(stderr, "%s: no termcap entry for a `%s' terminal\n",
  130.             myname, term_name);
  131.     }
  132.  
  133.     /* pretend it's dumb and proceed */
  134.     smart_terminal = No;
  135.     return;
  136.     }
  137.  
  138.     /* "hardcopy" immediately indicates a very stupid terminal */
  139.     if (tgetflag("hc"))
  140.     {
  141.     smart_terminal = No;
  142.     return;
  143.     }
  144.  
  145.     /* set up common terminal capabilities */
  146.     if ((screen_length = tgetnum("li")) <= 0)
  147.     {
  148.     screen_length = smart_terminal = 0;
  149.     return;
  150.     }
  151.  
  152.     /* screen_width is a little different */
  153.     if ((screen_width = tgetnum("co")) == -1)
  154.     {
  155.     screen_width = 79;
  156.     }
  157.     else
  158.     {
  159.     screen_width -= 1;
  160.     }
  161.  
  162. #ifdef TIOCGWINSZ
  163.     {
  164.     struct winsize ws;
  165.  
  166.     if (ioctl (1, TIOCGWINSZ, &ws) != -1)
  167.     {
  168.         if (ws.ws_row != 0)
  169.         {
  170.         screen_length = ws.ws_row;
  171.         }
  172.         if (ws.ws_col != 0)
  173.         {
  174.         screen_width = ws.ws_col - 1;
  175.         }
  176.     }
  177.     }
  178. #else
  179. #ifdef TIOCGSIZE
  180.     {
  181.     struct ttysize ts;
  182.  
  183.     if (ioctl (1, TIOCGSIZE, &ts) != -1)
  184.     {
  185.         if (ts.ts_lines != 0)
  186.         {
  187.         screen_length = ts.ts_lines;
  188.         }
  189.         if (ts.ts_cols != 0)
  190.         {
  191.         screen_width = ts.ts_cols - 1;
  192.         }
  193.     }
  194.     }
  195. #endif /* TIOCGSIZE */
  196. #endif /* TIOCGWINSZ */
  197.  
  198.     /* terminals that overstrike need special attention */
  199.     overstrike = tgetflag("os");
  200.  
  201.     /* initialize the pointer into the termcap string buffer */
  202.     bufptr = string_buffer;
  203.  
  204.     /* get "ce", clear to end */
  205.     if (!overstrike)
  206.     {
  207.     clear_line = tgetstr("ce", &bufptr);
  208.     }
  209.  
  210.     /* get necessary capabilities */
  211.     if ((clear_screen  = tgetstr("cl", &bufptr)) == NULL ||
  212.     (cursor_motion = tgetstr("cm", &bufptr)) == NULL)
  213.     {
  214.     smart_terminal = No;
  215.     return;
  216.     }
  217.  
  218.     /* get some more sophisticated stuff -- these are optional */
  219.     clear_to_end   = tgetstr("cd", &bufptr);
  220.     terminal_init  = tgetstr("ti", &bufptr);
  221.     terminal_end   = tgetstr("te", &bufptr);
  222.     start_standout = tgetstr("so", &bufptr);
  223.     end_standout   = tgetstr("se", &bufptr);
  224.  
  225.     /* pad character */
  226.     PC = (PCptr = tgetstr("pc", &bufptr)) ? *PCptr : 0;
  227.  
  228.     /* set convenience strings */
  229.     (void) strcpy(home, tgoto(cursor_motion, 0, 0));
  230.     (void) strcpy(lower_left, tgoto(cursor_motion, 0, screen_length - 1));
  231.  
  232.     /* if stdout is not a terminal, pretend we are a dumb terminal */
  233. #ifdef SGTTY
  234.     if (ioctl(STDOUT, TIOCGETP, &old_settings) == -1)
  235.     {
  236.     smart_terminal = No;
  237.     }
  238. #endif
  239. #ifdef TERMIO
  240.     if (ioctl(STDOUT, TCGETA, &old_settings) == -1)
  241.     {
  242.     smart_terminal = No;
  243.     }
  244. #endif
  245. #ifdef TERMIOS
  246.     if (tcgetattr(STDOUT, &old_settings) == -1)
  247.     {
  248.     smart_terminal = No;
  249.     }
  250. #endif
  251. }
  252.  
  253. init_screen()
  254.  
  255. {
  256.     /* get the old settings for safe keeping */
  257. #ifdef SGTTY
  258.     if (ioctl(STDOUT, TIOCGETP, &old_settings) != -1)
  259.     {
  260.     /* copy the settings so we can modify them */
  261.     new_settings = old_settings;
  262.  
  263.     /* turn on CBREAK and turn off character echo and tab expansion */
  264.     new_settings.sg_flags |= CBREAK;
  265.     new_settings.sg_flags &= ~(ECHO|XTABS);
  266.     (void) ioctl(STDOUT, TIOCSETP, &new_settings);
  267.  
  268.     /* remember the erase and kill characters */
  269.     ch_erase = old_settings.sg_erase;
  270.     ch_kill  = old_settings.sg_kill;
  271.  
  272. #ifdef TOStop
  273.     /* get the local mode word */
  274.     (void) ioctl(STDOUT, TIOCLGET, &old_lword);
  275.  
  276.     /* modify it */
  277.     new_lword = old_lword | LTOSTOP;
  278.     (void) ioctl(STDOUT, TIOCLSET, &new_lword);
  279. #endif
  280.     /* remember that it really is a terminal */
  281.     is_a_terminal = Yes;
  282.  
  283.     /* send the termcap initialization string */
  284.     putcap(terminal_init);
  285.     }
  286. #endif
  287. #ifdef TERMIO
  288.     if (ioctl(STDOUT, TCGETA, &old_settings) != -1)
  289.     {
  290.     /* copy the settings so we can modify them */
  291.     new_settings = old_settings;
  292.  
  293.     /* turn off ICANON, character echo and tab expansion */
  294.     new_settings.c_lflag &= ~(ICANON|ECHO);
  295.     new_settings.c_oflag &= ~(TAB3);
  296.     new_settings.c_cc[VMIN] = 1;
  297.     new_settings.c_cc[VTIME] = 0;
  298.     (void) ioctl(STDOUT, TCSETA, &new_settings);
  299.  
  300.     /* remember the erase and kill characters */
  301.     ch_erase = old_settings.c_cc[VERASE];
  302.     ch_kill  = old_settings.c_cc[VKILL];
  303.  
  304.     /* remember that it really is a terminal */
  305.     is_a_terminal = Yes;
  306.  
  307.     /* send the termcap initialization string */
  308.     putcap(terminal_init);
  309.     }
  310. #endif
  311. #ifdef TERMIOS
  312.     if (tcgetattr(STDOUT, &old_settings) != -1)
  313.     {
  314.     /* copy the settings so we can modify them */
  315.     new_settings = old_settings;
  316.  
  317.     /* turn off ICANON, character echo and tab expansion */
  318.     new_settings.c_lflag &= ~(ICANON|ECHO);
  319.     new_settings.c_oflag &= ~(TAB3);
  320.     new_settings.c_cc[VMIN] = 1;
  321.     new_settings.c_cc[VTIME] = 0;
  322.     (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
  323.  
  324.     /* remember the erase and kill characters */
  325.     ch_erase = old_settings.c_cc[VERASE];
  326.     ch_kill  = old_settings.c_cc[VKILL];
  327.  
  328.     /* remember that it really is a terminal */
  329.     is_a_terminal = Yes;
  330.  
  331.     /* send the termcap initialization string */
  332.     putcap(terminal_init);
  333.     }
  334. #endif
  335.  
  336.     if (!is_a_terminal)
  337.     {
  338.     /* not a terminal at all---consider it dumb */
  339.     smart_terminal = No;
  340.     }
  341. }
  342.  
  343. end_screen()
  344.  
  345. {
  346.     /* move to the lower left, clear the line and send "te" */
  347.     if (smart_terminal)
  348.     {
  349.     putcap(lower_left);
  350.     putcap(clear_line);
  351.     putcap(terminal_end);
  352.     }
  353.  
  354.     /* if we have settings to reset, then do so */
  355.     if (is_a_terminal)
  356.     {
  357. #ifdef SGTTY
  358.     (void) ioctl(STDOUT, TIOCSETP, &old_settings);
  359. #ifdef TOStop
  360.     (void) ioctl(STDOUT, TIOCLSET, &old_lword);
  361. #endif
  362. #endif
  363. #ifdef TERMIO
  364.     (void) ioctl(STDOUT, TCSETA, &old_settings);
  365. #endif
  366. #ifdef TERMIOS
  367.     (void) tcsetattr(STDOUT, TCSADRAIN, &old_settings);
  368. #endif
  369.     }
  370. }
  371.  
  372. reinit_screen()
  373.  
  374. {
  375.     /* install our settings if it is a terminal */
  376.     if (is_a_terminal)
  377.     {
  378. #ifdef SGTTY
  379.     (void) ioctl(STDOUT, TIOCSETP, &new_settings);
  380. #ifdef TOStop
  381.     (void) ioctl(STDOUT, TIOCLSET, &new_lword);
  382. #endif
  383. #endif
  384. #ifdef TERMIO
  385.     (void) ioctl(STDOUT, TCSETA, &new_settings);
  386. #endif
  387. #ifdef TERMIOS
  388.     (void) tcsetattr(STDOUT, TCSADRAIN, &new_settings);
  389. #endif
  390.     }
  391.  
  392.     /* send init string */
  393.     if (smart_terminal)
  394.     {
  395.     putcap(terminal_init);
  396.     }
  397. }
  398.  
  399. standout(msg)
  400.  
  401. char *msg;
  402.  
  403. {
  404.     if (smart_terminal)
  405.     {
  406.     putcap(start_standout);
  407.     fputs(msg, stdout);
  408.     putcap(end_standout);
  409.     }
  410.     else
  411.     {
  412.     fputs(msg, stdout);
  413.     }
  414. }
  415.  
  416. clear()
  417.  
  418. {
  419.     if (smart_terminal)
  420.     {
  421.     putcap(clear_screen);
  422.     }
  423. }
  424.  
  425. clear_eol(len)
  426.  
  427. int len;
  428.  
  429. {
  430.     if (smart_terminal && !overstrike && len > 0)
  431.     {
  432.     if (clear_line)
  433.     {
  434.         putcap(clear_line);
  435.         return(0);
  436.     }
  437.     else
  438.     {
  439.         while (len-- > 0)
  440.         {
  441.         putchar(' ');
  442.         }
  443.         return(1);
  444.     }
  445.     }
  446.     return(-1);
  447. }
  448.  
  449. go_home()
  450.  
  451. {
  452.     if (smart_terminal)
  453.     {
  454.     putcap(home);
  455.     }
  456. }
  457.  
  458. /* This has to be defined as a subroutine for tputs (instead of a macro) */
  459.  
  460. putstdout(ch)
  461.  
  462. char ch;
  463.  
  464. {
  465.     putchar(ch);
  466. }
  467.  
  468.