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

« back to all changes in this revision

Viewing changes to unix/xc/programs/Xserver/dix/colormap.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
/* $XFree86: xc/programs/Xserver/dix/colormap.c,v 3.10 2002/04/14 00:45:54 mvojkovi Exp $ */
 
2
/***********************************************************
 
3
 
 
4
Copyright 1987, 1998  The Open Group
 
5
 
 
6
Permission to use, copy, modify, distribute, and sell this software and its
 
7
documentation for any purpose is hereby granted without fee, provided that
 
8
the above copyright notice appear in all copies and that both that
 
9
copyright notice and this permission notice appear in supporting
 
10
documentation.
 
11
 
 
12
The above copyright notice and this permission notice shall be included in
 
13
all copies or substantial portions of the Software.
 
14
 
 
15
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 
18
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 
19
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 
20
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 
21
 
 
22
Except as contained in this notice, the name of The Open Group shall not be
 
23
used in advertising or otherwise to promote the sale, use or other dealings
 
24
in this Software without prior written authorization from The Open Group.
 
25
 
 
26
 
 
27
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 
28
 
 
29
                        All Rights Reserved
 
30
 
 
31
Permission to use, copy, modify, and distribute this software and its 
 
32
documentation for any purpose and without fee is hereby granted, 
 
33
provided that the above copyright notice appear in all copies and that
 
34
both that copyright notice and this permission notice appear in 
 
35
supporting documentation, and that the name of Digital not be
 
36
used in advertising or publicity pertaining to distribution of the
 
37
software without specific, written prior permission.  
 
38
 
 
39
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 
40
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 
41
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 
42
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 
43
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 
44
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 
45
SOFTWARE.
 
46
 
 
47
******************************************************************/
 
48
 
 
49
/* $Xorg: colormap.c,v 1.4 2001/02/09 02:04:39 xorgcvs Exp $ */
 
50
 
 
51
#include "X.h"
 
52
#define NEED_EVENTS
 
53
#include "Xproto.h"
 
54
#include "misc.h"
 
55
#include "dix.h"
 
56
#include "colormapst.h"
 
57
#include "os.h"
 
58
#include "scrnintstr.h"
 
59
#include "resource.h"
 
60
#include "windowstr.h"
 
61
#ifdef LBX
 
62
#include "lbxserve.h"
 
63
#endif
 
64
 
 
65
extern XID clientErrorValue;
 
66
extern int colormapPrivateCount;
 
67
 
 
68
static Pixel FindBestPixel(
 
69
#if NeedFunctionPrototypes
 
70
    EntryPtr /*pentFirst*/,
 
71
    int /*size*/,
 
72
    xrgb * /*prgb*/,
 
73
    int /*channel*/
 
74
#endif
 
75
);
 
76
 
 
77
static int AllComp(
 
78
#if NeedFunctionPrototypes
 
79
    EntryPtr /*pent*/,
 
80
    xrgb * /*prgb*/
 
81
#endif
 
82
);
 
83
 
 
84
static int RedComp(
 
85
#if NeedFunctionPrototypes
 
86
    EntryPtr /*pent*/,
 
87
    xrgb * /*prgb*/
 
88
#endif
 
89
);
 
90
 
 
91
static int GreenComp(
 
92
#if NeedFunctionPrototypes
 
93
    EntryPtr /*pent*/,
 
94
    xrgb * /*prgb*/
 
95
#endif
 
96
);
 
97
 
 
98
static int BlueComp(
 
99
#if NeedFunctionPrototypes
 
100
    EntryPtr /*pent*/,
 
101
    xrgb * /*prgb*/
 
102
#endif
 
103
);
 
104
 
 
105
static void FreePixels(
 
106
#if NeedFunctionPrototypes
 
107
    register ColormapPtr /*pmap*/,
 
108
    register int /*client*/
 
109
#endif
 
110
);
 
111
 
 
112
static void CopyFree(
 
113
#if NeedFunctionPrototypes
 
114
    int /*channel*/,
 
115
    int /*client*/,
 
116
    ColormapPtr /*pmapSrc*/,
 
117
    ColormapPtr /*pmapDst*/
 
118
#endif
 
119
);
 
120
 
 
121
static void FreeCell(
 
122
#if NeedFunctionPrototypes
 
123
    ColormapPtr /*pmap*/,
 
124
    Pixel /*i*/,
 
125
    int /*channel*/
 
126
#endif
 
127
);
 
128
 
 
129
static void UpdateColors(
 
130
#if NeedFunctionPrototypes
 
131
    ColormapPtr /*pmap*/
 
132
#endif
 
133
);
 
134
 
 
135
static int AllocDirect(
 
136
#if NeedFunctionPrototypes
 
137
    int /*client*/,
 
138
    ColormapPtr /*pmap*/,
 
139
    int /*c*/,
 
140
    int /*r*/,
 
141
    int /*g*/,
 
142
    int /*b*/,
 
143
    Bool /*contig*/,
 
144
    Pixel * /*pixels*/,
 
145
    Pixel * /*prmask*/,
 
146
    Pixel * /*pgmask*/,
 
147
    Pixel * /*pbmask*/
 
148
#endif
 
149
);
 
150
 
 
151
static int AllocPseudo(
 
152
#if NeedFunctionPrototypes
 
153
    int /*client*/,
 
154
    ColormapPtr /*pmap*/,
 
155
    int /*c*/,
 
156
    int /*r*/,
 
157
    Bool /*contig*/,
 
158
    Pixel * /*pixels*/,
 
159
    Pixel * /*pmask*/,
 
160
    Pixel ** /*pppixFirst*/
 
161
#endif
 
162
);
 
163
 
 
164
static Bool AllocCP(
 
165
#if NeedFunctionPrototypes
 
166
    ColormapPtr /*pmap*/,
 
167
    EntryPtr /*pentFirst*/,
 
168
    int /*count*/,
 
169
    int /*planes*/,
 
170
    Bool /*contig*/,
 
171
    Pixel * /*pixels*/,
 
172
    Pixel * /*pMask*/
 
173
#endif
 
174
);
 
175
 
 
176
static Bool AllocShared(
 
177
#if NeedFunctionPrototypes
 
178
    ColormapPtr /*pmap*/,
 
179
    Pixel * /*ppix*/,
 
180
    int /*c*/,
 
181
    int /*r*/,
 
182
    int /*g*/,
 
183
    int /*b*/,
 
184
    Pixel /*rmask*/,
 
185
    Pixel /*gmask*/,
 
186
    Pixel /*bmask*/,
 
187
    Pixel * /*ppixFirst*/
 
188
#endif
 
189
);
 
190
 
 
191
static int FreeCo(
 
192
#if NeedFunctionPrototypes
 
193
    ColormapPtr /*pmap*/,
 
194
    int /*client*/,
 
195
    int /*color*/,
 
196
    int /*npixIn*/,
 
197
    Pixel * /*ppixIn*/,
 
198
    Pixel /*mask*/
 
199
#endif
 
200
);
 
201
 
 
202
static int   TellNoMap(
 
203
#if NeedFunctionPrototypes
 
204
    WindowPtr   /*pwin*/,
 
205
    Colormap    * /*pmid*/
 
206
#endif
 
207
);
 
208
 
 
209
static void FindColorInRootCmap (
 
210
#if NeedFunctionPrototypes
 
211
    ColormapPtr /* pmap */,
 
212
    EntryPtr    /* pentFirst */,
 
213
    int         /* size */,
 
214
    xrgb*       /* prgb */,
 
215
    Pixel*      /* pPixel */,
 
216
    int         /* channel */,
 
217
    ColorCompareProcPtr /* comp */
 
218
#endif
 
219
);
 
220
 
 
221
#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
 
222
#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
 
223
#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1)
 
224
#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask)
 
225
 
 
226
/* GetNextBitsOrBreak(bits, mask, base)  -- 
 
227
 * (Suggestion: First read the macro, then read this explanation.
 
228
 *
 
229
 * Either generate the next value to OR in to a pixel or break out of this
 
230
 * while loop 
 
231
 *
 
232
 * This macro is used when we're trying to generate all 2^n combinations of
 
233
 * bits in mask.  What we're doing here is counting in binary, except that
 
234
 * the bits we use to count may not be contiguous.  This macro will be
 
235
 * called 2^n times, returning a different value in bits each time. Then
 
236
 * it will cause us to break out of a surrounding loop. (It will always be
 
237
 * called from within a while loop.)
 
238
 * On call: mask is the value we want to find all the combinations for
 
239
 * base has 1 bit set where the least significant bit of mask is set
 
240
 *
 
241
 * For example,if mask is 01010, base should be 0010 and we count like this:
 
242
 * 00010 (see this isn't so hard), 
 
243
 *     then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so
 
244
 *      we add that to bits getting (0100 + 0100) =
 
245
 * 01000 for our next value.
 
246
 *      then we add 0010 to get 
 
247
 * 01010 and we're done (easy as 1, 2, 3)
 
248
 */
 
249
#define GetNextBitsOrBreak(bits, mask, base)    \
 
250
            if((bits) == (mask))                \
 
251
                break;                          \
 
252
            (bits) += (base);                   \
 
253
            while((bits) & ~(mask))             \
 
254
                (bits) += ((bits) & ~(mask));   
 
255
/* ID of server as client */
 
256
#define SERVER_ID       0
 
257
 
 
258
typedef struct _colorResource
 
259
{
 
260
        Colormap        mid;
 
261
        int             client;
 
262
} colorResource;
 
263
 
 
264
/* Invariants:
 
265
 * refcnt == 0 means entry is empty
 
266
 * refcnt > 0 means entry is useable by many clients, so it can't be changed
 
267
 * refcnt == AllocPrivate means entry owned by one client only
 
268
 * fShared should only be set if refcnt == AllocPrivate, and only in red map
 
269
 */
 
270
 
 
271
 
 
272
/* Create and initialize the color map */
 
273
int 
 
274
CreateColormap (mid, pScreen, pVisual, ppcmap, alloc, client)
 
275
    Colormap    mid;            /* resource to use for this colormap */
 
276
    ScreenPtr   pScreen;
 
277
    VisualPtr   pVisual;
 
278
    ColormapPtr *ppcmap;        
 
279
    int         alloc;          /* 1 iff all entries are allocated writeable */
 
280
    int         client;
 
281
{
 
282
    int         class, size;
 
283
    unsigned long sizebytes;
 
284
    ColormapPtr pmap;
 
285
    register    EntryPtr        pent;
 
286
    int         i;
 
287
    register    Pixel   *ppix, **pptr;
 
288
 
 
289
    class = pVisual->class;
 
290
    if(!(class & DynamicClass) && (alloc != AllocNone) && (client != SERVER_ID))
 
291
        return (BadMatch);
 
292
 
 
293
    size = pVisual->ColormapEntries;
 
294
    sizebytes = (size * sizeof(Entry)) +
 
295
                (MAXCLIENTS * sizeof(Pixel *)) +
 
296
                (MAXCLIENTS * sizeof(int));
 
297
    if ((class | DynamicClass) == DirectColor)
 
298
        sizebytes *= 3;
 
299
    sizebytes += sizeof(ColormapRec);
 
300
    pmap = (ColormapPtr) xalloc(sizebytes);
 
301
    if (!pmap)
 
302
        return (BadAlloc);
 
303
    pmap->red = (EntryPtr)((char *)pmap + sizeof(ColormapRec));    
 
304
    sizebytes = size * sizeof(Entry);
 
305
    pmap->clientPixelsRed = (Pixel **)((char *)pmap->red + sizebytes);
 
306
    pmap->numPixelsRed = (int *)((char *)pmap->clientPixelsRed +
 
307
                                 (MAXCLIENTS * sizeof(Pixel *)));
 
308
    pmap->mid = mid;
 
309
    pmap->flags = 0;    /* start out with all flags clear */
 
310
    if(mid == pScreen->defColormap)
 
311
        pmap->flags |= IsDefault;
 
312
    pmap->pScreen = pScreen;
 
313
    pmap->pVisual = pVisual;
 
314
    pmap->class = class;
 
315
    if ((class | DynamicClass) == DirectColor)
 
316
        size = NUMRED(pVisual);
 
317
    pmap->freeRed = size;
 
318
    bzero ((char *) pmap->red, (int)sizebytes);
 
319
    bzero((char *) pmap->numPixelsRed, MAXCLIENTS * sizeof(int));
 
320
    for (pptr = &pmap->clientPixelsRed[MAXCLIENTS]; --pptr >= pmap->clientPixelsRed; )
 
321
        *pptr = (Pixel *)NULL;
 
322
    if (alloc == AllocAll)
 
323
    {
 
324
        if (class & DynamicClass)
 
325
            pmap->flags |= AllAllocated;
 
326
        for (pent = &pmap->red[size - 1]; pent >= pmap->red; pent--)
 
327
            pent->refcnt = AllocPrivate;
 
328
        pmap->freeRed = 0;
 
329
        ppix = (Pixel *)xalloc(size * sizeof(Pixel));
 
330
        if (!ppix)
 
331
        {
 
332
            xfree(pmap);
 
333
            return (BadAlloc);
 
334
        }
 
335
        pmap->clientPixelsRed[client] = ppix;
 
336
        for(i = 0; i < size; i++)
 
337
            ppix[i] = i;
 
338
        pmap->numPixelsRed[client] = size;
 
339
    }
 
340
 
 
341
    if ((class | DynamicClass) == DirectColor)
 
342
    {
 
343
        pmap->freeGreen = NUMGREEN(pVisual);
 
344
        pmap->green = (EntryPtr)((char *)pmap->numPixelsRed +
 
345
                                 (MAXCLIENTS * sizeof(int)));
 
346
        pmap->clientPixelsGreen = (Pixel **)((char *)pmap->green + sizebytes);
 
347
        pmap->numPixelsGreen = (int *)((char *)pmap->clientPixelsGreen +
 
348
                                       (MAXCLIENTS * sizeof(Pixel *)));
 
349
        pmap->freeBlue = NUMBLUE(pVisual);
 
350
        pmap->blue = (EntryPtr)((char *)pmap->numPixelsGreen +
 
351
                                (MAXCLIENTS * sizeof(int)));
 
352
        pmap->clientPixelsBlue = (Pixel **)((char *)pmap->blue + sizebytes);
 
353
        pmap->numPixelsBlue = (int *)((char *)pmap->clientPixelsBlue +
 
354
                                      (MAXCLIENTS * sizeof(Pixel *)));
 
355
 
 
356
        bzero ((char *) pmap->green, (int)sizebytes);
 
357
        bzero ((char *) pmap->blue, (int)sizebytes);
 
358
 
 
359
        memmove((char *) pmap->clientPixelsGreen,
 
360
                (char *) pmap->clientPixelsRed,
 
361
              MAXCLIENTS * sizeof(Pixel *));
 
362
        memmove((char *) pmap->clientPixelsBlue,
 
363
                (char *) pmap->clientPixelsRed,
 
364
              MAXCLIENTS * sizeof(Pixel *));
 
365
        bzero((char *) pmap->numPixelsGreen, MAXCLIENTS * sizeof(int));
 
366
        bzero((char *) pmap->numPixelsBlue, MAXCLIENTS * sizeof(int));
 
367
 
 
368
        /* If every cell is allocated, mark its refcnt */
 
369
        if (alloc == AllocAll)
 
370
        {
 
371
            size = pmap->freeGreen;
 
372
            for(pent = &pmap->green[size-1]; pent >= pmap->green; pent--)
 
373
                pent->refcnt = AllocPrivate;
 
374
            pmap->freeGreen = 0;
 
375
            ppix = (Pixel *) xalloc(size * sizeof(Pixel));
 
376
            if (!ppix)
 
377
            {
 
378
                xfree(pmap->clientPixelsRed[client]);
 
379
                xfree(pmap);
 
380
                return(BadAlloc);
 
381
            }
 
382
            pmap->clientPixelsGreen[client] = ppix;
 
383
            for(i = 0; i < size; i++)
 
384
                ppix[i] = i;
 
385
            pmap->numPixelsGreen[client] = size;
 
386
 
 
387
            size = pmap->freeBlue;
 
388
            for(pent = &pmap->blue[size-1]; pent >= pmap->blue; pent--)
 
389
                pent->refcnt = AllocPrivate;
 
390
            pmap->freeBlue = 0;
 
391
            ppix = (Pixel *) xalloc(size * sizeof(Pixel));
 
392
            if (!ppix)
 
393
            {
 
394
                xfree(pmap->clientPixelsGreen[client]);
 
395
                xfree(pmap->clientPixelsRed[client]);
 
396
                xfree(pmap);
 
397
                return(BadAlloc);
 
398
            }
 
399
            pmap->clientPixelsBlue[client] = ppix;
 
400
            for(i = 0; i < size; i++)
 
401
                ppix[i] = i;
 
402
            pmap->numPixelsBlue[client] = size;
 
403
        }
 
404
    }
 
405
    if (!AddResource(mid, RT_COLORMAP, (pointer)pmap))
 
406
        return (BadAlloc);
 
407
    /* If the device wants a chance to initialize the colormap in any way,
 
408
     * this is it.  In specific, if this is a Static colormap, this is the
 
409
     * time to fill in the colormap's values */
 
410
    pmap->flags |= BeingCreated;
 
411
 
 
412
 
 
413
    /*
 
414
     * Allocate the array of devPrivate's for this colormap.
 
415
     */
 
416
 
 
417
    if (colormapPrivateCount == 0)
 
418
        pmap->devPrivates = NULL;
 
419
    else
 
420
    {
 
421
        pmap->devPrivates = (DevUnion *) xalloc (
 
422
            colormapPrivateCount * sizeof(DevUnion));
 
423
 
 
424
        if (!pmap->devPrivates)
 
425
        {
 
426
            FreeResource (mid, RT_NONE);
 
427
            return BadAlloc;
 
428
        }
 
429
    }
 
430
 
 
431
    if (!(*pScreen->CreateColormap)(pmap))
 
432
    {
 
433
        FreeResource (mid, RT_NONE);
 
434
        return BadAlloc;
 
435
    }
 
436
    pmap->flags &= ~BeingCreated;
 
437
    *ppcmap = pmap;
 
438
    return (Success);
 
439
}
 
