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              *reg_image, *ximage ;
 398     int32_t             srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
 399     int32_t             dst_x, dst_y;   /* where in pixmap to write (UL) */
 400     int32_t             diff;
 401 
 402     ximage = XCreateImage(disp,fakeVis,(uint32_t) depth,format,0,NULL,
 403                           (uint32_t)width,(uint32_t)height,8,0);
 404 
 405     ximage->data = calloc(ximage->bytes_per_line*height*((format==ZPixmap)? 1 : depth), sizeof(char));
 406     ximage->bits_per_pixel = depth; /** Valid only if format is ZPixmap ***/
 407 
 408     for (reg = (image_region_type *) first_in_list( regions); reg;
 409          reg = (image_region_type *) next_in_list( regions))
 410     {
 411                 int32_t rect;
 412                 struct my_XRegion *vis_reg = (struct my_XRegion *)(reg->visible_region);
 413                 for (rect = 0; rect < vis_reg->numRects; rect++)
 414                 {
 415                     /** ------------------------------------------------------------------------
 416                             Intersect bbox with visible part of region giving src rect & output
 417                             location.  Width is the min right side minus the max left side.
 418                             Similar for height.  Offset src rect so x,y are relative to
 419                             origin of win, not the root-relative visible rect of win.
 420                         ------------------------------------------------------------------------ **/
 421                         srcRect_width  = MIN( vis_reg->rects[rect].x2, bbox.width + bbox.x)
 422                                          - MAX( vis_reg->rects[rect].x1, bbox.x);
 423 
 424                         srcRect_height = MIN( vis_reg->rects[rect].y2, bbox.height + bbox.y)
 425                                          - MAX( vis_reg->rects[rect].y1, bbox.y);
 426 
 427                         diff = bbox.x - vis_reg->rects[rect].x1;
 428                         srcRect_x = MAX( 0, diff)  + (vis_reg->rects[rect].x1 - reg->x_rootrel - reg->border);
 429                         dst_x     = MAX( 0, -diff) ;
 430 
 431                         diff = bbox.y - vis_reg->rects[rect].y1;
 432                         srcRect_y = MAX( 0, diff)  + (vis_reg->rects[rect].y1 - reg->y_rootrel - reg->border);
 433                         dst_y     = MAX( 0, -diff) ;
 434                         reg_image = XGetImage(disp,reg->win,srcRect_x,srcRect_y,
 435                                             (uint32_t) srcRect_width, (uint32_t) srcRect_height,AllPlanes,format) ;
 436 
 437                         if (reg_image) {
 438                             TransferImage(disp,reg_image,srcRect_width,
 439                                             srcRect_height,reg,ximage,dst_x,dst_y) ;
 440                             XDestroyImage(reg_image);
 441                         }
 442                 }
 443     }
 444     return ximage ;
 445 }
 446 
 447 
 448 /** ------------------------------------------------------------------------
 449     ------------------------------------------------------------------------ **/
 450 
 451 XImage *ReadAreaToImage(disp, srcRootWinid, x, y, width, height,
 452     numVisuals,pVisuals,numOverlayVisuals,pOverlayVisuals,numImageVisuals,
 453     pImageVisuals,vis_regions,vis_image_regions,format,allImage)
 454     Display             *disp;
 455     Window              srcRootWinid;   /* root win on which grab was done */
 456     int32_t                     x;   /* root rel UL corner of bounding box of grab */
 457     int32_t                     y;
 458     uint32_t            width;  /* size of bounding box of grab */
 459     uint32_t            height;
 460     /** int32_t                 transparentOverlays; ***/
 461     int32_t                     numVisuals;
 462     XVisualInfo         *pVisuals;
 463     int32_t                     numOverlayVisuals;
 464     OverlayInfo         *pOverlayVisuals;
 465     int32_t                     numImageVisuals;
 466     XVisualInfo         **pImageVisuals;
 467     list_ptr            vis_regions;    /* list of regions to read from */
 468     list_ptr            vis_image_regions ;/* list of regions to read from */
 469     int32_t                     format;
 470     int32_t             allImage ;
 471 {
 472     image_region_type   *reg;
 473     XRectangle          bbox;           /* bounding box of grabbed area */
 474     int32_t             depth ;
 475     XImage              *ximage, *ximage_ipm ;
 476     Visual              fakeVis ;
 477     int32_t     x1, y1;
 478     XImage      *image;
 479     unsigned char       *pmData ,  *ipmData ;
 480     int32_t                 transparentColor, transparentType;
 481     int32_t                     srcRect_x,srcRect_y,srcRect_width,srcRect_height ;
 482     int32_t                     diff ;
 483     int32_t                     dst_x, dst_y;   /* where in pixmap to write (UL) */
 484     int32_t                     pixel;
 485 
 486     bbox.x = (short) x;                 /* init X rect for bounding box */
 487     bbox.y = (short) y;
 488     bbox.width = (unsigned short) width;
 489     bbox.height = (unsigned short) height;
 490     ximage_ipm = NULL;
 491 
 492 
 493     initFakeVisual(&fakeVis) ;
 494 
 495     depth = 24 ;
 496     ximage = ReadRegionsInList(disp,&fakeVis,depth,format,
 497              (int32_t) width, (int32_t) height, bbox,vis_regions) ;
 498 
 499     pmData = (unsigned char *)ximage -> data ;
 500 
 501 /* if transparency possible do it again, but this time for image planes only */
 502     if (vis_image_regions && (vis_image_regions->next) && !allImage)
 503     {
 504             ximage_ipm = ReadRegionsInList(disp,&fakeVis,depth,format,
 505                          (int32_t) width, (int32_t) height,bbox,vis_image_regions) ;
 506         ipmData = (unsigned char *)ximage_ipm -> data ;
 507     }
 508 /* Now tranverse the overlay visual windows and test for transparency index.  */
 509 /* If you find one, subsitute the value from the matching image plane pixmap. */
 510 
 511     for (reg = (image_region_type *) first_in_list( vis_regions); reg;
 512          reg = (image_region_type *) next_in_list( vis_regions))
 513     {
 514 
 515         if (src_in_overlay( reg, numOverlayVisuals, pOverlayVisuals,
 516                                  &transparentColor, &transparentType))
 517         {
 518          int32_t test = 0 ;
 519              srcRect_width  = MIN( reg->width + reg->x_vis, bbox.width + bbox.x)
 520                                  - MAX( reg->x_vis, bbox.x);
 521              srcRect_height = MIN( reg->height + reg->y_vis, bbox.height
 522                                  + bbox.y) - MAX( reg->y_vis, bbox.y);
 523          diff = bbox.x - reg->x_vis;
 524          srcRect_x = MAX( 0, diff) + (reg->x_vis - reg->x_rootrel - reg->border);
 525          dst_x     = MAX( 0, -diff) ;
 526              diff = bbox.y - reg->y_vis;
 527              srcRect_y = MAX( 0, diff)  + (reg->y_vis - reg->y_rootrel - reg->border);
 528              dst_y     = MAX( 0, -diff) ;
 529         /* let's test some pixels for transparency */
 530          image = XGetImage(disp, reg->win, srcRect_x, srcRect_y,
 531                            (uint32_t) srcRect_width, (uint32_t) srcRect_height,
 532                            0xffffffff, ZPixmap);
 533 
 534         /* let's assume byte per pixel for overlay image for now */
 535              if ((image->depth == 8) && (transparentType == TransparentPixel))
 536              {
 537                  unsigned char *pixel_ptr;
 538                  unsigned char *start_of_line = (unsigned char *) image->data;
 539 
 540                  for (y1 = 0; y1 < srcRect_height; y1++) {
 541                     pixel_ptr = start_of_line;
 542                     for (x1 = 0; x1 < srcRect_width; x1++)
 543                     {
 544                         if (*pixel_ptr++ == transparentColor)
 545                         {
 546                         /*
 547                             *pmData++ = *ipmData++;
 548                             *pmData++ = *ipmData++;
 549                             *pmData++ = *ipmData++;
 550                         */
 551                         pixel = (int32_t) XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
 552                     XPutPixel(ximage,dst_x+x1, dst_y+y1,(unsigned long)pixel);
 553 
 554                         if(!test){
 555                            test = 1 ;
 556                         }
 557                         }
 558                         /*
 559                         else {
 560                             pmData +=3;
 561                             ipmData +=3;
 562                         }
 563                         */
 564                     }
 565                     start_of_line += image->bytes_per_line;
 566                 }
 567         } else {
 568                 if (transparentType == TransparentPixel) {
 569                 for (y1 = 0; y1 < srcRect_height; y1++) {
 570                       for (x1 = 0; x1 < srcRect_width; x1++)
 571                       {
 572                             int32_t pixel_value = (int32_t) XGetPixel(image, x1, y1);
 573                             if (pixel_value == transparentColor)
 574                             {
 575                             /*
 576                                 *pmData++ = *ipmData++;
 577                                 *pmData++ = *ipmData++;
 578                                 *pmData++ = *ipmData++;
 579                             */
 580                         pixel = (int32_t) XGetPixel(ximage_ipm,dst_x+x1,dst_y+y1) ;
 581                     XPutPixel(ximage,dst_x+x1, dst_y+y1,(unsigned long)pixel);
 582                         if(!test){
 583                            test = 1 ;
 584                         }
 585                             }
 586                             /*
 587                             else {
 588                                 pmData +=3;
 589                                 ipmData +=3;
 590                             }
 591                             */
 592                         }
 593                     }
 594                 } else {
 595                     for (y1 = 0; y1 < srcRect_height; y1++) {
 596                         for (x1 = 0; x1 < srcRect_width; x1++)
 597                         {
 598                             int32_t pixel_value = (int32_t) XGetPixel(image, x1, y1);
 599                             if (pixel_value & transparentColor)
 600                             {
 601                             /*
 602                                 *pmData++ = *ipmData++;
 603                                 *pmData++ = *ipmData++;
 604                                 *pmData++ = *ipmData++;
 605                             */
 606                      pixel = (int32_t) XGetPixel(ximage_ipm,dst_x+x1,
 607                                     dst_y+y1) ;
 608                      XPutPixel(ximage,dst_x+x1, dst_y+y1,(unsigned long)pixel);
 609                         if(!test){
 610                            test = 1 ;
 611                         }
 612                             }
 613                             /*
 614                             else {
 615                                 pmData +=3;
 616                                 ipmData +=3;
 617                             }
 618                             */
 619                         }
 620                     }
 621                 }
 622         }
 623         XDestroyImage (image);
 624       } /* end of src_in_overlay */
 625     } /** end transparency **/
 626     if (ximage_ipm != NULL) {
 627         XDestroyImage(ximage_ipm);
 628     }
 629     destroy_region_list( vis_regions);
 630     if (vis_image_regions) destroy_region_list( vis_image_regions );
 631     FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals);
 632     XSync(disp, 0);
 633 
 634     return ximage;
 635 }
 636 
 637 /** ------------------------------------------------------------------------
 638         Creates a list of the subwindows of a given window which have a
 639         different visual than their parents.  The function is recursive.
 640         This list is used in make_region_list(), which coalesces the
 641         windows with the same visual into a region.
 642         image_wins must point to an existing list struct that's already
 643         been zeroed (zero_list()).
 644     ------------------------------------------------------------------------ **/
 645 static void make_src_list( disp, image_wins, bbox, curr, x_rootrel, y_rootrel,
 646                     curr_attrs, pclip)
 647     Display             *disp;
 648     list_ptr            image_wins;
 649     XRectangle          *bbox;                  /* bnding box of area we want */
 650     Window              curr;
 651     int32_t                     x_rootrel;              /* pos of curr WRT root */
 652     int32_t                     y_rootrel;
 653     XWindowAttributes   *curr_attrs;
 654     XRectangle          *pclip;                 /* visible part of curr, not */
 655                                                 /* obscurred by ancestors */
 656 {
 657     XWindowAttributes child_attrs;
 658     Window root, parent, *child;        /* variables for XQueryTree() */
 659     Window *save_child_list;            /* variables for XQueryTree() */
 660     uint32_t nchild;            /* variables for XQueryTree() */
 661     XRectangle child_clip;              /* vis part of child */
 662     int32_t curr_clipX, curr_clipY, curr_clipRt, curr_clipBt;
 663 
 664     /* check that win is mapped & not outside bounding box */
 665     if (curr_attrs->map_state == IsViewable &&
 666         curr_attrs->class == InputOutput &&
 667         !( pclip->x >= (bbox->x + bbox->width)  ||
 668            pclip->y >= (bbox->y + bbox->height) ||
 669            (pclip->x + pclip->width)  <= bbox->x        ||
 670            (pclip->y + pclip->height) <= bbox->y)) {
 671 
 672         XQueryTree( disp, curr, &root, &parent, &child, &nchild );
 673         save_child_list = child;      /* so we can free list when we're done */
 674         add_window_to_list( image_wins, curr, x_rootrel, y_rootrel,
 675                             (int32_t) pclip->x, (int32_t) pclip->y,
 676                             (int32_t) pclip->width, (int32_t) pclip->height,
 677                             curr_attrs->border_width,curr_attrs->visual,
 678                             curr_attrs->colormap, parent);
 679 
 680 
 681 /** ------------------------------------------------------------------------
 682         set RR coords of right (Rt), left (X), bottom (Bt) and top (Y)
 683         of rect we clip all children by.  This is our own clip rect (pclip)
 684         inflicted on us by our parent plus our own borders.  Within the
 685         child loop, we figure the clip rect for each child by adding in
 686         it's rectangle (not taking into account the child's borders).
 687     ------------------------------------------------------------------------ **/
 688         curr_clipX = MAX( pclip->x, x_rootrel + curr_attrs->border_width);
 689         curr_clipY = MAX( pclip->y, y_rootrel + curr_attrs->border_width);
 690         curr_clipRt = MIN(pclip->x + pclip->width,
 691                                   x_rootrel + curr_attrs->width + 2 * curr_attrs->border_width);
 692 
 693         curr_clipBt = MIN(pclip->y + pclip->height,
 694                                   y_rootrel + curr_attrs->height + 2 * curr_attrs->border_width);
 695 
 696 
 697         while (nchild--) {
 698             int32_t new_width, new_height;
 699             int32_t child_xrr, child_yrr;       /* root relative x & y of child */
 700 
 701             XGetWindowAttributes( disp, *child, &child_attrs);
 702 
 703             /* intersect parent & child clip rects */
 704             child_xrr = x_rootrel + child_attrs.x + curr_attrs->border_width;
 705             child_clip.x = (short) MAX( curr_clipX, child_xrr);
 706             new_width = MIN(curr_clipRt,
 707                         child_xrr + child_attrs.width +
 708                          2 * child_attrs.border_width) - child_clip.x;
 709 
 710             if (new_width >= 0) {
 711                 child_clip.width = (unsigned short) new_width;
 712 
 713                 child_yrr = y_rootrel + child_attrs.y +
 714                             curr_attrs->border_width;
 715                 child_clip.y = (short) MAX( curr_clipY, child_yrr);
 716                 new_height = MIN(curr_clipBt,
 717                                          child_yrr + (int32_t) child_attrs.height +
 718                                          2 * child_attrs.border_width) - child_clip.y;
 719 
 720                 if (new_height >= 0) {
 721                     child_clip.height = (unsigned short) new_height;
 722                     make_src_list( disp, image_wins, bbox, *child,
 723                                    child_xrr, child_yrr,
 724                                    &child_attrs, &child_clip);
 725                 }
 726             }
 727             child++;
 728         }
 729         XFree( save_child_list);
 730     }
 731 }
 732 
 733 
 734 /** ------------------------------------------------------------------------
 735         This function creates a list of regions which tile a specified
 736         window.  Each region contains all visible portions of the window
 737         which are drawn with the same visual.  For example, if the
 738         window consists of subwindows of two different visual types,
 739         there will be two regions in the list.
 740         Returns a pointer to the list.
 741     ------------------------------------------------------------------------ **/
 742 static list_ptr make_region_list( disp, win, bbox, hasNonDefault,
 743                              numImageVisuals, pImageVisuals, allImage)
 744     Display             *disp;
 745     Window              win;
 746     XRectangle          *bbox;
 747     int32_t             *hasNonDefault;
 748     int32_t                     numImageVisuals;
 749     XVisualInfo         **pImageVisuals;
 750     int32_t                     *allImage;
 751 {
 752     XWindowAttributes   win_attrs;
 753     list                image_wins;
 754     list_ptr            image_regions;
 755     list_ptr            srcs_left;
 756     image_region_type   *new_reg;
 757     image_win_type      *base_src, *src;
 758     Region              bbox_region = XCreateRegion();
 759     XRectangle          clip;
 760     int32_t                     image_only;
 761 
 762     int32_t                 count=0 ;
 763 
 764     *hasNonDefault = False;
 765     XUnionRectWithRegion( bbox, bbox_region, bbox_region);
 766     XGetWindowAttributes( disp, win, &win_attrs);
 767 
 768     zero_list( &image_wins);
 769     clip.x = 0;
 770     clip.y = 0;
 771     clip.width  = (unsigned short) win_attrs.width;
 772     clip.height = (unsigned short) win_attrs.height;
 773     make_src_list( disp, &image_wins, bbox, win,
 774                    0 /* x_rootrel */, 0 /* y_rootrel */, &win_attrs, &clip);
 775 
 776     image_regions = new_list();
 777     image_only = (*allImage) ? True:False;
 778 
 779     for (base_src = (image_win_type *) first_in_list( &image_wins); base_src;
 780          base_src = (image_win_type *) next_in_list( &image_wins))
 781     {
 782         /* test for image visual */
 783         if (!image_only || src_in_image(base_src, numImageVisuals, pImageVisuals))
 784         {
 785             /* find a window whose visual hasn't been put in list yet */
 786             if (!src_in_region_list( base_src, image_regions))
 787             {
 788                 if (! (new_reg = (image_region_type *)
 789                                         malloc( sizeof( image_region_type)))) {
 790                     return (list_ptr) NULL;
 791                 }
 792                 count++;
 793 
 794                 new_reg->visible_region = XCreateRegion();
 795                 new_reg->win            = base_src->win;
 796                 new_reg->vis            = base_src->vis;
 797                 new_reg->cmap           = base_src->cmap;
 798                 new_reg->x_rootrel      = base_src->x_rootrel;
 799                 new_reg->y_rootrel      = base_src->y_rootrel;
 800                 new_reg->x_vis          = base_src->x_vis;
 801                 new_reg->y_vis          = base_src->y_vis;
 802                 new_reg->width          = base_src->width;
 803                 new_reg->height         = base_src->height;
 804                 new_reg->border         = base_src->border_width;
 805 
 806                 srcs_left = (list_ptr) dup_list_head( &image_wins, START_AT_CURR);
 807                 for (src = (image_win_type *) first_in_list( srcs_left); src;
 808                      src = (image_win_type *) next_in_list( srcs_left)) {
 809                     if (SAME_REGIONS( base_src, src)) {
 810                         add_rect_to_image_region( new_reg, src->x_vis, src->y_vis,
 811                                                   src->width, src->height);
 812                     }
 813                     else {
 814                         if (!image_only || src_in_image(src, numImageVisuals, pImageVisuals))
 815                         {
 816                             subtr_rect_from_image_region( new_reg, src->x_vis,
 817                                           src->y_vis, src->width, src->height);
 818                         }
 819                     }
 820                 }
 821                 XIntersectRegion( bbox_region, new_reg->visible_region,
 822                                   new_reg->visible_region);
 823                 if (! XEmptyRegion( new_reg->visible_region)) {
 824                     add_to_list( image_regions, new_reg);
 825                     if (new_reg->vis != DefaultVisualOfScreen( win_attrs.screen) ||
 826                         new_reg->cmap != DefaultColormapOfScreen(
 827                                                             win_attrs.screen)) {
 828                         *hasNonDefault = True;
 829                     }
 830                 }
 831                 else {
 832                     XDestroyRegion( new_reg->visible_region);
 833                     free( (void *) new_reg);
 834                 }
 835             }
 836         } else *allImage = 0;
 837     }
 838     delete_list( &image_wins, True);
 839     XDestroyRegion( bbox_region);
 840     return image_regions;
 841 }
 842 /** ------------------------------------------------------------------------
 843         Destructor called from destroy_region_list().
 844     ------------------------------------------------------------------------ **/
 845 void destroy_image_region( image_region)
 846     image_region_type *image_region;
 847 {
 848     XDestroyRegion( image_region->visible_region);
 849     free( (void *) image_region);
 850 }
 851 
 852 /** ------------------------------------------------------------------------
 853         Destroys the region list, destroying all the regions contained in it.
 854     ------------------------------------------------------------------------ **/
 855 static void destroy_region_list( rlist)
 856     list_ptr rlist;
 857 {
 858     delete_list_destroying( rlist, (DESTRUCT_FUNC_PTR)destroy_image_region);
 859 }
 860 
 861 
 862 /** ------------------------------------------------------------------------
 863         Subtracts the specified rectangle from the region in image_region.
 864         First converts the rectangle to a region of its own, since X
 865         only provides a way to subtract one region from another, not a
 866         rectangle from a region.
 867     ------------------------------------------------------------------------ **/
 868 static void subtr_rect_from_image_region( image_region, x, y, width, height)
 869     image_region_type *image_region;
 870     int32_t x;
 871     int32_t y;
 872     int32_t width;
 873     int32_t height;
 874 {
 875     XRectangle rect;
 876     Region rect_region;
 877 
 878     rect_region = XCreateRegion();
 879     rect.x = (short)x;
 880     rect.y = (short)y;
 881     rect.width = (unsigned short)width;
 882     rect.height = (unsigned short)height;
 883     XUnionRectWithRegion( &rect, rect_region, rect_region);
 884     XSubtractRegion( image_region->visible_region, rect_region,
 885                      image_region->visible_region);
 886     XDestroyRegion( rect_region);
 887 }
 888 
 889 
 890 /** ------------------------------------------------------------------------
 891         Adds the specified rectangle to the region in image_region.
 892     ------------------------------------------------------------------------ **/
 893 static void add_rect_to_image_region( image_region, x, y, width, height)
 894     image_region_type *image_region;
 895     int32_t x;
 896     int32_t y;
 897     int32_t width;
 898     int32_t height;
 899 {
 900     XRectangle rect;
 901 
 902     rect.x = (short) x;
 903     rect.y = (short) y;
 904     rect.width = (unsigned short) width;
 905     rect.height = (unsigned short) height;
 906     XUnionRectWithRegion( &rect, image_region->visible_region,
 907                           image_region->visible_region);
 908 }
 909 
 910 
 911 /** ------------------------------------------------------------------------
 912         Returns TRUE if the given src's visual is already represented in
 913         the image_regions list, FALSE otherwise.
 914     ------------------------------------------------------------------------ **/
 915 static int32_t src_in_region_list( src, image_regions)
 916     image_win_type *src;
 917     list_ptr image_regions;
 918 {
 919     image_region_type   *ir;
 920 
 921     for (ir = (image_region_type *) first_in_list( image_regions); ir;
 922          ir = (image_region_type *) next_in_list( image_regions)) {
 923         if (SAME_REGIONS( ir, src)) {
 924 
 925             return 1;
 926         }
 927     }
 928 
 929     return 0;
 930 }
 931 
 932 
 933 /** ------------------------------------------------------------------------
 934         Makes a new entry in image_wins with the given fields filled in.
 935     ------------------------------------------------------------------------ **/
 936 static void add_window_to_list( image_wins, w, xrr, yrr, x_vis, y_vis,
 937                                 width, height, border_width,vis, cmap, parent)
 938     list_ptr    image_wins;
 939     Window      w;
 940     int32_t             xrr;
 941     int32_t     yrr;
 942     int32_t             x_vis;
 943     int32_t     y_vis;
 944     int32_t     width;
 945     int32_t     height;
 946     int32_t     border_width;
 947     Visual      *vis;
 948     Colormap    cmap;
 949     Window      parent;
 950 {
 951     image_win_type      *new_src;
 952 
 953     if ((new_src = (image_win_type *) malloc( sizeof( image_win_type))) == NULL)
 954 
 955         return;
 956 
 957     new_src->win = w;
 958     new_src->x_rootrel = xrr;
 959     new_src->y_rootrel = yrr;
 960     new_src->x_vis = x_vis;
 961     new_src->y_vis = y_vis;
 962     new_src->width = width;
 963     new_src->height = height;
 964     new_src->border_width = border_width;
 965     new_src->vis = vis;
 966     new_src->cmap = cmap;
 967     new_src->parent = parent;
 968     add_to_list( image_wins, new_src);
 969 }
 970 
 971 /** ------------------------------------------------------------------------
 972         Returns TRUE if the given src's visual is in the image planes,
 973         FALSE otherwise.
 974     ------------------------------------------------------------------------ **/
 975 static int32_t src_in_image( src, numImageVisuals, pImageVisuals)
 976     image_win_type      *src;
 977     int32_t                     numImageVisuals;
 978     XVisualInfo         **pImageVisuals;
 979 {
 980     int32_t             i;
 981 
 982     for (i = 0 ; i < numImageVisuals ; i++)
 983     {
 984         if (pImageVisuals[i]->visual == src->vis)
 985             return 1;
 986     }
 987     return 0;
 988 }
 989 
 990 
 991 /** ------------------------------------------------------------------------
 992         Returns TRUE if the given src's visual is in the overlay planes
 993         and transparency is possible, FALSE otherwise.
 994     ------------------------------------------------------------------------ **/
 995 static int32_t src_in_overlay( src, numOverlayVisuals, pOverlayVisuals,
 996                         transparentColor, transparentType)
 997     image_region_type   *src;
 998     int32_t                     numOverlayVisuals;
 999     OverlayInfo         *pOverlayVisuals;
