1153 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			1153 lines
		
	
	
		
			28 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $Xorg: lbxcmap.c,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */
 | |
| 
 | |
| /*
 | |
| Copyright 1996, 1998  The Open Group
 | |
| 
 | |
| Permission to use, copy, modify, distribute, and sell this software and its
 | |
| documentation for any purpose is hereby granted without fee, provided that
 | |
| the above copyright notice appear in all copies and that both that
 | |
| copyright notice and this permission notice appear in supporting
 | |
| documentation.
 | |
| 
 | |
| 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 OPEN GROUP 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 Open Group 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 Open Group.
 | |
| */
 | |
| /* $XFree86: xc/programs/Xserver/lbx/lbxcmap.c,v 1.9 2001/08/23 14:46:57 alanh Exp $ */
 | |
| 
 | |
| #include <sys/types.h>
 | |
| #define NEED_REPLIES
 | |
| #define NEED_EVENTS
 | |
| #include "X.h"
 | |
| #include "Xproto.h"
 | |
| #include "Xos.h"
 | |
| #include "misc.h"
 | |
| #include "os.h"
 | |
| #include "dixstruct.h"
 | |
| #include "resource.h"
 | |
| #include "scrnintstr.h"
 | |
| #include "colormapst.h"
 | |
| #include "propertyst.h"
 | |
| #define _XLBX_SERVER_
 | |
| #include "lbxstr.h"
 | |
| #include "lbxserve.h"
 | |
| #include "Xfuncproto.h"
 | |
| #include <stdio.h>
 | |
| 
 | |
| static int lbxScreenPrivIndex;		/* lbx screen private index */
 | |
| static int lbxColormapPrivIndex;	/* lbx colormap private index */
 | |
| 
 | |
| typedef struct {			/* lbx screen private */
 | |
|     CreateColormapProcPtr CreateColormap;
 | |
|     DestroyColormapProcPtr DestroyColormap;
 | |
|   CloseScreenProcPtr CloseScreen;
 | |
| } LbxScreenPriv;
 | |
| 
 | |
| typedef struct _LbxStalled {
 | |
|     XID id;
 | |
|     struct _LbxStalled *next;
 | |
| } LbxStalled;
 | |
| 
 | |
| typedef struct _LbxColormapPriv {	/* lbx colormap private */
 | |
|     char	grab_status;
 | |
|     char	smart_grab;
 | |
|     LbxProxyPtr	grabber;
 | |
|     int		last_grabber;	/* uid, not pid */
 | |
|     LbxStalled	*stalled_clients;
 | |
|     ColormapPtr	next;		/* proxy chain */
 | |
| } LbxColormapPriv;
 | |
| 
 | |
| #define CMAP_NOT_GRABBED	0
 | |
| #define CMAP_GRABBED		1
 | |
| #define CMAP_WAITING_FOR_UNGRAB	2
 | |
| 
 | |
| static int LbxUnstallClient(pointer data, XID id);
 | |
| 
 | |
| static RESTYPE StalledResType;
 | |
| 
 | |
| /*
 | |
|  * Initialize the fields in the colormap private allocated for LBX.
 | |
|  */
 | |
| 
 | |
| static LbxColormapPriv *
 | |
| LbxColormapPrivInit (ColormapPtr pmap)
 | |
| {
 | |
|     LbxColormapPriv *cmapPriv;
 | |
| 
 | |
|     cmapPriv = (LbxColormapPriv *) xalloc (sizeof (LbxColormapPriv));
 | |
|     if (!cmapPriv)
 | |
| 	return cmapPriv;
 | |
| 
 | |
|     pmap->devPrivates[lbxColormapPrivIndex].ptr = (pointer) cmapPriv;
 | |
| 
 | |
|     cmapPriv->grab_status = CMAP_NOT_GRABBED;
 | |
|     cmapPriv->grabber = NULL;
 | |
|     cmapPriv->last_grabber = 0;
 | |
|     cmapPriv->smart_grab = FALSE;
 | |
|     cmapPriv->stalled_clients = NULL;
 | |
|     cmapPriv->next = NULL;
 | |
| 
 | |
|     return cmapPriv;
 | |
| }
 | |
| 
 | |
| 
 | |
| static int
 | |
| LbxDefCmapPrivInit (ColormapPtr pmap, int index)
 | |
