Exemple #1
0
Fichier : buffer.c Projet : 4ad/sam
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;
}
Exemple #2
0
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;
	}
}
Exemple #3
0
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;
    }
}
Exemple #4
0
Fichier : buffer.c Projet : 4ad/sam
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;
}
Exemple #5
0
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);
}