rasp.c - sam - An updated version of the sam text editor.
(HTM) git clone git://vernunftzentrum.de/sam.git
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) LICENSE
---
rasp.c (5438B)
---
1 /* Copyright (c) 1998 Lucent Technologies - All rights reserved. */
2 #include <u.h>
3 #include <libg.h>
4 #include <frame.h>
5 #include "flayer.h"
6 #include "samterm.h"
7
8 void
9 rinit(Rasp *r)
10 {
11 r->nrunes=0;
12 r->sect=0;
13 }
14
15 void
16 rclear(Rasp *r)
17 {
18 Section *s, *ns;
19
20 for(s=r->sect; s; s=ns){
21 ns = s->next;
22 free(s->text);
23 free(s);
24 }
25 r->sect = 0;
26 }
27
28 Section*
29 rsinsert(Rasp *r, Section *s) /* insert before s */
30 {
31 Section *t;
32 Section *u;
33
34 t = alloc(sizeof(Section));
35 if(r->sect == s){ /* includes empty list case: r->sect==s==0 */
36 r->sect = t;
37 t->next = s;
38 }else{
39 u = r->sect;
40 if(u == 0)
41 panic("rsinsert 1");
42 do{
43 if(u->next == s){
44 t->next = s;
45 u->next = t;
46 goto Return;
47 }
48 u=u->next;
49 }while(u);
50 panic("rsinsert 2");
51 }
52 Return:
53 return t;
54 }
55
56 void
57 rsdelete(Rasp *r, Section *s)
58 {
59 Section *t;
60
61 if(s == 0)
62 panic("rsdelete");
63 if(r->sect == s){
64 r->sect = s->next;
65 goto Free;
66 }
67 for(t=r->sect; t; t=t->next)
68 if(t->next == s){
69 t->next = s->next;
70 Free:
71 if(s->text)
72 free(s->text);
73 free(s);
74 return;
75 }
76 panic("rsdelete 2");
77 }
78
79 void
80 splitsect(Rasp *r, Section *s, int64_t n0)
81 {
82 if(s == 0)
83 panic("splitsect");
84 rsinsert(r, s->next);
85 if(s->text == 0)
86 s->next->text = 0;
87 else{
88 s->next->text = alloc(RUNESIZE*(TBLOCKSIZE+1));
89 Strcpy(s->next->text, s->text+n0);
90 s->text[n0] = 0;
91 }
92 s->next->nrunes = s->nrunes-n0;
93 s->nrunes = n0;
94 }
95
96 Section *
97 findsect(Rasp *r, Section *s, int64_t p, int64_t q) /* find sect containing q and put q on a sect boundary */
98 {
99 if(s==0 && p!=q)
100 panic("findsect");
101 for(; s && p+s->nrunes<=q; s=s->next)
102 p += s->nrunes;
103 if(p != q){
104 splitsect(r, s, q-p);
105 s = s->next;
106 }
107 return s;
108 }
109
110 void
111 rresize(Rasp *r, int64_t a, int64_t old, int64_t new)
112 {
113 Section *s, *t, *ns;
114
115 s = findsect(r, r->sect, 0L, a);
116 t = findsect(r, s, a, a+old);
117 for(; s!=t; s=ns){
118 ns=s->next;
119 rsdelete(r, s);
120 }
121 /* now insert the new piece before t */
122 if(new > 0){
123 ns=rsinsert(r, t);
124 ns->nrunes=new;
125 ns->text=0;
126 }
127 r->nrunes += new-old;
128 }
129
130 void
131 rdata(Rasp *r, int64_t p0, int64_t p1, wchar_t *cp)
132 {
133 Section *s, *t, *ns;
134
135 s = findsect(r, r->sect, 0L, p0);
136 t = findsect(r, s, p0, p1);
137 for(; s!=t; s=ns){
138 ns=s->next;
139 if(s->text)
140 panic("rdata");
141 rsdelete(r, s);
142 }
143 p1 -= p0;
144 s = rsinsert(r, t);
145 s->text = alloc(RUNESIZE*(TBLOCKSIZE+1));
146 memmove(s->text, cp, RUNESIZE*p1);
147 s->text[p1] = 0;
148 s->nrunes = p1;
149 }
150
151 void
152 rclean(Rasp *r)
153 {
154 Section *s;
155
156 for(s=r->sect; s; s=s->next)
157 while(s->next && (s->text!=0)==(s->next->text!=0)){
158 if(s->text){
159 if(s->nrunes+s->next->nrunes>TBLOCKSIZE)
160 break;
161 Strcpy(s->text+s->nrunes, s->next->text);
162 }
163 s->nrunes += s->next->nrunes;
164 rsdelete(r, s->next);
165 }
166 }
167
168 void
169 Strcpy(wchar_t *to, wchar_t *from)
170 {
171 do; while((*to++ = *from++));
172 }
173
174 wchar_t*
175 rload(Rasp *r, uint64_t p0, uint64_t p1, uint64_t *nrp)
176 {
177 Section *s;
178 int64_t p;
179 int n, nb;
180
181 nb = 0;
182 Strgrow(&scratch, &nscralloc, p1-p0+1);
183 scratch[0] = 0;
184 for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
185 p += s->nrunes;
186 while(p<p1 && s){
187 /*
188 * Subtle and important. If we are preparing to handle an 'rdata'
189 * call, it's because we have an 'rresize' hole here, so the
190 * screen doesn't have data for that space anyway (it got cut
191 * first). So pretend it isn't there.
192 */
193 if(s->text){
194 n = s->nrunes-(p0-p);
195 if(n>p1-p0) /* all in this section */
196 n = p1-p0;
197 memmove(scratch+nb, s->text+(p0-p), n*RUNESIZE);
198 nb += n;
199 scratch[nb] = 0;
200 }
201 p += s->nrunes;
202 p0 = p;
203 s = s->next;
204 }
205 if(nrp)
206 *nrp = nb;
207 return scratch;
208 }
209
210 int
211 rmissing(Rasp *r, uint64_t p0, uint64_t p1)
212 {
213 Section *s;
214 int64_t p;
215 int n, nm=0;
216
217 for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
218 p += s->nrunes;
219 while(p<p1 && s){
220 if(s->text == 0){
221 n = s->nrunes-(p0-p);
222 if(n > p1-p0) /* all in this section */
223 n = p1-p0;
224 nm += n;
225 }
226 p += s->nrunes;
227 p0 = p;
228 s = s->next;
229 }
230 return nm;
231 }
232
233 int
234 rcontig(Rasp *r, uint64_t p0, uint64_t p1, bool text)
235 {
236 Section *s;
237 int64_t p, n;
238 int np=0;
239
240 for(p=0,s=r->sect; s && p+s->nrunes<=p0; s=s->next)
241 p += s->nrunes;
242 while(p<p1 && s && (text ? (s->text!=0) : (s->text==0))){
243 n = s->nrunes-(p0-p);
244 if(n > p1-p0) /* all in this section */
245 n = p1-p0;
246 np += n;
247 p += s->nrunes;
248 p0 = p;
249 s = s->next;
250 }
251 return np;
252 }
253
254 void
255 Strgrow(wchar_t **s, int64_t *n, int want) /* can always toss the old data when called */
256 {
257 if(*n >= want)
258 return;
259 free(*s);
260 *s = alloc(RUNESIZE*want);
261 *n = want;
262 }