Vile 15/17 - vi feel-alike (multi-window)

Paul Fox pgf at cayman.COM
Sat Jun 8 08:10:19 AEST 1991


#!/bin/sh
# this is vileshar.15 (part 15 of Vile)
# do not concatenate these parts, unpack them in order with /bin/sh
# file tags continued
#
if test ! -r _shar_seq_.tmp; then
	echo 'Please unpack part 1 first!'
	exit 1
fi
(read Scheck
 if test "$Scheck" != 15; then
	echo Please unpack part "$Scheck" next!
	exit 1
 else
	exit 0
 fi
) < _shar_seq_.tmp || exit 1
echo 'x - continuing file tags'
sed 's/^X//' << 'SHAR_EOF' >> 'tags' &&
va_list	display.c	1509
va_start	display.c	/^#define va_start(list) list = (char *) &va_alist$/
varinit	eval.c	/^varinit()		\/* initialize the user variable list *\//
vcalloc	vmalloc.c	/^vcalloc(n,size,f,l)$/
vdump	vmalloc.c	/^vdump(id)$/
vfree	vmalloc.c	/^vfree(buffer,f,l)$/
vglobals	globals.c	/^vglobals(f,n)$/
viewfile	file.c	/^viewfile(f, n)	\/* visit a file in VIEW mode *\/$/
visual	main.c	/^visual() { return unimpl(); }$/
vmalloc	vmalloc.c	/^vmalloc(size,f,l)$/
vmalloc.c	vmalloc.c	1
void	search.c	/^#define	void	int$/
vrealloc	vmalloc.c	/^vrealloc(buffer,size,f,l)$/
vteeol	display.c	/^vteeol()$/
vtgetc	display.c	/^vtgetc(col)$/
vtinit	display.c	/^vtinit()$/
vtmove	display.c	/^vtmove(row, col)$/
vtputc	display.c	/^vtputc(c,list)$/
vtputsn	display.c	/^vtputsn(s,n)$/
vttidy	display.c	/^vttidy(f)$/
vverify	estruct.h	/^# define vverify(s) rvverify(s,__FILE__,__LINE__)$/
window.c	window.c	1
winit	window.c	/^winit()$/
word.c	word.c	1
wordcount	word.c	/^wordcount(f, n)$/
wordmov.c	wordmov.c	1
wpopup	window.c	/^wpopup()$/
wrapword	word.c	/^wrapword()$/
writemsg	random.c	/^writemsg(f, n)$/
writeout	file.c	/^writeout(fn,bp,msgf)$/
writequit	main.c	/^writequit(f,n)$/
writereg	file.c	/^writereg(rp,fn,msgf)$/
writeregion	file.c	/^writeregion(f,n)$/
yankline	random.c	/^yankline(f, n)$/
yankregion	region.c	/^yankregion(f, n)$/
zotbuf	buffer.c	/^zotbuf(bp)	\/* kill the buffer pointed to by bp *\/$/
SHAR_EOF
echo 'File tags is complete' &&
chmod 0444 tags ||
echo 'restore of tags failed'
Wc_c="`wc -c < 'tags'`"
test 57909 -eq "$Wc_c" ||
	echo 'tags: original size 57909, current size' "$Wc_c"
# ============= tags.c ==============
echo 'x - extracting tags.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'tags.c' &&
#include	"estruct.h"
#include        "edef.h"
X
#if TAGS
X
#ifndef NULL
#define NULL 0
#endif
X
/* Look up vi-style tags in the file "tags".
X	Invoked either by ":ta routine-name" or by "^]" while sitting
X	on a string.  In the latter case, the tag is the word under
X	the cursor.
X	written for vile by Paul Fox, (c)1990
X */
gototag(f,n)
{
X	register int i = 0;
X	register int s = TRUE;
X	static char tname[NFILEN];
X
X	if (clexec || isnamedcmd) {
X	        if ((s=mlreply("Tag name: ", tname, NFILEN)) != TRUE)
X	                return (s);
X	} else {
X		screen_string(tname,NFILEN,_ident);
X	}
X	if (s == TRUE)
X		s = tags(tname);
X	return s;
}
X
static BUFFER *tagbp;
X
tags(tag)
char *tag;
{
X	BUFFER *ocurbp;
X	register LINE *lp, *clp;
X	register int i, s;
X	char *tfp, *lplim;
X	char tname[NFILEN];
X	char tfname[NFILEN];
X	char tagpat[NPAT];
X	int lineno;
X	int changedfile;
X	LINE *odotp;
X	int odoto;
X	LINE *cheap_scan();
X
X	strcpy(tname,tag);
X
X	if (tagbp == NULL) {
X		if (gettagsfile() == FALSE)
X			return FALSE;
X	}
X
X	strcat(tname,"\t");
X
X	lp = cheap_scan(tagbp,tname);
X	if (lp == NULL) {
X		TTbeep();
X		mlwrite("No such tag: %s",tname);
X		return FALSE;
X	}
X	
X	tfp = lp->l_text + strlen(tname);
X	lplim = &lp->l_text[lp->l_used];
X	i = 0;
X	while (i < NFILEN && tfp < lplim && *tfp != '\t') {
X		tfname[i++] = *tfp++;
X	}
X	if (tfp >= lplim - 2) {
X		mlwrite("Bad line in tags file.");
X		return FALSE;
X	}
X
X	if (curbp && curwp) {
X		lineno = 1;
X	        for(clp = lforw(curbp->b_linep); 
X				clp != curwp->w_dotp; clp = lforw(clp))
X			lineno++;
X		pushuntag(curbp->b_fname, lineno);
X	}
X
X	tfname[i] = 0;
X	if (curbp == NULL || strcmp(tfname,curbp->b_fname)) {
X		s = getfile(tfname,TRUE);
X		if (s != TRUE) {
X			tossuntag();
X			return s;
X		}
X		changedfile = TRUE;
X	} else {
X		tname[strlen(tname)-1] = '\0'; /* get rid of tab we added */
X		mlwrite("[Tag \"%s\" in current buffer]", tname);
X		changedfile = FALSE;
X	}
X
X	/* it's an absolute move -- remember where we are */
X	odotp  = curwp->w_dotp;
X	odoto  = curwp->w_doto;
X
X	i = 0;
X	tfp++;  /* skip the tab */
X	if (isdigit(*tfp)) { /* then it's a line number */
X		int lineno = 0;
X		while (isdigit(*tfp)) {
X			lineno = 10*lineno + *tfp - '0';
X			tfp++;
X		}
X		s = gotoline(TRUE,lineno);
X		if (s != TRUE && !changedfile)
X			tossuntag();
X	} else {
X		tfp += 2; /* skip the "/^" */
X		lplim -= 2; /* skip the "$/" */
X		while (i < NPAT && tfp < lplim) {
X			if (*tfp == '\\' && tfp < lplim - 1)
X				tfp++;  /* the backslash escapes the next char */
X			tagpat[i++] = *tfp++;
X		}
X		tagpat[i] = 0;
X		lp = cheap_scan(curbp,tagpat);
X		if (lp == NULL) {
X			mlwrite("Tag not present");
X			if (!changedfile)
X				tossuntag();
X			return FALSE;
X		}
X		curwp->w_dotp = lp;
X		curwp->w_flag |= WFMOVE;
X		firstnonwhite(FALSE,1);
X		s = TRUE;
X	}
X	/* if we moved, update the "last dot" mark */
X	if (s == TRUE && curwp->w_dotp != odotp) {
X		curwp->w_ldmkp = odotp;
X		curwp->w_ldmko = odoto;
X	}
X	return s;
X	
}
X
gettagsfile()
{
X	int s;
X	char *tagsfile;
X
X	/* is there a "tags" buffer around? */
X        if ((tagbp=bfind("tags", NO_CREAT, 0)) == NULL) {
X		/* look up the tags file */
X		tagsfile = flook("tags", FL_HERE);
X
X		/* if it isn't around, don't sweat it */
X		if (tagsfile == NULL)
X		{
X	        	mlwrite("No tags file available.");
X			return(FALSE);
X		}
X
X		/* find the pointer to that buffer */
X	        if ((tagbp=bfind("tags", OK_CREAT, BFINVS)) == NULL) {
X	        	mlwrite("No tags buffer");
X	                return(FALSE);
X	        }
X
X		if ((s = readin(tagsfile, FALSE, tagbp, FALSE)) != TRUE) {
X			return(s);
X		}
X		tagbp->b_flag |= BFINVS;
X        }
X	return TRUE;
}
X
LINE *
cheap_scan(bp,name)
BUFFER *bp;
char *name;
{
X	LINE *lp;
X	register int len;
X	len = strlen(name);
X	lp = lforw(bp->b_linep);
X	while (lp != bp->b_linep) {
X		if (llength(lp) >= len) {
X			if (llength(lp) >= len &&
X				 !strncmp(lp->l_text, name, len))
X				return lp;
X		}
X		lp = lforw(lp);
X	}
X	return NULL;
}
X
untagpop(f,n)
int f,n;
{
X	int lineno;
X	char fname[NFILEN];
X	if (!f) n = 1;
X	while (n-- && popuntag(fname,&lineno))
X		;
X	if (lineno && fname[0]) {
X		int s;
X		s = getfile(fname,FALSE);
X		if (s != TRUE)
X			return s;
X		return gotoline(TRUE,lineno);
X	}
X	TTbeep();
X	mlwrite("No stacked un-tags");
X	return FALSE;
}
X
X
struct untag {
X	char *u_fname;
X	int u_lineno;
X	struct untag *u_stklink;
};
X
struct untag *untaghead = NULL;
X
pushuntag(fname,lineno)
char *fname;
int lineno;
{
X	struct untag *utp;
X	utp = (struct untag *)malloc(sizeof(struct untag));
X	if (!utp)
X		return;
X
X	utp->u_fname = (char *)malloc(strlen(fname)+1);
X	if (!utp->u_fname) {
X		free(utp);
X		return;
X	}
X
X	strcpy(utp->u_fname, fname);
X	utp->u_lineno = lineno;
X	utp->u_stklink = untaghead;
X	untaghead = utp;
}
X
popuntag(fname,linenop)
char *fname;
int *linenop;
{
X	register struct untag *utp;
X
X	if (untaghead) {
X		utp = untaghead;
X		untaghead = utp->u_stklink;
X		strcpy(fname, utp->u_fname);
X		*linenop = utp->u_lineno;
X		free(utp->u_fname);
X		free(utp);
X		return TRUE;
X	}
X	fname[0] = '\0';
X	*linenop = 0;
X	return FALSE;
X
}
X
/* discard without returning anything */
tossuntag()
{
X	register struct untag *utp;
X
X	if (untaghead) {
X		utp = untaghead;
X		untaghead = utp->u_stklink;
X		free(utp);
X	}
X	return;
X
}
X
BUFFER *filesbp;
X
X
/* create a filelist from the contents of
X *	the tags file.  for "dir1/dir2/file" include both that and
X *	"dir1/dir2/"
X */
makeflist()
{
X	register LINE *tlp, *flp;
X	register char *fnp;
X	register int i;
X	register int len;
X	char fname[NFILEN];
X	char *strchr();
X
X	if (!(othmode & OTH_LAZY))
X		return TRUE;
X
X	if (!tagbp && gettagsfile() == FALSE)
X			return FALSE;
X
X	if (filesbp != NULL)
X		return TRUE;
X
X	/* create the file list buffer   */
X	filesbp = bfind("[files]", OK_CREAT, BFINVS);
X	if (filesbp == NULL)
X		return FALSE;
X	filesbp->b_active = TRUE;
X
X	/* loop through the tags file */
X	tlp = lforw(tagbp->b_linep);
X	while (tlp != tagbp->b_linep) {
X		/* skip the tagname */
X		i = 0;
X		while (i < llength(tlp) && lgetc(tlp,i++) != '\t')
X			;
X		/* we're going to store the pathnames reversed, so that
X			the sorting puts all directories together (they'll
X			all start with their trailing slash) and all 
X			files with matching basenames will be grouped
X			together as well.
X		*/
X		/* pull out the filename, in reverse */
X		fnp = &fname[NFILEN-1];
X		*fnp-- = '\0';
X		while (i < llength(tlp)  && fnp >= fname && 
X					(*fnp = lgetc(tlp,i++)) != '\t') {
X			fnp--;
X		}
X		fnp++; /* forward past the tab */
X
X		/* insert into the file list */
X		if (sortsearch(fnp, &fname[NFILEN-1]-fnp, filesbp,
X							TRUE, NULL) == NULL)
X			return FALSE;
X
X		if (fnp = strchr(fnp, '/')) { /* first (really last) slash */
X			/* insert the directory name into the file list again */
X			if (sortsearch(fnp, &fname[NFILEN-1]-fnp, filesbp,
X							TRUE, NULL) == NULL)
X				return FALSE;
X		}
X		tlp = lforw(tlp);
X	}
X	return TRUE;
}
X
/* look for or insert a text string into the given buffer.  start looking
X	at the given line if non-null. */
sortsearch(text, len,  bp, insert, lpp)
char *text;
int len;
BUFFER *bp;
int insert;
LINE **lpp;
{
X	LINE *nlp, *lp;
X	register int i, r, cmplen;
X
X	if (lpp == NULL) {
X		lp = lforw(bp->b_linep);
X	} else {
X		lp = *lpp;
X		if (lp == NULL)
X			lp = lforw(bp->b_linep);
X		else
X			lp = lforw(lp);
X	}
X
X	while (1) {
X		cmplen = (len < llength(lp) && !insert) ? len : llength(lp);
X		if ((r = strncmp(text, lp->l_text, cmplen)) > 0 ||
X		     lp == bp->b_linep) { /* stick line into buffer */
X		     	if (!insert)
X				return FALSE;
X		        if ((nlp=lalloc(len)) == NULL)
X		                return FALSE;
X			memcpy(nlp->l_text, text, len);
X		        lp->l_bp->l_fp = nlp;
X		        nlp->l_bp = lp->l_bp;
X		        lp->l_bp = nlp;
X		        nlp->l_fp = lp;
X			if (lpp)
X				*lpp = nlp;
X			return TRUE;
X		} else if (r == 0) { /* it's already here, don't insert twice */
X			if (lpp)
X				*lpp = lp;
X			return TRUE;
X		}
X		lp = lforw(lp);
X	}
}
X
X
#else
taghello() { }
#endif
SHAR_EOF
chmod 0444 tags.c ||
echo 'restore of tags.c failed'
Wc_c="`wc -c < 'tags.c'`"
test 7806 -eq "$Wc_c" ||
	echo 'tags.c: original size 7806, current size' "$Wc_c"
