DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download
Index: ┃ T b

⟦b11787b31⟧ TextFile

    Length: 13610 (0x352a)
    Types: TextFile
    Names: »buffer.c«

Derivation

└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
    └─ ⟦this⟧ »EUUGD11/euug-87hel/sec1/micrognu/buffer.c« 

TextFile

/*
 *		Buffer handling.
 */
#include	"def.h"

/*
 * Attach a buffer to a window. The
 * values of dot and mark come from the buffer
 * if the use count is 0. Otherwise, they come
 * from some other window.
 */
/*ARGSUSED*/
usebuffer(f, n, k) {
	register BUFFER	*bp;
	register int	s;
	char		bufn[NBUFN];

	/* Get buffer to use from user */
	if (curbp->b_altb != NULL)
		s=eread("Switch to buffer: (default %s) ", bufn, NBUFN,
			 EFNEW|EFBUF, 
#ifdef	VARARGS
			 curbp->b_altb->b_bname
#else
			 &(curbp->b_altb->b_bname), (char *) NULL
#endif
			 ) ;
	else
		s=eread("Switch to buffer: ", bufn, NBUFN, EFNEW|EFBUF
#ifndef VARARGS
			 ,(char *) NULL
#endif
			 );
	if (s == ABORT) return (s);
	if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb ;
	else if ((bp=bfind(bufn, TRUE)) == NULL) return (FALSE);

	/* and put it in current window */
	curbp = bp;
	return showbuffer(bp, curwp, WFFORCE|WFHARD);
}

/*
 * pop to buffer asked for by the user.
 */
/*ARGSUSED*/
poptobuffer(f, n, k) {
	register BUFFER	*bp;
	register WINDOW	*wp;
	register int	s;
	char		bufn[NBUFN];

	/* Get buffer to use from user */
	if (curbp->b_altb != NULL)
		s=eread("Switch to buffer in other window: (default %s) ",
			 bufn, NBUFN, EFNEW|EFBUF, 
#ifdef	VARARGS
			 curbp->b_altb->b_bname
#else
			 &(curbp->b_altb->b_bname) ,(char *) NULL
#endif
			 ) ;
	else
		s=eread("Switch to buffer in other window: ", bufn, NBUFN,
		EFNEW|EFBUF
#ifndef VARARGS
		, (char *) NULL
#endif
		) ;
	if (s == ABORT) return (s);
	if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb ;
	else if ((bp=bfind(bufn, TRUE)) == NULL) return (FALSE);

	/* and put it in a new window */
	if ((wp = popbuf(bp)) == NULL) return FALSE;
	curbp = bp;
	curwp = wp;
	return TRUE;
}

/*
 * Dispose of a buffer, by name.
 * Ask for the name. Look it up (don't get too
 * upset if it isn't there at all!). Clear the buffer (ask
 * if the buffer has been changed). Then free the header
 * line and the buffer header. Bound to "C-X K".
 */
