~ubuntu-branches/ubuntu/gutsy/vnc4/gutsy

« back to all changes in this revision

Viewing changes to unix/xc/programs/xwd/multiVis.c

  • Committer: Bazaar Package Importer
  • Author(s): Ola Lundqvist
  • Date: 2006-05-15 20:35:17 UTC
  • mfrom: (1.1.2 upstream)
  • Revision ID: james.westby@ubuntu.com-20060515203517-l4lre1ku942mn26k
Tags: 4.1.1+X4.3.0-10
* Correction of critical security issue. Thanks to Martin Kogler
  <e9925248@student.tuwien.ac.at> that informed me about the issue,
  and provided the patch.
  This flaw was originally found by Steve Wiseman of intelliadmin.com.
* Applied patch from Javier Kohen <jkohen@users.sourceforge.net> that
  inform the user that only 8 first characters of the password will
  actually be used when typing more than 8 characters, closes:
  #355619.

Show diffs side-by-side

added added

removed removed

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