1 #include <u.h> 2 #include <libc.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].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 uchar *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].ptr); 81 f->box[bn+1].ptr = p; 82 } 83 } 84 85 static 86 uchar* 87 runeindex(uchar *p, int n) 88 { 89 int i, w; 90 Rune rune; 91 92 for(i=0; i<n; i++,p+=w) 93 if(*p < Runeself) 94 w = 1; 95 else{ 96 w = chartorune(&rune, (char*)p); 97 USED(rune); 98 } 99 return p; 100 } 101 102 static 103 void 104 truncatebox(Frame *f, Frbox *b, int n) /* drop last n chars; no allocation done */ 105 { 106 if(b->nrune<0 || b->nrune<n) 107 berror("truncatebox"); 108 b->nrune -= n; 109 runeindex(b->ptr, b->nrune)[0] = 0; 110 b->wid = strwidth(f->font, (char *)b->ptr); 111 } 112 113 static 114 void 115 chopbox(Frame *f, Frbox *b, int n) /* drop first n chars; no allocation done */ 116 { 117 if(b->nrune<0 || b->nrune<n) 118 berror("chopbox"); 119 strcpy((char*)b->ptr, (char*)runeindex(b->ptr, n)); 120 b->nrune -= n; 121 b->wid = strwidth(f->font, (char *)b->ptr); 122 } 123 124 void 125 _frsplitbox(Frame *f, int bn, int n) 126 { 127 dupbox(f, bn); 128 truncatebox(f, &f->box[bn], f->box[bn].nrune-n); 129 chopbox(f, &f->box[bn+1], n); 130 } 131 132 void 133 _frmergebox(Frame *f, int bn) /* merge bn and bn+1 */ 134 { 135 Frbox *b; 136 137 b = &f->box[bn]; 138 _frinsure(f, bn, NBYTE(&b[0])+NBYTE(&b[1])+1); 139 strcpy((char*)runeindex(b[0].ptr, b[0].nrune), (char*)b[1].ptr); 140 b[0].wid += b[1].wid; 141 b[0].nrune += b[1].nrune; 142 _frdelbox(f, bn+1, bn+1); 143 } 144 145 int 146 _frfindbox(Frame *f, int bn, ulong p, ulong q) /* find box containing q and put q on a box boundary */ 147 { 148 Frbox *b; 149 150 for(b = &f->box[bn]; bn<f->nbox && p+NRUNE(b)<=q; bn++, b++) 151 p += NRUNE(b); 152 if(p != q) 153 _frsplitbox(f, bn++, (int)(q-p)); 154 return bn; 155 } 156