multiVis.c revision 74a3f230
1b3307321Smrg/** ------------------------------------------------------------------------
2b3307321Smrg	This file contains functions to create a list of regions which
374a3f230Smrg	tile a specified window.  Each region contains all visible
4b3307321Smrg	portions of the window which are drawn with the same visual.
5b3307321Smrg	If the window consists of subwindows of two different visual types,
6b3307321Smrg	there will be two regions in the list.  The list can be traversed
7b3307321Smrg	to correctly pull an image of the window using XGetImage or the
8b3307321Smrg	Image Library.
9b3307321Smrg
10b3307321SmrgCopyright 1994 Hewlett-Packard Co.
11b3307321SmrgCopyright 1996, 1998  The Open Group
12b3307321Smrg
13b3307321SmrgPermission to use, copy, modify, distribute, and sell this software and its
14b3307321Smrgdocumentation for any purpose is hereby granted without fee, provided that
15b3307321Smrgthe above copyright notice appear in all copies and that both that
16b3307321Smrgcopyright notice and this permission notice appear in supporting
17b3307321Smrgdocumentation.
18b3307321Smrg
19b3307321SmrgThe above copyright notice and this permission notice shall be included
20b3307321Smrgin all copies or substantial portions of the Software.
21b3307321Smrg
22b3307321SmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
23b3307321SmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24b3307321SmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
25b3307321SmrgIN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
26b3307321SmrgOTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
27b3307321SmrgARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
28b3307321SmrgOTHER DEALINGS IN THE SOFTWARE.
29b3307321Smrg
30b3307321SmrgExcept as contained in this notice, the name of The Open Group shall
31b3307321Smrgnot be used in advertising or otherwise to promote the sale, use or
32b3307321Smrgother dealings in this Software without prior written authorization
33b3307321Smrgfrom The Open Group.
34b3307321Smrg
35b3307321Smrg    ------------------------------------------------------------------------ **/
36b3307321Smrg
37b3307321Smrg#include <stdlib.h>
38b3307321Smrg#include <X11/Xlib.h>
39b3307321Smrg#include <X11/Xutil.h>
40b3307321Smrg#include <X11/X.h>
41b3307321Smrg#include <stdio.h>
42b3307321Smrg#include "list.h"
43b3307321Smrg#include "wsutils.h"
44b3307321Smrg#include "multiVis.h"
45b3307321Smrg/* These structures are copied from X11/region.h.  For some reason
46b3307321Smrg * they're invisible from the outside.
47b3307321Smrg */
48b3307321Smrgtypedef struct {
49b3307321Smrg    short x1, x2, y1, y2;
50b3307321Smrg} myBox, myBOX, myBoxRec, *myBoxPtr;
51b3307321Smrg
52b3307321Smrgtypedef struct my_XRegion {
53b3307321Smrg    long size;
54b3307321Smrg    long numRects;
55b3307321Smrg    myBOX *rects;
56b3307321Smrg    myBOX extents;
57b3307321Smrg} myREGION;
58b3307321Smrg
59b3307321Smrg/* Items in long list of windows that have some part in the grabbed area */
60b3307321Smrgtypedef struct {
61b3307321Smrg    Window win;
62b3307321Smrg    Visual *vis;
63b3307321Smrg    Colormap cmap;
64b3307321Smrg    int x_rootrel, y_rootrel;	/* root relative location of window */
65b3307321Smrg    int x_vis, y_vis;  		/* rt rel x,y of vis part, not parent clipped */
66b3307321Smrg    int width, height; 		/* width and height of visible part */
67b3307321Smrg    int border_width;		/* border width of the window */
68b3307321Smrg    Window parent;		/* id of parent (for debugging) */
69b3307321Smrg} image_win_type;
70b3307321Smrg
7174a3f230Smrg/*  Items in short list of regions that tile the grabbed area.  May have
72b3307321Smrg    multiple windows in the region.
73b3307321Smrg*/
74b3307321Smrgtypedef struct {
75b3307321Smrg    Window win;			/* lowest window of this visual */
76b3307321Smrg    Visual *vis;
77b3307321Smrg    Colormap cmap;
78b3307321Smrg    int x_rootrel, y_rootrel;	/* root relative location of bottom window */
79b3307321Smrg    int x_vis, y_vis;  		/* rt rel x,y of vis part, not parent clipped */
80b3307321Smrg    int width, height;		/* w & h of visible rect of bottom window */
81b3307321Smrg    int border;			/* border width of the window */
82b3307321Smrg    Region visible_region;
83b3307321Smrg} image_region_type;
84b3307321Smrg
85b3307321Smrg/** ------------------------------------------------------------------------
8674a3f230Smrg	Returns TRUE if the two structs pointed to have the same "vis" &
87b3307321Smrg	"cmap" fields and s2 lies completely within s1.  s1 and s2 can
88b3307321Smrg	point to structs of image_win_type or image_region_type.
89b3307321Smrg    ------------------------------------------------------------------------ **/
90b3307321Smrg#define SAME_REGIONS( s1, s2)	\
91b3307321Smrg	((s1)->vis == (s2)->vis && (s1)->cmap == (s2)->cmap &&   	\
92b3307321Smrg	 (s1)->x_vis <= (s2)->x_vis &&				    \
93b3307321Smrg	 (s1)->y_vis <= (s2)->y_vis &&				    \
94b3307321Smrg	 (s1)->x_vis + (s1)->width  >= (s2)->x_vis + (s2)->width && \
95b3307321Smrg	 (s1)->y_vis + (s1)->height >= (s2)->y_vis + (s2)->height)
96b3307321Smrg
97b3307321Smrg#ifndef MIN
98b3307321Smrg#define MIN( a, b)	((a) < (b) ? a : b)
99b3307321Smrg#define MAX( a, b)	((a) > (b) ? a : b)
100b3307321Smrg#endif
101b3307321Smrg
102b3307321Smrg#define	RED_SHIFT        16
103b3307321Smrg#define GREEN_SHIFT       8
104b3307321Smrg#define BLUE_SHIFT        0
105b3307321Smrg
106b3307321Smrg/*
107b3307321Smrgextern list_ptr	new_list();
108b3307321Smrgextern list_ptr	dup_list_head();
109b3307321Smrgextern void *	first_in_list();
110b3307321Smrgextern void *	next_in_list();
111b3307321Smrgextern int	add_to_list();
112b3307321Smrgextern void	zero_list();
113b3307321Smrgextern void	delete_list();
114b3307321Smrgextern void	delete_list_destroying();
115b3307321Smrgextern unsigned int list_length();
116b3307321Smrg*/
117b3307321Smrg
118b3307321Smrg/* Prototype Declarations for Static Functions */
11974a3f230Smrgstatic void QueryColorMap(
12074a3f230Smrg           Display *, Colormap , Visual *,
121b3307321Smrg           XColor **, int *, int *, int *
122b3307321Smrg	   );
123b3307321Smrgstatic void TransferImage(
124b3307321Smrg           Display *, XImage *,int, int , image_region_type*,
12574a3f230Smrg           XImage *,int ,int
126b3307321Smrg	   );
127b3307321Smrgstatic XImage * ReadRegionsInList(
12874a3f230Smrg           Display *, Visual *, int, int, unsigned int,
12974a3f230Smrg           unsigned int, XRectangle, list_ptr
130b3307321Smrg           );
131b3307321Smrg
13274a3f230Smrgstatic list_ptr make_region_list(
133b3307321Smrg                  Display*, Window, XRectangle*,
134b3307321Smrg                  int*, int, XVisualInfo**, int	*
135b3307321Smrg         );
136b3307321Smrg
13774a3f230Smrgstatic void destroy_region_list(
13874a3f230Smrg            list_ptr
139b3307321Smrg            ) ;
14074a3f230Smrgstatic void subtr_rect_from_image_region(
14174a3f230Smrg           image_region_type *, int , int , int , int
142b3307321Smrg     );
14374a3f230Smrgstatic void add_rect_to_image_region(
144b3307321Smrg           image_region_type *,
14574a3f230Smrg           int , int , int , int
146b3307321Smrg     );
14774a3f230Smrgstatic int src_in_region_list(
14874a3f230Smrg    image_win_type *, list_ptr
149b3307321Smrg    );
150b3307321Smrgstatic void add_window_to_list(
151b3307321Smrg    list_ptr, Window, int, int ,
152b3307321Smrg    int	, int , int , int, int,
153b3307321Smrg    Visual*, Colormap, Window
154b3307321Smrg    );
15574a3f230Smrgstatic int src_in_image(
156b3307321Smrg    image_win_type 	*, int	, XVisualInfo**
157b3307321Smrg    );
15874a3f230Smrgstatic int src_in_overlay(
159b3307321Smrg    image_region_type *, int, OverlayInfo *, int*, int*
160b3307321Smrg    );
161b3307321Smrgstatic void make_src_list(
162b3307321Smrg    Display *, list_ptr, XRectangle *, Window,
163b3307321Smrg    int, int, XWindowAttributes *, XRectangle *
164b3307321Smrg);
165b3307321Smrgstatic void destroy_image_region(
166b3307321Smrg    image_region_type *
167b3307321Smrg);
168b3307321Smrg
169b3307321Smrg/* End of Prototype Declarations */
170b3307321Smrg
1715e358ecaSmrgvoid initFakeVisual(Visual *Vis)
172b3307321Smrg{
173b3307321Smrg    Vis->ext_data=NULL;
174b3307321Smrg    Vis->class = DirectColor ;
175b3307321Smrg    Vis->red_mask =   0x00FF0000;
176b3307321Smrg    Vis->green_mask = 0x0000FF00 ;
177b3307321Smrg    Vis->blue_mask  = 0x000000FF ;
178b3307321Smrg    Vis->map_entries = 256 ;
179b3307321Smrg    Vis->bits_per_rgb = 8 ;
180b3307321Smrg}
181b3307321Smrg
18274a3f230Smrgstatic void
1835e358ecaSmrgQueryColorMap(Display *disp, Colormap src_cmap, Visual *src_vis,
1845e358ecaSmrg	      XColor **src_colors, int *rShift, int *gShift, int *bShift)
185b3307321Smrg{
18674a3f230Smrg     unsigned int ncolors,i ;
187b3307321Smrg     unsigned long       redMask, greenMask, blueMask;
188b3307321Smrg     int                 redShift, greenShift, blueShift;
189b3307321Smrg     XColor *colors ;
190b3307321Smrg
19174a3f230Smrg     ncolors = (unsigned) src_vis->map_entries ;
192b3307321Smrg     *src_colors = colors = (XColor *)malloc(ncolors * sizeof(XColor) ) ;
193b3307321Smrg
194b3307321Smrg     if(src_vis->class != TrueColor && src_vis->class != DirectColor)
195b3307321Smrg     {
196b3307321Smrg         for(i=0 ; i < ncolors ; i++)
197b3307321Smrg         {
198b3307321Smrg	        colors[i].pixel = i ;
199b3307321Smrg                colors[i].pad = 0;
200b3307321Smrg                colors[i].flags = DoRed|DoGreen|DoBlue;
201b3307321Smrg         }
202b3307321Smrg     }
203b3307321Smrg     else /** src is decomposed rgb ***/
204b3307321Smrg     {
205b3307321Smrg        /* Get the X colormap */
206b3307321Smrg        redMask = src_vis->red_mask;
207b3307321Smrg        greenMask = src_vis->green_mask;
208b3307321Smrg        blueMask = src_vis->blue_mask;
209b3307321Smrg        redShift = 0; while (!(redMask&0x1)) {
210b3307321Smrg                redShift++;
211b3307321Smrg                redMask = redMask>>1;
212b3307321Smrg        }
213b3307321Smrg        greenShift = 0; while (!(greenMask&0x1)) {
214b3307321Smrg                greenShift++;
215b3307321Smrg                greenMask = greenMask>>1;
216b3307321Smrg        }
217b3307321Smrg        blueShift = 0; while (!(blueMask&0x1)) {
218b3307321Smrg                blueShift++;
219b3307321Smrg                blueMask = blueMask>>1;
220b3307321Smrg        }
221b3307321Smrg	*rShift = redShift ;
222b3307321Smrg	*gShift = greenShift ;
223b3307321Smrg	*bShift = blueShift ;
224b3307321Smrg        for (i=0; i<ncolors; i++) {
225b3307321Smrg		if( i <= redMask)colors[i].pixel = (i<<redShift) ;
226b3307321Smrg		if( i <= greenMask)colors[i].pixel |= (i<<greenShift) ;
227b3307321Smrg		if( i <= blueMask)colors[i].pixel |= (i<<blueShift) ;
228b3307321Smrg		/***** example :for gecko's 3-3-2 map, blue index should be <= 3.
229b3307321Smrg                colors[i].pixel = (i<<redShift)|(i<<greenShift)|(i<<blueShift);
230b3307321Smrg		*****/
231b3307321Smrg                colors[i].pad = 0;
232b3307321Smrg                colors[i].flags = DoRed|DoGreen|DoBlue;
233b3307321Smrg        }
234b3307321Smrg      }
235b3307321Smrg
23674a3f230Smrg      XQueryColors(disp, src_cmap, colors, (int) ncolors);
237b3307321Smrg}
238b3307321Smrg
239b3307321Smrgint
2405e358ecaSmrgGetMultiVisualRegions(Display *disp,
2415e358ecaSmrg		      /* root win on which grab was done */
2425e358ecaSmrg		      Window srcRootWinid,
2435e358ecaSmrg		      /* root rel UL corner of bounding box of grab */
2445e358ecaSmrg		      int x, int y,
2455e358ecaSmrg		      /* size of bounding box of grab */
2465e358ecaSmrg		      unsigned int width, unsigned int height,
2475e358ecaSmrg		      int *transparentOverlays, int *numVisuals,
2485e358ecaSmrg		      XVisualInfo **pVisuals, int *numOverlayVisuals,
2495e358ecaSmrg		      OverlayInfo **pOverlayVisuals,
2505e358ecaSmrg		      int *numImageVisuals, XVisualInfo ***pImageVisuals,
2515e358ecaSmrg		      /* list of regions to read from */
2525e358ecaSmrg		      list_ptr *vis_regions,
2535e358ecaSmrg		      list_ptr *vis_image_regions, int *allImage)
254b3307321Smrg{
255b3307321Smrg    int                 hasNonDefault;
256b3307321Smrg    XRectangle          bbox;           /* bounding box of grabbed area */
257b3307321Smrg
258b3307321Smrg
259b3307321Smrg    bbox.x = x;                 /* init X rect for bounding box */
260b3307321Smrg    bbox.y = y;
261b3307321Smrg    bbox.width = width;
262b3307321Smrg    bbox.height = height;
263b3307321Smrg
264b3307321Smrg    GetXVisualInfo(disp,DefaultScreen(disp),
265b3307321Smrg                    transparentOverlays,
266b3307321Smrg                    numVisuals, pVisuals,
267b3307321Smrg                    numOverlayVisuals, pOverlayVisuals,
268b3307321Smrg                    numImageVisuals, pImageVisuals);
269b3307321Smrg
270b3307321Smrg    *vis_regions = *vis_image_regions = NULL ;
271b3307321Smrg    if ((*vis_regions = make_region_list( disp, srcRootWinid, &bbox,
272b3307321Smrg                                         &hasNonDefault, *numImageVisuals,
27374a3f230Smrg                                         *pImageVisuals, allImage)) == NULL)
274b3307321Smrg    	return 0 ;
27574a3f230Smrg
276b3307321Smrg    if (*transparentOverlays)
277b3307321Smrg    {
278b3307321Smrg        *allImage = 1; /* until proven otherwise,
279b3307321Smrg                         this flags that it to be an image only list */
280b3307321Smrg        *vis_image_regions =
281b3307321Smrg                make_region_list( disp, srcRootWinid, &bbox, &hasNonDefault,
282b3307321Smrg                                        *numImageVisuals, *pImageVisuals, allImage);
283b3307321Smrg    }
284b3307321Smrg
285b3307321Smrg    /* if there is a second region in any of the two lists return 1 **/
286b3307321Smrg    if ( ( *vis_regions && (*vis_regions)->next && (*vis_regions)->next->next ) ||
28774a3f230Smrg         ( *vis_image_regions && (*vis_image_regions)->next &&
288b3307321Smrg           (*vis_image_regions)->next->next ) ) return 1 ;
289b3307321Smrg    else return 0 ;
290b3307321Smrg
291b3307321Smrg}
292b3307321Smrg
2935e358ecaSmrgstatic void TransferImage(Display *disp, XImage *reg_image,
2945e358ecaSmrg			  int srcw, int srch,
2955e358ecaSmrg			  image_region_type *reg, XImage *target_image,
2965e358ecaSmrg			  int dst_x, int dst_y)
297b3307321Smrg{
298b3307321Smrg    int i,j,old_pixel,new_pixel,red_ind,green_ind,blue_ind ;
299b3307321Smrg    XColor *colors;
30074a3f230Smrg    int rShift = 0, gShift = 0, bShift = 0;
301b3307321Smrg
30274a3f230Smrg    QueryColorMap(disp,reg->cmap,reg->vis,&colors,
303b3307321Smrg	 &rShift,&gShift,&bShift) ;
304b3307321Smrg
305b3307321Smrg    switch (reg->vis->class) {
30674a3f230Smrg    case TrueColor :
307b3307321Smrg       for(i=0 ; i < srch ; i++)
308b3307321Smrg       {
309b3307321Smrg         for(j=0 ; j < srcw ;  j++)
310b3307321Smrg         {
311b3307321Smrg	   old_pixel = XGetPixel(reg_image,j,i) ;
312b3307321Smrg
313b3307321Smrg           if( reg->vis->map_entries == 16) {
31474a3f230Smrg
315b3307321Smrg                 red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
316b3307321Smrg	         green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
317b3307321Smrg	         blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
318b3307321Smrg
31974a3f230Smrg	         new_pixel = (
320b3307321Smrg			      ((colors[red_ind].red >> 8) << RED_SHIFT)
321b3307321Smrg			      |((colors[green_ind].green >> 8) << GREEN_SHIFT)
322b3307321Smrg			      |((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
323b3307321Smrg                             );
324b3307321Smrg           }
32574a3f230Smrg	   else
326b3307321Smrg		new_pixel = old_pixel;
327b3307321Smrg
328b3307321Smrg           XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
32974a3f230Smrg
330b3307321Smrg         }
331b3307321Smrg       }
332b3307321Smrg       break;
333b3307321Smrg    case DirectColor :
334b3307321Smrg       for(i=0 ; i < srch ; i++)
335b3307321Smrg       {
33674a3f230Smrg
337b3307321Smrg         for(j=0 ; j < srcw ;  j++)
338b3307321Smrg         {
339b3307321Smrg	   old_pixel = XGetPixel(reg_image,j,i) ;
340b3307321Smrg           red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
341b3307321Smrg	   green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
342b3307321Smrg	   blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
34374a3f230Smrg
34474a3f230Smrg	   new_pixel = (
345b3307321Smrg			 ((colors[red_ind].red >> 8) << RED_SHIFT)
346b3307321Smrg			|((colors[green_ind].green >> 8) << GREEN_SHIFT)
347b3307321Smrg			|((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
348b3307321Smrg                       );
349b3307321Smrg           XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
35074a3f230Smrg
351b3307321Smrg         }
352b3307321Smrg       }
353b3307321Smrg       break;
354b3307321Smrg    default :
355b3307321Smrg       for(i=0 ; i < srch ; i++)
356b3307321Smrg       {
357b3307321Smrg         for(j=0 ; j < srcw ;  j++)
358b3307321Smrg         {
359b3307321Smrg	    old_pixel = XGetPixel(reg_image,j,i) ;
36074a3f230Smrg
36174a3f230Smrg	   new_pixel = (
362b3307321Smrg			 ((colors[old_pixel].red >> 8) << RED_SHIFT)
363b3307321Smrg			|((colors[old_pixel].green >> 8) << GREEN_SHIFT)
364b3307321Smrg			|((colors[old_pixel].blue >> 8) << BLUE_SHIFT)
365b3307321Smrg                       );
366b3307321Smrg           XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
36774a3f230Smrg
368b3307321Smrg         }
369b3307321Smrg       }
370b3307321Smrg       break;
371b3307321Smrg    }
372b3307321Smrg}
373b3307321Smrg
374b3307321Smrgstatic XImage *
3755e358ecaSmrgReadRegionsInList(Display *disp, Visual *fakeVis, int depth, int format,
37674a3f230Smrg		  unsigned int width, unsigned int height,
3775e358ecaSmrg		  XRectangle bbox,	/* bounding box of grabbed area */
3785e358ecaSmrg		  list_ptr regions)	/* list of regions to read from */
379b3307321Smrg{
380b3307321Smrg    image_region_type	*reg;
381b3307321Smrg    int			dst_x, dst_y;	/* where in pixmap to write (UL) */
382b3307321Smrg    int			diff;
383b3307321Smrg
384b3307321Smrg    XImage		*reg_image,*ximage ;
385b3307321Smrg    int			srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
38674a3f230Smrg    int                 bytes_per_line;
38774a3f230Smrg
388b3307321Smrg    ximage = XCreateImage(disp,fakeVis,depth,format,0,NULL,width,height,
389b3307321Smrg	         8,0) ;
390b3307321Smrg    bytes_per_line = ximage->bytes_per_line;
391b3307321Smrg
392b3307321Smrg    if (format == ZPixmap)
393b3307321Smrg    	  ximage->data = malloc(height*bytes_per_line);
394b3307321Smrg    else
395b3307321Smrg        ximage->data = malloc(height*bytes_per_line*depth);
396b3307321Smrg
397b3307321Smrg    ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/
39874a3f230Smrg
399b3307321Smrg    for (reg = (image_region_type *) first_in_list( regions); reg;
40074a3f230Smrg	 reg = (image_region_type *) next_in_list( regions))
401b3307321Smrg    {
402b3307321Smrg		int rect;
403b3307321Smrg		struct my_XRegion *vis_reg;
404b3307321Smrg		vis_reg = (struct my_XRegion *)(reg->visible_region);
40574a3f230Smrg		for (rect = 0;
406b3307321Smrg		     rect < vis_reg->numRects;
407b3307321Smrg		     rect++)
408b3307321Smrg		{
409b3307321Smrg		/** ------------------------------------------------------------------------
41074a3f230Smrg			Intersect bbox with visible part of region giving src rect & output
411b3307321Smrg			location.  Width is the min right side minus the max left side.
412b3307321Smrg			Similar for height.  Offset src rect so x,y are relative to
413b3307321Smrg			origin of win, not the root-relative visible rect of win.
414b3307321Smrg		    ------------------------------------------------------------------------ **/
41574a3f230Smrg		    srcRect_width  = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x) -
416b3307321Smrg				     MAX( vis_reg->rects[rect].x1, bbox.x);
41774a3f230Smrg		    srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y) -
418b3307321Smrg				     MAX( vis_reg->rects[rect].y1, bbox.y);
419b3307321Smrg		    diff = bbox.x - vis_reg->rects[rect].x1;
420b3307321Smrg		    srcRect_x = MAX( 0, diff)  + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border);
421b3307321Smrg		    dst_x     = MAX( 0, -diff) ;
422b3307321Smrg		    diff = bbox.y - vis_reg->rects[rect].y1;
423b3307321Smrg		    srcRect_y = MAX( 0, diff)  + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border);
424b3307321Smrg		    dst_y     = MAX( 0, -diff) ;
425b3307321Smrg                    reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y,
426b3307321Smrg				srcRect_width,srcRect_height,AllPlanes,format) ;
427b3307321Smrg		    TransferImage(disp,reg_image,srcRect_width,
428b3307321Smrg		                 srcRect_height,reg,ximage,dst_x,dst_y) ;
429b3307321Smrg	    }
430b3307321Smrg    }
431b3307321Smrg    return ximage ;
432b3307321Smrg}
433b3307321Smrg
434b3307321Smrg
435b3307321Smrg/** ------------------------------------------------------------------------
436b3307321Smrg    ------------------------------------------------------------------------ **/
437b3307321Smrg
4385e358ecaSmrgXImage *ReadAreaToImage(Display *disp,
4395e358ecaSmrg			/* root win on which grab was done */
4405e358ecaSmrg			Window srcRootWinid,
4415e358ecaSmrg			/* root rel UL corner of bounding box of grab */
4425e358ecaSmrg			int x, int y,
4435e358ecaSmrg			/* size of bounding box of grab */
44474a3f230Smrg			unsigned int width, unsigned int height,
4455e358ecaSmrg			int numVisuals, XVisualInfo *pVisuals,
4465e358ecaSmrg			int numOverlayVisuals, OverlayInfo *pOverlayVisuals,
4475e358ecaSmrg			int numImageVisuals, XVisualInfo **pImageVisuals,
4485e358ecaSmrg			/* list of regions to read from */
4495e358ecaSmrg			list_ptr vis_regions,
4505e358ecaSmrg			/* list of regions to read from */
4515e358ecaSmrg			list_ptr vis_image_regions,
4525e358ecaSmrg			int format, int allImage)
453b3307321Smrg{
454b3307321Smrg    image_region_type	*reg;
455b3307321Smrg    XRectangle		bbox;		/* bounding box of grabbed area */
456b3307321Smrg    int 		depth ;
457b3307321Smrg    XImage		*ximage, *ximage_ipm = NULL;
458b3307321Smrg    Visual		fakeVis ;
459b3307321Smrg    int 	x1, y1;
460b3307321Smrg    XImage	*image;
461b3307321Smrg#if 0
462b3307321Smrg    unsigned char 	*pmData ,  *ipmData ;
463b3307321Smrg#endif
464b3307321Smrg    int                 transparentColor, transparentType;
465b3307321Smrg    int			srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
466b3307321Smrg    int			diff ;
467b3307321Smrg    int			dst_x, dst_y;	/* where in pixmap to write (UL) */
468b3307321Smrg    int			pixel;
469b3307321Smrg
470b3307321Smrg    bbox.x = x;			/* init X rect for bounding box */
471b3307321Smrg    bbox.y = y;
472b3307321Smrg    bbox.width = width;
473b3307321Smrg    bbox.height = height;
474b3307321Smrg
475b3307321Smrg
476b3307321Smrg    initFakeVisual(&fakeVis) ;
477b3307321Smrg
478b3307321Smrg    depth = 24 ;
479b3307321Smrg    ximage = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
480b3307321Smrg	     bbox,vis_regions) ;
481b3307321Smrg#if 0
482b3307321Smrg    pmData = (unsigned char *)ximage -> data ;
483b3307321Smrg#endif
484b3307321Smrg
485b3307321Smrg/* if transparency possible do it again, but this time for image planes only */
486b3307321Smrg    if (vis_image_regions && (vis_image_regions->next) && !allImage)
487b3307321Smrg    {
488b3307321Smrg	ximage_ipm = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
489b3307321Smrg		     bbox,vis_image_regions) ;
490b3307321Smrg#if 0
491b3307321Smrg        ipmData = (unsigned char *)ximage_ipm -> data ;
492b3307321Smrg#endif
493b3307321Smrg    }
494b3307321Smrg/* Now tranverse the overlay visual windows and test for transparency index.  */
495b3307321Smrg/* If you find one, subsitute the value from the matching image plane pixmap. */
496b3307321Smrg
497b3307321Smrg    for (reg = (image_region_type *) first_in_list( vis_regions); reg;
498b3307321Smrg	 reg = (image_region_type *) next_in_list( vis_regions))
499b3307321Smrg    {
500b3307321Smrg
501b3307321Smrg	if (src_in_overlay( reg, numOverlayVisuals, pOverlayVisuals,
502b3307321Smrg				 &transparentColor, &transparentType))
503b3307321Smrg	{
504b3307321Smrg	int test = 0 ;
505b3307321Smrg	     srcRect_width  = MIN( reg->width + reg->x_vis, bbox.width + bbox.x)
506b3307321Smrg				 - MAX( reg->x_vis, bbox.x);
50774a3f230Smrg	     srcRect_height = MIN( reg->height + reg->y_vis, bbox.height
508b3307321Smrg				 + bbox.y) - MAX( reg->y_vis, bbox.y);
509b3307321Smrg             diff = bbox.x - reg->x_vis;
510b3307321Smrg             srcRect_x = MAX( 0, diff)  + (reg->x_vis - reg->x_rootrel - reg->border);
511b3307321Smrg             dst_x     = MAX( 0, -diff) ;
512b3307321Smrg	     diff = bbox.y - reg->y_vis;
513b3307321Smrg	     srcRect_y = MAX( 0, diff)  + (reg->y_vis - reg->y_rootrel - reg->border);
514b3307321Smrg	     dst_y     = MAX( 0, -diff) ;
515b3307321Smrg	/* let's test some pixels for transparency */
51674a3f230Smrg             image = XGetImage(disp, reg->win, srcRect_x, srcRect_y,
517b3307321Smrg		 srcRect_width, srcRect_height, 0xffffffff, ZPixmap);
518b3307321Smrg
519b3307321Smrg        /* let's assume byte per pixel for overlay image for now */
520b3307321Smrg	     if ((image->depth == 8) && (transparentType == TransparentPixel))
521b3307321Smrg	     {
522b3307321Smrg	         unsigned char *pixel_ptr;
523b3307321Smrg	         unsigned char *start_of_line = (unsigned char *) image->data;
524b3307321Smrg
525b3307321Smrg	         for (y1 = 0; y1 < srcRect_height; y1++) {
526b3307321Smrg		    pixel_ptr = start_of_line;
527b3307321Smrg		    for (x1 = 0; x1 < srcRect_width; x1++)
528b3307321Smrg		    {
529b3307321Smrg			if (*pixel_ptr++ == transparentColor)
530b3307321Smrg			{
531b3307321Smrg#if 0
532b3307321Smrg			    *pmData++ = *ipmData++;
533b3307321Smrg			    *pmData++ = *ipmData++;
534b3307321Smrg			    *pmData++ = *ipmData++;
535b3307321Smrg#endif
536b3307321Smrg	                pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
537b3307321Smrg                        XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
53874a3f230Smrg
539b3307321Smrg			if(!test){
540b3307321Smrg			   test = 1 ;
541b3307321Smrg			}
542b3307321Smrg			}
543b3307321Smrg#if 0
544b3307321Smrg			else {
545b3307321Smrg			    pmData +=3;
546b3307321Smrg			    ipmData +=3;
547b3307321Smrg			}
548b3307321Smrg#endif
549b3307321Smrg		    }
550b3307321Smrg		    start_of_line += image->bytes_per_line;
551b3307321Smrg		}
552b3307321Smrg	} else {
553b3307321Smrg		if (transparentType == TransparentPixel) {
554b3307321Smrg		for (y1 = 0; y1 < srcRect_height; y1++) {
555b3307321Smrg		      for (x1 = 0; x1 < srcRect_width; x1++)
556b3307321Smrg		      {
557b3307321Smrg			    int pixel_value = XGetPixel(image, x1, y1);
558b3307321Smrg			    if (pixel_value == transparentColor)
559b3307321Smrg			    {
560b3307321Smrg#if 0
561b3307321Smrg				*pmData++ = *ipmData++;
562b3307321Smrg				*pmData++ = *ipmData++;
563b3307321Smrg				*pmData++ = *ipmData++;
564b3307321Smrg#endif
565b3307321Smrg	                pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
566b3307321Smrg                        XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
567b3307321Smrg			if(!test){
568b3307321Smrg			   test = 1 ;
569b3307321Smrg			}
570b3307321Smrg			    }
571b3307321Smrg#if 0
572b3307321Smrg			    else {
573b3307321Smrg				pmData +=3;
574b3307321Smrg				ipmData +=3;
575b3307321Smrg			    }
576b3307321Smrg#endif
577b3307321Smrg			}
578b3307321Smrg		    }
579b3307321Smrg		} else {
580b3307321Smrg		    for (y1 = 0; y1 < srcRect_height; y1++) {
581b3307321Smrg			for (x1 = 0; x1 < srcRect_width; x1++)
582b3307321Smrg			{
583b3307321Smrg			    int pixel_value = XGetPixel(image, x1, y1);
584b3307321Smrg			    if (pixel_value & transparentColor)
585b3307321Smrg			    {
586b3307321Smrg#if 0
587b3307321Smrg				*pmData++ = *ipmData++;
588b3307321Smrg				*pmData++ = *ipmData++;
589b3307321Smrg				*pmData++ = *ipmData++;
590b3307321Smrg#endif
591b3307321Smrg	                        pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
592b3307321Smrg                                XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
593b3307321Smrg			if(!test){
594b3307321Smrg			   test = 1 ;
595b3307321Smrg			}
596b3307321Smrg			    }
597b3307321Smrg#if 0
598b3307321Smrg			    else {
599b3307321Smrg				pmData +=3;
600b3307321Smrg				ipmData +=3;
601b3307321Smrg			    }
602b3307321Smrg#endif
603b3307321Smrg			}
604b3307321Smrg		    }
605b3307321Smrg		}
606b3307321Smrg	}
607b3307321Smrg        XDestroyImage (image);
608b3307321Smrg      }	/* end of src_in_overlay */
609b3307321Smrg    } /** end transparency **/
610b3307321Smrg    destroy_region_list( vis_regions);
611b3307321Smrg    if (vis_image_regions) destroy_region_list( vis_image_regions );
612b3307321Smrg    FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals);
613b3307321Smrg    XSync(disp, 0);
614b3307321Smrg
615b3307321Smrg    return ximage;
616b3307321Smrg}
617b3307321Smrg
618b3307321Smrg/** ------------------------------------------------------------------------
619b3307321Smrg	Creates a list of the subwindows of a given window which have a
620b3307321Smrg	different visual than their parents.  The function is recursive.
621b3307321Smrg	This list is used in make_region_list(), which coalesces the
622b3307321Smrg	windows with the same visual into a region.
623b3307321Smrg	image_wins must point to an existing list struct that's already
624b3307321Smrg	been zeroed (zero_list()).
625b3307321Smrg    ------------------------------------------------------------------------ **/
6265e358ecaSmrgstatic void make_src_list(Display *disp, list_ptr image_wins,
6275e358ecaSmrg			  /* bnding box of area we want */
6285e358ecaSmrg			  XRectangle *bbox,
6295e358ecaSmrg			  Window curr,
6305e358ecaSmrg			  /* pos of curr WRT root */
6315e358ecaSmrg			  int x_rootrel, int y_rootrel,
6325e358ecaSmrg			  XWindowAttributes *curr_attrs,
6335e358ecaSmrg			  /* visible part of curr, not obscurred by ancestors */
6345e358ecaSmrg			  XRectangle *pclip)
635b3307321Smrg{
636b3307321Smrg    XWindowAttributes child_attrs;
637b3307321Smrg    Window root, parent, *child;	/* variables for XQueryTree() */
638b3307321Smrg    Window *save_child_list;		/* variables for XQueryTree() */
639b3307321Smrg    unsigned int nchild;		/* variables for XQueryTree() */
640b3307321Smrg    XRectangle child_clip;		/* vis part of child */
641b3307321Smrg    int curr_clipX, curr_clipY, curr_clipRt, curr_clipBt;
642b3307321Smrg
643b3307321Smrg    /* check that win is mapped & not outside bounding box */
644b3307321Smrg    if (curr_attrs->map_state == IsViewable &&
645b3307321Smrg	curr_attrs->class == InputOutput &&
646b3307321Smrg	!( pclip->x >= (int) (bbox->x + bbox->width)	||
647b3307321Smrg	   pclip->y >= (int) (bbox->y + bbox->height)	||
648b3307321Smrg	   (int) (pclip->x + pclip->width)  <= bbox->x	||
649b3307321Smrg	   (int) (pclip->y + pclip->height) <= bbox->y)) {
650b3307321Smrg
651b3307321Smrg	XQueryTree( disp, curr, &root, &parent, &child, &nchild );
652b3307321Smrg	save_child_list = child;      /* so we can free list when we're done */
65374a3f230Smrg	add_window_to_list( image_wins, curr, x_rootrel, y_rootrel,
65474a3f230Smrg			    pclip->x, pclip->y,
65574a3f230Smrg			    pclip->width, pclip->height,
65674a3f230Smrg			    curr_attrs->border_width,curr_attrs->visual,
657b3307321Smrg			    curr_attrs->colormap, parent);
658b3307321Smrg
65974a3f230Smrg
660b3307321Smrg/** ------------------------------------------------------------------------
661b3307321Smrg	set RR coords of right (Rt), left (X), bottom (Bt) and top (Y)
662b3307321Smrg	of rect we clip all children by.  This is our own clip rect (pclip)
663b3307321Smrg	inflicted on us by our parent plus our own borders.  Within the
664b3307321Smrg	child loop, we figure the clip rect for each child by adding in
665b3307321Smrg	it's rectangle (not taking into account the child's borders).
666b3307321Smrg    ------------------------------------------------------------------------ **/
667b3307321Smrg	curr_clipX = MAX( pclip->x, x_rootrel + (int) curr_attrs->border_width);
668b3307321Smrg	curr_clipY = MAX( pclip->y, y_rootrel + (int) curr_attrs->border_width);
669b3307321Smrg	curr_clipRt = MIN( pclip->x + (int) pclip->width,
67074a3f230Smrg			   x_rootrel + (int) curr_attrs->width +
671b3307321Smrg			   2 * (int) curr_attrs->border_width);
672b3307321Smrg	curr_clipBt = MIN( pclip->y + (int) pclip->height,
67374a3f230Smrg			   y_rootrel + (int) curr_attrs->height +
674b3307321Smrg			   2 * (int) curr_attrs->border_width);
675b3307321Smrg
676b3307321Smrg	while (nchild--) {
677b3307321Smrg	    int new_width, new_height;
678b3307321Smrg	    int child_xrr, child_yrr;	/* root relative x & y of child */
679b3307321Smrg
680b3307321Smrg	    XGetWindowAttributes( disp, *child, &child_attrs);
681b3307321Smrg
682b3307321Smrg	    /* intersect parent & child clip rects */
683b3307321Smrg	    child_xrr = x_rootrel + child_attrs.x + curr_attrs->border_width;
684b3307321Smrg	    child_clip.x = MAX( curr_clipX, child_xrr);
685b3307321Smrg	    new_width = MIN( curr_clipRt, child_xrr + (int) child_attrs.width
686b3307321Smrg			     + 2 * child_attrs.border_width)
687b3307321Smrg			- child_clip.x;
688b3307321Smrg	    if (new_width >= 0) {
689b3307321Smrg		child_clip.width = new_width;
690b3307321Smrg
69174a3f230Smrg		child_yrr = y_rootrel + child_attrs.y +
692b3307321Smrg			    curr_attrs->border_width;
693b3307321Smrg		child_clip.y = MAX( curr_clipY, child_yrr);
69474a3f230Smrg		new_height = MIN( curr_clipBt,
69574a3f230Smrg				  child_yrr + (int) child_attrs.height +
69674a3f230Smrg				      2 * child_attrs.border_width)
697b3307321Smrg			     - child_clip.y;
698b3307321Smrg		if (new_height >= 0) {
699b3307321Smrg		    child_clip.height = new_height;
70074a3f230Smrg		    make_src_list( disp, image_wins, bbox, *child,
70174a3f230Smrg				   child_xrr, child_yrr,
702b3307321Smrg				   &child_attrs, &child_clip);
703b3307321Smrg		}
704b3307321Smrg	    }
705b3307321Smrg	    child++;
706b3307321Smrg	}
707b3307321Smrg	XFree( save_child_list);
708b3307321Smrg    }
709b3307321Smrg}
710b3307321Smrg
711b3307321Smrg
712b3307321Smrg/** ------------------------------------------------------------------------
713b3307321Smrg	This function creates a list of regions which tile a specified
714b3307321Smrg	window.  Each region contains all visible portions of the window
715b3307321Smrg	which are drawn with the same visual.  For example, if the
716b3307321Smrg	window consists of subwindows of two different visual types,
71774a3f230Smrg	there will be two regions in the list.
718b3307321Smrg	Returns a pointer to the list.
719b3307321Smrg    ------------------------------------------------------------------------ **/
7205e358ecaSmrgstatic list_ptr make_region_list(Display *disp, Window win, XRectangle *bbox,
7215e358ecaSmrg				 int *hasNonDefault, int numImageVisuals,
7225e358ecaSmrg				 XVisualInfo **pImageVisuals, int *allImage)
723b3307321Smrg{
724b3307321Smrg    XWindowAttributes	win_attrs;
725b3307321Smrg    list		image_wins;
726b3307321Smrg    list_ptr		image_regions;
727b3307321Smrg    list_ptr		srcs_left;
728b3307321Smrg    image_region_type	*new_reg;
729b3307321Smrg    image_win_type	*base_src, *src;
730b3307321Smrg    Region		bbox_region = XCreateRegion();
731b3307321Smrg    XRectangle		clip;
732b3307321Smrg    int			image_only;
733b3307321Smrg
73474a3f230Smrg    int                 count=0 ;
73574a3f230Smrg
736b3307321Smrg    *hasNonDefault = False;
737b3307321Smrg    XUnionRectWithRegion( bbox, bbox_region, bbox_region);
738b3307321Smrg    XGetWindowAttributes( disp, win, &win_attrs);
739b3307321Smrg
740b3307321Smrg    zero_list( &image_wins);
741b3307321Smrg    clip.x = 0;
742b3307321Smrg    clip.y = 0;
743b3307321Smrg    clip.width  = win_attrs.width;
744b3307321Smrg    clip.height = win_attrs.height;
74574a3f230Smrg    make_src_list( disp, &image_wins, bbox, win,
746b3307321Smrg		   0 /* x_rootrel */, 0 /* y_rootrel */, &win_attrs, &clip);
747b3307321Smrg
748b3307321Smrg    image_regions = new_list();
74974a3f230Smrg    image_only = (*allImage) ? True:False;
750b3307321Smrg
751b3307321Smrg    for (base_src = (image_win_type *) first_in_list( &image_wins); base_src;
75274a3f230Smrg	 base_src = (image_win_type *) next_in_list( &image_wins))
753b3307321Smrg    {
754b3307321Smrg	/* test for image visual */
755b3307321Smrg	if (!image_only || src_in_image(base_src, numImageVisuals, pImageVisuals))
756b3307321Smrg	{
757b3307321Smrg	    /* find a window whose visual hasn't been put in list yet */
758b3307321Smrg	    if (!src_in_region_list( base_src, image_regions))
759b3307321Smrg	    {
76074a3f230Smrg		if (! (new_reg = (image_region_type *)
761b3307321Smrg					malloc( sizeof( image_region_type)))) {
762b3307321Smrg		    return (list_ptr) NULL;
763b3307321Smrg		}
76474a3f230Smrg		count++;
76574a3f230Smrg
766b3307321Smrg		new_reg->visible_region = XCreateRegion();
767b3307321Smrg		new_reg->win		= base_src->win;
768b3307321Smrg		new_reg->vis		= base_src->vis;
769b3307321Smrg		new_reg->cmap	 	= base_src->cmap;
770b3307321Smrg		new_reg->x_rootrel	= base_src->x_rootrel;
771b3307321Smrg		new_reg->y_rootrel	= base_src->y_rootrel;
772b3307321Smrg		new_reg->x_vis		= base_src->x_vis;
773b3307321Smrg		new_reg->y_vis		= base_src->y_vis;
774b3307321Smrg		new_reg->width		= base_src->width;
775b3307321Smrg		new_reg->height		= base_src->height;
776b3307321Smrg		new_reg->border		= base_src->border_width;
77774a3f230Smrg
778b3307321Smrg		srcs_left = (list_ptr) dup_list_head( &image_wins, START_AT_CURR);
779b3307321Smrg		for (src = (image_win_type *) first_in_list( srcs_left); src;
780b3307321Smrg		     src = (image_win_type *) next_in_list( srcs_left)) {
781b3307321Smrg		    if (SAME_REGIONS( base_src, src)) {
78274a3f230Smrg			add_rect_to_image_region( new_reg, src->x_vis, src->y_vis,
783b3307321Smrg						  src->width, src->height);
784b3307321Smrg		    }
785b3307321Smrg		    else {
786b3307321Smrg			if (!image_only || src_in_image(src, numImageVisuals, pImageVisuals))
78774a3f230Smrg			{
788b3307321Smrg			    subtr_rect_from_image_region( new_reg, src->x_vis,
789b3307321Smrg					  src->y_vis, src->width, src->height);
79074a3f230Smrg			}
791b3307321Smrg		    }
792b3307321Smrg		}
79374a3f230Smrg		XIntersectRegion( bbox_region, new_reg->visible_region,
794b3307321Smrg				  new_reg->visible_region);
795b3307321Smrg		if (! XEmptyRegion( new_reg->visible_region)) {
796b3307321Smrg		    add_to_list( image_regions, new_reg);
797b3307321Smrg		    if (new_reg->vis != DefaultVisualOfScreen( win_attrs.screen) ||
79874a3f230Smrg			new_reg->cmap != DefaultColormapOfScreen(
799b3307321Smrg							    win_attrs.screen)) {
800b3307321Smrg			*hasNonDefault = True;
801b3307321Smrg		    }
802b3307321Smrg		}
803b3307321Smrg		else {
804b3307321Smrg		    XDestroyRegion( new_reg->visible_region);
805b3307321Smrg		    free( (void *) new_reg);
806b3307321Smrg		}
807b3307321Smrg	    }
808b3307321Smrg	} else *allImage = 0;
809b3307321Smrg    }
810b3307321Smrg    delete_list( &image_wins, True);
811b3307321Smrg    XDestroyRegion( bbox_region);
812b3307321Smrg    return image_regions;
813b3307321Smrg}
814b3307321Smrg/** ------------------------------------------------------------------------
815b3307321Smrg	Destructor called from destroy_region_list().
816b3307321Smrg    ------------------------------------------------------------------------ **/
8175e358ecaSmrgstatic void destroy_image_region(image_region_type *image_region)
818b3307321Smrg{
819b3307321Smrg    XDestroyRegion( image_region->visible_region);
820b3307321Smrg    free( (void *) image_region);
821b3307321Smrg}
822b3307321Smrg
823b3307321Smrg/** ------------------------------------------------------------------------
824b3307321Smrg	Destroys the region list, destroying all the regions contained in it.
825b3307321Smrg    ------------------------------------------------------------------------ **/
8265e358ecaSmrgstatic void destroy_region_list(list_ptr rlist)
827b3307321Smrg{
828b3307321Smrg    delete_list_destroying( rlist, (DESTRUCT_FUNC_PTR)destroy_image_region);
829b3307321Smrg}
830b3307321Smrg
831b3307321Smrg
832b3307321Smrg/** ------------------------------------------------------------------------
833b3307321Smrg	Subtracts the specified rectangle from the region in image_region.
834b3307321Smrg	First converts the rectangle to a region of its own, since X
835b3307321Smrg	only provides a way to subtract one region from another, not a
836b3307321Smrg	rectangle from a region.
837b3307321Smrg    ------------------------------------------------------------------------ **/
8385e358ecaSmrgstatic void subtr_rect_from_image_region(image_region_type *image_region,
8395e358ecaSmrg					 int x, int y, int width, int height)
840b3307321Smrg{
841b3307321Smrg    XRectangle rect;
842b3307321Smrg    Region rect_region;
843b3307321Smrg
844b3307321Smrg    rect_region = XCreateRegion();
845b3307321Smrg    rect.x = x;
846b3307321Smrg    rect.y = y;
847b3307321Smrg    rect.width = width;
848b3307321Smrg    rect.height = height;
849b3307321Smrg    XUnionRectWithRegion( &rect, rect_region, rect_region);
85074a3f230Smrg    XSubtractRegion( image_region->visible_region, rect_region,
851b3307321Smrg		     image_region->visible_region);
852b3307321Smrg    XDestroyRegion( rect_region);
853b3307321Smrg}
854b3307321Smrg
855b3307321Smrg
856b3307321Smrg/** ------------------------------------------------------------------------
857b3307321Smrg	Adds the specified rectangle to the region in image_region.
858b3307321Smrg    ------------------------------------------------------------------------ **/
8595e358ecaSmrgstatic void add_rect_to_image_region(image_region_type *image_region,
8605e358ecaSmrg				     int x, int y, int width, int height)
861b3307321Smrg{
862b3307321Smrg    XRectangle rect;
863b3307321Smrg
864b3307321Smrg    rect.x = x;
865b3307321Smrg    rect.y = y;
866b3307321Smrg    rect.width = width;
867b3307321Smrg    rect.height = height;
86874a3f230Smrg    XUnionRectWithRegion( &rect, image_region->visible_region,
869b3307321Smrg			  image_region->visible_region);
870b3307321Smrg}
871b3307321Smrg
872b3307321Smrg
873b3307321Smrg/** ------------------------------------------------------------------------
874b3307321Smrg	Returns TRUE if the given src's visual is already represented in
875b3307321Smrg	the image_regions list, FALSE otherwise.
876b3307321Smrg    ------------------------------------------------------------------------ **/
8775e358ecaSmrgstatic int src_in_region_list(image_win_type *src, list_ptr image_regions)
878b3307321Smrg{
879b3307321Smrg    image_region_type	*ir;
880b3307321Smrg
881b3307321Smrg    for (ir = (image_region_type *) first_in_list( image_regions); ir;
882b3307321Smrg	 ir = (image_region_type *) next_in_list( image_regions)) {
883b3307321Smrg	if (SAME_REGIONS( ir, src)) {
884b3307321Smrg
885b3307321Smrg	    return 1;
886b3307321Smrg	}
887b3307321Smrg    }
888b3307321Smrg
889b3307321Smrg    return 0;
890b3307321Smrg}
891b3307321Smrg
892b3307321Smrg
893b3307321Smrg/** ------------------------------------------------------------------------
894b3307321Smrg	Makes a new entry in image_wins with the given fields filled in.
895b3307321Smrg    ------------------------------------------------------------------------ **/
8965e358ecaSmrgstatic void add_window_to_list(list_ptr image_wins, Window w,
89774a3f230Smrg			       int xrr, int yrr, int x_vis, int y_vis,
8985e358ecaSmrg			       int width, int height, int border_width,
8995e358ecaSmrg			       Visual *vis, Colormap cmap, Window parent)
900b3307321Smrg{
901b3307321Smrg    image_win_type	*new_src;
902b3307321Smrg
903b3307321Smrg    if ((new_src = (image_win_type *) malloc( sizeof( image_win_type))) == NULL)
904b3307321Smrg
905b3307321Smrg	return;
906b3307321Smrg
907b3307321Smrg    new_src->win = w;
908b3307321Smrg    new_src->x_rootrel = xrr;
909b3307321Smrg    new_src->y_rootrel = yrr;
910b3307321Smrg    new_src->x_vis = x_vis;
911b3307321Smrg    new_src->y_vis = y_vis;
912b3307321Smrg    new_src->width = width;
913b3307321Smrg    new_src->height = height;
914b3307321Smrg    new_src->border_width = border_width;
915b3307321Smrg    new_src->vis = vis;
916b3307321Smrg    new_src->cmap = cmap;
917b3307321Smrg    new_src->parent = parent;
918b3307321Smrg    add_to_list( image_wins, new_src);
919b3307321Smrg}
920b3307321Smrg
921b3307321Smrg/** ------------------------------------------------------------------------
922b3307321Smrg	Returns TRUE if the given src's visual is in the image planes,
923b3307321Smrg	FALSE otherwise.
924b3307321Smrg    ------------------------------------------------------------------------ **/
9255e358ecaSmrgstatic int src_in_image(image_win_type *src, int numImageVisuals,
9265e358ecaSmrg			XVisualInfo **pImageVisuals)
927b3307321Smrg{
928b3307321Smrg    int 		i;
929b3307321Smrg
930b3307321Smrg    for (i = 0 ; i < numImageVisuals ; i++)
931b3307321Smrg    {
932b3307321Smrg	if (pImageVisuals[i]->visual == src->vis)
933b3307321Smrg	    return 1;
934b3307321Smrg    }
935b3307321Smrg    return 0;
936b3307321Smrg}
937b3307321Smrg
938b3307321Smrg
939b3307321Smrg/** ------------------------------------------------------------------------
940b3307321Smrg	Returns TRUE if the given src's visual is in the overlay planes
941b3307321Smrg	and transparency is possible, FALSE otherwise.
942b3307321Smrg    ------------------------------------------------------------------------ **/
9435e358ecaSmrgstatic int src_in_overlay(image_region_type *src, int numOverlayVisuals,
94474a3f230Smrg			  OverlayInfo *pOverlayVisuals,
9455e358ecaSmrg			  int *transparentColor, int *transparentType)
946b3307321Smrg{
947b3307321Smrg    int 		i;
948b3307321Smrg
949b3307321Smrg    for (i = 0 ; i < numOverlayVisuals ; i++)
950b3307321Smrg    {
951b3307321Smrg	if (((pOverlayVisuals[i].pOverlayVisualInfo)->visual == src->vis)
952b3307321Smrg		&& (pOverlayVisuals[i].transparentType != None))
953b3307321Smrg	{
954b3307321Smrg	    *transparentColor = pOverlayVisuals[i].value;
955b3307321Smrg	    *transparentType = pOverlayVisuals[i].transparentType;
956b3307321Smrg	    return 1;
957b3307321Smrg	}
95874a3f230Smrg
959b3307321Smrg	else {
960b3307321Smrg	}
96174a3f230Smrg
962b3307321Smrg    }
963b3307321Smrg    return 0;
964b3307321Smrg}
965b3307321Smrg
966b3307321Smrg
967b3307321Smrg/********************** from wsutils.c ******************************/
968b3307321Smrg
969b3307321Smrg/******************************************************************************
970b3307321Smrg *
971b3307321Smrg * This file contains a set of example utility procedures; procedures that can
972b3307321Smrg * help a "window-smart" Starbase or PHIGS program determine information about
973b3307321Smrg * a device, and create image and overlay plane windows.  To use these
974b3307321Smrg * utilities, #include "wsutils.h" and compile this file and link the results
975b3307321Smrg * with your program.
976b3307321Smrg *
977b3307321Smrg ******************************************************************************/
978b3307321Smrg
979b3307321Smrg
980b3307321Smrg
981b3307321Smrg#define STATIC_GRAY	0x01
982b3307321Smrg#define GRAY_SCALE	0x02
983b3307321Smrg#define PSEUDO_COLOR	0x04
984b3307321Smrg#define TRUE_COLOR	0x10
985b3307321Smrg#define DIRECT_COLOR	0x11
986b3307321Smrg
987b3307321Smrg
988b3307321Smrgstatic int	weCreateServerOverlayVisualsProperty = False;
989b3307321Smrg
990b3307321Smrg
991b3307321Smrg/******************************************************************************
992b3307321Smrg *
993b3307321Smrg * GetXVisualInfo()
994b3307321Smrg *
995b3307321Smrg * This routine takes an X11 Display, screen number, and returns whether the
996b3307321Smrg * screen supports transparent overlays and three arrays:
997b3307321Smrg *
998b3307321Smrg *	1) All of the XVisualInfo struct's for the screen.
999b3307321Smrg *	2) All of the OverlayInfo struct's for the screen.
1000b3307321Smrg *	3) An array of pointers to the screen's image plane XVisualInfo
1001b3307321Smrg *	   structs.
1002b3307321Smrg *
1003b3307321Smrg * The code below obtains the array of all the screen's visuals, and obtains
1004b3307321Smrg * the array of all the screen's overlay visual information.  It then processes
1005b3307321Smrg * the array of the screen's visuals, determining whether the visual is an
1006b3307321Smrg * overlay or image visual.
1007b3307321Smrg *
1008b3307321Smrg * If the routine sucessfully obtained the visual information, it returns zero.
1009b3307321Smrg * If the routine didn't obtain the visual information, it returns non-zero.
1010b3307321Smrg *
1011b3307321Smrg ******************************************************************************/
1012b3307321Smrg
10135e358ecaSmrgint GetXVisualInfo(/* Which X server (aka "display"). */
10145e358ecaSmrg		   Display *display,
10155e358ecaSmrg		   /* Which screen of the "display". */
10165e358ecaSmrg		   int screen,
10175e358ecaSmrg		   /* Non-zero if there's at least one overlay visual and
10185e358ecaSmrg		    * if at least one of those supports a transparent pixel. */
10195e358ecaSmrg		   int *transparentOverlays,
10205e358ecaSmrg		   /* Number of XVisualInfo struct's pointed to by pVisuals. */
10215e358ecaSmrg		   int *numVisuals,
10225e358ecaSmrg		   /* All of the device's visuals. */
10235e358ecaSmrg		   XVisualInfo **pVisuals,
10245e358ecaSmrg		   /* Number of OverlayInfo's pointed to by pOverlayVisuals.
10255e358ecaSmrg		    * If this number is zero, the device does not have
10265e358ecaSmrg		    * overlay planes. */
10275e358ecaSmrg		   int *numOverlayVisuals,
10285e358ecaSmrg		   /* The device's overlay plane visual information. */
10295e358ecaSmrg		   OverlayInfo	**pOverlayVisuals,
10305e358ecaSmrg		   /* Number of XVisualInfo's pointed to by pImageVisuals. */
10315e358ecaSmrg		   int *numImageVisuals,
10325e358ecaSmrg		   /* The device's image visuals. */
10335e358ecaSmrg		   XVisualInfo ***pImageVisuals)
1034b3307321Smrg{
1035b3307321Smrg    XVisualInfo	getVisInfo;		/* Paramters of XGetVisualInfo */
1036b3307321Smrg    int		mask;
1037b3307321Smrg    XVisualInfo	*pVis, **pIVis;		/* Faster, local copies */
1038b3307321Smrg    OverlayInfo	*pOVis;
1039b3307321Smrg    OverlayVisualPropertyRec	*pOOldVis;
1040b3307321Smrg    int		nVisuals, nOVisuals;
1041b3307321Smrg    Atom	overlayVisualsAtom;	/* Parameters for XGetWindowProperty */
1042b3307321Smrg    Atom	actualType;
1043b3307321Smrg    unsigned long numLongs, bytesAfter;
104474a3f230Smrg    int		actualFormat;
1045b3307321Smrg    int		nImageVisualsAlloced;	/* Values to process the XVisualInfo */
1046b3307321Smrg    int		imageVisual;		/* array */
1047b3307321Smrg
1048b3307321Smrg
1049b3307321Smrg    /* First, get the list of visuals for this screen. */
1050b3307321Smrg    getVisInfo.screen = screen;
105174a3f230Smrg    mask = VisualScreenMask;
1052b3307321Smrg
1053b3307321Smrg    *pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals);
1054b3307321Smrg    if ((nVisuals = *numVisuals) <= 0)
1055b3307321Smrg    {
1056b3307321Smrg	/* Return that the information wasn't sucessfully obtained: */
1057b3307321Smrg	return(1);
1058b3307321Smrg    }
1059b3307321Smrg    pVis = *pVisuals;
1060b3307321Smrg
1061b3307321Smrg
1062b3307321Smrg    /* Now, get the overlay visual information for this screen.  To obtain
1063b3307321Smrg     * this information, get the SERVER_OVERLAY_VISUALS property.
1064b3307321Smrg     */
1065b3307321Smrg    overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True);
1066b3307321Smrg    if (overlayVisualsAtom != None)
1067b3307321Smrg    {
1068b3307321Smrg	/* Since the Atom exists, we can request the property's contents.  The
1069b3307321Smrg	 * do-while loop makes sure we get the entire list from the X server.
1070b3307321Smrg	 */
1071b3307321Smrg	bytesAfter = 0;
1072320e696bSmrg	numLongs = sizeof(OverlayVisualPropertyRec) / sizeof(long);
1073b3307321Smrg	do
1074b3307321Smrg	{
1075320e696bSmrg	    numLongs += bytesAfter * sizeof(long);
1076b3307321Smrg	    XGetWindowProperty(display, RootWindow(display, screen),
1077b3307321Smrg			       overlayVisualsAtom, 0, numLongs, False,
1078b3307321Smrg			       overlayVisualsAtom, &actualType, &actualFormat,
1079b3307321Smrg			       &numLongs, &bytesAfter, (unsigned char**) pOverlayVisuals);
1080b3307321Smrg	} while (bytesAfter > 0);
1081b3307321Smrg
1082b3307321Smrg
1083b3307321Smrg	/* Calculate the number of overlay visuals in the list. */
1084320e696bSmrg	*numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / sizeof(long));
1085b3307321Smrg    }
1086b3307321Smrg    else
1087b3307321Smrg    {
1088b3307321Smrg	/* This screen doesn't have overlay planes. */
1089b3307321Smrg	*numOverlayVisuals = 0;
1090b3307321Smrg	*pOverlayVisuals = NULL;
1091b3307321Smrg	*transparentOverlays = 0;
1092b3307321Smrg    }
1093b3307321Smrg
1094b3307321Smrg
1095b3307321Smrg    /* Process the pVisuals array. */
1096b3307321Smrg    *numImageVisuals = 0;
1097b3307321Smrg    nImageVisualsAlloced = 1;
1098b3307321Smrg    pIVis = *pImageVisuals = (XVisualInfo **) malloc(sizeof(XVisualInfo *));
1099b3307321Smrg    while (--nVisuals >= 0)
1100b3307321Smrg    {
1101b3307321Smrg	nOVisuals = *numOverlayVisuals;
1102b3307321Smrg	pOVis = *pOverlayVisuals;
1103b3307321Smrg	imageVisual = True;
1104b3307321Smrg	while (--nOVisuals >= 0)
1105b3307321Smrg	{
1106b3307321Smrg	    pOOldVis = (OverlayVisualPropertyRec *) pOVis;
1107b3307321Smrg	    if (pVis->visualid == pOOldVis->visualID)
1108b3307321Smrg	    {
1109b3307321Smrg		imageVisual = False;
1110b3307321Smrg		pOVis->pOverlayVisualInfo = pVis;
1111b3307321Smrg		if (pOVis->transparentType == TransparentPixel)
1112b3307321Smrg		    *transparentOverlays = 1;
1113b3307321Smrg	    }
1114b3307321Smrg	    pOVis++;
1115b3307321Smrg	}
1116b3307321Smrg	if (imageVisual)
1117b3307321Smrg	{
1118b3307321Smrg	    if ((*numImageVisuals += 1) > nImageVisualsAlloced)
1119b3307321Smrg	    {
1120b3307321Smrg		nImageVisualsAlloced++;
1121b3307321Smrg		*pImageVisuals = (XVisualInfo **)
1122b3307321Smrg		    realloc(*pImageVisuals, (nImageVisualsAlloced * sizeof(XVisualInfo *)));
1123b3307321Smrg		pIVis = *pImageVisuals + (*numImageVisuals - 1);
1124b3307321Smrg	    }
1125b3307321Smrg	    *pIVis++ = pVis;
1126b3307321Smrg	}
1127b3307321Smrg	pVis++;
1128b3307321Smrg    }
1129b3307321Smrg
1130b3307321Smrg
1131b3307321Smrg    /* Return that the information was sucessfully obtained: */
1132b3307321Smrg    return(0);
1133b3307321Smrg
1134b3307321Smrg} /* GetXVisualInfo() */
1135b3307321Smrg
1136b3307321Smrg
1137b3307321Smrg/******************************************************************************
1138b3307321Smrg *
1139b3307321Smrg * FreeXVisualInfo()
1140b3307321Smrg *
1141b3307321Smrg * This routine frees the data that was allocated by GetXVisualInfo().
1142b3307321Smrg *
1143b3307321Smrg ******************************************************************************/
1144b3307321Smrg
11455e358ecaSmrgvoid FreeXVisualInfo(XVisualInfo *pVisuals, OverlayInfo *pOverlayVisuals,
11465e358ecaSmrg		     XVisualInfo **pImageVisuals)
1147b3307321Smrg{
1148b3307321Smrg    XFree(pVisuals);
1149b3307321Smrg    if (weCreateServerOverlayVisualsProperty)
1150b3307321Smrg	free(pOverlayVisuals);
1151b3307321Smrg    else
1152b3307321Smrg	XFree(pOverlayVisuals);
1153b3307321Smrg    free(pImageVisuals);
1154b3307321Smrg
1155b3307321Smrg} /* FreeXVisualInfo() */
1156