Subversion Repositories planix.SVN

Rev

Blame | Last modification | View Log | RSS feed

#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->buttons)
                readmouse(mc);
        while(!(mc->buttons & but)){
                readmouse(mc);
                if(mc->buttons & (7^but))
                        goto Return;
        }
        r.min = mc->xy;
        r.max = mc->xy;
        do{
                rc = canonrect(r);
                drawgetrect(rc, 1);
                readmouse(mc);
                drawgetrect(rc, 0);
                r.max = mc->xy;
        }while(mc->buttons == but);

    Return:
        setcursor(mc, nil);
        if(mc->buttons & (7^but)){
                rc.min.x = rc.max.x = 0;
                rc.min.y = rc.max.y = 0;
                while(mc->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);
        }
}