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