[BACK]Return to buffer.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/buffer.c, Revision 1.56

1.56    ! kjell       1: /*     $OpenBSD: buffer.c,v 1.55 2006/04/03 00:40:56 deraadt Exp $     */
1.43      kjell       2:
                      3: /* This file is in the public domain. */
1.5       niklas      4:
1.1       deraadt     5: /*
                      6:  *             Buffer handling.
                      7:  */
1.4       millert     8:
1.56    ! kjell       9: #include <libgen.h>
        !            10: #include <stdarg.h>
        !            11:
1.4       millert    12: #include "def.h"
                     13: #include "kbd.h"               /* needed for modes */
1.1       deraadt    14:
1.52      deraadt    15: static struct buffer  *makelist(void);
1.1       deraadt    16:
1.50      kjell      17: /* ARGSUSED */
1.27      vincent    18: int
1.31      vincent    19: togglereadonly(int f, int n)
1.27      vincent    20: {
1.47      kjell      21:        if (!(curbp->b_flag & BFREADONLY))
1.27      vincent    22:                curbp->b_flag |= BFREADONLY;
1.47      kjell      23:        else {
1.27      vincent    24:                curbp->b_flag &=~ BFREADONLY;
                     25:                if (curbp->b_flag & BFCHG)
                     26:                        ewprintf("Warning: Buffer was modified");
                     27:        }
                     28:        curwp->w_flag |= WFMODE;
                     29:
1.47      kjell      30:        return (TRUE);
1.27      vincent    31: }
                     32:
1.1       deraadt    33: /*
                     34:  * Attach a buffer to a window. The values of dot and mark come
                     35:  * from the buffer if the use count is 0. Otherwise, they come
                     36:  * from some other window.  *scratch* is the default alternate
                     37:  * buffer.
                     38:  */
1.3       millert    39: /* ARGSUSED */
                     40: int
1.26      vincent    41: usebuffer(int f, int n)
1.1       deraadt    42: {
1.52      deraadt    43:        struct buffer *bp;
1.34      vincent    44:        char    bufn[NBUFN], *bufp;
1.1       deraadt    45:
                     46:        /* Get buffer to use from user */
1.21      deraadt    47:        if ((curbp->b_altb == NULL) &&
                     48:            ((curbp->b_altb = bfind("*scratch*", TRUE)) == NULL))
1.34      vincent    49:                bufp = eread("Switch to buffer: ", bufn, NBUFN, EFNEW | EFBUF);
1.1       deraadt    50:        else
1.34      vincent    51:                bufp = eread("Switch to buffer: (default %s) ", bufn, NBUFN,
1.55      deraadt    52:                    EFNUL | EFNEW | EFBUF, curbp->b_altb->b_bname);
1.1       deraadt    53:
1.34      vincent    54:        if (bufp == NULL)
1.37      db         55:                return (ABORT);
1.44      kjell      56:        if (bufp[0] == '\0' && curbp->b_altb != NULL)
1.3       millert    57:                bp = curbp->b_altb;
                     58:        else if ((bp = bfind(bufn, TRUE)) == NULL)
1.37      db         59:                return (FALSE);
1.1       deraadt    60:
                     61:        /* and put it in current window */
                     62:        curbp = bp;
1.37      db         63:        return (showbuffer(bp, curwp, WFFORCE | WFHARD));
1.1       deraadt    64: }
                     65:
                     66: /*
                     67:  * pop to buffer asked for by the user.
                     68:  */
1.3       millert    69: /* ARGSUSED */
                     70: int
1.26      vincent    71: poptobuffer(int f, int n)
1.1       deraadt    72: {
1.52      deraadt    73:        struct buffer *bp;
                     74:        struct mgwin  *wp;
1.34      vincent    75:        char    bufn[NBUFN], *bufp;
1.1       deraadt    76:
                     77:        /* Get buffer to use from user */
1.21      deraadt    78:        if ((curbp->b_altb == NULL) &&
                     79:            ((curbp->b_altb = bfind("*scratch*", TRUE)) == NULL))
1.34      vincent    80:                bufp = eread("Switch to buffer in other window: ", bufn, NBUFN,
1.55      deraadt    81:                    EFNEW | EFBUF);
1.1       deraadt    82:        else
1.34      vincent    83:                bufp = eread("Switch to buffer in other window: (default %s) ",
1.55      deraadt    84:                    bufn, NBUFN, EFNUL | EFNEW | EFBUF, curbp->b_altb->b_bname);
1.34      vincent    85:        if (bufp == NULL)
1.37      db         86:                return (ABORT);
1.44      kjell      87:        if (bufp[0] == '\0' && curbp->b_altb != NULL)
1.3       millert    88:                bp = curbp->b_altb;
                     89:        else if ((bp = bfind(bufn, TRUE)) == NULL)
1.37      db         90:                return (FALSE);
1.1       deraadt    91:
                     92:        /* and put it in a new window */
1.3       millert    93:        if ((wp = popbuf(bp)) == NULL)
1.37      db         94:                return (FALSE);
1.1       deraadt    95:        curbp = bp;
                     96:        curwp = wp;
1.37      db         97:        return (TRUE);
1.1       deraadt    98: }
                     99:
                    100: /*
                    101:  * Dispose of a buffer, by name.
                    102:  * Ask for the name. Look it up (don't get too
                    103:  * upset if it isn't there at all!). Clear the buffer (ask
                    104:  * if the buffer has been changed). Then free the header
                    105:  * line and the buffer header. Bound to "C-X K".
                    106:  */
