shithub: riscv

Download patch

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);
 	}
 }