440
 
 
441
int
 
442
FreeColormap (value, mid)
 
443
    pointer     value; /* must conform to DeleteType */
 
444
    XID         mid;
 
445
{
 
446
    int         i;
 
447
    register EntryPtr pent;
 
448
    ColormapPtr pmap = (ColormapPtr)value;
 
449
 
 
450
    if(CLIENT_ID(mid) != SERVER_ID)
 
451
    {
 
452
        (*pmap->pScreen->UninstallColormap) (pmap);
 
453
        WalkTree(pmap->pScreen, (VisitWindowProcPtr)TellNoMap, (pointer) &mid);
 
454
    }
 
455
 
 
456
    /* This is the device's chance to undo anything it needs to, especially
 
457
     * to free any storage it allocated */
 
458
    (*pmap->pScreen->DestroyColormap)(pmap);
 
459
 
 
460
    if(pmap->clientPixelsRed)
 
461
    {
 
462
        for(i = 0; i < MAXCLIENTS; i++)
 
463
            xfree(pmap->clientPixelsRed[i]);
 
464
    }
 
465
 
 
466
    if ((pmap->class == PseudoColor) || (pmap->class == GrayScale))
 
467
    {
 
468
        for(pent = &pmap->red[pmap->pVisual->ColormapEntries - 1];
 
469
            pent >= pmap->red;
 
470
            pent--)
 
471
        {
 
472
            if(pent->fShared)
 
473
            {
 
474
                if (--pent->co.shco.red->refcnt == 0)
 
475
                    xfree(pent->co.shco.red);
 
476
                if (--pent->co.shco.green->refcnt == 0)
 
477
                    xfree(pent->co.shco.green);
 
478
                if (--pent->co.shco.blue->refcnt == 0)
 
479
                    xfree(pent->co.shco.blue);
 
480
            }
 
481
        }
 
482
    }
 
483
    if((pmap->class | DynamicClass) == DirectColor)
 
484
    {
 
485
        for(i = 0; i < MAXCLIENTS; i++)
 
486
        {
 
487
            xfree(pmap->clientPixelsGreen[i]);
 
488
            xfree(pmap->clientPixelsBlue[i]);
 
489
        }
 
490
    }
 
491
 
 
492
    if (pmap->devPrivates)
 
493
        xfree(pmap->devPrivates);
 
494
 
 
495
    xfree(pmap);
 
496
    return(Success);
 
497
}
 
498
 
 
499
/* Tell window that pmid has disappeared */
 
500
static int
 
501
TellNoMap (pwin, pmid)
 
502
    WindowPtr   pwin;
 
503
    Colormap    *pmid;
 
504
{
 
505
    xEvent      xE;
 
506
 
 
507
    if (wColormap(pwin) == *pmid)
 
508
    {
 
509
        /* This should be call to DeliverEvent */
 
510
        xE.u.u.type = ColormapNotify;
 
511
        xE.u.colormap.window = pwin->drawable.id;
 
512
        xE.u.colormap.colormap = None;
 
513
        xE.u.colormap.new = TRUE;
 
514
        xE.u.colormap.state = ColormapUninstalled;
 
515
#ifdef PANORAMIX
 
516
        if(noPanoramiXExtension || !pwin->drawable.pScreen->myNum)
 
517
#endif
 
518
           DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
 
519
        if (pwin->optional) {
 
520
            pwin->optional->colormap = None;
 
521
            CheckWindowOptionalNeed (pwin);
 
522
        }
 
523
    }
 
524
 
 
525
    return (WT_WALKCHILDREN);
 
526
}
 
527
 
 
528
/* Tell window that pmid got uninstalled */
 
529
int
 
530
TellLostMap (pwin, value)
 
531
    WindowPtr   pwin;
 
532
    pointer     value;
 
533
{
 
534
    Colormap    *pmid = (Colormap *)value;
 
535
    xEvent      xE;
 
536
 
 
537
#ifdef PANORAMIX
 
538
    if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum)
 
539
        return WT_STOPWALKING;
 
540
#endif
 
541
    if (wColormap(pwin) == *pmid)
 
542
    {
 
543
        /* This should be call to DeliverEvent */
 
544
        xE.u.u.type = ColormapNotify;
 
545
        xE.u.colormap.window = pwin->drawable.id;
 
546
        xE.u.colormap.colormap = *pmid;
 
547
        xE.u.colormap.new = FALSE;
 
548
        xE.u.colormap.state = ColormapUninstalled;
 
549
        DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
 
550
    }
 
551
 
 
552
    return (WT_WALKCHILDREN);
 
553
}
 
554
 
 
555
/* Tell window that pmid got installed */
 
556
int
 
557
TellGainedMap (pwin, value)
 
558
    WindowPtr   pwin;
 
559
    pointer     value;
 
560
{
 
561
    Colormap    *pmid = (Colormap *)value;
 
562
    xEvent      xE;
 
563
 
 
564
#ifdef PANORAMIX
 
565
    if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum)
 
566
        return WT_STOPWALKING;
 
567
#endif
 
568
    if (wColormap (pwin) == *pmid)
 
569
    {
 
570
        /* This should be call to DeliverEvent */
 
571
        xE.u.u.type = ColormapNotify;
 
572
        xE.u.colormap.window = pwin->drawable.id;
 
573
        xE.u.colormap.colormap = *pmid;
 
574
        xE.u.colormap.new = FALSE;
 
575
        xE.u.colormap.state = ColormapInstalled;
 
576
        DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
 
577
    }
 
578
 
 
579
    return (WT_WALKCHILDREN);
 
580
}
 
581
 
 
582
  
 
583
int
 
584
CopyColormapAndFree (mid, pSrc, client)
 
585
    Colormap    mid;
 
586
    ColormapPtr pSrc;
 
587
    int         client;
 
588
{
 
589
    ColormapPtr pmap = (ColormapPtr) NULL;
 
590
    int         result, alloc, size;
 
591
    Colormap    midSrc;
 
592
    ScreenPtr   pScreen;
 
593
    VisualPtr   pVisual;
 
594
 
 
595
    pScreen = pSrc->pScreen;
 
596
    pVisual = pSrc->pVisual;
 
597
    midSrc = pSrc->mid;
 
598
    alloc = ((pSrc->flags & AllAllocated) && CLIENT_ID(midSrc) == client) ?
 
599
            AllocAll : AllocNone;
 
600
    size = pVisual->ColormapEntries;
 
601
 
 
602
    /* If the create returns non-0, it failed */
 
603
    result = CreateColormap (mid, pScreen, pVisual, &pmap, alloc, client);
 
604
    if(result != Success)
 
605
        return(result);
 
606
    if(alloc == AllocAll)
 
607
    {
 
608
        memmove((char *)pmap->red, (char *)pSrc->red, size * sizeof(Entry));
 
609
        if((pmap->class | DynamicClass) == DirectColor)
 
610
        {
 
611
            memmove((char *)pmap->green, (char *)pSrc->green, size * sizeof(Entry));
 
612
            memmove((char *)pmap->blue, (char *)pSrc->blue, size * sizeof(Entry));
 
613
        }
 
614
        pSrc->flags &= ~AllAllocated;
 
615
        FreePixels(pSrc, client);
 
616
        UpdateColors(pmap);
 
617
        return(Success);
 
618
    }
 
619
 
 
620
    CopyFree(REDMAP, client, pSrc, pmap);
 
621
    if ((pmap->class | DynamicClass) == DirectColor)
 
622
    {
 
623
        CopyFree(GREENMAP, client, pSrc, pmap);
 
624
        CopyFree(BLUEMAP, client, pSrc, pmap);
 
625
    }
 
626
    if (pmap->class & DynamicClass)
 
627
        UpdateColors(pmap);
 
628
    /* XXX should worry about removing any RT_CMAPENTRY resource */
 
629
    return(Success);
 
630
}
 
631
 
 
632
/* Helper routine for freeing large numbers of cells from a map */
 
633
static void
 
634
CopyFree (channel, client, pmapSrc, pmapDst)
 
635
    int         channel, client;
 
636
    ColormapPtr pmapSrc, pmapDst;
 
637
{
 
638
    int         z, npix, oldFree;
 
639
    EntryPtr    pentSrcFirst, pentDstFirst;
 
640
    EntryPtr    pentSrc, pentDst;
 
641
    Pixel       *ppix;
 
642
    int         nalloc;
 
643
 
 
644
    switch(channel)
 
645
    {
 
646
      default:  /* so compiler can see that everything gets initialized */
 
647
      case REDMAP:
 
648
        ppix = (pmapSrc->clientPixelsRed)[client];
 
649
        npix = (pmapSrc->numPixelsRed)[client];
 
650
        pentSrcFirst = pmapSrc->red;
 
651
        pentDstFirst = pmapDst->red;
 
652
        oldFree = pmapSrc->freeRed;
 
653
        break;
 
654
      case GREENMAP:
 
655
        ppix = (pmapSrc->clientPixelsGreen)[client];
 
656
        npix = (pmapSrc->numPixelsGreen)[client];
 
657
        pentSrcFirst = pmapSrc->green;
 
658
        pentDstFirst = pmapDst->green;
 
659
        oldFree = pmapSrc->freeGreen;
 
660
        break;
 
661
      case BLUEMAP:
 
662
        ppix = (pmapSrc->clientPixelsBlue)[client];
 
663
        npix = (pmapSrc->numPixelsBlue)[client];
 
664
        pentSrcFirst = pmapSrc->blue;
 
665
        pentDstFirst = pmapDst->blue;
 
666
        oldFree = pmapSrc->freeBlue;
 
667
        break;
 
668
    }
 
669
    nalloc = 0;
 
670
    if (pmapSrc->class & DynamicClass)
 
671
    {
 
672
        for(z = npix; --z >= 0; ppix++)
 
673
        {
 
674
            /* Copy entries */
 
675
            pentSrc = pentSrcFirst + *ppix;
 
676
            pentDst = pentDstFirst + *ppix;
 
677
            if (pentDst->refcnt > 0)
 
678
            {
 
679
                pentDst->refcnt++;
 
680
            }
 
681
            else
 
682
            {
 
683
                *pentDst = *pentSrc;
 
684
                nalloc++;
 
685
                if (pentSrc->refcnt > 0)
 
686
                    pentDst->refcnt = 1;
 
687
                else
 
688
                    pentSrc->fShared = FALSE;
 
689
            }
 
690
            FreeCell(pmapSrc, *ppix, channel);
 
691
        }
 
692
    }
 
693
 
 
694
    /* Note that FreeCell has already fixed pmapSrc->free{Color} */
 
695
    switch(channel)
 
696
    {
 
697
      case REDMAP:
 
698
        pmapDst->freeRed -= nalloc;
 
699
        (pmapDst->clientPixelsRed)[client] =
 
700
            (pmapSrc->clientPixelsRed)[client];
 
701
        (pmapSrc->clientPixelsRed)[client] = (Pixel *) NULL;
 
702
        (pmapDst->numPixelsRed)[client] = (pmapSrc->numPixelsRed)[client];
 
703
        (pmapSrc->numPixelsRed)[client] = 0;
 
704
        break;
 
705
      case GREENMAP:
 
706
        pmapDst->freeGreen -= nalloc;
 
707
        (pmapDst->clientPixelsGreen)[client] =
 
708
            (pmapSrc->clientPixelsGreen)[client];
 
709
        (pmapSrc->clientPixelsGreen)[client] = (Pixel *) NULL;
 
710
        (pmapDst->numPixelsGreen)[client] = (pmapSrc->numPixelsGreen)[client];
 
711
        (pmapSrc->numPixelsGreen)[client] = 0;
 
712
        break;
 
713
      case BLUEMAP:
 
714
        pmapDst->freeBlue -= nalloc;
 
715
        pmapDst->clientPixelsBlue[client] = pmapSrc->clientPixelsBlue[client];
 
716
        pmapSrc->clientPixelsBlue[client] = (Pixel *) NULL;
 
717
        pmapDst->numPixelsBlue[client] = pmapSrc->numPixelsBlue[client];
 
718
        pmapSrc->numPixelsBlue[client] = 0;
 
719
        break;
 
720
    }
 
721
}
 
722
 
 
723
/* Free the ith entry in a color map.  Must handle freeing of
 
724
 * colors allocated through AllocColorPlanes */
 
725
static void
 
726
FreeCell (pmap, i, channel)
 
