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
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.

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));
}
}
void pl_drawicon(Image *b, Rectangle r, int stick, int flags, Icon *s){
Rectangle save;
Point ul, offs;

View file

@ -48,46 +48,25 @@ void pl_drawedit(Panel *p){
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,18 +85,20 @@ void pl_snarfedit(Panel *p, int cut){
*/
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);
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,7 +152,13 @@ void pl_typeedit(Panel *p, Rune c){
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;
@ -187,6 +174,8 @@ void pl_typeedit(Panel *p, Rune c){
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 @@ void plinitedit(Panel *v, int flags, Point minsize, Rune *text, int ntext, void
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;

View file

@ -15,35 +15,31 @@ struct Entry{
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 @@ void pl_drawentry(Panel *p){
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 @@ void pl_typeentry(Panel *p, Rune c){
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 @@ void pl_typeentry(Panel *p, Rune c){
*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 @@ void plinitentry(Panel *v, int flags, int wid, char *str, void (*hit)(Panel *, c
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)

View file

@ -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
*/

View file

@ -89,6 +89,8 @@ Panel *pl_newpanel(Panel *parent, int ndata){
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 @@ void plfree(Panel *p){
Panel *cp, *ncp;
if(p==0)
return;
if(p==plkbfocus)
plkbfocus=0;
for(cp=p->child;cp;cp=ncp){
ncp=cp->next;
plfree(cp);

View file

@ -26,7 +26,8 @@ OFILES=\
slider.$O\
textview.$O\
textwin.$O\
utf.$O
utf.$O\
snarf.$O
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 (*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 @@ struct Panel{
#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 @@ void plescroll(Panel *, int); /* scroll an edit window */
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 @@ char *plrtsnarftext(Rtext *);
int plgetpostextview(Panel *);
void plsetpostextview(Panel *, int);
char *plsnarftext(Panel *);
/*
* Idols
@ -183,3 +187,11 @@ Idol *plmkidol(Idol**, Image*, Image*, char*, void*);
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 */

View file

@ -75,6 +75,8 @@ int pl_hitpopup(Panel *g, Mouse *m){
}
}
plmouse(p, m);
if((m->buttons&7)==0)
g->state=UP;
return (m->buttons&7)!=0;
}
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 *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;
}

View file

@ -52,7 +52,8 @@ void pl_drawtextview(Panel *p){
* 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 @@ int pl_pritextview(Panel *p, Point xy){
}
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 @@ void plinittextview(Panel *v, int flags, Point minsize, Rtext *t, void (*hit)(Pa
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);
@ -202,9 +209,3 @@ 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;
}

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
* 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 @@ void killpix(Www *w){
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 @@ void hit3(int button, int item){
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);