Blame lib/Xm/XpmCrDatFrI.c

Packit b099d7
/* $XConsortium: XpmCrDatFrI.c /main/2 1996/09/20 08:01:45 pascale $ */
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
*  CrDataFI.c:                                                                *
Packit b099d7
*                                                                             *
Packit b099d7
*  XPM library                                                                *
Packit b099d7
*  Scan an image and possibly its mask and create an XPM array                *
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(CreateColors, int, (char **dataptr, unsigned int *data_size,
Packit b099d7
			  XpmColor *colors, unsigned int ncolors,
Packit b099d7
			  unsigned int cpp));
Packit b099d7
Packit b099d7
LFUNC(CreatePixels, void, (char **dataptr, unsigned int data_size,
Packit b099d7
			   unsigned int width,
Packit b099d7
			   unsigned int height, unsigned int cpp,
Packit b099d7
			   unsigned int *pixels, XpmColor *colors));
Packit b099d7
Packit b099d7
LFUNC(CountExtensions, void, (XpmExtension *ext, unsigned int num,
Packit b099d7
			      unsigned int *ext_size,
Packit b099d7
			      unsigned int *ext_nlines));
Packit b099d7
Packit b099d7
LFUNC(CreateExtensions, void, (char **dataptr, unsigned int data_size,
Packit b099d7
			       unsigned int offset,
Packit b099d7
			       XpmExtension *ext, unsigned int num,
Packit b099d7
			       unsigned int ext_nlines));
Packit b099d7
Packit b099d7
int
Packit b099d7
XpmCreateDataFromImage(display, data_return, image, shapeimage, attributes)
Packit b099d7
    Display *display;
Packit b099d7
    char ***data_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 (data_return)
Packit b099d7
	*data_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 data from the XpmImage */
Packit b099d7
    if (attributes) {
Packit b099d7
	xpmSetInfo(&info, attributes);
Packit b099d7
	ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info;;
Packit b099d7
    } else