727
    ColormapPtr pmap;
 
728
    Pixel i;
 
729
    int channel;
 
730
{
 
731
    EntryPtr pent;
 
732
    int *pCount;
 
733
 
 
734
 
 
735
    switch (channel)
 
736
    {
 
737
      default:  /* so compiler can see that everything gets initialized */
 
738
      case PSEUDOMAP:
 
739
      case REDMAP:
 
740
          pent = (EntryPtr) &pmap->red[i];
 
741
          pCount = &pmap->freeRed;
 
742
          break;
 
743
      case GREENMAP:
 
744
          pent = (EntryPtr) &pmap->green[i];
 
745
          pCount = &pmap->freeGreen;
 
746
          break;
 
747
      case BLUEMAP:
 
748
          pent = (EntryPtr) &pmap->blue[i];
 
749
          pCount = &pmap->freeBlue;
 
750
          break;
 
751
    }
 
752
    /* If it's not privately allocated and it's not time to free it, just
 
753
     * decrement the count */
 
754
    if (pent->refcnt > 1)
 
755
        pent->refcnt--;
 
756
    else
 
757
    {
 
758
        /* If the color type is shared, find the sharedcolor. If decremented
 
759
         * refcnt is 0, free the shared cell. */
 
760
        if (pent->fShared)
 
761
        {
 
762
            if(--pent->co.shco.red->refcnt == 0)
 
763
                xfree(pent->co.shco.red);
 
764
            if(--pent->co.shco.green->refcnt == 0)
 
765
                xfree(pent->co.shco.green);
 
766
            if(--pent->co.shco.blue->refcnt == 0)
 
767
                xfree(pent->co.shco.blue);
 
768
            pent->fShared = FALSE;
 
769
        }
 
770
        pent->refcnt = 0;
 
771
        *pCount += 1;
 
772
    }
 
773
}
 
774
 
 
775
static void
 
776
UpdateColors (pmap)
 
777
    ColormapPtr pmap;
 
778
{
 
779
    xColorItem          *defs;
 
780
    register xColorItem *pdef;
 
781
    register EntryPtr   pent;
 
782
    register VisualPtr  pVisual;
 
783
    int                 i, n, size;
 
784
 
 
785
    pVisual = pmap->pVisual;
 
786
    size = pVisual->ColormapEntries;
 
787
    defs = (xColorItem *)ALLOCATE_LOCAL(size * sizeof(xColorItem));
 
788
    if (!defs)
 
789
        return;
 
790
    n = 0;
 
791
    pdef = defs;
 
792
    if (pmap->class == DirectColor)
 
793
    {
 
794
        for (i = 0; i < size; i++)
 
795
        {
 
796
            if (!pmap->red[i].refcnt &&
 
797
                !pmap->green[i].refcnt &&
 
798
                !pmap->blue[i].refcnt)
 
799
                continue;
 
800
            pdef->pixel = ((Pixel)i << pVisual->offsetRed) |
 
801
                          ((Pixel)i << pVisual->offsetGreen) |
 
802
                          ((Pixel)i << pVisual->offsetBlue);
 
803
            pdef->red = pmap->red[i].co.local.red;
 
804
            pdef->green = pmap->green[i].co.local.green;
 
805
            pdef->blue = pmap->blue[i].co.local.blue;
 
806
            pdef->flags = DoRed|DoGreen|DoBlue;
 
807
            pdef++;
 
808
            n++;
 
809
        }
 
810
    }
 
811
    else
 
812
    {
 
813
        for (i = 0, pent = pmap->red; i < size; i++, pent++)
 
814
        {
 
815
            if (!pent->refcnt)
 
816
                continue;
 
817
            pdef->pixel = i;
 
818
            if(pent->fShared)
 
819
            {
 
820
                pdef->red = pent->co.shco.red->color;
 
821
                pdef->green = pent->co.shco.green->color;
 
822
                pdef->blue = pent->co.shco.blue->color;
 
823
            }
 
824
            else
 
825
            {
 
826
                pdef->red = pent->co.local.red;
 
827
                pdef->green = pent->co.local.green;
 
828
                pdef->blue = pent->co.local.blue;
 
829
            }
 
830
            pdef->flags = DoRed|DoGreen|DoBlue;
 
831
            pdef++;
 
832
            n++;
 
833
        }
 
834
    }
 
835
    if (n)
 
836
        (*pmap->pScreen->StoreColors)(pmap, n, defs);
 
837
    DEALLOCATE_LOCAL(defs);
 
838
}
 
839
 
 
840
/* Get a read-only color from a ColorMap (probably slow for large maps)
 
841
 * Returns by changing the value in pred, pgreen, pblue and pPix
 
842
 */
 
843
int
 
844
AllocColor (pmap, pred, pgreen, pblue, pPix, client)
 
845
    ColormapPtr         pmap;
 
846
    unsigned short      *pred, *pgreen, *pblue;
 
847
    Pixel               *pPix;
 
848
    int                 client;
 
849
{
 
850
    Pixel       pixR, pixG, pixB;
 
851
    int         entries;
 
852
    xrgb        rgb;
 
853
    int         class;
 
854
    VisualPtr   pVisual;
 
855
    int         npix;
 
856
    Pixel       *ppix;
 
857
 
 
858
    pVisual = pmap->pVisual;
 
859
    (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual);
 
860
    rgb.red = *pred;
 
861
    rgb.green = *pgreen;
 
862
    rgb.blue = *pblue;
 
863
    class = pmap->class;
 
864
    entries = pVisual->ColormapEntries;
 
865
 
 
866
    /* If the colormap is being created, then we want to be able to change
 
867
     * the colormap, even if it's a static type. Otherwise, we'd never be
 
868
     * able to initialize static colormaps
 
869
     */
 
870
    if(pmap->flags & BeingCreated)
 
871
        class |= DynamicClass;
 
872
 
 
873
    /* If this is one of the static storage classes, and we're not initializing
 
874
     * it, the best we can do is to find the closest color entry to the
 
875
     * requested one and return that.
 
876
     */
 
877
    switch (class) {
 
878
    case StaticColor:
 
879
    case StaticGray:
 
880
        /* Look up all three components in the same pmap */
 
881
        *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
 
882
        *pred = pmap->red[pixR].co.local.red;
 
883
        *pgreen = pmap->red[pixR].co.local.green;
 
884
        *pblue = pmap->red[pixR].co.local.blue;
 
885
        npix = pmap->numPixelsRed[client];
 
886
        ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client],
 
887
                                  (npix + 1) * sizeof(Pixel));
 
888
        if (!ppix)
 
889
            return (BadAlloc);
 
890
        ppix[npix] = pixR;
 
891
        pmap->clientPixelsRed[client] = ppix;
 
892
        pmap->numPixelsRed[client]++;
 
893
        break;
 
894
 
 
895
    case TrueColor:
 
896
        /* Look up each component in its own map, then OR them together */
 
897
        pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
 
898
        pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
 
899
        pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
 
900
        *pPix = (pixR << pVisual->offsetRed) |
 
901
                (pixG << pVisual->offsetGreen) |
 
902
                (pixB << pVisual->offsetBlue);
 
903
        *pred = pmap->red[pixR].co.local.red;
 
904
        *pgreen = pmap->green[pixG].co.local.green;
 
905
        *pblue = pmap->blue[pixB].co.local.blue;
 
906
        npix = pmap->numPixelsRed[client];
 
907
        ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client],
 
908
                                  (npix + 1) * sizeof(Pixel));
 
909
        if (!ppix)
 
910
            return (BadAlloc);
 
911
        ppix[npix] = pixR;
 
912
        pmap->clientPixelsRed[client] = ppix;
 
913
        npix = pmap->numPixelsGreen[client];
 
914
        ppix = (Pixel *) xrealloc(pmap->clientPixelsGreen[client],
 
915
                                  (npix + 1) * sizeof(Pixel));
 
916
        if (!ppix)
 
917
            return (BadAlloc);
 
918
        ppix[npix] = pixG;
 
919
        pmap->clientPixelsGreen[client] = ppix;
 
920
        npix = pmap->numPixelsBlue[client];
 
921
        ppix = (Pixel *) xrealloc(pmap->clientPixelsBlue[client],
 
922
                                  (npix + 1) * sizeof(Pixel));
 
923
        if (!ppix)
 
924
            return (BadAlloc);
 
925
        ppix[npix] = pixB;
 
926
        pmap->clientPixelsBlue[client] = ppix;
 
927
        pmap->numPixelsRed[client]++;
 
928
        pmap->numPixelsGreen[client]++;
 
929
        pmap->numPixelsBlue[client]++;
 
930
        break;
 
931
 
 
932
    case GrayScale:
 
933
    case PseudoColor:
 
934
        if (pmap->mid != pmap->pScreen->defColormap &&
 
935
            pmap->pVisual->vid == pmap->pScreen->rootVisual)
 
936
        {
 
937
            ColormapPtr prootmap = (ColormapPtr)
 
938
                SecurityLookupIDByType (clients[client], pmap->pScreen->defColormap,
 
939
                                         RT_COLORMAP, SecurityReadAccess);
 
940
 
 
941
            if (pmap->class == prootmap->class)
 
942
                FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb, 
 
943
                        pPix, PSEUDOMAP, AllComp);
 
944
        }
 
945
        if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP,
 
946
                      client, AllComp) != Success)
 
947
            return (BadAlloc);
 
948
        break;
 
949
 
 
950
    case DirectColor:
 
951
        if (pmap->mid != pmap->pScreen->defColormap &&
 
952
            pmap->pVisual->vid == pmap->pScreen->rootVisual)
 
953
        {
 
954
            ColormapPtr prootmap = (ColormapPtr)
 
955
                SecurityLookupIDByType (clients[client], pmap->pScreen->defColormap,
 
956
                                         RT_COLORMAP, SecurityReadAccess);
 
957
 
 
958
            if (pmap->class == prootmap->class)
 
959
            {
 
960
                pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; 
 
961
                FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb, 
 
962
                        &pixR, REDMAP, RedComp);
 
963
                pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; 
 
964
                FindColorInRootCmap (prootmap, prootmap->green, entries, &rgb, 
 
965
                        &pixG, GREENMAP, GreenComp);
 
966
                pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; 
 
967
                FindColorInRootCmap (prootmap, prootmap->blue, entries, &rgb, 
 
968
                        &pixB, BLUEMAP, BlueComp);
 
969
                *pPix = pixR | pixG | pixB;
 
970
            }
 
971
        }
 
972
 
 
973
        pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed; 
 
974
        if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
 
975
                      client, RedComp) != Success)
 
976
            return (BadAlloc);
 
977
        pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen; 
 
978
        if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
 
979
                      GREENMAP, client, GreenComp) != Success)
 
980
        {
 
981
            (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0);
 
982
            return (BadAlloc);
 
983
        }
 
984
        pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue; 
 
985
        if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
 
986
                      client, BlueComp) != Success)
 
987
        {
 
988
            (void)FreeCo(pmap, client, GREENMAP, 1, &pixG, (Pixel)0);
 
989
            (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0);
 
990
            return (BadAlloc);
 
991
        }
 
992
        *pPix = pixR | pixG | pixB;
 
993
        break;
 
994
    }
 
995
 
 
996
    /* if this is the client's first pixel in this colormap, tell the
 
997
     * resource manager that the client has pixels in this colormap which
 
998
     * should be freed when the client dies */
 
999
    if ((pmap->numPixelsRed[client] == 1) &&
 
1000
        (CLIENT_ID(pmap->mid) != client) &&
 
1001
        !(pmap->flags & BeingCreated))
 
1002
    {
 
1003
        colorResource   *pcr;
 
1004
 
 
1005
        pcr = (colorResource *) xalloc(sizeof(colorResource));
 
1006
        if (!pcr)
 
1007
        {
 
1008
            (void)FreeColors(pmap, client, 1, pPix, (Pixel)0);
 
1009
            return (BadAlloc);
 
1010
        }
 
1011
        pcr->mid = pmap->mid;
 
1012
        pcr->client = client;
 
1013
        if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
 
1014
            return (BadAlloc);
 
1015
    }
 
1016
    return (Success);
 
1017
}
 
1018
 
 
1019
/*
 
1020
 * FakeAllocColor -- fake an AllocColor request by
 
1021
 * returning a free pixel if availible, otherwise returning
 
1022
 * the closest matching pixel.  This is used by the mi
 
1023
 * software sprite code to recolor cursors.  A nice side-effect
 
1024
 * is that this routine will never return failure.
 
1025
 */
 
1026
 
 
1027
void
 
1028
FakeAllocColor (pmap, item)
 
1029
    register ColormapPtr pmap;
 
1030
    register xColorItem  *item;
 
1031
{
 
1032
    Pixel       pixR, pixG, pixB;
 
1033
    Pixel       temp;
 
1034
    int         entries;
 
1035
    xrgb        rgb;
 
1036
    int         class;
 
1037
    register VisualPtr  pVisual;
 
1038
 
 
1039
    pVisual = pmap->pVisual;
 
1040
    rgb.red = item->red;
 
1041
    rgb.green = item->green;
 
1042
    rgb.blue = item->blue;
 
1043
    (*pmap->pScreen->ResolveColor) (&rgb.red, &rgb.green, &rgb.blue, pVisual);
 
1044
    class = pmap->class;
 
1045
    entries = pVisual->ColormapEntries;
 
1046
 
 
1047
    switch (class) {
 
1048
    case GrayScale:
 
1049
    case PseudoColor:
 
1050
        item->pixel = 0;
 
1051
        if (FindColor(pmap, pmap->red, entries, &rgb, &temp, PSEUDOMAP,
 
1052
                      -1, AllComp) == Success) {
 
1053
            item->pixel = temp;
 
1054
            break;
 
1055
        }
 
1056
        /* fall through ... */
 
1057
    case StaticColor:
 
1058
    case StaticGray:
 
1059
        item->pixel = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
 
1060
        break;
 
1061
 
 
1062
    case DirectColor:
 
1063
        /* Look up each component in its own map, then OR them together */
 
1064
        pixR = (item->pixel & pVisual->redMask) >> pVisual->offsetRed; 
 
1065
        pixG = (item->pixel & pVisual->greenMask) >> pVisual->offsetGreen; 
 
1066
        pixB = (item->pixel & pVisual->blueMask) >> pVisual->offsetBlue; 
 
1067
        if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
 
1068
                      -1, RedComp) != Success)
 
1069
            pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP)
 
1070
                        << pVisual->offsetRed;
 
1071
        if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
 
1072
                      GREENMAP, -1, GreenComp) != Success)
 
1073
            pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb,
 
1074
                                 GREENMAP) << pVisual->offsetGreen;
 
1075
        if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
 
1076
                      -1, BlueComp) != Success)
 
1077
            pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP)
 
1078
                        << pVisual->offsetBlue;
 
1079
        item->pixel = pixR | pixG | pixB;
 
1080
        break;
 
1081
 
 
1082
    case TrueColor:
 
1083
        /* Look up each component in its own map, then OR them together */
 
1084
        pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
 
1085
        pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
 
1086
        pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
 
1087
        item->pixel = (pixR << pVisual->offsetRed) |
 
1088
                      (pixG << pVisual->offsetGreen) |
 
1089
                      (pixB << pVisual->offsetBlue);
 
1090
        break;
 
1091
    }
 
