git: 9front

Download patch

ref: 50c661ce3e4ff694080d8ff68167b507a4baf153
parent: 67ea0e0d70e735cfc86e3e82a37e3a911fe243e6
author: cinap_lenrek <cinap_lenrek@gmx.de>
date: Sun Sep 23 16:14:47 EDT 2012

mothra: snarf and paste

--- a/sys/man/1/mothra
+++ b/sys/man/1/mothra
@@ -97,11 +97,12 @@
 .B moth mode
 menu option again exits moth mode.
 .TP
-.B snarf url
-Copy the current URL to the snarf buffer.
+.B snarf
+Copy the current entry text or selected page text to snarf buffer.
+If nothing is selected, the current URL is copied.
 .TP
 .B paste
-Paste the current snarf buffer at the current cursor position.
+Paste the snarf buffer to the current text entry.
 .TP
 .B save hit
 Save the current URL to the hit list.
--- a/sys/src/cmd/mothra/libpanel/draw.c
+++ b/sys/src/cmd/mothra/libpanel/draw.c
@@ -139,6 +139,7 @@
 		*size=subpt(*size, Pt(4*FWID+2*SPACE, 4*FWID+2*SPACE));
 	}
 }
+
 void pl_drawicon(Image *b, Rectangle r, int stick, int flags, Icon *s){
 	Rectangle save;
 	Point ul, offs;
--- a/sys/src/cmd/mothra/libpanel/edit.c
+++ b/sys/src/cmd/mothra/libpanel/edit.c
@@ -48,46 +48,25 @@
 	if(sb && sb->setscrollbar)
 		sb->setscrollbar(sb, ep->t->top, ep->t->bot, ep->t->etext-ep->t->text);
 }
