void Binsert(Buffer *b, String *s, Posn p0) { if(b->c2>b->disc->nrunes || b->c1>b->disc->nrunes) panic("binsert cache"); if(p0<0) panic("Binsert p0<0"); if(s->n == 0) return; if(incache(b, p0, p0) && b->cache.n+s->n<=STRSIZE){ Strinsert(&b->cache, s, p0-b->c1); b->dirty = TRUE; if(b->cache.n > BLOCKSIZE*2){ b->nrunes += s->n; Bflush(b); /* try to leave some cache around p0 */ if(p0 >= b->c1+BLOCKSIZE){ /* first BLOCKSIZE can go */ Strdelete(&b->cache, 0, BLOCKSIZE); b->c1 += BLOCKSIZE; }else if(p0 <= b->c2-BLOCKSIZE){ /* last BLOCKSIZE can go */ b->cache.n -= BLOCKSIZE; b->c2 -= BLOCKSIZE; }else{ /* too hard; negate the cache and pick up next time */ Strzero(&b->cache); b->c1 = b->c2 = 0; } return; } }else{ Bflush(b); if(s->n >= BLOCKSIZE/2){ b->cache.n = 0; b->c1 = b->c2 = 0; Dinsert(b->disc, s->s, s->n, p0); }else{ int m; Posn minp; if(b->nrunes-p0 > BLOCKSIZE/2) m = BLOCKSIZE/2; else m = b->nrunes-p0; minp = p0-BLOCKSIZE/2; if(minp < 0) minp = 0; m += p0-minp; Strinsure(&b->cache, m); if(Dread(b->disc, b->cache.s, m, minp)!=m) panic("Bread"); b->cache.n = m; b->c1 = minp; b->c2 = minp+m; Strinsert(&b->cache, s, p0-b->c1); b->dirty = TRUE; } } b->nrunes += s->n; }
void setgenstr(File *f, Posn p0, Posn p1) { if(p0 != p1){ if(p1-p0 >= TBLOCKSIZE) error(Etoolong); Strinsure(&genstr, p1-p0); bufread(&f->b, p0, genbuf, p1-p0); memmove(genstr.s, genbuf, RUNESIZE*(p1-p0)); genstr.n = p1-p0; }else{ if(snarfbuf.nc == 0) error(Eempty); if(snarfbuf.nc > TBLOCKSIZE) error(Etoolong); bufread(&snarfbuf, (Posn)0, genbuf, snarfbuf.nc); Strinsure(&genstr, snarfbuf.nc); memmove(genstr.s, genbuf, RUNESIZE*snarfbuf.nc); genstr.n = snarfbuf.nc; } }
void setgenstr(File *f, Posn p0, Posn p1) { if(p0 != p1) { if(p1-p0 >= TBLOCKSIZE) error(Etoolong); Strinsure(&genstr, p1-p0); Fchars(f, genbuf, p0, p1); memmove(genstr.s, genbuf, RUNESIZE*(p1-p0)); genstr.n = p1-p0; } else { if(snarfbuf->nrunes == 0) error(Eempty); if(snarfbuf->nrunes > TBLOCKSIZE) error(Etoolong); Bread(snarfbuf, genbuf, snarfbuf->nrunes, (Posn)0); Strinsure(&genstr, snarfbuf->nrunes); memmove(genstr.s, genbuf, RUNESIZE*snarfbuf->nrunes); genstr.n = snarfbuf->nrunes; } }
int Bread(Buffer *b, Rune *addr, int n, Posn p0) { int m; if(b->c2>b->disc->nrunes || b->c1>b->disc->nrunes) panic("bread cache"); if(p0 < 0) panic("Bread p0<0"); if(p0+n > b->nrunes){ n = b->nrunes-p0; if(n < 0) panic("Bread<0"); } if(!incache(b, p0, p0+n)){ Bflush(b); if(n>=BLOCKSIZE/2) return Dread(b->disc, addr, n, p0); else{ Posn minp; if(b->nrunes-p0>BLOCKSIZE/2) m = BLOCKSIZE/2; else m = b->nrunes-p0; if(m<n) m = n; minp = p0-BLOCKSIZE/2; if(minp<0) minp = 0; m += p0-minp; Strinsure(&b->cache, m); if(Dread(b->disc, b->cache.s, m, minp)!=m) panic("Bread"); b->cache.n = m; b->c1 = minp; b->c2 = minp+m; b->dirty = FALSE; } } memmove(addr, &b->cache.s[p0-b->c1], n*RUNESIZE); return n; }
void fileundo(File *f, int isundo, int canredo, uint *q0p, uint *q1p, int flag) { Undo u; Rune *buf; uint i, n, up; uint stop; Buffer *delta, *epsilon; if(isundo){ /* undo; reverse delta onto epsilon, seq decreases */ delta = &f->delta; epsilon = &f->epsilon; stop = f->seq; }else{ /* redo; reverse epsilon onto delta, seq increases */ delta = &f->epsilon; epsilon = &f->delta; stop = 0; /* don't know yet */ } raspstart(f); while(delta->nc > 0){ /* rasp and buffer are in sync; sync with wire if needed */ if(needoutflush()) raspflush(f); up = delta->nc-Undosize; bufread(delta, up, (Rune*)&u, Undosize); if(isundo){ if(u.seq < stop){ f->seq = u.seq; raspdone(f, flag); return; } }else{ if(stop == 0) stop = u.seq; if(u.seq > stop){ raspdone(f, flag); return; } } switch(u.type){ default: panic("undo unknown u.type"); break; case Delete: f->seq = u.seq; if(canredo) fileundelete(f, epsilon, u.p0, u.p0+u.n); f->mod = u.mod; bufdelete(&f->Buffer, u.p0, u.p0+u.n); raspdelete(f, u.p0, u.p0+u.n, flag); *q0p = u.p0; *q1p = u.p0; break; case Insert: f->seq = u.seq; if(canredo) fileuninsert(f, epsilon, u.p0, u.n); f->mod = u.mod; up -= u.n; buf = fbufalloc(); for(i=0; i<u.n; i+=n){ n = u.n - i; if(n > RBUFSIZE) n = RBUFSIZE; bufread(delta, up+i, buf, n); bufinsert(&f->Buffer, u.p0+i, buf, n); raspinsert(f, u.p0+i, buf, n, flag); } fbuffree(buf); *q0p = u.p0; *q1p = u.p0+u.n; break; case Filename: f->seq = u.seq; if(canredo) fileunsetname(f, epsilon); f->mod = u.mod; up -= u.n; Strinsure(&f->name, u.n+1); bufread(delta, up, f->name.s, u.n); f->name.s[u.n] = 0; f->name.n = u.n; fixname(&f->name); sortname(f); break; case Dot: f->seq = u.seq; if(canredo) fileunsetdot(f, epsilon, f->dot.r); f->mod = u.mod; f->dot.r.p1 = u.p0; f->dot.r.p2 = u.p0 + u.n; break; case Mark: f->seq = u.seq; if(canredo) fileunsetmark(f, epsilon, f->mark); f->mod = u.mod; f->mark.p1 = u.p0; f->mark.p2 = u.p0 + u.n; break; } bufdelete(delta, up, delta->nc); } if(isundo) f->seq = 0; raspdone(f, flag); }