aboutsummaryrefslogtreecommitdiff
path: root/src/libdraw/alloc.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/libdraw/alloc.c')
-rw-r--r--src/libdraw/alloc.c237
1 files changed, 237 insertions, 0 deletions
diff --git a/src/libdraw/alloc.c b/src/libdraw/alloc.c
new file mode 100644
index 00000000..50b96fd8
--- /dev/null
+++ b/src/libdraw/alloc.c
@@ -0,0 +1,237 @@
+#include <u.h>
+#include <libc.h>
+#include <draw.h>
+
+Image*
+allocimage(Display *d, Rectangle r, u32int chan, int repl, u32int val)
+{
+ return _allocimage(nil, d, r, chan, repl, val, 0, 0);
+}
+
+Image*
+_allocimage(Image *ai, Display *d, Rectangle r, u32int chan, int repl, u32int val, int screenid, int refresh)
+{
+ uchar *a;
+ char *err;
+ Image *i;
+ Rectangle clipr;
+ int id;
+ int depth;
+
+ err = 0;
+ i = 0;
+
+ if(chan == 0){
+ werrstr("bad channel descriptor");
+ return nil;
+ }
+
+ depth = chantodepth(chan);
+ if(depth == 0){
+ err = "bad channel descriptor";
+ Error:
+ if(err)
+ werrstr("allocimage: %s", err);
+ else
+ werrstr("allocimage: %r");
+ free(i);
+ return 0;
+ }
+
+ /* flush pending data so we don't get error allocating the image */
+ flushimage(d, 0);
+ a = bufimage(d, 1+4+4+1+4+1+4*4+4*4+4);
+ if(a == 0)
+ goto Error;
+ d->imageid++;
+ id = d->imageid;
+ a[0] = 'b';
+ BPLONG(a+1, id);
+ BPLONG(a+5, screenid);
+ a[9] = refresh;
+ BPLONG(a+10, chan);
+ a[14] = repl;
+ BPLONG(a+15, r.min.x);
+ BPLONG(a+19, r.min.y);
+ BPLONG(a+23, r.max.x);
+ BPLONG(a+27, r.max.y);
+ if(repl)
+ /* huge but not infinite, so various offsets will leave it huge, not overflow */
+ clipr = Rect(-0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF);
+ else
+ clipr = r;
+ BPLONG(a+31, clipr.min.x);
+ BPLONG(a+35, clipr.min.y);
+ BPLONG(a+39, clipr.max.x);
+ BPLONG(a+43, clipr.max.y);
+ BPLONG(a+47, val);
+ if(flushimage(d, 0) < 0)
+ goto Error;
+
+ if(ai)
+ i = ai;
+ else{
+ i = malloc(sizeof(Image));
+ if(i == nil){
+ a = bufimage(d, 1+4);
+ if(a){
+ a[0] = 'f';
+ BPLONG(a+1, id);
+ flushimage(d, 0);
+ }
+ goto Error;
+ }
+ }
+ i->display = d;
+ i->id = id;
+ i->depth = depth;
+ i->chan = chan;
+ i->r = r;
+ i->clipr = clipr;
+ i->repl = repl;
+ i->screen = 0;
+ i->next = 0;
+ return i;
+}
+
+Image*
+namedimage(Display *d, char *name)
+{
+ uchar *a;
+ char *err, buf[12*12+1];
+ Image *i;
+ int id, n;
+ u32int chan;
+
+ err = 0;
+ i = 0;
+
+ n = strlen(name);
+ if(n >= 256){
+ err = "name too long";
+ Error:
+ if(err)
+ werrstr("namedimage: %s", err);
+ else
+ werrstr("namedimage: %r");
+ if(i)
+ free(i);
+ return 0;
+ }
+ /* flush pending data so we don't get error allocating the image */
+ flushimage(d, 0);
+ a = bufimage(d, 1+4+1+n+1);
+ if(a == 0)
+ goto Error;
+ d->imageid++;
+ id = d->imageid;
+ a[0] = 'n';
+ BPLONG(a+1, id);
+ a[5] = n;
+ memmove(a+6, name, n);
+ a[6+n] = 'I';
+ if(flushimage(d, 0) < 0)
+ goto Error;
+ if(_drawmsgread(d, buf, sizeof buf) < 12*12)
+ goto Error;
+ buf[12*12] = '\0';
+
+ i = malloc(sizeof(Image));
+ if(i == nil){
+ Error1:
+ a = bufimage(d, 1+4);
+ if(a){
+ a[0] = 'f';
+ BPLONG(a+1, id);
+ flushimage(d, 0);
+ }
+ goto Error;
+ }
+ i->display = d;
+ i->id = id;
+ if((chan=strtochan(buf+2*12))==0){
+ werrstr("bad channel '%.12s' from devdraw", buf+2*12);
+ goto Error1;
+ }
+ i->chan = chan;
+ i->depth = chantodepth(chan);
+ i->repl = atoi(buf+3*12);
+ i->r.min.x = atoi(buf+4*12);
+ i->r.min.y = atoi(buf+5*12);
+ i->r.max.x = atoi(buf+6*12);
+ i->r.max.y = atoi(buf+7*12);
+ i->clipr.min.x = atoi(buf+8*12);
+ i->clipr.min.y = atoi(buf+9*12);
+ i->clipr.max.x = atoi(buf+10*12);
+ i->clipr.max.y = atoi(buf+11*12);
+ i->screen = 0;
+ i->next = 0;
+ return i;
+}
+
+int
+nameimage(Image *i, char *name, int in)
+{
+ uchar *a;
+ int n;
+
+ n = strlen(name);
+ a = bufimage(i->display, 1+4+1+1+n);
+ if(a == 0)
+ return 0;
+ a[0] = 'N';
+ BPLONG(a+1, i->id);
+ a[5] = in;
+ a[6] = n;
+ memmove(a+7, name, n);
+ if(flushimage(i->display, 0) < 0)
+ return 0;
+ return 1;
+}
+
+int
+_freeimage1(Image *i)
+{
+ uchar *a;
+ Display *d;
+ Image *w;
+
+ if(i == 0)
+ return 0;
+ /* make sure no refresh events occur on this if we block in the write */
+ d = i->display;
+ /* flush pending data so we don't get error deleting the image */
+ flushimage(d, 0);
+ a = bufimage(d, 1+4);
+ if(a == 0)
+ return -1;
+ a[0] = 'f';
+ BPLONG(a+1, i->id);
+ if(i->screen){
+ w = d->windows;
+ if(w == i)
+ d->windows = i->next;
+ else
+ while(w){
+ if(w->next == i){
+ w->next = i->next;
+ break;
+ }
+ w = w->next;
+ }
+ }
+ if(flushimage(d, i->screen!=0) < 0)
+ return -1;
+
+ return 0;
+}
+
+int
+freeimage(Image *i)
+{
+ int ret;
+
+ ret = _freeimage1(i);
+ free(i);
+ return ret;
+}