-void pl_snarfedit(Panel *p, int cut){
-	int fd, n, r, s0, s1;
-	char *s, *x;
+
+char *pl_snarfedit(Panel *p){
+	int s0, s1;
 	Rune *t;
 
-	if((fd=open("/dev/snarf", cut ? OWRITE|OTRUNC : OREAD))<0)
-		return;
-	if(cut){
-		t=pleget(p);
-		plegetsel(p, &s0, &s1);
-		if(t==0 || s0>=s1){
-			close(fd);
-			return;
-		}
-		s = smprint("%.*S", s1-s0, t+s0);
-		if((n = strlen(s))>0)
-			write(fd, s, n);
-		free(s);
-		plepaste(p, 0, 0);
-	}else{
-		n=0;
-		s=nil;
-		for(;;){
-			if((x=realloc(s, n+1024)) == nil){
-				free(s);
-				close(fd);
-				return;
-			}
-			s=x;
-			if((r = read(fd, s+n, 1024)) <= 0)
-				break;
-			n += r;
-		}
-		t=runesmprint("%.*s", n, s);
+	t=pleget(p);
+	plegetsel(p, &s0, &s1);
+	if(t==0 || s0>=s1)
+		return nil;
+	return smprint("%.*S", s1-s0, t+s0);
+}
+void pl_pasteedit(Panel *p, char *s){
+	Rune *t;
+	if(t=runesmprint("%s", s)){
 		plepaste(p, t, runestrlen(t));
-		free(s);
 		free(t);
 	}
-	close(fd);
 }
+
 /*
  * Should do double-clicks:
  *	If ep->sel0==ep->sel1 on entry and the
@@ -106,7 +85,8 @@
  */
 int pl_hitedit(Panel *p, Mouse *m){
 	Edit *ep;
-	if((m->buttons&7)==1){
+	if(m->buttons&1){
+		plgrabkb(p);
 		ep=p->data;
 		ep->t->b=p->b;
 		twhilite(ep->t, ep->sel0, ep->sel1, 0);
@@ -113,11 +93,12 @@
 		twselect(ep->t, m);
 		ep->sel0=ep->t->sel0;
 		ep->sel1=ep->t->sel1;
-		plgrabkb(p);
-		if((m->buttons&7)==3)
-			pl_snarfedit(p, 1);
+		if((m->buttons&7)==3){
+			plsnarf(p);
+			plepaste(p, 0, 0);	/* cut */
+		}
 		else if((m->buttons&7)==5)
-			pl_snarfedit(p, 0);
+			plpaste(p);
 		else if(ep->hit)
 			(*ep->hit)(p);
 	}
@@ -171,8 +152,14 @@
 	twhilite(t, ep->sel0, ep->sel1, 0);
 	switch(c){
 	case Kesc:
-		pl_snarfedit(p, 1);
+		plsnarf(p);
+		plepaste(p, 0, 0);	/* cut */
 		break;
+	case Kdel:	/* clear */
+		ep->sel0=0;
+		ep->sel1=plelen(p);
+		plepaste(p, 0, 0);	/* cut */
+		break;
 	case Kbs:	/* ^H: erase character */
 		if(ep->sel0!=0) --ep->sel0;
 		twreplace(t, ep->sel0, ep->sel1, 0, 0);
@@ -187,6 +174,8 @@
 		twreplace(t, ep->sel0, ep->sel1, 0, 0);
 		break;
 	default:
+		if((c & 0xFF00) == KF || (c & 0xFF00) == Spec)
+			break;
 		twreplace(t, ep->sel0, ep->sel1, &c, 1);
 		++ep->sel0;
 		break;
@@ -233,6 +222,8 @@
 	v->getsize=pl_getsizeedit;
 	v->childspace=pl_childspaceedit;
 	v->free=pl_freeedit;
+	v->snarf=pl_snarfedit;
+	v->paste=pl_pasteedit;
 	v->kind="edit";
 	ep->hit=hit;
 	ep->minsize=minsize;
--- a/sys/src/cmd/mothra/libpanel/entry.c
+++ b/sys/src/cmd/mothra/libpanel/entry.c
@@ -15,35 +15,31 @@
 	Point minsize;
 };
 #define	SLACK	7	/* enough for one extra rune and ◀ and a nul */
-void pl_snarfentry(Panel *p, int cut){
+char *pl_snarfentry(Panel *p){
 	Entry *ep;
-	int fd, n;
-	char *s;
+	int n;
 
 	ep=p->data;
-	if((fd=open("/dev/snarf", cut ? OWRITE|OTRUNC : OREAD))<0)
+	n=ep->entp-ep->entry;
+	if(n<=0) return nil;
+	return smprint("%.*s", n, ep->entry);
+}
+void pl_pasteentry(Panel *p, char *s){
+	Entry *ep;
+	char *e;
+	int n, m;
+
+	ep=p->data;
+	n=ep->entp-ep->entry;
+	m=strlen(s);
+	if((e=realloc(ep->entry,n+m+SLACK))==0)
 		return;
-	if(cut){
-		if((n=ep->entp-ep->entry)>0)
-			write(fd, ep->entry, n);
-		ep->entp=ep->entry;
-	}else{
-		n=1024;
-		s=malloc(n+SLACK);
-		if(s==0){
-			close(fd);
-			return;
-		}
-		if((n=readn(fd, s, n))<0)
-			n=0;
-		free(ep->entry);
-		s=realloc(s, n+SLACK);
-		ep->entry=s;
-		ep->eent=s+n;
-		ep->entp=s+n;
-	}
-	close(fd);
-	*ep->entp='\0';
+	ep->entry=e;
+	e+=n;
+	strncpy(e, s, m);
+	e+=m;
+	*e='\0';
+	ep->entp=ep->eent=e;
 	pldraw(p, p->b);
 }
 void pl_drawentry(Panel *p){
@@ -68,20 +64,29 @@
 		free(s);
 }
 int pl_hitentry(Panel *p, Mouse *m){
-	if((m->buttons&OUT)==0 && (m->buttons&7)){
+	if((m->buttons&7)==1){
 		plgrabkb(p);
 
 		p->state=DOWN;
 		pldraw(p, p->b);
-		while(m->buttons&7){
+		while(m->buttons&1){
 			int old;
 			old=m->buttons;
 			*m=emouse();
 			if((old&7)==1){
-				if((m->buttons&7)==3)
-					pl_snarfentry(p, 1);
+				if((m->buttons&7)==3){
+					Entry *ep;
+
+					plsnarf(p);
+
+					/* cut */
+					ep=p->data;
+					ep->entp=ep->entry;
+					*ep->entp='\0';
+					pldraw(p, p->b);
+				}
 				if((m->buttons&7)==5)
-					pl_snarfentry(p, 0);
+					plpaste(p);
 			}
 		}
 		p->state=UP;
@@ -100,8 +105,9 @@
 		if(ep->hit) ep->hit(p, ep->entry);
 		return;
 	case Kesc:
-		pl_snarfentry(p, 1);
-		return;
+		plsnarf(p);
+		/* no break */
+	case Kdel:	/* clear */
 	case Knack:	/* ^U: erase line */
 		ep->entp=ep->entry;
 		*ep->entp='\0';
@@ -118,7 +124,7 @@
 		*ep->entp='\0';
 		break;
 	default:
-		if(c < 0x20 || c == Kdel || (c & 0xFF00) == KF || (c & 0xFF00) == Spec)
+		if(c < 0x20 || (c & 0xFF00) == KF || (c & 0xFF00) == Spec)
 			break;
 		ep->entp+=runetochar(ep->entp, &c);
 		if(ep->entp>ep->eent){
@@ -162,6 +168,8 @@
 	v->childspace=pl_childspaceentry;
 	ep->minsize=Pt(wid, font->height);
 	v->free=pl_freeentry;
+	v->snarf=pl_snarfentry;
+	v->paste=pl_pasteentry;
 	elen=100;
 	if(str) elen+=strlen(str);
 	if(ep->entry==nil)
--- a/sys/src/cmd/mothra/libpanel/event.c
+++ b/sys/src/cmd/mothra/libpanel/event.c
@@ -4,16 +4,17 @@
 #include <event.h>
 #include <panel.h>
 #include "pldefs.h"
-Panel *pl_kbfocus;
+
 void plgrabkb(Panel *g){
-	pl_kbfocus=g;
+	plkbfocus=g;
 }
 void plkeyboard(Rune c){
-	if(pl_kbfocus){
-		pl_kbfocus->type(pl_kbfocus, c);
+	if(plkbfocus){
+		plkbfocus->type(plkbfocus, c);
 		flushimage(display, 1);
 	}
 }
+
 /*
  * Return the most leafward, highest priority panel containing p
  */
--- a/sys/src/cmd/mothra/libpanel/mem.c
+++ b/sys/src/cmd/mothra/libpanel/mem.c
@@ -89,6 +89,8 @@
 	v->scroll=pl_scrollerror;
 	v->setscrollbar=pl_setscrollbarerror;
 	v->free=0;
+	v->snarf=0;
+	v->paste=0;
 	if(ndata)
 		v->data=pl_emalloc(ndata);
 	else
@@ -99,6 +101,8 @@
 	Panel *cp, *ncp;
 	if(p==0)
 		return;
+	if(p==plkbfocus)
+		plkbfocus=0;
 	for(cp=p->child;cp;cp=ncp){
 		ncp=cp->next;
 		plfree(cp);
--- a/sys/src/cmd/mothra/libpanel/mkfile
+++ b/sys/src/cmd/mothra/libpanel/mkfile
@@ -26,7 +26,8 @@
 	slider.$O\
 	textview.$O\
 	textwin.$O\
-	utf.$O
+	utf.$O\
+	snarf.$O
 
 HFILES=panel.h pldefs.h rtext.h
 
--- a/sys/src/cmd/mothra/libpanel/panel.h
+++ b/sys/src/cmd/mothra/libpanel/panel.h
@@ -55,6 +55,8 @@
 	void (*scroll)(Panel *, int, int, int, int);	/* scroll bar to scrollee */
 	void (*setscrollbar)(Panel *, int, int, int);	/* scrollee to scroll bar */
 	void (*free)(Panel *);				/* free fields of data when done */
+	char* (*snarf)(Panel *);			/* snarf text from panel */
+	void (*paste)(Panel *, char *);			/* paste text into panel */
 };
 /*
  * Panel flags
@@ -101,6 +103,8 @@
 #define PL_HOT		1
 #define PL_SEL		2
 
+Panel *plkbfocus;			/* the panel in keyboard focus */
+
 int plinit(int);			/* initialization */
 void plpack(Panel *, Rectangle);	/* figure out where to put the Panel & children */
 void plmove(Panel *, Point);		/* move an already-packed panel to a new location */
@@ -122,6 +126,7 @@
 Scroll plgetscroll(Panel *);		/* get scrolling information from panel */
 void plsetscroll(Panel *, Scroll);	/* set scrolling information */
 void plplacelabel(Panel *, int);	/* label placement */
+
 /*
  * Panel creation & reinitialization functions
  */
@@ -174,7 +179,6 @@
 
 int plgetpostextview(Panel *);
 void plsetpostextview(Panel *, int);
-char *plsnarftext(Panel *);
 
 /*
  * Idols
@@ -183,3 +187,11 @@
 void plfreeidol(Idol*);
 Point plidolsize(Idol*, Font*, int);
 void *plidollistgetsel(Panel*);
+
+/*
+ * Snarf
+ */
+void plputsnarf(char *);
+char *plgetsnarf(void);
+void plsnarf(Panel *);			/* snarf a panel */
+void plpaste(Panel *);			/* paste a panel */
--- a/sys/src/cmd/mothra/libpanel/popup.c
+++ b/sys/src/cmd/mothra/libpanel/popup.c
@@ -75,6 +75,8 @@
 		}
 	}
 	plmouse(p, m);
+	if((m->buttons&7)==0)
+		g->state=UP;
 	return (m->buttons&7)!=0;
 }
 void pl_typepopup(Panel *g, Rune c){
--- a/sys/src/cmd/mothra/libpanel/rtext.c
+++ b/sys/src/cmd/mothra/libpanel/rtext.c
@@ -291,26 +291,30 @@
 }
 
 char *plrtsnarftext(Rtext *w){
-	char *b, *p, *e;
+	char *b, *p, *e, *t;
 	int n;
 
-	p = e = 0;
+	b=p=e=0;
 	for(; w; w = w->next){
-		if((w->flags&PL_SEL)==0 || w->b!=0 || w->p!=0 || w->text==0)
+		if((w->flags&PL_SEL)==0 || w->text==0)
 			continue;
-		n = strlen(w->text)+4;
-		if((b = realloc(p, (e+n) - p)) == nil)
-			break;
-		e = (e - p) + b;
-		p = b;
+		n = strlen(w->text)+64;
+		if(p+n >= e){
+			n = (p+n+64)-b;
+			if((t = realloc(b, n))==0)
+				break;
+			p = t+(p-b);
+			e = t+n;
+			b = t;
+		}
 		if(w->space == 0)
-			e += sprint(e, "%s", w->text);
+			p += sprint(p, "%s", w->text);
 		else if(w->space > 0)
-			e += sprint(e, " %s", w->text);
+			p += sprint(p, " %s", w->text);
 		else if(PL_OP(w->space) == PL_TAB)
-			e += sprint(e, "\t%s", w->text);
+			p += sprint(p, "\t%s", w->text);
 		if(w->nextline == w->next)
-			e += sprint(e, "\n");
+			p += sprint(p, "\n");
 	}
-	return p;
+	return b;
 }
--- a/sys/src/cmd/mothra/libpanel/textview.c
+++ b/sys/src/cmd/mothra/libpanel/textview.c
@@ -52,7 +52,8 @@
  * If t is a panel word, pass the mouse event on to it
  */
 void pl_passon(Rtext *t, Mouse *m){
-	if(t && t->b==0 && t->p!=0) plmouse(t->p, m);
+	if(t && t->b==0 && t->p!=0)
+		plmouse(t->p, m);
 }
 int pl_hittextview(Panel *p, Mouse *m){
 	Rtext *oldhitword, *oldhitfirst;
@@ -166,6 +167,11 @@
 	}
 	return PRI_NORMAL;
 }
+
+char* pl_snarftextview(Panel *p){
+	return plrtsnarftext(((Textview *)p->data)->text);
+}
+
 void plinittextview(Panel *v, int flags, Point minsize, Rtext *t, void (*hit)(Panel *, int, Rtext *)){
 	Textview *tp;
 	tp=v->data;
@@ -185,6 +191,7 @@
 	tp->hitfirst=0;
 	tp->hitword=0;
 	v->scroll=pl_scrolltextview;
+	v->snarf=pl_snarftextview;
 	tp->twid=-1;
 	v->scr.pos=Pt(0,0);
 	v->scr.size=Pt(0,1);
@@ -201,10 +208,4 @@
 void plsetpostextview(Panel *p, int yoffs){
 	((Textview *)p->data)->yoffs=yoffs;
 	pldraw(p, p->b);
-}
-char* plsnarftext(Panel *p){
-	static char *b = nil;
-	free(b);
-	b = plrtsnarftext(((Textview *)p->data)->text);
-	return b;
 }
--- a/sys/src/cmd/mothra/mothra.c
+++ b/sys/src/cmd/mothra/mothra.c
@@ -118,20 +118,21 @@
  * Make sure that the keyboard focus is on-screen, by adjusting it to
  * be the cmd entry if necessary.
  */
-void adjkb(void){
+int adjkb(void){
 	Rtext *t;
 	int yoffs;
-	extern Panel *pl_kbfocus;	/* this is a secret panel library name */
 	if(current){
 		yoffs=text->r.min.y-plgetpostextview(text);
 		for(t=current->text;t;t=t->next) if(!eqrect(t->r, Rect(0,0,0,0))){
-			if(t->r.max.y+yoffs>text->r.max.y) break;
-			if(t->r.min.y+yoffs>=text->r.min.y
+			if(t->r.max.y+yoffs>=text->r.min.y
+			&& t->r.min.y+yoffs<text->r.max.y
 			&& t->b==0
-			&& subpanel(t->p, pl_kbfocus)) return;
+			&& subpanel(t->p, plkbfocus))
+				return 1;
 		}
 	}
 	plgrabkb(cmd);
+	return 0;
 }
 
 void scrolltext(int dy, int whence)
@@ -1013,33 +1014,16 @@
 	w->pix=0;
 	updtext(w);
 }
-
 void snarf(Panel *p){
-	char *s;
-	int fd;
-
-	if((fd=open("/dev/snarf", OWRITE|OTRUNC))>=0){
-		s = plsnarftext(text);
-		if(s==0)
-			s = urlstr(selection);
-		fprint(fd, "%s", s);
-		close(fd);
-	}
+	if(p==0) p=cmd;
+	plputsnarf(urlstr(selection));
+	/* non-ops if nothing selected */
+	plsnarf(p);
+	plsnarf(text);
 }
 void paste(Panel *p){
-	char buf[1024];
-	int n, len, fd;
-	if((fd=open("/dev/snarf", OREAD))<0)
-		return;
-	nstrcpy(buf, plentryval(p), sizeof(buf));
-	len=strlen(buf);
-	n=read(fd, buf+len, sizeof(buf)-len-1);
-	if(n>0){
-		buf[len+n]='\0';
-		plinitentry(cmd, PACKE|EXPAND, 0, buf, docmd);
-		pldraw(cmd, screen);
-	}
-	close(fd);
+	if(p==0) p=cmd;
+	plpaste(p);
 }
 void hit3(int button, int item){
 	char name[NNAME];
@@ -1069,10 +1053,10 @@
 		mothon(current, !mothmode);
 		break;
 	case 2:
-		snarf(cmd);
+		snarf(plkbfocus);
 		break;
 	case 3:
-		paste(cmd);
+		paste(plkbfocus);
 		break;
 	case 4:
 		snprint(name, sizeof(name), "%s/hit.html", home);
--