home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 1 / 1430 / XtoPS.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-12-28  |  39.5 KB  |  1,393 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. static 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. static 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.   unsigned int
  392.     CompressImage();
  393.  
  394.   /*
  395.     Open output image file.
  396.   */
  397.   if (*image->filename == '-')
  398.     image->file=stdout;
  399.   else
  400.     image->file=fopen(image->filename,"w");
  401.   if (image->file == (FILE *) NULL)
  402.     {
  403.       (void) fprintf(stderr,"Can't open %s for printing\n",image->filename);
  404.       return(False);
  405.     }
  406.   /*
  407.     Compute image rotation.
  408.   */
  409.   if (((double) image->columns/(double) image->rows) > 1.0)
  410.     rotate=(-90.0);
  411.   else
  412.     rotate=0.0;
  413.   /*
  414.     Compute image scaling.
  415.   */
  416.   image_width=(double) image->columns/PointsPerInch;
  417.   image_height=(double) image->rows/PointsPerInch;
  418.   /*
  419.     Check max page sizes
  420.   */
  421.   max=image_width > image_height ? image_width : image_height;
  422.   if (max > (PageHeight-(2.0*PageBorder)))
  423.     {
  424.       scale=(PageHeight-(2.0*PageBorder))/max;
  425.       image_height*=scale;
  426.       image_width*=scale;
  427.     }
  428.   min=image_width > image_height ? image_height : image_width;
  429.   if (min > (PageWidth-(2.0*PageBorder)))
  430.     {
  431.       scale=(PageWidth-(2.0*PageBorder))/min;
  432.       image_width*=scale;
  433.       image_height*=scale;
  434.     }
  435.   scale_x=image_width*PointsPerInch;
  436.   scale_y=image_height*PointsPerInch;
  437.   translate_x=0.0;
  438.   translate_y=0.0;
  439.   if (rotate == 0.0)
  440.     {
  441.       delta_x=PageWidth-(image_width+(2.0*PageBorder));
  442.       delta_y=PageHeight-(image_height+(2.0*PageBorder));
  443.       if (delta_x >= 0.0)
  444.         translate_x=((delta_x/2.0+PageBorder)* PointsPerInch);
  445.       else
  446.         translate_x=PageBorder*PointsPerInch;
  447.       if (delta_y >= 0.0)
  448.         translate_y=((delta_y/2.0+PageBorder)* PointsPerInch);
  449.       else
  450.         translate_y=PageBorder*PointsPerInch;
  451.     }
  452.   else
  453.     {
  454.       delta_x=PageHeight-(image_width+(2.0*PageBorder));
  455.       delta_y=PageWidth-(image_height+(2.0*PageBorder));
  456.       if (delta_x >= 0.0)
  457.         translate_x=((delta_x/2.0+PageBorder-PageHeight)*PointsPerInch);
  458.       else
  459.         translate_x=(PageBorder-PageHeight)*PointsPerInch;
  460.       if (delta_y >= 0.0)
  461.         translate_y=((delta_y/2.0+PageBorder)*PointsPerInch);
  462.       else
  463.         translate_y=PageBorder*PointsPerInch;
  464.     }
  465.   /*
  466.     Output postscript commands.
  467.   */
  468.   for (q=commands; *q; q++)
  469.     (void) fprintf(image->file,"%s\n",*q);
  470.   /*
  471.     Output image data.
  472.   */
  473.   (void) fprintf(image->file,"%f\n%f %f\n%f %f\n%s\n%d %d\n%d\n",rotate,
  474.     translate_x,translate_y,scale_x,scale_y,image->filename,image->columns,
  475.     image->rows,grayscale);
  476.   p=image->pixels;
  477.   j=0;
  478.   for (i=0; i < image->packets; i++)
  479.   {
  480.     j++;
  481.     if (grayscale)
  482.       {
  483.         gray=Intensity(*p);
  484.         (void) fprintf(image->file,"%02x%02x ",p->length,gray);
  485.         if ((j % 6) == 0)
  486.           (void) fprintf(image->file,"\n");
  487.       }
  488.     else
  489.       {
  490.         red=p->red;
  491.         green=p->green;
  492.         blue=p->blue;
  493.         (void) fprintf(image->file,"%02x%02x%02x%02x ",p->length,red,green,
  494.           blue);
  495.         if ((j % 3) == 0)
  496.           (void) fprintf(image->file,"\n");
  497.       }
  498.     p++;
  499.   }
  500.   (void) fprintf(image->file,"\n\n");
  501.   if (image->file != stdin)
  502.     (void) fclose(image->file);
  503.   return(True);
  504. }
  505.  
  506. /*
  507. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  508. %                                                                             %
  509. %                                                                             %
  510. %                                                                             %
  511. %   R e a d C o l o r m a p                                                   %
  512. %                                                                             %
  513. %                                                                             %
  514. %                                                                             %
  515. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  516. %
  517. %  Function ReadColormap returns the colormap of the image and the
  518. %  number of colors in the colormap.
  519. %
  520. %  The format of the ReadColormap function is:
  521. %
  522. %      number_colors=ReadColormap(display,window_attributes,colors)
  523. %
  524. %  A description of each parameter follows:
  525. %
  526. %    o number_colors:  ReadColormap returns the number of colors in the
  527. %      colormap.
  528. %
  529. %    o display:  Specifies a pointer to the Display structure;  returned from
  530. %      XOpenDisplay.
  531. %
  532. %    o window_attributes:  Specifies a pointer to the window attributes
  533. %      structure;  returned from XGetWindowAttributes.
  534. %
  535. %    o colors:  Specifies a an array of XColor structures.  The colormap
  536. %      red, green, and blue  are returned.
  537. %
  538. %
  539. */
  540. static int ReadColormap(display,window_attributes,colors)
  541. Display
  542.   *display;
  543.  
  544. XWindowAttributes
  545.   *window_attributes;
  546.  
  547. XColor
  548.   **colors;
  549. {
  550.   int
  551.     number_colors;
  552.  
  553.   register int
  554.     i;
  555.  
  556.   if (!window_attributes->colormap)
  557.     return(0);
  558.   if (window_attributes->visual->class == TrueColor)
  559.     return(0);
  560.   number_colors=window_attributes->visual->map_entries;
  561.   *colors=(XColor *) malloc((unsigned) (number_colors*sizeof(XColor)));
  562.   if (*colors == (XColor *) NULL)
  563.     {
  564.       (void) fprintf(stderr,"Can't continue, not enough memory.\n");
  565.       exit(1);
  566.     }
  567.   for (i=0; i < number_colors; i++)
  568.     if (window_attributes->visual->class != DirectColor)
  569.       for (i=0; i < number_colors; i++)
  570.       {
  571.         (*colors)[i].pixel=i;
  572.         (*colors)[i].pad=0;
  573.       }
  574.     else
  575.       {
  576.         unsigned long
  577.           blue,
  578.           blue_bit,
  579.           green,
  580.           green_bit,
  581.           red,
  582.           red_bit;
  583.  
  584.         red=0;
  585.         green=0;
  586.         blue=0;
  587.         red_bit=window_attributes->visual->red_mask &
  588.           (~(window_attributes->visual->red_mask)+1);
  589.         green_bit=window_attributes->visual->green_mask &
  590.           (~(window_attributes->visual->green_mask)+1);
  591.         blue_bit=window_attributes->visual->blue_mask &
  592.           (~(window_attributes->visual->blue_mask)+1);
  593.         for (i=0; i < number_colors; i++)
  594.         {
  595.           (*colors)[i].pixel=red | green | blue;
  596.           (*colors)[i].pad=0;
  597.           red+=red_bit;
  598.           if (red > window_attributes->visual->red_mask)
  599.             red=0;
  600.           green+=green_bit;
  601.           if (green > window_attributes->visual->green_mask)
  602.             green=0;
  603.           blue+=blue_bit;
  604.           if (blue > window_attributes->visual->blue_mask)
  605.             blue=0;
  606.         }
  607.       }
  608.   XQueryColors(display,window_attributes->colormap,*colors,number_colors);
  609.   return(number_colors);
  610. }
  611.  
  612. /*
  613. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  614. %                                                                             %
  615. %                                                                             %
  616. %                                                                             %
  617. %   R e a d I m a g e                                                         %
  618. %                                                                             %
  619. %                                                                             %
  620. %                                                                             %
  621. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  622. %
  623. %  Procedure ReadImage reads an image from an X window.
  624. %
  625. %  The format of the ReadImage routine is:
  626. %
  627. %      ReadImage(display,screen,window,borders,image)
  628. %
  629. %  A description of each parameter follows:
  630. %
  631. %    o display:  Specifies a pointer to the Display structure;  returned from
  632. %      XOpenDisplay.
  633. %
  634. %    o screen: Specifies the screen id of the root window.
  635. %
  636. %    o window: Specifies the window id where the image resides.
  637. %
  638. %    o borders: Specifies whether borders pixels are to be saved with
  639. %      the image.
  640. %
  641. %    o image:  specifies a pointer to the Image structure.
  642. %
  643. %
  644. */
  645. static void ReadImage(display,screen,window,borders,image)
  646. Display
  647.   *display;
  648.  
  649. int
  650.   screen;
  651.  
  652. Window
  653.   window;
  654.  
  655. unsigned int
  656.   borders;
  657.  
  658. Image
  659.   *image;
  660. {
  661.   char
  662.     *window_name;
  663.  
  664.   int
  665.     display_width,
  666.     display_height,
  667.     x,
  668.     y;
  669.  
  670.   register int 
  671.     i;
  672.  
  673.   register unsigned int
  674.     pixel;
  675.  
  676.   unsigned char
  677.     red,
  678.     green,
  679.     blue;
  680.  
  681.   Window
  682.     child;
  683.  
  684.   XColor
  685.     *colors;
  686.  
  687.   XImage
  688.     *ximage;
  689.  
  690.   XWindowAttributes
  691.     window_attributes;
  692.  
  693.   /*
  694.     Inform the user not to alter the screen.
  695.   */
  696.   XBell(display,0);
  697.   /*
  698.     Get the attributes of the window being dumped.
  699.   */
  700.   if(!XGetWindowAttributes(display,window,&window_attributes))
  701.     {
  702.       (void) fprintf(stderr,
  703.         "Can't continue, unable to get target window attributes.\n");
  704.       exit(1);
  705.     }
  706.   XTranslateCoordinates(display,window,XRootWindow(display,screen),0,0,&x,&y,
  707.     &child);
  708.   window_attributes.x=x;
  709.   window_attributes.y=y;
  710.   image->columns=window_attributes.width;
  711.   image->rows=window_attributes.height;
  712.   if (borders)
  713.     {
  714.       /*
  715.         Do not include border in image.
  716.       */
  717.       x-=window_attributes.border_width;
  718.       y-=window_attributes.border_width;
  719.       image->columns+=2*window_attributes.border_width;
  720.       image->rows+=2*window_attributes.border_width;
  721.     }
  722.   /*
  723.     clip to window
  724.   */
  725.   if (x < 0)
  726.     {
  727.       image->columns+=x;
  728.       x=0;
  729.     }
  730.   if (y < 0)
  731.     {
  732.       image->rows+=y;
  733.       y=0;
  734.     }
  735.   display_width=DisplayWidth(display,screen);
  736.   display_height=DisplayHeight(display,screen);
  737.   if ((x+image->columns) > display_width)
  738.     image->columns=display_width-x;
  739.   if ((y+image->rows) > display_height)
  740.     image->rows=display_height-y;
  741.   /*
  742.     Get image from window with XGetImage.
  743.   */
  744.   x-=window_attributes.x;
  745.   y-=window_attributes.y;
  746.   ximage=XGetImage(display,window,x,y,image->columns,image->rows,AllPlanes,
  747.     ZPixmap);
  748.   if (!ximage)
  749.     {
  750.       (void) fprintf(stderr,
  751.         "Can't continue, unable to get image at %dx%d+%d+%d\n",image->columns,
  752.           image->rows,x,y);
  753.       exit(1);
  754.      }
  755.   image->colors=ReadColormap(display,&window_attributes,&colors);
  756.   XBell(display,0);
  757.   XBell(display,0);
  758.   XFlush(display);
  759.   /*
  760.     Convert image to MIFF format.
  761.   */
  762.   image->comments=(char *) NULL;
  763.   if (XFetchName(display,window,&window_name))
  764.     {
  765.       image->comments=(char *) malloc((unsigned int) (strlen(window_name)+256));
  766.       if (image->comments == (char *) NULL)
  767.         {
  768.           (void) fprintf(stderr,
  769.             "Can't import X11 window, not enough memory.\n");
  770.           exit(1);
  771.         }
  772.       (void) strcpy(image->comments,"  Imported from X11 window: ");
  773.       (void) strcat(image->comments,window_name);
  774.     }
  775.   if ((window_attributes.visual->class == TrueColor) ||
  776.       (window_attributes.visual->class == DirectColor))
  777.     image->class=DirectClass;
  778.   else
  779.     image->class=PseudoClass;
  780.   image->compression=RunlengthEncodedCompression;
  781.   image->scene=0;
  782.   image->pixels=(RunlengthPacket *)
  783.     malloc(image->columns*image->rows*sizeof(RunlengthPacket));
  784.   if (image->pixels == (RunlengthPacket *) NULL)
  785.     {
  786.       (void) fprintf(stderr,"Can't import X11 window, not enough memory.\n");
  787.       exit(1);
  788.     }
  789.   image->channel=InitializeChannel(image->pixels);
  790.   image->packets=0;
  791.   if (image->class == PseudoClass)
  792.     {
  793.       /*
  794.         Image is pseudo-color.
  795.       */
  796.       image->colormap=(ColorPacket *)
  797.         malloc((unsigned) (image->colors*sizeof(ColorPacket)));
  798.       if (image->colormap == (ColorPacket *) NULL)
  799.         {
  800.           (void) fprintf(stderr,"Can't continue, not enough memory.\n");
  801.           exit(1);
  802.         }
  803.       for (i=0; i < image->colors; i++)
  804.       {
  805.         image->colormap[i].red=colors[i].red >> 8;
  806.         image->colormap[i].green=colors[i].green >> 8;
  807.         image->colormap[i].blue=colors[i].blue >> 8;
  808.       }
  809.       for (y=0; y < image->rows; y++)
  810.       {
  811.         for (x=0; x < image->columns; x++)
  812.         {
  813.           pixel=XGetPixel(ximage,x,y);
  814.           image->packets+=WritePacket(image->channel,
  815.             (unsigned char) (colors[pixel].red >> 8),
  816.             (unsigned char) (colors[pixel].green >> 8),
  817.             (unsigned char) (colors[pixel].blue >> 8),
  818.             (unsigned short) pixel,1);
  819.         }
  820.       }
  821.     }
  822.   else
  823.     {
  824.       register unsigned long
  825.         color,
  826.         index;
  827.  
  828.       unsigned long
  829.         blue_mask,
  830.         blue_shift,
  831.         green_mask,
  832.         green_shift,
  833.         red_mask,
  834.         red_shift;
  835.  
  836.       /*
  837.         Determine shift and mask for red, green, and blue.
  838.       */
  839.       red_mask=window_attributes.visual->red_mask;
  840.       red_shift=0;
  841.       while (!(red_mask & 0x01))
  842.       {
  843.         red_mask>>=1;
  844.         red_shift++;
  845.       }
  846.       green_mask=window_attributes.visual->green_mask;
  847.       green_shift=0;
  848.       while (!(green_mask & 0x01))
  849.       {
  850.         green_mask>>=1;
  851.         green_shift++;
  852.       }
  853.       blue_mask=window_attributes.visual->blue_mask;
  854.       blue_shift=0;
  855.       while (!(blue_mask & 0x01))
  856.       {
  857.         blue_mask>>=1;
  858.         blue_shift++;
  859.       }
  860.       /*
  861.         Convert DirectColor or TrueColor image to DirectClass.
  862.       */
  863.       if ((image->colors > 0) && 
  864.           (window_attributes.visual->class == DirectColor))
  865.         for (y=0; y < image->rows; y++)
  866.         {
  867.           for (x=0; x < image->columns; x++)
  868.           {
  869.             pixel=XGetPixel(ximage,x,y);
  870.             index=(pixel >> red_shift) & red_mask;
  871.             red=(unsigned char) (colors[index].red >> 8);
  872.             index=(pixel >> green_shift) & green_mask;
  873.             green=(unsigned char) (colors[index].green >> 8);
  874.             index=(pixel >> blue_shift) & blue_mask;
  875.             blue=(unsigned char) (colors[index].blue >> 8);
  876.             image->packets+=WritePacket(image->channel,red,green,blue,0,1);
  877.           }
  878.         }
  879.       else
  880.         for (y=0; y < image->rows; y++)
  881.         {
  882.           for (x=0; x < image->columns; x++)
  883.           {
  884.             pixel=XGetPixel(ximage,x,y);
  885.             color=(pixel >> red_shift) & red_mask;
  886.             red=(unsigned char) 
  887.               ((((unsigned long) color*65535)/red_mask) >> 8);
  888.             color=(pixel >> green_shift) & green_mask;
  889.             green=(unsigned char) 
  890.               ((((unsigned long) color*65535)/green_mask) >> 8);
  891.             color=(pixel >> blue_shift) & blue_mask;
  892.             blue=(unsigned char) 
  893.               ((((unsigned long) color*65535)/blue_mask) >> 8);
  894.             image->packets+=WritePacket(image->channel,red,green,blue,0,1);
  895.           }
  896.         }
  897.     }
  898.   /*
  899.     Free image and colormap.
  900.   */
  901.   if (image->colors > 0)
  902.     free((char *) colors);
  903.   XDestroyImage(ximage);
  904.   image->pixels=(RunlengthPacket *)
  905.     realloc((char *) image->pixels,image->packets*sizeof(RunlengthPacket));
  906. }
  907.  
  908. /*
  909. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  910. %                                                                             %
  911. %                                                                             %
  912. %                                                                             %
  913. %   S e l e c t W i n d o w                                                   %
  914. %                                                                             %
  915. %                                                                             %
  916. %                                                                             %
  917. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  918. %
  919. %  Function SelectWindow allows a  user to select a window using the mouse.
  920. %
  921. %  The format of the SelectWindow function is:
  922. %
  923. %      window=SelectWindow(display,screen)
  924. %
  925. %  A description of each parameter follows:
  926. %
  927. %    o window:  SelectWindow returns the window id.
  928. %
  929. %    o display:  Specifies a pointer to the Display structure;  returned from
  930. %      XOpenDisplay.
  931. %
  932. %    o screen: Specifies the screen id of the root window.
  933. %
  934. %
  935. */
  936. static Window SelectWindow(display,screen)
  937. Display
  938.   *display;
  939.  
  940. int
  941.   screen;
  942. {
  943.   Cursor
  944.     cursor;
  945.  
  946.   int
  947.     status;
  948.  
  949.   unsigned int
  950.     presses;
  951.  
  952.   Window
  953.     target_window;
  954.  
  955.   XEvent
  956.     event;
  957.  
  958.   /*
  959.     Make the target cursor.
  960.   */
  961.   cursor=XCreateFontCursor(display,XC_crosshair);
  962.   /*
  963.     Grab the pointer using target cursor.
  964.   */
  965.   status=XGrabPointer(display,XRootWindow(display,screen),False,
  966.     ButtonPressMask | ButtonReleaseMask,GrabModeSync,GrabModeAsync,
  967.     XRootWindow(display,screen),cursor,CurrentTime);
  968.   if (status != GrabSuccess)
  969.     {
  970.       (void) fprintf(stderr,"Can't continue, cannot grab the mouse.\n");
  971.       exit(1);
  972.     }
  973.   /*
  974.     Select a window.
  975.   */
  976.   target_window=None;
  977.   presses=0;
  978.   do
  979.   {
  980.     /*
  981.       Allow another event.
  982.     */
  983.     XAllowEvents(display,SyncPointer,CurrentTime);
  984.     XWindowEvent(display,XRootWindow(display,screen),ButtonPressMask |
  985.       ButtonReleaseMask,&event);
  986.     switch (event.type)
  987.     {
  988.       case ButtonPress:
  989.       {
  990.         if (target_window == None)
  991.           {
  992.             target_window=event.xbutton.subwindow;
  993.             if (target_window == None)
  994.               target_window=XRootWindow(display,screen);
  995.           }
  996.         presses++;
  997.         break;
  998.       }
  999.       case ButtonRelease:
  1000.       {
  1001.         if (presses > 0)
  1002.           presses--;
  1003.         break;
  1004.       }
  1005.       default:
  1006.         break;
  1007.     }
  1008.   }
  1009.   while ((target_window == None) || (presses != 0));
  1010.   XUngrabPointer(display,CurrentTime);
  1011.   return(target_window);
  1012. }
  1013.  
  1014. /*
  1015. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1016. %                                                                             %
  1017. %                                                                             %
  1018. %                                                                             %
  1019. %   U s a g e                                                                 %
  1020. %                                                                             %
  1021. %                                                                             %
  1022. %                                                                             %
  1023. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1024. %
  1025. %  Procedure Usage displays the program usage;
  1026. %
  1027. %  The format of the Usage routine is:
  1028. %
  1029. %      Usage(program_name,message)
  1030. %
  1031. %  A description of each parameter follows:
  1032. %
  1033. %    program_name:  Specifies the name of this program.
  1034. %
  1035. %    message:  Specifies a specific message to display to the user.
  1036. %
  1037. */
  1038. static void Usage(program_name,message)
  1039. char
  1040.   *message,
  1041.   *program_name;
  1042. {
  1043.   char
  1044.     **p;
  1045.  
  1046.   static char
  1047.     *options[]=
  1048.     {
  1049.       "+border        include image borders in the output image",
  1050.       "-display name  X server to contact",
  1051.       "+frame         include window manager frame",
  1052.       "+grayscale     print image as gray scale colors",
  1053.       "-id number     select window with this id",
  1054.       "-name name     select window with this name",
  1055.       "-root          select root window",
  1056.       NULL
  1057.     };
  1058.   if (message)
  1059.     (void) fprintf(stderr,"Can't continue, %s\n\n",message);
  1060.   (void) fprintf(stderr,"Usage: %s [options ...] file\n",program_name);
  1061.   (void) fprintf(stderr,"\nWhere options include:\n");
  1062.   for (p=options; *p; p++)
  1063.     (void) fprintf(stderr,"  %s\n",*p);
  1064.   (void) fprintf(stderr,
  1065.     "\nChange '+' to '-' in any option above to reverse its effect.\n");
  1066.   (void) fprintf(stderr,
  1067.     "For example, -borders means do not include image borders.\n");
  1068.   (void) fprintf(stderr,"\nSpecify 'file' as '-' for standard output.\n");
  1069.   exit(1);
  1070. }
  1071.  
  1072. /*
  1073. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1074. %                                                                             %
  1075. %                                                                             %
  1076. %                                                                             %
  1077. %   W i n d o w B y N a m e                                                   %
  1078. %                                                                             %
  1079. %                                                                             %
  1080. %                                                                             %
  1081. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1082. %
  1083. %  Function WindowByName locates a window with a given name on a display.
  1084. %  If no window with the given name is found, 0 is returned. If more than
  1085. %  one window has the given name, the first one is returned.  Only root and
  1086. %  its children are searched.
  1087. %
  1088. %  The format of the WindowByName function is:
  1089. %
  1090. %      window=WindowByName(display,root,name)
  1091. %
  1092. %
  1093. %  A description of each parameter follows:
  1094. %
  1095. %    o window:  WindowByName returns the window id.
  1096. %
  1097. %    o display:  Specifies a pointer to the Display structure;  returned from
  1098. %      XOpenDisplay.
  1099. %
  1100. %    o root:  Specifies a pointer to a window.
  1101. %
  1102. %    o name:  Specifies the name of the window to locate.
  1103. %
  1104. %
  1105. */
  1106. static Window WindowByName(display,root,name)
  1107. Display
  1108.   *display;
  1109.  
  1110. Window
  1111.   root;
  1112.  
  1113. char
  1114.   *name;
  1115. {
  1116.   char
  1117.     *window_name;
  1118.  
  1119.   register int
  1120.     i;
  1121.  
  1122.   unsigned int
  1123.     number_children;
  1124.  
  1125.   Window
  1126.     *children,
  1127.     child,
  1128.     window;
  1129.  
  1130.   if (XFetchName(display,root,&window_name) && !strcmp(window_name,name))
  1131.     return(root);
  1132.   if (!XQueryTree(display,root,&child,&child,&children,&number_children))
  1133.     return(0);
  1134.   window=0;
  1135.   for (i=0; i < number_children; i++)
  1136.   {
  1137.     /*
  1138.       Search each child and their children.
  1139.     */
  1140.     window=WindowByName(display,children[i],name);
  1141.     if (window)
  1142.       break;
  1143.   }
  1144.   if (children)
  1145.     XFree((char *) children);
  1146.   return(window);
  1147. }
  1148.  
  1149. /*
  1150. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1151. %                                                                             %
  1152. %                                                                             %
  1153. %                                                                             %
  1154. %   W i n d o w B y P r o p e r y                                             %
  1155. %                                                                             %
  1156. %                                                                             %
  1157. %                                                                             %
  1158. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1159. %
  1160. %  Function WindowByProperty locates a child window with a given property.
  1161. %  If no window with the given name is found, 0 is returned.  If more than
  1162. %  one window has the given property, the first one is returned.  Only the 
  1163. %  window specified and its subwindows are searched.
  1164. %
  1165. %  The format of the WindowByProperty function is:
  1166. %
  1167. %      child=WindowByName(display,window,property)
  1168. %
  1169. %
  1170. %  A description of each parameter follows:
  1171. %
  1172. %    o child:  WindowByProperty returns the window id with the specified
  1173. %      property.  If no windows are found, WindowByProperty returns 0.
  1174. %
  1175. %    o display:  Specifies a pointer to the Display structure;  returned from
  1176. %      XOpenDisplay.
  1177. %
  1178. %    o property:  Specifies the property of the window to locate.
  1179. %
  1180. %
  1181. */
  1182. static Window WindowByProperty(display,window,property)
  1183. Display 
  1184.   *display;
  1185.  
  1186. Window 
  1187.   window;
  1188.  
  1189. Atom 
  1190.   property;
  1191. {
  1192.   Atom 
  1193.     type;
  1194.  
  1195.   int 
  1196.     format;
  1197.  
  1198.   unsigned char 
  1199.     *data;
  1200.  
  1201.   unsigned int 
  1202.     i,
  1203.     number_children;
  1204.  
  1205.   unsigned long 
  1206.     after,
  1207.     number_items;
  1208.  
  1209.   Window 
  1210.     *children,
  1211.     child,
  1212.     parent,
  1213.     root;
  1214.  
  1215.   if (!XQueryTree(display,window,&root,&parent,&children,&number_children))
  1216.     return((Window) NULL);
  1217.   type=None;
  1218.   child=(Window) NULL;
  1219.   for (i=0; (i < number_children) && !child; i++) 
  1220.   {
  1221.     XGetWindowProperty(display,children[i],property,0,0,False,AnyPropertyType, 
  1222.       &type,&format,&number_items,&after,&data);
  1223.     if (type)
  1224.       child=children[i];
  1225.   }
  1226.   for (i = 0; (i < number_children) && !child; i++)
  1227.     child=WindowByProperty(display,children[i],property);
  1228.   if (children) 
  1229.     XFree((char *) children);
  1230.   return(child);
  1231. }
  1232.  
  1233. /*
  1234. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1235. %                                                                             %
  1236. %                                                                             %
  1237. %                                                                             %
  1238. %    M a i n                                                                  %
  1239. %                                                                             %
  1240. %                                                                             %
  1241. %                                                                             %
  1242. %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
  1243. %
  1244. %
  1245. */
  1246. main(argc,argv)
  1247. int
  1248.   argc;
  1249.  
  1250. char
  1251.   *argv[];
  1252. {
  1253.   char
  1254.     *option,
  1255.     *program_name,
  1256.     *server_name;
  1257.  
  1258.   Display
  1259.     *display;
  1260.  
  1261.   Image
  1262.     *image;
  1263.  
  1264.   int
  1265.     borders,
  1266.     frame,
  1267.     i,
  1268.     screen;
  1269.  
  1270.   unsigned int
  1271.     grayscale,
  1272.     PrintImage();
  1273.  
  1274.   Window
  1275.     target_window;
  1276.  
  1277.   /*
  1278.     Connect to X server.
  1279.   */
  1280.   program_name=argv[0];
  1281.   server_name=(char *) NULL;
  1282.   for (i=1; i < argc; i++)
  1283.   {
  1284.     /*
  1285.       Check command line for server name.
  1286.     */
  1287.     option=argv[i];
  1288.     if ((strlen(option) > 1) && ((*option == '-') || (*option == '+')))
  1289.       if (strncmp("dis",option+1,3) == 0)
  1290.         {
  1291.           /*
  1292.             User specified server name.
  1293.           */
  1294.           i++;
  1295.           if (i == argc)
  1296.             Usage(program_name,"missing server name on -display");
  1297.           server_name=argv[i];
  1298.           break;
  1299.         }
  1300.   }
  1301.   display=XOpenDisplay(server_name);
  1302.   if (display == (Display *) NULL)
  1303.     {
  1304.       (void) fprintf(stderr,"Can't continue, unable to connect to %s.\n",
  1305.         XDisplayName(server_name));
  1306.       exit(1);
  1307.     }
  1308.   screen=XDefaultScreen(display);
  1309.   /*
  1310.     Get X defaults.
  1311.   */
  1312.   option=XGetDefault(display,program_name,"borders");
  1313.   borders=IsTrue(option);
  1314.   option=XGetDefault(display,program_name,"frame");
  1315.   frame=IsTrue(option);
  1316.   option=XGetDefault(display,program_name,"grayscale");
  1317.   grayscale=IsTrue(option);
  1318.   /*
  1319.     Check command syntax.
  1320.   */
  1321.   target_window=(Window) NULL;
  1322.   for (i=1; i < argc-1; i++)
  1323.   {
  1324.     option=argv[i];
  1325.     if ((strlen(option) > 1) && ((*option == '-') || (*option == '+')))
  1326.       switch(*(option+1))
  1327.       {
  1328.         case 'b':
  1329.         {
  1330.           borders=(*option == '+');
  1331.           break;
  1332.         }
  1333.         case 'h':
  1334.         {
  1335.           Usage(program_name,(char *) NULL);
  1336.           break;
  1337.         }
  1338.         case 'f':
  1339.         {
  1340.           frame=(*option == '+');
  1341.           break;
  1342.         }
  1343.         case 'g':
  1344.         {
  1345.           grayscale=(*option == '+');
  1346.           break;
  1347.         }
  1348.         case 'i':
  1349.         {
  1350.           i++;
  1351.           if (i == argc)
  1352.             Usage(program_name,"missing id on -id");
  1353.           option=argv[i];
  1354.           target_window=(Window) strtol(option,(char **) NULL,0);
  1355.           break;
  1356.         }
  1357.         case 'n':
  1358.         {
  1359.           i++;
  1360.           if (i == argc)
  1361.             Usage(program_name,"missing name on -name");
  1362.           option=argv[i]; 
  1363.           target_window=
  1364.             WindowByName(display,XRootWindow(display,screen),option);
  1365.           if (target_window == (Window) NULL)
  1366.             (void) fprintf(stderr,"No window with name %s exists!\n",option);
  1367.           break;
  1368.         }
  1369.         case 'r':
  1370.         {
  1371.           target_window=XRootWindow(display,screen);
  1372.           break;
  1373.         }
  1374.         default:
  1375.           Usage(program_name,(char *) NULL);
  1376.       }
  1377.   }
  1378.   if (argc == 1)
  1379.     Usage(program_name,(char *) NULL);
  1380.   if (!target_window)
  1381.     target_window=SelectWindow(display,screen);
  1382.   if (!frame)
  1383.     if (target_window != XRootWindow(display,screen))
  1384.       target_window=ClientWindow(display,target_window);
  1385.   image=(Image *) malloc(sizeof(Image));
  1386.   (void) strcpy(image->filename,argv[argc-1]);
  1387.   ReadImage(display,screen,target_window,(unsigned int) borders,image);
  1388.   (void) fprintf(stderr,"%s %dx%d\n",image->filename,image->columns,
  1389.     image->rows);
  1390.   (void) PrintImage(image,grayscale);
  1391.   return(True);
  1392. }
  1393.