v08i026: The JOVE text editor, Part07/13

sources-request at mirror.TMC.COM sources-request at mirror.TMC.COM
Thu Feb 5 07:32:52 AEST 1987


Submitted by: seismo!rochester!jpayne (Jonathan Payne)
Mod.sources: Volume 8, Issue 26
Archive-name: jove/Part07

#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If all goes well, you will see the message "End of archive 7 (of 13)."
# Contents:  re.c recover.c scandir.c screen.c teachjove.c
#   tune.template version.c
PATH=/bin:/usr/bin:/usr/ucb; export PATH
echo shar: extracting "'re.c'" '(17213 characters)'
if test -f 're.c' ; then 
  echo shar: will not over-write existing file "'re.c'"
else
sed 's/^X//' >re.c <<'@//E*O*F re.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
X/* search package */
X
X#include "jove.h"
X#include "ctype.h"
X
X#define NALTS	16	/* number of alternate search strings */
X
Xchar	searchstr[128],
X	compbuf[256],		/* global default compbuf */
X	rep_search[128],	/* replace search string */
X	rep_str[128],		/* contains replacement string */
X	*cur_compb,		/* usually points at compbuf */
X	REbuf[LBSIZE],		/* points at line we're scanning */
X	*alternates[NALTS];
X
Xint	REdirection;
X
Xint	CaseIgnore = 0,
X	WrapScan = 0,
X	UseRE = 0;
X
Xprivate char	CaseEquiv[] = {
X	'\000',	'\001',	'\002',	'\003',	'\004',	'\005',	'\006',	'\007',
X	'\010',	'\011',	'\012',	'\013',	'\014',	'\015',	'\016',	'\017',
X	'\020',	'\021',	'\022',	'\023',	'\024',	'\025',	'\026',	'\027',
X	'\030',	'\031',	'\032',	'\033',	'\034',	'\035',	'\036',	'\037',
X	'\040',	'!',	'"',	'#',	'$',	'%',	'&',	'\'',
X	'(',	')',	'*',	'+',	',',	'-',	'.',	'/',
X	'0',	'1',	'2',	'3',	'4',	'5',	'6',	'7',
X	'8',	'9',	':',	';',	'<',	'=',	'>',	'?',
X	'@',	'A',	'B',	'C',	'D',	'E',	'F',	'G',
X	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
X	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
X	'X',	'Y',	'Z',	'[',	'\\',	']',	'^',	'_',
X	'`',	'A',	'B',	'C',	'D',	'E',	'F',	'G',
X	'H',	'I',	'J',	'K',	'L',	'M',	'N',	'O',
X	'P',	'Q',	'R',	'S',	'T',	'U',	'V',	'W',
X	'X',	'Y',	'Z',	'{',	'|',	'}',	'~',	'\177'
X};
X
X#define cind_cmp(a, b)	(CaseEquiv[a] == CaseEquiv[b])
X
Xprivate int	REpeekc;
Xprivate char	*REptr;
X
Xprivate
XREgetc()
X{
X	int	c;
X
X	if ((c = REpeekc) != -1)
X		REpeekc = -1;
X	else if (*REptr)
X		c = *REptr++;
X	else
X		c = 0;
X
X	return c;
X}
X
X#define STAR 	01	/* Match any number of last RE. */
X#define AT_BOL	2	/* ^ */
X#define AT_EOL	4	/* $ */
X#define AT_BOW	6	/* \< */
X#define AT_EOW	8	/* \> */
X#define OPENP	10	/* \( */
X#define CLOSEP	12	/* \) */
X#define CURLYB	14	/* \{ */
X
X#define NOSTR	14	/* Codes <= NOSTR can't be *'d. */
X
X#define ANYC	NOSTR+2		/* . */
X#define NORMC	ANYC+2		/* normal character */
X#define CINDC	NORMC+2		/* case independent character */
X#define ONE_OF	CINDC+2		/* [xxx] */
X#define NONE_OF	ONE_OF+2	/* [^xxx] */
X#define BACKREF	NONE_OF+2	/* \# */
X#define EOP	BACKREF+2	/* end of pattern */
X
X#define NPAR	9	/* [1-9] */
Xprivate int	nparens;
Xprivate char	*comp_p,
X		**alt_p,
X		**alt_endp;
X
XREcompile(pattern, re, into_buf, alt_bufp)
Xchar	*pattern,
X	*into_buf,
X	**alt_bufp;
X{
X	REptr = pattern;
X	REpeekc = -1;
X	comp_p = cur_compb = into_buf;
X	alt_p = alt_bufp;
X	alt_endp = alt_p + NALTS;
X	*alt_p++ = comp_p;
X	nparens = 0;
X	(void) do_comp(re ? OKAY_RE : NORM);
X	*alt_p = 0;
X}
X
X/* compile the pattern into an internal code */
X
Xprivate
Xdo_comp(kind)
X{
X	char	*last_p,
X		*chr_cnt = 0;
X	int	parens[NPAR],
X		*parenp,
X		c,
X		ret_code;
X
X	parenp = parens;
X	last_p = 0;
X	ret_code = 1;
X
X	while (c = REgetc()) {
X		if (comp_p > &cur_compb[(sizeof compbuf) - 4])
Xtoolong:		complain("Search string too long/complex.");
X		if (c != '*')
X			last_p = comp_p;
X
X		if (kind == NORM && index(".[*", c) != 0)
X			goto defchar;
X		switch (c) {
X		case '\\':
X			switch (c = REgetc()) {
X			case 0:
X				complain("Premature end of pattern.");
X
X			case '{':
X			    {
X			    	char	*wcntp;		/* word count */
X
X			    	*comp_p++ = CURLYB;
X			    	wcntp = comp_p;
X			    	*comp_p++ = 0;
X			    	for (;;) {
X			    		int	comp_val;
X			    		char	*comp_len;
X
X			    		comp_len = comp_p++;
X			    		comp_val = do_comp(IN_CB);
X			    		*comp_len = comp_p - comp_len;
X			    		(*wcntp)++;
X			    		if (comp_val == 0)
X			    			break;
X			    	}
X			    	break;
X			    }
X
X			case '}':
X				if (kind != IN_CB)
X					complain("Unexpected \}.");
X				ret_code = 0;
X				goto outahere;
X
X			case '(':
X				if (nparens >= NPAR)
X					complain("Too many ('s; max is %d.", NPAR);
X				*comp_p++ = OPENP;
X				*comp_p++ = nparens;
X				*parenp++ = nparens++;
X				break;
X
X			case ')':
X				if (parenp == parens)
X					complain("Too many )'s.");
X				*comp_p++ = CLOSEP;
X				*comp_p++ = *--parenp;
X				break;
X
X			case '|':
X				if (alt_p >= alt_endp)
X					complain("Too many alternates; max %d.", NALTS);
X				*comp_p++ = EOP;
X				*alt_p++ = comp_p;
X				nparens = 0;
X				break;
X
X			case '1':
X			case '2':
X			case '3':
X			case '4':
X			case '5':
X			case '6':
X			case '7':
X			case '8':
X			case '9':
X				*comp_p++ = BACKREF;
X				*comp_p++ = c - '1';
X				break;
X
X			case '<':
X				*comp_p++ = AT_BOW;
X				break;
X
X			case '>':
X				*comp_p++ = AT_EOW;
X				break;
X
X			default:
X				goto defchar;
X			}
X			break;
X
X		case ',':
X			if (kind != IN_CB)
X				goto defchar;
X			goto outahere;
X
X		case '.':
X			*comp_p++ = ANYC;
X			break;
X
X		case '^':
X			if (comp_p == cur_compb || comp_p[-1] == EOP) {
X				*comp_p++ = AT_BOL;
X				break;
X			}
X			goto defchar;
X
X		case '$':
X			if ((REpeekc = REgetc()) != 0 && REpeekc != '\\')
X				goto defchar;
X			*comp_p++ = AT_EOL;
X			break;
X
X		case '[':
X		    {
X		    	int	chrcnt;
X
X		    	*comp_p++ = ONE_OF;
X			if (comp_p + 16 >= &cur_compb[(sizeof compbuf)])
X				goto toolong;
X		    	bzero(comp_p, 16);
X		    	if ((REpeekc = REgetc()) == '^') {
X		    		*last_p = NONE_OF;
X		    		/* Get it for real this time. */
X		    		(void) REgetc();
X		    	}
X		    	chrcnt = 1;
X		    	while ((c = REgetc()) != ']' && c != 0) {
X		    		if (c == '\\')
X		    			c = REgetc();
X				else if ((REpeekc = REgetc()) == '-') {
X					int	c2;
X
X					(void) REgetc();     /* reread '-' */
X					c2 = REgetc();
X					while (c < c2) {
X						comp_p[c/8] |= (1 << (c%8));
X						c++;
X					}
X				}
X				comp_p[c/8] |= (1 << (c%8));
X		    		chrcnt++;
X		    	}
X		    	if (c == 0)
X		    		complain("Missing ].");
X		    	if (chrcnt == 1)
X		    		complain("Empty [].");
X		    	comp_p += 16;
X		    	break;
X		    }
X
X		case '*':
X			if (last_p == 0 || *last_p <= NOSTR)
X				goto defchar;
X			if (chr_cnt) {
X				char	lastc = chr_cnt[*chr_cnt];
X
X				comp_p = chr_cnt + *chr_cnt;
X				(*chr_cnt)--;
X				*comp_p++ = chr_cnt[-1] | STAR;
X				*comp_p++ = lastc;
X			} else
X				*last_p |= STAR;
X			break;
X
X		default:
Xdefchar:		if (chr_cnt)
X				(*chr_cnt)++;	/* increment the count */
X			else {
X				*comp_p++ = (CaseIgnore) ? CINDC : NORMC;
X				chr_cnt = comp_p++;
X				*chr_cnt = 1;   /* last_p[1] = 1; */
X			}
X			*comp_p++ = c;
X			continue;
X		}
X		chr_cnt = FALSE;
X	}
Xoutahere:
X	/* End of pattern, let's do some error checking. */
X	if (parenp != parens)
X		complain("Unmatched ()'s.");
X	if (kind == IN_CB && c == 0)	/* End of pattern with \}. */
X		complain("Missing \}.");
X	*comp_p++ = EOP;
X
X	return ret_code;
X}
X
Xprivate char	*pstrtlst[NPAR],	/* index into REbuf */
X		*pendlst[NPAR],
X		*REbolp,
X		*locs,
X		*loc1,
X		*loc2;
X
Xint	REbom,
X	REeom,		/* beginning and end of match */
X	REalt_num;	/* if alternatives, which one matched? */
X
Xprivate
Xbackref(n, linep)
Xregister char	*linep;
X{
X	register char	*backsp,
X			*backep;
X
X	backsp = pstrtlst[n];
X	backep = pendlst[n];
X	while (*backsp++ == *linep++)
X		if (backsp >= backep)
X			return 1;
X	return 0;
X}
X
Xprivate
Xmember(comp_p, c, af)
Xregister char	*comp_p;
Xregister int	c,
X		af;
X{
X	if (c == 0)
X		return 0;	/* try to match EOL always fails */
X	if (comp_p[c/8] & (1 << (c%8)))
X		return af;
X	return !af;
X}
X
Xprivate
XREmatch(linep, comp_p)
Xregister char	*linep,
X		*comp_p;
X{
X	char	*first_p = linep;
X	register int	n;
X
X	for (;;) switch (*comp_p++) {
X	case NORMC:
X		n = *comp_p++;
X		while (--n >= 0)
X			if (*linep++ != *comp_p++)
X				return 0;
X		continue;
X
X	case CINDC:	/* case independent comparison */
X		n = *comp_p++;
X		while (--n >= 0)
X			if (!cind_cmp(*linep++, *comp_p++))
X				return 0;
X		continue;
X
X	case EOP:
X		loc2 = linep;
X		REeom = (loc2 - REbolp);
X		return 1;	/* Success! */
X
X	case AT_BOL:
X		if (linep == REbolp)
X			continue;
X		return 0;
X
X	case AT_EOL:
X		if (*linep == 0)
X			continue;
X		return 0;
X
X	case ANYC:
X		if (*linep++ != 0)
X			continue;
X		return 0;
X
X	case AT_BOW:
X		if (ismword(*linep) && (linep == REbolp || !ismword(linep[-1])))
X			continue;
X		return 0;
X
X	case AT_EOW:
X		if ((*linep == 0 || !ismword(*linep)) &&
X		    (linep != REbolp && ismword(linep[-1])))
X			continue;
X		return 0;
X
X	case ONE_OF:
X	case NONE_OF:
X		if (member(comp_p, *linep++, comp_p[-1] == ONE_OF)) {
X			comp_p += 16;
X			continue;
X		}
X		return 0;
X
X	case OPENP:
X		pstrtlst[*comp_p++] = linep;
X		continue;
X
X	case CLOSEP:
X		pendlst[*comp_p++] = linep;
X		continue;
X
X	case BACKREF:
X		if (pstrtlst[n = *comp_p++] == 0) {
X			s_mess("\\%d was not specified.", n + 1);
X			return 0;
X		}
X		if (backref(n, linep)) {
X			linep += pendlst[n] - pstrtlst[n];
X			continue;
X		}
X		return 0;
X
X	case CURLYB:
X	    {
X	    	int	wcnt,
X	    		any;
X
X	    	wcnt = *comp_p++;
X	    	any = 0;
X
X	    	while (--wcnt >= 0) {
X	    		if (any == 0)
X	    			any = REmatch(linep, comp_p + 1);
X	    		comp_p += *comp_p;
X	    	}
X	    	if (any == 0)
X	    		return 0;
X	    	linep = loc2;
X	    	continue;
X	    }
X
X	case ANYC | STAR:
X		first_p = linep;
X		while (*linep++)
X			;
X		goto star;
X
X	case NORMC | STAR:
X		first_p = linep;
X		while (*comp_p == *linep++)
X			;
X		comp_p++;
X		goto star;
X
X	case CINDC | STAR:
X		first_p = linep;
X		while (cind_cmp(*comp_p, *linep++))
X			;
X		comp_p++;
X		goto star;
X
X	case ONE_OF | STAR:
X	case NONE_OF | STAR:
X		first_p = linep;
X		while (member(comp_p, *linep++, comp_p[-1] == (ONE_OF | STAR)))
X			;
X		comp_p += 16;
X		goto star;
X
X	case BACKREF | STAR:
X		first_p = linep;
X		n = *comp_p++;
X		while (backref(n, linep))
X			linep += pendlst[n] - pstrtlst[n];
X		while (linep >= first_p) {
X			if (REmatch(linep, comp_p))
X				return 1;
X			linep -= pendlst[n] - pstrtlst[n];
X		}
X		continue;
X
Xstar:		do {
X			linep--;
X			if (linep < locs)
X				break;
X			if (REmatch(linep, comp_p))
X				return 1;
X		} while (linep > first_p);
X		return 0;
X
X	default:
X		complain("RE error match (%d).", comp_p[-1]);
X	}
X	/* NOTREACHED. */
X}
X
Xprivate
XREreset()
X{
X	register int	i;
X
X	for (i = 0; i < NPAR; i++)
X		pstrtlst[i] = pendlst[i] = 0;
X}
X
X/* Index LINE at OFFSET, the compiled EXPR, with alternates ALTS.  If
X   lbuf_okay is nonzero it's okay to use linebuf if LINE is the current
X   line.  This should save lots of time in things like paren matching in
X   LISP mode.  Saves all that copying from linebuf to REbuf.  substitute()
X   is the guy who calls re_lindex with lbuf_okay as 0, since the substitution
X   gets placed in linebuf ... doesn't work too well when the source and
X   destination strings are the same.  I hate all these arguments!
X
X   This code is cumbersome, repetetive for reasons of efficiency.  Fast
X   search is a must as far as I am concerned. */
X
Xre_lindex(line, offset, expr, alts, lbuf_okay)
XLine	*line;
Xchar	*expr,
X	**alts;
X{
X	int	isquick;
X	register int	firstc,
X			c;
X	register char	*resp;
X
X	REreset();
X	if (lbuf_okay) {
X		REbolp = lbptr(line);
X		if (offset == -1)
X			offset = strlen(REbolp);	/* arg! */
X	} else {
X		REbolp = ltobuf(line, REbuf);
X		if (offset == -1) {	/* Reverse search, find end of line. */
X			extern int	Jr_Len;
X
X			offset = Jr_Len;	/* Just Read Len. */
X		}
X	}
X	resp = REbolp;
X	isquick = ((expr[0] == NORMC || expr[0] == CINDC) &&
X		   (alternates[1] == 0));
X	if (isquick) {
X		firstc = expr[2];
X		if (expr[0] == CINDC)
X			firstc = CaseEquiv[firstc];
X	}
X	locs = REbolp + offset;
X
X	if (REdirection == FORWARD) {
X	    do {
X		char	**altp = alts;
X
X		if (isquick) {
X			if (expr[0] == NORMC)
X				while ((c = *locs++) != 0 && c != firstc)
X					;
X			else
X				while (((c = *locs++) != 0) &&
X					(CaseEquiv[c] != firstc))
X					;
X			if (*--locs == 0)
X				break;
X		}
X		REalt_num = 1;
X		while (*altp) {
X			if (REmatch(locs, *altp++)) {
X				loc1 = locs;
X				REbom = loc1 - REbolp;
X				return 1;
X			}
X			REalt_num++;
X		}
X	    } while (*locs++);
X	} else {
X	    do {
X		char	**altp = alts;
X
X		if (isquick) {
X			if (expr[0] == NORMC) {
X				while (locs >= REbolp && *locs-- != firstc)
X					;
X				if (*++locs != firstc)
X					break;
X			} else {
X				while (locs >= REbolp && CaseEquiv[*locs--] != firstc)
X					;
X				if (CaseEquiv[*++locs] != firstc)
X					break;
X			}
X		}
X		REalt_num = 1;
X		while (*altp) {
X			if (REmatch(locs, *altp++)) {
X				loc1 = locs;
X				REbom = loc1 - REbolp;
X				return 1;
X			}
X			REalt_num++;
X		}
X	    } while (--locs >= resp);
X	}
X
X	return 0;
X}
X
Xint	okay_wrap = 0;	/* Do a wrap search ... not when we're
X			   parsing errors ... */
X
XBufpos *
Xdosearch(pattern, dir, re)
Xchar	*pattern;
X{
X	Bufpos	*pos;
X
X	if (bobp() && eobp())	/* Can't match!  There's no buffer. */
X		return 0;
X
X	REcompile(pattern, re, compbuf, alternates);
X
X	pos = docompiled(dir, compbuf, alternates);
X	return pos;
X}
X
XBufpos *
Xdocompiled(dir, expr, alts)
Xchar	*expr,
X	**alts;
X{
X	static Bufpos	ret;
X	register Line	*lp;
X	register int	offset;
X	int	we_wrapped = 0;
X
X	lsave();
X	/* Search now lsave()'s so it doesn't make any assumptions on
X	   whether the the contents of curline/curchar are in linebuf.
X	   Nowhere does search write all over linebuf.  However, we have to
X	   be careful about what calls we make here, because many of them
X	   assume (and rightly so) that curline is in linebuf. */
X
X	REdirection = dir;
X	lp = curline;
X	offset = curchar;
X	if (dir == BACKWARD) {
X		if (bobp()) {
X			if (okay_wrap && WrapScan)
X				goto doit;
X			return 0;
X		}
X		/* here we simulate BackChar() */
X		if (bolp()) {
X			lp = lp->l_prev;
X			offset = strlen(lbptr(lp));
X		} else
X			--offset;
X	} else if ((dir == FORWARD) &&
X		   (lbptr(lp)[offset] == '\0') &&
X		   !lastp(lp)) {
X		lp = lp->l_next;
X		offset = 0;
X	}
X
X	do {
X		if (re_lindex(lp, offset, expr, alts, YES))
X			break;
Xdoit:		lp = (dir == FORWARD) ? lp->l_next : lp->l_prev;
X		if (lp == 0) {
X			if (okay_wrap && WrapScan) {
X				lp = (dir == FORWARD) ?
X				     curbuf->b_first : curbuf->b_last;
X				we_wrapped++;
X			} else
X				 break;
X		}
X		if (dir == FORWARD)
X			offset = 0;
X		else
X			offset = -1;	/* signals re_lindex ... */
X	} while (lp != curline);
X
X	if (lp == curline && we_wrapped)
X		lp = 0;
X	if (lp == 0)
X		return 0;
X	ret.p_line = lp;
X	ret.p_char = (dir == FORWARD) ? REeom : REbom;
X	return &ret;
X}
X
Xprivate char *
Xinsert(off, endp, which)
Xchar	*off,
X	*endp;
X{
X	register char	*pp;
X	register int	n;
X
X	n = pendlst[which] - pstrtlst[which];
X	pp = pstrtlst[which];
X	while (--n >= 0) {
X		*off++ = *pp++;
X		if (off >= endp)
X			len_error(ERROR);
X	}
X	return off;
X}
X
X/* Perform the substitution.  If DELP is nonzero the matched string is
X   deleted, i.e., the substitution string is not inserted. */
X
Xre_dosub(tobuf, delp)
Xchar	*tobuf;
X{
X	register char	*tp,
X			*rp,
X			*repp;
X	int	c;
X	char	*endp;
X
X	tp = tobuf;
X	endp = tp + LBSIZE;
X	rp = REbuf;
X	repp = rep_str;
X
X	while (rp < loc1)
X		*tp++ = *rp++;
X
X	if (!delp) while (c = *repp++) {
X		if (c == '\\') {
X			if ((c = *repp++) == '\0') {
X				*tp++ = '\\';
X	  			goto endchk;
X			} else if ((c = *repp++) >= '1' && c <= nparens + '1') {
X				tp = insert(tp, endp, c - '1');
X				continue;
X			}
X		}
X		*tp++ = c;
Xendchk:		if (tp >= endp)
X			len_error(ERROR);
X	}
X	rp = loc2;
X	loc2 = REbuf + max(1, tp - tobuf);
X	REeom = loc2 - REbuf;
X	/* At least one character past the match, to prevent an infinite
X	   number of replacements in the same position, e.g.,
X	   replace "^" with "". */
X	while (*tp++ = *rp++)
X		if (tp >= endp)
X			len_error(ERROR);
X}
X
Xputmatch(which, buf, size)
Xchar	*buf;
X{
X	*(insert(buf, buf + size, which - 1)) = 0;
X}
X
Xsetsearch(str)
Xchar	*str;
X{
X	strcpy(searchstr, str);
X}
X
Xchar *
Xgetsearch()
X{
X	return searchstr;
X}
X
XRErecur()
X{
X	char	sbuf[sizeof searchstr],
X		cbuf[sizeof compbuf],
X		repbuf[sizeof rep_str],
X		*altbuf[NALTS];
X	int	npars;
X	Mark	*m = MakeMark(curline, REbom, FLOATER);
X
X	message("Type C-X C-C to continue with query replace.");
X
X	npars = nparens;
X	byte_copy(compbuf, cbuf, sizeof compbuf);
X	byte_copy(searchstr, sbuf, sizeof searchstr);
X	byte_copy(rep_str, repbuf, sizeof rep_str);
X	byte_copy((char *) alternates, (char *) altbuf, sizeof alternates);
X	Recur();
X	nparens = npars;
X	byte_copy(cbuf, compbuf, sizeof compbuf);
X	byte_copy(sbuf, searchstr, sizeof searchstr);
X	byte_copy(repbuf, rep_str, sizeof rep_str);
X	byte_copy((char *) altbuf, (char *) alternates, sizeof alternates);
X	if (!exp_p)
X		ToMark(m);
X	DelMark(m);
X}
X
XForSearch()
X{
X	search(FORWARD, UseRE, YES);
X}
X
XRevSearch()
X{
X	search(BACKWARD, UseRE, YES);
X}
X
XFSrchND()
X{
X	search(FORWARD, UseRE, NO);
X}
X
XRSrchND()
X{
X	search(BACKWARD, UseRE, NO);
X}
X
Xprivate
Xsearch(dir, re, setdefault)
X{
X	Bufpos	*newdot;
X	char	*s;
X
X	s = ask(searchstr, ProcFmt);
X	if (setdefault)
X		setsearch(s);
X	okay_wrap = YES;
X	newdot = dosearch(s, dir, re);
X	okay_wrap = NO;
X	if (newdot == 0) {
X		if (WrapScan)
X			complain("No \"%s\" in buffer.", s);
X		else
X			complain("No \"%s\" found to %s.", s,
X				 (dir == FORWARD) ? "bottom" : "top");
X	}
X	PushPntp(newdot->p_line);
X	SetDot(newdot);
X}
X
X/* Do we match PATTERN at OFFSET in BUF? */
X
XLookingAt(pattern, buf, offset)
Xchar	*pattern,
X	*buf;
X{
X	register char	**alt = alternates;
X
X	REcompile(pattern, 1, compbuf, alternates);
X	REreset();
X	locs = buf + offset;
X	REbolp = buf;
X
X	while (*alt)
X		if (REmatch(locs, *alt++))
X			return 1;
X	return 0;
X}
X
Xlook_at(expr)
Xchar	*expr;
X{
X	REcompile(expr, 0, compbuf, alternates);
X	REreset();
X	locs = linebuf + curchar;
X	REbolp = linebuf;
X	if (REmatch(locs, alternates[0]))
X		return 1;
X	return 0;
X}
X
@//E*O*F re.c//
if test 17213 -ne "`wc -c <'re.c'`"; then
    echo shar: error transmitting "'re.c'" '(should have been 17213 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'recover.c'" '(14068 characters)'
