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