/* @(#)parse.c 17.1.1.1 (ESO-IPG) 01/25/02 17:26:43 */ /*--------------------------------------------------------------------- * $Date: 93/07/12 18:31:08 $ $Revision: 2.2.6.1 $ *--------------------------------------------------------------------- * * * Copyright (c) 1992, Visual Edge Software Ltd. * * ALL RIGHTS RESERVED. Permission to use, copy, modify, and * distribute this software and its documentation for any purpose * and without fee is hereby granted, provided that the above * copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of Visual Edge Software not be * used in advertising or publicity pertaining to distribution of * the software without specific, written prior permission. The year * included in the notice is the year of the creation of the work. *-------------------------------------------------------------------*/ /* * Copyright 1990, 1991 GROUPE BULL * * Permission to use, copy, modify, and distribute this software and its * documentation for any purpose and without fee is hereby granted, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of GROUPE BULL not be used in advertising * or publicity pertaining to distribution of the software without specific, * written prior permission. GROUPE BULL makes no representations about the * suitability of this software for any purpose. It is provided "as is" * without express or implied warranty. * * GROUPE BULL disclaims all warranties with regard to this software, * including all implied warranties of merchantability and fitness, * in no event shall GROUPE BULL be liable for any special, * indirect or consequential damages or any damages * whatsoever resulting from loss of use, data or profits, * whether in an action of contract, negligence or other tortious * action, arising out of or in connection with the use * or performance of this software. * */ /*****************************************************************************\ * 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 #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; 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); } } 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; } if (!notend) free(string); *nextensions = num; *extensions = exts; return(XpmSuccess); }