diff options
Diffstat (limited to 'libXpm/src')
-rw-r--r-- | libXpm/src/CrBufFrI.c | 898 | ||||
-rw-r--r-- | libXpm/src/CrDatFrI.c | 806 | ||||
-rw-r--r-- | libXpm/src/Makefile.am | 86 | ||||
-rw-r--r-- | libXpm/src/RdFToI.c | 548 | ||||
-rw-r--r-- | libXpm/src/WrFFrI.c | 726 | ||||
-rw-r--r-- | libXpm/src/XpmI.h | 664 | ||||
-rw-r--r-- | libXpm/src/create.c | 5034 | ||||
-rw-r--r-- | libXpm/src/data.c | 958 | ||||
-rw-r--r-- | libXpm/src/parse.c | 1608 | ||||
-rw-r--r-- | libXpm/src/scan.c | 2048 |
10 files changed, 6688 insertions, 6688 deletions
diff --git a/libXpm/src/CrBufFrI.c b/libXpm/src/CrBufFrI.c index b191037dc..113a45c1e 100644 --- a/libXpm/src/CrBufFrI.c +++ b/libXpm/src/CrBufFrI.c @@ -1,449 +1,449 @@ -/*
- * Copyright (C) 1989-95 GROUPE BULL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of GROUPE BULL shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from GROUPE BULL.
- */
-
-/*****************************************************************************\
-* CrBufFrI.c: *
-* *
-* XPM library *
-* Scan an image and possibly its mask and create an XPM buffer *
-* *
-* Developed by Arnaud Le Hors *
-\*****************************************************************************/
-
-/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "XpmI.h"
-
-LFUNC(WriteColors, int, (char **dataptr, unsigned int *data_size,
- unsigned int *used_size, XpmColor *colors,
- unsigned int ncolors, unsigned int cpp));
-
-LFUNC(WritePixels, void, (char *dataptr, unsigned int data_size,
- unsigned int *used_size,
- unsigned int width, unsigned int height,
- unsigned int cpp, unsigned int *pixels,
- XpmColor *colors));
-
-LFUNC(WriteExtensions, void, (char *dataptr, unsigned int data_size,
- unsigned int *used_size,
- XpmExtension *ext, unsigned int num));
-
-LFUNC(ExtensionsSize, unsigned int, (XpmExtension *ext, unsigned int num));
-LFUNC(CommentsSize, int, (XpmInfo *info));
-
-int
-XpmCreateBufferFromImage(
- Display *display,
- char **buffer_return,
- XImage *image,
- XImage *shapeimage,
- XpmAttributes *attributes)
-{
- XpmImage xpmimage;
- XpmInfo info;
- int ErrorStatus;
-
- /* initialize return value */
- if (buffer_return)
- *buffer_return = NULL;
-
- /* create an XpmImage from the image */
- ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
- &xpmimage, attributes);
- if (ErrorStatus != XpmSuccess)
- return (ErrorStatus);
-
- /* create the buffer from the XpmImage */
- if (attributes) {
- xpmSetInfo(&info, attributes);
- ErrorStatus =
- XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, &info);
- } else
- ErrorStatus =
- XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, NULL);
-
- /* free the XpmImage */
- XpmFreeXpmImage(&xpmimage);
-
- return (ErrorStatus);
-}
-
-
-#undef RETURN
-#define RETURN(status) \
-do \
-{ \
- ErrorStatus = status; \
- goto error; \
-}while(0)
-
-int
-XpmCreateBufferFromXpmImage(
- char **buffer_return,
- XpmImage *image,
- XpmInfo *info)
-{
- /* calculation variables */
- int ErrorStatus;
- char buf[BUFSIZ];
- unsigned int cmts, extensions, ext_size = 0;
- unsigned int l, cmt_size = 0;
- char *ptr = NULL, *p;
- unsigned int ptr_size, used_size, tmp;
-
- *buffer_return = NULL;
-
- cmts = info && (info->valuemask & XpmComments);
- extensions = info && (info->valuemask & XpmExtensions)
- && info->nextensions;
-
- /* compute the extensions and comments size */
- if (extensions)
- ext_size = ExtensionsSize(info->extensions, info->nextensions);
- if (cmts)
- cmt_size = CommentsSize(info);
-
- /* write the header line */
-#ifndef VOID_SPRINTF
- used_size =
-#endif
- sprintf(buf, "/* XPM */\nstatic char * image_name[] = {\n");
-#ifdef VOID_SPRINTF
- used_size = strlen(buf);
-#endif
- ptr_size = used_size + ext_size + cmt_size + 1; /* ptr_size can't be 0 */
- if(ptr_size <= used_size ||
- ptr_size <= ext_size ||
- ptr_size <= cmt_size)
- {
- return XpmNoMemory;
- }
- ptr = (char *) XpmMalloc(ptr_size);
- if (!ptr)
- return XpmNoMemory;
- strcpy(ptr, buf);
-
- /* write the values line */
- if (cmts && info->hints_cmt) {
-#ifndef VOID_SPRINTF
- used_size +=
-#endif
- snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->hints_cmt);
-#ifdef VOID_SPRINTF
- used_size += strlen(info->hints_cmt) + 5;
-#endif
- }
-#ifndef VOID_SPRINTF
- l =
-#endif
- sprintf(buf, "\"%d %d %d %d", image->width, image->height,
- image->ncolors, image->cpp);
-#ifdef VOID_SPRINTF
- l = strlen(buf);
-#endif
-
- if (info && (info->valuemask & XpmHotspot)) {
-#ifndef VOID_SPRINTF
- l +=
-#endif
- snprintf(buf + l, sizeof(buf)-l, " %d %d", info->x_hotspot, info->y_hotspot);
-#ifdef VOID_SPRINTF
- l = strlen(buf);
-#endif
- }
- if (extensions) {
-#ifndef VOID_SPRINTF
- l +=
-#endif
- sprintf(buf + l, " XPMEXT");
-#ifdef VOID_SPRINTF
- l = strlen(buf);
-#endif
- }
-#ifndef VOID_SPRINTF
- l +=
-#endif
- sprintf(buf + l, "\",\n");
-#ifdef VOID_SPRINTF
- l = strlen(buf);
-#endif
- ptr_size += l;
- if(ptr_size <= l)
- RETURN(XpmNoMemory);
- p = (char *) XpmRealloc(ptr, ptr_size);
- if (!p)
- RETURN(XpmNoMemory);
- ptr = p;
- strcpy(ptr + used_size, buf);
- used_size += l;
-
- /* write colors */
- if (cmts && info->colors_cmt) {
-#ifndef VOID_SPRINTF
- used_size +=
-#endif
- snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->colors_cmt);
-#ifdef VOID_SPRINTF
- used_size += strlen(info->colors_cmt) + 5;
-#endif
- }
- ErrorStatus = WriteColors(&ptr, &ptr_size, &used_size,
- image->colorTable, image->ncolors, image->cpp);
-
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
-
- /*
- * now we know the exact size we need, realloc the data
- * 4 = 1 (for '"') + 3 (for '",\n')
- * 1 = - 2 (because the last line does not end with ',\n') + 3 (for '};\n')
- */
- if(image->width > UINT_MAX / image->cpp ||
- (tmp = image->width * image->cpp + 4) <= 4 ||
- image->height > UINT_MAX / tmp ||
- (tmp = image->height * tmp + 1) <= 1 ||
- (ptr_size += tmp) <= tmp)
- RETURN(XpmNoMemory);
-
- p = (char *) XpmRealloc(ptr, ptr_size);
- if (!p)
- RETURN(XpmNoMemory);
- ptr = p;
-
- /* print pixels */
- if (cmts && info->pixels_cmt) {
-#ifndef VOID_SPRINTF
- used_size +=
-#endif
- snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->pixels_cmt);
-#ifdef VOID_SPRINTF
- used_size += strlen(info->pixels_cmt) + 5;
-#endif
- }
- WritePixels(ptr + used_size, ptr_size - used_size, &used_size, image->width, image->height,
- image->cpp, image->data, image->colorTable);
-
- /* print extensions */
- if (extensions)
- WriteExtensions(ptr + used_size, ptr_size-used_size, &used_size,
- info->extensions, info->nextensions);
-
- /* close the array */
- strcpy(ptr + used_size, "};\n");
-
- *buffer_return = ptr;
-
- return (XpmSuccess);
-
-/* exit point in case of error, free only locally allocated variables */
-error:
- if (ptr)
- XpmFree(ptr);
- return (ErrorStatus);
-}
-
-
-static int
-WriteColors(
- char **dataptr,
- unsigned int *data_size,
- unsigned int *used_size,
- XpmColor *colors,
- unsigned int ncolors,
- unsigned int cpp)
-{
- char buf[BUFSIZ] = {0};
- unsigned int a, key, l;
- char *s, *s2;
- char **defaults;
-
- *buf = '"';
- for (a = 0; a < ncolors; a++, colors++) {
-
- defaults = (char **) colors;
- s = buf + 1;
- if(cpp > (sizeof(buf) - (s-buf)))
- return(XpmNoMemory);
- strncpy(s, *defaults++, cpp);
- s += cpp;
-
- for (key = 1; key <= NKEYS; key++, defaults++) {
- if ((s2 = *defaults)) {
-#ifndef VOID_SPRINTF
- s +=
-#endif
- /* assume C99 compliance */
- snprintf(s, sizeof(buf) - (s-buf), "\t%s %s", xpmColorKeys[key - 1], s2);
-#ifdef VOID_SPRINTF
- s += strlen(s);
-#endif
- /* now let's check if s points out-of-bounds */
- if((s-buf) > sizeof(buf))
- return(XpmNoMemory);
- }
- }
- if(sizeof(buf) - (s-buf) < 4)
- return(XpmNoMemory);
- strcpy(s, "\",\n");
- l = s + 3 - buf;
- if( *data_size >= UINT_MAX-l ||
- *data_size + l <= *used_size ||
- (*data_size + l - *used_size) <= sizeof(buf))
- return(XpmNoMemory);
- s = (char *) XpmRealloc(*dataptr, *data_size + l);
- if (!s)
- return (XpmNoMemory);
- *data_size += l;
- strcpy(s + *used_size, buf);
- *used_size += l;
- *dataptr = s;
- }
- return (XpmSuccess);
-}
-
-static void
-WritePixels(
- char *dataptr,
- unsigned int data_size,
- unsigned int *used_size,
- unsigned int width,
- unsigned int height,
- unsigned int cpp,
- unsigned int *pixels,
- XpmColor *colors)
-{
- char *s = dataptr;
- unsigned int x, y, h;
-
- if(height <= 1)
- return;
-
- h = height - 1;
- for (y = 0; y < h; y++) {
- *s++ = '"';
- for (x = 0; x < width; x++, pixels++) {
- if(cpp >= (data_size - (s-dataptr)))
- return;
- strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? :-\ */
- s += cpp;
- }
- if((data_size - (s-dataptr)) < 4)
- return;
- strcpy(s, "\",\n");
- s += 3;
- }
- /* duplicate some code to avoid a test in the loop */
- *s++ = '"';
- for (x = 0; x < width; x++, pixels++) {
- if(cpp >= (data_size - (s-dataptr)))
- return;
- strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? */
- s += cpp;
- }
- *s++ = '"';
- *used_size += s - dataptr;
-}
-
-static unsigned int
-ExtensionsSize(
- XpmExtension *ext,
- unsigned int num)
-{
- unsigned int x, y, a, size;
- char **line;
-
- size = 0;
- if(num == 0)
- return(0); /* ok? */
- for (x = 0; x < num; x++, ext++) {
- /* 11 = 10 (for ',\n"XPMEXT ') + 1 (for '"') */
- size += strlen(ext->name) + 11;
- a = ext->nlines; /* how can we trust ext->nlines to be not out-of-bounds? */
- for (y = 0, line = ext->lines; y < a; y++, line++)
- /* 4 = 3 (for ',\n"') + 1 (for '"') */
- size += strlen(*line) + 4;
- }
- /* 13 is for ',\n"XPMENDEXT"' */
- if(size > UINT_MAX - 13) /* unlikely */
- return(0);
- return size + 13;
-}
-
-static void
-WriteExtensions(
- char *dataptr,
- unsigned int data_size,
- unsigned int *used_size,
- XpmExtension *ext,
- unsigned int num)
-{
- unsigned int x, y, a;
- char **line;
- char *s = dataptr;
-
- for (x = 0; x < num; x++, ext++) {
-#ifndef VOID_SPRINTF
- s +=
-#endif
- snprintf(s, data_size - (s-dataptr), ",\n\"XPMEXT %s\"", ext->name);
-#ifdef VOID_SPRINTF
- s += strlen(ext->name) + 11;
-#endif
- a = ext->nlines;
- for (y = 0, line = ext->lines; y < a; y++, line++) {
-#ifndef VOID_SPRINTF
- s +=
-#endif
- snprintf(s, data_size - (s-dataptr), ",\n\"%s\"", *line);
-#ifdef VOID_SPRINTF
- s += strlen(*line) + 4;
-#endif
- }
- }
- strncpy(s, ",\n\"XPMENDEXT\"", data_size - (s-dataptr)-1);
- *used_size += s - dataptr + 13;
-}
-
-static int
-CommentsSize(XpmInfo *info)
-{
- int size = 0;
-
- /* 5 = 2 (for "/_*") + 3 (for "*_/\n") */
- /* wrap possible but *very* unlikely */
- if (info->hints_cmt)
- size += 5 + strlen(info->hints_cmt);
-
- if (info->colors_cmt)
- size += 5 + strlen(info->colors_cmt);
-
- if (info->pixels_cmt)
- size += 5 + strlen(info->pixels_cmt);
-
- return size;
-}
+/* + * Copyright (C) 1989-95 GROUPE BULL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of GROUPE BULL shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from GROUPE BULL. + */ + +/*****************************************************************************\ +* CrBufFrI.c: * +* * +* XPM library * +* Scan an image and possibly its mask and create an XPM buffer * +* * +* Developed by Arnaud Le Hors * +\*****************************************************************************/ + +/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "XpmI.h" + +LFUNC(WriteColors, int, (char **dataptr, unsigned int *data_size, + unsigned int *used_size, XpmColor *colors, + unsigned int ncolors, unsigned int cpp)); + +LFUNC(WritePixels, void, (char *dataptr, unsigned int data_size, + unsigned int *used_size, + unsigned int width, unsigned int height, + unsigned int cpp, unsigned int *pixels, + XpmColor *colors)); + +LFUNC(WriteExtensions, void, (char *dataptr, unsigned int data_size, + unsigned int *used_size, + XpmExtension *ext, unsigned int num)); + +LFUNC(ExtensionsSize, unsigned int, (XpmExtension *ext, unsigned int num)); +LFUNC(CommentsSize, int, (XpmInfo *info)); + +int +XpmCreateBufferFromImage( + Display *display, + char **buffer_return, + XImage *image, + XImage *shapeimage, + XpmAttributes *attributes) +{ + XpmImage xpmimage; + XpmInfo info; + int ErrorStatus; + + /* initialize return value */ + if (buffer_return) + *buffer_return = NULL; + + /* create an XpmImage from the image */ + ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage, + &xpmimage, attributes); + if (ErrorStatus != XpmSuccess) + return (ErrorStatus); + + /* create the buffer from the XpmImage */ + if (attributes) { + xpmSetInfo(&info, attributes); + ErrorStatus = + XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, &info); + } else + ErrorStatus = + XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, NULL); + + /* free the XpmImage */ + XpmFreeXpmImage(&xpmimage); + + return (ErrorStatus); +} + + +#undef RETURN +#define RETURN(status) \ +do \ +{ \ + ErrorStatus = status; \ + goto error; \ +}while(0) + +int +XpmCreateBufferFromXpmImage( + char **buffer_return, + XpmImage *image, + XpmInfo *info) +{ + /* calculation variables */ + int ErrorStatus; + char buf[BUFSIZ]; + unsigned int cmts, extensions, ext_size = 0; + unsigned int l, cmt_size = 0; + char *ptr = NULL, *p; + unsigned int ptr_size, used_size, tmp; + + *buffer_return = NULL; + + cmts = info && (info->valuemask & XpmComments); + extensions = info && (info->valuemask & XpmExtensions) + && info->nextensions; + + /* compute the extensions and comments size */ + if (extensions) + ext_size = ExtensionsSize(info->extensions, info->nextensions); + if (cmts) + cmt_size = CommentsSize(info); + + /* write the header line */ +#ifndef VOID_SPRINTF + used_size = +#endif + sprintf(buf, "/* XPM */\nstatic char * image_name[] = {\n"); +#ifdef VOID_SPRINTF + used_size = strlen(buf); +#endif + ptr_size = used_size + ext_size + cmt_size + 1; /* ptr_size can't be 0 */ + if(ptr_size <= used_size || + ptr_size <= ext_size || + ptr_size <= cmt_size) + { + return XpmNoMemory; + } + ptr = (char *) XpmMalloc(ptr_size); + if (!ptr) + return XpmNoMemory; + strcpy(ptr, buf); + + /* write the values line */ + if (cmts && info->hints_cmt) { +#ifndef VOID_SPRINTF + used_size += +#endif + snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->hints_cmt); +#ifdef VOID_SPRINTF + used_size += strlen(info->hints_cmt) + 5; +#endif + } +#ifndef VOID_SPRINTF + l = +#endif + sprintf(buf, "\"%d %d %d %d", image->width, image->height, + image->ncolors, image->cpp); +#ifdef VOID_SPRINTF + l = strlen(buf); +#endif + + if (info && (info->valuemask & XpmHotspot)) { +#ifndef VOID_SPRINTF + l += +#endif + snprintf(buf + l, sizeof(buf)-l, " %d %d", info->x_hotspot, info->y_hotspot); +#ifdef VOID_SPRINTF + l = strlen(buf); +#endif + } + if (extensions) { +#ifndef VOID_SPRINTF + l += +#endif + sprintf(buf + l, " XPMEXT"); +#ifdef VOID_SPRINTF + l = strlen(buf); +#endif + } +#ifndef VOID_SPRINTF + l += +#endif + sprintf(buf + l, "\",\n"); +#ifdef VOID_SPRINTF + l = strlen(buf); +#endif + ptr_size += l; + if(ptr_size <= l) + RETURN(XpmNoMemory); + p = (char *) XpmRealloc(ptr, ptr_size); + if (!p) + RETURN(XpmNoMemory); + ptr = p; + strcpy(ptr + used_size, buf); + used_size += l; + + /* write colors */ + if (cmts && info->colors_cmt) { +#ifndef VOID_SPRINTF + used_size += +#endif + snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->colors_cmt); +#ifdef VOID_SPRINTF + used_size += strlen(info->colors_cmt) + 5; +#endif + } + ErrorStatus = WriteColors(&ptr, &ptr_size, &used_size, + image->colorTable, image->ncolors, image->cpp); + + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + + /* + * now we know the exact size we need, realloc the data + * 4 = 1 (for '"') + 3 (for '",\n') + * 1 = - 2 (because the last line does not end with ',\n') + 3 (for '};\n') + */ + if(image->width > UINT_MAX / image->cpp || + (tmp = image->width * image->cpp + 4) <= 4 || + image->height > UINT_MAX / tmp || + (tmp = image->height * tmp + 1) <= 1 || + (ptr_size += tmp) <= tmp) + RETURN(XpmNoMemory); + + p = (char *) XpmRealloc(ptr, ptr_size); + if (!p) + RETURN(XpmNoMemory); + ptr = p; + + /* print pixels */ + if (cmts && info->pixels_cmt) { +#ifndef VOID_SPRINTF + used_size += +#endif + snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->pixels_cmt); +#ifdef VOID_SPRINTF + used_size += strlen(info->pixels_cmt) + 5; +#endif + } + WritePixels(ptr + used_size, ptr_size - used_size, &used_size, image->width, image->height, + image->cpp, image->data, image->colorTable); + + /* print extensions */ + if (extensions) + WriteExtensions(ptr + used_size, ptr_size-used_size, &used_size, + info->extensions, info->nextensions); + + /* close the array */ + strcpy(ptr + used_size, "};\n"); + + *buffer_return = ptr; + + return (XpmSuccess); + +/* exit point in case of error, free only locally allocated variables */ +error: + if (ptr) + XpmFree(ptr); + return (ErrorStatus); +} + + +static int +WriteColors( + char **dataptr, + unsigned int *data_size, + unsigned int *used_size, + XpmColor *colors, + unsigned int ncolors, + unsigned int cpp) +{ + char buf[BUFSIZ] = {0}; + unsigned int a, key, l; + char *s, *s2; + char **defaults; + + *buf = '"'; + for (a = 0; a < ncolors; a++, colors++) { + + defaults = (char **) colors; + s = buf + 1; + if(cpp > (sizeof(buf) - (s-buf))) + return(XpmNoMemory); + strncpy(s, *defaults++, cpp); + s += cpp; + + for (key = 1; key <= NKEYS; key++, defaults++) { + if ((s2 = *defaults)) { +#ifndef VOID_SPRINTF + s += +#endif + /* assume C99 compliance */ + snprintf(s, sizeof(buf) - (s-buf), "\t%s %s", xpmColorKeys[key - 1], s2); +#ifdef VOID_SPRINTF + s += strlen(s); +#endif + /* now let's check if s points out-of-bounds */ + if((s-buf) > sizeof(buf)) + return(XpmNoMemory); + } + } + if(sizeof(buf) - (s-buf) < 4) + return(XpmNoMemory); + strcpy(s, "\",\n"); + l = s + 3 - buf; + if( *data_size >= UINT_MAX-l || + *data_size + l <= *used_size || + (*data_size + l - *used_size) <= sizeof(buf)) + return(XpmNoMemory); + s = (char *) XpmRealloc(*dataptr, *data_size + l); + if (!s) + return (XpmNoMemory); + *data_size += l; + strcpy(s + *used_size, buf); + *used_size += l; + *dataptr = s; + } + return (XpmSuccess); +} + +static void +WritePixels( + char *dataptr, + unsigned int data_size, + unsigned int *used_size, + unsigned int width, + unsigned int height, + unsigned int cpp, + unsigned int *pixels, + XpmColor *colors) +{ + char *s = dataptr; + unsigned int x, y, h; + + if(height <= 1) + return; + + h = height - 1; + for (y = 0; y < h; y++) { + *s++ = '"'; + for (x = 0; x < width; x++, pixels++) { + if(cpp >= (data_size - (s-dataptr))) + return; + strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? :-\ */ + s += cpp; + } + if((data_size - (s-dataptr)) < 4) + return; + strcpy(s, "\",\n"); + s += 3; + } + /* duplicate some code to avoid a test in the loop */ + *s++ = '"'; + for (x = 0; x < width; x++, pixels++) { + if(cpp >= (data_size - (s-dataptr))) + return; + strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? */ + s += cpp; + } + *s++ = '"'; + *used_size += s - dataptr; +} + +static unsigned int +ExtensionsSize( + XpmExtension *ext, + unsigned int num) +{ + unsigned int x, y, a, size; + char **line; + + size = 0; + if(num == 0) + return(0); /* ok? */ + for (x = 0; x < num; x++, ext++) { + /* 11 = 10 (for ',\n"XPMEXT ') + 1 (for '"') */ + size += strlen(ext->name) + 11; + a = ext->nlines; /* how can we trust ext->nlines to be not out-of-bounds? */ + for (y = 0, line = ext->lines; y < a; y++, line++) + /* 4 = 3 (for ',\n"') + 1 (for '"') */ + size += strlen(*line) + 4; + } + /* 13 is for ',\n"XPMENDEXT"' */ + if(size > UINT_MAX - 13) /* unlikely */ + return(0); + return size + 13; +} + +static void +WriteExtensions( + char *dataptr, + unsigned int data_size, + unsigned int *used_size, + XpmExtension *ext, + unsigned int num) +{ + unsigned int x, y, a; + char **line; + char *s = dataptr; + + for (x = 0; x < num; x++, ext++) { +#ifndef VOID_SPRINTF + s += +#endif + snprintf(s, data_size - (s-dataptr), ",\n\"XPMEXT %s\"", ext->name); +#ifdef VOID_SPRINTF + s += strlen(ext->name) + 11; +#endif + a = ext->nlines; + for (y = 0, line = ext->lines; y < a; y++, line++) { +#ifndef VOID_SPRINTF + s += +#endif + snprintf(s, data_size - (s-dataptr), ",\n\"%s\"", *line); +#ifdef VOID_SPRINTF + s += strlen(*line) + 4; +#endif + } + } + strncpy(s, ",\n\"XPMENDEXT\"", data_size - (s-dataptr)-1); + *used_size += s - dataptr + 13; +} + +static int +CommentsSize(XpmInfo *info) +{ + int size = 0; + + /* 5 = 2 (for "/_*") + 3 (for "*_/\n") */ + /* wrap possible but *very* unlikely */ + if (info->hints_cmt) + size += 5 + strlen(info->hints_cmt); + + if (info->colors_cmt) + size += 5 + strlen(info->colors_cmt); + + if (info->pixels_cmt) + size += 5 + strlen(info->pixels_cmt); + + return size; +} diff --git a/libXpm/src/CrDatFrI.c b/libXpm/src/CrDatFrI.c index 04bb9a046..0dacf5127 100644 --- a/libXpm/src/CrDatFrI.c +++ b/libXpm/src/CrDatFrI.c @@ -1,403 +1,403 @@ -/*
- * Copyright (C) 1989-95 GROUPE BULL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of GROUPE BULL shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from GROUPE BULL.
- */
-
-/*****************************************************************************\
-* CrDataFI.c: *
-* *
-* XPM library *
-* Scan an image and possibly its mask and create an XPM array *
-* *
-* Developed by Arnaud Le Hors *
-\*****************************************************************************/
-
-/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "XpmI.h"
-
-LFUNC(CreateColors, int, (char **dataptr, unsigned int *data_size,
- XpmColor *colors, unsigned int ncolors,
- unsigned int cpp));
-
-LFUNC(CreatePixels, void, (char **dataptr, unsigned int data_size,
- unsigned int width,
- unsigned int height, unsigned int cpp,
- unsigned int *pixels, XpmColor *colors));
-
-LFUNC(CountExtensions, void, (XpmExtension *ext, unsigned int num,
- unsigned int *ext_size,
- unsigned int *ext_nlines));
-
-LFUNC(CreateExtensions, void, (char **dataptr, unsigned int data_size,
- unsigned int offset,
- XpmExtension *ext, unsigned int num,
- unsigned int ext_nlines));
-
-int
-XpmCreateDataFromImage(
- Display *display,
- char ***data_return,
- XImage *image,
- XImage *shapeimage,
- XpmAttributes *attributes)
-{
- XpmImage xpmimage;
- XpmInfo info;
- int ErrorStatus;
-
- /* initialize return value */
- if (data_return)
- *data_return = NULL;
-
- /* create an XpmImage from the image */
- ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
- &xpmimage, attributes);
- if (ErrorStatus != XpmSuccess)
- return (ErrorStatus);
-
- /* create the data from the XpmImage */
- if (attributes) {
- xpmSetInfo(&info, attributes);
- ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info);
- } else
- ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL);
-
- /* free the XpmImage */
- XpmFreeXpmImage(&xpmimage);
-
- return (ErrorStatus);
-}
-
-#undef RETURN
-#define RETURN(status) \
-do \
-{ \
- ErrorStatus = status; \
- goto exit; \
-} while(0)
-
-int
-XpmCreateDataFromXpmImage(
- char ***data_return,
- XpmImage *image,
- XpmInfo *info)
-{
- /* calculation variables */
- int ErrorStatus;
- char buf[BUFSIZ];
- char **header = NULL, **data, **sptr, **sptr2, *s;
- unsigned int header_size, header_nlines;
- unsigned int data_size, data_nlines;
- unsigned int extensions = 0, ext_size = 0, ext_nlines = 0;
- unsigned int offset, l, n;
-
- *data_return = NULL;
-
- extensions = info && (info->valuemask & XpmExtensions)
- && info->nextensions;
-
- /* compute the number of extensions lines and size */
- if (extensions)
- CountExtensions(info->extensions, info->nextensions,
- &ext_size, &ext_nlines);
-
- /*
- * alloc a temporary array of char pointer for the header section which
- * is the hints line + the color table lines
- */
- header_nlines = 1 + image->ncolors; /* this may wrap and/or become 0 */
-
- /* 2nd check superfluous if we do not need header_nlines any further */
- if(header_nlines <= image->ncolors ||
- header_nlines >= UINT_MAX / sizeof(char *))
- return(XpmNoMemory);
-
- header_size = sizeof(char *) * header_nlines;
- if (header_size >= UINT_MAX / sizeof(char *))
- return (XpmNoMemory);
- header = (char **) XpmCalloc(header_size, sizeof(char *)); /* can we trust image->ncolors */
- if (!header)
- return (XpmNoMemory);
-
- /* print the hints line */
- s = buf;
-#ifndef VOID_SPRINTF
- s +=
-#endif
- sprintf(s, "%d %d %d %d", image->width, image->height,
- image->ncolors, image->cpp);
-#ifdef VOID_SPRINTF
- s += strlen(s);
-#endif
-
- if (info && (info->valuemask & XpmHotspot)) {
-#ifndef VOID_SPRINTF
- s +=
-#endif
- sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot);
-#ifdef VOID_SPRINTF
- s += strlen(s);
-#endif
- }
- if (extensions) {
- strcpy(s, " XPMEXT");
- s += 7;
- }
- l = s - buf + 1;
- *header = (char *) XpmMalloc(l);
- if (!*header)
- RETURN(XpmNoMemory);
- header_size += l;
- strcpy(*header, buf);
-
- /* print colors */
- ErrorStatus = CreateColors(header + 1, &header_size,
- image->colorTable, image->ncolors, image->cpp);
-
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
-
- /* now we know the size needed, alloc the data and copy the header lines */
- offset = image->width * image->cpp + 1;
-
- if(offset <= image->width || offset <= image->cpp)
- RETURN(XpmNoMemory);
-
- if( (image->height + ext_nlines) >= UINT_MAX / sizeof(char *))
- RETURN(XpmNoMemory);
- data_size = (image->height + ext_nlines) * sizeof(char *);
-
- if (image->height > UINT_MAX / offset ||
- image->height * offset > UINT_MAX - data_size)
- RETURN(XpmNoMemory);
- data_size += image->height * offset;
-
- if( (header_size + ext_size) >= (UINT_MAX - data_size) )
- RETURN(XpmNoMemory);
- data_size += header_size + ext_size;
-
- data = (char **) XpmMalloc(data_size);
- if (!data)
- RETURN(XpmNoMemory);
-
- data_nlines = header_nlines + image->height + ext_nlines;
- *data = (char *) (data + data_nlines);
-
- /* can header have less elements then n suggests? */
- n = image->ncolors;
- for (l = 0, sptr = data, sptr2 = header; l <= n && sptr && sptr2; l++, sptr++, sptr2++) {
- strcpy(*sptr, *sptr2);
- *(sptr + 1) = *sptr + strlen(*sptr2) + 1;
- }
-
- /* print pixels */
- data[header_nlines] = (char *) data + header_size
- + (image->height + ext_nlines) * sizeof(char *);
-
- CreatePixels(data + header_nlines, data_size-header_nlines, image->width, image->height,
- image->cpp, image->data, image->colorTable);
-
- /* print extensions */
- if (extensions)
- CreateExtensions(data + header_nlines + image->height - 1,
- data_size - header_nlines - image->height + 1, offset,
- info->extensions, info->nextensions,
- ext_nlines);
-
- *data_return = data;
- ErrorStatus = XpmSuccess;
-
-/* exit point, free only locally allocated variables */
-exit:
- if (header) {
- for (l = 0; l < header_nlines; l++)
- if (header[l])
- XpmFree(header[l]);
- XpmFree(header);
- }
- return(ErrorStatus);
-}
-
-static int
-CreateColors(
- char **dataptr,
- unsigned int *data_size,
- XpmColor *colors,
- unsigned int ncolors,
- unsigned int cpp)
-{
- char buf[BUFSIZ];
- unsigned int a, key, l;
- char *s, *s2;
- char **defaults;
-
- /* can ncolors be trusted here? */
- for (a = 0; a < ncolors; a++, colors++, dataptr++) {
-
- defaults = (char **) colors;
- if(sizeof(buf) <= cpp)
- return(XpmNoMemory);
- strncpy(buf, *defaults++, cpp);
- s = buf + cpp;
-
- if(sizeof(buf) <= (s-buf))
- return XpmNoMemory;
-
- for (key = 1; key <= NKEYS; key++, defaults++) {
- if ((s2 = *defaults)) {
-#ifndef VOID_SPRINTF
- s +=
-#endif
- /* assume C99 compliance */
- snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2);
-#ifdef VOID_SPRINTF
- s += strlen(s);
-#endif
- /* does s point out-of-bounds? */
- if(sizeof(buf) < (s-buf))
- return XpmNoMemory;
- }
- }
- /* what about using strdup()? */
- l = s - buf + 1;
- s = (char *) XpmMalloc(l);
- if (!s)
- return (XpmNoMemory);
- *data_size += l;
- *dataptr = strcpy(s, buf);
- }
- return (XpmSuccess);
-}
-
-static void
-CreatePixels(
- char **dataptr,
- unsigned int data_size,
- unsigned int width,
- unsigned int height,
- unsigned int cpp,
- unsigned int *pixels,
- XpmColor *colors)
-{
- char *s;
- unsigned int x, y, h, offset;
-
- if(height <= 1)
- return;
-
- h = height - 1;
-
- offset = width * cpp + 1;
-
- if(offset <= width || offset <= cpp)
- return;
-
- /* why trust h? */
- for (y = 0; y < h; y++, dataptr++) {
- s = *dataptr;
- /* why trust width? */
- for (x = 0; x < width; x++, pixels++) {
- if(cpp > (data_size - (s - *dataptr)))
- return;
- strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */
- s += cpp;
- }
- *s = '\0';
- if(offset > data_size)
- return;
- *(dataptr + 1) = *dataptr + offset;
- }
- /* duplicate some code to avoid a test in the loop */
- s = *dataptr;
- /* why trust width? */
- for (x = 0; x < width; x++, pixels++) {
- if(cpp > data_size - (s - *dataptr))
- return;
- strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */
- s += cpp;
- }
- *s = '\0';
-}
-
-static void
-CountExtensions(
- XpmExtension *ext,
- unsigned int num,
- unsigned int *ext_size,
- unsigned int *ext_nlines)
-{
- unsigned int x, y, a, size, nlines;
- char **line;
-
- size = 0;
- nlines = 0;
- for (x = 0; x < num; x++, ext++) {
- /* 1 for the name */
- nlines += ext->nlines + 1;
- /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */
- size += strlen(ext->name) + 8;
- a = ext->nlines;
- for (y = 0, line = ext->lines; y < a; y++, line++)
- size += strlen(*line) + 1;
- }
- /* 10 and 1 are for the ending "XPMENDEXT" */
- *ext_size = size + 10;
- *ext_nlines = nlines + 1;
-}
-
-static void
-CreateExtensions(
- char **dataptr,
- unsigned int data_size,
- unsigned int offset,
- XpmExtension *ext,
- unsigned int num,
- unsigned int ext_nlines)
-{
- unsigned int x, y, a, b;
- char **line;
-
- *(dataptr + 1) = *dataptr + offset;
- dataptr++;
- a = 0;
- for (x = 0; x < num; x++, ext++) {
- snprintf(*dataptr, data_size, "XPMEXT %s", ext->name);
- a++;
- if (a < ext_nlines)
- *(dataptr + 1) = *dataptr + strlen(ext->name) + 8;
- dataptr++;
- b = ext->nlines; /* can we trust these values? */
- for (y = 0, line = ext->lines; y < b; y++, line++) {
- strcpy(*dataptr, *line);
- a++;
- if (a < ext_nlines)
- *(dataptr + 1) = *dataptr + strlen(*line) + 1;
- dataptr++;
- }
- }
- strcpy(*dataptr, "XPMENDEXT");
-}
+/* + * Copyright (C) 1989-95 GROUPE BULL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of GROUPE BULL shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from GROUPE BULL. + */ + +/*****************************************************************************\ +* CrDataFI.c: * +* * +* XPM library * +* Scan an image and possibly its mask and create an XPM array * +* * +* Developed by Arnaud Le Hors * +\*****************************************************************************/ + +/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "XpmI.h" + +LFUNC(CreateColors, int, (char **dataptr, unsigned int *data_size, + XpmColor *colors, unsigned int ncolors, + unsigned int cpp)); + +LFUNC(CreatePixels, void, (char **dataptr, unsigned int data_size, + unsigned int width, + unsigned int height, unsigned int cpp, + unsigned int *pixels, XpmColor *colors)); + +LFUNC(CountExtensions, void, (XpmExtension *ext, unsigned int num, + unsigned int *ext_size, + unsigned int *ext_nlines)); + +LFUNC(CreateExtensions, void, (char **dataptr, unsigned int data_size, + unsigned int offset, + XpmExtension *ext, unsigned int num, + unsigned int ext_nlines)); + +int +XpmCreateDataFromImage( + Display *display, + char ***data_return, + XImage *image, + XImage *shapeimage, + XpmAttributes *attributes) +{ + XpmImage xpmimage; + XpmInfo info; + int ErrorStatus; + + /* initialize return value */ + if (data_return) + *data_return = NULL; + + /* create an XpmImage from the image */ + ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage, + &xpmimage, attributes); + if (ErrorStatus != XpmSuccess) + return (ErrorStatus); + + /* create the data from the XpmImage */ + if (attributes) { + xpmSetInfo(&info, attributes); + ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info); + } else + ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL); + + /* free the XpmImage */ + XpmFreeXpmImage(&xpmimage); + + return (ErrorStatus); +} + +#undef RETURN +#define RETURN(status) \ +do \ +{ \ + ErrorStatus = status; \ + goto exit; \ +} while(0) + +int +XpmCreateDataFromXpmImage( + char ***data_return, + XpmImage *image, + XpmInfo *info) +{ + /* calculation variables */ + int ErrorStatus; + char buf[BUFSIZ]; + char **header = NULL, **data, **sptr, **sptr2, *s; + unsigned int header_size, header_nlines; + unsigned int data_size, data_nlines; + unsigned int extensions = 0, ext_size = 0, ext_nlines = 0; + unsigned int offset, l, n; + + *data_return = NULL; + + extensions = info && (info->valuemask & XpmExtensions) + && info->nextensions; + + /* compute the number of extensions lines and size */ + if (extensions) + CountExtensions(info->extensions, info->nextensions, + &ext_size, &ext_nlines); + + /* + * alloc a temporary array of char pointer for the header section which + * is the hints line + the color table lines + */ + header_nlines = 1 + image->ncolors; /* this may wrap and/or become 0 */ + + /* 2nd check superfluous if we do not need header_nlines any further */ + if(header_nlines <= image->ncolors || + header_nlines >= UINT_MAX / sizeof(char *)) + return(XpmNoMemory); + + header_size = sizeof(char *) * header_nlines; + if (header_size >= UINT_MAX / sizeof(char *)) + return (XpmNoMemory); + header = (char **) XpmCalloc(header_size, sizeof(char *)); /* can we trust image->ncolors */ + if (!header) + return (XpmNoMemory); + + /* print the hints line */ + s = buf; +#ifndef VOID_SPRINTF + s += +#endif + sprintf(s, "%d %d %d %d", image->width, image->height, + image->ncolors, image->cpp); +#ifdef VOID_SPRINTF + s += strlen(s); +#endif + + if (info && (info->valuemask & XpmHotspot)) { +#ifndef VOID_SPRINTF + s += +#endif + sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot); +#ifdef VOID_SPRINTF + s += strlen(s); +#endif + } + if (extensions) { + strcpy(s, " XPMEXT"); + s += 7; + } + l = s - buf + 1; + *header = (char *) XpmMalloc(l); + if (!*header) + RETURN(XpmNoMemory); + header_size += l; + strcpy(*header, buf); + + /* print colors */ + ErrorStatus = CreateColors(header + 1, &header_size, + image->colorTable, image->ncolors, image->cpp); + + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + + /* now we know the size needed, alloc the data and copy the header lines */ + offset = image->width * image->cpp + 1; + + if(offset <= image->width || offset <= image->cpp) + RETURN(XpmNoMemory); + + if( (image->height + ext_nlines) >= UINT_MAX / sizeof(char *)) + RETURN(XpmNoMemory); + data_size = (image->height + ext_nlines) * sizeof(char *); + + if (image->height > UINT_MAX / offset || + image->height * offset > UINT_MAX - data_size) + RETURN(XpmNoMemory); + data_size += image->height * offset; + + if( (header_size + ext_size) >= (UINT_MAX - data_size) ) + RETURN(XpmNoMemory); + data_size += header_size + ext_size; + + data = (char **) XpmMalloc(data_size); + if (!data) + RETURN(XpmNoMemory); + + data_nlines = header_nlines + image->height + ext_nlines; + *data = (char *) (data + data_nlines); + + /* can header have less elements then n suggests? */ + n = image->ncolors; + for (l = 0, sptr = data, sptr2 = header; l <= n && sptr && sptr2; l++, sptr++, sptr2++) { + strcpy(*sptr, *sptr2); + *(sptr + 1) = *sptr + strlen(*sptr2) + 1; + } + + /* print pixels */ + data[header_nlines] = (char *) data + header_size + + (image->height + ext_nlines) * sizeof(char *); + + CreatePixels(data + header_nlines, data_size-header_nlines, image->width, image->height, + image->cpp, image->data, image->colorTable); + + /* print extensions */ + if (extensions) + CreateExtensions(data + header_nlines + image->height - 1, + data_size - header_nlines - image->height + 1, offset, + info->extensions, info->nextensions, + ext_nlines); + + *data_return = data; + ErrorStatus = XpmSuccess; + +/* exit point, free only locally allocated variables */ +exit: + if (header) { + for (l = 0; l < header_nlines; l++) + if (header[l]) + XpmFree(header[l]); + XpmFree(header); + } + return(ErrorStatus); +} + +static int +CreateColors( + char **dataptr, + unsigned int *data_size, + XpmColor *colors, + unsigned int ncolors, + unsigned int cpp) +{ + char buf[BUFSIZ]; + unsigned int a, key, l; + char *s, *s2; + char **defaults; + + /* can ncolors be trusted here? */ + for (a = 0; a < ncolors; a++, colors++, dataptr++) { + + defaults = (char **) colors; + if(sizeof(buf) <= cpp) + return(XpmNoMemory); + strncpy(buf, *defaults++, cpp); + s = buf + cpp; + + if(sizeof(buf) <= (s-buf)) + return XpmNoMemory; + + for (key = 1; key <= NKEYS; key++, defaults++) { + if ((s2 = *defaults)) { +#ifndef VOID_SPRINTF + s += +#endif + /* assume C99 compliance */ + snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2); +#ifdef VOID_SPRINTF + s += strlen(s); +#endif + /* does s point out-of-bounds? */ + if(sizeof(buf) < (s-buf)) + return XpmNoMemory; + } + } + /* what about using strdup()? */ + l = s - buf + 1; + s = (char *) XpmMalloc(l); + if (!s) + return (XpmNoMemory); + *data_size += l; + *dataptr = strcpy(s, buf); + } + return (XpmSuccess); +} + +static void +CreatePixels( + char **dataptr, + unsigned int data_size, + unsigned int width, + unsigned int height, + unsigned int cpp, + unsigned int *pixels, + XpmColor *colors) +{ + char *s; + unsigned int x, y, h, offset; + + if(height <= 1) + return; + + h = height - 1; + + offset = width * cpp + 1; + + if(offset <= width || offset <= cpp) + return; + + /* why trust h? */ + for (y = 0; y < h; y++, dataptr++) { + s = *dataptr; + /* why trust width? */ + for (x = 0; x < width; x++, pixels++) { + if(cpp > (data_size - (s - *dataptr))) + return; + strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */ + s += cpp; + } + *s = '\0'; + if(offset > data_size) + return; + *(dataptr + 1) = *dataptr + offset; + } + /* duplicate some code to avoid a test in the loop */ + s = *dataptr; + /* why trust width? */ + for (x = 0; x < width; x++, pixels++) { + if(cpp > data_size - (s - *dataptr)) + return; + strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */ + s += cpp; + } + *s = '\0'; +} + +static void +CountExtensions( + XpmExtension *ext, + unsigned int num, + unsigned int *ext_size, + unsigned int *ext_nlines) +{ + unsigned int x, y, a, size, nlines; + char **line; + + size = 0; + nlines = 0; + for (x = 0; x < num; x++, ext++) { + /* 1 for the name */ + nlines += ext->nlines + 1; + /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */ + size += strlen(ext->name) + 8; + a = ext->nlines; + for (y = 0, line = ext->lines; y < a; y++, line++) + size += strlen(*line) + 1; + } + /* 10 and 1 are for the ending "XPMENDEXT" */ + *ext_size = size + 10; + *ext_nlines = nlines + 1; +} + +static void +CreateExtensions( + char **dataptr, + unsigned int data_size, + unsigned int offset, + XpmExtension *ext, + unsigned int num, + unsigned int ext_nlines) +{ + unsigned int x, y, a, b; + char **line; + + *(dataptr + 1) = *dataptr + offset; + dataptr++; + a = 0; + for (x = 0; x < num; x++, ext++) { + snprintf(*dataptr, data_size, "XPMEXT %s", ext->name); + a++; + if (a < ext_nlines) + *(dataptr + 1) = *dataptr + strlen(ext->name) + 8; + dataptr++; + b = ext->nlines; /* can we trust these values? */ + for (y = 0, line = ext->lines; y < b; y++, line++) { + strcpy(*dataptr, *line); + a++; + if (a < ext_nlines) + *(dataptr + 1) = *dataptr + strlen(*line) + 1; + dataptr++; + } + } + strcpy(*dataptr, "XPMENDEXT"); +} diff --git a/libXpm/src/Makefile.am b/libXpm/src/Makefile.am index ba8797f7f..297d310b8 100644 --- a/libXpm/src/Makefile.am +++ b/libXpm/src/Makefile.am @@ -1,43 +1,43 @@ -# Daniel Stone disowns all copyright on this file.
-
-lib_LTLIBRARIES=libXpm.la
-
-AM_CPPFLAGS = -I$(top_srcdir)/include/X11/
-AM_CFLAGS = $(CWARNFLAGS) $(XPM_CFLAGS)
-
-libXpm_la_LDFLAGS = -version-number 4:11:0 -no-undefined
-libXpm_la_LIBADD = $(XPM_LIBS)
-
-libXpm_la_SOURCES = \
- Attrib.c \
- CrBufFrI.c \
- CrBufFrP.c \
- CrDatFrI.c \
- CrDatFrP.c \
- CrIFrBuf.c \
- CrIFrDat.c \
- CrIFrP.c \
- CrPFrBuf.c \
- CrPFrDat.c \
- CrPFrI.c \
- Image.c \
- Info.c \
- RdFToBuf.c \
- RdFToDat.c \
- RdFToI.c \
- RdFToP.c \
- WrFFrBuf.c \
- WrFFrDat.c \
- WrFFrI.c \
- WrFFrP.c \
- XpmI.h \
- create.c \
- data.c \
- hashtab.c \
- misc.c \
- parse.c \
- rgb.c \
- rgbtab.h \
- scan.c
-
-EXTRA_DIST = amigax.c amigax.h simx.c simx.h
+# Daniel Stone disowns all copyright on this file. + +lib_LTLIBRARIES=libXpm.la + +AM_CPPFLAGS = -I$(top_srcdir)/include/X11/ +AM_CFLAGS = $(CWARNFLAGS) $(XPM_CFLAGS) + +libXpm_la_LDFLAGS = -version-number 4:11:0 -no-undefined +libXpm_la_LIBADD = $(XPM_LIBS) + +libXpm_la_SOURCES = \ + Attrib.c \ + CrBufFrI.c \ + CrBufFrP.c \ + CrDatFrI.c \ + CrDatFrP.c \ + CrIFrBuf.c \ + CrIFrDat.c \ + CrIFrP.c \ + CrPFrBuf.c \ + CrPFrDat.c \ + CrPFrI.c \ + Image.c \ + Info.c \ + RdFToBuf.c \ + RdFToDat.c \ + RdFToI.c \ + RdFToP.c \ + WrFFrBuf.c \ + WrFFrDat.c \ + WrFFrI.c \ + WrFFrP.c \ + XpmI.h \ + create.c \ + data.c \ + hashtab.c \ + misc.c \ + parse.c \ + rgb.c \ + rgbtab.h \ + scan.c + +EXTRA_DIST = amigax.c amigax.h simx.c simx.h diff --git a/libXpm/src/RdFToI.c b/libXpm/src/RdFToI.c index 9f6e3c007..b27a6726d 100644 --- a/libXpm/src/RdFToI.c +++ b/libXpm/src/RdFToI.c @@ -1,274 +1,274 @@ -/*
- * Copyright (C) 1989-95 GROUPE BULL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of GROUPE BULL shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from GROUPE BULL.
- */
-
-/*****************************************************************************\
-* RdFToI.c: *
-* *
-* XPM library *
-* Parse an XPM file and create the image and possibly its mask *
-* *
-* Developed by Arnaud Le Hors *
-\*****************************************************************************/
-
-/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "XpmI.h"
-#ifndef NO_ZPIPE
-#include <fcntl.h>
-#include <errno.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-typedef int pid_t;
-#else
-#ifdef FOR_MSW
-#include <fcntl.h>
-#endif
-#endif
-
-LFUNC(OpenReadFile, int, (char *filename, xpmData *mdata));
-LFUNC(xpmDataClose, void, (xpmData *mdata));
-
-FUNC(xpmPipeThrough, FILE*, (int fd,
- const char *cmd,
- const char *arg1,
- const char *mode));
-
-#ifndef CXPMPROG
-int
-XpmReadFileToImage(
- Display *display,
- char *filename,
- XImage **image_return,
- XImage **shapeimage_return,
- XpmAttributes *attributes)
-{
- XpmImage image;
- XpmInfo info;
- int ErrorStatus;
- xpmData mdata;
-
- xpmInitXpmImage(&image);
- xpmInitXpmInfo(&info);
-
- /* open file to read */
- if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess)
- return (ErrorStatus);
-
- /* create the XImage from the XpmData */
- if (attributes) {
- xpmInitAttributes(attributes);
- xpmSetInfoMask(&info, attributes);
- ErrorStatus = xpmParseDataAndCreate(display, &mdata,
- image_return, shapeimage_return,
- &image, &info, attributes);
- } else
- ErrorStatus = xpmParseDataAndCreate(display, &mdata,
- image_return, shapeimage_return,
- &image, NULL, attributes);
- if (attributes) {
- if (ErrorStatus >= 0) /* no fatal error */
- xpmSetAttributes(attributes, &image, &info);
- XpmFreeXpmInfo(&info);
- }
-
- xpmDataClose(&mdata);
- /* free the XpmImage */
- XpmFreeXpmImage(&image);
-
- return (ErrorStatus);
-}
-
-int
-XpmReadFileToXpmImage(
- char *filename,
- XpmImage *image,
- XpmInfo *info)
-{
- xpmData mdata;
- int ErrorStatus;
-
- /* init returned values */
- xpmInitXpmImage(image);
- xpmInitXpmInfo(info);
-
- /* open file to read */
- if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess)
- return (ErrorStatus);
-
- /* create the XpmImage from the XpmData */
- ErrorStatus = xpmParseData(&mdata, image, info);
-
- xpmDataClose(&mdata);
-
- return (ErrorStatus);
-}
-#endif /* CXPMPROG */
-
-#ifndef NO_ZPIPE
-/* Do not depend on errno after read_through */
-FILE*
-xpmPipeThrough(
- int fd,
- const char *cmd,
- const char *arg1,
- const char *mode)
-{
- FILE* fp;
- int status, fds[2], in = 0, out = 1;
- pid_t pid;
- if ( 'w' == *mode )
- out = 0, in = 1;
- if ( pipe(fds) < 0 )
- return NULL;
- pid = fork();
- if ( pid < 0 )
- goto fail1;
- if ( 0 == pid )
- {
- close(fds[in]);
- if ( dup2(fds[out], out) < 0 )
- goto err;
- close(fds[out]);
- if ( dup2(fd, in) < 0 )
- goto err;
- close(fd);
- pid = fork();
- if ( pid < 0 )
- goto err;
- if ( 0 == pid )
- {
- execlp(cmd, cmd, arg1, (char *)NULL);
- perror(cmd);
- goto err;
- }
- _exit(0);
- err:
- _exit(1);
- }
- close(fds[out]);
- /* calling process: wait for first child */
- while ( waitpid(pid, &status, 0) < 0 && EINTR == errno )
- ;
- if ( WIFSIGNALED(status) ||
- (WIFEXITED(status) && WEXITSTATUS(status) != 0) )
- goto fail2;
- fp = fdopen(fds[in], mode);
- if ( !fp )
- goto fail2;
- close(fd); /* still open in 2nd child */
- return fp;
-fail1:
- close(fds[out]);
-fail2:
- close(fds[in]);
- return NULL;
-}
-#endif
-
-/*
- * open the given file to be read as an xpmData which is returned.
- */
-static int
-OpenReadFile(
- char *filename,
- xpmData *mdata)
-{
- if (!filename) {
- mdata->stream.file = (stdin);
- mdata->type = XPMFILE;
- } else {
- int fd = open(filename, O_RDONLY);
-#if defined(NO_ZPIPE)
- if ( fd < 0 )
- return XpmOpenFailed;
-#else
- const char* ext = NULL;
- if ( fd >= 0 )
- ext = strrchr(filename, '.');
-#ifdef STAT_ZFILE /* searching for z-files if the given name not found */
- else
- {
- size_t len = strlen(filename);
- char *compressfile = (char *) XpmMalloc(len + 4);
- if ( !compressfile )
- return (XpmNoMemory);
- strcpy(compressfile, filename);
- strcpy(compressfile + len, ext = ".Z");
- fd = open(compressfile, O_RDONLY);
- if ( fd < 0 )
- {
- strcpy(compressfile + len, ext = ".gz");
- fd = open(compressfile, O_RDONLY);
- if ( fd < 0 )
- {
- XpmFree(compressfile);
- return XpmOpenFailed;
- }
- }
- XpmFree(compressfile);
- }
-#endif
- if ( ext && !strcmp(ext, ".Z") )
- {
- mdata->type = XPMPIPE;
- mdata->stream.file = xpmPipeThrough(fd, "uncompress", "-c", "r");
- }
- else if ( ext && !strcmp(ext, ".gz") )
- {
- mdata->type = XPMPIPE;
- mdata->stream.file = xpmPipeThrough(fd, "gunzip", "-qc", "r");
- }
- else
-#endif /* z-files */
- {
- mdata->type = XPMFILE;
- mdata->stream.file = fdopen(fd, "r");
- }
- if (!mdata->stream.file)
- {
- close(fd);
- return (XpmOpenFailed);
- }
- }
- mdata->CommentLength = 0;
-#ifdef CXPMPROG
- mdata->lineNum = 0;
- mdata->charNum = 0;
-#endif
- return (XpmSuccess);
-}
-
-/*
- * close the file related to the xpmData if any
- */
-static void
-xpmDataClose(xpmData *mdata)
-{
- if (mdata->stream.file != (stdin))
- fclose(mdata->stream.file);
-}
+/* + * Copyright (C) 1989-95 GROUPE BULL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of GROUPE BULL shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from GROUPE BULL. + */ + +/*****************************************************************************\ +* RdFToI.c: * +* * +* XPM library * +* Parse an XPM file and create the image and possibly its mask * +* * +* Developed by Arnaud Le Hors * +\*****************************************************************************/ + +/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "XpmI.h" +#ifndef NO_ZPIPE +#include <fcntl.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> +typedef int pid_t; +#else +#ifdef FOR_MSW +#include <fcntl.h> +#endif +#endif + +LFUNC(OpenReadFile, int, (char *filename, xpmData *mdata)); +LFUNC(xpmDataClose, void, (xpmData *mdata)); + +FUNC(xpmPipeThrough, FILE*, (int fd, + const char *cmd, + const char *arg1, + const char *mode)); + +#ifndef CXPMPROG +int +XpmReadFileToImage( + Display *display, + char *filename, + XImage **image_return, + XImage **shapeimage_return, + XpmAttributes *attributes) +{ + XpmImage image; + XpmInfo info; + int ErrorStatus; + xpmData mdata; + + xpmInitXpmImage(&image); + xpmInitXpmInfo(&info); + + /* open file to read */ + if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess) + return (ErrorStatus); + + /* create the XImage from the XpmData */ + if (attributes) { + xpmInitAttributes(attributes); + xpmSetInfoMask(&info, attributes); + ErrorStatus = xpmParseDataAndCreate(display, &mdata, + image_return, shapeimage_return, + &image, &info, attributes); + } else + ErrorStatus = xpmParseDataAndCreate(display, &mdata, + image_return, shapeimage_return, + &image, NULL, attributes); + if (attributes) { + if (ErrorStatus >= 0) /* no fatal error */ + xpmSetAttributes(attributes, &image, &info); + XpmFreeXpmInfo(&info); + } + + xpmDataClose(&mdata); + /* free the XpmImage */ + XpmFreeXpmImage(&image); + + return (ErrorStatus); +} + +int +XpmReadFileToXpmImage( + char *filename, + XpmImage *image, + XpmInfo *info) +{ + xpmData mdata; + int ErrorStatus; + + /* init returned values */ + xpmInitXpmImage(image); + xpmInitXpmInfo(info); + + /* open file to read */ + if ((ErrorStatus = OpenReadFile(filename, &mdata)) != XpmSuccess) + return (ErrorStatus); + + /* create the XpmImage from the XpmData */ + ErrorStatus = xpmParseData(&mdata, image, info); + + xpmDataClose(&mdata); + + return (ErrorStatus); +} +#endif /* CXPMPROG */ + +#ifndef NO_ZPIPE +/* Do not depend on errno after read_through */ +FILE* +xpmPipeThrough( + int fd, + const char *cmd, + const char *arg1, + const char *mode) +{ + FILE* fp; + int status, fds[2], in = 0, out = 1; + pid_t pid; + if ( 'w' == *mode ) + out = 0, in = 1; + if ( pipe(fds) < 0 ) + return NULL; + pid = fork(); + if ( pid < 0 ) + goto fail1; + if ( 0 == pid ) + { + close(fds[in]); + if ( dup2(fds[out], out) < 0 ) + goto err; + close(fds[out]); + if ( dup2(fd, in) < 0 ) + goto err; + close(fd); + pid = fork(); + if ( pid < 0 ) + goto err; + if ( 0 == pid ) + { + execlp(cmd, cmd, arg1, (char *)NULL); + perror(cmd); + goto err; + } + _exit(0); + err: + _exit(1); + } + close(fds[out]); + /* calling process: wait for first child */ + while ( waitpid(pid, &status, 0) < 0 && EINTR == errno ) + ; + if ( WIFSIGNALED(status) || + (WIFEXITED(status) && WEXITSTATUS(status) != 0) ) + goto fail2; + fp = fdopen(fds[in], mode); + if ( !fp ) + goto fail2; + close(fd); /* still open in 2nd child */ + return fp; +fail1: + close(fds[out]); +fail2: + close(fds[in]); + return NULL; +} +#endif + +/* + * open the given file to be read as an xpmData which is returned. + */ +static int +OpenReadFile( + char *filename, + xpmData *mdata) +{ + if (!filename) { + mdata->stream.file = (stdin); + mdata->type = XPMFILE; + } else { + int fd = open(filename, O_RDONLY); +#if defined(NO_ZPIPE) + if ( fd < 0 ) + return XpmOpenFailed; +#else + const char* ext = NULL; + if ( fd >= 0 ) + ext = strrchr(filename, '.'); +#ifdef STAT_ZFILE /* searching for z-files if the given name not found */ + else + { + size_t len = strlen(filename); + char *compressfile = (char *) XpmMalloc(len + 4); + if ( !compressfile ) + return (XpmNoMemory); + strcpy(compressfile, filename); + strcpy(compressfile + len, ext = ".Z"); + fd = open(compressfile, O_RDONLY); + if ( fd < 0 ) + { + strcpy(compressfile + len, ext = ".gz"); + fd = open(compressfile, O_RDONLY); + if ( fd < 0 ) + { + XpmFree(compressfile); + return XpmOpenFailed; + } + } + XpmFree(compressfile); + } +#endif + if ( ext && !strcmp(ext, ".Z") ) + { + mdata->type = XPMPIPE; + mdata->stream.file = xpmPipeThrough(fd, "uncompress", "-c", "r"); + } + else if ( ext && !strcmp(ext, ".gz") ) + { + mdata->type = XPMPIPE; + mdata->stream.file = xpmPipeThrough(fd, "gunzip", "-qc", "r"); + } + else +#endif /* z-files */ + { + mdata->type = XPMFILE; + mdata->stream.file = fdopen(fd, "r"); + } + if (!mdata->stream.file) + { + close(fd); + return (XpmOpenFailed); + } + } + mdata->CommentLength = 0; +#ifdef CXPMPROG + mdata->lineNum = 0; + mdata->charNum = 0; +#endif + return (XpmSuccess); +} + +/* + * close the file related to the xpmData if any + */ +static void +xpmDataClose(xpmData *mdata) +{ + if (mdata->stream.file != (stdin)) + fclose(mdata->stream.file); +} diff --git a/libXpm/src/WrFFrI.c b/libXpm/src/WrFFrI.c index 46e800577..f2726f995 100644 --- a/libXpm/src/WrFFrI.c +++ b/libXpm/src/WrFFrI.c @@ -1,363 +1,363 @@ -/*
- * Copyright (C) 1989-95 GROUPE BULL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of GROUPE BULL shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from GROUPE BULL.
- */
-
-/*****************************************************************************\
-* WrFFrI.c: *
-* *
-* XPM library *
-* Write an image and possibly its mask to an XPM file *
-* *
-* Developed by Arnaud Le Hors *
-\*****************************************************************************/
-
-/*
- * The code related to AMIGA has been added by
- * Lorens Younes (d93-hyo@nada.kth.se) 4/96
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "XpmI.h"
-
-#ifndef NO_ZPIPE
-#include "sys/wait.h"
-#include "sys/types.h"
-#include "fcntl.h"
-#include "unistd.h"
-#include "errno.h"
-#endif
-
-/* MS Windows define a function called WriteFile @#%#&!!! */
-LFUNC(xpmWriteFile, int, (FILE *file, XpmImage *image, char *name,
- XpmInfo *info));
-
-LFUNC(WriteColors, void, (FILE *file, XpmColor *colors, unsigned int ncolors));
-
-LFUNC(WritePixels, int, (FILE *file, unsigned int width, unsigned int height,
- unsigned int cpp, unsigned int *pixels,
- XpmColor *colors));
-
-LFUNC(WriteExtensions, void, (FILE *file, XpmExtension *ext,
- unsigned int num));
-
-LFUNC(OpenWriteFile, int, (char *filename, xpmData *mdata));
-LFUNC(xpmDataClose, void, (xpmData *mdata));
-
-int
-XpmWriteFileFromImage(
- Display *display,
- char *filename,
- XImage *image,
- XImage *shapeimage,
- XpmAttributes *attributes)
-{
- XpmImage xpmimage;
- XpmInfo info;
- int ErrorStatus;
-
- /* create an XpmImage from the image */
- ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
- &xpmimage, attributes);
- if (ErrorStatus != XpmSuccess)
- return (ErrorStatus);
-
- /* write the file from the XpmImage */
- if (attributes) {
- xpmSetInfo(&info, attributes);
- ErrorStatus = XpmWriteFileFromXpmImage(filename, &xpmimage, &info);
- } else
- ErrorStatus = XpmWriteFileFromXpmImage(filename, &xpmimage, NULL);
-
- /* free the XpmImage */
- XpmFreeXpmImage(&xpmimage);
-
- return (ErrorStatus);
-}
-
-int
-XpmWriteFileFromXpmImage(
- char *filename,
- XpmImage *image,
- XpmInfo *info)
-{
- xpmData mdata;
- char *name, *dot, *s, new_name[BUFSIZ] = {0};
- int ErrorStatus;
-
- /* open file to write */
- if ((ErrorStatus = OpenWriteFile(filename, &mdata)) != XpmSuccess)
- return (ErrorStatus);
-
- /* figure out a name */
- if (filename) {
-#ifdef VMS
- name = filename;
-#else
- if (!(name = strrchr(filename, '/'))
-#ifdef AMIGA
- && !(name = strrchr(filename, ':'))
-#endif
- )
- name = filename;
- else
- name++;
-#endif
- /* let's try to make a valid C syntax name */
- if (strchr(name, '.')) {
- strncpy(new_name, name, sizeof(new_name));
- new_name[sizeof(new_name)-1] = '\0';
- /* change '.' to '_' */
- name = s = new_name;
- while ((dot = strchr(s, '.'))) {
- *dot = '_';
- s = dot;
- }
- }
- if (strchr(name, '-')) {
- if (name != new_name) {
- strncpy(new_name, name, sizeof(new_name));
- new_name[sizeof(new_name)-1] = '\0';
- name = new_name;
- }
- /* change '-' to '_' */
- s = name;
- while ((dot = strchr(s, '-'))) {
- *dot = '_';
- s = dot;
- }
- }
- } else
- name = "image_name";
-
- /* write the XpmData from the XpmImage */
- if (ErrorStatus == XpmSuccess)
- ErrorStatus = xpmWriteFile(mdata.stream.file, image, name, info);
-
- xpmDataClose(&mdata);
-
- return (ErrorStatus);
-}
-
-static int
-xpmWriteFile(
- FILE *file,
- XpmImage *image,
- char *name,
- XpmInfo *info)
-{
- /* calculation variables */
- unsigned int cmts, extensions;
- int ErrorStatus;
-
- cmts = info && (info->valuemask & XpmComments);
- extensions = info && (info->valuemask & XpmExtensions)
- && info->nextensions;
-
- /* print the header line */
- fprintf(file, "/* XPM */\nstatic char * %s[] = {\n", name);
-
- /* print the hints line */
- if (cmts && info->hints_cmt)
- fprintf(file, "/*%s*/\n", info->hints_cmt);
-
- fprintf(file, "\"%d %d %d %d", image->width, image->height,
- image->ncolors, image->cpp);
-
- if (info && (info->valuemask & XpmHotspot))
- fprintf(file, " %d %d", info->x_hotspot, info->y_hotspot);
-
- if (extensions)
- fprintf(file, " XPMEXT");
-
- fprintf(file, "\",\n");
-
- /* print colors */
- if (cmts && info->colors_cmt)
- fprintf(file, "/*%s*/\n", info->colors_cmt);
-
- WriteColors(file, image->colorTable, image->ncolors);
-
- /* print pixels */
- if (cmts && info->pixels_cmt)
- fprintf(file, "/*%s*/\n", info->pixels_cmt);
-
- ErrorStatus = WritePixels(file, image->width, image->height, image->cpp,
- image->data, image->colorTable);
- if (ErrorStatus != XpmSuccess)
- return (ErrorStatus);
-
- /* print extensions */
- if (extensions)
- WriteExtensions(file, info->extensions, info->nextensions);
-
- /* close the array */
- fprintf(file, "};\n");
-
- return (XpmSuccess);
-}
-
-static void
-WriteColors(
- FILE *file,
- XpmColor *colors,
- unsigned int ncolors)
-{
- unsigned int a, key;
- char *s;
- char **defaults;
-
- for (a = 0; a < ncolors; a++, colors++) {
-
- defaults = (char **) colors;
- fprintf(file, "\"%s", *defaults++);
-
- for (key = 1; key <= NKEYS; key++, defaults++) {
- if ((s = *defaults))
- fprintf(file, "\t%s %s", xpmColorKeys[key - 1], s);
- }
- fprintf(file, "\",\n");
- }
-}
-
-
-static int
-WritePixels(
- FILE *file,
- unsigned int width,
- unsigned int height,
- unsigned int cpp,
- unsigned int *pixels,
- XpmColor *colors)
-{
- char *s, *p, *buf;
- unsigned int x, y, h;
-
- h = height - 1;
- if (cpp != 0 && width >= (UINT_MAX - 3)/cpp)
- return XpmNoMemory;
- p = buf = (char *) XpmMalloc(width * cpp + 3);
- if (!buf)
- return (XpmNoMemory);
- *buf = '"';
- p++;
- for (y = 0; y < h; y++) {
- s = p;
- for (x = 0; x < width; x++, pixels++) {
- strncpy(s, colors[*pixels].string, cpp);
- s += cpp;
- }
- *s++ = '"';
- *s = '\0';
- fprintf(file, "%s,\n", buf);
- }
- /* duplicate some code to avoid a test in the loop */
- s = p;
- for (x = 0; x < width; x++, pixels++) {
- strncpy(s, colors[*pixels].string, cpp);
- s += cpp;
- }
- *s++ = '"';
- *s = '\0';
- fprintf(file, "%s", buf);
-
- XpmFree(buf);
- return (XpmSuccess);
-}
-
-static void
-WriteExtensions(
- FILE *file,
- XpmExtension *ext,
- unsigned int num)
-{
- unsigned int x, y, n;
- char **line;
-
- for (x = 0; x < num; x++, ext++) {
- fprintf(file, ",\n\"XPMEXT %s\"", ext->name);
- n = ext->nlines;
- for (y = 0, line = ext->lines; y < n; y++, line++)
- fprintf(file, ",\n\"%s\"", *line);
- }
- fprintf(file, ",\n\"XPMENDEXT\"");
-}
-
-
-#ifndef NO_ZPIPE
-FUNC(xpmPipeThrough, FILE*, (int fd,
- const char* cmd,
- const char* arg1,
- const char* mode));
-#endif
-
-/*
- * open the given file to be written as an xpmData which is returned
- */
-static int
-OpenWriteFile(
- char *filename,
- xpmData *mdata)
-{
- if (!filename) {
- mdata->stream.file = (stdout);
- mdata->type = XPMFILE;
- } else {
-#ifndef NO_ZPIPE
- size_t len;
-#endif
- int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
- if ( fd < 0 )
- return(XpmOpenFailed);
-#ifndef NO_ZPIPE
- len = strlen(filename);
- if (len > 2 && !strcmp(".Z", filename + (len - 2))) {
- mdata->stream.file = xpmPipeThrough(fd, "compress", NULL, "w");
- mdata->type = XPMPIPE;
- } else if (len > 3 && !strcmp(".gz", filename + (len - 3))) {
- mdata->stream.file = xpmPipeThrough(fd, "gzip", "-q", "w");
- mdata->type = XPMPIPE;
- } else
-#endif
- {
- mdata->stream.file = fdopen(fd, "w");
- mdata->type = XPMFILE;
- }
- if (!mdata->stream.file)
- return (XpmOpenFailed);
- }
- return (XpmSuccess);
-}
-
-/*
- * close the file related to the xpmData if any
- */
-static void
-xpmDataClose(xpmData *mdata)
-{
- if (mdata->stream.file != (stdout))
- fclose(mdata->stream.file);
-}
-
+/* + * Copyright (C) 1989-95 GROUPE BULL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of GROUPE BULL shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from GROUPE BULL. + */ + +/*****************************************************************************\ +* WrFFrI.c: * +* * +* XPM library * +* Write an image and possibly its mask to an XPM file * +* * +* Developed by Arnaud Le Hors * +\*****************************************************************************/ + +/* + * The code related to AMIGA has been added by + * Lorens Younes (d93-hyo@nada.kth.se) 4/96 + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "XpmI.h" + +#ifndef NO_ZPIPE +#include "sys/wait.h" +#include "sys/types.h" +#include "fcntl.h" +#include "unistd.h" +#include "errno.h" +#endif + +/* MS Windows define a function called WriteFile @#%#&!!! */ +LFUNC(xpmWriteFile, int, (FILE *file, XpmImage *image, char *name, + XpmInfo *info)); + +LFUNC(WriteColors, void, (FILE *file, XpmColor *colors, unsigned int ncolors)); + +LFUNC(WritePixels, int, (FILE *file, unsigned int width, unsigned int height, + unsigned int cpp, unsigned int *pixels, + XpmColor *colors)); + +LFUNC(WriteExtensions, void, (FILE *file, XpmExtension *ext, + unsigned int num)); + +LFUNC(OpenWriteFile, int, (char *filename, xpmData *mdata)); +LFUNC(xpmDataClose, void, (xpmData *mdata)); + +int +XpmWriteFileFromImage( + Display *display, + char *filename, + XImage *image, + XImage *shapeimage, + XpmAttributes *attributes) +{ + XpmImage xpmimage; + XpmInfo info; + int ErrorStatus; + + /* create an XpmImage from the image */ + ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage, + &xpmimage, attributes); + if (ErrorStatus != XpmSuccess) + return (ErrorStatus); + + /* write the file from the XpmImage */ + if (attributes) { + xpmSetInfo(&info, attributes); + ErrorStatus = XpmWriteFileFromXpmImage(filename, &xpmimage, &info); + } else + ErrorStatus = XpmWriteFileFromXpmImage(filename, &xpmimage, NULL); + + /* free the XpmImage */ + XpmFreeXpmImage(&xpmimage); + + return (ErrorStatus); +} + +int +XpmWriteFileFromXpmImage( + char *filename, + XpmImage *image, + XpmInfo *info) +{ + xpmData mdata; + char *name, *dot, *s, new_name[BUFSIZ] = {0}; + int ErrorStatus; + + /* open file to write */ + if ((ErrorStatus = OpenWriteFile(filename, &mdata)) != XpmSuccess) + return (ErrorStatus); + + /* figure out a name */ + if (filename) { +#ifdef VMS + name = filename; +#else + if (!(name = strrchr(filename, '/')) +#ifdef AMIGA + && !(name = strrchr(filename, ':')) +#endif + ) + name = filename; + else + name++; +#endif + /* let's try to make a valid C syntax name */ + if (strchr(name, '.')) { + strncpy(new_name, name, sizeof(new_name)); + new_name[sizeof(new_name)-1] = '\0'; + /* change '.' to '_' */ + name = s = new_name; + while ((dot = strchr(s, '.'))) { + *dot = '_'; + s = dot; + } + } + if (strchr(name, '-')) { + if (name != new_name) { + strncpy(new_name, name, sizeof(new_name)); + new_name[sizeof(new_name)-1] = '\0'; + name = new_name; + } + /* change '-' to '_' */ + s = name; + while ((dot = strchr(s, '-'))) { + *dot = '_'; + s = dot; + } + } + } else + name = "image_name"; + + /* write the XpmData from the XpmImage */ + if (ErrorStatus == XpmSuccess) + ErrorStatus = xpmWriteFile(mdata.stream.file, image, name, info); + + xpmDataClose(&mdata); + + return (ErrorStatus); +} + +static int +xpmWriteFile( + FILE *file, + XpmImage *image, + char *name, + XpmInfo *info) +{ + /* calculation variables */ + unsigned int cmts, extensions; + int ErrorStatus; + + cmts = info && (info->valuemask & XpmComments); + extensions = info && (info->valuemask & XpmExtensions) + && info->nextensions; + + /* print the header line */ + fprintf(file, "/* XPM */\nstatic char * %s[] = {\n", name); + + /* print the hints line */ + if (cmts && info->hints_cmt) + fprintf(file, "/*%s*/\n", info->hints_cmt); + + fprintf(file, "\"%d %d %d %d", image->width, image->height, + image->ncolors, image->cpp); + + if (info && (info->valuemask & XpmHotspot)) + fprintf(file, " %d %d", info->x_hotspot, info->y_hotspot); + + if (extensions) + fprintf(file, " XPMEXT"); + + fprintf(file, "\",\n"); + + /* print colors */ + if (cmts && info->colors_cmt) + fprintf(file, "/*%s*/\n", info->colors_cmt); + + WriteColors(file, image->colorTable, image->ncolors); + + /* print pixels */ + if (cmts && info->pixels_cmt) + fprintf(file, "/*%s*/\n", info->pixels_cmt); + + ErrorStatus = WritePixels(file, image->width, image->height, image->cpp, + image->data, image->colorTable); + if (ErrorStatus != XpmSuccess) + return (ErrorStatus); + + /* print extensions */ + if (extensions) + WriteExtensions(file, info->extensions, info->nextensions); + + /* close the array */ + fprintf(file, "};\n"); + + return (XpmSuccess); +} + +static void +WriteColors( + FILE *file, + XpmColor *colors, + unsigned int ncolors) +{ + unsigned int a, key; + char *s; + char **defaults; + + for (a = 0; a < ncolors; a++, colors++) { + + defaults = (char **) colors; + fprintf(file, "\"%s", *defaults++); + + for (key = 1; key <= NKEYS; key++, defaults++) { + if ((s = *defaults)) + fprintf(file, "\t%s %s", xpmColorKeys[key - 1], s); + } + fprintf(file, "\",\n"); + } +} + + +static int +WritePixels( + FILE *file, + unsigned int width, + unsigned int height, + unsigned int cpp, + unsigned int *pixels, + XpmColor *colors) +{ + char *s, *p, *buf; + unsigned int x, y, h; + + h = height - 1; + if (cpp != 0 && width >= (UINT_MAX - 3)/cpp) + return XpmNoMemory; + p = buf = (char *) XpmMalloc(width * cpp + 3); + if (!buf) + return (XpmNoMemory); + *buf = '"'; + p++; + for (y = 0; y < h; y++) { + s = p; + for (x = 0; x < width; x++, pixels++) { + strncpy(s, colors[*pixels].string, cpp); + s += cpp; + } + *s++ = '"'; + *s = '\0'; + fprintf(file, "%s,\n", buf); + } + /* duplicate some code to avoid a test in the loop */ + s = p; + for (x = 0; x < width; x++, pixels++) { + strncpy(s, colors[*pixels].string, cpp); + s += cpp; + } + *s++ = '"'; + *s = '\0'; + fprintf(file, "%s", buf); + + XpmFree(buf); + return (XpmSuccess); +} + +static void +WriteExtensions( + FILE *file, + XpmExtension *ext, + unsigned int num) +{ + unsigned int x, y, n; + char **line; + + for (x = 0; x < num; x++, ext++) { + fprintf(file, ",\n\"XPMEXT %s\"", ext->name); + n = ext->nlines; + for (y = 0, line = ext->lines; y < n; y++, line++) + fprintf(file, ",\n\"%s\"", *line); + } + fprintf(file, ",\n\"XPMENDEXT\""); +} + + +#ifndef NO_ZPIPE +FUNC(xpmPipeThrough, FILE*, (int fd, + const char* cmd, + const char* arg1, + const char* mode)); +#endif + +/* + * open the given file to be written as an xpmData which is returned + */ +static int +OpenWriteFile( + char *filename, + xpmData *mdata) +{ + if (!filename) { + mdata->stream.file = (stdout); + mdata->type = XPMFILE; + } else { +#ifndef NO_ZPIPE + size_t len; +#endif + int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644); + if ( fd < 0 ) + return(XpmOpenFailed); +#ifndef NO_ZPIPE + len = strlen(filename); + if (len > 2 && !strcmp(".Z", filename + (len - 2))) { + mdata->stream.file = xpmPipeThrough(fd, "compress", NULL, "w"); + mdata->type = XPMPIPE; + } else if (len > 3 && !strcmp(".gz", filename + (len - 3))) { + mdata->stream.file = xpmPipeThrough(fd, "gzip", "-q", "w"); + mdata->type = XPMPIPE; + } else +#endif + { + mdata->stream.file = fdopen(fd, "w"); + mdata->type = XPMFILE; + } + if (!mdata->stream.file) + return (XpmOpenFailed); + } + return (XpmSuccess); +} + +/* + * close the file related to the xpmData if any + */ +static void +xpmDataClose(xpmData *mdata) +{ + if (mdata->stream.file != (stdout)) + fclose(mdata->stream.file); +} + diff --git a/libXpm/src/XpmI.h b/libXpm/src/XpmI.h index ead31ab82..9d4b1aeee 100644 --- a/libXpm/src/XpmI.h +++ b/libXpm/src/XpmI.h @@ -1,332 +1,332 @@ -/*
- * Copyright (C) 1989-95 GROUPE BULL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of GROUPE BULL shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from GROUPE BULL.
- */
-
-/*****************************************************************************\
-* XpmI.h: *
-* *
-* XPM library *
-* Internal Include file *
-* *
-* ** Everything defined here is subject to changes any time. ** *
-* *
-* Developed by Arnaud Le Hors *
-\*****************************************************************************/
-
-/*
- * The code related to FOR_MSW has been added by
- * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
- */
-
-#ifndef XPMI_h
-#define XPMI_h
-
-#include "xpm.h"
-
-/*
- * lets try to solve include files
- */
-
-#include <sys/types.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <limits.h>
-/* stdio.h doesn't declare popen on a Sequent DYNIX OS */
-#ifdef sequent
-extern FILE *popen();
-#endif
-
-#ifdef FOR_MSW
-#include "simx.h"
-#else
-#include <X11/Xos.h>
-#include <X11/Xfuncs.h>
-#include <X11/Xmd.h>
-#endif
-
-#ifdef VMS
-#include <unixio.h>
-#include <file.h>
-#endif
-
-/* The following should help people wanting to use their own memory allocation
- * functions. To avoid the overhead of a function call when the standard
- * functions are used these are all macros, even the XpmFree function which
- * needs to be a real function for the outside world though.
- * So if change these be sure to change the XpmFree function in misc.c
- * accordingly.
- */
-#define XpmFree(ptr) free(ptr)
-
-#ifndef FOR_MSW
-#define XpmMalloc(size) malloc((size))
-#define XpmRealloc(ptr, size) realloc((ptr), (size))
-#define XpmCalloc(nelem, elsize) calloc((nelem), (elsize))
-#else
-/* checks for mallocs bigger than 64K */
-#define XpmMalloc(size) boundCheckingMalloc((long)(size))/* in simx.[ch] */
-#define XpmRealloc(ptr, size) boundCheckingRealloc((ptr),(long)(size))
-#define XpmCalloc(nelem, elsize) \
- boundCheckingCalloc((long)(nelem),(long) (elsize))
-#endif
-
-#if defined(SCO) || defined(__USLC__)
-#include <stdint.h> /* For SIZE_MAX */
-#endif
-#include <limits.h>
-#ifndef SIZE_MAX
-# ifdef ULONG_MAX
-# define SIZE_MAX ULONG_MAX
-# else
-# define SIZE_MAX UINT_MAX
-# endif
-#endif
-
-#define XPMMAXCMTLEN BUFSIZ
-typedef struct {
- unsigned int type;
- union {
- FILE *file;
- char **data;
- } stream;
- char *cptr;
- unsigned int line;
- int CommentLength;
- char Comment[XPMMAXCMTLEN];
- char *Bcmt, *Ecmt, Bos, Eos;
- int format; /* 1 if XPM1, 0 otherwise */
-#ifdef CXPMPROG
- int lineNum;
- int charNum;
-#endif
-} xpmData;
-
-#define XPMARRAY 0
-#define XPMFILE 1
-#define XPMPIPE 2
-#define XPMBUFFER 3
-
-#define EOL '\n'
-#define TAB '\t'
-#define SPC ' '
-
-typedef struct {
- char *type; /* key word */
- char *Bcmt; /* string beginning comments */
- char *Ecmt; /* string ending comments */
- char Bos; /* character beginning strings */
- char Eos; /* character ending strings */
- char *Strs; /* strings separator */
- char *Dec; /* data declaration string */
- char *Boa; /* string beginning assignment */
- char *Eoa; /* string ending assignment */
-} xpmDataType;
-
-extern xpmDataType xpmDataTypes[];
-
-/*
- * rgb values and ascii names (from rgb text file) rgb values,
- * range of 0 -> 65535 color mnemonic of rgb value
- */
-typedef struct {
- int r, g, b;
- char *name;
-} xpmRgbName;
-
-/* Maximum number of rgb mnemonics allowed in rgb text file. */
-#define MAX_RGBNAMES 1024
-
-extern char *xpmColorKeys[];
-
-#define TRANSPARENT_COLOR "None" /* this must be a string! */
-
-/* number of xpmColorKeys */
-#define NKEYS 5
-
-/* XPM internal routines */
-
-FUNC(xpmParseData, int, (xpmData *data, XpmImage *image, XpmInfo *info));
-FUNC(xpmParseDataAndCreate, int, (Display *display, xpmData *data,
- XImage **image_return,
- XImage **shapeimage_return,
- XpmImage *image, XpmInfo *info,
- XpmAttributes *attributes));
-
-FUNC(xpmFreeColorTable, void, (XpmColor *colorTable, int ncolors));
-
-FUNC(xpmInitAttributes, void, (XpmAttributes *attributes));
-
-FUNC(xpmInitXpmImage, void, (XpmImage *image));
-
-FUNC(xpmInitXpmInfo, void, (XpmInfo *info));
-
-FUNC(xpmSetInfoMask, void, (XpmInfo *info, XpmAttributes *attributes));
-FUNC(xpmSetInfo, void, (XpmInfo *info, XpmAttributes *attributes));
-FUNC(xpmSetAttributes, void, (XpmAttributes *attributes, XpmImage *image,
- XpmInfo *info));
-
-#if !defined(FOR_MSW) && !defined(AMIGA)
-FUNC(xpmCreatePixmapFromImage, void, (Display *display, Drawable d,
- XImage *ximage, Pixmap *pixmap_return));
-
-FUNC(xpmCreateImageFromPixmap, void, (Display *display, Pixmap pixmap,
- XImage **ximage_return,
- unsigned int *width,
- unsigned int *height));
-#endif
-
-/* structures and functions related to hastable code */
-
-typedef struct _xpmHashAtom {
- char *name;
- void *data;
-} *xpmHashAtom;
-
-typedef struct {
- unsigned int size;
- unsigned int limit;
- unsigned int used;
- xpmHashAtom *atomTable;
-} xpmHashTable;
-
-FUNC(xpmHashTableInit, int, (xpmHashTable *table));
-FUNC(xpmHashTableFree, void, (xpmHashTable *table));
-FUNC(xpmHashSlot, xpmHashAtom *, (xpmHashTable *table, char *s));
-FUNC(xpmHashIntern, int, (xpmHashTable *table, char *tag, void *data));
-
-#define HashAtomData(i) ((void *)(long)i)
-#define HashColorIndex(slot) ((unsigned long)((*slot)->data))
-#define USE_HASHTABLE (cpp > 2 && ncolors > 4)
-
-/* I/O utility */
-
-FUNC(xpmNextString, int, (xpmData *mdata));
-FUNC(xpmNextUI, int, (xpmData *mdata, unsigned int *ui_return));
-FUNC(xpmGetString, int, (xpmData *mdata, char **sptr, unsigned int *l));
-
-#define xpmGetC(mdata) \
- ((!mdata->type || mdata->type == XPMBUFFER) ? \
- (*mdata->cptr++) : (getc(mdata->stream.file)))
-
-FUNC(xpmNextWord, unsigned int,
- (xpmData *mdata, char *buf, unsigned int buflen));
-FUNC(xpmGetCmt, int, (xpmData *mdata, char **cmt));
-FUNC(xpmParseHeader, int, (xpmData *mdata));
-FUNC(xpmParseValues, 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));
-
-FUNC(xpmParseColors, int, (xpmData *data, unsigned int ncolors,
- unsigned int cpp, XpmColor **colorTablePtr,
- xpmHashTable *hashtable));
-
-FUNC(xpmParseExtensions, int, (xpmData *data, XpmExtension **extensions,
- unsigned int *nextensions));
-
-/* RGB utility */
-
-FUNC(xpmReadRgbNames, int, (char *rgb_fname, xpmRgbName *rgbn));
-FUNC(xpmGetRgbName, char *, (xpmRgbName *rgbn, int rgbn_max,
- int red, int green, int blue));
-FUNC(xpmFreeRgbNames, void, (xpmRgbName *rgbn, int rgbn_max));
-#ifdef FOR_MSW
-FUNC(xpmGetRGBfromName,int, (char *name, int *r, int *g, int *b));
-#endif
-
-#ifndef AMIGA
-FUNC(xpm_xynormalizeimagebits, void, (register unsigned char *bp,
- register XImage *img));
-FUNC(xpm_znormalizeimagebits, void, (register unsigned char *bp,
- register XImage *img));
-
-/*
- * Macros
- *
- * The XYNORMALIZE macro determines whether XY format data requires
- * normalization and calls a routine to do so if needed. The logic in
- * this module is designed for LSBFirst byte and bit order, so
- * normalization is done as required to present the data in this order.
- *
- * The ZNORMALIZE macro performs byte and nibble order normalization if
- * required for Z format data.
- *
- * The XYINDEX macro computes the index to the starting byte (char) boundary
- * for a bitmap_unit containing a pixel with coordinates x and y for image
- * data in XY format.
- *
- * The ZINDEX* macros compute the index to the starting byte (char) boundary
- * for a pixel with coordinates x and y for image data in ZPixmap format.
- *
- */
-
-#define XYNORMALIZE(bp, img) \
- if ((img->byte_order == MSBFirst) || (img->bitmap_bit_order == MSBFirst)) \
- xpm_xynormalizeimagebits((unsigned char *)(bp), img)
-
-#define ZNORMALIZE(bp, img) \
- if (img->byte_order == MSBFirst) \
- xpm_znormalizeimagebits((unsigned char *)(bp), img)
-
-#define XYINDEX(x, y, img) \
- ((y) * img->bytes_per_line) + \
- (((x) + img->xoffset) / img->bitmap_unit) * (img->bitmap_unit >> 3)
-
-#define ZINDEX(x, y, img) ((y) * img->bytes_per_line) + \
- (((x) * img->bits_per_pixel) >> 3)
-
-#define ZINDEX32(x, y, img) ((y) * img->bytes_per_line) + ((x) << 2)
-
-#define ZINDEX16(x, y, img) ((y) * img->bytes_per_line) + ((x) << 1)
-
-#define ZINDEX8(x, y, img) ((y) * img->bytes_per_line) + (x)
-
-#define ZINDEX1(x, y, img) ((y) * img->bytes_per_line) + ((x) >> 3)
-#endif /* not AMIGA */
-
-#ifdef __STDC__
-#define Const const
-#else
-#define Const /**/
-#endif
-
-#ifdef NEED_STRDUP
-FUNC(xpmstrdup, char *, (char *s1));
-#else
-#undef xpmstrdup
-#define xpmstrdup strdup
-#endif
-
-#ifdef NEED_STRCASECMP
-FUNC(xpmstrcasecmp, int, (char *s1, char *s2));
-#else
-#undef xpmstrcasecmp
-#define xpmstrcasecmp strcasecmp
-#endif
-
-FUNC(xpmatoui, unsigned int,
- (char *p, unsigned int l, unsigned int *ui_return));
-
-#endif
+/* + * Copyright (C) 1989-95 GROUPE BULL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of GROUPE BULL shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from GROUPE BULL. + */ + +/*****************************************************************************\ +* XpmI.h: * +* * +* XPM library * +* Internal Include file * +* * +* ** Everything defined here is subject to changes any time. ** * +* * +* Developed by Arnaud Le Hors * +\*****************************************************************************/ + +/* + * The code related to FOR_MSW has been added by + * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94 + */ + +#ifndef XPMI_h +#define XPMI_h + +#include "xpm.h" + +/* + * lets try to solve include files + */ + +#include <sys/types.h> +#include <stdio.h> +#include <stdlib.h> +#include <limits.h> +/* stdio.h doesn't declare popen on a Sequent DYNIX OS */ +#ifdef sequent +extern FILE *popen(); +#endif + +#ifdef FOR_MSW +#include "simx.h" +#else +#include <X11/Xos.h> +#include <X11/Xfuncs.h> +#include <X11/Xmd.h> +#endif + +#ifdef VMS +#include <unixio.h> +#include <file.h> +#endif + +/* The following should help people wanting to use their own memory allocation + * functions. To avoid the overhead of a function call when the standard + * functions are used these are all macros, even the XpmFree function which + * needs to be a real function for the outside world though. + * So if change these be sure to change the XpmFree function in misc.c + * accordingly. + */ +#define XpmFree(ptr) free(ptr) + +#ifndef FOR_MSW +#define XpmMalloc(size) malloc((size)) +#define XpmRealloc(ptr, size) realloc((ptr), (size)) +#define XpmCalloc(nelem, elsize) calloc((nelem), (elsize)) +#else +/* checks for mallocs bigger than 64K */ +#define XpmMalloc(size) boundCheckingMalloc((long)(size))/* in simx.[ch] */ +#define XpmRealloc(ptr, size) boundCheckingRealloc((ptr),(long)(size)) +#define XpmCalloc(nelem, elsize) \ + boundCheckingCalloc((long)(nelem),(long) (elsize)) +#endif + +#if defined(SCO) || defined(__USLC__) +#include <stdint.h> /* For SIZE_MAX */ +#endif +#include <limits.h> +#ifndef SIZE_MAX +# ifdef ULONG_MAX +# define SIZE_MAX ULONG_MAX +# else +# define SIZE_MAX UINT_MAX +# endif +#endif + +#define XPMMAXCMTLEN BUFSIZ +typedef struct { + unsigned int type; + union { + FILE *file; + char **data; + } stream; + char *cptr; + unsigned int line; + int CommentLength; + char Comment[XPMMAXCMTLEN]; + char *Bcmt, *Ecmt, Bos, Eos; + int format; /* 1 if XPM1, 0 otherwise */ +#ifdef CXPMPROG + int lineNum; + int charNum; +#endif +} xpmData; + +#define XPMARRAY 0 +#define XPMFILE 1 +#define XPMPIPE 2 +#define XPMBUFFER 3 + +#define EOL '\n' +#define TAB '\t' +#define SPC ' ' + +typedef struct { + char *type; /* key word */ + char *Bcmt; /* string beginning comments */ + char *Ecmt; /* string ending comments */ + char Bos; /* character beginning strings */ + char Eos; /* character ending strings */ + char *Strs; /* strings separator */ + char *Dec; /* data declaration string */ + char *Boa; /* string beginning assignment */ + char *Eoa; /* string ending assignment */ +} xpmDataType; + +extern xpmDataType xpmDataTypes[]; + +/* + * rgb values and ascii names (from rgb text file) rgb values, + * range of 0 -> 65535 color mnemonic of rgb value + */ +typedef struct { + int r, g, b; + char *name; +} xpmRgbName; + +/* Maximum number of rgb mnemonics allowed in rgb text file. */ +#define MAX_RGBNAMES 1024 + +extern char *xpmColorKeys[]; + +#define TRANSPARENT_COLOR "None" /* this must be a string! */ + +/* number of xpmColorKeys */ +#define NKEYS 5 + +/* XPM internal routines */ + +FUNC(xpmParseData, int, (xpmData *data, XpmImage *image, XpmInfo *info)); +FUNC(xpmParseDataAndCreate, int, (Display *display, xpmData *data, + XImage **image_return, + XImage **shapeimage_return, + XpmImage *image, XpmInfo *info, + XpmAttributes *attributes)); + +FUNC(xpmFreeColorTable, void, (XpmColor *colorTable, int ncolors)); + +FUNC(xpmInitAttributes, void, (XpmAttributes *attributes)); + +FUNC(xpmInitXpmImage, void, (XpmImage *image)); + +FUNC(xpmInitXpmInfo, void, (XpmInfo *info)); + +FUNC(xpmSetInfoMask, void, (XpmInfo *info, XpmAttributes *attributes)); +FUNC(xpmSetInfo, void, (XpmInfo *info, XpmAttributes *attributes)); +FUNC(xpmSetAttributes, void, (XpmAttributes *attributes, XpmImage *image, + XpmInfo *info)); + +#if !defined(FOR_MSW) && !defined(AMIGA) +FUNC(xpmCreatePixmapFromImage, void, (Display *display, Drawable d, + XImage *ximage, Pixmap *pixmap_return)); + +FUNC(xpmCreateImageFromPixmap, void, (Display *display, Pixmap pixmap, + XImage **ximage_return, + unsigned int *width, + unsigned int *height)); +#endif + +/* structures and functions related to hastable code */ + +typedef struct _xpmHashAtom { + char *name; + void *data; +} *xpmHashAtom; + +typedef struct { + unsigned int size; + unsigned int limit; + unsigned int used; + xpmHashAtom *atomTable; +} xpmHashTable; + +FUNC(xpmHashTableInit, int, (xpmHashTable *table)); +FUNC(xpmHashTableFree, void, (xpmHashTable *table)); +FUNC(xpmHashSlot, xpmHashAtom *, (xpmHashTable *table, char *s)); +FUNC(xpmHashIntern, int, (xpmHashTable *table, char *tag, void *data)); + +#define HashAtomData(i) ((void *)(long)i) +#define HashColorIndex(slot) ((unsigned long)((*slot)->data)) +#define USE_HASHTABLE (cpp > 2 && ncolors > 4) + +/* I/O utility */ + +FUNC(xpmNextString, int, (xpmData *mdata)); +FUNC(xpmNextUI, int, (xpmData *mdata, unsigned int *ui_return)); +FUNC(xpmGetString, int, (xpmData *mdata, char **sptr, unsigned int *l)); + +#define xpmGetC(mdata) \ + ((!mdata->type || mdata->type == XPMBUFFER) ? \ + (*mdata->cptr++) : (getc(mdata->stream.file))) + +FUNC(xpmNextWord, unsigned int, + (xpmData *mdata, char *buf, unsigned int buflen)); +FUNC(xpmGetCmt, int, (xpmData *mdata, char **cmt)); +FUNC(xpmParseHeader, int, (xpmData *mdata)); +FUNC(xpmParseValues, 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)); + +FUNC(xpmParseColors, int, (xpmData *data, unsigned int ncolors, + unsigned int cpp, XpmColor **colorTablePtr, + xpmHashTable *hashtable)); + +FUNC(xpmParseExtensions, int, (xpmData *data, XpmExtension **extensions, + unsigned int *nextensions)); + +/* RGB utility */ + +FUNC(xpmReadRgbNames, int, (char *rgb_fname, xpmRgbName *rgbn)); +FUNC(xpmGetRgbName, char *, (xpmRgbName *rgbn, int rgbn_max, + int red, int green, int blue)); +FUNC(xpmFreeRgbNames, void, (xpmRgbName *rgbn, int rgbn_max)); +#ifdef FOR_MSW +FUNC(xpmGetRGBfromName,int, (char *name, int *r, int *g, int *b)); +#endif + +#ifndef AMIGA +FUNC(xpm_xynormalizeimagebits, void, (register unsigned char *bp, + register XImage *img)); +FUNC(xpm_znormalizeimagebits, void, (register unsigned char *bp, + register XImage *img)); + +/* + * Macros + * + * The XYNORMALIZE macro determines whether XY format data requires + * normalization and calls a routine to do so if needed. The logic in + * this module is designed for LSBFirst byte and bit order, so + * normalization is done as required to present the data in this order. + * + * The ZNORMALIZE macro performs byte and nibble order normalization if + * required for Z format data. + * + * The XYINDEX macro computes the index to the starting byte (char) boundary + * for a bitmap_unit containing a pixel with coordinates x and y for image + * data in XY format. + * + * The ZINDEX* macros compute the index to the starting byte (char) boundary + * for a pixel with coordinates x and y for image data in ZPixmap format. + * + */ + +#define XYNORMALIZE(bp, img) \ + if ((img->byte_order == MSBFirst) || (img->bitmap_bit_order == MSBFirst)) \ + xpm_xynormalizeimagebits((unsigned char *)(bp), img) + +#define ZNORMALIZE(bp, img) \ + if (img->byte_order == MSBFirst) \ + xpm_znormalizeimagebits((unsigned char *)(bp), img) + +#define XYINDEX(x, y, img) \ + ((y) * img->bytes_per_line) + \ + (((x) + img->xoffset) / img->bitmap_unit) * (img->bitmap_unit >> 3) + +#define ZINDEX(x, y, img) ((y) * img->bytes_per_line) + \ + (((x) * img->bits_per_pixel) >> 3) + +#define ZINDEX32(x, y, img) ((y) * img->bytes_per_line) + ((x) << 2) + +#define ZINDEX16(x, y, img) ((y) * img->bytes_per_line) + ((x) << 1) + +#define ZINDEX8(x, y, img) ((y) * img->bytes_per_line) + (x) + +#define ZINDEX1(x, y, img) ((y) * img->bytes_per_line) + ((x) >> 3) +#endif /* not AMIGA */ + +#ifdef __STDC__ +#define Const const +#else +#define Const /**/ +#endif + +#ifdef NEED_STRDUP +FUNC(xpmstrdup, char *, (char *s1)); +#else +#undef xpmstrdup +#define xpmstrdup strdup +#endif + +#ifdef NEED_STRCASECMP +FUNC(xpmstrcasecmp, int, (char *s1, char *s2)); +#else +#undef xpmstrcasecmp +#define xpmstrcasecmp strcasecmp +#endif + +FUNC(xpmatoui, unsigned int, + (char *p, unsigned int l, unsigned int *ui_return)); + +#endif diff --git a/libXpm/src/create.c b/libXpm/src/create.c index f9823ca6c..7c75a4211 100644 --- a/libXpm/src/create.c +++ b/libXpm/src/create.c @@ -1,2517 +1,2517 @@ -/*
- * Copyright (C) 1989-95 GROUPE BULL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of GROUPE BULL shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from GROUPE BULL.
- */
-
-/*****************************************************************************\
-* create.c: *
-* *
-* XPM library *
-* Create an X image and possibly its related shape mask *
-* from the given XpmImage. *
-* *
-* Developed by Arnaud Le Hors *
-\*****************************************************************************/
-
-/*
- * The code related to FOR_MSW has been added by
- * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
- */
-
-/*
- * The code related to AMIGA has been added by
- * Lorens Younes (d93-hyo@nada.kth.se) 4/96
- */
-
-/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "XpmI.h"
-#include <ctype.h>
-
-LFUNC(xpmVisualType, int, (Visual *visual));
-
-LFUNC(AllocColor, int, (Display *display, Colormap colormap,
- char *colorname, XColor *xcolor, void *closure));
-LFUNC(FreeColors, int, (Display *display, Colormap colormap,
- Pixel *pixels, int n, void *closure));
-
-#ifndef FOR_MSW
-LFUNC(SetCloseColor, int, (Display *display, Colormap colormap,
- Visual *visual, XColor *col,
- Pixel *image_pixel, Pixel *mask_pixel,
- Pixel *alloc_pixels, unsigned int *nalloc_pixels,
- XpmAttributes *attributes, XColor *cols, int ncols,
- XpmAllocColorFunc allocColor, void *closure));
-#else
-/* let the window system take care of close colors */
-#endif
-
-LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual,
- char *colorname, unsigned int color_index,
- Pixel *image_pixel, Pixel *mask_pixel,
- unsigned int *mask_pixel_index,
- Pixel *alloc_pixels, unsigned int *nalloc_pixels,
- Pixel *used_pixels, unsigned int *nused_pixels,
- XpmAttributes *attributes, XColor *cols, int ncols,
- XpmAllocColorFunc allocColor, void *closure));
-
-LFUNC(CreateXImage, int, (Display *display, Visual *visual,
- unsigned int depth, int format, unsigned int width,
- unsigned int height, XImage **image_return));
-
-LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes,
- XpmColor *colors, unsigned int ncolors,
- Pixel *image_pixels, Pixel *mask_pixels,
- unsigned int *mask_pixel_index,
- Pixel *alloc_pixels, unsigned int *nalloc_pixels,
- Pixel *used_pixels, unsigned int *nused_pixels));
-
-#ifndef FOR_MSW
-LFUNC(ParseAndPutPixels, int, (xpmData *data, unsigned int width,
- unsigned int height, unsigned int ncolors,
- unsigned int cpp, XpmColor *colorTable,
- xpmHashTable *hashtable,
- XImage *image, Pixel *image_pixels,
- XImage *mask, Pixel *mask_pixels));
-#else /* FOR_MSW */
-LFUNC(ParseAndPutPixels, int, (Display *dc, xpmData *data, unsigned int width,
- unsigned int height, unsigned int ncolors,
- unsigned int cpp, XpmColor *colorTable,
- xpmHashTable *hashtable,
- XImage *image, Pixel *image_pixels,
- XImage *mask, Pixel *mask_pixels));
-#endif
-
-#ifndef FOR_MSW
-# ifndef AMIGA
-/* XImage pixel routines */
-LFUNC(PutImagePixels, void, (XImage *image, unsigned int width,
- unsigned int height, unsigned int *pixelindex,
- Pixel *pixels));
-
-LFUNC(PutImagePixels32, void, (XImage *image, unsigned int width,
- unsigned int height, unsigned int *pixelindex,
- Pixel *pixels));
-
-LFUNC(PutImagePixels16, void, (XImage *image, unsigned int width,
- unsigned int height, unsigned int *pixelindex,
- Pixel *pixels));
-
-LFUNC(PutImagePixels8, void, (XImage *image, unsigned int width,
- unsigned int height, unsigned int *pixelindex,
- Pixel *pixels));
-
-LFUNC(PutImagePixels1, void, (XImage *image, unsigned int width,
- unsigned int height, unsigned int *pixelindex,
- Pixel *pixels));
-
-LFUNC(PutPixel1, int, (XImage *ximage, int x, int y, unsigned long pixel));
-LFUNC(PutPixel, int, (XImage *ximage, int x, int y, unsigned long pixel));
-#if !defined(WORD64) && !defined(LONG64)
-LFUNC(PutPixel32, int, (XImage *ximage, int x, int y, unsigned long pixel));
-#endif
-LFUNC(PutPixel32MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
-LFUNC(PutPixel32LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
-LFUNC(PutPixel16MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
-LFUNC(PutPixel16LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
-LFUNC(PutPixel8, int, (XImage *ximage, int x, int y, unsigned long pixel));
-LFUNC(PutPixel1MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
-LFUNC(PutPixel1LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
-
-# else /* AMIGA */
-LFUNC(APutImagePixels, void, (XImage *ximage, unsigned int width,
- unsigned int height, unsigned int *pixelindex,
- Pixel *pixels));
-# endif/* AMIGA */
-#else /* FOR_MSW */
-/* FOR_MSW pixel routine */
-LFUNC(MSWPutImagePixels, void, (Display *dc, XImage *image,
- unsigned int width, unsigned int height,
- unsigned int *pixelindex, Pixel *pixels));
-#endif /* FOR_MSW */
-
-#ifdef NEED_STRCASECMP
-FUNC(xpmstrcasecmp, int, (char *s1, char *s2));
-
-/*
- * in case strcasecmp is not provided by the system here is one
- * which does the trick
- */
-int
-xpmstrcasecmp(
- register char *s1,
- register char *s2)
-{
- register int c1, c2;
-
- while (*s1 && *s2) {
- c1 = tolower(*s1);
- c2 = tolower(*s2);
- if (c1 != c2)
- return (c1 - c2);
- s1++;
- s2++;
- }
- return (int) (*s1 - *s2);
-}
-
-#endif
-
-/*
- * return the default color key related to the given visual
- */
-static int
-xpmVisualType(Visual *visual)
-{
-#ifndef FOR_MSW
-# ifndef AMIGA
- switch (visual->class) {
- case StaticGray:
- case GrayScale:
- switch (visual->map_entries) {
- case 2:
- return (XPM_MONO);
- case 4:
- return (XPM_GRAY4);
- default:
- return (XPM_GRAY);
- }
- default:
- return (XPM_COLOR);
- }
-# else
- /* set the key explicitly in the XpmAttributes to override this */
- return (XPM_COLOR);
-# endif
-#else
- /* there should be a similar switch for MSW */
- return (XPM_COLOR);
-#endif
-}
-
-
-typedef struct {
- int cols_index;
- long closeness;
-} CloseColor;
-
-static int
-closeness_cmp(Const void *a, Const void *b)
-{
- CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
-
- /* cast to int as qsort requires */
- return (int) (x->closeness - y->closeness);
-}
-
-
-/* default AllocColor function:
- * call XParseColor if colorname is given, return negative value if failure
- * call XAllocColor and return 0 if failure, positive otherwise
- */
-static int
-AllocColor(
- Display *display,
- Colormap colormap,
- char *colorname,
- XColor *xcolor,
- void *closure) /* not used */
-{
- int status;
- if (colorname)
- if (!XParseColor(display, colormap, colorname, xcolor))
- return -1;
- status = XAllocColor(display, colormap, xcolor);
- return status != 0 ? 1 : 0;
-}
-
-
-#ifndef FOR_MSW
-/*
- * set a close color in case the exact one can't be set
- * return 0 if success, 1 otherwise.
- */
-
-static int
-SetCloseColor(
- Display *display,
- Colormap colormap,
- Visual *visual,
- XColor *col,
- Pixel *image_pixel,
- Pixel *mask_pixel,
- Pixel *alloc_pixels,
- unsigned int *nalloc_pixels,
- XpmAttributes *attributes,
- XColor *cols,
- int ncols,
- XpmAllocColorFunc allocColor,
- void *closure)
-{
-
- /*
- * Allocation failed, so try close colors. To get here the visual must
- * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor?
- * What about sharing systems like QDSS?). Beware: we have to treat
- * DirectColor differently.
- */
-
-
- long int red_closeness, green_closeness, blue_closeness;
- int n;
- Bool alloc_color;
-
- if (attributes && (attributes->valuemask & XpmCloseness))
- red_closeness = green_closeness = blue_closeness =
- attributes->closeness;
- else {
- red_closeness = attributes->red_closeness;
- green_closeness = attributes->green_closeness;
- blue_closeness = attributes->blue_closeness;
- }
- if (attributes && (attributes->valuemask & XpmAllocCloseColors))
- alloc_color = attributes->alloc_close_colors;
- else
- alloc_color = True;
-
- /*
- * We sort the colormap by closeness and try to allocate the color
- * closest to the target. If the allocation of this close color fails,
- * which almost never happens, then one of two scenarios is possible.
- * Either the colormap must have changed (since the last close color
- * allocation or possibly while we were sorting the colormap), or the
- * color is allocated as Read/Write by some other client. (Note: X
- * _should_ allow clients to check if a particular color is Read/Write,
- * but it doesn't! :-( ). We cannot determine which of these scenarios
- * occurred, so we try the next closest color, and so on, until no more
- * colors are within closeness of the target. If we knew that the
- * colormap had changed, we could skip this sequence.
- *
- * If _none_ of the colors within closeness of the target can be allocated,
- * then we can finally be pretty sure that the colormap has actually
- * changed. In this case we try to allocate the original color (again),
- * then try the closecolor stuff (again)...
- *
- * In theory it would be possible for an infinite loop to occur if another
- * process kept changing the colormap every time we sorted it, so we set
- * a maximum on the number of iterations. After this many tries, we use
- * XGrabServer() to ensure that the colormap remains unchanged.
- *
- * This approach gives particularly bad worst case performance - as many as
- * <MaximumIterations> colormap reads and sorts may be needed, and as
- * many as <MaximumIterations> * <ColormapSize> attempted allocations
- * may fail. On an 8-bit system, this means as many as 3 colormap reads,
- * 3 sorts and 768 failed allocations per execution of this code!
- * Luckily, my experiments show that in general use in a typical 8-bit
- * color environment only about 1 in every 10000 allocations fails to
- * succeed in the fastest possible time. So virtually every time what
- * actually happens is a single sort followed by a successful allocate.
- * The very first allocation also costs a colormap read, but no further
- * reads are usually necessary.
- */
-
-#define ITERATIONS 2 /* more than one is almost never
- * necessary */
-
- for (n = 0; n <= ITERATIONS; ++n) {
- CloseColor *closenesses =
- (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor));
- int i, c;
-
- for (i = 0; i < ncols; ++i) { /* build & sort closenesses table */
-#define COLOR_FACTOR 3
-#define BRIGHTNESS_FACTOR 1
-
- closenesses[i].cols_index = i;
- closenesses[i].closeness =
- COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red)
- + abs((long) col->green - (long) cols[i].green)
- + abs((long) col->blue - (long) cols[i].blue))
- + BRIGHTNESS_FACTOR * abs(((long) col->red +
- (long) col->green +
- (long) col->blue)
- - ((long) cols[i].red +
- (long) cols[i].green +
- (long) cols[i].blue));
- }
- qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp);
-
- i = 0;
- c = closenesses[i].cols_index;
- while ((long) cols[c].red >= (long) col->red - red_closeness &&
- (long) cols[c].red <= (long) col->red + red_closeness &&
- (long) cols[c].green >= (long) col->green - green_closeness &&
- (long) cols[c].green <= (long) col->green + green_closeness &&
- (long) cols[c].blue >= (long) col->blue - blue_closeness &&
- (long) cols[c].blue <= (long) col->blue + blue_closeness) {
- if (alloc_color) {
- if ((*allocColor)(display, colormap, NULL, &cols[c], closure)){
- if (n == ITERATIONS)
- XUngrabServer(display);
- XpmFree(closenesses);
- *image_pixel = cols[c].pixel;
- *mask_pixel = 1;
- alloc_pixels[(*nalloc_pixels)++] = cols[c].pixel;
- return (0);
- } else {
- ++i;
- if (i == ncols)
- break;
- c = closenesses[i].cols_index;
- }
- } else {
- if (n == ITERATIONS)
- XUngrabServer(display);
- XpmFree(closenesses);
- *image_pixel = cols[c].pixel;
- *mask_pixel = 1;
- return (0);
- }
- }
-
- /* Couldn't allocate _any_ of the close colors! */
-
- if (n == ITERATIONS)
- XUngrabServer(display);
- XpmFree(closenesses);
-
- if (i == 0 || i == ncols) /* no color close enough or cannot */
- return (1); /* alloc any color (full of r/w's) */
-
- if ((*allocColor)(display, colormap, NULL, col, closure)) {
- *image_pixel = col->pixel;
- *mask_pixel = 1;
- alloc_pixels[(*nalloc_pixels)++] = col->pixel;
- return (0);
- } else { /* colormap has probably changed, so
- * re-read... */
- if (n == ITERATIONS - 1)
- XGrabServer(display);
-
-#if 0
- if (visual->class == DirectColor) {
- /* TODO */
- } else
-#endif
- XQueryColors(display, colormap, cols, ncols);
- }
- }
- return (1);
-}
-
-#define USE_CLOSECOLOR attributes && \
-(((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \
- || ((attributes->valuemask & XpmRGBCloseness) && \
- (attributes->red_closeness != 0 \
- || attributes->green_closeness != 0 \
- || attributes->blue_closeness != 0)))
-
-#else
- /* FOR_MSW part */
- /* nothing to do here, the window system does it */
-#endif
-
-/*
- * set the color pixel related to the given colorname,
- * return 0 if success, 1 otherwise.
- */
-
-static int
-SetColor(
- Display *display,
- Colormap colormap,
- Visual *visual,
- char *colorname,
- unsigned int color_index,
- Pixel *image_pixel,
- Pixel *mask_pixel,
- unsigned int *mask_pixel_index,
- Pixel *alloc_pixels,
- unsigned int *nalloc_pixels,
- Pixel *used_pixels,
- unsigned int *nused_pixels,
- XpmAttributes *attributes,
- XColor *cols,
- int ncols,
- XpmAllocColorFunc allocColor,
- void *closure)
-{
- XColor xcolor;
- int status;
-
- if (xpmstrcasecmp(colorname, TRANSPARENT_COLOR)) {
- status = (*allocColor)(display, colormap, colorname, &xcolor, closure);
- if (status < 0) /* parse color failed */
- return (1);
-
- if (status == 0) {
-#ifndef FOR_MSW
- if (USE_CLOSECOLOR)
- return (SetCloseColor(display, colormap, visual, &xcolor,
- image_pixel, mask_pixel,
- alloc_pixels, nalloc_pixels,
- attributes, cols, ncols,
- allocColor, closure));
- else
-#endif /* ndef FOR_MSW */
- return (1);
- } else
- alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel;
- *image_pixel = xcolor.pixel;
-#ifndef FOR_MSW
- *mask_pixel = 1;
-#else
- *mask_pixel = RGB(0,0,0);
-#endif
- used_pixels[(*nused_pixels)++] = xcolor.pixel;
- } else {
- *image_pixel = 0;
-#ifndef FOR_MSW
- *mask_pixel = 0;
-#else
- *mask_pixel = RGB(255,255,255);
-#endif
- /* store the color table index */
- *mask_pixel_index = color_index;
- }
- return (0);
-}
-
-
-static int
-CreateColors(
- Display *display,
- XpmAttributes *attributes,
- XpmColor *colors,
- unsigned int ncolors,
- Pixel *image_pixels,
- Pixel *mask_pixels,
- unsigned int *mask_pixel_index,
- Pixel *alloc_pixels,
- unsigned int *nalloc_pixels,
- Pixel *used_pixels,
- unsigned int *nused_pixels)
-{
- /* variables stored in the XpmAttributes structure */
- Visual *visual;
- Colormap colormap;
- XpmColorSymbol *colorsymbols = NULL;
- unsigned int numsymbols;
- XpmAllocColorFunc allocColor;
- void *closure;
-
- char *colorname;
- unsigned int color, key;
- Bool pixel_defined;
- XpmColorSymbol *symbol = NULL;
- char **defaults;
- int ErrorStatus = XpmSuccess;
- char *s;
- int default_index;
-
- XColor *cols = NULL;
- unsigned int ncols = 0;
-
- /*
- * retrieve information from the XpmAttributes
- */
- if (attributes && attributes->valuemask & XpmColorSymbols) {
- colorsymbols = attributes->colorsymbols;
- numsymbols = attributes->numsymbols;
- } else
- numsymbols = 0;
-
- if (attributes && attributes->valuemask & XpmVisual)
- visual = attributes->visual;
- else
- visual = XDefaultVisual(display, XDefaultScreen(display));
-
- if (attributes && (attributes->valuemask & XpmColormap))
- colormap = attributes->colormap;
- else
- colormap = XDefaultColormap(display, XDefaultScreen(display));
-
- if (attributes && (attributes->valuemask & XpmColorKey))
- key = attributes->color_key;
- else
- key = xpmVisualType(visual);
-
- if (attributes && (attributes->valuemask & XpmAllocColor))
- allocColor = attributes->alloc_color;
- else
- allocColor = AllocColor;
- if (attributes && (attributes->valuemask & XpmColorClosure))
- closure = attributes->color_closure;
- else
- closure = NULL;
-
-#ifndef FOR_MSW
- if (USE_CLOSECOLOR) {
- /* originally from SetCloseColor */
-#if 0
- if (visual->class == DirectColor) {
-
- /*
- * TODO: Implement close colors for DirectColor visuals. This is
- * difficult situation. Chances are that we will never get here,
- * because any machine that supports DirectColor will probably
- * also support TrueColor (and probably PseudoColor). Also,
- * DirectColor colormaps can be very large, so looking for close
- * colors may be too slow.
- */
- } else {
-#endif
- unsigned int i;
-
-#ifndef AMIGA
- ncols = visual->map_entries;
-#else
- ncols = colormap->Count;
-#endif
- cols = (XColor *) XpmCalloc(ncols, sizeof(XColor));
- for (i = 0; i < ncols; ++i)
- cols[i].pixel = i;
- XQueryColors(display, colormap, cols, ncols);
-#if 0
- }
-#endif
- }
-#endif /* ndef FOR_MSW */
-
- switch (key) {
- case XPM_MONO:
- default_index = 2;
- break;
- case XPM_GRAY4:
- default_index = 3;
- break;
- case XPM_GRAY:
- default_index = 4;
- break;
- case XPM_COLOR:
- default:
- default_index = 5;
- break;
- }
-
- for (color = 0; color < ncolors; color++, colors++,
- image_pixels++, mask_pixels++) {
- colorname = NULL;
- pixel_defined = False;
- defaults = (char **) colors;
-
- /*
- * look for a defined symbol
- */
- if (numsymbols) {
-
- unsigned int n;
-
- s = defaults[1];
- for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) {
- if (symbol->name && s && !strcmp(symbol->name, s))
- /* override name */
- break;
- if (!symbol->name && symbol->value) { /* override value */
- int def_index = default_index;
-
- while (defaults[def_index] == NULL) /* find defined
- * colorname */
- --def_index;
- if (def_index < 2) {/* nothing towards mono, so try
- * towards color */
- def_index = default_index + 1;
- while (def_index <= 5 && defaults[def_index] == NULL)
- ++def_index;
- }
- if (def_index >= 2 && defaults[def_index] != NULL &&
- !xpmstrcasecmp(symbol->value, defaults[def_index]))
- break;
- }
- }
- if (n != numsymbols) {
- if (symbol->name && symbol->value)
- colorname = symbol->value;
- else
- pixel_defined = True;
- }
- }
- if (!pixel_defined) { /* pixel not given as symbol value */
-
- unsigned int k;
-
- if (colorname) { /* colorname given as symbol value */
- if (!SetColor(display, colormap, visual, colorname, color,
- image_pixels, mask_pixels, mask_pixel_index,
- alloc_pixels, nalloc_pixels, used_pixels,
- nused_pixels, attributes, cols, ncols,
- allocColor, closure))
- pixel_defined = True;
- else
- ErrorStatus = XpmColorError;
- }
- k = key;
- while (!pixel_defined && k > 1) {
- if (defaults[k]) {
- if (!SetColor(display, colormap, visual, defaults[k],
- color, image_pixels, mask_pixels,
- mask_pixel_index, alloc_pixels,
- nalloc_pixels, used_pixels, nused_pixels,
- attributes, cols, ncols,
- allocColor, closure)) {
- pixel_defined = True;
- break;
- } else
- ErrorStatus = XpmColorError;
- }
- k--;
- }
- k = key + 1;
- while (!pixel_defined && k < NKEYS + 1) {
- if (defaults[k]) {
- if (!SetColor(display, colormap, visual, defaults[k],
- color, image_pixels, mask_pixels,
- mask_pixel_index, alloc_pixels,
- nalloc_pixels, used_pixels, nused_pixels,
- attributes, cols, ncols,
- allocColor, closure)) {
- pixel_defined = True;
- break;
- } else
- ErrorStatus = XpmColorError;
- }
- k++;
- }
- if (!pixel_defined) {
- if (cols)
- XpmFree(cols);
- return (XpmColorFailed);
- }
- } else {
- /* simply use the given pixel */
- *image_pixels = symbol->pixel;
- /* the following makes the mask to be built even if none
- is given a particular pixel */
- if (symbol->value
- && !xpmstrcasecmp(symbol->value, TRANSPARENT_COLOR)) {
- *mask_pixels = 0;
- *mask_pixel_index = color;
- } else
- *mask_pixels = 1;
- used_pixels[(*nused_pixels)++] = *image_pixels;
- }
- }
- if (cols)
- XpmFree(cols);
- return (ErrorStatus);
-}
-
-
-/* default FreeColors function, simply call XFreeColors */
-static int
-FreeColors(
- Display *display,
- Colormap colormap,
- Pixel *pixels,
- int n,
- void *closure) /* not used */
-{
- return XFreeColors(display, colormap, pixels, n, 0);
-}
-
-
-/* function call in case of error */
-
-#undef RETURN
-#define RETURN(status) \
-do \
-{ \
- ErrorStatus = status; \
- goto error; \
-} while(0)
-
-int
-XpmCreateImageFromXpmImage(
- Display *display,
- XpmImage *image,
- XImage **image_return,
- XImage **shapeimage_return,
- XpmAttributes *attributes)
-{
- /* variables stored in the XpmAttributes structure */
- Visual *visual;
- Colormap colormap;
- unsigned int depth;
- int bitmap_format;
- XpmFreeColorsFunc freeColors;
-
- /* variables to return */
- XImage *ximage = NULL;
- XImage *shapeimage = NULL;
- unsigned int mask_pixel_index = XpmUndefPixel;
- int ErrorStatus;
-
- /* calculation variables */
- Pixel *image_pixels = NULL;
- Pixel *mask_pixels = NULL;
- Pixel *alloc_pixels = NULL;
- Pixel *used_pixels = NULL;
- unsigned int nalloc_pixels = 0;
- unsigned int nused_pixels = 0;
-
- /* initialize return values */
- if (image_return)
- *image_return = NULL;
- if (shapeimage_return)
- *shapeimage_return = NULL;
-
- /* retrieve information from the XpmAttributes */
- if (attributes && (attributes->valuemask & XpmVisual))
- visual = attributes->visual;
- else
- visual = XDefaultVisual(display, XDefaultScreen(display));
-
- if (attributes && (attributes->valuemask & XpmColormap))
- colormap = attributes->colormap;
- else
- colormap = XDefaultColormap(display, XDefaultScreen(display));
-
- if (attributes && (attributes->valuemask & XpmDepth))
- depth = attributes->depth;
- else
- depth = XDefaultDepth(display, XDefaultScreen(display));
-
- if (attributes && (attributes->valuemask & XpmBitmapFormat))
- bitmap_format = attributes->bitmap_format;
- else
- bitmap_format = ZPixmap;
-
- if (attributes && (attributes->valuemask & XpmFreeColors))
- freeColors = attributes->free_colors;
- else
- freeColors = FreeColors;
-
- ErrorStatus = XpmSuccess;
-
- if (image->ncolors >= UINT_MAX / sizeof(Pixel))
- return (XpmNoMemory);
-
- /* malloc pixels index tables */
- image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
- if (!image_pixels)
- return (XpmNoMemory);
-
- mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
- if (!mask_pixels)
- RETURN(XpmNoMemory);
-
- /* maximum of allocated pixels will be the number of colors */
- alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
- if (!alloc_pixels)
- RETURN(XpmNoMemory);
-
- /* maximum of allocated pixels will be the number of colors */
- used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
- if (!used_pixels)
- RETURN(XpmNoMemory);
-
- /* get pixel colors, store them in index tables */
- ErrorStatus = CreateColors(display, attributes, image->colorTable,
- image->ncolors, image_pixels, mask_pixels,
- &mask_pixel_index, alloc_pixels, &nalloc_pixels,
- used_pixels, &nused_pixels);
-
- if (ErrorStatus != XpmSuccess
- && (ErrorStatus < 0 || (attributes
- && (attributes->valuemask & XpmExactColors)
- && attributes->exactColors)))
- RETURN(ErrorStatus);
-
- /* create the ximage */
- if (image_return) {
- ErrorStatus = CreateXImage(display, visual, depth,
- (depth == 1 ? bitmap_format : ZPixmap),
- image->width, image->height, &ximage);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
-
-#ifndef FOR_MSW
-# ifndef AMIGA
-
- /*
- * set the ximage data using optimized functions for ZPixmap
- */
-
- if (ximage->bits_per_pixel == 8)
- PutImagePixels8(ximage, image->width, image->height,
- image->data, image_pixels);
- else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
- (ximage->byte_order == ximage->bitmap_bit_order))
- PutImagePixels1(ximage, image->width, image->height,
- image->data, image_pixels);
- else if (ximage->bits_per_pixel == 16)
- PutImagePixels16(ximage, image->width, image->height,
- image->data, image_pixels);
- else if (ximage->bits_per_pixel == 32)
- PutImagePixels32(ximage, image->width, image->height,
- image->data, image_pixels);
- else
- PutImagePixels(ximage, image->width, image->height,
- image->data, image_pixels);
-# else /* AMIGA */
- APutImagePixels(ximage, image->width, image->height,
- image->data, image_pixels);
-# endif
-#else /* FOR_MSW */
- MSWPutImagePixels(display, ximage, image->width, image->height,
- image->data, image_pixels);
-#endif
- }
- /* create the shape mask image */
- if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
- ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
- image->width, image->height, &shapeimage);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
-
-#ifndef FOR_MSW
-# ifndef AMIGA
- PutImagePixels1(shapeimage, image->width, image->height,
- image->data, mask_pixels);
-# else /* AMIGA */
- APutImagePixels(shapeimage, image->width, image->height,
- image->data, mask_pixels);
-# endif
-#else /* FOR_MSW */
- MSWPutImagePixels(display, shapeimage, image->width, image->height,
- image->data, mask_pixels);
-#endif
-
- }
- XpmFree(image_pixels);
- XpmFree(mask_pixels);
-
- /* if requested return used pixels in the XpmAttributes structure */
- if (attributes && (attributes->valuemask & XpmReturnPixels ||
-/* 3.2 backward compatibility code */
- attributes->valuemask & XpmReturnInfos)) {
-/* end 3.2 bc */
- attributes->pixels = used_pixels;
- attributes->npixels = nused_pixels;
- attributes->mask_pixel = mask_pixel_index;
- } else
- XpmFree(used_pixels);
-
- /* if requested return alloc'ed pixels in the XpmAttributes structure */
- if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
- attributes->alloc_pixels = alloc_pixels;
- attributes->nalloc_pixels = nalloc_pixels;
- } else
- XpmFree(alloc_pixels);
-
- /* return created images */
- if (image_return)
- *image_return = ximage;
- if (shapeimage_return)
- *shapeimage_return = shapeimage;
-
- return (ErrorStatus);
-
-/* exit point in case of error, free only locally allocated variables */
-error:
- if (ximage)
- XDestroyImage(ximage);
- if (shapeimage)
- XDestroyImage(shapeimage);
- if (image_pixels)
- XpmFree(image_pixels);
- if (mask_pixels)
- XpmFree(mask_pixels);
- if (nalloc_pixels)
- (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
- if (alloc_pixels)
- XpmFree(alloc_pixels);
- if (used_pixels)
- XpmFree(used_pixels);
-
- return (ErrorStatus);
-}
-
-
-/*
- * Create an XImage with its data
- */
-static int
-CreateXImage(
- Display *display,
- Visual *visual,
- unsigned int depth,
- int format,
- unsigned int width,
- unsigned int height,
- XImage **image_return)
-{
- int bitmap_pad;
-
- /* first get bitmap_pad */
- if (depth > 16)
- bitmap_pad = 32;
- else if (depth > 8)
- bitmap_pad = 16;
- else
- bitmap_pad = 8;
-
- /* then create the XImage with data = NULL and bytes_per_line = 0 */
- *image_return = XCreateImage(display, visual, depth, format, 0, 0,
- width, height, bitmap_pad, 0);
- if (!*image_return)
- return (XpmNoMemory);
-
-#if !defined(FOR_MSW) && !defined(AMIGA)
- if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) {
- XDestroyImage(*image_return);
- return XpmNoMemory;
- }
- /* now that bytes_per_line must have been set properly alloc data */
- if((*image_return)->bytes_per_line == 0 || height == 0)
- return XpmNoMemory;
- (*image_return)->data =
- (char *) XpmMalloc((*image_return)->bytes_per_line * height);
-
- if (!(*image_return)->data) {
- XDestroyImage(*image_return);
- *image_return = NULL;
- return (XpmNoMemory);
- }
-#else
- /* under FOR_MSW and AMIGA XCreateImage has done it all */
-#endif
- return (XpmSuccess);
-}
-
-#ifndef FOR_MSW
-# ifndef AMIGA
-/*
- * The functions below are written from X11R5 MIT's code (XImUtil.c)
- *
- * The idea is to have faster functions than the standard XPutPixel function
- * to build the image data. Indeed we can speed up things by suppressing tests
- * performed for each pixel. We do the same tests but at the image level.
- * We also assume that we use only ZPixmap images with null offsets.
- */
-
-LFUNC(_putbits, void, (register char *src, int dstoffset,
- register int numbits, register char *dst));
-
-LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register unsigned int nb));
-
-static unsigned char Const _reverse_byte[0x100] = {
- 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
- 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
- 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
- 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
- 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
- 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
- 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
- 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
- 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
- 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
- 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
- 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
- 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
- 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
- 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
- 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
- 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
- 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
- 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
- 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
- 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
- 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
- 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
- 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
- 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
- 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
- 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
- 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
- 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
- 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
- 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
- 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
-};
-
-static int
-_XReverse_Bytes(
- register unsigned char *bpt,
- register unsigned int nb)
-{
- do {
- *bpt = _reverse_byte[*bpt];
- bpt++;
- } while (--nb > 0); /* is nb user-controled? */
- return 0;
-}
-
-
-void
-xpm_xynormalizeimagebits(
- register unsigned char *bp,
- register XImage *img)
-{
- register unsigned char c;
-
- if (img->byte_order != img->bitmap_bit_order) {
- switch (img->bitmap_unit) {
-
- case 16:
- c = *bp;
- *bp = *(bp + 1);
- *(bp + 1) = c;
- break;
-
- case 32:
- c = *(bp + 3);
- *(bp + 3) = *bp;
- *bp = c;
- c = *(bp + 2);
- *(bp + 2) = *(bp + 1);
- *(bp + 1) = c;
- break;
- }
- }
- if (img->bitmap_bit_order == MSBFirst)
- _XReverse_Bytes(bp, img->bitmap_unit >> 3);
-}
-
-void
-xpm_znormalizeimagebits(
- register unsigned char *bp,
- register XImage *img)
-{
- register unsigned char c;
-
- switch (img->bits_per_pixel) {
-
- case 2:
- _XReverse_Bytes(bp, 1);
- break;
-
- case 4:
- *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
- break;
-
- case 16:
- c = *bp;
- *bp = *(bp + 1);
- *(bp + 1) = c;
- break;
-
- case 24:
- c = *(bp + 2);
- *(bp + 2) = *bp;
- *bp = c;
- break;
-
- case 32:
- c = *(bp + 3);
- *(bp + 3) = *bp;
- *bp = c;
- c = *(bp + 2);
- *(bp + 2) = *(bp + 1);
- *(bp + 1) = c;
- break;
- }
-}
-
-static unsigned char Const _lomask[0x09] = {
-0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
-static unsigned char Const _himask[0x09] = {
-0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
-
-static void
-_putbits(
- register char *src, /* address of source bit string */
- int dstoffset, /* bit offset into destination;
- * range is 0-31 */
- register int numbits, /* number of bits to copy to
- * destination */
- register char *dst) /* address of destination bit string */
-{
- register unsigned char chlo, chhi;
- int hibits;
-
- dst = dst + (dstoffset >> 3);
- dstoffset = dstoffset & 7;
- hibits = 8 - dstoffset;
- chlo = *dst & _lomask[dstoffset];
- for (;;) {
- chhi = (*src << dstoffset) & _himask[dstoffset];
- if (numbits <= hibits) {
- chhi = chhi & _lomask[dstoffset + numbits];
- *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
- break;
- }
- *dst = chhi | chlo;
- dst++;
- numbits = numbits - hibits;
- chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
- src++;
- if (numbits <= dstoffset) {
- chlo = chlo & _lomask[numbits];
- *dst = (*dst & _himask[numbits]) | chlo;
- break;
- }
- numbits = numbits - dstoffset;
- }
-}
-
-/*
- * Default method to write pixels into a Z image data structure.
- * The algorithm used is:
- *
- * copy the destination bitmap_unit or Zpixel to temp
- * normalize temp if needed
- * copy the pixel bits into the temp
- * renormalize temp if needed
- * copy the temp back into the destination image data
- */
-
-static void
-PutImagePixels(
- XImage *image,
- unsigned int width,
- unsigned int height,
- unsigned int *pixelindex,
- Pixel *pixels)
-{
- register char *src;
- register char *dst;
- register unsigned int *iptr;
- register unsigned int x, y;
- register char *data;
- Pixel pixel, px;
- int nbytes, depth, ibu, ibpp, i;
-
- data = image->data;
- iptr = pixelindex;
- depth = image->depth;
- if (depth == 1) {
- ibu = image->bitmap_unit;
- for (y = 0; y < height; y++) /* how can we trust height */
- for (x = 0; x < width; x++, iptr++) { /* how can we trust width */
- pixel = pixels[*iptr];
- for (i = 0, px = pixel; i < sizeof(unsigned long);
- i++, px >>= 8)
- ((unsigned char *) &pixel)[i] = px;
- src = &data[XYINDEX(x, y, image)];
- dst = (char *) &px;
- px = 0;
- nbytes = ibu >> 3;
- for (i = nbytes; --i >= 0;)
- *dst++ = *src++;
- XYNORMALIZE(&px, image);
- _putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
- XYNORMALIZE(&px, image);
- src = (char *) &px;
- dst = &data[XYINDEX(x, y, image)];
- for (i = nbytes; --i >= 0;)
- *dst++ = *src++;
- }
- } else {
- ibpp = image->bits_per_pixel;
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- pixel = pixels[*iptr];
- if (depth == 4)
- pixel &= 0xf;
- for (i = 0, px = pixel; i < sizeof(unsigned long); i++,
- px >>= 8)
- ((unsigned char *) &pixel)[i] = px;
- src = &data[ZINDEX(x, y, image)];
- dst = (char *) &px;
- px = 0;
- nbytes = (ibpp + 7) >> 3;
- for (i = nbytes; --i >= 0;)
- *dst++ = *src++;
- ZNORMALIZE(&px, image);
- _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
- ZNORMALIZE(&px, image);
- src = (char *) &px;
- dst = &data[ZINDEX(x, y, image)];
- for (i = nbytes; --i >= 0;)
- *dst++ = *src++;
- }
- }
-}
-
-/*
- * write pixels into a 32-bits Z image data structure
- */
-
-#if !defined(WORD64) && !defined(LONG64)
-/* this item is static but deterministic so let it slide; doesn't
- * hurt re-entrancy of this library. Note if it is actually const then would
- * be OK under rules of ANSI-C but probably not C++ which may not
- * want to allocate space for it.
- */
-static unsigned long byteorderpixel = MSBFirst << 24;
-
-#endif
-
-/*
- WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
- 3.2e code - by default you get the speeded-up version.
-*/
-
-static void
-PutImagePixels32(
- XImage *image,
- unsigned int width,
- unsigned int height,
- unsigned int *pixelindex,
- Pixel *pixels)
-{
- unsigned char *data;
- unsigned int *iptr;
- unsigned int y;
- Pixel pixel;
-
-#ifdef WITHOUT_SPEEDUPS
-
- unsigned int x;
- unsigned char *addr;
-
- data = (unsigned char *) image->data;
- iptr = pixelindex;
-#if !defined(WORD64) && !defined(LONG64)
- if (*((char *) &byteorderpixel) == image->byte_order) {
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- addr = &data[ZINDEX32(x, y, image)];
- *((unsigned long *) addr) = pixels[*iptr];
- }
- } else
-#endif
- if (image->byte_order == MSBFirst)
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- addr = &data[ZINDEX32(x, y, image)];
- pixel = pixels[*iptr];
- addr[0] = pixel >> 24;
- addr[1] = pixel >> 16;
- addr[2] = pixel >> 8;
- addr[3] = pixel;
- }
- else
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- addr = &data[ZINDEX32(x, y, image)];
- pixel = pixels[*iptr];
- addr[0] = pixel;
- addr[1] = pixel >> 8;
- addr[2] = pixel >> 16;
- addr[3] = pixel >> 24;
- }
-
-#else /* WITHOUT_SPEEDUPS */
-
- unsigned int bpl = image->bytes_per_line;
- unsigned char *data_ptr, *max_data;
-
- data = (unsigned char *) image->data;
- iptr = pixelindex;
-#if !defined(WORD64) && !defined(LONG64)
- if (*((char *) &byteorderpixel) == image->byte_order) {
- for (y = 0; y < height; y++) {
- data_ptr = data;
- max_data = data_ptr + (width << 2);
-
- while (data_ptr < max_data) {
- *((unsigned long *) data_ptr) = pixels[*(iptr++)];
- data_ptr += (1 << 2);
- }
- data += bpl;
- }
- } else
-#endif
- if (image->byte_order == MSBFirst)
- for (y = 0; y < height; y++) {
- data_ptr = data;
- max_data = data_ptr + (width << 2);
-
- while (data_ptr < max_data) {
- pixel = pixels[*(iptr++)];
-
- *data_ptr++ = pixel >> 24;
- *data_ptr++ = pixel >> 16;
- *data_ptr++ = pixel >> 8;
- *data_ptr++ = pixel;
-
- }
- data += bpl;
- }
- else
- for (y = 0; y < height; y++) {
- data_ptr = data;
- max_data = data_ptr + (width << 2);
-
- while (data_ptr < max_data) {
- pixel = pixels[*(iptr++)];
-
- *data_ptr++ = pixel;
- *data_ptr++ = pixel >> 8;
- *data_ptr++ = pixel >> 16;
- *data_ptr++ = pixel >> 24;
- }
- data += bpl;
- }
-
-#endif /* WITHOUT_SPEEDUPS */
-}
-
-/*
- * write pixels into a 16-bits Z image data structure
- */
-
-static void
-PutImagePixels16(
- XImage *image,
- unsigned int width,
- unsigned int height,
- unsigned int *pixelindex,
- Pixel *pixels)
-{
- unsigned char *data;
- unsigned int *iptr;
- unsigned int y;
-
-#ifdef WITHOUT_SPEEDUPS
-
- unsigned int x;
- unsigned char *addr;
-
- data = (unsigned char *) image->data;
- iptr = pixelindex;
- if (image->byte_order == MSBFirst)
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- addr = &data[ZINDEX16(x, y, image)];
- addr[0] = pixels[*iptr] >> 8;
- addr[1] = pixels[*iptr];
- }
- else
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- addr = &data[ZINDEX16(x, y, image)];
- addr[0] = pixels[*iptr];
- addr[1] = pixels[*iptr] >> 8;
- }
-
-#else /* WITHOUT_SPEEDUPS */
-
- Pixel pixel;
-
- unsigned int bpl = image->bytes_per_line;
- unsigned char *data_ptr, *max_data;
-
- data = (unsigned char *) image->data;
- iptr = pixelindex;
- if (image->byte_order == MSBFirst)
- for (y = 0; y < height; y++) {
- data_ptr = data;
- max_data = data_ptr + (width << 1);
-
- while (data_ptr < max_data) {
- pixel = pixels[*(iptr++)];
-
- data_ptr[0] = pixel >> 8;
- data_ptr[1] = pixel;
-
- data_ptr += (1 << 1);
- }
- data += bpl;
- }
- else
- for (y = 0; y < height; y++) {
- data_ptr = data;
- max_data = data_ptr + (width << 1);
-
- while (data_ptr < max_data) {
- pixel = pixels[*(iptr++)];
-
- data_ptr[0] = pixel;
- data_ptr[1] = pixel >> 8;
-
- data_ptr += (1 << 1);
- }
- data += bpl;
- }
-
-#endif /* WITHOUT_SPEEDUPS */
-}
-
-/*
- * write pixels into a 8-bits Z image data structure
- */
-
-static void
-PutImagePixels8(
- XImage *image,
- unsigned int width,
- unsigned int height,
- unsigned int *pixelindex,
- Pixel *pixels)
-{
- char *data;
- unsigned int *iptr;
- unsigned int y;
-
-#ifdef WITHOUT_SPEEDUPS
-
- unsigned int x;
-
- data = image->data;
- iptr = pixelindex;
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++)
- data[ZINDEX8(x, y, image)] = pixels[*iptr];
-
-#else /* WITHOUT_SPEEDUPS */
-
- unsigned int bpl = image->bytes_per_line;
- char *data_ptr, *max_data;
-
- data = image->data;
- iptr = pixelindex;
-
- for (y = 0; y < height; y++) {
- data_ptr = data;
- max_data = data_ptr + width;
-
- while (data_ptr < max_data)
- *(data_ptr++) = pixels[*(iptr++)];
-
- data += bpl;
- }
-
-#endif /* WITHOUT_SPEEDUPS */
-}
-
-/*
- * write pixels into a 1-bit depth image data structure and **offset null**
- */
-
-static void
-PutImagePixels1(
- XImage *image,
- unsigned int width,
- unsigned int height,
- unsigned int *pixelindex,
- Pixel *pixels)
-{
- if (image->byte_order != image->bitmap_bit_order)
- PutImagePixels(image, width, height, pixelindex, pixels);
- else {
- unsigned int *iptr;
- unsigned int y;
- char *data;
-
-#ifdef WITHOUT_SPEEDUPS
-
- unsigned int x;
-
- data = image->data;
- iptr = pixelindex;
- if (image->bitmap_bit_order == MSBFirst)
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- if (pixels[*iptr] & 1)
- data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
- else
- data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
- }
- else
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- if (pixels[*iptr] & 1)
- data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
- else
- data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
- }
-
-#else /* WITHOUT_SPEEDUPS */
-
- char value;
- char *data_ptr, *max_data;
- int bpl = image->bytes_per_line;
- int diff, count;
-
- data = image->data;
- iptr = pixelindex;
-
- diff = width & 7;
- width >>= 3;
-
- if (image->bitmap_bit_order == MSBFirst)
- for (y = 0; y < height; y++) {
- data_ptr = data;
- max_data = data_ptr + width;
- while (data_ptr < max_data) {
- value = 0;
-
- value = (value << 1) | (pixels[*(iptr++)] & 1);
- value = (value << 1) | (pixels[*(iptr++)] & 1);
- value = (value << 1) | (pixels[*(iptr++)] & 1);
- value = (value << 1) | (pixels[*(iptr++)] & 1);
- value = (value << 1) | (pixels[*(iptr++)] & 1);
- value = (value << 1) | (pixels[*(iptr++)] & 1);
- value = (value << 1) | (pixels[*(iptr++)] & 1);
- value = (value << 1) | (pixels[*(iptr++)] & 1);
-
- *(data_ptr++) = value;
- }
- if (diff) {
- value = 0;
- for (count = 0; count < diff; count++) {
- if (pixels[*(iptr++)] & 1)
- value |= (0x80 >> count);
- }
- *(data_ptr) = value;
- }
- data += bpl;
- }
- else
- for (y = 0; y < height; y++) {
- data_ptr = data;
- max_data = data_ptr + width;
- while (data_ptr < max_data) {
- value = 0;
- iptr += 8;
-
- value = (value << 1) | (pixels[*(--iptr)] & 1);
- value = (value << 1) | (pixels[*(--iptr)] & 1);
- value = (value << 1) | (pixels[*(--iptr)] & 1);
- value = (value << 1) | (pixels[*(--iptr)] & 1);
- value = (value << 1) | (pixels[*(--iptr)] & 1);
- value = (value << 1) | (pixels[*(--iptr)] & 1);
- value = (value << 1) | (pixels[*(--iptr)] & 1);
- value = (value << 1) | (pixels[*(--iptr)] & 1);
-
- iptr += 8;
- *(data_ptr++) = value;
- }
- if (diff) {
- value = 0;
- for (count = 0; count < diff; count++) {
- if (pixels[*(iptr++)] & 1)
- value |= (1 << count);
- }
- *(data_ptr) = value;
- }
- data += bpl;
- }
-
-#endif /* WITHOUT_SPEEDUPS */
- }
-}
-
-int
-XpmCreatePixmapFromXpmImage(
- Display *display,
- Drawable d,
- XpmImage *image,
- Pixmap *pixmap_return,
- Pixmap *shapemask_return,
- XpmAttributes *attributes)
-{
- XImage *ximage, *shapeimage;
- int ErrorStatus;
-
- /* initialize return values */
- if (pixmap_return)
- *pixmap_return = 0;
- if (shapemask_return)
- *shapemask_return = 0;
-
- /* create the ximages */
- ErrorStatus = XpmCreateImageFromXpmImage(display, image,
- (pixmap_return ? &ximage : NULL),
- (shapemask_return ?
- &shapeimage : NULL),
- attributes);
- if (ErrorStatus < 0)
- return (ErrorStatus);
-
- /* create the pixmaps and destroy images */
- if (pixmap_return && ximage) {
- xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
- XDestroyImage(ximage);
- }
- if (shapemask_return && shapeimage) {
- xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
- XDestroyImage(shapeimage);
- }
- return (ErrorStatus);
-}
-
-# else /* AMIGA */
-
-static void
-APutImagePixels (
- XImage *image,
- unsigned int width,
- unsigned int height,
- unsigned int *pixelindex,
- Pixel *pixels)
-{
- unsigned int *data = pixelindex;
- unsigned int x, y;
- unsigned char *array;
- XImage *tmp_img;
- BOOL success = FALSE;
-
- array = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*array));
- if (array != NULL)
- {
- tmp_img = AllocXImage ((((width+15)>>4)<<4), 1,
- image->rp->BitMap->Depth);
- if (tmp_img != NULL)
- {
- for (y = 0; y < height; ++y)
- {
- for (x = 0; x < width; ++x)
- array[x] = pixels[*(data++)];
- WritePixelLine8 (image->rp, 0, y, width, array, tmp_img->rp);
- }
- FreeXImage (tmp_img);
- success = TRUE;
- }
- XpmFree (array);
- }
-
- if (!success)
- {
- for (y = 0; y < height; ++y)
- for (x = 0; x < width; ++x)
- XPutPixel (image, x, y, pixels[*(data++)]);
- }
-}
-
-# endif/* AMIGA */
-#else /* FOR_MSW part follows */
-static void
-MSWPutImagePixels(
- Display *dc,
- XImage *image,
- unsigned int width,
- unsigned int height,
- unsigned int *pixelindex,
- Pixel *pixels)
-{
- unsigned int *data = pixelindex;
- unsigned int x, y;
- HBITMAP obm;
-
- obm = SelectObject(*dc, image->bitmap);
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++) {
- SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */
- }
- }
- SelectObject(*dc, obm);
-}
-
-#endif /* FOR_MSW */
-
-
-
-#if !defined(FOR_MSW) && !defined(AMIGA)
-
-static int
-PutPixel1(
- register XImage *ximage,
- int x,
- int y,
- unsigned long pixel)
-{
- register char *src;
- register char *dst;
- register int i;
- Pixel px;
- int nbytes;
-
- if(x < 0 || y < 0)
- return 0;
-
- for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8)
- ((unsigned char *)&pixel)[i] = px;
- src = &ximage->data[XYINDEX(x, y, ximage)];
- dst = (char *)&px;
- px = 0;
- nbytes = ximage->bitmap_unit >> 3;
- for (i = nbytes; --i >= 0; ) *dst++ = *src++;
- XYNORMALIZE(&px, ximage);
- i = ((x + ximage->xoffset) % ximage->bitmap_unit);
- _putbits ((char *)&pixel, i, 1, (char *)&px);
- XYNORMALIZE(&px, ximage);
- src = (char *) &px;
- dst = &ximage->data[XYINDEX(x, y, ximage)];
- for (i = nbytes; --i >= 0; )
- *dst++ = *src++;
-
- return 1;
-}
-
-static int
-PutPixel(
- register XImage *ximage,
- int x,
- int y,
- unsigned long pixel)
-{
- register char *src;
- register char *dst;
- register int i;
- Pixel px;
- unsigned int nbytes, ibpp;
-
- if(x < 0 || y < 0)
- return 0;
-
- ibpp = ximage->bits_per_pixel;
- if (ximage->depth == 4)
- pixel &= 0xf;
- for (i = 0, px = pixel; i < sizeof(unsigned long); i++, px >>= 8)
- ((unsigned char *) &pixel)[i] = px;
- src = &ximage->data[ZINDEX(x, y, ximage)];
- dst = (char *) &px;
- px = 0;
- nbytes = (ibpp + 7) >> 3;
- for (i = nbytes; --i >= 0;)
- *dst++ = *src++;
- ZNORMALIZE(&px, ximage);
- _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
- ZNORMALIZE(&px, ximage);
- src = (char *) &px;
- dst = &ximage->data[ZINDEX(x, y, ximage)];
- for (i = nbytes; --i >= 0;)
- *dst++ = *src++;
-
- return 1;
-}
-
-#if !defined(WORD64) && !defined(LONG64)
-static int
-PutPixel32(
- register XImage *ximage,
- int x,
- int y,
- unsigned long pixel)
-{
- unsigned char *addr;
-
- if(x < 0 || y < 0)
- return 0;
-
- addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
- *((unsigned long *)addr) = pixel;
- return 1;
-}
-#endif
-
-static int
-PutPixel32MSB(
- register XImage *ximage,
- int x,
- int y,
- unsigned long pixel)
-{
- unsigned char *addr;
-
- if(x < 0 || y < 0)
- return 0;
-
- addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
- addr[0] = pixel >> 24;
- addr[1] = pixel >> 16;
- addr[2] = pixel >> 8;
- addr[3] = pixel;
- return 1;
-}
-
-static int
-PutPixel32LSB(
- register XImage *ximage,
- int x,
- int y,
- unsigned long pixel)
-{
- unsigned char *addr;
-
- if(x < 0 || y < 0)
- return 0;
-
- addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
- addr[3] = pixel >> 24;
- addr[2] = pixel >> 16;
- addr[1] = pixel >> 8;
- addr[0] = pixel;
- return 1;
-}
-
-static int
-PutPixel16MSB(
- register XImage *ximage,
- int x,
- int y,
- unsigned long pixel)
-{
- unsigned char *addr;
-
- if(x < 0 || y < 0)
- return 0;
-
- addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
- addr[0] = pixel >> 8;
- addr[1] = pixel;
- return 1;
-}
-
-static int
-PutPixel16LSB(
- register XImage *ximage,
- int x,
- int y,
- unsigned long pixel)
-{
- unsigned char *addr;
-
- if(x < 0 || y < 0)
- return 0;
-
- addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
- addr[1] = pixel >> 8;
- addr[0] = pixel;
- return 1;
-}
-
-static int
-PutPixel8(
- register XImage *ximage,
- int x,
- int y,
- unsigned long pixel)
-{
- if(x < 0 || y < 0)
- return 0;
-
- ximage->data[ZINDEX8(x, y, ximage)] = pixel;
- return 1;
-}
-
-static int
-PutPixel1MSB(
- register XImage *ximage,
- int x,
- int y,
- unsigned long pixel)
-{
- if(x < 0 || y < 0)
- return 0;
-
- if (pixel & 1)
- ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7);
- else
- ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7));
- return 1;
-}
-
-static int
-PutPixel1LSB(
- register XImage *ximage,
- int x,
- int y,
- unsigned long pixel)
-{
- if(x < 0 || y < 0)
- return 0;
-
- if (pixel & 1)
- ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7);
- else
- ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7));
- return 1;
-}
-
-#endif /* not FOR_MSW && not AMIGA */
-
-/*
- * This function parses an Xpm file or data and directly create an XImage
- */
-int
-xpmParseDataAndCreate(
- Display *display,
- xpmData *data,
- XImage **image_return,
- XImage **shapeimage_return,
- XpmImage *image,
- XpmInfo *info,
- XpmAttributes *attributes)
-{
- /* variables stored in the XpmAttributes structure */
- Visual *visual;
- Colormap colormap;
- unsigned int depth;
- int bitmap_format;
- XpmFreeColorsFunc freeColors;
-
- /* variables to return */
- XImage *ximage = NULL;
- XImage *shapeimage = NULL;
- unsigned int mask_pixel_index = XpmUndefPixel;
-
- /* calculation variables */
- Pixel *image_pixels = NULL;
- Pixel *mask_pixels = NULL;
- Pixel *alloc_pixels = NULL;
- Pixel *used_pixels = NULL;
- unsigned int nalloc_pixels = 0;
- unsigned int nused_pixels = 0;
- unsigned int width, height, ncolors, cpp;
- unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
- XpmColor *colorTable = NULL;
- char *hints_cmt = NULL;
- char *colors_cmt = NULL;
- char *pixels_cmt = NULL;
-
- unsigned int cmts;
- int ErrorStatus;
- xpmHashTable hashtable;
-
-
- /* initialize return values */
- if (image_return)
- *image_return = NULL;
- if (shapeimage_return)
- *shapeimage_return = NULL;
-
-
- /* retrieve information from the XpmAttributes */
- if (attributes && (attributes->valuemask & XpmVisual))
- visual = attributes->visual;
- else
- visual = XDefaultVisual(display, XDefaultScreen(display));
-
- if (attributes && (attributes->valuemask & XpmColormap))
- colormap = attributes->colormap;
- else
- colormap = XDefaultColormap(display, XDefaultScreen(display));
-
- if (attributes && (attributes->valuemask & XpmDepth))
- depth = attributes->depth;
- else
- depth = XDefaultDepth(display, XDefaultScreen(display));
-
- if (attributes && (attributes->valuemask & XpmBitmapFormat))
- bitmap_format = attributes->bitmap_format;
- else
- bitmap_format = ZPixmap;
-
- if (attributes && (attributes->valuemask & XpmFreeColors))
- freeColors = attributes->free_colors;
- else
- freeColors = FreeColors;
-
- cmts = info && (info->valuemask & XpmReturnComments);
-
- /*
- * parse the header
- */
- ErrorStatus = xpmParseHeader(data);
- if (ErrorStatus != XpmSuccess)
- return (ErrorStatus);
-
- /*
- * read values
- */
- ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
- &x_hotspot, &y_hotspot, &hotspot,
- &extensions);
- if (ErrorStatus != XpmSuccess)
- return (ErrorStatus);
-
- /*
- * store the hints comment line
- */
- if (cmts)
- xpmGetCmt(data, &hints_cmt);
-
- /*
- * init the hashtable
- */
- if (USE_HASHTABLE) {
- ErrorStatus = xpmHashTableInit(&hashtable);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
- }
-
- /*
- * read colors
- */
- ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
-
- /*
- * store the colors comment line
- */
- if (cmts)
- xpmGetCmt(data, &colors_cmt);
-
- /* malloc pixels index tables */
- if (ncolors >= UINT_MAX / sizeof(Pixel))
- RETURN(XpmNoMemory);
-
- image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
- if (!image_pixels)
- RETURN(XpmNoMemory);
-
- mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
- if (!mask_pixels)
- RETURN(XpmNoMemory);
-
- /* maximum of allocated pixels will be the number of colors */
- alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
- if (!alloc_pixels)
- RETURN(XpmNoMemory);
-
- /* maximum of allocated pixels will be the number of colors */
- used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
- if (!used_pixels)
- RETURN(XpmNoMemory);
-
- /* get pixel colors, store them in index tables */
- ErrorStatus = CreateColors(display, attributes, colorTable, ncolors,
- image_pixels, mask_pixels, &mask_pixel_index,
- alloc_pixels, &nalloc_pixels, used_pixels,
- &nused_pixels);
-
- if (ErrorStatus != XpmSuccess
- && (ErrorStatus < 0 || (attributes
- && (attributes->valuemask & XpmExactColors)
- && attributes->exactColors)))
- RETURN(ErrorStatus);
-
- /* now create the ximage */
- if (image_return) {
- ErrorStatus = CreateXImage(display, visual, depth,
- (depth == 1 ? bitmap_format : ZPixmap),
- width, height, &ximage);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
-
-#if !defined(FOR_MSW) && !defined(AMIGA)
-
- /*
- * set the XImage pointer function, to be used with XPutPixel,
- * to an internal optimized function
- */
-
- if (ximage->bits_per_pixel == 8)
- ximage->f.put_pixel = PutPixel8;
- else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
- (ximage->byte_order == ximage->bitmap_bit_order))
- if (ximage->bitmap_bit_order == MSBFirst)
- ximage->f.put_pixel = PutPixel1MSB;
- else
- ximage->f.put_pixel = PutPixel1LSB;
- else if (ximage->bits_per_pixel == 16)
- if (ximage->bitmap_bit_order == MSBFirst)
- ximage->f.put_pixel = PutPixel16MSB;
- else
- ximage->f.put_pixel = PutPixel16LSB;
- else if (ximage->bits_per_pixel == 32)
-#if !defined(WORD64) && !defined(LONG64)
- if (*((char *)&byteorderpixel) == ximage->byte_order)
- ximage->f.put_pixel = PutPixel32;
- else
-#endif
- if (ximage->bitmap_bit_order == MSBFirst)
- ximage->f.put_pixel = PutPixel32MSB;
- else
- ximage->f.put_pixel = PutPixel32LSB;
- else if ((ximage->bits_per_pixel | ximage->depth) == 1)
- ximage->f.put_pixel = PutPixel1;
- else
- ximage->f.put_pixel = PutPixel;
-#endif /* not FOR_MSW && not AMIGA */
- }
-
- /* create the shape mask image */
- if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
- ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
- width, height, &shapeimage);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
-
-#if !defined(FOR_MSW) && !defined(AMIGA)
- if (shapeimage->bitmap_bit_order == MSBFirst)
- shapeimage->f.put_pixel = PutPixel1MSB;
- else
- shapeimage->f.put_pixel = PutPixel1LSB;
-#endif
- }
-
- /*
- * read pixels and put them in the XImage
- */
- ErrorStatus = ParseAndPutPixels(
-#ifdef FOR_MSW
- display,
-#endif
- data, width, height, ncolors, cpp,
- colorTable, &hashtable,
- ximage, image_pixels,
- shapeimage, mask_pixels);
- XpmFree(image_pixels);
- image_pixels = NULL;
- XpmFree(mask_pixels);
- mask_pixels = NULL;
-
- /*
- * free the hastable
- */
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
- else if (USE_HASHTABLE)
- xpmHashTableFree(&hashtable);
-
- /*
- * store the pixels comment line
- */
- if (cmts)
- xpmGetCmt(data, &pixels_cmt);
-
- /*
- * parse extensions
- */
- if (info && (info->valuemask & XpmReturnExtensions)) {
- if (extensions) {
- ErrorStatus = xpmParseExtensions(data, &info->extensions,
- &info->nextensions);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
- } else {
- info->extensions = NULL;
- info->nextensions = 0;
- }
- }
- /*
- * store found informations in the XpmImage structure
- */
- image->width = width;
- image->height = height;
- image->cpp = cpp;
- image->ncolors = ncolors;
- image->colorTable = colorTable;
- image->data = NULL;
-
- if (info) {
- if (cmts) {
- info->hints_cmt = hints_cmt;
- info->colors_cmt = colors_cmt;
- info->pixels_cmt = pixels_cmt;
- }
- if (hotspot) {
- info->x_hotspot = x_hotspot;
- info->y_hotspot = y_hotspot;
- info->valuemask |= XpmHotspot;
- }
- }
- /* if requested return used pixels in the XpmAttributes structure */
- if (attributes && (attributes->valuemask & XpmReturnPixels ||
-/* 3.2 backward compatibility code */
- attributes->valuemask & XpmReturnInfos)) {
-/* end 3.2 bc */
- attributes->pixels = used_pixels;
- attributes->npixels = nused_pixels;
- attributes->mask_pixel = mask_pixel_index;
- } else
- XpmFree(used_pixels);
-
- /* if requested return alloc'ed pixels in the XpmAttributes structure */
- if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
- attributes->alloc_pixels = alloc_pixels;
- attributes->nalloc_pixels = nalloc_pixels;
- } else
- XpmFree(alloc_pixels);
-
- /* return created images */
- if (image_return)
- *image_return = ximage;
- if (shapeimage_return)
- *shapeimage_return = shapeimage;
-
- return (XpmSuccess);
-
-/* exit point in case of error, free only locally allocated variables */
-error:
- if (USE_HASHTABLE)
- xpmHashTableFree(&hashtable);
- if (colorTable)
- xpmFreeColorTable(colorTable, ncolors);
- if (hints_cmt)
- XpmFree(hints_cmt);
- if (colors_cmt)
- XpmFree(colors_cmt);
- if (pixels_cmt)
- XpmFree(pixels_cmt);
- if (ximage)
- XDestroyImage(ximage);
- if (shapeimage)
- XDestroyImage(shapeimage);
- if (image_pixels)
- XpmFree(image_pixels);
- if (mask_pixels)
- XpmFree(mask_pixels);
- if (nalloc_pixels)
- (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL);
- if (alloc_pixels)
- XpmFree(alloc_pixels);
- if (used_pixels)
- XpmFree(used_pixels);
-
- return (ErrorStatus);
-}
-
-static int
-ParseAndPutPixels(
-#ifdef FOR_MSW
- Display *dc,
-#endif
- xpmData *data,
- unsigned int width,
- unsigned int height,
- unsigned int ncolors,
- unsigned int cpp,
- XpmColor *colorTable,
- xpmHashTable *hashtable,
- XImage *image,
- Pixel *image_pixels,
- XImage *shapeimage,
- Pixel *shape_pixels)
-{
- unsigned int a, x, y;
-
- switch (cpp) {
-
- case (1): /* Optimize for single character
- * colors */
- {
- unsigned short colidx[256];
-#ifdef FOR_MSW
- HDC shapedc;
- HBITMAP obm, sobm;
-
- if ( shapeimage ) {
- shapedc = CreateCompatibleDC(*dc);
- sobm = SelectObject(shapedc, shapeimage->bitmap);
- } else {
- shapedc = NULL;
- }
- obm = SelectObject(*dc, image->bitmap);
-#endif
- if (ncolors > 256)
- return (XpmFileInvalid);
-
- bzero((char *)colidx, 256 * sizeof(short));
- for (a = 0; a < ncolors; a++)
- colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
-
- for (y = 0; y < height; y++) {
- xpmNextString(data);
- for (x = 0; x < width; x++) {
- int c = xpmGetC(data);
-
- if (c > 0 && c < 256 && colidx[c] != 0) {
-#ifndef FOR_MSW
- XPutPixel(image, x, y, image_pixels[colidx[c] - 1]);
- if (shapeimage)
- XPutPixel(shapeimage, x, y,
- shape_pixels[colidx[c] - 1]);
-#else
- SetPixel(*dc, x, y, image_pixels[colidx[c] - 1]);
- if (shapedc) {
- SetPixel(shapedc, x, y, shape_pixels[colidx[c] - 1]);
- }
-#endif
- } else
- return (XpmFileInvalid);
- }
- }
-#ifdef FOR_MSW
- if ( shapedc ) {
- SelectObject(shapedc, sobm);
- DeleteDC(shapedc);
- }
- SelectObject(*dc, obm);
-#endif
- }
- break;
-
- case (2): /* Optimize for double character
- * colors */
- {
-
-/* free all allocated pointers at all exits */
-#define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
-if (cidx[f]) XpmFree(cidx[f]);}
-
- /* array of pointers malloced by need */
- unsigned short *cidx[256];
- unsigned int char1;
-
- bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
- for (a = 0; a < ncolors; a++) {
- char1 = (unsigned char) colorTable[a].string[0];
- if (cidx[char1] == NULL) { /* get new memory */
- cidx[char1] = (unsigned short *)
- XpmCalloc(256, sizeof(unsigned short));
- if (cidx[char1] == NULL) { /* new block failed */
- FREE_CIDX;
- return (XpmNoMemory);
- }
- }
- cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
- }
-
- for (y = 0; y < height; y++) {
- xpmNextString(data);
- for (x = 0; x < width; x++) {
- int cc1 = xpmGetC(data);
- if (cc1 > 0 && cc1 < 256) {
- int cc2 = xpmGetC(data);
- if (cc2 > 0 && cc2 < 256 &&
- cidx[cc1] && cidx[cc1][cc2] != 0) {
-#ifndef FOR_MSW
- XPutPixel(image, x, y,
- image_pixels[cidx[cc1][cc2] - 1]);
- if (shapeimage)
- XPutPixel(shapeimage, x, y,
- shape_pixels[cidx[cc1][cc2] - 1]);
-#else
- SelectObject(*dc, image->bitmap);
- SetPixel(*dc, x, y, image_pixels[cidx[cc1][cc2] - 1]);
- if (shapeimage) {
- SelectObject(*dc, shapeimage->bitmap);
- SetPixel(*dc, x, y,
- shape_pixels[cidx[cc1][cc2] - 1]);
- }
-#endif
- } else {
- FREE_CIDX;
- return (XpmFileInvalid);
- }
- } else {
- FREE_CIDX;
- return (XpmFileInvalid);
- }
- }
- }
- FREE_CIDX;
- }
- break;
-
- default: /* Non-optimized case of long color
- * names */
- {
- char *s;
- char buf[BUFSIZ];
-
- if (cpp >= sizeof(buf))
- return (XpmFileInvalid);
-
- buf[cpp] = '\0';
- if (USE_HASHTABLE) {
- xpmHashAtom *slot;
-
- for (y = 0; y < height; y++) {
- xpmNextString(data);
- for (x = 0; x < width; x++) {
- for (a = 0, s = buf; a < cpp; a++, s++)
- *s = xpmGetC(data);
- slot = xpmHashSlot(hashtable, buf);
- if (!*slot) /* no color matches */
- return (XpmFileInvalid);
-#ifndef FOR_MSW
- XPutPixel(image, x, y,
- image_pixels[HashColorIndex(slot)]);
- if (shapeimage)
- XPutPixel(shapeimage, x, y,
- shape_pixels[HashColorIndex(slot)]);
-#else
- SelectObject(*dc, image->bitmap);
- SetPixel(*dc, x, y,
- image_pixels[HashColorIndex(slot)]);
- if (shapeimage) {
- SelectObject(*dc, shapeimage->bitmap);
- SetPixel(*dc, x, y,
- shape_pixels[HashColorIndex(slot)]);
- }
-#endif
- }
- }
- } else {
- for (y = 0; y < height; y++) {
- xpmNextString(data);
- for (x = 0; x < width; x++) {
- for (a = 0, s = buf; a < cpp; a++, s++)
- *s = xpmGetC(data);
- for (a = 0; a < ncolors; a++)
- if (!strcmp(colorTable[a].string, buf))
- break;
- if (a == ncolors) /* no color matches */
- return (XpmFileInvalid);
-#ifndef FOR_MSW
- XPutPixel(image, x, y, image_pixels[a]);
- if (shapeimage)
- XPutPixel(shapeimage, x, y, shape_pixels[a]);
-#else
- SelectObject(*dc, image->bitmap);
- SetPixel(*dc, x, y, image_pixels[a]);
- if (shapeimage) {
- SelectObject(*dc, shapeimage->bitmap);
- SetPixel(*dc, x, y, shape_pixels[a]);
- }
-#endif
- }
- }
- }
- }
- break;
- }
- return (XpmSuccess);
-}
+/* + * Copyright (C) 1989-95 GROUPE BULL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of GROUPE BULL shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from GROUPE BULL. + */ + +/*****************************************************************************\ +* create.c: * +* * +* XPM library * +* Create an X image and possibly its related shape mask * +* from the given XpmImage. * +* * +* Developed by Arnaud Le Hors * +\*****************************************************************************/ + +/* + * The code related to FOR_MSW has been added by + * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94 + */ + +/* + * The code related to AMIGA has been added by + * Lorens Younes (d93-hyo@nada.kth.se) 4/96 + */ + +/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "XpmI.h" +#include <ctype.h> + +LFUNC(xpmVisualType, int, (Visual *visual)); + +LFUNC(AllocColor, int, (Display *display, Colormap colormap, + char *colorname, XColor *xcolor, void *closure)); +LFUNC(FreeColors, int, (Display *display, Colormap colormap, + Pixel *pixels, int n, void *closure)); + +#ifndef FOR_MSW +LFUNC(SetCloseColor, int, (Display *display, Colormap colormap, + Visual *visual, XColor *col, + Pixel *image_pixel, Pixel *mask_pixel, + Pixel *alloc_pixels, unsigned int *nalloc_pixels, + XpmAttributes *attributes, XColor *cols, int ncols, + XpmAllocColorFunc allocColor, void *closure)); +#else +/* let the window system take care of close colors */ +#endif + +LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual, + char *colorname, unsigned int color_index, + Pixel *image_pixel, Pixel *mask_pixel, + unsigned int *mask_pixel_index, + Pixel *alloc_pixels, unsigned int *nalloc_pixels, + Pixel *used_pixels, unsigned int *nused_pixels, + XpmAttributes *attributes, XColor *cols, int ncols, + XpmAllocColorFunc allocColor, void *closure)); + +LFUNC(CreateXImage, int, (Display *display, Visual *visual, + unsigned int depth, int format, unsigned int width, + unsigned int height, XImage **image_return)); + +LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes, + XpmColor *colors, unsigned int ncolors, + Pixel *image_pixels, Pixel *mask_pixels, + unsigned int *mask_pixel_index, + Pixel *alloc_pixels, unsigned int *nalloc_pixels, + Pixel *used_pixels, unsigned int *nused_pixels)); + +#ifndef FOR_MSW +LFUNC(ParseAndPutPixels, int, (xpmData *data, unsigned int width, + unsigned int height, unsigned int ncolors, + unsigned int cpp, XpmColor *colorTable, + xpmHashTable *hashtable, + XImage *image, Pixel *image_pixels, + XImage *mask, Pixel *mask_pixels)); +#else /* FOR_MSW */ +LFUNC(ParseAndPutPixels, int, (Display *dc, xpmData *data, unsigned int width, + unsigned int height, unsigned int ncolors, + unsigned int cpp, XpmColor *colorTable, + xpmHashTable *hashtable, + XImage *image, Pixel *image_pixels, + XImage *mask, Pixel *mask_pixels)); +#endif + +#ifndef FOR_MSW +# ifndef AMIGA +/* XImage pixel routines */ +LFUNC(PutImagePixels, void, (XImage *image, unsigned int width, + unsigned int height, unsigned int *pixelindex, + Pixel *pixels)); + +LFUNC(PutImagePixels32, void, (XImage *image, unsigned int width, + unsigned int height, unsigned int *pixelindex, + Pixel *pixels)); + +LFUNC(PutImagePixels16, void, (XImage *image, unsigned int width, + unsigned int height, unsigned int *pixelindex, + Pixel *pixels)); + +LFUNC(PutImagePixels8, void, (XImage *image, unsigned int width, + unsigned int height, unsigned int *pixelindex, + Pixel *pixels)); + +LFUNC(PutImagePixels1, void, (XImage *image, unsigned int width, + unsigned int height, unsigned int *pixelindex, + Pixel *pixels)); + +LFUNC(PutPixel1, int, (XImage *ximage, int x, int y, unsigned long pixel)); +LFUNC(PutPixel, int, (XImage *ximage, int x, int y, unsigned long pixel)); +#if !defined(WORD64) && !defined(LONG64) +LFUNC(PutPixel32, int, (XImage *ximage, int x, int y, unsigned long pixel)); +#endif +LFUNC(PutPixel32MSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); +LFUNC(PutPixel32LSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); +LFUNC(PutPixel16MSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); +LFUNC(PutPixel16LSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); +LFUNC(PutPixel8, int, (XImage *ximage, int x, int y, unsigned long pixel)); +LFUNC(PutPixel1MSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); +LFUNC(PutPixel1LSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); + +# else /* AMIGA */ +LFUNC(APutImagePixels, void, (XImage *ximage, unsigned int width, + unsigned int height, unsigned int *pixelindex, + Pixel *pixels)); +# endif/* AMIGA */ +#else /* FOR_MSW */ +/* FOR_MSW pixel routine */ +LFUNC(MSWPutImagePixels, void, (Display *dc, XImage *image, + unsigned int width, unsigned int height, + unsigned int *pixelindex, Pixel *pixels)); +#endif /* FOR_MSW */ + +#ifdef NEED_STRCASECMP +FUNC(xpmstrcasecmp, int, (char *s1, char *s2)); + +/* + * in case strcasecmp is not provided by the system here is one + * which does the trick + */ +int +xpmstrcasecmp( + register char *s1, + register char *s2) +{ + register int c1, c2; + + while (*s1 && *s2) { + c1 = tolower(*s1); + c2 = tolower(*s2); + if (c1 != c2) + return (c1 - c2); + s1++; + s2++; + } + return (int) (*s1 - *s2); +} + +#endif + +/* + * return the default color key related to the given visual + */ +static int +xpmVisualType(Visual *visual) +{ +#ifndef FOR_MSW +# ifndef AMIGA + switch (visual->class) { + case StaticGray: + case GrayScale: + switch (visual->map_entries) { + case 2: + return (XPM_MONO); + case 4: + return (XPM_GRAY4); + default: + return (XPM_GRAY); + } + default: + return (XPM_COLOR); + } +# else + /* set the key explicitly in the XpmAttributes to override this */ + return (XPM_COLOR); +# endif +#else + /* there should be a similar switch for MSW */ + return (XPM_COLOR); +#endif +} + + +typedef struct { + int cols_index; + long closeness; +} CloseColor; + +static int +closeness_cmp(Const void *a, Const void *b) +{ + CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b; + + /* cast to int as qsort requires */ + return (int) (x->closeness - y->closeness); +} + + +/* default AllocColor function: + * call XParseColor if colorname is given, return negative value if failure + * call XAllocColor and return 0 if failure, positive otherwise + */ +static int +AllocColor( + Display *display, + Colormap colormap, + char *colorname, + XColor *xcolor, + void *closure) /* not used */ +{ + int status; + if (colorname) + if (!XParseColor(display, colormap, colorname, xcolor)) + return -1; + status = XAllocColor(display, colormap, xcolor); + return status != 0 ? 1 : 0; +} + + +#ifndef FOR_MSW +/* + * set a close color in case the exact one can't be set + * return 0 if success, 1 otherwise. + */ + +static int +SetCloseColor( + Display *display, + Colormap colormap, + Visual *visual, + XColor *col, + Pixel *image_pixel, + Pixel *mask_pixel, + Pixel *alloc_pixels, + unsigned int *nalloc_pixels, + XpmAttributes *attributes, + XColor *cols, + int ncols, + XpmAllocColorFunc allocColor, + void *closure) +{ + + /* + * Allocation failed, so try close colors. To get here the visual must + * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor? + * What about sharing systems like QDSS?). Beware: we have to treat + * DirectColor differently. + */ + + + long int red_closeness, green_closeness, blue_closeness; + int n; + Bool alloc_color; + + if (attributes && (attributes->valuemask & XpmCloseness)) + red_closeness = green_closeness = blue_closeness = + attributes->closeness; + else { + red_closeness = attributes->red_closeness; + green_closeness = attributes->green_closeness; + blue_closeness = attributes->blue_closeness; + } + if (attributes && (attributes->valuemask & XpmAllocCloseColors)) + alloc_color = attributes->alloc_close_colors; + else + alloc_color = True; + + /* + * We sort the colormap by closeness and try to allocate the color + * closest to the target. If the allocation of this close color fails, + * which almost never happens, then one of two scenarios is possible. + * Either the colormap must have changed (since the last close color + * allocation or possibly while we were sorting the colormap), or the + * color is allocated as Read/Write by some other client. (Note: X + * _should_ allow clients to check if a particular color is Read/Write, + * but it doesn't! :-( ). We cannot determine which of these scenarios + * occurred, so we try the next closest color, and so on, until no more + * colors are within closeness of the target. If we knew that the + * colormap had changed, we could skip this sequence. + * + * If _none_ of the colors within closeness of the target can be allocated, + * then we can finally be pretty sure that the colormap has actually + * changed. In this case we try to allocate the original color (again), + * then try the closecolor stuff (again)... + * + * In theory it would be possible for an infinite loop to occur if another + * process kept changing the colormap every time we sorted it, so we set + * a maximum on the number of iterations. After this many tries, we use + * XGrabServer() to ensure that the colormap remains unchanged. + * + * This approach gives particularly bad worst case performance - as many as + * <MaximumIterations> colormap reads and sorts may be needed, and as + * many as <MaximumIterations> * <ColormapSize> attempted allocations + * may fail. On an 8-bit system, this means as many as 3 colormap reads, + * 3 sorts and 768 failed allocations per execution of this code! + * Luckily, my experiments show that in general use in a typical 8-bit + * color environment only about 1 in every 10000 allocations fails to + * succeed in the fastest possible time. So virtually every time what + * actually happens is a single sort followed by a successful allocate. + * The very first allocation also costs a colormap read, but no further + * reads are usually necessary. + */ + +#define ITERATIONS 2 /* more than one is almost never + * necessary */ + + for (n = 0; n <= ITERATIONS; ++n) { + CloseColor *closenesses = + (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor)); + int i, c; + + for (i = 0; i < ncols; ++i) { /* build & sort closenesses table */ +#define COLOR_FACTOR 3 +#define BRIGHTNESS_FACTOR 1 + + closenesses[i].cols_index = i; + closenesses[i].closeness = + COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red) + + abs((long) col->green - (long) cols[i].green) + + abs((long) col->blue - (long) cols[i].blue)) + + BRIGHTNESS_FACTOR * abs(((long) col->red + + (long) col->green + + (long) col->blue) + - ((long) cols[i].red + + (long) cols[i].green + + (long) cols[i].blue)); + } + qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp); + + i = 0; + c = closenesses[i].cols_index; + while ((long) cols[c].red >= (long) col->red - red_closeness && + (long) cols[c].red <= (long) col->red + red_closeness && + (long) cols[c].green >= (long) col->green - green_closeness && + (long) cols[c].green <= (long) col->green + green_closeness && + (long) cols[c].blue >= (long) col->blue - blue_closeness && + (long) cols[c].blue <= (long) col->blue + blue_closeness) { + if (alloc_color) { + if ((*allocColor)(display, colormap, NULL, &cols[c], closure)){ + if (n == ITERATIONS) + XUngrabServer(display); + XpmFree(closenesses); + *image_pixel = cols[c].pixel; + *mask_pixel = 1; + alloc_pixels[(*nalloc_pixels)++] = cols[c].pixel; + return (0); + } else { + ++i; + if (i == ncols) + break; + c = closenesses[i].cols_index; + } + } else { + if (n == ITERATIONS) + XUngrabServer(display); + XpmFree(closenesses); + *image_pixel = cols[c].pixel; + *mask_pixel = 1; + return (0); + } + } + + /* Couldn't allocate _any_ of the close colors! */ + + if (n == ITERATIONS) + XUngrabServer(display); + XpmFree(closenesses); + + if (i == 0 || i == ncols) /* no color close enough or cannot */ + return (1); /* alloc any color (full of r/w's) */ + + if ((*allocColor)(display, colormap, NULL, col, closure)) { + *image_pixel = col->pixel; + *mask_pixel = 1; + alloc_pixels[(*nalloc_pixels)++] = col->pixel; + return (0); + } else { /* colormap has probably changed, so + * re-read... */ + if (n == ITERATIONS - 1) + XGrabServer(display); + +#if 0 + if (visual->class == DirectColor) { + /* TODO */ + } else +#endif + XQueryColors(display, colormap, cols, ncols); + } + } + return (1); +} + +#define USE_CLOSECOLOR attributes && \ +(((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \ + || ((attributes->valuemask & XpmRGBCloseness) && \ + (attributes->red_closeness != 0 \ + || attributes->green_closeness != 0 \ + || attributes->blue_closeness != 0))) + +#else + /* FOR_MSW part */ + /* nothing to do here, the window system does it */ +#endif + +/* + * set the color pixel related to the given colorname, + * return 0 if success, 1 otherwise. + */ + +static int +SetColor( + Display *display, + Colormap colormap, + Visual *visual, + char *colorname, + unsigned int color_index, + Pixel *image_pixel, + Pixel *mask_pixel, + unsigned int *mask_pixel_index, + Pixel *alloc_pixels, + unsigned int *nalloc_pixels, + Pixel *used_pixels, + unsigned int *nused_pixels, + XpmAttributes *attributes, + XColor *cols, + int ncols, + XpmAllocColorFunc allocColor, + void *closure) +{ + XColor xcolor; + int status; + + if (xpmstrcasecmp(colorname, TRANSPARENT_COLOR)) { + status = (*allocColor)(display, colormap, colorname, &xcolor, closure); + if (status < 0) /* parse color failed */ + return (1); + + if (status == 0) { +#ifndef FOR_MSW + if (USE_CLOSECOLOR) + return (SetCloseColor(display, colormap, visual, &xcolor, + image_pixel, mask_pixel, + alloc_pixels, nalloc_pixels, + attributes, cols, ncols, + allocColor, closure)); + else +#endif /* ndef FOR_MSW */ + return (1); + } else + alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel; + *image_pixel = xcolor.pixel; +#ifndef FOR_MSW + *mask_pixel = 1; +#else + *mask_pixel = RGB(0,0,0); +#endif + used_pixels[(*nused_pixels)++] = xcolor.pixel; + } else { + *image_pixel = 0; +#ifndef FOR_MSW + *mask_pixel = 0; +#else + *mask_pixel = RGB(255,255,255); +#endif + /* store the color table index */ + *mask_pixel_index = color_index; + } + return (0); +} + + +static int +CreateColors( + Display *display, + XpmAttributes *attributes, + XpmColor *colors, + unsigned int ncolors, + Pixel *image_pixels, + Pixel *mask_pixels, + unsigned int *mask_pixel_index, + Pixel *alloc_pixels, + unsigned int *nalloc_pixels, + Pixel *used_pixels, + unsigned int *nused_pixels) +{ + /* variables stored in the XpmAttributes structure */ + Visual *visual; + Colormap colormap; + XpmColorSymbol *colorsymbols = NULL; + unsigned int numsymbols; + XpmAllocColorFunc allocColor; + void *closure; + + char *colorname; + unsigned int color, key; + Bool pixel_defined; + XpmColorSymbol *symbol = NULL; + char **defaults; + int ErrorStatus = XpmSuccess; + char *s; + int default_index; + + XColor *cols = NULL; + unsigned int ncols = 0; + + /* + * retrieve information from the XpmAttributes + */ + if (attributes && attributes->valuemask & XpmColorSymbols) { + colorsymbols = attributes->colorsymbols; + numsymbols = attributes->numsymbols; + } else + numsymbols = 0; + + if (attributes && attributes->valuemask & XpmVisual) + visual = attributes->visual; + else + visual = XDefaultVisual(display, XDefaultScreen(display)); + + if (attributes && (attributes->valuemask & XpmColormap)) + colormap = attributes->colormap; + else + colormap = XDefaultColormap(display, XDefaultScreen(display)); + + if (attributes && (attributes->valuemask & XpmColorKey)) + key = attributes->color_key; + else + key = xpmVisualType(visual); + + if (attributes && (attributes->valuemask & XpmAllocColor)) + allocColor = attributes->alloc_color; + else + allocColor = AllocColor; + if (attributes && (attributes->valuemask & XpmColorClosure)) + closure = attributes->color_closure; + else + closure = NULL; + +#ifndef FOR_MSW + if (USE_CLOSECOLOR) { + /* originally from SetCloseColor */ +#if 0 + if (visual->class == DirectColor) { + + /* + * TODO: Implement close colors for DirectColor visuals. This is + * difficult situation. Chances are that we will never get here, + * because any machine that supports DirectColor will probably + * also support TrueColor (and probably PseudoColor). Also, + * DirectColor colormaps can be very large, so looking for close + * colors may be too slow. + */ + } else { +#endif + unsigned int i; + +#ifndef AMIGA + ncols = visual->map_entries; +#else + ncols = colormap->Count; +#endif + cols = (XColor *) XpmCalloc(ncols, sizeof(XColor)); + for (i = 0; i < ncols; ++i) + cols[i].pixel = i; + XQueryColors(display, colormap, cols, ncols); +#if 0 + } +#endif + } +#endif /* ndef FOR_MSW */ + + switch (key) { + case XPM_MONO: + default_index = 2; + break; + case XPM_GRAY4: + default_index = 3; + break; + case XPM_GRAY: + default_index = 4; + break; + case XPM_COLOR: + default: + default_index = 5; + break; + } + + for (color = 0; color < ncolors; color++, colors++, + image_pixels++, mask_pixels++) { + colorname = NULL; + pixel_defined = False; + defaults = (char **) colors; + + /* + * look for a defined symbol + */ + if (numsymbols) { + + unsigned int n; + + s = defaults[1]; + for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) { + if (symbol->name && s && !strcmp(symbol->name, s)) + /* override name */ + break; + if (!symbol->name && symbol->value) { /* override value */ + int def_index = default_index; + + while (defaults[def_index] == NULL) /* find defined + * colorname */ + --def_index; + if (def_index < 2) {/* nothing towards mono, so try + * towards color */ + def_index = default_index + 1; + while (def_index <= 5 && defaults[def_index] == NULL) + ++def_index; + } + if (def_index >= 2 && defaults[def_index] != NULL && + !xpmstrcasecmp(symbol->value, defaults[def_index])) + break; + } + } + if (n != numsymbols) { + if (symbol->name && symbol->value) + colorname = symbol->value; + else + pixel_defined = True; + } + } + if (!pixel_defined) { /* pixel not given as symbol value */ + + unsigned int k; + + if (colorname) { /* colorname given as symbol value */ + if (!SetColor(display, colormap, visual, colorname, color, + image_pixels, mask_pixels, mask_pixel_index, + alloc_pixels, nalloc_pixels, used_pixels, + nused_pixels, attributes, cols, ncols, + allocColor, closure)) + pixel_defined = True; + else + ErrorStatus = XpmColorError; + } + k = key; + while (!pixel_defined && k > 1) { + if (defaults[k]) { + if (!SetColor(display, colormap, visual, defaults[k], + color, image_pixels, mask_pixels, + mask_pixel_index, alloc_pixels, + nalloc_pixels, used_pixels, nused_pixels, + attributes, cols, ncols, + allocColor, closure)) { + pixel_defined = True; + break; + } else + ErrorStatus = XpmColorError; + } + k--; + } + k = key + 1; + while (!pixel_defined && k < NKEYS + 1) { + if (defaults[k]) { + if (!SetColor(display, colormap, visual, defaults[k], + color, image_pixels, mask_pixels, + mask_pixel_index, alloc_pixels, + nalloc_pixels, used_pixels, nused_pixels, + attributes, cols, ncols, + allocColor, closure)) { + pixel_defined = True; + break; + } else + ErrorStatus = XpmColorError; + } + k++; + } + if (!pixel_defined) { + if (cols) + XpmFree(cols); + return (XpmColorFailed); + } + } else { + /* simply use the given pixel */ + *image_pixels = symbol->pixel; + /* the following makes the mask to be built even if none + is given a particular pixel */ + if (symbol->value + && !xpmstrcasecmp(symbol->value, TRANSPARENT_COLOR)) { + *mask_pixels = 0; + *mask_pixel_index = color; + } else + *mask_pixels = 1; + used_pixels[(*nused_pixels)++] = *image_pixels; + } + } + if (cols) + XpmFree(cols); + return (ErrorStatus); +} + + +/* default FreeColors function, simply call XFreeColors */ +static int +FreeColors( + Display *display, + Colormap colormap, + Pixel *pixels, + int n, + void *closure) /* not used */ +{ + return XFreeColors(display, colormap, pixels, n, 0); +} + + +/* function call in case of error */ + +#undef RETURN +#define RETURN(status) \ +do \ +{ \ + ErrorStatus = status; \ + goto error; \ +} while(0) + +int +XpmCreateImageFromXpmImage( + Display *display, + XpmImage *image, + XImage **image_return, + XImage **shapeimage_return, + XpmAttributes *attributes) +{ + /* variables stored in the XpmAttributes structure */ + Visual *visual; + Colormap colormap; + unsigned int depth; + int bitmap_format; + XpmFreeColorsFunc freeColors; + + /* variables to return */ + XImage *ximage = NULL; + XImage *shapeimage = NULL; + unsigned int mask_pixel_index = XpmUndefPixel; + int ErrorStatus; + + /* calculation variables */ + Pixel *image_pixels = NULL; + Pixel *mask_pixels = NULL; + Pixel *alloc_pixels = NULL; + Pixel *used_pixels = NULL; + unsigned int nalloc_pixels = 0; + unsigned int nused_pixels = 0; + + /* initialize return values */ + if (image_return) + *image_return = NULL; + if (shapeimage_return) + *shapeimage_return = NULL; + + /* retrieve information from the XpmAttributes */ + if (attributes && (attributes->valuemask & XpmVisual)) + visual = attributes->visual; + else + visual = XDefaultVisual(display, XDefaultScreen(display)); + + if (attributes && (attributes->valuemask & XpmColormap)) + colormap = attributes->colormap; + else + colormap = XDefaultColormap(display, XDefaultScreen(display)); + + if (attributes && (attributes->valuemask & XpmDepth)) + depth = attributes->depth; + else + depth = XDefaultDepth(display, XDefaultScreen(display)); + + if (attributes && (attributes->valuemask & XpmBitmapFormat)) + bitmap_format = attributes->bitmap_format; + else + bitmap_format = ZPixmap; + + if (attributes && (attributes->valuemask & XpmFreeColors)) + freeColors = attributes->free_colors; + else + freeColors = FreeColors; + + ErrorStatus = XpmSuccess; + + if (image->ncolors >= UINT_MAX / sizeof(Pixel)) + return (XpmNoMemory); + + /* malloc pixels index tables */ + image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); + if (!image_pixels) + return (XpmNoMemory); + + mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); + if (!mask_pixels) + RETURN(XpmNoMemory); + + /* maximum of allocated pixels will be the number of colors */ + alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); + if (!alloc_pixels) + RETURN(XpmNoMemory); + + /* maximum of allocated pixels will be the number of colors */ + used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); + if (!used_pixels) + RETURN(XpmNoMemory); + + /* get pixel colors, store them in index tables */ + ErrorStatus = CreateColors(display, attributes, image->colorTable, + image->ncolors, image_pixels, mask_pixels, + &mask_pixel_index, alloc_pixels, &nalloc_pixels, + used_pixels, &nused_pixels); + + if (ErrorStatus != XpmSuccess + && (ErrorStatus < 0 || (attributes + && (attributes->valuemask & XpmExactColors) + && attributes->exactColors))) + RETURN(ErrorStatus); + + /* create the ximage */ + if (image_return) { + ErrorStatus = CreateXImage(display, visual, depth, + (depth == 1 ? bitmap_format : ZPixmap), + image->width, image->height, &ximage); + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + +#ifndef FOR_MSW +# ifndef AMIGA + + /* + * set the ximage data using optimized functions for ZPixmap + */ + + if (ximage->bits_per_pixel == 8) + PutImagePixels8(ximage, image->width, image->height, + image->data, image_pixels); + else if (((ximage->bits_per_pixel | ximage->depth) == 1) && + (ximage->byte_order == ximage->bitmap_bit_order)) + PutImagePixels1(ximage, image->width, image->height, + image->data, image_pixels); + else if (ximage->bits_per_pixel == 16) + PutImagePixels16(ximage, image->width, image->height, + image->data, image_pixels); + else if (ximage->bits_per_pixel == 32) + PutImagePixels32(ximage, image->width, image->height, + image->data, image_pixels); + else + PutImagePixels(ximage, image->width, image->height, + image->data, image_pixels); +# else /* AMIGA */ + APutImagePixels(ximage, image->width, image->height, + image->data, image_pixels); +# endif +#else /* FOR_MSW */ + MSWPutImagePixels(display, ximage, image->width, image->height, + image->data, image_pixels); +#endif + } + /* create the shape mask image */ + if (mask_pixel_index != XpmUndefPixel && shapeimage_return) { + ErrorStatus = CreateXImage(display, visual, 1, bitmap_format, + image->width, image->height, &shapeimage); + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + +#ifndef FOR_MSW +# ifndef AMIGA + PutImagePixels1(shapeimage, image->width, image->height, + image->data, mask_pixels); +# else /* AMIGA */ + APutImagePixels(shapeimage, image->width, image->height, + image->data, mask_pixels); +# endif +#else /* FOR_MSW */ + MSWPutImagePixels(display, shapeimage, image->width, image->height, + image->data, mask_pixels); +#endif + + } + XpmFree(image_pixels); + XpmFree(mask_pixels); + + /* if requested return used pixels in the XpmAttributes structure */ + if (attributes && (attributes->valuemask & XpmReturnPixels || +/* 3.2 backward compatibility code */ + attributes->valuemask & XpmReturnInfos)) { +/* end 3.2 bc */ + attributes->pixels = used_pixels; + attributes->npixels = nused_pixels; + attributes->mask_pixel = mask_pixel_index; + } else + XpmFree(used_pixels); + + /* if requested return alloc'ed pixels in the XpmAttributes structure */ + if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) { + attributes->alloc_pixels = alloc_pixels; + attributes->nalloc_pixels = nalloc_pixels; + } else + XpmFree(alloc_pixels); + + /* return created images */ + if (image_return) + *image_return = ximage; + if (shapeimage_return) + *shapeimage_return = shapeimage; + + return (ErrorStatus); + +/* exit point in case of error, free only locally allocated variables */ +error: + if (ximage) + XDestroyImage(ximage); + if (shapeimage) + XDestroyImage(shapeimage); + if (image_pixels) + XpmFree(image_pixels); + if (mask_pixels) + XpmFree(mask_pixels); + if (nalloc_pixels) + (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL); + if (alloc_pixels) + XpmFree(alloc_pixels); + if (used_pixels) + XpmFree(used_pixels); + + return (ErrorStatus); +} + + +/* + * Create an XImage with its data + */ +static int +CreateXImage( + Display *display, + Visual *visual, + unsigned int depth, + int format, + unsigned int width, + unsigned int height, + XImage **image_return) +{ + int bitmap_pad; + + /* first get bitmap_pad */ + if (depth > 16) + bitmap_pad = 32; + else if (depth > 8) + bitmap_pad = 16; + else + bitmap_pad = 8; + + /* then create the XImage with data = NULL and bytes_per_line = 0 */ + *image_return = XCreateImage(display, visual, depth, format, 0, 0, + width, height, bitmap_pad, 0); + if (!*image_return) + return (XpmNoMemory); + +#if !defined(FOR_MSW) && !defined(AMIGA) + if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) { + XDestroyImage(*image_return); + return XpmNoMemory; + } + /* now that bytes_per_line must have been set properly alloc data */ + if((*image_return)->bytes_per_line == 0 || height == 0) + return XpmNoMemory; + (*image_return)->data = + (char *) XpmMalloc((*image_return)->bytes_per_line * height); + + if (!(*image_return)->data) { + XDestroyImage(*image_return); + *image_return = NULL; + return (XpmNoMemory); + } +#else + /* under FOR_MSW and AMIGA XCreateImage has done it all */ +#endif + return (XpmSuccess); +} + +#ifndef FOR_MSW +# ifndef AMIGA +/* + * The functions below are written from X11R5 MIT's code (XImUtil.c) + * + * The idea is to have faster functions than the standard XPutPixel function + * to build the image data. Indeed we can speed up things by suppressing tests + * performed for each pixel. We do the same tests but at the image level. + * We also assume that we use only ZPixmap images with null offsets. + */ + +LFUNC(_putbits, void, (register char *src, int dstoffset, + register int numbits, register char *dst)); + +LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register unsigned int nb)); + +static unsigned char Const _reverse_byte[0x100] = { + 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, + 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, + 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, + 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, + 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, + 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, + 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, + 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, + 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, + 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, + 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, + 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, + 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, + 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, + 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, + 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, + 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, + 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, + 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, + 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, + 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, + 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, + 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, + 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, + 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, + 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, + 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, + 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, + 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, + 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, + 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, + 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff +}; + +static int +_XReverse_Bytes( + register unsigned char *bpt, + register unsigned int nb) +{ + do { + *bpt = _reverse_byte[*bpt]; + bpt++; + } while (--nb > 0); /* is nb user-controled? */ + return 0; +} + + +void +xpm_xynormalizeimagebits( + register unsigned char *bp, + register XImage *img) +{ + register unsigned char c; + + if (img->byte_order != img->bitmap_bit_order) { + switch (img->bitmap_unit) { + + case 16: + c = *bp; + *bp = *(bp + 1); + *(bp + 1) = c; + break; + + case 32: + c = *(bp + 3); + *(bp + 3) = *bp; + *bp = c; + c = *(bp + 2); + *(bp + 2) = *(bp + 1); + *(bp + 1) = c; + break; + } + } + if (img->bitmap_bit_order == MSBFirst) + _XReverse_Bytes(bp, img->bitmap_unit >> 3); +} + +void +xpm_znormalizeimagebits( + register unsigned char *bp, + register XImage *img) +{ + register unsigned char c; + + switch (img->bits_per_pixel) { + + case 2: + _XReverse_Bytes(bp, 1); + break; + + case 4: + *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF); + break; + + case 16: + c = *bp; + *bp = *(bp + 1); + *(bp + 1) = c; + break; + + case 24: + c = *(bp + 2); + *(bp + 2) = *bp; + *bp = c; + break; + + case 32: + c = *(bp + 3); + *(bp + 3) = *bp; + *bp = c; + c = *(bp + 2); + *(bp + 2) = *(bp + 1); + *(bp + 1) = c; + break; + } +} + +static unsigned char Const _lomask[0x09] = { +0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; +static unsigned char Const _himask[0x09] = { +0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; + +static void +_putbits( + register char *src, /* address of source bit string */ + int dstoffset, /* bit offset into destination; + * range is 0-31 */ + register int numbits, /* number of bits to copy to + * destination */ + register char *dst) /* address of destination bit string */ +{ + register unsigned char chlo, chhi; + int hibits; + + dst = dst + (dstoffset >> 3); + dstoffset = dstoffset & 7; + hibits = 8 - dstoffset; + chlo = *dst & _lomask[dstoffset]; + for (;;) { + chhi = (*src << dstoffset) & _himask[dstoffset]; + if (numbits <= hibits) { + chhi = chhi & _lomask[dstoffset + numbits]; + *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi; + break; + } + *dst = chhi | chlo; + dst++; + numbits = numbits - hibits; + chlo = (unsigned char) (*src & _himask[hibits]) >> hibits; + src++; + if (numbits <= dstoffset) { + chlo = chlo & _lomask[numbits]; + *dst = (*dst & _himask[numbits]) | chlo; + break; + } + numbits = numbits - dstoffset; + } +} + +/* + * Default method to write pixels into a Z image data structure. + * The algorithm used is: + * + * copy the destination bitmap_unit or Zpixel to temp + * normalize temp if needed + * copy the pixel bits into the temp + * renormalize temp if needed + * copy the temp back into the destination image data + */ + +static void +PutImagePixels( + XImage *image, + unsigned int width, + unsigned int height, + unsigned int *pixelindex, + Pixel *pixels) +{ + register char *src; + register char *dst; + register unsigned int *iptr; + register unsigned int x, y; + register char *data; + Pixel pixel, px; + int nbytes, depth, ibu, ibpp, i; + + data = image->data; + iptr = pixelindex; + depth = image->depth; + if (depth == 1) { + ibu = image->bitmap_unit; + for (y = 0; y < height; y++) /* how can we trust height */ + for (x = 0; x < width; x++, iptr++) { /* how can we trust width */ + pixel = pixels[*iptr]; + for (i = 0, px = pixel; i < sizeof(unsigned long); + i++, px >>= 8) + ((unsigned char *) &pixel)[i] = px; + src = &data[XYINDEX(x, y, image)]; + dst = (char *) &px; + px = 0; + nbytes = ibu >> 3; + for (i = nbytes; --i >= 0;) + *dst++ = *src++; + XYNORMALIZE(&px, image); + _putbits((char *) &pixel, (x % ibu), 1, (char *) &px); + XYNORMALIZE(&px, image); + src = (char *) &px; + dst = &data[XYINDEX(x, y, image)]; + for (i = nbytes; --i >= 0;) + *dst++ = *src++; + } + } else { + ibpp = image->bits_per_pixel; + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + pixel = pixels[*iptr]; + if (depth == 4) + pixel &= 0xf; + for (i = 0, px = pixel; i < sizeof(unsigned long); i++, + px >>= 8) + ((unsigned char *) &pixel)[i] = px; + src = &data[ZINDEX(x, y, image)]; + dst = (char *) &px; + px = 0; + nbytes = (ibpp + 7) >> 3; + for (i = nbytes; --i >= 0;) + *dst++ = *src++; + ZNORMALIZE(&px, image); + _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px); + ZNORMALIZE(&px, image); + src = (char *) &px; + dst = &data[ZINDEX(x, y, image)]; + for (i = nbytes; --i >= 0;) + *dst++ = *src++; + } + } +} + +/* + * write pixels into a 32-bits Z image data structure + */ + +#if !defined(WORD64) && !defined(LONG64) +/* this item is static but deterministic so let it slide; doesn't + * hurt re-entrancy of this library. Note if it is actually const then would + * be OK under rules of ANSI-C but probably not C++ which may not + * want to allocate space for it. + */ +static unsigned long byteorderpixel = MSBFirst << 24; + +#endif + +/* + WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original + 3.2e code - by default you get the speeded-up version. +*/ + +static void +PutImagePixels32( + XImage *image, + unsigned int width, + unsigned int height, + unsigned int *pixelindex, + Pixel *pixels) +{ + unsigned char *data; + unsigned int *iptr; + unsigned int y; + Pixel pixel; + +#ifdef WITHOUT_SPEEDUPS + + unsigned int x; + unsigned char *addr; + + data = (unsigned char *) image->data; + iptr = pixelindex; +#if !defined(WORD64) && !defined(LONG64) + if (*((char *) &byteorderpixel) == image->byte_order) { + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + addr = &data[ZINDEX32(x, y, image)]; + *((unsigned long *) addr) = pixels[*iptr]; + } + } else +#endif + if (image->byte_order == MSBFirst) + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + addr = &data[ZINDEX32(x, y, image)]; + pixel = pixels[*iptr]; + addr[0] = pixel >> 24; + addr[1] = pixel >> 16; + addr[2] = pixel >> 8; + addr[3] = pixel; + } + else + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + addr = &data[ZINDEX32(x, y, image)]; + pixel = pixels[*iptr]; + addr[0] = pixel; + addr[1] = pixel >> 8; + addr[2] = pixel >> 16; + addr[3] = pixel >> 24; + } + +#else /* WITHOUT_SPEEDUPS */ + + unsigned int bpl = image->bytes_per_line; + unsigned char *data_ptr, *max_data; + + data = (unsigned char *) image->data; + iptr = pixelindex; +#if !defined(WORD64) && !defined(LONG64) + if (*((char *) &byteorderpixel) == image->byte_order) { + for (y = 0; y < height; y++) { + data_ptr = data; + max_data = data_ptr + (width << 2); + + while (data_ptr < max_data) { + *((unsigned long *) data_ptr) = pixels[*(iptr++)]; + data_ptr += (1 << 2); + } + data += bpl; + } + } else +#endif + if (image->byte_order == MSBFirst) + for (y = 0; y < height; y++) { + data_ptr = data; + max_data = data_ptr + (width << 2); + + while (data_ptr < max_data) { + pixel = pixels[*(iptr++)]; + + *data_ptr++ = pixel >> 24; + *data_ptr++ = pixel >> 16; + *data_ptr++ = pixel >> 8; + *data_ptr++ = pixel; + + } + data += bpl; + } + else + for (y = 0; y < height; y++) { + data_ptr = data; + max_data = data_ptr + (width << 2); + + while (data_ptr < max_data) { + pixel = pixels[*(iptr++)]; + + *data_ptr++ = pixel; + *data_ptr++ = pixel >> 8; + *data_ptr++ = pixel >> 16; + *data_ptr++ = pixel >> 24; + } + data += bpl; + } + +#endif /* WITHOUT_SPEEDUPS */ +} + +/* + * write pixels into a 16-bits Z image data structure + */ + +static void +PutImagePixels16( + XImage *image, + unsigned int width, + unsigned int height, + unsigned int *pixelindex, + Pixel *pixels) +{ + unsigned char *data; + unsigned int *iptr; + unsigned int y; + +#ifdef WITHOUT_SPEEDUPS + + unsigned int x; + unsigned char *addr; + + data = (unsigned char *) image->data; + iptr = pixelindex; + if (image->byte_order == MSBFirst) + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + addr = &data[ZINDEX16(x, y, image)]; + addr[0] = pixels[*iptr] >> 8; + addr[1] = pixels[*iptr]; + } + else + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + addr = &data[ZINDEX16(x, y, image)]; + addr[0] = pixels[*iptr]; + addr[1] = pixels[*iptr] >> 8; + } + +#else /* WITHOUT_SPEEDUPS */ + + Pixel pixel; + + unsigned int bpl = image->bytes_per_line; + unsigned char *data_ptr, *max_data; + + data = (unsigned char *) image->data; + iptr = pixelindex; + if (image->byte_order == MSBFirst) + for (y = 0; y < height; y++) { + data_ptr = data; + max_data = data_ptr + (width << 1); + + while (data_ptr < max_data) { + pixel = pixels[*(iptr++)]; + + data_ptr[0] = pixel >> 8; + data_ptr[1] = pixel; + + data_ptr += (1 << 1); + } + data += bpl; + } + else + for (y = 0; y < height; y++) { + data_ptr = data; + max_data = data_ptr + (width << 1); + + while (data_ptr < max_data) { + pixel = pixels[*(iptr++)]; + + data_ptr[0] = pixel; + data_ptr[1] = pixel >> 8; + + data_ptr += (1 << 1); + } + data += bpl; + } + +#endif /* WITHOUT_SPEEDUPS */ +} + +/* + * write pixels into a 8-bits Z image data structure + */ + +static void +PutImagePixels8( + XImage *image, + unsigned int width, + unsigned int height, + unsigned int *pixelindex, + Pixel *pixels) +{ + char *data; + unsigned int *iptr; + unsigned int y; + +#ifdef WITHOUT_SPEEDUPS + + unsigned int x; + + data = image->data; + iptr = pixelindex; + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) + data[ZINDEX8(x, y, image)] = pixels[*iptr]; + +#else /* WITHOUT_SPEEDUPS */ + + unsigned int bpl = image->bytes_per_line; + char *data_ptr, *max_data; + + data = image->data; + iptr = pixelindex; + + for (y = 0; y < height; y++) { + data_ptr = data; + max_data = data_ptr + width; + + while (data_ptr < max_data) + *(data_ptr++) = pixels[*(iptr++)]; + + data += bpl; + } + +#endif /* WITHOUT_SPEEDUPS */ +} + +/* + * write pixels into a 1-bit depth image data structure and **offset null** + */ + +static void +PutImagePixels1( + XImage *image, + unsigned int width, + unsigned int height, + unsigned int *pixelindex, + Pixel *pixels) +{ + if (image->byte_order != image->bitmap_bit_order) + PutImagePixels(image, width, height, pixelindex, pixels); + else { + unsigned int *iptr; + unsigned int y; + char *data; + +#ifdef WITHOUT_SPEEDUPS + + unsigned int x; + + data = image->data; + iptr = pixelindex; + if (image->bitmap_bit_order == MSBFirst) + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + if (pixels[*iptr] & 1) + data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7); + else + data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7)); + } + else + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + if (pixels[*iptr] & 1) + data[ZINDEX1(x, y, image)] |= 1 << (x & 7); + else + data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7)); + } + +#else /* WITHOUT_SPEEDUPS */ + + char value; + char *data_ptr, *max_data; + int bpl = image->bytes_per_line; + int diff, count; + + data = image->data; + iptr = pixelindex; + + diff = width & 7; + width >>= 3; + + if (image->bitmap_bit_order == MSBFirst) + for (y = 0; y < height; y++) { + data_ptr = data; + max_data = data_ptr + width; + while (data_ptr < max_data) { + value = 0; + + value = (value << 1) | (pixels[*(iptr++)] & 1); + value = (value << 1) | (pixels[*(iptr++)] & 1); + value = (value << 1) | (pixels[*(iptr++)] & 1); + value = (value << 1) | (pixels[*(iptr++)] & 1); + value = (value << 1) | (pixels[*(iptr++)] & 1); + value = (value << 1) | (pixels[*(iptr++)] & 1); + value = (value << 1) | (pixels[*(iptr++)] & 1); + value = (value << 1) | (pixels[*(iptr++)] & 1); + + *(data_ptr++) = value; + } + if (diff) { + value = 0; + for (count = 0; count < diff; count++) { + if (pixels[*(iptr++)] & 1) + value |= (0x80 >> count); + } + *(data_ptr) = value; + } + data += bpl; + } + else + for (y = 0; y < height; y++) { + data_ptr = data; + max_data = data_ptr + width; + while (data_ptr < max_data) { + value = 0; + iptr += 8; + + value = (value << 1) | (pixels[*(--iptr)] & 1); + value = (value << 1) | (pixels[*(--iptr)] & 1); + value = (value << 1) | (pixels[*(--iptr)] & 1); + value = (value << 1) | (pixels[*(--iptr)] & 1); + value = (value << 1) | (pixels[*(--iptr)] & 1); + value = (value << 1) | (pixels[*(--iptr)] & 1); + value = (value << 1) | (pixels[*(--iptr)] & 1); + value = (value << 1) | (pixels[*(--iptr)] & 1); + + iptr += 8; + *(data_ptr++) = value; + } + if (diff) { + value = 0; + for (count = 0; count < diff; count++) { + if (pixels[*(iptr++)] & 1) + value |= (1 << count); + } + *(data_ptr) = value; + } + data += bpl; + } + +#endif /* WITHOUT_SPEEDUPS */ + } +} + +int +XpmCreatePixmapFromXpmImage( + Display *display, + Drawable d, + XpmImage *image, + Pixmap *pixmap_return, + Pixmap *shapemask_return, + XpmAttributes *attributes) +{ + XImage *ximage, *shapeimage; + int ErrorStatus; + + /* initialize return values */ + if (pixmap_return) + *pixmap_return = 0; + if (shapemask_return) + *shapemask_return = 0; + + /* create the ximages */ + ErrorStatus = XpmCreateImageFromXpmImage(display, image, + (pixmap_return ? &ximage : NULL), + (shapemask_return ? + &shapeimage : NULL), + attributes); + if (ErrorStatus < 0) + return (ErrorStatus); + + /* create the pixmaps and destroy images */ + if (pixmap_return && ximage) { + xpmCreatePixmapFromImage(display, d, ximage, pixmap_return); + XDestroyImage(ximage); + } + if (shapemask_return && shapeimage) { + xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return); + XDestroyImage(shapeimage); + } + return (ErrorStatus); +} + +# else /* AMIGA */ + +static void +APutImagePixels ( + XImage *image, + unsigned int width, + unsigned int height, + unsigned int *pixelindex, + Pixel *pixels) +{ + unsigned int *data = pixelindex; + unsigned int x, y; + unsigned char *array; + XImage *tmp_img; + BOOL success = FALSE; + + array = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*array)); + if (array != NULL) + { + tmp_img = AllocXImage ((((width+15)>>4)<<4), 1, + image->rp->BitMap->Depth); + if (tmp_img != NULL) + { + for (y = 0; y < height; ++y) + { + for (x = 0; x < width; ++x) + array[x] = pixels[*(data++)]; + WritePixelLine8 (image->rp, 0, y, width, array, tmp_img->rp); + } + FreeXImage (tmp_img); + success = TRUE; + } + XpmFree (array); + } + + if (!success) + { + for (y = 0; y < height; ++y) + for (x = 0; x < width; ++x) + XPutPixel (image, x, y, pixels[*(data++)]); + } +} + +# endif/* AMIGA */ +#else /* FOR_MSW part follows */ +static void +MSWPutImagePixels( + Display *dc, + XImage *image, + unsigned int width, + unsigned int height, + unsigned int *pixelindex, + Pixel *pixels) +{ + unsigned int *data = pixelindex; + unsigned int x, y; + HBITMAP obm; + + obm = SelectObject(*dc, image->bitmap); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */ + } + } + SelectObject(*dc, obm); +} + +#endif /* FOR_MSW */ + + + +#if !defined(FOR_MSW) && !defined(AMIGA) + +static int +PutPixel1( + register XImage *ximage, + int x, + int y, + unsigned long pixel) +{ + register char *src; + register char *dst; + register int i; + Pixel px; + int nbytes; + + if(x < 0 || y < 0) + return 0; + + for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8) + ((unsigned char *)&pixel)[i] = px; + src = &ximage->data[XYINDEX(x, y, ximage)]; + dst = (char *)&px; + px = 0; + nbytes = ximage->bitmap_unit >> 3; + for (i = nbytes; --i >= 0; ) *dst++ = *src++; + XYNORMALIZE(&px, ximage); + i = ((x + ximage->xoffset) % ximage->bitmap_unit); + _putbits ((char *)&pixel, i, 1, (char *)&px); + XYNORMALIZE(&px, ximage); + src = (char *) &px; + dst = &ximage->data[XYINDEX(x, y, ximage)]; + for (i = nbytes; --i >= 0; ) + *dst++ = *src++; + + return 1; +} + +static int +PutPixel( + register XImage *ximage, + int x, + int y, + unsigned long pixel) +{ + register char *src; + register char *dst; + register int i; + Pixel px; + unsigned int nbytes, ibpp; + + if(x < 0 || y < 0) + return 0; + + ibpp = ximage->bits_per_pixel; + if (ximage->depth == 4) + pixel &= 0xf; + for (i = 0, px = pixel; i < sizeof(unsigned long); i++, px >>= 8) + ((unsigned char *) &pixel)[i] = px; + src = &ximage->data[ZINDEX(x, y, ximage)]; + dst = (char *) &px; + px = 0; + nbytes = (ibpp + 7) >> 3; + for (i = nbytes; --i >= 0;) + *dst++ = *src++; + ZNORMALIZE(&px, ximage); + _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px); + ZNORMALIZE(&px, ximage); + src = (char *) &px; + dst = &ximage->data[ZINDEX(x, y, ximage)]; + for (i = nbytes; --i >= 0;) + *dst++ = *src++; + + return 1; +} + +#if !defined(WORD64) && !defined(LONG64) +static int +PutPixel32( + register XImage *ximage, + int x, + int y, + unsigned long pixel) +{ + unsigned char *addr; + + if(x < 0 || y < 0) + return 0; + + addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)]; + *((unsigned long *)addr) = pixel; + return 1; +} +#endif + +static int +PutPixel32MSB( + register XImage *ximage, + int x, + int y, + unsigned long pixel) +{ + unsigned char *addr; + + if(x < 0 || y < 0) + return 0; + + addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)]; + addr[0] = pixel >> 24; + addr[1] = pixel >> 16; + addr[2] = pixel >> 8; + addr[3] = pixel; + return 1; +} + +static int +PutPixel32LSB( + register XImage *ximage, + int x, + int y, + unsigned long pixel) +{ + unsigned char *addr; + + if(x < 0 || y < 0) + return 0; + + addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)]; + addr[3] = pixel >> 24; + addr[2] = pixel >> 16; + addr[1] = pixel >> 8; + addr[0] = pixel; + return 1; +} + +static int +PutPixel16MSB( + register XImage *ximage, + int x, + int y, + unsigned long pixel) +{ + unsigned char *addr; + + if(x < 0 || y < 0) + return 0; + + addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)]; + addr[0] = pixel >> 8; + addr[1] = pixel; + return 1; +} + +static int +PutPixel16LSB( + register XImage *ximage, + int x, + int y, + unsigned long pixel) +{ + unsigned char *addr; + + if(x < 0 || y < 0) + return 0; + + addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)]; + addr[1] = pixel >> 8; + addr[0] = pixel; + return 1; +} + +static int +PutPixel8( + register XImage *ximage, + int x, + int y, + unsigned long pixel) +{ + if(x < 0 || y < 0) + return 0; + + ximage->data[ZINDEX8(x, y, ximage)] = pixel; + return 1; +} + +static int +PutPixel1MSB( + register XImage *ximage, + int x, + int y, + unsigned long pixel) +{ + if(x < 0 || y < 0) + return 0; + + if (pixel & 1) + ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7); + else + ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7)); + return 1; +} + +static int +PutPixel1LSB( + register XImage *ximage, + int x, + int y, + unsigned long pixel) +{ + if(x < 0 || y < 0) + return 0; + + if (pixel & 1) + ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7); + else + ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7)); + return 1; +} + +#endif /* not FOR_MSW && not AMIGA */ + +/* + * This function parses an Xpm file or data and directly create an XImage + */ +int +xpmParseDataAndCreate( + Display *display, + xpmData *data, + XImage **image_return, + XImage **shapeimage_return, + XpmImage *image, + XpmInfo *info, + XpmAttributes *attributes) +{ + /* variables stored in the XpmAttributes structure */ + Visual *visual; + Colormap colormap; + unsigned int depth; + int bitmap_format; + XpmFreeColorsFunc freeColors; + + /* variables to return */ + XImage *ximage = NULL; + XImage *shapeimage = NULL; + unsigned int mask_pixel_index = XpmUndefPixel; + + /* calculation variables */ + Pixel *image_pixels = NULL; + Pixel *mask_pixels = NULL; + Pixel *alloc_pixels = NULL; + Pixel *used_pixels = NULL; + unsigned int nalloc_pixels = 0; + unsigned int nused_pixels = 0; + unsigned int width, height, ncolors, cpp; + unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0; + XpmColor *colorTable = NULL; + char *hints_cmt = NULL; + char *colors_cmt = NULL; + char *pixels_cmt = NULL; + + unsigned int cmts; + int ErrorStatus; + xpmHashTable hashtable; + + + /* initialize return values */ + if (image_return) + *image_return = NULL; + if (shapeimage_return) + *shapeimage_return = NULL; + + + /* retrieve information from the XpmAttributes */ + if (attributes && (attributes->valuemask & XpmVisual)) + visual = attributes->visual; + else + visual = XDefaultVisual(display, XDefaultScreen(display)); + + if (attributes && (attributes->valuemask & XpmColormap)) + colormap = attributes->colormap; + else + colormap = XDefaultColormap(display, XDefaultScreen(display)); + + if (attributes && (attributes->valuemask & XpmDepth)) + depth = attributes->depth; + else + depth = XDefaultDepth(display, XDefaultScreen(display)); + + if (attributes && (attributes->valuemask & XpmBitmapFormat)) + bitmap_format = attributes->bitmap_format; + else + bitmap_format = ZPixmap; + + if (attributes && (attributes->valuemask & XpmFreeColors)) + freeColors = attributes->free_colors; + else + freeColors = FreeColors; + + cmts = info && (info->valuemask & XpmReturnComments); + + /* + * parse the header + */ + ErrorStatus = xpmParseHeader(data); + if (ErrorStatus != XpmSuccess) + return (ErrorStatus); + + /* + * read values + */ + ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp, + &x_hotspot, &y_hotspot, &hotspot, + &extensions); + if (ErrorStatus != XpmSuccess) + return (ErrorStatus); + + /* + * store the hints comment line + */ + if (cmts) + xpmGetCmt(data, &hints_cmt); + + /* + * init the hashtable + */ + if (USE_HASHTABLE) { + ErrorStatus = xpmHashTableInit(&hashtable); + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + } + + /* + * read colors + */ + ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable); + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + + /* + * store the colors comment line + */ + if (cmts) + xpmGetCmt(data, &colors_cmt); + + /* malloc pixels index tables */ + if (ncolors >= UINT_MAX / sizeof(Pixel)) + RETURN(XpmNoMemory); + + image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); + if (!image_pixels) + RETURN(XpmNoMemory); + + mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); + if (!mask_pixels) + RETURN(XpmNoMemory); + + /* maximum of allocated pixels will be the number of colors */ + alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); + if (!alloc_pixels) + RETURN(XpmNoMemory); + + /* maximum of allocated pixels will be the number of colors */ + used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); + if (!used_pixels) + RETURN(XpmNoMemory); + + /* get pixel colors, store them in index tables */ + ErrorStatus = CreateColors(display, attributes, colorTable, ncolors, + image_pixels, mask_pixels, &mask_pixel_index, + alloc_pixels, &nalloc_pixels, used_pixels, + &nused_pixels); + + if (ErrorStatus != XpmSuccess + && (ErrorStatus < 0 || (attributes + && (attributes->valuemask & XpmExactColors) + && attributes->exactColors))) + RETURN(ErrorStatus); + + /* now create the ximage */ + if (image_return) { + ErrorStatus = CreateXImage(display, visual, depth, + (depth == 1 ? bitmap_format : ZPixmap), + width, height, &ximage); + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + +#if !defined(FOR_MSW) && !defined(AMIGA) + + /* + * set the XImage pointer function, to be used with XPutPixel, + * to an internal optimized function + */ + + if (ximage->bits_per_pixel == 8) + ximage->f.put_pixel = PutPixel8; + else if (((ximage->bits_per_pixel | ximage->depth) == 1) && + (ximage->byte_order == ximage->bitmap_bit_order)) + if (ximage->bitmap_bit_order == MSBFirst) + ximage->f.put_pixel = PutPixel1MSB; + else + ximage->f.put_pixel = PutPixel1LSB; + else if (ximage->bits_per_pixel == 16) + if (ximage->bitmap_bit_order == MSBFirst) + ximage->f.put_pixel = PutPixel16MSB; + else + ximage->f.put_pixel = PutPixel16LSB; + else if (ximage->bits_per_pixel == 32) +#if !defined(WORD64) && !defined(LONG64) + if (*((char *)&byteorderpixel) == ximage->byte_order) + ximage->f.put_pixel = PutPixel32; + else +#endif + if (ximage->bitmap_bit_order == MSBFirst) + ximage->f.put_pixel = PutPixel32MSB; + else + ximage->f.put_pixel = PutPixel32LSB; + else if ((ximage->bits_per_pixel | ximage->depth) == 1) + ximage->f.put_pixel = PutPixel1; + else + ximage->f.put_pixel = PutPixel; +#endif /* not FOR_MSW && not AMIGA */ + } + + /* create the shape mask image */ + if (mask_pixel_index != XpmUndefPixel && shapeimage_return) { + ErrorStatus = CreateXImage(display, visual, 1, bitmap_format, + width, height, &shapeimage); + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + +#if !defined(FOR_MSW) && !defined(AMIGA) + if (shapeimage->bitmap_bit_order == MSBFirst) + shapeimage->f.put_pixel = PutPixel1MSB; + else + shapeimage->f.put_pixel = PutPixel1LSB; +#endif + } + + /* + * read pixels and put them in the XImage + */ + ErrorStatus = ParseAndPutPixels( +#ifdef FOR_MSW + display, +#endif + data, width, height, ncolors, cpp, + colorTable, &hashtable, + ximage, image_pixels, + shapeimage, mask_pixels); + XpmFree(image_pixels); + image_pixels = NULL; + XpmFree(mask_pixels); + mask_pixels = NULL; + + /* + * free the hastable + */ + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + else if (USE_HASHTABLE) + xpmHashTableFree(&hashtable); + + /* + * store the pixels comment line + */ + if (cmts) + xpmGetCmt(data, &pixels_cmt); + + /* + * parse extensions + */ + if (info && (info->valuemask & XpmReturnExtensions)) { + if (extensions) { + ErrorStatus = xpmParseExtensions(data, &info->extensions, + &info->nextensions); + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + } else { + info->extensions = NULL; + info->nextensions = 0; + } + } + /* + * store found informations in the XpmImage structure + */ + image->width = width; + image->height = height; + image->cpp = cpp; + image->ncolors = ncolors; + image->colorTable = colorTable; + image->data = NULL; + + if (info) { + if (cmts) { + info->hints_cmt = hints_cmt; + info->colors_cmt = colors_cmt; + info->pixels_cmt = pixels_cmt; + } + if (hotspot) { + info->x_hotspot = x_hotspot; + info->y_hotspot = y_hotspot; + info->valuemask |= XpmHotspot; + } + } + /* if requested return used pixels in the XpmAttributes structure */ + if (attributes && (attributes->valuemask & XpmReturnPixels || +/* 3.2 backward compatibility code */ + attributes->valuemask & XpmReturnInfos)) { +/* end 3.2 bc */ + attributes->pixels = used_pixels; + attributes->npixels = nused_pixels; + attributes->mask_pixel = mask_pixel_index; + } else + XpmFree(used_pixels); + + /* if requested return alloc'ed pixels in the XpmAttributes structure */ + if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) { + attributes->alloc_pixels = alloc_pixels; + attributes->nalloc_pixels = nalloc_pixels; + } else + XpmFree(alloc_pixels); + + /* return created images */ + if (image_return) + *image_return = ximage; + if (shapeimage_return) + *shapeimage_return = shapeimage; + + return (XpmSuccess); + +/* exit point in case of error, free only locally allocated variables */ +error: + if (USE_HASHTABLE) + xpmHashTableFree(&hashtable); + if (colorTable) + xpmFreeColorTable(colorTable, ncolors); + if (hints_cmt) + XpmFree(hints_cmt); + if (colors_cmt) + XpmFree(colors_cmt); + if (pixels_cmt) + XpmFree(pixels_cmt); + if (ximage) + XDestroyImage(ximage); + if (shapeimage) + XDestroyImage(shapeimage); + if (image_pixels) + XpmFree(image_pixels); + if (mask_pixels) + XpmFree(mask_pixels); + if (nalloc_pixels) + (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL); + if (alloc_pixels) + XpmFree(alloc_pixels); + if (used_pixels) + XpmFree(used_pixels); + + return (ErrorStatus); +} + +static int +ParseAndPutPixels( +#ifdef FOR_MSW + Display *dc, +#endif + xpmData *data, + unsigned int width, + unsigned int height, + unsigned int ncolors, + unsigned int cpp, + XpmColor *colorTable, + xpmHashTable *hashtable, + XImage *image, + Pixel *image_pixels, + XImage *shapeimage, + Pixel *shape_pixels) +{ + unsigned int a, x, y; + + switch (cpp) { + + case (1): /* Optimize for single character + * colors */ + { + unsigned short colidx[256]; +#ifdef FOR_MSW + HDC shapedc; + HBITMAP obm, sobm; + + if ( shapeimage ) { + shapedc = CreateCompatibleDC(*dc); + sobm = SelectObject(shapedc, shapeimage->bitmap); + } else { + shapedc = NULL; + } + obm = SelectObject(*dc, image->bitmap); +#endif + if (ncolors > 256) + return (XpmFileInvalid); + + bzero((char *)colidx, 256 * sizeof(short)); + for (a = 0; a < ncolors; a++) + colidx[(unsigned char)colorTable[a].string[0]] = a + 1; + + for (y = 0; y < height; y++) { + xpmNextString(data); + for (x = 0; x < width; x++) { + int c = xpmGetC(data); + + if (c > 0 && c < 256 && colidx[c] != 0) { +#ifndef FOR_MSW + XPutPixel(image, x, y, image_pixels[colidx[c] - 1]); + if (shapeimage) + XPutPixel(shapeimage, x, y, + shape_pixels[colidx[c] - 1]); +#else + SetPixel(*dc, x, y, image_pixels[colidx[c] - 1]); + if (shapedc) { + SetPixel(shapedc, x, y, shape_pixels[colidx[c] - 1]); + } +#endif + } else + return (XpmFileInvalid); + } + } +#ifdef FOR_MSW + if ( shapedc ) { + SelectObject(shapedc, sobm); + DeleteDC(shapedc); + } + SelectObject(*dc, obm); +#endif + } + break; + + case (2): /* Optimize for double character + * colors */ + { + +/* free all allocated pointers at all exits */ +#define FREE_CIDX {int f; for (f = 0; f < 256; f++) \ +if (cidx[f]) XpmFree(cidx[f]);} + + /* array of pointers malloced by need */ + unsigned short *cidx[256]; + unsigned int char1; + + bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */ + for (a = 0; a < ncolors; a++) { + char1 = (unsigned char) colorTable[a].string[0]; + if (cidx[char1] == NULL) { /* get new memory */ + cidx[char1] = (unsigned short *) + XpmCalloc(256, sizeof(unsigned short)); + if (cidx[char1] == NULL) { /* new block failed */ + FREE_CIDX; + return (XpmNoMemory); + } + } + cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1; + } + + for (y = 0; y < height; y++) { + xpmNextString(data); + for (x = 0; x < width; x++) { + int cc1 = xpmGetC(data); + if (cc1 > 0 && cc1 < 256) { + int cc2 = xpmGetC(data); + if (cc2 > 0 && cc2 < 256 && + cidx[cc1] && cidx[cc1][cc2] != 0) { +#ifndef FOR_MSW + XPutPixel(image, x, y, + image_pixels[cidx[cc1][cc2] - 1]); + if (shapeimage) + XPutPixel(shapeimage, x, y, + shape_pixels[cidx[cc1][cc2] - 1]); +#else + SelectObject(*dc, image->bitmap); + SetPixel(*dc, x, y, image_pixels[cidx[cc1][cc2] - 1]); + if (shapeimage) { + SelectObject(*dc, shapeimage->bitmap); + SetPixel(*dc, x, y, + shape_pixels[cidx[cc1][cc2] - 1]); + } +#endif + } else { + FREE_CIDX; + return (XpmFileInvalid); + } + } else { + FREE_CIDX; + return (XpmFileInvalid); + } + } + } + FREE_CIDX; + } + break; + + default: /* Non-optimized case of long color + * names */ + { + char *s; + char buf[BUFSIZ]; + + if (cpp >= sizeof(buf)) + return (XpmFileInvalid); + + buf[cpp] = '\0'; + if (USE_HASHTABLE) { + xpmHashAtom *slot; + + for (y = 0; y < height; y++) { + xpmNextString(data); + for (x = 0; x < width; x++) { + for (a = 0, s = buf; a < cpp; a++, s++) + *s = xpmGetC(data); + slot = xpmHashSlot(hashtable, buf); + if (!*slot) /* no color matches */ + return (XpmFileInvalid); +#ifndef FOR_MSW + XPutPixel(image, x, y, + image_pixels[HashColorIndex(slot)]); + if (shapeimage) + XPutPixel(shapeimage, x, y, + shape_pixels[HashColorIndex(slot)]); +#else + SelectObject(*dc, image->bitmap); + SetPixel(*dc, x, y, + image_pixels[HashColorIndex(slot)]); + if (shapeimage) { + SelectObject(*dc, shapeimage->bitmap); + SetPixel(*dc, x, y, + shape_pixels[HashColorIndex(slot)]); + } +#endif + } + } + } else { + for (y = 0; y < height; y++) { + xpmNextString(data); + for (x = 0; x < width; x++) { + for (a = 0, s = buf; a < cpp; a++, s++) + *s = xpmGetC(data); + for (a = 0; a < ncolors; a++) + if (!strcmp(colorTable[a].string, buf)) + break; + if (a == ncolors) /* no color matches */ + return (XpmFileInvalid); +#ifndef FOR_MSW + XPutPixel(image, x, y, image_pixels[a]); + if (shapeimage) + XPutPixel(shapeimage, x, y, shape_pixels[a]); +#else + SelectObject(*dc, image->bitmap); + SetPixel(*dc, x, y, image_pixels[a]); + if (shapeimage) { + SelectObject(*dc, shapeimage->bitmap); + SetPixel(*dc, x, y, shape_pixels[a]); + } +#endif + } + } + } + } + break; + } + return (XpmSuccess); +} diff --git a/libXpm/src/data.c b/libXpm/src/data.c index 904e60b6b..347aa46a2 100644 --- a/libXpm/src/data.c +++ b/libXpm/src/data.c @@ -1,479 +1,479 @@ -/*
- * Copyright (C) 1989-95 GROUPE BULL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of GROUPE BULL shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from GROUPE BULL.
- */
-
-/*****************************************************************************\
-* data.c: *
-* *
-* XPM library *
-* IO utilities *
-* *
-* Developed by Arnaud Le Hors *
-\*****************************************************************************/
-
-/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
-
-#ifndef CXPMPROG
-#if 0
-/* Official version number */
-static char *RCS_Version = "$XpmVersion: 3.4k $";
-
-/* Internal version number */
-static char *RCS_Id = "Id: xpm.shar,v 3.71 1998/03/19 19:47:14 lehors Exp $";
-#endif
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "XpmI.h"
-#endif
-#include <ctype.h>
-
-#ifndef CXPMPROG
-#define Getc(data, file) getc(file)
-#define Ungetc(data, c, file) ungetc(c, file)
-#endif
-
-static int
-ParseComment(xpmData *data)
-{
- if (data->type == XPMBUFFER) {
- register char c;
- register unsigned int n = 0;
- unsigned int notend;
- char *s, *s2;
-
- s = data->Comment;
- *s = data->Bcmt[0];
-
- /* skip the string beginning comment */
- s2 = data->Bcmt;
- do {
- c = *data->cptr++;
- *++s = c;
- n++;
- s2++;
- } while (c == *s2 && *s2 != '\0' && c);
-
- if (*s2 != '\0') {
- /* this wasn't the beginning of a comment */
- data->cptr -= n;
- return 0;
- }
- /* store comment */
- data->Comment[0] = *s;
- s = data->Comment;
- notend = 1;
- n = 0;
- while (notend) {
- s2 = data->Ecmt;
- while (*s != *s2 && c) {
- c = *data->cptr++;
- if (n == XPMMAXCMTLEN - 1) { /* forget it */
- s = data->Comment;
- n = 0;
- }
- *++s = c;
- n++;
- }
- data->CommentLength = n;
- do {
- c = *data->cptr++;
- if (n == XPMMAXCMTLEN - 1) { /* forget it */
- s = data->Comment;
- n = 0;
- }
- *++s = c;
- n++;
- s2++;
- } while (c == *s2 && *s2 != '\0' && c);
- if (*s2 == '\0') {
- /* this is the end of the comment */
- notend = 0;
- data->cptr--;
- }
- }
- return 0;
- } else {
- FILE *file = data->stream.file;
- register int c;
- register unsigned int n = 0, a;
- unsigned int notend;
- char *s, *s2;
-
- s = data->Comment;
- *s = data->Bcmt[0];
-
- /* skip the string beginning comment */
- s2 = data->Bcmt;
- do {
- c = Getc(data, file);
- *++s = c;
- n++;
- s2++;
- } while (c == *s2 && *s2 != '\0' && c != EOF);
-
- if (*s2 != '\0') {
- /* this wasn't the beginning of a comment */
- /* put characters back in the order that we got them */
- for (a = n; a > 0; a--, s--)
- Ungetc(data, *s, file);
- return 0;
- }
- /* store comment */
- data->Comment[0] = *s;
- s = data->Comment;
- notend = 1;
- n = 0;
- while (notend) {
- s2 = data->Ecmt;
- while (*s != *s2 && c != EOF) {
- c = Getc(data, file);
- if (n == XPMMAXCMTLEN - 1) { /* forget it */
- s = data->Comment;
- n = 0;
- }
- *++s = c;
- n++;
- }
- data->CommentLength = n;
- do {
- c = Getc(data, file);
- if (n == XPMMAXCMTLEN - 1) { /* forget it */
- s = data->Comment;
- n = 0;
- }
- *++s = c;
- n++;
- s2++;
- } while (c == *s2 && *s2 != '\0' && c != EOF);
- if (*s2 == '\0') {
- /* this is the end of the comment */
- notend = 0;
- Ungetc(data, *s, file);
- }
- }
- return 0;
- }
-}
-
-/*
- * skip to the end of the current string and the beginning of the next one
- */
-int
-xpmNextString(xpmData *data)
-{
- if (!data->type)
- data->cptr = (data->stream.data)[++data->line];
- else if (data->type == XPMBUFFER) {
- register char c;
-
- /* get to the end of the current string */
- if (data->Eos)
- while ((c = *data->cptr++) && c != data->Eos);
-
- /*
- * then get to the beginning of the next string looking for possible
- * comment
- */
- if (data->Bos) {
- while ((c = *data->cptr++) && c != data->Bos)
- if (data->Bcmt && c == data->Bcmt[0])
- ParseComment(data);
- } else if (data->Bcmt) { /* XPM2 natural */
- while ((c = *data->cptr++) == data->Bcmt[0])
- ParseComment(data);
- data->cptr--;
- }
- } else {
- register int c;
- FILE *file = data->stream.file;
-
- /* get to the end of the current string */
- if (data->Eos)
- while ((c = Getc(data, file)) != data->Eos && c != EOF);
-
- /*
- * then get to the beginning of the next string looking for possible
- * comment
- */
- if (data->Bos) {
- while ((c = Getc(data, file)) != data->Bos && c != EOF)
- if (data->Bcmt && c == data->Bcmt[0])
- ParseComment(data);
-
- } else if (data->Bcmt) { /* XPM2 natural */
- while ((c = Getc(data, file)) == data->Bcmt[0])
- ParseComment(data);
- Ungetc(data, c, file);
- }
- }
- return 0;
-}
-
-
-/*
- * skip whitespace and return the following word
- */
-unsigned int
-xpmNextWord(
- xpmData *data,
- char *buf,
- unsigned int buflen)
-{
- register unsigned int n = 0;
- int c;
-
- if (!data->type || data->type == XPMBUFFER) {
- while (isspace(c = *data->cptr) && c != data->Eos)
- data->cptr++;
- do {
- c = *data->cptr++;
- *buf++ = c;
- n++;
- } while (!isspace(c) && c != data->Eos && n < buflen);
- n--;
- data->cptr--;
- } else {
- FILE *file = data->stream.file;
-
- while ((c = Getc(data, file)) != EOF && isspace(c) && c != data->Eos);
- while (!isspace(c) && c != data->Eos && c != EOF && n < buflen) {
- *buf++ = c;
- n++;
- c = Getc(data, file);
- }
- Ungetc(data, c, file);
- }
- return (n); /* this returns bytes read + 1 */
-}
-
-/*
- * skip whitespace and compute the following unsigned int,
- * returns 1 if one is found and 0 if not
- */
-int
-xpmNextUI(
- xpmData *data,
- unsigned int *ui_return)
-{
- char buf[BUFSIZ];
- int l;
-
- l = xpmNextWord(data, buf, BUFSIZ);
- return xpmatoui(buf, l, ui_return);
-}
-
-/*
- * return end of string - WARNING: malloc!
- */
-int
-xpmGetString(
- xpmData *data,
- char **sptr,
- unsigned int *l)
-{
- unsigned int i, n = 0;
- int c;
- char *p = NULL, *q, buf[BUFSIZ];
-
- if (!data->type || data->type == XPMBUFFER) {
- if (data->cptr) {
- char *start = data->cptr;
- while ((c = *data->cptr) && c != data->Eos)
- data->cptr++;
- n = data->cptr - start + 1;
- p = (char *) XpmMalloc(n);
- if (!p)
- return (XpmNoMemory);
- strncpy(p, start, n);
- if (data->type) /* XPMBUFFER */
- p[n - 1] = '\0';
- }
- } else {
- FILE *file = data->stream.file;
-
- if ((c = Getc(data, file)) == EOF)
- return (XpmFileInvalid);
-
- i = 0;
- q = buf;
- p = (char *) XpmMalloc(1);
- while (c != data->Eos && c != EOF) {
- if (i == BUFSIZ) {
- /* get to the end of the buffer */
- /* malloc needed memory */
- q = (char *) XpmRealloc(p, n + i);
- if (!q) {
- XpmFree(p);
- return (XpmNoMemory);
- }
- p = q;
- q += n;
- /* and copy what we already have */
- strncpy(q, buf, i);
- n += i;
- i = 0;
- q = buf;
- }
- *q++ = c;
- i++;
- c = Getc(data, file);
- }
- if (c == EOF) {
- XpmFree(p);
- return (XpmFileInvalid);
- }
- if (n + i != 0) {
- /* malloc needed memory */
- q = (char *) XpmRealloc(p, n + i + 1);
- if (!q) {
- XpmFree(p);
- return (XpmNoMemory);
- }
- p = q;
- q += n;
- /* and copy the buffer */
- strncpy(q, buf, i);
- n += i;
- p[n++] = '\0';
- } else {
- *p = '\0';
- n = 1;
- }
- Ungetc(data, c, file);
- }
- *sptr = p;
- *l = n;
- return (XpmSuccess);
-}
-
-/*
- * get the current comment line
- */
-int
-xpmGetCmt(
- xpmData *data,
- char **cmt)
-{
- if (!data->type)
- *cmt = NULL;
- else if (data->CommentLength != 0 && data->CommentLength < UINT_MAX - 1) {
- if( (*cmt = (char *) XpmMalloc(data->CommentLength + 1)) == NULL)
- return XpmNoMemory;
- strncpy(*cmt, data->Comment, data->CommentLength);
- (*cmt)[data->CommentLength] = '\0';
- data->CommentLength = 0;
- } else
- *cmt = NULL;
- return 0;
-}
-
-xpmDataType xpmDataTypes[] =
-{
- {"", "!", "\n", '\0', '\n', "", "", "", ""}, /* Natural type */
- {"C", "/*", "*/", '"', '"', ",\n", "static char *", "[] = {\n", "};\n"},
- {"Lisp", ";", "\n", '"', '"', "\n", "(setq ", " '(\n", "))\n"},
- {NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL}
-};
-
-/*
- * parse xpm header
- */
-int
-xpmParseHeader(xpmData *data)
-{
- char buf[BUFSIZ+1] = {0};
- int l, n = 0;
-
- if (data->type) {
- data->Bos = '\0';
- data->Eos = '\n';
- data->Bcmt = data->Ecmt = NULL;
- l = xpmNextWord(data, buf, BUFSIZ);
- if (l == 7 && !strncmp("#define", buf, 7)) {
- /* this maybe an XPM 1 file */
- char *ptr;
-
- l = xpmNextWord(data, buf, BUFSIZ);
- if (!l)
- return (XpmFileInvalid);
- buf[l] = '\0';
- ptr = strrchr(buf, '_');
- if (!ptr || strncmp("_format", ptr, l - (ptr - buf)))
- return XpmFileInvalid;
- /* this is definitely an XPM 1 file */
- data->format = 1;
- n = 1; /* handle XPM1 as mainly XPM2 C */
- } else {
-
- /*
- * skip the first word, get the second one, and see if this is
- * XPM 2 or 3
- */
- l = xpmNextWord(data, buf, BUFSIZ);
- if ((l == 3 && !strncmp("XPM", buf, 3)) ||
- (l == 4 && !strncmp("XPM2", buf, 4))) {
- if (l == 3)
- n = 1; /* handle XPM as XPM2 C */
- else {
- /* get the type key word */
- l = xpmNextWord(data, buf, BUFSIZ);
-
- /*
- * get infos about this type
- */
- while (xpmDataTypes[n].type
- && strncmp(xpmDataTypes[n].type, buf, l))
- n++;
- }
- data->format = 0;
- } else
- /* nope this is not an XPM file */
- return XpmFileInvalid;
- }
- if (xpmDataTypes[n].type) {
- if (n == 0) { /* natural type */
- data->Bcmt = xpmDataTypes[n].Bcmt;
- data->Ecmt = xpmDataTypes[n].Ecmt;
- xpmNextString(data); /* skip the end of the headerline */
- data->Bos = xpmDataTypes[n].Bos;
- data->Eos = xpmDataTypes[n].Eos;
- } else {
- data->Bcmt = xpmDataTypes[n].Bcmt;
- data->Ecmt = xpmDataTypes[n].Ecmt;
- if (!data->format) { /* XPM 2 or 3 */
- data->Bos = xpmDataTypes[n].Bos;
- data->Eos = '\0';
- /* get to the beginning of the first string */
- xpmNextString(data);
- data->Eos = xpmDataTypes[n].Eos;
- } else /* XPM 1 skip end of line */
- xpmNextString(data);
- }
- } else
- /* we don't know about that type of XPM file... */
- return XpmFileInvalid;
- }
- return XpmSuccess;
-}
+/* + * Copyright (C) 1989-95 GROUPE BULL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of GROUPE BULL shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from GROUPE BULL. + */ + +/*****************************************************************************\ +* data.c: * +* * +* XPM library * +* IO utilities * +* * +* Developed by Arnaud Le Hors * +\*****************************************************************************/ + +/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ + +#ifndef CXPMPROG +#if 0 +/* Official version number */ +static char *RCS_Version = "$XpmVersion: 3.4k $"; + +/* Internal version number */ +static char *RCS_Id = "Id: xpm.shar,v 3.71 1998/03/19 19:47:14 lehors Exp $"; +#endif +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "XpmI.h" +#endif +#include <ctype.h> + +#ifndef CXPMPROG +#define Getc(data, file) getc(file) +#define Ungetc(data, c, file) ungetc(c, file) +#endif + +static int +ParseComment(xpmData *data) +{ + if (data->type == XPMBUFFER) { + register char c; + register unsigned int n = 0; + unsigned int notend; + char *s, *s2; + + s = data->Comment; + *s = data->Bcmt[0]; + + /* skip the string beginning comment */ + s2 = data->Bcmt; + do { + c = *data->cptr++; + *++s = c; + n++; + s2++; + } while (c == *s2 && *s2 != '\0' && c); + + if (*s2 != '\0') { + /* this wasn't the beginning of a comment */ + data->cptr -= n; + return 0; + } + /* store comment */ + data->Comment[0] = *s; + s = data->Comment; + notend = 1; + n = 0; + while (notend) { + s2 = data->Ecmt; + while (*s != *s2 && c) { + c = *data->cptr++; + if (n == XPMMAXCMTLEN - 1) { /* forget it */ + s = data->Comment; + n = 0; + } + *++s = c; + n++; + } + data->CommentLength = n; + do { + c = *data->cptr++; + if (n == XPMMAXCMTLEN - 1) { /* forget it */ + s = data->Comment; + n = 0; + } + *++s = c; + n++; + s2++; + } while (c == *s2 && *s2 != '\0' && c); + if (*s2 == '\0') { + /* this is the end of the comment */ + notend = 0; + data->cptr--; + } + } + return 0; + } else { + FILE *file = data->stream.file; + register int c; + register unsigned int n = 0, a; + unsigned int notend; + char *s, *s2; + + s = data->Comment; + *s = data->Bcmt[0]; + + /* skip the string beginning comment */ + s2 = data->Bcmt; + do { + c = Getc(data, file); + *++s = c; + n++; + s2++; + } while (c == *s2 && *s2 != '\0' && c != EOF); + + if (*s2 != '\0') { + /* this wasn't the beginning of a comment */ + /* put characters back in the order that we got them */ + for (a = n; a > 0; a--, s--) + Ungetc(data, *s, file); + return 0; + } + /* store comment */ + data->Comment[0] = *s; + s = data->Comment; + notend = 1; + n = 0; + while (notend) { + s2 = data->Ecmt; + while (*s != *s2 && c != EOF) { + c = Getc(data, file); + if (n == XPMMAXCMTLEN - 1) { /* forget it */ + s = data->Comment; + n = 0; + } + *++s = c; + n++; + } + data->CommentLength = n; + do { + c = Getc(data, file); + if (n == XPMMAXCMTLEN - 1) { /* forget it */ + s = data->Comment; + n = 0; + } + *++s = c; + n++; + s2++; + } while (c == *s2 && *s2 != '\0' && c != EOF); + if (*s2 == '\0') { + /* this is the end of the comment */ + notend = 0; + Ungetc(data, *s, file); + } + } + return 0; + } +} + +/* + * skip to the end of the current string and the beginning of the next one + */ +int +xpmNextString(xpmData *data) +{ + if (!data->type) + data->cptr = (data->stream.data)[++data->line]; + else if (data->type == XPMBUFFER) { + register char c; + + /* get to the end of the current string */ + if (data->Eos) + while ((c = *data->cptr++) && c != data->Eos); + + /* + * then get to the beginning of the next string looking for possible + * comment + */ + if (data->Bos) { + while ((c = *data->cptr++) && c != data->Bos) + if (data->Bcmt && c == data->Bcmt[0]) + ParseComment(data); + } else if (data->Bcmt) { /* XPM2 natural */ + while ((c = *data->cptr++) == data->Bcmt[0]) + ParseComment(data); + data->cptr--; + } + } else { + register int c; + FILE *file = data->stream.file; + + /* get to the end of the current string */ + if (data->Eos) + while ((c = Getc(data, file)) != data->Eos && c != EOF); + + /* + * then get to the beginning of the next string looking for possible + * comment + */ + if (data->Bos) { + while ((c = Getc(data, file)) != data->Bos && c != EOF) + if (data->Bcmt && c == data->Bcmt[0]) + ParseComment(data); + + } else if (data->Bcmt) { /* XPM2 natural */ + while ((c = Getc(data, file)) == data->Bcmt[0]) + ParseComment(data); + Ungetc(data, c, file); + } + } + return 0; +} + + +/* + * skip whitespace and return the following word + */ +unsigned int +xpmNextWord( + xpmData *data, + char *buf, + unsigned int buflen) +{ + register unsigned int n = 0; + int c; + + if (!data->type || data->type == XPMBUFFER) { + while (isspace(c = *data->cptr) && c != data->Eos) + data->cptr++; + do { + c = *data->cptr++; + *buf++ = c; + n++; + } while (!isspace(c) && c != data->Eos && n < buflen); + n--; + data->cptr--; + } else { + FILE *file = data->stream.file; + + while ((c = Getc(data, file)) != EOF && isspace(c) && c != data->Eos); + while (!isspace(c) && c != data->Eos && c != EOF && n < buflen) { + *buf++ = c; + n++; + c = Getc(data, file); + } + Ungetc(data, c, file); + } + return (n); /* this returns bytes read + 1 */ +} + +/* + * skip whitespace and compute the following unsigned int, + * returns 1 if one is found and 0 if not + */ +int +xpmNextUI( + xpmData *data, + unsigned int *ui_return) +{ + char buf[BUFSIZ]; + int l; + + l = xpmNextWord(data, buf, BUFSIZ); + return xpmatoui(buf, l, ui_return); +} + +/* + * return end of string - WARNING: malloc! + */ +int +xpmGetString( + xpmData *data, + char **sptr, + unsigned int *l) +{ + unsigned int i, n = 0; + int c; + char *p = NULL, *q, buf[BUFSIZ]; + + if (!data->type || data->type == XPMBUFFER) { + if (data->cptr) { + char *start = data->cptr; + while ((c = *data->cptr) && c != data->Eos) + data->cptr++; + n = data->cptr - start + 1; + p = (char *) XpmMalloc(n); + if (!p) + return (XpmNoMemory); + strncpy(p, start, n); + if (data->type) /* XPMBUFFER */ + p[n - 1] = '\0'; + } + } else { + FILE *file = data->stream.file; + + if ((c = Getc(data, file)) == EOF) + return (XpmFileInvalid); + + i = 0; + q = buf; + p = (char *) XpmMalloc(1); + while (c != data->Eos && c != EOF) { + if (i == BUFSIZ) { + /* get to the end of the buffer */ + /* malloc needed memory */ + q = (char *) XpmRealloc(p, n + i); + if (!q) { + XpmFree(p); + return (XpmNoMemory); + } + p = q; + q += n; + /* and copy what we already have */ + strncpy(q, buf, i); + n += i; + i = 0; + q = buf; + } + *q++ = c; + i++; + c = Getc(data, file); + } + if (c == EOF) { + XpmFree(p); + return (XpmFileInvalid); + } + if (n + i != 0) { + /* malloc needed memory */ + q = (char *) XpmRealloc(p, n + i + 1); + if (!q) { + XpmFree(p); + return (XpmNoMemory); + } + p = q; + q += n; + /* and copy the buffer */ + strncpy(q, buf, i); + n += i; + p[n++] = '\0'; + } else { + *p = '\0'; + n = 1; + } + Ungetc(data, c, file); + } + *sptr = p; + *l = n; + return (XpmSuccess); +} + +/* + * get the current comment line + */ +int +xpmGetCmt( + xpmData *data, + char **cmt) +{ + if (!data->type) + *cmt = NULL; + else if (data->CommentLength != 0 && data->CommentLength < UINT_MAX - 1) { + if( (*cmt = (char *) XpmMalloc(data->CommentLength + 1)) == NULL) + return XpmNoMemory; + strncpy(*cmt, data->Comment, data->CommentLength); + (*cmt)[data->CommentLength] = '\0'; + data->CommentLength = 0; + } else + *cmt = NULL; + return 0; +} + +xpmDataType xpmDataTypes[] = +{ + {"", "!", "\n", '\0', '\n', "", "", "", ""}, /* Natural type */ + {"C", "/*", "*/", '"', '"', ",\n", "static char *", "[] = {\n", "};\n"}, + {"Lisp", ";", "\n", '"', '"', "\n", "(setq ", " '(\n", "))\n"}, + {NULL, NULL, NULL, 0, 0, NULL, NULL, NULL, NULL} +}; + +/* + * parse xpm header + */ +int +xpmParseHeader(xpmData *data) +{ + char buf[BUFSIZ+1] = {0}; + int l, n = 0; + + if (data->type) { + data->Bos = '\0'; + data->Eos = '\n'; + data->Bcmt = data->Ecmt = NULL; + l = xpmNextWord(data, buf, BUFSIZ); + if (l == 7 && !strncmp("#define", buf, 7)) { + /* this maybe an XPM 1 file */ + char *ptr; + + l = xpmNextWord(data, buf, BUFSIZ); + if (!l) + return (XpmFileInvalid); + buf[l] = '\0'; + ptr = strrchr(buf, '_'); + if (!ptr || strncmp("_format", ptr, l - (ptr - buf))) + return XpmFileInvalid; + /* this is definitely an XPM 1 file */ + data->format = 1; + n = 1; /* handle XPM1 as mainly XPM2 C */ + } else { + + /* + * skip the first word, get the second one, and see if this is + * XPM 2 or 3 + */ + l = xpmNextWord(data, buf, BUFSIZ); + if ((l == 3 && !strncmp("XPM", buf, 3)) || + (l == 4 && !strncmp("XPM2", buf, 4))) { + if (l == 3) + n = 1; /* handle XPM as XPM2 C */ + else { + /* get the type key word */ + l = xpmNextWord(data, buf, BUFSIZ); + + /* + * get infos about this type + */ + while (xpmDataTypes[n].type + && strncmp(xpmDataTypes[n].type, buf, l)) + n++; + } + data->format = 0; + } else + /* nope this is not an XPM file */ + return XpmFileInvalid; + } + if (xpmDataTypes[n].type) { + if (n == 0) { /* natural type */ + data->Bcmt = xpmDataTypes[n].Bcmt; + data->Ecmt = xpmDataTypes[n].Ecmt; + xpmNextString(data); /* skip the end of the headerline */ + data->Bos = xpmDataTypes[n].Bos; + data->Eos = xpmDataTypes[n].Eos; + } else { + data->Bcmt = xpmDataTypes[n].Bcmt; + data->Ecmt = xpmDataTypes[n].Ecmt; + if (!data->format) { /* XPM 2 or 3 */ + data->Bos = xpmDataTypes[n].Bos; + data->Eos = '\0'; + /* get to the beginning of the first string */ + xpmNextString(data); + data->Eos = xpmDataTypes[n].Eos; + } else /* XPM 1 skip end of line */ + xpmNextString(data); + } + } else + /* we don't know about that type of XPM file... */ + return XpmFileInvalid; + } + return XpmSuccess; +} diff --git a/libXpm/src/parse.c b/libXpm/src/parse.c index 1d3ef5f9d..5c7915f78 100644 --- a/libXpm/src/parse.c +++ b/libXpm/src/parse.c @@ -1,804 +1,804 @@ -/*
- * Copyright (C) 1989-95 GROUPE BULL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of GROUPE BULL shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from GROUPE BULL.
- */
-
-/*****************************************************************************\
-* parse.c: *
-* *
-* XPM library *
-* Parse an XPM file or array and store the found informations *
-* in the given XpmImage structure. *
-* *
-* Developed by Arnaud Le Hors *
-\*****************************************************************************/
-
-/*
- * The code related to FOR_MSW has been added by
- * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
- */
-
-/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "XpmI.h"
-#include <ctype.h>
-#include <string.h>
-
-#if defined(HAS_STRLCAT) || defined(HAVE_STRLCAT)
-# define STRLCAT(dst, src, dstsize) do { \
- if (strlcat(dst, src, dstsize) >= (dstsize)) \
- return (XpmFileInvalid); } while(0)
-# define STRLCPY(dst, src, dstsize) do { \
- if (strlcpy(dst, src, dstsize) >= (dstsize)) \
- return (XpmFileInvalid); } while(0)
-#else
-# define STRLCAT(dst, src, dstsize) do { \
- if ((strlen(dst) + strlen(src)) < (dstsize)) \
- strcat(dst, src); \
- else return (XpmFileInvalid); } while(0)
-# define STRLCPY(dst, src, dstsize) do { \
- if (strlen(src) < (dstsize)) \
- strcpy(dst, src); \
- else return (XpmFileInvalid); } while(0)
-#endif
-
-LFUNC(ParsePixels, int, (xpmData *data, unsigned int width,
- unsigned int height, unsigned int ncolors,
- unsigned int cpp, XpmColor *colorTable,
- xpmHashTable *hashtable, unsigned int **pixels));
-
-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 */
-};
-
-int
-xpmParseValues(
- 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)
-{
- unsigned int l;
- char buf[BUFSIZ + 1];
-
- if (!data->format) { /* XPM 2 or 3 */
-
- /*
- * 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, BUFSIZ);
- if (l) {
- *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6));
- if (*extensions)
- *hotspot = (xpmNextUI(data, x_hotspot)
- && xpmNextUI(data, y_hotspot));
- else {
- *hotspot = (xpmatoui(buf, l, x_hotspot)
- && xpmNextUI(data, y_hotspot));
- l = xpmNextWord(data, buf, BUFSIZ);
- *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6));
- }
- }
- } else {
-
- /*
- * XPM 1 file read values: width, height, ncolors, chars_per_pixel
- */
- int i;
- char *ptr;
- Bool got_one, saw_width = False, saw_height = False;
- Bool saw_ncolors = False, saw_chars_per_pixel = False;
-
- for (i = 0; i < 4; i++) {
- l = xpmNextWord(data, buf, BUFSIZ);
- if (l != 7 || strncmp("#define", buf, 7))
- return (XpmFileInvalid);
- l = xpmNextWord(data, buf, BUFSIZ);
- if (!l)
- return (XpmFileInvalid);
- buf[l] = '\0';
- ptr = buf;
- got_one = False;
- while (!got_one) {
- ptr = strchr(ptr, '_');
- if (!ptr)
- return (XpmFileInvalid);
- switch (l - (ptr - buf)) {
- case 6:
- if (saw_width || strncmp("_width", ptr, 6)
- || !xpmNextUI(data, width))
- return (XpmFileInvalid);
- else
- saw_width = True;
- got_one = True;
- break;
- case 7:
- if (saw_height || strncmp("_height", ptr, 7)
- || !xpmNextUI(data, height))
- return (XpmFileInvalid);
- else
- saw_height = True;
- got_one = True;
- break;
- case 8:
- if (saw_ncolors || strncmp("_ncolors", ptr, 8)
- || !xpmNextUI(data, ncolors))
- return (XpmFileInvalid);
- else
- saw_ncolors = True;
- got_one = True;
- break;
- case 16:
- if (saw_chars_per_pixel
- || strncmp("_chars_per_pixel", ptr, 16)
- || !xpmNextUI(data, cpp))
- return (XpmFileInvalid);
- else
- saw_chars_per_pixel = True;
- got_one = True;
- break;
- default:
- ptr++;
- }
- }
- /* skip the end of line */
- xpmNextString(data);
- }
- if (!saw_width || !saw_height || !saw_ncolors || !saw_chars_per_pixel)
- return (XpmFileInvalid);
-
- *hotspot = 0;
- *extensions = 0;
- }
- return (XpmSuccess);
-}
-
-int
-xpmParseColors(
- xpmData *data,
- unsigned int ncolors,
- unsigned int cpp,
- XpmColor **colorTablePtr,
- xpmHashTable *hashtable)
-{
- unsigned int key = 0, l, a, b, len;
- unsigned int curkey; /* current color key */
- unsigned int lastwaskey; /* key read */
- char buf[BUFSIZ+1];
- char curbuf[BUFSIZ]; /* current buffer */
- char **sptr, *s;
- XpmColor *color;
- XpmColor *colorTable;
- char **defaults;
- int ErrorStatus;
-
- if (ncolors >= UINT_MAX / sizeof(XpmColor))
- return (XpmNoMemory);
- colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor));
- if (!colorTable)
- return (XpmNoMemory);
-
- if (!data->format) { /* XPM 2 or 3 */
- for (a = 0, color = colorTable; a < ncolors; a++, color++) {
- xpmNextString(data); /* skip the line */
-
- /*
- * read pixel value
- */
- if (cpp >= UINT_MAX - 1) {
- xpmFreeColorTable(colorTable, ncolors);
- return (XpmNoMemory);
- }
- color->string = (char *) XpmMalloc(cpp + 1);
- if (!color->string) {
- xpmFreeColorTable(colorTable, ncolors);
- return (XpmNoMemory);
- }
- for (b = 0, s = color->string; b < cpp; b++, s++)
- *s = xpmGetC(data);
- *s = '\0';
-
- /*
- * store the string in the hashtable with its color index number
- */
- if (USE_HASHTABLE) {
- ErrorStatus =
- xpmHashIntern(hashtable, color->string, HashAtomData(a));
- if (ErrorStatus != XpmSuccess) {
- xpmFreeColorTable(colorTable, ncolors);
- return (ErrorStatus);
- }
- }
-
- /*
- * read color keys and values
- */
- defaults = (char **) color;
- curkey = 0;
- lastwaskey = 0;
- *curbuf = '\0'; /* init curbuf */
- while ((l = xpmNextWord(data, buf, BUFSIZ))) {
- 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 */
- len = strlen(curbuf) + 1;
- s = (char *) XpmMalloc(len);
- if (!s) {
- xpmFreeColorTable(colorTable, ncolors);
- return (XpmNoMemory);
- }
- defaults[curkey] = s;
- memcpy(s, curbuf, len);
- }
- 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)
- STRLCAT(curbuf, " ", sizeof(curbuf));/* append space */
- buf[l] = '\0';
- STRLCAT(curbuf, buf, sizeof(curbuf)); /* append buf */
- lastwaskey = 0;
- }
- }
- if (!curkey) { /* key without value */
- xpmFreeColorTable(colorTable, ncolors);
- return (XpmFileInvalid);
- }
- len = strlen(curbuf) + 1; /* integer overflow just theoretically possible */
- s = defaults[curkey] = (char *) XpmMalloc(len);
- if (!s) {
- xpmFreeColorTable(colorTable, ncolors);
- return (XpmNoMemory);
- }
- memcpy(s, curbuf, len);
- }
- } else { /* XPM 1 */
- /* get to the beginning of the first string */
- data->Bos = '"';
- data->Eos = '\0';
- xpmNextString(data);
- data->Eos = '"';
- for (a = 0, color = colorTable; a < ncolors; a++, color++) {
-
- /*
- * read pixel value
- */
- if (cpp >= UINT_MAX - 1) {
- xpmFreeColorTable(colorTable, ncolors);
- return (XpmNoMemory);
- }
- color->string = (char *) XpmMalloc(cpp + 1);
- if (!color->string) {
- xpmFreeColorTable(colorTable, ncolors);
- return (XpmNoMemory);
- }
- for (b = 0, s = color->string; b < cpp; b++, s++)
- *s = xpmGetC(data);
- *s = '\0';
-
- /*
- * store the string in the hashtable with its color index number
- */
- if (USE_HASHTABLE) {
- ErrorStatus =
- xpmHashIntern(hashtable, color->string, HashAtomData(a));
- if (ErrorStatus != XpmSuccess) {
- xpmFreeColorTable(colorTable, ncolors);
- return (ErrorStatus);
- }
- }
-
- /*
- * read color values
- */
- xpmNextString(data); /* get to the next string */
- *curbuf = '\0'; /* init curbuf */
- while ((l = xpmNextWord(data, buf, BUFSIZ))) {
- if (*curbuf != '\0')
- STRLCAT(curbuf, " ", sizeof(curbuf));/* append space */
- buf[l] = '\0';
- STRLCAT(curbuf, buf, sizeof(curbuf)); /* append buf */
- }
- len = strlen(curbuf) + 1;
- s = (char *) XpmMalloc(len);
- if (!s) {
- xpmFreeColorTable(colorTable, ncolors);
- return (XpmNoMemory);
- }
- memcpy(s, curbuf, len);
- color->c_color = s;
- *curbuf = '\0'; /* reset curbuf */
- if (a < ncolors - 1) /* can we trust ncolors -> leave data's bounds */
- xpmNextString(data); /* get to the next string */
- }
- }
- *colorTablePtr = colorTable;
- return (XpmSuccess);
-}
-
-static int
-ParsePixels(
- xpmData *data,
- unsigned int width,
- unsigned int height,
- unsigned int ncolors,
- unsigned int cpp,
- XpmColor *colorTable,
- xpmHashTable *hashtable,
- unsigned int **pixels)
-{
- unsigned int *iptr, *iptr2 = NULL; /* found by Egbert Eich */
- unsigned int a, x, y;
-
- if ((height > 0 && width >= UINT_MAX / height) ||
- width * height >= UINT_MAX / sizeof(unsigned int))
- return XpmNoMemory;
-#ifndef FOR_MSW
- iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height);
-#else
-
- /*
- * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!!
- * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary
- */
- iptr2 = (unsigned int *)
- XpmMalloc((long) sizeof(unsigned int) * (long) width * (long) height);
-#endif
- if (!iptr2)
- return (XpmNoMemory);
-
- iptr = iptr2;
-
- switch (cpp) {
-
- case (1): /* Optimize for single character
- * colors */
- {
- unsigned short colidx[256];
-
- if (ncolors > 256) {
- XpmFree(iptr2); /* found by Egbert Eich */
- return (XpmFileInvalid);
- }
-
- bzero((char *)colidx, 256 * sizeof(short));
- for (a = 0; a < ncolors; a++)
- colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
-
- for (y = 0; y < height; y++) {
- xpmNextString(data);
- for (x = 0; x < width; x++, iptr++) {
- int c = xpmGetC(data);
-
- if (c > 0 && c < 256 && colidx[c] != 0)
- *iptr = colidx[c] - 1;
- else {
- XpmFree(iptr2);
- return (XpmFileInvalid);
- }
- }
- }
- }
- break;
-
- case (2): /* Optimize for double character
- * colors */
- {
-
-/* free all allocated pointers at all exits */
-#define FREE_CIDX \
-do \
-{ \
- int f; for (f = 0; f < 256; f++) \
- if (cidx[f]) XpmFree(cidx[f]); \
-} while(0)
-
- /* array of pointers malloced by need */
- unsigned short *cidx[256];
- unsigned int char1;
-
- bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
- for (a = 0; a < ncolors; a++) {
- char1 = (unsigned char) colorTable[a].string[0];
- if (cidx[char1] == NULL) { /* get new memory */
- cidx[char1] = (unsigned short *)
- XpmCalloc(256, sizeof(unsigned short));
- if (cidx[char1] == NULL) { /* new block failed */
- FREE_CIDX;
- XpmFree(iptr2);
- return (XpmNoMemory);
- }
- }
- cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
- }
-
- for (y = 0; y < height; y++) {
- xpmNextString(data);
- for (x = 0; x < width; x++, iptr++) {
- int cc1 = xpmGetC(data);
- if (cc1 > 0 && cc1 < 256) {
- int cc2 = xpmGetC(data);
- if (cc2 > 0 && cc2 < 256 &&
- cidx[cc1] && cidx[cc1][cc2] != 0)
- *iptr = cidx[cc1][cc2] - 1;
- else {
- FREE_CIDX;
- XpmFree(iptr2);
- return (XpmFileInvalid);
- }
- } else {
- FREE_CIDX;
- XpmFree(iptr2);
- return (XpmFileInvalid);
- }
- }
- }
- FREE_CIDX;
- }
- break;
-
- default: /* Non-optimized case of long color
- * names */
- {
- char *s;
- char buf[BUFSIZ];
-
- if (cpp >= sizeof(buf)) {
- XpmFree(iptr2); /* found by Egbert Eich */
- return (XpmFileInvalid);
- }
-
- buf[cpp] = '\0';
- 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); /* int assigned to char, not a problem here */
- slot = xpmHashSlot(hashtable, buf);
- if (!*slot) { /* no color matches */
- XpmFree(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); /* int assigned to char, not a problem here */
- for (a = 0; a < ncolors; a++)
- if (!strcmp(colorTable[a].string, buf))
- break;
- if (a == ncolors) { /* no color matches */
- XpmFree(iptr2);
- return (XpmFileInvalid);
- }
- *iptr = a;
- }
- }
- }
- }
- break;
- }
- *pixels = iptr2;
- return (XpmSuccess);
-}
-
-int
-xpmParseExtensions(
- 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 *) XpmMalloc(sizeof(XpmExtension));
- /* get the whole string */
- status = xpmGetString(data, &string, &l);
- if (status != XpmSuccess) {
- XpmFree(exts);
- return (status);
- }
- /* look for the key word XPMEXT, skip lines before this */
- while ((notstart = strncmp("XPMEXT", string, 6))
- && (notend = strncmp("XPMENDEXT", string, 9))) {
- XpmFree(string);
- xpmNextString(data);
- status = xpmGetString(data, &string, &l);
- if (status != XpmSuccess) {
- XpmFree(exts);
- return (status);
- }
- }
- if (!notstart)
- notend = strncmp("XPMENDEXT", string, 9);
- while (!notstart && notend) {
- /* there starts an extension */
- ext = (XpmExtension *)
- XpmRealloc(exts, (num + 1) * sizeof(XpmExtension)); /* can the loop be forced to iterate often enough to make "(num + 1) * sizeof(XpmExtension)" wrapping? */
- if (!ext) {
- XpmFree(string);
- XpmFreeExtensions(exts, num);
- 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 *) XpmMalloc(l - a - 6);
- if (!ext->name) {
- XpmFree(string);
- ext->lines = NULL;
- ext->nlines = 0;
- XpmFreeExtensions(exts, num + 1);
- return (XpmNoMemory);
- }
- strncpy(ext->name, s + a, l - a - 6);
- XpmFree(string);
- /* now store the related lines */
- xpmNextString(data);
- status = xpmGetString(data, &string, &l);
- if (status != XpmSuccess) {
- ext->lines = NULL;
- ext->nlines = 0;
- XpmFreeExtensions(exts, num + 1);
- return (status);
- }
- ext->lines = (char **) XpmMalloc(sizeof(char *));
- nlines = 0;
- while ((notstart = strncmp("XPMEXT", string, 6))
- && (notend = strncmp("XPMENDEXT", string, 9))) {
- sp = (char **)
- XpmRealloc(ext->lines, (nlines + 1) * sizeof(char *)); /* can we iterate enough for a wrapping? */
- if (!sp) {
- XpmFree(string);
- ext->nlines = nlines;
- XpmFreeExtensions(exts, num + 1);
- return (XpmNoMemory);
- }
- ext->lines = sp;
- ext->lines[nlines] = string;
- nlines++;
- xpmNextString(data);
- status = xpmGetString(data, &string, &l);
- if (status != XpmSuccess) {
- ext->nlines = nlines;
- XpmFreeExtensions(exts, num + 1);
- return (status);
- }
- }
- if (!nlines) {
- XpmFree(ext->lines);
- ext->lines = NULL;
- }
- ext->nlines = nlines;
- num++;
- }
- if (!num) {
- XpmFree(string);
- XpmFree(exts);
- exts = NULL;
- } else if (!notend)
- XpmFree(string);
- *nextensions = num;
- *extensions = exts;
- return (XpmSuccess);
-}
-
-
-/* function call in case of error */
-#undef RETURN
-#define RETURN(status) \
-do { \
- goto error; \
-} while(0)
-
-/*
- * This function parses an Xpm file or data and store the found informations
- * in an an XpmImage structure which is returned.
- */
-int
-xpmParseData(
- xpmData *data,
- XpmImage *image,
- XpmInfo *info)
-{
- /* variables to return */
- unsigned int width, height, ncolors, cpp;
- unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
- XpmColor *colorTable = NULL;
- unsigned int *pixelindex = NULL;
- char *hints_cmt = NULL;
- char *colors_cmt = NULL;
- char *pixels_cmt = NULL;
-
- unsigned int cmts;
- int ErrorStatus;
- xpmHashTable hashtable;
-
- cmts = info && (info->valuemask & XpmReturnComments);
-
- /*
- * parse the header
- */
- ErrorStatus = xpmParseHeader(data);
- if (ErrorStatus != XpmSuccess)
- return (ErrorStatus);
-
- /*
- * read values
- */
- ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
- &x_hotspot, &y_hotspot, &hotspot,
- &extensions);
- if (ErrorStatus != XpmSuccess)
- return (ErrorStatus);
-
- /*
- * store the hints comment line
- */
- if (cmts)
- xpmGetCmt(data, &hints_cmt);
-
- /*
- * init the hashtable
- */
- if (USE_HASHTABLE) {
- ErrorStatus = xpmHashTableInit(&hashtable);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
- }
-
- /*
- * read colors
- */
- ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
- if (ErrorStatus != XpmSuccess) {
- if (USE_HASHTABLE)
- xpmHashTableFree(&hashtable);
- RETURN(ErrorStatus);
- }
-
- /*
- * store the colors comment line
- */
- if (cmts)
- 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 (cmts)
- xpmGetCmt(data, &pixels_cmt);
-
- /*
- * parse extensions
- */
- if (info && (info->valuemask & XpmReturnExtensions)) {
- if (extensions) {
- ErrorStatus = xpmParseExtensions(data, &info->extensions,
- &info->nextensions);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
- } else {
- info->extensions = NULL;
- info->nextensions = 0;
- }
- }
-
- /*
- * store found informations in the XpmImage structure
- */
- image->width = width;
- image->height = height;
- image->cpp = cpp;
- image->ncolors = ncolors;
- image->colorTable = colorTable;
- image->data = pixelindex;
-
- if (info) {
- if (cmts) {
- info->hints_cmt = hints_cmt;
- info->colors_cmt = colors_cmt;
- info->pixels_cmt = pixels_cmt;
- }
- if (hotspot) {
- info->x_hotspot = x_hotspot;
- info->y_hotspot = y_hotspot;
- info->valuemask |= XpmHotspot;
- }
- }
- return (XpmSuccess);
-
-/* exit point in case of error, free only locally allocated variables */
-error:
- if (colorTable)
- xpmFreeColorTable(colorTable, ncolors);
- if (pixelindex)
- XpmFree(pixelindex);
- if (hints_cmt)
- XpmFree(hints_cmt);
- if (colors_cmt)
- XpmFree(colors_cmt);
- if (pixels_cmt)
- XpmFree(pixels_cmt);
-
- return(ErrorStatus);
-}
+/* + * Copyright (C) 1989-95 GROUPE BULL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of GROUPE BULL shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from GROUPE BULL. + */ + +/*****************************************************************************\ +* parse.c: * +* * +* XPM library * +* Parse an XPM file or array and store the found informations * +* in the given XpmImage structure. * +* * +* Developed by Arnaud Le Hors * +\*****************************************************************************/ + +/* + * The code related to FOR_MSW has been added by + * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94 + */ + +/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "XpmI.h" +#include <ctype.h> +#include <string.h> + +#if defined(HAS_STRLCAT) || defined(HAVE_STRLCAT) +# define STRLCAT(dst, src, dstsize) do { \ + if (strlcat(dst, src, dstsize) >= (dstsize)) \ + return (XpmFileInvalid); } while(0) +# define STRLCPY(dst, src, dstsize) do { \ + if (strlcpy(dst, src, dstsize) >= (dstsize)) \ + return (XpmFileInvalid); } while(0) +#else +# define STRLCAT(dst, src, dstsize) do { \ + if ((strlen(dst) + strlen(src)) < (dstsize)) \ + strcat(dst, src); \ + else return (XpmFileInvalid); } while(0) +# define STRLCPY(dst, src, dstsize) do { \ + if (strlen(src) < (dstsize)) \ + strcpy(dst, src); \ + else return (XpmFileInvalid); } while(0) +#endif + +LFUNC(ParsePixels, int, (xpmData *data, unsigned int width, + unsigned int height, unsigned int ncolors, + unsigned int cpp, XpmColor *colorTable, + xpmHashTable *hashtable, unsigned int **pixels)); + +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 */ +}; + +int +xpmParseValues( + 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) +{ + unsigned int l; + char buf[BUFSIZ + 1]; + + if (!data->format) { /* XPM 2 or 3 */ + + /* + * 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, BUFSIZ); + if (l) { + *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6)); + if (*extensions) + *hotspot = (xpmNextUI(data, x_hotspot) + && xpmNextUI(data, y_hotspot)); + else { + *hotspot = (xpmatoui(buf, l, x_hotspot) + && xpmNextUI(data, y_hotspot)); + l = xpmNextWord(data, buf, BUFSIZ); + *extensions = (l == 6 && !strncmp("XPMEXT", buf, 6)); + } + } + } else { + + /* + * XPM 1 file read values: width, height, ncolors, chars_per_pixel + */ + int i; + char *ptr; + Bool got_one, saw_width = False, saw_height = False; + Bool saw_ncolors = False, saw_chars_per_pixel = False; + + for (i = 0; i < 4; i++) { + l = xpmNextWord(data, buf, BUFSIZ); + if (l != 7 || strncmp("#define", buf, 7)) + return (XpmFileInvalid); + l = xpmNextWord(data, buf, BUFSIZ); + if (!l) + return (XpmFileInvalid); + buf[l] = '\0'; + ptr = buf; + got_one = False; + while (!got_one) { + ptr = strchr(ptr, '_'); + if (!ptr) + return (XpmFileInvalid); + switch (l - (ptr - buf)) { + case 6: + if (saw_width || strncmp("_width", ptr, 6) + || !xpmNextUI(data, width)) + return (XpmFileInvalid); + else + saw_width = True; + got_one = True; + break; + case 7: + if (saw_height || strncmp("_height", ptr, 7) + || !xpmNextUI(data, height)) + return (XpmFileInvalid); + else + saw_height = True; + got_one = True; + break; + case 8: + if (saw_ncolors || strncmp("_ncolors", ptr, 8) + || !xpmNextUI(data, ncolors)) + return (XpmFileInvalid); + else + saw_ncolors = True; + got_one = True; + break; + case 16: + if (saw_chars_per_pixel + || strncmp("_chars_per_pixel", ptr, 16) + || !xpmNextUI(data, cpp)) + return (XpmFileInvalid); + else + saw_chars_per_pixel = True; + got_one = True; + break; + default: + ptr++; + } + } + /* skip the end of line */ + xpmNextString(data); + } + if (!saw_width || !saw_height || !saw_ncolors || !saw_chars_per_pixel) + return (XpmFileInvalid); + + *hotspot = 0; + *extensions = 0; + } + return (XpmSuccess); +} + +int +xpmParseColors( + xpmData *data, + unsigned int ncolors, + unsigned int cpp, + XpmColor **colorTablePtr, + xpmHashTable *hashtable) +{ + unsigned int key = 0, l, a, b, len; + unsigned int curkey; /* current color key */ + unsigned int lastwaskey; /* key read */ + char buf[BUFSIZ+1]; + char curbuf[BUFSIZ]; /* current buffer */ + char **sptr, *s; + XpmColor *color; + XpmColor *colorTable; + char **defaults; + int ErrorStatus; + + if (ncolors >= UINT_MAX / sizeof(XpmColor)) + return (XpmNoMemory); + colorTable = (XpmColor *) XpmCalloc(ncolors, sizeof(XpmColor)); + if (!colorTable) + return (XpmNoMemory); + + if (!data->format) { /* XPM 2 or 3 */ + for (a = 0, color = colorTable; a < ncolors; a++, color++) { + xpmNextString(data); /* skip the line */ + + /* + * read pixel value + */ + if (cpp >= UINT_MAX - 1) { + xpmFreeColorTable(colorTable, ncolors); + return (XpmNoMemory); + } + color->string = (char *) XpmMalloc(cpp + 1); + if (!color->string) { + xpmFreeColorTable(colorTable, ncolors); + return (XpmNoMemory); + } + for (b = 0, s = color->string; b < cpp; b++, s++) + *s = xpmGetC(data); + *s = '\0'; + + /* + * store the string in the hashtable with its color index number + */ + if (USE_HASHTABLE) { + ErrorStatus = + xpmHashIntern(hashtable, color->string, HashAtomData(a)); + if (ErrorStatus != XpmSuccess) { + xpmFreeColorTable(colorTable, ncolors); + return (ErrorStatus); + } + } + + /* + * read color keys and values + */ + defaults = (char **) color; + curkey = 0; + lastwaskey = 0; + *curbuf = '\0'; /* init curbuf */ + while ((l = xpmNextWord(data, buf, BUFSIZ))) { + 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 */ + len = strlen(curbuf) + 1; + s = (char *) XpmMalloc(len); + if (!s) { + xpmFreeColorTable(colorTable, ncolors); + return (XpmNoMemory); + } + defaults[curkey] = s; + memcpy(s, curbuf, len); + } + 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) + STRLCAT(curbuf, " ", sizeof(curbuf));/* append space */ + buf[l] = '\0'; + STRLCAT(curbuf, buf, sizeof(curbuf)); /* append buf */ + lastwaskey = 0; + } + } + if (!curkey) { /* key without value */ + xpmFreeColorTable(colorTable, ncolors); + return (XpmFileInvalid); + } + len = strlen(curbuf) + 1; /* integer overflow just theoretically possible */ + s = defaults[curkey] = (char *) XpmMalloc(len); + if (!s) { + xpmFreeColorTable(colorTable, ncolors); + return (XpmNoMemory); + } + memcpy(s, curbuf, len); + } + } else { /* XPM 1 */ + /* get to the beginning of the first string */ + data->Bos = '"'; + data->Eos = '\0'; + xpmNextString(data); + data->Eos = '"'; + for (a = 0, color = colorTable; a < ncolors; a++, color++) { + + /* + * read pixel value + */ + if (cpp >= UINT_MAX - 1) { + xpmFreeColorTable(colorTable, ncolors); + return (XpmNoMemory); + } + color->string = (char *) XpmMalloc(cpp + 1); + if (!color->string) { + xpmFreeColorTable(colorTable, ncolors); + return (XpmNoMemory); + } + for (b = 0, s = color->string; b < cpp; b++, s++) + *s = xpmGetC(data); + *s = '\0'; + + /* + * store the string in the hashtable with its color index number + */ + if (USE_HASHTABLE) { + ErrorStatus = + xpmHashIntern(hashtable, color->string, HashAtomData(a)); + if (ErrorStatus != XpmSuccess) { + xpmFreeColorTable(colorTable, ncolors); + return (ErrorStatus); + } + } + + /* + * read color values + */ + xpmNextString(data); /* get to the next string */ + *curbuf = '\0'; /* init curbuf */ + while ((l = xpmNextWord(data, buf, BUFSIZ))) { + if (*curbuf != '\0') + STRLCAT(curbuf, " ", sizeof(curbuf));/* append space */ + buf[l] = '\0'; + STRLCAT(curbuf, buf, sizeof(curbuf)); /* append buf */ + } + len = strlen(curbuf) + 1; + s = (char *) XpmMalloc(len); + if (!s) { + xpmFreeColorTable(colorTable, ncolors); + return (XpmNoMemory); + } + memcpy(s, curbuf, len); + color->c_color = s; + *curbuf = '\0'; /* reset curbuf */ + if (a < ncolors - 1) /* can we trust ncolors -> leave data's bounds */ + xpmNextString(data); /* get to the next string */ + } + } + *colorTablePtr = colorTable; + return (XpmSuccess); +} + +static int +ParsePixels( + xpmData *data, + unsigned int width, + unsigned int height, + unsigned int ncolors, + unsigned int cpp, + XpmColor *colorTable, + xpmHashTable *hashtable, + unsigned int **pixels) +{ + unsigned int *iptr, *iptr2 = NULL; /* found by Egbert Eich */ + unsigned int a, x, y; + + if ((height > 0 && width >= UINT_MAX / height) || + width * height >= UINT_MAX / sizeof(unsigned int)) + return XpmNoMemory; +#ifndef FOR_MSW + iptr2 = (unsigned int *) XpmMalloc(sizeof(unsigned int) * width * height); +#else + + /* + * special treatment to trick DOS malloc(size_t) where size_t is 16 bit!! + * XpmMalloc is defined to longMalloc(long) and checks the 16 bit boundary + */ + iptr2 = (unsigned int *) + XpmMalloc((long) sizeof(unsigned int) * (long) width * (long) height); +#endif + if (!iptr2) + return (XpmNoMemory); + + iptr = iptr2; + + switch (cpp) { + + case (1): /* Optimize for single character + * colors */ + { + unsigned short colidx[256]; + + if (ncolors > 256) { + XpmFree(iptr2); /* found by Egbert Eich */ + return (XpmFileInvalid); + } + + bzero((char *)colidx, 256 * sizeof(short)); + for (a = 0; a < ncolors; a++) + colidx[(unsigned char)colorTable[a].string[0]] = a + 1; + + for (y = 0; y < height; y++) { + xpmNextString(data); + for (x = 0; x < width; x++, iptr++) { + int c = xpmGetC(data); + + if (c > 0 && c < 256 && colidx[c] != 0) + *iptr = colidx[c] - 1; + else { + XpmFree(iptr2); + return (XpmFileInvalid); + } + } + } + } + break; + + case (2): /* Optimize for double character + * colors */ + { + +/* free all allocated pointers at all exits */ +#define FREE_CIDX \ +do \ +{ \ + int f; for (f = 0; f < 256; f++) \ + if (cidx[f]) XpmFree(cidx[f]); \ +} while(0) + + /* array of pointers malloced by need */ + unsigned short *cidx[256]; + unsigned int char1; + + bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */ + for (a = 0; a < ncolors; a++) { + char1 = (unsigned char) colorTable[a].string[0]; + if (cidx[char1] == NULL) { /* get new memory */ + cidx[char1] = (unsigned short *) + XpmCalloc(256, sizeof(unsigned short)); + if (cidx[char1] == NULL) { /* new block failed */ + FREE_CIDX; + XpmFree(iptr2); + return (XpmNoMemory); + } + } + cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1; + } + + for (y = 0; y < height; y++) { + xpmNextString(data); + for (x = 0; x < width; x++, iptr++) { + int cc1 = xpmGetC(data); + if (cc1 > 0 && cc1 < 256) { + int cc2 = xpmGetC(data); + if (cc2 > 0 && cc2 < 256 && + cidx[cc1] && cidx[cc1][cc2] != 0) + *iptr = cidx[cc1][cc2] - 1; + else { + FREE_CIDX; + XpmFree(iptr2); + return (XpmFileInvalid); + } + } else { + FREE_CIDX; + XpmFree(iptr2); + return (XpmFileInvalid); + } + } + } + FREE_CIDX; + } + break; + + default: /* Non-optimized case of long color + * names */ + { + char *s; + char buf[BUFSIZ]; + + if (cpp >= sizeof(buf)) { + XpmFree(iptr2); /* found by Egbert Eich */ + return (XpmFileInvalid); + } + + buf[cpp] = '\0'; + 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); /* int assigned to char, not a problem here */ + slot = xpmHashSlot(hashtable, buf); + if (!*slot) { /* no color matches */ + XpmFree(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); /* int assigned to char, not a problem here */ + for (a = 0; a < ncolors; a++) + if (!strcmp(colorTable[a].string, buf)) + break; + if (a == ncolors) { /* no color matches */ + XpmFree(iptr2); + return (XpmFileInvalid); + } + *iptr = a; + } + } + } + } + break; + } + *pixels = iptr2; + return (XpmSuccess); +} + +int +xpmParseExtensions( + 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 *) XpmMalloc(sizeof(XpmExtension)); + /* get the whole string */ + status = xpmGetString(data, &string, &l); + if (status != XpmSuccess) { + XpmFree(exts); + return (status); + } + /* look for the key word XPMEXT, skip lines before this */ + while ((notstart = strncmp("XPMEXT", string, 6)) + && (notend = strncmp("XPMENDEXT", string, 9))) { + XpmFree(string); + xpmNextString(data); + status = xpmGetString(data, &string, &l); + if (status != XpmSuccess) { + XpmFree(exts); + return (status); + } + } + if (!notstart) + notend = strncmp("XPMENDEXT", string, 9); + while (!notstart && notend) { + /* there starts an extension */ + ext = (XpmExtension *) + XpmRealloc(exts, (num + 1) * sizeof(XpmExtension)); /* can the loop be forced to iterate often enough to make "(num + 1) * sizeof(XpmExtension)" wrapping? */ + if (!ext) { + XpmFree(string); + XpmFreeExtensions(exts, num); + 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 *) XpmMalloc(l - a - 6); + if (!ext->name) { + XpmFree(string); + ext->lines = NULL; + ext->nlines = 0; + XpmFreeExtensions(exts, num + 1); + return (XpmNoMemory); + } + strncpy(ext->name, s + a, l - a - 6); + XpmFree(string); + /* now store the related lines */ + xpmNextString(data); + status = xpmGetString(data, &string, &l); + if (status != XpmSuccess) { + ext->lines = NULL; + ext->nlines = 0; + XpmFreeExtensions(exts, num + 1); + return (status); + } + ext->lines = (char **) XpmMalloc(sizeof(char *)); + nlines = 0; + while ((notstart = strncmp("XPMEXT", string, 6)) + && (notend = strncmp("XPMENDEXT", string, 9))) { + sp = (char **) + XpmRealloc(ext->lines, (nlines + 1) * sizeof(char *)); /* can we iterate enough for a wrapping? */ + if (!sp) { + XpmFree(string); + ext->nlines = nlines; + XpmFreeExtensions(exts, num + 1); + return (XpmNoMemory); + } + ext->lines = sp; + ext->lines[nlines] = string; + nlines++; + xpmNextString(data); + status = xpmGetString(data, &string, &l); + if (status != XpmSuccess) { + ext->nlines = nlines; + XpmFreeExtensions(exts, num + 1); + return (status); + } + } + if (!nlines) { + XpmFree(ext->lines); + ext->lines = NULL; + } + ext->nlines = nlines; + num++; + } + if (!num) { + XpmFree(string); + XpmFree(exts); + exts = NULL; + } else if (!notend) + XpmFree(string); + *nextensions = num; + *extensions = exts; + return (XpmSuccess); +} + + +/* function call in case of error */ +#undef RETURN +#define RETURN(status) \ +do { \ + goto error; \ +} while(0) + +/* + * This function parses an Xpm file or data and store the found informations + * in an an XpmImage structure which is returned. + */ +int +xpmParseData( + xpmData *data, + XpmImage *image, + XpmInfo *info) +{ + /* variables to return */ + unsigned int width, height, ncolors, cpp; + unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0; + XpmColor *colorTable = NULL; + unsigned int *pixelindex = NULL; + char *hints_cmt = NULL; + char *colors_cmt = NULL; + char *pixels_cmt = NULL; + + unsigned int cmts; + int ErrorStatus; + xpmHashTable hashtable; + + cmts = info && (info->valuemask & XpmReturnComments); + + /* + * parse the header + */ + ErrorStatus = xpmParseHeader(data); + if (ErrorStatus != XpmSuccess) + return (ErrorStatus); + + /* + * read values + */ + ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp, + &x_hotspot, &y_hotspot, &hotspot, + &extensions); + if (ErrorStatus != XpmSuccess) + return (ErrorStatus); + + /* + * store the hints comment line + */ + if (cmts) + xpmGetCmt(data, &hints_cmt); + + /* + * init the hashtable + */ + if (USE_HASHTABLE) { + ErrorStatus = xpmHashTableInit(&hashtable); + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + } + + /* + * read colors + */ + ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable); + if (ErrorStatus != XpmSuccess) { + if (USE_HASHTABLE) + xpmHashTableFree(&hashtable); + RETURN(ErrorStatus); + } + + /* + * store the colors comment line + */ + if (cmts) + 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 (cmts) + xpmGetCmt(data, &pixels_cmt); + + /* + * parse extensions + */ + if (info && (info->valuemask & XpmReturnExtensions)) { + if (extensions) { + ErrorStatus = xpmParseExtensions(data, &info->extensions, + &info->nextensions); + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + } else { + info->extensions = NULL; + info->nextensions = 0; + } + } + + /* + * store found informations in the XpmImage structure + */ + image->width = width; + image->height = height; + image->cpp = cpp; + image->ncolors = ncolors; + image->colorTable = colorTable; + image->data = pixelindex; + + if (info) { + if (cmts) { + info->hints_cmt = hints_cmt; + info->colors_cmt = colors_cmt; + info->pixels_cmt = pixels_cmt; + } + if (hotspot) { + info->x_hotspot = x_hotspot; + info->y_hotspot = y_hotspot; + info->valuemask |= XpmHotspot; + } + } + return (XpmSuccess); + +/* exit point in case of error, free only locally allocated variables */ +error: + if (colorTable) + xpmFreeColorTable(colorTable, ncolors); + if (pixelindex) + XpmFree(pixelindex); + if (hints_cmt) + XpmFree(hints_cmt); + if (colors_cmt) + XpmFree(colors_cmt); + if (pixels_cmt) + XpmFree(pixels_cmt); + + return(ErrorStatus); +} diff --git a/libXpm/src/scan.c b/libXpm/src/scan.c index 13c30759b..d2780a1ee 100644 --- a/libXpm/src/scan.c +++ b/libXpm/src/scan.c @@ -1,1024 +1,1024 @@ -/*
- * Copyright (C) 1989-95 GROUPE BULL
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to
- * deal in the Software without restriction, including without limitation the
- * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- * sell copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- * Except as contained in this notice, the name of GROUPE BULL shall not be
- * used in advertising or otherwise to promote the sale, use or other dealings
- * in this Software without prior written authorization from GROUPE BULL.
- */
-
-/*****************************************************************************\
-* scan.c: *
-* *
-* XPM library *
-* Scanning utility for XPM file format *
-* *
-* Developed by Arnaud Le Hors *
-\*****************************************************************************/
-
-/*
- * The code related to FOR_MSW has been added by
- * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
- */
-
-/*
- * The code related to AMIGA has been added by
- * Lorens Younes (d93-hyo@nada.kth.se) 4/96
- */
-
-/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "XpmI.h"
-
-#define MAXPRINTABLE 92 /* number of printable ascii chars
- * minus \ and " for string compat
- * and ? to avoid ANSI trigraphs. */
-
-static char *printable =
-" .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\
-ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
-
-/*
- * printable begin with a space, so in most case, due to my algorithm, when
- * the number of different colors is less than MAXPRINTABLE, it will give a
- * char follow by "nothing" (a space) in the readable xpm file
- */
-
-
-typedef struct {
- Pixel *pixels;
- unsigned int *pixelindex;
- unsigned int size;
- unsigned int ncolors;
- unsigned int mask_pixel; /* whether there is or not */
-} PixelsMap;
-
-LFUNC(storePixel, int, (Pixel pixel, PixelsMap *pmap,
- unsigned int *index_return));
-
-LFUNC(storeMaskPixel, int, (Pixel pixel, PixelsMap *pmap,
- unsigned int *index_return));
-
-typedef int (*storeFuncPtr)(Pixel pixel, PixelsMap *pmap,
- unsigned int *index_return);
-
-#ifndef FOR_MSW
-# ifndef AMIGA
-LFUNC(GetImagePixels, int, (XImage *image, unsigned int width,
- unsigned int height, PixelsMap *pmap));
-
-LFUNC(GetImagePixels32, int, (XImage *image, unsigned int width,
- unsigned int height, PixelsMap *pmap));
-
-LFUNC(GetImagePixels16, int, (XImage *image, unsigned int width,
- unsigned int height, PixelsMap *pmap));
-
-LFUNC(GetImagePixels8, int, (XImage *image, unsigned int width,
- unsigned int height, PixelsMap *pmap));
-
-LFUNC(GetImagePixels1, int, (XImage *image, unsigned int width,
- unsigned int height, PixelsMap *pmap,
- storeFuncPtr storeFunc));
-# else /* AMIGA */
-LFUNC(AGetImagePixels, int, (XImage *image, unsigned int width,
- unsigned int height, PixelsMap *pmap,
- storeFuncPtr storeFunc));
-# endif/* AMIGA */
-#else /* ndef FOR_MSW */
-LFUNC(MSWGetImagePixels, int, (Display *d, XImage *image, unsigned int width,
- unsigned int height, PixelsMap *pmap,
- storeFuncPtr storeFunc));
-#endif
-LFUNC(ScanTransparentColor, int, (XpmColor *color, unsigned int cpp,
- XpmAttributes *attributes));
-
-LFUNC(ScanOtherColors, int, (Display *display, XpmColor *colors,
- unsigned int ncolors,
- Pixel *pixels, unsigned int mask,
- unsigned int cpp, XpmAttributes *attributes));
-
-/*
- * This function stores the given pixel in the given arrays which are grown
- * if not large enough.
- */
-static int
-storePixel(
- Pixel pixel,
- PixelsMap *pmap,
- unsigned int *index_return)
-{
- unsigned int i;
- Pixel *p;
- unsigned int ncolors;
-
- if (*index_return) { /* this is a transparent pixel! */
- *index_return = 0;
- return 0;
- }
- ncolors = pmap->ncolors;
- p = pmap->pixels + pmap->mask_pixel;
- for (i = pmap->mask_pixel; i < ncolors; i++, p++)
- if (*p == pixel)
- break;
- if (i == ncolors) {
- if (ncolors >= pmap->size) {
- pmap->size *= 2;
- p = (Pixel *) XpmRealloc(pmap->pixels, sizeof(Pixel) * pmap->size);
- if (!p)
- return (1);
- pmap->pixels = p;
-
- }
- (pmap->pixels)[ncolors] = pixel;
- pmap->ncolors++;
- }
- *index_return = i;
- return 0;
-}
-
-static int
-storeMaskPixel(
- Pixel pixel,
- PixelsMap *pmap,
- unsigned int *index_return)
-{
- if (!pixel) {
- if (!pmap->ncolors) {
- pmap->ncolors = 1;
- (pmap->pixels)[0] = 0;
- pmap->mask_pixel = 1;
- }
- *index_return = 1;
- } else
- *index_return = 0;
- return 0;
-}
-
-/* function call in case of error */
-#undef RETURN
-#define RETURN(status) \
-do { \
- ErrorStatus = status; \
- goto error; \
-} while(0)
-
-/*
- * This function scans the given image and stores the found informations in
- * the given XpmImage structure.
- */
-int
-XpmCreateXpmImageFromImage(
- Display *display,
- XImage *image,
- XImage *shapeimage,
- XpmImage *xpmimage,
- XpmAttributes *attributes)
-{
- /* variables stored in the XpmAttributes structure */
- unsigned int cpp;
-
- /* variables to return */
- PixelsMap pmap;
- XpmColor *colorTable = NULL;
- int ErrorStatus = 0;
-
- /* calculation variables */
- unsigned int width = 0;
- unsigned int height = 0;
- unsigned int cppm; /* minimum chars per pixel */
- unsigned int c;
-
- /* initialize pmap */
- pmap.pixels = NULL;
- pmap.pixelindex = NULL;
- pmap.size = 256; /* should be enough most of the time */
- pmap.ncolors = 0;
- pmap.mask_pixel = 0;
-
- /*
- * get geometry
- */
- if (image) {
- width = image->width;
- height = image->height;
- } else if (shapeimage) {
- width = shapeimage->width;
- height = shapeimage->height;
- }
-
- /*
- * retrieve information from the XpmAttributes
- */
- if (attributes && (attributes->valuemask & XpmCharsPerPixel
-/* 3.2 backward compatibility code */
- || attributes->valuemask & XpmInfos))
-/* end 3.2 bc */
- cpp = attributes->cpp;
- else
- cpp = 0;
-
- if ((height > 0 && width >= UINT_MAX / height) ||
- width * height >= UINT_MAX / sizeof(unsigned int))
- RETURN(XpmNoMemory);
- pmap.pixelindex =
- (unsigned int *) XpmCalloc(width * height, sizeof(unsigned int));
- if (!pmap.pixelindex)
- RETURN(XpmNoMemory);
-
- if (pmap.size >= UINT_MAX / sizeof(Pixel))
- RETURN(XpmNoMemory);
-
- pmap.pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * pmap.size);
- if (!pmap.pixels)
- RETURN(XpmNoMemory);
-
- /*
- * scan shape mask if any
- */
- if (shapeimage) {
-#ifndef FOR_MSW
-# ifndef AMIGA
- ErrorStatus = GetImagePixels1(shapeimage, width, height, &pmap,
- storeMaskPixel);
-# else
- ErrorStatus = AGetImagePixels(shapeimage, width, height, &pmap,
- storeMaskPixel);
-# endif
-#else
- ErrorStatus = MSWGetImagePixels(display, shapeimage, width, height,
- &pmap, storeMaskPixel);
-#endif
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
- }
-
- /*
- * scan the image data
- *
- * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use optimized
- * functions, otherwise use slower but sure general one.
- *
- */
-
- if (image) {
-#ifndef FOR_MSW
-# ifndef AMIGA
- if (((image->bits_per_pixel | image->depth) == 1) &&
- (image->byte_order == image->bitmap_bit_order))
- ErrorStatus = GetImagePixels1(image, width, height, &pmap,
- storePixel);
- else if (image->format == ZPixmap) {
- if (image->bits_per_pixel == 8)
- ErrorStatus = GetImagePixels8(image, width, height, &pmap);
- else if (image->bits_per_pixel == 16)
- ErrorStatus = GetImagePixels16(image, width, height, &pmap);
- else if (image->bits_per_pixel == 32)
- ErrorStatus = GetImagePixels32(image, width, height, &pmap);
- } else
- ErrorStatus = GetImagePixels(image, width, height, &pmap);
-# else
- ErrorStatus = AGetImagePixels(image, width, height, &pmap,
- storePixel);
-# endif
-#else
- ErrorStatus = MSWGetImagePixels(display, image, width, height, &pmap,
- storePixel);
-#endif
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
- }
-
- /*
- * get rgb values and a string of char, and possibly a name for each
- * color
- */
- if (pmap.ncolors >= UINT_MAX / sizeof(XpmColor))
- RETURN(XpmNoMemory);
- colorTable = (XpmColor *) XpmCalloc(pmap.ncolors, sizeof(XpmColor));
- if (!colorTable)
- RETURN(XpmNoMemory);
-
- /* compute the minimal cpp */
- for (cppm = 1, c = MAXPRINTABLE; pmap.ncolors > c; cppm++)
- c *= MAXPRINTABLE;
- if (cpp < cppm)
- cpp = cppm;
-
- if (pmap.mask_pixel) {
- ErrorStatus = ScanTransparentColor(colorTable, cpp, attributes);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
- }
-
- ErrorStatus = ScanOtherColors(display, colorTable, pmap.ncolors,
- pmap.pixels, pmap.mask_pixel, cpp,
- attributes);
- if (ErrorStatus != XpmSuccess)
- RETURN(ErrorStatus);
-
- /*
- * store found informations in the XpmImage structure
- */
- xpmimage->width = width;
- xpmimage->height = height;
- xpmimage->cpp = cpp;
- xpmimage->ncolors = pmap.ncolors;
- xpmimage->colorTable = colorTable;
- xpmimage->data = pmap.pixelindex;
-
- XpmFree(pmap.pixels);
- return (XpmSuccess);
-
-/* exit point in case of error, free only locally allocated variables */
-error:
- if (pmap.pixelindex)
- XpmFree(pmap.pixelindex);
- if (pmap.pixels)
- XpmFree(pmap.pixels);
- if (colorTable)
- xpmFreeColorTable(colorTable, pmap.ncolors);
-
- return (ErrorStatus);
-}
-
-static int
-ScanTransparentColor(
- XpmColor *color,
- unsigned int cpp,
- XpmAttributes *attributes)
-{
- char *s;
- unsigned int a, b, c;
-
- /* first get a character string */
- a = 0;
- if (cpp >= UINT_MAX - 1)
- return (XpmNoMemory);
- if (!(s = color->string = (char *) XpmMalloc(cpp + 1)))
- return (XpmNoMemory);
- *s++ = printable[c = a % MAXPRINTABLE];
- for (b = 1; b < cpp; b++, s++)
- *s = printable[c = ((a - c) / MAXPRINTABLE) % MAXPRINTABLE];
- *s = '\0';
-
- /* then retreive related info from the attributes if any */
- if (attributes && (attributes->valuemask & XpmColorTable
-/* 3.2 backward compatibility code */
- || attributes->valuemask & XpmInfos)
-/* end 3.2 bc */
- && attributes->mask_pixel != XpmUndefPixel) {
-
- unsigned int key;
- char **defaults = (char **) color;
- char **mask_defaults;
-
-/* 3.2 backward compatibility code */
- if (attributes->valuemask & XpmColorTable)
-/* end 3.2 bc */
- mask_defaults = (char **) (
- attributes->colorTable + attributes->mask_pixel);
-/* 3.2 backward compatibility code */
- else
- mask_defaults = (char **)
- ((XpmColor **) attributes->colorTable)[attributes->mask_pixel];
-/* end 3.2 bc */
- for (key = 1; key <= NKEYS; key++) {
- if ((s = mask_defaults[key])) {
- defaults[key] = (char *) xpmstrdup(s);
- if (!defaults[key])
- return (XpmNoMemory);
- }
- }
- } else {
- color->c_color = (char *) xpmstrdup(TRANSPARENT_COLOR);
- if (!color->c_color)
- return (XpmNoMemory);
- }
- return (XpmSuccess);
-}
-
-static int
-ScanOtherColors(
- Display *display,
- XpmColor *colors,
- unsigned int ncolors,
- Pixel *pixels,
- unsigned int mask,
- unsigned int cpp,
- XpmAttributes *attributes)
-{
- /* variables stored in the XpmAttributes structure */
- Colormap colormap;
- char *rgb_fname;
-
-#ifndef FOR_MSW
- xpmRgbName rgbn[MAX_RGBNAMES];
-#else
- xpmRgbName *rgbn = NULL;
-#endif
- int rgbn_max = 0;
- unsigned int i, j, c, i2;
- XpmColor *color;
- XColor *xcolors = NULL, *xcolor;
- char *colorname, *s;
- XpmColor *colorTable = NULL, **oldColorTable = NULL;
- unsigned int ancolors = 0;
- Pixel *apixels = NULL;
- unsigned int mask_pixel = 0;
- Bool found;
-
- /* retrieve information from the XpmAttributes */
- if (attributes && (attributes->valuemask & XpmColormap))
- colormap = attributes->colormap;
- else
- colormap = XDefaultColormap(display, XDefaultScreen(display));
- if (attributes && (attributes->valuemask & XpmRgbFilename))
- rgb_fname = attributes->rgb_fname;
- else
- rgb_fname = NULL;
-
- /* start from the right element */
- if (mask) {
- colors++;
- ncolors--;
- pixels++;
- }
-
- /* first get character strings and rgb values */
- if (ncolors >= UINT_MAX / sizeof(XColor) || cpp >= UINT_MAX - 1)
- return (XpmNoMemory);
- xcolors = (XColor *) XpmMalloc(sizeof(XColor) * ncolors);
- if (!xcolors)
- return (XpmNoMemory);
-
- for (i = 0, i2 = mask, color = colors, xcolor = xcolors;
- i < ncolors; i++, i2++, color++, xcolor++, pixels++) {
-
- if (!(s = color->string = (char *) XpmMalloc(cpp + 1))) {
- XpmFree(xcolors);
- return (XpmNoMemory);
- }
- *s++ = printable[c = i2 % MAXPRINTABLE];
- for (j = 1; j < cpp; j++, s++)
- *s = printable[c = ((i2 - c) / MAXPRINTABLE) % MAXPRINTABLE];
- *s = '\0';
-
- xcolor->pixel = *pixels;
- }
- XQueryColors(display, colormap, xcolors, ncolors);
-
-#ifndef FOR_MSW
- /* read the rgb file if any was specified */
- if (rgb_fname)
- rgbn_max = xpmReadRgbNames(attributes->rgb_fname, rgbn);
-#else
- /* FOR_MSW: rgb names and values are hardcoded in rgbtab.h */
- rgbn_max = xpmReadRgbNames(NULL, NULL);
-#endif
-
- if (attributes && attributes->valuemask & XpmColorTable) {
- colorTable = attributes->colorTable;
- ancolors = attributes->ncolors;
- apixels = attributes->pixels;
- mask_pixel = attributes->mask_pixel;
- }
-/* 3.2 backward compatibility code */
- else if (attributes && attributes->valuemask & XpmInfos) {
- oldColorTable = (XpmColor **) attributes->colorTable;
- ancolors = attributes->ncolors;
- apixels = attributes->pixels;
- mask_pixel = attributes->mask_pixel;
- }
-/* end 3.2 bc */
-
- for (i = 0, color = colors, xcolor = xcolors; i < ncolors;
- i++, color++, xcolor++) {
-
- /* look for related info from the attributes if any */
- found = False;
- if (ancolors) {
- unsigned int offset = 0;
-
- for (j = 0; j < ancolors; j++) {
- if (j == mask_pixel) {
- offset = 1;
- continue;
- }
- if (apixels[j - offset] == xcolor->pixel)
- break;
- }
- if (j != ancolors) {
- unsigned int key;
- char **defaults = (char **) color;
- char **adefaults;
-
-/* 3.2 backward compatibility code */
- if (oldColorTable)
- adefaults = (char **) oldColorTable[j];
- else
-/* end 3.2 bc */
- adefaults = (char **) (colorTable + j);
-
- found = True;
- for (key = 1; key <= NKEYS; key++) {
- if ((s = adefaults[key]))
- defaults[key] = (char *) xpmstrdup(s);
- }
- }
- }
- if (!found) {
- /* if nothing found look for a color name */
- colorname = NULL;
- if (rgbn_max)
- colorname = xpmGetRgbName(rgbn, rgbn_max, xcolor->red,
- xcolor->green, xcolor->blue);
- if (colorname)
- color->c_color = (char *) xpmstrdup(colorname);
- else {
- /* at last store the rgb value */
- char buf[BUFSIZ];
-#ifndef FOR_MSW
- sprintf(buf, "#%04X%04X%04X",
- xcolor->red, xcolor->green, xcolor->blue);
-#else
- sprintf(buf, "#%02x%02x%02x",
- xcolor->red, xcolor->green, xcolor->blue);
-#endif
- color->c_color = (char *) xpmstrdup(buf);
- }
- if (!color->c_color) {
- XpmFree(xcolors);
- xpmFreeRgbNames(rgbn, rgbn_max);
- return (XpmNoMemory);
- }
- }
- }
-
- XpmFree(xcolors);
- xpmFreeRgbNames(rgbn, rgbn_max);
- return (XpmSuccess);
-}
-
-#ifndef FOR_MSW
-# ifndef AMIGA
-/*
- * The functions below are written from X11R5 MIT's code (XImUtil.c)
- *
- * The idea is to have faster functions than the standard XGetPixel function
- * to scan the image data. Indeed we can speed up things by suppressing tests
- * performed for each pixel. We do exactly the same tests but at the image
- * level.
- */
-
-static unsigned long Const low_bits_table[] = {
- 0x00000000, 0x00000001, 0x00000003, 0x00000007,
- 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
- 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
- 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
- 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
- 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
- 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
- 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
- 0xffffffff
-};
-
-/*
- * Default method to scan pixels of an image data structure.
- * The algorithm used is:
- *
- * copy the source bitmap_unit or Zpixel into temp
- * normalize temp if needed
- * extract the pixel bits into return value
- *
- */
-
-static int
-GetImagePixels(
- XImage *image,
- unsigned int width,
- unsigned int height,
- PixelsMap *pmap)
-{
- char *src;
- char *dst;
- unsigned int *iptr;
- char *data;
- unsigned int x, y;
- int bits, depth, ibu, ibpp, offset, i;
- unsigned long lbt;
- Pixel pixel, px;
-
- data = image->data;
- iptr = pmap->pixelindex;
- depth = image->depth;
- lbt = low_bits_table[depth];
- ibpp = image->bits_per_pixel;
- offset = image->xoffset;
-
- if (image->bitmap_unit < 0)
- return (XpmNoMemory);
-
- if ((image->bits_per_pixel | image->depth) == 1) {
- ibu = image->bitmap_unit;
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- src = &data[XYINDEX(x, y, image)];
- dst = (char *) &pixel;
- pixel = 0;
- for (i = ibu >> 3; --i >= 0;)
- *dst++ = *src++;
- XYNORMALIZE(&pixel, image);
- bits = (x + offset) % ibu;
- pixel = ((((char *) &pixel)[bits >> 3]) >> (bits & 7)) & 1;
- if (ibpp != depth)
- pixel &= lbt;
- if (storePixel(pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- } else if (image->format == XYPixmap) {
- int nbytes, bpl, j;
- long plane = 0;
- ibu = image->bitmap_unit;
- nbytes = ibu >> 3;
- bpl = image->bytes_per_line;
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- pixel = 0;
- plane = 0;
- for (i = depth; --i >= 0;) {
- src = &data[XYINDEX(x, y, image) + plane];
- dst = (char *) &px;
- px = 0;
- for (j = nbytes; --j >= 0;)
- *dst++ = *src++;
- XYNORMALIZE(&px, image);
- bits = (x + offset) % ibu;
- pixel = (pixel << 1) |
- (((((char *) &px)[bits >> 3]) >> (bits & 7)) & 1);
- plane = plane + (bpl * height);
- }
- if (ibpp != depth)
- pixel &= lbt;
- if (storePixel(pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- } else if (image->format == ZPixmap) {
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- src = &data[ZINDEX(x, y, image)];
- dst = (char *) &px;
- px = 0;
- for (i = (ibpp + 7) >> 3; --i >= 0;)
- *dst++ = *src++;
- ZNORMALIZE(&px, image);
- pixel = 0;
- for (i = sizeof(unsigned long); --i >= 0;)
- pixel = (pixel << 8) | ((unsigned char *) &px)[i];
- if (ibpp == 4) {
- if (x & 1)
- pixel >>= 4;
- else
- pixel &= 0xf;
- }
- if (ibpp != depth)
- pixel &= lbt;
- if (storePixel(pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- } else
- return (XpmColorError); /* actually a bad image */
- return (XpmSuccess);
-}
-
-/*
- * scan pixels of a 32-bits Z image data structure
- */
-
-#if !defined(WORD64) && !defined(LONG64)
-static unsigned long byteorderpixel = MSBFirst << 24;
-#endif
-
-static int
-GetImagePixels32(
- XImage *image,
- unsigned int width,
- unsigned int height,
- PixelsMap *pmap)
-{
- unsigned char *addr;
- unsigned char *data;
- unsigned int *iptr;
- unsigned int x, y;
- unsigned long lbt;
- Pixel pixel;
- int depth;
-
- data = (unsigned char *) image->data;
- iptr = pmap->pixelindex;
- depth = image->depth;
- lbt = low_bits_table[depth];
-#if !defined(WORD64) && !defined(LONG64)
- if (*((char *) &byteorderpixel) == image->byte_order) {
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- addr = &data[ZINDEX32(x, y, image)];
- pixel = *((unsigned long *) addr);
- if (depth != 32)
- pixel &= lbt;
- if (storePixel(pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- } else
-#endif
- if (image->byte_order == MSBFirst)
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- addr = &data[ZINDEX32(x, y, image)];
- pixel = ((unsigned long) addr[0] << 24 |
- (unsigned long) addr[1] << 16 |
- (unsigned long) addr[2] << 8 |
- addr[3]);
- if (depth != 32)
- pixel &= lbt;
- if (storePixel(pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- else
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- addr = &data[ZINDEX32(x, y, image)];
- pixel = (addr[0] |
- (unsigned long) addr[1] << 8 |
- (unsigned long) addr[2] << 16 |
- (unsigned long) addr[3] << 24);
- if (depth != 32)
- pixel &= lbt;
- if (storePixel(pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- return (XpmSuccess);
-}
-
-/*
- * scan pixels of a 16-bits Z image data structure
- */
-
-static int
-GetImagePixels16(
- XImage *image,
- unsigned int width,
- unsigned int height,
- PixelsMap *pmap)
-{
- unsigned char *addr;
- unsigned char *data;
- unsigned int *iptr;
- unsigned int x, y;
- unsigned long lbt;
- Pixel pixel;
- int depth;
-
- data = (unsigned char *) image->data;
- iptr = pmap->pixelindex;
- depth = image->depth;
- lbt = low_bits_table[depth];
- if (image->byte_order == MSBFirst)
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- addr = &data[ZINDEX16(x, y, image)];
- pixel = addr[0] << 8 | addr[1];
- if (depth != 16)
- pixel &= lbt;
- if (storePixel(pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- else
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- addr = &data[ZINDEX16(x, y, image)];
- pixel = addr[0] | addr[1] << 8;
- if (depth != 16)
- pixel &= lbt;
- if (storePixel(pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- return (XpmSuccess);
-}
-
-/*
- * scan pixels of a 8-bits Z image data structure
- */
-
-static int
-GetImagePixels8(
- XImage *image,
- unsigned int width,
- unsigned int height,
- PixelsMap *pmap)
-{
- unsigned int *iptr;
- unsigned char *data;
- unsigned int x, y;
- unsigned long lbt;
- Pixel pixel;
- int depth;
-
- data = (unsigned char *) image->data;
- iptr = pmap->pixelindex;
- depth = image->depth;
- lbt = low_bits_table[depth];
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- pixel = data[ZINDEX8(x, y, image)];
- if (depth != 8)
- pixel &= lbt;
- if (storePixel(pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- return (XpmSuccess);
-}
-
-/*
- * scan pixels of a 1-bit depth Z image data structure
- */
-
-static int
-GetImagePixels1(
- XImage *image,
- unsigned int width,
- unsigned int height,
- PixelsMap *pmap,
- storeFuncPtr storeFunc)
-{
- unsigned int *iptr;
- unsigned int x, y;
- char *data;
- Pixel pixel;
- int xoff, yoff, offset, bpl;
-
- data = image->data;
- iptr = pmap->pixelindex;
- offset = image->xoffset;
- bpl = image->bytes_per_line;
-
- if (image->bitmap_bit_order == MSBFirst)
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- xoff = x + offset;
- yoff = y * bpl + (xoff >> 3);
- xoff &= 7;
- pixel = (data[yoff] & (0x80 >> xoff)) ? 1 : 0;
- if ((*storeFunc) (pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- else
- for (y = 0; y < height; y++)
- for (x = 0; x < width; x++, iptr++) {
- xoff = x + offset;
- yoff = y * bpl + (xoff >> 3);
- xoff &= 7;
- pixel = (data[yoff] & (1 << xoff)) ? 1 : 0;
- if ((*storeFunc) (pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- return (XpmSuccess);
-}
-
-# else /* AMIGA */
-
-#define CLEAN_UP(status) \
-do {\
- if (pixels) XpmFree (pixels);\
- if (tmp_img) FreeXImage (tmp_img);\
- return (status);\
-} while(0)
-
-static int
-AGetImagePixels (
- XImage *image,
- unsigned int width,
- unsigned int height,
- PixelsMap *pmap,
- int (*storeFunc) (Pixel, PixelsMap *, unsigned int *))
-{
- unsigned int *iptr;
- unsigned int x, y;
- unsigned char *pixels;
- XImage *tmp_img;
-
- pixels = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*pixels));
- if (pixels == NULL)
- return XpmNoMemory;
-
- tmp_img = AllocXImage ((((width+15)>>4)<<4), 1, image->rp->BitMap->Depth);
- if (tmp_img == NULL)
- CLEAN_UP (XpmNoMemory);
-
- iptr = pmap->pixelindex;
- for (y = 0; y < height; ++y)
- {
- ReadPixelLine8 (image->rp, 0, y, width, pixels, tmp_img->rp);
- for (x = 0; x < width; ++x, ++iptr)
- {
- if ((*storeFunc) (pixels[x], pmap, iptr))
- CLEAN_UP (XpmNoMemory);
- }
- }
-
- CLEAN_UP (XpmSuccess);
-}
-
-#undef CLEAN_UP
-
-# endif/* AMIGA */
-#else /* ndef FOR_MSW */
-static int
-MSWGetImagePixels(
- Display *display,
- XImage *image,
- unsigned int width,
- unsigned int height,
- PixelsMap *pmap,
- int (*storeFunc) (Pixel, PixelsMap*, unsigned int *))
-{
- unsigned int *iptr;
- unsigned int x, y;
- Pixel pixel;
-
- iptr = pmap->pixelindex;
-
- SelectObject(*display, image->bitmap);
- for (y = 0; y < height; y++) {
- for (x = 0; x < width; x++, iptr++) {
- pixel = GetPixel(*display, x, y);
- if ((*storeFunc) (pixel, pmap, iptr))
- return (XpmNoMemory);
- }
- }
- return (XpmSuccess);
-}
-
-#endif
-
-#ifndef FOR_MSW
-# ifndef AMIGA
-int
-XpmCreateXpmImageFromPixmap(
- Display *display,
- Pixmap pixmap,
- Pixmap shapemask,
- XpmImage *xpmimage,
- XpmAttributes *attributes)
-{
- XImage *ximage = NULL;
- XImage *shapeimage = NULL;
- unsigned int width = 0;
- unsigned int height = 0;
- int ErrorStatus;
-
- /* get geometry */
- if (attributes && attributes->valuemask & XpmSize) {
- width = attributes->width;
- height = attributes->height;
- }
- /* get the ximages */
- if (pixmap)
- xpmCreateImageFromPixmap(display, pixmap, &ximage, &width, &height);
- if (shapemask)
- xpmCreateImageFromPixmap(display, shapemask, &shapeimage,
- &width, &height);
-
- /* create the related XpmImage */
- ErrorStatus = XpmCreateXpmImageFromImage(display, ximage, shapeimage,
- xpmimage, attributes);
-
- /* destroy the ximages */
- if (ximage)
- XDestroyImage(ximage);
- if (shapeimage)
- XDestroyImage(shapeimage);
-
- return (ErrorStatus);
-}
-
-# endif/* not AMIGA */
-#endif /* ndef FOR_MSW */
+/* + * Copyright (C) 1989-95 GROUPE BULL + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Except as contained in this notice, the name of GROUPE BULL shall not be + * used in advertising or otherwise to promote the sale, use or other dealings + * in this Software without prior written authorization from GROUPE BULL. + */ + +/*****************************************************************************\ +* scan.c: * +* * +* XPM library * +* Scanning utility for XPM file format * +* * +* Developed by Arnaud Le Hors * +\*****************************************************************************/ + +/* + * The code related to FOR_MSW has been added by + * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94 + */ + +/* + * The code related to AMIGA has been added by + * Lorens Younes (d93-hyo@nada.kth.se) 4/96 + */ + +/* October 2004, source code review by Thomas Biege <thomas@suse.de> */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif +#include "XpmI.h" + +#define MAXPRINTABLE 92 /* number of printable ascii chars + * minus \ and " for string compat + * and ? to avoid ANSI trigraphs. */ + +static char *printable = +" .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\ +ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|"; + +/* + * printable begin with a space, so in most case, due to my algorithm, when + * the number of different colors is less than MAXPRINTABLE, it will give a + * char follow by "nothing" (a space) in the readable xpm file + */ + + +typedef struct { + Pixel *pixels; + unsigned int *pixelindex; + unsigned int size; + unsigned int ncolors; + unsigned int mask_pixel; /* whether there is or not */ +} PixelsMap; + +LFUNC(storePixel, int, (Pixel pixel, PixelsMap *pmap, + unsigned int *index_return)); + +LFUNC(storeMaskPixel, int, (Pixel pixel, PixelsMap *pmap, + unsigned int *index_return)); + +typedef int (*storeFuncPtr)(Pixel pixel, PixelsMap *pmap, + unsigned int *index_return); + +#ifndef FOR_MSW +# ifndef AMIGA +LFUNC(GetImagePixels, int, (XImage *image, unsigned int width, + unsigned int height, PixelsMap *pmap)); + +LFUNC(GetImagePixels32, int, (XImage *image, unsigned int width, + unsigned int height, PixelsMap *pmap)); + +LFUNC(GetImagePixels16, int, (XImage *image, unsigned int width, + unsigned int height, PixelsMap *pmap)); + +LFUNC(GetImagePixels8, int, (XImage *image, unsigned int width, + unsigned int height, PixelsMap *pmap)); + +LFUNC(GetImagePixels1, int, (XImage *image, unsigned int width, + unsigned int height, PixelsMap *pmap, + storeFuncPtr storeFunc)); +# else /* AMIGA */ +LFUNC(AGetImagePixels, int, (XImage *image, unsigned int width, + unsigned int height, PixelsMap *pmap, + storeFuncPtr storeFunc)); +# endif/* AMIGA */ +#else /* ndef FOR_MSW */ +LFUNC(MSWGetImagePixels, int, (Display *d, XImage *image, unsigned int width, + unsigned int height, PixelsMap *pmap, + storeFuncPtr storeFunc)); +#endif +LFUNC(ScanTransparentColor, int, (XpmColor *color, unsigned int cpp, + XpmAttributes *attributes)); + +LFUNC(ScanOtherColors, int, (Display *display, XpmColor *colors, + unsigned int ncolors, + Pixel *pixels, unsigned int mask, + unsigned int cpp, XpmAttributes *attributes)); + +/* + * This function stores the given pixel in the given arrays which are grown + * if not large enough. + */ +static int +storePixel( + Pixel pixel, + PixelsMap *pmap, + unsigned int *index_return) +{ + unsigned int i; + Pixel *p; + unsigned int ncolors; + + if (*index_return) { /* this is a transparent pixel! */ + *index_return = 0; + return 0; + } + ncolors = pmap->ncolors; + p = pmap->pixels + pmap->mask_pixel; + for (i = pmap->mask_pixel; i < ncolors; i++, p++) + if (*p == pixel) + break; + if (i == ncolors) { + if (ncolors >= pmap->size) { + pmap->size *= 2; + p = (Pixel *) XpmRealloc(pmap->pixels, sizeof(Pixel) * pmap->size); + if (!p) + return (1); + pmap->pixels = p; + + } + (pmap->pixels)[ncolors] = pixel; + pmap->ncolors++; + } + *index_return = i; + return 0; +} + +static int +storeMaskPixel( + Pixel pixel, + PixelsMap *pmap, + unsigned int *index_return) +{ + if (!pixel) { + if (!pmap->ncolors) { + pmap->ncolors = 1; + (pmap->pixels)[0] = 0; + pmap->mask_pixel = 1; + } + *index_return = 1; + } else + *index_return = 0; + return 0; +} + +/* function call in case of error */ +#undef RETURN +#define RETURN(status) \ +do { \ + ErrorStatus = status; \ + goto error; \ +} while(0) + +/* + * This function scans the given image and stores the found informations in + * the given XpmImage structure. + */ +int +XpmCreateXpmImageFromImage( + Display *display, + XImage *image, + XImage *shapeimage, + XpmImage *xpmimage, + XpmAttributes *attributes) +{ + /* variables stored in the XpmAttributes structure */ + unsigned int cpp; + + /* variables to return */ + PixelsMap pmap; + XpmColor *colorTable = NULL; + int ErrorStatus = 0; + + /* calculation variables */ + unsigned int width = 0; + unsigned int height = 0; + unsigned int cppm; /* minimum chars per pixel */ + unsigned int c; + + /* initialize pmap */ + pmap.pixels = NULL; + pmap.pixelindex = NULL; + pmap.size = 256; /* should be enough most of the time */ + pmap.ncolors = 0; + pmap.mask_pixel = 0; + + /* + * get geometry + */ + if (image) { + width = image->width; + height = image->height; + } else if (shapeimage) { + width = shapeimage->width; + height = shapeimage->height; + } + + /* + * retrieve information from the XpmAttributes + */ + if (attributes && (attributes->valuemask & XpmCharsPerPixel +/* 3.2 backward compatibility code */ + || attributes->valuemask & XpmInfos)) +/* end 3.2 bc */ + cpp = attributes->cpp; + else + cpp = 0; + + if ((height > 0 && width >= UINT_MAX / height) || + width * height >= UINT_MAX / sizeof(unsigned int)) + RETURN(XpmNoMemory); + pmap.pixelindex = + (unsigned int *) XpmCalloc(width * height, sizeof(unsigned int)); + if (!pmap.pixelindex) + RETURN(XpmNoMemory); + + if (pmap.size >= UINT_MAX / sizeof(Pixel)) + RETURN(XpmNoMemory); + + pmap.pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * pmap.size); + if (!pmap.pixels) + RETURN(XpmNoMemory); + + /* + * scan shape mask if any + */ + if (shapeimage) { +#ifndef FOR_MSW +# ifndef AMIGA + ErrorStatus = GetImagePixels1(shapeimage, width, height, &pmap, + storeMaskPixel); +# else + ErrorStatus = AGetImagePixels(shapeimage, width, height, &pmap, + storeMaskPixel); +# endif +#else + ErrorStatus = MSWGetImagePixels(display, shapeimage, width, height, + &pmap, storeMaskPixel); +#endif + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + } + + /* + * scan the image data + * + * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use optimized + * functions, otherwise use slower but sure general one. + * + */ + + if (image) { +#ifndef FOR_MSW +# ifndef AMIGA + if (((image->bits_per_pixel | image->depth) == 1) && + (image->byte_order == image->bitmap_bit_order)) + ErrorStatus = GetImagePixels1(image, width, height, &pmap, + storePixel); + else if (image->format == ZPixmap) { + if (image->bits_per_pixel == 8) + ErrorStatus = GetImagePixels8(image, width, height, &pmap); + else if (image->bits_per_pixel == 16) + ErrorStatus = GetImagePixels16(image, width, height, &pmap); + else if (image->bits_per_pixel == 32) + ErrorStatus = GetImagePixels32(image, width, height, &pmap); + } else + ErrorStatus = GetImagePixels(image, width, height, &pmap); +# else + ErrorStatus = AGetImagePixels(image, width, height, &pmap, + storePixel); +# endif +#else + ErrorStatus = MSWGetImagePixels(display, image, width, height, &pmap, + storePixel); +#endif + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + } + + /* + * get rgb values and a string of char, and possibly a name for each + * color + */ + if (pmap.ncolors >= UINT_MAX / sizeof(XpmColor)) + RETURN(XpmNoMemory); + colorTable = (XpmColor *) XpmCalloc(pmap.ncolors, sizeof(XpmColor)); + if (!colorTable) + RETURN(XpmNoMemory); + + /* compute the minimal cpp */ + for (cppm = 1, c = MAXPRINTABLE; pmap.ncolors > c; cppm++) + c *= MAXPRINTABLE; + if (cpp < cppm) + cpp = cppm; + + if (pmap.mask_pixel) { + ErrorStatus = ScanTransparentColor(colorTable, cpp, attributes); + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + } + + ErrorStatus = ScanOtherColors(display, colorTable, pmap.ncolors, + pmap.pixels, pmap.mask_pixel, cpp, + attributes); + if (ErrorStatus != XpmSuccess) + RETURN(ErrorStatus); + + /* + * store found informations in the XpmImage structure + */ + xpmimage->width = width; + xpmimage->height = height; + xpmimage->cpp = cpp; + xpmimage->ncolors = pmap.ncolors; + xpmimage->colorTable = colorTable; + xpmimage->data = pmap.pixelindex; + + XpmFree(pmap.pixels); + return (XpmSuccess); + +/* exit point in case of error, free only locally allocated variables */ +error: + if (pmap.pixelindex) + XpmFree(pmap.pixelindex); + if (pmap.pixels) + XpmFree(pmap.pixels); + if (colorTable) + xpmFreeColorTable(colorTable, pmap.ncolors); + + return (ErrorStatus); +} + +static int +ScanTransparentColor( + XpmColor *color, + unsigned int cpp, + XpmAttributes *attributes) +{ + char *s; + unsigned int a, b, c; + + /* first get a character string */ + a = 0; + if (cpp >= UINT_MAX - 1) + return (XpmNoMemory); + if (!(s = color->string = (char *) XpmMalloc(cpp + 1))) + return (XpmNoMemory); + *s++ = printable[c = a % MAXPRINTABLE]; + for (b = 1; b < cpp; b++, s++) + *s = printable[c = ((a - c) / MAXPRINTABLE) % MAXPRINTABLE]; + *s = '\0'; + + /* then retreive related info from the attributes if any */ + if (attributes && (attributes->valuemask & XpmColorTable +/* 3.2 backward compatibility code */ + || attributes->valuemask & XpmInfos) +/* end 3.2 bc */ + && attributes->mask_pixel != XpmUndefPixel) { + + unsigned int key; + char **defaults = (char **) color; + char **mask_defaults; + +/* 3.2 backward compatibility code */ + if (attributes->valuemask & XpmColorTable) +/* end 3.2 bc */ + mask_defaults = (char **) ( + attributes->colorTable + attributes->mask_pixel); +/* 3.2 backward compatibility code */ + else + mask_defaults = (char **) + ((XpmColor **) attributes->colorTable)[attributes->mask_pixel]; +/* end 3.2 bc */ + for (key = 1; key <= NKEYS; key++) { + if ((s = mask_defaults[key])) { + defaults[key] = (char *) xpmstrdup(s); + if (!defaults[key]) + return (XpmNoMemory); + } + } + } else { + color->c_color = (char *) xpmstrdup(TRANSPARENT_COLOR); + if (!color->c_color) + return (XpmNoMemory); + } + return (XpmSuccess); +} + +static int +ScanOtherColors( + Display *display, + XpmColor *colors, + unsigned int ncolors, + Pixel *pixels, + unsigned int mask, + unsigned int cpp, + XpmAttributes *attributes) +{ + /* variables stored in the XpmAttributes structure */ + Colormap colormap; + char *rgb_fname; + +#ifndef FOR_MSW + xpmRgbName rgbn[MAX_RGBNAMES]; +#else + xpmRgbName *rgbn = NULL; +#endif + int rgbn_max = 0; + unsigned int i, j, c, i2; + XpmColor *color; + XColor *xcolors = NULL, *xcolor; + char *colorname, *s; + XpmColor *colorTable = NULL, **oldColorTable = NULL; + unsigned int ancolors = 0; + Pixel *apixels = NULL; + unsigned int mask_pixel = 0; + Bool found; + + /* retrieve information from the XpmAttributes */ + if (attributes && (attributes->valuemask & XpmColormap)) + colormap = attributes->colormap; + else + colormap = XDefaultColormap(display, XDefaultScreen(display)); + if (attributes && (attributes->valuemask & XpmRgbFilename)) + rgb_fname = attributes->rgb_fname; + else + rgb_fname = NULL; + + /* start from the right element */ + if (mask) { + colors++; + ncolors--; + pixels++; + } + + /* first get character strings and rgb values */ + if (ncolors >= UINT_MAX / sizeof(XColor) || cpp >= UINT_MAX - 1) + return (XpmNoMemory); + xcolors = (XColor *) XpmMalloc(sizeof(XColor) * ncolors); + if (!xcolors) + return (XpmNoMemory); + + for (i = 0, i2 = mask, color = colors, xcolor = xcolors; + i < ncolors; i++, i2++, color++, xcolor++, pixels++) { + + if (!(s = color->string = (char *) XpmMalloc(cpp + 1))) { + XpmFree(xcolors); + return (XpmNoMemory); + } + *s++ = printable[c = i2 % MAXPRINTABLE]; + for (j = 1; j < cpp; j++, s++) + *s = printable[c = ((i2 - c) / MAXPRINTABLE) % MAXPRINTABLE]; + *s = '\0'; + + xcolor->pixel = *pixels; + } + XQueryColors(display, colormap, xcolors, ncolors); + +#ifndef FOR_MSW + /* read the rgb file if any was specified */ + if (rgb_fname) + rgbn_max = xpmReadRgbNames(attributes->rgb_fname, rgbn); +#else + /* FOR_MSW: rgb names and values are hardcoded in rgbtab.h */ + rgbn_max = xpmReadRgbNames(NULL, NULL); +#endif + + if (attributes && attributes->valuemask & XpmColorTable) { + colorTable = attributes->colorTable; + ancolors = attributes->ncolors; + apixels = attributes->pixels; + mask_pixel = attributes->mask_pixel; + } +/* 3.2 backward compatibility code */ + else if (attributes && attributes->valuemask & XpmInfos) { + oldColorTable = (XpmColor **) attributes->colorTable; + ancolors = attributes->ncolors; + apixels = attributes->pixels; + mask_pixel = attributes->mask_pixel; + } +/* end 3.2 bc */ + + for (i = 0, color = colors, xcolor = xcolors; i < ncolors; + i++, color++, xcolor++) { + + /* look for related info from the attributes if any */ + found = False; + if (ancolors) { + unsigned int offset = 0; + + for (j = 0; j < ancolors; j++) { + if (j == mask_pixel) { + offset = 1; + continue; + } + if (apixels[j - offset] == xcolor->pixel) + break; + } + if (j != ancolors) { + unsigned int key; + char **defaults = (char **) color; + char **adefaults; + +/* 3.2 backward compatibility code */ + if (oldColorTable) + adefaults = (char **) oldColorTable[j]; + else +/* end 3.2 bc */ + adefaults = (char **) (colorTable + j); + + found = True; + for (key = 1; key <= NKEYS; key++) { + if ((s = adefaults[key])) + defaults[key] = (char *) xpmstrdup(s); + } + } + } + if (!found) { + /* if nothing found look for a color name */ + colorname = NULL; + if (rgbn_max) + colorname = xpmGetRgbName(rgbn, rgbn_max, xcolor->red, + xcolor->green, xcolor->blue); + if (colorname) + color->c_color = (char *) xpmstrdup(colorname); + else { + /* at last store the rgb value */ + char buf[BUFSIZ]; +#ifndef FOR_MSW + sprintf(buf, "#%04X%04X%04X", + xcolor->red, xcolor->green, xcolor->blue); +#else + sprintf(buf, "#%02x%02x%02x", + xcolor->red, xcolor->green, xcolor->blue); +#endif + color->c_color = (char *) xpmstrdup(buf); + } + if (!color->c_color) { + XpmFree(xcolors); + xpmFreeRgbNames(rgbn, rgbn_max); + return (XpmNoMemory); + } + } + } + + XpmFree(xcolors); + xpmFreeRgbNames(rgbn, rgbn_max); + return (XpmSuccess); +} + +#ifndef FOR_MSW +# ifndef AMIGA +/* + * The functions below are written from X11R5 MIT's code (XImUtil.c) + * + * The idea is to have faster functions than the standard XGetPixel function + * to scan the image data. Indeed we can speed up things by suppressing tests + * performed for each pixel. We do exactly the same tests but at the image + * level. + */ + +static unsigned long Const low_bits_table[] = { + 0x00000000, 0x00000001, 0x00000003, 0x00000007, + 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f, + 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff, + 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff, + 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff, + 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff, + 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff, + 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff, + 0xffffffff +}; + +/* + * Default method to scan pixels of an image data structure. + * The algorithm used is: + * + * copy the source bitmap_unit or Zpixel into temp + * normalize temp if needed + * extract the pixel bits into return value + * + */ + +static int +GetImagePixels( + XImage *image, + unsigned int width, + unsigned int height, + PixelsMap *pmap) +{ + char *src; + char *dst; + unsigned int *iptr; + char *data; + unsigned int x, y; + int bits, depth, ibu, ibpp, offset, i; + unsigned long lbt; + Pixel pixel, px; + + data = image->data; + iptr = pmap->pixelindex; + depth = image->depth; + lbt = low_bits_table[depth]; + ibpp = image->bits_per_pixel; + offset = image->xoffset; + + if (image->bitmap_unit < 0) + return (XpmNoMemory); + + if ((image->bits_per_pixel | image->depth) == 1) { + ibu = image->bitmap_unit; + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + src = &data[XYINDEX(x, y, image)]; + dst = (char *) &pixel; + pixel = 0; + for (i = ibu >> 3; --i >= 0;) + *dst++ = *src++; + XYNORMALIZE(&pixel, image); + bits = (x + offset) % ibu; + pixel = ((((char *) &pixel)[bits >> 3]) >> (bits & 7)) & 1; + if (ibpp != depth) + pixel &= lbt; + if (storePixel(pixel, pmap, iptr)) + return (XpmNoMemory); + } + } else if (image->format == XYPixmap) { + int nbytes, bpl, j; + long plane = 0; + ibu = image->bitmap_unit; + nbytes = ibu >> 3; + bpl = image->bytes_per_line; + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + pixel = 0; + plane = 0; + for (i = depth; --i >= 0;) { + src = &data[XYINDEX(x, y, image) + plane]; + dst = (char *) &px; + px = 0; + for (j = nbytes; --j >= 0;) + *dst++ = *src++; + XYNORMALIZE(&px, image); + bits = (x + offset) % ibu; + pixel = (pixel << 1) | + (((((char *) &px)[bits >> 3]) >> (bits & 7)) & 1); + plane = plane + (bpl * height); + } + if (ibpp != depth) + pixel &= lbt; + if (storePixel(pixel, pmap, iptr)) + return (XpmNoMemory); + } + } else if (image->format == ZPixmap) { + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + src = &data[ZINDEX(x, y, image)]; + dst = (char *) &px; + px = 0; + for (i = (ibpp + 7) >> 3; --i >= 0;) + *dst++ = *src++; + ZNORMALIZE(&px, image); + pixel = 0; + for (i = sizeof(unsigned long); --i >= 0;) + pixel = (pixel << 8) | ((unsigned char *) &px)[i]; + if (ibpp == 4) { + if (x & 1) + pixel >>= 4; + else + pixel &= 0xf; + } + if (ibpp != depth) + pixel &= lbt; + if (storePixel(pixel, pmap, iptr)) + return (XpmNoMemory); + } + } else + return (XpmColorError); /* actually a bad image */ + return (XpmSuccess); +} + +/* + * scan pixels of a 32-bits Z image data structure + */ + +#if !defined(WORD64) && !defined(LONG64) +static unsigned long byteorderpixel = MSBFirst << 24; +#endif + +static int +GetImagePixels32( + XImage *image, + unsigned int width, + unsigned int height, + PixelsMap *pmap) +{ + unsigned char *addr; + unsigned char *data; + unsigned int *iptr; + unsigned int x, y; + unsigned long lbt; + Pixel pixel; + int depth; + + data = (unsigned char *) image->data; + iptr = pmap->pixelindex; + depth = image->depth; + lbt = low_bits_table[depth]; +#if !defined(WORD64) && !defined(LONG64) + if (*((char *) &byteorderpixel) == image->byte_order) { + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + addr = &data[ZINDEX32(x, y, image)]; + pixel = *((unsigned long *) addr); + if (depth != 32) + pixel &= lbt; + if (storePixel(pixel, pmap, iptr)) + return (XpmNoMemory); + } + } else +#endif + if (image->byte_order == MSBFirst) + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + addr = &data[ZINDEX32(x, y, image)]; + pixel = ((unsigned long) addr[0] << 24 | + (unsigned long) addr[1] << 16 | + (unsigned long) addr[2] << 8 | + addr[3]); + if (depth != 32) + pixel &= lbt; + if (storePixel(pixel, pmap, iptr)) + return (XpmNoMemory); + } + else + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + addr = &data[ZINDEX32(x, y, image)]; + pixel = (addr[0] | + (unsigned long) addr[1] << 8 | + (unsigned long) addr[2] << 16 | + (unsigned long) addr[3] << 24); + if (depth != 32) + pixel &= lbt; + if (storePixel(pixel, pmap, iptr)) + return (XpmNoMemory); + } + return (XpmSuccess); +} + +/* + * scan pixels of a 16-bits Z image data structure + */ + +static int +GetImagePixels16( + XImage *image, + unsigned int width, + unsigned int height, + PixelsMap *pmap) +{ + unsigned char *addr; + unsigned char *data; + unsigned int *iptr; + unsigned int x, y; + unsigned long lbt; + Pixel pixel; + int depth; + + data = (unsigned char *) image->data; + iptr = pmap->pixelindex; + depth = image->depth; + lbt = low_bits_table[depth]; + if (image->byte_order == MSBFirst) + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + addr = &data[ZINDEX16(x, y, image)]; + pixel = addr[0] << 8 | addr[1]; + if (depth != 16) + pixel &= lbt; + if (storePixel(pixel, pmap, iptr)) + return (XpmNoMemory); + } + else + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + addr = &data[ZINDEX16(x, y, image)]; + pixel = addr[0] | addr[1] << 8; + if (depth != 16) + pixel &= lbt; + if (storePixel(pixel, pmap, iptr)) + return (XpmNoMemory); + } + return (XpmSuccess); +} + +/* + * scan pixels of a 8-bits Z image data structure + */ + +static int +GetImagePixels8( + XImage *image, + unsigned int width, + unsigned int height, + PixelsMap *pmap) +{ + unsigned int *iptr; + unsigned char *data; + unsigned int x, y; + unsigned long lbt; + Pixel pixel; + int depth; + + data = (unsigned char *) image->data; + iptr = pmap->pixelindex; + depth = image->depth; + lbt = low_bits_table[depth]; + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + pixel = data[ZINDEX8(x, y, image)]; + if (depth != 8) + pixel &= lbt; + if (storePixel(pixel, pmap, iptr)) + return (XpmNoMemory); + } + return (XpmSuccess); +} + +/* + * scan pixels of a 1-bit depth Z image data structure + */ + +static int +GetImagePixels1( + XImage *image, + unsigned int width, + unsigned int height, + PixelsMap *pmap, + storeFuncPtr storeFunc) +{ + unsigned int *iptr; + unsigned int x, y; + char *data; + Pixel pixel; + int xoff, yoff, offset, bpl; + + data = image->data; + iptr = pmap->pixelindex; + offset = image->xoffset; + bpl = image->bytes_per_line; + + if (image->bitmap_bit_order == MSBFirst) + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + xoff = x + offset; + yoff = y * bpl + (xoff >> 3); + xoff &= 7; + pixel = (data[yoff] & (0x80 >> xoff)) ? 1 : 0; + if ((*storeFunc) (pixel, pmap, iptr)) + return (XpmNoMemory); + } + else + for (y = 0; y < height; y++) + for (x = 0; x < width; x++, iptr++) { + xoff = x + offset; + yoff = y * bpl + (xoff >> 3); + xoff &= 7; + pixel = (data[yoff] & (1 << xoff)) ? 1 : 0; + if ((*storeFunc) (pixel, pmap, iptr)) + return (XpmNoMemory); + } + return (XpmSuccess); +} + +# else /* AMIGA */ + +#define CLEAN_UP(status) \ +do {\ + if (pixels) XpmFree (pixels);\ + if (tmp_img) FreeXImage (tmp_img);\ + return (status);\ +} while(0) + +static int +AGetImagePixels ( + XImage *image, + unsigned int width, + unsigned int height, + PixelsMap *pmap, + int (*storeFunc) (Pixel, PixelsMap *, unsigned int *)) +{ + unsigned int *iptr; + unsigned int x, y; + unsigned char *pixels; + XImage *tmp_img; + + pixels = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*pixels)); + if (pixels == NULL) + return XpmNoMemory; + + tmp_img = AllocXImage ((((width+15)>>4)<<4), 1, image->rp->BitMap->Depth); + if (tmp_img == NULL) + CLEAN_UP (XpmNoMemory); + + iptr = pmap->pixelindex; + for (y = 0; y < height; ++y) + { + ReadPixelLine8 (image->rp, 0, y, width, pixels, tmp_img->rp); + for (x = 0; x < width; ++x, ++iptr) + { + if ((*storeFunc) (pixels[x], pmap, iptr)) + CLEAN_UP (XpmNoMemory); + } + } + + CLEAN_UP (XpmSuccess); +} + +#undef CLEAN_UP + +# endif/* AMIGA */ +#else /* ndef FOR_MSW */ +static int +MSWGetImagePixels( + Display *display, + XImage *image, + unsigned int width, + unsigned int height, + PixelsMap *pmap, + int (*storeFunc) (Pixel, PixelsMap*, unsigned int *)) +{ + unsigned int *iptr; + unsigned int x, y; + Pixel pixel; + + iptr = pmap->pixelindex; + + SelectObject(*display, image->bitmap); + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++, iptr++) { + pixel = GetPixel(*display, x, y); + if ((*storeFunc) (pixel, pmap, iptr)) + return (XpmNoMemory); + } + } + return (XpmSuccess); +} + +#endif + +#ifndef FOR_MSW +# ifndef AMIGA +int +XpmCreateXpmImageFromPixmap( + Display *display, + Pixmap pixmap, + Pixmap shapemask, + XpmImage *xpmimage, + XpmAttributes *attributes) +{ + XImage *ximage = NULL; + XImage *shapeimage = NULL; + unsigned int width = 0; + unsigned int height = 0; + int ErrorStatus; + + /* get geometry */ + if (attributes && attributes->valuemask & XpmSize) { + width = attributes->width; + height = attributes->height; + } + /* get the ximages */ + if (pixmap) + xpmCreateImageFromPixmap(display, pixmap, &ximage, &width, &height); + if (shapemask) + xpmCreateImageFromPixmap(display, shapemask, &shapeimage, + &width, &height); + + /* create the related XpmImage */ + ErrorStatus = XpmCreateXpmImageFromImage(display, ximage, shapeimage, + xpmimage, attributes); + + /* destroy the ximages */ + if (ximage) + XDestroyImage(ximage); + if (shapeimage) + XDestroyImage(shapeimage); + + return (ErrorStatus); +} + +# endif/* not AMIGA */ +#endif /* ndef FOR_MSW */ |