if test -f 'recover.c' ; then 
  echo shar: will not over-write existing file "'recover.c'"
else
sed 's/^X//' >recover.c <<'@//E*O*F recover.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
X/* Recovers JOVE files after a system/editor crash.
X   Usage: recover [-d directory] [-syscrash]
X   The -syscrash option is specified in /etc/rc and what it does it
X   move all the jove tmp files from TMP_DIR to REC_DIR.
X
X   The -d option lets you specify the directory to search for tmp files when
X   the default isn't the right one.
X
X   Look in Makefile to change the default directories. */
X
X#include <stdio.h>	/* Do stdio first so it doesn't override OUR
X			   definitions. */
X#undef EOF
X#undef BUFSIZ
X#undef putchar
X
X#include "jove.h"
X#include "temp.h"
X#include "rec.h"
X#include <signal.h>
X#include <sys/file.h>
X#include <sys/stat.h>
X#include <sys/dir.h>
X
X#ifndef L_SET
X#	define L_SET	0
X#	define L_INCR	1
X#endif
X
Xchar	blk_buf[BUFSIZ];
Xint	nleft;
XFILE	*ptrs_fp;
Xint	data_fd;
Xstruct rec_head	Header;
Xchar	datafile[40],
X	pntrfile[40];
Xlong	Nchars,
X	Nlines;
Xchar	tty[] = "/dev/tty";
Xint	UserID,
X	Verbose = 0;
Xchar	*Directory = 0;		/* the directory we're looking in */
X
Xstruct file_pair {
X	char	*file_data,
X		*file_rec;
X#define INSPECTED	01
X	int	file_flags;
X	struct file_pair	*file_next;
X} *First = 0,
X  *Last = 0;
X
Xstruct rec_entry	*buflist[100] = {0};
X
X#ifndef BSD4_2
X
Xtypedef struct {
X	int	d_fd;		/* File descriptor for this directory */
X} DIR;
X
XDIR *
Xopendir(dir)
Xchar	*dir;
X{
X	DIR	*dp = (DIR *) malloc(sizeof *dp);
X
X	if ((dp->d_fd = open(dir, 0)) == -1)
X		return NULL;
X	return dp;
X}
X
Xclosedir(dp)
XDIR	*dp;
X{
X	(void) close(dp->d_fd);
X	free(dp);
X}
X
Xstruct direct *
Xreaddir(dp)
XDIR	*dp;
X{
X	static struct direct	dir;
X
X	do
X		if (read(dp->d_fd, &dir, sizeof dir) != sizeof dir)
X			return NULL;
X	while (dir.d_ino == 0);
X
X	return &dir;
X}
X
X#endif BSD4_2
X
X/* Get a line at `tl' in the tmp file into `buf' which should be LBSIZE
X   long. */
X
Xgetline(tl, buf)
Xdisk_line	tl;
Xchar	*buf;
X{
X	register char	*bp,
X			*lp;
X	register int	nl;
X	char	*getblock();
X
X	lp = buf;
X	bp = getblock(tl >> 1);
X	nl = nleft;
X	tl = blk_round(tl);
X
X	while (*lp++ = *bp++) {
X		if (--nl == 0) {
X			tl = forward_block(tl);
X			bp = getblock(tl >> 1);
X			nl = nleft;
X		}
X	}
X}
X
Xchar *
Xgetblock(atl)
Xdisk_line	atl;
X{
X	int	bno,
X		off;
X	static int	curblock = -1;
X
X	bno = daddr_to_bno(atl);
X	off = daddr_to_off(atl);
X	nleft = BUFSIZ - off;
X
X	if (bno != curblock) {
X		lseek(data_fd, (long) bno * BUFSIZ, L_SET);
X		read(data_fd, blk_buf, BUFSIZ);
X		curblock = bno;
X	}
X	return blk_buf + off;
X}
X
Xchar *
Xcopystr(s)
Xchar	*s;
X{
X	char	*str;
X
X	str = malloc(strlen(s) + 1);
X	strcpy(str, s);
X
X	return str;
X}
X
X/* Scandir returns the number of entries or -1 if the directory cannoot
X   be opened or malloc fails. */
X
Xscandir(dir, nmptr, qualify, sorter)
Xchar	*dir;
Xstruct direct	***nmptr;
Xint	(*qualify)();
Xstruct direct	*(*sorter)();
X{
X	DIR	*dirp;
X	struct direct	*entry,
X			**ourarray;
X	int	nalloc = 10,
X		nentries = 0;
X
X	if ((dirp = opendir(dir)) == NULL)
X		return -1;
X	ourarray = (struct direct **) malloc(nalloc * sizeof (struct direct *));
X	while ((entry = readdir(dirp)) != NULL) {
X		if (qualify != 0 && (*qualify)(entry) == 0)
X			continue;
X		if (nentries == nalloc) {
X			ourarray = (struct direct **) realloc(ourarray, (nalloc += 10) * sizeof (struct direct));
X			if (ourarray == NULL)
X				return -1;
X		}
X		ourarray[nentries] = (struct direct *) malloc(sizeof *entry);
X		*ourarray[nentries] = *entry;
X		nentries++;
X	}
X	closedir(dirp);
X	if (nentries != nalloc)
X		ourarray = (struct direct **) realloc(ourarray,
X					(nentries * sizeof (struct direct)));
X	if (sorter != 0)
X		qsort(ourarray, nentries, sizeof (struct direct **), sorter);
X	*nmptr = ourarray;
X
X	return nentries;
X}
X
Xalphacomp(a, b)
Xstruct direct	**a,
X		**b;
X{
X	return strcmp((*a)->d_name, (*b)->d_name);
X}
X
Xchar	*CurDir;
X
X/* Scan the DIRNAME directory for jove tmp files, and make a linked list
X   out of them. */
X
Xget_files(dirname)
Xchar	*dirname;
X{
X	int	add_name();
X	struct direct	**nmptr;
X
X	CurDir = dirname;
X	scandir(dirname, &nmptr, add_name, (int (*)())0);
X}
X
Xadd_name(dp)
Xstruct direct	*dp;
X{
X	char	dfile[128],
X		rfile[128];
X	struct file_pair	*fp;
X	struct rec_head		header;
X	int	fd;
X
X	if (strncmp(dp->d_name, "jrec", 4) != 0)
X		return 0;
X	/* If we get here, we found a "recover" tmp file, so now
X	   we look for the corresponding "data" tmp file.  First,
X	   though, we check to see whether there is anything in
X	   the "recover" file.  If it's 0 length, there's no point
X	   in saving its name. */
X	(void) sprintf(rfile, "%s/%s", CurDir, dp->d_name);
X	(void) sprintf(dfile, "%s/jove%s", CurDir, dp->d_name + 4);
X	if ((fd = open(rfile, 0)) != -1) {
X		if ((read(fd, (char *) &header, sizeof header) != sizeof header)) {
X			close(fd);
X		    	return 0;
X		} else
X			close(fd);
X	}
X	if (access(dfile, 0) != 0) {
X		fprintf(stderr, "recover: can't find the data file for %s/%s\n", Directory, dp->d_name);
X		fprintf(stderr, "so deleting...\n");
X		(void) unlink(rfile);
X		(void) unlink(dfile);
X		return 0;
X	}
X	/* If we get here, we've found both files, so we put them
X	   in the list. */
X	fp = (struct file_pair *) malloc (sizeof *fp);
X	if ((char *) fp == 0) {
X		fprintf(stderr, "recover: cannot malloc for file_pair.\n");
X		exit(-1);
X	}
X	fp->file_data = copystr(dfile);
X	fp->file_rec = copystr(rfile);
X	fp->file_flags = 0;
X	fp->file_next = First;
X	First = fp;
X
X	return 1;
X}
X
Xoptions()
X{
X	printf("Options are:\n");
X	printf("	?		list options.\n");
X	printf("	get		get a buffer to a file.\n");
X	printf("	list		list known buffers.\n");
X	printf("	print		print a buffer to terminal.\n");
X	printf("	quit		quit and delete jove tmp files.\n");
X	printf("	restore		restore all buffers.\n");
X}
X
X/* Returns a legitimate buffer # */
X
Xstruct rec_entry **
Xgetsrc()
X{
X	char	name[128];
X	int	number;
X
X	for (;;) {
X		tellme("Which buffer ('?' for list)? ", name);
X		if (name[0] == '?')
X			list();
X		else if (name[0] == '\0')
X			return 0;
X		else if ((number = atoi(name)) > 0 && number <= Header.Nbuffers)
X			return &buflist[number];
X		else {
X			int	i;
X
X			for (i = 1; i <= Header.Nbuffers; i++)
X				if (strcmp(buflist[i]->r_bname, name) == 0)
X					return &buflist[i];
X			printf("%s: unknown buffer.\n", name);
X		}
X	}
X}
X
X/* Get a destination file name. */
X
Xstatic char *
Xgetdest()
X{
X	static char	filebuf[256];
X
X	tellme("Output file: ", filebuf);
X	if (filebuf[0] == '\0')
X		return 0;
X	return filebuf;
X}
X
X#include "ctype.h"
X
Xchar *
Xreadword(buf)
Xchar	*buf;
X{
X	int	c;
X	char	*bp = buf;
X
X	while (index(" \t\n", c = getchar()))
X		;
X
X	do {
X		if (index(" \t\n", c))
X			break;
X		*bp++ = c;
X	} while ((c = getchar()) != EOF);
X	*bp = 0;
X
X	return buf;
X}
X
Xtellme(quest, answer)
Xchar	*quest,
X	*answer;
X{
X	if (stdin->_cnt <= 0) {
X		printf("%s", quest);
X		fflush(stdout);
X	}
X	readword(answer);
X}
X
X/* Print the specified file to strandard output. */
X
Xjmp_buf	int_env;
X
Xcatch()
X{
X	longjmp(int_env, 1);
X}
X
Xrestore()
X{
X	register int	i;
X	char	tofile[100],
X		answer[30];
X	int	nrecovered = 0;
X
X	for (i = 1; i <= Header.Nbuffers; i++) {
X		(void) sprintf(tofile, "#%s", buflist[i]->r_bname);
Xtryagain:
X		printf("Restoring %s to %s, okay?", buflist[i]->r_bname,
X						     tofile);
X		tellme(" ", answer);
X		switch (answer[0]) {
X		case 'y':
X			break;
X
X		case 'n':
X			continue;
X
X		default:
X			tellme("What file should I use instead? ", tofile);
X			goto tryagain;
X		}
X		get(&buflist[i], tofile);
X		nrecovered++;
X	}
X	printf("Recovered %d buffers.\n", nrecovered);
X}
X
Xget(src, dest)
Xstruct rec_entry	**src;
Xchar	*dest;
X{
X	FILE	*outfile;
X
X	if (src == 0 || dest == 0)
X		return;
X	(void) signal(SIGINT, catch);
X	if (setjmp(int_env) == 0) {
X		if ((outfile = fopen(dest, "w")) == NULL) {
X			printf("recover: cannot create %s.\n", dest);
X			return;
X		}
X		seekto(src - buflist);
X		if (dest != tty)
X			printf("\"%s\"", dest);
X		dump_file(outfile);
X	} else
X		printf("\nAborted!\n");
X	fclose(outfile);
X	if (dest != tty)
X		printf(" %ld lines, %ld characters.\n", Nlines, Nchars);
X	(void) signal(SIGINT, SIG_DFL);
X}
X
Xchar **
Xscanvec(args, str)
Xregister char	**args,
X		*str;
X{
X	while (*args) {
X		if (strcmp(*args, str) == 0)
X			return args;
X		args++;
X	}
X	return 0;
X}
X
Xread_rec(recptr)
Xstruct rec_entry	*recptr;
X{
X	if (fread((char *) recptr, sizeof *recptr, 1, ptrs_fp) != 1)
X		fprintf(stderr, "recover: cannot read record.\n");
X}
X
Xseekto(which)
X{
X	struct rec_entry	rec;
X
X	fseek(ptrs_fp, (long) (sizeof Header), L_SET);
X	
X	while (which-- > 1) {
X		read_rec(&rec);
X		if (fseek(ptrs_fp, (long) rec.r_nlines * sizeof (disk_line),
X			L_INCR) == -1)
X			printf("recover: improper fseek!\n");
X	}
X}
X
Xmakblist()
X{
X	int	i;
X
X	for (i = 1; i <= Header.Nbuffers; i++) {
X		seekto(i);
X		if (buflist[i] == 0)
X			buflist[i] = (struct rec_entry *) malloc (sizeof (struct rec_entry));
X		read_rec(buflist[i]);
X	}
X	if (buflist[i]) {
X		free((char *) buflist[i]);
X		buflist[i] = 0;
X	}
X}
X
Xdisk_line
Xgetaddr(fp)
Xregister FILE	*fp;
X{
X	register int	nchars = sizeof (disk_line);
X	disk_line	addr;
X	register char	*cp = (char *) &addr;
X
X	while (--nchars >= 0)
X		*cp++ = getc(fp);
X
X	return addr;
X}
X
Xdump_file(out)
XFILE	*out;
X{
X	struct rec_entry	record;
X	register int	nlines;
X	register disk_line	daddr;
X	char	buf[BUFSIZ];
X
X	read_rec(&record);
X	nlines = record.r_nlines;
X	Nchars = Nlines = 0L;
X	while (--nlines >= 0) {
X		daddr = getaddr(ptrs_fp);
X		getline(daddr, buf);
X		Nlines++;
X		Nchars += 1 + strlen(buf);
X		fputs(buf, out);
X		if (nlines > 0)
X			fputc('\n', out);
X	}
X	if (out != stdout)
X		fclose(out);
X}
X
X/* List all the buffers. */
X
Xlist()
X{
X	int	i;
X
X	for (i = 1; i <= Header.Nbuffers; i++)
X		printf("%d) buffer %s  \"%s\" (%d lines)\n", i,
X			buflist[i]->r_bname,
X			buflist[i]->r_fname,
X			buflist[i]->r_nlines);
X}
X
Xdoit(fp)
Xstruct file_pair	*fp;
X{
X	char	answer[30];
X	char	*datafile = fp->file_data,
X		*pntrfile = fp->file_rec;
X
X	ptrs_fp = fopen(pntrfile, "r");
X	if (ptrs_fp == NULL) {
X		if (Verbose)
X			fprintf(stderr, "recover: cannot read rec file (%s).\n", pntrfile);
X		return 0;
X	}
X	fread((char *) &Header, sizeof Header, 1, ptrs_fp);
X	if (Header.Uid != UserID)
X		return 0;
X
X	/* Don't ask about JOVE's that are still running ... */
X#ifdef KILL0
X	if (kill(Header.Pid, 0) == 0)
X		return 0;
X#else
X#ifdef LSRHS
X	if (pexist(Header.Pid))
X		return 0;
X#endif LSRHS
X#endif KILL0
X
X	if (Header.Nbuffers == 0) {
X		printf("There are no modified buffers in %s; should I delete the tmp file?", pntrfile);
X		ask_del(" ", fp);
X		return 1;
X	}
X		
X	if (Header.Nbuffers < 0) {
X		fprintf(stderr, "recover: %s doesn't look like a jove file.\n", pntrfile);
X		ask_del("Should I delete it? ", fp);
X		return 1;	/* We'll, we sort of found something. */
X	}
X	printf("Found %d buffer%s last updated: %s",
X		Header.Nbuffers,
X		Header.Nbuffers != 1 ? "s" : "",
X		ctime(&Header.UpdTime));
X	data_fd = open(datafile, 0);
X	if (data_fd == -1) {
X		fprintf(stderr, "recover: but I can't read the data file (%s).\n", datafile);
X		ask_del("Should I delete the tmp files? ", fp);
X		return 1;
X	}
X	makblist();
X
X	for (;;) {
X		tellme("(Type '?' for options): ", answer);
X		switch (answer[0]) {
X		case '\0':
X			continue;
X
X		case '?':
X			options();
X			break;
X
X		case 'l':
X			list();
X			break;
X
X		case 'p':
X			get(getsrc(), tty);
X			break;
X
X		case 'q':
X			ask_del("Shall I delete the tmp files? ", fp);
X			return 1;
X
X		case 'g':
X		    {	/* So it asks for src first. */
X		    	char	*dest;
X		    	struct rec_entry	**src;
X
X		    	if ((src = getsrc()) == 0)
X		    		break;
X		    	dest = getdest();
X			get(src, dest);
X			break;
X		    }
X
X		case 'r':
X			restore();
X			break;
X
X		default:
X			printf("I don't know how to \"%s\"!\n", answer);
X			break;
X		}
X	}
X}
X
Xask_del(prompt, fp)
Xchar	*prompt;
Xstruct file_pair	*fp;
X{
X	char	yorn[20];
X
X	tellme(prompt, yorn);
X	if (yorn[0] == 'y')
X		del_files(fp);
X}
X
Xdel_files(fp)
Xstruct file_pair	*fp;
X{
X	(void) unlink(fp->file_data);
X	(void) unlink(fp->file_rec);
X}
X
X#ifdef notdef
Xsavetmps()
X{
X	struct file_pair	*fp;
X	int	status,
X		pid;
X
X	if (strcmp(TMP_DIR, REC_DIR) == 0)
X		return;		/* Files are moved to the same place. */
X	get_files(TMP_DIR);
X	for (fp = First; fp != 0; fp = fp->file_next) {
X		switch (pid = fork()) {
X		case -1:
X			fprintf(stderr, "recover: can't fork\n!");
X			exit(-1);
X
X		case 0:
X			execl("/bin/cp", "cp", fp->file_data, fp->file_rec, 
X				  REC_DIR, (char *)0);
X			fprintf(stderr, "recover: cannot execl /bin/cp.\n");
X			exit(-1);
X
X		default:
X			while (wait(&status) != pid)
X				;
X			if (status != 0)
X				fprintf(stderr, "recover: non-zero status (%d) returned from copy.\n", status);
X		}
X	}
X}
X#endif
X
Xlookup(dir)
Xchar	*dir;
X{
X	struct file_pair	*fp;
X	struct rec_head		header;
X	char	yorn[20];
X	int	nfound = 0,
X		this_one;
X
X	printf("Checking %s ...\n", dir);
X	Directory = dir;
X	get_files(dir);
X	for (fp = First; fp != 0; fp = fp->file_next) {
X		nfound += doit(fp);
X		if (ptrs_fp)
X			(void) fclose(ptrs_fp);
X		if (data_fd > 0)
X			(void) close(data_fd);
X	}
X	return nfound;
X}
X
Xmain(argc, argv)
Xint	argc;
Xchar	*argv[];
X{
X	int	nfound;
X	char	**argvp;
X
X	UserID = getuid();
X
X	if (scanvec(argv, "-help")) {
X		printf("recover: usage: recover [-d directory]\n");
X		printf("Use \"recover\" after JOVE has died for some\n");
X		printf("unknown reason.\n\n");
X		printf("Use \"recover -syscrash\" when the system is in the process\n");
X		printf("of rebooting.  This is done automatically at reboot time\n");
X		printf("and so most of you don't have to worry about that.\n\n");
X		printf("Use \"recover -d directory\" when the tmp files are store\n");
X		printf("in DIRECTORY instead of the default one (/tmp).\n");
X		exit(0);
X	}
X	if (scanvec(argv, "-v"))
X		Verbose++;
X/*	if (scanvec(argv, "-syscrash")) {
X		printf("Recovering jove files ... ");
X		savetmps();
X		printf("Done.\n");
X		exit(0);
X	} */
X	if (argvp = scanvec(argv, "-uid"))
X		UserID = atoi(argvp[1]);
X	if (argvp = scanvec(argv, "-d"))
X		nfound = lookup(argvp[1]);
X	else
X		nfound = lookup(TmpFilePath);
X	if (nfound == 0)
X		printf("There's nothing to recover.\n");
X}
@//E*O*F recover.c//
if test 14068 -ne "`wc -c <'recover.c'`"; then
    echo shar: error transmitting "'recover.c'" '(should have been 14068 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'scandir.c'" '(2708 characters)'
