]> git.lizzy.rs Git - plan9front.git/blob - sys/src/cmd/sam/rasp.c
Import sources from 2011-03-30 iso image
[plan9front.git] / sys / src / cmd / sam / rasp.c
1 #include "sam.h"
2 /*
3  * GROWDATASIZE must be big enough that all errors go out as Hgrowdata's,
4  * so they will be scrolled into visibility in the ~~sam~~ window (yuck!).
5  */
6 #define GROWDATASIZE    50      /* if size is > this, send data with grow */
7
8 void    rcut(List*, Posn, Posn);
9 int     rterm(List*, Posn);
10 void    rgrow(List*, Posn, Posn);
11
12 static  Posn    growpos;
13 static  Posn    grown;
14 static  Posn    shrinkpos;
15 static  Posn    shrunk;
16
17 /*
18  * rasp routines inform the terminal of changes to the file.
19  *
20  * a rasp is a list of spans within the file, and an indication
21  * of whether the terminal knows about the span.
22  *
23  * optimize by coalescing multiple updates to the same span
24  * if it is not known by the terminal.
25  *
26  * other possible optimizations: flush terminal's rasp by cut everything,
27  * insert everything if rasp gets too large.
28  */
29
30 /*
31  * only called for initial load of file
32  */
33 void
34 raspload(File *f)
35 {
36         if(f->rasp == nil)
37                 return;
38         grown = f->nc;
39         growpos = 0;
40         if(f->nc)
41                 rgrow(f->rasp, 0, f->nc);
42         raspdone(f, 1);
43 }
44
45 void
46 raspstart(File *f)
47 {
48         if(f->rasp == nil)
49                 return;
50         grown = 0;
51         shrunk = 0;
52         outbuffered = 1;
53 }
54
55 void
56 raspdone(File *f, int toterm)
57 {
58         if(f->dot.r.p1 > f->nc)
59                 f->dot.r.p1 = f->nc;
60         if(f->dot.r.p2 > f->nc)
61                 f->dot.r.p2 = f->nc;
62         if(f->mark.p1 > f->nc)
63                 f->mark.p1 = f->nc;
64         if(f->mark.p2 > f->nc)
65                 f->mark.p2 = f->nc;
66         if(f->rasp == nil)
67                 return;
68         if(grown)
69                 outTsll(Hgrow, f->tag, growpos, grown);
70         else if(shrunk)
71                 outTsll(Hcut, f->tag, shrinkpos, shrunk);
72         if(toterm)
73                 outTs(Hcheck0, f->tag);
74         outflush();
75         outbuffered = 0;
76         if(f == cmd){
77                 cmdpt += cmdptadv;
78                 cmdptadv = 0;
79         }
80 }
81
82 void
83 raspflush(File *f)
84 {
85         if(grown){
86                 outTsll(Hgrow, f->tag, growpos, grown);
87                 grown = 0;
88         }
89         else if(shrunk){
90                 outTsll(Hcut, f->tag, shrinkpos, shrunk);
91                 shrunk = 0;
92         }
93         outflush();
94 }
95
96 void
97 raspdelete(File *f, uint p1, uint p2, int toterm)
98 {
99         long n;
100
101         n = p2 - p1;
102         if(n == 0)
103                 return;
104
105         if(p2 <= f->dot.r.p1){
106                 f->dot.r.p1 -= n;
107                 f->dot.r.p2 -= n;
108         }
109         if(p2 <= f->mark.p1){
110                 f->mark.p1 -= n;
111                 f->mark.p2 -= n;
112         }
113
114         if(f->rasp == nil)
115                 return;
116
117         if(f==cmd && p1<cmdpt){
118                 if(p2 <= cmdpt)
119                         cmdpt -= n;
120                 else
121                         cmdpt = p1;
122         }
123         if(toterm){
124                 if(grown){
125                         outTsll(Hgrow, f->tag, growpos, grown);
126                         grown = 0;
127                 }else if(shrunk && shrinkpos!=p1 && shrinkpos!=p2){
128                         outTsll(Hcut, f->tag, shrinkpos, shrunk);
129                         shrunk = 0;
130                 }
131                 if(!shrunk || shrinkpos==p2)
132                         shrinkpos = p1;
133                 shrunk += n;
134         }
135         rcut(f->rasp, p1, p2);
136 }
137
138 void
139 raspinsert(File *f, uint p1, Rune *buf, uint n, int toterm)
140 {
141         Range r;
142
143         if(n == 0)
144                 return;
145
146         if(p1 < f->dot.r.p1){
147                 f->dot.r.p1 += n;
148                 f->dot.r.p2 += n;
149         }
150         if(p1 < f->mark.p1){
151                 f->mark.p1 += n;
152                 f->mark.p2 += n;
153         }
154
155
156         if(f->rasp == nil)
157                 return;
158         if(f==cmd && p1<cmdpt)
159                 cmdpt += n;
160         if(toterm){
161                 if(shrunk){
162                         outTsll(Hcut, f->tag, shrinkpos, shrunk);
163                         shrunk = 0;
164                 }
165                 if(n>GROWDATASIZE || !rterm(f->rasp, p1)){
166                         rgrow(f->rasp, p1, n);
167                         if(grown && growpos+grown!=p1 && growpos!=p1){
168                                 outTsll(Hgrow, f->tag, growpos, grown);
169                                 grown = 0;
170                         }
171                         if(!grown)
172                                 growpos = p1;
173                         grown += n;
174                 }else{
175                         if(grown){
176                                 outTsll(Hgrow, f->tag, growpos, grown);
177                                 grown = 0;
178                         }
179                         rgrow(f->rasp, p1, n);
180                         r = rdata(f->rasp, p1, n);
181                         if(r.p1!=p1 || r.p2!=p1+n)
182                                 panic("rdata in toterminal");
183                         outTsllS(Hgrowdata, f->tag, p1, n, tmprstr(buf, n));
184                 }
185         }else{
186                 rgrow(f->rasp, p1, n);
187                 r = rdata(f->rasp, p1, n);
188                 if(r.p1!=p1 || r.p2!=p1+n)
189                         panic("rdata in toterminal");
190         }
191 }
192
193 #define M       0x80000000L
194 #define P(i)    r->posnptr[i]
195 #define T(i)    (P(i)&M)        /* in terminal */
196 #define L(i)    (P(i)&~M)       /* length of this piece */
197
198 void
199 rcut(List *r, Posn p1, Posn p2)
200 {
201         Posn p, x;
202         int i;
203
204         if(p1 == p2)
205                 panic("rcut 0");
206         for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
207                 ;
208         if(i == r->nused)
209                 panic("rcut 1");
210         if(p < p1){     /* chop this piece */
211                 if(p+L(i) < p2){
212                         x = p1-p;
213                         p += L(i);
214                 }else{
215                         x = L(i)-(p2-p1);
216                         p = p2;
217                 }
218                 if(T(i))
219                         P(i) = x|M;
220                 else
221                         P(i) = x;
222                 i++;
223         }
224         while(i<r->nused && p+L(i)<=p2){
225                 p += L(i);
226                 dellist(r, i);
227         }
228         if(p < p2){
229                 if(i == r->nused)
230                         panic("rcut 2");
231                 x = L(i)-(p2-p);
232                 if(T(i))
233                         P(i) = x|M;
234                 else
235                         P(i) = x;
236         }
237         /* can we merge i and i-1 ? */
238         if(i>0 && i<r->nused && T(i-1)==T(i)){
239                 x = L(i-1)+L(i);
240                 dellist(r, i--);
241                 if(T(i))
242                         P(i)=x|M;
243                 else
244                         P(i)=x;
245         }
246 }
247
248 void
249 rgrow(List *r, Posn p1, Posn n)
250 {
251         Posn p;
252         int i;
253
254         if(n == 0)
255                 panic("rgrow 0");
256         for(p=0,i=0; i<r->nused && p+L(i)<=p1; p+=L(i++))
257                 ;
258         if(i == r->nused){      /* stick on end of file */
259                 if(p!=p1)
260                         panic("rgrow 1");
261                 if(i>0 && !T(i-1))
262                         P(i-1)+=n;
263                 else
264                         inslist(r, i, n);
265         }else if(!T(i))         /* goes in this empty piece */
266                 P(i)+=n;
267         else if(p==p1 && i>0 && !T(i-1))        /* special case; simplifies life */
268                 P(i-1)+=n;
269         else if(p==p1)
270                 inslist(r, i, n);
271         else{                   /* must break piece in terminal */
272                 inslist(r, i+1, (L(i)-(p1-p))|M);
273                 inslist(r, i+1, n);
274                 P(i) = (p1-p)|M;
275         }
276 }
277
278 int
279 rterm(List *r, Posn p1)
280 {
281         Posn p;
282         int i;
283
284         for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++))
285                 ;
286         if(i==r->nused && (i==0 || !T(i-1)))
287                 return 0;
288         return T(i);
289 }
290
291 Range
292 rdata(List *r, Posn p1, Posn n)
293 {
294         Posn p;
295         int i;
296         Range rg;
297
298         if(n==0)
299                 panic("rdata 0");
300         for(p = 0,i = 0; i<r->nused && p+L(i)<=p1; p+=L(i++))
301                 ;
302         if(i==r->nused)
303                 panic("rdata 1");
304         if(T(i)){
305                 n-=L(i)-(p1-p);
306                 if(n<=0){
307                         rg.p1 = rg.p2 = p1;
308                         return rg;
309                 }
310                 p+=L(i++);
311                 p1 = p;
312         }
313         if(T(i) || i==r->nused)
314                 panic("rdata 2");
315         if(p+L(i)<p1+n)
316                 n = L(i)-(p1-p);
317         rg.p1 = p1;
318         rg.p2 = p1+n;
319         if(p!=p1){
320                 inslist(r, i+1, L(i)-(p1-p));
321                 P(i)=p1-p;
322                 i++;
323         }
324         if(L(i)!=n){
325                 inslist(r, i+1, L(i)-n);
326                 P(i)=n;
327         }
328         P(i)|=M;
329         /* now i is set; can we merge? */
330         if(i<r->nused-1 && T(i+1)){
331                 P(i)=(n+=L(i+1))|M;
332                 dellist(r, i+1);
333         }
334         if(i>0 && T(i-1)){
335                 P(i)=(n+L(i-1))|M;
336                 dellist(r, i-1);
337         }
338         return rg;
339 }