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