#include #include #include #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) berror("_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 || n1nbox; 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=f->nbox || n1>=f->nbox) berror("_frfreebox"); n1++; for(i=n0; ibox[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 == nil) berror("_frgrowbox"); } intern void dupbox(Frame *f, int bn) { char *p; if(f->box[bn].nrune < 0) berror("dupbox"); _fraddbox(f, bn, 1); if(f->box[bn].nrune >= 0){ p = _frallocstr(NBYTE(&f->box[bn])+1); strcpy((char*)p, (char*)f->box[bn].ptr); f->box[bn+1].ptr = p; } } intern char* runeindex(char *p, int n) { int i, w; Rune rune; for(i=0; inrune<0 || b->nrunenrune -= n; runeindex(b->ptr, b->nrune)[0] = 0; b->wid = strwidth(f->font, (char *)b->ptr); } intern void chopbox(Frame *f, Frbox *b, int n) /* drop first n chars; no allocation done */ { if(b->nrune<0 || b->nruneptr, (char*)runeindex(b->ptr, n)); b->nrune -= n; b->wid = strwidth(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, uint p, uint q) /* find box containing q and put q on a box boundary */ { Frbox *b; uint nrune; for(b = &f->box[bn]; bn < f->nbox; bn++) { nrune = 1; if(b->nrune >= 0) nrune = b->nrune; if(p+nrune > q) break; p += nrune; b++; } if(p != q) _frsplitbox(f, bn++, (int)(q-p)); return bn; }