Newsgroups: comp.sources.misc
From: Peter Reilley <pvr@wang.com>
Subject:  v22i014:  beav - Binary file editor and viewer, Part05/09
Message-ID: <1991Aug14.200759.5781@sparky.IMD.Sterling.COM>
X-Md4-Signature: 94cdd6a0d9f1cd2988989e5361fa2e6d
Date: Wed, 14 Aug 1991 20:07:59 GMT
Approved: kent@sparky.imd.sterling.com

Submitted-by: Peter Reilley <pvr@wang.com>
Posting-number: Volume 22, Issue 14
Archive-name: beav/part05
Environment: UNIX, AIX, MSDOS

#! /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 5 (of 9)."
# Contents:  buffer.c def.h
# Wrapped by pvr@elf on Mon Aug 12 13:51:33 1991
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'buffer.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'buffer.c'\"
else
echo shar: Extracting \"'buffer.c'\" \(20898 characters\)
sed "s/^X//" >'buffer.c' <<'END_OF_FILE'
X/*
X*       Buffer handling.
X*/
X
X#include    "def.h"
X
Xbool    onebuf ();
Xbool    killablebufs ();
Xbool    _yankbuffer ();
Xchar    next_buf ();
Xbool    bclear ();
Xbool    addline ();
Xchar    makelist ();
Xbool    popblist ();
Xchar    listbuffers ();
Xchar    _killbuffer ();
Xbool    _usebuffer ();
X
Xextern  ROW_FMT text_fmt;
Xextern    char    MSG_use_b[];
Xextern    char    MSG_kill_b[];
Xextern    char    MSG_not_fnd[];
Xextern    char    MSG_no_del_m[];
Xextern    char    MSG_buf_disp[];
Xextern    char    MSG_main[];
Xextern    char    MSG_l_buf_h[];
Xextern    char    MSG_l_buf_h1[];
Xextern    char    MSG_no_chg[];
Xextern    char    MSG_yank_b[];
Xextern    char    MSG_no_buf[];
Xextern    char    MSG_no_s_yank[];
Xextern    char    MSG_buf_nam[];
Xextern    char    MSG_bad_l[];
Xextern    char    MSG_pick[];
Xextern    char    MSG_siz_chg[];
Xextern    char    MSG_no_siz_chg[];
Xextern    char    MSG_up_arrow[];
Xextern    char    MSG_null[];
Xextern    char    MSG_save_buf[];
Xextern    char    MSG_cnt_al_b[];
Xextern    char    MSG_ins_cnt[];
X
XBUFFER	sav_buf;
XLINE	sav_line_h;
X/*
X* Attach a buffer to a window. The
X* values of dot and mark come from the buffer
X* if the use count is 0. Otherwise, they come
X* from some other window.
X*
X* plus hacks for prev/next buffer and use-buffer-split  (jam)
X* functions (like in file.c)
X*/
Xchar    usebuffer ()
X{
X
X	char    bufn[NBUFN];
X	register char   s;
X
X	if ((s = ereply (MSG_use_b, bufn, NBUFN, 0)) != TRUE)
X		return (s);
X	return (_usebuffer (bufn));
X}
X
X/* use buffer, split window first
X*/
Xchar    use_buffer ()
X{
X	char    bufn[NBUFN];
X	register char   s;
X
X	if ((s = ereply (MSG_use_b, bufn, NBUFN, 0)) != TRUE)
X		return (s);
X	splitwind ();
X	return (_usebuffer (bufn));
X}
X
X/* does all the work for changing to a new buffer for use-buffer,
X* use-buffer-split and prev-buff & next-buff
X*/
Xbool _usebuffer (bufn)
Xchar   *bufn;
X{
X	register    BUFFER * bp;
X	register    WINDOW * wp;
X
X	if (strcmp (MSG_kill_b, bufn) == 0)/* hack! */
X		bp = blistp;
X	else
X		if ((bp = bfind (bufn, TRUE)) == NULL)
X			return (FALSE);
X
X	/* if current buffer is special and new buffer is normal */
X	/* set to hex byte mode */
X	if ((curbp == blistp) && (R_TYPE(curwp) == TEXT))
X	{
X		dispsize1 ();
X		hexmode ();
X	}
X
X	if (--curbp -> b_nwnd == 0)
X	{
X		/* Last use.         */
X		curbp -> b_dotp = curwp -> w_dotp;
X		curbp -> b_doto = curwp -> w_doto;
X		curbp -> b_unit_offset = curwp -> w_unit_offset;/* pvr */
X		curbp -> b_markp = curwp -> w_markp;
X		curbp -> b_marko = curwp -> w_marko;
X	}
X	curbp = bp;                 /* Switch.       */
X	curwp -> w_bufp = bp;
X	curwp -> w_linep = bp -> b_linep;/* For macros, ignored.     */
X	curwp -> w_loff = 0; /* pvr */
X	curwp -> w_flag |= WFMODE | WFFORCE | WFHARD;
X	/* Quite nasty.      */
X	if (bp -> b_nwnd++ == 0)
X	{
X		/* First use.        */
X		curwp -> w_dotp = bp -> b_dotp;
X		curwp -> w_doto = bp -> b_doto;
X		curwp -> w_unit_offset = 0;     /* pvr */
X		curwp -> w_markp = bp -> b_markp;
X		curwp -> w_marko = bp -> b_marko;
X		wind_on_dot (curwp);
X		/* if we are in the funny TEXT mode then goto standard HEX mode */
X		if (R_TYPE(curwp) == TEXT)
X			hexmode ();
X		return (TRUE);
X	}
X	wp = wheadp;                /* Look for old.     */
X	while (wp != NULL)
X	{
X		if (wp != curwp && wp -> w_bufp == bp)
X		{
X			curwp -> w_dotp = wp -> w_dotp;
X			curwp -> w_doto = wp -> w_doto;
X			curwp -> w_unit_offset = wp -> w_unit_offset;/* pvr */
X			curwp -> w_markp = wp -> w_markp;
X			curwp -> w_marko = wp -> w_marko;
X			break;
X		}
X		wp = wp -> w_wndp;
X	}
X	wind_on_dot (curwp);
X	/* if we are in the funny TEXT mode then goto standard HEX mode */
X	if (R_TYPE(curwp) == TEXT)
X		hexmode ();
X	return (TRUE);
X}
X
X
X/*
X* Dispose of a buffer, by name.
X* Ask for the name. Look it up (don't get too
X* upset if it isn't there at all!). Get quite upset
X* if the buffer is being displayed. Clear the buffer (ask
X* if the buffer has been changed). Then free the header
X* line and the buffer header. Bound to "C-X K".
X*/
Xchar    killbuffer ()
X{
X	register char   s;
X	char    bufn[NBUFN];
X
X	if ((s = ereply (MSG_kill_b, bufn, NBUFN, 0)) != TRUE)
X		return (s);
X	if (s = _killbuffer (bufn))
X		writ_echo (okmsg);             /* verbose-ness (jam) */
X	return (s);
X}
X
X
Xchar    _killbuffer (bufn)
Xchar   *bufn;
X{
X	register    BUFFER * bp,
X	*bp1,
X	*bp2;
X	register char   s,
X	x = 0;
X
X	if ((bp = bfind (bufn, FALSE)) == NULL)
X	{
X		writ_echo (MSG_not_fnd);
X		return (FALSE);
X	}
X
X
X	if (killablebufs (bp))      /* can't kill '?' if no other buffers */
X	{
X		writ_echo (MSG_no_del_m);
X		return (FALSE);
X	}
X
X	/* see if the buffer to be killed is in a window */
X	bp1 = bp;
X	if (curbp == blistp && onebuf (bp))/* Hack ! */
X	{
X		next_buf ();
X		onlywind ();
X		update ();
X	}
X
X	if (bp -> b_nwnd > 0)
X	{
X		if ((s = eyesno (MSG_buf_disp)) != TRUE)
X			return (s);
X
X		/* make the current window the only window if it is to die */
X		onlywind ();
X		if (curbp == bp)
X		{
X			next_buf ();
X			if (curbp == bp)
X				x++;
X		}
X	}
X	if ((s = bclear (bp)) != TRUE)/* Blow text away.      */
X	{
X		if (bp1 == blistp)      /* special buffer */
X			curbp = bp1;
X		else
X			if (!x)
X				_usebuffer (bp1 -> b_bname);
X		/* back to original buffer (jam) */
X		return (s);
X	}
X	if (x)
X	{
X		_usebuffer (MSG_main);
X		x++;
X	}
X
X	free ((char *) bp -> b_linep);/* Release header line.         */
X	bp1 = NULL;                 /* Find the header.     */
X	bp2 = bheadp;
X	while (bp2 != bp)
X	{
X		bp1 = bp2;
X		bp2 = bp2 -> b_bufp;
X	}
X	bp2 = bp2 -> b_bufp;        /* Next one in chain.   */
X	if (bp1 == NULL)            /* Unlink it.           */
X		bheadp = bp2;
X	else
X		bp1 -> b_bufp = bp2;
X	free ((char *) bp);         /* Release buffer block         */
X	if (x)
X		update ();
X	/* update buffer display */
X	if ((blistp -> b_nwnd != 0) &&
X	    (blistp -> b_type == BTLIST))
X		listbuffers ();
X	return (TRUE);
X}
X
X/*
X* Display the buffer list. This is done
X* in two parts. The "makelist" routine figures out
X* the text, and puts it in the buffer whoses header is
X* pointed to by the external "blistp". The "popblist"
X* then pops the data onto the screen. Bound to
X* "C-X C-B".
X*/
Xchar    listbuffers ()
X{
X	register char   s;
X
X	if ((s = makelist ()) != TRUE)
X		return (s);
X	return (popblist ());
X}
X/*
X* Display the save buffer contents.
X* Bound to "Meta C-W".
X*/
Xchar    showsavebuf ()
X{
X	WINDOW   *wp;
X
X	if (sav_buf.b_nwnd == 0)
X	{
X		splitwind ();
X		_usebuffer (MSG_save_buf);
X	}
X	else
X	{
X		wp = wheadp;                /* Look for old.     */
X		while (wp != NULL)
X		{
X			if (wp -> w_bufp == &sav_buf)
X			{
X				wp -> w_flag |= WFMODE | WFFORCE | WFHARD;
X				break;
X			}
X			wp = wp -> w_wndp;
X		}
X	}
X}
X
X/*
X* Pop the special buffer whose
X* buffer header is pointed to by the external
X* variable "blistp" onto the screen. This is used
X* by the "listbuffers" routine (above) and by
X* some other packages. Returns a status.
X*/
Xbool popblist ()
X{
X	register    WINDOW * wp;
X	register    BUFFER * bp;
X
X	if (blistp -> b_nwnd == 0)  /* Not on screen yet.    */
X	{
X		if ((wp = wpopup ()) == NULL)
X			return (FALSE);
X		bp = wp -> w_bufp;
X		if (--bp -> b_nwnd == 0)
X		{
X			bp -> b_dotp = wp -> w_dotp;
X			bp -> b_doto = wp -> w_doto;
X			bp -> b_unit_offset = wp -> w_unit_offset;/* pvr */
X			bp -> b_markp = wp -> w_markp;
X			bp -> b_marko = wp -> w_marko;
X		}
X		wp -> w_bufp = blistp;
X		++blistp -> b_nwnd;
X	}
X	wp = wheadp;
X	while (wp != NULL)
X	{
X		if (wp -> w_bufp == blistp)
X		{
X			wp -> w_linep = lforw (blistp -> b_linep);
X			wp -> w_loff = 0;
X			wp -> w_dotp = lforw (blistp -> b_linep);
X			wp -> w_doto = 0;
X			wp -> w_unit_offset = 0;
X			wp -> w_markp = NULL;
X			wp -> w_marko = 0;
X			wp -> w_disp_shift = 0;
X			wp -> w_intel_mode = FALSE;
X			wp -> w_fmt_ptr = &text_fmt;
X			wp -> w_flag |= WFMODE | WFHARD;
X		}
X		wp = wp -> w_wndp;
X	}
X	return (TRUE);
X}
X
X/*
X* This routine rebuilds the
X* text in the special secret buffer
X* that holds the buffer list. It is called
X* by the list buffers command. Return TRUE
X* if everything works. Return FALSE if there
X* is an error (if there is no memory).
X*/
Xchar    makelist ()
X{
X	register    char  *cp1;
X	register    char  *cp2;
X	register    int    c;
X	register    BUFFER * bp;
X	register    LINE * lp;
X	register    A32    nbytes;
X	register    char   s;
X	char    b[8 + 1];
X	char    line[128];
X
X	blistp -> b_flag &= ~BFCHG; /* Blow away old.    */
X	if ((s = bclear (blistp)) != TRUE)
X		return (s);
X	blistp -> b_flag |= BFVIEW;
X	blistp -> b_type = BTLIST;
X	strcpy (blistp -> b_fname, MSG_up_arrow);
X	if (addline (MSG_l_buf_h) == FALSE
X	    || addline (MSG_l_buf_h1) == FALSE)
X		return (FALSE);
X	bp = bheadp;                /* For all buffers   */
X	while (bp != NULL)
X	{
X		cp1 = &line[0];         /* Start at left edge    */
X		if ((bp -> b_flag & BFCHG) != 0)/* "*" if changed    */
X			*cp1++ = '*';
X		else
X			if (bp -> b_flag & BFVIEW)/* jam */
X				*cp1++ = 'R';   /* readonly */
X			else
X				*cp1++ = ' ';
X		*cp1++ = ' ';           /* Gap. */
X		if ((bp -> b_flag & BFBAD) != 0)/* "?" if maybe trashed  */
X			*cp1++ = '?';
X		else
X			*cp1++ = ' ';
X		*cp1++ = ' ';           /* Gap. */
X		nbytes = bp -> b_linep -> l_bp -> l_file_offset +
X		    bp -> b_linep -> l_bp -> l_used;
X		sprintf (b, "%8lx", nbytes); /* 8 digit buffer size.   */
X		cp2 = &b[0];
X		while ((c = *cp2++) != 0)
X			*cp1++ = c;
X		*cp1++ = ' ';           /* Gap.          */
X		cp2 = &bp -> b_bname[0];/* Buffer name       */
X		while ((c = *cp2++) != 0)
X			*cp1++ = c;
X		*cp1++ = ' ';           /* Gap.          */
X		*cp1++ = ' ';           /* Gap.          */
X		cp2 = &bp -> b_fname[0];/* File name         */
X		if (*cp2 != 0)
X		{
X			while (cp1 < &line[1 + 1 + 1 + 1 + 6 + 1 + NBUFN + 1])
X				*cp1++ = ' ';
X			while ((c = *cp2++) != 0)
X			{
X				if (cp1 < &line[128 - 1])
X					*cp1++ = c;
X			}
X		}
X		while (cp1 < &line[80])   /* Fill out line to col 80 */
X			*cp1++ = ' ';
X
X		*cp1 = 0;               /* Add to the buffer.    */
X		if (addline (line) == FALSE)
X			return (FALSE);
X		bp = bp -> b_bufp;
X	}
X	return (TRUE);              /* All done      */
X}
X
X/*
X* The argument "text" points to
X* a string. Append this line to the
X* buffer list buffer. 
X* Return TRUE if it worked and
X* FALSE if you ran out of room.
X*/
Xbool addline (text)
Xchar   *text;
X{
X	register    LINE    * lp;
X	register    int     i, allocsize;
X	register    int     ntext;
X
X	ntext = strlen (text);
X	allocsize = 128;
X
X	if ((lp = lalloc (allocsize)) == NULL)
X		return (FALSE);
X
X	for (i = 0; i < ntext; ++i)
X		lputc (lp, i, text[i]);
X
X	for (; i < allocsize; ++i)     /* fill out line with spaces */
X		lputc (lp, i, ' ');
X
X	blistp -> b_linep -> l_bp -> l_fp = lp;/* Hook onto the end  */
X	lp -> l_bp = blistp -> b_linep -> l_bp;
X	blistp -> b_linep -> l_bp = lp;
X	lp -> l_fp = blistp -> b_linep;
X	lp -> l_size = allocsize;  /* line size is limited to 80 chars */
X	lp -> l_used = allocsize;
X	lp -> l_file_offset = lp -> l_bp -> l_file_offset + lp -> l_bp -> l_used;
X	if (blistp -> b_dotp == blistp -> b_linep)/* If "." is at the end    */
X		blistp -> b_dotp = lp;  /* move it to new line   */
X	return (TRUE);
X}
X
X
X/*
X* Look through the list of
X* buffers. Return TRUE if there
X* are any changed buffers. Special buffers
X* like the buffer list buffer don't count, as
X* they are not in the list. Return FALSE if
X* there are no changed buffers.
X*/
Xbool anycb ()
X{
X	register    BUFFER * bp;
X
X	bp = bheadp;
X	while (bp != NULL)
X	{
X
X		if ((bp -> b_flag & BFCHG) != 0)
X			return (TRUE);
X		bp = bp -> b_bufp;
X	}
X	return (FALSE);
X}
X
X
X/*
X* Search for a buffer, by name.
X* If not found, and the "cflag" is TRUE,
X* create a buffer and put it in the list of
X* all buffers. Return pointer to the BUFFER
X* block for the buffer.
X*/
XBUFFER * bfind (bname, cflag)
Xregister char  *bname;
X{
X	register    BUFFER * bp;
X
X	bp = bheadp;
X	while (bp != NULL)
X	{
X		if (strcmp (bname, bp -> b_bname) == 0)
X			return (bp);
X		bp = bp -> b_bufp;
X	}
X	if (cflag != FALSE && (bp = bcreate (bname)) != NULL)
X	{
X		bp -> b_bufp = bheadp;
X		bheadp = bp;
X	}
X	return (bp);
X}
X
X
X/*
X* Create a buffer, by name.
X* Return a pointer to the BUFFER header
X* block, or NULL if the buffer cannot
X* be created. The BUFFER is not put in the
X* list of all buffers; this is called by
X* "edinit" to create the buffer list
X* buffer.
X*/
XBUFFER * bcreate (bname)
Xregister char  *bname;
X{
X
X	register    BUFFER * bp;
X	register    LINE * lp;
X
X	if ((bp = (BUFFER *) malloc (sizeof (BUFFER))) == NULL)
X	{
X		err_echo (MSG_cnt_al_b);
X		return (NULL);
X	}
X	if ((lp = lalloc (0)) == NULL)
X	{
X		free ((char *) bp);
X		return (NULL);
X	}
X	bp -> b_bufp = NULL;
X	bp -> b_dotp = lp;
X	bp -> b_doto = 0;
X	bp -> b_unit_offset = 0;    /* unit offset   pvr */
X	bp -> b_markp = NULL;
X	bp -> b_marko = 0;
X	bp -> b_flag = 0;
X	bp -> b_nwnd = 0;
X	bp -> b_linep = lp;
X	strcpy (bp -> b_fname, MSG_null);
X	strcpy (bp -> b_bname, bname);
X	lp -> l_fp = lp;
X	lp -> l_bp = lp;
X	lp -> l_file_offset = 0;    /* pvr */
X	lp -> l_used = 0;           /* pvr */
X	lp -> l_size = 0;           /* size of zero indicates the header line  pvr 
X					                                */
X	return (bp);
X}
X
X
X/*
X* This routine blows away all of the text
X* in a buffer. If the buffer is marked as changed
X* then we ask if it is ok to blow it away; this is
X* to save the user the grief of losing text. The
X* window chain is nearly always wrong if this gets
X* called; the caller must arrange for the updates
X* that are required. Return TRUE if everything
X* looks good.
X*/
Xbool bclear (bp)
Xregister    BUFFER * bp;
X{
X	register    LINE * lp;
X	register char   s;
X
X	if ((bp -> b_flag & BFCHG) != 0/* Changed.       */
X	&& (s = eyesno (MSG_no_chg)) != TRUE)
X		return (s);
X	bp -> b_flag &= ~BFCHG;     /* Not changed       */
X	while ((lp = lforw (bp -> b_linep)) != bp -> b_linep)
X		lfree (lp);
X	bp -> b_dotp = bp -> b_linep;/* Fix "."      */
X	bp -> b_doto = 0;
X	bp -> b_unit_offset = 0;    /* pvr */
X	bp -> b_markp = NULL;       /* Invalidate mark  */
X	bp -> b_marko = 0;
X	return (TRUE);
X}
X
X
X/* flip to next buffer in the list, wrap
X* to beginning if required (wrap around)
X* (skips buffers saved  by save-region)  
X*/
Xchar    next_buf ()
X{
X	register    BUFFER * bp;
X
X	bp = curbp;
X	while (TRUE)
X	{
X		if (!(bp = bp -> b_bufp))
X			bp = bheadp;
X		if ((bp -> b_type == BTSAVE) ||
X		    (bp -> b_type == BTLIST) ||
X		    (bp -> b_type == BTHELP))
X			continue;
X		break;
X	}
X	_usebuffer (bp -> b_bname);
X}
X
X
X/* flip to prev buffer in the list, wrap
X* to end if required (wrap around)
X* (does NOT skip buffers saved by save-region)  
X*/
Xchar    prev_buf ()
X{
X	register    BUFFER * sp;
X
X	if ((sp = curbp) == bheadp) /* front of list */
X	{
X		for (; sp -> b_bufp; sp = sp -> b_bufp)
X			;
X	}
X	else /* cycle around */
X	{
X		for (sp = bheadp; sp -> b_bufp; sp = sp -> b_bufp)
X		{
X			if (sp -> b_bufp == curbp)
X				break;
X		}
X	}
X	return (_usebuffer (sp -> b_bname));
X}
X
X
X/* yank a buffer into current buffer
X*/
Xchar    yank_buffer ()
X{
X	register    LINE * lp;
X	register    BUFFER * bp = curbp;
X	register char   s;
X	char    bufn[NBUFN];
X
X	if ((s = ereply (MSG_yank_b, bufn, NBUFN, 0)) != TRUE)
X		return (FALSE);
X	return (_yankbuffer (bufn));
X}
X
X
Xbool _yankbuffer (bufn)
Xchar   *bufn;
X{
X	register    LINE * lp;
X	register    BUFFER * bp = curbp;
X	register int    s;
X	A32      cnt;
X	char        buf[80], buf1[80];
X
X	if ((bp = bfind (bufn, FALSE)) == NULL)
X	{
X		writ_echo (MSG_no_buf);
X		return (FALSE);
X	}
X	if (strcmp (bp -> b_bname, curbp -> b_bname) == 0)
X	{
X		writ_echo (MSG_no_s_yank);
X		return (FALSE);
X	}
X	cnt = 0;
X	lp = lforw (bp -> b_linep);
X	while (TRUE)
X	{
X		cnt += lp -> l_used;
X		for (s = 0; s < lp -> l_used; s++)
X			if (linsert (1, lp -> l_text[s]) == FALSE)
X				return (FALSE);
X
X		if ((lp = lforw (lp)) == bp -> b_linep)
X		{
X			break;
X		}
X
X		if ((cnt & 0x7ff) == 0)
X		{
X			sprintf (buf1, MSG_ins_cnt, R_POS_FMT(curwp));
X			sprintf (buf, buf1, cnt);
X			writ_echo (buf);
X			/* check if we should quit */
X			if (ttkeyready ())
X			{
X				l_fix_up (lp -> l_bp);
X				wind_on_dot_all();
X				if (ttgetc () == CTL_G)  /* was it an abort key? */
X					return (FALSE);
X			}
X		}
X	}
X	writ_echo (okmsg);
X	return (TRUE);
X}
X
X
Xbool buffername ()
X{
X
X	register    WINDOW * wp;
X	register char  *p;
X	register char   s;
X	char    bname[NBUFN + 1];
X
X	if ((s = ereply (MSG_buf_nam, bname, NBUFN, 0)) == ABORT)
X		return (s);
X	for (p = bname; *p && *p != ' '; p++)
X		;
X	*p = 0;                     /* no blanks */
X	strcpy (curbp -> b_bname, bname);
X	wp = wheadp;                /* Update mode lines.   */
X	while (wp != NULL)
X	{
X		if (wp -> w_bufp == curbp)
X			wp -> w_flag |= WFMODE;
X		wp = wp -> w_wndp;
X	}
X	if ((blistp -> b_nwnd != 0) &&  /* update buffer display */
X	(blistp -> b_type == BTLIST))
X		listbuffers ();
X	return (TRUE);
X}
X
X
X/* any killable buffers around ? (jam)
X*/
Xbool killablebufs (bp)
Xregister    BUFFER * bp;
X{
X	if (strcmp (bp -> b_bname, MSG_main) == 0)/* doomed buffer is 'empty' */
X		if (bheadp == bp)       /* and is only buffer in list */
X			if (bheadp -> b_bufp == 0)/* then there are no killable buffers */
X				return (TRUE);
X	return (FALSE);
X}
X
X
X/* only 1 buffer around ?
X*/
Xbool onebuf (bp)
Xregister    BUFFER * bp;
X{
X	if (strcmp (bp -> b_bname, bheadp -> b_bname) == 0)
X		if (bheadp -> b_bufp == 0)
X			return (TRUE);
X	return (FALSE);
X}
X
X
X/* funky new name; real yukky!!!! (jam) 
X*/
Xvoid funky_name (bname, n)
Xregister char  *bname;
Xint     n;
X{
X	char    num[10];
X	register int    i;
X	register char  *p;
X
X	for (i = 0; i < 10; i++)
X		num[i] = ' ';
X	for (p = bname; *p; p++)
X		*p = 0;
X	*bname++ = '#';
X	sprintf (num, "%lx", (long) n + 1);
X	for (p = num; *p; p++)
X		if (*p != ' ')
X			*bname++ = *p;
X	*bname = 0;
X}
X
X
X/* pick a buffer to goto/kill
X*/
X#define BUFFEROFFSET (11)       /* depends on makelist !! */
X
Xbool pickone ()
X{
X	register int    s,
X	i,
X	c;
X	register char  *p;
X	register    LINE * lp;
X	char    name[NBUFN + 1];
X	char    buf[3];
X
X	lp = curwp -> w_dotp;       /* get the buffer name from the line */
X
X	i = 0;
X	if (!llength (lp))
X	{
X		writ_echo (MSG_bad_l);
X		return (FALSE);
X	}
X	for (s = BUFFEROFFSET; (c = lgetc (lp, s)) != ' '; s++)
X	{
X		name[i++] = c;
X		if (s >= llength (lp))
X			break;
X	}
X	name[i] = 0;
X	if (!bfind (name, FALSE))
X	{
X		writ_echo (MSG_bad_l);
X		return (FALSE);
X	}
Xloop:
X	if ((s = ereply (MSG_pick, buf, 2, name)) != TRUE)
X		return (FALSE);
X	if (ISLOWER (buf[0]) != FALSE)
X		buf[0] = TOUPPER (buf[0]);
X	if (buf[0] == 'K')
X		_killbuffer (name);
X	else
X		if (buf[0] == 'G')
X			_usebuffer (name);
X		else
X			if (buf[0] == 'S')
X			{
X				_usebuffer (name);
X				/* goto this buffer, but don't show the user */
X				filesave ();
X				_usebuffer (MSG_kill_b);
X				/* jump back to this window - HACK ! */
X				listbuffers (); /* update the list */
X			}
X			else
X				goto loop;
X	writ_echo (MSG_null);
X	return (TRUE);
X}
X/*
X*   Toggle the buffer size lock bit.
X*/
Xchar bufsizlock ()
X{
X	if (curbp -> b_flag & BFSLOCK)
X	{
X		curbp -> b_flag &= ~BFSLOCK;
X		writ_echo (MSG_siz_chg);
X	}
X	else
X	{
X		if (insert_mode)
X			insert_toggle ();
X		curbp -> b_flag |= BFSLOCK;
X		writ_echo (MSG_no_siz_chg);
X	}
X	return (TRUE);
X}
X
X/*
X *   Append the given line to the end of the given buffer.
X */
Xvoid   b_append_l (buf_p, lp)
XBUFFER *buf_p;
XLINE   *lp;
X{
X	LINE   *h_lp;
X
X	h_lp = buf_p -> b_linep;
X
X	lp -> l_fp = h_lp;
X	lp -> l_bp = h_lp -> l_bp;
X	lp -> l_bp -> l_fp = lp;
X	h_lp -> l_bp = lp;
X	lp -> l_file_offset = lp -> l_bp -> l_file_offset + lp -> l_bp -> l_used;
X}
X/*
X *   Append the given line to the end of the given buffer.
X */
Xbool   b_append_c (buf_p, ch)
XBUFFER *buf_p;
XD8     ch;
X{
X	LINE   *lp;
X	WINDOW *wp;
X
X	lp = buf_p -> b_linep -> l_bp;	/* get last line */
X	/* do I need to get a new line? */
X	if (lp -> l_size <= lp -> l_used)
X	{
X		if ((lp = lalloc (KBLOCK)) == NULL)
X			return (FALSE);
X
X		lp -> l_fp = buf_p -> b_linep;
X		lp -> l_bp = buf_p -> b_linep -> l_bp;
X		lp -> l_bp -> l_fp = lp;
X		buf_p -> b_linep -> l_bp = lp;
X	}
X	lp -> l_text[lp -> l_used++] = ch;
X
X	return (TRUE);
X}
X
X/*
X * Initialize the save buffer.
X */
Xvoid save_buf_init ()
X{
X	register    BUFFER * bp;
X
X	sav_line_h.l_fp = &sav_line_h;
X	sav_line_h.l_bp = &sav_line_h;
X	sav_line_h.l_file_offset = 0;
X	sav_line_h.l_used = 0;
X	sav_line_h.l_size = 0;
X
X	sav_buf.b_type = BTSAVE;
X	sav_buf.b_bufp = NULL;
X	sav_buf.b_dotp = &sav_line_h;
X	sav_buf.b_doto = 0;
X	sav_buf.b_unit_offset = 0;
X	sav_buf.b_markp = NULL;
X	sav_buf.b_marko = 0;
X	sav_buf.b_linep = &sav_line_h;
X	sav_buf.b_nwnd = 0;
X	sav_buf.b_flag = BFVIEW;
X	sav_buf.b_begin_addr = 0;
X	sav_buf.b_file_size = 0;
X	sav_buf.b_fname[0] = 0;
X	strcpy (sav_buf.b_bname, MSG_save_buf);
X
X	/* put on end of chain */
X	bp = bheadp;
X	while ((bp -> b_bufp) != NULL)
X		bp = bp -> b_bufp;
X
X	bp->b_bufp = &sav_buf;
X
X}
X
X/*
X * Set the save buffer dot pointer to the begining.
X */
Xvoid save_buf_home ()
X{
X	sav_buf.b_dotp = sav_buf.b_linep -> l_fp;
X	sav_buf.b_doto = 0;
X	sav_buf.b_flag = BFVIEW;
X}
X
XD16  get_save_char ()
X{
X	D8 ch;
X
X	/* are we past the end of the buffer */
X	if (sav_buf.b_dotp == sav_buf.b_linep)
X		return (-1);
X	ch = sav_buf.b_dotp -> l_text[sav_buf.b_doto++];
X	if (sav_buf.b_doto >= sav_buf.b_dotp -> l_used)
X	{
X		sav_buf.b_doto = 0;
X		sav_buf.b_dotp = sav_buf.b_dotp -> l_fp;
X	}
X	return ((D16)ch);
X}
X
END_OF_FILE
if test 20898 -ne `wc -c <'buffer.c'`; then
    echo shar: \"'buffer.c'\" unpacked with wrong size!
