xref: /plan9-contrib/sys/src/libdraw/getrect.c (revision 9a747e4fd48b9f4522c70c07e8f882a15030f964)
17dd7cddfSDavid du Colombier #include <u.h>
27dd7cddfSDavid du Colombier #include <libc.h>
37dd7cddfSDavid du Colombier #include <draw.h>
47dd7cddfSDavid du Colombier #include <thread.h>
57dd7cddfSDavid du Colombier #include <cursor.h>
67dd7cddfSDavid du Colombier #include <mouse.h>
77dd7cddfSDavid du Colombier 
87dd7cddfSDavid du Colombier #define	W	Borderwidth
97dd7cddfSDavid du Colombier 
107dd7cddfSDavid du Colombier static Image *tmp[4];
117dd7cddfSDavid du Colombier static Image *red;
127dd7cddfSDavid du Colombier 
137dd7cddfSDavid du Colombier static Cursor sweep={
147dd7cddfSDavid du Colombier 	{-7, -7},
157dd7cddfSDavid du Colombier 	{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07,
167dd7cddfSDavid du Colombier 	 0xE0, 0x07, 0xE0, 0x07, 0xE3, 0xF7, 0xE3, 0xF7,
177dd7cddfSDavid du Colombier 	 0xE3, 0xE7, 0xE3, 0xF7, 0xE3, 0xFF, 0xE3, 0x7F,
187dd7cddfSDavid du Colombier 	 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,},
197dd7cddfSDavid du Colombier 	{0x00, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x40, 0x02,
207dd7cddfSDavid du Colombier 	 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x41, 0xE2,
217dd7cddfSDavid du Colombier 	 0x41, 0xC2, 0x41, 0xE2, 0x41, 0x72, 0x40, 0x38,
227dd7cddfSDavid du Colombier 	 0x40, 0x1C, 0x40, 0x0E, 0x7F, 0xE6, 0x00, 0x00,}
237dd7cddfSDavid du Colombier };
247dd7cddfSDavid du Colombier 
257dd7cddfSDavid du Colombier static
267dd7cddfSDavid du Colombier void
brects(Rectangle r,Rectangle rp[4])277dd7cddfSDavid du Colombier brects(Rectangle r, Rectangle rp[4])
287dd7cddfSDavid du Colombier {
297dd7cddfSDavid du Colombier 	if(Dx(r) < 2*W)
307dd7cddfSDavid du Colombier 		r.max.x = r.min.x+2*W;
317dd7cddfSDavid du Colombier 	if(Dy(r) < 2*W)
327dd7cddfSDavid du Colombier 		r.max.y = r.min.y+2*W;
337dd7cddfSDavid du Colombier 	rp[0] = Rect(r.min.x, r.min.y, r.max.x, r.min.y+W);
347dd7cddfSDavid du Colombier 	rp[1] = Rect(r.min.x, r.max.y-W, r.max.x, r.max.y);
357dd7cddfSDavid du Colombier 	rp[2] = Rect(r.min.x, r.min.y+W, r.min.x+W, r.max.y-W);
367dd7cddfSDavid du Colombier 	rp[3] = Rect(r.max.x-W, r.min.y+W, r.max.x, r.max.y-W);
377dd7cddfSDavid du Colombier }
387dd7cddfSDavid du Colombier 
397dd7cddfSDavid du Colombier Rectangle
getrect(int but,Mousectl * mc)407dd7cddfSDavid du Colombier getrect(int but, Mousectl *mc)
417dd7cddfSDavid du Colombier {
427dd7cddfSDavid du Colombier 	Rectangle r, rc;
437dd7cddfSDavid du Colombier 
447dd7cddfSDavid du Colombier 	but = 1<<(but-1);
457dd7cddfSDavid du Colombier 	setcursor(mc, &sweep);
467dd7cddfSDavid du Colombier 	while(mc->buttons)
477dd7cddfSDavid du Colombier 		readmouse(mc);
487dd7cddfSDavid du Colombier 	while(!(mc->buttons & but)){
497dd7cddfSDavid du Colombier 		readmouse(mc);
507dd7cddfSDavid du Colombier 		if(mc->buttons & (7^but))
517dd7cddfSDavid du Colombier 			goto Return;
527dd7cddfSDavid du Colombier 	}
537dd7cddfSDavid du Colombier 	r.min = mc->xy;
547dd7cddfSDavid du Colombier 	r.max = mc->xy;
557dd7cddfSDavid du Colombier 	do{
567dd7cddfSDavid du Colombier 		rc = canonrect(r);
577dd7cddfSDavid du Colombier 		drawgetrect(rc, 1);
587dd7cddfSDavid du Colombier 		readmouse(mc);
597dd7cddfSDavid du Colombier 		drawgetrect(rc, 0);
607dd7cddfSDavid du Colombier 		r.max = mc->xy;
617dd7cddfSDavid du Colombier 	}while(mc->buttons == but);
627dd7cddfSDavid du Colombier 
637dd7cddfSDavid du Colombier     Return:
647dd7cddfSDavid du Colombier 	setcursor(mc, nil);
657dd7cddfSDavid du Colombier 	if(mc->buttons & (7^but)){
667dd7cddfSDavid du Colombier 		rc.min.x = rc.max.x = 0;
677dd7cddfSDavid du Colombier 		rc.min.y = rc.max.y = 0;
687dd7cddfSDavid du Colombier 		while(mc->buttons)
697dd7cddfSDavid du Colombier 			readmouse(mc);
707dd7cddfSDavid du Colombier 	}
717dd7cddfSDavid du Colombier 	return rc;
727dd7cddfSDavid du Colombier }
737dd7cddfSDavid du Colombier 
747dd7cddfSDavid du Colombier static
757dd7cddfSDavid du Colombier void
freetmp(void)767dd7cddfSDavid du Colombier freetmp(void)
777dd7cddfSDavid du Colombier {
787dd7cddfSDavid du Colombier 	freeimage(tmp[0]);
797dd7cddfSDavid du Colombier 	freeimage(tmp[1]);
807dd7cddfSDavid du Colombier 	freeimage(tmp[2]);
817dd7cddfSDavid du Colombier 	freeimage(tmp[3]);
827dd7cddfSDavid du Colombier 	freeimage(red);
837dd7cddfSDavid du Colombier 	tmp[0] = tmp[1] = tmp[2] = tmp[3] = red = nil;
847dd7cddfSDavid du Colombier }
857dd7cddfSDavid du Colombier 
867dd7cddfSDavid du Colombier static
877dd7cddfSDavid du Colombier int
max(int a,int b)887dd7cddfSDavid du Colombier max(int a, int b)
897dd7cddfSDavid du Colombier {
907dd7cddfSDavid du Colombier 	if(a > b)
917dd7cddfSDavid du Colombier 		return a;
927dd7cddfSDavid du Colombier 	return b;
937dd7cddfSDavid du Colombier }
947dd7cddfSDavid du Colombier 
957dd7cddfSDavid du Colombier void
drawgetrect(Rectangle rc,int up)967dd7cddfSDavid du Colombier drawgetrect(Rectangle rc, int up)
977dd7cddfSDavid du Colombier {
987dd7cddfSDavid du Colombier 	int i;
997dd7cddfSDavid du Colombier 	Rectangle r, rects[4];
1007dd7cddfSDavid du Colombier 
1017dd7cddfSDavid du Colombier 	/*
1027dd7cddfSDavid du Colombier 	 * BUG: if for some reason we have two of these going on at once
1037dd7cddfSDavid du Colombier 	 * when we must grow the tmp buffers, we lose data.  Also if tmp
1047dd7cddfSDavid du Colombier 	 * is unallocated and we ask to restore the screen, it would be nice
1057dd7cddfSDavid du Colombier 	 * to complain, but we silently make a mess.
1067dd7cddfSDavid du Colombier 	 */
1077dd7cddfSDavid du Colombier 	if(up && tmp[0]!=nil)
10859cc4ca5SDavid du Colombier 		if(Dx(tmp[0]->r)<Dx(rc) || Dy(tmp[2]->r)<Dy(rc))
1097dd7cddfSDavid du Colombier 			freetmp();
1107dd7cddfSDavid du Colombier 	if(tmp[0] == 0){
111*9a747e4fSDavid du Colombier 		r = Rect(0, 0, max(Dx(display->screenimage->r), Dx(rc)), W);
112*9a747e4fSDavid du Colombier 		tmp[0] = allocimage(display, r, screen->chan, 0, -1);
113*9a747e4fSDavid du Colombier 		tmp[1] = allocimage(display, r, screen->chan, 0, -1);
114*9a747e4fSDavid du Colombier 		r = Rect(0, 0, W, max(Dy(display->screenimage->r), Dy(rc)));
115*9a747e4fSDavid du Colombier 		tmp[2] = allocimage(display, r, screen->chan, 0, -1);
116*9a747e4fSDavid du Colombier 		tmp[3] = allocimage(display, r, screen->chan, 0, -1);
117*9a747e4fSDavid du Colombier 		red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed);
1187dd7cddfSDavid du Colombier 		if(tmp[0]==0 || tmp[1]==0 || tmp[2]==0 || tmp[3]==0 || red==0){
1197dd7cddfSDavid du Colombier 			freetmp();
1207dd7cddfSDavid du Colombier 			drawerror(display, "getrect: allocimage failed");
1217dd7cddfSDavid du Colombier 		}
1227dd7cddfSDavid du Colombier 	}
1237dd7cddfSDavid du Colombier 	brects(rc, rects);
1247dd7cddfSDavid du Colombier 	if(!up){
1257dd7cddfSDavid du Colombier 		for(i=0; i<4; i++)
1267dd7cddfSDavid du Colombier 			draw(screen, rects[i], tmp[i], nil, ZP);
1277dd7cddfSDavid du Colombier 		return;
1287dd7cddfSDavid du Colombier 	}
1297dd7cddfSDavid du Colombier 	for(i=0; i<4; i++){
1307dd7cddfSDavid du Colombier 		draw(tmp[i], Rect(0, 0, Dx(rects[i]), Dy(rects[i])), screen, nil, rects[i].min);
1317dd7cddfSDavid du Colombier 		draw(screen, rects[i], red, nil, ZP);
1327dd7cddfSDavid du Colombier 	}
1337dd7cddfSDavid du Colombier }
134