1 /* $XConsortium: multiVis.c /main/4 1996/10/14 15:04:08 swick $ */
2 /** ------------------------------------------------------------------------
3 	This file contains functions to create a list of regions which
4 	tile a specified window.  Each region contains all visible
5 	portions of the window which are drawn with the same visual.
6 	If the window consists of subwindows of two different visual types,
7 	there will be two regions in the list.  The list can be traversed
8 	to correctly pull an image of the window using XGetImage or the
9 	Image Library.
10 
11 Copyright (c) 1994 Hewlett-Packard Co.
12 Copyright (c) 1996  X Consortium
13 
14 Permission is hereby granted, free of charge, to any person obtaining
15 a copy of this software and associated documentation files (the
16 "Software"), to deal in the Software without restriction, including
17 without limitation the rights to use, copy, modify, merge, publish,
18 distribute, sublicense, and sell copies of the Software, and to
19 permit persons to whom the Software is furnished to do so, subject to
20 the following conditions:
21 
22 The above copyright notice and this permission notice shall be included
23 in all copies or substantial portions of the Software.
24 
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
26 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
27 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
28 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
29 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
30 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
31 OTHER DEALINGS IN THE SOFTWARE.
32 
33 Except as contained in this notice, the name of the X Consortium shall
34 not be used in advertising or otherwise to promote the sale, use or
35 other dealings in this Software without prior written authorization
36 from the X Consortium.
37 
38     ------------------------------------------------------------------------ **/
39 #include <stdlib.h>
40 #include <X11/Xlib.h>
41 #include <X11/Xutil.h>
42 #include <X11/X.h>
43 #include <stdio.h>
44 #include "list.h"
45 #include "wsutils.h"
46 #include "multiVis.h"
47 static char *vis_class_str[] = { "StaticGray" , "GrayScale" , "StaticColor",
48 				 "PseudoColor","TrueColor","DirectColor" } ;
49 /* These structures are copied from X11/region.h.  For some reason
50  * they're invisible from the outside.
51  */
52 typedef struct {
53     short x1, x2, y1, y2;
54 } myBox, myBOX, myBoxRec, *myBoxPtr;
55 
56 typedef struct my_XRegion {
57     long size;
58     long numRects;
59     myBOX *rects;
60     myBOX extents;
61 } myREGION;
62 
63 /* Items in long list of windows that have some part in the grabbed area */
64 typedef struct {
65     Window win;
66     Visual *vis;
67     Colormap cmap;
68     int x_rootrel, y_rootrel;	/* root relative location of window */
69     int x_vis, y_vis;  		/* rt rel x,y of vis part, not parent clipped */
70     int width, height; 		/* width and height of visible part */
71     int border_width;		/* border width of the window */
72     Window parent;		/* id of parent (for debugging) */
73 } image_win_type;
74 
75 /*  Items in short list of regions that tile the grabbed area.  May have
76     multiple windows in the region.
77 */
78 typedef struct {
79     Window win;			/* lowest window of this visual */
80     Visual *vis;
81     Colormap cmap;
82     int x_rootrel, y_rootrel;	/* root relative location of bottom window */
83     int x_vis, y_vis;  		/* rt rel x,y of vis part, not parent clipped */
84     int width, height;		/* w & h of visible rect of bottom window */
85     int border;			/* border width of the window */
86     Region visible_region;
87 } image_region_type;
88 
89 /** ------------------------------------------------------------------------
90 	Returns TRUE if the two structs pointed to have the same "vis" &
91 	"cmap" fields and s2 lies completely within s1.  s1 and s2 can
92 	point to structs of image_win_type or image_region_type.
93     ------------------------------------------------------------------------ **/
94 #define SAME_REGIONS( s1, s2)	\
95 	((s1)->vis == (s2)->vis && (s1)->cmap == (s2)->cmap &&   	\
96 	 (s1)->x_vis <= (s2)->x_vis &&				    \
97 	 (s1)->y_vis <= (s2)->y_vis &&				    \
98 	 (s1)->x_vis + (s1)->width  >= (s2)->x_vis + (s2)->width && \
99 	 (s1)->y_vis + (s1)->height >= (s2)->y_vis + (s2)->height)
100 
101 #ifndef MIN
102 #define MIN( a, b)	((a) < (b) ? a : b)
103 #define MAX( a, b)	((a) > (b) ? a : b)
104 #endif
105 
106 #define	RED_SHIFT        16
107 #define GREEN_SHIFT       8
108 #define BLUE_SHIFT        0
109 
110 /*
111 extern list_ptr	new_list();
112 extern list_ptr	dup_list_head();
113 extern void *	first_in_list();
114 extern void *	next_in_list();
115 extern int	add_to_list();
116 extern void	zero_list();
117 extern void	delete_list();
118 extern void	delete_list_destroying();
119 extern unsigned int list_length();
120 */
121 
122 /* Prototype Declarations for Static Functions */
123 static int QueryColorMap(
124 #if NeedFunctionPrototypes
125            Display *, Colormap , Visual *,
126            XColor **, int *, int *, int *
127 #endif
128 	   );
129 static void TransferImage(
130 #if NeedFunctionPrototypes
131            Display *, XImage *,int, int , image_region_type*,
132            XImage *,int ,int
133 #endif
134 	   );
135 static XImage * ReadRegionsInList(
136 #if NeedFunctionPrototypes
137            Display *, Visual *, int ,int ,int ,
138            int , XRectangle, list_ptr
139 #endif
140            );
141 
142 static list_ptr make_region_list(
143 #if NeedFunctionPrototypes
144                   Display*, Window, XRectangle*,
145                   int*, int, XVisualInfo**, int	*
146 #endif
147          );
148 
149 static void destroy_region_list(
150 #if NeedFunctionPrototypes
151             list_ptr
152 #endif
153             ) ;
154 static void subtr_rect_from_image_region(
155 #if NeedFunctionPrototypes
156            image_region_type *, int , int , int , int
157 #endif
158      );
159 static void add_rect_to_image_region(
160 #if NeedFunctionPrototypes
161            image_region_type *,
162            int , int , int , int
163 #endif
164      );
165 static int src_in_region_list(
166 #if NeedFunctionPrototypes
167     image_win_type *, list_ptr
168 #endif
169     );
170 static void add_window_to_list(
171 #if NeedFunctionPrototypes
172     list_ptr, Window, int, int ,
173     int	, int , int , int, int,
174     Visual*, Colormap, Window
175 #endif
176     );
177 static int src_in_image(
178 #if NeedFunctionPrototypes
179     image_win_type 	*, int	, XVisualInfo**
180 #endif
181     );
182 static int src_in_overlay(
183 #if NeedFunctionPrototypes
184     image_region_type *, int, OverlayInfo *, int*, int*
185 #endif
186     );
187 
188 /* End of Prototype Declarations */
189 
initFakeVisual(Vis)190 void initFakeVisual(Vis)
191 Visual *Vis ;
192 {
193     Vis->ext_data=NULL;
194     Vis->class = DirectColor ;
195     Vis->red_mask =   0x00FF0000;
196     Vis->green_mask = 0x0000FF00 ;
197     Vis->blue_mask  = 0x000000FF ;
198     Vis->map_entries = 256 ;
199     Vis->bits_per_rgb = 8 ;
200 }
201 
202 static int
QueryColorMap(disp,src_cmap,src_vis,src_colors,rShift,gShift,bShift)203 QueryColorMap(disp,src_cmap,src_vis,src_colors,rShift,gShift,bShift)
204 Display *disp ;
205 Visual *src_vis ;
206 Colormap src_cmap ;
207 XColor **src_colors ;
208 int *rShift, *gShift, *bShift;
209 {
210      int ncolors,i ;
211      unsigned long       redMask, greenMask, blueMask, pixel;
212      int                 redShift, greenShift, blueShift;
213      XColor *colors ;
214 
215      ncolors = src_vis->map_entries ;
216      *src_colors = colors = (XColor *)malloc(ncolors * sizeof(XColor) ) ;
217 
218      if(src_vis->class != TrueColor && src_vis->class != DirectColor)
219      {
220          for(i=0 ; i < ncolors ; i++)
221          {
222 	        colors[i].pixel = i ;
223                 colors[i].pad = 0;
224                 colors[i].flags = DoRed|DoGreen|DoBlue;
225          }
226      }
227      else /** src is decomposed rgb ***/
228      {
229         /* Get the X colormap */
230         redMask = src_vis->red_mask;
231         greenMask = src_vis->green_mask;
232         blueMask = src_vis->blue_mask;
233         redShift = 0; while (!(redMask&0x1)) {
234                 redShift++;
235                 redMask = redMask>>1;
236         }
237         greenShift = 0; while (!(greenMask&0x1)) {
238                 greenShift++;
239                 greenMask = greenMask>>1;
240         }
241         blueShift = 0; while (!(blueMask&0x1)) {
242                 blueShift++;
243                 blueMask = blueMask>>1;
244         }
245 	*rShift = redShift ;
246 	*gShift = greenShift ;
247 	*bShift = blueShift ;
248         for (i=0; i<ncolors; i++) {
249 		if( i <= redMask)colors[i].pixel = (i<<redShift) ;
250 		if( i <= greenMask)colors[i].pixel |= (i<<greenShift) ;
251 		if( i <= blueMask)colors[i].pixel |= (i<<blueShift) ;
252 		/***** example :for gecko's 3-3-2 map, blue index should be <= 3.
253                 colors[i].pixel = (i<<redShift)|(i<<greenShift)|(i<<blueShift);
254 		*****/
255                 colors[i].pad = 0;
256                 colors[i].flags = DoRed|DoGreen|DoBlue;
257         }
258       }
259 
260 
261       XQueryColors(disp, src_cmap, colors, ncolors);
262       return ncolors ;
263 }
264 
265 int
GetMultiVisualRegions(disp,srcRootWinid,x,y,width,height,transparentOverlays,numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,numImageVisuals,pImageVisuals,vis_regions,vis_image_regions,allImage)266 GetMultiVisualRegions(disp,srcRootWinid, x, y, width, height,
267     transparentOverlays,numVisuals, pVisuals,numOverlayVisuals, pOverlayVisuals,
268     numImageVisuals, pImageVisuals,vis_regions,vis_image_regions,allImage)
269     Display             *disp;
270     Window              srcRootWinid;   /* root win on which grab was done */
271     int                 x;      /* root rel UL corner of bounding box of grab */
272     int                 y;
273     unsigned int        width;  /* size of bounding box of grab */
274     unsigned int        height;
275     int                 *transparentOverlays ;
276     int                 *numVisuals;
277     XVisualInfo         **pVisuals;
278     int                 *numOverlayVisuals;
279     OverlayInfo         **pOverlayVisuals;
280     int                 *numImageVisuals;
281     XVisualInfo         ***pImageVisuals;
282     list_ptr            *vis_regions;    /* list of regions to read from */
283     list_ptr            *vis_image_regions ;
284     int			*allImage ;
285 {
286     int                 hasNonDefault;
287     XRectangle          bbox;           /* bounding box of grabbed area */
288 
289 
290     bbox.x = x;                 /* init X rect for bounding box */
291     bbox.y = y;
292     bbox.width = width;
293     bbox.height = height;
294 
295     GetXVisualInfo(disp,DefaultScreen(disp),
296                     transparentOverlays,
297                     numVisuals, pVisuals,
298                     numOverlayVisuals, pOverlayVisuals,
299                     numImageVisuals, pImageVisuals);
300 
301     *vis_regions = *vis_image_regions = NULL ;
302     if ((*vis_regions = make_region_list( disp, srcRootWinid, &bbox,
303                                          &hasNonDefault, *numImageVisuals,
304                                          *pImageVisuals, allImage)) == NULL)
305     	return 0 ;
306 
307     if (*transparentOverlays)
308     {
309         *allImage = 1; /* until proven otherwise,
310                          this flags that it to be an image only list */
311         *vis_image_regions =
312                 make_region_list( disp, srcRootWinid, &bbox, &hasNonDefault,
313                                         *numImageVisuals, *pImageVisuals, allImage);
314     }
315 
316     /* if there is a second region in any of the two lists return 1 **/
317     if ( ( *vis_regions && (*vis_regions)->next && (*vis_regions)->next->next ) ||
318          ( *vis_image_regions && (*vis_image_regions)->next &&
319            (*vis_image_regions)->next->next ) ) return 1 ;
320     else return 0 ;
321 
322 }
323 
TransferImage(disp,reg_image,srcw,srch,reg,target_image,dst_x,dst_y)324 static void TransferImage(disp,reg_image,srcw,srch,reg,
325 			  target_image,dst_x,dst_y)
326 Display *disp;
327 XImage *reg_image,*target_image ;
328 image_region_type	*reg;
329 int srcw,srch,dst_x , dst_y ;
330 {
331     int *indexMap,ncolors ;
332     int i,j,old_pixel,new_pixel,red_ind,green_ind,blue_ind ;
333     XColor *colors;
334     int rShift,gShift,bShift;
335     int targetBytesPerLine ;
336 
337     ncolors = QueryColorMap(disp,reg->cmap,reg->vis,&colors,
338 	 &rShift,&gShift,&bShift) ;
339 
340     targetBytesPerLine = target_image->bytes_per_line;
341 
342     switch (reg->vis->class) {
343     case TrueColor :
344        for(i=0 ; i < srch ; i++)
345        {
346          for(j=0 ; j < srcw ;  j++)
347          {
348 	   old_pixel = XGetPixel(reg_image,j,i) ;
349 
350            if( reg->vis->map_entries == 16) {
351 
352                  red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
353 	         green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
354 	         blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
355 
356 	         new_pixel = (
357 			      ((colors[red_ind].red >> 8) << RED_SHIFT)
358 			      |((colors[green_ind].green >> 8) << GREEN_SHIFT)
359 			      |((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
360                              );
361            }
362 	   else
363 		new_pixel = old_pixel;
364 
365            XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
366 
367          }
368        }
369        break;
370     case DirectColor :
371        for(i=0 ; i < srch ; i++)
372        {
373 
374          for(j=0 ; j < srcw ;  j++)
375          {
376 	   old_pixel = XGetPixel(reg_image,j,i) ;
377            red_ind = (old_pixel & reg->vis->red_mask) >> rShift ;
378 	   green_ind = (old_pixel & reg->vis->green_mask) >> gShift ;
379 	   blue_ind = (old_pixel & reg->vis->blue_mask) >> bShift ;
380 
381 	   new_pixel = (
382 			 ((colors[red_ind].red >> 8) << RED_SHIFT)
383 			|((colors[green_ind].green >> 8) << GREEN_SHIFT)
384 			|((colors[blue_ind].blue >> 8) << BLUE_SHIFT)
385                        );
386            XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
387 
388          }
389        }
390        break;
391     default :
392        for(i=0 ; i < srch ; i++)
393        {
394          for(j=0 ; j < srcw ;  j++)
395          {
396 	    old_pixel = XGetPixel(reg_image,j,i) ;
397 
398 	   new_pixel = (
399 			 ((colors[old_pixel].red >> 8) << RED_SHIFT)
400 			|((colors[old_pixel].green >> 8) << GREEN_SHIFT)
401 			|((colors[old_pixel].blue >> 8) << BLUE_SHIFT)
402                        );
403            XPutPixel(target_image,dst_x+j, dst_y+i,new_pixel);
404 
405          }
406        }
407        break;
408     }
409 }
410 
411 static XImage *
ReadRegionsInList(disp,fakeVis,depth,format,width,height,bbox,regions)412 ReadRegionsInList(disp,fakeVis,depth,format,width,height,bbox,regions)
413 Display *disp ;
414 Visual *fakeVis ;
415 int depth , width , height ;
416 int format ;
417 XRectangle	bbox;		/* bounding box of grabbed area */
418 list_ptr regions;/* list of regions to read from */
419 {
420     image_region_type	*reg;
421     int			dst_x, dst_y;	/* where in pixmap to write (UL) */
422     int			diff;
423     int			hasNonDefault;
424 
425     int			allImage = 0;
426     int			transparentColor, transparentType;
427     XImage		*reg_image,*ximage ;
428     int			srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
429     int                 rem ;
430     int                 bytes_per_line;
431     int                 bitmap_unit;
432 
433     bitmap_unit = sizeof (long);
434     if (format == ZPixmap)
435        bytes_per_line = width*depth/8;
436     else
437        bytes_per_line = width/8;
438 
439 
440     /* Find out how many more bytes are required for padding so that
441     ** bytes per scan line will be multiples of bitmap_unit bits */
442     if (format == ZPixmap) {
443        rem = (bytes_per_line*8)%bitmap_unit;
444     if (rem)
445        bytes_per_line += (rem/8 + 1);
446     }
447 
448     ximage = XCreateImage(disp,fakeVis,depth,format,0,NULL,width,height,
449 	         8,0) ;
450     bytes_per_line = ximage->bytes_per_line;
451 
452     if (format == ZPixmap)
453     	  ximage->data = malloc(height*bytes_per_line);
454     else
455         ximage->data = malloc(height*bytes_per_line*depth);
456 
457     ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/
458 
459     for (reg = (image_region_type *) first_in_list( regions); reg;
460 	 reg = (image_region_type *) next_in_list( regions))
461     {
462 		int rect;
463 		struct my_XRegion *vis_reg;
464 		vis_reg = (struct my_XRegion *)(reg->visible_region);
465 		for (rect = 0;
466 		     rect < vis_reg->numRects;
467 		     rect++)
468 		{
469 		/** ------------------------------------------------------------------------
470 			Intersect bbox with visible part of region giving src rect & output
471 			location.  Width is the min right side minus the max left side.
472 			Similar for height.  Offset src rect so x,y are relative to
473 			origin of win, not the root-relative visible rect of win.
474 		    ------------------------------------------------------------------------ **/
475 		    srcRect_width  = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x) -
476 				     MAX( vis_reg->rects[rect].x1, bbox.x);
477 		    srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y) -
478 				     MAX( vis_reg->rects[rect].y1, bbox.y);
479 		    diff = bbox.x - vis_reg->rects[rect].x1;
480 		    srcRect_x = MAX( 0, diff)  + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border);
481 		    dst_x     = MAX( 0, -diff) ;
482 		    diff = bbox.y - vis_reg->rects[rect].y1;
483 		    srcRect_y = MAX( 0, diff)  + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border);
484 		    dst_y     = MAX( 0, -diff) ;
485                     reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y,
486 				srcRect_width,srcRect_height,AllPlanes,format) ;
487 		    TransferImage(disp,reg_image,srcRect_width,
488 		                 srcRect_height,reg,ximage,dst_x,dst_y) ;
489 	    }
490     }
491     return ximage ;
492 }
493 
494 
495 /** ------------------------------------------------------------------------
496     ------------------------------------------------------------------------ **/
497 
ReadAreaToImage(disp,srcRootWinid,x,y,width,height,numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,numImageVisuals,pImageVisuals,vis_regions,vis_image_regions,format,allImage)498 XImage *ReadAreaToImage(disp, srcRootWinid, x, y, width, height,
499     numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,numImageVisuals,
500     pImageVisuals,vis_regions,vis_image_regions,format,allImage)
501     Display		*disp;
502     Window		srcRootWinid;	/* root win on which grab was done */
503     int			x;   /* root rel UL corner of bounding box of grab */
504     int			y;
505     unsigned int	width;	/* size of bounding box of grab */
506     unsigned int	height;
507     /** int			transparentOverlays; ***/
508     int			numVisuals;
509     XVisualInfo		*pVisuals;
510     int			numOverlayVisuals;
511     OverlayInfo		*pOverlayVisuals;
512     int			numImageVisuals;
513     XVisualInfo		**pImageVisuals;
514     list_ptr		vis_regions;	/* list of regions to read from */
515     list_ptr		vis_image_regions ;/* list of regions to read from */
516     int			format;
517     int 		allImage ;
518 {
519     image_region_type	*reg;
520     XRectangle		bbox;		/* bounding box of grabbed area */
521     int 		depth ;
522     XImage		*ximage, *ximage_ipm ;
523     Visual		fakeVis ;
524     int 	x1, y1;
525     XImage	*image;
526     unsigned char 	*pmData ,  *ipmData ;
527     int                 transparentColor, transparentType;
528     int			srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
529     int			diff ;
530     int			dst_x, dst_y;	/* where in pixmap to write (UL) */
531     int			pixel;
532 
533     bbox.x = x;			/* init X rect for bounding box */
534     bbox.y = y;
535     bbox.width = width;
536     bbox.height = height;
537 
538 
539     initFakeVisual(&fakeVis) ;
540 
541     depth = 24 ;
542     ximage = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
543 	     bbox,vis_regions) ;
544     pmData = (unsigned char *)ximage -> data ;
545 
546 /* if transparency possible do it again, but this time for image planes only */
547     if (vis_image_regions && (vis_image_regions->next) && !allImage)
548     {
549 	ximage_ipm = ReadRegionsInList(disp,&fakeVis,depth,format,width,height,
550 		     bbox,vis_image_regions) ;
551         ipmData = (unsigned char *)ximage_ipm -> data ;
552     }
553 /* Now tranverse the overlay visual windows and test for transparency index.  */
554 /* If you find one, subsitute the value from the matching image plane pixmap. */
555 
556     for (reg = (image_region_type *) first_in_list( vis_regions); reg;
557 	 reg = (image_region_type *) next_in_list( vis_regions))
558     {
559 
560 	if (src_in_overlay( reg, numOverlayVisuals, pOverlayVisuals,
561 				 &transparentColor, &transparentType))
562 	{
563 	int test = 0 ;
564 	     srcRect_width  = MIN( reg->width + reg->x_vis, bbox.width + bbox.x)
565 				 - MAX( reg->x_vis, bbox.x);
566 	     srcRect_height = MIN( reg->height + reg->y_vis, bbox.height
567 				 + bbox.y) - MAX( reg->y_vis, bbox.y);
568              diff = bbox.x - reg->x_vis;
569              srcRect_x = MAX( 0, diff)  + (reg->x_vis - reg->x_rootrel - reg->border);
570              dst_x     = MAX( 0, -diff) ;
571 	     diff = bbox.y - reg->y_vis;
572 	     srcRect_y = MAX( 0, diff)  + (reg->y_vis - reg->y_rootrel - reg->border);
573 	     dst_y     = MAX( 0, -diff) ;
574 	/* let's test some pixels for transparency */
575              image = XGetImage(disp, reg->win, srcRect_x, srcRect_y,
576 		 srcRect_width, srcRect_height, 0xffffffff, ZPixmap);
577 
578         /* let's assume byte per pixel for overlay image for now */
579 	     if ((image->depth == 8) && (transparentType == TransparentPixel))
580 	     {
581 	         unsigned char *pixel_ptr;
582 	         unsigned char *start_of_line = (unsigned char *) image->data;
583 
584 	         for (y1 = 0; y1 < srcRect_height; y1++) {
585 		    pixel_ptr = start_of_line;
586 		    for (x1 = 0; x1 < srcRect_width; x1++)
587 		    {
588 			if (*pixel_ptr++ == transparentColor)
589 			{
590 			/*
591 			    *pmData++ = *ipmData++;
592 			    *pmData++ = *ipmData++;
593 			    *pmData++ = *ipmData++;
594 			*/
595 	                pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
596                         XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
597 
598 			if(!test){
599 			   test = 1 ;
600 			}
601 			}
602 			/*
603 			else {
604 			    pmData +=3;
605 			    ipmData +=3;
606 			}
607 			*/
608 		    }
609 		    start_of_line += image->bytes_per_line;
610 		}
611 	} else {
612 		if (transparentType == TransparentPixel) {
613 		for (y1 = 0; y1 < srcRect_height; y1++) {
614 		      for (x1 = 0; x1 < srcRect_width; x1++)
615 		      {
616 			    int pixel_value = XGetPixel(image, x1, y1);
617 			    if (pixel_value == transparentColor)
618 			    {
619 			    /*
620 				*pmData++ = *ipmData++;
621 				*pmData++ = *ipmData++;
622 				*pmData++ = *ipmData++;
623 			    */
624 	                pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
625                         XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
626 			if(!test){
627 			   test = 1 ;
628 			}
629 			    }
630 			    /*
631 			    else {
632 				pmData +=3;
633 				ipmData +=3;
634 			    }
635 			    */
636 			}
637 		    }
638 		} else {
639 		    for (y1 = 0; y1 < srcRect_height; y1++) {
640 			for (x1 = 0; x1 < srcRect_width; x1++)
641 			{
642 			    int pixel_value = XGetPixel(image, x1, y1);
643 			    if (pixel_value & transparentColor)
644 			    {
645 			    /*
646 				*pmData++ = *ipmData++;
647 				*pmData++ = *ipmData++;
648 				*pmData++ = *ipmData++;
649 			    */
650 	                        pixel = XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
651                                 XPutPixel(ximage,dst_x+x1, dst_y+y1,pixel);
652 			if(!test){
653 			   test = 1 ;
654 			}
655 			    }
656 			    /*
657 			    else {
658 				pmData +=3;
659 				ipmData +=3;
660 			    }
661 			    */
662 			}
663 		    }
664 		}
665 	}
666         XDestroyImage (image);
667       }	/* end of src_in_overlay */
668     } /** end transparency **/
669     destroy_region_list( vis_regions);
670     if (vis_image_regions) destroy_region_list( vis_image_regions );
671     FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals);
672     XSync(disp, 0);
673 
674     return ximage;
675 }
676 
677 /** ------------------------------------------------------------------------
678 	Creates a list of the subwindows of a given window which have a
679 	different visual than their parents.  The function is recursive.
680 	This list is used in make_region_list(), which coalesces the
681 	windows with the same visual into a region.
682 	image_wins must point to an existing list struct that's already
683 	been zeroed (zero_list()).
684     ------------------------------------------------------------------------ **/
make_src_list(disp,image_wins,bbox,curr,x_rootrel,y_rootrel,curr_attrs,pclip)685 static void make_src_list( disp, image_wins, bbox, curr, x_rootrel, y_rootrel,
686 		    curr_attrs, pclip)
687     Display		*disp;
688     list_ptr		image_wins;
689     XRectangle		*bbox;			/* bnding box of area we want */
690     Window		curr;
691     int			x_rootrel;		/* pos of curr WRT root */
692     int			y_rootrel;
693     XWindowAttributes	*curr_attrs;
694     XRectangle		*pclip;			/* visible part of curr, not */
695 						/* obscurred by ancestors */
696 {
697     XWindowAttributes child_attrs;
698     Window root, parent, *child;	/* variables for XQueryTree() */
699     Window *save_child_list;		/* variables for XQueryTree() */
700     unsigned int nchild;		/* variables for XQueryTree() */
701     XRectangle child_clip;		/* vis part of child */
702     int curr_clipX, curr_clipY, curr_clipRt, curr_clipBt;
703 
704     /* check that win is mapped & not outside bounding box */
705     if (curr_attrs->map_state == IsViewable &&
706 	curr_attrs->class == InputOutput &&
707 	!( pclip->x >= (int) (bbox->x + bbox->width)	||
708 	   pclip->y >= (int) (bbox->y + bbox->height)	||
709 	   (int) (pclip->x + pclip->width)  <= bbox->x	||
710 	   (int) (pclip->y + pclip->height) <= bbox->y)) {
711 
712 	XQueryTree( disp, curr, &root, &parent, &child, &nchild );
713 	save_child_list = child;      /* so we can free list when we're done */
714 	add_window_to_list( image_wins, curr, x_rootrel, y_rootrel,
715 			    pclip->x, pclip->y,
716 			    pclip->width, pclip->height,
717 			    curr_attrs->border_width,curr_attrs->visual,
718 			    curr_attrs->colormap, parent);
719 
720 
721 /** ------------------------------------------------------------------------
722 	set RR coords of right (Rt), left (X), bottom (Bt) and top (Y)
723 	of rect we clip all children by.  This is our own clip rect (pclip)
724 	inflicted on us by our parent plus our own borders.  Within the
725 	child loop, we figure the clip rect for each child by adding in
726 	it's rectangle (not taking into account the child's borders).
727     ------------------------------------------------------------------------ **/
728 	curr_clipX = MAX( pclip->x, x_rootrel + (int) curr_attrs->border_width);
729 	curr_clipY = MAX( pclip->y, y_rootrel + (int) curr_attrs->border_width);
730 	curr_clipRt = MIN( pclip->x + (int) pclip->width,
731 			   x_rootrel + (int) curr_attrs->width +
732 			   2 * (int) curr_attrs->border_width);
733 	curr_clipBt = MIN( pclip->y + (int) pclip->height,
734 			   y_rootrel + (int) curr_attrs->height +
735 			   2 * (int) curr_attrs->border_width);
736 
737 	while (nchild--) {
738 	    int new_width, new_height;
739 	    int child_xrr, child_yrr;	/* root relative x & y of child */
740 
741 	    XGetWindowAttributes( disp, *child, &child_attrs);
742 
743 	    /* intersect parent & child clip rects */
744 	    child_xrr = x_rootrel + child_attrs.x + curr_attrs->border_width;
745 	    child_clip.x = MAX( curr_clipX, child_xrr);
746 	    new_width = MIN( curr_clipRt, child_xrr + (int) child_attrs.width
747 			     + 2 * child_attrs.border_width)
748 			- child_clip.x;
749 	    if (new_width >= 0) {
750 		child_clip.width = new_width;
751 
752 		child_yrr = y_rootrel + child_attrs.y +
753 			    curr_attrs->border_width;
754 		child_clip.y = MAX( curr_clipY, child_yrr);
755 		new_height = MIN( curr_clipBt,
756 				  child_yrr + (int) child_attrs.height +
757 				      2 * child_attrs.border_width)
758 			     - child_clip.y;
759 		if (new_height >= 0) {
760 		    child_clip.height = new_height;
761 		    make_src_list( disp, image_wins, bbox, *child,
762 				   child_xrr, child_yrr,
763 				   &child_attrs, &child_clip);
764 		}
765 	    }
766 	    child++;
767 	}
768 	XFree( save_child_list);
769     }
770 }
771 
772 
773 /** ------------------------------------------------------------------------
774 	This function creates a list of regions which tile a specified
775 	window.  Each region contains all visible portions of the window
776 	which are drawn with the same visual.  For example, if the
777 	window consists of subwindows of two different visual types,
778 	there will be two regions in the list.
779 	Returns a pointer to the list.
780     ------------------------------------------------------------------------ **/
make_region_list(disp,win,bbox,hasNonDefault,numImageVisuals,pImageVisuals,allImage)781 static list_ptr make_region_list( disp, win, bbox, hasNonDefault,
782 			     numImageVisuals, pImageVisuals, allImage)
783     Display 		*disp;
784     Window 		win;
785     XRectangle 		*bbox;
786     int 		*hasNonDefault;
787     int			numImageVisuals;
788     XVisualInfo		**pImageVisuals;
789     int			*allImage;
790 {
791     XWindowAttributes	win_attrs;
792     list		image_wins;
793     list_ptr		image_regions;
794     list_ptr		srcs_left;
795     image_region_type	*new_reg;
796     image_win_type	*base_src, *src;
797     Region		bbox_region = XCreateRegion();
798     XRectangle		clip;
799     int			image_only;
800 
801     int                 count=0 ;
802 
803     *hasNonDefault = False;
804     XUnionRectWithRegion( bbox, bbox_region, bbox_region);
805     XGetWindowAttributes( disp, win, &win_attrs);
806 
807     zero_list( &image_wins);
808     clip.x = 0;
809     clip.y = 0;
810     clip.width  = win_attrs.width;
811     clip.height = win_attrs.height;
812     make_src_list( disp, &image_wins, bbox, win,
813 		   0 /* x_rootrel */, 0 /* y_rootrel */, &win_attrs, &clip);
814 
815     image_regions = new_list();
816     image_only = (*allImage) ? True:False;
817 
818     for (base_src = (image_win_type *) first_in_list( &image_wins); base_src;
819 	 base_src = (image_win_type *) next_in_list( &image_wins))
820     {
821 	/* test for image visual */
822 	if (!image_only || src_in_image(base_src, numImageVisuals, pImageVisuals))
823 	{
824 	    /* find a window whose visual hasn't been put in list yet */
825 	    if (!src_in_region_list( base_src, image_regions))
826 	    {
827 		if (! (new_reg = (image_region_type *)
828 					malloc( sizeof( image_region_type)))) {
829 		    return (list_ptr) NULL;
830 		}
831 		count++;
832 
833 		new_reg->visible_region = XCreateRegion();
834 		new_reg->win		= base_src->win;
835 		new_reg->vis		= base_src->vis;
836 		new_reg->cmap	 	= base_src->cmap;
837 		new_reg->x_rootrel	= base_src->x_rootrel;
838 		new_reg->y_rootrel	= base_src->y_rootrel;
839 		new_reg->x_vis		= base_src->x_vis;
840 		new_reg->y_vis		= base_src->y_vis;
841 		new_reg->width		= base_src->width;
842 		new_reg->height		= base_src->height;
843 		new_reg->border		= base_src->border_width;
844 
845 		srcs_left = (list_ptr) dup_list_head( &image_wins, START_AT_CURR);
846 		for (src = (image_win_type *) first_in_list( srcs_left); src;
847 		     src = (image_win_type *) next_in_list( srcs_left)) {
848 		    if (SAME_REGIONS( base_src, src)) {
849 			add_rect_to_image_region( new_reg, src->x_vis, src->y_vis,
850 						  src->width, src->height);
851 		    }
852 		    else {
853 			if (!image_only || src_in_image(src, numImageVisuals, pImageVisuals))
854 			{
855 			    subtr_rect_from_image_region( new_reg, src->x_vis,
856 					  src->y_vis, src->width, src->height);
857 			}
858 		    }
859 		}
860 		XIntersectRegion( bbox_region, new_reg->visible_region,
861 				  new_reg->visible_region);
862 		if (! XEmptyRegion( new_reg->visible_region)) {
863 		    add_to_list( image_regions, new_reg);
864 		    if (new_reg->vis != DefaultVisualOfScreen( win_attrs.screen) ||
865 			new_reg->cmap != DefaultColormapOfScreen(
866 							    win_attrs.screen)) {
867 			*hasNonDefault = True;
868 		    }
869 		}
870 		else {
871 		    XDestroyRegion( new_reg->visible_region);
872 		    free( (void *) new_reg);
873 		}
874 	    }
875 	} else *allImage = 0;
876     }
877     delete_list( &image_wins, True);
878     XDestroyRegion( bbox_region);
879     return image_regions;
880 }
881 /** ------------------------------------------------------------------------
882 	Destructor called from destroy_region_list().
883     ------------------------------------------------------------------------ **/
destroy_image_region(image_region)884 void destroy_image_region( image_region)
885     image_region_type *image_region;
886 {
887     XDestroyRegion( image_region->visible_region);
888     free( (void *) image_region);
889 }
890 
891 /** ------------------------------------------------------------------------
892 	Destroys the region list, destroying all the regions contained in it.
893     ------------------------------------------------------------------------ **/
destroy_region_list(rlist)894 static void destroy_region_list( rlist)
895     list_ptr rlist;
896 {
897     delete_list_destroying( rlist, (DESTRUCT_FUNC_PTR)destroy_image_region);
898 }
899 
900 
901 /** ------------------------------------------------------------------------
902 	Subtracts the specified rectangle from the region in image_region.
903 	First converts the rectangle to a region of its own, since X
904 	only provides a way to subtract one region from another, not a
905 	rectangle from a region.
906     ------------------------------------------------------------------------ **/
subtr_rect_from_image_region(image_region,x,y,width,height)907 static void subtr_rect_from_image_region( image_region, x, y, width, height)
908     image_region_type *image_region;
909     int x;
910     int y;
911     int width;
912     int height;
913 {
914     XRectangle rect;
915     Region rect_region;
916 
917     rect_region = XCreateRegion();
918     rect.x = x;
919     rect.y = y;
920     rect.width = width;
921     rect.height = height;
922     XUnionRectWithRegion( &rect, rect_region, rect_region);
923     XSubtractRegion( image_region->visible_region, rect_region,
924 		     image_region->visible_region);
925     XDestroyRegion( rect_region);
926 }
927 
928 
929 /** ------------------------------------------------------------------------
930 	Adds the specified rectangle to the region in image_region.
931     ------------------------------------------------------------------------ **/
add_rect_to_image_region(image_region,x,y,width,height)932 static void add_rect_to_image_region( image_region, x, y, width, height)
933     image_region_type *image_region;
934     int x;
935     int y;
936     int width;
937     int height;
938 {
939     XRectangle rect;
940 
941     rect.x = x;
942     rect.y = y;
943     rect.width = width;
944     rect.height = height;
945     XUnionRectWithRegion( &rect, image_region->visible_region,
946 			  image_region->visible_region);
947 }
948 
949 
950 /** ------------------------------------------------------------------------
951 	Returns TRUE if the given src's visual is already represented in
952 	the image_regions list, FALSE otherwise.
953     ------------------------------------------------------------------------ **/
src_in_region_list(src,image_regions)954 static int src_in_region_list( src, image_regions)
955     image_win_type *src;
956     list_ptr image_regions;
957 {
958     image_region_type	*ir;
959 
960     for (ir = (image_region_type *) first_in_list( image_regions); ir;
961 	 ir = (image_region_type *) next_in_list( image_regions)) {
962 	if (SAME_REGIONS( ir, src)) {
963 
964 	    return 1;
965 	}
966     }
967 
968     return 0;
969 }
970 
971 
972 /** ------------------------------------------------------------------------
973 	Makes a new entry in image_wins with the given fields filled in.
974     ------------------------------------------------------------------------ **/
add_window_to_list(image_wins,w,xrr,yrr,x_vis,y_vis,width,height,border_width,vis,cmap,parent)975 static void add_window_to_list( image_wins, w, xrr, yrr, x_vis, y_vis,
976 				width, height, border_width,vis, cmap, parent)
977     list_ptr	image_wins;
978     Window	w;
979     int		xrr;
980     int 	yrr;
981     int		x_vis;
982     int 	y_vis;
983     int 	width;
984     int 	height;
985     Visual	*vis;
986     Colormap	cmap;
987     Window	parent;
988 {
989     image_win_type	*new_src;
990 
991     if ((new_src = (image_win_type *) malloc( sizeof( image_win_type))) == NULL)
992 
993 	return;
994 
995     new_src->win = w;
996     new_src->x_rootrel = xrr;
997     new_src->y_rootrel = yrr;
998     new_src->x_vis = x_vis;
999     new_src->y_vis = y_vis;
1000     new_src->width = width;
1001     new_src->height = height;
1002     new_src->border_width = border_width;
1003     new_src->vis = vis;
1004     new_src->cmap = cmap;
1005     new_src->parent = parent;
1006     add_to_list( image_wins, new_src);
1007 }
1008 
1009 /** ------------------------------------------------------------------------
1010 	Returns TRUE if the given src's visual is in the image planes,
1011 	FALSE otherwise.
1012     ------------------------------------------------------------------------ **/
src_in_image(src,numImageVisuals,pImageVisuals)1013 static int src_in_image( src, numImageVisuals, pImageVisuals)
1014     image_win_type 	*src;
1015     int			numImageVisuals;
1016     XVisualInfo		**pImageVisuals;
1017 {
1018     int 		i;
1019 
1020     for (i = 0 ; i < numImageVisuals ; i++)
1021     {
1022 	if (pImageVisuals[i]->visual == src->vis)
1023 	    return 1;
1024     }
1025     return 0;
1026 }
1027 
1028 
1029 /** ------------------------------------------------------------------------
1030 	Returns TRUE if the given src's visual is in the overlay planes
1031 	and transparency is possible, FALSE otherwise.
1032     ------------------------------------------------------------------------ **/
src_in_overlay(src,numOverlayVisuals,pOverlayVisuals,transparentColor,transparentType)1033 static int src_in_overlay( src, numOverlayVisuals, pOverlayVisuals,
1034 			transparentColor, transparentType)
1035     image_region_type 	*src;
1036     int			numOverlayVisuals;
1037     OverlayInfo         *pOverlayVisuals;
1038     int			*transparentColor;
1039     int			*transparentType;
1040 {
1041     int 		i;
1042 
1043     for (i = 0 ; i < numOverlayVisuals ; i++)
1044     {
1045 	if (((pOverlayVisuals[i].pOverlayVisualInfo)->visual == src->vis)
1046 		&& (pOverlayVisuals[i].transparentType != None))
1047 	{
1048 	    *transparentColor = pOverlayVisuals[i].value;
1049 	    *transparentType = pOverlayVisuals[i].transparentType;
1050 	    return 1;
1051 	}
1052 
1053 	else {
1054 	}
1055 
1056     }
1057     return 0;
1058 }
1059 
1060 
1061 /********************** from wsutils.c ******************************/
1062 
1063 /******************************************************************************
1064  *
1065  * This file contains a set of example utility procedures; procedures that can
1066  * help a "window-smart" Starbase or PHIGS program determine information about
1067  * a device, and create image and overlay plane windows.  To use these
1068  * utilities, #include "wsutils.h" and compile this file and link the results
1069  * with your program.
1070  *
1071  ******************************************************************************/
1072 
1073 
1074 
1075 #define STATIC_GRAY	0x01
1076 #define GRAY_SCALE	0x02
1077 #define PSEUDO_COLOR	0x04
1078 #define TRUE_COLOR	0x10
1079 #define DIRECT_COLOR	0x11
1080 
1081 
1082 static int	weCreateServerOverlayVisualsProperty = False;
1083 
1084 
1085 /******************************************************************************
1086  *
1087  * GetXVisualInfo()
1088  *
1089  * This routine takes an X11 Display, screen number, and returns whether the
1090  * screen supports transparent overlays and three arrays:
1091  *
1092  *	1) All of the XVisualInfo struct's for the screen.
1093  *	2) All of the OverlayInfo struct's for the screen.
1094  *	3) An array of pointers to the screen's image plane XVisualInfo
1095  *	   structs.
1096  *
1097  * The code below obtains the array of all the screen's visuals, and obtains
1098  * the array of all the screen's overlay visual information.  It then processes
1099  * the array of the screen's visuals, determining whether the visual is an
1100  * overlay or image visual.
1101  *
1102  * If the routine sucessfully obtained the visual information, it returns zero.
1103  * If the routine didn't obtain the visual information, it returns non-zero.
1104  *
1105  ******************************************************************************/
1106 
GetXVisualInfo(display,screen,transparentOverlays,numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,numImageVisuals,pImageVisuals)1107 int GetXVisualInfo(display, screen, transparentOverlays,
1108 		   numVisuals, pVisuals,
1109 		   numOverlayVisuals, pOverlayVisuals,
1110 		   numImageVisuals, pImageVisuals)
1111 
1112     Display	*display;		/* Which X server (aka "display"). */
1113     int		screen;			/* Which screen of the "display". */
1114     int		*transparentOverlays;	/* Non-zero if there's at least one
1115 					 * overlay visual and if at least one
1116 					 * of those supports a transparent
1117 					 * pixel. */
1118     int		*numVisuals;		/* Number of XVisualInfo struct's
1119 					 * pointed to to by pVisuals. */
1120     XVisualInfo	**pVisuals;		/* All of the device's visuals. */
1121     int		*numOverlayVisuals;	/* Number of OverlayInfo's pointed
1122 					 * to by pOverlayVisuals.  If this
1123 					 * number is zero, the device does
1124 					 * not have overlay planes. */
1125     OverlayInfo	**pOverlayVisuals;	/* The device's overlay plane visual
1126 					 * information. */
1127     int		*numImageVisuals;	/* Number of XVisualInfo's pointed
1128 					 * to by pImageVisuals. */
1129     XVisualInfo	***pImageVisuals;	/* The device's image visuals. */
1130 {
1131     XVisualInfo	getVisInfo;		/* Paramters of XGetVisualInfo */
1132     int		mask;
1133     XVisualInfo	*pVis, **pIVis;		/* Faster, local copies */
1134     OverlayInfo	*pOVis;
1135     OverlayVisualPropertyRec	*pOOldVis;
1136     int		nVisuals, nOVisuals, nIVisuals;
1137     Atom	overlayVisualsAtom;	/* Parameters for XGetWindowProperty */
1138     Atom	actualType;
1139     unsigned long numLongs, bytesAfter;
1140     int		actualFormat;
1141     int		nImageVisualsAlloced;	/* Values to process the XVisualInfo */
1142     int		imageVisual;		/* array */
1143 
1144 
1145     /* First, get the list of visuals for this screen. */
1146     getVisInfo.screen = screen;
1147     mask = VisualScreenMask;
1148 
1149     *pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals);
1150     if ((nVisuals = *numVisuals) <= 0)
1151     {
1152 	/* Return that the information wasn't sucessfully obtained: */
1153 	return(1);
1154     }
1155     pVis = *pVisuals;
1156 
1157 
1158     /* Now, get the overlay visual information for this screen.  To obtain
1159      * this information, get the SERVER_OVERLAY_VISUALS property.
1160      */
1161     overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True);
1162     if (overlayVisualsAtom != None)
1163     {
1164 	/* Since the Atom exists, we can request the property's contents.  The
1165 	 * do-while loop makes sure we get the entire list from the X server.
1166 	 */
1167 	bytesAfter = 0;
1168 	numLongs = sizeof(OverlayVisualPropertyRec) / 4;
1169 	do
1170 	{
1171 	    numLongs += bytesAfter * 4;
1172 	    XGetWindowProperty(display, RootWindow(display, screen),
1173 			       overlayVisualsAtom, 0, numLongs, False,
1174 			       overlayVisualsAtom, &actualType, &actualFormat,
1175 			       &numLongs, &bytesAfter, (unsigned char**) pOverlayVisuals);
1176 	} while (bytesAfter > 0);
1177 
1178 
1179 	/* Calculate the number of overlay visuals in the list. */
1180 	*numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / 4);
1181     }
1182     else
1183     {
1184 	/* This screen doesn't have overlay planes. */
1185 	*numOverlayVisuals = 0;
1186 	*pOverlayVisuals = NULL;
1187 	*transparentOverlays = 0;
1188     }
1189 
1190 
1191     /* Process the pVisuals array. */
1192     *numImageVisuals = 0;
1193     nImageVisualsAlloced = 1;
1194     pIVis = *pImageVisuals = (XVisualInfo **) malloc(sizeof(XVisualInfo *));
1195     while (--nVisuals >= 0)
1196     {
1197 	nOVisuals = *numOverlayVisuals;
1198 	pOVis = *pOverlayVisuals;
1199 	imageVisual = True;
1200 	while (--nOVisuals >= 0)
1201 	{
1202 	    pOOldVis = (OverlayVisualPropertyRec *) pOVis;
1203 	    if (pVis->visualid == pOOldVis->visualID)
1204 	    {
1205 		imageVisual = False;
1206 		pOVis->pOverlayVisualInfo = pVis;
1207 		if (pOVis->transparentType == TransparentPixel)
1208 		    *transparentOverlays = 1;
1209 	    }
1210 	    pOVis++;
1211 	}
1212 	if (imageVisual)
1213 	{
1214 	    if ((*numImageVisuals += 1) > nImageVisualsAlloced)
1215 	    {
1216 		nImageVisualsAlloced++;
1217 		*pImageVisuals = (XVisualInfo **)
1218 		    realloc(*pImageVisuals, (nImageVisualsAlloced * sizeof(XVisualInfo *)));
1219 		pIVis = *pImageVisuals + (*numImageVisuals - 1);
1220 	    }
1221 	    *pIVis++ = pVis;
1222 	}
1223 	pVis++;
1224     }
1225 
1226 
1227     /* Return that the information was sucessfully obtained: */
1228     return(0);
1229 
1230 } /* GetXVisualInfo() */
1231 
1232 
1233 /******************************************************************************
1234  *
1235  * FreeXVisualInfo()
1236  *
1237  * This routine frees the data that was allocated by GetXVisualInfo().
1238  *
1239  ******************************************************************************/
1240 
FreeXVisualInfo(pVisuals,pOverlayVisuals,pImageVisuals)1241 void FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals)
1242 
1243     XVisualInfo	*pVisuals;
1244     OverlayInfo	*pOverlayVisuals;
1245     XVisualInfo	**pImageVisuals;
1246 {
1247     XFree(pVisuals);
1248     if (weCreateServerOverlayVisualsProperty)
1249 	free(pOverlayVisuals);
1250     else
1251 	XFree(pOverlayVisuals);
1252     free(pImageVisuals);
1253 
1254 } /* FreeXVisualInfo() */
1255