1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4 
5 Image*
allocimage(Display * d,Rectangle r,u32int chan,int repl,u32int val)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*
_allocimage(Image * ai,Display * d,Rectangle r,u32int chan,int repl,u32int val,int screenid,int refresh)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*
namedimage(Display * d,char * name)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
nameimage(Image * i,char * name,int in)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
_freeimage1(Image * i)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
freeimage(Image * i)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 }
242