v23i066: Complete reposting of TRN at patchlevel 1, Part07/14

Rich Salz rsalz at bbn.com
Fri Jan 4 04:54:17 AEST 1991


Submitted-by: Wayne Davison <0004475895 at mcimail.com>
Posting-number: Volume 23, Issue 66
Archive-name: trn/part07

#! /bin/sh
# This is a shell archive.  Remove anything before this line, then feed it
# into a shell via "sh file" or similar.  To overwrite existing files,
# type "sh file -c".
# The tool that generated this appeared in the comp.sources.unix newsgroup;
# send mail to comp-sources-unix at uunet.uu.net if you want that tool.
# Contents:  art.c init.c term.c
# Wrapped by rsalz at litchi.bbn.com on Thu Dec 27 11:34:06 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo If this archive is complete, you will see the following message:
echo '          "shar: End of archive 7 (of 14)."'
if test -f 'art.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'art.c'\"
else
  echo shar: Extracting \"'art.c'\" \(25145 characters\)
  sed "s/^X//" >'art.c' <<'END_OF_FILE'
X/* $Header: art.c,v 4.3.3.2 90/08/20 16:05:33 davison Trn $
X *
X * $Log:	art.c,v $
X * Revision 4.3.3.2  90/08/20  16:05:33  davison
X * Fixed bug in backpage code.
X * 
X * Revision 4.3.3.1  90/06/20  22:35:51  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.3  90/04/21  14:43:27  sob
X * Revised previous patch insure that it does not decrement below zero.
X * 
X * Revision 4.3.2.2  90/03/22  23:03:25  sob
X * Fixes provided by Wayne Davison <drivax!davison>
X * 
X * Revision 4.3.2.1  89/11/07  23:20:57  sob
X * Bug fixes for NNTP
X * 
X * Revision 4.3.1.5  85/09/10  11:07:18  lwall
X * %m not restored on some returns.
X * 
X * Revision 4.3.1.4  85/05/23  12:13:31  lwall
X * shouldn't display article that's really a subdirectory.
X * 
X * Revision 4.3.1.3  85/05/13  09:29:55  lwall
X * Added CUSTOMLINES option.
X * 
X * Revision 4.3.1.2  85/05/10  13:46:07  lwall
X * Fixed header reparse bug on backpage.
X * 
X * Revision 4.3.1.1  85/05/10  11:30:56  lwall
X * Branch for patches.
X * 
X * Revision 4.3  85/05/01  11:34:51  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "rn.h"
X#include "ngstuff.h"
X#include "ngdata.h"
X#include "head.h"
X#include "cheat.h"
X#include "help.h"
X#include "search.h"
X#include "artio.h"
X#include "ng.h"
X#include "bits.h"
X#include "final.h"
X#include "artstate.h"
X#include "rcstuff.h"
X#include "term.h"
X#include "sw.h"
X#include "util.h"
X#include "backpage.h"
X#include "intrp.h"
X#ifdef USETHREADS
X#include "rthreads.h"
X#endif
X#include "INTERN.h"
X#include "art.h"
X
X/* page_switch() return values */
X
X#define PS_NORM 0
X#define PS_ASK 1
X#define PS_RAISE 2
X#define PS_TOEND 3
X
Xbool special = FALSE;		/* is next page special length? */
Xint slines = 0;			/* how long to make page when special */
XART_LINE highlight = -1;	/* next line to be highlighted */
Xchar *restart = Nullch;		/* if nonzero, the place where last */
X				/* line left off on line split */
Xchar *blinebeg;			/* where in buffer current line began */
XART_POS alinebeg;		/* where in file current line began */
X
X#ifdef INNERSEARCH
XART_POS innersearch = 0;	/* artpos of end of line we found */
X				/* for 'g' command */
XART_LINE isrchline = 0;			/* last line to display */
Xbool hide_everything = FALSE;
X				/* if set, do not write page now, */
X				/* but refresh when done with page */
XCOMPEX gcompex;				/* in article search pattern */
X#endif
X
Xbool firstpage;			/* is this the 1st page of article? */
X
Xchar art_buf[LBUFLEN];		/* place for article lines */
X
Xvoid
Xart_init()
X{
X    ;
X}
X
Xint
Xdo_article()
X{
X    register char *s;
X    ART_POS artsize;			/* size in bytes of article */
X    bool hide_this_line = FALSE;	/* hidden header line? */
X    ART_LINE linenum;	/* line # on page, 1 origin */
X#ifdef ULSMARTS
X    bool under_lining = FALSE;
X			    /* are we underlining a word? */
X#endif
X    register char *bufptr = art_buf;
X			    /* pointer to input buffer */
X    register int outpos;	/* column position of output */
X    static char prompt_buf[64];		/* place to hold prompt */
X    bool notesfiles = FALSE;		/* might there be notesfiles junk? */
X    char oldmode = mode;
X
X#ifdef INNERSEARCH
X    register int outputok;
X#endif
X
X    if (fstat(artfp->_file,&filestat))
X			    /* get article file stats */
X	return DA_CLEAN;
X    if ((filestat.st_mode & S_IFMT) != S_IFREG)
X	return DA_NORM;
X    artsize = filestat.st_size;
X			    /* from that get article size */
X    sprintf(prompt_buf,
X	"%%sEnd of article %ld (of %ld)--what next? [%%s]",
X	(long)art,(long)lastart);	/* format prompt string */
X    prompt = prompt_buf;
X    int_count = 0;		/* interrupt count is 0 */
X    firstpage = (topline < 0);
X    for (;;) {			/* for each page */
X#ifdef USETHREADS
X	if (max_tree_lines)
X	    init_tree();	/* init tree display */
X#endif
X	assert(art == openart);
X	if (do_fseek) {
X#ifdef ASYNC_PARSE
X	    parse_maybe(art);		/* make sure header is ours */
X#endif
X	    artpos = vrdary(artline);
X	    if (artpos < 0)
X		artpos = -artpos;	/* labs(), anyone? */
X	    if (firstpage)
X		artpos = (ART_POS)0;
X	    fseek(artfp,artpos,0);
X	    if (artpos < htype[PAST_HEADER].ht_minpos)
X		in_header = SOME_LINE;
X	    do_fseek = FALSE;
X	    restart = Nullch;
X	}
X	linenum = 1;
X	if (firstpage) {
X	    if (firstline) {
X		interp(art_buf, (sizeof art_buf), firstline);
X#ifdef USETHREADS
X		linenum += tree_puts(art_buf,linenum+topline,0);
X#else
X#ifdef CLEAREOL
X		maybe_eol();	
X#endif /* CLEAREOL */
X		fputs(art_buf,stdout) FLUSH;
X		linenum++;
X#endif
X		artopen(art);		/* rewind article in case interp */
X					/* forced a header parse */
X	    }
X	    else {
X		ART_NUM i;
X
X#ifdef USETHREADS
X		if (ThreadedGroup) {
X		    int sel, unseen;
X
X		    sel = curr_p_art && (selected_roots[curr_p_art->root] & 1);
X		    unseen = !was_read(art);
X		    sprintf(art_buf,"%s%s #%ld",ngname,moderated,(long)art);
X		    if (selected_root_cnt) {
X			i = selected_count - (unseen && sel);
X			sprintf(art_buf+strlen(art_buf)," (%ld + %ld more)",
X			    (long)i,(long)toread[ng] - selected_count
X					- unthreaded - (!sel && unseen));
X		    }
X		    else if ((i = (ART_NUM)(toread[ng]-unthreaded-unseen)) != 0)
X			sprintf(art_buf+strlen(art_buf)," (%ld more)",(long)i);
X		    linenum += tree_puts(art_buf,linenum+topline,0);
X		}
X		else
X#endif
X		{
X#ifdef CLEAREOL
X		    maybe_eol();	
X#endif /* CLEAREOL */
X		    printf("Article %ld",(long)art);
X		    i = (ART_NUM)(toread[ng] - 1 + was_read(art));
X#ifdef DELAYMARK
X		    if (i || dmcount) {
X			printf(" (%ld more",(long)i);
X			if (dmcount)
X			    printf(" + %ld Marked to return)",(long)dmcount);
X			putchar(')');
X		    }
X#else
X		    if (i)
X			printf(" (%ld more)",(long)i);
X#endif
X		    if (htype[NGS_LINE].ht_flags & HT_HIDE)
X			printf(" in %s", ngname);
X		    fputs(moderated,stdout);
X		    fputs(":\n",stdout) FLUSH;
X		    linenum++;
X		}
X	    }
X	    start_header(art);
X	    forcelast = FALSE;		/* we will have our day in court */
X	    restart = Nullch;
X	    artline = 0;		/* start counting lines */
X	    artpos = 0;
X	    vwtary(artline,artpos);	/* remember pos in file */
X	}
X	for (;				/* linenum already set */
X	  in_header || (
X#ifdef INNERSEARCH
X	  innersearch ? innermore() :
X#endif
X	  linenum<(firstpage?initlines:(special?slines:LINES)) );
X	  linenum++) {		/* for each line on page */
X	    if (int_count) {	/* exit via interrupt? */
X		putchar('\n') FLUSH;	/* get to left margin */
X		int_count = 0;	/* reset interrupt count */
X		mode = oldmode;
X		special = FALSE;
X		return DA_NORM;	/* skip out of loops */
X	    }
X	    if (restart) {		/* did not finish last line? */
X		bufptr = restart;	/* then start again here */
X		restart = Nullch;	/* and reset the flag */
X	    }
X	    else {			/* not a restart */
X		if (fgets(art_buf,LBUFLEN,artfp)==Nullch) {
X					/* if all done */
X		    mode = oldmode;
X		    special = FALSE;
X		    return DA_NORM;	/* skip out of loops */
X		}
X		bufptr = art_buf;	/* so start at beginning */
X		art_buf[LBUFLEN-1] = '\0';
X					/* make sure string ends */
X	    }
X	    blinebeg = bufptr;	/* remember where we began */
X	    alinebeg = artpos;	/* both in buffer and file */
X	    if (in_header && bufptr == art_buf) {
X		hide_this_line =
X		    parseline(art_buf,do_hiding,hide_this_line);
X#ifdef USETHREADS
X		if (!in_header) {
X		    linenum += finish_tree(linenum+topline);
X		}
X#endif
X	    } else if (notesfiles && do_hiding &&
X	      bufptr == art_buf && *art_buf == '#' &&
X	      isupper(art_buf[1]) && art_buf[2] == ':' ) {
X		fgets(art_buf,sizeof(art_buf),artfp);
X		if (index(art_buf,'!') != Nullch)
X		    fgets(art_buf,sizeof(art_buf),artfp);
X		htype[PAST_HEADER].ht_minpos = ftell(artfp);
X					/* exclude notesfiles droppings */
X		hide_this_line = TRUE;	/* and do not print either */
X		notesfiles = FALSE;
X	    }
X#ifdef CUSTOMLINES
X	    if (hideline && bufptr == art_buf &&
X		  execute(&hide_compex,art_buf) )
X		hide_this_line = TRUE;
X#endif
X	    if (in_header && htype[in_header].ht_flags & HT_MAGIC) {
X		if (in_header == NGS_LINE) {
X		    hide_this_line = (index(art_buf,',') == Nullch);
X		}
X		else if (in_header == EXPIR_LINE) {
X		    if (!(htype[EXPIR_LINE].ht_flags & HT_HIDE))
X		    hide_this_line = (strlen(art_buf) < 10);
X		}
X		else if (in_header == FROM_LINE) {
X		    if (do_hiding && (s = index(art_buf+6,'(')) != Nullch) {
X			strcpy(art_buf+6,s+1);
X			if((s = rindex(art_buf+6,')')) != Nullch)
X			    *s = '\0';
X		    }
X		}
X#ifdef USETHREADS
X		else if (in_header == DATE_LINE && curr_p_art && do_hiding) {
X		    strcpy(art_buf+6,ctime(&curr_p_art->date));
X		}
X#endif
X	    }
X	    if (in_header == SUBJ_LINE &&
X		htype[SUBJ_LINE].ht_flags & HT_MAGIC) {
X			    /* is this the subject? */
X		int length;
X
X		length = strlen(art_buf)-1;
X		artline++;
X		art_buf[length] = '\0';		/* wipe out newline */
X#ifdef NOFIREWORKS
X		no_ulfire();
X#endif
X		notesfiles =
X		    (instr(&art_buf[length-10]," - (nf") != Nullch);
X#ifdef USETHREADS
X		/* tree_puts(, ,1) underlines subject */
X		linenum += tree_puts(art_buf,linenum+topline,1)-1;
X#else
X		if (oldsubject) {
X		    length += 7;
X		    fputs("(SAME) ",stdout);
X		    oldsubject = FALSE;
X		}
X		if (length+UG > COLS) {		/* rarely true */
X		    linenum++;
X		    vwtary(artline,vrdary(artline-1)+COLS);
X		    artline++;
X		}
X		s = art_buf + 8;
X		*s++ = '\0';	/* make into 2 strings */
X#ifdef CLEAREOL
X		maybe_eol();	
X#endif /* CLEAREOL */
X		fputs(art_buf,stdout) FLUSH;
X				/* print up through : */
X		if (!UG)
X		    putchar(' ');
X		underprint(s);	/* print subject underlined */
X		putchar('\n') FLUSH;	/* and finish the line */
X#endif
X	    }
X	    else if (hide_this_line && do_hiding) {
X					/* do not print line? */
X		linenum--;		/* compensate for linenum++ */
X		if (!in_header)
X		    hide_this_line = FALSE;
X	    }
X#ifdef USETHREADS
X	    else if (in_header) {
X		artline++;
X		linenum += tree_puts(art_buf,linenum+topline,0)-1;
X	    }
X#endif
X	    else {			/* just a normal line */
X		if (highlight==artline) {	/* this line to be highlit? */
X		    if (marking == STANDOUT) {
X#ifdef NOFIREWORKS
X			if (erase_screen)
X			    no_sofire();
X#endif
X			standout();
X		    }
X		    else {
X#ifdef NOFIREWORKS
X			if (erase_screen)
X			    no_ulfire();
X#endif
X			underline();
X		    }
X		    if (*bufptr == '\n')
X			putchar(' ');
X		}
X#ifdef INNERSEARCH
X		outputok = !hide_everything;
X					/* get it into register, hopefully */
X#endif
X#ifdef CLEAREOL
X#ifdef INNERSEARCH
X		if (outputok)
X#endif
X		maybe_eol();	
X#endif /* CLEAREOL */
X#ifdef CUSTOMLINES
X		if (pagestop && bufptr == art_buf && 
X		  execute(&page_compex,art_buf) )
X		    linenum = 32700;
X#endif
X		for (outpos = 0; outpos < COLS; ) {
X				    /* while line has room */
X		    if (*bufptr >= ' ') {	/* normal char? */
X#ifdef ULSMARTS
X			if (*bufptr == '_') {
X			    if (bufptr[1] == '\b') {
X				if (!under_lining && highlight!=artline
X#ifdef INNERSEARCH
X				    && outputok
X#endif
X				    ) {
X				    under_lining++;
X				    if (UG) {
X					if (bufptr != buf &&
X					  bufptr[-1] == ' ') {
X					    outpos--;
X					    backspace();
X					}
X				    }
X				    underline();
X				}
X				bufptr += 2;
X			    }
X			}
X			else {
X			    if (under_lining) {
X				under_lining = 0;
X				un_underline();
X				if (UG) {
X				    if (*bufptr == ' ')
X					goto skip_put;
X				    outpos++;
X				}
X			    }
X			}
X#endif
X#ifdef INNERSEARCH
X			if (outputok)
X#endif
X			{
X#ifdef ROTATION
X			    if (rotate && !in_header
X			      && isalpha(*bufptr)) {
X				if ((*bufptr & 31) <= 13)
X				    putchar(*bufptr+13);
X				else
X				    putchar(*bufptr-13);
X			    }
X			    else
X#endif
X				putchar(*bufptr);
X			}
X			if (*UC && ((highlight==artline && marking == 1)
X#ifdef ULSMARTS
X			    || under_lining
X#endif
X			    )) {
X			    backspace();
X			    underchar();
X			}
X		    skip_put:
X			bufptr++;
X			outpos++;
X		    }
X		    else if (*bufptr == '\n' || !*bufptr) {
X						    /* newline? */
X#ifdef ULSMARTS
X			if (under_lining) {
X			    under_lining = 0;
X			    un_underline();
X			}
X#endif
X#ifdef DEBUGGING
X			if (debug & DEB_INNERSRCH && outpos < COLS - 6) {
X			    standout();
X			    printf("%4d",artline); 
X			    un_standout();
X			}
X#endif
X#ifdef INNERSEARCH
X			if (outputok)
X#endif
X			    putchar('\n') FLUSH;
X			restart = 0;
X			outpos = 1000;	/* signal normal \n */
X		    }
X		    else if (*bufptr == '\t') {	/* tab? */
X#ifdef INNERSEARCH
X			if (outputok)
X#endif
X			    putchar(*bufptr);
X			bufptr++;
X			outpos += 8 - outpos % 8;
X		    }
X		    else if (*bufptr == '\f') {	/* form feed? */
X#ifdef INNERSEARCH
X			if (outputok)
X#endif
X			    fputs("^L",stdout);
X			if (bufptr == blinebeg && highlight != artline)
X			    linenum = 32700;
X			    /* how is that for a magic number? */
X			bufptr++;
X			outpos += 2;
X		    }
X		    else {		/* other control char */
X#ifdef INNERSEARCH
X			if (outputok)
X#endif
X			{
X			    putchar('^');
X			    if (highlight == artline && *UC && marking == 1) {
X				backspace();
X				underchar();
X				putchar(*bufptr+64);
X				backspace();
X				underchar();
X			    }
X			    else
X				putchar(*bufptr+64);
X			}
X			bufptr++;
X			outpos += 2;
X		    }
X		    
X		} /* end of column loop */
X
X		if (outpos < 1000) {/* did line overflow? */
X		    restart = bufptr;
X				    /* restart here next time */
X		    if (AM) {	/* automatic margins on tty? */
X			if (!XN && *bufptr == '\n')
X				    /* need we simulate XN? */
X			    restart = 0;
X				    /* skip the newline */
X		    }
X		    else {		/* cursor just hangs there */
X#ifdef INNERSEARCH
X			if (outputok)
X#endif
X			    putchar('\n') FLUSH;
X				    /* so move it down ourselves */
X			if (*bufptr == '\n')
X			    restart = 0;
X				    /* simulate XN if need be */
X		    }
X#ifdef CLEAREOL
X/* #ifdef INNERSEARCH
X		    if (outputok)
X#endif
X		    maybe_eol(); */	/* comment this out for now
X						    until I am sure it is
X						    needed*/
X
X#endif /* CLEAREOL */
X		}
X
X		/* handle normal end of output line formalities */
X
X		if (highlight == artline) {
X					/* were we highlighting line? */
X		    if (marking == STANDOUT)
X			un_standout();
X		    else
X			un_underline();
X		    highlight = -1;	/* no more we are */
X		}
X		artline++;	/* count the line just printed */
X		if (artline - LINES + 1 > topline)
X			    /* did we just scroll top line off? */
X		    topline = artline - LINES + 1;
X			    /* then recompute top line # */
X	    }
X
X	    /* determine actual position in file */
X
X	    if (restart)	/* stranded somewhere in the buffer? */
X		artpos += restart - blinebeg;
X			    /* just calculate position */
X	    else		/* no, ftell will do */
X		artpos = ftell(artfp);
X			    /* so do ftell */
X	    vwtary(artline,artpos);	/* remember pos in file */
X	} /* end of line loop */
X
X#ifdef INNERSEARCH
X	innersearch = 0;
X	if (hide_everything) {
X	    hide_everything = FALSE;
X	    *buf = Ctl('l');
X	    goto fake_command;
X	}
X#endif
X	if (linenum >= 32700)/* did last line have formfeed? */
X	    vwtary(artline-1,-vrdary(artline-1));
X			    /* remember by negating pos in file */
X
X	special = FALSE;	/* end of page, so reset page length */
X	firstpage = FALSE;	/* and say it is not 1st time thru */
X
X	/* extra loop bombout */
X
X	if (artpos == artsize) {/* did we just now reach EOF? */
X	    mode = oldmode;
X	    return DA_NORM;	/* avoid --MORE--(100%) */
X	}
X
X/* not done with this article, so pretend we are a pager */
X
Xreask_pager:		    
X	unflush_output();	/* disable any ^O in effect */
X	standout();		/* enter standout mode */
X	printf("--MORE--(%ld%%)",(long)(artpos*100/artsize));
X	un_standout();	/* leave standout mode */
X	fflush(stdout);
X/* reinp_pager:     			/* unused, commented for lint */
X	eat_typeahead();
X#ifdef DEBUGGING
X	if (debug & DEB_CHECKPOINTING) {
X	    printf("(%d %d %d)",checkcount,linenum,artline);
X	    fflush(stdout);
X	}
X#endif
X	if (checkcount >= docheckwhen &&
X	  linenum == LINES &&
X	  (artline > 40 || checkcount >= docheckwhen+10) ) {
X			    /* while he is reading a whole page */
X			    /* in an article he is interested in */
X	    checkcount = 0;
X	    checkpoint_rc();	/* update .newsrc */
X	}
X	collect_subjects();		/* loads subject cache until */
X					/* input is pending */
X	mode = 'p';
X	getcmd(buf);
X	if (errno) {
X	    if (LINES < 100 && !int_count)
X		*buf = '\f';/* on CONT fake up refresh */
X	    else {
X		*buf = 'q';	/* on INTR or paper just quit */
X	    }
X	}
X	carriage_return();
X#ifndef CLEAREOL
X	erase_eol();	/* and erase the prompt */
X#else
X	if (erase_screen && can_home_clear)	
X	    clear_rest();
X	else
X	    erase_eol();	/* and erase the prompt */
X#endif /* CLEAREOL */
X	carriage_return();	/* Resets kernel's tab column counter to 0 */
X	fflush(stdout);
X
X    fake_command:		/* used by innersearch */
X
X	/* parse and process pager command */
X
X	switch (page_switch()) {
X	case PS_ASK:	/* reprompt "--MORE--..." */
X	    goto reask_pager;
X	case PS_RAISE:	/* reparse on article level */
X	    mode = oldmode;
X	    return DA_RAISE;
X	case PS_TOEND:	/* fast pager loop exit */
X	    mode = oldmode;
X	    return DA_TOEND;
X	case PS_NORM:	/* display more article */
X	    break;
X	}
X    } /* end of page loop */
X}
X
X/* process pager commands */
X
Xint
Xpage_switch()
X{
X    register char *s;
X    
X    switch (*buf) {
X    case 'd':
X    case Ctl('d'):	/* half page */
X	special = TRUE;
X	slines = LINES / 2 + 1;
X	if (marking && *blinebeg != '\f'
X#ifdef CUSTOMLINES
X	  && (!pagestop || blinebeg != art_buf ||
X	      !execute(&page_compex,blinebeg))
X#endif
X	  ) {
X	    up_line();
X	    highlight = --artline;
X	    restart = blinebeg;
X	    artpos = alinebeg;
X	}
X	return PS_NORM;
X    case '!':			/* shell escape */
X	escapade();
X	return PS_ASK;
X#ifdef INNERSEARCH
X    case Ctl('i'):
X	gline = 3;
X	sprintf(cmd_buf,"^[^%c]",*blinebeg);
X	compile(&gcompex,cmd_buf,TRUE,TRUE);
X	goto caseG;
X    case Ctl('g'):
X	gline = 3;
X	compile(&gcompex,"^Subject:",TRUE,TRUE);
X	goto caseG;
X    case 'g':		/* in-article search */
X	if (!finish_command(FALSE))/* get rest of command */
X	    return PS_ASK;
X	s = buf+1;
X	if (isspace(*s))
X	    s++;
X	if ((s = compile(&gcompex,s,TRUE,TRUE)) != Nullch) {
X			    /* compile regular expression */
X	    printf("\n%s\n",s) FLUSH;
X	    return PS_ASK;
X	}
X	carriage_return();
X	erase_eol();	/* erase the prompt */
X	carriage_return();	/* Resets kernel's tab column counter to 0 */
X	/* FALL THROUGH */
X    caseG:
X    case 'G': {
X	/* ART_LINE lines_to_skip = 0; */
X	ART_POS start_where;
X
X	if (gline < 0 || gline > LINES-2)
X	    gline = LINES-2;
X#ifdef DEBUGGING
X	if (debug & DEB_INNERSRCH)
X	    printf("Start here? %d  >=? %d\n",topline + gline + 1,artline)
X	      FLUSH;
X#endif
X	if (*buf == Ctl('i') || topline+gline+1 >= artline)
X	    start_where = artpos;
X			/* in case we had a line wrap */
X	else {
X	    start_where = vrdary(topline+gline+1);
X	    if (start_where < 0)
X		start_where = -start_where;
X	}
X	if (start_where < htype[PAST_HEADER].ht_minpos)
X	    start_where = htype[PAST_HEADER].ht_minpos;
X	fseek(artfp,(long)start_where,0);
X	innersearch = 0; /* assume not found */
X	while (fgets(buf, sizeof buf, artfp) != Nullch) {
X	    /* lines_to_skip++; 		NOT USED NOW */
X#ifdef DEBUGGING
X	    if (debug & DEB_INNERSRCH)
X		printf("Test %s",buf) FLUSH;
X#endif
X	    if (execute(&gcompex,buf) != Nullch) {
X		innersearch = ftell(artfp);
X		break;
X	    }
X	}
X	if (!innersearch) {
X	    fseek(artfp,artpos,0);
X	    fputs("(Not found)",stdout) FLUSH;
X	    return PS_ASK;
X	}
X#ifdef DEBUGGING
X	if (debug & DEB_INNERSRCH)
X	    printf("On page? %ld <=? %ld\n",(long)innersearch,(long)artpos)
X	      FLUSH;
X#endif
X	if (innersearch <= artpos) {	/* already on page? */
X	    if (innersearch < artpos) {
X		artline = topline+1;
X		while (vrdary(artline) < innersearch)
X		    artline++;
X	    }
X	    highlight = artline - 1;
X#ifdef DEBUGGING
X	    if (debug & DEB_INNERSRCH)
X		printf("@ %d\n",highlight) FLUSH;
X#endif
X	    topline = highlight - gline;
X	    if (topline < -1)
X		topline = -1;
X	    *buf = '\f';		/* fake up a refresh */
X	    innersearch = 0;
X	    return page_switch();
X	}
X	else {				/* who knows how many lines it is? */
X	    do_fseek = TRUE;
X	    hide_everything = TRUE;
X	}
X	return PS_NORM;
X    }
X#else
X    case 'g': case 'G': case Ctl('g'):
X	notincl("g");
X	return PS_ASK;
X#endif
X    case '\n':		/* one line */
X	special = TRUE;
X	slines = 2;
X	return PS_NORM;
X#ifdef ROTATION
X    case 'X':
X	rotate = !rotate;
X	/* FALL THROUGH */
X#endif
X    case 'l':
X    case '\f':		/* refresh screen */
X#ifdef DEBUGGING
X	if (debug & DEB_INNERSRCH) {
X	    printf("Topline = %d",topline) FLUSH;
X	    gets(buf);
X	}
X#endif
X	clear();
X	carriage_return();	/* Resets kernel's tab column counter to 0 */
X	do_fseek = TRUE;
X	artline = topline;
X	if (artline < 0)
X	    artline = 0;
X	firstpage = (topline < 0);
X	return PS_NORM;
X    case 'b':
X    case '\b':
X    case Ctl('b'): {	/* back up a page */
X	ART_LINE target;
X
X#ifndef CLEAREOL
X	clear();
X#else
X	if (can_home_clear)	/* if we can home do it */
X	    home_cursor();
X	else
X	    clear();
X
X#endif /* CLEAREOL */
X	carriage_return();	/* Resets kernel's tab column counter to 0 */
X	do_fseek = TRUE;	/* reposition article file */
X	target = topline - (LINES - 2);
X	artline = topline;
X	if (artline >= 0) do {
X	    artline--;
X	} while(artline >= 0 && artline > target && vrdary(artline-1) >= 0);
X	topline = artline;
X			/* remember top line of screen */
X			/*  (line # within article file) */
X	if (artline < 0)
X	    artline = 0;
X	firstpage = (topline < 0);
X	return PS_NORM;
X    }
X    case 'h': {		/* help */
X	int cmd;
X
X	if ((cmd = help_page()) > 0)
X	    pushchar(cmd);
X	return PS_ASK;
X    }
X#ifdef USETHREADS
X    case 't':		/* output thread data */
X	page_line = 1;
X	p_art = curr_p_art;
X	entire_tree();
X	return PS_ASK;
X#endif
X    case '\177':
X    case '\0':		/* treat del,break as 'n' */
X	*buf = 'n';
X	/* FALL THROUGH */
X    case 'k':	case 'K':
X#ifdef USETHREADS
X    case 'T':	case 'J':
X#endif
X    case 'n':	case 'N':	case Ctl('n'):
X    case 's':	case 'S':
X    case 'e':
X    case 'u':
X    case 'w':	case 'W':
X    case '|':
X	mark_as_read();		/* mark article as read */
X	/* FALL THROUGH */
X#ifdef USETHREADS
X    case 'U':	case ',':
X    case '<':	case '>':
X    case '[':	case ']':
X    case '{':	case '}':
X    case '+':   case ':':
X#endif
X    case '#':
X    case '$':
X    case '&':
X    case '-':
X    case '.':
X    case '/':
X    case '1': case '2': case '3': case '4': case '5':
X    case '6': case '7': case '8': case '9':
X    case '=':
X    case '?':
X    case 'c':	case 'C':	
X#ifdef DEBUGGING
X    case 'D':
X#endif
X    case 'E':
X    case 'f':	case 'F':	
X    case 'j':
X				case Ctl('k'):
X    case 'm':	case 'M':	
X    case 'p':	case 'P':	case Ctl('p'):	
X		case 'Q':
X    case 'r':	case 'R':	case Ctl('r'):
X    case 'v':
X		case 'Y':
X#ifndef ROTATION
X    case 'x':	case 'X':
X#endif
X    case Ctl('x'):
X    case '^':
X
X#ifdef ROTATION
X	rotate = FALSE;
X#endif
X	reread = FALSE;
X	do_hiding = TRUE;
X	if (index("nNpP",*buf) == Nullch &&
X	  index("wWsSe:!&|/?123456789.",*buf) != Nullch) {
X	    setdfltcmd();
X	    standout();		/* enter standout mode */
X	    printf(prompt,mailcall,dfltcmd);
X			    /* print prompt, whatever it is */
X	    un_standout();	/* leave standout mode */
X	    putchar(' ');
X	    fflush(stdout);
X	}
X	return PS_RAISE;	/* and pretend we were at end */
X#ifdef ROTATION
X    case 'x':
X	rotate = TRUE;
X	/* FALL THROUGH */
X#endif
X    case 'y':
X    case Ctl('v'):
X					/* Leaving it undocumented in case */
X					/* I want to steal the key--LAW */
X    case ' ':	/* continue current article */
X	if (erase_screen) {	/* -e? */
X#ifndef CLEAREOL
X	    clear();		/* clear screen */
X#else
X	    if (can_home_clear)	/* if we can home do it */
X		home_cursor();
X	    else
X		clear();	/* else clear screen */
X
X#endif /* CLEAREOL */
X	    if (*blinebeg != '\f'
X#ifdef CUSTOMLINES
X	      && (!pagestop || blinebeg != art_buf ||
X	          !execute(&page_compex,blinebeg))
X#endif
X	      ) {
X		restart = blinebeg;
X		artline--;	 /* restart this line */
X		artpos = alinebeg;
X		if (marking)	/* and mark repeated line */
X		    highlight = artline;
X	    }
X	    topline = artline;
X			/* and remember top line of screen */
X			/*  (line # within article file) */
X	}
X	else if (marking && *blinebeg != '\f'
X#ifdef CUSTOMLINES
X	  && (!pagestop || blinebeg != art_buf ||
X	      !execute(&page_compex,blinebeg))
X#endif
X	  ) {
X				/* are we marking repeats? */
X	    up_line();		/* go up one line */
X	    highlight = --artline;/* and get ready to highlight */
X	    restart = blinebeg;	/*   the old line */
X	    artpos = alinebeg;
X	}
X	return PS_NORM;
X    case 'q':	/* quit this article? */
X	do_hiding = TRUE;
X	return PS_TOEND;
X    default:
X	fputs(hforhelp,stdout) FLUSH;
X	settle_down();
X	return PS_ASK;
X    }
X}
X
X#ifdef INNERSEARCH
Xbool
Xinnermore()
X{
X    if (artpos < innersearch) {		/* not even on page yet? */
X#ifdef DEBUGGING
X	if (debug & DEB_INNERSRCH)
X	    printf("Not on page %ld < %ld\n",(long)artpos,(long)innersearch)
X	      FLUSH;
X#endif
X	return TRUE;
X    }
X    if (artpos == innersearch) {	/* just got onto page? */
X	isrchline = artline;		/* remember first line after */
X	highlight = artline - 1;
X#ifdef DEBUGGING
X	if (debug & DEB_INNERSRCH)
X	    printf("There it is %ld = %ld, %d @ %d\n",(long)artpos,
X		(long)innersearch,hide_everything,highlight) FLUSH;
X#endif
X	if (hide_everything) {		/* forced refresh? */
X	    topline = highlight - gline;
X	    if (topline < -1)
X		topline = -1;
X	    return FALSE;		/* let refresh do it all */
X	}
X    }
X#ifdef DEBUGGING
X    if (debug & DEB_INNERSRCH)
X	printf("Not far enough? %d <? %d + %d\n",artline,isrchline,gline)
X	  FLUSH;
X#endif
X    if (artline < isrchline + gline) {
X	return TRUE;
X    }
X    return FALSE;
X}
X#endif
END_OF_FILE
  if test 25145 -ne `wc -c <'art.c'`; then
    echo shar: \"'art.c'\" unpacked with wrong size!
  fi
  # end of 'art.c'