1092
}
 
1093
 
 
1094
/* free a pixel value obtained from FakeAllocColor */
 
1095
void
 
1096
FakeFreeColor(pmap, pixel)
 
1097
    register ColormapPtr pmap;
 
1098
    Pixel pixel;
 
1099
{
 
1100
    register VisualPtr pVisual;
 
1101
    Pixel pixR, pixG, pixB;
 
1102
 
 
1103
    switch (pmap->class) {
 
1104
    case GrayScale:
 
1105
    case PseudoColor:
 
1106
        if (pmap->red[pixel].refcnt == AllocTemporary)
 
1107
            pmap->red[pixel].refcnt = 0;
 
1108
        break;
 
1109
    case DirectColor:
 
1110
        pVisual = pmap->pVisual;
 
1111
        pixR = (pixel & pVisual->redMask) >> pVisual->offsetRed; 
 
1112
        pixG = (pixel & pVisual->greenMask) >> pVisual->offsetGreen; 
 
1113
        pixB = (pixel & pVisual->blueMask) >> pVisual->offsetBlue; 
 
1114
        if (pmap->red[pixR].refcnt == AllocTemporary)
 
1115
            pmap->red[pixR].refcnt = 0;
 
1116
        if (pmap->green[pixG].refcnt == AllocTemporary)
 
1117
            pmap->green[pixG].refcnt = 0;
 
1118
        if (pmap->blue[pixB].refcnt == AllocTemporary)
 
1119
            pmap->blue[pixB].refcnt = 0;
 
1120
        break;
 
1121
    }
 
1122
}
 
1123
 
 
1124
typedef unsigned short  BigNumUpper;
 
1125
typedef unsigned long   BigNumLower;
 
1126
 
 
1127
#define BIGNUMLOWERBITS 24
 
1128
#define BIGNUMUPPERBITS 16
 
1129
#define BIGNUMLOWER (1 << BIGNUMLOWERBITS)
 
1130
#define BIGNUMUPPER (1 << BIGNUMUPPERBITS)
 
1131
#define UPPERPART(i)    ((i) >> BIGNUMLOWERBITS)
 
1132
#define LOWERPART(i)    ((i) & (BIGNUMLOWER - 1))
 
1133
 
 
1134
typedef struct _bignum {
 
1135
    BigNumUpper upper;
 
1136
    BigNumLower lower;
 
1137
} BigNumRec, *BigNumPtr;
 
1138
 
 
1139
#define BigNumGreater(x,y) (((x)->upper > (y)->upper) ||\
 
1140
                            ((x)->upper == (y)->upper && (x)->lower > (y)->lower))
 
1141
 
 
1142
#define UnsignedToBigNum(u,r)   (((r)->upper = UPPERPART(u)), \
 
1143
                                 ((r)->lower = LOWERPART(u)))
 
1144
 
 
1145
#define MaxBigNum(r)            (((r)->upper = BIGNUMUPPER-1), \
 
1146
                                 ((r)->lower = BIGNUMLOWER-1))
 
1147
 
 
1148
static void
 
1149
#if NeedFunctionPrototypes
 
1150
BigNumAdd (BigNumPtr x, BigNumPtr y, BigNumPtr r)
 
1151
#else
 
1152
BigNumAdd (x, y, r)
 
1153
    BigNumPtr   x, y, r;
 
1154
#endif
 
1155
{
 
1156
    BigNumLower lower, carry = 0;
 
1157
 
 
1158
    lower = x->lower + y->lower;
 
1159
    if (lower >= BIGNUMLOWER) {
 
1160
        lower -= BIGNUMLOWER;
 
1161
        carry = 1;
 
1162
    }
 
1163
    r->lower = lower;
 
1164
    r->upper = x->upper + y->upper + carry;
 
1165
}
 
1166
 
 
1167
static Pixel
 
1168
FindBestPixel(pentFirst, size, prgb, channel)
 
1169
    EntryPtr    pentFirst;
 
1170
    int         size;
 
1171
    xrgb        *prgb;
 
1172
    int         channel;
 
1173
{
 
1174
    EntryPtr    pent;
 
1175
    Pixel       pixel, final;
 
1176
    long        dr, dg, db;
 
1177
    unsigned long   sq;
 
1178
    BigNumRec   minval, sum, temp;
 
1179
 
 
1180
    final = 0;
 
1181
    MaxBigNum(&minval);
 
1182
    /* look for the minimal difference */
 
1183
    for (pent = pentFirst, pixel = 0; pixel < size; pent++, pixel++)
 
1184
    {
 
1185
        dr = dg = db = 0;
 
1186
        switch(channel)
 
1187
        {
 
1188
          case PSEUDOMAP:
 
1189
              dg = (long) pent->co.local.green - prgb->green;
 
1190
              db = (long) pent->co.local.blue - prgb->blue;
 
1191
          case REDMAP:
 
1192
              dr = (long) pent->co.local.red - prgb->red;
 
1193
              break;
 
1194
          case GREENMAP:
 
1195
              dg = (long) pent->co.local.green - prgb->green;
 
1196
              break;
 
1197
          case BLUEMAP:
 
1198
              db = (long) pent->co.local.blue - prgb->blue;
 
1199
              break;
 
1200
        }
 
1201
        sq = dr * dr;
 
1202
        UnsignedToBigNum (sq, &sum);
 
1203
        sq = dg * dg;
 
1204
        UnsignedToBigNum (sq, &temp);
 
1205
        BigNumAdd (&sum, &temp, &sum);
 
1206
        sq = db * db;
 
1207
        UnsignedToBigNum (sq, &temp);
 
1208
        BigNumAdd (&sum, &temp, &sum);
 
1209
        if (BigNumGreater (&minval, &sum))
 
1210
        {
 
1211
            final = pixel;
 
1212
            minval = sum;
 
1213
        }
 
1214
    }
 
1215
    return(final);
 
1216
}
 
1217
 
 
1218
static void
 
1219
FindColorInRootCmap (pmap, pentFirst, size, prgb, pPixel, channel, comp)
 
1220
    ColormapPtr pmap;
 
1221
    EntryPtr    pentFirst;
 
1222
    int         size;
 
1223
    xrgb*       prgb;
 
1224
    Pixel*      pPixel;
 
1225
    int         channel;
 
1226
    ColorCompareProcPtr comp;
 
1227
{
 
1228
    EntryPtr    pent;
 
1229
    Pixel       pixel;
 
1230
    int         count;
 
1231
 
 
1232
    if ((pixel = *pPixel) >= size)
 
1233
        pixel = 0;
 
1234
    for (pent = pentFirst + pixel, count = size; --count >= 0; pent++, pixel++)
 
1235
    {
 
1236
        if (pent->refcnt > 0 && (*comp) (pent, prgb))
 
1237
        {
 
1238
            switch (channel)
 
1239
            {
 
1240
            case REDMAP:
 
1241
                pixel <<= pmap->pVisual->offsetRed;
 
1242
                break;
 
1243
            case GREENMAP:
 
1244
                pixel <<= pmap->pVisual->offsetGreen;
 
1245
                break;
 
1246
            case BLUEMAP:
 
1247
                pixel <<= pmap->pVisual->offsetBlue;
 
1248
                break;
 
1249
            default: /* PSEUDOMAP */
 
1250
                break;
 
1251
            }
 
1252
            *pPixel = pixel;
 
1253
        }
 
1254
    }
 
1255
}
 
1256
 
 
1257
/* Tries to find a color in pmap that exactly matches the one requested in prgb
 
1258
 * if it can't it allocates one.
 
1259
 * Starts looking at pentFirst + *pPixel, so if you want a specific pixel,
 
1260
 * load *pPixel with that value, otherwise set it to 0
 
1261
 */
 
1262
int
 
1263
FindColor (pmap, pentFirst, size, prgb, pPixel, channel, client, comp)
 
1264
    ColormapPtr pmap;
 
1265
    EntryPtr    pentFirst;
 
1266
    int         size;
 
1267
    xrgb        *prgb;
 
1268
    Pixel       *pPixel;
 
1269
    int         channel;
 
1270
    int         client;
 
1271
    ColorCompareProcPtr comp;
 
1272
{
 
1273
    EntryPtr    pent;
 
1274
    Bool        foundFree;
 
1275
    Pixel       pixel, Free = 0;
 
1276
    int         npix, count, *nump = NULL;
 
1277
    Pixel       **pixp = NULL, *ppix;
 
1278
    xColorItem  def;
 
1279
 
 
1280
    foundFree = FALSE;
 
1281
 
 
1282
    if((pixel = *pPixel) >= size)
 
1283
        pixel = 0;
 
1284
    /* see if there is a match, and also look for a free entry */
 
1285
    for (pent = pentFirst + pixel, count = size; --count >= 0; )
 
1286
    {
 
1287
        if (pent->refcnt > 0)
 
1288
        {
 
1289
            if ((*comp) (pent, prgb))
 
1290
            {
 
1291
                if (client >= 0)
 
1292
                    pent->refcnt++;
 
1293
                *pPixel = pixel;
 
1294
                switch(channel)
 
1295
                {
 
1296
                  case REDMAP:
 
1297
                    *pPixel <<= pmap->pVisual->offsetRed;
 
1298
                  case PSEUDOMAP:
 
1299
                    break;
 
1300
                  case GREENMAP:
 
1301
                    *pPixel <<= pmap->pVisual->offsetGreen;
 
1302
                    break;
 
1303
                  case BLUEMAP:
 
1304
                    *pPixel <<= pmap->pVisual->offsetBlue;
 
1305
                    break;
 
1306
                }
 
1307
                goto gotit;
 
1308
            }
 
1309
        }
 
1310
        else if (!foundFree && pent->refcnt == 0)
 
1311
        {
 
1312
            Free = pixel;
 
1313
            foundFree = TRUE;
 
1314
            /* If we're initializing the colormap, then we are looking for
 
1315
             * the first free cell we can find, not to minimize the number
 
1316
             * of entries we use.  So don't look any further. */
 
1317
            if(pmap->flags & BeingCreated)
 
1318
                break;
 
1319
        }
 
1320
        pixel++;
 
1321
        if(pixel >= size)
 
1322
        {
 
1323
            pent = pentFirst;
 
1324
            pixel = 0;
 
1325
        }
 
1326
        else
 
1327
            pent++;
 
1328
    }
 
1329
 
 
1330
    /* If we got here, we didn't find a match.  If we also didn't find
 
1331
     * a free entry, we're out of luck.  Otherwise, we'll usurp a free
 
1332
     * entry and fill it in */
 
1333
    if (!foundFree)
 
1334
        return (BadAlloc);
 
1335
    pent = pentFirst + Free;
 
1336
    pent->fShared = FALSE;
 
1337
    pent->refcnt = (client >= 0) ? 1 : AllocTemporary;
 
1338
 
 
1339
    switch (channel)
 
1340
    {
 
1341
      case PSEUDOMAP:
 
1342
        pent->co.local.red = prgb->red;
 
1343
        pent->co.local.green = prgb->green;
 
1344
        pent->co.local.blue = prgb->blue;
 
1345
        def.red = prgb->red;
 
1346
        def.green = prgb->green;
 
1347
        def.blue = prgb->blue;
 
1348
        def.flags = (DoRed|DoGreen|DoBlue);
 
1349
        if (client >= 0)
 
1350
            pmap->freeRed--;
 
1351
        def.pixel = Free;
 
1352
        break;
 
1353
 
 
1354
      case REDMAP:
 
1355
        pent->co.local.red = prgb->red;
 
1356
        def.red = prgb->red;
 
1357
        def.green = pmap->green[0].co.local.green;
 
1358
        def.blue = pmap->blue[0].co.local.blue;
 
1359
        def.flags = DoRed;
 
1360
        if (client >= 0)
 
1361
            pmap->freeRed--;
 
1362
        def.pixel = Free << pmap->pVisual->offsetRed;
 
1363
        break;
 
1364
 
 
1365
      case GREENMAP:
 
1366
        pent->co.local.green = prgb->green;
 
1367
        def.red = pmap->red[0].co.local.red;
 
1368
        def.green = prgb->green;
 
1369
        def.blue = pmap->blue[0].co.local.blue;
 
1370
        def.flags = DoGreen;
 
1371
        if (client >= 0)
 
1372
            pmap->freeGreen--;
 
1373
        def.pixel = Free << pmap->pVisual->offsetGreen;
 
1374
        break;
 
1375
 
 
1376
      case BLUEMAP:
 
1377
        pent->co.local.blue = prgb->blue;
 
1378
        def.red = pmap->red[0].co.local.red;
 
1379
        def.green = pmap->green[0].co.local.green;
 
1380
        def.blue = prgb->blue;
 
1381
        def.flags = DoBlue;
 
1382
        if (client >= 0)
 
1383
            pmap->freeBlue--;
 
1384
        def.pixel = Free << pmap->pVisual->offsetBlue;
 
1385
        break;
 
1386
    }
 
1387
    (*pmap->pScreen->StoreColors) (pmap, 1, &def);
 
1388
    pixel = Free;       
 
1389
    *pPixel = def.pixel;
 
1390
 
 
1391
gotit:
 
1392
    if (pmap->flags & BeingCreated || client == -1)
 
1393
        return(Success);
 
1394
    /* Now remember the pixel, for freeing later */
 
1395
    switch (channel)
 
1396
    {
 
1397
      case PSEUDOMAP:
 
1398
      case REDMAP:
 
1399
        nump = pmap->numPixelsRed;
 
1400
        pixp = pmap->clientPixelsRed;
 
1401
        break;
 
1402
 
 
1403
      case GREENMAP:
 
1404
        nump = pmap->numPixelsGreen;
 
1405
        pixp = pmap->clientPixelsGreen;
 
1406
        break;
 
1407
 
 
1408
      case BLUEMAP:
 
1409
        nump = pmap->numPixelsBlue;
 
1410
        pixp = pmap->clientPixelsBlue;
 
1411
        break;
 
1412
    }
 
1413
    npix = nump[client];
 
1414
    ppix = (Pixel *) xrealloc (pixp[client], (npix + 1) * sizeof(Pixel));
 
1415
    if (!ppix)
 
1416
    {
 
1417
        pent->refcnt--;
 
1418
        if (!pent->fShared)
 
1419
            switch (channel)
 
1420
            {
 
1421
              case PSEUDOMAP:
 
1422
              case REDMAP:
 
1423
                pmap->freeRed++;
 
1424
                break;
 
1425
              case GREENMAP:
 
1426
                pmap->freeGreen++;
 
1427
                break;
 
1428
              case BLUEMAP:
 
1429
                pmap->freeBlue++;
 
1430
                break;
 
1431
            }
 
1432
        return(BadAlloc);
 
1433
    }
 
1434
    ppix[npix] = pixel;
 
1435
    pixp[client] = ppix;
 
1436
    nump[client]++;
 
1437
 
 
1438
    return(Success);
 
1439
}
 
1440
 
 
1441
/* Comparison functions -- passed to FindColor to determine if an
 
1442
 * entry is already the color we're looking for or not */
 
1443
static int
 
1444
AllComp (pent, prgb)
 
1445
    EntryPtr    pent;
 
1446
    xrgb        *prgb;
 
