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