plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

getrect.c (3064B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <draw.h>
      4 #include <thread.h>
      5 #include <cursor.h>
      6 #include <mouse.h>
      7 
      8 #define	W	Borderwidth
      9 
     10 static Image *tmp[4];
     11 static Image *red;
     12 
     13 static Cursor sweep={
     14 	{-7, -7},
     15 	{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07,
     16 	 0xE0, 0x07, 0xE0, 0x07, 0xE3, 0xF7, 0xE3, 0xF7,
     17 	 0xE3, 0xE7, 0xE3, 0xF7, 0xE3, 0xFF, 0xE3, 0x7F,
     18 	 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,},
     19 	{0x00, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x40, 0x02,
     20 	 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x41, 0xE2,
     21 	 0x41, 0xC2, 0x41, 0xE2, 0x41, 0x72, 0x40, 0x38,
     22 	 0x40, 0x1C, 0x40, 0x0E, 0x7F, 0xE6, 0x00, 0x00,}
     23 };
     24 
     25 static
     26 void
     27 brects(Rectangle r, Rectangle rp[4])
     28 {
     29 	if(Dx(r) < 2*W)
     30 		r.max.x = r.min.x+2*W;
     31 	if(Dy(r) < 2*W)
     32 		r.max.y = r.min.y+2*W;
     33 	rp[0] = Rect(r.min.x, r.min.y, r.max.x, r.min.y+W);
     34 	rp[1] = Rect(r.min.x, r.max.y-W, r.max.x, r.max.y);
     35 	rp[2] = Rect(r.min.x, r.min.y+W, r.min.x+W, r.max.y-W);
     36 	rp[3] = Rect(r.max.x-W, r.min.y+W, r.max.x, r.max.y-W);
     37 }
     38 
     39 Rectangle
     40 getrect(int but, Mousectl *mc)
     41 {
     42 	Rectangle r, rc;
     43 
     44 	but = 1<<(but-1);
     45 	setcursor(mc, &sweep);
     46 	while(mc->m.buttons)
     47 		readmouse(mc);
     48 	while(!(mc->m.buttons & but)){
     49 		readmouse(mc);
     50 		if(mc->m.buttons & (7^but))
     51 			goto Return;
     52 	}
     53 	r.min = mc->m.xy;
     54 	r.max = mc->m.xy;
     55 	do{
     56 		rc = canonrect(r);
     57 		drawgetrect(rc, 1);
     58 		readmouse(mc);
     59 		drawgetrect(rc, 0);
     60 		r.max = mc->m.xy;
     61 	}while(mc->m.buttons == but);
     62 
     63     Return:
     64 	setcursor(mc, nil);
     65 	if(mc->m.buttons & (7^but)){
     66 		rc.min.x = rc.max.x = 0;
     67 		rc.min.y = rc.max.y = 0;
     68 		while(mc->m.buttons)
     69 			readmouse(mc);
     70 	}
     71 	return rc;
     72 }
     73 
     74 static
     75 void
     76 freetmp(void)
     77 {
     78 	freeimage(tmp[0]);
     79 	freeimage(tmp[1]);
     80 	freeimage(tmp[2]);
     81 	freeimage(tmp[3]);
     82 	freeimage(red);
     83 	tmp[0] = tmp[1] = tmp[2] = tmp[3] = red = nil;
     84 }
     85 
     86 static
     87 int
     88 max(int a, int b)
     89 {
     90 	if(a > b)
     91 		return a;
     92 	return b;
     93 }
     94 
     95 void
     96 drawgetrect(Rectangle rc, int up)
     97 {
     98 	int i;
     99 	Rectangle r, rects[4];
    100 
    101 	/*
    102 	 * BUG: if for some reason we have two of these going on at once
    103 	 * when we must grow the tmp buffers, we lose data.  Also if tmp
    104 	 * is unallocated and we ask to restore the screen, it would be nice
    105 	 * to complain, but we silently make a mess.
    106 	 */
    107 	if(up && tmp[0]!=nil)
    108 		if(Dx(tmp[0]->r)<Dx(rc) || Dy(tmp[2]->r)<Dy(rc))
    109 			freetmp();
    110 	if(tmp[0] == 0){
    111 		r = Rect(0, 0, max(Dx(display->screenimage->r), Dx(rc)), W);
    112 		tmp[0] = allocimage(display, r, screen->chan, 0, -1);
    113 		tmp[1] = allocimage(display, r, screen->chan, 0, -1);
    114 		r = Rect(0, 0, W, max(Dy(display->screenimage->r), Dy(rc)));
    115 		tmp[2] = allocimage(display, r, screen->chan, 0, -1);
    116 		tmp[3] = allocimage(display, r, screen->chan, 0, -1);
    117 		red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed);
    118 		if(tmp[0]==0 || tmp[1]==0 || tmp[2]==0 || tmp[3]==0 || red==0){
    119 			freetmp();
    120 			drawerror(display, "getrect: allocimage failed");
    121 		}
    122 	}
    123 	brects(rc, rects);
    124 	if(!up){
    125 		for(i=0; i<4; i++)
    126 			draw(screen, rects[i], tmp[i], nil, ZP);
    127 		return;
    128 	}
    129 	for(i=0; i<4; i++){
    130 		draw(tmp[i], Rect(0, 0, Dx(rects[i]), Dy(rects[i])), screen, nil, rects[i].min);
    131 		draw(screen, rects[i], red, nil, ZP);
    132 	}
    133 }