1447
{
 
1448
    if((pent->co.local.red == prgb->red) &&
 
1449
       (pent->co.local.green == prgb->green) &&
 
1450
       (pent->co.local.blue == prgb->blue) )
 
1451
       return (1);
 
1452
    return (0);
 
1453
}
 
1454
 
 
1455
static int
 
1456
RedComp (pent, prgb)
 
1457
    EntryPtr    pent;
 
1458
    xrgb        *prgb;
 
1459
{
 
1460
    if (pent->co.local.red == prgb->red) 
 
1461
        return (1);
 
1462
    return (0);
 
1463
}
 
1464
 
 
1465
static int
 
1466
GreenComp (pent, prgb)
 
1467
    EntryPtr    pent;
 
1468
    xrgb        *prgb;
 
1469
{
 
1470
    if (pent->co.local.green == prgb->green) 
 
1471
        return (1);
 
1472
    return (0);
 
1473
}
 
1474
 
 
1475
static int
 
1476
BlueComp (pent, prgb)
 
1477
    EntryPtr    pent;
 
1478
    xrgb        *prgb;
 
1479
{
 
1480
    if (pent->co.local.blue == prgb->blue) 
 
1481
        return (1);
 
1482
    return (0);
 
1483
}
 
1484
 
 
1485
 
 
1486
/* Read the color value of a cell */
 
1487
 
 
1488
int
 
1489
QueryColors (pmap, count, ppixIn, prgbList)
 
1490
    ColormapPtr pmap;
 
1491
    int         count;
 
1492
    Pixel       *ppixIn;
 
1493
    xrgb        *prgbList;
 
1494
{
 
1495
    Pixel       *ppix, pixel;
 
1496
    xrgb        *prgb;
 
1497
    VisualPtr   pVisual;
 
1498
    EntryPtr    pent;
 
1499
    Pixel       i;
 
1500
    int         errVal = Success;
 
1501
 
 
1502
    pVisual = pmap->pVisual;
 
1503
    if ((pmap->class | DynamicClass) == DirectColor)
 
1504
    {
 
1505
        int numred, numgreen, numblue;
 
1506
        Pixel rgbbad;
 
1507
 
 
1508
        numred = NUMRED(pVisual);
 
1509
        numgreen = NUMGREEN(pVisual);
 
1510
        numblue = NUMBLUE(pVisual);
 
1511
        rgbbad = ~RGBMASK(pVisual);
 
1512
        for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++)
 
1513
        {
 
1514
            pixel = *ppix;
 
1515
            if (pixel & rgbbad) {
 
1516
                clientErrorValue = pixel;
 
1517
                errVal =  BadValue;
 
1518
                continue;
 
1519
            }
 
1520
            i  = (pixel & pVisual->redMask) >> pVisual->offsetRed;
 
1521
            if (i >= numred)
 
1522
            {
 
1523
                clientErrorValue = pixel;
 
1524
                errVal =  BadValue;
 
1525
                continue;
 
1526
            }
 
1527
            prgb->red = pmap->red[i].co.local.red;
 
1528
            i  = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
 
1529
            if (i >= numgreen)
 
1530
            {
 
1531
                clientErrorValue = pixel;
 
1532
                errVal =  BadValue;
 
1533
                continue;
 
1534
            }
 
1535
            prgb->green = pmap->green[i].co.local.green;
 
1536
            i  = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
 
1537
            if (i >= numblue)
 
1538
            {
 
1539
                clientErrorValue = pixel;
 
1540
                errVal =  BadValue;
 
1541
                continue;
 
1542
            }
 
1543
            prgb->blue = pmap->blue[i].co.local.blue;
 
1544
        }
 
1545
    }
 
1546
    else
 
1547
    {
 
1548
        for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++)
 
1549
        {
 
1550
            pixel = *ppix;
 
1551
            if (pixel >= pVisual->ColormapEntries)
 
1552
            {
 
1553
                clientErrorValue = pixel;
 
1554
                errVal = BadValue;
 
1555
            }
 
1556
            else
 
1557
            {
 
1558
                pent = (EntryPtr)&pmap->red[pixel];
 
1559
                if (pent->fShared)
 
1560
                {
 
1561
                    prgb->red = pent->co.shco.red->color;
 
1562
                    prgb->green = pent->co.shco.green->color;
 
1563
                    prgb->blue = pent->co.shco.blue->color;
 
1564
                }
 
1565
                else
 
1566
                {
 
1567
                    prgb->red = pent->co.local.red;
 
1568
                    prgb->green = pent->co.local.green;
 
1569
                    prgb->blue = pent->co.local.blue;
 
1570
                }
 
1571
            }
 
1572
        }
 
1573
    }
 
1574
    return (errVal);
 
1575
}
 
1576
 
 
1577
static void
 
1578
FreePixels(pmap, client)
 
1579
    register ColormapPtr        pmap;
 
1580
    register int                client;
 
1581
{
 
1582
    register Pixel              *ppix, *ppixStart;
 
1583
    register int                n;
 
1584
    int                         class;
 
1585
#ifdef LBX
 
1586
    Bool                        grabbed;
 
1587
    Bool                        zeroRefCount;
 
1588
    Bool                        anyRefCountReachedZero = 0;
 
1589
#endif
 
1590
 
 
1591
    class = pmap->class;
 
1592
    ppixStart = pmap->clientPixelsRed[client];
 
1593
    if (class & DynamicClass)
 
1594
    {
 
1595
        n = pmap->numPixelsRed[client];
 
1596
#ifdef LBX
 
1597
        grabbed = LbxCheckCmapGrabbed (pmap);
 
1598
        if (grabbed)
 
1599
        {
 
1600
            /*
 
1601
             * If the colormap is grabbed by a proxy, the server must
 
1602
             * notify the proxy of all cells that are freed (the refcount
 
1603
             * has reached zero on these cells).
 
1604
             */
 
1605
 
 
1606
            LbxBeginFreeCellsEvent (pmap);
 
1607
            LbxSortPixelList (ppixStart, n);
 
1608
        }
 
1609
#endif
 
1610
        for (ppix = ppixStart; --n >= 0; )
 
1611
        {
 
1612
            FreeCell(pmap, *ppix, REDMAP);
 
1613
#ifdef LBX
 
1614
            /*
 
1615
             * Only PSEUDO colormaps are grabbed by LBX proxies.
 
1616
             * Check if the ref count reached zero on this pixel.
 
1617
             */
 
1618
 
 
1619
            zeroRefCount = pmap->red[*ppix].refcnt == 0;
 
1620
            if (zeroRefCount)
 
1621
                anyRefCountReachedZero = 1;
 
1622
            
 
1623
            if (grabbed && zeroRefCount)
 
1624
                LbxAddFreeCellToEvent (pmap, *ppix);
 
1625
#endif
 
1626
            ppix++;
 
1627
        }
 
1628
#ifdef LBX
 
1629
        if (grabbed)
 
1630
            LbxEndFreeCellsEvent (pmap);
 
1631
        else if (anyRefCountReachedZero)
 
1632
        {
 
1633
            /*
 
1634
             * We only send LbxFreeCell events to a proxy that has the colormap
 
1635
             * grabbed.  If the colormap is not grabbed, the proxy that last
 
1636
             * had the colormap grabbed will not be able to do a smart grab
 
1637
             * in the future.  A smart grab can only occur if the proxy is kept
 
1638
             * up to date on every alloc/free change in the colormap.
 
1639
             */
 
1640
 
 
1641
            LbxDisableSmartGrab (pmap);
 
1642
        }
 
1643
#endif
 
1644
    }
 
1645
 
 
1646
    xfree(ppixStart);
 
1647
    pmap->clientPixelsRed[client] = (Pixel *) NULL;
 
1648
    pmap->numPixelsRed[client] = 0;
 
1649
    if ((class | DynamicClass) == DirectColor) 
 
1650
    {
 
1651
        ppixStart = pmap->clientPixelsGreen[client];
 
1652
        if (class & DynamicClass)
 
1653
            for (ppix = ppixStart, n = pmap->numPixelsGreen[client]; --n >= 0;)
 
1654
                FreeCell(pmap, *ppix++, GREENMAP);
 
1655
        xfree(ppixStart);
 
1656
        pmap->clientPixelsGreen[client] = (Pixel *) NULL;
 
1657
        pmap->numPixelsGreen[client] = 0;
 
1658
 
 
1659
        ppixStart = pmap->clientPixelsBlue[client];
 
1660
        if (class & DynamicClass)
 
1661
            for (ppix = ppixStart, n = pmap->numPixelsBlue[client]; --n >= 0; )
 
1662
                FreeCell(pmap, *ppix++, BLUEMAP);
 
1663
        xfree(ppixStart);
 
1664
        pmap->clientPixelsBlue[client] = (Pixel *) NULL;
 
1665
        pmap->numPixelsBlue[client] = 0;
 
1666
    }
 
1667
}
 
1668
 
 
1669
/* Free all of a client's colors and cells */
 
1670
/*ARGSUSED*/
 
1671
int
 
1672
FreeClientPixels (value, fakeid)
 
1673
    pointer value;  /* must conform to DeleteType */
 
1674
    XID fakeid;
 
1675
{
 
1676
    ColormapPtr pmap;
 
1677
    colorResource *pcr = (colorResource *)value;
 
1678
 
 
1679
    pmap = (ColormapPtr) LookupIDByType(pcr->mid, RT_COLORMAP);
 
1680
    if (pmap)
 
1681
        FreePixels(pmap, pcr->client);
 
1682
    xfree(pcr);
 
1683
    return Success;
 
1684
}
 
1685
 
 
1686
int
 
1687
AllocColorCells (client, pmap, colors, planes, contig, ppix, masks)
 
1688
    int         client;
 
1689
    ColormapPtr pmap;
 
1690
    int         colors, planes;
 
1691
    Bool        contig;
 
1692
    Pixel       *ppix;
 
1693
    Pixel       *masks;
 
1694
{
 
1695
    Pixel       rmask, gmask, bmask, *ppixFirst, r, g, b;
 
1696
    int         n, class;
 
1697
    int         ok;
 
1698
    int         oldcount;
 
1699
    colorResource *pcr = (colorResource *)NULL;
 
1700
 
 
1701
    class = pmap->class;
 
1702
    if (!(class & DynamicClass))
 
1703
        return (BadAlloc); /* Shouldn't try on this type */
 
1704
    oldcount = pmap->numPixelsRed[client];
 
1705
    if (pmap->class == DirectColor)
 
1706
        oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
 
1707
    if (!oldcount && (CLIENT_ID(pmap->mid) != client))
 
1708
    {
 
1709
        pcr = (colorResource *) xalloc(sizeof(colorResource));
 
1710
        if (!pcr)
 
1711
            return (BadAlloc);
 
1712
    }
 
1713
 
 
1714
    if (pmap->class == DirectColor)
 
1715
    {
 
1716
        ok = AllocDirect (client, pmap, colors, planes, planes, planes,
 
1717
                          contig, ppix, &rmask, &gmask, &bmask);
 
1718
        if(ok == Success)
 
1719
        {
 
1720
            for (r = g = b = 1, n = planes; --n >= 0; r += r, g += g, b += b)
 
1721
            {
 
1722
                while(!(rmask & r))
 
1723
                    r += r;
 
1724
                while(!(gmask & g))
 
1725
                    g += g;
 
1726
                while(!(bmask & b))
 
1727
                    b += b;
 
1728
                *masks++ = r | g | b;
 
1729
            }
 
1730
        }
 
1731
    }
 
1732
    else
 
1733
    {
 
1734
        ok = AllocPseudo (client, pmap, colors, planes, contig, ppix, &rmask,
 
1735
                          &ppixFirst);
 
1736
        if(ok == Success)
 
1737
        {
 
1738
            for (r = 1, n = planes; --n >= 0; r += r)
 
1739
            {
 
1740
                while(!(rmask & r))
 
1741
                    r += r;
 
1742
                *masks++ = r;
 
1743
            }
 
1744
        }
 
1745
    }
 
1746
 
 
1747
    /* if this is the client's first pixels in this colormap, tell the
 
1748
     * resource manager that the client has pixels in this colormap which
 
1749
     * should be freed when the client dies */
 
1750
    if ((ok == Success) && pcr)
 
1751
    {
 
1752
        pcr->mid = pmap->mid;
 
1753
        pcr->client = client;
 
1754
        if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
 
1755
            ok = BadAlloc;
 
1756
    } else if (pcr)
 
1757
        xfree(pcr);
 
1758
 
 
1759
    return (ok);
 
1760
}
 
1761
 
 
1762
 
 
1763
int
 
1764
AllocColorPlanes (client, pmap, colors, r, g, b, contig, pixels,
 
1765
                  prmask, pgmask, pbmask)
 
1766
    int         client;
 
1767
    ColormapPtr pmap;
 
1768
    int         colors, r, g, b;
 
1769
    Bool        contig;
 
1770
    Pixel       *pixels;
 
1771
    Pixel       *prmask, *pgmask, *pbmask;
 
1772
{
 
1773
    int         ok;
 
1774
    Pixel       mask, *ppixFirst;
 
1775
    register Pixel shift;
 
1776
    register int i;
 
1777
    int         class;
 
1778
    int         oldcount;
 
1779
    colorResource *pcr = (colorResource *)NULL;
 
1780
 
 
1781
    class = pmap->class;
 
1782
    if (!(class & DynamicClass))
 
1783
        return (BadAlloc); /* Shouldn't try on this type */
 
1784
    oldcount = pmap->numPixelsRed[client];
 
1785
    if (class == DirectColor)
 
1786
        oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
 
1787
    if (!oldcount && (CLIENT_ID(pmap->mid) != client))
 
1788
    {
 
1789
        pcr = (colorResource *) xalloc(sizeof(colorResource));
 
1790
        if (!pcr)
 
1791
            return (BadAlloc);
 
1792
    }
 
1793
 
 
1794
    if (class == DirectColor)
 
1795
    {
 
1796
        ok = AllocDirect (client, pmap, colors, r, g, b, contig, pixels,
 
1797
                          prmask, pgmask, pbmask);
 
1798
    }
 
1799
    else
 
1800
    {
 
1801
        /* Allocate the proper pixels */
 
1802
        /* XXX This is sort of bad, because of contig is set, we force all
 
1803
         * r + g + b bits to be contiguous.  Should only force contiguity
 
1804
         * per mask 
 
1805
         */
 
1806
        ok = AllocPseudo (client, pmap, colors, r + g + b, contig, pixels,
 
1807
                          &mask, &ppixFirst);
 
1808
 
 
1809
        if(ok == Success)
 
1810
        {
 
1811
            /* now split that mask into three */
 
1812
            *prmask = *pgmask = *pbmask = 0;
 
1813
            shift = 1;
 
1814
            for (i = r; --i >= 0; shift += shift)
 
1815
            {
 
1816
                while (!(mask & shift))
 
1817
                    shift += shift;
 
1818
                *prmask |= shift;
 
1819
            }
 
1820
            for (i = g; --i >= 0; shift += shift)
 
1821
            {
 
1822
                while (!(mask & shift))
 
1823
                    shift += shift;
 
1824
                *pgmask |= shift;
 
1825
            }
 
1826
            for (i = b; --i >= 0; shift += shift)
 
1827
            {
 
1828
                while (!(mask & shift))
 
1829
                    shift += shift;
 
1830
                *pbmask |= shift;
 
1831
            }
 
1832
 
 
1833
            /* set up the shared color cells */
 
1834
            if (!AllocShared(pmap, pixels, colors, r, g, b,
 
1835
                             *prmask, *pgmask, *pbmask, ppixFirst))
 
1836
            {
 
1837
                (void)FreeColors(pmap, client, colors, pixels, mask);
 
1838
                ok = BadAlloc;
 
1839
            }
 
1840
        }
 
1841
    }
 
1842
 
 
1843
    /* if this is the client's first pixels in this colormap, tell the
 
1844
     * resource manager that the client has pixels in this colormap which
 
1845
     * should be freed when the client dies */
 
1846
    if ((ok == Success) && pcr)
 
1847
    {
 
1848
        pcr->mid = pmap->mid;
 
1849
        pcr->client = client;
 
1850
        if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
 
1851
            ok = BadAlloc;
 
1852
    } else if (pcr)
 
1853
        xfree(pcr);
 
1854
 
 
1855
    return (ok);
 
1856
}
 
