Path: news.larc.nasa.gov!amiga-request
From: amiga-request@ab20.larc.nasa.gov (Amiga Sources/Binaries Moderator)
Subject: v91i188: BEAV 1.32 - Binary Editor and Viewer, Part09/11
Reply-To: pvr@wang.com (Peter Reilley)
Newsgroups: comp.sources.amiga
Message-ID: <comp.sources.amiga.v91i188@ab20.larc.nasa.gov>
References: <comp.sources.amiga.v91i180@ab20.larc.nasa.gov>
Date: 14 Nov 91 11:10:46 GMT
Approved: tadguy@uunet.UU.NET (Tad Guy)
X-Mail-Submissions-To: amiga@uunet.uu.net
X-Post-Discussions-To: comp.sys.amiga.misc

Submitted-by: pvr@wang.com (Peter Reilley)
Posting-number: Volume 91, Issue 188
Archive-name: utilities/beav-1.32/part09

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 9 (of 11)."
# Contents:  display.c
# Wrapped by tadguy@ab20 on Mon Nov 11 21:23:12 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'display.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'display.c'\"
else
echo shar: Extracting \"'display.c'\" \(30889 characters\)
sed "s/^X//" >'display.c' <<'END_OF_FILE'
X/*
X* The functions in this file handle redisplay. The
X* redisplay system knows almost nothing about the editing
X* process; the editing functions do, however, set some
X* hints to eliminate a lot of the grinding. There is more
X* that can be done; the "vtputc" interface is a real
X* pig.  The MEMMAP
X* changes things around for memory mapped video. With
X* both off, the terminal is a VT52.
X*/
X
X#include	<sys/types.h> 
X#include	<sys/stat.h> 
X#include    "def.h"
X
XD32 get_long ();
XD16 get_int ();
Xvoid writ_echo ();
Xvoid uline ();
Xvoid ucopy ();
Xvoid modeline ();
Xvoid bin_to_text ();
Xuint fill_buf ();
Xuint get_currow ();
Xuint get_curcol ();
X#if MSDOS
Xvoid    mem_line ();
X#endif
X
Xextern    char    MSG_prn_to[];
Xextern    char    MSG_disp_r_n[];
Xextern    char    MSG_11lX[];
Xextern    char    MSG_11lo[];
Xextern    char    MSG_11ld[];
Xextern    char    MSG_03o[];
Xextern    char    MSG_06o[];
Xextern    char    MSG_011lo[];
Xextern    char    MSG_03u[];
Xextern    char    MSG_05u[];
Xextern    char    MSG_010lu[];
Xextern    char    MSG_02X[];
Xextern    char    MSG_04X[];
Xextern    char    MSG_08lX[];
Xextern    char    MSG_prog_name[];
Xextern    char    MSG_disp_b_lst[];
Xextern    char    MSG_file[];
Xextern    char    MSG_RO[];
Xextern    char    MSG_WL[];
Xextern    char    MSG_RW[];
Xextern    char    MSG_AU[];
Xextern    char    MSG_NOT_AU[];
Xextern    char    MSG_curs_asc[];
Xextern    char    MSG_curs_ebc[];
Xextern    char    MSG_curs_hex[];
Xextern    char    MSG_curs_bin[];
Xextern    char    MSG_curs_dec[];
Xextern    char    MSG_curs_oct[];
Xextern    char    MSG_siz_8[];
Xextern    char    MSG_siz_16[];
Xextern    char    MSG_siz_32[];
Xextern    char    MSG_siz_null[];
Xextern    char    MSG_int_shift[];
Xextern    char    MSG_mot_shift[];
Xextern    char    MSG_print1[];
Xextern    char    MSG_print2[];
X#if RUNCHK
Xextern    char    ERR_disp_1[];
Xextern    char    ERR_disp_2[];
Xextern    char    ERR_disp_3[];
Xextern    char    ERR_disp_4[];
Xextern    char    ERR_disp_5[];
Xextern    char    ERR_disp_6[];
X#endif
X
Xextern char ebcdic_table[];
X
Xextern  bool    mem_map;
X
X/*
X* You can change these back to the types
X* implied by the name if you get tight for space. If you
X* make both of them "int" you get better code on the VAX.
X* They do nothing if this is not Gosling redisplay, except
X* for change the size of a structure that isn't used.
X* A bit of a cheat.
X*/
X#define XCHAR   int
X#define XSHORT  int
X
X/*
X* A video structure always holds
X* an array of characters whose length is equal to
X* the longest line possible. Only some of this is
X* used if "ncol" isn't the same as "NCOL".
X*/
Xtypedef struct vid
X{
X	short   v_hash;             /* Hash code, for compares.     */
X	short   v_flag;             /* Flag word.                   */
X	short   v_color;            /* Color of the line.           */
X	XSHORT v_cost;      /* Cost of display.     */
X	char    v_text[NCOL];       /* The actual characters.       */
X}                   VIDEO;
X
X#define VFCHG   0x0001          /* Changed.                     */
X#define VFHBAD  0x0002          /* Hash and cost are bad.       */
X
X/*
X* SCORE structures hold the optimal
X* trace trajectory, and the cost of redisplay, when
X* the dynamic programming redisplay code is used.
X* If no fancy redisplay, this isn't used. The trace index
X* fields can be "char", and the score a "short", but
X* this makes the code worse on the VAX.
X*/
Xtypedef struct
X{
X	XCHAR s_itrace;             /* "i" index for track back.    */
X	XCHAR s_jtrace;             /* "j" index for trace back.    */
X	XSHORT s_cost;              /* Display cost.                */
X}               SCORE;
X
Xint     sgarbf = TRUE;          /* TRUE if screen is garbage.   */
Xint     vtrow = 0;              /* Virtual cursor row.          */
Xint     vtcol = 0;              /* Virtual cursor column.       */
Xint     tthue = CNONE;          /* Current color.               */
Xint     ttrow = HUGE;           /* Physical cursor row.         */
Xint     ttcol = HUGE;           /* Physical cursor column.      */
Xint     tttop = HUGE;           /* Top of scroll region.        */
Xint     ttbot = HUGE;           /* Bottom of scroll region.     */
Xchar    file_off_bad = FALSE;   /* Have file offsets been changed */
X
XVIDEO * vscreen[NROW];          /* Edge vector, virtual.        */
XVIDEO * pscreen[NROW];          /* Edge vector, physical.       */
XVIDEO video[2 * (NROW)];        /* Actual screen data.          */
XVIDEO blanks;                   /* Blank line image.            */
X
X/*
X* Initialize the data structures used
X* by the display code. The edge vectors used
X* to access the screens are set up. The operating
X* system's terminal I/O channel is set up. Fill the
X* "blanks" array with ASCII blanks. The rest is done
X* at compile time. The original window is marked
X* as needing full update, and the physical screen
X* is marked as garbage, so all the right stuff happens
X* on the first call to redisplay.
X*/
Xvoid vtinit ()
X{
X	register    VIDEO * vp;
X	register int    i;
X
X	ttopen ();
X	ttinit ();
X	vp = &video[0];
X	for (i = 0; i < NROW; ++i)
X	{
X		vscreen[i] = vp;
X		++vp;
X		pscreen[i] = vp;
X		++vp;
X	}
X	blanks.v_color = CTEXT;
X	for (i = 0; i < NCOL; ++i)
X		blanks.v_text[i] = ' ';
X}
X
X/*
X* Tidy up the virtual display system
X* in anticipation of a return back to the host
X* operating system. Right now all we do is position
X* the cursor to the last line, erase the line, and
X* close the terminal channel.
X*/
Xvoid vttidy ()
X{
X	ttcolor (CTEXT);
X	ttnowindow ();              /* No scroll window.    */
X	ttmove (nrow - 1, 0);       /* Echo line.           */
X	tteeol ();
X	tttidy ();
X	ttflush ();
X	ttclose ();
X}
X
X/*
X* Move the virtual cursor to an origin
X* 0 spot on the virtual display screen. I could
X* store the column as a character pointer to the spot
X* on the line, which would make "vtputc" a little bit
X* more efficient. No checking for errors.
X*/
Xvoid vtmove (row, col)
X{
X	vtrow = row;
X	vtcol = col;
X}
X
X/*
X* Write a character to the virtual display,
X* dealing with long lines and the display of unprintable
X* things like control characters. Also expand tabs every 8
X* columns. This code only puts printing characters into
X* the virtual display image. Special care must be taken when
X* expanding tabs. On a screen whose width is not a multiple
X* of 8, it is possible for the virtual cursor to hit the
X* right margin before the next tab stop is reached. This
X* makes the tab code loop if you are not careful.
X* Three guesses how we found this.
X*/
Xvoid vtputc (c)
Xregister char   c;
X{
X	register    VIDEO * vp;
X
X	vp = vscreen[vtrow];
X	if (vtcol >= ncol)
X		vp -> v_text[ncol - 1] = '$';
X	else
X		if (ISCTRL (c) != FALSE)
X		{
X			vtputc ('^');
X			vtputc (c ^ 0x40);
X		}
X		else
X		{
X			vp -> v_text[vtcol] = c;
X			vtcol++;
X		}
X
X}
X/*
X* Write an entire screen line in the correct format.    pvr
X*
X* This code only puts printing characters into
X* the virtual display image.
X* Return TRUE if something was printed to the line.
X*/
X#define REGI  register
Xbool vtputd (wp, row)
XWINDOW * wp;
Xint     row;                    /* line # to print to v screen */
X
X{
X	REGI VIDEO * vp;
X	REGI char   mode;
X	REGI A32    row_offst;
X	REGI uint   chrs_per_row,
X	    lin_offset,
X	    i,
X	    chrs_in_lin;
X	LINE * cur_line;
X	static char w_buf[128];      /* temp buffer for data */
X
X	vp = vscreen[vtrow];        /* point to VIDEO structure to print into */
X	mode = R_TYPE(wp);          /* get type of format structure */
X
X	/* get number of bytes per row */
X	chrs_per_row = R_BYTES(wp);
X
X	/* determine the offset from begining of the buffer for this line */
X	row_offst = WIND_POS(wp) + (row * chrs_per_row);
X
X	/* search for and point to first character in buffer to be printed */
X	cur_line = wp -> w_linep;   /* start with current first window line */
X	while (TRUE)
X	{                       /* find line with desired character */
X		if (cur_line == wp -> w_bufp -> b_linep)
X		{                   /* at end of buffer? */
X			return (FALSE);
X		}
X		if (cur_line -> l_file_offset > row_offst)
X		{
X			/* if less than current line */
X			cur_line = cur_line -> l_bp;/* step back */
X		}
X		else
X			if ((cur_line -> l_file_offset + cur_line -> l_used) <= row_offst)
X			{
X				cur_line = cur_line -> l_fp;/* step ahead */
X			}
X			else
X				break;
X	}
X
X	lin_offset = row_offst - cur_line -> l_file_offset;/* offset into line */
X
X	/* get index into the current line to start reading the current row's data */
X	/* copy line text into buffer */
X	chrs_in_lin = fill_buf (wp, cur_line, lin_offset, w_buf, chrs_per_row);
X
X	/* limit line length to screen width, used in TEXT mode only */
X	if (chrs_in_lin > NCOL)
X		chrs_in_lin = NCOL;
X
X	/* Clear the line to spaces */
X	for (i = 0; i < NCOL; i++)
X	{
X		vp -> v_text[i] = ' ';
X	}
X	switch (mode)
X	{
X	case TEXT:
X		break;
X	case ASCII:
X	case EBCDIC:
X	case BINARY:
X	case HEX:
X		/* print the row offset from the start of the file in HEX */
X		sprintf (vp -> v_text, MSG_11lX, row_offst);/* to vid buf */
X		break;
X	case OCTAL:
X		/* print the row offset from the start of the file */
X		sprintf (vp -> v_text, MSG_11lo, row_offst);/* to vid buf */
X		break;
X	case DECIMAL:
X		/* print the row offset from the start of the file */
X		sprintf (vp -> v_text, MSG_11ld, row_offst);/* to vid buf */
X		break;
X#if RUNCHK
X	default:
X		writ_echo (ERR_disp_1);
X		break;
X#endif
X	}
X
X	/* print the binary data to the text line */
X	bin_to_text (w_buf, vp -> v_text, chrs_in_lin,
X	    wp -> w_fmt_ptr);
X
X	vtcol = NCOL;
X	return (TRUE);
X}
X
X/*
X*   Print the contents of then binary data buffer bin_buf
X*   into the proper mode of text into txt_buf.
X*   Process 'len' bytes.
X*
X*   input:
X*           bin_buf     pointer to buffer of binary data to process.
X*           txt_buf     pointer to output buffer to print text result into.
X*           len         length in bytes of data in bin_buf to process.
X*           fmt_ptr     pointer to a ROW_FMT to use to format the data
X*                       conversion and printing process.
X*   output:
X*           none.       
X*/
X
Xvoid bin_to_text (bin_buf, txt_buf, len, fmt_ptr)
X
Xchar   *bin_buf,
X*txt_buf;
Xuint    len;
XROW_FMT *fmt_ptr;
X
X{
X	uchar   i,
X	    ch,
X	    k,
X	    j,
X	    mode,
X	    size,
X	    *posn;
X	uint    temp_int;
X	ulong   temp_long;
X
X	mode = fmt_ptr -> r_type;   /* get type of format structure */
X	size = fmt_ptr -> r_size;   /* get size of format structure */
X	posn = fmt_ptr -> r_positions;/* pointer to array of display positions */
X
X	switch (mode)
X	{
X	case TEXT:
X	case ASCII:
X		for (i = 0; i < len; i++)
X		{
X			ch = bin_buf[i];
X			if ((ch >= ' ') && (ch < 0x7f))
X				txt_buf[posn[0] + i] = ch;
X			else
X				txt_buf[posn[0] + i] = '.';
X		}
X		break;
X
X	case EBCDIC:
X		for (i = 0; i < len; i++)
X		{
X			txt_buf[posn[0] + i] =
X			    0xff & ebcdic_table[0xff & bin_buf[i]];
X		}
X		break;
X
X	case OCTAL:
X		switch (size)
X		{
X		case BYTES:     /* print octal bytes */
X			for (i = 0; i < len; i++)
X			{
X				sprintf (&txt_buf[
X                                    posn[i]], MSG_03o, 0xff & bin_buf[i]);
X			}
X			break;
X
X		case WORDS:     /* print octal words */
X			k = 0;
X			for (i = 0; i < len;
X			    i += 2)
X			{
X				temp_int = get_int (&bin_buf[i]);
X				sprintf (&txt_buf[posn[k++]], MSG_06o, temp_int);
X			}
X			break;
X
X		case DWORDS:    /* print octal double words */
X			k = 0;
X			for (i = 0; i < len;
X			    i += 4)
X			{
X				temp_long = get_long (&bin_buf[i]);
X				sprintf (&txt_buf[posn[k++]], MSG_011lo, temp_long);
X			}
X			break;
X		}
X		break;
X
X	case DECIMAL:
X		switch (size)
X		{
X		case BYTES:     /* print decimal bytes */
X			for (i = 0; i < len; i++)
X			{
X				sprintf (&txt_buf[
X                                    posn[i]], MSG_03u, 0xff & bin_buf[i]);
X			}
X			break;
X
X		case WORDS:     /* print decimal words */
X			k = 0;
X			for (i = 0; i < len;
X			    i += 2)
X			{
X				temp_int = get_int (&bin_buf[i]);
X				sprintf (&txt_buf[
X                                    posn[k++]], MSG_05u, temp_int);
X			}
X			break;
X
X		case DWORDS:    /* print decimal double words */
X			k = 0;
X			for (i = 0; i < len; i += 4)
X			{
X				temp_long = get_long (&bin_buf[i]);
X				sprintf (&txt_buf[
X                                    posn[k++]], MSG_010lu, temp_long);
X			}
X			break;
X		}
X		break;
X
X	case HEX:
X		switch (size)
X		{
X		case BYTES:     /* print hex bytes and ascii chars */
X			for (i = 0; i < len; i++)
X			{
X				if ((bin_buf[i] >= ' ') && (bin_buf[i] < 0x7f))
X					txt_buf[posn[i + 16]] = 0xff & bin_buf[i];
X				else
X					txt_buf[posn[i + 16]] = '.';
X				sprintf (&txt_buf[posn[i]], MSG_02X, 0xff & bin_buf[i]);
X			}
X			break;
X
X		case WORDS:     /* print hex words */
X			k = 0;
X			for (i = 0; i < len; i += 2)
X			{
X				temp_int = get_int (&bin_buf[i]);
X				sprintf (&txt_buf[
X                                    posn[k++]], MSG_04X, temp_int);
X			}
X			break;
X
X		case DWORDS:    /* print hex double words */
X			k = 0;
X			for (i = 0; i < len; i += 4)
X			{
X				temp_long = get_long (&bin_buf[i]);
X				sprintf (&txt_buf[
X                                    posn[k++]], MSG_08lX, temp_long);
X			}
X			break;
X		}
X		break;
X
X	case BINARY:
X		switch (size)
X		{
X		case BYTES:     /* print binary bits */
X			for (i = 0; i < len; i++)
X			{
X				ch = bin_buf[i];/* get char to convert */
X				for (k = 0; k < 8; k++)
X				{
X					if (ch & 0x80)
X						txt_buf[posn[i] + k]
X						    = '1';
X					else
X						txt_buf[posn[i] + k]
X						    = '0';
X					ch = ch << 1;/* slide next bit into place */
X				}
X			}
X			break;
X
X		case WORDS:
X			j = 0;
X			for (i = 0; i < len; i += 2)
X			{
X				temp_int = get_int (&bin_buf[i]);
X
X				for (k = 0; k < 16; k++)
X				{
X					if (temp_int & 0x8000)
X						txt_buf[posn[j] + k]
X						    = '1';
X					else
X						txt_buf[posn[j] + k]
X						    = '0';
X					temp_int = temp_int << 1;
X					/* slide next bit into place */
X				}
X				j++;
X			}
X			break;
X
X		case DWORDS:
X			j = 0;
X			for (i = 0; i < len; i += 4)
X			{
X				temp_long = get_long (&bin_buf[i]);
X				for (k = 0; k < 32; k++)
X				{
X					if (temp_long & 0x80000000)
X						txt_buf[posn[j] + k]
X						    = '1';
X					else
X						txt_buf[posn[j] + k]
X						    = '0';
X					temp_long = temp_long << 1;
X					/* slide next bit into place */
X				}
X				j++;
X			}
X			break;
X		}
X		break;
X#if RUNCHK
X	default:
X		writ_echo (ERR_disp_2);
X		break;
X#endif
X	}
X	len *= (fmt_ptr -> r_chr_per_u + 1);
X	/* Clean up any garbage characters left by the sprintf's */
X	for (i = 0; i < NCOL; i++)
X	{
X		if (txt_buf[i] == 0)
X			txt_buf[i] = ' ';
X	}
X}
X
X/*
X*   Get an int from the buffer.
X*   Perform the Intel byte shuffle if necessary
X*/
X
XD16 get_int (w_buf)
Xuchar  *w_buf;
X
X{
X	int     temp_int;
X
X	if (curwp -> w_intel_mode)
X	{
X		temp_int = 0xff & w_buf[1];
X		temp_int <<= 8;
X		temp_int |= 0xff & w_buf[0];
X	}
X	else
X	{
X		temp_int = 0xff & w_buf[0];
X		temp_int <<= 8;
X		temp_int |= 0xff & w_buf[1];
X	}
X	return (temp_int);
X}
X
X/*
X*   Get an long from the buffer.
X*   Perform the Intel byte shuffle if necessary
X*/
X
XD32 get_long (w_buf)
Xuchar  *w_buf;
X
X{
X	long    temp_long;
X
X	if (curwp -> w_intel_mode)
X	{
X		temp_long = 0xff & w_buf[3];
X		temp_long <<= 8;
X		temp_long |= 0xff & w_buf[2];
X		temp_long <<= 8;
X		temp_long |= 0xff & w_buf[1];
X		temp_long <<= 8;
X		temp_long |= 0xff & w_buf[0];
X	}
X	else
X	{
X		temp_long = 0xff & w_buf[0];
X		temp_long <<= 8;
X		temp_long |= 0xff & w_buf[1];
X		temp_long <<= 8;
X		temp_long |= 0xff & w_buf[2];
X		temp_long <<= 8;
X		temp_long |= 0xff & w_buf[3];
X	}
X	return (temp_long);
X}
X
X
X/*
X*   Copy a length of bytes from the buffer LINEs into the designated
X*   buffer.   If the current LINE does not have enough bytes then
X*   advance to the next.   Return the actual number of bytes copied.
X*   The number copied would be less than the number requested if
X*   end of file is reached.
X*/
X
Xuint    fill_buf (wp, lin, lin_off, w_buff, cnt)
XWINDOW  *wp;
XLINE    *lin;
Xuint    lin_off,
Xcnt;
Xchar    *w_buff;
X{
X	REGI uint   src,
X	    dest,
X	    i;
X
X	src = lin_off;              /* initialize source line index */
X	dest = 0;                   /* initialize destination buffer index */
X
X	while (TRUE)
X	{
X		while (src < lin -> l_used)
X		{
X			w_buff[dest++] = lin -> l_text[src++];/* copy byte */
X
X			if (dest == cnt)
X			{               /* if done */
X				return (cnt);   /* then leave */
X			}
X		}
X		if (R_TYPE(wp) == TEXT)
X			return (dest);   /* in text mode don't advance to next line */
X
X		lin = lin -> l_fp;      /* move to the next line */
X		if (lin == wp -> w_bufp -> b_linep)
X		{                   /* if past last line */
X			{
X			for (i = dest; i < cnt; ++i)
X				w_buff[i] = 0;/* fill rest of buffer with zeros */
X			return (dest);  /* return number of chars copied */
X		}
X	}
X	src = 0;                /* start next LINE at first byte */
X}
Xreturn (0);
X}
X
X/*
X* Erase from the end of the
X* software cursor to the end of the
X* line on which the software cursor is
X* located. The display routines will decide
X* if a hardware erase to end of line command
X* should be used to display this.
X*/
Xvoid vteeol ()
X{
X	register    VIDEO * vp;
X
X	vp = vscreen[vtrow];
X	while (vtcol < ncol)
X		vp -> v_text[vtcol++] = ' ';
X}
X
X/*
X* Make sure that the display is
X* right. This is a three part process. First,
X* scan through all of the windows looking for dirty
X* ones. Check the framing, and refresh the screen.
X* Second, make the
X* virtual and physical screens the same.
X*/
Xvoid update ()
X{
X	register    WINDOW * wp;
X	register    VIDEO * vp1;
X	register    VIDEO * vp2;
X	register uint    i;
X	register int    hflag;
X
X	hflag = FALSE;              /* Not hard.            */
X	wp = wheadp;
X	while (wp != NULL)
X	{
X		/* is this window to be displayed in linked mode */
X		if ((curbp -> b_flag & BFLINK) &&
X		    (wp -> w_bufp == curbp))
X		{                   /* move dot to current window's dot position */
X			wp -> w_dotp = curwp -> w_dotp;
X			wp -> w_doto = curwp -> w_doto;
X			move_ptr (wp, 0L, TRUE, TRUE, TRUE); /* insure dot is aligned */
X			wind_on_dot (wp);   /* move window to new dot position */
X		}
X
X		if (wp -> w_flag != 0)
X
X		{                   /* Need update.         */
X			move_ptr (wp, 0L, FALSE, TRUE, TRUE); /* window on row boundary */
X			move_ptr (wp, 0L, TRUE, TRUE, TRUE); /* dot on unit boundary */
X			if ((wp -> w_flag & WFFORCE) == 0)
X			{
X				wind_on_dot (wp);/* position window on dot */
X			}
X			i = get_currow (wp); /* Redo this one line, mabey.    */
X			if ((wp -> w_flag & ~WFMODE) == WFEDIT)
X			{
X				vscreen[i] -> v_color = CTEXT;
X				vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
X				vtmove (i, 0);
X				vtputd (wp, i - wp -> w_toprow);/* print line to the screen */
X			}
X			else
X				if ((wp -> w_flag & ~WFMODE) == WFMOVE)
X				{
X					while (i < wp -> w_toprow + wp -> w_ntrows)
X					{
X						/* paint entire window */
X						vscreen[i] -> v_color = CTEXT;
X						vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
X						vtmove (i, 0);
X						/* print line to the screen */
X						if (!vtputd (wp, i - wp -> w_toprow))
X							vteeol ();
X						++i;
X					}
X				}
X				else
X					if ((wp -> w_flag & (WFEDIT | WFHARD)) != 0)
X					{
X						hflag = TRUE;
X						i = wp -> w_toprow;
X						while (i < wp -> w_toprow + wp -> w_ntrows)
X						{
X							/* paint entire window */
X							vscreen[i] -> v_color = CTEXT;
X							vscreen[i] -> v_flag |= (VFCHG | VFHBAD);
X							vtmove (i, 0);
X							/* print line to the screen */
X							if (!vtputd (wp, i - wp -> w_toprow))
X								vteeol ();
X							++i;
X						}
X					}
X			if ((wp -> w_flag & WFMODE) ||
X			    (wp -> w_flag & WFMOVE) ||
X			    (wp -> w_flag & WFHARD))
X				modeline (wp);
X			wp -> w_flag = 0;
X		}
X		wp = wp -> w_wndp;
X	}
X	if (sgarbf != FALSE)
X	{                       /* Screen is garbage.   */
X		sgarbf = FALSE;         /* Erase-page clears    */
X		epresf = FALSE;         /* the message area.    */
X		tttop = HUGE;           /* Forget where you set */
X		ttbot = HUGE;           /* scroll region.       */
X		tthue = CNONE;          /* Color unknown.       */
X		ttmove (0, 0);
X		tteeop ();
X#if MSDOS
X		if (mem_map)
X		{
X			for (i = 0; i < nrow; ++i)
X			{
X				mem_line (i, vscreen[i]);
X			}
X		}
X		else
X		{
X#endif
X			for (i = 0; i < nrow; ++i)
X			{
X				uline (i, vscreen[i], &blanks);
X				ucopy (vscreen[i], pscreen[i]);
X			}
X#if MSDOS
X		}
X#endif
X		ttmove (get_currow (curwp), get_curcol (curwp));
X		ttflush ();
X		return;
X	}
X	for (i = 0; i < nrow; ++i)
X	{                       /* Easy update.         */
X		vp1 = vscreen[i];
X		vp2 = pscreen[i];
X		if ((vp1 -> v_flag & VFCHG) != 0)
X		{
X#if MSDOS
X			if (mem_map)
X				mem_line (i, vp1);
X			else
X#endif
X				{
X					uline (i, vp1, vp2);
X					ucopy (vp1, vp2);
X				}
X		}
X	}
X	ttmove (get_currow (curwp), get_curcol (curwp));
X	ttflush ();
X}
X/*
X*   Get the window relative row in which the cursor will
X*   appear. pvr
X*/
Xuint    get_currow (wp)
XWINDOW * wp;
X{
X	A32    row;
X	/* number of bytes from start of window */
X	row = DOT_POS(wp) - WIND_POS(wp);
X	/* number of rows down in window */
X	row /= R_BYTES(wp);
X	row += wp -> w_toprow;
X#if RUNCHK
X	if (row < wp -> w_toprow)
X		printf (ERR_disp_3);
X	if (row > (wp -> w_ntrows + wp -> w_toprow))
X		printf (ERR_disp_4);
X#endif
X	return (row & 0xffff);
X}
X
X/*
X*   Get the window relative column in which the cursor will
X*   appear. pvr
X*/
Xuint    get_curcol (wp)
XWINDOW * wp;
X{
X	long    offset,
X	index;
X	uint    b_per_u, pos;
X
X	b_per_u = R_B_PER_U(wp);
X	/* dot offset from start of buffer */
X	offset = DOT_POS(wp);
X	offset -= wp -> w_disp_shift;
X	offset &= ~(b_per_u - 1);
X	/* calculate mod of the current file position */
X	index = offset & (R_BYTES(wp) - 1);
X	index /= b_per_u;
X	/* limit to window width */
X	if (index >= NCOL)
X		index = NCOL;
X	pos = wp -> w_fmt_ptr -> r_positions[index] + wp -> w_unit_offset;
X	return (pos);
X}
X#if MSDOS
Xvoid    mem_line (row, vvp)
Xint     row;
XVIDEO * vvp;
X{
X	vvp -> v_flag &= ~VFCHG;    /* Changes done.        */
X	ttcolor (vvp -> v_color);
X	putline (row + 1, 1, ncol, &vvp -> v_text[0]);
X}
X#endif
X/*
X* Update a saved copy of a line,
X* kept in a VIDEO structure. The "vvp" is
X* the one in the "vscreen". The "pvp" is the one
X* in the "pscreen". This is called to make the
X* virtual and physical screens the same when
X* display has done an update.
X*/
Xvoid ucopy (vvp, pvp)
Xregister    VIDEO * vvp;
Xregister    VIDEO * pvp;
X{
X	register int    i;
X
X	vvp -> v_flag &= ~VFCHG;    /* Changes done.        */
X	pvp -> v_flag = vvp -> v_flag;/* Update model.        */
X	pvp -> v_hash = vvp -> v_hash;
X	pvp -> v_cost = vvp -> v_cost;
X	pvp -> v_color = vvp -> v_color;
X	for (i = 0; i < ncol; ++i)
X		pvp -> v_text[i] = vvp -> v_text[i];
X}
X
X/*
X* Update a single line. This routine only
X* uses basic functionality (no insert and delete character,
X* but erase to end of line). The "vvp" points at the VIDEO
X* structure for the line on the virtual screen, and the "pvp"
X* is the same for the physical screen. Avoid erase to end of
X* line when updating CMODE color lines, because of the way that
X* reverse video works on most terminals.
X*/
Xvoid uline (row, vvp, pvp)
XVIDEO * vvp;
XVIDEO * pvp;
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;
X
X	if (vvp -> v_color != pvp -> v_color)
X	{                       /* Wrong color, do a    */
X		ttmove (row, 0);        /* full redraw.         */
X		ttcolor (vvp -> v_color);
X		cp1 = &vvp -> v_text[0];
X		cp2 = &vvp -> v_text[ncol];
X		while (cp1 != cp2)
X		{
X			ttputc (*cp1++);
X			++ttcol;
X		}
X		return;
X	}
X	cp1 = &vvp -> v_text[0];    /* Compute left match.  */
X	cp2 = &pvp -> v_text[0];
X	while (cp1 != &vvp -> v_text[ncol] && cp1[0] == cp2[0])
X	{
X		++cp1;
X		++cp2;
X	}
X	if (cp1 == &vvp -> v_text[ncol])/* All equal.           */
X		return;
X	nbflag = FALSE;
X	cp3 = &vvp -> v_text[ncol]; /* Compute right match. */
X	cp4 = &pvp -> v_text[ncol];
X	while (cp3[-1] == cp4[-1])
X	{
X		--cp3;
X		--cp4;
X		if (cp3[0] != ' ')      /* Note non-blanks in   */
X			nbflag = TRUE;      /* the right match.     */
X	}
X	cp5 = cp3;                  /* Is erase good?       */
X	if (nbflag == FALSE && vvp -> v_color == CTEXT)
X	{
X		while (cp5 != cp1 && cp5[-1] == ' ')
X			--cp5;
X		/* Alcyon hack */
X		if ((int) (cp3 - cp5) <= tceeol)
X			cp5 = cp3;
X	}
X	/* Alcyon hack */
X	ttmove (row, (int) (cp1 - &vvp -> v_text[0]));
X	ttcolor (vvp -> v_color);
X	while (cp1 != cp5)
X	{
X		ttputc (*cp1++);
X		++ttcol;
X	}
X	if (cp5 != cp3)             /* Do erase.            */
X		tteeol ();
X}
X
X/*
X* Redisplay the mode line for
X* the window pointed to by the "wp".
X* This is the only routine that has any idea
X* of how the modeline is formatted. You can
X* change the modeline format by hacking at
X* this routine. Called by "update" any time
X* there is a dirty window.
X*/
X
Xvoid modeline (wp)
Xregister    WINDOW * wp;
X{
X	register char  *cp,
X	mode,
X	size,
X	u_posn,
X	*s;
X	register char   c;
X	register int    n;
X	register    BUFFER * bp;
X	register    A32 posn;
X
X	static char posn_buf[30] =
X	{
X		0
X	};                          /* krw */
X
X	mode = wp -> w_fmt_ptr -> r_type;/* get type of format structure */
X	size = wp -> w_fmt_ptr -> r_size;/* get size of format structure */
X
X	n = wp -> w_toprow + wp -> w_ntrows;/* Location.            */
X	vscreen[n] -> v_color = CMODE;/* Mode line color.     */
X	vscreen[n] -> v_flag |= (VFCHG | VFHBAD);/* Recompute, display.  */
X	vtmove (n, 0);              /* Seek to right line.  */
X	bp = wp -> w_bufp;
X
X	cp = MSG_prog_name;               /* Program name.  pvr    */
X	n = 5;
X	while ((c = *cp++) != 0)
X	{
X		vtputc (c);
X		++n;
X	}
X
X	if ((bp -> b_flag & BFBAD) != 0)/* "?" if trashed.      */
X		vtputc ('?');
X	else
X		vtputc (' ');
X
X	if ((bp -> b_flag & BFCHG) != 0)/* "*" if changed.      */
X		vtputc ('*');
X	else
X		vtputc (' ');
X
X	if (insert_mode)            /* "I" if insert mode  */
X		vtputc ('I');
X	else
X		vtputc ('O');
X
X	if (bp == blistp)
X	{                       /* special list */
X		cp = MSG_disp_b_lst;
X		while ((c = *cp++) != 0)
X		{
X			vtputc (c);
X			++n;
X		}
X		goto pad;
X	}
X
X	/* Buffer name */
X	vtputc (' ');
X	++n;
X	cp = &bp -> b_bname[0];
X	while ((c = *cp++) != 0)
X	{
X		vtputc (c);
X		++n;
X	}
X	while ((int) (cp - &bp -> b_bname[0]) < NBUFN)
X	{
X		vtputc (' ');
X		n++;
X		cp++;
X	}
X
X	/* File name.           */
X	vtputc (' ');
X	++n;
X	cp = MSG_file;
X	while ((c = *cp++) != 0)
X	{
X		vtputc (c);
X		++n;
X	}
X	cp = &bp -> b_fname[0];
X	while ((c = *cp++) != 0)
X	{
X		vtputc (c);
X		++n;
X	}
X	cp--;
X	while ((int) (cp - &bp -> b_fname[0]) < NFILE)
X	{
X		vtputc (' ');
X		n++;
X		cp++;
X	}
X
X	if (bp -> b_flag & BFVIEW)
X		s = MSG_RO;
X	else if (bp -> b_flag & BFSLOCK)
X		s = MSG_WL;
X	else
X		s = MSG_RW;
X
X	while (*s)
X	{                       /* krw */
X		vtputc (*s++);
X		++n;
X	}
X
X	if (auto_update && !(bp -> b_flag & BFVIEW) && bp -> b_bname[0])/* jam */
X		s = MSG_AU;
X	else
X		s = MSG_NOT_AU;
X	for (; *s && n < NCOL;)
X	{
X		vtputc (*s++);
X		++n;
X	}
X
X	/* Insert current dot position into mode line. */
X	posn = DOT_POS(wp);
X	u_posn = R_CHR_PER_U(wp) - wp -> w_unit_offset - 1;
X	if (u_posn < 0)
X		u_posn = 0;
X	switch (mode)
X	{
X	case TEXT:
X	case ASCII:
X		sprintf (posn_buf, MSG_curs_asc, posn);
X		break;
X	case EBCDIC:
X		sprintf (posn_buf, MSG_curs_ebc, posn);
X		break;
X	case HEX:
X		sprintf (posn_buf, MSG_curs_hex, posn, u_posn);
X		break;
X	case BINARY:
X		sprintf (posn_buf, MSG_curs_bin, posn, u_posn);
X		break;
X	case DECIMAL:
X		sprintf (posn_buf, MSG_curs_dec, posn, u_posn);
X		break;
X	case OCTAL:
X		sprintf (posn_buf, MSG_curs_oct, posn, u_posn);
X		break;
X#if RUNCHK
X	default:
X		writ_echo (ERR_disp_5);
X		break;
X#endif
X	}
X
X	cp = posn_buf;
X	while ((c = *cp++) != 0)
X	{
X		vtputc (c);
X		++n;
X	}
X
X
X	if ((mode == HEX) ||
X	    (mode == DECIMAL) ||
X	    (mode == OCTAL))
X	{
X		switch (size)
X		{
X		case BYTES:
X			sprintf (posn_buf, MSG_siz_8);
X			break;
X		case WORDS:
X			sprintf (posn_buf, MSG_siz_16);
X			break;
X		case DWORDS:
X			sprintf (posn_buf, MSG_siz_32);
X			break;
X#if RUNCHK
X		default:
X			writ_echo (ERR_disp_6);
X			break;
X#endif
X		}
X	}
X	else
X		sprintf (posn_buf, MSG_siz_null);
X
X	cp = posn_buf;
X	while ((c = *cp++) != 0)
X	{
X		vtputc (c);
X		++n;
X	}
X
X	if (wp -> w_intel_mode)
X		sprintf (posn_buf, MSG_int_shift, wp -> w_disp_shift);
X	else
X		sprintf (posn_buf, MSG_mot_shift, wp -> w_disp_shift);
X	cp = posn_buf;
X	while ((c = *cp++) != 0)
X	{
X		vtputc (c);
X		++n;
X	}
X
X
X	/* pad out */
Xpad:
X	while (n < ncol)
X	{
X		vtputc (' ');
X		++n;
X	}
X}
X
X/*
X* write text to the echo line 
X*/
Xvoid    writ_echo (buf)
Xchar    *buf;
X{
X	int     i;
X	char    *vpp;
X	bool    fill_spac;
X
X	fill_spac = FALSE;
X	vpp = vscreen[nrow - 1] -> v_text;
X	vscreen[nrow - 1] -> v_color = CTEXT;
X	vscreen[nrow - 1] -> v_flag |= VFCHG;
X	epresf = TRUE;
X
X	for (i = 0; i < NCOL; i++)
X	{
X		if (buf[i] == 0)
X			fill_spac = TRUE;
X		if (fill_spac)
X			vpp[i] = ' ';
X		else 
X			vpp[i] = buf[i];
X	}
X#if MSDOS
X	if (mem_map)
X	{
X		mem_line (nrow - 1, vscreen[nrow - 1]);
X	}
X	else
X#endif
X		{
X			uline (nrow - 1, vscreen[nrow - 1], pscreen[nrow - 1]);
X			uline (nrow - 1, vscreen[nrow - 1], &blanks);
X			ucopy (vscreen[nrow - 1], pscreen[nrow - 1]);
X			ttflush ();
X		}
X}
X
X/*
X* Print the current buffer from mark to dot using the 
X* current window's display format.
X* Prompt for file name or io device to print to.
X*/
X
Xbool    print ()
X{
X	LINE    *dot_l_sav, *mark_l_sav, *wind_l_sav;
X	int     dot_off_sav, mark_off_sav, wind_off_sav, i;
X	char   s;
X	char    fname[NFILEN];
X	register int    nline;
X	char    buf[NFILEN], buf1[NFILEN];
X
X	/* save the original window state */
X	dot_l_sav = curwp -> w_dotp;
X	dot_off_sav = curwp -> w_doto;
X	mark_l_sav = curwp -> w_markp;
X	mark_off_sav = curwp -> w_marko;
X	wind_l_sav = curwp -> w_linep;
X	wind_off_sav = curwp -> w_loff;
X
X	/* if mark is not set then set it to location zero */
X	if (curwp -> w_markp == NULL)
X	{
X		curwp -> w_markp = curwp -> w_bufp -> b_linep -> l_fp;
X		curwp -> w_marko = 0;
X	}
X
X	nline = 0;
X	if ((s = ereply (MSG_prn_to, fname, NFILEN, NULL)) == ABORT)
X		return (s);
X	adjustcase (fname);
X	if ((s = ffwopen (fname, S_IREAD | S_IWRITE)) != FIOSUC)/* Open writes message. */
X		return (FALSE);
X
X	sprintf (buf, MSG_print1, fname);
X	writ_echo (buf);
X	/* make dot before mark */
X	if (DOT_POS(curwp) > MARK_POS(curwp))
X		swapmark ();    /* make mark first */
X
X	while (DOT_POS(curwp) <= MARK_POS(curwp))
X	{
X		/* check if we should quit */
X		if (ttkeyready ())
X		{
X			if (ttgetc () == CTL_G)   /* quit if abort was hit */
X				break;
X		}
X		nline++;
X		/* move window so that first line is on dot */
X		move_ptr (curwp, DOT_POS(curwp), FALSE, TRUE, FALSE);
X
X		if (vtputd (curwp, 0))   /* print line into video buffer */
X		{
X			for (i = NCOL; (vscreen[vtrow] -> v_text[i] < '!') ||
X			    (vscreen[vtrow] -> v_text[i] > '~'); i--)
X				;
X			i++;
X			if ((s = ffputline (vscreen[vtrow] -> v_text, i)) != FIOSUC)
X				break;
X			if ((s = ffputline (MSG_disp_r_n, 2)) != FIOSUC)
X				break;
X		}
X		else
X			break;
X		forwline (0, 1, KRANDOM);   /* advance to next line */
X	}
X	ffclose ();
X	sprintf (buf1, MSG_print2, R_POS_FMT(curwp));
X	sprintf (buf, buf1, (long) nline);
X	writ_echo (buf);
X
X	/* restore the original window state */
X	curwp -> w_dotp = dot_l_sav;
X	curwp -> w_doto = dot_off_sav;
X	curwp -> w_markp = mark_l_sav;
X	curwp -> w_marko = mark_off_sav;
X	curwp -> w_linep = wind_l_sav;
X	curwp -> w_loff = wind_off_sav;
X	curwp -> w_flag |= WFHARD;  /* insure that window is still presentable */
X	return (TRUE);
X}
END_OF_FILE
if test 30889 -ne `wc -c <'display.c'`; then
    echo shar: \"'display.c'\" unpacked with wrong size!
fi
# end of 'display.c'
fi
echo shar: End of archive 9 \(of 11\).
cp /dev/null ark9isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 11 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@uunet.uu.net>.
Mail comments to the moderator at <amiga-request@uunet.uu.net>.
Post requests for sources, and general discussion to comp.sys.amiga.misc.
