From bd998b2a78e32af7a2a8cf39ee8c11bbb3cd12ca Mon Sep 17 00:00:00 2001 From: cinap_lenrek Date: Sat, 22 Sep 2012 19:54:33 +0200 Subject: [PATCH] mothra: text selection 2nd attempt --- sys/src/cmd/mothra/forms.c | 2 +- sys/src/cmd/mothra/libpanel/panel.h | 10 +- sys/src/cmd/mothra/libpanel/rtext.c | 67 +++++++++++-- sys/src/cmd/mothra/libpanel/textview.c | 134 ++----------------------- sys/src/cmd/mothra/mothra.c | 2 +- sys/src/cmd/mothra/rdhtml.c | 2 +- 6 files changed, 80 insertions(+), 137 deletions(-) diff --git a/sys/src/cmd/mothra/forms.c b/sys/src/cmd/mothra/forms.c index aa5a89056..10aba2256 100644 --- a/sys/src/cmd/mothra/forms.c +++ b/sys/src/cmd/mothra/forms.c @@ -395,7 +395,7 @@ void mkfieldpanel(Rtext *t){ free(t->text); t->text=0; t->p=f->p; - t->hot=1; + t->flags|=PL_HOT; } } void h_checkinput(Panel *p, int, int v){ diff --git a/sys/src/cmd/mothra/libpanel/panel.h b/sys/src/cmd/mothra/libpanel/panel.h index 042863a8b..4d30f9dba 100644 --- a/sys/src/cmd/mothra/libpanel/panel.h +++ b/sys/src/cmd/mothra/libpanel/panel.h @@ -9,7 +9,7 @@ struct Scroll{ Point pos, size; }; struct Rtext{ - int hot; /* responds to hits? */ + int flags; /* responds to hits? text selection? */ void *user; /* user data */ int space; /* how much space before, if no break */ int indent; /* how much space before, after a break */ @@ -96,6 +96,11 @@ struct Panel{ #define PRI_NORMAL 0 /* ordinary panels */ #define PRI_POPUP 1 /* popup menus */ #define PRI_SCROLLBAR 2 /* scroll bars */ + +/* Rtext.flags */ +#define PL_HOT 1 +#define PL_SEL 2 + 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 */ @@ -164,6 +169,9 @@ Rtext *plrtstr(Rtext **, int, int, Font *, char *, int, void *); Rtext *plrtbitmap(Rtext **, int, int, Image *, int, void *); Rtext *plrtpanel(Rtext **, int, int, Panel *, void *); void plrtfree(Rtext *); +void plrtseltext(Rtext *, Rtext *, Rtext *); +char *plrtsnarftext(Rtext *); + int plgetpostextview(Panel *); void plsetpostextview(Panel *, int); char *plsnarftext(Panel *); diff --git a/sys/src/cmd/mothra/libpanel/rtext.c b/sys/src/cmd/mothra/libpanel/rtext.c index 9d18c75d4..1071dae95 100644 --- a/sys/src/cmd/mothra/libpanel/rtext.c +++ b/sys/src/cmd/mothra/libpanel/rtext.c @@ -13,10 +13,10 @@ #define LEAD 4 /* extra space between lines */ #define BORD 2 /* extra border for images */ -Rtext *pl_rtnew(Rtext **t, int space, int indent, Image *b, Panel *p, Font *f, char *s, int hot, void *user){ +Rtext *pl_rtnew(Rtext **t, int space, int indent, Image *b, Panel *p, Font *f, char *s, int flags, void *user){ Rtext *new; new=pl_emalloc(sizeof(Rtext)); - new->hot=hot; + new->flags=flags; new->user=user; new->space=space; new->indent=indent; @@ -37,11 +37,11 @@ Rtext *pl_rtnew(Rtext **t, int space, int indent, Image *b, Panel *p, Font *f, c Rtext *plrtpanel(Rtext **t, int space, int indent, Panel *p, void *user){ return pl_rtnew(t, space, indent, 0, p, 0, 0, 1, user); } -Rtext *plrtstr(Rtext **t, int space, int indent, Font *f, char *s, int hot, void *user){ - return pl_rtnew(t, space, indent, 0, 0, f, s, hot, user); +Rtext *plrtstr(Rtext **t, int space, int indent, Font *f, char *s, int flags, void *user){ + return pl_rtnew(t, space, indent, 0, 0, f, s, flags, user); } -Rtext *plrtbitmap(Rtext **t, int space, int indent, Image *b, int hot, void *user){ - return pl_rtnew(t, space, indent, b, 0, 0, 0, hot, user); +Rtext *plrtbitmap(Rtext **t, int space, int indent, Image *b, int flags, void *user){ + return pl_rtnew(t, space, indent, b, 0, 0, 0, flags, user); } void plrtfree(Rtext *t){ Rtext *next; @@ -171,7 +171,7 @@ void pl_rtdraw(Image *b, Rectangle r, Rtext *t, int yoffs){ && dr.min.yb){ draw(b, insetrect(dr, BORD), t->b, 0, t->b->r.min); - if(t->hot) border(b, dr, 1, display->black, ZP); + if(t->flags&PL_HOT) border(b, dr, 1, display->black, ZP); } else if(t->p){ plmove(t->p, subpt(dr.min, t->p->r.min)); @@ -179,17 +179,20 @@ void pl_rtdraw(Image *b, Rectangle r, Rtext *t, int yoffs){ } else{ string(b, dr.min, display->black, ZP, t->font, t->text); - if(t->hot){ + if(t->flags&PL_HOT){ if(lp.y+1 != dr.max.y) lp = Pt(dr.min.x, dr.max.y-1); line(b, lp, Pt(dr.max.x, dr.max.y-1), Endsquare, Endsquare, 0, display->black, ZP); lp = Pt(dr.max.x, dr.max.y-1); - continue; + goto Cont; } } lp=ZP; + Cont: + if(t->flags&PL_SEL) + pl_highlight(b, dr); } } replclipr(b, b->repl, cr); @@ -240,7 +243,7 @@ Rtext *pl_rthit(Rtext *t, int yoffs, Point p, Point ul){ for(;t!=0;t=t->next){ if(t->topy>p.y) return 0; r = t->r; - if(t->hot && t->b == nil && t->p == nil){ + if((t->flags&PL_HOT) != 0 && t->b == nil && t->p == nil){ if(lp.y == r.max.y && lp.x < r.min.x) r.min.x=lp.x; lp=r.max; @@ -250,3 +253,47 @@ Rtext *pl_rthit(Rtext *t, int yoffs, Point p, Point ul){ } return 0; } + +void plrtseltext(Rtext *t, Rtext *s, Rtext *e){ + while(t){ + t->flags &= ~PL_SEL; + t = t->next; + } + if(s==0 || e==0) + return; + for(t=s; t!=0 && t!=e; t=t->next) + ; + if(t==e){ + for(t=s; t!=e; t=t->next) + t->flags |= PL_SEL; + }else{ + for(t=e; t!=s; t=t->next) + t->flags |= PL_SEL; + } + t->flags |= PL_SEL; +} + +char *plrtsnarftext(Rtext *w){ + char *b, *p, *e; + int n; + + p = e = 0; + for(; w; w = w->next){ + if((w->flags&PL_SEL)==0 || w->b!=0 || w->p!=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; + if(w->space == 0) + e += sprint(e, "%s", w->text); + else if(w->space > 0) + e += sprint(e, " %s", w->text); + else if(PL_OP(w->space) == PL_TAB) + e += sprint(e, "\t%s", w->text); + if(w->nextline == w->next) + e += sprint(e, "\n"); + } + return p; +} diff --git a/sys/src/cmd/mothra/libpanel/textview.c b/sys/src/cmd/mothra/libpanel/textview.c index 27b8bc5ad..69c44568e 100644 --- a/sys/src/cmd/mothra/libpanel/textview.c +++ b/sys/src/cmd/mothra/libpanel/textview.c @@ -10,7 +10,6 @@ #include #include #include "pldefs.h" -#include "rtext.h" typedef struct Textview Textview; struct Textview{ @@ -19,82 +18,12 @@ struct Textview{ int yoffs; /* offset of top of screen */ Rtext *hitword; /* text to hilite */ 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; }; -/* - * 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; - 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(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{ - 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) @@ -116,7 +45,6 @@ void pl_drawnon(Rtext *rp, Image *b){ void pl_fixtextview(Panel *p, Textview *tp, Rectangle r){ Panel *sb; int lo, hi; - pl_hilitewords(p, tp->hitword, tp->hitfirst, 1); lo=tp->yoffs; hi=lo+r.max.y-r.min.y; /* wrong? */ sb=p->yscroller; @@ -130,7 +58,7 @@ void pl_drawtextview(Panel *p){ tp=p->data; b=allocimage(display, p->r, screen->chan, 0, DNofill); if(b==0) b=p->b; - r=pl_outline(b, p->r, p->state); + r=pl_outline(b, p->r, UP); twid=r.max.x-r.min.x; if(twid!=tp->twid){ tp->twid=twid; @@ -169,9 +97,8 @@ int pl_hittextview(Panel *p, Mouse *m){ if(m->buttons&OUT) p->state=UP; else if(m->buttons&7){ - tp->buttons=m->buttons; p->state=DOWN; - + tp->buttons=m->buttons; ul=p->r.min; size=subpt(p->r.max, p->r.min); pl_interior(p->state, &ul, &size); @@ -189,13 +116,14 @@ int pl_hittextview(Panel *p, Mouse *m){ p->state=UP; } if(tp->hitfirst!=oldhitfirst || tp->hitword!=oldhitword){ - pl_hilitewords(p, oldhitword, oldhitfirst, 0); - pl_hilitewords(p, tp->hitword, tp->hitfirst, 1); + plrtseltext(tp->text, tp->hitword, tp->hitfirst); + pl_drawtextview(p); if(tp->hitword==tp->hitfirst) pl_passon(tp->hitword, m); } if(hitme && tp->hit && tp->hitword!=0 && tp->hitword==tp->hitfirst){ - pl_hilitewords(p, tp->hitword, tp->hitfirst, 0); + plrtseltext(tp->text, 0, 0); + pl_drawtextview(p); tp->hit(p, tp->buttons, tp->hitword); tp->hitword=0; tp->hitfirst=0; @@ -230,7 +158,6 @@ void pl_scrolltextview(Panel *p, int dir, int buttons, int num, int den){ break; } if(yoffs!=tp->yoffs){ - 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; @@ -283,7 +210,6 @@ void plinittextview(Panel *v, int flags, Point minsize, Rtext *t, void (*hit)(Pa 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); @@ -302,47 +228,9 @@ 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; +char* plsnarftext(Panel *p){ + static char *b = nil; + free(b); + b = plrtsnarftext(((Textview *)p->data)->text); + return b; } diff --git a/sys/src/cmd/mothra/mothra.c b/sys/src/cmd/mothra/mothra.c index ecd724d31..b64cce64a 100644 --- a/sys/src/cmd/mothra/mothra.c +++ b/sys/src/cmd/mothra/mothra.c @@ -989,7 +989,7 @@ mothon(Www *w, int on) t->next = nil; ap=emalloc(sizeof(Action)); ap->link = strdup(a->link); - plrtstr(&t->next, 0, 0, t->font, strdup("->"), 1, ap); + plrtstr(&t->next, 0, 0, t->font, strdup("->"), PL_HOT, ap); t->next->next = x; } else { t->next = x->next; diff --git a/sys/src/cmd/mothra/rdhtml.c b/sys/src/cmd/mothra/rdhtml.c index a31454e77..8405244a1 100644 --- a/sys/src/cmd/mothra/rdhtml.c +++ b/sys/src/cmd/mothra/rdhtml.c @@ -144,7 +144,7 @@ void pl_htmloutput(Hglob *g, int nsp, char *s, Field *field){ } } plrtstr(&g->dst->text, space, indent, f->font, strdup(s), - g->state->link[0] || g->state->image[0], ap); + (g->state->link[0] || g->state->image[0]) ? PL_HOT : 0, ap); g->para=0; g->linebrk=0; g->dst->changed=1;