diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/cmd/abaco/main.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/cmd/abaco/main.c')
-rwxr-xr-x | sys/src/cmd/abaco/main.c | 433 |
1 files changed, 433 insertions, 0 deletions
diff --git a/sys/src/cmd/abaco/main.c b/sys/src/cmd/abaco/main.c new file mode 100755 index 000000000..b190e9f02 --- /dev/null +++ b/sys/src/cmd/abaco/main.c @@ -0,0 +1,433 @@ +#include <u.h> +#include <libc.h> +#include <draw.h> +#include <memdraw.h> +#include <thread.h> +#include <mouse.h> +#include <keyboard.h> +#include <cursor.h> +#include <frame.h> +#include <regexp.h> +#include <plumb.h> +#include <html.h> +#include "dat.h" +#include "fns.h" + +enum { + WPERCOL = 8, +}; +void mousethread(void *); +void keyboardthread(void *); +void iconinit(void); +void plumbproc(void*); + +Channel *cexit; +Channel *cplumb; +Mousectl *mousectl; + +char *fontnames[2] = { + "/lib/font/bit/lucidasans/unicode.8.font", + "/lib/font/bit/lucidasans/passwd.6.font", +}; + +int snarffd = -1; +int mainpid; +int plumbwebfd; +int plumbsendfd ; +char *webmountpt = "/mnt/web"; +char *charset = "iso-8859-1"; +int mainstacksize = STACK; + +void readpage(Column *, char *); +int shutdown(void *, char *); + +void +derror(Display *, char *s) +{ + error(s); +} + +static void +usage(void) +{ + fprint(2, "usage: %s [-c ncol] [-m mtpt] [-t charset] [url...]\n", + argv0); + exits("usage"); +} + +void +threadmain(int argc, char *argv[]) +{ + Column *c; + char buf[256]; + int i, ncol; + + rfork(RFENVG|RFNAMEG); + + ncol = 1; + ARGBEGIN{ + case 'c': + ncol = atoi(EARGF(usage())); + if(ncol <= 0) + usage(); + break; + case 'm': + webmountpt = EARGF(usage()); + break; + case 'p': + procstderr++; + break; + case 't': + charset = EARGF(usage()); + break; + default: + usage(); + break; + }ARGEND + + snprint(buf, sizeof(buf), "%s/ctl", webmountpt); + webctlfd = open(buf, ORDWR); + if(webctlfd < 0) + sysfatal("can't initialize webfs: %r"); + + snarffd = open("/dev/snarf", OREAD|OCEXEC); + + if(initdraw(derror, fontnames[0], "abaco") < 0) + sysfatal("can't open display: %r"); + memimageinit(); + iconinit(); + timerinit(); + initfontpaths(); + + cexit = chancreate(sizeof(int), 0); + crefresh = chancreate(sizeof(Page *), 0); + if(cexit==nil || crefresh==nil) + sysfatal("can't create initial channels: %r"); + + mousectl = initmouse(nil, screen); + if(mousectl == nil) + sysfatal("can't initialize mouse: %r"); + mouse = mousectl; + keyboardctl = initkeyboard(nil); + if(keyboardctl == nil) + sysfatal("can't initialize keyboard: %r"); + mainpid = getpid(); + plumbwebfd = plumbopen("web", OREAD|OCEXEC); + if(plumbwebfd >= 0){ + cplumb = chancreate(sizeof(Plumbmsg*), 0); + proccreate(plumbproc, nil, STACK); + } + plumbsendfd = plumbopen("send", OWRITE|OCEXEC); + + rowinit(&row, screen->clipr); + for(i=0; i<ncol; i++){ + c = rowadd(&row, nil, -1); + if(c==nil && i==0) + error("initializing columns"); + } + c = row.col[row.ncol-1]; + for(i=0; i<argc; i++) + if(i/WPERCOL >= row.ncol) + readpage(c, argv[i]); + else + readpage(row.col[i/WPERCOL], argv[i]); + flushimage(display, 1); + threadcreate(keyboardthread, nil, STACK); + threadcreate(mousethread, nil, STACK); + + threadnotify(shutdown, 1); + recvul(cexit); + threadexitsall(nil); +} + +void +readpage(Column *c, char *s) +{ + Window *w; + Runestr rs; + + w = coladd(c, nil, nil, -1); + bytetorunestr(s, &rs); + pageget(&w->page, &rs, nil, HGet, TRUE); + closerunestr(&rs); +} + +char *oknotes[] = { + "delete", + "hangup", + "kill", + "exit", + nil +}; + +int +shutdown(void*, char *msg) +{ + int i; + + for(i=0; oknotes[i]; i++) + if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0) + threadexitsall(msg); + print("abaco: %s\n", msg); +// abort(); + return 0; +} + +void +plumbproc(void *) +{ + Plumbmsg *m; + + threadsetname("plumbproc"); + for(;;){ + m = plumbrecv(plumbwebfd); + if(m == nil) + threadexits(nil); + sendp(cplumb, m); + } +} + +enum { KTimer, KKey, NKALT, }; + +void +keyboardthread(void *) +{ + Timer *timer; + Text *t; + Rune r; + + static Alt alts[NKALT+1]; + + alts[KTimer].c = nil; + alts[KTimer].v = nil; + alts[KTimer].op = CHANNOP; + alts[KKey].c = keyboardctl->c; + alts[KKey].v = &r; + alts[KKey].op = CHANRCV; + alts[NKALT].op = CHANEND; + + timer = nil; + threadsetname("keyboardthread"); + for(;;){ + switch(alt(alts)){ + case KTimer: + timerstop(timer); + alts[KTimer].c = nil; + alts[KTimer].op = CHANNOP; + break; + case KKey: + casekeyboard: + typetext = rowwhich(&row, mouse->xy, r, TRUE); + t = typetext; + if(t!=nil && t->col!=nil && + !(r==Kdown || r==Kleft || r==Kright)) + /* scrolling doesn't change activecol */ + activecol = t->col; + if(timer != nil) + timercancel(timer); + if(t!=nil){ + texttype(t, r); + timer = timerstart(500); + alts[KTimer].c = timer->c; + alts[KTimer].op = CHANRCV; + }else{ + timer = nil; + alts[KTimer].c = nil; + alts[KTimer].op = CHANNOP; + } + if(nbrecv(keyboardctl->c, &r) > 0) + goto casekeyboard; + flushimage(display, 1); + break; + } + } +} + +void +mousethread(void *) +{ + Plumbmsg *pm; + Mouse m; + Text *t; + int but; + enum { MResize, MMouse, MPlumb, MRefresh, NMALT }; + static Alt alts[NMALT+1]; + + threadsetname("mousethread"); + alts[MResize].c = mousectl->resizec; + alts[MResize].v = nil; + alts[MResize].op = CHANRCV; + alts[MMouse].c = mousectl->c; + alts[MMouse].v = &mousectl->Mouse; + alts[MMouse].op = CHANRCV; + alts[MPlumb].c = cplumb; + alts[MPlumb].v = ± + alts[MPlumb].op = CHANRCV; + alts[MRefresh].c = crefresh; + alts[MRefresh].v = nil; + alts[MRefresh].op = CHANRCV; + if(cplumb == nil) + alts[MPlumb].op = CHANNOP; + alts[NMALT].op = CHANEND; + + for(;;){ + qlock(&row); + flushrefresh(); + qunlock(&row); + flushimage(display, 1); + switch(alt(alts)){ + case MResize: + if(getwindow(display, Refnone) < 0) + error("resized"); + scrlresize(); + tmpresize(); + rowresize(&row, screen->clipr); + break; + case MPlumb: + plumblook(pm); + plumbfree(pm); + break; + case MRefresh: + break; + case MMouse: + m = mousectl->Mouse; + if(m.buttons == 0) + continue; + + qlock(&row); + but = 0; + if(m.buttons == 1) + but = 1; + else if(m.buttons == 2) + but = 2; + else if(m.buttons == 4) + but = 3; + + if(m.buttons & (8|16)){ + if(m.buttons & 8) + but = Kscrolloneup; + else + but = Kscrollonedown; + rowwhich(&row, m.xy, but, TRUE); + }else if(but){ + t = rowwhich(&row, m.xy, but, FALSE); + if(t) + textmouse(t, m.xy, but); + } + qunlock(&row); + break; + } + } +} + +Cursor boxcursor = { + {-7, -7}, + {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, + 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, + 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF, + 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, + {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, + 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, + 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, + 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00} +}; + +void +iconinit(void) +{ + Rectangle r; + + /* Green */ + tagcols[BACK] = allocimagemix(display, DPalegreen, DWhite); + if(tagcols[BACK] == nil) + error("allocimagemix"); + tagcols[HIGH] = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkgreen); + tagcols[BORD] = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedgreen); + tagcols[TEXT] = display->black; + tagcols[HTEXT] = display->black; + + /* Grey */ + textcols[BACK] = display->white; + textcols[HIGH] = eallocimage(display, Rect(0,0,1,1), CMAP8,1, 0xCCCCCCFF); + textcols[BORD] = display->black; + textcols[TEXT] = display->black; + textcols[HTEXT] = display->black; + + r = Rect(0, 0, Scrollsize+2, font->height+1); + button = eallocimage(display, r, screen->chan, 0, DNofill); + draw(button, r, tagcols[BACK], nil, r.min); + r.max.x -= 2; + border(button, r, 2, tagcols[BORD], ZP); + + r = button->r; + colbutton = eallocimage(display, r, screen->chan, 0, 0x00994CFF); + + but2col = eallocimage(display, Rect(0,0,1,2), screen->chan, 1, 0xAA0000FF); + but3col = eallocimage(display, Rect(0,0,1,2), screen->chan, 1, 0x444488FF); + + passfont = openfont(display, fontnames[1]); + if(passfont == nil) + error("openfont"); +} + +/* + * /dev/snarf updates when the file is closed, so we must open our own + * fd here rather than use snarffd + */ + +/* + * rio truncates large snarf buffers, so this avoids using the + * service if the string is huge + */ + +enum +{ + NSnarf = 1000, + MAXSNARF = 100*1024, +}; + +void +putsnarf(Runestr *rs) +{ + int fd, i, n; + + if(snarffd<0 || rs->nr==0) + return; + if(rs->nr > MAXSNARF) + return; + fd = open("/dev/snarf", OWRITE); + if(fd < 0) + return; + for(i=0; i<rs->nr; i+=n){ + n = rs->nr-i; + if(n > NSnarf) + n =NSnarf; + if(fprint(fd, "%.*S", n, rs->r) < 0) + break; + } + close(fd); +} + +void +getsnarf(Runestr *rs) +{ + int i, n, nb, nulls; + char *sn, buf[BUFSIZE]; + + if(snarffd < 0) + return; + sn = nil; + i = 0; + seek(snarffd, 0, 0); + while((n=read(snarffd, buf, sizeof(buf))) > 0){ + sn = erealloc(sn, i+n+1); + memmove(sn+i, buf, n); + i += n; + sn[i] = 0; + } + if(i > 0){ + rs->r = runemalloc(i+1); + cvttorunes(sn, i, rs->r, &nb, &rs->nr, &nulls); + free(sn); + } +} |