# ============= tcap.c ==============
echo 'x - extracting tcap.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'tcap.c' &&
/*	tcap:	Unix V5, V7 and BS4.2 Termcap video driver
X		for MicroEMACS
*/
X
#define	termdef	1			/* don't define "term" external */
X
#include <stdio.h>
#include	"estruct.h"
#include        "edef.h"
#include <signal.h>
X
#if TERMCAP
X
#define	MARGIN	8
#define	SCRSIZ	64
#define	NPAUSE	10			/* # times thru update to pause */
#define BEL     0x07
#define ESC     0x1B
X
extern int      ttopen();
extern int      ttgetc();
extern int      ttputc();
extern int	tgetnum();
extern int      ttflush();
extern int      ttclose();
extern int	tcapkopen();
extern int	tcapkclose();
extern int      tcapmove();
extern int      tcapeeol();
extern int      tcapeeop();
extern int      tcapbeep();
extern int	tcaprev();
extern int	tcapcres();
extern int      tcapopen();
extern int      tput();
extern char     *tgoto();
#if	COLOR
extern	int	tcapfcol();
extern	int	tcapbcol();
#endif
#if	SCROLLCODE
extern	int	tcapscroll_reg();
extern	int	tcapscroll_delins();
#endif
X
#define TCAPSLEN 315
char tcapbuf[TCAPSLEN];
char *UP, PC, *CM, *CE, *CL, *SO, *SE;
X
#if	SCROLLCODE
char *CS, *DL, *AL, *SF, *SR;
#endif
X
TERM term = {
X	NULL,	/* these four values are set dynamically at open time */
X	NULL,
X	NULL,
X	NULL,
X	MARGIN,
X	SCRSIZ,
X	NPAUSE,
X        tcapopen,
X        ttclose,
X        tcapkopen,
X        tcapkclose,
X        ttgetc,
X        ttputc,
X        ttflush,
X        tcapmove,
X        tcapeeol,
X        tcapeeop,
X        tcapbeep,
X        tcaprev,
X        tcapcres
#if	COLOR
X	, tcapfcol,
X	tcapbcol
#endif
#if	SCROLLCODE
X	, NULL		/* set dynamically at open time */
#endif
};
X
tcapopen()
{
X        char *getenv();
X        char *t, *p, *tgetstr();
X        char tcbuf[1024];
X        char *tv_stype;
X        char err_str[72];
X
X        if ((tv_stype = getenv("TERM")) == NULL)
X        {
X                puts("Environment variable TERM not defined!");
X                exit(1);
X        }
X
X        if ((tgetent(tcbuf, tv_stype)) != 1)
X        {
X                sprintf(err_str, "Unknown terminal type %s!", tv_stype);
X                puts(err_str);
X                exit(1);
X        }
X
X	/* Get screen size from system, or else from termcap.  */
X	getscreensize(&term.t_ncol, &term.t_nrow);
X 
X	if ((term.t_nrow <= 0) && (term.t_nrow=(short)tgetnum("li")) == -1) {
X		puts("termcap entry incomplete (lines)");
X		exit(1);
X	}
X	term.t_nrow -= 1;
X
X
X	if ((term.t_ncol <= 0) &&(term.t_ncol=(short)tgetnum("co")) == -1){
X		puts("Termcap entry incomplete (columns)");
X		exit(1);
X	}
X
#ifdef SIGWINCH
X	term.t_mrow =  200;
X	term.t_mcol = 200;
#else
X	term.t_mrow =  term.t_nrow;
X	term.t_mcol =  term.t_ncol;
#endif
X        p = tcapbuf;
X        t = tgetstr("pc", &p);
X        if(t)
X                PC = *t;
X
X        CL = tgetstr("cl", &p);
X        CM = tgetstr("cm", &p);
X        CE = tgetstr("ce", &p);
X        UP = tgetstr("up", &p);
X	SE = tgetstr("se", &p);
X	SO = tgetstr("so", &p);
X	if (SO != NULL)
X		revexist = TRUE;
X
X        if(CL == NULL || CM == NULL || UP == NULL)
X        {
X                puts("Incomplete termcap entry\n");
X                exit(1);
X        }
X
X	if (CE == NULL)		/* will we be able to use clear to EOL? */
X		eolexist = FALSE;
#if SCROLLCODE
X        CS = tgetstr("cs", &p);
X        SF = tgetstr("sf", &p);
X        SR = tgetstr("sr", &p);
X	DL = tgetstr("dl", &p);
X	AL = tgetstr("al", &p);
X	
X	if (CS && SR) {
X		if (SF == NULL) /* assume '\n' scrolls forward */
X			SF = "\n";
X		term.t_scroll = tcapscroll_reg;
X	} else if (DL && AL) {
X		term.t_scroll = tcapscroll_delins;
X	} else {
X		term.t_scroll = NULL;
X	}
#endif
X		
X        if (p >= &tcapbuf[TCAPSLEN])
X        {
X                puts("Terminal description too big!\n");
X                exit(1);
X        }
X        ttopen();
}
X
tcapkopen()
{
X	strcpy(sres, "NORMAL");
}
X
tcapkclose()
{
}
X
tcapmove(row, col)
register int row, col;
{
X        putpad(tgoto(CM, col, row));
}
X
tcapeeol()
{
X        putpad(CE);
}
X
tcapeeop()
{
X        putpad(CL);
}
X
tcaprev(state)		/* change reverse video status */
int state;		/* FALSE = normal video, TRUE = reverse video */
{
X	static int revstate = -1;
X	if (state == revstate)
X		return;
X	revstate = state;
X	if (state) {
X		if (SO != NULL)
X			putpad(SO);
X	} else {
X		if (SE != NULL)
X			putpad(SE);
X	}
}
X
tcapcres()	/* change screen resolution */
{
X	return(TRUE);
}
X
#if SCROLLCODE
X
/* move howmany lines starting at from to to */
tcapscroll_reg(from,to,howmany)
{
X	int i;
X	if (to == from) return;
X	if (to < from) {
X		tcapscrollregion(to, from + howmany - 1);
X		tcapmove(from + howmany - 1,0);
X		for (i = from - to; i > 0; i--)
X			putpad(SF);
X	} else { /* from < to */
X		tcapscrollregion(from, to + howmany - 1);
X		tcapmove(from,0);
X		for (i = to - from; i > 0; i--)
X			putpad(SR);
X	}
X	tcapscrollregion(0, term.t_nrow);
}
X
/* 
PRETTIER_SCROLL is prettier but slower -- it scrolls 
X		a line at a time instead of all at once.
*/
X
/* move howmany lines starting at from to to */
tcapscroll_delins(from,to,howmany)
{
X	int i;
X	if (to == from) return;
#if PRETTIER_SCROLL
X	if (abs(from-to) > 1) {
X		tcapscroll_delins(from, (from<to) ? to-1:to+1, howmany);
X		if (from < to)
X			from = to-1;
X		else
X			from = to+1;	
X	}
#endif
X	if (to < from) {
X		tcapmove(to,0);
X		for (i = from - to; i > 0; i--)
X			putpad(DL);
X		tcapmove(to+howmany,0);
X		for (i = from - to; i > 0; i--)
X			putpad(AL);
X	} else {
X		tcapmove(from+howmany,0);
X		for (i = to - from; i > 0; i--)
X			putpad(DL);
X		tcapmove(from,0);
X		for (i = to - from; i > 0; i--)
X			putpad(AL);
X	}
}
X
/* cs is set up just like cm, so we use tgoto... */
tcapscrollregion(top,bot)
{
X        putpad(tgoto(CS, bot, top));
}
X
#endif
X
spal(dummy)	/* change palette string */
{
X	/*	Does nothing here	*/
}
X
#if	COLOR
tcapfcol()	/* no colors here, ignore this */
{
}
X
tcapbcol()	/* no colors here, ignore this */
{
}
#endif
X
tcapbeep()
{
X	ttputc(BEL);
}
X
putpad(str)
char    *str;
{
X	tputs(str, 1, ttputc);
}
X
putnpad(str, n)
char    *str;
{
X	tputs(str, n, ttputc);
}
X
X
#if	FLABEL
fnclabel(f, n)		/* label a function key */
int f,n;	/* default flag, numeric argument [unused] */
{
X	/* on machines with no function keys...don't bother */
X	return(TRUE);
}
#endif
#else
X
hello()
{
}
X
#endif
SHAR_EOF
chmod 0444 tcap.c ||
echo 'restore of tcap.c failed'
Wc_c="`wc -c < 'tcap.c'`"
test 6065 -eq "$Wc_c" ||
	echo 'tcap.c: original size 6065, current size' "$Wc_c"
