|
|
1.1 root 1: /* EMACS_MODES: c !fill */
2: #include <signal.h>
3: #include <sys/types.h>
4: #ifndef PC
5: #include <sys/stat.h>
6: #endif PC
7: #include "emacs_io.h"
8: #include "emacs_gb.h"
9: #include "emacs_buf.h"
10:
11:
12:
13: /* leng * length of a line in the buffer */
14:
15: leng(line)
16:
17: register int line;
18:
19: {
20: /* Keywords: line-representation:10 length */
21:
22: register char *lp;
23: register char *olp;
24:
25: olp = lp = mkline(line);
26: while (*lp++ != EOL);
27: return(lp-olp-1);
28: }
29:
30: allout () /* break all links */
31:
32: {
33: register unsigned *outp;
34: register int xptr;
35: register int q;
36: /* Keywords: buffer-representation:50 line-representation:5 paging buffer-changing:10 */
37:
38: for (outp = ptrs+nlines; outp > ptrs; outp--) {
39: xptr = *outp;
40: if (xptr&01) {
41: q = xptr-1;
42: *outp = ((bblock[q>>BSHIFT]<<BRSHIFT) + ((q&BMASK)>>LSSHIFT))<<1;
43: }
44: }
45: }
46:
47:
48: /* mkline -- make a pointer to the current line */
49:
50: /* pages in the line if out of core, makes a null string for an empty
51: line */
52:
53: char *
54:
55: ckline(line,len)
56: int line;
57: int len;
58: /* Keywords: buffer-representation:50 line-representation:50 paging:20 buffer-allocation */
59:
60: {
61: register char *lp;
62: char *lp1;
63: register char *q;
64: register int fileadd;
65: int x;
66: int s;
67:
68: lp = mkline(line);
69: if (len <= (LSMALL*(*(lp-1))-2)) return(lp);
70:
71: /* current line is too small */
72:
73:
74: if ((len+2) >= MAXEL) {
75: error(WARN,33,line,MAXEL-1); /* report problems */
76: return(NULL); /* line too long, let caller handle */
77: }
78: s = (len+1+LSMALL)>>LSSHIFT;
79: x = ptrs[line]-1;
80:
81: fileadd = (bblock[x>>BSHIFT]<<BRSHIFT) + ((x&BMASK)>>LSSHIFT);
82:
83: if ((fileadd + bbuf[0][x]) == BUFEND) {
84: if ((fileadd & BRMASK) == ((fileadd+s-1)&BRMASK)) {
85:
86: /* current line extends in place */
87: BUFEND = fileadd + s;
88: bbuf [0] [x] = s;
89: TRACE(TRCKEX);
90: TRACE(line);
91: TRACE(s);
92:
93: return (&bbuf[0][x+1]);
94: }
95: }
96:
97: /* must copy to new buffer */
98:
99: if ((BUFEND&BRMASK) != ((BUFEND-1+s)&BRMASK)) {
100: BUFEND = (BUFEND&BRMASK)+BFACT;
101: }
102: ptrs[0] = BUFEND<<1;
103: BUFEND += s;
104: TRACE(TRCKCP);
105: TRACE(line);
106: TRACE(s);
107: xline = line; /* Mark the real line in ptrs[0] */
108: holdin(0,line); /* get both lines in memory */
109: q = &(bbuf[0][ptrs[line]]); /* old line buffer */
110: lp = lp1 = &(bbuf[0][ptrs[0]]); /* new buffer */
111: *(lp-1) = s;
112: s = (*(q-1)*LSMALL); /* old length */
113: while (s--) if ((*lp++ = *q++) == EOL) break;
114: ptrs[line] = ptrs[0];
115: ptrs[0] = 0;
116: modify(line);
117: return(lp1);
118: }
119:
120: char *
121:
122: mkl(line)
123: register int line;
124:
125: {
126: register char *p;
127: register int i;
128: int block;
129: int newf;
130: /* Keywords: buffer-representation paging line-representation buffer-allocation */
131:
132: while (line>nlines) {
133: sputl(nlines+1,0,line);
134: if (line >= NPTRS) {
135: if (!growbuf(line)) return(NULL);
136: }
137: nlines++;
138: ptrs[nlines] = 0;
139: }
140:
141: if (INMEM(line)) return (&bbuf[0][ptrs[line]]);
142:
143: /* no current line */
144:
145: nmkline++; /* count for stats */
146:
147: TRACE(TRMAKE);
148: TRACE(line);
149:
150: if (BUFILE == NULL) {
151: BUFILE = gtemp(curbf); /* get a temp file */
152: BUFEND = BFACT; /* remember 0 == NULL */
153: }
154: if (ptrs[line] == 0) {
155: ptrs[line] = (BUFEND++)<<1; /* assign new buffer */
156: newf = 1;
157: TRACE(TRMKEM);
158: } else newf = 0;
159: block = ((ptrs[line]))>>(BRSHIFT+1);
160:
161: /* first see if desired block is in memory already */
162:
163: for (i = fbkno; i < NBLOCK; i++) if (block == bblock[i]) {
164: goto bfill;
165: }
166:
167: /* now try to swap in */
168:
169: for (i = fbkno; i <= NBLOCK+1; i++) {
170: if (++nxtflsh >= NBLOCK) nxtflsh = fbkno;
171: if (bstat[nxtflsh] == 0) {
172: bgrab(nxtflsh,block); /* get block in (won't fail)*/
173: i = nxtflsh;
174: if (line)lowpt[i]=hipt[i]=line;
175: else lowpt[i]=hipt[i]=xline;
176: goto bfill;
177: } else bflush(nxtflsh); /* try to force out block */
178: }
179:
180: /* can't find a buffer to flush */
181:
182: error(FATAL,34); /* File buffers broken */
183:
184:
185: bfill:
186: p= &bbuf[i][LSMALL*((ptrs[line]>>1)&BRESID)+1];
187: ptrs[line] = p-bbuf[0];
188: if (newf) {
189: *(p-1) = 1; /* line size */
190: *(p) = EOL;
191: modify(line); /* make sure line is flushed */
192: }
193: if (line==0) line = xline;
194: if (line<lowpt[i])lowpt[i]=line;
195: if (line > hipt[i])hipt[i] = line;
196: return(p);
197: }
198:
199:
200: /* gtemp -- get a temp file, and unlink it */
201:
202: gtemp(fn)
203: int fn;
204: {
205: /* Keywords: temporary-files filenames:50 */
206:
207: char tfile [64];
208: register int tf;
209: #ifdef PC
210: retry: seprintf(tfile,"%s:emt.%d",BTEMPATH,fn);
211: tf = creat(tfile,6);
212: if (tf < 0) {
213: ctfile();
214: goto retry;
215: }
216: #else
217: seprintf(tfile,"%s/em.%o.%o",BTEMPATH,fn,getpid());
218: while ((tf = creat(tfile,0600)) < 0) {
219: if ((errno != 4) && (errno != 23)) break;
220: }
221: close(tf);
222: while ((tf = open(tfile,2)) < 0) {
223: if ((errno != 4) && (errno != 23)) break;
224: }
225: if (tf < 0) {
226: error(FATAL,errno,"temp file");
227: }
228: #ifdef MINFILES
229: if (fn == NBUF) unlink(tfile); /* lose the file */
230: #else
231: unlink(tfile); /* lose the file */
232: #endif
233: #endif
234: return(tf);
235: }
236:
237: #ifdef PC
238: rmtemp()
239: {
240: /* Keywords: temporary-files filenames:20 */
241:
242: char tfile[64];
243: int i;
244: btmpfile[curbf] = BUFILE; /* set up for current buffer */
245: for (i = 0; i < NBUF; i++) if (btmpfile[i]) close(btmpfile[i]);
246: if (kfile) close(kfile);
247: for (i = 0; i <= NBUF; i++) {
248: seprintf(tfile,"%s:emt.%d",BTEMPATH,i);
249: unlink(tfile);
250: }
251: }
252:
253: /* Called on out of space errors, asks for file to delete and continues */
254:
255: mkspace()
256: {
257: char *cp;
258: char filebuf[64];
259: char tmp[128];
260: /* Keywords: PC-only temporary-files deletion:10 user-interface:50 */
261:
262: if (error(WARN,76,BTEMPATH) == 0) {
263: cp = getname("File to delete on temp file disk?");
264: if (cp) {
265: mstrcpy(tmp,fnbuf); /* Preserve fnbuf */
266: seprintf(filebuf,"%s:%s",BTEMPATH,cp);
267: if (unlink(filebuf) == 0) {
268: mstrcpy(fnbuf,tmp);
269: return(1);
270: }
271: mstrcpy(fnbuf,tmp);
272: }
273: }
274: return(0);
275: }
276: #endif PC
277:
278: #ifdef MINFILES
279: rmtemp()
280: {
281: /* Keywords: temporary-files filenames:20 */
282: char tfile [64];
283: register int fn;
284: btmpfile[curbf] = BUFILE; /* set up for current buffer */
285: for (fn = 0; fn < NBUF; fn++) {
286: if (btmpfile[fn]) {
287: rftmp(fn);
288: }
289: }
290: rftmp(NBUF);
291: }
292: rftmp(fn)
293: register int fn;
294: {
295: /* Keywords: temporary-files filenames:20 MINFILES-version */
296: char tfile[64];
297: seprintf(tfile,"%s/em.%o.%o",BTEMPATH,fn,getpid());
298: unlink(tfile);
299: }
300:
301: otemp(fn)
302: int fn;
303: {
304: /* Keywords: temporary-files filenames:20 MINFILES-version */
305: char tfile [64];
306: register int tf;
307: seprintf(tfile,"%s/em.%o.%o",BTEMPATH,fn,getpid());
308: while ((tf = open(tfile,2)) < 0) {
309: if ((errno != 4) && (errno != 23)) break;
310: }
311: if (tf < 0) {
312: error(FATAL,errno,"temp file");
313: }
314: return(tf);
315: }
316: #endif
317:
318: /* utility program to insure that both lines are in memory before proceeding */
319:
320: holdin(line1,line2)
321:
322: register int line1,line2;
323: /* Keywords: paging line-representation:10 */
324:
325: {
326:
327: while (OUTMEM(line1) || OUTMEM(line2)) {
328: mkline(line1);
329: mkline(line2);
330: }
331: }
332:
333: /* growbuf -- grow the amount of buffer storage */
334: growbuf(iline)
335:
336: int iline;
337: /* Keywords: buffer-representation memory-allocation */
338:
339: {
340: register unsigned *ndadd;
341: register int line;
342:
343:
344: line = (iline&BRKMSK)+01000; /* round up to next multiple
345: * of 512 */
346:
347: ndadd = &ptrs[line]; /* new need address */
348: #ifdef PC
349: if (line >= MPTRS) {
350: #else
351: if (brk(ndadd) != 0) {
352: #endif PC
353: line = iline+4; /* try for less */
354: ndadd = &ptrs[line];
355: #ifdef PC
356: if (line >= MPTRS) {
357: #else
358: if (brk(ndadd) != 0) {
359: #endif PC
360: error(NORM,35); /* Too Many lines */
361: return(0);
362: }
363: }
364: NPTRS = line;
365: return(1);
366:
367: }
368:
369:
370:
371:
372: /* bgrab -- fill a specific buffer with a specific block */
373:
374: bgrab(x,blkno)
375: /* Keywords: buffer-representation paging paging-I/O encryption:10 */
376:
377: register int x;
378: int blkno;
379: {
380: register int base;
381: register unsigned *p;
382: register unsigned *endp;
383: #ifndef pdp11
384: unsigned bsblock;
385: #else
386: unsigned short bsblock;
387: #endif
388: int rstat;
389: long seekpos;
390:
391: TRACE(TRBGRAB);
392: TRACE(x);
393: TRACE(blkno);
394: if (bblock[x]) { /* if block is occupied */
395: if (bstat[x]) {
396: if (bflush(x)== 0) return(0);
397: }
398: base = x*BLEN+1;
399: bsblock = bblock[x]<<(1+BRSHIFT);
400: if (hipt[x] > nlines) hipt[x]=nlines; /* Make sure it's in bounds! */
401: if (lowpt[x] < 0) lowpt[x] = 0; /* likewise */
402: endp = &ptrs[lowpt[x]];
403: for (p= &ptrs[hipt[x]]; p>=endp; p--) {
404: if((*p &01) && (((*p - base)&(~BMASK)) == NULL)) {
405: *p = bsblock + ((*p - base)>>(LSSHIFT-1));
406: }
407: }
408: /* break all links to block */
409:
410: }
411: bblock[x] = blkno;
412: if (blkno&& (blkno<=mostwrit)) {
413: if (blkno != sblk) { /* if we must seek */
414: TRACE(TRSEEK);
415: TRACE(sblk);
416: TRACE(blkno);
417: seekpos = (long) BLEN * (long) blkno;
418: nbseek++;
419: lseek(BUFILE,seekpos,0);
420: }
421: nbread++;
422: TRACE(TRREAD);
423: TRACE(x);
424: TRACE(blkno);
425: while ((rstat =read(BUFILE,bbuf[x],BLEN)) != BLEN) {
426: if (errno != 4) break;
427: }
428: if (rstat != BLEN) error(FATAL,errno,"reading buffer");
429: #ifdef CRYPTO
430: if (bbuf[x][0]&0200) {
431:
432: /* First byte of buffer is always a count, and thus shouldn't have the */
433: /* 0200 bit on. This insures that enciphered bufferes are deciphered */
434:
435: cryptic(&bbuf[x][0]);
436: bbuf[x][0] &= 0177; /* Make sure high order bit is off */
437: }
438: #endif
439: sblk = blkno+1;
440: }
441: return(1);
442: }
443: #ifdef CRYPTO
444: cryptic(cp)
445: register long *cp; /* Types deliberately mismatched */
446: {
447: /* Keywords: buffer-representation encryption paging:10 */
448:
449: long x;
450: register long *endp;
451:
452: endp = cp + BLEN/sizeof(x);
453: while (cp < endp) *cp++ ^= bufkey;
454: }
455: #endif
456: /* bflush -- flush contents of a buffer */
457:
458: bflush(x)
459: /* Keywords: buffer-representation paging paging-I/O encryption:10 */
460:
461: register int x;
462: {
463:
464: long seekpos;
465: if (bstat[x]) {
466: retry:
467: if (sblk != bblock[x]) {
468: seekpos = (long) bblock[x] * (long) BLEN;
469: TRACE(TRSEEK);
470: TRACE(sblk);
471: TRACE(bblock[x]);
472: nbseek++;
473: lseek(BUFILE,seekpos,0);
474: }
475: #ifdef CRYPTO
476: if (crypt) {
477: cryptic(&bbuf[x][0]);
478: bbuf[x][0] |= 0200;
479: }
480: #endif CRYPTO
481: while(write(BUFILE,bbuf[x],BLEN) != BLEN) {
482: #ifdef PC
483: if (mkspace()) {
484: bblock[x] = -1; /* Don't know where we are */
485: goto retry;
486: }
487: return(0);
488: #else
489: if (errno != 4) error(FATAL,errno,"buffer file");
490: #endif
491: }
492: #ifdef CRYPTO
493: if (bbuf[x][0]&0200) {
494: cryptic(&bbuf[x][0]);
495: bbuf[x][0] &= 0177; /* Make sure high order bit is off */
496: }
497: #endif CRYPTO
498: nbwrite++;
499: TRACE(TRWRIT);
500: TRACE(x);
501: TRACE(bblock[x]);
502: sblk = bblock[x]+1;
503: if (bblock[x] > mostwrit) mostwrit = bblock[x];
504: bstat[x] = 0;
505: }
506: return(1);
507: }
508:
509: /* initializes line buffer free list, ptrs array to empty */
510:
511:
512:
513: bufinit()
514: /* Keywords: buffer-changing:10 buffer-representation buffer-allocation:50 */
515:
516: {
517: register int i;
518: register unsigned *p;
519:
520: /* now set up buffer stuff */
521:
522:
523: for (p = &ptrs[NPTRS-1]; p >= ptrs; p--) { /* clear ptrs */
524: *p = 0;
525: }
526:
527: /* set up free buffer line list */
528:
529: for (i = fbkno; i < NBLOCK; i++) bstat[i] = bblock[i] = 0;
530: nxtflsh= NBLOCK; /* initial buffer to use */
531: nlines = 1;
532: mostwrit = 0;
533: sblk = 0;
534: curln = 1;
535: column = 0;
536: curblk = 0;
537: if (BUFILE) BUFEND = BFACT; /* re-use buffer */
538: }
539: #ifdef PC
540:
541: /* change temp file -- change place where temp files are put. */
542:
543:
544: ctfile()
545: {
546: /* Keywords: PC-only buffer-representation temporary-files filenames:10 */
547:
548: char *cp;
549: cp = getname("Tempfile Directory? ");
550: if (cp) {
551: *BTEMPATH = *cp;
552: }
553: if (mostwrit == 0) {
554: /* Re-allocate current buffer */
555: close(BUFILE);
556: BUFILE = gtemp(curbf);
557: }
558: }
559:
560: #endif PC
561: /* wout -- write out file */
562:
563: wout(name,aflag)
564: /* Keywords: writing buffer-representation:50 commands:10 PC-only:10 macro-hooks:10 */
565: /* Keywords: encryption:20 unix-interface:10 dired:20 user-interface:10 */
566:
567: char *name;
568: int aflag;
569: {
570: FILE outbuf[1];
571: register FILE *outfile;
572: register int i;
573: int nosave; /* return value from backup link */
574: char backb[128]; /* buffer for name of backup file */
575: char *backp;
576: char *bp;
577: register char *cp;
578: #ifndef PC
579: struct stat inode; /* status buffer */
580: #endif
581: int status;
582: int xstat;
583:
584: if (hooks[Pre_Write_Hook]) {
585: stkstr(name);
586: if (hook(Pre_Write_Hook)==0) {
587: unprompt();
588: return(0);
589: }
590: retrvs(fnbuf,FNLEN);
591: name=fnbuf;
592: }
593:
594: #ifdef DIRED
595: if (diron) return(dclean());
596: #endif
597: if (*name == NULL) return(0);
598: bp = name;
599: cp = backp = backb;
600: while (*cp = *bp++) {
601: if (*cp++ == '/') backp = cp;
602: }
603: strcpy(backp,"EMACS_save");
604: nosave = 1;
605: prompt1("Wait");
606: #ifndef PC
607: mflush(stdout);
608: status = stat(name,&inode); /* get old file modes */
609: /* don't care if file not there */
610: /* if ((status==0) && (((inode.st_mode &0200) == 0) || (inode.st_uid != myuid))) {*/
611: if (status == 0) {
612: if (inode.st_mode & S_IFDIR) {/* Writing a directory, yuck */
613: error(WARN,81,name,name,filename);
614: return(0);
615: }
616: if (access(name,02) != 0) {
617: if (gyn("File not explicitly writeable, write anyway?")<=0) return(0);
618: }
619: }
620: #endif PC
621: if ((aflag>1)||(aflag<-1)) {
622: outfile = xopen (outbuf,name,"ba");
623: if (status == 0) goto wfile1; /* if file was there */
624: }
625: #ifndef PC
626: if ((status == 0) && streq(filename,name) &&
627: (mtime[bfnumb()]) && (mtime[bfnumb()] != inode.st_mtime)) {
628:
629: error(WARN,78,name);
630: return(0);
631: }
632: /* don't prompt if user wants file links saved */
633: if (savelink) goto wfile;
634: if ((status== 0) && (inode.st_nlink != 1)) {
635:
636: i = gyn("File %s is linked to another, write to both (y) or only to %s ?",name,name);
637: if (i < 0) return(0);
638: if (i > 0) goto wfile;
639: }
640:
641: nosave = streq(name,backb); /* see if we are trying to link backup */
642: if (nosave==0) {
643: nosave = link (name,backb);
644:
645: /* make backup link to file in case */
646: /* we crash. Old copy will be in
647: * EMACS_save if crash occurs during write */
648: if (nosave == 0) unlink(name); /* remove old file */
649: }
650: #endif PC
651: wfile: outfile = xopen (outbuf,name,"bw");
652: wfile1: if (outfile == NULL) {
653: error(WARN,errno,name);
654: return(0);
655: }
656: prompt1("Writing");
657: mflush(stdout);
658:
659: #ifdef CRYPTO
660: if (crypt) {
661: char crbuf[32];
662: seprintf(crbuf,"crypt %s",cryptkey);
663: splfile = outfile ->_frn;
664: if (unx(crbuf,6)<0) return(0);
665: outfile->_frn = splfile;
666: }
667: #endif
668:
669: for (i = 1; i <= nlines; i++) {
670: if (i != 1) {
671: #ifdef PC
672: if (BINMODE == 0) putc(CTRLM,outfile);
673: #endif PC
674: putc('\n',outfile);
675: }
676: cp = mkline(i);
677: while (*cp != EOL) {
678: if (PICMODE && (*cp == ' ')) {
679: register int x;
680: for (x = 1; cp[x]==' '; x++);
681: if (cp[x] == EOL) break;
682: while (x--) {
683: putc(*cp,outfile);
684: cp++;
685: }
686: } else {
687: putc(*cp,outfile);
688: cp++;
689: }
690: }
691: }
692: if (EOFNL) {
693: cp = mkline(nlines);
694: if (*cp!=EOL) {
695: putc('\n', outfile);
696: #ifdef PC
697: if (BINMODE == 0) putc(CTRLM,outfile);
698: #endif PC
699: }
700: }
701: #ifdef PC
702: if (BINMODE == 0) putc('\032',outfile);
703: mclose(outfile);
704: #else
705: if (mclose(outfile)) { /* Error occurred during write */
706: /* Try to put back old file */
707: if (nosave==0) { /* error writing saved file */
708: unlink(name);
709: link(backb,name); /* Put everything back */
710: unlink(backb);
711: prompt1("No write: %s", name);
712: return(0);
713: }
714: prompt1("File errors: %s", name);
715: mtime[bfnumb()] = 0;
716: return(0);
717: }
718:
719: #ifdef CRYPTO
720: if (crypt) wait(&xstat); /* Eliminate zombies */
721: #endif
722: if (nosave == 0) unlink(backb); /* remove backup link */
723:
724: if (status == 0) {
725: chmod(name,inode.st_mode);/* set modes right */
726: chown(name,inode.st_uid,inode.st_gid); /* set owner and group */
727: } else {
728: chmod(name,0666 & ~mymask);/* Modes by umask */
729: }
730: #endif PC
731: if ((aflag<2)&&(aflag>-2)) {
732: prompt1("Written: %s", name);
733: }
734: else prompt1("Appended: %s", name);
735: NSCHAR=0;
736: if (aflag>0) {
737: strcpy(filename,name);
738: bufmod = 0;
739: }
740: #ifndef PC
741: if (streq(filename,name)) {
742:
743: if (stat(name,&inode) != 0) {
744: error(WARN,errno,name);
745: } else {
746: mtime[bfnumb()] = inode.st_mtime;
747: }
748: }
749: #endif
750: dispmod();
751: move(curln,column); /* Restore state information */
752: return(1);
753: }
754:
755: /* read in a file into the buffer */
756: /* re-initializes buffer first */
757:
758:
759: readin(fn,reinit)
760:
761: char *fn;
762: int reinit;
763: {
764:
765: /* Keywords: reading encryption:20 PC-only:10 dired:10 unix-interface:10 commands:10 macro-hooks:10 */
766:
767: FILE *filein;
768: FILE finbuf[1];
769: #ifndef PC
770: struct stat inode;
771: int xstat;
772: #endif
773: #ifdef DIRED
774: extern char dired_args[];
775: #endif
776:
777: if (fn[0] == 0) fn = filename; /* default to previous file */
778: if (fn[0] == 0) return(0); /* no default */
779:
780: if (VERBOSE) {
781: prompt1 ("Wait");
782: mflush(stdout);
783: }
784: if (hooks[Pre_Read_Hook]) {
785: stkstr(fn);
786: if (hook(Pre_Read_Hook) == 0) {
787: unprompt();
788: return(0);
789: }
790: retrvs(fnbuf,FNLEN);
791: fn = fnbuf;
792: }
793: filein = xopen( finbuf,fn,"br");
794: if (filein == NULL) {
795: unprompt();
796: if (reinit>0) error(WARN,errno,fn);
797: if (filename[0] == 0) {
798: strcpy(filename,fn); /* copy name */
799: dispmod();
800: }
801: return(0);
802: }
803: #ifndef PC
804: if (fstat(filein->_frn,&inode) != 0) {
805: error(WARN,errno,fn);
806: return(0);
807: }
808: if (inode.st_size >= MAXFS) { /* Check for grossly huge file */
809: error(WARN,77,fn);
810: return(0);
811: }
812: #ifndef DIRED
813: if (inode.st_mode & S_IFDIR) {
814: /* Reading a directory, check to be sure */
815: if (error(WARN,82,fn)) return(0);
816: /* go ahead and read it if the user wants to */
817: }
818: #endif
819: #endif
820: #ifdef DIRED
821: if (inode.st_mode & S_IFDIR) {
822: char dircom[128];
823: diron = 1;
824: splfile = filein ->_frn;
825: seprintf(dircom,"ls %s %s", dired_args,fn);
826: if (unx(dircom,7) < 0) return(0);
827: filein->_frn = splfile;
828: } else diron = 0;
829: #endif
830: if (VERBOSE) {
831: prompt1("Reading");
832: mflush(stdout);
833: }
834: if (reinit == -1) reinit = 1;
835: if (reinit == 1) bufinit();
836: #ifdef CRYPTO
837: if (crypt) {
838: char crbuf[32];
839: seprintf(crbuf,"crypt %s",cryptkey);
840: splfile = filein->_frn;
841: if (unx(crbuf ,7)<0) return(0);
842: filein->_frn = splfile;
843: }
844: #endif
845: readsub(filein,reinit,fn,0); /* do the reading */
846: #ifdef CRYPTO
847: if (crypt) wait(&xstat); /* Eliminate zombies */
848: #endif
849: #ifdef DIRED
850: if (diron) wait(&xstat); /* Eliminate zombies */
851: #endif
852: #ifndef PC
853: if (streq(filename,fn)) {
854: struct stat ninode;
855: mtime[bfnumb()] = inode.st_mtime;
856: if (stat(fn,&ninode) != 0) {
857: error(WARN,errno,fn);
858: } else {
859: if ((ninode.st_mtime != inode.st_mtime)||
860: (ninode.st_ino != inode.st_ino)) {
861: error(WARN,79,fn);
862: }
863: }
864: }
865: #endif
866: unprompt();
867: ttfill(); /* try to read ahead*/
868: if (hooks[Post_Read_Hook]) hook (Post_Read_Hook);
869: return(1);
870: }
871:
872:
873: readsub(filein,reinit,fn,cpyflag)
874: /* Keywords: reading buffer-representation:5 unix-interface:20 dired:30 file-modes:10 */
875:
876: int reinit;
877: #ifndef pdp11
878: register
879: #endif
880: int cpyflag;
881: register FILE *filein;
882: char *fn;
883: {
884: register int c;
885: int i;
886: char fbuf[MAXEL];
887: register char *fp;
888: register char *endbuf;
889: int warnl;
890:
891: i = curln;
892: if (reinit != 1) {
893: RARE = 1; /* turn off trouble */
894: while ((c = getc(filein)) != EOF) {
895: #ifdef PC
896: if (BINMODE == 0){
897: if (c == '\032') break;
898: if (c == '\n') bdel(1); /* Wipe out spurious cr */
899:
900: }
901: #endif PC
902: if (cpyflag) putchar(c); /* output character */
903: put(c);
904: if (c == EOL) clptr = mkline(curln);
905: }
906: } else {
907: if (BUFILE == NULL) {
908: BUFILE = gtemp(curbf); /* get a temp file */
909: }
910: BUFEND = BFACT; /* remember 0 == NULL */
911: fp = &fbuf[0];
912: endbuf = fbuf+MAXEL-2;
913: warnl = -1; /* last "line too long" */
914: while ((c = getc(filein)) != EOF) {
915: #ifdef PC
916: if (BINMODE == 0){
917: if (c == '\032') break;
918: if (c == '\n') fp--; /* Wipe out trailing CR */
919: }
920: #endif PC
921: if (cpyflag) putchar(c); /* echo to terminal */
922:
923: if (c == '\n') {
924: *fp = EOL;
925: if (addline(fbuf,fp-fbuf,i++)==0) goto eof;
926: fp = &fbuf[0];
927: } else {
928: #ifdef DIRED
929: if (diron) while (fp-fbuf < 4) *fp++ = ' '; /* make room for markings */
930:
931: #endif
932: *fp++ = c;
933: if (fp >= endbuf) {
934: fp--;
935: if (i == warnl) continue;
936: warnl = i;
937: if(error(NORM,33,i,MAXEL-1)) goto eof;
938: continue;
939: }
940: }
941: }
942: eof: *fp = EOL;
943: addline(fbuf,fp-fbuf,i);
944: move(1,0);
945: strncpy(filename,fn,FNLEN); /* Copy name written */
946: bufmod = 0; /* buffer up to date */
947: }
948: mclose(filein);
949: if (cpyflag) mflush(stdout); /* Force output to come out */
950: NSCHAR = 0;
951: bfmodes(); /* set buffer modes */
952: fclear(); /* file is now bad */
953: RARE = 0; /* normal modes back on */
954: }
955:
956: /* Express access to the buffer. This code plunks in one line at
957: * the end of the buffer, manipulating all appropriate data, much
958: * swifter than the usual ckline-bgrab sequence. What is assumed by
959: * this function is that it is called after bufinit and no other
960: * intervening buffer manipulations. It leaves the ptrs array set
961: * up with no lines in memory, but with the last n blocks of the
962: * file in bbuf and properly initialized. */
963:
964:
965:
966:
967: addline(cp,len,line)
968: register char *cp;
969: int len;
970: int line;
971: {
972: /* Keywords: buffer-representation:50 line-representation:20 reading:10 buffer-allocation:20 */
973:
974: register char *lp;
975: register int x;
976: register int s;
977:
978: if (line >= NPTRS) {
979: if (!growbuf(line)) {
980: error(NORM,35);
981: return(0);
982: }
983: }
984: nlines=line;
985:
986: s = (len+1+LSMALL)>>LSSHIFT;
987: if (((BUFEND-1) & BRMASK) != ((BUFEND+s-1)&BRMASK)) {
988:
989: /* Need to go into the next block */
990:
991: nxtflsh++;
992: if (nxtflsh>=NBLOCK) nxtflsh=fbkno;
993: x = nxtflsh;
994: bflush(x);
995: BUFEND=((BUFEND-1)&BRMASK)+BFACT;
996: bstat[x]=1;
997: lowpt[x]=hipt[x]=line;
998: bblock[x]=(BUFEND>>BRSHIFT);
999: }
1000: ptrs[nlines] = BUFEND<<1;
1001: lp = &bbuf[nxtflsh][((BUFEND&BRESID)<<LSSHIFT)];
1002: *lp++ = s; /* save size */
1003: while ((*lp++ = *cp++) != EOL); /* copy the line */
1004: BUFEND += s;
1005: return(1);
1006: }
1007:
1008:
1009:
1010: /* findf -- go forward to find row and columns */
1011:
1012: /* leaves kline, kcol pointing at the character count characters ahead
1013: of curln, column */
1014:
1015:
1016: findf(count)
1017:
1018: register int count;
1019: /* Keywords: buffer-representation:10 movement:20 commands:10 forwards */
1020:
1021: {
1022: kmark();
1023: while (count--) {
1024: if (*klptr++ != EOL) kcol++;
1025: else {
1026: if (kline == nlines) return(0);
1027: kcol = 0;
1028: ++kline;
1029: klptr = mkline(kline);
1030: }
1031: }
1032: return(1);
1033: }
1034:
1035: /* findb -- go back n chars */
1036:
1037: /* leaves kline, kcol pointing at the character count characters before
1038: the current character */
1039: /* Keywords: buffer-representation:10 movement:20 commands:10 backwards */
1040: findb(count)
1041:
1042: register int count;
1043:
1044: {
1045: kline = curln;
1046: kcol = column;
1047:
1048: while (count) {
1049: if (count > kcol) {
1050: count-=(kcol+1); /*plus one for the nl */
1051: kcol = 0;
1052: if (kline == 1) return(0);
1053: kline--;
1054: kcol = leng(kline);
1055: } else {
1056: kcol -= count;
1057: return(1);
1058: }
1059: }
1060: return(1);
1061: }
1062:
1063:
1064: /* mark a line as modified (also re-displays mode line if necessary) */
1065:
1066:
1067: modify(line)
1068: /* Keywords: buffer-representation:10 dired:20 mode-line:10 deletion:10 insertion:10 */
1069:
1070: register int line;
1071:
1072: {
1073:
1074: if (INMEM(line)) {
1075: bstat[(ptrs[line])>>BSHIFT] = 1;
1076: }
1077: #ifdef DIRED
1078: if (diron) {
1079: register char *lp;
1080: lp = mkline(line);
1081: if ((column > 4) && (column < 14)) {
1082: lp[1] = 'M';
1083: } else if ((column > 18) && (column < 36)) {
1084: lp[2] = 'O';
1085: }
1086: sputl(line,1,line); /* refresh */
1087: }
1088: #endif
1089: if (bufmod == 0) {
1090: bufmod++;
1091: dispmod();
1092: }
1093: }
1094:
1095: /* stack text segment on kill stack */
1096:
1097: /* the kill stack holds up to NKILLP segments, or a total of KBSIZE
1098: * characters. killstk adds the segment delimited by its arguments to
1099: * this stack */
1100:
1101: killstk(a,b,c,d)
1102: /* Keywords: killstack stacking picture-mode:10 deletion:10 */
1103:
1104: register int a;
1105: register int b;
1106: int c;
1107: int d;
1108:
1109: {
1110: register char *ap;
1111:
1112: if (kbapp) { /* if appending */
1113: kend--; /* backspace over the \0 */
1114: } else {
1115: if (nkp == NKILLP) { /* no more kill pointers available */
1116: mvdown();
1117: }
1118: nkp++;
1119: kstk[nkp] = kend; /* start of saved text */
1120: }
1121: kget(kend);
1122:
1123: if (PICMODE) {
1124: int x;
1125: if (b>d) {
1126: x=d;
1127: d=b;
1128: b=x;
1129: }
1130: while (a <= c) {
1131: ap = mkline(a);
1132: a++;
1133: for (x = 0; x < d; x++) {
1134: if (x<b) {
1135: if (*ap != EOL) ap++;
1136: } else {
1137: if (*ap != EOL) {
1138: kbuf[kptr++] = *ap++;
1139: } else {
1140: kbuf[kptr++] = ' ';
1141: }
1142: kbmod=1;
1143: if (kptr>=KBSIZE) knext();
1144: }
1145: }
1146: if (a<=c) {
1147: kbmod=1;
1148: kbuf[kptr++] = EOL;
1149: if (kptr>=KBSIZE) knext();
1150: }
1151: }
1152: } else {
1153: ap = mkline(a);
1154: while ((a < c) || (b < d) ) {
1155: if ((kbuf[kptr] = ap[b++]) == EOL) {
1156: ++a;
1157: ap = mkline(a);
1158: b = 0;
1159: }
1160: kbmod = 1;
1161: if (++kptr>=KBSIZE) {
1162: knext();
1163: }
1164: }
1165: }
1166: kbapp = 0; /* don't turn on append for now */
1167: kbuf[kptr++] = 0;
1168: kbmod = 1;
1169: if (kptr>=KBSIZE) {
1170: knext();
1171: }
1172: kend = (long)kptr + kbase;
1173: }
1174: stkstr(sp)
1175: /* Keywords: killstack stacking macro-programming:50 */
1176:
1177: register char *sp;
1178: {
1179: register char c;
1180:
1181: if (kbapp) { /* if appending */
1182: kend--; /* backspace over the \0 */
1183: } else {
1184: if (nkp == NKILLP) { /* no more kill pointers available */
1185: mvdown();
1186: }
1187: nkp++;
1188: kstk[nkp] = kend; /* start of saved text */
1189: }
1190: kget(kend);
1191: do {
1192: c = kbuf[kptr++] = *sp++;
1193: kbmod = 1;
1194: if (kptr>=KBSIZE) knext();
1195: } while (c);
1196: kend = (long)kptr + kbase;
1197: kbapp = 0;
1198: }
1199:
1200: kput(ptr)
1201: unsigned int ptr;
1202: {
1203: /* Keywords: killstack stacking string-variables macro-programming:20 */
1204:
1205: long real_ptr;
1206: int x;
1207:
1208: if (sizeof(x) < 4) { /* If int's are only 16 bits, adjust ptr */
1209:
1210: real_ptr = kend & 0177777;
1211: if (real_ptr > ptr) real_ptr = ((long) ptr) + (kend & 037777600000);
1212: else real_ptr = ((long) ptr) + (kend & 037777600000) -65536;
1213: } else real_ptr = ptr;
1214:
1215: if ((real_ptr < 0) || (real_ptr >= kend)) {
1216: error (WARN,82);
1217: real_ptr = 0;
1218: }
1219: if (nkp == NKILLP) { /* no more kill pointers available */
1220: mvdown();
1221: }
1222: nkp++;
1223: kstk[nkp] = real_ptr; /* start of saved text */
1224: }
1225: kgptr()
1226: {
1227: /* Keywords: killstack stacking insertion:10 retrieval:10 string-variables:10 */
1228: if (nkp>-1) {
1229: nkp--;
1230: return(kstk[nkp+1]);
1231: } else {
1232: return(0); /* Error, too many pops */
1233: }
1234: }
1235:
1236:
1237:
1238: /* kapp -- append to kill buffer */
1239:
1240: kapp()
1241: {
1242: /* Keywords: commands killstack appending */
1243:
1244: kbapp = 2; /* force next kill to append */
1245: }
1246:
1247: /*knext -- next kill buffer*/
1248:
1249:
1250: knext()
1251: {
1252: long nbase;
1253: /* Keywords: killstack paging */
1254:
1255: nbase = kbase + (long) KBSIZE;
1256: if (nbase >= KBLIM) nbase = 0;
1257: kget(nbase);
1258: }
1259:
1260:
1261: /* kget get next kill buffer */
1262:
1263: kget(nbase)
1264: long nbase;
1265: {
1266: /* Keywords: killstack paging paging-I/O */
1267:
1268: register long xbase;
1269: int st;
1270:
1271: #ifdef univac /* MZ */
1272: xbase = nbase & 0xffffffe00; /* Univac uses one's compliment. */
1273: #else /* MZ */
1274: xbase = nbase &( (long) -KBSIZE);
1275: #endif /* MZ */
1276:
1277: if (xbase == kbase) {
1278: kptr = nbase - kbase;
1279: return;
1280: }
1281: if (kfile == 0) {
1282: kfile = gtemp(NBUF);
1283: }
1284: if (kbmod) {
1285: retry: lseek(kfile,kbase,0);
1286: while(write(kfile,kbuf,KBSIZE) != KBSIZE) {
1287: #ifdef PC
1288: if (mkspace()) goto retry;
1289: break;
1290: #else
1291: if (errno != 4) error(FATAL,errno,"kill buffer");
1292: #endif
1293: }
1294: if (kbase >= kbwrt) kbwrt = kbase+KBSIZE;
1295: kbmod = 0;
1296: }
1297: if (nbase < kbwrt) {
1298: lseek(kfile,xbase,0);
1299: while((st=read(kfile,kbuf,KBSIZE) != KBSIZE)) {
1300: if (errno != 4) {
1301: error(FATAL,errno,"reading kill buffer");
1302: return;
1303: }
1304: }
1305: }
1306: kbase = xbase;
1307: kptr = nbase-xbase;
1308: return;
1309: }
1310:
1311: /* mvdown pushes the bottom text segment off of the kill stack */
1312:
1313:
1314:
1315: mvdown() /* move down kill stack */
1316: /* Keywords: killstack stacking */
1317:
1318: {
1319: register int i;
1320: for (i = 0; i <= nkp; i++) kstk[i] = kstk[i+1];
1321: nkp--;
1322: }
1323:
1324: /* retrv retrieves the top text segment from the kill stack and inserts
1325: * it into the buffer at the current location */
1326:
1327:
1328: retrv() /* retrieve from kill stack */
1329: /* Keywords: commands killstack picture-mode:20 insertion:10 retrieval */
1330:
1331: {
1332: register char c;
1333: register int oldcol,oldln;
1334:
1335: if (nkp <0) return(0); /* nothing in the kill stack */
1336: RARE = 1; /* turn off trouble */
1337: oldln = curln;
1338: oldcol = column;
1339: kget(kstk[nkp]);
1340: while (c= kbuf[kptr]) {
1341: if (PICMODE) {
1342: if (c==EOL) {
1343: move(++curln,0);
1344: lext(curln,oldcol);
1345: } else {
1346: insertc(1,c);
1347: }
1348: } else {
1349: if(put(c)==0) break;
1350: }
1351: if (++kptr >= KBSIZE) {
1352: knext();
1353: }
1354: }
1355: RARE = 0; /* normal modes back on */
1356: unins(oldln,oldcol);
1357: return(1); /* done */
1358: }
1359:
1360: retrvs(strp,mc) /* retrieve from kill stack */
1361: /* Keywords: commands killstack macro-programming retrieval */
1362:
1363: register char *strp;
1364: register int mc;
1365: {
1366: register int nc;
1367:
1368: nc = 0;
1369:
1370:
1371: kget(kstk[nkp]);
1372: while (*strp++ = kbuf[kptr]) {
1373: if (++nc >= mc) {
1374: *(--strp) = 0; /* finish off string */
1375: error(WARN,63); /* file name too big */
1376: break; /* break loop */
1377: }
1378: if (++kptr >= KBSIZE) {
1379: knext();
1380: }
1381: }
1382: kpop(); /* pop the kill stack */
1383: if (etrace) {
1384: putout("Retrieved %s from kill stack",strp-nc-1);
1385: }
1386: return(nc); /* done */
1387: }
1388:
1389: /* kpop pops the top item off of the kill stack */
1390: kpop()
1391: /* Keywords: commands killstack stacking popping */
1392:
1393: {
1394: if (nkp>-1) {
1395: nkp--;
1396: return(1);
1397: } else return(0);
1398: }
1399:
1400: /* fsave saves the buffer if it has been modified since last read or write */
1401:
1402:
1403: fsave(arg)
1404: register int arg;
1405: {
1406: /* Keywords: commands buffers files writing:50 saving dired:10 */
1407:
1408: if ((arg == 0) && (streq(bbfname[curbf],".exec"))) return(0);
1409:
1410: #ifdef DIRED
1411: if (diron) return(dclean());
1412: #endif
1413: if (READONLY) {
1414: if (arg) error(WARN,71);
1415: return(0);
1416: }
1417: if (bufmod && (*filename== 0)) {
1418: if (infrn == 0) return(fright(1)); /* no file name */
1419: error(WARN,65,bufname); /* Don't read the file name in a macro */
1420: return(0);
1421: }
1422:
1423: if (bufmod) {
1424: return(wout(filename,1));
1425: } else {
1426: if (arg == 0) return(1);
1427: prompt1("File %s is up to date",filename);
1428: return(1);
1429: }
1430: }
1431:
1432: /* fname, bname, and modded return the current file, buffer, and buffer
1433: * modified flags */
1434:
1435:
1436: char *
1437: fname()
1438: {
1439: return(filename);
1440: }
1441: char *
1442: bname()
1443: {
1444: return(bufname);
1445: }
1446: int
1447: bfnumb()
1448: {
1449: return(curbf);
1450: }
1451: int
1452: modded()
1453: {
1454: if (bufmod) return(1);
1455: else return(0);
1456: }
1457:
1458: /* chbuf moves to a new buffer denoted by the buffer number of its
1459: * argument */
1460:
1461: /* each buffer has a filename, buffername, modified flag, current
1462: * position, and size, The ptrs array of a non-active buffer is stored in
1463: * the temp file for the buffer.
1464: */
1465:
1466: chbuf(x)
1467:
1468: register int x;
1469: /* Keywords: buffers:50 buffer-representation buffer-changing unix-interface macro-hooks:10 */
1470:
1471: {
1472: register int i;
1473: register int rx;
1474: unsigned cpointer;
1475:
1476:
1477: if (SAVEMD) IGNORE(fsave(0)); /* save buffer */
1478: if (hooks[Leave_Buffer_Hook]) hook(Leave_Buffer_Hook);
1479: for (i = fbkno; i < NBLOCK; i++) bflush(i);
1480: allout();
1481: NSCHAR = 0;
1482: btmpfile[curbf] = BUFILE;
1483: btmpfree[curbf] = BUFEND;
1484: bcurln[curbf] = curln;
1485: bcolumn[curbf] = column;
1486: if (BUFILE) {
1487: while (1) {
1488: lseek(BUFILE,(long)((long) BUFEND * (long) LSMALL),0);
1489: rx = write(BUFILE,(char *)ptrs,(nlines+1)*(sizeof cpointer));
1490: if (rx == (nlines+1)*(sizeof cpointer)) break;
1491: #ifdef PC
1492: mkspace();
1493: #endif
1494: }
1495: }
1496: bnlines[curbf] = nlines;
1497: #ifdef MINFILES
1498: if (BUFILE) close(BUFILE);
1499: if (btmpfile[x]) btmpfile[x] = otemp(x);
1500: #endif
1501: curbf = x;
1502: bufinit();
1503:
1504: BUFEND = btmpfree[x];
1505: mostwrit = ((BUFEND-1)/BFACT);
1506: BUFILE = btmpfile[x];
1507: nlines = bnlines[x];
1508: if (BUFILE) {
1509: while (1) {
1510: lseek(BUFILE, (long)((long) BUFEND * (long) LSMALL), 0);
1511: rx = read(BUFILE,(char *)ptrs, (nlines+1)*(sizeof cpointer));
1512: if (rx ==(nlines+1)*(sizeof cpointer)) break;
1513: if (errno != 4) error (FATAL,errno,"Reading line pointers");
1514: }
1515: }
1516:
1517: bfmodes(); /* set buffer modes */
1518: move(bcurln[x],bcolumn[x]);
1519: if (bnlines[x] == 0) bufmod = 0; /* EMPTY BUFFERS CAN'T HAVE BEEN MODIFIED!!!! */
1520: if (hooks[Enter_Buffer_Hook]) hook(Enter_Buffer_Hook);
1521: }
1522:
1523: /* chgbuf changes buffers by name. If no buffer of the right name
1524: * exists, one is made */
1525:
1526:
1527: chgbuf(sp)
1528: /* Keywords: buffers commands:10 buffer-representation:20 */
1529:
1530: char *sp;
1531:
1532: {
1533: int i;
1534: i = finbuf(sp,1);
1535: if (i >= 0) {
1536: chbuf(i);
1537: return(1);
1538: }
1539: return(0);
1540: }
1541:
1542:
1543: finbuf(sp,crflg)
1544: /* Keywords: commands:20 buffers:50 files:50 reading:20 buffer-changing */
1545:
1546: char *sp;
1547: int crflg;
1548: {
1549: register int ep = -1;
1550: register int i;
1551:
1552: if (*sp == 0) {
1553: error(WARN,36);
1554: return(-1);
1555: }
1556: for (i = 0; i < NBUF; i++) {
1557: if (streq(sp,bbfname[i])) {
1558: return(i);
1559: }
1560: if ((ep < 0) && (bbfname[i] [0] == 0)) ep = i;
1561: }
1562: i = aint(sp); /* try numeric buffer name */
1563: if ((i < NBUF) && (i >= 0)) {
1564: if (bbfname[i] [0] == 0) {
1565: inibuf(i);
1566: seprintf(bbfname[i],"%d",i); /* name buffer */
1567: }
1568: return(i);
1569: }
1570: if (crflg == 0) return(-1); /* Don't create new buffer */
1571: if (crflg < 0) { /* Complain about buffer */
1572: error(WARN,39,sp);
1573: return(-1);
1574: }
1575:
1576: /* Buffer does not now exist, create it */
1577:
1578: if (ep>=0) {
1579: inibuf(ep);
1580: if (streq(sp,"...")) seprintf(bbfname[ep],"%d",ep);
1581: else strcpy(bbfname[ep],sp);
1582: return(ep);
1583: } else {
1584: error(WARN,37,NBUF);
1585: return(-1);
1586: }
1587: }
1588:
1589: /* inibuf -- initialize buffer data */
1590:
1591: inibuf(ep)
1592: register int ep; /* buffer number */
1593: /* Keywords: buffer-representation buffers commands:10 */
1594:
1595: {
1596: bbfname[ep] [0] = 0;
1597: btmpfree[ep] = 0;
1598: bcurln[ep] = bcolumn[ep] = 0;
1599: bnlines[ep] = 0;
1600: bbfmod[ep] = 0;
1601: bfilname[ep] [0] = 0;
1602: mtime[ep] = 0;
1603: }
1604:
1605: /* edbuf is the find file command, it asks for a filename, finds a
1606: * buffer containing the file if it exists, otherwise it makes a new buffer
1607: * to hold the file */
1608:
1609: edbuf(arg)
1610: /* Keywords: commands buffers buffer-changing reading:10 files dired:20 */
1611:
1612: int arg;
1613: {
1614: register int i;
1615: int retv;
1616: int exists;
1617: char *sp;
1618: #ifdef DIRED
1619: char nbuf[256];
1620: #endif
1621: exists = 0;
1622: sp = expenv(getname("Filename to Find? "));
1623: if (sp == NULL) return(0);
1624: #ifdef DIRED
1625: if (*sp != '/') {
1626: catstr(nbuf,filename,sp); /* relative path */
1627: if ((nbuf[0] == '.') && (nbuf[1] == '/')) sp = nbuf+2;
1628: else sp = nbuf;
1629: }
1630: #endif
1631: for (i = 0; i < NBUF; i++) {
1632: if (streq(bfilname[i], sp)) {
1633: chbuf(i);
1634: if (arg > 1) return(readin(sp,1));
1635: return(1);
1636: }
1637: if (streq(bbfname[i], sp)) {
1638: exists = 1;
1639: }
1640: }
1641: if (exists) retv = chgbuf("...");
1642: else retv = chgbuf(sp);
1643: if (retv) retv=readin(sp,arg);
1644: return(retv);
1645: }
1646:
1647: /* cpbuf is the change buffer command, it prompts for a buffer name and
1648: * mmoves to it unless the name is '*', in which case a list of active
1649: * buffers is displayed */
1650:
1651: cpbuf(arg)
1652: /* Keywords: commands buffer-changing files:10 */
1653: int arg;
1654: {
1655: int i;
1656: i = fndbuf(arg);
1657: if (arg && (i >= 0)) chbuf(i);
1658: return(i>= 0);
1659: }
1660: buflist() /* list active buffers */
1661: /* Keywords: commands buffers user-interface informational-displays */
1662:
1663: {
1664: register int i;
1665: char c;
1666:
1667: mtop();
1668: putout("Buffers used:");
1669: putout ("");
1670: for(i = 0; i < NBUF; i++) {
1671: if (bbfname[i] [0] ) {
1672: if (i == curbf) c = '*';
1673: else c = ' ';
1674: putout ("%c (%d) %s %c %s",
1675: c,i,bbfname[i],mdchar[bbfmod[i]], bfilname[i]);
1676: }
1677: }
1678: putout (endput);
1679: return(contin());
1680: }
1681:
1682:
1683: /* fndbuf finds/creates a buffer with a given name */
1684:
1685:
1686: fndbuf(crflg)
1687: int crflg;
1688: {
1689: /* Keywords: commands:20 buffers files:20 windows:10 */
1690:
1691:
1692: register char *bn;
1693:
1694: again: bn = getname("Buffer Name? ");
1695:
1696: if (bn == NULL) return(-1);
1697: if ((*bn == 0) || (*bn == '*')) {
1698: if(buflist()) return(-1);
1699: else goto again;
1700: }
1701: return(finbuf(bn,crflg));
1702: }
1703:
1704: /* bufmove -- pipe text from one buffer to another */
1705:
1706: /* sends the text in the region to a specified buffer */
1707:
1708: bfsend(arg)
1709:
1710: int arg;
1711: {
1712: register int i;
1713: register int j;
1714:
1715: /* Keywords: commands buffers regions insertion:20 buffer-changing:50 */
1716:
1717: i = fndbuf(1);
1718: if (i >= 0) {
1719: pickup(arg); /* pick up the region */
1720: j = curbf;
1721: chbuf(i);
1722: if (i == procbuf) {
1723: bot(); /* Force insertion to the bottom */
1724: mark(curbf); /* Force mark to end of buffer */
1725: }
1726: retrv();
1727: kpop();
1728: #ifndef PC
1729: if (i == procbuf) {
1730: exch(curbf);
1731: while (curln < nlines) {
1732: sendproc (mkline(curln)+column,leng(curln)+1-column);
1733: curln++;
1734: column=0;
1735: }
1736: sendproc (mkline(curln)+column,leng(curln)-column);
1737: bot();
1738: }
1739: #endif
1740: chbuf(j); /* back to old buffer */
1741: }
1742: }
1743:
1744: /* rnbuf -- rename buffer or buffer file */
1745:
1746:
1747: rnbuf(arg)
1748:
1749: int arg;
1750: /* Keywords: commands buffers:50 files:50 naming */
1751:
1752: {
1753: register char *sp;
1754: int bn;
1755:
1756: sp = expenv(getname("New Name? "));
1757: if ((sp== NULL) || ((arg == 1) && (*sp == NULL))) return;
1758: if (arg == 1) { /* change buffer name */
1759: bn = finbuf(sp,0);
1760: if ((bn >= 0) && (bn != curbf)) {
1761: /* (allow change to current name */
1762: error(WARN,38,sp); /* Buffer name in use */
1763: return;
1764: }
1765: strcpy(bbfname[curbf],sp);
1766: } else {
1767: strcpy(bfilname[curbf],sp);
1768: mtime[curbf]=0; /* Buffer wasn't read from this file */
1769:
1770: }
1771: dispmod();
1772: }
1773:
1774: /* rmbuf prompts for a buffer name and removes the buffer */
1775:
1776:
1777: rmbuf()
1778: /* Keywords: buffers commands deletion */
1779:
1780: {
1781: register int i;
1782:
1783: if ((i = fndbuf(-1)) >= 0) {
1784: klbfr(i);
1785: return(1);
1786: }
1787: return(0);
1788: }
1789: klbfr(i)
1790:
1791: register int i;
1792: /* Keywords: commands:10 buffers buffer-representation:20 deletion unix-interface:10 shell-escape:20 */
1793:
1794: {
1795: if (i == curbf) {
1796: IGNORE(error (WARN,40));
1797: return;
1798: }
1799: #ifndef PC
1800: if (i == procbuf) flushproc();
1801: #endif
1802: if (i == windbuf()) onewind(); /* killing other window */
1803:
1804: if (btmpfile[i]) {
1805: #ifdef MINFILES
1806: rftmp(i);
1807: #else
1808: close(btmpfile[i]);
1809: #endif
1810: btmpfile[i] = 0;
1811: }
1812: inibuf(i);
1813: }
1814:
1815: /* clean up unwritten buffers. bclean checks for unwritten buffers, and
1816: * if any are found, writes them out if the user wishes */
1817:
1818: bclean()
1819: /* Keywords: dired:20 saving:70 exit-processing files:30 user-interface:10 */
1820:
1821: {
1822: register int i;
1823:
1824: bbfmod[curbf] = bufmod;
1825: bnlines[curbf] = nlines;
1826: #ifdef DIRED
1827: if (diron) fsave(0);
1828: #endif
1829: for (i = 0; i < NBUF; i++) {
1830: if ((bbfmod[i]) && (bbfname[i] [0]) &&
1831: (bnlines[i] > 1) &&
1832: (READONLY == 0) &&
1833: (streq(bbfname[i],".exec") == 0)){
1834:
1835:
1836: if (SAVEMD) {
1837: chbuf(i);
1838: fsave(0);
1839:
1840: } else {
1841: switch (gyn("buffer %s modified since last write to file %s, write?",
1842: &(bbfname[i][0]),&(bfilname[i][0]))) {
1843: case 0:
1844: break; /* no */
1845: case 1:
1846: /* yes answer */
1847: chbuf(i);
1848: if(fsave(1)<= 0) return(-1);
1849: break;
1850: case -1:
1851: default:
1852: unprompt(); /* clean up msg */
1853: return(-1);
1854: }
1855: }
1856: }
1857: }
1858: return(0);
1859: }
1860:
1861: crash(arg) /* handle crashes */
1862:
1863: int arg; /* sometimes is reason for crash */
1864: {
1865: /* Keywords: internal-errors saving unix-interface:30 files:20 */
1866: #ifndef PC
1867: register int i;
1868: register char *home;
1869: register int x = 0;
1870:
1871: signal(SIGHUP,SIG_IGN);
1872: signal(SIGINT,SIG_IGN); /* go into our shell */
1873:
1874: if (arg == SIGHUP) {
1875: no_io = 1; /* Make sure we do no I/O */
1876: close(0);
1877: close(1);
1878: close(2);
1879: open("/dev/null",2);
1880: dup(0);
1881: dup(0);
1882: }
1883: if (crashes++) eabort(0); /* one crash per customer */
1884: home = getenv("HOME");
1885:
1886: bbfmod[curbf] = bufmod;
1887:
1888: for (i = 0; i < NBUF; i++) {
1889: if ((bbfmod[i]) && (bbfname[i] [0])){
1890: seprintf(bfilname[i],"%s/emacs%d",home,i);
1891: chbuf(i);
1892: mtime[curbf] = 0; /* Don't complain about previous file! */
1893: IGNORE(fsave(0));
1894: x++; /* flag that we saved one */
1895: }
1896: }
1897: if (x) {
1898: USILENT++;
1899: infrn = -1; /* Make sure that unx doesn't ask questions */
1900: unx("echo $LOGTTY your emacs buffers are in $HOME/emacs[0-9]* | mail $LOGNAME &",0);
1901: }
1902: #endif
1903: quit();
1904: }
1905:
1906: /* collect -- garbage collection of buffer file */
1907:
1908: collect()
1909:
1910: /* Keywords: buffer-allocation buffer-representation killstack:20 */
1911: {
1912: int oldcol;
1913: int oldln;
1914: int onlns;
1915:
1916: prompt1("Garbage collecting buffer");
1917: mflush(stdout);
1918:
1919: oldln = curln;
1920: oldcol = column;
1921:
1922: top();
1923: onlns = kline = nlines;
1924: kcol = leng(kline);
1925: tkill(); /* kill all text into kill buffer */
1926:
1927: bufinit(); /* reinit buffer storage */
1928: top();
1929: retrv();
1930: if (onlns != curln) {
1931: error(WARN,75); /* buffer too large for emacs */
1932: }
1933: kpop();
1934: unpop(2); /* Ignore for undo */
1935: move(oldln,oldcol);
1936: unprompt();
1937: }
1938:
1939: /* pshchr -- push a character into the macro buffer */
1940:
1941: pshchr(ch)
1942:
1943: register int ch;
1944: /* Keywords: memory-allocation:10 macro-programming:10 paging:20 */
1945: /* Keywords: buffer-allocation:20 buffer-representation:20 */
1946: {
1947: if (macptr >= fbkno*BLEN) {
1948: if ((fbkno+2<NBLOCK) && bgrab(fbkno++,0)){
1949: /* grab another buffer */
1950: if (nxtflsh < fbkno) nxtflsh = fbkno;
1951: clptr=mkline(curln); /* Restore line pointer */
1952: } else error(FATAL,41); /* too many macros */
1953: }
1954: bbuf[0][macptr++] = ch;
1955: }
1956:
1957: pbfname() /* put buffer name in kill stack*/
1958: {
1959: /* Keywords: commands macro-programming naming buffers */
1960: stkstr(bname());
1961: }
1962: pfnname() /* put file name in kill stack */
1963: /* Keywords: commands macro-programming naming files */
1964: {
1965: stkstr(fname());
1966: }
1967:
1968: pvname(count) /* put version in kill stack */
1969: int count;
1970: {
1971: /* Keywords: commands macro-programming naming versions */
1972: if (count) stkstr(version);
1973: else stkstr(serial);
1974: }
1975:
1976: recurse(arg) /* call emacs recursively */
1977: int arg;
1978: /* Keywords: user-interface:10 macro-programming:90 key-bindings:10 mode-line:5 recursive-editing commands:50 */
1979: {
1980: long svkst[NKILLP+1]; /* kill buffer save area */
1981: int svnkp;
1982: register int i,c;
1983: char *omyname;
1984: char nmbuf[64];
1985: int eresult;
1986:
1987:
1988: if (arg == 0) {
1989: register char *map;
1990: map = getname(""); /* Termination map */
1991: pushin(NULL); /* back to the tty */
1992: while (1) {
1993: disup();
1994: c = (getchar()&0177);
1995:
1996: /* Map is a bit map of 4 bit bytes, each represented as a hex digit */
1997:
1998: i = map[c>>2];
1999: if (i>'9') i = 9+(i&017);
2000: else i = i - '0';
2001: if (8 & (i<<(c&3))) put(c);
2002: else {
2003: inpop();
2004: return(c);
2005: }
2006: }
2007: }
2008: for (i = 0; i <= NKILLP; i++) svkst[i] = kstk[i];
2009: svnkp = nkp;
2010: omyname = myname;
2011: pushin(NULL); /* back to the tty */
2012: seprintf(nmbuf,"%s*",myname);
2013: myname = nmbuf;
2014: dispmod();
2015: eresult = edit(1);
2016: myname = omyname; /* pop name */
2017: dispmod();
2018: inpop(); /* pop input */
2019: for (i = 0; i <= NKILLP; i++) kstk[i] = svkst[i];
2020: nkp = svnkp;
2021: return(eresult);
2022: }
2023:
2024: kdup(arg) /* duplicate argument */
2025:
2026: int arg; /* level to duplicate */
2027: /* Keywords: commands macro-programming killstack string-variables:20 stacking */
2028: {
2029: register long dupkp;
2030:
2031: if (arg > nkp) return(0);
2032: dupkp = kstk[nkp-arg];
2033: if (nkp == NKILLP) mvdown(); /* make room */
2034: kstk[++nkp] = dupkp;
2035: return(1);
2036: }
2037:
2038: kflush(count) /* flush kill stack */
2039:
2040: register int count;
2041: /* Keywords: commands macro-programming killstack string-variables:20 popping */
2042: {
2043: while (count--) {
2044: if (kpop() == 0) return(0);
2045: }
2046: return(1);
2047: }
2048:
2049: kexch(count) /* exchange kill stack */
2050: /* Keywords: commands macro-programming killstack string-variables:20 */
2051: {
2052: register long dupkp;
2053:
2054: if (count<(nkp+1)) {
2055: dupkp = kstk[nkp];
2056: kstk[nkp] = kstk[nkp-count];
2057: kstk[nkp-count] = dupkp;
2058: return(1);
2059: } else return(0);
2060: }
2061:
2062: /* unmod -- mark or change buffer modified flag */
2063:
2064: unmod(arg)
2065: /* Keywords: mode-line:20 buffers:80 file-modes:10 files:20 macro-programming:50 */
2066: {
2067: if (arg == 1) bufmod = 0;
2068: else if (arg > 1) bufmod = 1;
2069: dispmod();
2070: return(bufmod);
2071: }
2072:
2073: #ifdef PC
2074: #define KBDFILE "c:emk"
2075: #define KBDMODE 1
2076: #else
2077: #define KBDFILE "$HOME/.emacs_kbd"
2078: #define KBDMODE 0666
2079: #endif
2080: strtkbd()
2081: {
2082: /* Keywords: commands macro-programming:20 filenames:10 unix-interface:40 keyboard-macros */
2083: if (kbdfile) endkbd();
2084: kbdfile = creat(expenv(KBDFILE),KBDMODE);
2085: return(kbdfile);
2086: }
2087: endkbd()
2088: {
2089: /* Keywords: commands macro-programming:20 filenames:10 unix-interface:40 keyboard-macros */
2090: if (kbdfile) close(kbdfile);
2091: kbdfile=0;
2092: }
2093: exkbd(arg)
2094: register int arg;
2095: /* Keywords: commands macro-programming:20 filenames:10 unix-interface:40 keyboard-macros */
2096: {
2097: while (arg-- > 0) infile(KBDFILE);
2098: }
2099: setkey()
2100: /* Keywords: commands files file-modes:50 encryption */
2101: {
2102: #ifdef CRYPTO
2103: char *kp;
2104: kp = getname("Encryption Key? ");
2105: if (kp && *kp) {
2106: strcpy(cryptkey,kp);
2107: crypt = 1;
2108: } else crypt = 0;
2109: #else
2110: beep();
2111: #endif
2112: }
2113: #ifndef PC
2114: access(path, amode)
2115: char *path;
2116: int amode;
2117: /* Keywords: file-modes files reading:20 writing:20 unix-interface */
2118: {
2119: struct stat stb;
2120: register int uid;
2121:
2122: /*** This nonsense would not be necessary if ***/
2123: /*** the saccess in sys2.c would do the check based on ***/
2124: /*** the effective uid and gid instead of the real ones ***/
2125:
2126: if( stat(path, &stb) < 0 ) {
2127: return(-1);
2128: }
2129:
2130: if( (uid=geteuid())==0 || amode==0 ) {
2131: /*** super user or existence check only ***/
2132:
2133: return(0);
2134: }
2135:
2136: if( uid == stb.st_uid ) {
2137: /*** uid's match ***/
2138:
2139: amode <<= 6;
2140: } else {
2141: if( getegid() == stb.st_gid ) {
2142: /*** gid's match ***/
2143:
2144: amode <<= 3;
2145: }
2146: }
2147:
2148: if( (stb.st_mode&amode) == amode ) {
2149: return(0);
2150: }
2151: return(-1);
2152: }
2153:
2154: #endif PC
2155:
2156:
2157: undoit(n,doit)
2158:
2159: /* Keywords: undo insertion:50 deletion:50 killstack:20 */
2160:
2161: int n;
2162: int doit;
2163: {
2164: int unline;
2165: int uncol;
2166: long unparm;
2167: int untype;
2168:
2169:
2170: uncol = undostack[--n] & (MAXEL-1);
2171: unline = undostack[n]>>MAXELSH;
2172: move(unline,uncol);
2173: unparm = undostack[--n]>>UNDSHIFT;
2174: untype = undostack[n] & UNDMASK;
2175:
2176: switch(untype) {
2177:
2178: case UNINS:
2179: if (doit) {
2180: kline = unparm >>MAXELSH;
2181: kcol = unparm & (MAXEL-1);
2182: tkill();
2183: kpop();
2184: }
2185: break;
2186: case UNBAD: /* Multiple undo that exceeds limits */
2187:
2188: if (error(WARN,85)) return(n);
2189:
2190: case UNMUL: /* Multi-segment undo */
2191: while (unparm>0) {
2192: untype = undoit(n,doit);
2193: uncol = n-untype;
2194: if (uncol<0) uncol += NUNDO;
2195: unparm -= uncol/2;
2196: n = untype;
2197: }
2198: break;
2199: case UNDEL:
2200: if (doit) {
2201: if (nkp == NKILLP) { /* no more kill pointers available */
2202: mvdown();
2203: }
2204: nkp++;
2205: kstk[nkp] = unparm;
2206: retrv();
2207: }
2208: break;
2209: }
2210: if (n<= 0) n = NUNDO;
2211: return(n);
2212: }
2213:
2214: unadd()
2215: {
2216: /* Keywords: undo stacking */
2217:
2218: undostack[undop++] = ((long) curln) * MAXEL + column;
2219: }
2220:
2221: unins(stline,stcol)
2222:
2223: /* Keywords: undo insertion stacking */
2224:
2225: {
2226: long n;
2227: if (undop >= NUNDO) {
2228: undop = 0;
2229: unseg++;
2230: }
2231: n = ((long) stline) * MAXEL + stcol;
2232: undostack[undop++] = UNINS+ (n<<UNDSHIFT);
2233: unadd();
2234: }
2235:
2236: undel()
2237:
2238: /* Keywords: undo deletion stacking */
2239:
2240: {
2241: if (undop >= NUNDO) {
2242: undop = 0;
2243: unseg++;
2244: }
2245: undostack[undop++] = UNDEL+ (kend<<UNDSHIFT);
2246: unadd();
2247: }
2248:
2249: unstart()
2250: {
2251: return (undop+unseg*NUNDO);
2252: }
2253: unend(unp)
2254: register int unp;
2255: {
2256: int untype;
2257:
2258: unp = (undop+unseg*NUNDO)-unp;
2259: if (unp >= NUNDO/2) {
2260: untype= UNBAD;
2261: unp = NUNDO/2-2;
2262: } else untype = UNMUL;
2263: unp = unp / 2;
2264: if (unp == 1) return; /* No point in storing extra indirection */
2265: if (undop >= NUNDO) undop = 0;
2266: undostack[undop++] = untype + (unp<<UNDSHIFT);
2267: unadd();
2268: }
2269:
2270: undo(arg)
2271:
2272: /* Keywords: commands undo */
2273:
2274: {
2275: int undp;
2276: int unp;
2277:
2278: unp = unstart(); /* Set up for undoing undo */
2279: undp = undop;
2280: while (arg--) {
2281: /* Only the last undo really undoes anything */
2282:
2283: undp = undoit(undp,(arg == 0));
2284: }
2285: unend(unp);
2286: }
2287: unpop(n)
2288: {
2289: undop -= 2*n;
2290: if (undop < 0) undop += NUNDO;
2291: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.