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