]> git.lizzy.rs Git - plan9front.git/blobdiff - sys/src/cmd/mothra/mothra.c
mothra: mouse scrollwheel behave the same as in sam
[plan9front.git] / sys / src / cmd / mothra / mothra.c
index 897cba4ebdf0dd37b79ab382155aea941a72213f..fef7c9573b94021ff329910c90c64050deb01901 100644 (file)
@@ -9,16 +9,16 @@
 #include <plumb.h>
 #include <cursor.h>
 #include <panel.h>
+#include <regexp.h>
 #include "mothra.h"
 #include "rtext.h"
-int debug=0;           /* -d flag causes debug messages to appear in mothra.err */
-int verbose=0;         /* -v flag causes html errors to appear in mothra.err */
+int debug=0;
+int verbose=0;         /* -v flag causes html errors to be written to file-descriptor 2 */
 int defdisplay=1;      /* is the default (initial) display visible? */
 Panel *root;   /* the whole display */
 Panel *alt;    /* the alternate display */
 Panel *alttext;        /* the alternate text window */
 Panel *cmd;    /* command entry */
-Panel *curttl; /* label giving the title of the visible text */
 Panel *cururl; /* label giving the url of the visible text */
 Panel *list;   /* list of previously acquired www pages */
 Panel *msg;    /* message display */
