]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdraw/alloc.c
Import sources from 2011-03-30 iso image - lib
[plan9front.git] / sys / src / libdraw / alloc.c
1 #include <u.h>
2 #include <libc.h>
3 #include <draw.h>
4
5 Image*
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*
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*
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
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
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
235 freeimage(Image *i)
236 {
237         int ret;
238
239         ret = _freeimage1(i);
240         free(i);
241         return ret;
242 }