home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1930 / XtoPS.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  47.3 KB  |  1,597 lines

  1. /*
  2. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  3. %                                                                             %
  4. %                                                                             %
  5. %                     X   X  TTTTT   OOO   PPPP   SSSSS                       %
  6. %                      X X     T    O   O  P   P  S                           %
  7. %                       X      T    O   O  PPPP    SSS                        %
  8. %                      X X     T    O   O  P          S                       %
  9. %                     X   X    T     OOO   P      SSSSS                       %
  10. %                                                                             %
  11. %                                                                             %
  12. %                  Import X11 image to a Postscript format.                   %
  13. %                                                                             %
  14. %                                                                             %
  15. %                           Software Design                                   %
  16. %                             John Cristy                                     %
  17. %                            October  1990                                    %
  18. %                                                                             %
  19. %                                                                             %
  20. %  Copyright 1990 E. I. Dupont de Nemours & Company                           %
  21. %                                                                             %
  22. %  Permission to use, copy, modify, distribute, and sell this software and    %
  23. %  its documentation for any purpose is hereby granted without fee,           %
  24. %  provided that the above Copyright notice appear in all copies and that     %
  25. %  both that Copyright notice and this permission notice appear in            %
  26. %  supporting documentation, and that the name of E. I. Dupont de Nemours     %
  27. %  & Company not be used in advertising or publicity pertaining to            %
  28. %  distribution of the software without specific, written prior               %
  29. %  permission.  E. I. Dupont de Nemours & Company makes no representations    %
  30. %  about the suitability of this software for any purpose.  It is provided    %
  31. %  "as is" without express or implied warranty.                               %
  32. %                                                                             %
  33. %  E. I. Dupont de Nemours & Company disclaims all warranties with regard     %
  34. %  to this software, including all implied warranties of merchantability      %
  35. %  and fitness, in no event shall E. I. Dupont de Nemours & Company be        %
  36. %  liable for any special, indirect or consequential damages or any           %
  37. %  damages whatsoever resulting from loss of use, data or profits, whether    %
  38. %  in an action of contract, negligence or other tortious action, arising     %
  39. %  out of or in connection with the use or performance of this software.      %
  40. %                                                                             %
  41. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  42. %
  43. %  The XtoPS program reads an image from any visible window on an X server 
  44. %  and outputs it to encapsulated Postscript file.  You can view this file 
  45. %  with any Postscript compatible viewer or printer.  The image is displayed in
  46. %  color on viewers or printers that support color Postscript, otherwise it is 
  47. %  displayed as grayscale.
  48. %
  49. %  The XtoPS program command syntax is:
  50. %
  51. %  Usage: XtoPS [options ...] file
  52. %
  53. %  Where options include:
  54. %    -border        include image borders in the output image
  55. %    -display name  X server to contact
  56. %    -frame         include window manager frame
  57. %    -id number     select window with this id
  58. %    -name name     select window with this name
  59. %    -root          select root window
  60. %
  61. %  Change '-' to '+' in any option above to reverse its effect.
  62. %  For example, +frame means do not include window manager frame.
  63. %
  64. %  Specify 'file' as '-' for standard input or output.
  65. %
  66. %
  67. */
  68.  
  69. #include <X11/Xos.h>
  70. #include <X11/Xlib.h>
  71. #include <X11/Xutil.h>
  72. #include <X11/Xatom.h>
  73. #include <X11/cursorfont.h>
  74. #include "display.h"
  75. #ifdef PRE_R4_ICCCM
  76. #include "PreR4Icccm.h"
  77. #endif
  78.  
  79. /*
  80. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  81. %                                                                             %
  82. %                                                                             %
  83. %                                                                             %
  84. %   C l i e n t W i n d o w                                                   %
  85. %                                                                             %
  86. %                                                                             %
  87. %                                                                             %
  88. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  89. %
  90. %  Function ClientWindow finds a window, at or below the specified window,  
  91. %  which has a WM_STATE property.  If such a window is found, it is returned,  
  92. %  otherwise the argument window is returned.
  93. %
  94. %  The format of the ClientWindow function is:
  95. %
  96. %      client_window=ClientWindow(display,target_window)
  97. %
  98. %  A description of each parameter follows:
  99. %
  100. %    o client_window:  ClientWindow returns a window, at or below the specified 
  101. %      window, which has a WM_STATE property otherwise the argument 
  102. %      target_window is returned.
  103. %
  104. %    o display:  Specifies a pointer to the Display structure;  returned from
  105. %      XOpenDisplay.
  106. %
  107. %    o target_window:  Specifies the window to find a WM_STATE property.
  108. %
  109. %
  110. */
  111. static Window ClientWindow(display,target_window)
  112. Display 
  113.   *display;
  114.  
  115. Window 
  116.   target_window;
  117. {
  118.   Atom 
  119.     state,
  120.     type;
  121.  
  122.   int 
  123.     format;
  124.  
  125.   static Window 
  126.     WindowByProperty();
  127.  
  128.   unsigned char 
  129.     *data;
  130.  
  131.   unsigned long 
  132.     after,
  133.     number_items;
  134.  
  135.   Window 
  136.     client_window;
  137.  
  138.   state=XInternAtom(display,"WM_STATE",True);
  139.   if (state == (Atom) NULL)
  140.     return(target_window);
  141.   type=(Atom) NULL;
  142.   (void) XGetWindowProperty(display,target_window,state,0L,0L,False,
  143.     AnyPropertyType,&type,&format,&number_items,&after,&data);
  144.   if (type != (Atom) NULL)
  145.     return(target_window);
  146.   client_window=WindowByProperty(display,target_window,state);
  147.   if (client_window == (Window) NULL)
  148.     return(target_window);
  149.   return(client_window);
  150. }
  151.  
  152. /*
  153. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  154. %                                                                             %
  155. %                                                                             %
  156. %                                                                             %
  157. %   E r r o r                                                                 %
  158. %                                                                             %
  159. %                                                                             %
  160. %                                                                             %
  161. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  162. %
  163. %  Function Error displays an error message and then terminates the program.
  164. %
  165. %  The format of the Error routine is:
  166. %
  167. %      Error(message,qualifier)
  168. %
  169. %  A description of each parameter follows:
  170. %
  171. %    o message:  Specifies the message to display before terminating the
  172. %      program.
  173. %
  174. %    o qualifier:  Specifies any qualifier to the message.
  175. %
  176. %
  177. */
  178. void Error(message,qualifier)
  179. char
  180.   *message,
  181.   *qualifier;
  182. {
  183.   (void) fprintf(stderr,"%s: %s",application_name,message); 
  184.   if (qualifier != (char *) NULL)
  185.     (void) fprintf(stderr," %s",qualifier);
  186.   (void) fprintf(stderr,".\n");
  187.   exit(1);
  188. }
  189.  
  190. /*
  191. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  192. %                                                                             %
  193. %                                                                             %
  194. %                                                                             %
  195. %   I s T r u e                                                               %
  196. %                                                                             %
  197. %                                                                             %
  198. %                                                                             %
  199. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  200. %
  201. %  Function IsTrue returns True if the boolean is "true", "on", "yes" or "1".
  202. %
  203. %  The format of the IsTrue routine is:
  204. %
  205. %      option=IsTrue(boolean)
  206. %
  207. %  A description of each parameter follows:
  208. %
  209. %    o option:  either True or False depending on the boolean parameter.
  210. %
  211. %    o boolean:  Specifies a pointer to a character array.
  212. %
  213. %
  214. */
  215. static int IsTrue(boolean)
  216. char
  217.   *boolean;
  218. {
  219.   char
  220.     c,
  221.     *p;
  222.  
  223.   if (boolean == (char *) NULL)
  224.     return(False);
  225.   for (p=boolean; *p != (char) NULL; p++)
  226.   {
  227.     /*
  228.       Convert to lower case.
  229.     */
  230.     c=(*p);
  231.     if (isascii(c) && isupper(c))
  232.       *p=tolower(c);
  233.   }
  234.   if (strcmp(boolean,"true") == 0)
  235.     return(True);
  236.   if (strcmp(boolean,"on") == 0)
  237.     return(True);
  238.   if (strcmp(boolean,"yes") == 0)
  239.     return(True);
  240.   if (strcmp(boolean,"1") == 0)
  241.     return(True);
  242.   return(False);
  243. }
  244.  
  245. /*
  246. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  247. %                                                                             %
  248. %                                                                             %
  249. %                                                                             %
  250. %   P r i n t I m a g e                                                       %
  251. %                                                                             %
  252. %                                                                             %
  253. %                                                                             %
  254. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  255. %
  256. %  Function PrintImage translates a MIFF image to encapsulated Postscript for
  257. %  printing.
  258. %
  259. %  The format of the PrintImage routine is:
  260. %
  261. %      status=PrintImage(image)
  262. %
  263. %  A description of each parameter follows:
  264. %
  265. %    o status:  Function PrintImage return True if the image is printed.
  266. %      False is returned if the image file cannot be opened for printing.
  267. %
  268. %    o image:  The address of a structure of type Image;  returned from
  269. %      ReadImage.
  270. %
  271. %
  272. */
  273. unsigned int PrintImage(image)
  274. Image
  275.   *image;
  276. {
  277. #define PointsPerInch 72.0
  278. #define PageBottomMargin 1.27
  279. #define PageLeftMargin 0.21
  280. #define PageWidth  8.5
  281. #define PageHeight 11.0
  282.  
  283.   static char
  284.     *commands[]=
  285.     {
  286.       "%",
  287.       "% Display a runlength-encoded color image.  The image is displayed",
  288.       "% in color on viewers and printers that support color Postscript,",
  289.       "% otherwise it is displayed as grayscale.",
  290.       "%",
  291.       "/buffer 512 string def",
  292.       "/byte 1 string def",
  293.       "/color_packet 3 string def",
  294.       "/gray_packet 1 string def",
  295.       "/pixels 768 string def",
  296.       "",
  297.       "/DirectClassPacket",
  298.       "{",
  299.       "  %",
  300.       "  % Get a runlength-encoded DirectClass packet.",
  301.       "  %",
  302.       "  % Parameters:",
  303.       "  %   length:  number of pixels minus one of this color.",
  304.       "  %   red.",
  305.       "  %   green.",
  306.       "  %   blue.",
  307.       "  %",
  308.       "  currentfile byte readhexstring pop 0 get",
  309.       "  /number_pixels exch 1 add 3 mul def",
  310.       "  currentfile color_packet readhexstring pop pop",
  311.       "  0 3 number_pixels 1 sub",
  312.       "  {",
  313.       "    pixels exch color_packet putinterval",
  314.       "  } for",
  315.       "  pixels 0 number_pixels getinterval",
  316.       "} bind def",
  317.       "",
  318.       "/DirectClassImage",
  319.       "{",
  320.       "  %",
  321.       "  % Display a runlength-encoded DirectClass image.",
  322.       "  %",
  323.       "  systemdict /colorimage known",
  324.       "  {",
  325.       "    columns rows 8",
  326.       "    [",
  327.       "      columns 0 0",
  328.       "      rows neg 0 rows",
  329.       "    ]",
  330.       "    { DirectClassPacket } false 3 colorimage",
  331.       "  }",
  332.       "  {",
  333.       "    %",
  334.       "    % No colorimage operator;  convert to grayscale.",
  335.       "    %",
  336.       "    columns rows 8",
  337.       "    [",
  338.       "      columns 0 0",
  339.       "      rows neg 0 rows",
  340.       "    ]",
  341.       "    { GrayDirectClassPacket } image",
  342.       "  } ifelse",
  343.       "} bind def",
  344.       "",
  345.       "/GrayDirectClassPacket",
  346.       "{",
  347.       "  %",
  348.       "  % Get a runlength-encoded DirectClass packet;  convert to grayscale.",
  349.       "  %",
  350.       "  % Parameters:",
  351.       "  %   length:  number of pixels minus one of this color",
  352.       "  %   red",
  353.       "  %   green",
  354.       "  %   blue",
  355.       "  %",
  356.       "  currentfile byte readhexstring pop 0 get",
  357.       "  /number_pixels exch 1 add def",
  358.       "  currentfile color_packet readhexstring pop pop",
  359.       "  color_packet 0 get 0.299 mul",
  360.       "  color_packet 1 get 0.587 mul add",
  361.       "  color_packet 2 get 0.114 mul add",
  362.       "  cvi",
  363.       "  /gray_packet exch def",
  364.       "  0 1 number_pixels 1 sub",
  365.       "  {",
  366.       "    pixels exch gray_packet put",
  367.       "  } for",
  368.       "  pixels 0 number_pixels getinterval",
  369.       "} bind def",
  370.       "",
  371.       "/GrayPseudoClassPacket",
  372.       "{",
  373.       "  %",
  374.       "  % Get a runlength-encoded PseudoClass packet;  convert to grayscale.",
  375.       "  %",
  376.       "  % Parameters:",
  377.       "  %",
  378.       "  %   length:  number of pixels minus one of this color.",
  379.       "  %   index:  index into the colormap.",
  380.       "  %",
  381.       "  currentfile byte readhexstring pop 0 get",
  382.       "  /number_pixels exch 1 add def",
  383.       "  currentfile byte readhexstring pop 0 get",
  384.       "  /offset exch 3 mul def",
  385.       "  /color_packet colormap offset 3 getinterval def",
  386.       "  color_packet 0 get 0.299 mul",
  387.       "  color_packet 1 get 0.587 mul add",
  388.       "  color_packet 2 get 0.114 mul add",
  389.       "  cvi",
  390.       "  /gray_packet exch def",
  391.       "  0 1 number_pixels 1 sub",
  392.       "  {",
  393.       "    pixels exch gray_packet put",
  394.       "  } for",
  395.       "  pixels 0 number_pixels getinterval",
  396.       "} bind def",
  397.       "",
  398.       "/PseudoClassPacket",
  399.       "{",
  400.       "  %",
  401.       "  % Get a runlength-encoded PseudoClass packet.",
  402.       "  %",
  403.       "  % Parameters:",
  404.       "  %   length:  number of pixels minus one of this color.",
  405.       "  %   index:  index into the colormap.",
  406.       "  %",
  407.       "  %",
  408.       "  currentfile byte readhexstring pop 0 get",
  409.       "  /number_pixels exch 1 add 3 mul def",
  410.       "  currentfile byte readhexstring pop 0 get",
  411.       "  /offset exch 3 mul def",
  412.       "  /color_packet colormap offset 3 getinterval def",
  413.       "  0 3 number_pixels 1 sub",
  414.       "  {",
  415.       "    pixels exch color_packet putinterval",
  416.       "  } for",
  417.       "  pixels 0 number_pixels getinterval",
  418.       "} bind def",
  419.       "",
  420.       "/PseudoClassImage",
  421.       "{",
  422.       "  %",
  423.       "  % Display a runlength-encoded PseudoClass image.",
  424.       "  %",
  425.       "  % Parameters:",
  426.       "  %",
  427.       "  %   colors:  number of colors in the colormap.",
  428.       "  %   colormap:  red, green, blue color packets.",
  429.       "  %",
  430.       "  currentfile buffer readline pop",
  431.       "  token { /colors exch def } { } ifelse",
  432.       "  /colors colors 3 mul def",
  433.       "  /colormap colors string def",
  434.       "  currentfile colormap readhexstring pop pop",
  435.       "  systemdict /colorimage known",
  436.       "  {",
  437.       "    columns rows 8",
  438.       "    [",
  439.       "      columns 0 0",
  440.       "      rows neg 0 rows",
  441.       "    ]",
  442.       "    { PseudoClassPacket } false 3 colorimage",
  443.       "  }",
  444.       "  {",
  445.       "    %",
  446.       "    % No colorimage operator;  convert to grayscale.",
  447.       "    %",
  448.       "    columns rows 8",
  449.       "    [",
  450.       "      columns 0 0",
  451.       "      rows neg 0 rows",
  452.       "    ]",
  453.       "    { GrayPseudoClassPacket } image",
  454.       "  } ifelse",
  455.       "} bind def",
  456.       "",
  457.       "/DisplayImage",
  458.       "{",
  459.       "  %",
  460.       "  % Display a runlength-encoded DirectClass or PseudoClass image.",
  461.       "  %",
  462.       "  % Parameters:",
  463.       "  %   degrees rotation.",
  464.       "  %   x & y translation.",
  465.       "  %   x & y scale.",
  466.       "  %   image columns & rows.",
  467.       "  %   class: DirectClass or PseudoClass.",
  468.       "  %   hex color runlength-encoded packets.",
  469.       "  %",
  470.       "  gsave",
  471.       "  currentfile buffer readline pop",
  472.       "  token { /degrees exch def } { } ifelse",
  473.       "  degrees rotate",
  474.       "  currentfile buffer readline pop",
  475.       "  token { /x exch def } { } ifelse",
  476.       "  token { /y exch def } { } ifelse",
  477.       "  x y translate",
  478.       "  currentfile buffer readline pop",
  479.       "  token { /x exch def } { } ifelse",
  480.       "  token { /y exch def } { } ifelse",
  481.       "  x y scale",
  482.       "  currentfile buffer readline pop",
  483.       "  token { /columns exch def } { } ifelse",
  484.       "  token { /rows exch def } { } ifelse",
  485.       "  currentfile buffer readline pop",
  486.       "  token { /class exch def } { } ifelse",
  487.       "  class 0 gt { PseudoClassImage } { DirectClassImage } ifelse",
  488.       "  grestore",
  489.       "  showpage",
  490.       "} bind def",
  491.       "",
  492.       "DisplayImage",
  493.       NULL
  494.     };
  495.  
  496.   char
  497.     **q;
  498.  
  499.   double
  500.     delta_x,
  501.     delta_y,
  502.     image_height,
  503.     image_width,
  504.     max,
  505.     min,
  506.     rotate,
  507.     scale,
  508.     scale_x,
  509.     scale_y,
  510.     translate_x,
  511.     translate_y;
  512.  
  513.   register RunlengthPacket
  514.     *p;
  515.  
  516.   register int
  517.     i,
  518.     j;
  519.  
  520.   /*
  521.     Open output image file.
  522.   */
  523.   if (*image->filename == '-')
  524.     image->file=stdout;
  525.   else
  526.     image->file=fopen(image->filename,"w");
  527.   if (image->file == (FILE *) NULL)
  528.     {
  529.       (void) fprintf(stderr,"%s: unable to print image, cannot open %s.\n",
  530.         application_name,image->filename);
  531.       return(False);
  532.     }
  533.   /*
  534.     Compute image rotation.
  535.   */
  536.   if (((double) image->columns/(double) image->rows) > 1.0)
  537.     rotate=(-90.0);
  538.   else
  539.     rotate=0.0;
  540.   /*
  541.     Compute image scaling.
  542.   */
  543.   image_width=(double) image->columns/PointsPerInch;
  544.   image_height=(double) image->rows/PointsPerInch;
  545.   /*
  546.     Check max page sizes
  547.   */
  548.   max=image_width > image_height ? image_width : image_height;
  549.   if (max > (PageHeight-(2.0*PageBottomMargin)))
  550.     {
  551.       scale=(PageHeight-(2.0*PageBottomMargin))/max;
  552.       image_height*=scale;
  553.       image_width*=scale;
  554.     }
  555.   min=image_width > image_height ? image_height : image_width;
  556.   if (min > (PageWidth-(2.0*PageLeftMargin)))
  557.     {
  558.       scale=(PageWidth-(2.0*PageLeftMargin))/min;
  559.       image_width*=scale;
  560.       image_height*=scale;
  561.     }
  562.   scale_x=image_width*PointsPerInch;
  563.   scale_y=image_height*PointsPerInch;
  564.   translate_x=0.0;
  565.   translate_y=0.0;
  566.   if (rotate == 0.0)
  567.     {
  568.       delta_x=PageWidth-(image_width+(2.0*PageLeftMargin));
  569.       delta_y=PageHeight-(image_height+(2.0*PageBottomMargin));
  570.       if (delta_x >= 0.0)
  571.         translate_x=((delta_x/2.0+PageLeftMargin)*PointsPerInch);
  572.       else
  573.         translate_x=PageLeftMargin*PointsPerInch;
  574.       if (delta_y >= 0.0)
  575.         translate_y=((delta_y/2.0+PageBottomMargin)*PointsPerInch);
  576.       else
  577.         translate_y=PageBottomMargin*PointsPerInch;
  578.     }
  579.   else
  580.     {
  581.       delta_x=PageHeight-(image_width+(2.0*PageBottomMargin));
  582.       delta_y=PageWidth-(image_height+(2.0*PageLeftMargin));
  583.       if (delta_x >= 0.0)
  584.         translate_x=((delta_x/2.0+PageBottomMargin-PageHeight)*PointsPerInch);
  585.       else
  586.         translate_x=(PageBottomMargin-PageHeight)*PointsPerInch;
  587.       if (delta_y >= 0.0)
  588.         translate_y=((delta_y/2.0+PageLeftMargin)*PointsPerInch);
  589.       else
  590.         translate_y=PageLeftMargin*PointsPerInch;
  591.     }
  592.   /*
  593.     Output encapsulated Postscript header.
  594.   */
  595.   (void) fprintf(image->file,"%%!PS-Adobe-2.0 EPSF-2.0\n");
  596.   if (rotate == 0.0)
  597.     (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n",
  598.       (unsigned int) translate_x,(unsigned int) translate_y,
  599.       (unsigned int) (translate_x+scale_x),
  600.       (unsigned int) (translate_y+scale_y));
  601.   else
  602.     (void) fprintf(image->file,"%%%%BoundingBox: %d %d %d %d\n",
  603.       (unsigned int) translate_y,(unsigned int) -(translate_x+scale_x),
  604.       (unsigned int) (translate_y+scale_y),(unsigned int) -translate_x);
  605.   (void) fprintf(image->file,"%%%%Creator: ImageMagick\n");
  606.   (void) fprintf(image->file,"%%%%Title: %s\n",image->filename);
  607.   (void) fprintf(image->file,"%%%%EndComments\n");
  608.   /*
  609.     Output encapsulated Postscript commands.
  610.   */
  611.   for (q=commands; *q; q++)
  612.     (void) fprintf(image->file,"%s\n",*q);
  613.   /*
  614.     Output image data.
  615.   */
  616.   (void) fprintf(image->file,"%f\n%f %f\n%f %f\n%d %d\n%d\n",rotate,
  617.     translate_x,translate_y,scale_x,scale_y,image->columns,image->rows,
  618.     (image->class == PseudoClass));
  619.   p=image->pixels;
  620.   j=0;
  621.   switch (image->class)
  622.   {
  623.     case DirectClass:
  624.     {
  625.       /*
  626.         Dump DirectColor packets.
  627.       */
  628.       for (i=0; i < image->packets; i++)
  629.       {
  630.         j++;
  631.         (void) fprintf(image->file,"%02x%02x%02x%02x",p->length,p->red,
  632.           p->green,p->blue);
  633.         if (j == 9)
  634.           {
  635.             j=0;
  636.             (void) fprintf(image->file,"\n");
  637.           }
  638.         p++;
  639.       }
  640.       break;
  641.     }
  642.     case PseudoClass:
  643.     {
  644.       /*
  645.         Dump number of colors, colormap, PseudoColor packets.
  646.       */
  647.       (void) fprintf(image->file,"%d\n",image->colors);
  648.       for (i=0; i < image->colors; i++)
  649.         (void) fprintf(image->file,"%02x%02x%02x\n",image->colormap[i].red,
  650.           image->colormap[i].green,image->colormap[i].blue);
  651.       for (i=0; i < image->packets; i++)
  652.       {
  653.         j++;
  654.         (void) fprintf(image->file,"%02x%02x",p->length,p->index);
  655.         if (j == 18)
  656.           {
  657.             j=0;
  658.             (void) fprintf(image->file,"\n");
  659.           }
  660.         p++;
  661.       }
  662.       break;
  663.     }
  664.   }
  665.   (void) fprintf(image->file,"\n\n");
  666.   (void) fprintf(image->file,"%%%%Trailer\n");
  667.   if (image->file != stdin)
  668.     (void) fclose(image->file);
  669.   return(True);
  670. }
  671.  
  672. /*
  673. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  674. %                                                                             %
  675. %                                                                             %
  676. %                                                                             %
  677. %   R e a d C o l o r m a p                                                   %
  678. %                                                                             %
  679. %                                                                             %
  680. %                                                                             %
  681. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  682. %
  683. %  Function ReadColormap returns the red, green, and blue colormap of a window.
  684. %  Additionally, the number of colors in the colormap is returned.
  685. %
  686. %  The format of the ReadColormap function is:
  687. %
  688. %      number_colors=ReadColormap(display,window_attributes,colors)
  689. %
  690. %  A description of each parameter follows:
  691. %
  692. %    o number_colors:  ReadColormap returns the number of colors in the
  693. %      colormap.
  694. %
  695. %    o display:  Specifies a pointer to the Display structure;  returned from
  696. %      XOpenDisplay.
  697. %
  698. %    o window_attributes:  Specifies a pointer to the window attributes
  699. %      structure;  returned from XGetWindowAttributes.
  700. %
  701. %    o colors:  Specifies a an array of XColor structures.  The colormap
  702. %      red, green, and blue are returned.
  703. %
  704. %
  705. */
  706. static int ReadColormap(display,window_attributes,colors)
  707. Display
  708.   *display;
  709.  
  710. XWindowAttributes
  711.   *window_attributes;
  712.  
  713. XColor
  714.   **colors;
  715. {
  716.   int
  717.     number_colors;
  718.  
  719.   register int
  720.     i;
  721.  
  722.   if (window_attributes->colormap == (Colormap) NULL)
  723.     return(0);
  724.   if (window_attributes->visual->class == TrueColor)
  725.     return(0);
  726.   number_colors=window_attributes->visual->map_entries;
  727.   *colors=(XColor *) malloc((unsigned) (number_colors*sizeof(XColor)));
  728.   if (*colors == (XColor *) NULL)
  729.     Error("unable to allocate memory",(char *) NULL);
  730.   for (i=0; i < number_colors; i++)
  731.     if (window_attributes->visual->class != DirectColor)
  732.       for (i=0; i < number_colors; i++)
  733.       {
  734.         (*colors)[i].pixel=i;
  735.         (*colors)[i].pad=0;
  736.       }
  737.     else
  738.       {
  739.         unsigned long
  740.           blue,
  741.           blue_bit,
  742.           green,
  743.           green_bit,
  744.           red,
  745.           red_bit;
  746.  
  747.         /*
  748.           DirectColor visual.
  749.         */
  750.         red=0;
  751.         green=0;
  752.         blue=0;
  753.         red_bit=window_attributes->visual->red_mask &
  754.           (~(window_attributes->visual->red_mask)+1);
  755.         green_bit=window_attributes->visual->green_mask &
  756.           (~(window_attributes->visual->green_mask)+1);
  757.         blue_bit=window_attributes->visual->blue_mask &
  758.           (~(window_attributes->visual->blue_mask)+1);
  759.         for (i=0; i < number_colors; i++)
  760.         {
  761.           (*colors)[i].pixel=red | green | blue;
  762.           (*colors)[i].pad=0;
  763.           red+=red_bit;
  764.           if (red > window_attributes->visual->red_mask)
  765.             red=0;
  766.           green+=green_bit;
  767.           if (green > window_attributes->visual->green_mask)
  768.             green=0;
  769.           blue+=blue_bit;
  770.           if (blue > window_attributes->visual->blue_mask)
  771.             blue=0;
  772.         }
  773.       }
  774.   XQueryColors(display,window_attributes->colormap,*colors,number_colors);
  775.   return(number_colors);
  776. }
  777.  
  778. /*
  779. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  780. %                                                                             %
  781. %                                                                             %
  782. %                                                                             %
  783. %   R e a d I m a g e                                                         %
  784. %                                                                             %
  785. %                                                                             %
  786. %                                                                             %
  787. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  788. %
  789. %  Procedure ReadImage reads an image from an X window.
  790. %
  791. %  The format of the ReadImage routine is:
  792. %
  793. %      ReadImage(display,root_window,target_window,client_window,borders,
  794. %        image)
  795. %
  796. %  A description of each parameter follows:
  797. %
  798. %    o display:  Specifies a pointer to the Display structure;  returned from
  799. %      XOpenDisplay.
  800. %
  801. %    o root_window: Specifies the id of the root window.
  802. %
  803. %    o target_window: Specifies the id of the target window.
  804. %
  805. %    o client_window: Specifies the id of the client of the target window.
  806. %
  807. %    o borders: Specifies whether borders pixels are to be saved with
  808. %      the image.
  809. %
  810. %    o image:  specifies a pointer to the Image structure.
  811. %
  812. %
  813. */
  814. static void ReadImage(display,root_window,target_window,client_window,borders,
  815.   image)
  816. Display
  817.   *display;
  818.  
  819. Window
  820.   root_window,
  821.   target_window,
  822.   client_window;
  823.  
  824. unsigned int
  825.   borders;
  826.  
  827. Image
  828.   *image;
  829. {
  830.   int
  831.     display_width,
  832.     display_height,
  833.     x,
  834.     y;
  835.  
  836.   register int 
  837.     i;
  838.  
  839.   register RunlengthPacket
  840.     *p;
  841.  
  842.   register unsigned long
  843.     pixel;
  844.  
  845.   unsigned char
  846.     blue,
  847.     green,
  848.     red;
  849.  
  850.   Window
  851.     child;
  852.  
  853.   XColor
  854.     *colors;
  855.  
  856.   XImage
  857.     *ximage;
  858.  
  859.   XTextProperty
  860.     window_name;
  861.  
  862.   XWindowAttributes
  863.     client_attributes,
  864.     target_attributes;
  865.  
  866.   /*
  867.     Inform the user not to alter the screen.
  868.   */
  869.   XBell(display,0);
  870.   /*
  871.     Get the attributes of the window being dumped.
  872.   */
  873.   if (!XGetWindowAttributes(display,target_window,&target_attributes) ||
  874.       !XGetWindowAttributes(display,client_window,&client_attributes))
  875.     Error("unable to get target window attributes",(char *) NULL);
  876.   XTranslateCoordinates(display,target_window,root_window,0,0,&x,&y,&child);
  877.   target_attributes.x=x;
  878.   target_attributes.y=y;
  879.   image->columns=target_attributes.width;
  880.   image->rows=target_attributes.height;
  881.   if (borders)
  882.     {
  883.       /*
  884.         Do not include border in image.
  885.       */
  886.       x-=target_attributes.border_width;
  887.       y-=target_attributes.border_width;
  888.       image->columns+=2*target_attributes.border_width;
  889.       image->rows+=2*target_attributes.border_width;
  890.     }
  891.   /*
  892.     clip to window
  893.   */
  894.   if (x < 0)
  895.     {
  896.       image->columns+=x;
  897.       x=0;
  898.     }
  899.   if (y < 0)
  900.     {
  901.       image->rows+=y;
  902.       y=0;
  903.     }
  904.   display_width=DisplayWidth(display,XDefaultScreen(display));
  905.   display_height=DisplayHeight(display,XDefaultScreen(display));
  906.   if ((x+image->columns) > display_width)
  907.     image->columns=display_width-x;
  908.   if ((y+image->rows) > display_height)
  909.     image->rows=display_height-y;
  910.   /*
  911.     Get image from window with XGetImage.
  912.   */
  913.   x-=target_attributes.x;
  914.   y-=target_attributes.y;
  915.   ximage=XGetImage(display,target_window,x,y,image->columns,image->rows,
  916.     AllPlanes,ZPixmap);
  917.   if (ximage == (XImage *) NULL)
  918.     Error("unable to get image",(char *) NULL);
  919.   /*
  920.     Obtain the window colormap from the client of the target window.
  921.   */
  922.   image->colors=ReadColormap(display,&client_attributes,&colors);
  923.   XBell(display,0);
  924.   XBell(display,0);
  925.   XFlush(display);
  926.   /*
  927.     Convert image to MIFF format.
  928.   */
  929.   image->comments=(char *) NULL;
  930.   if (XGetWMName(display,target_window,&window_name))
  931.     {
  932.       /*
  933.         Initial image comment.
  934.       */
  935.       image->comments=(char *) 
  936.     malloc((unsigned int) (strlen((char *) window_name.value)+256));
  937.       if (image->comments == (char *) NULL)
  938.         Error("unable to allocate memory",(char *) NULL);
  939.       (void) sprintf(image->comments,"\n  Imported from X11 window: %s\n\0",
  940.         window_name.value);
  941.     }
  942.   if ((target_attributes.visual->class == TrueColor) ||
  943.       (target_attributes.visual->class == DirectColor))
  944.     image->class=DirectClass;
  945.   else
  946.     image->class=PseudoClass;
  947.   image->compression=RunlengthEncodedCompression;
  948.   image->scene=0;
  949.   image->pixels=(RunlengthPacket *)
  950.     malloc(image->columns*image->rows*sizeof(RunlengthPacket));
  951.   if (image->pixels == (RunlengthPacket *) NULL)
  952.     Error("unable to allocate memory",(char *) NULL);
  953.   image->packets=0;
  954.   p=image->pixels;
  955.   p->length=MaxRunlength;
  956.   switch (image->class)
  957.   {
  958.     case DirectClass:
  959.     {
  960.       register unsigned long
  961.         color,
  962.         index;
  963.  
  964.       unsigned long
  965.         blue_mask,
  966.         blue_shift,
  967.         green_mask,
  968.         green_shift,
  969.         red_mask,
  970.         red_shift;
  971.  
  972.       /*
  973.         Determine shift and mask for red, green, and blue.
  974.       */
  975.       red_mask=target_attributes.visual->red_mask;
  976.       red_shift=0;
  977.       while ((red_mask & 0x01) == 0)
  978.       {
  979.         red_mask>>=1;
  980.         red_shift++;
  981.       }
  982.       green_mask=target_attributes.visual->green_mask;
  983.       green_shift=0;
  984.       while ((green_mask & 0x01) == 0)
  985.       {
  986.         green_mask>>=1;
  987.         green_shift++;
  988.       }
  989.       blue_mask=target_attributes.visual->blue_mask;
  990.       blue_shift=0;
  991.       while ((blue_mask & 0x01) == 0)
  992.       {
  993.         blue_mask>>=1;
  994.         blue_shift++;
  995.       }
  996.       /*
  997.         Convert X image to DirectClass packets.
  998.       */
  999.       if ((image->colors > 0) && 
  1000.           (target_attributes.visual->class == DirectColor))
  1001.         for (y=0; y < image->rows; y++)
  1002.         {
  1003.           for (x=0; x < image->columns; x++)
  1004.           {
  1005.             pixel=XGetPixel(ximage,x,y);
  1006.             index=(pixel >> red_shift) & red_mask;
  1007.             red=(unsigned char) (colors[index].red >> 8);
  1008.             index=(pixel >> green_shift) & green_mask;
  1009.             green=(unsigned char) (colors[index].green >> 8);
  1010.             index=(pixel >> blue_shift) & blue_mask;
  1011.             blue=(unsigned char) (colors[index].blue >> 8);
  1012.             if ((red == p->red) && (green == p->green) && (blue == p->blue) && 
  1013.                 (p->length < MaxRunlength))
  1014.                 p->length++;
  1015.               else
  1016.                 {
  1017.                   if (image->packets > 0)
  1018.                     p++;
  1019.                   image->packets++;
  1020.                   p->red=red;
  1021.                   p->green=green;
  1022.                   p->blue=blue;
  1023.                   p->index=0;
  1024.                   p->length=0;
  1025.                 }
  1026.           }
  1027.         }
  1028.       else
  1029.         for (y=0; y < image->rows; y++)
  1030.           for (x=0; x < image->columns; x++)
  1031.           {
  1032.             pixel=XGetPixel(ximage,x,y);
  1033.             color=(pixel >> red_shift) & red_mask;
  1034.             red=(unsigned char) 
  1035.               ((((unsigned long) color*65535)/red_mask) >> 8);
  1036.             color=(pixel >> green_shift) & green_mask;
  1037.             green=(unsigned char) 
  1038.               ((((unsigned long) color*65535)/green_mask) >> 8);
  1039.             color=(pixel >> blue_shift) & blue_mask;
  1040.             blue=(unsigned char) 
  1041.               ((((unsigned long) color*65535)/blue_mask) >> 8);
  1042.             if ((red == p->red) && (green == p->green) && (blue == p->blue) && 
  1043.                 (p->length < MaxRunlength))
  1044.                 p->length++;
  1045.               else
  1046.                 {
  1047.                   if (image->packets > 0)
  1048.                     p++;
  1049.                   image->packets++;
  1050.                   p->red=red;
  1051.                   p->green=green;
  1052.                   p->blue=blue;
  1053.                   p->index=0;
  1054.                   p->length=0;
  1055.                 }
  1056.           }
  1057.       break;
  1058.     }
  1059.     case PseudoClass:
  1060.     {
  1061.       /*
  1062.         Convert X image to PseudoClass packets.
  1063.       */
  1064.       image->colormap=(ColorPacket *)
  1065.         malloc((unsigned) (image->colors*sizeof(ColorPacket)));
  1066.       if (image->colormap == (ColorPacket *) NULL)
  1067.         Error("unable to allocate memory",(char *) NULL);
  1068.       for (i=0; i < image->colors; i++)
  1069.       {
  1070.         image->colormap[i].red=colors[i].red >> 8;
  1071.         image->colormap[i].green=colors[i].green >> 8;
  1072.         image->colormap[i].blue=colors[i].blue >> 8;
  1073.       }
  1074.       for (y=0; y < image->rows; y++)
  1075.         for (x=0; x < image->columns; x++)
  1076.         {
  1077.           pixel=XGetPixel(ximage,x,y);
  1078.           red=(unsigned char) (colors[pixel].red >> 8);
  1079.           green=(unsigned char) (colors[pixel].green >> 8);
  1080.           blue=(unsigned char) (colors[pixel].blue >> 8);
  1081.           if ((red == p->red) && (green == p->green) && (blue == p->blue) && 
  1082.               (p->length < MaxRunlength))
  1083.               p->length++;
  1084.             else
  1085.               {
  1086.                 if (image->packets > 0)
  1087.                   p++;
  1088.                 image->packets++;
  1089.                 p->red=red;
  1090.                 p->green=green;
  1091.                 p->blue=blue;
  1092.                 p->index=(unsigned short) pixel;
  1093.                 p->length=0;
  1094.               }
  1095.         }
  1096.       break;
  1097.     }
  1098.   }
  1099.   /*
  1100.     Free image and colormap.
  1101.   */
  1102.   if (image->colors > 0)
  1103.     (void) free((char *) colors);
  1104.   XDestroyImage(ximage);
  1105.   if (image->packets > ((image->columns*image->rows*3) >> 2))
  1106.     image->compression=NoCompression;
  1107.   image->pixels=(RunlengthPacket *)
  1108.     realloc((char *) image->pixels,image->packets*sizeof(RunlengthPacket));
  1109. }
  1110.  
  1111. /*
  1112. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1113. %                                                                             %
  1114. %                                                                             %
  1115. %                                                                             %
  1116. %   S e l e c t W i n d o w                                                   %
  1117. %                                                                             %
  1118. %                                                                             %
  1119. %                                                                             %
  1120. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1121. %
  1122. %  Function SelectWindow allows a user to select a window using the mouse.
  1123. %
  1124. %  The format of the SelectWindow function is:
  1125. %
  1126. %      target_window=SelectWindow(display,root_window)
  1127. %
  1128. %  A description of each parameter follows:
  1129. %
  1130. %    o window:  SelectWindow returns the window id.
  1131. %
  1132. %    o display:  Specifies a pointer to the Display structure;  returned from
  1133. %      XOpenDisplay.
  1134. %
  1135. %    o root_window: Specifies the window id of the root window.
  1136. %
  1137. %
  1138. */
  1139. static Window SelectWindow(display,root_window)
  1140. Display
  1141.   *display;
  1142.  
  1143. Window
  1144.   root_window;
  1145. {
  1146.   Cursor
  1147.     crosshair_cursor;
  1148.  
  1149.   int
  1150.     status;
  1151.  
  1152.   unsigned int
  1153.     presses;
  1154.  
  1155.   Window
  1156.     target_window;
  1157.  
  1158.   XEvent
  1159.     event;
  1160.  
  1161.   /*
  1162.     Make the target cursor.
  1163.   */
  1164.   crosshair_cursor=XCreateFontCursor(display,XC_crosshair);
  1165.   /*
  1166.     Grab the pointer using target cursor.
  1167.   */
  1168.   status=XGrabPointer(display,root_window,False,ButtonPressMask | 
  1169.     ButtonReleaseMask,GrabModeSync,GrabModeAsync,root_window,crosshair_cursor,
  1170.     CurrentTime);
  1171.   if (status != GrabSuccess)
  1172.     Error("cannot grab the mouse",(char *) NULL);
  1173.   /*
  1174.     Select a window.
  1175.   */
  1176.   target_window=(Window) NULL;
  1177.   presses=0;
  1178.   do
  1179.   {
  1180.     /*
  1181.       Allow another event.
  1182.     */
  1183.     XAllowEvents(display,SyncPointer,CurrentTime);
  1184.     XWindowEvent(display,root_window,ButtonPressMask | ButtonReleaseMask,
  1185.       &event);
  1186.     switch (event.type)
  1187.     {
  1188.       case ButtonPress:
  1189.       {
  1190.         if (target_window == (Window) NULL)
  1191.           {
  1192.             target_window=event.xbutton.subwindow;
  1193.             if (target_window == (Window) NULL)
  1194.               target_window=root_window;
  1195.           }
  1196.         presses++;
  1197.         break;
  1198.       }
  1199.       case ButtonRelease:
  1200.       {
  1201.         if (presses > 0)
  1202.           presses--;
  1203.         break;
  1204.       }
  1205.       default:
  1206.         break;
  1207.     }
  1208.   }
  1209.   while ((target_window == (Window) NULL) || (presses != 0));
  1210.   XUngrabPointer(display,CurrentTime);
  1211.   XFreeCursor(display,crosshair_cursor);
  1212.   return(target_window);
  1213. }
  1214.  
  1215. /*
  1216. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1217. %                                                                             %
  1218. %                                                                             %
  1219. %                                                                             %
  1220. %   U s a g e                                                                 %
  1221. %                                                                             %
  1222. %                                                                             %
  1223. %                                                                             %
  1224. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1225. %
  1226. %  Procedure Usage displays the program usage;
  1227. %
  1228. %  The format of the Usage routine is:
  1229. %
  1230. %      Usage(message)
  1231. %
  1232. %  A description of each parameter follows:
  1233. %
  1234. %    message:  Specifies a specific message to display to the user.
  1235. %
  1236. */
  1237. static void Usage(message)
  1238. char
  1239.   *message;
  1240. {
  1241.   char
  1242.     **p;
  1243.  
  1244.   static char
  1245.     *options[]=
  1246.     {
  1247.       "-border         include image borders in the output image",
  1248.       "-display server X server to contact",
  1249.       "-frame          include window manager frame",
  1250.       "-id number      select window with this id",
  1251.       "-name name      select window with this name",
  1252.       "-root           select root window",
  1253.       (char *) NULL
  1254.     };
  1255.   if (message != (char *) NULL)
  1256.     (void) fprintf(stderr,"Can't continue, %s.\n\n",message);
  1257.   (void) fprintf(stderr,"Usage: %s [options ...] file\n",application_name);
  1258.   (void) fprintf(stderr,"\nWhere options include:\n");
  1259.   for (p=options; *p != (char *) NULL; p++)
  1260.     (void) fprintf(stderr,"  %s\n",*p);
  1261.   (void) fprintf(stderr,
  1262.     "\nChange '-' to '+' in any option above to reverse its effect.\n");
  1263.   (void) fprintf(stderr,
  1264.     "For example, +frame means do not include window manager frame.\n");
  1265.   (void) fprintf(stderr,"\nSpecify 'file' as '-' for standard output.\n");
  1266.   exit(1);
  1267. }
  1268.  
  1269. /*
  1270. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1271. %                                                                             %
  1272. %                                                                             %
  1273. %                                                                             %
  1274. %   W i n d o w B y N a m e                                                   %
  1275. %                                                                             %
  1276. %                                                                             %
  1277. %                                                                             %
  1278. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1279. %
  1280. %  Function WindowByName locates a window with a given name on a display.
  1281. %  If no window with the given name is found, 0 is returned. If more than
  1282. %  one window has the given name, the first one is returned.  Only root and
  1283. %  its children are searched.
  1284. %
  1285. %  The format of the WindowByName function is:
  1286. %
  1287. %      window=WindowByName(display,root_window,name)
  1288. %
  1289. %  A description of each parameter follows:
  1290. %
  1291. %    o window:  WindowByName returns the window id.
  1292. %
  1293. %    o display:  Specifies a pointer to the Display structure;  returned from
  1294. %      XOpenDisplay.
  1295. %
  1296. %    o root_window:  Specifies the id of the root window.
  1297. %
  1298. %    o name:  Specifies the name of the window to locate.
  1299. %
  1300. %
  1301. */
  1302. static Window WindowByName(display,root_window,name)
  1303. Display
  1304.   *display;
  1305.  
  1306. Window
  1307.   root_window;
  1308.  
  1309. char
  1310.   *name;
  1311. {
  1312.   register int
  1313.     i;
  1314.  
  1315.   unsigned int
  1316.     number_children;
  1317.  
  1318.   Window
  1319.     *children,
  1320.     child,
  1321.     window;
  1322.  
  1323.   XTextProperty
  1324.     window_name;
  1325.  
  1326.   if (XGetWMName(display,root_window,&window_name))
  1327.     if (strcmp((char *) window_name.value,name) == 0)
  1328.       return(root_window);
  1329.   if (!XQueryTree(display,root_window,&child,&child,&children,&number_children))
  1330.     return(0);
  1331.   window=0;
  1332.   for (i=0; i < number_children; i++)
  1333.   {
  1334.     /*
  1335.       Search each child and their children.
  1336.     */
  1337.     window=WindowByName(display,children[i],name);
  1338.     if (window != (Window) NULL)
  1339.       break;
  1340.   }
  1341.   if (children != (Window *) NULL)
  1342.     XFree((char *) children);
  1343.   return(window);
  1344. }
  1345.  
  1346. /*
  1347. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1348. %                                                                             %
  1349. %                                                                             %
  1350. %                                                                             %
  1351. %   W i n d o w B y P r o p e r y                                             %
  1352. %                                                                             %
  1353. %                                                                             %
  1354. %                                                                             %
  1355. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1356. %
  1357. %  Function WindowByProperty locates a child window with a given property.
  1358. %  If no window with the given name is found, 0 is returned.  If more than
  1359. %  one window has the given property, the first one is returned.  Only the 
  1360. %  window specified and its subwindows are searched.
  1361. %
  1362. %  The format of the WindowByProperty function is:
  1363. %
  1364. %      child=WindowByProperty(display,window,property)
  1365. %
  1366. %  A description of each parameter follows:
  1367. %
  1368. %    o child:  WindowByProperty returns the window id with the specified
  1369. %      property.  If no windows are found, WindowByProperty returns 0.
  1370. %
  1371. %    o display:  Specifies a pointer to the Display structure;  returned from
  1372. %      XOpenDisplay.
  1373. %
  1374. %    o property:  Specifies the property of the window to locate.
  1375. %
  1376. %
  1377. */
  1378. static Window WindowByProperty(display,window,property)
  1379. Display 
  1380.   *display;
  1381.  
  1382. Window 
  1383.   window;
  1384.  
  1385. Atom 
  1386.   property;
  1387. {
  1388.   Atom 
  1389.     type;
  1390.  
  1391.   int 
  1392.     format;
  1393.  
  1394.   unsigned char 
  1395.     *data;
  1396.  
  1397.   unsigned int 
  1398.     i,
  1399.     number_children;
  1400.  
  1401.   unsigned long 
  1402.     after,
  1403.     number_items;
  1404.  
  1405.   Window 
  1406.     *children,
  1407.     child,
  1408.     parent,
  1409.     root;
  1410.  
  1411.   if (!XQueryTree(display,window,&root,&parent,&children,&number_children))
  1412.     return((Window) NULL);
  1413.   type=(Atom) NULL;
  1414.   child=(Window) NULL;
  1415.   for (i=0; (i < number_children) && (child == (Window) NULL); i++) 
  1416.   {
  1417.     (void) XGetWindowProperty(display,children[i],property,0L,0L,False,
  1418.       AnyPropertyType,&type,&format,&number_items,&after,&data);
  1419.     if (type != (Atom) NULL)
  1420.       child=children[i];
  1421.   }
  1422.   for (i = 0; (i < number_children) && (child == (Window) NULL); i++)
  1423.     child=WindowByProperty(display,children[i],property);
  1424.   if (children != (Window *) NULL) 
  1425.     XFree((char *) children);
  1426.   return(child);
  1427. }
  1428.  
  1429. /*
  1430. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1431. %                                                                             %
  1432. %                                                                             %
  1433. %                                                                             %
  1434. %    M a i n                                                                  %
  1435. %                                                                             %
  1436. %                                                                             %
  1437. %                                                                             %
  1438. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1439. %
  1440. %
  1441. */
  1442. int main(argc,argv)
  1443. int
  1444.   argc;
  1445.  
  1446. char
  1447.   *argv[];
  1448. {
  1449.   char
  1450.     *filename,
  1451.     *option,
  1452.     *server_name;
  1453.  
  1454.   Display
  1455.     *display;
  1456.  
  1457.   extern unsigned int
  1458.     WriteImage();
  1459.  
  1460.   Image
  1461.     image;
  1462.  
  1463.   int
  1464.     i;
  1465.  
  1466.   unsigned int
  1467.     borders,
  1468.     frame,
  1469.     j;
  1470.  
  1471.   Window
  1472.     client_window,
  1473.     root_window,
  1474.     target_window;
  1475.  
  1476.   /*
  1477.     Display usage profile if there are no command line arguments.
  1478.   */
  1479.   application_name=(*argv);
  1480.   if (argc < 2)
  1481.     Usage((char *) NULL);
  1482.   /*
  1483.     Connect to X server.
  1484.   */
  1485.   server_name=(char *) NULL;
  1486.   for (i=1; i < argc; i++)
  1487.   {
  1488.     /*
  1489.       Check command line for server name.
  1490.     */
  1491.     option=argv[i];
  1492.     if ((strlen(option) > 1) && ((*option == '-') || (*option == '+')))
  1493.       if (strncmp("dis",option+1,3) == 0)
  1494.         {
  1495.           /*
  1496.             User specified server name.
  1497.           */
  1498.           i++;
  1499.           if (i == argc)
  1500.             Usage("missing server name on -display");
  1501.           server_name=argv[i];
  1502.           break;
  1503.         }
  1504.   }
  1505.   display=XOpenDisplay(server_name);
  1506.   if (display == (Display *) NULL)
  1507.     Error("unable to connect to",XDisplayName(server_name));
  1508.   root_window=XRootWindow(display,XDefaultScreen(display));
  1509.   /*
  1510.     Get X defaults.
  1511.   */
  1512.   option=XGetDefault(display,application_name,"borders");
  1513.   borders=IsTrue(option);
  1514.   option=XGetDefault(display,application_name,"frame");
  1515.   frame=IsTrue(option);
  1516.   /*
  1517.     Check command syntax.
  1518.   */
  1519.   filename=(char *) NULL;
  1520.   target_window=(Window) NULL;
  1521.   for (i=1; i < argc; i++)
  1522.   {
  1523.     option=argv[i];
  1524.     if ((strlen(option) < 2) || ((*option != '-') && (*option != '+')))
  1525.       filename=argv[i];
  1526.     else
  1527.       switch(*(option+1))
  1528.       {
  1529.         case 'b':
  1530.         {
  1531.           borders=(*option == '-');
  1532.           break;
  1533.         }
  1534.         case 'h':
  1535.         {
  1536.           Usage((char *) NULL);
  1537.           break;
  1538.         }
  1539.         case 'f':
  1540.         {
  1541.           frame=(*option == '-');
  1542.           break;
  1543.         }
  1544.         case 'i':
  1545.         {
  1546.           i++;
  1547.           if (i == argc)
  1548.             Usage("missing id on -id");
  1549.           option=argv[i];
  1550.           target_window=(Window) strtol(option,(char **) NULL,0);
  1551.           break;
  1552.         }
  1553.         case 'n':
  1554.         {
  1555.           i++;
  1556.           if (i == argc)
  1557.             Usage("missing name on -name");
  1558.           option=argv[i]; 
  1559.           target_window=WindowByName(display,root_window,option);
  1560.           if (target_window == (Window) NULL)
  1561.             (void) fprintf(stderr,"No window with name %s exists!\n",option);
  1562.           break;
  1563.         }
  1564.         case 'r':
  1565.         {
  1566.           target_window=root_window;
  1567.           break;
  1568.         }
  1569.         default:
  1570.           Usage((char *) NULL);
  1571.       }
  1572.   }
  1573.   if (filename == (char *) NULL)
  1574.     Usage("missing an image file name");
  1575.   /*
  1576.     If the window is not specified, let the user choose one with the mouse.
  1577.   */
  1578.   if (target_window == (Window) NULL)
  1579.     target_window=SelectWindow(display,root_window);
  1580.   client_window=target_window;
  1581.   if (target_window != root_window)
  1582.     if (XGetGeometry(display,target_window,&root_window,&i,&i,&j,&j,&j,&j))
  1583.       {
  1584.         /*
  1585.           Get client window.
  1586.         */
  1587.         client_window=ClientWindow(display,target_window);
  1588.         if (!frame)
  1589.           target_window=client_window;
  1590.       }
  1591.   (void) strcpy(image.filename,filename);
  1592.   ReadImage(display,root_window,target_window,client_window,borders,&image);
  1593.   (void) fprintf(stderr,"%s %dx%d\n",image.filename,image.columns,image.rows);
  1594.   (void) PrintImage(&image);
  1595.   return(False);
  1596. }
  1597.