R6.6 is the Xorg base-line 53/9553/1
authorKaleb Keithley <kaleb@freedesktop.org>
Fri, 14 Nov 2003 15:54:55 +0000 (15:54 +0000)
committerSung-Jin Park <sj76.park@samsung.com>
Tue, 3 Sep 2013 04:25:28 +0000 (00:25 -0400)
Change-Id: I19f8e5635fa98321434b44c8178a0fbedb8610c9

xwud.c [new file with mode: 0644]
xwud.man [new file with mode: 0644]

diff --git a/xwud.c b/xwud.c
new file mode 100644 (file)
index 0000000..2b1e6c9
--- /dev/null
+++ b/xwud.c
@@ -0,0 +1,1144 @@
+/* $Xorg: xwud.c,v 1.5 2001/02/09 02:06:04 xorgcvs Exp $ */
+/*
+
+Copyright 1985, 1986, 1988, 1998  The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from The Open Group.
+
+*/
+
+/* xwud - marginally useful raster image undumper */
+
+
+#include <X11/Xos.h>
+#include <X11/Xlib.h>
+#include <X11/Xutil.h>
+#include <X11/Xatom.h>
+#include <stdio.h>
+#include <X11/XWDFile.h>
+#define  XK_LATIN1
+#include <X11/keysymdef.h>
+#include <errno.h>
+
+#ifdef X_NOT_STDC_ENV
+extern int errno;
+#endif
+
+extern char *malloc();
+unsigned Image_Size();
+Atom wm_protocols;
+Atom wm_delete_window;
+int split;
+
+char *progname;
+
+usage()
+{
+    fprintf(stderr, "usage: %s [-in <file>] [-noclick] [-geometry <geom>] [-display <display>]\n", progname);
+    fprintf(stderr, "            [-new] [-std <maptype>] [-raw] [-vis <vis-type-or-id>]\n");
+    fprintf(stderr, "            [-help] [-rv] [-plane <number>] [-fg <color>] [-bg <color>]\n");
+    fprintf(stderr, "            [-scale]\n");
+    exit(1);
+}
+
+Bool
+Read(ptr, size, nitems, stream)
+    char *ptr;
+    int size;
+    int nitems;
+    FILE *stream;
+{
+    size *= nitems;
+    while (size) {
+       nitems = fread(ptr, 1, size, stream);
+       if (nitems <= 0)
+           return False;
+       size -= nitems;
+       ptr += nitems;
+    }
+    return True;
+}
+
+main(argc, argv)
+    int argc;
+    char **argv;
+{
+    Display *dpy;
+    int screen;
+    register int i;
+    XImage in_image_struct;
+    XImage *in_image, *out_image;
+    XSetWindowAttributes attributes;
+    XVisualInfo vinfo, *vinfos;
+    long mask;
+    register char *buffer;
+    unsigned long swaptest = 1;
+    int count, stdcnt;
+    unsigned buffer_size;
+    int win_name_size;
+    int ncolors;
+    char *file_name = NULL;
+    char *win_name;
+    Bool inverse = False, rawbits = False, newmap = False;
+    Bool onclick = True;
+    Bool scale = False;
+    int plane = -1;
+    char *std = NULL;
+    char *vis = NULL;
+    char *display_name = NULL;
+    char *fgname = NULL;
+    char *bgname = NULL;
+    char *geom = NULL;
+    int gbits = 0;
+    XSizeHints hints;
+    XTextProperty textprop;
+    XClassHint class_hint;
+    XColor *colors, color, igncolor;
+    Window image_win;
+    Colormap colormap;
+    XEvent event;
+    register XExposeEvent *expose = (XExposeEvent *)&event;
+    GC gc;
+    XGCValues gc_val;
+    XWDFileHeader header;
+    XWDColor xwdcolor;
+    FILE *in_file = stdin;
+    char *map_name;
+    Atom map_prop;
+    XStandardColormap *stdmaps, *stdmap;
+    char c;
+    int win_width, win_height;
+
+    progname = argv[0];
+
+    for (i = 1; i < argc; i++) {
+       if (strcmp(argv[i], "-bg") == 0) {
+           if (++i >= argc) usage();
+           bgname = argv[i];
+           continue;
+       }
+       if (strcmp(argv[i], "-display") == 0) {
+           if (++i >= argc) usage();
+           display_name = argv[i];
+           continue;
+       }
+       if (strcmp(argv[i], "-fg") == 0) {
+           if (++i >= argc) usage();
+           fgname = argv[i];
+           continue;
+       }
+       if (strcmp(argv[i], "-geometry") == 0) {
+           if (++i >= argc) usage();
+           geom = argv[i];
+           continue;
+       }
+       if (strcmp(argv[i], "-help") == 0) {
+           usage();
+       }
+       if (strcmp(argv[i], "-in") == 0) {
+           if (++i >= argc) usage();
+           file_name = argv[i];
+           continue;
+       }
+       if (strcmp(argv[i], "-inverse") == 0) { /* for compatibility */
+           inverse = True;
+           continue;
+       }
+       if (strcmp(argv[i], "-new") == 0) {
+           newmap = True;
+           if (std) usage();
+           continue;
+       }
+       if (strcmp(argv[i], "-noclick") == 0) {
+           onclick = False;
+           continue;
+       }
+       if (strcmp(argv[i], "-plane") == 0) {
+           if (++i >= argc) usage();
+           plane = atoi(argv[i]);
+           continue;
+       }
+       if (strcmp(argv[i], "-raw") == 0) {
+           rawbits = True;
+           if (std) usage();
+           continue;
+       }
+       if (strcmp(argv[i], "-rv") == 0) {
+           inverse = True;
+           continue;
+       }
+       if (strcmp(argv[i], "-scale") == 0) {
+           scale = True;
+           continue;
+       }
+       if (strcmp(argv[i], "-split") == 0) {
+           split = True;
+           continue;
+       }
+       if (strcmp(argv[i], "-std") == 0) {
+           if (++i >= argc) usage();
+           std = argv[i];
+           if (newmap || rawbits) usage();
+           continue;
+       }
+       if (strcmp(argv[i], "-vis") == 0) {
+           if (++i >= argc) usage();
+           vis = argv[i];
+           continue;
+       }
+       usage();
+    }
+    
+    if (file_name) {
+       in_file = fopen(file_name, "rb");
+       if (in_file == NULL)
+           Error("Can't open input file as specified.");
+    }
+#ifdef WIN32
+    else
+       _setmode(fileno(in_file), _O_BINARY);
+#endif
+    
+    dpy = XOpenDisplay(display_name);
+    if (dpy == NULL) {
+       fprintf(stderr, "%s:  unable to open display \"%s\"\n",
+               progname, XDisplayName(display_name));
+       exit(1);
+    }
+    screen = DefaultScreen(dpy);
+
+    /*
+     * Read in header information.
+     */
+    if(!Read((char *)&header, SIZEOF(XWDheader), 1, in_file))
+      Error("Unable to read dump file header.");
+
+    if (*(char *) &swaptest)
+       _swaplong((char *) &header, SIZEOF(XWDheader));
+
+    /* check to see if the dump file is in the proper format */
+    if (header.file_version != XWD_FILE_VERSION) {
+       fprintf(stderr,"xwud: XWD file format version mismatch.");
+       Error("exiting.");
+    }
+    if (header.header_size < SIZEOF(XWDheader)) {
+       fprintf(stderr,"xwud: XWD header size is too small.");
+       Error("exiting.");
+    }
+
+    /* alloc window name */
+    win_name_size = (header.header_size - SIZEOF(XWDheader));
+    if((win_name = malloc((unsigned) win_name_size + 6)) == NULL)
+      Error("Can't malloc window name storage.");
+    strcpy(win_name, "xwud: ");
+
+     /* read in window name */
+    if(!Read(win_name + 6, sizeof(char), win_name_size, in_file))
+      Error("Unable to read window name from dump file.");
+
+    /* initialize the input image */
+
+    in_image = &in_image_struct;
+    in_image->depth = header.pixmap_depth;
+    in_image->format = header.pixmap_format;
+    in_image->xoffset = header.xoffset;
+    in_image->data = NULL;
+    in_image->width = header.pixmap_width;
+    in_image->height = header.pixmap_height;
+    in_image->bitmap_pad = header.bitmap_pad;
+    in_image->bytes_per_line = header.bytes_per_line;
+    in_image->byte_order = header.byte_order;
+    in_image->bitmap_unit = header.bitmap_unit;
+    in_image->bitmap_bit_order = header.bitmap_bit_order;
+    in_image->bits_per_pixel = header.bits_per_pixel;
+    in_image->red_mask = header.red_mask;
+    in_image->green_mask = header.green_mask;
+    in_image->blue_mask = header.blue_mask;
+    if (!XInitImage(in_image))
+       Error("Invalid input image header data.");
+
+    /* read in the color map buffer */
+    if((ncolors = header.ncolors)) {
+       colors = (XColor *)malloc((unsigned) ncolors * sizeof(XColor));
+       if (!colors)
+           Error("Can't malloc color table");
+       for (i = 0; i < ncolors; i++) {
+           if(!Read((char *) &xwdcolor, SIZEOF(XWDColor), 1, in_file))
+               Error("Unable to read color map from dump file.");
+           colors[i].pixel = xwdcolor.pixel;
+           colors[i].red = xwdcolor.red;
+           colors[i].green = xwdcolor.green;
+           colors[i].blue = xwdcolor.blue;
+           colors[i].flags = xwdcolor.flags;
+       }
+       if (*(char *) &swaptest) {
+           for (i = 0; i < ncolors; i++) {
+               _swaplong((char *) &colors[i].pixel, sizeof(long));
+               _swapshort((char *) &colors[i].red, 3 * sizeof(short));
+           }
+       }
+    }
+    else
+       /* no color map exists, turn on the raw option */
+       rawbits = True;
+
+    /* alloc the pixel buffer */
+    buffer_size = Image_Size(in_image);
+    if((buffer = malloc(buffer_size)) == NULL)
+      Error("Can't malloc data buffer.");
+
+    /* read in the image data */
+    if (!Read(buffer, sizeof(char), (int)buffer_size, in_file))
+        Error("Unable to read pixmap from dump file.");
+
+     /* close the input file */
+    (void) fclose(in_file);
+
+    if (plane >= in_image->depth)
+       Error("plane number exceeds image depth");
+    if ((in_image->format == XYPixmap) && (plane >= 0)) {
+       buffer += in_image->bytes_per_line * in_image->height *
+                 (in_image->depth - (plane + 1));
+       in_image->depth = 1;
+       ncolors = 0;
+    }
+    if (in_image->bits_per_pixel == 1 && in_image->depth == 1) {
+       in_image->format = XYBitmap;
+       newmap = False;
+       rawbits = True;
+    }
+    in_image->data = buffer;
+
+    if (std) {
+       map_name = malloc(strlen(std) + 9);
+       strcpy(map_name, "RGB_");
+       strcat(map_name, std);
+       strcat(map_name, "_MAP");
+       Latin1Upper(map_name);
+       map_prop = XInternAtom(dpy, map_name, True);
+       if (!map_prop || !XGetRGBColormaps(dpy, RootWindow(dpy, screen),
+                                          &stdmaps, &stdcnt, map_prop))
+           Error("specified standard colormap does not exist");
+    }
+    vinfo.screen = screen;
+    mask = VisualScreenMask;
+    if (vis)
+    {
+       char *vt;
+       vt = malloc(strlen(vis) + 1);
+       strcpy(vt, vis);
+       Latin1Upper(vt);
+       if (strcmp(vt, "STATICGRAY") == 0) {
+           vinfo.class = StaticGray;
+           mask |= VisualClassMask;
+       } else if (strcmp(vt, "GRAYSCALE") == 0) {
+           vinfo.class = GrayScale;
+           mask |= VisualClassMask;
+       } else if (strcmp(vt, "STATICCOLOR") == 0) {
+           vinfo.class = StaticColor;
+           mask |= VisualClassMask;
+       } else if (strcmp(vt, "PSEUDOCOLOR") == 0) {
+           vinfo.class = PseudoColor;
+           mask |= VisualClassMask;
+       } else if (strcmp(vt, "DIRECTCOLOR") == 0) {
+           vinfo.class = DirectColor;
+           mask |= VisualClassMask;
+       } else if (strcmp(vt, "TRUECOLOR") == 0) {
+           vinfo.class = TrueColor;
+           mask |= VisualClassMask;
+       } else if (strcmp(vt, "MATCH") == 0) {
+           vinfo.class = header.visual_class;
+           mask |= VisualClassMask;
+       } else if (strcmp(vt, "DEFAULT") == 0) {
+           vinfo.visualid= XVisualIDFromVisual(DefaultVisual(dpy, screen));
+           mask |= VisualIDMask;
+       } else {
+           vinfo.visualid = 0;
+           mask |= VisualIDMask;
+           sscanf(vis, "0x%lx", &vinfo.visualid);
+           if (!vinfo.visualid)
+             sscanf(vis, "%ld", &vinfo.visualid);
+           if (!vinfo.visualid)
+             Error("invalid visual specifier");
+       }
+    }
+    if (rawbits && (in_image->depth > 1) && (plane < 0)) {
+       vinfo.depth = in_image->depth;
+       mask |= VisualDepthMask;
+    }
+    vinfos = XGetVisualInfo(dpy, mask, &vinfo, &count);
+    if (count == 0)
+       Error("no matching visual found");
+
+    /* find a workable visual */
+    if (std) {
+       stdmap = &stdmaps[0];
+       if (mask & VisualIDMask) {
+           for (i = 0; i < stdcnt; i++) {
+               if (stdmaps[i].visualid == vinfo.visualid) {
+                   stdmap = &stdmaps[i];
+                   break;
+               }
+           }
+           if (stdmap->visualid != vinfo.visualid)
+               Error("no standard colormap matching specified visual");
+       }
+       for (i = 0; i < count; i++) {
+           if (stdmap->visualid == vinfos[i].visualid) {
+               vinfo = vinfos[i];
+               break;
+           }
+       }
+    } else if ((in_image->depth == 1) ||
+              ((in_image->format == ZPixmap) && (plane >= 0)) ||
+              rawbits) {
+       vinfo = vinfos[0];
+       if (!(mask & VisualIDMask)) {
+           for (i = 0; i < count; i++) {
+               if ((vinfos[i].visualid ==
+                    XVisualIDFromVisual(DefaultVisual(dpy, screen))) &&
+                   (vinfos[i].depth == DefaultDepth(dpy, screen))) {
+                   vinfo = vinfos[i];
+                   break;
+               }
+           }
+       }
+    } else {
+       /* get best visual */
+       vinfo = vinfos[0];
+       for (i = 0; i < count; i++) {
+           int z1, z2;
+           z2 = EffectiveSize(&vinfos[i]);
+           if ((z2 >= ncolors) &&
+               (vinfos[i].depth == in_image->depth) &&
+               (vinfos[i].class == header.visual_class))
+           {
+               vinfo = vinfos[i];
+               break;
+           }
+           z1 = EffectiveSize(&vinfo);
+           if ((z2 > z1) ||
+               ((z2 == z1) &&
+                (VisualRank(vinfos[i].class) >= VisualRank(vinfo.class))))
+               vinfo = vinfos[i];
+       }
+       if ((newmap || (vinfo.visual != DefaultVisual(dpy, screen))) &&
+           (vinfo.class != StaticGray) &&
+           (vinfo.class != StaticColor) &&
+           (vinfo.class == header.visual_class) &&
+           (vinfo.depth == in_image->depth) &&
+           ((vinfo.class == PseudoColor) ||
+            (vinfo.class == GrayScale) ||
+            ((vinfo.red_mask == header.red_mask) &&
+             (vinfo.green_mask == header.green_mask) &&
+             (vinfo.blue_mask == header.blue_mask)))) {
+           rawbits = True;
+           newmap = True;
+       }
+    }
+
+    /* get the appropriate colormap */
+    if (newmap && (vinfo.class & 1) &&
+       (vinfo.depth == in_image->depth) &&
+       (vinfo.class == header.visual_class) &&
+       (vinfo.colormap_size >= ncolors) &&
+       (vinfo.red_mask == header.red_mask) &&
+       (vinfo.green_mask == header.green_mask) &&
+       (vinfo.blue_mask == header.blue_mask)) {
+       colormap = XCreateColormap(dpy, RootWindow(dpy, screen), vinfo.visual,
+                                  AllocAll);
+       if (ncolors) {
+           for (i = 0; i < ncolors; i++)
+               colors[i].flags = DoRed|DoGreen|DoBlue;
+           XStoreColors(dpy, colormap, colors, ncolors);
+       }
+    } else if (std) {
+       colormap = stdmap->colormap;
+    } else {
+       if (!newmap && (vinfo.visual == DefaultVisual(dpy, screen)))
+           colormap = DefaultColormap(dpy, screen);
+       else
+           colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
+                                      vinfo.visual, AllocNone);
+       newmap = False;
+    }
+
+    /* create the output image */
+    if ((in_image->format == ZPixmap) && (plane >= 0)) {
+       out_image = XCreateImage(dpy, vinfo.visual, 1,
+                                XYBitmap, 0, NULL,
+                                in_image->width, in_image->height,
+                                XBitmapPad(dpy), 0);
+       out_image->data = malloc(Image_Size(out_image));
+       Extract_Plane(in_image, out_image, plane);
+       ncolors = 0;
+    } else if (rawbits || newmap) {
+       out_image = in_image;
+    } else {
+       out_image = XCreateImage(dpy, vinfo.visual, vinfo.depth,
+                                (vinfo.depth == 1) ? XYBitmap :
+                                                     in_image->format,
+                                in_image->xoffset, NULL,
+                                in_image->width, in_image->height,
+                                XBitmapPad(dpy), 0);
+       out_image->data = malloc(Image_Size(out_image));
+       if (std) {
+           if (!stdmap->green_max && !stdmap->blue_max && IsGray(dpy, stdmap))
+               Do_StdGray(dpy, stdmap, ncolors, colors, in_image, out_image);
+           else
+               Do_StdCol(dpy, stdmap, ncolors, colors, in_image, out_image);
+       } else if ((header.visual_class == TrueColor) ||
+                  (header.visual_class == DirectColor))
+           Do_Direct(dpy, &header, &colormap, ncolors, colors,
+                     in_image, out_image);
+       else
+           Do_Pseudo(dpy, &colormap, ncolors, colors, in_image, out_image);
+    }
+
+    if (out_image->depth == 1) {
+       if (fgname &&
+           XAllocNamedColor(dpy, colormap, fgname, &color, &igncolor))
+           gc_val.foreground = color.pixel;
+       else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[1]))
+           gc_val.foreground = colors[1].pixel;
+       else
+           gc_val.foreground = BlackPixel (dpy, screen);
+       if (bgname &&
+           XAllocNamedColor(dpy, colormap, bgname, &color, &igncolor))
+           gc_val.background = color.pixel;
+       else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[0]))
+           gc_val.background = colors[0].pixel;
+       else
+           gc_val.background = WhitePixel (dpy, screen);
+       if (inverse) {
+           unsigned long tmp;
+           tmp = gc_val.foreground;
+           gc_val.foreground = gc_val.background;
+           gc_val.background = tmp;
+       }
+    } else {
+       gc_val.background = XGetPixel(out_image, 0, 0);
+       gc_val.foreground = 0;
+    }
+
+    attributes.background_pixel = gc_val.background;
+    attributes.border_pixel = gc_val.background;
+    if (scale)
+       attributes.bit_gravity = ForgetGravity;
+    else
+       attributes.bit_gravity = NorthWestGravity;
+    attributes.event_mask = ButtonPressMask|ButtonReleaseMask|KeyPressMask|
+                           ExposureMask;
+    if (scale)
+       attributes.event_mask |= StructureNotifyMask;
+    attributes.colormap = colormap;
+
+    hints.x = header.window_x;
+    hints.y = header.window_y;
+    hints.width = out_image->width;
+    hints.height = out_image->height;
+    if (geom)
+       gbits = XParseGeometry(geom, &hints.x, &hints.y,
+                              (unsigned int *)&hints.width,
+                              (unsigned int *)&hints.height);
+    hints.flags = ((gbits & (XValue|YValue)) ? USPosition : 0) |
+                 ((gbits & (HeightValue|WidthValue)) ? USSize : PSize);
+    if (!scale) {
+       hints.flags |= PMaxSize;
+       hints.max_width = (hints.width > out_image->width) ?
+           hints.width : out_image->width;
+       hints.max_height = (hints.height > out_image->height) ?
+           hints.height : out_image->height;
+    }
+    if ((gbits & XValue) && (gbits & XNegative))
+       hints.x += DisplayWidth(dpy, screen) - hints.width; 
+    if ((gbits & YValue) && (gbits & YNegative))
+       hints.y += DisplayHeight(dpy, screen) - hints.height;
+
+    /* create the image window */
+    image_win = XCreateWindow(dpy, RootWindow(dpy, screen),
+                             hints.x, hints.y, hints.width, hints.height,
+                             0, vinfo.depth, InputOutput, vinfo.visual,
+                             CWBorderPixel|CWBackPixel|CWColormap|CWEventMask|CWBitGravity,
+                             &attributes);
+    win_width = hints.width;
+    win_height = hints.height;
+
+    /* Setup for ICCCM delete window. */
+    wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
+    wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
+    (void) XSetWMProtocols (dpy, image_win, &wm_delete_window, 1);
+     
+    textprop.value = (unsigned char *) win_name;
+    textprop.encoding = XA_STRING;
+    textprop.format = 8;
+    textprop.nitems = strlen(win_name);
+    class_hint.res_name = (char *)NULL;
+    class_hint.res_class = "Xwud";
+    /* set standard properties */
+    XSetWMProperties(dpy, image_win, &textprop, (XTextProperty *)NULL,
+                    argv, argc, &hints, (XWMHints *)NULL, &class_hint);
+
+    /* map the image window */
+    XMapWindow(dpy, image_win);
+
+    gc = XCreateGC (dpy, image_win, GCForeground|GCBackground, &gc_val);
+
+    while (1) {
+       /* wait on mouse input event to terminate */
+       XNextEvent(dpy, &event);
+       switch(event.type) {
+       case ClientMessage:
+         if (event.xclient.message_type == wm_protocols && 
+             event.xclient.data.l[0] == wm_delete_window)  {
+           XCloseDisplay(dpy);
+           exit(0);            /* ICCCM delete window */
+         }
+           break;
+       case ButtonPress:
+           break;
+       case ButtonRelease:
+           if (onclick) {
+               XCloseDisplay(dpy);
+               exit(0);
+           }
+           break;
+       case KeyPress:
+           i = XLookupString(&event.xkey, &c, 1, NULL, NULL);
+           if ((i == 1) && ((c == 'q') || (c == 'Q') || (c == '\03'))) {
+               XCloseDisplay(dpy);
+               exit(0);
+           }
+           break;
+       case ConfigureNotify:
+           win_width = event.xconfigure.width;
+           win_height = event.xconfigure.height;
+           break;
+       case Expose:
+           if (scale)
+               putScaledImage(dpy, image_win, gc, out_image,
+                              expose->x, expose->y,
+                              expose->width, expose->height,
+                              win_width, win_height);
+           else if ((expose->x < out_image->width) &&
+                    (expose->y < out_image->height)) {
+               if ((out_image->width - expose->x) < expose->width)
+                   expose->width = out_image->width - expose->x;
+               if ((out_image->height - expose->y) < expose->height)
+                   expose->height = out_image->height - expose->y;
+               putImage(dpy, image_win, gc, out_image,
+                         expose->x, expose->y,
+                         expose->width, expose->height);
+           }
+           break;
+       }
+    }
+}
+
+putImage (dpy, image_win, gc, out_image, x, y, w, h)
+    Display    *dpy;
+    Window     image_win;
+    GC         gc;
+    XImage     *out_image;
+    int                x, y, w, h;
+{
+#define SPLIT_SIZE  100
+    int        t_x, t_y, t_w, t_h;
+    if (split) {
+       for (t_y = y; t_y < y + h; t_y += t_h) {
+           t_h = SPLIT_SIZE;
+           if (t_y + t_h > y + h)
+               t_h = y + h - t_y;
+           for (t_x = x; t_x < x + w; t_x += t_w) {
+               t_w = SPLIT_SIZE;
+               if (t_x + t_w > x + w)
+                   t_w = x + w - t_x;
+               XPutImage(dpy, image_win, gc, out_image,
+                         t_x, t_y, t_x, t_y, t_w, t_h);
+           }
+       }
+    } else {
+       XPutImage (dpy, image_win, gc, out_image, x, y, x, y, w, h);
+    }
+}
+
+typedef short Position;
+typedef unsigned short Dimension;
+typedef unsigned long Pixel;
+
+#define roundint(x)                   (int)((x) + 0.5)
+
+typedef struct {
+  Position *x, *y;
+  Dimension *width, *height;
+} Table;
+
+putScaledImage(display, d, gc, src_image, exp_x, exp_y,
+              exp_width, exp_height, dest_width, dest_height)
+    Display*            display;
+    Drawable            d;
+    GC                  gc;
+    XImage*             src_image;
+    int                         exp_x;
+    int                         exp_y;
+    unsigned int        exp_width;
+    unsigned int        exp_height;
+    unsigned int        dest_width;
+    unsigned int        dest_height;
+{
+    XImage *dest_image;
+    Position x, y, min_y, max_y, exp_max_y, src_x, src_max_x, src_y;
+    Dimension w, h, strip_height;
+    Table table;    
+    Pixel pixel;
+    double ratio_x, ratio_y;
+    Bool fast8;
+
+    if (dest_width == src_image->width && dest_height == src_image->height) {
+       /* same for x and y, just send it out */
+       XPutImage(display, d, gc, src_image, exp_x, exp_y, 
+                 exp_x, exp_y, exp_width, exp_height); 
+       return;
+    }
+
+    ratio_x = (double)dest_width / (double)src_image->width;
+    ratio_y = (double)dest_height / (double)src_image->height;
+    src_x = exp_x / ratio_x;
+    if (src_x >= src_image->width)
+       src_x = src_image->width - 1;
+    src_y = exp_y / ratio_y;
+    if (src_y >= src_image->height)
+       src_y = src_image->height - 1;
+    exp_max_y = exp_y + exp_height;
+    src_max_x = roundint((exp_x + exp_width) / ratio_x) + 1;
+    if (src_max_x > src_image->width)
+       src_max_x = src_image->width;
+
+    strip_height = 65536 / roundint(ratio_x * src_image->bytes_per_line);
+    if (strip_height == 0)
+       strip_height = 1;
+    if (strip_height > exp_height)
+       strip_height = exp_height;
+
+    h = strip_height + roundint(ratio_y);
+    dest_image = XCreateImage(display,
+                             DefaultVisualOfScreen(
+                                            DefaultScreenOfDisplay(display)),
+                             src_image->depth, src_image->format, 
+                             0, NULL,
+                             dest_width, h,
+                             src_image->bitmap_pad, 0);
+    dest_image->data = malloc(dest_image->bytes_per_line * h);
+    fast8 = (src_image->depth == 8 && src_image->bits_per_pixel == 8 &&
+            dest_image->bits_per_pixel == 8 && src_image->format == ZPixmap);
+
+    table.x = (Position *) malloc(sizeof(Position) * (src_image->width + 1));
+    table.y = (Position *) malloc(sizeof(Position) * (src_image->height + 1));
+    table.width = (Dimension *) malloc(sizeof(Dimension) * src_image->width);
+    table.height = (Dimension *) malloc(sizeof(Dimension)*src_image->height);
+    
+    table.x[0] = 0;
+    for (x = 1; x <= src_image->width; x++) {
+       table.x[x] = roundint(ratio_x * x);
+       table.width[x - 1] = table.x[x] - table.x[x - 1];
+    }
+
+    table.y[0] = 0;
+    for (y = 1; y <= src_image->height; y++) {
+       table.y[y] = roundint(ratio_y * y);
+       table.height[y - 1] = table.y[y] - table.y[y - 1];
+    }
+
+    for (min_y = table.y[src_y]; min_y < exp_max_y; min_y = table.y[y]) {
+       max_y = min_y + strip_height;
+       if (max_y > exp_max_y) {
+           strip_height = exp_max_y - min_y;
+           max_y = exp_max_y;
+       }
+       for (y = src_y; table.y[y] < max_y; y++) {
+           if (table.y[y] < min_y)
+               continue;
+           if (fast8) {
+               for (x = src_x; x < src_max_x; x++) {
+                   pixel = ((unsigned char *)src_image->data)
+                       [y * src_image->bytes_per_line + x];
+                   for (h = 0; h < table.height[y]; h++) {
+                       memset(dest_image->data +
+                              (table.y[y] + h - min_y) *
+                              dest_image->bytes_per_line + table.x[x],
+                              pixel, table.width[x]);
+                   }
+               }
+           } else {
+               for (x = src_x; x < src_max_x; x++) {
+                   pixel = XGetPixel(src_image, x, y);
+                   for (h = 0; h < table.height[y]; h++) {
+                       for (w = 0; w < table.width[x]; w++)
+                           XPutPixel(dest_image,
+                                     table.x[x] + w,
+                                     table.y[y] + h - min_y,
+                                     pixel);
+                   }
+               }
+           }
+       }
+       XPutImage(display, d, gc, dest_image, exp_x, 0,
+                 exp_x, min_y, exp_width, table.y[y] - min_y);
+       if (y >= src_image->height)
+           break;
+    }
+    
+    XFree((char *)table.x);
+    XFree((char *)table.y);
+    XFree((char *)table.width);
+    XFree((char *)table.height);
+
+    XDestroyImage(dest_image);
+}
+
+Latin1Upper(s)
+    char *s;
+{
+    unsigned char *str = (unsigned char *)s;
+    unsigned char c;
+
+    for (; (c = *str); str++)
+    {
+       if ((c >= XK_a) && (c <= XK_z))
+           *str = c - (XK_a - XK_A);
+       else if ((c >= XK_agrave) && (c <= XK_odiaeresis))
+           *str = c - (XK_agrave - XK_Agrave);
+       else if ((c >= XK_oslash) && (c <= XK_thorn))
+           *str = c - (XK_oslash - XK_Ooblique);
+    }
+}
+
+Extract_Plane(in_image, out_image, plane)
+    register XImage *in_image, *out_image;
+    int plane;
+{
+    register int x, y;
+
+    for (y = 0; y < in_image->height; y++)
+       for (x = 0; x < in_image->width; x++)
+           XPutPixel(out_image, x, y,
+                     (XGetPixel(in_image, x, y) >> plane) & 1);
+}
+
+int
+EffectiveSize(vinfo)
+    XVisualInfo *vinfo;
+{
+    if ((vinfo->class == DirectColor) || (vinfo->class == TrueColor))
+       return (vinfo->red_mask | vinfo->green_mask | vinfo->blue_mask) + 1;
+    else
+       return vinfo->colormap_size;
+}
+
+VisualRank(class)
+    int class;
+{
+    switch (class) {
+    case PseudoColor:
+       return 5;
+    case DirectColor:
+       return 4;
+    case TrueColor:
+       return 3;
+    case StaticColor:
+       return 2;
+    case GrayScale:
+       return 1;
+    case StaticGray:
+       return 0;
+    }
+}
+
+int
+IsGray(dpy, stdmap)
+    Display *dpy;
+    XStandardColormap *stdmap;
+{
+    XColor color;
+
+    color.pixel = stdmap->base_pixel + (stdmap->red_max * stdmap->red_mult);
+    XQueryColor(dpy, stdmap->colormap, &color);
+    return (color.green || color.blue);
+}
+
+Do_StdGray(dpy, stdmap, ncolors, colors, in_image, out_image)
+    Display *dpy;
+    XStandardColormap *stdmap;
+    int ncolors;
+    XColor *colors;
+    register XImage *in_image, *out_image;
+{
+    register int i, x, y;
+    register XColor *color;
+    unsigned lim;
+
+    lim = stdmap->red_max + 1;
+    for (i = 0, color = colors; i < ncolors; i++, color++)
+       color->pixel = stdmap->base_pixel +
+                      (((((int)(30L * color->red +
+                                59L * color->green +
+                                11L * color->blue) / 100)
+                         * lim) >> 16) * stdmap->red_mult);
+    for (y = 0; y < in_image->height; y++) {
+       for (x = 0; x < in_image->width; x++) {
+           XPutPixel(out_image, x, y,
+                     colors[XGetPixel(in_image, x, y)].pixel);
+       }
+    }
+}
+
+#define MapVal(val,lim,mult) ((((val * lim) + 32768) / 65535) * mult)
+
+Do_StdCol(dpy, stdmap, ncolors, colors, in_image, out_image)
+    Display *dpy;
+    XStandardColormap *stdmap;
+    int ncolors;
+    XColor *colors;
+    register XImage *in_image, *out_image;
+{
+    register int i, x, y;
+    register XColor *color;
+    unsigned limr, limg, limb;
+
+    limr = stdmap->red_max;
+    limg = stdmap->green_max;
+    limb = stdmap->blue_max;
+    for (i = 0, color = colors; i < ncolors; i++, color++)
+       color->pixel = stdmap->base_pixel +
+                      MapVal(color->red, limr, stdmap->red_mult) +
+                      MapVal(color->green, limg, stdmap->green_mult) +
+                      MapVal(color->blue, limb, stdmap->blue_mult);
+    for (y = 0; y < in_image->height; y++) {
+       for (x = 0; x < in_image->width; x++) {
+           XPutPixel(out_image, x, y,
+                     colors[XGetPixel(in_image, x, y)].pixel);
+       }
+    }
+}
+
+Colormap
+CopyColormapAndFree(dpy, colormap)
+    Display *dpy;
+    Colormap colormap;
+{
+    if (colormap == DefaultColormap(dpy, DefaultScreen(dpy)))
+       return XCopyColormapAndFree(dpy, colormap);
+    Error("Visual type is not large enough to hold all colors of the image.");
+}
+
+Do_Pseudo(dpy, colormap, ncolors, colors, in_image, out_image)
+    Display *dpy;
+    Colormap *colormap;
+    int ncolors;
+    XColor *colors;
+    register XImage *in_image, *out_image;
+{
+    register int i, x, y;
+    register XColor *color;
+
+    for (i = 0; i < ncolors; i++)
+       colors[i].flags = 0;
+    for (y = 0; y < in_image->height; y++) {
+       for (x = 0; x < in_image->width; x++) {
+           color = &colors[XGetPixel(in_image, x, y)];
+           if (!color->flags) {
+               color->flags = DoRed | DoGreen | DoBlue;
+               if (!XAllocColor(dpy, *colormap, color)) {
+                   *colormap = CopyColormapAndFree(dpy, *colormap);
+                   XAllocColor(dpy, *colormap, color);
+               }
+           }
+           XPutPixel(out_image, x, y, color->pixel);
+       }
+    }
+}
+
+Do_Direct(dpy, header, colormap, ncolors, colors, in_image, out_image)
+    Display *dpy;
+    XWDFileHeader *header;
+    Colormap *colormap;
+    int ncolors;
+    XColor *colors;
+    XImage *in_image, *out_image;
+{
+    register int x, y;
+    XColor color;
+    unsigned long rmask, gmask, bmask;
+    int rshift = 0, gshift = 0, bshift = 0;
+    int i;
+    unsigned long pix, xpix;
+    unsigned long *pixels, *rpixels;
+
+    rmask = header->red_mask;
+    while (!(rmask & 1)) {
+       rmask >>= 1;
+       rshift++;
+    }
+    gmask = header->green_mask;
+    while (!(gmask & 1)) {
+       gmask >>= 1;
+       gshift++;
+    }
+    bmask = header->blue_mask;
+    while (!(bmask & 1)) {
+       bmask >>= 1;
+       bshift++;
+    }
+    if (in_image->depth <= 12) {
+       pix = 1 << in_image->depth;
+       pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix);
+       for (i = 0; i < pix; i++)
+           pixels[i] = ~0L;
+       color.flags = DoRed | DoGreen | DoBlue;
+       for (y = 0; y < in_image->height; y++) {
+           for (x = 0; x < in_image->width; x++) {
+               pix = XGetPixel(in_image, x, y);
+               if ((color.pixel = pixels[pix]) == ~0L) {
+                   color.red = (pix >> rshift) & rmask;
+                   color.green = (pix >> gshift) & gmask;
+                   color.blue = (pix >> bshift) & bmask;
+                   if (ncolors) {
+                       color.red = colors[color.red].red;
+                       color.green = colors[color.green].green;
+                       color.blue = colors[color.blue].blue;
+                   } else {
+                       color.red = (((unsigned long)color.red * 65535) /
+                                    rmask);
+                       color.green = (((unsigned long)color.green * 65535) /
+                                      gmask);
+                       color.blue = (((unsigned long)color.blue * 65535) /
+                                     bmask);
+                   }
+                   if (!XAllocColor(dpy, *colormap, &color)) {
+                       *colormap = CopyColormapAndFree(dpy, *colormap);
+                       XAllocColor(dpy, *colormap, &color);
+                   }
+                   pixels[pix] = color.pixel;
+               }
+               XPutPixel(out_image, x, y, color.pixel);
+           }
+       }
+    } else {
+       pix = 1 << 12;
+       pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix);
+       rpixels = (unsigned long *)malloc(sizeof(unsigned long) * pix);
+       for (i = 0; i < pix; i++) {
+           pixels[i] = ~0L;
+           rpixels[i] = ~0L;
+       }
+       color.flags = DoRed | DoGreen | DoBlue;
+       for (y = 0; y < in_image->height; y++) {
+           for (x = 0; x < in_image->width; x++) {
+               pix = XGetPixel(in_image, x, y);
+               xpix = ((pix >> 12) ^ pix) & ((1 << 12) - 1);
+               if (((color.pixel = pixels[xpix]) == ~0L) ||
+                   (rpixels[xpix] != pix)) {
+                   color.red = (pix >> rshift) & rmask;
+                   color.green = (pix >> gshift) & gmask;
+                   color.blue = (pix >> bshift) & bmask;
+                   if (ncolors) {
+                       color.red = colors[color.red].red;
+                       color.green = colors[color.green].green;
+                       color.blue = colors[color.blue].blue;
+                   } else {
+                       color.red = (((unsigned long)color.red * 65535) /
+                                    rmask);
+                       color.green = (((unsigned long)color.green * 65535) /
+                                      gmask);
+                       color.blue = (((unsigned long)color.blue * 65535) /
+                                     bmask);
+                   }
+                   if (!XAllocColor(dpy, *colormap, &color)) {
+                       *colormap = CopyColormapAndFree(dpy, *colormap);
+                       XAllocColor(dpy, *colormap, &color);
+                   }
+                   pixels[xpix] = color.pixel;
+                   rpixels[xpix] = pix;
+               }
+               XPutPixel(out_image, x, y, color.pixel);
+           }
+       }
+    }
+}
+
+unsigned Image_Size(image)
+     XImage *image;
+{
+    if (image->format != ZPixmap)
+      return(image->bytes_per_line * image->height * image->depth);
+
+    return((unsigned)image->bytes_per_line * image->height);
+}
+
+Error(string)
+       char *string;
+{
+       fprintf(stderr, "xwud: Error => %s\n", string);
+       if (errno != 0) {
+               perror("xwud");
+               fprintf(stderr, "\n");
+       }
+       exit(1);
+}
+
+_swapshort (bp, n)
+    register char *bp;
+    register unsigned n;
+{
+    register char c;
+    register char *ep = bp + n;
+
+    while (bp < ep) {
+       c = *bp;
+       *bp = *(bp + 1);
+       bp++;
+       *bp++ = c;
+    }
+}
+
+_swaplong (bp, n)
+    register char *bp;
+    register unsigned n;
+{
+    register char c;
+    register char *ep = bp + n;
+    register char *sp;
+
+    while (bp < ep) {
+       sp = bp + 3;
+       c = *sp;
+       *sp = *bp;
+       *bp++ = c;
+       sp = bp + 1;
+       c = *sp;
+       *sp = *bp;
+       *bp++ = c;
+       bp += 2;
+    }
+}
diff --git a/xwud.man b/xwud.man
new file mode 100644 (file)
index 0000000..6a730df
--- /dev/null
+++ b/xwud.man
@@ -0,0 +1,150 @@
+.\" $Xorg: xwud.man,v 1.4 2001/02/09 02:06:04 xorgcvs Exp $
+.\" Copyright 1988, 1998  The Open Group
+.\" 
+.\" Permission to use, copy, modify, distribute, and sell this software and its
+.\" documentation for any purpose is hereby granted without fee, provided that
+.\" the above copyright notice appear in all copies and that both that
+.\" copyright notice and this permission notice appear in supporting
+.\" documentation.
+.\" 
+.\" The above copyright notice and this permission notice shall be included
+.\" in all copies or substantial portions of the Software.
+.\" 
+.\" THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+.\" OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+.\" MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+.\" IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
+.\" OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+.\" ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+.\" OTHER DEALINGS IN THE SOFTWARE.
+.\" 
+.\" Except as contained in this notice, the name of The Open Group shall
+.\" not be used in advertising or otherwise to promote the sale, use or
+.\" other dealings in this Software without prior written authorization
+.\" from The Open Group.
+.TH XWUD 1 "Release 6.4" "X Version 11"
+.SH NAME
+xwud - image displayer for X
+.SH SYNOPSIS
+.B "xwud"
+[-in \fIfile\fP] [-noclick] [-geometry \fIgeom\fP] [-display \fIdisplay\fP]
+[-new] [-std <maptype>] [-raw] [-vis <vis-type-or-id>] [-scale]
+[-help] [-rv] [-plane \fInumber\fP] [-fg \fIcolor\fP] [-bg \fIcolor\fP]
+.SH DESCRIPTION
+.PP
+.I Xwud
+is an X Window System image undumping utility.
+.I Xwud
+allows X users to display in a window an image saved
+in a specially formatted dump file, such as produced by \fIxwd(1)\fP.
+.SH OPTIONS
+.PP
+.TP 8
+.B "-bg \fIcolor\fP"
+If a bitmap image (or a single plane of an image) is displayed, this option
+can be used to specify the color to display for the "0" bits in the image.
+.PP
+.TP 8
+.B "-display \fIdisplay\fP"
+This option allows you to specify the server to connect to; see \fIX(1)\fP.
+.PP
+.TP 8
+.B "-fg \fIcolor\fP"
+If a bitmap image (or a single plane of an image) is displayed, this option
+can be used to specify the color to display for the "1" bits in the image.
+.PP
+.TP 8
+.B "-geometry \fIgeom\fP"
+This option allows you to specify the size and position of the window.
+Typically you will only want to specify the position, and let the size
+default to the actual size of the image.
+.PP
+.TP 8
+.B "-help"
+Print out a short description of the allowable options.
+.PP
+.TP 8
+.B "-in \fIfile\fP"
+This option allows the user to explicitly specify the input 
+file on the command line.  If no input file is given, the standard input
+is assumed.
+.PP
+.TP 8
+.B -new
+This option forces creation of a new colormap for displaying the image.
+If the image characteristics happen to match those of the display, this
+can get the image on the screen faster, but at the cost of using a new
+colormap (which on most displays will cause other windows to go
+technicolor).
+.PP
+.TP 8
+.B "-noclick"
+Clicking any button in the window will terminate the application,
+unless this option is specified.  Termination can always be achieved
+by typing 'q', 'Q', or ctrl-c.
+.PP
+.TP 8
+.B "-plane \fInumber\fP"
+You can select a single bit plane of the image to display
+with this option.  Planes are numbered with zero being the least
+significant bit.  This option can be used to figure out which plane to
+pass to \fIxpr(1)\fP for printing.
+.PP
+.TP 8
+.B -raw
+This option forces the image to be displayed with whatever color values
+happen to currently exist on the screen.  This option is mostly useful when
+undumping an image back onto the same screen that the image originally
+came from, while the original windows are still on the screen, and results
+in getting the image on the screen faster.
+.PP
+.TP 8
+.B -rv
+If a bitmap image (or a single plane of an image) is displayed, this option
+forces the foreground and background colors to be swapped.  This may be
+needed when displaying a bitmap image which has the color sense of pixel
+values "0" and "1" reversed from what they are on your display.
+.PP
+.TP 8
+.B -scale
+Allow the window to be resized, and scale the image to the size of the window.
+.PP
+.TP 8
+.B "-std \fImaptype\fP"
+This option causes the image to be displayed using the specified
+Standard Colormap.  The property name is obtained by converting the
+type to upper case, prepending "RGB_", and appending "_MAP".
+Typical types are "best", "default", and "gray".  See \fIxstdcmap(1)\fP
+for one way of creating Standard Colormaps.
+.PP
+.TP 8
+.B "-vis \fIvis-type-or-id\fP"
+This option allows you to specify a particular visual or visual class.
+The default is to pick the "best" one.  A particular class can be
+specified: "StaticGray", "GrayScale", "StaticColor", "PseudoColor",
+"DirectColor", or "TrueColor".  Or "Match" can be specified, meaning
+use the same class as the source image.  Alternatively, an exact
+visual id (specific to the server) can be specified, either as a
+hexadecimal number (prefixed with "0x") or as a decimal number.
+Finally, "default" can be specified, meaning to use the same class
+as the colormap of the root window.  Case is not significant in
+any of these strings.
+.SH ENVIRONMENT
+.PP
+.TP 8
+.B DISPLAY
+To get default display.
+.SH FILES
+.PP
+.TP 8
+.B XWDFile.h
+X Window Dump File format definition file.
+.SH BUGS
+xwud doesn't handle big/deep images very well on servers that don't 
+have the BIG-REQUESTS extension.
+.SH SEE ALSO
+xwd(1), xpr(1), xstdcmap(1), X(1)
+.SH AUTHOR
+Bob Scheifler, MIT X Consortium
+
+