/*
* 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);
}