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