fi
if test -f 'init.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'init.c'\"
else
  echo shar: Extracting \"'init.c'\" \(8405 characters\)
  sed "s/^X//" >'init.c' <<'END_OF_FILE'
X/* $Header: init.c,v 4.3.3.1 90/06/20 22:37:39 davison Trn $
X *
X * $Log:	init.c,v $
X * Revision 4.3.3.1  90/06/20  22:37:39  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.6  90/05/08  22:05:55  sob
X * Added quick startup (-q) flag.
X * 
X * Revision 4.3.2.5  90/05/04  23:10:01  sob
X * Fix for exiting "second" rn such that tty will be left in correct state.
X * Provided by glenn at mathcs.emory.edu
X * 
X * Revision 4.3.2.4  90/03/22  23:04:32  sob
X * Fixes provided by Wayne Davison <drivax!davison>
X * 
X * Revision 4.3.2.3  90/03/17  21:34:04  sob
X * Cleaned up a bit.
X * 
X * Revision 4.3.2.2  89/11/08  01:17:48  sob
X * Added changes to insure that this will compile for RN or RRN with no
X * changes to the source code.
X * 
X * Revision 4.3.2.1  89/11/06  00:39:14  sob
X * Added RRN support from NNTP 1.5
X * 
X * Revision 4.3.1.4  86/09/05  14:24:02  lwall
X * Removed net.announce dependency.
X * 
X * Revision 4.3.1.3  85/07/23  18:08:36  lwall
X * Fixed up NOLINEBUF option to work.
X * 
X * Revision 4.3.1.2  85/05/21  14:22:46  lwall
X * Sped up "rn -c" by avoiding unnecessary initialization.
X * 
X * Revision 4.3.1.1  85/05/10  11:33:39  lwall
X * Branch for patches.
X * 
X * Revision 4.3  85/05/01  16:16:13  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "util.h"
X#include "final.h"
X#include "term.h"
X#include "last.h"
X#include "rn.h"
X#include "rcstuff.h"
X#include "ngdata.h"
X#include "only.h"
X#include "intrp.h"
X#include "addng.h"
X#include "sw.h"
X#include "art.h"
X#include "artsrch.h"
X#include "artio.h"
X#include "backpage.h"
X#include "bits.h"
X#include "cheat.h"
X#include "head.h"
X#include "help.h"
X#include "kfile.h"
X#include "ngsrch.h"
X#include "ngstuff.h"
X#include "rcln.h"
X#include "respond.h"
X#ifdef SERVER
X#include "server.h"
X#endif
X#ifdef USETHREADS
X#include "rthreads.h"
X#endif
X#include "ng.h"
X#include "INTERN.h"
X#include "init.h"
X
Xbool
Xinitialize(argc,argv)
Xint argc;
Xchar *argv[];
X{
X    char *tcbuf;
X    register bool foundany = FALSE;
X    long time();
X#ifdef SERVER
X    char *server;
X    int response;
X#endif
X#ifdef NOLINEBUF
X    static char std_out_buf[BUFSIZ];	/* must be static or malloced */
X
X    setbuf(stdout, std_out_buf);
X#endif
X
X    tcbuf = safemalloc(1024);		/* make temp buffer for termcap and */
X					/* other initialization stuff */
X    
X    /* init terminal */
X    
X    term_init();			/* must precede sw_init() so that */
X					/* ospeed is set for baud-rate */
X					/* switches.  Actually terminal */
X					/* mode setting is in term_set() */
X
X    /* we have to know rnlib to look up global switches in %X/INIT */
X
X    lib = savestr(filexp(LIB));
X    rnlib = savestr(filexp(RNLIB));
X
X    /* decode switches */
X
X    sw_init(argc,argv,&tcbuf);          /* must not do % interps! */
X					/* (but may mung environment) */
X
X    /* init signals, status flags */
X
X    final_init();
X    
X    /* start up file expansion and the % interpreter */
X
X    intrp_init(tcbuf);
X    
X    /* now make sure we have a current working directory */
X
X    if (!checkflag)
X	cwd_check();
X    
X    /* now that we know where to save things, cd to news directory */
X
X    if (chdir(spool)) {
X	printf(nocd,spool) FLUSH;
X	finalize(1);
X    }
X
X    /* if we aren't just checking, turn off echo */
X
X    if (!checkflag)
X	term_set(tcbuf);
X
X    /* get info on last rn run, if any */
X
X    if (!checkflag)
X	last_init(tcbuf);
X
X    free(tcbuf);			/* recover 1024 bytes */
X
X    /* make sure we are the sole possessors of .newsrc */
X
X    if (!checkflag)
X	lock_check();
X
X    /* check for news news */
X
X    if (!checkflag)
X	newsnews_check();
X
X#ifdef SERVER
X
X    /* open connection to server if appropriate */
X
X    server = getserverbyfile(SERVER_FILE);
X    if (server == NULL) {
X	fprintf(stderr, "Can't get the name of the news server from %s\n",
X		SERVER_FILE);
X	fprintf(stderr,
X	  "Either fix this file, or put NNTPSERVER in your environment.\n");
X	finalize(1);
X    }
X
X    response = server_init(server);
X    if (response < 0) {
X	fprintf(stderr,
X	    "Couldn't connect to %s news server, try again later.\n",
X		server);
X	finalize(1);
X    }
X
X    if (handle_server_response(response, server) < 0)
X	finalize(1);
X
X#endif
X
X    /* open active file, etc. */
X
X    ngdata_init();
X
X    /* now read in the .newsrc file */
X
X    foundany = rcstuff_init();
X
X    /* it looks like we will actually read something, so init everything */
X
X    addng_init();
X    art_init();
X    artio_init();
X    artsrch_init();
X    backpage_init();
X    bits_init();
X    cheat_init();
X    head_init();
X    help_init();
X    kfile_init();
X    ng_init();
X    ngsrch_init();
X    ngstuff_init();
X    only_init();
X    rcln_init();
X    respond_init();
X    rn_init();
X    search_init();
X#ifdef USETHREADS
X    thread_init();
X#endif
X    util_init();
X
X#ifdef FINDNEWNG
X    fstat(actfp->_file,&filestat);	/* did active file grow? */
X	/*
X	 * Skip this check if the -q flag was given.
X	 */
X	
X    if (!quickstart && filestat.st_size != lastactsiz) {
X	long actsiz = filestat.st_size;	/* remember new size */
X	NG_NUM oldnext = nextrcline;	/* remember # lines in newsrc */
X#ifdef FASTNEW
X	bool munged = writesoft || !lastactsiz;
X					/* bad soft ptrs -> edited active */
X#else
X	bool munged = TRUE;		/* just assume .newsrc munged */
X#endif
X
X#ifdef VERBOSE
X	IF(verbose)
X	    fputs("\nChecking active list for new newsgroups...\n",stdout)
X	      FLUSH;
X	ELSE
X#endif
X#ifdef TERSE
X	    fputs("\nNew newsgroups:\n",stdout) FLUSH;
X#endif
X#ifdef FASTNEW
X	if (!munged) {			/* maybe just do tail of file? */
X	    fseek(actfp,lastactsiz-1,0);
X	    fgets(buf,LBUFLEN,actfp);
X	    munged = (*buf != '\n');
X	    if (!munged)
X		munged = newlist(munged,FALSE);
X	}
X#endif
X	if (munged) {			/* must we scan entire file? */
X	    fseek(actfp,0L,0);		/* rewind active file */
X	    newlist(munged,FALSE);      /* sure hope they use hashing... */
X	}
X	lastactsiz = actsiz;		/* remember for .rnlast */
X	if (nextrcline != oldnext) {	/* did we add any new groups? */
X	    foundany = TRUE;		/* let main() know */
X	    starthere = 0;              /* and start ng scan from the top */
X	}
X    }
X#endif
X    time(&lasttime);			/* remember when we inited-- */
X					/* ends up back in .rnlast */
X    writelast();                       /* in fact, put it there now */
X    
X#ifdef FINDNEWNG
X# ifdef ONLY
X    if (maxngtodo)			/* patterns on command line? */
X	foundany |= scanactive();
X# endif
X#endif
X
X    return foundany;
X}
X
X/* make sure there is no rn out there already */
X
Xvoid
Xlock_check()
X{
X    lockname = savestr(filexp(LOCKNAME));
X    if (!checkflag) {
X	tmpfp = fopen(lockname,"r");
X	if (tmpfp != Nullfp) {
X	    int processnum;
X    
X	    fgets(buf,LBUFLEN,tmpfp);
X	    fclose(tmpfp);
X	    processnum = atoi(buf);
X#ifdef VERBOSE
X	    IF(verbose)
X		printf("You seem to have left an rn running, process %d.\n",
X		    processnum) FLUSH;
X	    ELSE
X#endif
X#ifdef TERSE
X		printf("Rn left running, #%d.\n", processnum) FLUSH;
X#endif
X	    if (kill(processnum, SIGEMT)) {
X				    /* does process not exist? */
X				    /* (rn ignores SIGEMT) */
X		sleep(2);
X#ifdef VERBOSE
X		IF(verbose)
X		    fputs("\n\
XThat process does not seem to exist anymore.  The count of read articles\n\
Xmay be incorrect in the last newsgroup accessed by that other (defunct)\n\
Xprocess.\n\n",stdout) FLUSH;
X		ELSE
X#endif
X#ifdef TERSE
X		    fputs("\nProcess crashed.\n",stdout) FLUSH;
X#endif
X		if (*lastngname) {
X#ifdef VERBOSE
X		    IF(verbose)
X			printf("(The last newsgroup accessed was %s.)\n\n",
X			lastngname) FLUSH;
X		    ELSE
X#endif
X#ifdef TERSE
X			printf("(In %s.)\n\n",lastngname) FLUSH;
X#endif
X		}
X		get_anything();
X		putchar('\n') FLUSH;
X	    }
X	    else {
X#ifdef VERBOSE
X		IF(verbose)
X		    fputs("\n\
XYou may not have two copies of rn running simultaneously.  Goodbye.\n\
X",stdout) FLUSH;
X		ELSE
X#endif
X#ifdef TERSE
X		    fputs("\nCan't start another.\n",stdout) FLUSH;
X#endif
X               if (bizarre)
X                 resetty();
X		exit(0);
X	    }
X	}
X	tmpfp = fopen(lockname,"w");
X	if (tmpfp == Nullfp) {
X	    printf(cantcreate,lockname) FLUSH;
X	    sig_catcher(0);
X	}
X	fprintf(tmpfp,"%d\n",getpid());
X	fclose(tmpfp);
X    }
X}
X
Xvoid
Xnewsnews_check()
X{
X    char *newsnewsname = filexp(NEWSNEWSNAME);
X
X    if ((tmpfp = fopen(newsnewsname,"r")) != Nullfp) {
X	fstat(tmpfp->_file,&filestat);
X	if (filestat.st_mtime > lasttime) {
X	    while (fgets(buf,sizeof(buf),tmpfp) != Nullch)
X		fputs(buf,stdout) FLUSH;
X	    get_anything();
X	    putchar('\n') FLUSH;
X	}
X	fclose(tmpfp);
X    }
X}
END_OF_FILE
  if test 8405 -ne `wc -c <'init.c'`; then
    echo shar: \"'init.c'\" unpacked with wrong size!
  fi
  # end of 'init.c'
