]>
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 #ifdef macintosh // we have a strange parameter problem here
115 ptr
= strchr(ptr
, '_'); // index
117 ptr
= index(ptr
, '_');
120 return (XpmFileInvalid
);
121 switch (l
- (ptr
- buf
)) {
123 if (saw_width
|| strncmp("_width", ptr
, 6)
124 || !xpmNextUI(data
, width
))
125 return (XpmFileInvalid
);
131 if (saw_height
|| strncmp("_height", ptr
, 7)
132 || !xpmNextUI(data
, height
))
133 return (XpmFileInvalid
);
139 if (saw_ncolors
|| strncmp("_ncolors", ptr
, 8)
140 || !xpmNextUI(data
, ncolors
))
141 return (XpmFileInvalid
);
147 if (saw_chars_per_pixel
148 || strncmp("_chars_per_pixel", ptr
, 16)
149 || !xpmNextUI(data
, cpp
))
150 return (XpmFileInvalid
);
152 saw_chars_per_pixel
= True
;
159 /* skip the end of line */
162 if (!saw_width
|| !saw_height
|| !saw_ncolors
|| !saw_chars_per_pixel
)
163 return (XpmFileInvalid
);
172 xpmParseColors(data
, ncolors
, cpp
, colorTablePtr
, hashtable
)
174 unsigned int ncolors
;
176 XpmColor
**colorTablePtr
;
177 xpmHashTable
*hashtable
;
179 unsigned int key
, l
, a
, b
;
180 unsigned int curkey
; /* current color key */
181 unsigned int lastwaskey
; /* key read */
183 char curbuf
[BUFSIZ
]; /* current buffer */
186 XpmColor
*colorTable
;
190 colorTable
= (XpmColor
*) XpmCalloc(ncolors
, sizeof(XpmColor
));
192 return (XpmNoMemory
);
194 if (!data
->format
) { /* XPM 2 or 3 */
195 for (a
= 0, color
= colorTable
; a
< ncolors
; a
++, color
++) {
196 xpmNextString(data
); /* skip the line */
201 color
->string
= (char *) XpmMalloc(cpp
+ 1);
202 if (!color
->string
) {
203 xpmFreeColorTable(colorTable
, ncolors
);
204 return (XpmNoMemory
);
206 for (b
= 0, s
= color
->string
; b
< cpp
; b
++, s
++)
211 * store the string in the hashtable with its color index number
215 xpmHashIntern(hashtable
, color
->string
, HashAtomData(a
));
216 if (ErrorStatus
!= XpmSuccess
) {
217 xpmFreeColorTable(colorTable
, ncolors
);
218 return (ErrorStatus
);
223 * read color keys and values
225 defaults
= (char **) color
;
228 *curbuf
= '\0'; /* init curbuf */
229 while ((l
= xpmNextWord(data
, buf
, BUFSIZ
))!=NULL
) {
231 for (key
= 0, sptr
= xpmColorKeys
; key
< NKEYS
; key
++,
233 if ((strlen(*sptr
) == l
) && (!strncmp(*sptr
, buf
, l
)))
236 if (!lastwaskey
&& key
< NKEYS
) { /* open new key */
237 if (curkey
) { /* flush string */
238 s
= (char *) XpmMalloc(strlen(curbuf
) + 1);
240 xpmFreeColorTable(colorTable
, ncolors
);
241 return (XpmNoMemory
);
243 defaults
[curkey
] = s
;
246 curkey
= key
+ 1; /* set new key */
247 *curbuf
= '\0'; /* reset curbuf */
250 if (!curkey
) { /* key without value */
251 xpmFreeColorTable(colorTable
, ncolors
);
252 return (XpmFileInvalid
);
255 strcat(curbuf
, " "); /* append space */
257 strcat(curbuf
, buf
);/* append buf */
261 if (!curkey
) { /* key without value */
262 xpmFreeColorTable(colorTable
, ncolors
);
263 return (XpmFileInvalid
);
265 s
= defaults
[curkey
] = (char *) XpmMalloc(strlen(curbuf
) + 1);
267 xpmFreeColorTable(colorTable
, ncolors
);
268 return (XpmNoMemory
);
273 /* get to the beginning of the first string */
278 for (a
= 0, color
= colorTable
; a
< ncolors
; a
++, color
++) {
283 color
->string
= (char *) XpmMalloc(cpp
+ 1);
284 if (!color
->string
) {
285 xpmFreeColorTable(colorTable
, ncolors
);
286 return (XpmNoMemory
);
288 for (b
= 0, s
= color
->string
; b
< cpp
; b
++, s
++)
293 * store the string in the hashtable with its color index number
297 xpmHashIntern(hashtable
, color
->string
, HashAtomData(a
));
298 if (ErrorStatus
!= XpmSuccess
) {
299 xpmFreeColorTable(colorTable
, ncolors
);
300 return (ErrorStatus
);
307 xpmNextString(data
); /* get to the next string */
308 *curbuf
= '\0'; /* init curbuf */
309 while ((l
= xpmNextWord(data
, buf
, BUFSIZ
))!=NULL
) {
311 strcat(curbuf
, " ");/* append space */
313 strcat(curbuf
, buf
); /* append buf */
315 s
= (char *) XpmMalloc(strlen(curbuf
) + 1);
317 xpmFreeColorTable(colorTable
, ncolors
);
318 return (XpmNoMemory
);
322 *curbuf
= '\0'; /* reset curbuf */
324 xpmNextString(data
); /* get to the next string */
327 *colorTablePtr
= colorTable
;
332 ParsePixels(data
, width
, height
, ncolors
, cpp
, colorTable
, hashtable
, pixels
)
336 unsigned int ncolors
;
338 XpmColor
*colorTable
;
339 xpmHashTable
*hashtable
;
340 unsigned int **pixels
;
342 unsigned int *iptr
, *iptr2
;
343 unsigned int a
, x
, y
;
346 iptr2
= (unsigned int *) XpmMalloc(sizeof(unsigned int) * width
* height
);
350 * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!!
351 * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary
353 iptr2
= (unsigned int *)
354 XpmMalloc((long) sizeof(unsigned int) * (long) width
* (long) height
);
357 return (XpmNoMemory
);
363 case (1): /* Optimize for single character
366 unsigned short colidx
[256];
368 bzero((char *)colidx
, 256 * sizeof(short));
369 for (a
= 0; a
< ncolors
; a
++)
370 colidx
[(unsigned char)colorTable
[a
].string
[0]] = a
+ 1;
372 for (y
= 0; y
< height
; y
++) {
374 for (x
= 0; x
< width
; x
++, iptr
++) {
375 int c
= xpmGetC(data
);
377 if (c
> 0 && c
< 256 && colidx
[c
] != 0)
378 *iptr
= colidx
[c
] - 1;
381 return (XpmFileInvalid
);
388 case (2): /* Optimize for double character
392 /* free all allocated pointers at all exits */
393 #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
394 if (cidx[f]) XpmFree(cidx[f]);}
396 /* array of pointers malloced by need */
397 unsigned short *cidx
[256];
400 bzero((char *)cidx
, 256 * sizeof(unsigned short *)); /* init */
401 for (a
= 0; a
< ncolors
; a
++) {
402 char1
= colorTable
[a
].string
[0];
403 if (cidx
[char1
] == NULL
) { /* get new memory */
404 cidx
[char1
] = (unsigned short *)
405 XpmCalloc(256, sizeof(unsigned short));
406 if (cidx
[char1
] == NULL
) { /* new block failed */
409 return (XpmNoMemory
);
412 cidx
[char1
][(unsigned char)colorTable
[a
].string
[1]] = a
+ 1;
415 for (y
= 0; y
< height
; y
++) {
417 for (x
= 0; x
< width
; x
++, iptr
++) {
418 int cc1
= xpmGetC(data
);
419 if (cc1
> 0 && cc1
< 256) {
420 int cc2
= xpmGetC(data
);
421 if (cc2
> 0 && cc2
< 256 &&
422 cidx
[cc1
] && cidx
[cc1
][cc2
] != 0)
423 *iptr
= cidx
[cc1
][cc2
] - 1;
427 return (XpmFileInvalid
);
432 return (XpmFileInvalid
);
440 default: /* Non-optimized case of long color
450 for (y
= 0; y
< height
; y
++) {
452 for (x
= 0; x
< width
; x
++, iptr
++) {
453 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
455 slot
= xpmHashSlot(hashtable
, buf
);
456 if (!*slot
) { /* no color matches */
458 return (XpmFileInvalid
);
460 *iptr
= HashColorIndex(slot
);
464 for (y
= 0; y
< height
; y
++) {
466 for (x
= 0; x
< width
; x
++, iptr
++) {
467 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
469 for (a
= 0; a
< ncolors
; a
++)
470 if (!strcmp(colorTable
[a
].string
, buf
))
472 if (a
== ncolors
) { /* no color matches */
474 return (XpmFileInvalid
);
488 xpmParseExtensions(data
, extensions
, nextensions
)
490 XpmExtension
**extensions
;
491 unsigned int *nextensions
;
493 XpmExtension
*exts
= NULL
, *ext
;
494 unsigned int num
= 0;
495 unsigned int nlines
, a
, l
, notstart
, notend
= 0;
497 char *string
, *s
, *s2
, **sp
;
500 exts
= (XpmExtension
*) XpmMalloc(sizeof(XpmExtension
));
501 /* get the whole string */
502 status
= xpmGetString(data
, &string
, &l
);
503 if (status
!= XpmSuccess
) {
507 /* look for the key word XPMEXT, skip lines before this */
508 while ((notstart
= strncmp("XPMEXT", string
, 6))!=NULL
509 && (notend
= strncmp("XPMENDEXT", string
, 9))!=NULL
) {
512 status
= xpmGetString(data
, &string
, &l
);
513 if (status
!= XpmSuccess
) {
519 notend
= strncmp("XPMENDEXT", string
, 9);
520 while (!notstart
&& notend
) {
521 /* there starts an extension */
522 ext
= (XpmExtension
*)
523 XpmRealloc(exts
, (num
+ 1) * sizeof(XpmExtension
));
526 XpmFreeExtensions(exts
, num
);
527 return (XpmNoMemory
);
531 /* skip whitespace and store its name */
536 ext
->name
= (char *) XpmMalloc(l
- a
- 6);
541 XpmFreeExtensions(exts
, num
+ 1);
542 return (XpmNoMemory
);
544 strncpy(ext
->name
, s
+ a
, l
- a
- 6);
546 /* now store the related lines */
548 status
= xpmGetString(data
, &string
, &l
);
549 if (status
!= XpmSuccess
) {
552 XpmFreeExtensions(exts
, num
+ 1);
555 ext
->lines
= (char **) XpmMalloc(sizeof(char *));
557 while ((notstart
= strncmp("XPMEXT", string
, 6))!=NULL
558 && (notend
= strncmp("XPMENDEXT", string
, 9))!=NULL
) {
560 XpmRealloc(ext
->lines
, (nlines
+ 1) * sizeof(char *));
563 ext
->nlines
= nlines
;
564 XpmFreeExtensions(exts
, num
+ 1);
565 return (XpmNoMemory
);
568 ext
->lines
[nlines
] = string
;
571 status
= xpmGetString(data
, &string
, &l
);
572 if (status
!= XpmSuccess
) {
573 ext
->nlines
= nlines
;
574 XpmFreeExtensions(exts
, num
+ 1);
582 ext
->nlines
= nlines
;
597 /* function call in case of error */
599 #define RETURN(status) \
605 * This function parses an Xpm file or data and store the found informations
606 * in an an XpmImage structure which is returned.
609 xpmParseData(data
, image
, info
)
614 /* variables to return */
615 unsigned int width
, height
, ncolors
, cpp
;
616 unsigned int x_hotspot
, y_hotspot
, hotspot
= 0, extensions
= 0;
617 XpmColor
*colorTable
= NULL
;
618 unsigned int *pixelindex
= NULL
;
619 char *hints_cmt
= NULL
;
620 char *colors_cmt
= NULL
;
621 char *pixels_cmt
= NULL
;
625 xpmHashTable hashtable
;
627 cmts
= info
&& (info
->valuemask
& XpmReturnComments
);
632 ErrorStatus
= xpmParseHeader(data
);
633 if (ErrorStatus
!= XpmSuccess
)
634 return (ErrorStatus
);
639 ErrorStatus
= xpmParseValues(data
, &width
, &height
, &ncolors
, &cpp
,
640 &x_hotspot
, &y_hotspot
, &hotspot
,
642 if (ErrorStatus
!= XpmSuccess
)
643 return (ErrorStatus
);
646 * store the hints comment line
649 xpmGetCmt(data
, &hints_cmt
);
655 ErrorStatus
= xpmHashTableInit(&hashtable
);
656 if (ErrorStatus
!= XpmSuccess
)
657 return (ErrorStatus
);
663 ErrorStatus
= xpmParseColors(data
, ncolors
, cpp
, &colorTable
, &hashtable
);
664 if (ErrorStatus
!= XpmSuccess
) {
666 xpmHashTableFree(&hashtable
);
671 * store the colors comment line
674 xpmGetCmt(data
, &colors_cmt
);
677 * read pixels and index them on color number
679 ErrorStatus
= ParsePixels(data
, width
, height
, ncolors
, cpp
, colorTable
,
680 &hashtable
, &pixelindex
);
686 xpmHashTableFree(&hashtable
);
688 if (ErrorStatus
!= XpmSuccess
)
692 * store the pixels comment line
695 xpmGetCmt(data
, &pixels_cmt
);
700 if (info
&& (info
->valuemask
& XpmReturnExtensions
))
702 ErrorStatus
= xpmParseExtensions(data
, &info
->extensions
,
704 if (ErrorStatus
!= XpmSuccess
)
707 info
->extensions
= NULL
;
708 info
->nextensions
= 0;
712 * store found informations in the XpmImage structure
714 image
->width
= width
;
715 image
->height
= height
;
717 image
->ncolors
= ncolors
;
718 image
->colorTable
= colorTable
;
719 image
->data
= pixelindex
;
723 info
->hints_cmt
= hints_cmt
;
724 info
->colors_cmt
= colors_cmt
;
725 info
->pixels_cmt
= pixels_cmt
;
728 info
->x_hotspot
= x_hotspot
;
729 info
->y_hotspot
= y_hotspot
;
730 info
->valuemask
|= XpmHotspot
;
735 /* exit point in case of error, free only locally allocated variables */
738 xpmFreeColorTable(colorTable
, ncolors
);