# ============= termio.c ==============
echo 'x - extracting termio.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'termio.c' &&
/*
X * The functions in this file negotiate with the operating system for
X * characters, and write characters in a barely buffered fashion on the display.
X * All operating systems.
X */
#include        <stdio.h>
#include	"estruct.h"
#include        "edef.h"
X
#if   MSDOS & TURBO
#include <conio.h>
#endif
X
#if     AMIGA
#define NEW 1006L
#define AMG_MAXBUF      1024L
static long terminal;
static char     scrn_tmp[AMG_MAXBUF+1];
static long     scrn_tmp_p = 0;
#endif
X
#if ST520 & MEGAMAX
#include <osbind.h>
X	int STscancode = 0;	
#endif
X
#if     VMS
#include        <stsdef.h>
#include        <ssdef.h>
#include        <descrip.h>
#include        <iodef.h>
#include        <ttdef.h>
#include	<tt2def.h>
X
#define NIBUF   128                     /* Input buffer size            */
#define NOBUF   1024                    /* MM says bug buffers win!     */
#define EFN     0                       /* Event flag                   */
X
char    obuf[NOBUF];                    /* Output buffer                */
int     nobuf;                  /* # of bytes in above    */
char    ibuf[NIBUF];                    /* Input buffer          */
int     nibuf;                  /* # of bytes in above  */
int     ibufi;                  /* Read index                   */
int     oldmode[3];                     /* Old TTY mode bits            */
int     newmode[3];                     /* New TTY mode bits            */
short   iochan;                  /* TTY I/O channel             */
#endif
X
#if     CPM
#include        <bdos.h>
#endif
X
#if     MSDOS & (LATTICE | MSC | TURBO | AZTEC | MWC86)
union REGS rg;		/* cpu register for use of DOS calls */
int nxtchar = -1;	/* character held from type ahead    */
#endif
X
#if RAINBOW
#include "rainbow.h"
#endif
X
#if	USG			/* System V */
#include	<signal.h>
#include	<termio.h>
#include	<fcntl.h>
int kbdflgs;			/* saved keyboard fd flags	*/
int kbdpoll;			/* in O_NDELAY mode			*/
int kbdqp;			/* there is a char in kbdq	*/
char kbdq;			/* char we've already read	*/
struct	termio	otermio;	/* original terminal characteristics */
struct	termio	ntermio;	/* charactoristics to use inside */
#endif
X
#if V7 | BSD
#undef	CTRL
#include        <sgtty.h>        /* for stty/gtty functions */
#include	<signal.h>
struct  sgttyb  ostate;          /* saved tty state */
struct  sgttyb  nstate;          /* values for editor mode */
struct  sgttyb  rnstate;          /* values for raw editor mode */
int olstate;		/* Saved local mode values */
int nlstate;		/* new local mode values */
struct ltchars	oltchars;	/* Saved terminal special character set */
struct ltchars	nltchars = { -1, -1, -1, -1, -1, -1 }; /* a lot of nothing */
struct tchars	otchars;	/* Saved terminal special character set */
struct tchars	ntchars; /*  = { -1, -1, -1, -1, -1, -1 }; */
#if BSD
#include <sys/ioctl.h>		/* to get at the typeahead */
#define	TBUFSIZ	128
char tobuf[TBUFSIZ];		/* terminal output buffer */
#endif
#endif
X
#if ULTRIX
#include <sys/termios.h>
#endif
X
extern CMDFUNC f_backchar;
X
/*
X * This function is called once to set up the terminal device streams.
X * On VMS, it translates TT until it finds the terminal, then assigns
X * a channel to it and sets it raw. On CPM it is a no-op.
X */
ttopen()
{
#if     AMIGA
X	char oline[NSTRING];
#if	AZTEC
X	extern	Enable_Abort;	/* Turn off ctrl-C interrupt */
X
X	Enable_Abort = 0;	/* for the Manx compiler */
#endif
X	strcpy(oline, "RAW:0/0/640/200/");
X	strcat(oline, PROGNAME);
X	strcat(oline, " ");
X	strcat(oline, VERSION);
X	strcat(oline, "/Amiga");
X        terminal = Open(oline, NEW);
#endif
#if     VMS
X        struct  dsc$descriptor  idsc;
X        struct  dsc$descriptor  odsc;
X        char    oname[40];
X        int     iosb[2];
X        int     status;
X
X        odsc.dsc$a_pointer = "TT";
X        odsc.dsc$w_length  = strlen(odsc.dsc$a_pointer);
X        odsc.dsc$b_dtype        = DSC$K_DTYPE_T;
X        odsc.dsc$b_class        = DSC$K_CLASS_S;
X        idsc.dsc$b_dtype        = DSC$K_DTYPE_T;
X        idsc.dsc$b_class        = DSC$K_CLASS_S;
X        do {
X                idsc.dsc$a_pointer = odsc.dsc$a_pointer;
X                idsc.dsc$w_length  = odsc.dsc$w_length;
X                odsc.dsc$a_pointer = &oname[0];
X                odsc.dsc$w_length  = sizeof(oname);
X                status = LIB$SYS_TRNLOG(&idsc, &odsc.dsc$w_length, &odsc);
X                if (status!=SS$_NORMAL && status!=SS$_NOTRAN)
X                        exit(status);
X                if (oname[0] == 0x1B) {
X                        odsc.dsc$a_pointer += 4;
X                        odsc.dsc$w_length  -= 4;
X                }
X        } while (status == SS$_NORMAL);
X        status = SYS$ASSIGN(&odsc, &iochan, 0, 0);
X        if (status != SS$_NORMAL)
X                exit(status);
X        status = SYS$QIOW(EFN, iochan, IO$_SENSEMODE, iosb, 0, 0,
X                          oldmode, sizeof(oldmode), 0, 0, 0, 0);
X        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
X                exit(status);
X        newmode[0] = oldmode[0];
X        newmode[1] = oldmode[1] | TT$M_NOECHO;
X        newmode[1] &= ~(TT$M_TTSYNC|TT$M_HOSTSYNC);
X        newmode[2] = oldmode[2] | TT2$M_PASTHRU;
X        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
X                          newmode, sizeof(newmode), 0, 0, 0, 0);
X        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
X                exit(status);
X        term.t_nrow = (newmode[1]>>24) - 1;
X        term.t_ncol = newmode[0]>>16;
X
#endif
#if     CPM
#endif
X
#if     MSDOS & (HP150 == 0) & LATTICE
X	/* kill the ctrl-break interupt */
X	rg.h.ah = 0x33;		/* control-break check dos call */
X	rg.h.al = 1;		/* set the current state */
X	rg.h.dl = 0;		/* set it OFF */
X	intdos(&rg, &rg);	/* go for it! */
#endif
X
#if	USG
X	ioctl(0, TCGETA, &otermio);	/* save old settings */
X	ntermio = otermio;
X	/* setup new settings, preserve flow control, and allow BREAK */
X	ntermio.c_iflag = BRKINT|(otermio.c_iflag & IXON|IXANY|IXOFF);
X	ntermio.c_oflag = 0;
X	ntermio.c_lflag = ISIG;
X	ntermio.c_cc[VMIN] = 1;
X	ntermio.c_cc[VTIME] = 0;
X	ntermio.c_cc[VSWTCH] = -1;
#ifdef SIGTSTP	/* suspension under sys5 -- is this a standard? */
#if POSIX	/* ODT uses this... */
X	ntermio.c_cc[VSUSP] = -1;
X	ntermio.c_cc[VSTART] = -1;
X	ntermio.c_cc[VSTOP] = -1;
#else
X	ntermio.c_cc[V_SUSP] = -1;
X	ntermio.c_cc[V_DSUSP] = -1;
#endif
#endif
X	intrc = ntermio.c_cc[VINTR];
X	killc = ntermio.c_cc[VKILL];
X	backspc = ntermio.c_cc[VERASE];
X	ioctl(0, TCSETA, &ntermio);	/* and activate them */
X	kbdflgs = fcntl( 0, F_GETFL, 0 );
X	kbdpoll = FALSE;
#endif
X
#if     V7 | BSD
X	ioctl(0,TIOCGETP,&ostate); /* save old state */
X	killc = ostate.sg_kill;
X	backspc = ostate.sg_erase;
X
X	nstate = ostate;
X        nstate.sg_flags |= CBREAK;
X        nstate.sg_flags &= ~(ECHO|CRMOD);       /* no echo for now... */
X	ioctl(0,TIOCSETP,&nstate); /* set new state */
X
X	rnstate = nstate;
X        rnstate.sg_flags &= ~CBREAK;
X        rnstate.sg_flags |= RAW;
X
X	ioctl(0, TIOCGETC, &otchars);		/* Save old characters */
X	intrc = otchars.t_intrc;
X
X	ntchars = otchars;
X	ntchars.t_brkc = -1;
X	ntchars.t_eofc = -1;
X	ioctl(0, TIOCSETC, &ntchars);		/* Place new character into K */
X
X	ioctl(0, TIOCGLTC, &oltchars);		/* Save old characters */
X	ioctl(0, TIOCSLTC, &nltchars);		/* Place new character into K */
X
#if	BSD
X	ioctl(0, TIOCLGET, &olstate);
X	nlstate = olstate;
X	nlstate |= LLITOUT;
X	ioctl(0, TIOCLSET, &nlstate);
X	/* provide a smaller terminal output buffer so that
X	   the type ahead detection works better (more often) */
X	setbuffer(stdout, &tobuf[0], TBUFSIZ);
X	setbuf(stdin, NULL);
#endif
#endif
X
#if UNIX && defined(SIGTSTP)
X	{
X	extern	int rtfrmshell();	/* return from suspended shell */
X	signal(SIGTSTP,SIG_DFL);	/* set signals so that we can */
X	signal(SIGCONT,rtfrmshell);	/* suspend & restart */
X	signal(SIGTTOU,SIG_IGN);	/* ignore output prevention */
X	}
#endif
X	/* make sure backspace is bound to backspace */
X	asciitbl[backspc] = &f_backchar;
X
X	/* make sure backspace is considered a backspace by the code */
X	_chartypes_[backspc] |= _bspace;
X
X	/* on all screens we are not sure of the initial position */
X	/*  of the cursor					*/
X	ttrow = 999;
X	ttcol = 999;
}
X
/*
X * This function gets called just before we go back home to the command
X * interpreter. On VMS it puts the terminal back in a reasonable state.
X * Another no-operation on CPM.
X */
ttclose()
{
#if     AMIGA
#if	LATTICE
X        amg_flush();
X        Close(terminal);
#endif
#if	AZTEC
X        amg_flush();
X	Enable_Abort = 1;	/* Fix for Manx */
X        Close(terminal);
#endif
#endif
X
#if     VMS
X        int     status;
X        int     iosb[1];
X
X        ttflush();
X        status = SYS$QIOW(EFN, iochan, IO$_SETMODE, iosb, 0, 0,
X                 oldmode, sizeof(oldmode), 0, 0, 0, 0);
X        if (status!=SS$_NORMAL || (iosb[0]&0xFFFF)!=SS$_NORMAL)
X                exit(status);
X        status = SYS$DASSGN(iochan);
X        if (status != SS$_NORMAL)
X                exit(status);
#endif
#if     CPM
#endif
#if     MSDOS & (HP150 == 0) & LATTICE
X	/* restore the ctrl-break interupt */
X	rg.h.ah = 0x33;		/* control-break check dos call */
X	rg.h.al = 1;		/* set the current state */
X	rg.h.dl = 1;		/* set it ON */
X	intdos(&rg, &rg);	/* go for it! */
#endif
X
X	ttclean(TRUE);
}
X
ttclean(f)
{
X	if (f) {
X		movecursor(term.t_nrow, ttcol); /* don't care about column */
X		ttputc('\n');
X		ttputc('\r');
X	}
X	TTflush();
#if UNIX
#if	USG
X	ioctl(0, TCSETAF, &otermio);
X	fcntl(0, F_SETFL, kbdflgs);
#endif
#if     V7 | BSD
X	ioctl(0,TIOCSETP,&ostate);
X	ioctl(0, TIOCSETC, &otchars);
X	ioctl(0, TIOCSLTC, &oltchars);
#if	BSD
X	ioctl(0, TIOCLSET, &olstate);
#endif
#endif
#else
X	TTclose();
X	TTkclose();
#endif
}
X
ttunclean()
{
#if	USG
X	ioctl(0, TCSETAF, &ntermio);
#endif
#if     V7 | BSD
X	ioctl(0, TIOCSETP,&nstate);
X	ioctl(0, TIOCSETC, &ntchars);
X	ioctl(0, TIOCSLTC, &nltchars);
#if	BSD
X	ioctl(0, TIOCLSET, &nlstate);
#endif
#endif
}
X
/*
X * Write a character to the display. On VMS, terminal output is buffered, and
X * we just put the characters in the big array, after checking for overflow.
X * On CPM terminal I/O unbuffered, so we just write the byte out. Ditto on
X * MS-DOS (use the very very raw console output routine).
X */
ttputc(c)
#if     AMIGA | (ST520 & MEGAMAX)
X        char c;
#endif
{
#if     AMIGA
X        scrn_tmp[scrn_tmp_p++] = c;
X        if(scrn_tmp_p>=AMG_MAXBUF)
X                amg_flush();
#endif
#if	ST520 & MEGAMAX
X	Bconout(2,c);
#endif
#if     VMS
X        if (nobuf >= NOBUF)
X                ttflush();
X        obuf[nobuf++] = c;
#endif
X
#if     CPM
X        bios(BCONOUT, c, 0);
#endif
X
#if     MSDOS & MWC86
X        putcnb(c);
#endif
X
#if	MSDOS & (LATTICE | AZTEC) & ~IBMPC
X	bdos(6, c, 0);
#endif
X
#if RAINBOW
X        Put_Char(c);                    /* fast video */
#endif
X
X
#if     V7 | USG | BSD
X        fputc(c, stdout);
#endif
}
X
#if	AMIGA
amg_flush()
{
X        if(scrn_tmp_p)
X                Write(terminal,scrn_tmp,scrn_tmp_p);
X        scrn_tmp_p = 0;
}
#endif
X
/*
X * Flush terminal buffer. Does real work where the terminal output is buffered
X * up. A no-operation on systems where byte at a time terminal I/O is done.
X */
ttflush()
{
#if     AMIGA
X        amg_flush();
#endif
#if     VMS
X        int     status;
X        int     iosb[2];
X
X        status = SS$_NORMAL;
X        if (nobuf != 0) {
X                status = SYS$QIOW(EFN, iochan, IO$_WRITELBLK|IO$M_NOFORMAT,
X                         iosb, 0, 0, obuf, nobuf, 0, 0, 0, 0);
X                if (status == SS$_NORMAL)
X                        status = iosb[0] & 0xFFFF;
X                nobuf = 0;
X        }
X        return (status);
#endif
X
#if     CPM
#endif
X
#if     MSDOS
#endif
X
#if     V7 | USG | BSD
X        fflush(stdout);
#endif
}
X
extern int tungotc;
X
/*
X * Read a character from the terminal, performing no editing and doing no echo
X * at all. More complex in VMS that almost anyplace else, which figures. Very
X * simple on CPM, because the system can do exactly what you want.
X */
ttgetc()
{
X	int c;
#if     AMIGA
X        char ch;
X
X        amg_flush();
X        Read(terminal, &ch, 1L);
X        return(255 & (int)ch);
#endif
#if	ST520 & MEGAMAX
X	long ch;
X
/*
X * blink the cursor only if nothing is happening, this keeps the
X * cursor on steadily during movement making it easier to track
X */
X	STcurblink(TRUE);  /* the cursor blinks while we wait */
X	ch = Bconin(2);
X	STcurblink(FALSE); /* the cursor is steady while we work */
X	STscancode = (ch >> 16) & 0xff;
X       	return(255 & (int)ch);
#endif
#if     VMS
X        int     status;
X        int     iosb[2];
X        int     term[2];
X
X        while (ibufi >= nibuf) {
X                ibufi = 0;
X                term[0] = 0;
X                term[1] = 0;
X                status = SYS$QIOW(EFN, iochan, IO$_READLBLK|IO$M_TIMED,
X                         iosb, 0, 0, ibuf, NIBUF, 0, term, 0, 0);
X                if (status != SS$_NORMAL)
X                        exit(status);
X                status = iosb[0] & 0xFFFF;
X                if (status!=SS$_NORMAL && status!=SS$_TIMEOUT)
X                        exit(status);
X                nibuf = (iosb[0]>>16) + (iosb[1]>>16);
X                if (nibuf == 0) {
X                        status = SYS$QIOW(EFN, iochan, IO$_READLBLK,
X                                 iosb, 0, 0, ibuf, 1, 0, term, 0, 0);
X                        if (status != SS$_NORMAL
X                        || (status = (iosb[0]&0xFFFF)) != SS$_NORMAL)
X                                exit(status);
X                        nibuf = (iosb[0]>>16) + (iosb[1]>>16);
X                }
X        }
X        return (ibuf[ibufi++] & 0xFF);    /* Allow multinational  */
#endif
X
#if     CPM
X        return (biosb(BCONIN, 0, 0));
#endif
X
#if RAINBOW
X
X        while ((c = Read_Keyboard()) < 0);
X
X        if ((c & Function_Key) == 0)
X                if (!((c & 0xFF) == 015 || (c & 0xFF) == 0177))
X                        c &= 0xFF;
X
X        return c;
#endif
X
#if     MSDOS & MWC86
X        return (getcnb());
#endif
X
#if	MSDOS & (LATTICE | MSC | TURBO | AZTEC)
X
X	/* if a char already is ready, return it */
X	if (nxtchar >= 0) {
X		c = nxtchar;
X		nxtchar = -1;
X		return(c);
X	}
X
X	/* call the dos to get a char */
X	rg.h.ah = 7;		/* dos Direct Console Input call */
X	intdos(&rg, &rg);
X	c = rg.h.al;		/* grab the char */
X	return(c & 0xff);
#endif
X
#if     V7 | BSD
X        /*stty(0, &rnstate);                      /* set raw mode */
X        c = fgetc(stdin);
X	if (c == -1)
X		/* this doesn't work -- read doesn't return on interrupt */
X		c = kcod2key(intrc);
X	else
X		c &= 0x7f;
X        /*stty(0, &nstate);                       /* set mode */
X	return c;
#endif
X
#if	USG
X	if( kbdqp ) {
X		kbdqp = FALSE;
X	} else {
X		if( kbdpoll && fcntl( 0, F_SETFL, kbdflgs ) < 0 )
X			return FALSE;	/* what ??  i don't understand -- pgf */
X		kbdpoll = FALSE;
X		if (read(0, &kbdq, 1) < 0) {
X			return -1;
X		}
X	}
X	return ( kbdq & 0x7f );
#endif
}
X
X
#if	NeWS
/* typahead:	Check to see if any characters are already in the
X		keyboard buffer
*/
typahead()
{
X	return(inhibit_update) ;
}
#endif
X
#if	TYPEAH & (~ST520 | ~LATTICE ) & ~NeWS
X
/* typahead:	Check to see if any characters are already in the
X		keyboard buffer
*/
typahead()
{
X	long x;
X
#if	MSDOS & (MSC | TURBO)
X	if (tungotc > 0)
X		return TRUE;
X
X	if (kbhit() != 0)
X		return(TRUE);
X	else
X		return(FALSE);
#endif
X
#if	MSDOS & (LATTICE | AZTEC | MWC86)
X	int c;		/* character read */
X	int flags;	/* cpu flags from dos call */
X
X	if (nxtchar >= 0)
X		return(TRUE);
X
X	if (tungotc > 0)
X		return TRUE;
X
X
X	rg.h.ah = 6;	/* Direct Console I/O call */
X	rg.h.dl = 255;	/*         does console input */
#if	LATTICE | AZTEC
X	flags = intdos(&rg, &rg);
#else
X	intcall(&rg, &rg, 0x21);
X	flags = rg.x.flags;
#endif
X	c = rg.h.al;	/* grab the character */
X
X	/* no character pending */
X	if ((flags & 0x40) != 0)
X		return(FALSE);
X
X	/* save the character and return true */
X	nxtchar = c;
X	return(TRUE);
#endif
X
#if	BSD
X	if (tungotc > 0)
X		return TRUE;
X
X	return((ioctl(0,FIONREAD,&x) < 0) ? 0 : (int)x);
#endif
X
#if	USG
X	if (tungotc > 0)
X		return TRUE;
X
X	if( !kbdqp )
X	{
X		if( !kbdpoll && fcntl( 0, F_SETFL, kbdflgs | O_NDELAY ) < 0 )
X			return(FALSE);
X		kbdpoll = TRUE;  /* I think */
X		kbdqp = (1 == read( 0, &kbdq, 1 ));
X	}
X	return ( kbdqp );
#endif
X
}
#endif
X
SHAR_EOF
chmod 0444 termio.c ||
echo 'restore of termio.c failed'
Wc_c="`wc -c < 'termio.c'`"
test 16097 -eq "$Wc_c" ||
	echo 'termio.c: original size 16097, current size' "$Wc_c"
