Example #1
0
/*
 * updateline()
 *
 * int row;		row of screen to update
 * struct video *vp1;	virtual screen image
 * struct video *vp2;	physical screen image
 */
static int updateline(int row, struct video *vp1, struct video *vp2)
{
#if RAINBOW
/*	UPDATELINE specific code for the DEC rainbow 100 micro	*/

	unicode_t *cp1;
	unicode_t *cp2;
	int nch;

	/* since we don't know how to make the rainbow do this, turn it off */
	flags &= (~VFREV & ~VFREQ);

	cp1 = &vp1->v_text[0];	/* Use fast video. */
	cp2 = &vp2->v_text[0];
	putline(row + 1, 1, cp1);
	nch = term.t_ncol;

	do {
		*cp2 = *cp1;
		++cp2;
		++cp1;
	}
	while (--nch);
	*flags &= ~VFCHG;
#else
/*	UPDATELINE code for all other versions		*/

	unicode_t *cp1;
	unicode_t *cp2;
	unicode_t *cp3;
	unicode_t *cp4;
	unicode_t *cp5;
	int nbflag;	/* non-blanks to the right flag? */
	int rev;		/* reverse video flag */
	int req;		/* reverse video request flag */


	/* set up pointers to virtual and physical lines */
	cp1 = &vp1->v_text[0];
	cp2 = &vp2->v_text[0];

#if	COLOR
	TTforg(vp1->v_rfcolor);
	TTbacg(vp1->v_rbcolor);
#endif

#if	REVSTA | COLOR
	/* if we need to change the reverse video status of the
	   current line, we need to re-write the entire line     */
	rev = (vp1->v_flag & VFREV) == VFREV;
	req = (vp1->v_flag & VFREQ) == VFREQ;
	if ((rev != req)
#if	COLOR
	    || (vp1->v_fcolor != vp1->v_rfcolor)
	    || (vp1->v_bcolor != vp1->v_rbcolor)
#endif
	    ) {
		movecursor(row, 0);	/* Go to start of line. */
		/* set rev video if needed */
		if (rev != req)
			(*term.t_rev) (req);

		/* scan through the line and dump it to the screen and
		   the virtual screen array                             */
		cp3 = &vp1->v_text[term.t_ncol];
		while (cp1 < cp3) {
			TTputc(*cp1);
			++ttcol;
			*cp2++ = *cp1++;
		}
		/* turn rev video off */
		if (rev != req)
			(*term.t_rev) (FALSE);

		/* update the needed flags */
		vp1->v_flag &= ~VFCHG;
		if (req)
			vp1->v_flag |= VFREV;
		else
			vp1->v_flag &= ~VFREV;
#if	COLOR
		vp1->v_fcolor = vp1->v_rfcolor;
		vp1->v_bcolor = vp1->v_rbcolor;
#endif
		return TRUE;
	}
#endif

	/* advance past any common chars at the left */
	while (cp1 != &vp1->v_text[term.t_ncol] && cp1[0] == cp2[0]) {
		++cp1;
		++cp2;
	}

/* This can still happen, even though we only call this routine on changed
 * lines. A hard update is always done when a line splits, a massive
 * change is done, or a buffer is displayed twice. This optimizes out most
 * of the excess updating. A lot of computes are used, but these tend to
 * be hard operations that do a lot of update, so I don't really care.
 */
	/* if both lines are the same, no update needs to be done */
	if (cp1 == &vp1->v_text[term.t_ncol]) {
		vp1->v_flag &= ~VFCHG;	/* flag this line is changed */
		return TRUE;
	}

	/* find out if there is a match on the right */
	nbflag = FALSE;
	cp3 = &vp1->v_text[term.t_ncol];
	cp4 = &vp2->v_text[term.t_ncol];

	while (cp3[-1] == cp4[-1]) {
		--cp3;
		--cp4;
		if (cp3[0] != ' ')	/* Note if any nonblank */
			nbflag = TRUE;	/* in right match. */
	}

	cp5 = cp3;

	/* Erase to EOL ? */
	if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) {
		while (cp5 != cp1 && cp5[-1] == ' ')
			--cp5;

		if (cp3 - cp5 <= 3)	/* Use only if erase is */
			cp5 = cp3;	/* fewer characters. */
	}

	movecursor(row, cp1 - &vp1->v_text[0]);	/* Go to start of line. */
#if	REVSTA
	TTrev(rev);
#endif

	while (cp1 != cp5) {	/* Ordinary. */
		TTputc(*cp1);
		++ttcol;
		*cp2++ = *cp1++;
	}

	if (cp5 != cp3) {	/* Erase. */
		TTeeol();
		while (cp1 != cp3)
			*cp2++ = *cp1++;
	}
#if	REVSTA
	TTrev(FALSE);
#endif
	vp1->v_flag &= ~VFCHG;	/* flag this line as updated */
	return TRUE;
