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