# ============= tipc.c ==============
echo 'x - extracting tipc.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'tipc.c' &&
/*
X * The routines in this file provide support for the TI-PC and other
X * compatible terminals. It goes directly to the graphics RAM to do
X * screen output. It compiles into nothing if not a TI-PC driver
X */
X
#define termdef 1                       /* don't define "term" external */
X
#include        <stdio.h>
#include        "estruct.h"
#include        "edef.h"
X
#if     TIPC
X
#define NROW    25                      /* Screen size.                 */
#define NCOL    80                      /* Edit if you want to.         */
#define MARGIN  8                       /* size of minimim margin and   */
#define SCRSIZ  64                      /* scroll size for extended lines */
#define NPAUSE  200                     /* # times thru update to pause */
#define BEL     0x07                    /* BEL character.               */
#define ESC     0x1B                    /* ESC character.               */
#define SPACE   32                      /* space character              */
#define SCADD   0xDE000L                /* address of screen RAM        */
X
#define CHAR_ENABLE     0x08            /* TI attribute to show char    */
#define TI_REVERSE      0x10            /* TI attribute to reverse char */
#define BLACK   0+CHAR_ENABLE           /* TI attribute for Black       */
#define BLUE    1+CHAR_ENABLE           /* TI attribute for Blue        */
#define RED     2+CHAR_ENABLE           /* TI attribute for Red         */
#define MAGENTA 3+CHAR_ENABLE           /* TI attribute for Magenta     */
#define GREEN   4+CHAR_ENABLE           /* TI attribute for Green       */
#define CYAN    5+CHAR_ENABLE           /* TI attribute for Cyan        */
#define YELLOW  6+CHAR_ENABLE           /* TI attribute for Yellow      */
#define WHITE   7+CHAR_ENABLE           /* TI attribute for White       */
X
X
extern  int     ttopen();               /* Forward references.          */
extern  int     ttgetc();
extern  int     ttputc();
extern  int     ttflush();
extern  int     ttclose();
extern  int     timove();
extern  int     tieeol();
extern  int     tieeop();
extern  int     tibeep();
extern  int     tiopen();
extern  int     tirev();
extern	int	ticres();
extern  int     ticlose();
extern  int     tiputc();
X
#if     COLOR
extern  int     tifcol();
extern  int     tibcol();
X
int     cfcolor = -1;           /* current forground color */
int     cbcolor = -1;           /* current background color */
int     ctrans[] =              /* ansi to ti color translation table */
X        {BLACK, RED, GREEN, YELLOW, BLUE, MAGENTA, CYAN, WHITE};
#endif
X
/*
X * Standard terminal interface dispatch table. Most of the fields point into
X * "termio" code.
X */
TERM    term    = {
X	NROW-1,
X        NROW-1,
X        NCOL,
X        NCOL,
X        MARGIN,
X        SCRSIZ,
X        NPAUSE,
X        tiopen,
X        ticlose,
X        ttgetc,
X        tiputc,
X        ttflush,
X        timove,
X        tieeol,
X        tieeop,
X        tibeep,
X        tirev,
X        ticres
#if     COLOR
X        , tifcol,
X        tibcol
#endif
};
X
extern union REGS rg;
X
#if     COLOR
setatt( attr )
int attr;
{
X        rg.h.ah = 0x16;         /* set the forground character attribute */
X        rg.h.bl = attr;
X        int86( 0x49, &rg, &rg );
}
X
tifcol(color)           /* set the current output color */
X
int color;      /* color to set */
X
{
X        cfcolor = ctrans[color];
X        setatt ( cfcolor );
}
X
tibcol(color)           /* set the current background color */
X
int color;      /* color to set */
X
{
X        cbcolor = ctrans[color];
}
#endif
X
timove(row, col)
{
X        rg.h.ah = 2;            /* set cursor position function code */
X        rg.h.dh = col;
X        rg.h.dl = row;
X        int86(0x49, &rg, &rg);
}
X
tieeol()        /* erase to the end of the line */
X
{
X        int ccol;       /* current column cursor lives */
X        int crow;       /*         row  */
X
X        /* find the current cursor position */
X        rg.h.ah = 3;            /* read cursor position function code */
X        int86(0x49, &rg, &rg);
X        ccol = rg.h.dh;         /* record current column */
X        crow = rg.h.dl;         /* and row */
X
X        rg.h.ah = 0x09;         /* Write character at cursor position */
X        rg.h.al = ' ';          /* Space */
X        rg.h.bl = cfcolor;
X        rg.x.cx = NCOL-ccol;    /* Number of characters to write */
X        int86(0x49, &rg, &rg);
X
}
X
tiputc(ch)      /* put a character at the current position in the
X                   current colors */
X
int ch;
X
{
X        rg.h.ah = 0x0E;         /* write char to screen with current attrs */
X        rg.h.al = ch;
X        int86(0x49, &rg, &rg);
}
X
tieeop()                        /* Actually a clear screen */
{
X
X        rg.h.ah = 0x13;         /* Clear Text Screen and Home Cursor */
X        int86(0x49, &rg, &rg);
}
X
tirev(state)            /* change reverse video state */
X
int state;      /* TRUE = reverse, FALSE = normal */
X
{
X        setatt( state ? cbcolor : cfcolor  );
}
X
ticres()	/* change screen resolution */
X
{
X	return(TRUE);
}
X
spal()		/* change palette string */
X
{
X	/*	Does nothing here	*/
}
X
tibeep()
{
X        bdos(6, BEL, 0);
}
X
tiopen()
{
X	strcpy(sres, "NORMAL");
X        revexist = TRUE;
X        ttopen();
}
X
ticlose()
X
{
#if     COLOR
X        tifcol(7);
X        tibcol(0);
#endif
X        ttclose();
}
#else
tihello()
{
}
#endif
X
SHAR_EOF
chmod 0444 tipc.c ||
echo 'restore of tipc.c failed'
Wc_c="`wc -c < 'tipc.c'`"
test 5308 -eq "$Wc_c" ||
	echo 'tipc.c: original size 5308, current size' "$Wc_c"
