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