if test -f 'scandir.c' ; then 
  echo shar: will not over-write existing file "'scandir.c'"
else
sed 's/^X//' >scandir.c <<'@//E*O*F scandir.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
X#include "jove.h"
X#include <sys/stat.h>
X#include <sys/dir.h>
X
X#ifdef F_COMPLETION
X
X#ifdef BSD4_2
X
X#define DIRSIZE(entry)	DIRSIZ(entry)
X
X#else
X
X#define DIRSIZE(entry)	(min(strlen(entry->d_name), DIRSIZ))
X
Xtypedef struct {
X	int	d_fd;		/* File descriptor for this directory */
X} DIR;
X
XDIR *
Xopendir(dir)
Xchar	*dir;
X{
X	DIR	*dp = (DIR *) malloc(sizeof *dp);
X	struct stat	stbuf;
X
X	if ((dp->d_fd = open(dir, 0)) == -1)
X		return 0;
X	if ((fstat(dp->d_fd, &stbuf) == -1) || !(stbuf.st_mode & S_IFDIR)) {
X		closedir(dp);
X		return 0;	/* this isn't a directory! */
X	}
X	return dp;
X}
X
Xclosedir(dp)
XDIR	*dp;
X{
X	(void) close(dp->d_fd);
X	free((char *) dp);
X}
X
Xstruct direct *
Xreaddir(dp)
XDIR	*dp;
X{
X	static struct direct	dir;
X
X	do
X		if (read(dp->d_fd, &dir, sizeof dir) != sizeof dir)
X			return 0;
X	while (dir.d_ino == 0);
X
X	return &dir;
X}
X
X#endif BSD4_2
X
X/* Scandir returns the number of entries or -1 if the directory cannoot
X   be opened or malloc fails. */
X
Xscandir(dir, nmptr, qualify, sorter)
Xchar	*dir;
Xchar	***nmptr;
Xint	(*qualify)();
Xint	(*sorter)();
X{
X	DIR	*dirp;
X	struct direct	*entry;
X	char	**ourarray;
X	unsigned int	nalloc = 10,
X			nentries = 0;
X
X	if ((dirp = opendir(dir)) == 0)
X		return -1;
X	if ((ourarray = (char **) malloc(nalloc * sizeof (char *))) == 0)
Xmemfail:	complain("[Malloc failed: cannot scandir]");
X	while ((entry = readdir(dirp)) != 0) {
X		if (qualify != 0 && (*qualify)(entry->d_name) == 0)
X			continue;
X		if (nentries == nalloc) {
X			ourarray = (char **) realloc((char *) ourarray, (nalloc += 10) * sizeof (char *));
X			if (ourarray == 0)
X				goto memfail;
X		}
X		ourarray[nentries] = (char *) malloc(DIRSIZE(entry) + 1);
X		null_ncpy(ourarray[nentries], entry->d_name, (int) DIRSIZE(entry));
X		nentries++;
X	}
X	closedir(dirp);
X	if ((nentries + 1) != nalloc)
X		ourarray = (char **) realloc((char *) ourarray,
X					((nentries + 1) * sizeof (char *)));
X	if (sorter != 0)
X		qsort((char *) ourarray, nentries, sizeof (char **), sorter);
X	*nmptr = ourarray;
X	ourarray[nentries] = 0;		/* guaranteed 0 pointer */
X
X	return nentries;
X}
X
Xfreedir(nmptr, nentries)
Xchar	***nmptr;
X{
X	char	**ourarray = *nmptr;
X
X	while (--nentries >= 0)
X		free(*ourarray++);
X	free((char *) *nmptr);
X	*nmptr = 0;
X}
X
Xalphacomp(a, b)
Xchar	**a,
X	**b;
X{
X	return strcmp(*a, *b);
X}
X
X#endif
@//E*O*F scandir.c//
if test 2708 -ne "`wc -c <'scandir.c'`"; then
    echo shar: error transmitting "'scandir.c'" '(should have been 2708 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'screen.c'" '(17553 characters)'
