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