# ============= undo.c ==============
echo 'x - extracting undo.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'undo.c' &&
X
/* these routines take care of undo operations */
/* code by Paul Fox, original algorithm mostly by Julia Harper May, 89 */
X
#include "estruct.h"
#include "edef.h"
X
#ifndef NULL
#define NULL 0
#endif
X
X
/* the undo strategy is this:
X	1) For any deleted line, push it onto the undo list.
X	2) On any change to a line, make a copy of it, push the copy to
X		the undo list, and mark the original as having been copied.
X		Do not copy/push lines that are marked as having been copied.
X		Push a tag matching up the copy with the original.  Later,
X		when the copy has been put into the file, we can
X		go back through the undo stack, find lines there pointing
X		at the original, and make them point at the copy.  ugh.
X		This wouldn't be necessary if we used line no's as the pointers,
X		instead of real pointers.
X
X	On the actual undo, we pop these things one by one.  There should
X	either be no lines where it goes (it was deleted), or exactly
X	one line where it goes (it was changed/copied).  That makes it
X	easy to undo the changes one by one.  Of course, we need to build
X	a different, inverse stack as we go, so that undo can be undone.
X
X	The "copied" flag in the LINE structure is unioned with the stack
X	link pointer on the undo stack, since they aren't both needed at once.
X
*/
X
X
#define CURSTK(bp) (&(bp->b_udstks[bp->b_udstkindx]))
#define ALTSTK(bp) (&(bp->b_udstks[1^(bp->b_udstkindx)]))
#define CURDOTP(bp) (bp->b_uddotps[bp->b_udstkindx])
#define ALTDOTP(bp) (bp->b_uddotps[1^(bp->b_udstkindx)])
#define CURDOTO(bp) (bp->b_uddotos[bp->b_udstkindx])
#define ALTDOTO(bp) (bp->b_uddotos[1^(bp->b_udstkindx)])
#define SWITCHSTKS(bp) (bp->b_udstkindx = 1 ^ bp->b_udstkindx)
X
short needundocleanup;
LINE *copyline();
X
/* push the line onto the right undo stack. */
toss_to_undo(lp)
LINE *lp;
{
X	if (needundocleanup)
X		preundocleanup();
X	pushline(lp,CURSTK(curbp));
X	if ((ALTDOTP(curbp) == NULL) || (ALTDOTP(curbp) == lp)) {
X		/* need to save a dot -- either the next line or 
X			the previous one */
X		if (lp->l_fp == curbp->b_linep) {
X			ALTDOTP(curbp) = lp->l_bp;
X			ALTDOTO(curbp) = firstchar(lp->l_bp);
X		} else {
X			ALTDOTP(curbp) = lp->l_fp;
X			ALTDOTO(curbp) = firstchar(lp->l_fp);
X		}
X	}
X	dumpuline(lp);
}
X
/* push a copy of a line onto the right undo stack */
/* push a patch so we can later fix up any references to this line that */
/* might already be in the stack.  */
/* This unforutunate breach of stak protocol is because we'd rather push the */
/* _copy_ than the origianal. When the undo happens, the later pops will  */
/* point at the _original_ (which will by then be on the other undo stack)  */
/* unless we fix them now. */
copy_for_undo(lp)
LINE *lp;
{
X	register LINE *nlp;
X
X	if (needundocleanup)
X		preundocleanup();
X
X	if (liscopied(lp))
X		return(TRUE);
X
X	/* take care of the normal undo stack */
X	nlp = copyline(lp);
X	if (nlp == NULL)
X		return(FALSE);
X	pushline(nlp,CURSTK(curbp));
X
X	make_undo_patch(lp,nlp,LINEUNDOPATCH);
X
X	lsetcopied(lp);
X
X	setupuline(lp);
X
X	if (ALTDOTP(curbp) == NULL) {
X		ALTDOTP(curbp) = lp;
X		ALTDOTO(curbp) = curwp->w_doto;
X	}
X	return (TRUE);
}
X
/* push an unreal line onto the right undo stack */
/* lp should be the new line, _after_ insertion, so l_fp and l_bp are right */
tag_for_undo(lp)
LINE *lp;
{
X	register LINE *nlp;
X
X	if (needundocleanup)
X		preundocleanup();
X
X	if (liscopied(lp))
X		return(TRUE);
X
X	nlp = lalloc(-1);
X	if (nlp == NULL)
X		return(FALSE);
X	llength(nlp) = LINENOTREAL;
X	nlp->l_fp = lp->l_fp;
X	nlp->l_bp = lp->l_bp;
X	pushline(nlp,CURSTK(curbp));
X	lsetcopied(lp);
X	if (ALTDOTP(curbp) == NULL) {
X		    ALTDOTP(curbp) = lp;
X		    ALTDOTO(curbp) = curwp->w_doto;
X	}
X	return (TRUE);
}
X
pushline(lp,stk)
LINE *lp,**stk;
{
X	lp->l_nxtundo = *stk;
X	*stk = lp;
}
X
LINE *
popline(stk)
LINE **stk;
{
X	LINE *lp;
X	lp = *stk;
X	if (lp != NULL) {
X		*stk = lp->l_nxtundo;
X		lp->l_nxtundo = NULL;
X	}
X	return (lp);
}
X
make_undo_patch(olp,nlp,type)
LINE *olp,*nlp;
{
X	register LINE *plp;
X	/* push on a tag that matches up the copy with the original */
X	plp = lalloc(-1);
X	if (plp == NULL)
X		return(FALSE);
X	llength(plp) = type;
X	plp->l_fp = olp;	/* l_fp is the original line */
X	plp->l_bp = nlp;	/* l_bp is the copy */
X	pushline(plp,CURSTK(curbp));
}
X
patchstk(newlp,oldlp)
LINE *newlp, *oldlp;
{
X	register LINE *tlp;
X	for (tlp = *CURSTK(curbp); tlp != NULL ; tlp = tlp->l_nxtundo) {
X		if (!lispatch(tlp)) {
X			if (tlp->l_fp == oldlp)
X				tlp->l_fp = newlp;
X			if (tlp->l_bp == oldlp)
X				tlp->l_bp = newlp;
X		}
X	}
}
X
LINE *
copyline(lp)
register LINE *lp;
{
X	int i;
X	register LINE *nlp;
X	
X	nlp = lalloc(lp->l_used);
X	if (nlp == NULL)
X		return(NULL);
X	/* copy the text and forward and back pointers.  everything else 
X		matches already */
X	nlp->l_fp = lp->l_fp;
X	nlp->l_bp = lp->l_bp;
X	/* copy the rest */
X	memcpy(nlp->l_text, lp->l_text, llength(lp));
X	return nlp;
}
X
X
/* before any undoable command (except undo itself), clean the undo list */
/* clean the copied flag on the line we're the copy of */
freeundostacks(bp)
register BUFFER *bp;
{
X	register LINE *lp;
X	int i;
X
X	for (i = 0; i <= 1; i++, SWITCHSTKS(bp)) {
X		while ((lp = popline(CURSTK(bp))) != NULL) {
X			lfree(lp);
X		}
X	}
X
X	/* clear the flags in the buffer */
X	/* there may be a way to clean these less drastically, by
X		using the information on the stacks above, but I
X		couldn't figure it out.  -pgf  */
X	lp = lforw(bp->b_linep);
X	while (lp != bp->b_linep) {
X		lsetnotcopied(lp);
X		lp = lforw(lp);
X	}
X
}
X
undo(f,n)
{
X	LINE *lp, *alp;
X	int nopops = TRUE;
X	
X	if (curbp->b_mode & MDVIEW)
X		return(rdonly());
X
X	while ((lp = popline(CURSTK(curbp))) != NULL) {
X		nopops = FALSE;
#if NEWUNDO
X		if (lismarkpatch(lp)) {
X			register LINE *tlp;
X			resetuline(lp->l_bp,lp->l_fp);
X			tlp = lp->l_fp;
X			lp->l_fp = lp->l_bp;
X			lp->l_bp = tlp;
X			pushline(lp,ALTSTK(curbp));
X			continue;
X		}
#endif
X		if (lislinepatch(lp)) {
X			patchstk(lp->l_bp, lp->l_fp);
X			lfree(lp);
X			continue;
X		}
X		lchange(WFHARD|WFINS|WFKILLS);
X		if (lp->l_bp->l_fp != lp->l_fp) { /* theres something there */
X			if (lp->l_bp->l_fp->l_fp == lp->l_fp) {
X				/* then there is exactly one line there */
X				/* alp is the line to remove */
X				/* lp is the line we're putting in */
X				alp = lp->l_bp->l_fp;
X				repointstuff(lp,alp);
X				/* remove it */
X				lp->l_bp->l_fp = alp->l_fp;
X				alp->l_fp->l_bp = alp->l_bp;
X			} else { /* there is more than one line there */
X				mlwrite("Bug! no stacked line for an insert");
X				/* cleanup ? naw, a bugs a bug */
X				return(FALSE);
X			}
X		} else { /* there is no line where we're going */
X			/* create an "unreal" tag line to push */
X			alp = lalloc(-1);
X			if (alp == NULL)
X				return(FALSE);
X			llength(alp) = LINENOTREAL;
X			alp->l_fp = lp->l_fp;
X			alp->l_bp = lp->l_bp;
X		}
X
X		/* insert real lines into the buffer 
X			throw away the markers */
X		if (lisreal(lp)) {
X			lp->l_bp->l_fp = lp;
X			lp->l_fp->l_bp = lp;
X		} else {
X			lfree(lp);
X		}
X
X		pushline(alp,ALTSTK(curbp));
X	}
X	
X	if (nopops) {
X		TTbeep();
X		return (FALSE);
X	}
X
X
X	curwp->w_dotp = CURDOTP(curbp);
X	curwp->w_doto = CURDOTO(curbp);
X	if (curwp->w_doto >= llength(curwp->w_dotp))
X		curwp->w_doto = llength(curwp->w_dotp) - 1;
X	else if (curwp->w_doto < firstchar(curwp->w_dotp))
X		curwp->w_doto = firstchar(curwp->w_dotp);
X
X	SWITCHSTKS(curbp);
X	
X	vverify("undo");
X	
X	return TRUE;
}
X
mayneedundo()
{
X	needundocleanup = TRUE;
}
X
preundocleanup()
{
X	freeundostacks(curbp);
X	CURDOTP(curbp) = curwp->w_dotp;
X	CURDOTO(curbp) = curwp->w_doto;
X	ALTDOTP(curbp) = NULL;
X	ALTDOTO(curbp) = curwp->w_doto;
X	needundocleanup = FALSE;
}
X
lineundo(f,n)
{
X	register LINE *ulp;	/* the Undo line */
X	register LINE *lp;	/* the line we may replace */
X	register WINDOW *wp;
X	register char *ntext;
X
X	ulp = curbp->b_ulinep;
X	if (ulp == NULL) {
X		TTbeep();
X		return FALSE;
X	}
X
X	lp = ulp->l_nxtundo;
X
X	if (ulp->l_fp != lp->l_fp ||
X	    ulp->l_bp != lp->l_bp) {
X	    	/* then the change affected more than one line */
X		dumpuline(ulp);
X		return FALSE;
X	}
X
X	/* avoid losing our undo stacks needlessly */
X	if (linesmatch(ulp,lp) == TRUE) 
X		return TRUE;
X
X	curwp->w_dotp = lp;
X	preundocleanup();
X
X
X	ntext = malloc(ulp->l_size);
X	if (ntext == NULL)
X		return (FALSE);
X
X	copy_for_undo(lp);
X
X	memcpy(ntext, ulp->l_text, llength(ulp));
X	free(lp->l_text);
X	lp->l_text = ntext;
X	lp->l_used = ulp->l_used;
X	lp->l_size = ulp->l_size;
X
X	/* let's be defensive about this */
X	wp = wheadp;
X	while (wp != NULL) {
X		if (wp->w_dotp == lp)
X			wp->w_doto = 0;
X		if (wp->w_mkp == lp)
X			wp->w_mko = 0;
X		if (wp->w_ldmkp == lp)
X			wp->w_ldmko = 0;
X		wp = wp->w_wndp;
X	}
X	if (CURDOTP(curbp) == lp)
X		CURDOTO(curbp) = 0;
X	if (curbp->b_nmmarks != NULL) {
X		/* fix the named marks */
X		int i;
X		struct MARK *mp;
X		for (i = 0; i < 26; i++) {
X			mp = &(curbp->b_nmmarks[i]);
X			if (mp->markp == lp)
X				mp->marko = 0;
X		}
X	}
X
X	curwp->w_flag |= WFEDIT;
X	
X	vverify("lineundo");
X	return TRUE;
X
}
X
repointstuff(nlp,olp)
register LINE *nlp,*olp;
{
X	register WINDOW *wp;
X
X	/* fix anything important that points to it */
X	wp = wheadp;
X	while (wp != NULL) {
X		if (wp->w_linep == olp)
X			if (lisreal(nlp)) {
X				wp->w_linep = nlp;
X			} else {
X				wp->w_linep = olp->l_fp;
X			}
X		if (wp->w_mkp == olp) {
X			if (lisreal(nlp)) {
X				wp->w_mkp = nlp;
X			} else {
X				wp->w_mkp = olp->l_fp;
X			}
X			wp->w_mko = 0;
X		}
X		if (wp->w_ldmkp == olp) {
X			if (lisreal(nlp)) {
X				wp->w_ldmkp = nlp;
X			} else {
X				wp->w_ldmkp = olp->l_fp;
X			}
X			wp->w_ldmko = 0;
X		}
X		wp = wp->w_wndp;
X	}
#if 0
no code for ALTDOTO, but this was ifdef'ed out before I put that in...  pgf
X	if (ALTDOTP(curbp) == olp) {
X		if (lisreal(nlp)) {
X			ALTDOTP(curbp) = nlp;
X		} else {
X		    mlwrite("Bug: preundodot points at newly inserted line!");
X		}
X	}
#endif
X	if (CURDOTP(curbp) == olp) {
X		if (lisreal(nlp)) {
X			CURDOTP(curbp) = nlp;
X		} else {
X		    mlwrite("Bug: preundodot points at newly inserted line!");
X		}
X	}
X	if (curbp->b_nmmarks != NULL) {
X		/* fix the named marks */
X		int i;
X		struct MARK *mp;
X		for (i = 0; i < 26; i++) {
X			mp = &(curbp->b_nmmarks[i]);
X			if (mp->markp == olp) {
X				if (lisreal(nlp)) {
X					mp->markp = nlp;
X					mp->marko = 0;
X				} else {
X				mlwrite("Sorry, lost the mark.");
X				}
X			}
X		}
X	}
#if !NEWUNDO
X	resetuline(olp,nlp);
#endif
}
X
linesmatch(lp1,lp2)
register LINE *lp1,*lp2;
{
X	int i;
X	if (llength(lp1) != llength(lp2))
X		return FALSE;
X	return !memcmp(lp1->l_text, lp2->l_text, llength(lp1));
}
X
dumpuline(lp)
LINE *lp;
{
X	if ((curbp->b_ulinep != NULL) &&
X		    (curbp->b_ulinep->l_nxtundo == lp)) {
X		lfree(curbp->b_ulinep);
X		curbp->b_ulinep = NULL;
X	}
}
X
setupuline(lp)
LINE *lp;
{
X	/* take care of the U line */
X	if ((curbp->b_ulinep == NULL) || (curbp->b_ulinep->l_nxtundo != lp)) {
X		if (curbp->b_ulinep != NULL)
X			lfree(curbp->b_ulinep);
X		curbp->b_ulinep = copyline(lp);
X		if (curbp->b_ulinep != NULL)
X			curbp->b_ulinep->l_nxtundo = lp;
X	}
}
X
resetuline(olp,nlp)
register LINE *olp,*nlp;
{
X	if (curbp->b_ulinep != NULL && curbp->b_ulinep->l_nxtundo == olp) {
X		if (lisreal(nlp)) {
X			curbp->b_ulinep->l_nxtundo = nlp;
X		} else {
X			mlwrite("Bug: b_ulinep pointed at inserted line!");
X		}
X	}
}
X
firstchar(lp)
LINE *lp;
{
X	int off = 0;
X	while ( off != llength(lp) && isspace(lgetc(lp, off)) )
X		off++;
X	return off;
}
SHAR_EOF
chmod 0444 undo.c ||
echo 'restore of undo.c failed'
Wc_c="`wc -c < 'undo.c'`"
test 11158 -eq "$Wc_c" ||
	echo 'undo.c: original size 11158, current size' "$Wc_c"
