1 /*
2 
3 Copyright 1985, 1986, 1988, 1998  The Open Group
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.
10 
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
13 
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
21 
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
25 from The Open Group.
26 
27 */
28 
29 /* xwud - marginally useful raster image undumper */
30 
31 #ifdef HAVE_CONFIG_H
32 #include "config.h"
33 #endif
34 
35 #include <X11/Xos.h>
36 #include <X11/Xlib.h>
37 #include <X11/Xutil.h>
38 #include <X11/Xatom.h>
39 #include <stdio.h>
40 #include <X11/XWDFile.h>
41 #define  XK_LATIN1
42 #include <X11/keysymdef.h>
43 #include <errno.h>
44 #include <stdlib.h>
45 
46 static Atom wm_protocols;
47 static Atom wm_delete_window;
48 static int split;
49 
50 static char *progname;
51 
52 static Bool Read(char *ptr, int size, int nitems, FILE *stream);
53 static void putImage(Display *dpy, Window image_win, GC gc,
54 		     XImage *out_image, int x, int y, int w, int h);
55 static void putScaledImage(Display *display, Drawable d, GC gc,
56 			   XImage *src_image, int exp_x, int exp_y,
57 			   unsigned int exp_width, unsigned int exp_height,
58 			   unsigned int dest_width, unsigned dest_height);
59 static void Latin1Upper(char *s);
60 static void Extract_Plane(XImage *in_image, XImage *out_image, int plane);
61 static int EffectiveSize(XVisualInfo *vinfo);
62 static int VisualRank(int class);
63 static int IsGray(Display *dpy, XStandardColormap *stdmap);
64 static void Do_StdGray(Display *dpy, XStandardColormap *stdmap, int ncolors,
65 		       XColor *colors, XImage *in_image, XImage *out_image);
66 static void Do_StdCol(Display *dpy, XStandardColormap *stdmap, int ncolors,
67 		      XColor *colors, XImage *in_image, XImage *out_image);
68 static Colormap CopyColormapAndFree(Display *dpy, Colormap colormap);
69 static void Do_Pseudo(Display *dpy, Colormap *colormap, int ncolors,
70 		      XColor *colors, XImage *in_image, XImage *out_image);
71 static void Do_Direct(Display *dpy, XWDFileHeader *header, Colormap *colormap,
72 		      int ncolors, XColor *colors,
73 		      XImage *in_image, XImage *out_image, XVisualInfo *vinfo);
74 static unsigned int Image_Size(XImage *image);
75 static void Error(const char *string) _X_NORETURN;
76 static void _swapshort(char *bp, unsigned int n);
77 static void _swaplong(char *bp, unsigned int n);
78 static void DumpHeader(const XWDFileHeader *header, const char *win_name);
79 
80 static void _X_NORETURN _X_COLD
usage(const char * errmsg)81 usage(const char *errmsg)
82 {
83     if (errmsg != NULL)
84         fprintf (stderr, "%s: %s\n\n", progname, errmsg);
85 
86     fprintf(stderr, "usage: %s %s",
87             progname,
88             " [-in <file>] [-noclick] [-geometry <geom>] [-display <display>]\n"
89  "            [-new] [-std <maptype>] [-raw] [-vis <vis-type-or-id>]\n"
90  "            [-help] [-rv] [-plane <number>] [-fg <color>] [-bg <color>]\n"
91  "            [-scale] [-dumpheader] [-version]\n"
92         );
93     exit(1);
94 }
95 
96 static Bool
Read(char * ptr,int size,int nitems,FILE * stream)97 Read(char *ptr, int size, int nitems, FILE *stream)
98 {
99     size *= nitems;
100     while (size) {
101 	nitems = fread(ptr, 1, size, stream);
102 	if (nitems <= 0)
103 	    return False;
104 	size -= nitems;
105 	ptr += nitems;
106     }
107     return True;
108 }
109 
110 int
main(int argc,char * argv[])111 main(int argc, char *argv[])
112 {
113     Display *dpy;
114     int screen;
115     register int i;
116     XImage in_image_struct;
117     XImage *in_image, *out_image;
118     XSetWindowAttributes attributes;
119     XVisualInfo vinfo, *vinfos;
120     long mask;
121     register char *buffer;
122     unsigned long swaptest = 1;
123     int count, stdcnt;
124     unsigned buffer_size;
125     int win_name_size;
126     int ncolors;
127     char *file_name = NULL;
128     char *win_name;
129     Bool inverse = False, rawbits = False, newmap = False;
130     Bool onclick = True;
131     Bool scale = False;
132     int plane = -1;
133     char *std = NULL;
134     char *vis = NULL;
135     char *display_name = NULL;
136     char *fgname = NULL;
137     char *bgname = NULL;
138     char *geom = NULL;
139     int gbits = 0;
140     XSizeHints hints;
141     XTextProperty textprop;
142     XClassHint class_hint;
143     XColor *colors = NULL, color, igncolor;
144     Window image_win;
145     Colormap colormap;
146     XEvent event;
147     register XExposeEvent *expose = (XExposeEvent *)&event;
148     GC gc;
149     XGCValues gc_val;
150     XWDFileHeader header;
151     XWDColor xwdcolor;
152     FILE *in_file = stdin;
153     char *map_name;
154     Atom map_prop;
155     XStandardColormap *stdmaps, *stdmap = NULL;
156     char c;
157     int win_width, win_height;
158     Bool dump_header = False;
159 
160     progname = argv[0];
161 
162     for (i = 1; i < argc; i++) {
163 	if (strcmp(argv[i], "-bg") == 0) {
164 	    if (++i >= argc) usage("-bg requires an argument");
165 	    bgname = argv[i];
166 	    continue;
167 	}
168 	if (strcmp(argv[i], "-display") == 0) {
169 	    if (++i >= argc) usage("-display requires an argument");
170 	    display_name = argv[i];
171 	    continue;
172 	}
173 	if (strcmp(argv[i], "-dumpheader") == 0) {
174 	    dump_header = True;
175 	    continue;
176 	}
177 	if (strcmp(argv[i], "-fg") == 0) {
178 	    if (++i >= argc) usage("-fg requires an argument");
179 	    fgname = argv[i];
180 	    continue;
181 	}
182 	if (strcmp(argv[i], "-geometry") == 0) {
183 	    if (++i >= argc) usage("-geometry requires an argument");
184 	    geom = argv[i];
185 	    continue;
186 	}
187 	if (strcmp(argv[i], "-help") == 0) {
188 	    usage(NULL);
189 	}
190 	if (strcmp(argv[i], "-in") == 0) {
191 	    if (++i >= argc) usage("-in requires an argument");
192 	    file_name = argv[i];
193 	    continue;
194 	}
195 	if (strcmp(argv[i], "-inverse") == 0) { /* for compatibility */
196 	    inverse = True;
197 	    continue;
198 	}
199 	if (strcmp(argv[i], "-new") == 0) {
200 	    newmap = True;
201 	    if (std) usage("-new cannot be specified with -std");
202 	    continue;
203 	}
204 	if (strcmp(argv[i], "-noclick") == 0) {
205 	    onclick = False;
206 	    continue;
207 	}
208 	if (strcmp(argv[i], "-plane") == 0) {
209 	    if (++i >= argc) usage("-plane requires an argument");
210 	    plane = atoi(argv[i]);
211 	    continue;
212 	}
213 	if (strcmp(argv[i], "-raw") == 0) {
214 	    rawbits = True;
215 	    if (std) usage("-new cannot be specified with -std");
216 	    continue;
217 	}
218 	if (strcmp(argv[i], "-rv") == 0) {
219 	    inverse = True;
220 	    continue;
221 	}
222 	if (strcmp(argv[i], "-scale") == 0) {
223 	    scale = True;
224 	    continue;
225 	}
226 	if (strcmp(argv[i], "-split") == 0) {
227 	    split = True;
228 	    continue;
229 	}
230 	if (strcmp(argv[i], "-std") == 0) {
231 	    if (++i >= argc) usage("-std requires an argument");
232 	    std = argv[i];
233 	    if (newmap || rawbits)
234                 usage("-std cannot be specified with -raw or -new");
235 	    continue;
236 	}
237 	if (strcmp(argv[i], "-vis") == 0) {
238 	    if (++i >= argc) usage("-vis requires an argument");
239 	    vis = argv[i];
240 	    continue;
241 	}
242 	if (strcmp(argv[i], "-version") == 0) {
243 	    puts(PACKAGE_STRING);
244 	    exit(0);
245 	}
246 	fprintf (stderr, "%s: unrecognized argument '%s'\n\n",
247 		 progname, argv[i]);
248 	usage(NULL);
249     }
250 
251     if (file_name) {
252 	in_file = fopen(file_name, "rb");
253 	if (in_file == NULL)
254 	    Error("Can't open input file as specified.");
255     }
256 #ifdef WIN32
257     else
258 	_setmode(fileno(in_file), _O_BINARY);
259 #endif
260 
261     dpy = XOpenDisplay(display_name);
262     if (dpy == NULL) {
263 	fprintf(stderr, "%s:  unable to open display \"%s\"\n",
264 		progname, XDisplayName(display_name));
265 	exit(1);
266     }
267     screen = DefaultScreen(dpy);
268 
269     /*
270      * Read in header information.
271      */
272     if(!Read((char *)&header, SIZEOF(XWDheader), 1, in_file))
273       Error("Unable to read dump file header.");
274 
275     if (*(char *) &swaptest)
276 	_swaplong((char *) &header, SIZEOF(XWDheader));
277 
278     /* check to see if the dump file is in the proper format */
279     if (header.file_version != XWD_FILE_VERSION) {
280 	fprintf(stderr,"xwud: XWD file format version mismatch.");
281 	Error("exiting.");
282     }
283     if (header.header_size < SIZEOF(XWDheader)) {
284 	fprintf(stderr,"xwud: XWD header size is too small.");
285 	Error("exiting.");
286     }
287 
288     /* alloc window name */
289     win_name_size = (header.header_size - SIZEOF(XWDheader));
290     if (win_name_size < 1)
291       Error("win_name_size");
292     if((win_name = malloc((unsigned) win_name_size + 6)) == NULL)
293       Error("Can't malloc window name storage.");
294     strcpy(win_name, "xwud: ");
295 
296      /* read in window name */
297     if(!Read(win_name + 6, sizeof(char), win_name_size, in_file))
298       Error("Unable to read window name from dump file.");
299     (win_name + 6)[win_name_size - 1] = 0;
300 
301     if (dump_header) {
302 	DumpHeader(&header, win_name);
303 	exit(0);
304     }
305 
306     /* initialize the input image */
307 
308     in_image = &in_image_struct;
309     in_image->depth = header.pixmap_depth;
310     in_image->format = header.pixmap_format;
311     in_image->xoffset = header.xoffset;
312     in_image->data = NULL;
313     in_image->width = header.pixmap_width;
314     in_image->height = header.pixmap_height;
315     in_image->bitmap_pad = header.bitmap_pad;
316     in_image->bytes_per_line = header.bytes_per_line;
317     in_image->byte_order = header.byte_order;
318     in_image->bitmap_unit = header.bitmap_unit;
319     in_image->bitmap_bit_order = header.bitmap_bit_order;
320     in_image->bits_per_pixel = header.bits_per_pixel;
321     in_image->red_mask = header.red_mask;
322     in_image->green_mask = header.green_mask;
323     in_image->blue_mask = header.blue_mask;
324     if (!XInitImage(in_image))
325 	Error("Invalid input image header data.");
326 
327     /* read in the color map buffer */
328     if((ncolors = header.ncolors)) {
329 	colors = (XColor *)malloc((unsigned) ncolors * sizeof(XColor));
330 	if (!colors)
331 	    Error("Can't malloc color table");
332 	for (i = 0; i < ncolors; i++) {
333 	    if(!Read((char *) &xwdcolor, SIZEOF(XWDColor), 1, in_file))
334 		Error("Unable to read color map from dump file.");
335 	    colors[i].pixel = xwdcolor.pixel;
336 	    colors[i].red = xwdcolor.red;
337 	    colors[i].green = xwdcolor.green;
338 	    colors[i].blue = xwdcolor.blue;
339 	    colors[i].flags = xwdcolor.flags;
340 	}
341 	if (*(char *) &swaptest) {
342 	    for (i = 0; i < ncolors; i++) {
343 		_swaplong((char *) &colors[i].pixel, sizeof(long));
344 		_swapshort((char *) &colors[i].red, 3 * sizeof(short));
345 	    }
346 	}
347     }
348     else
349 	/* no color map exists, turn on the raw option */
350 	rawbits = True;
351 
352     /* alloc the pixel buffer */
353     buffer_size = Image_Size(in_image);
354     if((buffer = malloc(buffer_size)) == NULL)
355       Error("Can't malloc data buffer.");
356 
357     /* read in the image data */
358     if (!Read(buffer, sizeof(char), (int)buffer_size, in_file))
359         Error("Unable to read pixmap from dump file.");
360 
361      /* close the input file */
362     (void) fclose(in_file);
363 
364     if (plane >= in_image->depth)
365 	Error("plane number exceeds image depth");
366     if ((in_image->format == XYPixmap) && (plane >= 0)) {
367 	buffer += in_image->bytes_per_line * in_image->height *
368 		  (in_image->depth - (plane + 1));
369 	in_image->depth = 1;
370 	ncolors = 0;
371     }
372     if (in_image->bits_per_pixel == 1 && in_image->depth == 1) {
373 	in_image->format = XYBitmap;
374 	newmap = False;
375 	rawbits = True;
376     }
377     in_image->data = buffer;
378 
379     if (std) {
380 	map_name = malloc(strlen(std) + 9);
381 	strcpy(map_name, "RGB_");
382 	strcat(map_name, std);
383 	strcat(map_name, "_MAP");
384 	Latin1Upper(map_name);
385 	map_prop = XInternAtom(dpy, map_name, True);
386 	if (!map_prop || !XGetRGBColormaps(dpy, RootWindow(dpy, screen),
387 					   &stdmaps, &stdcnt, map_prop))
388 	    Error("specified standard colormap does not exist");
389     }
390     vinfo.screen = screen;
391     mask = VisualScreenMask;
392     if (vis)
393     {
394 	char *vt = strdup(vis);
395 	Latin1Upper(vt);
396 	if (strcmp(vt, "STATICGRAY") == 0) {
397 	    vinfo.class = StaticGray;
398 	    mask |= VisualClassMask;
399 	} else if (strcmp(vt, "GRAYSCALE") == 0) {
400 	    vinfo.class = GrayScale;
401 	    mask |= VisualClassMask;
402 	} else if (strcmp(vt, "STATICCOLOR") == 0) {
403 	    vinfo.class = StaticColor;
404 	    mask |= VisualClassMask;
405 	} else if (strcmp(vt, "PSEUDOCOLOR") == 0) {
406 	    vinfo.class = PseudoColor;
407 	    mask |= VisualClassMask;
408 	} else if (strcmp(vt, "DIRECTCOLOR") == 0) {
409 	    vinfo.class = DirectColor;
410 	    mask |= VisualClassMask;
411 	} else if (strcmp(vt, "TRUECOLOR") == 0) {
412 	    vinfo.class = TrueColor;
413 	    mask |= VisualClassMask;
414 	} else if (strcmp(vt, "MATCH") == 0) {
415 	    vinfo.class = header.visual_class;
416 	    mask |= VisualClassMask;
417 	} else if (strcmp(vt, "DEFAULT") == 0) {
418 	    vinfo.visualid= XVisualIDFromVisual(DefaultVisual(dpy, screen));
419 	    mask |= VisualIDMask;
420 	} else {
421 	    vinfo.visualid = 0;
422 	    mask |= VisualIDMask;
423 	    sscanf(vis, "0x%lx", &vinfo.visualid);
424 	    if (!vinfo.visualid)
425 	      sscanf(vis, "%lu", &vinfo.visualid);
426 	    if (!vinfo.visualid)
427 	      Error("invalid visual specifier");
428 	}
429     }
430     if (rawbits && (in_image->depth > 1) && (plane < 0)) {
431 	vinfo.depth = in_image->depth;
432 	mask |= VisualDepthMask;
433     }
434     vinfos = XGetVisualInfo(dpy, mask, &vinfo, &count);
435     if (count == 0)
436 	Error("no matching visual found");
437 
438     /* find a workable visual */
439     if (std) {
440 	stdmap = &stdmaps[0];
441 	if (mask & VisualIDMask) {
442 	    for (i = 0; i < stdcnt; i++) {
443 		if (stdmaps[i].visualid == vinfo.visualid) {
444 		    stdmap = &stdmaps[i];
445 		    break;
446 		}
447 	    }
448 	    if (stdmap->visualid != vinfo.visualid)
449 		Error("no standard colormap matching specified visual");
450 	}
451 	for (i = 0; i < count; i++) {
452 	    if (stdmap->visualid == vinfos[i].visualid) {
453 		vinfo = vinfos[i];
454 		break;
455 	    }
456 	}
457     } else if ((in_image->depth == 1) ||
458 	       ((in_image->format == ZPixmap) && (plane >= 0)) ||
459 	       rawbits) {
460 	vinfo = vinfos[0];
461 	if (!(mask & VisualIDMask)) {
462 	    for (i = 0; i < count; i++) {
463 		if ((vinfos[i].visualid ==
464 		     XVisualIDFromVisual(DefaultVisual(dpy, screen))) &&
465 		    (vinfos[i].depth == DefaultDepth(dpy, screen))) {
466 		    vinfo = vinfos[i];
467 		    break;
468 		}
469 	    }
470 	}
471     } else {
472 	/* get best visual */
473 	vinfo = vinfos[0];
474 	for (i = 0; i < count; i++) {
475 	    int z1, z2;
476 	    z2 = EffectiveSize(&vinfos[i]);
477 	    if ((z2 >= ncolors) &&
478 		(vinfos[i].depth == in_image->depth) &&
479 		(vinfos[i].class == header.visual_class))
480 	    {
481 		vinfo = vinfos[i];
482 		break;
483 	    }
484 	    z1 = EffectiveSize(&vinfo);
485 	    if ((z2 > z1) ||
486 		((z2 == z1) &&
487 		 (VisualRank(vinfos[i].class) >= VisualRank(vinfo.class))))
488 		vinfo = vinfos[i];
489 	}
490 	if ((newmap || (vinfo.visual != DefaultVisual(dpy, screen))) &&
491 	    (vinfo.class != StaticGray) &&
492 	    (vinfo.class != StaticColor) &&
493 	    (vinfo.class == header.visual_class) &&
494 	    (vinfo.depth == in_image->depth) &&
495 	    ((vinfo.class == PseudoColor) ||
496 	     (vinfo.class == GrayScale) ||
497 	     ((vinfo.red_mask == header.red_mask) &&
498 	      (vinfo.green_mask == header.green_mask) &&
499 	      (vinfo.blue_mask == header.blue_mask)))) {
500 	    rawbits = True;
501 	    newmap = True;
502 	}
503     }
504 
505     /* get the appropriate colormap */
506     if (newmap && (vinfo.class & 1) &&
507 	(vinfo.depth == in_image->depth) &&
508 	(vinfo.class == header.visual_class) &&
509 	(vinfo.colormap_size >= ncolors) &&
510 	(vinfo.red_mask == header.red_mask) &&
511 	(vinfo.green_mask == header.green_mask) &&
512 	(vinfo.blue_mask == header.blue_mask)) {
513 	colormap = XCreateColormap(dpy, RootWindow(dpy, screen), vinfo.visual,
514 				   AllocAll);
515 	if (ncolors) {
516 	    for (i = 0; i < ncolors; i++)
517 		colors[i].flags = DoRed|DoGreen|DoBlue;
518 	    XStoreColors(dpy, colormap, colors, ncolors);
519 	}
520     } else if (std) {
521 	colormap = stdmap->colormap;
522     } else {
523 	if (!newmap && (vinfo.visual == DefaultVisual(dpy, screen)))
524 	    colormap = DefaultColormap(dpy, screen);
525 	else
526 	    colormap = XCreateColormap(dpy, RootWindow(dpy, screen),
527 				       vinfo.visual, AllocNone);
528 	newmap = False;
529     }
530 
531     /* create the output image */
532     if ((in_image->format == ZPixmap) && (plane >= 0)) {
533 	out_image = XCreateImage(dpy, vinfo.visual, 1,
534 				 XYBitmap, 0, NULL,
535 				 in_image->width, in_image->height,
536 				 XBitmapPad(dpy), 0);
537 	out_image->data = malloc(Image_Size(out_image));
538 	Extract_Plane(in_image, out_image, plane);
539 	ncolors = 0;
540     } else if (rawbits || newmap) {
541 	out_image = in_image;
542     } else {
543 	out_image = XCreateImage(dpy, vinfo.visual, vinfo.depth,
544 				 (vinfo.depth == 1) ? XYBitmap :
545 						      in_image->format,
546 				 in_image->xoffset, NULL,
547 				 in_image->width, in_image->height,
548 				 XBitmapPad(dpy), 0);
549 	out_image->data = malloc(Image_Size(out_image));
550 	if (std) {
551 	    if (!stdmap->green_max && !stdmap->blue_max && IsGray(dpy, stdmap))
552 		Do_StdGray(dpy, stdmap, ncolors, colors, in_image, out_image);
553 	    else
554 		Do_StdCol(dpy, stdmap, ncolors, colors, in_image, out_image);
555 	} else if ((header.visual_class == TrueColor) ||
556 		   (header.visual_class == DirectColor))
557 	    Do_Direct(dpy, &header, &colormap, ncolors, colors,
558 		      in_image, out_image, &vinfo);
559 	else
560 	    Do_Pseudo(dpy, &colormap, ncolors, colors, in_image, out_image);
561     }
562 
563     if (out_image->depth == 1) {
564 	if (fgname &&
565 	    XAllocNamedColor(dpy, colormap, fgname, &color, &igncolor))
566 	    gc_val.foreground = color.pixel;
567 	else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[1]))
568 	    gc_val.foreground = colors[1].pixel;
569 	else
570 	    gc_val.foreground = BlackPixel (dpy, screen);
571 	if (bgname &&
572 	    XAllocNamedColor(dpy, colormap, bgname, &color, &igncolor))
573 	    gc_val.background = color.pixel;
574 	else if ((ncolors == 2) && XAllocColor(dpy, colormap, &colors[0]))
575 	    gc_val.background = colors[0].pixel;
576 	else
577 	    gc_val.background = WhitePixel (dpy, screen);
578 	if (inverse) {
579 	    unsigned long tmp;
580 	    tmp = gc_val.foreground;
581 	    gc_val.foreground = gc_val.background;
582 	    gc_val.background = tmp;
583 	}
584     } else {
585 	gc_val.background = XGetPixel(out_image, 0, 0);
586 	gc_val.foreground = 0;
587     }
588 
589     attributes.background_pixel = gc_val.background;
590     attributes.border_pixel = gc_val.background;
591     if (scale)
592 	attributes.bit_gravity = ForgetGravity;
593     else
594 	attributes.bit_gravity = NorthWestGravity;
595     attributes.event_mask = ButtonPressMask|ButtonReleaseMask|KeyPressMask|
596 			    ExposureMask;
597     if (scale)
598 	attributes.event_mask |= StructureNotifyMask;
599     attributes.colormap = colormap;
600 
601     hints.x = header.window_x;
602     hints.y = header.window_y;
603     hints.width = out_image->width;
604     hints.height = out_image->height;
605     if (geom)
606 	gbits = XParseGeometry(geom, &hints.x, &hints.y,
607 			       (unsigned int *)&hints.width,
608 			       (unsigned int *)&hints.height);
609     hints.flags = ((gbits & (XValue|YValue)) ? USPosition : 0) |
610 		  ((gbits & (HeightValue|WidthValue)) ? USSize : PSize);
611     if (!scale) {
612 	hints.flags |= PMaxSize;
613 	hints.max_width = (hints.width > out_image->width) ?
614 	    hints.width : out_image->width;
615 	hints.max_height = (hints.height > out_image->height) ?
616 	    hints.height : out_image->height;
617     }
618     if ((gbits & XValue) && (gbits & XNegative))
619 	hints.x += DisplayWidth(dpy, screen) - hints.width;
620     if ((gbits & YValue) && (gbits & YNegative))
621 	hints.y += DisplayHeight(dpy, screen) - hints.height;
622 
623     /* create the image window */
624     image_win = XCreateWindow(dpy, RootWindow(dpy, screen),
625 			      hints.x, hints.y, hints.width, hints.height,
626 			      0, vinfo.depth, InputOutput, vinfo.visual,
627 			      CWBorderPixel|CWBackPixel|CWColormap|CWEventMask|CWBitGravity,
628 			      &attributes);
629     win_width = hints.width;
630     win_height = hints.height;
631 
632     /* Setup for ICCCM delete window. */
633     wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
634     wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
635     (void) XSetWMProtocols (dpy, image_win, &wm_delete_window, 1);
636 
637     textprop.value = (unsigned char *) win_name;
638     textprop.encoding = XA_STRING;
639     textprop.format = 8;
640     textprop.nitems = strlen(win_name);
641     class_hint.res_name = (char *)NULL;
642     class_hint.res_class = "Xwud";
643     /* set standard properties */
644     XSetWMProperties(dpy, image_win, &textprop, (XTextProperty *)NULL,
645 		     argv, argc, &hints, (XWMHints *)NULL, &class_hint);
646 
647     /* map the image window */
648     XMapWindow(dpy, image_win);
649 
650     gc = XCreateGC (dpy, image_win, GCForeground|GCBackground, &gc_val);
651 
652     while (1) {
653 	/* wait on mouse input event to terminate */
654 	XNextEvent(dpy, &event);
655 	switch(event.type) {
656 	case ClientMessage:
657 	  if (event.xclient.message_type == wm_protocols &&
658 	      event.xclient.data.l[0] == wm_delete_window)  {
659 	    XCloseDisplay(dpy);
660 	    exit(0);		/* ICCCM delete window */
661 	  }
662 	    break;
663 	case ButtonPress:
664 	    break;
665 	case ButtonRelease:
666 	    if (onclick) {
667 		XCloseDisplay(dpy);
668 		exit(0);
669 	    }
670 	    break;
671 	case KeyPress:
672 	    i = XLookupString(&event.xkey, &c, 1, NULL, NULL);
673 	    if ((i == 1) && ((c == 'q') || (c == 'Q') || (c == '\03'))) {
674 		XCloseDisplay(dpy);
675 		exit(0);
676 	    }
677 	    break;
678 	case ConfigureNotify:
679 	    win_width = event.xconfigure.width;
680 	    win_height = event.xconfigure.height;
681 	    break;
682 	case Expose:
683 	    if (scale)
684 		putScaledImage(dpy, image_win, gc, out_image,
685 			       expose->x, expose->y,
686 			       expose->width, expose->height,
687 			       win_width, win_height);
688 	    else if ((expose->x < out_image->width) &&
689 		     (expose->y < out_image->height)) {
690 		if ((out_image->width - expose->x) < expose->width)
691 		    expose->width = out_image->width - expose->x;
692 		if ((out_image->height - expose->y) < expose->height)
693 		    expose->height = out_image->height - expose->y;
694 		putImage(dpy, image_win, gc, out_image,
695 			  expose->x, expose->y,
696 			  expose->width, expose->height);
697 	    }
698 	    break;
699 	}
700     }
701     exit(0);
702 }
703 
704 static void
putImage(Display * dpy,Window image_win,GC gc,XImage * out_image,int x,int y,int w,int h)705 putImage(Display *dpy, Window image_win, GC gc, XImage *out_image,
706 	 int x, int y, int w, int h)
707 {
708 #define SPLIT_SIZE  100
709     int	t_x, t_y, t_w, t_h;
710     if (split) {
711     	for (t_y = y; t_y < y + h; t_y += t_h) {
712     	    t_h = SPLIT_SIZE;
713     	    if (t_y + t_h > y + h)
714 	    	t_h = y + h - t_y;
715     	    for (t_x = x; t_x < x + w; t_x += t_w) {
716 	    	t_w = SPLIT_SIZE;
717 	    	if (t_x + t_w > x + w)
718 	    	    t_w = x + w - t_x;
719 	    	XPutImage(dpy, image_win, gc, out_image,
720 		      	  t_x, t_y, t_x, t_y, t_w, t_h);
721     	    }
722     	}
723     } else {
724 	XPutImage (dpy, image_win, gc, out_image, x, y, x, y, w, h);
725     }
726 }
727 
728 typedef short Position;
729 typedef unsigned short Dimension;
730 typedef unsigned long Pixel;
731 
732 #define roundint(x)                   (int)((x) + 0.5)
733 
734 typedef struct {
735   Position *x, *y;
736   Dimension *width, *height;
737 } Table;
738 
739 static void
putScaledImage(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 dest_height)740 putScaledImage(Display *display, Drawable d, GC gc, XImage *src_image,
741 	       int exp_x, int exp_y,
742 	       unsigned int exp_width, unsigned int exp_height,
743 	       unsigned int dest_width, unsigned dest_height)
744 {
745     XImage *dest_image;
746     Position x, y, min_y, max_y, exp_max_y, src_x, src_max_x, src_y;
747     Dimension w, h, strip_height;
748     Table table;
749     Pixel pixel;
750     double ratio_x, ratio_y;
751     Bool fast8;
752 
753     if (dest_width == src_image->width && dest_height == src_image->height) {
754 	/* same for x and y, just send it out */
755 	XPutImage(display, d, gc, src_image, exp_x, exp_y,
756 		  exp_x, exp_y, exp_width, exp_height);
757 	return;
758     }
759 
760     ratio_x = (double)dest_width / (double)src_image->width;
761     ratio_y = (double)dest_height / (double)src_image->height;
762 
763     src_x = exp_x / ratio_x;
764     if (src_x >= src_image->width)
765 	src_x = src_image->width - 1;
766     src_y = exp_y / ratio_y;
767     if (src_y >= src_image->height)
768 	src_y = src_image->height - 1;
769     exp_max_y = exp_y + exp_height;
770     src_max_x = roundint((exp_x + exp_width) / ratio_x) + 1;
771     if (src_max_x > src_image->width)
772 	src_max_x = src_image->width;
773 
774     strip_height = 65536 / roundint(ratio_x * src_image->bytes_per_line);
775     if (strip_height == 0)
776 	strip_height = 1;
777     if (strip_height > exp_height)
778 	strip_height = exp_height;
779 
780     h = strip_height + roundint(ratio_y);
781     dest_image = XCreateImage(display,
782 			      DefaultVisualOfScreen(
783 					     DefaultScreenOfDisplay(display)),
784 			      src_image->depth, src_image->format,
785 			      0, NULL,
786 			      dest_width, h,
787 			      src_image->bitmap_pad, 0);
788     dest_image->data = malloc(dest_image->bytes_per_line * h);
789     fast8 = (src_image->depth == 8 && src_image->bits_per_pixel == 8 &&
790 	     dest_image->bits_per_pixel == 8 && src_image->format == ZPixmap);
791 
792     table.x = (Position *) malloc(sizeof(Position) * (src_image->width + 1));
793     table.y = (Position *) malloc(sizeof(Position) * (src_image->height + 1));
794     table.width = (Dimension *) malloc(sizeof(Dimension) * src_image->width);
795     table.height = (Dimension *) malloc(sizeof(Dimension)*src_image->height);
796 
797     table.x[0] = 0;
798     for (x = 1; x <= src_image->width; x++) {
799 	table.x[x] = roundint(ratio_x * x);
800 	table.width[x - 1] = table.x[x] - table.x[x - 1];
801     }
802 
803     table.y[0] = 0;
804     for (y = 1; y <= src_image->height; y++) {
805 	table.y[y] = roundint(ratio_y * y);
806 	table.height[y - 1] = table.y[y] - table.y[y - 1];
807     }
808 
809     for (min_y = table.y[src_y]; min_y < exp_max_y; min_y = table.y[y]) {
810 	max_y = min_y + strip_height;
811 	if (max_y > exp_max_y) {
812 	    strip_height = exp_max_y - min_y;
813 	    max_y = exp_max_y;
814 	}
815 	for (y = src_y; table.y[y] < max_y; y++) {
816 	    if (table.y[y] < min_y)
817 		continue;
818 	    if (fast8) {
819 		for (x = src_x; x < src_max_x; x++) {
820 		    pixel = ((unsigned char *)src_image->data)
821 			[y * src_image->bytes_per_line + x];
822 		    for (h = 0; h < table.height[y]; h++) {
823 			memset(dest_image->data +
824 			       (table.y[y] + h - min_y) *
825 			       dest_image->bytes_per_line + table.x[x],
826 			       pixel, table.width[x]);
827 		    }
828 		}
829 	    } else {
830 		for (x = src_x; x < src_max_x; x++) {
831 		    pixel = XGetPixel(src_image, x, y);
832 		    for (h = 0; h < table.height[y]; h++) {
833 			for (w = 0; w < table.width[x]; w++)
834 			    XPutPixel(dest_image,
835 				      table.x[x] + w,
836 				      table.y[y] + h - min_y,
837 				      pixel);
838 		    }
839 		}
840 	    }
841 	}
842 	XPutImage(display, d, gc, dest_image, exp_x, 0,
843 		  exp_x, min_y, exp_width, table.y[y] - min_y);
844 	if (y >= src_image->height)
845 	    break;
846     }
847 
848     XFree((char *)table.x);
849     XFree((char *)table.y);
850     XFree((char *)table.width);
851     XFree((char *)table.height);
852 
853     XDestroyImage(dest_image);
854 }
855 
856 static void
Latin1Upper(char * s)857 Latin1Upper(char *s)
858 {
859     unsigned char *str = (unsigned char *)s;
860     unsigned char c;
861 
862     for (; (c = *str); str++)
863     {
864 	if ((c >= XK_a) && (c <= XK_z))
865 	    *str = c - (XK_a - XK_A);
866 	else if ((c >= XK_agrave) && (c <= XK_odiaeresis))
867 	    *str = c - (XK_agrave - XK_Agrave);
868 	else if ((c >= XK_oslash) && (c <= XK_thorn))
869 	    *str = c - (XK_oslash - XK_Ooblique);
870     }
871 }
872 
873 static void
Extract_Plane(XImage * in_image,XImage * out_image,int plane)874 Extract_Plane(XImage *in_image, XImage *out_image, int plane)
875 {
876     register int x, y;
877 
878     for (y = 0; y < in_image->height; y++)
879 	for (x = 0; x < in_image->width; x++)
880 	    XPutPixel(out_image, x, y,
881 		      (XGetPixel(in_image, x, y) >> plane) & 1);
882 }
883 
884 static int
EffectiveSize(XVisualInfo * vinfo)885 EffectiveSize(XVisualInfo *vinfo)
886 {
887     if ((vinfo->class == DirectColor) || (vinfo->class == TrueColor))
888 	return (vinfo->red_mask | vinfo->green_mask | vinfo->blue_mask) + 1;
889     else
890 	return vinfo->colormap_size;
891 }
892 
893 static int
VisualRank(int class)894 VisualRank(int class)
895 {
896     switch (class) {
897     case PseudoColor:
898 	return 5;
899     case TrueColor:
900 	return 4;
901     case DirectColor:
902 	return 3;
903     case StaticColor:
904 	return 2;
905     case GrayScale:
906 	return 1;
907     case StaticGray:
908 	return 0;
909     }
910     /* NOTREACHED */
911     return -1;
912 }
913 
914 static int
IsGray(Display * dpy,XStandardColormap * stdmap)915 IsGray(Display *dpy, XStandardColormap *stdmap)
916 {
917     XColor color;
918 
919     color.pixel = stdmap->base_pixel + (stdmap->red_max * stdmap->red_mult);
920     XQueryColor(dpy, stdmap->colormap, &color);
921     return (color.green || color.blue);
922 }
923 
924 static void
Do_StdGray(Display * dpy,XStandardColormap * stdmap,int ncolors,XColor * colors,XImage * in_image,XImage * out_image)925 Do_StdGray(Display *dpy, XStandardColormap *stdmap,
926 	   int ncolors, XColor *colors, XImage *in_image, XImage *out_image)
927 {
928     register int i, x, y;
929     register XColor *color;
930     unsigned lim;
931 
932     lim = stdmap->red_max + 1;
933     for (i = 0, color = colors; i < ncolors; i++, color++)
934 	color->pixel = stdmap->base_pixel +
935 		       (((((int)(30L * color->red +
936 			         59L * color->green +
937 			         11L * color->blue) / 100)
938 			  * lim) >> 16) * stdmap->red_mult);
939     for (y = 0; y < in_image->height; y++) {
940 	for (x = 0; x < in_image->width; x++) {
941 	    XPutPixel(out_image, x, y,
942 		      colors[XGetPixel(in_image, x, y)].pixel);
943 	}
944     }
945 }
946 
947 #define MapVal(val,lim,mult) ((((val * lim) + 32768) / 65535) * mult)
948 
949 static void
Do_StdCol(Display * dpy,XStandardColormap * stdmap,int ncolors,XColor * colors,XImage * in_image,XImage * out_image)950 Do_StdCol(Display *dpy, XStandardColormap *stdmap,
951 	  int ncolors, XColor *colors, XImage *in_image, XImage *out_image)
952 {
953     register int i, x, y;
954     register XColor *color;
955     unsigned limr, limg, limb;
956 
957     limr = stdmap->red_max;
958     limg = stdmap->green_max;
959     limb = stdmap->blue_max;
960     for (i = 0, color = colors; i < ncolors; i++, color++)
961 	color->pixel = stdmap->base_pixel +
962 		       MapVal(color->red, limr, stdmap->red_mult) +
963 		       MapVal(color->green, limg, stdmap->green_mult) +
964 		       MapVal(color->blue, limb, stdmap->blue_mult);
965     for (y = 0; y < in_image->height; y++) {
966 	for (x = 0; x < in_image->width; x++) {
967 	    XPutPixel(out_image, x, y,
968 		      colors[XGetPixel(in_image, x, y)].pixel);
969 	}
970     }
971 }
972 
973 static Colormap
CopyColormapAndFree(Display * dpy,Colormap colormap)974 CopyColormapAndFree(Display *dpy, Colormap colormap)
975 {
976     if (colormap == DefaultColormap(dpy, DefaultScreen(dpy)))
977 	return XCopyColormapAndFree(dpy, colormap);
978     Error("Visual type is not large enough to hold all colors of the image.");
979     /*NOTREACHED*/
980     return (Colormap)0;
981 }
982 
983 static void
Do_Pseudo(Display * dpy,Colormap * colormap,int ncolors,XColor * colors,XImage * in_image,XImage * out_image)984 Do_Pseudo(Display *dpy, Colormap *colormap,
985 	  int ncolors, XColor *colors, XImage *in_image, XImage *out_image)
986 {
987     register int i, x, y;
988     register XColor *color;
989 
990     for (i = 0; i < ncolors; i++)
991 	colors[i].flags = 0;
992     for (y = 0; y < in_image->height; y++) {
993 	for (x = 0; x < in_image->width; x++) {
994 	    color = &colors[XGetPixel(in_image, x, y)];
995 	    if (!color->flags) {
996 		color->flags = DoRed | DoGreen | DoBlue;
997 		if (!XAllocColor(dpy, *colormap, color)) {
998 		    *colormap = CopyColormapAndFree(dpy, *colormap);
999 		    XAllocColor(dpy, *colormap, color);
1000 		}
1001 	    }
1002 	    XPutPixel(out_image, x, y, color->pixel);
1003 	}
1004     }
1005 }
1006 
1007 static void
Do_Direct(Display * dpy,XWDFileHeader * header,Colormap * colormap,int ncolors,XColor * colors,XImage * in_image,XImage * out_image,XVisualInfo * vinfo)1008 Do_Direct(Display *dpy, XWDFileHeader *header, Colormap *colormap,
1009 	  int ncolors, XColor *colors, XImage *in_image, XImage *out_image,
1010           XVisualInfo *vinfo)
1011 {
1012     register int x, y;
1013     XColor color;
1014     unsigned long rmask, gmask, bmask;
1015     unsigned long ormask, ogmask, obmask;
1016     unsigned long  rshift = 0, gshift = 0, bshift = 0;
1017     unsigned long  orshift = 0, ogshift = 0, obshift = 0;
1018     int i;
1019     unsigned long pix, xpix;
1020     unsigned long *pixels, *rpixels;
1021 
1022     rmask = header->red_mask;
1023     while (!(rmask & 1)) {
1024 	rmask >>= 1;
1025 	rshift++;
1026     }
1027     gmask = header->green_mask;
1028     while (!(gmask & 1)) {
1029 	gmask >>= 1;
1030 	gshift++;
1031     }
1032     bmask = header->blue_mask;
1033     while (!(bmask & 1)) {
1034 	bmask >>= 1;
1035 	bshift++;
1036     }
1037     if (in_image->depth <= 12) {
1038 	pix = 1 << in_image->depth;
1039 	pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix);
1040 	if (pixels == NULL)
1041 	    Error("Unable to allocate memory for pixel conversion");
1042 	for (i = 0; i < pix; i++)
1043 	    pixels[i] = ~0L;
1044 	color.flags = DoRed | DoGreen | DoBlue;
1045 	for (y = 0; y < in_image->height; y++) {
1046 	    for (x = 0; x < in_image->width; x++) {
1047 		pix = XGetPixel(in_image, x, y);
1048 		if ((color.pixel = pixels[pix]) == ~0L) {
1049 		    color.red = (pix >> rshift) & rmask;
1050 		    color.green = (pix >> gshift) & gmask;
1051 		    color.blue = (pix >> bshift) & bmask;
1052 		    if (ncolors) {
1053 			color.red = colors[color.red].red;
1054 			color.green = colors[color.green].green;
1055 			color.blue = colors[color.blue].blue;
1056 		    } else {
1057 			color.red = (((unsigned long)color.red * 65535) /
1058 				     rmask);
1059 			color.green = (((unsigned long)color.green * 65535) /
1060 				       gmask);
1061 			color.blue = (((unsigned long)color.blue * 65535) /
1062 				      bmask);
1063 		    }
1064 		    if (!XAllocColor(dpy, *colormap, &color)) {
1065 			*colormap = CopyColormapAndFree(dpy, *colormap);
1066 			XAllocColor(dpy, *colormap, &color);
1067 		    }
1068 		    pixels[pix] = color.pixel;
1069 		}
1070 		XPutPixel(out_image, x, y, color.pixel);
1071 	    }
1072 	}
1073 	free(pixels);
1074     } else if (header->visual_class == TrueColor &&
1075 	       vinfo->class == TrueColor) {
1076 	ormask = vinfo->red_mask;
1077 	while (!(ormask & 1)) {
1078 	    ormask >>= 1;
1079 	    orshift++;
1080 	}
1081 	ogmask = vinfo->green_mask;
1082 	while (!(ogmask & 1)) {
1083 	    ogmask >>= 1;
1084 	    ogshift++;
1085 	}
1086 	obmask = vinfo->blue_mask;
1087 	while (!(obmask & 1)) {
1088 	    obmask >>= 1;
1089 	    obshift++;
1090 	}
1091 	for (y = 0; y < in_image->height; y++) {
1092 	    for (x = 0; x < in_image->width; x++) {
1093 		pix = XGetPixel(in_image, x, y);
1094 		xpix = (((((pix >> rshift) & rmask) * 65535 / rmask)
1095 			 * ormask / 65535) << orshift) |
1096 		       (((((pix >> gshift) & gmask) * 65535 / gmask)
1097 			 * ogmask / 65535) << ogshift) |
1098 		       (((((pix >> bshift) & bmask) * 65535 / bmask)
1099 			 * obmask / 65535) << obshift);
1100 		XPutPixel(out_image, x, y, xpix);
1101 	    }
1102 	}
1103     } else {
1104 	if (header->visual_class == TrueColor)
1105 	    ncolors = 0;
1106 	pix = 1 << 12;
1107 	pixels = (unsigned long *)malloc(sizeof(unsigned long) * pix);
1108 	rpixels = (unsigned long *)malloc(sizeof(unsigned long) * pix);
1109 	if ((pixels == NULL) || (rpixels == NULL))
1110 	    Error("Unable to allocate memory for pixel conversion");
1111 	for (i = 0; i < pix; i++) {
1112 	    pixels[i] = ~0L;
1113 	    rpixels[i] = ~0L;
1114 	}
1115 	color.flags = DoRed | DoGreen | DoBlue;
1116 	for (y = 0; y < in_image->height; y++) {
1117 	    for (x = 0; x < in_image->width; x++) {
1118 		pix = XGetPixel(in_image, x, y);
1119 		xpix = ((pix >> 12) ^ pix) & ((1 << 12) - 1);
1120 		if (((color.pixel = pixels[xpix]) == ~0L) ||
1121 		    (rpixels[xpix] != pix)) {
1122 		    color.red = (pix >> rshift) & rmask;
1123 		    color.green = (pix >> gshift) & gmask;
1124 		    color.blue = (pix >> bshift) & bmask;
1125 		    if (ncolors) {
1126 			color.red = colors[color.red].red;
1127 			color.green = colors[color.green].green;
1128 			color.blue = colors[color.blue].blue;
1129 		    } else {
1130 			color.red = (((unsigned long)color.red * 65535) /
1131 				     rmask);
1132 			color.green = (((unsigned long)color.green * 65535) /
1133 				       gmask);
1134 			color.blue = (((unsigned long)color.blue * 65535) /
1135 				      bmask);
1136 		    }
1137 		    if (!XAllocColor(dpy, *colormap, &color)) {
1138 			*colormap = CopyColormapAndFree(dpy, *colormap);
1139 			XAllocColor(dpy, *colormap, &color);
1140 		    }
1141 		    pixels[xpix] = color.pixel;
1142 		    rpixels[xpix] = pix;
1143 		}
1144 		XPutPixel(out_image, x, y, color.pixel);
1145 	    }
1146 	}
1147 	free(pixels);
1148 	free(rpixels);
1149     }
1150 }
1151 
1152 static unsigned int
Image_Size(XImage * image)1153 Image_Size(XImage *image)
1154 {
1155     if (image->format != ZPixmap)
1156       return(image->bytes_per_line * image->height * image->depth);
1157 
1158     return((unsigned)image->bytes_per_line * image->height);
1159 }
1160 
1161 static void
Error(const char * string)1162 Error(const char *string)
1163 {
1164 	fprintf(stderr, "xwud: Error => %s\n", string);
1165 	if (errno != 0) {
1166 		perror("xwud");
1167 		fprintf(stderr, "\n");
1168 	}
1169 	exit(1);
1170 }
1171 
1172 static void
_swapshort(char * bp,unsigned int n)1173 _swapshort(char *bp, unsigned int n)
1174 {
1175     register char c;
1176     register char *ep = bp + n;
1177 
1178     while (bp < ep) {
1179 	c = *bp;
1180 	*bp = *(bp + 1);
1181 	bp++;
1182 	*bp++ = c;
1183     }
1184 }
1185 
1186 static void
_swaplong(char * bp,unsigned int n)1187 _swaplong(char *bp, unsigned int n)
1188 {
1189     register char c;
1190     register char *ep = bp + n;
1191     register char *sp;
1192 
1193     while (bp < ep) {
1194 	sp = bp + 3;
1195 	c = *sp;
1196 	*sp = *bp;
1197 	*bp++ = c;
1198 	sp = bp + 1;
1199 	c = *sp;
1200 	*sp = *bp;
1201 	*bp++ = c;
1202 	bp += 2;
1203     }
1204 }
1205 
1206 static void
DumpHeader(const XWDFileHeader * header,const char * win_name)1207 DumpHeader(const XWDFileHeader *header, const char *win_name)
1208 {
1209 	printf("window name:        %s\n", win_name);
1210 	printf("sizeof(XWDheader):  %d\n", (int)sizeof(*header));
1211 	printf("header size:        %d\n", (int)header->header_size);
1212 	printf("file version:       %d\n", (int)header->file_version);
1213 	printf("pixmap format:      %d\n", (int)header->pixmap_format);
1214 	printf("pixmap depth:       %d\n", (int)header->pixmap_depth);
1215 	printf("pixmap width:       %d\n", (int)header->pixmap_width);
1216 	printf("pixmap height:      %d\n", (int)header->pixmap_height);
1217 	printf("x offset:           %d\n", (int)header->xoffset);
1218 	printf("byte order:         %d\n", (int)header->byte_order);
1219 	printf("bitmap unit:        %d\n", (int)header->bitmap_unit);
1220 	printf("bitmap bit order:   %d\n", (int)header->bitmap_bit_order);
1221 	printf("bitmap pad:         %d\n", (int)header->bitmap_pad);
1222 	printf("bits per pixel:     %d\n", (int)header->bits_per_pixel);
1223 	printf("bytes per line:     %d\n", (int)header->bytes_per_line);
1224 	printf("visual class:       %d\n", (int)header->visual_class);
1225 	printf("red mask:           %d\n", (int)header->red_mask);
1226 	printf("green mask:         %d\n", (int)header->green_mask);
1227 	printf("blue mask:          %d\n", (int)header->blue_mask);
1228 	printf("bits per rgb:       %d\n", (int)header->bits_per_rgb);
1229 	printf("colormap entries:   %d\n", (int)header->colormap_entries);
1230 	printf("num colors:         %d\n", (int)header->ncolors);
1231 	printf("window width:       %d\n", (int)header->window_width);
1232 	printf("window height:      %d\n", (int)header->window_height);
1233 	printf("window x:           %d\n", (int)header->window_x);
1234 	printf("window y:           %d\n", (int)header->window_y);
1235 	printf("border width:       %d\n", (int)header->window_bdrwidth);
1236 }
1237 
1238