]>
git.saurik.com Git - wxWidgets.git/blob - src/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 ptr
= index(ptr
, '_');
116 return (XpmFileInvalid
);
117 switch (l
- (ptr
- buf
)) {
119 if (saw_width
|| strncmp("_width", ptr
, 6)
120 || !xpmNextUI(data
, width
))
121 return (XpmFileInvalid
);
127 if (saw_height
|| strncmp("_height", ptr
, 7)
128 || !xpmNextUI(data
, height
))
129 return (XpmFileInvalid
);
135 if (saw_ncolors
|| strncmp("_ncolors", ptr
, 8)
136 || !xpmNextUI(data
, ncolors
))
137 return (XpmFileInvalid
);
143 if (saw_chars_per_pixel
144 || strncmp("_chars_per_pixel", ptr
, 16)
145 || !xpmNextUI(data
, cpp
))
146 return (XpmFileInvalid
);
148 saw_chars_per_pixel
= True
;
155 /* skip the end of line */
158 if (!saw_width
|| !saw_height
|| !saw_ncolors
|| !saw_chars_per_pixel
)
159 return (XpmFileInvalid
);
168 xpmParseColors(data
, ncolors
, cpp
, colorTablePtr
, hashtable
)
170 unsigned int ncolors
;
172 XpmColor
**colorTablePtr
;
173 xpmHashTable
*hashtable
;
175 unsigned int key
, l
, a
, b
;
176 unsigned int curkey
; /* current color key */
177 unsigned int lastwaskey
; /* key read */
179 char curbuf
[BUFSIZ
]; /* current buffer */
182 XpmColor
*colorTable
;
186 colorTable
= (XpmColor
*) XpmCalloc(ncolors
, sizeof(XpmColor
));
188 return (XpmNoMemory
);
190 if (!data
->format
) { /* XPM 2 or 3 */
191 for (a
= 0, color
= colorTable
; a
< ncolors
; a
++, color
++) {
192 xpmNextString(data
); /* skip the line */
197 color
->string
= (char *) XpmMalloc(cpp
+ 1);
198 if (!color
->string
) {
199 xpmFreeColorTable(colorTable
, ncolors
);
200 return (XpmNoMemory
);
202 for (b
= 0, s
= color
->string
; b
< cpp
; b
++, s
++)
207 * store the string in the hashtable with its color index number
211 xpmHashIntern(hashtable
, color
->string
, HashAtomData(a
));
212 if (ErrorStatus
!= XpmSuccess
) {
213 xpmFreeColorTable(colorTable
, ncolors
);
214 return (ErrorStatus
);
219 * read color keys and values
221 defaults
= (char **) color
;
224 *curbuf
= '\0'; /* init curbuf */
225 while (l
= xpmNextWord(data
, buf
, BUFSIZ
)) {
227 for (key
= 0, sptr
= xpmColorKeys
; key
< NKEYS
; key
++,
229 if ((strlen(*sptr
) == l
) && (!strncmp(*sptr
, buf
, l
)))
232 if (!lastwaskey
&& key
< NKEYS
) { /* open new key */
233 if (curkey
) { /* flush string */
234 s
= (char *) XpmMalloc(strlen(curbuf
) + 1);
236 xpmFreeColorTable(colorTable
, ncolors
);
237 return (XpmNoMemory
);
239 defaults
[curkey
] = s
;
242 curkey
= key
+ 1; /* set new key */
243 *curbuf
= '\0'; /* reset curbuf */
246 if (!curkey
) { /* key without value */
247 xpmFreeColorTable(colorTable
, ncolors
);
248 return (XpmFileInvalid
);
251 strcat(curbuf
, " "); /* append space */
253 strcat(curbuf
, buf
);/* append buf */
257 if (!curkey
) { /* key without value */
258 xpmFreeColorTable(colorTable
, ncolors
);
259 return (XpmFileInvalid
);
261 s
= defaults
[curkey
] = (char *) XpmMalloc(strlen(curbuf
) + 1);
263 xpmFreeColorTable(colorTable
, ncolors
);
264 return (XpmNoMemory
);
269 /* get to the beginning of the first string */
274 for (a
= 0, color
= colorTable
; a
< ncolors
; a
++, color
++) {
279 color
->string
= (char *) XpmMalloc(cpp
+ 1);
280 if (!color
->string
) {
281 xpmFreeColorTable(colorTable
, ncolors
);
282 return (XpmNoMemory
);
284 for (b
= 0, s
= color
->string
; b
< cpp
; b
++, s
++)
289 * store the string in the hashtable with its color index number
293 xpmHashIntern(hashtable
, color
->string
, HashAtomData(a
));
294 if (ErrorStatus
!= XpmSuccess
) {
295 xpmFreeColorTable(colorTable
, ncolors
);
296 return (ErrorStatus
);
303 xpmNextString(data
); /* get to the next string */
304 *curbuf
= '\0'; /* init curbuf */
305 while (l
= xpmNextWord(data
, buf
, BUFSIZ
)) {
307 strcat(curbuf
, " ");/* append space */
309 strcat(curbuf
, buf
); /* append buf */
311 s
= (char *) XpmMalloc(strlen(curbuf
) + 1);
313 xpmFreeColorTable(colorTable
, ncolors
);
314 return (XpmNoMemory
);
318 *curbuf
= '\0'; /* reset curbuf */
320 xpmNextString(data
); /* get to the next string */
323 *colorTablePtr
= colorTable
;
328 ParsePixels(data
, width
, height
, ncolors
, cpp
, colorTable
, hashtable
, pixels
)
332 unsigned int ncolors
;
334 XpmColor
*colorTable
;
335 xpmHashTable
*hashtable
;
336 unsigned int **pixels
;
338 unsigned int *iptr
, *iptr2
;
339 unsigned int a
, x
, y
;
342 iptr2
= (unsigned int *) XpmMalloc(sizeof(unsigned int) * width
* height
);
346 * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!!
347 * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary
349 iptr2
= (unsigned int *)
350 XpmMalloc((long) sizeof(unsigned int) * (long) width
* (long) height
);
353 return (XpmNoMemory
);
359 case (1): /* Optimize for single character
362 unsigned short colidx
[256];
364 bzero((char *)colidx
, 256 * sizeof(short));
365 for (a
= 0; a
< ncolors
; a
++)
366 colidx
[(unsigned char)colorTable
[a
].string
[0]] = a
+ 1;
368 for (y
= 0; y
< height
; y
++) {
370 for (x
= 0; x
< width
; x
++, iptr
++) {
371 int c
= xpmGetC(data
);
373 if (c
> 0 && c
< 256 && colidx
[c
] != 0)
374 *iptr
= colidx
[c
] - 1;
377 return (XpmFileInvalid
);
384 case (2): /* Optimize for double character
388 /* free all allocated pointers at all exits */
389 #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
390 if (cidx[f]) XpmFree(cidx[f]);}
392 /* array of pointers malloced by need */
393 unsigned short *cidx
[256];
396 bzero((char *)cidx
, 256 * sizeof(unsigned short *)); /* init */
397 for (a
= 0; a
< ncolors
; a
++) {
398 char1
= colorTable
[a
].string
[0];
399 if (cidx
[char1
] == NULL
) { /* get new memory */
400 cidx
[char1
] = (unsigned short *)
401 XpmCalloc(256, sizeof(unsigned short));
402 if (cidx
[char1
] == NULL
) { /* new block failed */
405 return (XpmNoMemory
);
408 cidx
[char1
][(unsigned char)colorTable
[a
].string
[1]] = a
+ 1;
411 for (y
= 0; y
< height
; y
++) {
413 for (x
= 0; x
< width
; x
++, iptr
++) {
414 int cc1
= xpmGetC(data
);
415 if (cc1
> 0 && cc1
< 256) {
416 int cc2
= xpmGetC(data
);
417 if (cc2
> 0 && cc2
< 256 &&
418 cidx
[cc1
] && cidx
[cc1
][cc2
] != 0)
419 *iptr
= cidx
[cc1
][cc2
] - 1;
423 return (XpmFileInvalid
);
428 return (XpmFileInvalid
);
436 default: /* Non-optimized case of long color
446 for (y
= 0; y
< height
; y
++) {
448 for (x
= 0; x
< width
; x
++, iptr
++) {
449 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
451 slot
= xpmHashSlot(hashtable
, buf
);
452 if (!*slot
) { /* no color matches */
454 return (XpmFileInvalid
);
456 *iptr
= HashColorIndex(slot
);
460 for (y
= 0; y
< height
; y
++) {
462 for (x
= 0; x
< width
; x
++, iptr
++) {
463 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
465 for (a
= 0; a
< ncolors
; a
++)
466 if (!strcmp(colorTable
[a
].string
, buf
))
468 if (a
== ncolors
) { /* no color matches */
470 return (XpmFileInvalid
);
484 xpmParseExtensions(data
, extensions
, nextensions
)
486 XpmExtension
**extensions
;
487 unsigned int *nextensions
;
489 XpmExtension
*exts
= NULL
, *ext
;
490 unsigned int num
= 0;
491 unsigned int nlines
, a
, l
, notstart
, notend
= 0;
493 char *string
, *s
, *s2
, **sp
;
496 exts
= (XpmExtension
*) XpmMalloc(sizeof(XpmExtension
));
497 /* get the whole string */
498 status
= xpmGetString(data
, &string
, &l
);
499 if (status
!= XpmSuccess
) {
503 /* look for the key word XPMEXT, skip lines before this */
504 while ((notstart
= strncmp("XPMEXT", string
, 6))
505 && (notend
= strncmp("XPMENDEXT", string
, 9))) {
508 status
= xpmGetString(data
, &string
, &l
);
509 if (status
!= XpmSuccess
) {
515 notend
= strncmp("XPMENDEXT", string
, 9);
516 while (!notstart
&& notend
) {
517 /* there starts an extension */
518 ext
= (XpmExtension
*)
519 XpmRealloc(exts
, (num
+ 1) * sizeof(XpmExtension
));
522 XpmFreeExtensions(exts
, num
);
523 return (XpmNoMemory
);
527 /* skip whitespace and store its name */
532 ext
->name
= (char *) XpmMalloc(l
- a
- 6);
537 XpmFreeExtensions(exts
, num
+ 1);
538 return (XpmNoMemory
);
540 strncpy(ext
->name
, s
+ a
, l
- a
- 6);
542 /* now store the related lines */
544 status
= xpmGetString(data
, &string
, &l
);
545 if (status
!= XpmSuccess
) {
548 XpmFreeExtensions(exts
, num
+ 1);
551 ext
->lines
= (char **) XpmMalloc(sizeof(char *));
553 while ((notstart
= strncmp("XPMEXT", string
, 6))
554 && (notend
= strncmp("XPMENDEXT", string
, 9))) {
556 XpmRealloc(ext
->lines
, (nlines
+ 1) * sizeof(char *));
559 ext
->nlines
= nlines
;
560 XpmFreeExtensions(exts
, num
+ 1);
561 return (XpmNoMemory
);
564 ext
->lines
[nlines
] = string
;
567 status
= xpmGetString(data
, &string
, &l
);
568 if (status
!= XpmSuccess
) {
569 ext
->nlines
= nlines
;
570 XpmFreeExtensions(exts
, num
+ 1);
578 ext
->nlines
= nlines
;
593 /* function call in case of error */
595 #define RETURN(status) \
601 * This function parses an Xpm file or data and store the found informations
602 * in an an XpmImage structure which is returned.
605 xpmParseData(data
, image
, info
)
610 /* variables to return */
611 unsigned int width
, height
, ncolors
, cpp
;
612 unsigned int x_hotspot
, y_hotspot
, hotspot
= 0, extensions
= 0;
613 XpmColor
*colorTable
= NULL
;
614 unsigned int *pixelindex
= NULL
;
615 char *hints_cmt
= NULL
;
616 char *colors_cmt
= NULL
;
617 char *pixels_cmt
= NULL
;
621 xpmHashTable hashtable
;
623 cmts
= info
&& (info
->valuemask
& XpmReturnComments
);
628 ErrorStatus
= xpmParseHeader(data
);
629 if (ErrorStatus
!= XpmSuccess
)
630 return (ErrorStatus
);
635 ErrorStatus
= xpmParseValues(data
, &width
, &height
, &ncolors
, &cpp
,
636 &x_hotspot
, &y_hotspot
, &hotspot
,
638 if (ErrorStatus
!= XpmSuccess
)
639 return (ErrorStatus
);
642 * store the hints comment line
645 xpmGetCmt(data
, &hints_cmt
);
651 ErrorStatus
= xpmHashTableInit(&hashtable
);
652 if (ErrorStatus
!= XpmSuccess
)
653 return (ErrorStatus
);
659 ErrorStatus
= xpmParseColors(data
, ncolors
, cpp
, &colorTable
, &hashtable
);
660 if (ErrorStatus
!= XpmSuccess
) {
662 xpmHashTableFree(&hashtable
);
667 * store the colors comment line
670 xpmGetCmt(data
, &colors_cmt
);
673 * read pixels and index them on color number
675 ErrorStatus
= ParsePixels(data
, width
, height
, ncolors
, cpp
, colorTable
,
676 &hashtable
, &pixelindex
);
682 xpmHashTableFree(&hashtable
);
684 if (ErrorStatus
!= XpmSuccess
)
688 * store the pixels comment line
691 xpmGetCmt(data
, &pixels_cmt
);
696 if (info
&& (info
->valuemask
& XpmReturnExtensions
))
698 ErrorStatus
= xpmParseExtensions(data
, &info
->extensions
,
700 if (ErrorStatus
!= XpmSuccess
)
703 info
->extensions
= NULL
;
704 info
->nextensions
= 0;
708 * store found informations in the XpmImage structure
710 image
->width
= width
;
711 image
->height
= height
;
713 image
->ncolors
= ncolors
;
714 image
->colorTable
= colorTable
;
715 image
->data
= pixelindex
;
719 info
->hints_cmt
= hints_cmt
;
720 info
->colors_cmt
= colors_cmt
;
721 info
->pixels_cmt
= pixels_cmt
;
724 info
->x_hotspot
= x_hotspot
;
725 info
->y_hotspot
= y_hotspot
;
726 info
->valuemask
|= XpmHotspot
;
731 /* exit point in case of error, free only locally allocated variables */
734 xpmFreeColorTable(colorTable
, ncolors
);