plan9port

fork of plan9port with libvec, libstr and libsdb
Log | Files | Refs | README | LICENSE

alloc.c (4188B)


      1 #include <u.h>
      2 #include <libc.h>
      3 #include <draw.h>
      4 
      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 }
     10 
     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;
     20 
     21 	err = 0;
     22 	i = 0;
     23 
     24 	if(chan == 0){
     25 		werrstr("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 			werrstr("allocimage: %s", err);
     35 		else
     36 			werrstr("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 	u32int 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 			werrstr("namedimage: %s", err);
    115 		else
    116 			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';
    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 		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 }
    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 || 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 		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 	if(i == nil)
    235 		return 0;
    236 	if(i == screen)
    237 		abort();
    238 	ret = _freeimage1(i);
    239 	free(i);
    240 	return ret;
    241 }