| #include <u.h> |
| #include <libc.h> |
| #include <draw.h> |
| #include <mouse.h> |
| #include <frame.h> |
| |
| #define SLOP 25 |
| |
| void |
| _fraddbox(Frame *f, int bn, int n) /* add n boxes after bn, shift the rest up, |
| * box[bn+n]==box[bn] */ |
| { |
| int i; |
| |
| if(bn > f->nbox) |
| drawerror(f->display, "_fraddbox"); |
| if(f->nbox+n > f->nalloc) |
| _frgrowbox(f, n+SLOP); |
| for(i=f->nbox; --i>=bn; ) |
| f->box[i+n] = f->box[i]; |
| f->nbox+=n; |
| } |
| |
| void |
| _frclosebox(Frame *f, int n0, int n1) /* inclusive */ |
| { |
| int i; |
| |
| if(n0>=f->nbox || n1>=f->nbox || n1<n0) |
| drawerror(f->display, "_frclosebox"); |
| n1++; |
| for(i=n1; i<f->nbox; i++) |
| f->box[i-(n1-n0)] = f->box[i]; |
| f->nbox -= n1-n0; |
| } |
| |
| void |
| _frdelbox(Frame *f, int n0, int n1) /* inclusive */ |
| { |
| if(n0>=f->nbox || n1>=f->nbox || n1<n0) |
| drawerror(f->display, "_frdelbox"); |
| _frfreebox(f, n0, n1); |
| _frclosebox(f, n0, n1); |
| } |
| |
| void |
| _frfreebox(Frame *f, int n0, int n1) /* inclusive */ |
| { |
| int i; |
| |
| if(n1<n0) |
| return; |
| if(n0>=f->nbox || n1>=f->nbox) |
| drawerror(f->display, "_frfreebox"); |
| n1++; |
| for(i=n0; i<n1; i++) |
| if(f->box[i].nrune >= 0) |
| free(f->box[i].ptr); |
| } |
| |
| void |
| _frgrowbox(Frame *f, int delta) |
| { |
| f->nalloc += delta; |
| f->box = realloc(f->box, f->nalloc*sizeof(Frbox)); |
| if(f->box == 0) |
| drawerror(f->display, "_frgrowbox"); |
| } |
| |
| static |
| void |
| dupbox(Frame *f, int bn) |
| { |
| uchar *p; |
| |
| if(f->box[bn].nrune < 0) |
| drawerror(f->display, "dupbox"); |
| _fraddbox(f, bn, 1); |
| if(f->box[bn].nrune >= 0){ |
| p = _frallocstr(f, NBYTE(&f->box[bn])+1); |
| strcpy((char*)p, (char*)f->box[bn].ptr); |
| f->box[bn+1].ptr = p; |
| } |
| } |
| |
| static |
| uchar* |
| runeindex(uchar *p, int n) |
| { |
| int i, w; |
| Rune rune; |
| |
| for(i=0; i<n; i++,p+=w) |
| if(*p < Runeself) |
| w = 1; |
| else{ |
| w = chartorune(&rune, (char*)p); |
| USED(rune); |
| } |
| return p; |
| } |
| |
| static |
| void |
| truncatebox(Frame *f, Frbox *b, int n) /* drop last n chars; no allocation done */ |
| { |
| if(b->nrune<0 || b->nrune<n) |
| drawerror(f->display, "truncatebox"); |
| b->nrune -= n; |
| runeindex(b->ptr, b->nrune)[0] = 0; |
| b->wid = stringwidth(f->font, (char *)b->ptr); |
| } |
| |
| static |
| void |
| chopbox(Frame *f, Frbox *b, int n) /* drop first n chars; no allocation done */ |
| { |
| char *p; |
| |
| if(b->nrune<0 || b->nrune<n) |
| drawerror(f->display, "chopbox"); |
| p = (char*)runeindex(b->ptr, n); |
| memmove((char*)b->ptr, p, strlen(p)+1); |
| b->nrune -= n; |
| b->wid = stringwidth(f->font, (char *)b->ptr); |
| } |
| |
| void |
| _frsplitbox(Frame *f, int bn, int n) |
| { |
| dupbox(f, bn); |
| truncatebox(f, &f->box[bn], f->box[bn].nrune-n); |
| chopbox(f, &f->box[bn+1], n); |
| } |
| |
| void |
| _frmergebox(Frame *f, int bn) /* merge bn and bn+1 */ |
| { |
| Frbox *b; |
| |
| b = &f->box[bn]; |
| _frinsure(f, bn, NBYTE(&b[0])+NBYTE(&b[1])+1); |
| strcpy((char*)runeindex(b[0].ptr, b[0].nrune), (char*)b[1].ptr); |
| b[0].wid += b[1].wid; |
| b[0].nrune += b[1].nrune; |
| _frdelbox(f, bn+1, bn+1); |
| } |
| |
| int |
| _frfindbox(Frame *f, int bn, ulong p, ulong q) /* find box containing q and put q on a box boundary */ |
| { |
| Frbox *b; |
| |
| for(b = &f->box[bn]; bn<f->nbox && p+NRUNE(b)<=q; bn++, b++) |
| p += NRUNE(b); |
| if(p != q) |
| _frsplitbox(f, bn++, (int)(q-p)); |
| return bn; |
| } |