PageRenderTime 57ms CodeModel.GetById 17ms app.highlight 33ms RepoModel.GetById 1ms app.codeStats 1ms

/sxpm/sxpm.c

#
C | 750 lines | 583 code | 75 blank | 92 comment | 109 complexity | 399a8d29bc2d05aba001b0ec83cf7897 MD5 | raw file
  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 */
 62static 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)
110static Colormap colormap;
111
112void Usage(void);
113void ErrorMessage(int ErrorStatus, const char *tag);
114void Punt(int i);
115void VersionInfo(void);
116void kinput(Widget widget, char *tag, XEvent *xe, Boolean *b);
117void GetNumbers(int num, int *format_return,
118		int *libmajor_return,
119		char *libminor_return);
120
121#define IWIDTH      50
122#define IHEIGHT     50
123
124typedef struct _XpmIcon {
125    Pixmap pixmap;
126    Pixmap mask;
127    XpmAttributes attributes;
128}        XpmIcon;
129
130static char **command;
131static Widget topw;
132static XpmIcon view, icon;
133static XrmOptionDescRec options[] = {
134    {"-hints", ".hints", XrmoptionNoArg, (XtPointer) "True"},
135    {"-icon", ".icon", XrmoptionSepArg, (XtPointer) NULL},
136};
137
138int
139main(
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
577void
578Usage(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\
609if no input is specified sxpm reads from standard input.\n\
610\n"));
611    exit(0);
612}
613
614
615void
616ErrorMessage(
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
673void
674Punt(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
701void
702kinput(
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 */
719void
720GetNumbers(
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
731void
732VersionInfo(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}