| {
 | |
| #if 0
 | |
|     /* BUG: You can't do that. lbxColormapPrivIndex hasn't 
 | |
| 	been initialized yet.  */
 | |
|     pmap->devPrivates[lbxColormapPrivIndex].ptr = NULL;
 | |
| #endif
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| LbxCreateColormap (ColormapPtr pmap)
 | |
| {
 | |
|     ScreenPtr pScreen = pmap->pScreen;
 | |
|     Bool ret;
 | |
| 
 | |
|     pScreen->CreateColormap = ((LbxScreenPriv *) (pScreen->devPrivates[
 | |
| 	lbxScreenPrivIndex].ptr))->CreateColormap;
 | |
| 
 | |
|     pmap->devPrivates[lbxColormapPrivIndex].ptr = NULL;
 | |
|     ret = (*pScreen->CreateColormap) (pmap);
 | |
|  
 | |
|     pScreen->CreateColormap = LbxCreateColormap;
 | |
| 
 | |
|     return ret;
 | |
| }
 | |
| 
 | |
| static void
 | |
| LbxDestroyColormap (ColormapPtr pmap)
 | |
| {
 | |
|     ScreenPtr pScreen = pmap->pScreen;
 | |
| 
 | |
|     LbxReleaseCmap(pmap, FALSE);
 | |
|     pScreen->DestroyColormap = ((LbxScreenPriv *) (pScreen->devPrivates[
 | |
| 	lbxScreenPrivIndex].ptr))->DestroyColormap;
 | |
|     (*pScreen->DestroyColormap) (pmap);
 | |
|     if (pmap->devPrivates && pmap->devPrivates[lbxColormapPrivIndex].ptr)
 | |
| 	xfree(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | |
|     pScreen->DestroyColormap = LbxDestroyColormap;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| LbxCloseScreen(int i, ScreenPtr pScreen)
 | |
| {
 | |
|     LbxScreenPriv* pLbxScrPriv = ((LbxScreenPriv *) 
 | |
| 			     (pScreen->devPrivates[lbxScreenPrivIndex].ptr));
 | |
|     
 | |
|     pScreen->CloseScreen = pLbxScrPriv->CloseScreen;
 | |
| 
 | |
|     xfree(pScreen->devPrivates[lbxScreenPrivIndex].ptr);
 | |
|     pScreen->devPrivates[lbxScreenPrivIndex].ptr = NULL;
 | |
| 
 | |
|     return pScreen->CloseScreen(i, pScreen);
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Initialize LBX colormap private.
 | |
|  */
 | |
| 
 | |
| int
 | |
| LbxCmapInit (void)
 | |
| 
 | |
| {
 | |
|     LbxScreenPriv *pScreenPriv;
 | |
|     ColormapPtr defMap;
 | |
|     ScreenPtr pScreen;
 | |
|     int i;
 | |
| 
 | |
|     StalledResType = CreateNewResourceType(LbxUnstallClient);
 | |
| 
 | |
|     lbxScreenPrivIndex = AllocateScreenPrivateIndex ();
 | |
|     if (lbxScreenPrivIndex < 0)
 | |
| 	return 0;
 | |
| 
 | |
|     lbxColormapPrivIndex = AllocateColormapPrivateIndex (LbxDefCmapPrivInit);
 | |
|     if (lbxColormapPrivIndex < 0)
 | |
| 	return 0;
 | |
| 
 | |
|     for (i = 0; i < screenInfo.numScreens; i++)
 | |
|     {
 | |
| 	pScreen = screenInfo.screens[i];
 | |
| 
 | |
|         defMap = (ColormapPtr) LookupIDByType(
 | |
| 			pScreen->defColormap, RT_COLORMAP);
 | |
| 
 | |
| 	/* now lbxColormapPrivIndex exists */
 | |
|         defMap->devPrivates[lbxColormapPrivIndex].ptr = NULL;
 | |
| 
 | |
| 	pScreenPriv = (LbxScreenPriv *) xalloc (sizeof (LbxScreenPriv));
 | |
| 	if (!pScreenPriv)
 | |
| 	    return 0;
 | |
| 
 | |
| 	pScreenPriv->CreateColormap = pScreen->CreateColormap;
 | |
| 	pScreen->CreateColormap = LbxCreateColormap;
 | |
| 	pScreenPriv->DestroyColormap = pScreen->DestroyColormap;
 | |
| 	pScreen->DestroyColormap = LbxDestroyColormap;
 | |
| 	pScreenPriv->CloseScreen = pScreen->CloseScreen;
 | |
| 	pScreen->CloseScreen = LbxCloseScreen;
 | |
| 	pScreen->devPrivates[lbxScreenPrivIndex].ptr = (pointer) pScreenPriv;
 | |
|     }
 | |
| 
 | |
|     return 1;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Return the number of allocated cells in the PSEUDO colormap.
 | |
|  */
 | |
| 
 | |
| static int
 | |
| NumAllocatedCells (EntryPtr pent,
 | |
| 		   int size)
 | |
| {
 | |
|     Pixel pixel;
 | |
|     int count = 0;
 | |
| 
 | |
|     for (pixel = 0; pixel < size; pixel++)
 | |
|     {
 | |
| 	if (pent[pixel].refcnt != 0 && pent[pixel].refcnt != AllocTemporary)
 | |
| 	    count++;
 | |
|     }
 | |
| 
 | |
|     return count;
 | |
| }
 | |
| 
 | |
| #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 PIX_OUT(ptr,is2,val) \
 | |
|     if (is2) *ptr++ = (val) >> 8; \
 | |
|     *ptr++ = (val)
 | |
| #define RGB_OUT(ptr,is2,shift,val) \
 | |
|     *ptr++ = (val) >> shift; \
 | |
|     if (is2) *ptr++ = (val)
 | |
| 
 | |
| /*
 | |
|  * Return the list of allocated cells in the channel in
 | |
|  * the format required by LbxGrabCmapReply.
 | |
|  */
 | |
| 
 | |
| static CARD8 *
 | |
| OutputChannel(ColormapPtr pmap,
 | |
| 	      EntryPtr chan,
 | |
| 	      int size,
 | |
| 	      CARD8 *ptr,
 | |
| 	      CARD8 flags,
 | |
| 	      CARD8 channels)
 | |
| {
 | |
|     Bool	px2;
 | |
|     Bool	rgb2;
 | |
|     int		shift;
 | |
|     int		rgb_sz;
 | |
|     Pixel	pixel;
 | |
|     EntryPtr	pent;
 | |
|     CARD8 *pixel_private_range_ptr = NULL;
 | |
|     CARD8 *pixel_shared_range_ptr = NULL;
 | |
|     int		allocpriv;
 | |
| 
 | |
|     px2 = (flags & LBX_2BYTE_PIXELS) != 0;
 | |
|     rgb2 = (flags & LBX_RGB_BITS_MASK) > 7;
 | |
|     if (rgb2)
 | |
| 	shift = 8;
 | |
|     else
 | |
| 	shift = 15 - (flags & LBX_RGB_BITS_MASK);
 | |
|     rgb_sz = rgb2 + 1;
 | |
|     if (channels == (DoRed|DoGreen|DoBlue))
 | |
| 	rgb_sz *= 3;
 | |
|     /* kinda gross, but ddxen use AllocAll on static maps */
 | |
|     allocpriv = (pmap->pVisual->class & DynamicClass) ? AllocPrivate : 0;
 | |
|     for (pixel = 0; pixel < size; pixel++)
 | |
|     {
 | |
| 	pent = (EntryPtr) &chan[pixel];
 | |
| 
 | |
| 	if (pent->refcnt == 0 || pent->refcnt == AllocTemporary)
 | |
| 	{
 | |
| 	    /*
 | |
| 	     * A free pixel.  This disrupts all ranges.
 | |
| 	     */
 | |
| 
 | |
| 	    pixel_private_range_ptr = pixel_shared_range_ptr = NULL;
 | |
| 
 | |
| 	    continue;
 | |
| 	}
 | |
| 	else if (pent->refcnt == allocpriv)
 | |
| 	{
 | |
| 	    /*
 | |
| 	     * A private pixel.  This disrupts any PIXEL_SHARED_RANGE.
 | |
| 	     */
 | |
| 
 | |
| 	    pixel_shared_range_ptr = NULL;
 | |
| 
 | |
| 	    if (!pixel_private_range_ptr)
 | |
| 	    {
 | |
| 		pixel_private_range_ptr = ptr;
 | |
| 
 | |
| 		*ptr++ = LBX_PIXEL_PRIVATE;
 | |
| 		PIX_OUT(ptr, px2, pixel);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		CARD8 *pos = pixel_private_range_ptr + 2 + px2;
 | |
| 		if (*pixel_private_range_ptr == LBX_PIXEL_PRIVATE) {
 | |
| 		    *pixel_private_range_ptr = LBX_PIXEL_RANGE_PRIVATE;
 | |
| 		    ptr += 1 + px2;
 | |
| 		}
 | |
| 		PIX_OUT(pos, px2, pixel);
 | |
| 	    }
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    /*
 | |
| 	     * A shared pixel.  This disrupts any PIXEL_PRIVATE_RANGE.
 | |
| 	     */
 | |
| 
 | |
| 	    pixel_private_range_ptr = NULL;
 | |
| 
 | |
| 	    if (!pixel_shared_range_ptr)
 | |
| 	    {
 | |
| 		pixel_shared_range_ptr = ptr;
 | |
| 
 | |
| 		*ptr++ = LBX_PIXEL_SHARED;
 | |
| 		PIX_OUT(ptr, px2, pixel);
 | |
| 	    }
 | |
| 	    else
 | |
| 	    {
 | |
| 		CARD8 *pos = pixel_shared_range_ptr + 2 + px2;
 | |
| 		if (*pixel_shared_range_ptr == LBX_PIXEL_SHARED)
 | |
| 		{
 | |
| 		    *pixel_shared_range_ptr = LBX_PIXEL_RANGE_SHARED;
 | |
| 		    memmove (pos + 1 + px2, pos, rgb_sz);
 | |
| 		    ptr += 1 + px2;
 | |
| 		}
 | |
| 		PIX_OUT(pos, px2, pixel);
 | |
| 	    }
 | |
| 
 | |
| 	    if (channels & DoRed) {
 | |
| 		RGB_OUT(ptr, rgb2, shift, pent->co.local.red);
 | |
| 	    }
 | |
| 	    if (channels & DoGreen) {
 | |
| 		RGB_OUT(ptr, rgb2, shift, pent->co.local.green);
 | |
| 	    }
 | |
| 	    if (channels & DoBlue) {
 | |
| 		RGB_OUT(ptr, rgb2, shift, pent->co.local.blue);
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
|     return ptr;
 | |
| }
 | |
| 
 | |
| static void
 | |
| GetAllocatedCells (ColormapPtr pmap,
 | |
| 		   CARD8 *flags,
 | |
| 		   CARD8 *buf,
 | |
| 		   int *bytes)
 | |
| {
 | |
|     CARD8	*ptr;
 | |
| 
 | |
|     *flags = pmap->pVisual->bitsPerRGBValue - 1;
 | |
|     if (pmap->pVisual->ColormapEntries > 256)
 | |
| 	*flags |= LBX_2BYTE_PIXELS;
 | |
|     if (!(pmap->pVisual->class & DynamicClass))
 | |
| 	*flags |= LBX_AUTO_RELEASE;
 | |
|     if ((pmap->pVisual->class | DynamicClass) == DirectColor) {
 | |
| 	*flags |= LBX_3CHANNELS;
 | |
| 	ptr = OutputChannel(pmap, pmap->red, NUMRED(pmap->pVisual),
 | |
| 			    buf, *flags, DoRed);
 | |
| 	*ptr++ = LBX_NEXT_CHANNEL;
 | |
| 	ptr = OutputChannel(pmap, pmap->green, NUMGREEN(pmap->pVisual),
 | |
| 			    ptr, *flags, DoGreen);
 | |
| 	*ptr++ = LBX_NEXT_CHANNEL;
 | |
| 	ptr = OutputChannel(pmap, pmap->blue, NUMBLUE(pmap->pVisual),
 | |
| 			    ptr, *flags, DoBlue);
 | |
|     } else
 | |
| 	ptr = OutputChannel(pmap, pmap->red, pmap->pVisual->ColormapEntries,
 | |
| 			    buf, *flags, DoRed|DoGreen|DoBlue);
 | |
|     *ptr++ = LBX_LIST_END;
 | |
|     *bytes = ptr - buf;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Send an LbxReleaseCmapEvent to a proxy.
 | |
|  */
 | |
| 
 | |
| static void
 | |
| SendReleaseCmapEvent (LbxProxyPtr proxy,
 | |
| 		      Colormap cmap)
 | |
| {
 | |
|     xLbxReleaseCmapEvent ev;
 | |
|     ClientPtr client;
 | |
|     LbxClientPtr lbxcp;
 | |
|     int n;
 | |
| 
 | |
|     lbxcp = proxy->lbxClients[0];
 | |
| 
 | |
|     if (lbxcp && (client = lbxcp->client))
 | |
|     {
 | |
| 	ev.type = LbxEventCode;
 | |
| 	ev.lbxType = LbxReleaseCmapEvent;
 | |
| 	ev.sequenceNumber = client->sequence;
 | |
| 	ev.colormap = cmap;
 | |
| 	ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = ev.pad5 = ev.pad6 = 0;
 | |
| 
 | |
| 	if (client->swapped)
 | |
| 	{
 | |
| 	    swaps(&ev.sequenceNumber, n);
 | |
| 	    swapl(&ev.colormap, n);
 | |
| 	}
 | |
| 
 | |
| 	WriteToClient(client, sz_xLbxReleaseCmapEvent, (char *) &ev);
 | |
| 	LbxForceOutput(proxy);
 | |
| 
 | |
| #ifdef COLOR_DEBUG
 | |
| 	fprintf (stderr,
 | |
| 	    "Sent LbxReleaseCmapEvent to proxy %d, seq = 0x%x, cmap = 0x%x\n",
 | |
| 	    proxy->pid, client->sequence, cmap);
 | |
| #endif
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * WaitForServerCmapControl checks if the colormap is grabbed by a proxy,
 | |
|  * and if so, sends an LbxReleaseCmapEvent to the proxy.  It then suspends
 | |
|  * the current request until the server gets the ReleaseCmap message from
 | |
|  * the proxy.
 | |
|  */
 | |
| 
 | |
| static Bool
 | |
| WaitForServerCmapControl (ClientPtr client,
 | |
| 			  ColormapPtr pmap)
 | |
| {
 | |
|     LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | |
| 	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | |
|     LbxStalled *stalled;
 | |
| 
 | |
|     if (cmapPriv->grab_status == CMAP_GRABBED)
 | |
|     {
 | |
| 	/*
 | |
| 	 * Send an LbxReleaseCmapEvent to the proxy that has the grab.
 | |
| 	 */
 | |
| 
 | |
| 	SendReleaseCmapEvent (cmapPriv->grabber, pmap->mid);
 | |
| 	cmapPriv->grab_status = CMAP_WAITING_FOR_UNGRAB;
 | |
|     }
 | |
| 
 | |
|     stalled = (LbxStalled *)xalloc(sizeof(LbxStalled));
 | |
|     if (!stalled)
 | |
| 	return FALSE;
 | |
|     stalled->id = FakeClientID(client->index);
 | |
|     stalled->next = cmapPriv->stalled_clients;
 | |
|     cmapPriv->stalled_clients = stalled;
 | |
|     return AddResource(stalled->id, StalledResType, (pointer)cmapPriv);
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * When the X server gets any of the requests that allocate color cells,
 | |
|  * it calls LbxCheckColorRequest on the request.  This function will check
 | |
|  * if the colormap is grabbed by a proxy, and if so, will suspend the
 | |
|  * current request and wait for the proxy to release the colormap.
 | |
|  */
 | |
| 
 | |
| Bool
 | |
| LbxCheckColorRequest (ClientPtr client,
 | |
| 		      ColormapPtr pmap,
 | |
| 		      xReq *req)
 | |
| {
 | |
|     LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | |
| 	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | |
| 
 | |
|     if (!cmapPriv)
 | |
| 	return FALSE;
 | |
| 
 | |
|     if (cmapPriv->grab_status != CMAP_NOT_GRABBED)
 | |
|     {
 | |
| 	/*
 | |
| 	 * The colormap is grabbed by a proxy.  Reset this request, and
 | |
| 	 * process it after the server gets back control of the colormap.
 | |
| 	 * Before we reset the request, we must put it back in the
 | |
| 	 * client's byte order.
 | |
| 	 */
 | |
| 
 | |
| 	if (!WaitForServerCmapControl (client, pmap))
 | |
| 	    return FALSE;
 | |
| 
 | |
| 	if (client->swapped)
 | |
| 	{
 | |
| 	    register int n;
 | |
| 
 | |
| 	    switch (req->reqType)
 | |
| 	    {
 | |
| 	    case X_AllocColor:
 | |
| 	    {
 | |
| 		xAllocColorReq *stuff = (xAllocColorReq *) req;
 | |
| 		swaps(&stuff->length, n);
 | |
| 		swapl(&stuff->cmap, n);
 | |
| 		swaps(&stuff->red, n);
 | |
| 		swaps(&stuff->green, n);
 | |
| 		swaps(&stuff->blue, n);
 | |
| 		break;
 | |
| 	    }
 | |
| 	    case X_AllocNamedColor:
 | |
| 	    {
 | |
| 		xAllocNamedColorReq *stuff = (xAllocNamedColorReq *) req;
 | |
| 		swaps(&stuff->length, n);
 | |
| 		swapl(&stuff->cmap, n);
 | |
| 		swaps(&stuff->nbytes, n);
 | |
| 		break;
 | |
| 	    }
 | |
| 	    case X_AllocColorCells:
 | |
| 	    {
 | |
| 		xAllocColorCellsReq *stuff = (xAllocColorCellsReq *) req;
 | |
| 		swaps(&stuff->length, n);
 | |
| 		swapl(&stuff->cmap, n);
 | |
| 		swaps(&stuff->colors, n);
 | |
| 		swaps(&stuff->planes, n);
 | |
| 		break;
 | |
| 	    }
 | |
| 	    case X_AllocColorPlanes:
 | |
| 	    {
 | |
| 		xAllocColorPlanesReq *stuff = (xAllocColorPlanesReq *) req;
 | |
| 		swaps(&stuff->length, n);
 | |
| 		swapl(&stuff->cmap, n);
 | |
| 		swaps(&stuff->colors, n);
 | |
| 		swaps(&stuff->red, n);
 | |
| 		swaps(&stuff->green, n);
 | |
| 		swaps(&stuff->blue, n);
 | |
| 		break;
 | |
| 	    }
 | |
| 	    default:
 | |
| 		break;
 | |
| 	    }
 | |
| 	}
 | |
| 
 | |
| 	ResetCurrentRequest(client);
 | |
| 	client->sequence--;
 | |
| 	IgnoreClient(client);
 | |
| 
 | |
| 	return TRUE;
 | |
|     }
 | |
| 
 | |
|     if (!LbxClient(client) ||
 | |
| 	LbxProxy(client)->uid != cmapPriv->last_grabber)
 | |
|     {
 | |
| 	/*
 | |
| 	 * Next time the proxy for this client does a colormap grab, it
 | |
| 	 * will have to get the colormap state (a non-smart grab).
 | |
| 	 */
 | |
| 
 | |
| 	cmapPriv->smart_grab = FALSE;
 | |
|     }
 | |
| 
 | |
|     return FALSE;
 | |
| }
 | |
| 
 | |
| static Bool
 | |
| LbxGrabbedByClient (ClientPtr client,
 | |
| 		    ColormapPtr pmap)
 | |
| {
 | |
|     LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | |
| 	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | |
|     return (cmapPriv &&
 | |
| 	    (cmapPriv->grab_status != CMAP_NOT_GRABBED) &&
 | |
| 	    (cmapPriv->grabber == LbxProxy(client)));
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Check if a colormap is grabbed by a proxy.
 | |
|  */
 | |
| 
 | |
| int
 | |
| LbxCheckCmapGrabbed (ColormapPtr pmap)
 | |
| {
 | |
|     LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | |
| 	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | |
| 
 | |
|     return (cmapPriv && (cmapPriv->grab_status == CMAP_GRABBED));
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Disable a smart grab on the specified colormap.
 | |
|  */
 | |
| 
 | |
| void
 | |
| LbxDisableSmartGrab (ColormapPtr pmap)
 | |
| {
 | |
|     LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | |
| 	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | |
| 
 | |
|     if (cmapPriv)
 | |
| 	cmapPriv->smart_grab = FALSE;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Send an LbxFreeCellsEvent to the specified proxy.
 | |
|  */
 | |
| 
 | |
| static void
 | |
| SendFreeCellsEvent (LbxProxyPtr proxy,
 | |
| 		    Colormap cmap,
 | |
| 		    Pixel pixel_start,
 | |
| 		    Pixel pixel_end)
 | |
| {
 | |
|     xLbxFreeCellsEvent ev;
 | |
|     ClientPtr client;
 | |
|     LbxClientPtr lbxcp;
 | |
|     int n;
 | |
| 
 | |
|     lbxcp = proxy->lbxClients[0];
 | |
| 
 | |
|     if (lbxcp && (client = lbxcp->client))
 | |
|     {
 | |
| 	ev.type = LbxEventCode;
 | |
| 	ev.lbxType =  LbxFreeCellsEvent;
 | |
| 	ev.sequenceNumber = client->sequence;
 | |
| 	ev.colormap = cmap;
 | |
| 	ev.pixelStart = pixel_start;
 | |
| 	ev.pixelEnd = pixel_end;
 | |
| 	ev.pad1 = ev.pad2 = ev.pad3 = ev.pad4 = 0;
 | |
| 
 | |
| 	if (client->swapped)
 | |
| 	{
 | |
| 	    swaps(&ev.sequenceNumber, n);
 | |
| 	    swapl(&ev.colormap, n);
 | |
| 	    swapl(&ev.pixelStart, n);
 | |
| 	    swapl(&ev.pixelEnd, n);
 | |
| 	}
 | |
| 
 | |
| 	WriteToClient(client, sz_xLbxFreeCellsEvent, (char *) &ev);
 | |
| 	LbxForceOutput(proxy);
 | |
| #ifdef COLOR_DEBUG
 | |
| 	fprintf (stderr, "Sent LbxFreeCellsEvent to proxy %d, seq = 0x%x\n",
 | |
| 	    proxy->pid, client->sequence);
 | |
| 	fprintf (stderr, "   cmap = 0x%x, pixelStart = %d, pixelEnd = %d\n",
 | |
| 	    cmap, pixel_start, pixel_end);
 | |
| #endif
 | |
|     }
 | |
| }
 | |
| 
 | |
| /* XXX use of globals like this is gross */
 | |
| static long pixel_start;
 | |
| static long pixel_end;
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * LbxFreeCellsEvent generation functions.
 | |
|  */
 | |
| 
 | |
| /*ARGSUSED*/
 | |
| void
 | |
| LbxBeginFreeCellsEvent (ColormapPtr pmap)
 | |
| {
 | |
|     pixel_start = -1;
 | |
|     pixel_end = -1;
 | |
| }
 | |
| 
 | |
| 
 | |
| void
 | |
| LbxAddFreeCellToEvent (ColormapPtr pmap,
 | |
| 		       Pixel pixel)
 | |
| {
 | |
|     /*
 | |
|      * We must notify the proxy that has this colormap
 | |
|      * grabbed which cells are being freed (their refcount
 | |
|      * has reached zero).
 | |
|      */
 | |
| 
 | |
|     if (pixel_start == -1)
 | |
| 	pixel_start = pixel;
 | |
|     else
 | |
|     {
 | |
| 	if (pixel_end == -1)
 | |
| 	    pixel_end = pixel;
 | |
| 	else
 | |
| 	{
 | |
| 	    if (pixel_end + 1 == pixel)
 | |
| 		pixel_end = pixel;
 | |
| 	    else if (pixel > pixel_end + 1)
 | |
| 	    {
 | |
| 		LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | |
| 		    (pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | |
| 
 | |
| 		SendFreeCellsEvent (cmapPriv->grabber,
 | |
| 				    pmap->mid, pixel_start, pixel_end);
 | |
| 
 | |
| 		pixel_start = pixel;
 | |
| 		pixel_end = -1;
 | |
| 	    }
 | |
| 	}
 | |
|     }
 | |
| }
 | |
| 
 | |
| void
 | |
| LbxEndFreeCellsEvent (ColormapPtr pmap)
 | |
| {
 | |
|     /*
 | |
|      * Check if there is an LbxFreeCellEvent we need to write.
 | |
|      */
 | |
| 
 | |
|     if (pixel_start != -1)
 | |
|     {
 | |
| 	LbxColormapPriv *cmapPriv = (LbxColormapPriv *)
 | |
| 	    (pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | |
| 
 | |
| 	SendFreeCellsEvent (cmapPriv->grabber,
 | |
| 			    pmap->mid, pixel_start,
 | |
| 			    pixel_end == -1 ? pixel_start : pixel_end);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Sort the specified pixel list.  This optimizes generation
 | |
|  * of LbxFreeCellsEvent.
 | |
|  */
 | |
| 
 | |
| void
 | |
| LbxSortPixelList (Pixel *pixels,
 | |
| 		  int count)
 | |
| {
 | |
|      int i, j;
 | |
| 
 | |
|      for (i = 0; i <= count - 2; i++)
 | |
| 	 for (j = count - 1; j > i; j--)
 | |
| 	    if (pixels[j - 1] > pixels[j])
 | |
| 	    {
 | |
| 		Pixel temp = pixels[j - 1];
 | |
| 		pixels[j - 1] = pixels[j];
 | |
| 		pixels[j] = temp;
 | |
| 	    }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Handle a colormap grab request from a proxy.
 | |
|  */
 | |
| 
 | |
| int
 | |
| ProcLbxGrabCmap(ClientPtr client)
 | |
| {
 | |
|     REQUEST(xLbxGrabCmapReq);
 | |
|     xLbxGrabCmapReply *reply;
 | |
|     Bool smartGrab;
 | |
|     LbxColormapPriv *cmapPriv;
 | |
|     ColormapPtr pmap;
 | |
|     int bytes, n;
 | |
|     LbxProxyPtr proxy = LbxProxy(client);
 | |
| 
 | |
|     client->sequence--;		/* not a counted request */
 | |
| 
 | |
|     pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap,
 | |
| 						 RT_COLORMAP,
 | |
| 						 SecurityWriteAccess);
 | |
| 
 | |
|     if (!pmap)
 | |
|     {
 | |
|         client->errorValue = stuff->cmap;
 | |
| 	return BadColor;
 | |
|     }
 | |
| 
 | |
|     cmapPriv = (LbxColormapPriv *)
 | |
| 	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | |
|     if (!cmapPriv)
 | |
|     {
 | |
| 	cmapPriv = LbxColormapPrivInit (pmap);
 | |
| 	if (!cmapPriv)
 | |
| 	    return BadAlloc;
 | |
|     }
 | |
| 
 | |
| 
 | |
|     /*
 | |
|      * We have a SMART GRAB if since this proxy last ungrabbed the
 | |
|      * colormap, no color cell was alloc'd by an entity other than
 | |
|      * this proxy (this includes other proxies as well as clients
 | |
|      * directly connected to the X server without a proxy).
 | |
|      *
 | |
|      * We want to optimize this special case because a proxy may give
 | |
|      * up a grab because it got a request that it could not handle
 | |
|      * (e.g. AllocNamedColor or LookupColor).  When it asks back for
 | |
|      * the grab, there is no need for the server to send the colormap
 | |
|      * state, because the proxy is already up to date on the state of
 | |
|      * the colormap.
 | |
|      *
 | |
|      * In order for this to work, the following assumptions are made
 | |
|      * about the proxy:
 | |
|      *
 | |
|      * - the proxy is kept up to date on all cell allocations made on its
 | |
|      *   behalf resulting from the following requests: AllocNamedColor, 
 | |
|      *   AllocColorCells, AllocColorPlanes
 | |
|      * - the proxy is kept up to date on all cells freed by any client
 | |
|      *   via the LbxFreeCell event.
 | |
|      */
 | |
| 
 | |
|     /* if proxy is this confused, give it full info */
 | |
|     if (cmapPriv->grab_status == CMAP_GRABBED && cmapPriv->grabber == proxy)
 | |
| 	LbxReleaseCmap(pmap, FALSE);
 | |
| 
 | |
|     if (proxy->uid != cmapPriv->last_grabber)
 | |
| 	cmapPriv->smart_grab = FALSE;
 | |
|     smartGrab = cmapPriv->smart_grab;
 | |
| 
 | |
| #ifdef COLOR_DEBUG
 | |
|     fprintf (stderr, "\nGot colormap grab request, ");
 | |
|     fprintf (stderr, "seq = 0x%x, proxy = %d, client = %d, cmap = 0x%x\n",
 | |
| 	client->sequence, proxy->pid, client->index, stuff->cmap);
 | |
| 
 | |
|     if (cmapPriv->grab_status == CMAP_NOT_GRABBED)
 | |
|     {
 | |
| 	fprintf (stderr, "cmap 0x%x is not grabbed by any proxy\n",
 | |
| 	    stuff->cmap);
 | |
| 	if (smartGrab)
 | |
| 	    fprintf (stderr, "This is a smart grab\n");
 | |
|     }
 | |
|     else if (cmapPriv->grab_status == CMAP_GRABBED)
 | |
|     {
 | |
| 	if (cmapPriv->grabber == proxy)
 | |
| 	{
 | |
| 	    fprintf (stderr, "cmap 0x%x is already grabbed by proxy %d\n",
 | |
| 	        stuff->cmap, proxy->pid);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    fprintf (stderr, "cmap 0x%x is currently grabbed by proxy %d\n",
 | |
| 	        stuff->cmap, cmapPriv->grabber->pid);
 | |
| 	}
 | |
|     }
 | |
|     else if (cmapPriv->grab_status == CMAP_WAITING_FOR_UNGRAB)
 | |
|     {
 | |
| 	fprintf (stderr,
 | |
| 	    "Already waiting for cmap 0x%x to be ungrabbed by proxy %d\n",
 | |
| 	    stuff->cmap, cmapPriv->grabber->pid);
 | |
|     }
 | |
| #endif
 | |
| 
 | |
|     if (cmapPriv->grab_status != CMAP_NOT_GRABBED &&
 | |
| 	cmapPriv->grabber != proxy)
 | |
|     {
 | |
| 	/*
 | |
| 	 * The colormap is grabbed by a proxy other than the one that
 | |
| 	 * is requesting this grab.  Reset this grab request, and process
 | |
|          * it after the server gets back control of the colormap.  Before
 | |
| 	 * we reset the request, we must put it back in the client's byte
 | |
| 	 * order.
 | |
| 	 */
 | |
| 
 | |
| 	if (!WaitForServerCmapControl (client, pmap))
 | |
| 	    return BadAlloc;
 | |
| 
 | |
| 	if (client->swapped)
 | |
| 	{
 | |
| 	    swaps(&stuff->length, n);
 | |
| 	    swapl(&stuff->cmap, n);
 | |
| 	}
 | |
| 
 | |
| 	ResetCurrentRequest(client);
 | |
| 	IgnoreClient(client);
 | |
| 
 | |
| 	return Success;
 | |
|     }
 | |
| 
 | |
|     if (pmap->pVisual->class & DynamicClass) {
 | |
| 	cmapPriv->grabber = proxy;
 | |
| 	cmapPriv->grab_status = CMAP_GRABBED;
 | |
| 	cmapPriv->next = proxy->grabbedCmaps;
 | |
| 	proxy->grabbedCmaps = pmap;
 | |
|     } else
 | |
| 	smartGrab = FALSE;
 | |
| 
 | |
|     /*
 | |
|      * For an smart grab (see comments above), there is no information
 | |
|      * sent about the colormap cells because the proxy is all up to date.
 | |
|      * Otherwise, the server sends the proxy the state of all allocated
 | |
|      * cells in the colormap.  All cells not specified are assumed free.
 | |
|      */
 | |
| 
 | |
|     bytes = 0;
 | |
|     if (!smartGrab) {
 | |
| 	if ((pmap->pVisual->class | DynamicClass) == DirectColor) {
 | |
| 	    bytes = NumAllocatedCells(pmap->red,
 | |
| 				      NUMRED(pmap->pVisual)) * 9;
 | |
| 	    bytes += NumAllocatedCells(pmap->green,
 | |
| 				       NUMGREEN(pmap->pVisual)) * 9;
 | |
| 	    bytes += NumAllocatedCells(pmap->blue,
 | |
| 				       NUMBLUE(pmap->pVisual)) * 9;
 | |
| 	    bytes += 2;
 | |
| 	} else
 | |
| 	    bytes = NumAllocatedCells(pmap->red,
 | |
| 				      pmap->pVisual->ColormapEntries) * 9;
 | |
|     }
 | |
|     bytes += sz_xLbxGrabCmapReply + 1;
 | |
|     reply = (xLbxGrabCmapReply *) xalloc (bytes);
 | |
|     bzero (reply, sz_xLbxGrabCmapReply);
 | |
| 
 | |
|     if (smartGrab)
 | |
|     {
 | |
| 	reply->flags = LBX_SMART_GRAB;
 | |
| 	reply->length = 0;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
| 	GetAllocatedCells (pmap, &reply->flags,
 | |
| 			   (CARD8 *) reply + sz_xLbxGrabCmapReplyHdr, &bytes);
 | |
| 	if (bytes <= (sz_xLbxGrabCmapReply - sz_xLbxGrabCmapReplyHdr))
 | |
| 	    reply->length = 0;
 | |
| 	else
 | |
| 	    reply->length = (sz_xLbxGrabCmapReplyHdr +
 | |
| 		bytes - sz_xLbxGrabCmapReply + 3) >> 2;
 | |
|     }
 | |
| 
 | |
|     reply->type = X_Reply;
 | |
|     reply->sequenceNumber = client->sequence;
 | |
| 
 | |
|     bytes = sz_xLbxGrabCmapReply + (reply->length << 2);
 | |
| 
 | |
|     if (client->swapped)
 | |
|     {
 | |
| 	register char n;
 | |
| 
 | |
| 	swaps (&reply->sequenceNumber, n);
 | |
| 	swapl (&reply->length, n);
 | |
|     }
 | |
| 
 | |
|     WriteToClient (client, bytes, (char *)reply);
 | |
|     
 | |
|     xfree (reply);
 | |
| 
 | |
|     return (client->noClientException);
 | |
| }
 | |
| 
 | |
| static int
 | |
| LbxUnstallClient(pointer     data,
 | |
| 		 XID         id)
 | |
| {
 | |
|     LbxColormapPriv *cmapPriv = (LbxColormapPriv *)data;
 | |
|     LbxStalled **prev;
 | |
|     ClientPtr client;
 | |
| 
 | |
|     for (prev = &cmapPriv->stalled_clients; *prev && (*prev)->id != id; )
 | |
| 	prev = &(*prev)->next;
 | |
|     *prev = (*prev)->next;
 | |
|     client = clients[CLIENT_ID(id)];
 | |
|     if (!client->clientGone)
 | |
| 	AttendClient(client);
 | |
|     return 0;
 | |
| }
 | |
| 
 | |
| void
 | |
| LbxReleaseCmap(ColormapPtr pmap,
 | |
| 	       Bool smart)
 | |
| {
 | |
|     LbxColormapPriv *cmapPriv;
 | |
|     ColormapPtr *prev;
 | |
| 
 | |
|     if (!pmap->devPrivates)
 | |
| 	return;
 | |
|     cmapPriv = (LbxColormapPriv *)
 | |
| 	(pmap->devPrivates[lbxColormapPrivIndex].ptr);
 | |
|     if (!cmapPriv || (cmapPriv->grab_status == CMAP_NOT_GRABBED))
 | |
| 	return;
 | |
| 
 | |
|     for (prev = &cmapPriv->grabber->grabbedCmaps; *prev && *prev != pmap; )
 | |
| 	prev = &((LbxColormapPriv *)
 | |
| 		 (*prev)->devPrivates[lbxColormapPrivIndex].ptr)->next;
 | |
|     if (*prev == pmap)
 | |
| 	*prev = cmapPriv->next;
 | |
| 
 | |
|     while (cmapPriv->stalled_clients)
 | |
| 	FreeResource(cmapPriv->stalled_clients->id, 0);
 | |
| 
 | |
|     cmapPriv->grab_status = CMAP_NOT_GRABBED;
 | |
|     cmapPriv->last_grabber = smart ? cmapPriv->grabber->uid : 0;
 | |
|     cmapPriv->grabber = NULL;
 | |
|     cmapPriv->smart_grab = smart;
 | |
| }
 | |
| 
 | |
| /*
 | |
|  * Handle a colormap release request from a proxy.
 | |
|  */
 | |
| 
 | |
| int
 | |
| ProcLbxReleaseCmap(ClientPtr	client)
 | |
| {
 | |
|     REQUEST(xLbxReleaseCmapReq);
 | |
|     ColormapPtr pmap;
 | |
| 
 | |
| #ifdef COLOR_DEBUG
 | |
|     fprintf (stderr, "Got colormap release request, ");
 | |
|     fprintf (stderr, "seq = 0x%x, proxy = %d, client = %d, cmap = 0x%x\n",
 | |
| 	client->sequence, LbxProxyID(client), client->index, stuff->cmap);
 | |
| #endif
 | |
| 
 | |
|     pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap,
 | |
| 						 RT_COLORMAP,
 | |
| 						 SecurityWriteAccess);
 | |
| 
 | |
|     if (!pmap)
 | |
|     {
 | |
|         client->errorValue = stuff->cmap;
 | |
| 	return BadColor;
 | |
|     }
 | |
| 
 | |
|     if (LbxGrabbedByClient(client, pmap))
 | |
| 	LbxReleaseCmap(pmap, TRUE);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * Handle an LbxAllocColor request.  The proxy did the alloc and
 | |
|  * is telling the server what rgb and pixel value to use.
 | |
|  */
 | |
| 
 | |
| int
 | |
| ProcLbxAllocColor(ClientPtr	client)
 | |
| {
 | |
|     REQUEST(xLbxAllocColorReq);
 | |
|     ColormapPtr pmap;
 | |
|     CARD32 pixel = stuff->pixel;
 | |
| 
 | |
|     REQUEST_SIZE_MATCH (xLbxAllocColorReq);
 | |
|     pmap = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap,
 | |
| 						 RT_COLORMAP,
 | |
| 						 SecurityWriteAccess);
 | |
| 
 | |
| #ifdef COLOR_DEBUG
 | |
|     fprintf (stderr,
 | |
| 	"Got LBX alloc color: seq = 0x%x, proxy = %d, client = %d\n",
 | |
| 	client->sequence, LbxProxyID(client), client->index);
 | |
|     fprintf (stderr, "  cmap = 0x%x, pixel = %d, rgb = (%d,%d,%d)\n",
 | |
|         stuff->cmap, stuff->pixel, stuff->red, stuff->green, stuff->blue);
 | |
| #endif
 | |
| 
 | |
|     if (pmap)
 | |
|     {
 | |
| 	int status;
 | |
| 	if (!LbxGrabbedByClient(client, pmap))
 | |
| 	    return BadAccess;
 | |
| 
 | |
| 	status = AllocColor (pmap,
 | |
| 	    &stuff->red, &stuff->green, &stuff->blue,
 | |
| 	    &pixel, client->index);
 | |
| 
 | |
| 	if (status == Success && pixel != stuff->pixel)
 | |
| 	{
 | |
| 	    /*
 | |
| 	     * Internal error - Proxy allocated different pixel from server
 | |
| 	     */
 | |
| #ifdef COLOR_DEBUG
 | |
| 	    fprintf(stderr, "got pixel %d (%d, %d, %d), expected %d\n",
 | |
| 		    pixel, stuff->red, stuff->green, stuff->blue, stuff->pixel);
 | |
| #endif
 | |
| 	    FreeColors (pmap, client->index, 1, &pixel, 0L);
 | |
| 	    return BadAlloc;
 | |
| 	}
 | |
| 
 | |
| 	return status;
 | |
|     }
 | |
|     else
 | |
|     {
 | |
|         client->errorValue = stuff->cmap;
 | |
|         return (BadColor);
 | |
|     }
 | |
| }
 | |
| 
 | |
| 
 | |
| /*
 | |
|  * The proxy sends an LbxIncrementPixel request when it short circuits
 | |
|  * an AllocColor.  The server must bump up the reference count the
 | |
|  * specified amount.
 | |
|  */
 | |
| 
 | |
| int
 | |
| ProcLbxIncrementPixel(ClientPtr	client)
 | |
| {
 | |
|     REQUEST(xLbxIncrementPixelReq);
 | |
|     ColormapPtr pmap;
 | |
|     EntryPtr    pent;
 | |
|     Pixel	pixel;
 | |
|     unsigned	short red, green, blue;
 | |
|     VisualPtr	pVisual;
 | |
|     int		status;
 | |
| 
 | |
| #ifdef COLOR_DEBUG
 | |
|     fprintf (stderr,
 | |
| 	"Got LBX increment pixel: seq = 0x%x, proxy = %d, client = %d\n",
 | |
| 	client->sequence, LbxProxyID(client), client->index);
 | |
|     fprintf (stderr, "  cmap = 0x%x, pixel = %d\n",
 | |
|         stuff->cmap, stuff->pixel);
 | |
| #endif
 | |
| 
 | |
|     /*
 | |
|      * Looks up the color associated with the pixel, and then call
 | |
|      * AllocColor() - a bit round-about, but it should work.
 | |
|      */
 | |
| 
 | |
|     pmap = (ColormapPtr) SecurityLookupIDByType(client, stuff->cmap,
 | |
| 						RT_COLORMAP,
 | |
| 						SecurityWriteAccess);
 | |
|     if (!pmap) {
 | |
|         client->errorValue = stuff->cmap;
 | |
| 	return BadColor;
 | |
|     }
 | |
| 
 | |
|     pixel = stuff->pixel;
 | |
| 
 | |
|     switch (pmap->class) {
 | |
|     case StaticColor:
 | |
|     case StaticGray:
 | |
| 	red = pmap->red[pixel].co.local.red;
 | |
| 	green = pmap->red[pixel].co.local.green;
 | |
| 	blue = pmap->red[pixel].co.local.blue;
 | |
| 	break;
 | |
|     case GrayScale:
 | |
|     case PseudoColor:
 | |
| 	pent = pmap->red + pixel;
 | |
| 	red = pent->co.local.red;
 | |
| 	green = pent->co.local.green;
 | |
| 	blue = pent->co.local.blue;
 | |
| 	break;
 | |
|     default:
 | |
| 	pVisual = pmap->pVisual;
 | |
| 	red = pmap->red[(pixel & pVisual->redMask) >> pVisual->offsetRed].co.local.red;
 | |
| 	green = pmap->green[(pixel & pVisual->greenMask) >> pVisual->offsetGreen].co.local.green;
 | |
| 	blue = pmap->blue[(pixel & pVisual->blueMask) >> pVisual->offsetBlue].co.local.blue;
 | |
| 	break;
 | |
|     }
 | |
| 
 | |
|     status = AllocColor(pmap, &red, &green, &blue, &pixel, client->index);
 | |
| 
 | |
|     if (status == Success && pixel != stuff->pixel)
 | |
|     {
 | |
| 	/*
 | |
| 	 * Internal error - Proxy allocated different pixel from server
 | |
| 	 */
 | |
| #ifdef COLOR_DEBUG
 | |
| 	fprintf(stderr, "got pixel %d, expected %d\n", pixel, stuff->pixel);
 | |
| #endif
 | |
| 	FreeColors (pmap, client->index, 1, &pixel, 0L);
 | |
| 	return BadAlloc;
 | |
|     }
 | |
| 
 | |
|     return status;
 | |
| }
 |