tin-1.00/curses.c

/*
 *  curses.c
 */
 
/*
 *  This is a screen management library borrowed with permission from the
 *  Elm mail system (a great mailer--I highly recommend it!).
 *
 *  I've hacked this library to only provide what Tass needs.
 *
 *  Original copyright follows:
 */
 
/*******************************************************************************
 *  The Elm Mail System  -  $Revision: 2.1 $   $State: Exp $
 *
 *          Copyright (c) 1986 Dave Taylor
 ******************************************************************************/
 
#include <stdio.h>
#include <curses.h>
#include <sys/ioctl.h>
 
#ifdef TRUE
#undef TRUE
#define     TRUE        1
#endif
 
#ifdef FALSE
#undef FALSE
#define     FALSE       0
#endif
 
#define     BACKSPACE   '\b'
#define     VERY_LONG_STRING    2500
 
int LINES=23;
int COLS=80;
 
int inverse_okay = TRUE;
 
#ifdef BSD
#  ifndef BSD4_1
#    include <sgtty.h>
#  else
#    include <termio.h>
#  endif
#else
#  ifndef SYSV
#    include <termio.h>
#  endif
#endif
 
 
#include <ctype.h>
 
/*
#ifdef BSD
#undef tolower
#endif
*/
 
#define TTYIN   0
 
#ifdef SHORTNAMES
# define _clearinverse  _clrinv
# define _cleartoeoln   _clrtoeoln
# define _cleartoeos    _clr2eos
#endif
 
#ifndef BSD
struct termio _raw_tty,
              _original_tty;
#else
#define TCGETA  TIOCGETP
#define TCSETAW TIOCSETP
 
struct sgttyb _raw_tty,
          _original_tty;
#endif
 
static int _inraw = 0;                  /* are we IN rawmode?    */
 
#define DEFAULT_LINES_ON_TERMINAL   24
#define DEFAULT_COLUMNS_ON_TERMINAL 80
 
static
char *_clearscreen, *_moveto, *_cleartoeoln, *_cleartoeos,
    *_setinverse, *_clearinverse, *_setunderline, *_clearunderline;
 
static
int _lines,_columns;
 
static char _terminal[1024];              /* Storage for terminal entry */
static char _capabilities[1024];           /* String for cursor motion */
 
static char *ptr = _capabilities;   /* for buffering         */
 
int    outchar();           /* char output for tputs */
char  *tgetstr(),                  /* Get termcap capability */
      *tgoto();             /* and the goto stuff    */
 
int InitScreen()
{
    int  tgetent(),      /* get termcap entry */
         err;
    char termname[40];
    char *strcpy(), *getenv();
 
    if (getenv("TERM") == NULL) {
        fprintf(stderr,
          "TERM variable not set; Tass requires screen capabilities\n");
        return(FALSE);
    }
    if (strcpy(termname, getenv("TERM")) == NULL) {
        fprintf(stderr,"Can't get TERM variable\n");
        return(FALSE);
    }
    if ((err = tgetent(_terminal, termname)) != 1) {
        fprintf(stderr,"Can't get entry for TERM\n");
        return(FALSE);
    }
 
    /* load in all those pesky values */
    _clearscreen       = tgetstr("cl", &ptr);
    _moveto            = tgetstr("cm", &ptr);
    _cleartoeoln       = tgetstr("ce", &ptr);
    _cleartoeos        = tgetstr("cd", &ptr);
    _lines             = tgetnum("li");
    _columns       = tgetnum("co");
    _setinverse        = tgetstr("so", &ptr);
    _clearinverse      = tgetstr("se", &ptr);
    _setunderline      = tgetstr("us", &ptr);
    _clearunderline    = tgetstr("ue", &ptr);
 
    if (!_clearscreen) {
        fprintf(stderr,
            "Terminal must have clearscreen (cl) capability\n");
        return(FALSE);
    }
    if (!_moveto) {
        fprintf(stderr,
            "Terminal must have cursor motion (cm)\n");
        return(FALSE);
    }
    if (!_cleartoeoln) {
        fprintf(stderr,
            "Terminal must have clear to end-of-line (ce)\n");
        return(FALSE);
    }
    if (!_cleartoeos) {
        fprintf(stderr,
            "Terminal must have clear to end-of-screen (cd)\n");
        return(FALSE);
    }
    if (_lines == -1)
        _lines = DEFAULT_LINES_ON_TERMINAL;
    if (_columns == -1)
        _columns = DEFAULT_COLUMNS_ON_TERMINAL;
    return(TRUE);
}
 
