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