home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / xpm-3.2a / parse.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-16  |  12.0 KB  |  457 lines

  1. /* Copyright 1990,91 GROUPE BULL -- See license conditions in file COPYRIGHT */
  2. /*****************************************************************************\
  3. * parse.c:                                                                    *
  4. *                                                                             *
  5. *  XPM library                                                                *
  6. *  Parse an XPM file or array and store the found informations                *
  7. *  in an an xpmInternAttrib structure which is returned.                      *
  8. *                                                                             *
  9. *  Developed by Arnaud Le Hors                                                *
  10. \*****************************************************************************/
  11.  
  12.  
  13. #include "xpmP.h"
  14. #ifdef VMS
  15. #include "sys$library:ctype.h"
  16. #else
  17. #include <ctype.h>
  18. #endif
  19.  
  20. LFUNC(ParseValues, int, (xpmData *data, unsigned int *width,
  21.              unsigned int *height, unsigned int *ncolors,
  22.              unsigned int *cpp,  unsigned int *x_hotspot,
  23.              unsigned int *y_hotspot, unsigned int *hotspot,
  24.              unsigned int *extensions));
  25.  
  26. LFUNC(ParseColors, int, (xpmData *data, unsigned int ncolors, unsigned int cpp,
  27.              char ****colorTablePtr, xpmHashTable *hashtable));
  28.  
  29. LFUNC(ParsePixels, int, (xpmData *data, unsigned int width, 
  30.              unsigned int height, unsigned int ncolors,
  31.              unsigned int cpp, char ***colorTable,
  32.              xpmHashTable *hashtable, unsigned int **pixels));
  33.  
  34. LFUNC(ParseExtensions, int, (xpmData *data, XpmExtension **extensions,
  35.                  unsigned int *nextensions));
  36.  
  37. char *xpmColorKeys[] =
  38. {
  39.  "s",                    /* key #1: symbol */
  40.  "m",                    /* key #2: mono visual */
  41.  "g4",                    /* key #3: 4 grays visual */
  42.  "g",                    /* key #4: gray visual */
  43.  "c",                    /* key #5: color visual */
  44. };
  45.  
  46.  
  47. /* function call in case of error, frees only locally allocated variables */
  48. #undef RETURN
  49. #define RETURN(status) \
  50.   { if (colorTable) xpmFreeColorTable(colorTable, ncolors); \
  51.     if (pixelindex) free(pixelindex); \
  52.     if (hints_cmt)  free(hints_cmt); \
  53.     if (colors_cmt) free(colors_cmt); \
  54.     if (pixels_cmt) free(pixels_cmt); \
  55.     return(status); }
  56.  
  57. /*
  58.  * This function parses an Xpm file or data and store the found informations
  59.  * in an an xpmInternAttrib structure which is returned.
  60.  */
  61. int
  62. xpmParseData(data, attrib_return, attributes)
  63.     xpmData *data;
  64.     xpmInternAttrib *attrib_return;
  65.     XpmAttributes *attributes;
  66. {
  67.     /* variables to return */
  68.     unsigned int width, height, ncolors, cpp;
  69.     unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
  70.     char ***colorTable = NULL;
  71.     unsigned int *pixelindex = NULL;
  72.     char *hints_cmt = NULL;
  73.     char *colors_cmt = NULL;
  74.     char *pixels_cmt = NULL;
  75.  
  76.     int ErrorStatus;
  77.     xpmHashTable hashtable;
  78.  
  79.     /*
  80.      * read values
  81.      */
  82.     ErrorStatus = ParseValues(data, &width, &height, &ncolors, &cpp,
  83.                   &x_hotspot, &y_hotspot, &hotspot, &extensions);
  84.     if (ErrorStatus != XpmSuccess)
  85.     return(ErrorStatus);
  86.  
  87.     /*
  88.      * store the hints comment line 
  89.      */
  90.     if (attributes && (attributes->valuemask & XpmReturnInfos))
  91.     xpmGetCmt(data, &hints_cmt);
  92.  
  93.     /*
  94.      * init the hastable
  95.      */
  96.     if (USE_HASHTABLE)
  97.     xpmHashTableInit(&hashtable);
  98.     
  99.     /*
  100.      * read colors 
  101.      */
  102.     ErrorStatus = ParseColors(data, ncolors, cpp, &colorTable, &hashtable);
  103.     if (ErrorStatus != XpmSuccess)
  104.     RETURN(ErrorStatus);
  105.  
  106.     /*
  107.      * store the colors comment line 
  108.      */
  109.     if (attributes && (attributes->valuemask & XpmReturnInfos))
  110.     xpmGetCmt(data, &colors_cmt);
  111.  
  112.     /*
  113.      * read pixels and index them on color number 
  114.      */
  115.     ErrorStatus = ParsePixels(data, width, height, ncolors, cpp, colorTable,
  116.                   &hashtable, &pixelindex);
  117.  
  118.     /*
  119.      * free the hastable
  120.      */
  121.     if (USE_HASHTABLE)
  122.     xpmHashTableFree(&hashtable);
  123.     
  124.     if (ErrorStatus != XpmSuccess)
  125.     RETURN(ErrorStatus);
  126.  
  127.     /*
  128.      * store the pixels comment line 
  129.      */
  130.     if (attributes && (attributes->valuemask & XpmReturnInfos))
  131.     xpmGetCmt(data, &pixels_cmt);
  132.  
  133.     /*
  134.      * parse extensions
  135.      */
  136.     if (extensions && attributes
  137.     && (attributes->valuemask & XpmReturnExtensions)) {
  138.     ErrorStatus = ParseExtensions(data, &attributes->extensions,
  139.                       &attributes->nextensions);
  140.     if (ErrorStatus != XpmSuccess)
  141.         RETURN(ErrorStatus);
  142.     }
  143.  
  144.     /*
  145.      * store found informations in the xpmInternAttrib structure 
  146.      */
  147.     attrib_return->width = width;
  148.     attrib_return->height = height;
  149.     attrib_return->cpp = cpp;
  150.     attrib_return->ncolors = ncolors;
  151.     attrib_return->colorTable = colorTable;
  152.     attrib_return->pixelindex = pixelindex;
  153.  
  154.     if (attributes) {
  155.     if (attributes->valuemask & XpmReturnInfos) {
  156.         attributes->hints_cmt = hints_cmt;
  157.         attributes->colors_cmt = colors_cmt;
  158.         attributes->pixels_cmt = pixels_cmt;
  159.     }
  160.     if (hotspot) {
  161.         attributes->x_hotspot = x_hotspot;
  162.         attributes->y_hotspot = y_hotspot;
  163.         attributes->valuemask |= XpmHotspot;
  164.     }
  165.     }
  166.     return (XpmSuccess);
  167. }
  168.  
  169. static int
  170. ParseValues(data, width, height, ncolors, cpp,
  171.         x_hotspot, y_hotspot, hotspot, extensions)
  172.     xpmData *data;
  173.     unsigned int *width, *height, *ncolors, *cpp;
  174.     unsigned int *x_hotspot, *y_hotspot,  *hotspot;
  175.     unsigned int *extensions;
  176. {
  177.     unsigned int l;
  178.     char buf[BUFSIZ];
  179.  
  180.     /*
  181.      * read values: width, height, ncolors, chars_per_pixel 
  182.      */
  183.     if (!(xpmNextUI(data, width) && xpmNextUI(data, height)
  184.       && xpmNextUI(data, ncolors) && xpmNextUI(data, cpp)))
  185.     return(XpmFileInvalid);
  186.  
  187.     /*
  188.      * read optional information (hotspot and/or XPMEXT) if any 
  189.      */
  190.     l = xpmNextWord(data, buf);
  191.     if (l) {
  192.     *extensions = l == 6 && !strncmp("XPMEXT", buf, 6);
  193.     if (*extensions)
  194.         *hotspot = xpmNextUI(data, x_hotspot)
  195.         && xpmNextUI(data, y_hotspot);
  196.     else {
  197.         *hotspot = atoui(buf, l, x_hotspot) && xpmNextUI(data, y_hotspot);
  198.         l = xpmNextWord(data, buf);
  199.         *extensions = l == 6 && !strncmp("XPMEXT", buf, 6);
  200.     }
  201.     }
  202.     return (XpmSuccess);
  203. }
  204.  
  205. static int
  206. ParseColors(data, ncolors, cpp, colorTablePtr, hashtable)
  207.     xpmData *data;
  208.     unsigned int ncolors;
  209.     unsigned int cpp;
  210.     char ****colorTablePtr;        /* Jee, that's something! */
  211.     xpmHashTable *hashtable;
  212. {
  213.     unsigned int key, l, a, b;
  214.     unsigned int curkey;        /* current color key */
  215.     unsigned int lastwaskey;        /* key read */
  216.     char buf[BUFSIZ];
  217.     char curbuf[BUFSIZ];        /* current buffer */
  218.     char ***ct, **cts, **sptr, *s;
  219.     char ***colorTable;
  220.  
  221.     colorTable = (char ***) calloc(ncolors, sizeof(char **));
  222.     if (!colorTable)
  223.     return(XpmNoMemory);
  224.  
  225.     for (a = 0, ct = colorTable; a < ncolors; a++, ct++) {
  226.     xpmNextString(data);        /* skip the line */
  227.     cts = *ct = (char **) calloc((NKEYS + 1), sizeof(char *));
  228.     if (!cts) {
  229.         xpmFreeColorTable(colorTable, ncolors);
  230.         return(XpmNoMemory);
  231.     }
  232.  
  233.     /*
  234.      * read pixel value 
  235.      */
  236.     *cts = (char *) malloc(cpp + 1); /* + 1 for null terminated */
  237.     if (!*cts) {
  238.         xpmFreeColorTable(colorTable, ncolors);
  239.         return(XpmNoMemory);
  240.     }
  241.     for (b = 0, s = *cts; b < cpp; b++, s++)
  242.         *s = xpmGetC(data);
  243.     *s = '\0';
  244.  
  245.     /*
  246.      * tore the string in the hashtable with its color index number
  247.      */
  248.     if (USE_HASHTABLE)
  249.         xpmHashIntern(hashtable, *cts, HashAtomData(a));
  250.  
  251.     /*
  252.      * read color keys and values 
  253.      */
  254.     curkey = 0;
  255.     lastwaskey = 0;
  256.     while (l = xpmNextWord(data, buf)) {
  257.         if (!lastwaskey) {
  258.         for (key = 0, sptr = xpmColorKeys; key < NKEYS; key++, sptr++)
  259.             if ((strlen(*sptr) == l) && (!strncmp(*sptr, buf, l)))
  260.             break;
  261.         }
  262.         if (!lastwaskey && key < NKEYS) { /* open new key */
  263.         if (curkey) {        /* flush string */
  264.             s = cts[curkey] = (char *) malloc(strlen(curbuf) + 1);
  265.             if (!s) {
  266.             xpmFreeColorTable(colorTable, ncolors);
  267.             return(XpmNoMemory);
  268.             }
  269.             strcpy(s, curbuf);
  270.         }
  271.         curkey = key + 1;    /* set new key  */
  272.         *curbuf = '\0';        /* reset curbuf */
  273.         lastwaskey = 1;
  274.         } else {
  275.         if (!curkey) {        /* key without value */
  276.             xpmFreeColorTable(colorTable, ncolors);
  277.             return(XpmFileInvalid);
  278.         }
  279.         if (!lastwaskey)
  280.             strcat(curbuf, " "); /* append space */
  281.         buf[l] = '\0';
  282.         strcat(curbuf, buf);    /* append buf */
  283.         lastwaskey = 0;
  284.         }
  285.     }
  286.     if (!curkey) {            /* key without value */
  287.         xpmFreeColorTable(colorTable, ncolors);
  288.         return(XpmFileInvalid);
  289.     }
  290.     s = cts[curkey] = (char *) malloc(strlen(curbuf) + 1);
  291.     if (!s) {
  292.         xpmFreeColorTable(colorTable, ncolors);
  293.         return(XpmNoMemory);
  294.     }
  295.     strcpy(s, curbuf);
  296.     }
  297.     *colorTablePtr = colorTable;
  298.     return(XpmSuccess);
  299. }
  300.  
  301. static int
  302. ParsePixels(data, width, height, ncolors, cpp, colorTable, hashtable, pixels)
  303.     xpmData *data;
  304.     unsigned int width;
  305.     unsigned int height;
  306.     unsigned int ncolors;
  307.     unsigned int cpp;
  308.     char ***colorTable;
  309.     xpmHashTable *hashtable;
  310.     unsigned int **pixels;
  311. {
  312.     unsigned int *iptr, *iptr2;
  313.     char *s;
  314.     unsigned int a, x, y;
  315.     char buf[BUFSIZ];
  316.  
  317.     iptr2 = (unsigned int *) malloc(sizeof(unsigned int) * width * height);
  318.     if (!iptr2)
  319.     return(XpmNoMemory);
  320.  
  321.     buf[cpp] = '\0';
  322.     iptr = iptr2;
  323.     if (USE_HASHTABLE) {
  324.     xpmHashAtom *slot;
  325.  
  326.     for (y = 0; y < height; y++) {
  327.         xpmNextString(data);
  328.         for (x = 0; x < width; x++, iptr++) {
  329.         for (a = 0, s = buf; a < cpp; a++, s++)
  330.             *s = xpmGetC(data);
  331.         slot = xpmHashSlot(hashtable, buf);
  332.         if (!*slot) {        /* no color matches */
  333.             free(iptr2);
  334.             return(XpmFileInvalid);
  335.         }
  336.         *iptr = HashColorIndex(slot);
  337.         }
  338.     }
  339.     } else {
  340.     for (y = 0; y < height; y++) {
  341.         xpmNextString(data);
  342.         for (x = 0; x < width; x++, iptr++) {
  343.         for (a = 0, s = buf; a < cpp; a++, s++)
  344.             *s = xpmGetC(data);
  345.         for (a = 0; a < ncolors; a++)
  346.             if (!strcmp(colorTable[a][0], buf))
  347.             break;
  348.         if (a == ncolors) {    /* no color matches */
  349.             free(iptr2);
  350.             return(XpmFileInvalid);
  351.         }
  352.         *iptr = a;
  353.         }
  354.     }
  355.     }
  356.     *pixels = iptr2;
  357.     return (XpmSuccess);
  358. }
  359.  
  360. static int
  361. ParseExtensions(data, extensions, nextensions)
  362.     xpmData *data;
  363.     XpmExtension **extensions;
  364.     unsigned int *nextensions;
  365. {
  366.     XpmExtension *exts = NULL, *ext;
  367.     unsigned int num = 0;
  368.     unsigned int nlines, a, l, notstart, notend = 0;
  369.     int status;
  370.     char *string, *s, *s2, **sp;
  371.  
  372.     xpmNextString(data);
  373.     exts = (XpmExtension *) malloc(sizeof(XpmExtension));
  374.     /* get the whole string */
  375.     status = xpmGetString(data, &string, &l);
  376.     if (status != XpmSuccess) {
  377.     free(exts);
  378.     return(status);
  379.     }
  380.     /* look for the key word XPMEXT, skip lines before this */
  381.     while ((notstart = strncmp("XPMEXT", string, 6))
  382.        && (notend = strncmp("XPMENDEXT", string, 9))) {
  383.     free(string);
  384.     xpmNextString(data);
  385.     status = xpmGetString(data, &string, &l);
  386.     if (status != XpmSuccess) {
  387.         free(exts);
  388.         return(status);
  389.     }
  390.     }
  391.     if (!notstart)
  392.     notend = strncmp("XPMENDEXT", string, 9);
  393.     while (!notstart && notend) {
  394.     /* there starts an extension */
  395.     ext = (XpmExtension *) realloc(exts, (num + 1) * sizeof(XpmExtension));
  396.     if (!ext) {
  397.         free(exts);
  398.         return(XpmNoMemory);
  399.     }
  400.     exts = ext;
  401.     ext += num;
  402.     /* skip whitespace and store its name */
  403.     s2 = s = string + 6;
  404.     while (isspace(*s2))
  405.         s2++;
  406.     a = s2 - s;
  407.     ext->name = (char *) malloc(l - a - 6);
  408.     if (!ext->name) {
  409.         free(exts);
  410.         return(XpmNoMemory);
  411.     }
  412.     strncpy(ext->name, s + a, l - a - 6);
  413.     free(string);
  414.     /* now store the related lines */
  415.     xpmNextString(data);
  416.     status = xpmGetString(data, &string, &l);
  417.     if (status != XpmSuccess) {
  418.         free(exts);
  419.         return(status);
  420.     }
  421.     ext->lines = (char **) malloc(sizeof(char *));
  422.     nlines = 0;
  423.     while ((notstart = strncmp("XPMEXT", string, 6))
  424.            && (notend = strncmp("XPMENDEXT", string, 9))) {
  425.         sp = (char **) realloc(ext->lines, (nlines + 1) * sizeof(char *));
  426.         if (!sp) {
  427.         free(exts);
  428.         return(XpmNoMemory);
  429.         }
  430.         ext->lines = sp;
  431.         ext->lines[nlines] = string;
  432.         nlines++;
  433.         xpmNextString(data);
  434.         status = xpmGetString(data, &string, &l);
  435.         if (status != XpmSuccess) {
  436.         free(exts);
  437.         return(status);
  438.         }
  439.     }
  440.     if (!nlines) {
  441.         free(ext->lines);
  442.         ext->lines = NULL;
  443.     }
  444.     ext->nlines = nlines;
  445.     num++;
  446.     }
  447.     if (!num) {
  448.     free(string);
  449.     free(exts);
  450.     exts = NULL;
  451.     } else if (!notend)
  452.     free(string);
  453.     *nextensions = num;
  454.     *extensions = exts;
  455.     return(XpmSuccess);
  456. }
  457.