]>
git.saurik.com Git - wxWidgets.git/blob - src/xpm/parse.c
2 * Copyright (C) 1989-94 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
43 #include "sys$library:ctype.h"
50 #include <X11/Xfuncs.h> /* bzero, bcopy */
59 LFUNC(ParseValues
, int, (xpmData
*data
, unsigned int *width
,
60 unsigned int *height
, unsigned int *ncolors
,
61 unsigned int *cpp
, unsigned int *x_hotspot
,
62 unsigned int *y_hotspot
, unsigned int *hotspot
,
63 unsigned int *extensions
));
65 LFUNC(ParseColors
, int, (xpmData
*data
, unsigned int ncolors
, unsigned int cpp
,
66 XpmColor
**colorTablePtr
, xpmHashTable
*hashtable
));
68 LFUNC(ParsePixels
, int, (xpmData
*data
, unsigned int width
,
69 unsigned int height
, unsigned int ncolors
,
70 unsigned int cpp
, XpmColor
*colorTable
,
71 xpmHashTable
*hashtable
, unsigned int **pixels
));
73 LFUNC(ParseExtensions
, int, (xpmData
*data
, XpmExtension
**extensions
,
74 unsigned int *nextensions
));
76 char *xpmColorKeys
[] = {
77 "s", /* key #1: symbol */
78 "m", /* key #2: mono visual */
79 "g4", /* key #3: 4 grays visual */
80 "g", /* key #4: gray visual */
81 "c", /* key #5: color visual */
85 /* function call in case of error, frees only locally allocated variables */
87 #define RETURN(status) \
89 if (colorTable) xpmFreeColorTable(colorTable, ncolors); \
90 if (pixelindex) XpmFree(pixelindex); \
91 if (hints_cmt) XpmFree(hints_cmt); \
92 if (colors_cmt) XpmFree(colors_cmt); \
93 if (pixels_cmt) XpmFree(pixels_cmt); \
98 * This function parses an Xpm file or data and store the found informations
99 * in an an XpmImage structure which is returned.
102 xpmParseData(xpmData
*data
, XpmImage
*image
, XpmInfo
*info
)
104 /* variables to return */
105 unsigned int width
, height
, ncolors
, cpp
;
106 unsigned int x_hotspot
, y_hotspot
, hotspot
= 0, extensions
= 0;
107 XpmColor
*colorTable
= NULL
;
108 unsigned int *pixelindex
= NULL
;
109 char *hints_cmt
= NULL
;
110 char *colors_cmt
= NULL
;
111 char *pixels_cmt
= NULL
;
115 xpmHashTable hashtable
;
117 cmts
= info
&& (info
->valuemask
& XpmReturnComments
);
122 ErrorStatus
= xpmParseHeader(data
);
123 if (ErrorStatus
!= XpmSuccess
)
124 return (ErrorStatus
);
129 ErrorStatus
= ParseValues(data
, &width
, &height
, &ncolors
, &cpp
,
130 &x_hotspot
, &y_hotspot
, &hotspot
, &extensions
);
131 if (ErrorStatus
!= XpmSuccess
)
132 return (ErrorStatus
);
135 * store the hints comment line
138 xpmGetCmt(data
, &hints_cmt
);
144 ErrorStatus
= xpmHashTableInit(&hashtable
);
145 if (ErrorStatus
!= XpmSuccess
)
146 return (ErrorStatus
);
152 ErrorStatus
= ParseColors(data
, ncolors
, cpp
, &colorTable
, &hashtable
);
153 if (ErrorStatus
!= XpmSuccess
)
157 * store the colors comment line
160 xpmGetCmt(data
, &colors_cmt
);
163 * read pixels and index them on color number
165 ErrorStatus
= ParsePixels(data
, width
, height
, ncolors
, cpp
, colorTable
,
166 &hashtable
, &pixelindex
);
172 xpmHashTableFree(&hashtable
);
174 if (ErrorStatus
!= XpmSuccess
)
178 * store the pixels comment line
181 xpmGetCmt(data
, &pixels_cmt
);
186 if (info
&& (info
->valuemask
& XpmReturnExtensions
))
188 ErrorStatus
= ParseExtensions(data
, &info
->extensions
,
190 if (ErrorStatus
!= XpmSuccess
)
193 info
->extensions
= NULL
;
194 info
->nextensions
= 0;
198 * store found informations in the XpmImage structure
200 image
->width
= width
;
201 image
->height
= height
;
203 image
->ncolors
= ncolors
;
204 image
->colorTable
= colorTable
;
205 image
->data
= pixelindex
;
209 info
->hints_cmt
= hints_cmt
;
210 info
->colors_cmt
= colors_cmt
;
211 info
->pixels_cmt
= pixels_cmt
;
214 info
->x_hotspot
= x_hotspot
;
215 info
->y_hotspot
= y_hotspot
;
216 info
->valuemask
|= XpmHotspot
;
223 ParseValues(xpmData
*data
, unsigned int *width
, unsigned int *height
, unsigned int *ncolors
, unsigned int *cpp
,
224 unsigned int *x_hotspot
, unsigned int *y_hotspot
, unsigned int *hotspot
, unsigned int *extensions
)
229 if (!data
->format
) { /* XPM 2 or 3 */
232 * read values: width, height, ncolors, chars_per_pixel
234 if (!(xpmNextUI(data
, width
) && xpmNextUI(data
, height
)
235 && xpmNextUI(data
, ncolors
) && xpmNextUI(data
, cpp
)))
236 return (XpmFileInvalid
);
239 * read optional information (hotspot and/or XPMEXT) if any
241 l
= xpmNextWord(data
, buf
, BUFSIZ
);
243 *extensions
= (l
== 6 && !strncmp("XPMEXT", buf
, 6));
245 *hotspot
= (xpmNextUI(data
, x_hotspot
)
246 && xpmNextUI(data
, y_hotspot
));
248 *hotspot
= (atoui(buf
, l
, x_hotspot
)
249 && xpmNextUI(data
, y_hotspot
));
250 l
= xpmNextWord(data
, buf
, BUFSIZ
);
251 *extensions
= (l
== 6 && !strncmp("XPMEXT", buf
, 6));
257 * XPM 1 file read values: width, height, ncolors, chars_per_pixel
262 for (i
= 0; i
< 4; i
++) {
263 l
= xpmNextWord(data
, buf
, BUFSIZ
);
264 if (l
!= 7 || strncmp("#define", buf
, 7))
265 return (XpmFileInvalid
);
266 l
= xpmNextWord(data
, buf
, BUFSIZ
);
268 return (XpmFileInvalid
);
269 ptr
= strchr(buf
, '_');
271 return (XpmFileInvalid
);
272 switch (l
- (ptr
- buf
)) {
274 if (!strncmp("_width", ptr
, 6) && !xpmNextUI(data
, width
))
275 return (XpmFileInvalid
);
278 if (!strncmp("_height", ptr
, 7) && !xpmNextUI(data
, height
))
279 return (XpmFileInvalid
);
282 if (!strncmp("_ncolors", ptr
, 8) && !xpmNextUI(data
, ncolors
))
283 return (XpmFileInvalid
);
286 if (!strncmp("_chars_per_pixel", ptr
, 16)
287 && !xpmNextUI(data
, cpp
))
288 return (XpmFileInvalid
);
291 return (XpmFileInvalid
);
293 /* skip the end of line */
303 ParseColors(xpmData
*data
, unsigned int ncolors
, unsigned int cpp
, XpmColor
**colorTablePtr
, xpmHashTable
*hashtable
)
305 unsigned int key
, l
, a
, b
;
306 unsigned int curkey
; /* current color key */
307 unsigned int lastwaskey
; /* key read */
309 char curbuf
[BUFSIZ
]; /* current buffer */
312 XpmColor
*colorTable
;
316 colorTable
= (XpmColor
*) XpmCalloc(ncolors
, sizeof(XpmColor
));
318 return (XpmNoMemory
);
320 if (!data
->format
) { /* XPM 2 or 3 */
321 for (a
= 0, color
= colorTable
; a
< ncolors
; a
++, color
++) {
322 xpmNextString(data
); /* skip the line */
327 color
->string
= (char *) XpmMalloc(cpp
+ 1);
328 if (!color
->string
) {
329 xpmFreeColorTable(colorTable
, ncolors
);
330 return (XpmNoMemory
);
332 for (b
= 0, s
= color
->string
; b
< cpp
; b
++, s
++)
337 * store the string in the hashtable with its color index number
341 xpmHashIntern(hashtable
, color
->string
, HashAtomData(a
));
342 if (ErrorStatus
!= XpmSuccess
) {
343 xpmFreeColorTable(colorTable
, ncolors
);
344 return (ErrorStatus
);
349 * read color keys and values
351 defaults
= (char **) color
;
354 *curbuf
= '\0'; /* init curbuf */
355 while (l
= xpmNextWord(data
, buf
, BUFSIZ
)) {
357 for (key
= 0, sptr
= xpmColorKeys
; key
< NKEYS
; key
++,
359 if ((strlen(*sptr
) == l
) && (!strncmp(*sptr
, buf
, l
)))
362 if (!lastwaskey
&& key
< NKEYS
) { /* open new key */
363 if (curkey
) { /* flush string */
364 s
= (char *) XpmMalloc(strlen(curbuf
) + 1);
366 xpmFreeColorTable(colorTable
, ncolors
);
367 return (XpmNoMemory
);
369 defaults
[curkey
] = s
;
372 curkey
= key
+ 1; /* set new key */
373 *curbuf
= '\0'; /* reset curbuf */
376 if (!curkey
) { /* key without value */
377 xpmFreeColorTable(colorTable
, ncolors
);
378 return (XpmFileInvalid
);
381 strcat(curbuf
, " "); /* append space */
383 strcat(curbuf
, buf
);/* append buf */
387 if (!curkey
) { /* key without value */
388 xpmFreeColorTable(colorTable
, ncolors
);
389 return (XpmFileInvalid
);
391 s
= defaults
[curkey
] = (char *) XpmMalloc(strlen(curbuf
) + 1);
393 xpmFreeColorTable(colorTable
, ncolors
);
394 return (XpmNoMemory
);
399 /* get to the beginning of the first string */
404 for (a
= 0, color
= colorTable
; a
< ncolors
; a
++, color
++) {
409 color
->string
= (char *) XpmMalloc(cpp
+ 1);
410 if (!color
->string
) {
411 xpmFreeColorTable(colorTable
, ncolors
);
412 return (XpmNoMemory
);
414 for (b
= 0, s
= color
->string
; b
< cpp
; b
++, s
++)
419 * store the string in the hashtable with its color index number
423 xpmHashIntern(hashtable
, color
->string
, HashAtomData(a
));
424 if (ErrorStatus
!= XpmSuccess
) {
425 xpmFreeColorTable(colorTable
, ncolors
);
426 return (ErrorStatus
);
433 xpmNextString(data
); /* get to the next string */
434 *curbuf
= '\0'; /* init curbuf */
435 while (l
= xpmNextWord(data
, buf
, BUFSIZ
)) {
437 strcat(curbuf
, " ");/* append space */
439 strcat(curbuf
, buf
); /* append buf */
441 s
= (char *) XpmMalloc(strlen(curbuf
) + 1);
443 xpmFreeColorTable(colorTable
, ncolors
);
444 return (XpmNoMemory
);
448 *curbuf
= '\0'; /* reset curbuf */
450 xpmNextString(data
); /* get to the next string */
453 *colorTablePtr
= colorTable
;
458 ParsePixels(xpmData
*data
, unsigned int width
, unsigned int height
, unsigned int ncolors
,
459 unsigned int cpp
, XpmColor
*colorTable
, xpmHashTable
*hashtable
, unsigned int **pixels
)
461 unsigned int *iptr
, *iptr2
;
462 unsigned int a
, x
, y
;
465 iptr2
= (unsigned int *) XpmMalloc(sizeof(unsigned int) * width
* height
);
469 * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!!
470 * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary
472 iptr2
= (unsigned int *)
473 XpmMalloc((long) sizeof(unsigned int) * (long) width
* (long) height
);
476 return (XpmNoMemory
);
482 case (1): /* Optimize for single character
485 unsigned short colidx
[256];
487 bzero((char *)colidx
, 256 * sizeof(short));
488 for (a
= 0; a
< ncolors
; a
++)
489 colidx
[colorTable
[a
].string
[0]] = a
+ 1;
491 for (y
= 0; y
< height
; y
++) {
493 for (x
= 0; x
< width
; x
++, iptr
++) {
494 int idx
= colidx
[xpmGetC(data
)];
500 return (XpmFileInvalid
);
507 case (2): /* Optimize for double character
511 /* free all allocated pointers at all exits */
512 #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
513 if (cidx[f]) XpmFree(cidx[f]);}
515 /* array of pointers malloced by need */
516 unsigned short *cidx
[256];
519 bzero((char *)cidx
, 256 * sizeof(unsigned short *)); /* init */
520 for (a
= 0; a
< ncolors
; a
++) {
521 char1
= colorTable
[a
].string
[0];
522 if (cidx
[char1
] == NULL
) { /* get new memory */
523 cidx
[char1
] = (unsigned short *)
524 XpmCalloc(256, sizeof(unsigned short));
525 if (cidx
[char1
] == NULL
) { /* new block failed */
528 return (XpmNoMemory
);
531 cidx
[char1
][colorTable
[a
].string
[1]] = a
+ 1;
534 for (y
= 0; y
< height
; y
++) {
536 for (x
= 0; x
< width
; x
++, iptr
++) {
537 int cc1
= xpmGetC(data
);
538 int idx
= cidx
[cc1
][xpmGetC(data
)];
545 return (XpmFileInvalid
);
553 default: /* Non-optimized case of long color
563 for (y
= 0; y
< height
; y
++) {
565 for (x
= 0; x
< width
; x
++, iptr
++) {
566 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
568 slot
= xpmHashSlot(hashtable
, buf
);
569 if (!*slot
) { /* no color matches */
571 return (XpmFileInvalid
);
573 *iptr
= HashColorIndex(slot
);
577 for (y
= 0; y
< height
; y
++) {
579 for (x
= 0; x
< width
; x
++, iptr
++) {
580 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
582 for (a
= 0; a
< ncolors
; a
++)
583 if (!strcmp(colorTable
[a
].string
, buf
))
585 if (a
== ncolors
) { /* no color matches */
587 return (XpmFileInvalid
);
601 ParseExtensions(xpmData
*data
, XpmExtension
**extensions
, unsigned int *nextensions
)
603 XpmExtension
*exts
= NULL
, *ext
;
604 unsigned int num
= 0;
605 unsigned int nlines
, a
, l
, notstart
, notend
= 0;
607 char *string
, *s
, *s2
, **sp
;
610 exts
= (XpmExtension
*) XpmMalloc(sizeof(XpmExtension
));
611 /* get the whole string */
612 status
= xpmGetString(data
, &string
, &l
);
613 if (status
!= XpmSuccess
) {
617 /* look for the key word XPMEXT, skip lines before this */
618 while ((notstart
= strncmp("XPMEXT", string
, 6))
619 && (notend
= strncmp("XPMENDEXT", string
, 9))) {
622 status
= xpmGetString(data
, &string
, &l
);
623 if (status
!= XpmSuccess
) {
629 notend
= strncmp("XPMENDEXT", string
, 9);
630 while (!notstart
&& notend
) {
631 /* there starts an extension */
632 ext
= (XpmExtension
*)
633 XpmRealloc(exts
, (num
+ 1) * sizeof(XpmExtension
));
636 XpmFreeExtensions(exts
, num
);
637 return (XpmNoMemory
);
641 /* skip whitespace and store its name */
646 ext
->name
= (char *) XpmMalloc(l
- a
- 6);
651 XpmFreeExtensions(exts
, num
+ 1);
652 return (XpmNoMemory
);
654 strncpy(ext
->name
, s
+ a
, l
- a
- 6);
656 /* now store the related lines */
658 status
= xpmGetString(data
, &string
, &l
);
659 if (status
!= XpmSuccess
) {
662 XpmFreeExtensions(exts
, num
+ 1);
665 ext
->lines
= (char **) XpmMalloc(sizeof(char *));
667 while ((notstart
= strncmp("XPMEXT", string
, 6))
668 && (notend
= strncmp("XPMENDEXT", string
, 9))) {
670 XpmRealloc(ext
->lines
, (nlines
+ 1) * sizeof(char *));
673 ext
->nlines
= nlines
;
674 XpmFreeExtensions(exts
, num
+ 1);
675 return (XpmNoMemory
);
678 ext
->lines
[nlines
] = string
;
681 status
= xpmGetString(data
, &string
, &l
);
682 if (status
!= XpmSuccess
) {
683 ext
->nlines
= nlines
;
684 XpmFreeExtensions(exts
, num
+ 1);
692 ext
->nlines
= nlines
;