frbox.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
       ---
       frbox.c (3196B)
       ---
            1 /* Copyright (c) 1998 Lucent Technologies - All rights reserved. */
            2 #include <u.h>
            3 #include <libg.h>
            4 #include <frame.h>
            5 
            6 #define SLOP    25
            7 
            8 void
            9 _fraddbox(Frame *f, int bn, int n)  /* add n boxes after bn, shift the rest up,
           10                  * box[bn+n]==box[bn] */
           11 {
           12     int i;
           13 
           14     if(bn > f->nbox)
           15         berror("_fraddbox");
           16     if(f->nbox+n > f->nalloc)
           17         _frgrowbox(f, n+SLOP);
           18     for(i=f->nbox; --i>=bn; )
           19         f->box[i+n] = f->box[i];
           20     f->nbox+=n;
           21 }
           22 
           23 void
           24 _frclosebox(Frame *f, int n0, int n1)   /* inclusive */
           25 {
           26     int i;
           27 
           28     if(n0>=f->nbox || n1>=f->nbox || n1<n0)
           29         berror("_frclosebox");
           30     n1++;
           31     for(i=n1; i<f->nbox; i++)
           32         f->box[i-(n1-n0)] = f->box[i];
           33     f->nbox -= n1-n0;
           34 }
           35 
           36 void
           37 _frdelbox(Frame *f, int n0, int n1) /* inclusive */
           38 {
           39     if(n0>=f->nbox || n1>=f->nbox || n1<n0)
           40         berror("_frdelbox");
           41     _frfreebox(f, n0, n1);
           42     _frclosebox(f, n0, n1);
           43 }
           44 
           45 void
           46 _frfreebox(Frame *f, int n0, int n1)    /* inclusive */
           47 {
           48     int i;
           49 
           50     if(n1<n0)
           51         return;
           52     if(n0>=f->nbox || n1>=f->nbox)
           53         berror("_frfreebox");
           54     n1++;
           55     for(i=n0; i<n1; i++)
           56         if(f->box[i].nrune >= 0)
           57             free(f->box[i].a.ptr);
           58 }
           59 
           60 void
           61 _frgrowbox(Frame *f, int delta)
           62 {
           63     f->nalloc += delta;
           64     f->box = realloc(f->box, f->nalloc*sizeof(Frbox));
           65     if(f->box == 0)
           66         berror("_frgrowbox");
           67 }
           68 
           69 static
           70 void
           71 dupbox(Frame *f, int bn)
           72 {
           73     uint8_t *p;
           74 
           75     if(f->box[bn].nrune < 0)
           76         berror("dupbox");
           77     _fraddbox(f, bn, 1);
           78     if(f->box[bn].nrune >= 0){
           79         p = _frallocstr(NBYTE(&f->box[bn])+1);
           80         strcpy((char*)p, (char*)f->box[bn].a.ptr);
           81         f->box[bn+1].a.ptr = p;
           82     }
           83 }
           84 
           85 static
           86 uint8_t*
           87 runeindex(uint8_t *p, int n)
           88 {
           89     int i, w;
           90     wchar_t rune;
           91 
           92     for(i=0; i<n; i++,p+=w)
           93         w = chartorune(&rune, (char*)p);
           94     return p;
           95 }
           96 
           97 static
           98 void
           99 truncatebox(Frame *f, Frbox *b, int n)  /* drop last n chars; no allocation done */
          100 {
          101     if(b->nrune<0 || b->nrune<n)
          102         berror("truncatebox");
          103     b->nrune -= n;
          104     runeindex(b->a.ptr, b->nrune)[0] = 0;
          105     b->wid = strwidth(f->font, (char *)b->a.ptr);
          106 }
          107 
          108 static
          109 void
          110 chopbox(Frame *f, Frbox *b, int n)  /* drop first n chars; no allocation done */
          111 {
          112     if(b->nrune<0 || b->nrune<n)
          113         berror("chopbox");
          114 
          115     uint8_t *ri = runeindex(b->a.ptr, n);
          116     memmove(b->a.ptr, ri, strlen((char *)ri) + 1);
          117     b->nrune -= n;
          118     b->wid = strwidth(f->font, (char *)b->a.ptr);
          119 }
          120 
          121 void
          122 _frsplitbox(Frame *f, int bn, int n)
          123 {
          124     dupbox(f, bn);
          125     truncatebox(f, &f->box[bn], f->box[bn].nrune-n);
          126     chopbox(f, &f->box[bn+1], n);
          127 }
          128 
          129 void
          130 _frmergebox(Frame *f, int bn)       /* merge bn and bn+1 */
          131 {
          132     Frbox *b;
          133 
          134     b = &f->box[bn];
          135     _frinsure(f, bn, NBYTE(&b[0])+NBYTE(&b[1])+1);
          136     strcpy((char*)runeindex(b[0].a.ptr, b[0].nrune), (char*)b[1].a.ptr);
          137     b[0].wid += b[1].wid;
          138     b[0].nrune += b[1].nrune;
          139     _frdelbox(f, bn+1, bn+1);
          140 }
          141 
          142 int
          143 _frfindbox(Frame *f, int bn, uint64_t p, uint64_t q)  /* find box containing q and put q on a box boundary */
          144 {
          145     Frbox *b;
          146 
          147     for(b = &f->box[bn]; bn<f->nbox && p+NRUNE(b)<=q; bn++, b++)
          148         p += NRUNE(b);
          149     if(p != q)
          150         _frsplitbox(f, bn++, (int)(q-p));
          151     return bn;
          152 }