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