1000     int32_t                     *transparentColor;
1001     int32_t                     *transparentType;
1002 {
1003     int32_t             i;
1004 
1005     for (i = 0 ; i < numOverlayVisuals ; i++)
1006     {
1007         if (((pOverlayVisuals[i].pOverlayVisualInfo)->visual == src->vis)
1008                 && (pOverlayVisuals[i].transparentType != None))
1009         {
1010             *transparentColor = pOverlayVisuals[i].value;
1011             *transparentType = pOverlayVisuals[i].transparentType;
1012             return 1;
1013         }
1014 
1015         else {
1016         }
1017 
1018     }
1019     return 0;
1020 }
1021 
1022 
1023 /********************** from wsutils.c ******************************/
1024 
1025 /******************************************************************************
1026  *
1027  * This file contains a set of example utility procedures; procedures that can
1028  * help a "window-smart" Starbase or PHIGS program determine information about
1029  * a device, and create image and overlay plane windows.  To use these
1030  * utilities, #include "wsutils.h" and compile this file and link the results
1031  * with your program.
1032  *
1033  ******************************************************************************/
1034 
1035 
1036 
1037 #define STATIC_GRAY     0x01
1038 #define GRAY_SCALE      0x02
1039 #define PSEUDO_COLOR    0x04
1040 #define TRUE_COLOR      0x10
1041 #define DIRECT_COLOR    0x11
1042 
1043 
1044 static int32_t  weCreateServerOverlayVisualsProperty = False;
1045 
1046 
1047 /******************************************************************************
1048  *
1049  * GetXVisualInfo()
1050  *
1051  * This routine takes an X11 Display, screen number, and returns whether the
1052  * screen supports transparent overlays and three arrays:
1053  *
1054  *      1) All of the XVisualInfo struct's for the screen.
1055  *      2) All of the OverlayInfo struct's for the screen.
1056  *      3) An array of pointers to the screen's image plane XVisualInfo
1057  *         structs.
1058  *
1059  * The code below obtains the array of all the screen's visuals, and obtains
1060  * the array of all the screen's overlay visual information.  It then processes
1061  * the array of the screen's visuals, determining whether the visual is an
1062  * overlay or image visual.
1063  *
1064  * If the routine sucessfully obtained the visual information, it returns zero.
1065  * If the routine didn't obtain the visual information, it returns non-zero.
1066  *
1067  ******************************************************************************/
1068 
1069 int32_t GetXVisualInfo(display, screen, transparentOverlays,
1070                    numVisuals, pVisuals,
1071                    numOverlayVisuals, pOverlayVisuals,
1072                    numImageVisuals, pImageVisuals)
1073 
1074     Display     *display;                   /* Which X server (aka "display"). */
1075     int32_t             screen;                 /* Which screen of the "display". */
1076     int32_t             *transparentOverlays;   /* Non-zero if there's at least one
1077                                          * overlay visual and if at least one
1078                                          * of those supports a transparent
1079                                          * pixel. */
1080     int32_t             *numVisuals;            /* Number of XVisualInfo struct's
1081                                          * pointed to by pVisuals. */
1082     XVisualInfo **pVisuals;             /* All of the device's visuals. */
1083     int32_t             *numOverlayVisuals;     /* Number of OverlayInfo's pointed
1084                                          * to by pOverlayVisuals.  If this
1085                                          * number is zero, the device does
1086                                          * not have overlay planes. */
1087     OverlayInfo **pOverlayVisuals;      /* The device's overlay plane visual
1088                                          * information. */
1089     int32_t             *numImageVisuals;       /* Number of XVisualInfo's pointed
1090                                          * to by pImageVisuals. */
1091     XVisualInfo ***pImageVisuals;       /* The device's image visuals. */
1092 {
1093     XVisualInfo getVisInfo;             /* Parameters of XGetVisualInfo */
1094     int32_t             mask;
1095     XVisualInfo *pVis, **pIVis;         /* Faster, local copies */
1096     OverlayInfo *pOVis;
1097     OverlayVisualPropertyRec    *pOOldVis;
1098     int32_t             nVisuals, nOVisuals;
1099     Atom        overlayVisualsAtom;     /* Parameters for XGetWindowProperty */
1100     Atom        actualType;
1101     unsigned long numLongs, bytesAfter;
1102     int32_t             actualFormat;
1103     int32_t             nImageVisualsAlloced;   /* Values to process the XVisualInfo */
1104     int32_t             imageVisual;            /* array */
1105 
1106 
1107     /* First, get the list of visuals for this screen. */
1108     getVisInfo.screen = screen;
1109     mask = VisualScreenMask;
1110 
1111     *pVisuals = XGetVisualInfo(display, mask, &getVisInfo, numVisuals);
1112     if ((nVisuals = *numVisuals) <= 0)
1113     {
1114         /* Return that the information wasn't sucessfully obtained: */
1115         return(1);
1116     }
1117     pVis = *pVisuals;
1118 
1119 
1120     /* Now, get the overlay visual information for this screen.  To obtain
1121      * this information, get the SERVER_OVERLAY_VISUALS property.
1122      */
1123     overlayVisualsAtom = XInternAtom(display, "SERVER_OVERLAY_VISUALS", True);
1124     if (overlayVisualsAtom != None)
1125     {
1126         /* Since the Atom exists, we can request the property's contents.  The
1127          * do-while loop makes sure we get the entire list from the X server.
1128          */
1129         bytesAfter = 0;
1130         numLongs = sizeof(OverlayVisualPropertyRec) / 4;
1131         do
1132         {
1133             numLongs += bytesAfter * 4;
1134             XGetWindowProperty(display, RootWindow(display, screen),
1135                                overlayVisualsAtom, 0, numLongs, False,
1136                                overlayVisualsAtom, &actualType, &actualFormat,
1137                                &numLongs, &bytesAfter, (unsigned char**) pOverlayVisuals);
1138         } while (bytesAfter > 0);
1139 
1140 
1141         /* Calculate the number of overlay visuals in the list. */
1142         /* *numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / 4); */
1143         *numOverlayVisuals = numLongs / (sizeof(OverlayVisualPropertyRec) / sizeof(long));
1144     }
1145     else
1146     {
1147         /* This screen doesn't have overlay planes. */
1148         *numOverlayVisuals = 0;
1149         *pOverlayVisuals = NULL;
1150         *transparentOverlays = 0;
1151     }
1152 
1153 
1154     /* Process the pVisuals array. */
1155     *numImageVisuals = 0;
1156     nImageVisualsAlloced = 1;
1157     pIVis = *pImageVisuals = (XVisualInfo **) malloc(sizeof(XVisualInfo *));
1158     while (--nVisuals >= 0)
1159     {
1160         nOVisuals = *numOverlayVisuals;
1161         pOVis = *pOverlayVisuals;
1162         imageVisual = True;
1163         while (--nOVisuals >= 0)
1164         {
1165             pOOldVis = (OverlayVisualPropertyRec *) pOVis;
1166             if (pVis->visualid == pOOldVis->visualID)
1167             {
1168                 imageVisual = False;
1169                 pOVis->pOverlayVisualInfo = pVis;
1170                 if (pOVis->transparentType == TransparentPixel)
1171                     *transparentOverlays = 1;
1172             }
1173             pOVis++;
1174         }
1175         if (imageVisual)
1176         {
1177             if ((*numImageVisuals += 1) > nImageVisualsAlloced)
1178             {
1179                 nImageVisualsAlloced++;
1180                 *pImageVisuals = (XVisualInfo **)
1181                     realloc(*pImageVisuals, (nImageVisualsAlloced * sizeof(XVisualInfo *)));
1182                 pIVis = *pImageVisuals + (*numImageVisuals - 1);
1183             }
1184             *pIVis++ = pVis;
1185         }
1186         pVis++;
1187     }
1188 
1189 
1190     /* Return that the information was sucessfully obtained: */
1191     return(0);
1192 
1193 } /* GetXVisualInfo() */
1194 
1195 
1196 /******************************************************************************
1197  *
1198  * FreeXVisualInfo()
1199  *
1200  * This routine frees the data that was allocated by GetXVisualInfo().
1201  *
1202  ******************************************************************************/
1203 
1204 void FreeXVisualInfo(pVisuals, pOverlayVisuals, pImageVisuals)
1205 
1206     XVisualInfo *pVisuals;
1207     OverlayInfo *pOverlayVisuals;
1208     XVisualInfo **pImageVisuals;
1209 {
1210     XFree(pVisuals);
1211     if (weCreateServerOverlayVisualsProperty)
1212         free(pOverlayVisuals);
1213     else
1214         XFree(pOverlayVisuals);
1215     free(pImageVisuals);
1216 
1217 } /* FreeXVisualInfo() */