Blob


1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
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 }
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;
21 err = 0;
22 i = 0;
24 if(chan == 0){
25 werrstr("bad channel descriptor");
26 return nil;
27 }
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 }
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;
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 }
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;
106 err = 0;
107 i = 0;
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;
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';
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);
148 goto Error;
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;
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;
172 int
173 nameimage(Image *i, char *name, int in)
175 uchar *a;
176 int n;
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;
192 int
193 _freeimage1(Image *i)
195 uchar *a;
196 Display *d;
197 Image *w;
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;
220 w = w->next;
223 if(flushimage(d, i->screen!=0) < 0)
224 return -1;
226 return 0;
229 int
230 freeimage(Image *i)
232 int ret;
234 if(i == nil)
235 return 0;
236 if(i == screen)
237 abort();
238 ret = _freeimage1(i);
239 free(i);
240 return ret;