|
|
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.