14 int verbose=0; /* -v flag causes html errors to appear in error log */
15 int defdisplay=1; /* is the default (initial) display visible? */
16 Panel *root; /* the whole display */
17 Panel *alt; /* the alternate display */
18 Panel *alttext; /* the alternate text window */
19 Panel *cmd; /* command entry */
20 Panel *curttl; /* label giving the title of the visible text */
21 Panel *cururl; /* label giving the url of the visible text */
22 Panel *list; /* list of previously acquired www pages */
23 Panel *msg; /* message display */
24 Panel *menu3; /* button 3 menu */
25 Mouse mouse; /* current mouse data */
26 char mothra[] = "mothra!";
43 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x07, 0xe0,
44 0x07, 0xe0, 0x07, 0xe0, 0x03, 0xc0, 0x0F, 0xF0,
45 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8,
46 0x0F, 0xF0, 0x1F, 0xF8, 0x3F, 0xFC, 0x3F, 0xFC,
48 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x04, 0x20,
49 0x04, 0x20, 0x06, 0x60, 0x02, 0x40, 0x0C, 0x30,
50 0x10, 0x08, 0x14, 0x08, 0x14, 0x28, 0x12, 0x28,
51 0x0A, 0x50, 0x16, 0x68, 0x20, 0x04, 0x3F, 0xFC,
55 0x0F, 0xBF, 0x0F, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF,
56 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,
57 0xFF, 0xFE, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF,
58 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
60 0x00, 0x0E, 0x07, 0x1F, 0x03, 0x17, 0x73, 0x6F,
61 0xFB, 0xCE, 0xDB, 0x8C, 0xDB, 0xC0, 0xFB, 0x6C,
62 0x77, 0xFC, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03,
63 0x94, 0xA6, 0x63, 0x3C, 0x63, 0x18, 0x94, 0x90
67 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0,
68 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x1F, 0xF0,
69 0x3F, 0xF0, 0x7F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
70 0xFB, 0xFF, 0xF3, 0xFF, 0x00, 0x00, 0x00, 0x00,
72 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0,
73 0x07, 0xE0, 0x01, 0xE0, 0x03, 0xE0, 0x07, 0x60,
74 0x0E, 0x60, 0x1C, 0x00, 0x38, 0x00, 0x71, 0xB6,
75 0x61, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
79 {0x00, 0x00, 0x60, 0x06, 0xf8, 0x1f, 0xfc, 0x3f,
80 0xfe, 0x7f, 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfe,
81 0x7f, 0xfe, 0x3f, 0xfc, 0x3f, 0xfc, 0x1f, 0xf8,
82 0x1f, 0xf8, 0x0e, 0x70, 0x0c, 0x30, 0x00, 0x00, },
83 {0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x58, 0x1a,
84 0x5c, 0x3a, 0x64, 0x26, 0x27, 0xe4, 0x37, 0xec,
85 0x37, 0xec, 0x17, 0xe8, 0x1b, 0xd8, 0x0e, 0x70,
86 0x0c, 0x30, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, }
88 char *mtpt="/mnt/web";
95 void docmd(Panel *, char *);
96 void doprev(Panel *, int, int);
99 void setcurrent(int, char *);
100 char *genwww(Panel *, int);
102 void dolink(Panel *, int, Rtext *);
117 static Www a[1+NWWW];
118 return &a[1+(index % NWWW)];
121 return wwwtop<NWWW ? wwwtop : NWWW;
124 void err(Display *, char *msg){
125 fprint(2, "err: %s (%r)\n", msg);
128 int subpanel(Panel *obj, Panel *subj){
130 if(obj==subj) return 1;
131 for(obj=obj->child;obj;obj=obj->next)
132 if(subpanel(obj, subj)) return 1;
136 * Make sure that the keyboard focus is on-screen, by adjusting it to
137 * be the cmd entry if necessary.
142 extern Panel *pl_kbfocus; /* this is a secret panel library name */
144 yoffs=text->r.min.y-plgetpostextview(text);
145 for(t=current->text;t;t=t->next) if(!eqrect(t->r, Rect(0,0,0,0))){
146 if(t->r.max.y+yoffs>text->r.max.y) break;
147 if(t->r.min.y+yoffs>=text->r.min.y
149 && subpanel(t->p, pl_kbfocus)) return;
155 void scrolltext(int dy, int whence)
159 s = plgetscroll(text);
168 s.pos.y = s.size.y+dy;
173 if(s.pos.y > s.size.y)
175 plsetscroll(text, s);
180 menu3=plmenu(0, 0, buttons, PACKN|FILLX, hit3);
181 root=plpopup(root, EXPAND, 0, 0, menu3);
182 p=plgroup(root, PACKN|FILLX);
183 msg=pllabel(p, PACKN|FILLX, mothra);
184 plplacelabel(msg, PLACEW);
185 pllabel(p, PACKW, "Go:");
186 cmd=plentry(p, PACKN|FILLX, 0, "", docmd);
187 p=plgroup(root, PACKN|FILLX);
188 bar=plscrollbar(p, PACKW);
189 list=pllist(p, PACKN|FILLX, genwww, 8, doprev);
190 plscroll(list, 0, bar);
191 p=plgroup(root, PACKN|FILLX);
192 pllabel(p, PACKW, "Title:");
193 curttl=pllabel(p, PACKE|EXPAND, "Initializing");
194 plplacelabel(curttl, PLACEW);
195 p=plgroup(root, PACKN|FILLX);
196 pllabel(p, PACKW, "Url:");
197 cururl=pllabel(p, PACKE|EXPAND, "---");
198 plplacelabel(cururl, PLACEW);
199 p=plgroup(root, PACKN|EXPAND);
200 bar=plscrollbar(p, PACKW);
201 text=pltextview(p, PACKE|EXPAND, Pt(0, 0), 0, dolink);
202 plscroll(text, 0, bar);
204 alt=plpopup(0, PACKE|EXPAND, 0, 0, menu3);
205 bar=plscrollbar(alt, PACKW);
206 alttext=pltextview(alt, PACKE|EXPAND, Pt(0, 0), 0, dolink);
207 plscroll(alttext, 0, bar);
210 void killcohort(void){
212 for(i=0;i!=3;i++){ /* It's a long way to the kitchen */
213 postnote(PNGROUP, cohort, "kill\n");
217 void catch(void*, char*){
220 void dienow(void*, char*){
223 int mkmfile(char *stem, int mode){
225 char filename[NNAME];
230 sprint(home, "%s/lib", henv);
231 f=create(home, OREAD, DMDIR|0777);
233 sprint(home, "%s/lib/mothra", henv);
234 f=create(home, OREAD, DMDIR|0777);
239 strcpy(home, "/tmp");
241 snprint(filename, sizeof(filename), "%s/%s", home, stem);
242 f=create(filename, OWRITE, mode);
244 f=create(stem, OWRITE, mode);
252 esetcursor(&mothcurs);
254 esetcursor(current->alldone ? 0 : &readingcurs);
257 void scrollto(char *tag);
259 void main(int argc, char *argv[]){
261 enum { Eplumb = 128 };
269 case 'd': debug++; break;
270 case 'v': verbose=1; break;
278 * so that we can stop all subprocesses with a note,
279 * and to isolate rendezvous from other processes
281 if(cohort = rfork(RFPROC|RFNOTEG|RFNAMEG|RFREND)){
293 fprint(2, "Usage: %s [-d] [-m mtpt] [url]\n", argv[0]);
297 if(url==0 || url[0]=='\0')
300 case 1: url=argv[0]; break;
302 errfile=mkmfile("mothra.err", 0666);
307 logfile=mkmfile("mothra.log", 0666|DMAPPEND);
308 if(initdraw(err, 0, "mothra") < 0)
309 sysfatal("initdraw: %r");
310 display->locking = 1;
311 chrwidth=stringwidth(font, "0");
312 pltabsize(chrwidth, 8*chrwidth);
313 einit(Emouse|Ekeyboard);
314 eplumb(Eplumb, "web");
315 if(pipe(kickpipe) < 0)
316 sysfatal("pipe: %r");
317 estart(0, kickpipe[0], 256);
318 plinit(screen->depth);
319 if(debug) notify(dienow);
321 hrule=allocimage(display, Rect(0, 0, 2048, 5), screen->chan, 0, DWhite);
323 fprint(2, "%s: can't allocimage!\n", argv[0]);
326 draw(hrule, Rect(0,1,1280,3), display->black, 0, ZP);
327 linespace=allocimage(display, Rect(0, 0, 2048, 5), screen->chan, 0, DWhite);
329 fprint(2, "%s: can't allocimage!\n", argv[0]);
332 bullet=allocimage(display, Rect(0,0,25, 8), screen->chan, 0, DWhite);
333 fillellipse(bullet, Pt(4,4), 3, 3, display->black, ZP);
336 strcpy(new->title, "See error message above");
337 plrtstr(&new->text, 0, 0, font, "See error message above", 0, 0);
341 unlockdisplay(display);
343 lockdisplay(display);
345 geturl(url, GET, 0, 1, 0);
347 if(logfile==-1) message("Can't open log file");
350 if(mouse.buttons==0 && current){
351 if(current->finished){
353 if(current->url->tag[0])
354 scrollto(current->url->tag);
361 else if(current->changed){
367 flushimage(display, 1);
368 unlockdisplay(display);
370 lockdisplay(display);
383 scrolltext(-text->size.y/4, 1);
386 scrolltext(-text->size.y/2, 1);
389 scrolltext(text->size.y/4, 1);
392 scrolltext(text->size.y/2, 1);
395 scrolltext(-text->size.y, 2);
401 plmouse(root, &mouse);
406 geturl(pm->data, GET, 0, 1, 0);
412 Cursor confirmcursor={
414 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
415 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
416 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
417 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
419 0x00, 0x0E, 0x07, 0x1F, 0x03, 0x17, 0x73, 0x6F,
420 0xFB, 0xCE, 0xDB, 0x8C, 0xDB, 0xC0, 0xFB, 0x6C,
421 0x77, 0xFC, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03,
422 0x94, 0xA6, 0x63, 0x3C, 0x63, 0x18, 0x94, 0x90,
426 esetcursor(&confirmcursor);
427 do down=emouse(); while(!down.buttons);
428 do up=emouse(); while(up.buttons);
430 return down.buttons==(1<<(b-1));
432 void message(char *s, ...){
433 static char buf[1024];
437 out = buf + vsnprint(buf, sizeof(buf), s, args);
440 plinitlabel(msg, PACKN|FILLX, buf);
441 if(defdisplay) pldraw(msg, screen);
443 void htmlerror(char *name, int line, char *m, ...){
444 static char buf[1024];
449 out=buf+snprint(buf, sizeof(buf), "%s: line %d: ", name, line);
450 out+=vsnprint(out, sizeof(buf)-(out-buf)-1, m, args);
453 fprint(2, "%s\n", buf);
456 void eresized(int new){
459 lockdisplay(display);
460 if(new && getwindow(display, Refnone) == -1) {
461 fprint(2, "getwindow: %r\n");
465 plinitlabel(curttl, PACKE|EXPAND, "---");
466 plinitlabel(cururl, PACKE|EXPAND, "---");
470 plinitlabel(curttl, PACKE|EXPAND, current->title);
471 plinitlabel(cururl, PACKE|EXPAND, current->url->fullname);
473 draw(screen, r, display->white, 0, ZP);
474 pldraw(root, screen);
475 unlockdisplay(display);
477 void *emalloc(int n){
481 fprint(2, "out of space\n");
486 void *emallocz(int n, int z){
494 char *genwww(Panel *, int index){
495 static char buf[1024];
501 snprint(buf, sizeof(buf), "%2d %s", i+1, www(i)->title);
505 void scrollto(char *tag){
508 if(current == nil || text == nil)
511 for(tp=current->text;tp;tp=tp->next){
513 if(ap && ap->name && strcmp(ap->name, tag)==0){
514 current->yoffs=tp->topy;
519 plsetpostextview(text, current->yoffs);
520 flushimage(display, 1);
524 * selected text should be a url.
526 void setcurrent(int index, char *tag){
530 if(new==current && (tag==0 || tag[0]==0)) return;
532 current->yoffs=plgetpostextview(text);
534 plinitlabel(curttl, PACKE|EXPAND, current->title);
535 if(defdisplay) pldraw(curttl, screen);
536 plinitlabel(cururl, PACKE|EXPAND, current->url->fullname);
537 if(defdisplay) pldraw(cururl, screen);
538 plinittextview(text, PACKE|EXPAND, Pt(0, 0), current->text, dolink);
543 do ++s; while(*s==' ' || *s=='\t');
546 void save(int ifd, char *name){
550 message("save: %s: %r", name);
553 ofd=create(name, OWRITE, 0666);
555 message("save: %s: %r", name);
558 switch(rfork(RFNOTEG|RFNAMEG|RFFDG|RFMEM|RFPROC|RFNOWAIT)){
560 message("Can't fork: %r");
567 snprint(buf, sizeof(buf), "-pid %d", getpid());
568 if(newwindow(buf) != -1){
569 close(2); open("/dev/cons", OWRITE);
570 if((cfd = open("/dev/label", OWRITE)) >= 0){
571 fprint(cfd, "save %s", name);
574 if((cfd = open("/dev/wctl", OWRITE)) >= 0){
575 fprint(cfd, "scroll\n");
578 fprint(2, "save %s...\n", name);
579 execl("/bin/tput", "tput", "-p", nil);
581 execl("/bin/cat", "cat", nil);
588 void screendump(char *name, int full){
591 fd=create(name, OWRITE, 0666);
593 message("can't create %s", name);
597 writeimage(fd, screen, 0);
599 if((b=allocimage(display, text->r, screen->chan, 0, DNofill)) == nil){
600 message("can't allocate image");
604 draw(b, b->r, screen, 0, b->r.min);
605 writeimage(fd, b, 0);
612 * convert a url into a local file name.
614 char *urltofile(Url *url){
618 if(url->fullname[0] || url->reltext[0])
622 if(slash = strrchr(name, '/'))
630 * user typed a command.
632 void docmd(Panel *p, char *s){
637 while(*s==' ' || *s=='\t') s++;
639 * Non-command does a get on the url
641 if(s[0]!='\0' && s[1]!='\0' && s[1]!=' ')
642 geturl(s, GET, 0, 0, 0);
643 else switch(c = s[0]){
645 message("Unknown command %s, type h for help", s);
649 if(*s=='\0' && selection)
657 s = urlstr(selection);
659 message("no url selected");
661 geturl(s, GET, 0, 0, 0);
666 doprev(nil, 1, wwwtop-atoi(s));
668 message("Usage: j index");
673 if(s==0 || *s=='\0'){
674 snprint(buf, sizeof(buf), "dump.bit");
675 if(eenter("Screendump to", buf, sizeof(buf), &mouse) <= 0)
679 screendump(s, c == 'W');
684 message("no url selected");
687 if(s==0 || *s=='\0'){
688 snprint(buf, sizeof(buf), "%s", urltofile(selection));
689 if(eenter("Save to", buf, sizeof(buf), &mouse) <= 0)
693 save(urlopen(selection, GET, 0), s);
698 plinitentry(cmd, EXPAND, 0, "", docmd);
699 if(defdisplay) pldraw(cmd, screen);
701 void hiturl(int buttons, char *url, int map){
703 case 1: geturl(url, GET, 0, 0, map); break;
704 case 2: selurl(url); break;
705 case 4: message("Button 3 hit on url can't happen!"); break;
709 * user selected from the list of available pages
711 void doprev(Panel *p, int buttons, int index){
714 if(index < 0 || index >= nwww())
718 case 1: setcurrent(i, 0); /* no break ... */
719 case 2: selurl(www(i)->url->fullname); break;
720 case 4: message("Button 3 hit on page can't happen!"); break;
725 * Follow an html link
727 void dolink(Panel *p, int buttons, Rtext *word){
728 char *file, mapurl[NNAME];
734 if(a == nil || a->image == nil && a->link == nil)
737 hiturl(buttons, a->image ? a->image : a->link, 0);
739 yoffs=plgetpostextview(p);
740 coord=subpt(subpt(mouse.xy, word->r.min), p->r.min);
741 snprint(mapurl, sizeof(mapurl), "%s?%d,%d", a->link, coord.x, coord.y+yoffs);
742 hiturl(buttons, mapurl, 1);
744 hiturl(buttons, a->link ? a->link : a->image, 0);
747 void filter(char *cmd, int fd){
748 switch(rfork(RFFDG|RFPROC|RFMEM|RFNOWAIT)){
750 message("Can't fork!");
756 execl("/bin/rc", "rc", "-c", cmd, 0);
761 void gettext(Www *w, int fd, int type){
762 switch(rfork(RFFDG|RFPROC|RFMEM|RFNOWAIT)){
764 message("Can't fork, please wait");
768 plrdhtml(w->url->fullname, fd, w);
770 plrdplain(w->url->fullname, fd, w);
776 void freetext(Rtext *t){
781 for(; t!=0; t = t->next){
796 int fileurlopen(Url *url){
797 char *rel, *base, *x;
801 if(cistrncmp(url->basename, "file:", 5) == 0)
802 base = url->basename+5;
803 if(cistrncmp(url->reltext, "file:", 5) == 0)
804 rel = url->reltext+5;
805 if(rel == nil && base == nil)
809 if(base && base[0] == '/' && rel[0] != '/'){
810 if(x = strrchr(base, '/'))
812 snprint(url->fullname, sizeof(url->fullname), "%s/%s", base, rel);
815 snprint(url->fullname, sizeof(url->fullname), "%s", rel);
817 if(x = strrchr(url->fullname, '#')){
819 strncpy(url->tag, x, sizeof(url->tag));
821 fd = open(cleanname(url->fullname), OREAD);
824 memset(url->fullname, 0, sizeof(url->fullname));
825 strcpy(url->fullname, "file:");
826 fd2path(fd, url->fullname+5, sizeof(url->fullname)-6);
830 int readstr(char *buf, int nbuf, char *base, char *name){
835 snprint(path, sizeof path, "%s/%s", base, name);
836 if((fd = open(path, OREAD)) >= 0){
837 if((n = read(fd, buf, nbuf-1)) < 0)
845 int urlopen(Url *url, int method, char *body){
846 int conn, ctlfd, fd, n;
847 char buf[1024+1], *p;
849 if(debug) fprint(2, "urlopen %s (%s)\n", url->reltext, url->basename);
852 if((fd = fileurlopen(url)) >= 0)
854 snprint(buf, sizeof buf, "%s/clone", mtpt);
855 if((ctlfd = open(buf, ORDWR)) < 0)
857 if((n = read(ctlfd, buf, sizeof buf-1)) <= 0){
863 if(url->basename[0]){
864 n = snprint(buf, sizeof buf, "baseurl %s", url->basename);
865 write(ctlfd, buf, n);
867 n = snprint(buf, sizeof buf, "url %s", url->reltext);
868 if(write(ctlfd, buf, n) != n){
873 if(method == POST && body){
874 snprint(buf, sizeof buf, "%s/%d/postbody", mtpt, conn);
875 if((fd = open(buf, OWRITE)) < 0)
878 if(write(fd, body, n) != n){
884 snprint(buf, sizeof buf, "%s/%d/body", mtpt, conn);
885 if((fd = open(buf, OREAD)) < 0)
887 snprint(buf, sizeof buf, "%s/%d/parsed", mtpt, conn);
888 readstr(url->fullname, sizeof(url->fullname), buf, "url");
889 readstr(url->tag, sizeof(url->tag), buf, "fragment");
894 int pipeline(char *cmd, int fd)
901 werrstr("pipeline for %s failed: %r", cmd);
914 execl("/bin/rc", "rc", "-c", cmd, 0);
925 return url->fullname;
930 void selurl(char *urlname){
932 seturl(&url, urlname, current?
933 current->url->fullname :
936 message("selected: %s", urlstr(selection));
938 void seturl(Url *url, char *urlname, char *base){
939 strncpy(url->reltext, urlname, sizeof(url->reltext));
940 strncpy(url->basename, base, sizeof(url->basename));
941 url->fullname[0] = 0;
945 Url *copyurl(Url *u){
947 v=emalloc(sizeof(Url));
951 void freeurl(Url *u){
952 if(u!=&defurl && u!=&badurl)
957 * get the file at the given url
959 void geturl(char *urlname, int method, char *body, int plumb, int map){
960 int i, fd, typ, pfd[2];
974 message("getting %s", selection->reltext);
975 esetcursor(&patientcurs);
977 if((fd=urlopen(selection, method, body)) < 0){
982 message("getting %s", selection->fullname);
983 if(mothmode && !plumb)
988 fd=pipeline("/bin/gunzip", fd);
992 fd=pipeline("/bin/uncompress", fd);
999 message("unknown file type");
1003 snprint(cmd, sizeof(cmd), "%s", urltofile(selection));
1004 if(eenter("Save to", cmd, sizeof(cmd), &mouse) <= 0){
1011 fd = pipeline("/bin/uhtml", fd);
1014 for(i=wwwtop-1; i>=0 && i!=(wwwtop-NWWW-1); i--){
1016 n += countpix(w->pix);
1017 if(n < NPIXMB*1024*1024)
1019 if(!w->finished && !w->alldone)
1021 for(t=w->text; t; t=t->next)
1027 w = www(i = wwwtop++);
1029 /* wait for the reader to finish the document */
1030 while(!w->finished && !w->alldone){
1031 unlockdisplay(display);
1033 lockdisplay(display);
1039 memset(w, 0, sizeof(*w));
1042 w->url=copyurl(current->url);
1044 w->url=copyurl(selection);
1047 gettext(w, fd, typ);
1048 plinitlist(list, PACKN|FILLX, genwww, 8, doprev);
1049 if(defdisplay) pldraw(list, screen);
1050 setcurrent(i, selection->tag);
1053 if(rfork(RFFDG|RFNOTEG|RFPROC|RFNAMEG|RFNOWAIT) == 0){
1054 snprint(cmd, sizeof(cmd), "-pid %d", getpid());
1055 if(newwindow(cmd) != -1){
1056 close(1); open("/dev/cons", OWRITE);
1057 print("reading gif...\n");
1068 filter("page -w", fd);
1075 void updtext(Www *w){
1078 for(t=w->text;t;t=t->next){
1086 w->yoffs=plgetpostextview(text);
1087 plinittextview(text, PACKE|EXPAND, Pt(0, 0), w->text, dolink);
1088 plsetpostextview(text, w->yoffs);
1089 pldraw(root, screen);
1091 void update(Www *w){
1093 write(kickpipe[1], "C", 1);
1095 void finish(Www *w){
1097 write(kickpipe[1], "F", 1);
1101 mothon(Www *w, int on)
1106 if(current == nil || mothmode == on)
1109 message("moth mode!");
1113 * insert or remove artificial links to the href for
1114 * images that are also links
1116 for(t=w->text;t;t=t->next){
1118 if(a == nil || a->image == nil || a->link == nil)
1123 ap=mallocz(sizeof(Action), 1);
1124 ap->link = strdup(a->link);
1125 plrtstr(&t->next, 0, 0, t->font, strdup("->"), 1, ap);
1137 void snarf(Panel *p){
1139 if((fd=open("/dev/snarf", OWRITE|OTRUNC))>=0){
1140 fprint(fd, "%s", urlstr(selection));
1144 void paste(Panel *p){
1147 if((fd=open("/dev/snarf", OREAD))<0)
1149 strncpy(buf, plentryval(p), sizeof(buf));
1151 n=read(fd, buf+len, sizeof(buf)-len-1);
1154 plinitentry(cmd, PACKE|EXPAND, 0, buf, docmd);
1155 pldraw(cmd, screen);
1159 void hit3(int button, int item){
1170 current->yoffs=plgetpostextview(text);
1174 defdisplay=!defdisplay;
1175 plpack(root, screen->r);
1176 plinittextview(text, PACKE|EXPAND, Pt(0, 0), current->text, dolink);
1177 plsetpostextview(text, current->yoffs);
1178 pldraw(root, screen);
1181 mothon(current, !mothmode);
1190 snprint(name, sizeof(name), "%s/hit.html", home);
1191 fd=open(name, OWRITE);
1193 fd=create(name, OWRITE, 0666);
1195 message("can't open %s", name);
1198 fprint(fd, "<html><head><title>Hit List</title></head>\n");
1199 fprint(fd, "<body><h1>Hit list</h1>\n");
1202 fprint(fd, "<p><a href=\"%s\">%s</a>\n", urlstr(selection), urlstr(selection));
1206 snprint(name, sizeof(name), "file:%s/hit.html", home);
1207 geturl(name, GET, 0, 1, 0);
1211 draw(screen, screen->r, display->white, 0, ZP);