Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 #include <thread.h>
5 #include <mouse.h>
6 #include <cursor.h>
7 #include <keyboard.h>
8 #include <frame.h>
9 #include "flayer.h"
10 #include "samterm.h"
12 void
13 rinit(Rasp *r)
14 {
15 r->nrunes=0;
16 r->sect=0;
17 }
19 void
20 rclear(Rasp *r)
21 {
22 Section *s, *ns;
24 for(s=r->sect; s; s=ns){
25 ns = s->next;
26 free(s->text);
27 free(s);
28 }
29 r->sect = 0;
30 }
32 Section*
33 rsinsert(Rasp *r, Section *s) /* insert before s */
34 {
35 Section *t;
36 Section *u;
38 t = alloc(sizeof(Section));
39 if(r->sect == s){ /* includes empty list case: r->sect==s==0 */
40 r->sect = t;
41 t->next = s;
42 }else{
43 u = r->sect;
44 if(u == 0)
45 panic("rsinsert 1");
46 do{
47 if(u->next == s){
48 t->next = s;
49 u->next = t;
50 goto Return;
51 }
52 u=u->next;
53 }while(u);
54 panic("rsinsert 2");
55 }
56 Return:
57 return t;
58 }
60 void
61 rsdelete(Rasp *r, Section *s)
62 {
63 Section *t;
65 if(s == 0)
66 panic("rsdelete");
67 if(r->sect == s){
68 r->sect = s->next;
69 goto Free;
70 }
71 for(t=r->sect; t; t=t->next)
72 if(t->next == s){
73 t->next = s->next;
74 Free:
75 if(s->text)
76 free(s->text);
77 free(s);
78 return;
79 }
80 panic("rsdelete 2");
81 }
83 void
84 splitsect(Rasp *r, Section *s, long n0)
85 {
86 if(s == 0)
87 panic("splitsect");
88 rsinsert(r, s->next);
89 if(s->text == 0)
90 s->next->text = 0;
91 else{
92 s->next->text = alloc(RUNESIZE*(TBLOCKSIZE+1));
93 Strcpy(s->next->text, s->text+n0);
94 s->text[n0] = 0;
95 }
96 s->next->nrunes = s->nrunes-n0;
97 s->nrunes = n0;
98 }
100 Section *
101 findsect(Rasp *r, Section *s, long p, long q) /* find sect containing q and put q on a sect boundary */
103 if(s==0 && p!=q)
104 panic("findsect");
105 for(; s && p+s->nrunes<=q; s=s->next)
106 p += s->nrunes;
107 if(p != q){
108 splitsect(r, s, q-p);
109 s = s->next;
111 return s;
114 void
115 rresize(Rasp *r, long a, long old, long new)
117 Section *s, *t, *ns;
119 s = findsect(r, r->sect, 0L, a);
120 t = findsect(r, s, a, a+old);
121 for(; s!=t; s=ns){
122 ns=s->next;
123 rsdelete(r, s);
125 /* now insert the new piece before t */
126 if(new > 0){
127 ns=rsinsert(r, t);
128 ns->nrunes=new;
129 ns->text=0;
131 r->nrunes += new-old;
134 void
135 rdata(Rasp *r, long p0, long p1, Rune *cp)
137 Section *s, *t, *ns;
139 s = findsect(r, r->sect, 0L, p0);
140 t = findsect(r, s, p0, p1);
141 for(; s!=t; s=ns){
142 ns=s->next;
143 if(s->text)
144 panic("rdata");
145 rsdelete(r, s);
147 p1 -= p0;
148 s = rsinsert(r, t);
149 s->text = alloc(RUNESIZE*(TBLOCKSIZE+1));
150 memmove(s->text, cp, RUNESIZE*p1);
151 s->text[p1] = 0;
152 s->nrunes = p1;
155 void
156 rclean(Rasp *r)
158 Section *s;
160 for(s=r->sect; s; s=s->next)
161 while(s->next && (s->text!=0)==(s->next->text!=0)){
162 if(s->text){
163 if(s->nrunes+s->next->nrunes>TBLOCKSIZE)
164 break;
165 Strcpy(s->text+s->nrunes, s->next->text);
167 s->nrunes += s->next->nrunes;
168 rsdelete(r, s->next);
172 void
173 Strcpy(Rune *to, Rune *from)
175 do; while(*to++ = *from++);
178 Rune*
179 rload(Rasp *r, ulong p0, ulong p1, ulong *nrp)
181 Section *s;
182 long p;
183 int n, nb;
185 nb = 0;
186 Strgrow(&scratch, &nscralloc, p1-p0+1);
187 scratch[0] = 0;
188 for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
189 p += s->nrunes;
190 while(p<p1 && s){
191 /*
192 * Subtle and important. If we are preparing to handle an 'rdata'
193 * call, it's because we have an 'rresize' hole here, so the
194 * screen doesn't have data for that space anyway (it got cut
195 * first). So pretend it isn't there.
196 */
197 if(s->text){
198 n = s->nrunes-(p0-p);
199 if(n>p1-p0) /* all in this section */
200 n = p1-p0;
201 memmove(scratch+nb, s->text+(p0-p), n*RUNESIZE);
202 nb += n;
203 scratch[nb] = 0;
205 p += s->nrunes;
206 p0 = p;
207 s = s->next;
209 if(nrp)
210 *nrp = nb;
211 return scratch;
214 int
215 rmissing(Rasp *r, ulong p0, ulong p1)
217 Section *s;
218 long p;
219 int n, nm=0;
221 for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
222 p += s->nrunes;
223 while(p<p1 && s){
224 if(s->text == 0){
225 n = s->nrunes-(p0-p);
226 if(n > p1-p0) /* all in this section */
227 n = p1-p0;
228 nm += n;
230 p += s->nrunes;
231 p0 = p;
232 s = s->next;
234 return nm;
237 int
238 rcontig(Rasp *r, ulong p0, ulong p1, int text)
240 Section *s;
241 long p, n;
242 int np=0;
244 for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
245 p += s->nrunes;
246 while(p<p1 && s && (text? (s->text!=0) : (s->text==0))){
247 n = s->nrunes-(p0-p);
248 if(n > p1-p0) /* all in this section */
249 n = p1-p0;
250 np += n;
251 p += s->nrunes;
252 p0 = p;
253 s = s->next;
255 return np;
258 void
259 Strgrow(Rune **s, long *n, int want) /* can always toss the old data when called */
261 if(*n >= want)
262 return;
263 free(*s);
264 *s = alloc(RUNESIZE*want);
265 *n = want;