Packit b099d7
	ErrorStatus = XpmCreateDataFromXpmImage(data_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
#undef RETURN
Packit b099d7
#define RETURN(status) \
Packit b099d7
do { \
Packit b099d7
    if (header) { \
Packit b099d7
	for (l = 0; l < header_nlines; l++) \
Packit b099d7
	    if (header[l]) \
Packit b099d7
		XpmFree(header[l]); \
Packit b099d7
		XpmFree(header); \
Packit b099d7
    } \
Packit b099d7
    return(status); \
Packit b099d7
} while(0)
Packit b099d7
Packit b099d7
int
Packit b099d7
XpmCreateDataFromXpmImage(data_return, image, info)
Packit b099d7
    char ***data_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
    char **header = NULL, **data, **sptr, **sptr2, *s;
Packit b099d7
    unsigned int header_size, header_nlines;
Packit b099d7
    unsigned int data_size, data_nlines;
Packit b099d7
    unsigned int extensions = 0, ext_size = 0, ext_nlines = 0;
Packit b099d7
    unsigned int offset, l, n;
Packit b099d7
Packit b099d7
    *data_return = NULL;
Packit b099d7
Packit b099d7
    extensions = info && (info->valuemask & XpmExtensions)
Packit b099d7
	&& info->nextensions;
Packit b099d7
Packit b099d7
    /* compute the number of extensions lines and size */
Packit b099d7
    if (extensions)
Packit b099d7
	CountExtensions(info->extensions, info->nextensions,
Packit b099d7
			&ext_size, &ext_nlines);
Packit b099d7
Packit b099d7
    /*
Packit b099d7
     * alloc a temporary array of char pointer for the header section which
Packit b099d7
     * is the hints line + the color table lines
Packit b099d7
     */
Packit b099d7
    header_nlines = 1 + image->ncolors;
Packit b099d7
    if(header_nlines <= image->ncolors ||
Packit b099d7
       header_nlines >= UINT_MAX / sizeof(char *))
Packit b099d7
      return(XpmNoMemory);
Packit b099d7
    header_size = sizeof(char *) * header_nlines;
Packit b099d7
    if (header_size >= UINT_MAX / sizeof(char *))
Packit b099d7
	return (XpmNoMemory);
Packit b099d7
    header = (char **) XpmCalloc(header_size, sizeof(char *));
Packit b099d7
    if (!header)
Packit b099d7
	return (XpmNoMemory);
Packit b099d7
Packit b099d7
    /* print the hints line */
Packit b099d7
    s = buf;
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
    s +=
Packit b099d7
#endif
Packit b099d7
    sprintf(s, "%d %d %d %d", image->width, image->height,
Packit b099d7
	    image->ncolors, image->cpp);
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
    s += strlen(s);
Packit b099d7
#endif
Packit b099d7
Packit b099d7
    if (info && (info->valuemask & XpmHotspot)) {
Packit b099d7
#ifndef VOID_SPRINTF
Packit b099d7
	s +=
Packit b099d7
#endif
Packit b099d7
	sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot);
Packit b099d7
#ifdef VOID_SPRINTF
Packit b099d7
	s += strlen(s);
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
    if (extensions) {
Packit b099d7
	strcpy(s, " XPMEXT");
Packit b099d7
	s += 7;
Packit b099d7
    }
Packit b099d7
    l = s - buf + 1;
Packit b099d7
    *header = (char *) XpmMalloc(l);
Packit b099d7
    if (!*header)
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
    header_size += l;
Packit b099d7
    strcpy(*header, buf);
Packit b099d7
Packit b099d7
    /* print colors */
Packit b099d7
    ErrorStatus = CreateColors(header + 1, &header_size,
Packit b099d7
			       image->colorTable, image->ncolors, image->cpp);
Packit b099d7
Packit b099d7
    if (ErrorStatus != XpmSuccess)
Packit b099d7
	RETURN(ErrorStatus);
Packit b099d7
Packit b099d7
    /* now we know the size needed, alloc the data and copy the header lines */
Packit b099d7
    offset = image->width * image->cpp + 1;
Packit b099d7
Packit b099d7
    if(offset <= image->width || offset <= image->cpp)
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
Packit b099d7
    if( (image->height + ext_nlines) >= UINT_MAX / sizeof(char *))
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
    data_size = (image->height + ext_nlines) * sizeof(char *);
Packit b099d7
Packit b099d7
    if (image->height > UINT_MAX / offset ||
Packit b099d7
        image->height * offset > UINT_MAX - data_size)
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
    data_size += image->height * offset;
Packit b099d7
Packit b099d7
    if( (header_size + ext_size) >= (UINT_MAX - data_size) )
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
    data_size += header_size + ext_size;
Packit b099d7
Packit b099d7
    data = (char **) XpmMalloc(data_size);
Packit b099d7
    if (!data)
Packit b099d7
	RETURN(XpmNoMemory);
Packit b099d7
Packit b099d7
    data_nlines = header_nlines + image->height + ext_nlines;
Packit b099d7
    *data = (char *) (data + data_nlines);
Packit b099d7
Packit b099d7
    /* can header have less elements then n suggests? */
Packit b099d7
    n = image->ncolors;
Packit b099d7
    for (l = 0, sptr = data, sptr2 = header; l <= n && sptr && sptr2; l++, sptr++, sptr2++) {
Packit b099d7
	strcpy(*sptr, *sptr2);
Packit b099d7
	*(sptr + 1) = *sptr + strlen(*sptr2) + 1;
Packit b099d7
    }
Packit b099d7
Packit b099d7
    /* print pixels */
Packit b099d7
    data[header_nlines] = (char *) data + header_size
Packit b099d7
	+ (image->height + ext_nlines) * sizeof(char *);
Packit b099d7
Packit b099d7
    CreatePixels(data + header_nlines, data_size-header_nlines, image->width, image->height,
Packit b099d7
		 image->cpp, image->data, image->colorTable);
Packit b099d7
Packit b099d7
    /* print extensions */
Packit b099d7
    if (extensions)
Packit b099d7
	CreateExtensions(data + header_nlines + image->height - 1,
Packit b099d7
			 data_size - header_nlines - image->height + 1, offset,
Packit b099d7
			 info->extensions, info->nextensions,
Packit b099d7
			 ext_nlines);
Packit b099d7
Packit b099d7
    *data_return = data;
Packit b099d7
Packit b099d7
    RETURN(XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
static int
Packit b099d7
CreateColors(dataptr, data_size, colors, ncolors, cpp)
Packit b099d7
    char **dataptr;
Packit b099d7
    unsigned int *data_size;
Packit b099d7
    XpmColor *colors;
Packit b099d7
    unsigned int ncolors;
Packit b099d7
    unsigned int cpp;
Packit b099d7
{
Packit b099d7
    char buf[BUFSIZ];
Packit b099d7
    unsigned int a, key, l;
Packit b099d7
    char *s, *s2;
Packit b099d7
    char **defaults;
Packit b099d7
Packit b099d7
    /* can ncolors be trusted here? */
Packit b099d7
    for (a = 0; a < ncolors; a++, colors++, dataptr++) {
Packit b099d7
Packit b099d7
	defaults = (char **) colors;
Packit b099d7
 	if(sizeof(buf) <= cpp)
Packit b099d7
	    return(XpmNoMemory);
Packit b099d7
	strncpy(buf, *defaults++, cpp);
Packit b099d7
	s = buf + cpp;
Packit b099d7
Packit b099d7
 	if(sizeof(buf) <= (s-buf))
Packit b099d7
	    return XpmNoMemory;
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
	    }
Packit b099d7
	}
Packit b099d7
 	/* what about using strdup()? */
Packit b099d7
	l = s - buf + 1;
Packit b099d7
	s = (char *) XpmMalloc(l);
Packit b099d7
	if (!s)
Packit b099d7
	    return (XpmNoMemory);
Packit b099d7
	*data_size += l;
Packit b099d7
	*dataptr = strcpy(s, buf);
Packit b099d7
    }
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
CreatePixels(dataptr, data_size, width, height, cpp, pixels, colors)
Packit b099d7
    char **dataptr;
Packit b099d7
    unsigned int data_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;
Packit b099d7
    unsigned int x, y, h, offset;
Packit b099d7
Packit b099d7
    if(height <= 1)
Packit b099d7
    	return;
Packit b099d7
Packit b099d7
    h = height - 1;
Packit b099d7
Packit b099d7
    offset = width * cpp + 1;
Packit b099d7
Packit b099d7
    if(offset <= width || offset <= cpp)
Packit b099d7
    	return;
Packit b099d7
Packit b099d7
    /* why trust h? */
Packit b099d7
    for (y = 0; y < h; y++, dataptr++) {
Packit b099d7
	s = *dataptr;
Packit b099d7
	/* why trust width? */
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); /* why trust pixel? */
Packit b099d7
	    s += cpp;
Packit b099d7
	}