1857
 
 
1858
static int
 
1859
AllocDirect (client, pmap, c, r, g, b, contig, pixels, prmask, pgmask, pbmask)
 
1860
    int         client;
 
1861
    ColormapPtr pmap;
 
1862
    int         c, r, g, b;
 
1863
    Bool        contig;
 
1864
    Pixel       *pixels;
 
1865
    Pixel       *prmask, *pgmask, *pbmask;
 
1866
{
 
1867
    Pixel       *ppixRed, *ppixGreen, *ppixBlue;
 
1868
    Pixel       *ppix, *pDst, *p;
 
1869
    int         npix, npixR, npixG, npixB;
 
1870
    Bool        okR, okG, okB;
 
1871
    Pixel       *rpix = 0, *gpix = 0, *bpix = 0;
 
1872
 
 
1873
    npixR = c << r;
 
1874
    npixG = c << g;
 
1875
    npixB = c << b;
 
1876
    if ((r >= 32) || (g >= 32) || (b >= 32) ||
 
1877
        (npixR > pmap->freeRed) || (npixR < c) ||
 
1878
        (npixG > pmap->freeGreen) || (npixG < c) ||
 
1879
        (npixB > pmap->freeBlue) || (npixB < c))
 
1880
        return BadAlloc;
 
1881
 
 
1882
    /* start out with empty pixels */
 
1883
    for(p = pixels; p < pixels + c; p++)
 
1884
        *p = 0;
 
1885
 
 
1886
    ppixRed = (Pixel *)ALLOCATE_LOCAL(npixR * sizeof(Pixel));
 
1887
    ppixGreen = (Pixel *)ALLOCATE_LOCAL(npixG * sizeof(Pixel));
 
1888
    ppixBlue = (Pixel *)ALLOCATE_LOCAL(npixB * sizeof(Pixel));
 
1889
    if (!ppixRed || !ppixGreen || !ppixBlue)
 
1890
    {
 
1891
        if (ppixBlue) DEALLOCATE_LOCAL(ppixBlue);
 
1892
        if (ppixGreen) DEALLOCATE_LOCAL(ppixGreen);
 
1893
        if (ppixRed) DEALLOCATE_LOCAL(ppixRed);
 
1894
        return(BadAlloc);
 
1895
    }
 
1896
 
 
1897
    okR = AllocCP(pmap, pmap->red, c, r, contig, ppixRed, prmask);
 
1898
    okG = AllocCP(pmap, pmap->green, c, g, contig, ppixGreen, pgmask);
 
1899
    okB = AllocCP(pmap, pmap->blue, c, b, contig, ppixBlue, pbmask);
 
1900
 
 
1901
    if (okR && okG && okB)
 
1902
    {
 
1903
        rpix = (Pixel *) xrealloc(pmap->clientPixelsRed[client],
 
1904
                                  (pmap->numPixelsRed[client] + (c << r)) *
 
1905
                                  sizeof(Pixel));
 
1906
        if (rpix)
 
1907
            pmap->clientPixelsRed[client] = rpix;
 
1908
        gpix = (Pixel *) xrealloc(pmap->clientPixelsGreen[client],
 
1909
                                  (pmap->numPixelsGreen[client] + (c << g)) *
 
1910
                                  sizeof(Pixel));
 
1911
        if (gpix)
 
1912
            pmap->clientPixelsGreen[client] = gpix;
 
1913
        bpix = (Pixel *) xrealloc(pmap->clientPixelsBlue[client],
 
1914
                                  (pmap->numPixelsBlue[client] + (c << b)) *
 
1915
                                  sizeof(Pixel));
 
1916
        if (bpix)
 
1917
            pmap->clientPixelsBlue[client] = bpix;
 
1918
    }
 
1919
 
 
1920
    if (!okR || !okG || !okB || !rpix || !gpix || !bpix)
 
1921
    {
 
1922
        if (okR)
 
1923
            for(ppix = ppixRed, npix = npixR; --npix >= 0; ppix++)
 
1924
                pmap->red[*ppix].refcnt = 0;
 
1925
        if (okG)
 
1926
            for(ppix = ppixGreen, npix = npixG; --npix >= 0; ppix++)
 
1927
                pmap->green[*ppix].refcnt = 0;
 
1928
        if (okB)
 
1929
            for(ppix = ppixBlue, npix = npixB; --npix >= 0; ppix++)
 
1930
                pmap->blue[*ppix].refcnt = 0;
 
1931
        DEALLOCATE_LOCAL(ppixBlue);
 
1932
        DEALLOCATE_LOCAL(ppixGreen);
 
1933
        DEALLOCATE_LOCAL(ppixRed);
 
1934
        return(BadAlloc);
 
1935
    }
 
1936
 
 
1937
    *prmask <<= pmap->pVisual->offsetRed;
 
1938
    *pgmask <<= pmap->pVisual->offsetGreen;
 
1939
    *pbmask <<= pmap->pVisual->offsetBlue;
 
1940
 
 
1941
    ppix = rpix + pmap->numPixelsRed[client];
 
1942
    for (pDst = pixels, p = ppixRed; p < ppixRed + npixR; p++)
 
1943
    {
 
1944
        *ppix++ = *p;
 
1945
        if(p < ppixRed + c)
 
1946
            *pDst++ |= *p << pmap->pVisual->offsetRed;
 
1947
    }
 
1948
    pmap->numPixelsRed[client] += npixR;
 
1949
    pmap->freeRed -= npixR;
 
1950
 
 
1951
    ppix = gpix + pmap->numPixelsGreen[client];
 
1952
    for (pDst = pixels, p = ppixGreen; p < ppixGreen + npixG; p++)
 
1953
    {
 
1954
        *ppix++ = *p;
 
1955
        if(p < ppixGreen + c)
 
1956
            *pDst++ |= *p << pmap->pVisual->offsetGreen;
 
1957
    }
 
1958
    pmap->numPixelsGreen[client] += npixG;
 
1959
    pmap->freeGreen -= npixG;
 
1960
 
 
1961
    ppix = bpix + pmap->numPixelsBlue[client];
 
1962
    for (pDst = pixels, p = ppixBlue; p < ppixBlue + npixB; p++)
 
1963
    {
 
1964
        *ppix++ = *p;
 
1965
        if(p < ppixBlue + c)
 
1966
            *pDst++ |= *p << pmap->pVisual->offsetBlue;
 
1967
    }
 
1968
    pmap->numPixelsBlue[client] += npixB;
 
1969
    pmap->freeBlue -= npixB;
 
1970
 
 
1971
    DEALLOCATE_LOCAL(ppixBlue);
 
1972
    DEALLOCATE_LOCAL(ppixGreen);
 
1973
    DEALLOCATE_LOCAL(ppixRed);
 
1974
 
 
1975
    return (Success);
 
1976
}
 
1977
 
 
1978
static int
 
1979
AllocPseudo (client, pmap, c, r, contig, pixels, pmask, pppixFirst)
 
1980
    int         client;
 
1981
    ColormapPtr pmap;
 
1982
    int         c, r;
 
1983
    Bool        contig;
 
1984
    Pixel       *pixels;
 
1985
    Pixel       *pmask;
 
1986
    Pixel       **pppixFirst;
 
1987
{
 
1988
    Pixel       *ppix, *p, *pDst, *ppixTemp;
 
1989
    int         npix;
 
1990
    Bool        ok;
 
1991
 
 
1992
    npix = c << r;
 
1993
    if ((r >= 32) || (npix > pmap->freeRed) || (npix < c))
 
1994
        return(BadAlloc);
 
1995
    if(!(ppixTemp = (Pixel *)ALLOCATE_LOCAL(npix * sizeof(Pixel))))
 
1996
        return(BadAlloc);
 
1997
    ok = AllocCP(pmap, pmap->red, c, r, contig, ppixTemp, pmask);
 
1998
 
 
1999
    if (ok)
 
2000
    {
 
2001
 
 
2002
        /* all the allocated pixels are added to the client pixel list,
 
2003
         * but only the unique ones are returned to the client */
 
2004
        ppix = (Pixel *)xrealloc(pmap->clientPixelsRed[client],
 
2005
                         (pmap->numPixelsRed[client] + npix) * sizeof(Pixel));
 
2006
        if (!ppix)
 
2007
        {
 
2008
            for (p = ppixTemp; p < ppixTemp + npix; p++)
 
2009
                pmap->red[*p].refcnt = 0;
 
2010
            return (BadAlloc);
 
2011
        }
 
2012
        pmap->clientPixelsRed[client] = ppix;
 
2013
        ppix += pmap->numPixelsRed[client];
 
2014
        *pppixFirst = ppix;
 
2015
        pDst = pixels;
 
2016
        for (p = ppixTemp; p < ppixTemp + npix; p++)
 
2017
        {
 
2018
            *ppix++ = *p;
 
2019
            if(p < ppixTemp + c)
 
2020
                *pDst++ = *p;
 
2021
        }
 
2022
        pmap->numPixelsRed[client] += npix;
 
2023
        pmap->freeRed -= npix;
 
2024
    }
 
2025
    DEALLOCATE_LOCAL(ppixTemp);
 
2026
    return (ok ? Success : BadAlloc);
 
2027
}
 
2028
 
 
2029
/* Allocates count << planes pixels from colormap pmap for client. If
 
2030
 * contig, then the plane mask is made of consecutive bits.  Returns
 
2031
 * all count << pixels in the array pixels. The first count of those
 
2032
 * pixels are the unique pixels.  *pMask has the mask to Or with the
 
2033
 * unique pixels to get the rest of them.
 
2034
 *
 
2035
 * Returns True iff all pixels could be allocated 
 
2036
 * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE
 
2037
 * (see AllocShared for why we care)
 
2038
 */
 
2039
static Bool
 
2040
AllocCP (pmap, pentFirst, count, planes, contig, pixels, pMask)
 
2041
    ColormapPtr pmap;
 
2042
    EntryPtr    pentFirst;
 
2043
    int         count, planes;
 
2044
    Bool        contig;
 
2045
    Pixel       *pixels, *pMask;
 
2046
    
 
2047
{
 
2048
    EntryPtr    ent;
 
2049
    Pixel       pixel, base, entries, maxp, save;
 
2050
    int         dplanes, found;
 
2051
    Pixel       *ppix;
 
2052
    Pixel       mask;
 
2053
    Pixel       finalmask;
 
2054
 
 
2055
    dplanes = pmap->pVisual->nplanes;
 
2056
 
 
2057
    /* Easy case.  Allocate pixels only */
 
2058
    if (planes == 0)
 
2059
    {
 
2060
        /* allocate writable entries */
 
2061
        ppix = pixels;
 
2062
        ent = pentFirst;
 
2063
        pixel = 0;
 
2064
        while (--count >= 0)
 
2065
        {
 
2066
            /* Just find count unallocated cells */
 
2067
            while (ent->refcnt)
 
2068
            {
 
2069
                ent++;
 
2070
                pixel++;
 
2071
            }
 
2072
            ent->refcnt = AllocPrivate;
 
2073
            *ppix++ = pixel;
 
2074
            ent->fShared = FALSE;
 
2075
        }
 
2076
        *pMask = 0;
 
2077
        return (TRUE);
 
2078
    }
 
2079
    else if (planes > dplanes)
 
2080
    {
 
2081
        return (FALSE);
 
2082
    }
 
2083
 
 
2084
    /* General case count pixels * 2 ^ planes cells to be allocated */
 
2085
 
 
2086
    /* make room for new pixels */
 
2087
    ent = pentFirst;
 
2088
 
 
2089
    /* first try for contiguous planes, since it's fastest */
 
2090
    for (mask = (((Pixel)1) << planes) - 1, base = 1, dplanes -= (planes - 1);
 
2091
         --dplanes >= 0;
 
2092
         mask += mask, base += base)
 
2093
    {
 
2094
        ppix = pixels;
 
2095
        found = 0;
 
2096
        pixel = 0;
 
2097
        entries = pmap->pVisual->ColormapEntries - mask;
 
2098
        while (pixel < entries)
 
2099
        {
 
2100
            save = pixel;
 
2101
            maxp = pixel + mask + base;
 
2102
            /* check if all are free */
 
2103
            while (pixel != maxp && ent[pixel].refcnt == 0)
 
2104
                pixel += base;
 
2105
            if (pixel == maxp)
 
2106
                {
 
2107
                    /* this one works */
 
2108
                    *ppix++ = save;
 
2109
                    found++;
 
2110
                    if (found == count)
 
2111
                    {
 
2112
                        /* found enough, allocate them all */
 
2113
                        while (--count >= 0)
 
2114
                        {
 
2115
                            pixel = pixels[count];
 
2116
                            maxp = pixel + mask;
 
2117
                            while (1)
 
2118
                            {
 
2119
                                ent[pixel].refcnt = AllocPrivate;
 
2120
                                ent[pixel].fShared = FALSE;
 
2121
                                if (pixel == maxp)
 
2122
                                    break;
 
2123
                                pixel += base;
 
2124
                                *ppix++ = pixel;
 
2125
                            }
 
2126
                        }
 
2127
                        *pMask = mask;
 
2128
                        return (TRUE);
 
2129
                    }
 
2130
                }
 
2131
            pixel = save + 1;
 
2132
            if (pixel & mask)
 
2133
                pixel += mask;
 
2134
        }
 
2135
    }
 
2136
 
 
2137
    dplanes = pmap->pVisual->nplanes;
 
2138
    if (contig || planes == 1 || dplanes < 3)
 
2139
        return (FALSE);
 
2140
 
 
2141
    /* this will be very slow for large maps, need a better algorithm */
 
2142
 
 
2143
    /*
 
2144
       we can generate the smallest and largest numbers that fits in dplanes
 
2145
       bits and contain exactly planes bits set as follows. First, we need to
 
2146
       check that it is possible to generate such a mask at all.
 
2147
       (Non-contiguous masks need one more bit than contiguous masks). Then
 
2148
       the smallest such mask consists of the rightmost planes-1 bits set, then
 
2149
       a zero, then a one in position planes + 1. The formula is
 
2150
         (3 << (planes-1)) -1
 
2151
       The largest such masks consists of the leftmost planes-1 bits set, then
 
2152
       a zero, then a one bit in position dplanes-planes-1. If dplanes is
 
2153
       smaller than 32 (the number of bits in a word) then the formula is:
 
2154
         (1<<dplanes) - (1<<(dplanes-planes+1) + (1<<dplanes-planes-1)
 
2155
       If dplanes = 32, then we can't calculate (1<<dplanes) and we have
 
2156
       to use:
 
2157
         ( (1<<(planes-1)) - 1) << (dplanes-planes+1) + (1<<(dplanes-planes-1))
 
2158
          
 
2159
          << Thank you, Loretta>>>
 
2160
 
 
2161
    */
 
2162
 
 
2163
    finalmask =
 
2164
        (((((Pixel)1)<<(planes-1)) - 1) << (dplanes-planes+1)) +
 
2165
          (((Pixel)1)<<(dplanes-planes-1));
 
2166
    for (mask = (((Pixel)3) << (planes -1)) - 1; mask <= finalmask; mask++)
 
2167
    {
 
2168
        /* next 3 magic statements count number of ones (HAKMEM #169) */
 
2169
        pixel = (mask >> 1) & 033333333333;
 
2170
        pixel = mask - pixel - ((pixel >> 1) & 033333333333);
 
2171
        if ((((pixel + (pixel >> 3)) & 030707070707) % 077) != planes)
 
2172
            continue;
 
2173
        ppix = pixels;
 
2174
        found = 0;
 
2175
        entries = pmap->pVisual->ColormapEntries - mask;
 
2176
        base = lowbit (mask);
 
2177
        for (pixel = 0; pixel < entries; pixel++)
 
2178
        {
 
2179
            if (pixel & mask)
 
2180
                continue;
 
2181
            maxp = 0;
 
2182
            /* check if all are free */
 
2183
            while (ent[pixel + maxp].refcnt == 0)
 
2184
            {
 
2185
                GetNextBitsOrBreak(maxp, mask, base);
 
2186
            }
 
2187
            if ((maxp < mask) || (ent[pixel + mask].refcnt != 0))
 
2188
                continue;
 
2189
            /* this one works */
 
2190
            *ppix++ = pixel;
 
2191
            found++;
 
2192
            if (found < count)
 
2193
                continue;
 
2194
            /* found enough, allocate them all */
 
2195
            while (--count >= 0)
 
2196
            {
 
2197
                pixel = (pixels)[count];
 
2198
                maxp = 0;
 
2199
                while (1)
 
2200
                {
 
2201
                    ent[pixel + maxp].refcnt = AllocPrivate;
 
2202
                    ent[pixel + maxp].fShared = FALSE;
 
2203
                    GetNextBitsOrBreak(maxp, mask, base);
 
2204
                    *ppix++ = pixel + maxp;
 
2205
                }
 
2206
            }
 
2207
 
 
2208
            *pMask = mask;
 
2209
            return (TRUE);
 
2210
        }
 
2211
    }
 
2212
    return (FALSE);
 
2213
}
 