1.3       millert   107: /* ARGSUSED */
                    108: int
1.35      jfb       109: killbuffer_cmd(int f, int n)
1.1       deraadt   110: {
1.52      deraadt   111:        struct buffer *bp;
1.34      vincent   112:        char    bufn[NBUFN], *bufp;
1.3       millert   113:
1.40      kjell     114:        if ((bufp = eread("Kill buffer: (default %s) ", bufn, NBUFN,
                    115:            EFNUL | EFNEW | EFBUF, curbp->b_bname)) == NULL)
1.37      db        116:                return (ABORT);
1.44      kjell     117:        else if (bufp[0] == '\0')
1.3       millert   118:                bp = curbp;
                    119:        else if ((bp = bfind(bufn, FALSE)) == NULL)
1.37      db        120:                return (FALSE);
                    121:        return (killbuffer(bp));
1.35      jfb       122: }
                    123:
                    124: int
1.52      deraadt   125: killbuffer(struct buffer *bp)
1.35      jfb       126: {
1.52      deraadt   127:        struct buffer *bp1;
                    128:        struct buffer *bp2;
                    129:        struct mgwin  *wp;
1.41      kjell     130:        int s;
1.48      deraadt   131:        struct undo_rec *rec, *next;
1.3       millert   132:
                    133:        /*
1.37      db        134:         * Find some other buffer to display. Try the alternate buffer,
1.3       millert   135:         * then the first different buffer in the buffer list.  If there's
                    136:         * only one buffer, create buffer *scratch* and make it the alternate
                    137:         * buffer.  Return if *scratch* is only buffer...
1.1       deraadt   138:         */
                    139:        if ((bp1 = bp->b_altb) == NULL) {
                    140:                bp1 = (bp == bheadp) ? bp->b_bufp : bheadp;
                    141:                if (bp1 == NULL) {
                    142:                        /* only one buffer. see if it's *scratch* */
1.3       millert   143:                        if (bp == bfind("*scratch*", FALSE))
1.49      kjell     144:                                return (TRUE);
1.1       deraadt   145:                        /* create *scratch* for alternate buffer */
1.3       millert   146:                        if ((bp1 = bfind("*scratch*", TRUE)) == NULL)
1.37      db        147:                                return (FALSE);
1.1       deraadt   148:                }
                    149:        }
1.41      kjell     150:        if ((s = bclear(bp)) != TRUE)
                    151:                return (s);
1.1       deraadt   152:        for (wp = wheadp; bp->b_nwnd > 0; wp = wp->w_wndp) {
1.3       millert   153:                if (wp->w_bufp == bp) {
                    154:                        bp2 = bp1->b_altb;      /* save alternate buffer */
                    155:                        if (showbuffer(bp1, wp, WFMODE | WFFORCE | WFHARD))
                    156:                                bp1->b_altb = bp2;
                    157:                        else
                    158:                                bp1 = bp2;
                    159:                }
                    160:        }
                    161:        if (bp == curbp)
                    162:                curbp = bp1;
                    163:        free(bp->b_linep);                      /* Release header line.  */
                    164:        bp2 = NULL;                             /* Find the header.      */
1.1       deraadt   165:        bp1 = bheadp;
                    166:        while (bp1 != bp) {
                    167:                if (bp1->b_altb == bp)
                    168:                        bp1->b_altb = (bp->b_altb == bp1) ? NULL : bp->b_altb;
                    169:                bp2 = bp1;
                    170:                bp1 = bp1->b_bufp;
                    171:        }
1.3       millert   172:        bp1 = bp1->b_bufp;                      /* Next one in chain.    */
                    173:        if (bp2 == NULL)                        /* Unlink it.            */
1.1       deraadt   174:                bheadp = bp1;
                    175:        else
                    176:                bp2->b_bufp = bp1;
1.3       millert   177:        while (bp1 != NULL) {                   /* Finish with altb's    */
1.1       deraadt   178:                if (bp1->b_altb == bp)
                    179:                        bp1->b_altb = (bp->b_altb == bp1) ? NULL : bp->b_altb;
                    180:                bp1 = bp1->b_bufp;
                    181:        }
1.46      kjell     182:        rec = LIST_FIRST(&bp->b_undo);
                    183:        while (rec != NULL) {
                    184:                next = LIST_NEXT(rec, next);
                    185:                free_undo_record(rec);
                    186:                rec = next;
                    187:        }
                    188:
1.54      kjell     189:        free(bp->b_bname);                      /* Release name block    */
1.3       millert   190:        free(bp);                               /* Release buffer block */
1.37      db        191:        return (TRUE);
1.1       deraadt   192: }
                    193:
                    194: /*
                    195:  * Save some buffers - just call anycb with the arg flag.
                    196:  */
