+++ /dev/null
-/***********************************************************
-
-Copyright (c) 1987 X Consortium
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of the X Consortium shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from the X Consortium.
-
-
-Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
-
- All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
-provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
-supporting documentation, and that the name of Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
-ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
-WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
-ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
-SOFTWARE.
-
-******************************************************************/
-
-/* $XConsortium: colormap.c /main/71 1996/06/17 11:01:33 mor $ */
-/* $XFree86: xc/programs/Xserver/dix/colormap.c,v 3.1 1996/12/23 06:29:34 dawes Exp $ */
-
-#include "X.h"
-#define NEED_EVENTS
-#include "Xproto.h"
-#include "misc.h"
-#include "dix.h"
-#include "colormapst.h"
-#include "os.h"
-#include "scrnintstr.h"
-#include "resource.h"
-#include "windowstr.h"
-
-extern XID clientErrorValue;
-
-static Pixel FindBestPixel(
-#if NeedFunctionPrototypes
- EntryPtr /*pentFirst*/,
- int /*size*/,
- xrgb * /*prgb*/,
- int /*channel*/
-#endif
-);
-
-static int AllComp(
-#if NeedFunctionPrototypes
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-#endif
-);
-
-static int RedComp(
-#if NeedFunctionPrototypes
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-#endif
-);
-
-static int GreenComp(
-#if NeedFunctionPrototypes
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-#endif
-);
-
-static int BlueComp(
-#if NeedFunctionPrototypes
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-#endif
-);
-
-static void FreePixels(
-#if NeedFunctionPrototypes
- register ColormapPtr /*pmap*/,
- register int /*client*/
-#endif
-);
-
-static void CopyFree(
-#if NeedFunctionPrototypes
- int /*channel*/,
- int /*client*/,
- ColormapPtr /*pmapSrc*/,
- ColormapPtr /*pmapDst*/
-#endif
-);
-
-static void FreeCell(
-#if NeedFunctionPrototypes
- ColormapPtr /*pmap*/,
- Pixel /*i*/,
- int /*channel*/
-#endif
-);
-
-static void UpdateColors(
-#if NeedFunctionPrototypes
- ColormapPtr /*pmap*/
-#endif
-);
-
-static int AllocDirect(
-#if NeedFunctionPrototypes
- int /*client*/,
- ColormapPtr /*pmap*/,
- int /*c*/,
- int /*r*/,
- int /*g*/,
- int /*b*/,
- Bool /*contig*/,
- Pixel * /*pixels*/,
- Pixel * /*prmask*/,
- Pixel * /*pgmask*/,
- Pixel * /*pbmask*/
-#endif
-);
-
-static int AllocPseudo(
-#if NeedFunctionPrototypes
- int /*client*/,
- ColormapPtr /*pmap*/,
- int /*c*/,
- int /*r*/,
- Bool /*contig*/,
- Pixel * /*pixels*/,
- Pixel * /*pmask*/,
- Pixel ** /*pppixFirst*/
-#endif
-);
-
-static Bool AllocCP(
-#if NeedFunctionPrototypes
- ColormapPtr /*pmap*/,
- EntryPtr /*pentFirst*/,
- int /*count*/,
- int /*planes*/,
- Bool /*contig*/,
- Pixel * /*pixels*/,
- Pixel * /*pMask*/
-#endif
-);
-
-static Bool AllocShared(
-#if NeedFunctionPrototypes
- ColormapPtr /*pmap*/,
- Pixel * /*ppix*/,
- int /*c*/,
- int /*r*/,
- int /*g*/,
- int /*b*/,
- Pixel /*rmask*/,
- Pixel /*gmask*/,
- Pixel /*bmask*/,
- Pixel * /*ppixFirst*/
-#endif
-);
-
-static int FreeCo(
-#if NeedFunctionPrototypes
- ColormapPtr /*pmap*/,
- int /*client*/,
- int /*color*/,
- int /*npixIn*/,
- Pixel * /*ppixIn*/,
- Pixel /*mask*/
-#endif
-);
-
-static int TellNoMap(
-#if NeedFunctionPrototypes
- WindowPtr /*pwin*/,
- Colormap * /*pmid*/
-#endif
-);
-
-#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
-#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
-#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1)
-#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask)
-
-/* GetNextBitsOrBreak(bits, mask, base) --
- * (Suggestion: First read the macro, then read this explanation.
- *
- * Either generate the next value to OR in to a pixel or break out of this
- * while loop
- *
- * This macro is used when we're trying to generate all 2^n combinations of
- * bits in mask. What we're doing here is counting in binary, except that
- * the bits we use to count may not be contiguous. This macro will be
- * called 2^n times, returning a different value in bits each time. Then
- * it will cause us to break out of a surrounding loop. (It will always be
- * called from within a while loop.)
- * On call: mask is the value we want to find all the combinations for
- * base has 1 bit set where the least significant bit of mask is set
- *
- * For example,if mask is 01010, base should be 0010 and we count like this:
- * 00010 (see this isn't so hard),
- * then we add base to bits and get 0100. (bits & ~mask) is (0100 & 0100) so
- * we add that to bits getting (0100 + 0100) =
- * 01000 for our next value.
- * then we add 0010 to get
- * 01010 and we're done (easy as 1, 2, 3)
- */
-#define GetNextBitsOrBreak(bits, mask, base) \
- if((bits) == (mask)) \
- break; \
- (bits) += (base); \
- while((bits) & ~(mask)) \
- (bits) += ((bits) & ~(mask));
-/* ID of server as client */
-#define SERVER_ID 0
-
-typedef struct _colorResource
-{
- Colormap mid;
- int client;
-} colorResource;
-
-/* Invariants:
- * refcnt == 0 means entry is empty
- * refcnt > 0 means entry is useable by many clients, so it can't be changed
- * refcnt == AllocPrivate means entry owned by one client only
- * fShared should only be set if refcnt == AllocPrivate, and only in red map
- */
-
-
-/* Create and initialize the color map */
-int
-CreateColormap (mid, pScreen, pVisual, ppcmap, alloc, client)
- Colormap mid; /* resource to use for this colormap */
- ScreenPtr pScreen;
- VisualPtr pVisual;
- ColormapPtr *ppcmap;
- int alloc; /* 1 iff all entries are allocated writeable */
- int client;
-{
- int class, size;
- unsigned long sizebytes;
- ColormapPtr pmap;
- register EntryPtr pent;
- int i;
- register Pixel *ppix, **pptr;
- extern int colormapPrivateCount;
-
- class = pVisual->class;
- if(!(class & DynamicClass) && (alloc != AllocNone) && (client != SERVER_ID))
- return (BadMatch);
-
- size = pVisual->ColormapEntries;
- sizebytes = (size * sizeof(Entry)) +
- (MAXCLIENTS * sizeof(Pixel *)) +
- (MAXCLIENTS * sizeof(int));
- if ((class | DynamicClass) == DirectColor)
- sizebytes *= 3;
- sizebytes += sizeof(ColormapRec);
- pmap = (ColormapPtr) xalloc(sizebytes);
- if (!pmap)
- return (BadAlloc);
- pmap->red = (EntryPtr)((char *)pmap + sizeof(ColormapRec));
- sizebytes = size * sizeof(Entry);
- pmap->clientPixelsRed = (Pixel **)((char *)pmap->red + sizebytes);
- pmap->numPixelsRed = (int *)((char *)pmap->clientPixelsRed +
- (MAXCLIENTS * sizeof(Pixel *)));
- pmap->mid = mid;
- pmap->flags = 0; /* start out with all flags clear */
- if(mid == pScreen->defColormap)
- pmap->flags |= IsDefault;
- pmap->pScreen = pScreen;
- pmap->pVisual = pVisual;
- pmap->class = class;
- if ((class | DynamicClass) == DirectColor)
- size = NUMRED(pVisual);
- pmap->freeRed = size;
- bzero ((char *) pmap->red, (int)sizebytes);
- bzero((char *) pmap->numPixelsRed, MAXCLIENTS * sizeof(int));
- for (pptr = &pmap->clientPixelsRed[MAXCLIENTS]; --pptr >= pmap->clientPixelsRed; )
- *pptr = (Pixel *)NULL;
- if (alloc == AllocAll)
- {
- if (class & DynamicClass)
- pmap->flags |= AllAllocated;
- for (pent = &pmap->red[size - 1]; pent >= pmap->red; pent--)
- pent->refcnt = AllocPrivate;
- pmap->freeRed = 0;
- ppix = (Pixel *)xalloc(size * sizeof(Pixel));
- if (!ppix)
- {
- xfree(pmap);
- return (BadAlloc);
- }
- pmap->clientPixelsRed[client] = ppix;
- for(i = 0; i < size; i++)
- ppix[i] = i;
- pmap->numPixelsRed[client] = size;
- }
-
- if ((class | DynamicClass) == DirectColor)
- {
- pmap->freeGreen = NUMGREEN(pVisual);
- pmap->green = (EntryPtr)((char *)pmap->numPixelsRed +
- (MAXCLIENTS * sizeof(int)));
- pmap->clientPixelsGreen = (Pixel **)((char *)pmap->green + sizebytes);
- pmap->numPixelsGreen = (int *)((char *)pmap->clientPixelsGreen +
- (MAXCLIENTS * sizeof(Pixel *)));
- pmap->freeBlue = NUMBLUE(pVisual);
- pmap->blue = (EntryPtr)((char *)pmap->numPixelsGreen +
- (MAXCLIENTS * sizeof(int)));
- pmap->clientPixelsBlue = (Pixel **)((char *)pmap->blue + sizebytes);
- pmap->numPixelsBlue = (int *)((char *)pmap->clientPixelsBlue +
- (MAXCLIENTS * sizeof(Pixel *)));
-
- bzero ((char *) pmap->green, (int)sizebytes);
- bzero ((char *) pmap->blue, (int)sizebytes);
-
- memmove((char *) pmap->clientPixelsGreen,
- (char *) pmap->clientPixelsRed,
- MAXCLIENTS * sizeof(Pixel *));
- memmove((char *) pmap->clientPixelsBlue,
- (char *) pmap->clientPixelsRed,
- MAXCLIENTS * sizeof(Pixel *));
- bzero((char *) pmap->numPixelsGreen, MAXCLIENTS * sizeof(int));
- bzero((char *) pmap->numPixelsBlue, MAXCLIENTS * sizeof(int));
-
- /* If every cell is allocated, mark its refcnt */
- if (alloc == AllocAll)
- {
- size = pmap->freeGreen;
- for(pent = &pmap->green[size-1]; pent >= pmap->green; pent--)
- pent->refcnt = AllocPrivate;
- pmap->freeGreen = 0;
- ppix = (Pixel *) xalloc(size * sizeof(Pixel));
- if (!ppix)
- {
- xfree(pmap->clientPixelsRed[client]);
- xfree(pmap);
- return(BadAlloc);
- }
- pmap->clientPixelsGreen[client] = ppix;
- for(i = 0; i < size; i++)
- ppix[i] = i;
- pmap->numPixelsGreen[client] = size;
-
- size = pmap->freeBlue;
- for(pent = &pmap->blue[size-1]; pent >= pmap->blue; pent--)
- pent->refcnt = AllocPrivate;
- pmap->freeBlue = 0;
- ppix = (Pixel *) xalloc(size * sizeof(Pixel));
- if (!ppix)
- {
- xfree(pmap->clientPixelsGreen[client]);
- xfree(pmap->clientPixelsRed[client]);
- xfree(pmap);
- return(BadAlloc);
- }
- pmap->clientPixelsBlue[client] = ppix;
- for(i = 0; i < size; i++)
- ppix[i] = i;
- pmap->numPixelsBlue[client] = size;
- }
- }
- if (!AddResource(mid, RT_COLORMAP, (pointer)pmap))
- return (BadAlloc);
- /* If the device wants a chance to initialize the colormap in any way,
- * this is it. In specific, if this is a Static colormap, this is the
- * time to fill in the colormap's values */
- pmap->flags |= BeingCreated;
-
-
- /*
- * Allocate the array of devPrivate's for this colormap.
- */
-
- if (colormapPrivateCount == 0)
- pmap->devPrivates = NULL;
- else
- {
- pmap->devPrivates = (DevUnion *) xalloc (
- colormapPrivateCount * sizeof(DevUnion));
-
- if (!pmap->devPrivates)
- {
- FreeResource (mid, RT_NONE);
- return BadAlloc;
- }
- }
-
- if (!(*pScreen->CreateColormap)(pmap))
- {
- FreeResource (mid, RT_NONE);
- return BadAlloc;
- }
- pmap->flags &= ~BeingCreated;
- *ppcmap = pmap;
- return (Success);
-}
-
-int
-FreeColormap (value, mid)
- pointer value; /* must conform to DeleteType */
- XID mid;
-{
- int i;
- register EntryPtr pent;
- ColormapPtr pmap = (ColormapPtr)value;
-
- if(CLIENT_ID(mid) != SERVER_ID)
- {
- (*pmap->pScreen->UninstallColormap) (pmap);
- WalkTree(pmap->pScreen, (VisitWindowProcPtr)TellNoMap, (pointer) &mid);
- }
-
- /* This is the device's chance to undo anything it needs to, especially
- * to free any storage it allocated */
- (*pmap->pScreen->DestroyColormap)(pmap);
-
- if(pmap->clientPixelsRed)
- {
- for(i = 0; i < MAXCLIENTS; i++)
- xfree(pmap->clientPixelsRed[i]);
- }
-
- if ((pmap->class == PseudoColor) || (pmap->class == GrayScale))
- {
- for(pent = &pmap->red[pmap->pVisual->ColormapEntries - 1];
- pent >= pmap->red;
- pent--)
- {
- if(pent->fShared)
- {
- if (--pent->co.shco.red->refcnt == 0)
- xfree(pent->co.shco.red);
- if (--pent->co.shco.green->refcnt == 0)
- xfree(pent->co.shco.green);
- if (--pent->co.shco.blue->refcnt == 0)
- xfree(pent->co.shco.blue);
- }
- }
- }
- if((pmap->class | DynamicClass) == DirectColor)
- {
- for(i = 0; i < MAXCLIENTS; i++)
- {
- xfree(pmap->clientPixelsGreen[i]);
- xfree(pmap->clientPixelsBlue[i]);
- }
- }
-
- if (pmap->devPrivates)
- xfree(pmap->devPrivates);
-
- xfree(pmap);
- return(Success);
-}
-
-/* Tell window that pmid has disappeared */
-static int
-TellNoMap (pwin, pmid)
- WindowPtr pwin;
- Colormap *pmid;
-{
- xEvent xE;
- if (wColormap(pwin) == *pmid)
- {
- /* This should be call to DeliverEvent */
- xE.u.u.type = ColormapNotify;
- xE.u.colormap.window = pwin->drawable.id;
- xE.u.colormap.colormap = None;
- xE.u.colormap.new = TRUE;
- xE.u.colormap.state = ColormapUninstalled;
- DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
- if (pwin->optional) {
- pwin->optional->colormap = None;
- CheckWindowOptionalNeed (pwin);
- }
- }
-
- return (WT_WALKCHILDREN);
-}
-
-/* Tell window that pmid got uninstalled */
-int
-TellLostMap (pwin, value)
- WindowPtr pwin;
- pointer value;
-{
- Colormap *pmid = (Colormap *)value;
- xEvent xE;
- if (wColormap(pwin) == *pmid)
- {
- /* This should be call to DeliverEvent */
- xE.u.u.type = ColormapNotify;
- xE.u.colormap.window = pwin->drawable.id;
- xE.u.colormap.colormap = *pmid;
- xE.u.colormap.new = FALSE;
- xE.u.colormap.state = ColormapUninstalled;
- DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
- }
-
- return (WT_WALKCHILDREN);
-}
-
-/* Tell window that pmid got installed */
-int
-TellGainedMap (pwin, value)
- WindowPtr pwin;
- pointer value;
-{
- Colormap *pmid = (Colormap *)value;
- xEvent xE;
- if (wColormap (pwin) == *pmid)
- {
- /* This should be call to DeliverEvent */
- xE.u.u.type = ColormapNotify;
- xE.u.colormap.window = pwin->drawable.id;
- xE.u.colormap.colormap = *pmid;
- xE.u.colormap.new = FALSE;
- xE.u.colormap.state = ColormapInstalled;
- DeliverEvents(pwin, &xE, 1, (WindowPtr)NULL);
- }
-
- return (WT_WALKCHILDREN);
-}
-
-
-int
-CopyColormapAndFree (mid, pSrc, client)
- Colormap mid;
- ColormapPtr pSrc;
- int client;
-{
- ColormapPtr pmap = (ColormapPtr) NULL;
- int result, alloc, size;
- Colormap midSrc;
- ScreenPtr pScreen;
- VisualPtr pVisual;
-
- pScreen = pSrc->pScreen;
- pVisual = pSrc->pVisual;
- midSrc = pSrc->mid;
- alloc = ((pSrc->flags & AllAllocated) && CLIENT_ID(midSrc) == client) ?
- AllocAll : AllocNone;
- size = pVisual->ColormapEntries;
-
- /* If the create returns non-0, it failed */
- result = CreateColormap (mid, pScreen, pVisual, &pmap, alloc, client);
- if(result != Success)
- return(result);
- if(alloc == AllocAll)
- {
- memmove((char *)pmap->red, (char *)pSrc->red, size * sizeof(Entry));
- if((pmap->class | DynamicClass) == DirectColor)
- {
- memmove((char *)pmap->green, (char *)pSrc->green, size * sizeof(Entry));
- memmove((char *)pmap->blue, (char *)pSrc->blue, size * sizeof(Entry));
- }
- pSrc->flags &= ~AllAllocated;
- FreePixels(pSrc, client);
- UpdateColors(pmap);
- return(Success);
- }
-
- CopyFree(REDMAP, client, pSrc, pmap);
- if ((pmap->class | DynamicClass) == DirectColor)
- {
- CopyFree(GREENMAP, client, pSrc, pmap);
- CopyFree(BLUEMAP, client, pSrc, pmap);
- }
- if (pmap->class & DynamicClass)
- UpdateColors(pmap);
- /* XXX should worry about removing any RT_CMAPENTRY resource */
- return(Success);
-}
-
-/* Helper routine for freeing large numbers of cells from a map */
-static void
-CopyFree (channel, client, pmapSrc, pmapDst)
- int channel, client;
- ColormapPtr pmapSrc, pmapDst;
-{
- int z, npix, oldFree;
- EntryPtr pentSrcFirst, pentDstFirst;
- EntryPtr pentSrc, pentDst;
- Pixel *ppix;
- int nalloc;
-
- switch(channel)
- {
- default: /* so compiler can see that everything gets initialized */
- case REDMAP:
- ppix = (pmapSrc->clientPixelsRed)[client];
- npix = (pmapSrc->numPixelsRed)[client];
- pentSrcFirst = pmapSrc->red;
- pentDstFirst = pmapDst->red;
- oldFree = pmapSrc->freeRed;
- break;
- case GREENMAP:
- ppix = (pmapSrc->clientPixelsGreen)[client];
- npix = (pmapSrc->numPixelsGreen)[client];
- pentSrcFirst = pmapSrc->green;
- pentDstFirst = pmapDst->green;
- oldFree = pmapSrc->freeGreen;
- break;
- case BLUEMAP:
- ppix = (pmapSrc->clientPixelsBlue)[client];
- npix = (pmapSrc->numPixelsBlue)[client];
- pentSrcFirst = pmapSrc->blue;
- pentDstFirst = pmapDst->blue;
- oldFree = pmapSrc->freeBlue;
- break;
- }
- nalloc = 0;
- if (pmapSrc->class & DynamicClass)
- {
- for(z = npix; --z >= 0; ppix++)
- {
- /* Copy entries */
- pentSrc = pentSrcFirst + *ppix;
- pentDst = pentDstFirst + *ppix;
- if (pentDst->refcnt > 0)
- {
- pentDst->refcnt++;
- }
- else
- {
- *pentDst = *pentSrc;
- nalloc++;
- if (pentSrc->refcnt > 0)
- pentDst->refcnt = 1;
- else
- pentSrc->fShared = FALSE;
- }
- FreeCell(pmapSrc, *ppix, channel);
- }
- }
-
- /* Note that FreeCell has already fixed pmapSrc->free{Color} */
- switch(channel)
- {
- case REDMAP:
- pmapDst->freeRed -= nalloc;
- (pmapDst->clientPixelsRed)[client] =
- (pmapSrc->clientPixelsRed)[client];
- (pmapSrc->clientPixelsRed)[client] = (Pixel *) NULL;
- (pmapDst->numPixelsRed)[client] = (pmapSrc->numPixelsRed)[client];
- (pmapSrc->numPixelsRed)[client] = 0;
- break;
- case GREENMAP:
- pmapDst->freeGreen -= nalloc;
- (pmapDst->clientPixelsGreen)[client] =
- (pmapSrc->clientPixelsGreen)[client];
- (pmapSrc->clientPixelsGreen)[client] = (Pixel *) NULL;
- (pmapDst->numPixelsGreen)[client] = (pmapSrc->numPixelsGreen)[client];
- (pmapSrc->numPixelsGreen)[client] = 0;
- break;
- case BLUEMAP:
- pmapDst->freeBlue -= nalloc;
- pmapDst->clientPixelsBlue[client] = pmapSrc->clientPixelsBlue[client];
- pmapSrc->clientPixelsBlue[client] = (Pixel *) NULL;
- pmapDst->numPixelsBlue[client] = pmapSrc->numPixelsBlue[client];
- pmapSrc->numPixelsBlue[client] = 0;
- break;
- }
-}
-
-/* Free the ith entry in a color map. Must handle freeing of
- * colors allocated through AllocColorPlanes */
-static void
-FreeCell (pmap, i, channel)
- ColormapPtr pmap;
- Pixel i;
- int channel;
-{
- EntryPtr pent;
- int *pCount;
-
-
- switch (channel)
- {
- default: /* so compiler can see that everything gets initialized */
- case PSEUDOMAP:
- case REDMAP:
- pent = (EntryPtr) &pmap->red[i];
- pCount = &pmap->freeRed;
- break;
- case GREENMAP:
- pent = (EntryPtr) &pmap->green[i];
- pCount = &pmap->freeGreen;
- break;
- case BLUEMAP:
- pent = (EntryPtr) &pmap->blue[i];
- pCount = &pmap->freeBlue;
- break;
- }
- /* If it's not privately allocated and it's not time to free it, just
- * decrement the count */
- if (pent->refcnt > 1)
- pent->refcnt--;
- else
- {
- /* If the color type is shared, find the sharedcolor. If decremented
- * refcnt is 0, free the shared cell. */
- if (pent->fShared)
- {
- if(--pent->co.shco.red->refcnt == 0)
- xfree(pent->co.shco.red);
- if(--pent->co.shco.green->refcnt == 0)
- xfree(pent->co.shco.green);
- if(--pent->co.shco.blue->refcnt == 0)
- xfree(pent->co.shco.blue);
- pent->fShared = FALSE;
- }
- pent->refcnt = 0;
- *pCount += 1;
- }
-}
-
-static void
-UpdateColors (pmap)
- ColormapPtr pmap;
-{
- xColorItem *defs;
- register xColorItem *pdef;
- register EntryPtr pent;
- register VisualPtr pVisual;
- int i, n, size;
-
- pVisual = pmap->pVisual;
- size = pVisual->ColormapEntries;
- defs = (xColorItem *)ALLOCATE_LOCAL(size * sizeof(xColorItem));
- if (!defs)
- return;
- n = 0;
- pdef = defs;
- if (pmap->class == DirectColor)
- {
- for (i = 0; i < size; i++)
- {
- if (!pmap->red[i].refcnt &&
- !pmap->green[i].refcnt &&
- !pmap->blue[i].refcnt)
- continue;
- pdef->pixel = ((Pixel)i << pVisual->offsetRed) |
- ((Pixel)i << pVisual->offsetGreen) |
- ((Pixel)i << pVisual->offsetBlue);
- pdef->red = pmap->red[i].co.local.red;
- pdef->green = pmap->green[i].co.local.green;
- pdef->blue = pmap->blue[i].co.local.blue;
- pdef->flags = DoRed|DoGreen|DoBlue;
- pdef++;
- n++;
- }
- }
- else
- {
- for (i = 0, pent = pmap->red; i < size; i++, pent++)
- {
- if (!pent->refcnt)
- continue;
- pdef->pixel = i;
- if(pent->fShared)
- {
- pdef->red = pent->co.shco.red->color;
- pdef->green = pent->co.shco.green->color;
- pdef->blue = pent->co.shco.blue->color;
- }
- else
- {
- pdef->red = pent->co.local.red;
- pdef->green = pent->co.local.green;
- pdef->blue = pent->co.local.blue;
- }
- pdef->flags = DoRed|DoGreen|DoBlue;
- pdef++;
- n++;
- }
- }
- if (n)
- (*pmap->pScreen->StoreColors)(pmap, n, defs);
- DEALLOCATE_LOCAL(defs);
-}
-
-/* Get a read-only color from a ColorMap (probably slow for large maps)
- * Returns by changing the value in pred, pgreen, pblue and pPix
- */
-int
-AllocColor (pmap, pred, pgreen, pblue, pPix, client)
- ColormapPtr pmap;
- unsigned short *pred, *pgreen, *pblue;
- Pixel *pPix;
- int client;
-{
- Pixel pixR, pixG, pixB;
- int entries;
- xrgb rgb;
- int class;
- VisualPtr pVisual;
- int npix;
- Pixel *ppix;
-
- pVisual = pmap->pVisual;
- (*pmap->pScreen->ResolveColor) (pred, pgreen, pblue, pVisual);
- rgb.red = *pred;
- rgb.green = *pgreen;
- rgb.blue = *pblue;
- class = pmap->class;
- entries = pVisual->ColormapEntries;
-
- /* If the colormap is being created, then we want to be able to change
- * the colormap, even if it's a static type. Otherwise, we'd never be
- * able to initialize static colormaps
- */
- if(pmap->flags & BeingCreated)
- class |= DynamicClass;
-
- /* If this is one of the static storage classes, and we're not initializing
- * it, the best we can do is to find the closest color entry to the
- * requested one and return that.
- */
- switch (class) {
- case StaticColor:
- case StaticGray:
- /* Look up all three components in the same pmap */
- *pPix = pixR = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
- *pred = pmap->red[pixR].co.local.red;
- *pgreen = pmap->red[pixR].co.local.green;
- *pblue = pmap->red[pixR].co.local.blue;
- npix = pmap->numPixelsRed[client];
- ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixR;
- pmap->clientPixelsRed[client] = ppix;
- pmap->numPixelsRed[client]++;
- break;
-
- case TrueColor:
- /* Look up each component in its own map, then OR them together */
- pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
- pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
- pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
- *pPix = (pixR << pVisual->offsetRed) |
- (pixG << pVisual->offsetGreen) |
- (pixB << pVisual->offsetBlue);
- *pred = pmap->red[pixR].co.local.red;
- *pgreen = pmap->green[pixG].co.local.green;
- *pblue = pmap->blue[pixB].co.local.blue;
- npix = pmap->numPixelsRed[client];
- ppix = (Pixel *) xrealloc(pmap->clientPixelsRed[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixR;
- pmap->clientPixelsRed[client] = ppix;
- npix = pmap->numPixelsGreen[client];
- ppix = (Pixel *) xrealloc(pmap->clientPixelsGreen[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixG;
- pmap->clientPixelsGreen[client] = ppix;
- npix = pmap->numPixelsBlue[client];
- ppix = (Pixel *) xrealloc(pmap->clientPixelsBlue[client],
- (npix + 1) * sizeof(Pixel));
- if (!ppix)
- return (BadAlloc);
- ppix[npix] = pixB;
- pmap->clientPixelsBlue[client] = ppix;
- pmap->numPixelsRed[client]++;
- pmap->numPixelsGreen[client]++;
- pmap->numPixelsBlue[client]++;
- break;
-
- case GrayScale:
- case PseudoColor:
- if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP,
- client, AllComp) != Success)
- return (BadAlloc);
- break;
-
- case DirectColor:
- pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed;
- if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
- client, RedComp) != Success)
- return (BadAlloc);
- pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen;
- if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
- GREENMAP, client, GreenComp) != Success)
- {
- (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0);
- return (BadAlloc);
- }
- pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue;
- if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
- client, BlueComp) != Success)
- {
- (void)FreeCo(pmap, client, GREENMAP, 1, &pixG, (Pixel)0);
- (void)FreeCo(pmap, client, REDMAP, 1, &pixR, (Pixel)0);
- return (BadAlloc);
- }
- *pPix = pixR | pixG | pixB;
- break;
- }
-
- /* if this is the client's first pixel in this colormap, tell the
- * resource manager that the client has pixels in this colormap which
- * should be freed when the client dies */
- if ((pmap->numPixelsRed[client] == 1) &&
- (CLIENT_ID(pmap->mid) != client) &&
- !(pmap->flags & BeingCreated))
- {
- colorResource *pcr;
-
- pcr = (colorResource *) xalloc(sizeof(colorResource));
- if (!pcr)
- {
- (void)FreeColors(pmap, client, 1, pPix, (Pixel)0);
- return (BadAlloc);
- }
- pcr->mid = pmap->mid;
- pcr->client = client;
- if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
- return (BadAlloc);
- }
- return (Success);
-}
-
-/*
- * FakeAllocColor -- fake an AllocColor request by
- * returning a free pixel if availible, otherwise returning
- * the closest matching pixel. This is used by the mi
- * software sprite code to recolor cursors. A nice side-effect
- * is that this routine will never return failure.
- */
-
-void
-FakeAllocColor (pmap, item)
- register ColormapPtr pmap;
- register xColorItem *item;
-{
- Pixel pixR, pixG, pixB;
- Pixel temp;
- int entries;
- xrgb rgb;
- int class;
- register VisualPtr pVisual;
-
- pVisual = pmap->pVisual;
- rgb.red = item->red;
- rgb.green = item->green;
- rgb.blue = item->blue;
- (*pmap->pScreen->ResolveColor) (&rgb.red, &rgb.green, &rgb.blue, pVisual);
- class = pmap->class;
- entries = pVisual->ColormapEntries;
-
- switch (class) {
- case GrayScale:
- case PseudoColor:
- item->pixel = 0;
- if (FindColor(pmap, pmap->red, entries, &rgb, &temp, PSEUDOMAP,
- -1, AllComp) == Success) {
- item->pixel = temp;
- break;
- }
- /* fall through ... */
- case StaticColor:
- case StaticGray:
- item->pixel = FindBestPixel(pmap->red, entries, &rgb, PSEUDOMAP);
- break;
-
- case DirectColor:
- /* Look up each component in its own map, then OR them together */
- pixR = (item->pixel & pVisual->redMask) >> pVisual->offsetRed;
- pixG = (item->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- pixB = (item->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (FindColor(pmap, pmap->red, NUMRED(pVisual), &rgb, &pixR, REDMAP,
- -1, RedComp) != Success)
- pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP)
- << pVisual->offsetRed;
- if (FindColor(pmap, pmap->green, NUMGREEN(pVisual), &rgb, &pixG,
- GREENMAP, -1, GreenComp) != Success)
- pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb,
- GREENMAP) << pVisual->offsetGreen;
- if (FindColor(pmap, pmap->blue, NUMBLUE(pVisual), &rgb, &pixB, BLUEMAP,
- -1, BlueComp) != Success)
- pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP)
- << pVisual->offsetBlue;
- item->pixel = pixR | pixG | pixB;
- break;
-
- case TrueColor:
- /* Look up each component in its own map, then OR them together */
- pixR = FindBestPixel(pmap->red, NUMRED(pVisual), &rgb, REDMAP);
- pixG = FindBestPixel(pmap->green, NUMGREEN(pVisual), &rgb, GREENMAP);
- pixB = FindBestPixel(pmap->blue, NUMBLUE(pVisual), &rgb, BLUEMAP);
- item->pixel = (pixR << pVisual->offsetRed) |
- (pixG << pVisual->offsetGreen) |
- (pixB << pVisual->offsetBlue);
- break;
- }
-}
-
-/* free a pixel value obtained from FakeAllocColor */
-void
-FakeFreeColor(pmap, pixel)
- register ColormapPtr pmap;
- Pixel pixel;
-{
- register VisualPtr pVisual;
- Pixel pixR, pixG, pixB;
-
- switch (pmap->class) {
- case GrayScale:
- case PseudoColor:
- if (pmap->red[pixel].refcnt == AllocTemporary)
- pmap->red[pixel].refcnt = 0;
- break;
- case DirectColor:
- pVisual = pmap->pVisual;
- pixR = (pixel & pVisual->redMask) >> pVisual->offsetRed;
- pixG = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- pixB = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (pmap->red[pixR].refcnt == AllocTemporary)
- pmap->red[pixR].refcnt = 0;
- if (pmap->green[pixG].refcnt == AllocTemporary)
- pmap->green[pixG].refcnt = 0;
- if (pmap->blue[pixB].refcnt == AllocTemporary)
- pmap->blue[pixB].refcnt = 0;
- break;
- }
-}
-
-typedef unsigned short BigNumUpper;
-typedef unsigned long BigNumLower;
-
-#define BIGNUMLOWERBITS 24
-#define BIGNUMUPPERBITS 16
-#define BIGNUMLOWER (1 << BIGNUMLOWERBITS)
-#define BIGNUMUPPER (1 << BIGNUMUPPERBITS)
-#define UPPERPART(i) ((i) >> BIGNUMLOWERBITS)
-#define LOWERPART(i) ((i) & (BIGNUMLOWER - 1))
-
-typedef struct _bignum {
- BigNumUpper upper;
- BigNumLower lower;
-} BigNumRec, *BigNumPtr;
-
-#define BigNumGreater(x,y) (((x)->upper > (y)->upper) ||\
- ((x)->upper == (y)->upper && (x)->lower > (y)->lower))
-
-#define UnsignedToBigNum(u,r) (((r)->upper = UPPERPART(u)), \
- ((r)->lower = LOWERPART(u)))
-
-#define MaxBigNum(r) (((r)->upper = BIGNUMUPPER-1), \
- ((r)->lower = BIGNUMLOWER-1))
-
-static void
-#if NeedFunctionPrototypes
-BigNumAdd (BigNumPtr x, BigNumPtr y, BigNumPtr r)
-#else
-BigNumAdd (x, y, r)
- BigNumPtr x, y, r;
-#endif
-{
- BigNumLower lower, carry = 0;
-
- lower = x->lower + y->lower;
- if (lower >= BIGNUMLOWER) {
- lower -= BIGNUMLOWER;
- carry = 1;
- }
- r->lower = lower;
- r->upper = x->upper + y->upper + carry;
-}
-
-static Pixel
-FindBestPixel(pentFirst, size, prgb, channel)
- EntryPtr pentFirst;
- int size;
- xrgb *prgb;
- int channel;
-{
- EntryPtr pent;
- Pixel pixel, final;
- long dr, dg, db;
- unsigned long sq;
- BigNumRec minval, sum, temp;
-
- final = 0;
- MaxBigNum(&minval);
- /* look for the minimal difference */
- for (pent = pentFirst, pixel = 0; pixel < size; pent++, pixel++)
- {
- dr = dg = db = 0;
- switch(channel)
- {
- case PSEUDOMAP:
- dg = pent->co.local.green - prgb->green;
- db = pent->co.local.blue - prgb->blue;
- case REDMAP:
- dr = pent->co.local.red - prgb->red;
- break;
- case GREENMAP:
- dg = pent->co.local.green - prgb->green;
- break;
- case BLUEMAP:
- db = pent->co.local.blue - prgb->blue;
- break;
- }
- sq = dr * dr;
- UnsignedToBigNum (sq, &sum);
- sq = dg * dg;
- UnsignedToBigNum (sq, &temp);
- BigNumAdd (&sum, &temp, &sum);
- sq = db * db;
- UnsignedToBigNum (sq, &temp);
- BigNumAdd (&sum, &temp, &sum);
- if (BigNumGreater (&minval, &sum))
- {
- final = pixel;
- minval = sum;
- }
- }
- return(final);
-}
-
-/* Tries to find a color in pmap that exactly matches the one requested in prgb
- * if it can't it allocates one.
- * Starts looking at pentFirst + *pPixel, so if you want a specific pixel,
- * load *pPixel with that value, otherwise set it to 0
- */
-int
-FindColor (pmap, pentFirst, size, prgb, pPixel, channel, client, comp)
- ColormapPtr pmap;
- EntryPtr pentFirst;
- int size;
- xrgb *prgb;
- Pixel *pPixel;
- int channel;
- int client;
- ColorCompareProcPtr comp;
-{
- EntryPtr pent;
- Bool foundFree;
- Pixel pixel, Free;
- int npix, count, *nump;
- Pixel **pixp, *ppix;
- xColorItem def;
-
- foundFree = FALSE;
-
- if((pixel = *pPixel) >= size)
- pixel = 0;
- /* see if there is a match, and also look for a free entry */
- for (pent = pentFirst + pixel, count = size; --count >= 0; )
- {
- if (pent->refcnt > 0)
- {
- if ((*comp) (pent, prgb))
- {
- if (client >= 0)
- pent->refcnt++;
- *pPixel = pixel;
- switch(channel)
- {
- case REDMAP:
- *pPixel <<= pmap->pVisual->offsetRed;
- case PSEUDOMAP:
- break;
- case GREENMAP:
- *pPixel <<= pmap->pVisual->offsetGreen;
- break;
- case BLUEMAP:
- *pPixel <<= pmap->pVisual->offsetBlue;
- break;
- }
- goto gotit;
- }
- }
- else if (!foundFree && pent->refcnt == 0)
- {
- Free = pixel;
- foundFree = TRUE;
- /* If we're initializing the colormap, then we are looking for
- * the first free cell we can find, not to minimize the number
- * of entries we use. So don't look any further. */
- if(pmap->flags & BeingCreated)
- break;
- }
- pixel++;
- if(pixel >= size)
- {
- pent = pentFirst;
- pixel = 0;
- }
- else
- pent++;
- }
-
- /* If we got here, we didn't find a match. If we also didn't find
- * a free entry, we're out of luck. Otherwise, we'll usurp a free
- * entry and fill it in */
- if (!foundFree)
- return (BadAlloc);
- pent = pentFirst + Free;
- pent->fShared = FALSE;
- pent->refcnt = (client >= 0) ? 1 : AllocTemporary;
-
- switch (channel)
- {
- case PSEUDOMAP:
- pent->co.local.red = prgb->red;
- pent->co.local.green = prgb->green;
- pent->co.local.blue = prgb->blue;
- def.red = prgb->red;
- def.green = prgb->green;
- def.blue = prgb->blue;
- def.flags = (DoRed|DoGreen|DoBlue);
- if (client >= 0)
- pmap->freeRed--;
- def.pixel = Free;
- break;
-
- case REDMAP:
- pent->co.local.red = prgb->red;
- def.red = prgb->red;
- def.green = pmap->green[0].co.local.green;
- def.blue = pmap->blue[0].co.local.blue;
- def.flags = DoRed;
- if (client >= 0)
- pmap->freeRed--;
- def.pixel = Free << pmap->pVisual->offsetRed;
- break;
-
- case GREENMAP:
- pent->co.local.green = prgb->green;
- def.red = pmap->red[0].co.local.red;
- def.green = prgb->green;
- def.blue = pmap->blue[0].co.local.blue;
- def.flags = DoGreen;
- if (client >= 0)
- pmap->freeGreen--;
- def.pixel = Free << pmap->pVisual->offsetGreen;
- break;
-
- case BLUEMAP:
- pent->co.local.blue = prgb->blue;
- def.red = pmap->red[0].co.local.red;
- def.green = pmap->green[0].co.local.green;
- def.blue = prgb->blue;
- def.flags = DoBlue;
- if (client >= 0)
- pmap->freeBlue--;
- def.pixel = Free << pmap->pVisual->offsetBlue;
- break;
- }
- (*pmap->pScreen->StoreColors) (pmap, 1, &def);
- pixel = Free;
- *pPixel = def.pixel;
-
-gotit:
- if (pmap->flags & BeingCreated || client == -1)
- return(Success);
- /* Now remember the pixel, for freeing later */
- switch (channel)
- {
- case PSEUDOMAP:
- case REDMAP:
- nump = pmap->numPixelsRed;
- pixp = pmap->clientPixelsRed;
- break;
-
- case GREENMAP:
- nump = pmap->numPixelsGreen;
- pixp = pmap->clientPixelsGreen;
- break;
-
- case BLUEMAP:
- nump = pmap->numPixelsBlue;
- pixp = pmap->clientPixelsBlue;
- break;
- }
- npix = nump[client];
- ppix = (Pixel *) xrealloc (pixp[client], (npix + 1) * sizeof(Pixel));
- if (!ppix)
- {
- pent->refcnt--;
- if (!pent->fShared)
- switch (channel)
- {
- case PSEUDOMAP:
- case REDMAP:
- pmap->freeRed++;
- break;
- case GREENMAP:
- pmap->freeGreen++;
- break;
- case BLUEMAP:
- pmap->freeBlue++;
- break;
- }
- return(BadAlloc);
- }
- ppix[npix] = pixel;
- pixp[client] = ppix;
- nump[client]++;
-
- return(Success);
-}
-
-/* Comparison functions -- passed to FindColor to determine if an
- * entry is already the color we're looking for or not */
-static int
-AllComp (pent, prgb)
- EntryPtr pent;
- xrgb *prgb;
-{
- if((pent->co.local.red == prgb->red) &&
- (pent->co.local.green == prgb->green) &&
- (pent->co.local.blue == prgb->blue) )
- return (1);
- return (0);
-}
-
-static int
-RedComp (pent, prgb)
- EntryPtr pent;
- xrgb *prgb;
-{
- if (pent->co.local.red == prgb->red)
- return (1);
- return (0);
-}
-
-static int
-GreenComp (pent, prgb)
- EntryPtr pent;
- xrgb *prgb;
-{
- if (pent->co.local.green == prgb->green)
- return (1);
- return (0);
-}
-
-static int
-BlueComp (pent, prgb)
- EntryPtr pent;
- xrgb *prgb;
-{
- if (pent->co.local.blue == prgb->blue)
- return (1);
- return (0);
-}
-
-
-/* Read the color value of a cell */
-
-int
-QueryColors (pmap, count, ppixIn, prgbList)
- ColormapPtr pmap;
- int count;
- Pixel *ppixIn;
- xrgb *prgbList;
-{
- Pixel *ppix, pixel;
- xrgb *prgb;
- VisualPtr pVisual;
- EntryPtr pent;
- Pixel i;
- int errVal = Success;
-
- pVisual = pmap->pVisual;
- if ((pmap->class | DynamicClass) == DirectColor)
- {
- int numred, numgreen, numblue;
- Pixel rgbbad;
-
- numred = NUMRED(pVisual);
- numgreen = NUMGREEN(pVisual);
- numblue = NUMBLUE(pVisual);
- rgbbad = ~RGBMASK(pVisual);
- for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++)
- {
- pixel = *ppix;
- if (pixel & rgbbad) {
- clientErrorValue = pixel;
- errVal = BadValue;
- continue;
- }
- i = (pixel & pVisual->redMask) >> pVisual->offsetRed;
- if (i >= numred)
- {
- clientErrorValue = pixel;
- errVal = BadValue;
- continue;
- }
- prgb->red = pmap->red[i].co.local.red;
- i = (pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- if (i >= numgreen)
- {
- clientErrorValue = pixel;
- errVal = BadValue;
- continue;
- }
- prgb->green = pmap->green[i].co.local.green;
- i = (pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (i >= numblue)
- {
- clientErrorValue = pixel;
- errVal = BadValue;
- continue;
- }
- prgb->blue = pmap->blue[i].co.local.blue;
- }
- }
- else
- {
- for( ppix = ppixIn, prgb = prgbList; --count >= 0; ppix++, prgb++)
- {
- pixel = *ppix;
- if (pixel >= pVisual->ColormapEntries)
- {
- clientErrorValue = pixel;
- errVal = BadValue;
- }
- else
- {
- pent = (EntryPtr)&pmap->red[pixel];
- if (pent->fShared)
- {
- prgb->red = pent->co.shco.red->color;
- prgb->green = pent->co.shco.green->color;
- prgb->blue = pent->co.shco.blue->color;
- }
- else
- {
- prgb->red = pent->co.local.red;
- prgb->green = pent->co.local.green;
- prgb->blue = pent->co.local.blue;
- }
- }
- }
- }
- return (errVal);
-}
-
-static void
-FreePixels(pmap, client)
- register ColormapPtr pmap;
- register int client;
-{
- register Pixel *ppix, *ppixStart;
- register int n;
- int class;
-#ifdef LBX
- Bool grabbed;
- Bool zeroRefCount;
- Bool anyRefCountReachedZero = 0;
-#endif
-
- class = pmap->class;
- ppixStart = pmap->clientPixelsRed[client];
- if (class & DynamicClass)
- {
- n = pmap->numPixelsRed[client];
-#ifdef LBX
- grabbed = LbxCheckCmapGrabbed (pmap);
- if (grabbed)
- {
- /*
- * If the colormap is grabbed by a proxy, the server must
- * notify the proxy of all cells that are freed (the refcount
- * has reached zero on these cells).
- */
-
- LbxBeginFreeCellsEvent (pmap);
- LbxSortPixelList (ppixStart, n);
- }
-#endif
- for (ppix = ppixStart; --n >= 0; )
- {
- FreeCell(pmap, *ppix, REDMAP);
-#ifdef LBX
- /*
- * Only PSEUDO colormaps are grabbed by LBX proxies.
- * Check if the ref count reached zero on this pixel.
- */
-
- zeroRefCount = pmap->red[*ppix].refcnt == 0;
- if (zeroRefCount)
- anyRefCountReachedZero = 1;
-
- if (grabbed && zeroRefCount)
- LbxAddFreeCellToEvent (pmap, *ppix);
-#endif
- ppix++;
- }
-#ifdef LBX
- if (grabbed)
- LbxEndFreeCellsEvent (pmap);
- else if (anyRefCountReachedZero)
- {
- /*
- * We only send LbxFreeCell events to a proxy that has the colormap
- * grabbed. If the colormap is not grabbed, the proxy that last
- * had the colormap grabbed will not be able to do a smart grab
- * in the future. A smart grab can only occur if the proxy is kept
- * up to date on every alloc/free change in the colormap.
- */
-
- LbxDisableSmartGrab (pmap);
- }
-#endif
- }
-
- xfree(ppixStart);
- pmap->clientPixelsRed[client] = (Pixel *) NULL;
- pmap->numPixelsRed[client] = 0;
- if ((class | DynamicClass) == DirectColor)
- {
- ppixStart = pmap->clientPixelsGreen[client];
- if (class & DynamicClass)
- for (ppix = ppixStart, n = pmap->numPixelsGreen[client]; --n >= 0;)
- FreeCell(pmap, *ppix++, GREENMAP);
- xfree(ppixStart);
- pmap->clientPixelsGreen[client] = (Pixel *) NULL;
- pmap->numPixelsGreen[client] = 0;
-
- ppixStart = pmap->clientPixelsBlue[client];
- if (class & DynamicClass)
- for (ppix = ppixStart, n = pmap->numPixelsBlue[client]; --n >= 0; )
- FreeCell(pmap, *ppix++, BLUEMAP);
- xfree(ppixStart);
- pmap->clientPixelsBlue[client] = (Pixel *) NULL;
- pmap->numPixelsBlue[client] = 0;
- }
-}
-
-/* Free all of a client's colors and cells */
-/*ARGSUSED*/
-int
-FreeClientPixels (value, fakeid)
- pointer value; /* must conform to DeleteType */
- XID fakeid;
-{
- ColormapPtr pmap;
- colorResource *pcr = (colorResource *)value;
-
- pmap = (ColormapPtr) LookupIDByType(pcr->mid, RT_COLORMAP);
- if (pmap)
- FreePixels(pmap, pcr->client);
- xfree(pcr);
- return Success;
-}
-
-int
-AllocColorCells (client, pmap, colors, planes, contig, ppix, masks)
- int client;
- ColormapPtr pmap;
- int colors, planes;
- Bool contig;
- Pixel *ppix;
- Pixel *masks;
-{
- Pixel rmask, gmask, bmask, *ppixFirst, r, g, b;
- int n, class;
- int ok;
- int oldcount;
- colorResource *pcr = (colorResource *)NULL;
-
- class = pmap->class;
- if (!(class & DynamicClass))
- return (BadAlloc); /* Shouldn't try on this type */
- oldcount = pmap->numPixelsRed[client];
- if (pmap->class == DirectColor)
- oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
- if (!oldcount && (CLIENT_ID(pmap->mid) != client))
- {
- pcr = (colorResource *) xalloc(sizeof(colorResource));
- if (!pcr)
- return (BadAlloc);
- }
-
- if (pmap->class == DirectColor)
- {
- ok = AllocDirect (client, pmap, colors, planes, planes, planes,
- contig, ppix, &rmask, &gmask, &bmask);
- if(ok == Success)
- {
- for (r = g = b = 1, n = planes; --n >= 0; r += r, g += g, b += b)
- {
- while(!(rmask & r))
- r += r;
- while(!(gmask & g))
- g += g;
- while(!(bmask & b))
- b += b;
- *masks++ = r | g | b;
- }
- }
- }
- else
- {
- ok = AllocPseudo (client, pmap, colors, planes, contig, ppix, &rmask,
- &ppixFirst);
- if(ok == Success)
- {
- for (r = 1, n = planes; --n >= 0; r += r)
- {
- while(!(rmask & r))
- r += r;
- *masks++ = r;
- }
- }
- }
-
- /* if this is the client's first pixels in this colormap, tell the
- * resource manager that the client has pixels in this colormap which
- * should be freed when the client dies */
- if ((ok == Success) && pcr)
- {
- pcr->mid = pmap->mid;
- pcr->client = client;
- if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
- ok = BadAlloc;
- } else if (pcr)
- xfree(pcr);
-
- return (ok);
-}
-
-
-int
-AllocColorPlanes (client, pmap, colors, r, g, b, contig, pixels,
- prmask, pgmask, pbmask)
- int client;
- ColormapPtr pmap;
- int colors, r, g, b;
- Bool contig;
- Pixel *pixels;
- Pixel *prmask, *pgmask, *pbmask;
-{
- int ok;
- Pixel mask, *ppixFirst;
- register Pixel shift;
- register int i;
- int class;
- int oldcount;
- colorResource *pcr = (colorResource *)NULL;
-
- class = pmap->class;
- if (!(class & DynamicClass))
- return (BadAlloc); /* Shouldn't try on this type */
- oldcount = pmap->numPixelsRed[client];
- if (class == DirectColor)
- oldcount += pmap->numPixelsGreen[client] + pmap->numPixelsBlue[client];
- if (!oldcount && (CLIENT_ID(pmap->mid) != client))
- {
- pcr = (colorResource *) xalloc(sizeof(colorResource));
- if (!pcr)
- return (BadAlloc);
- }
-
- if (class == DirectColor)
- {
- ok = AllocDirect (client, pmap, colors, r, g, b, contig, pixels,
- prmask, pgmask, pbmask);
- }
- else
- {
- /* Allocate the proper pixels */
- /* XXX This is sort of bad, because of contig is set, we force all
- * r + g + b bits to be contiguous. Should only force contiguity
- * per mask
- */
- ok = AllocPseudo (client, pmap, colors, r + g + b, contig, pixels,
- &mask, &ppixFirst);
-
- if(ok == Success)
- {
- /* now split that mask into three */
- *prmask = *pgmask = *pbmask = 0;
- shift = 1;
- for (i = r; --i >= 0; shift += shift)
- {
- while (!(mask & shift))
- shift += shift;
- *prmask |= shift;
- }
- for (i = g; --i >= 0; shift += shift)
- {
- while (!(mask & shift))
- shift += shift;
- *pgmask |= shift;
- }
- for (i = b; --i >= 0; shift += shift)
- {
- while (!(mask & shift))
- shift += shift;
- *pbmask |= shift;
- }
-
- /* set up the shared color cells */
- if (!AllocShared(pmap, pixels, colors, r, g, b,
- *prmask, *pgmask, *pbmask, ppixFirst))
- {
- (void)FreeColors(pmap, client, colors, pixels, mask);
- ok = BadAlloc;
- }
- }
- }
-
- /* if this is the client's first pixels in this colormap, tell the
- * resource manager that the client has pixels in this colormap which
- * should be freed when the client dies */
- if ((ok == Success) && pcr)
- {
- pcr->mid = pmap->mid;
- pcr->client = client;
- if (!AddResource(FakeClientID(client), RT_CMAPENTRY, (pointer)pcr))
- ok = BadAlloc;
- } else if (pcr)
- xfree(pcr);
-
- return (ok);
-}
-
-static int
-AllocDirect (client, pmap, c, r, g, b, contig, pixels, prmask, pgmask, pbmask)
- int client;
- ColormapPtr pmap;
- int c, r, g, b;
- Bool contig;
- Pixel *pixels;
- Pixel *prmask, *pgmask, *pbmask;
-{
- Pixel *ppixRed, *ppixGreen, *ppixBlue;
- Pixel *ppix, *pDst, *p;
- int npix, npixR, npixG, npixB;
- Bool okR, okG, okB;
- Pixel *rpix = 0, *gpix = 0, *bpix = 0;
-
- npixR = c << r;
- npixG = c << g;
- npixB = c << b;
- if ((r >= 32) || (g >= 32) || (b >= 32) ||
- (npixR > pmap->freeRed) || (npixR < c) ||
- (npixG > pmap->freeGreen) || (npixG < c) ||
- (npixB > pmap->freeBlue) || (npixB < c))
- return BadAlloc;
-
- /* start out with empty pixels */
- for(p = pixels; p < pixels + c; p++)
- *p = 0;
-
- ppixRed = (Pixel *)ALLOCATE_LOCAL(npixR * sizeof(Pixel));
- ppixGreen = (Pixel *)ALLOCATE_LOCAL(npixG * sizeof(Pixel));
- ppixBlue = (Pixel *)ALLOCATE_LOCAL(npixB * sizeof(Pixel));
- if (!ppixRed || !ppixGreen || !ppixBlue)
- {
- if (ppixBlue) DEALLOCATE_LOCAL(ppixBlue);
- if (ppixGreen) DEALLOCATE_LOCAL(ppixGreen);
- if (ppixRed) DEALLOCATE_LOCAL(ppixRed);
- return(BadAlloc);
- }
-
- okR = AllocCP(pmap, pmap->red, c, r, contig, ppixRed, prmask);
- okG = AllocCP(pmap, pmap->green, c, g, contig, ppixGreen, pgmask);
- okB = AllocCP(pmap, pmap->blue, c, b, contig, ppixBlue, pbmask);
-
- if (okR && okG && okB)
- {
- rpix = (Pixel *) xrealloc(pmap->clientPixelsRed[client],
- (pmap->numPixelsRed[client] + (c << r)) *
- sizeof(Pixel));
- if (rpix)
- pmap->clientPixelsRed[client] = rpix;
- gpix = (Pixel *) xrealloc(pmap->clientPixelsGreen[client],
- (pmap->numPixelsGreen[client] + (c << g)) *
- sizeof(Pixel));
- if (gpix)
- pmap->clientPixelsGreen[client] = gpix;
- bpix = (Pixel *) xrealloc(pmap->clientPixelsBlue[client],
- (pmap->numPixelsBlue[client] + (c << b)) *
- sizeof(Pixel));
- if (bpix)
- pmap->clientPixelsBlue[client] = bpix;
- }
-
- if (!okR || !okG || !okB || !rpix || !gpix || !bpix)
- {
- if (okR)
- for(ppix = ppixRed, npix = npixR; --npix >= 0; ppix++)
- pmap->red[*ppix].refcnt = 0;
- if (okG)
- for(ppix = ppixGreen, npix = npixG; --npix >= 0; ppix++)
- pmap->green[*ppix].refcnt = 0;
- if (okB)
- for(ppix = ppixBlue, npix = npixB; --npix >= 0; ppix++)
- pmap->blue[*ppix].refcnt = 0;
- DEALLOCATE_LOCAL(ppixBlue);
- DEALLOCATE_LOCAL(ppixGreen);
- DEALLOCATE_LOCAL(ppixRed);
- return(BadAlloc);
- }
-
- *prmask <<= pmap->pVisual->offsetRed;
- *pgmask <<= pmap->pVisual->offsetGreen;
- *pbmask <<= pmap->pVisual->offsetBlue;
-
- ppix = rpix + pmap->numPixelsRed[client];
- for (pDst = pixels, p = ppixRed; p < ppixRed + npixR; p++)
- {
- *ppix++ = *p;
- if(p < ppixRed + c)
- *pDst++ |= *p << pmap->pVisual->offsetRed;
- }
- pmap->numPixelsRed[client] += npixR;
- pmap->freeRed -= npixR;
-
- ppix = gpix + pmap->numPixelsGreen[client];
- for (pDst = pixels, p = ppixGreen; p < ppixGreen + npixG; p++)
- {
- *ppix++ = *p;
- if(p < ppixGreen + c)
- *pDst++ |= *p << pmap->pVisual->offsetGreen;
- }
- pmap->numPixelsGreen[client] += npixG;
- pmap->freeGreen -= npixG;
-
- ppix = bpix + pmap->numPixelsBlue[client];
- for (pDst = pixels, p = ppixBlue; p < ppixBlue + npixB; p++)
- {
- *ppix++ = *p;
- if(p < ppixBlue + c)
- *pDst++ |= *p << pmap->pVisual->offsetBlue;
- }
- pmap->numPixelsBlue[client] += npixB;
- pmap->freeBlue -= npixB;
-
- DEALLOCATE_LOCAL(ppixBlue);
- DEALLOCATE_LOCAL(ppixGreen);
- DEALLOCATE_LOCAL(ppixRed);
-
- return (Success);
-}
-
-static int
-AllocPseudo (client, pmap, c, r, contig, pixels, pmask, pppixFirst)
- int client;
- ColormapPtr pmap;
- int c, r;
- Bool contig;
- Pixel *pixels;
- Pixel *pmask;
- Pixel **pppixFirst;
-{
- Pixel *ppix, *p, *pDst, *ppixTemp;
- int npix;
- Bool ok;
-
- npix = c << r;
- if ((r >= 32) || (npix > pmap->freeRed) || (npix < c))
- return(BadAlloc);
- if(!(ppixTemp = (Pixel *)ALLOCATE_LOCAL(npix * sizeof(Pixel))))
- return(BadAlloc);
- ok = AllocCP(pmap, pmap->red, c, r, contig, ppixTemp, pmask);
-
- if (ok)
- {
-
- /* all the allocated pixels are added to the client pixel list,
- * but only the unique ones are returned to the client */
- ppix = (Pixel *)xrealloc(pmap->clientPixelsRed[client],
- (pmap->numPixelsRed[client] + npix) * sizeof(Pixel));
- if (!ppix)
- {
- for (p = ppixTemp; p < ppixTemp + npix; p++)
- pmap->red[*p].refcnt = 0;
- return (BadAlloc);
- }
- pmap->clientPixelsRed[client] = ppix;
- ppix += pmap->numPixelsRed[client];
- *pppixFirst = ppix;
- pDst = pixels;
- for (p = ppixTemp; p < ppixTemp + npix; p++)
- {
- *ppix++ = *p;
- if(p < ppixTemp + c)
- *pDst++ = *p;
- }
- pmap->numPixelsRed[client] += npix;
- pmap->freeRed -= npix;
- }
- DEALLOCATE_LOCAL(ppixTemp);
- return (ok ? Success : BadAlloc);
-}
-
-/* Allocates count << planes pixels from colormap pmap for client. If
- * contig, then the plane mask is made of consecutive bits. Returns
- * all count << pixels in the array pixels. The first count of those
- * pixels are the unique pixels. *pMask has the mask to Or with the
- * unique pixels to get the rest of them.
- *
- * Returns True iff all pixels could be allocated
- * All cells allocated will have refcnt set to AllocPrivate and shared to FALSE
- * (see AllocShared for why we care)
- */
-static Bool
-AllocCP (pmap, pentFirst, count, planes, contig, pixels, pMask)
- ColormapPtr pmap;
- EntryPtr pentFirst;
- int count, planes;
- Bool contig;
- Pixel *pixels, *pMask;
-
-{
- EntryPtr ent;
- Pixel pixel, base, entries, maxp, save;
- int dplanes, found;
- Pixel *ppix;
- Pixel mask;
- Pixel finalmask;
-
- dplanes = pmap->pVisual->nplanes;
-
- /* Easy case. Allocate pixels only */
- if (planes == 0)
- {
- /* allocate writable entries */
- ppix = pixels;
- ent = pentFirst;
- pixel = 0;
- while (--count >= 0)
- {
- /* Just find count unallocated cells */
- while (ent->refcnt)
- {
- ent++;
- pixel++;
- }
- ent->refcnt = AllocPrivate;
- *ppix++ = pixel;
- ent->fShared = FALSE;
- }
- *pMask = 0;
- return (TRUE);
- }
- else if (planes > dplanes)
- {
- return (FALSE);
- }
-
- /* General case count pixels * 2 ^ planes cells to be allocated */
-
- /* make room for new pixels */
- ent = pentFirst;
-
- /* first try for contiguous planes, since it's fastest */
- for (mask = (((Pixel)1) << planes) - 1, base = 1, dplanes -= (planes - 1);
- --dplanes >= 0;
- mask += mask, base += base)
- {
- ppix = pixels;
- found = 0;
- pixel = 0;
- entries = pmap->pVisual->ColormapEntries - mask;
- while (pixel < entries)
- {
- save = pixel;
- maxp = pixel + mask + base;
- /* check if all are free */
- while (pixel != maxp && ent[pixel].refcnt == 0)
- pixel += base;
- if (pixel == maxp)
- {
- /* this one works */
- *ppix++ = save;
- found++;
- if (found == count)
- {
- /* found enough, allocate them all */
- while (--count >= 0)
- {
- pixel = pixels[count];
- maxp = pixel + mask;
- while (1)
- {
- ent[pixel].refcnt = AllocPrivate;
- ent[pixel].fShared = FALSE;
- if (pixel == maxp)
- break;
- pixel += base;
- *ppix++ = pixel;
- }
- }
- *pMask = mask;
- return (TRUE);
- }
- }
- pixel = save + 1;
- if (pixel & mask)
- pixel += mask;
- }
- }
-
- dplanes = pmap->pVisual->nplanes;
- if (contig || planes == 1 || dplanes < 3)
- return (FALSE);
-
- /* this will be very slow for large maps, need a better algorithm */
-
- /*
- we can generate the smallest and largest numbers that fits in dplanes
- bits and contain exactly planes bits set as follows. First, we need to
- check that it is possible to generate such a mask at all.
- (Non-contiguous masks need one more bit than contiguous masks). Then
- the smallest such mask consists of the rightmost planes-1 bits set, then
- a zero, then a one in position planes + 1. The formula is
- (3 << (planes-1)) -1
- The largest such masks consists of the leftmost planes-1 bits set, then
- a zero, then a one bit in position dplanes-planes-1. If dplanes is
- smaller than 32 (the number of bits in a word) then the formula is:
- (1<<dplanes) - (1<<(dplanes-planes+1) + (1<<dplanes-planes-1)
- If dplanes = 32, then we can't calculate (1<<dplanes) and we have
- to use:
- ( (1<<(planes-1)) - 1) << (dplanes-planes+1) + (1<<(dplanes-planes-1))
-
- << Thank you, Loretta>>>
-
- */
-
- finalmask =
- (((((Pixel)1)<<(planes-1)) - 1) << (dplanes-planes+1)) +
- (((Pixel)1)<<(dplanes-planes-1));
- for (mask = (((Pixel)3) << (planes -1)) - 1; mask <= finalmask; mask++)
- {
- /* next 3 magic statements count number of ones (HAKMEM #169) */
- pixel = (mask >> 1) & 033333333333;
- pixel = mask - pixel - ((pixel >> 1) & 033333333333);
- if ((((pixel + (pixel >> 3)) & 030707070707) % 077) != planes)
- continue;
- ppix = pixels;
- found = 0;
- entries = pmap->pVisual->ColormapEntries - mask;
- base = lowbit (mask);
- for (pixel = 0; pixel < entries; pixel++)
- {
- if (pixel & mask)
- continue;
- maxp = 0;
- /* check if all are free */
- while (ent[pixel + maxp].refcnt == 0)
- {
- GetNextBitsOrBreak(maxp, mask, base);
- }
- if ((maxp < mask) || (ent[pixel + mask].refcnt != 0))
- continue;
- /* this one works */
- *ppix++ = pixel;
- found++;
- if (found < count)
- continue;
- /* found enough, allocate them all */
- while (--count >= 0)
- {
- pixel = (pixels)[count];
- maxp = 0;
- while (1)
- {
- ent[pixel + maxp].refcnt = AllocPrivate;
- ent[pixel + maxp].fShared = FALSE;
- GetNextBitsOrBreak(maxp, mask, base);
- *ppix++ = pixel + maxp;
- }
- }
-
- *pMask = mask;
- return (TRUE);
- }
- }
- return (FALSE);
-}
-
-static Bool
-AllocShared (pmap, ppix, c, r, g, b, rmask, gmask, bmask, ppixFirst)
- ColormapPtr pmap;
- Pixel *ppix;
- int c, r, g, b;
- Pixel rmask, gmask, bmask;
- Pixel *ppixFirst; /* First of the client's new pixels */
-{
- Pixel *pptr, *cptr;
- int npix, z, npixClientNew, npixShared;
- Pixel basemask, base, bits, common;
- SHAREDCOLOR *pshared, **ppshared, **psharedList;
-
- npixClientNew = c << (r + g + b);
- npixShared = (c << r) + (c << g) + (c << b);
- psharedList = (SHAREDCOLOR **)ALLOCATE_LOCAL(npixShared *
- sizeof(SHAREDCOLOR *));
- if (!psharedList)
- return FALSE;
- ppshared = psharedList;
- for (z = npixShared; --z >= 0; )
- {
- if (!(ppshared[z] = (SHAREDCOLOR *)xalloc(sizeof(SHAREDCOLOR))))
- {
- for (z++ ; z < npixShared; z++)
- xfree(ppshared[z]);
- return FALSE;
- }
- }
- for(pptr = ppix, npix = c; --npix >= 0; pptr++)
- {
- basemask = ~(gmask | bmask);
- common = *pptr & basemask;
- if (rmask)
- {
- bits = 0;
- base = lowbit (rmask);
- while(1)
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == (common | bits))
- {
- pmap->red[*cptr].fShared = TRUE;
- pmap->red[*cptr].co.shco.red = pshared;
- }
- }
- GetNextBitsOrBreak(bits, rmask, base);
- }
- }
- else
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == common)
- {
- pmap->red[*cptr].fShared = TRUE;
- pmap->red[*cptr].co.shco.red = pshared;
- }
- }
- }
- basemask = ~(rmask | bmask);
- common = *pptr & basemask;
- if (gmask)
- {
- bits = 0;
- base = lowbit (gmask);
- while(1)
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (r + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == (common | bits))
- {
- pmap->red[*cptr].co.shco.green = pshared;
- }
- }
- GetNextBitsOrBreak(bits, gmask, base);
- }
- }
- else
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == common)
- {
- pmap->red[*cptr].co.shco.green = pshared;
- }
- }
- }
- basemask = ~(rmask | gmask);
- common = *pptr & basemask;
- if (bmask)
- {
- bits = 0;
- base = lowbit (bmask);
- while(1)
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (r + g);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == (common | bits))
- {
- pmap->red[*cptr].co.shco.blue = pshared;
- }
- }
- GetNextBitsOrBreak(bits, bmask, base);
- }
- }
- else
- {
- pshared = *ppshared++;
- pshared->refcnt = 1 << (g + b);
- for (cptr = ppixFirst, z = npixClientNew; --z >= 0; cptr++)
- {
- if ((*cptr & basemask) == common)
- {
- pmap->red[*cptr].co.shco.blue = pshared;
- }
- }
- }
- }
- DEALLOCATE_LOCAL(psharedList);
- return TRUE;
-}
-
-
-/* Free colors and/or cells (probably slow for large numbers) */
-
-int
-FreeColors (pmap, client, count, pixels, mask)
- ColormapPtr pmap;
- int client, count;
- Pixel *pixels;
- Pixel mask;
-{
- int rval, result, class;
- Pixel rmask;
-
- class = pmap->class;
- if (pmap->flags & AllAllocated)
- return(BadAccess);
- if ((class | DynamicClass) == DirectColor)
- {
- rmask = mask & RGBMASK(pmap->pVisual);
- result = FreeCo(pmap, client, REDMAP, count, pixels,
- mask & pmap->pVisual->redMask);
- /* If any of the three calls fails, we must report that, if more
- * than one fails, it's ok that we report the last one */
- rval = FreeCo(pmap, client, GREENMAP, count, pixels,
- mask & pmap->pVisual->greenMask);
- if(rval != Success)
- result = rval;
- rval = FreeCo(pmap, client, BLUEMAP, count, pixels,
- mask & pmap->pVisual->blueMask);
- if(rval != Success)
- result = rval;
- }
- else
- {
- rmask = mask & ((((Pixel)1) << pmap->pVisual->nplanes) - 1);
- result = FreeCo(pmap, client, PSEUDOMAP, count, pixels, rmask);
- }
- if ((mask != rmask) && count)
- {
- clientErrorValue = *pixels | mask;
- result = BadValue;
- }
- /* XXX should worry about removing any RT_CMAPENTRY resource */
- return (result);
-}
-
-/* Helper for FreeColors -- frees all combinations of *newpixels and mask bits
- * which the client has allocated in channel colormap cells of pmap.
- * doesn't change newpixels if it doesn't need to */
-static int
-FreeCo (pmap, client, color, npixIn, ppixIn, mask)
- ColormapPtr pmap; /* which colormap head */
- int client;
- int color; /* which sub-map, eg RED, BLUE, PSEUDO */
- int npixIn; /* number of pixels passed in */
- Pixel *ppixIn; /* list of base pixels */
- Pixel mask; /* mask client gave us */
-{
-
- Pixel *ppixClient, pixTest;
- int npixClient, npixNew, npix;
- Pixel bits, base, cmask, rgbbad;
- Pixel *pptr, *cptr;
- int n, zapped;
- int errVal = Success;
- int offset, numents;
-#ifdef LBX
- Bool grabbed;
- Bool zeroRefCount;
- Bool anyRefCountReachedZero = 0;
-#endif
-
- if (npixIn == 0)
- return (errVal);
- bits = 0;
- zapped = 0;
- base = lowbit (mask);
-
- switch(color)
- {
- case REDMAP:
- cmask = pmap->pVisual->redMask;
- rgbbad = ~RGBMASK(pmap->pVisual);
- offset = pmap->pVisual->offsetRed;
- numents = (cmask >> offset) + 1;
- ppixClient = pmap->clientPixelsRed[client];
- npixClient = pmap->numPixelsRed[client];
- break;
- case GREENMAP:
- cmask = pmap->pVisual->greenMask;
- rgbbad = ~RGBMASK(pmap->pVisual);
- offset = pmap->pVisual->offsetGreen;
- numents = (cmask >> offset) + 1;
- ppixClient = pmap->clientPixelsGreen[client];
- npixClient = pmap->numPixelsGreen[client];
- break;
- case BLUEMAP:
- cmask = pmap->pVisual->blueMask;
- rgbbad = ~RGBMASK(pmap->pVisual);
- offset = pmap->pVisual->offsetBlue;
- numents = (cmask >> offset) + 1;
- ppixClient = pmap->clientPixelsBlue[client];
- npixClient = pmap->numPixelsBlue[client];
- break;
- default: /* so compiler can see that everything gets initialized */
- case PSEUDOMAP:
- cmask = ~((Pixel)0);
- rgbbad = 0;
- offset = 0;
- numents = pmap->pVisual->ColormapEntries;
- ppixClient = pmap->clientPixelsRed[client];
- npixClient = pmap->numPixelsRed[client];
- break;
- }
-
-#ifdef LBX
- grabbed = LbxCheckCmapGrabbed (pmap);
-
- if (grabbed)
- {
- /*
- * If the colormap is grabbed by a proxy, the server must
- * notify the proxy of all cells that are freed (the refcount
- * has reached zero on these cells).
- */
-
- LbxBeginFreeCellsEvent (pmap);
- LbxSortPixelList (ppixIn, npixIn);
- }
-#endif
-
- /* zap all pixels which match */
- while (1)
- {
- /* go through pixel list */
- for (pptr = ppixIn, n = npixIn; --n >= 0; pptr++)
- {
- pixTest = ((*pptr | bits) & cmask) >> offset;
- if ((pixTest >= numents) || (*pptr & rgbbad))
- {
- clientErrorValue = *pptr | bits;
- errVal = BadValue;
- continue;
- }
-
- /* find match in client list */
- for (cptr = ppixClient, npix = npixClient;
- --npix >= 0 && *cptr != pixTest;
- cptr++) ;
-
- if (npix >= 0)
- {
- if (pmap->class & DynamicClass)
- {
- FreeCell(pmap, pixTest, color);
-#ifdef LBX
- /*
- * Only PSEUDO colormaps are grabbed by LBX proxies.
- * Check if the ref count reached zero on this pixel.
- */
-
- zeroRefCount = pmap->red[pixTest].refcnt == 0;
- if (zeroRefCount)
- anyRefCountReachedZero = 1;
-
- if (grabbed && zeroRefCount)
- LbxAddFreeCellToEvent (pmap, pixTest);
-#endif
- }
- *cptr = ~((Pixel)0);
- zapped++;
- }
- else
- errVal = BadAccess;
- }
- /* generate next bits value */
- GetNextBitsOrBreak(bits, mask, base);
- }
-
-#ifdef LBX
- if (grabbed)
- LbxEndFreeCellsEvent (pmap);
- else if (anyRefCountReachedZero)
- {
- /*
- * We only send LbxFreeCell events to a proxy that has the colormap
- * grabbed. If the colormap is not grabbed, the proxy that last
- * had the colormap grabbed will not be able to do a smart grab
- * in the future. A smart grab can only occur if the proxy is kept
- * up to date on every alloc/free change in the colormap.
- */
-
- LbxDisableSmartGrab (pmap);
- }
-#endif
-
- /* delete freed pixels from client pixel list */
- if (zapped)
- {
- npixNew = npixClient - zapped;
- if (npixNew)
- {
- /* Since the list can only get smaller, we can do a copy in
- * place and then realloc to a smaller size */
- pptr = cptr = ppixClient;
-
- /* If we have all the new pixels, we don't have to examine the
- * rest of the old ones */
- for(npix = 0; npix < npixNew; cptr++)
- {
- if (*cptr != ~((Pixel)0))
- {
- *pptr++ = *cptr;
- npix++;
- }
- }
- pptr = (Pixel *)xrealloc(ppixClient, npixNew * sizeof(Pixel));
- if (pptr)
- ppixClient = pptr;
- npixClient = npixNew;
- }
- else
- {
- npixClient = 0;
- xfree(ppixClient);
- ppixClient = (Pixel *)NULL;
- }
- switch(color)
- {
- case PSEUDOMAP:
- case REDMAP:
- pmap->clientPixelsRed[client] = ppixClient;
- pmap->numPixelsRed[client] = npixClient;
- break;
- case GREENMAP:
- pmap->clientPixelsGreen[client] = ppixClient;
- pmap->numPixelsGreen[client] = npixClient;
- break;
- case BLUEMAP:
- pmap->clientPixelsBlue[client] = ppixClient;
- pmap->numPixelsBlue[client] = npixClient;
- break;
- }
- }
- return (errVal);
-}
-
-
-
-/* Redefine color values */
-int
-StoreColors (pmap, count, defs)
- ColormapPtr pmap;
- int count;
- xColorItem *defs;
-{
- register Pixel pix;
- register xColorItem *pdef;
- register EntryPtr pent, pentT, pentLast;
- register VisualPtr pVisual;
- SHAREDCOLOR *pred, *pgreen, *pblue;
- int n, ChgRed, ChgGreen, ChgBlue, idef;
- int class, errVal = Success;
- int ok;
-
-
- class = pmap->class;
- if(!(class & DynamicClass) && !(pmap->flags & BeingCreated))
- {
- return(BadAccess);
- }
- pVisual = pmap->pVisual;
-
- idef = 0;
- if((class | DynamicClass) == DirectColor)
- {
- int numred, numgreen, numblue;
- Pixel rgbbad;
-
- numred = NUMRED(pVisual);
- numgreen = NUMGREEN(pVisual);
- numblue = NUMBLUE(pVisual);
- rgbbad = ~RGBMASK(pVisual);
- for (pdef = defs, n = 0; n < count; pdef++, n++)
- {
- ok = TRUE;
- (*pmap->pScreen->ResolveColor)
- (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
-
- if (pdef->pixel & rgbbad)
- {
- errVal = BadValue;
- clientErrorValue = pdef->pixel;
- continue;
- }
- pix = (pdef->pixel & pVisual->redMask) >> pVisual->offsetRed;
- if (pix >= numred)
- {
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->red[pix].refcnt != AllocPrivate)
- {
- errVal = BadAccess;
- ok = FALSE;
- }
- else if (pdef->flags & DoRed)
- {
- pmap->red[pix].co.local.red = pdef->red;
- }
- else
- {
- pdef->red = pmap->red[pix].co.local.red;
- }
-
- pix = (pdef->pixel & pVisual->greenMask) >> pVisual->offsetGreen;
- if (pix >= numgreen)
- {
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->green[pix].refcnt != AllocPrivate)
- {
- errVal = BadAccess;
- ok = FALSE;
- }
- else if (pdef->flags & DoGreen)
- {
- pmap->green[pix].co.local.green = pdef->green;
- }
- else
- {
- pdef->green = pmap->green[pix].co.local.green;
- }
-
- pix = (pdef->pixel & pVisual->blueMask) >> pVisual->offsetBlue;
- if (pix >= numblue)
- {
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->blue[pix].refcnt != AllocPrivate)
- {
- errVal = BadAccess;
- ok = FALSE;
- }
- else if (pdef->flags & DoBlue)
- {
- pmap->blue[pix].co.local.blue = pdef->blue;
- }
- else
- {
- pdef->blue = pmap->blue[pix].co.local.blue;
- }
- /* If this is an o.k. entry, then it gets added to the list
- * to be sent to the hardware. If not, skip it. Once we've
- * skipped one, we have to copy all the others.
- */
- if(ok)
- {
- if(idef != n)
- defs[idef] = defs[n];
- idef++;
- } else
- clientErrorValue = pdef->pixel;
- }
- }
- else
- {
- for (pdef = defs, n = 0; n < count; pdef++, n++)
- {
-
- ok = TRUE;
- if (pdef->pixel >= pVisual->ColormapEntries)
- {
- clientErrorValue = pdef->pixel;
- errVal = BadValue;
- ok = FALSE;
- }
- else if (pmap->red[pdef->pixel].refcnt != AllocPrivate)
- {
- errVal = BadAccess;
- ok = FALSE;
- }
-
- /* If this is an o.k. entry, then it gets added to the list
- * to be sent to the hardware. If not, skip it. Once we've
- * skipped one, we have to copy all the others.
- */
- if(ok)
- {
- if(idef != n)
- defs[idef] = defs[n];
- idef++;
- }
- else
- continue;
-
- (*pmap->pScreen->ResolveColor)
- (&pdef->red, &pdef->green, &pdef->blue, pmap->pVisual);
-
- pent = &pmap->red[pdef->pixel];
-
- if(pdef->flags & DoRed)
- {
- if(pent->fShared)
- {
- pent->co.shco.red->color = pdef->red;
- if (pent->co.shco.red->refcnt > 1)
- ok = FALSE;
- }
- else
- pent->co.local.red = pdef->red;
- }
- else
- {
- if(pent->fShared)
- pdef->red = pent->co.shco.red->color;
- else
- pdef->red = pent->co.local.red;
- }
- if(pdef->flags & DoGreen)
- {
- if(pent->fShared)
- {
- pent->co.shco.green->color = pdef->green;
- if (pent->co.shco.green->refcnt > 1)
- ok = FALSE;
- }
- else
- pent->co.local.green = pdef->green;
- }
- else
- {
- if(pent->fShared)
- pdef->green = pent->co.shco.green->color;
- else
- pdef->green = pent->co.local.green;
- }
- if(pdef->flags & DoBlue)
- {
- if(pent->fShared)
- {
- pent->co.shco.blue->color = pdef->blue;
- if (pent->co.shco.blue->refcnt > 1)
- ok = FALSE;
- }
- else
- pent->co.local.blue = pdef->blue;
- }
- else
- {
- if(pent->fShared)
- pdef->blue = pent->co.shco.blue->color;
- else
- pdef->blue = pent->co.local.blue;
- }
-
- if(!ok)
- {
- /* have to run through the colormap and change anybody who
- * shares this value */
- pred = pent->co.shco.red;
- pgreen = pent->co.shco.green;
- pblue = pent->co.shco.blue;
- ChgRed = pdef->flags & DoRed;
- ChgGreen = pdef->flags & DoGreen;
- ChgBlue = pdef->flags & DoBlue;
- pentLast = pmap->red + pVisual->ColormapEntries;
-
- for(pentT = pmap->red; pentT < pentLast; pentT++)
- {
- if(pentT->fShared && (pentT != pent))
- {
- xColorItem defChg;
-
- /* There are, alas, devices in this world too dumb
- * to read their own hardware colormaps. Sick, but
- * true. So we're going to be really nice and load
- * the xColorItem with the proper value for all the
- * fields. We will only set the flags for those
- * fields that actually change. Smart devices can
- * arrange to change only those fields. Dumb devices
- * can rest assured that we have provided for them,
- * and can change all three fields */
-
- defChg.flags = 0;
- if(ChgRed && pentT->co.shco.red == pred)
- {
- defChg.flags |= DoRed;
- }
- if(ChgGreen && pentT->co.shco.green == pgreen)
- {
- defChg.flags |= DoGreen;
- }
- if(ChgBlue && pentT->co.shco.blue == pblue)
- {
- defChg.flags |= DoBlue;
- }
- if(defChg.flags != 0)
- {
- defChg.pixel = pentT - pmap->red;
- defChg.red = pentT->co.shco.red->color;
- defChg.green = pentT->co.shco.green->color;
- defChg.blue = pentT->co.shco.blue->color;
- (*pmap->pScreen->StoreColors) (pmap, 1, &defChg);
- }
- }
- }
-
- }
- }
- }
- /* Note that we use idef, the count of acceptable entries, and not
- * count, the count of proposed entries */
- if (idef != 0)
- ( *pmap->pScreen->StoreColors) (pmap, idef, defs);
- return (errVal);
-}
-
-int
-IsMapInstalled(map, pWin)
- Colormap map;
- WindowPtr pWin;
-{
- Colormap *pmaps;
- int imap, nummaps, found;
-
- pmaps = (Colormap *) ALLOCATE_LOCAL(
- pWin->drawable.pScreen->maxInstalledCmaps * sizeof(Colormap));
- if(!pmaps)
- return(FALSE);
- nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
- (pWin->drawable.pScreen, pmaps);
- found = FALSE;
- for(imap = 0; imap < nummaps; imap++)
- {
- if(pmaps[imap] == map)
- {
- found = TRUE;
- break;
- }
- }
- DEALLOCATE_LOCAL(pmaps);
- return (found);
-}