]> git.saurik.com Git - wxWidgets.git/blame - src/xpm/parse.c
typo fixed
[wxWidgets.git] / src / xpm / parse.c
CommitLineData
cfbe03c9 1/*
e6ed776f 2 * Copyright (C) 1989-95 GROUPE BULL
cfbe03c9
JS
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 *
21 * Except as contained in this notice, the name of GROUPE BULL shall not be
22 * used in advertising or otherwise to promote the sale, use or other dealings
23 * in this Software without prior written authorization from GROUPE BULL.
24 */
25
26/*****************************************************************************\
27* parse.c: *
28* *
29* XPM library *
30* Parse an XPM file or array and store the found informations *
31* in the given XpmImage structure. *
32* *
33* Developed by Arnaud Le Hors *
34\*****************************************************************************/
35
36/*
37 * The code related to FOR_MSW has been added by
38 * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
39 */
40
e6ed776f 41#include "XpmI.h"
cfbe03c9 42#include <ctype.h>
cfbe03c9
JS
43
44LFUNC(ParsePixels, int, (xpmData *data, unsigned int width,
45 unsigned int height, unsigned int ncolors,
46 unsigned int cpp, XpmColor *colorTable,
47 xpmHashTable *hashtable, unsigned int **pixels));
48
cfbe03c9
JS
49char *xpmColorKeys[] = {
50 "s", /* key #1: symbol */
51 "m", /* key #2: mono visual */
52 "g4", /* key #3: 4 grays visual */
53 "g", /* key #4: gray visual */
54 "c", /* key #5: color visual */
55};
56
ea258ad3
DW
57#ifdef __OS2__
58/* Visual Age cannot deal with old, non-ansi, code */
59int xpmParseValues(
60 xpmData* data
61, unsigned int* width
62, unsigned int* height
63, unsigned int* ncolors
64, unsigned int* cpp
65, unsigned int* x_hotspot
66, unsigned int* y_hotspot
67, unsigned int* hotspot
68, unsigned int* extensions
69)
70#else
cfbe03c9 71int
e6ed776f
GRG
72xpmParseValues(data, width, height, ncolors, cpp,
73 x_hotspot, y_hotspot, hotspot, extensions)
74 xpmData *data;
75 unsigned int *width, *height, *ncolors, *cpp;
76 unsigned int *x_hotspot, *y_hotspot, *hotspot;
77 unsigned int *extensions;
ea258ad3 78#endif
cfbe03c9
JS
79{
80 unsigned int l;
81 char buf[BUFSIZ];
82
83 if (!data->format) { /* XPM 2 or 3 */
84
85 /*
86 * read values: width, height, ncolors, chars_per_pixel
87 */
88 if (!(xpmNextUI(data, width) && xpmNextUI(data, height)
89 && xpmNextUI(data, ncolors) && xpmNextUI(data, cpp)))
90 return (XpmFileInvalid);
91
92 /*
93 * read optional information (hotspot and/or XPMEXT) if any
94 */
95 l = xpmNextWord(data, buf, BUFSIZ);
96 if (l) {
97 *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6));
98 if (*extensions)
99 *hotspot = (xpmNextUI(data, x_hotspot)
100 && xpmNextUI(data, y_hotspot));
101 else {
e6ed776f 102 *hotspot = (xpmatoui(buf, l, x_hotspot)
cfbe03c9
JS
103 && xpmNextUI(data, y_hotspot));
104 l = xpmNextWord(data, buf, BUFSIZ);
105 *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6));
106 }
107 }
108 } else {
109
110 /*
111 * XPM 1 file read values: width, height, ncolors, chars_per_pixel
112 */
113 int i;
114 char *ptr;
e6ed776f
GRG
115 Bool got_one, saw_width = False, saw_height = False;
116 Bool saw_ncolors = False, saw_chars_per_pixel = False;
cfbe03c9
JS
117
118 for (i = 0; i < 4; i++) {
119 l = xpmNextWord(data, buf, BUFSIZ);
120 if (l != 7 || strncmp("#define", buf, 7))
121 return (XpmFileInvalid);
122 l = xpmNextWord(data, buf, BUFSIZ);
123 if (!l)
124 return (XpmFileInvalid);
e6ed776f
GRG
125 buf[l] = '\0';
126 ptr = buf;
127 got_one = False;
128 while (!got_one) {
129 ptr = index(ptr, '_');
130 if (!ptr)
cfbe03c9 131 return (XpmFileInvalid);
e6ed776f
GRG
132 switch (l - (ptr - buf)) {
133 case 6:
134 if (saw_width || strncmp("_width", ptr, 6)
135 || !xpmNextUI(data, width))
136 return (XpmFileInvalid);
137 else
138 saw_width = True;
139 got_one = True;
140 break;
141 case 7:
142 if (saw_height || strncmp("_height", ptr, 7)
143 || !xpmNextUI(data, height))
144 return (XpmFileInvalid);
145 else
146 saw_height = True;
147 got_one = True;
148 break;
149 case 8:
150 if (saw_ncolors || strncmp("_ncolors", ptr, 8)
151 || !xpmNextUI(data, ncolors))
152 return (XpmFileInvalid);
153 else
154 saw_ncolors = True;
155 got_one = True;
156 break;
157 case 16:
158 if (saw_chars_per_pixel
159 || strncmp("_chars_per_pixel", ptr, 16)
160 || !xpmNextUI(data, cpp))
161 return (XpmFileInvalid);
162 else
163 saw_chars_per_pixel = True;
164 got_one = True;
165 break;
166 default:
167 ptr++;
168 }
cfbe03c9
JS
169 }
170 /* skip the end of line */
171 xpmNextString(data);
172 }
e6ed776f
GRG
173 if (!saw_width || !saw_height || !saw_ncolors || !saw_chars_per_pixel)
174 return (XpmFileInvalid);
175
cfbe03c9
JS
176 *hotspot = 0;
177 *extensions = 0;
178 }
179 return (XpmSuccess);
180}
181
ea258ad3
DW
182#ifdef __OS2__
183/* Visual Age cannot deal with old, non-ansi, code */
184int xpmParseColors(
185 xpmData* data
186, unsigned int ncolors
187, unsigned int cpp
188, XpmColor** colorTablePtr
189, xpmHashTable* hashtable
190)
191#else
e6ed776f
GRG
192int
193xpmParseColors(data, ncolors, cpp, colorTablePtr, hashtable)
194 xpmData *data;
195 unsigned int ncolors;
196 unsigned int cpp;
197 XpmColor **colorTablePtr;
198 xpmHashTable *hashtable;
ea258ad3 199#endif
cfbe03c9
JS
200{
201 unsigned int key, l, a, b;
202 unsigned int curkey; /* current color key */
203 unsigned int lastwaskey; /* key read */
204 char buf[BUFSIZ];
205 char curbuf[BUFSIZ]; /* current buffer */
206 char **sptr, *s;
207 XpmColor *color;
208 XpmColor *colorTable;
209 char **defaults;
210 int ErrorStatus;
211
212 colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor));
213 if (!colorTable)
214 return (XpmNoMemory);
215
216 if (!data->format) { /* XPM 2 or 3 */
217 for (a = 0, color = colorTable; a < ncolors; a++, color++) {
218 xpmNextString(data); /* skip the line */
219
220 /*
221 * read pixel value
222 */
223 color->string = (char *) XpmMalloc(cpp + 1);
224 if (!color->string) {
225 xpmFreeColorTable(colorTable, ncolors);
226 return (XpmNoMemory);
227 }
228 for (b = 0, s = color->string; b < cpp; b++, s++)
229 *s = xpmGetC(data);
230 *s = '\0';
231
232 /*
233 * store the string in the hashtable with its color index number
234 */
235 if (USE_HASHTABLE) {
236 ErrorStatus =
237 xpmHashIntern(hashtable, color->string, HashAtomData(a));
238 if (ErrorStatus != XpmSuccess) {
239 xpmFreeColorTable(colorTable, ncolors);
240 return (ErrorStatus);
241 }
242 }
243
244 /*
245 * read color keys and values
246 */
247 defaults = (char **) color;
248 curkey = 0;
249 lastwaskey = 0;
250 *curbuf = '\0'; /* init curbuf */
251 while (l = xpmNextWord(data, buf, BUFSIZ)) {
252 if (!lastwaskey) {
253 for (key = 0, sptr = xpmColorKeys; key < NKEYS; key++,
254 sptr++)
255 if ((strlen(*sptr) == l) && (!strncmp(*sptr, buf, l)))
256 break;
257 }
258 if (!lastwaskey && key < NKEYS) { /* open new key */
259 if (curkey) { /* flush string */
260 s = (char *) XpmMalloc(strlen(curbuf) + 1);
261 if (!s) {
262 xpmFreeColorTable(colorTable, ncolors);
263 return (XpmNoMemory);
264 }
265 defaults[curkey] = s;
266 strcpy(s, curbuf);
267 }
268 curkey = key + 1; /* set new key */
269 *curbuf = '\0'; /* reset curbuf */
270 lastwaskey = 1;
271 } else {
272 if (!curkey) { /* key without value */
273 xpmFreeColorTable(colorTable, ncolors);
274 return (XpmFileInvalid);
275 }
276 if (!lastwaskey)
277 strcat(curbuf, " "); /* append space */
278 buf[l] = '\0';
279 strcat(curbuf, buf);/* append buf */
280 lastwaskey = 0;
281 }
282 }
283 if (!curkey) { /* key without value */
284 xpmFreeColorTable(colorTable, ncolors);
285 return (XpmFileInvalid);
286 }
287 s = defaults[curkey] = (char *) XpmMalloc(strlen(curbuf) + 1);
288 if (!s) {
289 xpmFreeColorTable(colorTable, ncolors);
290 return (XpmNoMemory);
291 }
292 strcpy(s, curbuf);
293 }
294 } else { /* XPM 1 */
295 /* get to the beginning of the first string */
296 data->Bos = '"';
297 data->Eos = '\0';
298 xpmNextString(data);
299 data->Eos = '"';
300 for (a = 0, color = colorTable; a < ncolors; a++, color++) {
301
302 /*
303 * read pixel value
304 */
305 color->string = (char *) XpmMalloc(cpp + 1);
306 if (!color->string) {
307 xpmFreeColorTable(colorTable, ncolors);
308 return (XpmNoMemory);
309 }
310 for (b = 0, s = color->string; b < cpp; b++, s++)
311 *s = xpmGetC(data);
312 *s = '\0';
313
314 /*
315 * store the string in the hashtable with its color index number
316 */
317 if (USE_HASHTABLE) {
318 ErrorStatus =
319 xpmHashIntern(hashtable, color->string, HashAtomData(a));
320 if (ErrorStatus != XpmSuccess) {
321 xpmFreeColorTable(colorTable, ncolors);
322 return (ErrorStatus);
323 }
324 }
325
326 /*
327 * read color values
328 */
329 xpmNextString(data); /* get to the next string */
330 *curbuf = '\0'; /* init curbuf */
331 while (l = xpmNextWord(data, buf, BUFSIZ)) {
332 if (*curbuf != '\0')
333 strcat(curbuf, " ");/* append space */
334 buf[l] = '\0';
335 strcat(curbuf, buf); /* append buf */
336 }
337 s = (char *) XpmMalloc(strlen(curbuf) + 1);
338 if (!s) {
339 xpmFreeColorTable(colorTable, ncolors);
340 return (XpmNoMemory);
341 }
342 strcpy(s, curbuf);
343 color->c_color = s;
344 *curbuf = '\0'; /* reset curbuf */
345 if (a < ncolors - 1)
346 xpmNextString(data); /* get to the next string */
347 }
348 }
349 *colorTablePtr = colorTable;
350 return (XpmSuccess);
351}
352
ea258ad3
DW
353#ifdef __OS2__
354/* Visual Age cannot deal with old, non-ansi, code */
355static int
356ParsePixels(
357 xpmData* data
358, unsigned int width
359, unsigned int height
360, unsigned int ncolors
361, unsigned int cpp
362, XpmColor* colorTable
363, xpmHashTable* hashtable
364, unsigned int** pixels
365)
366#else
cfbe03c9 367static int
e6ed776f
GRG
368ParsePixels(data, width, height, ncolors, cpp, colorTable, hashtable, pixels)
369 xpmData *data;
370 unsigned int width;
371 unsigned int height;
372 unsigned int ncolors;
373 unsigned int cpp;
374 XpmColor *colorTable;
375 xpmHashTable *hashtable;
376 unsigned int **pixels;
ea258ad3 377#endif
cfbe03c9
JS
378{
379 unsigned int *iptr, *iptr2;
380 unsigned int a, x, y;
381
382#ifndef FOR_MSW
383 iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height);
384#else
385
386 /*
387 * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!!
388 * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary
389 */
390 iptr2 = (unsigned int *)
391 XpmMalloc((long) sizeof(unsigned int) * (long) width * (long) height);
392#endif
393 if (!iptr2)
394 return (XpmNoMemory);
395
396 iptr = iptr2;
397
398 switch (cpp) {
399
400 case (1): /* Optimize for single character
401 * colors */
402 {
403 unsigned short colidx[256];
404
405 bzero((char *)colidx, 256 * sizeof(short));
406 for (a = 0; a < ncolors; a++)
e6ed776f 407 colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
cfbe03c9
JS
408
409 for (y = 0; y < height; y++) {
410 xpmNextString(data);
411 for (x = 0; x < width; x++, iptr++) {
e6ed776f 412 int c = xpmGetC(data);
cfbe03c9 413
e6ed776f
GRG
414 if (c > 0 && c < 256 && colidx[c] != 0)
415 *iptr = colidx[c] - 1;
cfbe03c9
JS
416 else {
417 XpmFree(iptr2);
418 return (XpmFileInvalid);
419 }
420 }
421 }
422 }
423 break;
424
425 case (2): /* Optimize for double character
426 * colors */
427 {
428
429/* free all allocated pointers at all exits */
430#define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
431if (cidx[f]) XpmFree(cidx[f]);}
432
433 /* array of pointers malloced by need */
434 unsigned short *cidx[256];
435 int char1;
436
437 bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
438 for (a = 0; a < ncolors; a++) {
439 char1 = colorTable[a].string[0];
440 if (cidx[char1] == NULL) { /* get new memory */
441 cidx[char1] = (unsigned short *)
442 XpmCalloc(256, sizeof(unsigned short));
443 if (cidx[char1] == NULL) { /* new block failed */
444 FREE_CIDX;
445 XpmFree(iptr2);
446 return (XpmNoMemory);
447 }
448 }
e6ed776f 449 cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
cfbe03c9
JS
450 }
451
452 for (y = 0; y < height; y++) {
453 xpmNextString(data);
454 for (x = 0; x < width; x++, iptr++) {
455 int cc1 = xpmGetC(data);
e6ed776f
GRG
456 if (cc1 > 0 && cc1 < 256) {
457 int cc2 = xpmGetC(data);
458 if (cc2 > 0 && cc2 < 256 &&
459 cidx[cc1] && cidx[cc1][cc2] != 0)
460 *iptr = cidx[cc1][cc2] - 1;
461 else {
462 FREE_CIDX;
463 XpmFree(iptr2);
464 return (XpmFileInvalid);
465 }
466 } else {
cfbe03c9
JS
467 FREE_CIDX;
468 XpmFree(iptr2);
469 return (XpmFileInvalid);
470 }
471 }
472 }
473 FREE_CIDX;
474 }
475 break;
476
477 default: /* Non-optimized case of long color
478 * names */
479 {
480 char *s;
481 char buf[BUFSIZ];
482
483 buf[cpp] = '\0';
484 if (USE_HASHTABLE) {
485 xpmHashAtom *slot;
486
487 for (y = 0; y < height; y++) {
488 xpmNextString(data);
489 for (x = 0; x < width; x++, iptr++) {
490 for (a = 0, s = buf; a < cpp; a++, s++)
491 *s = xpmGetC(data);
492 slot = xpmHashSlot(hashtable, buf);
493 if (!*slot) { /* no color matches */
494 XpmFree(iptr2);
495 return (XpmFileInvalid);
496 }
497 *iptr = HashColorIndex(slot);
498 }
499 }
500 } else {
501 for (y = 0; y < height; y++) {
502 xpmNextString(data);
503 for (x = 0; x < width; x++, iptr++) {
504 for (a = 0, s = buf; a < cpp; a++, s++)
505 *s = xpmGetC(data);
506 for (a = 0; a < ncolors; a++)
507 if (!strcmp(colorTable[a].string, buf))
508 break;
509 if (a == ncolors) { /* no color matches */
510 XpmFree(iptr2);
511 return (XpmFileInvalid);
512 }
513 *iptr = a;
514 }
515 }
516 }
517 }
518 break;
519 }
520 *pixels = iptr2;
521 return (XpmSuccess);
522}
523
ea258ad3
DW
524#ifdef __OS2__
525/* Visual Age cannot deal with old, non-ansi, code */
526int xpmParseExtensions(
527 xpmData* data
528, XpmExtension** extensions
529, unsigned int* nextensions
530)
531#else
e6ed776f
GRG
532int
533xpmParseExtensions(data, extensions, nextensions)
534 xpmData *data;
535 XpmExtension **extensions;
536 unsigned int *nextensions;
ea258ad3 537#endif
cfbe03c9
JS
538{
539 XpmExtension *exts = NULL, *ext;
540 unsigned int num = 0;
541 unsigned int nlines, a, l, notstart, notend = 0;
542 int status;
543 char *string, *s, *s2, **sp;
544
545 xpmNextString(data);
546 exts = (XpmExtension *) XpmMalloc(sizeof(XpmExtension));
547 /* get the whole string */
548 status = xpmGetString(data, &string, &l);
549 if (status != XpmSuccess) {
550 XpmFree(exts);
551 return (status);
552 }
553 /* look for the key word XPMEXT, skip lines before this */
554 while ((notstart = strncmp("XPMEXT", string, 6))
555 && (notend = strncmp("XPMENDEXT", string, 9))) {
556 XpmFree(string);
557 xpmNextString(data);
558 status = xpmGetString(data, &string, &l);
559 if (status != XpmSuccess) {
560 XpmFree(exts);
561 return (status);
562 }
563 }
564 if (!notstart)
565 notend = strncmp("XPMENDEXT", string, 9);
566 while (!notstart && notend) {
567 /* there starts an extension */
568 ext = (XpmExtension *)
569 XpmRealloc(exts, (num + 1) * sizeof(XpmExtension));
570 if (!ext) {
571 XpmFree(string);
572 XpmFreeExtensions(exts, num);
573 return (XpmNoMemory);
574 }
575 exts = ext;
576 ext += num;
577 /* skip whitespace and store its name */
578 s2 = s = string + 6;
579 while (isspace(*s2))
580 s2++;
581 a = s2 - s;
582 ext->name = (char *) XpmMalloc(l - a - 6);
583 if (!ext->name) {
584 XpmFree(string);
585 ext->lines = NULL;
586 ext->nlines = 0;
587 XpmFreeExtensions(exts, num + 1);
588 return (XpmNoMemory);
589 }
590 strncpy(ext->name, s + a, l - a - 6);
591 XpmFree(string);
592 /* now store the related lines */
593 xpmNextString(data);
594 status = xpmGetString(data, &string, &l);
595 if (status != XpmSuccess) {
596 ext->lines = NULL;
597 ext->nlines = 0;
598 XpmFreeExtensions(exts, num + 1);
599 return (status);
600 }
601 ext->lines = (char **) XpmMalloc(sizeof(char *));
602 nlines = 0;
603 while ((notstart = strncmp("XPMEXT", string, 6))
604 && (notend = strncmp("XPMENDEXT", string, 9))) {
605 sp = (char **)
606 XpmRealloc(ext->lines, (nlines + 1) * sizeof(char *));
607 if (!sp) {
608 XpmFree(string);
609 ext->nlines = nlines;
610 XpmFreeExtensions(exts, num + 1);
611 return (XpmNoMemory);
612 }
613 ext->lines = sp;
614 ext->lines[nlines] = string;
615 nlines++;
616 xpmNextString(data);
617 status = xpmGetString(data, &string, &l);
618 if (status != XpmSuccess) {
619 ext->nlines = nlines;
620 XpmFreeExtensions(exts, num + 1);
621 return (status);
622 }
623 }
624 if (!nlines) {
625 XpmFree(ext->lines);
626 ext->lines = NULL;
627 }
628 ext->nlines = nlines;
629 num++;
630 }
631 if (!num) {
632 XpmFree(string);
633 XpmFree(exts);
634 exts = NULL;
635 } else if (!notend)
636 XpmFree(string);
637 *nextensions = num;
638 *extensions = exts;
639 return (XpmSuccess);
640}
e6ed776f
GRG
641
642
643/* function call in case of error */
644#undef RETURN
645#define RETURN(status) \
646{ \
647 goto error; \
648}
649
650/*
651 * This function parses an Xpm file or data and store the found informations
652 * in an an XpmImage structure which is returned.
653 */
ea258ad3
DW
654#ifdef __OS2__
655/* Visual Age cannot deal with old, non-ansi, code */
656int xpmParseData(
657 xpmData* data
658, XpmImage* image
659, XpmInfo* info
660)
661#else
e6ed776f
GRG
662int
663xpmParseData(data, image, info)
664 xpmData *data;
665 XpmImage *image;
666 XpmInfo *info;
ea258ad3 667#endif
e6ed776f
GRG
668{
669 /* variables to return */
670 unsigned int width, height, ncolors, cpp;
671 unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
672 XpmColor *colorTable = NULL;
673 unsigned int *pixelindex = NULL;
674 char *hints_cmt = NULL;
675 char *colors_cmt = NULL;
676 char *pixels_cmt = NULL;
677
678 unsigned int cmts;
679 int ErrorStatus;
680 xpmHashTable hashtable;
681
682 cmts = info && (info->valuemask & XpmReturnComments);
683
684 /*
685 * parse the header
686 */
687 ErrorStatus = xpmParseHeader(data);
688 if (ErrorStatus != XpmSuccess)
689 return (ErrorStatus);
690
691 /*
692 * read values
693 */
694 ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
695 &x_hotspot, &y_hotspot, &hotspot,
696 &extensions);
697 if (ErrorStatus != XpmSuccess)
698 return (ErrorStatus);
699
700 /*
701 * store the hints comment line
702 */
703 if (cmts)
704 xpmGetCmt(data, &hints_cmt);
705
706 /*
707 * init the hastable
708 */
709 if (USE_HASHTABLE) {
710 ErrorStatus = xpmHashTableInit(&hashtable);
711 if (ErrorStatus != XpmSuccess)
712 return (ErrorStatus);
713 }
714
715 /*
716 * read colors
717 */
718 ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
719 if (ErrorStatus != XpmSuccess) {
720 if (USE_HASHTABLE)
721 xpmHashTableFree(&hashtable);
722 RETURN(ErrorStatus);
723 }
724
725 /*
726 * store the colors comment line
727 */
728 if (cmts)
729 xpmGetCmt(data, &colors_cmt);
730
731 /*
732 * read pixels and index them on color number
733 */
734 ErrorStatus = ParsePixels(data, width, height, ncolors, cpp, colorTable,
735 &hashtable, &pixelindex);
736
737 /*
738 * free the hastable
739 */
740 if (USE_HASHTABLE)
741 xpmHashTableFree(&hashtable);
742
743 if (ErrorStatus != XpmSuccess)
744 RETURN(ErrorStatus);
745
746 /*
747 * store the pixels comment line
748 */
749 if (cmts)
750 xpmGetCmt(data, &pixels_cmt);
751
752 /*
753 * parse extensions
754 */
755 if (info && (info->valuemask & XpmReturnExtensions))
756 if (extensions) {
757 ErrorStatus = xpmParseExtensions(data, &info->extensions,
758 &info->nextensions);
759 if (ErrorStatus != XpmSuccess)
760 RETURN(ErrorStatus);
761 } else {
762 info->extensions = NULL;
763 info->nextensions = 0;
764 }
765
766 /*
767 * store found informations in the XpmImage structure
768 */
769 image->width = width;
770 image->height = height;
771 image->cpp = cpp;
772 image->ncolors = ncolors;
773 image->colorTable = colorTable;
774 image->data = pixelindex;
775
776 if (info) {
777 if (cmts) {
778 info->hints_cmt = hints_cmt;
779 info->colors_cmt = colors_cmt;
780 info->pixels_cmt = pixels_cmt;
781 }
782 if (hotspot) {
783 info->x_hotspot = x_hotspot;
784 info->y_hotspot = y_hotspot;
785 info->valuemask |= XpmHotspot;
786 }
787 }
788 return (XpmSuccess);
789
790/* exit point in case of error, free only locally allocated variables */
791error:
792 if (colorTable)
793 xpmFreeColorTable(colorTable, ncolors);
794 if (pixelindex)
795 XpmFree(pixelindex);
796 if (hints_cmt)
797 XpmFree(hints_cmt);
798 if (colors_cmt)
799 XpmFree(colors_cmt);
800 if (pixels_cmt)
801 XpmFree(pixels_cmt);
802
803 return(ErrorStatus);
804}