xwd.c revision 5e358eca
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
77b3307321Smrgtypedef unsigned long Pixel;
78b3307321Smrg#include "X11/XWDFile.h"
79b3307321Smrg
80b3307321Smrg#define FEEP_VOLUME 0
81b3307321Smrg
82b3307321Smrg/* Include routines to do parsing */
83b3307321Smrg#include "dsimple.h"
84b3307321Smrg#include "list.h"
85b3307321Smrg#include "wsutils.h"
86b3307321Smrg#include "multiVis.h"
87b3307321Smrg
88b3307321Smrg#ifdef XKB
89b3307321Smrg#include <X11/extensions/XKBbells.h>
90b3307321Smrg#endif
91b3307321Smrg
92b3307321Smrg/* Setable Options */
93b3307321Smrg
945e358ecaSmrgstatic int format = ZPixmap;
955e358ecaSmrgstatic Bool nobdrs = False;
965e358ecaSmrgstatic Bool on_root = False;
975e358ecaSmrgstatic Bool standard_out = True;
985e358ecaSmrgstatic Bool debug = False;
995e358ecaSmrgstatic Bool silent = False;
1005e358ecaSmrgstatic Bool use_installed = False;
1015e358ecaSmrgstatic long add_pixel_value = 0;
102b3307321Smrg
103b3307321Smrg
104b3307321Smrgextern int main(int, char **);
105b3307321Smrgextern void Window_Dump(Window, FILE *);
106b3307321Smrgextern int Image_Size(XImage *);
107b3307321Smrgextern int Get_XColors(XWindowAttributes *, XColor **);
108b3307321Smrgextern void _swapshort(register char *, register unsigned);
109b3307321Smrgextern void _swaplong(register char *, register unsigned);
110b3307321Smrgstatic long parse_long(char *);
111b3307321Smrgstatic int Get24bitDirectColors(XColor **);
112b3307321Smrgstatic int ReadColors(Visual *, Colormap, XColor **);
113b3307321Smrg
114b3307321Smrg
1155e358ecaSmrgstatic long parse_long (char *s)
116b3307321Smrg{
117b3307321Smrg    char *fmt = "%lu";
118b3307321Smrg    long retval = 0L;
119b3307321Smrg    int thesign = 1;
120b3307321Smrg
121b3307321Smrg    if (s && s[0]) {
122b3307321Smrg	if (s[0] == '-') s++, thesign = -1;
123b3307321Smrg	if (s[0] == '0') s++, fmt = "%lo";
124b3307321Smrg	if (s[0] == 'x' || s[0] == 'X') s++, fmt = "%lx";
125b3307321Smrg	(void) sscanf (s, fmt, &retval);
126b3307321Smrg    }
127b3307321Smrg    return (thesign * retval);
128b3307321Smrg}
129b3307321Smrg
130b3307321Smrgint
1315e358ecaSmrgmain(int argc, char **argv)
132b3307321Smrg{
133b3307321Smrg    register int i;
134b3307321Smrg    Window target_win;
135b3307321Smrg    FILE *out_file = stdout;
136b3307321Smrg    Bool frame_only = False;
137b3307321Smrg
138b3307321Smrg    INIT_NAME;
139b3307321Smrg
140b3307321Smrg    Setup_Display_And_Screen(&argc, argv);
141b3307321Smrg
142b3307321Smrg    /* Get window select on command line, if any */
143b3307321Smrg    target_win = Select_Window_Args(&argc, argv);
144b3307321Smrg
145b3307321Smrg    for (i = 1; i < argc; i++) {
146b3307321Smrg	if (!strcmp(argv[i], "-nobdrs")) {
147b3307321Smrg	    nobdrs = True;
148b3307321Smrg	    continue;
149b3307321Smrg	}
150b3307321Smrg	if (!strcmp(argv[i], "-debug")) {
151b3307321Smrg	    debug = True;
152b3307321Smrg	    continue;
153b3307321Smrg	}
154b3307321Smrg	if (!strcmp(argv[i], "-help"))
155b3307321Smrg	  usage();
156b3307321Smrg	if (!strcmp(argv[i], "-out")) {
157b3307321Smrg	    if (++i >= argc) usage();
158b3307321Smrg	    if (!(out_file = fopen(argv[i], "wb")))
159b3307321Smrg	      Fatal_Error("Can't open output file as specified.");
160b3307321Smrg	    standard_out = False;
161b3307321Smrg	    continue;
162b3307321Smrg	}
163b3307321Smrg	if (!strcmp(argv[i], "-xy")) {
164b3307321Smrg	    format = XYPixmap;
165b3307321Smrg	    continue;
166b3307321Smrg	}
167b3307321Smrg	if (!strcmp(argv[i], "-screen")) {
168b3307321Smrg	    on_root = True;
169b3307321Smrg	    continue;
170b3307321Smrg	}
171b3307321Smrg	if (!strcmp(argv[i], "-icmap")) {
172b3307321Smrg	    use_installed = True;
173b3307321Smrg	    continue;
174b3307321Smrg	}
175b3307321Smrg	if (!strcmp(argv[i], "-add")) {
176b3307321Smrg	    if (++i >= argc) usage();
177b3307321Smrg	    add_pixel_value = parse_long (argv[i]);
178b3307321Smrg	    continue;
179b3307321Smrg	}
180b3307321Smrg	if (!strcmp(argv[i], "-frame")) {
181b3307321Smrg	    frame_only = True;
182b3307321Smrg	    continue;
183b3307321Smrg	}
184b3307321Smrg	if (!strcmp(argv[i], "-silent")) {
185b3307321Smrg	    silent = True;
186b3307321Smrg	    continue;
187b3307321Smrg	}
188b3307321Smrg	usage();
189b3307321Smrg    }
190b3307321Smrg#ifdef WIN32
191b3307321Smrg    if (standard_out)
192b3307321Smrg	_setmode(fileno(out_file), _O_BINARY);
193b3307321Smrg#endif
194b3307321Smrg
195b3307321Smrg    /*
196b3307321Smrg     * Let the user select the target window.
197b3307321Smrg     */
198afe13c8eSmrg    if (target_win == None)
199afe13c8eSmrg	target_win = Select_Window(dpy, !frame_only);
200b3307321Smrg
201b3307321Smrg    /*
202b3307321Smrg     * Dump it!
203b3307321Smrg     */
204b3307321Smrg    Window_Dump(target_win, out_file);
205b3307321Smrg
206b3307321Smrg    XCloseDisplay(dpy);
207b3307321Smrg    if (fclose(out_file)) {
208b3307321Smrg	perror("xwd");
209b3307321Smrg	exit(1);
210b3307321Smrg    }
211b3307321Smrg    exit(0);
212b3307321Smrg}
213b3307321Smrg
214b3307321Smrgstatic int
2155e358ecaSmrgGet24bitDirectColors(XColor **colors)
216b3307321Smrg{
217b3307321Smrg    int i , ncolors = 256 ;
218b3307321Smrg    XColor *tcol ;
219b3307321Smrg
220b3307321Smrg    *colors = tcol = (XColor *)malloc(sizeof(XColor) * ncolors) ;
221b3307321Smrg
222b3307321Smrg    for(i=0 ; i < ncolors ; i++)
223b3307321Smrg    {
224b3307321Smrg	tcol[i].pixel = i << 16 | i << 8 | i ;
225b3307321Smrg	tcol[i].red = tcol[i].green = tcol[i].blue = i << 8   | i ;
226b3307321Smrg    }
227b3307321Smrg
228b3307321Smrg    return ncolors ;
229b3307321Smrg}
230b3307321Smrg
231b3307321Smrg
232b3307321Smrg/*
233b3307321Smrg * Window_Dump: dump a window to a file which must already be open for
234b3307321Smrg *              writting.
235b3307321Smrg */
236b3307321Smrg
237b3307321Smrgvoid
2385e358ecaSmrgWindow_Dump(Window window, FILE *out)
239b3307321Smrg{
240b3307321Smrg    unsigned long swaptest = 1;
241b3307321Smrg    XColor *colors;
242b3307321Smrg    unsigned buffer_size;
243b3307321Smrg    int win_name_size;
244b3307321Smrg    int header_size;
245b3307321Smrg    int ncolors, i;
246b3307321Smrg    char *win_name;
247b3307321Smrg    Bool got_win_name;
248b3307321Smrg    XWindowAttributes win_info;
249b3307321Smrg    XImage *image;
250b3307321Smrg    int absx, absy, x, y;
251b3307321Smrg    unsigned width, height;
252b3307321Smrg    int dwidth, dheight;
253b3307321Smrg    int bw;
254b3307321Smrg    Window dummywin;
255b3307321Smrg    XWDFileHeader header;
256b3307321Smrg    XWDColor xwdcolor;
257b3307321Smrg
258b3307321Smrg    int                 transparentOverlays , multiVis;
259b3307321Smrg    int                 numVisuals;
260b3307321Smrg    XVisualInfo         *pVisuals;
261b3307321Smrg    int                 numOverlayVisuals;
262b3307321Smrg    OverlayInfo         *pOverlayVisuals;
263b3307321Smrg    int                 numImageVisuals;
264b3307321Smrg    XVisualInfo         **pImageVisuals;
265b3307321Smrg    list_ptr            vis_regions;    /* list of regions to read from */
266b3307321Smrg    list_ptr            vis_image_regions ;
267b3307321Smrg    Visual		vis_h,*vis ;
268b3307321Smrg    int			allImage = 0 ;
269b3307321Smrg
270b3307321Smrg    /*
271b3307321Smrg     * Inform the user not to alter the screen.
272b3307321Smrg     */
273b3307321Smrg    if (!silent) {
274b3307321Smrg#ifdef XKB
275b3307321Smrg	XkbStdBell(dpy,None,50,XkbBI_Wait);
276b3307321Smrg#else
277b3307321Smrg	XBell(dpy,FEEP_VOLUME);
278b3307321Smrg#endif
279b3307321Smrg	XFlush(dpy);
280b3307321Smrg    }
281b3307321Smrg
282b3307321Smrg    /*
283b3307321Smrg     * Get the parameters of the window being dumped.
284b3307321Smrg     */
285b3307321Smrg    if (debug) outl("xwd: Getting target window information.\n");
286b3307321Smrg    if(!XGetWindowAttributes(dpy, window, &win_info))
287b3307321Smrg      Fatal_Error("Can't get target window attributes.");
288b3307321Smrg
289b3307321Smrg    /* handle any frame window */
290b3307321Smrg    if (!XTranslateCoordinates (dpy, window, RootWindow (dpy, screen), 0, 0,
291b3307321Smrg				&absx, &absy, &dummywin)) {
292b3307321Smrg	fprintf (stderr,
293b3307321Smrg		 "%s:  unable to translate window coordinates (%d,%d)\n",
294b3307321Smrg		 program_name, absx, absy);
295b3307321Smrg	exit (1);
296b3307321Smrg    }
297b3307321Smrg    win_info.x = absx;
298b3307321Smrg    win_info.y = absy;
299b3307321Smrg    width = win_info.width;
300b3307321Smrg    height = win_info.height;
301b3307321Smrg    bw = 0;
302b3307321Smrg
303b3307321Smrg    if (!nobdrs) {
304b3307321Smrg	absx -= win_info.border_width;
305b3307321Smrg	absy -= win_info.border_width;
306b3307321Smrg	bw = win_info.border_width;
307b3307321Smrg	width += (2 * bw);
308b3307321Smrg	height += (2 * bw);
309b3307321Smrg    }
310b3307321Smrg    dwidth = DisplayWidth (dpy, screen);
311b3307321Smrg    dheight = DisplayHeight (dpy, screen);
312b3307321Smrg
313b3307321Smrg
314b3307321Smrg    /* clip to window */
315b3307321Smrg    if (absx < 0) width += absx, absx = 0;
316b3307321Smrg    if (absy < 0) height += absy, absy = 0;
317b3307321Smrg    if (absx + width > dwidth) width = dwidth - absx;
318b3307321Smrg    if (absy + height > dheight) height = dheight - absy;
319b3307321Smrg
320b3307321Smrg    XFetchName(dpy, window, &win_name);
321b3307321Smrg    if (!win_name || !win_name[0]) {
322b3307321Smrg	win_name = "xwdump";
323b3307321Smrg	got_win_name = False;
324b3307321Smrg    } else {
325b3307321Smrg	got_win_name = True;
326b3307321Smrg    }
327b3307321Smrg
328b3307321Smrg    /* sizeof(char) is included for the null string terminator. */
329b3307321Smrg    win_name_size = strlen(win_name) + sizeof(char);
330b3307321Smrg
331b3307321Smrg    /*
332b3307321Smrg     * Snarf the pixmap with XGetImage.
333b3307321Smrg     */
334b3307321Smrg
335b3307321Smrg    x = absx - win_info.x;
336b3307321Smrg    y = absy - win_info.y;
337b3307321Smrg
338b3307321Smrg    multiVis = GetMultiVisualRegions(dpy,RootWindow(dpy, screen),
339b3307321Smrg               absx, absy,
340b3307321Smrg	       width, height,&transparentOverlays,&numVisuals, &pVisuals,
341b3307321Smrg               &numOverlayVisuals,&pOverlayVisuals,&numImageVisuals,
342b3307321Smrg               &pImageVisuals,&vis_regions,&vis_image_regions,&allImage) ;
343b3307321Smrg    if (on_root || multiVis)
344b3307321Smrg    {
345b3307321Smrg	if(!multiVis)
346b3307321Smrg	    image = XGetImage (dpy, RootWindow(dpy, screen), absx, absy,
347b3307321Smrg                    width, height, AllPlanes, format);
348b3307321Smrg	else
349b3307321Smrg	    image = ReadAreaToImage(dpy, RootWindow(dpy, screen), absx, absy,
350b3307321Smrg                width, height,
351b3307321Smrg    		numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,
352b3307321Smrg                numImageVisuals, pImageVisuals,vis_regions,
353b3307321Smrg                vis_image_regions,format,allImage);
354b3307321Smrg    }
355b3307321Smrg    else
356b3307321Smrg	image = XGetImage (dpy, window, x, y, width, height, AllPlanes, format);
357b3307321Smrg    if (!image) {
358b3307321Smrg	fprintf (stderr, "%s:  unable to get image at %dx%d+%d+%d\n",
359b3307321Smrg		 program_name, width, height, x, y);
360b3307321Smrg	exit (1);
361b3307321Smrg    }
362b3307321Smrg
363b3307321Smrg    if (add_pixel_value != 0) XAddPixel (image, add_pixel_value);
364b3307321Smrg
365b3307321Smrg    /*
366b3307321Smrg     * Determine the pixmap size.
367b3307321Smrg     */
368b3307321Smrg    buffer_size = Image_Size(image);
369b3307321Smrg
370b3307321Smrg    if (debug) outl("xwd: Getting Colors.\n");
371b3307321Smrg
372b3307321Smrg    if( !multiVis)
373b3307321Smrg    {
374b3307321Smrg       ncolors = Get_XColors(&win_info, &colors);
375b3307321Smrg       vis = win_info.visual ;
376b3307321Smrg    }
377b3307321Smrg    else
378b3307321Smrg    {
379b3307321Smrg       ncolors = Get24bitDirectColors(&colors) ;
380b3307321Smrg       initFakeVisual(&vis_h) ;
381b3307321Smrg       vis = &vis_h ;
382b3307321Smrg    }
383b3307321Smrg    /*
384b3307321Smrg     * Inform the user that the image has been retrieved.
385b3307321Smrg     */
386b3307321Smrg    if (!silent) {
387b3307321Smrg#ifdef XKB
388b3307321Smrg	XkbStdBell(dpy,window,FEEP_VOLUME,XkbBI_Proceed);
389b3307321Smrg	XkbStdBell(dpy,window,FEEP_VOLUME,XkbBI_RepeatingLastBell);
390b3307321Smrg#else
391b3307321Smrg	XBell(dpy, FEEP_VOLUME);
392b3307321Smrg	XBell(dpy, FEEP_VOLUME);
393b3307321Smrg#endif
394b3307321Smrg	XFlush(dpy);
395b3307321Smrg    }
396b3307321Smrg
397b3307321Smrg    /*
398b3307321Smrg     * Calculate header size.
399b3307321Smrg     */
400b3307321Smrg    if (debug) outl("xwd: Calculating header size.\n");
401b3307321Smrg    header_size = SIZEOF(XWDheader) + win_name_size;
402b3307321Smrg
403b3307321Smrg    /*
404b3307321Smrg     * Write out header information.
405b3307321Smrg     */
406b3307321Smrg    if (debug) outl("xwd: Constructing and dumping file header.\n");
407b3307321Smrg    header.header_size = (CARD32) header_size;
408b3307321Smrg    header.file_version = (CARD32) XWD_FILE_VERSION;
409b3307321Smrg    header.pixmap_format = (CARD32) format;
410b3307321Smrg    header.pixmap_depth = (CARD32) image->depth;
411b3307321Smrg    header.pixmap_width = (CARD32) image->width;
412b3307321Smrg    header.pixmap_height = (CARD32) image->height;
413b3307321Smrg    header.xoffset = (CARD32) image->xoffset;
414b3307321Smrg    header.byte_order = (CARD32) image->byte_order;
415b3307321Smrg    header.bitmap_unit = (CARD32) image->bitmap_unit;
416b3307321Smrg    header.bitmap_bit_order = (CARD32) image->bitmap_bit_order;
417b3307321Smrg    header.bitmap_pad = (CARD32) image->bitmap_pad;
418b3307321Smrg    header.bits_per_pixel = (CARD32) image->bits_per_pixel;
419b3307321Smrg    header.bytes_per_line = (CARD32) image->bytes_per_line;
420b3307321Smrg    /****
421b3307321Smrg    header.visual_class = (CARD32) win_info.visual->class;
422b3307321Smrg    header.red_mask = (CARD32) win_info.visual->red_mask;
423b3307321Smrg    header.green_mask = (CARD32) win_info.visual->green_mask;
424b3307321Smrg    header.blue_mask = (CARD32) win_info.visual->blue_mask;
425b3307321Smrg    header.bits_per_rgb = (CARD32) win_info.visual->bits_per_rgb;
426b3307321Smrg    header.colormap_entries = (CARD32) win_info.visual->map_entries;
427b3307321Smrg    *****/
428b3307321Smrg    header.visual_class = (CARD32) vis->class;
429b3307321Smrg    header.red_mask = (CARD32) vis->red_mask;
430b3307321Smrg    header.green_mask = (CARD32) vis->green_mask;
431b3307321Smrg    header.blue_mask = (CARD32) vis->blue_mask;
432b3307321Smrg    header.bits_per_rgb = (CARD32) vis->bits_per_rgb;
433b3307321Smrg    header.colormap_entries = (CARD32) vis->map_entries;
434b3307321Smrg
435b3307321Smrg    header.ncolors = ncolors;
436b3307321Smrg    header.window_width = (CARD32) win_info.width;
437b3307321Smrg    header.window_height = (CARD32) win_info.height;
438b3307321Smrg    header.window_x = absx;
439b3307321Smrg    header.window_y = absy;
440b3307321Smrg    header.window_bdrwidth = (CARD32) win_info.border_width;
441b3307321Smrg
442b3307321Smrg    if (*(char *) &swaptest) {
443b3307321Smrg	_swaplong((char *) &header, sizeof(header));
444b3307321Smrg	for (i = 0; i < ncolors; i++) {
445b3307321Smrg	    _swaplong((char *) &colors[i].pixel, sizeof(CARD32));
446b3307321Smrg	    _swapshort((char *) &colors[i].red, 3 * sizeof(short));
447b3307321Smrg	}
448b3307321Smrg    }
449b3307321Smrg
450b3307321Smrg    if (fwrite((char *)&header, SIZEOF(XWDheader), 1, out) != 1 ||
451b3307321Smrg	fwrite(win_name, win_name_size, 1, out) != 1) {
452b3307321Smrg	perror("xwd");
453b3307321Smrg	exit(1);
454b3307321Smrg    }
455b3307321Smrg
456b3307321Smrg    /*
457b3307321Smrg     * Write out the color maps, if any
458b3307321Smrg     */
459b3307321Smrg
460b3307321Smrg    if (debug) outl("xwd: Dumping %d colors.\n", ncolors);
461b3307321Smrg    for (i = 0; i < ncolors; i++) {
462b3307321Smrg	xwdcolor.pixel = colors[i].pixel;
463b3307321Smrg	xwdcolor.red = colors[i].red;
464b3307321Smrg	xwdcolor.green = colors[i].green;
465b3307321Smrg	xwdcolor.blue = colors[i].blue;
466b3307321Smrg	xwdcolor.flags = colors[i].flags;
467b3307321Smrg	if (fwrite((char *) &xwdcolor, SIZEOF(XWDColor), 1, out) != 1) {
468b3307321Smrg	    perror("xwd");
469b3307321Smrg	    exit(1);
470b3307321Smrg	}
471b3307321Smrg    }
472b3307321Smrg
473b3307321Smrg    /*
474b3307321Smrg     * Write out the buffer.
475b3307321Smrg     */
476b3307321Smrg    if (debug) outl("xwd: Dumping pixmap.  bufsize=%d\n",buffer_size);
477b3307321Smrg
478b3307321Smrg    /*
479b3307321Smrg     *    This copying of the bit stream (data) to a file is to be replaced
480b3307321Smrg     *  by an Xlib call which hasn't been written yet.  It is not clear
481b3307321Smrg     *  what other functions of xwd will be taken over by this (as yet)
482b3307321Smrg     *  non-existant X function.
483b3307321Smrg     */
484b3307321Smrg    if (fwrite(image->data, (int) buffer_size, 1, out) != 1) {
485b3307321Smrg	perror("xwd");
486b3307321Smrg	exit(1);
487b3307321Smrg    }
488b3307321Smrg
489b3307321Smrg    /*
490b3307321Smrg     * free the color buffer.
491b3307321Smrg     */
492b3307321Smrg
493b3307321Smrg    if(debug && ncolors > 0) outl("xwd: Freeing colors.\n");
494b3307321Smrg    if(ncolors > 0) free(colors);
495b3307321Smrg
496b3307321Smrg    /*
497b3307321Smrg     * Free window name string.
498b3307321Smrg     */
499b3307321Smrg    if (debug) outl("xwd: Freeing window name string.\n");
500b3307321Smrg    if (got_win_name) XFree(win_name);
501b3307321Smrg
502b3307321Smrg    /*
503b3307321Smrg     * Free image
504b3307321Smrg     */
505b3307321Smrg    XDestroyImage(image);
506b3307321Smrg}
507b3307321Smrg
508b3307321Smrg/*
509b3307321Smrg * Report the syntax for calling xwd.
510b3307321Smrg */
511b3307321Smrgvoid
5125e358ecaSmrgusage(void)
513b3307321Smrg{
514b3307321Smrg    fprintf (stderr,
515b3307321Smrg"usage: %s [-display host:dpy] [-debug] [-help] %s [-nobdrs] [-out <file>]",
516b3307321Smrg	   program_name, "[{-root|-id <id>|-name <name>}]");
517b3307321Smrg    fprintf (stderr, " [-xy] [-add value] [-frame]\n");
518b3307321Smrg    exit(1);
519b3307321Smrg}
520b3307321Smrg
521b3307321Smrg
522b3307321Smrg/*
523b3307321Smrg * Determine the pixmap size.
524b3307321Smrg */
525b3307321Smrg
5265e358ecaSmrgint Image_Size(XImage *image)
527b3307321Smrg{
528b3307321Smrg    if (image->format != ZPixmap)
529b3307321Smrg      return(image->bytes_per_line * image->height * image->depth);
530b3307321Smrg
531b3307321Smrg    return(image->bytes_per_line * image->height);
532b3307321Smrg}
533b3307321Smrg
534b3307321Smrg#define lowbit(x) ((x) & (~(x) + 1))
535b3307321Smrg
536b3307321Smrgstatic int
5375e358ecaSmrgReadColors(Visual *vis, Colormap cmap, XColor **colors)
538b3307321Smrg{
539b3307321Smrg    int i,ncolors ;
540b3307321Smrg
541b3307321Smrg    ncolors = vis->map_entries;
542b3307321Smrg
543b3307321Smrg    if (!(*colors = (XColor *) malloc (sizeof(XColor) * ncolors)))
544b3307321Smrg      Fatal_Error("Out of memory!");
545b3307321Smrg
546b3307321Smrg    if (vis->class == DirectColor ||
547b3307321Smrg	vis->class == TrueColor) {
548b3307321Smrg	Pixel red, green, blue, red1, green1, blue1;
549b3307321Smrg
550b3307321Smrg	red = green = blue = 0;
551b3307321Smrg	red1 = lowbit(vis->red_mask);
552b3307321Smrg	green1 = lowbit(vis->green_mask);
553b3307321Smrg	blue1 = lowbit(vis->blue_mask);
554b3307321Smrg	for (i=0; i<ncolors; i++) {
555b3307321Smrg	  (*colors)[i].pixel = red|green|blue;
556b3307321Smrg	  (*colors)[i].pad = 0;
557b3307321Smrg	  red += red1;
558b3307321Smrg	  if (red > vis->red_mask)
559b3307321Smrg	    red = 0;
560b3307321Smrg	  green += green1;
561b3307321Smrg	  if (green > vis->green_mask)
562b3307321Smrg	    green = 0;
563b3307321Smrg	  blue += blue1;
564b3307321Smrg	  if (blue > vis->blue_mask)
565b3307321Smrg	    blue = 0;
566b3307321Smrg	}
567b3307321Smrg    } else {
568b3307321Smrg	for (i=0; i<ncolors; i++) {
569b3307321Smrg	  (*colors)[i].pixel = i;
570b3307321Smrg	  (*colors)[i].pad = 0;
571b3307321Smrg	}
572b3307321Smrg    }
573b3307321Smrg
574b3307321Smrg    XQueryColors(dpy, cmap, *colors, ncolors);
575b3307321Smrg
576b3307321Smrg    return(ncolors);
577b3307321Smrg}
578b3307321Smrg
579b3307321Smrg/*
580b3307321Smrg * Get the XColors of all pixels in image - returns # of colors
581b3307321Smrg */
5825e358ecaSmrgint Get_XColors(XWindowAttributes *win_info, XColor **colors)
583b3307321Smrg{
584b3307321Smrg    int i, ncolors;
585b3307321Smrg    Colormap cmap = win_info->colormap;
586b3307321Smrg
587b3307321Smrg    if (use_installed)
588b3307321Smrg	/* assume the visual will be OK ... */
589b3307321Smrg	cmap = XListInstalledColormaps(dpy, win_info->root, &i)[0];
590b3307321Smrg    if (!cmap)
591b3307321Smrg	return(0);
592b3307321Smrg    ncolors = ReadColors(win_info->visual,cmap,colors) ;
593b3307321Smrg    return ncolors ;
594b3307321Smrg}
595b3307321Smrg
596b3307321Smrgvoid
5975e358ecaSmrg_swapshort (register char *bp, register unsigned n)
598b3307321Smrg{
599b3307321Smrg    register char c;
600b3307321Smrg    register char *ep = bp + n;
601b3307321Smrg
602b3307321Smrg    while (bp < ep) {
603b3307321Smrg	c = *bp;
604b3307321Smrg	*bp = *(bp + 1);
605b3307321Smrg	bp++;
606b3307321Smrg	*bp++ = c;
607b3307321Smrg    }
608b3307321Smrg}
609b3307321Smrg
610b3307321Smrgvoid
6115e358ecaSmrg_swaplong (register char *bp, register unsigned n)
612b3307321Smrg{
613b3307321Smrg    register char c;
614b3307321Smrg    register char *ep = bp + n;
615b3307321Smrg
616b3307321Smrg    while (bp < ep) {
617b3307321Smrg        c = bp[3];
618b3307321Smrg        bp[3] = bp[0];
619b3307321Smrg        bp[0] = c;
620b3307321Smrg        c = bp[2];
621b3307321Smrg        bp[2] = bp[1];
622b3307321Smrg        bp[1] = c;
623b3307321Smrg        bp += 4;
624b3307321Smrg    }
625b3307321Smrg}
626