[mod.sources] v09i047: Repost of display.c from MicroEmacs, Patch1

sources-request@mirror.UUCP (04/14/87)

Submitted by: pur-ee!pur-phy!duncan!lawrence
Mod.sources: Volume 9, Issue 47
Archive-name: uemacs3.8b/Patch1

[  When last we heard from this group, articles had been leaving
   site "mirror" with 512 bytes elided from them...  This is the
   first of a couple of re-posts.  --r$  ]

Daniel Lawrence can be reached at:
	UUCP:	ihnp4!pur-ee!pur-phy!duncan!lawrence
	ARPA:	nwd@j.cc.purdue.edu
	FIDO:	The Programmer's Room 201/2
		(317) 742-5533  300/1200 baud  24 hours
	USmail:	617 New York St
		Lafayette, IN 47901
	ATT:	(317) 742-5153
-----CUT-----HERE-----
#! /bin/sh
# This is a shell archive.  Remove anything before this line,
# then unpack it by saving it in a file and typing "sh file".
# If this archive is complete, you will see the message:
#		"End of shell archive."
# Contents:  display.c
# Wrapped by rs@mirror on Tue Apr 14 16:52:46 1987
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
echo shar: Extracting \"display.c\" \(23829 characters\)
if test -f display.c ; then 
  echo shar: Will not over-write existing file \"display.c\"
