home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1979 Regents of the University of California */
- #include "ex.h"
- #include "ex_temp.h"
- #include "ex_vis.h"
-
- /*
- * Editor temporary file routines.
- * Very similar to those of ed, except uses 2 input buffers.
- */
- #define READ 0
- #define WRITE 1
-
- char tfname[40];
- char rfname[40];
- int havetmp;
- short tfile = -1;
- short rfile = -1;
-
- fileinit()
- {
- register char *p;
- register int i, j;
- struct stat stbuf;
-
- if (tline == INCRMT * 3)
- return;
- cleanup(0);
- close(tfile);
- tline = INCRMT * 3;
- blocks[0] = 1;
- blocks[1] = 2;
- blocks[2] = -1;
- dirtcnt = 0;
- iblock = -1;
- iblock2 = -1;
- oblock = -1;
- CP(tfname, svalue(DIRECTORY));
- if (stat(tfname, &stbuf)) {
- dumbness:
- if (setexit() == 0)
- filioerr(tfname);
- else
- putNFL();
- cleanup(1);
- exit(1);
- }
- if ((stbuf.st_mode & S_IFMT) != S_IFDIR) {
- errno = ENOTDIR;
- goto dumbness;
- }
- ichanged = 0;
- ichang2 = 0;
- ignore(strcat(tfname, "/ExXXXXX"));
- for (p = strend(tfname), i = 5, j = getpid(); i > 0; i--, j /= 10)
- *--p = j % 10 | '0';
- tfile = creat(tfname, 0600);
- if (tfile < 0)
- goto dumbness;
- havetmp = 1;
- close(tfile);
- tfile = open(tfname, 2);
- if (tfile < 0)
- goto dumbness;
- /* brk((char *)fendcore); */
- }
-
- cleanup(all)
- bool all;
- {
- if (havetmp)
- unlink(tfname);
- havetmp = 0;
- if (all && rfile >= 0) {
- unlink(rfname);
- close(rfile);
- rfile = -1;
- }
- }
-
- getline(tl)
- line tl;
- {
- register char *bp, *lp;
- register int nl;
-
- lp = linebuf;
- bp = getblock(tl, READ);
- nl = nleft;
- tl &= ~OFFMSK;
- while (*lp++ = *bp++)
- if (--nl == 0) {
- bp = getblock(tl += INCRMT, READ);
- nl = nleft;
- }
- }
-
- putline()
- {
- register char *bp, *lp;
- register int nl;
- line tl;
-
- dirtcnt++;
- lp = linebuf;
- change();
- tl = tline;
- bp = getblock(tl, WRITE);
- nl = nleft;
- tl &= ~OFFMSK;
- while (*bp = *lp++) {
- if (*bp++ == '\n') {
- *--bp = 0;
- linebp = lp;
- break;
- }
- if (--nl == 0) {
- bp = getblock(tl += INCRMT, WRITE);
- nl = nleft;
- }
- }
- tl = tline;
- tline += (((lp - linebuf) + BNDRY - 1) >> SHFT) & 077776;
- return (tl);
- }
-
- int read();
- int write();
-
- char *
- getblock(atl, iof)
- line atl;
- int iof;
- {
- register int bno, off;
-
- bno = (atl >> OFFBTS) & BLKMSK;
- off = (atl << SHFT) & LBTMSK;
- if (bno >= NMBLKS)
- error(" Tmp file too large");
- nleft = BUFSIZ - off;
- if (bno == iblock) {
- ichanged |= iof;
- hitin2 = 0;
- return (ibuff + off);
- }
- if (bno == iblock2) {
- ichang2 |= iof;
- hitin2 = 1;
- return (ibuff2 + off);
- }
- if (bno == oblock)
- return (obuff + off);
- if (iof == READ) {
- if (hitin2 == 0) {
- if (ichang2)
- blkio(iblock2, ibuff2, write);
- ichang2 = 0;
- iblock2 = bno;
- blkio(bno, ibuff2, read);
- hitin2 = 1;
- return (ibuff2 + off);
- }
- hitin2 = 0;
- if (ichanged)
- blkio(iblock, ibuff, write);
- ichanged = 0;
- iblock = bno;
- blkio(bno, ibuff, read);
- return (ibuff + off);
- }
- if (oblock >= 0)
- blkio(oblock, obuff, write);
- oblock = bno;
- return (obuff + off);
- }
-
- blkio(b, buf, iofcn)
- short b;
- char *buf;
- int (*iofcn)();
- {
-
- lseek(tfile, (long) (unsigned) b * BUFSIZ, 0);
- if ((*iofcn)(tfile, buf, BUFSIZ) != BUFSIZ)
- filioerr(tfname);
- }
-
- /*
- * Synchronize the state of the temporary file in case
- * a crash occurs.
- */
- synctmp()
- {
- register int cnt;
- register line *bp, *a;
-
- if (dol == zero)
- return;
- if (ichanged)
- blkio(iblock, ibuff, write);
- ichanged = 0;
- if (ichang2)
- blkio(iblock2, ibuff2, write);
- ichang2 = 0;
- if (oblock != -1)
- blkio(oblock, obuff, write);
- time(&H.Time);
- uid = getuid();
- *zero = (line) H.Time;
- for (a = zero, bp = blocks; a <= dol; a += BUFSIZ / sizeof *a, bp++) {
- if (*bp < 0) {
- tline = (tline + OFFMSK) &~ OFFMSK;
- *bp = ((tline >> OFFBTS) & BLKMSK);
- tline += INCRMT;
- oblock = *bp + 1;
- bp[1] = -1;
- }
- lseek(tfile, (long) (unsigned) *bp * BUFSIZ, 0);
- cnt = ((dol - a) + 2) * sizeof (line);
- if (cnt > BUFSIZ)
- cnt = BUFSIZ;
- if (write(tfile, (char *) a, cnt) != cnt) {
- oops:
- *zero = 0;
- filioerr(tfname);
- }
- *zero = 0;
- }
- flines = lineDOL();
- lseek(tfile, 0l, 0);
- if (write(tfile, (char *) &H, sizeof H) != sizeof H)
- goto oops;
- }
-
- TSYNC()
- {
-
- if (dirtcnt > 12) {
- dirtcnt = 0;
- synctmp();
- }
- }
-
- /*
- * Named buffer routines.
- * These are implemented differently than the main buffer.
- * Each named buffer has a chain of blocks in the register file.
- * Each block contains roughly 508 chars of text,
- * and a previous and next block number. We also have information
- * about which blocks came from deletes of multiple partial lines,
- * e.g. deleting a sentence or a LISP object.
- *
- * We maintain a free map for the temp file. To free the blocks
- * in a register we must read the blocks to find how they are chained
- * together.
- *
- * BUG: The default savind of deleted lines in numbered
- * buffers may be rather inefficient; it hasn't been profiled.
- */
- struct strreg {
- short rg_flags;
- short rg_nleft;
- short rg_first;
- short rg_last;
- } strregs[('z'-'a'+1) + ('9'-'0'+1)], *strp;
-
- struct rbuf {
- short rb_prev;
- short rb_next;
- char rb_text[BUFSIZ - 2 * sizeof (short)];
- } *rbuf;
- short rused[32];
- short rnleft;
- short rblock;
- short rnext;
- char *rbufcp;
-
- regio(b, iofcn)
- short b;
- int (*iofcn)();
- {
-
- if (rfile == -1) {
- CP(rfname, tfname);
- *(strend(rfname) - 7) = 'R';
- rfile = creat(rfname, 0600);
- if (rfile < 0)
- oops:
- filioerr(rfname);
- close(rfile);
- rfile = open(rfname, 2);
- if (rfile < 0)
- goto oops;
- }
- lseek(rfile, (long) b * BUFSIZ, 0);
- if ((*iofcn)(rfile, rbuf, BUFSIZ) != BUFSIZ)
- goto oops;
- rblock = b;
- }
-
- REGblk()
- {
- register int i, j, m;
-
- for (i = 0; i < sizeof rused / sizeof rused[0]; i++) {
- m = rused[i] ^ 0177777;
- if (i == 0)
- m &= ~1;
- if (m != 0) {
- j = 0;
- while ((m & 1) == 0)
- j++, m >>= 1;
- rused[i] |= (1 << j);
- #ifdef RDEBUG
- printf("allocating block %d\n", i * 16 + j);
- #endif
- return (i * 16 + j);
- }
- }
- error("Out of register space (ugh)");
- /*NOTREACHED*/
- }
-
- struct strreg *
- mapreg(c)
- register int c;
- {
-
- if (isupper(c))
- c = tolower(c);
- return (isdigit(c) ? &strregs[('z'-'a'+1)+(c-'0')] : &strregs[c-'a']);
- }
-
- int shread();
-
- KILLreg(c)
- register int c;
- {
- struct rbuf arbuf;
- register struct strreg *sp;
-
- rbuf = &arbuf;
- sp = mapreg(c);
- rblock = sp->rg_first;
- sp->rg_first = sp->rg_last = 0;
- sp->rg_flags = sp->rg_nleft = 0;
- while (rblock != 0) {
- #ifdef RDEBUG
- printf("freeing block %d\n", rblock);
- #endif
- rused[rblock / 16] &= ~(1 << (rblock % 16));
- regio(rblock, shread);
- rblock = rbuf->rb_next;
- }
- }
-
- /*VARARGS*/
- shread()
- {
- struct front { short a; short b; };
-
- if (read(rfile, (char *) rbuf, sizeof (struct front)) == sizeof (struct front))
- return (sizeof (struct rbuf));
- return (0);
- }
-
- int getREG();
-
- putreg(c)
- char c;
- {
- struct rbuf arbuf;
- register line *odot = dot;
- register line *odol = dol;
- register int cnt;
-
- deletenone();
- appendnone();
- rbuf = &arbuf;
- rnleft = 0;
- rblock = 0;
- rnext = mapreg(c)->rg_first;
- if (rnext == 0) {
- if (inopen) {
- splitw++;
- vclean();
- vgoto(WECHO, 0);
- }
- vreg = -1;
- error("Nothing in register %c", c);
- }
- if (inopen && partreg(c)) {
- squish();
- addr1 = addr2 = dol;
- }
- ignore(append(getREG, addr2));
- if (inopen && partreg(c)) {
- unddol = dol;
- dol = odol;
- dot = odot;
- pragged(0);
- }
- cnt = undap2 - undap1;
- killcnt(cnt);
- notecnt = cnt;
- }
-
- partreg(c)
- char c;
- {
-
- return (mapreg(c)->rg_flags);
- }
-
- notpart(c)
- register int c;
- {
-
- if (c)
- mapreg(c)->rg_flags = 0;
- }
-
- getREG()
- {
- register char *lp = linebuf;
- register int c;
-
- for (;;) {
- if (rnleft == 0) {
- if (rnext == 0)
- return (EOF);
- regio(rnext, read);
- rnext = rbuf->rb_next;
- rbufcp = rbuf->rb_text;
- rnleft = sizeof rbuf->rb_text;
- }
- c = *rbufcp;
- if (c == 0)
- return (EOF);
- rbufcp++, --rnleft;
- if (c == '\n') {
- *lp++ = 0;
- return (0);
- }
- *lp++ = c;
- }
- }
-
- YANKreg(c)
- register int c;
- {
- struct rbuf arbuf;
- register line *addr;
- register struct strreg *sp;
-
- if (isdigit(c))
- kshift();
- if (islower(c))
- KILLreg(c);
- strp = sp = mapreg(c);
- sp->rg_flags = inopen && cursor && wcursor;
- rbuf = &arbuf;
- if (sp->rg_last) {
- regio(sp->rg_last, read);
- rnleft = sp->rg_nleft;
- rbufcp = &rbuf->rb_text[sizeof rbuf->rb_text - rnleft];
- } else {
- rblock = 0;
- rnleft = 0;
- }
- for (addr = addr1; addr <= addr2; addr++) {
- getline(*addr);
- if (sp->rg_flags) {
- if (addr == addr2)
- *wcursor = 0;
- if (addr == addr1)
- strcpy(linebuf, cursor);
- }
- YANKline();
- }
- rbflush();
- killed();
- }
-
- kshift()
- {
- register int i;
-
- KILLreg('9');
- for (i = '8'; i >= '0'; i--)
- copy(mapreg(i+1), mapreg(i), sizeof (struct strreg));
- }
-
- YANKline()
- {
- register char *lp = linebuf;
- register struct rbuf *rp = rbuf;
- register int c;
-
- do {
- c = *lp++;
- if (c == 0)
- c = '\n';
- if (rnleft == 0) {
- rp->rb_next = REGblk();
- rbflush();
- rblock = rp->rb_next;
- rp->rb_next = 0;
- rp->rb_prev = rblock;
- rnleft = sizeof rp->rb_text;
- rbufcp = rp->rb_text;
- }
- *rbufcp++ = c;
- --rnleft;
- } while (c != '\n');
- if (rnleft)
- *rbufcp = 0;
- }
-
- rbflush()
- {
- register struct strreg *sp = strp;
-
- if (rblock == 0)
- return;
- regio(rblock, write);
- if (sp->rg_first == 0)
- sp->rg_first = rblock;
- sp->rg_last = rblock;
- sp->rg_nleft = rnleft;
- }
-