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 }