Blame lib/Xm/XpmWrFFrI.c

Packit b099d7
/* $TOG: XpmWrFFrI.c /main/3 1998/07/22 15:43:49 mgreess $ */
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
*  WrFFrI.c:                                                                  *
Packit b099d7
*                                                                             *
Packit b099d7
*  XPM library                                                                *
Packit b099d7
*  Write an image and possibly its mask to an XPM file                        *
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
#if !defined(NO_ZPIPE) && defined(WIN32)
Packit b099d7
# define popen _popen
Packit b099d7
# define pclose _pclose
Packit b099d7
#endif
Packit b099d7
Packit b099d7
/* MS Windows define a function called WriteFile @#%#&!!! */
Packit b099d7
LFUNC(xpmWriteFile, int, (FILE *file, XpmImage *image, char *name,
Packit b099d7
			  XpmInfo *info));
Packit b099d7
Packit b099d7
LFUNC(WriteColors, void, (FILE *file, XpmColor *colors, unsigned int ncolors));
Packit b099d7
Packit b099d7
LFUNC(WritePixels, int, (FILE *file, 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, (FILE *file, XpmExtension *ext,
Packit b099d7
			      unsigned int num));
Packit b099d7
Packit b099d7
LFUNC(OpenWriteFile, int, (char *filename, xpmData *mdata));
Packit b099d7
LFUNC(xpmDataClose, void, (xpmData *mdata));
Packit b099d7
Packit b099d7
int
Packit b099d7
XpmWriteFileFromImage(display, filename, image, shapeimage, attributes)
Packit b099d7
    Display *display;
Packit b099d7
    char *filename;
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
    /* 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
    /* write the file from the XpmImage */
Packit b099d7
    if (attributes) {
Packit b099d7
	xpmSetInfo(&info, attributes);
Packit b099d7
	ErrorStatus = XpmWriteFileFromXpmImage(filename, &xpmimage, &info;;
Packit b099d7
    } else
Packit b099d7
	ErrorStatus = XpmWriteFileFromXpmImage(filename, &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
int
Packit b099d7
XpmWriteFileFromXpmImage(filename, image, info)
Packit b099d7
    char *filename;
Packit b099d7
    XpmImage *image;
Packit b099d7
    XpmInfo *info;
Packit b099d7
{
Packit b099d7
    xpmData mdata;
Packit b099d7
    char *name, *dot, *s, new_name[BUFSIZ] = {0};
Packit b099d7
    int ErrorStatus;
Packit b099d7
Packit b099d7
    /* open file to write */
Packit b099d7
    if ((ErrorStatus = OpenWriteFile(filename, &mdata)) != XpmSuccess)
Packit b099d7
	return (ErrorStatus);
Packit b099d7
Packit b099d7
    /* figure out a name */
Packit b099d7
    if (filename) {
Packit b099d7
#ifdef VMS
Packit b099d7
	name = filename;
Packit b099d7
#else
Packit b099d7
	if (!(name = rindex(filename, '/')))
Packit b099d7
	    name = filename;
Packit b099d7
	else
Packit b099d7
	    name++;
Packit b099d7
#endif
Packit b099d7
	/* let's try to make a valid C syntax name */
Packit b099d7
	if ((dot = index(name, '.'))) {
Packit b099d7
 	    strncpy(new_name, name, sizeof(new_name));
Packit b099d7
 	    new_name[sizeof(new_name)-1] = 0;
Packit b099d7
	    /* change '.' to '_' */
Packit b099d7
	    name = s = new_name;
Packit b099d7
	    while ((dot = index(s, '.'))) {
Packit b099d7
		*dot = '_';
Packit b099d7
		s = dot;
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
	if ((dot = index(name, '-'))) {
Packit b099d7
	    if (name != new_name) {
Packit b099d7
		strncpy(new_name, name, sizeof(new_name));
Packit b099d7
		new_name[sizeof(new_name)-1] = 0;
Packit b099d7
		name = new_name;
Packit b099d7
	    }
Packit b099d7
	    /* change '-' to '_' */
Packit b099d7
	    s = name;
Packit b099d7
	    while ((dot = index(s, '-'))) {
Packit b099d7
		*dot = '_';
Packit b099d7
		s = dot;
Packit b099d7
	    }
Packit b099d7
	}
Packit b099d7
    } else
Packit b099d7
	name = "image_name";
Packit b099d7
Packit b099d7
    /* write the XpmData from the XpmImage */
Packit b099d7
    if (ErrorStatus == XpmSuccess)
Packit b099d7
	ErrorStatus = xpmWriteFile(mdata.stream.file, image, name, info);
Packit b099d7
Packit b099d7
    xpmDataClose(&mdata);
Packit b099d7
Packit b099d7
    return (ErrorStatus);
Packit b099d7
}
Packit b099d7
Packit b099d7
static int
Packit b099d7
xpmWriteFile(file, image, name, info)
Packit b099d7
    FILE *file;
Packit b099d7
    XpmImage *image;
Packit b099d7
    char *name;
Packit b099d7
    XpmInfo *info;
Packit b099d7
{
Packit b099d7
    /* calculation variables */
Packit b099d7
    unsigned int cmts, extensions;
Packit b099d7
    int ErrorStatus;
Packit b099d7
Packit b099d7
    cmts = info && (info->valuemask & XpmComments);
Packit b099d7
    extensions = info && (info->valuemask & XpmExtensions)
Packit b099d7
	&& info->nextensions;
Packit b099d7
Packit b099d7
    /* print the header line */
Packit b099d7
    fprintf(file, "/* XPM */\nstatic char * %s[] = {\n", name);
Packit b099d7
Packit b099d7
    /* print the hints line */
Packit b099d7
    if (cmts && info->hints_cmt)
Packit b099d7
	fprintf(file, "/*%s*/\n", info->hints_cmt);
Packit b099d7
Packit b099d7
    fprintf(file, "\"%d %d %d %d", image->width, image->height,
Packit b099d7
	    image->ncolors, image->cpp);
Packit b099d7
Packit b099d7
    if (info && (info->valuemask & XpmHotspot))
Packit b099d7
	fprintf(file, " %d %d", info->x_hotspot, info->y_hotspot);
Packit b099d7
Packit b099d7
    if (extensions)
Packit b099d7
	fprintf(file, " XPMEXT");
Packit b099d7
Packit b099d7
    fprintf(file, "\",\n");
Packit b099d7
Packit b099d7
    /* print colors */
Packit b099d7
    if (cmts && info->colors_cmt)
Packit b099d7
	fprintf(file, "/*%s*/\n", info->colors_cmt);
Packit b099d7
Packit b099d7
    WriteColors(file, image->colorTable, image->ncolors);
Packit b099d7
Packit b099d7
    /* print pixels */
Packit b099d7
    if (cmts && info->pixels_cmt)
Packit b099d7
	fprintf(file, "/*%s*/\n", info->pixels_cmt);
Packit b099d7
Packit b099d7
    ErrorStatus = WritePixels(file, image->width, image->height, image->cpp,
Packit b099d7
			      image->data, image->colorTable);
Packit b099d7
    if (ErrorStatus != XpmSuccess)
Packit b099d7
	return (ErrorStatus);
Packit b099d7
Packit b099d7
    /* print extensions */
Packit b099d7
    if (extensions)
Packit b099d7
	WriteExtensions(file, info->extensions, info->nextensions);
Packit b099d7
Packit b099d7
    /* close the array */
Packit b099d7
    fprintf(file, "};\n");
Packit b099d7
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
WriteColors(file, colors, ncolors)
Packit b099d7
    FILE *file;
Packit b099d7
    XpmColor *colors;
Packit b099d7
    unsigned int ncolors;
Packit b099d7
{
Packit b099d7
    unsigned int a, key;
Packit b099d7
    char *s;
Packit b099d7
    char **defaults;
Packit b099d7
Packit b099d7
    for (a = 0; a < ncolors; a++, colors++) {
Packit b099d7
Packit b099d7
	defaults = (char **) colors;
Packit b099d7
	fprintf(file, "\"%s", *defaults++);
Packit b099d7
Packit b099d7
	for (key = 1; key <= NKEYS; key++, defaults++) {
Packit b099d7
	    if ((s = *defaults))
Packit b099d7
		fprintf(file, "\t%s %s", xpmColorKeys[key - 1], s);
Packit b099d7
	}
Packit b099d7
	fprintf(file, "\",\n");
Packit b099d7
    }
Packit b099d7
}
Packit b099d7
Packit b099d7
Packit b099d7
static int
Packit b099d7
WritePixels(file, width, height, cpp, pixels, colors)
Packit b099d7
    FILE *file;
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, *p, *buf;
Packit b099d7
    unsigned int x, y, h;
Packit b099d7
Packit b099d7
    h = height - 1;
Packit b099d7
    if (cpp != 0 && width >= (UINT_MAX - 3)/cpp) 
Packit b099d7
	return XpmNoMemory;    
Packit b099d7
    p = buf = (char *) XpmMalloc(width * cpp + 3);
Packit b099d7
    if (!buf)
Packit b099d7
	return (XpmNoMemory);
Packit b099d7
    *buf = '"';
Packit b099d7
    p++;
Packit b099d7
    for (y = 0; y < h; y++) {
Packit b099d7
	s = p;
Packit b099d7
	for (x = 0; x < width; x++, pixels++) {
Packit b099d7
	    strncpy(s, colors[*pixels].string, cpp);
Packit b099d7
	    s += cpp;
Packit b099d7
	}
Packit b099d7
	*s++ = '"';
Packit b099d7
	*s = '\0';
Packit b099d7
	fprintf(file, "%s,\n", buf);
Packit b099d7
    }
Packit b099d7
    /* duplicate some code to avoid a test in the loop */
Packit b099d7
    s = p;
Packit b099d7
    for (x = 0; x < width; x++, pixels++) {
Packit b099d7
	strncpy(s, colors[*pixels].string, cpp);
Packit b099d7
	s += cpp;
Packit b099d7
    }
Packit b099d7
    *s++ = '"';
Packit b099d7
    *s = '\0';
Packit b099d7
    fprintf(file, "%s", buf);
Packit b099d7
Packit b099d7
    XpmFree(buf);
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
static void
Packit b099d7
WriteExtensions(file, ext, num)
Packit b099d7
    FILE *file;
Packit b099d7
    XpmExtension *ext;
Packit b099d7
    unsigned int num;
Packit b099d7
{
Packit b099d7
    unsigned int x, y, n;
Packit b099d7
    char **line;
Packit b099d7
Packit b099d7
    for (x = 0; x < num; x++, ext++) {
Packit b099d7
	fprintf(file, ",\n\"XPMEXT %s\"", ext->name);
Packit b099d7
	n = ext->nlines;
Packit b099d7
	for (y = 0, line = ext->lines; y < n; y++, line++)
Packit b099d7
	    fprintf(file, ",\n\"%s\"", *line);
Packit b099d7
    }
Packit b099d7
    fprintf(file, ",\n\"XPMENDEXT\"");
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * open the given file to be written as an xpmData which is returned
Packit b099d7
 */
Packit b099d7
#ifndef NO_ZPIPE
Packit b099d7
	FILE *Xpms_popen(char *cmd, const char *type);
Packit b099d7
#else
Packit b099d7
#	define Xpms_popen popen
Packit b099d7
#endif
Packit b099d7
static int
Packit b099d7
OpenWriteFile(filename, mdata)
Packit b099d7
    char *filename;
Packit b099d7
    xpmData *mdata;
Packit b099d7
{
Packit b099d7
#ifndef NO_ZPIPE
Packit b099d7
    char buf[BUFSIZ];
Packit b099d7
Packit b099d7
#endif
Packit b099d7
Packit b099d7
    if (!filename) {
Packit b099d7
	mdata->stream.file = (stdout);
Packit b099d7
	mdata->type = XPMFILE;
Packit b099d7
    } else {
Packit b099d7
#ifndef NO_ZPIPE
Packit b099d7
	size_t len = strlen(filename);
Packit b099d7
Packit b099d7
	if(len == 0)
Packit b099d7
		return(XpmOpenFailed);
Packit b099d7
Packit b099d7
	if (len > 2 && !strcmp(".Z", filename + (len - 2))) {
Packit b099d7
	    snprintf(buf, sizeof(buf), "compress > \"%s\"", filename);
Packit b099d7
	    if (!(mdata->stream.file = Xpms_popen(buf, "w")))
Packit b099d7
		return (XpmOpenFailed);
Packit b099d7
Packit b099d7
	    mdata->type = XPMPIPE;
Packit b099d7
	} else if (len > 3 && !strcmp(".gz", filename + (len - 3))) {
Packit b099d7
	    snprintf(buf, sizeof(buf), "gzip -q > \"%s\"", filename);
Packit b099d7
	    if (!(mdata->stream.file = Xpms_popen(buf, "w")))
Packit b099d7
		return (XpmOpenFailed);
Packit b099d7
Packit b099d7
	    mdata->type = XPMPIPE;
Packit b099d7
	} else {
Packit b099d7
#endif
Packit b099d7
	    if (!(mdata->stream.file = fopen(filename, "w")))
Packit b099d7
		return (XpmOpenFailed);
Packit b099d7
Packit b099d7
	    mdata->type = XPMFILE;
Packit b099d7
#ifndef NO_ZPIPE
Packit b099d7
	}
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
    return (XpmSuccess);
Packit b099d7
}
Packit b099d7
Packit b099d7
/*
Packit b099d7
 * close the file related to the xpmData if any
Packit b099d7
 */
Packit b099d7
static void
Packit b099d7
xpmDataClose(mdata)
Packit b099d7
    xpmData *mdata;
Packit b099d7
{
Packit b099d7
    switch (mdata->type) {
Packit b099d7
    case XPMFILE:
Packit b099d7
	if (mdata->stream.file != (stdout))
Packit b099d7
	    fclose(mdata->stream.file);
Packit b099d7
	break;
Packit b099d7
#ifndef NO_ZPIPE
Packit b099d7
    case XPMPIPE:
Packit b099d7
	fclose(mdata->stream.file);
Packit b099d7
	break;
Packit b099d7
#endif
Packit b099d7
    }
Packit b099d7
}