1.3       millert   197: /* ARGSUSED */
                    198: int
1.26      vincent   199: savebuffers(int f, int n)
1.1       deraadt   200: {
1.3       millert   201:        if (anycb(f) == ABORT)
1.37      db        202:                return (ABORT);
                    203:        return (TRUE);
1.1       deraadt   204: }
                    205:
                    206: /*
1.19      art       207:  * Listing buffers.
                    208:  */
                    209: static int listbuf_ncol;
                    210:
                    211: static int     listbuf_goto_buffer(int f, int n);
1.39      jason     212: static int     listbuf_goto_buffer_one(int f, int n);
                    213: static int     listbuf_goto_buffer_helper(int f, int n, int only);
1.19      art       214:
                    215: static PF listbuf_pf[] = {
1.37      db        216:        listbuf_goto_buffer
1.19      art       217: };
1.39      jason     218: static PF listbuf_one[] = {
                    219:        listbuf_goto_buffer_one
                    220: };
                    221:
1.19      art       222:
1.39      jason     223: static struct KEYMAPE (2 + IMAPEXT) listbufmap = {
                    224:        2,
                    225:        2 + IMAPEXT,
1.19      art       226:        rescan,
                    227:        {
1.39      jason     228:                {
1.45      deraadt   229:                        CCHR('M'), CCHR('M'), listbuf_pf, NULL
1.39      jason     230:                },
                    231:                {
1.45      deraadt   232:                        '1', '1', listbuf_one, NULL
1.39      jason     233:                }
1.19      art       234:        }
                    235: };
                    236:
                    237: /*
1.1       deraadt   238:  * Display the buffer list. This is done
                    239:  * in two parts. The "makelist" routine figures out
                    240:  * the text, and puts it in a buffer. "popbuf"
                    241:  * then pops the data onto the screen. Bound to
                    242:  * "C-X C-B".
                    243:  */
1.3       millert   244: /* ARGSUSED */
                    245: int
