shithub: riscv

Download patch

ref: 20f2add592f8463ef6820afd07a342acb26da304
parent: b2c2d1ed2a0ce84f3ebe34065d35cec0789653cb
author: stanley lieber <stanley.lieber@gmail.com>
date: Sun Feb 8 08:19:47 EST 2015

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_)

--- a/sys/src/cmd/mothra/libpanel/draw.c
+++ b/sys/src/cmd/mothra/libpanel/draw.c
@@ -243,7 +243,7 @@
 }
 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);
--- a/sys/src/cmd/mothra/libpanel/pack.c
+++ b/sys/src/cmd/mothra/libpanel/pack.c
@@ -97,6 +97,7 @@
 	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:
--- a/sys/src/cmd/mothra/libpanel/panel.h
+++ b/sys/src/cmd/mothra/libpanel/panel.h
@@ -86,6 +86,8 @@
 #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 */
 
 /*
--- a/sys/src/cmd/mothra/libpanel/pldefs.h
+++ b/sys/src/cmd/mothra/libpanel/pldefs.h
@@ -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 */
--- a/sys/src/cmd/mothra/libpanel/rtext.c
+++ b/sys/src/cmd/mothra/libpanel/rtext.c
@@ -67,14 +67,16 @@
 }
 /*
  * 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 @@
 			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 @@
 		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 @@
 		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 @@
  * 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);
+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);
+		}		
 	}
-	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);
-	}
 }
-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){
--- a/sys/src/cmd/mothra/libpanel/textview.c
+++ b/sys/src/cmd/mothra/libpanel/textview.c
@@ -15,11 +15,12 @@
 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 @@
 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 @@
 	Textview *tp;
 
 	tp=p->data;
-
 	hitme=0;
 	oldstate=p->state;
 	oldhitword=tp->hitword;
@@ -78,7 +88,7 @@
 			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,38 +118,64 @@
 	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(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);
+		}
 	}
-	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);
-	}
 }
 void pl_typetextview(Panel *g, Rune c){
 	USED(g, c);
@@ -162,7 +198,7 @@
 	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 @@
 	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 @@
 	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);
 }
--- a/sys/src/cmd/mothra/mothra.c
+++ b/sys/src/cmd/mothra/mothra.c
@@ -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 @@
 		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 @@
 			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 @@
 	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);
@@ -389,6 +422,12 @@
 				break;
 			case Kack:
 				search();
+				break;
+			case Kright:
+				sidescroll(text->size.x/4, 1);
+				break;
+			case Kleft:
+				sidescroll(-text->size.x/4, 1);
 				break;
 			}
 			break;
--