home *** CD-ROM | disk | FTP | other *** search
- /*
- * Buffer handling.
- */
- #include "no_help.h"
-
- #include "def.h"
- #include "line.h"
- #include "buffer.h"
- #include "window.h"
- #include "foob.h"
-
- #ifdef ANSI
- #include <stdlib.h>
- #include <string.h>
- #endif
-
- static RSIZE itor
- PROTO((char buf[], int, RSIZE));
-
- /*
- * 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.
- * *scratch* is the default alternate buffer.
- */
- /* ARGSUSED */
- usebuffer(f, n)
- {
- register struct buffer *bp;
- register int s;
- char bufn[NBUFN];
-
- /* Get buffer to use from user */
- if ((curbp->b_altb == NULL)
- && ((curbp->b_altb = bfind("*scratch*", TRUE)) == NULL))
- s = eread("Switch to buffer: ", bufn, NBUFN, EFNEW | EFBUF);
- else
- s = eread("Switch to buffer: (default %s) ", bufn, NBUFN,
- EFNEW | EFBUF, curbp->b_altb->b_bname);
-
- 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)
- {
- register struct buffer *bp;
- register struct window *wp;
- register int s;
- char bufn[NBUFN];
- struct window *popbuf();
-
- /* Get buffer to use from user */
- if ((curbp->b_altb == NULL)
- && ((curbp->b_altb = bfind("*scratch*", TRUE)) == NULL))
- s = eread("Switch to buffer in other window: ", bufn, NBUFN,
- EFNEW | EFBUF);
- else
- s = eread("Switch to buffer in other window: (default %s) ",
- bufn, NBUFN, EFNEW | EFBUF, curbp->b_altb->b_bname);
- 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)
- {
- register struct buffer *bp;
- register struct buffer *bp1;
- register struct buffer *bp2;
- struct window *wp;
- register int s;
- char bufn[NBUFN];
-
- if ((s = eread("Kill buffer: (default %s) ", bufn, NBUFN, EFNEW | EFBUF,
- curbp->b_bname)) == ABORT)
- return (s);
- else if (s == FALSE)
- bp = curbp;
- else if ((bp = bfind(bufn, FALSE)) == NULL)
- return FALSE;
-
- /*
- * find some other buffer to display. try the alternate buffer, then
- * the first different buffer in the buffer list. if there's
- * only one buffer, create buffer *scratch* and make it the alternate
- * buffer. return if *scratch* is only buffer
- */
- if ((bp1 = bp->b_altb) == NULL || bp1 == bp) {
- bp1 = (bp == bheadp) ? bp->b_bufp : bheadp;
- if (bp1 == NULL) {
- /* only one buffer. see if it's *scratch* */
- if (bp == bfind("*scratch*", FALSE))
- return FALSE;
- /* create *scratch* for alternate buffer */
- if ((bp1 = bfind("*scratch*", TRUE)) == NULL)
- return FALSE;
- }
- }
- if (bclear(bp) != TRUE)
- return TRUE;
- for (wp = wheadp; bp->b_nwnd > 0; wp = wp->w_wndp) {
- if (wp->w_bufp == bp) {
- bp2 = bp1->b_altb; /* save alternate buffer */
- if (showbuffer(bp1, wp, WFMODE | WFFORCE | WFHARD) != NULL)
- bp1->b_altb = bp2;
- else
- bp1 = bp2;
- }
- }
- if (bp == curbp)
- curbp = bp1;
- free((char *) bp->b_linep); /* Release header line. */
- bp2 = NULL; /* Find the header. */
- for (bp1 = bheadp; bp1 != bp; bp1 = bp1->b_bufp) {
- if (bp1->b_altb == bp)
- bp1->b_altb = (bp->b_altb == bp1) ? NULL : bp->b_altb;
- bp2 = bp1;
- }
- bp1 = bp1->b_bufp; /* Next one in chain. */
- if (bp2 == NULL) /* Unlink it. */
- bheadp = bp1;
- else
- bp2->b_bufp = bp1;
- while (bp1 != NULL) { /* Finish with altb's */
- if (bp1->b_altb == bp)
- bp1->b_altb = (bp->b_altb == bp1) ? NULL : bp->b_altb;
- bp1 = bp1->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)
- {
- 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)
- {
- register struct buffer *bp;
- register struct window *wp;
- struct buffer *makelist();
- struct window *popbuf();
-
- 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).
- */
- struct buffer *
- makelist()
- {
- register char *cp1;
- register char *cp2;
- register int c;
- register struct buffer *bp;
- struct line *lp;
- register RSIZE nbytes;
- struct buffer *blp;
- char b[6 + 1];
- char line[128];
-
- if ((blp = bfind("*Buffer List*", TRUE)) == NULL)
- return NULL;
- blp->b_flag &= ~BFCHG; /* Blow away old. */
- if (bclear(blp) != TRUE)
- return NULL;
-
- (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;
- for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
- 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);
- }
- if (nbytes)
- nbytes--; /* no bonus newline */
- }
- (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;
- }
- blp->b_dotp = lforw(blp->b_linep); /* put dot at beginning of
- * buffer */
- blp->b_doto = 0;
- return blp; /* All done */
- }
-
- /*
- * Used above.
- */
- static RSIZE
- 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;
- }
- /* NOTREACHED */
- }
-
- /*
- * 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 struct buffer *bp;
- char *text;
- {
- register struct line *lp;
- register int i;
- register int ntext;
-
- if (!text)
- return FALSE;
- ntext = strlen(text);
- if ((lp = lalloc(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;
- #ifdef notdef
- 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;
- #endif
- 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 struct buffer *bp;
- register int unsaved = FALSE, t, none = TRUE;
- 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);
- none = t = FALSE;
- if (f == TRUE || (t = eyorn(prompt)) == TRUE)
- t = buffsave(bp);
- if (t == ABORT)
- return t;
- unsaved = unsaved || !t;
- }
- }
- if (none) ewprintf("(No files need saving)");
- return unsaved;
- }
-
- /*
- * 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.
- */
- struct buffer *
- bfind(bname, cflag)
- register char *bname;
- {
- register struct buffer *bp;
- register struct line *lp;
- int i;
- extern int defb_nmodes;
- extern struct maps *defb_modes[PBMODES];
- extern int defb_flag;
-
- if (!bname)
- return NULL;
- bp = bheadp;
- while (bp != NULL) {
- if (fncmp(bname, bp->b_bname) == 0)
- return bp;
- bp = bp->b_bufp;
- }
- if (cflag != TRUE)
- return NULL;
- /* NOSTRICT */
- if ((bp = (struct buffer *) malloc(sizeof(struct buffer))) == NULL) {
- ewprintf("Can't get %d bytes", sizeof(struct buffer));
- return NULL;
- }
- if ((bp->b_bname = (char *) malloc((unsigned) (strlen(bname) + 1))) == NULL) {
- ewprintf("Can't get %d bytes", strlen(bname) + 1);
- free((char *) bp);
- return NULL;
- }
- if ((lp = lalloc(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 = defb_flag;
- bp->b_nwnd = 0;
- bp->b_linep = lp;
- bp->b_nmodes = defb_nmodes;
- #ifdef FOOB
- bp->b_foob = getfoob((char *) NULL);
- #endif
-
- i = 0;
- do {
- bp->b_modes[i] = defb_modes[i];
- } while (i++ < defb_nmodes);
- bp->b_fname[0] = '\0';
- (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 struct buffer *bp;
- {
- register struct line *lp;
- register int s;
- VOID lfree();
-
- 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 struct buffer *bp;
- register struct window *wp;
- {
- register struct buffer *obp;
- struct 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.
- */
- struct window *
- popbuf(bp)
- register struct buffer *bp;
- {
- register struct 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.
- */
- /* ARGSUSED */
- bufferinsert(f, n)
- {
- register struct buffer *bp;
- register struct 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;
- clp = lforw(bp->b_linep);
- for (;;) {
- for (clo = 0; clo < llength(clp); clo++)
- if (linsert(1, lgetc(clp, clo)) == FALSE)
- return FALSE;
- if ((clp = lforw(clp)) == bp->b_linep)
- break;
- if (newline(FFRAND, 1) == FALSE) /* fake newline */
- return FALSE;
- nline++;
- }
- 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)
- {
- register struct 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;
- }
-
- #ifndef NO_HELP
- /*
- * Popbuf and set all windows to top of buffer. Currently only used by help
- * functions.
- */
-
- popbuftop(bp)
- register struct buffer *bp;
- {
- register struct window *wp;
-
- bp->b_dotp = lforw(bp->b_linep);
- bp->b_doto = 0;
- if (bp->b_nwnd != 0) {
- for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
- if (wp->w_bufp == bp) {
- wp->w_dotp = bp->b_dotp;
- wp->w_doto = 0;
- wp->w_flag |= WFHARD;
- }
- }
- return popbuf(bp) != NULL;
- }
- #endif
-