if test -f 'screen.c' ; then 
  echo shar: will not over-write existing file "'screen.c'"
else
sed 's/^X//' >screen.c <<'@//E*O*F screen.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
X#include "jove.h"
X#include "io.h"
X#include "ctype.h"
X#include "termcap.h"
X
Xextern int	BufSize;
X
Xint	OkayAbort,
X	tabstop = 8;
X
Xint	(*TTins_line)(),
X	(*TTdel_line)();
X
Xstruct scrimage
X	*DesiredScreen = 0,
X	*PhysScreen = 0;
X
Xstruct screenline	*Screen = 0,	/* the screen (a bunch of screenline) */
X			*Savelines = 0,	/* another bunch (LI of them) */
X			*Curline = 0;	/* current line */
Xchar	*cursor,			/* offset into current Line */
X	*cursend;
X
Xint	CapCol,
X	CapLine,
X
X	i_line,
X	i_col;
X
Xmake_scr()
X{
X	register int	i;
X	register struct screenline	*ns;
X	register char	*nsp;
X
X#ifdef RESHAPING
X	/* In case we are RESHAPING the window! */
X	if (DesiredScreen)
X		free((char *) DesiredScreen);
X	if (PhysScreen)
X		free((char *) PhysScreen);
X	if (Savelines)
X		free((char *) Savelines);
X	if (Screen) {
X		free(Screen->s_line);	/* free all the screen data */
X		free((char *) Screen);
X	}
X#endif RESHAPING
X
X	DesiredScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
X	PhysScreen = (struct scrimage *) malloc((unsigned) LI * sizeof (struct scrimage));
X
X	Savelines = (struct screenline *)
X			malloc((unsigned) LI * sizeof(struct screenline));
X	ns = Screen = (struct screenline *)
X			malloc((unsigned) LI * sizeof(struct screenline));
X
X	nsp = (char *) malloc((unsigned)CO * LI);
X	if (nsp == 0) {
X		printf("\n\rCannot malloc screen!\n");
X		finish(1);
X	}
X
X	for (i = 0; i < LI; i++) {
X		ns->s_line = nsp;
X		nsp += CO;
X		ns->s_length = nsp - 1;		/* End of Line */
X		ns++;
X	}
X	cl_scr(0);
X}
X
Xclrline(cp1, cp2)
Xregister char	*cp1,
X		*cp2;
X{
X	while (cp1 <= cp2)
X		*cp1++ = ' ';
X}
X
X#define sputc(c)	((*cursor != (char) (c)) ? dosputc(c) : (cursor++, i_col++))
X#define soutputc(c)	if (--n <= 0) break; else sputc(c)
X
Xcl_eol()
X{
X	if (cursor > cursend)
X		return;
X
X	if (cursor < Curline->s_length) {
X		if (CE) {
X			Placur(i_line, i_col);
X			putpad(CE, 1);
X			clrline(cursor, Curline->s_length);
X		} else {
X		/* Ugh.  The slow way for dumb terminals. */
X			register char *savecp = cursor;
X
X			while (cursor <= Curline->s_length)
X				sputc(' ');
X			cursor = savecp;
X		}
X		Curline->s_length = cursor;
X	}
X}
X
Xcl_scr(doit)
X{
X	register int	i;
X	register struct screenline	*sp = Screen;
X
X	for (i = 0; i < LI; i++, sp++) {
X		clrline(sp->s_line, sp->s_length);
X		sp->s_length = sp->s_line;
X		PhysScreen[i].s_id = 0;
X	}
X	if (doit) {
X		putpad(CL, LI);
X		CapCol = CapLine = 0;
X		UpdMesg++;
X	}
X}
X
X#ifdef ID_CHAR
Xextern int	IN_INSmode;
X#endif
X
X/* Output one character (if necessary) at the current position */
X
Xdosputc(c)
Xregister char	c;
X{
X	if (*cursor != c) {
X#ifdef ID_CHAR
X		if (IN_INSmode)
X			INSmode(0);
X#endif
X		if (i_line != CapLine || i_col != CapCol)
X			Placur(i_line, i_col);
X		if (UL && (c & 0177) == '_' && (*cursor & 0177) != ' ')
X			putstr(" \b");		/* Erase so '_' looks right. */
X		*cursor++ = c;
X		putchar(c & 0177);
X		CapCol++;
X		i_col++;
X	} else {
X		cursor++;
X		i_col++;
X	}
X}
X
X/* Write `line' at the current position of `cursor'.  Stop when we
X   reach the end of the screen.  Aborts if there is a character
X   waiting.  */
X
Xswrite(line, inversep, abortable)
Xregister char	*line;
Xregister int	abortable;
X{
X	register int	c;
X	int	col = i_col,
X		aborted = 0;
X	register int	n = cursend - cursor;
X	int	or_byte = inversep ? 0200 : 0,
X		thebyte;
X
X	if (n <= 0)
X		return 1;
X
X	OkayAbort = 0;
X	while (c = *line++) {
X		if (abortable && OkayAbort) {
X			OkayAbort = NO;
X			if (InputPending = charp()) {
X				aborted = 1;
X				break;
X			}
X		}
X		if (c == '\t') {
X			int	nchars;
X
X			nchars = (tabstop - (col % tabstop));
X			col += nchars;
X
X			thebyte = (' ' | or_byte);
X			while (nchars--)
X				soutputc(thebyte);
X			if (n <= 0)
X				break;
X		} else if (isctrl(c)) {
X			thebyte = ('^' | or_byte);
X			soutputc(thebyte);
X			thebyte = (((c == '\177') ? '?' : c + '@') | or_byte);
X			soutputc(thebyte);
X			col += 2;
X		} else {
X			thebyte = (c | or_byte);
X			soutputc(thebyte);
X			col++;
X		}
X	}
X	if (n <= 0) {
X		if ((*line == '\0') && (c != '\t') && !isctrl(c))
X			sputc(c|or_byte);
X		else
X			sputc('!'|or_byte);
X	}
X	if (cursor > Curline->s_length)
X		Curline->s_length = cursor;
X	return !aborted;
X}
X
X/* This is for writing a buffer line to the screen.  This is to
X   minimize the amount of copying from one buffer to another buffer.
X   This gets the info directly from the disk buffers. */
X
XBufSwrite(linenum)
X{
X	char	*bp;
X	register int	n = cursend - cursor,
X			col = 0,
X			c;
X	int	StartCol = DesiredScreen[linenum].s_offset,
X		visspace = DesiredScreen[linenum].s_window->w_flags & W_VISSPACE,
X		aborted = 0;
X
X	bp = lcontents(DesiredScreen[linenum].s_lp);
X	if (*bp) for (;;) {
X		if (col >= StartCol) {
X			DesiredScreen[linenum].s_offset = col;
X			break;
X		}
X
X		c = *bp++ & 0177;
X		if (c == '\t')
X			col += (tabstop - (col % tabstop));
X		else if (isctrl(c))
X			col += 2;
X		else
X			col++;
X	}
X
X	OkayAbort = 0;
X	while (c = (*bp++ & 0177)) {
X		if (OkayAbort) {
X			OkayAbort = NO;
X			if (InputPending = charp()) {
X				aborted = 1;
X				break;
X			}
X		}
X		if (c == '\t') {
X			int	nchars = (tabstop - (col % tabstop));
X
X			col += nchars;
X			if (visspace) {
X				soutputc('>');
X				nchars--;
X			}
X			while (--nchars >= 0)
X				soutputc(' ');
X			if (n <= 0)
X				break;
X		} else if (isctrl(c)) {
X			soutputc('^');
X			soutputc((c == '\177') ? '?' : c + '@');
X			col += 2;
X		} else {
X			if (c == ' ' && visspace)
X				c = '_';
X			soutputc(c);
X			col++;
X		}
X	}
X	if (n <= 0) {
X		if ((*bp == '\0') && (c != '\t') && !isctrl(c))
X			sputc(c);
X		else
X			sputc('!');
X	}
X	if (cursor > Curline->s_length)
X		Curline->s_length = cursor;
X	return !aborted;		/* Didn't abort */
X}
X
Xi_set(nline, ncol)
Xregister int	nline,
X		ncol;
X{
X	Curline = &Screen[nline];
X	cursor = Curline->s_line + ncol;
X	cursend = &Curline->s_line[CO - 1];
X	i_line = nline;
X	i_col = ncol;
X}
X
X/* Insert `num' lines a top, but leave all the lines BELOW `bottom'
X   alone (at least they won't look any different when we are done).
X   This changes the screen array AND does the physical changes. */
X
Xv_ins_line(num, top, bottom)
X{
X	register int	i;
X
X	/* Save the screen pointers. */
X
X	for(i = 0; i < num && top + i <= bottom; i++)
X		Savelines[i] = Screen[bottom - i];
X
X	/* Num number of bottom lines will be lost.
X	   Copy everything down num number of times. */
X
X	for (i = bottom; i > top && i-num >= 0; i--)
X		Screen[i] = Screen[i - num];
X
X	/* Restore the saved ones, making them blank. */
X
X	for (i = 0; i < num; i++) {
X		Screen[top + i] = Savelines[i];
X		clrline(Screen[top + i].s_line, Screen[top + i].s_length);
X		Screen[top + i].s_length = Screen[top + i].s_line;
X	}
X
X	(*TTins_line)(top, bottom, num);
X}
X
X/* Delete `num' lines starting at `top' leaving the lines below `bottom'
X   alone.  This updates the internal image as well as the physical image.  */
X
Xv_del_line(num, top, bottom)
X{
X	register int	i,
X			bot;
X
X	bot = bottom;
X
X	/* Save the lost lines. */
X
X	for (i = 0; i < num && top + i <= bottom; i++)
X		Savelines[i] = Screen[top + i];
X
X	/* Copy everything up num number of lines. */
X
X	for (i = top; num + i <= bottom; i++)
X		Screen[i] = Screen[i + num];
X
X	/* Restore the lost ones, clearing them. */
X
X	for (i = 0; i < num; i++) {
X		Screen[bottom - i] = Savelines[i];
X		clrline(Screen[bot].s_line, Screen[bot].s_length);
X		Screen[bot].s_length = Screen[bot].s_line;
X		bot--;
X	}
X
X	(*TTdel_line)(top, bottom, num);
X}
X
X
X/* The cursor optimization happens here.  You may decide that this
X   is going too far with cursor optimization, or perhaps it should
X   limit the amount of checking to when the output speed is slow.
X   What ever turns you on ...   */
X
Xprivate struct cursaddr {
X	int	c_numchars,
X		(*c_proc)();
X};
X
Xprivate char	*Cmstr;
Xprivate struct cursaddr	*HorMin,
X			*VertMin,
X			*DirectMin;
X
Xprivate ForMotion(),
X	ForTab(),
X	BackMotion(),
X	RetTab(),
X	DownMotion(),
X	UpMotion(),
X	GoDirect(),
X	HomeGo(),
X	BottomUp();
X	
X
Xprivate struct cursaddr	WarpHor[] = {
X	0,	ForMotion,
X	0,	ForTab,
X	0,	BackMotion,
X	0,	RetTab
X};
X
Xprivate struct cursaddr	WarpVert[] = {
X	0,	DownMotion,
X	0,	UpMotion
X};
X
Xprivate struct cursaddr	WarpDirect[] = {
X	0,	GoDirect,
X	0,	HomeGo,
X	0,	BottomUp
X};
X
X#undef	FORWARD
X#define	FORWARD		0	/* Move forward */
X#define FORTAB		1	/* Forward using tabs */
X#undef	BACKWARD
X#define	BACKWARD	2	/* Move backward */
X#define RETFORWARD	3	/* Beginning of line and then tabs */
X#define NUMHOR		4
X
X#define DOWN		0	/* Move down */
X#define UPMOVE		1	/* Move up */
X#define NUMVERT		2
X
X#define DIRECT		0	/* Using CM */
X#define HOME		1	/* HOME	*/
X#define LOWER		2	/* Lower Line */
X#define NUMDIRECT	3
X
X#define	home()		Placur(0, 0)
X#define LowLine()	putpad(LL, 1), CapLine = ILI, CapCol = 0
X#define PrintHo()	putpad(HO, 1), CapLine = CapCol = 0
X
Xint	phystab = 8;
X
Xprivate
XGoDirect(line, col)
Xregister int	line,
X		col;
X{
X	putpad(Cmstr, 1);
X	CapLine = line;
X	CapCol = col;
X}
X
Xprivate
XRetTab(col)
Xregister int	col;
X{
X	putchar('\r');
X	CapCol = 0;
X	ForTab(col);
X}
X
Xprivate
XHomeGo(line, col)
X{
X	PrintHo();
X	DownMotion(line);
X	ForTab(col);
X}
X
Xprivate
XBottomUp(line, col)
Xregister int	line,
X		col;
X{
X	LowLine();
X	UpMotion(line);
X	ForTab(col);
X}
X
X/* Tries to move forward using tabs (if possible).  It tabs to the
X   closest tabstop which means it may go past 'destcol' and backspace
X   to it. */
X
Xprivate
XForTab(destcol)
Xint	destcol;
X{
X	register int	tabgoal,
X			ntabs,
X			tabstp = phystab;
X
X	if (TABS && (tabstp > 0)) {
X		tabgoal = destcol + (tabstp / 2);
X		tabgoal -= (tabgoal % tabstp);
X
X		/* Don't tab to last place or else it is likely to screw up. */
X		if (tabgoal >= CO)
X			tabgoal -= tabstp;
X
X		ntabs = (tabgoal / tabstp) - (CapCol / tabstp);
X		while (--ntabs >= 0)
X			putchar('\t');
X		CapCol = tabgoal;
X	}
X	if (CapCol > destcol)
X		BackMotion(destcol);
X	else if (CapCol < destcol)
X		ForMotion(destcol);
X}
X
Xprivate
XForMotion(destcol)
Xregister int	destcol;
X{
X	register int	nchars = destcol - CapCol;
X	register char	*cp = &Screen[CapLine].s_line[CapCol];
X
X	while (--nchars >= 0)
X		putchar(*cp++ & 0177);
X	CapCol = destcol;
X}
X
Xprivate
XBackMotion(destcol)
Xregister int	destcol;
X{
X	register int	nchars = CapCol - destcol;
X
X	if (BC)
X		while (--nchars >= 0)
X			putpad(BC, 1);
X	else
X		while (--nchars >= 0)
X			putchar('\b');
X	CapCol = destcol;
X}
X
Xprivate
XDownMotion(destline)
Xregister int	destline;
X{
X	register int	nlines = destline - CapLine;
X
X	while (--nlines >= 0)
X		putchar('\n');
X	CapLine = destline;
X}
X
Xprivate
XUpMotion(destline)
Xregister int	destline;
X{
X	register int	nchars = CapLine - destline;
X
X	while (--nchars >= 0)
X		putpad(UP, 1);
X	CapLine = destline;
X}
X
X#ifdef ID_CHAR
Xstatic int	EIlen;
X#endif
Xextern int	IMlen;
X
XInitCM()
X{
X	HOlen = HO ? strlen(HO) : 1000;
X	LLlen = LL ? strlen(LL) : 1000;
X	UPlen = UP ? strlen(UP) : 1000;
X#ifdef ID_CHAR
X	if (EI)
X		EIlen = strlen(EI);
X#endif
X}
X
XPlacur(line, col)
X{
X	int	dline,		/* Number of lines to move */
X		dcol;		/* Number of columns to move */
X	register int	best,
X			i;
X	register struct cursaddr	*cp;
X	int	xtracost = 0;	/* Misc addition to cost. */
X
X#define CursMin(which,addrs,max) \
X	for (best = 0, cp = &addrs[1], i = 1; i < max; i++, cp++) \
X		if (cp->c_numchars < addrs[best].c_numchars) \
X			best = i; \
X	which = &addrs[best];
X
X	if (line == CapLine && col == CapCol)
X		return;		/* We are already there. */
X
X	dline = line - CapLine;
X	dcol = col - CapCol;
X#ifdef ID_CHAR
X	if (IN_INSmode && MI)
X		xtracost = EIlen + IMlen;
X	/* If we're already in insert mode, it is likely that we will
X	   want to be in insert mode again, after the insert. */
X#endif
X
X	/* Number of characters to move horizontally for each case.
X	   1: Just move forward by typing the right character on the screen.
X	   2: Print the correct number of back spaces.
X	   3: Try tabbing to the correct place.
X	   4: Try going to the beginning of the line, and then tab. */
X
X	if (dcol == 1 || dcol == 0) {		/* Most common case. */
X		HorMin = &WarpHor[FORWARD];
X		HorMin->c_numchars = dcol + xtracost;
X	} else {
X		WarpHor[FORWARD].c_numchars = dcol >= 0 ? dcol + xtracost : 1000;
X		WarpHor[BACKWARD].c_numchars = dcol < 0 ? -(dcol + xtracost) : 1000;
X		WarpHor[FORTAB].c_numchars = dcol >= 0 && TABS ?
X				ForNum(CapCol, col) + xtracost : 1000;
X		WarpHor[RETFORWARD].c_numchars = (xtracost + 1 + (TABS ? ForNum(0, col) : col));
X
X		/* Which is the shortest of the bunch */
X
X		CursMin(HorMin, WarpHor, NUMHOR);
X	}
X
X	/* Moving vertically is more simple. */
X
X	WarpVert[DOWN].c_numchars = dline >= 0 ? dline : 1000;
X	WarpVert[UPMOVE].c_numchars = dline < 0 ? ((-dline) * UPlen) : 1000;
X
X	/* Which of these is simpler */
X	CursMin(VertMin, WarpVert, NUMVERT);
X
X	/* Homing first and lowering first are considered 
X	   direct motions.
X	   Homing first's total is the sum of the cost of homing
X	   and the sum of tabbing (if possible) to the right. */
X	
X	if (VertMin->c_numchars + HorMin->c_numchars <= 3) {
X		DirectMin = &WarpDirect[DIRECT];	/* A dummy ... */
X		DirectMin->c_numchars = 100;
X	} else {
X		WarpDirect[DIRECT].c_numchars = CM ?
X				strlen(Cmstr = tgoto(CM, col, line)) : 1000;
X		WarpDirect[HOME].c_numchars = HOlen + line +
X				WarpHor[RETFORWARD].c_numchars;
X		WarpDirect[LOWER].c_numchars = LLlen + ((ILI - line) * UPlen) +
X				WarpHor[RETFORWARD].c_numchars;
X		CursMin(DirectMin, WarpDirect, NUMDIRECT);
X	}
X
X	if (HorMin->c_numchars + VertMin->c_numchars < DirectMin->c_numchars) {
X		if (line != CapLine)
X			(*VertMin->c_proc)(line);
X		if (col != CapCol) {
X#ifdef ID_CHAR
X			if (IN_INSmode)	/* We may use real characters ... */
X				INSmode(0);
X#endif
X			(*HorMin->c_proc)(col);
X		}
X	} else {
X#ifdef ID_CHAR
X		if (IN_INSmode && !MI)
X			INSmode(0);
X#endif
X		(*DirectMin->c_proc)(line, col);
X	}
X}
X
X#define abs(x)	((x) >= 0 ? (x) : -(x))
X
XForNum(from, to)
Xregister int	from;
X{
X	register int	tabgoal,
X			tabstp = phystab;
X	int		numchars = 0;
X
X	if (from >= to)
X		return from - to;
X	if (TABS && (tabstp > 0)) {
X		tabgoal = to + (tabstp / 2);
X		tabgoal -= (tabgoal % tabstp);
X		if (tabgoal >= CO)
X			tabgoal -= tabstp;
X		numchars = (tabgoal / tabstop) - (from / tabstp);
X		from = tabgoal;
X	}
X	return numchars + abs(from - to);
X}
X
X#ifdef WIRED_TERMS
X
XBGi_lines(top, bottom, num)
X{
X	printf("\033[%d;%dr\033[%dL\033[r", top + 1, bottom + 1, num);
X	CapCol = CapLine = 0;
X}
X
XSUNi_lines(top, bottom, num)
X{
X	Placur(bottom - num + 1, 0);
X	printf("\033[%dM", num);
X	Placur(top, 0);
X	printf("\033[%dL", num);
X}
X
XC100i_lines(top, bottom, num)
X{
X	if (num <= 1) {
X		GENi_lines(top, bottom, num);
X		return;
X	}
X	printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
X	CapLine = CapCol = 0;
X	Placur(top, 0);
X	while (num--)
X		putpad(AL, ILI - CapLine);
X	printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
X	CapLine = CapCol = 0;
X}
X
X#endif WIRED_TERMS
X
XGENi_lines(top, bottom, num)
X{
X	register int	i;
X
X	if (CS) {
X		putpad(tgoto(CS, bottom, top));
X		CapCol = CapLine = 0;
X		Placur(top, 0);
X		for (i = 0; i < num; i++)
X			putpad(SR, bottom - top);
X		putpad(tgoto(CS, ILI, 0));
X		CapCol = CapLine = 0;
X	} else {
X		Placur(bottom - num + 1, 0);
X		if (M_DL && (num > 1)) {
X			char	minibuf[16];
X
X			sprintf(minibuf, M_DL, num);
X			putpad(minibuf, ILI - CapLine);
X		} else {
X			for (i = 0; i < num; i++)
X				putpad(DL, ILI - CapLine);
X		}
X		Placur(top, 0);
X		if (M_AL && (num > 1)) {
X			char	minibuf[16];
X
X			sprintf(minibuf, M_AL, num);
X			putpad(minibuf, ILI - CapLine);
X		} else {
X			for (i = 0; i < num; i++)
X				putpad(AL, ILI - CapLine);
X		}
X	}
X}
X
X#ifdef WIRED_TERMS
X
XBGd_lines(top, bottom, num)
X{
X	printf("\033[%d;%dr\033[%dM\033[r", top + 1, bottom + 1, num);
X	CapCol = CapLine = 0;
X}
X
XSUNd_lines(top, bottom, num)
X{
X	Placur(top, 0);
X	printf("\033[%dM", num);
X	Placur(bottom + 1 - num, 0);
X	printf("\033[%dL", num);
X}
X
XC100d_lines(top, bottom, num)
X{
X	if (num <= 1) {
X		GENd_lines(top, bottom, num);
X		return;
X	}
X	printf("\033v%c%c%c%c", ' ', ' ', ' ' + bottom + 1, ' ' + CO);
X	CapLine = CapCol = 0;
X	Placur(top, 0);
X	while (num--)
X		putpad(DL, ILI - CapLine);
X	printf("\033v%c%c%c%c", ' ', ' ', ' ' + LI, ' ' + CO);
X	CapLine = CapCol = 0;
X}
X
X#endif WIRED_TERMS
X
XGENd_lines(top, bottom, num)
X{
X	register int	i;
X
X	if (CS) {
X		putpad(tgoto(CS, bottom, top));
X		CapCol = CapLine = 0;
X		Placur(bottom, 0);
X		for (i = 0; i < num; i++)
X			putpad(SF, bottom - top);
X		putpad(tgoto(CS, ILI, 0));
X		CapCol = CapLine = 0;
X	} else {
X		Placur(top, 0);
X		if (M_DL && (num > 1)) {
X			char	minibuf[16];
X
X			sprintf(minibuf, M_DL, num);
X			putpad(minibuf, ILI - top);
X		} else {
X			for (i = 0; i < num; i++)
X				putpad(DL, ILI - top);
X		}
X		Placur(bottom + 1 - num, 0);
X		if (M_AL && (num > 1)) {
X			char	minibuf[16];
X
X			sprintf(minibuf, M_AL, num);
X			putpad(minibuf, ILI - CapLine);
X		} else {
X			for (i = 0; i < num; i++)
X				putpad(AL, ILI - CapLine);
X		}
X	}
X}
X
Xstruct ID_lookup {
X	char	*ID_name;
X	int	(*I_proc)();	/* proc to insert lines */
X	int	(*D_proc)();	/* proc to delete lines */
X} ID_trms[] = {
X	"generic",	GENi_lines,	GENd_lines,	/* This should stay here */
X#ifdef WIRED_TERMS
X	"sun",		SUNi_lines,	SUNd_lines,
X	"bg",		BGi_lines,	BGd_lines,
X	"c1",		C100i_lines,	C100d_lines,
X#endif WIRED_TERMS
X	0,		0,		0
X};
X
XIDline_setup(tname)
Xchar	*tname;
X{
X	register struct ID_lookup	*idp;
X
X	for (idp = &ID_trms[1]; idp->ID_name; idp++)
X		if (strncmp(idp->ID_name, tname, strlen(idp->ID_name)) == 0)
X			break;
X	if (idp->ID_name == 0)
X		idp = &ID_trms[0];
X	TTins_line = idp->I_proc;
X	TTdel_line = idp->D_proc;
X}
@//E*O*F screen.c//
if test 17553 -ne "`wc -c <'screen.c'`"; then
    echo shar: error transmitting "'screen.c'" '(should have been 17553 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'teachjove.c'" '(1052 characters)'
