ref: f34ef5a8d43bdf2728cefb12707be8ea4f2052bb
parent: 9a06f93b71e339741ac6078a0246e11e789aa784
author: cinap_lenrek <[email protected]>
date: Sat Sep 22 13:46:56 EDT 2012
mothra: first attempt on text selection
--- a/sys/src/cmd/mothra/libpanel/draw.c
+++ b/sys/src/cmd/mothra/libpanel/draw.c
@@ -17,21 +17,11 @@
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;
}
--- a/sys/src/cmd/mothra/libpanel/panel.h
+++ b/sys/src/cmd/mothra/libpanel/panel.h
@@ -166,6 +166,8 @@
void plrtfree(Rtext *);
int plgetpostextview(Panel *);
void plsetpostextview(Panel *, int);
+char *plsnarftext(Panel *);
+
/*
* Idols
*/
--- a/sys/src/cmd/mothra/libpanel/textview.c
+++ b/sys/src/cmd/mothra/libpanel/textview.c
@@ -10,6 +10,8 @@
#include <event.h>
#include <panel.h>
#include "pldefs.h"
+#include "rtext.h"
+
typedef struct Textview Textview;
struct Textview{
void (*hit)(Panel *, int, Rtext *); /* call back to user on hit */
@@ -16,38 +18,83 @@
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);
+ 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{
- if(tp->hitsave){
- draw(p->b, r, tp->hitsave, 0, r.min);
- freeimage(tp->hitsave);
- tp->hitsave = 0;
+ 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_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 @@
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);
+ 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 @@
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 @@
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);
@@ -245,4 +301,48 @@
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;
}
--- a/sys/src/cmd/mothra/mothra.c
+++ b/sys/src/cmd/mothra/mothra.c
@@ -90,7 +90,7 @@
char *buttons[]={
"alt display",
"moth mode",
- "snarf url",
+ "snarf",
"paste",
"save hit",
"hit list",
@@ -1015,9 +1015,14 @@
}
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);
}
}