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