]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdraw/getrect.c
devvmx: add support for SG_STICKY segments
[plan9front.git] / sys / src / libdraw / getrect.c
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->buttons)
47                 readmouse(mc);
48         while(!(mc->buttons & but)){
49                 readmouse(mc);
50                 if(mc->buttons & (7^but))
51                         goto Return;
52         }
53         r.min = mc->xy;
54         r.max = mc->xy;
55         do{
56                 rc = canonrect(r);
57                 drawgetrect(rc, 1);
58                 readmouse(mc);
59                 drawgetrect(rc, 0);
60                 r.max = mc->xy;
61         }while(mc->buttons == but);
62
63     Return:
64         setcursor(mc, nil);
65         if(mc->buttons & (7^but)){
66                 rc.min.x = rc.max.x = 0;
67                 rc.min.y = rc.max.y = 0;
68                 while(mc->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 }