]>
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 #define __ORIGINAL_XORG_CODE
51 #include <X11/Xfuncs.h> /* bzero, bcopy */
60 LFUNC(ParseValues
, int, (xpmData
*data
, unsigned int *width
,
61 unsigned int *height
, unsigned int *ncolors
,
62 unsigned int *cpp
, unsigned int *x_hotspot
,
63 unsigned int *y_hotspot
, unsigned int *hotspot
,
64 unsigned int *extensions
));
66 LFUNC(ParseColors
, int, (xpmData
*data
, unsigned int ncolors
, unsigned int cpp
,
67 XpmColor
**colorTablePtr
, xpmHashTable
*hashtable
));
69 LFUNC(ParsePixels
, int, (xpmData
*data
, unsigned int width
,
70 unsigned int height
, unsigned int ncolors
,
71 unsigned int cpp
, XpmColor
*colorTable
,
72 xpmHashTable
*hashtable
, unsigned int **pixels
));
74 LFUNC(ParseExtensions
, int, (xpmData
*data
, XpmExtension
**extensions
,
75 unsigned int *nextensions
));
77 char *xpmColorKeys
[] = {
78 "s", /* key #1: symbol */
79 "m", /* key #2: mono visual */
80 "g4", /* key #3: 4 grays visual */
81 "g", /* key #4: gray visual */
82 "c", /* key #5: color visual */
86 /* function call in case of error, frees only locally allocated variables */
88 #define RETURN(status) \
90 if (colorTable) xpmFreeColorTable(colorTable, ncolors); \
91 if (pixelindex) XpmFree(pixelindex); \
92 if (hints_cmt) XpmFree(hints_cmt); \
93 if (colors_cmt) XpmFree(colors_cmt); \
94 if (pixels_cmt) XpmFree(pixels_cmt); \
99 * This function parses an Xpm file or data and store the found informations
100 * in an an XpmImage structure which is returned.
103 xpmParseData(xpmData
*data
, XpmImage
*image
, XpmInfo
*info
)
105 /* variables to return */
106 unsigned int width
, height
, ncolors
, cpp
;
107 unsigned int x_hotspot
, y_hotspot
, hotspot
= 0, extensions
= 0;
108 XpmColor
*colorTable
= NULL
;
109 unsigned int *pixelindex
= NULL
;
110 char *hints_cmt
= NULL
;
111 char *colors_cmt
= NULL
;
112 char *pixels_cmt
= NULL
;
116 xpmHashTable hashtable
;
118 cmts
= info
&& (info
->valuemask
& XpmReturnComments
);
123 ErrorStatus
= xpmParseHeader(data
);
124 if (ErrorStatus
!= XpmSuccess
)
125 return (ErrorStatus
);
130 ErrorStatus
= ParseValues(data
, &width
, &height
, &ncolors
, &cpp
,
131 &x_hotspot
, &y_hotspot
, &hotspot
, &extensions
);
132 if (ErrorStatus
!= XpmSuccess
)
133 return (ErrorStatus
);
136 * store the hints comment line
139 xpmGetCmt(data
, &hints_cmt
);
145 ErrorStatus
= xpmHashTableInit(&hashtable
);
146 if (ErrorStatus
!= XpmSuccess
)
147 return (ErrorStatus
);
153 ErrorStatus
= ParseColors(data
, ncolors
, cpp
, &colorTable
, &hashtable
);
154 if (ErrorStatus
!= XpmSuccess
)
158 * store the colors comment line
161 xpmGetCmt(data
, &colors_cmt
);
164 * read pixels and index them on color number
166 ErrorStatus
= ParsePixels(data
, width
, height
, ncolors
, cpp
, colorTable
,
167 &hashtable
, &pixelindex
);
173 xpmHashTableFree(&hashtable
);
175 if (ErrorStatus
!= XpmSuccess
)
179 * store the pixels comment line
182 xpmGetCmt(data
, &pixels_cmt
);
187 if (info
&& (info
->valuemask
& XpmReturnExtensions
))
189 ErrorStatus
= ParseExtensions(data
, &info
->extensions
,
191 if (ErrorStatus
!= XpmSuccess
)
194 info
->extensions
= NULL
;
195 info
->nextensions
= 0;
199 * store found informations in the XpmImage structure
201 image
->width
= width
;
202 image
->height
= height
;
204 image
->ncolors
= ncolors
;
205 image
->colorTable
= colorTable
;
206 image
->data
= pixelindex
;
210 info
->hints_cmt
= hints_cmt
;
211 info
->colors_cmt
= colors_cmt
;
212 info
->pixels_cmt
= pixels_cmt
;
215 info
->x_hotspot
= x_hotspot
;
216 info
->y_hotspot
= y_hotspot
;
217 info
->valuemask
|= XpmHotspot
;
224 ParseValues(xpmData
*data
, unsigned int *width
, unsigned int *height
, unsigned int *ncolors
, unsigned int *cpp
,
225 unsigned int *x_hotspot
, unsigned int *y_hotspot
, unsigned int *hotspot
, unsigned int *extensions
)
230 if (!data
->format
) { /* XPM 2 or 3 */
233 * read values: width, height, ncolors, chars_per_pixel
235 if (!(xpmNextUI(data
, width
) && xpmNextUI(data
, height
)
236 && xpmNextUI(data
, ncolors
) && xpmNextUI(data
, cpp
)))
237 return (XpmFileInvalid
);
240 * read optional information (hotspot and/or XPMEXT) if any
242 l
= xpmNextWord(data
, buf
, BUFSIZ
);
244 *extensions
= (l
== 6 && !strncmp("XPMEXT", buf
, 6));
246 *hotspot
= (xpmNextUI(data
, x_hotspot
)
247 && xpmNextUI(data
, y_hotspot
));
249 *hotspot
= (atoui(buf
, l
, x_hotspot
)
250 && xpmNextUI(data
, y_hotspot
));
251 l
= xpmNextWord(data
, buf
, BUFSIZ
);
252 *extensions
= (l
== 6 && !strncmp("XPMEXT", buf
, 6));
258 * XPM 1 file read values: width, height, ncolors, chars_per_pixel
263 for (i
= 0; i
< 4; i
++) {
264 l
= xpmNextWord(data
, buf
, BUFSIZ
);
265 if (l
!= 7 || strncmp("#define", buf
, 7))
266 return (XpmFileInvalid
);
267 l
= xpmNextWord(data
, buf
, BUFSIZ
);
269 return (XpmFileInvalid
);
270 ptr
= strchr(buf
, '_');
272 return (XpmFileInvalid
);
273 switch (l
- (ptr
- buf
)) {
275 if (!strncmp("_width", ptr
, 6) && !xpmNextUI(data
, width
))
276 return (XpmFileInvalid
);
279 if (!strncmp("_height", ptr
, 7) && !xpmNextUI(data
, height
))
280 return (XpmFileInvalid
);
283 if (!strncmp("_ncolors", ptr
, 8) && !xpmNextUI(data
, ncolors
))
284 return (XpmFileInvalid
);
287 if (!strncmp("_chars_per_pixel", ptr
, 16)
288 && !xpmNextUI(data
, cpp
))
289 return (XpmFileInvalid
);
292 return (XpmFileInvalid
);
294 /* skip the end of line */
304 ParseColors(xpmData
*data
, unsigned int ncolors
, unsigned int cpp
, XpmColor
**colorTablePtr
, xpmHashTable
*hashtable
)
306 unsigned int key
, l
, a
, b
;
307 unsigned int curkey
; /* current color key */
308 unsigned int lastwaskey
; /* key read */
310 char curbuf
[BUFSIZ
]; /* current buffer */
313 XpmColor
*colorTable
;
317 colorTable
= (XpmColor
*) XpmCalloc(ncolors
, sizeof(XpmColor
));
319 return (XpmNoMemory
);
321 if (!data
->format
) { /* XPM 2 or 3 */
322 for (a
= 0, color
= colorTable
; a
< ncolors
; a
++, color
++) {
323 xpmNextString(data
); /* skip the line */
328 color
->string
= (char *) XpmMalloc(cpp
+ 1);
329 if (!color
->string
) {
330 xpmFreeColorTable(colorTable
, ncolors
);
331 return (XpmNoMemory
);
333 for (b
= 0, s
= color
->string
; b
< cpp
; b
++, s
++)
338 * store the string in the hashtable with its color index number
342 xpmHashIntern(hashtable
, color
->string
, HashAtomData(a
));
343 if (ErrorStatus
!= XpmSuccess
) {
344 xpmFreeColorTable(colorTable
, ncolors
);
345 return (ErrorStatus
);
350 * read color keys and values
352 defaults
= (char **) color
;
355 *curbuf
= '\0'; /* init curbuf */
356 while (l
= xpmNextWord(data
, buf
, BUFSIZ
)) {
358 for (key
= 0, sptr
= xpmColorKeys
; key
< NKEYS
; key
++,
360 if ((strlen(*sptr
) == l
) && (!strncmp(*sptr
, buf
, l
)))
363 if (!lastwaskey
&& key
< NKEYS
) { /* open new key */
364 if (curkey
) { /* flush string */
365 s
= (char *) XpmMalloc(strlen(curbuf
) + 1);
367 xpmFreeColorTable(colorTable
, ncolors
);
368 return (XpmNoMemory
);
370 defaults
[curkey
] = s
;
373 curkey
= key
+ 1; /* set new key */
374 *curbuf
= '\0'; /* reset curbuf */
377 if (!curkey
) { /* key without value */
378 xpmFreeColorTable(colorTable
, ncolors
);
379 return (XpmFileInvalid
);
382 strcat(curbuf
, " "); /* append space */
384 strcat(curbuf
, buf
);/* append buf */
388 if (!curkey
) { /* key without value */
389 xpmFreeColorTable(colorTable
, ncolors
);
390 return (XpmFileInvalid
);
392 s
= defaults
[curkey
] = (char *) XpmMalloc(strlen(curbuf
) + 1);
394 xpmFreeColorTable(colorTable
, ncolors
);
395 return (XpmNoMemory
);
400 /* get to the beginning of the first string */
405 for (a
= 0, color
= colorTable
; a
< ncolors
; a
++, color
++) {
410 color
->string
= (char *) XpmMalloc(cpp
+ 1);
411 if (!color
->string
) {
412 xpmFreeColorTable(colorTable
, ncolors
);
413 return (XpmNoMemory
);
415 for (b
= 0, s
= color
->string
; b
< cpp
; b
++, s
++)
420 * store the string in the hashtable with its color index number
424 xpmHashIntern(hashtable
, color
->string
, HashAtomData(a
));
425 if (ErrorStatus
!= XpmSuccess
) {
426 xpmFreeColorTable(colorTable
, ncolors
);
427 return (ErrorStatus
);
434 xpmNextString(data
); /* get to the next string */
435 *curbuf
= '\0'; /* init curbuf */
436 while (l
= xpmNextWord(data
, buf
, BUFSIZ
)) {
438 strcat(curbuf
, " ");/* append space */
440 strcat(curbuf
, buf
); /* append buf */
442 s
= (char *) XpmMalloc(strlen(curbuf
) + 1);
444 xpmFreeColorTable(colorTable
, ncolors
);
445 return (XpmNoMemory
);
449 *curbuf
= '\0'; /* reset curbuf */
451 xpmNextString(data
); /* get to the next string */
454 *colorTablePtr
= colorTable
;
459 ParsePixels(xpmData
*data
, unsigned int width
, unsigned int height
, unsigned int ncolors
,
460 unsigned int cpp
, XpmColor
*colorTable
, xpmHashTable
*hashtable
, unsigned int **pixels
)
462 unsigned int *iptr
, *iptr2
;
463 unsigned int a
, x
, y
;
466 iptr2
= (unsigned int *) XpmMalloc(sizeof(unsigned int) * width
* height
);
470 * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!!
471 * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary
473 iptr2
= (unsigned int *)
474 XpmMalloc((long) sizeof(unsigned int) * (long) width
* (long) height
);
477 return (XpmNoMemory
);
483 case (1): /* Optimize for single character
486 unsigned short colidx
[256];
488 bzero((char *)colidx
, 256 * sizeof(short));
489 for (a
= 0; a
< ncolors
; a
++)
490 colidx
[colorTable
[a
].string
[0]] = a
+ 1;
492 for (y
= 0; y
< height
; y
++) {
494 for (x
= 0; x
< width
; x
++, iptr
++) {
495 int idx
= colidx
[xpmGetC(data
)];
501 return (XpmFileInvalid
);
508 case (2): /* Optimize for double character
512 /* free all allocated pointers at all exits */
513 #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
514 if (cidx[f]) XpmFree(cidx[f]);}
516 /* array of pointers malloced by need */
517 unsigned short *cidx
[256];
520 bzero((char *)cidx
, 256 * sizeof(unsigned short *)); /* init */
521 for (a
= 0; a
< ncolors
; a
++) {
522 char1
= colorTable
[a
].string
[0];
523 if (cidx
[char1
] == NULL
) { /* get new memory */
524 cidx
[char1
] = (unsigned short *)
525 XpmCalloc(256, sizeof(unsigned short));
526 if (cidx
[char1
] == NULL
) { /* new block failed */
529 return (XpmNoMemory
);
532 cidx
[char1
][colorTable
[a
].string
[1]] = a
+ 1;
535 for (y
= 0; y
< height
; y
++) {
537 for (x
= 0; x
< width
; x
++, iptr
++) {
538 int cc1
= xpmGetC(data
);
539 int idx
= cidx
[cc1
][xpmGetC(data
)];
546 return (XpmFileInvalid
);
554 default: /* Non-optimized case of long color
564 for (y
= 0; y
< height
; y
++) {
566 for (x
= 0; x
< width
; x
++, iptr
++) {
567 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
569 slot
= xpmHashSlot(hashtable
, buf
);
570 if (!*slot
) { /* no color matches */
572 return (XpmFileInvalid
);
574 *iptr
= HashColorIndex(slot
);
578 for (y
= 0; y
< height
; y
++) {
580 for (x
= 0; x
< width
; x
++, iptr
++) {
581 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
583 for (a
= 0; a
< ncolors
; a
++)
584 if (!strcmp(colorTable
[a
].string
, buf
))
586 if (a
== ncolors
) { /* no color matches */
588 return (XpmFileInvalid
);
602 ParseExtensions(xpmData
*data
, XpmExtension
**extensions
, unsigned int *nextensions
)
604 XpmExtension
*exts
= NULL
, *ext
;
605 unsigned int num
= 0;
606 unsigned int nlines
, a
, l
, notstart
, notend
= 0;
608 char *string
, *s
, *s2
, **sp
;
611 exts
= (XpmExtension
*) XpmMalloc(sizeof(XpmExtension
));
612 /* get the whole string */
613 status
= xpmGetString(data
, &string
, &l
);
614 if (status
!= XpmSuccess
) {
618 /* look for the key word XPMEXT, skip lines before this */
619 while ((notstart
= strncmp("XPMEXT", string
, 6))
620 && (notend
= strncmp("XPMENDEXT", string
, 9))) {
623 status
= xpmGetString(data
, &string
, &l
);
624 if (status
!= XpmSuccess
) {
630 notend
= strncmp("XPMENDEXT", string
, 9);
631 while (!notstart
&& notend
) {
632 /* there starts an extension */
633 ext
= (XpmExtension
*)
634 XpmRealloc(exts
, (num
+ 1) * sizeof(XpmExtension
));
637 XpmFreeExtensions(exts
, num
);
638 return (XpmNoMemory
);
642 /* skip whitespace and store its name */
647 ext
->name
= (char *) XpmMalloc(l
- a
- 6);
652 XpmFreeExtensions(exts
, num
+ 1);
653 return (XpmNoMemory
);
655 strncpy(ext
->name
, s
+ a
, l
- a
- 6);
657 /* now store the related lines */
659 status
= xpmGetString(data
, &string
, &l
);
660 if (status
!= XpmSuccess
) {
663 XpmFreeExtensions(exts
, num
+ 1);
666 ext
->lines
= (char **) XpmMalloc(sizeof(char *));
668 while ((notstart
= strncmp("XPMEXT", string
, 6))
669 && (notend
= strncmp("XPMENDEXT", string
, 9))) {
671 XpmRealloc(ext
->lines
, (nlines
+ 1) * sizeof(char *));
674 ext
->nlines
= nlines
;
675 XpmFreeExtensions(exts
, num
+ 1);
676 return (XpmNoMemory
);
679 ext
->lines
[nlines
] = string
;
682 status
= xpmGetString(data
, &string
, &l
);
683 if (status
!= XpmSuccess
) {
684 ext
->nlines
= nlines
;
685 XpmFreeExtensions(exts
, num
+ 1);
693 ext
->nlines
= nlines
;