# ============= vile.hlp ==============
echo 'x - extracting vile.hlp (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'vile.hlp' &&
X
Getting along with vile
-----------------------
X	Use Ctrl-D and Ctrl-U to scroll through this help information.
X
X	Type Ctrl-O to make this the only window on the screen.
X
X	The only vile commands described herein are those not 
X	present in vi, or differing greatly from those in vi.
X	There is a section at the bottom describing other differences
X	between vile and vi.
X
X	First, to leave vile, use any of the following:
X		:q
X		:quit
X		:exit
X		:wq	(writes the file before quitting)
X		:q!	(quits without writing changes!)
X		Q
X		ZZ	(will write all unwritten buffers)
X		^X-^C	(don't know why.  _They_ don't put in ":q" for _us_!)
X
X	To get help (probably just this text), use any of:
X		:h
X		:help
X		^X-^H
X		^A-^H
X
General Remarks
---------------
X	Vile holds text in "buffers".  Usually, these correspond to a file
X	that you are editing, but not always.  For instance, a buffer
X	might be used to display this help text, or to hold the output
X	of a shell command that you have run.  Buffers have names, and
X	these usually match the names of the files they contain.
X
X	Buffers are sometimes displayed in windows.  A buffer may be 
X	displayed in more than one window at the same time.  There is 
X	no such thing as a hidden window.  All existing windows are on 
X	the screen.  There may, however, be hidden buffers, which are not 
X	currently associated with any window.
X
X	All yank/delete registers (the default unnamed register, the numbered
X	registers ("1-"9) that hold line-deletes, and the named registers
X	("a-"z)) are global to the editor, and not attached to any single
X	buffer.  Thus you can delete text in one buffer and put it back in
X	another. 
X
X	Undo operations are attached to a buffer, not a window.  Thus if
X	you have two windows to the same buffer, and make a change in one,
X	you can undo it in the other.
X
Buffer manipulation commands:  
-----------------------------
X	_	Show a history list of the up to 9 most recently visited 
X		buffers.  Follow this command with a digit to select that
X		buffer, or simply repeat it ("__") as a synonym for "_1".
X		Modified buffers are preceded by a '*' in the history list.
X		There are many different ways to get the previous file:
X			__
X			_1
X			1_
X			:p
X			:e#
X			^^   (ctrl-^)  (but many keyboards can't produce this)
X
X	:e	Edit a file.  If the file is already in a buffer, that buffer
X		will be recalled into the current window.
X
X	:e!	Re-edit a file.  A different filename can be given, but the 
X		buffer name will not change to match it. 
X
X	^X-e	Edit the file whose pathname appears under the cursor.  That
X		is, if you are editing a makefile, you could edit one of the
X		source files by placing the cursor at the start of its name
X		and using this command.
X
X	:n	Go to the next buffer.  "next" means least recently used.
X
X	:rename	Rename the current buffer.  Prompts for a new name.  Does
X		not affect the filename associated with the buffer.  Use ":f"
X		to do that.
X		This command is useful for renaming the "[Output]" buffer, if
X		you wish to preserve its contents, but run a new command. 
X
X	:b	Edit a buffer.  Recalls the named buffer.  Does not look for
X		a file of that name.  Will find "invisible" buffers.
X
X	:ki	Kill a buffer.  Remove the buffer and its contents from the
X		editor.  Will ask if changes to the buffer should be discarded.
X		Currently, a buffer that is being displayed cannot be killed.
X		
X	*	Display a list of all buffers, or make that display go away
X		if it's already present.  Leave your finger on the key, and
X		it's easy to create and destroy the list.  The buffers are
X		numbered; the numbers correspond to the history numbers
X		shown and used by the '_' command, described above.  (If
X		the buffer number is greater than 9, then the "nn_" form of
X		the '_' command must be used, since '_' will only accept a
SHAR_EOF
true || echo 'restore of vile.hlp failed'
echo 'End of Vile part 15'
echo 'File vile.hlp is continued in part 16'
echo 16 > _shar_seq_.tmp
exit 0
-- 
		paul fox, pgf at cayman.com, (617)494-1999
		Cayman Systems, 26 Landsdowne St., Cambridge, MA 02139



More information about the Alt.sources mailing list