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;
113 void ErrorMessage(int ErrorStatus, char *tag);
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);
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\
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\
621 char *warning = NULL;
623 switch (ErrorStatus) {
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.
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");
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");
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");
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");
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");
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);
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);
677 XFreePixmap(dpy, icon.pixmap);
679 XFreePixmap(dpy, icon.mask);
681 XFreeColors(dpy, colormap,
682 icon.attributes.alloc_pixels,
683 icon.attributes.nalloc_pixels, 0);
685 XpmFreeAttributes(&icon.attributes);
688 XFreePixmap(dpy, view.pixmap);
690 XFreePixmap(dpy, view.mask);
692 XFreeColors(dpy, colormap,
693 view.attributes.alloc_pixels,
694 view.attributes.nalloc_pixels, 0);
696 XpmFreeAttributes(&view.attributes);
710 XLookupString(&(xe->xkey), &c, 1, NULL, NULL);
711 if (c == 'q' || c == 'Q')
716 * small function to extract various version numbers from the given global
717 * number (following the rule described in xpm.h).
723 int *libmajor_return,
724 char *libminor_return)
726 *format_return = num / 10000;
727 *libmajor_return = (num % 10000) / 100;
728 *libminor_return = 'a' + (num % 10000) % 100 - 1;
734 int format, libmajor;
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);
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.
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);