aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix
diff options
context:
space:
mode:
Diffstat (limited to 'xorg-server/dix')
-rw-r--r--xorg-server/dix/Xserver-dtrace.h75
-rw-r--r--xorg-server/dix/colormap.c5522
-rw-r--r--xorg-server/dix/dispatch.c34
-rw-r--r--xorg-server/dix/dixfonts.c4206
-rw-r--r--xorg-server/dix/events.c5
-rw-r--r--xorg-server/dix/getevents.c2416
-rw-r--r--xorg-server/dix/main.c41
-rw-r--r--xorg-server/dix/makefile40
-rw-r--r--xorg-server/dix/ptrveloc.c9
-rw-r--r--xorg-server/dix/registry.c1
10 files changed, 6279 insertions, 6070 deletions
diff --git a/xorg-server/dix/Xserver-dtrace.h b/xorg-server/dix/Xserver-dtrace.h
new file mode 100644
index 000000000..b4f27a0bc
--- /dev/null
+++ b/xorg-server/dix/Xserver-dtrace.h
@@ -0,0 +1,75 @@
+/* Copyright 2006 Sun Microsystems, Inc. All rights reserved.
+ *
+ * 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, and/or sell copies of the Software, and to permit persons
+ * to whom the Software is furnished to do so, provided that the above
+ * copyright notice(s) and this permission notice appear in all copies of
+ * the Software and that both the above copyright notice(s) and this
+ * permission notice appear in supporting documentation.
+ *
+ * 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
+ * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
+ * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR 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.
+ *
+ * Except as contained in this notice, the name of a copyright holder
+ * shall not be used in advertising or otherwise to promote the sale, use
+ * or other dealings in this Software without prior written authorization
+ * of the copyright holder.
+ */
+
+/*
+ * Generated by dtrace(1M), and then modified for backwards compatibility
+ * with older versions of dtrace. Used if dtrace -h fails.
+ * (Since _ENABLED support was added after dtrace -h, this assumes if
+ * dtrace -h fails, _ENABLED will too.)
+ */
+
+#ifndef _XSERVER_DTRACE_H
+#define _XSERVER_DTRACE_H
+
+#include <unistd.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define XSERVER_CLIENT_AUTH(arg0, arg1, arg2, arg3) \
+ winDebug("XSERVER_CLIENT_AUTH: %d %s %d %d\n",arg0, arg1, arg2, arg3)
+#define XSERVER_CLIENT_CONNECT(arg0, arg1) \
+ winDebug("XSERVER_CLIENT_CONNECT: %d %d\n",arg0, arg1)
+#define XSERVER_CLIENT_DISCONNECT(arg0) \
+ winDebug("XSERVER_CLIENT_DISCONNECT: %d %d\n",arg0)
+#define XSERVER_REQUEST_DONE(arg0, arg1, arg2, arg3, arg4) \
+ winDebug("XSERVER_REQUEST_DONE: %s %d %d %d %d\n",arg0, arg1, arg2, arg3, arg4)
+#define XSERVER_REQUEST_START(arg0, arg1, arg2, arg3, arg4) \
+ winDebug("XSERVER_REQUEST_START: %s %d %d %d ->%p\n",arg0, arg1, arg2, arg3, arg4)
+#define XSERVER_RESOURCE_ALLOC(arg0, arg1, arg2, arg3) \
+ winDebug("XSERVER_RESOURCE_ALLOC: 0x%x 0x%x ->%p %s\n",arg0, arg1, arg2, arg3)
+#define XSERVER_RESOURCE_FREE(arg0, arg1, arg2, arg3) \
+ winDebug("XSERVER_RESOURCE_FREE: 0x%x 0x%x ->%p %s\n",arg0, arg1, arg2, arg3)
+#define XSERVER_SEND_EVENT(arg0, arg1, arg2) \
+ winDebug("XSERVER_SEND_EVENT: 0x%x 0x%x ->%p\n",arg0, arg1, arg2)
+
+#define XSERVER_CLIENT_AUTH_ENABLED() (1)
+#define XSERVER_CLIENT_CONNECT_ENABLED() (1)
+#define XSERVER_CLIENT_DISCONNECT_ENABLED() (1)
+#define XSERVER_REQUEST_DONE_ENABLED() (1)
+#define XSERVER_REQUEST_START_ENABLED() (1)
+#define XSERVER_RESOURCE_ALLOC_ENABLED() (1)
+#define XSERVER_RESOURCE_FREE_ENABLED() (1)
+#define XSERVER_SEND_EVENT_ENABLED() (1)
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _XSERVER_DTRACE_H */
diff --git a/xorg-server/dix/colormap.c b/xorg-server/dix/colormap.c
index bf9794125..cd2101e4a 100644
--- a/xorg-server/dix/colormap.c
+++ b/xorg-server/dix/colormap.c
@@ -1,2759 +1,2763 @@
-/***********************************************************
-
-Copyright 1987, 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.
-
-
-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.
-
-******************************************************************/
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include <stdio.h>
-#include <string.h>
-#include <strings.h>
-#include "misc.h"
-#include "dix.h"
-#include "colormapst.h"
-#include "os.h"
-#include "scrnintstr.h"
-#include "resource.h"
-#include "windowstr.h"
-#include "privates.h"
-#include "xace.h"
-
-extern XID clientErrorValue;
-
-static Pixel FindBestPixel(
- EntryPtr /*pentFirst*/,
- int /*size*/,
- xrgb * /*prgb*/,
- int /*channel*/
-);
-
-static int AllComp(
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-);
-
-static int RedComp(
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-);
-
-static int GreenComp(
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-);
-
-static int BlueComp(
- EntryPtr /*pent*/,
- xrgb * /*prgb*/
-);
-
-static void FreePixels(
- ColormapPtr /*pmap*/,
- int /*client*/
-);
-
-static void CopyFree(
- int /*channel*/,
- int /*client*/,
- ColormapPtr /*pmapSrc*/,
- ColormapPtr /*pmapDst*/
-);
-
-static void FreeCell(
- ColormapPtr /*pmap*/,
- Pixel /*i*/,
- int /*channel*/
-);
-
-static void UpdateColors(
- ColormapPtr /*pmap*/
-);
-
-static int AllocDirect(
- int /*client*/,
- ColormapPtr /*pmap*/,
- int /*c*/,
- int /*r*/,
- int /*g*/,
- int /*b*/,
- Bool /*contig*/,
- Pixel * /*pixels*/,
- Pixel * /*prmask*/,
- Pixel * /*pgmask*/,
- Pixel * /*pbmask*/
-);
-
-static int AllocPseudo(
- int /*client*/,
- ColormapPtr /*pmap*/,
- int /*c*/,
- int /*r*/,
- Bool /*contig*/,
- Pixel * /*pixels*/,
- Pixel * /*pmask*/,
- Pixel ** /*pppixFirst*/
-);
-
-static Bool AllocCP(
- ColormapPtr /*pmap*/,
- EntryPtr /*pentFirst*/,
- int /*count*/,
- int /*planes*/,
- Bool /*contig*/,
- Pixel * /*pixels*/,
- Pixel * /*pMask*/
-);
-
-static Bool AllocShared(
- ColormapPtr /*pmap*/,
- Pixel * /*ppix*/,
- int /*c*/,
- int /*r*/,
- int /*g*/,
- int /*b*/,
- Pixel /*rmask*/,
- Pixel /*gmask*/,
- Pixel /*bmask*/,
- Pixel * /*ppixFirst*/
-);
-
-static int FreeCo(
- ColormapPtr /*pmap*/,
- int /*client*/,
- int /*color*/,
- int /*npixIn*/,
- Pixel * /*ppixIn*/,
- Pixel /*mask*/
-);
-
-static int TellNoMap(
- WindowPtr /*pwin*/,
- Colormap * /*pmid*/
-);
-
-static void FindColorInRootCmap (
- ColormapPtr /* pmap */,
- EntryPtr /* pentFirst */,
- int /* size */,
- xrgb* /* prgb */,
- Pixel* /* pPixel */,
- int /* channel */,
- ColorCompareProcPtr /* comp */
-);
-
-#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
-#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
-#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1)
-#if COMPOSITE
-#define ALPHAMASK(vis) ((vis)->nplanes < 32 ? 0 : \
- (CARD32) ~((vis)->redMask|(vis)->greenMask|(vis)->blueMask))
-#else
-#define ALPHAMASK(vis) 0
-#endif
-
-#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask | ALPHAMASK(vis))
-
-/* 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
- *
- * \param mid resource to use for this colormap
- * \param alloc 1 iff all entries are allocated writable
- */
-int
-CreateColormap (Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
- ColormapPtr *ppcmap, int alloc, int client)
-{
- int class, size;
- unsigned long sizebytes;
- ColormapPtr pmap;
- EntryPtr pent;
- int i;
- Pixel *ppix, **pptr;
-
- 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 = xalloc(sizebytes);
- if (!pmap)
- return (BadAlloc);
-#if defined(_XSERVER64)
- pmap->pad0 = 0;
- pmap->pad1 = 0;
-#if (X_BYTE_ORDER == X_LITTLE_ENDIAN)
- pmap->pad2 = 0;
-#endif
-#endif
- 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 = 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 = 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 = 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;
- }
- }
- pmap->devPrivates = NULL;
- pmap->flags |= BeingCreated;
-
- if (!AddResource(mid, RT_COLORMAP, (pointer)pmap))
- return (BadAlloc);
-
- /*
- * Security creation/labeling check
- */
- i = XaceHook(XACE_RESOURCE_ACCESS, clients[client], mid, RT_COLORMAP,
- pmap, RT_NONE, NULL, DixCreateAccess);
- if (i != Success) {
- FreeResource(mid, RT_NONE);
- return i;
- }
-
- /* 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 */
- if (!(*pScreen->CreateColormap)(pmap))
- {
- FreeResource (mid, RT_NONE);
- return BadAlloc;
- }
- pmap->flags &= ~BeingCreated;
- *ppcmap = pmap;
- return (Success);
-}
-
-/**
- *
- * \param value must conform to DeleteType
- */
-int
-FreeColormap (pointer value, XID mid)
-{
- int i;
- 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]);
- }
- }
-
- dixFreePrivates(pmap->devPrivates);
- xfree(pmap);
- return(Success);
-}
-
-/* Tell window that pmid has disappeared */
-static int
-TellNoMap (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;
-#ifdef PANORAMIX
- if(noPanoramiXExtension || !pwin->drawable.pScreen->myNum)
-#endif
- 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 (WindowPtr pwin, pointer value)
-{
- Colormap *pmid = (Colormap *)value;
- xEvent xE;
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum)
- return WT_STOPWALKING;
-#endif
- 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 (WindowPtr pwin, pointer value)
-{
- Colormap *pmid = (Colormap *)value;
- xEvent xE;
-
-#ifdef PANORAMIX
- if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum)
- return WT_STOPWALKING;
-#endif
- 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 (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 (int channel, int client, ColormapPtr pmapSrc, ColormapPtr pmapDst)
-{
- int z, npix;
- 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;
- break;
- case GREENMAP:
- ppix = (pmapSrc->clientPixelsGreen)[client];
- npix = (pmapSrc->numPixelsGreen)[client];
- pentSrcFirst = pmapSrc->green;
- pentDstFirst = pmapDst->green;
- break;
- case BLUEMAP:
- ppix = (pmapSrc->clientPixelsBlue)[client];
- npix = (pmapSrc->numPixelsBlue)[client];
- pentSrcFirst = pmapSrc->blue;
- pentDstFirst = pmapDst->blue;
- 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 (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 (ColormapPtr pmap)
-{
- xColorItem *defs;
- xColorItem *pdef;
- EntryPtr pent;
- VisualPtr pVisual;
- int i, n, size;
-
- pVisual = pmap->pVisual;
- size = pVisual->ColormapEntries;
- defs = xalloc(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);
- xfree(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 (ColormapPtr pmap,
- unsigned short *pred, unsigned short *pgreen, unsigned short *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) |
- ALPHAMASK(pVisual);
-
- *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 (pmap->mid != pmap->pScreen->defColormap &&
- pmap->pVisual->vid == pmap->pScreen->rootVisual)
- {
- ColormapPtr prootmap;
- dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap,
- RT_COLORMAP, clients[client], DixReadAccess);
-
- if (pmap->class == prootmap->class)
- FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb,
- pPix, PSEUDOMAP, AllComp);
- }
- if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP,
- client, AllComp) != Success)
- return (BadAlloc);
- break;
-
- case DirectColor:
- if (pmap->mid != pmap->pScreen->defColormap &&
- pmap->pVisual->vid == pmap->pScreen->rootVisual)
- {
- ColormapPtr prootmap;
- dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap,
- RT_COLORMAP, clients[client], DixReadAccess);
-
- if (pmap->class == prootmap->class)
- {
- pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed;
- FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb,
- &pixR, REDMAP, RedComp);
- pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen;
- FindColorInRootCmap (prootmap, prootmap->green, entries, &rgb,
- &pixG, GREENMAP, GreenComp);
- pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue;
- FindColorInRootCmap (prootmap, prootmap->blue, entries, &rgb,
- &pixB, BLUEMAP, BlueComp);
- *pPix = pixR | pixG | pixB;
- }
- }
-
- 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 | ALPHAMASK(pVisual);
-
- 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 = 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 (ColormapPtr pmap, xColorItem *item)
-{
- Pixel pixR, pixG, pixB;
- Pixel temp;
- int entries;
- xrgb rgb;
- int class;
- 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:
- temp = 0;
- 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(ColormapPtr pmap, Pixel pixel)
-{
- 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
-BigNumAdd (BigNumPtr x, BigNumPtr y, BigNumPtr r)
-{
- 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(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 = (long) pent->co.local.green - prgb->green;
- db = (long) pent->co.local.blue - prgb->blue;
- case REDMAP:
- dr = (long) pent->co.local.red - prgb->red;
- break;
- case GREENMAP:
- dg = (long) pent->co.local.green - prgb->green;
- break;
- case BLUEMAP:
- db = (long) 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);
-}
-
-static void
-FindColorInRootCmap (ColormapPtr pmap, EntryPtr pentFirst, int size,
- xrgb *prgb, Pixel *pPixel, int channel,
- ColorCompareProcPtr comp)
-{
- EntryPtr pent;
- Pixel pixel;
- int count;
-
- if ((pixel = *pPixel) >= size)
- pixel = 0;
- for (pent = pentFirst + pixel, count = size; --count >= 0; pent++, pixel++)
- {
- if (pent->refcnt > 0 && (*comp) (pent, prgb))
- {
- switch (channel)
- {
- case REDMAP:
- pixel <<= pmap->pVisual->offsetRed;
- break;
- case GREENMAP:
- pixel <<= pmap->pVisual->offsetGreen;
- break;
- case BLUEMAP:
- pixel <<= pmap->pVisual->offsetBlue;
- break;
- default: /* PSEUDOMAP */
- break;
- }
- *pPixel = pixel;
- }
- }
-}
-
-/* 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 (ColormapPtr pmap, EntryPtr pentFirst, int size, xrgb *prgb,
- Pixel *pPixel, int channel, int client,
- ColorCompareProcPtr comp)
-{
- EntryPtr pent;
- Bool foundFree;
- Pixel pixel, Free = 0;
- int npix, count, *nump = NULL;
- Pixel **pixp = NULL, *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 (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 (EntryPtr pent, xrgb *prgb)
-{
- if (pent->co.local.red == prgb->red)
- return (1);
- return (0);
-}
-
-static int
-GreenComp (EntryPtr pent, xrgb *prgb)
-{
- if (pent->co.local.green == prgb->green)
- return (1);
- return (0);
-}
-
-static int
-BlueComp (EntryPtr pent, xrgb *prgb)
-{
- if (pent->co.local.blue == prgb->blue)
- return (1);
- return (0);
-}
-
-
-/* Read the color value of a cell */
-
-int
-QueryColors (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(ColormapPtr pmap, int client)
-{
- Pixel *ppix, *ppixStart;
- int n;
- int class;
-
- class = pmap->class;
- ppixStart = pmap->clientPixelsRed[client];
- if (class & DynamicClass)
- {
- n = pmap->numPixelsRed[client];
- for (ppix = ppixStart; --n >= 0; )
- {
- FreeCell(pmap, *ppix, REDMAP);
- ppix++;
- }
- }
-
- 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;
- }
-}
-
-/**
- * Frees all of a client's colors and cells.
- *
- * \param value must conform to DeleteType
- * \unused fakeid
- */
-int
-FreeClientPixels (pointer value, XID fakeid)
-{
- pointer pmap;
- colorResource *pcr = value;
- int rc;
-
- rc = dixLookupResourceByType(&pmap, pcr->mid, RT_COLORMAP, serverClient,
- DixRemoveAccess);
- if (rc == Success)
- FreePixels((ColormapPtr)pmap, pcr->client);
- xfree(pcr);
- return Success;
-}
-
-int
-AllocColorCells (int client, ColormapPtr pmap, int colors, int 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 = 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 (int client, ColormapPtr pmap, int colors,
- int r, int g, int b, Bool contig, Pixel *pixels,
- Pixel *prmask, Pixel *pgmask, Pixel *pbmask)
-{
- int ok;
- Pixel mask, *ppixFirst;
- Pixel shift;
- 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 = 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 (int client, ColormapPtr pmap, int c, int r, int g, int b, Bool contig,
- Pixel *pixels, Pixel *prmask, Pixel *pgmask, Pixel *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 = xalloc(npixR * sizeof(Pixel));
- ppixGreen = xalloc(npixG * sizeof(Pixel));
- ppixBlue = xalloc(npixB * sizeof(Pixel));
- if (!ppixRed || !ppixGreen || !ppixBlue)
- {
- if (ppixBlue) xfree(ppixBlue);
- if (ppixGreen) xfree(ppixGreen);
- if (ppixRed) xfree(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;
- xfree(ppixBlue);
- xfree(ppixGreen);
- xfree(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;
-
-
- for (pDst = pixels; pDst < pixels + c; pDst++)
- *pDst |= ALPHAMASK(pmap->pVisual);
-
- xfree(ppixBlue);
- xfree(ppixGreen);
- xfree(ppixRed);
-
- return (Success);
-}
-
-static int
-AllocPseudo (int client, ColormapPtr pmap, int c, int 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 = xalloc(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;
- }
- xfree(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 (ColormapPtr pmap, EntryPtr pentFirst, int count, int planes,
- Bool contig, Pixel *pixels, Pixel *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);
-}
-
-/**
- *
- * \param ppixFirst First of the client's new pixels
- */
-static Bool
-AllocShared (ColormapPtr pmap, Pixel *ppix, int c, int r, int g, int b,
- Pixel rmask, Pixel gmask, Pixel bmask, Pixel *ppixFirst)
-{
- 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 = xalloc(npixShared * sizeof(SHAREDCOLOR *));
- if (!psharedList)
- return FALSE;
- ppshared = psharedList;
- for (z = npixShared; --z >= 0; )
- {
- if (!(ppshared[z] = 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;
- }
- }
- }
- }
- xfree(psharedList);
- return TRUE;
-}
-
-
-/** FreeColors
- * Free colors and/or cells (probably slow for large numbers)
- */
-int
-FreeColors (ColormapPtr pmap, int client, int 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
- *
- * \param pmap which colormap head
- * \param color which sub-map, eg, RED, BLUE, PSEUDO
- * \param npixIn number of pixels passed in
- * \param ppixIn number of base pixels
- * \param mask mask client gave us
- */
-static int
-FreeCo (ColormapPtr pmap, int client, int color, int npixIn, Pixel *ppixIn, Pixel mask)
-{
- Pixel *ppixClient, pixTest;
- int npixClient, npixNew, npix;
- Pixel bits, base, cmask, rgbbad;
- Pixel *pptr, *cptr;
- int n, zapped;
- int errVal = Success;
- int offset, numents;
-
- 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;
- }
-
-
- /* 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);
- }
- *cptr = ~((Pixel)0);
- zapped++;
- }
- else
- errVal = BadAccess;
- }
- /* generate next bits value */
- GetNextBitsOrBreak(bits, mask, base);
- }
-
- /* 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 (ColormapPtr pmap, int count, xColorItem *defs)
-{
- Pixel pix;
- xColorItem *pdef;
- EntryPtr pent, pentT, pentLast;
- 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(Colormap map, WindowPtr pWin)
-{
- Colormap *pmaps;
- int imap, nummaps, found;
-
- pmaps = xalloc(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;
- }
- }
- xfree(pmaps);
- return (found);
-}
-
-struct colormap_lookup_data {
- ScreenPtr pScreen;
- VisualPtr visuals;
-};
-
-static void _colormap_find_resource(pointer value, XID id,
- pointer cdata)
-{
- struct colormap_lookup_data *cmap_data = cdata;
- VisualPtr visuals = cmap_data->visuals;
- ScreenPtr pScreen = cmap_data->pScreen;
- ColormapPtr cmap = value;
- int j;
-
- if (pScreen != cmap->pScreen)
- return;
-
- j = cmap->pVisual - pScreen->visuals;
- cmap->pVisual = &visuals[j];
-}
-
-/* something has realloced the visuals, instead of breaking
- ABI fix it up here - glx and compsite did this wrong */
-Bool
-ResizeVisualArray(ScreenPtr pScreen, int new_visual_count,
- DepthPtr depth)
-{
- struct colormap_lookup_data cdata;
- int numVisuals;
- VisualPtr visuals;
- XID *vids, vid;
- int first_new_vid, first_new_visual, i;
-
- first_new_vid = depth->numVids;
- first_new_visual = pScreen->numVisuals;
-
- vids = xrealloc(depth->vids, (depth->numVids + new_visual_count) * sizeof(XID));
- if (!vids)
- return FALSE;
-
- /* its realloced now no going back if we fail the next one */
- depth->vids = vids;
-
- numVisuals = pScreen->numVisuals + new_visual_count;
- visuals = xrealloc(pScreen->visuals, numVisuals * sizeof(VisualRec));
- if (!visuals) {
- return FALSE;
- }
-
- cdata.visuals = visuals;
- cdata.pScreen = pScreen;
- FindClientResourcesByType(serverClient, RT_COLORMAP, _colormap_find_resource, &cdata);
-
- pScreen->visuals = visuals;
-
- for (i = 0; i < new_visual_count; i++) {
- vid = FakeClientID(0);
- pScreen->visuals[first_new_visual + i].vid = vid;
- vids[first_new_vid + i] = vid;
- }
-
- depth->numVids += new_visual_count;
- pScreen->numVisuals += new_visual_count;
-
- return TRUE;
-}
+/***********************************************************
+
+Copyright 1987, 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.
+
+
+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.
+
+******************************************************************/
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <stdio.h>
+#include <string.h>
+#include <strings.h>
+#include "misc.h"
+#include "dix.h"
+#include "colormapst.h"
+#include "os.h"
+#include "scrnintstr.h"
+#include "resource.h"
+#include "windowstr.h"
+#include "privates.h"
+#include "xace.h"
+
+#ifdef _MSC_VER
+#define UpdateColors thisUpdateColors
+#endif
+
+extern XID clientErrorValue;
+
+static Pixel FindBestPixel(
+ EntryPtr /*pentFirst*/,
+ int /*size*/,
+ xrgb * /*prgb*/,
+ int /*channel*/
+);
+
+static int AllComp(
+ EntryPtr /*pent*/,
+ xrgb * /*prgb*/
+);
+
+static int RedComp(
+ EntryPtr /*pent*/,
+ xrgb * /*prgb*/
+);
+
+static int GreenComp(
+ EntryPtr /*pent*/,
+ xrgb * /*prgb*/
+);
+
+static int BlueComp(
+ EntryPtr /*pent*/,
+ xrgb * /*prgb*/
+);
+
+static void FreePixels(
+ ColormapPtr /*pmap*/,
+ int /*client*/
+);
+
+static void CopyFree(
+ int /*channel*/,
+ int /*client*/,
+ ColormapPtr /*pmapSrc*/,
+ ColormapPtr /*pmapDst*/
+);
+
+static void FreeCell(
+ ColormapPtr /*pmap*/,
+ Pixel /*i*/,
+ int /*channel*/
+);
+
+static void UpdateColors(
+ ColormapPtr /*pmap*/
+);
+
+static int AllocDirect(
+ int /*client*/,
+ ColormapPtr /*pmap*/,
+ int /*c*/,
+ int /*r*/,
+ int /*g*/,
+ int /*b*/,
+ Bool /*contig*/,
+ Pixel * /*pixels*/,
+ Pixel * /*prmask*/,
+ Pixel * /*pgmask*/,
+ Pixel * /*pbmask*/
+);
+
+static int AllocPseudo(
+ int /*client*/,
+ ColormapPtr /*pmap*/,
+ int /*c*/,
+ int /*r*/,
+ Bool /*contig*/,
+ Pixel * /*pixels*/,
+ Pixel * /*pmask*/,
+ Pixel ** /*pppixFirst*/
+);
+
+static Bool AllocCP(
+ ColormapPtr /*pmap*/,
+ EntryPtr /*pentFirst*/,
+ int /*count*/,
+ int /*planes*/,
+ Bool /*contig*/,
+ Pixel * /*pixels*/,
+ Pixel * /*pMask*/
+);
+
+static Bool AllocShared(
+ ColormapPtr /*pmap*/,
+ Pixel * /*ppix*/,
+ int /*c*/,
+ int /*r*/,
+ int /*g*/,
+ int /*b*/,
+ Pixel /*rmask*/,
+ Pixel /*gmask*/,
+ Pixel /*bmask*/,
+ Pixel * /*ppixFirst*/
+);
+
+static int FreeCo(
+ ColormapPtr /*pmap*/,
+ int /*client*/,
+ int /*color*/,
+ int /*npixIn*/,
+ Pixel * /*ppixIn*/,
+ Pixel /*mask*/
+);
+
+static int TellNoMap(
+ WindowPtr /*pwin*/,
+ Colormap * /*pmid*/
+);
+
+static void FindColorInRootCmap (
+ ColormapPtr /* pmap */,
+ EntryPtr /* pentFirst */,
+ int /* size */,
+ xrgb* /* prgb */,
+ Pixel* /* pPixel */,
+ int /* channel */,
+ ColorCompareProcPtr /* comp */
+);
+
+#define NUMRED(vis) ((vis->redMask >> vis->offsetRed) + 1)
+#define NUMGREEN(vis) ((vis->greenMask >> vis->offsetGreen) + 1)
+#define NUMBLUE(vis) ((vis->blueMask >> vis->offsetBlue) + 1)
+#if COMPOSITE
+#define ALPHAMASK(vis) ((vis)->nplanes < 32 ? 0 : \
+ (CARD32) ~((vis)->redMask|(vis)->greenMask|(vis)->blueMask))
+#else
+#define ALPHAMASK(vis) 0
+#endif
+
+#define RGBMASK(vis) (vis->redMask | vis->greenMask | vis->blueMask | ALPHAMASK(vis))
+
+/* 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
+ *
+ * \param mid resource to use for this colormap
+ * \param alloc 1 iff all entries are allocated writable
+ */
+int
+CreateColormap (Colormap mid, ScreenPtr pScreen, VisualPtr pVisual,
+ ColormapPtr *ppcmap, int alloc, int client)
+{
+ int class, size;
+ unsigned long sizebytes;
+ ColormapPtr pmap;
+ EntryPtr pent;
+ int i;
+ Pixel *ppix, **pptr;
+
+ 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 = xalloc(sizebytes);
+ if (!pmap)
+ return (BadAlloc);
+#if defined(_XSERVER64)
+ pmap->pad0 = 0;
+ pmap->pad1 = 0;
+#if (X_BYTE_ORDER == X_LITTLE_ENDIAN)
+ pmap->pad2 = 0;
+#endif
+#endif
+ 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 = 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 = 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 = 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;
+ }
+ }
+ pmap->devPrivates = NULL;
+ pmap->flags |= BeingCreated;
+
+ if (!AddResource(mid, RT_COLORMAP, (pointer)pmap))
+ return (BadAlloc);
+
+ /*
+ * Security creation/labeling check
+ */
+ i = XaceHook(XACE_RESOURCE_ACCESS, clients[client], mid, RT_COLORMAP,
+ pmap, RT_NONE, NULL, DixCreateAccess);
+ if (i != Success) {
+ FreeResource(mid, RT_NONE);
+ return i;
+ }
+
+ /* 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 */
+ if (!(*pScreen->CreateColormap)(pmap))
+ {
+ FreeResource (mid, RT_NONE);
+ return BadAlloc;
+ }
+ pmap->flags &= ~BeingCreated;
+ *ppcmap = pmap;
+ return (Success);
+}
+
+/**
+ *
+ * \param value must conform to DeleteType
+ */
+int
+FreeColormap (pointer value, XID mid)
+{
+ int i;
+ 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]);
+ }
+ }
+
+ dixFreePrivates(pmap->devPrivates);
+ xfree(pmap);
+ return(Success);
+}
+
+/* Tell window that pmid has disappeared */
+static int
+TellNoMap (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;
+#ifdef PANORAMIX
+ if(noPanoramiXExtension || !pwin->drawable.pScreen->myNum)
+#endif
+ 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 (WindowPtr pwin, pointer value)
+{
+ Colormap *pmid = (Colormap *)value;
+ xEvent xE;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum)
+ return WT_STOPWALKING;
+#endif
+ 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 (WindowPtr pwin, pointer value)
+{
+ Colormap *pmid = (Colormap *)value;
+ xEvent xE;
+
+#ifdef PANORAMIX
+ if(!noPanoramiXExtension && pwin->drawable.pScreen->myNum)
+ return WT_STOPWALKING;
+#endif
+ 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 (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 (int channel, int client, ColormapPtr pmapSrc, ColormapPtr pmapDst)
+{
+ int z, npix;
+ 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;
+ break;
+ case GREENMAP:
+ ppix = (pmapSrc->clientPixelsGreen)[client];
+ npix = (pmapSrc->numPixelsGreen)[client];
+ pentSrcFirst = pmapSrc->green;
+ pentDstFirst = pmapDst->green;
+ break;
+ case BLUEMAP:
+ ppix = (pmapSrc->clientPixelsBlue)[client];
+ npix = (pmapSrc->numPixelsBlue)[client];
+ pentSrcFirst = pmapSrc->blue;
+ pentDstFirst = pmapDst->blue;
+ 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 (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 (ColormapPtr pmap)
+{
+ xColorItem *defs;
+ xColorItem *pdef;
+ EntryPtr pent;
+ VisualPtr pVisual;
+ int i, n, size;
+
+ pVisual = pmap->pVisual;
+ size = pVisual->ColormapEntries;
+ defs = xalloc(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);
+ xfree(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 (ColormapPtr pmap,
+ unsigned short *pred, unsigned short *pgreen, unsigned short *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) |
+ ALPHAMASK(pVisual);
+
+ *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 (pmap->mid != pmap->pScreen->defColormap &&
+ pmap->pVisual->vid == pmap->pScreen->rootVisual)
+ {
+ ColormapPtr prootmap;
+ dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap,
+ RT_COLORMAP, clients[client], DixReadAccess);
+
+ if (pmap->class == prootmap->class)
+ FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb,
+ pPix, PSEUDOMAP, AllComp);
+ }
+ if (FindColor(pmap, pmap->red, entries, &rgb, pPix, PSEUDOMAP,
+ client, AllComp) != Success)
+ return (BadAlloc);
+ break;
+
+ case DirectColor:
+ if (pmap->mid != pmap->pScreen->defColormap &&
+ pmap->pVisual->vid == pmap->pScreen->rootVisual)
+ {
+ ColormapPtr prootmap;
+ dixLookupResourceByType((pointer *)&prootmap, pmap->pScreen->defColormap,
+ RT_COLORMAP, clients[client], DixReadAccess);
+
+ if (pmap->class == prootmap->class)
+ {
+ pixR = (*pPix & pVisual->redMask) >> pVisual->offsetRed;
+ FindColorInRootCmap (prootmap, prootmap->red, entries, &rgb,
+ &pixR, REDMAP, RedComp);
+ pixG = (*pPix & pVisual->greenMask) >> pVisual->offsetGreen;
+ FindColorInRootCmap (prootmap, prootmap->green, entries, &rgb,
+ &pixG, GREENMAP, GreenComp);
+ pixB = (*pPix & pVisual->blueMask) >> pVisual->offsetBlue;
+ FindColorInRootCmap (prootmap, prootmap->blue, entries, &rgb,
+ &pixB, BLUEMAP, BlueComp);
+ *pPix = pixR | pixG | pixB;
+ }
+ }
+
+ 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 | ALPHAMASK(pVisual);
+
+ 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 = 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 (ColormapPtr pmap, xColorItem *item)
+{
+ Pixel pixR, pixG, pixB;
+ Pixel temp;
+ int entries;
+ xrgb rgb;
+ int class;
+ 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:
+ temp = 0;
+ 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(ColormapPtr pmap, Pixel pixel)
+{
+ 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
+BigNumAdd (BigNumPtr x, BigNumPtr y, BigNumPtr r)
+{
+ 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(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 = (long) pent->co.local.green - prgb->green;
+ db = (long) pent->co.local.blue - prgb->blue;
+ case REDMAP:
+ dr = (long) pent->co.local.red - prgb->red;
+ break;
+ case GREENMAP:
+ dg = (long) pent->co.local.green - prgb->green;
+ break;
+ case BLUEMAP:
+ db = (long) 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);
+}
+
+static void
+FindColorInRootCmap (ColormapPtr pmap, EntryPtr pentFirst, int size,
+ xrgb *prgb, Pixel *pPixel, int channel,
+ ColorCompareProcPtr comp)
+{
+ EntryPtr pent;
+ Pixel pixel;
+ int count;
+
+ if ((pixel = *pPixel) >= size)
+ pixel = 0;
+ for (pent = pentFirst + pixel, count = size; --count >= 0; pent++, pixel++)
+ {
+ if (pent->refcnt > 0 && (*comp) (pent, prgb))
+ {
+ switch (channel)
+ {
+ case REDMAP:
+ pixel <<= pmap->pVisual->offsetRed;
+ break;
+ case GREENMAP:
+ pixel <<= pmap->pVisual->offsetGreen;
+ break;
+ case BLUEMAP:
+ pixel <<= pmap->pVisual->offsetBlue;
+ break;
+ default: /* PSEUDOMAP */
+ break;
+ }
+ *pPixel = pixel;
+ }
+ }
+}
+
+/* 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 (ColormapPtr pmap, EntryPtr pentFirst, int size, xrgb *prgb,
+ Pixel *pPixel, int channel, int client,
+ ColorCompareProcPtr comp)
+{
+ EntryPtr pent;
+ Bool foundFree;
+ Pixel pixel, Free = 0;
+ int npix, count, *nump = NULL;
+ Pixel **pixp = NULL, *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 (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 (EntryPtr pent, xrgb *prgb)
+{
+ if (pent->co.local.red == prgb->red)
+ return (1);
+ return (0);
+}
+
+static int
+GreenComp (EntryPtr pent, xrgb *prgb)
+{
+ if (pent->co.local.green == prgb->green)
+ return (1);
+ return (0);
+}
+
+static int
+BlueComp (EntryPtr pent, xrgb *prgb)
+{
+ if (pent->co.local.blue == prgb->blue)
+ return (1);
+ return (0);
+}
+
+
+/* Read the color value of a cell */
+
+int
+QueryColors (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(ColormapPtr pmap, int client)
+{
+ Pixel *ppix, *ppixStart;
+ int n;
+ int class;
+
+ class = pmap->class;
+ ppixStart = pmap->clientPixelsRed[client];
+ if (class & DynamicClass)
+ {
+ n = pmap->numPixelsRed[client];
+ for (ppix = ppixStart; --n >= 0; )
+ {
+ FreeCell(pmap, *ppix, REDMAP);
+ ppix++;
+ }
+ }
+
+ 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;
+ }
+}
+
+/**
+ * Frees all of a client's colors and cells.
+ *
+ * \param value must conform to DeleteType
+ * \unused fakeid
+ */
+int
+FreeClientPixels (pointer value, XID fakeid)
+{
+ pointer pmap;
+ colorResource *pcr = value;
+ int rc;
+
+ rc = dixLookupResourceByType(&pmap, pcr->mid, RT_COLORMAP, serverClient,
+ DixRemoveAccess);
+ if (rc == Success)
+ FreePixels((ColormapPtr)pmap, pcr->client);
+ xfree(pcr);
+ return Success;
+}
+
+int
+AllocColorCells (int client, ColormapPtr pmap, int colors, int 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 = 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 (int client, ColormapPtr pmap, int colors,
+ int r, int g, int b, Bool contig, Pixel *pixels,
+ Pixel *prmask, Pixel *pgmask, Pixel *pbmask)
+{
+ int ok;
+ Pixel mask, *ppixFirst;
+ Pixel shift;
+ 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 = 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 (int client, ColormapPtr pmap, int c, int r, int g, int b, Bool contig,
+ Pixel *pixels, Pixel *prmask, Pixel *pgmask, Pixel *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 = xalloc(npixR * sizeof(Pixel));
+ ppixGreen = xalloc(npixG * sizeof(Pixel));
+ ppixBlue = xalloc(npixB * sizeof(Pixel));
+ if (!ppixRed || !ppixGreen || !ppixBlue)
+ {
+ if (ppixBlue) xfree(ppixBlue);
+ if (ppixGreen) xfree(ppixGreen);
+ if (ppixRed) xfree(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;
+ xfree(ppixBlue);
+ xfree(ppixGreen);
+ xfree(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;
+
+
+ for (pDst = pixels; pDst < pixels + c; pDst++)
+ *pDst |= ALPHAMASK(pmap->pVisual);
+
+ xfree(ppixBlue);
+ xfree(ppixGreen);
+ xfree(ppixRed);
+
+ return (Success);
+}
+
+static int
+AllocPseudo (int client, ColormapPtr pmap, int c, int 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 = xalloc(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;
+ }
+ xfree(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 (ColormapPtr pmap, EntryPtr pentFirst, int count, int planes,
+ Bool contig, Pixel *pixels, Pixel *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);
+}
+
+/**
+ *
+ * \param ppixFirst First of the client's new pixels
+ */
+static Bool
+AllocShared (ColormapPtr pmap, Pixel *ppix, int c, int r, int g, int b,
+ Pixel rmask, Pixel gmask, Pixel bmask, Pixel *ppixFirst)
+{
+ 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 = xalloc(npixShared * sizeof(SHAREDCOLOR *));
+ if (!psharedList)
+ return FALSE;
+ ppshared = psharedList;
+ for (z = npixShared; --z >= 0; )
+ {
+ if (!(ppshared[z] = 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;
+ }
+ }
+ }
+ }
+ xfree(psharedList);
+ return TRUE;
+}
+
+
+/** FreeColors
+ * Free colors and/or cells (probably slow for large numbers)
+ */
+int
+FreeColors (ColormapPtr pmap, int client, int 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
+ *
+ * \param pmap which colormap head
+ * \param color which sub-map, eg, RED, BLUE, PSEUDO
+ * \param npixIn number of pixels passed in
+ * \param ppixIn number of base pixels
+ * \param mask mask client gave us
+ */
+static int
+FreeCo (ColormapPtr pmap, int client, int color, int npixIn, Pixel *ppixIn, Pixel mask)
+{
+ Pixel *ppixClient, pixTest;
+ int npixClient, npixNew, npix;
+ Pixel bits, base, cmask, rgbbad;
+ Pixel *pptr, *cptr;
+ int n, zapped;
+ int errVal = Success;
+ int offset, numents;
+
+ 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;
+ }
+
+
+ /* 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);
+ }
+ *cptr = ~((Pixel)0);
+ zapped++;
+ }
+ else
+ errVal = BadAccess;
+ }
+ /* generate next bits value */
+ GetNextBitsOrBreak(bits, mask, base);
+ }
+
+ /* 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 (ColormapPtr pmap, int count, xColorItem *defs)
+{
+ Pixel pix;
+ xColorItem *pdef;
+ EntryPtr pent, pentT, pentLast;
+ 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(Colormap map, WindowPtr pWin)
+{
+ Colormap *pmaps;
+ int imap, nummaps, found;
+
+ pmaps = xalloc(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;
+ }
+ }
+ xfree(pmaps);
+ return (found);
+}
+
+struct colormap_lookup_data {
+ ScreenPtr pScreen;
+ VisualPtr visuals;
+};
+
+static void _colormap_find_resource(pointer value, XID id,
+ pointer cdata)
+{
+ struct colormap_lookup_data *cmap_data = cdata;
+ VisualPtr visuals = cmap_data->visuals;
+ ScreenPtr pScreen = cmap_data->pScreen;
+ ColormapPtr cmap = value;
+ int j;
+
+ if (pScreen != cmap->pScreen)
+ return;
+
+ j = cmap->pVisual - pScreen->visuals;
+ cmap->pVisual = &visuals[j];
+}
+
+/* something has realloced the visuals, instead of breaking
+ ABI fix it up here - glx and compsite did this wrong */
+Bool
+ResizeVisualArray(ScreenPtr pScreen, int new_visual_count,
+ DepthPtr depth)
+{
+ struct colormap_lookup_data cdata;
+ int numVisuals;
+ VisualPtr visuals;
+ XID *vids, vid;
+ int first_new_vid, first_new_visual, i;
+
+ first_new_vid = depth->numVids;
+ first_new_visual = pScreen->numVisuals;
+
+ vids = xrealloc(depth->vids, (depth->numVids + new_visual_count) * sizeof(XID));
+ if (!vids)
+ return FALSE;
+
+ /* its realloced now no going back if we fail the next one */
+ depth->vids = vids;
+
+ numVisuals = pScreen->numVisuals + new_visual_count;
+ visuals = xrealloc(pScreen->visuals, numVisuals * sizeof(VisualRec));
+ if (!visuals) {
+ return FALSE;
+ }
+
+ cdata.visuals = visuals;
+ cdata.pScreen = pScreen;
+ FindClientResourcesByType(serverClient, RT_COLORMAP, _colormap_find_resource, &cdata);
+
+ pScreen->visuals = visuals;
+
+ for (i = 0; i < new_visual_count; i++) {
+ vid = FakeClientID(0);
+ pScreen->visuals[first_new_visual + i].vid = vid;
+ vids[first_new_vid + i] = vid;
+ }
+
+ depth->numVids += new_visual_count;
+ pScreen->numVisuals += new_visual_count;
+
+ return TRUE;
+}
diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c
index 414bd0404..3d5baeb4d 100644
--- a/xorg-server/dix/dispatch.c
+++ b/xorg-server/dix/dispatch.c
@@ -110,6 +110,10 @@ Equipment Corporation.
#include <version-config.h>
#endif
+#ifdef CreateWindow
+#undef CreateWindow
+#endif
+
#ifdef PANORAMIX_DEBUG
#include <stdio.h>
int ProcInitialConnection();
@@ -409,6 +413,9 @@ Dispatch(void)
start_tick = SmartScheduleTime;
while (!isItTimeToYield)
{
+#ifdef XSERVER_DTRACE
+ CARD8 StartMajorOp;
+#endif
if (*icheck[0] != *icheck[1])
ProcessInputEvents();
@@ -433,7 +440,8 @@ Dispatch(void)
client->sequence++;
#ifdef XSERVER_DTRACE
- XSERVER_REQUEST_START(LookupMajorName(MAJOROP), MAJOROP,
+ StartMajorOp=MAJOROP;
+ XSERVER_REQUEST_START(LookupMajorName(StartMajorOp), StartMajorOp,
((xReq *)client->requestBuffer)->length,
client->index, client->requestBuffer);
#endif
@@ -446,8 +454,28 @@ Dispatch(void)
XaceHookAuditEnd(client, result);
}
#ifdef XSERVER_DTRACE
- XSERVER_REQUEST_DONE(LookupMajorName(MAJOROP), MAJOROP,
- client->sequence, client->index, result);
+ if (result!=Success)
+ {
+ char Message[255];
+ sprintf(Message,"ERROR: %s (0x%x)",LookupMajorName(StartMajorOp),client->errorValue);
+ XSERVER_REQUEST_DONE(Message, MAJOROP,
+ client->sequence, client->index, result);
+ }
+ else
+ {
+ if (StartMajorOp!=MAJOROP)
+ {
+ char Message[255];
+ sprintf(Message,"Changed request: %s -> %s",LookupMajorName(StartMajorOp),LookupMajorName(MAJOROP));
+ XSERVER_REQUEST_DONE(Message, MAJOROP,
+ client->sequence, client->index, result);
+ }
+ else
+ {
+ XSERVER_REQUEST_DONE(LookupMajorName(MAJOROP), MAJOROP,
+ client->sequence, client->index, result);
+ }
+ }
#endif
if (result != Success)
diff --git a/xorg-server/dix/dixfonts.c b/xorg-server/dix/dixfonts.c
index 329318d5d..77c166ee5 100644
--- a/xorg-server/dix/dixfonts.c
+++ b/xorg-server/dix/dixfonts.c
@@ -1,2102 +1,2104 @@
-/************************************************************************
-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.
-
-************************************************************************/
-/* The panoramix components contained the following notice */
-/*
-Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
-
-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.
-
-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
-DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
-BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation
-shall not be used in advertising or otherwise to promote the sale, use or other
-dealings in this Software without prior written authorization from Digital
-Equipment Corporation.
-
-******************************************************************/
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xmd.h>
-#include <X11/Xproto.h>
-#include "scrnintstr.h"
-#include "resource.h"
-#include "dixstruct.h"
-#include "cursorstr.h"
-#include "misc.h"
-#include "opaque.h"
-#include "dixfontstr.h"
-#include "closestr.h"
-#include "dixfont.h"
-#include "xace.h"
-
-#ifdef DEBUG
-#include <stdio.h>
-#endif
-
-#ifdef XF86BIGFONT
-#define _XF86BIGFONT_SERVER_
-#include <X11/extensions/xf86bigfont.h>
-#endif
-
-#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics
-
-extern pointer fosNaturalParams;
-extern FontPtr defaultFont;
-
-static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
-static int num_fpes = 0;
-static FPEFunctions *fpe_functions = (FPEFunctions *) 0;
-static int num_fpe_types = 0;
-
-static unsigned char *font_path_string;
-
-static int num_slept_fpes = 0;
-static int size_slept_fpes = 0;
-static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
-static FontPatternCachePtr patternCache;
-
-static int
-FontToXError(int err)
-{
- switch (err) {
- case Successful:
- return Success;
- case AllocError:
- return BadAlloc;
- case BadFontName:
- return BadName;
- case BadFontPath:
- case BadFontFormat: /* is there something better? */
- case BadCharRange:
- return BadValue;
- default:
- return err;
- }
-}
-
-static int
-LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size,
- unsigned char *data)
-{
- if (fpe_functions[pfont->fpe->type].load_glyphs)
- return (*fpe_functions[pfont->fpe->type].load_glyphs)
- (client, pfont, 0, nchars, item_size, data);
- else
- return Successful;
-}
-
-/*
- * adding RT_FONT prevents conflict with default cursor font
- */
-Bool
-SetDefaultFont(char *defaultfontname)
-{
- int err;
- FontPtr pf;
- XID fid;
-
- fid = FakeClientID(0);
- err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync,
- (unsigned) strlen(defaultfontname), defaultfontname);
- if (err != Success)
- return FALSE;
- err = dixLookupResourceByType((pointer *)&pf, fid, RT_FONT, serverClient,
- DixReadAccess);
- if (err != Success)
- return FALSE;
- defaultFont = pf;
- return TRUE;
-}
-
-/*
- * note that the font wakeup queue is not refcounted. this is because
- * an fpe needs to be added when it's inited, and removed when it's finally
- * freed, in order to handle any data that isn't requested, like FS events.
- *
- * since the only thing that should call these routines is the renderer's
- * init_fpe() and free_fpe(), there shouldn't be any problem in using
- * freed data.
- */
-void
-QueueFontWakeup(FontPathElementPtr fpe)
-{
- int i;
- FontPathElementPtr *new;
-
- for (i = 0; i < num_slept_fpes; i++) {
- if (slept_fpes[i] == fpe) {
- return;
- }
- }
- if (num_slept_fpes == size_slept_fpes) {
- new = (FontPathElementPtr *)
- xrealloc(slept_fpes,
- sizeof(FontPathElementPtr) * (size_slept_fpes + 4));
- if (!new)
- return;
- slept_fpes = new;
- size_slept_fpes += 4;
- }
- slept_fpes[num_slept_fpes] = fpe;
- num_slept_fpes++;
-}
-
-void
-RemoveFontWakeup(FontPathElementPtr fpe)
-{
- int i,
- j;
-
- for (i = 0; i < num_slept_fpes; i++) {
- if (slept_fpes[i] == fpe) {
- for (j = i; j < num_slept_fpes; j++) {
- slept_fpes[j] = slept_fpes[j + 1];
- }
- num_slept_fpes--;
- return;
- }
- }
-}
-
-void
-FontWakeup(pointer data, int count, pointer LastSelectMask)
-{
- int i;
- FontPathElementPtr fpe;
-
- if (count < 0)
- return;
- /* wake up any fpe's that may be waiting for information */
- for (i = 0; i < num_slept_fpes; i++) {
- fpe = slept_fpes[i];
- (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask);
- }
-}
-
-/* XXX -- these two funcs may want to be broken into macros */
-static void
-UseFPE(FontPathElementPtr fpe)
-{
- fpe->refcount++;
-}
-
-static void
-FreeFPE (FontPathElementPtr fpe)
-{
- fpe->refcount--;
- if (fpe->refcount == 0) {
- (*fpe_functions[fpe->type].free_fpe) (fpe);
- xfree(fpe->name);
- xfree(fpe);
- }
-}
-
-static Bool
-doOpenFont(ClientPtr client, OFclosurePtr c)
-{
- FontPtr pfont = NullFont;
- FontPathElementPtr fpe = NULL;
- ScreenPtr pScr;
- int err = Successful;
- int i;
- char *alias,
- *newname;
- int newlen;
- int aliascount = 20;
- /*
- * Decide at runtime what FontFormat to use.
- */
- Mask FontFormat =
-
- ((screenInfo.imageByteOrder == LSBFirst) ?
- BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) |
-
- ((screenInfo.bitmapBitOrder == LSBFirst) ?
- BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) |
-
- BitmapFormatImageRectMin |
-
-#if GLYPHPADBYTES == 1
- BitmapFormatScanlinePad8 |
-#endif
-
-#if GLYPHPADBYTES == 2
- BitmapFormatScanlinePad16 |
-#endif
-
-#if GLYPHPADBYTES == 4
- BitmapFormatScanlinePad32 |
-#endif
-
-#if GLYPHPADBYTES == 8
- BitmapFormatScanlinePad64 |
-#endif
-
- BitmapFormatScanlineUnit8;
-
- if (client->clientGone)
- {
- if (c->current_fpe < c->num_fpes)
- {
- fpe = c->fpe_list[c->current_fpe];
- (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
- }
- err = Successful;
- goto bail;
- }
- while (c->current_fpe < c->num_fpes) {
- fpe = c->fpe_list[c->current_fpe];
- err = (*fpe_functions[fpe->type].open_font)
- ((pointer) client, fpe, c->flags,
- c->fontname, c->fnamelen, FontFormat,
- BitmapFormatMaskByte |
- BitmapFormatMaskBit |
- BitmapFormatMaskImageRectangle |
- BitmapFormatMaskScanLinePad |
- BitmapFormatMaskScanLineUnit,
- c->fontid, &pfont, &alias,
- c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
- c->non_cachable_font :
- (FontPtr)0);
-
- if (err == FontNameAlias && alias) {
- newlen = strlen(alias);
- newname = (char *) xrealloc(c->fontname, newlen);
- if (!newname) {
- err = AllocError;
- break;
- }
- memmove(newname, alias, newlen);
- c->fontname = newname;
- c->fnamelen = newlen;
- c->current_fpe = 0;
- if (--aliascount <= 0) {
- /* We've tried resolving this alias 20 times, we're
- * probably stuck in an infinite loop of aliases pointing
- * to each other - time to take emergency exit!
- */
- err = BadImplementation;
- break;
- }
- continue;
- }
- if (err == BadFontName) {
- c->current_fpe++;
- continue;
- }
- if (err == Suspended) {
- if (!c->slept) {
- c->slept = TRUE;
- ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c);
- }
- return TRUE;
- }
- break;
- }
-
- if (err != Successful)
- goto bail;
- if (!pfont) {
- err = BadFontName;
- goto bail;
- }
- /* check values for firstCol, lastCol, firstRow, and lastRow */
- if (pfont->info.firstCol > pfont->info.lastCol ||
- pfont->info.firstRow > pfont->info.lastRow ||
- pfont->info.lastCol - pfont->info.firstCol > 255) {
- err = AllocError;
- goto bail;
- }
- if (!pfont->fpe)
- pfont->fpe = fpe;
- pfont->refcnt++;
- if (pfont->refcnt == 1) {
- UseFPE(pfont->fpe);
- for (i = 0; i < screenInfo.numScreens; i++) {
- pScr = screenInfo.screens[i];
- if (pScr->RealizeFont)
- {
- if (!(*pScr->RealizeFont) (pScr, pfont))
- {
- CloseFont (pfont, (Font) 0);
- err = AllocError;
- goto bail;
- }
- }
- }
- }
- if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) {
- err = AllocError;
- goto bail;
- }
- if (patternCache && pfont != c->non_cachable_font)
- CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen,
- pfont);
-bail:
- if (err != Successful && c->client != serverClient) {
- SendErrorToClient(c->client, X_OpenFont, 0,
- c->fontid, FontToXError(err));
- }
- if (c->slept)
- ClientWakeup(c->client);
- for (i = 0; i < c->num_fpes; i++) {
- FreeFPE(c->fpe_list[i]);
- }
- xfree(c->fpe_list);
- xfree(c->fontname);
- xfree(c);
- return TRUE;
-}
-
-int
-OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname)
-{
- OFclosurePtr c;
- int i;
- FontPtr cached = (FontPtr)0;
-
-#ifdef FONTDEBUG
- char *f;
- f = xalloc(lenfname + 1);
- memmove(f, pfontname, lenfname);
- f[lenfname] = '\0';
- ErrorF("[dix] OpenFont: fontname is \"%s\"\n", f);
- xfree(f);
-#endif
- if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
- return BadName;
- if (patternCache)
- {
-
- /*
- ** Check name cache. If we find a cached version of this font that
- ** is cachable, immediately satisfy the request with it. If we find
- ** a cached version of this font that is non-cachable, we do not
- ** satisfy the request with it. Instead, we pass the FontPtr to the
- ** FPE's open_font code (the fontfile FPE in turn passes the
- ** information to the rasterizer; the fserve FPE ignores it).
- **
- ** Presumably, the font is marked non-cachable because the FPE has
- ** put some licensing restrictions on it. If the FPE, using
- ** whatever logic it relies on, determines that it is willing to
- ** share this existing font with the client, then it has the option
- ** to return the FontPtr we passed it as the newly-opened font.
- ** This allows the FPE to exercise its licensing logic without
- ** having to create another instance of a font that already exists.
- */
-
- cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
- if (cached && cached->info.cachable)
- {
- if (!AddResource(fid, RT_FONT, (pointer) cached))
- return BadAlloc;
- cached->refcnt++;
- return Success;
- }
- }
- c = xalloc(sizeof(OFclosureRec));
- if (!c)
- return BadAlloc;
- c->fontname = xalloc(lenfname);
- c->origFontName = pfontname;
- c->origFontNameLen = lenfname;
- if (!c->fontname) {
- xfree(c);
- return BadAlloc;
- }
- /*
- * copy the current FPE list, so that if it gets changed by another client
- * while we're blocking, the request still appears atomic
- */
- c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes);
- if (!c->fpe_list) {
- xfree(c->fontname);
- xfree(c);
- return BadAlloc;
- }
- memmove(c->fontname, pfontname, lenfname);
- for (i = 0; i < num_fpes; i++) {
- c->fpe_list[i] = font_path_elements[i];
- UseFPE(c->fpe_list[i]);
- }
- c->client = client;
- c->fontid = fid;
- c->current_fpe = 0;
- c->num_fpes = num_fpes;
- c->fnamelen = lenfname;
- c->slept = FALSE;
- c->flags = flags;
- c->non_cachable_font = cached;
-
- (void) doOpenFont(client, c);
- return Success;
-}
-
-/**
- * Decrement font's ref count, and free storage if ref count equals zero
- *
- * \param value must conform to DeleteType
- */
-int
-CloseFont(pointer value, XID fid)
-{
- int nscr;
- ScreenPtr pscr;
- FontPathElementPtr fpe;
- FontPtr pfont = (FontPtr)value;
-
- if (pfont == NullFont)
- return (Success);
- if (--pfont->refcnt == 0) {
- if (patternCache)
- RemoveCachedFontPattern (patternCache, pfont);
- /*
- * since the last reference is gone, ask each screen to free any
- * storage it may have allocated locally for it.
- */
- for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
- pscr = screenInfo.screens[nscr];
- if (pscr->UnrealizeFont)
- (*pscr->UnrealizeFont) (pscr, pfont);
- }
- if (pfont == defaultFont)
- defaultFont = NULL;
-#ifdef XF86BIGFONT
- XF86BigfontFreeFontShm(pfont);
-#endif
- fpe = pfont->fpe;
- (*fpe_functions[fpe->type].close_font) (fpe, pfont);
- FreeFPE(fpe);
- }
- return (Success);
-}
-
-
-/***====================================================================***/
-
-/**
- * Sets up pReply as the correct QueryFontReply for pFont with the first
- * nProtoCCIStructs char infos.
- *
- * \param pReply caller must allocate this storage
- */
-void
-QueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs)
-{
- FontPropPtr pFP;
- int r,
- c,
- i;
- xFontProp *prFP;
- xCharInfo *prCI;
- xCharInfo *charInfos[256];
- unsigned char chars[512];
- int ninfos;
- unsigned long ncols;
- unsigned long count;
-
- /* pr->length set in dispatch */
- pReply->minCharOrByte2 = pFont->info.firstCol;
- pReply->defaultChar = pFont->info.defaultCh;
- pReply->maxCharOrByte2 = pFont->info.lastCol;
- pReply->drawDirection = pFont->info.drawDirection;
- pReply->allCharsExist = pFont->info.allExist;
- pReply->minByte1 = pFont->info.firstRow;
- pReply->maxByte1 = pFont->info.lastRow;
- pReply->fontAscent = pFont->info.fontAscent;
- pReply->fontDescent = pFont->info.fontDescent;
-
- pReply->minBounds = pFont->info.ink_minbounds;
- pReply->maxBounds = pFont->info.ink_maxbounds;
-
- pReply->nFontProps = pFont->info.nprops;
- pReply->nCharInfos = nProtoCCIStructs;
-
- for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]);
- i < pFont->info.nprops;
- i++, pFP++, prFP++) {
- prFP->name = pFP->name;
- prFP->value = pFP->value;
- }
-
- ninfos = 0;
- ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1);
- prCI = (xCharInfo *) (prFP);
- for (r = pFont->info.firstRow;
- ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow;
- r++) {
- i = 0;
- for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) {
- chars[i++] = r;
- chars[i++] = c;
- }
- (*pFont->get_metrics) (pFont, ncols, chars,
- TwoD16Bit, &count, charInfos);
- i = 0;
- for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) {
- *prCI = *charInfos[i];
- prCI++;
- ninfos++;
- }
- }
- return;
-}
-
-static Bool
-doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
-{
- FontPathElementPtr fpe;
- int err = Successful;
- FontNamesPtr names = NULL;
- char *name, *resolved=NULL;
- int namelen, resolvedlen;
- int nnames;
- int stringLens;
- int i;
- xListFontsReply reply;
- char *bufptr;
- char *bufferStart;
- int aliascount = 0;
-
- if (client->clientGone)
- {
- if (c->current.current_fpe < c->num_fpes)
- {
- fpe = c->fpe_list[c->current.current_fpe];
- (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
- }
- err = Successful;
- goto bail;
- }
-
- if (!c->current.patlen)
- goto finish;
-
- while (c->current.current_fpe < c->num_fpes) {
- fpe = c->fpe_list[c->current.current_fpe];
- err = Successful;
-
- if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
- {
- /* This FPE doesn't support/require list_fonts_and_aliases */
-
- err = (*fpe_functions[fpe->type].list_fonts)
- ((pointer) c->client, fpe, c->current.pattern,
- c->current.patlen, c->current.max_names - c->names->nnames,
- c->names);
-
- if (err == Suspended) {
- if (!c->slept) {
- c->slept = TRUE;
- ClientSleep(client,
- (ClientSleepProcPtr)doListFontsAndAliases,
- (pointer) c);
- }
- return TRUE;
- }
-
- err = BadFontName;
- }
- else
- {
- /* Start of list_fonts_and_aliases functionality. Modeled
- after list_fonts_with_info in that it resolves aliases,
- except that the information collected from FPEs is just
- names, not font info. Each list_next_font_or_alias()
- returns either a name into name/namelen or an alias into
- name/namelen and its target name into resolved/resolvedlen.
- The code at this level then resolves the alias by polling
- the FPEs. */
-
- if (!c->current.list_started) {
- err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
- ((pointer) c->client, fpe, c->current.pattern,
- c->current.patlen, c->current.max_names - c->names->nnames,
- &c->current.private);
- if (err == Suspended) {
- if (!c->slept) {
- ClientSleep(client,
- (ClientSleepProcPtr)doListFontsAndAliases,
- (pointer) c);
- c->slept = TRUE;
- }
- return TRUE;
- }
- if (err == Successful)
- c->current.list_started = TRUE;
- }
- if (err == Successful) {
- char *tmpname;
- name = 0;
- err = (*fpe_functions[fpe->type].list_next_font_or_alias)
- ((pointer) c->client, fpe, &name, &namelen, &tmpname,
- &resolvedlen, c->current.private);
- if (err == Suspended) {
- if (!c->slept) {
- ClientSleep(client,
- (ClientSleepProcPtr)doListFontsAndAliases,
- (pointer) c);
- c->slept = TRUE;
- }
- return TRUE;
- }
- if (err == FontNameAlias) {
- if (resolved) xfree(resolved);
- resolved = xalloc(resolvedlen + 1);
- if (resolved)
- memmove(resolved, tmpname, resolvedlen + 1);
- }
- }
-
- if (err == Successful)
- {
- if (c->haveSaved)
- {
- if (c->savedName)
- (void)AddFontNamesName(c->names, c->savedName,
- c->savedNameLen);
- }
- else
- (void)AddFontNamesName(c->names, name, namelen);
- }
-
- /*
- * When we get an alias back, save our state and reset back to
- * the start of the FPE looking for the specified name. As
- * soon as a real font is found for the alias, pop back to the
- * old state
- */
- else if (err == FontNameAlias) {
- char tmp_pattern[XLFDMAXFONTNAMELEN];
- /*
- * when an alias recurses, we need to give
- * the last FPE a chance to clean up; so we call
- * it again, and assume that the error returned
- * is BadFontName, indicating the alias resolution
- * is complete.
- */
- memmove(tmp_pattern, resolved, resolvedlen);
- if (c->haveSaved)
- {
- char *tmpname;
- int tmpnamelen;
-
- tmpname = 0;
- (void) (*fpe_functions[fpe->type].list_next_font_or_alias)
- ((pointer) c->client, fpe, &tmpname, &tmpnamelen,
- &tmpname, &tmpnamelen, c->current.private);
- if (--aliascount <= 0)
- {
- err = BadFontName;
- goto ContBadFontName;
- }
- }
- else
- {
- c->saved = c->current;
- c->haveSaved = TRUE;
- if (c->savedName)
- xfree(c->savedName);
- c->savedName = xalloc(namelen + 1);
- if (c->savedName)
- memmove(c->savedName, name, namelen + 1);
- c->savedNameLen = namelen;
- aliascount = 20;
- }
- memmove(c->current.pattern, tmp_pattern, resolvedlen);
- c->current.patlen = resolvedlen;
- c->current.max_names = c->names->nnames + 1;
- c->current.current_fpe = -1;
- c->current.private = 0;
- err = BadFontName;
- }
- }
- /*
- * At the end of this FPE, step to the next. If we've finished
- * processing an alias, pop state back. If we've collected enough
- * font names, quit.
- */
- if (err == BadFontName) {
- ContBadFontName: ;
- c->current.list_started = FALSE;
- c->current.current_fpe++;
- err = Successful;
- if (c->haveSaved)
- {
- if (c->names->nnames == c->current.max_names ||
- c->current.current_fpe == c->num_fpes) {
- c->haveSaved = FALSE;
- c->current = c->saved;
- /* Give the saved namelist a chance to clean itself up */
- continue;
- }
- }
- if (c->names->nnames == c->current.max_names)
- break;
- }
- }
-
- /*
- * send the reply
- */
- if (err != Successful) {
- SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
- goto bail;
- }
-
-finish:
-
- names = c->names;
- nnames = names->nnames;
- client = c->client;
- stringLens = 0;
- for (i = 0; i < nnames; i++)
- stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
-
- memset(&reply, 0, sizeof(xListFontsReply));
- reply.type = X_Reply;
- reply.length = bytes_to_int32(stringLens + nnames);
- reply.nFonts = nnames;
- reply.sequenceNumber = client->sequence;
-
- bufptr = bufferStart = xalloc(reply.length << 2);
-
- if (!bufptr && reply.length) {
- SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
- goto bail;
- }
- /*
- * since WriteToClient long word aligns things, copy to temp buffer and
- * write all at once
- */
- for (i = 0; i < nnames; i++) {
- if (names->length[i] > 255)
- reply.nFonts--;
- else
- {
- *bufptr++ = names->length[i];
- memmove( bufptr, names->names[i], names->length[i]);
- bufptr += names->length[i];
- }
- }
- nnames = reply.nFonts;
- reply.length = bytes_to_int32(stringLens + nnames);
- client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
- WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
- (void) WriteToClient(client, stringLens + nnames, bufferStart);
- xfree(bufferStart);
-
-bail:
- if (c->slept)
- ClientWakeup(client);
- for (i = 0; i < c->num_fpes; i++)
- FreeFPE(c->fpe_list[i]);
- xfree(c->fpe_list);
- if (c->savedName) xfree(c->savedName);
- FreeFontNames(names);
- xfree(c);
- if (resolved) xfree(resolved);
- return TRUE;
-}
-
-int
-ListFonts(ClientPtr client, unsigned char *pattern, unsigned length,
- unsigned max_names)
-{
- int i;
- LFclosurePtr c;
-
- /*
- * The right error to return here would be BadName, however the
- * specification does not allow for a Name error on this request.
- * Perhaps a better solution would be to return a nil list, i.e.
- * a list containing zero fontnames.
- */
- if (length > XLFDMAXFONTNAMELEN)
- return BadAlloc;
-
- i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
- if (i != Success)
- return i;
-
- if (!(c = xalloc(sizeof *c)))
- return BadAlloc;
- c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes);
- if (!c->fpe_list) {
- xfree(c);
- return BadAlloc;
- }
- c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100);
- if (!c->names)
- {
- xfree(c->fpe_list);
- xfree(c);
- return BadAlloc;
- }
- memmove( c->current.pattern, pattern, length);
- for (i = 0; i < num_fpes; i++) {
- c->fpe_list[i] = font_path_elements[i];
- UseFPE(c->fpe_list[i]);
- }
- c->client = client;
- c->num_fpes = num_fpes;
- c->current.patlen = length;
- c->current.current_fpe = 0;
- c->current.max_names = max_names;
- c->current.list_started = FALSE;
- c->current.private = 0;
- c->haveSaved = FALSE;
- c->slept = FALSE;
- c->savedName = 0;
- doListFontsAndAliases(client, c);
- return Success;
-}
-
-int
-doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
-{
- FontPathElementPtr fpe;
- int err = Successful;
- char *name;
- int namelen;
- int numFonts;
- FontInfoRec fontInfo,
- *pFontInfo;
- xListFontsWithInfoReply *reply;
- int length;
- xFontProp *pFP;
- int i;
- int aliascount = 0;
- xListFontsWithInfoReply finalReply;
-
- if (client->clientGone)
- {
- if (c->current.current_fpe < c->num_fpes)
- {
- fpe = c->fpe_list[c->current.current_fpe];
- (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
- }
- err = Successful;
- goto bail;
- }
- client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
- if (!c->current.patlen)
- goto finish;
- while (c->current.current_fpe < c->num_fpes)
- {
- fpe = c->fpe_list[c->current.current_fpe];
- err = Successful;
- if (!c->current.list_started)
- {
- err = (*fpe_functions[fpe->type].start_list_fonts_with_info)
- (client, fpe, c->current.pattern, c->current.patlen,
- c->current.max_names, &c->current.private);
- if (err == Suspended)
- {
- if (!c->slept)
- {
- ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c);
- c->slept = TRUE;
- }
- return TRUE;
- }
- if (err == Successful)
- c->current.list_started = TRUE;
- }
- if (err == Successful)
- {
- name = 0;
- pFontInfo = &fontInfo;
- err = (*fpe_functions[fpe->type].list_next_font_with_info)
- (client, fpe, &name, &namelen, &pFontInfo,
- &numFonts, c->current.private);
- if (err == Suspended)
- {
- if (!c->slept)
- {
- ClientSleep(client,
- (ClientSleepProcPtr)doListFontsWithInfo,
- c);
- c->slept = TRUE;
- }
- return TRUE;
- }
- }
- /*
- * When we get an alias back, save our state and reset back to the
- * start of the FPE looking for the specified name. As soon as a real
- * font is found for the alias, pop back to the old state
- */
- if (err == FontNameAlias)
- {
- /*
- * when an alias recurses, we need to give
- * the last FPE a chance to clean up; so we call
- * it again, and assume that the error returned
- * is BadFontName, indicating the alias resolution
- * is complete.
- */
- if (c->haveSaved)
- {
- char *tmpname;
- int tmpnamelen;
- FontInfoPtr tmpFontInfo;
-
- tmpname = 0;
- tmpFontInfo = &fontInfo;
- (void) (*fpe_functions[fpe->type].list_next_font_with_info)
- (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
- &numFonts, c->current.private);
- if (--aliascount <= 0)
- {
- err = BadFontName;
- goto ContBadFontName;
- }
- }
- else
- {
- c->saved = c->current;
- c->haveSaved = TRUE;
- c->savedNumFonts = numFonts;
- if (c->savedName)
- xfree(c->savedName);
- c->savedName = xalloc(namelen + 1);
- if (c->savedName)
- memmove(c->savedName, name, namelen + 1);
- aliascount = 20;
- }
- memmove(c->current.pattern, name, namelen);
- c->current.patlen = namelen;
- c->current.max_names = 1;
- c->current.current_fpe = 0;
- c->current.private = 0;
- c->current.list_started = FALSE;
- }
- /*
- * At the end of this FPE, step to the next. If we've finished
- * processing an alias, pop state back. If we've sent enough font
- * names, quit. Always wait for BadFontName to let the FPE
- * have a chance to clean up.
- */
- else if (err == BadFontName)
- {
- ContBadFontName: ;
- c->current.list_started = FALSE;
- c->current.current_fpe++;
- err = Successful;
- if (c->haveSaved)
- {
- if (c->current.max_names == 0 ||
- c->current.current_fpe == c->num_fpes)
- {
- c->haveSaved = FALSE;
- c->saved.max_names -= (1 - c->current.max_names);
- c->current = c->saved;
- }
- }
- else if (c->current.max_names == 0)
- break;
- }
- else if (err == Successful)
- {
- length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
- reply = c->reply;
- if (c->length < length)
- {
- reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length);
- if (!reply)
- {
- err = AllocError;
- break;
- }
- memset((char*)reply + c->length, 0, length - c->length);
- c->reply = reply;
- c->length = length;
- }
- if (c->haveSaved)
- {
- numFonts = c->savedNumFonts;
- name = c->savedName;
- namelen = strlen(name);
- }
- reply->type = X_Reply;
- reply->length = bytes_to_int32(sizeof *reply - sizeof(xGenericReply) +
- pFontInfo->nprops * sizeof(xFontProp) +
- namelen);
- reply->sequenceNumber = client->sequence;
- reply->nameLength = namelen;
- reply->minBounds = pFontInfo->ink_minbounds;
- reply->maxBounds = pFontInfo->ink_maxbounds;
- reply->minCharOrByte2 = pFontInfo->firstCol;
- reply->maxCharOrByte2 = pFontInfo->lastCol;
- reply->defaultChar = pFontInfo->defaultCh;
- reply->nFontProps = pFontInfo->nprops;
- reply->drawDirection = pFontInfo->drawDirection;
- reply->minByte1 = pFontInfo->firstRow;
- reply->maxByte1 = pFontInfo->lastRow;
- reply->allCharsExist = pFontInfo->allExist;
- reply->fontAscent = pFontInfo->fontAscent;
- reply->fontDescent = pFontInfo->fontDescent;
- reply->nReplies = numFonts;
- pFP = (xFontProp *) (reply + 1);
- for (i = 0; i < pFontInfo->nprops; i++)
- {
- pFP->name = pFontInfo->props[i].name;
- pFP->value = pFontInfo->props[i].value;
- pFP++;
- }
- WriteSwappedDataToClient(client, length, reply);
- (void) WriteToClient(client, namelen, name);
- if (pFontInfo == &fontInfo)
- {
- xfree(fontInfo.props);
- xfree(fontInfo.isStringProp);
- }
- --c->current.max_names;
- }
- }
-finish:
- length = sizeof(xListFontsWithInfoReply);
- bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply));
- finalReply.type = X_Reply;
- finalReply.sequenceNumber = client->sequence;
- finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply)
- - sizeof(xGenericReply));
- WriteSwappedDataToClient(client, length, &finalReply);
-bail:
- if (c->slept)
- ClientWakeup(client);
- for (i = 0; i < c->num_fpes; i++)
- FreeFPE(c->fpe_list[i]);
- xfree(c->reply);
- xfree(c->fpe_list);
- if (c->savedName) xfree(c->savedName);
- xfree(c);
- return TRUE;
-}
-
-int
-StartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern,
- int max_names)
-{
- int i;
- LFWIclosurePtr c;
-
- /*
- * The right error to return here would be BadName, however the
- * specification does not allow for a Name error on this request.
- * Perhaps a better solution would be to return a nil list, i.e.
- * a list containing zero fontnames.
- */
- if (length > XLFDMAXFONTNAMELEN)
- return BadAlloc;
-
- i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
- if (i != Success)
- return i;
-
- if (!(c = xalloc(sizeof *c)))
- goto badAlloc;
- c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes);
- if (!c->fpe_list)
- {
- xfree(c);
- goto badAlloc;
- }
- memmove(c->current.pattern, pattern, length);
- for (i = 0; i < num_fpes; i++)
- {
- c->fpe_list[i] = font_path_elements[i];
- UseFPE(c->fpe_list[i]);
- }
- c->client = client;
- c->num_fpes = num_fpes;
- c->reply = 0;
- c->length = 0;
- c->current.patlen = length;
- c->current.current_fpe = 0;
- c->current.max_names = max_names;
- c->current.list_started = FALSE;
- c->current.private = 0;
- c->savedNumFonts = 0;
- c->haveSaved = FALSE;
- c->slept = FALSE;
- c->savedName = 0;
- doListFontsWithInfo(client, c);
- return Success;
-badAlloc:
- return BadAlloc;
-}
-
-#define TextEltHeader 2
-#define FontShiftSize 5
-static XID clearGC[] = { CT_NONE };
-#define clearGCmask (GCClipMask)
-
-int
-doPolyText(ClientPtr client, PTclosurePtr c)
-{
- FontPtr pFont = c->pGC->font, oldpFont;
- Font fid, oldfid;
- int err = Success, lgerr; /* err is in X error, not font error, space */
- enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT;
- FontPathElementPtr fpe;
- GC *origGC = NULL;
-
- if (client->clientGone)
- {
- fpe = c->pGC->font->fpe;
- (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
-
- if (c->slept)
- {
- /* Client has died, but we cannot bail out right now. We
- need to clean up after the work we did when going to
- sleep. Setting the drawable pointer to 0 makes this
- happen without any attempts to render or perform other
- unnecessary activities. */
- c->pDraw = (DrawablePtr)0;
- }
- else
- {
- err = Success;
- goto bail;
- }
- }
-
- /* Make sure our drawable hasn't disappeared while we slept. */
- if (c->slept && c->pDraw)
- {
- DrawablePtr pDraw;
- dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
- if (c->pDraw != pDraw) {
- /* Our drawable has disappeared. Treat like client died... ask
- the FPE code to clean up after client and avoid further
- rendering while we clean up after ourself. */
- fpe = c->pGC->font->fpe;
- (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
- c->pDraw = (DrawablePtr)0;
- }
- }
-
- client_state = c->slept ? SLEEPING : NEVER_SLEPT;
-
- while (c->endReq - c->pElt > TextEltHeader)
- {
- if (*c->pElt == FontChange)
- {
- if (c->endReq - c->pElt < FontShiftSize)
- {
- err = BadLength;
- goto bail;
- }
-
- oldpFont = pFont;
- oldfid = fid;
-
- fid = ((Font)*(c->pElt+4)) /* big-endian */
- | ((Font)*(c->pElt+3)) << 8
- | ((Font)*(c->pElt+2)) << 16
- | ((Font)*(c->pElt+1)) << 24;
- err = dixLookupResourceByType((pointer *)&pFont, fid, RT_FONT,
- client, DixReadAccess);
- if (err != Success)
- {
- err = (err == BadValue) ? BadFont : err;
- /* restore pFont and fid for step 4 (described below) */
- pFont = oldpFont;
- fid = oldfid;
-
- /* If we're in START_SLEEP mode, the following step
- shortens the request... in the unlikely event that
- the fid somehow becomes valid before we come through
- again to actually execute the polytext, which would
- then mess up our refcounting scheme badly. */
- c->err = err;
- c->endReq = c->pElt;
-
- goto bail;
- }
-
- /* Step 3 (described below) on our new font */
- if (client_state == START_SLEEP)
- pFont->refcnt++;
- else
- {
- if (pFont != c->pGC->font && c->pDraw)
- {
- ChangeGC( c->pGC, GCFont, &fid);
- ValidateGC(c->pDraw, c->pGC);
- if (c->reqType == X_PolyText8)
- c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8;
- else
- c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16;
- }
-
- /* Undo the refcnt++ we performed when going to sleep */
- if (client_state == SLEEPING)
- (void)CloseFont(c->pGC->font, (Font)0);
- }
- c->pElt += FontShiftSize;
- }
- else /* print a string */
- {
- unsigned char *pNextElt;
- pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize;
- if ( pNextElt > c->endReq)
- {
- err = BadLength;
- goto bail;
- }
- if (client_state == START_SLEEP)
- {
- c->pElt = pNextElt;
- continue;
- }
- if (c->pDraw)
- {
- lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize,
- c->pElt + TextEltHeader);
- }
- else lgerr = Successful;
-
- if (lgerr == Suspended)
- {
- if (!c->slept) {
- int len;
- GC *pGC;
- PTclosurePtr new_closure;
-
- /* We're putting the client to sleep. We need to do a few things
- to ensure successful and atomic-appearing execution of the
- remainder of the request. First, copy the remainder of the
- request into a safe malloc'd area. Second, create a scratch GC
- to use for the remainder of the request. Third, mark all fonts
- referenced in the remainder of the request to prevent their
- deallocation. Fourth, make the original GC look like the
- request has completed... set its font to the final font value
- from this request. These GC manipulations are for the unlikely
- (but possible) event that some other client is using the GC.
- Steps 3 and 4 are performed by running this procedure through
- the remainder of the request in a special no-render mode
- indicated by client_state = START_SLEEP. */
-
- /* Step 1 */
- /* Allocate a malloc'd closure structure to replace
- the local one we were passed */
- new_closure = xalloc(sizeof(PTclosureRec));
- if (!new_closure)
- {
- err = BadAlloc;
- goto bail;
- }
- *new_closure = *c;
- c = new_closure;
-
- len = c->endReq - c->pElt;
- c->data = xalloc(len);
- if (!c->data)
- {
- xfree(c);
- err = BadAlloc;
- goto bail;
- }
- memmove(c->data, c->pElt, len);
- c->pElt = c->data;
- c->endReq = c->pElt + len;
-
- /* Step 2 */
-
- pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
- if (!pGC)
- {
- xfree(c->data);
- xfree(c);
- err = BadAlloc;
- goto bail;
- }
- if ((err = CopyGC(c->pGC, pGC, GCFunction |
- GCPlaneMask | GCForeground |
- GCBackground | GCFillStyle |
- GCTile | GCStipple |
- GCTileStipXOrigin |
- GCTileStipYOrigin | GCFont |
- GCSubwindowMode | GCClipXOrigin |
- GCClipYOrigin | GCClipMask)) !=
- Success)
- {
- FreeScratchGC(pGC);
- xfree(c->data);
- xfree(c);
- err = BadAlloc;
- goto bail;
- }
- origGC = c->pGC;
- c->pGC = pGC;
- ValidateGC(c->pDraw, c->pGC);
-
- c->slept = TRUE;
- ClientSleep(client,
- (ClientSleepProcPtr)doPolyText,
- (pointer) c);
-
- /* Set up to perform steps 3 and 4 */
- client_state = START_SLEEP;
- continue; /* on to steps 3 and 4 */
- }
- return TRUE;
- }
- else if (lgerr != Successful)
- {
- err = FontToXError(lgerr);
- goto bail;
- }
- if (c->pDraw)
- {
- c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */
- c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg,
- *c->pElt, c->pElt + TextEltHeader);
- }
- c->pElt = pNextElt;
- }
- }
-
-bail:
-
- if (client_state == START_SLEEP)
- {
- /* Step 4 */
- if (pFont != origGC->font)
- {
- ChangeGC(origGC, GCFont, &fid);
- ValidateGC(c->pDraw, origGC);
- }
-
- /* restore pElt pointer for execution of remainder of the request */
- c->pElt = c->data;
- return TRUE;
- }
-
- if (c->err != Success) err = c->err;
- if (err != Success && c->client != serverClient) {
-#ifdef PANORAMIX
- if (noPanoramiXExtension || !c->pGC->pScreen->myNum)
-#endif
- SendErrorToClient(c->client, c->reqType, 0, 0, err);
- }
- if (c->slept)
- {
- ClientWakeup(c->client);
- ChangeGC(c->pGC, clearGCmask, clearGC);
-
- /* Unreference the font from the scratch GC */
- CloseFont(c->pGC->font, (Font)0);
- c->pGC->font = NullFont;
-
- FreeScratchGC(c->pGC);
- xfree(c->data);
- xfree(c);
- }
- return TRUE;
-}
-
-int
-PolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt,
- unsigned char *endReq, int xorg, int yorg, int reqType, XID did)
-{
- PTclosureRec local_closure;
-
- local_closure.pElt = pElt;
- local_closure.endReq = endReq;
- local_closure.client = client;
- local_closure.pDraw = pDraw;
- local_closure.xorg = xorg;
- local_closure.yorg = yorg;
- if ((local_closure.reqType = reqType) == X_PolyText8)
- {
- local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8;
- local_closure.itemSize = 1;
- }
- else
- {
- local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16;
- local_closure.itemSize = 2;
- }
- local_closure.pGC = pGC;
- local_closure.did = did;
- local_closure.err = Success;
- local_closure.slept = FALSE;
-
- (void) doPolyText(client, &local_closure);
- return Success;
-}
-
-
-#undef TextEltHeader
-#undef FontShiftSize
-
-int
-doImageText(ClientPtr client, ITclosurePtr c)
-{
- int err = Success, lgerr; /* err is in X error, not font error, space */
- FontPathElementPtr fpe;
-
- if (client->clientGone)
- {
- fpe = c->pGC->font->fpe;
- (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
- err = Success;
- goto bail;
- }
-
- /* Make sure our drawable hasn't disappeared while we slept. */
- if (c->slept && c->pDraw)
- {
- DrawablePtr pDraw;
- dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
- if (c->pDraw != pDraw) {
- /* Our drawable has disappeared. Treat like client died... ask
- the FPE code to clean up after client. */
- fpe = c->pGC->font->fpe;
- (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
- err = Success;
- goto bail;
- }
- }
-
- lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data);
- if (lgerr == Suspended)
- {
- if (!c->slept) {
- GC *pGC;
- unsigned char *data;
- ITclosurePtr new_closure;
-
- /* We're putting the client to sleep. We need to
- save some state. Similar problem to that handled
- in doPolyText, but much simpler because the
- request structure is much simpler. */
-
- new_closure = xalloc(sizeof(ITclosureRec));
- if (!new_closure)
- {
- err = BadAlloc;
- goto bail;
- }
- *new_closure = *c;
- c = new_closure;
-
- data = xalloc(c->nChars * c->itemSize);
- if (!data)
- {
- xfree(c);
- err = BadAlloc;
- goto bail;
- }
- memmove(data, c->data, c->nChars * c->itemSize);
- c->data = data;
-
- pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
- if (!pGC)
- {
- xfree(c->data);
- xfree(c);
- err = BadAlloc;
- goto bail;
- }
- if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask |
- GCForeground | GCBackground | GCFillStyle |
- GCTile | GCStipple | GCTileStipXOrigin |
- GCTileStipYOrigin | GCFont |
- GCSubwindowMode | GCClipXOrigin |
- GCClipYOrigin | GCClipMask)) != Success)
- {
- FreeScratchGC(pGC);
- xfree(c->data);
- xfree(c);
- err = BadAlloc;
- goto bail;
- }
- c->pGC = pGC;
- ValidateGC(c->pDraw, c->pGC);
-
- c->slept = TRUE;
- ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c);
- }
- return TRUE;
- }
- else if (lgerr != Successful)
- {
- err = FontToXError(lgerr);
- goto bail;
- }
- if (c->pDraw)
- {
- (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg,
- c->nChars, c->data);
- }
-
-bail:
-
- if (err != Success && c->client != serverClient) {
- SendErrorToClient(c->client, c->reqType, 0, 0, err);
- }
- if (c->slept)
- {
- ClientWakeup(c->client);
- ChangeGC(c->pGC, clearGCmask, clearGC);
-
- /* Unreference the font from the scratch GC */
- CloseFont(c->pGC->font, (Font)0);
- c->pGC->font = NullFont;
-
- FreeScratchGC(c->pGC);
- xfree(c->data);
- xfree(c);
- }
- return TRUE;
-}
-
-int
-ImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars,
- unsigned char *data, int xorg, int yorg, int reqType, XID did)
-{
- ITclosureRec local_closure;
-
- local_closure.client = client;
- local_closure.pDraw = pDraw;
- local_closure.pGC = pGC;
- local_closure.nChars = nChars;
- local_closure.data = data;
- local_closure.xorg = xorg;
- local_closure.yorg = yorg;
- if ((local_closure.reqType = reqType) == X_ImageText8)
- {
- local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8;
- local_closure.itemSize = 1;
- }
- else
- {
- local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16;
- local_closure.itemSize = 2;
- }
- local_closure.did = did;
- local_closure.slept = FALSE;
-
- (void) doImageText(client, &local_closure);
- return Success;
-}
-
-
-/* does the necessary magic to figure out the fpe type */
-static int
-DetermineFPEType(char *pathname)
-{
- int i;
-
- for (i = 0; i < num_fpe_types; i++) {
- if ((*fpe_functions[i].name_check) (pathname))
- return i;
- }
- return -1;
-}
-
-
-static void
-FreeFontPath(FontPathElementPtr *list, int n, Bool force)
-{
- int i;
-
- for (i = 0; i < n; i++) {
- if (force) {
- /* Sanity check that all refcounts will be 0 by the time
- we get to the end of the list. */
- int found = 1; /* the first reference is us */
- int j;
- for (j = i+1; j < n; j++) {
- if (list[j] == list[i])
- found++;
- }
- if (list[i]->refcount != found) {
- list[i]->refcount = found; /* ensure it will get freed */
- }
- }
- FreeFPE(list[i]);
- }
- xfree(list);
-}
-
-static FontPathElementPtr
-find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len)
-{
- FontPathElementPtr fpe;
- int i;
-
- for (i = 0; i < num; i++) {
- fpe = list[i];
- if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0)
- return fpe;
- }
- return (FontPathElementPtr) 0;
-}
-
-
-static int
-SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist)
-{
- int i, err = 0;
- int valid_paths = 0;
- unsigned int len;
- unsigned char *cp = paths;
- FontPathElementPtr fpe = NULL, *fplist;
-
- fplist = xalloc(sizeof(FontPathElementPtr) * npaths);
- if (!fplist) {
- *bad = 0;
- return BadAlloc;
- }
- for (i = 0; i < num_fpe_types; i++) {
- if (fpe_functions[i].set_path_hook)
- (*fpe_functions[i].set_path_hook) ();
- }
- for (i = 0; i < npaths; i++)
- {
- len = (unsigned int) (*cp++);
-
- if (len == 0)
- {
- if (persist)
- ErrorF("[dix] Removing empty element from the valid list of fontpaths\n");
- err = BadValue;
- }
- else
- {
- /* if it's already in our active list, just reset it */
- /*
- * note that this can miss FPE's in limbo -- may be worth catching
- * them, though it'd muck up refcounting
- */
- fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len);
- if (fpe)
- {
- err = (*fpe_functions[fpe->type].reset_fpe) (fpe);
- if (err == Successful)
- {
- UseFPE(fpe);/* since it'll be decref'd later when freed
- * from the old list */
- }
- else
- fpe = 0;
- }
- /* if error or can't do it, act like it's a new one */
- if (!fpe)
- {
- fpe = xalloc(sizeof(FontPathElementRec));
- if (!fpe)
- {
- err = BadAlloc;
- goto bail;
- }
- fpe->name = xalloc(len + 1);
- if (!fpe->name)
- {
- xfree(fpe);
- err = BadAlloc;
- goto bail;
- }
- fpe->refcount = 1;
-
- strncpy(fpe->name, (char *) cp, (int) len);
- fpe->name[len] = '\0';
- fpe->name_length = len;
- fpe->type = DetermineFPEType(fpe->name);
- if (fpe->type == -1)
- err = BadValue;
- else
- err = (*fpe_functions[fpe->type].init_fpe) (fpe);
- if (err != Successful)
- {
- if (persist)
- {
- ErrorF("[dix] Could not init font path element %s, removing from list!\n",
- fpe->name);
- }
- xfree (fpe->name);
- xfree (fpe);
- }
- }
- }
- if (err != Successful)
- {
- if (!persist)
- goto bail;
- }
- else
- {
- fplist[valid_paths++] = fpe;
- }
- cp += len;
- }
-
- FreeFontPath(font_path_elements, num_fpes, FALSE);
- font_path_elements = fplist;
- if (patternCache)
- EmptyFontPatternCache(patternCache);
- num_fpes = valid_paths;
-
- return Success;
-bail:
- *bad = i;
- while (--valid_paths >= 0)
- FreeFPE(fplist[valid_paths]);
- xfree(fplist);
- return FontToXError(err);
-}
-
-/* XXX -- do we need to pass error down to each renderer? */
-int
-SetFontPath(ClientPtr client, int npaths, unsigned char *paths, int *error)
-{
- int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
- if (err != Success)
- return err;
-
- if (npaths == 0) {
- if (SetDefaultFontPath(defaultFontPath) != Success)
- return BadValue;
- } else {
- err = SetFontPathElements(npaths, paths, error, FALSE);
- }
- return err;
-}
-
-int
-SetDefaultFontPath(char *path)
-{
- char *temp_path,
- *start,
- *end;
- unsigned char *cp,
- *pp,
- *nump,
- *newpath;
- int num = 1,
- len,
- err,
- size = 0,
- bad;
-
- /* ensure temp_path contains "built-ins" */
- start = path;
- while (1) {
- start = strstr(start, "built-ins");
- if (start == NULL)
- break;
- end = start + strlen("built-ins");
- if ((start == path || start[-1] == ',') && (!*end || *end == ','))
- break;
- start = end;
- }
- if (!start) {
- temp_path = Xprintf("%s%sbuilt-ins", path, *path ? "," : "");
- } else {
- temp_path = Xstrdup(path);
- }
- if (!temp_path)
- return BadAlloc;
-
- /* get enough for string, plus values -- use up commas */
- len = strlen(temp_path) + 1;
- nump = cp = newpath = xalloc(len);
- if (!newpath)
- return BadAlloc;
- pp = (unsigned char *) temp_path;
- cp++;
- while (*pp) {
- if (*pp == ',') {
- *nump = (unsigned char) size;
- nump = cp++;
- pp++;
- num++;
- size = 0;
- } else {
- *cp++ = *pp++;
- size++;
- }
- }
- *nump = (unsigned char) size;
-
- err = SetFontPathElements(num, newpath, &bad, TRUE);
-
- xfree(newpath);
- xfree(temp_path);
-
- return err;
-}
-
-int
-GetFontPath(ClientPtr client, int *count, int *length, unsigned char **result)
-{
- int i;
- unsigned char *c;
- int len;
- FontPathElementPtr fpe;
-
- i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
- if (i != Success)
- return i;
-
- len = 0;
- for (i = 0; i < num_fpes; i++) {
- fpe = font_path_elements[i];
- len += fpe->name_length + 1;
- }
- font_path_string = (unsigned char *) xrealloc(font_path_string, len);
- if (!font_path_string)
- return BadAlloc;
-
- c = font_path_string;
- *length = 0;
- for (i = 0; i < num_fpes; i++) {
- fpe = font_path_elements[i];
- *c = fpe->name_length;
- *length += *c++;
- memmove(c, fpe->name, fpe->name_length);
- c += fpe->name_length;
- }
- *count = num_fpes;
- *result = font_path_string;
- return Success;
-}
-
-void
-DeleteClientFontStuff(ClientPtr client)
-{
- int i;
- FontPathElementPtr fpe;
-
- for (i = 0; i < num_fpes; i++)
- {
- fpe = font_path_elements[i];
- if (fpe_functions[fpe->type].client_died)
- (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
- }
-}
-
-void
-InitFonts (void)
-{
- patternCache = MakeFontPatternCache();
-
- BuiltinRegisterFpeFunctions();
- FontFileRegisterFpeFunctions();
- fs_register_fpe_functions();
-}
-
-int
-GetDefaultPointSize (void)
-{
- return 120;
-}
-
-
-FontResolutionPtr
-GetClientResolutions (int *num)
-{
- static struct _FontResolution res;
- ScreenPtr pScreen;
-
- pScreen = screenInfo.screens[0];
- res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth;
- /*
- * XXX - we'll want this as long as bitmap instances are prevalent
- so that we can match them from scalable fonts
- */
- if (res.x_resolution < 88)
- res.x_resolution = 75;
- else
- res.x_resolution = 100;
- res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight;
- if (res.y_resolution < 88)
- res.y_resolution = 75;
- else
- res.y_resolution = 100;
- res.point_size = 120;
- *num = 1;
- return &res;
-}
-
-/*
- * returns the type index of the new fpe
- *
- * should be called (only once!) by each type of fpe when initialized
- */
-
-int
-RegisterFPEFunctions(NameCheckFunc name_func,
- InitFpeFunc init_func,
- FreeFpeFunc free_func,
- ResetFpeFunc reset_func,
- OpenFontFunc open_func,
- CloseFontFunc close_func,
- ListFontsFunc list_func,
- StartLfwiFunc start_lfwi_func,
- NextLfwiFunc next_lfwi_func,
- WakeupFpeFunc wakeup_func,
- ClientDiedFunc client_died,
- LoadGlyphsFunc load_glyphs,
- StartLaFunc start_list_alias_func,
- NextLaFunc next_list_alias_func,
- SetPathFunc set_path_func)
-{
- FPEFunctions *new;
-
- /* grow the list */
- new = (FPEFunctions *) xrealloc(fpe_functions,
- (num_fpe_types + 1) * sizeof(FPEFunctions));
- if (!new)
- return -1;
- fpe_functions = new;
-
- fpe_functions[num_fpe_types].name_check = name_func;
- fpe_functions[num_fpe_types].open_font = open_func;
- fpe_functions[num_fpe_types].close_font = close_func;
- fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func;
- fpe_functions[num_fpe_types].list_fonts = list_func;
- fpe_functions[num_fpe_types].start_list_fonts_with_info =
- start_lfwi_func;
- fpe_functions[num_fpe_types].list_next_font_with_info =
- next_lfwi_func;
- fpe_functions[num_fpe_types].init_fpe = init_func;
- fpe_functions[num_fpe_types].free_fpe = free_func;
- fpe_functions[num_fpe_types].reset_fpe = reset_func;
- fpe_functions[num_fpe_types].client_died = client_died;
- fpe_functions[num_fpe_types].load_glyphs = load_glyphs;
- fpe_functions[num_fpe_types].start_list_fonts_and_aliases =
- start_list_alias_func;
- fpe_functions[num_fpe_types].list_next_font_or_alias =
- next_list_alias_func;
- fpe_functions[num_fpe_types].set_path_hook = set_path_func;
-
- return num_fpe_types++;
-}
-
-void
-FreeFonts(void)
-{
- if (patternCache) {
- FreeFontPatternCache(patternCache);
- patternCache = 0;
- }
- FreeFontPath(font_path_elements, num_fpes, TRUE);
- font_path_elements = 0;
- num_fpes = 0;
- xfree(fpe_functions);
- num_fpe_types = 0;
- fpe_functions = (FPEFunctions *) 0;
-}
-
-/* convenience functions for FS interface */
-
-FontPtr
-find_old_font(XID id)
-{
- pointer pFont;
- dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess);
- return (FontPtr)pFont;
-}
-
-Font
-GetNewFontClientID(void)
-{
- return FakeClientID(0);
-}
-
-int
-StoreFontClientFont(FontPtr pfont, Font id)
-{
- return AddResource(id, RT_NONE, (pointer) pfont);
-}
-
-void
-DeleteFontClientID(Font id)
-{
- FreeResource(id, RT_NONE);
-}
-
-int
-client_auth_generation(ClientPtr client)
-{
- return 0;
-}
-
-static int fs_handlers_installed = 0;
-static unsigned int last_server_gen;
-
-int
-init_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler)
-{
- /* if server has reset, make sure the b&w handlers are reinstalled */
- if (last_server_gen < serverGeneration) {
- last_server_gen = serverGeneration;
- fs_handlers_installed = 0;
- }
- if (fs_handlers_installed == 0) {
- if (!RegisterBlockAndWakeupHandlers(block_handler,
- FontWakeup, (pointer) 0))
- return AllocError;
- fs_handlers_installed++;
- }
- QueueFontWakeup(fpe);
- return Successful;
-}
-
-void
-remove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all)
-{
- if (all) {
- /* remove the handlers if no one else is using them */
- if (--fs_handlers_installed == 0) {
- RemoveBlockAndWakeupHandlers(block_handler, FontWakeup,
- (pointer) 0);
- }
- }
- RemoveFontWakeup(fpe);
-}
+/************************************************************************
+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.
+
+************************************************************************/
+/* The panoramix components contained the following notice */
+/*
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+
+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.
+
+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
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL 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 Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xmd.h>
+#include <X11/Xproto.h>
+#include "scrnintstr.h"
+#include "resource.h"
+#include "dixstruct.h"
+#include "cursorstr.h"
+#include "misc.h"
+#include "opaque.h"
+#include "dixfontstr.h"
+#include "closestr.h"
+#include "dixfont.h"
+#include "xace.h"
+
+#ifdef DEBUG
+#include <stdio.h>
+#endif
+
+#ifdef XF86BIGFONT
+#define _XF86BIGFONT_SERVER_
+#include <X11/extensions/xf86bigfont.h>
+#endif
+
+#define QUERYCHARINFO(pci, pr) *(pr) = (pci)->metrics
+
+extern pointer fosNaturalParams;
+extern FontPtr defaultFont;
+
+static FontPathElementPtr *font_path_elements = (FontPathElementPtr *) 0;
+static int num_fpes = 0;
+static FPEFunctions *fpe_functions = (FPEFunctions *) 0;
+static int num_fpe_types = 0;
+
+static unsigned char *font_path_string;
+
+static int num_slept_fpes = 0;
+static int size_slept_fpes = 0;
+static FontPathElementPtr *slept_fpes = (FontPathElementPtr *) 0;
+static FontPatternCachePtr patternCache;
+
+static int
+FontToXError(int err)
+{
+ switch (err) {
+ case Successful:
+ return Success;
+ case AllocError:
+ return BadAlloc;
+ case BadFontName:
+ return BadName;
+ case BadFontPath:
+ case BadFontFormat: /* is there something better? */
+ case BadCharRange:
+ return BadValue;
+ default:
+ return err;
+ }
+}
+
+static int
+LoadGlyphs(ClientPtr client, FontPtr pfont, unsigned nchars, int item_size,
+ unsigned char *data)
+{
+ if (fpe_functions[pfont->fpe->type].load_glyphs)
+ return (*fpe_functions[pfont->fpe->type].load_glyphs)
+ (client, pfont, 0, nchars, item_size, data);
+ else
+ return Successful;
+}
+
+/*
+ * adding RT_FONT prevents conflict with default cursor font
+ */
+Bool
+SetDefaultFont(char *defaultfontname)
+{
+ int err;
+ FontPtr pf;
+ XID fid;
+ static FontPtr last_pf;
+
+ fid = FakeClientID(0);
+ err = OpenFont(serverClient, fid, FontLoadAll | FontOpenSync,
+ (unsigned) strlen(defaultfontname), defaultfontname);
+ if (err != Success)
+ return FALSE;
+ err = dixLookupResourceByType((pointer *)&pf, fid, RT_FONT, serverClient,
+ DixReadAccess);
+ if (err == Success) last_pf = pf;
+ if (last_pf == (FontPtr) NULL)
+ return FALSE;
+ defaultFont = last_pf;
+ return TRUE;
+}
+
+/*
+ * note that the font wakeup queue is not refcounted. this is because
+ * an fpe needs to be added when it's inited, and removed when it's finally
+ * freed, in order to handle any data that isn't requested, like FS events.
+ *
+ * since the only thing that should call these routines is the renderer's
+ * init_fpe() and free_fpe(), there shouldn't be any problem in using
+ * freed data.
+ */
+void
+QueueFontWakeup(FontPathElementPtr fpe)
+{
+ int i;
+ FontPathElementPtr *new;
+
+ for (i = 0; i < num_slept_fpes; i++) {
+ if (slept_fpes[i] == fpe) {
+ return;
+ }
+ }
+ if (num_slept_fpes == size_slept_fpes) {
+ new = (FontPathElementPtr *)
+ xrealloc(slept_fpes,
+ sizeof(FontPathElementPtr) * (size_slept_fpes + 4));
+ if (!new)
+ return;
+ slept_fpes = new;
+ size_slept_fpes += 4;
+ }
+ slept_fpes[num_slept_fpes] = fpe;
+ num_slept_fpes++;
+}
+
+void
+RemoveFontWakeup(FontPathElementPtr fpe)
+{
+ int i,
+ j;
+
+ for (i = 0; i < num_slept_fpes; i++) {
+ if (slept_fpes[i] == fpe) {
+ for (j = i; j < num_slept_fpes; j++) {
+ slept_fpes[j] = slept_fpes[j + 1];
+ }
+ num_slept_fpes--;
+ return;
+ }
+ }
+}
+
+void
+FontWakeup(pointer data, int count, pointer LastSelectMask)
+{
+ int i;
+ FontPathElementPtr fpe;
+
+ if (count < 0)
+ return;
+ /* wake up any fpe's that may be waiting for information */
+ for (i = 0; i < num_slept_fpes; i++) {
+ fpe = slept_fpes[i];
+ (void) (*fpe_functions[fpe->type].wakeup_fpe) (fpe, LastSelectMask);
+ }
+}
+
+/* XXX -- these two funcs may want to be broken into macros */
+static void
+UseFPE(FontPathElementPtr fpe)
+{
+ fpe->refcount++;
+}
+
+static void
+FreeFPE (FontPathElementPtr fpe)
+{
+ fpe->refcount--;
+ if (fpe->refcount == 0) {
+ (*fpe_functions[fpe->type].free_fpe) (fpe);
+ xfree(fpe->name);
+ xfree(fpe);
+ }
+}
+
+static Bool
+doOpenFont(ClientPtr client, OFclosurePtr c)
+{
+ FontPtr pfont = NullFont;
+ FontPathElementPtr fpe = NULL;
+ ScreenPtr pScr;
+ int err = Successful;
+ int i;
+ char *alias,
+ *newname;
+ int newlen;
+ int aliascount = 20;
+ /*
+ * Decide at runtime what FontFormat to use.
+ */
+ Mask FontFormat =
+
+ ((screenInfo.imageByteOrder == LSBFirst) ?
+ BitmapFormatByteOrderLSB : BitmapFormatByteOrderMSB) |
+
+ ((screenInfo.bitmapBitOrder == LSBFirst) ?
+ BitmapFormatBitOrderLSB : BitmapFormatBitOrderMSB) |
+
+ BitmapFormatImageRectMin |
+
+#if GLYPHPADBYTES == 1
+ BitmapFormatScanlinePad8 |
+#endif
+
+#if GLYPHPADBYTES == 2
+ BitmapFormatScanlinePad16 |
+#endif
+
+#if GLYPHPADBYTES == 4
+ BitmapFormatScanlinePad32 |
+#endif
+
+#if GLYPHPADBYTES == 8
+ BitmapFormatScanlinePad64 |
+#endif
+
+ BitmapFormatScanlineUnit8;
+
+ if (client->clientGone)
+ {
+ if (c->current_fpe < c->num_fpes)
+ {
+ fpe = c->fpe_list[c->current_fpe];
+ (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
+ }
+ err = Successful;
+ goto bail;
+ }
+ while (c->current_fpe < c->num_fpes) {
+ fpe = c->fpe_list[c->current_fpe];
+ err = (*fpe_functions[fpe->type].open_font)
+ ((pointer) client, fpe, c->flags,
+ c->fontname, c->fnamelen, FontFormat,
+ BitmapFormatMaskByte |
+ BitmapFormatMaskBit |
+ BitmapFormatMaskImageRectangle |
+ BitmapFormatMaskScanLinePad |
+ BitmapFormatMaskScanLineUnit,
+ c->fontid, &pfont, &alias,
+ c->non_cachable_font && c->non_cachable_font->fpe == fpe ?
+ c->non_cachable_font :
+ (FontPtr)0);
+
+ if (err == FontNameAlias && alias) {
+ newlen = strlen(alias);
+ newname = (char *) xrealloc(c->fontname, newlen);
+ if (!newname) {
+ err = AllocError;
+ break;
+ }
+ memmove(newname, alias, newlen);
+ c->fontname = newname;
+ c->fnamelen = newlen;
+ c->current_fpe = 0;
+ if (--aliascount <= 0) {
+ /* We've tried resolving this alias 20 times, we're
+ * probably stuck in an infinite loop of aliases pointing
+ * to each other - time to take emergency exit!
+ */
+ err = BadImplementation;
+ break;
+ }
+ continue;
+ }
+ if (err == BadFontName) {
+ c->current_fpe++;
+ continue;
+ }
+ if (err == Suspended) {
+ if (!c->slept) {
+ c->slept = TRUE;
+ ClientSleep(client, (ClientSleepProcPtr)doOpenFont, (pointer) c);
+ }
+ return TRUE;
+ }
+ break;
+ }
+
+ if (err != Successful)
+ goto bail;
+ if (!pfont) {
+ err = BadFontName;
+ goto bail;
+ }
+ /* check values for firstCol, lastCol, firstRow, and lastRow */
+ if (pfont->info.firstCol > pfont->info.lastCol ||
+ pfont->info.firstRow > pfont->info.lastRow ||
+ pfont->info.lastCol - pfont->info.firstCol > 255) {
+ err = AllocError;
+ goto bail;
+ }
+ if (!pfont->fpe)
+ pfont->fpe = fpe;
+ pfont->refcnt++;
+ if (pfont->refcnt == 1) {
+ UseFPE(pfont->fpe);
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ pScr = screenInfo.screens[i];
+ if (pScr->RealizeFont)
+ {
+ if (!(*pScr->RealizeFont) (pScr, pfont))
+ {
+ CloseFont (pfont, (Font) 0);
+ err = AllocError;
+ goto bail;
+ }
+ }
+ }
+ }
+ if (!AddResource(c->fontid, RT_FONT, (pointer) pfont)) {
+ err = AllocError;
+ goto bail;
+ }
+ if (patternCache && pfont != c->non_cachable_font)
+ CacheFontPattern(patternCache, c->origFontName, c->origFontNameLen,
+ pfont);
+bail:
+ if (err != Successful && c->client != serverClient) {
+ SendErrorToClient(c->client, X_OpenFont, 0,
+ c->fontid, FontToXError(err));
+ }
+ if (c->slept)
+ ClientWakeup(c->client);
+ for (i = 0; i < c->num_fpes; i++) {
+ FreeFPE(c->fpe_list[i]);
+ }
+ xfree(c->fpe_list);
+ xfree(c->fontname);
+ xfree(c);
+ return TRUE;
+}
+
+int
+OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontname)
+{
+ OFclosurePtr c;
+ int i;
+ FontPtr cached = (FontPtr)0;
+
+#ifdef FONTDEBUG
+ char *f;
+ f = xalloc(lenfname + 1);
+ memmove(f, pfontname, lenfname);
+ f[lenfname] = '\0';
+ ErrorF("[dix] OpenFont: fontname is \"%s\"\n", f);
+ xfree(f);
+#endif
+ if (!lenfname || lenfname > XLFDMAXFONTNAMELEN)
+ return BadName;
+ if (patternCache)
+ {
+
+ /*
+ ** Check name cache. If we find a cached version of this font that
+ ** is cachable, immediately satisfy the request with it. If we find
+ ** a cached version of this font that is non-cachable, we do not
+ ** satisfy the request with it. Instead, we pass the FontPtr to the
+ ** FPE's open_font code (the fontfile FPE in turn passes the
+ ** information to the rasterizer; the fserve FPE ignores it).
+ **
+ ** Presumably, the font is marked non-cachable because the FPE has
+ ** put some licensing restrictions on it. If the FPE, using
+ ** whatever logic it relies on, determines that it is willing to
+ ** share this existing font with the client, then it has the option
+ ** to return the FontPtr we passed it as the newly-opened font.
+ ** This allows the FPE to exercise its licensing logic without
+ ** having to create another instance of a font that already exists.
+ */
+
+ cached = FindCachedFontPattern(patternCache, pfontname, lenfname);
+ if (cached && cached->info.cachable)
+ {
+ if (!AddResource(fid, RT_FONT, (pointer) cached))
+ return BadAlloc;
+ cached->refcnt++;
+ return Success;
+ }
+ }
+ c = xalloc(sizeof(OFclosureRec));
+ if (!c)
+ return BadAlloc;
+ c->fontname = xalloc(lenfname);
+ c->origFontName = pfontname;
+ c->origFontNameLen = lenfname;
+ if (!c->fontname) {
+ xfree(c);
+ return BadAlloc;
+ }
+ /*
+ * copy the current FPE list, so that if it gets changed by another client
+ * while we're blocking, the request still appears atomic
+ */
+ c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes);
+ if (!c->fpe_list) {
+ xfree(c->fontname);
+ xfree(c);
+ return BadAlloc;
+ }
+ memmove(c->fontname, pfontname, lenfname);
+ for (i = 0; i < num_fpes; i++) {
+ c->fpe_list[i] = font_path_elements[i];
+ UseFPE(c->fpe_list[i]);
+ }
+ c->client = client;
+ c->fontid = fid;
+ c->current_fpe = 0;
+ c->num_fpes = num_fpes;
+ c->fnamelen = lenfname;
+ c->slept = FALSE;
+ c->flags = flags;
+ c->non_cachable_font = cached;
+
+ (void) doOpenFont(client, c);
+ return Success;
+}
+
+/**
+ * Decrement font's ref count, and free storage if ref count equals zero
+ *
+ * \param value must conform to DeleteType
+ */
+int
+CloseFont(pointer value, XID fid)
+{
+ int nscr;
+ ScreenPtr pscr;
+ FontPathElementPtr fpe;
+ FontPtr pfont = (FontPtr)value;
+
+ if (pfont == NullFont)
+ return (Success);
+ if (--pfont->refcnt == 0) {
+ if (patternCache)
+ RemoveCachedFontPattern (patternCache, pfont);
+ /*
+ * since the last reference is gone, ask each screen to free any
+ * storage it may have allocated locally for it.
+ */
+ for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
+ pscr = screenInfo.screens[nscr];
+ if (pscr->UnrealizeFont)
+ (*pscr->UnrealizeFont) (pscr, pfont);
+ }
+ if (pfont == defaultFont)
+ defaultFont = NULL;
+#ifdef XF86BIGFONT
+ XF86BigfontFreeFontShm(pfont);
+#endif
+ fpe = pfont->fpe;
+ (*fpe_functions[fpe->type].close_font) (fpe, pfont);
+ FreeFPE(fpe);
+ }
+ return (Success);
+}
+
+
+/***====================================================================***/
+
+/**
+ * Sets up pReply as the correct QueryFontReply for pFont with the first
+ * nProtoCCIStructs char infos.
+ *
+ * \param pReply caller must allocate this storage
+ */
+void
+QueryFont(FontPtr pFont, xQueryFontReply *pReply, int nProtoCCIStructs)
+{
+ FontPropPtr pFP;
+ int r,
+ c,
+ i;
+ xFontProp *prFP;
+ xCharInfo *prCI;
+ xCharInfo *charInfos[256];
+ unsigned char chars[512];
+ int ninfos;
+ unsigned long ncols;
+ unsigned long count;
+
+ /* pr->length set in dispatch */
+ pReply->minCharOrByte2 = pFont->info.firstCol;
+ pReply->defaultChar = pFont->info.defaultCh;
+ pReply->maxCharOrByte2 = pFont->info.lastCol;
+ pReply->drawDirection = pFont->info.drawDirection;
+ pReply->allCharsExist = pFont->info.allExist;
+ pReply->minByte1 = pFont->info.firstRow;
+ pReply->maxByte1 = pFont->info.lastRow;
+ pReply->fontAscent = pFont->info.fontAscent;
+ pReply->fontDescent = pFont->info.fontDescent;
+
+ pReply->minBounds = pFont->info.ink_minbounds;
+ pReply->maxBounds = pFont->info.ink_maxbounds;
+
+ pReply->nFontProps = pFont->info.nprops;
+ pReply->nCharInfos = nProtoCCIStructs;
+
+ for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) (&pReply[1]);
+ i < pFont->info.nprops;
+ i++, pFP++, prFP++) {
+ prFP->name = pFP->name;
+ prFP->value = pFP->value;
+ }
+
+ ninfos = 0;
+ ncols = (unsigned long) (pFont->info.lastCol - pFont->info.firstCol + 1);
+ prCI = (xCharInfo *) (prFP);
+ for (r = pFont->info.firstRow;
+ ninfos < nProtoCCIStructs && r <= (int)pFont->info.lastRow;
+ r++) {
+ i = 0;
+ for (c = pFont->info.firstCol; c <= (int)pFont->info.lastCol; c++) {
+ chars[i++] = r;
+ chars[i++] = c;
+ }
+ (*pFont->get_metrics) (pFont, ncols, chars,
+ TwoD16Bit, &count, charInfos);
+ i = 0;
+ for (i = 0; i < (int) count && ninfos < nProtoCCIStructs; i++) {
+ *prCI = *charInfos[i];
+ prCI++;
+ ninfos++;
+ }
+ }
+ return;
+}
+
+static Bool
+doListFontsAndAliases(ClientPtr client, LFclosurePtr c)
+{
+ FontPathElementPtr fpe;
+ int err = Successful;
+ FontNamesPtr names = NULL;
+ char *name, *resolved=NULL;
+ int namelen, resolvedlen;
+ int nnames;
+ int stringLens;
+ int i;
+ xListFontsReply reply;
+ char *bufptr;
+ char *bufferStart;
+ int aliascount = 0;
+
+ if (client->clientGone)
+ {
+ if (c->current.current_fpe < c->num_fpes)
+ {
+ fpe = c->fpe_list[c->current.current_fpe];
+ (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
+ }
+ err = Successful;
+ goto bail;
+ }
+
+ if (!c->current.patlen)
+ goto finish;
+
+ while (c->current.current_fpe < c->num_fpes) {
+ fpe = c->fpe_list[c->current.current_fpe];
+ err = Successful;
+
+ if (!fpe_functions[fpe->type].start_list_fonts_and_aliases)
+ {
+ /* This FPE doesn't support/require list_fonts_and_aliases */
+
+ err = (*fpe_functions[fpe->type].list_fonts)
+ ((pointer) c->client, fpe, c->current.pattern,
+ c->current.patlen, c->current.max_names - c->names->nnames,
+ c->names);
+
+ if (err == Suspended) {
+ if (!c->slept) {
+ c->slept = TRUE;
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsAndAliases,
+ (pointer) c);
+ }
+ return TRUE;
+ }
+
+ err = BadFontName;
+ }
+ else
+ {
+ /* Start of list_fonts_and_aliases functionality. Modeled
+ after list_fonts_with_info in that it resolves aliases,
+ except that the information collected from FPEs is just
+ names, not font info. Each list_next_font_or_alias()
+ returns either a name into name/namelen or an alias into
+ name/namelen and its target name into resolved/resolvedlen.
+ The code at this level then resolves the alias by polling
+ the FPEs. */
+
+ if (!c->current.list_started) {
+ err = (*fpe_functions[fpe->type].start_list_fonts_and_aliases)
+ ((pointer) c->client, fpe, c->current.pattern,
+ c->current.patlen, c->current.max_names - c->names->nnames,
+ &c->current.private);
+ if (err == Suspended) {
+ if (!c->slept) {
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsAndAliases,
+ (pointer) c);
+ c->slept = TRUE;
+ }
+ return TRUE;
+ }
+ if (err == Successful)
+ c->current.list_started = TRUE;
+ }
+ if (err == Successful) {
+ char *tmpname;
+ name = 0;
+ err = (*fpe_functions[fpe->type].list_next_font_or_alias)
+ ((pointer) c->client, fpe, &name, &namelen, &tmpname,
+ &resolvedlen, c->current.private);
+ if (err == Suspended) {
+ if (!c->slept) {
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsAndAliases,
+ (pointer) c);
+ c->slept = TRUE;
+ }
+ return TRUE;
+ }
+ if (err == FontNameAlias) {
+ if (resolved) xfree(resolved);
+ resolved = xalloc(resolvedlen + 1);
+ if (resolved)
+ memmove(resolved, tmpname, resolvedlen + 1);
+ }
+ }
+
+ if (err == Successful)
+ {
+ if (c->haveSaved)
+ {
+ if (c->savedName)
+ (void)AddFontNamesName(c->names, c->savedName,
+ c->savedNameLen);
+ }
+ else
+ (void)AddFontNamesName(c->names, name, namelen);
+ }
+
+ /*
+ * When we get an alias back, save our state and reset back to
+ * the start of the FPE looking for the specified name. As
+ * soon as a real font is found for the alias, pop back to the
+ * old state
+ */
+ else if (err == FontNameAlias) {
+ char tmp_pattern[XLFDMAXFONTNAMELEN];
+ /*
+ * when an alias recurses, we need to give
+ * the last FPE a chance to clean up; so we call
+ * it again, and assume that the error returned
+ * is BadFontName, indicating the alias resolution
+ * is complete.
+ */
+ memmove(tmp_pattern, resolved, resolvedlen);
+ if (c->haveSaved)
+ {
+ char *tmpname;
+ int tmpnamelen;
+
+ tmpname = 0;
+ (void) (*fpe_functions[fpe->type].list_next_font_or_alias)
+ ((pointer) c->client, fpe, &tmpname, &tmpnamelen,
+ &tmpname, &tmpnamelen, c->current.private);
+ if (--aliascount <= 0)
+ {
+ err = BadFontName;
+ goto ContBadFontName;
+ }
+ }
+ else
+ {
+ c->saved = c->current;
+ c->haveSaved = TRUE;
+ if (c->savedName)
+ xfree(c->savedName);
+ c->savedName = xalloc(namelen + 1);
+ if (c->savedName)
+ memmove(c->savedName, name, namelen + 1);
+ c->savedNameLen = namelen;
+ aliascount = 20;
+ }
+ memmove(c->current.pattern, tmp_pattern, resolvedlen);
+ c->current.patlen = resolvedlen;
+ c->current.max_names = c->names->nnames + 1;
+ c->current.current_fpe = -1;
+ c->current.private = 0;
+ err = BadFontName;
+ }
+ }
+ /*
+ * At the end of this FPE, step to the next. If we've finished
+ * processing an alias, pop state back. If we've collected enough
+ * font names, quit.
+ */
+ if (err == BadFontName) {
+ ContBadFontName: ;
+ c->current.list_started = FALSE;
+ c->current.current_fpe++;
+ err = Successful;
+ if (c->haveSaved)
+ {
+ if (c->names->nnames == c->current.max_names ||
+ c->current.current_fpe == c->num_fpes) {
+ c->haveSaved = FALSE;
+ c->current = c->saved;
+ /* Give the saved namelist a chance to clean itself up */
+ continue;
+ }
+ }
+ if (c->names->nnames == c->current.max_names)
+ break;
+ }
+ }
+
+ /*
+ * send the reply
+ */
+ if (err != Successful) {
+ SendErrorToClient(client, X_ListFonts, 0, 0, FontToXError(err));
+ goto bail;
+ }
+
+finish:
+
+ names = c->names;
+ nnames = names->nnames;
+ client = c->client;
+ stringLens = 0;
+ for (i = 0; i < nnames; i++)
+ stringLens += (names->length[i] <= 255) ? names->length[i] : 0;
+
+ memset(&reply, 0, sizeof(xListFontsReply));
+ reply.type = X_Reply;
+ reply.length = bytes_to_int32(stringLens + nnames);
+ reply.nFonts = nnames;
+ reply.sequenceNumber = client->sequence;
+
+ bufptr = bufferStart = xalloc(reply.length << 2);
+
+ if (!bufptr && reply.length) {
+ SendErrorToClient(client, X_ListFonts, 0, 0, BadAlloc);
+ goto bail;
+ }
+ /*
+ * since WriteToClient long word aligns things, copy to temp buffer and
+ * write all at once
+ */
+ for (i = 0; i < nnames; i++) {
+ if (names->length[i] > 255)
+ reply.nFonts--;
+ else
+ {
+ *bufptr++ = names->length[i];
+ memmove( bufptr, names->names[i], names->length[i]);
+ bufptr += names->length[i];
+ }
+ }
+ nnames = reply.nFonts;
+ reply.length = bytes_to_int32(stringLens + nnames);
+ client->pSwapReplyFunc = ReplySwapVector[X_ListFonts];
+ WriteSwappedDataToClient(client, sizeof(xListFontsReply), &reply);
+ (void) WriteToClient(client, stringLens + nnames, bufferStart);
+ xfree(bufferStart);
+
+bail:
+ if (c->slept)
+ ClientWakeup(client);
+ for (i = 0; i < c->num_fpes; i++)
+ FreeFPE(c->fpe_list[i]);
+ xfree(c->fpe_list);
+ if (c->savedName) xfree(c->savedName);
+ FreeFontNames(names);
+ xfree(c);
+ if (resolved) xfree(resolved);
+ return TRUE;
+}
+
+int
+ListFonts(ClientPtr client, unsigned char *pattern, unsigned length,
+ unsigned max_names)
+{
+ int i;
+ LFclosurePtr c;
+
+ /*
+ * The right error to return here would be BadName, however the
+ * specification does not allow for a Name error on this request.
+ * Perhaps a better solution would be to return a nil list, i.e.
+ * a list containing zero fontnames.
+ */
+ if (length > XLFDMAXFONTNAMELEN)
+ return BadAlloc;
+
+ i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
+ if (i != Success)
+ return i;
+
+ if (!(c = xalloc(sizeof *c)))
+ return BadAlloc;
+ c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes);
+ if (!c->fpe_list) {
+ xfree(c);
+ return BadAlloc;
+ }
+ c->names = MakeFontNamesRecord(max_names < 100 ? max_names : 100);
+ if (!c->names)
+ {
+ xfree(c->fpe_list);
+ xfree(c);
+ return BadAlloc;
+ }
+ memmove( c->current.pattern, pattern, length);
+ for (i = 0; i < num_fpes; i++) {
+ c->fpe_list[i] = font_path_elements[i];
+ UseFPE(c->fpe_list[i]);
+ }
+ c->client = client;
+ c->num_fpes = num_fpes;
+ c->current.patlen = length;
+ c->current.current_fpe = 0;
+ c->current.max_names = max_names;
+ c->current.list_started = FALSE;
+ c->current.private = 0;
+ c->haveSaved = FALSE;
+ c->slept = FALSE;
+ c->savedName = 0;
+ doListFontsAndAliases(client, c);
+ return Success;
+}
+
+int
+doListFontsWithInfo(ClientPtr client, LFWIclosurePtr c)
+{
+ FontPathElementPtr fpe;
+ int err = Successful;
+ char *name;
+ int namelen;
+ int numFonts;
+ FontInfoRec fontInfo,
+ *pFontInfo;
+ xListFontsWithInfoReply *reply;
+ int length;
+ xFontProp *pFP;
+ int i;
+ int aliascount = 0;
+ xListFontsWithInfoReply finalReply;
+
+ if (client->clientGone)
+ {
+ if (c->current.current_fpe < c->num_fpes)
+ {
+ fpe = c->fpe_list[c->current.current_fpe];
+ (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
+ }
+ err = Successful;
+ goto bail;
+ }
+ client->pSwapReplyFunc = ReplySwapVector[X_ListFontsWithInfo];
+ if (!c->current.patlen)
+ goto finish;
+ while (c->current.current_fpe < c->num_fpes)
+ {
+ fpe = c->fpe_list[c->current.current_fpe];
+ err = Successful;
+ if (!c->current.list_started)
+ {
+ err = (*fpe_functions[fpe->type].start_list_fonts_with_info)
+ (client, fpe, c->current.pattern, c->current.patlen,
+ c->current.max_names, &c->current.private);
+ if (err == Suspended)
+ {
+ if (!c->slept)
+ {
+ ClientSleep(client, (ClientSleepProcPtr)doListFontsWithInfo, c);
+ c->slept = TRUE;
+ }
+ return TRUE;
+ }
+ if (err == Successful)
+ c->current.list_started = TRUE;
+ }
+ if (err == Successful)
+ {
+ name = 0;
+ pFontInfo = &fontInfo;
+ err = (*fpe_functions[fpe->type].list_next_font_with_info)
+ (client, fpe, &name, &namelen, &pFontInfo,
+ &numFonts, c->current.private);
+ if (err == Suspended)
+ {
+ if (!c->slept)
+ {
+ ClientSleep(client,
+ (ClientSleepProcPtr)doListFontsWithInfo,
+ c);
+ c->slept = TRUE;
+ }
+ return TRUE;
+ }
+ }
+ /*
+ * When we get an alias back, save our state and reset back to the
+ * start of the FPE looking for the specified name. As soon as a real
+ * font is found for the alias, pop back to the old state
+ */
+ if (err == FontNameAlias)
+ {
+ /*
+ * when an alias recurses, we need to give
+ * the last FPE a chance to clean up; so we call
+ * it again, and assume that the error returned
+ * is BadFontName, indicating the alias resolution
+ * is complete.
+ */
+ if (c->haveSaved)
+ {
+ char *tmpname;
+ int tmpnamelen;
+ FontInfoPtr tmpFontInfo;
+
+ tmpname = 0;
+ tmpFontInfo = &fontInfo;
+ (void) (*fpe_functions[fpe->type].list_next_font_with_info)
+ (client, fpe, &tmpname, &tmpnamelen, &tmpFontInfo,
+ &numFonts, c->current.private);
+ if (--aliascount <= 0)
+ {
+ err = BadFontName;
+ goto ContBadFontName;
+ }
+ }
+ else
+ {
+ c->saved = c->current;
+ c->haveSaved = TRUE;
+ c->savedNumFonts = numFonts;
+ if (c->savedName)
+ xfree(c->savedName);
+ c->savedName = xalloc(namelen + 1);
+ if (c->savedName)
+ memmove(c->savedName, name, namelen + 1);
+ aliascount = 20;
+ }
+ memmove(c->current.pattern, name, namelen);
+ c->current.patlen = namelen;
+ c->current.max_names = 1;
+ c->current.current_fpe = 0;
+ c->current.private = 0;
+ c->current.list_started = FALSE;
+ }
+ /*
+ * At the end of this FPE, step to the next. If we've finished
+ * processing an alias, pop state back. If we've sent enough font
+ * names, quit. Always wait for BadFontName to let the FPE
+ * have a chance to clean up.
+ */
+ else if (err == BadFontName)
+ {
+ ContBadFontName: ;
+ c->current.list_started = FALSE;
+ c->current.current_fpe++;
+ err = Successful;
+ if (c->haveSaved)
+ {
+ if (c->current.max_names == 0 ||
+ c->current.current_fpe == c->num_fpes)
+ {
+ c->haveSaved = FALSE;
+ c->saved.max_names -= (1 - c->current.max_names);
+ c->current = c->saved;
+ }
+ }
+ else if (c->current.max_names == 0)
+ break;
+ }
+ else if (err == Successful)
+ {
+ length = sizeof(*reply) + pFontInfo->nprops * sizeof(xFontProp);
+ reply = c->reply;
+ if (c->length < length)
+ {
+ reply = (xListFontsWithInfoReply *) xrealloc(c->reply, length);
+ if (!reply)
+ {
+ err = AllocError;
+ break;
+ }
+ memset((char*)reply + c->length, 0, length - c->length);
+ c->reply = reply;
+ c->length = length;
+ }
+ if (c->haveSaved)
+ {
+ numFonts = c->savedNumFonts;
+ name = c->savedName;
+ namelen = strlen(name);
+ }
+ reply->type = X_Reply;
+ reply->length = bytes_to_int32(sizeof *reply - sizeof(xGenericReply) +
+ pFontInfo->nprops * sizeof(xFontProp) +
+ namelen);
+ reply->sequenceNumber = client->sequence;
+ reply->nameLength = namelen;
+ reply->minBounds = pFontInfo->ink_minbounds;
+ reply->maxBounds = pFontInfo->ink_maxbounds;
+ reply->minCharOrByte2 = pFontInfo->firstCol;
+ reply->maxCharOrByte2 = pFontInfo->lastCol;
+ reply->defaultChar = pFontInfo->defaultCh;
+ reply->nFontProps = pFontInfo->nprops;
+ reply->drawDirection = pFontInfo->drawDirection;
+ reply->minByte1 = pFontInfo->firstRow;
+ reply->maxByte1 = pFontInfo->lastRow;
+ reply->allCharsExist = pFontInfo->allExist;
+ reply->fontAscent = pFontInfo->fontAscent;
+ reply->fontDescent = pFontInfo->fontDescent;
+ reply->nReplies = numFonts;
+ pFP = (xFontProp *) (reply + 1);
+ for (i = 0; i < pFontInfo->nprops; i++)
+ {
+ pFP->name = pFontInfo->props[i].name;
+ pFP->value = pFontInfo->props[i].value;
+ pFP++;
+ }
+ WriteSwappedDataToClient(client, length, reply);
+ (void) WriteToClient(client, namelen, name);
+ if (pFontInfo == &fontInfo)
+ {
+ xfree(fontInfo.props);
+ xfree(fontInfo.isStringProp);
+ }
+ --c->current.max_names;
+ }
+ }
+finish:
+ length = sizeof(xListFontsWithInfoReply);
+ bzero((char *) &finalReply, sizeof(xListFontsWithInfoReply));
+ finalReply.type = X_Reply;
+ finalReply.sequenceNumber = client->sequence;
+ finalReply.length = bytes_to_int32(sizeof(xListFontsWithInfoReply)
+ - sizeof(xGenericReply));
+ WriteSwappedDataToClient(client, length, &finalReply);
+bail:
+ if (c->slept)
+ ClientWakeup(client);
+ for (i = 0; i < c->num_fpes; i++)
+ FreeFPE(c->fpe_list[i]);
+ xfree(c->reply);
+ xfree(c->fpe_list);
+ if (c->savedName) xfree(c->savedName);
+ xfree(c);
+ return TRUE;
+}
+
+int
+StartListFontsWithInfo(ClientPtr client, int length, unsigned char *pattern,
+ int max_names)
+{
+ int i;
+ LFWIclosurePtr c;
+
+ /*
+ * The right error to return here would be BadName, however the
+ * specification does not allow for a Name error on this request.
+ * Perhaps a better solution would be to return a nil list, i.e.
+ * a list containing zero fontnames.
+ */
+ if (length > XLFDMAXFONTNAMELEN)
+ return BadAlloc;
+
+ i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
+ if (i != Success)
+ return i;
+
+ if (!(c = xalloc(sizeof *c)))
+ goto badAlloc;
+ c->fpe_list = xalloc(sizeof(FontPathElementPtr) * num_fpes);
+ if (!c->fpe_list)
+ {
+ xfree(c);
+ goto badAlloc;
+ }
+ memmove(c->current.pattern, pattern, length);
+ for (i = 0; i < num_fpes; i++)
+ {
+ c->fpe_list[i] = font_path_elements[i];
+ UseFPE(c->fpe_list[i]);
+ }
+ c->client = client;
+ c->num_fpes = num_fpes;
+ c->reply = 0;
+ c->length = 0;
+ c->current.patlen = length;
+ c->current.current_fpe = 0;
+ c->current.max_names = max_names;
+ c->current.list_started = FALSE;
+ c->current.private = 0;
+ c->savedNumFonts = 0;
+ c->haveSaved = FALSE;
+ c->slept = FALSE;
+ c->savedName = 0;
+ doListFontsWithInfo(client, c);
+ return Success;
+badAlloc:
+ return BadAlloc;
+}
+
+#define TextEltHeader 2
+#define FontShiftSize 5
+static XID clearGC[] = { CT_NONE };
+#define clearGCmask (GCClipMask)
+
+int
+doPolyText(ClientPtr client, PTclosurePtr c)
+{
+ FontPtr pFont = c->pGC->font, oldpFont;
+ Font fid, oldfid;
+ int err = Success, lgerr; /* err is in X error, not font error, space */
+ enum { NEVER_SLEPT, START_SLEEP, SLEEPING } client_state = NEVER_SLEPT;
+ FontPathElementPtr fpe;
+ GC *origGC = NULL;
+
+ if (client->clientGone)
+ {
+ fpe = c->pGC->font->fpe;
+ (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
+
+ if (c->slept)
+ {
+ /* Client has died, but we cannot bail out right now. We
+ need to clean up after the work we did when going to
+ sleep. Setting the drawable pointer to 0 makes this
+ happen without any attempts to render or perform other
+ unnecessary activities. */
+ c->pDraw = (DrawablePtr)0;
+ }
+ else
+ {
+ err = Success;
+ goto bail;
+ }
+ }
+
+ /* Make sure our drawable hasn't disappeared while we slept. */
+ if (c->slept && c->pDraw)
+ {
+ DrawablePtr pDraw;
+ dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
+ if (c->pDraw != pDraw) {
+ /* Our drawable has disappeared. Treat like client died... ask
+ the FPE code to clean up after client and avoid further
+ rendering while we clean up after ourself. */
+ fpe = c->pGC->font->fpe;
+ (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
+ c->pDraw = (DrawablePtr)0;
+ }
+ }
+
+ client_state = c->slept ? SLEEPING : NEVER_SLEPT;
+
+ while (c->endReq - c->pElt > TextEltHeader)
+ {
+ if (*c->pElt == FontChange)
+ {
+ if (c->endReq - c->pElt < FontShiftSize)
+ {
+ err = BadLength;
+ goto bail;
+ }
+
+ oldpFont = pFont;
+ oldfid = fid;
+
+ fid = ((Font)*(c->pElt+4)) /* big-endian */
+ | ((Font)*(c->pElt+3)) << 8
+ | ((Font)*(c->pElt+2)) << 16
+ | ((Font)*(c->pElt+1)) << 24;
+ err = dixLookupResourceByType((pointer *)&pFont, fid, RT_FONT,
+ client, DixReadAccess);
+ if (err != Success)
+ {
+ err = (err == BadValue) ? BadFont : err;
+ /* restore pFont and fid for step 4 (described below) */
+ pFont = oldpFont;
+ fid = oldfid;
+
+ /* If we're in START_SLEEP mode, the following step
+ shortens the request... in the unlikely event that
+ the fid somehow becomes valid before we come through
+ again to actually execute the polytext, which would
+ then mess up our refcounting scheme badly. */
+ c->err = err;
+ c->endReq = c->pElt;
+
+ goto bail;
+ }
+
+ /* Step 3 (described below) on our new font */
+ if (client_state == START_SLEEP)
+ pFont->refcnt++;
+ else
+ {
+ if (pFont != c->pGC->font && c->pDraw)
+ {
+ ChangeGC( c->pGC, GCFont, &fid);
+ ValidateGC(c->pDraw, c->pGC);
+ if (c->reqType == X_PolyText8)
+ c->polyText = (PolyTextPtr) c->pGC->ops->PolyText8;
+ else
+ c->polyText = (PolyTextPtr) c->pGC->ops->PolyText16;
+ }
+
+ /* Undo the refcnt++ we performed when going to sleep */
+ if (client_state == SLEEPING)
+ (void)CloseFont(c->pGC->font, (Font)0);
+ }
+ c->pElt += FontShiftSize;
+ }
+ else /* print a string */
+ {
+ unsigned char *pNextElt;
+ pNextElt = c->pElt + TextEltHeader + (*c->pElt)*c->itemSize;
+ if ( pNextElt > c->endReq)
+ {
+ err = BadLength;
+ goto bail;
+ }
+ if (client_state == START_SLEEP)
+ {
+ c->pElt = pNextElt;
+ continue;
+ }
+ if (c->pDraw)
+ {
+ lgerr = LoadGlyphs(client, c->pGC->font, *c->pElt, c->itemSize,
+ c->pElt + TextEltHeader);
+ }
+ else lgerr = Successful;
+
+ if (lgerr == Suspended)
+ {
+ if (!c->slept) {
+ int len;
+ GC *pGC;
+ PTclosurePtr new_closure;
+
+ /* We're putting the client to sleep. We need to do a few things
+ to ensure successful and atomic-appearing execution of the
+ remainder of the request. First, copy the remainder of the
+ request into a safe malloc'd area. Second, create a scratch GC
+ to use for the remainder of the request. Third, mark all fonts
+ referenced in the remainder of the request to prevent their
+ deallocation. Fourth, make the original GC look like the
+ request has completed... set its font to the final font value
+ from this request. These GC manipulations are for the unlikely
+ (but possible) event that some other client is using the GC.
+ Steps 3 and 4 are performed by running this procedure through
+ the remainder of the request in a special no-render mode
+ indicated by client_state = START_SLEEP. */
+
+ /* Step 1 */
+ /* Allocate a malloc'd closure structure to replace
+ the local one we were passed */
+ new_closure = xalloc(sizeof(PTclosureRec));
+ if (!new_closure)
+ {
+ err = BadAlloc;
+ goto bail;
+ }
+ *new_closure = *c;
+ c = new_closure;
+
+ len = c->endReq - c->pElt;
+ c->data = xalloc(len);
+ if (!c->data)
+ {
+ xfree(c);
+ err = BadAlloc;
+ goto bail;
+ }
+ memmove(c->data, c->pElt, len);
+ c->pElt = c->data;
+ c->endReq = c->pElt + len;
+
+ /* Step 2 */
+
+ pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
+ if (!pGC)
+ {
+ xfree(c->data);
+ xfree(c);
+ err = BadAlloc;
+ goto bail;
+ }
+ if ((err = CopyGC(c->pGC, pGC, GCFunction |
+ GCPlaneMask | GCForeground |
+ GCBackground | GCFillStyle |
+ GCTile | GCStipple |
+ GCTileStipXOrigin |
+ GCTileStipYOrigin | GCFont |
+ GCSubwindowMode | GCClipXOrigin |
+ GCClipYOrigin | GCClipMask)) !=
+ Success)
+ {
+ FreeScratchGC(pGC);
+ xfree(c->data);
+ xfree(c);
+ err = BadAlloc;
+ goto bail;
+ }
+ origGC = c->pGC;
+ c->pGC = pGC;
+ ValidateGC(c->pDraw, c->pGC);
+
+ c->slept = TRUE;
+ ClientSleep(client,
+ (ClientSleepProcPtr)doPolyText,
+ (pointer) c);
+
+ /* Set up to perform steps 3 and 4 */
+ client_state = START_SLEEP;
+ continue; /* on to steps 3 and 4 */
+ }
+ return TRUE;
+ }
+ else if (lgerr != Successful)
+ {
+ err = FontToXError(lgerr);
+ goto bail;
+ }
+ if (c->pDraw)
+ {
+ c->xorg += *((INT8 *)(c->pElt + 1)); /* must be signed */
+ c->xorg = (* c->polyText)(c->pDraw, c->pGC, c->xorg, c->yorg,
+ *c->pElt, c->pElt + TextEltHeader);
+ }
+ c->pElt = pNextElt;
+ }
+ }
+
+bail:
+
+ if (client_state == START_SLEEP)
+ {
+ /* Step 4 */
+ if (pFont != origGC->font)
+ {
+ ChangeGC(origGC, GCFont, &fid);
+ ValidateGC(c->pDraw, origGC);
+ }
+
+ /* restore pElt pointer for execution of remainder of the request */
+ c->pElt = c->data;
+ return TRUE;
+ }
+
+ if (c->err != Success) err = c->err;
+ if (err != Success && c->client != serverClient) {
+#ifdef PANORAMIX
+ if (noPanoramiXExtension || !c->pGC->pScreen->myNum)
+#endif
+ SendErrorToClient(c->client, c->reqType, 0, 0, err);
+ }
+ if (c->slept)
+ {
+ ClientWakeup(c->client);
+ ChangeGC(c->pGC, clearGCmask, clearGC);
+
+ /* Unreference the font from the scratch GC */
+ CloseFont(c->pGC->font, (Font)0);
+ c->pGC->font = NullFont;
+
+ FreeScratchGC(c->pGC);
+ xfree(c->data);
+ xfree(c);
+ }
+ return TRUE;
+}
+
+int
+PolyText(ClientPtr client, DrawablePtr pDraw, GC *pGC, unsigned char *pElt,
+ unsigned char *endReq, int xorg, int yorg, int reqType, XID did)
+{
+ PTclosureRec local_closure;
+
+ local_closure.pElt = pElt;
+ local_closure.endReq = endReq;
+ local_closure.client = client;
+ local_closure.pDraw = pDraw;
+ local_closure.xorg = xorg;
+ local_closure.yorg = yorg;
+ if ((local_closure.reqType = reqType) == X_PolyText8)
+ {
+ local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText8;
+ local_closure.itemSize = 1;
+ }
+ else
+ {
+ local_closure.polyText = (PolyTextPtr) pGC->ops->PolyText16;
+ local_closure.itemSize = 2;
+ }
+ local_closure.pGC = pGC;
+ local_closure.did = did;
+ local_closure.err = Success;
+ local_closure.slept = FALSE;
+
+ (void) doPolyText(client, &local_closure);
+ return Success;
+}
+
+
+#undef TextEltHeader
+#undef FontShiftSize
+
+int
+doImageText(ClientPtr client, ITclosurePtr c)
+{
+ int err = Success, lgerr; /* err is in X error, not font error, space */
+ FontPathElementPtr fpe;
+
+ if (client->clientGone)
+ {
+ fpe = c->pGC->font->fpe;
+ (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
+ err = Success;
+ goto bail;
+ }
+
+ /* Make sure our drawable hasn't disappeared while we slept. */
+ if (c->slept && c->pDraw)
+ {
+ DrawablePtr pDraw;
+ dixLookupDrawable(&pDraw, c->did, client, 0, DixWriteAccess);
+ if (c->pDraw != pDraw) {
+ /* Our drawable has disappeared. Treat like client died... ask
+ the FPE code to clean up after client. */
+ fpe = c->pGC->font->fpe;
+ (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
+ err = Success;
+ goto bail;
+ }
+ }
+
+ lgerr = LoadGlyphs(client, c->pGC->font, c->nChars, c->itemSize, c->data);
+ if (lgerr == Suspended)
+ {
+ if (!c->slept) {
+ GC *pGC;
+ unsigned char *data;
+ ITclosurePtr new_closure;
+
+ /* We're putting the client to sleep. We need to
+ save some state. Similar problem to that handled
+ in doPolyText, but much simpler because the
+ request structure is much simpler. */
+
+ new_closure = xalloc(sizeof(ITclosureRec));
+ if (!new_closure)
+ {
+ err = BadAlloc;
+ goto bail;
+ }
+ *new_closure = *c;
+ c = new_closure;
+
+ data = xalloc(c->nChars * c->itemSize);
+ if (!data)
+ {
+ xfree(c);
+ err = BadAlloc;
+ goto bail;
+ }
+ memmove(data, c->data, c->nChars * c->itemSize);
+ c->data = data;
+
+ pGC = GetScratchGC(c->pGC->depth, c->pGC->pScreen);
+ if (!pGC)
+ {
+ xfree(c->data);
+ xfree(c);
+ err = BadAlloc;
+ goto bail;
+ }
+ if ((err = CopyGC(c->pGC, pGC, GCFunction | GCPlaneMask |
+ GCForeground | GCBackground | GCFillStyle |
+ GCTile | GCStipple | GCTileStipXOrigin |
+ GCTileStipYOrigin | GCFont |
+ GCSubwindowMode | GCClipXOrigin |
+ GCClipYOrigin | GCClipMask)) != Success)
+ {
+ FreeScratchGC(pGC);
+ xfree(c->data);
+ xfree(c);
+ err = BadAlloc;
+ goto bail;
+ }
+ c->pGC = pGC;
+ ValidateGC(c->pDraw, c->pGC);
+
+ c->slept = TRUE;
+ ClientSleep(client, (ClientSleepProcPtr)doImageText, (pointer) c);
+ }
+ return TRUE;
+ }
+ else if (lgerr != Successful)
+ {
+ err = FontToXError(lgerr);
+ goto bail;
+ }
+ if (c->pDraw)
+ {
+ (* c->imageText)(c->pDraw, c->pGC, c->xorg, c->yorg,
+ c->nChars, c->data);
+ }
+
+bail:
+
+ if (err != Success && c->client != serverClient) {
+ SendErrorToClient(c->client, c->reqType, 0, 0, err);
+ }
+ if (c->slept)
+ {
+ ClientWakeup(c->client);
+ ChangeGC(c->pGC, clearGCmask, clearGC);
+
+ /* Unreference the font from the scratch GC */
+ CloseFont(c->pGC->font, (Font)0);
+ c->pGC->font = NullFont;
+
+ FreeScratchGC(c->pGC);
+ xfree(c->data);
+ xfree(c);
+ }
+ return TRUE;
+}
+
+int
+ImageText(ClientPtr client, DrawablePtr pDraw, GC *pGC, int nChars,
+ unsigned char *data, int xorg, int yorg, int reqType, XID did)
+{
+ ITclosureRec local_closure;
+
+ local_closure.client = client;
+ local_closure.pDraw = pDraw;
+ local_closure.pGC = pGC;
+ local_closure.nChars = nChars;
+ local_closure.data = data;
+ local_closure.xorg = xorg;
+ local_closure.yorg = yorg;
+ if ((local_closure.reqType = reqType) == X_ImageText8)
+ {
+ local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText8;
+ local_closure.itemSize = 1;
+ }
+ else
+ {
+ local_closure.imageText = (ImageTextPtr) pGC->ops->ImageText16;
+ local_closure.itemSize = 2;
+ }
+ local_closure.did = did;
+ local_closure.slept = FALSE;
+
+ (void) doImageText(client, &local_closure);
+ return Success;
+}
+
+
+/* does the necessary magic to figure out the fpe type */
+static int
+DetermineFPEType(char *pathname)
+{
+ int i;
+
+ for (i = 0; i < num_fpe_types; i++) {
+ if ((*fpe_functions[i].name_check) (pathname))
+ return i;
+ }
+ return -1;
+}
+
+
+static void
+FreeFontPath(FontPathElementPtr *list, int n, Bool force)
+{
+ int i;
+
+ for (i = 0; i < n; i++) {
+ if (force) {
+ /* Sanity check that all refcounts will be 0 by the time
+ we get to the end of the list. */
+ int found = 1; /* the first reference is us */
+ int j;
+ for (j = i+1; j < n; j++) {
+ if (list[j] == list[i])
+ found++;
+ }
+ if (list[i]->refcount != found) {
+ list[i]->refcount = found; /* ensure it will get freed */
+ }
+ }
+ FreeFPE(list[i]);
+ }
+ xfree(list);
+}
+
+static FontPathElementPtr
+find_existing_fpe(FontPathElementPtr *list, int num, unsigned char *name, int len)
+{
+ FontPathElementPtr fpe;
+ int i;
+
+ for (i = 0; i < num; i++) {
+ fpe = list[i];
+ if (fpe->name_length == len && memcmp(name, fpe->name, len) == 0)
+ return fpe;
+ }
+ return (FontPathElementPtr) 0;
+}
+
+
+static int
+SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist)
+{
+ int i, err = 0;
+ int valid_paths = 0;
+ unsigned int len;
+ unsigned char *cp = paths;
+ FontPathElementPtr fpe = NULL, *fplist;
+
+ fplist = xalloc(sizeof(FontPathElementPtr) * npaths);
+ if (!fplist) {
+ *bad = 0;
+ return BadAlloc;
+ }
+ for (i = 0; i < num_fpe_types; i++) {
+ if (fpe_functions[i].set_path_hook)
+ (*fpe_functions[i].set_path_hook) ();
+ }
+ for (i = 0; i < npaths; i++)
+ {
+ len = (unsigned int) (*cp++);
+
+ if (len == 0)
+ {
+ if (persist)
+ ErrorF("[dix] Removing empty element from the valid list of fontpaths\n");
+ err = BadValue;
+ }
+ else
+ {
+ /* if it's already in our active list, just reset it */
+ /*
+ * note that this can miss FPE's in limbo -- may be worth catching
+ * them, though it'd muck up refcounting
+ */
+ fpe = find_existing_fpe(font_path_elements, num_fpes, cp, len);
+ if (fpe)
+ {
+ err = (*fpe_functions[fpe->type].reset_fpe) (fpe);
+ if (err == Successful)
+ {
+ UseFPE(fpe);/* since it'll be decref'd later when freed
+ * from the old list */
+ }
+ else
+ fpe = 0;
+ }
+ /* if error or can't do it, act like it's a new one */
+ if (!fpe)
+ {
+ fpe = xalloc(sizeof(FontPathElementRec));
+ if (!fpe)
+ {
+ err = BadAlloc;
+ goto bail;
+ }
+ fpe->name = xalloc(len + 1);
+ if (!fpe->name)
+ {
+ xfree(fpe);
+ err = BadAlloc;
+ goto bail;
+ }
+ fpe->refcount = 1;
+
+ strncpy(fpe->name, (char *) cp, (int) len);
+ fpe->name[len] = '\0';
+ fpe->name_length = len;
+ fpe->type = DetermineFPEType(fpe->name);
+ if (fpe->type == -1)
+ err = BadValue;
+ else
+ err = (*fpe_functions[fpe->type].init_fpe) (fpe);
+ if (err != Successful)
+ {
+ if (persist)
+ {
+ ErrorF("[dix] Could not init font path element %s, removing from list!\n",
+ fpe->name);
+ }
+ xfree (fpe->name);
+ xfree (fpe);
+ }
+ }
+ }
+ if (err != Successful)
+ {
+ if (!persist)
+ goto bail;
+ }
+ else
+ {
+ fplist[valid_paths++] = fpe;
+ }
+ cp += len;
+ }
+
+ FreeFontPath(font_path_elements, num_fpes, FALSE);
+ font_path_elements = fplist;
+ if (patternCache)
+ EmptyFontPatternCache(patternCache);
+ num_fpes = valid_paths;
+
+ return Success;
+bail:
+ *bad = i;
+ while (--valid_paths >= 0)
+ FreeFPE(fplist[valid_paths]);
+ xfree(fplist);
+ return FontToXError(err);
+}
+
+/* XXX -- do we need to pass error down to each renderer? */
+int
+SetFontPath(ClientPtr client, int npaths, unsigned char *paths, int *error)
+{
+ int err = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
+ if (err != Success)
+ return err;
+
+ if (npaths == 0) {
+ if (SetDefaultFontPath(defaultFontPath) != Success)
+ return BadValue;
+ } else {
+ err = SetFontPathElements(npaths, paths, error, FALSE);
+ }
+ return err;
+}
+
+int
+SetDefaultFontPath(char *path)
+{
+ char *temp_path,
+ *start,
+ *end;
+ unsigned char *cp,
+ *pp,
+ *nump,
+ *newpath;
+ int num = 1,
+ len,
+ err,
+ size = 0,
+ bad;
+
+ /* ensure temp_path contains "built-ins" */
+ start = path;
+ while (1) {
+ start = strstr(start, "built-ins");
+ if (start == NULL)
+ break;
+ end = start + strlen("built-ins");
+ if ((start == path || start[-1] == ',') && (!*end || *end == ','))
+ break;
+ start = end;
+ }
+ if (!start) {
+ temp_path = Xprintf("%s%sbuilt-ins", path, *path ? "," : "");
+ } else {
+ temp_path = Xstrdup(path);
+ }
+ if (!temp_path)
+ return BadAlloc;
+
+ /* get enough for string, plus values -- use up commas */
+ len = strlen(temp_path) + 1;
+ nump = cp = newpath = xalloc(len);
+ if (!newpath)
+ return BadAlloc;
+ pp = (unsigned char *) temp_path;
+ cp++;
+ while (*pp) {
+ if (*pp == ',') {
+ *nump = (unsigned char) size;
+ nump = cp++;
+ pp++;
+ num++;
+ size = 0;
+ } else {
+ *cp++ = *pp++;
+ size++;
+ }
+ }
+ *nump = (unsigned char) size;
+
+ err = SetFontPathElements(num, newpath, &bad, TRUE);
+
+ xfree(newpath);
+ xfree(temp_path);
+
+ return err;
+}
+
+int
+GetFontPath(ClientPtr client, int *count, int *length, unsigned char **result)
+{
+ int i;
+ unsigned char *c;
+ int len;
+ FontPathElementPtr fpe;
+
+ i = XaceHook(XACE_SERVER_ACCESS, client, DixGetAttrAccess);
+ if (i != Success)
+ return i;
+
+ len = 0;
+ for (i = 0; i < num_fpes; i++) {
+ fpe = font_path_elements[i];
+ len += fpe->name_length + 1;
+ }
+ font_path_string = (unsigned char *) xrealloc(font_path_string, len);
+ if (!font_path_string)
+ return BadAlloc;
+
+ c = font_path_string;
+ *length = 0;
+ for (i = 0; i < num_fpes; i++) {
+ fpe = font_path_elements[i];
+ *c = fpe->name_length;
+ *length += *c++;
+ memmove(c, fpe->name, fpe->name_length);
+ c += fpe->name_length;
+ }
+ *count = num_fpes;
+ *result = font_path_string;
+ return Success;
+}
+
+void
+DeleteClientFontStuff(ClientPtr client)
+{
+ int i;
+ FontPathElementPtr fpe;
+
+ for (i = 0; i < num_fpes; i++)
+ {
+ fpe = font_path_elements[i];
+ if (fpe_functions[fpe->type].client_died)
+ (*fpe_functions[fpe->type].client_died) ((pointer) client, fpe);
+ }
+}
+
+void
+InitFonts (void)
+{
+ patternCache = MakeFontPatternCache();
+
+ BuiltinRegisterFpeFunctions();
+ FontFileRegisterFpeFunctions();
+ fs_register_fpe_functions();
+}
+
+int
+GetDefaultPointSize (void)
+{
+ return 120;
+}
+
+
+FontResolutionPtr
+GetClientResolutions (int *num)
+{
+ static struct _FontResolution res;
+ ScreenPtr pScreen;
+
+ pScreen = screenInfo.screens[0];
+ res.x_resolution = (pScreen->width * 25.4) / pScreen->mmWidth;
+ /*
+ * XXX - we'll want this as long as bitmap instances are prevalent
+ so that we can match them from scalable fonts
+ */
+ if (res.x_resolution < 88)
+ res.x_resolution = 75;
+ else
+ res.x_resolution = 100;
+ res.y_resolution = (pScreen->height * 25.4) / pScreen->mmHeight;
+ if (res.y_resolution < 88)
+ res.y_resolution = 75;
+ else
+ res.y_resolution = 100;
+ res.point_size = 120;
+ *num = 1;
+ return &res;
+}
+
+/*
+ * returns the type index of the new fpe
+ *
+ * should be called (only once!) by each type of fpe when initialized
+ */
+
+int
+RegisterFPEFunctions(NameCheckFunc name_func,
+ InitFpeFunc init_func,
+ FreeFpeFunc free_func,
+ ResetFpeFunc reset_func,
+ OpenFontFunc open_func,
+ CloseFontFunc close_func,
+ ListFontsFunc list_func,
+ StartLfwiFunc start_lfwi_func,
+ NextLfwiFunc next_lfwi_func,
+ WakeupFpeFunc wakeup_func,
+ ClientDiedFunc client_died,
+ LoadGlyphsFunc load_glyphs,
+ StartLaFunc start_list_alias_func,
+ NextLaFunc next_list_alias_func,
+ SetPathFunc set_path_func)
+{
+ FPEFunctions *new;
+
+ /* grow the list */
+ new = (FPEFunctions *) xrealloc(fpe_functions,
+ (num_fpe_types + 1) * sizeof(FPEFunctions));
+ if (!new)
+ return -1;
+ fpe_functions = new;
+
+ fpe_functions[num_fpe_types].name_check = name_func;
+ fpe_functions[num_fpe_types].open_font = open_func;
+ fpe_functions[num_fpe_types].close_font = close_func;
+ fpe_functions[num_fpe_types].wakeup_fpe = wakeup_func;
+ fpe_functions[num_fpe_types].list_fonts = list_func;
+ fpe_functions[num_fpe_types].start_list_fonts_with_info =
+ start_lfwi_func;
+ fpe_functions[num_fpe_types].list_next_font_with_info =
+ next_lfwi_func;
+ fpe_functions[num_fpe_types].init_fpe = init_func;
+ fpe_functions[num_fpe_types].free_fpe = free_func;
+ fpe_functions[num_fpe_types].reset_fpe = reset_func;
+ fpe_functions[num_fpe_types].client_died = client_died;
+ fpe_functions[num_fpe_types].load_glyphs = load_glyphs;
+ fpe_functions[num_fpe_types].start_list_fonts_and_aliases =
+ start_list_alias_func;
+ fpe_functions[num_fpe_types].list_next_font_or_alias =
+ next_list_alias_func;
+ fpe_functions[num_fpe_types].set_path_hook = set_path_func;
+
+ return num_fpe_types++;
+}
+
+void
+FreeFonts(void)
+{
+ if (patternCache) {
+ FreeFontPatternCache(patternCache);
+ patternCache = 0;
+ }
+ FreeFontPath(font_path_elements, num_fpes, TRUE);
+ font_path_elements = 0;
+ num_fpes = 0;
+ xfree(fpe_functions);
+ num_fpe_types = 0;
+ fpe_functions = (FPEFunctions *) 0;
+}
+
+/* convenience functions for FS interface */
+
+FontPtr
+find_old_font(XID id)
+{
+ pointer pFont;
+ dixLookupResourceByType(&pFont, id, RT_NONE, serverClient, DixReadAccess);
+ return (FontPtr)pFont;
+}
+
+Font
+GetNewFontClientID(void)
+{
+ return FakeClientID(0);
+}
+
+int
+StoreFontClientFont(FontPtr pfont, Font id)
+{
+ return AddResource(id, RT_NONE, (pointer) pfont);
+}
+
+void
+DeleteFontClientID(Font id)
+{
+ FreeResource(id, RT_NONE);
+}
+
+int
+client_auth_generation(ClientPtr client)
+{
+ return 0;
+}
+
+static int fs_handlers_installed = 0;
+static unsigned int last_server_gen;
+
+int
+init_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler)
+{
+ /* if server has reset, make sure the b&w handlers are reinstalled */
+ if (last_server_gen < serverGeneration) {
+ last_server_gen = serverGeneration;
+ fs_handlers_installed = 0;
+ }
+ if (fs_handlers_installed == 0) {
+ if (!RegisterBlockAndWakeupHandlers(block_handler,
+ FontWakeup, (pointer) 0))
+ return AllocError;
+ fs_handlers_installed++;
+ }
+ QueueFontWakeup(fpe);
+ return Successful;
+}
+
+void
+remove_fs_handlers(FontPathElementPtr fpe, BlockHandlerProcPtr block_handler, Bool all)
+{
+ if (all) {
+ /* remove the handlers if no one else is using them */
+ if (--fs_handlers_installed == 0) {
+ RemoveBlockAndWakeupHandlers(block_handler, FontWakeup,
+ (pointer) 0);
+ }
+ }
+ RemoveFontWakeup(fpe);
+}
diff --git a/xorg-server/dix/events.c b/xorg-server/dix/events.c
index 015c2b19f..7c6beacd2 100644
--- a/xorg-server/dix/events.c
+++ b/xorg-server/dix/events.c
@@ -779,7 +779,10 @@ CheckPhysLimits(
{
#ifdef PANORAMIX
if (!noPanoramiXExtension)
- XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
+ {
+ if (pScreen && ((new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)))
+ XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
+ }
else
#endif
{
diff --git a/xorg-server/dix/getevents.c b/xorg-server/dix/getevents.c
index 2df32e8f5..eb1563aa4 100644
--- a/xorg-server/dix/getevents.c
+++ b/xorg-server/dix/getevents.c
@@ -1,1204 +1,1212 @@
-/*
- * Copyright © 2006 Nokia Corporation
- * Copyright © 2006-2007 Daniel Stone
- * Copyright © 2008 Red Hat, Inc.
- *
- * 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 (including the next
- * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
- *
- * Authors: Daniel Stone <daniel@fooishbar.org>
- * Peter Hutterer <peter.hutterer@who-t.net>
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/keysym.h>
-#include <X11/Xproto.h>
-
-#include "misc.h"
-#include "resource.h"
-#include "inputstr.h"
-#include "scrnintstr.h"
-#include "cursorstr.h"
-#include "dixstruct.h"
-#include "globals.h"
-#include "dixevents.h"
-#include "mipointer.h"
-#include "eventstr.h"
-#include "eventconvert.h"
-
-#include <X11/extensions/XKBproto.h>
-#include "xkbsrv.h"
-
-#ifdef PANORAMIX
-#include "panoramiX.h"
-#include "panoramiXsrv.h"
-#endif
-
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include "exglobals.h"
-#include "exevents.h"
-#include "exglobals.h"
-#include "extnsionst.h"
-#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */
-
-/* Number of motion history events to store. */
-#define MOTION_HISTORY_SIZE 256
-
-/* InputEventList is the container list for all input events generated by the
- * DDX. The DDX is expected to call GetEventList() and then pass the list into
- * Get{Pointer|Keyboard}Events.
- */
-EventListPtr InputEventList = NULL;
-int InputEventListLen = 0;
-
-int
-GetEventList(EventListPtr* list)
-{
- *list = InputEventList;
- return InputEventListLen;
-}
-
-/**
- * Pick some arbitrary size for Xi motion history.
- */
-int
-GetMotionHistorySize(void)
-{
- return MOTION_HISTORY_SIZE;
-}
-
-void
-set_key_down(DeviceIntPtr pDev, int key_code, int type)
-{
- if (type == KEY_PROCESSED)
- pDev->key->down[key_code >> 3] |= (1 << (key_code & 7));
- else
- pDev->key->postdown[key_code >> 3] |= (1 << (key_code & 7));
-}
-
-void
-set_key_up(DeviceIntPtr pDev, int key_code, int type)
-{
- if (type == KEY_PROCESSED)
- pDev->key->down[key_code >> 3] &= ~(1 << (key_code & 7));
- else
- pDev->key->postdown[key_code >> 3] &= ~(1 << (key_code & 7));
-}
-
-Bool
-key_is_down(DeviceIntPtr pDev, int key_code, int type)
-{
- int ret = 0;
-
- if (type & KEY_PROCESSED)
- ret |= !!(pDev->key->down[key_code >> 3] & (1 << (key_code & 7)));
- else if (type & KEY_POSTED)
- ret |= !!(pDev->key->postdown[key_code >> 3] & (1 << (key_code & 7)));
-
- return ret;
-}
-
-static Bool
-key_autorepeats(DeviceIntPtr pDev, int key_code)
-{
- return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
- (1 << (key_code & 7)));
-}
-
-static void
-init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms)
-{
- memset(event, 0, sizeof(DeviceEvent));
- event->header = ET_Internal;
- event->length = sizeof(DeviceEvent);
- event->time = ms;
- event->deviceid = dev->id;
- event->sourceid = dev->id;
-}
-
-static void
-init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
-{
- memset(event, 0, sizeof(RawDeviceEvent));
- event->header = ET_Internal;
- event->length = sizeof(RawDeviceEvent);
- event->type = ET_RawKeyPress - ET_KeyPress + type;
- event->time = ms;
- event->deviceid = dev->id;
- event->sourceid = dev->id;
- event->detail.button = detail;
-}
-
-static void
-set_raw_valuators(RawDeviceEvent *event, int first, int num, int *valuators, int32_t* data)
-{
- int i;
- for (i = first; i < first + num; i++)
- SetBit(event->valuators.mask, i);
-
- memcpy(&data[first], valuators, num * sizeof(uint32_t));
-}
-
-
-static void
-set_valuators(DeviceIntPtr dev, DeviceEvent* event, int first_valuator,
- int num_valuators, int *valuators)
-{
- int i;
-
- for (i = first_valuator; i < first_valuator + num_valuators; i++)
- {
- SetBit(event->valuators.mask, i);
- if (dev->valuator->mode == Absolute)
- SetBit(event->valuators.mode, i);
- event->valuators.data_frac[i] =
- dev->last.remainder[i] * (1 << 16) * (1 << 16);
- }
-
- memcpy(&event->valuators.data[first_valuator],
- valuators, num_valuators * sizeof(uint32_t));
-
-}
-
-void
-CreateClassesChangedEvent(EventList* event,
- DeviceIntPtr master,
- DeviceIntPtr slave,
- int type)
-{
- int i;
- DeviceChangedEvent *dce;
- CARD32 ms = GetTimeInMillis();
-
- dce = (DeviceChangedEvent*)event->event;
- memset(dce, 0, sizeof(DeviceChangedEvent));
- dce->deviceid = slave->id;
- dce->masterid = master->id;
- dce->header = ET_Internal;
- dce->length = sizeof(DeviceChangedEvent);
- dce->type = ET_DeviceChanged;
- dce->time = ms;
- dce->flags = type;
- dce->flags |= DEVCHANGE_SLAVE_SWITCH;
- dce->sourceid = slave->id;
-
- if (slave->button)
- {
- dce->buttons.num_buttons = slave->button->numButtons;
- for (i = 0; i < dce->buttons.num_buttons; i++)
- dce->buttons.names[i] = slave->button->labels[i];
- }
- if (slave->valuator)
- {
- dce->num_valuators = slave->valuator->numAxes;
- for (i = 0; i < dce->num_valuators; i++)
- {
- dce->valuators[i].min = slave->valuator->axes[i].min_value;
- dce->valuators[i].max = slave->valuator->axes[i].max_value;
- dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
- /* This should, eventually, be a per-axis mode */
- dce->valuators[i].mode = slave->valuator->mode;
- dce->valuators[i].name = slave->valuator->axes[i].label;
- }
- }
- if (slave->key)
- {
- dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
- dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
- }
-}
-
-/**
- * Rescale the coord between the two axis ranges.
- */
-static int
-rescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to,
- int defmax)
-{
- int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return;
- float value;
-
- if(from && from->min_value < from->max_value) {
- fmin = from->min_value;
- fmax = from->max_value;
- }
- if(to && to->min_value < to->max_value) {
- tmin = to->min_value;
- tmax = to->max_value;
- }
-
- if(fmin == tmin && fmax == tmax) {
- if (remainder_return)
- *remainder_return = remainder;
- return coord;
- }
-
- if(fmax == fmin) { /* avoid division by 0 */
- if (remainder_return)
- *remainder_return = 0.0;
- return 0;
- }
-
- value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
- coord_return = lroundf(value);
- if (remainder_return)
- *remainder_return = value - coord_return;
- return coord_return;
-}
-
-/**
- * Update all coordinates when changing to a different SD
- * to ensure that relative reporting will work as expected
- * without loss of precision.
- *
- * pDev->last.valuators will be in absolute device coordinates after this
- * function.
- */
-static void
-updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
-{
- ScreenPtr scr = miPointerGetScreen(pDev);
- int i;
- DeviceIntPtr lastSlave;
-
- /* master->last.valuators[0]/[1] is in screen coords and the actual
- * position of the pointer */
- pDev->last.valuators[0] = master->last.valuators[0];
- pDev->last.valuators[1] = master->last.valuators[1];
-
- if (!pDev->valuator)
- return;
-
- /* scale back to device coordinates */
- if(pDev->valuator->numAxes > 0)
- pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0],
- &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width);
- if(pDev->valuator->numAxes > 1)
- pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1],
- &pDev->last.remainder[0], NULL, pDev->valuator->axes + 1, scr->height);
-
- /* calculate the other axis as well based on info from the old
- * slave-device. If the old slave had less axes than this one,
- * last.valuators is reset to 0.
- */
- if ((lastSlave = master->last.slave) && lastSlave->valuator) {
- for (i = 2; i < pDev->valuator->numAxes; i++) {
- if (i >= lastSlave->valuator->numAxes)
- pDev->last.valuators[i] = 0;
- else
- pDev->last.valuators[i] =
- rescaleValuatorAxis(pDev->last.valuators[i],
- pDev->last.remainder[i],
- &pDev->last.remainder[i],
- lastSlave->valuator->axes + i,
- pDev->valuator->axes + i, 0);
- }
- }
-
-}
-
-/**
- * Allocate the motion history buffer.
- */
-void
-AllocateMotionHistory(DeviceIntPtr pDev)
-{
- int size;
- if (pDev->valuator->motion)
- xfree(pDev->valuator->motion);
-
- if (pDev->valuator->numMotionEvents < 1)
- return;
-
- /* An MD must have a motion history size large enough to keep all
- * potential valuators, plus the respective range of the valuators.
- * 3 * INT32 for (min_val, max_val, curr_val))
- */
- if (IsMaster(pDev))
- size = sizeof(INT32) * 3 * MAX_VALUATORS;
- else
- size = sizeof(INT32) * pDev->valuator->numAxes;
-
- size += sizeof(Time);
-
- pDev->valuator->motion = xcalloc(pDev->valuator->numMotionEvents, size);
- pDev->valuator->first_motion = 0;
- pDev->valuator->last_motion = 0;
- if (!pDev->valuator->motion)
- ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
- pDev->name, size * pDev->valuator->numMotionEvents);
-}
-
-/**
- * Dump the motion history between start and stop into the supplied buffer.
- * Only records the event for a given screen in theory, but in practice, we
- * sort of ignore this.
- *
- * If core is set, we only generate x/y, in INT16, scaled to screen coords.
- */
-int
-GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
- unsigned long stop, ScreenPtr pScreen, BOOL core)
-{
- char *ibuff = NULL, *obuff;
- int i = 0, ret = 0;
- int j, coord;
- Time current;
- /* The size of a single motion event. */
- int size;
- int dflt;
- AxisInfo from, *to; /* for scaling */
- INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
- INT16 *corebuf;
- AxisInfo core_axis = {0};
-
- if (!pDev->valuator || !pDev->valuator->numMotionEvents)
- return 0;
-
- if (core && !pScreen)
- return 0;
-
- if (IsMaster(pDev))
- size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
- else
- size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
-
- *buff = xalloc(size * pDev->valuator->numMotionEvents);
- if (!(*buff))
- return 0;
- obuff = (char *)*buff;
-
- for (i = pDev->valuator->first_motion;
- i != pDev->valuator->last_motion;
- i = (i + 1) % pDev->valuator->numMotionEvents) {
- /* We index the input buffer by which element we're accessing, which
- * is not monotonic, and the output buffer by how many events we've
- * written so far. */
- ibuff = (char *) pDev->valuator->motion + (i * size);
- memcpy(&current, ibuff, sizeof(Time));
-
- if (current > stop) {
- return ret;
- }
- else if (current >= start) {
- if (core)
- {
- memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
-
- icbuf = (INT32*)(ibuff + sizeof(Time));
- corebuf = (INT16*)(obuff + sizeof(Time));
-
- /* fetch x coordinate + range */
- memcpy(&from.min_value, icbuf++, sizeof(INT32));
- memcpy(&from.max_value, icbuf++, sizeof(INT32));
- memcpy(&coord, icbuf++, sizeof(INT32));
-
- /* scale to screen coords */
- to = &core_axis;
- to->max_value = pScreen->width;
- coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width);
-
- memcpy(corebuf, &coord, sizeof(INT16));
- corebuf++;
-
- /* fetch y coordinate + range */
- memcpy(&from.min_value, icbuf++, sizeof(INT32));
- memcpy(&from.max_value, icbuf++, sizeof(INT32));
- memcpy(&coord, icbuf++, sizeof(INT32));
-
- to->max_value = pScreen->height;
- coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height);
- memcpy(corebuf, &coord, sizeof(INT16));
-
- } else if (IsMaster(pDev))
- {
- memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
-
- ocbuf = (INT32*)(obuff + sizeof(Time));
- icbuf = (INT32*)(ibuff + sizeof(Time));
- for (j = 0; j < MAX_VALUATORS; j++)
- {
- if (j >= pDev->valuator->numAxes)
- break;
-
- /* fetch min/max/coordinate */
- memcpy(&from.min_value, icbuf++, sizeof(INT32));
- memcpy(&from.max_value, icbuf++, sizeof(INT32));
- memcpy(&coord, icbuf++, sizeof(INT32));
-
- to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL;
-
- /* x/y scaled to screen if no range is present */
- if (j == 0 && (from.max_value < from.min_value))
- from.max_value = pScreen->width;
- else if (j == 1 && (from.max_value < from.min_value))
- from.max_value = pScreen->height;
-
- if (j == 0 && (to->max_value < to->min_value))
- dflt = pScreen->width;
- else if (j == 1 && (to->max_value < to->min_value))
- dflt = pScreen->height;
- else
- dflt = 0;
-
- /* scale from stored range into current range */
- coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0);
- memcpy(ocbuf, &coord, sizeof(INT32));
- ocbuf++;
- }
- } else
- memcpy(obuff, ibuff, size);
-
- /* don't advance by size here. size may be different to the
- * actually written size if the MD has less valuators than MAX */
- if (core)
- obuff += sizeof(INT32) + sizeof(Time);
- else
- obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
- ret++;
- }
- }
-
- return ret;
-}
-
-
-/**
- * Update the motion history for a specific device, with the list of
- * valuators.
- *
- * Layout of the history buffer:
- * for SDs: [time] [val0] [val1] ... [valn]
- * for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
- *
- * For events that have some valuators unset (first_valuator > 0):
- * min_val == max_val == val == 0.
- */
-static void
-updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
- int num_valuators, int *valuators)
-{
- char *buff = (char *) pDev->valuator->motion;
- ValuatorClassPtr v;
- int i;
-
- if (!pDev->valuator->numMotionEvents)
- return;
-
- v = pDev->valuator;
- if (IsMaster(pDev))
- {
- buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
- v->last_motion;
-
- memcpy(buff, &ms, sizeof(Time));
- buff += sizeof(Time);
-
- memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
- buff += 3 * sizeof(INT32) * first_valuator;
-
- for (i = first_valuator; i < first_valuator + num_valuators; i++)
- {
- if (i >= v->numAxes)
- break;
- memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
- buff += sizeof(INT32);
- memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
- buff += sizeof(INT32);
- memcpy(buff, &valuators[i - first_valuator], sizeof(INT32));
- buff += sizeof(INT32);
- }
- } else
- {
-
- buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
- pDev->valuator->last_motion;
-
- memcpy(buff, &ms, sizeof(Time));
- buff += sizeof(Time);
-
- memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
- buff += sizeof(INT32) * first_valuator;
-
- memcpy(buff, valuators, sizeof(INT32) * num_valuators);
- }
-
- pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
- pDev->valuator->numMotionEvents;
- /* If we're wrapping around, just keep the circular buffer going. */
- if (pDev->valuator->first_motion == pDev->valuator->last_motion)
- pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
- pDev->valuator->numMotionEvents;
-
- return;
-}
-
-
-/**
- * Returns the maximum number of events GetKeyboardEvents,
- * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
- *
- * This MUST be absolutely constant, from init until exit.
- */
-int
-GetMaximumEventsNum(void) {
- /* One raw event
- * One device event
- * One possible device changed event
- */
- return 3;
-}
-
-
-/**
- * Clip an axis to its bounds, which are declared in the call to
- * InitValuatorAxisClassStruct.
- */
-static void
-clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
-{
- AxisInfoPtr axis;
-
- if (axisNum >= pDev->valuator->numAxes)
- return;
-
- axis = pDev->valuator->axes + axisNum;
-
- /* If a value range is defined, clip. If not, do nothing */
- if (axis->max_value <= axis->min_value)
- return;
-
- if (*val < axis->min_value)
- *val = axis->min_value;
- if (*val > axis->max_value)
- *val = axis->max_value;
-}
-
-/**
- * Clip every axis in the list of valuators to its bounds.
- */
-static void
-clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
- int *valuators)
-{
- int i;
-
- for (i = 0; i < num_valuators; i++)
- clipAxis(pDev, i + first_valuator, &(valuators[i]));
-}
-
-/**
- * Create the DCCE event (does not update the master's device state yet, this
- * is done in the event processing).
- * Pull in the coordinates from the MD if necessary.
- *
- * @param events Pointer to a pre-allocated event list.
- * @param dev The slave device that generated an event.
- * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
- * @param num_events The current number of events, returns the number of
- * events if a DCCE was generated.
- * @return The updated @events pointer.
- */
-static EventListPtr
-updateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events)
-{
- DeviceIntPtr master;
-
- master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER : MASTER_KEYBOARD);
-
- if (master && master->last.slave != dev)
- {
- CreateClassesChangedEvent(events, master, dev, type);
- updateSlaveDeviceCoords(master, dev);
- master->last.slave = dev;
- master->last.numValuators = dev->last.numValuators;
- (*num_events)++;
- events++;
- }
- return events;
-}
-
-/**
- * Move the device's pointer to the position given in the valuators.
- *
- * @param dev The device which's pointer is to be moved.
- * @param x Returns the x position of the pointer after the move.
- * @param y Returns the y position of the pointer after the move.
- * @param first The first valuator in @valuators
- * @param num Total number of valuators in @valuators.
- * @param valuators Valuator data for each axis between @first and
- * @first+@num.
- */
-static void
-moveAbsolute(DeviceIntPtr dev, int *x, int *y,
- int first, int num, int *valuators)
-{
- int i;
-
-
- if (num >= 1 && first == 0)
- *x = *(valuators + 0);
- else
- *x = dev->last.valuators[0];
-
- if (first <= 1 && num >= (2 - first))
- *y = *(valuators + 1 - first);
- else
- *y = dev->last.valuators[1];
-
- clipAxis(dev, 0, x);
- clipAxis(dev, 1, y);
-
- i = (first > 2) ? 0 : 2;
- for (; i < num; i++)
- {
- dev->last.valuators[i + first] = valuators[i];
- clipAxis(dev, i, &dev->last.valuators[i + first]);
- }
-}
-
-/**
- * Move the device's pointer by the values given in @valuators.
- *
- * @param dev The device which's pointer is to be moved.
- * @param x Returns the x position of the pointer after the move.
- * @param y Returns the y position of the pointer after the move.
- * @param first The first valuator in @valuators
- * @param num Total number of valuators in @valuators.
- * @param valuators Valuator data for each axis between @first and
- * @first+@num.
- */
-static void
-moveRelative(DeviceIntPtr dev, int *x, int *y,
- int first, int num, int *valuators)
-{
- int i;
-
- *x = dev->last.valuators[0];
- *y = dev->last.valuators[1];
-
- if (num >= 1 && first == 0)
- *x += *(valuators +0);
-
- if (first <= 1 && num >= (2 - first))
- *y += *(valuators + 1 - first);
-
- /* if attached, clip both x and y to the defined limits (usually
- * co-ord space limit). If it is attached, we need x/y to go over the
- * limits to be able to change screens. */
- if(dev->u.master) {
- clipAxis(dev, 0, x);
- clipAxis(dev, 1, y);
- }
-
- /* calc other axes, clip, drop back into valuators */
- i = (first > 2) ? 0 : 2;
- for (; i < num; i++)
- {
- dev->last.valuators[i + first] += valuators[i];
- clipAxis(dev, i, &dev->last.valuators[i + first]);
- valuators[i] = dev->last.valuators[i + first];
- }
-}
-
-/**
- * Accelerate the data in valuators based on the device's acceleration scheme.
- *
- * @param dev The device which's pointer is to be moved.
- * @param first The first valuator in @valuators
- * @param num Total number of valuators in @valuators.
- * @param valuators Valuator data for each axis between @first and
- * @first+@num.
- * @param ms Current time.
- */
-static void
-accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
-{
- if (dev->valuator->accelScheme.AccelSchemeProc)
- dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms);
-}
-
-/**
- * If we have HW cursors, this actually moves the visible sprite. If not, we
- * just do all the screen crossing, etc.
- *
- * We scale from device to screen coordinates here, call
- * miPointerSetPosition() and then scale back into device coordinates (if
- * needed). miPSP will change x/y if the screen was crossed.
- *
- * @param dev The device to be moved.
- * @param x Pointer to current x-axis value, may be modified.
- * @param y Pointer to current y-axis value, may be modified.
- * @param x_frac Fractional part of current x-axis value, may be modified.
- * @param y_frac Fractional part of current y-axis value, may be modified.
- * @param scr Screen the device's sprite is currently on.
- * @param screenx Screen x coordinate the sprite is on after the update.
- * @param screeny Screen y coordinate the sprite is on after the update.
- * @param screenx_frac Fractional part of screen x coordinate, as above.
- * @param screeny_frac Fractional part of screen y coordinate, as above.
- */
-static void
-positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
- ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
-{
- int old_screenx, old_screeny;
-
- /* scale x&y to screen */
- if (dev->valuator->numAxes > 0) {
- *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac,
- dev->valuator->axes + 0, NULL, scr->width);
- } else {
- *screenx = dev->last.valuators[0];
- *screenx_frac = dev->last.remainder[0];
- }
-
- if (dev->valuator->numAxes > 1) {
- *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac,
- dev->valuator->axes + 1, NULL, scr->height);
- } else {
- *screeny = dev->last.valuators[1];
- *screeny_frac = dev->last.remainder[1];
- }
-
- /* Hit the left screen edge? */
- if (*screenx <= 0 && *screenx_frac < 0.0f)
- {
- *screenx_frac = 0.0f;
- x_frac = 0.0f;
- }
- if (*screeny <= 0 && *screeny_frac < 0.0f)
- {
- *screeny_frac = 0.0f;
- y_frac = 0.0f;
- }
-
-
- old_screenx = *screenx;
- old_screeny = *screeny;
- /* This takes care of crossing screens for us, as well as clipping
- * to the current screen. */
- miPointerSetPosition(dev, screenx, screeny);
-
- if (dev->u.master) {
- dev->u.master->last.valuators[0] = *screenx;
- dev->u.master->last.valuators[1] = *screeny;
- dev->u.master->last.remainder[0] = *screenx_frac;
- dev->u.master->last.remainder[1] = *screeny_frac;
- }
-
- /* Crossed screen? Scale back to device coordiantes */
- if(*screenx != old_screenx)
- {
- scr = miPointerGetScreen(dev);
- *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL,
- dev->valuator->axes + 0, scr->width);
- }
- if(*screeny != old_screeny)
- {
- scr = miPointerGetScreen(dev);
- *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL,
- dev->valuator->axes + 1, scr->height);
- }
-
- /* dropy x/y (device coordinates) back into valuators for next event */
- dev->last.valuators[0] = *x;
- dev->last.valuators[1] = *y;
- dev->last.remainder[0] = x_frac;
- dev->last.remainder[1] = y_frac;
-}
-
-/**
- * Update the motion history for the device and (if appropriate) for its
- * master device.
- * @param dev Slave device to update.
- * @param first First valuator to append to history.
- * @param num Total number of valuators to append to history.
- * @param ms Current time
- */
-static void
-updateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms)
-{
- updateMotionHistory(dev, ms, first, num, &dev->last.valuators[first]);
- if (dev->u.master)
- {
- DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
- updateMotionHistory(master, ms, first, num, &dev->last.valuators[first]);
- }
-}
-
-/**
- * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
- * valuators.
- */
-int
-GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
- return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL);
-}
-
-
-/**
- * Returns a set of keyboard events for KeyPress/KeyRelease, optionally
- * also with valuator events. Handles Xi and XKB.
- *
- * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
- * event (ProcessOtherEvent).
- *
- * events is not NULL-terminated; the return value is the number of events.
- * The DDX is responsible for allocating the event structure in the first
- * place via GetMaximumEventsNum(), and for freeing it.
- *
- * This function does not change the core keymap to that of the device;
- * that is done by SwitchCoreKeyboard, which is called from
- * mieqProcessInputEvents. If replacing that function, take care to call
- * SetCoreKeyboard before processInputProc, so keymaps are altered to suit.
- */
-int
-GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
- int key_code, int first_valuator,
- int num_valuators, int *valuators) {
- int num_events = 0;
- CARD32 ms = 0;
- DeviceEvent *event;
- RawDeviceEvent *raw;
-
- /* refuse events from disabled devices */
- if (!pDev->enabled)
- return 0;
-
- if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
- (type != KeyPress && type != KeyRelease) ||
- (key_code < 8 || key_code > 255))
- return 0;
-
- num_events = 1;
-
- events = updateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
-
- /* Handle core repeating, via press/release/press/release. */
- if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
- /* If autorepeating is disabled either globally or just for that key,
- * or we have a modifier, don't generate a repeat event. */
- if (!pDev->kbdfeed->ctrl.autoRepeat ||
- !key_autorepeats(pDev, key_code) ||
- pDev->key->xkbInfo->desc->map->modmap[key_code])
- return 0;
- }
-
- ms = GetTimeInMillis();
-
- raw = (RawDeviceEvent*)events->event;
- events++;
- num_events++;
-
- init_raw(pDev, raw, ms, type, key_code);
- set_raw_valuators(raw, first_valuator, num_valuators, valuators,
- raw->valuators.data_raw);
-
- if (num_valuators)
- clipValuators(pDev, first_valuator, num_valuators, valuators);
-
- set_raw_valuators(raw, first_valuator, num_valuators, valuators,
- raw->valuators.data);
-
- event = (DeviceEvent*) events->event;
- init_event(pDev, event, ms);
- event->detail.key = key_code;
-
- if (type == KeyPress) {
- event->type = ET_KeyPress;
- set_key_down(pDev, key_code, KEY_POSTED);
- }
- else if (type == KeyRelease) {
- event->type = ET_KeyRelease;
- set_key_up(pDev, key_code, KEY_POSTED);
- }
-
- if (num_valuators)
- clipValuators(pDev, first_valuator, num_valuators, valuators);
-
- set_valuators(pDev, event, first_valuator, num_valuators, valuators);
-
- return num_events;
-}
-
-/**
- * Initialize an event list and fill with 32 byte sized events.
- * This event list is to be passed into GetPointerEvents() and
- * GetKeyboardEvents().
- *
- * @param num_events Number of elements in list.
- */
-EventListPtr
-InitEventList(int num_events)
-{
- EventListPtr events;
- int i;
-
- events = (EventListPtr)xcalloc(num_events, sizeof(EventList));
- if (!events)
- return NULL;
-
- for (i = 0; i < num_events; i++)
- {
- events[i].evlen = sizeof(InternalEvent);
- events[i].event = xcalloc(1, sizeof(InternalEvent));
- if (!events[i].event)
- {
- /* rollback */
- while(i--)
- xfree(events[i].event);
- xfree(events);
- events = NULL;
- break;
- }
- }
-
- return events;
-}
-
-/**
- * Free an event list.
- *
- * @param list The list to be freed.
- * @param num_events Number of elements in list.
- */
-void
-FreeEventList(EventListPtr list, int num_events)
-{
- if (!list)
- return;
- while(num_events--)
- xfree(list[num_events].event);
- xfree(list);
-}
-
-/**
- * Generate a series of xEvents (filled into the EventList) representing
- * pointer motion, or button presses. Xi and XKB-aware.
- *
- * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
- * event (ProcessOtherEvent).
- *
- * events is not NULL-terminated; the return value is the number of events.
- * The DDX is responsible for allocating the event structure in the first
- * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
- *
- * In the generated events rootX/Y will be in absolute screen coords and
- * the valuator information in the absolute or relative device coords.
- *
- * last.valuators[x] of the device is always in absolute device coords.
- * last.valuators[x] of the master device is in absolute screen coords.
- *
- * master->last.valuators[x] for x > 2 is undefined.
- */
-int
-GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
- int flags, int first_valuator, int num_valuators,
- int *valuators) {
- int num_events = 1;
- CARD32 ms;
- DeviceEvent *event;
- RawDeviceEvent *raw;
- int x = 0, y = 0, /* device coords */
- cx, cy; /* only screen coordinates */
- float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac;
- ScreenPtr scr = miPointerGetScreen(pDev);
-
- /* refuse events from disabled devices */
- if (!pDev->enabled)
- return 0;
-
- ms = GetTimeInMillis(); /* before pointer update to help precision */
-
- if (!scr || !pDev->valuator || first_valuator < 0 ||
- ((num_valuators + first_valuator) > pDev->valuator->numAxes) ||
- (type != MotionNotify && type != ButtonPress && type != ButtonRelease) ||
- (type != MotionNotify && !pDev->button) ||
- ((type == ButtonPress || type == ButtonRelease) && !buttons) ||
- (type == MotionNotify && num_valuators <= 0))
- return 0;
-
- events = updateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
-
- raw = (RawDeviceEvent*)events->event;
- events++;
- num_events++;
-
- init_raw(pDev, raw, ms, type, buttons);
- set_raw_valuators(raw, first_valuator, num_valuators, valuators,
- raw->valuators.data_raw);
-
- if (flags & POINTER_ABSOLUTE)
- {
- if (flags & POINTER_SCREEN) /* valuators are in screen coords */
- {
-
- if (num_valuators >= 1 && first_valuator == 0)
- valuators[0] = rescaleValuatorAxis(valuators[0], 0.0, &x_frac, NULL,
- pDev->valuator->axes + 0,
- scr->width);
- if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
- valuators[1 - first_valuator] = rescaleValuatorAxis(valuators[1 - first_valuator], 0.0, &y_frac, NULL,
- pDev->valuator->axes + 1,
- scr->height);
- }
-
- moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators);
- } else {
- if (flags & POINTER_ACCELERATE) {
- accelPointer(pDev, first_valuator, num_valuators, valuators, ms);
- /* The pointer acceleration code modifies the fractional part
- * in-place, so we need to extract this information first */
- x_frac = pDev->last.remainder[0];
- y_frac = pDev->last.remainder[1];
- }
- moveRelative(pDev, &x, &y, first_valuator, num_valuators, valuators);
- }
-
- set_raw_valuators(raw, first_valuator, num_valuators, valuators,
- raw->valuators.data);
-
- positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
- updateHistory(pDev, first_valuator, num_valuators, ms);
-
- /* Update the valuators with the true value sent to the client*/
- if (num_valuators >= 1 && first_valuator == 0)
- valuators[0] = x;
- if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
- valuators[1 - first_valuator] = y;
-
- if (num_valuators)
- clipValuators(pDev, first_valuator, num_valuators, valuators);
-
- event = (DeviceEvent*) events->event;
- init_event(pDev, event, ms);
-
- if (type == MotionNotify) {
- event->type = ET_Motion;
- event->detail.button = 0;
- }
- else {
- if (type == ButtonPress) {
- event->type = ET_ButtonPress;
- pDev->button->postdown[buttons >> 3] |= (1 << (buttons & 7));
- }
- else if (type == ButtonRelease) {
- event->type = ET_ButtonRelease;
- pDev->button->postdown[buttons >> 3] &= ~(1 << (buttons & 7));
- }
- event->detail.button = buttons;
- }
-
- event->root_x = cx; /* root_x/y always in screen coords */
- event->root_y = cy;
- event->root_x_frac = cx_frac;
- event->root_y_frac = cy_frac;
-
- set_valuators(pDev, event, first_valuator, num_valuators, valuators);
-
- return num_events;
-}
-
-
-/**
- * Post ProximityIn/ProximityOut events, accompanied by valuators.
- *
- * events is not NULL-terminated; the return value is the number of events.
- * The DDX is responsible for allocating the event structure in the first
- * place via GetMaximumEventsNum(), and for freeing it.
- */
-int
-GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
- int first_valuator, int num_valuators, int *valuators)
-{
- int num_events = 1;
- DeviceEvent *event;
-
- /* refuse events from disabled devices */
- if (!pDev->enabled)
- return 0;
-
- /* Sanity checks. */
- if (type != ProximityIn && type != ProximityOut)
- return 0;
- if (!pDev->valuator)
- return 0;
- /* Do we need to send a DeviceValuator event? */
- if ((pDev->valuator->mode & 1) == Relative)
- num_valuators = 0;
-
- /* You fail. */
- if (first_valuator < 0 ||
- (num_valuators + first_valuator) > pDev->valuator->numAxes)
- return 0;
-
- events = updateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
-
- event = (DeviceEvent *) events->event;
- init_event(pDev, event, GetTimeInMillis());
- event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
-
- if (num_valuators)
- clipValuators(pDev, first_valuator, num_valuators, valuators);
-
- set_valuators(pDev, event, first_valuator, num_valuators, valuators);
-
- return num_events;
-}
-
-/**
- * Synthesize a single motion event for the core pointer.
- *
- * Used in cursor functions, e.g. when cursor confinement changes, and we need
- * to shift the pointer to get it inside the new bounds.
- */
-void
-PostSyntheticMotion(DeviceIntPtr pDev,
- int x,
- int y,
- int screen,
- unsigned long time)
-{
- DeviceEvent ev;
-
-#ifdef PANORAMIX
- /* Translate back to the sprite screen since processInputProc
- will translate from sprite screen to screen 0 upon reentry
- to the DIX layer. */
- if (!noPanoramiXExtension) {
- x += panoramiXdataPtr[0].x - panoramiXdataPtr[screen].x;
- y += panoramiXdataPtr[0].y - panoramiXdataPtr[screen].y;
- }
-#endif
-
- memset(&ev, 0, sizeof(DeviceEvent));
- init_event(pDev, &ev, time);
- ev.root_x = x;
- ev.root_y = y;
- ev.type = ET_Motion;
- ev.time = time;
-
- /* FIXME: MD/SD considerations? */
- (*pDev->public.processInputProc)((InternalEvent*)&ev, pDev);
-}
+/*
+ * Copyright © 2006 Nokia Corporation
+ * Copyright © 2006-2007 Daniel Stone
+ * Copyright © 2008 Red Hat, Inc.
+ *
+ * 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 (including the next
+ * paragraph) 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 AUTHORS OR COPYRIGHT HOLDERS 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.
+ *
+ * Authors: Daniel Stone <daniel@fooishbar.org>
+ * Peter Hutterer <peter.hutterer@who-t.net>
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/keysym.h>
+#include <X11/Xproto.h>
+
+#include "misc.h"
+#include "resource.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#include "cursorstr.h"
+#include "dixstruct.h"
+#include "globals.h"
+#include "dixevents.h"
+#include "mipointer.h"
+#include "eventstr.h"
+#include "eventconvert.h"
+
+#include <X11/extensions/XKBproto.h>
+#include "xkbsrv.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#include "panoramiXsrv.h"
+#endif
+
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "exglobals.h"
+#include "exevents.h"
+#include "exglobals.h"
+#include "extnsionst.h"
+#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */
+
+#ifdef _MSC_VER
+float roundf(float f)
+{
+ return ((f<0.0f) ? ceil(f-.5) : floor (f+.5));
+}
+#define lroundf(val) ((int)roundf(val))
+#endif
+
+/* Number of motion history events to store. */
+#define MOTION_HISTORY_SIZE 256
+
+/* InputEventList is the container list for all input events generated by the
+ * DDX. The DDX is expected to call GetEventList() and then pass the list into
+ * Get{Pointer|Keyboard}Events.
+ */
+EventListPtr InputEventList = NULL;
+int InputEventListLen = 0;
+
+int
+GetEventList(EventListPtr* list)
+{
+ *list = InputEventList;
+ return InputEventListLen;
+}
+
+/**
+ * Pick some arbitrary size for Xi motion history.
+ */
+int
+GetMotionHistorySize(void)
+{
+ return MOTION_HISTORY_SIZE;
+}
+
+void
+set_key_down(DeviceIntPtr pDev, int key_code, int type)
+{
+ if (type == KEY_PROCESSED)
+ pDev->key->down[key_code >> 3] |= (1 << (key_code & 7));
+ else
+ pDev->key->postdown[key_code >> 3] |= (1 << (key_code & 7));
+}
+
+void
+set_key_up(DeviceIntPtr pDev, int key_code, int type)
+{
+ if (type == KEY_PROCESSED)
+ pDev->key->down[key_code >> 3] &= ~(1 << (key_code & 7));
+ else
+ pDev->key->postdown[key_code >> 3] &= ~(1 << (key_code & 7));
+}
+
+Bool
+key_is_down(DeviceIntPtr pDev, int key_code, int type)
+{
+ int ret = 0;
+
+ if (type & KEY_PROCESSED)
+ ret |= !!(pDev->key->down[key_code >> 3] & (1 << (key_code & 7)));
+ else if (type & KEY_POSTED)
+ ret |= !!(pDev->key->postdown[key_code >> 3] & (1 << (key_code & 7)));
+
+ return ret;
+}
+
+static Bool
+key_autorepeats(DeviceIntPtr pDev, int key_code)
+{
+ return !!(pDev->kbdfeed->ctrl.autoRepeats[key_code >> 3] &
+ (1 << (key_code & 7)));
+}
+
+static void
+init_event(DeviceIntPtr dev, DeviceEvent* event, Time ms)
+{
+ memset(event, 0, sizeof(DeviceEvent));
+ event->header = ET_Internal;
+ event->length = sizeof(DeviceEvent);
+ event->time = ms;
+ event->deviceid = dev->id;
+ event->sourceid = dev->id;
+}
+
+static void
+init_raw(DeviceIntPtr dev, RawDeviceEvent *event, Time ms, int type, int detail)
+{
+ memset(event, 0, sizeof(RawDeviceEvent));
+ event->header = ET_Internal;
+ event->length = sizeof(RawDeviceEvent);
+ event->type = ET_RawKeyPress - ET_KeyPress + type;
+ event->time = ms;
+ event->deviceid = dev->id;
+ event->sourceid = dev->id;
+ event->detail.button = detail;
+}
+
+static void
+set_raw_valuators(RawDeviceEvent *event, int first, int num, int *valuators, int32_t* data)
+{
+ int i;
+ for (i = first; i < first + num; i++)
+ SetBit(event->valuators.mask, i);
+
+ memcpy(&data[first], valuators, num * sizeof(uint32_t));
+}
+
+
+static void
+set_valuators(DeviceIntPtr dev, DeviceEvent* event, int first_valuator,
+ int num_valuators, int *valuators)
+{
+ int i;
+
+ for (i = first_valuator; i < first_valuator + num_valuators; i++)
+ {
+ SetBit(event->valuators.mask, i);
+ if (dev->valuator->mode == Absolute)
+ SetBit(event->valuators.mode, i);
+ event->valuators.data_frac[i] =
+ dev->last.remainder[i] * (1 << 16) * (1 << 16);
+ }
+
+ memcpy(&event->valuators.data[first_valuator],
+ valuators, num_valuators * sizeof(uint32_t));
+
+}
+
+void
+CreateClassesChangedEvent(EventList* event,
+ DeviceIntPtr master,
+ DeviceIntPtr slave,
+ int type)
+{
+ int i;
+ DeviceChangedEvent *dce;
+ CARD32 ms = GetTimeInMillis();
+
+ dce = (DeviceChangedEvent*)event->event;
+ memset(dce, 0, sizeof(DeviceChangedEvent));
+ dce->deviceid = slave->id;
+ dce->masterid = master->id;
+ dce->header = ET_Internal;
+ dce->length = sizeof(DeviceChangedEvent);
+ dce->type = ET_DeviceChanged;
+ dce->time = ms;
+ dce->flags = type;
+ dce->flags |= DEVCHANGE_SLAVE_SWITCH;
+ dce->sourceid = slave->id;
+
+ if (slave->button)
+ {
+ dce->buttons.num_buttons = slave->button->numButtons;
+ for (i = 0; i < dce->buttons.num_buttons; i++)
+ dce->buttons.names[i] = slave->button->labels[i];
+ }
+ if (slave->valuator)
+ {
+ dce->num_valuators = slave->valuator->numAxes;
+ for (i = 0; i < dce->num_valuators; i++)
+ {
+ dce->valuators[i].min = slave->valuator->axes[i].min_value;
+ dce->valuators[i].max = slave->valuator->axes[i].max_value;
+ dce->valuators[i].resolution = slave->valuator->axes[i].resolution;
+ /* This should, eventually, be a per-axis mode */
+ dce->valuators[i].mode = slave->valuator->mode;
+ dce->valuators[i].name = slave->valuator->axes[i].label;
+ }
+ }
+ if (slave->key)
+ {
+ dce->keys.min_keycode = slave->key->xkbInfo->desc->min_key_code;
+ dce->keys.max_keycode = slave->key->xkbInfo->desc->max_key_code;
+ }
+}
+
+/**
+ * Rescale the coord between the two axis ranges.
+ */
+static int
+rescaleValuatorAxis(int coord, float remainder, float *remainder_return, AxisInfoPtr from, AxisInfoPtr to,
+ int defmax)
+{
+ int fmin = 0, tmin = 0, fmax = defmax, tmax = defmax, coord_return;
+ float value;
+
+ if(from && from->min_value < from->max_value) {
+ fmin = from->min_value;
+ fmax = from->max_value;
+ }
+ if(to && to->min_value < to->max_value) {
+ tmin = to->min_value;
+ tmax = to->max_value;
+ }
+
+ if(fmin == tmin && fmax == tmax) {
+ if (remainder_return)
+ *remainder_return = remainder;
+ return coord;
+ }
+
+ if(fmax == fmin) { /* avoid division by 0 */
+ if (remainder_return)
+ *remainder_return = 0.0;
+ return 0;
+ }
+
+ value = (coord + remainder - fmin) * (tmax - tmin) / (fmax - fmin) + tmin;
+ coord_return = lroundf(value);
+ if (remainder_return)
+ *remainder_return = value - coord_return;
+ return coord_return;
+}
+
+/**
+ * Update all coordinates when changing to a different SD
+ * to ensure that relative reporting will work as expected
+ * without loss of precision.
+ *
+ * pDev->last.valuators will be in absolute device coordinates after this
+ * function.
+ */
+static void
+updateSlaveDeviceCoords(DeviceIntPtr master, DeviceIntPtr pDev)
+{
+ ScreenPtr scr = miPointerGetScreen(pDev);
+ int i;
+ DeviceIntPtr lastSlave;
+
+ /* master->last.valuators[0]/[1] is in screen coords and the actual
+ * position of the pointer */
+ pDev->last.valuators[0] = master->last.valuators[0];
+ pDev->last.valuators[1] = master->last.valuators[1];
+
+ if (!pDev->valuator)
+ return;
+
+ /* scale back to device coordinates */
+ if(pDev->valuator->numAxes > 0)
+ pDev->last.valuators[0] = rescaleValuatorAxis(pDev->last.valuators[0], pDev->last.remainder[0],
+ &pDev->last.remainder[0], NULL, pDev->valuator->axes + 0, scr->width);
+ if(pDev->valuator->numAxes > 1)
+ pDev->last.valuators[1] = rescaleValuatorAxis(pDev->last.valuators[1], pDev->last.remainder[1],
+ &pDev->last.remainder[0], NULL, pDev->valuator->axes + 1, scr->height);
+
+ /* calculate the other axis as well based on info from the old
+ * slave-device. If the old slave had less axes than this one,
+ * last.valuators is reset to 0.
+ */
+ if ((lastSlave = master->last.slave) && lastSlave->valuator) {
+ for (i = 2; i < pDev->valuator->numAxes; i++) {
+ if (i >= lastSlave->valuator->numAxes)
+ pDev->last.valuators[i] = 0;
+ else
+ pDev->last.valuators[i] =
+ rescaleValuatorAxis(pDev->last.valuators[i],
+ pDev->last.remainder[i],
+ &pDev->last.remainder[i],
+ lastSlave->valuator->axes + i,
+ pDev->valuator->axes + i, 0);
+ }
+ }
+
+}
+
+/**
+ * Allocate the motion history buffer.
+ */
+void
+AllocateMotionHistory(DeviceIntPtr pDev)
+{
+ int size;
+ if (pDev->valuator->motion)
+ xfree(pDev->valuator->motion);
+
+ if (pDev->valuator->numMotionEvents < 1)
+ return;
+
+ /* An MD must have a motion history size large enough to keep all
+ * potential valuators, plus the respective range of the valuators.
+ * 3 * INT32 for (min_val, max_val, curr_val))
+ */
+ if (IsMaster(pDev))
+ size = sizeof(INT32) * 3 * MAX_VALUATORS;
+ else
+ size = sizeof(INT32) * pDev->valuator->numAxes;
+
+ size += sizeof(Time);
+
+ pDev->valuator->motion = xcalloc(pDev->valuator->numMotionEvents, size);
+ pDev->valuator->first_motion = 0;
+ pDev->valuator->last_motion = 0;
+ if (!pDev->valuator->motion)
+ ErrorF("[dix] %s: Failed to alloc motion history (%d bytes).\n",
+ pDev->name, size * pDev->valuator->numMotionEvents);
+}
+
+/**
+ * Dump the motion history between start and stop into the supplied buffer.
+ * Only records the event for a given screen in theory, but in practice, we
+ * sort of ignore this.
+ *
+ * If core is set, we only generate x/y, in INT16, scaled to screen coords.
+ */
+int
+GetMotionHistory(DeviceIntPtr pDev, xTimecoord **buff, unsigned long start,
+ unsigned long stop, ScreenPtr pScreen, BOOL core)
+{
+ char *ibuff = NULL, *obuff;
+ int i = 0, ret = 0;
+ int j, coord;
+ Time current;
+ /* The size of a single motion event. */
+ int size;
+ int dflt;
+ AxisInfo from, *to; /* for scaling */
+ INT32 *ocbuf, *icbuf; /* pointer to coordinates for copying */
+ INT16 *corebuf;
+ AxisInfo core_axis = {0};
+
+ if (!pDev->valuator || !pDev->valuator->numMotionEvents)
+ return 0;
+
+ if (core && !pScreen)
+ return 0;
+
+ if (IsMaster(pDev))
+ size = (sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(Time);
+ else
+ size = (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
+
+ *buff = xalloc(size * pDev->valuator->numMotionEvents);
+ if (!(*buff))
+ return 0;
+ obuff = (char *)*buff;
+
+ for (i = pDev->valuator->first_motion;
+ i != pDev->valuator->last_motion;
+ i = (i + 1) % pDev->valuator->numMotionEvents) {
+ /* We index the input buffer by which element we're accessing, which
+ * is not monotonic, and the output buffer by how many events we've
+ * written so far. */
+ ibuff = (char *) pDev->valuator->motion + (i * size);
+ memcpy(&current, ibuff, sizeof(Time));
+
+ if (current > stop) {
+ return ret;
+ }
+ else if (current >= start) {
+ if (core)
+ {
+ memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
+
+ icbuf = (INT32*)(ibuff + sizeof(Time));
+ corebuf = (INT16*)(obuff + sizeof(Time));
+
+ /* fetch x coordinate + range */
+ memcpy(&from.min_value, icbuf++, sizeof(INT32));
+ memcpy(&from.max_value, icbuf++, sizeof(INT32));
+ memcpy(&coord, icbuf++, sizeof(INT32));
+
+ /* scale to screen coords */
+ to = &core_axis;
+ to->max_value = pScreen->width;
+ coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->width);
+
+ memcpy(corebuf, &coord, sizeof(INT16));
+ corebuf++;
+
+ /* fetch y coordinate + range */
+ memcpy(&from.min_value, icbuf++, sizeof(INT32));
+ memcpy(&from.max_value, icbuf++, sizeof(INT32));
+ memcpy(&coord, icbuf++, sizeof(INT32));
+
+ to->max_value = pScreen->height;
+ coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, pScreen->height);
+ memcpy(corebuf, &coord, sizeof(INT16));
+
+ } else if (IsMaster(pDev))
+ {
+ memcpy(obuff, ibuff, sizeof(Time)); /* copy timestamp */
+
+ ocbuf = (INT32*)(obuff + sizeof(Time));
+ icbuf = (INT32*)(ibuff + sizeof(Time));
+ for (j = 0; j < MAX_VALUATORS; j++)
+ {
+ if (j >= pDev->valuator->numAxes)
+ break;
+
+ /* fetch min/max/coordinate */
+ memcpy(&from.min_value, icbuf++, sizeof(INT32));
+ memcpy(&from.max_value, icbuf++, sizeof(INT32));
+ memcpy(&coord, icbuf++, sizeof(INT32));
+
+ to = (j < pDev->valuator->numAxes) ? &pDev->valuator->axes[j] : NULL;
+
+ /* x/y scaled to screen if no range is present */
+ if (j == 0 && (from.max_value < from.min_value))
+ from.max_value = pScreen->width;
+ else if (j == 1 && (from.max_value < from.min_value))
+ from.max_value = pScreen->height;
+
+ if (j == 0 && (to->max_value < to->min_value))
+ dflt = pScreen->width;
+ else if (j == 1 && (to->max_value < to->min_value))
+ dflt = pScreen->height;
+ else
+ dflt = 0;
+
+ /* scale from stored range into current range */
+ coord = rescaleValuatorAxis(coord, 0.0, NULL, &from, to, 0);
+ memcpy(ocbuf, &coord, sizeof(INT32));
+ ocbuf++;
+ }
+ } else
+ memcpy(obuff, ibuff, size);
+
+ /* don't advance by size here. size may be different to the
+ * actually written size if the MD has less valuators than MAX */
+ if (core)
+ obuff += sizeof(INT32) + sizeof(Time);
+ else
+ obuff += (sizeof(INT32) * pDev->valuator->numAxes) + sizeof(Time);
+ ret++;
+ }
+ }
+
+ return ret;
+}
+
+
+/**
+ * Update the motion history for a specific device, with the list of
+ * valuators.
+ *
+ * Layout of the history buffer:
+ * for SDs: [time] [val0] [val1] ... [valn]
+ * for MDs: [time] [min_val0] [max_val0] [val0] [min_val1] ... [valn]
+ *
+ * For events that have some valuators unset (first_valuator > 0):
+ * min_val == max_val == val == 0.
+ */
+static void
+updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator,
+ int num_valuators, int *valuators)
+{
+ char *buff = (char *) pDev->valuator->motion;
+ ValuatorClassPtr v;
+ int i;
+
+ if (!pDev->valuator->numMotionEvents)
+ return;
+
+ v = pDev->valuator;
+ if (IsMaster(pDev))
+ {
+ buff += ((sizeof(INT32) * 3 * MAX_VALUATORS) + sizeof(CARD32)) *
+ v->last_motion;
+
+ memcpy(buff, &ms, sizeof(Time));
+ buff += sizeof(Time);
+
+ memset(buff, 0, sizeof(INT32) * 3 * MAX_VALUATORS);
+ buff += 3 * sizeof(INT32) * first_valuator;
+
+ for (i = first_valuator; i < first_valuator + num_valuators; i++)
+ {
+ if (i >= v->numAxes)
+ break;
+ memcpy(buff, &v->axes[i].min_value, sizeof(INT32));
+ buff += sizeof(INT32);
+ memcpy(buff, &v->axes[i].max_value, sizeof(INT32));
+ buff += sizeof(INT32);
+ memcpy(buff, &valuators[i - first_valuator], sizeof(INT32));
+ buff += sizeof(INT32);
+ }
+ } else
+ {
+
+ buff += ((sizeof(INT32) * pDev->valuator->numAxes) + sizeof(CARD32)) *
+ pDev->valuator->last_motion;
+
+ memcpy(buff, &ms, sizeof(Time));
+ buff += sizeof(Time);
+
+ memset(buff, 0, sizeof(INT32) * pDev->valuator->numAxes);
+ buff += sizeof(INT32) * first_valuator;
+
+ memcpy(buff, valuators, sizeof(INT32) * num_valuators);
+ }
+
+ pDev->valuator->last_motion = (pDev->valuator->last_motion + 1) %
+ pDev->valuator->numMotionEvents;
+ /* If we're wrapping around, just keep the circular buffer going. */
+ if (pDev->valuator->first_motion == pDev->valuator->last_motion)
+ pDev->valuator->first_motion = (pDev->valuator->first_motion + 1) %
+ pDev->valuator->numMotionEvents;
+
+ return;
+}
+
+
+/**
+ * Returns the maximum number of events GetKeyboardEvents,
+ * GetKeyboardValuatorEvents, and GetPointerEvents will ever return.
+ *
+ * This MUST be absolutely constant, from init until exit.
+ */
+int
+GetMaximumEventsNum(void) {
+ /* One raw event
+ * One device event
+ * One possible device changed event
+ */
+ return 3;
+}
+
+
+/**
+ * Clip an axis to its bounds, which are declared in the call to
+ * InitValuatorAxisClassStruct.
+ */
+static void
+clipAxis(DeviceIntPtr pDev, int axisNum, int *val)
+{
+ AxisInfoPtr axis;
+
+ if (axisNum >= pDev->valuator->numAxes)
+ return;
+
+ axis = pDev->valuator->axes + axisNum;
+
+ /* If a value range is defined, clip. If not, do nothing */
+ if (axis->max_value <= axis->min_value)
+ return;
+
+ if (*val < axis->min_value)
+ *val = axis->min_value;
+ if (*val > axis->max_value)
+ *val = axis->max_value;
+}
+
+/**
+ * Clip every axis in the list of valuators to its bounds.
+ */
+static void
+clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators,
+ int *valuators)
+{
+ int i;
+
+ for (i = 0; i < num_valuators; i++)
+ clipAxis(pDev, i + first_valuator, &(valuators[i]));
+}
+
+/**
+ * Create the DCCE event (does not update the master's device state yet, this
+ * is done in the event processing).
+ * Pull in the coordinates from the MD if necessary.
+ *
+ * @param events Pointer to a pre-allocated event list.
+ * @param dev The slave device that generated an event.
+ * @param type Either DEVCHANGE_POINTER_EVENT and/or DEVCHANGE_KEYBOARD_EVENT
+ * @param num_events The current number of events, returns the number of
+ * events if a DCCE was generated.
+ * @return The updated @events pointer.
+ */
+static EventListPtr
+updateFromMaster(EventListPtr events, DeviceIntPtr dev, int type, int *num_events)
+{
+ DeviceIntPtr master;
+
+ master = GetMaster(dev, (type & DEVCHANGE_POINTER_EVENT) ? MASTER_POINTER : MASTER_KEYBOARD);
+
+ if (master && master->last.slave != dev)
+ {
+ CreateClassesChangedEvent(events, master, dev, type);
+ updateSlaveDeviceCoords(master, dev);
+ master->last.slave = dev;
+ master->last.numValuators = dev->last.numValuators;
+ (*num_events)++;
+ events++;
+ }
+ return events;
+}
+
+/**
+ * Move the device's pointer to the position given in the valuators.
+ *
+ * @param dev The device which's pointer is to be moved.
+ * @param x Returns the x position of the pointer after the move.
+ * @param y Returns the y position of the pointer after the move.
+ * @param first The first valuator in @valuators
+ * @param num Total number of valuators in @valuators.
+ * @param valuators Valuator data for each axis between @first and
+ * @first+@num.
+ */
+static void
+moveAbsolute(DeviceIntPtr dev, int *x, int *y,
+ int first, int num, int *valuators)
+{
+ int i;
+
+
+ if (num >= 1 && first == 0)
+ *x = *(valuators + 0);
+ else
+ *x = dev->last.valuators[0];
+
+ if (first <= 1 && num >= (2 - first))
+ *y = *(valuators + 1 - first);
+ else
+ *y = dev->last.valuators[1];
+
+ clipAxis(dev, 0, x);
+ clipAxis(dev, 1, y);
+
+ i = (first > 2) ? 0 : 2;
+ for (; i < num; i++)
+ {
+ dev->last.valuators[i + first] = valuators[i];
+ clipAxis(dev, i, &dev->last.valuators[i + first]);
+ }
+}
+
+/**
+ * Move the device's pointer by the values given in @valuators.
+ *
+ * @param dev The device which's pointer is to be moved.
+ * @param x Returns the x position of the pointer after the move.
+ * @param y Returns the y position of the pointer after the move.
+ * @param first The first valuator in @valuators
+ * @param num Total number of valuators in @valuators.
+ * @param valuators Valuator data for each axis between @first and
+ * @first+@num.
+ */
+static void
+moveRelative(DeviceIntPtr dev, int *x, int *y,
+ int first, int num, int *valuators)
+{
+ int i;
+
+ *x = dev->last.valuators[0];
+ *y = dev->last.valuators[1];
+
+ if (num >= 1 && first == 0)
+ *x += *(valuators +0);
+
+ if (first <= 1 && num >= (2 - first))
+ *y += *(valuators + 1 - first);
+
+ /* if attached, clip both x and y to the defined limits (usually
+ * co-ord space limit). If it is attached, we need x/y to go over the
+ * limits to be able to change screens. */
+ if(dev->u.master) {
+ clipAxis(dev, 0, x);
+ clipAxis(dev, 1, y);
+ }
+
+ /* calc other axes, clip, drop back into valuators */
+ i = (first > 2) ? 0 : 2;
+ for (; i < num; i++)
+ {
+ dev->last.valuators[i + first] += valuators[i];
+ clipAxis(dev, i, &dev->last.valuators[i + first]);
+ valuators[i] = dev->last.valuators[i + first];
+ }
+}
+
+/**
+ * Accelerate the data in valuators based on the device's acceleration scheme.
+ *
+ * @param dev The device which's pointer is to be moved.
+ * @param first The first valuator in @valuators
+ * @param num Total number of valuators in @valuators.
+ * @param valuators Valuator data for each axis between @first and
+ * @first+@num.
+ * @param ms Current time.
+ */
+static void
+accelPointer(DeviceIntPtr dev, int first, int num, int *valuators, CARD32 ms)
+{
+ if (dev->valuator->accelScheme.AccelSchemeProc)
+ dev->valuator->accelScheme.AccelSchemeProc(dev, first, num, valuators, ms);
+}
+
+/**
+ * If we have HW cursors, this actually moves the visible sprite. If not, we
+ * just do all the screen crossing, etc.
+ *
+ * We scale from device to screen coordinates here, call
+ * miPointerSetPosition() and then scale back into device coordinates (if
+ * needed). miPSP will change x/y if the screen was crossed.
+ *
+ * @param dev The device to be moved.
+ * @param x Pointer to current x-axis value, may be modified.
+ * @param y Pointer to current y-axis value, may be modified.
+ * @param x_frac Fractional part of current x-axis value, may be modified.
+ * @param y_frac Fractional part of current y-axis value, may be modified.
+ * @param scr Screen the device's sprite is currently on.
+ * @param screenx Screen x coordinate the sprite is on after the update.
+ * @param screeny Screen y coordinate the sprite is on after the update.
+ * @param screenx_frac Fractional part of screen x coordinate, as above.
+ * @param screeny_frac Fractional part of screen y coordinate, as above.
+ */
+static void
+positionSprite(DeviceIntPtr dev, int *x, int *y, float x_frac, float y_frac,
+ ScreenPtr scr, int *screenx, int *screeny, float *screenx_frac, float *screeny_frac)
+{
+ int old_screenx, old_screeny;
+
+ /* scale x&y to screen */
+ if (dev->valuator->numAxes > 0) {
+ *screenx = rescaleValuatorAxis(*x, x_frac, screenx_frac,
+ dev->valuator->axes + 0, NULL, scr->width);
+ } else {
+ *screenx = dev->last.valuators[0];
+ *screenx_frac = dev->last.remainder[0];
+ }
+
+ if (dev->valuator->numAxes > 1) {
+ *screeny = rescaleValuatorAxis(*y, y_frac, screeny_frac,
+ dev->valuator->axes + 1, NULL, scr->height);
+ } else {
+ *screeny = dev->last.valuators[1];
+ *screeny_frac = dev->last.remainder[1];
+ }
+
+ /* Hit the left screen edge? */
+ if (*screenx <= 0 && *screenx_frac < 0.0f)
+ {
+ *screenx_frac = 0.0f;
+ x_frac = 0.0f;
+ }
+ if (*screeny <= 0 && *screeny_frac < 0.0f)
+ {
+ *screeny_frac = 0.0f;
+ y_frac = 0.0f;
+ }
+
+
+ old_screenx = *screenx;
+ old_screeny = *screeny;
+ /* This takes care of crossing screens for us, as well as clipping
+ * to the current screen. */
+ miPointerSetPosition(dev, screenx, screeny);
+
+ if (dev->u.master) {
+ dev->u.master->last.valuators[0] = *screenx;
+ dev->u.master->last.valuators[1] = *screeny;
+ dev->u.master->last.remainder[0] = *screenx_frac;
+ dev->u.master->last.remainder[1] = *screeny_frac;
+ }
+
+ /* Crossed screen? Scale back to device coordiantes */
+ if(*screenx != old_screenx)
+ {
+ scr = miPointerGetScreen(dev);
+ *x = rescaleValuatorAxis(*screenx, *screenx_frac, &x_frac, NULL,
+ dev->valuator->axes + 0, scr->width);
+ }
+ if(*screeny != old_screeny)
+ {
+ scr = miPointerGetScreen(dev);
+ *y = rescaleValuatorAxis(*screeny, *screeny_frac, &y_frac, NULL,
+ dev->valuator->axes + 1, scr->height);
+ }
+
+ /* dropy x/y (device coordinates) back into valuators for next event */
+ dev->last.valuators[0] = *x;
+ dev->last.valuators[1] = *y;
+ dev->last.remainder[0] = x_frac;
+ dev->last.remainder[1] = y_frac;
+}
+
+/**
+ * Update the motion history for the device and (if appropriate) for its
+ * master device.
+ * @param dev Slave device to update.
+ * @param first First valuator to append to history.
+ * @param num Total number of valuators to append to history.
+ * @param ms Current time
+ */
+static void
+updateHistory(DeviceIntPtr dev, int first, int num, CARD32 ms)
+{
+ updateMotionHistory(dev, ms, first, num, &dev->last.valuators[first]);
+ if (dev->u.master)
+ {
+ DeviceIntPtr master = GetMaster(dev, MASTER_POINTER);
+ updateMotionHistory(master, ms, first, num, &dev->last.valuators[first]);
+ }
+}
+
+/**
+ * Convenience wrapper around GetKeyboardValuatorEvents, that takes no
+ * valuators.
+ */
+int
+GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) {
+ return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL);
+}
+
+
+/**
+ * Returns a set of keyboard events for KeyPress/KeyRelease, optionally
+ * also with valuator events. Handles Xi and XKB.
+ *
+ * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
+ * event (ProcessOtherEvent).
+ *
+ * events is not NULL-terminated; the return value is the number of events.
+ * The DDX is responsible for allocating the event structure in the first
+ * place via GetMaximumEventsNum(), and for freeing it.
+ *
+ * This function does not change the core keymap to that of the device;
+ * that is done by SwitchCoreKeyboard, which is called from
+ * mieqProcessInputEvents. If replacing that function, take care to call
+ * SetCoreKeyboard before processInputProc, so keymaps are altered to suit.
+ */
+int
+GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type,
+ int key_code, int first_valuator,
+ int num_valuators, int *valuators) {
+ int num_events = 0;
+ CARD32 ms = 0;
+ DeviceEvent *event;
+ RawDeviceEvent *raw;
+
+ /* refuse events from disabled devices */
+ if (!pDev->enabled)
+ return 0;
+
+ if (!events ||!pDev->key || !pDev->focus || !pDev->kbdfeed ||
+ (type != KeyPress && type != KeyRelease) ||
+ (key_code < 8 || key_code > 255))
+ return 0;
+
+ num_events = 1;
+
+ events = updateFromMaster(events, pDev, DEVCHANGE_KEYBOARD_EVENT, &num_events);
+
+ /* Handle core repeating, via press/release/press/release. */
+ if (type == KeyPress && key_is_down(pDev, key_code, KEY_POSTED)) {
+ /* If autorepeating is disabled either globally or just for that key,
+ * or we have a modifier, don't generate a repeat event. */
+ if (!pDev->kbdfeed->ctrl.autoRepeat ||
+ !key_autorepeats(pDev, key_code) ||
+ pDev->key->xkbInfo->desc->map->modmap[key_code])
+ return 0;
+ }
+
+ ms = GetTimeInMillis();
+
+ raw = (RawDeviceEvent*)events->event;
+ events++;
+ num_events++;
+
+ init_raw(pDev, raw, ms, type, key_code);
+ set_raw_valuators(raw, first_valuator, num_valuators, valuators,
+ raw->valuators.data_raw);
+
+ if (num_valuators)
+ clipValuators(pDev, first_valuator, num_valuators, valuators);
+
+ set_raw_valuators(raw, first_valuator, num_valuators, valuators,
+ raw->valuators.data);
+
+ event = (DeviceEvent*) events->event;
+ init_event(pDev, event, ms);
+ event->detail.key = key_code;
+
+ if (type == KeyPress) {
+ event->type = ET_KeyPress;
+ set_key_down(pDev, key_code, KEY_POSTED);
+ }
+ else if (type == KeyRelease) {
+ event->type = ET_KeyRelease;
+ set_key_up(pDev, key_code, KEY_POSTED);
+ }
+
+ if (num_valuators)
+ clipValuators(pDev, first_valuator, num_valuators, valuators);
+
+ set_valuators(pDev, event, first_valuator, num_valuators, valuators);
+
+ return num_events;
+}
+
+/**
+ * Initialize an event list and fill with 32 byte sized events.
+ * This event list is to be passed into GetPointerEvents() and
+ * GetKeyboardEvents().
+ *
+ * @param num_events Number of elements in list.
+ */
+EventListPtr
+InitEventList(int num_events)
+{
+ EventListPtr events;
+ int i;
+
+ events = (EventListPtr)xcalloc(num_events, sizeof(EventList));
+ if (!events)
+ return NULL;
+
+ for (i = 0; i < num_events; i++)
+ {
+ events[i].evlen = sizeof(InternalEvent);
+ events[i].event = xcalloc(1, sizeof(InternalEvent));
+ if (!events[i].event)
+ {
+ /* rollback */
+ while(i--)
+ xfree(events[i].event);
+ xfree(events);
+ events = NULL;
+ break;
+ }
+ }
+
+ return events;
+}
+
+/**
+ * Free an event list.
+ *
+ * @param list The list to be freed.
+ * @param num_events Number of elements in list.
+ */
+void
+FreeEventList(EventListPtr list, int num_events)
+{
+ if (!list)
+ return;
+ while(num_events--)
+ xfree(list[num_events].event);
+ xfree(list);
+}
+
+/**
+ * Generate a series of xEvents (filled into the EventList) representing
+ * pointer motion, or button presses. Xi and XKB-aware.
+ *
+ * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the
+ * event (ProcessOtherEvent).
+ *
+ * events is not NULL-terminated; the return value is the number of events.
+ * The DDX is responsible for allocating the event structure in the first
+ * place via InitEventList() and GetMaximumEventsNum(), and for freeing it.
+ *
+ * In the generated events rootX/Y will be in absolute screen coords and
+ * the valuator information in the absolute or relative device coords.
+ *
+ * last.valuators[x] of the device is always in absolute device coords.
+ * last.valuators[x] of the master device is in absolute screen coords.
+ *
+ * master->last.valuators[x] for x > 2 is undefined.
+ */
+int
+GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons,
+ int flags, int first_valuator, int num_valuators,
+ int *valuators) {
+ int num_events = 1;
+ CARD32 ms;
+ DeviceEvent *event;
+ RawDeviceEvent *raw;
+ int x = 0, y = 0, /* device coords */
+ cx, cy; /* only screen coordinates */
+ float x_frac = 0.0, y_frac = 0.0, cx_frac, cy_frac;
+ ScreenPtr scr = miPointerGetScreen(pDev);
+
+ /* refuse events from disabled devices */
+ if (!pDev->enabled)
+ return 0;
+
+ ms = GetTimeInMillis(); /* before pointer update to help precision */
+
+ if (!scr || !pDev->valuator || first_valuator < 0 ||
+ ((num_valuators + first_valuator) > pDev->valuator->numAxes) ||
+ (type != MotionNotify && type != ButtonPress && type != ButtonRelease) ||
+ (type != MotionNotify && !pDev->button) ||
+ ((type == ButtonPress || type == ButtonRelease) && !buttons) ||
+ (type == MotionNotify && num_valuators <= 0))
+ return 0;
+
+ events = updateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
+
+ raw = (RawDeviceEvent*)events->event;
+ events++;
+ num_events++;
+
+ init_raw(pDev, raw, ms, type, buttons);
+ set_raw_valuators(raw, first_valuator, num_valuators, valuators,
+ raw->valuators.data_raw);
+
+ if (flags & POINTER_ABSOLUTE)
+ {
+ if (flags & POINTER_SCREEN) /* valuators are in screen coords */
+ {
+
+ if (num_valuators >= 1 && first_valuator == 0)
+ valuators[0] = rescaleValuatorAxis(valuators[0], 0.0, &x_frac, NULL,
+ pDev->valuator->axes + 0,
+ scr->width);
+ if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
+ valuators[1 - first_valuator] = rescaleValuatorAxis(valuators[1 - first_valuator], 0.0, &y_frac, NULL,
+ pDev->valuator->axes + 1,
+ scr->height);
+ }
+
+ moveAbsolute(pDev, &x, &y, first_valuator, num_valuators, valuators);
+ } else {
+ if (flags & POINTER_ACCELERATE) {
+ accelPointer(pDev, first_valuator, num_valuators, valuators, ms);
+ /* The pointer acceleration code modifies the fractional part
+ * in-place, so we need to extract this information first */
+ x_frac = pDev->last.remainder[0];
+ y_frac = pDev->last.remainder[1];
+ }
+ moveRelative(pDev, &x, &y, first_valuator, num_valuators, valuators);
+ }
+
+ set_raw_valuators(raw, first_valuator, num_valuators, valuators,
+ raw->valuators.data);
+
+ positionSprite(pDev, &x, &y, x_frac, y_frac, scr, &cx, &cy, &cx_frac, &cy_frac);
+ updateHistory(pDev, first_valuator, num_valuators, ms);
+
+ /* Update the valuators with the true value sent to the client*/
+ if (num_valuators >= 1 && first_valuator == 0)
+ valuators[0] = x;
+ if (first_valuator <= 1 && num_valuators >= (2 - first_valuator))
+ valuators[1 - first_valuator] = y;
+
+ if (num_valuators)
+ clipValuators(pDev, first_valuator, num_valuators, valuators);
+
+ event = (DeviceEvent*) events->event;
+ init_event(pDev, event, ms);
+
+ if (type == MotionNotify) {
+ event->type = ET_Motion;
+ event->detail.button = 0;
+ }
+ else {
+ if (type == ButtonPress) {
+ event->type = ET_ButtonPress;
+ pDev->button->postdown[buttons >> 3] |= (1 << (buttons & 7));
+ }
+ else if (type == ButtonRelease) {
+ event->type = ET_ButtonRelease;
+ pDev->button->postdown[buttons >> 3] &= ~(1 << (buttons & 7));
+ }
+ event->detail.button = buttons;
+ }
+
+ event->root_x = cx; /* root_x/y always in screen coords */
+ event->root_y = cy;
+ event->root_x_frac = cx_frac;
+ event->root_y_frac = cy_frac;
+
+ set_valuators(pDev, event, first_valuator, num_valuators, valuators);
+
+ return num_events;
+}
+
+
+/**
+ * Post ProximityIn/ProximityOut events, accompanied by valuators.
+ *
+ * events is not NULL-terminated; the return value is the number of events.
+ * The DDX is responsible for allocating the event structure in the first
+ * place via GetMaximumEventsNum(), and for freeing it.
+ */
+int
+GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type,
+ int first_valuator, int num_valuators, int *valuators)
+{
+ int num_events = 1;
+ DeviceEvent *event;
+
+ /* refuse events from disabled devices */
+ if (!pDev->enabled)
+ return 0;
+
+ /* Sanity checks. */
+ if (type != ProximityIn && type != ProximityOut)
+ return 0;
+ if (!pDev->valuator)
+ return 0;
+ /* Do we need to send a DeviceValuator event? */
+ if ((pDev->valuator->mode & 1) == Relative)
+ num_valuators = 0;
+
+ /* You fail. */
+ if (first_valuator < 0 ||
+ (num_valuators + first_valuator) > pDev->valuator->numAxes)
+ return 0;
+
+ events = updateFromMaster(events, pDev, DEVCHANGE_POINTER_EVENT, &num_events);
+
+ event = (DeviceEvent *) events->event;
+ init_event(pDev, event, GetTimeInMillis());
+ event->type = (type == ProximityIn) ? ET_ProximityIn : ET_ProximityOut;
+
+ if (num_valuators)
+ clipValuators(pDev, first_valuator, num_valuators, valuators);
+
+ set_valuators(pDev, event, first_valuator, num_valuators, valuators);
+
+ return num_events;
+}
+
+/**
+ * Synthesize a single motion event for the core pointer.
+ *
+ * Used in cursor functions, e.g. when cursor confinement changes, and we need
+ * to shift the pointer to get it inside the new bounds.
+ */
+void
+PostSyntheticMotion(DeviceIntPtr pDev,
+ int x,
+ int y,
+ int screen,
+ unsigned long time)
+{
+ DeviceEvent ev;
+
+#ifdef PANORAMIX
+ /* Translate back to the sprite screen since processInputProc
+ will translate from sprite screen to screen 0 upon reentry
+ to the DIX layer. */
+ if (!noPanoramiXExtension) {
+ x += panoramiXdataPtr[0].x - panoramiXdataPtr[screen].x;
+ y += panoramiXdataPtr[0].y - panoramiXdataPtr[screen].y;
+ }
+#endif
+
+ memset(&ev, 0, sizeof(DeviceEvent));
+ init_event(pDev, &ev, time);
+ ev.root_x = x;
+ ev.root_y = y;
+ ev.type = ET_Motion;
+ ev.time = time;
+
+ /* FIXME: MD/SD considerations? */
+ (*pDev->public.processInputProc)((InternalEvent*)&ev, pDev);
+}
diff --git a/xorg-server/dix/main.c b/xorg-server/dix/main.c
index f96245a4b..fa65a4051 100644
--- a/xorg-server/dix/main.c
+++ b/xorg-server/dix/main.c
@@ -116,6 +116,10 @@ Equipment Corporation.
#include "dpmsproc.h"
#endif
+#ifdef _DEBUG
+#include <crtdbg.h>
+#endif
+
extern void Dispatch(void);
extern void InitProcVectors(void);
@@ -134,9 +138,43 @@ int main(int argc, char *argv[], char *envp[])
{
int i;
HWEventQueueType alwaysCheckForInput[2];
-
+ #ifdef _DEBUG
+ //int TmpFlag=_CrtSetDbgFlag( _CRTDBG_REPORT_FLAG);
+
+ //TmpFlag|=_CRTDBG_ALLOC_MEM_DF;
+ //TmpFlag|=_CRTDBG_DELAY_FREE_MEM_DF;
+ //TmpFlag|=_CRTDBG_CHECK_ALWAYS_DF;
+ //TmpFlag|=_CRTDBG_CHECK_CRT_DF;
+ //TmpFlag|=_CRTDBG_LEAK_CHECK_DF;
+
+ //_CrtSetDbgFlag(TmpFlag);
+ #endif
+
+ ptw32_processInitialize();
display = "0";
+ #ifdef WIN32
+ /* In Win32 we have different threads call Xlib functions (depending
+ on the commandline options given).
+ XInitThreads has to be called before
+ any xlib function is called (aoccording to the man page) */
+ XInitThreads();
+ /* change the current directory to the directory where the vcxsrv.exe executable is installed.
+ This is needed because the font directories are relative to the current directory.
+ */
+ {
+ char ModuleFilename[MAX_PATH];
+ char *pSlash;
+ GetModuleFileName(NULL,ModuleFilename,sizeof(ModuleFilename));
+ pSlash=strrchr(ModuleFilename,'\\');
+ if (pSlash)
+ {
+ *pSlash='\0';
+ chdir(ModuleFilename);
+ }
+ }
+ #endif
+
InitRegions();
pixman_disable_out_of_bounds_workaround();
@@ -307,6 +345,7 @@ int main(int argc, char *argv[], char *envp[])
memset(WindowTable, 0, sizeof(WindowTable));
CloseDownDevices();
+ InputDevicesClosed();
CloseDownEvents();
for (i = screenInfo.numScreens - 1; i >= 0; i--)
diff --git a/xorg-server/dix/makefile b/xorg-server/dix/makefile
new file mode 100644
index 000000000..01e98d638
--- /dev/null
+++ b/xorg-server/dix/makefile
@@ -0,0 +1,40 @@
+ifeq ($(DEBUG),1)
+DEFINES += FONTDEBUG XSERVER_DTRACE
+endif
+
+LIBRARY=libdix
+
+CSRCS=\
+ atom.c \
+ colormap.c \
+ cursor.c \
+ deprecated.c \
+ devices.c \
+ dispatch.c \
+ dixfonts.c \
+ dixutils.c \
+ enterleave.c \
+ events.c \
+ eventconvert.c \
+ extension.c \
+ ffs.c \
+ gc.c \
+ getevents.c \
+ globals.c \
+ glyphcurs.c \
+ grabs.c \
+ initatoms.c \
+ inpututils.c \
+ main.c \
+ pixmap.c \
+ privates.c \
+ property.c \
+ ptrveloc.c \
+ registry.c \
+ resource.c \
+ selection.c \
+ swaprep.c \
+ swapreq.c \
+ tables.c \
+ window.c
+
diff --git a/xorg-server/dix/ptrveloc.c b/xorg-server/dix/ptrveloc.c
index 37c8e5178..55cdb46c4 100644
--- a/xorg-server/dix/ptrveloc.c
+++ b/xorg-server/dix/ptrveloc.c
@@ -26,6 +26,10 @@
#include <dix-config.h>
#endif
+#ifdef _MSC_VER
+#define _USE_MATH_DEFINES
+#endif
+
#include <math.h>
#include <ptrveloc.h>
#include <exevents.h>
@@ -59,6 +63,11 @@
*
****************************************************************************/
+#ifdef _MSC_VER
+#define inline __inline
+#define lrintf(val) ((int)val)
+#endif
+
/* fwds */
int
SetAccelerationProfile(DeviceVelocityPtr vel, int profile_num);
diff --git a/xorg-server/dix/registry.c b/xorg-server/dix/registry.c
index ec853b37f..9aa73d11d 100644
--- a/xorg-server/dix/registry.c
+++ b/xorg-server/dix/registry.c
@@ -25,6 +25,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include <stdlib.h>
#include <string.h>
+#include <unistd.h>
#include <X11/X.h>
#include <X11/Xproto.h>
#include "resource.h"