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