|  | #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; | 
|  | } |