Blame lib/Xm/XpmCrBufFrI.c

Packit b099d7
/* $XConsortium: XpmCrBufFrI.c /main/2 1996/09/20 08:01:31 pascale $ */
Packit b099d7
Packit b099d7
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * Copyright (C) 1989-95 GROUPE BULL
Packit b099d7
 *
Packit b099d7
 * Permission is hereby granted, free of charge, to any person obtaining a copy
Packit b099d7
 * of this software and associated documentation files (the "Software"), to
Packit b099d7
 * deal in the Software without restriction, including without limitation the
Packit b099d7
 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
Packit b099d7
 * sell copies of the Software, and to permit persons to whom the Software is
Packit b099d7
 * furnished to do so, subject to the following conditions:
Packit b099d7
 *
Packit b099d7
 * The above copyright notice and this permission notice shall be included in
Packit b099d7
 * all copies or substantial portions of the Software.
Packit b099d7
 *
Packit b099d7
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit b099d7
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit b099d7
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
Packit b099d7
 * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
Packit b099d7
 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit b099d7
 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit b099d7
 *
Packit b099d7
 * Except as contained in this notice, the name of GROUPE BULL shall not be
Packit b099d7
 * used in advertising or otherwise to promote the sale, use or other dealings
Packit b099d7
 * in this Software without prior written authorization from GROUPE BULL.
Packit b099d7
 */
Packit b099d7
Packit b099d7
/*****************************************************************************\
Packit b099d7
*  CrBufFrI.c:                                                                *
Packit b099d7
*                                                                             *
Packit b099d7
*  XPM library                                                                *
Packit b099d7
*  Scan an image and possibly its mask and create an XPM buffer               *
Packit b099d7
*                                                                             *
Packit b099d7
*  Developed by Arnaud Le Hors                                                *
Packit b099d7
\*****************************************************************************/
Packit b099d7
Packit b099d7
#ifdef HAVE_CONFIG_H
Packit b099d7
#include <config.h>
Packit b099d7
#endif
Packit b099d7
Packit b099d7
Packit b099d7
/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
Packit b099d7
Packit b099d7
#include "XpmI.h"
Packit b099d7
Packit b099d7
LFUNC(WriteColors, int, (char **dataptr, unsigned int *data_size,
Packit b099d7
			 unsigned int *used_size, XpmColor *colors,
Packit b099d7
			 unsigned int ncolors, unsigned int cpp));
Packit b099d7
Packit b099d7
LFUNC(WritePixels, void, (char *dataptr, unsigned int data_size,
Packit b099d7
			  unsigned int *used_size,
Packit b099d7
			  unsigned int width, unsigned int height,
Packit b099d7
			  unsigned int cpp, unsigned int *pixels,
Packit b099d7
			  XpmColor *colors));
Packit b099d7
Packit b099d7
LFUNC(WriteExtensions, void, (char *dataptr, unsigned int data_size,
Packit b099d7
			      unsigned int *used_size,
Packit b099d7
			      XpmExtension *ext, unsigned int num));
Packit b099d7
Packit b099d7
LFUNC(ExtensionsSize, unsigned int, (XpmExtension *ext, unsigned int num));
Packit b099d7
LFUNC(CommentsSize, int, (XpmInfo *info));
Packit b099d7
Packit b099d7
int
Packit b099d7
XpmCreateBufferFromImage(display, buffer_return, image, shapeimage, attributes)
Packit b099d7
    Display *display;
Packit b099d7
    char **buffer_return;
Packit b099d7
    XImage *image;
Packit b099d7
    XImage *shapeimage;
Packit b099d7
    XpmAttributes *attributes;
Packit b099d7
{
Packit b099d7
    XpmImage xpmimage;
Packit b099d7
    XpmInfo info;
Packit b099d7
    int ErrorStatus;
Packit b099d7
Packit b099d7
    /* initialize return value */
Packit b099d7
    if (buffer_return)
Packit b099d7
	*buffer_return = NULL;
Packit b099d7
Packit b099d7
    /* create an XpmImage from the image */
Packit b099d7
    ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
Packit b099d7
					     &xpmimage, attributes);
