package version up
[platform/upstream/libXrandr.git] / src / XrrProviderProperty.c
1 /*
2  * Copyright © 2006 Keith Packard
3  *
4  * Permission to use, copy, modify, distribute, and sell this software and its
5  * documentation for any purpose is hereby granted without fee, provided that
6  * the above copyright notice appear in all copies and that both that copyright
7  * notice and this permission notice appear in supporting documentation, and
8  * that the name of the copyright holders not be used in advertising or
9  * publicity pertaining to distribution of the software without specific,
10  * written prior permission.  The copyright holders make no representations
11  * about the suitability of this software for any purpose.  It is provided "as
12  * is" without express or implied warranty.
13  *
14  * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
15  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
16  * EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY SPECIAL, INDIRECT OR
17  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
18  * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
19  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE
20  * OF THIS SOFTWARE.
21  */
22
23 #ifdef HAVE_CONFIG_H
24 #include <config.h>
25 #endif
26
27 #include <stdio.h>
28 #include <X11/Xlib.h>
29 /* we need to be able to manipulate the Display structure on events */
30 #include <X11/Xlibint.h>
31 #include <X11/extensions/render.h>
32 #include <X11/extensions/Xrender.h>
33 #include "Xrandrint.h"
34 #include <limits.h>
35
36 Atom *
37 XRRListProviderProperties (Display *dpy, RRProvider provider, int *nprop)
38 {
39     XExtDisplayInfo             *info = XRRFindDisplay(dpy);
40     xRRListProviderPropertiesReply rep;
41     xRRListProviderPropertiesReq        *req;
42     int                         nbytes, rbytes;
43     Atom                        *props = NULL;
44
45     RRCheckExtension (dpy, info, NULL);
46
47     LockDisplay (dpy);
48     GetReq (RRListProviderProperties, req);
49     req->reqType = info->codes->major_opcode;
50     req->randrReqType = X_RRListProviderProperties;
51     req->provider = provider;
52
53     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
54         UnlockDisplay (dpy);
55         SyncHandle ();
56         *nprop = 0;
57         return NULL;
58     }
59
60     if (rep.nAtoms) {
61         rbytes = rep.nAtoms * sizeof (Atom);
62         nbytes = rep.nAtoms << 2;
63
64         props = (Atom *) Xmalloc (rbytes);
65         if (props == NULL) {
66             _XEatDataWords (dpy, rep.length);
67             UnlockDisplay (dpy);
68             SyncHandle ();
69             *nprop = 0;
70             return NULL;
71         }
72
73         _XRead32 (dpy, props, nbytes);
74     }
75
76     *nprop = rep.nAtoms;
77     UnlockDisplay (dpy);
78     SyncHandle ();
79     return props;
80 }
81
82 XRRPropertyInfo *
83 XRRQueryProviderProperty (Display *dpy, RRProvider provider, Atom property)
84 {
85     XExtDisplayInfo             *info = XRRFindDisplay(dpy);
86     xRRQueryProviderPropertyReply rep;
87     xRRQueryProviderPropertyReq *req;
88     unsigned int                rbytes, nbytes;
89     XRRPropertyInfo             *prop_info;
90
91     RRCheckExtension (dpy, info, NULL);
92
93     LockDisplay (dpy);
94     GetReq (RRQueryProviderProperty, req);
95     req->reqType = info->codes->major_opcode;
96     req->randrReqType = X_RRQueryProviderProperty;
97     req->provider = provider;
98     req->property = property;
99
100     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) {
101         UnlockDisplay (dpy);
102         SyncHandle ();
103         return NULL;
104     }
105
106     if (rep.length < ((INT_MAX / sizeof(long)) - sizeof (XRRPropertyInfo))) {
107         rbytes = sizeof (XRRPropertyInfo) + (rep.length * sizeof (long));
108         nbytes = rep.length << 2;
109
110         prop_info = Xmalloc (rbytes);
111     } else
112         prop_info = NULL;
113
114     if (prop_info == NULL) {
115         _XEatDataWords (dpy, rep.length);
116         UnlockDisplay (dpy);
117         SyncHandle ();
118         return NULL;
119     }
120
121     prop_info->pending = rep.pending;
122     prop_info->range = rep.range;
123     prop_info->immutable = rep.immutable;
124     prop_info->num_values = rep.length;
125     if (rep.length != 0) {
126         prop_info->values = (long *) (prop_info + 1);
127         _XRead32 (dpy, prop_info->values, nbytes);
128     } else {
129         prop_info->values = NULL;
130     }
131
132     UnlockDisplay (dpy);
133     SyncHandle ();
134     return prop_info;
135 }
136
137 void
138 XRRConfigureProviderProperty (Display *dpy, RRProvider provider, Atom property,
139                             Bool pending, Bool range, int num_values,
140                             long *values)
141 {
142     XExtDisplayInfo                 *info = XRRFindDisplay(dpy);
143     xRRConfigureProviderPropertyReq   *req;
144     long len;
145
146     RRSimpleCheckExtension (dpy, info);
147
148     LockDisplay(dpy);
149     GetReq (RRConfigureProviderProperty, req);
150     req->reqType = info->codes->major_opcode;
151     req->randrReqType = X_RRConfigureProviderProperty;
152     req->provider = provider;
153     req->property = property;
154     req->pending = pending;
155     req->range = range;
156
157     len = num_values;
158     if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
159         SetReqLen(req, len, len);
160         len = (long)num_values << 2;
161         Data32 (dpy, values, len);
162     } /* else force BadLength */
163
164     UnlockDisplay(dpy);
165     SyncHandle();
166 }
167                         
168 void
169 XRRChangeProviderProperty (Display *dpy, RRProvider provider,
170                          Atom property, Atom type,
171                          int format, int mode,
172                          _Xconst unsigned char *data, int nelements)
173 {
174     XExtDisplayInfo             *info = XRRFindDisplay(dpy);
175     xRRChangeProviderPropertyReq        *req;
176     long len;
177
178     RRSimpleCheckExtension (dpy, info);
179
180     LockDisplay(dpy);
181     GetReq (RRChangeProviderProperty, req);
182     req->reqType = info->codes->major_opcode;
183     req->randrReqType = X_RRChangeProviderProperty;
184     req->provider = provider;
185     req->property = property;
186     req->type = type;
187     req->mode = mode;
188     if (nelements < 0) {
189         req->nUnits = 0;
190         req->format = 0; /* ask for garbage, get garbage */
191     } else {
192         req->nUnits = nelements;
193         req->format = format;
194     }
195
196     switch (req->format) {
197     case 8:
198         len = ((long)nelements + 3) >> 2;
199         if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
200             SetReqLen(req, len, len);
201             Data (dpy, (char *)data, nelements);
202         } /* else force BadLength */
203         break;
204
205     case 16:
206         len = ((long)nelements + 1) >> 1;
207         if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
208             SetReqLen(req, len, len);
209             len = (long)nelements << 1;
210             Data16 (dpy, (short *) data, len);
211         } /* else force BadLength */
212         break;
213
214     case 32:
215         len = nelements;
216         if (dpy->bigreq_size || req->length + len <= (unsigned) 65535) {
217             SetReqLen(req, len, len);
218             len = (long)nelements << 2;
219             Data32 (dpy, (long *) data, len);
220         } /* else force BadLength */
221         break;
222
223     default:
224         /* BadValue will be generated */ ;
225     }
226
227     UnlockDisplay(dpy);
228     SyncHandle();
229 }
230
231 void
232 XRRDeleteProviderProperty (Display *dpy, RRProvider provider, Atom property)
233 {
234     XExtDisplayInfo             *info = XRRFindDisplay(dpy);
235     xRRDeleteProviderPropertyReq *req;
236
237     RRSimpleCheckExtension (dpy, info);
238
239     LockDisplay(dpy);
240     GetReq(RRDeleteProviderProperty, req);
241     req->reqType = info->codes->major_opcode;
242     req->randrReqType = X_RRDeleteProviderProperty;
243     req->provider = provider;
244     req->property = property;
245     UnlockDisplay(dpy);
246     SyncHandle();
247 }
248
249 int
250 XRRGetProviderProperty (Display *dpy, RRProvider provider,
251                       Atom property, long offset, long length,
252                       Bool delete, Bool pending, Atom req_type, 
253                       Atom *actual_type, int *actual_format,
254                       unsigned long *nitems, unsigned long *bytes_after,
255                       unsigned char **prop)
256 {
257     XExtDisplayInfo             *info = XRRFindDisplay(dpy);
258     xRRGetProviderPropertyReply rep;
259     xRRGetProviderPropertyReq   *req;
260     unsigned long               nbytes, rbytes;
261
262     /* Always initialize return values, in case callers fail to initialize
263        them and fail to check the return code for an error. */
264     *actual_type = None;
265     *actual_format = 0;
266     *nitems = *bytes_after = 0L;
267     *prop = (unsigned char *) NULL;
268
269     RRCheckExtension (dpy, info, 1);
270
271     LockDisplay (dpy);
272     GetReq (RRGetProviderProperty, req);
273     req->reqType = info->codes->major_opcode;
274     req->randrReqType = X_RRGetProviderProperty;
275     req->provider = provider;
276     req->property = property;
277     req->type = req_type;
278     req->longOffset = offset;
279     req->longLength = length;
280     req->delete = delete;
281     req->pending = pending;
282
283     if (!_XReply (dpy, (xReply *) &rep, 0, xFalse))
284     {
285         UnlockDisplay (dpy);
286         SyncHandle ();
287         return ((xError *)&rep)->errorCode;
288     }
289
290     if (rep.propertyType != None) {
291         int format = rep.format;
292
293         /*
294          * Protect against both integer overflow and just plain oversized
295          * memory allocation - no server should ever return this many props.
296          */
297         if (rep.nItems >= (INT_MAX >> 4))
298             format = -1;        /* fall through to default error case */
299
300         /*
301          * One extra byte is malloced than is needed to contain the property
302          * data, but this last byte is null terminated and convenient for
303          * returning string properties, so the client doesn't then have to
304          * recopy the string to make it null terminated.
305          */
306         switch (format) {
307         case 8:
308             nbytes = rep.nItems;
309             rbytes = rep.nItems + 1;
310             if (rbytes > 0 && (*prop = Xmalloc (rbytes)))
311                 _XReadPad (dpy, (char *) *prop, nbytes);
312             break;
313
314         case 16:
315             nbytes = rep.nItems << 1;
316             rbytes = rep.nItems * sizeof (short) + 1;
317             if (rbytes > 0 && (*prop = Xmalloc (rbytes)))
318                 _XRead16Pad (dpy, (short *) *prop, nbytes);
319             break;
320
321         case 32:
322             nbytes = rep.nItems << 2;
323             rbytes = rep.nItems * sizeof (long) + 1;
324             if (rbytes > 0 && (*prop = Xmalloc (rbytes)))
325                 _XRead32 (dpy, (long *) *prop, nbytes);
326             break;
327
328         default:
329             /*
330              * This part of the code should never be reached.  If it is,
331              * the server sent back a property with an invalid format.
332              */
333             _XEatDataWords(dpy, rep.length);
334             UnlockDisplay(dpy);
335             SyncHandle();
336             return(BadImplementation);
337         }
338         if (! *prop) {
339             _XEatDataWords(dpy, rep.length);
340             UnlockDisplay(dpy);
341             SyncHandle();
342             return(BadAlloc);
343         }
344         (*prop)[rbytes - 1] = '\0';
345     }
346
347     *actual_type = rep.propertyType;
348     *actual_format = rep.format;
349     *nitems = rep.nItems;
350     *bytes_after = rep.bytesAfter;
351     UnlockDisplay (dpy);
352     SyncHandle ();
353
354     return Success;
355 }