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