1.26      vincent   246: listbuffers(int f, int n)
1.1       deraadt   247: {
1.52      deraadt   248:        static int               initialized = 0;
                    249:        struct buffer           *bp;
                    250:        struct mgwin            *wp;
1.1       deraadt   251:
1.19      art       252:        if (!initialized) {
                    253:                maps_add((KEYMAP *)&listbufmap, "listbufmap");
                    254:                initialized = 1;
                    255:        }
                    256:
1.3       millert   257:        if ((bp = makelist()) == NULL || (wp = popbuf(bp)) == NULL)
1.37      db        258:                return (FALSE);
                    259:        wp->w_dotp = bp->b_dotp; /* fix up if window already on screen */
1.1       deraadt   260:        wp->w_doto = bp->b_doto;
1.19      art       261:        bp->b_modes[0] = name_mode("fundamental");
                    262:        bp->b_modes[1] = name_mode("listbufmap");
                    263:        bp->b_nmodes = 1;
                    264:
1.37      db        265:        return (TRUE);
1.1       deraadt   266: }
                    267:
                    268: /*
                    269:  * This routine rebuilds the text for the
1.37      db        270:  * list buffers command. Return pointer
                    271:  * to new list if everything works.
                    272:  * Return NULL if there is an error (if
                    273:  * there is no memory).
1.1       deraadt   274:  */
1.52      deraadt   275: static struct buffer *
1.26      vincent   276: makelist(void)
1.3       millert   277: {
1.52      deraadt   278:        int             w = ncol / 2;
                    279:        struct buffer   *bp, *blp;
                    280:        struct line     *lp;
1.19      art       281:
1.3       millert   282:        if ((blp = bfind("*Buffer List*", TRUE)) == NULL)
1.37      db        283:                return (NULL);
1.3       millert   284:        if (bclear(blp) != TRUE)
1.37      db        285:                return (NULL);
1.3       millert   286:        blp->b_flag &= ~BFCHG;          /* Blow away old.        */
1.28      vincent   287:        blp->b_flag |= BFREADONLY;
1.1       deraadt   288:
1.19      art       289:        listbuf_ncol = ncol;            /* cache ncol for listbuf_goto_buffer */
                    290:
1.11      art       291:        if (addlinef(blp, "%-*s%s", w, " MR Buffer", "Size   File") == FALSE ||
                    292:            addlinef(blp, "%-*s%s", w, " -- ------", "----   ----") == FALSE)
1.37      db        293:                return (NULL);
1.11      art       294:
                    295:        for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
                    296:                RSIZE nbytes;
                    297:
1.3       millert   298:                nbytes = 0;                     /* Count bytes in buf.   */
1.1       deraadt   299:                if (bp != blp) {
                    300:                        lp = lforw(bp->b_linep);
                    301:                        while (lp != bp->b_linep) {
1.3       millert   302:                                nbytes += llength(lp) + 1;
1.1       deraadt   303:                                lp = lforw(lp);
                    304:                        }
1.3       millert   305:                        if (nbytes)
                    306:                                nbytes--;       /* no bonus newline      */
1.1       deraadt   307:                }
1.11      art       308:
1.19      art       309:                if (addlinef(blp, "%c%c%c %-*.*s%c%-6d %-*s",
1.11      art       310:                    (bp == curbp) ? '.' : ' ',  /* current buffer ? */
                    311:                    ((bp->b_flag & BFCHG) != 0) ? '*' : ' ',    /* changed ? */
1.27      vincent   312:                    ((bp->b_flag & BFREADONLY) != 0) ? ' ' : '*',
1.19      art       313:                    w - 5,              /* four chars already written */
                    314:                    w - 5,              /* four chars already written */
1.11      art       315:                    bp->b_bname,        /* buffer name */
1.19      art       316:                    strlen(bp->b_bname) < w - 5 ? ' ' : '$', /* truncated? */
1.11      art       317:                    nbytes,             /* buffer size */
                    318:                    w - 7,              /* seven chars already written */
                    319:                    bp->b_fname) == FALSE)
1.37      db        320:                        return (NULL);
1.1       deraadt   321:        }
1.3       millert   322:        blp->b_dotp = lforw(blp->b_linep);      /* put dot at beginning of
                    323:                                                 * buffer */
1.1       deraadt   324:        blp->b_doto = 0;
1.37      db        325:        return (blp);                           /* All done              */
1.19      art       326: }
                    327:
                    328: static int
                    329: listbuf_goto_buffer(int f, int n)
                    330: {
1.39      jason     331:        return (listbuf_goto_buffer_helper(f, n, 0));
                    332: }
                    333:
                    334: static int
                    335: listbuf_goto_buffer_one(int f, int n)
                    336: {
                    337:        return (listbuf_goto_buffer_helper(f, n, 1));
                    338: }
                    339:
                    340: static int
                    341: listbuf_goto_buffer_helper(int f, int n, int only)
                    342: {
1.52      deraadt   343:        struct buffer   *bp;
                    344:        struct mgwin    *wp;
                    345:        char            *line = NULL;
                    346:        int              i, ret = FALSE;
1.19      art       347:
                    348:        if (curwp->w_dotp->l_text[listbuf_ncol/2 - 1] == '$') {
                    349:                ewprintf("buffer name truncated");
1.37      db        350:                return (FALSE);
1.19      art       351:        }
                    352:
                    353:        if ((line = malloc(listbuf_ncol/2)) == NULL)
1.37      db        354:                return (FALSE);
1.19      art       355:
                    356:        memcpy(line, curwp->w_dotp->l_text + 4, listbuf_ncol/2 - 5);
                    357:        for (i = listbuf_ncol/2 - 6; i > 0; i--) {
                    358:                if (line[i] != ' ') {
                    359:                        line[i + 1] = '\0';
                    360:                        break;
                    361:                }
                    362:        }
1.37      db        363:        if (i == 0)
1.42      cloder    364:                goto cleanup;
1.19      art       365:
                    366:        for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
                    367:                if (strcmp(bp->b_bname, line) == 0)
                    368:                        break;
                    369:        }
