multiVis.c revision 320e696b
1b3307321Smrg/** ------------------------------------------------------------------------
2b3307321Smrg	This file contains functions to create a list of regions which
3b3307321Smrg	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>
41320e696bSmrg#include <X11/Intrinsic.h>
42b3307321Smrg#include <stdio.h>
43b3307321Smrg#include "list.h"
44b3307321Smrg#include "wsutils.h"
45b3307321Smrg#include "multiVis.h"
46b3307321Smrg/* These structures are copied from X11/region.h.  For some reason
47b3307321Smrg * they're invisible from the outside.
48b3307321Smrg */
49b3307321Smrgtypedef struct {
50b3307321Smrg    short x1, x2, y1, y2;
51b3307321Smrg} myBox, myBOX, myBoxRec, *myBoxPtr;
52b3307321Smrg
53b3307321Smrgtypedef struct my_XRegion {
54b3307321Smrg    long size;
55b3307321Smrg    long numRects;
56b3307321Smrg    myBOX *rects;
57b3307321Smrg    myBOX extents;
58b3307321Smrg} myREGION;
59b3307321Smrg
60b3307321Smrg/* Items in long list of windows that have some part in the grabbed area */
61b3307321Smrgtypedef struct {
62b3307321Smrg    Window win;
63b3307321Smrg    Visual *vis;
64b3307321Smrg    Colormap cmap;
65b3307321Smrg    int x_rootrel, y_rootrel;	/* root relative location of window */
66b3307321Smrg    int x_vis, y_vis;  		/* rt rel x,y of vis part, not parent clipped */
67b3307321Smrg    int width, height; 		/* width and height of visible part */
68b3307321Smrg    int border_width;		/* border width of the window */
69b3307321Smrg    Window parent;		/* id of parent (for debugging) */
70b3307321Smrg} image_win_type;
71b3307321Smrg
72b3307321Smrg/*  Items in short list of regions that tile the grabbed area.  May have
73b3307321Smrg    multiple windows in the region.
74b3307321Smrg*/
75b3307321Smrgtypedef struct {
76b3307321Smrg    Window win;			/* lowest window of this visual */
77b3307321Smrg    Visual *vis;
78b3307321Smrg    Colormap cmap;
79b3307321Smrg    int x_rootrel, y_rootrel;	/* root relative location of bottom window */
80b3307321Smrg    int x_vis, y_vis;  		/* rt rel x,y of vis part, not parent clipped */
81b3307321Smrg    int width, height;		/* w & h of visible rect of bottom window */
82b3307321Smrg    int border;			/* border width of the window */
83b3307321Smrg    Region visible_region;
84b3307321Smrg} image_region_type;
85b3307321Smrg
86b3307321Smrg/** ------------------------------------------------------------------------
87b3307321Smrg	Returns TRUE if the two structs pointed to have the same "vis" &
88b3307321Smrg	"cmap" fields and s2 lies completely within s1.  s1 and s2 can
89b3307321Smrg	point to structs of image_win_type or image_region_type.
90b3307321Smrg    ------------------------------------------------------------------------ **/
91b3307321Smrg#define SAME_REGIONS( s1, s2)	\
92b3307321Smrg	((s1)->vis == (s2)->vis && (s1)->cmap == (s2)->cmap &&   	\
93b3307321Smrg	 (s1)->x_vis <= (s2)->x_vis &&				    \
94b3307321Smrg	 (s1)->y_vis <= (s2)->y_vis &&				    \
95b3307321Smrg	 (s1)->x_vis + (s1)->width  >= (s2)->x_vis + (s2)->width && \
96b3307321Smrg	 (s1)->y_vis + (s1)->height >= (s2)->y_vis + (s2)->height)
97b3307321Smrg
98b3307321Smrg#ifndef MIN
99b3307321Smrg#define MIN( a, b)	((a) < (b) ? a : b)
100b3307321Smrg#define MAX( a, b)	((a) > (b) ? a : b)
101b3307321Smrg#endif
102b3307321Smrg
103b3307321Smrg#define	RED_SHIFT        16
104b3307321Smrg#define GREEN_SHIFT       8
105b3307321Smrg#define BLUE_SHIFT        0
106b3307321Smrg
107b3307321Smrg/*
108b3307321Smrgextern list_ptr	new_list();
109b3307321Smrgextern list_ptr	dup_list_head();
110b3307321Smrgextern void *	first_in_list();
111b3307321Smrgextern void *	next_in_list();
112b3307321Smrgextern int	add_to_list();
113b3307321Smrgextern void	zero_list();
114b3307321Smrgextern void	delete_list();
115b3307321Smrgextern void	delete_list_destroying();
116b3307321Smrgextern unsigned int list_length();
117b3307321Smrg*/
118b3307321Smrg
119b3307321Smrg/* Prototype Declarations for Static Functions */
120b3307321Smrgstatic int QueryColorMap(
121b3307321Smrg           Display *, Colormap , Visual *,
122b3307321Smrg           XColor **, int *, int *, int *
123b3307321Smrg	   );
124b3307321Smrgstatic void TransferImage(
125b3307321Smrg           Display *, XImage *,int, int , image_region_type*,
126b3307321Smrg           XImage *,int ,int
127b3307321Smrg	   );
128b3307321Smrgstatic XImage * ReadRegionsInList(
129b3307321Smrg           Display *, Visual *, int ,int ,int ,
130b3307321Smrg           int , XRectangle, list_ptr
131b3307321Smrg           );
132b3307321Smrg
133b3307321Smrgstatic list_ptr make_region_list(
134b3307321Smrg                  Display*, Window, XRectangle*,
135b3307321Smrg                  int*, int, XVisualInfo**, int	*
136b3307321Smrg         );
137b3307321Smrg
138b3307321Smrgstatic void destroy_region_list(
139b3307321Smrg            list_ptr
140b3307321Smrg            ) ;
141b3307321Smrgstatic void subtr_rect_from_image_region(
142b3307321Smrg           image_region_type *, int , int , int , int
143b3307321Smrg     );
144b3307321Smrgstatic void add_rect_to_image_region(
145b3307321Smrg           image_region_type *,
146b3307321Smrg           int , int , int , int
147b3307321Smrg     );
148b3307321Smrgstatic int src_in_region_list(
149b3307321Smrg    image_win_type *, list_ptr
150b3307321Smrg    );
151b3307321Smrgstatic void add_window_to_list(
152b3307321Smrg    list_ptr, Window, int, int ,
153b3307321Smrg    int	, int , int , int, int,
154b3307321Smrg    Visual*, Colormap, Window
155b3307321Smrg    );
156b3307321Smrgstatic int src_in_image(
157b3307321Smrg    image_win_type 	*, int	, XVisualInfo**
158b3307321Smrg    );
159b3307321Smrgstatic int src_in_overlay(
160b3307321Smrg    image_region_type *, int, OverlayInfo *, int*, int*
161b3307321Smrg    );
162b3307321Smrgstatic void make_src_list(
163b3307321Smrg    Display *, list_ptr, XRectangle *, Window,
164b3307321Smrg    int, int, XWindowAttributes *, XRectangle *
165b3307321Smrg);
166b3307321Smrgstatic void destroy_image_region(
167b3307321Smrg    image_region_type *
168b3307321Smrg);
169b3307321Smrg
170b3307321Smrg/* End of Prototype Declarations */
171b3307321Smrg
1725e358ecaSmrgvoid initFakeVisual(Visual *Vis)
173b3307321Smrg{
174b3307321Smrg    Vis->ext_data=NULL;
175b3307321Smrg    Vis->class = DirectColor ;
176b3307321Smrg    Vis->red_mask =   0x00FF0000;
177b3307321Smrg    Vis->green_mask = 0x0000FF00 ;
178b3307321Smrg    Vis->blue_mask  = 0x000000FF ;
179b3307321Smrg    Vis->map_entries = 256 ;
180b3307321Smrg    Vis->bits_per_rgb = 8 ;
181b3307321Smrg}
182b3307321Smrg
183b3307321Smrgstatic int
1845e358ecaSmrgQueryColorMap(Display *disp, Colormap src_cmap, Visual *src_vis,
1855e358ecaSmrg	      XColor **src_colors, int *rShift, int *gShift, int *bShift)
186b3307321Smrg{
187b3307321Smrg     int ncolors,i ;
188b3307321Smrg     unsigned long       redMask, greenMask, blueMask;
189b3307321Smrg     int                 redShift, greenShift, blueShift;
190b3307321Smrg     XColor *colors ;
191b3307321Smrg
192b3307321Smrg     ncolors = src_vis->map_entries ;
193b3307321Smrg     *src_colors = colors = (XColor *)malloc(ncolors * sizeof(XColor) ) ;
194b3307321Smrg
195b3307321Smrg     if(src_vis->class != TrueColor && src_vis->class != DirectColor)
196b3307321Smrg     {
197b3307321Smrg         for(i=0 ; i < ncolors ; i++)
198b3307321Smrg         {
199b3307321Smrg	        colors[i].pixel = i ;
200b3307321Smrg                colors[i].pad = 0;
201b3307321Smrg                colors[i].flags = DoRed|DoGreen|DoBlue;
202b3307321Smrg         }
203b3307321Smrg     }
204b3307321Smrg     else /** src is decomposed rgb ***/
205b3307321Smrg     {
206b3307321Smrg        /* Get the X colormap */
207b3307321Smrg        redMask = src_vis->red_mask;
208b3307321Smrg        greenMask = src_vis->green_mask;
209b3307321Smrg        blueMask = src_vis->blue_mask;
210b3307321Smrg        redShift = 0; while (!(redMask&0x1)) {
211b3307321Smrg                redShift++;
212b3307321Smrg                redMask = redMask>>1;
213b3307321Smrg        }
214b3307321Smrg        greenShift = 0; while (!(greenMask&0x1)) {
215b3307321Smrg                greenShift++;
216b3307321Smrg                greenMask = greenMask>>1;
217b3307321Smrg        }
218b3307321Smrg        blueShift = 0; while (!(blueMask&0x1)) {
219b3307321Smrg                blueShift++;
220b3307321Smrg                blueMask = blueMask>>1;
221b3307321Smrg        }
222b3307321Smrg	*rShift = redShift ;
223b3307321Smrg	*gShift = greenShift ;
224b3307321Smrg	*bShift = blueShift ;
225b3307321Smrg        for (i=0; i<ncolors; i++) {
226b3307321Smrg		if( i <= redMask)colors[i].pixel = (i<<redShift) ;
227b3307321Smrg		if( i <= greenMask)colors[i].pixel |= (i<<greenShift) ;
228b3307321Smrg		if( i <= blueMask)colors[i].pixel |= (i<<blueShift) ;
229b3307321Smrg		/***** example :for gecko's 3-3-2 map, blue index should be <= 3.
230b3307321Smrg                colors[i].pixel = (i<<redShift)|(i<<greenShift)|(i<<blueShift);
231b3307321Smrg		*****/
232b3307321Smrg                colors[i].pad = 0;
233b3307321Smrg                colors[i].flags = DoRed|DoGreen|DoBlue;
234b3307321Smrg        }
235b3307321Smrg      }
236b3307321Smrg
237b3307321Smrg
238b3307321Smrg      XQueryColors(disp, src_cmap, colors, ncolors);
239b3307321Smrg      return ncolors ;
240b3307321Smrg}
241b3307321Smrg
242b3307321Smrgint
2435e358ecaSmrgGetMultiVisualRegions(Display *disp,
2445e358ecaSmrg		      /* root win on which grab was done */
2455e358ecaSmrg		      Window srcRootWinid,
2465e358ecaSmrg		      /* root rel UL corner of bounding box of grab */
2475e358ecaSmrg		      int x, int y,
2485e358ecaSmrg		      /* size of bounding box of grab */
2495e358ecaSmrg		      unsigned int width, unsigned int height,
2505e358ecaSmrg		      int *transparentOverlays, int *numVisuals,
2515e358ecaSmrg		      XVisualInfo **pVisuals, int *numOverlayVisuals,
2525e358ecaSmrg		      OverlayInfo **pOverlayVisuals,
2535e358ecaSmrg		      int *numImageVisuals, XVisualInfo ***pImageVisuals,
2545e358ecaSmrg		      /* list of regions to read from */
2555e358ecaSmrg		      list_ptr *vis_regions,
2565e358ecaSmrg		      list_ptr *vis_image_regions, int *allImage)
257b3307321Smrg{
258b3307321Smrg    int                 hasNonDefault;
259b3307321Smrg    XRectangle          bbox;           /* bounding box of grabbed area */
260b3307321Smrg
261b3307321Smrg
262b3307321Smrg    bbox.x = x;                 /* init X rect for bounding box */
263b3307321Smrg    bbox.y = y;
264b3307321Smrg    bbox.width = width;
265b3307321Smrg    bbox.height = height;
266b3307321Smrg
267b3307321Smrg    GetXVisualInfo(disp,DefaultScreen(disp),
268b3307321Smrg                    transparentOverlays,
269b3307321Smrg                    numVisuals, pVisuals,
270b3307321Smrg                    numOverlayVisuals, pOverlayVisuals,
271b3307321Smrg                    numImageVisuals, pImageVisuals);
272b3307321Smrg
273b3307321Smrg    *vis_regions = *vis_image_regions = NULL ;
274b3307321Smrg    if ((*vis_regions = make_region_list( disp, srcRootWinid, &bbox,
275b3307321Smrg                                         &hasNonDefault, *numImageVisuals,
276b3307321Smrg                                         *pImageVisuals, allImage)) == NULL)
277b3307321Smrg    	return 0 ;
278b3307321Smrg
279b3307321Smrg    if (*transparentOverlays)
280b3307321Smrg    {
281b3307321Smrg        *allImage = 1; /* until proven otherwise,
282b3307321Smrg                         this flags that it to be an image only list */
283b3307321Smrg        *vis_image_regions =
284b3307321Smrg                make_region_list( disp, srcRootWinid, &bbox, &hasNonDefault,
285b3307321Smrg                                        *numImageVisuals, *pImageVisuals, allImage);
286b3307321Smrg    }
287b3307321Smrg
288b3307321Smrg    /* if there is a second region in any of the two lists return 1 **/
289b3307321Smrg    if ( ( *vis_regions && (*vis_regions)->next && (*vis_regions)->next->next ) ||
290b3307321Smrg         ( *vis_image_regions && (*vis_image_regions)->next &&
291b3307321Smrg           (*vis_image_regions)->next->next ) ) return 1 ;
292b3307321Smrg    else return 0 ;
293b3307321Smrg
294b3307321Smrg}
295b3307321Smrg
2965e358ecaSmrgstatic void TransferImage(Display *disp, XImage *reg_image,
2975e358ecaSmrg			  int srcw, int srch,
2985e358ecaSmrg			  image_region_type *reg, XImage *target_image,
2995e358ecaSmrg			  int dst_x, int dst_y)
300b3307321Smrg{
301b3307321Smrg    int i,j,old_pixel,new_pixel,red_ind,green_ind,blue_ind ;
302b3307321Smrg    XColor *colors;
303b3307321Smrg    int rShift,gShift,bShift;
304b3307321Smrg
305b3307321Smrg    (void) QueryColorMap(disp,reg->cmap,reg->vis,&colors,
306b3307321Smrg	 &rShift,&gShift,&bShift) ;
307b3307321Smrg
308b3307321Smrg    switch (reg->vis->class) {
309b3307321Smrg    case TrueColor :
310b3307321Smrg       for(i=0 ; i < srch ; i++)
311b3307321Smrg       {
312b3307321Smrg         for(j=0 ; j < srcw ;  j++)
313b3307321Smrg         {
314b3307321Smrg	   old_pixel = XGetPixel(reg_image,j,i) ;
315b3307321Smrg
316b3307321Smrg           if( reg->vis->map_entries == 16) {
317b3307321Smrg
318b3307321Smrg                 red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
319b3307321Smrg	         green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
320b3307321Smrg	         blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
321b3307321Smrg
322b3307321Smrg	         new_pixel = (
323b3307321Smrg			      ((colors[red_ind].red >> 8) << RED_SHIFT)
324b3307321Smrg			      |((colors[green_ind].green >> 8) << GREEN_SHIFT)
325b3307321Smrg			      |((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
326b3307321Smrg                             );
327b3307321Smrg           }
328b3307321Smrg	   else
329b3307321Smrg		new_pixel = old_pixel;
330b3307321Smrg
331b3307321Smrg           XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
332b3307321Smrg
333b3307321Smrg         }
334b3307321Smrg       }
335b3307321Smrg       break;
336b3307321Smrg    case DirectColor :
337b3307321Smrg       for(i=0 ; i < srch ; i++)
338b3307321Smrg       {
339b3307321Smrg
340b3307321Smrg         for(j=0 ; j < srcw ;  j++)
341b3307321Smrg         {
342b3307321Smrg	   old_pixel = XGetPixel(reg_image,j,i) ;
343b3307321Smrg           red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
344b3307321Smrg	   green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
345b3307321Smrg	   blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
346b3307321Smrg
347b3307321Smrg	   new_pixel = (
348b3307321Smrg			 ((colors[red_ind].red >> 8) << RED_SHIFT)
349b3307321Smrg			|((colors[green_ind].green >> 8) << GREEN_SHIFT)
350b3307321Smrg			|((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
351b3307321Smrg                       );
352b3307321Smrg           XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
353b3307321Smrg
354b3307321Smrg         }
355b3307321Smrg       }
356b3307321Smrg       break;
357b3307321Smrg    default :
358b3307321Smrg       for(i=0 ; i < srch ; i++)
359b3307321Smrg       {
360b3307321Smrg         for(j=0 ; j < srcw ;  j++)
361b3307321Smrg         {
362b3307321Smrg	    old_pixel = XGetPixel(reg_image,j,i) ;
363b3307321Smrg
364b3307321Smrg	   new_pixel = (
365b3307321Smrg			 ((colors[old_pixel].red >> 8) << RED_SHIFT)
366b3307321Smrg			|((colors[old_pixel].green >> 8) << GREEN_SHIFT)
367b3307321Smrg			|((colors[old_pixel].blue >> 8) << BLUE_SHIFT)
368b3307321Smrg                       );
369b3307321Smrg           XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
370b3307321Smrg
371b3307321Smrg         }
372b3307321Smrg       }
373b3307321Smrg       break;
374b3307321Smrg    }
375b3307321Smrg}
376b3307321Smrg
377b3307321Smrgstatic XImage *
3785e358ecaSmrgReadRegionsInList(Display *disp, Visual *fakeVis, int depth, int format,
3795e358ecaSmrg		  int width,int height,
3805e358ecaSmrg		  XRectangle bbox,	/* bounding box of grabbed area */
3815e358ecaSmrg		  list_ptr regions)	/* list of regions to read from */
382b3307321Smrg{
383b3307321Smrg    image_region_type	*reg;
384b3307321Smrg    int			dst_x, dst_y;	/* where in pixmap to write (UL) */
385b3307321Smrg    int			diff;
386b3307321Smrg
387b3307321Smrg    XImage		*reg_image,*ximage ;
388b3307321Smrg    int			srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
389b3307321Smrg    int                 bytes_per_line;
390b3307321Smrg    int                 bitmap_unit;
391b3307321Smrg
392b3307321Smrg    bitmap_unit = sizeof (long);
393b3307321Smrg
394b3307321Smrg    ximage = XCreateImage(disp,fakeVis,depth,format,0,NULL,width,height,
395b3307321Smrg	         8,0) ;
396b3307321Smrg    bytes_per_line = ximage->bytes_per_line;
397b3307321Smrg
398b3307321Smrg    if (format == ZPixmap)
399b3307321Smrg    	  ximage->data = malloc(height*bytes_per_line);
400b3307321Smrg    else
401b3307321Smrg        ximage->data = malloc(height*bytes_per_line*depth);
402b3307321Smrg
403b3307321Smrg    ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/
404b3307321Smrg
405b3307321Smrg    for (reg = (image_region_type *) first_in_list( regions); reg;
406b3307321Smrg	 reg = (image_region_type *) next_in_list( regions))
407b3307321Smrg    {
408b3307321Smrg		int rect;
409b3307321Smrg		struct my_XRegion *vis_reg;
410b3307321Smrg		vis_reg = (struct my_XRegion *)(reg->visible_region);
411b3307321Smrg		for (rect = 0;
412b3307321Smrg		     rect < vis_reg->numRects;
413b3307321Smrg		     rect++)
414b3307321Smrg		{
415b3307321Smrg		/** ------------------------------------------------------------------------
416b3307321Smrg			Intersect bbox with visible part of region giving src rect & output
417b3307321Smrg			location.  Width is the min right side minus the max left side.
418b3307321Smrg			Similar for height.  Offset src rect so x,y are relative to
419b3307321Smrg			origin of win, not the root-relative visible rect of win.
420b3307321Smrg		    ------------------------------------------------------------------------ **/
421b3307321Smrg		    srcRect_width  = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x) -
422b3307321Smrg				     MAX( vis_reg->rects[rect].x1, bbox.x);
423b3307321Smrg		    srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y) -
424b3307321Smrg				     MAX( vis_reg->rects[rect].y1, bbox.y);
425b3307321Smrg		    diff = bbox.x - vis_reg->rects[rect].x1;
426b3307321Smrg		    srcRect_x = MAX( 0, diff)  + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border);
427b3307321Smrg		    dst_x     = MAX( 0, -diff) ;
428b3307321Smrg		    diff = bbox.y - vis_reg->rects[rect].y1;
429b3307321Smrg		    srcRect_y = MAX( 0, diff)  + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border);
430b3307321Smrg		    dst_y     = MAX( 0, -diff) ;
431b3307321Smrg                    reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y,
432b3307321Smrg				srcRect_width,srcRect_height,AllPlanes,format) ;
433b3307321Smrg		    TransferImage(disp,reg_image,srcRect_width,
434b3307321Smrg		                 srcRect_height,reg,ximage,dst_x,dst_y) ;
435b3307321Smrg	    }
436b3307321Smrg    }
437b3307321Smrg    return ximage ;
438b3307321Smrg}
439b3307321Smrg
440b3307321Smrg
441b3307321Smrg/** ------------------------------------------------------------------------
442b3307321Smrg    ------------------------------------------------------------------------ **/
443b3307321Smrg
4445e358ecaSmrgXImage *ReadAreaToImage(Display *disp,
4455e358ecaSmrg			/* root win on which grab was done */
4465e358ecaSmrg			Window srcRootWinid,
4475e358ecaSmrg			/* root rel UL corner of bounding box of grab */
4485e358ecaSmrg			int x, int y,
4495e358ecaSmrg			/* size of bounding box of grab */
4505e358ecaSmrg			unsigned int width, unsigned int height,
4515e358ecaSmrg			int numVisuals, XVisualInfo *pVisuals,
4525e358ecaSmrg			int numOverlayVisuals, OverlayInfo *pOverlayVisuals,
4535e358ecaSmrg			int numImageVisuals, XVisualInfo **pImageVisuals,
4545e358ecaSmrg			/* list of regions to read from */
4555e358ecaSmrg			list_ptr vis_regions,
4565e358ecaSmrg			/* list of regions to read from */
4575e358ecaSmrg			list_ptr vis_image_regions,
4585e358ecaSmrg			int format, int allImage)
459b3307321Smrg{
460b3307321Smrg    image_region_type	*reg;
461b3307321Smrg    XRectangle		bbox;		/* bounding box of grabbed area */
462b3307321Smrg    int 		depth ;
463b3307321Smrg    XImage		*ximage, *ximage_ipm = NULL;
464b3307321Smrg    Visual		fakeVis ;
465b3307321Smrg    int 	x1, y1;
466b3307321Smrg    XImage	*image;
467b3307321Smrg#if 0
468b3307321Smrg    unsigned char 	*pmData ,  *ipmData ;
469b3307321Smrg#endif
470b3307321Smrg    int                 transparentColor, transparentType;
471b3307321Smrg    int			srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
472b3307321Smrg    int			diff ;
473b3307321Smrg    int			dst_x, dst_y;	/* where in pixmap to write (UL) */
474b3307321Smrg    int			pixel;
475b3307321Smrg
476b3307321Smrg    bbox.x = x;			/* init X rect for bounding box */
477b3307321Smrg    bbox.y = y;
478b3307321Smrg    bbox.width = width;
479b3307321Smrg    bbox.height = height;
480b3307321Smrg
481b3307321Smrg
482b3307321Smrg    initFakeVisual(&fakeVis) ;
483b3307321Smrg
484b3307321Smrg    depth = 24 ;
485b3307321Smrg    ximage = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
486b3307321Smrg	     bbox,vis_regions) ;
487b3307321Smrg#if 0
488b3307321Smrg    pmData = (unsigned char *)ximage -> data ;
489b3307321Smrg#endif
490b3307321Smrg
491b3307321Smrg/* if transparency possible do it again, but this time for image planes only */
492b3307321Smrg    if (vis_image_regions && (vis_image_regions->next) && !allImage)
493b3307321Smrg    {
494b3307321Smrg	ximage_ipm = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
495b3307321Smrg		     bbox,vis_image_regions) ;
496b3307321Smrg#if 0
497b3307321Smrg        ipmData = (unsigned char *)ximage_ipm -> data ;
498b3307321Smrg#endif
499b3307321Smrg    }
500b3307321Smrg/* Now tranverse the overlay visual windows and test for transparency index.  */
501b3307321Smrg/* If you find one, subsitute the value from the matching image plane pixmap. */
502b3307321Smrg
503b3307321Smrg    for (reg = (image_region_type *) first_in_list( vis_regions); reg;
504b3307321Smrg	 reg = (image_region_type *) next_in_list( vis_regions))
505b3307321Smrg    {
506b3307321Smrg
507b3307321Smrg	if (src_in_overlay( reg, numOverlayVisuals, pOverlayVisuals,
508b3307321Smrg				 &transparentColor, &transparentType))
509b3307321Smrg	{
510b3307321Smrg	int test = 0 ;
511b3307321Smrg	     srcRect_width  = MIN( reg->width + reg->x_vis, bbox.width + bbox.x)
512b3307321Smrg				 - MAX( reg->x_vis, bbox.x);
513b3307321Smrg	     srcRect_height = MIN( reg->height + reg->y_vis, bbox.height
514b3307321Smrg				 + bbox.y) - MAX( reg->y_vis, bbox.y);
515b3307321Smrg             diff = bbox.x - reg->x_vis;
516b3307321Smrg             srcRect_x = MAX( 0, diff)  + (reg->x_vis - reg->x_rootrel - reg->border);
517b3307321Smrg             dst_x     = MAX( 0, -diff) ;
518b3307321Smrg	     diff = bbox.y - reg->y_vis;
519b3307321Smrg	     srcRect_y = MAX( 0, diff)  + (reg->y_vis - reg->y_rootrel - reg->border);
520b3307321Smrg	     dst_y     = MAX( 0, -diff) ;
521b3307321Smrg	/* let's test some pixels for transparency */
522b3307321Smrg             image = XGetImage(disp, reg->win, srcRect_x, srcRect_y,
523b3307321Smrg		 srcRect_width, srcRect_height, 0xffffffff, ZPixmap);
524b3307321Smrg
525b3307321Smrg        /* let's assume byte per pixel for overlay image for now */
526b3307321Smrg	     if ((image->depth == 8) && (transparentType == TransparentPixel))
527b3307321Smrg	     {
528b3307321Smrg	         unsigned char *pixel_ptr;
529b3307321Smrg	         unsigned char *start_of_line = (unsigned char *) image->data;
530b3307321Smrg
531b3307321Smrg	         for (y1 = 0; y1 < srcRect_height; y1++) {
532b3307321Smrg		    pixel_ptr = start_of_line;
533b3307321Smrg		    for (x1 = 0; x1 < srcRect_width; x1++)
534b3307321Smrg		    {
535b3307321Smrg			if (*pixel_ptr++ == transparentColor)
536b3307321Smrg			{
537b3307321Smrg#if 0
538b3307321Smrg			    *pmData++ = *ipmData++;
539b3307321Smrg			    *pmData++ = *ipmData++;
540b3307321Smrg			    *pmData++ = *ipmData++;
541b3307321Smrg#endif
542b3307321Smrg	                pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
543b3307321Smrg                        XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
544b3307321Smrg
545b3307321Smrg			if(!test){
546b3307321Smrg			   test = 1 ;
547b3307321Smrg			}
548b3307321Smrg			}
549b3307321Smrg#if 0
550b3307321Smrg			else {
551b3307321Smrg			    pmData +=3;
552b3307321Smrg			    ipmData +=3;
553b3307321Smrg			}
554b3307321Smrg#endif
555b3307321Smrg		    }
556b3307321Smrg		    start_of_line += image->bytes_per_line;
557b3307321Smrg		}
558b3307321Smrg	} else {
559b3307321Smrg		if (transparentType == TransparentPixel) {
560b3307321Smrg		for (y1 = 0; y1 < srcRect_height; y1++) {
561b3307321Smrg		      for (x1 = 0; x1 < srcRect_width; x1++)
562b3307321Smrg		      {
563b3307321Smrg			    int pixel_value = XGetPixel(image, x1, y1);
564b3307321Smrg			    if (pixel_value == transparentColor)
565b3307321Smrg			    {
566b3307321Smrg#if 0
567b3307321Smrg				*pmData++ = *ipmData++;
568b3307321Smrg				*pmData++ = *ipmData++;
569b3307321Smrg				*pmData++ = *ipmData++;
570b3307321Smrg#endif
571b3307321Smrg	                pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
572b3307321Smrg                        XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
573b3307321Smrg			if(!test){
574b3307321Smrg			   test = 1 ;
575b3307321Smrg			}
576b3307321Smrg			    }
577b3307321Smrg#if 0
578b3307321Smrg			    else {
579b3307321Smrg				pmData +=3;
580b3307321Smrg				ipmData +=3;
581b3307321Smrg			    }
582b3307321Smrg#endif
583b3307321Smrg			}
584b3307321Smrg		    }
585b3307321Smrg		} else {
586b3307321Smrg		    for (y1 = 0; y1 < srcRect_height; y1++) {
587b3307321Smrg			for (x1 = 0; x1 < srcRect_width; x1++)
588b3307321Smrg			{
589b3307321Smrg			    int pixel_value = XGetPixel(image, x1, y1);
590b3307321Smrg			    if (pixel_value & transparentColor)
591b3307321Smrg			    {
592b3307321Smrg#if 0
593b3307321Smrg				*pmData++ = *ipmData++;
594b3307321Smrg				*pmData++ = *ipmData++;
595b3307321Smrg				*pmData++ = *ipmData++;
596b3307321Smrg#endif
597b3307321Smrg	                        pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
598b3307321Smrg                                XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
599b3307321Smrg			if(!test){
600b3307321Smrg			   test = 1 ;
601b3307321Smrg			}
602b3307321Smrg			    }
603b3307321Smrg#if 0
604b3307321Smrg			    else {
605b3307321Smrg				pmData +=3;
606b3307321Smrg				ipmData +=3;
607b3307321Smrg			    }
608b3307321Smrg#endif
609b3307321Smrg			}
610b3307321Smrg		    }
611b3307321Smrg		}
612b3307321Smrg	}
613b3307321Smrg        XDestroyImage (image);
614b3307321Smrg      }	/* end of src_in_overlay */
615b3307321Smrg    } /** end transparency **/
616b3307321Smrg    destroy_region_list( vis_regions);
617b3307321Smrg    if (vis_image_regions) destroy_region_list( vis_image_regions );
618b3307321Smrg    FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals);
619b3307321Smrg    XSync(disp, 0);
620b3307321Smrg
621b3307321Smrg    return ximage;
622b3307321Smrg}
623b3307321Smrg
624b3307321Smrg/** ------------------------------------------------------------------------
625b3307321Smrg	Creates a list of the subwindows of a given window which have a
626b3307321Smrg	different visual than their parents.  The function is recursive.
627b3307321Smrg	This list is used in make_region_list(), which coalesces the
628b3307321Smrg	windows with the same visual into a region.
629b3307321Smrg	image_wins must point to an existing list struct that's already
630b3307321Smrg	been zeroed (zero_list()).
631b3307321Smrg    ------------------------------------------------------------------------ **/
6325e358ecaSmrgstatic void make_src_list(Display *disp, list_ptr image_wins,
6335e358ecaSmrg			  /* bnding box of area we want */
6345e358ecaSmrg			  XRectangle *bbox,
6355e358ecaSmrg			  Window curr,
6365e358ecaSmrg			  /* pos of curr WRT root */
6375e358ecaSmrg			  int x_rootrel, int y_rootrel,
6385e358ecaSmrg			  XWindowAttributes *curr_attrs,
6395e358ecaSmrg			  /* visible part of curr, not obscurred by ancestors */
6405e358ecaSmrg			  XRectangle *pclip)
641b3307321Smrg{
642b3307321Smrg    XWindowAttributes child_attrs;
643b3307321Smrg    Window root, parent, *child;	/* variables for XQueryTree() */
644b3307321Smrg    Window *save_child_list;		/* variables for XQueryTree() */
645b3307321Smrg    unsigned int nchild;		/* variables for XQueryTree() */
646b3307321Smrg    XRectangle child_clip;		/* vis part of child */
647b3307321Smrg    int curr_clipX, curr_clipY, curr_clipRt, curr_clipBt;
648b3307321Smrg
649b3307321Smrg    /* check that win is mapped & not outside bounding box */
650b3307321Smrg    if (curr_attrs->map_state == IsViewable &&
651b3307321Smrg	curr_attrs->class == InputOutput &&
652b3307321Smrg	!( pclip->x >= (int) (bbox->x + bbox->width)	||
653b3307321Smrg	   pclip->y >= (int) (bbox->y + bbox->height)	||
654b3307321Smrg	   (int) (pclip->x + pclip->width)  <= bbox->x	||
655b3307321Smrg	   (int) (pclip->y + pclip->height) <= bbox->y)) {
656b3307321Smrg
657b3307321Smrg	XQueryTree( disp, curr, &root, &parent, &child, &nchild );
658b3307321Smrg	save_child_list = child;      /* so we can free list when we're done */
659b3307321Smrg	add_window_to_list( image_wins, curr, x_rootrel, y_rootrel,
660b3307321Smrg			    pclip->x, pclip->y,
661b3307321Smrg			    pclip->width, pclip->height,
662b3307321Smrg			    curr_attrs->border_width,curr_attrs->visual,
663b3307321Smrg			    curr_attrs->colormap, parent);
664b3307321Smrg
665b3307321Smrg
666b3307321Smrg/** ------------------------------------------------------------------------
667b3307321Smrg	set RR coords of right (Rt), left (X), bottom (Bt) and top (Y)
668b3307321Smrg	of rect we clip all children by.  This is our own clip rect (pclip)
669b3307321Smrg	inflicted on us by our parent plus our own borders.  Within the
670b3307321Smrg	child loop, we figure the clip rect for each child by adding in
671b3307321Smrg	it's rectangle (not taking into account the child's borders).
672b3307321Smrg    ------------------------------------------------------------------------ **/
673b3307321Smrg	curr_clipX = MAX( pclip->x, x_rootrel + (int) curr_attrs->border_width);
674b3307321Smrg	curr_clipY = MAX( pclip->y, y_rootrel + (int) curr_attrs->border_width);
675b3307321Smrg	curr_clipRt = MIN( pclip->x + (int) pclip->width,
676b3307321Smrg			   x_rootrel + (int) curr_attrs->width +
677b3307321Smrg			   2 * (int) curr_attrs->border_width);
678b3307321Smrg	curr_clipBt = MIN( pclip->y + (int) pclip->height,
679b3307321Smrg			   y_rootrel + (int) curr_attrs->height +
680b3307321Smrg			   2 * (int) curr_attrs->border_width);
681b3307321Smrg
682b3307321Smrg	while (nchild--) {
683b3307321Smrg	    int new_width, new_height;
684b3307321Smrg	    int child_xrr, child_yrr;	/* root relative x & y of child */
685b3307321Smrg
686b3307321Smrg	    XGetWindowAttributes( disp, *child, &child_attrs);
687b3307321Smrg
688b3307321Smrg	    /* intersect parent & child clip rects */
689b3307321Smrg	    child_xrr = x_rootrel + child_attrs.x + curr_attrs->border_width;
690b3307321Smrg	    child_clip.x = MAX( curr_clipX, child_xrr);
691b3307321Smrg	    new_width = MIN( curr_clipRt, child_xrr + (int) child_attrs.width
692b3307321Smrg			     + 2 * child_attrs.border_width)
693b3307321Smrg			- child_clip.x;
694b3307321Smrg	    if (new_width >= 0) {
695b3307321Smrg		child_clip.width = new_width;
696b3307321Smrg
697b3307321Smrg		child_yrr = y_rootrel + child_attrs.y +
698b3307321Smrg			    curr_attrs->border_width;
699b3307321Smrg		child_clip.y = MAX( curr_clipY, child_yrr);
700b3307321Smrg		new_height = MIN( curr_clipBt,
701b3307321Smrg				  child_yrr + (int) child_attrs.height +
702b3307321Smrg				      2 * child_attrs.border_width)
703b3307321Smrg			     - child_clip.y;
704b3307321Smrg		if (new_height >= 0) {
705b3307321Smrg		    child_clip.height = new_height;
706b3307321Smrg		    make_src_list( disp, image_wins, bbox, *child,
707b3307321Smrg				   child_xrr, child_yrr,
708b3307321Smrg				   &child_attrs, &child_clip);
709b3307321Smrg		}
710b3307321Smrg	    }
711b3307321Smrg	    child++;
712b3307321Smrg	}
713b3307321Smrg	XFree( save_child_list);
714b3307321Smrg    }
715b3307321Smrg}
716b3307321Smrg
717b3307321Smrg
718b3307321Smrg/** ------------------------------------------------------------------------
719b3307321Smrg	This function creates a list of regions which tile a specified
720b3307321Smrg	window.  Each region contains all visible portions of the window
721b3307321Smrg	which are drawn with the same visual.  For example, if the
722b3307321Smrg	window consists of subwindows of two different visual types,
723b3307321Smrg	there will be two regions in the list.
724b3307321Smrg	Returns a pointer to the list.
725b3307321Smrg    ------------------------------------------------------------------------ **/
7265e358ecaSmrgstatic list_ptr make_region_list(Display *disp, Window win, XRectangle *bbox,
7275e358ecaSmrg				 int *hasNonDefault, int numImageVisuals,
7285e358ecaSmrg				 XVisualInfo **pImageVisuals, int *allImage)
729b3307321Smrg{
730b3307321Smrg    XWindowAttributes	win_attrs;
731b3307321Smrg    list		image_wins;
732b3307321Smrg    list_ptr		image_regions;
733b3307321Smrg    list_ptr		srcs_left;
734b3307321Smrg    image_region_type	*new_reg;
735b3307321Smrg    image_win_type	*base_src, *src;
736b3307321Smrg    Region		bbox_region = XCreateRegion();
737b3307321Smrg    XRectangle		clip;
738b3307321Smrg    int			image_only;
739b3307321Smrg
740b3307321Smrg    int                 count=0 ;
741b3307321Smrg
742b3307321Smrg    *hasNonDefault = False;
743b3307321Smrg    XUnionRectWithRegion( bbox, bbox_region, bbox_region);
744b3307321Smrg    XGetWindowAttributes( disp, win, &win_attrs);
745b3307321Smrg
746b3307321Smrg    zero_list( &image_wins);
747b3307321Smrg    clip.x = 0;
748b3307321Smrg    clip.y = 0;
749b3307321Smrg    clip.width  = win_attrs.width;
750b3307321Smrg    clip.height = win_attrs.height;
751b3307321Smrg    make_src_list( disp, &image_wins, bbox, win,
752b3307321Smrg		   0 /* x_rootrel */, 0 /* y_rootrel */, &win_attrs, &clip);
753b3307321Smrg
754b3307321Smrg    image_regions = new_list();
755b3307321Smrg    image_only = (*allImage) ? True:False;
756b3307321Smrg
757b3307321Smrg    for (base_src = (image_win_type *) first_in_list( &image_wins); base_src;
758b3307321Smrg	 base_src = (image_win_type *) next_in_list( &image_wins))
759b3307321Smrg    {
760b3307321Smrg	/* test for image visual */
761b3307321Smrg	if (!image_only || src_in_image(base_src, numImageVisuals, pImageVisuals))
762b3307321Smrg	{
763b3307321Smrg	    /* find a window whose visual hasn't been put in list yet */
764b3307321Smrg	    if (!src_in_region_list( base_src, image_regions))
765b3307321Smrg	    {
766b3307321Smrg		if (! (new_reg = (image_region_type *)
767b3307321Smrg					malloc( sizeof( image_region_type)))) {
768b3307321Smrg		    return (list_ptr) NULL;
769b3307321Smrg		}
770b3307321Smrg		count++;
771b3307321Smrg
772b3307321Smrg		new_reg->visible_region = XCreateRegion();
773b3307321Smrg		new_reg->win		= base_src->win;
774b3307321Smrg		new_reg->vis		= base_src->vis;
775b3307321Smrg		new_reg->cmap	 	= base_src->cmap;
776b3307321Smrg		new_reg->x_rootrel	= base_src->x_rootrel;
777b3307321Smrg		new_reg->y_rootrel	= base_src->y_rootrel;
778b3307321Smrg		new_reg->x_vis		= base_src->x_vis;
779b3307321Smrg		new_reg->y_vis		= base_src->y_vis;
780b3307321Smrg		new_reg->width		= base_src->width;
781b3307321Smrg		new_reg->height		= base_src->height;
782b3307321Smrg		new_reg->border		= base_src->border_width;
783b3307321Smrg
784b3307321Smrg		srcs_left = (list_ptr) dup_list_head( &image_wins, START_AT_CURR);
785b3307321Smrg		for (src = (image_win_type *) first_in_list( srcs_left); src;
786b3307321Smrg		     src = (image_win_type *) next_in_list( srcs_left)) {
787b3307321Smrg		    if (SAME_REGIONS( base_src, src)) {
788b3307321Smrg			add_rect_to_image_region( new_reg, src->x_vis, src->y_vis,
789b3307321Smrg						  src->width, src->height);
790b3307321Smrg		    }
791b3307321Smrg		    else {
792b3307321Smrg			if (!image_only || src_in_image(src, numImageVisuals, pImageVisuals))
793b3307321Smrg			{
794b3307321Smrg			    subtr_rect_from_image_region( new_reg, src->x_vis,
795b3307321Smrg					  src->y_vis, src->width, src->height);
796b3307321Smrg			}
797b3307321Smrg		    }
798b3307321Smrg		}
799b3307321Smrg		XIntersectRegion( bbox_region, new_reg->visible_region,
800b3307321Smrg				  new_reg->visible_region);
801b3307321Smrg		if (! XEmptyRegion( new_reg->visible_region)) {
802b3307321Smrg		    add_to_list( image_regions, new_reg);
803b3307321Smrg		    if (new_reg->vis != DefaultVisualOfScreen( win_attrs.screen) ||
804b3307321Smrg			new_reg->cmap != DefaultColormapOfScreen(
805b3307321Smrg							    win_attrs.screen)) {
806b3307321Smrg			*hasNonDefault = True;
807b3307321Smrg		    }
808b3307321Smrg		}
809b3307321Smrg		else {
810b3307321Smrg		    XDestroyRegion( new_reg->visible_region);
811b3307321Smrg		    free( (void *) new_reg);
812b3307321Smrg		}
813b3307321Smrg	    }
814b3307321Smrg	} else *allImage = 0;
815b3307321Smrg    }
816b3307321Smrg    delete_list( &image_wins, True);
817b3307321Smrg    XDestroyRegion( bbox_region);
818b3307321Smrg    return image_regions;
819b3307321Smrg}
820b3307321Smrg/** ------------------------------------------------------------------------
821b3307321Smrg	Destructor called from destroy_region_list().
822b3307321Smrg    ------------------------------------------------------------------------ **/
8235e358ecaSmrgstatic void destroy_image_region(image_region_type *image_region)
824b3307321Smrg{
825b3307321Smrg    XDestroyRegion( image_region->visible_region);
826b3307321Smrg    free( (void *) image_region);
827b3307321Smrg}
828b3307321Smrg
829b3307321Smrg/** ------------------------------------------------------------------------
830b3307321Smrg	Destroys the region list, destroying all the regions contained in it.
831b3307321Smrg    ------------------------------------------------------------------------ **/
8325e358ecaSmrgstatic void destroy_region_list(list_ptr rlist)
833b3307321Smrg{
834b3307321Smrg    delete_list_destroying( rlist, (DESTRUCT_FUNC_PTR)destroy_image_region);
835b3307321Smrg}
836b3307321Smrg
837b3307321Smrg
838b3307321Smrg/** ------------------------------------------------------------------------
839b3307321Smrg	Subtracts the specified rectangle from the region in image_region.
840b3307321Smrg	First converts the rectangle to a region of its own, since X
841b3307321Smrg	only provides a way to subtract one region from another, not a
842b3307321Smrg	rectangle from a region.
843b3307321Smrg    ------------------------------------------------------------------------ **/
8445e358ecaSmrgstatic void subtr_rect_from_image_region(image_region_type *image_region,
8455e358ecaSmrg					 int x, int y, int width, int height)
846b3307321Smrg{
847b3307321Smrg    XRectangle rect;
848b3307321Smrg    Region rect_region;
849b3307321Smrg
850b3307321Smrg    rect_region = XCreateRegion();
851b3307321Smrg    rect.x = x;
852b3307321Smrg    rect.y = y;
853b3307321Smrg    rect.width = width;
854b3307321Smrg    rect.height = height;
855b3307321Smrg    XUnionRectWithRegion( &rect, rect_region, rect_region);
856b3307321Smrg    XSubtractRegion( image_region->visible_region, rect_region,
857b3307321Smrg		     image_region->visible_region);
858b3307321Smrg    XDestroyRegion( rect_region);
859b3307321Smrg}
860b3307321Smrg
861b3307321Smrg
862b3307321Smrg/** ------------------------------------------------------------------------
863b3307321Smrg	Adds the specified rectangle to the region in image_region.
864b3307321Smrg    ------------------------------------------------------------------------ **/
8655e358ecaSmrgstatic void add_rect_to_image_region(image_region_type *image_region,
8665e358ecaSmrg				     int x, int y, int width, int height)
867b3307321Smrg{
868b3307321Smrg    XRectangle rect;
869b3307321Smrg
870b3307321Smrg    rect.x = x;
871b3307321Smrg    rect.y = y;
872b3307321Smrg    rect.width = width;
873b3307321Smrg    rect.height = height;
874b3307321Smrg    XUnionRectWithRegion( &rect, image_region->visible_region,
875b3307321Smrg			  image_region->visible_region);
876b3307321Smrg}
877b3307321Smrg
878b3307321Smrg
879b3307321Smrg/** ------------------------------------------------------------------------
880b3307321Smrg	Returns TRUE if the given src's visual is already represented in
881b3307321Smrg	the image_regions list, FALSE otherwise.
882b3307321Smrg    ------------------------------------------------------------------------ **/
8835e358ecaSmrgstatic int src_in_region_list(image_win_type *src, list_ptr image_regions)
884b3307321Smrg{
885b3307321Smrg    image_region_type	*ir;
886b3307321Smrg
887b3307321Smrg    for (ir = (image_region_type *) first_in_list( image_regions); ir;
888b3307321Smrg	 ir = (image_region_type *) next_in_list( image_regions)) {
889b3307321Smrg	if (SAME_REGIONS( ir, src)) {
890b3307321Smrg
891b3307321Smrg	    return 1;
892b3307321Smrg	}
893b3307321Smrg    }
894b3307321Smrg
895b3307321Smrg    return 0;
896b3307321Smrg}
897b3307321Smrg
898b3307321Smrg
899b3307321Smrg/** ------------------------------------------------------------------------
900b3307321Smrg	Makes a new entry in image_wins with the given fields filled in.
901b3307321Smrg    ------------------------------------------------------------------------ **/
9025e358ecaSmrgstatic void add_window_to_list(list_ptr image_wins, Window w,
9035e358ecaSmrg			       int xrr, int yrr, int x_vis, int y_vis,
9045e358ecaSmrg			       int width, int height, int border_width,
9055e358ecaSmrg			       Visual *vis, Colormap cmap, Window parent)
906b3307321Smrg{
907b3307321Smrg    image_win_type	*new_src;
908b3307321Smrg
909b3307321Smrg    if ((new_src = (image_win_type *) malloc( sizeof( image_win_type))) == NULL)
910b3307321Smrg
911b3307321Smrg	return;
912b3307321Smrg
913b3307321Smrg    new_src->win = w;
914b3307321Smrg    new_src->x_rootrel = xrr;
915b3307321Smrg    new_src->y_rootrel = yrr;
916b3307321Smrg    new_src->x_vis = x_vis;
917b3307321Smrg    new_src->y_vis = y_vis;
918b3307321Smrg    new_src->width = width;
919b3307321Smrg    new_src->height = height;
920b3307321Smrg    new_src->border_width = border_width;
921b3307321Smrg    new_src->vis = vis;
922b3307321Smrg    new_src->cmap = cmap;
923b3307321Smrg    new_src->parent = parent;
924b3307321Smrg    add_to_list( image_wins, new_src);
925b3307321Smrg}
926b3307321Smrg
927b3307321Smrg/** ------------------------------------------------------------------------
928b3307321Smrg	Returns TRUE if the given src's visual is in the image planes,
929b3307321Smrg	FALSE otherwise.
930b3307321Smrg    ------------------------------------------------------------------------ **/
9315e358ecaSmrgstatic int src_in_image(image_win_type *src, int numImageVisuals,
9325e358ecaSmrg			XVisualInfo **pImageVisuals)
933b3307321Smrg{
934b3307321Smrg    int 		i;
935b3307321Smrg
936b3307321Smrg    for (i = 0 ; i < numImageVisuals ; i++)
937b3307321Smrg    {
938b3307321Smrg	if (pImageVisuals[i]->visual == src->vis)
939b3307321Smrg	    return 1;
940b3307321Smrg    }
941b3307321Smrg    return 0;
942b3307321Smrg}
943b3307321Smrg
944b3307321Smrg
945b3307321Smrg/** ------------------------------------------------------------------------
946b3307321Smrg	Returns TRUE if the given src's visual is in the overlay planes
947b3307321Smrg	and transparency is possible, FALSE otherwise.
948b3307321Smrg    ------------------------------------------------------------------------ **/
9495e358ecaSmrgstatic int src_in_overlay(image_region_type *src, int numOverlayVisuals,
9505e358ecaSmrg			  OverlayInfo *pOverlayVisuals,
9515e358ecaSmrg			  int *transparentColor, int *transparentType)
952b3307321Smrg{
953b3307321Smrg    int 		i;
954b3307321Smrg
955b3307321Smrg    for (i = 0 ; i < numOverlayVisuals ; i++)
956b3307321Smrg    {
957b3307321Smrg	if (((pOverlayVisuals[i].pOverlayVisualInfo)->visual == src->vis)
958b3307321Smrg		&& (pOverlayVisuals[i].transparentType != None))
959b3307321Smrg	{
960b3307321Smrg	    *transparentColor = pOverlayVisuals[i].value;
961b3307321Smrg	    *transparentType = pOverlayVisuals[i].transparentType;
962b3307321Smrg	    return 1;
963b3307321Smrg	}
964b3307321Smrg
965b3307321Smrg	else {
966b3307321Smrg	}
967b3307321Smrg
968b3307321Smrg    }
969b3307321Smrg    return 0;
970b3307321Smrg}
971b3307321Smrg
972b3307321Smrg
973b3307321Smrg/********************** from wsutils.c ******************************/
974b3307321Smrg
975b3307321Smrg/******************************************************************************
976b3307321Smrg *
977b3307321Smrg * This file contains a set of example utility procedures; procedures that can
978b3307321Smrg * help a "window-smart" Starbase or PHIGS program determine information about
979b3307321Smrg * a device, and create image and overlay plane windows.  To use these
980b3307321Smrg * utilities, #include "wsutils.h" and compile this file and link the results
981b3307321Smrg * with your program.
982b3307321Smrg *
983b3307321Smrg ******************************************************************************/
984b3307321Smrg
985b3307321Smrg
986b3307321Smrg
987b3307321Smrg#define STATIC_GRAY	0x01
988b3307321Smrg#define GRAY_SCALE	0x02
989b3307321Smrg#define PSEUDO_COLOR	0x04
990b3307321Smrg#define TRUE_COLOR	0x10
991b3307321Smrg#define DIRECT_COLOR	0x11
992b3307321Smrg
993b3307321Smrg
994b3307321Smrgstatic int	weCreateServerOverlayVisualsProperty = False;
995b3307321Smrg
996b3307321Smrg
997b3307321Smrg/******************************************************************************
998b3307321Smrg *
999b3307321Smrg * GetXVisualInfo()
1000b3307321Smrg *
1001b3307321Smrg * This routine takes an X11 Display, screen number, and returns whether the
1002b3307321Smrg * screen supports transparent overlays and three arrays:
1003b3307321Smrg *
1004b3307321Smrg *	1) All of the XVisualInfo struct's for the screen.
1005b3307321Smrg *	2) All of the OverlayInfo struct's for the screen.
1006b3307321Smrg *	3) An array of pointers to the screen's image plane XVisualInfo
1007b3307321Smrg *	   structs.
1008b3307321Smrg *
1009b3307321Smrg * The code below obtains the array of all the screen's visuals, and obtains
1010b3307321Smrg * the array of all the screen's overlay visual information.  It then processes
1011b3307321Smrg * the array of the screen's visuals, determining whether the visual is an
1012b3307321Smrg * overlay or image visual.
1013b3307321Smrg *
1014b3307321Smrg * If the routine sucessfully obtained the visual information, it returns zero.
1015b3307321Smrg * If the routine didn't obtain the visual information, it returns non-zero.
1016b3307321Smrg *
1017b3307321Smrg ******************************************************************************/
1018b3307321Smrg
10195e358ecaSmrgint GetXVisualInfo(/* Which X server (aka "display"). */
10205e358ecaSmrg		   Display *display,
10215e358ecaSmrg		   /* Which screen of the "display". */
10225e358ecaSmrg		   int screen,
10235e358ecaSmrg		   /* Non-zero if there's at least one overlay visual and
10245e358ecaSmrg		    * if at least one of those supports a transparent pixel. */
10255e358ecaSmrg		   int *transparentOverlays,
10265e358ecaSmrg		   /* Number of XVisualInfo struct's pointed to by pVisuals. */
10275e358ecaSmrg		   int *numVisuals,
10285e358ecaSmrg		   /* All of the device's visuals. */
10295e358ecaSmrg		   XVisualInfo **pVisuals,
10305e358ecaSmrg		   /* Number of OverlayInfo's pointed to by pOverlayVisuals.
10315e358ecaSmrg		    * If this number is zero, the device does not have
10325e358ecaSmrg		    * overlay planes. */
10335e358ecaSmrg		   int *numOverlayVisuals,
10345e358ecaSmrg		   /* The device's overlay plane visual information. */
10355e358ecaSmrg		   OverlayInfo	**pOverlayVisuals,
10365e358ecaSmrg		   /* Number of XVisualInfo's pointed to by pImageVisuals. */
10375e358ecaSmrg		   int *numImageVisuals,
10385e358ecaSmrg		   /* The device's image visuals. */
10395e358ecaSmrg		   XVisualInfo ***pImageVisuals)
1040b3307321Smrg{
1041b3307321Smrg    XVisualInfo	getVisInfo;		/* Paramters of XGetVisualInfo */
1042b3307321Smrg    int		mask;
1043b3307321Smrg    XVisualInfo	*pVis, **pIVis;		/* Faster, local copies */
1044b3307321Smrg    OverlayInfo	*pOVis;
1045b3307321Smrg    OverlayVisualPropertyRec	*pOOldVis;
1046b3307321Smrg    int		nVisuals, nOVisuals;
1047b3307321Smrg    Atom	overlayVisualsAtom;	/* Parameters for XGetWindowProperty */
1048b3307321Smrg    Atom	actualType;
1049b3307321Smrg    unsigned long numLongs, bytesAfter;
1050b3307321Smrg    int		actualFormat;
1051b3307321Smrg    int		nImageVisualsAlloced;	/* Values to process the XVisualInfo */
1052b3307321Smrg    int		imageVisual;		/* array */
1053b3307321Smrg
1054b3307321Smrg
1055b3307321Smrg    /* First, get the list of visuals for this screen. */
1056b3307321Smrg    getVisInfo.screen = screen;
1057b3307321Smrg    mask = VisualScreenMask;
1058b3307321Smrg
1059b3307321Smrg    *pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals);
1060b3307321Smrg    if ((nVisuals = *numVisuals) <= 0)
1061b3307321Smrg    {
1062b3307321Smrg	/* Return that the information wasn't sucessfully obtained: */
1063b3307321Smrg	return(1);
1064b3307321Smrg    }
1065b3307321Smrg    pVis = *pVisuals;
1066b3307321Smrg
1067b3307321Smrg
1068b3307321Smrg    /* Now, get the overlay visual information for this screen.  To obtain
1069b3307321Smrg     * this information, get the SERVER_OVERLAY_VISUALS property.
1070b3307321Smrg     */
1071b3307321Smrg    overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True);
1072b3307321Smrg    if (overlayVisualsAtom != None)
1073b3307321Smrg    {
1074b3307321Smrg	/* Since the Atom exists, we can request the property's contents.  The
1075b3307321Smrg	 * do-while loop makes sure we get the entire list from the X server.
1076b3307321Smrg	 */
1077b3307321Smrg	bytesAfter = 0;
1078320e696bSmrg	numLongs = sizeof(OverlayVisualPropertyRec) / sizeof(long);
1079b3307321Smrg	do
1080b3307321Smrg	{
1081320e696bSmrg	    numLongs += bytesAfter * sizeof(long);
1082b3307321Smrg	    XGetWindowProperty(display, RootWindow(display, screen),
1083b3307321Smrg			       overlayVisualsAtom, 0, numLongs, False,
1084b3307321Smrg			       overlayVisualsAtom, &actualType, &actualFormat,
1085b3307321Smrg			       &numLongs, &bytesAfter, (unsigned char**) pOverlayVisuals);
1086b3307321Smrg	} while (bytesAfter > 0);
1087b3307321Smrg
1088b3307321Smrg
1089b3307321Smrg	/* Calculate the number of overlay visuals in the list. */
1090320e696bSmrg	*numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / sizeof(long));
1091b3307321Smrg    }
1092b3307321Smrg    else
1093b3307321Smrg    {
1094b3307321Smrg	/* This screen doesn't have overlay planes. */
1095b3307321Smrg	*numOverlayVisuals = 0;
1096b3307321Smrg	*pOverlayVisuals = NULL;
1097b3307321Smrg	*transparentOverlays = 0;
1098b3307321Smrg    }
1099b3307321Smrg
1100b3307321Smrg
1101b3307321Smrg    /* Process the pVisuals array. */
1102b3307321Smrg    *numImageVisuals = 0;
1103b3307321Smrg    nImageVisualsAlloced = 1;
1104b3307321Smrg    pIVis = *pImageVisuals = (XVisualInfo **) malloc(sizeof(XVisualInfo *));
1105b3307321Smrg    while (--nVisuals >= 0)
1106b3307321Smrg    {
1107b3307321Smrg	nOVisuals = *numOverlayVisuals;
1108b3307321Smrg	pOVis = *pOverlayVisuals;
1109b3307321Smrg	imageVisual = True;
1110b3307321Smrg	while (--nOVisuals >= 0)
1111b3307321Smrg	{
1112b3307321Smrg	    pOOldVis = (OverlayVisualPropertyRec *) pOVis;
1113b3307321Smrg	    if (pVis->visualid == pOOldVis->visualID)
1114b3307321Smrg	    {
1115b3307321Smrg		imageVisual = False;
1116b3307321Smrg		pOVis->pOverlayVisualInfo = pVis;
1117b3307321Smrg		if (pOVis->transparentType == TransparentPixel)
1118b3307321Smrg		    *transparentOverlays = 1;
1119b3307321Smrg	    }
1120b3307321Smrg	    pOVis++;
1121b3307321Smrg	}
1122b3307321Smrg	if (imageVisual)
1123b3307321Smrg	{
1124b3307321Smrg	    if ((*numImageVisuals += 1) > nImageVisualsAlloced)
1125b3307321Smrg	    {
1126b3307321Smrg		nImageVisualsAlloced++;
1127b3307321Smrg		*pImageVisuals = (XVisualInfo **)
1128b3307321Smrg		    realloc(*pImageVisuals, (nImageVisualsAlloced * sizeof(XVisualInfo *)));
1129b3307321Smrg		pIVis = *pImageVisuals + (*numImageVisuals - 1);
1130b3307321Smrg	    }
1131b3307321Smrg	    *pIVis++ = pVis;
1132b3307321Smrg	}
1133b3307321Smrg	pVis++;
1134b3307321Smrg    }
1135b3307321Smrg
1136b3307321Smrg
1137b3307321Smrg    /* Return that the information was sucessfully obtained: */
1138b3307321Smrg    return(0);
1139b3307321Smrg
1140b3307321Smrg} /* GetXVisualInfo() */
1141b3307321Smrg
1142b3307321Smrg
1143b3307321Smrg/******************************************************************************
1144b3307321Smrg *
1145b3307321Smrg * FreeXVisualInfo()
1146b3307321Smrg *
1147b3307321Smrg * This routine frees the data that was allocated by GetXVisualInfo().
1148b3307321Smrg *
1149b3307321Smrg ******************************************************************************/
1150b3307321Smrg
11515e358ecaSmrgvoid FreeXVisualInfo(XVisualInfo *pVisuals, OverlayInfo *pOverlayVisuals,
11525e358ecaSmrg		     XVisualInfo **pImageVisuals)
1153b3307321Smrg{
1154b3307321Smrg    XFree(pVisuals);
1155b3307321Smrg    if (weCreateServerOverlayVisualsProperty)
1156b3307321Smrg	free(pOverlayVisuals);
1157b3307321Smrg    else
1158b3307321Smrg	XFree(pOverlayVisuals);
1159b3307321Smrg    free(pImageVisuals);
1160b3307321Smrg
1161b3307321Smrg} /* FreeXVisualInfo() */
1162