if test -f 'teachjove.c' ; then 
  echo shar: will not over-write existing file "'teachjove.c'"
else
sed 's/^X//' >teachjove.c <<'@//E*O*F teachjove.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
X#include <sys/types.h>
X#include <sys/file.h>
X
X#ifndef TEACHJOVE
X#    define TEACHJOVE	"/usr/lib/jove/teach-jove"
X#endif
X
X#ifndef W_OK
X#   define W_OK	2
X#   define F_OK	0
X#endif
X
Xextern char	*getenv();
X
Xmain()
X{
X	char	cmd[256],
X		fname[256],
X		*home;
X
X	if ((home = getenv("HOME")) == 0) {
X		printf("teachjove: cannot find your home!\n");
X		exit(-1);
X	}
X	(void) sprintf(fname, "%s/teach-jove", home);
X	if (access(fname, F_OK) != 0) {
X		(void) sprintf(cmd, "cp %s %s", TEACHJOVE, fname);
X		system(cmd);
X	}
X	(void) execlp("jove", "teachjove", fname, (char *) 0);
X	printf("teachjove: cannot execl jove!\n");
X}
X
@//E*O*F teachjove.c//
if test 1052 -ne "`wc -c <'teachjove.c'`"; then
    echo shar: error transmitting "'teachjove.c'" '(should have been 1052 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'tune.template'" '(882 characters)'