Packit b099d7
	*s = '\0';
Packit b099d7
	if(offset > data_size)
Packit b099d7
		return;
Packit b099d7
	*(dataptr + 1) = *dataptr + offset;
Packit b099d7
    }
Packit b099d7
    /* duplicate some code to avoid a test in the loop */
Packit b099d7
    s = *dataptr;
Packit b099d7
    /* why trust width? */
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); /* why should we trust *pixel? */
Packit b099d7
	s += cpp;
Packit b099d7
    }
Packit b099d7
    *s = '\0';
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
CountExtensions(ext, num, ext_size, ext_nlines)
Packit b099d7
    XpmExtension *ext;
Packit b099d7
    unsigned int num;
Packit b099d7
    unsigned int *ext_size;
Packit b099d7
    unsigned int *ext_nlines;
Packit b099d7
{
Packit b099d7
    unsigned int x, y, a, size, nlines;
Packit b099d7
    char **line;
Packit b099d7
Packit b099d7
    size = 0;
Packit b099d7
    nlines = 0;
Packit b099d7
    for (x = 0; x < num; x++, ext++) {
Packit b099d7
	/* 1 for the name */
Packit b099d7
	nlines += ext->nlines + 1;
Packit b099d7
	/* 8 = 7 (for "XPMEXT ") + 1 (for 0) */
Packit b099d7
	size += strlen(ext->name) + 8;
Packit b099d7
	a = ext->nlines;
Packit b099d7
	for (y = 0, line = ext->lines; y < a; y++, line++)
Packit b099d7
	    size += strlen(*line) + 1;
Packit b099d7
    }
Packit b099d7
    /* 10 and 1 are for the ending "XPMENDEXT" */
Packit b099d7
    *ext_size = size + 10;
Packit b099d7
    *ext_nlines = nlines + 1;
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
CreateExtensions(dataptr, data_size, offset, ext, num, ext_nlines)
Packit b099d7
    char **dataptr;
Packit b099d7
    unsigned int data_size;
Packit b099d7
    unsigned int offset;
Packit b099d7
    XpmExtension *ext;
Packit b099d7
    unsigned int num;
Packit b099d7
    unsigned int ext_nlines;
Packit b099d7
{
Packit b099d7
    unsigned int x, y, a, b;
Packit b099d7
    char **line;
Packit b099d7
Packit b099d7
    *(dataptr + 1) = *dataptr + offset;
Packit b099d7
    dataptr++;
Packit b099d7
    a = 0;
Packit b099d7
    for (x = 0; x < num; x++, ext++) {
Packit b099d7
	snprintf(*dataptr, data_size, "XPMEXT %s", ext->name);
Packit b099d7
	a++;
Packit b099d7
	if (a < ext_nlines)
Packit b099d7
	    *(dataptr + 1) = *dataptr + strlen(ext->name) + 8;
Packit b099d7
	dataptr++;
Packit b099d7
	b = ext->nlines; /* can we trust these values? */
Packit b099d7
	for (y = 0, line = ext->lines; y < b; y++, line++) {
Packit b099d7
	    strcpy(*dataptr, *line);
Packit b099d7
	    a++;
Packit b099d7
	    if (a < ext_nlines)
Packit b099d7
		*(dataptr + 1) = *dataptr + strlen(*line) + 1;
Packit b099d7
	    dataptr++;
Packit b099d7
	}
Packit b099d7
    }
Packit b099d7
    strcpy(*dataptr, "XPMENDEXT");
Packit b099d7
}