home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / X / mit / clients / xwud / xwud.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-07-25  |  25.2 KB  |  931 lines

  1. /* $XConsortium: xwud.c,v 1.48 91/07/25 18:02:05 rws Exp $ */
  2. /* Copyright 1985, 1986, 1988 Massachusetts Institute of Technology */
  3.  
  4. /*
  5. Permission to use, copy, modify, distribute, and sell this software and its
  6. documentation for any purpose is hereby granted without fee, provided that
  7. the above copyright notice appear in all copies and that both that
  8. copyright notice and this permission notice appear in supporting
  9. documentation, and that the name of M.I.T. not be used in advertising or
  10. publicity pertaining to distribution of the software without specific,
  11. written prior permission.  M.I.T. makes no representations about the
  12. suitability of this software for any purpose.  It is provided "as is"
  13. without express or implied warranty.
  14. */
  15.  
  16. /* xwud - marginally useful raster image undumper */
  17.  
  18.  
  19. #include <X11/Xos.h>
  20. #include <X11/Xlib.h>
  21. #include <X11/Xutil.h>
  22. #include <X11/Xatom.h>
  23. #include <stdio.h>
  24. #include <X11/XWDFile.h>
  25. #define  XK_LATIN1
  26. #include <X11/keysymdef.h>
  27. #include <errno.h>
  28.  
  29. extern int errno;
  30. extern char *malloc();
  31. unsigned Image_Size();
  32. Atom wm_protocols;
  33. Atom wm_delete_window;
  34.  
  35. char *progname;
  36.  
  37. usage()
  38. {
  39.     fprintf(stderr, "usage: %s [-in <file>] [-noclick] [-geometry <geom>] [-display <display>]\n", progname);
  40.     fprintf(stderr, "            [-new] [-std <maptype>] [-raw] [-vis <vis-type-or-id>]\n");
  41.     fprintf(stderr, "            [-help] [-rv] [-plane <number>] [-fg <color>] [-bg <color>]\n");
  42.     exit(1);
  43. }
  44.  
  45. Bool
  46. Read(ptr, size, nitems, stream)
  47.     char *ptr;
  48.     int size;
  49.     int nitems;
  50.     FILE *stream;
  51. {
  52.     size *= nitems;
  53.     while (size) {
  54.     nitems = fread(ptr, 1, size, stream);
  55.     if (nitems <= 0)
  56.         return False;
  57.     size -= nitems;
  58.     ptr += nitems;
  59.     }
  60.     return True;
  61. }
  62.  
  63. main(argc, argv)
  64.     int argc;
  65.     char **argv;
  66. {
  67.     Display *dpy;
  68.     int screen;
  69.     register int i;
  70.     XImage *in_image, *out_image;
  71.     XSetWindowAttributes attributes;
  72.     XVisualInfo vinfo, *vinfos;
  73.     long mask;
  74.     register char *buffer;
  75.     unsigned long swaptest = 1;
  76.     int count, stdcnt;
  77.     unsigned buffer_size;
  78.     int win_name_size;
  79.     int ncolors;
  80.     char *file_name = NULL;
  81.     char *win_name;
  82.     Bool inverse = False, rawbits = False, newmap = False;
  83.     Bool onclick = True;
  84.     int plane = -1;
  85.     char *std = NULL;
  86.     char *vis = NULL;
  87.     char *display_name = NULL;
  88.     char *fgname = NULL;
  89.     char *bgname = NULL;
  90.     char *geom = NULL;
  91.     int gbits = 0;
  92.     XSizeHints hints;
  93.     XTextProperty textprop;
  94.     XClassHint class_hint;
  95.     XColor *colors, color, igncolor;
  96.     Window image_win;
  97.     Colormap colormap;
  98.     XEvent event;
  99.     register XExposeEvent *expose = (XExposeEvent *)&event;
  100.     GC gc;
  101.     XGCValues gc_val;
  102.     XWDFileHeader header;
  103.     FILE *in_file = stdin;
  104.     char *map_name;
  105.     Atom map_prop;
  106.     XStandardColormap *stdmaps, *stdmap;
  107.     char c;
  108.  
  109.     progname = argv[0];
  110.  
  111.     for (i = 1; i < argc; i++) {
  112.     if (strcmp(argv[i], "-bg") == 0) {
  113.         if (++i >= argc) usage();
  114.         bgname = argv[i];
  115.         continue;
  116.     }
  117.     if (strcmp(argv[i], "-display") == 0) {
  118.         if (++i >= argc) usage();
  119.         display_name = argv[i];
  120.         continue;
  121.     }
  122.     if (strcmp(argv[i], "-fg") == 0) {
  123.         if (++i >= argc) usage();
  124.         fgname = argv[i];
  125.         continue;
  126.     }
  127.     if (strcmp(argv[i], "-geometry") == 0) {
  128.         if (++i >= argc) usage();
  129.         geom = argv[i];
  130.         continue;
  131.     }
  132.     if (strcmp(argv[i], "-help") == 0) {
  133.         usage();
  134.     }
  135.     if (strcmp(argv[i], "-in") == 0) {
  136.         if (++i >= argc) usage();
  137.         file_name = argv[i];
  138.         continue;
  139.     }
  140.     if (strcmp(argv[i], "-inverse") == 0) { /* for compatibility */
  141.         inverse = True;
  142.         continue;
  143.     }
  144.     if (strcmp(argv[i], "-new") == 0) {
  145.         newmap = True;
  146.         if (std) usage();
  147.         continue;
  148.     }
  149.     if (strcmp(argv[i], "-noclick") == 0) {
  150.         onclick = False;
  151.         continue;
  152.     }
  153.     if (strcmp(argv[i], "-plane") == 0) {
  154.         if (++i >= argc) usage();
  155.         plane = atoi(argv[i]);
  156.         continue;
  157.     }
  158.     if (strcmp(argv[i], "-raw") == 0) {
  159.         rawbits = True;
  160.         if (std) usage();
  161.         continue;
  162.     }
  163.     if (strcmp(argv[i], "-rv") == 0) {
  164.         inverse = True;
  165.         continue;
  166.     }
  167.     if (strcmp(argv[i], "-std") == 0) {
  168.         if (++i >= argc) usage();
  169.         std = argv[i];
  170.         if (newmap || rawbits) usage();
  171.         continue;
  172.     }
  173.     if (strcmp(argv[i], "-vis") == 0) {
  174.         if (++i >= argc) usage();
  175.         vis = argv[i];
  176.         continue;
  177.     }
  178.     usage();
  179.     }
  180.     
  181.     if (file_name) {
  182.     in_file = fopen(file_name, "r");
  183.     if (in_file == NULL)
  184.         Error("Can't open input file as specified.");
  185.     }
  186.     
  187.     dpy = XOpenDisplay(display_name);
  188.     if (dpy == NULL) {
  189.     fprintf(stderr, "%s:  unable to open display \"%s\"\n",
  190.         progname, XDisplayName(display_name));
  191.     exit(1);
  192.     }
  193.     screen = DefaultScreen(dpy);
  194.  
  195.     /*
  196.      * Read in header information.
  197.      */
  198.     if(!Read((char *)&header, sizeof(header), 1, in_file))
  199.       Error("Unable to read dump file header.");
  200.  
  201.     if (*(char *) &swaptest)
  202.     _swaplong((char *) &header, sizeof(header));
  203.  
  204.     /* check to see if the dump file is in the proper format */
  205.     if (header.file_version != XWD_FILE_VERSION) {
  206.     fprintf(stderr,"xwud: XWD file format version mismatch.");
  207.     Error("exiting.");
  208.     }
  209.     if (header.header_size < sizeof(header)) {
  210.     fprintf(stderr,"xwud: XWD header size is too small.");
  211.     Error("exiting.");
  212.     }
  213.  
  214.     /* alloc window name */
  215.     win_name_size = (header.header_size - sizeof(header));
  216.     if((win_name = malloc((unsigned) win_name_size + 6)) == NULL)
  217.       Error("Can't malloc window name storage.");
  218.     strcpy(win_name, "xwud: ");
  219.  
  220.      /* read in window name */
  221.     if(!Read(win_name + 6, sizeof(char), win_name_size, in_file))
  222.       Error("Unable to read window name from dump file.");
  223.  
  224.     /* initialize the input image */
  225.  
  226.     /* This is a crock.  Xlib does not provide a way to create an
  227.      * arbitrary image and get the internal image functions correctly
  228.      * initialized.  So, we cheat.
  229.      */
  230.     {
  231.     Display fakedpy;
  232.     ScreenFormat fakefmt;
  233.  
  234.     fakedpy.byte_order = (int) header.byte_order;
  235.     fakedpy.bitmap_unit = (int) header.bitmap_unit;
  236.     fakedpy.bitmap_bit_order = (int) header.bitmap_bit_order;
  237.     fakedpy.pixmap_format = &fakefmt;
  238.     fakedpy.nformats = 1;
  239.     fakefmt.depth = (int) header.pixmap_depth;
  240.     fakefmt.bits_per_pixel = (int) header.bits_per_pixel;
  241.  
  242.     in_image = XCreateImage(&fakedpy, NULL,
  243.                 (int) header.pixmap_depth,
  244.                 (int) header.pixmap_format,
  245.                 (int) header.xoffset, NULL,
  246.                 (int) header.pixmap_width,
  247.                 (int) header.pixmap_height,
  248.                 (int) header.bitmap_pad,
  249.                 (int) header.bytes_per_line);
  250.     }
  251.  
  252.     in_image->red_mask = header.red_mask;
  253.     in_image->green_mask = header.green_mask;
  254.     in_image->blue_mask = header.blue_mask;
  255.  
  256.     /* read in the color map buffer */
  257.     if(ncolors = header.ncolors) {
  258.     colors = (XColor *)malloc((unsigned) ncolors * sizeof(XColor));
  259.     if (!colors)
  260.         Error("Can't malloc color table");
  261.     if(!Read((char *) colors, sizeof(XColor), ncolors, in_file))
  262.       Error("Unable to read color map from dump file.");
  263.     if (*(char *) &swaptest) {
  264.         for (i = 0; i < ncolors; i++) {
  265.         _swaplong((char *) &colors[i].pixel, sizeof(long));
  266.         _swapshort((char *) &colors[i].red, 3 * sizeof(short));
  267.         }
  268.     }
  269.     }
  270.  
  271.     /* alloc the pixel buffer */
  272.     buffer_size = Image_Size(in_image);
  273.     if((buffer = malloc(buffer_size)) == NULL)
  274.       Error("Can't malloc data buffer.");
  275.  
  276.     /* read in the image data */
  277.     if (!Read(buffer, sizeof(char), (int)buffer_size, in_file))
  278.         Error("Unable to read pixmap from dump file.");
  279.  
  280.      /* close the input file */
  281.     (void) fclose(in_file);
  282.  
  283.     if (plane >= in_image->depth)
  284.     Error("plane number exceeds image depth");
  285.     if ((in_image->format == XYPixmap) && (plane >= 0)) {
  286.     buffer += in_image->bytes_per_line * in_image->height *
  287.           (in_image->depth - (plane + 1));
  288.     in_image->depth = 1;
  289.     ncolors = 0;
  290.     }
  291.     if (in_image->depth == 1) {
  292.     in_image->format = XYBitmap;
  293.     newmap = False;
  294.     rawbits = True;
  295.     }
  296.     in_image->data = buffer;
  297.  
  298.     if (std) {
  299.     map_name = malloc(strlen(std) + 9);
  300.     strcpy(map_name, "RGB_");
  301.     strcat(map_name, std);
  302.     strcat(map_name, "_MAP");
  303.     Latin1Upper(map_name);
  304.     map_prop = XInternAtom(dpy, map_name, True);
  305.     if (!map_prop || !XGetRGBColormaps(dpy, RootWindow(dpy, screen),
  306.                        &stdmaps, &stdcnt, map_prop))
  307.         Error("specified standard colormap does not exist");
  308.     }
  309.     vinfo.screen = screen;
  310.     mask = VisualScreenMask;
  311.     if (vis)
  312.     {
  313.     char *vt;
  314.     vt = malloc(strlen(vis) + 1);
  315.     strcpy(vt, vis);
  316.     Latin1Upper(vt);
  317.     if (strcmp(vt, "STATICGRAY") == 0) {
  318.         vinfo.class = StaticGray;
  319.         mask |= VisualClassMask;
  320.     } else if (strcmp(vt, "GRAYSCALE") == 0) {
  321.         vinfo.class = GrayScale;
  322.         mask |= VisualClassMask;
  323.     } else if (strcmp(vt, "STATICCOLOR") == 0) {
  324.         vinfo.class = StaticColor;
  325.         mask |= VisualClassMask;
  326.     } else if (strcmp(vt, "PSEUDOCOLOR") == 0) {
  327.         vinfo.class = PseudoColor;
  328.         mask |= VisualClassMask;
  329.     } else if (strcmp(vt, "DIRECTCOLOR") == 0) {
  330.         vinfo.class = DirectColor;
  331.         mask |= VisualClassMask;
  332.     } else if (strcmp(vt, "TRUECOLOR") == 0) {
  333.         vinfo.class = TrueColor;
  334.         mask |= VisualClassMask;
  335.     } else if (strcmp(vt, "MATCH") == 0) {
  336.         vinfo.class = header.visual_class;
  337.         mask |= VisualClassMask;
  338.     } else if (strcmp(vt, "DEFAULT") == 0) {
  339.         vinfo.visualid= XVisualIDFromVisual(DefaultVisual(dpy, screen));
  340.         mask |= VisualIDMask;
  341.     } else {
  342.         vinfo.visualid = 0;
  343.         mask |= VisualIDMask;
  344.         sscanf(vis, "0x%lx", &vinfo.visualid);
  345.         if (!vinfo.visualid)
  346.           sscanf(vis, "%ld", &vinfo.visualid);
  347.         if (!vinfo.visualid)
  348.           Error("invalid visual specifier");
  349.     }
  350.     }
  351.     if (rawbits && (in_image->depth > 1) && (plane < 0)) {
  352.     vinfo.depth = in_image->depth;
  353.     mask |= VisualDepthMask;
  354.     }
  355.     vinfos = XGetVisualInfo(dpy, mask, &vinfo, &count);
  356.     if (count == 0)
  357.     Error("no matching visual found");
  358.  
  359.     /* find a workable visual */
  360.     if (std) {
  361.     stdmap = &stdmaps[0];
  362.     if (mask & VisualIDMask) {
  363.         for (i = 0; i < stdcnt; i++) {
  364.         if (stdmaps[i].visualid == vinfo.visualid) {
  365.             stdmap = &stdmaps[i];
  366.             break;
  367.         }
  368.         }
  369.         if (stdmap->visualid != vinfo.visualid)
  370.         Error("no standard colormap matching specified visual");
  371.     }
  372.     for (i = 0; i < count; i++) {
  373.         if (stdmap->visualid == vinfos[i].visualid) {
  374.         vinfo = vinfos[i];
  375.         break;
  376.         }
  377.     }
  378.     } else if ((in_image->depth == 1) ||
  379.            ((in_image->format == ZPixmap) && (plane >= 0)) ||
  380.            rawbits) {
  381.     vinfo = vinfos[0];
  382.     if (!(mask & VisualIDMask)) {
  383.         for (i = 0; i < count; i++) {
  384.         if ((vinfos[i].visualid ==
  385.              XVisualIDFromVisual(DefaultVisual(dpy, screen))) &&
  386.             (vinfos[i].depth == DefaultDepth(dpy, screen))) {
  387.             vinfo = vinfos[i];
  388.             break;
  389.         }
  390.         }
  391.     }
  392.     } else {
  393.     /* get best visual */
  394.     vinfo = vinfos[0];
  395.     for (i = 1; i < count; i++) {
  396.         int z1, z2;
  397.         z2 = EffectiveSize(&vinfos[i]);
  398.         if ((z2 >= ncolors) &&
  399.         (vinfos[i].depth == in_image->depth) &&
  400.         (vinfos[i].class == header.visual_class))
  401.         {
  402.         vinfo = vinfos[i];
  403.         break;
  404.         }
  405.         z1 = EffectiveSize(&vinfo);
  406.         if ((z2 > z1) ||
  407.         ((z2 == z1) &&
  408.          (VisualRank(vinfos[i].class) >= VisualRank(vinfo.class))))
  409.         vinfo = vinfos[i];
  410.     }
  411.     if ((newmap || (vinfo.visual != DefaultVisual(dpy, screen))) &&
  412.         (vinfo.class != StaticGray) &&
  413.         (vinfo.class != StaticColor) &&
  414.         (vinfo.class == header.visual_class) &&
  415.         (vinfo.depth == in_image->depth) &&
  416.         ((vinfo.class == PseudoColor) ||
  417.          (vinfo.class == GrayScale) ||
  418.          ((vinfo.red_mask == header.red_mask) &&
  419.           (vinfo.green_mask == header.green_mask) &&
  420.           (vinfo.blue_mask == header.blue_mask)))) {
  421.         rawbits = True;
  422.         newmap = True;
  423.     }
  424.     }
  425.  
  426.     /* get the appropriate colormap */
  427.     if (newmap && (vinfo.class & 1) &&
  428.     (vinfo.depth == in_image->depth) &&
  429.     (vinfo.class == header.visual_class) &&
  430.     (vinfo.colormap_size >= ncolors) &&
  431.     (vinfo.red_mask == header.red_mask) &&
  432.     (vinfo.green_mask == header.green_mask) &&
  433.     (vinfo.blue_mask == header.blue_mask)) {
  434.     colormap = XCreateColormap(dpy, RootWindow(dpy, screen), vinfo.visual,
  435.                    AllocAll);
  436.     if (ncolors) {
  437.         for (i = 0; i < ncolors; i++)
  438.         colors[i].flags = DoRed|DoGreen|DoBlue;
  439.         XStoreColors(dpy, colormap, colors, ncolors);
  440.     }
  441.     } else if (std) {
  442.     colormap = stdmap->colormap;
  443.     } else {
  444.     if (!newmap && (vinfo.visual == DefaultVisual(dpy, screen)))
  445.         colormap = DefaultColormap(dpy, screen);
  446.     else
  447.         colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
  448.                        vinfo.visual, AllocNone);
  449.     newmap = False;
  450.     }
  451.  
  452.     /* create the output image */
  453.     if ((in_image->format == ZPixmap) && (plane >= 0)) {
  454.     out_image = XCreateImage(dpy, vinfo.visual, 1,
  455.                  XYBitmap, 0, NULL,
  456.                  in_image->width, in_image->height,
  457.                  XBitmapPad(dpy), 0);
  458.     out_image->data = malloc(Image_Size(out_image));
  459.     Extract_Plane(in_image, out_image, plane);
  460.     ncolors = 0;
  461.     } else if (rawbits || newmap) {
  462.     out_image = in_image;
  463.     } else {
  464.     out_image = XCreateImage(dpy, vinfo.visual, vinfo.depth,
  465.                  (vinfo.depth == 1) ? XYBitmap :
  466.                               in_image->format,
  467.                  in_image->xoffset, NULL,
  468.                  in_image->width, in_image->height,
  469.                  XBitmapPad(dpy), 0);
  470.     out_image->data = malloc(Image_Size(out_image));
  471.     if (std) {
  472.         if (!stdmap->green_max && !stdmap->blue_max && IsGray(dpy, stdmap))
  473.         Do_StdGray(dpy, stdmap, ncolors, colors, in_image, out_image);
  474.         else
  475.         Do_StdCol(dpy, stdmap, ncolors, colors, in_image, out_image);
  476.     } else if ((header.visual_class == TrueColor) ||
  477.            (header.visual_class == DirectColor))
  478.         Do_Direct(dpy, &header, &colormap, ncolors, colors,
  479.               in_image, out_image);
  480.     else
  481.         Do_Pseudo(dpy, &colormap, ncolors, colors, in_image, out_image);
  482.     }
  483.  
  484.     if (out_image->depth == 1) {
  485.     if (fgname &&
  486.         XAllocNamedColor(dpy, colormap, fgname, &color, &igncolor))
  487.         gc_val.foreground = color.pixel;
  488.     else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[1]))
  489.         gc_val.foreground = colors[1].pixel;
  490.     else
  491.         gc_val.foreground = BlackPixel (dpy, screen);
  492.     if (bgname &&
  493.         XAllocNamedColor(dpy, colormap, bgname, &color, &igncolor))
  494.         gc_val.background = color.pixel;
  495.     else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[0]))
  496.         gc_val.background = colors[0].pixel;
  497.     else
  498.         gc_val.background = WhitePixel (dpy, screen);
  499.     if (inverse) {
  500.         unsigned long tmp;
  501.         tmp = gc_val.foreground;
  502.         gc_val.foreground = gc_val.background;
  503.         gc_val.background = tmp;
  504.     }
  505.     } else {
  506.     gc_val.background = XGetPixel(out_image, 0, 0);
  507.     gc_val.foreground = 0;
  508.     }
  509.  
  510.     attributes.background_pixel = gc_val.background;
  511.     attributes.border_pixel = gc_val.background;
  512.     attributes.bit_gravity = NorthWestGravity;
  513.     attributes.event_mask = ButtonPressMask|ButtonReleaseMask|KeyPressMask|
  514.                 ExposureMask;
  515.     attributes.colormap = colormap;
  516.  
  517.     hints.x = header.window_x;
  518.     hints.y = header.window_y;
  519.     hints.width = out_image->width;
  520.     hints.height = out_image->height;
  521.     if (geom)
  522.     gbits = XParseGeometry(geom, &hints.x, &hints.y,
  523.                    (unsigned int *)&hints.width,
  524.                    (unsigned int *)&hints.height);
  525.     hints.max_width = (hints.width > out_image->width) ? hints.width :
  526.                              out_image->width;
  527.     hints.max_height = (hints.height > out_image->height) ? hints.height :
  528.                                 out_image->height;
  529.     hints.flags = PMaxSize |
  530.           ((gbits & (XValue|YValue)) ? USPosition : 0) |
  531.           ((gbits & (HeightValue|WidthValue)) ? USSize : PSize);
  532.  
  533.     if ((gbits & XValue) && (gbits & XNegative))
  534.     hints.x += DisplayWidth(dpy, screen) - hints.width; 
  535.     if ((gbits & YValue) && (gbits & YNegative))
  536.     hints.y += DisplayHeight(dpy, screen) - hints.height;
  537.  
  538.     /* create the image window */
  539.     image_win = XCreateWindow(dpy, RootWindow(dpy, screen),
  540.                   hints.x, hints.y, hints.width, hints.height,
  541.                   0, vinfo.depth, InputOutput, vinfo.visual,
  542.                   CWBorderPixel|CWBackPixel|CWColormap|CWEventMask|CWBitGravity,
  543.                   &attributes);
  544.  
  545.     /* Setup for ICCCM delete window. */
  546.     wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
  547.     wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  548.     (void) XSetWMProtocols (dpy, image_win, &wm_delete_window, 1);
  549.      
  550.     textprop.value = (unsigned char *) win_name;
  551.     textprop.encoding = XA_STRING;
  552.     textprop.format = 8;
  553.     textprop.nitems = strlen(win_name);
  554.     class_hint.res_name = (char *)NULL;
  555.     class_hint.res_class = "Xwud";
  556.     /* set standard properties */
  557.     XSetWMProperties(dpy, image_win, &textprop, (XTextProperty *)NULL,
  558.              argv, argc, &hints, (XWMHints *)NULL, &class_hint);
  559.  
  560.     /* map the image window */
  561.     XMapWindow(dpy, image_win);
  562.  
  563.     gc = XCreateGC (dpy, image_win, GCForeground|GCBackground, &gc_val);
  564.  
  565.     while (1) {
  566.     /* wait on mouse input event to terminate */
  567.     XNextEvent(dpy, &event);
  568.     switch(event.type) {
  569.     case ClientMessage:
  570.       if (event.xclient.message_type == wm_protocols && 
  571.           event.xclient.data.l[0] == wm_delete_window)  {
  572.         XCloseDisplay(dpy);
  573.         exit(0);        /* ICCCM delete window */
  574.       }
  575.         break;
  576.     case ButtonPress:
  577.         break;
  578.     case ButtonRelease:
  579.         if (onclick) {
  580.         XCloseDisplay(dpy);
  581.         exit(0);
  582.         }
  583.         break;
  584.     case KeyPress:
  585.         i = XLookupString(&event.xkey, &c, 1, NULL, NULL);
  586.         if ((i == 1) && ((c == 'q') || (c == 'Q') || (c == '\03'))) {
  587.         XCloseDisplay(dpy);
  588.         exit(0);
  589.         }
  590.         break;
  591.     case Expose:
  592.         if ((expose->x < out_image->width) &&
  593.         (expose->y < out_image->height)) {
  594.         if ((out_image->width - expose->x) < expose->width)
  595.             expose->width = out_image->width - expose->x;
  596.         if ((out_image->height - expose->y) < expose->height)
  597.             expose->height = out_image->height - expose->y;
  598.         XPutImage(dpy, image_win, gc, out_image,
  599.               expose->x, expose->y, expose->x, expose->y,
  600.               expose->width, expose->height);
  601.         }
  602.         break;
  603.     }
  604.     }
  605. }
  606.  
  607. Latin1Upper(str)
  608.     unsigned char *str;
  609. {
  610.     unsigned char c;
  611.  
  612.     for (; c = *str; str++)
  613.     {
  614.     if ((c >= XK_a) && (c <= XK_z))
  615.         *str = c - (XK_a - XK_A);
  616.     else if ((c >= XK_agrave) && (c <= XK_odiaeresis))
  617.         *str = c - (XK_agrave - XK_Agrave);
  618.     else if ((c >= XK_oslash) && (c <= XK_thorn))
  619.         *str = c - (XK_oslash - XK_Ooblique);
  620.     }
  621. }
  622.  
  623. Extract_Plane(in_image, out_image, plane)
  624.     register XImage *in_image, *out_image;
  625.     int plane;
  626. {
  627.     register int x, y;
  628.  
  629.     for (y = 0; y < in_image->height; y++)
  630.     for (x = 0; x < in_image->width; x++)
  631.         XPutPixel(out_image, x, y,
  632.               (XGetPixel(in_image, x, y) >> plane) & 1);
  633. }
  634.  
  635. int
  636. EffectiveSize(vinfo)
  637.     XVisualInfo *vinfo;
  638. {
  639.     if ((vinfo->class == DirectColor) || (vinfo->class == TrueColor))
  640.     return (vinfo->red_mask | vinfo->green_mask | vinfo->blue_mask) + 1;
  641.     else
  642.     return vinfo->colormap_size;
  643. }
  644.  
  645. VisualRank(class)
  646.     int class;
  647. {
  648.     switch (class) {
  649.     case PseudoColor:
  650.     return 5;
  651.     case DirectColor:
  652.     return 4;
  653.     case TrueColor:
  654.     return 3;
  655.     case StaticColor:
  656.     return 2;
  657.     case GrayScale:
  658.     return 1;
  659.     case StaticGray:
  660.     return 0;
  661.     }
  662. }
  663.  
  664. int
  665. IsGray(dpy, stdmap)
  666.     Display *dpy;
  667.     XStandardColormap *stdmap;
  668. {
  669.     XColor color;
  670.  
  671.     color.pixel = stdmap->base_pixel + (stdmap->red_max * stdmap->red_mult);
  672.     XQueryColor(dpy, stdmap->colormap, &color);
  673.     return (color.green || color.blue);
  674. }
  675.  
  676. Do_StdGray(dpy, stdmap, ncolors, colors, in_image, out_image)
  677.     Display *dpy;
  678.     XStandardColormap *stdmap;
  679.     int ncolors;
  680.     XColor *colors;
  681.     register XImage *in_image, *out_image;
  682. {
  683.     register int i, x, y;
  684.     register XColor *color;
  685.     unsigned lim;
  686.  
  687.     lim = stdmap->red_max + 1;
  688.     for (i = 0, color = colors; i < ncolors; i++, color++)
  689.     color->pixel = stdmap->base_pixel +
  690.                (((((int)(30L * color->red +
  691.                      59L * color->green +
  692.                      11L * color->blue) / 100)
  693.               * lim) >> 16) * stdmap->red_mult);
  694.     for (y = 0; y < in_image->height; y++) {
  695.     for (x = 0; x < in_image->width; x++) {
  696.         XPutPixel(out_image, x, y,
  697.               colors[XGetPixel(in_image, x, y)].pixel);
  698.     }
  699.     }
  700. }
  701.  
  702. #define MapVal(val,lim,mult) ((((val * lim) + 32768) / 65535) * mult)
  703.  
  704. Do_StdCol(dpy, stdmap, ncolors, colors, in_image, out_image)
  705.     Display *dpy;
  706.     XStandardColormap *stdmap;
  707.     int ncolors;
  708.     XColor *colors;
  709.     register XImage *in_image, *out_image;
  710. {
  711.     register int i, x, y;
  712.     register XColor *color;
  713.     unsigned limr, limg, limb;
  714.  
  715.     limr = stdmap->red_max;
  716.     limg = stdmap->green_max;
  717.     limb = stdmap->blue_max;
  718.     for (i = 0, color = colors; i < ncolors; i++, color++)
  719.     color->pixel = stdmap->base_pixel +
  720.                MapVal(color->red, limr, stdmap->red_mult) +
  721.                MapVal(color->green, limg, stdmap->green_mult) +
  722.                MapVal(color->blue, limb, stdmap->blue_mult);
  723.     for (y = 0; y < in_image->height; y++) {
  724.     for (x = 0; x < in_image->width; x++) {
  725.         XPutPixel(out_image, x, y,
  726.               colors[XGetPixel(in_image, x, y)].pixel);
  727.     }
  728.     }
  729. }
  730.  
  731. Colormap
  732. CopyColormapAndFree(dpy, colormap)
  733.     Display *dpy;
  734.     Colormap colormap;
  735. {
  736.     if (colormap == DefaultColormap(dpy, DefaultScreen(dpy)))
  737.     return XCopyColormapAndFree(dpy, colormap);
  738.     Error("Visual type is not large enough to hold all colors of the image.");
  739. }
  740.  
  741. Do_Pseudo(dpy, colormap, ncolors, colors, in_image, out_image)
  742.     Display *dpy;
  743.     Colormap *colormap;
  744.     int ncolors;
  745.     XColor *colors;
  746.     register XImage *in_image, *out_image;
  747. {
  748.     register int i, x, y;
  749.     register XColor *color;
  750.  
  751.     for (i = 0; i < ncolors; i++)
  752.     colors[i].flags = 0;
  753.     for (y = 0; y < in_image->height; y++) {
  754.     for (x = 0; x < in_image->width; x++) {
  755.         color = &colors[XGetPixel(in_image, x, y)];
  756.         if (!color->flags) {
  757.         color->flags = DoRed | DoGreen | DoBlue;
  758.         if (!XAllocColor(dpy, *colormap, color)) {
  759.             *colormap = CopyColormapAndFree(dpy, *colormap);
  760.             XAllocColor(dpy, *colormap, color);
  761.         }
  762.         }
  763.         XPutPixel(out_image, x, y, color->pixel);
  764.     }
  765.     }
  766. }
  767.  
  768. Do_Direct(dpy, header, colormap, ncolors, colors, in_image, out_image)
  769.     Display *dpy;
  770.     XWDFileHeader *header;
  771.     Colormap *colormap;
  772.     int ncolors;
  773.     XColor *colors;
  774.     XImage *in_image, *out_image;
  775. {
  776.     register int x, y;
  777.     XColor color;
  778.     unsigned long rmask, gmask, bmask;
  779.     int rshift = 0, gshift = 0, bshift = 0;
  780.     int i;
  781.     unsigned long pix, xpix;
  782.     unsigned long *pixels, *rpixels;
  783.  
  784.     rmask = header->red_mask;
  785.     while (!(rmask & 1)) {
  786.     rmask >>= 1;
  787.     rshift++;
  788.     }
  789.     gmask = header->green_mask;
  790.     while (!(gmask & 1)) {
  791.     gmask >>= 1;
  792.     gshift++;
  793.     }
  794.     bmask = header->blue_mask;
  795.     while (!(bmask & 1)) {
  796.     bmask >>= 1;
  797.     bshift++;
  798.     }
  799.     if (in_image->depth <= 12) {
  800.     pix = 1 << in_image->depth;
  801.     pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix);
  802.     for (i = 0; i < pix; i++)
  803.         pixels[i] = ~0L;
  804.     color.flags = DoRed | DoGreen | DoBlue;
  805.     for (y = 0; y < in_image->height; y++) {
  806.         for (x = 0; x < in_image->width; x++) {
  807.         pix = XGetPixel(in_image, x, y);
  808.         if ((color.pixel = pixels[pix]) == ~0L) {
  809.             color.red = (pix >> rshift) & rmask;
  810.             color.green = (pix >> gshift) & gmask;
  811.             color.blue = (pix >> bshift) & bmask;
  812.             if (ncolors) {
  813.             color.red = colors[color.red].red;
  814.             color.green = colors[color.green].green;
  815.             color.blue = colors[color.blue].blue;
  816.             } else {
  817.             color.red = (((unsigned long)color.red * 65535) /
  818.                      rmask);
  819.             color.green = (((unsigned long)color.green * 65535) /
  820.                        gmask);
  821.             color.blue = (((unsigned long)color.blue * 65535) /
  822.                       bmask);
  823.             }
  824.             if (!XAllocColor(dpy, *colormap, &color)) {
  825.             *colormap = CopyColormapAndFree(dpy, *colormap);
  826.             XAllocColor(dpy, *colormap, &color);
  827.             }
  828.             pixels[pix] = color.pixel;
  829.         }
  830.         XPutPixel(out_image, x, y, color.pixel);
  831.         }
  832.     }
  833.     } else {
  834.     pix = 1 << 12;
  835.     pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix);
  836.     rpixels = (unsigned long *)malloc(sizeof(unsigned long) * pix);
  837.     for (i = 0; i < pix; i++) {
  838.         pixels[i] = ~0L;
  839.         rpixels[i] = ~0L;
  840.     }
  841.     color.flags = DoRed | DoGreen | DoBlue;
  842.     for (y = 0; y < in_image->height; y++) {
  843.         for (x = 0; x < in_image->width; x++) {
  844.         pix = XGetPixel(in_image, x, y);
  845.         xpix = ((pix >> 12) ^ pix) & ((1 << 12) - 1);
  846.         if (((color.pixel = pixels[xpix]) == ~0L) ||
  847.             (rpixels[xpix] != pix)) {
  848.             color.red = (pix >> rshift) & rmask;
  849.             color.green = (pix >> gshift) & gmask;
  850.             color.blue = (pix >> bshift) & bmask;
  851.             if (ncolors) {
  852.             color.red = colors[color.red].red;
  853.             color.green = colors[color.green].green;
  854.             color.blue = colors[color.blue].blue;
  855.             } else {
  856.             color.red = (((unsigned long)color.red * 65535) /
  857.                      rmask);
  858.             color.green = (((unsigned long)color.green * 65535) /
  859.                        gmask);
  860.             color.blue = (((unsigned long)color.blue * 65535) /
  861.                       bmask);
  862.             }
  863.             if (!XAllocColor(dpy, *colormap, &color)) {
  864.             *colormap = CopyColormapAndFree(dpy, *colormap);
  865.             XAllocColor(dpy, *colormap, &color);
  866.             }
  867.             pixels[xpix] = color.pixel;
  868.             rpixels[xpix] = pix;
  869.         }
  870.         XPutPixel(out_image, x, y, color.pixel);
  871.         }
  872.     }
  873.     }
  874. }
  875.  
  876. unsigned Image_Size(image)
  877.      XImage *image;
  878. {
  879.     if (image->format != ZPixmap)
  880.       return(image->bytes_per_line * image->height * image->depth);
  881.  
  882.     return((unsigned)image->bytes_per_line * image->height);
  883. }
  884.  
  885. Error(string)
  886.     char *string;
  887. {
  888.     fprintf(stderr, "xwud: Error => %s\n", string);
  889.     if (errno != 0) {
  890.         perror("xwud");
  891.         fprintf(stderr, "\n");
  892.     }
  893.     exit(1);
  894. }
  895.  
  896. _swapshort (bp, n)
  897.     register char *bp;
  898.     register unsigned n;
  899. {
  900.     register char c;
  901.     register char *ep = bp + n;
  902.  
  903.     while (bp < ep) {
  904.     c = *bp;
  905.     *bp = *(bp + 1);
  906.     bp++;
  907.     *bp++ = c;
  908.     }
  909. }
  910.  
  911. _swaplong (bp, n)
  912.     register char *bp;
  913.     register unsigned n;
  914. {
  915.     register char c;
  916.     register char *ep = bp + n;
  917.     register char *sp;
  918.  
  919.     while (bp < ep) {
  920.     sp = bp + 3;
  921.     c = *sp;
  922.     *sp = *bp;
  923.     *bp++ = c;
  924.     sp = bp + 1;
  925.     c = *sp;
  926.     *sp = *bp;
  927.     *bp++ = c;
  928.     bp += 2;
  929.     }
  930. }
  931.