]> git.lizzy.rs Git - plan9front.git/blob - sys/src/libdraw/alloc.c
realemu: ignore access to CMOS/RTC address/data registers
[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(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)
43                         werrstr("allocimage: %s", err);
44                 else
45                         werrstr("allocimage: %r");
46                 free(i);
47                 return 0;
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 == 0)
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, val);
77         if(flushimage(d, 0) < 0)
78                 goto Error;
79
80         if(ai)
81                 i = ai;
82         else{
83                 i = malloc(sizeof(Image));
84                 if(i == nil){
85                         a = bufimage(d, 1+4);
86                         if(a){
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 = 0;
102         i->next = 0;
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 = 0;
116         i = 0;
117
118         n = strlen(name);
119         if(n >= 256){
120                 err = "name too long";
121     Error:
122                 if(err)
123                         werrstr("namedimage: %s", err);
124                 else
125                         werrstr("namedimage: %r");
126                 if(i)
127                         free(i);
128                 return 0;
129         }
130         /* flush pending data so we don't get error allocating the image */
131         flushimage(d, 0);
132         a = bufimage(d, 1+4+1+n);
133         if(a == 0)
134                 goto Error;
135         d->imageid++;
136         id = d->imageid;
137         a[0] = 'n';
138         BPLONG(a+1, id);
139         a[5] = n;
140         memmove(a+6, name, n);
141         if(flushimage(d, 0) < 0)
142                 goto Error;
143
144         if(pread(d->ctlfd, buf, sizeof buf, 0) < 12*12)
145                 goto Error;
146         buf[12*12] = '\0';
147
148         i = malloc(sizeof(Image));
149         if(i == nil){
150         Error1:
151                 a = bufimage(d, 1+4);
152                 if(a){
153                         a[0] = 'f';
154                         BPLONG(a+1, id);
155                         flushimage(d, 0);
156                 }
157                 goto Error;
158         }
159         i->display = d;
160         i->id = id;
161         if((chan=strtochan(buf+2*12))==0){
162                 werrstr("bad channel '%.12s' from devdraw", buf+2*12);
163                 goto Error1;
164         }
165         i->chan = chan;
166         i->depth = chantodepth(chan);
167         i->repl = atoi(buf+3*12);
168         i->r.min.x = atoi(buf+4*12);
169         i->r.min.y = atoi(buf+5*12);
170         i->r.max.x = atoi(buf+6*12);
171         i->r.max.y = atoi(buf+7*12);
172         i->clipr.min.x = atoi(buf+8*12);
173         i->clipr.min.y = atoi(buf+9*12);
174         i->clipr.max.x = atoi(buf+10*12);
175         i->clipr.max.y = atoi(buf+11*12);
176         i->screen = 0;
177         i->next = 0;
178         return i;
179 }
180
181 int
182 nameimage(Image *i, char *name, int in)
183 {
184         uchar *a;
185         int n;
186
187         n = strlen(name);
188         a = bufimage(i->display, 1+4+1+1+n);
189         if(a == 0)
190                 return 0;
191         a[0] = 'N';
192         BPLONG(a+1, i->id);
193         a[5] = in;
194         a[6] = n;
195         memmove(a+7, name, n);
196         if(flushimage(i->display, 0) < 0)
197                 return 0;
198         return 1;
199 }
200
201 int
202 _freeimage1(Image *i)
203 {
204         uchar *a;
205         Display *d;
206         Image *w;
207
208         if(i == 0 || i->display == 0)
209                 return 0;
210         /* make sure no refresh events occur on this if we block in the write */
211         d = i->display;
212         /* flush pending data so we don't get error deleting the image */
213         flushimage(d, 0);
214         a = bufimage(d, 1+4);
215         if(a == 0)
216                 return -1;
217         a[0] = 'f';
218         BPLONG(a+1, i->id);
219         if(i->screen){
220                 w = d->windows;
221                 if(w == i)
222                         d->windows = i->next;
223                 else
224                         while(w){
225                                 if(w->next == i){
226                                         w->next = i->next;
227                                         break;
228                                 }
229                                 w = w->next;
230                         }
231         }
232         if(flushimage(d, i->screen!=0) < 0)
233                 return -1;
234
235         return 0;
236 }
237
238 int
239 freeimage(Image *i)
240 {
241         int ret;
242
243         ret = _freeimage1(i);
244         free(i);
245         return ret;
246 }