trasp.c - plan9port - [fork] Plan 9 from user space | |
git clone git://src.adamsgaard.dk/plan9port | |
Log | |
Files | |
Refs | |
README | |
LICENSE | |
--- | |
trasp.c (5833B) | |
--- | |
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… | |
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->b.nc; | |
39 growpos = 0; | |
40 if(f->b.nc) | |
41 rgrow(f->rasp, 0, f->b.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->b.nc) | |
59 f->dot.r.p1 = f->b.nc; | |
60 if(f->dot.r.p2 > f->b.nc) | |
61 f->dot.r.p2 = f->b.nc; | |
62 if(f->mark.p1 > f->b.nc) | |
63 f->mark.p1 = f->b.nc; | |
64 if(f->mark.p2 > f->b.nc) | |
65 f->mark.p2 = f->b.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, … | |
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; simplif… | |
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) | |
287 return i > 0 && T(i-1); | |
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 } |