mothra: add side scrolling, controlled by left and right buttons on the keyboard. if desired, x-scrollbar can be set visible via the visxbar variable in mothra.c. (thanks, jpm_)

This commit is contained in:
stanley lieber 2015-02-08 13:19:47 -05:00
parent b2c2d1ed2a
commit 20f2add592
7 changed files with 189 additions and 84 deletions

View file

@ -243,7 +243,7 @@ void pl_sliderupd(Image *b, Rectangle r1, int dir, int lo, int hi){
}
void pl_draw1(Panel *p, Image *b);
void pl_drawall(Panel *p, Image *b){
if(p->flags&INVIS) return;
if(p->flags&INVIS || p->flags&IGNORE) return;
p->b=b;
p->draw(p);
for(p=p->child;p;p=p->next) pl_draw1(p, b);

View file

@ -97,6 +97,7 @@ void pl_setrect(Panel *p, Point ul, Point avail){
slack=subpt(space, p->childreq);
share=pl_getshare(p->child);
for(c=p->child;c;c=c->next){
if(c->flags&IGNORE) continue;
if(c->flags&EXPAND){
switch(c->flags&PACK){
case PACKN:

View file

@ -86,6 +86,8 @@ struct Panel{
#define MAXX 0x1000 /* make x size as big as biggest sibling's */
#define MAXY 0x2000 /* make y size as big as biggest sibling's */
#define BITMAP 0x4000 /* text argument is a bitmap, not a string */
/* pldefs.h flags 0x08000-0x40000 */
#define IGNORE 0x080000 /* ignore this panel totally */
#define USERFL 0x100000 /* start of user flag */
/*

View file

@ -5,10 +5,10 @@
* Variable-font text routines
* These could make a separate library.
*/
int pl_rtfmt(Rtext *, int);
void pl_rtdraw(Image *, Rectangle, Rtext *, int);
void pl_rtredraw(Image *, Rectangle, Rtext *, int, int);
Rtext *pl_rthit(Rtext *, int, Point, Point);
Point pl_rtfmt(Rtext *, int);
void pl_rtdraw(Image *, Rectangle, Rtext *, Point);
void pl_rtredraw(Image *, Rectangle, Rtext *, Point, Point, int);
Rtext *pl_rthit(Rtext *, Point, Point, Point);
#define HITME 0x08000 /* tells ptinpanel not to look at children */
#define LEAF 0x10000 /* newpanel will refuse to attach children */
#define INVIS 0x20000 /* don't draw this */

View file

@ -67,14 +67,16 @@ int pl_space(int space, int pos, int indent){
}
/*
* initialize rectangles & nextlines of text starting at t,
* galley width is wid. Returns the total length of the text
* galley width is wid. Returns the total width/height of the text
*/
int pl_rtfmt(Rtext *t, int wid){
Point pl_rtfmt(Rtext *t, int wid){
Rtext *tp, *eline;
int ascent, descent, x, space, a, d, w, topy, indent;
int ascent, descent, x, space, a, d, w, topy, indent, maxwid;
Point p;
p=Pt(0,0);
eline=t;
maxwid=0;
while(t){
ascent=0;
descent=0;
@ -147,9 +149,10 @@ int pl_rtfmt(Rtext *t, int wid){
if(t==eline) break;
p.x+=pl_space(t->space, p.x, indent);
}
if(p.x>maxwid) maxwid=p.x;
p.y+=descent+LEAD;
}
return p.y;
return Pt(maxwid, p.y);
}
/*
@ -163,9 +166,9 @@ void pl_stuffbitmap(Panel *p, Image *b){
pl_stuffbitmap(p, b);
}
void pl_rtdraw(Image *b, Rectangle r, Rtext *t, int yoffs){
void pl_rtdraw(Image *b, Rectangle r, Rtext *t, Point offs){
static Image *backup;
Point offs, lp;
Point lp;
Rectangle dr;
Image *bb;
@ -178,11 +181,13 @@ void pl_rtdraw(Image *b, Rectangle r, Rtext *t, int yoffs){
b=backup;
pl_clr(b, r);
lp=ZP;
offs=subpt(r.min, Pt(0, yoffs));
offs=subpt(r.min, offs);
for(;t;t=t->next) if(!eqrect(t->r, Rect(0,0,0,0))){
dr=rectaddpt(t->r, offs);
if(dr.max.y>r.min.y
&& dr.min.y<r.max.y){
&& dr.min.y<r.max.y
&& dr.max.x>r.min.x
&& dr.min.x<r.max.x){
if(t->b){
draw(b, insetrect(dr, BORD), t->b, 0, t->b->r.min);
if(t->flags&PL_HOT) border(b, dr, 1, display->black, ZP);
@ -232,30 +237,51 @@ void pl_reposition(Rtext *t, Image *b, Point p, Rectangle r){
* Rectangle r of Image b contains an image of Rtext t, offset by oldoffs.
* Redraw the text to have offset yoffs.
*/
void pl_rtredraw(Image *b, Rectangle r, Rtext *t, int yoffs, int oldoffs){
int dy, size;
dy=oldoffs-yoffs;
size=r.max.y-r.min.y;
if(dy>=size || -dy>=size)
pl_rtdraw(b, r, t, yoffs);
else if(dy<0){
pl_reposition(t, b, r.min,
Rect(r.min.x, r.min.y-dy, r.max.x, r.max.y));
pl_rtdraw(b, Rect(r.min.x, r.max.y+dy, r.max.x, r.max.y),
t, yoffs+size+dy);
}
else if(dy>0){
pl_reposition(t, b, Pt(r.min.x, r.min.y+dy),
Rect(r.min.x, r.min.y, r.max.x, r.max.y-dy));
pl_rtdraw(b, Rect(r.min.x, r.min.y, r.max.x, r.min.y+dy), t, yoffs);
void pl_rtredraw(Image *b, Rectangle r, Rtext *t, Point offs, Point oldoffs, int dir){
int d, size;
if(dir==VERT){
d=oldoffs.y-offs.y;
size=r.max.y-r.min.y;
if(d>=size || -d>=size) /* move more than screenful */
pl_rtdraw(b, r, t, offs);
else if(d<0){ /* down */
pl_reposition(t, b, r.min,
Rect(r.min.x, r.min.y-d, r.max.x, r.max.y));
pl_rtdraw(b, Rect(r.min.x, r.max.y+d, r.max.x, r.max.y),
t, Pt(offs.x, offs.y+size+d));
}
else if(d>0){ /* up */
pl_reposition(t, b, Pt(r.min.x, r.min.y+d),
Rect(r.min.x, r.min.y, r.max.x, r.max.y-d));
pl_rtdraw(b, Rect(r.min.x, r.min.y, r.max.x, r.min.y+d),
t, offs);
}
}else{ /* dir==HORIZ */
d=oldoffs.x-offs.x;
size=r.max.x-r.min.x;
if(d>=size || -d>=size) /* move more than screenful */
pl_rtdraw(b, r, t, offs);
else if(d<0){ /* right */
pl_reposition(t, b, r.min,
Rect(r.min.x-d, r.min.y, r.max.x, r.max.y));
pl_rtdraw(b, Rect(r.max.x+d, r.min.y, r.max.x, r.max.y),
t, Pt(offs.x+size+d, offs.y));
}
else if(d>0){ /* left */
pl_reposition(t, b, Pt(r.min.x+d, r.min.y),
Rect(r.min.x, r.min.y, r.max.x-d, r.max.y));
pl_rtdraw(b, Rect(r.min.x, r.min.y, r.min.x+d, r.max.y),
t, offs);
}
}
}
Rtext *pl_rthit(Rtext *t, int yoffs, Point p, Point ul){
Rtext *pl_rthit(Rtext *t, Point offs, Point p, Point ul){
Rectangle r;
Point lp;
if(t==0) return 0;
p.x-=ul.x;
p.y+=yoffs-ul.y;
p.x+=offs.x-ul.x;
p.y+=offs.y-ul.y;
while(t->nextline && t->nextline->topy<=p.y) t=t->nextline;
lp=ZP;
for(;t!=0;t=t->next){

View file

@ -15,11 +15,12 @@ typedef struct Textview Textview;
struct Textview{
void (*hit)(Panel *, int, Rtext *); /* call back to user on hit */
Rtext *text; /* text */
int yoffs; /* offset of top of screen */
Point offs; /* offset of left/top of screen */
Rtext *hitword; /* text to hilite */
Rtext *hitfirst; /* first word in range select */
int twid; /* text width */
int thgt; /* text height */
int twid; /* text width (visible) */
int thgt; /* text height (total) */
int maxwid; /* width of longest line */
Point minsize; /* smallest acceptible window size */
int buttons;
};
@ -27,25 +28,35 @@ struct Textview{
void pl_setscrpos(Panel *p, Textview *tp, Rectangle r){
Panel *sb;
int lo, hi;
lo=tp->yoffs;
lo=tp->offs.y;
hi=lo+r.max.y-r.min.y; /* wrong? */
sb=p->yscroller;
if(sb && sb->setscrollbar) sb->setscrollbar(sb, lo, hi, tp->thgt);
sb=p->yscroller;
if(sb && sb->setscrollbar)
sb->setscrollbar(sb, lo, hi, tp->thgt);
lo=tp->offs.x;
hi=lo+r.max.x-r.min.x;
sb=p->xscroller;
if(sb && sb->setscrollbar)
sb->setscrollbar(sb, lo, hi, tp->maxwid);
}
void pl_drawtextview(Panel *p){
int twid;
Rectangle r;
Textview *tp;
Point size;
tp=p->data;
r=pl_outline(p->b, p->r, UP);
twid=r.max.x-r.min.x;
if(twid!=tp->twid){
tp->twid=twid;
tp->thgt=pl_rtfmt(tp->text, tp->twid);
p->scr.size.y=tp->thgt;
size=pl_rtfmt(tp->text, tp->twid);
p->scr.size.x=tp->maxwid=size.x;
p->scr.size.y=tp->thgt=size.y;
}
p->scr.pos.y=tp->yoffs;
pl_rtdraw(p->b, r, tp->text, tp->yoffs);
p->scr.pos = tp->offs;
pl_rtdraw(p->b, r, tp->text, tp->offs);
pl_setscrpos(p, tp, r);
}
/*
@ -62,7 +73,6 @@ int pl_hittextview(Panel *p, Mouse *m){
Textview *tp;
tp=p->data;
hitme=0;
oldstate=p->state;
oldhitword=tp->hitword;
@ -78,7 +88,7 @@ int pl_hittextview(Panel *p, Mouse *m){
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);
tp->hitword=pl_rthit(tp->text, tp->offs, m->xy, ul);
if(tp->hitword==0)
if(oldhitword!=0 && oldstate==DOWN)
tp->hitword=oldhitword;
@ -108,37 +118,63 @@ int pl_hittextview(Panel *p, Mouse *m){
return 0;
}
void pl_scrolltextview(Panel *p, int dir, int buttons, int num, int den){
int yoffs;
int xoffs, yoffs;
Point ul, size;
Textview *tp;
Rectangle r;
if(dir!=VERT) return;
tp=p->data;
ul=p->r.min;
size=subpt(p->r.max, p->r.min);
pl_interior(p->state, &ul, &size);
switch(buttons){
default:
SET(yoffs);
break;
case 1: /* left -- top moves to pointer */
yoffs=(vlong)tp->yoffs-num*size.y/den;
if(yoffs<0) yoffs=0;
break;
case 2: /* middle -- absolute index of file */
yoffs=(vlong)tp->thgt*num/den;
break;
case 4: /* right -- line pointed at moves to top */
yoffs=tp->yoffs+(vlong)num*size.y/den;
if(yoffs>tp->thgt) yoffs=tp->thgt;
break;
}
if(yoffs!=tp->yoffs){
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;
pl_setscrpos(p, tp, r);
if(dir==VERT){
switch(buttons){
default:
SET(yoffs);
break;
case 1: /* left -- top moves to pointer */
yoffs=(vlong)tp->offs.y-num*size.y/den;
if(yoffs<0) yoffs=0;
break;
case 2: /* middle -- absolute index of file */
yoffs=(vlong)tp->thgt*num/den;
break;
case 4: /* right -- line pointed at moves to top */
yoffs=tp->offs.y+(vlong)num*size.y/den;
if(yoffs>tp->thgt) yoffs=tp->thgt;
break;
}
if(yoffs!=tp->offs.y){
r=pl_outline(p->b, p->r, p->state);
pl_rtredraw(p->b, r, tp->text,
Pt(tp->offs.x, yoffs), tp->offs, dir);
p->scr.pos.y=tp->offs.y=yoffs;
pl_setscrpos(p, tp, r);
}
}else{ /* dir==HORIZ */
switch(buttons){
default:
SET(xoffs);
break;
case 1: /* left */
xoffs=(vlong)tp->offs.x-num*size.x/den;
if(xoffs<0) xoffs=0;
break;
case 2: /* middle */
xoffs=(vlong)tp->maxwid*num/den;
break;
case 4: /* right */
xoffs=tp->offs.x+(vlong)num*size.x/den;
if(xoffs>tp->maxwid) xoffs=tp->maxwid;
break;
}
if(xoffs!=tp->offs.x){
r=pl_outline(p->b, p->r, p->state);
pl_rtredraw(p->b, r, tp->text,
Pt(xoffs, tp->offs.y), tp->offs, dir);
p->scr.pos.x=tp->offs.x=xoffs;
pl_setscrpos(p, tp, r);
}
}
}
void pl_typetextview(Panel *g, Rune c){
@ -162,7 +198,7 @@ int pl_pritextview(Panel *p, Point xy){
ul=p->r.min;
size=subpt(p->r.max, p->r.min);
pl_interior(p->state, &ul, &size);
h=pl_rthit(tp->text, tp->yoffs, xy, ul);
h=pl_rthit(tp->text, tp->offs, xy, ul);
if(h && h->b==0 && h->p!=0){
p=pl_ptinpanel(xy, h->p);
if(p) return p->pri(p, xy);
@ -189,12 +225,13 @@ void plinittextview(Panel *v, int flags, Point minsize, Rtext *t, void (*hit)(Pa
tp->hit=hit;
tp->minsize=minsize;
tp->text=t;
tp->yoffs=0;
tp->offs=ZP;
tp->hitfirst=0;
tp->hitword=0;
v->scroll=pl_scrolltextview;
v->snarf=pl_snarftextview;
tp->twid=-1;
tp->maxwid=0;
v->scr.pos=Pt(0,0);
v->scr.size=Pt(0,1);
}
@ -205,9 +242,9 @@ Panel *pltextview(Panel *parent, int flags, Point minsize, Rtext *t, void (*hit)
return v;
}
int plgetpostextview(Panel *p){
return ((Textview *)p->data)->yoffs;
return ((Textview *)p->data)->offs.y;
}
void plsetpostextview(Panel *p, int yoffs){
((Textview *)p->data)->yoffs=yoffs;
((Textview *)p->data)->offs.y=yoffs;
pldraw(p, p->b);
}

View file

@ -15,6 +15,8 @@
int debug=0;
int verbose=0; /* -v flag causes html errors to be written to file-descriptor 2 */
int defdisplay=1; /* is the default (initial) display visible? */
int visxbar=0; /* horizontal scrollbar visible? */
int topxbar=0; /* horizontal scrollbar at top? */
Panel *root; /* the whole display */
Panel *alt; /* the alternate display */
Panel *alttext; /* the alternate text window */
@ -152,16 +154,46 @@ void scrolltext(int dy, int whence)
s.pos.y = s.size.y+dy;
break;
}
if(s.pos.y < 0)
s.pos.y = 0;
if(s.pos.y > s.size.y)
s.pos.y = s.size.y;
if(s.pos.y < 0)
s.pos.y = 0;
plsetscroll(text, s);
}
void sidescroll(int dx, int whence)
{
Scroll s;
s = plgetscroll(text);
switch(whence){
case 0:
s.pos.x = dx;
break;
case 1:
s.pos.x += dx;
break;
case 2:
s.pos.x = s.size.x+dx;
break;
}
if(s.pos.x > s.size.x - text->size.x + 5)
s.pos.x = s.size.x - text->size.x + 5;
if(s.pos.x < 0)
s.pos.x = 0;
plsetscroll(text, s);
}
void mkpanels(void){
Panel *p, *bar, *swap;
Panel *p, *xbar, *ybar, *swap;
int xflags;
if(topxbar)
xflags=PACKN|USERFL;
else
xflags=PACKS|USERFL;
if(!visxbar)
xflags|=IGNORE;
menu3=plmenu(0, 0, buttons, PACKN|FILLX, hit3);
root=plpopup(root, EXPAND, 0, 0, menu3);
p=plgroup(root, PACKN|FILLX);
@ -170,23 +202,24 @@ void mkpanels(void){
pllabel(p, PACKW, "Go:");
cmd=plentry(p, PACKN|FILLX, 0, "", docmd);
p=plgroup(root, PACKN|FILLX);
bar=plscrollbar(p, PACKW);
ybar=plscrollbar(p, PACKW);
list=pllist(p, PACKN|FILLX, genwww, 8, doprev);
plscroll(list, 0, bar);
plscroll(list, 0, ybar);
p=plgroup(root, PACKN|FILLX);
pllabel(p, PACKW, "Url:");
cururl=pllabel(p, PACKE|EXPAND, "---");
plplacelabel(cururl, PLACEW);
p=plgroup(root, PACKN|EXPAND);
bar=plscrollbar(p, PACKW|USERFL);
ybar=plscrollbar(p, PACKW|USERFL);
xbar=plscrollbar(p, xflags);
text=pltextview(p, PACKE|EXPAND, Pt(0, 0), 0, dolink);
plscroll(text, 0, bar);
plscroll(text, xbar, ybar);
plgrabkb(cmd);
alt=plpopup(0, PACKE|EXPAND, 0, 0, menu3);
bar=plscrollbar(alt, PACKW|USERFL);
ybar=plscrollbar(alt, PACKW|USERFL);
xbar=plscrollbar(alt, xflags);
alttext=pltextview(alt, PACKE|EXPAND, Pt(0, 0), 0, dolink);
plscroll(alttext, 0, bar);
plscroll(alttext, xbar, ybar);
if(!defdisplay){
swap=root;
root=alt;
@ -318,11 +351,11 @@ void main(int argc, char *argv[]){
plinit(screen->depth);
if(debug) notify(dienow);
getfonts();
hrule=allocimage(display, Rect(0, 0, 2048, 5), screen->chan, 0, DWhite);
hrule=allocimage(display, Rect(0, 0, 1, 5), screen->chan, 1, DWhite);
if(hrule==0)
sysfatal("can't allocimage!");
draw(hrule, Rect(0,1,1280,3), display->black, 0, ZP);
linespace=allocimage(display, Rect(0, 0, 2048, 5), screen->chan, 0, DWhite);
draw(hrule, Rect(0,1,1,3), display->black, 0, ZP);
linespace=allocimage(display, Rect(0, 0, 1, 5), screen->chan, 1, DWhite);
if(linespace==0)
sysfatal("can't allocimage!");
bullet=allocimage(display, Rect(0,0,25, 8), screen->chan, 0, DWhite);
@ -390,6 +423,12 @@ void main(int argc, char *argv[]){
case Kack:
search();
break;
case Kright:
sidescroll(text->size.x/4, 1);
break;
case Kleft:
sidescroll(-text->size.x/4, 1);
break;
}
break;
case Emouse: