2 * Copyright (C) 1989-95 GROUPE BULL
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
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.
26 /*****************************************************************************\
29 * Show XPM File program *
31 * Developed by Arnaud Le Hors *
32 \*****************************************************************************/
40 #include <X11/StringDefs.h>
41 #include <X11/Intrinsic.h>
42 #include <X11/IntrinsicP.h>
43 #include <X11/Shell.h>
46 #include <X11/shape.h>
48 #include <X11/extensions/shape.h>
57 #define gettext(a) (a)
62 static char *plaid[] = {
63 /* width height ncolors chars_per_pixel */
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",
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 ",
87 "x x x x x x x x x x x x x x x x x x x x x x ",
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;
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);
124 typedef struct _XpmIcon {
127 XpmAttributes attributes;
130 static char **command;
132 static XpmIcon view, icon;
133 static XrmOptionDescRec options[] = {
134 {"-hints", ".hints", XrmoptionNoArg, (XtPointer) "True"},
135 {"-icon", ".icon", XrmoptionSepArg, (XtPointer) NULL},
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;
155 char *iconFile = NULL;
156 unsigned int numsymbols = 0;
157 XpmColorSymbol symbols[10];
160 unsigned long valuemask = 0;
170 XtSetLanguageProc(NULL,NULL,NULL);
171 bindtextdomain("sxpm",LOCALEDIR);
175 topw = XtInitialize(argv[0], "Sxpm",
176 options, XtNumber(options), &argc, argv);
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"));
184 colormap = XDefaultColormapOfScreen(XtScreen(topw));
187 * geometry management
190 if (XrmGetResource(xrdb, NULL, "sxpm.geometry", &stype, &val)
191 || XrmGetResource(xrdb, NULL, "Sxpm.geometry", &stype, &val)) {
198 geo = (char *) val.addr;
199 flags = XParseGeometry(geo, &x_rtn, &y_rtn,
200 (unsigned int *) &w_rtn,
201 (unsigned int *) &h_rtn);
203 if (!((WidthValue & flags) && (HeightValue & flags)))
213 XtSetArg(args[n], XtNwidth, 1);
215 XtSetArg(args[n], XtNheight, 1);
218 XtSetArg(args[n], XtNmappedWhenManaged, False);
220 XtSetArg(args[n], XtNinput, True);
222 XtSetValues(topw, args, n);
224 if ((XrmGetResource(xrdb, "sxpm.hints", "", &stype, &val)
225 || XrmGetResource(xrdb, "Sxpm.hints", "", &stype, &val))
226 && !strcmp((char *) val.addr, "True")) {
236 if (XrmGetResource(xrdb, "sxpm.icon", "", &stype, &val)
237 || XrmGetResource(xrdb, "Sxpm.icon", "", &stype, &val)) {
238 iconFile = (char *) val.addr;
246 if (XAllocNamedColor(dpy, colormap, "black", &color, &junk))
249 bpix = XBlackPixelOfScreen(XtScreen(topw));
251 iconW = XCreateSimpleWindow(dpy, root, 0, 0,
252 IWIDTH, IHEIGHT, 1, bpix, bpix);
254 icon.attributes.valuemask = XpmReturnAllocPixels;
255 ErrorStatus = XpmReadFileToPixmap(dpy, root, iconFile, &icon.pixmap,
256 &icon.mask, &icon.attributes);
257 ErrorMessage(ErrorStatus, "Icon");
259 XSetWindowBackgroundPixmap(dpy, iconW, icon.pixmap);
262 XtSetArg(args[n], XtNbackground, bpix);
264 XtSetArg(args[n], XtNiconWindow, iconW);
266 XtSetValues(topw, args, n);
274 for (n = 1; n < argc; n++) {
275 if (strcmp(argv[n], "-plaid") == 0) {
279 if (argv[n][0] != '-') {
284 if ((strlen(argv[n]) == 1) && (argv[n][0] == '-'))
287 if (strcmp(argv[n], "-o") == 0) {
289 if ((strlen(argv[n + 1]) == 1) && (argv[n + 1][0] == '-'))
292 output = argv[n + 1];
298 if (strcmp(argv[n], "-nod") == 0) {
302 if (strcmp(argv[n], "-nom") == 0) {
306 if (strcmp(argv[n], "-sc") == 0) {
308 valuemask |= XpmColorSymbols;
309 symbols[numsymbols].name = argv[++n];
310 symbols[numsymbols++].value = argv[++n];
315 if (strcmp(argv[n], "-sp") == 0) {
317 valuemask |= XpmColorSymbols;
318 symbols[numsymbols].name = argv[++n];
319 symbols[numsymbols].value = NULL;
320 symbols[numsymbols++].pixel = atol(argv[++n]);
324 if (strcmp(argv[n], "-cp") == 0) {
326 valuemask |= XpmColorSymbols;
327 symbols[numsymbols].name = NULL;
328 symbols[numsymbols].value = argv[++n];
329 symbols[numsymbols++].pixel = atol(argv[++n]);
333 if (strcmp(argv[n], "-mono") == 0) {
334 valuemask |= XpmColorKey;
335 view.attributes.color_key = XPM_MONO;
338 if (strcmp(argv[n], "-gray4") == 0 || strcmp(argv[n], "-grey4") == 0) {
339 valuemask |= XpmColorKey;
340 view.attributes.color_key = XPM_GRAY4;
343 if (strcmp(argv[n], "-gray") == 0 || strcmp(argv[n], "-grey") == 0) {
344 valuemask |= XpmColorKey;
345 view.attributes.color_key = XPM_GRAY;
348 if (strcmp(argv[n], "-color") == 0) {
349 valuemask |= XpmColorKey;
350 view.attributes.color_key = XPM_COLOR;
353 if (strncmp(argv[n], "-closecolors", 6) == 0) {
354 valuemask |= XpmCloseness;
355 view.attributes.closeness = 40000;
358 if (strcmp(argv[n], "-rgb") == 0) {
360 valuemask |= XpmRgbFilename;
361 view.attributes.rgb_fname = argv[++n];
367 if (strncmp(argv[n], "-version", 4) == 0) {
371 if (strcmp(argv[n], "-v") == 0) {
375 if (strcmp(argv[n], "-pcmap") == 0) {
376 valuemask |= XpmColormap;
382 XtRealizeWidget(topw);
383 if (valuemask & XpmColormap) {
384 colormap = XCreateColormap(dpy, win,
385 DefaultVisual(dpy, DefaultScreen(dpy)),
387 view.attributes.colormap = colormap;
388 XSetWindowColormap(dpy, win, colormap);
390 view.attributes.colorsymbols = symbols;
391 view.attributes.numsymbols = numsymbols;
392 view.attributes.valuemask = valuemask;
395 /* this is just to test the XpmCreateDataFromPixmap function */
397 view.attributes.valuemask |= XpmReturnAllocPixels;
398 view.attributes.valuemask |= XpmReturnExtensions;
399 ErrorStatus = XpmCreatePixmapFromData(dpy, win, plaid,
400 &view.pixmap, &view.mask,
402 ErrorMessage(ErrorStatus, "Plaid");
404 ErrorStatus = XpmCreateDataFromPixmap(dpy, &data, view.pixmap, view.mask,
406 ErrorMessage(ErrorStatus, "Data");
407 if (verbose && view.attributes.nextensions) {
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]);
418 XFreePixmap(dpy, view.pixmap);
420 XFreePixmap(dpy, view.mask);
422 XFreeColors(dpy, colormap,
423 view.attributes.alloc_pixels,
424 view.attributes.nalloc_pixels, 0);
426 XpmFreeAttributes(&view.attributes);
427 view.attributes.valuemask = valuemask;
430 if (input || stdinf) {
431 view.attributes.valuemask |= XpmReturnInfos;
432 view.attributes.valuemask |= XpmReturnAllocPixels;
433 view.attributes.valuemask |= XpmReturnExtensions;
439 * this is just to test the XpmCreatePixmapFromBuffer and
440 * XpmCreateBufferFromPixmap functions
442 ErrorStatus = XpmReadFileToBuffer(input, &buffer);
443 ErrorMessage(ErrorStatus, "CreateBufferFromFile");
445 ErrorStatus = XpmCreatePixmapFromBuffer(dpy, win, buffer,
446 &view.pixmap, &view.mask,
448 ErrorMessage(ErrorStatus, "CreatePixmapFromBuffer");
450 ErrorStatus = XpmCreateBufferFromPixmap(dpy, &buffer,
451 view.pixmap, view.mask,
453 ErrorMessage(ErrorStatus, "CreateBufferFromPixmap");
454 ErrorStatus = XpmWriteFileFromBuffer("buffer_output", buffer);
455 ErrorMessage(ErrorStatus, "WriteFileFromBuffer");
458 XFreePixmap(dpy, view.pixmap);
460 XFreePixmap(dpy, view.mask);
462 XFreeColors(dpy, colormap, view.attributes.alloc_pixels,
463 view.attributes.nalloc_pixels, 0);
465 XpmFreeAttributes(&view.attributes);
467 ErrorStatus = XpmReadFileToData(input, &data);
468 ErrorMessage(ErrorStatus, "ReadFileToData");
469 ErrorStatus = XpmCreatePixmapFromData(dpy, win, data,
470 &view.pixmap, &view.mask,
472 ErrorMessage(ErrorStatus, "CreatePixmapFromData");
473 ErrorStatus = XpmWriteFileFromData("sxpmout.xpm", data);
474 ErrorMessage(ErrorStatus, "WriteFileFromData");
476 XpmFreeAttributes(&view.attributes);
478 ErrorStatus = XpmReadFileToPixmap(dpy, win, input,
479 &view.pixmap, &view.mask,
481 ErrorMessage(ErrorStatus, "Read");
482 if (verbose && view.attributes.nextensions) {
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]);
497 ErrorStatus = XpmCreatePixmapFromData(dpy, win, data,
498 &view.pixmap, &view.mask,
502 ErrorStatus = XpmCreatePixmapFromData(dpy, win, plaid,
503 &view.pixmap, &view.mask,
506 ErrorMessage(ErrorStatus, "Plaid");
508 if (output || stdoutf) {
509 ErrorStatus = XpmWriteFileFromPixmap(dpy, output, view.pixmap,
510 view.mask, &view.attributes);
511 ErrorMessage(ErrorStatus, "Write");
516 * manage display if requested
519 XSizeHints size_hints;
520 char *xString = NULL;
523 && ((w_rtn < view.attributes.width)
524 || h_rtn < view.attributes.height)) {
529 view.attributes.width, view.attributes.height, 1);
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;
538 size_hints.flags = PMinSize;
540 size_hints.min_height = view.attributes.height;
541 size_hints.min_width = view.attributes.width;
542 XSetWMNormalHints(dpy, win, &size_hints);
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);
550 XStoreName(dpy, win, "Sxpm: stdin");
551 XSetIconName(dpy, win, "Sxpm: stdin");
553 XStoreName(dpy, win, "Sxpm");
554 XSetIconName(dpy, win, "Sxpm");
557 XtAddEventHandler(topw, KeyPressMask, False,
558 (XtEventHandler) kinput, NULL);
559 XSetWindowBackgroundPixmap(dpy, win, view.pixmap);
561 if (view.mask && !nom)
562 XShapeCombineMask(dpy, win, ShapeBounding, 0, 0,
563 view.mask, ShapeSet);
565 XClearWindow(dpy, win);
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\
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\
618 char *warning = NULL;
620 switch (ErrorStatus) {
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.
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");
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");
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");
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");
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");
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);
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);
674 XFreePixmap(dpy, icon.pixmap);
676 XFreePixmap(dpy, icon.mask);
678 XFreeColors(dpy, colormap,
679 icon.attributes.alloc_pixels,
680 icon.attributes.nalloc_pixels, 0);
682 XpmFreeAttributes(&icon.attributes);
685 XFreePixmap(dpy, view.pixmap);
687 XFreePixmap(dpy, view.mask);
689 XFreeColors(dpy, colormap,
690 view.attributes.alloc_pixels,
691 view.attributes.nalloc_pixels, 0);
693 XpmFreeAttributes(&view.attributes);
707 XLookupString(&(xe->xkey), &c, 1, NULL, NULL);
708 if (c == 'q' || c == 'Q')
713 * small function to extract various version numbers from the given global
714 * number (following the rule described in xpm.h).
720 int *libmajor_return,
721 char *libminor_return)
723 *format_return = num / 10000;
724 *libmajor_return = (num % 10000) / 100;
725 *libminor_return = 'a' + (num % 10000) % 100 - 1;
731 int format, libmajor;
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);
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.
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);