| @@ -1,251 +1,465 @@ | | | @@ -1,251 +1,465 @@ |
1 | /* | | 1 | /* |
2 | Copyright (c) 2002 XFree86 Inc | | 2 | Copyright (c) 2002 XFree86 Inc |
3 | */ | | 3 | */ |
4 | | | 4 | |
5 | #ifdef HAVE_CONFIG_H | | 5 | #ifdef HAVE_CONFIG_H |
6 | #include <config.h> | | 6 | #include <config.h> |
7 | #endif | | 7 | #endif |
8 | #include <stdlib.h> | | 8 | #include <stdlib.h> |
9 | #include <X11/Xlibint.h> | | 9 | #include <X11/Xlibint.h> |
10 | #include <X11/Xutil.h> | | 10 | #include <X11/Xutil.h> |
11 | #include <X11/extensions/Xext.h> | | 11 | #include <X11/extensions/Xext.h> |
12 | #include <X11/extensions/extutil.h> | | 12 | #include <X11/extensions/extutil.h> |
13 | #include <X11/extensions/XResproto.h> | | 13 | #include <X11/extensions/XResproto.h> |
14 | #include <X11/extensions/XRes.h> | | 14 | #include <X11/extensions/XRes.h> |
| | | 15 | #include <assert.h> |
15 | #include <limits.h> | | 16 | #include <limits.h> |
16 | | | 17 | |
17 | #ifndef HAVE__XEATDATAWORDS | | | |
18 | static inline void _XEatDataWords(Display *dpy, unsigned long n) | | | |
19 | { | | | |
20 | # ifndef LONG64 | | | |
21 | if (n >= (ULONG_MAX >> 2)) | | | |
22 | _XIOError(dpy); | | | |
23 | # endif | | | |
24 | _XEatData (dpy, n << 2); | | | |
25 | } | | | |
26 | #endif | | | |
27 | | | | |
28 | static XExtensionInfo _xres_ext_info_data; | | 18 | static XExtensionInfo _xres_ext_info_data; |
29 | static XExtensionInfo *xres_ext_info = &_xres_ext_info_data; | | 19 | static XExtensionInfo *xres_ext_info = &_xres_ext_info_data; |
30 | static const char *xres_extension_name = XRES_NAME; | | 20 | static const char *xres_extension_name = XRES_NAME; |
31 | | | 21 | |
32 | #define XResCheckExtension(dpy,i,val) \ | | 22 | #define XResCheckExtension(dpy,i,val) \ |
33 | XextCheckExtension (dpy, i, xres_extension_name, val) | | 23 | XextCheckExtension (dpy, i, xres_extension_name, val) |
34 | | | 24 | |
35 | static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xres_ext_info) | | 25 | static XEXT_GENERATE_CLOSE_DISPLAY (close_display, xres_ext_info) |
36 | | | 26 | |
37 | static XExtensionHooks xres_extension_hooks = { | | 27 | static XExtensionHooks xres_extension_hooks = { |
38 | NULL, /* create_gc */ | | 28 | NULL, /* create_gc */ |
39 | NULL, /* copy_gc */ | | 29 | NULL, /* copy_gc */ |
40 | NULL, /* flush_gc */ | | 30 | NULL, /* flush_gc */ |
41 | NULL, /* free_gc */ | | 31 | NULL, /* free_gc */ |
42 | NULL, /* create_font */ | | 32 | NULL, /* create_font */ |
43 | NULL, /* free_font */ | | 33 | NULL, /* free_font */ |
44 | close_display, /* close_display */ | | 34 | close_display, /* close_display */ |
45 | NULL, /* wire_to_event */ | | 35 | NULL, /* wire_to_event */ |
46 | NULL, /* event_to_wire */ | | 36 | NULL, /* event_to_wire */ |
47 | NULL, /* error */ | | 37 | NULL, /* error */ |
48 | NULL, /* error_string */ | | 38 | NULL, /* error_string */ |
49 | }; | | 39 | }; |
50 | | | 40 | |
51 | static XEXT_GENERATE_FIND_DISPLAY (find_display, xres_ext_info, | | 41 | static XEXT_GENERATE_FIND_DISPLAY (find_display, xres_ext_info, |
52 | xres_extension_name, | | 42 | xres_extension_name, |
53 | &xres_extension_hooks, | | 43 | &xres_extension_hooks, |
54 | 0, NULL) | | 44 | 0, NULL) |
55 | | | 45 | |
56 | Bool XResQueryExtension ( | | 46 | Bool XResQueryExtension ( |
57 | Display *dpy, | | 47 | Display *dpy, |
58 | int *event_base_return, | | 48 | int *event_base_return, |
59 | int *error_base_return | | 49 | int *error_base_return |
60 | ) | | 50 | ) |
61 | { | | 51 | { |
62 | XExtDisplayInfo *info = find_display (dpy); | | 52 | XExtDisplayInfo *info = find_display (dpy); |
63 | | | 53 | |
64 | if (XextHasExtension(info)) { | | 54 | if (XextHasExtension(info)) { |
65 | *event_base_return = info->codes->first_event; | | 55 | *event_base_return = info->codes->first_event; |
66 | *error_base_return = info->codes->first_error; | | 56 | *error_base_return = info->codes->first_error; |
67 | return True; | | 57 | return True; |
68 | } else { | | 58 | } else { |
69 | return False; | | 59 | return False; |
70 | } | | 60 | } |
71 | } | | 61 | } |
72 | | | 62 | |
73 | Status XResQueryVersion( | | 63 | Status XResQueryVersion( |
74 | Display *dpy, | | 64 | Display *dpy, |
75 | int *major_version_return, | | 65 | int *major_version_return, |
76 | int *minor_version_return | | 66 | int *minor_version_return |
77 | ) | | 67 | ) |
78 | { | | 68 | { |
79 | XExtDisplayInfo *info = find_display (dpy); | | 69 | XExtDisplayInfo *info = find_display (dpy); |
80 | xXResQueryVersionReply rep; | | 70 | xXResQueryVersionReply rep; |
81 | xXResQueryVersionReq *req; | | 71 | xXResQueryVersionReq *req; |
82 | | | 72 | |
83 | XResCheckExtension (dpy, info, 0); | | 73 | XResCheckExtension (dpy, info, 0); |
84 | | | 74 | |
85 | LockDisplay (dpy); | | 75 | LockDisplay (dpy); |
86 | GetReq (XResQueryVersion, req); | | 76 | GetReq (XResQueryVersion, req); |
87 | req->reqType = info->codes->major_opcode; | | 77 | req->reqType = info->codes->major_opcode; |
88 | req->XResReqType = X_XResQueryVersion; | | 78 | req->XResReqType = X_XResQueryVersion; |
89 | req->client_major = XRES_MAJOR_VERSION; | | 79 | req->client_major = XRES_MAJOR_VERSION; |
90 | req->client_minor = XRES_MINOR_VERSION; | | 80 | req->client_minor = XRES_MINOR_VERSION; |
91 | if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { | | 81 | if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { |
92 | UnlockDisplay (dpy); | | 82 | UnlockDisplay (dpy); |
93 | SyncHandle (); | | 83 | SyncHandle (); |
94 | return 0; | | 84 | return 0; |
95 | } | | 85 | } |
96 | *major_version_return = rep.server_major; | | 86 | *major_version_return = rep.server_major; |
97 | *minor_version_return = rep.server_minor; | | 87 | *minor_version_return = rep.server_minor; |
98 | UnlockDisplay (dpy); | | 88 | UnlockDisplay (dpy); |
99 | SyncHandle (); | | 89 | SyncHandle (); |
100 | return 1; | | 90 | return 1; |
101 | } | | 91 | } |
102 | | | 92 | |
103 | | | 93 | |
104 | Status XResQueryClients ( | | 94 | Status XResQueryClients ( |
105 | Display *dpy, | | 95 | Display *dpy, |
106 | int *num_clients, | | 96 | int *num_clients, |
107 | XResClient **clients | | 97 | XResClient **clients |
108 | ) | | 98 | ) |
109 | { | | 99 | { |
110 | XExtDisplayInfo *info = find_display (dpy); | | 100 | XExtDisplayInfo *info = find_display (dpy); |
111 | xXResQueryClientsReq *req; | | 101 | xXResQueryClientsReq *req; |
112 | xXResQueryClientsReply rep; | | 102 | xXResQueryClientsReply rep; |
113 | XResClient *clnts; | | 103 | XResClient *clnts; |
114 | int result = 0; | | 104 | int result = 0; |
115 | | | 105 | |
116 | *num_clients = 0; | | 106 | *num_clients = 0; |
117 | *clients = NULL; | | 107 | *clients = NULL; |
118 | | | 108 | |
119 | XResCheckExtension (dpy, info, 0); | | 109 | XResCheckExtension (dpy, info, 0); |
120 | | | 110 | |
121 | LockDisplay (dpy); | | 111 | LockDisplay (dpy); |
122 | GetReq (XResQueryClients, req); | | 112 | GetReq (XResQueryClients, req); |
123 | req->reqType = info->codes->major_opcode; | | 113 | req->reqType = info->codes->major_opcode; |
124 | req->XResReqType = X_XResQueryClients; | | 114 | req->XResReqType = X_XResQueryClients; |
125 | if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { | | 115 | if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { |
126 | UnlockDisplay (dpy); | | 116 | UnlockDisplay (dpy); |
127 | SyncHandle (); | | 117 | SyncHandle (); |
128 | return 0; | | 118 | return 0; |
129 | } | | 119 | } |
130 | | | 120 | |
131 | if(rep.num_clients) { | | 121 | if(rep.num_clients) { |
132 | if (rep.num_clients < (INT_MAX / sizeof(XResClient))) | | 122 | if (rep.num_clients < (INT_MAX / sizeof(XResClient))) |
133 | clnts = Xmalloc(sizeof(XResClient) * rep.num_clients); | | 123 | clnts = Xmalloc(sizeof(XResClient) * rep.num_clients); |
134 | else | | 124 | else |
135 | clnts = NULL; | | 125 | clnts = NULL; |
136 | | | 126 | |
137 | if (clnts != NULL) { | | 127 | if (clnts != NULL) { |
138 | xXResClient scratch; | | 128 | xXResClient scratch; |
139 | int i; | | 129 | int i; |
140 | | | 130 | |
141 | for(i = 0; i < rep.num_clients; i++) { | | 131 | for(i = 0; i < rep.num_clients; i++) { |
142 | _XRead(dpy, (char*)&scratch, sz_xXResClient); | | 132 | _XRead(dpy, (char*)&scratch, sz_xXResClient); |
143 | clnts[i].resource_base = scratch.resource_base; | | 133 | clnts[i].resource_base = scratch.resource_base; |
144 | clnts[i].resource_mask = scratch.resource_mask; | | 134 | clnts[i].resource_mask = scratch.resource_mask; |
145 | } | | 135 | } |
146 | *clients = clnts; | | 136 | *clients = clnts; |
147 | *num_clients = rep.num_clients; | | 137 | *num_clients = rep.num_clients; |
148 | result = 1; | | 138 | result = 1; |
149 | } else { | | 139 | } else { |
150 | _XEatDataWords(dpy, rep.length); | | 140 | _XEatDataWords(dpy, rep.length); |
151 | } | | 141 | } |
152 | } | | 142 | } |
153 | | | 143 | |
154 | UnlockDisplay (dpy); | | 144 | UnlockDisplay (dpy); |
155 | SyncHandle (); | | 145 | SyncHandle (); |
156 | return result; | | 146 | return result; |
157 | } | | 147 | } |
158 | | | 148 | |
159 | Status XResQueryClientResources ( | | 149 | Status XResQueryClientResources ( |
160 | Display *dpy, | | 150 | Display *dpy, |
161 | XID xid, | | 151 | XID xid, |
162 | int *num_types, | | 152 | int *num_types, |
163 | XResType **types | | 153 | XResType **types |
164 | ) | | 154 | ) |
165 | { | | 155 | { |
166 | XExtDisplayInfo *info = find_display (dpy); | | 156 | XExtDisplayInfo *info = find_display (dpy); |
167 | xXResQueryClientResourcesReq *req; | | 157 | xXResQueryClientResourcesReq *req; |
168 | xXResQueryClientResourcesReply rep; | | 158 | xXResQueryClientResourcesReply rep; |
169 | XResType *typs; | | 159 | XResType *typs; |
170 | int result = 0; | | 160 | int result = 0; |
171 | | | 161 | |
172 | *num_types = 0; | | 162 | *num_types = 0; |
173 | *types = NULL; | | 163 | *types = NULL; |
174 | | | 164 | |
175 | XResCheckExtension (dpy, info, 0); | | 165 | XResCheckExtension (dpy, info, 0); |
176 | | | 166 | |
177 | LockDisplay (dpy); | | 167 | LockDisplay (dpy); |
178 | GetReq (XResQueryClientResources, req); | | 168 | GetReq (XResQueryClientResources, req); |
179 | req->reqType = info->codes->major_opcode; | | 169 | req->reqType = info->codes->major_opcode; |
180 | req->XResReqType = X_XResQueryClientResources; | | 170 | req->XResReqType = X_XResQueryClientResources; |
181 | req->xid = xid; | | 171 | req->xid = xid; |
182 | if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { | | 172 | if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { |
183 | UnlockDisplay (dpy); | | 173 | UnlockDisplay (dpy); |
184 | SyncHandle (); | | 174 | SyncHandle (); |
185 | return 0; | | 175 | return 0; |
186 | } | | 176 | } |
187 | | | 177 | |
188 | if(rep.num_types) { | | 178 | if(rep.num_types) { |
189 | if (rep.num_types < (INT_MAX / sizeof(XResType))) | | 179 | if (rep.num_types < (INT_MAX / sizeof(XResType))) |
190 | typs = Xmalloc(sizeof(XResType) * rep.num_types); | | 180 | typs = Xmalloc(sizeof(XResType) * rep.num_types); |
191 | else | | 181 | else |
192 | typs = NULL; | | 182 | typs = NULL; |
193 | | | 183 | |
194 | if (typs != NULL) { | | 184 | if (typs != NULL) { |
195 | xXResType scratch; | | 185 | xXResType scratch; |
196 | int i; | | 186 | int i; |
197 | | | 187 | |
198 | for(i = 0; i < rep.num_types; i++) { | | 188 | for(i = 0; i < rep.num_types; i++) { |
199 | _XRead(dpy, (char*)&scratch, sz_xXResType); | | 189 | _XRead(dpy, (char*)&scratch, sz_xXResType); |
200 | typs[i].resource_type = scratch.resource_type; | | 190 | typs[i].resource_type = scratch.resource_type; |
201 | typs[i].count = scratch.count; | | 191 | typs[i].count = scratch.count; |
202 | } | | 192 | } |
203 | *types = typs; | | 193 | *types = typs; |
204 | *num_types = rep.num_types; | | 194 | *num_types = rep.num_types; |
205 | result = 1; | | 195 | result = 1; |
206 | } else { | | 196 | } else { |
207 | _XEatDataWords(dpy, rep.length); | | 197 | _XEatDataWords(dpy, rep.length); |
208 | } | | 198 | } |
209 | } | | 199 | } |
210 | | | 200 | |
211 | UnlockDisplay (dpy); | | 201 | UnlockDisplay (dpy); |
212 | SyncHandle (); | | 202 | SyncHandle (); |
213 | return result; | | 203 | return result; |
214 | } | | 204 | } |
215 | | | 205 | |
216 | Status XResQueryClientPixmapBytes ( | | 206 | Status XResQueryClientPixmapBytes ( |
217 | Display *dpy, | | 207 | Display *dpy, |
218 | XID xid, | | 208 | XID xid, |
219 | unsigned long *bytes | | 209 | unsigned long *bytes |
220 | ) | | 210 | ) |
221 | { | | 211 | { |
222 | XExtDisplayInfo *info = find_display (dpy); | | 212 | XExtDisplayInfo *info = find_display (dpy); |
223 | xXResQueryClientPixmapBytesReq *req; | | 213 | xXResQueryClientPixmapBytesReq *req; |
224 | xXResQueryClientPixmapBytesReply rep; | | 214 | xXResQueryClientPixmapBytesReply rep; |
225 | | | 215 | |
226 | *bytes = 0; | | 216 | *bytes = 0; |
227 | | | 217 | |
228 | XResCheckExtension (dpy, info, 0); | | 218 | XResCheckExtension (dpy, info, 0); |
229 | | | 219 | |
230 | LockDisplay (dpy); | | 220 | LockDisplay (dpy); |
231 | GetReq (XResQueryClientPixmapBytes, req); | | 221 | GetReq (XResQueryClientPixmapBytes, req); |
232 | req->reqType = info->codes->major_opcode; | | 222 | req->reqType = info->codes->major_opcode; |
233 | req->XResReqType = X_XResQueryClientPixmapBytes; | | 223 | req->XResReqType = X_XResQueryClientPixmapBytes; |
234 | req->xid = xid; | | 224 | req->xid = xid; |
235 | if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { | | 225 | if (!_XReply (dpy, (xReply *) &rep, 0, xTrue)) { |
236 | UnlockDisplay (dpy); | | 226 | UnlockDisplay (dpy); |
237 | SyncHandle (); | | 227 | SyncHandle (); |
238 | return 0; | | 228 | return 0; |
239 | } | | 229 | } |
240 | | | 230 | |
241 | #ifdef LONG64 | | 231 | #ifdef LONG64 |
242 | *bytes = (rep.bytes_overflow * 4294967295) + rep.bytes; | | 232 | *bytes = (rep.bytes_overflow * 4294967296UL) + rep.bytes; |
243 | #else | | 233 | #else |
244 | *bytes = rep.bytes_overflow ? 0xffffffff : rep.bytes; | | 234 | *bytes = rep.bytes_overflow ? 0xffffffff : rep.bytes; |
245 | #endif | | 235 | #endif |
246 | | | 236 | |
247 | UnlockDisplay (dpy); | | 237 | UnlockDisplay (dpy); |
248 | SyncHandle (); | | 238 | SyncHandle (); |
249 | return 1; | | 239 | return 1; |
250 | } | | 240 | } |
251 | | | 241 | |
| | | 242 | static Bool ReadClientValues( |
| | | 243 | Display *dpy, |
| | | 244 | long num_ids, |
| | | 245 | XResClientIdValue *client_ids /* out */ |
| | | 246 | ) |
| | | 247 | { |
| | | 248 | int c; |
| | | 249 | for (c = 0; c < num_ids; ++c) { |
| | | 250 | XResClientIdValue* client = client_ids + c; |
| | | 251 | long int value; |
| | | 252 | _XRead32 (dpy, &value, 4); |
| | | 253 | client->spec.client = value; |
| | | 254 | _XRead32 (dpy, &value, 4); |
| | | 255 | client->spec.mask = value; |
| | | 256 | _XRead32 (dpy, &value, 4); |
| | | 257 | client->length = value; |
| | | 258 | client->value = malloc(client->length); |
| | | 259 | _XRead32 (dpy, client->value, client->length); |
| | | 260 | } |
| | | 261 | return True; |
| | | 262 | } |
| | | 263 | |
| | | 264 | Status XResQueryClientIds ( |
| | | 265 | Display *dpy, |
| | | 266 | long num_specs, |
| | | 267 | XResClientIdSpec *client_specs, /* in */ |
| | | 268 | long *num_ids, /* out */ |
| | | 269 | XResClientIdValue **client_ids /* out */ |
| | | 270 | ) |
| | | 271 | { |
| | | 272 | XExtDisplayInfo *info = find_display (dpy); |
| | | 273 | xXResQueryClientIdsReq *req; |
| | | 274 | xXResQueryClientIdsReply rep; |
| | | 275 | int c; |
| | | 276 | |
| | | 277 | *num_ids = 0; |
| | | 278 | |
| | | 279 | XResCheckExtension (dpy, info, 0); |
| | | 280 | LockDisplay (dpy); |
| | | 281 | GetReq (XResQueryClientIds, req); |
| | | 282 | req->reqType = info->codes->major_opcode; |
| | | 283 | req->XResReqType = X_XResQueryClientIds; |
| | | 284 | req->length += num_specs * 2; /* 2 longs per client id spec */ |
| | | 285 | req->numSpecs = num_specs; |
| | | 286 | |
| | | 287 | for (c = 0; c < num_specs; ++c) { |
| | | 288 | Data32(dpy, &client_specs[c].client, 4); |
| | | 289 | Data32(dpy, &client_specs[c].mask, 4); |
| | | 290 | } |
| | | 291 | |
| | | 292 | if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { |
| | | 293 | goto error; |
| | | 294 | } |
| | | 295 | |
| | | 296 | *client_ids = calloc(rep.numIds, sizeof(**client_ids)); |
| | | 297 | *num_ids = rep.numIds; |
| | | 298 | |
| | | 299 | if (!ReadClientValues(dpy, *num_ids, *client_ids)) { |
| | | 300 | goto error; |
| | | 301 | } |
| | | 302 | |
| | | 303 | UnlockDisplay (dpy); |
| | | 304 | SyncHandle (); |
| | | 305 | return Success; |
| | | 306 | |
| | | 307 | error: |
| | | 308 | XResClientIdsDestroy (*num_ids, *client_ids); |
| | | 309 | *client_ids = NULL; |
| | | 310 | |
| | | 311 | UnlockDisplay (dpy); |
| | | 312 | SyncHandle (); |
| | | 313 | return !Success; |
| | | 314 | } |
| | | 315 | |
| | | 316 | void XResClientIdsDestroy ( |
| | | 317 | long num_ids, |
| | | 318 | XResClientIdValue *client_ids |
| | | 319 | ) |
| | | 320 | { |
| | | 321 | int c; |
| | | 322 | for (c = 0; c < num_ids; ++c) { |
| | | 323 | free(client_ids[c].value); |
| | | 324 | } |
| | | 325 | free(client_ids); |
| | | 326 | } |
| | | 327 | |
| | | 328 | XResClientIdType XResGetClientIdType( |
| | | 329 | XResClientIdValue* value |
| | | 330 | ) |
| | | 331 | { |
| | | 332 | int bit; |
| | | 333 | XResClientIdType idType = 0; |
| | | 334 | Bool found = False; |
| | | 335 | for (bit = 0; bit < XRES_CLIENT_ID_NR; ++bit) { |
| | | 336 | if (value->spec.mask & (1 << bit)) { |
| | | 337 | assert(!found); |
| | | 338 | found = True; |
| | | 339 | idType = bit; |
| | | 340 | } |
| | | 341 | } |
| | | 342 | |
| | | 343 | assert(found); |
| | | 344 | |
| | | 345 | return idType; |
| | | 346 | } |
| | | 347 | |
| | | 348 | pid_t XResGetClientPid( |
| | | 349 | XResClientIdValue* value |
| | | 350 | ) |
| | | 351 | { |
| | | 352 | if (value->spec.mask & XRES_CLIENT_ID_PID_MASK && value->length >= 4) { |
| | | 353 | return (pid_t) * (CARD32*) value->value; |
| | | 354 | } else { |
| | | 355 | return (pid_t) -1; |
| | | 356 | } |
| | | 357 | } |
| | | 358 | |
| | | 359 | static Status ReadResourceSizeSpec( |
| | | 360 | Display *dpy, |
| | | 361 | XResResourceSizeSpec *size |
| | | 362 | ) |
| | | 363 | { |
| | | 364 | long int value; |
| | | 365 | _XRead32(dpy, &value, 4); |
| | | 366 | size->spec.resource = value; |
| | | 367 | _XRead32(dpy, &value, 4); |
| | | 368 | size->spec.type = value; |
| | | 369 | _XRead32(dpy, &value, 4); |
| | | 370 | size->bytes = value; |
| | | 371 | _XRead32(dpy, &value, 4); |
| | | 372 | size->ref_count = value; |
| | | 373 | _XRead32(dpy, &value, 4); |
| | | 374 | size->use_count = value; |
| | | 375 | return 0; |
| | | 376 | } |
| | | 377 | |
| | | 378 | static Status ReadResourceSizeValues( |
| | | 379 | Display *dpy, |
| | | 380 | long num_sizes, |
| | | 381 | XResResourceSizeValue *sizes) |
| | | 382 | { |
| | | 383 | int c; |
| | | 384 | int d; |
| | | 385 | for (c = 0; c < num_sizes; ++c) { |
| | | 386 | long int num; |
| | | 387 | ReadResourceSizeSpec(dpy, &sizes[c].size); |
| | | 388 | _XRead32(dpy, &num, 4); |
| | | 389 | sizes[c].num_cross_references = num; |
| | | 390 | sizes[c].cross_references = num ? calloc(num, sizeof(*sizes[c].cross_references)) : NULL; |
| | | 391 | for (d = 0; d < num; ++d) { |
| | | 392 | ReadResourceSizeSpec(dpy, &sizes[c].cross_references[d]); |
| | | 393 | } |
| | | 394 | } |
| | | 395 | return Success; |
| | | 396 | } |
| | | 397 | |
| | | 398 | Status XResQueryResourceBytes ( |
| | | 399 | Display *dpy, |
| | | 400 | XID client, |
| | | 401 | long num_specs, |
| | | 402 | XResResourceIdSpec *resource_specs, /* in */ |
| | | 403 | long *num_sizes, /* out */ |
| | | 404 | XResResourceSizeValue **sizes /* out */ |
| | | 405 | ) |
| | | 406 | { |
| | | 407 | XExtDisplayInfo *info = find_display (dpy); |
| | | 408 | xXResQueryResourceBytesReq *req; |
| | | 409 | xXResQueryResourceBytesReply rep; |
| | | 410 | int c; |
| | | 411 | |
| | | 412 | *num_sizes = 0; |
| | | 413 | |
| | | 414 | XResCheckExtension (dpy, info, 0); |
| | | 415 | |
| | | 416 | LockDisplay (dpy); |
| | | 417 | GetReq (XResQueryResourceBytes, req); |
| | | 418 | req->reqType = info->codes->major_opcode; |
| | | 419 | req->XResReqType = X_XResQueryResourceBytes; |
| | | 420 | req->length += num_specs * 2; /* 2 longs per client id spec */ |
| | | 421 | req->client = client; |
| | | 422 | req->numSpecs = num_specs; |
| | | 423 | |
| | | 424 | for (c = 0; c < num_specs; ++c) { |
| | | 425 | Data32(dpy, &resource_specs[c].resource, 4); |
| | | 426 | Data32(dpy, &resource_specs[c].type, 4); |
| | | 427 | } |
| | | 428 | |
| | | 429 | *num_sizes = 0; |
| | | 430 | *sizes = NULL; |
| | | 431 | |
| | | 432 | if (!_XReply (dpy, (xReply *) &rep, 0, xFalse)) { |
| | | 433 | goto error; |
| | | 434 | } |
| | | 435 | |
| | | 436 | *sizes = calloc(rep.numSizes, sizeof(**sizes)); |
| | | 437 | *num_sizes = rep.numSizes; |
| | | 438 | |
| | | 439 | if (ReadResourceSizeValues(dpy, *num_sizes, *sizes) != Success) { |
| | | 440 | goto error; |
| | | 441 | } |
| | | 442 | |
| | | 443 | UnlockDisplay (dpy); |
| | | 444 | SyncHandle (); |
| | | 445 | return Success; |
| | | 446 | |
| | | 447 | error: |
| | | 448 | XResResourceSizeValuesDestroy(*num_sizes, *sizes); |
| | | 449 | |
| | | 450 | UnlockDisplay (dpy); |
| | | 451 | SyncHandle (); |
| | | 452 | return !Success; |
| | | 453 | } |
| | | 454 | |
| | | 455 | void XResResourceSizeValuesDestroy ( |
| | | 456 | long num_sizes, |
| | | 457 | XResResourceSizeValue *sizes |
| | | 458 | ) |
| | | 459 | { |
| | | 460 | int c; |
| | | 461 | for (c = 0; c < num_sizes; ++c) { |
| | | 462 | free(sizes[c].cross_references); |
| | | 463 | } |
| | | 464 | free(sizes); |
| | | 465 | } |