1.37      db        370:        if (bp == NULL)
1.42      cloder    371:                goto cleanup;
1.37      db        372:
1.19      art       373:        if ((wp = popbuf(bp)) == NULL)
1.42      cloder    374:                goto cleanup;
1.19      art       375:        curbp = bp;
                    376:        curwp = wp;
1.39      jason     377:
                    378:        if (only)
1.42      cloder    379:                ret = (onlywind(f, n));
                    380:        else
                    381:                ret = TRUE;
                    382:
                    383: cleanup:
                    384:        free(line);
1.19      art       385:
1.42      cloder    386:        return (ret);
1.1       deraadt   387: }
                    388:
                    389: /*
1.47      kjell     390:  * The argument "fmt" points to a format string.  Append this line to the
1.3       millert   391:  * buffer. Handcraft the EOL on the end.  Return TRUE if it worked and
1.1       deraadt   392:  * FALSE if you ran out of room.
                    393:  */
1.3       millert   394: int
1.52      deraadt   395: addlinef(struct buffer *bp, char *fmt, ...)
1.3       millert   396: {
1.52      deraadt   397:        va_list          ap;
                    398:        struct line     *lp;
1.1       deraadt   399:
1.30      vincent   400:        if ((lp = lalloc(0)) == NULL)
                    401:                return (FALSE);
1.8       art       402:        va_start(ap, fmt);
1.30      vincent   403:        if (vasprintf(&lp->l_text, fmt, ap) == -1) {
                    404:                lfree(lp);
1.16      deraadt   405:                va_end(ap);
1.30      vincent   406:                return (FALSE);
1.16      deraadt   407:        }
1.30      vincent   408:        lp->l_used = strlen(lp->l_text);
1.8       art       409:        va_end(ap);
                    410:
1.3       millert   411:        bp->b_linep->l_bp->l_fp = lp;           /* Hook onto the end     */
1.1       deraadt   412:        lp->l_bp = bp->b_linep->l_bp;
                    413:        bp->b_linep->l_bp = lp;
                    414:        lp->l_fp = bp->b_linep;
1.8       art       415:
1.37      db        416:        return (TRUE);
1.1       deraadt   417: }
                    418:
                    419: /*
1.3       millert   420:  * Look through the list of buffers, giving the user a chance to save them.
1.51      kjell     421:  * Return TRUE if there are any changed buffers afterwards.  Buffers that don't
                    422:  * have an associated file don't count.  Return FALSE if there are no changed
                    423:  * buffers.  Return ABORT if an error occurs or if the user presses c-g.
1.3       millert   424:  */
                    425: int
1.26      vincent   426: anycb(int f)
1.3       millert   427: {
1.52      deraadt   428:        struct buffer   *bp;
                    429:        int              s = FALSE, save = FALSE, ret;
1.53      kjell     430:        char             pbuf[NFILEN + 11];
1.1       deraadt   431:
                    432:        for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
1.21      deraadt   433:                if (bp->b_fname != NULL && *(bp->b_fname) != '\0' &&
                    434:                    (bp->b_flag & BFCHG) != 0) {
1.53      kjell     435:                        ret = snprintf(pbuf, sizeof(pbuf), "Save file %s",
1.17      deraadt   436:                            bp->b_fname);
1.53      kjell     437:                        if (ret < 0 || ret >= sizeof(pbuf)) {
1.51      kjell     438:                                ewprintf("Error: filename too long!");
                    439:                                return (ABORT);
                    440:                        }
1.53      kjell     441:                        if ((f == TRUE || (save = eyorn(pbuf)) == TRUE) &&
1.21      deraadt   442:                            buffsave(bp) == TRUE) {
1.1       deraadt   443:                                bp->b_flag &= ~BFCHG;
                    444:                                upmodes(bp);
1.3       millert   445:                        } else
                    446:                                s = TRUE;
                    447:                        if (save == ABORT)
                    448:                                return (save);
1.1       deraadt   449:                        save = TRUE;
                    450:                }
                    451:        }
                    452:        if (save == FALSE /* && kbdmop == NULL */ )     /* experimental */
                    453:                ewprintf("(No files need saving)");
1.37      db        454:        return (s);
1.1       deraadt   455: }
                    456:
                    457: /*
                    458:  * Search for a buffer, by name.
                    459:  * If not found, and the "cflag" is TRUE,
                    460:  * create a buffer and put it in the list of
                    461:  * all buffers. Return pointer to the BUFFER
                    462:  * block for the buffer.
                    463:  */
