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] [-f font] [url...]\n",
59 threadmain(int argc, char *argv[])
66 rfork(RFENVG|RFNAMEG);
71 ncol = atoi(EARGF(usage()));
76 webmountpt = EARGF(usage());
82 charset = EARGF(usage());
85 tfnt = EARGF(usage());
91 snprint(buf, sizeof(buf), "%s/ctl", webmountpt);
92 webctlfd = open(buf, ORDWR);
94 sysfatal("can't initialize webfs: %r");
96 snarffd = open("/dev/snarf", OREAD|OCEXEC);
99 tfnt = getenv("font");
104 if(initdraw(derror, fontnames[0], "abaco") < 0)
105 sysfatal("can't open display: %r");
111 cexit = chancreate(sizeof(int), 0);
112 crefresh = chancreate(sizeof(Page *), 0);
113 if(cexit==nil || crefresh==nil)
114 sysfatal("can't create initial channels: %r");
116 mousectl = initmouse(nil, screen);
118 sysfatal("can't initialize mouse: %r");
120 keyboardctl = initkeyboard(nil);
121 if(keyboardctl == nil)
122 sysfatal("can't initialize keyboard: %r");
124 plumbwebfd = plumbopen("web", OREAD|OCEXEC);
126 cplumb = chancreate(sizeof(Plumbmsg*), 0);
127 proccreate(plumbproc, nil, STACK);
129 plumbsendfd = plumbopen("send", OWRITE|OCEXEC);
131 rowinit(&row, screen->clipr);
132 for(i=0; i<ncol; i++){
133 c = rowadd(&row, nil, -1);
135 error("initializing columns");
137 c = row.col[row.ncol-1];
138 for(i=0; i<argc; i++)
139 if(i/WPERCOL >= row.ncol)
140 readpage(c, argv[i]);
142 readpage(row.col[i/WPERCOL], argv[i]);
143 flushimage(display, 1);
144 threadcreate(keyboardthread, nil, STACK);
145 threadcreate(mousethread, nil, STACK);
147 threadnotify(shutdown, 1);
153 readpage(Column *c, char *s)
158 w = coladd(c, nil, nil, -1);
159 bytetorunestr(s, &rs);
160 pageget(&w->page, &rs, nil, HGet, TRUE);
173 shutdown(void*, char *msg)
177 for(i=0; oknotes[i]; i++)
178 if(strncmp(oknotes[i], msg, strlen(oknotes[i])) == 0)
180 print("abaco: %s\n", msg);
190 threadsetname("plumbproc");
192 m = plumbrecv(plumbwebfd);
199 enum { KTimer, KKey, NKALT, };
202 keyboardthread(void *)
208 static Alt alts[NKALT+1];
210 alts[KTimer].c = nil;
211 alts[KTimer].v = nil;
212 alts[KTimer].op = CHANNOP;
213 alts[KKey].c = keyboardctl->c;
215 alts[KKey].op = CHANRCV;
216 alts[NKALT].op = CHANEND;
219 threadsetname("keyboardthread");
224 alts[KTimer].c = nil;
225 alts[KTimer].op = CHANNOP;
229 typetext = rowwhich(&row, mouse->xy, r, TRUE);
231 if(t!=nil && t->col!=nil &&
232 !(r==Kdown || r==Kleft || r==Kright))
233 /* scrolling doesn't change activecol */
239 timer = timerstart(500);
240 alts[KTimer].c = timer->c;
241 alts[KTimer].op = CHANRCV;
244 alts[KTimer].c = nil;
245 alts[KTimer].op = CHANNOP;
247 if(nbrecv(keyboardctl->c, &r) > 0)
249 flushimage(display, 1);
262 enum { MResize, MMouse, MPlumb, MRefresh, NMALT };
263 static Alt alts[NMALT+1];
265 threadsetname("mousethread");
266 alts[MResize].c = mousectl->resizec;
267 alts[MResize].v = nil;
268 alts[MResize].op = CHANRCV;
269 alts[MMouse].c = mousectl->c;
270 alts[MMouse].v = &mousectl->Mouse;
271 alts[MMouse].op = CHANRCV;
272 alts[MPlumb].c = cplumb;
273 alts[MPlumb].v = ±
274 alts[MPlumb].op = CHANRCV;
275 alts[MRefresh].c = crefresh;
276 alts[MRefresh].v = nil;
277 alts[MRefresh].op = CHANRCV;
279 alts[MPlumb].op = CHANNOP;
280 alts[NMALT].op = CHANEND;
286 flushimage(display, 1);
289 if(getwindow(display, Refnone) < 0)
293 rowresize(&row, screen->clipr);
310 else if(m.buttons == 2)
312 else if(m.buttons == 4)
315 if(m.buttons & (8|16)){
319 but = Kscrollonedown;
320 rowwhich(&row, m.xy, but, TRUE);
322 t = rowwhich(&row, m.xy, but, FALSE);
324 textmouse(t, m.xy, but);
334 {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
335 0xFF, 0xFF, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F,
336 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xFF, 0xFF,
337 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF},
338 {0x00, 0x00, 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE,
339 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
340 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E, 0x70, 0x0E,
341 0x7F, 0xFE, 0x7F, 0xFE, 0x7F, 0xFE, 0x00, 0x00}
350 tagcols[BACK] = allocimagemix(display, DPalegreen, DWhite);
351 if(tagcols[BACK] == nil)
352 error("allocimagemix");
353 tagcols[HIGH] = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, DDarkgreen);
354 tagcols[BORD] = eallocimage(display, Rect(0,0,1,1), screen->chan, 1, DMedgreen);
355 tagcols[TEXT] = display->black;
356 tagcols[HTEXT] = display->black;
359 textcols[BACK] = display->white;
360 textcols[HIGH] = eallocimage(display, Rect(0,0,1,1), CMAP8,1, 0xCCCCCCFF);
361 textcols[BORD] = display->black;
362 textcols[TEXT] = display->black;
363 textcols[HTEXT] = display->black;
365 r = Rect(0, 0, Scrollsize+2, font->height+1);
366 button = eallocimage(display, r, screen->chan, 0, DNofill);
367 draw(button, r, tagcols[BACK], nil, r.min);
369 border(button, r, 2, tagcols[BORD], ZP);
372 colbutton = eallocimage(display, r, screen->chan, 0, 0x00994CFF);
374 but2col = eallocimage(display, Rect(0,0,1,2), screen->chan, 1, 0xAA0000FF);
375 but3col = eallocimage(display, Rect(0,0,1,2), screen->chan, 1, 0x444488FF);
377 passfont = openfont(display, fontnames[1]);
383 * /dev/snarf updates when the file is closed, so we must open our own
384 * fd here rather than use snarffd
388 * rio truncates large snarf buffers, so this avoids using the
389 * service if the string is huge
399 putsnarf(Runestr *rs)
403 if(snarffd<0 || rs->nr==0)
405 if(rs->nr > MAXSNARF)
407 fd = open("/dev/snarf", OWRITE);
410 for(i=0; i<rs->nr; i+=n){
414 if(fprint(fd, "%.*S", n, rs->r) < 0)
421 getsnarf(Runestr *rs)
424 char *sn, buf[BUFSIZE];
431 while((n=read(snarffd, buf, sizeof(buf))) > 0){
432 sn = erealloc(sn, i+n+1);
433 memmove(sn+i, buf, n);
438 rs->r = runemalloc(i+1);
439 cvttorunes(sn, i, rs->r, &nb, &rs->nr, &nulls);