2214
 
 
2215
static Bool
 
2216
AllocShared (pmap, ppix, c, r, g, b, rmask, gmask, bmask, ppixFirst)
 
2217
    ColormapPtr pmap;
 
2218
    Pixel       *ppix;
 
2219
    int         c, r, g, b;
 
2220
    Pixel       rmask, gmask, bmask;
 
2221
    Pixel       *ppixFirst;     /* First of the client's new pixels */
 
2222
{
 
2223
    Pixel       *pptr, *cptr;
 
2224
    int         npix, z, npixClientNew, npixShared;
 
2225
    Pixel       basemask, base, bits, common;
 
2226
    SHAREDCOLOR *pshared, **ppshared, **psharedList;
 
2227
 
 
2228
    npixClientNew = c << (r + g + b);
 
2229
    npixShared = (c << r) + (c << g) + (c << b);
 
2230
    psharedList = (SHAREDCOLOR **)ALLOCATE_LOCAL(npixShared *
 
2231
                                                 sizeof(SHAREDCOLOR *));
 
2232
    if (!psharedList)
 
2233
        return FALSE;
 
2234
    ppshared = psharedList;
 
2235
    for (z = npixShared; --z >= 0; )
 
2236
    {
 
2237
        if (!(ppshared[z] = (SHAREDCOLOR *)xalloc(sizeof(SHAREDCOLOR))))
 
2238
        {
 
2239
            for (z++ ; z < npixShared; z++)
 
2240
                xfree(ppshared[z]);
 
2241
            return FALSE;
 
2242
        }
 
2243
    }
 
2244
    for(pptr = ppix, npix = c; --npix >= 0; pptr++)
 
2245
    {
 
2246
        basemask = ~(gmask | bmask);
 
2247
        common = *pptr & basemask;
 
2248
        if (rmask)
 
2249
        {
 
2250
            bits = 0;
 
2251
            base = lowbit (rmask);
 
2252
            while(1)
 
2253
            {
 
2254
                pshared = *ppshared++;
 
2255
                pshared->refcnt = 1 << (g + b);
 
2256
                for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
 
2257
                {
 
2258
                    if ((*cptr & basemask) == (common | bits))
 
2259
                    {
 
2260
                        pmap->red[*cptr].fShared = TRUE;
 
2261
                        pmap->red[*cptr].co.shco.red = pshared;
 
2262
                    }
 
2263
                }
 
2264
                GetNextBitsOrBreak(bits, rmask, base);
 
2265
            }
 
2266
        }
 
2267
        else
 
2268
        {
 
2269
            pshared = *ppshared++;
 
2270
            pshared->refcnt = 1 << (g + b);
 
2271
            for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
 
2272
            {
 
2273
                if ((*cptr & basemask) == common)
 
2274
                {
 
2275
                    pmap->red[*cptr].fShared = TRUE;
 
2276
                    pmap->red[*cptr].co.shco.red = pshared;
 
2277
                }
 
2278
            }
 
2279
        }
 
2280
        basemask = ~(rmask | bmask);
 
2281
        common = *pptr & basemask;
 
2282
        if (gmask)
 
2283
        {
 
2284
            bits = 0;
 
2285
            base = lowbit (gmask);
 
2286
            while(1)
 
2287
            {
 
2288
                pshared = *ppshared++;
 
2289
                pshared->refcnt = 1 << (r + b);
 
2290
                for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
 
2291
                {
 
2292
                    if ((*cptr & basemask) == (common | bits))
 
2293
                    {
 
2294
                        pmap->red[*cptr].co.shco.green = pshared;
 
2295
                    }
 
2296
                }
 
2297
                GetNextBitsOrBreak(bits, gmask, base);
 
2298
            }
 
2299
        }
 
2300
        else
 
2301
        {
 
2302
            pshared = *ppshared++;
 
2303
            pshared->refcnt = 1 << (g + b);
 
2304
            for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
 
2305
            {
 
2306
                if ((*cptr & basemask) == common)
 
2307
                {
 
2308
                    pmap->red[*cptr].co.shco.green = pshared;
 
2309
                }
 
2310
            }
 
2311
        }
 
2312
        basemask = ~(rmask | gmask);
 
2313
        common = *pptr & basemask;
 
2314
        if (bmask)
 
2315
        {
 
2316
            bits = 0;
 
2317
            base = lowbit (bmask);
 
2318
            while(1)
 
2319
            {
 
2320
                pshared = *ppshared++;
 
2321
                pshared->refcnt = 1 << (r + g);
 
2322
                for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
 
2323
                {
 
2324
                    if ((*cptr & basemask) == (common | bits))
 
2325
                    {
 
2326
                        pmap->red[*cptr].co.shco.blue = pshared;
 
2327
                    }
 
2328
                }
 
2329
                GetNextBitsOrBreak(bits, bmask, base);
 
2330
            }
 
2331
        }
 
2332
        else
 
2333
        {
 
2334
            pshared = *ppshared++;
 
2335
            pshared->refcnt = 1 << (g + b);
 
2336
            for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
 
2337
            {
 
2338
                if ((*cptr & basemask) == common)
 
2339
                {
 
2340
                    pmap->red[*cptr].co.shco.blue = pshared;
 
2341
                }
 
2342
            }
 
2343
        }
 
2344
    }
 
2345
    DEALLOCATE_LOCAL(psharedList);
 
2346
    return TRUE;
 
2347
}
 
2348
 
 
2349
 
 
2350
/* Free colors and/or cells (probably slow for large numbers) */
 
2351
 
 
2352
int
 
2353
FreeColors (pmap, client, count, pixels, mask)
 
2354
    ColormapPtr pmap;
 
2355
    int         client, count;
 
2356
    Pixel       *pixels;
 
2357
    Pixel       mask;
 
2358
{
 
2359
    int         rval, result, class;
 
2360
    Pixel       rmask;
 
2361
 
 
2362
    class = pmap->class;
 
2363
    if (pmap->flags & AllAllocated)
 
2364
        return(BadAccess);
 
2365
    if ((class | DynamicClass) == DirectColor)
 
2366
    {
 
2367
        rmask = mask & RGBMASK(pmap->pVisual);
 
2368
        result = FreeCo(pmap, client, REDMAP, count, pixels,
 
2369
                        mask & pmap->pVisual->redMask);
 
2370
        /* If any of the three calls fails, we must report that, if more
 
2371
         * than one fails, it's ok that we report the last one */
 
2372
        rval = FreeCo(pmap, client, GREENMAP, count, pixels,
 
2373
                      mask & pmap->pVisual->greenMask);
 
2374
        if(rval != Success)
 
2375
            result = rval;
 
2376
        rval = FreeCo(pmap, client, BLUEMAP, count, pixels,
 
2377
                      mask & pmap->pVisual->blueMask);
 
2378
        if(rval != Success)
 
2379
            result = rval;
 
2380
    }
 
2381
    else
 
2382
    {
 
2383
        rmask = mask & ((((Pixel)1) << pmap->pVisual->nplanes) - 1);
 
2384
        result = FreeCo(pmap, client, PSEUDOMAP, count, pixels, rmask);
 
2385
    }
 
2386
    if ((mask != rmask) && count)
 
2387
    {
 
2388
        clientErrorValue = *pixels | mask;
 
2389
        result = BadValue;
 
2390
    }
 
2391
    /* XXX should worry about removing any RT_CMAPENTRY resource */
 
2392
    return (result);
 
2393
}
 
2394
 
 
2395
/* Helper for FreeColors -- frees all combinations of *newpixels and mask bits
 
2396
 * which the client has allocated in channel colormap cells of pmap.
 
2397
 * doesn't change newpixels if it doesn't need to */
 
2398
static int
 
2399
FreeCo (pmap, client, color, npixIn, ppixIn, mask)
 
2400
    ColormapPtr pmap;           /* which colormap head */
 
2401
    int         client;         
 
2402
    int         color;          /* which sub-map, eg RED, BLUE, PSEUDO */
 
2403
    int         npixIn;         /* number of pixels passed in */
 
2404
    Pixel       *ppixIn;        /* list of base pixels */
 
2405
    Pixel       mask;           /* mask client gave us */ 
 
2406
{
 
2407
 
 
2408
    Pixel       *ppixClient, pixTest;
 
2409
    int         npixClient, npixNew, npix;
 
2410
    Pixel       bits, base, cmask, rgbbad;
 
2411
    Pixel       *pptr, *cptr;
 
2412
    int         n, zapped;
 
2413
    int         errVal = Success;
 
2414
    int         offset, numents;
 
2415
#ifdef LBX
 
2416
    Bool        grabbed;
 
2417
    Bool        zeroRefCount;
 
2418
    Bool        anyRefCountReachedZero = 0;
 
2419
#endif
 
2420
 
 
2421
    if (npixIn == 0)
 
2422
        return (errVal);
 
2423
    bits = 0;
 
2424
    zapped = 0;
 
2425
    base = lowbit (mask);
 
2426
 
 
2427
    switch(color)
 
2428
    {
 
2429
      case REDMAP:
 
2430
        cmask = pmap->pVisual->redMask;
 
2431
        rgbbad = ~RGBMASK(pmap->pVisual);
 
2432
        offset = pmap->pVisual->offsetRed;
 
2433
        numents = (cmask >> offset) + 1;
 
2434
        ppixClient = pmap->clientPixelsRed[client];
 
2435
        npixClient = pmap->numPixelsRed[client];
 
2436
        break;
 
2437
      case GREENMAP:
 
2438
        cmask = pmap->pVisual->greenMask;
 
2439
        rgbbad = ~RGBMASK(pmap->pVisual);
 
2440
        offset = pmap->pVisual->offsetGreen;
 
2441
        numents = (cmask >> offset) + 1;
 
2442
        ppixClient = pmap->clientPixelsGreen[client];
 
2443
        npixClient = pmap->numPixelsGreen[client];
 
2444
        break;
 
2445
      case BLUEMAP:
 
2446
        cmask = pmap->pVisual->blueMask;
 
2447
        rgbbad = ~RGBMASK(pmap->pVisual);
 
2448
        offset = pmap->pVisual->offsetBlue;
 
2449
        numents = (cmask >> offset) + 1;
 
2450
        ppixClient = pmap->clientPixelsBlue[client];
 
2451
        npixClient = pmap->numPixelsBlue[client];
 
2452
        break;
 
2453
      default:  /* so compiler can see that everything gets initialized */
 
2454
      case PSEUDOMAP:
 
2455
        cmask = ~((Pixel)0);
 
2456
        rgbbad = 0;
 
2457
        offset = 0;
 
2458
        numents = pmap->pVisual->ColormapEntries;
 
2459
        ppixClient = pmap->clientPixelsRed[client];
 
2460
        npixClient = pmap->numPixelsRed[client];
 
2461
        break;
 
2462
    }
 
2463
 
 
2464
#ifdef LBX
 
2465
    grabbed = LbxCheckCmapGrabbed (pmap);
 
2466
 
 
2467
    if (grabbed)
 
2468
    {
 
2469
        /*
 
2470
         * If the colormap is grabbed by a proxy, the server must
 
2471
         * notify the proxy of all cells that are freed (the refcount
 
2472
         * has reached zero on these cells).
 
2473
         */
 
2474
 
 
2475
        LbxBeginFreeCellsEvent (pmap);
 
2476
        LbxSortPixelList (ppixIn, npixIn);
 
2477
    }
 
2478
#endif
 
2479
 
 
2480
    /* zap all pixels which match */
 
2481
    while (1)
 
2482
    {
 
2483
        /* go through pixel list */
 
2484
        for (pptr = ppixIn, n = npixIn; --n >= 0; pptr++)
 
2485
        {
 
2486
            pixTest = ((*pptr | bits) & cmask) >> offset;
 
2487
            if ((pixTest >= numents) || (*pptr & rgbbad))
 
2488
            {
 
2489
                clientErrorValue = *pptr | bits;
 
2490
                errVal = BadValue;
 
2491
                continue;
 
2492
            }
 
2493
 
 
2494
            /* find match in client list */
 
2495
            for (cptr = ppixClient, npix = npixClient;
 
2496
                 --npix >= 0 && *cptr != pixTest;
 
2497
                 cptr++) ;
 
2498
 
 
2499
            if (npix >= 0)
 
2500
            {
 
2501
                if (pmap->class & DynamicClass)
 
2502
                {
 
2503
                    FreeCell(pmap, pixTest, color);
 
2504
#ifdef LBX
 
2505
                    /*
 
2506
                     * Only PSEUDO colormaps are grabbed by LBX proxies.
 
2507
                     * Check if the ref count reached zero on this pixel.
 
2508
                     */
 
2509
 
 
2510
                    zeroRefCount = pmap->red[pixTest].refcnt == 0;
 
2511
                    if (zeroRefCount)
 
2512
                        anyRefCountReachedZero = 1;
 
2513
 
 
2514
                    if (grabbed && zeroRefCount)
 
2515
                        LbxAddFreeCellToEvent (pmap, pixTest);
 
2516
#endif
 
2517
                }
 
2518
                *cptr = ~((Pixel)0);
 
2519
                zapped++;
 
2520
            }
 
2521
            else
 
2522
                errVal = BadAccess;
 
2523
        }
 
2524
        /* generate next bits value */
 
2525
        GetNextBitsOrBreak(bits, mask, base);
 
2526
    }
 
2527
 
 
2528
#ifdef LBX
 
2529
    if (grabbed)
 
2530
        LbxEndFreeCellsEvent (pmap);
 
2531
    else if (anyRefCountReachedZero)
 
2532
    {
 
2533
        /*
 
2534
         * We only send LbxFreeCell events to a proxy that has the colormap
 
2535
         * grabbed.  If the colormap is not grabbed, the proxy that last
 
2536
         * had the colormap grabbed will not be able to do a smart grab
 
2537
         * in the future.  A smart grab can only occur if the proxy is kept
 
2538
         * up to date on every alloc/free change in the colormap.
 
2539
         */
 
2540
        
 
2541
        LbxDisableSmartGrab (pmap);
 
2542
    }
 
2543
#endif
 
2544
 
 
2545
    /* delete freed pixels from client pixel list */
 
2546
    if (zapped)
 
2547
    {
 
2548
        npixNew = npixClient - zapped;
 
2549
        if (npixNew)
 
2550
        {
 
2551
            /* Since the list can only get smaller, we can do a copy in
 
2552
             * place and then realloc to a smaller size */
 
2553
            pptr = cptr = ppixClient;
 
2554
 
 
2555
            /* If we have all the new pixels, we don't have to examine the
 
2556
             * rest of the old ones */
 
2557
            for(npix = 0; npix < npixNew; cptr++)
 
2558
            {
 
2559
                if (*cptr != ~((Pixel)0))
 
2560
                {
 
2561
                    *pptr++ = *cptr;
 
2562
                    npix++;
 
2563
                }
 
2564
            }
 
2565
            pptr = (Pixel *)xrealloc(ppixClient, npixNew * sizeof(Pixel));
 
2566
            if (pptr)
 
2567
                ppixClient = pptr;
 
2568
            npixClient = npixNew;
 
2569
        }
 
2570
        else
 
2571
        {
 
2572
            npixClient = 0;
 
2573
            xfree(ppixClient);
 
2574
            ppixClient = (Pixel *)NULL;
 
2575
        }
 
2576
        switch(color)
 
2577
        {
 
2578
          case PSEUDOMAP:
 
2579
          case REDMAP:
 
2580
            pmap->clientPixelsRed[client] = ppixClient;
 
2581
            pmap->numPixelsRed[client] = npixClient;
 
2582
            break;
 
2583
          case GREENMAP:
 
2584
            pmap->clientPixelsGreen[client] = ppixClient;
 
2585
            pmap->numPixelsGreen[client] = npixClient;
 
2586
            break;
 
2587
          case BLUEMAP:
 
2588
            pmap->clientPixelsBlue[client] = ppixClient;
 
2589
            pmap->numPixelsBlue[client] = npixClient;
 
2590
            break;
 
2591
        }
 
2592
    }
 
2593
    return (errVal);
 
2594
}
 
