home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 October / usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso / misc / volume30 / tin / part11 / curses.c next >
C/C++ Source or Header  |  1992-05-20  |  8KB  |  419 lines

  1. /*
  2.  *  Project   : tin - a threaded Netnews reader
  3.  *  Module    : curses.c
  4.  *  Author    : D.Taylor & I.Lea
  5.  *  Created   : ??-??-86
  6.  *  Updated   : 03-04-92
  7.  *  Notes     : This is a screen management library borrowed with permission
  8.  *              from the Elm mail system (a great mailer--I highly recommend
  9.  *              it!).This library was hacked to provide what tin needs.
  10.  *  Copyright : Copyright (c) 1986-92 Dave Taylor & Iain Lea
  11.  *              The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
  12.  */
  13.  
  14. #include <stdio.h>
  15. #include <curses.h>
  16. #include <sys/errno.h>
  17.  
  18. #define DEFAULT_LINES_ON_TERMINAL    24
  19. #define DEFAULT_COLUMNS_ON_TERMINAL    80
  20.  
  21. int LINES = 23;
  22. int COLS  = 80;
  23. int inverse_okay = TRUE;
  24. static int _inraw = FALSE;                  /* are we IN rawmode?    */
  25.  
  26.  
  27. #ifndef INDEX_DAEMON
  28.  
  29. #define        BACKSPACE    '\b'
  30. #define        VERY_LONG_STRING    2500
  31.  
  32. #ifdef BSD 
  33. #    ifndef BSD4_1
  34. #        include <sgtty.h>
  35. #    else
  36. #        include <termio.h>
  37. #    endif
  38. #else
  39. #    ifndef SYSV
  40. #        ifndef MINIX
  41. #            ifdef sinix
  42. #                include <termios.h>
  43. #            else
  44. #                include <termio.h>
  45. #            endif
  46. #        else
  47. #            include <sgtty.h>
  48. #        endif
  49. #    endif
  50. #endif
  51.  
  52. #define TTYIN    0
  53.  
  54. #ifdef SHORTNAMES
  55. # define _clearinverse    _clrinv
  56. # define _cleartoeoln    _clrtoeoln
  57. # define _cleartoeos    _clr2eos
  58. #endif
  59.  
  60. #if defined(BSD) || defined(MINIX)
  61. #    define TCGETA    TIOCGETP
  62. #    define TCSETAW    TIOCSETP
  63.  
  64. struct sgttyb _raw_tty,
  65.           _original_tty;
  66. #else
  67. #    ifdef sinix
  68. #        ifndef TCGETA
  69. #            define TCGETA    STCGETA
  70. #        endif
  71. #        ifndef TCSETA
  72. #            define TCSETAW    STCSETAW
  73. #        endif
  74. struct termios _raw_tty, 
  75.               _original_tty;
  76. #    else
  77. struct termio _raw_tty, 
  78.               _original_tty;
  79. #    endif
  80. #endif
  81.  
  82. static char *_clearscreen, *_moveto, *_cleartoeoln, *_cleartoeos,
  83.             *_setinverse, *_clearinverse, *_setunderline, *_clearunderline,
  84.             *_terminalinit, *_terminalend;
  85.  
  86. static int _lines,_columns;
  87.  
  88. static char _terminal[1024];              /* Storage for terminal entry */
  89. static char _capabilities[1024];           /* String for cursor motion */
  90.  
  91. static char *ptr = _capabilities;    /* for buffering         */
  92.  
  93. int    outchar ();            /* char output for tputs */
  94. extern char    *tgetstr ();        /* Get termcap capability */
  95. extern char    *tgoto ();        /* and the goto stuff    */
  96.  
  97. #endif /* INDEX_DAEMON */
  98.  
  99. #include "tin.h"
  100.  
  101.  
  102. int InitScreen ()
  103. {
  104. #ifndef INDEX_DAEMON
  105.  
  106.     extern int tgetent();      /* get termcap entry */
  107.     char termname[40], *p;
  108.     
  109.     if ((p = (char *) getenv ("TERM")) == NULL) {
  110.         fprintf (stderr, "%s: TERM variable must be set to use screen capabilities\n", progname);
  111.         return (FALSE);
  112.     }
  113.     if (strcpy (termname, p) == NULL) {
  114.         fprintf (stderr,"%s: Can't get TERM variable\n", progname);
  115.         return (FALSE);
  116.     }
  117.     if (tgetent (_terminal, termname) != 1) {
  118.         fprintf (stderr,"%s: Can't get entry for TERM\n", progname);
  119.         return (FALSE);
  120.     }
  121.  
  122.     /* load in all those pesky values */
  123.     _clearscreen    = tgetstr ("cl", &ptr);
  124.     _moveto         = tgetstr ("cm", &ptr);
  125.     _cleartoeoln    = tgetstr ("ce", &ptr);
  126.     _cleartoeos     = tgetstr ("cd", &ptr);
  127.     _lines          = tgetnum ("li");
  128.     _columns        = tgetnum ("co");
  129.     _setinverse     = tgetstr ("so", &ptr);
  130.     _clearinverse   = tgetstr ("se", &ptr);
  131.     _setunderline   = tgetstr ("us", &ptr);
  132.     _clearunderline = tgetstr ("ue", &ptr);
  133.     _terminalinit   = tgetstr ("ti", &ptr);
  134.     _terminalend    = tgetstr ("te", &ptr);
  135.  
  136.     InitWin ();
  137.  
  138.     if (!_clearscreen) {
  139.         fprintf (stderr,
  140.             "%s: Terminal must have clearscreen (cl) capability\n",progname);
  141.         return (FALSE);
  142.     }
  143.     if (!_moveto) {
  144.         fprintf (stderr,
  145.             "%s: Terminal must have cursor motion (cm)\n", progname);
  146.         return (FALSE);
  147.     }
  148.     if (!_cleartoeoln) {
  149.         fprintf (stderr,
  150.             "%s: Terminal must have clear to end-of-line (ce)\n", progname);
  151.         return (FALSE);
  152.     }
  153.     if (!_cleartoeos) {
  154.         fprintf (stderr,
  155.             "%s: Terminal must have clear to end-of-screen (cd)\n", progname);
  156.         return (FALSE);
  157.     }
  158.  
  159.  
  160.  
  161.  
  162.  
  163.  
  164.  
  165.  
  166.  
  167.  
  168.     if (_lines == -1)
  169.         _lines = DEFAULT_LINES_ON_TERMINAL;
  170.     if (_columns == -1)
  171.         _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  172.     /* kludge to workaround no inverse */
  173.     if (_setinverse == 0) {
  174.         _setinverse = _setunderline;
  175.         _clearinverse = _clearunderline;
  176.         if (_setinverse == 0)
  177.             draw_arrow_mark = 1;
  178.     }
  179.     return (TRUE);
  180.  
  181. #else
  182.  
  183.     return (FALSE);
  184.  
  185. #endif /* INDEX_DAEMON */
  186. }
  187.  
  188. /*
  189.  *  returns the number of lines and columns on the display.
  190.  */
  191.  
  192. void ScreenSize (num_lines, num_columns)
  193.     int *num_lines, *num_columns;
  194. {
  195. #ifndef INDEX_DAEMON
  196.  
  197.     if (_lines == 0) _lines = DEFAULT_LINES_ON_TERMINAL;
  198.     if (_columns == 0) _columns = DEFAULT_COLUMNS_ON_TERMINAL;
  199.  
  200.     *num_lines = _lines - 1;        /* assume index from zero*/
  201.     *num_columns = _columns;        /* assume index from one */
  202.  
  203. #endif /* INDEX_DAEMON */
  204. }
  205.  
  206. void InitWin ()
  207. {
  208. #ifndef INDEX_DAEMON
  209.  
  210.     if (_terminalinit) {
  211.         tputs (_terminalinit, 1, outchar);
  212.         fflush (stdout);
  213.     }
  214.  
  215. #endif /* INDEX_DAEMON */
  216. }
  217.  
  218. void EndWin ()
  219. {
  220. #ifndef INDEX_DAEMON
  221.  
  222.     if (_terminalend) {
  223.         tputs (_terminalend, 1, outchar);
  224.         fflush (stdout);
  225.     }
  226.     
  227. #endif /* INDEX_DAEMON */
  228. }
  229.  
  230. /*
  231.  *  clear the screen: returns -1 if not capable
  232.  */
  233.  
  234. void ClearScreen ()
  235. {
  236. #ifndef INDEX_DAEMON
  237.  
  238.     tputs (_clearscreen, 1, outchar);
  239.     fflush (stdout);      /* clear the output buffer */
  240.  
  241. #endif /* INDEX_DAEMON */
  242. }
  243.  
  244. /*
  245.  *  move cursor to the specified row column on the screen.
  246.  *  0,0 is the top left!
  247.  */
  248.  
  249. void MoveCursor (row, col)
  250.     int row, col;
  251. {
  252. #ifndef INDEX_DAEMON
  253.  
  254.     char *stuff, *tgoto();
  255.  
  256.     stuff = tgoto (_moveto, col, row);
  257.     tputs (stuff, 1, outchar);
  258.     fflush (stdout);
  259.  
  260. #endif /* INDEX_DAEMON */
  261. }
  262.  
  263. /*
  264.  *  clear to end of line
  265.  */
  266.  
  267. void CleartoEOLN ()
  268. {
  269. #ifndef INDEX_DAEMON
  270.  
  271.     tputs (_cleartoeoln, 1, outchar);
  272.     fflush (stdout);  /* clear the output buffer */
  273.  
  274. #endif /* INDEX_DAEMON */
  275. }
  276.  
  277. /*
  278.  *  clear to end of screen
  279.  */
  280.  
  281. void CleartoEOS ()
  282. {
  283. #ifndef INDEX_DAEMON
  284.  
  285.     int i;
  286.     
  287.     if (_cleartoeos) {
  288.         tputs (_cleartoeos, 1, outchar);
  289.     } else {
  290.         for (i=_lines ; i < _lines ; i++) {
  291.             MoveCursor (i, 0);
  292.             CleartoEOLN ();
  293.         }
  294.     }
  295.     fflush (stdout);  /* clear the output buffer */
  296.  
  297. #endif /* INDEX_DAEMON */
  298. }
  299.  
  300. /*
  301.  *  set inverse video mode
  302.  */
  303.  
  304. void StartInverse ()
  305. {
  306. #ifndef INDEX_DAEMON
  307.  
  308.     if (_setinverse && inverse_okay)
  309.         tputs (_setinverse, 1, outchar);
  310.     fflush (stdout);
  311.  
  312. #endif /* INDEX_DAEMON */
  313. }
  314.  
  315. /*
  316.  *  compliment of startinverse
  317.  */
  318.  
  319. void EndInverse ()
  320. {
  321. #ifndef INDEX_DAEMON
  322.  
  323.     if (_clearinverse && inverse_okay)
  324.         tputs (_clearinverse, 1, outchar);
  325.     fflush (stdout);
  326.  
  327. #endif /* INDEX_DAEMON */
  328. }
  329.  
  330. /*
  331.  *  returns either 1 or 0, for ON or OFF
  332.  */
  333.  
  334. int RawState()
  335. {
  336.     return (_inraw);
  337. }
  338.  
  339. /*
  340.  *  state is either TRUE or FALSE, as indicated by call
  341.  */
  342.  
  343. void Raw(state)
  344.     int state;
  345. {
  346. #ifndef INDEX_DAEMON
  347.  
  348.     if (state == FALSE && _inraw) {
  349.       (void) ioctl(TTYIN, TCSETAW, &_original_tty);
  350.       _inraw = 0;
  351.     }
  352.     else if (state == TRUE && ! _inraw) {
  353.  
  354.       (void) ioctl(TTYIN, TCGETA, &_original_tty);    /** current setting **/
  355.  
  356.       (void) ioctl(TTYIN, TCGETA, &_raw_tty);    /** again! **/
  357. #if defined(BSD) || defined(MINIX)
  358.       _raw_tty.sg_flags &= ~(ECHO | CRMOD);    /* echo off */
  359.       _raw_tty.sg_flags |= CBREAK;    /* raw on    */
  360. #else
  361.       _raw_tty.c_lflag &= ~(ICANON | ECHO);    /* noecho raw mode        */
  362.  
  363.       _raw_tty.c_cc[VMIN] = '\01';    /* minimum # of chars to queue    */
  364.       _raw_tty.c_cc[VTIME] = '\0';    /* minimum time to wait for input */
  365. #endif
  366.  
  367.       (void) ioctl(TTYIN, TCSETAW, &_raw_tty);
  368.  
  369.       _inraw = 1;
  370.     }
  371.     
  372. #endif /* INDEX_DAEMON */
  373. }
  374.  
  375. /*
  376.  *  read a character with Raw mode set!
  377.  */
  378.  
  379. int ReadCh()
  380. {
  381. #ifndef INDEX_DAEMON
  382.     extern int errno;
  383.     char ch;
  384.     register int result = 0;
  385.     
  386. #ifdef READ_CHAR_HACK
  387. #undef getc
  388.     while ((result = getc(stdin)) == EOF) {
  389.         if (feof(stdin))
  390.             break;
  391.  
  392.         if (ferror(stdin) && errno != EINTR)
  393.             break;
  394.  
  395.         clearerr(stdin);
  396.     }
  397.  
  398.     return ((result == EOF) ? EOF : result & 0xFF);
  399. #else
  400.  
  401.     while ((result = read(0, &ch, 1)) < 0 && errno == EINTR)
  402.         ;    /* spin on signal interrupts */
  403.  
  404.         return((result <= 0 ) ? EOF : ch & 0xFF);
  405. #endif        
  406.  
  407. #endif /* INDEX_DAEMON */
  408. }
  409.  
  410. /*
  411.  *  output a character. From tputs... (Note: this CANNOT be a macro!)
  412.  */
  413.  
  414. int outchar(c)
  415.     char c;
  416. {
  417.     fputc (c, stdout);
  418. }
  419.