/*ARGSUSED*/
killbuffer(f, n, k) {
	register BUFFER	*bp;
	register BUFFER	*bp1;
	register BUFFER	*bp2;
	register WINDOW	*wp;
	register int	s;
	char		bufn[NBUFN];

	if ((s=eread("Kill buffer: (default %s) ", bufn, NBUFN, EFNEW|EFBUF,
#ifdef	VARARGS
		    curbp->b_bname
#else
		    &(curbp->b_bname)
#endif
		    )) == ABORT) return (s);
	else if (s == FALSE) bp = curbp ;
	else if ((bp=bfind(bufn, FALSE)) == NULL) return FALSE;

	if (bp->b_nwnd != 0) {
		if ((bp1 = bp->b_altb) == NULL) return FALSE;
		if (bclear(bp) != TRUE) return TRUE;
		for (wp = wheadp; bp->b_nwnd > 0; wp = wp->w_wndp) {
			/* Special case - could use showbuf, but don't */
			if (wp->w_bufp == bp) {
				--bp->b_nwnd;
				++bp1->b_nwnd;
				wp->w_bufp  = bp1 ;
				wp->w_dotp  = bp1->b_dotp;
				wp->w_doto  = bp1->b_doto;
				wp->w_markp = bp1->b_markp;
				wp->w_marko = bp1->b_marko;
				wp->w_linep = bp1->b_linep;
				wp->w_flag |= WFMODE|WFFORCE|WFHARD;
			}
		}
	}
	else if (bclear(bp) != TRUE) return TRUE;
	if (bp == curbp) curbp = bp->b_altb;
	free((char *) bp->b_linep);		/* Release header line.	*/
	bp1 = NULL;				/* Find the header.	*/
	bp2 = bheadp;
	while (bp2 != bp) {
		if (bp2->b_altb == bp) 
			bp2->b_altb = (bp->b_altb == bp2) ? NULL : bp->b_altb;
		bp1 = bp2;
		bp2 = bp2->b_bufp;
	}
	bp2 = bp2->b_bufp;			/* Next one in chain.	*/
	if (bp1 == NULL)			/* Unlink it.		*/
		bheadp = bp2;
	else
		bp1->b_bufp = bp2;
	while (bp2 != NULL) {			/* Finish with altb's	*/
		if (bp2->b_altb == bp) 
			bp2->b_altb = (bp->b_altb == bp2) ? NULL : bp->b_altb;
		bp2 = bp2->b_bufp;
	}
	free(bp->b_bname);		/* Release name block	*/
	free((char *) bp);			/* Release buffer block	*/
	return (TRUE);
}

/*
 * Save some buffers - just call anycb with the arg flag.
 */
/*ARGSUSED*/
savebuffers(f, n, k) {
	if (anycb(f) == ABORT) return ABORT;
	return TRUE;
}

/*
 * Display the buffer list. This is done
 * in two parts. The "makelist" routine figures out
 * the text, and puts it in a buffer. "popbuf"
 * then pops the data onto the screen. Bound to
 * "C-X C-B".
 */
/*ARGSUSED*/
listbuffers(f, n, k) {
	register BUFFER	*bp;
	register WINDOW *wp;
	BUFFER	 	*makelist();
	WINDOW		*popb();

	if ((bp=makelist()) == NULL || (wp=popbuf(bp)) == NULL)
		return FALSE;
	wp->w_dotp = bp->b_dotp;	/* fix up if window already on screen */
	wp->w_doto = bp->b_doto;
	return TRUE;
}

/*
 * This routine rebuilds the text for the
 * list buffers command. Return TRUE if
 * everything works. Return FALSE if there
 * is an error (if there is no memory).
 */
