Annotation of researchv9/cmd/emacs/emacs_buf.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.