shithub: riscv

ref: 65ab0d034b729354c1f13712284b555be5504a0b
dir: /sys/src/libframe/frselect.c/

View raw version
#include <u.h>
#include <libc.h>
#include <draw.h>
#include <thread.h>
#include <mouse.h>
#include <frame.h>

static
int
region(int a, int b)
{
	if(a < b)
		return -1;
	if(a == b)
		return 0;
	return 1;
}

void
frselect(Frame *f, Mousectl *mc)	/* when called, button 1 is down */
{
	ulong p0, p1, q;
	Point mp, pt0, pt1, qt;
	int reg, b, scrled;

	mp = mc->xy;
	b = mc->buttons;

	f->modified = 0;
	frdrawsel(f, frptofchar(f, f->p0), f->p0, f->p1, 0);
	p0 = p1 = frcharofpt(f, mp);
	f->p0 = p0;
	f->p1 = p1;
	pt0 = frptofchar(f, p0);
	pt1 = frptofchar(f, p1);
	frdrawsel(f, pt0, p0, p1, 1);
	reg = 0;
	do{
		scrled = 0;
		if(f->scroll){
			if(mp.y < f->r.min.y){
				(*f->scroll)(f, -(f->r.min.y-mp.y)/(int)f->font->height-1);
				p0 = f->p1;
				p1 = f->p0;
				scrled = 1;
			}else if(mp.y > f->r.max.y){
				(*f->scroll)(f, (mp.y-f->r.max.y)/(int)f->font->height+1);
				p0 = f->p0;
				p1 = f->p1;
				scrled = 1;
			}
			if(scrled){
				if(reg != region(p1, p0))
					q = p0, p0 = p1, p1 = q;	/* undo the swap that will happen below */
				pt0 = frptofchar(f, p0);
				pt1 = frptofchar(f, p1);
				reg = region(p1, p0);
			}
		}
		q = frcharofpt(f, mp);
		if(p1 != q){
			if(reg != region(q, p0)){	/* crossed starting point; reset */
				if(reg > 0)
					frdrawsel(f, pt0, p0, p1, 0);
				else if(reg < 0)
					frdrawsel(f, pt1, p1, p0, 0);
				p1 = p0;
				pt1 = pt0;
				reg = region(q, p0);
				if(reg == 0)
					frdrawsel(f, pt0, p0, p1, 1);
			}
			qt = frptofchar(f, q);
			if(reg > 0){
				if(q > p1)
					frdrawsel(f, pt1, p1, q, 1);
				else if(q < p1)
					frdrawsel(f, qt, q, p1, 0);
			}else if(reg < 0){
				if(q > p1)
					frdrawsel(f, pt1, p1, q, 0);
				else
					frdrawsel(f, qt, q, p1, 1);
			}
			p1 = q;
			pt1 = qt;
		}
		f->modified = 0;
		if(p0 < p1) {
			f->p0 = p0;
			f->p1 = p1;
		}
		else {
			f->p0 = p1;
			f->p1 = p0;
		}
		if(scrled)
			(*f->scroll)(f, 0);
		if(!scrled)
			readmouse(mc);
		mp = mc->xy;
	}while(mc->buttons == b);
}

void
frselectpaint(Frame *f, Point p0, Point p1, Image *col)
{
	int n;
	Point q0, q1;

	q0 = p0;
	q1 = p1;
	q0.y += f->font->height;
	q1.y += f->font->height;
	n = (p1.y-p0.y)/f->font->height;
	if(f->b == nil)
		drawerror(f->display, "frselectpaint b==0");
	if(p0.y == f->r.max.y)
		return;
	if(n == 0)
		draw(f->b, Rpt(p0, q1), col, nil, ZP);
	else{
		if(p0.x >= f->r.max.x)
			p0.x = f->r.max.x-1;
		draw(f->b, Rect(p0.x, p0.y, f->r.max.x, q0.y), col, nil, ZP);
		if(n > 1)
			draw(f->b, Rect(f->r.min.x, q0.y, f->r.max.x, p1.y),
				col, nil, ZP);
		draw(f->b, Rect(f->r.min.x, p1.y, q1.x, q1.y),
			col, nil, ZP);
	}
}