home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Usenet 1994 October
/
usenetsourcesnewsgroupsinfomagicoctober1994disk2.iso
/
unix
/
volume27
/
trn-3.3
/
part09
/
term.c
< prev
Wrap
C/C++ Source or Header
|
1993-11-27
|
28KB
|
1,302 lines
/* $Id: term.c,v 3.0 1992/02/01 03:09:32 davison Trn $
*/
/* This software is Copyright 1991 by Stan Barber.
*
* Permission is hereby granted to copy, reproduce, redistribute or otherwise
* use this software as long as: there is no monetary profit gained
* specifically from the use or reproduction of this software, it is not
* sold, rented, traded or otherwise marketed, and this copyright notice is
* included prominently in any copy made.
*
* The authors make no claims as to the fitness or correctness of this software
* for any use whatsoever, and it is provided as is. Any use of this software
* is at the user's own risk.
*/
#include "EXTERN.h"
#include "common.h"
#include "util.h"
#include "final.h"
#include "help.h"
#include "cache.h"
#include "intrp.h"
#include "INTERN.h"
#include "term.h"
#ifdef u3b2
#undef TIOCGWINSZ
#endif
char ERASECH; /* rubout character */
char KILLCH; /* line delete character */
char tcarea[TCSIZE]; /* area for "compiled" termcap strings */
int upcost;
/* guarantee capability pointer != Nullch */
/* (I believe terminfo will ignore the &tmpaddr argument.) */
char *tgetstr();
#define Tgetstr(key) ((tmpstr = tgetstr(key,&tmpaddr)) ? tmpstr : nullstr)
struct keymap {
char km_type[128];
union km_union {
struct keymap *km_km;
char *km_str;
} km_ptr[128];
};
#define KM_NOTHIN 0
#define KM_STRING 1
#define KM_KEYMAP 2
#define KM_BOGUS 3
#define KM_TMASK 3
#define KM_GSHIFT 4
#define KM_GMASK 7
typedef struct keymap KEYMAP;
KEYMAP *topmap INIT(Null(KEYMAP*));
void mac_init();
KEYMAP *newkeymap();
void show_keymap();
void line_col_calcs();
/* terminal initialization */
void
term_init()
{
savetty(); /* remember current tty state */
#ifdef I_TERMIO
outspeed = _tty.c_cflag & CBAUD; /* for tputs() */
ERASECH = _tty.c_cc[VERASE]; /* for finish_command() */
KILLCH = _tty.c_cc[VKILL]; /* for finish_command() */
if (GT = ((_tty.c_oflag & TABDLY) != TAB3))
/* we have tabs, so that's OK */;
else
_tty.c_oflag &= ~TAB3; /* turn off kernel tabbing -- done in rn */
#else /* !I_TERMIO */
# ifdef I_TERMIOS
outspeed = cfgetospeed(&_tty); /* for tputs() (output) */
ERASECH = _tty.c_cc[VERASE]; /* for finish_command() */
KILLCH = _tty.c_cc[VKILL]; /* for finish_command() */
#if 0
_tty.c_oflag &= ~OXTABS; /* turn off kernel tabbing-done in rn */
#endif
# else /* !I_TERMIOS */
outspeed = _tty.sg_ospeed; /* for tputs() */
ERASECH = _tty.sg_erase; /* for finish_command() */
KILLCH = _tty.sg_kill; /* for finish_command() */
if (GT = ((_tty.sg_flags & XTABS) != XTABS))
/* we have tabs, so that's OK */;
else
_tty.sg_flags &= ~XTABS;
# endif /* I_TERMIOS */
#endif /* I_TERMIO */
/* The following could be a table but I can't be sure that there isn't */
/* some degree of sparsity out there in the world. */
switch (outspeed) { /* 1 second of padding */
#ifdef BEXTA
case BEXTA: just_a_sec = 1920; break;
#else
#ifdef B19200
case B19200: just_a_sec = 1920; break;
#endif
#endif
case B9600: just_a_sec = 960; break;
case B4800: just_a_sec = 480; break;
case B2400: just_a_sec = 240; break;
case B1800: just_a_sec = 180; break;
case B1200: just_a_sec = 120; break;
case B600: just_a_sec = 60; break;
case B300: just_a_sec = 30; break;
/* do I really have to type the rest of this??? */
case B200: just_a_sec = 20; break;
case B150: just_a_sec = 15; break;
case B134: just_a_sec = 13; break;
case B110: just_a_sec = 11; break;
case B75: just_a_sec = 8; break;
case B50: just_a_sec = 5; break;
default: just_a_sec = 960; break;
/* if we are running detached I */
} /* don't want to know about it! */
}
/* set terminal characteristics */
void
term_set(tcbuf)
char *tcbuf; /* temp area for "uncompiled" termcap entry */
{
char *tmpaddr; /* must not be register */
register char *tmpstr;
char *s;
int status;
#ifdef TIOCGWINSZ
struct winsize winsize;
#endif
#ifdef PENDING
#if ! defined (FIONREAD) && ! defined (HAS_RDCHK)
/* do no delay reads on something that always gets closed on exit */
devtty = open("/dev/tty",0);
if (devtty < 0) {
printf(cantopen,"/dev/tty") FLUSH;
finalize(1);
}
fcntl(devtty,F_SETFL,O_NDELAY);
#endif
#endif
/* get all that good termcap stuff */
#ifdef HAS_TERMLIB
status = tgetent(tcbuf,getenv("TERM")); /* get termcap entry */
if (status < 1) {
#ifdef VERBOSE
printf("No termcap %s found.\n", status ? "file" : "entry") FLUSH;
#else
fputs("Termcap botch\n",stdout) FLUSH;
#endif
finalize(1);
}
tmpaddr = tcarea; /* set up strange tgetstr pointer */
s = Tgetstr("pc"); /* get pad character */
PC = *s; /* get it where tputs wants it */
if (!tgetflag("bs")) { /* is backspace not used? */
BC = Tgetstr("bc"); /* find out what is */
if (BC == nullstr) /* terminfo grok's 'bs' but not 'bc' */
BC = Tgetstr("le");
} else
BC = "\b"; /* make a backspace handy */
UP = Tgetstr("up"); /* move up a line */
if (!*UP) /* no UP string? */
marking = 0; /* disable any marking */
if (muck_up_clear) /* this is for weird HPs */
CL = "\n\n\n\n";
else
CL = Tgetstr("cl"); /* get clear string */
CE = Tgetstr("ce"); /* clear to end of line string */
TI = Tgetstr("ti"); /* initialize display */
TE = Tgetstr("te"); /* reset display */
HO = Tgetstr("ho"); /* home cursor if no CM */
CM = Tgetstr("cm"); /* cursor motion */
if (*CM || *HO)
can_home = TRUE;
#ifdef CLEAREOL
CD = Tgetstr("cd"); /* clear to end of display */
if (!*CE || !*CD || !can_home) /* can we CE, CD, and home? */
can_home_clear = FALSE; /* no, so disable use of clear eol */
if (!*CE)
CE = CD;
#endif /* CLEAREOL */
upcost = strlen(UP);
SO = Tgetstr("so"); /* begin standout */
SE = Tgetstr("se"); /* end standout */
if ((SG = tgetnum("sg"))<0)
SG = 0; /* blanks left by SG, SE */
US = Tgetstr("us"); /* start underline */
UE = Tgetstr("ue"); /* end underline */
if ((UG = tgetnum("ug"))<0)
UG = 0; /* blanks left by US, UE */
if (*US)
UC = nullstr; /* UC must not be NULL */
else
UC = Tgetstr("uc"); /* underline a character */
if (!*US && !*UC) { /* no underline mode? */
US = SO; /* substitute standout mode */
UE = SE;
UG = SG;
}
LINES = tgetnum("li"); /* lines per page */
COLS = tgetnum("co"); /* columns on page */
#ifdef TIOCGWINSZ
{ struct winsize ws;
if (ioctl(0, TIOCGWINSZ, &ws) >= 0 && ws.ws_row > 0 && ws.ws_col > 0) {
LINES = ws.ws_row;
COLS = ws.ws_col;
}
}
#endif
AM = tgetflag("am"); /* terminal wraps automatically? */
XN = tgetflag("xn"); /* then eats next newline? */
VB = Tgetstr("vb");
if (!*VB)
VB = "\007";
CR = Tgetstr("cr");
if (!*CR) {
if (tgetflag("nc") && *UP) {
CR = safemalloc((MEM_SIZE)strlen(UP)+2);
sprintf(CR,"%s\r",UP);
}
else
CR = "\r";
}
#ifdef TIOCGWINSZ
if (ioctl(1, TIOCGWINSZ, &winsize) >= 0) {
if (winsize.ws_row > 0)
LINES = winsize.ws_row;
if (winsize.ws_col > 0)
COLS = winsize.ws_col;
}
#endif
#else
?????? /* Roll your own... */
#endif
termlib_init();
line_col_calcs();
noecho(); /* turn off echo */
crmode(); /* enter cbreak mode */
mac_init(tcbuf);
}
void
set_macro(seq,def)
char *seq; /* input sequence of keys */
char *def; /* definition */
{
mac_line(def,seq,0);
/* check for common (?) brain damage: ku/kd/etc sequence may be the
* cursor move sequence instead of the input sequence.
* (This happens on the local xterm definitions.)
* Try to recognize and adjust for this case.
*/
if (seq[0] == '\033' && seq[1] == '[' && seq[2]) {
char lbuf[LBUFLEN]; /* copy of possibly non-writable string */
strcpy(lbuf,seq);
lbuf[1] = 'O';
mac_line(def,lbuf,0);
}
if (seq[0] == '\033' && seq[1] == 'O' && seq[2]) {
char lbuf[LBUFLEN]; /* copy of possibly non-writable string */
strcpy(lbuf,seq);
lbuf[1] = '[';
mac_line(def,lbuf,0);
}
}
/* Turn the arrow keys into macros that do some basic trn functions.
** Code provided by Clifford Adams.
*/
void
arrow_macros(tmpbuf)
char *tmpbuf;
{
char lbuf[256]; /* should be long enough */
char *tmpaddr = tmpbuf;
register char *tmpstr;
/* If arrows are defined as single keys, we probably don't
* want to redefine them. (The tvi912c defines kl as ^H)
*/
strcpy(lbuf,Tgetstr("ku")); /* up */
/* '(' at article or pager, 'p' otherwise */
if (strlen(lbuf)>1)
set_macro(lbuf,"%(%m=[ap]?\\(:p)");
strcpy(lbuf,Tgetstr("kd")); /* down */
/* ')' at article or pager, 'n' otherwise */
if (strlen(lbuf)>1)
set_macro(lbuf,"%(%m=[ap]?\\):n)");
strcpy(lbuf,Tgetstr("kl")); /* left */
/* '[' at article or pager, '<' otherwise */
if (strlen(lbuf)>1)
set_macro(lbuf,"%(%m=[ap]?\\[:<)");
strcpy(lbuf,Tgetstr("kr")); /* right */
/* CR at newsgroups, ']' at article or pager, '>' otherwise */
if (strlen(lbuf)>1)
set_macro(lbuf,"%(%m=n?^j:%(%m=[ap]?\\]:>))");
}
void
mac_init(tcbuf)
char *tcbuf;
{
char tmpbuf[1024];
if (auto_arrow_macros)
arrow_macros(tmpbuf);
if (use_threads)
tmpfp = fopen(filexp(getval("TRNMACRO",TRNMACRO)),"r");
else
tmpfp = Nullfp;
if (!tmpfp)
tmpfp = fopen(filexp(getval("RNMACRO",RNMACRO)),"r");
if (tmpfp) {
while (fgets(tcbuf,1024,tmpfp) != Nullch) {
mac_line(tcbuf,tmpbuf,(sizeof tmpbuf));
}
fclose(tmpfp);
}
}
void
mac_line(line,tmpbuf,tbsize)
char *line;
char *tmpbuf;
int tbsize;
{
register char *s, *m;
register KEYMAP *curmap;
register int ch;
register int garbage = 0;
static char override[] = "\nkeymap overrides string\n";
if (topmap == Null(KEYMAP*))
topmap = newkeymap();
if (*line == '#' || *line == '\n')
return;
if (line[ch = strlen(line)-1] == '\n')
line[ch] = '\0';
/* A 0 length signifies we already parsed the macro into tmpbuf,
** so line is just the definition. */
if (tbsize)
m = dointerp(tmpbuf,tbsize,line," \t");
else
m = line;
if (!*m)
return;
while (*m == ' ' || *m == '\t') m++;
for (s=tmpbuf,curmap=topmap; *s; s++) {
ch = *s & 0177;
if (s[1] == '+' && isdigit(s[2])) {
s += 2;
garbage = (*s & KM_GMASK) << KM_GSHIFT;
}
else
garbage = 0;
if (s[1]) {
if ((curmap->km_type[ch] & KM_TMASK) == KM_STRING) {
if (tbsize)
fputs(override,stdout) FLUSH;
free(curmap->km_ptr[ch].km_str);
curmap->km_ptr[ch].km_str = Nullch;
}
curmap->km_type[ch] = KM_KEYMAP + garbage;
if (curmap->km_ptr[ch].km_km == Null(KEYMAP*))
curmap->km_ptr[ch].km_km = newkeymap();
curmap = curmap->km_ptr[ch].km_km;
}
else {
if (tbsize && (curmap->km_type[ch] & KM_TMASK) == KM_KEYMAP)
fputs(override,stdout) FLUSH;
else {
curmap->km_type[ch] = KM_STRING + garbage;
curmap->km_ptr[ch].km_str = savestr(m);
}
}
}
}
KEYMAP*
newkeymap()
{
register int i;
register KEYMAP *map;
#ifndef lint
map = (KEYMAP*)safemalloc(sizeof(KEYMAP));
#else
map = Null(KEYMAP*);
#endif /* lint */
for (i=127; i>=0; --i) {
map->km_ptr[i].km_km = Null(KEYMAP*);
map->km_type[i] = KM_NOTHIN;
}
return map;
}
void
show_macros()
{
char prebuf[64];
if (topmap != Null(KEYMAP*)) {
print_lines("Macros:\n",STANDOUT);
*prebuf = '\0';
show_keymap(topmap,prebuf);
}
else {
print_lines("No macros defined.\n", NOMARKING);
}
}
void
show_keymap(curmap,prefix)
register KEYMAP *curmap;
char *prefix;
{
register int i;
register char *next = prefix + strlen(prefix);
register int kt;
for (i=0; i<128; i++) {
if (kt = curmap->km_type[i]) {
if (i < ' ')
sprintf(next,"^%c",i+64);
else if (i == ' ')
strcpy(next,"\\040");
else if (i == 127)
strcpy(next,"^?");
else
sprintf(next,"%c",i);
if ((kt >> KM_GSHIFT) & KM_GMASK) {
sprintf(cmd_buf,"+%d", (kt >> KM_GSHIFT) & KM_GMASK);
strcat(next,cmd_buf);
}
switch (kt & KM_TMASK) {
case KM_NOTHIN:
sprintf(cmd_buf,"%s %c\n",prefix,i);
print_lines(cmd_buf,NOMARKING);
break;
case KM_KEYMAP:
show_keymap(curmap->km_ptr[(char)i].km_km, prefix);
break;
case KM_STRING:
sprintf(cmd_buf,"%s %s\n",prefix,curmap->km_ptr[i].km_str);
print_lines(cmd_buf,NOMARKING);
break;
case KM_BOGUS:
sprintf(cmd_buf,"%s BOGUS\n",prefix);
print_lines(cmd_buf,STANDOUT);
break;
}
}
}
}
/* routine to pass to tputs */
char
putchr(ch)
register char_int ch;
{
putchar(ch);
#ifdef lint
ch = Null(char);
ch = ch;
#endif
return((char) 0);
}
/* input the 2nd and succeeding characters of a multi-character command */
/* returns TRUE if command finished, FALSE if they rubbed out first character */
int buflimit = LBUFLEN;
bool
finish_command(donewline)
int donewline;
{
register char *s;
register bool quoteone = FALSE;
s = buf;
if (s[1] != FINISHCMD) /* someone faking up a command? */
return TRUE;
do {
top:
if (*(unsigned char *)s < ' ') {
putchar('^');
putchar(*s | 64);
}
else if (*s == '\177') {
putchar('^');
putchar('?');
}
else
putchar(*s); /* echo previous character */
s++;
if (s - buf == buflimit)
break;
re_read:
fflush(stdout);
getcmd(s);
if (quoteone) {
quoteone = FALSE;
continue;
}
if (errno || *s == '\f') {
*s = Ctl('r'); /* force rewrite on CONT */
}
if (*s == '\033') { /* substitution desired? */
#ifdef ESCSUBS
char tmpbuf[4], *cpybuf;
tmpbuf[0] = '%';
read_tty(&tmpbuf[1],1);
#ifdef RAWONLY
tmpbuf[1] &= 0177;
#endif
tmpbuf[2] = '\0';
if (tmpbuf[1] == 'h') {
(void) help_subs();
*s = '\0';
reprint();
goto re_read;
}
else if (tmpbuf[1] == '\033') {
*s = '\0';
cpybuf = savestr(buf);
interp(buf, (sizeof buf), cpybuf);
free(cpybuf);
s = buf + strlen(buf);
reprint();
goto re_read;
}
else {
interp(s,(sizeof buf) - (s-buf),tmpbuf);
fputs(s,stdout);
s += strlen(s);
}
goto re_read;
#else
notincl("^[");
*s = '\0';
reprint();
goto re_read;
#endif
}
else if (*s == ERASECH) { /* they want to rubout a char? */
rubout();
s--; /* discount the char rubbed out */
if (*(unsigned char *)s < ' ' || *s == '\177')
rubout();
if (s == buf) { /* entire string gone? */
fflush(stdout); /* return to single char command mode */
return FALSE;
}
else
goto re_read;
}
else if (*s == KILLCH) { /* wipe out the whole line? */
while (s-- != buf) { /* emulate that many ERASEs */
rubout();
if (*(unsigned char *)s < ' ' || *s == '\177')
rubout();
}
fflush(stdout);
return FALSE; /* return to single char mode */
}
#ifdef WORDERASE
else if (*s == Ctl('w')) { /* wipe out one word? */
*s-- = ' ';
while (!isspace(*s) || isspace(s[1])) {
rubout();
if (s-- == buf) {
fflush(stdout);
return FALSE; /* return to single char mode */
}
if (*(unsigned char *)s < ' ' || *s == '\177')
rubout();
}
s++;
goto re_read;
}
#endif
else if (*s == Ctl('r')) {
*s = '\0';
reprint();
goto re_read;
}
else if (*s == Ctl('v')) {
putchar('^');
backspace();
fflush(stdout);
getcmd(s);
goto top;
}
else if (*s == '\\') {
quoteone = TRUE;
}
#ifdef cray
} while (*s != '\r'); /* till a newline (not echoed) */
#else
} while (*s != '\n'); /* till a newline (not echoed) */
#endif
*s = '\0'; /* terminate the string nicely */
if (donewline)
putchar('\n') FLUSH;
return TRUE; /* say we succeeded */
}
bool
finish_dblchar()
{
bool ret;
buflimit = 2;
ret = finish_command(FALSE);
buflimit = LBUFLEN;
return ret;
}
/* discard any characters typed ahead */
void
eat_typeahead()
{
if (!typeahead && nextin==nextout) { /* cancel only keyboard stuff */
#ifdef PENDING
while (input_pending())
read_tty(buf,sizeof(buf));
#else /* this is probably v7 */
# ifdef I_SGTTY
ioctl(_tty_ch,TIOCSETP,&_tty);
# else
# ifdef I_TERMIO
ioctl(_tty_ch,TCSETAW,&_tty);
# else
tcsetattr(_tty_ch,TCSAFLUSH,&_tty);
# endif
# endif
#endif
}
}
void
save_typeahead(buf, len)
char *buf;
int len;
{
int cnt;
while (input_pending()) {
cnt = read_tty(buf, len);
buf += cnt;
len -= cnt;
}
*buf = '\0';
}
void
settle_down()
{
dingaling();
fflush(stdout);
/*sleep(1);*/
nextout = nextin; /* empty circlebuf */
eat_typeahead();
}
/* read a character from the terminal, with multi-character pushback */
int
read_tty(addr,size)
char *addr;
int size;
{
if (nextout != nextin) {
*addr = circlebuf[nextout++];
nextout %= PUSHSIZE;
return 1;
}
else {
size = read(0,addr,size);
#ifdef RAWONLY
*addr &= 0177;
#endif
return size;
}
}
#ifdef PENDING
# if !defined (FIONREAD) && !defined (HAS_RDCHK)
int
circfill()
{
register int Howmany;
errno = 0;
Howmany = read(devtty,circlebuf+nextin,1);
if (Howmany < 0 && (errno == EAGAIN || errno == EINTR))
Howmany = 0;
if (Howmany) {
nextin += Howmany;
nextin %= PUSHSIZE;
}
return Howmany;
}
# endif /* PENDING */
#endif /* FIONREAD */
void
pushchar(c)
char_int c;
{
nextout--;
if (nextout < 0)
nextout = PUSHSIZE - 1;
if (nextout == nextin) {
fputs("\npushback buffer overflow\n",stdout) FLUSH;
sig_catcher(0);
}
circlebuf[nextout] = c;
}
/* print an underlined string, one way or another */
void
underprint(s)
register char *s;
{
assert(UC);
if (*UC) { /* char by char underline? */
while (*s) {
if (*(unsigned char *)s < ' ') {
putchar('^');
backspace();/* back up over it */
underchar();/* and do the underline */
putchar(*s+64);
backspace();/* back up over it */
underchar();/* and do the underline */
}
else {
putchar(*s);
backspace();/* back up over it */
underchar();/* and do the underline */
}
s++;
}
}
else { /* start and stop underline */
underline(); /* start underlining */
while (*s) {
if (*(unsigned char *)s < ' ') {
putchar('^');
putchar(*s+64);
}
else
putchar(*s);
s++;
}
un_underline(); /* stop underlining */
}
}
/* keep screen from flashing strangely on magic cookie terminals */
#ifdef NOFIREWORKS
void
no_sofire()
{
if (*UP && *SE) { /* should we disable fireworks? */
putchar('\n');
un_standout();
up_line();
carriage_return();
}
}
void
no_ulfire()
{
if (*UP && *US) { /* should we disable fireworks? */
putchar('\n');
un_underline();
up_line();
carriage_return();
}
}
#endif
/* get a character into a buffer */
void
getcmd(whatbuf)
register char *whatbuf;
{
register KEYMAP *curmap;
register int i;
bool no_macros;
int times = 0; /* loop detector */
char scrchar;
tryagain:
curmap = topmap;
no_macros = (whatbuf != buf && nextin == nextout);
for (;;) {
int_count = 0;
errno = 0;
if (read_tty(whatbuf,1) < 0){
if (!errno)
errno = EINTR;
if (errno == EINTR)
return;
perror(readerr);
sig_catcher(0);
}
lastchar = *whatbuf;
if (*whatbuf & 0200 || no_macros) {
*whatbuf &= 0177;
goto got_canonical;
}
if (curmap == Null(KEYMAP*))
goto got_canonical;
for (i = (curmap->km_type[*whatbuf] >> KM_GSHIFT) & KM_GMASK; i; --i){
read_tty(&scrchar,1);
}
switch (curmap->km_type[*whatbuf] & KM_TMASK) {
case KM_NOTHIN: /* no entry? */
if (curmap == topmap) /* unmapped canonical */
goto got_canonical;
settle_down();
goto tryagain;
case KM_KEYMAP: /* another keymap? */
curmap = curmap->km_ptr[*whatbuf].km_km;
assert(curmap != Null(KEYMAP*));
break;
case KM_STRING: /* a string? */
pushstring(curmap->km_ptr[*whatbuf].km_str,0200);
if (++times > 20) { /* loop? */
fputs("\nmacro loop?\n",stdout);
settle_down();
}
no_macros = FALSE;
goto tryagain;
}
}
got_canonical:
#ifdef I_SGTTY
if (*whatbuf == '\r')
*whatbuf = '\n';
#endif
if (whatbuf == buf)
whatbuf[1] = FINISHCMD; /* tell finish_command to work */
}
void
pushstring(str,bits)
char *str;
char_int bits;
{
register int i;
char tmpbuf[PUSHSIZE];
register char *s = tmpbuf;
assert(str != Nullch);
interp(tmpbuf,PUSHSIZE,str);
for (i = strlen(s)-1; i >= 0; --i)
pushchar(s[i] ^ bits);
}
int
get_anything()
{
char tmpbuf[2];
reask_anything:
unflush_output(); /* disable any ^O in effect */
standout();
#ifdef VERBOSE
IF(verbose)
fputs("[Type space to continue] ",stdout);
ELSE
#endif
#ifdef TERSE
fputs("[MORE] ",stdout);
#endif
un_standout();
fflush(stdout);
eat_typeahead();
if (int_count) {
return -1;
}
cache_until_key();
getcmd(tmpbuf);
if (errno || *tmpbuf == '\f') {
putchar('\n') FLUSH; /* if return from stop signal */
goto reask_anything; /* give them a prompt again */
}
if (*tmpbuf == 'h') {
#ifdef VERBOSE
IF(verbose)
fputs("\nType q to quit or space to continue.\n",stdout) FLUSH;
ELSE
#endif
#ifdef TERSE
fputs("\nq to quit, space to continue.\n",stdout) FLUSH;
#endif
goto reask_anything;
}
else if (*tmpbuf != ' ' && *tmpbuf != '\n') {
carriage_return();
erase_eol(); /* erase the prompt */
carriage_return();
return *tmpbuf == 'q' ? -1 : *tmpbuf;
}
if (*tmpbuf == '\n') {
page_line = LINES - 1;
carriage_return();
erase_eol();
carriage_return();
}
else {
page_line = 1;
if (erase_screen) /* -e? */
clear(); /* clear screen */
else {
carriage_return();
erase_eol(); /* erase the prompt */
carriage_return();
}
}
return 0;
}
int
pause_getcmd()
{
unflush_output(); /* disable any ^O in effect */
standout();
#ifdef VERBOSE
IF(verbose)
fputs("[Type space or a command] ",stdout);
ELSE
#endif
#ifdef TERSE
fputs("[CMD] ",stdout);
#endif
un_standout();
fflush(stdout);
eat_typeahead();
if (int_count)
return -1;
cache_until_key();
getcmd(buf);
if (errno || *buf == '\f')
return 0; /* if return from stop signal */
else if (*buf != ' ') {
carriage_return();
erase_eol(); /* erase the prompt */
carriage_return();
return *buf;
}
return 0;
}
void
in_char(prompt, newmode)
char *prompt;
char_int newmode;
{
char oldmode = mode;
reask_in_char:
unflush_output(); /* disable any ^O in effect */
fputs(prompt,stdout);
fflush(stdout);
eat_typeahead();
mode = newmode;
getcmd(buf);
if (errno || *buf == '\f') {
putchar('\n') FLUSH; /* if return from stop signal */
goto reask_in_char; /* give them a prompt again */
}
mode = oldmode;
}
void
in_answer(prompt, newmode)
char *prompt;
char_int newmode;
{
char oldmode = mode;
reask_in_answer:
unflush_output(); /* disable any ^O in effect */
fputs(prompt,stdout);
fflush(stdout);
eat_typeahead();
mode = newmode;
reinp_in_answer:
getcmd(buf);
if (errno || *buf == '\f') {
putchar('\n') FLUSH; /* if return from stop signal */
goto reask_in_answer; /* give them a prompt again */
}
if (*buf != ' ' && *buf != '\n')
if (!finish_command(TRUE))
goto reinp_in_answer;
mode = oldmode;
}
int
print_lines(what_to_print,hilite)
char *what_to_print;
int hilite;
{
register char *s;
register int i;
if (page_line < 0) /* they do not want to see this? */
return -1;
for (s=what_to_print; *s; ) {
if (page_line >= LINES || int_count) {
if (i = -1, int_count || (i = get_anything())) {
page_line = -1; /* disable further print_lines */
return i;
}
}
page_line++;
if (hilite == STANDOUT) {
#ifdef NOFIREWORKS
if (erase_screen)
no_sofire();
#endif
standout();
}
else if (hilite == UNDERLINE) {
#ifdef NOFIREWORKS
if (erase_screen)
no_ulfire();
#endif
underline();
}
for (i=0; i<COLS; i++) {
if (!*s)
break;
if (*(unsigned char *)s >= ' ')
putchar(*s);
else if (*s == '\t') {
putchar(*s);
i = ((i+8) & ~7) - 1;
}
else if (*s == '\n') {
i = 32000;
}
else {
i++;
putchar('^');
putchar(*s + 64);
}
s++;
}
if (i) {
if (hilite == STANDOUT)
un_standout();
else if (hilite == UNDERLINE)
un_underline();
if (AM && i == COLS)
fflush(stdout);
else
putchar('\n') FLUSH;
}
}
return 0;
}
void
page_init()
{
page_line = 1;
if (erase_screen)
clear();
else
putchar('\n') FLUSH;
}
void
pad(num)
int num;
{
register int i;
for (i = num; i; --i)
putchar(PC);
fflush(stdout);
}
/* echo the command just typed */
#ifdef VERIFY
void
printcmd()
{
if (verify && buf[1] == FINISHCMD) {
if (*(unsigned char *)buf < ' ') {
putchar('^');
putchar(*buf | 64);
backspace();
backspace();
}
else {
putchar(*buf);
backspace();
}
fflush(stdout);
}
}
#endif
void
rubout()
{
backspace(); /* do the old backspace, */
putchar(' '); /* space, */
backspace(); /* backspace trick */
}
void
reprint()
{
register char *s;
fputs("^R\n",stdout) FLUSH;
for (s = buf; *s; s++) {
if (*(unsigned char *)s < ' ') {
putchar('^');
putchar(*s | 64);
}
else
putchar(*s);
}
}
void
home_cursor()
{
char *tgoto();
if (!*HO) { /* no home sequence? */
if (!*CM) { /* no cursor motion either? */
fputs("\n\n\n", stdout);
return; /* forget it. */
}
tputs(tgoto(CM, 0, 0), 1, putchr); /* go to home via CM */
return;
}
else { /* we have home sequence */
tputs(HO, 1, putchr); /* home via HO */
}
}
void
goto_line(from,to) /* assumes caller is already at beginning of line */
int from,to;
{
char *tgoto(), *str;
int cmcost;
if (from == to)
return;
if (*CM && !muck_up_clear)
cmcost = strlen(str = tgoto(CM,0,to));
else
cmcost = 9999;
if (to > from) {
go_down:
if (to - from <= cmcost) {
while(from++ < to)
putchar('\n');
return;
}
} else if(*UP) {
if ((from - to) * upcost <= cmcost) {
while(from-- > to)
tputs(UP,1,putchr);
return;
}
} else if (cmcost == 9999) {
home_cursor();
from = 0;
goto go_down;
}
tputs(str,1,putchr);
}
void
line_col_calcs()
{
if (LINES > 0) { /* is this a crt? */
if (!initlines || !initlines_specified)
/* no -i or unreasonable value for initlines */
if (outspeed >= B9600) /* whole page at >= 9600 baud */
initlines = LINES;
else if (outspeed >= B4800)/* 16 lines at 4800 */
initlines = 16;
else /* otherwise just header */
initlines = 8;
}
else { /* not a crt */
LINES = 30000; /* so don't page */
CL = "\n\n"; /* put a couple of lines between */
if (!initlines || !initlines_specified)
/* make initlines reasonable */
initlines = 8;
}
if (COLS <= 0)
COLS = 80;
}
#ifdef SIGWINCH
Signal_t
winch_catcher(dummy)
int dummy;
{
/* Reset signal in case of System V dain bramage */
sigset(SIGWINCH, winch_catcher);
/* Come here if window size change signal received */
#ifdef TIOCGWINSZ
{ struct winsize ws;
char lines[10], cols[10];
if (ioctl(0, TIOCGWINSZ, &ws) >= 0 && ws.ws_row > 0 && ws.ws_col > 0) {
if (LINES != ws.ws_row || COLS != ws.ws_col) {
LINES = ws.ws_row;
COLS = ws.ws_col;
line_col_calcs();
sprintf(lines, "%d", LINES);
sprintf(cols, "%d", COLS);
export("LINES",lines);
export("COLUMNS",cols);
if (mode == 't' || mode == 'a' || mode == 'p')
forceme("\f"); /* cause a refresh */
/* (defined only if TIOCSTI defined) */
}
}
}
#else
/* Well, if SIGWINCH is defined, but TIOCGWINSZ isn't, there's */
/* almost certainly something wrong. Figure it out for yourself, */
/* because I don't know how to deal with it :-) */
#endif
}
#endif
void
termlib_init()
{
#ifdef USETITE
if (TI && *TI)
tputs(TI,1,putchr);
#endif
return;
}
void
termlib_reset()
{
#ifdef USETITE
if (TE && *TE)
tputs(TE,1,putchr);
#endif
return;
}