libXpm should not try to build into a pure wayland platform.
[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);
113 void ErrorMessage(int ErrorStatus, const char *tag);
114 void Punt(int i);
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     /* Muffle gcc */
574     return 0;
575 }
576
577 void
578 Usage(void)
579 {
580     /* L10N_Comments : Usage message (sxpm -h) in two parts.
581        In the first part %s is replaced by the command name. */
582     fprintf(stderr, gettext("\nUsage:  %s [options...]\n"), command[0]);
583     fprintf(stderr, gettext("Where options are:\n\
584 \n\
585 [-d host:display]            Display to connect to.\n\
586 [-g geom]                    Geometry of window.\n\
587 [-hints]                     Set ResizeInc for window.\n\
588 [-icon filename]             Set pixmap for iconWindow.\n\
589 [-plaid]                     Read the included plaid pixmap.\n\
590 [filename]                   Read from file 'filename', and from standard\n\
591                              input if 'filename' is '-'.\n\
592 [-o filename]                Write to file 'filename', and to standard\n\
593                              output if 'filename' is '-'.\n\
594 [-pcmap]                     Use a private colormap.\n\
595 [-closecolors]               Try to use `close' colors.\n\
596 [-nod]                       Don't display in window.\n\
597 [-nom]                       Don't use clip mask if any.\n\
598 [-mono]                      Use the colors specified for a monochrome visual.\n\
599 [-grey4]                     Use the colors specified for a 4 greyscale visual.\n\
600 [-grey]                      Use the colors specified for a greyscale visual.\n\
601 [-color]                     Use the colors specified for a color visual.\n\
602 [-sc symbol color]           Override color defaults.\n\
603 [-sp symbol pixel]           Override color defaults.\n\
604 [-cp color pixel]            Override color defaults.\n\
605 [-rgb filename]              Search color names in the rgb text file 'filename'.\n\
606 [-v]                         Verbose - print out extensions.\n\
607 [-version]                   Print out program's version number\n\
608                              and library's version number if different.\n\
609 if no input is specified sxpm reads from standard input.\n\
610 \n"));
611     exit(0);
612 }
613
614
615 void
616 ErrorMessage(
617     int          ErrorStatus,
618     const char  *tag)
619 {
620     char *error = NULL;
621     char *warning = NULL;
622
623     switch (ErrorStatus) {
624     case XpmSuccess:
625         return;
626     case XpmColorError:
627 /* L10N_Comments : The following set of messages are classified as
628    either errors or warnings.  Based on the class of message, different
629    wrappers are selected at the end to state the message source & class.
630
631            L10N_Comments : WARNING produced when filename can be read, but
632            contains an invalid color specification (need to create test case)*/
633         warning = gettext("Could not parse or alloc requested color");
634         break;
635     case XpmOpenFailed:
636         /* L10N_Comments : ERROR produced when filename does not exist
637            or insufficient permissions to open (i.e. sxpm /no/such/file ) */
638         error = gettext("Cannot open file");
639         break;
640     case XpmFileInvalid:
641         /* L10N_Comments : ERROR produced when filename can be read, but
642            is not an XPM file (i.e. sxpm /dev/null ) */
643         error = gettext("Invalid XPM file");
644         break;
645     case XpmNoMemory:
646         /* L10N_Comments : ERROR produced when filename can be read, but
647            is too big for memory
648            (i.e. limit datasize 32 ; sxpm /usr/dt/backdrops/Crochet.pm ) */
649         error = gettext("Not enough memory");
650         break;
651     case XpmColorFailed:
652         /* L10N_Comments : ERROR produced when filename can be read, but
653            contains an invalid color specification (need to create test case)*/
654         error = gettext("Failed to parse or alloc some color");
655         break;
656     }
657
658     if (warning)
659         /* L10N_Comments : Wrapper around above WARNING messages.
660            First %s is the tag for the operation that produced the warning.
661            Second %s is the message selected from the above set. */
662         fprintf(stderr, gettext("%s Xpm Warning: %s.\n"), tag, warning);
663
664     if (error) {
665         /* L10N_Comments : Wrapper around above ERROR messages.
666            First %s is the tag for the operation that produced the error.
667            Second %s is the message selected from the above set */
668         fprintf(stderr, gettext("%s Xpm Error: %s.\n"), tag, error);
669         Punt(1);
670     }
671 }
672
673 void
674 Punt(int i)
675 {
676     if (icon.pixmap) {
677         XFreePixmap(dpy, icon.pixmap);
678         if (icon.mask)
679             XFreePixmap(dpy, icon.mask);
680
681         XFreeColors(dpy, colormap,
682                     icon.attributes.alloc_pixels,
683                     icon.attributes.nalloc_pixels, 0);
684
685         XpmFreeAttributes(&icon.attributes);
686     }
687     if (view.pixmap) {
688         XFreePixmap(dpy, view.pixmap);
689         if (view.mask)
690             XFreePixmap(dpy, view.mask);
691
692         XFreeColors(dpy, colormap,
693                     view.attributes.alloc_pixels,
694                     view.attributes.nalloc_pixels, 0);
695
696         XpmFreeAttributes(&view.attributes);
697     }
698     exit(i);
699 }
700
701 void
702 kinput(
703     Widget       widget,
704     char        *tag,
705     XEvent      *xe,
706     Boolean     *b)
707 {
708     char c = '\0';
709
710     XLookupString(&(xe->xkey), &c, 1, NULL, NULL);
711     if (c == 'q' || c == 'Q')
712         Punt(0);
713 }
714
715 /*
716  * small function to extract various version numbers from the given global
717  * number (following the rule described in xpm.h).
718  */
719 void
720 GetNumbers(
721     int          num,
722     int         *format_return,
723     int         *libmajor_return,
724     char        *libminor_return)
725 {
726     *format_return = num / 10000;
727     *libmajor_return = (num % 10000) / 100;
728     *libminor_return = 'a' + (num % 10000) % 100 - 1;
729 }
730
731 void
732 VersionInfo(void)
733 {
734     int format, libmajor;
735     char libminor;
736
737     GetNumbers(XpmIncludeVersion, &format, &libmajor, &libminor);
738     /* L10N_Comments : sxpm -version output */
739     fprintf(stderr, gettext("sxpm version: %d.%d%c\n"),
740             format, libmajor, libminor);
741     /* L10N_Comments :
742      * if we are linked to an XPM library different from the one we've been
743      * compiled with, print its own number too when sxpm -version is called.
744      */
745     if (XpmIncludeVersion != XpmLibraryVersion()) {
746         GetNumbers(XpmLibraryVersion(), &format, &libmajor, &libminor);
747         fprintf(stderr, gettext("using the XPM library version: %d.%d%c\n"),
748                 format, libmajor, libminor);
749     }
750 }