Packit b099d7
    if (ErrorStatus != XpmSuccess)
Packit b099d7
	return (ErrorStatus);
Packit b099d7
Packit b099d7
    /* create the buffer from the XpmImage */
Packit b099d7
    if (attributes) {
Packit b099d7
	xpmSetInfo(&info, attributes);
Packit b099d7
	ErrorStatus =
Packit b099d7
	    XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, &info;;
Packit b099d7
    } else
Packit b099d7
	ErrorStatus =
Packit b099d7
	    XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, NULL);
Packit b099d7
Packit b099d7
    /* free the XpmImage */
Packit b099d7
    XpmFreeXpmImage(&xpmimage);
Packit b099d7
Packit b099d7
    return (ErrorStatus);
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
#undef RETURN
Packit b099d7
#define RETURN(status) \
Packit b099d7
do { \
Packit b099d7
    if (ptr) \
Packit b099d7
	XpmFree(ptr); \
Packit b099d7
    return(status); \
Packit b099d7
} while(0)
Packit b099d7
Packit b099d7
int
Packit b099d7
XpmCreateBufferFromXpmImage(buffer_return, image, info)
Packit b099d7
    char **buffer_return;
Packit b099d7
    XpmImage *image;
Packit b099d7
    XpmInfo *info;
Packit b099d7
{
Packit b099d7
    /* calculation variables */
Packit b099d7
    int ErrorStatus;
Packit b099d7
    char buf[BUFSIZ];
Packit b099d7
    unsigned int cmts, extensions, ext_size = 0;
Packit b099d7
    unsigned int l, cmt_size = 0;
Packit b099d7
    char *ptr = NULL, *p;
Packit b099d7
    unsigned int ptr_size, used_size, tmp;
Packit b099d7
Packit b099d7
    *buffer_return = NULL;
Packit b099d7
Packit b099d7
    cmts = info && (info->valuemask & XpmComments);
Packit b099d7
    extensions = info && (info->valuemask & XpmExtensions)
Packit b099d7
	&& info->nextensions;
Packit b099d7
Packit b099d7
    /* compute the extensions and comments size */
Packit b099d7
    if (extensions)
Packit b099d7
	ext_size = ExtensionsSize(info->extensions, info->nextensions);
Packit b099d7
    if (cmts)
Packit b099d7
	cmt_size = CommentsSize(info);
Packit b099d7
Packit b099d7
    /* write the header line */
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
    used_size =
Packit b099d7
#endif
Packit b099d7
    sprintf(buf, "/* XPM */\nstatic char * image_name[] = {\n");
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
    used_size = strlen(buf);
Packit b099d7
#endif
Packit b099d7
    ptr_size = used_size + ext_size + cmt_size + 1; /* ptr_size can't be 0 */
Packit b099d7
    if(ptr_size <= used_size ||
Packit b099d7
       ptr_size <= ext_size  ||
Packit b099d7
       ptr_size <= cmt_size)
Packit b099d7
    {
Packit b099d7
        return XpmNoMemory;
Packit b099d7
    }
Packit b099d7
    ptr = (char *) XpmMalloc(ptr_size);
Packit b099d7
    if (!ptr)
Packit b099d7
	return XpmNoMemory;
Packit b099d7
    strcpy(ptr, buf);
Packit b099d7
Packit b099d7
    /* write the values line */
Packit b099d7
    if (cmts && info->hints_cmt) {
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
	used_size +=
Packit b099d7
#endif
Packit b099d7
	snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->hints_cmt);
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
	used_size += strlen(info->hints_cmt) + 5;
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
    l =
Packit b099d7
#endif
Packit b099d7
    sprintf(buf, "\"%d %d %d %d", image->width, image->height,
Packit b099d7
	    image->ncolors, image->cpp);
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
    l = strlen(buf);
Packit b099d7
#endif
Packit b099d7
Packit b099d7
    if (info && (info->valuemask & XpmHotspot)) {
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
	l +=
Packit b099d7
#endif
Packit b099d7
	snprintf(buf + l, sizeof(buf)-l, " %d %d", info->x_hotspot, info->y_hotspot);
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
	l = strlen(buf);
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
    if (extensions) {
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
	l +=
Packit b099d7
#endif
Packit b099d7
	sprintf(buf + l, " XPMEXT");
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
	l = strlen(buf);
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
    l +=
Packit b099d7
#endif
Packit b099d7
    sprintf(buf + l, "\",\n");
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
    l = strlen(buf);
Packit b099d7
#endif
Packit b099d7
    ptr_size += l;
Packit b099d7
    if(ptr_size <= l)
Packit b099d7
        RETURN(XpmNoMemory);
Packit b099d7
    p = (char *) XpmRealloc(ptr, ptr_size);
Packit b099d7
    if (!p)
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
    ptr = p;
Packit b099d7
    strcpy(ptr + used_size, buf);
Packit b099d7
    used_size += l;
Packit b099d7
Packit b099d7
    /* write colors */
Packit b099d7
    if (cmts && info->colors_cmt) {
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
	used_size +=
Packit b099d7
#endif
Packit b099d7
	snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->colors_cmt);
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
	used_size += strlen(info->colors_cmt) + 5;
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
    ErrorStatus = WriteColors(&ptr, &ptr_size, &used_size,
Packit b099d7
			      image->colorTable, image->ncolors, image->cpp);
Packit b099d7
 
Packit b099d7
    if (ErrorStatus != XpmSuccess)
Packit b099d7
	RETURN(ErrorStatus);
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * now we know the exact size we need, realloc the data
Packit b099d7
     * 4 = 1 (for '"') + 3 (for '",\n')
Packit b099d7
     * 1 = - 2 (because the last line does not end with ',\n') + 3 (for '};\n')
Packit b099d7
     */
Packit b099d7
     if(image->width  > UINT_MAX / image->cpp ||
Packit b099d7
       (tmp = image->width * image->cpp + 4) <= 4 ||
Packit b099d7
        image->height > UINT_MAX / tmp ||
Packit b099d7
       (tmp = image->height * tmp + 1) <= 1 ||
Packit b099d7
       (ptr_size += tmp) <= tmp)
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
Packit b099d7
    p = (char *) XpmRealloc(ptr, ptr_size);
Packit b099d7
    if (!p)
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
    ptr = p;
Packit b099d7
Packit b099d7
    /* print pixels */
Packit b099d7
    if (cmts && info->pixels_cmt) {
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
	used_size +=
Packit b099d7
#endif
Packit b099d7
	snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->pixels_cmt);
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
	used_size += strlen(info->pixels_cmt) + 5;
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
    WritePixels(ptr + used_size, ptr_size - used_size, &used_size, image->width, image->height,
Packit b099d7
		image->cpp, image->data, image->colorTable);
Packit b099d7
Packit b099d7
    /* print extensions */
Packit b099d7
    if (extensions)
Packit b099d7
	WriteExtensions(ptr + used_size, ptr_size-used_size, &used_size,
Packit b099d7
			info->extensions, info->nextensions);
Packit b099d7
Packit b099d7
    /* close the array */
Packit b099d7
    strcpy(ptr + used_size, "};\n");
Packit b099d7
Packit b099d7
    *buffer_return = ptr;
Packit b099d7
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
static int
Packit b099d7
WriteColors(dataptr, data_size, used_size, colors, ncolors, cpp)
Packit b099d7
    char **dataptr;
Packit b099d7
    unsigned int *data_size;
Packit b099d7
    unsigned int *used_size;
Packit b099d7
    XpmColor *colors;
Packit b099d7
    unsigned int ncolors;
Packit b099d7
    unsigned int cpp;
Packit b099d7
{
Packit b099d7
    char buf[BUFSIZ] = {0};
Packit b099d7
    unsigned int a, key, l;
Packit b099d7
    char *s, *s2;
Packit b099d7
    char **defaults;
Packit b099d7
Packit b099d7
    *buf = '"';
Packit b099d7
    for (a = 0; a < ncolors; a++, colors++) {
Packit b099d7
Packit b099d7
	defaults = (char **) colors;
Packit b099d7
	s = buf + 1;
Packit b099d7
	if(cpp > (sizeof(buf) - (s-buf)))
Packit b099d7
		return(XpmNoMemory);
Packit b099d7
	strncpy(s, *defaults++, cpp);
Packit b099d7
	s += cpp;
Packit b099d7
Packit b099d7
	for (key = 1; key <= NKEYS; key++, defaults++) {
Packit b099d7
	    if ((s2 = *defaults)) {
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
		s +=
Packit b099d7
#endif
Packit b099d7
		/* assume C99 compliance */
Packit b099d7
		snprintf(s, sizeof(buf) - (s-buf), "\t%s %s", xpmColorKeys[key - 1], s2);
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
		s += strlen(s);
Packit b099d7
#endif
Packit b099d7
		/* now let's check if s points out-of-bounds */
Packit b099d7
		if((s-buf) > sizeof(buf))
Packit b099d7
			return(XpmNoMemory);
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
	if(sizeof(buf) - (s-buf) < 4)
Packit b099d7
		return(XpmNoMemory);
Packit b099d7
	strcpy(s, "\",\n");
Packit b099d7
	l = s + 3 - buf;
Packit b099d7
	if( *data_size                   >= UINT_MAX-l ||
Packit b099d7
	    *data_size + l               <= *used_size ||
Packit b099d7
	   (*data_size + l - *used_size) <= strlen(buf))
Packit b099d7
		return(XpmNoMemory);
Packit b099d7
	s = (char *) XpmRealloc(*dataptr, *data_size + l);
Packit b099d7
	if (!s)
Packit b099d7
	    return (XpmNoMemory);
Packit b099d7
	*data_size += l;
Packit b099d7
	strcpy(s + *used_size, buf);
Packit b099d7
	*used_size += l;
Packit b099d7
	*dataptr = s;
Packit b099d7
    }
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
WritePixels(dataptr, data_size, used_size, width, height, cpp, pixels, colors)
Packit b099d7
    char *dataptr;
Packit b099d7
    unsigned int data_size;
Packit b099d7
    unsigned int *used_size;
Packit b099d7
    unsigned int width;
Packit b099d7
    unsigned int height;
Packit b099d7
    unsigned int cpp;
Packit b099d7
    unsigned int *pixels;
Packit b099d7
    XpmColor *colors;
Packit b099d7
{
Packit b099d7
    char *s = dataptr;
Packit b099d7
    unsigned int x, y, h;
Packit b099d7
Packit b099d7
    if(height <= 1)
Packit b099d7
    	return;
Packit b099d7
Packit b099d7
    h = height - 1;
Packit b099d7
    for (y = 0; y < h; y++) {
Packit b099d7
	*s++ = '"';
Packit b099d7
	for (x = 0; x < width; x++, pixels++) {
Packit b099d7
	    if(cpp >= (data_size - (s-dataptr)))
Packit b099d7
		return;
Packit b099d7
	    strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? :-\ */
Packit b099d7
	    s += cpp;
Packit b099d7
	}
Packit b099d7
	if((data_size - (s-dataptr)) < 4)
Packit b099d7
		return;
Packit b099d7
	strcpy(s, "\",\n");
Packit b099d7
	s += 3;
Packit b099d7
    }
Packit b099d7
    /* duplicate some code to avoid a test in the loop */
Packit b099d7
    *s++ = '"';
Packit b099d7
    for (x = 0; x < width; x++, pixels++) {
Packit b099d7
	if(cpp >= (data_size - (s-dataptr)))
Packit b099d7
	    return;
Packit b099d7
	strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? */
Packit b099d7
	s += cpp;
Packit b099d7
    }
Packit b099d7
    *s++ = '"';
Packit b099d7
    *used_size += s - dataptr;
Packit b099d7
}
Packit b099d7
Packit b099d7
static unsigned int
Packit b099d7
ExtensionsSize(ext, num)
Packit b099d7
    XpmExtension *ext;
Packit b099d7
    unsigned int num;
Packit b099d7
{
Packit b099d7
    unsigned int x, y, a, size;
Packit b099d7
    char **line;
Packit b099d7
Packit b099d7
    size = 0;
Packit b099d7
    if(num == 0)
Packit b099d7
    	return(0); /* ok? */
Packit b099d7
    for (x = 0; x < num; x++, ext++) {
Packit b099d7
	/* 11 = 10 (for ',\n"XPMEXT ') + 1 (for '"') */
Packit b099d7
	size += strlen(ext->name) + 11;
Packit b099d7
	a = ext->nlines; /* how can we trust ext->nlines to be not out-of-bounds? */
Packit b099d7
	for (y = 0, line = ext->lines; y < a; y++, line++)
Packit b099d7
	    /* 4 = 3 (for ',\n"') + 1 (for '"') */
Packit b099d7
	    size += strlen(*line) + 4;
Packit b099d7
    }
Packit b099d7
    /* 13 is for ',\n"XPMENDEXT"' */
Packit b099d7
    if(size > UINT_MAX - 13) /* unlikely */
Packit b099d7
    	return(0);
Packit b099d7
    return size + 13;
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
WriteExtensions(dataptr, data_size, used_size, ext, num)
Packit b099d7
    char *dataptr;
Packit b099d7
    unsigned int data_size;
Packit b099d7
    unsigned int *used_size;
Packit b099d7
    XpmExtension *ext;
Packit b099d7
    unsigned int num;
Packit b099d7
{
Packit b099d7
    unsigned int x, y, a;
Packit b099d7
    char **line;
Packit b099d7
    char *s = dataptr;
Packit b099d7
Packit b099d7
    for (x = 0; x < num; x++, ext++) {
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
	s += 11 +
Packit b099d7
#endif
Packit b099d7
	snprintf(s, data_size - (s-dataptr), ",\n\"XPMEXT %s\"", ext->name);
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
	s += strlen(ext->name) + 11;
Packit b099d7
#endif
Packit b099d7
	a = ext->nlines;
Packit b099d7
	for (y = 0, line = ext->lines; y < a; y++, line++) {
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
	    s += 4 +
Packit b099d7
#endif
Packit b099d7
	    snprintf(s, data_size - (s-dataptr), ",\n\"%s\"", *line);
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
	    s += strlen(*line) + 4;
Packit b099d7
#endif
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
    strncpy(s, ",\n\"XPMENDEXT\"", data_size - (s-dataptr)-1);
Packit b099d7
    *used_size += s - dataptr + 13;
Packit b099d7
}
Packit b099d7
Packit b099d7
static int
Packit b099d7
CommentsSize(info)
Packit b099d7
    XpmInfo *info;
Packit b099d7
{
Packit b099d7
    int size = 0;
Packit b099d7
Packit b099d7
    /* 5 = 2 (for "/_*") + 3 (for "*_/\n") */
Packit b099d7
    /* wrap possible but *very* unlikely */
Packit b099d7
    if (info->hints_cmt)
Packit b099d7
	size += 5 + strlen(info->hints_cmt);
Packit b099d7
Packit b099d7
    if (info->colors_cmt)
Packit b099d7
	size += 5 + strlen(info->colors_cmt);
Packit b099d7
Packit b099d7
    if (info->pixels_cmt)
Packit b099d7
	size += 5 + strlen(info->pixels_cmt);
Packit b099d7
Packit b099d7
    return size;
Packit b099d7
}