#include "sam.h"
/*
 * GROWDATASIZE must be big enough that all errors go out as Hgrowdata's,
 * so they will be scrolled into visibility in the ~~sam~~ window (yuck!).
 */
#define	GROWDATASIZE	50	/* if size is > this, send data with grow */

void	rcut(List*, Posn, Posn);
int	rterm(List*, Posn);
void	rgrow(List*, Posn, Posn);

static	Posn	growpos;
static	Posn	grown;
static	Posn	shrinkpos;
static	Posn	shrunk;

/*
 * rasp routines inform the terminal of changes to the file.
 *
 * a rasp is a list of spans within the file, and an indication
 * of whether the terminal knows about the span.
 *
 * optimize by coalescing multiple updates to the same span
 * if it is not known by the terminal.
 *
 * other possible optimizations: flush terminal's rasp by cut everything,
 * insert everything if rasp gets too large.
 */

/*
 * only called for initial load of file
 */
void
raspload(File *f)
{
	if(f->rasp == nil)
		return;
	grown = f->b.nc;
	growpos = 0;
	if(f->b.nc)
		rgrow(f->rasp, 0, f->b.nc);
	raspdone(f, 1);
}

void
raspstart(File *f)
{
	if(f->rasp == nil)
		return;
	grown = 0;
	shrunk = 0;
	noflush = 1;
}

void
raspdone(File *f, int toterm)
{
	if(f->dot.r.p1 > f->b.nc)
		f->dot.r.p1 = f->b.nc;
	if(f->dot.r.p2 > f->b.nc)
		f->dot.r.p2 = f->b.nc;
	if(f->mark.p1 > f->b.nc)
		f->mark.p1 = f->b.nc;
	if(f->mark.p2 > f->b.nc)
		f->mark.p2 = f->b.nc;
	if(f->rasp == nil)
		return;
	if(grown)
		outTsll(Hgrow, f->tag, growpos, grown);
	else if(shrunk)
		outTsll(Hcut, f->tag, shrinkpos, shrunk);
	if(toterm)
		outTs(Hcheck0, f->tag);
	outflush();
	noflush = 0;
	if(f == cmd){
		cmdpt += cmdptadv;
		cmdptadv = 0;
	}
}

void
raspdelete(File *f, uint p1, uint p2, int toterm)
{
	long n;

	n = p2 - p1;
	if(n == 0)
		return;

	if(p2 <= f->dot.r.p1){
		f->dot.r.p1 -= n;
		f->dot.r.p2 -= n;
	}
	if(p2 <= f->mark.p1){
		f->mark.p1 -= n;
		f->mark.p2 -= n;
	}

	if(f->rasp == nil)
		return;

	if(f==cmd && p1<cmdpt){
		if(p2 <= cmdpt)
			cmdpt -= n;
		else
			cmdpt = p1;
	}
	if(toterm){
		if(grown){
			outTsll(Hgrow, f->tag, growpos, grown);
			grown = 0;
		}else if(shrunk && shrinkpos!=p1 && shrinkpos!=p2){
			outTsll(Hcut, f->tag, shrinkpos, shrunk);
			shrunk = 0;
		}
		if(!shrunk || shrinkpos==p2)
			shrinkpos = p1;
		shrunk += n;
	}
	rcut(f->rasp, p1, p2);
}

void
raspinsert(File *f, uint p1, Rune *buf, uint n, int toterm)
{
	Range r;

	if(n == 0)
		return;

	if(p1 < f->dot.r.p1){
		f->dot.r.p1 += n;
		f->dot.r.p2 += n;
	}
	if(p1 < f->mark.p1){
		f->mark.p1 += n;
		f->mark.p2 += n;
	}


	if(f->rasp == nil)
		return;
	if(f==cmd && p1<cmdpt)
		cmdpt += n;
	if(toterm){
		if(shrunk){
			outTsll(Hcut, f->tag, shrinkpos, shrunk);
			shrunk = 0;
		}
		if(n>GROWDATASIZE || !rterm(f->rasp, p1)){
			rgrow(f->rasp, p1, n);
			if(grown && growpos+grown!=p1 && growpos!=p1){
				outTsll(Hgrow, f->tag, growpos, grown);
				grown = 0;
			}
			if(!grown)
				growpos = p1;
			grown += n;
		}else{
			if(grown){
				outTsll(Hgrow, f->tag, growpos, grown);
				grown = 0;
			}
			rgrow(f->rasp, p1, n);
			r = rdata(f->rasp, p1, n);
			if(r.p1!=p1 || r.p2!=p1+n)
				panic("rdata in toterminal");
			outTsllS(Hgrowdata, f->tag, p1, n, tmprstr(buf, n));
		}
	}else{
		rgrow(f->rasp, p1, n);
		r = rdata(f->rasp, p1, n);
		if(r.p1!=p1 || r.p2!=p1+n)
			panic("rdata in toterminal");
	}
}

