1b3307321Smrg/*
2b3307321Smrg
3b3307321SmrgCopyright 1987, 1998  The Open Group
4b3307321Smrg
5b3307321SmrgPermission to use, copy, modify, distribute, and sell this software and its
6b3307321Smrgdocumentation for any purpose is hereby granted without fee, provided that
7b3307321Smrgthe above copyright notice appear in all copies and that both that
8b3307321Smrgcopyright notice and this permission notice appear in supporting
9b3307321Smrgdocumentation.
10b3307321Smrg
11b3307321SmrgThe above copyright notice and this permission notice shall be included in
12b3307321Smrgall copies or substantial portions of the Software.
13b3307321Smrg
14b3307321SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15b3307321SmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16b3307321SmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
17b3307321SmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18b3307321SmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19b3307321SmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20b3307321Smrg
21b3307321SmrgExcept as contained in this notice, the name of The Open Group shall not be
22b3307321Smrgused in advertising or otherwise to promote the sale, use or other dealings
23b3307321Smrgin this Software without prior written authorization from The Open Group.
24b3307321Smrg
25b3307321Smrg*/
26b3307321Smrg
27b3307321Smrg/*
28b3307321Smrg * xwd.c MIT Project Athena, X Window system window raster image dumper.
29b3307321Smrg *
3074a3f230Smrg * This program will dump a raster image of the contents of a window into a
31b3307321Smrg * file for output on graphics printers or for other uses.
32b3307321Smrg *
33b3307321Smrg *  Author:	Tony Della Fera, DEC
34b3307321Smrg *		17-Jun-85
3574a3f230Smrg *
36b3307321Smrg *  Modification history:
37b3307321Smrg *
38b3307321Smrg *  11/14/86 Bill Wyatt, Smithsonian Astrophysical Observatory
3974a3f230Smrg *    - Removed Z format option, changing it to an XY option. Monochrome
40b3307321Smrg *      windows will always dump in XY format. Color windows will dump
41b3307321Smrg *      in Z format by default, but can be dumped in XY format with the
42b3307321Smrg *      -xy option.
43b3307321Smrg *
44b3307321Smrg *  11/18/86 Bill Wyatt
4574a3f230Smrg *    - VERSION 6 is same as version 5 for monchrome. For colors, the
46b3307321Smrg *      appropriate number of Color structs are dumped after the header,
47b3307321Smrg *      which has the number of colors (=0 for monochrome) in place of the
48b3307321Smrg *      V5 padding at the end. Up to 16-bit displays are supported. I
49b3307321Smrg *      don't yet know how 24- to 32-bit displays will be handled under
50b3307321Smrg *      the Version 11 protocol.
51b3307321Smrg *
52b3307321Smrg *  6/15/87 David Krikorian, MIT Project Athena
53b3307321Smrg *    - VERSION 7 runs under the X Version 11 servers, while the previous
54b3307321Smrg *      versions of xwd were are for X Version 10.  This version is based
55b3307321Smrg *      on xwd version 6, and should eventually have the same color
56b3307321Smrg *      abilities. (Xwd V7 has yet to be tested on a color machine, so
57b3307321Smrg *      all color-related code is commented out until color support
58b3307321Smrg *      becomes practical.)
59b3307321Smrg */
60b3307321Smrg
61b3307321Smrg/*%
62b3307321Smrg *%    This is the format for commenting out color-related code until
63b3307321Smrg *%  color can be supported.
64b3307321Smrg%*/
65b3307321Smrg
6674a3f230Smrg#ifdef HAVE_CONFIG_H
6774a3f230Smrg#include "config.h"
6874a3f230Smrg#endif
6974a3f230Smrg
70b3307321Smrg#include <stdio.h>
71b3307321Smrg#include <errno.h>
72b3307321Smrg#include <X11/Xos.h>
73b3307321Smrg#include <stdlib.h>
74b3307321Smrg
75b3307321Smrg#include <X11/Xlib.h>
76b3307321Smrg#include <X11/Xutil.h>
77b3307321Smrg
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
11474b97a6cSmrgstatic long
11574b97a6cSmrgparse_long(char *s)
116b3307321Smrg{
117b3307321Smrg    long retval = 0L;
118b3307321Smrg    int thesign = 1;
119b3307321Smrg
120b3307321Smrg    if (s && s[0]) {
12174b97a6cSmrg        switch (s[0]) {
12274b97a6cSmrg        case '-':
12374b97a6cSmrg            (void) sscanf(s + 1, "%lu", &retval);
12474b97a6cSmrg            thesign = -1;
12574b97a6cSmrg            break;
12674b97a6cSmrg        case '0':
12774b97a6cSmrg            (void) sscanf(s + 1, "%lo", &retval);
12874b97a6cSmrg            break;
12974b97a6cSmrg        case 'x':
13074b97a6cSmrg        case 'X':
13174b97a6cSmrg            (void) sscanf(s + 1, "%lx", &retval);
13274b97a6cSmrg            break;
13374b97a6cSmrg        default:
13474b97a6cSmrg            (void) sscanf(s, "%lu", &retval);
13574b97a6cSmrg            break;
13674b97a6cSmrg        }
137b3307321Smrg    }
138b3307321Smrg    return (thesign * retval);
139b3307321Smrg}
140b3307321Smrg
141b3307321Smrgint
1425e358ecaSmrgmain(int argc, char **argv)
143b3307321Smrg{
144b3307321Smrg    register int i;
145b3307321Smrg    Window target_win;
146b3307321Smrg    FILE *out_file = stdout;
147b3307321Smrg    Bool frame_only = False;
148b3307321Smrg
149b3307321Smrg    INIT_NAME;
150b3307321Smrg
1516728f30eSmrg    /* Handle args that don't require opening a display */
1526728f30eSmrg    for (int n = 1; n < argc; n++) {
1536728f30eSmrg	const char *argn = argv[n];
1546728f30eSmrg	/* accept single or double dash for -help & -version */
1556728f30eSmrg	if (argn[0] == '-' && argn[1] == '-') {
1566728f30eSmrg	    argn++;
1576728f30eSmrg	}
1586728f30eSmrg	if (strcmp (argn, "-help") == 0) {
1596728f30eSmrg	    usage(NULL, EXIT_SUCCESS);
1606728f30eSmrg	    exit(0);
1616728f30eSmrg	}
1626728f30eSmrg	if (strcmp (argn, "-version") == 0) {
1636728f30eSmrg	    puts(PACKAGE_STRING);
1646728f30eSmrg	    exit(EXIT_SUCCESS);
1656728f30eSmrg	}
1666728f30eSmrg    }
1676728f30eSmrg
168b3307321Smrg    Setup_Display_And_Screen(&argc, argv);
169b3307321Smrg
170b3307321Smrg    /* Get window select on command line, if any */
171b3307321Smrg    target_win = Select_Window_Args(&argc, argv);
172b3307321Smrg
173b3307321Smrg    for (i = 1; i < argc; i++) {
17474b97a6cSmrg        if (!strcmp(argv[i], "-nobdrs")) {
17574b97a6cSmrg            nobdrs = True;
17674b97a6cSmrg            continue;
17774b97a6cSmrg        }
17874b97a6cSmrg        if (!strcmp(argv[i], "-debug")) {
17974b97a6cSmrg            debug = True;
18074b97a6cSmrg            continue;
18174b97a6cSmrg        }
18274b97a6cSmrg        if (!strcmp(argv[i], "-out")) {
18374b97a6cSmrg            if (++i >= argc)
1846728f30eSmrg                usage("-out requires an argument", EXIT_FAILURE);
18574b97a6cSmrg            if (!(out_file = fopen(argv[i], "wb")))
18674b97a6cSmrg                Fatal_Error("Can't open output file as specified.");
18774b97a6cSmrg            standard_out = False;
18874b97a6cSmrg            continue;
18974b97a6cSmrg        }
19074b97a6cSmrg        if (!strcmp(argv[i], "-xy")) {
19174b97a6cSmrg            format = XYPixmap;
19274b97a6cSmrg            continue;
19374b97a6cSmrg        }
19474b97a6cSmrg        if (!strcmp(argv[i], "-screen")) {
19574b97a6cSmrg            on_root = True;
19674b97a6cSmrg            continue;
19774b97a6cSmrg        }
19874b97a6cSmrg        if (!strcmp(argv[i], "-icmap")) {
19974b97a6cSmrg            use_installed = True;
20074b97a6cSmrg            continue;
20174b97a6cSmrg        }
20274b97a6cSmrg        if (!strcmp(argv[i], "-add")) {
20374b97a6cSmrg            if (++i >= argc)
2046728f30eSmrg                usage("-add requires an argument", EXIT_FAILURE);
20574b97a6cSmrg            add_pixel_value = parse_long(argv[i]);
20674b97a6cSmrg            continue;
20774b97a6cSmrg        }
20874b97a6cSmrg        if (!strcmp(argv[i], "-frame")) {
20974b97a6cSmrg            frame_only = True;
21074b97a6cSmrg            continue;
21174b97a6cSmrg        }
21274b97a6cSmrg        if (!strcmp(argv[i], "-silent")) {
21374b97a6cSmrg            silent = True;
21474b97a6cSmrg            continue;
21574b97a6cSmrg        }
21674b97a6cSmrg        fprintf(stderr, "%s: unrecognized argument '%s'\n",
21774b97a6cSmrg                program_name, argv[i]);
2186728f30eSmrg        usage(NULL, EXIT_FAILURE);
219b3307321Smrg    }
220b3307321Smrg#ifdef WIN32
221b3307321Smrg    if (standard_out)
22274b97a6cSmrg        _setmode(fileno(out_file), _O_BINARY);
223b3307321Smrg#endif
22474a3f230Smrg
225b3307321Smrg    /*
226b3307321Smrg     * Let the user select the target window.
227b3307321Smrg     */
228afe13c8eSmrg    if (target_win == None)
22974b97a6cSmrg        target_win = Select_Window(dpy, !frame_only);
230b3307321Smrg
231b3307321Smrg    /*
232b3307321Smrg     * Dump it!
233b3307321Smrg     */
234b3307321Smrg    Window_Dump(target_win, out_file);
235b3307321Smrg
236b3307321Smrg    XCloseDisplay(dpy);
237b3307321Smrg    if (fclose(out_file)) {
23874b97a6cSmrg        perror("xwd");
23974b97a6cSmrg        exit(1);
240b3307321Smrg    }
241b3307321Smrg    exit(0);
242b3307321Smrg}
243b3307321Smrg
244b3307321Smrgstatic int
2455e358ecaSmrgGet24bitDirectColors(XColor **colors)
246b3307321Smrg{
24774b97a6cSmrg    int i, ncolors = 256;
24874b97a6cSmrg    XColor *tcol;
249b3307321Smrg
2506728f30eSmrg    *colors = tcol = malloc(sizeof(XColor) * ncolors);
251b3307321Smrg
25274b97a6cSmrg    for (i = 0; i < ncolors; i++) {
25374b97a6cSmrg        tcol[i].pixel = i << 16 | i << 8 | i;
25474b97a6cSmrg        tcol[i].red = tcol[i].green = tcol[i].blue = i << 8 | i;
25574b97a6cSmrg        tcol[i].flags = 0;
256b3307321Smrg    }
257b3307321Smrg
25874b97a6cSmrg    return ncolors;
259b3307321Smrg}
260b3307321Smrg
261b3307321Smrg/*
262b3307321Smrg * Window_Dump: dump a window to a file which must already be open for
26374b97a6cSmrg *              writing.
264b3307321Smrg */
265b3307321Smrg
266b3307321Smrgvoid
2675e358ecaSmrgWindow_Dump(Window window, FILE *out)
268b3307321Smrg{
269b3307321Smrg    unsigned long swaptest = 1;
270b3307321Smrg    XColor *colors;
271b3307321Smrg    unsigned buffer_size;
27274a3f230Smrg    size_t win_name_size;
27374a3f230Smrg    CARD32 header_size;
274b3307321Smrg    int ncolors, i;
275b3307321Smrg    char *win_name;
27674a3f230Smrg    char default_win_name[] = "xwdump";
277b3307321Smrg    Bool got_win_name;
278b3307321Smrg    XWindowAttributes win_info;
279b3307321Smrg    XImage *image;
280b3307321Smrg    int absx, absy, x, y;
281b3307321Smrg    unsigned width, height;
282b3307321Smrg    int dwidth, dheight;
283b3307321Smrg    Window dummywin;
284b3307321Smrg    XWDFileHeader header;
285b3307321Smrg    XWDColor xwdcolor;
28674a3f230Smrg
28774b97a6cSmrg    int transparentOverlays, multiVis;
28874b97a6cSmrg    int numVisuals;
28974b97a6cSmrg    XVisualInfo *pVisuals;
29074b97a6cSmrg    int numOverlayVisuals;
29174b97a6cSmrg    OverlayInfo *pOverlayVisuals;
29274b97a6cSmrg    int numImageVisuals;
29374b97a6cSmrg    XVisualInfo **pImageVisuals;
29474b97a6cSmrg    list_ptr vis_regions;       /* list of regions to read from */
29574b97a6cSmrg    list_ptr vis_image_regions;
29674b97a6cSmrg    Visual vis_h, *vis;
29774b97a6cSmrg    int allImage = 0;
298b3307321Smrg
299b3307321Smrg    /*
300b3307321Smrg     * Inform the user not to alter the screen.
301b3307321Smrg     */
302b3307321Smrg    if (!silent) {
303b3307321Smrg#ifdef XKB
30474b97a6cSmrg        XkbStdBell(dpy, None, 50, XkbBI_Wait);
305b3307321Smrg#else
30674b97a6cSmrg        XBell(dpy, FEEP_VOLUME);
307b3307321Smrg#endif
30874b97a6cSmrg        XFlush(dpy);
309b3307321Smrg    }
310b3307321Smrg
311b3307321Smrg    /*
312b3307321Smrg     * Get the parameters of the window being dumped.
313b3307321Smrg     */
31474b97a6cSmrg    if (debug)
31574b97a6cSmrg        outl("xwd: Getting target window information.\n");
31674b97a6cSmrg    if (!XGetWindowAttributes(dpy, window, &win_info))
31774b97a6cSmrg        Fatal_Error("Can't get target window attributes.");
318b3307321Smrg
319b3307321Smrg    /* handle any frame window */
32074b97a6cSmrg    if (!XTranslateCoordinates(dpy, window, RootWindow(dpy, screen), 0, 0,
32174b97a6cSmrg                               &absx, &absy, &dummywin)) {
32274b97a6cSmrg        fprintf(stderr,
32374b97a6cSmrg                "%s:  unable to translate window coordinates (%d,%d)\n",
32474b97a6cSmrg                program_name, absx, absy);
32574b97a6cSmrg        exit(1);
326b3307321Smrg    }
327b3307321Smrg    win_info.x = absx;
328b3307321Smrg    win_info.y = absy;
329b3307321Smrg    width = win_info.width;
330b3307321Smrg    height = win_info.height;
331b3307321Smrg
332b3307321Smrg    if (!nobdrs) {
33374b97a6cSmrg        absx -= win_info.border_width;
33474b97a6cSmrg        absy -= win_info.border_width;
33574b97a6cSmrg        width += (2 * win_info.border_width);
33674b97a6cSmrg        height += (2 * win_info.border_width);
337b3307321Smrg    }
33874b97a6cSmrg    dwidth = DisplayWidth(dpy, screen);
33974b97a6cSmrg    dheight = DisplayHeight(dpy, screen);
340b3307321Smrg
341b3307321Smrg    /* clip to window */
3426728f30eSmrg    if (absx < 0) {
3436728f30eSmrg        width += absx;
3446728f30eSmrg        absx = 0;
3456728f30eSmrg    }
3466728f30eSmrg    if (absy < 0) {
3476728f30eSmrg        height += absy;
3486728f30eSmrg        absy = 0;
3496728f30eSmrg    }
35074b97a6cSmrg    if (absx + width > dwidth)
35174b97a6cSmrg        width = dwidth - absx;
35274b97a6cSmrg    if (absy + height > dheight)
35374b97a6cSmrg        height = dheight - absy;
35474b97a6cSmrg
35574b97a6cSmrg    if (!XFetchName(dpy, window, &win_name) || !win_name || !win_name[0]) {
35674b97a6cSmrg        win_name = default_win_name;
35774b97a6cSmrg        got_win_name = False;
35874b97a6cSmrg    }
35974b97a6cSmrg    else {
36074b97a6cSmrg        got_win_name = True;
361b3307321Smrg    }
362b3307321Smrg
363b3307321Smrg    /* sizeof(char) is included for the null string terminator. */
364b3307321Smrg    win_name_size = strlen(win_name) + sizeof(char);
365b3307321Smrg
366b3307321Smrg    /*
367b3307321Smrg     * Snarf the pixmap with XGetImage.
368b3307321Smrg     */
369b3307321Smrg
370b3307321Smrg    x = absx - win_info.x;
371b3307321Smrg    y = absy - win_info.y;
372b3307321Smrg
37374b97a6cSmrg    multiVis = GetMultiVisualRegions(dpy, RootWindow(dpy, screen),
37474b97a6cSmrg                                     absx, absy,
37574b97a6cSmrg                                     width, height, &transparentOverlays,
37674b97a6cSmrg                                     &numVisuals, &pVisuals,
37774b97a6cSmrg                                     &numOverlayVisuals, &pOverlayVisuals,
37874b97a6cSmrg                                     &numImageVisuals, &pImageVisuals,
37974b97a6cSmrg                                     &vis_regions, &vis_image_regions,
38074b97a6cSmrg                                     &allImage);
38174b97a6cSmrg    if (on_root || multiVis) {
38274b97a6cSmrg        if (!multiVis)
38374b97a6cSmrg            image = XGetImage(dpy, RootWindow(dpy, screen), absx, absy,
38474b97a6cSmrg                              width, height, AllPlanes, format);
38574b97a6cSmrg        else
38674b97a6cSmrg            image = ReadAreaToImage(dpy, RootWindow(dpy, screen), absx, absy,
38774b97a6cSmrg                                    width, height,
38874b97a6cSmrg                                    numVisuals, pVisuals,
38974b97a6cSmrg                                    numOverlayVisuals, pOverlayVisuals,
39074b97a6cSmrg                                    numImageVisuals, pImageVisuals,
39174b97a6cSmrg                                    vis_regions, vis_image_regions,
39274b97a6cSmrg                                    format, allImage);
393b3307321Smrg    }
394b3307321Smrg    else
39574b97a6cSmrg        image = XGetImage(dpy, window, x, y, width, height, AllPlanes, format);
396b3307321Smrg    if (!image) {
39774b97a6cSmrg        fprintf(stderr, "%s:  unable to get image at %dx%d+%d+%d\n",
39874b97a6cSmrg                program_name, width, height, x, y);
39974b97a6cSmrg        exit(1);
400b3307321Smrg    }
401b3307321Smrg
40274b97a6cSmrg    if (add_pixel_value != 0)
40374b97a6cSmrg        XAddPixel(image, add_pixel_value);
404b3307321Smrg
405b3307321Smrg    /*
406b3307321Smrg     * Determine the pixmap size.
407b3307321Smrg     */
408b3307321Smrg    buffer_size = Image_Size(image);
409b3307321Smrg
41074b97a6cSmrg    if (debug)
41174b97a6cSmrg        outl("xwd: Getting Colors.\n");
412b3307321Smrg
41374b97a6cSmrg    if (!multiVis) {
41474b97a6cSmrg        ncolors = Get_XColors(&win_info, &colors);
41574b97a6cSmrg        vis = win_info.visual;
416b3307321Smrg    }
41774b97a6cSmrg    else {
41874b97a6cSmrg        ncolors = Get24bitDirectColors(&colors);
41974b97a6cSmrg        initFakeVisual(&vis_h);
42074b97a6cSmrg        vis = &vis_h;
421b3307321Smrg    }
422b3307321Smrg    /*
423b3307321Smrg     * Inform the user that the image has been retrieved.
424b3307321Smrg     */
425b3307321Smrg    if (!silent) {
426b3307321Smrg#ifdef XKB
42774b97a6cSmrg        XkbStdBell(dpy, window, FEEP_VOLUME, XkbBI_Proceed);
42874b97a6cSmrg        XkbStdBell(dpy, window, FEEP_VOLUME, XkbBI_RepeatingLastBell);
429b3307321Smrg#else
43074b97a6cSmrg        XBell(dpy, FEEP_VOLUME);
43174b97a6cSmrg        XBell(dpy, FEEP_VOLUME);
432b3307321Smrg#endif
43374b97a6cSmrg        XFlush(dpy);
434b3307321Smrg    }
435b3307321Smrg
436b3307321Smrg    /*
437b3307321Smrg     * Calculate header size.
438b3307321Smrg     */
43974b97a6cSmrg    if (debug)
44074b97a6cSmrg        outl("xwd: Calculating header size.\n");
44174a3f230Smrg    header_size = SIZEOF(XWDheader) + (CARD32) win_name_size;
442b3307321Smrg
443b3307321Smrg    /*
444b3307321Smrg     * Write out header information.
445b3307321Smrg     */
44674b97a6cSmrg    if (debug)
44774b97a6cSmrg        outl("xwd: Constructing and dumping file header.\n");
44874b97a6cSmrg    memset(&header, 0, SIZEOF(XWDheader));
449b3307321Smrg    header.header_size = (CARD32) header_size;
450b3307321Smrg    header.file_version = (CARD32) XWD_FILE_VERSION;
451b3307321Smrg    header.pixmap_format = (CARD32) format;
452b3307321Smrg    header.pixmap_depth = (CARD32) image->depth;
453b3307321Smrg    header.pixmap_width = (CARD32) image->width;
454b3307321Smrg    header.pixmap_height = (CARD32) image->height;
455b3307321Smrg    header.xoffset = (CARD32) image->xoffset;
456b3307321Smrg    header.byte_order = (CARD32) image->byte_order;
457b3307321Smrg    header.bitmap_unit = (CARD32) image->bitmap_unit;
458b3307321Smrg    header.bitmap_bit_order = (CARD32) image->bitmap_bit_order;
459b3307321Smrg    header.bitmap_pad = (CARD32) image->bitmap_pad;
460b3307321Smrg    header.bits_per_pixel = (CARD32) image->bits_per_pixel;
461b3307321Smrg    header.bytes_per_line = (CARD32) image->bytes_per_line;
462b3307321Smrg    /****
463b3307321Smrg    header.visual_class = (CARD32) win_info.visual->class;
464b3307321Smrg    header.red_mask = (CARD32) win_info.visual->red_mask;
465b3307321Smrg    header.green_mask = (CARD32) win_info.visual->green_mask;
466b3307321Smrg    header.blue_mask = (CARD32) win_info.visual->blue_mask;
467b3307321Smrg    header.bits_per_rgb = (CARD32) win_info.visual->bits_per_rgb;
468b3307321Smrg    header.colormap_entries = (CARD32) win_info.visual->map_entries;
469b3307321Smrg    *****/
470b3307321Smrg    header.visual_class = (CARD32) vis->class;
471b3307321Smrg    header.red_mask = (CARD32) vis->red_mask;
472b3307321Smrg    header.green_mask = (CARD32) vis->green_mask;
473b3307321Smrg    header.blue_mask = (CARD32) vis->blue_mask;
474b3307321Smrg    header.bits_per_rgb = (CARD32) vis->bits_per_rgb;
475b3307321Smrg    header.colormap_entries = (CARD32) vis->map_entries;
476b3307321Smrg
477b3307321Smrg    header.ncolors = ncolors;
478b3307321Smrg    header.window_width = (CARD32) win_info.width;
479b3307321Smrg    header.window_height = (CARD32) win_info.height;
480b3307321Smrg    header.window_x = absx;
481b3307321Smrg    header.window_y = absy;
482b3307321Smrg    header.window_bdrwidth = (CARD32) win_info.border_width;
483b3307321Smrg
484b3307321Smrg    if (*(char *) &swaptest) {
48574b97a6cSmrg        _swaplong((char *) &header, sizeof(header));
48674b97a6cSmrg        for (i = 0; i < ncolors; i++) {
48774b97a6cSmrg            _swaplong((char *) &colors[i].pixel, sizeof(CARD32));
48874b97a6cSmrg            _swapshort((char *) &colors[i].red, 3 * sizeof(short));
48974b97a6cSmrg        }
490b3307321Smrg    }
491b3307321Smrg
49274b97a6cSmrg    if (fwrite((char *) &header, SIZEOF(XWDheader), 1, out) != 1 ||
49374b97a6cSmrg        fwrite(win_name, win_name_size, 1, out) != 1) {
49474b97a6cSmrg        perror("xwd");
49574b97a6cSmrg        exit(1);
496b3307321Smrg    }
497b3307321Smrg
498b3307321Smrg    /*
499b3307321Smrg     * Write out the color maps, if any
500b3307321Smrg     */
501b3307321Smrg
50274b97a6cSmrg    if (debug)
50374b97a6cSmrg        outl("xwd: Dumping %d colors.\n", ncolors);
504b3307321Smrg    for (i = 0; i < ncolors; i++) {
50574b97a6cSmrg        xwdcolor.pixel = colors[i].pixel;
50674b97a6cSmrg        xwdcolor.red = colors[i].red;
50774b97a6cSmrg        xwdcolor.green = colors[i].green;
50874b97a6cSmrg        xwdcolor.blue = colors[i].blue;
50974b97a6cSmrg        xwdcolor.flags = colors[i].flags;
51074b97a6cSmrg        if (fwrite((char *) &xwdcolor, SIZEOF(XWDColor), 1, out) != 1) {
51174b97a6cSmrg            perror("xwd");
51274b97a6cSmrg            exit(1);
51374b97a6cSmrg        }
514b3307321Smrg    }
515b3307321Smrg
516b3307321Smrg    /*
517b3307321Smrg     * Write out the buffer.
518b3307321Smrg     */
51974b97a6cSmrg    if (debug)
52074b97a6cSmrg        outl("xwd: Dumping pixmap.  bufsize=%d\n", buffer_size);
521b3307321Smrg
522b3307321Smrg    /*
52374b97a6cSmrg     *  This copying of the bit stream (data) to a file is to be replaced
524b3307321Smrg     *  by an Xlib call which hasn't been written yet.  It is not clear
525b3307321Smrg     *  what other functions of xwd will be taken over by this (as yet)
5266728f30eSmrg     *  non-existent X function.
527b3307321Smrg     */
528b3307321Smrg    if (fwrite(image->data, (int) buffer_size, 1, out) != 1) {
52974b97a6cSmrg        perror("xwd");
53074b97a6cSmrg        exit(1);
531b3307321Smrg    }
532b3307321Smrg
533b3307321Smrg    /*
534b3307321Smrg     * free the color buffer.
535b3307321Smrg     */
536b3307321Smrg
53774b97a6cSmrg    if (debug && ncolors > 0)
53874b97a6cSmrg        outl("xwd: Freeing colors.\n");
53974b97a6cSmrg    if (ncolors > 0)
54074b97a6cSmrg        free(colors);
541b3307321Smrg
542b3307321Smrg    /*
543b3307321Smrg     * Free window name string.
544b3307321Smrg     */
54574b97a6cSmrg    if (debug)
54674b97a6cSmrg        outl("xwd: Freeing window name string.\n");
54774b97a6cSmrg    if (got_win_name)
54874b97a6cSmrg        XFree(win_name);
549b3307321Smrg
550b3307321Smrg    /*
551b3307321Smrg     * Free image
552b3307321Smrg     */
553b3307321Smrg    XDestroyImage(image);
554b3307321Smrg}
555b3307321Smrg
556b3307321Smrg/*
557b3307321Smrg * Report the syntax for calling xwd.
558b3307321Smrg */
559b3307321Smrgvoid
5606728f30eSmrgusage(const char *errmsg, int exitval)
561b3307321Smrg{
56206ef0fecSmrg    if (errmsg != NULL)
56374b97a6cSmrg        fprintf(stderr, "%s: %s\n", program_name, errmsg);
56474b97a6cSmrg
56574b97a6cSmrg    fprintf(stderr,
56674b97a6cSmrg            "Usage: %s [options] [-root| -id <wdid>| -name <wdname>] > mywddump\n",
56774b97a6cSmrg            program_name);
56874b97a6cSmrg    fprintf(stderr,
56974b97a6cSmrg            "       %s [options] [-root| -id <wdid>| -name <wdname>] -out mywddump\n",
57074b97a6cSmrg            program_name);
57174b97a6cSmrg    fputs("Options:\n" "  -help                    Print this message\n"
57274b97a6cSmrg          "  -version                 Print the program version and exit\n"
57374b97a6cSmrg          "  -debug                   Enable debug mode\n"
57474b97a6cSmrg          "  -d, -display <host:dpy>  Specify server to connect\n"
57574b97a6cSmrg          "  -nobdrs                  Exclude window borders\n"
57674b97a6cSmrg          "  -out <file>              Specify an output file\n"
57774b97a6cSmrg          "  -xy                      Select XY dumping format for color displays\n"
57874b97a6cSmrg          "  -add <value>             Add a signed value to every pixel\n"
57974b97a6cSmrg          "  -frame                   Include window manager frame\n"
58074b97a6cSmrg          "  -root                    Select the root window\n"
58174b97a6cSmrg          "  -id <wdid>               Select a window by its resource id\n"
58274b97a6cSmrg          "  -name <wdname>           Select a window by its WM_NAME property\n"
58374b97a6cSmrg          "  -icmap                   Use the first colormap of the screen\n"
58474b97a6cSmrg          "  -screen                  Send the request against the root window\n"
58574b97a6cSmrg          "  -silent                  Don't ring any bells\n", stderr);
5866728f30eSmrg    exit(exitval);
587b3307321Smrg}
588b3307321Smrg
589b3307321Smrg/*
590b3307321Smrg * Determine the pixmap size.
591b3307321Smrg */
592b3307321Smrg
59374b97a6cSmrgint
59474b97a6cSmrgImage_Size(XImage *image)
595b3307321Smrg{
596b3307321Smrg    if (image->format != ZPixmap)
59774b97a6cSmrg        return (image->bytes_per_line * image->height * image->depth);
598b3307321Smrg
59974b97a6cSmrg    return (image->bytes_per_line * image->height);
600b3307321Smrg}
601b3307321Smrg
602b3307321Smrg#define lowbit(x) ((x) & (~(x) + 1))
603b3307321Smrg
604b3307321Smrgstatic int
6055e358ecaSmrgReadColors(Visual *vis, Colormap cmap, XColor **colors)
606b3307321Smrg{
60774b97a6cSmrg    int i, ncolors;
608b3307321Smrg
609b3307321Smrg    ncolors = vis->map_entries;
610b3307321Smrg
6116728f30eSmrg    if (!(*colors = malloc(sizeof(XColor) * ncolors)))
61274b97a6cSmrg        Fatal_Error("Out of memory!");
61374b97a6cSmrg
61474b97a6cSmrg    if (vis->class == DirectColor || vis->class == TrueColor) {
61574b97a6cSmrg        Pixel red, green, blue, red1, green1, blue1;
61674b97a6cSmrg
61774b97a6cSmrg        red = green = blue = 0;
61874b97a6cSmrg        red1 = lowbit(vis->red_mask);
61974b97a6cSmrg        green1 = lowbit(vis->green_mask);
62074b97a6cSmrg        blue1 = lowbit(vis->blue_mask);
62174b97a6cSmrg        for (i = 0; i < ncolors; i++) {
62274b97a6cSmrg            (*colors)[i].pixel = red | green | blue;
62374b97a6cSmrg            (*colors)[i].pad = 0;
62474b97a6cSmrg            red += red1;
62574b97a6cSmrg            if (red > vis->red_mask)
62674b97a6cSmrg                red = 0;
62774b97a6cSmrg            green += green1;
62874b97a6cSmrg            if (green > vis->green_mask)
62974b97a6cSmrg                green = 0;
63074b97a6cSmrg            blue += blue1;
63174b97a6cSmrg            if (blue > vis->blue_mask)
63274b97a6cSmrg                blue = 0;
63374b97a6cSmrg        }
63474b97a6cSmrg    }
63574b97a6cSmrg    else {
63674b97a6cSmrg        for (i = 0; i < ncolors; i++) {
63774b97a6cSmrg            (*colors)[i].pixel = i;
63874b97a6cSmrg            (*colors)[i].pad = 0;
63974b97a6cSmrg        }
640b3307321Smrg    }
641b3307321Smrg
642b3307321Smrg    XQueryColors(dpy, cmap, *colors, ncolors);
64374a3f230Smrg
64474b97a6cSmrg    return (ncolors);
645b3307321Smrg}
646b3307321Smrg
647b3307321Smrg/*
648b3307321Smrg * Get the XColors of all pixels in image - returns # of colors
649b3307321Smrg */
65074b97a6cSmrgint
65174b97a6cSmrgGet_XColors(XWindowAttributes *win_info, XColor **colors)
652b3307321Smrg{
653b3307321Smrg    int i, ncolors;
654b3307321Smrg    Colormap cmap = win_info->colormap;
655b3307321Smrg
656b3307321Smrg    if (use_installed)
65774b97a6cSmrg        /* assume the visual will be OK ... */
65874b97a6cSmrg        cmap = XListInstalledColormaps(dpy, win_info->root, &i)[0];
659b3307321Smrg    if (!cmap)
66074b97a6cSmrg        return (0);
66174b97a6cSmrg    ncolors = ReadColors(win_info->visual, cmap, colors);
66274b97a6cSmrg    return ncolors;
663b3307321Smrg}
664b3307321Smrg
665b3307321Smrgvoid
66674b97a6cSmrg_swapshort(register char *bp, register unsigned n)
667b3307321Smrg{
6686728f30eSmrg    char *ep = bp + n;
669b3307321Smrg
670b3307321Smrg    while (bp < ep) {
6716728f30eSmrg        char c = *bp;
67274b97a6cSmrg        *bp = *(bp + 1);
67374b97a6cSmrg        bp++;
67474b97a6cSmrg        *bp++ = c;
675b3307321Smrg    }
676b3307321Smrg}
677b3307321Smrg
678b3307321Smrgvoid
67974b97a6cSmrg_swaplong(register char *bp, register unsigned n)
680b3307321Smrg{
6816728f30eSmrg    char *ep = bp + n;
682b3307321Smrg
683b3307321Smrg    while (bp < ep) {
6846728f30eSmrg        char c = bp[3];
685b3307321Smrg        bp[3] = bp[0];
686b3307321Smrg        bp[0] = c;
687b3307321Smrg        c = bp[2];
688b3307321Smrg        bp[2] = bp[1];
689b3307321Smrg        bp[1] = c;
690b3307321Smrg        bp += 4;
691b3307321Smrg    }
692b3307321Smrg}
693