ELvis 1.4, part 6 of 8

Steve Kirkendall kirkenda at eecs.cs.pdx.edu
Tue Dec 4 08:33:56 AEST 1990


# --------------------------- cut here ----------------------------
# This is a shar archive.  To unpack it, save it to a file, and delete
# anything above the "cut here" line.  Then run sh on the file.
#
# -rw-r--r--  1 kirkenda     9893 Dec  2 17:57 modify.c
# -rw-r--r--  1 kirkenda    10230 Dec  2 17:57 move1.c
# -rw-r--r--  1 kirkenda     4445 Dec  2 17:57 move2.c
# -rw-r--r--  1 kirkenda     2697 Dec  2 17:57 move3.c
# -rw-r--r--  1 kirkenda     3699 Dec  2 17:57 move4.c
# -rw-r--r--  1 kirkenda     3940 Dec  2 17:57 move5.c
# -rw-r--r--  1 kirkenda    14362 Dec  2 17:57 opts.c
# -rw-r--r--  1 kirkenda     2306 Dec  2 17:57 recycle.c
# -rw-r--r--  1 kirkenda    19816 Dec  2 17:57 redraw.c
#

if test -f modify.c -a "$1" != -f
then
echo Will not overwrite modify.c
else
echo Extracting modify.c
sed 's/^X//' >modify.c <<\eof
X/* modify.c */
X
X/* This file contains the low-level file modification functions:
X *	delete(frommark, tomark)	- removes line or portions of lines
X *	add(frommark, text)		- inserts new text
X *	change(frommark, tomark, text)	- delete, then add
X */
X
X#include "config.h"
X#include "vi.h"
X
X#ifdef DEBUG
X# include <stdio.h>
Xstatic FILE *dbg;
X
X/*VARARGS1*/
Xdebout(msg, arg1, arg2, arg3, arg4, arg5)
X	char	*msg, *arg1, *arg2, *arg3, *arg4, *arg5;
X{
X	if (!dbg)
X	{
X		dbg = fopen("debug.out", "w");
X		setbuf(dbg, (FILE *)0);
X	}
X	fprintf(dbg, msg, arg1, arg2, arg3, arg4, arg5);
X}
X#endif /* DEBUG */
X
X/* delete a range of text from the file */
Xvoid delete(frommark, tomark)
X	MARK		frommark;	/* first char to be deleted */
X	MARK		tomark;		/* AFTER last char to be deleted */
X{
X	int		i;		/* used to move thru logical blocks */
X	REG char	*scan;		/* used to scan thru text of the blk */
X	REG char	*cpy;		/* used when copying chars */
X	BLK		*blk;		/* a text block */
X	long		l;		/* a line number */
X	MARK		m;		/* a traveling version of frommark */
X
X#ifdef DEBUG
X	debout("delete(%ld.%d, %ld.%d)\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark));
X#endif
X
X	/* if not deleting anything, quit now */
X	if (frommark == tomark)
X	{
X		return;
X	}
X
X	/* This is a change */
X	changes++;
X	significant = TRUE;
X
X	/* if this is a multi-line change, then we'll have to redraw */
X	if (markline(frommark) != markline(tomark))
X	{
X		mustredraw = TRUE;
X		redrawrange(markline(frommark), markline(tomark), markline(frommark));
X	}
X
X	/* adjust marks 'a through 'z and '' as needed */
X	l = markline(tomark);
X	for (i = 0; i < NMARKS; i++)
X	{
X		if (mark[i] < frommark)
X		{
X			continue;
X		}
X		else if (mark[i] < tomark)
X		{
X			mark[i] = MARK_UNSET;
X		}
X		else if (markline(mark[i]) == l)
X		{
X			if (markline(frommark) == l)
X			{
X				mark[i] -= markidx(tomark) - markidx(frommark);
X			}
X			else
X			{
X				mark[i] -= markidx(tomark);
X			}
X		}
X		else
X		{
X			mark[i] -= MARK_AT_LINE(l - markline(frommark));
X		}
X	}
X
X	/* Reporting... */
X	if (markidx(frommark) == 0 && markidx(tomark) == 0)
X	{
X		rptlines = markline(tomark) - markline(frommark);
X		rptlabel = "deleted";
X	}
X
X	/* find the block containing frommark */
X	l = markline(frommark);
X	for (i = 1; lnum[i] < l; i++)
X	{
X	}
X
X	/* process each affected block... */
X	for (m = frommark;
X	     m < tomark && lnum[i] < INFINITY;
X	     m = MARK_AT_LINE(lnum[i - 1] + 1))
X	{
X		/* fetch the block */
X		blk = blkget(i);
X
X		/* find the mark in the block */
X		scan = blk->c;
X		for (l = markline(m) - lnum[i - 1] - 1; l > 0; l--)
X		{
X			while (*scan++ != '\n')
X			{
X			}
X		}
X		scan += markidx(m);
X
X		/* figure out where the changes to this block end */
X		if (markline(tomark) > lnum[i])
X		{
X			cpy = blk->c + BLKSIZE;
X		}
X		else if (markline(tomark) == markline(m))
X		{
X			cpy = scan - markidx(m) + markidx(tomark);
X		}
X		else
X		{
X			cpy = scan;
X			for (l = markline(tomark) - markline(m);
X			     l > 0;
X			     l--)
X			{
X				while (*cpy++ != '\n')
X				{
X				}
X			}
X			cpy += markidx(tomark);
X		}
X
X		/* delete the stuff by moving chars within this block */
X		while (cpy < blk->c + BLKSIZE)
X		{
X			*scan++ = *cpy++;
X		}
X		while (scan < blk->c + BLKSIZE)
X		{
X			*scan++ = '\0';
X		}
X
X		/* adjust tomark to allow for lines deleted from this block */
X		tomark -= MARK_AT_LINE(lnum[i] + 1 - markline(m));
X
X		/* if this block isn't empty now, then advance i */
X		if (*blk->c)
X		{
X			i++;
X		}
X
X		/* the buffer has changed.  Update hdr and lnum. */
X		blkdirty(blk);
X	}
X
X	/* must have at least 1 line */
X	if (nlines == 0)
X	{
X		blk = blkadd(1);
X		blk->c[0] = '\n';
X		blkdirty(blk);
X		cursor = MARK_FIRST;
X	}
X}
X
X
X/* add some text at a specific place in the file */
Xvoid add(atmark, newtext)
X	MARK		atmark;		/* where to insert the new text */
X	char		*newtext;	/* NUL-terminated string to insert */
X{
X	REG char	*scan;		/* used to move through string */
X	REG char	*build;		/* used while copying chars */
X	int		addlines;	/* number of lines we're adding */
X	int		lastpart;	/* size of last partial line */
X	BLK		*blk;		/* the block to be modified */
X	int		blkno;		/* the logical block# of (*blk) */
X	REG char	*newptr;	/* where new text starts in blk */
X	BLK		buf;		/* holds chars from orig blk */
X	BLK		linebuf;	/* holds part of line that didn't fit */
X	BLK		*following;	/* the BLK following the last BLK */
X	int		i;
X	long		l;
X
X#ifdef DEBUG
X	debout("add(%ld.%d, \"%s\")\n", markline(atmark), markidx(atmark), newtext);
X#endif
X#ifdef lint
X	buf.c[0] = 0;
X#endif
X	/* if not adding anything, return now */
X	if (!*newtext)
X	{
X		return;
X	}
X
X	/* This is a change */
X	changes++;
X	significant = TRUE;
X
X	/* count the number of lines in the new text */
X	for (scan = newtext, lastpart = addlines = 0; *scan; )
X	{
X		if (*scan++ == '\n')
X		{
X			addlines++;
X			lastpart = 0;
X		}
X		else
X		{
X			lastpart++;
X		}
X	}
X
X	/* Reporting... */
X	if (lastpart == 0 && markidx(atmark) == 0)
X	{
X		rptlines = addlines;
X		rptlabel = "added";
X	}
X
X	/* extract the line# from atmark */
X	l = markline(atmark);
X
X	/* if more than 0 lines, then we'll have to redraw the screen */
X	if (addlines > 0)
X	{
X		mustredraw = TRUE;
X		if (markidx(atmark) == 0 && lastpart == 0)
X		{
X			redrawrange(l, l, l + addlines);
X		}
X		else
X		{
X			/* make sure the last line gets redrawn -- it was
X			 * split, so its appearance has changed
X			 */
X			redrawrange(l, l + 1L, l + addlines + 1L);
X		}
X	}
X
X	/* adjust marks 'a through 'z and '' as needed */
X	for (i = 0; i < NMARKS; i++)
X	{
X		if (mark[i] < atmark)
X		{
X			/* earlier line, or earlier in same line: no change */
X			continue;
X		}
X		else if (markline(mark[i]) > l)
X		{
X			/* later line: move down a whole number of lines */
X			mark[i] += MARK_AT_LINE(addlines);
X		}
X		else
X		{
X			/* later in same line */
X			if (addlines > 0)
X			{
X				/* multi-line add, which split this line:
X				 * move down, and possibly left or right,
X				 * depending on where the split was and how
X				 * much text was inserted after the last \n
X				 */
X				mark[i] += MARK_AT_LINE(addlines) + lastpart - markidx(atmark);
X			}
X			else
X			{
X				/* totally within this line: move right */
X				mark[i] += lastpart;
X			}
X		}
X	}
X
X	/* get the block to be modified */
X	for (blkno = 1; lnum[blkno] < l && lnum[blkno + 1] < INFINITY; blkno++)
X	{
X	}
X	blk = blkget(blkno);
X	buf = *blk;
X
X	/* figure out where the new text starts */
X	for (newptr = buf.c, l = markline(atmark) - lnum[blkno - 1] - 1;
X	     l > 0;
X	     l--)
X	{
X		while (*newptr++ != '\n')
X		{
X		}
X	}
X	newptr += markidx(atmark);
X
X	/* keep start of old block */
X	build = blk->c + (newptr - buf.c);
X
X	/* fill this block (or blocks) from the newtext string */
X	while (*newtext)
X	{
X		while (*newtext && build < blk->c + BLKSIZE - 1)
X		{
X			*build++ = *newtext++;
X		}
X		if (*newtext)
X		{
X			/* save the excess */
X			for (scan = linebuf.c + BLKSIZE;
X			     build > blk->c && build[-1] != '\n';
X			     )
X			{
X				*--scan = *--build;
X			}
X
X			/* write the block */
X			while (build < blk->c + BLKSIZE)
X			{
X				*build++ = '\0';
X			}
X			blkdirty(blk);
X
X			/* add another block */
X			blkno++;
X			blk = blkadd(blkno);
X
X			/* copy in the excess from last time */
X			for (build = blk->c; scan < linebuf.c + BLKSIZE; )
X			{
X				*build++ = *scan++;
X			}
X		}
X	}
X
X	/* fill this block(s) from remainder of orig block */
X	while (newptr < buf.c + BLKSIZE && *newptr)
X	{
X		while (newptr < buf.c + BLKSIZE
X		    && *newptr
X		    && build < blk->c + BLKSIZE - 1)
X		{
X			*build++ = *newptr++;
X		}
X		if (newptr < buf.c + BLKSIZE && *newptr)
X		{
X			/* save the excess */
X			for (scan = linebuf.c + BLKSIZE;
X			     build > blk->c && build[-1] != '\n';
X			     )
X			{
X				*--scan = *--build;
X			}
X
X			/* write the block */
X			while (build < blk->c + BLKSIZE)
X			{
X				*build++ = '\0';
X			}
X			blkdirty(blk);
X
X			/* add another block */
X			blkno++;
X			blk = blkadd(blkno);
X
X			/* copy in the excess from last time */
X			for (build = blk->c; scan < linebuf.c + BLKSIZE; )
X			{
X				*build++ = *scan++;
X			}
X		}
X	}
X
X	/* see if we can combine our last block with the following block */
X	if (lnum[blkno] < nlines && lnum[blkno + 1] - lnum[blkno] < (BLKSIZE >> 6))
X	{
X		/* hey, we probably can!  Get the following block & see... */
X		following = blkget(blkno + 1);
X		if (strlen(following->c) + (build - blk->c) < BLKSIZE - 1)
X		{
X			/* we can!  Copy text from following to blk */
X			for (scan = following->c; *scan; )
X			{
X				*build++ = *scan++;
X			}
X			while (build < blk->c + BLKSIZE)
X			{
X				*build++ = '\0';
X			}
X			blkdirty(blk);
X
X			/* pretend the following was the last blk */
X			blk = following;
X			build = blk->c;
X		}
X	}
X
X	/* that last block is dirty by now */
X	while (build < blk->c + BLKSIZE)
X	{
X		*build++ = '\0';
X	}
X	blkdirty(blk);
X}
X
X
X/* change the text of a file */
Xvoid change(frommark, tomark, newtext)
X	MARK	frommark, tomark;
X	char	*newtext;
X{
X	int	i;
X	long	l;
X	char	*text;
X	BLK	*blk;
X
X#ifdef DEBUG
X	debout("change(%ld.%d, %ld.%d, \"%s\")\n", markline(frommark), markidx(frommark), markline(tomark), markidx(tomark), newtext);
X#endif
X
X	/* optimize for single-character replacement */
X	if (frommark + 1 == tomark && newtext[0] && !newtext[1] && newtext[0] != '\n')
X	{
X		/* find the block containing frommark */
X		l = markline(frommark);
X		for (i = 1; lnum[i] < l; i++)
X		{
X		}
X
X		/* get the block */
X		blk = blkget(i);
X
X		/* find the line within the block */
X		for (text = blk->c, i = l - lnum[i - 1] - 1; i > 0; text++)
X		{
X			if (*text == '\n')
X			{
X				i--;
X			}
X		}
X
X		/* replace the char */
X		text += markidx(frommark);
X		if (*text == newtext[0])
X		{
X			/* no change was needed - same char */
X			return;
X		}
X		else if (*text != '\n')
X		{
X			/* This is a change */
X			changes++;
X			significant = TRUE;
X			ChangeText
X			{
X				*text = newtext[0];
X				blkdirty(blk);
X			}
X			return;
X		}
X		/* else it is a complex change involving newline... */
X	}
X
X	/* couldn't optimize, so do delete & add */
X	ChangeText
X	{
X		delete(frommark, tomark);
X		add(frommark, newtext);
X		rptlabel = "changed";
X	}
X}
eof
if test `wc -c <modify.c` -ne 9893
then
echo modify.c damaged!
fi
fi

if test -f move1.c -a "$1" != -f
then
echo Will not overwrite move1.c
else
echo Extracting move1.c
sed 's/^X//' >move1.c <<\eof
X/* move1.c */
X
X/* Author:
X *	Steve Kirkendall
X *	14407 SW Teal Blvd. #C
X *	Beaverton, OR 97005
X *	kirkenda at cs.pdx.edu
X */
X
X
X/* This file contains most movement functions */
X
X#include "config.h"
X#include <ctype.h>
X#include "vi.h"
X
X#ifndef isascii
X# define isascii(c)	!((c) & ~0x7f)
X#endif
X
XMARK	m_updnto(m, cnt, cmd)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument */
X{
X	DEFAULT(cmd == 'G' ? nlines : 1L);
X
X	/* move up or down 'cnt' lines */
X	switch (cmd)
X	{
X	  case ('P'&0x1f):
X	  case '-':
X	  case 'k':
X		m -= MARK_AT_LINE(cnt);
X		break;
X
X	  case 'G':
X		if (cnt < 1L || cnt > nlines)
X		{
X			msg("Only %ld lines", nlines);
X			return MARK_UNSET;
X		}
X		m = MARK_AT_LINE(cnt);
X		break;
X
X	  default:
X		m += MARK_AT_LINE(cnt);
X	}
X
X	/* if that left us screwed up, then fail */
X	if (m < MARK_FIRST || markline(m) > nlines)
X	{
X		return MARK_UNSET;
X	}
X
X	return m;
X}
X
X/*ARGSUSED*/
XMARK	m_right(m, cnt)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument */
X{
X	int		idx;	/* index of the new cursor position */
X
X	DEFAULT(1);
X
X	/* move to right, if that's OK */
X	pfetch(markline(m));
X	idx = markidx(m) + cnt;
X	if (idx < plen)
X	{
X		m += cnt;
X	}
X	else
X	{
X		return MARK_UNSET;
X	}
X
X	return m;
X}
X
X/*ARGSUSED*/
XMARK	m_left(m, cnt)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument */
X{
X	DEFAULT(1);
X
X	/* move to the left, if that's OK */
X	if (markidx(m) >= cnt)
X	{
X		m -= cnt;
X	}
X	else
X	{
X		return MARK_UNSET;
X	}
X
X	return m;
X}
X
X/*ARGSUSED*/
XMARK	m_tocol(m, cnt)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument */
X{
X	char	*text;	/* text of the line */
X	int	col;	/* column number */
X	int	idx;	/* index into the line */
X
X	DEFAULT(1);
X
X	/* internally, columns are numbered 0..COLS-1, not 1..COLS */
X	cnt--;
X
X	/* if 0, that's easy */
X	if (cnt == 0)
X	{
X		m &= ~(BLKSIZE - 1);
X		return m;
X	}
X
X	/* find that column within the line */
X	pfetch(markline(m));
X	text = ptext;
X	for (col = idx = 0; col < cnt && *text; text++, idx++)
X	{
X		if (*text == '\t' && !*o_list)
X		{
X			col += *o_tabstop;
X			col -= col % *o_tabstop;
X		}
X		else if (UCHAR(*text) < ' ' || *text == '\177')
X		{
X			col += 2;
X		}
X#ifndef NO_CHARATTR
X		else if (text[0] == '\\' && text[1] == 'f' && text[2] && *o_charattr)
X		{
X			text += 2; /* plus one more as part of for loop */
X		}
X#endif
X		else
X		{
X			col++;
X		}
X	}
X	if (!*text)
X	{
X		return MARK_UNSET;
X	}
X	else
X	{
X		m = (m & ~(BLKSIZE - 1)) + idx;
X	}
X	return m;
X}
X
X/*ARGSUSED*/
XMARK	m_front(m, cnt)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument (ignored) */
X{
X	char	*scan;
X
X	/* move to the first non-whitespace character */
X	pfetch(markline(m));
X	scan = ptext;
X	m &= ~(BLKSIZE - 1);
X	while (*scan == ' ' || *scan == '\t')
X	{
X		scan++;
X		m++;
X	}
X
X	return m;
X}
X
X/*ARGSUSED*/
XMARK	m_rear(m, cnt)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument (ignored) */
X{
X	/* Try to move *EXTREMELY* far to the right.  It is fervently hoped
X	 * that other code will convert this to a more reasonable MARK before
X	 * anything tries to actually use it.  (See adjmove() in vi.c)
X	 */
X	return m | (BLKSIZE - 1);
X}
X
X#ifndef NO_SENTENCE
X/*ARGSUSED*/
XMARK	m_fsentence(m, cnt)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument */
X{
X	REG char	*text;
X	REG long	l;
X
X	DEFAULT(1);
X
X	/* get the current line */
X	l = markline(m);
X	pfetch(l);
X	text = ptext + markidx(m);
X
X	/* for each requested sentence... */
X	while (cnt-- > 0)
X	{
X		/* search forward for one of [.?!] followed by spaces or EOL */
X		do
X		{
X			/* wrap at end of line */
X			if (!text[0])
X			{
X				if (l >= nlines)
X				{
X					return MARK_UNSET;
X				}
X				l++;
X				pfetch(l);
X				text = ptext;
X			}
X			else
X			{
X				text++;
X			}
X		} while (text[0] != '.' && text[0] != '?' && text[0] != '!'
X			|| text[1] && (text[1] != ' ' || text[2] && text[2] != ' '));
X	}
X
X	/* construct a mark for this location */
X	m = buildmark(text);
X
X	/* move forward to the first word of the next sentence */
X	m = m_fword(m, 1L);
X
X	return m;
X}
X
X/*ARGSUSED*/
XMARK	m_bsentence(m, cnt)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument */
X{
X	REG char	*text;	/* used to scan thru text */
X	REG long	l;	/* current line number */
X	int		flag;	/* have we passed at least one word? */
X
X	DEFAULT(1);
X
X	/* get the current line */
X	l = markline(m);
X	pfetch(l);
X	text = ptext + markidx(m);
X
X	/* for each requested sentence... */
X	flag = TRUE;
X	while (cnt-- > 0)
X	{
X		/* search backward for one of [.?!] followed by spaces or EOL */
X		do
X		{
X			/* wrap at beginning of line */
X			if (text == ptext)
X			{
X				do
X				{
X					if (l <= 1)
X					{
X						return MARK_UNSET;
X					}
X					l--;
X					pfetch(l);
X				} while (!*ptext);
X				text = ptext + plen - 1;
X			}
X			else
X			{
X				text--;
X			}
X
X			/* are we moving past a "word"? */
X			if (text[0] >= '0')
X			{
X				flag = FALSE;
X			}
X		} while (flag || text[0] != '.' && text[0] != '?' && text[0] != '!'
X			|| text[1] && (text[1] != ' ' || text[2] && text[2] != ' '));
X	}
X
X	/* construct a mark for this location */
X	m = buildmark(text);
X
X	/* move to the front of the following sentence */
X	m = m_fword(m, 1L);
X
X	return m;
X}
X#endif
X
X/*ARGSUSED*/
XMARK	m_fparagraph(m, cnt)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument */
X{
X	char	*text;
X	char	*pscn;	/* used to scan thru value of "paragraphs" option */
X	long	l;
X
X	DEFAULT(1);
X
X	for (l = markline(m); cnt > 0 && l++ < nlines; )
X	{
X		text = fetchline(l);
X		if (!*text)
X		{
X			cnt--;
X		}
X#ifndef NO_SENTENCE
X		else if (*text == '.')
X		{
X			for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
X			{
X				if (pscn[0] == text[1] && pscn[1] == text[2])
X				{
X					cnt--;
X					break;
X				}
X			}
X		}
X#endif
X	}
X	if (l <= nlines)
X	{
X		m = MARK_AT_LINE(l);
X	}
X	else
X	{
X		m = MARK_LAST;
X	}
X	return m;
X}
X
X/*ARGSUSED*/
XMARK	m_bparagraph(m, cnt)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument */
X{
X	char	*text;
X	char	*pscn;	/* used to scan thru value of "paragraph" option */
X	long	l;
X
X	DEFAULT(1);
X
X	for (l = markline(m); cnt > 0 && l-- > 1; )
X	{
X		text = fetchline(l);
X		if (!*text)
X		{
X			cnt--;
X		}
X#ifndef NO_SENTENCE
X		else if (*text == '.')
X		{
X			for (pscn = o_paragraphs; pscn[0] && pscn[1]; pscn += 2)
X			{
X				if (pscn[0] == text[1] && pscn[1] == text[2])
X				{
X					cnt--;
X					break;
X				}
X			}
X		}
X#endif
X	}
X	if (l >= 1)
X	{
X		m = MARK_AT_LINE(l);
X	}
X	else
X	{
X		m = MARK_FIRST;
X	}
X	return m;
X}
X
X/*ARGSUSED*/
XMARK	m_fsection(m, cnt, key)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* (ignored) */
X	int	key;	/* second key stroke - must be ']' */
X{
X	char	*text;
X	char	*sscn;	/* used to scan thru value of "sections" option */
X	long	l;
X
X	/* make sure second key was ']' */
X	if (key != ']')
X	{
X		return MARK_UNSET;
X	}
X
X	for (l = markline(m); l++ < nlines; )
X	{
X		text = fetchline(l);
X		if (*text == '{')
X		{
X			break;
X		}
X#ifndef NO_SENTENCE
X		else if (*text == '.')
X		{
X			for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
X			{
X				if (sscn[0] == text[1] && sscn[1] == text[2])
X				{
X					goto BreakBreak;
X				}
X			}
X		}
X#endif
X	}
XBreakBreak:
X	if (l <= nlines)
X	{
X		m = MARK_AT_LINE(l);
X	}
X	else
X	{
X		m = MARK_LAST;
X	}
X	return m;
X}
X
X/*ARGSUSED*/
XMARK	m_bsection(m, cnt, key)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* (ignored) */
X	int	key;	/* second key stroke - must be '[' */
X{
X	char	*text;
X	char	*sscn;	/* used to scan thru value of "sections" option */
X	long	l;
X
X	/* make sure second key was '[' */
X	if (key != '[')
X	{
X		return MARK_UNSET;
X	}
X
X	for (l = markline(m); l-- > 1; )
X	{
X		text = fetchline(l);
X		if (*text == '{')
X		{
X			break;
X		}
X#ifndef NO_SENTENCE
X		else if (*text == '.')
X		{
X			for (sscn = o_sections; sscn[0] && sscn[1]; sscn += 2)
X			{
X				if (sscn[0] == text[1] && sscn[1] == text[2])
X				{
X					goto BreakBreak;
X				}
X			}
X		}
X#endif
X	}
XBreakBreak:
X	if (l >= 1)
X	{
X		m = MARK_AT_LINE(l);
X	}
X	else
X	{
X		m = MARK_FIRST;
X	}
X	return m;
X}
X
X
X/*ARGSUSED*/
XMARK	m_match(m, cnt)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument (ignored) */
X{
X	long	l;
X	REG char	*text;
X	REG char	match;
X	REG char	nest;
X	REG int		count;
X
X	/* get the current line */
X	l = markline(m);
X	pfetch(l);
X	text = ptext + markidx(m);
X
X	/* search forward within line for one of "[](){}" */
X	for (match = '\0'; !match && *text; text++)
X	{
X		/* tricky way to recognize 'em in ASCII */
X		nest = *text;
X		if ((nest & 0xdf) == ']' || (nest & 0xdf) == '[')
X		{
X			match = nest ^ ('[' ^ ']');
X		}
X		else if ((nest & 0xfe) == '(')
X		{
X			match = nest ^ ('(' ^ ')');
X		}
X		else
X		{
X			match = 0;
X		}
X	}
X	if (!match)
X	{
X		return MARK_UNSET;
X	}
X	text--;
X
X	/* search forward or backward for match */
X	if (match == '(' || match == '[' || match == '{')
X	{
X		/* search backward */
X		for (count = 1; count > 0; )
X		{
X			/* wrap at beginning of line */
X			if (text == ptext)
X			{
X				do
X				{
X					if (l <= 1L)
X					{
X						return MARK_UNSET;
X					}
X					l--;
X					pfetch(l);
X				} while (!*ptext);
X				text = ptext + plen - 1;
X			}
X			else
X			{
X				text--;
X			}
X
X			/* check the char */
X			if (*text == match)
X				count--;
X			else if (*text == nest)
X				count++;
X		}
X	}
X	else
X	{
X		/* search forward */
X		for (count = 1; count > 0; )
X		{
X			/* wrap at end of line */
X			if (!*text)
X			{
X				if (l >= nlines)
X				{
X					return MARK_UNSET;
X				}
X				l++;
X				pfetch(l);
X				text = ptext;
X			}
X			else
X			{
X				text++;
X			}
X
X			/* check the char */
X			if (*text == match)
X				count--;
X			else if (*text == nest)
X				count++;
X		}
X	}
X
X	/* construct a mark for this place */
X	m = buildmark(text);
X	return m;
X}
X
X/*ARGSUSED*/
XMARK	m_tomark(m, cnt, key)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* (ignored) */
X	int	key;	/* keystroke - the mark to move to */
X{
X	/* mark '' is a special case */
X	if (key == '\'' || key == '`')
X	{
X		if (mark[26] == MARK_UNSET)
X		{
X			return MARK_FIRST;
X		}
X		else
X		{
X			return mark[26];
X		}
X	}
X
X	/* if not a valid mark number, don't move */
X	if (key < 'a' || key > 'z')
X	{
X		return MARK_UNSET;
X	}
X
X	/* return the selected mark -- may be MARK_UNSET */
X	if (!mark[key - 'a'])
X	{
X		msg("mark '%c is unset", key);
X	}
X	return mark[key - 'a'];
X}
X
eof
if test `wc -c <move1.c` -ne 10230
then
echo move1.c damaged!
fi
fi

if test -f move2.c -a "$1" != -f
then
echo Will not overwrite move2.c
else
echo Extracting move2.c
sed 's/^X//' >move2.c <<\eof
X/* move2.c */
X
X/* Author:
X *	Steve Kirkendall
X *	14407 SW Teal Blvd. #C
X *	Beaverton, OR 97005
X *	kirkenda at cs.pdx.edu
X */
X
X
X/* This function contains the movement functions that perform RE searching */
X
X#include "config.h"
X#include "vi.h"
X#include "regexp.h"
X
Xextern long	atol();
X
Xstatic regexp	*re;	/* compiled version of the pattern to search for */
Xstatic		prevsf;	/* boolean: previous search direction was forward? */
X
XMARK	m_nsrch(m)
X	MARK	m;	/* where to start searching */
X{
X	if (prevsf)
X	{
X		m = m_fsrch(m, (char *)0);
X		prevsf = TRUE;
X	}
X	else
X	{
X		m = m_bsrch(m, (char *)0);
X		prevsf = FALSE;
X	}
X	return m;
X}
X
XMARK	m_Nsrch(m)
X	MARK	m;	/* where to start searching */
X{
X	if (prevsf)
X	{
X		m = m_bsrch(m, (char *)0);
X		prevsf = TRUE;
X	}
X	else
X	{
X		m = m_fsrch(m, (char *)0);
X		prevsf = FALSE;
X	}
X	return m;
X}
X
XMARK	m_fsrch(m, ptrn)
X	MARK	m;	/* where to start searching */
X	char	*ptrn;	/* pattern to search for */
X{
X	long	l;	/* line# of line to be searched */
X	char	*line;	/* text of line to be searched */
X	int	wrapped;/* boolean: has our search wrapped yet? */
X	int	pos;	/* where we are in the line */
X	long	delta;	/* line offset, for things like "/foo/+1" */
X
X	/* remember: "previous search was forward" */
X	prevsf = TRUE;
X
X	delta = 0L;
X	if (ptrn && *ptrn)
X	{
X		/* locate the closing '/', if any */
X		line = parseptrn(ptrn);
X		if (*line)
X		{
X			delta = atol(line);
X		}
X		ptrn++;
X
X		/* free the previous pattern */
X		if (re) free(re);
X
X		/* compile the pattern */
X		re = regcomp(ptrn);
X		if (!re)
X		{
X			return MARK_UNSET;
X		}
X	}
X	else if (!re)
X	{
X		msg("No previous expression");
X		return MARK_UNSET;
X	}
X
X	/* search forward for the pattern */
X	pos = markidx(m) + 1;
X	pfetch(markline(m));
X	if (pos >= plen)
X	{
X		pos = 0;
X		m = (m | (BLKSIZE - 1)) + 1;
X	}
X	wrapped = FALSE;
X	for (l = markline(m); l != markline(m) + 1 || !wrapped; l++)
X	{
X		/* wrap search */
X		if (l > nlines)
X		{
X			/* if we wrapped once already, then the search failed */
X			if (wrapped)
X			{
X				break;
X			}
X
X			/* else maybe we should wrap now? */
X			if (*o_wrapscan)
X			{
X				l = 0;
X				wrapped = TRUE;
X				continue;
X			}
X			else
X			{
X				break;
X			}
X		}
X
X		/* get this line */
X		line = fetchline(l);
X
X		/* check this line */
X		if (regexec(re, &line[pos], (pos == 0)))
X		{
X			/* match! */
X			if (wrapped && *o_warn)
X				msg("(wrapped)");
X			if (delta != 0L)
X			{
X				l += delta;
X				if (l < 1 || l > nlines)
X				{
X					msg("search offset too big");
X					return MARK_UNSET;
X				}
X				return m_front(MARK_AT_LINE(l), 0L);
X			}
X			return MARK_AT_LINE(l) + (int)(re->startp[0] - line);
X		}
X		pos = 0;
X	}
X
X	/* not found */
X	msg(*o_wrapscan ? "Not found" : "Hit bottom without finding RE");
X	return MARK_UNSET;
X}
X
XMARK	m_bsrch(m, ptrn)
X	MARK	m;	/* where to start searching */
X	char	*ptrn;	/* pattern to search for */
X{
X	long	l;	/* line# of line to be searched */
X	char	*line;	/* text of line to be searched */
X	int	wrapped;/* boolean: has our search wrapped yet? */
X	int	pos;	/* last acceptable idx for a match on this line */
X	int	last;	/* remembered idx of the last acceptable match on this line */
X	int	try;	/* an idx at which we strat searching for another match */
X
X	/* remember: "previous search was not forward" */
X	prevsf = FALSE;
X
X	if (ptrn && *ptrn)
X	{
X		/* locate the closing '?', if any */
X		line = parseptrn(ptrn);
X		ptrn++;
X
X		/* free the previous pattern, if any */
X		if (re) free(re);
X
X		/* compile the pattern */
X		re = regcomp(ptrn);
X		if (!re)
X		{
X			return MARK_UNSET;
X		}
X	}
X	else if (!re)
X	{
X		msg("No previous expression");
X		return MARK_UNSET;
X	}
X
X	/* search backward for the pattern */
X	pos = markidx(m);
X	wrapped = FALSE;
X	for (l = markline(m); l != markline(m) - 1 || !wrapped; l--)
X	{
X		/* wrap search */
X		if (l < 1)
X		{
X			if (*o_wrapscan)
X			{
X				l = nlines + 1;
X				wrapped = TRUE;
X				continue;
X			}
X			else
X			{
X				break;
X			}
X		}
X
X		/* get this line */
X		line = fetchline(l);
X
X		/* check this line */
X		if (regexec(re, line, 1) && (int)(re->startp[0] - line) < pos)
X		{
X			/* match!  now find the last acceptable one in this line */
X			do
X			{
X				last = (int)(re->startp[0] - line);
X				try = (int)(re->endp[0] - line);
X			} while (try > 0
X				 && regexec(re, &line[try], FALSE)
X				 && (int)(re->startp[0] - line) < pos);
X
X			if (wrapped && *o_warn)
X				msg("(wrapped)");
X			return MARK_AT_LINE(l) + last;
X		}
X		pos = BLKSIZE;
X	}
X
X	/* not found */
X	msg(*o_wrapscan ? "Not found" : "Hit top without finding RE");
X	return MARK_UNSET;
X}
X
eof
if test `wc -c <move2.c` -ne 4445
then
echo move2.c damaged!
fi
fi

if test -f move3.c -a "$1" != -f
then
echo Will not overwrite move3.c
else
echo Extracting move3.c
sed 's/^X//' >move3.c <<\eof
X/* move3.c */
X
X/* Author:
X *	Steve Kirkendall
X *	14407 SW Teal Blvd. #C
X *	Beaverton, OR 97005
X *	kirkenda at cs.pdx.edu
X */
X
X
X/* This file contains movement functions that perform character searches */
X
X#include "config.h"
X#include "vi.h"
X
X#ifndef NO_CHARSEARCH
Xstatic MARK	(*prevfwdfn)();	/* function to search in same direction */
Xstatic MARK	(*prevrevfn)();	/* function to search in opposite direction */
Xstatic char	prev_key;	/* sought cvhar from previous [fFtT] */
X
XMARK	m__ch(m, cnt, cmd)
X	MARK	m;	/* current position */
X	long	cnt;
X	char	cmd;	/* command: either ',' or ';' */
X{
X	MARK	(*tmp)();
X
X	if (!prevfwdfn)
X	{
X		msg("No previous f, F, t, or T command");
X		return MARK_UNSET;
X	}
X
X	if (cmd == ',')
X	{
X		m =  (*prevrevfn)(m, cnt, prev_key);
X
X		/* Oops! we didn't want to change the prev*fn vars! */
X		tmp = prevfwdfn;
X		prevfwdfn = prevrevfn;
X		prevrevfn = tmp;
X
X		return m;
X	}
X	else
X	{
X		return (*prevfwdfn)(m, cnt, prev_key);
X	}
X}
X
X/* move forward within this line to next occurrence of key */
XMARK	m_fch(m, cnt, key)
X	MARK	m;	/* where to search from */
X	long	cnt;
X	char	key;	/* what to search for */
X{
X	REG char	*text;
X
X	DEFAULT(1);
X
X	prevfwdfn = m_fch;
X	prevrevfn = m_Fch;
X	prev_key = key;
X
X	pfetch(markline(m));
X	text = ptext + markidx(m);
X	while (cnt-- > 0)
X	{
X		do
X		{
X			m++;
X			text++;
X		} while (*text && *text != key);
X	}
X	if (!*text)
X	{
X		return MARK_UNSET;
X	}
X	return m;
X}
X
X/* move backward within this line to previous occurrence of key */
XMARK	m_Fch(m, cnt, key)
X	MARK	m;	/* where to search from */
X	long	cnt;
X	char	key;	/* what to search for */
X{
X	REG char	*text;
X
X	DEFAULT(1);
X
X	prevfwdfn = m_Fch;
X	prevrevfn = m_fch;
X	prev_key = key;
X
X	pfetch(markline(m));
X	text = ptext + markidx(m);
X	while (cnt-- > 0)
X	{
X		do
X		{
X			m--;
X			text--;
X		} while (text >= ptext && *text != key);
X	}
X	if (text < ptext)
X	{
X		return MARK_UNSET;
X	}
X	return m;
X}
X
X/* move forward within this line almost to next occurrence of key */
XMARK	m_tch(m, cnt, key)
X	MARK	m;	/* where to search from */
X	long	cnt;
X	char	key;	/* what to search for */
X{
X	/* skip the adjacent char */
X	pfetch(markline(m));
X	if (plen <= markidx(m))
X	{
X		return MARK_UNSET;
X	}
X	m++;
X
X	m = m_fch(m, cnt, key);
X	if (m == MARK_UNSET)
X	{
X		return MARK_UNSET;
X	}
X
X	prevfwdfn = m_tch;
X	prevrevfn = m_Tch;
X
X	return m - 1;
X}
X
X/* move backward within this line almost to previous occurrence of key */
XMARK	m_Tch(m, cnt, key)
X	MARK	m;	/* where to search from */
X	long	cnt;
X	char	key;	/* what to search for */
X{
X	/* skip the adjacent char */
X	if (markidx(m) == 0)
X	{
X		return MARK_UNSET;
X	}
X	m--;
X
X	m = m_Fch(m, cnt, key);
X	if (m == MARK_UNSET)
X	{
X		return MARK_UNSET;
X	}
X
X	prevfwdfn = m_Tch;
X	prevrevfn = m_tch;
X
X	return m + 1;
X}
X#endif
eof
if test `wc -c <move3.c` -ne 2697
then
echo move3.c damaged!
fi
fi

if test -f move4.c -a "$1" != -f
then
echo Will not overwrite move4.c
else
echo Extracting move4.c
sed 's/^X//' >move4.c <<\eof
X/* move4.c */
X
X/* Author:
X *	Steve Kirkendall
X *	14407 SW Teal Blvd. #C
X *	Beaverton, OR 97005
X *	kirkenda at cs.pdx.edu
X */
X
X
X/* This file contains movement functions which are screen-relative */
X
X#include "config.h"
X#include "vi.h"
X
X/* This moves the cursor to a particular row on the screen */
X/*ARGSUSED*/
XMARK m_row(m, cnt, key)
X	MARK	m;	/* the cursor position */
X	long	cnt;	/* the row we'll move to */
X	int	key;	/* the keystroke of this move - H/L/M */
X{
X	DEFAULT(1);
X
X	/* calculate destination line based on key */
X	cnt--;
X	switch (key)
X	{
X	  case 'H':
X		cnt = topline + cnt;
X		break;
X
X	  case 'M':
X		cnt = topline + (LINES - 1) / 2;
X		break;
X
X	  case 'L':
X		cnt = botline - cnt;
X		break;
X	}
X
X	/* return the mark of the destination line */
X	return MARK_AT_LINE(cnt);
X}
X
X
X/* This function repositions the current line to show on a given row */
X/*ARGSUSED*/
XMARK m_z(m, cnt, key)
X	MARK	m;	/* the cursor */
X	long	cnt;	/* the line number we're repositioning */
X	int	key;	/* key struck after the z */
X{
X	long	newtop;
X
X	/* Which line are we talking about? */
X	if (cnt < 0 || cnt > nlines)
X	{
X		return MARK_UNSET;
X	}
X	if (cnt)
X	{
X		m = MARK_AT_LINE(cnt);
X		newtop = cnt;
X	}
X	else
X	{
X		newtop = markline(m);
X	}
X
X	/* allow a "window size" number to be entered, but ignore it */
X	while (key >= '0' && key <= '9')
X	{
X		key = getkey(0);
X	}
X
X	/* figure out which line will have to be at the top of the screen */
X	switch (key)
X	{
X	  case '\n':
X#if OSK
X	  case '\l':
X#else
X	  case '\r':
X#endif
X	  case '+':
X		break;
X
X	  case '.':
X	  case 'z':
X		newtop -= LINES / 2;
X		break;
X
X	  case '-':
X		newtop -= LINES - 1;
X		break;
X
X	  default:
X		return MARK_UNSET;
X	}
X
X	/* make the new topline take effect */
X	if (newtop >= 1)
X	{
X		topline = newtop;
X	}
X	else
X	{
X		topline = 1L;
X	}
X	mustredraw = TRUE;
X
X	/* The cursor doesn't move */
X	return m;
X}
X
X
X/* This function scrolls the screen.  It does this by calling redraw() with
X * an off-screen line as the argument.  It will move the cursor if necessary
X * so that the cursor is on the new screen.
X */
X/*ARGSUSED*/
XMARK m_scroll(m, cnt, key)
X	MARK	m;	/* the cursor position */
X	long	cnt;	/* for some keys: the number of lines to scroll */
X	int	key;	/* keystroke that causes this movement */
X{
X	MARK	tmp;	/* a temporary mark, used as arg to redraw() */
X
X	/* adjust cnt, and maybe *o_scroll, depending of key */
X	switch (key)
X	{
X	  case ctrl('F'):
X	  case ctrl('B'):
X		DEFAULT(1);
X		mustredraw = TRUE;
X		cnt = cnt * (LINES - 1) - 1; /* keeps one old line on screen */
X		break;
X
X	  case ctrl('E'):
X	  case ctrl('Y'):
X		DEFAULT(1);
X		break;
X
X	  case ctrl('U'):
X	  case ctrl('D'):
X		if (cnt == 0) /* default */
X		{
X			cnt = *o_scroll;
X		}
X		else
X		{
X			if (cnt > LINES - 1)
X			{
X				cnt = LINES - 1;
X			}
X			*o_scroll = cnt;
X		}
X		break;
X	}
X
X	/* scroll up or down, depending on key */
X	switch (key)
X	{
X	  case ctrl('B'):
X	  case ctrl('Y'):
X	  case ctrl('U'):
X		cnt = topline - cnt;
X		if (cnt < 1L)
X		{
X			cnt = 1L;
X			m = MARK_FIRST;
X		}
X		tmp = MARK_AT_LINE(cnt) + markidx(m);
X		redraw(tmp, FALSE);
X		if (markline(m) > botline)
X		{
X			m = MARK_AT_LINE(botline);
X		}
X		break;
X
X	  case ctrl('F'):
X	  case ctrl('E'):
X	  case ctrl('D'):
X		cnt = botline + cnt;
X		if (cnt > nlines)
X		{
X			cnt = nlines;
X			m = MARK_LAST;
X		}
X		tmp = MARK_AT_LINE(cnt) + markidx(m);
X		redraw(tmp, FALSE);
X		if (markline(m) < topline)
X		{
X			m = MARK_AT_LINE(topline);
X		}
X		break;
X	}
X
X	/* arrange for ctrl-B and ctrl-F to redraw the smart line */
X	if (key == ctrl('B') || key == ctrl('F'))
X	{
X		changes++;
X
X		/* also, erase the statusline.  This happens naturally for
X		 * the scrolling commands, but the paging commands need to
X		 * explicitly clear the statusline.
X		 */
X		msg("");
X	}
X
X	return m;
X}
eof
if test `wc -c <move4.c` -ne 3699
then
echo move4.c damaged!
fi
fi

if test -f move5.c -a "$1" != -f
then
echo Will not overwrite move5.c
else
echo Extracting move5.c
sed 's/^X//' >move5.c <<\eof
X/* move5.c */
X
X/* Author:
X *	Steve Kirkendall
X *	14407 SW Teal Blvd. #C
X *	Beaverton, OR 97005
X *	kirkenda at cs.pdx.edu
X */
X
X
X/* This file contains the word-oriented movement functions */
X
X#include <ctype.h>
X#include "config.h"
X#include "vi.h"
X
X#ifndef isascii
X# define isascii(c)	!((c) & ~0x7f)
X#endif
X
X
XMARK	m_fword(m, cnt, cmd)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument */
X	int	cmd;	/* either 'w' or 'W' */
X{
X	REG long	l;
X	REG char	*text;
X	REG int		i;
X
X	DEFAULT(1);
X
X	l = markline(m);
X	pfetch(l);
X	text = ptext + markidx(m);
X	while (cnt-- > 0) /* yes, ASSIGNMENT! */
X	{
X		i = *text++;
X
X		if (cmd == 'W')
X		{
X			/* include any non-whitespace */
X			while (i && (!isascii(i) || !isspace(i)))
X			{
X				i = *text++;
X			}
X		}
X		else if (!isascii(i) || isalnum(i) || i == '_')
X		{
X			/* include an alphanumeric word */
X			while (i && (!isascii(i) || isalnum(i) || i == '_'))
X			{
X				i = *text++;
X			}
X		}
X		else
X		{
X			/* include contiguous punctuation */
X			while (i && isascii(i) && !isalnum(i) && !isspace(i))
X			{
X				i = *text++;
X			}
X		}
X
X		/* include trailing whitespace */
X		while (!i || isascii(i) && isspace(i))
X		{
X			/* did we hit the end of this line? */
X			if (!i)
X			{
X				/* move to next line, if there is one */
X				l++;
X				if (l > nlines)
X				{
X					return MARK_UNSET;
X				}
X				pfetch(l);
X				text = ptext;
X			}
X
X			i = *text++;
X		}
X		text--;
X	}
X
X	/* construct a MARK for this place */
X	m = buildmark(text);
X	return m;
X}
X
X
XMARK	m_bword(m, cnt, cmd)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument */
X	int	cmd;	/* either 'b' or 'B' */
X{
X	REG long	l;
X	REG char	*text;
X
X	DEFAULT(1);
X
X	l = markline(m);
X	pfetch(l);
X	text = ptext + markidx(m);
X	while (cnt-- > 0) /* yes, ASSIGNMENT! */
X	{
X		text--;
X
X		/* include preceding whitespace */
X		while (text < ptext || isascii(*text) && isspace(*text))
X		{
X			/* did we hit the end of this line? */
X			if (text < ptext)
X			{
X				/* move to preceding line, if there is one */
X				l--;
X				if (l <= 0)
X				{
X					return MARK_UNSET;
X				}
X				pfetch(l);
X				text = ptext + plen - 1;
X			}
X			else
X			{
X				text--;
X			}
X		}
X
X		if (cmd == 'B')
X		{
X			/* include any non-whitespace */
X			while (text >= ptext && (!isascii(*text) || !isspace(*text)))
X			{
X				text--;
X			}
X		}
X		else if (!isascii(*text) || isalnum(*text) || *text == '_')
X		{
X			/* include an alphanumeric word */
X			while (text >= ptext && (!isascii(*text) || isalnum(*text) || *text == '_'))
X			{
X				text--;
X			}
X		}
X		else
X		{
X			/* include contiguous punctuation */
X			while (text >= ptext && isascii(*text) && !isalnum(*text) && !isspace(*text))
X			{
X				text--;
X			}
X		}
X		text++;
X	}
X
X	/* construct a MARK for this place */
X	m = buildmark(text);
X	return m;
X}
X
XMARK	m_eword(m, cnt, cmd)
X	MARK	m;	/* movement is relative to this mark */
X	long	cnt;	/* a numeric argument */
X	int	cmd;	/* either 'e' or 'E' */
X{
X	REG long	l;
X	REG char	*text;
X	REG int		i;
X
X	DEFAULT(1);
X
X	l = markline(m);
X	pfetch(l);
X	text = ptext + markidx(m);
X	while (cnt-- > 0) /* yes, ASSIGNMENT! */
X	{
X		text++;
X		i = *text++;
X
X		/* include preceding whitespace */
X		while (!i || isascii(i) && isspace(i))
X		{
X			/* did we hit the end of this line? */
X			if (!i)
X			{
X				/* move to next line, if there is one */
X				l++;
X				if (l > nlines)
X				{
X					return MARK_UNSET;
X				}
X				pfetch(l);
X				text = ptext;
X			}
X
X			i = *text++;
X		}
X
X		if (cmd == 'E')
X		{
X			/* include any non-whitespace */
X			while (i && (!isascii(i) || !isspace(i)))
X			{
X				i = *text++;
X			}
X		}
X		else if (!isascii(i) || isalnum(i) || i == '_')
X		{
X			/* include an alphanumeric word */
X			while (i && (!isascii(i) || isalnum(i) || i == '_'))
X			{
X				i = *text++;
X			}
X		}
X		else
X		{
X			/* include contiguous punctuation */
X			while (i && isascii(i) && !isalnum(i) && !isspace(i))
X			{
X				i = *text++;
X			}
X		}
X		text -= 2;
X	}
X
X	/* construct a MARK for this place */
X	m = buildmark(text);
X	return m;
X}
eof
if test `wc -c <move5.c` -ne 3940
then
echo move5.c damaged!
fi
fi

if test -f opts.c -a "$1" != -f
then
echo Will not overwrite opts.c
else
echo Extracting opts.c
sed 's/^X//' >opts.c <<\eof
X/* opts.c */
X
X/* Author:
X *	Steve Kirkendall
X *	14407 SW Teal Blvd. #C
X *	Beaverton, OR 97005
X *	kirkenda at cs.pdx.edu
X */
X
X
X/* This file contains the code that manages the run-time options -- The 
X * values that can be modified via the "set" command.
X */
X
X#include "config.h"
X#include "vi.h"
X#ifndef NULL
X#define NULL (char *)0
X#endif
Xextern char	*getenv();
X
X/* maximum width to permit for strings, including ="" */
X#define MAXWIDTH 20
X
X/* These are the default values of all options */
Xchar	o_autoindent[1] =	{FALSE};
Xchar	o_autoprint[1] =	{TRUE};
Xchar	o_autowrite[1] = 	{FALSE};
X#ifndef NO_ERRLIST
Xchar	o_cc[30] =		{CC_COMMAND};
X#endif
X#ifndef NO_CHARATTR
Xchar	o_charattr[1] =		{FALSE};
X#endif
Xchar	o_columns[3] =		{80, 32, 255};
X#ifndef NO_DIGRAPH
Xchar	o_digraph[1] =		{FALSE};
X#endif
Xchar	o_directory[30] =	TMPDIR;
Xchar	o_edcompatible[1] =	{FALSE};
Xchar	o_errorbells[1] =	{TRUE};
Xchar	o_exrefresh[1] =	{TRUE};
X#ifndef NO_DIGRAPH
Xchar	o_flipcase[80]
X# if CS_IBMPC
X	= {"\207\200\201\232\202\220\204\216\206\217\221\222\224\231\244\245"}
X# endif
X# if CS_LATIN1
X	/* initialized by initopts() */
X# endif
X	;
X#endif
X#ifndef NO_SENTENCE
Xchar	o_hideformat[1] =	{FALSE};
X#endif
Xchar	o_ignorecase[1] =	{FALSE};
X#ifndef NO_EXTENSIONS
Xchar	o_inputmode[1] =	{FALSE};
X#endif
Xchar	o_keytime[3] =		{2, 0, 5};
Xchar	o_keywordprg[80] =	{KEYWORDPRG};
Xchar	o_lines[3] =		{25, 2, 50};	/* More lines? Enlarge kbuf */
Xchar	o_list[1] =		{FALSE};
X#ifndef NO_MAGIC
Xchar	o_magic[1] =		{TRUE};
X#endif
X#ifndef NO_ERRLIST
Xchar	o_make[30] =		{MAKE_COMMAND};
X#endif
X#ifndef NO_MODELINE
Xchar	o_modeline[1] =		{FALSE};
X#endif
X#ifndef NO_SENTENCE
Xchar	o_paragraphs[30] =	"PPppIPLPQP";
X#endif
X#if MSDOS
Xchar	o_pcbios[1] =		{TRUE};
X#endif
Xchar	o_readonly[1] =		{FALSE};
Xchar	o_report[3] =		{5, 1, 127};
Xchar	o_scroll[3] =		{12, 1, 127};
X#ifndef NO_SENTENCE
Xchar	o_sections[30] =	"NHSHSSSEse";
X#endif
Xchar	o_shell[60] =		SHELL;
Xchar	o_shiftwidth[3] =	{8, 1, 255};
X#ifndef NO_SHOWMATCH
Xchar	o_showmatch[1] =	{FALSE};
X#endif
X#ifndef	NO_SHOWMODE
Xchar	o_smd[1] =		{FALSE};
X#endif
Xchar	o_sidescroll[3] =	{8, 1, 40};
Xchar	o_sync[1] =		{NEEDSYNC};
Xchar	o_tabstop[3] =		{8, 1, 40};
Xchar	o_term[30] =		"?";
Xchar	o_vbell[1] =		{TRUE};
Xchar	o_warn[1] =		{TRUE};
Xchar	o_wrapmargin[3] =	{0, 0, 255};
Xchar	o_wrapscan[1] =		{TRUE};
X
X
X/* The following describes the names & types of all options */
X#define BOOL	0
X#define	NUM	1
X#define	STR	2
X#define SET	0x01	/* this option has had its value altered */
X#define CANSET	0x02	/* this option can be set at any time */
X#define RCSET	0x06	/* this option can be set in a .exrc file only */
X#define MR	0x40	/* does this option affect the way text is displayed? */
Xstruct
X{
X	char	*name;	/* name of an option */
X	char	*nm;	/* short name of an option */
X	char	type;	/* type of an option */
X	char	flags;	/* boolean: has this option been set? */
X	char	*value;	/* value */
X}
X	opts[] =
X{
X	/* name			type	flags	redraw	value */
X	{ "autoindent",	"ai",	BOOL,	CANSET	,	o_autoindent	},
X	{ "autoprint",	"ap",	BOOL,	CANSET	,	o_autoprint	},
X	{ "autowrite",	"aw",	BOOL,	CANSET	,	o_autowrite	},
X#ifndef NO_ERRLIST
X	{ "cc",		"cc",	STR,	CANSET	,	o_cc		},
X#endif
X#ifndef NO_CHARATTR
X	{ "charattr",	"ca",	BOOL,	CANSET	| MR,	o_charattr	},
X#endif
X	{ "columns",	"co",	NUM,	SET	,	o_columns	},
X#ifndef NO_DIGRAPH
X	{ "digraph",	"dig",	BOOL,	CANSET	,	o_digraph	},
X#endif
X	{ "directory",	"dir",	STR,	RCSET	,	o_directory	},
X	{ "edcompatible","ed",	BOOL,	CANSET	,	o_edcompatible	},
X	{ "errorbells",	"eb",	BOOL,	CANSET	,	o_errorbells	},
X	{ "exrefresh",	"er",	BOOL,	CANSET	,	o_exrefresh	},
X#ifndef NO_DIGRAPH
X	{ "flipcase",	"fc",	STR,	CANSET	,	o_flipcase	},
X#endif
X#ifndef NO_SENTENCE
X	{ "hideformat",	"hf",	BOOL,	CANSET	| MR,	o_hideformat	},
X#endif
X	{ "ignorecase",	"ic",	BOOL,	CANSET	,	o_ignorecase	},
X#ifndef NO_EXTENSIONS
X	{ "inputmode",	"im",	BOOL,	CANSET	,	o_inputmode	},
X#endif
X	{ "keytime",	"kt",	NUM,	CANSET	,	o_keytime	},
X	{ "keywordprg",	"kp",	STR,	CANSET	,	o_keywordprg	},
X	{ "lines",	"ls",	NUM,	SET	,	o_lines		},
X	{ "list",	"li",	BOOL,	CANSET	| MR,	o_list		},
X#ifndef NO_MAGIC
X	{ "magic",	"ma",	BOOL,	CANSET	,	o_magic		},
X#endif
X#ifndef NO_ERRLIST
X	{ "make",	"mk",	STR,	CANSET	,	o_make		},
X#endif
X#ifndef NO_MODELINE
X	{ "modeline",	"ml",	BOOL,	CANSET	,	o_modeline	},
X#endif
X#ifndef NO_SENTENCE
X	{ "paragraphs",	"pa",	STR,	CANSET	,	o_paragraphs	},
X#endif
X#if MSDOS
X	{ "pcbios",	"pc",	BOOL,	SET	,	o_pcbios	},
X#endif
X	{ "readonly",	"ro",	BOOL,	CANSET	,	o_readonly	},
X	{ "report",	"re",	NUM,	CANSET	,	o_report	},
X	{ "scroll",	"sc",	NUM,	CANSET	,	o_scroll	},
X#ifndef NO_SENTENCE
X	{ "sections",	"se",	STR,	CANSET	,	o_sections	},
X#endif
X	{ "shell",	"sh",	STR,	CANSET	,	o_shell		},
X#ifndef NO_SHOWMATCH
X	{ "showmatch",	"sm",	BOOL,	CANSET	,	o_showmatch	},
X#endif
X#ifndef	NO_SHOWMODE
X	{ "showmode",	"smd",	BOOL,	CANSET	,	o_smd		},
X#endif
X	{ "shiftwidth",	"sw",	NUM,	CANSET	,	o_shiftwidth	},
X	{ "sidescroll",	"ss",	NUM,	CANSET	,	o_sidescroll	},
X	{ "sync",	"sy",	BOOL,	CANSET	,	o_sync		},
X	{ "tabstop",	"ts",	NUM,	CANSET	| MR,	o_tabstop	},
X	{ "term",	"te",	STR,	SET	,	o_term		},
X	{ "vbell",	"vb",	BOOL,	CANSET	,	o_vbell		},
X	{ "warn",	"wa",	BOOL,	CANSET	,	o_warn		},
X	{ "wrapmargin",	"wm",	NUM,	CANSET	,	o_wrapmargin	},
X	{ "wrapscan",	"ws",	BOOL,	CANSET	,	o_wrapscan	},
X	{ NULL, NULL, 0, CANSET, NULL }
X};
X
X
X/* This function initializes certain options from environment variables, etc. */
Xvoid initopts()
X{
X	char	*val;
X	int	i;
X
X	/* set some stuff from environment variables */
X#if MSDOS
X	if (val = getenv("COMSPEC")) /* yes, ASSIGNMENT! */
X#else
X	if (val = getenv("SHELL")) /* yes, ASSIGNMENT! */
X#endif
X	{
X		strcpy(o_shell, val);
X	}
X
X#if ANY_UNIX
X	if (val = getenv("TERM")) /* yes, ASSIGNMENT! */
X	{
X		strcpy(o_term, val);
X	}
X#endif
X#if TOS
X	val = "vt52";
X	strcpy(o_term, val);
X#endif
X#if MSDOS
X	if ((val = getenv("TERM")) /* yes, ASSIGNMENT! */
X		&& strcmp(val, "pcbios"))
X	{
X		strcpy(o_term, val);
X		o_pcbios[0] = 0;
X	}
X	else
X	{
X		strcpy(o_term, "pcbios");
X		o_pcbios[0] = 1;
X	}
X#endif
X#if MSDOS || TOS
X	if ((val = getenv("TMP")) /* yes, ASSIGNMENT! */
X	||  (val = getenv("TEMP")))
X		strcpy(o_directory, val);
X#endif
X
X	*o_scroll = LINES / 2 - 1;
X
X	/* disable the vbell option if we don't know how to do a vbell */
X	if (!has_VB)
X	{
X		for (i = 0; opts[i].value != o_vbell; i++)
X		{
X		}
X		opts[i].flags &= ~CANSET;
X		*o_vbell = FALSE;
X	}
X
X#ifndef NO_DIGRAPH
X# ifdef CS_LATIN1
X	for (i = 0, val = o_flipcase; i < 32; i++)
X	{
X		/* leave out the multiply/divide symbols */
X		if (i == 23)
X			continue;
X
X		/* add upper/lowercase pair */
X		*val++ = i + 0xc0;
X		*val++ = i + 0xe0;
X	}
X	*val = '\0';
X# endif /* CS_LATIN1 */
X#endif /* not NO_DIGRAPH */
X}
X
X/* This function lists the current values of all options */
Xvoid dumpopts(all)
X	int	all;	/* boolean: dump all options, or just set ones? */
X{
X#ifndef NO_OPTCOLS
X	int	i, j, k;
X	char	nbuf[4];	/* used for converting numbers to ASCII */
X	int	widths[5];	/* width of each column, including gap */
X	int	ncols;		/* number of columns */
X	int	nrows;		/* number of options per column */
X	int	nset;		/* number of options to be output */
X	int	width;		/* width of a particular option */
X	int	todump[50];	/* indicies of options to be dumped */
X
X	/* step 1: count the number of set options */
X	for (nset = i = 0; opts[i].name; i++)
X	{
X		if (all || (opts[i].flags & SET))
X		{
X			todump[nset++] = i;
X		}
X	}
X
X	/* step two: try to use as many columns as possible */
X	for (ncols = (nset > 5 ? 5 : nset); ncols > 1; ncols--)
X	{
X		/* how many would go in this column? */
X		nrows = (nset + ncols - 1) / ncols;
X
X		/* figure out the width of each column */
X		for (i = 0; i < ncols; i++)
X		{
X			widths[i] = 0;
X			for (j = 0, k = nrows * i; j < nrows && k < nset; j++, k++)
X			{
X				/* figure out the width of a particular option */
X				switch (opts[todump[k]].type)
X				{
X				  case BOOL:
X					if (!*opts[todump[k]].value)
X						width = 2;
X					else
X						width = 0;
X					break;
X
X				  case STR:
X					width = 3 + strlen(opts[todump[k]].value);
X					if (width > MAXWIDTH)
X						width = MAXWIDTH;
X					break;
X
X				  case NUM:
X					width = 4;
X					break;
X				}
X				width += strlen(opts[todump[k]].name);
X
X				/* if this is the widest so far, widen col */
X				if (width > widths[i])
X				{
X					widths[i] = width;
X				}
X			}
X
X		}
X
X		/* if the total width is narrow enough, then use it */
X		for (width = -2, i = 0; i < ncols; i++)
X		{
X			width += widths[i] + 2;
X		}
X		if (width < COLS - 1)
X		{
X			break;
X		}
X	}
X
X	/* step 3: output the columns */
X	nrows = (nset + ncols - 1) / ncols;
X	for (i = 0; i < nrows; i++)
X	{
X		for (j = 0; j < ncols; j++)
X		{
X			/* if we hit the end of the options, quit */
X			k = i + j * nrows;
X			if (k >= nset)
X			{
X				break;
X			}
X
X			/* output this option's value */
X			width = 0;
X			switch (opts[todump[k]].type)
X			{
X			  case BOOL:
X				if (!*opts[todump[k]].value)
X				{
X					qaddch('n');
X					qaddch('o');
X					width = 2;
X				}
X				qaddstr(opts[todump[k]].name);
X				width += strlen(opts[todump[k]].name);
X				break;
X
X			  case NUM:
X				sprintf(nbuf, "%-3d", UCHAR(*opts[todump[k]].value));
X				qaddstr(opts[todump[k]].name);
X				qaddch('=');
X				qaddstr(nbuf);
X				width = 4 + strlen(opts[todump[k]].name);
X				break;
X
X			  case STR:
X				qaddstr(opts[todump[k]].name);
X				qaddch('=');
X				qaddch('"');
X				strcpy(tmpblk.c, opts[todump[k]].value);
X				width = 3 + strlen(tmpblk.c);
X				if (width > MAXWIDTH)
X				{
X					width = MAXWIDTH;
X					strcpy(tmpblk.c + MAXWIDTH - 6, "...");
X				}
X				qaddstr(tmpblk.c);
X				qaddch('"');
X				width += strlen(opts[todump[k]].name);
X				break;
X			}
X
X			/* pad the field to the correct size */
X			if (k + nrows <= nset)
X			{
X				while (width < widths[j] + 2)
X				{
X					qaddch(' ');
X					width++;
X				}
X			}
X		}
X		addch('\n');
X		exrefresh();
X	}
X#else
X	int	i;
X	int	col;
X	char	nbuf[4];
X
X	for (i = col = 0; opts[i].name; i++)
X	{
X		/* if not set and not all, ignore this option */
X		if (!all && !(opts[i].flags & SET))
X		{
X			continue;
X		}
X
X		/* align this option in one of the columns */
X		if (col > 52)
X		{
X			addch('\n');
X			col = 0;
X		}
X		else if (col > 26)
X		{
X			while (col < 52)
X			{
X				qaddch(' ');
X				col++;
X			}
X		}
X		else if (col > 0)
X		{
X			while (col < 26)
X			{
X				qaddch(' ');
X				col++;
X			}
X		}
X
X		switch (opts[i].type)
X		{
X		  case BOOL:
X			if (!*opts[i].value)
X			{
X				qaddch('n');
X				qaddch('o');
X				col += 2;
X			}
X			qaddstr(opts[i].name);
X			col += strlen(opts[i].name);
X			break;
X
X		  case NUM:
X			sprintf(nbuf, "%-3d", UCHAR(*opts[i].value));
X			qaddstr(opts[i].name);
X			qaddch('=');
X			qaddstr(nbuf);
X			col += 4 + strlen(opts[i].name);
X			break;
X
X		  case STR:
X			qaddstr(opts[i].name);
X			qaddch('=');
X			qaddch('"');
X			qaddstr(opts[i].value);
X			qaddch('"');
X			col += 3 + strlen(opts[i].name) + strlen(opts[i].value);
X			break;
X		}
X		exrefresh();
X	}
X	if (col > 0)
X	{
X		addch('\n');
X		exrefresh();
X	}
X#endif
X}
X
X#ifndef NO_MKEXRC
X/* This function saves the current configuarion of options to a file */
Xvoid saveopts(fd)
X	int	fd;	/* file descriptor to write to */
X{
X	int	i;
X	char	buf[256], *pos;
X
X	/* write each set options */
X	for (i = 0; opts[i].name; i++)
X	{
X		/* if unset or unsettable, ignore this option */
X		if (!(opts[i].flags & SET) || !(opts[i].flags & CANSET))
X		{
X			continue;
X		}
X
X		strcpy(buf, "set ");
X		pos = &buf[4];
X		switch (opts[i].type)
X		{
X		  case BOOL:
X			if (!*opts[i].value)
X			{
X				*pos++='n';
X				*pos++='o';
X			}
X			strcpy(pos, opts[i].name);
X			strcat(pos, "\n");
X			break;
X
X		  case NUM:
X			sprintf(pos, "%s=%-3d\n", opts[i].name, *opts[i].value & 0xff);
X			break;
X
X		  case STR:
X			sprintf(pos, "%s=\"%s\"\n", opts[i].name, opts[i].value);
X			break;
X		}
X		twrite(fd, buf, strlen(buf));
X	}
X}
X#endif
X
X
X/* This function changes the values of one or more options. */
Xvoid setopts(assignments)
X	char	*assignments;	/* a string containing option assignments */
X{
X	char	*name;		/* name of variable in assignments */
X	char	*value;		/* value of the variable */
X	char	*scan;		/* used for moving through strings */
X	int	i, j;
X
X	/* for each assignment... */
X	for (name = assignments; *name; )
X	{
X		/* skip whitespace */
X		if (*name == ' ' || *name == '\t')
X		{
X			name++;
X			continue;
X		}
X
X		/* find the value, if any */
X		for (scan = name; *scan >= 'a' && *scan <= 'z'; scan++)
X		{
X		}
X		if (*scan == '=')
X		{
X			*scan++ = '\0';
X			if (*scan == '"')
X			{
X				value = ++scan;
X				while (*scan && *scan != '"')
X				{
X					scan++;
X				}
X				if (*scan)
X				{
X					*scan++ = '\0';
X				}
X			}
X			else
X			{
X				value = scan;
X				while (*scan && *scan != ' ' && *scan != '\t')
X				{
X					scan++;
X				}
X				if (*scan)
X				{
X					*scan++ = '\0';
X				}
X			}
X		}
X		else
X		{
X			if (*scan)
X			{
X				*scan++ = '\0';
X			}
X			value = NULL;
X			if (name[0] == 'n' && name[1] == 'o')
X			{
X				name += 2;
X			}
X		}
X
X		/* find the variable */
X		for (i = 0;
X		     opts[i].name && strcmp(opts[i].name, name) && strcmp(opts[i].nm, name);
X		     i++)
X		{
X		}
X
X		/* change the variable */
X		if (!opts[i].name)
X		{
X			msg("invalid option name \"%s\"", name);
X		}
X		else if ((opts[i].flags & CANSET) != CANSET)
X		{
X			msg("option \"%s\" can't be altered", name);
X		}
X		else if ((opts[i].flags & RCSET) != CANSET && nlines >= 1L)
X		{
X			msg("option \"%s\" can only be set in a %s file", name, EXRC);
X		}
X		else if (value)
X		{
X			switch (opts[i].type)
X			{
X			  case BOOL:
X				msg("option \"[no]%s\" is boolean", name);
X				break;
X
X			  case NUM:
X				j = atoi(value);
X				if (j == 0 && *value != '0')
X				{
X					msg("option \"%s\" must have a numeric value", name);
X				}
X				else if (j < opts[i].value[1] || j > (opts[i].value[2] & 0xff))
X				{
X					msg("option \"%s\" must have a value between %d and %d",
X						name, opts[i].value[1], opts[i].value[2] & 0xff);
X				}
X				else
X				{
X					*opts[i].value = atoi(value);
X					opts[i].flags |= SET;
X				}
X				break;
X
X			  case STR:
X				strcpy(opts[i].value, value);
X				opts[i].flags |= SET;
X				break;
X			}
X			if (opts[i].flags & MR)
X			{
X				mustredraw = TRUE;
X			}
X		}
X		else /* valid option, no value */
X		{
X			if (opts[i].type == BOOL)
X			{
X				*opts[i].value = (name[-1] != 'o');
X				opts[i].flags |= SET;
X				if (opts[i].flags & MR)
X				{
X					mustredraw = TRUE;
X				}
X			}
X			else
X			{
X				msg("option \"%s\" must be given a value", name);
X			}
X		}
X
X		/* move on to the next option */
X		name = scan;
X	}
X
X	/* special processing ... */
X
X	/* if "readonly" then set the READONLY flag for this file */
X	if (*o_readonly)
X	{
X		setflag(file, READONLY);
X	}
X}
eof
if test `wc -c <opts.c` -ne 14362
then
echo opts.c damaged!
fi
fi

if test -f recycle.c -a "$1" != -f
then
echo Will not overwrite recycle.c
else
echo Extracting recycle.c
sed 's/^X//' >recycle.c <<\eof
X/* recycle.c */
X
X/* Author:
X *	Steve Kirkendall
X *	14407 SW Teal Blvd. #C
X *	Beaverton, OR 97005
X *	kirkenda at cs.pdx.edu
X */
X
X
X/* This file contains the functions perform garbage collection and allocate
X * reusable blocks.
X */
X
X#include "config.h"
X#include "vi.h"
X
X#ifndef NO_RECYCLE
X/* this whole file would have be skipped if NO_RECYCLE is defined */
X
Xextern long	lseek();
X
X#define BTST(bitno, byte)	((byte) & (1 << (bitno)))
X#define BSET(bitno, byte)	((byte) |= (1 << (bitno)))
X#define BCLR(bitno, byte)	((byte) &= ~(1 << (bitno)))
X
X#define TST(blkno)		((blkno) < MAXBIT ? BTST((blkno) & 7, bitmap[(blkno) >> 3]) : 1)
X#define SET(blkno)		if ((blkno) < MAXBIT) BSET((blkno) & 7, bitmap[(blkno) >> 3])
X#define CLR(blkno)		if ((blkno) < MAXBIT) BCLR((blkno) & 7, bitmap[(blkno) >> 3])
X
X/* bitmap of free blocks in first 4096k of tmp file */
Xstatic unsigned char bitmap[512];
X#define MAXBIT	(sizeof bitmap << 3)
X
X/* this function locates all free blocks in the current tmp file */
Xvoid garbage()
X{
X	int	i;
X	BLK	oldhdr;
X
X	/* start by assuming every block is free */
X	for (i = 0; i < sizeof bitmap; i++)
X	{
X		bitmap[i] = 255;
X	}
X
X	/* header block isn't free */
X#ifndef lint
X	CLR(0);
X#endif
X
X	/* blocks needed for current hdr aren't free */
X	for (i = 1; i < MAXBLKS; i++)
X	{
X		CLR(hdr.n[i]);
X	}
X
X	/* blocks needed for undo version aren't free */
X	lseek(tmpfd, 0L, 0);
X	if (read(tmpfd, &oldhdr, (unsigned)sizeof oldhdr) != sizeof oldhdr)
X	{
X		msg("garbage() failed to read oldhdr??");
X		for (i = 0; i < sizeof bitmap; i++)
X		{
X			bitmap[i] = 0;
X		}
X		return;
X	}
X	for (i = 1; i < MAXBLKS; i++)
X	{
X		CLR(oldhdr.n[i]);
X	}
X
X	/* blocks needed for cut buffers aren't free */
X	for (i = cutneeds(&oldhdr) - 1; i >= 0; i--)
X	{
X		CLR(oldhdr.n[i]);
X	}
X}
X
X/* This function allocates the first available block in the tmp file */
Xlong allocate()
X{
X	int	i;
X	long	offset;
X
X	/* search for the first byte with a free bit set */
X	for (i = 0; i < sizeof bitmap && bitmap[i] == 0; i++)
X	{
X	}
X
X	/* if we hit the end of the bitmap, return the end of the file */
X	if (i == sizeof bitmap)
X	{
X		offset = lseek(tmpfd, 0L, 2);
X	}
X	else /* compute the offset for the free block */
X	{
X		for (i <<= 3; TST(i) == 0; i++)
X		{
X		}
X		offset = (long)i * (long)BLKSIZE;
X
X		/* mark the block as "allocated" */
X		CLR(i);
X	}
X
X	return offset;
X}
X
X#endif
eof
if test `wc -c <recycle.c` -ne 2306
then
echo recycle.c damaged!
fi
fi

if test -f redraw.c -a "$1" != -f
then
echo Will not overwrite redraw.c
else
echo Extracting redraw.c
sed 's/^X//' >redraw.c <<\eof
X/* redraw.c */
X
X/* Author:
X *	Steve Kirkendall
X *	14407 SW Teal Blvd. #C
X *	Beaverton, OR 97005
X *	kirkenda at cs.pdx.edu
X */
X
X
X/* This file contains functions that draw text on the screen.  The major entry
X * points are:
X *	redrawrange()	- called from modify.c to give hints about what parts
X *			  of the screen need to be redrawn.
X *	redraw()	- redraws the screen (or part of it) and positions
X *			  the cursor where it belongs.
X *	idx2col()	- converts a markidx() value to a logical column number.
X */
X
X#include "config.h"
X#include "vi.h"
X
X/* This variable contains the line number that smartdrawtext() knows best */
Xstatic long smartlno;
X
X/* This function remebers where changes were made, so that the screen can be
X * redraw in a more efficient manner.
X */
Xstatic long	redrawafter;	/* line# of first line that must be redrawn */
Xstatic long	preredraw;	/* line# of last line changed, before change */
Xstatic long	postredraw;	/* line# of last line changed, after change */
Xvoid redrawrange(after, pre, post)
X	long	after;	/* lower bound of redrawafter */
X	long	pre;	/* upper bound of preredraw */
X	long	post;	/* upper bound of postredraw */
X{
X	if (after == redrawafter)
X	{
X		/* multiple insertions/deletions at the same place -- combine
X		 * them
X		 */
X		preredraw -= (post - pre);
X		if (postredraw < post)
X		{
X			preredraw += (post - postredraw);
X			postredraw = post;
X		}
X		if (redrawafter > preredraw)
X		{
X			redrawafter = preredraw;
X		}
X		if (redrawafter < 1L)
X		{
X			redrawafter = 0L;
X			preredraw = postredraw = INFINITY;
X		}
X	}
X	else if (postredraw > 0L)
X	{
X		/* multiple changes in different places -- redraw everything
X		 * after "after".
X		 */
X		postredraw = preredraw = INFINITY;
X		if (after < redrawafter)
X			redrawafter = after;
X	}
X	else
X	{
X		/* first change */
X		redrawafter = after;
X		preredraw = pre;
X		postredraw = post;
X	}
X}
X
X
X#ifndef NO_CHARATTR
X/* see if a given line uses character attribute strings */
Xstatic int hasattr(lno, text)
X	long		lno;	/* the line# of the cursor */
X	REG char	*text;	/* the text of the line, from fetchline */
X{
X	static long	plno;	/* previous line number */
X	static long	chgs;	/* previous value of changes counter */
X	static int	panswer;/* previous answer */
X	char		*scan;
X
X	/* if charattr is off, then the answer is "no, it doesn't" */
X	if (!*o_charattr)
X	{
X		chgs = 0; /* <- forces us to check if charattr is later set */
X		return FALSE;
X	}
X
X	/* if we already know the answer, return it... */
X	if (lno == plno && chgs == changes)
X	{
X		return panswer;
X	}
X
X	/* get the line & look for "\fX" */
X	if (!text[0] || !text[1] || !text[2])
X	{
X		panswer = FALSE;
X	}
X	else
X	{
X		for (scan = text; scan[2] && !(scan[0] == '\\' && scan[1] == 'f'); scan++)
X		{
X		}
X		panswer = (scan[2] != '\0');
X	}
X
X	/* save the results */
X	plno = lno;
X	chgs = changes;
X
X	/* return the results */
X	return panswer;
X}
X#endif
X
X
X
X/* This function converts a MARK to a column number.  It doesn't automatically
X * adjust for leftcol; that must be done by the calling function
X */
Xint idx2col(curs, text, inputting)
X	MARK		curs;	/* the line# & index# of the cursor */
X	REG char	*text;	/* the text of the line, from fetchline */
X	int		inputting;	/* boolean: called from input() ? */
X{
X	static MARK	pcursor;/* previous cursor, for possible shortcut */
X	static MARK	pcol;	/* column number for pcol */
X	static long	chgs;	/* previous value of changes counter */
X	REG int		col;	/* used to count column numbers */
X	REG int		idx;	/* used to count down the index */
X	REG int		i;
X
X	/* for now, assume we have to start counting at the left edge */
X	col = 0;
X	idx = markidx(curs);
X
X	/* if the file hasn't changed & line number is the same & it has no
X	 * embedded character attribute strings, can we do shortcuts?
X	 */
X	if (chgs == changes
X	 && !((curs ^ pcursor) & ~(BLKSIZE - 1))
X#ifndef NO_CHARATTR
X	 && !hasattr(markline(curs), text)
X#endif
X	)
X	{
X		/* no movement? */
X		if (curs == pcursor)
X		{
X			/* return the column of the char; for tabs, return its last column */
X			if (text[idx] == '\t' && !inputting && !*o_list)
X			{
X				return pcol + *o_tabstop - (pcol % *o_tabstop) - 1;
X			}
X			else
X			{
X				return pcol;
X			}
X		}
X
X		/* movement to right? */
X		if (curs > pcursor)
X		{
X			/* start counting from previous place */
X			col = pcol;
X			idx = markidx(curs) - markidx(pcursor);
X			text += markidx(pcursor);
X		}
X	}
X
X	/* count over to the char after the idx position */
X	while (idx > 0 && (i = *text)) /* yes, ASSIGNMENT! */
X	{
X		if (i == '\t' && !*o_list)
X		{
X			col += *o_tabstop;
X			col -= col % *o_tabstop;
X		}
X		else if (i >= '\0' && i < ' ' || i == '\177')
X		{
X			col += 2;
X		}
X#ifndef NO_CHARATTR
X		else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
X		{
X			text += 2; /* plus one more at bottom of loop */
X			idx -= 2;
X		}			
X#endif
X		else
X		{
X			col++;
X		}
X		text++;
X		idx--;
X	}
X
X	/* save stuff to speed next call */
X	pcursor = curs;
X	pcol = col;
X	chgs = changes;
X
X	/* return the column of the char; for tabs, return its last column */
X	if (*text == '\t' && !inputting && !*o_list)
X	{
X		return col + *o_tabstop - (col % *o_tabstop) - 1;
X	}
X	else
X	{
X		return col;
X	}
X}
X
X
X/* This function is similar to idx2col except that it takes care of sideways
X * scrolling - for the given line, at least.
X */
Xint mark2phys(m, text, inputting)
X	MARK	m;		/* a mark to convert */
X	char	*text;		/* the line that m refers to */
X	int	inputting;	/* boolean: caled from input() ? */
X{
X	int	i;
X
X	i = idx2col(m, text, inputting);
X	while (i < leftcol)
X	{
X		leftcol -= *o_sidescroll;
X		mustredraw = TRUE;
X		redrawrange(1L, INFINITY, INFINITY);
X		qaddch('\r');
X		/* drawtext(text); */
X	}
X	while (i > rightcol)
X	{
X		leftcol += *o_sidescroll;
X		mustredraw = TRUE;
X		redrawrange(1L, INFINITY, INFINITY);
X		qaddch('\r');
X		/* drawtext(text); */
X	}
X	physcol = i - leftcol;
X	physrow = markline(m) - topline;
X
X	return physcol;
X}
X
X/* This function draws a single line of text on the screen.  The screen's
X * cursor is assumed to be located at the leftmost column of the appropriate
X * row.
X */
Xstatic void drawtext(text, clr)
X	REG char	*text;	/* the text to draw */
X	int		clr;	/* boolean: do a clrtoeol? */
X{
X	REG int		col;	/* column number */
X	REG int		i;
X	REG int		tabstop;	/* *o_tabstop */
X	REG int		limitcol;	/* leftcol or leftcol + COLS */
X	int		abnormal;	/* boolean: charattr != A_NORMAL? */
X
X#ifndef NO_SENTENCE
X	/* if we're hiding format lines, and this is one of them, then hide it */
X	if (*o_hideformat && *text == '.')
X	{
X		clrtoeol();
X#if OSK
X		qaddch('\l');
X#else
X		qaddch('\n');
X#endif
X		return;
X	}
X#endif
X
X	/* move some things into registers... */
X	limitcol = leftcol;
X	tabstop = *o_tabstop;
X	abnormal = FALSE;
X
X#ifndef CRUNCH
X	if (clr)
X		clrtoeol();
X#endif
X	/* skip stuff that was scrolled off left edge */
X	for (col = 0;
X	     (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
X	     text++)
X	{
X		if (i == '\t' && !*o_list)
X		{
X			col = col + tabstop - (col % tabstop);
X		}
X		else if (i >= 0 && i < ' ' || i == '\177')
X		{
X			col += 2;
X		}
X#ifndef NO_CHARATTR
X		else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
X		{
X			text += 2; /* plus one more as part of "for" loop */
X
X			/* since this attribute might carry over, we need it */
X			switch (*text)
X			{
X			  case 'R':
X			  case 'P':
X				attrset(A_NORMAL);
X				abnormal = FALSE;
X				break;
X
X			  case 'B':
X				attrset(A_BOLD);
X				abnormal = TRUE;
X				break;
X
X			  case 'U':
X				attrset(A_UNDERLINE);
X				abnormal = TRUE;
X				break;
X
X			  case 'I':
X				attrset(A_ALTCHARSET);
X				abnormal = TRUE;
X				break;
X			}
X		}
X#endif
X		else
X		{
X			col++;
X		}
X	}
X
X	/* adjust for control char that was partially visible */
X	while (col > limitcol)
X	{
X		qaddch(' ');
X		limitcol++;
X	}
X
X	/* now for the visible characters */
X	for (limitcol = leftcol + COLS;
X	     (i = *text) && col < limitcol;
X	     text++)
X	{
X		if (i == '\t' && !*o_list)
X		{
X			i = col + tabstop - (col % tabstop);
X			if (i < limitcol)
X			{
X#ifdef CRUNCH
X				if (!clr && has_PT && !((i - leftcol) & 7))
X#else
X				if (has_PT && !((i - leftcol) & 7))
X#endif
X				{
X					do
X					{
X						qaddch('\t');
X						col += 8; /* not exact! */
X					} while (col < i);
X					col = i; /* NOW it is exact */
X				}
X				else
X				{
X					do
X					{
X						qaddch(' ');
X						col++;
X					} while (col < i);
X				}
X			}
X			else /* tab ending after screen? next line! */
X			{
X				col = limitcol;
X				if (has_AM)
X				{
X					addch('\n');	/* GB */
X				}
X			}
X		}
X		else if (i >= 0 && i < ' ' || i == '\177')
X		{
X			col += 2;
X			qaddch('^');
X			if (col <= limitcol)
X			{
X				qaddch(i ^ '@');
X			}
X		}
X#ifndef NO_CHARATTR
X		else if (i == '\\' && text[1] == 'f' && text[2] && *o_charattr)
X		{
X			text += 2; /* plus one more as part of "for" loop */
X			switch (*text)
X			{
X			  case 'R':
X			  case 'P':
X				attrset(A_NORMAL);
X				abnormal = FALSE;
X				break;
X
X			  case 'B':
X				attrset(A_BOLD);
X				abnormal = TRUE;
X				break;
X
X			  case 'U':
X				attrset(A_UNDERLINE);
X				abnormal = TRUE;
X				break;
X
X			  case 'I':
X				attrset(A_ALTCHARSET);
X				abnormal = TRUE;
X				break;
X			}
X		}
X#endif
X		else
X		{
X			col++;
X			qaddch(i);
X		}
X	}
X
X	/* get ready for the next line */
X#ifndef NO_CHARATTR
X	if (abnormal)
X	{
X		attrset(A_NORMAL);
X	}
X#endif
X	if (*o_list && col < limitcol)
X	{
X		qaddch('$');
X		col++;
X	}
X#ifdef CRUNCH
X	if (clr && col < limitcol)
X	{
X		clrtoeol();
X	}
X#endif
X	if (!has_AM || col < limitcol)
X	{
X		addch('\n');
X	}
X}
X
X
X#ifndef CRUNCH
Xstatic void nudgecursor(same, scan, new, lno)
X	int	same;	/* number of chars to be skipped over */
X	char	*scan;	/* where the same chars end */
X	char	*new;	/* where the visible part of the line starts */
X	long	lno;	/* line number of this line */
X{
X	if (same > 0)
X	{
X		if (same < 5)
X		{
X			/* move the cursor by overwriting */
X			while (same > 0)
X			{
X				qaddch(scan[-same]);
X				same--;
X			}
X		}
X		else
X		{
X			/* move the cursor by calling move() */
X			move((int)(lno - topline), (int)(scan - new));
X		}
X	}
X}
X#endif /* not CRUNCH */
X
X/* This function draws a single line of text on the screen, possibly with
X * some cursor optimization.  The cursor is repositioned before drawing
X * begins, so its position before doesn't really matter.
X */
Xstatic void smartdrawtext(text, lno)
X	REG char	*text;	/* the text to draw */
X	long		lno;	/* line number of the text */
X{
X#ifdef CRUNCH
X	move((int)(lno - topline), 0);
X	drawtext(text, TRUE);
X#else /* not CRUNCH */
X	static char	old[256];	/* how the line looked last time */
X	char		new[256];	/* how it looks now */
X	char		*build;		/* used to put chars into new[] */
X	char		*scan;		/* used for moving thru new[] or old[] */
X	char		*end;		/* last non-blank changed char */
X	char		*shift;		/* used to insert/delete chars */
X	int		same;		/* length of a run of unchanged chars */
X	int		limitcol;
X	int		col;
X	int		i;
X
X# ifndef NO_CHARATTR
X	/* if this line has attributes, do it the dumb way instead */
X	if (hasattr(lno, text))
X	{
X		move((int)(lno - topline), 0);
X		drawtext(text, TRUE);
X		return;
X	}
X# endif
X# ifndef NO_SENTENCE
X	/* if this line is a format line, & we're hiding format lines, then
X	 * let the dumb drawtext() function handle it
X	 */
X	if (*o_hideformat && *text == '.')
X	{
X		move((int)(lno - topline), 0);
X		drawtext(text, TRUE);
X		return;
X	}
X# endif
X
X	/* skip stuff that was scrolled off left edge */
X	limitcol = leftcol;
X	for (col = 0;
X	     (i = *text) && col < limitcol; /* yes, ASSIGNMENT! */
X	     text++)
X	{
X		if (i == '\t' && !*o_list)
X		{
X			col = col + *o_tabstop - (col % *o_tabstop);
X		}
X		else if (i >= 0 && i < ' ' || i == '\177')
X		{
X			col += 2;
X		}
X		else
X		{
X			col++;
X		}
X	}
X
X	/* adjust for control char that was partially visible */
X	build = new;
X	while (col > limitcol)
X	{
X		*build++ = ' ';
X		limitcol++;
X	}
X
X	/* now for the visible characters */
X	for (limitcol = leftcol + COLS;
X	     (i = *text) && col < limitcol;
X	     text++)
X	{
X		if (i == '\t' && !*o_list)
X		{
X			i = col + *o_tabstop - (col % *o_tabstop);
X			while (col < i && col < limitcol)
X			{
X				*build++ = ' ';
X				col++;
X			}
X		}
X		else if (i >= 0 && i < ' ' || i == '\177')
X		{
X			col += 2;
X			*build++ = '^';
X			if (col <= limitcol)
X			{
X				*build++ = (i ^ '@');
X			}
X		}
X		else
X		{
X			col++;
X			*build++ = i;
X		}
X	}
X	if (col < limitcol && *o_list)
X	{
X		*build++ = '$';
X		col++;
X	}
X	end = build;
X	while (col < limitcol)
X	{
X		*build++ = ' ';
X		col++;
X	}
X
X	/* locate the last non-blank character */
X	while (end > new && end[-1] == ' ')
X	{
X		end--;
X	}
X
X	/* can we optimize the displaying of this line? */
X	if (lno != smartlno)
X	{
X		/* nope, can't optimize - different line */
X		move((int)(lno - topline), 0);
X		for (scan = new, build = old; scan < end; )
X		{
X			qaddch(*scan);
X			*build++ = *scan++;
X		}
X		if (end < new + COLS)
X		{
X			clrtoeol();
X			while (build < old + COLS)
X			{
X				*build++ = ' ';
X			}
X		}
X		smartlno = lno;
X		return;
X	}
X
X	/* skip any initial unchanged characters */
X	for (scan = new, build = old; scan < end && *scan == *build; scan++, build++)
X	{
X	}
X	move((int)(lno - topline), (int)(scan - new));
X
X	/* The in-between characters must be changed */
X	same = 0;
X	while (scan < end)
X	{
X		/* is this character a match? */
X		if (scan[0] == build[0])
X		{
X			same++;
X		}
X		else /* do we want to insert? */
X		if (scan < end - 1 && scan[1] == build[0] && (has_IC || has_IM))
X		{
X			nudgecursor(same, scan, new, lno);
X			same = 0;
X
X			insch(*scan);
X			for (shift = old + COLS; --shift > build; )
X			{
X				shift[0] = shift[-1];
X			}
X			*build = *scan;
X		}
X		else /* do we want to delete? */
X		if (build < old + COLS - 1 && scan[0] == build[1] && has_DC)
X		{
X			nudgecursor(same, scan, new, lno);
X			same = 0;
X
X			delch();
X			same++;
X			for (shift = build; shift < old + COLS - 1; shift++)
X			{
X				shift[0] = shift[1];
X			}
X			*shift = ' ';
X		}
X		else /* we must overwrite */
X		{
X			nudgecursor(same, scan, new, lno);
X			same = 0;
X
X			addch(*scan);
X			*build = *scan;
X		}
X
X		build++;
X		scan++;
X	}
X
X	/* maybe clear to EOL */
X	while (build < old + COLS && *build == ' ')
X	{
X		build++;
X	}
X	if (build < old + COLS)
X	{
X		nudgecursor(same, scan, new, lno);
X		same = 0;
X
X		clrtoeol();
X		while (build < old + COLS)
X		{
X			*build++ = ' ';
X		}
X	}
X#endif /* not CRUNCH */
X}
X
X
X/* This function is used in visual mode for drawing the screen (or just parts
X * of the screen, if that's all thats needed).  It also takes care of
X * scrolling.
X */
Xvoid redraw(curs, inputting)
X	MARK	curs;		/* where to leave the screen's cursor */
X	int	inputting;	/* boolean: being called from input() ? */
X{
X	char		*text;		/* a line of text to display */
X	static long	chgs;		/* previous changes level */
X	long		l;
X	int		i;
X
X	/* if curs == MARK_UNSET, then we should reset internal vars */
X	if (curs == MARK_UNSET)
X	{
X		if (topline < 1 || topline > nlines)
X		{
X			topline = 1L;
X		}
X		else
X		{
X			move(LINES - 1, 0);
X			clrtoeol();
X		}
X		leftcol = 0;
X		mustredraw = TRUE;
X		redrawafter = INFINITY;
X		preredraw = 0L;
X		postredraw = 0L;
X		chgs = 0;
X		smartlno = 0L;
X		return;
X	}
X
X	/* figure out which column the cursor will be in */
X	l = markline(curs);
X	text = fetchline(l);
X	mark2phys(curs, text, inputting);
X
X	/* adjust topline, if necessary, to get the cursor on the screen */
X	if (l >= topline && l <= botline)
X	{
X		/* it is on the screen already */
X
X		/* if the file was changed but !mustredraw, then redraw line */
X		if (chgs != changes && !mustredraw)
X		{
X			smartdrawtext(text, l);
X		}
X	}
X	else if (l < topline && l > topline - LINES && (has_SR || has_AL))
X	{
X		/* near top - scroll down */
X		if (!mustredraw)
X		{
X			move(0,0);
X			while (l < topline)
X			{
X				topline--;
X				if (has_SR)
X				{
X					do_SR();
X				}
X				else
X				{
X					insertln();
X				}
X				text = fetchline(topline);
X				drawtext(text, FALSE);
X				do_UP();
X			}
X
X			/* blank out the last line */
X			move(LINES - 1, 0);
X			clrtoeol();
X		}
X		else
X		{
X			topline = l;
X			redrawafter = INFINITY;
X			preredraw = 0L;
X			postredraw = 0L;
X		}
X	}
X	else if (l > topline && l < botline + LINES)
X	{
X		/* near bottom -- scroll up */
X		if (!mustredraw
X#if 1
X		 || redrawafter == preredraw && preredraw == botline && postredraw == l
X#endif
X		)
X		{
X			move(LINES - 1,0);
X			clrtoeol();
X			while (l > botline)
X			{
X				topline++; /* <-- also adjusts botline */
X				text = fetchline(botline);
X				drawtext(text, FALSE);
X			}
X			mustredraw = FALSE;
X		}
X		else
X		{
X			topline = l - (LINES - 2);
X			redrawafter = INFINITY;
X			preredraw = 0L;
X			postredraw = 0L;
X		}
X	}
X	else
X	{
X		/* distant line - center it & force a redraw */
X		topline = l - (LINES / 2) - 1;
X		if (topline < 1)
X		{
X			topline = 1;
X		}
X		mustredraw = TRUE;
X		redrawafter = INFINITY;
X		preredraw = 0L;
X		postredraw = 0L;
X	}
X
X	/* Now... do we really have to redraw? */
X	if (mustredraw)
X	{
X		/* If redrawfter (and friends) aren't set, assume we should
X		 * redraw everything.
X		 */
X		if (redrawafter == INFINITY)
X		{
X			redrawafter = 0L;
X			preredraw = postredraw = INFINITY;
X		}
X
X		/* adjust smartlno to correspond with inserted/deleted lines */
X		if (smartlno >= redrawafter)
X		{
X			if (smartlno < preredraw)
X			{
X				smartlno = 0L;
X			}
X			else
X			{
X				smartlno += (postredraw - preredraw);
X			}
X		}
X
X		/* should we insert some lines into the screen? */
X		if (preredraw < postredraw && preredraw <= botline)
X		{
X			/* lines were inserted into the file */
X
X			/* decide where insertion should start */
X			if (preredraw < topline)
X			{
X				l = topline;
X			}
X			else
X			{
X				l = preredraw;
X			}
X
X			/* insert the lines... maybe */
X			if (l + postredraw - preredraw > botline || !has_AL)
X			{
X				/* Whoa!  a whole screen full - just redraw */
X				preredraw = postredraw = INFINITY;
X			}
X			else
X			{
X				/* really insert 'em */
X				move((int)(l - topline), 0);
X				for (i = postredraw - preredraw; i > 0; i--)
X				{
X					insertln();
X				}
X
X				/* NOTE: the contents of those lines will be
X				 * drawn as part of the regular redraw loop.
X				 */
X
X				/* clear the last line */
X				move(LINES - 1, 0);
X				clrtoeol();
X			}
X		}
X
X		/* do we want to delete some lines from the screen? */
X		if (preredraw > postredraw && postredraw <= botline)
X		{
X			if (preredraw > botline || !has_DL)
X			{
X				postredraw = preredraw = INFINITY;
X			}
X			else /* we'd best delete some lines from the screen */
X			{
X				/* clear the last line, so it doesn't look
X				 * ugly as it gets pulled up into the screen
X				 */
X				move(LINES - 1, 0);
X				clrtoeol();
X
X				/* delete the lines */
X				move((int)(postredraw - topline), 0);
X			 	for (l = postredraw;
X				     l < preredraw && l <= botline;
X				     l++)
X				{
X					deleteln();
X				}
X
X				/* draw the lines that are now newly visible
X				 * at the bottom of the screen
X				 */
X				i = LINES - 1 + (postredraw - preredraw);
X				move(i, 0);
X				for (l = topline + i; l <= botline; l++)
X				{
X					/* clear this line */
X					clrtoeol();
X
X					/* draw the line, or ~ for non-lines */
X					if (l <= nlines)
X					{
X						text = fetchline(l);
X						drawtext(text, FALSE);
X					}
X					else
X					{
X						addstr("~\n");
X					}
X				}
X			}
X		}
X
X		/* redraw the current line */
X		l = markline(curs);
X		pfetch(l);
X		smartdrawtext(ptext, l);
X
X		/* decide where we should start redrawing from */
X		if (redrawafter < topline)
X		{
X			l = topline;
X		}
X		else
X		{
X			l = redrawafter;
X		}
X		move((int)(l - topline), 0);
X
X		/* draw the other lines */
X		for (; l <= botline && l < postredraw; l++)
X		{
X			/* we already drew the current line, so skip it now */
X			if (l == smartlno)
X			{
X#if OSK
X				qaddch('\l');
X#else
X				qaddch('\n');
X#endif
X				continue;
X			}
X
X			/* draw the line, or ~ for non-lines */
X			if (l <= nlines)
X			{
X				text = fetchline(l);
X				drawtext(text, TRUE);
X			}
X			else
X			{
X				qaddch('~');
X				clrtoeol();
X				addch('\n');
X			}
X		}
X
X		mustredraw = FALSE;
X	}
X
X	/* force total (non-partial) redraw next time if not set */
X	redrawafter = INFINITY;
X	preredraw = 0L;
X	postredraw = 0L;
X
X	/* move the cursor to where it belongs */
X	move((int)(markline(curs) - topline), physcol);
X	wqrefresh(stdscr);
X
X	chgs = changes;
X}
eof
if test `wc -c <redraw.c` -ne 19816
then
echo redraw.c damaged!
fi
fi

exit 0
-------------------------------------------------------------------------------
Steve Kirkendall     kirkenda at cs.pdx.edu      Grad student at Portland State U.



More information about the Alt.sources mailing list