ref: 0adb432869b58347d874cd8961584817cd478c26
dir: /scrolldemo/scrolldemo.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <cursor.h> #include <thread.h> #include <mouse.h> #include <keyboard.h> #include <frame.h> #include "../scroll.h" typedef struct Text Text; struct Text { Frame; Scroll; Rune *text; uint org, len, cap; }; Image *cols[NCOL]; char buf[32000]; Rune lorem[32000]; enum { MOUSE, KEYBD, RESIZE, NCHAN, }; void textdraw(Text *t) { draw(screen, screen->r, cols[BACK], nil, ZP); frinsert(t, t->text+t->org, t->text+t->len, 0); scrollpos(t, t->org, t->org+t->Frame.nchars, t->len); flushimage(display, 1); } void textinit(Text *t) { Rectangle r; if(t->text == nil){ t->cap = 8192; t->text = mallocz(t->cap*sizeof(*t->text), 1); t->len = 0; } r = scrollinit(t, screen->r, screen, cols); frclear(t, 0); frinit(t, r, display->defaultfont, screen, cols); } void textaddrunes(Text *t, Rune *s) { int len; len = runestrlen(s); while(len > t->cap-t->len+1){ t->cap *= 2; t->text = realloc(t->text, t->cap*sizeof(*t->text)); } runestrecpy(t->text+t->len, t->text+t->cap, s); t->len += len; } void textresize(Text *t) { static char s[512]; if(getwindow(display, Refnone) < 0) sysfatal("%s: %r", argv0); textinit(t); textdraw(t); } uint bol(Text *t, uint org) { for(;org > 0; org--){ if(t->text[org-1] == L'\n') return org; } return org; } void textscroll(Text *t, Mousectl *mc) { while(mc->buttons == 2){ t->org = bol(t, scrollscr(t, mc)); textdraw(t); readmouse(mc); } if(mc->buttons == 1 || mc->buttons == 8 || mc->buttons == 4 || mc->buttons == 16){ t->org = bol(t, scrollscr(t, mc)); textdraw(t); } } void textmouse(Text *t, Mousectl *mc) { if(scrollactive(t, mc)) textscroll(t, mc); } void threadmain(int argc, char **argv) { Text *text; Keyboardctl *kc; Mousectl *mc; Rune r, *rs; char *s; int len; ARGBEGIN{ default: sysfatal("foo"); }ARGEND len = readn(0, buf, sizeof(buf)); buf[len] = '\0'; for(s = buf, rs = lorem; *s != '\0'; s+=len, rs++) len = chartorune(rs, s); *rs = L'\0'; if(initdraw(nil, nil, "guitest") < 0) sysfatal("initdraw: %r"); cols[BACK] = allocimagemix(display, DPurpleblue, DWhite); cols[HIGH] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkyellow); cols[BORD] = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue); cols[TEXT] = display->black; cols[HTEXT] = display->black; text = mallocz(sizeof(*text), 1); textinit(text); textaddrunes(text, lorem); lorem[0] = L'\0'; textdraw(text); flushimage(display, 1); if((mc = initmouse(nil, screen)) == nil) sysfatal("initmouse failed: %r"); if((kc = initkeyboard(nil)) == nil) sysfatal("initkeyboard failed: %r"); Alt a[NCHAN+1] = { [MOUSE] {mc->c, nil, CHANRCV}, [KEYBD] {kc->c, &r, CHANRCV}, [RESIZE] {mc->resizec, nil, CHANRCV}, [NCHAN] {nil, nil, CHANEND}, }; for(;;)switch(alt(a)){ default: break; case KEYBD: if(r == Kdel) goto End; break; case MOUSE: textmouse(text, mc); break; case RESIZE: textresize(text); break; } End: threadexitsall(0); }