Blob
1 #include <u.h>2 #include <libc.h>3 #include <draw.h>5 Image*6 allocimage(Display *d, Rectangle r, u32int chan, int repl, u32int val)7 {8 return _allocimage(nil, d, r, chan, repl, val, 0, 0);9 }11 Image*12 _allocimage(Image *ai, Display *d, Rectangle r, u32int chan, int repl, u32int val, int screenid, int refresh)13 {14 uchar *a;15 char *err;16 Image *i;17 Rectangle clipr;18 int id;19 int depth;21 err = 0;22 i = 0;24 if(chan == 0){25 werrstr("bad channel descriptor");26 return nil;27 }29 depth = chantodepth(chan);30 if(depth == 0){31 err = "bad channel descriptor";32 Error:33 if(err)34 werrstr("allocimage: %s", err);35 else36 werrstr("allocimage: %r");37 free(i);38 return 0;39 }41 /* flush pending data so we don't get error allocating the image */42 flushimage(d, 0);43 a = bufimage(d, 1+4+4+1+4+1+4*4+4*4+4);44 if(a == 0)45 goto Error;46 d->imageid++;47 id = d->imageid;48 a[0] = 'b';49 BPLONG(a+1, id);50 BPLONG(a+5, screenid);51 a[9] = refresh;52 BPLONG(a+10, chan);53 a[14] = repl;54 BPLONG(a+15, r.min.x);55 BPLONG(a+19, r.min.y);56 BPLONG(a+23, r.max.x);57 BPLONG(a+27, r.max.y);58 if(repl)59 /* huge but not infinite, so various offsets will leave it huge, not overflow */60 clipr = Rect(-0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF);61 else62 clipr = r;63 BPLONG(a+31, clipr.min.x);64 BPLONG(a+35, clipr.min.y);65 BPLONG(a+39, clipr.max.x);66 BPLONG(a+43, clipr.max.y);67 BPLONG(a+47, val);68 if(flushimage(d, 0) < 0)69 goto Error;71 if(ai)72 i = ai;73 else{74 i = malloc(sizeof(Image));75 if(i == nil){76 a = bufimage(d, 1+4);77 if(a){78 a[0] = 'f';79 BPLONG(a+1, id);80 flushimage(d, 0);81 }82 goto Error;83 }84 }85 i->display = d;86 i->id = id;87 i->depth = depth;88 i->chan = chan;89 i->r = r;90 i->clipr = clipr;91 i->repl = repl;92 i->screen = 0;93 i->next = 0;94 return i;95 }97 Image*98 namedimage(Display *d, char *name)99 {100 uchar *a;101 char *err, buf[12*12+1];102 Image *i;103 int id, n;104 u32int chan;106 err = 0;107 i = 0;109 n = strlen(name);110 if(n >= 256){111 err = "name too long";112 Error:113 if(err)114 werrstr("namedimage: %s", err);115 else116 werrstr("namedimage: %r");117 if(i)118 free(i);119 return 0;120 }121 /* flush pending data so we don't get error allocating the image */122 flushimage(d, 0);123 a = bufimage(d, 1+4+1+n+1);124 if(a == 0)125 goto Error;126 d->imageid++;127 id = d->imageid;128 a[0] = 'n';129 BPLONG(a+1, id);130 a[5] = n;131 memmove(a+6, name, n);132 a[6+n] = 'I';133 if(flushimage(d, 0) < 0)134 goto Error;135 if(_displayrddraw(d, buf, sizeof buf) < 12*12)136 goto Error;137 buf[12*12] = '\0';139 i = malloc(sizeof(Image));140 if(i == nil){141 Error1:142 a = bufimage(d, 1+4);143 if(a){144 a[0] = 'f';145 BPLONG(a+1, id);146 flushimage(d, 0);147 }148 goto Error;149 }150 i->display = d;151 i->id = id;152 if((chan=strtochan(buf+2*12))==0){153 werrstr("bad channel '%.12s' from devdraw", buf+2*12);154 goto Error1;155 }156 i->chan = chan;157 i->depth = chantodepth(chan);158 i->repl = atoi(buf+3*12);159 i->r.min.x = atoi(buf+4*12);160 i->r.min.y = atoi(buf+5*12);161 i->r.max.x = atoi(buf+6*12);162 i->r.max.y = atoi(buf+7*12);163 i->clipr.min.x = atoi(buf+8*12);164 i->clipr.min.y = atoi(buf+9*12);165 i->clipr.max.x = atoi(buf+10*12);166 i->clipr.max.y = atoi(buf+11*12);167 i->screen = 0;168 i->next = 0;169 return i;170 }172 int173 nameimage(Image *i, char *name, int in)174 {175 uchar *a;176 int n;178 n = strlen(name);179 a = bufimage(i->display, 1+4+1+1+n);180 if(a == 0)181 return 0;182 a[0] = 'N';183 BPLONG(a+1, i->id);184 a[5] = in;185 a[6] = n;186 memmove(a+7, name, n);187 if(flushimage(i->display, 0) < 0)188 return 0;189 return 1;190 }192 int193 _freeimage1(Image *i)194 {195 uchar *a;196 Display *d;197 Image *w;199 if(i == 0 || i->display == 0)200 return 0;201 /* make sure no refresh events occur on this if we block in the write */202 d = i->display;203 /* flush pending data so we don't get error deleting the image */204 flushimage(d, 0);205 a = bufimage(d, 1+4);206 if(a == 0)207 return -1;208 a[0] = 'f';209 BPLONG(a+1, i->id);210 if(i->screen){211 w = d->windows;212 if(w == i)213 d->windows = i->next;214 else215 while(w){216 if(w->next == i){217 w->next = i->next;218 break;219 }220 w = w->next;221 }222 }223 if(flushimage(d, i->screen!=0) < 0)224 return -1;226 return 0;227 }229 int230 freeimage(Image *i)231 {232 int ret;234 if(i == nil)235 return 0;236 if(i == screen)237 abort();238 ret = _freeimage1(i);239 free(i);240 return ret;241 }