1.52      deraadt   464: struct buffer *
1.26      vincent   465: bfind(const char *bname, int cflag)
1.3       millert   466: {
1.52      deraadt   467:        struct buffer   *bp;
                    468:        struct line     *lp;
                    469:        int              i;
1.1       deraadt   470:
                    471:        bp = bheadp;
                    472:        while (bp != NULL) {
1.7       art       473:                if (strcmp(bname, bp->b_bname) == 0)
1.37      db        474:                        return (bp);
1.1       deraadt   475:                bp = bp->b_bufp;
                    476:        }
1.3       millert   477:        if (cflag != TRUE)
1.37      db        478:                return (NULL);
1.29      vincent   479:
1.52      deraadt   480:        bp = calloc(1, sizeof(struct buffer));
1.32      vincent   481:        if (bp == NULL) {
1.52      deraadt   482:                ewprintf("Can't get %d bytes", sizeof(struct buffer));
1.37      db        483:                return (NULL);
1.1       deraadt   484:        }
1.20      vincent   485:        if ((bp->b_bname = strdup(bname)) == NULL) {
1.3       millert   486:                ewprintf("Can't get %d bytes", strlen(bname) + 1);
1.29      vincent   487:                free(bp);
1.37      db        488:                return (NULL);
1.1       deraadt   489:        }
                    490:        if ((lp = lalloc(0)) == NULL) {
1.54      kjell     491:                free(bp->b_bname);
1.29      vincent   492:                free(bp);
1.37      db        493:                return (NULL);
1.1       deraadt   494:        }
1.3       millert   495:        bp->b_altb = bp->b_bufp = NULL;
                    496:        bp->b_dotp = lp;
                    497:        bp->b_doto = 0;
1.1       deraadt   498:        bp->b_markp = NULL;
                    499:        bp->b_marko = 0;
1.3       millert   500:        bp->b_flag = defb_flag;
                    501:        bp->b_nwnd = 0;
1.1       deraadt   502:        bp->b_linep = lp;
                    503:        bp->b_nmodes = defb_nmodes;
1.46      kjell     504:        LIST_INIT(&bp->b_undo);
                    505:        bp->b_undoptr = NULL;
                    506:        memset(&bp->b_undopos, 0, sizeof(bp->b_undopos));
1.1       deraadt   507:        i = 0;
                    508:        do {
1.3       millert   509:                bp->b_modes[i] = defb_modes[i];
                    510:        } while (i++ < defb_nmodes);
1.1       deraadt   511:        bp->b_fname[0] = '\0';
                    512:        bzero(&bp->b_fi, sizeof(bp->b_fi));
                    513:        lp->l_fp = lp;
                    514:        lp->l_bp = lp;
                    515:        bp->b_bufp = bheadp;
                    516:        bheadp = bp;
1.37      db        517:        return (bp);
1.1       deraadt   518: }
                    519:
                    520: /*
                    521:  * This routine blows away all of the text
                    522:  * in a buffer. If the buffer is marked as changed
                    523:  * then we ask if it is ok to blow it away; this is
                    524:  * to save the user the grief of losing text. The
                    525:  * window chain is nearly always wrong if this gets
                    526:  * called; the caller must arrange for the updates
                    527:  * that are required. Return TRUE if everything
                    528:  * looks good.
                    529:  */
1.3       millert   530: int
1.52      deraadt   531: bclear(struct buffer *bp)
1.3       millert   532: {
1.52      deraadt   533:        struct line     *lp;
                    534:        int              s;
1.1       deraadt   535:
1.37      db        536:        if ((bp->b_flag & BFCHG) != 0 &&        /* Changed. */
1.21      deraadt   537:            (s = eyesno("Buffer modified; kill anyway")) != TRUE)
1.1       deraadt   538:                return (s);
1.3       millert   539:        bp->b_flag &= ~BFCHG;   /* Not changed           */
                    540:        while ((lp = lforw(bp->b_linep)) != bp->b_linep)
1.1       deraadt   541:                lfree(lp);
1.32      vincent   542:        bp->b_dotp = bp->b_linep;       /* Fix dot */
1.3       millert   543:        bp->b_doto = 0;
                    544:        bp->b_markp = NULL;     /* Invalidate "mark"     */
1.1       deraadt   545:        bp->b_marko = 0;
1.37      db        546:        return (TRUE);
1.1       deraadt   547: }
                    548:
                    549: /*
                    550:  * Display the given buffer in the given window. Flags indicated
                    551:  * action on redisplay.
                    552:  */
