xref: /plan9/sys/src/cmd/acme/scrl.c (revision ded93d448500000b5015fa25ce7726536dfedc06)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
59a747e4fSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier #include <keyboard.h>
87dd7cddfSDavid du Colombier #include <frame.h>
97dd7cddfSDavid du Colombier #include <fcall.h>
107dd7cddfSDavid du Colombier #include <plumb.h>
117dd7cddfSDavid du Colombier #include "dat.h"
127dd7cddfSDavid du Colombier #include "fns.h"
137dd7cddfSDavid du Colombier 
147dd7cddfSDavid du Colombier static Image *scrtmp;
157dd7cddfSDavid du Colombier 
167dd7cddfSDavid du Colombier static
177dd7cddfSDavid du Colombier Rectangle
scrpos(Rectangle r,uint p0,uint p1,uint tot)187dd7cddfSDavid du Colombier scrpos(Rectangle r, uint p0, uint p1, uint tot)
197dd7cddfSDavid du Colombier {
207dd7cddfSDavid du Colombier 	Rectangle q;
217dd7cddfSDavid du Colombier 	int h;
227dd7cddfSDavid du Colombier 
237dd7cddfSDavid du Colombier 	q = r;
247dd7cddfSDavid du Colombier 	h = q.max.y-q.min.y;
257dd7cddfSDavid du Colombier 	if(tot == 0)
267dd7cddfSDavid du Colombier 		return q;
277dd7cddfSDavid du Colombier 	if(tot > 1024*1024){
287dd7cddfSDavid du Colombier 		tot>>=10;
297dd7cddfSDavid du Colombier 		p0>>=10;
307dd7cddfSDavid du Colombier 		p1>>=10;
317dd7cddfSDavid du Colombier 	}
327dd7cddfSDavid du Colombier 	if(p0 > 0)
337dd7cddfSDavid du Colombier 		q.min.y += h*p0/tot;
347dd7cddfSDavid du Colombier 	if(p1 < tot)
357dd7cddfSDavid du Colombier 		q.max.y -= h*(tot-p1)/tot;
367dd7cddfSDavid du Colombier 	if(q.max.y < q.min.y+2){
377dd7cddfSDavid du Colombier 		if(q.min.y+2 <= r.max.y)
387dd7cddfSDavid du Colombier 			q.max.y = q.min.y+2;
397dd7cddfSDavid du Colombier 		else
407dd7cddfSDavid du Colombier 			q.min.y = q.max.y-2;
417dd7cddfSDavid du Colombier 	}
427dd7cddfSDavid du Colombier 	return q;
437dd7cddfSDavid du Colombier }
447dd7cddfSDavid du Colombier 
457dd7cddfSDavid du Colombier void
scrlresize(void)467dd7cddfSDavid du Colombier scrlresize(void)
477dd7cddfSDavid du Colombier {
487dd7cddfSDavid du Colombier 	freeimage(scrtmp);
499a747e4fSDavid du Colombier 	scrtmp = allocimage(display, Rect(0, 0, 32, screen->r.max.y), screen->chan, 0, DNofill);
507dd7cddfSDavid du Colombier 	if(scrtmp == nil)
517dd7cddfSDavid du Colombier 		error("scroll alloc");
527dd7cddfSDavid du Colombier }
537dd7cddfSDavid du Colombier 
547dd7cddfSDavid du Colombier void
textscrdraw(Text * t)557dd7cddfSDavid du Colombier textscrdraw(Text *t)
567dd7cddfSDavid du Colombier {
577dd7cddfSDavid du Colombier 	Rectangle r, r1, r2;
587dd7cddfSDavid du Colombier 	Image *b;
597dd7cddfSDavid du Colombier 
607dd7cddfSDavid du Colombier 	if(t->w==nil || t!=&t->w->body)
617dd7cddfSDavid du Colombier 		return;
627dd7cddfSDavid du Colombier 	if(scrtmp == nil)
637dd7cddfSDavid du Colombier 		scrlresize();
647dd7cddfSDavid du Colombier 	r = t->scrollr;
657dd7cddfSDavid du Colombier 	b = scrtmp;
667dd7cddfSDavid du Colombier 	r1 = r;
677dd7cddfSDavid du Colombier 	r1.min.x = 0;
687dd7cddfSDavid du Colombier 	r1.max.x = Dx(r);
697dd7cddfSDavid du Colombier 	r2 = scrpos(r1, t->org, t->org+t->nchars, t->file->nc);
707dd7cddfSDavid du Colombier 	if(!eqrect(r2, t->lastsr)){
717dd7cddfSDavid du Colombier 		t->lastsr = r2;
727dd7cddfSDavid du Colombier 		draw(b, r1, t->cols[BORD], nil, ZP);
737dd7cddfSDavid du Colombier 		draw(b, r2, t->cols[BACK], nil, ZP);
747dd7cddfSDavid du Colombier 		r2.min.x = r2.max.x-1;
757dd7cddfSDavid du Colombier 		draw(b, r2, t->cols[BORD], nil, ZP);
767dd7cddfSDavid du Colombier 		draw(t->b, r, b, nil, Pt(0, r1.min.y));
777dd7cddfSDavid du Colombier /*flushimage(display, 1);/*BUG?*/
787dd7cddfSDavid du Colombier 	}
797dd7cddfSDavid du Colombier }
807dd7cddfSDavid du Colombier 
817dd7cddfSDavid du Colombier void
scrsleep(uint dt)827dd7cddfSDavid du Colombier scrsleep(uint dt)
837dd7cddfSDavid du Colombier {
847dd7cddfSDavid du Colombier 	Timer	*timer;
857dd7cddfSDavid du Colombier 	static Alt alts[3];
867dd7cddfSDavid du Colombier 
877dd7cddfSDavid du Colombier 	timer = timerstart(dt);
887dd7cddfSDavid du Colombier 	alts[0].c = timer->c;
897dd7cddfSDavid du Colombier 	alts[0].v = nil;
907dd7cddfSDavid du Colombier 	alts[0].op = CHANRCV;
917dd7cddfSDavid du Colombier 	alts[1].c = mousectl->c;
927dd7cddfSDavid du Colombier 	alts[1].v = &mousectl->Mouse;
937dd7cddfSDavid du Colombier 	alts[1].op = CHANRCV;
947dd7cddfSDavid du Colombier 	alts[2].op = CHANEND;
957dd7cddfSDavid du Colombier 	for(;;)
967dd7cddfSDavid du Colombier 		switch(alt(alts)){
977dd7cddfSDavid du Colombier 		case 0:
987dd7cddfSDavid du Colombier 			timerstop(timer);
997dd7cddfSDavid du Colombier 			return;
1007dd7cddfSDavid du Colombier 		case 1:
1017dd7cddfSDavid du Colombier 			timercancel(timer);
1027dd7cddfSDavid du Colombier 			return;
1037dd7cddfSDavid du Colombier 		}
1047dd7cddfSDavid du Colombier }
1057dd7cddfSDavid du Colombier 
1067dd7cddfSDavid du Colombier void
textscroll(Text * t,int but)1077dd7cddfSDavid du Colombier textscroll(Text *t, int but)
1087dd7cddfSDavid du Colombier {
1097dd7cddfSDavid du Colombier 	uint p0, oldp0;
1107dd7cddfSDavid du Colombier 	Rectangle s;
1117dd7cddfSDavid du Colombier 	int x, y, my, h, first;
1127dd7cddfSDavid du Colombier 
1137dd7cddfSDavid du Colombier 	s = insetrect(t->scrollr, 1);
1147dd7cddfSDavid du Colombier 	h = s.max.y-s.min.y;
1157dd7cddfSDavid du Colombier 	x = (s.min.x+s.max.x)/2;
1167dd7cddfSDavid du Colombier 	oldp0 = ~0;
1177dd7cddfSDavid du Colombier 	first = TRUE;
1187dd7cddfSDavid du Colombier 	do{
1197dd7cddfSDavid du Colombier 		flushimage(display, 1);
1207dd7cddfSDavid du Colombier 		my = mouse->xy.y;
1217dd7cddfSDavid du Colombier 		if(my < s.min.y)
1227dd7cddfSDavid du Colombier 			my = s.min.y;
1237dd7cddfSDavid du Colombier 		if(my >= s.max.y)
1247dd7cddfSDavid du Colombier 			my = s.max.y;
1257dd7cddfSDavid du Colombier 		if(!eqpt(mouse->xy, Pt(x, my))){
1267dd7cddfSDavid du Colombier 			moveto(mousectl, Pt(x, my));
1277dd7cddfSDavid du Colombier 			readmouse(mousectl);		/* absorb event generated by moveto() */
1287dd7cddfSDavid du Colombier 		}
1297dd7cddfSDavid du Colombier 		if(but == 2){
1307dd7cddfSDavid du Colombier 			y = my;
131*ded93d44SDavid du Colombier 			p0 = (vlong)t->file->nc*(y-s.min.y)/h;
132*ded93d44SDavid du Colombier 			if(p0 >= t->q1)
133*ded93d44SDavid du Colombier 				p0 = textbacknl(t, p0, 2);
1347dd7cddfSDavid du Colombier 			if(oldp0 != p0)
1357dd7cddfSDavid du Colombier 				textsetorigin(t, p0, FALSE);
1367dd7cddfSDavid du Colombier 			oldp0 = p0;
1377dd7cddfSDavid du Colombier 			readmouse(mousectl);
1387dd7cddfSDavid du Colombier 			continue;
1397dd7cddfSDavid du Colombier 		}
1407dd7cddfSDavid du Colombier 		if(but == 1)
1417dd7cddfSDavid du Colombier 			p0 = textbacknl(t, t->org, (my-s.min.y)/t->font->height);
1427dd7cddfSDavid du Colombier 		else
1437dd7cddfSDavid du Colombier 			p0 = t->org+frcharofpt(t, Pt(s.max.x, my));
1447dd7cddfSDavid du Colombier 		if(oldp0 != p0)
1457dd7cddfSDavid du Colombier 			textsetorigin(t, p0, TRUE);
1467dd7cddfSDavid du Colombier 		oldp0 = p0;
1477dd7cddfSDavid du Colombier 		/* debounce */
1487dd7cddfSDavid du Colombier 		if(first){
1497dd7cddfSDavid du Colombier 			flushimage(display, 1);
1507dd7cddfSDavid du Colombier 			sleep(200);
1517dd7cddfSDavid du Colombier 			nbrecv(mousectl->c, &mousectl->Mouse);
1527dd7cddfSDavid du Colombier 			first = FALSE;
1537dd7cddfSDavid du Colombier 		}
1547dd7cddfSDavid du Colombier 		scrsleep(80);
1557dd7cddfSDavid du Colombier 	}while(mouse->buttons & (1<<(but-1)));
1567dd7cddfSDavid du Colombier 	while(mouse->buttons)
1577dd7cddfSDavid du Colombier 		readmouse(mousectl);
1587dd7cddfSDavid du Colombier }
159