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