xref: /plan9/sys/src/cmd/sam/rasp.c (revision 54d47c7104a034cf0bbe333e13d0054c9c216c87)
13e12c5d1SDavid du Colombier #include "sam.h"
23e12c5d1SDavid du Colombier /*
33e12c5d1SDavid du Colombier  * GROWDATASIZE must be big enough that all errors go out as Hgrowdata's,
43e12c5d1SDavid du Colombier  * so they will be scrolled into visibility in the ~~sam~~ window (yuck!).
53e12c5d1SDavid du Colombier  */
63e12c5d1SDavid du Colombier #define	GROWDATASIZE	50	/* if size is > this, send data with grow */
73e12c5d1SDavid du Colombier 
83e12c5d1SDavid du Colombier void	rcut(List*, Posn, Posn);
93e12c5d1SDavid du Colombier int	rterm(List*, Posn);
103e12c5d1SDavid du Colombier void	rgrow(List*, Posn, Posn);
113e12c5d1SDavid du Colombier 
127dd7cddfSDavid du Colombier static	Posn	growpos;
137dd7cddfSDavid du Colombier static	Posn	grown;
147dd7cddfSDavid du Colombier static	Posn	shrinkpos;
157dd7cddfSDavid du Colombier static	Posn	shrunk;
167dd7cddfSDavid du Colombier 
177dd7cddfSDavid du Colombier /*
187dd7cddfSDavid du Colombier  * rasp routines inform the terminal of changes to the file.
197dd7cddfSDavid du Colombier  *
207dd7cddfSDavid du Colombier  * a rasp is a list of spans within the file, and an indication
217dd7cddfSDavid du Colombier  * of whether the terminal knows about the span.
227dd7cddfSDavid du Colombier  *
237dd7cddfSDavid du Colombier  * optimize by coalescing multiple updates to the same span
247dd7cddfSDavid du Colombier  * if it is not known by the terminal.
257dd7cddfSDavid du Colombier  *
267dd7cddfSDavid du Colombier  * other possible optimizations: flush terminal's rasp by cut everything,
277dd7cddfSDavid du Colombier  * insert everything if rasp gets too large.
287dd7cddfSDavid du Colombier  */
297dd7cddfSDavid du Colombier 
307dd7cddfSDavid du Colombier /*
317dd7cddfSDavid du Colombier  * only called for initial load of file
327dd7cddfSDavid du Colombier  */
333e12c5d1SDavid du Colombier void
raspload(File * f)347dd7cddfSDavid du Colombier raspload(File *f)
353e12c5d1SDavid du Colombier {
367dd7cddfSDavid du Colombier 	if(f->rasp == nil)
373e12c5d1SDavid du Colombier 		return;
387dd7cddfSDavid du Colombier 	grown = f->nc;
397dd7cddfSDavid du Colombier 	growpos = 0;
407dd7cddfSDavid du Colombier 	if(f->nc)
417dd7cddfSDavid du Colombier 		rgrow(f->rasp, 0, f->nc);
427dd7cddfSDavid du Colombier 	raspdone(f, 1);
437dd7cddfSDavid du Colombier }
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier void
raspstart(File * f)467dd7cddfSDavid du Colombier raspstart(File *f)
477dd7cddfSDavid du Colombier {
487dd7cddfSDavid du Colombier 	if(f->rasp == nil)
497dd7cddfSDavid du Colombier 		return;
503e12c5d1SDavid du Colombier 	grown = 0;
517dd7cddfSDavid du Colombier 	shrunk = 0;
52*54d47c71SDavid du Colombier 	outbuffered = 1;
537dd7cddfSDavid du Colombier }
543e12c5d1SDavid du Colombier 
557dd7cddfSDavid du Colombier void
raspdone(File * f,int toterm)567dd7cddfSDavid du Colombier raspdone(File *f, int toterm)
577dd7cddfSDavid du Colombier {
587dd7cddfSDavid du Colombier 	if(f->dot.r.p1 > f->nc)
597dd7cddfSDavid du Colombier 		f->dot.r.p1 = f->nc;
607dd7cddfSDavid du Colombier 	if(f->dot.r.p2 > f->nc)
617dd7cddfSDavid du Colombier 		f->dot.r.p2 = f->nc;
627dd7cddfSDavid du Colombier 	if(f->mark.p1 > f->nc)
637dd7cddfSDavid du Colombier 		f->mark.p1 = f->nc;
647dd7cddfSDavid du Colombier 	if(f->mark.p2 > f->nc)
657dd7cddfSDavid du Colombier 		f->mark.p2 = f->nc;
667dd7cddfSDavid du Colombier 	if(f->rasp == nil)
677dd7cddfSDavid du Colombier 		return;
683e12c5d1SDavid du Colombier 	if(grown)
693e12c5d1SDavid du Colombier 		outTsll(Hgrow, f->tag, growpos, grown);
707dd7cddfSDavid du Colombier 	else if(shrunk)
717dd7cddfSDavid du Colombier 		outTsll(Hcut, f->tag, shrinkpos, shrunk);
723e12c5d1SDavid du Colombier 	if(toterm)
733e12c5d1SDavid du Colombier 		outTs(Hcheck0, f->tag);
743e12c5d1SDavid du Colombier 	outflush();
75*54d47c71SDavid du Colombier 	outbuffered = 0;
763e12c5d1SDavid du Colombier 	if(f == cmd){
777dd7cddfSDavid du Colombier 		cmdpt += cmdptadv;
783e12c5d1SDavid du Colombier 		cmdptadv = 0;
793e12c5d1SDavid du Colombier 	}
803e12c5d1SDavid du Colombier }
813e12c5d1SDavid du Colombier 
827dd7cddfSDavid du Colombier void
raspflush(File * f)83*54d47c71SDavid du Colombier raspflush(File *f)
84*54d47c71SDavid du Colombier {
85*54d47c71SDavid du Colombier 	if(grown){
86*54d47c71SDavid du Colombier 		outTsll(Hgrow, f->tag, growpos, grown);
87*54d47c71SDavid du Colombier 		grown = 0;
88*54d47c71SDavid du Colombier 	}
89*54d47c71SDavid du Colombier 	else if(shrunk){
90*54d47c71SDavid du Colombier 		outTsll(Hcut, f->tag, shrinkpos, shrunk);
91*54d47c71SDavid du Colombier 		shrunk = 0;
92*54d47c71SDavid du Colombier 	}
93*54d47c71SDavid du Colombier 	outflush();
94*54d47c71SDavid du Colombier }
95*54d47c71SDavid du Colombier 
96*54d47c71SDavid du Colombier void
raspdelete(File * f,uint p1,uint p2,int toterm)977dd7cddfSDavid du Colombier raspdelete(File *f, uint p1, uint p2, int toterm)
987dd7cddfSDavid du Colombier {
997dd7cddfSDavid du Colombier 	long n;
1007dd7cddfSDavid du Colombier 
1017dd7cddfSDavid du Colombier 	n = p2 - p1;
1027dd7cddfSDavid du Colombier 	if(n == 0)
1037dd7cddfSDavid du Colombier 		return;
1047dd7cddfSDavid du Colombier 
1057dd7cddfSDavid du Colombier 	if(p2 <= f->dot.r.p1){
1067dd7cddfSDavid du Colombier 		f->dot.r.p1 -= n;
1077dd7cddfSDavid du Colombier 		f->dot.r.p2 -= n;
1087dd7cddfSDavid du Colombier 	}
1097dd7cddfSDavid du Colombier 	if(p2 <= f->mark.p1){
1107dd7cddfSDavid du Colombier 		f->mark.p1 -= n;
1117dd7cddfSDavid du Colombier 		f->mark.p2 -= n;
1127dd7cddfSDavid du Colombier 	}
1137dd7cddfSDavid du Colombier 
1147dd7cddfSDavid du Colombier 	if(f->rasp == nil)
1157dd7cddfSDavid du Colombier 		return;
1167dd7cddfSDavid du Colombier 
1177dd7cddfSDavid du Colombier 	if(f==cmd && p1<cmdpt){
1187dd7cddfSDavid du Colombier 		if(p2 <= cmdpt)
1197dd7cddfSDavid du Colombier 			cmdpt -= n;
1207dd7cddfSDavid du Colombier 		else
1217dd7cddfSDavid du Colombier 			cmdpt = p1;
1227dd7cddfSDavid du Colombier 	}
1237dd7cddfSDavid du Colombier 	if(toterm){
1247dd7cddfSDavid du Colombier 		if(grown){
1257dd7cddfSDavid du Colombier 			outTsll(Hgrow, f->tag, growpos, grown);
1267dd7cddfSDavid du Colombier 			grown = 0;
1277dd7cddfSDavid du Colombier 		}else if(shrunk && shrinkpos!=p1 && shrinkpos!=p2){
1287dd7cddfSDavid du Colombier 			outTsll(Hcut, f->tag, shrinkpos, shrunk);
1297dd7cddfSDavid du Colombier 			shrunk = 0;
1307dd7cddfSDavid du Colombier 		}
1317dd7cddfSDavid du Colombier 		if(!shrunk || shrinkpos==p2)
1327dd7cddfSDavid du Colombier 			shrinkpos = p1;
1337dd7cddfSDavid du Colombier 		shrunk += n;
1347dd7cddfSDavid du Colombier 	}
1357dd7cddfSDavid du Colombier 	rcut(f->rasp, p1, p2);
1367dd7cddfSDavid du Colombier }
1377dd7cddfSDavid du Colombier 
1387dd7cddfSDavid du Colombier void
raspinsert(File * f,uint p1,Rune * buf,uint n,int toterm)1397dd7cddfSDavid du Colombier raspinsert(File *f, uint p1, Rune *buf, uint n, int toterm)
1407dd7cddfSDavid du Colombier {
1417dd7cddfSDavid du Colombier 	Range r;
1427dd7cddfSDavid du Colombier 
1437dd7cddfSDavid du Colombier 	if(n == 0)
1447dd7cddfSDavid du Colombier 		return;
1457dd7cddfSDavid du Colombier 
1467dd7cddfSDavid du Colombier 	if(p1 < f->dot.r.p1){
1477dd7cddfSDavid du Colombier 		f->dot.r.p1 += n;
1487dd7cddfSDavid du Colombier 		f->dot.r.p2 += n;
1497dd7cddfSDavid du Colombier 	}
1507dd7cddfSDavid du Colombier 	if(p1 < f->mark.p1){
1517dd7cddfSDavid du Colombier 		f->mark.p1 += n;
1527dd7cddfSDavid du Colombier 		f->mark.p2 += n;
1537dd7cddfSDavid du Colombier 	}
1547dd7cddfSDavid du Colombier 
1557dd7cddfSDavid du Colombier 
1567dd7cddfSDavid du Colombier 	if(f->rasp == nil)
1577dd7cddfSDavid du Colombier 		return;
1587dd7cddfSDavid du Colombier 	if(f==cmd && p1<cmdpt)
1597dd7cddfSDavid du Colombier 		cmdpt += n;
1607dd7cddfSDavid du Colombier 	if(toterm){
1617dd7cddfSDavid du Colombier 		if(shrunk){
1627dd7cddfSDavid du Colombier 			outTsll(Hcut, f->tag, shrinkpos, shrunk);
1637dd7cddfSDavid du Colombier 			shrunk = 0;
1647dd7cddfSDavid du Colombier 		}
1657dd7cddfSDavid du Colombier 		if(n>GROWDATASIZE || !rterm(f->rasp, p1)){
1667dd7cddfSDavid du Colombier 			rgrow(f->rasp, p1, n);
1677dd7cddfSDavid du Colombier 			if(grown && growpos+grown!=p1 && growpos!=p1){
1687dd7cddfSDavid du Colombier 				outTsll(Hgrow, f->tag, growpos, grown);
1697dd7cddfSDavid du Colombier 				grown = 0;
1707dd7cddfSDavid du Colombier 			}
1717dd7cddfSDavid du Colombier 			if(!grown)
1727dd7cddfSDavid du Colombier 				growpos = p1;
1737dd7cddfSDavid du Colombier 			grown += n;
1747dd7cddfSDavid du Colombier 		}else{
1757dd7cddfSDavid du Colombier 			if(grown){
1767dd7cddfSDavid du Colombier 				outTsll(Hgrow, f->tag, growpos, grown);
1777dd7cddfSDavid du Colombier 				grown = 0;
1787dd7cddfSDavid du Colombier 			}
1797dd7cddfSDavid du Colombier 			rgrow(f->rasp, p1, n);
1807dd7cddfSDavid du Colombier 			r = rdata(f->rasp, p1, n);
1817dd7cddfSDavid du Colombier 			if(r.p1!=p1 || r.p2!=p1+n)
1827dd7cddfSDavid du Colombier 				panic("rdata in toterminal");
1837dd7cddfSDavid du Colombier 			outTsllS(Hgrowdata, f->tag, p1, n, tmprstr(buf, n));
1847dd7cddfSDavid du Colombier 		}
1857dd7cddfSDavid du Colombier 	}else{
1867dd7cddfSDavid du Colombier 		rgrow(f->rasp, p1, n);
1877dd7cddfSDavid du Colombier 		r = rdata(f->rasp, p1, n);
1887dd7cddfSDavid du Colombier 		if(r.p1!=p1 || r.p2!=p1+n)
1897dd7cddfSDavid du Colombier 			panic("rdata in toterminal");
1907dd7cddfSDavid du Colombier 	}
1917dd7cddfSDavid du Colombier }
1927dd7cddfSDavid du Colombier 
1933e12c5d1SDavid du Colombier #define	M	0x80000000L
19473e742d7SDavid du Colombier #define	P(i)	r->posnptr[i]
1953e12c5d1SDavid du Colombier #define	T(i)	(P(i)&M)	/* in terminal */
1963e12c5d1SDavid du Colombier #define	L(i)	(P(i)&~M)	/* length of this piece */
1973e12c5d1SDavid du Colombier 
1983e12c5d1SDavid du Colombier void
rcut(List * r,Posn p1,Posn p2)1993e12c5d1SDavid du Colombier rcut(List *r, Posn p1, Posn p2)
2003e12c5d1SDavid du Colombier {
2013e12c5d1SDavid du Colombier 	Posn p, x;
2023e12c5d1SDavid du Colombier 	int i;
2033e12c5d1SDavid du Colombier 
2043e12c5d1SDavid du Colombier 	if(p1 == p2)
2053e12c5d1SDavid du Colombier 		panic("rcut 0");
2063e12c5d1SDavid du Colombier 	for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
2073e12c5d1SDavid du Colombier 		;
2083e12c5d1SDavid du Colombier 	if(i == r->nused)
2093e12c5d1SDavid du Colombier 		panic("rcut 1");
2103e12c5d1SDavid du Colombier 	if(p < p1){	/* chop this piece */
2113e12c5d1SDavid du Colombier 		if(p+L(i) < p2){
2123e12c5d1SDavid du Colombier 			x = p1-p;
2133e12c5d1SDavid du Colombier 			p += L(i);
2143e12c5d1SDavid du Colombier 		}else{
2153e12c5d1SDavid du Colombier 			x = L(i)-(p2-p1);
2163e12c5d1SDavid du Colombier 			p = p2;
2173e12c5d1SDavid du Colombier 		}
2183e12c5d1SDavid du Colombier 		if(T(i))
2193e12c5d1SDavid du Colombier 			P(i) = x|M;
2203e12c5d1SDavid du Colombier 		else
2213e12c5d1SDavid du Colombier 			P(i) = x;
2223e12c5d1SDavid du Colombier 		i++;
2233e12c5d1SDavid du Colombier 	}
2243e12c5d1SDavid du Colombier 	while(i<r->nused && p+L(i)<=p2){
2253e12c5d1SDavid du Colombier 		p += L(i);
2263e12c5d1SDavid du Colombier 		dellist(r, i);
2273e12c5d1SDavid du Colombier 	}
2283e12c5d1SDavid du Colombier 	if(p < p2){
2293e12c5d1SDavid du Colombier 		if(i == r->nused)
2303e12c5d1SDavid du Colombier 			panic("rcut 2");
2313e12c5d1SDavid du Colombier 		x = L(i)-(p2-p);
2323e12c5d1SDavid du Colombier 		if(T(i))
2333e12c5d1SDavid du Colombier 			P(i) = x|M;
2343e12c5d1SDavid du Colombier 		else
2353e12c5d1SDavid du Colombier 			P(i) = x;
2363e12c5d1SDavid du Colombier 	}
2373e12c5d1SDavid du Colombier 	/* can we merge i and i-1 ? */
2383e12c5d1SDavid du Colombier 	if(i>0 && i<r->nused && T(i-1)==T(i)){
2393e12c5d1SDavid du Colombier 		x = L(i-1)+L(i);
2403e12c5d1SDavid du Colombier 		dellist(r, i--);
2413e12c5d1SDavid du Colombier 		if(T(i))
2423e12c5d1SDavid du Colombier 			P(i)=x|M;
2433e12c5d1SDavid du Colombier 		else
2443e12c5d1SDavid du Colombier 			P(i)=x;
2453e12c5d1SDavid du Colombier 	}
2463e12c5d1SDavid du Colombier }
2473e12c5d1SDavid du Colombier 
2483e12c5d1SDavid du Colombier void
rgrow(List * r,Posn p1,Posn n)2493e12c5d1SDavid du Colombier rgrow(List *r, Posn p1, Posn n)
2503e12c5d1SDavid du Colombier {
2513e12c5d1SDavid du Colombier 	Posn p;
2523e12c5d1SDavid du Colombier 	int i;
2533e12c5d1SDavid du Colombier 
2543e12c5d1SDavid du Colombier 	if(n == 0)
2553e12c5d1SDavid du Colombier 		panic("rgrow 0");
2563e12c5d1SDavid du Colombier 	for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
2573e12c5d1SDavid du Colombier 		;
2583e12c5d1SDavid du Colombier 	if(i == r->nused){	/* stick on end of file */
2593e12c5d1SDavid du Colombier 		if(p!=p1)
2603e12c5d1SDavid du Colombier 			panic("rgrow 1");
2613e12c5d1SDavid du Colombier 		if(i>0 && !T(i-1))
2623e12c5d1SDavid du Colombier 			P(i-1)+=n;
2633e12c5d1SDavid du Colombier 		else
2643e12c5d1SDavid du Colombier 			inslist(r, i, n);
2653e12c5d1SDavid du Colombier 	}else if(!T(i))		/* goes in this empty piece */
2663e12c5d1SDavid du Colombier 		P(i)+=n;
2673e12c5d1SDavid du Colombier 	else if(p==p1 && i>0 && !T(i-1))	/* special case; simplifies life */
2683e12c5d1SDavid du Colombier 		P(i-1)+=n;
2693e12c5d1SDavid du Colombier 	else if(p==p1)
2703e12c5d1SDavid du Colombier 		inslist(r, i, n);
2713e12c5d1SDavid du Colombier 	else{			/* must break piece in terminal */
2723e12c5d1SDavid du Colombier 		inslist(r, i+1, (L(i)-(p1-p))|M);
2733e12c5d1SDavid du Colombier 		inslist(r, i+1, n);
2743e12c5d1SDavid du Colombier 		P(i) = (p1-p)|M;
2753e12c5d1SDavid du Colombier 	}
2763e12c5d1SDavid du Colombier }
2773e12c5d1SDavid du Colombier 
2783e12c5d1SDavid du Colombier int
rterm(List * r,Posn p1)2793e12c5d1SDavid du Colombier rterm(List *r, Posn p1)
2803e12c5d1SDavid du Colombier {
2813e12c5d1SDavid du Colombier 	Posn p;
2823e12c5d1SDavid du Colombier 	int i;
2833e12c5d1SDavid du Colombier 
2843e12c5d1SDavid du Colombier 	for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++))
2853e12c5d1SDavid du Colombier 		;
2863e12c5d1SDavid du Colombier 	if(i==r->nused && (i==0 || !T(i-1)))
2873e12c5d1SDavid du Colombier 		return 0;
2883e12c5d1SDavid du Colombier 	return T(i);
2893e12c5d1SDavid du Colombier }
2903e12c5d1SDavid du Colombier 
2913e12c5d1SDavid du Colombier Range
rdata(List * r,Posn p1,Posn n)2923e12c5d1SDavid du Colombier rdata(List *r, Posn p1, Posn n)
2933e12c5d1SDavid du Colombier {
2943e12c5d1SDavid du Colombier 	Posn p;
2953e12c5d1SDavid du Colombier 	int i;
2963e12c5d1SDavid du Colombier 	Range rg;
2973e12c5d1SDavid du Colombier 
2983e12c5d1SDavid du Colombier 	if(n==0)
2993e12c5d1SDavid du Colombier 		panic("rdata 0");
3003e12c5d1SDavid du Colombier 	for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++))
3013e12c5d1SDavid du Colombier 		;
3023e12c5d1SDavid du Colombier 	if(i==r->nused)
3033e12c5d1SDavid du Colombier 		panic("rdata 1");
3043e12c5d1SDavid du Colombier 	if(T(i)){
3053e12c5d1SDavid du Colombier 		n-=L(i)-(p1-p);
3063e12c5d1SDavid du Colombier 		if(n<=0){
3073e12c5d1SDavid du Colombier 			rg.p1 = rg.p2 = p1;
3083e12c5d1SDavid du Colombier 			return rg;
3093e12c5d1SDavid du Colombier 		}
3103e12c5d1SDavid du Colombier 		p+=L(i++);
3113e12c5d1SDavid du Colombier 		p1 = p;
3123e12c5d1SDavid du Colombier 	}
3133e12c5d1SDavid du Colombier 	if(T(i) || i==r->nused)
3143e12c5d1SDavid du Colombier 		panic("rdata 2");
3153e12c5d1SDavid du Colombier 	if(p+L(i)<p1+n)
3163e12c5d1SDavid du Colombier 		n = L(i)-(p1-p);
3173e12c5d1SDavid du Colombier 	rg.p1 = p1;
3183e12c5d1SDavid du Colombier 	rg.p2 = p1+n;
3193e12c5d1SDavid du Colombier 	if(p!=p1){
3203e12c5d1SDavid du Colombier 		inslist(r, i+1, L(i)-(p1-p));
3213e12c5d1SDavid du Colombier 		P(i)=p1-p;
3223e12c5d1SDavid du Colombier 		i++;
3233e12c5d1SDavid du Colombier 	}
3243e12c5d1SDavid du Colombier 	if(L(i)!=n){
3253e12c5d1SDavid du Colombier 		inslist(r, i+1, L(i)-n);
3263e12c5d1SDavid du Colombier 		P(i)=n;
3273e12c5d1SDavid du Colombier 	}
3283e12c5d1SDavid du Colombier 	P(i)|=M;
3293e12c5d1SDavid du Colombier 	/* now i is set; can we merge? */
3303e12c5d1SDavid du Colombier 	if(i<r->nused-1 && T(i+1)){
3313e12c5d1SDavid du Colombier 		P(i)=(n+=L(i+1))|M;
3323e12c5d1SDavid du Colombier 		dellist(r, i+1);
3333e12c5d1SDavid du Colombier 	}
3343e12c5d1SDavid du Colombier 	if(i>0 && T(i-1)){
3353e12c5d1SDavid du Colombier 		P(i)=(n+L(i-1))|M;
3363e12c5d1SDavid du Colombier 		dellist(r, i-1);
3373e12c5d1SDavid du Colombier 	}
3383e12c5d1SDavid du Colombier 	return rg;
3393e12c5d1SDavid du Colombier }
340