Merge branch 'devel/upgrade' into tizen
[platform/upstream/libXpm.git] / sxpm / sxpm.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 * sxpm.c:                                                                     *
28 *                                                                             *
29 *  Show XPM File program                                                      *
30 *                                                                             *
31 *  Developed by Arnaud Le Hors                                                *
32 \*****************************************************************************/
33
34 #ifdef HAVE_CONFIG_H
35 #include <config.h>
36 #endif
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <X11/StringDefs.h>
41 #include <X11/Intrinsic.h>
42 #include <X11/IntrinsicP.h>
43 #include <X11/Shell.h>
44
45 #ifdef VMS
46 #include <X11/shape.h>
47 #else
48 #include <X11/extensions/shape.h>
49 #endif
50
51 #include <X11/xpm.h>
52
53 #ifdef USE_GETTEXT
54 #include <locale.h>
55 #include <libintl.h>
56 #else
57 #define gettext(a) (a)
58 #endif
59
60 /* XPM */
61 /* plaid pixmap */
62 static char *plaid[] = {
63     /* width height ncolors chars_per_pixel */
64     "22 22 4 2 XPMEXT",
65     /* colors */
66     "   c red   m white  s light_color",
67     "Y  c green m black  s lines_in_mix",
68     "+  c yellow        m white  s lines_in_dark",
69     "x          m black  s dark_color",
70     /* pixels */
71     "x   x   x x x   x   x x x x x x + x x x x x ",
72     "  x   x   x   x   x   x x x x x x x x x x x ",
73     "x   x   x x x   x   x x x x x x + x x x x x ",
74     "  x   x   x   x   x   x x x x x x x x x x x ",
75     "x   x   x x x   x   x x x x x x + x x x x x ",
76     "Y Y Y Y Y x Y Y Y Y Y + x + x + x + x + x + ",
77     "x   x   x x x   x   x x x x x x + x x x x x ",
78     "  x   x   x   x   x   x x x x x x x x x x x ",
79     "x   x   x x x   x   x x x x x x + x x x x x ",
80     "  x   x   x   x   x   x x x x x x x x x x x ",
81     "x   x   x x x   x   x x x x x x + x x x x x ",
82     "          x           x   x   x Y x   x   x ",
83     "          x             x   x   Y   x   x   ",
84     "          x           x   x   x Y x   x   x ",
85     "          x             x   x   Y   x   x   ",
86     "          x           x   x   x Y x   x   x ",
87     "x x x x x x x x x x x x x x x x x x x x x x ",
88     "          x           x   x   x Y x   x   x ",
89     "          x             x   x   Y   x   x   ",
90     "          x           x   x   x Y x   x   x ",
91     "          x             x   x   Y   x   x   ",
92     "          x           x   x   x Y x   x   x ",
93     "bullshit",
94     "XPMEXT ext1 data1",
95     "XPMEXT ext2",
96     "data2_1",
97     "data2_2",
98     "XPMEXT",
99     "foo",
100     "",
101     "XPMEXT ext3",
102     "data3",
103     "XPMENDEXT"
104 };
105
106 #define win XtWindow(topw)
107 #define dpy XtDisplay(topw)
108 #define root XRootWindowOfScreen(XtScreen(topw))
109 #define xrdb XtDatabase(dpy)
110 static Colormap colormap;
111
112 void Usage(void) _X_NORETURN;
113 void ErrorMessage(int ErrorStatus, const char *tag);
114 void Punt(int i) _X_NORETURN;
115 void VersionInfo(void);
116 void kinput(Widget widget, char *tag, XEvent *xe, Boolean *b);
117 void GetNumbers(int num, int *format_return,
118                 int *libmajor_return,
119                 char *libminor_return);
120
121 #define IWIDTH      50
122 #define IHEIGHT     50
123
124 typedef struct _XpmIcon {
125     Pixmap pixmap;
126     Pixmap mask;
127     XpmAttributes attributes;
128 }        XpmIcon;
129
130 static char **command;
131 static Widget topw;
132 static XpmIcon view, icon;
133 static XrmOptionDescRec options[] = {
134     {"-hints", ".hints", XrmoptionNoArg, (XtPointer) "True"},
135     {"-icon", ".icon", XrmoptionSepArg, (XtPointer) NULL},
136 };
137
138 int
139 main(
140     int           argc,
141     char        **argv)
142 {
143     int ErrorStatus;
144     unsigned int verbose = 0;           /* performs verbose output */
145     unsigned int stdinf = 1;            /* read from stdin */
146     unsigned int stdoutf = 0;           /* write to stdout */
147     unsigned int nod = 0;               /* no display */
148     unsigned int nom = 0;               /* no mask display */
149     unsigned int incResize = 0;
150     unsigned int resize = 0;
151     unsigned int w_rtn;
152     unsigned int h_rtn;
153     char *input = NULL;
154     char *output = NULL;
155     char *iconFile = NULL;
156     unsigned int numsymbols = 0;
157     XpmColorSymbol symbols[10];
158     char *stype;
159     XrmValue val;
160     unsigned long valuemask = 0;
161     int n;
162     Arg args[4];
163
164 #ifdef Debug
165     char **data;
166     char *buffer;
167 #endif
168
169 #ifdef USE_GETTEXT
170     XtSetLanguageProc(NULL,NULL,NULL);
171     bindtextdomain("sxpm",LOCALEDIR);
172     textdomain("sxpm");
173 #endif
174
175     topw = XtInitialize(argv[0], "Sxpm",
176                         options, XtNumber(options), &argc, argv);
177
178     if (!topw) {
179         /* L10N_Comments : Error if no $DISPLAY or $DISPLAY can't be opened.
180            Not normally reached as Xt exits before we get here. */
181         fprintf(stderr, gettext("Sxpm Error... [ Undefined DISPLAY ]\n"));
182         exit(1);
183     }
184     colormap = XDefaultColormapOfScreen(XtScreen(topw));
185
186     /*
187      * geometry management
188      */
189
190     if (XrmGetResource(xrdb, NULL, "sxpm.geometry", &stype, &val)
191         || XrmGetResource(xrdb, NULL, "Sxpm.geometry", &stype, &val)) {
192
193         int flags;
194         int x_rtn;
195         int y_rtn;
196         char *geo = NULL;
197
198         geo = (char *) val.addr;
199         flags = XParseGeometry(geo, &x_rtn, &y_rtn,
200                                (unsigned int *) &w_rtn,
201                                (unsigned int *) &h_rtn);
202
203         if (!((WidthValue & flags) && (HeightValue & flags)))
204             resize = 1;
205
206     } else
207         resize = 1;
208
209     n = 0;
210     if (resize) {
211         w_rtn = 0;
212         h_rtn = 0;
213         XtSetArg(args[n], XtNwidth, 1);
214         n++;
215         XtSetArg(args[n], XtNheight, 1);
216         n++;
217     }
218     XtSetArg(args[n], XtNmappedWhenManaged, False);
219     n++;
220     XtSetArg(args[n], XtNinput, True);
221     n++;
222     XtSetValues(topw, args, n);
223
224     if ((XrmGetResource(xrdb, "sxpm.hints", "", &stype, &val)
225          || XrmGetResource(xrdb, "Sxpm.hints", "", &stype, &val))
226         && !strcmp((char *) val.addr, "True")) {
227         /* gotcha */
228         incResize = 1;
229         resize = 1;
230     }
231
232     /*
233      * icon management
234      */
235
236     if (XrmGetResource(xrdb, "sxpm.icon", "", &stype, &val)
237         || XrmGetResource(xrdb, "Sxpm.icon", "", &stype, &val)) {
238         iconFile = (char *) val.addr;
239     }
240     if (iconFile) {
241
242         XColor color, junk;
243         Pixel bpix;
244         Window iconW;
245
246         if (XAllocNamedColor(dpy, colormap, "black", &color, &junk))
247             bpix = color.pixel;
248         else
249             bpix = XBlackPixelOfScreen(XtScreen(topw));
250
251         iconW = XCreateSimpleWindow(dpy, root, 0, 0,
252                                     IWIDTH, IHEIGHT, 1, bpix, bpix);
253
254         icon.attributes.valuemask = XpmReturnAllocPixels;
255         ErrorStatus = XpmReadFileToPixmap(dpy, root, iconFile, &icon.pixmap,
256                                           &icon.mask, &icon.attributes);
257         ErrorMessage(ErrorStatus, "Icon");
258
259         XSetWindowBackgroundPixmap(dpy, iconW, icon.pixmap);
260
261         n = 0;
262         XtSetArg(args[n], XtNbackground, bpix);
263         n++;
264         XtSetArg(args[n], XtNiconWindow, iconW);
265         n++;
266         XtSetValues(topw, args, n);
267     }
268
269     /*
270      * arguments parsing
271      */
272
273     command = argv;
274     for (n = 1; n < argc; n++) {
275         if (strcmp(argv[n], "-plaid") == 0) {
276             stdinf = 0;
277             continue;
278         }
279         if (argv[n][0] != '-') {
280             stdinf = 0;
281             input = argv[n];
282             continue;
283         }
284         if ((strlen(argv[n]) == 1) && (argv[n][0] == '-'))
285             /* stdin */
286             continue;
287         if (strcmp(argv[n], "-o") == 0) {
288             if (n < argc - 1) {
289                 if ((strlen(argv[n + 1]) == 1) && (argv[n + 1][0] == '-'))
290                     stdoutf = 1;
291                 else
292                     output = argv[n + 1];
293                 n++;
294                 continue;
295             } else
296                 Usage();
297         }
298         if (strcmp(argv[n], "-nod") == 0) {
299             nod = 1;
300             continue;
301         }
302         if (strcmp(argv[n], "-nom") == 0) {
303             nom = 1;
304             continue;
305         }
306         if (strcmp(argv[n], "-sc") == 0) {
307             if (n < argc - 2) {
308                 valuemask |= XpmColorSymbols;
309                 symbols[numsymbols].name = argv[++n];
310                 symbols[numsymbols++].value = argv[++n];
311                 continue;
312             } else
313                 Usage();
314         }
315         if (strcmp(argv[n], "-sp") == 0) {
316             if (n < argc - 2) {
317                 valuemask |= XpmColorSymbols;
318                 symbols[numsymbols].name = argv[++n];
319                 symbols[numsymbols].value = NULL;
320                 symbols[numsymbols++].pixel = atol(argv[++n]);
321                 continue;
322             }
323         }
324         if (strcmp(argv[n], "-cp") == 0) {
325             if (n < argc - 2) {
326                 valuemask |= XpmColorSymbols;
327                 symbols[numsymbols].name = NULL;
328                 symbols[numsymbols].value = argv[++n];
329                 symbols[numsymbols++].pixel = atol(argv[++n]);
330                 continue;
331             }
332         }
333         if (strcmp(argv[n], "-mono") == 0) {
334             valuemask |= XpmColorKey;
335             view.attributes.color_key = XPM_MONO;
336             continue;
337         }
338         if (strcmp(argv[n], "-gray4") == 0 || strcmp(argv[n], "-grey4") == 0) {
339             valuemask |= XpmColorKey;
340             view.attributes.color_key = XPM_GRAY4;
341             continue;
342         }
343         if (strcmp(argv[n], "-gray") == 0 || strcmp(argv[n], "-grey") == 0) {
344             valuemask |= XpmColorKey;
345             view.attributes.color_key = XPM_GRAY;
346             continue;
347         }
348         if (strcmp(argv[n], "-color") == 0) {
349             valuemask |= XpmColorKey;
350             view.attributes.color_key = XPM_COLOR;
351             continue;
352         }
353         if (strncmp(argv[n], "-closecolors", 6) == 0) {
354             valuemask |= XpmCloseness;
355             view.attributes.closeness = 40000;
356             continue;
357         }
358         if (strcmp(argv[n], "-rgb") == 0) {
359             if (n < argc - 1) {
360                 valuemask |= XpmRgbFilename;
361                 view.attributes.rgb_fname = argv[++n];
362                 continue;
363             } else
364                 Usage();
365
366         }
367         if (strncmp(argv[n], "-version", 4) == 0) {
368             VersionInfo();
369             exit(0);
370         }
371         if (strcmp(argv[n], "-v") == 0) {
372             verbose = 1;
373             continue;
374         }
375         if (strcmp(argv[n], "-pcmap") == 0) {
376             valuemask |= XpmColormap;
377             continue;
378         }
379         Usage();
380     }
381
382     XtRealizeWidget(topw);
383     if (valuemask & XpmColormap) {
384         colormap = XCreateColormap(dpy, win,
385                                    DefaultVisual(dpy, DefaultScreen(dpy)),
386                                    AllocNone);
387         view.attributes.colormap = colormap;
388         XSetWindowColormap(dpy, win, colormap);
389     }
390     view.attributes.colorsymbols = symbols;
391     view.attributes.numsymbols = numsymbols;
392     view.attributes.valuemask = valuemask;
393
394 #ifdef Debug
395     /* this is just to test the XpmCreateDataFromPixmap function */
396
397     view.attributes.valuemask |= XpmReturnAllocPixels;
398     view.attributes.valuemask |= XpmReturnExtensions;
399     ErrorStatus = XpmCreatePixmapFromData(dpy, win, plaid,
400                                           &view.pixmap, &view.mask,
401                                           &view.attributes);
402     ErrorMessage(ErrorStatus, "Plaid");
403
404     ErrorStatus = XpmCreateDataFromPixmap(dpy, &data, view.pixmap, view.mask,
405                                           &view.attributes);
406     ErrorMessage(ErrorStatus, "Data");
407     if (verbose && view.attributes.nextensions) {
408         unsigned int i, j;
409
410         for (i = 0; i < view.attributes.nextensions; i++) {
411             fprintf(stderr, "Xpm extension : %s\n",
412                     view.attributes.extensions[i].name);
413             for (j = 0; j < view.attributes.extensions[i].nlines; j++)
414                 fprintf(stderr, "\t\t%s\n",
415                         view.attributes.extensions[i].lines[j]);
416         }
417     }
418     XFreePixmap(dpy, view.pixmap);
419     if (view.mask)
420         XFreePixmap(dpy, view.mask);
421
422     XFreeColors(dpy, colormap,
423                 view.attributes.alloc_pixels,
424                 view.attributes.nalloc_pixels, 0);
425
426     XpmFreeAttributes(&view.attributes);
427     view.attributes.valuemask = valuemask;
428 #endif
429
430     if (input || stdinf) {
431         view.attributes.valuemask |= XpmReturnInfos;
432         view.attributes.valuemask |= XpmReturnAllocPixels;
433         view.attributes.valuemask |= XpmReturnExtensions;
434
435 #ifdef Debug
436         XpmFree(data);
437
438         /*
439          * this is just to test the XpmCreatePixmapFromBuffer and
440          * XpmCreateBufferFromPixmap functions
441          */
442         ErrorStatus = XpmReadFileToBuffer(input, &buffer);
443         ErrorMessage(ErrorStatus, "CreateBufferFromFile");
444
445         ErrorStatus = XpmCreatePixmapFromBuffer(dpy, win, buffer,
446                                                 &view.pixmap, &view.mask,
447                                                 &view.attributes);
448         ErrorMessage(ErrorStatus, "CreatePixmapFromBuffer");
449         XpmFree(buffer);
450         ErrorStatus = XpmCreateBufferFromPixmap(dpy, &buffer,
451                                                 view.pixmap, view.mask,
452                                                 &view.attributes);
453         ErrorMessage(ErrorStatus, "CreateBufferFromPixmap");
454         ErrorStatus = XpmWriteFileFromBuffer("buffer_output", buffer);
455         ErrorMessage(ErrorStatus, "WriteFileFromBuffer");
456         XpmFree(buffer);
457         if (view.pixmap) {
458             XFreePixmap(dpy, view.pixmap);
459             if (view.mask)
460                 XFreePixmap(dpy, view.mask);
461
462             XFreeColors(dpy, colormap, view.attributes.alloc_pixels,
463                         view.attributes.nalloc_pixels, 0);
464
465             XpmFreeAttributes(&view.attributes);
466         }
467         ErrorStatus = XpmReadFileToData(input, &data);
468         ErrorMessage(ErrorStatus, "ReadFileToData");
469         ErrorStatus = XpmCreatePixmapFromData(dpy, win, data,
470                                               &view.pixmap, &view.mask,
471                                               &view.attributes);
472         ErrorMessage(ErrorStatus, "CreatePixmapFromData");
473         ErrorStatus = XpmWriteFileFromData("sxpmout.xpm", data);
474         ErrorMessage(ErrorStatus, "WriteFileFromData");
475         XpmFree(data);
476         XpmFreeAttributes(&view.attributes);
477 #endif
478         ErrorStatus = XpmReadFileToPixmap(dpy, win, input,
479                                           &view.pixmap, &view.mask,
480                                           &view.attributes);
481         ErrorMessage(ErrorStatus, "Read");
482         if (verbose && view.attributes.nextensions) {
483             unsigned int i, j;
484
485             for (i = 0; i < view.attributes.nextensions; i++) {
486                 /* L10N_Comments : Output when -v & file has extensions
487                    %s is replaced by extension name */
488                 fprintf(stderr, gettext("Xpm extension : %s\n"),
489                         view.attributes.extensions[i].name);
490                 for (j = 0; j < view.attributes.extensions[i].nlines; j++)
491                     fprintf(stderr, "\t\t%s\n",
492                             view.attributes.extensions[i].lines[j]);
493             }
494         }
495     } else {
496 #ifdef Debug
497         ErrorStatus = XpmCreatePixmapFromData(dpy, win, data,
498                                               &view.pixmap, &view.mask,
499                                               &view.attributes);
500         XpmFree(data);
501 #else
502         ErrorStatus = XpmCreatePixmapFromData(dpy, win, plaid,
503                                               &view.pixmap, &view.mask,
504                                               &view.attributes);
505 #endif
506         ErrorMessage(ErrorStatus, "Plaid");
507     }
508     if (output || stdoutf) {
509         ErrorStatus = XpmWriteFileFromPixmap(dpy, output, view.pixmap,
510                                              view.mask, &view.attributes);
511         ErrorMessage(ErrorStatus, "Write");
512     }
513     if (!nod) {
514
515         /*
516          * manage display if requested
517          */
518
519         XSizeHints size_hints;
520         char *xString = NULL;
521
522         if (w_rtn && h_rtn
523             && ((w_rtn < view.attributes.width)
524                 || h_rtn < view.attributes.height)) {
525             resize = 1;
526         }
527         if (resize) {
528             XtResizeWidget(topw,
529                            view.attributes.width, view.attributes.height, 1);
530         }
531         if (incResize) {
532             size_hints.flags = USSize | PMinSize | PResizeInc;
533             size_hints.height = view.attributes.height;
534             size_hints.width = view.attributes.width;
535             size_hints.height_inc = view.attributes.height;
536             size_hints.width_inc = view.attributes.width;
537         } else
538             size_hints.flags = PMinSize;
539
540         size_hints.min_height = view.attributes.height;
541         size_hints.min_width = view.attributes.width;
542         XSetWMNormalHints(dpy, win, &size_hints);
543
544         if (input) {
545             xString = (char *) XtMalloc((sizeof(char) * strlen(input)) + 20);
546             sprintf(xString, "Sxpm: %s", input);
547             XStoreName(dpy, win, xString);
548             XSetIconName(dpy, win, xString);
549         } else if (stdinf) {
550             XStoreName(dpy, win, "Sxpm: stdin");
551             XSetIconName(dpy, win, "Sxpm: stdin");
552         } else {
553             XStoreName(dpy, win, "Sxpm");
554             XSetIconName(dpy, win, "Sxpm");
555         }
556
557         XtAddEventHandler(topw, KeyPressMask, False,
558                           (XtEventHandler) kinput, NULL);
559         XSetWindowBackgroundPixmap(dpy, win, view.pixmap);
560
561         if (view.mask && !nom)
562             XShapeCombineMask(dpy, win, ShapeBounding, 0, 0,
563                               view.mask, ShapeSet);
564
565         XClearWindow(dpy, win);
566         XtMapWidget(topw);
567         if (xString)
568             XtFree(xString);
569         XtMainLoop();
570     }
571     Punt(0);
572 }
573
574 void
575 Usage(void)
576 {
577     /* L10N_Comments : Usage message (sxpm -h) in two parts.
578        In the first part %s is replaced by the command name. */
579     fprintf(stderr, gettext("\nUsage:  %s [options...]\n"), command[0]);
580     fprintf(stderr, gettext("Where options are:\n\
581 \n\
582 [-d host:display]            Display to connect to.\n\
583 [-g geom]                    Geometry of window.\n\
584 [-hints]                     Set ResizeInc for window.\n\
585 [-icon filename]             Set pixmap for iconWindow.\n\
586 [-plaid]                     Read the included plaid pixmap.\n\
587 [filename]                   Read from file 'filename', and from standard\n\
588                              input if 'filename' is '-'.\n\
589 [-o filename]                Write to file 'filename', and to standard\n\
590                              output if 'filename' is '-'.\n\
591 [-pcmap]                     Use a private colormap.\n\
592 [-closecolors]               Try to use `close' colors.\n\
593 [-nod]                       Don't display in window.\n\
594 [-nom]                       Don't use clip mask if any.\n\
595 [-mono]                      Use the colors specified for a monochrome visual.\n\
596 [-grey4]                     Use the colors specified for a 4 greyscale visual.\n\
597 [-grey]                      Use the colors specified for a greyscale visual.\n\
598 [-color]                     Use the colors specified for a color visual.\n\
599 [-sc symbol color]           Override color defaults.\n\
600 [-sp symbol pixel]           Override color defaults.\n\
601 [-cp color pixel]            Override color defaults.\n\
602 [-rgb filename]              Search color names in the rgb text file 'filename'.\n\
603 [-v]                         Verbose - print out extensions.\n\
604 [-version]                   Print out program's version number\n\
605                              and library's version number if different.\n\
606 if no input is specified sxpm reads from standard input.\n\
607 \n"));
608     exit(0);
609 }
610
611
612 void
613 ErrorMessage(
614     int          ErrorStatus,
615     const char  *tag)
616 {
617     char *error = NULL;
618     char *warning = NULL;
619
620     switch (ErrorStatus) {
621     case XpmSuccess:
622         return;
623     case XpmColorError:
624 /* L10N_Comments : The following set of messages are classified as
625    either errors or warnings.  Based on the class of message, different
626    wrappers are selected at the end to state the message source & class.
627
628            L10N_Comments : WARNING produced when filename can be read, but
629            contains an invalid color specification (need to create test case)*/
630         warning = gettext("Could not parse or alloc requested color");
631         break;
632     case XpmOpenFailed:
633         /* L10N_Comments : ERROR produced when filename does not exist
634            or insufficient permissions to open (i.e. sxpm /no/such/file ) */
635         error = gettext("Cannot open file");
636         break;
637     case XpmFileInvalid:
638         /* L10N_Comments : ERROR produced when filename can be read, but
639            is not an XPM file (i.e. sxpm /dev/null ) */
640         error = gettext("Invalid XPM file");
641         break;
642     case XpmNoMemory:
643         /* L10N_Comments : ERROR produced when filename can be read, but
644            is too big for memory
645            (i.e. limit datasize 32 ; sxpm /usr/dt/backdrops/Crochet.pm ) */
646         error = gettext("Not enough memory");
647         break;
648     case XpmColorFailed:
649         /* L10N_Comments : ERROR produced when filename can be read, but
650            contains an invalid color specification (need to create test case)*/
651         error = gettext("Failed to parse or alloc some color");
652         break;
653     }
654
655     if (warning)
656         /* L10N_Comments : Wrapper around above WARNING messages.
657            First %s is the tag for the operation that produced the warning.
658            Second %s is the message selected from the above set. */
659         fprintf(stderr, gettext("%s Xpm Warning: %s.\n"), tag, warning);
660
661     if (error) {
662         /* L10N_Comments : Wrapper around above ERROR messages.
663            First %s is the tag for the operation that produced the error.
664            Second %s is the message selected from the above set */
665         fprintf(stderr, gettext("%s Xpm Error: %s.\n"), tag, error);
666         Punt(1);
667     }
668 }
669
670 void
671 Punt(int i)
672 {
673     if (icon.pixmap) {
674         XFreePixmap(dpy, icon.pixmap);
675         if (icon.mask)
676             XFreePixmap(dpy, icon.mask);
677
678         XFreeColors(dpy, colormap,
679                     icon.attributes.alloc_pixels,
680                     icon.attributes.nalloc_pixels, 0);
681
682         XpmFreeAttributes(&icon.attributes);
683     }
684     if (view.pixmap) {
685         XFreePixmap(dpy, view.pixmap);
686         if (view.mask)
687             XFreePixmap(dpy, view.mask);
688
689         XFreeColors(dpy, colormap,
690                     view.attributes.alloc_pixels,
691                     view.attributes.nalloc_pixels, 0);
692
693         XpmFreeAttributes(&view.attributes);
694     }
695     exit(i);
696 }
697
698 void
699 kinput(
700     Widget       widget,
701     char        *tag,
702     XEvent      *xe,
703     Boolean     *b)
704 {
705     char c = '\0';
706
707     XLookupString(&(xe->xkey), &c, 1, NULL, NULL);
708     if (c == 'q' || c == 'Q')
709         Punt(0);
710 }
711
712 /*
713  * small function to extract various version numbers from the given global
714  * number (following the rule described in xpm.h).
715  */
716 void
717 GetNumbers(
718     int          num,
719     int         *format_return,
720     int         *libmajor_return,
721     char        *libminor_return)
722 {
723     *format_return = num / 10000;
724     *libmajor_return = (num % 10000) / 100;
725     *libminor_return = 'a' + (num % 10000) % 100 - 1;
726 }
727
728 void
729 VersionInfo(void)
730 {
731     int format, libmajor;
732     char libminor;
733
734     GetNumbers(XpmIncludeVersion, &format, &libmajor, &libminor);
735     /* L10N_Comments : sxpm -version output */
736     fprintf(stderr, gettext("sxpm version: %d.%d%c\n"),
737             format, libmajor, libminor);
738     /* L10N_Comments :
739      * if we are linked to an XPM library different from the one we've been
740      * compiled with, print its own number too when sxpm -version is called.
741      */
742     if (XpmIncludeVersion != XpmLibraryVersion()) {
743         GetNumbers(XpmLibraryVersion(), &format, &libmajor, &libminor);
744         fprintf(stderr, gettext("using the XPM library version: %d.%d%c\n"),
745                 format, libmajor, libminor);
746     }
747 }