#define	M	0x80000000L
#define	P(i)	r->longptr[i]
#define	T(i)	(P(i)&M)	/* in terminal */
#define	L(i)	(P(i)&~M)	/* length of this piece */

void
rcut(List *r, Posn p1, Posn p2)
{
	Posn p, x;
	int i;

	if(p1 == p2)
		panic("rcut 0");
	for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
		;
	if(i == r->nused)
		panic("rcut 1");
	if(p < p1){	/* chop this piece */
		if(p+L(i) < p2){
			x = p1-p;
			p += L(i);
		}else{
			x = L(i)-(p2-p1);
			p = p2;
		}
		if(T(i))
			P(i) = x|M;
		else
			P(i) = x;
		i++;
	}
	while(i<r->nused && p+L(i)<=p2){
		p += L(i);
		dellist(r, i);
	}
	if(p < p2){
		if(i == r->nused)
			panic("rcut 2");
		x = L(i)-(p2-p);
		if(T(i))
			P(i) = x|M;
		else
			P(i) = x;
	}
	/* can we merge i and i-1 ? */
	if(i>0 && i<r->nused && T(i-1)==T(i)){
		x = L(i-1)+L(i);
		dellist(r, i--);
		if(T(i))
			P(i)=x|M;
		else
			P(i)=x;
	}
}

void
rgrow(List *r, Posn p1, Posn n)
{
	Posn p;
	int i;

	if(n == 0)
		panic("rgrow 0");
	for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
		;
	if(i == r->nused){	/* stick on end of file */
		if(p!=p1)
			panic("rgrow 1");
		if(i>0 && !T(i-1))
			P(i-1)+=n;
		else
			inslist(r, i, n);
	}else if(!T(i))		/* goes in this empty piece */
		P(i)+=n;
	else if(p==p1 && i>0 && !T(i-1))	/* special case; simplifies life */
		P(i-1)+=n;
	else if(p==p1)
		inslist(r, i, n);
	else{			/* must break piece in terminal */
		inslist(r, i+1, (L(i)-(p1-p))|M);
		inslist(r, i+1, n);
		P(i) = (p1-p)|M;
	}
}

int
rterm(List *r, Posn p1)
{
	Posn p;
	int i;

	for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++))
		;
	if(i==r->nused && (i==0 || !T(i-1)))
		return 0;
	return T(i);
}

Range
rdata(List *r, Posn p1, Posn n)
{
	Posn p;
	int i;
	Range rg;

	if(n==0)
		panic("rdata 0");
	for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++))
		;
	if(i==r->nused)
		panic("rdata 1");
	if(T(i)){
		n-=L(i)-(p1-p);
		if(n<=0){
			rg.p1 = rg.p2 = p1;
			return rg;
		}
		p+=L(i++);
		p1 = p;
	}
	if(T(i) || i==r->nused)
		panic("rdata 2");
	if(p+L(i)<p1+n)
		n = L(i)-(p1-p);
	rg.p1 = p1;
	rg.p2 = p1+n;
	if(p!=p1){
		inslist(r, i+1, L(i)-(p1-p));
		P(i)=p1-p;
		i++;
	}
	if(L(i)!=n){
		inslist(r, i+1, L(i)-n);
		P(i)=n;
	}
	P(i)|=M;
	/* now i is set; can we merge? */
	if(i<r->nused-1 && T(i+1)){
		P(i)=(n+=L(i+1))|M;
		dellist(r, i+1);
	}
	if(i>0 && T(i-1)){
		P(i)=(n+L(i-1))|M;
		dellist(r, i-1);
	}
	return rg;
}
