mothra: snarf and paste

This commit is contained in:
cinap_lenrek 2012-09-23 20:14:47 +02:00
parent f68d096fb7
commit 948d0a1180
12 changed files with 143 additions and 133 deletions

View file

@ -97,11 +97,12 @@ Clicking the
.B moth mode .B moth mode
menu option again exits moth mode. menu option again exits moth mode.
.TP .TP
.B snarf url .B snarf
Copy the current URL to the snarf buffer. Copy the current entry text or selected page text to snarf buffer.
If nothing is selected, the current URL is copied.
.TP .TP
.B paste .B paste
Paste the current snarf buffer at the current cursor position. Paste the snarf buffer to the current text entry.
.TP .TP
.B save hit .B save hit
Save the current URL to the hit list. Save the current URL to the hit list.

View file

@ -139,6 +139,7 @@ void pl_interior(int state, Point *ul, Point *size){
*size=subpt(*size, Pt(4*FWID+2*SPACE, 4*FWID+2*SPACE)); *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){ void pl_drawicon(Image *b, Rectangle r, int stick, int flags, Icon *s){
Rectangle save; Rectangle save;
Point ul, offs; Point ul, offs;

View file

@ -48,46 +48,25 @@ void pl_drawedit(Panel *p){
if(sb && sb->setscrollbar) if(sb && sb->setscrollbar)
sb->setscrollbar(sb, ep->t->top, ep->t->bot, ep->t->etext-ep->t->text); 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 *pl_snarfedit(Panel *p){
char *s, *x; int s0, s1;
Rune *t; Rune *t;
if((fd=open("/dev/snarf", cut ? OWRITE|OTRUNC : OREAD))<0) t=pleget(p);
return; plegetsel(p, &s0, &s1);
if(cut){ if(t==0 || s0>=s1)
t=pleget(p); return nil;
plegetsel(p, &s0, &s1); return smprint("%.*S", s1-s0, t+s0);
if(t==0 || s0>=s1){ }
close(fd); void pl_pasteedit(Panel *p, char *s){
return; Rune *t;
} if(t=runesmprint("%s", s)){
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);
plepaste(p, t, runestrlen(t)); plepaste(p, t, runestrlen(t));
free(s);
free(t); free(t);
} }
close(fd);
} }
/* /*
* Should do double-clicks: * Should do double-clicks:
* If ep->sel0==ep->sel1 on entry and the * If ep->sel0==ep->sel1 on entry and the
@ -106,18 +85,20 @@ void pl_snarfedit(Panel *p, int cut){
*/ */
int pl_hitedit(Panel *p, Mouse *m){ int pl_hitedit(Panel *p, Mouse *m){
Edit *ep; Edit *ep;
if((m->buttons&7)==1){ if(m->buttons&1){
plgrabkb(p);
ep=p->data; ep=p->data;
ep->t->b=p->b; ep->t->b=p->b;
twhilite(ep->t, ep->sel0, ep->sel1, 0); twhilite(ep->t, ep->sel0, ep->sel1, 0);
twselect(ep->t, m); twselect(ep->t, m);
ep->sel0=ep->t->sel0; ep->sel0=ep->t->sel0;
ep->sel1=ep->t->sel1; ep->sel1=ep->t->sel1;
plgrabkb(p); if((m->buttons&7)==3){
if((m->buttons&7)==3) plsnarf(p);
pl_snarfedit(p, 1); plepaste(p, 0, 0); /* cut */
}
else if((m->buttons&7)==5) else if((m->buttons&7)==5)
pl_snarfedit(p, 0); plpaste(p);
else if(ep->hit) else if(ep->hit)
(*ep->hit)(p); (*ep->hit)(p);
} }
@ -171,7 +152,13 @@ void pl_typeedit(Panel *p, Rune c){
twhilite(t, ep->sel0, ep->sel1, 0); twhilite(t, ep->sel0, ep->sel1, 0);
switch(c){ switch(c){
case Kesc: 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; break;
case Kbs: /* ^H: erase character */ case Kbs: /* ^H: erase character */
if(ep->sel0!=0) --ep->sel0; if(ep->sel0!=0) --ep->sel0;
@ -187,6 +174,8 @@ void pl_typeedit(Panel *p, Rune c){
twreplace(t, ep->sel0, ep->sel1, 0, 0); twreplace(t, ep->sel0, ep->sel1, 0, 0);
break; break;
default: default:
if((c & 0xFF00) == KF || (c & 0xFF00) == Spec)
break;
twreplace(t, ep->sel0, ep->sel1, &c, 1); twreplace(t, ep->sel0, ep->sel1, &c, 1);
++ep->sel0; ++ep->sel0;
break; break;
@ -233,6 +222,8 @@ void plinitedit(Panel *v, int flags, Point minsize, Rune *text, int ntext, void
v->getsize=pl_getsizeedit; v->getsize=pl_getsizeedit;
v->childspace=pl_childspaceedit; v->childspace=pl_childspaceedit;
v->free=pl_freeedit; v->free=pl_freeedit;
v->snarf=pl_snarfedit;
v->paste=pl_pasteedit;
v->kind="edit"; v->kind="edit";
ep->hit=hit; ep->hit=hit;
ep->minsize=minsize; ep->minsize=minsize;

View file

@ -15,35 +15,31 @@ struct Entry{
Point minsize; Point minsize;
}; };
#define SLACK 7 /* enough for one extra rune and ◀ and a nul */ #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; Entry *ep;
int fd, n; int n;
char *s;
ep=p->data; 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; return;
if(cut){ ep->entry=e;
if((n=ep->entp-ep->entry)>0) e+=n;
write(fd, ep->entry, n); strncpy(e, s, m);
ep->entp=ep->entry; e+=m;
}else{ *e='\0';
n=1024; ep->entp=ep->eent=e;
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';
pldraw(p, p->b); pldraw(p, p->b);
} }
void pl_drawentry(Panel *p){ void pl_drawentry(Panel *p){
@ -68,20 +64,29 @@ void pl_drawentry(Panel *p){
free(s); free(s);
} }
int pl_hitentry(Panel *p, Mouse *m){ int pl_hitentry(Panel *p, Mouse *m){
if((m->buttons&OUT)==0 && (m->buttons&7)){ if((m->buttons&7)==1){
plgrabkb(p); plgrabkb(p);
p->state=DOWN; p->state=DOWN;
pldraw(p, p->b); pldraw(p, p->b);
while(m->buttons&7){ while(m->buttons&1){
int old; int old;
old=m->buttons; old=m->buttons;
*m=emouse(); *m=emouse();
if((old&7)==1){ if((old&7)==1){
if((m->buttons&7)==3) if((m->buttons&7)==3){
pl_snarfentry(p, 1); Entry *ep;
plsnarf(p);
/* cut */
ep=p->data;
ep->entp=ep->entry;
*ep->entp='\0';
pldraw(p, p->b);
}
if((m->buttons&7)==5) if((m->buttons&7)==5)
pl_snarfentry(p, 0); plpaste(p);
} }
} }
p->state=UP; p->state=UP;
@ -100,8 +105,9 @@ void pl_typeentry(Panel *p, Rune c){
if(ep->hit) ep->hit(p, ep->entry); if(ep->hit) ep->hit(p, ep->entry);
return; return;
case Kesc: case Kesc:
pl_snarfentry(p, 1); plsnarf(p);
return; /* no break */
case Kdel: /* clear */
case Knack: /* ^U: erase line */ case Knack: /* ^U: erase line */
ep->entp=ep->entry; ep->entp=ep->entry;
*ep->entp='\0'; *ep->entp='\0';
@ -118,7 +124,7 @@ void pl_typeentry(Panel *p, Rune c){
*ep->entp='\0'; *ep->entp='\0';
break; break;
default: default:
if(c < 0x20 || c == Kdel || (c & 0xFF00) == KF || (c & 0xFF00) == Spec) if(c < 0x20 || (c & 0xFF00) == KF || (c & 0xFF00) == Spec)
break; break;
ep->entp+=runetochar(ep->entp, &c); ep->entp+=runetochar(ep->entp, &c);
if(ep->entp>ep->eent){ if(ep->entp>ep->eent){
@ -162,6 +168,8 @@ void plinitentry(Panel *v, int flags, int wid, char *str, void (*hit)(Panel *, c
v->childspace=pl_childspaceentry; v->childspace=pl_childspaceentry;
ep->minsize=Pt(wid, font->height); ep->minsize=Pt(wid, font->height);
v->free=pl_freeentry; v->free=pl_freeentry;
v->snarf=pl_snarfentry;
v->paste=pl_pasteentry;
elen=100; elen=100;
if(str) elen+=strlen(str); if(str) elen+=strlen(str);
if(ep->entry==nil) if(ep->entry==nil)

View file

@ -4,16 +4,17 @@
#include <event.h> #include <event.h>
#include <panel.h> #include <panel.h>
#include "pldefs.h" #include "pldefs.h"
Panel *pl_kbfocus;
void plgrabkb(Panel *g){ void plgrabkb(Panel *g){
pl_kbfocus=g; plkbfocus=g;
} }
void plkeyboard(Rune c){ void plkeyboard(Rune c){
if(pl_kbfocus){ if(plkbfocus){
pl_kbfocus->type(pl_kbfocus, c); plkbfocus->type(plkbfocus, c);
flushimage(display, 1); flushimage(display, 1);
} }
} }
/* /*
* Return the most leafward, highest priority panel containing p * Return the most leafward, highest priority panel containing p
*/ */

View file

@ -89,6 +89,8 @@ Panel *pl_newpanel(Panel *parent, int ndata){
v->scroll=pl_scrollerror; v->scroll=pl_scrollerror;
v->setscrollbar=pl_setscrollbarerror; v->setscrollbar=pl_setscrollbarerror;
v->free=0; v->free=0;
v->snarf=0;
v->paste=0;
if(ndata) if(ndata)
v->data=pl_emalloc(ndata); v->data=pl_emalloc(ndata);
else else
@ -99,6 +101,8 @@ void plfree(Panel *p){
Panel *cp, *ncp; Panel *cp, *ncp;
if(p==0) if(p==0)
return; return;
if(p==plkbfocus)
plkbfocus=0;
for(cp=p->child;cp;cp=ncp){ for(cp=p->child;cp;cp=ncp){
ncp=cp->next; ncp=cp->next;
plfree(cp); plfree(cp);

View file

@ -26,7 +26,8 @@ OFILES=\
slider.$O\ slider.$O\
textview.$O\ textview.$O\
textwin.$O\ textwin.$O\
utf.$O utf.$O\
snarf.$O
HFILES=panel.h pldefs.h rtext.h HFILES=panel.h pldefs.h rtext.h

View file

@ -55,6 +55,8 @@ struct Panel{
void (*scroll)(Panel *, int, int, int, int); /* scroll bar to scrollee */ void (*scroll)(Panel *, int, int, int, int); /* scroll bar to scrollee */
void (*setscrollbar)(Panel *, int, int, int); /* scrollee to scroll bar */ void (*setscrollbar)(Panel *, int, int, int); /* scrollee to scroll bar */
void (*free)(Panel *); /* free fields of data when done */ 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 * Panel flags
@ -101,6 +103,8 @@ struct Panel{
#define PL_HOT 1 #define PL_HOT 1
#define PL_SEL 2 #define PL_SEL 2
Panel *plkbfocus; /* the panel in keyboard focus */
int plinit(int); /* initialization */ int plinit(int); /* initialization */
void plpack(Panel *, Rectangle); /* figure out where to put the Panel & children */ 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 */ void plmove(Panel *, Point); /* move an already-packed panel to a new location */
@ -122,6 +126,7 @@ void plescroll(Panel *, int); /* scroll an edit window */
Scroll plgetscroll(Panel *); /* get scrolling information from panel */ Scroll plgetscroll(Panel *); /* get scrolling information from panel */
void plsetscroll(Panel *, Scroll); /* set scrolling information */ void plsetscroll(Panel *, Scroll); /* set scrolling information */
void plplacelabel(Panel *, int); /* label placement */ void plplacelabel(Panel *, int); /* label placement */
/* /*
* Panel creation & reinitialization functions * Panel creation & reinitialization functions
*/ */
@ -174,7 +179,6 @@ char *plrtsnarftext(Rtext *);
int plgetpostextview(Panel *); int plgetpostextview(Panel *);
void plsetpostextview(Panel *, int); void plsetpostextview(Panel *, int);
char *plsnarftext(Panel *);
/* /*
* Idols * Idols
@ -183,3 +187,11 @@ Idol *plmkidol(Idol**, Image*, Image*, char*, void*);
void plfreeidol(Idol*); void plfreeidol(Idol*);
Point plidolsize(Idol*, Font*, int); Point plidolsize(Idol*, Font*, int);
void *plidollistgetsel(Panel*); void *plidollistgetsel(Panel*);
/*
* Snarf
*/
void plputsnarf(char *);
char *plgetsnarf(void);
void plsnarf(Panel *); /* snarf a panel */
void plpaste(Panel *); /* paste a panel */

View file

@ -75,6 +75,8 @@ int pl_hitpopup(Panel *g, Mouse *m){
} }
} }
plmouse(p, m); plmouse(p, m);
if((m->buttons&7)==0)
g->state=UP;
return (m->buttons&7)!=0; return (m->buttons&7)!=0;
} }
void pl_typepopup(Panel *g, Rune c){ void pl_typepopup(Panel *g, Rune c){

View file

@ -291,26 +291,30 @@ void plrtseltext(Rtext *t, Rtext *s, Rtext *e){
} }
char *plrtsnarftext(Rtext *w){ char *plrtsnarftext(Rtext *w){
char *b, *p, *e; char *b, *p, *e, *t;
int n; int n;
p = e = 0; b=p=e=0;
for(; w; w = w->next){ 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; continue;
n = strlen(w->text)+4; n = strlen(w->text)+64;
if((b = realloc(p, (e+n) - p)) == nil) if(p+n >= e){
break; n = (p+n+64)-b;
e = (e - p) + b; if((t = realloc(b, n))==0)
p = b; break;
p = t+(p-b);
e = t+n;
b = t;
}
if(w->space == 0) if(w->space == 0)
e += sprint(e, "%s", w->text); p += sprint(p, "%s", w->text);
else if(w->space > 0) 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) 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) if(w->nextline == w->next)
e += sprint(e, "\n"); p += sprint(p, "\n");
} }
return p; return b;
} }

View file

@ -52,7 +52,8 @@ void pl_drawtextview(Panel *p){
* If t is a panel word, pass the mouse event on to it * If t is a panel word, pass the mouse event on to it
*/ */
void pl_passon(Rtext *t, Mouse *m){ 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){ int pl_hittextview(Panel *p, Mouse *m){
Rtext *oldhitword, *oldhitfirst; Rtext *oldhitword, *oldhitfirst;
@ -166,6 +167,11 @@ int pl_pritextview(Panel *p, Point xy){
} }
return PRI_NORMAL; 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 *)){ void plinittextview(Panel *v, int flags, Point minsize, Rtext *t, void (*hit)(Panel *, int, Rtext *)){
Textview *tp; Textview *tp;
tp=v->data; tp=v->data;
@ -185,6 +191,7 @@ void plinittextview(Panel *v, int flags, Point minsize, Rtext *t, void (*hit)(Pa
tp->hitfirst=0; tp->hitfirst=0;
tp->hitword=0; tp->hitword=0;
v->scroll=pl_scrolltextview; v->scroll=pl_scrolltextview;
v->snarf=pl_snarftextview;
tp->twid=-1; tp->twid=-1;
v->scr.pos=Pt(0,0); v->scr.pos=Pt(0,0);
v->scr.size=Pt(0,1); v->scr.size=Pt(0,1);
@ -202,9 +209,3 @@ void plsetpostextview(Panel *p, int yoffs){
((Textview *)p->data)->yoffs=yoffs; ((Textview *)p->data)->yoffs=yoffs;
pldraw(p, p->b); pldraw(p, p->b);
} }
char* plsnarftext(Panel *p){
static char *b = nil;
free(b);
b = plrtsnarftext(((Textview *)p->data)->text);
return b;
}

View file

@ -118,20 +118,21 @@ int subpanel(Panel *obj, Panel *subj){
* Make sure that the keyboard focus is on-screen, by adjusting it to * Make sure that the keyboard focus is on-screen, by adjusting it to
* be the cmd entry if necessary. * be the cmd entry if necessary.
*/ */
void adjkb(void){ int adjkb(void){
Rtext *t; Rtext *t;
int yoffs; int yoffs;
extern Panel *pl_kbfocus; /* this is a secret panel library name */
if(current){ if(current){
yoffs=text->r.min.y-plgetpostextview(text); yoffs=text->r.min.y-plgetpostextview(text);
for(t=current->text;t;t=t->next) if(!eqrect(t->r, Rect(0,0,0,0))){ 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.max.y+yoffs>=text->r.min.y
if(t->r.min.y+yoffs>=text->r.min.y && t->r.min.y+yoffs<text->r.max.y
&& t->b==0 && t->b==0
&& subpanel(t->p, pl_kbfocus)) return; && subpanel(t->p, plkbfocus))
return 1;
} }
} }
plgrabkb(cmd); plgrabkb(cmd);
return 0;
} }
void scrolltext(int dy, int whence) void scrolltext(int dy, int whence)
@ -1013,33 +1014,16 @@ void killpix(Www *w){
w->pix=0; w->pix=0;
updtext(w); updtext(w);
} }
void snarf(Panel *p){ void snarf(Panel *p){
char *s; if(p==0) p=cmd;
int fd; plputsnarf(urlstr(selection));
/* non-ops if nothing selected */
if((fd=open("/dev/snarf", OWRITE|OTRUNC))>=0){ plsnarf(p);
s = plsnarftext(text); plsnarf(text);
if(s==0)
s = urlstr(selection);
fprint(fd, "%s", s);
close(fd);
}
} }
void paste(Panel *p){ void paste(Panel *p){
char buf[1024]; if(p==0) p=cmd;
int n, len, fd; plpaste(p);
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);
} }
void hit3(int button, int item){ void hit3(int button, int item){
char name[NNAME]; char name[NNAME];
@ -1069,10 +1053,10 @@ void hit3(int button, int item){
mothon(current, !mothmode); mothon(current, !mothmode);
break; break;
case 2: case 2:
snarf(cmd); snarf(plkbfocus);
break; break;
case 3: case 3:
paste(cmd); paste(plkbfocus);
break; break;
case 4: case 4:
snprint(name, sizeof(name), "%s/hit.html", home); snprint(name, sizeof(name), "%s/hit.html", home);