else
sed "s/^X//" >display.c <<'END_OF_display.c'
X/*
X * The functions in this file handle redisplay. There are two halves, the
X * ones that update the virtual display screen, and the ones that make the
X * physical display screen the same as the virtual display screen. These
X * functions use hints that are left in the windows by the commands.
X *
X */
X
X#include        <stdio.h>
X#include	"estruct.h"
X#include        "edef.h"
X
X#if	MEGAMAX & ST520
Xoverlay	"display"
X#endif
X
Xtypedef struct  VIDEO {
X        int	v_flag;                 /* Flags */
X#if	COLOR
X	int	v_fcolor;		/* current forground color */
X	int	v_bcolor;		/* current background color */
X	int	v_rfcolor;		/* requested forground color */
X	int	v_rbcolor;		/* requested background color */
X#endif
X        char    v_text[1];              /* Screen data. */
X}       VIDEO;
X
X#define VFCHG   0x0001                  /* Changed flag			*/
X#define	VFEXT	0x0002			/* extended (beyond column 80)	*/
X#define	VFREV	0x0004			/* reverse video status		*/
X#define	VFREQ	0x0008			/* reverse video request	*/
X#define	VFCOL	0x0010			/* color change requested	*/
X
XVIDEO   **vscreen;                      /* Virtual screen. */
X#if	MEMMAP == 0
XVIDEO   **pscreen;                      /* Physical screen. */
X#endif
X
X/*
X * Initialize the data structures used by the display code. The edge vectors
X * used to access the screens are set up. The operating system's terminal I/O
X * channel is set up. All the other things get initialized at compile time.
X * The original window has "WFCHG" set, so that it will get completely
X * redrawn on the first call to "update".
X */
Xvtinit()
X{
X    register int i;
X    register VIDEO *vp;
X    char *malloc();
X
X    TTopen();		/* open the screen */
X    TTkopen();		/* open the keyboard */
X    TTrev(FALSE);
X    vscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
X
X    if (vscreen == NULL)
X        exit(1);
X
X#if	MEMMAP == 0
X    pscreen = (VIDEO **) malloc(term.t_nrow*sizeof(VIDEO *));
X
X    if (pscreen == NULL)
X        exit(1);
X#endif
X
X    for (i = 0; i < term.t_nrow; ++i)
X        {
X        vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
X
X        if (vp == NULL)
X            exit(1);
X
X	vp->v_flag = 0;
X#if	COLOR
X	vp->v_rfcolor = 7;
X	vp->v_rbcolor = 0;
X#endif
X        vscreen[i] = vp;
X#if	MEMMAP == 0
X        vp = (VIDEO *) malloc(sizeof(VIDEO)+term.t_mcol);
X
X        if (vp == NULL)
X            exit(1);
X
X	vp->v_flag = 0;
X        pscreen[i] = vp;
X#endif
X        }
X}
X
X/*
X * Clean up the virtual terminal system, in anticipation for a return to the
X * operating system. Move down to the last line and clear it out (the next
X * system prompt will be written in the line). Shut down the channel to the
X * terminal.
X */
Xvttidy()
X{
X    mlerase();
X    movecursor(term.t_nrow, 0);
X    TTflush();
X    TTclose();
X    TTkclose();
X}
X
X/*
X * Set the virtual cursor to the specified row and column on the virtual
X * screen. There is no checking for nonsense values; this might be a good
X * idea during the early stages.
X */
Xvtmove(row, col)
X{
X    vtrow = row;
X    vtcol = col;
X}
X
X/* Write a character to the virtual screen. The virtual row and
X   column are updated. If we are not yet on left edge, don't print
X   it yet. If the line is too long put a "$" in the last column.
X   This routine only puts printing characters into the virtual
X   terminal buffers. Only column overflow is checked.
X*/
X
Xvtputc(c)
X
Xint c;
X
X{
X	register VIDEO *vp;	/* ptr to line being updated */
X
X	vp = vscreen[vtrow];
X
X	if (c == '\t') {
X		do {
X			vtputc(' ');
X		} while (((vtcol + taboff)&0x07) != 0);
X	} else if (vtcol >= term.t_ncol) {
X		++vtcol;
X		vp->v_text[term.t_ncol - 1] = '$';
X	} else if (c < 0x20 || c == 0x7F) {
X		vtputc('^');
X		vtputc(c ^ 0x40);
X	} else {
X		if (vtcol >= 0)
X			vp->v_text[vtcol] = c;
X		++vtcol;
X	}
X}
X
X/*
X * Erase from the end of the software cursor to the end of the line on which
X * the software cursor is located.
X */
Xvteeol()
X{
X    register VIDEO      *vp;
X
X    vp = vscreen[vtrow];
X    while (vtcol < term.t_ncol)
X        vp->v_text[vtcol++] = ' ';
X}
X
X/* upscreen:	user routine to force a screen update
X		always finishes complete update		*/
X
Xupscreen(f, n)
X
X{
X	update(TRUE);
X	return(TRUE);
X}
X
X/*
X * Make sure that the display is right. This is a three part process. First,
X * scan through all of the windows looking for dirty ones. Check the framing,
X * and refresh the screen. Second, make sure that "currow" and "curcol" are
X * correct for the current window. Third, make the virtual and physical
X * screens the same.
X */
Xupdate(force)
X
Xint force;	/* force update past type ahead? */
X
X{
X	register WINDOW *wp;
X
X#if	TYPEAH
X	if (force == FALSE && typahead())
X		return(TRUE);
X#endif
X#if	VISMAC == 0
X	if (force == FALSE && kbdmode == PLAY)
X		return(TRUE);
X#endif
X
X	/* update any windows that need refreshing */
X	wp = wheadp;
X	while (wp != NULL) {
X		if (wp->w_flag) {
X			/* if the window has changed, service it */
X			reframe(wp);	/* check the framing */
X			if ((wp->w_flag & ~WFMODE) == WFEDIT)
X				updone(wp);	/* update EDITed line */
X			else if (wp->w_flag & ~WFMOVE)
X				updall(wp);	/* update all lines */
X			if (wp->w_flag & WFMODE)
X				modeline(wp);	/* update modeline */
X			wp->w_flag = 0;
X			wp->w_force = 0;
X		}
X		/* on to the next window */
X		wp = wp->w_wndp;
X	}
X
X	/* recalc the current hardware cursor location */
X	updpos();
X
X#if	MEMMAP
X	/* update the cursor and flush the buffers */
X	movecursor(currow, curcol - lbound);
X#endif
X
X	/* check for lines to de-extend */
X	upddex();
X
X	/* if screen is garbage, re-plot it */
X	if (sgarbf != FALSE)
X		updgar();
X
X	/* update the virtual screen to the physical screen */
X	updupd(force);
X
X	/* update the cursor and flush the buffers */
X	movecursor(currow, curcol - lbound);
X	TTflush();
X	return(TRUE);
X}
X
X/*	reframe:	check to see if the cursor is on in the window
X			and re-frame it if needed or wanted		*/
X
Xreframe(wp)
X
XWINDOW *wp;
X
X{
X	register LINE *lp;
X	register int i;
X
X	/* if not a requested reframe, check for a needed one */
X	if ((wp->w_flag & WFFORCE) == 0) {
X		lp = wp->w_linep;
X		for (i = 0; i < wp->w_ntrows; i++) {
X
X			/* if the line is in the window, no reframe */
X			if (lp == wp->w_dotp)
X				return(TRUE);
X
X			/* if we are at the end of the file, reframe */
X			if (lp == wp->w_bufp->b_linep)
X				break;
X
X			/* on to the next line */
X			lp = lforw(lp);
X		}
X	}
X
X	/* reaching here, we need a window refresh */
X	i = wp->w_force;
X
X	/* how far back to reframe? */
X	if (i > 0) {		/* only one screen worth of lines max */
X		if (--i >= wp->w_ntrows)
X			i = wp->w_ntrows - 1;
X	} else if (i < 0) {	/* negative update???? */
X		i += wp->w_ntrows;
X		if (i < 0)
X			i = 0;
X	} else
X		i = wp->w_ntrows / 2;
X
X	/* backup to new line at top of window */
X	lp = wp->w_dotp;
X	while (i != 0 && lback(lp) != wp->w_bufp->b_linep) {
X		--i;
X		lp = lback(lp);
X	}
X
X	/* and reset the current line at top of window */
X	wp->w_linep = lp;
X	wp->w_flag |= WFHARD;
X	wp->w_flag &= ~WFFORCE;
X	return(TRUE);
X}
X
X/*	updone:	update the current line	to the virtual screen		*/
X
Xupdone(wp)
X
XWINDOW *wp;	/* window to update current line in */
X
X{
X	register LINE *lp;	/* line to update */
X	register int sline;	/* physical screen line to update */
X	register int i;
X
X	/* search down the line we want */
X	lp = wp->w_linep;
X	sline = wp->w_toprow;
X	while (lp != wp->w_dotp) {
X		++sline;
X		lp = lforw(lp);
X	}
X
X	/* and update the virtual line */
X	vscreen[sline]->v_flag |= VFCHG;
X	vscreen[sline]->v_flag &= ~VFREQ;
X	vtmove(sline, 0);
X	for (i=0; i < llength(lp); ++i)
X		vtputc(lgetc(lp, i));
X#if	COLOR
X	vscreen[sline]->v_rfcolor = wp->w_fcolor;
X	vscreen[sline]->v_rbcolor = wp->w_bcolor;
X#endif
X	vteeol();
X}
X
X/*	updall:	update all the lines in a window on the virtual screen */
X
Xupdall(wp)
X
XWINDOW *wp;	/* window to update lines in */
X
X{
X	register LINE *lp;	/* line to update */
X	register int sline;	/* physical screen line to update */
X	register int i;
X
X	/* search down the lines, updating them */
X	lp = wp->w_linep;
X	sline = wp->w_toprow;
X	while (sline < wp->w_toprow + wp->w_ntrows) {
X
X		/* and update the virtual line */
X		vscreen[sline]->v_flag |= VFCHG;
X		vscreen[sline]->v_flag &= ~VFREQ;
X		vtmove(sline, 0);
X		if (lp != wp->w_bufp->b_linep) {
X			/* if we are not at the end */
X			for (i=0; i < llength(lp); ++i)
X				vtputc(lgetc(lp, i));
X			lp = lforw(lp);
X		}
X
X		/* on to the next one */
X#if	COLOR
X		vscreen[sline]->v_rfcolor = wp->w_fcolor;
X		vscreen[sline]->v_rbcolor = wp->w_bcolor;
X#endif
X		vteeol();
X		++sline;
X	}
X
X}
X
X/*	updpos:	update the position of the hardware cursor and handle extended
X		lines. This is the only update for simple moves.	*/
X
Xupdpos()
X
X{
X	register LINE *lp;
X	register int c;
X	register int i;
X
X	/* find the current row */
X	lp = curwp->w_linep;
X	currow = curwp->w_toprow;
X	while (lp != curwp->w_dotp) {
X		++currow;
X		lp = lforw(lp);
X	}
X
X	/* find the current column */
X	curcol = 0;
X	i = 0;
X	while (i < curwp->w_doto) {
X		c = lgetc(lp, i++);
X		if (c == '\t')
X			curcol |= 0x07;
X		else
X			if (c < 0x20 || c == 0x7f)
X				++curcol;
X
X		++curcol;
X	}
X
X	/* if extended, flag so and update the virtual line image */
X	if (curcol >=  term.t_ncol - 1) {
X		vscreen[currow]->v_flag |= (VFEXT | VFCHG);
X		updext();
X	} else
X		lbound = 0;
X}
X
X/*	upddex:	de-extend any line that derserves it		*/
X
Xupddex()
X
X{
X	register WINDOW *wp;
X	register LINE *lp;
X	register int i,j;
X
X	wp = wheadp;
X
X	while (wp != NULL) {
X		lp = wp->w_linep;
X		i = wp->w_toprow;
X
X		while (i < wp->w_toprow + wp->w_ntrows) {
X			if (vscreen[i]->v_flag & VFEXT) {
X				if ((wp != curwp) || (lp != wp->w_dotp) ||
X				   (curcol < term.t_ncol - 1)) {
X					vtmove(i, 0);
X					for (j = 0; j < llength(lp); ++j)
X						vtputc(lgetc(lp, j));
X					vteeol();
X
X					/* this line no longer is extended */
X					vscreen[i]->v_flag &= ~VFEXT;
X					vscreen[i]->v_flag |= VFCHG;
X				}
X			}
X			lp = lforw(lp);
X			++i;
X		}
X		/* and onward to the next window */
X		wp = wp->w_wndp;
X	}
X}
X
X/*	updgar:	if the screen is garbage, clear the physical screen and
X		the virtual screen and force a full update		*/
X
Xupdgar()
X
X{
X	register char *txt;
X	register int i,j;
X
X	for (i = 0; i < term.t_nrow; ++i) {
X		vscreen[i]->v_flag |= VFCHG;
X#if	REVSTA
X		vscreen[i]->v_flag &= ~VFREV;
X#endif
X#if	COLOR
X		vscreen[i]->v_fcolor = gfcolor;
X		vscreen[i]->v_bcolor = gbcolor;
X#endif
X#if	MEMMAP == 0
X		txt = pscreen[i]->v_text;
X		for (j = 0; j < term.t_ncol; ++j)
X			txt[j] = ' ';
X#endif
X	}
X
X	movecursor(0, 0);		 /* Erase the screen. */
X	(*term.t_eeop)();
X	sgarbf = FALSE;			 /* Erase-page clears */
X	mpresf = FALSE;			 /* the message area. */
X#if	COLOR
X	mlerase();			/* needs to be cleared if colored */
X#endif
X}
X
X/*	updupd:	update the physical screen from the virtual screen	*/
X
Xupdupd(force)
X
Xint force;	/* forced update flag */
X
X{
X	register VIDEO *vp1;
X	register int i;
X
X	for (i = 0; i < term.t_nrow; ++i) {
X		vp1 = vscreen[i];
X
X		/* for each line that needs to be updated*/
X		if ((vp1->v_flag & VFCHG) != 0) {
X#if	TYPEAH
X			if (force == FALSE && typahead())
X				return(TRUE);
X#endif
X#if	MEMMAP
X			updateline(i, vp1);
X#else
X			updateline(i, vp1, pscreen[i]);
X#endif
X		}
X	}
X	return(TRUE);
X}
X
X/*	updext: update the extended line which the cursor is currently
X		on at a column greater than the terminal width. The line
X		will be scrolled right or left to let the user see where
X		the cursor is
X								*/
X
Xupdext()
X
X{
X	register int rcursor;	/* real cursor location */
X	register LINE *lp;	/* pointer to current line */
X	register int j;		/* index into line */
X
X	/* calculate what column the real cursor will end up in */
X	rcursor = ((curcol - term.t_ncol) % term.t_scrsiz) + term.t_margin;
X	taboff = lbound = curcol - rcursor + 1;
X
X	/* scan through the line outputing characters to the virtual screen */
X	/* once we reach the left edge					*/
X	vtmove(currow, -lbound);	/* start scanning offscreen */
X	lp = curwp->w_dotp;		/* line to output */
X	for (j=0; j<llength(lp); ++j)	/* until the end-of-line */
X		vtputc(lgetc(lp, j));
X
X	/* truncate the virtual line, restore tab offset */
X	vteeol();
X	taboff = 0;
X
X	/* and put a '$' in column 1 */
X	vscreen[currow]->v_text[0] = '$';
X}
X
X/*
X * Update a single line. This does not know how to use insert or delete
X * character sequences; we are using VT52 functionality. Update the physical
X * row and column variables. It does try an exploit erase to end of line. The
X * RAINBOW version of this routine uses fast video.
X */
X#if	MEMMAP
X/*	UPDATELINE specific code for the IBM-PC and other compatables */
X
Xupdateline(row, vp1)
X
Xint row;		/* row of screen to update */
Xstruct VIDEO *vp1;	/* virtual screen image */
X
X{
X#if	COLOR
X	scwrite(row, vp1->v_text, vp1->v_rfcolor, vp1->v_rbcolor);
X	vp1->v_fcolor = vp1->v_rfcolor;
X	vp1->v_bcolor = vp1->v_rbcolor;
X#else
X	if (vp1->v_flag & VFREQ)
X		scwrite(row, vp1->v_text, 0, 7);
X	else
X		scwrite(row, vp1->v_text, 7, 0);
X#endif
X	vp1->v_flag &= ~(VFCHG | VFCOL);	/* flag this line as changed */
X
X}
X
X#else
X
Xupdateline(row, vp1, vp2)
X
Xint row;		/* row of screen to update */
Xstruct VIDEO *vp1;	/* virtual screen image */
Xstruct VIDEO *vp2;	/* physical screen image */
X
X{
X#if RAINBOW
X/*	UPDATELINE specific code for the DEC rainbow 100 micro	*/
X
X    register char *cp1;
X    register char *cp2;
X    register int nch;
X
X    /* since we don't know how to make the rainbow do this, turn it off */
X    flags &= (~VFREV & ~VFREQ);
X
X    cp1 = &vp1->v_text[0];                    /* Use fast video. */
X    cp2 = &vp2->v_text[0];
X    putline(row+1, 1, cp1);
X    nch = term.t_ncol;
X
X    do
X        {
X        *cp2 = *cp1;
X        ++cp2;
X        ++cp1;
X        }
X    while (--nch);
X    *flags &= ~VFCHG;
X#else
X/*	UPDATELINE code for all other versions		*/
X
X	register char *cp1;
X	register char *cp2;
X	register char *cp3;
X	register char *cp4;
X	register char *cp5;
X	register int nbflag;	/* non-blanks to the right flag? */
X	int rev;		/* reverse video flag */
X	int req;		/* reverse video request flag */
X
X
X	/* set up pointers to virtual and physical lines */
X	cp1 = &vp1->v_text[0];
X	cp2 = &vp2->v_text[0];
X
X#if	COLOR
X	TTforg(vp1->v_rfcolor);
X	TTbacg(vp1->v_rbcolor);
X#endif
X
X#if	REVSTA | COLOR
X	/* if we need to change the reverse video status of the
X	   current line, we need to re-write the entire line     */
X	rev = (vp1->v_flag & VFREV) == VFREV;
X	req = (vp1->v_flag & VFREQ) == VFREQ;
X	if ((rev != req)
X#if	COLOR
X	    || (vp1->v_fcolor != vp1->v_rfcolor) || (vp1->v_bcolor != vp1->v_rbcolor)
X#endif
X#if	HP150
X	/* the HP150 has some reverse video problems */
X	    || req || rev
X#endif
X			) {
X		movecursor(row, 0);	/* Go to start of line. */
X		/* set rev video if needed */
X		if (rev != req)
X			(*term.t_rev)(req);
X
X		/* scan through the line and dump it to the screen and
X		   the virtual screen array				*/
X		cp3 = &vp1->v_text[term.t_ncol];
X		while (cp1 < cp3) {
X			TTputc(*cp1);
X			++ttcol;
X			*cp2++ = *cp1++;
X		}
X		/* turn rev video off */
X		if (rev != req)
X			(*term.t_rev)(FALSE);
X
X		/* update the needed flags */
X		vp1->v_flag &= ~VFCHG;
X		if (req)
X			vp1->v_flag |= VFREV;
X		else
X			vp1->v_flag &= ~VFREV;
X#if	COLOR
X		vp1->v_fcolor = vp1->v_rfcolor;
X		vp1->v_bcolor = vp1->v_rbcolor;
X#endif
X		return(TRUE);
X	}
X#endif
X
X	/* advance past any common chars at the left */
X	while (cp1 != &vp1->v_text[term.t_ncol] && cp1[0] == cp2[0]) {
X		++cp1;
X		++cp2;
X	}
X
X/* This can still happen, even though we only call this routine on changed
X * lines. A hard update is always done when a line splits, a massive
X * change is done, or a buffer is displayed twice. This optimizes out most
X * of the excess updating. A lot of computes are used, but these tend to
X * be hard operations that do a lot of update, so I don't really care.
X */
X	/* if both lines are the same, no update needs to be done */
X	if (cp1 == &vp1->v_text[term.t_ncol]) {
X 		vp1->v_flag &= ~VFCHG;		/* flag this line is changed */
X		return(TRUE);
X	}
X
X	/* find out if there is a match on the right */
X	nbflag = FALSE;
X	cp3 = &vp1->v_text[term.t_ncol];
X	cp4 = &vp2->v_text[term.t_ncol];
X
X	while (cp3[-1] == cp4[-1]) {
X		--cp3;
X		--cp4;
X		if (cp3[0] != ' ')		/* Note if any nonblank */
X			nbflag = TRUE;		/* in right match. */
X	}
X
X	cp5 = cp3;
X
X	/* Erase to EOL ? */
X	if (nbflag == FALSE && eolexist == TRUE && (req != TRUE)) {
X		while (cp5!=cp1 && cp5[-1]==' ')
X			--cp5;
X
X		if (cp3-cp5 <= 3)		/* Use only if erase is */
X			cp5 = cp3;		/* fewer characters. */
X	}
X
X	movecursor(row, cp1 - &vp1->v_text[0]);	/* Go to start of line. */
X#if	REVSTA
X	TTrev(rev);
X#endif
X
X	while (cp1 != cp5) {		/* Ordinary. */
X		TTputc(*cp1);
X		++ttcol;
X		*cp2++ = *cp1++;
X	}
X
X	if (cp5 != cp3) {		/* Erase. */
X		TTeeol();
X		while (cp1 != cp3)
X			*cp2++ = *cp1++;
X	}
X#if	REVSTA
X	TTrev(FALSE);
X#endif
X	vp1->v_flag &= ~VFCHG;		/* flag this line as updated */
X	return(TRUE);
X#endif
X}
X#endif
X
X/*
X * Redisplay the mode line for the window pointed to by the "wp". This is the
X * only routine that has any idea of how the modeline is formatted. You can
X * change the modeline format by hacking at this routine. Called by "update"
X * any time there is a dirty window.
X */
Xmodeline(wp)
X    WINDOW *wp;
X{
X    register char *cp;
X    register int c;
X    register int n;		/* cursor position count */
X    register BUFFER *bp;
X    register i;			/* loop index */
X    register lchar;		/* character to draw line in buffer with */
X    register firstm;		/* is this the first mode? */
X    char tline[NLINE];		/* buffer for part of mode line */
X
X    n = wp->w_toprow+wp->w_ntrows;      	/* Location. */
X    vscreen[n]->v_flag |= VFCHG | VFREQ | VFCOL;/* Redraw next time. */
X#if	COLOR
X    vscreen[n]->v_rfcolor = 0;			/* black on */
X    vscreen[n]->v_rbcolor = 7;			/* white.....*/
X#endif
X    vtmove(n, 0);                       	/* Seek to right line. */
X    if (wp == curwp)				/* mark the current buffer */
X	lchar = '=';
X    else
X#if	REVSTA
X	if (revexist)
X		lchar = ' ';
X	else
X#endif
X		lchar = '-';
X
X    vtputc(lchar);
X    bp = wp->w_bufp;
X
X    if ((bp->b_flag&BFCHG) != 0)                /* "*" if changed. */
X        vtputc('*');
X    else
X        vtputc(lchar);
X
X    n  = 2;
X    strcpy(tline, " MicroEMACS ");		/* Buffer name. */
X    strcat(tline, VERSION);
X    strcat(tline, " (");
X
X    /* display the modes */
X
X	firstm = TRUE;
X	for (i = 0; i < NUMMODES; i++)	/* add in the mode flags */
X		if (wp->w_bufp->b_mode & (1 << i)) {
X			if (firstm != TRUE)
X				strcat(tline, " ");
X			firstm = FALSE;
X			strcat(tline, modename[i]);
X		}
X	strcat(tline,") ");
X
X    cp = &tline[0];
X    while ((c = *cp++) != 0)
X        {
X        vtputc(c);
X        ++n;
X        }
X
X#if 0
X    vtputc(lchar);
X    vtputc((wp->w_flag&WFCOLR) != 0  ? 'C' : lchar);
X    vtputc((wp->w_flag&WFMODE) != 0  ? 'M' : lchar);
X    vtputc((wp->w_flag&WFHARD) != 0  ? 'H' : lchar);
X    vtputc((wp->w_flag&WFEDIT) != 0  ? 'E' : lchar);
X    vtputc((wp->w_flag&WFMOVE) != 0  ? 'V' : lchar);
X    vtputc((wp->w_flag&WFFORCE) != 0 ? 'F' : lchar);
X    vtputc(lchar);
X    n += 8;
X#endif
X
X    vtputc(lchar);
X    vtputc(lchar);
X    vtputc(' ');
X    n += 3;
X    cp = &bp->b_bname[0];
X
X    while ((c = *cp++) != 0)
X        {
X        vtputc(c);
X        ++n;
X        }
X
X    vtputc(' ');
X    vtputc(lchar);
X    vtputc(lchar);
X    n += 3;
X
X    if (bp->b_fname[0] != 0)            /* File name. */
X        {
X	vtputc(' ');
X	++n;
X        cp = "File: ";
X
X        while ((c = *cp++) != 0)
X            {
X            vtputc(c);
X            ++n;
X            }
X
X        cp = &bp->b_fname[0];
X
X        while ((c = *cp++) != 0)
X            {
X            vtputc(c);
X            ++n;
X            }
X
X        vtputc(' ');
X        ++n;
X        }
X
X    while (n < term.t_ncol)             /* Pad to full width. */
X        {
X        vtputc(lchar);
X        ++n;
X        }
X}
X
Xupmode()	/* update all the mode lines */
X
X{
X	register WINDOW *wp;
X
X	wp = wheadp;
X	while (wp != NULL) {
X		wp->w_flag |= WFMODE;
X		wp = wp->w_wndp;
X	}
X}
X
X/*
X * Send a command to the terminal to move the hardware cursor to row "row"
X * and column "col". The row and column arguments are origin 0. Optimize out
X * random calls. Update "ttrow" and "ttcol".
X */
Xmovecursor(row, col)
X    {
X    if (row!=ttrow || col!=ttcol)
X        {
X        ttrow = row;
X        ttcol = col;
X        TTmove(row, col);
X        }
X    }
X
X/*
X * Erase the message line. This is a special routine because the message line
X * is not considered to be part of the virtual screen. It always works
X * immediately; the terminal buffer is flushed via a call to the flusher.
X */
Xmlerase()
X    {
X    int i;
X    
X    movecursor(term.t_nrow, 0);
X#if	COLOR
X     TTforg(7);
X     TTbacg(0);
X#endif
X    if (eolexist == TRUE)
X	    TTeeol();
X    else {
X        for (i = 0; i < term.t_ncol - 1; i++)
X            TTputc(' ');
X        movecursor(term.t_nrow, 1);	/* force the move! */
X        movecursor(term.t_nrow, 0);
X    }
X    TTflush();
X    mpresf = FALSE;
X    }
X
X/*
X * Write a message into the message line. Keep track of the physical cursor
X * position. A small class of printf like format items is handled. Assumes the
X * stack grows down; this assumption is made by the "++" in the argument scan
X * loop. Set the "message line" flag TRUE.
X */
X
Xmlwrite(fmt, arg)
X    char *fmt;
X    {
X    register int c;
X    register char *ap;
X
X#if	COLOR
X	TTforg(7);
X	TTbacg(0);
X#endif
X    if (eolexist == FALSE) {
X        mlerase();
X        TTflush();
X    }
X
X    movecursor(term.t_nrow, 0);
X    ap = (char *) &arg;
X    while ((c = *fmt++) != 0) {
X        if (c != '%') {
X            TTputc(c);
X            ++ttcol;
X            }
X        else
X            {
X            c = *fmt++;
X            switch (c) {
X                case 'd':
X                    mlputi(*(int *)ap, 10);
X                    ap += sizeof(int);
X                    break;
X
X                case 'o':
X                    mlputi(*(int *)ap,  8);
X                    ap += sizeof(int);
X                    break;
X
X                case 'x':
X                    mlputi(*(int *)ap, 16);
X                    ap += sizeof(int);
X                    break;
X
X                case 'D':
X                    mlputli(*(long *)ap, 10);
X                    ap += sizeof(long);
X                    break;
X
X                case 's':
X                    mlputs(*(char **)ap);
X                    ap += sizeof(char *);
X                    break;
X
X		case 'f':
X		    mlputf(*(int *)ap);
X		    ap += sizeof(int);
X		    break;
X
X                default:
X                    TTputc(c);
X                    ++ttcol;
X                }
X            }
X        }
X    if (eolexist == TRUE)
X        TTeeol();
X    TTflush();
X    mpresf = TRUE;
X    }
X
X/*
X * Write out a string. Update the physical cursor position. This assumes that
X * the characters in the string all have width "1"; if this is not the case
X * things will get screwed up a little.
X */
Xmlputs(s)
X    char *s;
X    {
X    register int c;
X
X    while ((c = *s++) != 0)
X        {
X        TTputc(c);
X        ++ttcol;
X        }
X    }
X
X/*
X * Write out an integer, in the specified radix. Update the physical cursor
X * position.
X */
Xmlputi(i, r)
X    {
X    register int q;
X    static char hexdigits[] = "0123456789ABCDEF";
X
X    if (i < 0)
X        {
X        i = -i;
X        TTputc('-');
X        }
X
X    q = i/r;
X
X    if (q != 0)
X        mlputi(q, r);
X
X    TTputc(hexdigits[i%r]);
X    ++ttcol;
X    }
X
X/*
X * do the same except as a long integer.
X */
Xmlputli(l, r)
X    long l;
X    {
X    register long q;
X
X    if (l < 0)
X        {
X        l = -l;
X        TTputc('-');
X        }
X
X    q = l/r;
X
X    if (q != 0)
X        mlputli(q, r);
X
X    TTputc((int)(l%r)+'0');
X    ++ttcol;
X    }
X
X/*
X *	write out a scaled integer with two decimal places
X */
X
Xmlputf(s)
X
Xint s;	/* scaled integer to output */
X
X{
X	int i;	/* integer portion of number */
X	int f;	/* fractional portion of number */
X
X	/* break it up */
X	i = s / 100;
X	f = s % 100;
X
X	/* send out the integer portion */
X	mlputi(i, 10);
X	TTputc('.');
X	TTputc((f / 10) + '0');
X	TTputc((f % 10) + '0');
X	ttcol += 3;
X}	
X
X#if RAINBOW
X
Xputline(row, col, buf)
X    int row, col;
X    char buf[];
X    {
X    int n;
X
X    n = strlen(buf);
X    if (col + n - 1 > term.t_ncol)
X        n = term.t_ncol - col + 1;
X    Put_Data(row, col, n, buf);
X    }
X#endif
X
END_OF_display.c
if test 23829 -ne `wc -c <display.c`; then
    echo shar: \"display.c\" unpacked with wrong size!?
fi
# end of overwriting check
fi
echo shar: End of shell archive.
exit 0