2595
 
 
2596
 
 
2597
 
 
2598
/* Redefine color values */
 
2599
int
 
2600
StoreColors (pmap, count, defs)
 
2601
    ColormapPtr pmap;
 
2602
    int         count;
 
2603
    xColorItem  *defs;
 
2604
{
 
2605
    register Pixel      pix;
 
2606
    register xColorItem *pdef;
 
2607
    register EntryPtr   pent, pentT, pentLast;
 
2608
    register VisualPtr  pVisual;
 
2609
    SHAREDCOLOR         *pred, *pgreen, *pblue;
 
2610
    int                 n, ChgRed, ChgGreen, ChgBlue, idef;
 
2611
    int                 class, errVal = Success;
 
2612
    int                 ok;
 
2613
 
 
2614
 
 
2615
    class = pmap->class;
 
2616
    if(!(class & DynamicClass) && !(pmap->flags & BeingCreated))
 
2617
    {
 
2618
        return(BadAccess);
 
2619
    }
 
2620
    pVisual = pmap->pVisual;
 
2621
 
 
2622
    idef = 0;
 
2623
    if((class | DynamicClass) == DirectColor)
 
2624
    {
 
2625
        int numred, numgreen, numblue;
 
2626
        Pixel rgbbad;
 
2627
 
 
2628
        numred = NUMRED(pVisual);
 
2629
        numgreen = NUMGREEN(pVisual);
 
2630
        numblue = NUMBLUE(pVisual);
 
2631
        rgbbad = ~RGBMASK(pVisual);
 
2632
        for (pdef = defs, n = 0; n < count; pdef++, n++)
 
2633
        {
 
2634
            ok = TRUE;
 
2635
            (*pmap->pScreen->ResolveColor)
 
2636
                (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
 
2637
 
 
2638
            if (pdef->pixel & rgbbad)
 
2639
            {
 
2640
                errVal = BadValue;
 
2641
                clientErrorValue = pdef->pixel;
 
2642
                continue;
 
2643
            }
 
2644
            pix = (pdef->pixel & pVisual->redMask) >> pVisual->offsetRed;
 
2645
            if (pix >= numred)
 
2646
            {
 
2647
                errVal = BadValue;
 
2648
                ok = FALSE;
 
2649
            }
 
2650
            else if (pmap->red[pix].refcnt != AllocPrivate)
 
2651
            {
 
2652
                errVal = BadAccess;
 
2653
                ok = FALSE;
 
2654
            }
 
2655
            else if (pdef->flags & DoRed)
 
2656
            {
 
2657
                pmap->red[pix].co.local.red = pdef->red;
 
2658
            }
 
2659
            else
 
2660
            {
 
2661
                pdef->red = pmap->red[pix].co.local.red;
 
2662
            }
 
2663
 
 
2664
            pix = (pdef->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
 
2665
            if (pix >= numgreen)
 
2666
            {
 
2667
                errVal = BadValue;
 
2668
                ok = FALSE;
 
2669
            }
 
2670
            else if (pmap->green[pix].refcnt != AllocPrivate)
 
2671
            {
 
2672
                errVal = BadAccess;
 
2673
                ok = FALSE;
 
2674
            }
 
2675
            else if (pdef->flags & DoGreen)
 
2676
            {
 
2677
                pmap->green[pix].co.local.green = pdef->green;
 
2678
            }
 
2679
            else
 
2680
            {
 
2681
                pdef->green = pmap->green[pix].co.local.green;
 
2682
            }
 
2683
 
 
2684
            pix = (pdef->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
 
2685
            if (pix >= numblue)
 
2686
            {
 
2687
                errVal = BadValue;
 
2688
                ok = FALSE;
 
2689
            }
 
2690
            else if (pmap->blue[pix].refcnt != AllocPrivate)
 
2691
            {
 
2692
                errVal = BadAccess;
 
2693
                ok = FALSE;
 
2694
            }
 
2695
            else if (pdef->flags & DoBlue)
 
2696
            {
 
2697
                pmap->blue[pix].co.local.blue = pdef->blue;
 
2698
            }
 
2699
            else
 
2700
            {
 
2701
                pdef->blue = pmap->blue[pix].co.local.blue;
 
2702
            }
 
2703
            /* If this is an o.k. entry, then it gets added to the list
 
2704
             * to be sent to the hardware.  If not, skip it.  Once we've
 
2705
             * skipped one, we have to copy all the others.
 
2706
             */
 
2707
            if(ok)
 
2708
            {
 
2709
                if(idef != n)
 
2710
                    defs[idef] = defs[n];
 
2711
                idef++;
 
2712
            } else
 
2713
                clientErrorValue = pdef->pixel;
 
2714
        }
 
2715
    }
 
2716
    else
 
2717
    {
 
2718
        for (pdef = defs, n = 0; n < count; pdef++, n++)
 
2719
        {
 
2720
 
 
2721
            ok = TRUE;
 
2722
            if (pdef->pixel >= pVisual->ColormapEntries)
 
2723
            {
 
2724
                clientErrorValue = pdef->pixel;
 
2725
                errVal = BadValue;
 
2726
                ok = FALSE;
 
2727
            }
 
2728
            else if (pmap->red[pdef->pixel].refcnt != AllocPrivate)
 
2729
            {
 
2730
                errVal = BadAccess;
 
2731
                ok = FALSE;
 
2732
            }
 
2733
 
 
2734
            /* If this is an o.k. entry, then it gets added to the list
 
2735
             * to be sent to the hardware.  If not, skip it.  Once we've
 
2736
             * skipped one, we have to copy all the others.
 
2737
             */
 
2738
            if(ok)
 
2739
            {
 
2740
                if(idef != n)
 
2741
                    defs[idef] = defs[n];
 
2742
                idef++;
 
2743
            }
 
2744
            else
 
2745
                continue;
 
2746
 
 
2747
            (*pmap->pScreen->ResolveColor)
 
2748
                (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
 
2749
 
 
2750
            pent = &pmap->red[pdef->pixel];
 
2751
 
 
2752
            if(pdef->flags & DoRed)
 
2753
            {
 
2754
                if(pent->fShared)
 
2755
                {
 
2756
                    pent->co.shco.red->color = pdef->red;
 
2757
                    if (pent->co.shco.red->refcnt > 1)
 
2758
                        ok = FALSE;
 
2759
                }
 
2760
                else
 
2761
                    pent->co.local.red = pdef->red;
 
2762
            }
 
2763
            else
 
2764
            {
 
2765
                if(pent->fShared)
 
2766
                    pdef->red = pent->co.shco.red->color;
 
2767
                else
 
2768
                    pdef->red = pent->co.local.red;
 
2769
            }
 
2770
            if(pdef->flags & DoGreen)
 
2771
            {
 
2772
                if(pent->fShared)
 
2773
                {
 
2774
                    pent->co.shco.green->color = pdef->green;
 
2775
                    if (pent->co.shco.green->refcnt > 1)
 
2776
                        ok = FALSE;
 
2777
                }
 
2778
                else
 
2779
                    pent->co.local.green = pdef->green;
 
2780
            }
 
2781
            else
 
2782
            {
 
2783
                if(pent->fShared)
 
2784
                    pdef->green = pent->co.shco.green->color;
 
2785
                else
 
2786
                    pdef->green = pent->co.local.green;
 
2787
            }
 
2788
            if(pdef->flags & DoBlue)
 
2789
            {
 
2790
                if(pent->fShared)
 
2791
                {
 
2792
                    pent->co.shco.blue->color = pdef->blue;
 
2793
                    if (pent->co.shco.blue->refcnt > 1)
 
2794
                        ok = FALSE;
 
2795
                }
 
2796
                else
 
2797
                    pent->co.local.blue = pdef->blue;
 
2798
            }
 
2799
            else
 
2800
            {
 
2801
                if(pent->fShared)
 
2802
                    pdef->blue = pent->co.shco.blue->color;
 
2803
                else
 
2804
                    pdef->blue = pent->co.local.blue;
 
2805
            }
 
2806
 
 
2807
            if(!ok)
 
2808
            {
 
2809
                /* have to run through the colormap and change anybody who
 
2810
                 * shares this value */
 
2811
                pred = pent->co.shco.red;
 
2812
                pgreen = pent->co.shco.green;
 
2813
                pblue = pent->co.shco.blue;
 
2814
                ChgRed = pdef->flags & DoRed;
 
2815
                ChgGreen = pdef->flags & DoGreen;
 
2816
                ChgBlue = pdef->flags & DoBlue;
 
2817
                pentLast = pmap->red + pVisual->ColormapEntries;
 
2818
 
 
2819
                for(pentT = pmap->red; pentT < pentLast; pentT++)
 
2820
                {
 
2821
                    if(pentT->fShared && (pentT != pent))
 
2822
                    {
 
2823
                        xColorItem      defChg;
 
2824
 
 
2825
                        /* There are, alas, devices in this world too dumb
 
2826
                         * to read their own hardware colormaps.  Sick, but
 
2827
                         * true.  So we're going to be really nice and load
 
2828
                         * the xColorItem with the proper value for all the
 
2829
                         * fields.  We will only set the flags for those
 
2830
                         * fields that actually change.  Smart devices can
 
2831
                         * arrange to change only those fields.  Dumb devices
 
2832
                         * can rest assured that we have provided for them,
 
2833
                         * and can change all three fields */
 
2834
 
 
2835
                        defChg.flags = 0;
 
2836
                        if(ChgRed && pentT->co.shco.red == pred)
 
2837
                        {
 
2838
                            defChg.flags |= DoRed;
 
2839
                        }
 
2840
                        if(ChgGreen && pentT->co.shco.green == pgreen)
 
2841
                        {
 
2842
                            defChg.flags |= DoGreen;
 
2843
                        }
 
2844
                        if(ChgBlue && pentT->co.shco.blue == pblue)
 
2845
                        {
 
2846
                            defChg.flags |= DoBlue;
 
2847
                        }
 
2848
                        if(defChg.flags != 0)
 
2849
                        {
 
2850
                            defChg.pixel = pentT - pmap->red;
 
2851
                            defChg.red = pentT->co.shco.red->color;
 
2852
                            defChg.green = pentT->co.shco.green->color;
 
2853
                            defChg.blue = pentT->co.shco.blue->color;
 
2854
                            (*pmap->pScreen->StoreColors) (pmap, 1, &defChg);
 
2855
                        }
 
2856
                    }
 
2857
                }
 
2858
 
 
2859
            }
 
2860
        }
 
2861
    }
 
2862
    /* Note that we use idef, the count of acceptable entries, and not
 
2863
     * count, the count of proposed entries */
 
2864
    if (idef != 0)
 
2865
        ( *pmap->pScreen->StoreColors) (pmap, idef, defs);
 
2866
    return (errVal);
 
2867
}
 
2868
 
 
2869
int
 
2870
IsMapInstalled(map, pWin)
 
2871
    Colormap    map;
 
2872
    WindowPtr   pWin;
 
2873
{
 
2874
    Colormap    *pmaps;
 
2875
    int         imap, nummaps, found;
 
2876
 
 
2877
    pmaps = (Colormap *) ALLOCATE_LOCAL( 
 
2878
             pWin->drawable.pScreen->maxInstalledCmaps * sizeof(Colormap));
 
2879
    if(!pmaps)
 
2880
        return(FALSE);
 
2881
    nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
 
2882
        (pWin->drawable.pScreen, pmaps);
 
2883
    found = FALSE;
 
2884
    for(imap = 0; imap < nummaps; imap++)
 
2885
    {
 
2886
        if(pmaps[imap] == map)
 
2887
        {
 
2888
            found = TRUE;
 
2889
            break;
 
2890
        }
 
2891
    }
 
2892
    DEALLOCATE_LOCAL(pmaps);
 
2893
    return (found);
 
2894
}