|
|
1.1 root 1: /*************************************************************************
2: * This program is copyright (C) 1985, 1986 by Jonathan Payne. It is *
3: * provided to you without charge for use only on a licensed Unix *
4: * system. You may copy JOVE provided that this notice is included with *
5: * the copy. You may not sell copies of this program or versions *
6: * modified for use on microcomputer systems, unless the copies are *
7: * included with a Unix system distribution and the source is provided. *
8: *************************************************************************/
9:
10: /* Contains commands that deal with creating, selecting, killing and
11: listing buffers, and buffer modes, and find-file, etc. */
12:
13: #include "jove.h"
14:
15: #include <sys/stat.h>
16:
17: char *Mainbuf = "Main",
18: *NoName = "Sans un nom!";
19:
20: Buffer *world = 0, /* First in the list */
21: *curbuf = 0,
22: *lastbuf = 0; /* Last buffer we were in so we have a default
23: buffer during a select buffer. */
24:
25: /* Toggle BIT in the current buffer's minor mode flags. If argument is
26: supplied, a positive one always turns on the mode and zero argument
27: always turns it off. */
28:
29: TogMinor(bit)
30: {
31: if (exp_p) {
32: if (exp == 0)
33: curbuf->b_minor &= ~bit;
34: else
35: curbuf->b_minor |= bit;
36: } else
37: curbuf->b_minor ^= bit;
38: UpdModLine++;
39: }
40:
41: /* Creates a new buffer, links it at the end of the buffer chain, and
42: returns it. */
43:
44: static Buffer *
45: buf_alloc()
46: {
47: register Buffer *b,
48: *lastbp;
49:
50: lastbp = 0;
51: for (b = world; b != 0; lastbp = b, b = b->b_next)
52: ;
53:
54: b = (Buffer *) emalloc(sizeof (Buffer));
55: if (lastbp)
56: lastbp->b_next = b;
57: else
58: world = b;
59: b->b_first = 0;
60: b->b_next = 0;
61:
62: return b;
63: }
64:
65: /* Makes a buffer and initializes it. Obsolete. Used to take two
66: arguments, a buffer name and a file name. */
67:
68: static Buffer *
69: mak_buf()
70: {
71: register Buffer *newb;
72: register int i;
73:
74: newb = buf_alloc();
75: newb->b_fname = 0;
76: newb->b_name = NoName;
77: set_ino(newb);
78: newb->b_marks = 0;
79: newb->b_themark = 0; /* Index into markring */
80: /* No marks yet */
81: for (i = 0; i < NMARKS; i++)
82: newb->b_markring[i] = 0;
83: newb->b_modified = 0;
84: newb->b_type = B_FILE; /* File until proven SCRATCH */
85: newb->b_ntbf = 0;
86: newb->b_minor = 0;
87: newb->b_major = TEXT;
88: newb->b_first = 0;
89: initlist(newb);
90: return newb;
91: }
92:
93: ReNamBuf()
94: {
95: register char *new = 0,
96: *prompt = ProcFmt,
97: *second = "%s already exists; new name? ";
98:
99: for (;;) {
100: new = ask((char *) 0, prompt, new);
101: if (!buf_exists(new))
102: break;
103: prompt = second;
104: }
105: setbname(curbuf, new);
106: }
107:
108: FindFile()
109: {
110: register char *name;
111: char fnamebuf[FILESIZE];
112:
113: name = ask_file(curbuf->b_fname, fnamebuf);
114: SetABuf(curbuf);
115: SetBuf(do_find(curwind, name, 0));
116: }
117:
118: static
119: mkbuflist(bnamp)
120: register char **bnamp;
121: {
122: register Buffer *b;
123:
124: for (b = world; b != 0; b = b->b_next)
125: if (b->b_name != 0)
126: *bnamp++ = b->b_name;
127: *bnamp = 0;
128: }
129:
130: char *
131: ask_buf(def)
132: Buffer *def;
133: {
134: char *bnames[100];
135: register char *bname;
136: register int offset;
137: char prompt[100];
138:
139: if (def != 0 && def->b_name != 0)
140: sprintf(prompt, ": %f (default %s) ", def->b_name);
141: else
142: sprintf(prompt, ProcFmt);
143: mkbuflist(bnames);
144: offset = complete(bnames, prompt, RET_STATE);
145: if (offset == EOF)
146: complain((char *) 0);
147: if (offset == ORIGINAL)
148: bname = Minibuf;
149: else if (offset == NULLSTRING) {
150: if (def)
151: bname = def->b_name;
152: else
153: complain((char *) 0);
154: } else if (offset < 0)
155: complain((char *) 0);
156: else
157: bname = bnames[offset];
158:
159: return bname;
160: }
161:
162: BufSelect()
163: {
164: register char *bname;
165:
166: bname = ask_buf(lastbuf);
167: SetABuf(curbuf);
168: SetBuf(do_select(curwind, bname));
169: }
170:
171: static
172: defb_wind(b)
173: register Buffer *b;
174: {
175: register Window *w = fwind;
176: char *alt;
177:
178: if (lastbuf == b || lastbuf == 0) {
179: lastbuf = 0;
180: alt = (b->b_next != 0) ? b->b_next->b_name : Mainbuf;
181: } else
182: alt = lastbuf->b_name;
183:
184: do {
185: if (w->w_bufp == b) {
186: if (one_windp())
187: (void) do_select(w, alt);
188: else {
189: register Window *save = w->w_next;
190:
191: del_wind(w);
192: w = save->w_prev;
193: }
194: }
195: w = w->w_next;
196: } while (w != fwind);
197: }
198:
199: Buffer *
200: getNMbuf()
201: {
202: register Buffer *delbuf;
203: register char *bname;
204:
205: bname = ask_buf(curbuf);
206: if ((delbuf = buf_exists(bname)) == 0)
207: complain("[No such buffer]");
208: if (delbuf->b_modified)
209: confirm("%s modified, are you sure? ", bname);
210: return delbuf;
211: }
212:
213: BufErase()
214: {
215: register Buffer *delbuf;
216:
217: if (delbuf = getNMbuf()) {
218: initlist(delbuf);
219: delbuf->b_modified = 0;
220: }
221: }
222:
223: static
224: kill_buf(delbuf)
225: register Buffer *delbuf;
226: {
227: register Buffer *b,
228: *lastb = 0;
229: extern Buffer *perr_buf;
230:
231: #ifdef IPROCS
232: pbuftiedp(delbuf); /* Make sure buffer is not tied to a process */
233: #endif
234: for (b = world; b != 0; lastb = b, b = b->b_next)
235: if (b == delbuf)
236: break;
237: if (lastb)
238: lastb->b_next = delbuf->b_next;
239: else
240: world = delbuf->b_next;
241:
242: #define okay_free(ptr) if (ptr) free(ptr)
243:
244: lfreelist(delbuf->b_first);
245: okay_free(delbuf->b_name);
246: okay_free(delbuf->b_fname);
247: free((char *) delbuf);
248:
249: if (delbuf == lastbuf)
250: SetABuf(curbuf);
251: if (perr_buf == delbuf) {
252: ErrFree();
253: perr_buf = 0;
254: }
255: defb_wind(delbuf);
256: if (curbuf == delbuf)
257: SetBuf(curwind->w_bufp);
258: }
259:
260: /* offer to kill some buffers */
261:
262: KillSome()
263: {
264: register Buffer *b,
265: *next;
266: Buffer *oldb;
267: register char *y_or_n;
268:
269: for (b = world; b != 0; b = next) {
270: next = b->b_next;
271: y_or_n = ask("No", "Kill %s? ", b->b_name);
272: if (Upper(*y_or_n) != 'Y')
273: continue;
274: if (IsModified(b)) {
275: y_or_n = ask("No", "%s modified; should I save it? ", b->b_name);
276: if (Upper(*y_or_n) == 'Y') {
277: oldb = curbuf;
278: SetBuf(b);
279: SaveFile();
280: SetBuf(oldb);
281: }
282: }
283: kill_buf(b);
284: }
285: }
286:
287: BufKill()
288: {
289: Buffer *b;
290:
291: if ((b = getNMbuf()) == 0)
292: return;
293: kill_buf(b);
294: }
295:
296: static char *
297: line_cnt(b, buf)
298: register Buffer *b;
299: char *buf;
300: {
301: register int nlines = 0;
302: register Line *lp;
303:
304: for (lp = b->b_first; lp != 0; lp = lp->l_next, nlines++)
305: ;
306: sprintf(buf, "%d", nlines);
307: return buf;
308: }
309:
310: static char *TypeNames[] = {
311: 0,
312: "Scratch",
313: "File",
314: "Process",
315: "I-process"
316: };
317:
318: BufList()
319: {
320: register char *format = "%-2s %-5s %-11s %-1s %-*s %-s";
321: register Buffer *b;
322: int bcount = 1, /* To give each buffer a number */
323: buf_width = 11;
324: char nbuf[10];
325: extern int ModCount;
326:
327: for (b = world; b != 0; b = b->b_next)
328: buf_width = max(buf_width, strlen(b->b_name));
329:
330: TOstart("Buffer list", TRUE); /* true means auto-newline */
331:
332: Typeout("(* means buffer needs saving)");
333: Typeout("(+ means file hasn't been read yet)");
334: Typeout(NullStr);
335: Typeout(format, "NO", "Lines", "Type", NullStr, buf_width, "Name", "File");
336: Typeout(format, "--", "-----", "----", NullStr, buf_width, "----", "----");
337: for (b = world; b != 0; b = b->b_next) {
338: Typeout(format, itoa(bcount++),
339: line_cnt(b, nbuf),
340: TypeNames[b->b_type],
341: IsModified(b) ? "*" :
342: b->b_ntbf ? "+" : NullStr,
343: buf_width,
344: /* For the * (variable length field) */
345: b->b_name,
346: filename(b));
347:
348: if (TOabort)
349: break;
350: }
351: TOstop();
352: }
353:
354: bufname(b)
355: register Buffer *b;
356: {
357: char tmp[100],
358: *cp;
359: int try = 1;
360:
361: if (b->b_fname == 0)
362: complain("[No file name]");
363: cp = basename(b->b_fname);
364: strcpy(tmp, cp);
365: while (buf_exists(tmp)) {
366: sprintf(tmp, "%s.%d", cp, try);
367: try++;
368: }
369: setbname(b, tmp);
370: }
371:
372: initlist(b)
373: register Buffer *b;
374: {
375: lfreelist(b->b_first);
376: b->b_first = b->b_dot = b->b_last = 0;
377: (void) listput(b, b->b_first);
378:
379: SavLine(b->b_dot, NullStr);
380: b->b_char = 0;
381: AllMarkSet(b, b->b_dot, 0);
382: if (b == curbuf)
383: getDOT();
384: }
385:
386: /* Returns pointer to buffer with name NAME, or if NAME is a string of digits
387: returns the buffer whose number equals those digits. Otherwise, returns
388: 0. */
389:
390: Buffer *
391: buf_exists(name)
392: register char *name;
393: {
394: register Buffer *bp;
395: register int n;
396:
397: if (name == 0)
398: return 0;
399:
400: for (bp = world; bp != 0; bp = bp->b_next)
401: if (strcmp(bp->b_name, name) == 0)
402: return bp;
403:
404: /* Doesn't match any names. Try for a buffer number... */
405:
406: if ((n = chr_to_int(name, 10, 1)) > 0) {
407: for (bp = world; n > 1; bp = bp->b_next) {
408: if (bp == 0)
409: break;
410: --n;
411: }
412: return bp;
413: }
414:
415: return 0;
416: }
417:
418: /* Returns buffer pointer with a file name NAME, if one exists. Stat's the
419: file and compares inodes, in case NAME is a link, as well as the actual
420: characters that make up the file name. */
421:
422: Buffer *
423: file_exists(name)
424: register char *name;
425: {
426: struct stat stbuf;
427: register struct stat *s = &stbuf;
428: register Buffer *b = 0;
429: char fnamebuf[FILESIZE];
430:
431: if (name) {
432: PathParse(name, fnamebuf);
433: if (stat(fnamebuf, s) == -1)
434: s->st_ino = 0;
435: for (b = world; b != 0; b = b->b_next) {
436: if ((b->b_ino != 0 && b->b_ino == s->st_ino) ||
437: (strcmp(b->b_fname, fnamebuf) == 0))
438: break;
439: }
440: }
441: return b;
442: }
443:
444: char *
445: ralloc(obj, size)
446: register char *obj;
447: {
448: register char *new;
449:
450: if (obj)
451: new = realloc(obj, (unsigned) size);
452: if (new == 0 || !obj)
453: new = emalloc(size);
454: return new;
455: }
456:
457: setbname(b, name)
458: register Buffer *b;
459: register char *name;
460: {
461: UpdModLine++; /* Kludge ... but speeds things up considerably */
462: if (name) {
463: if (b->b_name == NoName)
464: b->b_name = 0;
465: b->b_name = ralloc(b->b_name, strlen(name) + 1);
466: strcpy(b->b_name, name);
467: } else
468: b->b_name = 0;
469: }
470:
471: setfname(b, name)
472: register Buffer *b;
473: register char *name;
474: {
475: char wholename[FILESIZE],
476: oldname[FILESIZE],
477: *oldptr = oldname;
478: Buffer *save = curbuf;
479:
480: SetBuf(b);
481: UpdModLine++; /* Kludge ... but speeds things up considerably */
482: if (b->b_fname == 0)
483: oldptr = 0;
484: else
485: strcpy(oldname, b->b_fname);
486: if (name) {
487: PathParse(name, wholename);
488: curbuf->b_fname = ralloc(curbuf->b_fname, strlen(wholename) + 1);
489: strcpy(curbuf->b_fname, wholename);
490: } else
491: b->b_fname = 0;
492: DoAutoExec(curbuf->b_fname, oldptr);
493: curbuf->b_mtime = curbuf->b_ino = 0; /* until they're known. */
494: SetBuf(save);
495: }
496:
497: set_ino(b)
498: register Buffer *b;
499: {
500: struct stat stbuf;
501:
502: if (b->b_fname == 0 || stat(b->b_fname, &stbuf) == -1) {
503: b->b_ino = 0;
504: b->b_mtime = 0;
505: } else {
506: b->b_ino = stbuf.st_ino;
507: b->b_mtime = stbuf.st_mtime;
508: }
509: }
510:
511: /* Find the file `fname' into buf and put in in window `w' */
512:
513: Buffer *
514: do_find(w, fname, force)
515: register Window *w;
516: register char *fname;
517: {
518: register Buffer *b;
519:
520: b = file_exists(fname);
521: if (b == 0) {
522: b = mak_buf();
523: setfname(b, fname);
524: bufname(b);
525: set_ino(b);
526: b->b_ntbf = 1;
527: if (force) {
528: Buffer *oldb = curbuf;
529:
530: SetBuf(b); /* this'll read the file */
531: SetBuf(oldb);
532: }
533: }
534: if (w)
535: tiewind(w, b);
536: return b;
537: }
538:
539: /* Set alternate buffer */
540:
541: SetABuf(b)
542: Buffer *b;
543: {
544: if (b != 0)
545: lastbuf = b;
546: }
547:
548: SetBuf(newbuf)
549: register Buffer *newbuf;
550: {
551: register Buffer *oldb = curbuf;
552:
553: if (newbuf == curbuf || newbuf == 0)
554: return;
555:
556: lsave();
557: curbuf = newbuf;
558: getDOT();
559: /* Do the read now ... */
560: if (curbuf->b_ntbf)
561: read_file(curbuf->b_fname, 0);
562:
563: #ifdef IPROCS
564: if (oldb != 0 && oldb->b_type != curbuf->b_type) {
565: if (curbuf->b_type == B_IPROCESS)
566: PushPBs(); /* Push process bindings */
567: else if (oldb->b_type == B_IPROCESS)
568: PopPBs();
569: }
570: assign_p(); /* Set cur_proc */
571: #endif
572: }
573:
574: Buffer *
575: do_select(w, name)
576: register Window *w;
577: register char *name;
578: {
579: register Buffer *new;
580:
581: if ((new = buf_exists(name)) == 0) {
582: new = mak_buf();
583: setfname(new, (char *) 0);
584: setbname(new, name);
585: }
586: if (w)
587: tiewind(w, new);
588: return new;
589: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.