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