ref: a4d0372d0f1916d1d9df34c4fe4ae7a98c8de020
dir: /text.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <thread.h> #include <mouse.h> #include <frame.h> #include "mez.h" enum { Scrollwid = 12, /* width of scroll bar */ Scrollgap = 4, /* gap right of scroll bar */ Margin = 4, /* margin around text */ }; #define max(a, b) ((a)>(b)?(a):(b)) #define min(a, b) ((a)<(b)?(a):(b)) void textdraw(Text *t) { Rectangle scrpos; Image *screen; screen = *t->screen; draw(screen, screen->r, t->cols[BACK], nil, ZP); draw(screen, t->scrollr, t->cols[BORD], nil, ZP); scrpos = t->scrollr; if(t->nlines > 0){ scrpos.min.y = scrpos.min.y+max(0, Dy(scrpos))*t->topline/t->nlines; scrpos.max.y = scrpos.min.y+Dy(t->scrollr)*t->Frame.maxlines/t->nlines; } scrpos = insetrect(scrpos, 1); draw(screen, scrpos, t->cols[BACK], nil, ZP); frinsert(t, t->text+t->lines[t->topline], t->text+t->textlen, 0); flushimage(display, 1); } void textinit(Text *t) { Image *screen; screen = *t->screen; t->scrollr = screen->r; t->scrollr.max.x = screen->r.min.x + Scrollwid + 1; t->bodyr.min.x = screen->r.min.x + Scrollwid + Scrollgap + Margin; t->bodyr.min.y = screen->r.min.y; t->bodyr.max = screen->r.max; if(t->text == nil){ t->textcap = 8192; t->text = emallocz(t->textcap*sizeof(*t->text), 1); t->textlen = 0; } if(t->lines == nil){ t->linescap = 1024; t->lines = emallocz(t->linescap*sizeof(*t->lines), 1); t->nlines = 0; t->topline = 0; } frclear(t, 0); frinit(t, t->bodyr, display->defaultfont, screen, t->cols); } void textaddline(Text *t, uint sol) { if(t->nlines == t->linescap){ t->linescap *= 2; t->lines = erealloc(t->lines, t->linescap*sizeof(*t->lines)); } t->lines[t->nlines++] = sol; } void textaddrunes(Text *t, Rune *s) { Rune *rp; int len; len = runestrlen(s); while(len > t->textcap-t->textlen+1){ t->textcap *= 2; t->text = erealloc(t->text, t->textcap*sizeof(*t->text)); } runestrecpy(t->text+t->textlen, t->text+t->textcap, s); for(rp = t->text+t->textlen; *rp != L'\0'; rp++) if(*rp == L'\n') textaddline(t, rp+1-t->text); t->textlen += len; } void textresize(Text *t) { static char s[512]; snprint(s, sizeof(s), "%s/winname", t->wsys); if(gengetwindow(display, s, t->screen, t->_screen, Refnone) < 0) sysfatal("%s: %r", argv0); textinit(t); textdraw(t); } void textscroll(Text *t, Mousectl *mc) { uint pos, i; while(mc->buttons == 2){ t->topline = min(max(0, mc->xy.y-t->scrollr.min.y)*t->nlines/Dy(t->scrollr), t->nlines-1); textdraw(t); readmouse(mc); } while(mc->buttons == 1){ pos = frcharofpt(t, (Point){t->bodyr.min.x+1, mc->xy.y}); for(i = t->topline; t->lines[t->topline]+pos > t->lines[i]; i++){ if(i == t->nlines) break; } i -= t->topline; if(t->topline < i) t->topline = 0; else t->topline -= i; textdraw(t); readmouse(mc); } while(mc->buttons == 4){ pos = frcharofpt(t, (Point){t->bodyr.min.x+1, mc->xy.y}); for(i = t->topline; t->lines[t->topline]+pos > t->lines[i]; i++); t->topline = min(i, t->nlines-1); textdraw(t); readmouse(mc); } } void textmouse(Text *t, Mousectl *mc) { if(ptinrect(mc->xy, t->scrollr)){ textscroll(t, mc); return; } }