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";
93 void docmd(Panel *, char *);
94 void doprev(Panel *, int, int);
97 void setcurrent(int, char *);
98 char *genwww(Panel *, int);
100 void dolink(Panel *, int, Rtext *);
115 static Www a[1+NWWW];
116 return &a[1+(index % NWWW)];
119 return wwwtop<NWWW ? wwwtop : NWWW;
122 void err(Display *, char *msg){
123 fprint(2, "err: %s (%r)\n", msg);
126 int subpanel(Panel *obj, Panel *subj){
128 if(obj==subj) return 1;
129 for(obj=obj->child;obj;obj=obj->next)
130 if(subpanel(obj, subj)) return 1;
134 * Make sure that the keyboard focus is on-screen, by adjusting it to
135 * be the cmd entry if necessary.
140 extern Panel *pl_kbfocus; /* this is a secret panel library name */
142 yoffs=text->r.min.y-plgetpostextview(text);
143 for(t=current->text;t;t=t->next) if(!eqrect(t->r, Rect(0,0,0,0))){
144 if(t->r.max.y+yoffs>text->r.max.y) break;
145 if(t->r.min.y+yoffs>=text->r.min.y
147 && subpanel(t->p, pl_kbfocus)) return;
153 void scrolltext(int dy, int whence)
157 s = plgetscroll(text);
166 s.pos.y = s.size.y+dy;
171 if(s.pos.y > s.size.y)
173 plsetscroll(text, s);
174 pldraw(root, screen);
179 menu3=plmenu(0, 0, buttons, PACKN|FILLX, hit3);
180 root=plpopup(root, EXPAND, 0, 0, menu3);
181 p=plgroup(root, PACKN|FILLX);
182 msg=pllabel(p, PACKN|FILLX, mothra);
183 plplacelabel(msg, PLACEW);
184 pllabel(p, PACKW, "Go:");
185 cmd=plentry(p, PACKN|FILLX, 0, "", docmd);
186 p=plgroup(root, PACKN|FILLX);
187 bar=plscrollbar(p, PACKW);
188 list=pllist(p, PACKN|FILLX, genwww, 8, doprev);
189 plscroll(list, 0, bar);
190 p=plgroup(root, PACKN|FILLX);
191 pllabel(p, PACKW, "Title:");
192 curttl=pllabel(p, PACKE|EXPAND, "Initializing");
193 plplacelabel(curttl, PLACEW);
194 p=plgroup(root, PACKN|FILLX);
195 pllabel(p, PACKW, "Url:");
196 cururl=pllabel(p, PACKE|EXPAND, "---");
197 plplacelabel(cururl, PLACEW);
198 p=plgroup(root, PACKN|EXPAND);
199 bar=plscrollbar(p, PACKW);
200 text=pltextview(p, PACKE|EXPAND, Pt(0, 0), 0, dolink);
201 plscroll(text, 0, bar);
203 alt=plpopup(0, PACKE|EXPAND, 0, 0, menu3);
204 bar=plscrollbar(alt, PACKW);
205 alttext=pltextview(alt, PACKE|EXPAND, Pt(0, 0), 0, dolink);
206 plscroll(alttext, 0, bar);
208 void killcohort(void){
210 for(i=0;i!=3;i++){ /* It's a long way to the kitchen */
211 postnote(PNGROUP, getpid(), "kill\n");
215 void dienow(void*, char*){
218 int mkmfile(char *stem, int mode){
220 char filename[NNAME];
225 sprint(home, "%s/lib", henv);
226 f=create(home, OREAD, DMDIR|0777);
228 sprint(home, "%s/lib/mothra", henv);
229 f=create(home, OREAD, DMDIR|0777);
234 strcpy(home, "/tmp");
236 snprint(filename, sizeof(filename), "%s/%s", home, stem);
237 f=create(filename, OWRITE, mode);
239 f=create(stem, OWRITE, mode);
247 esetcursor(&mothcurs);
249 esetcursor(current->alldone ? 0 : &readingcurs);
252 void scrollto(char *tag);
254 void main(int argc, char *argv[]){
256 enum { Eplumb = 128 };
264 case 'd': debug++; break;
265 case 'v': verbose=1; break;
273 * so that we can stop all subprocesses with a note,
274 * and to isolate rendezvous from other processes
276 rfork(RFNOTEG|RFNAMEG|RFREND);
281 fprint(2, "Usage: %s [-d] [-m mtpt] [url]\n", argv[0]);
285 if(url==0 || url[0]=='\0')
288 case 1: url=argv[0]; break;
290 errfile=mkmfile("mothra.err", 0666);
295 logfile=mkmfile("mothra.log", 0666|DMAPPEND);
297 initdraw(err,0,"mothra");
298 display->locking = 1;
299 chrwidth=stringwidth(font, "0");
300 pltabsize(chrwidth, 8*chrwidth);
301 einit(Emouse|Ekeyboard);
302 eplumb(Eplumb, "web");
304 plinit(screen->depth);
305 if(debug) notify(dienow);
307 hrule=allocimage(display, Rect(0, 0, 2048, 5), screen->chan, 0, DWhite);
309 fprint(2, "%s: can't allocimage!\n", argv[0]);
312 draw(hrule, Rect(0,1,1280,3), display->black, 0, ZP);
313 linespace=allocimage(display, Rect(0, 0, 2048, 5), screen->chan, 0, DWhite);
315 fprint(2, "%s: can't allocimage!\n", argv[0]);
318 bullet=allocimage(display, Rect(0,0,25, 8), screen->chan, 0, DWhite);
319 fillellipse(bullet, Pt(4,4), 3, 3, display->black, ZP);
322 strcpy(new->title, "See error message above");
323 plrtstr(&new->text, 0, 0, font, "See error message above", 0, 0);
327 unlockdisplay(display);
329 lockdisplay(display);
331 geturl(url, GET, 0, 1, 0);
333 if(logfile==-1) message("Can't open log file");
336 if(mouse.buttons==0 && current){
337 if(current->finished){
339 if(current->url->tag[0])
340 scrollto(current->url->tag);
347 else if(current->changed){
353 unlockdisplay(display);
355 lockdisplay(display);
368 scrolltext(-text->size.y/4, 1);
371 scrolltext(-text->size.y/2, 1);
374 scrolltext(text->size.y/4, 1);
377 scrolltext(text->size.y/2, 1);
380 scrolltext(-text->size.y, 2);
386 plmouse(root, e.mouse);
391 geturl(pm->data, GET, 0, 1, 0);
397 Cursor confirmcursor={
399 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
400 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
401 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
402 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
404 0x00, 0x0E, 0x07, 0x1F, 0x03, 0x17, 0x73, 0x6F,
405 0xFB, 0xCE, 0xDB, 0x8C, 0xDB, 0xC0, 0xFB, 0x6C,
406 0x77, 0xFC, 0x00, 0x00, 0x00, 0x01, 0x00, 0x03,
407 0x94, 0xA6, 0x63, 0x3C, 0x63, 0x18, 0x94, 0x90,
411 esetcursor(&confirmcursor);
412 do down=emouse(); while(!down.buttons);
413 do up=emouse(); while(up.buttons);
415 return down.buttons==(1<<(b-1));
417 void message(char *s, ...){
418 static char buf[1024];
422 out = buf + vsnprint(buf, sizeof(buf), s, args);
425 plinitlabel(msg, PACKN|FILLX, buf);
426 if(defdisplay) pldraw(msg, screen);
428 void htmlerror(char *name, int line, char *m, ...){
429 static char buf[1024];
434 out=buf+snprint(buf, sizeof(buf), "%s: line %d: ", name, line);
435 out+=vsnprint(out, sizeof(buf)-(out-buf)-1, m, args);
438 fprint(2, "%s\n", buf);
441 void eresized(int new){
444 lockdisplay(display);
445 if(new && getwindow(display, Refnone) == -1) {
446 fprint(2, "getwindow: %r\n");
450 plinitlabel(curttl, PACKE|EXPAND, "---");
451 plinitlabel(cururl, PACKE|EXPAND, "---");
455 plinitlabel(curttl, PACKE|EXPAND, current->title);
456 plinitlabel(cururl, PACKE|EXPAND, current->url->fullname);
458 draw(screen, r, display->white, 0, ZP);
459 pldraw(root, screen);
460 unlockdisplay(display);
462 void *emalloc(int n){
466 fprint(2, "out of space\n");
471 void *emallocz(int n, int z){
479 char *genwww(Panel *, int index){
480 static char buf[1024];
486 snprint(buf, sizeof(buf), "%2d %s", i+1, www(i)->title);
490 void scrollto(char *tag){
493 if(current == nil || text == nil)
496 for(tp=current->text;tp;tp=tp->next){
498 if(ap && ap->name && strcmp(ap->name, tag)==0){
499 current->yoffs=tp->topy;
504 plsetpostextview(text, current->yoffs);
505 flushimage(display, 1);
509 * selected text should be a url.
511 void setcurrent(int index, char *tag){
515 if(new==current && (tag==0 || tag[0]==0)) return;
517 current->yoffs=plgetpostextview(text);
519 plinitlabel(curttl, PACKE|EXPAND, current->title);
520 if(defdisplay) pldraw(curttl, screen);
521 plinitlabel(cururl, PACKE|EXPAND, current->url->fullname);
522 if(defdisplay) pldraw(cururl, screen);
523 plinittextview(text, PACKE|EXPAND, Pt(0, 0), current->text, dolink);
528 do ++s; while(*s==' ' || *s=='\t');
531 void save(int ifd, char *name){
535 message("save: %s: %r", name);
538 ofd=create(name, OEXCL|OWRITE, 0666);
540 message("save: %s: %r", name);
543 switch(rfork(RFNOTEG|RFNAMEG|RFFDG|RFPROC|RFNOWAIT)){
545 message("Can't fork: %r");
548 snprint(buf, sizeof(buf), "-pid %d", getpid());
549 if(newwindow(buf) != -1){
553 close(1); open("/dev/cons", OWRITE);
554 if((cfd = open("/dev/label", OWRITE)) >= 0){
555 fprint(cfd, "save %s", name);
558 if((cfd = open("/dev/wctl", OWRITE)) >= 0){
559 fprint(cfd, "scroll\n");
566 if((blk++ % 4) == 0){
571 if((n=read(ifd, buf, sizeof(buf))) <= 0)
573 if(write(ofd, buf, n) != n)
576 print("%lldK... ", off/1024);
586 void screendump(char *name, int full){
589 fd=create(name, OWRITE|OTRUNC, 0666);
591 message("can't create %s", name);
595 writeimage(fd, screen, 0);
597 if((b=allocimage(display, text->r, screen->chan, 0, DNofill)) == nil){
598 message("can't allocate image");
602 draw(b, b->r, screen, 0, b->r.min);
603 writeimage(fd, b, 0);
610 * convert a url into a local file name.
612 char *urltofile(Url *url){
616 if(url->fullname[0] || url->reltext[0])
620 if(slash = strrchr(name, '/'))
628 * user typed a command.
630 void docmd(Panel *p, char *s){
632 while(*s==' ' || *s=='\t') s++;
634 * Non-command does a get on the url
636 if(s[0]!='\0' && s[1]!='\0' && s[1]!=' ')
637 geturl(s, GET, 0, 0, 0);
640 message("Unknown command %s, type h for help", s);
644 if(*s=='\0' && selection)
652 s = urlstr(selection);
654 message("no url selected");
656 geturl(s, GET, 0, 0, 0);
661 doprev(nil, 1, wwwtop-atoi(s));
663 message("Usage: j index");
668 message("Usage: W file");
676 message("Usage: w file");
684 message("no url selected");
688 s = urltofile(selection);
689 if(s==0 || *s=='\0'){
690 message("Usage: s file");
693 save(urlopen(selection, GET, 0), s);
696 draw(screen, screen->r, display->white, 0, ZP);
699 plinitentry(cmd, EXPAND, 0, "", docmd);
700 if(defdisplay) pldraw(cmd, screen);
702 void hiturl(int buttons, char *url, int map){
704 case 1: geturl(url, GET, 0, 0, map); break;
705 case 2: selurl(url); break;
706 case 4: message("Button 3 hit on url can't happen!"); break;
710 * user selected from the list of available pages
712 void doprev(Panel *p, int buttons, int index){
715 if(index < 0 || index >= nwww())
719 case 1: setcurrent(i, 0); /* no break ... */
720 case 2: selurl(www(i)->url->fullname); break;
721 case 4: message("Button 3 hit on page can't happen!"); break;
726 * Follow an html link
728 void dolink(Panel *p, int buttons, Rtext *word){
729 char *file, mapurl[NNAME];
735 if(a == nil || a->image == nil && a->link == nil)
738 hiturl(buttons, a->image ? a->image : a->link, 0);
740 yoffs=plgetpostextview(p);
741 coord=subpt(subpt(mouse.xy, word->r.min), p->r.min);
742 snprint(mapurl, sizeof(mapurl), "%s?%d,%d", a->link, coord.x, coord.y+yoffs);
743 hiturl(buttons, mapurl, 1);
745 hiturl(buttons, a->link ? a->link : a->image, 0);
748 void filter(char *cmd, int fd){
749 flushimage(display, 1);
750 switch(rfork(RFFDG|RFPROC|RFNOWAIT)){
752 message("Can't fork!");
758 execl("/bin/rc", "rc", "-c", cmd, 0);
759 message("Can't exec /bin/rc!");
766 void gettext(Www *w, int fd, int type){
767 flushimage(display, 1);
768 switch(rfork(RFFDG|RFPROC|RFNOWAIT|RFMEM)){
770 message("Can't fork, please wait");
774 plrdhtml(w->url->fullname, fd, w);
776 plrdplain(w->url->fullname, fd, w);
782 void freetext(Rtext *t){
787 for(; t!=0; t = t->next){
802 int fileurlopen(Url *url){
803 char *rel, *base, *x;
807 if(cistrncmp(url->basename, "file:", 5) == 0)
808 base = url->basename+5;
809 if(cistrncmp(url->reltext, "file:", 5) == 0)
810 rel = url->reltext+5;
811 if(rel == nil && base == nil)
815 if(base && base[0] == '/' && rel[0] != '/'){
816 if(x = strrchr(base, '/'))
818 snprint(url->fullname, sizeof(url->fullname), "%s/%s", base, rel);
821 snprint(url->fullname, sizeof(url->fullname), "%s", rel);
823 if(x = strrchr(url->fullname, '#')){
825 strncpy(url->tag, x, sizeof(url->tag));
827 fd = open(cleanname(url->fullname), OREAD);
830 memset(url->fullname, 0, sizeof(url->fullname));
831 strcpy(url->fullname, "file:");
832 fd2path(fd, url->fullname+5, sizeof(url->fullname)-6);
836 int readstr(char *buf, int nbuf, char *base, char *name){
841 snprint(path, sizeof path, "%s/%s", base, name);
842 if((fd = open(path, OREAD)) >= 0){
843 if((n = read(fd, buf, nbuf-1)) < 0)
851 int urlopen(Url *url, int method, char *body){
852 int conn, ctlfd, fd, n;
853 char buf[1024+1], *p;
855 if(debug) fprint(2, "urlopen %s (%s)\n", url->reltext, url->basename);
858 if((fd = fileurlopen(url)) >= 0)
860 snprint(buf, sizeof buf, "%s/clone", mtpt);
861 if((ctlfd = open(buf, ORDWR)) < 0)
863 if((n = read(ctlfd, buf, sizeof buf-1)) <= 0){
869 if(url->basename[0]){
870 n = snprint(buf, sizeof buf, "baseurl %s", url->basename);
871 write(ctlfd, buf, n);
873 n = snprint(buf, sizeof buf, "url %s", url->reltext);
874 if(write(ctlfd, buf, n) != n){
879 if(method == POST && body){
880 snprint(buf, sizeof buf, "%s/%d/postbody", mtpt, conn);
881 if((fd = open(buf, OWRITE)) < 0)
884 if(write(fd, body, n) != n){
890 snprint(buf, sizeof buf, "%s/%d/body", mtpt, conn);
891 if((fd = open(buf, OREAD)) < 0)
893 snprint(buf, sizeof buf, "%s/%d/parsed", mtpt, conn);
894 readstr(url->fullname, sizeof(url->fullname), buf, "url");
895 readstr(url->tag, sizeof(url->tag), buf, "fragment");
900 int pipeline(char *cmd, int fd)
907 werrstr("pipeline for %s failed: %r", cmd);
920 execl("/bin/rc", "rc", "-c", cmd, 0);
931 return url->fullname;
936 void selurl(char *urlname){
938 seturl(&url, urlname, current?
939 current->url->fullname :
942 message("selected: %s", urlstr(selection));
944 void seturl(Url *url, char *urlname, char *base){
945 strncpy(url->reltext, urlname, sizeof(url->reltext));
946 strncpy(url->basename, base, sizeof(url->basename));
947 url->fullname[0] = 0;
951 Url *copyurl(Url *u){
953 v=emalloc(sizeof(Url));
957 void freeurl(Url *u){
958 if(u!=&defurl && u!=&badurl)
963 * get the file at the given url
965 void geturl(char *urlname, int method, char *body, int plumb, int map){
967 char *file, cmd[NNAME];
979 message("getting %s", selection->reltext);
980 esetcursor(&patientcurs);
982 if((fd=urlopen(selection, method, body)) < 0){
987 message("getting %s", selection->fullname);
988 if(mothmode && !plumb)
993 fd=pipeline("/bin/gunzip", fd);
997 fd=pipeline("/bin/uncompress", fd);
1004 message("unknown file type");
1008 file = urltofile(selection);
1010 message("save to '%s' ?", file);
1020 fd = pipeline("/bin/uhtml", fd);
1022 w = www(i = wwwtop++);
1024 extern void freeform(void *p);
1025 extern void freepix(void *p);
1027 /* wait for the reader to finish the document */
1028 while(!w->finished && !w->alldone){
1029 unlockdisplay(display);
1031 lockdisplay(display);
1038 memset(w, 0, sizeof(*w));
1041 w->url=copyurl(current->url);
1043 w->url=copyurl(selection);
1046 gettext(w, fd, typ);
1047 plinitlist(list, PACKN|FILLX, genwww, 8, doprev);
1048 if(defdisplay) pldraw(list, screen);
1049 setcurrent(i, selection->tag);
1052 if(rfork(RFFDG|RFNOTEG|RFPROC|RFNAMEG|RFNOWAIT) == 0){
1053 snprint(cmd, sizeof(cmd), "-pid %d", getpid());
1054 if(newwindow(cmd) != -1){
1055 close(1); open("/dev/cons", OWRITE);
1056 print("reading gif...\n");
1067 filter("page -w", fd);
1074 void updtext(Www *w){
1077 for(t=w->text;t;t=t->next){
1085 w->yoffs=plgetpostextview(text);
1086 plinittextview(text, PACKE|EXPAND, Pt(0, 0), w->text, dolink);
1087 plsetpostextview(text, w->yoffs);
1088 pldraw(root, screen);
1092 mothon(Www *w, int on)
1097 if(current == nil || mothmode == on)
1100 message("moth mode!");
1104 * insert or remove artificial links to the href for
1105 * images that are also links
1107 for(t=w->text;t;t=t->next){
1109 if(a == nil || a->image == nil || a->link == nil)
1114 ap=mallocz(sizeof(Action), 1);
1115 ap->link = strdup(a->link);
1116 plrtstr(&t->next, 0, 0, t->font, strdup("->"), 1, ap);
1128 void snarf(Panel *p){
1130 fd=create("/dev/snarf", OWRITE, 0666);
1132 fprint(fd, "%s", urlstr(selection));
1136 void paste(Panel *p){
1139 fd=open("/dev/snarf", OREAD);
1140 strncpy(buf, plentryval(p), sizeof(buf));
1142 n=read(fd, buf+len, sizeof(buf)-len-1);
1145 plinitentry(cmd, PACKE|EXPAND, 0, buf, docmd);
1146 pldraw(cmd, screen);
1150 void hit3(int button, int item){
1161 current->yoffs=plgetpostextview(text);
1165 defdisplay=!defdisplay;
1166 plpack(root, screen->r);
1167 plinittextview(text, PACKE|EXPAND, Pt(0, 0), current->text, dolink);
1168 plsetpostextview(text, current->yoffs);
1169 pldraw(root, screen);
1172 mothon(current, !mothmode);
1181 snprint(name, sizeof(name), "%s/hit.html", home);
1182 fd=open(name, OWRITE);
1184 fd=create(name, OWRITE, 0666);
1186 message("can't open %s", name);
1189 fprint(fd, "<html><head><title>Hit List</title></head>\n");
1190 fprint(fd, "<body><h1>Hit list</h1>\n");
1193 fprint(fd, "<p><a href=\"%s\">%s</a>\n", urlstr(selection), urlstr(selection));
1197 snprint(name, sizeof(name), "file:%s/hit.html", home);
1198 geturl(name, GET, 0, 1, 0);
1202 draw(screen, screen->r, display->white, 0, ZP);