BUFFER *
makelist() {
	register char	*cp1;
	register char	*cp2;
	register int	c;
	register BUFFER	*bp;
	register LINE	*lp;
	register RSIZE	nbytes;
	BUFFER		*blp;
	char		b[6+1];
	char		line[128];
	
	if ((blp = bfind("*Buffer List*", TRUE)) == NULL) return NULL;
	if (bclear(blp) != TRUE) return NULL;
	blp->b_flag &= ~BFCHG;			/* Blow away old.	*/

	(VOID) strcpy(line, " MR Buffer");
	cp1 = line + 10;
	while(cp1 < line + 4 + NBUFN + 1) *cp1++ = ' ';
	(VOID) strcpy(cp1, "Size   File");
	if (addline(blp, line) == FALSE) return NULL;
	(VOID) strcpy(line, " -- ------");
	cp1 = line + 10;
	while(cp1 < line + 4 + NBUFN + 1) *cp1++ = ' ';
	(VOID) strcpy(cp1, "----   ----");
	if (addline(blp, line) == FALSE) return NULL;
	bp = bheadp;				/* For all buffers	*/
	while (bp != NULL) {
		cp1 = &line[0];			/* Start at left edge	*/
		*cp1++ = (bp == curbp) ? '.' : ' ';
		*cp1++ = ((bp->b_flag&BFCHG) != 0) ? '*' : ' ';
		*cp1++ = ' ';			/* Gap.			*/
		*cp1++ = ' ';
		cp2 = &bp->b_bname[0];		/* Buffer name		*/
		while ((c = *cp2++) != 0)
			*cp1++ = c;
		while (cp1 < &line[4+NBUFN+1])
			*cp1++ = ' ';		
		nbytes = 0;			/* Count bytes in buf.	*/
		if (bp != blp) {
			lp = lforw(bp->b_linep);
			while (lp != bp->b_linep) {
				nbytes += llength(lp)+1;
				lp = lforw(lp);
			}
		}
		(VOID) itor(b, 6, nbytes);	/* 6 digit buffer size.	*/
		cp2 = &b[0];
		while ((c = *cp2++) != 0)
			*cp1++ = c;
		*cp1++ = ' ';			/* Gap..			*/
		cp2 = &bp->b_fname[0];		/* File name		*/
		if (*cp2 != 0) {
			while ((c = *cp2++) != 0) {
				if (cp1 < &line[128-1])
					*cp1++ = c;
			}
		}
		*cp1 = 0;			/* Add to the buffer.	*/
		if (addline(blp, line) == FALSE)
			return NULL;
		bp = bp->b_bufp;
	}
	blp->b_dotp = lforw(blp->b_linep);	/* put dot at beginning of buffer */
	blp->b_doto = 0;
	return blp;				/* All done		*/
}

/*
 * Used above.
 */
static itor(buf, width, num)
register char buf[]; register int width; register RSIZE num; {
	register RSIZE r;

	if (num / 10 == 0) {
		buf[0] = (num % 10) + '0';
		for (r = 1; r < width; buf[r++] = ' ')
			;
		buf[width] = '\0';
		return 1;
	} else {
		buf[r = itor(buf, width, num / (RSIZE)10)] = 
				(num % (RSIZE)10) + '0';
		return r + 1;
	}
}

/*
 * The argument "text" points to
 * a string. Append this line to the
 * buffer. Handcraft the EOL
 * on the end. Return TRUE if it worked and
 * FALSE if you ran out of room.
 */
addline(bp, text) register BUFFER *bp; char *text; {
	register LINE	*lp;
	register int	i;
	register int	ntext;

	ntext = strlen(text);
	if ((lp=lalloc((RSIZE) ntext)) == NULL)
		return (FALSE);
	for (i=0; i<ntext; ++i)
		lputc(lp, i, text[i]);
	bp->b_linep->l_bp->l_fp = lp;		/* Hook onto the end	*/
	lp->l_bp = bp->b_linep->l_bp;
	bp->b_linep->l_bp = lp;
	lp->l_fp = bp->b_linep;
	if (bp->b_dotp == bp->b_linep)		/* If "." is at the end	*/
		bp->b_dotp = lp;		/* move it to new line	*/
	if (bp->b_markp == bp->b_linep)		/* ditto for mark 	*/
		bp->b_markp = lp;
	return (TRUE);
}

/*
 * Look through the list of buffers, giving the user
 * a chance to save them.  Return TRUE if there are
 * any changed buffers afterwards. Buffers that don't
 * have an associated file don't count. Return FALSE
 * if there are no changed buffers.
 */
anycb(f) {
	register BUFFER	*bp;
	register int	s = FALSE, save = FALSE;
	char		prompt[NFILEN + 11];

	for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
		if (*(bp->b_fname) != '\0'
		&&  (bp->b_flag&BFCHG) != 0) {
			(VOID) strcpy(prompt, "Save file ");
			(VOID) strcpy(prompt + 10, bp->b_fname);
			if ((f == TRUE || (save = eyorn(prompt)) == TRUE)
			&&  writeout(bp, bp->b_fname) == TRUE) {
				bp->b_flag &= ~BFCHG;
				upmodes(bp);
			} else s = TRUE;
			if (save == ABORT) return (save);
			save = TRUE;
		}
	}
	if (save == FALSE && kbdmop == NULL)
		ewprintf("(No files need saving)");
	return s;
}

