13e12c5d1SDavid du Colombier #include <u.h> 23e12c5d1SDavid du Colombier #include <libc.h> 3*7dd7cddfSDavid du Colombier #include <draw.h> 4*7dd7cddfSDavid du Colombier #include <thread.h> 5*7dd7cddfSDavid du Colombier #include <mouse.h> 63e12c5d1SDavid du Colombier #include <frame.h> 73e12c5d1SDavid du Colombier 83e12c5d1SDavid du Colombier #define SLOP 25 93e12c5d1SDavid du Colombier 103e12c5d1SDavid du Colombier void 113e12c5d1SDavid du Colombier _fraddbox(Frame *f, int bn, int n) /* add n boxes after bn, shift the rest up, 123e12c5d1SDavid du Colombier * box[bn+n]==box[bn] */ 133e12c5d1SDavid du Colombier { 143e12c5d1SDavid du Colombier int i; 153e12c5d1SDavid du Colombier 163e12c5d1SDavid du Colombier if(bn > f->nbox) 17*7dd7cddfSDavid du Colombier drawerror(f->display, "_fraddbox"); 183e12c5d1SDavid du Colombier if(f->nbox+n > f->nalloc) 193e12c5d1SDavid du Colombier _frgrowbox(f, n+SLOP); 203e12c5d1SDavid du Colombier for(i=f->nbox; --i>=bn; ) 213e12c5d1SDavid du Colombier f->box[i+n] = f->box[i]; 223e12c5d1SDavid du Colombier f->nbox+=n; 233e12c5d1SDavid du Colombier } 243e12c5d1SDavid du Colombier 253e12c5d1SDavid du Colombier void 263e12c5d1SDavid du Colombier _frclosebox(Frame *f, int n0, int n1) /* inclusive */ 273e12c5d1SDavid du Colombier { 283e12c5d1SDavid du Colombier int i; 293e12c5d1SDavid du Colombier 303e12c5d1SDavid du Colombier if(n0>=f->nbox || n1>=f->nbox || n1<n0) 31*7dd7cddfSDavid du Colombier drawerror(f->display, "_frclosebox"); 323e12c5d1SDavid du Colombier n1++; 333e12c5d1SDavid du Colombier for(i=n1; i<f->nbox; i++) 343e12c5d1SDavid du Colombier f->box[i-(n1-n0)] = f->box[i]; 353e12c5d1SDavid du Colombier f->nbox -= n1-n0; 363e12c5d1SDavid du Colombier } 373e12c5d1SDavid du Colombier 383e12c5d1SDavid du Colombier void 393e12c5d1SDavid du Colombier _frdelbox(Frame *f, int n0, int n1) /* inclusive */ 403e12c5d1SDavid du Colombier { 413e12c5d1SDavid du Colombier if(n0>=f->nbox || n1>=f->nbox || n1<n0) 42*7dd7cddfSDavid du Colombier drawerror(f->display, "_frdelbox"); 433e12c5d1SDavid du Colombier _frfreebox(f, n0, n1); 443e12c5d1SDavid du Colombier _frclosebox(f, n0, n1); 453e12c5d1SDavid du Colombier } 463e12c5d1SDavid du Colombier 473e12c5d1SDavid du Colombier void 483e12c5d1SDavid du Colombier _frfreebox(Frame *f, int n0, int n1) /* inclusive */ 493e12c5d1SDavid du Colombier { 503e12c5d1SDavid du Colombier int i; 513e12c5d1SDavid du Colombier 523e12c5d1SDavid du Colombier if(n1<n0) 533e12c5d1SDavid du Colombier return; 543e12c5d1SDavid du Colombier if(n0>=f->nbox || n1>=f->nbox) 55*7dd7cddfSDavid du Colombier drawerror(f->display, "_frfreebox"); 563e12c5d1SDavid du Colombier n1++; 573e12c5d1SDavid du Colombier for(i=n0; i<n1; i++) 583e12c5d1SDavid du Colombier if(f->box[i].nrune >= 0) 593e12c5d1SDavid du Colombier free(f->box[i].ptr); 603e12c5d1SDavid du Colombier } 613e12c5d1SDavid du Colombier 623e12c5d1SDavid du Colombier void 633e12c5d1SDavid du Colombier _frgrowbox(Frame *f, int delta) 643e12c5d1SDavid du Colombier { 653e12c5d1SDavid du Colombier f->nalloc += delta; 663e12c5d1SDavid du Colombier f->box = realloc(f->box, f->nalloc*sizeof(Frbox)); 673e12c5d1SDavid du Colombier if(f->box == 0) 68*7dd7cddfSDavid du Colombier drawerror(f->display, "_frgrowbox"); 693e12c5d1SDavid du Colombier } 703e12c5d1SDavid du Colombier 713e12c5d1SDavid du Colombier static 723e12c5d1SDavid du Colombier void 733e12c5d1SDavid du Colombier dupbox(Frame *f, int bn) 743e12c5d1SDavid du Colombier { 753e12c5d1SDavid du Colombier uchar *p; 763e12c5d1SDavid du Colombier 773e12c5d1SDavid du Colombier if(f->box[bn].nrune < 0) 78*7dd7cddfSDavid du Colombier drawerror(f->display, "dupbox"); 793e12c5d1SDavid du Colombier _fraddbox(f, bn, 1); 803e12c5d1SDavid du Colombier if(f->box[bn].nrune >= 0){ 81*7dd7cddfSDavid du Colombier p = _frallocstr(f, NBYTE(&f->box[bn])+1); 823e12c5d1SDavid du Colombier strcpy((char*)p, (char*)f->box[bn].ptr); 833e12c5d1SDavid du Colombier f->box[bn+1].ptr = p; 843e12c5d1SDavid du Colombier } 853e12c5d1SDavid du Colombier } 863e12c5d1SDavid du Colombier 873e12c5d1SDavid du Colombier static 883e12c5d1SDavid du Colombier uchar* 893e12c5d1SDavid du Colombier runeindex(uchar *p, int n) 903e12c5d1SDavid du Colombier { 913e12c5d1SDavid du Colombier int i, w; 923e12c5d1SDavid du Colombier Rune rune; 933e12c5d1SDavid du Colombier 943e12c5d1SDavid du Colombier for(i=0; i<n; i++,p+=w) 953e12c5d1SDavid du Colombier if(*p < Runeself) 963e12c5d1SDavid du Colombier w = 1; 973e12c5d1SDavid du Colombier else{ 983e12c5d1SDavid du Colombier w = chartorune(&rune, (char*)p); 993e12c5d1SDavid du Colombier USED(rune); 1003e12c5d1SDavid du Colombier } 1013e12c5d1SDavid du Colombier return p; 1023e12c5d1SDavid du Colombier } 1033e12c5d1SDavid du Colombier 1043e12c5d1SDavid du Colombier static 1053e12c5d1SDavid du Colombier void 1063e12c5d1SDavid du Colombier truncatebox(Frame *f, Frbox *b, int n) /* drop last n chars; no allocation done */ 1073e12c5d1SDavid du Colombier { 1083e12c5d1SDavid du Colombier if(b->nrune<0 || b->nrune<n) 109*7dd7cddfSDavid du Colombier drawerror(f->display, "truncatebox"); 1103e12c5d1SDavid du Colombier b->nrune -= n; 1113e12c5d1SDavid du Colombier runeindex(b->ptr, b->nrune)[0] = 0; 112*7dd7cddfSDavid du Colombier b->wid = stringwidth(f->font, (char *)b->ptr); 1133e12c5d1SDavid du Colombier } 1143e12c5d1SDavid du Colombier 1153e12c5d1SDavid du Colombier static 1163e12c5d1SDavid du Colombier void 1173e12c5d1SDavid du Colombier chopbox(Frame *f, Frbox *b, int n) /* drop first n chars; no allocation done */ 1183e12c5d1SDavid du Colombier { 1193e12c5d1SDavid du Colombier if(b->nrune<0 || b->nrune<n) 120*7dd7cddfSDavid du Colombier drawerror(f->display, "chopbox"); 1213e12c5d1SDavid du Colombier strcpy((char*)b->ptr, (char*)runeindex(b->ptr, n)); 1223e12c5d1SDavid du Colombier b->nrune -= n; 123*7dd7cddfSDavid du Colombier b->wid = stringwidth(f->font, (char *)b->ptr); 1243e12c5d1SDavid du Colombier } 1253e12c5d1SDavid du Colombier 1263e12c5d1SDavid du Colombier void 1273e12c5d1SDavid du Colombier _frsplitbox(Frame *f, int bn, int n) 1283e12c5d1SDavid du Colombier { 1293e12c5d1SDavid du Colombier dupbox(f, bn); 1303e12c5d1SDavid du Colombier truncatebox(f, &f->box[bn], f->box[bn].nrune-n); 1313e12c5d1SDavid du Colombier chopbox(f, &f->box[bn+1], n); 1323e12c5d1SDavid du Colombier } 1333e12c5d1SDavid du Colombier 1343e12c5d1SDavid du Colombier void 1353e12c5d1SDavid du Colombier _frmergebox(Frame *f, int bn) /* merge bn and bn+1 */ 1363e12c5d1SDavid du Colombier { 1373e12c5d1SDavid du Colombier Frbox *b; 1383e12c5d1SDavid du Colombier 1393e12c5d1SDavid du Colombier b = &f->box[bn]; 1403e12c5d1SDavid du Colombier _frinsure(f, bn, NBYTE(&b[0])+NBYTE(&b[1])+1); 1413e12c5d1SDavid du Colombier strcpy((char*)runeindex(b[0].ptr, b[0].nrune), (char*)b[1].ptr); 1423e12c5d1SDavid du Colombier b[0].wid += b[1].wid; 1433e12c5d1SDavid du Colombier b[0].nrune += b[1].nrune; 1443e12c5d1SDavid du Colombier _frdelbox(f, bn+1, bn+1); 1453e12c5d1SDavid du Colombier } 1463e12c5d1SDavid du Colombier 1473e12c5d1SDavid du Colombier int 1483e12c5d1SDavid du Colombier _frfindbox(Frame *f, int bn, ulong p, ulong q) /* find box containing q and put q on a box boundary */ 1493e12c5d1SDavid du Colombier { 1503e12c5d1SDavid du Colombier Frbox *b; 1513e12c5d1SDavid du Colombier 1523e12c5d1SDavid du Colombier for(b = &f->box[bn]; bn<f->nbox && p+NRUNE(b)<=q; bn++, b++) 1533e12c5d1SDavid du Colombier p += NRUNE(b); 1543e12c5d1SDavid du Colombier if(p != q) 1553e12c5d1SDavid du Colombier _frsplitbox(f, bn++, (int)(q-p)); 1563e12c5d1SDavid du Colombier return bn; 1573e12c5d1SDavid du Colombier } 158