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