/*
 * Search for a buffer, by name.
 * If not found, and the "cflag" is TRUE,
 * create a buffer and put it in the list of
 * all buffers. Return pointer to the BUFFER
 * block for the buffer.
 */
BUFFER	*
bfind(bname, cflag) register char *bname; {
	register BUFFER	*bp;
	char		*malloc();
	register LINE	*lp;

	bp = bheadp;
	while (bp != NULL) {
		if (strcmp(bname, bp->b_bname) == 0)
			return (bp);
		bp = bp->b_bufp;
	}
	if (cflag!=TRUE) return NULL;
	/*NOSTRICT*/
	if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL) {
		ewprintf("Can't get %d bytes", sizeof(BUFFER));
		return NULL;
	}
	if ((bp->b_bname=malloc(strlen(bname)+1)) == NULL) {
		ewprintf("Can't get %d bytes", strlen(bname)+1);
		free((char *) bp);
		return NULL;
	}
	if ((lp=lalloc((RSIZE) 0)) == NULL) {
		free(bp->b_bname);
		free((char *) bp);
		return NULL;
	}
	bp->b_altb = bp->b_bufp  = NULL;
	bp->b_dotp  = lp;
	bp->b_doto  = 0;
	bp->b_markp = NULL;
	bp->b_marko = 0;
	bp->b_flag  = 0;
	bp->b_nwnd  = 0;
	bp->b_linep = lp;
	(VOID) strcpy(bp->b_fname, "");
	(VOID) strcpy(bp->b_bname, bname);
	lp->l_fp = lp;
	lp->l_bp = lp;
	bp->b_bufp = bheadp;
	bheadp = bp;
	return (bp);
}

/*
 * This routine blows away all of the text
 * in a buffer. If the buffer is marked as changed
 * then we ask if it is ok to blow it away; this is
 * to save the user the grief of losing text. The
 * window chain is nearly always wrong if this gets
 * called; the caller must arrange for the updates
 * that are required. Return TRUE if everything
 * looks good.
 */
bclear(bp) register BUFFER *bp; {
	register LINE	*lp;
	register int	s;
	
	if ((bp->b_flag&BFCHG) != 0		/* Changed.		*/
	&& (s=eyesno("Buffer modified; kill anyway")) != TRUE)
		return (s);
	bp->b_flag  &= ~BFCHG;			/* Not changed		*/
	while ((lp=lforw(bp->b_linep)) != bp->b_linep)
		lfree(lp);
	bp->b_dotp  = bp->b_linep;		/* Fix "."		*/
	bp->b_doto  = 0;
	bp->b_markp = NULL;			/* Invalidate "mark"	*/
	bp->b_marko = 0;
	return (TRUE);
}

/*
 * Display the given buffer in the given window. Flags indicated
 * action on redisplay.
 */
