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