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