home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1391 / XtoPS.c < prev    next >
C/C++ Source or Header  |  1990-12-28  |  40KB  |  1,368 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. %                            January  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 a X11 image from any visible window on a display
  44. %  and converts it to postscript format.  The image can then be printed on a
  45. %  postscript compatible printer in either color or grayscale.
  46. %
  47. %  The XtoPS program command syntax is:
  48. %
  49. %  Usage: XToPS [options ...] file
  50. %
  51. %  Where options include:
  52. %    +border        include image borders in the output image
  53. %    -display name  X server to contact
  54. %    +frame         include window manager frame
  55. %    +grayscale     print image as gray scale colors
  56. %    -id number     select window with this id
  57. %    -name name     select window with this name
  58. %    -root          select root window
  59. %
  60. %  Change '+' to '-' in any option above to reverse its effect.
  61. %  For example, -borders means do not include image borders).
  62. %
  63. %  Specify 'file' as '-' for standard input or output.
  64. %
  65. %
  66. */
  67.  
  68. /*
  69.   Include declarations.
  70. */
  71. #include <X11/Xlib.h>
  72. #include <X11/Xutil.h>
  73. #include <X11/cursorfont.h>
  74. #include "display.h"
  75.  
  76. /*
  77. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  78. %                                                                             %
  79. %                                                                             %
  80. %                                                                             %
  81. %   C l i e n t W i n d o w                                                   %
  82. %                                                                             %
  83. %                                                                             %
  84. %                                                                             %
  85. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  86. %
  87. %  Function ClientWindow finds a window, at or below the specified window,  
  88. %  which has a WM_STATE property.  If such a window is found, it is returned,  
  89. %  otherwise the argument window is returned.
  90. %
  91. %  The format of the ClientWindow function is:
  92. %
  93. %      child=ClientWindow(display,window)
  94. %
  95. %  A description of each parameter follows:
  96. %
  97. %    o child:  ClientWindow returns a window, at or below the specified 
  98. %      window, which has a WM_STATE property otherwise the argument window
  99. %      is returned.
  100. %
  101. %    o display:  Specifies a pointer to the Display structure;  returned from
  102. %      XOpenDisplay.
  103. %
  104. %    o window:  Specifies the window to find a WM_STATE property.
  105. %
  106. %
  107. */
  108. Window ClientWindow(display,window)
  109. Display 
  110.   *display;
  111.  
  112. Window 
  113.   window;
  114. {
  115.   Atom 
  116.     state;
  117.  
  118.   Atom 
  119.     type;
  120.  
  121.   int 
  122.     format;
  123.  
  124.   unsigned char 
  125.     *data;
  126.  
  127.   unsigned long 
  128.     after,
  129.     number_items;
  130.  
  131.   Window 
  132.     child,
  133.     WindowByProperty();
  134.  
  135.   state=XInternAtom(display,"WM_STATE",True);
  136.   if (!state)
  137.     return(window);
  138.   type=None;
  139.   XGetWindowProperty(display,window,state,0,0,False,AnyPropertyType,&type, 
  140.     &format,&number_items,&after,&data);
  141.   if (type)
  142.     return(window);
  143.   child=WindowByProperty(display,window,state);
  144.   if (!child)
  145.     return(window);
  146.   return(child);
  147. }
  148.  
  149. /*
  150. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  151. %                                                                             %
  152. %                                                                             %
  153. %                                                                             %
  154. %   I s T r u e                                                               %
  155. %                                                                             %
  156. %                                                                             %
  157. %                                                                             %
  158. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  159. %
  160. %  Function IsTrue returns True if the boolean is "true", "on", "yes" or "1".
  161. %
  162. %  The format of the IsTrue routine is:
  163. %
  164. %      option=IsTrue(boolean)
  165. %
  166. %  A description of each parameter follows:
  167. %
  168. %    o option:  either True or False depending on the boolean parameter.
  169. %
  170. %    o boolean:  Specifies a pointer to a character array.
  171. %
  172. %
  173. */
  174. int IsTrue(boolean)
  175. char
  176.   *boolean;
  177. {
  178.   char
  179.     c,
  180.     *p;
  181.  
  182.   if (!boolean)
  183.     return(False);
  184.   p=boolean;
  185.   for ( ; *p; p++)
  186.   {
  187.     /*
  188.       Convert to lower case.
  189.     */
  190.     c=(*p);
  191.     if (isascii(c) && isupper(c))
  192.       *p=tolower(c);
  193.   }
  194.   if (strcmp(boolean,"true") == 0)
  195.     return(True);
  196.   if (strcmp(boolean,"on") == 0)
  197.     return(True);
  198.   if (strcmp(boolean,"yes") == 0)
  199.     return(True);
  200.   if (strcmp(boolean,"1") == 0)
  201.     return(True);
  202.   if (strcmp(boolean,"+") == 0)
  203.     return(True);
  204.   return(False);
  205. }
  206.  
  207. /*
  208. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  209. %                                                                             %
  210. %                                                                             %
  211. %                                                                             %
  212. %   P r i n t I m a g e                                                       %
  213. %                                                                             %
  214. %                                                                             %
  215. %                                                                             %
  216. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  217. %
  218. %  Function PrintImage translates a MIFF image to postscript for printing.
  219. %
  220. %  The format of the PrintImage routine is:
  221. %
  222. %      status=PrintImage(image,grayscale)
  223. %
  224. %  A description of each parameter follows:
  225. %
  226. %    o status:  Function PrintImage return True if the image is printed.
  227. %      False is returned if the image file cannot be opened for printing.
  228. %
  229. %    o image:  The address of a structure of type Image;  returned from
  230. %      ReadImage.
  231. %
  232. %    o grayscale: An integer that specifies a grayscale image if non-zero.
  233. %
  234. %
  235. */
  236. unsigned int PrintImage(image,grayscale)
  237. Image
  238.   *image;
  239.  
  240. unsigned int
  241.   grayscale;
  242. {
  243. #define PointsPerInch 72.0
  244. #define PageBorder 0.25
  245. #define PageWidth  8.5
  246. #define PageHeight 11.0
  247.  
  248.   static char
  249.     *commands[]=
  250.     {
  251.       "%!",
  252.       "%",
  253.       "% Display a runlength-encoded grayscale or color image.",
  254.       "%",
  255.       "/buffer 512 string def",
  256.       "/byte 1 string def",
  257.       "/color_packet 3 string def",
  258.       "/gray_packet 1 string def",
  259.       "/expanded_packet 768 string def",
  260.       " ",
  261.       "/ReadColorPacket",
  262.       "{",
  263.       "  %",
  264.       "  % read a runlength-encoded color packet (length red green blue).",
  265.       "  %",
  266.       "  currentfile byte readhexstring pop 0 get",
  267.       "  /count exch 1 add def",
  268.       "  /count count 3 mul def",
  269.       "  currentfile color_packet readhexstring pop",
  270.       "  0 3 count 1 sub",
  271.       "  {",
  272.       "    expanded_packet exch color_packet putinterval",
  273.       "  } for pop",
  274.       "  expanded_packet 0 count getinterval",
  275.       "} def",
  276.       " ",
  277.       "/DisplayColorImage",
  278.       "{",
  279.       "  %",
  280.       "  % display a runlength-encoded color image.",
  281.       "  %",
  282.       "  columns rows 8",
  283.       "  [",
  284.       "    columns 0 0",
  285.       "    rows neg 0 rows",
  286.       "  ]",
  287.       "  { ReadColorPacket } false 3 colorimage",
  288.       "} def",
  289.       " ",
  290.       "/ReadGrayPacket",
  291.       "{",
  292.       "  %",
  293.       "  % read a runlength-encoded grayscale packet (length gray).",
  294.       "  %",
  295.       "  currentfile byte readhexstring pop 0 get",
  296.       "  /count exch 1 add def",
  297.       "  currentfile gray_packet readhexstring pop",
  298.       "  0 1 count 1 sub",
  299.       "  {",
  300.       "    expanded_packet exch gray_packet putinterval",
  301.       "  } for pop",
  302.       "  expanded_packet 0 count getinterval",
  303.       "} def",
  304.       " ",
  305.       "/DisplayGrayImage",
  306.       "{",
  307.       "  %",
  308.       "  % display a runlength-encoded grayscale image.",
  309.       "  %",
  310.       "  columns rows 8",
  311.       "  [",
  312.       "    columns 0 0",
  313.       "    rows neg 0 rows",
  314.       "  ]",
  315.       "  { ReadGrayPacket } image",
  316.       "} def",
  317.       " ",
  318.       "/DisplayImage",
  319.       "{",
  320.       "  %",
  321.       "  % display a runlength-encoded grayscale or color image.",
  322.       "  %",
  323.       "  initgraphics",
  324.       "  gsave",
  325.       "  currentfile buffer readline pop",
  326.       "  token { /degrees exch def } { } ifelse",
  327.       "  degrees rotate",
  328.       "  currentfile buffer readline pop",
  329.       "  token { /x exch def } { } ifelse",
  330.       "  token { /y exch def } { } ifelse",
  331.       "  x y translate",
  332.       "  currentfile buffer readline pop",
  333.       "  token { /x exch def } { } ifelse",
  334.       "  token { /y exch def } { } ifelse",
  335.       "  x y scale",
  336.       "  currentfile buffer readline pop",
  337.       "  currentfile buffer readline pop",
  338.       "  token { /columns exch def } { } ifelse",
  339.       "  token { /rows exch def } { } ifelse",
  340.       "  currentfile buffer readline pop",
  341.       "  token { /grayscale exch def } { } ifelse",
  342.       "  grayscale 0 gt { DisplayGrayImage } { DisplayColorImage } ifelse",
  343.       "  grestore",
  344.       "  showpage",
  345.       "} def",
  346.       " ",
  347.       "%",
  348.       "% DisplayImage parameters:",
  349.       "%   degrees rotation.",
  350.       "%   x & y translation.",
  351.       "%   x & y scale.",
  352.       "%   image name.",
  353.       "%   image columns & rows.",
  354.       "%   grayscale.",
  355.       "%   hex grayscale or color runlength-encoded packets.",
  356.       "% ",
  357.       "DisplayImage",
  358.       NULL
  359.     };
  360.  
  361.   char
  362.     **q;
  363.  
  364.   double
  365.     delta_x,
  366.     delta_y,
  367.     image_height,
  368.     image_width,
  369.     max,
  370.     min,
  371.     rotate,
  372.     scale,
  373.     scale_x,
  374.     scale_y,
  375.     translate_x,
  376.     translate_y;
  377.  
  378.   register RunlengthPacket
  379.     *p;
  380.  
  381.   register int
  382.     i,
  383.     j;
  384.  
  385.   register unsigned char
  386.     blue,
  387.     gray,
  388.     green,
  389.     red;
  390.  
  391.   /*
  392.     Open output image file.
  393.   */
  394.   if (*image->filename == '-')
  395.     image->file=stdout;
  396.   else
  397.     image->file=fopen(image->filename,"w");
  398.   if (image->file == (FILE *) NULL)
  399.     {
  400.       (void) fprintf(stderr,"Can't open %s for printing\n",image->filename);
  401.       return(False);
  402.     }
  403.   /*
  404.     Compute image rotation.
  405.   */
  406.   if (((double) image->columns/(double) image->rows) > 1.0)
  407.     rotate=(-90.0);
  408.   else
  409.     rotate=0.0;
  410.   /*
  411.     Compute image scaling.
  412.   */
  413.   image_width=(double) image->columns/PointsPerInch;
  414.   image_height=(double) image->rows/PointsPerInch;
  415.   /*
  416.     Check max page sizes
  417.   */
  418.   max=image_width > image_height ? image_width : image_height;
  419.   if (max > (PageHeight-(2.0*PageBorder)))
  420.     {
  421.       scale=(PageHeight-(2.0*PageBorder))/max;
  422.       image_height*=scale;
  423.       image_width*=scale;
  424.     }
  425.   min=image_width > image_height ? image_height : image_width;
  426.   if (min > (PageWidth-(2.0*PageBorder)))
  427.     {
  428.       scale=(PageWidth-(2.0*PageBorder))/min;
  429.       image_width*=scale;
  430.       image_height*=scale;
  431.     }
  432.   scale_x=image_width*PointsPerInch;
  433.   scale_y=image_height*PointsPerInch;
  434.   translate_x=0.0;
  435.   translate_y=0.0;
  436.   if (rotate == 0.0)
  437.     {
  438.       delta_x=PageWidth-(image_width+(2.0*PageBorder));
  439.       delta_y=PageHeight-(image_height+(2.0*PageBorder));
  440.       if (delta_x >= 0.0)
  441.         translate_x=((delta_x/2.0+PageBorder)* PointsPerInch);
  442.       else
  443.         translate_x=PageBorder*PointsPerInch;
  444.       if (delta_y >= 0.0)
  445.         translate_y=((delta_y/2.0+PageBorder)* PointsPerInch);
  446.       else
  447.         translate_y=PageBorder*PointsPerInch;
  448.     }
  449.   else
  450.     {
  451.       delta_x=PageHeight-(image_width+(2.0*PageBorder));
  452.       delta_y=PageWidth-(image_height+(2.0*PageBorder));
  453.       if (delta_x >= 0.0)
  454.         translate_x=((delta_x/2.0+PageBorder-PageHeight)*PointsPerInch);
  455.       else
  456.         translate_x=(PageBorder-PageHeight)*PointsPerInch;
  457.       if (delta_y >= 0.0)
  458.         translate_y=((delta_y/2.0+PageBorder)*PointsPerInch);
  459.       else
  460.         translate_y=PageBorder*PointsPerInch;
  461.     }
  462.   /*
  463.     Output postscript commands.
  464.   */
  465.   for (q=commands; *q; q++)
  466.     (void) fprintf(image->file,"%s\n",*q);
  467.   /*
  468.     Output image data.
  469.   */
  470.   (void) fprintf(image->file,"%f\n%f %f\n%f %f\n%s\n%d %d\n%d\n",rotate,
  471.     translate_x,translate_y,scale_x,scale_y,image->filename,image->columns,
  472.     image->rows,grayscale);
  473.   p=image->pixels;
  474.   j=0;
  475.   for (i=0; i < image->packets; i++)
  476.   {
  477.     j++;
  478.     if (grayscale)
  479.       {
  480.         gray=Intensity(*p);
  481.         (void) fprintf(image->file,"%02x%02x ",p->length,gray);
  482.         if ((j % 6) == 0)
  483.           (void) fprintf(image->file,"\n");
  484.       }
  485.     else
  486.       {
  487.         red=p->red;
  488.         green=p->green;
  489.         blue=p->blue;
  490.         (void) fprintf(image->file,"%02x%02x%02x%02x ",p->length,red,green,
  491.           blue);
  492.         if ((j % 3) == 0)
  493.           (void) fprintf(image->file,"\n");
  494.       }
  495.     p++;
  496.   }
  497.   (void) fprintf(image->file,"\n\n");
  498.   if (image->file != stdin)
  499.     (void) fclose(image->file);
  500.   return(True);
  501. }
  502.  
  503. /*
  504. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  505. %                                                                             %
  506. %                                                                             %
  507. %                                                                             %
  508. %   R e a d C o l o r m a p                                                   %
  509. %                                                                             %
  510. %                                                                             %
  511. %                                                                             %
  512. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  513. %
  514. %  Function ReadColormap returns the colormap of the image and the
  515. %  number of colors in the colormap.
  516. %
  517. %  The format of the ReadColormap function is:
  518. %
  519. %      number_colors=ReadColormap(display,window_attributes,colors)
  520. %
  521. %  A description of each parameter follows:
  522. %
  523. %    o number_colors:  ReadColormap returns the number of colors in the
  524. %      colormap.
  525. %
  526. %    o display:  Specifies a pointer to the Display structure;  returned from
  527. %      XOpenDisplay.
  528. %
  529. %    o window_attributes:  Specifies a pointer to the window attributes
  530. %      structure;  returned from XGetWindowAttributes.
  531. %
  532. %    o colors:  Specifies a an array of XColor structures.  The colormap
  533. %      red, green, and blue  are returned.
  534. %
  535. %
  536. */
  537. int ReadColormap(display,window_attributes,colors)
  538. Display
  539.   *display;
  540.  
  541. XWindowAttributes
  542.   *window_attributes;
  543.  
  544. XColor
  545.   **colors;
  546. {
  547.   int
  548.     number_colors;
  549.  
  550.   register int
  551.     i;
  552.  
  553.   if (!window_attributes->colormap)
  554.     return(0);
  555.   if (window_attributes->visual->class == TrueColor)
  556.     return(0);
  557.   number_colors=window_attributes->visual->map_entries;
  558.   *colors=(XColor *) malloc((unsigned) (number_colors*sizeof(XColor)));
  559.   if (*colors == (XColor *) NULL)
  560.     {
  561.       (void) fprintf(stderr,"Can't continue, not enough memory.\n");
  562.       exit(1);
  563.     }
  564.   for (i=0; i < number_colors; i++)
  565.     if (window_attributes->visual->class != DirectColor)
  566.       for (i=0; i < number_colors; i++)
  567.       {
  568.         (*colors)[i].pixel=i;
  569.         (*colors)[i].pad=0;
  570.       }
  571.     else
  572.       {
  573.         unsigned long
  574.           blue,
  575.           blue_bit,
  576.           green,
  577.           green_bit,
  578.           red,
  579.           red_bit;
  580.  
  581.         red=0;
  582.         green=0;
  583.         blue=0;
  584.         red_bit=window_attributes->visual->red_mask &
  585.           (~(window_attributes->visual->red_mask)+1);
  586.         green_bit=window_attributes->visual->green_mask &
  587.           (~(window_attributes->visual->green_mask)+1);
  588.         blue_bit=window_attributes->visual->blue_mask &
  589.           (~(window_attributes->visual->blue_mask)+1);
  590.         for (i=0; i < number_colors; i++)
  591.         {
  592.           (*colors)[i].pixel=red | green | blue;
  593.           (*colors)[i].pad=0;
  594.           red+=red_bit;
  595.           if (red > window_attributes->visual->red_mask)
  596.             red=0;
  597.           green+=green_bit;
  598.           if (green > window_attributes->visual->green_mask)
  599.             green=0;
  600.           blue+=blue_bit;
  601.           if (blue > window_attributes->visual->blue_mask)
  602.             blue=0;
  603.         }
  604.       }
  605.   XQueryColors(display,window_attributes->colormap,*colors,number_colors);
  606.   return(number_colors);
  607. }
  608.  
  609. /*
  610. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  611. %                                                                             %
  612. %                                                                             %
  613. %                                                                             %
  614. %   R e a d I m a g e                                                         %
  615. %                                                                             %
  616. %                                                                             %
  617. %                                                                             %
  618. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  619. %
  620. %  Procedure ReadImage reads an image from an X window.
  621. %
  622. %  The format of the ReadImage routine is:
  623. %
  624. %      ReadImage(display,screen,window,borders,image)
  625. %
  626. %  A description of each parameter follows:
  627. %
  628. %    o display:  Specifies a pointer to the Display structure;  returned from
  629. %      XOpenDisplay.
  630. %
  631. %    o screen: Specifies the screen id of the root window.
  632. %
  633. %    o window: Specifies the window id where the image resides.
  634. %
  635. %    o borders: Specifies whether borders pixels are to be saved with
  636. %      the image.
  637. %
  638. %    o image:  specifies a pointer to the Image structure.
  639. %
  640. %
  641. */
  642. static void ReadImage(display,screen,window,borders,image)
  643. Display
  644.   *display;
  645.  
  646. int
  647.   screen;
  648.  
  649. Window
  650.   window;
  651.  
  652. unsigned int
  653.   borders;
  654.  
  655. Image
  656.   *image;
  657. {
  658.   int
  659.     display_width,
  660.     display_height,
  661.     x,
  662.     y;
  663.  
  664.   register int 
  665.     i;
  666.  
  667.   register RunlengthPacket
  668.     *p;
  669.  
  670.   register unsigned int
  671.     pixel;
  672.  
  673.   Window
  674.     child;
  675.  
  676.   XColor
  677.     *colors;
  678.  
  679.   XImage
  680.     *ximage;
  681.  
  682.   XWindowAttributes
  683.     window_attributes;
  684.  
  685.   /*
  686.     Inform the user not to alter the screen.
  687.   */
  688.   XBell(display,0);
  689.   /*
  690.     Get the attributes of the window being dumped.
  691.   */
  692.   if(!XGetWindowAttributes(display,window,&window_attributes))
  693.     {
  694.       (void) fprintf(stderr,
  695.         "Can't continue, unable to get target window attributes.\n");
  696.       exit(1);
  697.     }
  698.   XTranslateCoordinates(display,window,XRootWindow(display,screen),0,0,&x,&y,
  699.     &child);
  700.   window_attributes.x=x;
  701.   window_attributes.y=y;
  702.   image->columns=window_attributes.width;
  703.   image->rows=window_attributes.height;
  704.   if (borders)
  705.     {
  706.       x-=window_attributes.border_width;
  707.       y-=window_attributes.border_width;
  708.       image->columns+=2*window_attributes.border_width;
  709.       image->rows+=2*window_attributes.border_width;
  710.     }
  711.   /*
  712.     clip to window
  713.   */
  714.   if (x < 0)
  715.     {
  716.       image->columns+=x;
  717.       x=0;
  718.     }
  719.   if (y < 0)
  720.     {
  721.       image->rows+=y;
  722.       y=0;
  723.     }
  724.   display_width=DisplayWidth(display,screen);
  725.   display_height=DisplayHeight(display,screen);
  726.   if ((x+image->columns) > display_width)
  727.     image->columns=display_width-x;
  728.   if ((y+image->rows) > display_height)
  729.     image->rows=display_height-y;
  730.   /*
  731.     Get image from window with XGetImage.
  732.   */
  733.   x-=window_attributes.x;
  734.   y-=window_attributes.y;
  735.   ximage=XGetImage(display,window,x,y,image->columns,image->rows,AllPlanes,
  736.     ZPixmap);
  737.   if (!ximage)
  738.     {
  739.       (void) fprintf(stderr,
  740.         "Can't continue, unable to get image at %dx%d+%d+%d\n",image->columns,
  741.           image->rows,x,y);
  742.       exit(1);
  743.      }
  744.   image->colors=ReadColormap(display,&window_attributes,&colors);
  745.   XBell(display,0);
  746.   XBell(display,0);
  747.   XFlush(display);
  748.   /*
  749.     Convert image to MIFF format.
  750.   */
  751.   image->comments=(char *) NULL;
  752.   image->class=(ximage->depth <= 16 ? PseudoClass : DirectClass);
  753.   image->compression=RunlengthEncodedCompression;
  754.   image->scene=0;
  755.   image->packets=image->columns*image->rows;
  756.   image->pixels=(RunlengthPacket *)
  757.     malloc((unsigned) (image->packets*sizeof(RunlengthPacket)));
  758.   if (image->pixels == (RunlengthPacket *) NULL)
  759.     {
  760.       (void) fprintf(stderr,"Can't image to postscript, not enough memory.\n");
  761.       exit(1);
  762.     }
  763.   p=image->pixels;
  764.   if (image->class == PseudoClass)
  765.     {
  766.       /*
  767.         Image is pseudo-color.
  768.       */
  769.       image->colormap=(ColorPacket *)
  770.         malloc((unsigned) (image->colors*sizeof(ColorPacket)));
  771.       if (image->colormap == (ColorPacket *) NULL)
  772.         {
  773.           (void) fprintf(stderr,"Can't continue, not enough memory.\n");
  774.           exit(1);
  775.         }
  776.       for (i=0; i < image->colors; i++)
  777.       {
  778.         image->colormap[i].red=colors[i].red >> 8;
  779.         image->colormap[i].green=colors[i].green >> 8;
  780.         image->colormap[i].blue=colors[i].blue >> 8;
  781.       }
  782.       for (y=0; y < image->rows; y++)
  783.       {
  784.         for (x=0; x < image->columns; x++)
  785.         {
  786.           pixel=XGetPixel(ximage,x,y);
  787.           p->red=(unsigned char) (colors[pixel].red >> 8);
  788.           p->green=(unsigned char) (colors[pixel].green >> 8);
  789.           p->blue=(unsigned char) (colors[pixel].blue >> 8);
  790.           p->index=(short unsigned int) pixel;
  791.           p->length=0;
  792.           p++;
  793.         }
  794.       }
  795.     }
  796.   else
  797.     {
  798.       register unsigned long
  799.         color,
  800.         index;
  801.  
  802.       unsigned long
  803.         blue_mask,
  804.         blue_shift,
  805.         green_mask,
  806.         green_shift,
  807.         red_mask,
  808.         red_shift;
  809.  
  810.       /*
  811.         Determine shift and mask for red, green, and blue.
  812.       */
  813.       red_mask=window_attributes.visual->red_mask;
  814.       red_shift=0;
  815.       while (!(red_mask & 0x01))
  816.       {
  817.         red_mask>>=1;
  818.         red_shift++;
  819.       }
  820.       green_mask=window_attributes.visual->green_mask;
  821.       green_shift=0;
  822.       while (!(green_mask & 0x01))
  823.       {
  824.         green_mask>>=1;
  825.         green_shift++;
  826.       }
  827.       blue_mask=window_attributes.visual->blue_mask;
  828.       blue_shift=0;
  829.       while (!(blue_mask & 0x01))
  830.       {
  831.         blue_mask>>=1;
  832.         blue_shift++;
  833.       }
  834.       /*
  835.         Convert DirectColor or TrueColor image to DirectClass.
  836.       */
  837.       if ((image->colors > 0) && 
  838.           (window_attributes.visual->class == DirectColor))
  839.         for (y=0; y < image->rows; y++)
  840.         {
  841.           for (x=0; x < image->columns; x++)
  842.           {
  843.             pixel=XGetPixel(ximage,x,y);
  844.             index=(pixel >> red_shift) & red_mask;
  845.             p->red=(unsigned char) (colors[index].red >> 8);
  846.             index=(pixel >> green_shift) & green_mask;
  847.             p->green=(unsigned char) (colors[index].green >> 8);
  848.             index=(pixel >> blue_shift) & blue_mask;
  849.             p->blue=(unsigned char) (colors[index].blue >> 8);
  850.             p->index=0;
  851.             p->length=0;
  852.             p++;
  853.           }
  854.         }
  855.       else
  856.         for (y=0; y < image->rows; y++)
  857.         {
  858.           for (x=0; x < image->columns; x++)
  859.           {
  860.             pixel=XGetPixel(ximage,x,y);
  861.             color=(pixel >> red_shift) & red_mask;
  862.             p->red=(unsigned char) 
  863.               ((((unsigned long) color*65535)/red_mask) >> 8);
  864.             color=(pixel >> green_shift) & green_mask;
  865.             p->green=(unsigned char) 
  866.               ((((unsigned long) color*65535)/green_mask) >> 8);
  867.             color=(pixel >> blue_shift) & blue_mask;
  868.             p->blue=(unsigned char) 
  869.               ((((unsigned long) color*65535)/blue_mask) >> 8);
  870.             p->index=0;
  871.             p->length=0;
  872.             p++;
  873.           }
  874.         }
  875.     }
  876.   /*
  877.     Free image and colormap.
  878.   */
  879.   if (image->colors > 0)
  880.     free((char *) colors);
  881.   XDestroyImage(ximage);
  882. }
  883.  
  884. /*
  885. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  886. %                                                                             %
  887. %                                                                             %
  888. %                                                                             %
  889. %   S e l e c t W i n d o w                                                   %
  890. %                                                                             %
  891. %                                                                             %
  892. %                                                                             %
  893. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  894. %
  895. %  Function SelectWindow allows a  user to select a window using the mouse.
  896. %
  897. %  The format of the SelectWindow function is:
  898. %
  899. %      window=SelectWindow(display,screen)
  900. %
  901. %  A description of each parameter follows:
  902. %
  903. %    o window:  SelectWindow returns the window id.
  904. %
  905. %    o display:  Specifies a pointer to the Display structure;  returned from
  906. %      XOpenDisplay.
  907. %
  908. %    o screen: Specifies the screen id of the root window.
  909. %
  910. %
  911. */
  912. Window SelectWindow(display,screen)
  913. Display
  914.   *display;
  915.  
  916. int
  917.   screen;
  918. {
  919.   Cursor
  920.     cursor;
  921.  
  922.   int
  923.     status;
  924.  
  925.   unsigned int
  926.     presses;
  927.  
  928.   Window
  929.     target_window;
  930.  
  931.   XEvent
  932.     event;
  933.  
  934.   /*
  935.     Make the target cursor.
  936.   */
  937.   cursor=XCreateFontCursor(display,XC_crosshair);
  938.   /*
  939.     Grab the pointer using target cursor.
  940.   */
  941.   status=XGrabPointer(display,XRootWindow(display,screen),False,
  942.     ButtonPressMask | ButtonReleaseMask,GrabModeSync,GrabModeAsync,
  943.     XRootWindow(display,screen),cursor,CurrentTime);
  944.   if (status != GrabSuccess)
  945.     {
  946.       (void) fprintf(stderr,"Can't continue, cannot grab the mouse.\n");
  947.       exit(1);
  948.     }
  949.   /*
  950.     Select a window.
  951.   */
  952.   target_window=None;
  953.   presses=0;
  954.   while ((target_window == None) || (presses != 0))
  955.   {
  956.     /*
  957.       Allow another event.
  958.     */
  959.     XAllowEvents(display,SyncPointer,CurrentTime);
  960.     XWindowEvent(display,XRootWindow(display,screen),ButtonPressMask |
  961.       ButtonReleaseMask,&event);
  962.     switch (event.type)
  963.     {
  964.       case ButtonPress:
  965.       {
  966.         if (target_window == None)
  967.           {
  968.             target_window=event.xbutton.subwindow;
  969.             if (target_window == None)
  970.               target_window=XRootWindow(display,screen);
  971.           }
  972.         presses++;
  973.         break;
  974.       }
  975.       case ButtonRelease:
  976.       {
  977.     if (presses > 0)
  978.         presses--;
  979.         break;
  980.       }
  981.       default:
  982.         break;
  983.     }
  984.   }
  985.   XUngrabPointer(display,CurrentTime);
  986.   return(target_window);
  987. }
  988.  
  989. /*
  990. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  991. %                                                                             %
  992. %                                                                             %
  993. %                                                                             %
  994. %   U s a g e                                                                 %
  995. %                                                                             %
  996. %                                                                             %
  997. %                                                                             %
  998. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  999. %
  1000. %  Procedure Usage displays the program usage;
  1001. %
  1002. %  The format of the Usage routine is:
  1003. %
  1004. %      Usage(program_name,message)
  1005. %
  1006. %  A description of each parameter follows:
  1007. %
  1008. %    program_name:  Specifies the name of this program.
  1009. %
  1010. %    message:  Specifies a specific message to display to the user.
  1011. %
  1012. */
  1013. void Usage(program_name,message)
  1014. char
  1015.   *message,
  1016.   *program_name;
  1017. {
  1018.   char
  1019.     **p;
  1020.  
  1021.   static char
  1022.     *options[]=
  1023.     {
  1024.       "+border        include image borders in the output image",
  1025.       "-display name  X server to contact",
  1026.       "+frame         include window manager frame",
  1027.       "+grayscale     print image as gray scale colors",
  1028.       "-id number     select window with this id",
  1029.       "-name name     select window with this name",
  1030.       "-root          select root window",
  1031.       NULL
  1032.     };
  1033.   if (message)
  1034.     (void) fprintf(stderr,"Can't continue, %s\n\n",message);
  1035.   (void) fprintf(stderr,"Usage: %s [options ...] file\n",program_name);
  1036.   (void) fprintf(stderr,"\nWhere options include:\n");
  1037.   for (p=options; *p; p++)
  1038.     (void) fprintf(stderr,"  %s\n",*p);
  1039.   (void) fprintf(stderr,
  1040.     "\nChange '+' to '-' in any option above to reverse its effect.\n");
  1041.   (void) fprintf(stderr,
  1042.     "For example, -borders means do not include image borders.\n");
  1043.   (void) fprintf(stderr,"\nSpecify 'file' as '-' for standard output.\n");
  1044.   exit(1);
  1045. }
  1046.  
  1047. /*
  1048. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1049. %                                                                             %
  1050. %                                                                             %
  1051. %                                                                             %
  1052. %   W i n d o w B y N a m e                                                   %
  1053. %                                                                             %
  1054. %                                                                             %
  1055. %                                                                             %
  1056. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1057. %
  1058. %  Function WindowByName locates a window with a given name on a display.
  1059. %  If no window with the given name is found, 0 is returned. If more than
  1060. %  one window has the given name, the first one is returned.  Only root and
  1061. %  its children are searched.
  1062. %
  1063. %  The format of the WindowByName function is:
  1064. %
  1065. %      window=WindowByName(display,root,name)
  1066. %
  1067. %
  1068. %  A description of each parameter follows:
  1069. %
  1070. %    o window:  WindowByName returns the window id.
  1071. %
  1072. %    o display:  Specifies a pointer to the Display structure;  returned from
  1073. %      XOpenDisplay.
  1074. %
  1075. %    o root:  Specifies a pointer to a window.
  1076. %
  1077. %    o name:  Specifies the name of the window to locate.
  1078. %
  1079. %
  1080. */
  1081. Window WindowByName(display,root,name)
  1082. Display
  1083.   *display;
  1084.  
  1085. Window
  1086.   root;
  1087.  
  1088. char
  1089.   *name;
  1090. {
  1091.   char
  1092.     *window_name;
  1093.  
  1094.   register int
  1095.     i;
  1096.  
  1097.   unsigned int
  1098.     number_children;
  1099.  
  1100.   Window
  1101.     *children,
  1102.     child,
  1103.     window;
  1104.  
  1105.   if (XFetchName(display,root,&window_name) && !strcmp(window_name,name))
  1106.     return(root);
  1107.   if (!XQueryTree(display,root,&child,&child,&children,&number_children))
  1108.     return(0);
  1109.   window=0;
  1110.   for (i=0; i < number_children; i++)
  1111.   {
  1112.     /*
  1113.       Search each child and their children.
  1114.     */
  1115.     window=WindowByName(display,children[i],name);
  1116.     if (window)
  1117.       break;
  1118.   }
  1119.   if (children)
  1120.     XFree((char *) children);
  1121.   return(window);
  1122. }
  1123.  
  1124. /*
  1125. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1126. %                                                                             %
  1127. %                                                                             %
  1128. %                                                                             %
  1129. %   W i n d o w B y P r o p e r y                                             %
  1130. %                                                                             %
  1131. %                                                                             %
  1132. %                                                                             %
  1133. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1134. %
  1135. %  Function WindowByProperty locates a child window with a given property.
  1136. %  If no window with the given name is found, 0 is returned.  If more than
  1137. %  one window has the given property, the first one is returned.  Only the 
  1138. %  window specified and its subwindows are searched.
  1139. %
  1140. %  The format of the WindowByProperty function is:
  1141. %
  1142. %      child=WindowByName(display,window,property)
  1143. %
  1144. %
  1145. %  A description of each parameter follows:
  1146. %
  1147. %    o child:  WindowByProperty returns the window id with the specified
  1148. %      property.  If no windows are found, WindowByProperty returns 0.
  1149. %
  1150. %    o display:  Specifies a pointer to the Display structure;  returned from
  1151. %      XOpenDisplay.
  1152. %
  1153. %    o property:  Specifies the property of the window to locate.
  1154. %
  1155. %
  1156. */
  1157. Window WindowByProperty(display,window,property)
  1158. Display 
  1159.   *display;
  1160.  
  1161. Window 
  1162.   window;
  1163.  
  1164. Atom 
  1165.   property;
  1166. {
  1167.   Atom 
  1168.     type;
  1169.  
  1170.   int 
  1171.     format;
  1172.  
  1173.   unsigned char 
  1174.     *data;
  1175.  
  1176.   unsigned int 
  1177.     i,
  1178.     number_children;
  1179.  
  1180.   unsigned long 
  1181.     after,
  1182.     number_items;
  1183.  
  1184.   Window 
  1185.     *children,
  1186.     child,
  1187.     parent,
  1188.     root;
  1189.  
  1190.   if (!XQueryTree(display,window,&root,&parent,&children,&number_children))
  1191.     return((Window) NULL);
  1192.   type=None;
  1193.   child=(Window) NULL;
  1194.   for (i=0; (i < number_children) && !child; i++) 
  1195.   {
  1196.     XGetWindowProperty(display,children[i],property,0,0,False,AnyPropertyType, 
  1197.       &type,&format,&number_items,&after,&data);
  1198.     if (type)
  1199.       child=children[i];
  1200.   }
  1201.   for (i = 0; (i < number_children) && !child; i++)
  1202.     child=WindowByProperty(display,children[i],property);
  1203.   if (children) 
  1204.     XFree((char *) children);
  1205.   return(child);
  1206. }
  1207.  
  1208. /*
  1209. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1210. %                                                                             %
  1211. %                                                                             %
  1212. %                                                                             %
  1213. %    M a i n                                                                  %
  1214. %                                                                             %
  1215. %                                                                             %
  1216. %                                                                             %
  1217. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1218. %
  1219. %
  1220. */
  1221. main(argc,argv)
  1222. int
  1223.   argc;
  1224.  
  1225. char
  1226.   *argv[];
  1227. {
  1228.   char
  1229.     *option,
  1230.     *program_name,
  1231.     *server_name;
  1232.  
  1233.   Display
  1234.     *display;
  1235.  
  1236.   Image
  1237.     *image;
  1238.  
  1239.   int
  1240.     borders,
  1241.     frame,
  1242.     i,
  1243.     screen;
  1244.  
  1245.   unsigned int
  1246.     grayscale,
  1247.     PrintImage();
  1248.  
  1249.   Window
  1250.     target_window;
  1251.  
  1252.   /*
  1253.     Connect to X server.
  1254.   */
  1255.   program_name=argv[0];
  1256.   server_name=(char *) NULL;
  1257.   for (i=1; i < argc; i++)
  1258.   {
  1259.     /*
  1260.       Check command line for server name.
  1261.     */
  1262.     option=argv[i];
  1263.     if ((strlen(option) > 1) && ((*option == '-') || (*option == '+')))
  1264.       if (strncmp("dis",option+1,3) == 0)
  1265.         {
  1266.           /*
  1267.             User specified server name.
  1268.           */
  1269.           i++;
  1270.           if (i == argc)
  1271.             Usage(program_name,"missing server name on -display");
  1272.           server_name=argv[i];
  1273.           break;
  1274.         }
  1275.   }
  1276.   display=XOpenDisplay(server_name);
  1277.   if (display == (Display *) NULL)
  1278.     {
  1279.       (void) fprintf(stderr,"Can't continue, unable to connect to %s.\n",
  1280.         XDisplayName(server_name));
  1281.       exit(1);
  1282.     }
  1283.   screen=XDefaultScreen(display);
  1284.   /*
  1285.     Get X defaults.
  1286.   */
  1287.   option=XGetDefault(display,program_name,"borders");
  1288.   borders=IsTrue(option);
  1289.   option=XGetDefault(display,program_name,"frame");
  1290.   frame=IsTrue(option);
  1291.   option=XGetDefault(display,program_name,"grayscale");
  1292.   grayscale=IsTrue(option);
  1293.   /*
  1294.     Check command syntax.
  1295.   */
  1296.   target_window=(Window) NULL;
  1297.   for (i=1; i < argc-1; i++)
  1298.   {
  1299.     option=argv[i];
  1300.     if ((strlen(option) > 1) && ((*option == '-') || (*option == '+')))
  1301.       switch(*(option+1))
  1302.       {
  1303.         case 'b':
  1304.         {
  1305.           borders=(*option == '+');
  1306.           break;
  1307.         }
  1308.         case 'h':
  1309.         {
  1310.           Usage(program_name,(char *) NULL);
  1311.           break;
  1312.         }
  1313.         case 'f':
  1314.         {
  1315.           frame=(*option == '+');
  1316.           break;
  1317.         }
  1318.         case 'g':
  1319.         {
  1320.           grayscale=(*option == '+');
  1321.           break;
  1322.         }
  1323.         case 'i':
  1324.         {
  1325.           i++;
  1326.           if (i == argc)
  1327.             Usage(program_name,"missing id on -id");
  1328.           option=argv[i];
  1329.           target_window=(Window) strtol(option,(char **) NULL,0);
  1330.           break;
  1331.         }
  1332.         case 'n':
  1333.         {
  1334.           i++;
  1335.           if (i == argc)
  1336.             Usage(program_name,"missing name on -name");
  1337.           option=argv[i]; 
  1338.           target_window=
  1339.             WindowByName(display,XRootWindow(display,screen),option);
  1340.           if (target_window == (Window) NULL)
  1341.             (void) fprintf(stderr,"No window with name %s exists!\n",option);
  1342.           break;
  1343.         }
  1344.         case 'r':
  1345.         {
  1346.           target_window=XRootWindow(display,screen);
  1347.           break;
  1348.         }
  1349.         default:
  1350.           Usage(program_name,(char *) NULL);
  1351.       }
  1352.   }
  1353.   if (argc == 1)
  1354.     Usage(program_name,(char *) NULL);
  1355.   if (!target_window)
  1356.     target_window=SelectWindow(display,screen);
  1357.   if (!frame)
  1358.     if (target_window != XRootWindow(display,screen))
  1359.       target_window=ClientWindow(display,target_window);
  1360.   image=(Image *) malloc(sizeof(Image));
  1361.   (void) strcpy(image->filename,argv[argc-1]);
  1362.   ReadImage(display,screen,target_window,(unsigned int) borders,image);
  1363.   (void) fprintf(stderr,"%s %dx%d\n",image->filename,image->columns,
  1364.     image->rows);
  1365.   (void) PrintImage(image,grayscale);
  1366.   return(True);
  1367. }
  1368.