Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  * Copyright (C) 1989-95 GROUPE BULL
      3  *
      4  * Permission is hereby granted, free of charge, to any person obtaining a copy
      5  * of this software and associated documentation files (the "Software"), to
      6  * deal in the Software without restriction, including without limitation the
      7  * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
      8  * sell copies of the Software, and to permit persons to whom the Software is
      9  * furnished to do so, subject to the following conditions:
     10  *
     11  * The above copyright notice and this permission notice shall be included in
     12  * all copies or substantial portions of the Software.
     13  *
     14  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     17  * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     18  * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     19  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20  *
     21  * Except as contained in this notice, the name of GROUPE BULL shall not be
     22  * used in advertising or otherwise to promote the sale, use or other dealings
     23  * in this Software without prior written authorization from GROUPE BULL.
     24  */
     25 
     26 /*****************************************************************************\
     27 *  WrFFrI.c:                                                                  *
     28 *                                                                             *
     29 *  XPM library                                                                *
     30 *  Write an image and possibly its mask to an XPM file                        *
     31 *                                                                             *
     32 *  Developed by Arnaud Le Hors                                                *
     33 \*****************************************************************************/
     34 
     35 #ifdef HAVE_CONFIG_H
     36 #include <config.h>
     37 #endif
     38 #include "XpmI.h"
     39 
     40 #ifndef NO_ZPIPE
     41 #include "sys/wait.h"
     42 #include "sys/types.h"
     43 #include "unistd.h"
     44 #include "errno.h"
     45 #endif
     46 
     47 #include "fcntl.h"
     48 
     49 /* MS Windows define a function called WriteFile @#%#&!!! */
     50 LFUNC(xpmWriteFile, int, (FILE *file, XpmImage *image, const char *name,
     51 			  XpmInfo *info));
     52 
     53 LFUNC(WriteColors, void, (FILE *file, XpmColor *colors, unsigned int ncolors));
     54 
     55 LFUNC(WritePixels, int, (FILE *file, unsigned int width, unsigned int height,
     56 			 unsigned int cpp, unsigned int *pixels,
     57 			 XpmColor *colors));
     58 
     59 LFUNC(WriteExtensions, void, (FILE *file, XpmExtension *ext,
     60 			      unsigned int num));
     61 
     62 LFUNC(OpenWriteFile, int, (const char *filename, xpmData *mdata));
     63 LFUNC(xpmDataClose, void, (xpmData *mdata));
     64 
     65 int
     66 XpmWriteFileFromImage(
     67     Display		*display,
     68     const char		*filename,
     69     XImage		*image,
     70     XImage		*shapeimage,
     71     XpmAttributes	*attributes)
     72 {
     73     XpmImage xpmimage;
     74     XpmInfo info;
     75     int ErrorStatus;
     76 
     77     /* create an XpmImage from the image */
     78     ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
     79 					     &xpmimage, attributes);
     80     if (ErrorStatus != XpmSuccess)
     81 	return (ErrorStatus);
     82 
     83     /* write the file from the XpmImage */
     84     if (attributes) {
     85 	xpmSetInfo(&info, attributes);
     86 	ErrorStatus = XpmWriteFileFromXpmImage(filename, &xpmimage, &info);
     87     } else
     88 	ErrorStatus = XpmWriteFileFromXpmImage(filename, &xpmimage, NULL);
     89 
     90     /* free the XpmImage */
     91     XpmFreeXpmImage(&xpmimage);
     92 
     93     return (ErrorStatus);
     94 }
     95 
     96 int
     97 XpmWriteFileFromXpmImage(
     98     const char	*filename,
     99     XpmImage	*image,
    100     XpmInfo	*info)
    101 {
    102     xpmData mdata;
    103     const char *name;
    104     char *dot, *s, new_name[BUFSIZ] = {0};
    105     int ErrorStatus;
    106 
    107     /* open file to write */
    108     if ((ErrorStatus = OpenWriteFile(filename, &mdata)) != XpmSuccess)
    109 	return (ErrorStatus);
    110 
    111     /* figure out a name */
    112     if (filename) {
    113 #ifdef VMS
    114 	name = filename;
    115 #else
    116 	if (!(name = strrchr(filename, '/')))
    117 	    name = filename;
    118 	else
    119 	    name++;
    120 #endif
    121 	/* let's try to make a valid C syntax name */
    122 	if (strchr(name, '.')) {
    123 	    strncpy(new_name, name, sizeof(new_name));
    124 	    new_name[sizeof(new_name)-1] = '\0';
    125 	    /* change '.' to '_' */
    126 	    name = s = new_name;
    127 	    while ((dot = strchr(s, '.'))) {
    128 		*dot = '_';
    129 		s = dot;
    130 	    }
    131 	}
    132 	if (strchr(name, '-')) {
    133 	    if (name != new_name) {
    134 		strncpy(new_name, name, sizeof(new_name));
    135 		new_name[sizeof(new_name)-1] = '\0';
    136 		name = new_name;
    137 	    }
    138 	    /* change '-' to '_' */
    139 	    s = new_name;
    140 	    while ((dot = strchr(s, '-'))) {
    141 		*dot = '_';
    142 		s = dot;
    143 	    }
    144 	}
    145     } else
    146 	name = "image_name";
    147 
    148     /* write the XpmData from the XpmImage */
    149     if (ErrorStatus == XpmSuccess)
    150 	ErrorStatus = xpmWriteFile(mdata.stream.file, image, name, info);
    151 
    152     xpmDataClose(&mdata);
    153 
    154     return (ErrorStatus);
    155 }
    156 
    157 static int
    158 xpmWriteFile(
    159     FILE	*file,
    160     XpmImage	*image,
    161     const char	*name,
    162     XpmInfo	*info)
    163 {
    164     /* calculation variables */
    165     unsigned int cmts, extensions;
    166     int ErrorStatus;
    167 
    168     cmts = info && (info->valuemask & XpmComments);
    169     extensions = info && (info->valuemask & XpmExtensions)
    170 	&& info->nextensions;
    171 
    172     /* print the header line */
    173     fprintf(file, "/* XPM */\nstatic char * %s[] = {\n", name);
    174 
    175     /* print the hints line */
    176     if (cmts && info->hints_cmt)
    177 	fprintf(file, "/*%s*/\n", info->hints_cmt);
    178 
    179     fprintf(file, "\"%d %d %d %d", image->width, image->height,
    180 	    image->ncolors, image->cpp);
    181 
    182     if (info && (info->valuemask & XpmHotspot))
    183 	fprintf(file, " %d %d", info->x_hotspot, info->y_hotspot);
    184 
    185     if (extensions)
    186 	fprintf(file, " XPMEXT");
    187 
    188     fprintf(file, "\",\n");
    189 
    190     /* print colors */
    191     if (cmts && info->colors_cmt)
    192 	fprintf(file, "/*%s*/\n", info->colors_cmt);
    193 
    194     WriteColors(file, image->colorTable, image->ncolors);
    195 
    196     /* print pixels */
    197     if (cmts && info->pixels_cmt)
    198 	fprintf(file, "/*%s*/\n", info->pixels_cmt);
    199 
    200     ErrorStatus = WritePixels(file, image->width, image->height, image->cpp,
    201 			      image->data, image->colorTable);
    202     if (ErrorStatus != XpmSuccess)
    203 	return (ErrorStatus);
    204 
    205     /* print extensions */
    206     if (extensions)
    207 	WriteExtensions(file, info->extensions, info->nextensions);
    208 
    209     /* close the array */
    210     fprintf(file, "};\n");
    211 
    212     return (XpmSuccess);
    213 }
    214 
    215 static void
    216 WriteColors(
    217     FILE		*file,
    218     XpmColor		*colors,
    219     unsigned int	 ncolors)
    220 {
    221     unsigned int a, key;
    222     char *s;
    223     char **defaults;
    224 
    225     for (a = 0; a < ncolors; a++, colors++) {
    226 
    227 	defaults = (char **) colors;
    228 	fprintf(file, "\"%s", *defaults++);
    229 
    230 	for (key = 1; key <= NKEYS; key++, defaults++) {
    231 	    if ((s = *defaults))
    232 		fprintf(file, "\t%s %s", xpmColorKeys[key - 1], s);
    233 	}
    234 	fprintf(file, "\",\n");
    235     }
    236 }
    237 
    238 
    239 static int
    240 WritePixels(
    241     FILE		*file,
    242     unsigned int	 width,
    243     unsigned int	 height,
    244     unsigned int	 cpp,
    245     unsigned int	*pixels,
    246     XpmColor		*colors)
    247 {
    248     char *s, *p, *buf;
    249     unsigned int x, y, h;
    250 
    251     h = height - 1;
    252     if (cpp != 0 && width >= (UINT_MAX - 3)/cpp)
    253 	return XpmNoMemory;
    254     p = buf = (char *) XpmMalloc(width * cpp + 3);
    255     if (!buf)
    256 	return (XpmNoMemory);
    257     *buf = '"';
    258     p++;
    259     for (y = 0; y < h; y++) {
    260 	s = p;
    261 	for (x = 0; x < width; x++, pixels++) {
    262 	    strncpy(s, colors[*pixels].string, cpp);
    263 	    s += cpp;
    264 	}
    265 	*s++ = '"';
    266 	*s = '\0';
    267 	fprintf(file, "%s,\n", buf);
    268     }
    269     /* duplicate some code to avoid a test in the loop */
    270     s = p;
    271     for (x = 0; x < width; x++, pixels++) {
    272 	strncpy(s, colors[*pixels].string, cpp);
    273 	s += cpp;
    274     }
    275     *s++ = '"';
    276     *s = '\0';
    277     fprintf(file, "%s", buf);
    278 
    279     XpmFree(buf);
    280     return (XpmSuccess);
    281 }
    282 
    283 static void
    284 WriteExtensions(
    285     FILE		*file,
    286     XpmExtension	*ext,
    287     unsigned int	 num)
    288 {
    289     unsigned int x, y, n;
    290     char **line;
    291 
    292     for (x = 0; x < num; x++, ext++) {
    293 	fprintf(file, ",\n\"XPMEXT %s\"", ext->name);
    294 	n = ext->nlines;
    295 	for (y = 0, line = ext->lines; y < n; y++, line++)
    296 	    fprintf(file, ",\n\"%s\"", *line);
    297     }
    298     fprintf(file, ",\n\"XPMENDEXT\"");
    299 }
    300 
    301 
    302 #ifndef NO_ZPIPE
    303 HFUNC(xpmPipeThrough, FILE*, (int fd,
    304 			     const char* cmd,
    305 			     const char* arg1,
    306 			     const char* mode));
    307 #endif
    308 
    309 /*
    310  * open the given file to be written as an xpmData which is returned
    311  */
    312 static int
    313 OpenWriteFile(
    314     const char	*filename,
    315     xpmData	*mdata)
    316 {
    317     if (!filename) {
    318 	mdata->stream.file = (stdout);
    319 	mdata->type = XPMFILE;
    320     } else {
    321 #ifndef NO_ZPIPE
    322 	size_t len;
    323 #endif
    324 	int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC|O_CLOEXEC, 0644);
    325 	if ( fd < 0 )
    326 	    return(XpmOpenFailed);
    327 #ifndef NO_ZPIPE
    328 	len = strlen(filename);
    329 	if (len > 2 && !strcmp(".Z", filename + (len - 2))) {
    330 #ifdef XPM_PATH_COMPRESS
    331 	    mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_COMPRESS, NULL, "w");
    332 #else
    333 	    mdata->stream.file = NULL;
    334 #endif
    335 	    mdata->type = XPMPIPE;
    336 	} else if (len > 3 && !strcmp(".gz", filename + (len - 3))) {
    337 	    mdata->stream.file = xpmPipeThrough(fd, XPM_PATH_GZIP, "-q", "w");
    338 	    mdata->type = XPMPIPE;
    339 	} else
    340 #endif
    341 	{
    342 	    mdata->stream.file = fdopen(fd, "w");
    343 	    mdata->type = XPMFILE;
    344 	}
    345 	if (!mdata->stream.file) {
    346 	    close(fd);
    347 	    return (XpmOpenFailed);
    348 	}
    349     }
    350     return (XpmSuccess);
    351 }
    352 
    353 /*
    354  * close the file related to the xpmData if any
    355  */
    356 static void
    357 xpmDataClose(xpmData *mdata)
    358 {
    359     if (mdata->stream.file != (stdout))
    360 	fclose(mdata->stream.file);
    361 }
    362 
    363