if test -f 'tune.template' ; then 
  echo shar: will not over-write existing file "'tune.template'"
else
sed 's/^X//' >tune.template <<'@//E*O*F tune.template//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
X#define NOEXTERNS
X
X#include "tune.h"
X
Xchar	TmpFilePath[128] = "TMPDIR";
X
Xchar	*d_tempfile = "joveXXXXXX",	/* buffer lines go here */
X	*p_tempfile = "jrecXXXXXX",	/* line pointers go here */
X	*Recover = "LIBDIR/recover",
X	*CmdDb = "LIBDIR/cmds.doc",
X		/* copy of "cmds.doc" lives in the doc subdirectory */
X
X	*Joverc = "LIBDIR/.joverc",
X
X#ifdef PIPEPROCS
X	*Portsrv = "LIBDIR/portsrv",
X#endif
X
X	Shell[128] = "SHELL",
X	ShFlags[16] = "-c";
@//E*O*F tune.template//
if test 882 -ne "`wc -c <'tune.template'`"; then
    echo shar: error transmitting "'tune.template'" '(should have been 882 characters)'
fi
fi # end of overwriting check
echo shar: extracting "'version.c'" '(473 characters)'
if test -f 'version.c' ; then 
  echo shar: will not over-write existing file "'version.c'"
else
sed 's/^X//' >version.c <<'@//E*O*F version.c//'
X/************************************************************************
X * This program is Copyright (C) 1986 by Jonathan Payne.  JOVE is       *
X * provided to you without charge, and with no warranty.  You may give  *
X * away copies of JOVE, including sources, provided that this notice is *
X * included in all the files.                                           *
X ************************************************************************/
X
Xchar	*version = "4.6.1.4";
@//E*O*F version.c//
if test 473 -ne "`wc -c <'version.c'`"; then
    echo shar: error transmitting "'version.c'" '(should have been 473 characters)'
fi
fi # end of overwriting check
echo shar: "End of archive 7 (of 13)."
cp /dev/null ark7isdone
DONE=true
for I in 1 2 3 4 5 6 7 8 9 10 11 12 13; do
    if test -f ark${I}isdone; then
        echo "You have run archive ${I}."
    else
        echo "You still need to run archive ${I}."
        DONE=false
    fi
done
case $DONE in
    true)
        echo "You have run all 13 archives."
        echo 'Now read the README and Makefile.'
        ;;
esac
##  End of shell archive.
exit 0



More information about the Mod.sources mailing list