1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | #include "xcursorint.h" |
24 | #include <stdlib.h> |
25 | #include <string.h> |
26 | |
27 | XcursorImage * |
28 | XcursorImageCreate (int width, int height) |
29 | { |
30 | XcursorImage *image; |
31 | |
32 | image = malloc (sizeof (XcursorImage) + |
33 | width * height * sizeof (XcursorPixel)); |
34 | if (!image) |
35 | return NULL((void*)0); |
36 | image->version = XCURSOR_IMAGE_VERSION1; |
37 | image->pixels = (XcursorPixel *) (image + 1); |
38 | image->size = width > height ? width : height; |
39 | image->width = width; |
40 | image->height = height; |
41 | image->delay = 0; |
42 | return image; |
43 | } |
44 | |
45 | void |
46 | XcursorImageDestroy (XcursorImage *image) |
47 | { |
48 | free (image); |
49 | } |
50 | |
51 | XcursorImages * |
52 | XcursorImagesCreate (int size) |
53 | { |
54 | XcursorImages *images; |
55 | |
56 | images = malloc (sizeof (XcursorImages) + |
57 | size * sizeof (XcursorImage *)); |
58 | if (!images) |
59 | return NULL((void*)0); |
60 | images->nimage = 0; |
61 | images->images = (XcursorImage **) (images + 1); |
62 | images->name = NULL((void*)0); |
63 | return images; |
64 | } |
65 | |
66 | void |
67 | XcursorImagesDestroy (XcursorImages *images) |
68 | { |
69 | int n; |
70 | |
71 | if (!images) |
72 | return; |
73 | |
74 | for (n = 0; n < images->nimage; n++) |
75 | XcursorImageDestroy (images->images[n]); |
76 | if (images->name) |
77 | free (images->name); |
78 | free (images); |
79 | } |
80 | |
81 | void |
82 | XcursorImagesSetName (XcursorImages *images, const char *name) |
83 | { |
84 | char *new; |
85 | |
86 | if (!images || !name) |
87 | return; |
88 | |
89 | new = strdup (name); |
90 | |
91 | if (!new) |
92 | return; |
93 | |
94 | if (images->name) |
95 | free (images->name); |
96 | images->name = new; |
97 | } |
98 | |
99 | XcursorComment * |
100 | XcursorCommentCreate (XcursorUInt comment_type, int length) |
101 | { |
102 | XcursorComment *comment; |
103 | |
104 | if (length > XCURSOR_COMMENT_MAX_LEN0x100000) |
105 | return NULL((void*)0); |
106 | |
107 | comment = malloc (sizeof (XcursorComment) + length + 1); |
108 | if (!comment) |
109 | return NULL((void*)0); |
110 | comment->version = XCURSOR_COMMENT_VERSION1; |
111 | comment->comment_type = comment_type; |
112 | comment->comment = (char *) (comment + 1); |
113 | comment->comment[0] = '\0'; |
114 | return comment; |
115 | } |
116 | |
117 | void |
118 | XcursorCommentDestroy (XcursorComment *comment) |
119 | { |
120 | free (comment); |
121 | } |
122 | |
123 | XcursorComments * |
124 | XcursorCommentsCreate (int size) |
125 | { |
126 | XcursorComments *comments; |
127 | |
128 | comments = malloc (sizeof (XcursorComments) + |
129 | size * sizeof (XcursorComment *)); |
130 | if (!comments) |
131 | return NULL((void*)0); |
132 | comments->ncomment = 0; |
133 | comments->comments = (XcursorComment **) (comments + 1); |
134 | return comments; |
135 | } |
136 | |
137 | void |
138 | XcursorCommentsDestroy (XcursorComments *comments) |
139 | { |
140 | int n; |
141 | |
142 | if (!comments) |
143 | return; |
144 | |
145 | for (n = 0; n < comments->ncomment; n++) |
146 | XcursorCommentDestroy (comments->comments[n]); |
147 | free (comments); |
148 | } |
149 | |
150 | static XcursorBool |
151 | _XcursorReadUInt (XcursorFile *file, XcursorUInt *u) |
152 | { |
153 | unsigned char bytes[4]; |
154 | |
155 | if (!file || !u) |
156 | return XcursorFalse0; |
157 | |
158 | if ((*file->read) (file, bytes, 4) != 4) |
159 | return XcursorFalse0; |
160 | *u = ((bytes[0] << 0) | |
161 | (bytes[1] << 8) | |
162 | (bytes[2] << 16) | |
163 | (bytes[3] << 24)); |
164 | return XcursorTrue1; |
165 | } |
166 | |
167 | static XcursorBool |
168 | _XcursorReadBytes (XcursorFile *file, char *bytes, int length) |
169 | { |
170 | if (!file || !bytes || (*file->read) (file, (unsigned char *) bytes, length) != length) |
171 | return XcursorFalse0; |
172 | return XcursorTrue1; |
173 | } |
174 | |
175 | static XcursorBool |
176 | _XcursorWriteUInt (XcursorFile *file, XcursorUInt u) |
177 | { |
178 | unsigned char bytes[4]; |
179 | |
180 | if (!file) |
| |
| |
| |
| |
181 | return XcursorFalse0; |
182 | |
183 | bytes[0] = u; |
184 | bytes[1] = u >> 8; |
185 | bytes[2] = u >> 16; |
186 | bytes[3] = u >> 24; |
187 | if ((*file->write) (file, bytes, 4) != 4) |
| 27 | | Calling '_XcursorStdioFileWrite' | |
|
| 28 | | Returning from '_XcursorStdioFileWrite' | |
|
| |
| 34 | | Calling '_XcursorStdioFileWrite' | |
|
| 35 | | Returning from '_XcursorStdioFileWrite' | |
|
| |
| 41 | | Calling '_XcursorStdioFileWrite' | |
|
| 42 | | Returning from '_XcursorStdioFileWrite' | |
|
| |
| 48 | | Calling '_XcursorStdioFileWrite' | |
|
| 49 | | Returning from '_XcursorStdioFileWrite' | |
|
| |
188 | return XcursorFalse0; |
189 | return XcursorTrue1; |
190 | } |
191 | |
192 | static XcursorBool |
193 | _XcursorWriteBytes (XcursorFile *file, char *bytes, int length) |
194 | { |
195 | if (!file || !bytes || (*file->write) (file, (unsigned char *) bytes, length) != length) |
196 | return XcursorFalse0; |
197 | return XcursorTrue1; |
198 | } |
199 | |
200 | static void |
201 | _XcursorFileHeaderDestroy (XcursorFileHeader *fileHeader) |
202 | { |
203 | free (fileHeader); |
204 | } |
205 | |
206 | static XcursorFileHeader * |
207 | _XcursorFileHeaderCreate (XcursorUInt ntoc) |
208 | { |
209 | XcursorFileHeader *fileHeader; |
210 | |
211 | if (ntoc > 0x10000) |
| 12 | | Assuming 'ntoc' is <= 65536 | |
|
| |
212 | return NULL((void*)0); |
213 | fileHeader = malloc (sizeof (XcursorFileHeader) + |
| 14 | | Uninitialized value stored to field 'type' | |
|
214 | ntoc * sizeof (XcursorFileToc)); |
215 | if (!fileHeader) |
| 15 | | Assuming 'fileHeader' is non-null | |
|
| |
216 | return NULL((void*)0); |
217 | fileHeader->magic = XCURSOR_MAGIC0x72756358; |
218 | fileHeader->header = XCURSOR_FILE_HEADER_LEN(4 * 4); |
219 | fileHeader->version = XCURSOR_FILE_VERSION((1 << 16) | (0)); |
220 | fileHeader->ntoc = ntoc; |
221 | fileHeader->tocs = (XcursorFileToc *) (fileHeader + 1); |
222 | return fileHeader; |
223 | } |
224 | |
225 | static XcursorFileHeader * |
226 | _XcursorReadFileHeader (XcursorFile *file) |
227 | { |
228 | XcursorFileHeader head, *fileHeader; |
229 | XcursorUInt skip; |
230 | int n; |
231 | |
232 | if (!file) |
233 | return NULL((void*)0); |
234 | |
235 | if (!_XcursorReadUInt (file, &head.magic)) |
236 | return NULL((void*)0); |
237 | if (head.magic != XCURSOR_MAGIC0x72756358) |
238 | return NULL((void*)0); |
239 | if (!_XcursorReadUInt (file, &head.header)) |
240 | return NULL((void*)0); |
241 | if (!_XcursorReadUInt (file, &head.version)) |
242 | return NULL((void*)0); |
243 | if (!_XcursorReadUInt (file, &head.ntoc)) |
244 | return NULL((void*)0); |
245 | skip = head.header - XCURSOR_FILE_HEADER_LEN(4 * 4); |
246 | if (skip) |
247 | if ((*file->seek) (file, skip, SEEK_CUR1) == EOF(-1)) |
248 | return NULL((void*)0); |
249 | fileHeader = _XcursorFileHeaderCreate (head.ntoc); |
250 | if (!fileHeader) |
251 | return NULL((void*)0); |
252 | fileHeader->magic = head.magic; |
253 | fileHeader->header = head.header; |
254 | fileHeader->version = head.version; |
255 | fileHeader->ntoc = head.ntoc; |
256 | for (n = 0; n < fileHeader->ntoc; n++) |
257 | { |
258 | if (!_XcursorReadUInt (file, &fileHeader->tocs[n].type)) |
259 | break; |
260 | if (!_XcursorReadUInt (file, &fileHeader->tocs[n].subtype)) |
261 | break; |
262 | if (!_XcursorReadUInt (file, &fileHeader->tocs[n].position)) |
263 | break; |
264 | } |
265 | if (n != fileHeader->ntoc) |
266 | { |
267 | _XcursorFileHeaderDestroy (fileHeader); |
268 | return NULL((void*)0); |
269 | } |
270 | return fileHeader; |
271 | } |
272 | |
273 | static XcursorUInt |
274 | _XcursorFileHeaderLength (XcursorFileHeader *fileHeader) |
275 | { |
276 | return (XCURSOR_FILE_HEADER_LEN(4 * 4) + |
277 | fileHeader->ntoc * XCURSOR_FILE_TOC_LEN(3 * 4)); |
278 | } |
279 | |
280 | static XcursorBool |
281 | _XcursorWriteFileHeader (XcursorFile *file, XcursorFileHeader *fileHeader) |
282 | { |
283 | int toc; |
284 | |
285 | if (!file || !fileHeader) |
| |
286 | return XcursorFalse0; |
287 | |
288 | if (!_XcursorWriteUInt (file, fileHeader->magic)) |
| 25 | | Calling '_XcursorWriteUInt' | |
|
| 30 | | Returning from '_XcursorWriteUInt' | |
|
| |
289 | return XcursorFalse0; |
290 | if (!_XcursorWriteUInt (file, fileHeader->header)) |
| 32 | | Calling '_XcursorWriteUInt' | |
|
| 37 | | Returning from '_XcursorWriteUInt' | |
|
| |
291 | return XcursorFalse0; |
292 | if (!_XcursorWriteUInt (file, fileHeader->version)) |
| 39 | | Calling '_XcursorWriteUInt' | |
|
| 44 | | Returning from '_XcursorWriteUInt' | |
|
| |
293 | return XcursorFalse0; |
294 | if (!_XcursorWriteUInt (file, fileHeader->ntoc)) |
| 46 | | Calling '_XcursorWriteUInt' | |
|
| 51 | | Returning from '_XcursorWriteUInt' | |
|
| |
295 | return XcursorFalse0; |
296 | for (toc = 0; toc < fileHeader->ntoc; toc++) |
| 53 | | Loop condition is true. Entering loop body | |
|
297 | { |
298 | if (!_XcursorWriteUInt (file, fileHeader->tocs[toc].type)) |
| 54 | | Function call argument is an uninitialized value |
|
299 | return XcursorFalse0; |
300 | if (!_XcursorWriteUInt (file, fileHeader->tocs[toc].subtype)) |
301 | return XcursorFalse0; |
302 | if (!_XcursorWriteUInt (file, fileHeader->tocs[toc].position)) |
303 | return XcursorFalse0; |
304 | } |
305 | return XcursorTrue1; |
306 | } |
307 | |
308 | static XcursorBool |
309 | _XcursorSeekToToc (XcursorFile *file, |
310 | XcursorFileHeader *fileHeader, |
311 | int toc) |
312 | { |
313 | if (!file || !fileHeader || \ |
314 | (*file->seek) (file, fileHeader->tocs[toc].position, SEEK_SET0) == EOF(-1)) |
315 | return XcursorFalse0; |
316 | return XcursorTrue1; |
317 | } |
318 | |
319 | static XcursorBool |
320 | _XcursorFileReadChunkHeader (XcursorFile *file, |
321 | XcursorFileHeader *fileHeader, |
322 | int toc, |
323 | XcursorChunkHeader *chunkHeader) |
324 | { |
325 | if (!file || !fileHeader || !chunkHeader) |
326 | return XcursorFalse0; |
327 | if (!_XcursorSeekToToc (file, fileHeader, toc)) |
328 | return XcursorFalse0; |
329 | if (!_XcursorReadUInt (file, &chunkHeader->header)) |
330 | return XcursorFalse0; |
331 | if (!_XcursorReadUInt (file, &chunkHeader->type)) |
332 | return XcursorFalse0; |
333 | if (!_XcursorReadUInt (file, &chunkHeader->subtype)) |
334 | return XcursorFalse0; |
335 | if (!_XcursorReadUInt (file, &chunkHeader->version)) |
336 | return XcursorFalse0; |
337 | |
338 | if (chunkHeader->type != fileHeader->tocs[toc].type || |
339 | chunkHeader->subtype != fileHeader->tocs[toc].subtype) |
340 | return XcursorFalse0; |
341 | return XcursorTrue1; |
342 | } |
343 | |
344 | static XcursorBool |
345 | _XcursorFileWriteChunkHeader (XcursorFile *file, |
346 | XcursorFileHeader *fileHeader, |
347 | int toc, |
348 | XcursorChunkHeader *chunkHeader) |
349 | { |
350 | if (!file || !fileHeader || !chunkHeader) |
351 | return XcursorFalse0; |
352 | if (!_XcursorSeekToToc (file, fileHeader, toc)) |
353 | return XcursorFalse0; |
354 | if (!_XcursorWriteUInt (file, chunkHeader->header)) |
355 | return XcursorFalse0; |
356 | if (!_XcursorWriteUInt (file, chunkHeader->type)) |
357 | return XcursorFalse0; |
358 | if (!_XcursorWriteUInt (file, chunkHeader->subtype)) |
359 | return XcursorFalse0; |
360 | if (!_XcursorWriteUInt (file, chunkHeader->version)) |
361 | return XcursorFalse0; |
362 | return XcursorTrue1; |
363 | } |
364 | |
365 | #define dist(a,b)((a) > (b) ? (a) - (b) : (b) - (a)) ((a) > (b) ? (a) - (b) : (b) - (a)) |
366 | |
367 | static XcursorDim |
368 | _XcursorFindBestSize (XcursorFileHeader *fileHeader, |
369 | XcursorDim size, |
370 | int *nsizesp) |
371 | { |
372 | int n; |
373 | int nsizes = 0; |
374 | XcursorDim bestSize = 0; |
375 | XcursorDim thisSize; |
376 | |
377 | if (!fileHeader || !nsizesp) |
378 | return 0; |
379 | |
380 | for (n = 0; n < fileHeader->ntoc; n++) |
381 | { |
382 | if (fileHeader->tocs[n].type != XCURSOR_IMAGE_TYPE0xfffd0002) |
383 | continue; |
384 | thisSize = fileHeader->tocs[n].subtype; |
385 | if (!bestSize || dist (thisSize, size)((thisSize) > (size) ? (thisSize) - (size) : (size) - (thisSize )) < dist (bestSize, size)((bestSize) > (size) ? (bestSize) - (size) : (size) - (bestSize ))) |
386 | { |
387 | bestSize = thisSize; |
388 | nsizes = 1; |
389 | } |
390 | else if (thisSize == bestSize) |
391 | nsizes++; |
392 | } |
393 | *nsizesp = nsizes; |
394 | return bestSize; |
395 | } |
396 | |
397 | static int |
398 | _XcursorFindImageToc (XcursorFileHeader *fileHeader, |
399 | XcursorDim size, |
400 | int count) |
401 | { |
402 | int toc; |
403 | XcursorDim thisSize; |
404 | |
405 | if (!fileHeader) |
406 | return 0; |
407 | |
408 | for (toc = 0; toc < fileHeader->ntoc; toc++) |
409 | { |
410 | if (fileHeader->tocs[toc].type != XCURSOR_IMAGE_TYPE0xfffd0002) |
411 | continue; |
412 | thisSize = fileHeader->tocs[toc].subtype; |
413 | if (thisSize != size) |
414 | continue; |
415 | if (!count) |
416 | break; |
417 | count--; |
418 | } |
419 | if (toc == fileHeader->ntoc) |
420 | return -1; |
421 | return toc; |
422 | } |
423 | |
424 | static XcursorImage * |
425 | _XcursorReadImage (XcursorFile *file, |
426 | XcursorFileHeader *fileHeader, |
427 | int toc) |
428 | { |
429 | XcursorChunkHeader chunkHeader; |
430 | XcursorImage head; |
431 | XcursorImage *image; |
432 | int n; |
433 | XcursorPixel *p; |
434 | |
435 | if (!file || !fileHeader) |
436 | return NULL((void*)0); |
437 | |
438 | if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader)) |
439 | return NULL((void*)0); |
440 | if (!_XcursorReadUInt (file, &head.width)) |
441 | return NULL((void*)0); |
442 | if (!_XcursorReadUInt (file, &head.height)) |
443 | return NULL((void*)0); |
444 | if (!_XcursorReadUInt (file, &head.xhot)) |
445 | return NULL((void*)0); |
446 | if (!_XcursorReadUInt (file, &head.yhot)) |
447 | return NULL((void*)0); |
448 | if (!_XcursorReadUInt (file, &head.delay)) |
449 | return NULL((void*)0); |
450 | |
451 | if (head.width >= 0x10000 || head.height > 0x10000) |
452 | return NULL((void*)0); |
453 | if (head.width == 0 || head.height == 0) |
454 | return NULL((void*)0); |
455 | if (head.xhot > head.width || head.yhot > head.height) |
456 | return NULL((void*)0); |
457 | |
458 | |
459 | image = XcursorImageCreate (head.width, head.height); |
460 | if (chunkHeader.version < image->version) |
461 | image->version = chunkHeader.version; |
462 | image->size = chunkHeader.subtype; |
463 | image->xhot = head.xhot; |
464 | image->yhot = head.yhot; |
465 | image->delay = head.delay; |
466 | n = image->width * image->height; |
467 | p = image->pixels; |
468 | while (n--) |
469 | { |
470 | if (!_XcursorReadUInt (file, p)) |
471 | { |
472 | XcursorImageDestroy (image); |
473 | return NULL((void*)0); |
474 | } |
475 | p++; |
476 | } |
477 | return image; |
478 | } |
479 | |
480 | static XcursorUInt |
481 | _XcursorImageLength (XcursorImage *image) |
482 | { |
483 | if (!image) |
484 | return 0; |
485 | |
486 | return XCURSOR_IMAGE_HEADER_LEN((4 * 4) + (5*4)) + (image->width * image->height) * 4; |
487 | } |
488 | |
489 | static XcursorBool |
490 | _XcursorWriteImage (XcursorFile *file, |
491 | XcursorFileHeader *fileHeader, |
492 | int toc, |
493 | XcursorImage *image) |
494 | { |
495 | XcursorChunkHeader chunkHeader; |
496 | int n; |
497 | XcursorPixel *p; |
498 | |
499 | if (!file || !fileHeader || !image) |
500 | return XcursorFalse0; |
501 | |
502 | |
503 | if (image->width > XCURSOR_IMAGE_MAX_SIZE0x7fff || |
504 | image->height > XCURSOR_IMAGE_MAX_SIZE0x7fff) |
505 | return XcursorFalse0; |
506 | if (image->width == 0 || image->height == 0) |
507 | return XcursorFalse0; |
508 | if (image->xhot > image->width || image->yhot > image->height) |
509 | return XcursorFalse0; |
510 | |
511 | |
512 | chunkHeader.header = XCURSOR_IMAGE_HEADER_LEN((4 * 4) + (5*4)); |
513 | chunkHeader.type = XCURSOR_IMAGE_TYPE0xfffd0002; |
514 | chunkHeader.subtype = image->size; |
515 | chunkHeader.version = XCURSOR_IMAGE_VERSION1; |
516 | |
517 | if (!_XcursorFileWriteChunkHeader (file, fileHeader, toc, &chunkHeader)) |
518 | return XcursorFalse0; |
519 | |
520 | |
521 | if (!_XcursorWriteUInt (file, image->width)) |
522 | return XcursorFalse0; |
523 | if (!_XcursorWriteUInt (file, image->height)) |
524 | return XcursorFalse0; |
525 | if (!_XcursorWriteUInt (file, image->xhot)) |
526 | return XcursorFalse0; |
527 | if (!_XcursorWriteUInt (file, image->yhot)) |
528 | return XcursorFalse0; |
529 | if (!_XcursorWriteUInt (file, image->delay)) |
530 | return XcursorFalse0; |
531 | |
532 | |
533 | n = image->width * image->height; |
534 | p = image->pixels; |
535 | while (n--) |
536 | { |
537 | if (!_XcursorWriteUInt (file, *p)) |
538 | return XcursorFalse0; |
539 | p++; |
540 | } |
541 | return XcursorTrue1; |
542 | } |
543 | |
544 | static XcursorComment * |
545 | _XcursorReadComment (XcursorFile *file, |
546 | XcursorFileHeader *fileHeader, |
547 | int toc) |
548 | { |
549 | XcursorChunkHeader chunkHeader; |
550 | XcursorUInt length; |
551 | XcursorComment *comment; |
552 | |
553 | if (!file || !fileHeader) |
554 | return NULL((void*)0); |
555 | |
556 | |
557 | if (!_XcursorFileReadChunkHeader (file, fileHeader, toc, &chunkHeader)) |
558 | return NULL((void*)0); |
559 | |
560 | if (!_XcursorReadUInt (file, &length)) |
561 | return NULL((void*)0); |
562 | comment = XcursorCommentCreate (chunkHeader.subtype, length); |
563 | if (!comment) |
564 | return NULL((void*)0); |
565 | if (!_XcursorReadBytes (file, comment->comment, length)) |
566 | { |
567 | XcursorCommentDestroy (comment); |
568 | return NULL((void*)0); |
569 | } |
570 | comment->comment[length] = '\0'; |
571 | return comment; |
572 | } |
573 | |
574 | static XcursorUInt |
575 | _XcursorCommentLength (XcursorComment *comment) |
576 | { |
577 | return XCURSOR_COMMENT_HEADER_LEN((4 * 4) + (1 *4)) + strlen (comment->comment); |
578 | } |
579 | |
580 | static XcursorBool |
581 | _XcursorWriteComment (XcursorFile *file, |
582 | XcursorFileHeader *fileHeader, |
583 | int toc, |
584 | XcursorComment *comment) |
585 | { |
586 | XcursorChunkHeader chunkHeader; |
587 | XcursorUInt length; |
588 | |
589 | if (!file || !fileHeader || !comment || !comment->comment) |
590 | return XcursorFalse0; |
591 | |
592 | length = strlen (comment->comment); |
593 | |
594 | |
595 | if (length > XCURSOR_COMMENT_MAX_LEN0x100000) |
596 | return XcursorFalse0; |
597 | |
598 | |
599 | chunkHeader.header = XCURSOR_COMMENT_HEADER_LEN((4 * 4) + (1 *4)); |
600 | chunkHeader.type = XCURSOR_COMMENT_TYPE0xfffe0001; |
601 | chunkHeader.subtype = comment->comment_type; |
602 | chunkHeader.version = XCURSOR_COMMENT_VERSION1; |
603 | |
604 | if (!_XcursorFileWriteChunkHeader (file, fileHeader, toc, &chunkHeader)) |
605 | return XcursorFalse0; |
606 | |
607 | |
608 | if (!_XcursorWriteUInt (file, length)) |
609 | return XcursorFalse0; |
610 | |
611 | if (!_XcursorWriteBytes (file, comment->comment, length)) |
612 | return XcursorFalse0; |
613 | return XcursorTrue1; |
614 | } |
615 | |
616 | XcursorImage * |
617 | XcursorXcFileLoadImage (XcursorFile *file, int size) |
618 | { |
619 | XcursorFileHeader *fileHeader; |
620 | XcursorDim bestSize; |
621 | int nsize; |
622 | int toc; |
623 | XcursorImage *image; |
624 | |
625 | if (size < 0) |
626 | return NULL((void*)0); |
627 | fileHeader = _XcursorReadFileHeader (file); |
628 | if (!fileHeader) |
629 | return NULL((void*)0); |
630 | bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize); |
631 | if (!bestSize) |
632 | return NULL((void*)0); |
633 | toc = _XcursorFindImageToc (fileHeader, bestSize, 0); |
634 | if (toc < 0) |
635 | return NULL((void*)0); |
636 | image = _XcursorReadImage (file, fileHeader, toc); |
637 | _XcursorFileHeaderDestroy (fileHeader); |
638 | return image; |
639 | } |
640 | |
641 | XcursorImages * |
642 | XcursorXcFileLoadImages (XcursorFile *file, int size) |
643 | { |
644 | XcursorFileHeader *fileHeader; |
645 | XcursorDim bestSize; |
646 | int nsize; |
647 | XcursorImages *images; |
648 | int n; |
649 | int toc; |
650 | |
651 | if (!file || size < 0) |
652 | return NULL((void*)0); |
653 | fileHeader = _XcursorReadFileHeader (file); |
654 | if (!fileHeader) |
655 | return NULL((void*)0); |
656 | bestSize = _XcursorFindBestSize (fileHeader, (XcursorDim) size, &nsize); |
657 | if (!bestSize) |
658 | { |
659 | _XcursorFileHeaderDestroy (fileHeader); |
660 | return NULL((void*)0); |
661 | } |
662 | images = XcursorImagesCreate (nsize); |
663 | if (!images) |
664 | { |
665 | _XcursorFileHeaderDestroy (fileHeader); |
666 | return NULL((void*)0); |
667 | } |
668 | for (n = 0; n < nsize; n++) |
669 | { |
670 | toc = _XcursorFindImageToc (fileHeader, bestSize, n); |
671 | if (toc < 0) |
672 | break; |
673 | images->images[images->nimage] = _XcursorReadImage (file, fileHeader, |
674 | toc); |
675 | if (!images->images[images->nimage]) |
676 | break; |
677 | images->nimage++; |
678 | } |
679 | _XcursorFileHeaderDestroy (fileHeader); |
680 | if (images->nimage != nsize) |
681 | { |
682 | XcursorImagesDestroy (images); |
683 | images = NULL((void*)0); |
684 | } |
685 | return images; |
686 | } |
687 | |
688 | XcursorImages * |
689 | XcursorXcFileLoadAllImages (XcursorFile *file) |
690 | { |
691 | XcursorFileHeader *fileHeader; |
692 | XcursorImage *image; |
693 | XcursorImages *images; |
694 | int nimage; |
695 | int n; |
696 | int toc; |
697 | |
698 | if (!file) |
699 | return NULL((void*)0); |
700 | |
701 | fileHeader = _XcursorReadFileHeader (file); |
702 | if (!fileHeader) |
703 | return NULL((void*)0); |
704 | nimage = 0; |
705 | for (n = 0; n < fileHeader->ntoc; n++) |
706 | { |
707 | switch (fileHeader->tocs[n].type) { |
708 | case XCURSOR_IMAGE_TYPE0xfffd0002: |
709 | nimage++; |
710 | break; |
711 | } |
712 | } |
713 | images = XcursorImagesCreate (nimage); |
714 | if (!images) |
715 | { |
716 | _XcursorFileHeaderDestroy (fileHeader); |
717 | return NULL((void*)0); |
718 | } |
719 | for (toc = 0; toc < fileHeader->ntoc; toc++) |
720 | { |
721 | switch (fileHeader->tocs[toc].type) { |
722 | case XCURSOR_IMAGE_TYPE0xfffd0002: |
723 | image = _XcursorReadImage (file, fileHeader, toc); |
724 | if (image) |
725 | { |
726 | images->images[images->nimage] = image; |
727 | images->nimage++; |
728 | } |
729 | break; |
730 | } |
731 | } |
732 | _XcursorFileHeaderDestroy (fileHeader); |
733 | if (images->nimage != nimage) |
734 | { |
735 | XcursorImagesDestroy (images); |
736 | images = NULL((void*)0); |
737 | } |
738 | return images; |
739 | } |
740 | |
741 | XcursorBool |
742 | XcursorXcFileLoad (XcursorFile *file, |
743 | XcursorComments **commentsp, |
744 | XcursorImages **imagesp) |
745 | { |
746 | XcursorFileHeader *fileHeader; |
747 | int nimage; |
748 | int ncomment; |
749 | XcursorImages *images; |
750 | XcursorImage *image; |
751 | XcursorComment *comment; |
752 | XcursorComments *comments; |
753 | int toc; |
754 | |
755 | if (!file) |
756 | return 0; |
757 | fileHeader = _XcursorReadFileHeader (file); |
758 | if (!fileHeader) |
759 | return 0; |
760 | nimage = 0; |
761 | ncomment = 0; |
762 | for (toc = 0; toc < fileHeader->ntoc; toc++) |
763 | { |
764 | switch (fileHeader->tocs[toc].type) { |
765 | case XCURSOR_COMMENT_TYPE0xfffe0001: |
766 | ncomment++; |
767 | break; |
768 | case XCURSOR_IMAGE_TYPE0xfffd0002: |
769 | nimage++; |
770 | break; |
771 | } |
772 | } |
773 | images = XcursorImagesCreate (nimage); |
774 | if (!images) |
775 | return 0; |
776 | comments = XcursorCommentsCreate (ncomment); |
777 | if (!comments) |
778 | { |
779 | XcursorImagesDestroy (images); |
780 | return 0; |
781 | } |
782 | for (toc = 0; toc < fileHeader->ntoc; toc++) |
783 | { |
784 | switch (fileHeader->tocs[toc].type) { |
785 | case XCURSOR_COMMENT_TYPE0xfffe0001: |
786 | comment = _XcursorReadComment (file, fileHeader, toc); |
787 | if (comment) |
788 | { |
789 | comments->comments[comments->ncomment] = comment; |
790 | comments->ncomment++; |
791 | } |
792 | break; |
793 | case XCURSOR_IMAGE_TYPE0xfffd0002: |
794 | image = _XcursorReadImage (file, fileHeader, toc); |
795 | if (image) |
796 | { |
797 | images->images[images->nimage] = image; |
798 | images->nimage++; |
799 | } |
800 | break; |
801 | } |
802 | } |
803 | _XcursorFileHeaderDestroy (fileHeader); |
804 | if (images->nimage != nimage || comments->ncomment != ncomment) |
805 | { |
806 | XcursorImagesDestroy (images); |
807 | XcursorCommentsDestroy (comments); |
808 | images = NULL((void*)0); |
809 | comments = NULL((void*)0); |
810 | return XcursorFalse0; |
811 | } |
812 | *imagesp = images; |
813 | *commentsp = comments; |
814 | return XcursorTrue1; |
815 | } |
816 | |
817 | XcursorBool |
818 | XcursorXcFileSave (XcursorFile *file, |
819 | const XcursorComments *comments, |
820 | const XcursorImages *images) |
821 | { |
822 | XcursorFileHeader *fileHeader; |
823 | XcursorUInt position; |
824 | int n; |
825 | int toc; |
826 | |
827 | if (!file || !comments || !images) |
| |
828 | return XcursorFalse0; |
829 | |
830 | fileHeader = _XcursorFileHeaderCreate (comments->ncomment + images->nimage); |
| 11 | | Calling '_XcursorFileHeaderCreate' | |
|
| 17 | | Returning from '_XcursorFileHeaderCreate' | |
|
831 | if (!fileHeader) |
| |
832 | return XcursorFalse0; |
833 | |
834 | position = _XcursorFileHeaderLength (fileHeader); |
| 19 | | Calling '_XcursorFileHeaderLength' | |
|
| 20 | | Returning from '_XcursorFileHeaderLength' | |
|
835 | |
836 | |
837 | |
838 | |
839 | |
840 | |
841 | toc = 0; |
842 | for (n = 0; n < images->nimage; n++) |
| 21 | | Loop condition is false. Execution continues on line 851 | |
|
843 | { |
844 | fileHeader->tocs[toc].type = XCURSOR_IMAGE_TYPE0xfffd0002; |
845 | fileHeader->tocs[toc].subtype = images->images[n]->size; |
846 | fileHeader->tocs[toc].position = position; |
847 | position += _XcursorImageLength (images->images[n]); |
848 | toc++; |
849 | } |
850 | |
851 | for (n = 0; n < comments->ncomment; n++) |
| 22 | | Loop condition is false. Execution continues on line 863 | |
|
852 | { |
853 | fileHeader->tocs[toc].type = XCURSOR_COMMENT_TYPE0xfffe0001; |
854 | fileHeader->tocs[toc].subtype = comments->comments[n]->comment_type; |
855 | fileHeader->tocs[toc].position = position; |
856 | position += _XcursorCommentLength (comments->comments[n]); |
857 | toc++; |
858 | } |
859 | |
860 | |
861 | |
862 | |
863 | if (!_XcursorWriteFileHeader (file, fileHeader)) |
| 23 | | Calling '_XcursorWriteFileHeader' | |
|
864 | goto bail; |
865 | |
866 | |
867 | |
868 | |
869 | toc = 0; |
870 | for (n = 0; n < images->nimage; n++) |
871 | { |
872 | if (!_XcursorWriteImage (file, fileHeader, toc, images->images[n])) |
873 | goto bail; |
874 | toc++; |
875 | } |
876 | |
877 | |
878 | |
879 | |
880 | for (n = 0; n < comments->ncomment; n++) |
881 | { |
882 | if (!_XcursorWriteComment (file, fileHeader, toc, comments->comments[n])) |
883 | goto bail; |
884 | toc++; |
885 | } |
886 | |
887 | _XcursorFileHeaderDestroy (fileHeader); |
888 | return XcursorTrue1; |
889 | bail: |
890 | _XcursorFileHeaderDestroy (fileHeader); |
891 | return XcursorFalse0; |
892 | } |
893 | |
894 | static int |
895 | _XcursorStdioFileRead (XcursorFile *file, unsigned char *buf, int len) |
896 | { |
897 | FILE *f = file->closure; |
898 | return fread (buf, 1, len, f); |
899 | } |
900 | |
901 | static int |
902 | _XcursorStdioFileWrite (XcursorFile *file, unsigned char *buf, int len) |
903 | { |
904 | FILE *f = file->closure; |
905 | return fwrite (buf, 1, len, f); |
906 | } |
907 | |
908 | static int |
909 | _XcursorStdioFileSeek (XcursorFile *file, long offset, int whence) |
910 | { |
911 | FILE *f = file->closure; |
912 | return fseek (f, offset, whence); |
913 | } |
914 | |
915 | static void |
916 | _XcursorStdioFileInitialize (FILE *stdfile, XcursorFile *file) |
917 | { |
918 | file->closure = stdfile; |
919 | file->read = _XcursorStdioFileRead; |
920 | file->write = _XcursorStdioFileWrite; |
921 | file->seek = _XcursorStdioFileSeek; |
922 | } |
923 | |
924 | XcursorImage * |
925 | XcursorFileLoadImage (FILE *file, int size) |
926 | { |
927 | XcursorFile f; |
928 | |
929 | if (!file) |
930 | return NULL((void*)0); |
931 | |
932 | _XcursorStdioFileInitialize (file, &f); |
933 | return XcursorXcFileLoadImage (&f, size); |
934 | } |
935 | |
936 | XcursorImages * |
937 | XcursorFileLoadImages (FILE *file, int size) |
938 | { |
939 | XcursorFile f; |
940 | |
941 | if (!file) |
942 | return NULL((void*)0); |
943 | |
944 | _XcursorStdioFileInitialize (file, &f); |
945 | return XcursorXcFileLoadImages (&f, size); |
946 | } |
947 | |
948 | XcursorImages * |
949 | XcursorFileLoadAllImages (FILE *file) |
950 | { |
951 | XcursorFile f; |
952 | |
953 | if (!file) |
954 | return NULL((void*)0); |
955 | |
956 | _XcursorStdioFileInitialize (file, &f); |
957 | return XcursorXcFileLoadAllImages (&f); |
958 | } |
959 | |
960 | XcursorBool |
961 | XcursorFileLoad (FILE *file, |
962 | XcursorComments **commentsp, |
963 | XcursorImages **imagesp) |
964 | { |
965 | XcursorFile f; |
966 | |
967 | if (!file || !commentsp || !imagesp) |
968 | return XcursorFalse0; |
969 | |
970 | _XcursorStdioFileInitialize (file, &f); |
971 | return XcursorXcFileLoad (&f, commentsp, imagesp); |
972 | } |
973 | |
974 | XcursorBool |
975 | XcursorFileSaveImages (FILE *file, const XcursorImages *images) |
976 | { |
977 | XcursorComments *comments; |
978 | XcursorFile f; |
979 | XcursorBool ret; |
980 | |
981 | if (!file || !images) |
982 | return 0; |
983 | if ((comments = XcursorCommentsCreate (0)) == NULL((void*)0)) |
984 | return 0; |
985 | _XcursorStdioFileInitialize (file, &f); |
986 | ret = XcursorXcFileSave (&f, comments, images) && fflush (file) != EOF(-1); |
987 | XcursorCommentsDestroy (comments); |
988 | return ret; |
989 | } |
990 | |
991 | XcursorBool |
992 | XcursorFileSave (FILE * file, |
993 | const XcursorComments *comments, |
994 | const XcursorImages *images) |
995 | { |
996 | XcursorFile f; |
997 | |
998 | if (!file || !comments || !images) |
| |
999 | return XcursorFalse0; |
1000 | |
1001 | _XcursorStdioFileInitialize (file, &f); |
1002 | return XcursorXcFileSave (&f, comments, images) && fflush (file) != EOF(-1); |
| 9 | | Calling 'XcursorXcFileSave' | |
|
1003 | } |
1004 | |
1005 | XcursorImage * |
1006 | XcursorFilenameLoadImage (const char *file, int size) |
1007 | { |
1008 | FILE *f; |
1009 | XcursorImage *image; |
1010 | |
1011 | if (!file || size < 0) |
1012 | return NULL((void*)0); |
1013 | |
1014 | f = fopen (file, "r"); |
1015 | if (!f) |
1016 | return NULL((void*)0); |
1017 | image = XcursorFileLoadImage (f, size); |
1018 | fclose (f); |
1019 | return image; |
1020 | } |
1021 | |
1022 | XcursorImages * |
1023 | XcursorFilenameLoadImages (const char *file, int size) |
1024 | { |
1025 | FILE *f; |
1026 | XcursorImages *images; |
1027 | |
1028 | if (!file || size < 0) |
1029 | return NULL((void*)0); |
1030 | |
1031 | f = fopen (file, "r"); |
1032 | if (!f) |
1033 | return NULL((void*)0); |
1034 | images = XcursorFileLoadImages (f, size); |
1035 | fclose (f); |
1036 | return images; |
1037 | } |
1038 | |
1039 | XcursorImages * |
1040 | XcursorFilenameLoadAllImages (const char *file) |
1041 | { |
1042 | FILE *f; |
1043 | XcursorImages *images; |
1044 | |
1045 | if (!file) |
1046 | return NULL((void*)0); |
1047 | |
1048 | f = fopen (file, "r"); |
1049 | if (!f) |
1050 | return NULL((void*)0); |
1051 | images = XcursorFileLoadAllImages (f); |
1052 | fclose (f); |
1053 | return images; |
1054 | } |
1055 | |
1056 | XcursorBool |
1057 | XcursorFilenameLoad (const char *file, |
1058 | XcursorComments **commentsp, |
1059 | XcursorImages **imagesp) |
1060 | { |
1061 | FILE *f; |
1062 | XcursorBool ret; |
1063 | |
1064 | if (!file) |
1065 | return XcursorFalse0; |
1066 | |
1067 | f = fopen (file, "r"); |
1068 | if (!f) |
1069 | return 0; |
1070 | ret = XcursorFileLoad (f, commentsp, imagesp); |
1071 | fclose (f); |
1072 | return ret; |
1073 | } |
1074 | |
1075 | XcursorBool |
1076 | XcursorFilenameSaveImages (const char *file, const XcursorImages *images) |
1077 | { |
1078 | FILE *f; |
1079 | XcursorBool ret; |
1080 | |
1081 | if (!file || !images) |
1082 | return XcursorFalse0; |
1083 | |
1084 | f = fopen (file, "w"); |
1085 | if (!f) |
1086 | return 0; |
1087 | ret = XcursorFileSaveImages (f, images); |
1088 | return fclose (f) != EOF(-1) && ret; |
1089 | } |
1090 | |
1091 | XcursorBool |
1092 | XcursorFilenameSave (const char *file, |
1093 | const XcursorComments *comments, |
1094 | const XcursorImages *images) |
1095 | { |
1096 | FILE *f; |
1097 | XcursorBool ret; |
1098 | |
1099 | if (!file || !comments || !images) |
| 1 | Assuming 'file' is non-null | |
|
| 2 | | Assuming 'comments' is non-null | |
|
| 3 | | Assuming 'images' is non-null | |
|
| |
1100 | return XcursorFalse0; |
1101 | |
1102 | f = fopen (file, "w"); |
1103 | if (!f) |
| 5 | | Assuming 'f' is non-null | |
|
| |
1104 | return 0; |
1105 | ret = XcursorFileSave (f, comments, images); |
| 7 | | Calling 'XcursorFileSave' | |
|
1106 | return fclose (f) != EOF(-1) && ret; |
1107 | } |