diff --git a/sys/src/cmd/mothra/libpanel/draw.c b/sys/src/cmd/mothra/libpanel/draw.c index 7dbd19fc1..733039a4c 100644 --- a/sys/src/cmd/mothra/libpanel/draw.c +++ b/sys/src/cmd/mothra/libpanel/draw.c @@ -17,21 +17,11 @@ static int plldepth; static Image *pl_white, *pl_light, *pl_dark, *pl_black, *pl_hilit; int pl_drawinit(int ldepth){ plldepth=ldepth; -/* - pl_white=allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xFFFFFFFF); - pl_light=allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xAAAAAAFF); - pl_dark =allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x555555FF); - pl_black=allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x000000FF); - pl_hilit=allocimage(display, Rect(0,0,1,1), CHAN1(CAlpha,8), 1, 0x80); -*/ - pl_white=allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0xFFFFFFFF); pl_light=allocimagemix(display, DPalebluegreen, DWhite); pl_dark =allocimage(display, Rect(0,0,1,1), screen->chan, 1, DPurpleblue); pl_black=allocimage(display, Rect(0,0,1,1), screen->chan, 1, 0x000000FF); pl_hilit=allocimage(display, Rect(0,0,1,1), CHAN1(CAlpha,8), 1, 0x80); - - if(pl_white==0 || pl_light==0 || pl_black==0 || pl_dark==0) return 0; return 1; } diff --git a/sys/src/cmd/mothra/libpanel/panel.h b/sys/src/cmd/mothra/libpanel/panel.h index 740bb5d45..042863a8b 100644 --- a/sys/src/cmd/mothra/libpanel/panel.h +++ b/sys/src/cmd/mothra/libpanel/panel.h @@ -166,6 +166,8 @@ Rtext *plrtpanel(Rtext **, int, int, Panel *, void *); void plrtfree(Rtext *); int plgetpostextview(Panel *); void plsetpostextview(Panel *, int); +char *plsnarftext(Panel *); + /* * Idols */ diff --git a/sys/src/cmd/mothra/libpanel/textview.c b/sys/src/cmd/mothra/libpanel/textview.c index 785d6da89..27b8bc5ad 100644 --- a/sys/src/cmd/mothra/libpanel/textview.c +++ b/sys/src/cmd/mothra/libpanel/textview.c @@ -10,44 +10,91 @@ #include #include #include "pldefs.h" +#include "rtext.h" + typedef struct Textview Textview; struct Textview{ void (*hit)(Panel *, int, Rtext *); /* call back to user on hit */ Rtext *text; /* text */ int yoffs; /* offset of top of screen */ Rtext *hitword; /* text to hilite */ - Image *hitsave; /* for restoring hilit text */ + Rtext *hitfirst; /* first word in range select */ + Image *hitsave; /* for restoring hilit text */ int twid; /* text width */ int thgt; /* text height */ Point minsize; /* smallest acceptible window size */ int buttons; + char *snarf; + char *esnarf; }; -void pl_hiliteword(Panel *p, Rtext *w, int on){ + +/* + * Highlight a range of words from s to e. + */ +void pl_hilitewords(Panel *p, Rtext *s, Rtext *e, int on) +{ Point ul, size; Rectangle r; Textview *tp; - if(w==0 || (w->b==0 && w->p!=0)) return; + Rtext *t; + + if(s==0 || e==0) + return; + for(t=s; t!=0 && t!=e; t=t->next) + ; + if(t==e){ + r=s->r; + for(t=s; t!=e; t=t->next) + combinerect(&r, t->r); + }else{ + r=e->r; + for(t=e; t!=s; t=t->next) + combinerect(&r, t->r); + } + combinerect(&r, t->r); + tp=p->data; ul=p->r.min; size=subpt(p->r.max, p->r.min); pl_interior(UP, &ul, &size); ul.y-=tp->yoffs; - r=rectaddpt(w->r, ul); - if(rectclip(&r, p->r)){ - if(on){ - if(tp->hitsave) freeimage(tp->hitsave); - tp->hitsave = allocimage(display, r, screen->chan, 0, DNofill); - if(tp->hitsave) draw(tp->hitsave, r, p->b, 0, r.min); - pl_highlight(p->b, r); - }else{ - if(tp->hitsave){ - draw(p->b, r, tp->hitsave, 0, r.min); - freeimage(tp->hitsave); - tp->hitsave = 0; + r=rectaddpt(r, ul); + if(rectclip(&r, p->r)==0) + return; + + if(on){ + if(tp->hitsave) freeimage(tp->hitsave); + tp->hitsave = allocimage(display, r, screen->chan, 0, DNofill); + if(tp->hitsave) draw(tp->hitsave, r, p->b, 0, r.min); + if(t==e){ + for(t=s; t!=e; t=t->next){ + if(t->p!=0) continue; + r=rectaddpt(t->r, ul); + if(rectclip(&r, p->r)) + pl_highlight(p->b, r); } + }else{ + for(t=e; t!=s; t=t->next){ + if(t->p!=0) continue; + r=rectaddpt(t->r, ul); + if(rectclip(&r, p->r)) + pl_highlight(p->b, r); + } + } + if(t->p==0){ + r=rectaddpt(t->r, ul); + if(rectclip(&r, p->r)) + pl_highlight(p->b, r); + } + } else { + if(tp->hitsave){ + draw(p->b, r, tp->hitsave, 0, r.min); + freeimage(tp->hitsave); + tp->hitsave = 0; } } } + void pl_stuffbitmap(Panel *p, Image *b){ p->b=b; for(p=p->child;p;p=p->next) @@ -69,7 +116,7 @@ void pl_drawnon(Rtext *rp, Image *b){ void pl_fixtextview(Panel *p, Textview *tp, Rectangle r){ Panel *sb; int lo, hi; - pl_hiliteword(p, tp->hitword, 1); + pl_hilitewords(p, tp->hitword, tp->hitfirst, 1); lo=tp->yoffs; hi=lo+r.max.y-r.min.y; /* wrong? */ sb=p->yscroller; @@ -106,45 +153,52 @@ void pl_passon(Rtext *t, Mouse *m){ if(t && t->b==0 && t->p!=0) plmouse(t->p, m); } int pl_hittextview(Panel *p, Mouse *m){ - Rtext *oldhitword; - int hitme; + Rtext *oldhitword, *oldhitfirst; + int hitme, oldstate; Point ul, size; Textview *tp; - tp=p->data; - oldhitword=tp->hitword; - hitme=0; - pl_passon(oldhitword, m); + tp=p->data; + + hitme=0; + oldstate=p->state; + oldhitword=tp->hitword; + oldhitfirst=tp->hitfirst; + if(oldhitword==oldhitfirst) + pl_passon(oldhitword, m); if(m->buttons&OUT) p->state=UP; else if(m->buttons&7){ tp->buttons=m->buttons; p->state=DOWN; - if(oldhitword==0 - || oldhitword->b!=0 - || oldhitword->p==0 - || (oldhitword->p->flags&REMOUSE)==0){ - ul=p->r.min; - size=subpt(p->r.max, p->r.min); - pl_interior(p->state, &ul, &size); - tp->hitword=pl_rthit(tp->text, tp->yoffs, m->xy, ul); - if(tp->hitword!=0 && tp->hitword->hot==0) tp->hitword=0; - } + + ul=p->r.min; + size=subpt(p->r.max, p->r.min); + pl_interior(p->state, &ul, &size); + tp->hitword=pl_rthit(tp->text, tp->yoffs, m->xy, ul); + if(tp->hitword==0) + if(oldhitword!=0 && oldstate==DOWN) + tp->hitword=oldhitword; + else + tp->hitfirst=0; + if(tp->hitword!=0 && oldstate!=DOWN) + tp->hitfirst=tp->hitword; } else{ if(p->state==DOWN) hitme=1; p->state=UP; } - if(tp->hitword!=oldhitword){ - pl_hiliteword(p, oldhitword, 0); - pl_hiliteword(p, tp->hitword, 1); - pl_passon(tp->hitword, m); + if(tp->hitfirst!=oldhitfirst || tp->hitword!=oldhitword){ + pl_hilitewords(p, oldhitword, oldhitfirst, 0); + pl_hilitewords(p, tp->hitword, tp->hitfirst, 1); + if(tp->hitword==tp->hitfirst) + pl_passon(tp->hitword, m); } - if(hitme && tp->hit && tp->hitword){ - pl_hiliteword(p, tp->hitword, 0); - if(tp->hitword->b!=0 || tp->hitword->p==0) - tp->hit(p, tp->buttons, tp->hitword); + if(hitme && tp->hit && tp->hitword!=0 && tp->hitword==tp->hitfirst){ + pl_hilitewords(p, tp->hitword, tp->hitfirst, 0); + tp->hit(p, tp->buttons, tp->hitword); tp->hitword=0; + tp->hitfirst=0; } return 0; } @@ -176,7 +230,7 @@ void pl_scrolltextview(Panel *p, int dir, int buttons, int num, int den){ break; } if(yoffs!=tp->yoffs){ - pl_hiliteword(p, tp->hitword, 0); + pl_hilitewords(p, tp->hitword, tp->hitfirst, 0); r=pl_outline(p->b, p->r, p->state); pl_rtredraw(p->b, r, tp->text, yoffs, tp->yoffs); p->scr.pos.y=tp->yoffs=yoffs; @@ -227,7 +281,9 @@ void plinittextview(Panel *v, int flags, Point minsize, Rtext *t, void (*hit)(Pa tp->minsize=minsize; tp->text=t; tp->yoffs=0; + tp->hitfirst=0; tp->hitword=0; + tp->esnarf=tp->snarf=0; v->scroll=pl_scrolltextview; tp->twid=-1; v->scr.pos=Pt(0,0); @@ -246,3 +302,47 @@ void plsetpostextview(Panel *p, int yoffs){ ((Textview *)p->data)->yoffs=yoffs; pldraw(p, p->b); } + +static void +snarfword(Textview *tp, Rtext *w){ + char *b; + int n; + if(w->b!=0 || w->p!=0 || w->text==0) + return; + n = strlen(w->text)+4; + if((b = realloc(tp->snarf, (tp->esnarf+n) - tp->snarf)) == nil) + return; + tp->esnarf = (tp->esnarf - tp->snarf) + b; + tp->snarf = b; + if(w->space == 0) + tp->esnarf += sprint(tp->esnarf, "%s", w->text); + else if(w->space > 0) + tp->esnarf += sprint(tp->esnarf, " %s", w->text); + else if(PL_OP(w->space) == PL_TAB) + tp->esnarf += sprint(tp->esnarf, "\t%s", w->text); + if(w->nextline == w->next) + tp->esnarf += sprint(tp->esnarf, "\n"); +} + +char *plsnarftext(Panel *p){ + Rtext *t, *s, *e; + Textview *tp; + tp=p->data; + free(tp->snarf); + tp->snarf=tp->esnarf=0; + s = tp->hitfirst; + e = tp->hitword; + if(s==0 || e==0) + return nil; + for(t=s; t!=0 && t!=e; t=t->next) + ; + if(t==e){ + for(t=s; t!=e; t=t->next) + snarfword(tp, t); + }else{ + for(t=e; t!=s; t=t->next) + snarfword(tp, t); + } + snarfword(tp, t); + return tp->snarf; +} diff --git a/sys/src/cmd/mothra/mothra.c b/sys/src/cmd/mothra/mothra.c index 058d58d64..ecd724d31 100644 --- a/sys/src/cmd/mothra/mothra.c +++ b/sys/src/cmd/mothra/mothra.c @@ -90,7 +90,7 @@ void killpix(Www *w); char *buttons[]={ "alt display", "moth mode", - "snarf url", + "snarf", "paste", "save hit", "hit list", @@ -1015,9 +1015,14 @@ void killpix(Www *w){ } void snarf(Panel *p){ + char *s; int fd; + if((fd=open("/dev/snarf", OWRITE|OTRUNC))>=0){ - fprint(fd, "%s", urlstr(selection)); + s = plsnarftext(text); + if(s==0) + s = urlstr(selection); + fprint(fd, "%s", s); close(fd); } }