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