#endif
}
Example #2
0
// Update a single line on the physical screen, given row, virtual screen image, and physical screen image.  This does not know
// how to use insert or delete character sequences; we are using VT52 functionality.  Update the physical row and column
// variables.  It does try to exploit erase to end of line.  Return status.
static int pupd_line(int row,Video *vp,Video *pp) {
	char *vir_left;			// Left pointer to virtual line.
	char *phy_left;			// Left pointer to physical line.
	char *vir_right;		// Right pointer to virtual line.
	char *phy_right;		// Right pointer to physical line.
	int rev_left;			// Leftmost reversed char index.
	int rev_right;			// Rightmost reversed char index.
	char *left_blank;		// Left-most trailing blank.
	int non_blanks;			// Non-blanks to the right flag.
	int update_column;		// Update column.
	int old_rev_state = false;	// Reverse video states.
	int new_rev_state;

	// Set up pointers to virtual and physical lines.
	vir_left = vp->v_text;
	vir_right = vp->v_text + term.t_ncol;
	phy_left = pp->v_text;
	phy_right = pp->v_text + term.t_ncol;
	update_column = 0;
	rev_left = FARRIGHT;
	rev_right = 0;
	non_blanks = true;

	// If this is a legitimate line to optimize.
	if(!(pp->v_flags & VFNEW)) {

		// Advance past any common chars at the left.
		while(vir_left != vp->v_text + term.t_ncol && vir_left[0] == phy_left[0]) {
			++vir_left;
			++update_column;
			++phy_left;
			}

		// Advance past any common chars at the right.
		non_blanks = false;
		while(vir_right[-1] == phy_right[-1] && vir_right >= vir_left) {
			--vir_right;
			--phy_right;

			// Note if any nonblank in right match.
			if(vir_right[0] != ' ')
				non_blanks = true;
			}
		}

#if COLOR
	// New line color?
	if(vp->v_rfcolor != vp->v_fcolor || vp->v_rbcolor != vp->v_bcolor) {
		vp->v_fcolor = vp->v_rfcolor;
		vp->v_bcolor = vp->v_rbcolor;
		vp->v_flags &= ~VFCOLOR;
		vir_left = vp->v_text;
		vir_right = vp->v_text + term.t_ncol;
		phy_left = pp->v_text;
		phy_right = pp->v_text + term.t_ncol;
		update_column = 0;
		}

	if(TTforg(vp->v_fcolor) != SUCCESS || TTbacg(vp->v_bcolor) != SUCCESS)
		return rc.status;
#endif

	// Reverse video changes?
	if(vp->v_left != pp->v_left || vp->v_right != pp->v_right) {

		// Adjust leftmost edge.
		if(vp->v_left < pp->v_left)
			rev_left = vp->v_left;
		else
			rev_left = pp->v_left;

		pp->v_left = vp->v_left;
		if(rev_left < update_column) {
			vir_left = vp->v_text + rev_left;
			phy_left = pp->v_text + rev_left;
			update_column = rev_left;
			}

		// Adjust rightmost edge.
		if(vp->v_right > pp->v_right)
			rev_right = vp->v_right;
		else
			rev_right = pp->v_right;

		pp->v_right = vp->v_right;
		if(vp->v_text + rev_right > vir_right) {
			vir_right = vp->v_text + rev_right;
			phy_right = pp->v_text + rev_right;
			}
		}
	else {
		rev_left = vp->v_left;
		rev_right = vp->v_right;
		}

	// If both lines are the same, no update needs to be done.
	if(!(pp->v_flags & VFNEW) && vir_left > vir_right) {
		vp->v_flags &= ~VFCHGD;			// Clear changed flag.
		return rc.status;
		}

	left_blank = vir_right;

	// Erase to EOL?
	if(non_blanks == false && (opflags & OPHAVEEOL)) {
		while(left_blank != vir_left && left_blank[-1] == ' ')
			--left_blank;
		if(vir_right - left_blank <= 3)		// Use only if erase is > 3 characters.
			left_blank = vir_right;
		}

	// Move to the beginning of the text to update.
	if(movecursor(row,update_column) != SUCCESS)
		return rc.status;

	while(vir_left != left_blank) {		// Ordinary.

		// Are we in a reverse video field?
		if(pp->v_left <= update_column && update_column < pp->v_right)
			new_rev_state = true;
		else
			new_rev_state = false;

		// If moving in or out of reverse video, change it.
		if(new_rev_state != old_rev_state) {
			if(TTrev(new_rev_state) != SUCCESS)
				return rc.status;
			old_rev_state = new_rev_state;
			}

		// Output the next character.
		if(TTputc(*vir_left) != SUCCESS)
			return rc.status;
		++update_column;
		*phy_left++ = *vir_left++;
		}

	if(left_blank != vir_right) {		// Erase.

		// Are we in a reverse video field?
		if(pp->v_left <= update_column && update_column < pp->v_right)
			new_rev_state = true;
		else
			new_rev_state = false;

		// If moving in or out of reverse video, change it.
		if(new_rev_state != old_rev_state) {
			if(TTrev(new_rev_state) != SUCCESS)
				return rc.status;
			old_rev_state = new_rev_state;
			}

#if TT_TERMCAP
		// TERMCAP does not tell us if the current terminal propagates the current attributes to the end of the line
		// when an erase to end of line sequence is sent.  Don't let TERMCAP use EEOL if in a reverse video line!
		if(new_rev_state == true)
			while(update_column++ < (int) term.t_ncol) {
				if(TTputc(' ') != SUCCESS)
					return rc.status;
				}
		else if(TTeeol() != SUCCESS)
			return rc.status;
#else
		if(TTeeol() != SUCCESS)
			return rc.status;
#endif
		while(vir_left != vir_right)
			*phy_left++ = *vir_left++;
		}

	vp->v_flags &= ~VFCHGD;			// Flag this line as updated.
#if COLOR
	vp->v_flags &= ~VFCOLOR;
#endif
	// Always leave in the default state.
	if(old_rev_state == true)
		(void) TTrev(false);

	return rc.status;
	}