home *** CD-ROM | disk | FTP | other *** search
- /* Copyright 1990,91 GROUPE BULL -- See license conditions in file COPYRIGHT */
- /*****************************************************************************\
- * parse.c: *
- * *
- * XPM library *
- * Parse an XPM file or array and store the found informations *
- * in an an xpmInternAttrib structure which is returned. *
- * *
- * Developed by Arnaud Le Hors *
- \*****************************************************************************/
-
-
- #include "xpmP.h"
- #ifdef VMS
- #include "sys$library:ctype.h"
- #else
- #include <ctype.h>
- #endif
-
- LFUNC(ParseValues, int, (xpmData *data, unsigned int *width,
- unsigned int *height, unsigned int *ncolors,
- unsigned int *cpp, unsigned int *x_hotspot,
- unsigned int *y_hotspot, unsigned int *hotspot,
- unsigned int *extensions));
-
- LFUNC(ParseColors, int, (xpmData *data, unsigned int ncolors, unsigned int cpp,
- char ****colorTablePtr, xpmHashTable *hashtable));
-
- LFUNC(ParsePixels, int, (xpmData *data, unsigned int width,
- unsigned int height, unsigned int ncolors,
- unsigned int cpp, char ***colorTable,
- xpmHashTable *hashtable, unsigned int **pixels));
-
- LFUNC(ParseExtensions, int, (xpmData *data, XpmExtension **extensions,
- unsigned int *nextensions));
-
- char *xpmColorKeys[] =
- {
- "s", /* key #1: symbol */
- "m", /* key #2: mono visual */
- "g4", /* key #3: 4 grays visual */
- "g", /* key #4: gray visual */
- "c", /* key #5: color visual */
- };
-
-
- /* function call in case of error, frees only locally allocated variables */
- #undef RETURN
- #define RETURN(status) \
- { if (colorTable) xpmFreeColorTable(colorTable, ncolors); \
- if (pixelindex) free(pixelindex); \
- if (hints_cmt) free(hints_cmt); \
- if (colors_cmt) free(colors_cmt); \
- if (pixels_cmt) free(pixels_cmt); \
- return(status); }
-
- /*
- * This function parses an Xpm file or data and store the found informations
- * in an an xpmInternAttrib structure which is returned.
- */
- int
- xpmParseData(data, attrib_return, attributes)
- xpmData *data;
- xpmInternAttrib *attrib_return;
- XpmAttributes *attributes;
- {
- /* variables to return */
- unsigned int width, height, ncolors, cpp;
- unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
- char ***colorTable = NULL;
- unsigned int *pixelindex = NULL;
- char *hints_cmt = NULL;
- char *colors_cmt = NULL;
- char *pixels_cmt = NULL;
-
- int ErrorStatus;
- xpmHashTable hashtable;
-
- /*
- * read values
- */
- ErrorStatus = ParseValues(data, &width, &height, &ncolors, &cpp,
- &x_hotspot, &y_hotspot, &hotspot, &extensions);
- if (ErrorStatus != XpmSuccess)
- return(ErrorStatus);
-
- /*
- * store the hints comment line
- */
- if (attributes && (attributes->valuemask & XpmReturnInfos))
- xpmGetCmt(data, &hints_cmt);
-
- /*
- * init the hastable
- */
- if (USE_HASHTABLE)
- xpmHashTableInit(&hashtable);
-
- /*
- * read colors
- */
- ErrorStatus = ParseColors(data, ncolors, cpp, &colorTable, &hashtable);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
-
- /*
- * store the colors comment line
- */
- if (attributes && (attributes->valuemask & XpmReturnInfos))
- xpmGetCmt(data, &colors_cmt);
-
- /*
- * read pixels and index them on color number
- */
- ErrorStatus = ParsePixels(data, width, height, ncolors, cpp, colorTable,
- &hashtable, &pixelindex);
-
- /*
- * free the hastable
- */
- if (USE_HASHTABLE)
- xpmHashTableFree(&hashtable);
-
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
-
- /*
- * store the pixels comment line
- */
- if (attributes && (attributes->valuemask & XpmReturnInfos))
- xpmGetCmt(data, &pixels_cmt);
-
- /*
- * parse extensions
- */
- if (extensions && attributes
- && (attributes->valuemask & XpmReturnExtensions)) {
- ErrorStatus = ParseExtensions(data, &attributes->extensions,
- &attributes->nextensions);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
- }
-
- /*
- * store found informations in the xpmInternAttrib structure
- */
- attrib_return->width = width;
- attrib_return->height = height;
- attrib_return->cpp = cpp;
- attrib_return->ncolors = ncolors;
- attrib_return->colorTable = colorTable;
- attrib_return->pixelindex = pixelindex;
-
- if (attributes) {
- if (attributes->valuemask & XpmReturnInfos) {
- attributes->hints_cmt = hints_cmt;
- attributes->colors_cmt = colors_cmt;
- attributes->pixels_cmt = pixels_cmt;
- }
- if (hotspot) {
- attributes->x_hotspot = x_hotspot;
- attributes->y_hotspot = y_hotspot;
- attributes->valuemask |= XpmHotspot;
- }
- }
- return (XpmSuccess);
- }
-
- static int
- ParseValues(data, width, height, ncolors, cpp,
- x_hotspot, y_hotspot, hotspot, extensions)
- xpmData *data;
- unsigned int *width, *height, *ncolors, *cpp;
- unsigned int *x_hotspot, *y_hotspot, *hotspot;
- unsigned int *extensions;
- {
- unsigned int l;
- char buf[BUFSIZ];
-
- /*
- * read values: width, height, ncolors, chars_per_pixel
- */
- if (!(xpmNextUI(data, width) && xpmNextUI(data, height)
- && xpmNextUI(data, ncolors) && xpmNextUI(data, cpp)))
- return(XpmFileInvalid);
-
- /*
- * read optional information (hotspot and/or XPMEXT) if any
- */
- l = xpmNextWord(data, buf);
- if (l) {
- *extensions = l == 6 && !strncmp("XPMEXT", buf, 6);
- if (*extensions)
- *hotspot = xpmNextUI(data, x_hotspot)
- && xpmNextUI(data, y_hotspot);
- else {
- *hotspot = atoui(buf, l, x_hotspot) && xpmNextUI(data, y_hotspot);
- l = xpmNextWord(data, buf);
- *extensions = l == 6 && !strncmp("XPMEXT", buf, 6);
- }
- }
- return (XpmSuccess);
- }
-
- static int
- ParseColors(data, ncolors, cpp, colorTablePtr, hashtable)
- xpmData *data;
- unsigned int ncolors;
- unsigned int cpp;
- char ****colorTablePtr; /* Jee, that's something! */
- xpmHashTable *hashtable;
- {
- unsigned int key, l, a, b;
- unsigned int curkey; /* current color key */
- unsigned int lastwaskey; /* key read */
- char buf[BUFSIZ];
- char curbuf[BUFSIZ]; /* current buffer */
- char ***ct, **cts, **sptr, *s;
- char ***colorTable;
-
- colorTable = (char ***) calloc(ncolors, sizeof(char **));
- if (!colorTable)
- return(XpmNoMemory);
-
- for (a = 0, ct = colorTable; a < ncolors; a++, ct++) {
- xpmNextString(data); /* skip the line */
- cts = *ct = (char **) calloc((NKEYS + 1), sizeof(char *));
- if (!cts) {
- xpmFreeColorTable(colorTable, ncolors);
- return(XpmNoMemory);
- }
-
- /*
- * read pixel value
- */
- *cts = (char *) malloc(cpp + 1); /* + 1 for null terminated */
- if (!*cts) {
- xpmFreeColorTable(colorTable, ncolors);
- return(XpmNoMemory);
- }
- for (b = 0, s = *cts; b < cpp; b++, s++)
- *s = xpmGetC(data);
- *s = '\0';
-
- /*
- * tore the string in the hashtable with its color index number
- */
- if (USE_HASHTABLE)
- xpmHashIntern(hashtable, *cts, HashAtomData(a));
-
- /*
- * read color keys and values
- */
- curkey = 0;
- lastwaskey = 0;
- while (l = xpmNextWord(data, buf)) {
- if (!lastwaskey) {
- for (key = 0, sptr = xpmColorKeys; key < NKEYS; key++, sptr++)
- if ((strlen(*sptr) == l) && (!strncmp(*sptr, buf, l)))
- break;
- }
- if (!lastwaskey && key < NKEYS) { /* open new key */
- if (curkey) { /* flush string */
- s = cts[curkey] = (char *) malloc(strlen(curbuf) + 1);
- if (!s) {
- xpmFreeColorTable(colorTable, ncolors);
- return(XpmNoMemory);
- }
- strcpy(s, curbuf);
- }
- curkey = key + 1; /* set new key */
- *curbuf = '\0'; /* reset curbuf */
- lastwaskey = 1;
- } else {
- if (!curkey) { /* key without value */
- xpmFreeColorTable(colorTable, ncolors);
- return(XpmFileInvalid);
- }
- if (!lastwaskey)
- strcat(curbuf, " "); /* append space */
- buf[l] = '\0';
- strcat(curbuf, buf); /* append buf */
- lastwaskey = 0;
- }
- }
- if (!curkey) { /* key without value */
- xpmFreeColorTable(colorTable, ncolors);
- return(XpmFileInvalid);
- }
- s = cts[curkey] = (char *) malloc(strlen(curbuf) + 1);
- if (!s) {
- xpmFreeColorTable(colorTable, ncolors);
- return(XpmNoMemory);
- }
- strcpy(s, curbuf);
- }
- *colorTablePtr = colorTable;
- return(XpmSuccess);
- }
-
- static int
- ParsePixels(data, width, height, ncolors, cpp, colorTable, hashtable, pixels)
- xpmData *data;
- unsigned int width;
- unsigned int height;
- unsigned int ncolors;
- unsigned int cpp;
- char ***colorTable;
- xpmHashTable *hashtable;
- unsigned int **pixels;
- {
- unsigned int *iptr, *iptr2;
- char *s;
- unsigned int a, x, y;
- char buf[BUFSIZ];
-
- iptr2 = (unsigned int *) malloc(sizeof(unsigned int) * width * height);
- if (!iptr2)
- return(XpmNoMemory);
-
- buf[cpp] = '\0';
- iptr = iptr2;
- if (USE_HASHTABLE) {
- xpmHashAtom *slot;
-
- for (y = 0; y < height; y++) {
- xpmNextString(data);
- for (x = 0; x < width; x++, iptr++) {
- for (a = 0, s = buf; a < cpp; a++, s++)
- *s = xpmGetC(data);
- slot = xpmHashSlot(hashtable, buf);
- if (!*slot) { /* no color matches */
- free(iptr2);
- return(XpmFileInvalid);
- }
- *iptr = HashColorIndex(slot);
- }
- }
- } else {
- for (y = 0; y < height; y++) {
- xpmNextString(data);
- for (x = 0; x < width; x++, iptr++) {
- for (a = 0, s = buf; a < cpp; a++, s++)
- *s = xpmGetC(data);
- for (a = 0; a < ncolors; a++)
- if (!strcmp(colorTable[a][0], buf))
- break;
- if (a == ncolors) { /* no color matches */
- free(iptr2);
- return(XpmFileInvalid);
- }
- *iptr = a;
- }
- }
- }
- *pixels = iptr2;
- return (XpmSuccess);
- }
-
- static int
- ParseExtensions(data, extensions, nextensions)
- xpmData *data;
- XpmExtension **extensions;
- unsigned int *nextensions;
- {
- XpmExtension *exts = NULL, *ext;
- unsigned int num = 0;
- unsigned int nlines, a, l, notstart, notend = 0;
- int status;
- char *string, *s, *s2, **sp;
-
- xpmNextString(data);
- exts = (XpmExtension *) malloc(sizeof(XpmExtension));
- /* get the whole string */
- status = xpmGetString(data, &string, &l);
- if (status != XpmSuccess) {
- free(exts);
- return(status);
- }
- /* look for the key word XPMEXT, skip lines before this */
- while ((notstart = strncmp("XPMEXT", string, 6))
- && (notend = strncmp("XPMENDEXT", string, 9))) {
- free(string);
- xpmNextString(data);
- status = xpmGetString(data, &string, &l);
- if (status != XpmSuccess) {
- free(exts);
- return(status);
- }
- }
- if (!notstart)
- notend = strncmp("XPMENDEXT", string, 9);
- while (!notstart && notend) {
- /* there starts an extension */
- ext = (XpmExtension *) realloc(exts, (num + 1) * sizeof(XpmExtension));
- if (!ext) {
- free(exts);
- return(XpmNoMemory);
- }
- exts = ext;
- ext += num;
- /* skip whitespace and store its name */
- s2 = s = string + 6;
- while (isspace(*s2))
- s2++;
- a = s2 - s;
- ext->name = (char *) malloc(l - a - 6);
- if (!ext->name) {
- free(exts);
- return(XpmNoMemory);
- }
- strncpy(ext->name, s + a, l - a - 6);
- free(string);
- /* now store the related lines */
- xpmNextString(data);
- status = xpmGetString(data, &string, &l);
- if (status != XpmSuccess) {
- free(exts);
- return(status);
- }
- ext->lines = (char **) malloc(sizeof(char *));
- nlines = 0;
- while ((notstart = strncmp("XPMEXT", string, 6))
- && (notend = strncmp("XPMENDEXT", string, 9))) {
- sp = (char **) realloc(ext->lines, (nlines + 1) * sizeof(char *));
- if (!sp) {
- free(exts);
- return(XpmNoMemory);
- }
- ext->lines = sp;
- ext->lines[nlines] = string;
- nlines++;
- xpmNextString(data);
- status = xpmGetString(data, &string, &l);
- if (status != XpmSuccess) {
- free(exts);
- return(status);
- }
- }
- if (!nlines) {
- free(ext->lines);
- ext->lines = NULL;
- }
- ext->nlines = nlines;
- num++;
- }
- if (!num) {
- free(string);
- free(exts);
- exts = NULL;
- } else if (!notend)
- free(string);
- *nextensions = num;
- *extensions = exts;
- return(XpmSuccess);
- }
-