1 #include "lib9.h" 2 #include "draw.h" 3 #include "kernel.h" 4 5 Image* 6 allocimage(Display *d, Rectangle r, ulong chan, int repl, ulong val) 7 { 8 return _allocimage(nil, d, r, chan, repl, val, 0, 0); 9 } 10 11 Image* 12 _allocimage(Image *ai, Display *d, Rectangle r, ulong chan, int repl, ulong val, int screenid, int refresh) 13 { 14 uchar *a; 15 char *err; 16 Image *i; 17 Rectangle clipr; 18 int id; 19 int depth; 20 21 err = 0; 22 i = 0; 23 24 if(chan == 0){ 25 kwerrstr("bad channel descriptor"); 26 return nil; 27 } 28 29 depth = chantodepth(chan); 30 if(depth == 0){ 31 err = "bad channel descriptor"; 32 Error: 33 if(err) 34 kwerrstr("allocimage: %s", err); 35 else 36 kwerrstr("allocimage: %r"); 37 free(i); 38 return 0; 39 } 40 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 else 62 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; 70 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 } 96 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 ulong chan; 105 106 err = 0; 107 i = 0; 108 109 n = strlen(name); 110 if(n >= 256){ 111 err = "name too long"; 112 Error: 113 if(err) 114 kwerrstr("namedimage: %s", err); 115 else 116 kwerrstr("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); 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 if(flushimage(d, 0) < 0) 133 goto Error; 134 135 if(kchanio(d->ctlchan, buf, sizeof buf, OREAD) < 12*12) 136 goto Error; 137 buf[12*12] = '\0'; 138 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 kwerrstr("bad channel from devdraw"); 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 } 171 172 int 173 nameimage(Image *i, char *name, int in) 174 { 175 uchar *a; 176 int n; 177 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 } 191 192 int 193 _freeimage1(Image *i) 194 { 195 uchar *a; 196 Display *d; 197 Image *w; 198 199 if(i == 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 else 215 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; 225 226 return 0; 227 } 228 229 int 230 freeimage(Image *i) 231 { 232 int ret; 233 234 ret = _freeimage1(i); 235 free(i); 236 return ret; 237 } 238