| #include <u.h> |
| #include <libc.h> |
| #include <draw.h> |
| #include <thread.h> |
| #include <cursor.h> |
| #include <mouse.h> |
| |
| #define W Borderwidth |
| |
| static Image *tmp[4]; |
| static Image *red; |
| |
| static Cursor sweep={ |
| {-7, -7}, |
| {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x07, |
| 0xE0, 0x07, 0xE0, 0x07, 0xE3, 0xF7, 0xE3, 0xF7, |
| 0xE3, 0xE7, 0xE3, 0xF7, 0xE3, 0xFF, 0xE3, 0x7F, |
| 0xE0, 0x3F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,}, |
| {0x00, 0x00, 0x7F, 0xFE, 0x40, 0x02, 0x40, 0x02, |
| 0x40, 0x02, 0x40, 0x02, 0x40, 0x02, 0x41, 0xE2, |
| 0x41, 0xC2, 0x41, 0xE2, 0x41, 0x72, 0x40, 0x38, |
| 0x40, 0x1C, 0x40, 0x0E, 0x7F, 0xE6, 0x00, 0x00,} |
| }; |
| |
| static |
| void |
| brects(Rectangle r, Rectangle rp[4]) |
| { |
| if(Dx(r) < 2*W) |
| r.max.x = r.min.x+2*W; |
| if(Dy(r) < 2*W) |
| r.max.y = r.min.y+2*W; |
| rp[0] = Rect(r.min.x, r.min.y, r.max.x, r.min.y+W); |
| rp[1] = Rect(r.min.x, r.max.y-W, r.max.x, r.max.y); |
| rp[2] = Rect(r.min.x, r.min.y+W, r.min.x+W, r.max.y-W); |
| rp[3] = Rect(r.max.x-W, r.min.y+W, r.max.x, r.max.y-W); |
| } |
| |
| Rectangle |
| getrect(int but, Mousectl *mc) |
| { |
| Rectangle r, rc; |
| |
| but = 1<<(but-1); |
| setcursor(mc, &sweep); |
| while(mc->m.buttons) |
| readmouse(mc); |
| while(!(mc->m.buttons & but)){ |
| readmouse(mc); |
| if(mc->m.buttons & (7^but)) |
| goto Return; |
| } |
| r.min = mc->m.xy; |
| r.max = mc->m.xy; |
| do{ |
| rc = canonrect(r); |
| drawgetrect(rc, 1); |
| readmouse(mc); |
| drawgetrect(rc, 0); |
| r.max = mc->m.xy; |
| }while(mc->m.buttons == but); |
| |
| Return: |
| setcursor(mc, nil); |
| if(mc->m.buttons & (7^but)){ |
| rc.min.x = rc.max.x = 0; |
| rc.min.y = rc.max.y = 0; |
| while(mc->m.buttons) |
| readmouse(mc); |
| } |
| return rc; |
| } |
| |
| static |
| void |
| freetmp(void) |
| { |
| freeimage(tmp[0]); |
| freeimage(tmp[1]); |
| freeimage(tmp[2]); |
| freeimage(tmp[3]); |
| freeimage(red); |
| tmp[0] = tmp[1] = tmp[2] = tmp[3] = red = nil; |
| } |
| |
| static |
| int |
| max(int a, int b) |
| { |
| if(a > b) |
| return a; |
| return b; |
| } |
| |
| void |
| drawgetrect(Rectangle rc, int up) |
| { |
| int i; |
| Rectangle r, rects[4]; |
| |
| /* |
| * BUG: if for some reason we have two of these going on at once |
| * when we must grow the tmp buffers, we lose data. Also if tmp |
| * is unallocated and we ask to restore the screen, it would be nice |
| * to complain, but we silently make a mess. |
| */ |
| if(up && tmp[0]!=nil) |
| if(Dx(tmp[0]->r)<Dx(rc) || Dy(tmp[2]->r)<Dy(rc)) |
| freetmp(); |
| if(tmp[0] == 0){ |
| r = Rect(0, 0, max(Dx(display->screenimage->r), Dx(rc)), W); |
| tmp[0] = allocimage(display, r, screen->chan, 0, -1); |
| tmp[1] = allocimage(display, r, screen->chan, 0, -1); |
| r = Rect(0, 0, W, max(Dy(display->screenimage->r), Dy(rc))); |
| tmp[2] = allocimage(display, r, screen->chan, 0, -1); |
| tmp[3] = allocimage(display, r, screen->chan, 0, -1); |
| red = allocimage(display, Rect(0,0,1,1), screen->chan, 1, DRed); |
| if(tmp[0]==0 || tmp[1]==0 || tmp[2]==0 || tmp[3]==0 || red==0){ |
| freetmp(); |
| drawerror(display, "getrect: allocimage failed"); |
| } |
| } |
| brects(rc, rects); |
| if(!up){ |
| for(i=0; i<4; i++) |
| draw(screen, rects[i], tmp[i], nil, ZP); |
| return; |
| } |
| for(i=0; i<4; i++){ |
| draw(tmp[i], Rect(0, 0, Dx(rects[i]), Dy(rects[i])), screen, nil, rects[i].min); |
| draw(screen, rects[i], red, nil, ZP); |
| } |
| } |