ref: c0383d8291b2da3aed8a7751097a220442777652
dir: /sys/src/libdraw/egetrect.c/
#include <u.h> #include <libc.h> #include <draw.h> #include <cursor.h> #include <event.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 egetrect(int but, Mouse *m) { Rectangle r, rc; but = 1<<(but-1); esetcursor(&sweep); while(m->buttons) *m = emouse(); while(!(m->buttons & but)){ *m = emouse(); if(m->buttons & (7^but)) goto Return; } r.min = m->xy; r.max = m->xy; do{ rc = canonrect(r); edrawgetrect(rc, 1); *m = emouse(); edrawgetrect(rc, 0); r.max = m->xy; }while(m->buttons == but); Return: esetcursor(0); if(m->buttons & (7^but)){ rc.min.x = rc.max.x = 0; rc.min.y = rc.max.y = 0; while(m->buttons) *m = emouse(); } 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; } void edrawgetrect(Rectangle rc, int up) { int i; Rectangle r, rects[4]; 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, Dx(screen->r), W); tmp[0] = allocimage(display, r, screen->chan, 0, -1); tmp[1] = allocimage(display, r, screen->chan, 0, -1); r = Rect(0, 0, W, Dy(screen->r)); 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) 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); } }