rasp.c (4453B)
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" 11 12 void 13 rinit(Rasp *r) 14 { 15 r->nrunes=0; 16 r->sect=0; 17 } 18 19 void 20 rclear(Rasp *r) 21 { 22 Section *s, *ns; 23 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 } 31 32 Section* 33 rsinsert(Rasp *r, Section *s) /* insert before s */ 34 { 35 Section *t; 36 Section *u; 37 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 } 59 60 void 61 rsdelete(Rasp *r, Section *s) 62 { 63 Section *t; 64 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 } 82 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 } 99 100 Section * 101 findsect(Rasp *r, Section *s, long p, long q) /* find sect containing q and put q on a sect boundary */ 102 { 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; 110 } 111 return s; 112 } 113 114 void 115 rresize(Rasp *r, long a, long old, long new) 116 { 117 Section *s, *t, *ns; 118 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); 124 } 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; 130 } 131 r->nrunes += new-old; 132 } 133 134 void 135 rdata(Rasp *r, long p0, long p1, Rune *cp) 136 { 137 Section *s, *t, *ns; 138 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); 146 } 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; 153 } 154 155 void 156 rclean(Rasp *r) 157 { 158 Section *s; 159 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); 166 } 167 s->nrunes += s->next->nrunes; 168 rsdelete(r, s->next); 169 } 170 } 171 172 void 173 Strcpy(Rune *to, Rune *from) 174 { 175 do; while(*to++ = *from++); 176 } 177 178 Rune* 179 rload(Rasp *r, ulong p0, ulong p1, ulong *nrp) 180 { 181 Section *s; 182 long p; 183 int n, nb; 184 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; 204 } 205 p += s->nrunes; 206 p0 = p; 207 s = s->next; 208 } 209 if(nrp) 210 *nrp = nb; 211 return scratch; 212 } 213 214 int 215 rmissing(Rasp *r, ulong p0, ulong p1) 216 { 217 Section *s; 218 long p; 219 int n, nm=0; 220 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; 229 } 230 p += s->nrunes; 231 p0 = p; 232 s = s->next; 233 } 234 return nm; 235 } 236 237 int 238 rcontig(Rasp *r, ulong p0, ulong p1, int text) 239 { 240 Section *s; 241 long p, n; 242 int np=0; 243 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; 254 } 255 return np; 256 } 257 258 void 259 Strgrow(Rune **s, long *n, int want) /* can always toss the old data when called */ 260 { 261 if(*n >= want) 262 return; 263 free(*s); 264 *s = alloc(RUNESIZE*want); 265 *n = want; 266 }