URI:
       trasp.c - plan9port - [fork] Plan 9 from user space
  HTML git clone git://src.adamsgaard.dk/plan9port
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       trasp.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 }