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