xwd.c revision b3307321
1b3307321Smrg/* $Xorg: xwd.c,v 1.5 2001/02/09 02:06:03 xorgcvs Exp $ */
2b3307321Smrg
3b3307321Smrg/*
4b3307321Smrg
5b3307321SmrgCopyright 1987, 1998  The Open Group
6b3307321Smrg
7b3307321SmrgPermission to use, copy, modify, distribute, and sell this software and its
8b3307321Smrgdocumentation for any purpose is hereby granted without fee, provided that
9b3307321Smrgthe above copyright notice appear in all copies and that both that
10b3307321Smrgcopyright notice and this permission notice appear in supporting
11b3307321Smrgdocumentation.
12b3307321Smrg
13b3307321SmrgThe above copyright notice and this permission notice shall be included in
14b3307321Smrgall copies or substantial portions of the Software.
15b3307321Smrg
16b3307321SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17b3307321SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18b3307321SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
19b3307321SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
20b3307321SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21b3307321SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22b3307321Smrg
23b3307321SmrgExcept as contained in this notice, the name of The Open Group shall not be
24b3307321Smrgused in advertising or otherwise to promote the sale, use or other dealings
25b3307321Smrgin this Software without prior written authorization from The Open Group.
26b3307321Smrg
27b3307321Smrg*/
28b3307321Smrg/* $XFree86: xc/programs/xwd/xwd.c,v 3.11 2002/09/16 18:06:21 eich Exp $ */
29b3307321Smrg
30b3307321Smrg/*
31b3307321Smrg * xwd.c MIT Project Athena, X Window system window raster image dumper.
32b3307321Smrg *
33b3307321Smrg * This program will dump a raster image of the contents of a window into a
34b3307321Smrg * file for output on graphics printers or for other uses.
35b3307321Smrg *
36b3307321Smrg *  Author:	Tony Della Fera, DEC
37b3307321Smrg *		17-Jun-85
38b3307321Smrg *
39b3307321Smrg *  Modification history:
40b3307321Smrg *
41b3307321Smrg *  11/14/86 Bill Wyatt, Smithsonian Astrophysical Observatory
42b3307321Smrg *    - Removed Z format option, changing it to an XY option. Monochrome
43b3307321Smrg *      windows will always dump in XY format. Color windows will dump
44b3307321Smrg *      in Z format by default, but can be dumped in XY format with the
45b3307321Smrg *      -xy option.
46b3307321Smrg *
47b3307321Smrg *  11/18/86 Bill Wyatt
48b3307321Smrg *    - VERSION 6 is same as version 5 for monchrome. For colors, the
49b3307321Smrg *      appropriate number of Color structs are dumped after the header,
50b3307321Smrg *      which has the number of colors (=0 for monochrome) in place of the
51b3307321Smrg *      V5 padding at the end. Up to 16-bit displays are supported. I
52b3307321Smrg *      don't yet know how 24- to 32-bit displays will be handled under
53b3307321Smrg *      the Version 11 protocol.
54b3307321Smrg *
55b3307321Smrg *  6/15/87 David Krikorian, MIT Project Athena
56b3307321Smrg *    - VERSION 7 runs under the X Version 11 servers, while the previous
57b3307321Smrg *      versions of xwd were are for X Version 10.  This version is based
58b3307321Smrg *      on xwd version 6, and should eventually have the same color
59b3307321Smrg *      abilities. (Xwd V7 has yet to be tested on a color machine, so
60b3307321Smrg *      all color-related code is commented out until color support
61b3307321Smrg *      becomes practical.)
62b3307321Smrg */
63b3307321Smrg
64b3307321Smrg/*%
65b3307321Smrg *%    This is the format for commenting out color-related code until
66b3307321Smrg *%  color can be supported.
67b3307321Smrg%*/
68b3307321Smrg
69b3307321Smrg#include <stdio.h>
70b3307321Smrg#include <errno.h>
71b3307321Smrg#include <X11/Xos.h>
72b3307321Smrg#include <stdlib.h>
73b3307321Smrg
74b3307321Smrg#include <X11/Xlib.h>
75b3307321Smrg#include <X11/Xutil.h>
76b3307321Smrg
77b3307321Smrg#include <X11/Xmu/WinUtil.h>
78b3307321Smrgtypedef unsigned long Pixel;
79b3307321Smrg#include "X11/XWDFile.h"
80b3307321Smrg
81b3307321Smrg#define FEEP_VOLUME 0
82b3307321Smrg
83b3307321Smrg/* Include routines to do parsing */
84b3307321Smrg#include "dsimple.h"
85b3307321Smrg#include "list.h"
86b3307321Smrg#include "wsutils.h"
87b3307321Smrg#include "multiVis.h"
88b3307321Smrg
89b3307321Smrg#ifdef XKB
90b3307321Smrg#include <X11/extensions/XKBbells.h>
91b3307321Smrg#endif
92b3307321Smrg
93b3307321Smrg/* Setable Options */
94b3307321Smrg
95b3307321Smrgint format = ZPixmap;
96b3307321SmrgBool nobdrs = False;
97b3307321SmrgBool on_root = False;
98b3307321SmrgBool standard_out = True;
99b3307321SmrgBool debug = False;
100b3307321SmrgBool silent = False;
101b3307321SmrgBool use_installed = False;
102b3307321Smrglong add_pixel_value = 0;
103b3307321Smrg
104b3307321Smrg
105b3307321Smrgextern int main(int, char **);
106b3307321Smrgextern void Window_Dump(Window, FILE *);
107b3307321Smrgextern int Image_Size(XImage *);
108b3307321Smrgextern int Get_XColors(XWindowAttributes *, XColor **);
109b3307321Smrgextern void _swapshort(register char *, register unsigned);
110b3307321Smrgextern void _swaplong(register char *, register unsigned);
111b3307321Smrgstatic long parse_long(char *);
112b3307321Smrgstatic int Get24bitDirectColors(XColor **);
113b3307321Smrgstatic int ReadColors(Visual *, Colormap, XColor **);
114b3307321Smrg
115b3307321Smrg
116b3307321Smrgstatic long parse_long (s)
117b3307321Smrg    char *s;
118b3307321Smrg{
119b3307321Smrg    char *fmt = "%lu";
120b3307321Smrg    long retval = 0L;
121b3307321Smrg    int thesign = 1;
122b3307321Smrg
123b3307321Smrg    if (s && s[0]) {
124b3307321Smrg	if (s[0] == '-') s++, thesign = -1;
125b3307321Smrg	if (s[0] == '0') s++, fmt = "%lo";
126b3307321Smrg	if (s[0] == 'x' || s[0] == 'X') s++, fmt = "%lx";
127b3307321Smrg	(void) sscanf (s, fmt, &retval);
128b3307321Smrg    }
129b3307321Smrg    return (thesign * retval);
130b3307321Smrg}
131b3307321Smrg
132b3307321Smrgint
133b3307321Smrgmain(argc, argv)
134b3307321Smrg    int argc;
135b3307321Smrg    char **argv;
136b3307321Smrg{
137b3307321Smrg    register int i;
138b3307321Smrg    Window target_win;
139b3307321Smrg    FILE *out_file = stdout;
140b3307321Smrg    Bool frame_only = False;
141b3307321Smrg
142b3307321Smrg    INIT_NAME;
143b3307321Smrg
144b3307321Smrg    Setup_Display_And_Screen(&argc, argv);
145b3307321Smrg
146b3307321Smrg    /* Get window select on command line, if any */
147b3307321Smrg    target_win = Select_Window_Args(&argc, argv);
148b3307321Smrg
149b3307321Smrg    for (i = 1; i < argc; i++) {
150b3307321Smrg	if (!strcmp(argv[i], "-nobdrs")) {
151b3307321Smrg	    nobdrs = True;
152b3307321Smrg	    continue;
153b3307321Smrg	}
154b3307321Smrg	if (!strcmp(argv[i], "-debug")) {
155b3307321Smrg	    debug = True;
156b3307321Smrg	    continue;
157b3307321Smrg	}
158b3307321Smrg	if (!strcmp(argv[i], "-help"))
159b3307321Smrg	  usage();
160b3307321Smrg	if (!strcmp(argv[i], "-out")) {
161b3307321Smrg	    if (++i >= argc) usage();
162b3307321Smrg	    if (!(out_file = fopen(argv[i], "wb")))
163b3307321Smrg	      Fatal_Error("Can't open output file as specified.");
164b3307321Smrg	    standard_out = False;
165b3307321Smrg	    continue;
166b3307321Smrg	}
167b3307321Smrg	if (!strcmp(argv[i], "-xy")) {
168b3307321Smrg	    format = XYPixmap;
169b3307321Smrg	    continue;
170b3307321Smrg	}
171b3307321Smrg	if (!strcmp(argv[i], "-screen")) {
172b3307321Smrg	    on_root = True;
173b3307321Smrg	    continue;
174b3307321Smrg	}
175b3307321Smrg	if (!strcmp(argv[i], "-icmap")) {
176b3307321Smrg	    use_installed = True;
177b3307321Smrg	    continue;
178b3307321Smrg	}
179b3307321Smrg	if (!strcmp(argv[i], "-add")) {
180b3307321Smrg	    if (++i >= argc) usage();
181b3307321Smrg	    add_pixel_value = parse_long (argv[i]);
182b3307321Smrg	    continue;
183b3307321Smrg	}
184b3307321Smrg	if (!strcmp(argv[i], "-frame")) {
185b3307321Smrg	    frame_only = True;
186b3307321Smrg	    continue;
187b3307321Smrg	}
188b3307321Smrg	if (!strcmp(argv[i], "-silent")) {
189b3307321Smrg	    silent = True;
190b3307321Smrg	    continue;
191b3307321Smrg	}
192b3307321Smrg	usage();
193b3307321Smrg    }
194b3307321Smrg#ifdef WIN32
195b3307321Smrg    if (standard_out)
196b3307321Smrg	_setmode(fileno(out_file), _O_BINARY);
197b3307321Smrg#endif
198b3307321Smrg
199b3307321Smrg    /*
200b3307321Smrg     * Let the user select the target window.
201b3307321Smrg     */
202b3307321Smrg    if (!target_win) {
203b3307321Smrg	target_win = Select_Window(dpy);
204b3307321Smrg    }
205b3307321Smrg
206b3307321Smrg    if (target_win != None && !frame_only) {
207b3307321Smrg        Window root;
208b3307321Smrg        int dummyi;
209b3307321Smrg        unsigned int dummy;
210b3307321Smrg
211b3307321Smrg        if (XGetGeometry (dpy, target_win, &root, &dummyi, &dummyi,
212b3307321Smrg			      &dummy, &dummy, &dummy, &dummy) &&
213b3307321Smrg                              target_win != root) {
214b3307321Smrg	      target_win = XmuClientWindow (dpy, target_win);
215b3307321Smrg	}
216b3307321Smrg    }
217b3307321Smrg
218b3307321Smrg
219b3307321Smrg    /*
220b3307321Smrg     * Dump it!
221b3307321Smrg     */
222b3307321Smrg    Window_Dump(target_win, out_file);
223b3307321Smrg
224b3307321Smrg    XCloseDisplay(dpy);
225b3307321Smrg    if (fclose(out_file)) {
226b3307321Smrg	perror("xwd");
227b3307321Smrg	exit(1);
228b3307321Smrg    }
229b3307321Smrg    exit(0);
230b3307321Smrg}
231b3307321Smrg
232b3307321Smrgstatic int
233b3307321SmrgGet24bitDirectColors(colors)
234b3307321SmrgXColor **colors ;
235b3307321Smrg{
236b3307321Smrg    int i , ncolors = 256 ;
237b3307321Smrg    XColor *tcol ;
238b3307321Smrg
239b3307321Smrg    *colors = tcol = (XColor *)malloc(sizeof(XColor) * ncolors) ;
240b3307321Smrg
241b3307321Smrg    for(i=0 ; i < ncolors ; i++)
242b3307321Smrg    {
243b3307321Smrg	tcol[i].pixel = i << 16 | i << 8 | i ;
244b3307321Smrg	tcol[i].red = tcol[i].green = tcol[i].blue = i << 8   | i ;
245b3307321Smrg    }
246b3307321Smrg
247b3307321Smrg    return ncolors ;
248b3307321Smrg}
249b3307321Smrg
250b3307321Smrg
251b3307321Smrg/*
252b3307321Smrg * Window_Dump: dump a window to a file which must already be open for
253b3307321Smrg *              writting.
254b3307321Smrg */
255b3307321Smrg
256b3307321Smrgvoid
257b3307321SmrgWindow_Dump(window, out)
258b3307321Smrg     Window window;
259b3307321Smrg     FILE *out;
260b3307321Smrg{
261b3307321Smrg    unsigned long swaptest = 1;
262b3307321Smrg    XColor *colors;
263b3307321Smrg    unsigned buffer_size;
264b3307321Smrg    int win_name_size;
265b3307321Smrg    int header_size;
266b3307321Smrg    int ncolors, i;
267b3307321Smrg    char *win_name;
268b3307321Smrg    Bool got_win_name;
269b3307321Smrg    XWindowAttributes win_info;
270b3307321Smrg    XImage *image;
271b3307321Smrg    int absx, absy, x, y;
272b3307321Smrg    unsigned width, height;
273b3307321Smrg    int dwidth, dheight;
274b3307321Smrg    int bw;
275b3307321Smrg    Window dummywin;
276b3307321Smrg    XWDFileHeader header;
277b3307321Smrg    XWDColor xwdcolor;
278b3307321Smrg
279b3307321Smrg    int                 transparentOverlays , multiVis;
280b3307321Smrg    int                 numVisuals;
281b3307321Smrg    XVisualInfo         *pVisuals;
282b3307321Smrg    int                 numOverlayVisuals;
283b3307321Smrg    OverlayInfo         *pOverlayVisuals;
284b3307321Smrg    int                 numImageVisuals;
285b3307321Smrg    XVisualInfo         **pImageVisuals;
286b3307321Smrg    list_ptr            vis_regions;    /* list of regions to read from */
287b3307321Smrg    list_ptr            vis_image_regions ;
288b3307321Smrg    Visual		vis_h,*vis ;
289b3307321Smrg    int			allImage = 0 ;
290b3307321Smrg
291b3307321Smrg    /*
292b3307321Smrg     * Inform the user not to alter the screen.
293b3307321Smrg     */
294b3307321Smrg    if (!silent) {
295b3307321Smrg#ifdef XKB
296b3307321Smrg	XkbStdBell(dpy,None,50,XkbBI_Wait);
297b3307321Smrg#else
298b3307321Smrg	XBell(dpy,FEEP_VOLUME);
299b3307321Smrg#endif
300b3307321Smrg	XFlush(dpy);
301b3307321Smrg    }
302b3307321Smrg
303b3307321Smrg    /*
304b3307321Smrg     * Get the parameters of the window being dumped.
305b3307321Smrg     */
306b3307321Smrg    if (debug) outl("xwd: Getting target window information.\n");
307b3307321Smrg    if(!XGetWindowAttributes(dpy, window, &win_info))
308b3307321Smrg      Fatal_Error("Can't get target window attributes.");
309b3307321Smrg
310b3307321Smrg    /* handle any frame window */
311b3307321Smrg    if (!XTranslateCoordinates (dpy, window, RootWindow (dpy, screen), 0, 0,
312b3307321Smrg				&absx, &absy, &dummywin)) {
313b3307321Smrg	fprintf (stderr,
314b3307321Smrg		 "%s:  unable to translate window coordinates (%d,%d)\n",
315b3307321Smrg		 program_name, absx, absy);
316b3307321Smrg	exit (1);
317b3307321Smrg    }
318b3307321Smrg    win_info.x = absx;
319b3307321Smrg    win_info.y = absy;
320b3307321Smrg    width = win_info.width;
321b3307321Smrg    height = win_info.height;
322b3307321Smrg    bw = 0;
323b3307321Smrg
324b3307321Smrg    if (!nobdrs) {
325b3307321Smrg	absx -= win_info.border_width;
326b3307321Smrg	absy -= win_info.border_width;
327b3307321Smrg	bw = win_info.border_width;
328b3307321Smrg	width += (2 * bw);
329b3307321Smrg	height += (2 * bw);
330b3307321Smrg    }
331b3307321Smrg    dwidth = DisplayWidth (dpy, screen);
332b3307321Smrg    dheight = DisplayHeight (dpy, screen);
333b3307321Smrg
334b3307321Smrg
335b3307321Smrg    /* clip to window */
336b3307321Smrg    if (absx < 0) width += absx, absx = 0;
337b3307321Smrg    if (absy < 0) height += absy, absy = 0;
338b3307321Smrg    if (absx + width > dwidth) width = dwidth - absx;
339b3307321Smrg    if (absy + height > dheight) height = dheight - absy;
340b3307321Smrg
341b3307321Smrg    XFetchName(dpy, window, &win_name);
342b3307321Smrg    if (!win_name || !win_name[0]) {
343b3307321Smrg	win_name = "xwdump";
344b3307321Smrg	got_win_name = False;
345b3307321Smrg    } else {
346b3307321Smrg	got_win_name = True;
347b3307321Smrg    }
348b3307321Smrg
349b3307321Smrg    /* sizeof(char) is included for the null string terminator. */
350b3307321Smrg    win_name_size = strlen(win_name) + sizeof(char);
351b3307321Smrg
352b3307321Smrg    /*
353b3307321Smrg     * Snarf the pixmap with XGetImage.
354b3307321Smrg     */
355b3307321Smrg
356b3307321Smrg    x = absx - win_info.x;
357b3307321Smrg    y = absy - win_info.y;
358b3307321Smrg
359b3307321Smrg    multiVis = GetMultiVisualRegions(dpy,RootWindow(dpy, screen),
360b3307321Smrg               absx, absy,
361b3307321Smrg	       width, height,&transparentOverlays,&numVisuals, &pVisuals,
362b3307321Smrg               &numOverlayVisuals,&pOverlayVisuals,&numImageVisuals,
363b3307321Smrg               &pImageVisuals,&vis_regions,&vis_image_regions,&allImage) ;
364b3307321Smrg    if (on_root || multiVis)
365b3307321Smrg    {
366b3307321Smrg	if(!multiVis)
367b3307321Smrg	    image = XGetImage (dpy, RootWindow(dpy, screen), absx, absy,
368b3307321Smrg                    width, height, AllPlanes, format);
369b3307321Smrg	else
370b3307321Smrg	    image = ReadAreaToImage(dpy, RootWindow(dpy, screen), absx, absy,
371b3307321Smrg                width, height,
372b3307321Smrg    		numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,
373b3307321Smrg                numImageVisuals, pImageVisuals,vis_regions,
374b3307321Smrg                vis_image_regions,format,allImage);
375b3307321Smrg    }
376b3307321Smrg    else
377b3307321Smrg	image = XGetImage (dpy, window, x, y, width, height, AllPlanes, format);
378b3307321Smrg    if (!image) {
379b3307321Smrg	fprintf (stderr, "%s:  unable to get image at %dx%d+%d+%d\n",
380b3307321Smrg		 program_name, width, height, x, y);
381b3307321Smrg	exit (1);
382b3307321Smrg    }
383b3307321Smrg
384b3307321Smrg    if (add_pixel_value != 0) XAddPixel (image, add_pixel_value);
385b3307321Smrg
386b3307321Smrg    /*
387b3307321Smrg     * Determine the pixmap size.
388b3307321Smrg     */
389b3307321Smrg    buffer_size = Image_Size(image);
390b3307321Smrg
391b3307321Smrg    if (debug) outl("xwd: Getting Colors.\n");
392b3307321Smrg
393b3307321Smrg    if( !multiVis)
394b3307321Smrg    {
395b3307321Smrg       ncolors = Get_XColors(&win_info, &colors);
396b3307321Smrg       vis = win_info.visual ;
397b3307321Smrg    }
398b3307321Smrg    else
399b3307321Smrg    {
400b3307321Smrg       ncolors = Get24bitDirectColors(&colors) ;
401b3307321Smrg       initFakeVisual(&vis_h) ;
402b3307321Smrg       vis = &vis_h ;
403b3307321Smrg    }
404b3307321Smrg    /*
405b3307321Smrg     * Inform the user that the image has been retrieved.
406b3307321Smrg     */
407b3307321Smrg    if (!silent) {
408b3307321Smrg#ifdef XKB
409b3307321Smrg	XkbStdBell(dpy,window,FEEP_VOLUME,XkbBI_Proceed);
410b3307321Smrg	XkbStdBell(dpy,window,FEEP_VOLUME,XkbBI_RepeatingLastBell);
411b3307321Smrg#else
412b3307321Smrg	XBell(dpy, FEEP_VOLUME);
413b3307321Smrg	XBell(dpy, FEEP_VOLUME);
414b3307321Smrg#endif
415b3307321Smrg	XFlush(dpy);
416b3307321Smrg    }
417b3307321Smrg
418b3307321Smrg    /*
419b3307321Smrg     * Calculate header size.
420b3307321Smrg     */
421b3307321Smrg    if (debug) outl("xwd: Calculating header size.\n");
422b3307321Smrg    header_size = SIZEOF(XWDheader) + win_name_size;
423b3307321Smrg
424b3307321Smrg    /*
425b3307321Smrg     * Write out header information.
426b3307321Smrg     */
427b3307321Smrg    if (debug) outl("xwd: Constructing and dumping file header.\n");
428b3307321Smrg    header.header_size = (CARD32) header_size;
429b3307321Smrg    header.file_version = (CARD32) XWD_FILE_VERSION;
430b3307321Smrg    header.pixmap_format = (CARD32) format;
431b3307321Smrg    header.pixmap_depth = (CARD32) image->depth;
432b3307321Smrg    header.pixmap_width = (CARD32) image->width;
433b3307321Smrg    header.pixmap_height = (CARD32) image->height;
434b3307321Smrg    header.xoffset = (CARD32) image->xoffset;
435b3307321Smrg    header.byte_order = (CARD32) image->byte_order;
436b3307321Smrg    header.bitmap_unit = (CARD32) image->bitmap_unit;
437b3307321Smrg    header.bitmap_bit_order = (CARD32) image->bitmap_bit_order;
438b3307321Smrg    header.bitmap_pad = (CARD32) image->bitmap_pad;
439b3307321Smrg    header.bits_per_pixel = (CARD32) image->bits_per_pixel;
440b3307321Smrg    header.bytes_per_line = (CARD32) image->bytes_per_line;
441b3307321Smrg    /****
442b3307321Smrg    header.visual_class = (CARD32) win_info.visual->class;
443b3307321Smrg    header.red_mask = (CARD32) win_info.visual->red_mask;
444b3307321Smrg    header.green_mask = (CARD32) win_info.visual->green_mask;
445b3307321Smrg    header.blue_mask = (CARD32) win_info.visual->blue_mask;
446b3307321Smrg    header.bits_per_rgb = (CARD32) win_info.visual->bits_per_rgb;
447b3307321Smrg    header.colormap_entries = (CARD32) win_info.visual->map_entries;
448b3307321Smrg    *****/
449b3307321Smrg    header.visual_class = (CARD32) vis->class;
450b3307321Smrg    header.red_mask = (CARD32) vis->red_mask;
451b3307321Smrg    header.green_mask = (CARD32) vis->green_mask;
452b3307321Smrg    header.blue_mask = (CARD32) vis->blue_mask;
453b3307321Smrg    header.bits_per_rgb = (CARD32) vis->bits_per_rgb;
454b3307321Smrg    header.colormap_entries = (CARD32) vis->map_entries;
455b3307321Smrg
456b3307321Smrg    header.ncolors = ncolors;
457b3307321Smrg    header.window_width = (CARD32) win_info.width;
458b3307321Smrg    header.window_height = (CARD32) win_info.height;
459b3307321Smrg    header.window_x = absx;
460b3307321Smrg    header.window_y = absy;
461b3307321Smrg    header.window_bdrwidth = (CARD32) win_info.border_width;
462b3307321Smrg
463b3307321Smrg    if (*(char *) &swaptest) {
464b3307321Smrg	_swaplong((char *) &header, sizeof(header));
465b3307321Smrg	for (i = 0; i < ncolors; i++) {
466b3307321Smrg	    _swaplong((char *) &colors[i].pixel, sizeof(CARD32));
467b3307321Smrg	    _swapshort((char *) &colors[i].red, 3 * sizeof(short));
468b3307321Smrg	}
469b3307321Smrg    }
470b3307321Smrg
471b3307321Smrg    if (fwrite((char *)&header, SIZEOF(XWDheader), 1, out) != 1 ||
472b3307321Smrg	fwrite(win_name, win_name_size, 1, out) != 1) {
473b3307321Smrg	perror("xwd");
474b3307321Smrg	exit(1);
475b3307321Smrg    }
476b3307321Smrg
477b3307321Smrg    /*
478b3307321Smrg     * Write out the color maps, if any
479b3307321Smrg     */
480b3307321Smrg
481b3307321Smrg    if (debug) outl("xwd: Dumping %d colors.\n", ncolors);
482b3307321Smrg    for (i = 0; i < ncolors; i++) {
483b3307321Smrg	xwdcolor.pixel = colors[i].pixel;
484b3307321Smrg	xwdcolor.red = colors[i].red;
485b3307321Smrg	xwdcolor.green = colors[i].green;
486b3307321Smrg	xwdcolor.blue = colors[i].blue;
487b3307321Smrg	xwdcolor.flags = colors[i].flags;
488b3307321Smrg	if (fwrite((char *) &xwdcolor, SIZEOF(XWDColor), 1, out) != 1) {
489b3307321Smrg	    perror("xwd");
490b3307321Smrg	    exit(1);
491b3307321Smrg	}
492b3307321Smrg    }
493b3307321Smrg
494b3307321Smrg    /*
495b3307321Smrg     * Write out the buffer.
496b3307321Smrg     */
497b3307321Smrg    if (debug) outl("xwd: Dumping pixmap.  bufsize=%d\n",buffer_size);
498b3307321Smrg
499b3307321Smrg    /*
500b3307321Smrg     *    This copying of the bit stream (data) to a file is to be replaced
501b3307321Smrg     *  by an Xlib call which hasn't been written yet.  It is not clear
502b3307321Smrg     *  what other functions of xwd will be taken over by this (as yet)
503b3307321Smrg     *  non-existant X function.
504b3307321Smrg     */
505b3307321Smrg    if (fwrite(image->data, (int) buffer_size, 1, out) != 1) {
506b3307321Smrg	perror("xwd");
507b3307321Smrg	exit(1);
508b3307321Smrg    }
509b3307321Smrg
510b3307321Smrg    /*
511b3307321Smrg     * free the color buffer.
512b3307321Smrg     */
513b3307321Smrg
514b3307321Smrg    if(debug && ncolors > 0) outl("xwd: Freeing colors.\n");
515b3307321Smrg    if(ncolors > 0) free(colors);
516b3307321Smrg
517b3307321Smrg    /*
518b3307321Smrg     * Free window name string.
519b3307321Smrg     */
520b3307321Smrg    if (debug) outl("xwd: Freeing window name string.\n");
521b3307321Smrg    if (got_win_name) XFree(win_name);
522b3307321Smrg
523b3307321Smrg    /*
524b3307321Smrg     * Free image
525b3307321Smrg     */
526b3307321Smrg    XDestroyImage(image);
527b3307321Smrg}
528b3307321Smrg
529b3307321Smrg/*
530b3307321Smrg * Report the syntax for calling xwd.
531b3307321Smrg */
532b3307321Smrgvoid
533b3307321Smrgusage()
534b3307321Smrg{
535b3307321Smrg    fprintf (stderr,
536b3307321Smrg"usage: %s [-display host:dpy] [-debug] [-help] %s [-nobdrs] [-out <file>]",
537b3307321Smrg	   program_name, "[{-root|-id <id>|-name <name>}]");
538b3307321Smrg    fprintf (stderr, " [-xy] [-add value] [-frame]\n");
539b3307321Smrg    exit(1);
540b3307321Smrg}
541b3307321Smrg
542b3307321Smrg
543b3307321Smrg/*
544b3307321Smrg * Determine the pixmap size.
545b3307321Smrg */
546b3307321Smrg
547b3307321Smrgint Image_Size(image)
548b3307321Smrg     XImage *image;
549b3307321Smrg{
550b3307321Smrg    if (image->format != ZPixmap)
551b3307321Smrg      return(image->bytes_per_line * image->height * image->depth);
552b3307321Smrg
553b3307321Smrg    return(image->bytes_per_line * image->height);
554b3307321Smrg}
555b3307321Smrg
556b3307321Smrg#define lowbit(x) ((x) & (~(x) + 1))
557b3307321Smrg
558b3307321Smrgstatic int
559b3307321SmrgReadColors(vis,cmap,colors)
560b3307321SmrgVisual *vis ;
561b3307321SmrgColormap cmap ;
562b3307321SmrgXColor **colors ;
563b3307321Smrg{
564b3307321Smrg    int i,ncolors ;
565b3307321Smrg
566b3307321Smrg    ncolors = vis->map_entries;
567b3307321Smrg
568b3307321Smrg    if (!(*colors = (XColor *) malloc (sizeof(XColor) * ncolors)))
569b3307321Smrg      Fatal_Error("Out of memory!");
570b3307321Smrg
571b3307321Smrg    if (vis->class == DirectColor ||
572b3307321Smrg	vis->class == TrueColor) {
573b3307321Smrg	Pixel red, green, blue, red1, green1, blue1;
574b3307321Smrg
575b3307321Smrg	red = green = blue = 0;
576b3307321Smrg	red1 = lowbit(vis->red_mask);
577b3307321Smrg	green1 = lowbit(vis->green_mask);
578b3307321Smrg	blue1 = lowbit(vis->blue_mask);
579b3307321Smrg	for (i=0; i<ncolors; i++) {
580b3307321Smrg	  (*colors)[i].pixel = red|green|blue;
581b3307321Smrg	  (*colors)[i].pad = 0;
582b3307321Smrg	  red += red1;
583b3307321Smrg	  if (red > vis->red_mask)
584b3307321Smrg	    red = 0;
585b3307321Smrg	  green += green1;
586b3307321Smrg	  if (green > vis->green_mask)
587b3307321Smrg	    green = 0;
588b3307321Smrg	  blue += blue1;
589b3307321Smrg	  if (blue > vis->blue_mask)
590b3307321Smrg	    blue = 0;
591b3307321Smrg	}
592b3307321Smrg    } else {
593b3307321Smrg	for (i=0; i<ncolors; i++) {
594b3307321Smrg	  (*colors)[i].pixel = i;
595b3307321Smrg	  (*colors)[i].pad = 0;
596b3307321Smrg	}
597b3307321Smrg    }
598b3307321Smrg
599b3307321Smrg    XQueryColors(dpy, cmap, *colors, ncolors);
600b3307321Smrg
601b3307321Smrg    return(ncolors);
602b3307321Smrg}
603b3307321Smrg
604b3307321Smrg/*
605b3307321Smrg * Get the XColors of all pixels in image - returns # of colors
606b3307321Smrg */
607b3307321Smrgint Get_XColors(win_info, colors)
608b3307321Smrg     XWindowAttributes *win_info;
609b3307321Smrg     XColor **colors;
610b3307321Smrg{
611b3307321Smrg    int i, ncolors;
612b3307321Smrg    Colormap cmap = win_info->colormap;
613b3307321Smrg
614b3307321Smrg    if (use_installed)
615b3307321Smrg	/* assume the visual will be OK ... */
616b3307321Smrg	cmap = XListInstalledColormaps(dpy, win_info->root, &i)[0];
617b3307321Smrg    if (!cmap)
618b3307321Smrg	return(0);
619b3307321Smrg    ncolors = ReadColors(win_info->visual,cmap,colors) ;
620b3307321Smrg    return ncolors ;
621b3307321Smrg}
622b3307321Smrg
623b3307321Smrgvoid
624b3307321Smrg_swapshort (bp, n)
625b3307321Smrg    register char *bp;
626b3307321Smrg    register unsigned n;
627b3307321Smrg{
628b3307321Smrg    register char c;
629b3307321Smrg    register char *ep = bp + n;
630b3307321Smrg
631b3307321Smrg    while (bp < ep) {
632b3307321Smrg	c = *bp;
633b3307321Smrg	*bp = *(bp + 1);
634b3307321Smrg	bp++;
635b3307321Smrg	*bp++ = c;
636b3307321Smrg    }
637b3307321Smrg}
638b3307321Smrg
639b3307321Smrgvoid
640b3307321Smrg_swaplong (bp, n)
641b3307321Smrg    register char *bp;
642b3307321Smrg    register unsigned n;
643b3307321Smrg{
644b3307321Smrg    register char c;
645b3307321Smrg    register char *ep = bp + n;
646b3307321Smrg
647b3307321Smrg    while (bp < ep) {
648b3307321Smrg        c = bp[3];
649b3307321Smrg        bp[3] = bp[0];
650b3307321Smrg        bp[0] = c;
651b3307321Smrg        c = bp[2];
652b3307321Smrg        bp[2] = bp[1];
653b3307321Smrg        bp[1] = c;
654b3307321Smrg        bp += 4;
655b3307321Smrg    }
656b3307321Smrg}
657