|
|
1.1 root 1: #include <X/mit-copyright.h>
2:
3: /* Copyright 1985, 1986, Massachusetts Institute of Technology */
4:
5: /*
6: * xwd.c MIT Project Athena, X Window system window raster image dumper.
7: *
8: * This program will dump a raster image of the contents of a window into a
9: * file for output on graphics printers or for other uses.
10: *
11: * Author: Tony Della Fera, DEC
12: * 17-Jun-85
13: *
14: * Modification history:
15: *
16: * 11/14/86 Bill Wyatt, Smithsonian Astrophysical Observatory
17: * - Removed Z format option, changing it to an XY option. Monochrome
18: * windows will always dump in XY format. Color windows will dump
19: * in Z format by default, but can be dumped in XY format with the
20: * -xy option.
21: *
22: * 11/18/86 Bill Wyatt
23: * - VERSION 6 is same as version 5 for monchrome. For colors, the
24: * appropriate number of Color structs are dumped after the header,
25: * which has the number of colors (=0 for monochrome) in place of the
26: * V5 padding at the end. Up to 16-bit displays are supported. I
27: * don't yet know how 24- to 32-bit displays will be handled under
28: * the Version 11 protocol.
29: */
30:
31: #ifndef lint
32: static char *rcsid_xwd_c = "$Header: xwd.c,v 10.12 86/11/25 09:01:08 jg Rel $";
33: #endif
34:
35: #include <X/Xlib.h>
36: #include <sys/types.h>
37: #include <stdio.h>
38: #include <strings.h>
39:
40: char *calloc();
41:
42: typedef enum _bool {FALSE, TRUE} Bool;
43:
44: #include "../cursors/target.cursor"
45: #include "../cursors/target_mask.cursor"
46:
47: #include "XWDFile.h"
48:
49: #define MAX(a, b) (a) > (b) ? (a) : (b)
50: #define MIN(a, b) (a) < (b) ? (a) : (b)
51: #define ABS(a) (a) < 0 ? -(a) : (a)
52:
53: #define FAILURE 0
54:
55: #define FEEP_VOLUME 0
56:
57: extern int errno;
58:
59: main(argc, argv)
60: int argc;
61: char **argv;
62: {
63: register int i, *histbuffer;
64: register u_short *wbuffer;
65: register char *buffer, *cbuffer;
66:
67: unsigned buffer_size;
68: int virt_x, virt_y;
69: int virt_width, virt_height;
70: int pixmap_format = -1;
71: int win_name_size;
72: int header_size;
73: int ncolors = 0;
74: char *str_index;
75: char *file_name;
76: char display[256];
77: char *win_name;
78: Bool nobdrs = FALSE;
79: Bool debug = FALSE;
80: Bool standard_out = TRUE;
81:
82: Color *pixcolors;
83: Display *dpy;
84: Window target_win;
85: Window image_win;
86: WindowInfo win_info;
87: Cursor cursor;
88: XButtonEvent rep;
89:
90: XWDFileHeader header;
91:
92: FILE *out_file = stdout;
93:
94: for (i = 1; i < argc; i++) {
95: str_index = (char *)index (argv[i], ':');
96: if(str_index != (char *)NULL) {
97: (void) strncpy(display,argv[i],sizeof(display));
98: continue;
99: }
100: str_index = (char *) index (argv [i], '-');
101: if (str_index == (char *)NULL) Syntax(argv[0]);
102: if (strncmp(argv[i], "-nobdrs", 6) == 0) {
103: nobdrs = TRUE;
104: continue;
105: }
106: if (strncmp(argv[i], "-debug", 6) == 0) {
107: debug = TRUE;
108: continue;
109: }
110: if (strncmp(argv[i], "-help", 5) == 0) {
111: Syntax(argv[0]);
112: }
113: if (strncmp(argv[i], "-out", 4) == 0) {
114: if (++i >= argc) Syntax(argv[0]);
115: file_name = argv[i];
116: standard_out = FALSE;
117: continue;
118: }
119: if(strncmp(argv[i], "-xy") == 0) {
120: pixmap_format = XYFormat;
121: continue;
122: }
123: Syntax(argv[0]);
124: }
125:
126: if (!standard_out) {
127: /*
128: * Open the output file.
129: */
130: if((out_file = fopen(file_name, "w")) == NULL)
131: Error("Can't open output file as specified.");
132: }
133:
134: /*
135: * Open the display.
136: */
137: if ((dpy = XOpenDisplay(display)) == NULL) {
138: fprintf(stderr, "%s: Can't open display '%s'\n",
139: argv[0], XDisplayName(display));
140: exit(1);
141: }
142:
143:
144: /*
145: * Store the cursor incase we need it.
146: */
147: if (debug) fprintf(stderr,"xwd: Storing target cursor.\n");
148: if((cursor = XCreateCursor(
149: target_width, target_height,
150: target_bits, target_mask_bits,
151: 8, 8,
152: BlackPixel, WhitePixel,
153: GXcopy
154: )) == FAILURE)
155: Error("Error occured while trying to store target cursor.");
156:
157: /*
158: * Set the right pixmap format for the display type.
159: */
160: if(DisplayPlanes() == 1) pixmap_format = XYFormat;
161: else {
162: if(pixmap_format != XYFormat) pixmap_format = ZFormat;
163: }
164:
165: /*
166: * Let the user select the target window.
167: */
168: if(XGrabMouse(RootWindow, cursor, ButtonPressed) == FAILURE)
169: Error("Can't grab the mouse.");
170: XNextEvent(&rep);
171: XUngrabMouse();
172: target_win = rep.subwindow;
173: if (target_win == 0) {
174: /*
175: * The user must have indicated the root window.
176: */
177: if (debug) fprintf(stderr,"xwd: Root window selected as target.\n");
178: target_win = RootWindow;
179: }
180: else if (debug)
181: fprintf(stderr,
182: "xwd: Window 0x%x slected as target.\n", target_win);
183:
184: /*
185: * Inform the user not to alter the screen.
186: */
187: XFeep(FEEP_VOLUME);
188:
189: /*
190: * Get the parameters of the window being dumped.
191: */
192: if (debug) fprintf(stderr,"xwd: Getting target window information.\n");
193:
194: if(XQueryWindow(target_win, &win_info) == FAILURE)
195: Error("Can't query target window.");
196: if(XFetchName(target_win, &win_name) == FAILURE)
197: Error("Can't fetch target window name.");
198:
199: /* sizeof(char) is included for the null string terminator. */
200: win_name_size = strlen(win_name) + sizeof(char);
201:
202: /*
203: * Calculate the virtual x, y, width and height of the window pane image
204: * (this depends on wether or not the borders are included.
205: */
206: if (nobdrs) {
207: if (debug) fprintf(stderr,"xwd: Image without borders selected.\n");
208: image_win = target_win;
209: virt_x = 0;
210: virt_y = 0;
211: virt_width = win_info.width;
212: virt_height = win_info.height;
213: }
214: else {
215: if (debug) fprintf(stderr,"xwd: Image with borders selected.\n");
216: image_win = RootWindow;
217: virt_x = win_info.x;
218: virt_y = win_info.y;
219: virt_width = win_info.width + (win_info.bdrwidth << 1);
220: virt_height = win_info.height + (win_info.bdrwidth << 1);
221: }
222:
223: /*
224: * Determine the pixmap size.
225: */
226: if (pixmap_format == XYFormat) {
227: buffer_size = XYPixmapSize(virt_width, virt_height, DisplayPlanes());
228: if (debug) {
229: fprintf(stderr,
230: "xwd: Pixmap in XYFormat, size %d bytes.\n", buffer_size);
231: }
232: }
233: else if (DisplayPlanes() < 9) {
234: buffer_size = BZPixmapSize(virt_width, virt_height);
235: if (debug) {
236: fprintf(stderr,
237: "xwd: Pixmap in byte ZFormat, size %d bytes.\n", buffer_size);
238: }
239: }
240: else {
241: buffer_size = WZPixmapSize(virt_width, virt_height);
242: if (debug) {
243: fprintf(stderr,
244: "xwd: Pixmap in word ZFormat, size %d bytes.\n", buffer_size);
245: }
246: }
247:
248:
249: /*
250: * Calloc the buffer.
251: */
252: if (debug) fprintf(stderr,"xwd: Calloc'ing data buffer.\n");
253: if((buffer = calloc(buffer_size , 1)) == NULL)
254: Error("Can't calloc data buffer.");
255:
256: /*
257: * Snarf the pixmap out of the frame buffer.
258: * Color windows get snarfed in Z format first to check the color
259: * map allocations before resnarfing if XY format selected.
260: */
261: if (debug) fprintf(stderr,"xwd: Getting pixmap.\n");
262: if (DisplayPlanes() == 1) {
263: (void) XPixmapGetXY(
264: image_win,
265: virt_x, virt_y,
266: virt_width, virt_height,
267: (short *)buffer
268: );
269: }
270: else {
271: (void) XPixmapGetZ(
272: image_win,
273: virt_x, virt_y,
274: virt_width, virt_height,
275: (caddr_t)buffer
276: );
277: }
278:
279: /*
280: * Find the number of colors used, then write them out to the file.
281: */
282: ncolors = 0;
283: if(DisplayPlanes() > 1) {
284: if(DisplayPlanes() < 9) {
285: histbuffer = (int *)calloc(256, sizeof(int));
286: bzero(histbuffer, 256*sizeof(int));
287: pixcolors = (Color *)calloc(1, sizeof(Color));
288: for(i=0; i<buffer_size; i++) {
289: /* if previously found, skip color query */
290: if(histbuffer[(int)buffer[i]] == 0) {
291: pixcolors =
292: (Color *)realloc(pixcolors, sizeof(Color)*(++ncolors));
293: if(debug)
294: fprintf(stderr,"Color %3d at pixel val %5d, i= %5d =",
295: ncolors, buffer[i], i);
296: histbuffer[(int)buffer[i]]++;
297: pixcolors[ncolors-1].pixel = (int)buffer[i];
298: if(XQueryColor(&pixcolors[ncolors-1]) == 0)
299: Error("Unable to query color table?");
300: if(debug) fprintf(stderr,"%5d %5d %5d\n",
301: pixcolors[ncolors-1].red,
302: pixcolors[ncolors-1].green,
303: pixcolors[ncolors-1].blue);
304: }
305: }
306: }
307: else if(DisplayPlanes() < 17) {
308: wbuffer = (u_short *)buffer;
309: histbuffer = (int *)calloc(65536, sizeof(int));
310: bzero(histbuffer, 65536*sizeof(int));
311: pixcolors = (Color *)calloc(1, sizeof(Color));
312: for(i=0; i<(buffer_size/sizeof(u_short)); i++) {
313: /* if previously found, skip color query */
314: if(histbuffer[(int)wbuffer[i]] == 0) {
315: pixcolors =
316: (Color *)realloc(pixcolors, sizeof(Color)*(++ncolors));
317: if(debug)
318: fprintf(stderr,"Color %2d at pixel val %d, i= %d =",
319: ncolors, wbuffer[i], i);
320: histbuffer[(int)wbuffer[i]]++;
321: pixcolors[ncolors-1].pixel = (int)wbuffer[i];
322: if(XQueryColor(&pixcolors[ncolors-1]) == 0)
323: Error("Unable to query color table?");
324: if(debug) fprintf(stderr,"%d %d %d\n",
325: pixcolors[ncolors-1].red,
326: pixcolors[ncolors-1].green,
327: pixcolors[ncolors-1].blue);
328: }
329: }
330: }
331: else if(DisplayPlanes() > 16)
332: Error("Unable to handle more than 16 planes at this time");
333:
334: /* reread in XY format if necessary */
335: if(pixmap_format == XYFormat) {
336: (void) XPixmapGetXY(image_win,
337: virt_x, virt_y,
338: virt_width, virt_height,
339: (short *)buffer);
340: }
341:
342: free(histbuffer);
343: }
344:
345: /*
346: * Inform the user that the image has been retrieved.
347: */
348: XFeep(FEEP_VOLUME);
349: XFeep(FEEP_VOLUME);
350: XFlush();
351:
352: /*
353: * Calculate header size.
354: */
355: if (debug) fprintf(stderr,"xwd: Calculating header size.\n");
356: header_size = sizeof(header) + win_name_size;
357:
358: /*
359: * Write out header information.
360: */
361: if (debug) fprintf(stderr,"xwd: Constructing and dumping file header.\n");
362: header.header_size = header_size;
363: header.file_version = XWD_FILE_VERSION;
364: header.display_type = DisplayType();
365: header.display_planes = DisplayPlanes();
366: header.pixmap_format = pixmap_format;
367: header.pixmap_width = virt_width;
368: header.pixmap_height = virt_height;
369: header.window_width = win_info.width;
370: header.window_height = win_info.height;
371: header.window_x = win_info.x;
372: header.window_y = win_info.y;
373: header.window_bdrwidth = win_info.bdrwidth;
374: header.window_ncolors = ncolors;
375:
376: (void) fwrite((char *)&header, sizeof(header), 1, out_file);
377: (void) fwrite(win_name, win_name_size, 1, out_file);
378:
379: /*
380: * Write out the color maps, if any
381: */
382: if (debug) fprintf(stderr,"xwd: Dumping %d colors.\n",ncolors);
383: (void) fwrite(pixcolors, sizeof(Color), ncolors, out_file);
384:
385: /*
386: * Write out the buffer.
387: */
388: if (debug) fprintf(stderr,"xwd: Dumping pixmap.\n");
389: (void) fwrite(buffer, (int) buffer_size, 1, out_file);
390:
391: /*
392: * Close the output file.
393: */
394: if (debug) fprintf(stderr,"xwd: Closing output file.\n");
395: (void) fclose(out_file);
396:
397: /*
398: * free the color buffer.
399: */
400: if(debug && ncolors > 0) fprintf(stderr,"xwd: Freeing color map.\n");
401: if(ncolors > 0) free(pixcolors);
402:
403: /*
404: * Free the pixmap buffer.
405: */
406: if (debug) fprintf(stderr,"xwd: Freeing pixmap buffer.\n");
407: free(buffer);
408:
409: /*
410: * Free window name string.
411: */
412: if (debug) fprintf(stderr,"xwd: Freeing window name string.\n");
413: free(win_name);
414: exit(0);
415: }
416:
417: /*
418: * Report the syntax for calling xwd.
419: */
420: Syntax(call)
421: char *call;
422: {
423: fprintf(
424: stderr,
425: "xwd: %s [-debug] [-help] [-nobdrs] [-out <file>]\n",
426: call
427: );
428: fprintf(stderr, " [-xy] [[host]:vs]\n");
429: exit(1);
430: }
431:
432:
433: /*
434: * Error - Fatal xwd error.
435: */
436: Error(string)
437: char *string; /* Error description string. */
438: {
439: fprintf(stderr, "\nxwd: Error => %s", string);
440: if (errno != 0) {
441: perror("xwd");
442: fprintf(stderr, "\n");
443: }
444:
445: exit(1);
446: }
447:
448: /* End of xwd.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.