telephil9initial importc9c50ad6 years agoHistory
250 lines · 6.0 KB · C
RawDownload
/* * Fonted text viewer, calls out to code in rtext.c * * Should redo this to copy the already-visible parts on scrolling & only * update the newly appearing stuff -- then the offscreen assembly bitmap can go away. */#include <u.h>#include <libc.h>#include <draw.h>#include <event.h>#include <panel.h>#include "pldefs.h" typedef struct Textview Textview;struct Textview{	void (*hit)(Panel *, int, Rtext *); /* call back to user on hit */	Rtext *text;			/* text */	Point offs;			/* offset of left/top of screen */	Rtext *hitword;			/* text to hilite */	Rtext *hitfirst;		/* first word in range select */	int twid;			/* text width (visible) */	int thgt;			/* text height (total) */	int maxwid;			/* width of longest line */	Point minsize;			/* smallest acceptible window size */	int buttons;}; void pl_setscrpos(Panel *p, Textview *tp, Rectangle r){	Panel *sb;	int lo, hi; 	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);	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;		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 = tp->offs;	pl_rtdraw(p->b, r, tp->text, tp->offs);	pl_setscrpos(p, tp, r);}/* * 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);}int pl_hittextview(Panel *p, Mouse *m){	Rtext *oldhitword, *oldhitfirst;	int hitme, oldstate;	Point ul, size;	Textview *tp; 	tp=p->data;	hitme=0;	oldstate=p->state;	oldhitword=tp->hitword;	oldhitfirst=tp->hitfirst;	if(oldhitword==oldhitfirst)		pl_passon(oldhitword, m);	if(m->buttons&OUT)		p->state=UP;	else if(m->buttons&7){		p->state=DOWN;		tp->buttons=m->buttons;		if(oldhitword==0 || oldhitword->p==0 || (oldhitword->p->flags&REMOUSE)==0){			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->offs, m->xy, ul);			if(tp->hitword==0)				if(oldhitword!=0 && oldstate==DOWN)					tp->hitword=oldhitword;				else					tp->hitfirst=0;			if(tp->hitword!=0 && oldstate!=DOWN)				tp->hitfirst=tp->hitword;		}	}	else{		if(p->state==DOWN) hitme=1;		p->state=UP;	}	if(tp->hitfirst!=oldhitfirst || tp->hitword!=oldhitword){		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){		plrtseltext(tp->text, 0, 0);		pl_drawtextview(p);		tp->hit(p, tp->buttons, tp->hitword);		tp->hitword=0;		tp->hitfirst=0;	}	return 0;}void pl_scrolltextview(Panel *p, int dir, int buttons, int num, int den){	int xoffs, yoffs;	Point ul, size;	Textview *tp;	Rectangle r; 	tp=p->data;	ul=p->r.min;	size=subpt(p->r.max, p->r.min);	pl_interior(p->state, &ul, &size);	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){	USED(g, c);}Point pl_getsizetextview(Panel *p, Point children){	USED(children);	return pl_boxsize(((Textview *)p->data)->minsize, p->state);}void pl_childspacetextview(Panel *g, Point *ul, Point *size){	USED(g, ul, size);}/* * Priority depends on what thing inside the panel we're pointing at. */int pl_pritextview(Panel *p, Point xy){	Point ul, size;	Textview *tp;	Rtext *h;	tp=p->data;	ul=p->r.min;	size=subpt(p->r.max, p->r.min);	pl_interior(p->state, &ul, &size);	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);	}	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;	v->flags=flags|LEAF;	v->state=UP;	v->draw=pl_drawtextview;	v->hit=pl_hittextview;	v->type=pl_typetextview;	v->getsize=pl_getsizetextview;	v->childspace=pl_childspacetextview;	v->kind="textview";	v->pri=pl_pritextview;	tp->hit=hit;	tp->minsize=minsize;	tp->text=t;	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);}Panel *pltextview(Panel *parent, int flags, Point minsize, Rtext *t, void (*hit)(Panel *, int, Rtext *)){	Panel *v;	v=pl_newpanel(parent, sizeof(Textview));	plinittextview(v, flags, minsize, t, hit);	return v;}int plgetpostextview(Panel *p){	return ((Textview *)p->data)->offs.y;}void plsetpostextview(Panel *p, int yoffs){	((Textview *)p->data)->offs.y=yoffs;	pldraw(p, p->b);}