aboutsummaryrefslogtreecommitdiff
path: root/src/libdraw/getrect.c
diff options
context:
space:
mode:
authorrsc <devnull@localhost>2003-09-30 17:47:42 +0000
committerrsc <devnull@localhost>2003-09-30 17:47:42 +0000
commited7c8e8d02c02bdbff1e88a6d8d1419f39af48ad (patch)
treeebcd32d20b0df2584bce713fefa87620ecd1cce7 /src/libdraw/getrect.c
parentb2cfc4e2e71d0f0a5113ddfbd93c8285cc4d74e4 (diff)
downloadplan9port-ed7c8e8d02c02bdbff1e88a6d8d1419f39af48ad.tar.gz
plan9port-ed7c8e8d02c02bdbff1e88a6d8d1419f39af48ad.tar.bz2
plan9port-ed7c8e8d02c02bdbff1e88a6d8d1419f39af48ad.zip
Initial import.
Diffstat (limited to 'src/libdraw/getrect.c')
-rw-r--r--src/libdraw/getrect.c133
1 files changed, 133 insertions, 0 deletions
diff --git a/src/libdraw/getrect.c b/src/libdraw/getrect.c
new file mode 100644
index 00000000..a050e4c4
--- /dev/null
+++ b/src/libdraw/getrect.c
@@ -0,0 +1,133 @@
+#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);
+ }
+}