1.3       millert   553: int
1.52      deraadt   554: showbuffer(struct buffer *bp, struct mgwin *wp, int flags)
1.3       millert   555: {
1.52      deraadt   556:        struct buffer   *obp;
                    557:        struct mgwin    *owp;
1.1       deraadt   558:
1.32      vincent   559:        if (wp->w_bufp == bp) { /* Easy case! */
1.1       deraadt   560:                wp->w_flag |= flags;
1.32      vincent   561:                wp->w_dotp = bp->b_dotp;
                    562:                wp->w_doto = bp->b_doto;
1.37      db        563:                return (TRUE);
1.1       deraadt   564:        }
1.37      db        565:        /* First, detach the old buffer from the window */
1.1       deraadt   566:        if ((bp->b_altb = obp = wp->w_bufp) != NULL) {
                    567:                if (--obp->b_nwnd == 0) {
1.3       millert   568:                        obp->b_dotp = wp->w_dotp;
                    569:                        obp->b_doto = wp->w_doto;
1.1       deraadt   570:                        obp->b_markp = wp->w_markp;
                    571:                        obp->b_marko = wp->w_marko;
                    572:                }
                    573:        }
                    574:        /* Now, attach the new buffer to the window */
                    575:        wp->w_bufp = bp;
                    576:
1.3       millert   577:        if (bp->b_nwnd++ == 0) {        /* First use.            */
                    578:                wp->w_dotp = bp->b_dotp;
                    579:                wp->w_doto = bp->b_doto;
1.1       deraadt   580:                wp->w_markp = bp->b_markp;
                    581:                wp->w_marko = bp->b_marko;
                    582:        } else
1.3       millert   583:                /* already on screen, steal values from other window */
1.1       deraadt   584:                for (owp = wheadp; owp != NULL; owp = wp->w_wndp)
                    585:                        if (wp->w_bufp == bp && owp != wp) {
1.3       millert   586:                                wp->w_dotp = owp->w_dotp;
                    587:                                wp->w_doto = owp->w_doto;
1.1       deraadt   588:                                wp->w_markp = owp->w_markp;
                    589:                                wp->w_marko = owp->w_marko;
                    590:                                break;
                    591:                        }
1.3       millert   592:        wp->w_flag |= WFMODE | flags;
1.56    ! kjell     593:        return (TRUE);
        !           594: }
        !           595:
        !           596: /*
        !           597:  * Augment a buffer name with a number, if necessary
        !           598:  *
        !           599:  * If more than one file of the same basename() is open,
        !           600:  * the additional buffers are named "file<2>", "file<3>", and
        !           601:  * so forth.  This function adjusts a buffer name to
        !           602:  * include the number, if necessary.
        !           603:  */
        !           604: int
        !           605: baugname(char *bn, const char *fn, size_t bs)
        !           606: {
        !           607:        int      count;
        !           608:        size_t   remain, len;
        !           609:
        !           610:        len = strlcpy(bn, basename(fn), bs);
        !           611:        if (len >= bs)
        !           612:                return (FALSE);
        !           613:
        !           614:        remain = bs - len;
        !           615:        for (count = 2; bfind(bn, FALSE) != NULL; count++)
        !           616:                snprintf(bn + len, remain, "<%d>", count);
        !           617:
1.37      db        618:        return (TRUE);
1.1       deraadt   619: }
                    620:
                    621: /*
                    622:  * Pop the buffer we got passed onto the screen.
                    623:  * Returns a status.
                    624:  */
1.52      deraadt   625: struct mgwin *
                    626: popbuf(struct buffer *bp)
1.3       millert   627: {
1.52      deraadt   628:        struct mgwin    *wp;
1.1       deraadt   629:
1.3       millert   630:        if (bp->b_nwnd == 0) {  /* Not on screen yet.    */
                    631:                if ((wp = wpopup()) == NULL)
1.37      db        632:                        return (NULL);
1.1       deraadt   633:        } else
                    634:                for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
                    635:                        if (wp->w_bufp == bp) {
1.3       millert   636:                                wp->w_flag |= WFHARD | WFFORCE;
1.37      db        637:                                return (wp);
1.1       deraadt   638:                        }
1.3       millert   639:        if (showbuffer(bp, wp, WFHARD) != TRUE)
1.37      db        640:                return (NULL);
                    641:        return (wp);
1.1       deraadt   642: }
                    643:
                    644: /*
                    645:  * Insert another buffer at dot.  Very useful.
                    646:  */
1.3       millert   647: /* ARGSUSED */
                    648: int
