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