|
|
1.1 root 1: /*
2: * Buffer management.
3: * Some of the functions are internal and some are actually attached to user
4: * keys. Like everyone else, they set hints for the display system.
5: */
6: #include <stdio.h>
7: #include "ed.h"
8:
9: /*
10: * Attach a buffer to a window. The values of dot and mark come from the buffer
11: * if the use count is 0. Otherwise, they come from some other window.
12: */
13: usebuffer(f, n)
14: {
15: register BUFFER *bp;
16: register WINDOW *wp;
17: register int s;
18: uchar bufn[NBUFN];
19:
20: if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
21: return (s);
22: #if GEM
23: fixname(bufn);
24: #endif
25: if ((bp=bfind(bufn, TRUE, 0)) == NULL)
26: return (FALSE);
27: if (--curbp->b_nwnd == 0) { /* Last use. */
28: curbp->b_dotp = curwp->w_dotp;
29: curbp->b_doto = curwp->w_doto;
30: curbp->b_markp = curwp->w_markp;
31: curbp->b_marko = curwp->w_marko;
32: }
33: curbp = bp; /* Switch. */
34: curwp->w_bufp = bp;
35: curwp->w_linep = bp->b_linep; /* For macros, ignored. */
36: curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */
37: if (bp->b_nwnd++ == 0) { /* First use. */
38: curwp->w_dotp = bp->b_dotp;
39: curwp->w_doto = bp->b_doto;
40: curwp->w_markp = bp->b_markp;
41: curwp->w_marko = bp->b_marko;
42: return (TRUE);
43: }
44: wp = wheadp; /* Look for old. */
45: while (wp != NULL) {
46: if (wp!=curwp && wp->w_bufp==bp) {
47: curwp->w_dotp = wp->w_dotp;
48: curwp->w_doto = wp->w_doto;
49: curwp->w_markp = wp->w_markp;
50: curwp->w_marko = wp->w_marko;
51: break;
52: }
53: wp = wp->w_wndp;
54: }
55: return (TRUE);
56: }
57:
58: /*
59: * Dispose of a buffer, by name.
60: * Ask for the name. Look it up (don't get too upset if it isn't there at
61: * all!). Get quite upset if the buffer is the current buffer. If it is
62: * displayed, make sure the user wants it gone, and if (s)he does, delete
63: * the windows associated with it as well.
64: * Clear the buffer (ask if the buffer has been changed). Then free the header
65: * line and the buffer header. Bound to "C-X K".
66: */
67: killbuffer(f, n)
68: {
69: register BUFFER *bp;
70: register BUFFER *bp1;
71: register BUFFER *bp2;
72: register int s;
73: uchar bufn[NBUFN];
74:
75: if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
76: return (s);
77: #if GEM
78: fixname(bufn);
79: #endif
80: if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown. */
81: return (TRUE);
82: if (bp->b_nwnd != 0) { /* If on screen. */
83: if (curbp == bp) {
84: mlwrite("Buffer is current buffer");
85: return (FALSE);
86: } else {
87: if ((s = mlyesno("Buffer is displayed: Really kill"))
88: != TRUE)
89: return (FALSE);
90: }
91: }
92: if ((s=bclear(bp)) != TRUE) /* Blow text away. */
93: return (s);
94: while (bp->b_nwnd != 0) /* Blow windows away. */
95: zapbwind(bp);
96: free((char *) bp->b_linep); /* Release header line. */
97: bp1 = NULL; /* Find the header. */
98: bp2 = bheadp;
99: while (bp2 != bp) {
100: bp1 = bp2;
101: bp2 = bp2->b_bufp;
102: }
103: bp2 = bp2->b_bufp; /* Next one in chain. */
104: if (bp1 == NULL) /* Unlink it. */
105: bheadp = bp2;
106: else
107: bp1->b_bufp = bp2;
108: free((char *) bp); /* Release buffer block */
109: return (TRUE);
110: }
111:
112: /*
113: * List all of the active buffers. First update the special buffer that
114: * holds the list. Next make sure at least 1 window is displaying the
115: * buffer list, splitting the screen if this is what it takes.
116: * Lastly, repaint all of the windows that are displaying the list.
117: * Bound to "C-X C-B".
118: */
119: listbuffers(f, n)
120: {
121: register WINDOW *wp;
122: register BUFFER *bp;
123: register int s;
124:
125: if ((s=makelist()) != TRUE)
126: return (s);
127: if (blistp->b_nwnd == 0) { /* Not on screen yet. */
128: if ((wp=wpopup()) == NULL)
129: return (FALSE);
130: bp = wp->w_bufp;
131: if (--bp->b_nwnd == 0) {
132: bp->b_dotp = wp->w_dotp;
133: bp->b_doto = wp->w_doto;
134: bp->b_markp = wp->w_markp;
135: bp->b_marko = wp->w_marko;
136: }
137: wp->w_bufp = blistp;
138: ++blistp->b_nwnd;
139: }
140: wp = wheadp;
141: while (wp != NULL) {
142: if (wp->w_bufp == blistp) {
143: wp->w_linep = lforw(blistp->b_linep);
144: wp->w_dotp = lforw(blistp->b_linep);
145: wp->w_doto = 0;
146: wp->w_markp = NULL;
147: wp->w_marko = 0;
148: wp->w_flag |= WFMODE|WFHARD;
149: }
150: wp = wp->w_wndp;
151: }
152: return (TRUE);
153: }
154:
155: /*
156: * This routine rebuilds the text in the special secret buffer that holds
157: * the buffer list. It is called by the list buffers command. Return TRUE
158: * if everything works. Return FALSE if there is an error
159: * (if there is no memory).
160: */
161: makelist()
162: {
163: register uchar *cp1;
164: register uchar *cp2;
165: register BUFFER *bp;
166: register LINE *lp;
167: register long nlines;
168: register long nbytes;
169: register int c;
170: uchar b[6+1];
171: uchar line[128];
172:
173: blistp->b_flag &= ~BFCHG; /* Don't complain! */
174: if ((c=bclear(blistp)) != TRUE) /* Blow old text away */
175: return (c);
176: strcpy(blistp->b_fname, "");
177: if (addline(blistp, "C Size Lines Buffer File") == FALSE
178: || addline(blistp,"- ---- ----- ------ ----") == FALSE)
179: return (FALSE);
180: bp = bheadp; /* For all buffers */
181: while (bp != NULL) {
182: if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones. */
183: bp = bp->b_bufp;
184: continue;
185: }
186: cp1 = &line[0]; /* Start at left edge */
187: if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */
188: *cp1++ = '*';
189: else
190: *cp1++ = ' ';
191: *cp1++ = ' '; /* Gap. */
192: nbytes = 0; /* Count bytes in buf. */
193: nlines = 0; /* Count lines in buf. */
194: lp = lforw(bp->b_linep);
195: while (lp != bp->b_linep) {
196: nlines++;
197: nbytes += llength(lp)+1;
198: lp = lforw(lp);
199: }
200: ltoa(b, 6, nbytes); /* 6 digit buffer size. */
201: cp2 = &b[0];
202: while ((c = *cp2++) != 0)
203: *cp1++ = c;
204: *cp1++ = ' '; /* Gap. */
205: ltoa(b, 6, nlines); /* 6 digit # of lines */
206: cp2 = &b[0];
207: while ((c = *cp2++) != 0)
208: *cp1++ = c;
209: *cp1++ = ' '; /* Gap. */
210: cp2 = &bp->b_bname[0]; /* Buffer name */
211: while ((c = *cp2++) != 0)
212: *cp1++ = c;
213: cp2 = &bp->b_fname[0]; /* File name */
214: if (*cp2 != 0) {
215: while (cp1 < &line[1+1+6+1+6+1+NBUFN+1])
216: *cp1++ = ' ';
217: while ((c = *cp2++) != 0) {
218: if (cp1 < &line[128-1])
219: *cp1++ = c;
220: }
221: }
222: *cp1 = 0; /* Add to the buffer. */
223: if (addline(blistp,line) == FALSE)
224: return (FALSE);
225: bp = bp->b_bufp;
226: }
227: return (TRUE); /* All done */
228: }
229:
230: ltoa(buf, width, num)
231: register uchar buf[];
232: register int width;
233: register long num;
234: {
235: buf[width] = 0; /* End of string. */
236: while (num >= 10) { /* Conditional digits. */
237: buf[--width] = (num%10) + '0';
238: num /= 10;
239: }
240: buf[--width] = num + '0'; /* Always 1 digit. */
241: while (width != 0) /* Pad with blanks. */
242: buf[--width] = ' ';
243: }
244:
245: /*
246: * The argument "text" points to a string. Append this line to the buffer
247: * specified. Handcraft the EOL on the end. Return TRUE if it worked and
248: * FALSE if you ran out of room.
249: */
250: addline(bp, text)
251: register BUFFER *bp;
252: uchar *text;
253: {
254: register LINE *lp;
255: register int i;
256: register int ntext;
257:
258: ntext = strlen(text);
259: if ((lp=lalloc(ntext)) == NULL)
260: return (FALSE);
261: for (i=0; i<ntext; ++i)
262: lputc(lp, i, text[i]);
263: lforw(lback(bp->b_linep)) = lp; /* Hook onto the end */
264: lp->l_bp = bp->b_linep->l_bp;
265: bp->b_linep->l_bp = lp;
266: lforw(lp) = bp->b_linep;
267: if (bp->b_dotp == bp->b_linep) /* If "." is at the end */
268: bp->b_dotp = lp; /* move it to new line */
269: return (TRUE);
270: }
271:
272: /*
273: * Look through the list of buffers. Return TRUE if there are any changed
274: * buffers. Buffers that hold magic internal stuff are not considered;
275: * who cares if the list of buffer names is hacked.
276: * Return FALSE if no buffers have been changed.
277: */
278: anycb()
279: {
280: register BUFFER *bp;
281:
282: bp = bheadp;
283: while (bp != NULL) {
284: if ((bp->b_flag&(BFTEMP|BFNOWRT|BFERROR))==0
285: && (bp->b_flag&BFCHG)!=0)
286: return (TRUE);
287: bp = bp->b_bufp;
288: }
289: return (FALSE);
290: }
291:
292: /*
293: * Find a buffer, by name. Return a pointer to the BUFFER structure
294: * associated with it. If the named buffer is found, but is a TEMP buffer
295: * (like the buffer list) conplain. If the buffer is not found and the "cflag"
296: * is TRUE, create it. The "bflag" is the settings for the flags in in buffer.
297: */
298: BUFFER *bfind(bname, cflag, bflag)
299: register uchar *bname;
300: {
301: register BUFFER *bp;
302: register LINE *lp;
303:
304: bp = bheadp;
305: while (bp != NULL) {
306: if (strcmp(bname, bp->b_bname) == 0) {
307: if ((bp->b_flag&BFTEMP) != 0) {
308: mlwrite("Cannot select builtin buffer");
309: return (NULL);
310: }
311: return (bp);
312: }
313: bp = bp->b_bufp;
314: }
315: if (cflag != FALSE) {
316: if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
317: return (NULL);
318: if ((lp=lalloc(0)) == NULL) {
319: free((char *) bp);
320: return (NULL);
321: }
322: bp->b_bufp = bheadp;
323: bheadp = bp;
324: bp->b_dotp = lp;
325: bp->b_doto = 0;
326: bp->b_markp = NULL;
327: bp->b_marko = 0;
328: bp->b_flag = bflag;
329: bp->b_nwnd = 0;
330: bp->b_linep = lp;
331: strcpy(bp->b_fname, "");
332: strcpy(bp->b_bname, bname);
333: lforw(lp) = lp;
334: lp->l_bp = lp;
335: }
336: return (bp);
337: }
338:
339: /*
340: * This routine blows away all of the text in a buffer. If the buffer is
341: * marked as changed then we ask if it is ok to blow it away; this is
342: * to save the user the grief of losing text. The window chain is nearly
343: * always wrong if this gets called; the caller must arrange for the updates
344: * that are required. Return TRUE if everything looks good.
345: */
346: bclear(bp)
347: register BUFFER *bp;
348: {
349: register LINE *lp;
350: register int s;
351:
352: if ((bp->b_flag&BFTEMP) == 0 /* Not scratch buffer. */
353: && (bp->b_flag&BFCHG) != 0 /* Something changed */
354: && (s=mlyesno("Discard changes")) != TRUE)
355: return (s);
356: bp->b_flag &= ~BFCHG; /* Not changed */
357: while ((lp=lforw(bp->b_linep)) != bp->b_linep)
358: lfree(lp);
359: bp->b_dotp = bp->b_linep; /* Fix "." */
360: bp->b_doto = 0;
361: bp->b_markp = NULL; /* Invalidate "mark" */
362: bp->b_marko = 0;
363: return (TRUE);
364: }
365:
366: #if LIBHELP
367: /*
368: * Put up a help window with the text pointed to by txt.
369: */
370: helpwindow(tag)
371: uchar *tag;
372: {
373: register WINDOW *wp;
374: register BUFFER *bp;
375: register int s;
376:
377: if ((s=makehelp(tag)) != TRUE) {
378: while (helpbp->b_nwnd != 0) /* If on screen */
379: zaphelp(0, 0); /* Delete windows */
380: return (s);
381: }
382: if (helpbp->b_nwnd == 0) { /* Not on screen yet. */
383: if ((wp=wpopup(helpbp)) == NULL)
384: return (FALSE);
385: bp = wp->w_bufp;
386: if (--bp->b_nwnd == 0) {
387: bp->b_dotp = wp->w_dotp;
388: bp->b_doto = wp->w_doto;
389: bp->b_markp = wp->w_markp;
390: bp->b_marko = wp->w_marko;
391: }
392: wp->w_bufp = helpbp;
393: ++helpbp->b_nwnd;
394: }
395: wp = wheadp;
396: while (wp != NULL) {
397: if (wp->w_bufp == helpbp) {
398: wp->w_linep = lforw(helpbp->b_linep);
399: wp->w_dotp = lforw(helpbp->b_linep);
400: wp->w_doto = 0;
401: wp->w_markp = NULL;
402: wp->w_marko = 0;
403: wp->w_flag |= WFMODE|WFHARD;
404: }
405: wp = wp->w_wndp;
406: }
407: return (TRUE);
408: }
409:
410: /*
411: * Service routine for help...
412: */
413: addhelp(str)
414: uchar *str;
415: {
416: addline(helpbp, str);
417: }
418:
419: /*
420: * This routine rebuilds the text in the special secret buffer that holds
421: * the help. It is called by the help command. Return TRUE if
422: * everything works. Return FALSE if there is an error (if there is no memory
423: * or no help for the topic or file not found.)
424: */
425: makehelp(tag)
426: uchar *tag;
427: {
428: extern uchar *helpfile;
429: register int c;
430:
431: helpbp->b_flag &= ~BFCHG; /* Don't complain! */
432: if ((c=bclear(helpbp)) != TRUE) /* Blow old text away */
433: return (c);
434: strcpy(helpbp->b_fname, tag);
435:
436: if ((c = help(tag, addhelp)) < 0)
437: mlwrite("[Can't open help file %s]", helpfile);
438: else if (c > 0)
439: mlwrite("[No help available for topic \"%s\"]", tag);
440:
441: return (c == 0); /* All done */
442: }
443:
444: /*
445: * Put up a help window with an index of matching topics
446: */
447: topicwindow(tag)
448: uchar *tag;
449: {
450: register WINDOW *wp;
451: register BUFFER *bp;
452: register int s;
453:
454: if ((s=makeindex(tag)) != TRUE) {
455: while (helpbp->b_nwnd != 0) /* If on screen */
456: zaphelp(0, 0); /* Delete windows */
457: return (s);
458: }
459: if (helpbp->b_nwnd == 0) { /* Not on screen yet. */
460: if ((wp=wpopup(helpbp)) == NULL)
461: return (FALSE);
462: bp = wp->w_bufp;
463: if (--bp->b_nwnd == 0) {
464: bp->b_dotp = wp->w_dotp;
465: bp->b_doto = wp->w_doto;
466: bp->b_markp = wp->w_markp;
467: bp->b_marko = wp->w_marko;
468: }
469: wp->w_bufp = helpbp;
470: ++helpbp->b_nwnd;
471: }
472: wp = wheadp;
473: while (wp != NULL) {
474: if (wp->w_bufp == helpbp) {
475: wp->w_linep = lforw(helpbp->b_linep);
476: wp->w_dotp = lforw(helpbp->b_linep);
477: wp->w_doto = 0;
478: wp->w_markp = NULL;
479: wp->w_marko = 0;
480: wp->w_flag |= WFMODE|WFHARD;
481: }
482: wp = wp->w_wndp;
483: }
484: return (TRUE);
485: }
486:
487: /*
488: * This routine rebuilds the text in the special secret buffer that holds
489: * the help. It is called by the help command. Return TRUE if
490: * everything works. Return FALSE if there is an error (if there is no memory
491: * or no help for the topic or file not found.)
492: */
493: makeindex(tag)
494: uchar *tag;
495: {
496: extern uchar *helpfile;
497: register int c;
498:
499: helpbp->b_flag &= ~BFCHG; /* Don't complain! */
500: if ((c=bclear(helpbp)) != TRUE) /* Blow old text away */
501: return (c);
502: strcpy(helpbp->b_fname, "index for ");
503: strcat(helpbp->b_fname, tag);
504:
505: if ((c = indexhelp(tag, addhelp)) < 0)
506: mlwrite("[Can't open help file %s]", helpfile);
507: else if (c > 0)
508: mlwrite("[No entries matching \"%s\"]", tag);
509:
510: return (c == 0); /* All done */
511: }
512: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.