fi
# end of 'buffer.c'
fi
if test -f 'def.h' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'def.h'\"
else
echo shar: Extracting \"'def.h'\" \(21279 characters\)
sed "s/^X//" >'def.h' <<'END_OF_FILE'
X/*
X *     Common header file.
X *
X * This file is the general header file for all parts
X * of the display editor. It contains all of the
X * general definitions and macros. It also contains some
X * conditional compilation flags. All of the per-system and
X * per-terminal definitions are in special header files.
X * The most common reason to edit this file would be to zap
X * the definition of CVMVAS or BACKUP.
X */
X#define LINT_ARGS   1           /* enable lint type checking */
X#include        "stdio.h"
X
X#ifndef NOPROTO
X#ifdef UNIX
X#include        "sys/types.h"
X#endif /* UNIX */
X#include	    "lintfunc.dec"
X#endif  /* NOPROTO */
X
X#define BACKUP  1           /* Make backup file.            */
X#define RUNCHK  1           /* Do additional checking at run time */
X
X#ifndef	uchar
X#define uchar   unsigned    char
X#endif
X
X#ifndef	uint
X#define uint    unsigned    int 
X#endif
X
X#ifndef	ushort
X#define ushort  unsigned    short
X#endif
X
X#ifndef	ulong
X#define ulong   unsigned    long
X#endif
X
X/* these defines are reserved for handling data values from the buffer */
X#define     D8  uchar       /* this had better be a 8 bit quantity */
X#define     D16 ushort      /* this had better be a 16 bit quantity */
X#define     D32 ulong       /* this had better be a 32 bit quantity */
X
X/* this define is reserved for the address of a location in the buffer */
X#define     A32 ulong        /* this is a 32 bit address into the buffer */
X
X#define     bool char       /* used for boolean values      */
X#define     bits char       /* used for boolean bit flags   */
X
X/* this define is reserved for the byte location in the a LINE structure */
X#define     LPOS uint       /* this is a 32 bit address into the buffer */
X
X/*
X *      MS-DOS system header file.
X */
X#if	MSDOS
X#define LARGE   1           /* Large model.         */
X#endif
X#define PCC 1               /* "[]" won't work.     */
X#define GOOD    0           /* Indicate hunkydoryhood   */
X
X/*
X * Macros used by the buffer name making code.
X * Start at the end of the file name, scan to the left
X * until BDC1 (or BDC2, if defined) is reached. The buffer
X * name starts just to the right of that location, and
X * stops at end of string (or at the next BDC3 character,
X * if defined). BDC2 and BDC3 are mainly for VMS.
X */
X#define BDC1    ':'         /* Buffer names.        */
X#define BDC2    '/'         /* Buffer names. jam    */
X
X#ifdef UNIX
X#define PATHCHR ':'
X#define	SEPCHAR '/'
X#else
X#define PATHCHR ';'
X#define	SEPCHAR 0x5c	/* this is a \ char */
X#endif
X
X/*
X *      Digital ANSI terminal header file
X */
X#define GOSLING 0           /* Compile in fancy display.    */
X#ifdef MSDOS
X#define	ANSI	1			/* send ANSI escape codes */
X#endif
X
X#ifdef UNIX
X#define NROW	100
X#define NCOL    80          /* Columns.         */
X#else
X#define NROW    25          /* Rows.for boot    */
X#define NCOL    80          /* Columns.         */
X#endif
X
X#define CUSTOMIZE                       /* compile switch for extended key
Xbinding in extend.c           */
X#define COSMETIC                        /* cosmetic screen stuff on 
Xinsert off screen             */
X#ifdef MSDOS
X#define WANG_CHARACTER_SCREEN 0xf0000000L
X#endif
X/*
X * Table sizes, etc.
X */
X#define NSHASH  31          /* Symbol table hash size.      */
X#define NFILEN  80          /* Length, file name.           */
X#define NBUFN   13          /* Length, buffer name.     */
X#define NFILE   12          /* Length, file name.  */ /* krw */
X#define NKBDM   256         /* Length, keyboard macro.      */
X#define NMSG    512         /* Length, message buffer.      */
X#define NPAT    80          /* Length, pattern.             */
X#define HUGE    1000        /* A rather large number.       */
X#define NSRCH   128         /* Undoable search commands.    */
X#define NXNAME  64          /* Length, extended command.    */
X#define MAXPOS  0x7FFFFFFF  /* Maximum positive long value  */
X
X/*
X * This is the initial allocation for user data storage.
X * It has should be in the range of 1 to less than half the size 
X * of an int.   The define LPOS is used to index into an array of this size.
X * This is main tunable parameter for the speed of beav.
X * If it is too large inserts and deletes will be slow but
X * file loads will be fast and memory will be efficiently used.
X * If it is too small the reverse will be true.
X * This seems like a good number, but I have not tested it for performance.
X */
X#define NLINE   0x1000      /* Length, line.      pvr  */
X
X/*
X * When memory must be reallocated this is added to the allocation
X * request to allow for a little slop on areas that are being worked on.
X * This should reduce the number of allocations done.
X */
X#define NBLOCK  0x1000      /* Line block extra size        */
X
X/*
X * This is the number of bytes that are allocated for the kill buffer 
X * when data cannot be moved by changing the pointers.
X */
X#define KBLOCK  0x1000      /* Kill buffer block size.  */
X
X/*
X * Universal.
X */
X#define FALSE   0                       /* False, no, bad, etc.         */
X#define TRUE    1                       /* True, yes, good, etc.        */
X#define ABORT   2                       /* Death, ^G, abort, etc.       */
X
X/*
X * These flag bits keep track of
X * some aspects of the last command.
X * The CFKILL flag controls the clearing versus appending
X * of data in the kill buffer.
X */
X#define CFKILL  0x0002                  /* Last command was a kill      */
X
X/*
X * File I/O.
X */
X#define FIOSUC  0                       /* Success.                     */
X#define FIOFNF  1                       /* File not found.              */
X#define FIOEOF  2                       /* End of file.                 */
X#define FIOERR  3                       /* Error.                       */
X
X/*
X * Directory I/O.
X */
X#define DIOSUC  0                       /* Success.                     */
X#define DIOEOF  1                       /* End of file.                 */
X#define DIOERR  2                       /* Error.                       */
X
X/*
X * Display colors.
X */
X#define CNONE   0                       /* Unknown color.               */
X#define CTEXT   1                       /* Text color.                  */
X#define CMODE   2                       /* Mode line color.             */
X
X/*
X * Flags for "eread".
X */
X#define EFNEW   0x0001                  /* New prompt.                  */
X#define EFAUTO  0x0002                  /* Autocompletion enabled.      */
X#define EFCR    0x0004                  /* Echo CR at end; last read.   */
X
X/*
X * Keys are represented inside using an 11 bit
X * keyboard code. The transformation between the keys on
X * the keyboard and 11 bit code is done by terminal specific
X * code in the "kbd.c" file. The actual character is stored
X * in 8 bits (DEC multinationals work); there is also a control
X * flag KCTRL, a meta flag KMETA, and a control-X flag KCTLX.
X * ASCII control characters are always represented using the
X * KCTRL form. Although the C0 control set is free, it is
X * reserved for C0 controls because it makes the communication
X * between "getkey" and "getkbd" easier. The funny keys get
X * mapped into the C1 control area.
X */
X#define NKEYS   2048                    /* 11 bit code.                 */
X
X#define METACH  0x1B                    /* M- prefix,   Control-[, ESC  */
X#define CTMECH  0x1C                    /* C-M- prefix, Control-\       */
X#define EXITCH  0x1D                    /* Exit level,  Control-]       */
X#define CTRLCH  0x1E                    /* C- prefix,   Control-^       */
X#define HELPCH  0x1F                    /* Help key,    Control-_       */
X#define CTL_G   0x07                    /* Abort command key            */
X
X#define KCHAR   0x00FF                  /* The basic character code.    */
X#define KCTRL   0x0100                  /* Control flag.                */
X#define KMETA   0x0200                  /* Meta flag.                   */
X#define KCTLX   0x0400                  /* Control-X flag.              */
X
X#define KFIRST  0x0080                  /* First special.       fitz    */
X#define KLAST   0x00F3                  /* Last special.                */
X
X#define KRANDOM 0x0080                  /* A "no key" code.             */
X
X/*
X*	This causes the key sequence ESC [ <key> to be delevered as
X*	KCTRL | KMETA | KCTLX | <key>.   This allows VT100 function keys
X*	to be bound. 
X*/
X#define	VT100KEY
X
X/*
X *	These define the column used in the help (wallchart) function 
X */
X#define	HFUNCCOL	3
X#define	HKEY    	32
X#define	HKEYCODE	50
X#define	HENDCOL 	55
X
X/*
X * These flags, and the macros below them,
X * make up a do-it-yourself set of "ctype" macros that
X * understand the DEC multinational set, and let me ask
X * a slightly different set of questions.
X */
X#define _W      0x01                    /* Word.                        */
X#define _U      0x02                    /* Upper case letter.           */
X#define _L      0x04                    /* Lower case letter.           */
X#define _C      0x08                    /* Control.                     */
X
X#define ISCTRL(c)       ((cinfo[(c)]&_C)!=0)
X#define ISUPPER(c)      ((cinfo[(c)]&_U)!=0)
X#define ISLOWER(c)      ((cinfo[(c)]&_L)!=0)
X#define TOUPPER(c)      ((c)-0x20)
X#define TOLOWER(c)      ((c)+0x20)
X
X#define BUF_SIZE(wp)    (wp -> w_bufp -> b_linep -> l_bp -> l_file_offset + \
X                        wp -> w_bufp -> b_linep -> l_bp -> l_used)
X#define BUF_START(wp)   (wp -> w_bufp -> b_linep -> l_fp -> l_file_offset)
X#define DOT_POS(wp)     (wp -> w_dotp -> l_file_offset + wp -> w_doto)
X#define MARK_POS(wp)    (wp -> w_markp -> l_file_offset + wp -> w_marko)
X#define DOT_CHAR(wp)    (wp -> w_dotp -> l_text[wp -> w_doto])
X#define WIND_POS(wp)    (wp -> w_linep -> l_file_offset + wp -> w_loff)
X#define R_TYPE(wp)      (wp -> w_fmt_ptr -> r_type)
X#define R_SIZE(wp)      (wp -> w_fmt_ptr -> r_size)
X#define R_UNITS(wp)     (wp -> w_fmt_ptr -> r_units)
X#define R_BYTES(wp)     (wp -> w_fmt_ptr -> r_bytes)
X#define R_ALIGN(wp)     (wp -> w_fmt_ptr -> r_align)
X#define R_B_PER_U(wp)   (wp -> w_fmt_ptr -> r_b_per_u)
X#define R_CHR_PER_U(wp) (wp -> w_fmt_ptr -> r_chr_per_u)
X#define R_FLAGS(wp)     (wp -> w_fmt_ptr -> r_flags)
X#define R_UNIT_FMT(wp)  (wp -> w_fmt_ptr -> r_unit_fmt)
X#define R_POS_FMT(wp)   (wp -> w_fmt_ptr -> r_pos_fmt)
X#define R_BYTE_FMT(wp)   (wp -> w_fmt_ptr -> r_byte_fmt)
X#define R_POSITIONS(wp) (wp -> w_fmt_ptr -> r_positions)
X
X/*
X * The symbol table links editing functions
X * to names. Entries in the key map point at the symbol
X * table entry. A reference count is kept, but it is
X * probably next to useless right now. The old type code,
X * which was not being used and probably not right
X * anyway, is all gone.
X */
Xtypedef struct  SYMBOL {
X	struct  SYMBOL *s_symp;         /* Hash chain.                  */
X	short   s_nkey;                 /* Count of keys bound here.    */
X	char    *s_name;                /* Name.            */
X	bool    (*s_funcp)();           /* Function.                    */
X	bits    s_modify;               /* modify bit */
X}       SYMBOL;
X
X/*
X*   These are the legal values for 's_modify' and 'k_modify'
X*/
X#define SMOD    0x01            /* command modifies the buffer  */
X#define SSIZE   0x02            /* command changes buffer size  */
X#define SSRCH   0x04            /* command valid in search  */
X#define SRPLC   0x08            /* command valid in replace */
X#define SBOUND  0x10            /* key was bound bu user or rc file */
X
X/*
X * There is a window structure allocated for
X * every active display window. The windows are kept in a
X * big list, in top to bottom screen order, with the listhead at
X * "wheadp". Each window contains its own values of dot and mark.
X * The flag field contains some bits that are set by commands
X * to guide redisplay; although this is a bit of a compromise in
X * terms of decoupling, the full blown redisplay is just too
X * expensive to run for every input character.
X */
Xtypedef struct  WINDOW {
X	struct  WINDOW *w_wndp;         /* Next window                  */
X	struct  BUFFER *w_bufp;         /* Buffer displayed in window   */
X	struct  LINE *w_linep;          /* Top line in the window       */
X	LPOS    w_loff;                 /* Offset into line for start pvr  */
X	A32     w_wind_temp;            /* temp storage for window file pos */
X	struct  LINE *w_dotp;           /* Line containing "."          */
X	LPOS    w_doto;                 /* Offset into line for "." */
X	A32     w_dot_temp;             /* temp storage for dot file pos */
X	struct  LINE *w_markp;          /* Line containing "mark"       */
X	LPOS    w_marko;                /* Byte offset for "mark"       */
X	A32     w_mark_temp;            /* temp storage for mark file pos */
X	char    w_unit_offset;          /* Byte offset for "." into unit pvr */
X	char    w_toprow;               /* Origin 0 top row of window   */
X	char    w_ntrows;               /* # of rows of text in window  */
X	bits    w_flag;                 /* Flags.                       */
X	char    w_disp_shift;           /* Display byte shift; 0-3  pvr */
X	bool    w_intel_mode;           /* Display byte swaped.     pvr */
X	struct  ROW_FMT *w_fmt_ptr;     /* Pointer to display format pvr */
X}       WINDOW;
X
X/*
X * Window flags are set by command processors to
X * tell the display system what has happened to the buffer
X * mapped by the window. Setting "WFHARD" is always a safe thing
X * to do, but it may do more work than is necessary. Always try
X * to set the simplest action that achieves the required update.
X * Because commands set bits in the "w_flag", update will see
X * all change flags, and do the most general one.
X */
X#define WFFORCE 0x01                    /* Force reframe.               */
X#define WFMOVE  0x02                    /* Movement from line to line.  */
X#define WFEDIT  0x04                    /* Editing within a line.       */
X#define WFHARD  0x08                    /* Better to a full display.    */
X#define WFMODE  0x10                    /* Update mode line.        */
X/*
X*   This structure contains how a row is constructed.   pvr
X*/
X
Xtypedef struct  ROW_FMT {
X	uchar   r_type;     /* format type nibbles          */
X	uchar   r_size;     /* format size: must be 0,1,3,7,15, etc */
X	uchar   r_units;    /* number of units per window row: must be 1,2,4,8,16*/
X	uchar   r_bytes;    /* number of bytes per window row: must be 1,2,4,8,16*/
X	uchar   r_align;    /* number of bytes per align row: must be 1,2,4,8,16*/
X	uchar   r_b_per_u;  /* number of bytes per unit: must be 1,2,4,8,16 */
X	uchar   r_chr_per_u; /* displayed chars per unit     */
X	bits    r_flags;    /* flags controlling format     */
X	char    *r_unit_fmt; /* print format for unit */
X	char    *r_pos_fmt; /* print format for buffer position, always a long */
X	char    *r_byte_fmt; /* print format for bytes */
X	uchar   *r_positions; /* list of unit positions   */
X	struct ROW_FMT *r_srch_fmt; /* pointer to search display format */
X} ROW_FMT;
X
X/* legal values for 'r_size'  (values significant; used as bit mask) pvr */
X
X#define BYTES   0x00        /* Display as byte; 8 bits  */
X#define WORDS   0x01        /* Display as word;    16 bits  */
X#define DWORDS  0x03        /* Display as doubles; 32 bits  */
X
X/* legal values for 'r_type'   pvr */
X#define ASCII   0x10        /* Display as ascii     */
X#define OCTAL   0x20        /* Display as octal values  */
X#define DECIMAL 0x30        /* Display as decimal values    */
X#define HEX     0x40        /* Display as hex values    */
X#define BINARY  0x50        /* Display as binary values */
X#define EBCDIC  0x60        /* Display as ebcdic        */
X#define TEXT    0x70        /* Display as normal text   */
X
X/*
X * Text is kept in buffers. A buffer header, described
X * below, exists for every buffer in the system. The buffers are
X * kept in a big list, so that commands that search for a buffer by
X * name can find the buffer header. There is a safe store for the
X * dot and mark in the header, but this is only valid if the buffer
X * is not being displayed (that is, if "b_nwnd" is 0). The text for
X * the buffer is kept in a circularly linked list of lines, with
X * a pointer to the header line in "b_linep".
X */
Xtypedef struct  BUFFER {
X	bits    b_type;         /* Type of buffer       */
X	struct  BUFFER *b_bufp; /* Link to next BUFFER          */
X	struct  LINE *b_dotp;   /* Link to "." LINE structure   */
X	LPOS    b_doto;         /* Offset of "." in above LINE  */
X	char    b_unit_offset;  /* Offset into unit for "." pvr */
X	struct  LINE *b_markp;  /* The same as the above two,   */
X	LPOS    b_marko;        /* but for the "mark"       */
X	struct  LINE *b_linep;  /* Link to the header LINE      */
X	char    b_nwnd;         /* Count of windows on buffer   */
X	bits    b_flag;         /* Flags            */
X	A32     b_begin_addr;   /* File address of begining of buffer */
X	A32     b_end_addr;     /* File address of end of buffer */
X	A32     b_file_size;    /* Size of file */
X	char    b_fname[NFILEN]; /* File name                    */
X	char    b_bname[NBUFN];  /* Buffer name                  */
X}   BUFFER;
X
X/* Values for 'buf_type' */
X#define BTFILE   0x00            /* Buffer contains a file   */
X#define BTDISK   0x01            /* Buffer points to a disk  */
X#define BTMEMORY 0x02            /* Buffer points to memory  */
X#define BTSAVE   0x03            /* This is the save buffer */
X#define BTLIST   0x04            /* This is the buffer list */
X#define BTHELP   0x05            /* This is the help buffer */
X
X/* Values for 'b_flag' */
X
X#define BFCHG   0x01            /* Changed.         */
X#define BFBAK   0x02            /* Need to make a backup.       */
X#define BFBAD   0x04            /* may be trashed alloc error?  */
X#define BFINMEM 0x08            /* File is entirely in memory */
X#define BFVIEW  0x10            /* read only (jam)               */
X#define BFLINK  0x20            /* Linked mode    pvr        */
X#define BFSLOCK 0x40            /* Lock buffer size   pvr    */
X/*
X * This structure holds the starting position
X * (as a line/offset pair) and the number of characters in a
X * region of a buffer. This makes passing the specification
X * of a region around a little bit easier.
X * There have been some complaints that the short in this
X * structure is wrong; that a long would be more appropriate.
X * I'll await more comments from the folks with the little
X * machines; I have a VAX, and everything fits.
X */
Xtypedef struct  reg {
X	struct  LINE *r_linep;          /* Origin LINE address.         */
X	LPOS    r_offset;               /* Origin LINE offset.          */
X	A32     r_size;                 /* Length in characters.        */
X}       REGION;
X
X/*
X * All text is kept in circularly linked
X * lists of "LINE" structures. These begin at the
X * header line (which is the blank line beyond the
X * end of the buffer). This line is pointed to by
X * the "BUFFER". Each line contains a the number of
X * bytes in the line (the "used" size), the size
X * of the text array, and the text. The end of line
X * is not stored as a byte; it's implied. Future
X * additions will include update hints, and a
X * list of marks into the line.
X */
Xtypedef struct  LINE {
X	struct  LINE *l_fp;       /* Link to the next line        */
X	struct  LINE *l_bp;       /* Link to the previous line    */
X	A32     l_file_offset;        /* Offset from begining of file pvr */
X	LPOS    l_size;           /* Allocated size           */
X	LPOS    l_used;           /* Used size            */
X#if     PCC
X	D8      l_text[1];        /* A bunch of characters.       */
X#else
X	D8      l_text[];         /* A bunch of characters.       */
X#endif
X}      LINE;
X
X/*
X * The rationale behind these macros is that you
X * could (with some editing, like changing the type of a line
X * link from a "LINE *" to a "REFLINE", and fixing the commands
X * like file reading that break the rules) change the actual
X * storage representation of lines to use something fancy on
X * machines with small address spaces.
X */
X#define lforw(lp)       ((lp)->l_fp)
X#define lback(lp)       ((lp)->l_bp)
X#define lgetc(lp, n)    ((lp)->l_text[(n)]&0xFF)
X#define lputc(lp, n, c) ((lp)->l_text[(n)]=(c))
X#define llength(lp)     ((lp)->l_used)
X
X/*
X * Externals.
X */
Xextern  int     thisflag;
Xextern  int     lastflag;
Xextern  int     curgoal;
Xextern  int     epresf;
Xextern  int     sgarbf;
Xextern  WINDOW  *curwp;
Xextern  BUFFER  *curbp;
Xextern  WINDOW  *wheadp;
Xextern  BUFFER  *bheadp;
Xextern  BUFFER  *blistp;
Xextern  short   kbdm[];
Xextern  short   *kbdmip;
Xextern  short   *kbdmop;
Xextern  SYMBOL  *symbol[];
Xextern  SYMBOL  *binding[];
Xextern  BUFFER  *bfind();
Xextern  BUFFER  *bcreate();
Xextern  WINDOW  *wpopup();
Xextern  LINE    *lalloc();
Xextern  int     nrow;
Xextern  int     ncol;
Xextern  char    version[];
Xextern  int     ttrow;
Xextern  int     ttcol;
Xextern  int     tceeol;
Xextern  int     tcinsl;
Xextern  int     tcdell;
Xextern  char    cinfo[];
Xextern  SYMBOL  *symlookup();
Xextern  int     nmsg;
Xextern  int     curmsgf;
Xextern  int     newmsgf;
Xextern  char    msg[];
X
X/* jam
X */
Xextern  char    *okmsg;
Xextern  int     insert_mode;
Xextern  int     extend_buf;
Xextern  int     flush_num;
Xextern  int     auto_update;
Xextern  int     flush_count;
Xextern  int     rowb;
Xextern  char    file_off_bad;
X
X/*
X * Standard I/O.
X */
Xextern  char    *malloc();
Xextern  char    *strcpy();
Xextern  char    *strcat();
END_OF_FILE
if test 21279 -ne `wc -c <'def.h'`; then
    echo shar: \"'def.h'\" unpacked with wrong size!
fi
# end of 'def.h'
fi
echo shar: End of archive 5 \(of 9\).
cp /dev/null ark5isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 9 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

-- 
>>>>>>>>>>>>>>>> Peter Reilley ..... pvr@wang.com <<<<<<<<<<<<<<<<<<<<<<<
                     Well, that about says it.

exit 0 # Just in case...
-- 
Kent Landfield                   INTERNET: kent@sparky.IMD.Sterling.COM
Sterling Software, IMD           UUCP:     uunet!sparky!kent
Phone:    (402) 291-8300         FAX:      (402) 291-4362
Please send comp.sources.misc-related mail to kent@uunet.uu.net.
