1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | |
11 | |
12 | |
13 | |
14 | |
15 | |
16 | |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | |
24 | |
25 | |
26 | |
27 | |
28 | |
29 | |
30 | |
31 | |
32 | |
33 | |
34 | |
35 | |
36 | |
37 | |
38 | |
39 | |
40 | |
41 | |
42 | |
43 | |
44 | |
45 | |
46 | |
47 | |
48 | |
49 | |
50 | |
51 | |
52 | |
53 | |
54 | |
55 | |
56 | |
57 | |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | #ifdef HAVE_CONFIG_H1 |
67 | #include "config.h" |
68 | #endif |
69 | |
70 | #include <stdio.h> |
71 | #include <errno(*__error()).h> |
72 | #include <X11/Xos.h> |
73 | #include <stdlib.h> |
74 | |
75 | #include <X11/Xlib.h> |
76 | #include <X11/Xutil.h> |
77 | |
78 | #include "X11/XWDFile.h" |
79 | |
80 | #define FEEP_VOLUME0 0 |
81 | |
82 | |
83 | #include "dsimple.h" |
84 | #include "list.h" |
85 | #include "wsutils.h" |
86 | #include "multiVis.h" |
87 | |
88 | #ifdef XKB1 |
89 | #include <X11/extensions/XKBbells.h> |
90 | #endif |
91 | |
92 | |
93 | |
94 | static int format = ZPixmap2; |
95 | static Boolint nobdrs = False0; |
96 | static Boolint on_root = False0; |
97 | static Boolint standard_out = True1; |
98 | static Boolint debug = False0; |
99 | static Boolint silent = False0; |
100 | static Boolint use_installed = False0; |
101 | static long add_pixel_value = 0; |
102 | |
103 | |
104 | extern int main(int, char **); |
105 | extern void Window_Dump(Window, FILE *); |
106 | extern int Image_Size(XImage *); |
107 | extern int Get_XColors(XWindowAttributes *, XColor **); |
108 | extern void _swapshort(register char *, register unsigned); |
109 | extern void _swaplong(register char *, register unsigned); |
110 | static long parse_long(char *); |
111 | static int Get24bitDirectColors(XColor **); |
112 | static int ReadColors(Visual *, Colormap, XColor **); |
113 | |
114 | |
115 | static long parse_long (char *s) |
116 | { |
117 | long retval = 0L; |
118 | int thesign = 1; |
119 | |
120 | if (s && s[0]) { |
121 | switch(s[0]) { |
122 | case '-': |
123 | (void) sscanf (s + 1, "%lu", &retval); |
124 | thesign = -1; |
125 | break; |
126 | case '0': |
127 | (void) sscanf (s + 1, "%lo", &retval); |
128 | break; |
129 | case 'x': |
130 | case 'X': |
131 | (void) sscanf (s + 1, "%lx", &retval); |
132 | break; |
133 | default: |
134 | (void) sscanf (s, "%lu", &retval); |
135 | break; |
136 | } |
137 | } |
138 | return (thesign * retval); |
139 | } |
140 | |
141 | int |
142 | main(int argc, char **argv) |
143 | { |
144 | register int i; |
145 | Window target_win; |
146 | FILE *out_file = stdout__stdoutp; |
147 | Boolint frame_only = False0; |
148 | |
149 | INIT_NAMEprogram_name=argv[0]; |
150 | |
151 | Setup_Display_And_Screen(&argc, argv); |
152 | |
153 | |
154 | target_win = Select_Window_Args(&argc, argv); |
155 | |
156 | for (i = 1; i < argc; i++) { |
157 | if (!strcmp(argv[i], "-nobdrs")) { |
158 | nobdrs = True1; |
159 | continue; |
160 | } |
161 | if (!strcmp(argv[i], "-debug")) { |
162 | debug = True1; |
163 | continue; |
164 | } |
165 | if (!strcmp(argv[i], "-help")) |
166 | usage(NULL((void*)0)); |
167 | if (!strcmp(argv[i], "-out")) { |
168 | if (++i >= argc) usage("-out requires an argument"); |
169 | if (!(out_file = fopen(argv[i], "wb"))) |
170 | Fatal_Error("Can't open output file as specified."); |
171 | standard_out = False0; |
172 | continue; |
173 | } |
174 | if (!strcmp(argv[i], "-xy")) { |
175 | format = XYPixmap1; |
176 | continue; |
177 | } |
178 | if (!strcmp(argv[i], "-screen")) { |
179 | on_root = True1; |
180 | continue; |
181 | } |
182 | if (!strcmp(argv[i], "-icmap")) { |
183 | use_installed = True1; |
184 | continue; |
185 | } |
186 | if (!strcmp(argv[i], "-add")) { |
187 | if (++i >= argc) usage("-add requires an argument"); |
188 | add_pixel_value = parse_long (argv[i]); |
189 | continue; |
190 | } |
191 | if (!strcmp(argv[i], "-frame")) { |
192 | frame_only = True1; |
193 | continue; |
194 | } |
195 | if (!strcmp(argv[i], "-silent")) { |
196 | silent = True1; |
197 | continue; |
198 | } |
199 | if (!strcmp(argv[i], "-version")) { |
200 | puts(PACKAGE_STRING"xwd 1.0.6"); |
201 | exit(0); |
202 | } |
203 | fprintf (stderr__stderrp, "%s: unrecognized argument '%s'\n", |
204 | program_name, argv[i]); |
205 | usage(NULL((void*)0)); |
206 | } |
207 | #ifdef WIN32 |
208 | if (standard_out) |
209 | _setmode(fileno(out_file), _O_BINARY); |
210 | #endif |
211 | |
212 | |
213 | |
214 | |
215 | if (target_win == None0L) |
216 | target_win = Select_Window(dpy, !frame_only); |
217 | |
218 | |
219 | |
220 | |
221 | Window_Dump(target_win, out_file); |
222 | |
223 | XCloseDisplay(dpy); |
224 | if (fclose(out_file)) { |
225 | perror("xwd"); |
226 | exit(1); |
227 | } |
228 | exit(0); |
229 | } |
230 | |
231 | static int |
232 | Get24bitDirectColors(XColor **colors) |
233 | { |
234 | int i , ncolors = 256 ; |
235 | XColor *tcol ; |
236 | |
237 | *colors = tcol = (XColor *)malloc(sizeof(XColor) * ncolors) ; |
238 | |
239 | for(i=0 ; i < ncolors ; i++) |
240 | { |
241 | tcol[i].pixel = i << 16 | i << 8 | i ; |
242 | tcol[i].red = tcol[i].green = tcol[i].blue = i << 8 | i ; |
243 | } |
244 | |
245 | return ncolors ; |
246 | } |
247 | |
248 | |
249 | |
250 | |
251 | |
252 | |
253 | |
254 | void |
255 | Window_Dump(Window window, FILE *out) |
256 | { |
257 | unsigned long swaptest = 1; |
258 | XColor *colors; |
259 | unsigned buffer_size; |
260 | size_t win_name_size; |
261 | CARD32 header_size; |
262 | int ncolors, i; |
263 | char *win_name; |
264 | char default_win_name[] = "xwdump"; |
265 | Boolint got_win_name; |
266 | XWindowAttributes win_info; |
267 | XImage *image; |
268 | int absx, absy, x, y; |
269 | unsigned width, height; |
270 | int dwidth, dheight; |
271 | Window dummywin; |
272 | XWDFileHeader header; |
273 | XWDColor xwdcolor; |
274 | |
275 | int transparentOverlays , multiVis; |
276 | int numVisuals; |
277 | XVisualInfo *pVisuals; |
278 | int numOverlayVisuals; |
279 | OverlayInfo *pOverlayVisuals; |
280 | int numImageVisuals; |
281 | XVisualInfo **pImageVisuals; |
282 | list_ptr vis_regions; |
283 | list_ptr vis_image_regions ; |
284 | Visual vis_h,*vis ; |
285 | int allImage = 0 ; |
286 | |
287 | |
288 | |
289 | |
290 | if (!silent) { |
| 1 | Assuming 'silent' is not equal to 0 | |
|
| |
291 | #ifdef XKB1 |
292 | XkbStdBell(dpy,None0L,50,XkbBI_Wait11); |
293 | #else |
294 | XBell(dpy,FEEP_VOLUME0); |
295 | #endif |
296 | XFlush(dpy); |
297 | } |
298 | |
299 | |
300 | |
301 | |
302 | if (debug) outl("xwd: Getting target window information.\n"); |
| |
| |
303 | if(!XGetWindowAttributes(dpy, window, &win_info)) |
| |
304 | Fatal_Error("Can't get target window attributes."); |
305 | |
306 | |
307 | if (!XTranslateCoordinates (dpy, window, RootWindow (dpy, screen)((&((_XPrivDisplay)(dpy))->screens[screen])->root), 0, 0, |
| |
308 | &absx, &absy, &dummywin)) { |
309 | fprintf (stderr__stderrp, |
310 | "%s: unable to translate window coordinates (%d,%d)\n", |
311 | program_name, absx, absy); |
312 | exit (1); |
313 | } |
314 | win_info.x = absx; |
315 | win_info.y = absy; |
316 | width = win_info.width; |
317 | height = win_info.height; |
318 | |
319 | if (!nobdrs) { |
| 7 | | Assuming 'nobdrs' is not equal to 0 | |
|
| |
320 | absx -= win_info.border_width; |
321 | absy -= win_info.border_width; |
322 | width += (2 * win_info.border_width); |
323 | height += (2 * win_info.border_width); |
324 | } |
325 | dwidth = DisplayWidth (dpy, screen)((&((_XPrivDisplay)(dpy))->screens[screen])->width); |
326 | dheight = DisplayHeight (dpy, screen)((&((_XPrivDisplay)(dpy))->screens[screen])->height ); |
327 | |
328 | |
329 | |
330 | if (absx < 0) width += absx, absx = 0; |
| |
| |
331 | if (absy < 0) height += absy, absy = 0; |
| 11 | | Assuming 'absy' is >= 0 | |
|
| |
332 | if (absx + width > dwidth) width = dwidth - absx; |
| |
333 | if (absy + height > dheight) height = dheight - absy; |
| |
334 | |
335 | XFetchName(dpy, window, &win_name); |
336 | if (!win_name || !win_name[0]) { |
| 15 | | Assuming 'win_name' is non-null | |
|
| |
337 | win_name = default_win_name; |
338 | got_win_name = False0; |
339 | } else { |
340 | got_win_name = True1; |
341 | } |
342 | |
343 | |
344 | win_name_size = strlen(win_name) + sizeof(char); |
345 | |
346 | |
347 | |
348 | |
349 | |
350 | x = absx - win_info.x; |
351 | y = absy - win_info.y; |
352 | |
353 | multiVis = GetMultiVisualRegions(dpy,RootWindow(dpy, screen)((&((_XPrivDisplay)(dpy))->screens[screen])->root), |
354 | absx, absy, |
355 | width, height,&transparentOverlays,&numVisuals, &pVisuals, |
356 | &numOverlayVisuals,&pOverlayVisuals,&numImageVisuals, |
357 | &pImageVisuals,&vis_regions,&vis_image_regions,&allImage) ; |
358 | if (on_root || multiVis) |
| |
359 | { |
360 | if(!multiVis) |
361 | image = XGetImage (dpy, RootWindow(dpy, screen)((&((_XPrivDisplay)(dpy))->screens[screen])->root), absx, absy, |
362 | width, height, AllPlanes((unsigned long)~0L), format); |
363 | else |
364 | image = ReadAreaToImage(dpy, RootWindow(dpy, screen)((&((_XPrivDisplay)(dpy))->screens[screen])->root), absx, absy, |
365 | width, height, |
366 | numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals, |
367 | numImageVisuals, pImageVisuals,vis_regions, |
368 | vis_image_regions,format,allImage); |
369 | } |
370 | else |
371 | image = XGetImage (dpy, window, x, y, width, height, AllPlanes((unsigned long)~0L), format); |
372 | if (!image) { |
| 18 | | Assuming 'image' is non-null | |
|
| |
373 | fprintf (stderr__stderrp, "%s: unable to get image at %dx%d+%d+%d\n", |
374 | program_name, width, height, x, y); |
375 | exit (1); |
376 | } |
377 | |
378 | if (add_pixel_value != 0) XAddPixel (image, add_pixel_value)((*((image)->f.add_pixel))((image), (add_pixel_value))); |
| 20 | | Assuming 'add_pixel_value' is equal to 0 | |
|
| |
379 | |
380 | |
381 | |
382 | |
383 | buffer_size = Image_Size(image); |
384 | |
385 | if (debug) outl("xwd: Getting Colors.\n"); |
| |
| |
386 | |
387 | if( !multiVis) |
| |
388 | { |
389 | ncolors = Get_XColors(&win_info, &colors); |
390 | vis = win_info.visual ; |
391 | } |
392 | else |
393 | { |
394 | ncolors = Get24bitDirectColors(&colors) ; |
395 | initFakeVisual(&vis_h) ; |
396 | vis = &vis_h ; |
397 | } |
398 | |
399 | |
400 | |
401 | if (!silent) { |
| 25 | | Assuming 'silent' is not equal to 0 | |
|
| |
402 | #ifdef XKB1 |
403 | XkbStdBell(dpy,window,FEEP_VOLUME0,XkbBI_Proceed12); |
404 | XkbStdBell(dpy,window,FEEP_VOLUME0,XkbBI_RepeatingLastBell28); |
405 | #else |
406 | XBell(dpy, FEEP_VOLUME0); |
407 | XBell(dpy, FEEP_VOLUME0); |
408 | #endif |
409 | XFlush(dpy); |
410 | } |
411 | |
412 | |
413 | |
414 | |
415 | if (debug) outl("xwd: Calculating header size.\n"); |
| |
416 | header_size = SIZEOF(XWDheader)100 + (CARD32) win_name_size; |
417 | |
418 | |
419 | |
420 | |
421 | if (debug) outl("xwd: Constructing and dumping file header.\n"); |
| |
422 | header.header_size = (CARD32) header_size; |
423 | header.file_version = (CARD32) XWD_FILE_VERSION7; |
424 | header.pixmap_format = (CARD32) format; |
425 | header.pixmap_depth = (CARD32) image->depth; |
426 | header.pixmap_width = (CARD32) image->width; |
427 | header.pixmap_height = (CARD32) image->height; |
428 | header.xoffset = (CARD32) image->xoffset; |
429 | header.byte_order = (CARD32) image->byte_order; |
430 | header.bitmap_unit = (CARD32) image->bitmap_unit; |
431 | header.bitmap_bit_order = (CARD32) image->bitmap_bit_order; |
432 | header.bitmap_pad = (CARD32) image->bitmap_pad; |
433 | header.bits_per_pixel = (CARD32) image->bits_per_pixel; |
434 | header.bytes_per_line = (CARD32) image->bytes_per_line; |
435 | |
436 | |
437 | |
438 | |
439 | |
440 | |
441 | |
442 | |
443 | header.visual_class = (CARD32) vis->class; |
444 | header.red_mask = (CARD32) vis->red_mask; |
445 | header.green_mask = (CARD32) vis->green_mask; |
446 | header.blue_mask = (CARD32) vis->blue_mask; |
447 | header.bits_per_rgb = (CARD32) vis->bits_per_rgb; |
448 | header.colormap_entries = (CARD32) vis->map_entries; |
449 | |
450 | header.ncolors = ncolors; |
451 | header.window_width = (CARD32) win_info.width; |
452 | header.window_height = (CARD32) win_info.height; |
453 | header.window_x = absx; |
454 | header.window_y = absy; |
455 | header.window_bdrwidth = (CARD32) win_info.border_width; |
456 | |
457 | if (*(char *) &swaptest) { |
| |
458 | _swaplong((char *) &header, sizeof(header)); |
| |
459 | for (i = 0; i < ncolors; i++) { |
460 | _swaplong((char *) &colors[i].pixel, sizeof(CARD32)); |
461 | _swapshort((char *) &colors[i].red, 3 * sizeof(short)); |
462 | } |
463 | } |
464 | |
465 | if (fwrite((char *)&header, SIZEOF(XWDheader)100, 1, out) != 1 || |
466 | fwrite(win_name, win_name_size, 1, out) != 1) { |
467 | perror("xwd"); |
468 | exit(1); |
469 | } |
470 | |
471 | |
472 | |
473 | |
474 | |
475 | if (debug) outl("xwd: Dumping %d colors.\n", ncolors); |
476 | for (i = 0; i < ncolors; i++) { |
477 | xwdcolor.pixel = colors[i].pixel; |
478 | xwdcolor.red = colors[i].red; |
479 | xwdcolor.green = colors[i].green; |
480 | xwdcolor.blue = colors[i].blue; |
481 | xwdcolor.flags = colors[i].flags; |
482 | if (fwrite((char *) &xwdcolor, SIZEOF(XWDColor)12, 1, out) != 1) { |
483 | perror("xwd"); |
484 | exit(1); |
485 | } |
486 | } |
487 | |
488 | |
489 | |
490 | |
491 | if (debug) outl("xwd: Dumping pixmap. bufsize=%d\n",buffer_size); |
492 | |
493 | |
494 | |
495 | |
496 | |
497 | |
498 | |
499 | if (fwrite(image->data, (int) buffer_size, 1, out) != 1) { |
500 | perror("xwd"); |
501 | exit(1); |
502 | } |
503 | |
504 | |
505 | |
506 | |
507 | |
508 | if(debug && ncolors > 0) outl("xwd: Freeing colors.\n"); |
509 | if(ncolors > 0) free(colors); |
510 | |
511 | |
512 | |
513 | |
514 | if (debug) outl("xwd: Freeing window name string.\n"); |
515 | if (got_win_name) XFree(win_name); |
516 | |
517 | |
518 | |
519 | |
520 | XDestroyImage(image)((*((image)->f.destroy_image))((image))); |
521 | } |
522 | |
523 | |
524 | |
525 | |
526 | void |
527 | usage(const char *errmsg) |
528 | { |
529 | if (errmsg != NULL((void*)0)) |
530 | fprintf (stderr__stderrp, "%s: %s\n", program_name, errmsg); |
531 | |
532 | fprintf (stderr__stderrp, |
533 | "usage: %s [-display host:dpy] [-debug] [-help] %s [-nobdrs] [-out <file>]", |
534 | program_name, "[{-root|-id <id>|-name <name>}]"); |
535 | fprintf (stderr__stderrp, " [-xy] [-add value] [-frame] [-version]\n"); |
536 | exit(1); |
537 | } |
538 | |
539 | |
540 | |
541 | |
542 | |
543 | |
544 | int Image_Size(XImage *image) |
545 | { |
546 | if (image->format != ZPixmap2) |
547 | return(image->bytes_per_line * image->height * image->depth); |
548 | |
549 | return(image->bytes_per_line * image->height); |
550 | } |
551 | |
552 | #define lowbit(x)((x) & (~(x) + 1)) ((x) & (~(x) + 1)) |
553 | |
554 | static int |
555 | ReadColors(Visual *vis, Colormap cmap, XColor **colors) |
556 | { |
557 | int i,ncolors ; |
558 | |
559 | ncolors = vis->map_entries; |
560 | |
561 | if (!(*colors = (XColor *) malloc (sizeof(XColor) * ncolors))) |
562 | Fatal_Error("Out of memory!"); |
563 | |
564 | if (vis->class == DirectColor5 || |
565 | vis->class == TrueColor4) { |
566 | Pixel red, green, blue, red1, green1, blue1; |
567 | |
568 | red = green = blue = 0; |
569 | red1 = lowbit(vis->red_mask)((vis->red_mask) & (~(vis->red_mask) + 1)); |
570 | green1 = lowbit(vis->green_mask)((vis->green_mask) & (~(vis->green_mask) + 1)); |
571 | blue1 = lowbit(vis->blue_mask)((vis->blue_mask) & (~(vis->blue_mask) + 1)); |
572 | for (i=0; i<ncolors; i++) { |
573 | (*colors)[i].pixel = red|green|blue; |
574 | (*colors)[i].pad = 0; |
575 | red += red1; |
576 | if (red > vis->red_mask) |
577 | red = 0; |
578 | green += green1; |
579 | if (green > vis->green_mask) |
580 | green = 0; |
581 | blue += blue1; |
582 | if (blue > vis->blue_mask) |
583 | blue = 0; |
584 | } |
585 | } else { |
586 | for (i=0; i<ncolors; i++) { |
587 | (*colors)[i].pixel = i; |
588 | (*colors)[i].pad = 0; |
589 | } |
590 | } |
591 | |
592 | XQueryColors(dpy, cmap, *colors, ncolors); |
593 | |
594 | return(ncolors); |
595 | } |
596 | |
597 | |
598 | |
599 | |
600 | int Get_XColors(XWindowAttributes *win_info, XColor **colors) |
601 | { |
602 | int i, ncolors; |
603 | Colormap cmap = win_info->colormap; |
604 | |
605 | if (use_installed) |
606 | |
607 | cmap = XListInstalledColormaps(dpy, win_info->root, &i)[0]; |
608 | if (!cmap) |
609 | return(0); |
610 | ncolors = ReadColors(win_info->visual,cmap,colors) ; |
611 | return ncolors ; |
612 | } |
613 | |
614 | void |
615 | _swapshort (register char *bp, register unsigned n) |
616 | { |
617 | register char c; |
618 | register char *ep = bp + n; |
619 | |
620 | while (bp < ep) { |
621 | c = *bp; |
622 | *bp = *(bp + 1); |
623 | bp++; |
624 | *bp++ = c; |
625 | } |
626 | } |
627 | |
628 | void |
629 | _swaplong (register char *bp, register unsigned n) |
630 | { |
631 | register char c; |
632 | register char *ep = bp + n; |
633 | |
634 | while (bp < ep) { |
| 31 | | Loop condition is true. Entering loop body | |
|
635 | c = bp[3]; |
| 32 | | Assigned value is garbage or undefined |
|
636 | bp[3] = bp[0]; |
637 | bp[0] = c; |
638 | c = bp[2]; |
639 | bp[2] = bp[1]; |
640 | bp[1] = c; |
641 | bp += 4; |
642 | } |
643 | } |