]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdraw/alloc.c
sed: add -u flag that flushes output buffers before reading in further input
[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         a = bufimage(d, 1+4+4+1+4+1+4*4+4*4+4);
51         if(a == nil)
52                 goto Error;
53         d->imageid++;
54         id = d->imageid;
55         a[0] = 'b';
56         BPLONG(a+1, id);
57         BPLONG(a+5, screenid);
58         a[9] = refresh;
59         BPLONG(a+10, chan);
60         a[14] = repl;
61         BPLONG(a+15, r.min.x);
62         BPLONG(a+19, r.min.y);
63         BPLONG(a+23, r.max.x);
64         BPLONG(a+27, r.max.y);
65         if(repl)
66                 /* huge but not infinite, so various offsets will leave it huge, not overflow */
67                 clipr = Rect(-0x3FFFFFFF, -0x3FFFFFFF, 0x3FFFFFFF, 0x3FFFFFFF);
68         else
69                 clipr = r;
70         BPLONG(a+31, clipr.min.x);
71         BPLONG(a+35, clipr.min.y);
72         BPLONG(a+39, clipr.max.x);
73         BPLONG(a+43, clipr.max.y);
74         BPLONG(a+47, col);
75
76         if(ai != nil)
77                 i = ai;
78         else{
79                 i = malloc(sizeof(Image));
80                 if(i == nil){
81                         a = bufimage(d, 1+4);
82                         if(a != nil){
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 = nil;
98         i->next = nil;
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 = nil;
112         i = nil;
113
114         n = strlen(name);
115         if(n >= 256){
116                 err = "name too long";
117     Error:
118                 if(err != nil)
119                         werrstr("namedimage: %s", err);
120                 else
121                         werrstr("namedimage: %r");
122                 free(i);
123                 return nil;
124         }
125         /* flush pending data so we don't get error allocating the image */
126         flushimage(d, 0);
127         a = bufimage(d, 1+4+1+n);
128         if(a == nil)
129                 goto Error;
130         d->imageid++;
131         id = d->imageid;
132         a[0] = 'n';
133         BPLONG(a+1, id);
134         a[5] = n;
135         memmove(a+6, name, n);
136         if(flushimage(d, 0) < 0)
137                 goto Error;
138
139         if(pread(d->ctlfd, buf, sizeof buf, 0) < 12*12)
140                 goto Error;
141         buf[12*12] = '\0';
142
143         i = malloc(sizeof(Image));
144         if(i == nil){
145         Error1:
146                 a = bufimage(d, 1+4);
147                 if(a != nil){
148                         a[0] = 'f';
149                         BPLONG(a+1, id);
150                         flushimage(d, 0);
151                 }
152                 goto Error;
153         }
154         i->display = d;
155         i->id = id;
156         if((chan=strtochan(buf+2*12))==0){
157                 werrstr("bad channel '%.12s' from devdraw", buf+2*12);
158                 goto Error1;
159         }
160         i->chan = chan;
161         i->depth = chantodepth(chan);
162         i->repl = atoi(buf+3*12);
163         i->r.min.x = atoi(buf+4*12);
164         i->r.min.y = atoi(buf+5*12);
165         i->r.max.x = atoi(buf+6*12);
166         i->r.max.y = atoi(buf+7*12);
167         i->clipr.min.x = atoi(buf+8*12);
168         i->clipr.min.y = atoi(buf+9*12);
169         i->clipr.max.x = atoi(buf+10*12);
170         i->clipr.max.y = atoi(buf+11*12);
171         i->screen = nil;
172         i->next = nil;
173         return i;
174 }
175
176 int
177 nameimage(Image *i, char *name, int in)
178 {
179         uchar *a;
180         int n;
181
182         n = strlen(name);
183         a = bufimage(i->display, 1+4+1+1+n);
184         if(a == nil)
185                 return 0;
186         a[0] = 'N';
187         BPLONG(a+1, i->id);
188         a[5] = in;
189         a[6] = n;
190         memmove(a+7, name, n);
191         if(flushimage(i->display, 0) < 0)
192                 return 0;
193         return 1;
194 }
195
196 int
197 _freeimage1(Image *i)
198 {
199         uchar *a;
200         Display *d;
201         Image *w;
202
203         if(i == nil || i->display == nil)
204                 return 0;
205         d = i->display;
206         if(i->screen != nil){
207                 w = d->windows;
208                 if(w == i)
209                         d->windows = i->next;
210                 else
211                         while(w != nil){
212                                 if(w->next == i){
213                                         w->next = i->next;
214                                         break;
215                                 }
216                                 w = w->next;
217                         }
218         }
219         a = bufimage(d, 1+4);
220         if(a == nil)
221                 return -1;
222         a[0] = 'f';
223         BPLONG(a+1, i->id);
224         return 0;
225 }
226
227 int
228 freeimage(Image *i)
229 {
230         int ret;
231
232         ret = _freeimage1(i);
233         free(i);
234         return ret;
235 }