1.26      vincent   649: bufferinsert(int f, int n)
1.1       deraadt   650: {
1.52      deraadt   651:        struct buffer *bp;
                    652:        struct line   *clp;
1.36      deraadt   653:        int     clo, nline;
                    654:        char    bufn[NBUFN], *bufp;
1.1       deraadt   655:
                    656:        /* Get buffer to use from user */
                    657:        if (curbp->b_altb != NULL)
1.34      vincent   658:                bufp = eread("Insert buffer: (default %s) ", bufn, NBUFN,
1.40      kjell     659:                    EFNUL | EFNEW | EFBUF, curbp->b_altb->b_bname);
1.1       deraadt   660:        else
1.38      cloder    661:                bufp = eread("Insert buffer: ", bufn, NBUFN, EFNEW | EFBUF);
1.34      vincent   662:        if (bufp == NULL)
1.37      db        663:                return (ABORT);
1.34      vincent   664:        if (bufp[0] == '\0' && curbp->b_altb != NULL)
1.3       millert   665:                bp = curbp->b_altb;
                    666:        else if ((bp = bfind(bufn, FALSE)) == NULL)
1.37      db        667:                return (FALSE);
1.1       deraadt   668:
1.3       millert   669:        if (bp == curbp) {
1.1       deraadt   670:                ewprintf("Cannot insert buffer into self");
1.37      db        671:                return (FALSE);
1.1       deraadt   672:        }
                    673:        /* insert the buffer */
                    674:        nline = 0;
                    675:        clp = lforw(bp->b_linep);
1.3       millert   676:        for (;;) {
1.1       deraadt   677:                for (clo = 0; clo < llength(clp); clo++)
                    678:                        if (linsert(1, lgetc(clp, clo)) == FALSE)
1.37      db        679:                                return (FALSE);
1.3       millert   680:                if ((clp = lforw(clp)) == bp->b_linep)
                    681:                        break;
                    682:                if (newline(FFRAND, 1) == FALSE)        /* fake newline */
1.37      db        683:                        return (FALSE);
1.1       deraadt   684:                nline++;
                    685:        }
1.3       millert   686:        if (nline == 1)
                    687:                ewprintf("[Inserted 1 line]");
                    688:        else
                    689:                ewprintf("[Inserted %d lines]", nline);
1.1       deraadt   690:
1.37      db        691:        clp = curwp->w_linep;           /* cosmetic adjustment  */
1.3       millert   692:        if (curwp->w_dotp == clp) {     /* for offscreen insert */
                    693:                while (nline-- && lback(clp) != curbp->b_linep)
1.1       deraadt   694:                        clp = lback(clp);
1.37      db        695:                curwp->w_linep = clp;   /* adjust framing.      */
1.1       deraadt   696:                curwp->w_flag |= WFHARD;
                    697:        }
                    698:        return (TRUE);
                    699: }
                    700:
                    701: /*
                    702:  * Turn off the dirty bit on this buffer.
                    703:  */
1.3       millert   704: /* ARGSUSED */
                    705: int
1.26      vincent   706: notmodified(int f, int n)
1.1       deraadt   707: {
1.52      deraadt   708:        struct mgwin *wp;
1.1       deraadt   709:
                    710:        curbp->b_flag &= ~BFCHG;
1.3       millert   711:        wp = wheadp;            /* Update mode lines.    */
1.1       deraadt   712:        while (wp != NULL) {
                    713:                if (wp->w_bufp == curbp)
                    714:                        wp->w_flag |= WFMODE;
                    715:                wp = wp->w_wndp;
                    716:        }
                    717:        ewprintf("Modification-flag cleared");
1.37      db        718:        return (TRUE);
1.1       deraadt   719: }
                    720:
                    721: #ifndef NO_HELP
                    722: /*
                    723:  * Popbuf and set all windows to top of buffer.         Currently only used by
                    724:  * help functions.
                    725:  */
1.3       millert   726: int
1.52      deraadt   727: popbuftop(struct buffer *bp)
1.1       deraadt   728: {
1.52      deraadt   729:        struct mgwin *wp;
1.1       deraadt   730:
1.3       millert   731:        bp->b_dotp = lforw(bp->b_linep);
                    732:        bp->b_doto = 0;
                    733:        if (bp->b_nwnd != 0) {
                    734:                for (wp = wheadp; wp != NULL; wp = wp->w_wndp)
                    735:                        if (wp->w_bufp == bp) {
                    736:                                wp->w_dotp = bp->b_dotp;
                    737:                                wp->w_doto = 0;
                    738:                                wp->w_flag |= WFHARD;
                    739:                        }
                    740:        }
1.37      db        741:        return (popbuf(bp) != NULL);
1.1       deraadt   742: }
                    743: #endif