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