]>
git.saurik.com Git - wxWidgets.git/blob - src/mac/xpm/parse.c
2 * Copyright (C) 1989-95 GROUPE BULL
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
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.
26 /*****************************************************************************\
30 * Parse an XPM file or array and store the found informations *
31 * in the given XpmImage structure. *
33 * Developed by Arnaud Le Hors *
34 \*****************************************************************************/
37 * The code related to FOR_MSW has been added by
38 * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
44 LFUNC(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
));
49 char *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 */
58 xpmParseValues(data
, width
, height
, ncolors
, cpp
,
59 x_hotspot
, y_hotspot
, hotspot
, extensions
)
61 unsigned int *width
, *height
, *ncolors
, *cpp
;
62 unsigned int *x_hotspot
, *y_hotspot
, *hotspot
;
63 unsigned int *extensions
;
68 if (!data
->format
) { /* XPM 2 or 3 */
71 * read values: width, height, ncolors, chars_per_pixel
73 if (!(xpmNextUI(data
, width
) && xpmNextUI(data
, height
)
74 && xpmNextUI(data
, ncolors
) && xpmNextUI(data
, cpp
)))
75 return (XpmFileInvalid
);
78 * read optional information (hotspot and/or XPMEXT) if any
80 l
= xpmNextWord(data
, buf
, BUFSIZ
);
82 *extensions
= (l
== 6 && !strncmp("XPMEXT", buf
, 6));
84 *hotspot
= (xpmNextUI(data
, x_hotspot
)
85 && xpmNextUI(data
, y_hotspot
));
87 *hotspot
= (xpmatoui(buf
, l
, x_hotspot
)
88 && xpmNextUI(data
, y_hotspot
));
89 l
= xpmNextWord(data
, buf
, BUFSIZ
);
90 *extensions
= (l
== 6 && !strncmp("XPMEXT", buf
, 6));
96 * XPM 1 file read values: width, height, ncolors, chars_per_pixel
100 Bool got_one
, saw_width
= False
, saw_height
= False
;
101 Bool saw_ncolors
= False
, saw_chars_per_pixel
= False
;
103 for (i
= 0; i
< 4; i
++) {
104 l
= xpmNextWord(data
, buf
, BUFSIZ
);
105 if (l
!= 7 || strncmp("#define", buf
, 7))
106 return (XpmFileInvalid
);
107 l
= xpmNextWord(data
, buf
, BUFSIZ
);
109 return (XpmFileInvalid
);
114 #if defined(macintosh) || defined(__APPLE__)
115 // we have a strange parameter problem here
116 ptr
= strchr(ptr
, '_'); // index
118 ptr
= index(ptr
, '_');
121 return (XpmFileInvalid
);
122 switch (l
- (ptr
- buf
)) {
124 if (saw_width
|| strncmp("_width", ptr
, 6)
125 || !xpmNextUI(data
, width
))
126 return (XpmFileInvalid
);
132 if (saw_height
|| strncmp("_height", ptr
, 7)
133 || !xpmNextUI(data
, height
))
134 return (XpmFileInvalid
);
140 if (saw_ncolors
|| strncmp("_ncolors", ptr
, 8)
141 || !xpmNextUI(data
, ncolors
))
142 return (XpmFileInvalid
);
148 if (saw_chars_per_pixel
149 || strncmp("_chars_per_pixel", ptr
, 16)
150 || !xpmNextUI(data
, cpp
))
151 return (XpmFileInvalid
);
153 saw_chars_per_pixel
= True
;
160 /* skip the end of line */
163 if (!saw_width
|| !saw_height
|| !saw_ncolors
|| !saw_chars_per_pixel
)
164 return (XpmFileInvalid
);
173 xpmParseColors(data
, ncolors
, cpp
, colorTablePtr
, hashtable
)
175 unsigned int ncolors
;
177 XpmColor
**colorTablePtr
;
178 xpmHashTable
*hashtable
;
180 unsigned int key
, l
, a
, b
;
181 unsigned int curkey
; /* current color key */
182 unsigned int lastwaskey
; /* key read */
184 char curbuf
[BUFSIZ
]; /* current buffer */
187 XpmColor
*colorTable
;
191 colorTable
= (XpmColor
*) XpmCalloc(ncolors
, sizeof(XpmColor
));
193 return (XpmNoMemory
);
195 if (!data
->format
) { /* XPM 2 or 3 */
196 for (a
= 0, color
= colorTable
; a
< ncolors
; a
++, color
++) {
197 xpmNextString(data
); /* skip the line */
202 color
->string
= (char *) XpmMalloc(cpp
+ 1);
203 if (!color
->string
) {
204 xpmFreeColorTable(colorTable
, ncolors
);
205 return (XpmNoMemory
);
207 for (b
= 0, s
= color
->string
; b
< cpp
; b
++, s
++)
212 * store the string in the hashtable with its color index number
216 xpmHashIntern(hashtable
, color
->string
, HashAtomData(a
));
217 if (ErrorStatus
!= XpmSuccess
) {
218 xpmFreeColorTable(colorTable
, ncolors
);
219 return (ErrorStatus
);
224 * read color keys and values
226 defaults
= (char **) color
;
229 *curbuf
= '\0'; /* init curbuf */
230 while ((l
= xpmNextWord(data
, buf
, BUFSIZ
))!=NULL
) {
232 for (key
= 0, sptr
= xpmColorKeys
; key
< NKEYS
; key
++,
234 if ((strlen(*sptr
) == l
) && (!strncmp(*sptr
, buf
, l
)))
237 if (!lastwaskey
&& key
< NKEYS
) { /* open new key */
238 if (curkey
) { /* flush string */
239 s
= (char *) XpmMalloc(strlen(curbuf
) + 1);
241 xpmFreeColorTable(colorTable
, ncolors
);
242 return (XpmNoMemory
);
244 defaults
[curkey
] = s
;
247 curkey
= key
+ 1; /* set new key */
248 *curbuf
= '\0'; /* reset curbuf */
251 if (!curkey
) { /* key without value */
252 xpmFreeColorTable(colorTable
, ncolors
);
253 return (XpmFileInvalid
);
256 strcat(curbuf
, " "); /* append space */
258 strcat(curbuf
, buf
);/* append buf */
262 if (!curkey
) { /* key without value */
263 xpmFreeColorTable(colorTable
, ncolors
);
264 return (XpmFileInvalid
);
266 s
= defaults
[curkey
] = (char *) XpmMalloc(strlen(curbuf
) + 1);
268 xpmFreeColorTable(colorTable
, ncolors
);
269 return (XpmNoMemory
);
274 /* get to the beginning of the first string */
279 for (a
= 0, color
= colorTable
; a
< ncolors
; a
++, color
++) {
284 color
->string
= (char *) XpmMalloc(cpp
+ 1);
285 if (!color
->string
) {
286 xpmFreeColorTable(colorTable
, ncolors
);
287 return (XpmNoMemory
);
289 for (b
= 0, s
= color
->string
; b
< cpp
; b
++, s
++)
294 * store the string in the hashtable with its color index number
298 xpmHashIntern(hashtable
, color
->string
, HashAtomData(a
));
299 if (ErrorStatus
!= XpmSuccess
) {
300 xpmFreeColorTable(colorTable
, ncolors
);
301 return (ErrorStatus
);
308 xpmNextString(data
); /* get to the next string */
309 *curbuf
= '\0'; /* init curbuf */
310 while ((l
= xpmNextWord(data
, buf
, BUFSIZ
))!=NULL
) {
312 strcat(curbuf
, " ");/* append space */
314 strcat(curbuf
, buf
); /* append buf */
316 s
= (char *) XpmMalloc(strlen(curbuf
) + 1);
318 xpmFreeColorTable(colorTable
, ncolors
);
319 return (XpmNoMemory
);
323 *curbuf
= '\0'; /* reset curbuf */
325 xpmNextString(data
); /* get to the next string */
328 *colorTablePtr
= colorTable
;
333 ParsePixels(data
, width
, height
, ncolors
, cpp
, colorTable
, hashtable
, pixels
)
337 unsigned int ncolors
;
339 XpmColor
*colorTable
;
340 xpmHashTable
*hashtable
;
341 unsigned int **pixels
;
343 unsigned int *iptr
, *iptr2
;
344 unsigned int a
, x
, y
;
347 iptr2
= (unsigned int *) XpmMalloc(sizeof(unsigned int) * width
* height
);
351 * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!!
352 * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary
354 iptr2
= (unsigned int *)
355 XpmMalloc((long) sizeof(unsigned int) * (long) width
* (long) height
);
358 return (XpmNoMemory
);
364 case (1): /* Optimize for single character
367 unsigned short colidx
[256];
369 bzero((char *)colidx
, 256 * sizeof(short));
370 for (a
= 0; a
< ncolors
; a
++)
371 colidx
[(unsigned char)colorTable
[a
].string
[0]] = a
+ 1;
373 for (y
= 0; y
< height
; y
++) {
375 for (x
= 0; x
< width
; x
++, iptr
++) {
376 int c
= xpmGetC(data
);
378 if (c
> 0 && c
< 256 && colidx
[c
] != 0)
379 *iptr
= colidx
[c
] - 1;
382 return (XpmFileInvalid
);
389 case (2): /* Optimize for double character
393 /* free all allocated pointers at all exits */
394 #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
395 if (cidx[f]) XpmFree(cidx[f]);}
397 /* array of pointers malloced by need */
398 unsigned short *cidx
[256];
401 bzero((char *)cidx
, 256 * sizeof(unsigned short *)); /* init */
402 for (a
= 0; a
< ncolors
; a
++) {
403 char1
= colorTable
[a
].string
[0];
404 if (cidx
[char1
] == NULL
) { /* get new memory */
405 cidx
[char1
] = (unsigned short *)
406 XpmCalloc(256, sizeof(unsigned short));
407 if (cidx
[char1
] == NULL
) { /* new block failed */
410 return (XpmNoMemory
);
413 cidx
[char1
][(unsigned char)colorTable
[a
].string
[1]] = a
+ 1;
416 for (y
= 0; y
< height
; y
++) {
418 for (x
= 0; x
< width
; x
++, iptr
++) {
419 int cc1
= xpmGetC(data
);
420 if (cc1
> 0 && cc1
< 256) {
421 int cc2
= xpmGetC(data
);
422 if (cc2
> 0 && cc2
< 256 &&
423 cidx
[cc1
] && cidx
[cc1
][cc2
] != 0)
424 *iptr
= cidx
[cc1
][cc2
] - 1;
428 return (XpmFileInvalid
);
433 return (XpmFileInvalid
);
441 default: /* Non-optimized case of long color
451 for (y
= 0; y
< height
; y
++) {
453 for (x
= 0; x
< width
; x
++, iptr
++) {
454 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
456 slot
= xpmHashSlot(hashtable
, buf
);
457 if (!*slot
) { /* no color matches */
459 return (XpmFileInvalid
);
461 *iptr
= HashColorIndex(slot
);
465 for (y
= 0; y
< height
; y
++) {
467 for (x
= 0; x
< width
; x
++, iptr
++) {
468 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
470 for (a
= 0; a
< ncolors
; a
++)
471 if (!strcmp(colorTable
[a
].string
, buf
))
473 if (a
== ncolors
) { /* no color matches */
475 return (XpmFileInvalid
);
489 xpmParseExtensions(data
, extensions
, nextensions
)
491 XpmExtension
**extensions
;
492 unsigned int *nextensions
;
494 XpmExtension
*exts
= NULL
, *ext
;
495 unsigned int num
= 0;
496 unsigned int nlines
, a
, l
, notstart
, notend
= 0;
498 char *string
, *s
, *s2
, **sp
;
501 exts
= (XpmExtension
*) XpmMalloc(sizeof(XpmExtension
));
502 /* get the whole string */
503 status
= xpmGetString(data
, &string
, &l
);
504 if (status
!= XpmSuccess
) {
508 /* look for the key word XPMEXT, skip lines before this */
509 while ((notstart
= strncmp("XPMEXT", string
, 6))!=NULL
510 && (notend
= strncmp("XPMENDEXT", string
, 9))!=NULL
) {
513 status
= xpmGetString(data
, &string
, &l
);
514 if (status
!= XpmSuccess
) {
520 notend
= strncmp("XPMENDEXT", string
, 9);
521 while (!notstart
&& notend
) {
522 /* there starts an extension */
523 ext
= (XpmExtension
*)
524 XpmRealloc(exts
, (num
+ 1) * sizeof(XpmExtension
));
527 XpmFreeExtensions(exts
, num
);
528 return (XpmNoMemory
);
532 /* skip whitespace and store its name */
537 ext
->name
= (char *) XpmMalloc(l
- a
- 6);
542 XpmFreeExtensions(exts
, num
+ 1);
543 return (XpmNoMemory
);
545 strncpy(ext
->name
, s
+ a
, l
- a
- 6);
547 /* now store the related lines */
549 status
= xpmGetString(data
, &string
, &l
);
550 if (status
!= XpmSuccess
) {
553 XpmFreeExtensions(exts
, num
+ 1);
556 ext
->lines
= (char **) XpmMalloc(sizeof(char *));
558 while ((notstart
= strncmp("XPMEXT", string
, 6))!=NULL
559 && (notend
= strncmp("XPMENDEXT", string
, 9))!=NULL
) {
561 XpmRealloc(ext
->lines
, (nlines
+ 1) * sizeof(char *));
564 ext
->nlines
= nlines
;
565 XpmFreeExtensions(exts
, num
+ 1);
566 return (XpmNoMemory
);
569 ext
->lines
[nlines
] = string
;
572 status
= xpmGetString(data
, &string
, &l
);
573 if (status
!= XpmSuccess
) {
574 ext
->nlines
= nlines
;
575 XpmFreeExtensions(exts
, num
+ 1);
583 ext
->nlines
= nlines
;
598 /* function call in case of error */
600 #define RETURN(status) \
606 * This function parses an Xpm file or data and store the found informations
607 * in an an XpmImage structure which is returned.
610 xpmParseData(data
, image
, info
)
615 /* variables to return */
616 unsigned int width
, height
, ncolors
, cpp
;
617 unsigned int x_hotspot
, y_hotspot
, hotspot
= 0, extensions
= 0;
618 XpmColor
*colorTable
= NULL
;
619 unsigned int *pixelindex
= NULL
;
620 char *hints_cmt
= NULL
;
621 char *colors_cmt
= NULL
;
622 char *pixels_cmt
= NULL
;
626 xpmHashTable hashtable
;
628 cmts
= info
&& (info
->valuemask
& XpmReturnComments
);
633 ErrorStatus
= xpmParseHeader(data
);
634 if (ErrorStatus
!= XpmSuccess
)
635 return (ErrorStatus
);
640 ErrorStatus
= xpmParseValues(data
, &width
, &height
, &ncolors
, &cpp
,
641 &x_hotspot
, &y_hotspot
, &hotspot
,
643 if (ErrorStatus
!= XpmSuccess
)
644 return (ErrorStatus
);
647 * store the hints comment line
650 xpmGetCmt(data
, &hints_cmt
);
656 ErrorStatus
= xpmHashTableInit(&hashtable
);
657 if (ErrorStatus
!= XpmSuccess
)
658 return (ErrorStatus
);
664 ErrorStatus
= xpmParseColors(data
, ncolors
, cpp
, &colorTable
, &hashtable
);
665 if (ErrorStatus
!= XpmSuccess
) {
667 xpmHashTableFree(&hashtable
);
672 * store the colors comment line
675 xpmGetCmt(data
, &colors_cmt
);
678 * read pixels and index them on color number
680 ErrorStatus
= ParsePixels(data
, width
, height
, ncolors
, cpp
, colorTable
,
681 &hashtable
, &pixelindex
);
687 xpmHashTableFree(&hashtable
);
689 if (ErrorStatus
!= XpmSuccess
)
693 * store the pixels comment line
696 xpmGetCmt(data
, &pixels_cmt
);
701 if (info
&& (info
->valuemask
& XpmReturnExtensions
))
703 ErrorStatus
= xpmParseExtensions(data
, &info
->extensions
,
705 if (ErrorStatus
!= XpmSuccess
)
708 info
->extensions
= NULL
;
709 info
->nextensions
= 0;
713 * store found informations in the XpmImage structure
715 image
->width
= width
;
716 image
->height
= height
;
718 image
->ncolors
= ncolors
;
719 image
->colorTable
= colorTable
;
720 image
->data
= pixelindex
;
724 info
->hints_cmt
= hints_cmt
;
725 info
->colors_cmt
= colors_cmt
;
726 info
->pixels_cmt
= pixels_cmt
;
729 info
->x_hotspot
= x_hotspot
;
730 info
->y_hotspot
= y_hotspot
;
731 info
->valuemask
|= XpmHotspot
;
736 /* exit point in case of error, free only locally allocated variables */
739 xpmFreeColorTable(colorTable
, ncolors
);