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!";
29 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x07, 0xe0,
30 0x07, 0xe0, 0x07, 0xe0, 0x03, 0xc0, 0x0F, 0xF0,
31 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8, 0x1F, 0xF8,
32 0x0F, 0xF0, 0x1F, 0xF8, 0x3F, 0xFC, 0x3F, 0xFC,
34 0x01, 0x80, 0x03, 0xC0, 0x07, 0xE0, 0x04, 0x20,
35 0x04, 0x20, 0x06, 0x60, 0x02, 0x40, 0x0C, 0x30,
36 0x10, 0x08, 0x14, 0x08, 0x14, 0x28, 0x12, 0x28,
37 0x0A, 0x50, 0x16, 0x68, 0x20, 0x04, 0x3F, 0xFC,
41 0x0F, 0xBF, 0x0F, 0xBF, 0xFF, 0xFF, 0xFF, 0xFF,
42 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFE, 0xFF, 0xFE,
43 0xFF, 0xFE, 0xFF, 0xFF, 0x00, 0x03, 0xFF, 0xFF,
44 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFE, 0xFF, 0xFC,
46 0x00, 0x0E, 0x07, 0x1F, 0x03, 0x17, 0x73, 0x6F,
47 0xFB, 0xCE, 0xDB, 0x8C, 0xDB, 0xC0, 0xFB, 0x6C,
48 0x77, 0xFC, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03,
49 0x94, 0xA6, 0x63, 0x3C, 0x63, 0x18, 0x94, 0x90
53 0x00, 0x00, 0x00, 0x00, 0x0F, 0xF0, 0x0F, 0xF0,
54 0x0F, 0xF0, 0x0F, 0xF0, 0x0F, 0xF0, 0x1F, 0xF0,
55 0x3F, 0xF0, 0x7F, 0xF0, 0xFF, 0xFF, 0xFF, 0xFF,
56 0xFB, 0xFF, 0xF3, 0xFF, 0x00, 0x00, 0x00, 0x00,
58 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0,
59 0x07, 0xE0, 0x01, 0xE0, 0x03, 0xE0, 0x07, 0x60,
60 0x0E, 0x60, 0x1C, 0x00, 0x38, 0x00, 0x71, 0xB6,
61 0x61, 0xB6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
65 {0x00, 0x00, 0x60, 0x06, 0xf8, 0x1f, 0xfc, 0x3f,
66 0xfe, 0x7f, 0xff, 0xff, 0x7f, 0xfe, 0x7f, 0xfe,
67 0x7f, 0xfe, 0x3f, 0xfc, 0x3f, 0xfc, 0x1f, 0xf8,
68 0x1f, 0xf8, 0x0e, 0x70, 0x0c, 0x30, 0x00, 0x00, },
69 {0x00, 0x00, 0x00, 0x00, 0x60, 0x06, 0x58, 0x1a,
70 0x5c, 0x3a, 0x64, 0x26, 0x27, 0xe4, 0x37, 0xec,
71 0x37, 0xec, 0x17, 0xe8, 0x1b, 0xd8, 0x0e, 0x70,
72 0x0c, 0x30, 0x04, 0x20, 0x00, 0x00, 0x00, 0x00, }
74 char *mtpt="/mnt/web";
81 void docmd(Panel *, char *);
82 void doprev(Panel *, int, int);
85 void setcurrent(int, char *);
86 char *genwww(Panel *, int);
88 void dolink(Panel *, int, Rtext *);
104 return &a[index % NWWW];
107 return wwwtop<NWWW ? wwwtop : NWWW;
110 int subpanel(Panel *obj, Panel *subj){
112 if(obj==subj) return 1;
113 for(obj=obj->child;obj;obj=obj->next)
114 if(subpanel(obj, subj)) return 1;
118 * Make sure that the keyboard focus is on-screen, by adjusting it to
119 * be the cmd entry if necessary.
124 extern Panel *pl_kbfocus; /* this is a secret panel library name */
126 yoffs=text->r.min.y-plgetpostextview(text);
127 for(t=current->text;t;t=t->next) if(!eqrect(t->r, Rect(0,0,0,0))){
128 if(t->r.max.y+yoffs>text->r.max.y) break;
129 if(t->r.min.y+yoffs>=text->r.min.y
131 && subpanel(t->p, pl_kbfocus)) return;
137 void scrolltext(int dy, int whence)
141 s = plgetscroll(text);
150 s.pos.y = s.size.y+dy;
155 if(s.pos.y > s.size.y)
157 plsetscroll(text, s);
162 menu3=plmenu(0, 0, buttons, PACKN|FILLX, hit3);
163 root=plpopup(root, EXPAND, 0, 0, menu3);
164 p=plgroup(root, PACKN|FILLX);
165 msg=pllabel(p, PACKN|FILLX, mothra);
166 plplacelabel(msg, PLACEW);
167 pllabel(p, PACKW, "Go:");
168 cmd=plentry(p, PACKN|FILLX, 0, "", docmd);
169 p=plgroup(root, PACKN|FILLX);
170 bar=plscrollbar(p, PACKW);
171 list=pllist(p, PACKN|FILLX, genwww, 8, doprev);
172 plscroll(list, 0, bar);
173 p=plgroup(root, PACKN|FILLX);
174 pllabel(p, PACKW, "Title:");
175 curttl=pllabel(p, PACKE|EXPAND, "Initializing");
176 plplacelabel(curttl, PLACEW);
177 p=plgroup(root, PACKN|FILLX);
178 pllabel(p, PACKW, "Url:");
179 cururl=pllabel(p, PACKE|EXPAND, "---");
180 plplacelabel(cururl, PLACEW);
181 p=plgroup(root, PACKN|EXPAND);
182 bar=plscrollbar(p, PACKW);
183 text=pltextview(p, PACKE|EXPAND, Pt(0, 0), 0, dolink);
184 plscroll(text, 0, bar);
186 alt=plpopup(0, PACKE|EXPAND, 0, 0, menu3);
187 bar=plscrollbar(alt, PACKW);
188 alttext=pltextview(alt, PACKE|EXPAND, Pt(0, 0), 0, dolink);
189 plscroll(alttext, 0, bar);
192 void killcohort(void){
194 for(i=0;i!=3;i++){ /* It's a long way to the kitchen */
195 postnote(PNGROUP, cohort, "kill\n");
199 void catch(void*, char*){
202 void dienow(void*, char*){
205 int mkmfile(char *stem, int mode){
207 char filename[NNAME];
212 sprint(home, "%s/lib", henv);
213 f=create(home, OREAD, DMDIR|0777);
215 sprint(home, "%s/lib/mothra", henv);
216 f=create(home, OREAD, DMDIR|0777);
221 strcpy(home, "/tmp");
223 snprint(filename, sizeof(filename), "%s/%s", home, stem);
224 f=create(filename, OWRITE, mode);
226 f=create(stem, OWRITE, mode);
234 esetcursor(&mothcurs);
236 esetcursor(current->alldone ? 0 : &readingcurs);
239 void scrollto(char *tag);
241 void main(int argc, char *argv[]){
243 enum { Eplumb = 128 };
253 case 'd': debug++; break;
254 case 'v': verbose=1; break;
262 * so that we can stop all subprocesses with a note,
263 * and to isolate rendezvous from other processes
265 if(cohort = rfork(RFPROC|RFNOTEG|RFNAMEG|RFREND)){
277 fprint(2, "Usage: %s [-d] [-m mtpt] [url]\n", argv[0]);
282 case 1: url=argv[0]; break;
284 errfile=mkmfile("mothra.err", 0666);
289 logfile=mkmfile("mothra.log", 0666|DMAPPEND);
290 if(initdraw(0, 0, mothra) < 0)
291 sysfatal("initdraw: %r");
292 display->locking = 1;
293 chrwidth=stringwidth(font, "0");
294 pltabsize(chrwidth, 8*chrwidth);
295 einit(Emouse|Ekeyboard);
296 eplumb(Eplumb, "web");
297 if(pipe(kickpipe) < 0)
298 sysfatal("pipe: %r");
299 estart(0, kickpipe[0], 256);
300 plinit(screen->depth);
301 if(debug) notify(dienow);
303 hrule=allocimage(display, Rect(0, 0, 2048, 5), screen->chan, 0, DWhite);
305 sysfatal("can't allocimage!");
306 draw(hrule, Rect(0,1,1280,3), display->black, 0, ZP);
307 linespace=allocimage(display, Rect(0, 0, 2048, 5), screen->chan, 0, DWhite);
309 sysfatal("can't allocimage!");
310 bullet=allocimage(display, Rect(0,0,25, 8), screen->chan, 0, DWhite);
311 fillellipse(bullet, Pt(4,4), 3, 3, display->black, ZP);
314 unlockdisplay(display);
316 lockdisplay(display);
319 geturl(url, GET, 0, 1, 0);
321 if(logfile==-1) message("Can't open log file");
324 if(mouse.buttons==0 && current){
325 if(current->finished){
327 if(current->url->tag[0])
328 scrollto(current->url->tag);
335 else if(current->changed){
341 flushimage(display, 1);
342 unlockdisplay(display);
344 lockdisplay(display);
357 scrolltext(-text->size.y/4, 1);
360 scrolltext(-text->size.y/2, 1);
363 scrolltext(text->size.y/4, 1);
366 scrolltext(text->size.y/2, 1);
369 scrolltext(-text->size.y, 2);
375 if(mouse.buttons & (8|16)){
376 if(mouse.buttons & 8)
377 scrolltext(-text->size.y/24, 1);
379 scrolltext(text->size.y/24, 1);
382 plmouse(root, &mouse);
387 geturl(pm->data, GET, 0, 1, 0);
393 Cursor confirmcursor={
395 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
396 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
397 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
398 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
400 0x00, 0x0E, 0x07, 0x1F, 0x03, 0x17, 0x73, 0x6F,
401 0xFB, 0xCE, 0xDB, 0x8C, 0xDB, 0xC0, 0xFB, 0x6C,
402 0x77, 0xFC, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03,
403 0x94, 0xA6, 0x63, 0x3C, 0x63, 0x18, 0x94, 0x90,
407 esetcursor(&confirmcursor);
408 do down=emouse(); while(!down.buttons);
409 do up=emouse(); while(up.buttons);
411 return down.buttons==(1<<(b-1));
413 void message(char *s, ...){
414 static char buf[1024];
418 out = buf + vsnprint(buf, sizeof(buf), s, args);
421 plinitlabel(msg, PACKN|FILLX, buf);
422 if(defdisplay) pldraw(msg, screen);
424 void htmlerror(char *name, int line, char *m, ...){
425 static char buf[1024];
430 out=buf+snprint(buf, sizeof(buf), "%s: line %d: ", name, line);
431 out+=vsnprint(out, sizeof(buf)-(out-buf)-1, m, args);
434 fprint(2, "%s\n", buf);
437 void eresized(int new){
440 lockdisplay(display);
441 if(new && getwindow(display, Refnone) == -1) {
442 fprint(2, "getwindow: %r\n");
446 plinitlabel(curttl, PACKE|EXPAND, "---");
447 plinitlabel(cururl, PACKE|EXPAND, "---");
451 plinitlabel(curttl, PACKE|EXPAND, current->title);
452 plinitlabel(cururl, PACKE|EXPAND, current->url->fullname);
454 draw(screen, r, display->white, 0, ZP);
455 pldraw(root, screen);
456 unlockdisplay(display);
458 void *emalloc(int n){
462 sysfatal("out of memory");
463 setmalloctag(v, getcallerpc(&n));
466 void *emallocz(int n, int z){
471 setmalloctag(v, getcallerpc(&n));
475 char *genwww(Panel *, int index){
476 static char buf[1024];
482 snprint(buf, sizeof(buf), "%2d %s", i+1, www(i)->title);
486 void scrollto(char *tag){
489 if(current == nil || text == nil)
492 for(tp=current->text;tp;tp=tp->next){
494 if(ap && ap->name && strcmp(ap->name, tag)==0){
495 current->yoffs=tp->topy;
500 plsetpostextview(text, current->yoffs);
501 flushimage(display, 1);
505 * selected text should be a url.
507 void setcurrent(int index, char *tag){
511 if(new==current && (tag==0 || tag[0]==0)) return;
513 current->yoffs=plgetpostextview(text);
515 plinitlabel(curttl, PACKE|EXPAND, current->title);
516 if(defdisplay) pldraw(curttl, screen);
517 plinitlabel(cururl, PACKE|EXPAND, current->url->fullname);
518 if(defdisplay) pldraw(cururl, screen);
519 plinittextview(text, PACKE|EXPAND, Pt(0, 0), current->text, dolink);
521 if((i = open("/dev/label", OWRITE)) >= 0){
522 fprint(i, "%s %s", mothra, current->url->fullname);
528 do ++s; while(*s==' ' || *s=='\t');
531 void save(int ifd, char *name){
535 message("save: %s: %r", name);
538 ofd=create(name, OWRITE, 0666);
540 message("save: %s: %r", name);
543 switch(rfork(RFNOTEG|RFNAMEG|RFFDG|RFMEM|RFPROC|RFNOWAIT)){
545 message("Can't fork: %r");
553 snprint(buf, sizeof(buf),
554 "{tput -p || cat} |[2] {aux/statusmsg -k %q >/dev/null || cat >/dev/null}", name);
555 execl("/bin/rc", "rc", "-c", buf, nil);
562 void screendump(char *name, int full){
565 fd=create(name, OWRITE, 0666);
567 message("can't create %s", name);
571 writeimage(fd, screen, 0);
573 if((b=allocimage(display, text->r, screen->chan, 0, DNofill)) == nil){
574 message("can't allocate image");
578 draw(b, b->r, screen, 0, b->r.min);
579 writeimage(fd, b, 0);
586 * convert a url into a local file name.
588 char *urltofile(Url *url){
592 if(url->fullname[0] || url->reltext[0])
596 if(slash = strrchr(name, '/'))
604 * user typed a command.
606 void docmd(Panel *p, char *s){
611 while(*s==' ' || *s=='\t') s++;
613 * Non-command does a get on the url
615 if(s[0]!='\0' && s[1]!='\0' && s[1]!=' ')
616 geturl(s, GET, 0, 0, 0);
617 else switch(c = s[0]){
619 message("Unknown command %s, type h for help", s);
623 if(*s=='\0' && selection)
631 s = urlstr(selection);
633 message("no url selected");
635 geturl(s, GET, 0, 0, 0);
640 doprev(nil, 1, wwwtop-atoi(s));
642 message("Usage: j index");
647 if(s==0 || *s=='\0'){
648 snprint(buf, sizeof(buf), "dump.bit");
649 if(eenter("Screendump to", buf, sizeof(buf), &mouse) <= 0)
653 screendump(s, c == 'W');
658 message("no url selected");
661 if(s==0 || *s=='\0'){
662 snprint(buf, sizeof(buf), "%s", urltofile(selection));
663 if(eenter("Save to", buf, sizeof(buf), &mouse) <= 0)
667 save(urlopen(selection, GET, 0), s);
672 plinitentry(cmd, EXPAND, 0, "", docmd);
673 if(defdisplay) pldraw(cmd, screen);
675 void hiturl(int buttons, char *url, int map){
677 case 1: geturl(url, GET, 0, 0, map); break;
678 case 2: selurl(url); break;
679 case 4: message("Button 3 hit on url can't happen!"); break;
683 * user selected from the list of available pages
685 void doprev(Panel *p, int buttons, int index){
688 if(index < 0 || index >= nwww())
692 case 1: setcurrent(i, 0); /* no break ... */
693 case 2: selurl(www(i)->url->fullname); break;
694 case 4: message("Button 3 hit on page can't happen!"); break;
699 * Follow an html link
701 void dolink(Panel *p, int buttons, Rtext *word){
702 char *file, mapurl[NNAME];
708 if(a == nil || a->image == nil && a->link == nil)
711 hiturl(buttons, a->image ? a->image : a->link, 0);
713 yoffs=plgetpostextview(p);
714 coord=subpt(subpt(mouse.xy, word->r.min), p->r.min);
715 snprint(mapurl, sizeof(mapurl), "%s?%d,%d", a->link, coord.x, coord.y+yoffs);
716 hiturl(buttons, mapurl, 1);
718 hiturl(buttons, a->link ? a->link : a->image, 0);
721 void filter(char *cmd, int fd){
722 switch(rfork(RFFDG|RFPROC|RFMEM|RFNOWAIT)){
724 message("Can't fork!");
730 execl("/bin/rc", "rc", "-c", cmd, 0);
735 void gettext(Www *w, int fd, int type){
736 switch(rfork(RFFDG|RFPROC|RFMEM|RFNOWAIT)){
738 message("Can't fork, please wait");
742 plrdhtml(w->url->fullname, fd, w);
744 plrdplain(w->url->fullname, fd, w);
750 void freetext(Rtext *t){
755 for(; t!=0; t = t->next){
770 int fileurlopen(Url *url){
771 char *rel, *base, *x;
775 if(cistrncmp(url->basename, "file:", 5) == 0)
776 base = url->basename+5;
777 if(cistrncmp(url->reltext, "file:", 5) == 0)
778 rel = url->reltext+5;
779 if(rel == nil && base == nil)
783 if(base && base[0] == '/' && rel[0] != '/'){
784 if(x = strrchr(base, '/'))
786 snprint(url->fullname, sizeof(url->fullname), "%s/%s", base, rel);
789 snprint(url->fullname, sizeof(url->fullname), "%s", rel);
791 if(x = strrchr(url->fullname, '#')){
793 strncpy(url->tag, x, sizeof(url->tag));
795 fd = open(cleanname(url->fullname), OREAD);
798 memset(url->fullname, 0, sizeof(url->fullname));
799 strcpy(url->fullname, "file:");
800 fd2path(fd, url->fullname+5, sizeof(url->fullname)-6);
804 int readstr(char *buf, int nbuf, char *base, char *name){
809 snprint(path, sizeof path, "%s/%s", base, name);
810 if((fd = open(path, OREAD)) >= 0){
811 if((n = read(fd, buf, nbuf-1)) < 0)
819 int urlopen(Url *url, int method, char *body){
820 int conn, ctlfd, fd, n;
821 char buf[1024+1], *p;
823 if(debug) fprint(2, "urlopen %s (%s)\n", url->reltext, url->basename);
826 if((fd = fileurlopen(url)) >= 0)
828 snprint(buf, sizeof buf, "%s/clone", mtpt);
829 if((ctlfd = open(buf, ORDWR)) < 0)
831 if((n = read(ctlfd, buf, sizeof buf-1)) <= 0){
837 if(url->basename[0]){
838 n = snprint(buf, sizeof buf, "baseurl %s", url->basename);
839 write(ctlfd, buf, n);
841 n = snprint(buf, sizeof buf, "url %s", url->reltext);
842 if(write(ctlfd, buf, n) != n){
847 if(method == POST && body){
848 snprint(buf, sizeof buf, "%s/%d/postbody", mtpt, conn);
849 if((fd = open(buf, OWRITE)) < 0)
852 if(write(fd, body, n) != n){
858 snprint(buf, sizeof buf, "%s/%d/body", mtpt, conn);
859 if((fd = open(buf, OREAD)) < 0)
861 snprint(buf, sizeof buf, "%s/%d/parsed", mtpt, conn);
862 readstr(url->fullname, sizeof(url->fullname), buf, "url");
863 readstr(url->tag, sizeof(url->tag), buf, "fragment");
868 int pipeline(char *cmd, int fd)
875 werrstr("pipeline for %s failed: %r", cmd);
888 execl("/bin/rc", "rc", "-c", cmd, 0);
899 return url->fullname;
904 void selurl(char *urlname){
906 seturl(&url, urlname, current ? current->url->fullname : "");
908 message("selected: %s", urlstr(selection));
910 void seturl(Url *url, char *urlname, char *base){
911 strncpy(url->reltext, urlname, sizeof(url->reltext));
912 strncpy(url->basename, base, sizeof(url->basename));
913 url->fullname[0] = 0;
917 Url *copyurl(Url *u){
919 v=emalloc(sizeof(Url));
923 void freeurl(Url *u){
928 * get the file at the given url
930 void geturl(char *urlname, int method, char *body, int plumb, int map){
931 int i, fd, typ, pfd[2];
945 message("getting %s", selection->reltext);
946 esetcursor(&patientcurs);
948 if((fd=urlopen(selection, method, body)) < 0){
952 message("getting %s", selection->fullname);
953 if(mothmode && !plumb)
958 fd=pipeline("/bin/gunzip", fd);
962 fd=pipeline("/bin/uncompress", fd);
969 message("unknown file type");
973 snprint(cmd, sizeof(cmd), "%s", urltofile(selection));
974 if(eenter("Save to", cmd, sizeof(cmd), &mouse) <= 0){
981 fd = pipeline("/bin/uhtml", fd);
984 for(i=wwwtop-1; i>=0 && i!=(wwwtop-NWWW-1); i--){
986 n += countpix(w->pix);
987 if(n < NPIXMB*1024*1024)
989 if(!w->finished && !w->alldone)
991 for(t=w->text; t; t=t->next)
997 w = www(i = wwwtop++);
999 /* wait for the reader to finish the document */
1000 while(!w->finished && !w->alldone){
1001 unlockdisplay(display);
1003 lockdisplay(display);
1009 memset(w, 0, sizeof(*w));
1012 w->url=copyurl(current->url);
1014 w->url=copyurl(selection);
1017 gettext(w, fd, typ);
1018 plinitlist(list, PACKN|FILLX, genwww, 8, doprev);
1019 if(defdisplay) pldraw(list, screen);
1020 setcurrent(i, selection->tag);
1023 if(rfork(RFFDG|RFNOTEG|RFPROC|RFNAMEG|RFNOWAIT) == 0){
1024 snprint(cmd, sizeof(cmd), "-pid %d", getpid());
1025 if(newwindow(cmd) != -1){
1026 close(1); open("/dev/cons", OWRITE);
1027 print("reading gif...\n");
1038 filter("page -w", fd);
1045 void updtext(Www *w){
1048 for(t=w->text;t;t=t->next){
1056 w->yoffs=plgetpostextview(text);
1057 plinittextview(text, PACKE|EXPAND, Pt(0, 0), w->text, dolink);
1058 plsetpostextview(text, w->yoffs);
1059 pldraw(root, screen);
1061 void update(Www *w){
1063 write(kickpipe[1], "C", 1);
1065 void finish(Www *w){
1067 write(kickpipe[1], "F", 1);
1071 mothon(Www *w, int on)
1076 if(current == nil || mothmode == on)
1079 message("moth mode!");
1083 * insert or remove artificial links to the href for
1084 * images that are also links
1086 for(t=w->text;t;t=t->next){
1088 if(a == nil || a->image == nil || a->link == nil)
1093 ap=mallocz(sizeof(Action), 1);
1094 ap->link = strdup(a->link);
1095 plrtstr(&t->next, 0, 0, t->font, strdup("->"), 1, ap);
1107 void snarf(Panel *p){
1109 if((fd=open("/dev/snarf", OWRITE|OTRUNC))>=0){
1110 fprint(fd, "%s", urlstr(selection));
1114 void paste(Panel *p){
1117 if((fd=open("/dev/snarf", OREAD))<0)
1119 strncpy(buf, plentryval(p), sizeof(buf));
1121 n=read(fd, buf+len, sizeof(buf)-len-1);
1124 plinitentry(cmd, PACKE|EXPAND, 0, buf, docmd);
1125 pldraw(cmd, screen);
1129 void hit3(int button, int item){
1140 current->yoffs=plgetpostextview(text);
1144 defdisplay=!defdisplay;
1145 plpack(root, screen->r);
1146 plinittextview(text, PACKE|EXPAND, Pt(0, 0), current->text, dolink);
1147 plsetpostextview(text, current->yoffs);
1148 pldraw(root, screen);
1151 mothon(current, !mothmode);
1160 snprint(name, sizeof(name), "%s/hit.html", home);
1161 fd=open(name, OWRITE);
1163 fd=create(name, OWRITE, 0666);
1165 message("can't open %s", name);
1168 fprint(fd, "<html><head><title>Hit List</title></head>\n");
1169 fprint(fd, "<body><h1>Hit list</h1>\n");
1172 fprint(fd, "<p><a href=\"%s\">%s</a>\n", urlstr(selection), urlstr(selection));
1176 snprint(name, sizeof(name), "file:%s/hit.html", home);
1177 geturl(name, GET, 0, 1, 0);