Merge branch 'devel/upgrade' into tizen
[platform/upstream/libXpm.git] / src / WrFFrI.c
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 /*
36  * The code related to AMIGA has been added by
37  * Lorens Younes (d93-hyo@nada.kth.se) 4/96
38  */
39
40 #ifdef HAVE_CONFIG_H
41 #include <config.h>
42 #endif
43 #include "XpmI.h"
44
45 #ifndef NO_ZPIPE
46 #include "sys/wait.h"
47 #include "sys/types.h"
48 #include "unistd.h"
49 #include "errno.h"
50 #endif
51
52 #include "fcntl.h"
53
54 /* MS Windows define a function called WriteFile @#%#&!!! */
55 LFUNC(xpmWriteFile, int, (FILE *file, XpmImage *image, const char *name,
56                           XpmInfo *info));
57
58 LFUNC(WriteColors, void, (FILE *file, XpmColor *colors, unsigned int ncolors));
59
60 LFUNC(WritePixels, int, (FILE *file, unsigned int width, unsigned int height,
61                          unsigned int cpp, unsigned int *pixels,
62                          XpmColor *colors));
63
64 LFUNC(WriteExtensions, void, (FILE *file, XpmExtension *ext,
65                               unsigned int num));
66
67 LFUNC(OpenWriteFile, int, (const char *filename, xpmData *mdata));
68 LFUNC(xpmDataClose, void, (xpmData *mdata));
69
70 int
71 XpmWriteFileFromImage(
72     Display             *display,
73     const char          *filename,
74     XImage              *image,
75     XImage              *shapeimage,
76     XpmAttributes       *attributes)
77 {
78     XpmImage xpmimage;
79     XpmInfo info;
80     int ErrorStatus;
81
82     /* create an XpmImage from the image */
83     ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
84                                              &xpmimage, attributes);
85     if (ErrorStatus != XpmSuccess)
86         return (ErrorStatus);
87
88     /* write the file from the XpmImage */
89     if (attributes) {
90         xpmSetInfo(&info, attributes);
91         ErrorStatus = XpmWriteFileFromXpmImage(filename, &xpmimage, &info);
92     } else
93         ErrorStatus = XpmWriteFileFromXpmImage(filename, &xpmimage, NULL);
94
95     /* free the XpmImage */
96     XpmFreeXpmImage(&xpmimage);
97
98     return (ErrorStatus);
99 }
100
101 int
102 XpmWriteFileFromXpmImage(
103     const char  *filename,
104     XpmImage    *image,
105     XpmInfo     *info)
106 {
107     xpmData mdata;
108     const char *name;
109     char *dot, *s, new_name[BUFSIZ] = {0};
110     int ErrorStatus;
111
112     /* open file to write */
113     if ((ErrorStatus = OpenWriteFile(filename, &mdata)) != XpmSuccess)
114         return (ErrorStatus);
115
116     /* figure out a name */
117     if (filename) {
118 #ifdef VMS
119         name = filename;
120 #else
121         if (!(name = strrchr(filename, '/'))
122 #ifdef AMIGA
123             && !(name = strrchr(filename, ':'))
124 #endif
125      )
126             name = filename;
127         else
128             name++;
129 #endif
130         /* let's try to make a valid C syntax name */
131         if (strchr(name, '.')) {
132             strncpy(new_name, name, sizeof(new_name));
133             new_name[sizeof(new_name)-1] = '\0';
134             /* change '.' to '_' */
135             name = s = new_name;
136             while ((dot = strchr(s, '.'))) {
137                 *dot = '_';
138                 s = dot;
139             }
140         }
141         if (strchr(name, '-')) {
142             if (name != new_name) {
143                 strncpy(new_name, name, sizeof(new_name));
144                 new_name[sizeof(new_name)-1] = '\0';
145                 name = new_name;
146             }
147             /* change '-' to '_' */
148             s = new_name;
149             while ((dot = strchr(s, '-'))) {
150                 *dot = '_';
151                 s = dot;
152             }
153         }
154     } else
155         name = "image_name";
156
157     /* write the XpmData from the XpmImage */
158     if (ErrorStatus == XpmSuccess)
159         ErrorStatus = xpmWriteFile(mdata.stream.file, image, name, info);
160
161     xpmDataClose(&mdata);
162
163     return (ErrorStatus);
164 }
165
166 static int
167 xpmWriteFile(
168     FILE        *file,
169     XpmImage    *image,
170     const char  *name,
171     XpmInfo     *info)
172 {
173     /* calculation variables */
174     unsigned int cmts, extensions;
175     int ErrorStatus;
176
177     cmts = info && (info->valuemask & XpmComments);
178     extensions = info && (info->valuemask & XpmExtensions)
179         && info->nextensions;
180
181     /* print the header line */
182     fprintf(file, "/* XPM */\nstatic char * %s[] = {\n", name);
183
184     /* print the hints line */
185     if (cmts && info->hints_cmt)
186         fprintf(file, "/*%s*/\n", info->hints_cmt);
187
188     fprintf(file, "\"%d %d %d %d", image->width, image->height,
189             image->ncolors, image->cpp);
190
191     if (info && (info->valuemask & XpmHotspot))
192         fprintf(file, " %d %d", info->x_hotspot, info->y_hotspot);
193
194     if (extensions)
195         fprintf(file, " XPMEXT");
196
197     fprintf(file, "\",\n");
198
199     /* print colors */
200     if (cmts && info->colors_cmt)
201         fprintf(file, "/*%s*/\n", info->colors_cmt);
202
203     WriteColors(file, image->colorTable, image->ncolors);
204
205     /* print pixels */
206     if (cmts && info->pixels_cmt)
207         fprintf(file, "/*%s*/\n", info->pixels_cmt);
208
209     ErrorStatus = WritePixels(file, image->width, image->height, image->cpp,
210                               image->data, image->colorTable);
211     if (ErrorStatus != XpmSuccess)
212         return (ErrorStatus);
213
214     /* print extensions */
215     if (extensions)
216         WriteExtensions(file, info->extensions, info->nextensions);
217
218     /* close the array */
219     fprintf(file, "};\n");
220
221     return (XpmSuccess);
222 }
223
224 static void
225 WriteColors(
226     FILE                *file,
227     XpmColor            *colors,
228     unsigned int         ncolors)
229 {
230     unsigned int a, key;
231     char *s;
232     char **defaults;
233
234     for (a = 0; a < ncolors; a++, colors++) {
235
236         defaults = (char **) colors;
237         fprintf(file, "\"%s", *defaults++);
238
239         for (key = 1; key <= NKEYS; key++, defaults++) {
240             if ((s = *defaults))
241                 fprintf(file, "\t%s %s", xpmColorKeys[key - 1], s);
242         }
243         fprintf(file, "\",\n");
244     }
245 }
246
247
248 static int
249 WritePixels(
250     FILE                *file,
251     unsigned int         width,
252     unsigned int         height,
253     unsigned int         cpp,
254     unsigned int        *pixels,
255     XpmColor            *colors)
256 {
257     char *s, *p, *buf;
258     unsigned int x, y, h;
259
260     h = height - 1;
261     if (cpp != 0 && width >= (UINT_MAX - 3)/cpp)
262         return XpmNoMemory;
263     p = buf = (char *) XpmMalloc(width * cpp + 3);
264     if (!buf)
265         return (XpmNoMemory);
266     *buf = '"';
267     p++;
268     for (y = 0; y < h; y++) {
269         s = p;
270         for (x = 0; x < width; x++, pixels++) {
271             strncpy(s, colors[*pixels].string, cpp);
272             s += cpp;
273         }
274         *s++ = '"';
275         *s = '\0';
276         fprintf(file, "%s,\n", buf);
277     }
278     /* duplicate some code to avoid a test in the loop */
279     s = p;
280     for (x = 0; x < width; x++, pixels++) {
281         strncpy(s, colors[*pixels].string, cpp);
282         s += cpp;
283     }
284     *s++ = '"';
285     *s = '\0';
286     fprintf(file, "%s", buf);
287
288     XpmFree(buf);
289     return (XpmSuccess);
290 }
291
292 static void
293 WriteExtensions(
294     FILE                *file,
295     XpmExtension        *ext,
296     unsigned int         num)
297 {
298     unsigned int x, y, n;
299     char **line;
300
301     for (x = 0; x < num; x++, ext++) {
302         fprintf(file, ",\n\"XPMEXT %s\"", ext->name);
303         n = ext->nlines;
304         for (y = 0, line = ext->lines; y < n; y++, line++)
305             fprintf(file, ",\n\"%s\"", *line);
306     }
307     fprintf(file, ",\n\"XPMENDEXT\"");
308 }
309
310
311 #ifndef NO_ZPIPE
312 FUNC(xpmPipeThrough, FILE*, (int fd,
313                              const char* cmd,
314                              const char* arg1,
315                              const char* mode));
316 #endif
317
318 /*
319  * open the given file to be written as an xpmData which is returned
320  */
321 static int
322 OpenWriteFile(
323     const char  *filename,
324     xpmData     *mdata)
325 {
326     if (!filename) {
327         mdata->stream.file = (stdout);
328         mdata->type = XPMFILE;
329     } else {
330 #ifndef NO_ZPIPE
331         size_t len;
332 #endif
333         int fd = open(filename, O_WRONLY|O_CREAT|O_TRUNC, 0644);
334         if ( fd < 0 )
335             return(XpmOpenFailed);
336 #ifndef NO_ZPIPE
337         len = strlen(filename);
338         if (len > 2 && !strcmp(".Z", filename + (len - 2))) {
339             mdata->stream.file = xpmPipeThrough(fd, "compress", NULL, "w");
340             mdata->type = XPMPIPE;
341         } else if (len > 3 && !strcmp(".gz", filename + (len - 3))) {
342             mdata->stream.file = xpmPipeThrough(fd, "gzip", "-q", "w");
343             mdata->type = XPMPIPE;
344         } else
345 #endif
346         {
347             mdata->stream.file = fdopen(fd, "w");
348             mdata->type = XPMFILE;
349         }
350         if (!mdata->stream.file) {
351             close(fd);
352             return (XpmOpenFailed);
353         }
354     }
355     return (XpmSuccess);
356 }
357
358 /*
359  * close the file related to the xpmData if any
360  */
361 static void
362 xpmDataClose(xpmData *mdata)
363 {
364     if (mdata->stream.file != (stdout))
365         fclose(mdata->stream.file);
366 }
367