]>
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
;