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