fi
if test -f 'term.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'term.c'\"
else
  echo shar: Extracting \"'term.c'\" \(25423 characters\)
  sed "s/^X//" >'term.c' <<'END_OF_FILE'
X/* $Header: term.c,v 4.3.3.1 90/07/28 18:09:09 davison Trn $
X *
X * $Log:	term.c,v $
X * Revision 4.3.3.1  90/07/28  18:09:09  davison
X * Initial Trn Release
X * 
X * Revision 4.3.2.7  90/04/21  16:54:29  sob
X * Installed patches provided by SCO for SCO Xenix
X * 
X * Revision 4.3.2.6  90/04/13  23:48:17  sob
X * Modifications provided by Gene Hackney for 3b2.
X * 
X * Revision 4.3.2.5  90/04/06  20:35:08  sob
X * Added fixes for SCO Xenix sent by ronald at robobar.co.uk.
X * 
X * Revision 4.3.2.4  90/03/22  23:05:38  sob
X * Fixes provided by Wayne Davison <drivax!davison>
X * 
X * Revision 4.3.2.3  89/11/28  01:51:58  sob
X * Now handles SIGWINCH correctly.
X * 
X * Revision 4.3.2.2  89/11/27  01:31:34  sob
X * Altered NNTP code per ideas suggested by Bela Lubkin
X * <filbo at gorn.santa-cruz.ca.us>
X * 
X * Revision 4.3.2.1  89/11/06  01:02:12  sob
X * Added RRN support from NNTP 1.5
X * 
X * Revision 4.3.1.3  85/09/10  11:05:23  lwall
X * Improved %m in in_char().
X * 
X * Revision 4.3.1.2  85/05/16  16:45:35  lwall
X * Forced \r to \n on input.
X * Fix for terminfo braindamage regarding bc emulation.
X * 
X * Revision 4.3.1.1  85/05/10  11:41:03  lwall
X * Branch for patches.
X * 
X * Revision 4.3  85/05/01  11:51:10  lwall
X * Baseline for release with 4.3bsd.
X * 
X */
X
X#include "EXTERN.h"
X#include "common.h"
X#include "util.h"
X#include "final.h"
X#include "help.h"
X#include "cheat.h"
X#include "intrp.h"
X#include "INTERN.h"
X#include "term.h"
X
X#ifdef SYS_PTEM
X#include <sys/stream.h>
X#include <sys/ptem.h>
X#endif
X
Xchar ERASECH;		/* rubout character */
Xchar KILLCH;		/* line delete character */
Xchar tcarea[TCSIZE];	/* area for "compiled" termcap strings */
X
X#ifdef USETHREADS
Xint upcost;
X#endif
X
X/* guarantee capability pointer != Nullch */
X/* (I believe terminfo will ignore the &tmpaddr argument.) */
X
X#define Tgetstr(key) ((tmpstr = tgetstr(key,&tmpaddr)) ? tmpstr : nullstr)
X
X#ifdef PUSHBACK
Xstruct keymap {
X    char km_type[128];
X    union km_union {
X	struct keymap *km_km;
X	char *km_str;
X    } km_ptr[128];
X};
X
X#define KM_NOTHIN 0
X#define KM_STRING 1
X#define KM_KEYMAP 2
X#define KM_BOGUS 3
X
X#define KM_TMASK 3
X#define KM_GSHIFT 4
X#define KM_GMASK 7
X
Xtypedef struct keymap KEYMAP;
X
XKEYMAP *topmap INIT(Null(KEYMAP*));
X
Xvoid mac_init();
XKEYMAP *newkeymap();
Xvoid show_keymap();
Xvoid pushstring();
X#endif
X
Xvoid line_col_calcs();
X
X/* terminal initialization */
X
Xvoid
Xterm_init()
X{
X    savetty();				/* remember current tty state */
X
X#ifdef TERMIO
X    ospeed = _tty.c_cflag & CBAUD;	/* for tputs() */
X    ERASECH = _tty.c_cc[VERASE];	/* for finish_command() */
X    KILLCH = _tty.c_cc[VKILL];		/* for finish_command() */
X#else
X    ospeed = _tty.sg_ospeed;		/* for tputs() */
X    ERASECH = _tty.sg_erase;		/* for finish_command() */
X    KILLCH = _tty.sg_kill;		/* for finish_command() */
X#endif
X
X    /* The following could be a table but I can't be sure that there isn't */
X    /* some degree of sparsity out there in the world. */
X
X    switch (ospeed) {			/* 1 second of padding */
X#ifdef BEXTA
X        case BEXTA:  just_a_sec = 1920; break;
X#else
X#ifdef B19200
X        case B19200: just_a_sec = 1920; break;
X#endif
X#endif
X        case B9600:  just_a_sec =  960; break;
X        case B4800:  just_a_sec =  480; break;
X        case B2400:  just_a_sec =  240; break;
X        case B1800:  just_a_sec =  180; break;
X        case B1200:  just_a_sec =  120; break;
X        case B600:   just_a_sec =   60; break;
X	case B300:   just_a_sec =   30; break;
X	/* do I really have to type the rest of this??? */
X        case B200:   just_a_sec =   20; break;
X        case B150:   just_a_sec =   15; break;
X        case B134:   just_a_sec =   13; break;
X        case B110:   just_a_sec =   11; break;
X        case B75:    just_a_sec =    8; break;
X        case B50:    just_a_sec =    5; break;
X        default:     just_a_sec =  960; break;
X					/* if we are running detached I */
X    }					/*  don't want to know about it! */
X}
X
X/* set terminal characteristics */
X
Xvoid
Xterm_set(tcbuf)
Xchar *tcbuf;		/* temp area for "uncompiled" termcap entry */
X{
X    char *tmpaddr;			/* must not be register */
X    register char *tmpstr;
X    char *tgetstr();
X    char *s;
X    int status;
X#ifdef TIOCGWINSZ
X#ifdef u3b2
Xstruct winsize {
X	unsigned short ws_row;       /* rows, in characters*/
X	unsigned short ws_col;       /* columns, in character */
X	unsigned short ws_xpixel;    /* horizontal size, pixels */
X	unsigned short ws_ypixel;    /* vertical size, pixels */
X};
X#endif
X    struct winsize winsize;
X#endif
X
X#ifdef PENDING
X#if ! defined (FIONREAD) && ! defined (RDCHK)
X    /* do no delay reads on something that always gets closed on exit */
X
X    devtty = open("/dev/tty",0);
X    if (devtty < 0) {
X	printf(cantopen,"/dev/tty") FLUSH;
X	finalize(1);
X    }
X    fcntl(devtty,F_SETFL,O_NDELAY);
X#endif
X#endif
X    
X    /* get all that good termcap stuff */
X
X#ifdef HAVETERMLIB
X    status = tgetent(tcbuf,getenv("TERM"));	/* get termcap entry */
X    if (status < 1) {
X#ifdef VERBOSE
X	printf("No termcap %s found.\n", status ? "file" : "entry") FLUSH;
X#else
X	fputs("Termcap botch\n",stdout) FLUSH;
X#endif
X	finalize(1);
X    }
X    tmpaddr = tcarea;			/* set up strange tgetstr pointer */
X    s = Tgetstr("pc");			/* get pad character */
X    PC = *s;				/* get it where tputs wants it */
X    if (!tgetflag("bs")) {		/* is backspace not used? */
X	BC = Tgetstr("bc");		/* find out what is */
X	if (BC == nullstr) 		/* terminfo grok's 'bs' but not 'bc' */
X	    BC = Tgetstr("le");
X    } else
X	BC = "\b";			/* make a backspace handy */
X    UP = Tgetstr("up");			/* move up a line */
X    if (!*UP)				/* no UP string? */
X	marking = 0;			/* disable any marking */
X    if (muck_up_clear)			/* this is for weird HPs */
X	CL = "\n\n\n\n";
X    else
X	CL = Tgetstr("cl");		/* get clear string */
X    CE = Tgetstr("ce");			/* clear to end of line string */
X#if defined(CLEAREOL) || defined(USETHREADS)
X    HO = Tgetstr("ho");			/* home cursor if no CM */
X    CM = Tgetstr("cm");			/* cursor motion */
X    if (*CM || *HO)
X	can_home = TRUE;
X#endif
X#ifdef CLEAREOL
X    CD = Tgetstr("cd");			/* clear to end of display */
X    if (!*CE || !*CD || !can_home)	/* can we CE, CD, and home? */
X	can_home_clear = FALSE;		/*  no, so disable use of clear eol */
X#endif /* CLEAREOL */
X#ifdef USETHREADS
X    upcost = strlen(UP);
X#endif
X    SO = Tgetstr("so");			/* begin standout */
X    SE = Tgetstr("se");			/* end standout */
X    if ((SG = tgetnum("sg"))<0)
X	SG = 0;				/* blanks left by SG, SE */
X    US = Tgetstr("us");			/* start underline */
X    UE = Tgetstr("ue");			/* end underline */
X    if ((UG = tgetnum("ug"))<0)
X	UG = 0;				/* blanks left by US, UE */
X    if (*US)
X	UC = nullstr;			/* UC must not be NULL */
X    else
X	UC = Tgetstr("uc");		/* underline a character */
X    if (!*US && !*UC) {			/* no underline mode? */
X	US = SO;			/* substitute standout mode */
X	UE = SE;
X	UG = SG;
X    }
X    LINES = tgetnum("li");		/* lines per page */
X    COLS = tgetnum("co");		/* columns on page */
X
X#ifdef TIOCGWINSZ
X    { struct winsize ws;
X	if (ioctl(0, TIOCGWINSZ, &ws) >= 0 && ws.ws_row > 0 && ws.ws_col > 0) {
X	    LINES = ws.ws_row;
X	    COLS = ws.ws_col;
X	}
X    }
X#endif
X	
X    AM = tgetflag("am");		/* terminal wraps automatically? */
X    XN = tgetflag("xn");		/* then eats next newline? */
X    VB = Tgetstr("vb");
X    if (!*VB)
X	VB = "\007";
X    CR = Tgetstr("cr");
X    if (!*CR) {
X	if (tgetflag("nc") && *UP) {
X	    CR = safemalloc((MEM_SIZE)strlen(UP)+2);
X	    sprintf(CR,"%s\r",UP);
X	}
X	else
X	    CR = "\r";
X    }
X#ifdef TIOCGWINSZ
X	if (ioctl(1, TIOCGWINSZ, &winsize)>=0) {
X		if (winsize.ws_row>0) LINES=winsize.ws_row;
X		if (winsize.ws_col>0) COLS=winsize.ws_col;
X	}
X#endif
X#else
X    ??????				/* Roll your own... */
X#endif
X    line_col_calcs();
X    noecho();				/* turn off echo */
X    crmode();				/* enter cbreak mode */
X
X#ifdef PUSHBACK
X    mac_init(tcbuf);
X#endif
X}
X
X#ifdef PUSHBACK
Xvoid
Xmac_init(tcbuf)
Xchar *tcbuf;
X{
X    char tmpbuf[1024];
X
X    tmpfp = fopen(filexp(getval("RNMACRO",RNMACRO)),"r");
X    if (tmpfp != Nullfp) {
X	while (fgets(tcbuf,1024,tmpfp) != Nullch) {
X	    mac_line(tcbuf,tmpbuf,(sizeof tmpbuf));
X	}
X	fclose(tmpfp);
X    }
X}
X
Xvoid
Xmac_line(line,tmpbuf,tbsize)
Xchar *line;
Xchar *tmpbuf;
Xint tbsize;
X{
X    register char *s, *m;
X    register KEYMAP *curmap;
X    register int ch;
X    register int garbage = 0;
X    static char override[] = "\nkeymap overrides string\n";
X
X    if (topmap == Null(KEYMAP*))
X	topmap = newkeymap();
X    if (*line == '#' || *line == '\n')
X	return;
X    if (line[ch = strlen(line)-1] == '\n')
X	line[ch] = '\0';
X    m = dointerp(tmpbuf,tbsize,line," \t");
X    if (!*m)
X	return;
X    while (*m == ' ' || *m == '\t') m++;
X    for (s=tmpbuf,curmap=topmap; *s; s++) {
X	ch = *s & 0177;
X	if (s[1] == '+' && isdigit(s[2])) {
X	    s += 2;
X	    garbage = (*s & KM_GMASK) << KM_GSHIFT;
X	}
X	else
X	    garbage = 0;
X	if (s[1]) {
X	    if ((curmap->km_type[ch] & KM_TMASK) == KM_STRING) {
X		fputs(override,stdout) FLUSH;
X		free(curmap->km_ptr[ch].km_str);
X		curmap->km_ptr[ch].km_str = Nullch;
X	    }
X	    curmap->km_type[ch] = KM_KEYMAP + garbage;
X	    if (curmap->km_ptr[ch].km_km == Null(KEYMAP*))
X		curmap->km_ptr[ch].km_km = newkeymap();
X	    curmap = curmap->km_ptr[ch].km_km;
X	}
X	else {
X	    if ((curmap->km_type[ch] & KM_TMASK) == KM_KEYMAP)
X		fputs(override,stdout) FLUSH;
X	    else {
X		curmap->km_type[ch] = KM_STRING + garbage;
X		curmap->km_ptr[ch].km_str = savestr(m);
X	    }
X	}
X    }
X}
X
XKEYMAP*
Xnewkeymap()
X{
X    register int i;
X    register KEYMAP *map;
X
X#ifndef lint
X    map = (KEYMAP*)safemalloc(sizeof(KEYMAP));
X#else
X    map = Null(KEYMAP*);
X#endif /* lint */
X    for (i=127; i>=0; --i) {
X	map->km_ptr[i].km_km = Null(KEYMAP*);
X	map->km_type[i] = KM_NOTHIN;
X    }
X    return map;
X}
X
Xvoid
Xshow_macros()
X{
X    char prebuf[64];
X
X    if (topmap != Null(KEYMAP*)) {
X	print_lines("Macros:\n",STANDOUT);
X	*prebuf = '\0';
X	show_keymap(topmap,prebuf);
X    }
X    else {
X	print_lines("No macros defined.\n", NOMARKING);
X    }
X}
X
Xvoid
Xshow_keymap(curmap,prefix)
Xregister KEYMAP *curmap;
Xchar *prefix;
X{
X    register int i;
X    register char *next = prefix + strlen(prefix);
X    register int kt;
X
X    for (i=0; i<128; i++) {
X	if (kt = curmap->km_type[i]) {
X	    if (i < ' ')
X		sprintf(next,"^%c",i+64);
X	    else if (i == ' ')
X		strcpy(next,"\\040");
X	    else if (i == 127)
X		strcpy(next,"^?");
X	    else
X		sprintf(next,"%c",i);
X	    if ((kt >> KM_GSHIFT) & KM_GMASK) {
X		sprintf(cmd_buf,"+%d", (kt >> KM_GSHIFT) & KM_GMASK);
X		strcat(next,cmd_buf);
X	    }
X	    switch (kt & KM_TMASK) {
X	    case KM_NOTHIN:
X		sprintf(cmd_buf,"%s	%c\n",prefix,i);
X		print_lines(cmd_buf,NOMARKING);
X		break;
X	    case KM_KEYMAP:
X		show_keymap(curmap->km_ptr[(char)i].km_km, prefix);
X		break;
X	    case KM_STRING:
X		sprintf(cmd_buf,"%s	%s\n",prefix,curmap->km_ptr[i].km_str);
X		print_lines(cmd_buf,NOMARKING);
X		break;
X	    case KM_BOGUS:
X		sprintf(cmd_buf,"%s	BOGUS\n",prefix);
X		print_lines(cmd_buf,STANDOUT);
X		break;
X	    }
X	}
X    }
X}
X
X#endif
X
X/* routine to pass to tputs */
X
Xchar
Xputchr(ch)
Xregister char ch;
X{
X    putchar(ch);
X#ifdef lint
X    ch = Null(char);
X    ch = ch;
X#endif
X    return((char) 0);
X}
X
X/* input the 2nd and succeeding characters of a multi-character command */
X/* returns TRUE if command finished, FALSE if they rubbed out first character */
X
Xbool
Xfinish_command(donewline)
Xint donewline;
X{
X    register char *s;
X    register bool quoteone = FALSE;
X
X    s = buf;
X    if (s[1] != FINISHCMD)		/* someone faking up a command? */
X	return TRUE;
X    do {
X      top:
X	if ((unsigned char)*s < ' ') {
X	    putchar('^');
X	    putchar(*s | 64);
X	}
X	else if (*s == '\177') {
X	    putchar('^');
X	    putchar('?');
X	}
X	else
X	    putchar(*s);		/* echo previous character */
X	s++;
Xre_read:
X	fflush(stdout);
X	getcmd(s);
X	if (quoteone) {
X	    quoteone = FALSE;
X	    continue;
X	}
X	if (errno || *s == Ctl('l')) {
X	    *s = Ctl('r');		/* force rewrite on CONT */
X	}
X	if (*s == '\033') {		/* substitution desired? */
X#ifdef ESCSUBS
X	    char tmpbuf[4], *cpybuf;
X
X	    tmpbuf[0] = '%';
X	    read_tty(&tmpbuf[1],1);
X#ifdef RAWONLY
X	    tmpbuf[1] &= 0177;
X#endif
X	    tmpbuf[2] = '\0';
X	    if (tmpbuf[1] == 'h') {
X		(void) help_subs();
X		*s = '\0';
X		reprint();
X		goto re_read;
X	    }
X	    else if (tmpbuf[1] == '\033') {
X		*s = '\0';
X		cpybuf = savestr(buf);
X		interp(buf, (sizeof buf), cpybuf);
X		free(cpybuf);
X		s = buf + strlen(buf);
X		reprint();
X		goto re_read;
X	    }
X	    else {
X		interp(s,(sizeof buf) - (s-buf),tmpbuf);
X		fputs(s,stdout);
X		s += strlen(s);
X	    }
X	    goto re_read;
X#else
X	    notincl("^[");
X	    *s = '\0';
X	    reprint();
X	    goto re_read;
X#endif
X	}
X	else if (*s == ERASECH) {	/* they want to rubout a char? */
X	    rubout();
X	    s--;			/* discount the char rubbed out */
X	    if ((unsigned char)*s < ' ' || *s == '\177')
X		rubout();
X	    if (s == buf) {		/* entire string gone? */
X		fflush(stdout);		/* return to single char command mode */
X		return FALSE;
X	    }
X	    else
X		goto re_read;
X	}
X	else if (*s == KILLCH) {	/* wipe out the whole line? */
X	    while (s-- != buf) {	/* emulate that many ERASEs */
X		rubout();
X		if ((unsigned char)*s < ' ' || *s == '\177')
X		    rubout();
X	    }
X	    fflush(stdout);
X	    return FALSE;		/* return to single char mode */
X	}
X#ifdef WORDERASE
X	else if (*s == Ctl('w')) {	/* wipe out one word? */
X	    *s-- = ' ';
X	    while (!isspace(*s) || isspace(s[1])) {
X		rubout();
X		if (s-- == buf) {
X		    fflush(stdout);
X		    return FALSE;	/* return to single char mode */
X		}
X		if ((unsigned char)*s < ' ' || *s == '\177')
X		    rubout();
X	    }
X	    s++;
X	    goto re_read;
X	}
X#endif
X	else if (*s == Ctl('r')) {
X	    *s = '\0';
X	    reprint();
X	    goto re_read;
X	}
X	else if (*s == Ctl('v')) {
X	    putchar('^');
X	    backspace();
X	    fflush(stdout);
X	    getcmd(s);
X	    goto top;
X	}
X	else if (*s == '\\') {
X	    quoteone = TRUE;
X	}
X    } while (*s != '\n');		/* till a newline (not echoed) */
X    *s = '\0';				/* terminate the string nicely */
X    if (donewline)
X	putchar('\n') FLUSH;
X    return TRUE;			/* say we succeeded */
X}
X
X/* discard any characters typed ahead */
X
Xvoid
Xeat_typeahead()
X{
X#ifdef PUSHBACK
X    if (!typeahead && nextin==nextout)	/* cancel only keyboard stuff */
X#else
X    if (!typeahead)
X#endif
X    {
X#ifdef PENDING
X	while (input_pending())
X	    read_tty(buf,sizeof(buf));
X#else /* this is probably v7 */
X	ioctl(_tty_ch,TIOCSETP,&_tty);
X#endif
X    }
X}
X
Xvoid
Xsettle_down()
X{
X    dingaling();
X    fflush(stdout);
X    sleep(1);
X#ifdef PUSHBACK
X    nextout = nextin;			/* empty circlebuf */
X#endif
X    eat_typeahead();
X}
X
X#ifdef PUSHBACK
X/* read a character from the terminal, with multi-character pushback */
X
Xint
Xread_tty(addr,size)
Xchar *addr;
Xint size;
X{
X    if (nextout != nextin) {
X	*addr = circlebuf[nextout++];
X	nextout %= PUSHSIZE;
X	return 1;
X    }
X    else {
X	size = read(0,addr,size);
X#ifdef RAWONLY
X	*addr &= 0177;
X#endif
X	return size;
X    }
X}
X
X#ifdef PENDING
X#if ! defined (FIONREAD) && ! defined (RDCHK)
Xint
Xcircfill()
X{
X    register int Howmany = read(devtty,circlebuf+nextin,1);
X
X    if (Howmany) {
X	nextin += Howmany;
X	nextin %= PUSHSIZE;
X    }
X    return Howmany;
X}
X#endif /* PENDING */
X#endif /* FIONREAD */
X
Xvoid
Xpushchar(c)
Xchar c;
X{
X    nextout--;
X    if (nextout < 0)
X	nextout = PUSHSIZE - 1;
X    if (nextout == nextin) {
X	fputs("\npushback buffer overflow\n",stdout) FLUSH;
X	sig_catcher(0);
X    }
X    circlebuf[nextout] = c;
X}
X
X#else /* PUSHBACK */
X#ifndef read_tty
X/* read a character from the terminal, with hacks for O_NDELAY reads */
X
Xint
Xread_tty(addr,size)
Xchar *addr;
Xint size;
X{
X    if (is_input) {
X	*addr = pending_ch;
X	is_input = FALSE;
X	return 1;
X    }
X    else {
X	size = read(0,addr,size);
X#ifdef RAWONLY
X	*addr &= 0177;
X#endif
X	return size;
X    }
X}
X#endif /* read_tty */
X#endif /* PUSHBACK */
X
X/* print an underlined string, one way or another */
X
Xvoid
Xunderprint(s)
Xregister char *s;
X{
X    assert(UC);
X    if (*UC) {		/* char by char underline? */
X	while (*s) {
X	    if ((unsigned char)*s < ' ') {
X		putchar('^');
X		backspace();/* back up over it */
X		underchar();/* and do the underline */
X		putchar(*s+64);
X		backspace();/* back up over it */
X		underchar();/* and do the underline */
X	    }
X	    else {
X		putchar(*s);
X		backspace();/* back up over it */
X		underchar();/* and do the underline */
X	    }
X	    s++;
X	}
X    }
X    else {		/* start and stop underline */
X	underline();	/* start underlining */
X	while (*s) {
X	    if ((unsigned char)*s < ' ') {
X		putchar('^');
X		putchar(*s+64);
X	    }
X	    else
X		putchar(*s);
X	    s++;
X	}
X	un_underline();	/* stop underlining */
X    }
X}
X
X/* keep screen from flashing strangely on magic cookie terminals */
X
X#ifdef NOFIREWORKS
Xvoid
Xno_sofire()
X{
X    if (*UP && *SE) {		/* should we disable fireworks? */
X	putchar('\n');
X	un_standout();
X	up_line();
X	carriage_return();
X    }
X}
X
Xvoid
Xno_ulfire()
X{
X    if (*UP && *US) {		/* should we disable fireworks? */
X	putchar('\n');
X	un_underline();
X	up_line();
X	carriage_return();
X    }
X}
X#endif
X
X/* get a character into a buffer */
X
Xvoid
Xgetcmd(whatbuf)
Xregister char *whatbuf;
X{
X#ifdef PUSHBACK
X    register KEYMAP *curmap;
X    register int i;
X    bool no_macros; 
X    int times = 0;			/* loop detector */
X    char scrchar;
X
Xtryagain:
X    curmap = topmap;
X    no_macros = (whatbuf != buf && nextin == nextout); 
X#endif
X    for (;;) {
X	int_count = 0;
X	errno = 0;
X	if (read_tty(whatbuf,1) < 0)
X	    if (!errno)
X	        errno = EINTR;
X	    else {
X	    perror(readerr);
X	    sig_catcher(0);
X	}
X#ifdef PUSHBACK
X	if (*whatbuf & 0200 || no_macros) {
X	    *whatbuf &= 0177;
X	    goto got_canonical;
X	}
X	if (curmap == Null(KEYMAP*))
X	    goto got_canonical;
X	for (i = (curmap->km_type[*whatbuf] >> KM_GSHIFT) & KM_GMASK; i; --i){
X	    read_tty(&scrchar,1);
X	}
X	switch (curmap->km_type[*whatbuf] & KM_TMASK) {
X	case KM_NOTHIN:			/* no entry? */
X	    if (curmap == topmap)	/* unmapped canonical */
X		goto got_canonical;
X	    settle_down();
X	    goto tryagain;
X	case KM_KEYMAP:			/* another keymap? */
X	    curmap = curmap->km_ptr[*whatbuf].km_km;
X	    assert(curmap != Null(KEYMAP*));
X	    break;
X	case KM_STRING:			/* a string? */
X	    pushstring(curmap->km_ptr[*whatbuf].km_str);
X	    if (++times > 20) {		/* loop? */
X		fputs("\nmacro loop?\n",stdout);
X		settle_down();
X	    }
X	    no_macros = FALSE;
X	    goto tryagain;
X	}
X#else
X#ifdef RAWONLY
X	*whatbuf &= 0177;
X#endif
X	break;
X#endif
X    }
X
Xgot_canonical:
X#ifndef TERMIO
X    if (*whatbuf == '\r')
X	*whatbuf = '\n';
X#endif
X    if (whatbuf == buf)
X	whatbuf[1] = FINISHCMD;		/* tell finish_command to work */
X}
X
X#ifdef PUSHBACK
Xvoid
Xpushstring(str)
Xchar *str;
X{
X    register int i;
X    char tmpbuf[PUSHSIZE];
X    register char *s = tmpbuf;
X
X    assert(str != Nullch);
X    interp(s,PUSHSIZE,str);
X    for (i = strlen(s)-1; i >= 0; --i) {
X	s[i] ^= 0200; 
X	pushchar(s[i]);
X    }
X}
X#endif
X
Xint
Xget_anything()
X{
X    char tmpbuf[2];
X
Xreask_anything:
X    unflush_output();			/* disable any ^O in effect */
X    standout();
X#ifdef VERBOSE
X    IF(verbose)
X	fputs("[Type space to continue] ",stdout);
X    ELSE
X#endif
X#ifdef TERSE
X	fputs("[MORE] ",stdout);
X#endif
X    un_standout();
X    fflush(stdout);
X    eat_typeahead();
X    if (int_count) {
X	return -1;
X    }
X    collect_subjects();			/* loads subject cache until */
X					/* input is pending */
X    getcmd(tmpbuf);
X    if (errno || *tmpbuf == '\f') {
X	putchar('\n') FLUSH;		/* if return from stop signal */
X	goto reask_anything;		/* give them a prompt again */
X    }
X    if (*tmpbuf == 'h') {
X#ifdef VERBOSE
X	IF(verbose)
X	    fputs("\nType q to quit or space to continue.\n",stdout) FLUSH;
X	ELSE
X#endif
X#ifdef TERSE
X	    fputs("\nq to quit, space to continue.\n",stdout) FLUSH;
X#endif
X	goto reask_anything;
X    }
X    else if (*tmpbuf != ' ' && *tmpbuf != '\n') {
X	carriage_return();
X	erase_eol();	/* erase the prompt */
X	carriage_return();
X	return *tmpbuf == 'q' ? -1 : *tmpbuf;
X    }
X    if (*tmpbuf == '\n') {
X	page_line = LINES - 1;
X	carriage_return();
X	erase_eol();
X	carriage_return();
X    }
X    else {
X	page_line = 1;
X	if (erase_screen)		/* -e? */
X	    clear();			/* clear screen */
X	else {
X	    carriage_return();
X	    erase_eol();		/* erase the prompt */
X	    carriage_return();
X	}
X    }
X    return 0;
X}
X
X#ifdef USETHREADS
Xint
Xpause_getcmd()
X{
X    unflush_output();			/* disable any ^O in effect */
X    standout();
X#ifdef VERBOSE
X    IF(verbose)
X	fputs("[Type space or a command] ",stdout);
X    ELSE
X#endif
X#ifdef TERSE
X	fputs("[CMD] ",stdout);
X#endif
X    un_standout();
X    fflush(stdout);
X    eat_typeahead();
X    if (int_count) {
X	return -1;
X    }
X    getcmd(buf);
X    if (errno || *buf == '\f') {
X	return 0;			/* if return from stop signal */
X    }
X    else if (*buf != ' ') {
X	carriage_return();
X	erase_eol();	/* erase the prompt */
X	carriage_return();
X	return *buf;
X    }
X    return 0;
X}
X#endif
X
Xvoid
Xin_char(prompt, newmode)
Xchar *prompt;
Xchar newmode;
X{
X    char oldmode = mode;
X
Xreask_in_char:
X    unflush_output();			/* disable any ^O in effect */
X    fputs(prompt,stdout);
X    fflush(stdout);
X    eat_typeahead();
X    mode = newmode;
X    getcmd(buf);
X    if (errno || *buf == '\f') {
X	putchar('\n') FLUSH;		/* if return from stop signal */
X	goto reask_in_char;		/* give them a prompt again */
X    }
X    mode = oldmode;
X}
X
Xint
Xprint_lines(what_to_print,hilite)
Xchar *what_to_print;
Xint hilite;
X{
X    register char *s;
X    register int i;
X
X    if (page_line < 0)			/* they do not want to see this? */
X	return -1;
X    for (s=what_to_print; *s; ) {
X	if (page_line >= LINES || int_count) {
X	    if (i = -1, int_count || (i = get_anything())) {
X		page_line = -1;		/* disable further print_lines */
X		return i;
X	    }
X	}
X	page_line++;
X	if (hilite == STANDOUT) {
X#ifdef NOFIREWORKS
X	    if (erase_screen)
X		no_sofire();
X#endif
X	    standout();
X	}
X	else if (hilite == UNDERLINE) {
X#ifdef NOFIREWORKS
X	    if (erase_screen)
X		no_ulfire();
X#endif
X	    underline();
X	}
X	for (i=0; i<COLS; i++) {
X	    if (!*s)
X		break;
X	    if ((unsigned char)*s >= ' ')
X		putchar(*s);
X	    else if (*s == '\t') {
X		putchar(*s);
X		i = ((i+8) & ~7) - 1; 
X	    }
X	    else if (*s == '\n') {
X		i = 32000;
X	    }
X	    else {
X		i++;
X		putchar('^');
X		putchar(*s + 64);
X	    }
X	    s++;
X	}
X	if (i) {
X	    if (hilite == STANDOUT)
X		un_standout();
X	    else if (hilite == UNDERLINE)
X		un_underline();
X	    if (AM && i == COLS)
X		fflush(stdout);
X	    else
X		putchar('\n') FLUSH;
X	}
X    }
X    return 0;
X}
X
Xvoid
Xpage_init()
X{
X    page_line = 1;
X    if (erase_screen)
X	clear();
X    else
X	putchar('\n') FLUSH;
X}
X
Xvoid
Xpad(num)
Xint num;
X{
X    register int i;
X
X    for (i = num; i; --i)
X	putchar(PC);
X    fflush(stdout);
X}
X
X/* echo the command just typed */
X
X#ifdef VERIFY
Xvoid
Xprintcmd()
X{
X    if (verify && buf[1] == FINISHCMD) {
X	if ((unsigned char)*buf < ' ') {
X	    putchar('^');
X	    putchar(*buf | 64);
X	    backspace();
X	    backspace();
X	}
X	else {
X	    putchar(*buf);
X	    backspace();
X	}
X	fflush(stdout);
X    }
X}
X#endif
X
Xvoid
Xrubout()
X{
X    backspace();			/* do the old backspace, */
X    putchar(' ');			/*   space, */
X    backspace();			/*     backspace trick */
X}
X
Xvoid
Xreprint()
X{
X    register char *s;
X
X    fputs("^R\n",stdout) FLUSH;
X    for (s = buf; *s; s++) {
X	if ((unsigned char)*s < ' ') {
X	    putchar('^');
X	    putchar(*s | 64);
X	}
X	else
X	    putchar(*s);
X    }
X}
X
X#if defined(CLEAREOL) || defined(USETHREADS)
Xvoid
Xhome_cursor()
X{
X    char *tgoto();
X
X    if (!*HO) {			/* no home sequence? */
X	if (!*CM) {		/* no cursor motion either? */
X	    fputs ("\n\n\n", stdout);
X	    return;		/* forget it. */
X	}
X	tputs (tgoto (CM, 0, 0), 1, putchr);	/* go to home via CM */
X	return;
X    }
X    else {			/* we have home sequence */
X	tputs (HO, 1, putchr);	/* home via HO */
X    }
X}
X#endif
X
X#ifdef USETHREADS
Xvoid
Xgoto_line(from,to)	/* assumes caller is already at beginning of line */
Xint from,to;
X{
X    char *tgoto(), *str;
X    int cmcost;
X
X    if (from == to) {
X	return;
X    }
X    if (*CM) {
X	cmcost = strlen(str = tgoto(CM,0,to));
X    } else {
X	cmcost = 9999;
X    }
X    if (to > from) {
X      go_down:
X	if (to - from <= cmcost) {
X	    while(from++ < to) {
X		putchar('\n');
X	    }
X	    return;
X	}
X    } else if(*UP) {
X	if ((from - to) * upcost <= cmcost) {
X	    while(from-- > to) {
X		tputs(UP,1,putchr);
X	    }
X	    return;
X	}
X    } else if (cmcost == 9999) {
X	home_cursor();
X	from = 0;
X	goto go_down;
X    }
X    tputs(str,1,putchr);
X}
X#endif
X
X
Xvoid
Xline_col_calcs()
X{
X     if (LINES > 0) {			/* is this a crt? */
X	  if ((!initlines) || (!initlines_specified))
X	       /* no -i or unreasonable value for initlines */
X	       if (ospeed >= B9600) 	/* whole page at >= 9600 baud */
X		    initlines = LINES;
X	       else if (ospeed >= B4800)/* 16 lines at 4800 */
X		    initlines = 16;
X	       else			/* otherwise just header */
X		    initlines = 8;
X     }
X     else {				/* not a crt */
X	  LINES = 30000;		/* so don't page */
X	  CL = "\n\n";			/* put a couple of lines between */
X	  if ((!initlines) || (!initlines_specified))
X	       /* make initlines reasonable */
X	       initlines = 8;
X     }
X     if (COLS <= 0)
X	  COLS = 80;
X}
X
X
X#ifdef SIGWINCH
Xint
Xwinch_catcher()
X{
X     /* Come here if window size change signal received */
X#ifdef TIOCGWINSZ
X     struct winsize ws;
X
X     if (ioctl(0, TIOCGWINSZ, &ws) >= 0 && ws.ws_row > 0 && ws.ws_col > 0) {
X          LINES = ws.ws_row;
X          COLS = ws.ws_col;
X          line_col_calcs();
X     }
X#else
X     ???????
X     /* Well, if SIGWINCH is defined, but TIOCGWINSZ isn't, there's    */
X     /* almost certainly something wrong.  Figure it out for yourself, */
X     /* because I don't know now to deal :-)                           */
X#endif
X}
X#endif
END_OF_FILE
  if test 25423 -ne `wc -c <'term.c'`; then
    echo shar: \"'term.c'\" unpacked with wrong size!
  fi
  # end of 'term.c'
fi
echo shar: End of archive 7 \(of 14\).
cp /dev/null ark7isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 14 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still must unpack the following archives:
    echo "        " ${MISSING}
fi
exit 0
exit 0 # Just in case...
-- 
Please send comp.sources.unix-related mail to rsalz at uunet.uu.net.
Use a domain-based address or give alternate paths, or you may lose out.



More information about the Comp.sources.unix mailing list