void ScreenSize(num_lines, num_columns)
    int *num_lines, *num_columns;
{
    /** returns the number of lines and columns on the display. **/
 
    if (_lines == 0) _lines = DEFAULT_LINES_ON_TERMINAL;
    if (_columns == 0) _columns = DEFAULT_COLUMNS_ON_TERMINAL;
 
    *num_lines = _lines - 1;        /* assume index from zero*/
    *num_columns = _columns;        /* assume index from one */
}
 
void ClearScreen()
{
    /* clear the screen: returns -1 if not capable */
 
    tputs(_clearscreen, 1, outchar);
    fflush(stdout);      /* clear the output buffer */
}
 
void MoveCursor(row, col)
int row, col;
{
    /** move cursor to the specified row column on the screen.
            0,0 is the top left! **/
 
    char *stuff, *tgoto();
 
    stuff = tgoto(_moveto, col, row);
    tputs(stuff, 1, outchar);
    fflush(stdout);
}
 
void CleartoEOLN()
{
    /** clear to end of line **/
 
    tputs(_cleartoeoln, 1, outchar);
    fflush(stdout);  /* clear the output buffer */
}
 
void CleartoEOS()
{
    /** clear to end of screen **/
 
    tputs(_cleartoeos, 1, outchar);
    fflush(stdout);  /* clear the output buffer */
}
 
 
void StartInverse()
{
    /** set inverse video mode **/
 
    if (_setinverse && inverse_okay)
        tputs(_setinverse, 1, outchar);
/*  fflush(stdout); */
}
 
 
void EndInverse()
{
    /** compliment of startinverse **/
 
    if (_clearinverse && inverse_okay)
        tputs(_clearinverse, 1, outchar);
/*  fflush(stdout); */
}
 
 
int RawState()
{
    /** returns either 1 or 0, for ON or OFF **/
 
    return( _inraw );
}
 
 
void Raw(state)
    int state;
{
    /** state is either TRUE or FALSE, as indicated by call **/
 
    if (state == FALSE && _inraw) {
      (void) ioctl(TTYIN, TCSETAW, &_original_tty);
      _inraw = 0;
    }
    else if (state == TRUE && ! _inraw) {
 
      (void) ioctl(TTYIN, TCGETA, &_original_tty);  /** current setting **/
 
      (void) ioctl(TTYIN, TCGETA, &_raw_tty);    /** again! **/
#ifdef BSD
      _raw_tty.sg_flags &= ~(ECHO | CRMOD); /* echo off */
      _raw_tty.sg_flags |= CBREAK;  /* raw on    */
#else
      _raw_tty.c_lflag &= ~(ICANON | ECHO); /* noecho raw mode        */
 
      _raw_tty.c_cc[VMIN] = '\01';  /* minimum # of chars to queue    */
      _raw_tty.c_cc[VTIME] = '\0';  /* minimum time to wait for input */
#endif
 
      (void) ioctl(TTYIN, TCSETAW, &_raw_tty);
 
      _inraw = 1;
    }
}
 
int ReadCh()
{
    /** read a character with Raw mode set! **/
 
    register int result;
    char ch;
    result = read(0, &ch, 1);
        return((result <= 0 ) ? EOF : ch & 0x7F);
}
 
 
int outchar(c)
char c;
{
    /** output the given character.  From tputs... **/
    /** Note: this CANNOT be a macro!              **/
 
    putc(c, stdout);
}