showbuffer(bp, wp, flags) register BUFFER *bp; register WINDOW *wp; {
	register BUFFER	*obp;
	register WINDOW	*owp;

	if (wp->w_bufp == bp) {			/* Easy case!	*/
		wp->w_flag |= flags;
		return TRUE ;
	}

	/* First, dettach the old buffer from the window */
	if ((bp->b_altb = obp = wp->w_bufp) != NULL) {
		if (--obp->b_nwnd == 0) {
			obp->b_dotp  = wp->w_dotp;
			obp->b_doto  = wp->w_doto;
			obp->b_markp = wp->w_markp;
			obp->b_marko = wp->w_marko;
		}
	}

	/* Now, attach the new buffer to the window */
	wp->w_bufp = bp;

	if (bp->b_nwnd++ == 0) {		/* First use.		*/
		wp->w_dotp  = bp->b_dotp;
		wp->w_doto  = bp->b_doto;
		wp->w_markp = bp->b_markp;
		wp->w_marko = bp->b_marko;
	} else
	/* already on screen, steal values from other window */
		for (owp = wheadp; owp != NULL; owp = wp->w_wndp)
			if (wp->w_bufp == bp && owp != wp) {
				wp->w_dotp  = owp->w_dotp;
				wp->w_doto  = owp->w_doto;
				wp->w_markp = owp->w_markp;
				wp->w_marko = owp->w_marko;
				break;
			}
	wp->w_flag |= WFMODE|flags;
	return TRUE;
}

/*
 * Pop the buffer we got passed onto the screen.
 * Returns a status.
 */
WINDOW *
popbuf(bp) register BUFFER *bp; {
	register WINDOW	*wp;

	if (bp->b_nwnd == 0) {		/* Not on screen yet.	*/
		if ((wp=wpopup()) == NULL) return NULL;
	} else
		for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
			if (wp->w_bufp == bp) {
				wp->w_flag |= WFHARD|WFFORCE;
				return wp ;
			}
	if (showbuffer(bp, wp, WFHARD) != TRUE) return NULL;
	return wp;
}

/*
 * Insert another buffer at dot.  Very useful.
 */

bufferinsert(f, n, k)
{
	register BUFFER *bp;
	register LINE	*clp;
	register int	clo;
	register int	nline;
	int		s;
	char		bufn[NBUFN];

	/* Get buffer to use from user */
	if (curbp->b_altb != NULL)
		s=eread("Insert buffer: (default %s) ", bufn, NBUFN,
			 EFNEW|EFBUF, &(curbp->b_altb->b_bname),
			 (char *) NULL) ;
	else
		s=eread("Insert buffer: ", bufn, NBUFN, EFNEW|EFBUF,
			 (char *) NULL) ;
	if (s == ABORT) return (s);
	if (s == FALSE && curbp->b_altb != NULL) bp = curbp->b_altb;
	else if ((bp=bfind(bufn, FALSE)) == NULL) return (FALSE);

	if (bp==curbp) {
		ewprintf("Cannot insert buffer into self");
		return (FALSE);
	}

	/* insert the buffer */	
	nline = 0;
	for (clp = lforw(bp->b_linep); clp != bp->b_linep; clp = lforw(clp)) {
		for (clo = 0; clo < llength(clp); clo++)
			if (linsert((RSIZE)1, lgetc(clp, clo)) == FALSE)
				return (FALSE);
		if (newline(FALSE, 1, KRANDOM) == FALSE) /* fake newline */
			return (FALSE);
		nline++;
	}
	if (kbdmop==NULL) {
		if (nline == 1)
			ewprintf("[Inserted 1 line]");
		else
			ewprintf("[Inserted %d lines]", nline);
	}

	clp = curwp->w_linep;			/* cosmetic adjustment */
	if (curwp->w_dotp == clp) {		/* for offscreen insert */
		while (nline-- && lback(clp)!=curbp->b_linep)
			clp = lback(clp);
		curwp->w_linep = clp;		/* adjust framing.	*/
		curwp->w_flag |= WFHARD;
	}
	return (TRUE);
}

/*
 * Turn off the dirty bit on this buffer.
 */
/*ARGSUSED*/
notmodified(f, n, k)
{
	register WINDOW *wp;
	
	curbp->b_flag &= ~BFCHG;
	wp = wheadp;				/* Update mode lines.	*/
	while (wp != NULL) {
		if (wp->w_bufp == curbp)
			wp->w_flag |= WFMODE;
		wp = wp->w_wndp;
	}
	ewprintf("Modification-flag cleared");
	return (TRUE);
}