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 void13 rinit(Rasp *r)14 {15 r->nrunes=0;16 r->sect=0;17 }19 void20 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 void61 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 void84 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 */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 }114 void115 rresize(Rasp *r, long a, long old, long new)116 {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);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 }134 void135 rdata(Rasp *r, long p0, long p1, Rune *cp)136 {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);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 }155 void156 rclean(Rasp *r)157 {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);166 }167 s->nrunes += s->next->nrunes;168 rsdelete(r, s->next);169 }170 }172 void173 Strcpy(Rune *to, Rune *from)174 {175 do; while(*to++ = *from++);176 }178 Rune*179 rload(Rasp *r, ulong p0, ulong p1, ulong *nrp)180 {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 the194 * screen doesn't have data for that space anyway (it got cut195 * 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 }214 int215 rmissing(Rasp *r, ulong p0, ulong p1)216 {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;229 }230 p += s->nrunes;231 p0 = p;232 s = s->next;233 }234 return nm;235 }237 int238 rcontig(Rasp *r, ulong p0, ulong p1, int text)239 {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;254 }255 return np;256 }258 void259 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 }