home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
misc
/
volume30
/
tin
/
part11
/
curses.c
next >
Wrap
C/C++ Source or Header
|
1992-05-20
|
8KB
|
419 lines
/*
* Project : tin - a threaded Netnews reader
* Module : curses.c
* Author : D.Taylor & I.Lea
* Created : ??-??-86
* Updated : 03-04-92
* Notes : This is a screen management library borrowed with permission
* from the Elm mail system (a great mailer--I highly recommend
* it!).This library was hacked to provide what tin needs.
* Copyright : Copyright (c) 1986-92 Dave Taylor & Iain Lea
* The Elm Mail System - $Revision: 2.1 $ $State: Exp $
*/
#include <stdio.h>
#include <curses.h>
#include <sys/errno.h>
#define DEFAULT_LINES_ON_TERMINAL 24
#define DEFAULT_COLUMNS_ON_TERMINAL 80
int LINES = 23;
int COLS = 80;
int inverse_okay = TRUE;
static int _inraw = FALSE; /* are we IN rawmode? */
#ifndef INDEX_DAEMON
#define BACKSPACE '\b'
#define VERY_LONG_STRING 2500
#ifdef BSD
# ifndef BSD4_1
# include <sgtty.h>
# else
# include <termio.h>
# endif
#else
# ifndef SYSV
# ifndef MINIX
# ifdef sinix
# include <termios.h>
# else
# include <termio.h>
# endif
# else
# include <sgtty.h>
# endif
# endif
#endif
#define TTYIN 0
#ifdef SHORTNAMES
# define _clearinverse _clrinv
# define _cleartoeoln _clrtoeoln
# define _cleartoeos _clr2eos
#endif
#if defined(BSD) || defined(MINIX)
# define TCGETA TIOCGETP
# define TCSETAW TIOCSETP
struct sgttyb _raw_tty,
_original_tty;
#else
# ifdef sinix
# ifndef TCGETA
# define TCGETA STCGETA
# endif
# ifndef TCSETA
# define TCSETAW STCSETAW
# endif
struct termios _raw_tty,
_original_tty;
# else
struct termio _raw_tty,
_original_tty;
# endif
#endif
static char *_clearscreen, *_moveto, *_cleartoeoln, *_cleartoeos,
*_setinverse, *_clearinverse, *_setunderline, *_clearunderline,
*_terminalinit, *_terminalend;
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 */
extern char *tgetstr (); /* Get termcap capability */
extern char *tgoto (); /* and the goto stuff */
#endif /* INDEX_DAEMON */
#include "tin.h"
int InitScreen ()
{
#ifndef INDEX_DAEMON
extern int tgetent(); /* get termcap entry */
char termname[40], *p;
if ((p = (char *) getenv ("TERM")) == NULL) {
fprintf (stderr, "%s: TERM variable must be set to use screen capabilities\n", progname);
return (FALSE);
}
if (strcpy (termname, p) == NULL) {
fprintf (stderr,"%s: Can't get TERM variable\n", progname);
return (FALSE);
}
if (tgetent (_terminal, termname) != 1) {
fprintf (stderr,"%s: Can't get entry for TERM\n", progname);
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);
_terminalinit = tgetstr ("ti", &ptr);
_terminalend = tgetstr ("te", &ptr);
InitWin ();
if (!_clearscreen) {
fprintf (stderr,
"%s: Terminal must have clearscreen (cl) capability\n",progname);
return (FALSE);
}
if (!_moveto) {
fprintf (stderr,
"%s: Terminal must have cursor motion (cm)\n", progname);
return (FALSE);
}
if (!_cleartoeoln) {
fprintf (stderr,
"%s: Terminal must have clear to end-of-line (ce)\n", progname);
return (FALSE);
}
if (!_cleartoeos) {
fprintf (stderr,
"%s: Terminal must have clear to end-of-screen (cd)\n", progname);
return (FALSE);
}
if (_lines == -1)
_lines = DEFAULT_LINES_ON_TERMINAL;
if (_columns == -1)
_columns = DEFAULT_COLUMNS_ON_TERMINAL;
/* kludge to workaround no inverse */
if (_setinverse == 0) {
_setinverse = _setunderline;
_clearinverse = _clearunderline;
if (_setinverse == 0)
draw_arrow_mark = 1;
}
return (TRUE);
#else
return (FALSE);
#endif /* INDEX_DAEMON */
}
/*
* returns the number of lines and columns on the display.
*/
void ScreenSize (num_lines, num_columns)
int *num_lines, *num_columns;
{
#ifndef INDEX_DAEMON
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 */
#endif /* INDEX_DAEMON */
}
void InitWin ()
{
#ifndef INDEX_DAEMON
if (_terminalinit) {
tputs (_terminalinit, 1, outchar);
fflush (stdout);
}
#endif /* INDEX_DAEMON */
}
void EndWin ()
{
#ifndef INDEX_DAEMON
if (_terminalend) {
tputs (_terminalend, 1, outchar);
fflush (stdout);
}
#endif /* INDEX_DAEMON */
}
/*
* clear the screen: returns -1 if not capable
*/
void ClearScreen ()
{
#ifndef INDEX_DAEMON
tputs (_clearscreen, 1, outchar);
fflush (stdout); /* clear the output buffer */
#endif /* INDEX_DAEMON */
}
/*
* move cursor to the specified row column on the screen.
* 0,0 is the top left!
*/
void MoveCursor (row, col)
int row, col;
{
#ifndef INDEX_DAEMON
char *stuff, *tgoto();
stuff = tgoto (_moveto, col, row);
tputs (stuff, 1, outchar);
fflush (stdout);
#endif /* INDEX_DAEMON */
}
/*
* clear to end of line
*/
void CleartoEOLN ()
{
#ifndef INDEX_DAEMON
tputs (_cleartoeoln, 1, outchar);
fflush (stdout); /* clear the output buffer */
#endif /* INDEX_DAEMON */
}
/*
* clear to end of screen
*/
void CleartoEOS ()
{
#ifndef INDEX_DAEMON
int i;
if (_cleartoeos) {
tputs (_cleartoeos, 1, outchar);
} else {
for (i=_lines ; i < _lines ; i++) {
MoveCursor (i, 0);
CleartoEOLN ();
}
}
fflush (stdout); /* clear the output buffer */
#endif /* INDEX_DAEMON */
}
/*
* set inverse video mode
*/
void StartInverse ()
{
#ifndef INDEX_DAEMON
if (_setinverse && inverse_okay)
tputs (_setinverse, 1, outchar);
fflush (stdout);
#endif /* INDEX_DAEMON */
}
/*
* compliment of startinverse
*/
void EndInverse ()
{
#ifndef INDEX_DAEMON
if (_clearinverse && inverse_okay)
tputs (_clearinverse, 1, outchar);
fflush (stdout);
#endif /* INDEX_DAEMON */
}
/*
* returns either 1 or 0, for ON or OFF
*/
int RawState()
{
return (_inraw);
}
/*
* state is either TRUE or FALSE, as indicated by call
*/
void Raw(state)
int state;
{
#ifndef INDEX_DAEMON
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! **/
#if defined(BSD) || defined(MINIX)
_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;
}
#endif /* INDEX_DAEMON */
}
/*
* read a character with Raw mode set!
*/
int ReadCh()
{
#ifndef INDEX_DAEMON
extern int errno;
char ch;
register int result = 0;
#ifdef READ_CHAR_HACK
#undef getc
while ((result = getc(stdin)) == EOF) {
if (feof(stdin))
break;
if (ferror(stdin) && errno != EINTR)
break;
clearerr(stdin);
}
return ((result == EOF) ? EOF : result & 0xFF);
#else
while ((result = read(0, &ch, 1)) < 0 && errno == EINTR)
; /* spin on signal interrupts */
return((result <= 0 ) ? EOF : ch & 0xFF);
#endif
#endif /* INDEX_DAEMON */
}
/*
* output a character. From tputs... (Note: this CANNOT be a macro!)
*/
int outchar(c)
char c;
{
fputc (c, stdout);
}