forgotten commit. disabled until egl is adapted.
[AROS-Contrib.git] / fish / microemacs / buffer.c
blob5520d79a52e84a13f3567fe094e8df0fd16fd926
1 /*
2 * Buffer management.
3 * Some of the functions are internal,
4 * and some are actually attached to user
5 * keys. Like everyone else, they set hints
6 * for the display system.
7 */
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdlib.h>
11 #include "ed.h"
14 * Attach a buffer to a window. The
15 * values of dot and mark come from the buffer
16 * if the use count is 0. Otherwise, they come
17 * from some other window.
19 int usebuffer(f, n)
20 int f;
21 int n;
23 register BUFFER *bp;
24 register WINDOW *wp;
25 register int s;
26 char bufn[NBUFN];
28 if ((s=mlreply("Use buffer: ", bufn, NBUFN)) != TRUE)
29 return (s);
30 if ((bp=bfind(bufn, TRUE, 0)) == NULL)
31 return (FALSE);
32 if (--curbp->b_nwnd == 0) { /* Last use. */
33 curbp->b_dotp = curwp->w_dotp;
34 curbp->b_doto = curwp->w_doto;
35 curbp->b_markp = curwp->w_markp;
36 curbp->b_marko = curwp->w_marko;
38 curbp = bp; /* Switch. */
39 curwp->w_bufp = bp;
40 curwp->w_linep = bp->b_linep; /* For macros, ignored. */
41 curwp->w_flag |= WFMODE|WFFORCE|WFHARD; /* Quite nasty. */
42 if (bp->b_nwnd++ == 0) { /* First use. */
43 curwp->w_dotp = bp->b_dotp;
44 curwp->w_doto = bp->b_doto;
45 curwp->w_markp = bp->b_markp;
46 curwp->w_marko = bp->b_marko;
47 return (TRUE);
49 wp = wheadp; /* Look for old. */
50 while (wp != NULL) {
51 if (wp!=curwp && wp->w_bufp==bp) {
52 curwp->w_dotp = wp->w_dotp;
53 curwp->w_doto = wp->w_doto;
54 curwp->w_markp = wp->w_markp;
55 curwp->w_marko = wp->w_marko;
56 break;
58 wp = wp->w_wndp;
60 return (TRUE);
64 * Dispose of a buffer, by name.
65 * Ask for the name. Look it up (don't get too
66 * upset if it isn't there at all!). Get quite upset
67 * if the buffer is being displayed. Clear the buffer (ask
68 * if the buffer has been changed). Then free the header
69 * line and the buffer header. Bound to "C-X K".
71 int killbuffer(f, n)
72 int f;
73 int n;
75 register BUFFER *bp;
76 register BUFFER *bp1;
77 register BUFFER *bp2;
78 register int s;
79 char bufn[NBUFN];
81 if ((s=mlreply("Kill buffer: ", bufn, NBUFN)) != TRUE)
82 return (s);
83 if ((bp=bfind(bufn, FALSE, 0)) == NULL) /* Easy if unknown. */
84 return (TRUE);
85 if (bp->b_nwnd != 0) { /* Error if on screen. */
86 mlwrite("Buffer is being displayed");
87 return (FALSE);
89 if ((s=bclear(bp)) != TRUE) /* Blow text away. */
90 return (s);
91 free((char *) bp->b_linep); /* Release header line. */
92 bp1 = NULL; /* Find the header. */
93 bp2 = bheadp;
94 while (bp2 != bp) {
95 bp1 = bp2;
96 bp2 = bp2->b_bufp;
98 bp2 = bp2->b_bufp; /* Next one in chain. */
99 if (bp1 == NULL) /* Unlink it. */
100 bheadp = bp2;
101 else
102 bp1->b_bufp = bp2;
103 free((char *) bp); /* Release buffer block */
104 return (TRUE);
108 * List all of the active
109 * buffers. First update the special
110 * buffer that holds the list. Next make
111 * sure at least 1 window is displaying the
112 * buffer list, splitting the screen if this
113 * is what it takes. Lastly, repaint all of
114 * the windows that are displaying the
115 * list. Bound to "C-X C-B".
117 int listbuffers(f, n)
118 int f;
119 int n;
121 register WINDOW *wp;
122 register BUFFER *bp;
123 register int s;
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;
137 wp->w_bufp = blistp;
138 ++blistp->b_nwnd;
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;
150 wp = wp->w_wndp;
152 return (TRUE);
156 * This routine rebuilds the
157 * text in the special secret buffer
158 * that holds the buffer list. It is called
159 * by the list buffers command. Return TRUE
160 * if everything works. Return FALSE if there
161 * is an error (if there is no memory).
163 int makelist()
165 register char *cp1;
166 register char *cp2;
167 register int c;
168 register BUFFER *bp;
169 register LINE *lp;
170 register int nbytes;
171 register int s;
172 char b[6+1];
173 char line[128];
175 blistp->b_flag &= ~BFCHG; /* Don't complain! */
176 if ((s=bclear(blistp)) != TRUE) /* Blow old text away */
177 return (s);
178 strcpy(blistp->b_fname, "");
179 if (addline("C Size Buffer File") == FALSE
180 || addline("- ---- ------ ----") == FALSE)
181 return (FALSE);
182 bp = bheadp; /* For all buffers */
183 while (bp != NULL) {
184 if ((bp->b_flag&BFTEMP) != 0) { /* Skip magic ones. */
185 bp = bp->b_bufp;
186 continue;
188 cp1 = &line[0]; /* Start at left edge */
189 if ((bp->b_flag&BFCHG) != 0) /* "*" if changed */
190 *cp1++ = '*';
191 else
192 *cp1++ = ' ';
193 *cp1++ = ' '; /* Gap. */
194 nbytes = 0; /* Count bytes in buf. */
195 lp = lforw(bp->b_linep);
196 while (lp != bp->b_linep) {
197 nbytes += llength(lp)+1;
198 lp = lforw(lp);
200 itoa(b, 6, nbytes); /* 6 digit buffer size. */
201 cp2 = &b[0];
202 while ((c = *cp2++) != 0)
203 *cp1++ = c;
204 *cp1++ = ' '; /* Gap. */
205 cp2 = &bp->b_bname[0]; /* Buffer name */
206 while ((c = *cp2++) != 0)
207 *cp1++ = c;
208 cp2 = &bp->b_fname[0]; /* File name */
209 if (*cp2 != 0) {
210 while (cp1 < &line[1+1+6+1+NBUFN+1])
211 *cp1++ = ' ';
212 while ((c = *cp2++) != 0) {
213 if (cp1 < &line[128-1])
214 *cp1++ = c;
217 *cp1 = 0; /* Add to the buffer. */
218 if (addline(line) == FALSE)
219 return (FALSE);
220 bp = bp->b_bufp;
222 return (TRUE); /* All done */
225 void itoa(buf, width, num)
226 register char buf[];
227 register int width;
228 register int num;
230 buf[width] = 0; /* End of string. */
231 while (num >= 10) { /* Conditional digits. */
232 buf[--width] = (num%10) + '0';
233 num /= 10;
235 buf[--width] = num + '0'; /* Always 1 digit. */
236 while (width != 0) /* Pad with blanks. */
237 buf[--width] = ' ';
241 * The argument "text" points to
242 * a string. Append this line to the
243 * buffer list buffer. Handcraft the EOL
244 * on the end. Return TRUE if it worked and
245 * FALSE if you ran out of room.
247 int addline(text)
248 const char *text;
250 register LINE *lp;
251 register int i;
252 register int ntext;
254 ntext = strlen(text);
255 if ((lp=lalloc(ntext)) == NULL)
256 return (FALSE);
257 for (i=0; i<ntext; ++i)
258 lputc(lp, i, text[i]);
259 blistp->b_linep->l_bp->l_fp = lp; /* Hook onto the end */
260 lp->l_bp = blistp->b_linep->l_bp;
261 blistp->b_linep->l_bp = lp;
262 lp->l_fp = blistp->b_linep;
263 if (blistp->b_dotp == blistp->b_linep) /* If "." is at the end */
264 blistp->b_dotp = lp; /* move it to new line */
265 return (TRUE);
269 * Look through the list of
270 * buffers. Return TRUE if there
271 * are any changed buffers. Buffers
272 * that hold magic internal stuff are
273 * not considered; who cares if the
274 * list of buffer names is hacked.
275 * Return FALSE if no buffers
276 * have been changed.
278 int anycb()
280 register BUFFER *bp;
282 bp = bheadp;
283 while (bp != NULL) {
284 if ((bp->b_flag&BFTEMP)==0 && (bp->b_flag&BFCHG)!=0)
285 return (TRUE);
286 bp = bp->b_bufp;
288 return (FALSE);
292 * Find a buffer, by name. Return a pointer
293 * to the BUFFER structure associated with it. If
294 * the named buffer is found, but is a TEMP buffer (like
295 * the buffer list) conplain. If the buffer is not found
296 * and the "cflag" is TRUE, create it. The "bflag" is
297 * the settings for the flags in in buffer.
299 BUFFER *
300 bfind(bname, cflag, bflag)
301 register char *bname;
302 int cflag;
303 int bflag;
305 register BUFFER *bp;
306 register LINE *lp;
308 bp = bheadp;
309 while (bp != NULL) {
310 if (strcmp(bname, bp->b_bname) == 0) {
311 if ((bp->b_flag&BFTEMP) != 0) {
312 mlwrite("Cannot select builtin buffer");
313 return (NULL);
315 return (bp);
317 bp = bp->b_bufp;
319 if (cflag != FALSE) {
320 if ((bp=(BUFFER *)malloc(sizeof(BUFFER))) == NULL)
321 return (NULL);
322 if ((lp=lalloc(0)) == NULL) {
323 free((char *) bp);
324 return (NULL);
326 bp->b_bufp = bheadp;
327 bheadp = bp;
328 bp->b_dotp = lp;
329 bp->b_doto = 0;
330 bp->b_markp = NULL;
331 bp->b_marko = 0;
332 bp->b_flag = bflag;
333 bp->b_nwnd = 0;
334 bp->b_linep = lp;
335 strcpy(bp->b_fname, "");
336 strcpy(bp->b_bname, bname);
337 lp->l_fp = lp;
338 lp->l_bp = lp;
340 return (bp);
344 * This routine blows away all of the text
345 * in a buffer. If the buffer is marked as changed
346 * then we ask if it is ok to blow it away; this is
347 * to save the user the grief of losing text. The
348 * window chain is nearly always wrong if this gets
349 * called; the caller must arrange for the updates
350 * that are required. Return TRUE if everything
351 * looks good.
353 int bclear(bp)
354 register BUFFER *bp;
356 register LINE *lp;
357 register int s;
359 if ((bp->b_flag&BFTEMP) == 0 /* Not scratch buffer. */
360 && (bp->b_flag&BFCHG) != 0 /* Something changed */
361 && (s=mlyesno("Discard changes")) != TRUE)
362 return (s);
363 bp->b_flag &= ~BFCHG; /* Not changed */
364 while ((lp=lforw(bp->b_linep)) != bp->b_linep)
365 lfree(lp);
366 bp->b_dotp = bp->b_linep; /* Fix "." */
367 bp->b_doto = 0;
368 bp->b_markp = NULL; /* Invalidate "mark" */
369 bp->b_marko = 0;
370 return (TRUE);