@@ -92,6 +92,7 @@ char *buttons[]={
        "moth mode",
        "snarf",
        "paste",
+       "search",
        "save hit",
        "hit list",
        "exit",
@@ -159,7 +160,8 @@ void scrolltext(int dy, int whence)
 }
 
 void mkpanels(void){
-       Panel *p, *bar;
+       Panel *p, *bar, *swap;
+
        menu3=plmenu(0, 0, buttons, PACKN|FILLX, hit3);
        root=plpopup(root, EXPAND, 0, 0, menu3);
                p=plgroup(root, PACKN|FILLX);
@@ -171,10 +173,6 @@ void mkpanels(void){
                        bar=plscrollbar(p, PACKW);
                        list=pllist(p, PACKN|FILLX, genwww, 8, doprev);
                        plscroll(list, 0, bar);
-               p=plgroup(root, PACKN|FILLX);
-                       pllabel(p, PACKW, "Title:");
-                       curttl=pllabel(p, PACKE|EXPAND, "---");
-                       plplacelabel(curttl, PLACEW);
                p=plgroup(root, PACKN|FILLX);
                        pllabel(p, PACKW, "Url:");
                        cururl=pllabel(p, PACKE|EXPAND, "---");
@@ -188,6 +186,15 @@ void mkpanels(void){
                bar=plscrollbar(alt, PACKW|USERFL);
                alttext=pltextview(alt, PACKE|EXPAND, Pt(0, 0), 0, dolink);
                plscroll(alttext, 0, bar);
+
+       if(!defdisplay){
+               swap=root;
+               root=alt;
+               alt=swap;
+               swap=text;
+               text=alttext;
+               alttext=swap;
+       }
 }
 int cohort = -1;
 void killcohort(void){
@@ -203,29 +210,29 @@ void catch(void*, char*){
 void dienow(void*, char*){
        noted(NDFLT);
 }
-int mkmfile(char *stem, int mode){
-       char *henv;
-       char filename[NNAME];
+
+char* mkhome(void){
+       static char *home;              /* where to put files */
+       char *henv, *tmp;
        int f;
-       if(home[0]=='\0'){
+
+       if(home == nil){
                henv=getenv("home");
                if(henv){
-                       sprint(home, "%s/lib", henv);
-                       f=create(home, OREAD, DMDIR|0777);
+                       tmp = smprint("%s/lib", henv);
+                       f=create(tmp, OREAD, DMDIR|0777);
                        if(f!=-1) close(f);
-                       sprint(home, "%s/lib/mothra", henv);
+                       free(tmp);
+
+                       home = smprint("%s/lib/mothra", henv);
                        f=create(home, OREAD, DMDIR|0777);
                        if(f!=-1) close(f);
                        free(henv);
                }
                else
-                       strcpy(home, "/tmp");
+                       home = strdup("/tmp");
        }
-       snprint(filename, sizeof(filename), "%s/%s", home, stem);
-       f=create(filename, OWRITE, mode);
-       if(f==-1)
-               f=create(stem, OWRITE, mode);
-       return f;
+       return home;
 }
 
 void donecurs(void){
@@ -249,6 +256,8 @@ void drawlock(int dolock){
 }
 
 void scrollto(char *tag);
+void search(void);
+
 extern char *mtpt; /* url */
 
 void main(int argc, char *argv[]){
@@ -258,7 +267,6 @@ void main(int argc, char *argv[]){
        Www *new;
        Action *a;
        char *url;
-       int errfile;
        int i;
 
        quotefmtinstall();
@@ -270,6 +278,7 @@ void main(int argc, char *argv[]){
        case 'm':
                if(mtpt = ARGF())
                        break;
+       case 'a': defdisplay=0; break;
        default:  goto Usage;
        }ARGEND
 
@@ -289,18 +298,13 @@ void main(int argc, char *argv[]){
        switch(argc){
        default:
        Usage:
-               fprint(2, "Usage: %s [-d] [-m mtpt] [url]\n", argv[0]);
+               fprint(2, "Usage: %s [-dva] [-m mtpt] [url]\n", argv0);
                exits("usage");
        case 0:
                url=getenv("url");
                break;
        case 1: url=argv[0]; break;
        }
-       errfile=mkmfile("mothra.err", 0666);
-       if(errfile!=-1){
-               dup(errfile, 2);
-               close(errfile);
-       }
        if(initdraw(0, 0, mothra) < 0)
                sysfatal("initdraw: %r");
        display->locking = 1;
@@ -324,7 +328,6 @@ void main(int argc, char *argv[]){
        bullet=allocimage(display, Rect(0,0,25, 8), screen->chan, 0, DWhite);
        fillellipse(bullet, Pt(4,4), 3, 3, display->black, ZP);
        mkpanels();
-
        unlockdisplay(display);
        eresized(0);
        drawlock(1);
@@ -384,15 +387,18 @@ void main(int argc, char *argv[]){
                        case Kend:
                                scrolltext(-text->size.y, 2);
                                break;
+                       case Kack:
+                               search();
+                               break;
                        }
                        break;
                case Emouse:
                        mouse=e.mouse;
-                       if(mouse.buttons & (8|16)){
+                       if(mouse.buttons & (8|16) && ptinrect(mouse.xy, text->r)){
                                if(mouse.buttons & 8)
-                                       scrolltext(-text->size.y/24, 1);
+                                       scrolltext(text->r.min.y - mouse.xy.y, 1);
                                else
-                                       scrolltext(text->size.y/24, 1);
+                                       scrolltext(mouse.xy.y - text->r.min.y, 1);
                                break;
                        }
                        plmouse(root, &mouse);
@@ -461,7 +467,7 @@ void eresized(int new){
        r=screen->r;
        plpack(root, r);
        plpack(alt, r);
-       draw(screen, r, display->white, 0, ZP);
+       pldraw(cmd, screen);    /* put cmd box on screen for alt display */
        pldraw(root, screen);
        flushimage(display, 1);
        drawlock(0);
@@ -482,12 +488,20 @@ void nstrcpy(char *to, char *from, int len){
 
 char *genwww(Panel *, int index){
        static char buf[1024];
+       Www *w;
        int i;
 
        if(index >= nwww())
                return 0;
        i = wwwtop-index-1;
-       snprint(buf, sizeof(buf), "%2d %s", i+1, www(i)->title);
+       w = www(i);
+       if(!w->url)
+               return 0;
+       if(w->title[0]!='\0'){
+               w->gottitle=1;
+               snprint(buf, sizeof(buf), "%2d %s", i+1, w->title);
+       } else
+               snprint(buf, sizeof(buf), "%2d %s", i+1, urlstr(w->url));
        return buf;
 }
 
@@ -520,8 +534,6 @@ void setcurrent(int index, char *tag){
        if(current)
                current->yoffs=plgetpostextview(text);
        current=new;
-       plinitlabel(curttl, PACKE|EXPAND, current->title);
-       if(defdisplay) pldraw(curttl, screen);
        plinitlabel(cururl, PACKE|EXPAND, current->url->fullname);
        if(defdisplay) pldraw(cururl, screen);
        plinittextview(text, PACKE|EXPAND, Pt(0, 0), current->text, dolink);
@@ -684,7 +696,47 @@ void docmd(Panel *p, char *s){
                exits(0);
        }
        plinitentry(cmd, EXPAND, 0, "", docmd);
-       if(defdisplay) pldraw(cmd, screen);
+       pldraw(root, screen);
+}
+
+void search(void){
+       static char last[256];
+       char buf[256];
+       Reprog *re;
+       Rtext *tp;
+
+       for(;;){
+               if(current == nil || current->text == nil || text == nil)
+                       return;
+               strncpy(buf, last, sizeof(buf)-1);
+               if(eenter("Search for", buf, sizeof(buf), &mouse) <= 0)
+                       return;
+               re = regcompnl(buf);
+               if(re == nil)
+                       return;
+               strncpy(last, buf, sizeof(buf)-1);
+               for(tp=current->text;tp;tp=tp->next)
+                       if(tp->flags & PL_SEL)
+                               break;
+               if(tp == nil)
+                       tp = current->text;
+               else {
+                       tp->flags &= ~PL_SEL;
+                       tp = tp->next;
+               }
+               while(tp != nil){
+                       tp->flags &= ~PL_SEL;
+                       if(tp->text && *tp->text)
+                       if(regexec(re, tp->text, nil, 0)){
+                               tp->flags |= PL_SEL;
+                               plsetpostextview(text, tp->topy);
+                               break;
+                       }
+                       tp = tp->next;
+               }
+               free(re);
+               updtext(current);
+       }
 }
 
 void hiturl(int buttons, char *url, int map){
@@ -720,29 +772,36 @@ void dolink(Panel *p, int buttons, Rtext *word){
        int yoffs;
        Action *a;
 
+       /* really a button, hit it */
+       if(word->p != nil && word->p != p && strcmp(word->p->kind, "button") == 0){
+               extern void pl_buttonhit(Panel *p, int buttons, int check);
+               pl_buttonhit(word->p, buttons, 0);
+               return;
+       }
+
        a=word->user;
-       if(a == nil || a->image == nil && a->link == nil)
+       if(a == nil || (a->link == nil && a->image == nil))
                return;
        if(mothmode)
                hiturl(buttons, a->image ? a->image : a->link, 0);
-       else if(a->ismap){
-               yoffs=plgetpostextview(p);
-               coord=subpt(subpt(mouse.xy, word->r.min), p->r.min);
-               snprint(mapurl, sizeof(mapurl), "%s?%d,%d", a->link, coord.x, coord.y+yoffs);
-               hiturl(buttons, mapurl, 1);
-       } else
-               hiturl(buttons, a->link ? a->link : a->image, 0);
+       else if(a->link){
+               if(a->ismap){
+                       yoffs=plgetpostextview(p);
+                       coord=subpt(subpt(mouse.xy, word->r.min), p->r.min);
+                       snprint(mapurl, sizeof(mapurl), "%s?%d,%d", a->link, coord.x, coord.y+yoffs);
+                       hiturl(buttons, mapurl, 1);
+               } else
+                       hiturl(buttons, a->link, 0);
+       }
 }
 
-void filter(char *cmd, int fd){
-       switch(rfork(RFFDG|RFPROC|RFMEM|RFNOWAIT)){
+void filter(int fd, char *cmd){
+       switch(rfork(RFFDG|RFPROC|RFMEM|RFREND|RFNOWAIT|RFNOTEG)){
        case -1:
                message("Can't fork!");
                break;
        case 0:
-               close(0);
-               dup(fd, 0);
-               close(fd);
+               dupfds(fd, 1, 2, -1);
                execl("/bin/rc", "rc", "-c", cmd, 0);
                _exits(0);
        }
@@ -783,32 +842,65 @@ void freetext(Rtext *t){
        plrtfree(tt);
 }
 
-int pipeline(char *cmd, int fd)
+void
+dupfds(int fd, ...)
+{
+       int mfd, n, i;
+       va_list arg;
+       Dir *dir;
+
+       va_start(arg, fd);
+       for(mfd = 0; fd >= 0; fd = va_arg(arg, int), mfd++)
+               if(fd != mfd)
+                       if(dup(fd, mfd) < 0)
+                               sysfatal("dup: %r");
+       va_end(arg);
+       if((fd = open("/fd", OREAD)) < 0)
+               sysfatal("open: %r");
+       n = dirreadall(fd, &dir);
+       for(i=0; i<n; i++){
+               if(strstr(dir[i].name, "ctl"))
+                       continue;
+               fd = atoi(dir[i].name);
+               if(fd >= mfd)
+                       close(fd);
+       }
+       free(dir);
+}
+
+int pipeline(int fd, char *fmt, ...)
 {
+       char buf[80], *argv[4];
+       va_list arg;
        int pfd[2];
 
-       if(pipe(pfd)==-1){
-Err:
+       va_start(arg, fmt);
+       vsnprint(buf, sizeof buf, fmt, arg);
+       va_end(arg);
+
+       if(pipe(pfd) < 0){
+       Err:
                close(fd);
-               werrstr("pipeline for %s failed: %r", cmd);
+               werrstr("pipeline for %s failed: %r", buf);
                return -1;
        }
-       switch(fork()){
+       switch(rfork(RFPROC|RFMEM|RFFDG|RFREND|RFNOWAIT)){
        case -1:
                close(pfd[0]);
                close(pfd[1]);
                goto Err;
        case 0:
-               dup(fd, 0);
-               dup(pfd[0], 1);
-               close(pfd[0]);
-               close(pfd[1]);
-               execl("/bin/rc", "rc", "-c", cmd, 0);
+               dupfds(fd, pfd[1], 2, -1);
+               argv[0] = "rc";
+               argv[1] = "-c";
+               argv[2] = buf;
+               argv[3] = nil;
+               exec("/bin/rc", argv);
                _exits(0);
        }
-       close(pfd[0]);
        close(fd);
-       return pfd[1];
+       close(pfd[1]);
+       return pfd[0];
 }
 
 char*
@@ -822,6 +914,7 @@ Url* selurl(char *urlname){
        seturl(&url, urlname, current ? current->url->fullname : "");
        selection=&url;
        message("selected: %s", urlstr(selection));
+       plgrabkb(cmd);          /* for snarf */
        return selection;
 }
 void seturl(Url *url, char *urlname, char *base){
@@ -885,7 +978,7 @@ void geturl(char *urlname, int post, int plumb, int map){
                        save(fd, cmd);
                        break;
                case HTML:
-                       fd = pipeline("/bin/uhtml", fd);
+                       fd = pipeline(fd, "exec uhtml");
                case PLAIN:
                        n=0; 
                        for(i=wwwtop-1; i>=0 && i!=(wwwtop-NWWW-1); i--){
@@ -934,7 +1027,7 @@ void geturl(char *urlname, int post, int plumb, int map){
                case PNG:
                case BMP:
                case PAGE:
-                       filter("page -w", fd);
+                       filter(fd, "exec page -w");
                        break;
                }
                break;
@@ -944,6 +1037,8 @@ void geturl(char *urlname, int post, int plumb, int map){
 void updtext(Www *w){
        Rtext *t;
        Action *a;
+       if(defdisplay && w->gottitle==0 && w->title[0]!='\0')
+               pldraw(list, screen);
        for(t=w->text;t;t=t->next){
                a=t->user;
                if(a){
@@ -957,7 +1052,7 @@ void updtext(Www *w){
        w->yoffs=plgetpostextview(text);
        plinittextview(text, PACKE|EXPAND, Pt(0, 0), w->text, dolink);
        plsetpostextview(text, w->yoffs);
-       pldraw(root, screen);
+       pldraw(text, screen);
 }
 
 void finish(Www *w){
@@ -983,8 +1078,15 @@ mothon(Www *w, int on)
         */
        for(t=w->text;t;t=t->next){
                a=t->user;
-               if(a == nil || a->image == nil || a->link == nil)
+               if(a == nil || a->image == nil)
                        continue;
+               if(a->link == nil){
+                       if(on)
+                               t->flags |= PL_HOT;
+                       else
+                               t->flags &= ~PL_HOT;
+                       continue;
+               }
                x = t->next;
                if(on){
                        t->next = nil;
@@ -993,9 +1095,11 @@ mothon(Www *w, int on)
                        plrtstr(&t->next, 0, 0, t->font, strdup("->"), PL_HOT, ap);
                        t->next->next = x;
                } else {
-                       t->next = x->next;
-                       x->next = nil;
-                       freetext(x);
+                       if(x) {
+                               t->next = x->next;
+                               x->next = nil;
+                               freetext(x);
+                       }
                }
        }
        updtext(w);
@@ -1015,11 +1119,14 @@ void killpix(Www *w){
        updtext(w);
 }
 void snarf(Panel *p){
-       if(p==0) p=cmd;
-       plputsnarf(urlstr(selection));
-       /* non-ops if nothing selected */
-       plsnarf(p);
-       plsnarf(text);
+       if(p==0 || p==cmd){
+               if(selection){
+                       plputsnarf(urlstr(selection));
+                       plsnarf(text);
+               }else
+                       message("no url selected");
+       }else
+               plsnarf(p);
 }
 void paste(Panel *p){
        if(p==0) p=cmd;
@@ -1059,7 +1166,14 @@ void hit3(int button, int item){
                paste(plkbfocus);
                break;
        case 4:
-               snprint(name, sizeof(name), "%s/hit.html", home);
+               search();
+               break;
+       case 5:
+               if(!selection){
+                       message("no url selected");
+                       break;
+               }
+               snprint(name, sizeof(name), "%s/hit.html", mkhome());
                fd=open(name, OWRITE);
                if(fd==-1){
                        fd=create(name, OWRITE, 0666);
@@ -1074,11 +1188,11 @@ void hit3(int button, int item){
                fprint(fd, "<p><a href=\"%s\">%s</a>\n", urlstr(selection), urlstr(selection));
                close(fd);
                break;
-       case 5:
-               snprint(name, sizeof(name), "file:%s/hit.html", home);
+       case 6:
+               snprint(name, sizeof(name), "file:%s/hit.html", mkhome());
                geturl(name, -1, 1, 0);
                break;
-       case 6:
+       case 7:
                if(confirm(3))
                        exits(0);
                break;