19 void mousethread(void *);
20 void keyboardthread(void *);
22 void plumbproc(void*);
28 char *fontnames[2] = {
29 "/lib/font/bit/lucidasans/unicode.8.font",
30 "/lib/font/bit/lucidasans/passwd.6.font",
37 char *webmountpt = "/mnt/web";
38 char *charset = "iso-8859-1";
39 int mainstacksize = STACK;
41 void readpage(Column *, char *);
42 int shutdown(void *, char *);
45 derror(Display *, char *s)
53 fprint(2, "usage: %s [-c ncol] [-m mtpt] [-t charset] [url...]\n",
59 threadmain(int argc, char *argv[])
65 rfork(RFENVG|RFNAMEG);
70 ncol = atoi(EARGF(usage()));
75 webmountpt = EARGF(usage());
81 charset = EARGF(usage());
88 snprint(buf, sizeof(buf), "%s/ctl", webmountpt);
89 webctlfd = open(buf, ORDWR);
91 sysfatal("can't initialize webfs: %r");
93 snarffd = open("/dev/snarf", OREAD|OCEXEC);
95 if(initdraw(derror, fontnames[0], "abaco") < 0)
96 sysfatal("can't open display: %r");
102 cexit = chancreate(sizeof(int), 0);
103 crefresh = chancreate(sizeof(Page *), 0);
104 if(cexit==nil || crefresh==nil)
105 sysfatal("can't create initial channels: %r");
107 mousectl = initmouse(nil, screen);
109 sysfatal("can't initialize mouse: %r");
111 keyboardctl = initkeyboard(nil);
112 if(keyboardctl == nil)
113 sysfatal("can't initialize keyboard: %r");
115 plumbwebfd = plumbopen("web", OREAD|OCEXEC);
117 cplumb = chancreate(sizeof(Plumbmsg*), 0);
118 proccreate(plumbproc, nil, STACK);
120 plumbsendfd = plumbopen("send", OWRITE|OCEXEC);
122 rowinit(&row, screen->clipr);
123 for(i=0; i<ncol; i++){
124 c = rowadd(&row, nil, -1);
126 error("initializing columns");
128 c = row.col[row.ncol-1];
129 for(i=0; i<argc; i++)
130 if(i/WPERCOL >= row.ncol)
131 readpage(c, argv[i]);
133 readpage(row.col[i/WPERCOL], argv[i]);
134 flushimage(display, 1);
135 threadcreate(keyboardthread, nil, STACK);
136 threadcreate(mousethread, nil, STACK);
138 threadnotify(shutdown, 1);
144 readpage(Column *c, char *s)
149 w = coladd(c, nil, nil, -1);
150 bytetorunestr(s, &rs);
151 pageget(&w->page, &rs, nil, HGet, TRUE);
164 shutdown(void*, char *msg)
168 for(i=0; oknotes[i]; i++)
169 if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0)
171 print("abaco: %s\n", msg);
181 threadsetname("plumbproc");
183 m = plumbrecv(plumbwebfd);
190 enum { KTimer, KKey, NKALT, };
193 keyboardthread(void *)
199 static Alt alts[NKALT+1];
201 alts[KTimer].c = nil;
202 alts[KTimer].v = nil;
203 alts[KTimer].op = CHANNOP;
204 alts[KKey].c = keyboardctl->c;
206 alts[KKey].op = CHANRCV;
207 alts[NKALT].op = CHANEND;
210 threadsetname("keyboardthread");
215 alts[KTimer].c = nil;
216 alts[KTimer].op = CHANNOP;
220 typetext = rowwhich(&row, mouse->xy, r, TRUE);
222 if(t!=nil && t->col!=nil &&
223 !(r==Kdown || r==Kleft || r==Kright))
224 /* scrolling doesn't change activecol */
230 timer = timerstart(500);
231 alts[KTimer].c = timer->c;
232 alts[KTimer].op = CHANRCV;
235 alts[KTimer].c = nil;
236 alts[KTimer].op = CHANNOP;
238 if(nbrecv(keyboardctl->c, &r) > 0)
240 flushimage(display, 1);
253 enum { MResize, MMouse, MPlumb, MRefresh, NMALT };
254 static Alt alts[NMALT+1];
256 threadsetname("mousethread");
257 alts[MResize].c = mousectl->resizec;
258 alts[MResize].v = nil;
259 alts[MResize].op = CHANRCV;
260 alts[MMouse].c = mousectl->c;
261 alts[MMouse].v = &mousectl->Mouse;
262 alts[MMouse].op = CHANRCV;
263 alts[MPlumb].c = cplumb;
264 alts[MPlumb].v = ±
265 alts[MPlumb].op = CHANRCV;
266 alts[MRefresh].c = crefresh;
267 alts[MRefresh].v = nil;
268 alts[MRefresh].op = CHANRCV;
270 alts[MPlumb].op = CHANNOP;
271 alts[NMALT].op = CHANEND;
277 flushimage(display, 1);
280 if(getwindow(display, Refnone) < 0)
284 rowresize(&row, screen->clipr);
301 else if(m.buttons == 2)
303 else if(m.buttons == 4)
306 if(m.buttons & (8|16)){
310 but = Kscrollonedown;
311 rowwhich(&row, m.xy, but, TRUE);
313 t = rowwhich(&row, m.xy, but, FALSE);
315 textmouse(t, m.xy, but);
325 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
326 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F,
327 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF,
328 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
329 {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE,
330 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
331 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
332 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00}
341 tagcols[BACK] = allocimagemix(display, DPalegreen, DWhite);
342 if(tagcols[BACK] == nil)
343 error("allocimagemix");
344 tagcols[HIGH] = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkgreen);
345 tagcols[BORD] = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedgreen);
346 tagcols[TEXT] = display->black;
347 tagcols[HTEXT] = display->black;
350 textcols[BACK] = display->white;
351 textcols[HIGH] = eallocimage(display, Rect(0,0,1,1), CMAP8,1, 0xCCCCCCFF);
352 textcols[BORD] = display->black;
353 textcols[TEXT] = display->black;
354 textcols[HTEXT] = display->black;
356 r = Rect(0, 0, Scrollsize+2, font->height+1);
357 button = eallocimage(display, r, screen->chan, 0, DNofill);
358 draw(button, r, tagcols[BACK], nil, r.min);
360 border(button, r, 2, tagcols[BORD], ZP);
363 colbutton = eallocimage(display, r, screen->chan, 0, 0x00994CFF);
365 but2col = eallocimage(display, Rect(0,0,1,2), screen->chan, 1, 0xAA0000FF);
366 but3col = eallocimage(display, Rect(0,0,1,2), screen->chan, 1, 0x444488FF);
368 passfont = openfont(display, fontnames[1]);
374 * /dev/snarf updates when the file is closed, so we must open our own
375 * fd here rather than use snarffd
379 * rio truncates large snarf buffers, so this avoids using the
380 * service if the string is huge
390 putsnarf(Runestr *rs)
394 if(snarffd<0 || rs->nr==0)
396 if(rs->nr > MAXSNARF)
398 fd = open("/dev/snarf", OWRITE);
401 for(i=0; i<rs->nr; i+=n){
405 if(fprint(fd, "%.*S", n, rs->r) < 0)
412 getsnarf(Runestr *rs)
415 char *sn, buf[BUFSIZE];
422 while((n=read(snarffd, buf, sizeof(buf))) > 0){
423 sn = erealloc(sn, i+n+1);
424 memmove(sn+i, buf, n);
429 rs->r = runemalloc(i+1);
430 cvttorunes(sn, i, rs->r, &nb, &rs->nr, &nulls);