aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--xorg-server/Xext/xf86bigfont.c1528
-rw-r--r--xorg-server/Xi/extinit.c2621
-rw-r--r--xorg-server/Xi/xiproperty.c2717
-rw-r--r--xorg-server/Xi/xiproperty.h133
-rw-r--r--xorg-server/dix/dispatch.c26
-rw-r--r--xorg-server/dix/dixutils.c1786
-rw-r--r--xorg-server/glx/xfont.c397
-rw-r--r--xorg-server/hw/dmx/dmxpict.c2630
-rw-r--r--xorg-server/hw/xquartz/bundle/Makefile.am176
-rw-r--r--xorg-server/include/dix.h1198
-rw-r--r--xorg-server/include/os.h1074
-rw-r--r--xorg-server/include/xkbsrv.h2
-rw-r--r--xorg-server/mi/miarc.c7284
-rw-r--r--xorg-server/os/access.c4404
-rw-r--r--xorg-server/os/auth.c679
-rw-r--r--xorg-server/os/mitauth.c394
-rw-r--r--xorg-server/os/osdep.h23
-rw-r--r--xorg-server/os/rpcauth.c386
-rw-r--r--xorg-server/os/xdmauth.c998
-rw-r--r--xorg-server/os/xdmcp.c3332
-rw-r--r--xorg-server/render/picture.c3642
-rw-r--r--xorg-server/render/picturestr.h1390
-rw-r--r--xorg-server/render/render.c131
-rw-r--r--xorg-server/xfixes/region.c1712
-rw-r--r--xorg-server/xkbdata.src/Makefile.am36
-rw-r--r--xorg-server/xkbdata.src/configure.in195
-rw-r--r--xorg-server/xkbdata.src/rules/base.xml.in17
-rw-r--r--xorg-server/xkbdata.src/symbols/Makefile.am6
-rw-r--r--xorg-server/xkbdata.src/symbols/ara14
-rw-r--r--xorg-server/xkbdata.src/symbols/bw19
-rw-r--r--xorg-server/xkbdata.src/symbols/de1010
-rw-r--r--xorg-server/xkbdata.src/symbols/ke37
-rw-r--r--xorg-server/xkbdata.src/symbols/level5283
-rw-r--r--xorg-server/xkbdata.src/xkeyboard-config.pc.in8
34 files changed, 20126 insertions, 20162 deletions
diff --git a/xorg-server/Xext/xf86bigfont.c b/xorg-server/Xext/xf86bigfont.c
index a4eb3f659..8e8d460e5 100644
--- a/xorg-server/Xext/xf86bigfont.c
+++ b/xorg-server/Xext/xf86bigfont.c
@@ -1,769 +1,759 @@
-/*
- * BIGFONT extension for sharing font metrics between clients (if possible)
- * and for transmitting font metrics to clients in a compressed form.
- *
- * Copyright (c) 1999-2000 Bruno Haible
- * Copyright (c) 1999-2000 The XFree86 Project, Inc.
- */
-
-/* THIS IS NOT AN X CONSORTIUM STANDARD */
-
-/*
- * Big fonts suffer from the following: All clients that have opened a
- * font can access the complete glyph metrics array (the XFontStruct member
- * `per_char') directly, without going through a macro. Moreover these
- * glyph metrics are ink metrics, i.e. are not redundant even for a
- * fixed-width font. For a Unicode font, the size of this array is 768 KB.
- *
- * Problems: 1. It eats a lot of memory in each client. 2. All this glyph
- * metrics data is piped through the socket when the font is opened.
- *
- * This extension addresses these two problems for local clients, by using
- * shared memory. It also addresses the second problem for non-local clients,
- * by compressing the data before transmit by a factor of nearly 6.
- *
- * If you use this extension, your OS ought to nicely support shared memory.
- * This means: Shared memory should be swappable to the swap, and the limits
- * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB,
- * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls
- * on segments that have already been marked "removed", because it permits
- * these segments to be cleaned up by the OS if the X server is killed with
- * signal SIGKILL.
- *
- * This extension is transparently exploited by Xlib (functions XQueryFont,
- * XLoadQueryFont).
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <sys/types.h>
-#ifdef HAS_SHM
-#if defined(linux) && (!defined(__GNU_LIBRARY__) || __GNU_LIBRARY__ < 2)
-/* libc4 does not define __GNU_LIBRARY__, libc5 defines __GNU_LIBRARY__ as 1 */
-/* Linux libc4 and libc5 only (because glibc doesn't include kernel headers):
- Linux 2.0.x and 2.2.x define SHMLBA as PAGE_SIZE, but forget to define
- PAGE_SIZE. It is defined in <asm/page.h>. */
-#include <asm/page.h>
-#endif
-#ifdef SVR4
-#include <sys/sysmacros.h>
-#endif
-#if defined(__CYGWIN__) || defined(__SCO__)
-#include <sys/param.h>
-#include <sys/sysmacros.h>
-#endif
-#include <sys/ipc.h>
-#include <sys/shm.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <time.h>
-#include <errno.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "os.h"
-#include "dixstruct.h"
-#include "gcstruct.h"
-#include "dixfontstr.h"
-#include "extnsionst.h"
-#include "protocol-versions.h"
-
-#include <X11/extensions/xf86bigfproto.h>
-#include "xf86bigfontsrv.h"
-
-static void XF86BigfontResetProc(
- ExtensionEntry * /* extEntry */
- );
-
-static DISPATCH_PROC(ProcXF86BigfontDispatch);
-static DISPATCH_PROC(ProcXF86BigfontQueryVersion);
-static DISPATCH_PROC(ProcXF86BigfontQueryFont);
-static DISPATCH_PROC(SProcXF86BigfontDispatch);
-static DISPATCH_PROC(SProcXF86BigfontQueryVersion);
-static DISPATCH_PROC(SProcXF86BigfontQueryFont);
-
-#ifdef HAS_SHM
-
-/* A random signature, transmitted to the clients so they can verify that the
- shared memory segment they are attaching to was really established by the
- X server they are talking to. */
-static CARD32 signature;
-
-/* Index for additional information stored in a FontRec's devPrivates array. */
-static int FontShmdescIndex;
-
-static unsigned int pagesize;
-
-static Bool badSysCall = FALSE;
-
-#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
-
-#include <sys/signal.h>
-
-static void
-SigSysHandler(
- int signo)
-{
- badSysCall = TRUE;
-}
-
-static Bool
-CheckForShmSyscall(void)
-{
- void (*oldHandler)(int);
- int shmid = -1;
-
- /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
- oldHandler = signal(SIGSYS, SigSysHandler);
-
- badSysCall = FALSE;
- shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
- if (shmid != -1)
- {
- /* Successful allocation - clean up */
- shmctl(shmid, IPC_RMID, NULL);
- }
- else
- {
- /* Allocation failed */
- badSysCall = TRUE;
- }
- signal(SIGSYS, oldHandler);
- return (!badSysCall);
-}
-
-#define MUST_CHECK_FOR_SHM_SYSCALL
-
-#endif
-
-#endif
-
-void
-XFree86BigfontExtensionInit(void)
-{
- if (AddExtension(XF86BIGFONTNAME,
- XF86BigfontNumberEvents,
- XF86BigfontNumberErrors,
- ProcXF86BigfontDispatch,
- SProcXF86BigfontDispatch,
- XF86BigfontResetProc,
- StandardMinorOpcode)) {
-#ifdef HAS_SHM
-#ifdef MUST_CHECK_FOR_SHM_SYSCALL
- /*
- * Note: Local-clients will not be optimized without shared memory
- * support. Remote-client optimization does not depend on shared
- * memory support. Thus, the extension is still registered even
- * when shared memory support is not functional.
- */
- if (!CheckForShmSyscall()) {
- ErrorF(XF86BIGFONTNAME " extension local-client optimization disabled due to lack of shared memory support in the kernel\n");
- return;
- }
-#endif
-
- srand((unsigned int) time(NULL));
- signature = ((unsigned int) (65536.0/(RAND_MAX+1.0) * rand()) << 16)
- + (unsigned int) (65536.0/(RAND_MAX+1.0) * rand());
- /* fprintf(stderr, "signature = 0x%08X\n", signature); */
-
- FontShmdescIndex = AllocateFontPrivateIndex();
-
-#if !defined(CSRG_BASED) && !defined(__CYGWIN__)
- pagesize = SHMLBA;
-#else
-# ifdef _SC_PAGESIZE
- pagesize = sysconf(_SC_PAGESIZE);
-# else
- pagesize = getpagesize();
-# endif
-#endif
-#endif
- }
-}
-
-
-/* ========== Management of shared memory segments ========== */
-
-#ifdef HAS_SHM
-
-#ifdef __linux__
-/* On Linux, shared memory marked as "removed" can still be attached.
- Nice feature, because the kernel will automatically free the associated
- storage when the server and all clients are gone. */
-#define EARLY_REMOVE
-#endif
-
-typedef struct _ShmDesc {
- struct _ShmDesc *next;
- struct _ShmDesc **prev;
- int shmid;
- char *attach_addr;
-} ShmDescRec, *ShmDescPtr;
-
-static ShmDescPtr ShmList = (ShmDescPtr) NULL;
-
-static ShmDescPtr
-shmalloc(
- unsigned int size)
-{
- ShmDescPtr pDesc;
- int shmid;
- char *addr;
-
-#ifdef MUST_CHECK_FOR_SHM_SYSCALL
- if (pagesize == 0)
- return (ShmDescPtr) NULL;
-#endif
-
- /* On some older Linux systems, the number of shared memory segments
- system-wide is 127. In Linux 2.4, it is 4095.
- Therefore there is a tradeoff to be made between allocating a
- shared memory segment on one hand, and allocating memory and piping
- the glyph metrics on the other hand. If the glyph metrics size is
- small, we prefer the traditional way. */
- if (size < 3500)
- return (ShmDescPtr) NULL;
-
- pDesc = xalloc(sizeof(ShmDescRec));
- if (!pDesc)
- return (ShmDescPtr) NULL;
-
- size = (size + pagesize-1) & -pagesize;
- shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
- if (shmid == -1) {
- ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n",
- size, strerror(errno));
- xfree(pDesc);
- return (ShmDescPtr) NULL;
- }
-
- if ((addr = shmat(shmid, 0, 0)) == (char *)-1) {
- ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n",
- size, strerror(errno));
- shmctl(shmid, IPC_RMID, (void *) 0);
- xfree(pDesc);
- return (ShmDescPtr) NULL;
- }
-
-#ifdef EARLY_REMOVE
- shmctl(shmid, IPC_RMID, (void *) 0);
-#endif
-
- pDesc->shmid = shmid;
- pDesc->attach_addr = addr;
- if (ShmList) ShmList->prev = &pDesc->next;
- pDesc->next = ShmList;
- pDesc->prev = &ShmList;
- ShmList = pDesc;
-
- return pDesc;
-}
-
-static void
-shmdealloc(
- ShmDescPtr pDesc)
-{
-#ifndef EARLY_REMOVE
- shmctl(pDesc->shmid, IPC_RMID, (void *) 0);
-#endif
- shmdt(pDesc->attach_addr);
-
- if (pDesc->next) pDesc->next->prev = pDesc->prev;
- *pDesc->prev = pDesc->next;
- xfree(pDesc);
-}
-
-#endif
-
-/* Called when a font is closed. */
-void
-XF86BigfontFreeFontShm(
- FontPtr pFont)
-{
-#ifdef HAS_SHM
- ShmDescPtr pDesc;
-
- /* If during shutdown of the server, XF86BigfontCleanup() has already
- * called shmdealloc() for all segments, we don't need to do it here.
- */
- if (!ShmList)
- return;
-
- pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
- if (pDesc)
- shmdealloc(pDesc);
-#endif
-}
-
-/* Called upon fatal signal. */
-void
-XF86BigfontCleanup(void)
-{
-#ifdef HAS_SHM
- while (ShmList)
- shmdealloc(ShmList);
-#endif
-}
-
-/* Called when a server generation dies. */
-static void
-XF86BigfontResetProc(
- ExtensionEntry* extEntry)
-{
- /* This function is normally called from CloseDownExtensions(), called
- * from main(). It will be followed by a call to FreeAllResources(),
- * which will call XF86BigfontFreeFontShm() for each font. Thus it
- * appears that we do not need to do anything in this function. --
- * But I prefer to write robust code, and not keep shared memory lying
- * around when it's not needed any more. (Someone might close down the
- * extension without calling FreeAllResources()...)
- */
- XF86BigfontCleanup();
-}
-
-
-/* ========== Handling of extension specific requests ========== */
-
-static int
-ProcXF86BigfontQueryVersion(
- ClientPtr client)
-{
- xXF86BigfontQueryVersionReply reply;
-
- REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq);
- reply.type = X_Reply;
- reply.length = 0;
- reply.sequenceNumber = client->sequence;
- reply.majorVersion = SERVER_XF86BIGFONT_MAJOR_VERSION;
- reply.minorVersion = SERVER_XF86BIGFONT_MINOR_VERSION;
- reply.uid = geteuid();
- reply.gid = getegid();
-#ifdef HAS_SHM
- reply.signature = signature;
-#else
- reply.signature = 0; /* This is redundant. Avoids uninitialized memory. */
-#endif
- reply.capabilities =
-#ifdef HAS_SHM
- (LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0)
-#else
- 0
-#endif
- ; /* may add more bits here in future versions */
- if (client->swapped) {
- char tmp;
- swaps(&reply.sequenceNumber, tmp);
- swapl(&reply.length, tmp);
- swaps(&reply.majorVersion, tmp);
- swaps(&reply.minorVersion, tmp);
- swapl(&reply.uid, tmp);
- swapl(&reply.gid, tmp);
- swapl(&reply.signature, tmp);
- }
- WriteToClient(client,
- sizeof(xXF86BigfontQueryVersionReply), (char *)&reply);
- return client->noClientException;
-}
-
-static void
-swapCharInfo(
- xCharInfo *pCI)
-{
- char tmp;
-
- swaps(&pCI->leftSideBearing, tmp);
- swaps(&pCI->rightSideBearing, tmp);
- swaps(&pCI->characterWidth, tmp);
- swaps(&pCI->ascent, tmp);
- swaps(&pCI->descent, tmp);
- swaps(&pCI->attributes, tmp);
-}
-
-/* static CARD32 hashCI (xCharInfo *p); */
-#define hashCI(p) \
- (CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \
- (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \
- (p->characterWidth << 16) + \
- (p->ascent << 11) + (p->descent << 6)) ^ p->attributes)
-
-static int
-ProcXF86BigfontQueryFont(
- ClientPtr client)
-{
- FontPtr pFont;
- REQUEST(xXF86BigfontQueryFontReq);
- CARD32 stuff_flags;
- xCharInfo* pmax;
- xCharInfo* pmin;
- int nCharInfos;
- int shmid;
-#ifdef HAS_SHM
- ShmDescPtr pDesc;
-#else
-#define pDesc 0
-#endif
- xCharInfo* pCI;
- CARD16* pIndex2UniqIndex;
- CARD16* pUniqIndex2Index;
- CARD32 nUniqCharInfos;
-
-#if 0
- REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
-#else
- switch (client->req_len) {
- case 2: /* client with version 1.0 libX11 */
- stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0);
- break;
- case 3: /* client with version 1.1 libX11 */
- stuff_flags = stuff->flags;
- break;
- default:
- return BadLength;
- }
-#endif
- client->errorValue = stuff->id; /* EITHER font or gc */
- dixLookupResourceByType((pointer *)&pFont, stuff->id, RT_FONT,
- client, DixGetAttrAccess);
- if (!pFont) {
- GC *pGC;
- dixLookupResourceByType((pointer *)&pGC, stuff->id, RT_GC,
- client, DixGetAttrAccess);
- if (!pGC)
- return BadFont; /* procotol spec says only error is BadFont */
-
- pFont = pGC->font;
- }
-
- pmax = FONTINKMAX(pFont);
- pmin = FONTINKMIN(pFont);
- nCharInfos =
- (pmax->rightSideBearing == pmin->rightSideBearing
- && pmax->leftSideBearing == pmin->leftSideBearing
- && pmax->descent == pmin->descent
- && pmax->ascent == pmin->ascent
- && pmax->characterWidth == pmin->characterWidth)
- ? 0 : N2dChars(pFont);
- shmid = -1;
- pCI = NULL;
- pIndex2UniqIndex = NULL;
- pUniqIndex2Index = NULL;
- nUniqCharInfos = 0;
-
- if (nCharInfos > 0) {
-#ifdef HAS_SHM
- if (!badSysCall)
- pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
- else
- pDesc = NULL;
- if (pDesc) {
- pCI = (xCharInfo *) pDesc->attach_addr;
- if (stuff_flags & XF86Bigfont_FLAGS_Shm)
- shmid = pDesc->shmid;
- } else {
- if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall)
- pDesc = shmalloc(nCharInfos * sizeof(xCharInfo)
- + sizeof(CARD32));
- if (pDesc) {
- pCI = (xCharInfo *) pDesc->attach_addr;
- shmid = pDesc->shmid;
- } else {
-#endif
- pCI = xalloc(nCharInfos * sizeof(xCharInfo));
- if (!pCI)
- return BadAlloc;
-#ifdef HAS_SHM
- }
-#endif
- /* Fill nCharInfos starting at pCI. */
- {
- xCharInfo* prCI = pCI;
- int ninfos = 0;
- int ncols = pFont->info.lastCol - pFont->info.firstCol + 1;
- int row;
- for (row = pFont->info.firstRow;
- row <= pFont->info.lastRow && ninfos < nCharInfos;
- row++) {
- unsigned char chars[512];
- xCharInfo* tmpCharInfos[256];
- unsigned long count;
- int col;
- unsigned long i;
- i = 0;
- for (col = pFont->info.firstCol;
- col <= pFont->info.lastCol;
- col++) {
- chars[i++] = row;
- chars[i++] = col;
- }
- (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit,
- &count, tmpCharInfos);
- for (i = 0; i < count && ninfos < nCharInfos; i++) {
- *prCI++ = *tmpCharInfos[i];
- ninfos++;
- }
- }
- }
-#ifdef HAS_SHM
- if (pDesc && !badSysCall) {
- *(CARD32 *)(pCI + nCharInfos) = signature;
- if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) {
- shmdealloc(pDesc);
- return BadAlloc;
- }
- }
- }
-#endif
- if (shmid == -1) {
- /* Cannot use shared memory, so remove-duplicates the xCharInfos
- using a temporary hash table. */
- /* Note that CARD16 is suitable as index type, because
- nCharInfos <= 0x10000. */
- CARD32 hashModulus;
- CARD16* pHash2UniqIndex;
- CARD16* pUniqIndex2NextUniqIndex;
- CARD32 NextIndex;
- CARD32 NextUniqIndex;
- CARD16* tmp;
- CARD32 i, j;
-
- hashModulus = 67;
- if (hashModulus > nCharInfos+1)
- hashModulus = nCharInfos+1;
-
- tmp = xalloc((4*nCharInfos+1) * sizeof(CARD16));
- if (!tmp) {
- if (!pDesc) xfree(pCI);
- return BadAlloc;
- }
- pIndex2UniqIndex = tmp;
- /* nCharInfos elements */
- pUniqIndex2Index = tmp + nCharInfos;
- /* max. nCharInfos elements */
- pUniqIndex2NextUniqIndex = tmp + 2*nCharInfos;
- /* max. nCharInfos elements */
- pHash2UniqIndex = tmp + 3*nCharInfos;
- /* hashModulus (<= nCharInfos+1) elements */
-
- /* Note that we can use 0xffff as end-of-list indicator, because
- even if nCharInfos = 0x10000, 0xffff can not occur as valid
- entry before the last element has been inserted. And once the
- last element has been inserted, we don't need the hash table
- any more. */
- for (j = 0; j < hashModulus; j++)
- pHash2UniqIndex[j] = (CARD16)(-1);
-
- NextUniqIndex = 0;
- for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) {
- xCharInfo* p = &pCI[NextIndex];
- CARD32 hashCode = hashCI(p) % hashModulus;
- for (i = pHash2UniqIndex[hashCode];
- i != (CARD16)(-1);
- i = pUniqIndex2NextUniqIndex[i]) {
- j = pUniqIndex2Index[i];
- if (pCI[j].leftSideBearing == p->leftSideBearing
- && pCI[j].rightSideBearing == p->rightSideBearing
- && pCI[j].characterWidth == p->characterWidth
- && pCI[j].ascent == p->ascent
- && pCI[j].descent == p->descent
- && pCI[j].attributes == p->attributes)
- break;
- }
- if (i != (CARD16)(-1)) {
- /* Found *p at Index j, UniqIndex i */
- pIndex2UniqIndex[NextIndex] = i;
- } else {
- /* Allocate a new entry in the Uniq table */
- if (hashModulus <= 2*NextUniqIndex
- && hashModulus < nCharInfos+1) {
- /* Time to increate hash table size */
- hashModulus = 2*hashModulus+1;
- if (hashModulus > nCharInfos+1)
- hashModulus = nCharInfos+1;
- for (j = 0; j < hashModulus; j++)
- pHash2UniqIndex[j] = (CARD16)(-1);
- for (i = 0; i < NextUniqIndex; i++)
- pUniqIndex2NextUniqIndex[i] = (CARD16)(-1);
- for (i = 0; i < NextUniqIndex; i++) {
- j = pUniqIndex2Index[i];
- p = &pCI[j];
- hashCode = hashCI(p) % hashModulus;
- pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
- pHash2UniqIndex[hashCode] = i;
- }
- p = &pCI[NextIndex];
- hashCode = hashCI(p) % hashModulus;
- }
- i = NextUniqIndex++;
- pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
- pHash2UniqIndex[hashCode] = i;
- pUniqIndex2Index[i] = NextIndex;
- pIndex2UniqIndex[NextIndex] = i;
- }
- }
- nUniqCharInfos = NextUniqIndex;
- /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */
- }
- }
-
- {
- int nfontprops = pFont->info.nprops;
- int rlength =
- sizeof(xXF86BigfontQueryFontReply)
- + nfontprops * sizeof(xFontProp)
- + (nCharInfos > 0 && shmid == -1
- ? nUniqCharInfos * sizeof(xCharInfo)
- + (nCharInfos+1)/2 * 2 * sizeof(CARD16)
- : 0);
- xXF86BigfontQueryFontReply* reply = xalloc(rlength);
- char* p;
- if (!reply) {
- if (nCharInfos > 0) {
- if (shmid == -1) xfree(pIndex2UniqIndex);
- if (!pDesc) xfree(pCI);
- }
- return BadAlloc;
- }
- reply->type = X_Reply;
- reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
- reply->sequenceNumber = client->sequence;
- reply->minBounds = pFont->info.ink_minbounds;
- reply->maxBounds = pFont->info.ink_maxbounds;
- reply->minCharOrByte2 = pFont->info.firstCol;
- reply->maxCharOrByte2 = pFont->info.lastCol;
- reply->defaultChar = pFont->info.defaultCh;
- reply->nFontProps = pFont->info.nprops;
- reply->drawDirection = pFont->info.drawDirection;
- reply->minByte1 = pFont->info.firstRow;
- reply->maxByte1 = pFont->info.lastRow;
- reply->allCharsExist = pFont->info.allExist;
- reply->fontAscent = pFont->info.fontAscent;
- reply->fontDescent = pFont->info.fontDescent;
- reply->nCharInfos = nCharInfos;
- reply->nUniqCharInfos = nUniqCharInfos;
- reply->shmid = shmid;
- reply->shmsegoffset = 0;
- if (client->swapped) {
- char tmp;
- swaps(&reply->sequenceNumber, tmp);
- swapl(&reply->length, tmp);
- swapCharInfo(&reply->minBounds);
- swapCharInfo(&reply->maxBounds);
- swaps(&reply->minCharOrByte2, tmp);
- swaps(&reply->maxCharOrByte2, tmp);
- swaps(&reply->defaultChar, tmp);
- swaps(&reply->nFontProps, tmp);
- swaps(&reply->fontAscent, tmp);
- swaps(&reply->fontDescent, tmp);
- swapl(&reply->nCharInfos, tmp);
- swapl(&reply->nUniqCharInfos, tmp);
- swapl(&reply->shmid, tmp);
- swapl(&reply->shmsegoffset, tmp);
- }
- p = (char*) &reply[1];
- {
- FontPropPtr pFP;
- xFontProp* prFP;
- int i;
- for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p;
- i < nfontprops;
- i++, pFP++, prFP++) {
- prFP->name = pFP->name;
- prFP->value = pFP->value;
- if (client->swapped) {
- char tmp;
- swapl(&prFP->name, tmp);
- swapl(&prFP->value, tmp);
- }
- }
- p = (char*) prFP;
- }
- if (nCharInfos > 0 && shmid == -1) {
- xCharInfo* pci;
- CARD16* ps;
- int i, j;
- pci = (xCharInfo*) p;
- for (i = 0; i < nUniqCharInfos; i++, pci++) {
- *pci = pCI[pUniqIndex2Index[i]];
- if (client->swapped)
- swapCharInfo(pci);
- }
- ps = (CARD16*) pci;
- for (j = 0; j < nCharInfos; j++, ps++) {
- *ps = pIndex2UniqIndex[j];
- if (client->swapped) {
- char tmp;
- swaps(ps, tmp);
- }
- }
- }
- WriteToClient(client, rlength, (char *)reply);
- xfree(reply);
- if (nCharInfos > 0) {
- if (shmid == -1) xfree(pIndex2UniqIndex);
- if (!pDesc) xfree(pCI);
- }
- return (client->noClientException);
- }
-}
-
-static int
-ProcXF86BigfontDispatch(
- ClientPtr client)
-{
- REQUEST(xReq);
-
- switch (stuff->data) {
- case X_XF86BigfontQueryVersion:
- return ProcXF86BigfontQueryVersion(client);
- case X_XF86BigfontQueryFont:
- return ProcXF86BigfontQueryFont(client);
- default:
- return BadRequest;
- }
-}
-
-static int
-SProcXF86BigfontQueryVersion(
- ClientPtr client)
-{
- REQUEST(xXF86BigfontQueryVersionReq);
- char tmp;
-
- swaps(&stuff->length, tmp);
- return ProcXF86BigfontQueryVersion(client);
-}
-
-static int
-SProcXF86BigfontQueryFont(
- ClientPtr client)
-{
- REQUEST(xXF86BigfontQueryFontReq);
- char tmp;
-
- swaps(&stuff->length, tmp);
- REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
- swapl(&stuff->id, tmp);
- return ProcXF86BigfontQueryFont(client);
-}
-
-static int
-SProcXF86BigfontDispatch(
- ClientPtr client)
-{
- REQUEST(xReq);
-
- switch (stuff->data) {
- case X_XF86BigfontQueryVersion:
- return SProcXF86BigfontQueryVersion(client);
- case X_XF86BigfontQueryFont:
- return SProcXF86BigfontQueryFont(client);
- default:
- return BadRequest;
- }
-}
+/*
+ * BIGFONT extension for sharing font metrics between clients (if possible)
+ * and for transmitting font metrics to clients in a compressed form.
+ *
+ * Copyright (c) 1999-2000 Bruno Haible
+ * Copyright (c) 1999-2000 The XFree86 Project, Inc.
+ */
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD */
+
+/*
+ * Big fonts suffer from the following: All clients that have opened a
+ * font can access the complete glyph metrics array (the XFontStruct member
+ * `per_char') directly, without going through a macro. Moreover these
+ * glyph metrics are ink metrics, i.e. are not redundant even for a
+ * fixed-width font. For a Unicode font, the size of this array is 768 KB.
+ *
+ * Problems: 1. It eats a lot of memory in each client. 2. All this glyph
+ * metrics data is piped through the socket when the font is opened.
+ *
+ * This extension addresses these two problems for local clients, by using
+ * shared memory. It also addresses the second problem for non-local clients,
+ * by compressing the data before transmit by a factor of nearly 6.
+ *
+ * If you use this extension, your OS ought to nicely support shared memory.
+ * This means: Shared memory should be swappable to the swap, and the limits
+ * should be high enough (SHMMNI at least 64, SHMMAX at least 768 KB,
+ * SHMALL at least 48 MB). It is a plus if your OS allows shmat() calls
+ * on segments that have already been marked "removed", because it permits
+ * these segments to be cleaned up by the OS if the X server is killed with
+ * signal SIGKILL.
+ *
+ * This extension is transparently exploited by Xlib (functions XQueryFont,
+ * XLoadQueryFont).
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#ifdef HAS_SHM
+#if defined(linux) && (!defined(__GNU_LIBRARY__) || __GNU_LIBRARY__ < 2)
+/* libc4 does not define __GNU_LIBRARY__, libc5 defines __GNU_LIBRARY__ as 1 */
+/* Linux libc4 and libc5 only (because glibc doesn't include kernel headers):
+ Linux 2.0.x and 2.2.x define SHMLBA as PAGE_SIZE, but forget to define
+ PAGE_SIZE. It is defined in <asm/page.h>. */
+#include <asm/page.h>
+#endif
+#ifdef SVR4
+#include <sys/sysmacros.h>
+#endif
+#if defined(__CYGWIN__) || defined(__SCO__)
+#include <sys/param.h>
+#include <sys/sysmacros.h>
+#endif
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <time.h>
+#include <errno.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "gcstruct.h"
+#include "dixfontstr.h"
+#include "extnsionst.h"
+#include "protocol-versions.h"
+
+#include <X11/extensions/xf86bigfproto.h>
+#include "xf86bigfontsrv.h"
+
+static void XF86BigfontResetProc(
+ ExtensionEntry * /* extEntry */
+ );
+
+static DISPATCH_PROC(ProcXF86BigfontDispatch);
+static DISPATCH_PROC(ProcXF86BigfontQueryVersion);
+static DISPATCH_PROC(ProcXF86BigfontQueryFont);
+static DISPATCH_PROC(SProcXF86BigfontDispatch);
+static DISPATCH_PROC(SProcXF86BigfontQueryVersion);
+static DISPATCH_PROC(SProcXF86BigfontQueryFont);
+
+#ifdef HAS_SHM
+
+/* A random signature, transmitted to the clients so they can verify that the
+ shared memory segment they are attaching to was really established by the
+ X server they are talking to. */
+static CARD32 signature;
+
+/* Index for additional information stored in a FontRec's devPrivates array. */
+static int FontShmdescIndex;
+
+static unsigned int pagesize;
+
+static Bool badSysCall = FALSE;
+
+#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
+
+#include <sys/signal.h>
+
+static void
+SigSysHandler(
+ int signo)
+{
+ badSysCall = TRUE;
+}
+
+static Bool
+CheckForShmSyscall(void)
+{
+ void (*oldHandler)(int);
+ int shmid = -1;
+
+ /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
+ oldHandler = signal(SIGSYS, SigSysHandler);
+
+ badSysCall = FALSE;
+ shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
+ if (shmid != -1)
+ {
+ /* Successful allocation - clean up */
+ shmctl(shmid, IPC_RMID, NULL);
+ }
+ else
+ {
+ /* Allocation failed */
+ badSysCall = TRUE;
+ }
+ signal(SIGSYS, oldHandler);
+ return (!badSysCall);
+}
+
+#define MUST_CHECK_FOR_SHM_SYSCALL
+
+#endif
+
+#endif
+
+void
+XFree86BigfontExtensionInit(void)
+{
+ if (AddExtension(XF86BIGFONTNAME,
+ XF86BigfontNumberEvents,
+ XF86BigfontNumberErrors,
+ ProcXF86BigfontDispatch,
+ SProcXF86BigfontDispatch,
+ XF86BigfontResetProc,
+ StandardMinorOpcode)) {
+#ifdef HAS_SHM
+#ifdef MUST_CHECK_FOR_SHM_SYSCALL
+ /*
+ * Note: Local-clients will not be optimized without shared memory
+ * support. Remote-client optimization does not depend on shared
+ * memory support. Thus, the extension is still registered even
+ * when shared memory support is not functional.
+ */
+ if (!CheckForShmSyscall()) {
+ ErrorF(XF86BIGFONTNAME " extension local-client optimization disabled due to lack of shared memory support in the kernel\n");
+ return;
+ }
+#endif
+
+ srand((unsigned int) time(NULL));
+ signature = ((unsigned int) (65536.0/(RAND_MAX+1.0) * rand()) << 16)
+ + (unsigned int) (65536.0/(RAND_MAX+1.0) * rand());
+ /* fprintf(stderr, "signature = 0x%08X\n", signature); */
+
+ FontShmdescIndex = AllocateFontPrivateIndex();
+
+#if !defined(CSRG_BASED) && !defined(__CYGWIN__)
+ pagesize = SHMLBA;
+#else
+# ifdef _SC_PAGESIZE
+ pagesize = sysconf(_SC_PAGESIZE);
+# else
+ pagesize = getpagesize();
+# endif
+#endif
+#endif
+ }
+}
+
+
+/* ========== Management of shared memory segments ========== */
+
+#ifdef HAS_SHM
+
+#ifdef __linux__
+/* On Linux, shared memory marked as "removed" can still be attached.
+ Nice feature, because the kernel will automatically free the associated
+ storage when the server and all clients are gone. */
+#define EARLY_REMOVE
+#endif
+
+typedef struct _ShmDesc {
+ struct _ShmDesc *next;
+ struct _ShmDesc **prev;
+ int shmid;
+ char *attach_addr;
+} ShmDescRec, *ShmDescPtr;
+
+static ShmDescPtr ShmList = (ShmDescPtr) NULL;
+
+static ShmDescPtr
+shmalloc(
+ unsigned int size)
+{
+ ShmDescPtr pDesc;
+ int shmid;
+ char *addr;
+
+#ifdef MUST_CHECK_FOR_SHM_SYSCALL
+ if (pagesize == 0)
+ return (ShmDescPtr) NULL;
+#endif
+
+ /* On some older Linux systems, the number of shared memory segments
+ system-wide is 127. In Linux 2.4, it is 4095.
+ Therefore there is a tradeoff to be made between allocating a
+ shared memory segment on one hand, and allocating memory and piping
+ the glyph metrics on the other hand. If the glyph metrics size is
+ small, we prefer the traditional way. */
+ if (size < 3500)
+ return (ShmDescPtr) NULL;
+
+ pDesc = xalloc(sizeof(ShmDescRec));
+ if (!pDesc)
+ return (ShmDescPtr) NULL;
+
+ size = (size + pagesize-1) & -pagesize;
+ shmid = shmget(IPC_PRIVATE, size, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
+ if (shmid == -1) {
+ ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n",
+ size, strerror(errno));
+ xfree(pDesc);
+ return (ShmDescPtr) NULL;
+ }
+
+ if ((addr = shmat(shmid, 0, 0)) == (char *)-1) {
+ ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n",
+ size, strerror(errno));
+ shmctl(shmid, IPC_RMID, (void *) 0);
+ xfree(pDesc);
+ return (ShmDescPtr) NULL;
+ }
+
+#ifdef EARLY_REMOVE
+ shmctl(shmid, IPC_RMID, (void *) 0);
+#endif
+
+ pDesc->shmid = shmid;
+ pDesc->attach_addr = addr;
+ if (ShmList) ShmList->prev = &pDesc->next;
+ pDesc->next = ShmList;
+ pDesc->prev = &ShmList;
+ ShmList = pDesc;
+
+ return pDesc;
+}
+
+static void
+shmdealloc(
+ ShmDescPtr pDesc)
+{
+#ifndef EARLY_REMOVE
+ shmctl(pDesc->shmid, IPC_RMID, (void *) 0);
+#endif
+ shmdt(pDesc->attach_addr);
+
+ if (pDesc->next) pDesc->next->prev = pDesc->prev;
+ *pDesc->prev = pDesc->next;
+ xfree(pDesc);
+}
+
+#endif
+
+/* Called when a font is closed. */
+void
+XF86BigfontFreeFontShm(
+ FontPtr pFont)
+{
+#ifdef HAS_SHM
+ ShmDescPtr pDesc;
+
+ /* If during shutdown of the server, XF86BigfontCleanup() has already
+ * called shmdealloc() for all segments, we don't need to do it here.
+ */
+ if (!ShmList)
+ return;
+
+ pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
+ if (pDesc)
+ shmdealloc(pDesc);
+#endif
+}
+
+/* Called upon fatal signal. */
+void
+XF86BigfontCleanup(void)
+{
+#ifdef HAS_SHM
+ while (ShmList)
+ shmdealloc(ShmList);
+#endif
+}
+
+/* Called when a server generation dies. */
+static void
+XF86BigfontResetProc(
+ ExtensionEntry* extEntry)
+{
+ /* This function is normally called from CloseDownExtensions(), called
+ * from main(). It will be followed by a call to FreeAllResources(),
+ * which will call XF86BigfontFreeFontShm() for each font. Thus it
+ * appears that we do not need to do anything in this function. --
+ * But I prefer to write robust code, and not keep shared memory lying
+ * around when it's not needed any more. (Someone might close down the
+ * extension without calling FreeAllResources()...)
+ */
+ XF86BigfontCleanup();
+}
+
+
+/* ========== Handling of extension specific requests ========== */
+
+static int
+ProcXF86BigfontQueryVersion(
+ ClientPtr client)
+{
+ xXF86BigfontQueryVersionReply reply;
+
+ REQUEST_SIZE_MATCH(xXF86BigfontQueryVersionReq);
+ reply.type = X_Reply;
+ reply.length = 0;
+ reply.sequenceNumber = client->sequence;
+ reply.majorVersion = SERVER_XF86BIGFONT_MAJOR_VERSION;
+ reply.minorVersion = SERVER_XF86BIGFONT_MINOR_VERSION;
+ reply.uid = geteuid();
+ reply.gid = getegid();
+#ifdef HAS_SHM
+ reply.signature = signature;
+#else
+ reply.signature = 0; /* This is redundant. Avoids uninitialized memory. */
+#endif
+ reply.capabilities =
+#ifdef HAS_SHM
+ (LocalClient(client) && !client->swapped ? XF86Bigfont_CAP_LocalShm : 0)
+#else
+ 0
+#endif
+ ; /* may add more bits here in future versions */
+ if (client->swapped) {
+ char tmp;
+ swaps(&reply.sequenceNumber, tmp);
+ swapl(&reply.length, tmp);
+ swaps(&reply.majorVersion, tmp);
+ swaps(&reply.minorVersion, tmp);
+ swapl(&reply.uid, tmp);
+ swapl(&reply.gid, tmp);
+ swapl(&reply.signature, tmp);
+ }
+ WriteToClient(client,
+ sizeof(xXF86BigfontQueryVersionReply), (char *)&reply);
+ return client->noClientException;
+}
+
+static void
+swapCharInfo(
+ xCharInfo *pCI)
+{
+ char tmp;
+
+ swaps(&pCI->leftSideBearing, tmp);
+ swaps(&pCI->rightSideBearing, tmp);
+ swaps(&pCI->characterWidth, tmp);
+ swaps(&pCI->ascent, tmp);
+ swaps(&pCI->descent, tmp);
+ swaps(&pCI->attributes, tmp);
+}
+
+/* static CARD32 hashCI (xCharInfo *p); */
+#define hashCI(p) \
+ (CARD32)(((p->leftSideBearing << 27) + (p->leftSideBearing >> 5) + \
+ (p->rightSideBearing << 23) + (p->rightSideBearing >> 9) + \
+ (p->characterWidth << 16) + \
+ (p->ascent << 11) + (p->descent << 6)) ^ p->attributes)
+
+static int
+ProcXF86BigfontQueryFont(
+ ClientPtr client)
+{
+ FontPtr pFont;
+ REQUEST(xXF86BigfontQueryFontReq);
+ CARD32 stuff_flags;
+ xCharInfo* pmax;
+ xCharInfo* pmin;
+ int nCharInfos;
+ int shmid;
+#ifdef HAS_SHM
+ ShmDescPtr pDesc;
+#else
+#define pDesc 0
+#endif
+ xCharInfo* pCI;
+ CARD16* pIndex2UniqIndex;
+ CARD16* pUniqIndex2Index;
+ CARD32 nUniqCharInfos;
+
+#if 0
+ REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
+#else
+ switch (client->req_len) {
+ case 2: /* client with version 1.0 libX11 */
+ stuff_flags = (LocalClient(client) && !client->swapped ? XF86Bigfont_FLAGS_Shm : 0);
+ break;
+ case 3: /* client with version 1.1 libX11 */
+ stuff_flags = stuff->flags;
+ break;
+ default:
+ return BadLength;
+ }
+#endif
+ if (dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess) != Success)
+ return BadFont; /* procotol spec says only error is BadFont */
+
+ pmax = FONTINKMAX(pFont);
+ pmin = FONTINKMIN(pFont);
+ nCharInfos =
+ (pmax->rightSideBearing == pmin->rightSideBearing
+ && pmax->leftSideBearing == pmin->leftSideBearing
+ && pmax->descent == pmin->descent
+ && pmax->ascent == pmin->ascent
+ && pmax->characterWidth == pmin->characterWidth)
+ ? 0 : N2dChars(pFont);
+ shmid = -1;
+ pCI = NULL;
+ pIndex2UniqIndex = NULL;
+ pUniqIndex2Index = NULL;
+ nUniqCharInfos = 0;
+
+ if (nCharInfos > 0) {
+#ifdef HAS_SHM
+ if (!badSysCall)
+ pDesc = (ShmDescPtr) FontGetPrivate(pFont, FontShmdescIndex);
+ else
+ pDesc = NULL;
+ if (pDesc) {
+ pCI = (xCharInfo *) pDesc->attach_addr;
+ if (stuff_flags & XF86Bigfont_FLAGS_Shm)
+ shmid = pDesc->shmid;
+ } else {
+ if (stuff_flags & XF86Bigfont_FLAGS_Shm && !badSysCall)
+ pDesc = shmalloc(nCharInfos * sizeof(xCharInfo)
+ + sizeof(CARD32));
+ if (pDesc) {
+ pCI = (xCharInfo *) pDesc->attach_addr;
+ shmid = pDesc->shmid;
+ } else {
+#endif
+ pCI = xalloc(nCharInfos * sizeof(xCharInfo));
+ if (!pCI)
+ return BadAlloc;
+#ifdef HAS_SHM
+ }
+#endif
+ /* Fill nCharInfos starting at pCI. */
+ {
+ xCharInfo* prCI = pCI;
+ int ninfos = 0;
+ int ncols = pFont->info.lastCol - pFont->info.firstCol + 1;
+ int row;
+ for (row = pFont->info.firstRow;
+ row <= pFont->info.lastRow && ninfos < nCharInfos;
+ row++) {
+ unsigned char chars[512];
+ xCharInfo* tmpCharInfos[256];
+ unsigned long count;
+ int col;
+ unsigned long i;
+ i = 0;
+ for (col = pFont->info.firstCol;
+ col <= pFont->info.lastCol;
+ col++) {
+ chars[i++] = row;
+ chars[i++] = col;
+ }
+ (*pFont->get_metrics) (pFont, ncols, chars, TwoD16Bit,
+ &count, tmpCharInfos);
+ for (i = 0; i < count && ninfos < nCharInfos; i++) {
+ *prCI++ = *tmpCharInfos[i];
+ ninfos++;
+ }
+ }
+ }
+#ifdef HAS_SHM
+ if (pDesc && !badSysCall) {
+ *(CARD32 *)(pCI + nCharInfos) = signature;
+ if (!FontSetPrivate(pFont, FontShmdescIndex, pDesc)) {
+ shmdealloc(pDesc);
+ return BadAlloc;
+ }
+ }
+ }
+#endif
+ if (shmid == -1) {
+ /* Cannot use shared memory, so remove-duplicates the xCharInfos
+ using a temporary hash table. */
+ /* Note that CARD16 is suitable as index type, because
+ nCharInfos <= 0x10000. */
+ CARD32 hashModulus;
+ CARD16* pHash2UniqIndex;
+ CARD16* pUniqIndex2NextUniqIndex;
+ CARD32 NextIndex;
+ CARD32 NextUniqIndex;
+ CARD16* tmp;
+ CARD32 i, j;
+
+ hashModulus = 67;
+ if (hashModulus > nCharInfos+1)
+ hashModulus = nCharInfos+1;
+
+ tmp = xalloc((4*nCharInfos+1) * sizeof(CARD16));
+ if (!tmp) {
+ if (!pDesc) xfree(pCI);
+ return BadAlloc;
+ }
+ pIndex2UniqIndex = tmp;
+ /* nCharInfos elements */
+ pUniqIndex2Index = tmp + nCharInfos;
+ /* max. nCharInfos elements */
+ pUniqIndex2NextUniqIndex = tmp + 2*nCharInfos;
+ /* max. nCharInfos elements */
+ pHash2UniqIndex = tmp + 3*nCharInfos;
+ /* hashModulus (<= nCharInfos+1) elements */
+
+ /* Note that we can use 0xffff as end-of-list indicator, because
+ even if nCharInfos = 0x10000, 0xffff can not occur as valid
+ entry before the last element has been inserted. And once the
+ last element has been inserted, we don't need the hash table
+ any more. */
+ for (j = 0; j < hashModulus; j++)
+ pHash2UniqIndex[j] = (CARD16)(-1);
+
+ NextUniqIndex = 0;
+ for (NextIndex = 0; NextIndex < nCharInfos; NextIndex++) {
+ xCharInfo* p = &pCI[NextIndex];
+ CARD32 hashCode = hashCI(p) % hashModulus;
+ for (i = pHash2UniqIndex[hashCode];
+ i != (CARD16)(-1);
+ i = pUniqIndex2NextUniqIndex[i]) {
+ j = pUniqIndex2Index[i];
+ if (pCI[j].leftSideBearing == p->leftSideBearing
+ && pCI[j].rightSideBearing == p->rightSideBearing
+ && pCI[j].characterWidth == p->characterWidth
+ && pCI[j].ascent == p->ascent
+ && pCI[j].descent == p->descent
+ && pCI[j].attributes == p->attributes)
+ break;
+ }
+ if (i != (CARD16)(-1)) {
+ /* Found *p at Index j, UniqIndex i */
+ pIndex2UniqIndex[NextIndex] = i;
+ } else {
+ /* Allocate a new entry in the Uniq table */
+ if (hashModulus <= 2*NextUniqIndex
+ && hashModulus < nCharInfos+1) {
+ /* Time to increate hash table size */
+ hashModulus = 2*hashModulus+1;
+ if (hashModulus > nCharInfos+1)
+ hashModulus = nCharInfos+1;
+ for (j = 0; j < hashModulus; j++)
+ pHash2UniqIndex[j] = (CARD16)(-1);
+ for (i = 0; i < NextUniqIndex; i++)
+ pUniqIndex2NextUniqIndex[i] = (CARD16)(-1);
+ for (i = 0; i < NextUniqIndex; i++) {
+ j = pUniqIndex2Index[i];
+ p = &pCI[j];
+ hashCode = hashCI(p) % hashModulus;
+ pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
+ pHash2UniqIndex[hashCode] = i;
+ }
+ p = &pCI[NextIndex];
+ hashCode = hashCI(p) % hashModulus;
+ }
+ i = NextUniqIndex++;
+ pUniqIndex2NextUniqIndex[i] = pHash2UniqIndex[hashCode];
+ pHash2UniqIndex[hashCode] = i;
+ pUniqIndex2Index[i] = NextIndex;
+ pIndex2UniqIndex[NextIndex] = i;
+ }
+ }
+ nUniqCharInfos = NextUniqIndex;
+ /* fprintf(stderr, "font metrics: nCharInfos = %d, nUniqCharInfos = %d, hashModulus = %d\n", nCharInfos, nUniqCharInfos, hashModulus); */
+ }
+ }
+
+ {
+ int nfontprops = pFont->info.nprops;
+ int rlength =
+ sizeof(xXF86BigfontQueryFontReply)
+ + nfontprops * sizeof(xFontProp)
+ + (nCharInfos > 0 && shmid == -1
+ ? nUniqCharInfos * sizeof(xCharInfo)
+ + (nCharInfos+1)/2 * 2 * sizeof(CARD16)
+ : 0);
+ xXF86BigfontQueryFontReply* reply = xalloc(rlength);
+ char* p;
+ if (!reply) {
+ if (nCharInfos > 0) {
+ if (shmid == -1) xfree(pIndex2UniqIndex);
+ if (!pDesc) xfree(pCI);
+ }
+ return BadAlloc;
+ }
+ reply->type = X_Reply;
+ reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
+ reply->sequenceNumber = client->sequence;
+ reply->minBounds = pFont->info.ink_minbounds;
+ reply->maxBounds = pFont->info.ink_maxbounds;
+ reply->minCharOrByte2 = pFont->info.firstCol;
+ reply->maxCharOrByte2 = pFont->info.lastCol;
+ reply->defaultChar = pFont->info.defaultCh;
+ reply->nFontProps = pFont->info.nprops;
+ reply->drawDirection = pFont->info.drawDirection;
+ reply->minByte1 = pFont->info.firstRow;
+ reply->maxByte1 = pFont->info.lastRow;
+ reply->allCharsExist = pFont->info.allExist;
+ reply->fontAscent = pFont->info.fontAscent;
+ reply->fontDescent = pFont->info.fontDescent;
+ reply->nCharInfos = nCharInfos;
+ reply->nUniqCharInfos = nUniqCharInfos;
+ reply->shmid = shmid;
+ reply->shmsegoffset = 0;
+ if (client->swapped) {
+ char tmp;
+ swaps(&reply->sequenceNumber, tmp);
+ swapl(&reply->length, tmp);
+ swapCharInfo(&reply->minBounds);
+ swapCharInfo(&reply->maxBounds);
+ swaps(&reply->minCharOrByte2, tmp);
+ swaps(&reply->maxCharOrByte2, tmp);
+ swaps(&reply->defaultChar, tmp);
+ swaps(&reply->nFontProps, tmp);
+ swaps(&reply->fontAscent, tmp);
+ swaps(&reply->fontDescent, tmp);
+ swapl(&reply->nCharInfos, tmp);
+ swapl(&reply->nUniqCharInfos, tmp);
+ swapl(&reply->shmid, tmp);
+ swapl(&reply->shmsegoffset, tmp);
+ }
+ p = (char*) &reply[1];
+ {
+ FontPropPtr pFP;
+ xFontProp* prFP;
+ int i;
+ for (i = 0, pFP = pFont->info.props, prFP = (xFontProp *) p;
+ i < nfontprops;
+ i++, pFP++, prFP++) {
+ prFP->name = pFP->name;
+ prFP->value = pFP->value;
+ if (client->swapped) {
+ char tmp;
+ swapl(&prFP->name, tmp);
+ swapl(&prFP->value, tmp);
+ }
+ }
+ p = (char*) prFP;
+ }
+ if (nCharInfos > 0 && shmid == -1) {
+ xCharInfo* pci;
+ CARD16* ps;
+ int i, j;
+ pci = (xCharInfo*) p;
+ for (i = 0; i < nUniqCharInfos; i++, pci++) {
+ *pci = pCI[pUniqIndex2Index[i]];
+ if (client->swapped)
+ swapCharInfo(pci);
+ }
+ ps = (CARD16*) pci;
+ for (j = 0; j < nCharInfos; j++, ps++) {
+ *ps = pIndex2UniqIndex[j];
+ if (client->swapped) {
+ char tmp;
+ swaps(ps, tmp);
+ }
+ }
+ }
+ WriteToClient(client, rlength, (char *)reply);
+ xfree(reply);
+ if (nCharInfos > 0) {
+ if (shmid == -1) xfree(pIndex2UniqIndex);
+ if (!pDesc) xfree(pCI);
+ }
+ return (client->noClientException);
+ }
+}
+
+static int
+ProcXF86BigfontDispatch(
+ ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data) {
+ case X_XF86BigfontQueryVersion:
+ return ProcXF86BigfontQueryVersion(client);
+ case X_XF86BigfontQueryFont:
+ return ProcXF86BigfontQueryFont(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcXF86BigfontQueryVersion(
+ ClientPtr client)
+{
+ REQUEST(xXF86BigfontQueryVersionReq);
+ char tmp;
+
+ swaps(&stuff->length, tmp);
+ return ProcXF86BigfontQueryVersion(client);
+}
+
+static int
+SProcXF86BigfontQueryFont(
+ ClientPtr client)
+{
+ REQUEST(xXF86BigfontQueryFontReq);
+ char tmp;
+
+ swaps(&stuff->length, tmp);
+ REQUEST_SIZE_MATCH(xXF86BigfontQueryFontReq);
+ swapl(&stuff->id, tmp);
+ return ProcXF86BigfontQueryFont(client);
+}
+
+static int
+SProcXF86BigfontDispatch(
+ ClientPtr client)
+{
+ REQUEST(xReq);
+
+ switch (stuff->data) {
+ case X_XF86BigfontQueryVersion:
+ return SProcXF86BigfontQueryVersion(client);
+ case X_XF86BigfontQueryFont:
+ return SProcXF86BigfontQueryFont(client);
+ default:
+ return BadRequest;
+ }
+}
diff --git a/xorg-server/Xi/extinit.c b/xorg-server/Xi/extinit.c
index b7910cd13..07057377a 100644
--- a/xorg-server/Xi/extinit.c
+++ b/xorg-server/Xi/extinit.c
@@ -1,1310 +1,1311 @@
-/************************************************************
-
-Copyright 1989, 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 1989 by Hewlett-Packard Company, Palo Alto, California.
-
- 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 Hewlett-Packard not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
-
-HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-HEWLETT-PACKARD 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.
-
-********************************************************/
-
-/********************************************************************
- *
- * Dispatch routines and initialization routines for the X input extension.
- *
- */
-
-#define NUMTYPES 15
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "inputstr.h"
-#include "gcstruct.h" /* pointer for extnsionst.h */
-#include "extnsionst.h" /* extension entry */
-#include <X11/extensions/XI.h>
-#include <X11/extensions/XIproto.h>
-#include <X11/extensions/XI2proto.h>
-#include <X11/extensions/geproto.h>
-#include "geext.h" /* extension interfaces for ge */
-
-#include "dixevents.h"
-#include "exevents.h"
-#include "extinit.h"
-#include "exglobals.h"
-#include "swaprep.h"
-#include "privates.h"
-#include "protocol-versions.h"
-
-/* modules local to Xi */
-#include "allowev.h"
-#include "chgdctl.h"
-#include "chgfctl.h"
-#include "chgkbd.h"
-#include "chgprop.h"
-#include "chgptr.h"
-#include "closedev.h"
-#include "devbell.h"
-#include "getbmap.h"
-#include "getbmap.h"
-#include "getdctl.h"
-#include "getfctl.h"
-#include "getfocus.h"
-#include "getkmap.h"
-#include "getmmap.h"
-#include "getprop.h"
-#include "getselev.h"
-#include "getvers.h"
-#include "getvers.h"
-#include "grabdev.h"
-#include "grabdevb.h"
-#include "grabdevk.h"
-#include "gtmotion.h"
-#include "listdev.h"
-#include "opendev.h"
-#include "queryst.h"
-#include "selectev.h"
-#include "sendexev.h"
-#include "chgkmap.h"
-#include "setbmap.h"
-#include "setdval.h"
-#include "setfocus.h"
-#include "setmmap.h"
-#include "setmode.h"
-#include "ungrdev.h"
-#include "ungrdevb.h"
-#include "ungrdevk.h"
-#include "xiallowev.h"
-#include "xiselectev.h"
-#include "xigrabdev.h"
-#include "xipassivegrab.h"
-#include "xisetdevfocus.h"
-#include "xiproperty.h"
-#include "xichangecursor.h"
-#include "xichangehierarchy.h"
-#include "xigetclientpointer.h"
-#include "xiquerydevice.h"
-#include "xiquerypointer.h"
-#include "xiqueryversion.h"
-#include "xisetclientpointer.h"
-#include "xiwarppointer.h"
-
-
-/* Masks for XI events have to be aligned with core event (partially anyway).
- * If DeviceButtonMotionMask is != ButtonMotionMask, event delivery
- * breaks down. The device needs the dev->button->motionMask. If DBMM is
- * the same as BMM, we can ensure that both core and device events can be
- * delivered, without the need for extra structures in the DeviceIntRec. */
-const Mask DeviceKeyPressMask = KeyPressMask;
-const Mask DeviceKeyReleaseMask = KeyReleaseMask;
-const Mask DeviceButtonPressMask = ButtonPressMask;
-const Mask DeviceButtonReleaseMask = ButtonReleaseMask;
-const Mask DeviceProximityMask = (1L << 4);
-const Mask DeviceStateNotifyMask = (1L << 5);
-const Mask DevicePointerMotionMask = PointerMotionMask;
-const Mask DevicePointerMotionHintMask = PointerMotionHintMask;
-const Mask DeviceButton1MotionMask = Button1MotionMask;
-const Mask DeviceButton2MotionMask = Button2MotionMask;
-const Mask DeviceButton3MotionMask = Button3MotionMask;
-const Mask DeviceButton4MotionMask = Button4MotionMask;
-const Mask DeviceButton5MotionMask = Button5MotionMask;
-const Mask DeviceButtonMotionMask = ButtonMotionMask;
-const Mask DeviceFocusChangeMask = (1L << 14);
-const Mask DeviceMappingNotifyMask = (1L << 15);
-const Mask ChangeDeviceNotifyMask = (1L << 16);
-const Mask DeviceButtonGrabMask = (1L << 17);
-const Mask DeviceOwnerGrabButtonMask = (1L << 17);
-const Mask DevicePresenceNotifyMask = (1L << 18);
-const Mask DeviceEnterWindowMask = (1L << 18);
-const Mask DeviceLeaveWindowMask = (1L << 19);
-const Mask DevicePropertyNotifyMask = (1L << 20);
-const Mask XIAllMasks = (1L << 21) - 1;
-
-int ExtEventIndex;
-Mask ExtExclusiveMasks[EMASKSIZE];
-
-static struct dev_type
-{
- Atom type;
- char *name;
-} dev_type[] = {
- {
- 0, XI_KEYBOARD}, {
- 0, XI_MOUSE}, {
- 0, XI_TABLET}, {
- 0, XI_TOUCHSCREEN}, {
- 0, XI_TOUCHPAD}, {
- 0, XI_BARCODE}, {
- 0, XI_BUTTONBOX}, {
- 0, XI_KNOB_BOX}, {
- 0, XI_ONE_KNOB}, {
- 0, XI_NINE_KNOB}, {
- 0, XI_TRACKBALL}, {
- 0, XI_QUADRATURE}, {
- 0, XI_ID_MODULE}, {
- 0, XI_SPACEBALL}, {
- 0, XI_DATAGLOVE}, {
- 0, XI_EYETRACKER}, {
- 0, XI_CURSORKEYS}, {
-0, XI_FOOTMOUSE}};
-
-CARD8 event_base[numInputClasses];
-XExtEventInfo EventInfo[32];
-
-static DeviceIntRec xi_all_devices;
-static DeviceIntRec xi_all_master_devices;
-
-/**
- * Dispatch vector. Functions defined in here will be called when the matching
- * request arrives.
- */
-static int (*ProcIVector[])(ClientPtr) = {
- NULL, /* 0 */
- ProcXGetExtensionVersion, /* 1 */
- ProcXListInputDevices, /* 2 */
- ProcXOpenDevice, /* 3 */
- ProcXCloseDevice, /* 4 */
- ProcXSetDeviceMode, /* 5 */
- ProcXSelectExtensionEvent, /* 6 */
- ProcXGetSelectedExtensionEvents, /* 7 */
- ProcXChangeDeviceDontPropagateList, /* 8 */
- ProcXGetDeviceDontPropagateList, /* 9 */
- ProcXGetDeviceMotionEvents, /* 10 */
- ProcXChangeKeyboardDevice, /* 11 */
- ProcXChangePointerDevice, /* 12 */
- ProcXGrabDevice, /* 13 */
- ProcXUngrabDevice, /* 14 */
- ProcXGrabDeviceKey, /* 15 */
- ProcXUngrabDeviceKey, /* 16 */
- ProcXGrabDeviceButton, /* 17 */
- ProcXUngrabDeviceButton, /* 18 */
- ProcXAllowDeviceEvents, /* 19 */
- ProcXGetDeviceFocus, /* 20 */
- ProcXSetDeviceFocus, /* 21 */
- ProcXGetFeedbackControl, /* 22 */
- ProcXChangeFeedbackControl, /* 23 */
- ProcXGetDeviceKeyMapping, /* 24 */
- ProcXChangeDeviceKeyMapping, /* 25 */
- ProcXGetDeviceModifierMapping, /* 26 */
- ProcXSetDeviceModifierMapping, /* 27 */
- ProcXGetDeviceButtonMapping, /* 28 */
- ProcXSetDeviceButtonMapping, /* 29 */
- ProcXQueryDeviceState, /* 30 */
- ProcXSendExtensionEvent, /* 31 */
- ProcXDeviceBell, /* 32 */
- ProcXSetDeviceValuators, /* 33 */
- ProcXGetDeviceControl, /* 34 */
- ProcXChangeDeviceControl, /* 35 */
- /* XI 1.5 */
- ProcXListDeviceProperties, /* 36 */
- ProcXChangeDeviceProperty, /* 37 */
- ProcXDeleteDeviceProperty, /* 38 */
- ProcXGetDeviceProperty, /* 39 */
- /* XI 2 */
- ProcXIQueryPointer, /* 40 */
- ProcXIWarpPointer, /* 41 */
- ProcXIChangeCursor, /* 42 */
- ProcXIChangeHierarchy, /* 43 */
- ProcXISetClientPointer, /* 44 */
- ProcXIGetClientPointer, /* 45 */
- ProcXISelectEvents, /* 46 */
- ProcXIQueryVersion, /* 47 */
- ProcXIQueryDevice, /* 48 */
- ProcXISetFocus, /* 49 */
- ProcXIGetFocus, /* 50 */
- ProcXIGrabDevice, /* 51 */
- ProcXIUngrabDevice, /* 52 */
- ProcXIAllowEvents, /* 53 */
- ProcXIPassiveGrabDevice, /* 54 */
- ProcXIPassiveUngrabDevice, /* 55 */
- ProcXIListProperties, /* 56 */
- ProcXIChangeProperty, /* 57 */
- ProcXIDeleteProperty, /* 58 */
- ProcXIGetProperty, /* 59 */
- ProcXIGetSelectedEvents /* 60 */
-};
-
-/* For swapped clients */
-static int (*SProcIVector[])(ClientPtr) = {
- NULL, /* 0 */
- SProcXGetExtensionVersion, /* 1 */
- SProcXListInputDevices, /* 2 */
- SProcXOpenDevice, /* 3 */
- SProcXCloseDevice, /* 4 */
- SProcXSetDeviceMode, /* 5 */
- SProcXSelectExtensionEvent, /* 6 */
- SProcXGetSelectedExtensionEvents, /* 7 */
- SProcXChangeDeviceDontPropagateList, /* 8 */
- SProcXGetDeviceDontPropagateList, /* 9 */
- SProcXGetDeviceMotionEvents, /* 10 */
- SProcXChangeKeyboardDevice, /* 11 */
- SProcXChangePointerDevice, /* 12 */
- SProcXGrabDevice, /* 13 */
- SProcXUngrabDevice, /* 14 */
- SProcXGrabDeviceKey, /* 15 */
- SProcXUngrabDeviceKey, /* 16 */
- SProcXGrabDeviceButton, /* 17 */
- SProcXUngrabDeviceButton, /* 18 */
- SProcXAllowDeviceEvents, /* 19 */
- SProcXGetDeviceFocus, /* 20 */
- SProcXSetDeviceFocus, /* 21 */
- SProcXGetFeedbackControl, /* 22 */
- SProcXChangeFeedbackControl, /* 23 */
- SProcXGetDeviceKeyMapping, /* 24 */
- SProcXChangeDeviceKeyMapping, /* 25 */
- SProcXGetDeviceModifierMapping, /* 26 */
- SProcXSetDeviceModifierMapping, /* 27 */
- SProcXGetDeviceButtonMapping, /* 28 */
- SProcXSetDeviceButtonMapping, /* 29 */
- SProcXQueryDeviceState, /* 30 */
- SProcXSendExtensionEvent, /* 31 */
- SProcXDeviceBell, /* 32 */
- SProcXSetDeviceValuators, /* 33 */
- SProcXGetDeviceControl, /* 34 */
- SProcXChangeDeviceControl, /* 35 */
- SProcXListDeviceProperties, /* 36 */
- SProcXChangeDeviceProperty, /* 37 */
- SProcXDeleteDeviceProperty, /* 38 */
- SProcXGetDeviceProperty, /* 39 */
- SProcXIQueryPointer, /* 40 */
- SProcXIWarpPointer, /* 41 */
- SProcXIChangeCursor, /* 42 */
- SProcXIChangeHierarchy, /* 43 */
- SProcXISetClientPointer, /* 44 */
- SProcXIGetClientPointer, /* 45 */
- SProcXISelectEvents, /* 46 */
- SProcXIQueryVersion, /* 47 */
- SProcXIQueryDevice, /* 48 */
- SProcXISetFocus, /* 49 */
- SProcXIGetFocus, /* 50 */
- SProcXIGrabDevice, /* 51 */
- SProcXIUngrabDevice, /* 52 */
- SProcXIAllowEvents, /* 53 */
- SProcXIPassiveGrabDevice, /* 54 */
- SProcXIPassiveUngrabDevice, /* 55 */
- SProcXIListProperties, /* 56 */
- SProcXIChangeProperty, /* 57 */
- SProcXIDeleteProperty, /* 58 */
- SProcXIGetProperty, /* 59 */
- SProcXIGetSelectedEvents /* 60 */
-};
-
-/*****************************************************************
- *
- * Globals referenced elsewhere in the server.
- *
- */
-
-int IReqCode = 0;
-int IEventBase = 0;
-int BadDevice = 0;
-static int BadEvent = 1;
-int BadMode = 2;
-int DeviceBusy = 3;
-int BadClass = 4;
-
-int DeviceValuator;
-int DeviceKeyPress;
-int DeviceKeyRelease;
-int DeviceButtonPress;
-int DeviceButtonRelease;
-int DeviceMotionNotify;
-int DeviceFocusIn;
-int DeviceFocusOut;
-int ProximityIn;
-int ProximityOut;
-int DeviceStateNotify;
-int DeviceKeyStateNotify;
-int DeviceButtonStateNotify;
-int DeviceMappingNotify;
-int ChangeDeviceNotify;
-int DevicePresenceNotify;
-int DevicePropertyNotify;
-
-int RT_INPUTCLIENT;
-
-/*****************************************************************
- *
- * Externs defined elsewhere in the X server.
- *
- */
-
-extern XExtensionVersion XIVersion;
-
-
-Mask PropagateMask[MAXDEVICES];
-
-/*****************************************************************
- *
- * Versioning support
- *
- */
-
-static int XIClientPrivateKeyIndex;
-DevPrivateKey XIClientPrivateKey = &XIClientPrivateKeyIndex;
-
-
-/*****************************************************************
- *
- * Declarations of local routines.
- *
- */
-
-static void
-XIClientCallback(CallbackListPtr *list,
- pointer closure,
- pointer data)
-{
- NewClientInfoRec *clientinfo = (NewClientInfoRec*)data;
- ClientPtr pClient = clientinfo->client;
- XIClientPtr pXIClient;
-
- pXIClient = dixLookupPrivate(&pClient->devPrivates, XIClientPrivateKey);
- pXIClient->major_version = 0;
- pXIClient->minor_version = 0;
-}
-
-/*************************************************************************
- *
- * ProcIDispatch - main dispatch routine for requests to this extension.
- * This routine is used if server and client have the same byte ordering.
- *
- */
-
-static int
-ProcIDispatch(ClientPtr client)
-{
- REQUEST(xReq);
- if (stuff->data > (IREQUESTS + XI2REQUESTS) || !ProcIVector[stuff->data])
- return BadRequest;
-
- return (*ProcIVector[stuff->data])(client);
-}
-
-/*******************************************************************************
- *
- * SProcXDispatch
- *
- * Main swapped dispatch routine for requests to this extension.
- * This routine is used if server and client do not have the same byte ordering.
- *
- */
-
-static int
-SProcIDispatch(ClientPtr client)
-{
- REQUEST(xReq);
- if (stuff->data > IREQUESTS || !SProcIVector[stuff->data])
- return BadRequest;
-
- return (*SProcIVector[stuff->data])(client);
-}
-
-/**********************************************************************
- *
- * SReplyIDispatch
- * Swap any replies defined in this extension.
- *
- */
-
-static void
-SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
- /* All we look at is the type field */
-{ /* This is common to all replies */
- if (rep->RepType == X_GetExtensionVersion)
- SRepXGetExtensionVersion(client, len,
- (xGetExtensionVersionReply *) rep);
- else if (rep->RepType == X_ListInputDevices)
- SRepXListInputDevices(client, len, (xListInputDevicesReply *) rep);
- else if (rep->RepType == X_OpenDevice)
- SRepXOpenDevice(client, len, (xOpenDeviceReply *) rep);
- else if (rep->RepType == X_SetDeviceMode)
- SRepXSetDeviceMode(client, len, (xSetDeviceModeReply *) rep);
- else if (rep->RepType == X_GetSelectedExtensionEvents)
- SRepXGetSelectedExtensionEvents(client, len,
- (xGetSelectedExtensionEventsReply *)
- rep);
- else if (rep->RepType == X_GetDeviceDontPropagateList)
- SRepXGetDeviceDontPropagateList(client, len,
- (xGetDeviceDontPropagateListReply *)
- rep);
- else if (rep->RepType == X_GetDeviceMotionEvents)
- SRepXGetDeviceMotionEvents(client, len,
- (xGetDeviceMotionEventsReply *) rep);
- else if (rep->RepType == X_GrabDevice)
- SRepXGrabDevice(client, len, (xGrabDeviceReply *) rep);
- else if (rep->RepType == X_GetDeviceFocus)
- SRepXGetDeviceFocus(client, len, (xGetDeviceFocusReply *) rep);
- else if (rep->RepType == X_GetFeedbackControl)
- SRepXGetFeedbackControl(client, len, (xGetFeedbackControlReply *) rep);
- else if (rep->RepType == X_GetDeviceKeyMapping)
- SRepXGetDeviceKeyMapping(client, len,
- (xGetDeviceKeyMappingReply *) rep);
- else if (rep->RepType == X_GetDeviceModifierMapping)
- SRepXGetDeviceModifierMapping(client, len,
- (xGetDeviceModifierMappingReply *) rep);
- else if (rep->RepType == X_SetDeviceModifierMapping)
- SRepXSetDeviceModifierMapping(client, len,
- (xSetDeviceModifierMappingReply *) rep);
- else if (rep->RepType == X_GetDeviceButtonMapping)
- SRepXGetDeviceButtonMapping(client, len,
- (xGetDeviceButtonMappingReply *) rep);
- else if (rep->RepType == X_SetDeviceButtonMapping)
- SRepXSetDeviceButtonMapping(client, len,
- (xSetDeviceButtonMappingReply *) rep);
- else if (rep->RepType == X_QueryDeviceState)
- SRepXQueryDeviceState(client, len, (xQueryDeviceStateReply *) rep);
- else if (rep->RepType == X_SetDeviceValuators)
- SRepXSetDeviceValuators(client, len, (xSetDeviceValuatorsReply *) rep);
- else if (rep->RepType == X_GetDeviceControl)
- SRepXGetDeviceControl(client, len, (xGetDeviceControlReply *) rep);
- else if (rep->RepType == X_ChangeDeviceControl)
- SRepXChangeDeviceControl(client, len,
- (xChangeDeviceControlReply *) rep);
- else if (rep->RepType == X_ListDeviceProperties)
- SRepXListDeviceProperties(client, len, (xListDevicePropertiesReply*)rep);
- else if (rep->RepType == X_GetDeviceProperty)
- SRepXGetDeviceProperty(client, len, (xGetDevicePropertyReply *) rep);
- else if (rep->RepType == X_XIQueryPointer)
- SRepXIQueryPointer(client, len, (xXIQueryPointerReply *) rep);
- else if (rep->RepType == X_XIGetClientPointer)
- SRepXIGetClientPointer(client, len, (xXIGetClientPointerReply*) rep);
- else if (rep->RepType == X_XIQueryVersion)
- SRepXIQueryVersion(client, len, (xXIQueryVersionReply*)rep);
- else if (rep->RepType == X_XIQueryDevice)
- SRepXIQueryDevice(client, len, (xXIQueryDeviceReply*)rep);
- else if (rep->RepType == X_XIGrabDevice)
- SRepXIGrabDevice(client, len, (xXIGrabDeviceReply *) rep);
- else if (rep->RepType == X_XIGrabDevice)
- SRepXIPassiveGrabDevice(client, len, (xXIPassiveGrabDeviceReply *) rep);
- else if (rep->RepType == X_XIListProperties)
- SRepXIListProperties(client, len, (xXIListPropertiesReply *) rep);
- else if (rep->RepType == X_XIGetProperty)
- SRepXIGetProperty(client, len, (xXIGetPropertyReply *) rep);
- else if (rep->RepType == X_XIGetSelectedEvents)
- SRepXIGetSelectedEvents(client, len, (xXIGetSelectedEventsReply *) rep);
- else if (rep->RepType == X_XIGetFocus)
- SRepXIGetFocus(client, len, (xXIGetFocusReply *) rep);
- else {
- FatalError("XINPUT confused sending swapped reply");
- }
-}
-
-/************************************************************************
- *
- * This function swaps the DeviceValuator event.
- *
- */
-
-static void
-SEventDeviceValuator(deviceValuator * from, deviceValuator * to)
-{
- char n;
- int i;
- INT32 *ip B32;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swaps(&to->device_state, n);
- ip = &to->valuator0;
- for (i = 0; i < 6; i++) {
- swapl((ip + i), n); /* macro - braces are required */
- }
-}
-
-static void
-SEventFocus(deviceFocus * from, deviceFocus * to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swapl(&to->time, n);
- swapl(&to->window, n);
-}
-
-static void
-SDeviceStateNotifyEvent(deviceStateNotify * from, deviceStateNotify * to)
-{
- int i;
- char n;
- INT32 *ip B32;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swapl(&to->time, n);
- ip = &to->valuator0;
- for (i = 0; i < 3; i++) {
- swapl((ip + i), n); /* macro - braces are required */
- }
-}
-
-static void
-SDeviceKeyStateNotifyEvent(deviceKeyStateNotify * from,
- deviceKeyStateNotify * to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
-}
-
-static void
-SDeviceButtonStateNotifyEvent(deviceButtonStateNotify * from,
- deviceButtonStateNotify * to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
-}
-
-static void
-SChangeDeviceNotifyEvent(changeDeviceNotify * from, changeDeviceNotify * to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swapl(&to->time, n);
-}
-
-static void
-SDeviceMappingNotifyEvent(deviceMappingNotify * from, deviceMappingNotify * to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swapl(&to->time, n);
-}
-
-static void
-SDevicePresenceNotifyEvent (devicePresenceNotify *from, devicePresenceNotify *to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber,n);
- swapl(&to->time, n);
- swaps(&to->control, n);
-}
-
-static void
-SDevicePropertyNotifyEvent (devicePropertyNotify *from, devicePropertyNotify *to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber,n);
- swapl(&to->time, n);
- swapl(&to->atom, n);
-}
-
-static void
-SDeviceLeaveNotifyEvent (xXILeaveEvent *from, xXILeaveEvent *to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber,n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->time, n);
- swapl(&to->root, n);
- swapl(&to->event, n);
- swapl(&to->child, n);
- swapl(&to->root_x, n);
- swapl(&to->root_y, n);
- swapl(&to->event_x, n);
- swapl(&to->event_y, n);
- swaps(&to->sourceid, n);
- swaps(&to->buttons_len, n);
- swapl(&to->mods.base_mods, n);
- swapl(&to->mods.latched_mods, n);
- swapl(&to->mods.locked_mods, n);
-}
-
-static void
-SDeviceChangedEvent(xXIDeviceChangedEvent* from, xXIDeviceChangedEvent* to)
-{
- char n;
- int i, j;
- xXIAnyInfo *any;
-
- *to = *from;
- memcpy(&to[1], &from[1], from->length * 4);
-
- any = (xXIAnyInfo*)&to[1];
- for (i = 0; i < to->num_classes; i++)
- {
- int length = any->length;
-
- switch(any->type)
- {
- case KeyClass:
- {
- xXIKeyInfo *ki = (xXIKeyInfo*)any;
- uint32_t *key = (uint32_t*)&ki[1];
- for (j = 0; j < ki->num_keycodes; j++, key++)
- swapl(key, n);
- swaps(&ki->num_keycodes, n);
- }
- break;
- case ButtonClass:
- {
- xXIButtonInfo *bi = (xXIButtonInfo*)any;
- Atom *labels = (Atom*)((char*)bi + sizeof(xXIButtonInfo) +
- pad_to_int32(bits_to_bytes(bi->num_buttons)));
- for (j = 0; j < bi->num_buttons; j++)
- swapl(&labels[j], n);
- swaps(&bi->num_buttons, n);
- }
- break;
- case ValuatorClass:
- {
- xXIValuatorInfo* ai = (xXIValuatorInfo*)any;
- swapl(&ai->label, n);
- swapl(&ai->min.integral, n);
- swapl(&ai->min.frac, n);
- swapl(&ai->max.integral, n);
- swapl(&ai->max.frac, n);
- swapl(&ai->resolution, n);
- swaps(&ai->number, n);
- }
- break;
- }
-
- swaps(&any->type, n);
- swaps(&any->length, n);
- swaps(&any->sourceid, n);
-
- any = (xXIAnyInfo*)((char*)any + length * 4);
- }
-
- swaps(&to->sequenceNumber, n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->time, n);
- swaps(&to->num_classes, n);
- swaps(&to->sourceid, n);
-
-}
-
-static void SDeviceEvent(xXIDeviceEvent *from, xXIDeviceEvent *to)
-{
- int i;
- char n;
- char *ptr;
- char *vmask;
-
- memcpy(to, from, sizeof(xEvent) + from->length * 4);
-
- swaps(&to->sequenceNumber, n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->time, n);
- swapl(&to->detail, n);
- swapl(&to->root, n);
- swapl(&to->event, n);
- swapl(&to->child, n);
- swapl(&to->root_x, n);
- swapl(&to->root_y, n);
- swapl(&to->event_x, n);
- swapl(&to->event_y, n);
- swaps(&to->buttons_len, n);
- swaps(&to->valuators_len, n);
- swaps(&to->sourceid, n);
- swapl(&to->mods.base_mods, n);
- swapl(&to->mods.latched_mods, n);
- swapl(&to->mods.locked_mods, n);
- swapl(&to->mods.effective_mods, n);
-
- ptr = (char*)(&to[1]);
- ptr += from->buttons_len * 4;
- vmask = ptr; /* valuator mask */
- ptr += from->valuators_len * 4;
- for (i = 0; i < from->valuators_len * 32; i++)
- {
- if (BitIsOn(vmask, i))
- {
- swapl(((uint32_t*)ptr), n);
- ptr += 4;
- swapl(((uint32_t*)ptr), n);
- ptr += 4;
- }
- }
-}
-
-static void SDeviceHierarchyEvent(xXIHierarchyEvent *from,
- xXIHierarchyEvent *to)
-{
- int i;
- char n;
- xXIHierarchyInfo *info;
-
- *to = *from;
- memcpy(&to[1], &from[1], from->length * 4);
- swaps(&to->sequenceNumber, n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->time, n);
- swapl(&to->flags, n);
- swaps(&to->num_info, n);
-
- info = (xXIHierarchyInfo*)&to[1];
- for (i = 0; i< from->num_info; i++)
- {
- swaps(&info->deviceid, n);
- swaps(&info->attachment, n);
- info++;
- }
-}
-
-static void SXIPropertyEvent(xXIPropertyEvent *from, xXIPropertyEvent *to)
-{
- char n;
-
- *to = *from;
- swaps(&to->sequenceNumber, n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->property, n);
-}
-
-static void SRawEvent(xXIRawEvent *from, xXIRawEvent *to)
-{
- char n;
- int i;
- FP3232 *values;
- unsigned char *mask;
-
- memcpy(to, from, sizeof(xEvent) + from->length * 4);
-
- swaps(&to->sequenceNumber, n);
- swapl(&to->length, n);
- swaps(&to->evtype, n);
- swaps(&to->deviceid, n);
- swapl(&to->time, n);
- swapl(&to->detail, n);
-
-
- mask = (unsigned char*)&to[1];
- values = (FP3232*)(mask + from->valuators_len * 4);
-
- for (i = 0; i < from->valuators_len * 4 * 8; i++)
- {
- if (BitIsOn(mask, i))
- {
- /* for each bit set there are two FP3232 values on the wire, in
- * the order abcABC for data and data_raw. Here we swap as if
- * they were in aAbBcC order because it's easier and really
- * doesn't matter.
- */
- swapl(&values->integral, n);
- swapl(&values->frac, n);
- values++;
- swapl(&values->integral, n);
- swapl(&values->frac, n);
- values++;
- }
- }
-
- swaps(&to->valuators_len, n);
-}
-
-
-/** Event swapping function for XI2 events. */
-void
-XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
-{
- switch(from->evtype)
- {
- case XI_Enter:
- case XI_Leave:
- SDeviceLeaveNotifyEvent((xXILeaveEvent*)from, (xXILeaveEvent*)to);
- break;
- case XI_DeviceChanged:
- SDeviceChangedEvent((xXIDeviceChangedEvent*)from,
- (xXIDeviceChangedEvent*)to);
- break;
- case XI_HierarchyChanged:
- SDeviceHierarchyEvent((xXIHierarchyEvent*)from, (xXIHierarchyEvent*)to);
- break;
- case XI_PropertyEvent:
- SXIPropertyEvent((xXIPropertyEvent*)from,
- (xXIPropertyEvent*)to);
- break;
- case XI_Motion:
- case XI_KeyPress:
- case XI_KeyRelease:
- case XI_ButtonPress:
- case XI_ButtonRelease:
- SDeviceEvent((xXIDeviceEvent*)from, (xXIDeviceEvent*)to);
- break;
- case XI_RawMotion:
- case XI_RawKeyPress:
- case XI_RawKeyRelease:
- case XI_RawButtonPress:
- case XI_RawButtonRelease:
- SRawEvent((xXIRawEvent*)from, (xXIRawEvent*)to);
- break;
- default:
- ErrorF("[Xi] Unknown event type to swap. This is a bug.\n");
- break;
- }
-}
-
-/**************************************************************************
- *
- * Allow the specified event to have its propagation suppressed.
- * The default is to not allow suppression of propagation.
- *
- */
-
-static void
-AllowPropagateSuppress(Mask mask)
-{
- int i;
-
- for (i = 0; i < MAXDEVICES; i++)
- PropagateMask[i] |= mask;
-}
-
-/**************************************************************************
- *
- * Record an event mask where there is no unique corresponding event type.
- * We can't call SetMaskForEvent, since that would clobber the existing
- * mask for that event. MotionHint and ButtonMotion are examples.
- *
- * Since extension event types will never be less than 64, we can use
- * 0-63 in the EventInfo array as the "type" to be used to look up this
- * mask. This means that the corresponding macros such as
- * DevicePointerMotionHint must have access to the same constants.
- *
- */
-
-static void
-SetEventInfo(Mask mask, int constant)
-{
- EventInfo[ExtEventIndex].mask = mask;
- EventInfo[ExtEventIndex++].type = constant;
-}
-
-/**************************************************************************
- *
- * Allow the specified event to be restricted to being selected by one
- * client at a time.
- * The default is to allow more than one client to select the event.
- *
- */
-
-static void
-SetExclusiveAccess(Mask mask)
-{
- int i;
-
- for (i = 0; i < MAXDEVICES; i++)
- ExtExclusiveMasks[i] |= mask;
-}
-
-/**************************************************************************
- *
- * Assign the specified mask to the specified event.
- *
- */
-
-static void
-SetMaskForExtEvent(Mask mask, int event)
-{
- int i;
-
- EventInfo[ExtEventIndex].mask = mask;
- EventInfo[ExtEventIndex++].type = event;
-
- if ((event < LASTEvent) || (event >= 128))
- FatalError("MaskForExtensionEvent: bogus event number");
-
- for (i = 0; i < MAXDEVICES; i++)
- SetMaskForEvent(i, mask, event);
-}
-
-/************************************************************************
- *
- * This function sets up extension event types and masks.
- *
- */
-
-static void
-FixExtensionEvents(ExtensionEntry * extEntry)
-{
- DeviceValuator = extEntry->eventBase;
- DeviceKeyPress = DeviceValuator + 1;
- DeviceKeyRelease = DeviceKeyPress + 1;
- DeviceButtonPress = DeviceKeyRelease + 1;
- DeviceButtonRelease = DeviceButtonPress + 1;
- DeviceMotionNotify = DeviceButtonRelease + 1;
- DeviceFocusIn = DeviceMotionNotify + 1;
- DeviceFocusOut = DeviceFocusIn + 1;
- ProximityIn = DeviceFocusOut + 1;
- ProximityOut = ProximityIn + 1;
- DeviceStateNotify = ProximityOut + 1;
- DeviceMappingNotify = DeviceStateNotify + 1;
- ChangeDeviceNotify = DeviceMappingNotify + 1;
- DeviceKeyStateNotify = ChangeDeviceNotify + 1;
- DeviceButtonStateNotify = DeviceKeyStateNotify + 1;
- DevicePresenceNotify = DeviceButtonStateNotify + 1;
- DevicePropertyNotify = DevicePresenceNotify + 1;
-
- event_base[KeyClass] = DeviceKeyPress;
- event_base[ButtonClass] = DeviceButtonPress;
- event_base[ValuatorClass] = DeviceMotionNotify;
- event_base[ProximityClass] = ProximityIn;
- event_base[FocusClass] = DeviceFocusIn;
- event_base[OtherClass] = DeviceStateNotify;
-
- BadDevice += extEntry->errorBase;
- BadEvent += extEntry->errorBase;
- BadMode += extEntry->errorBase;
- DeviceBusy += extEntry->errorBase;
- BadClass += extEntry->errorBase;
-
- SetMaskForExtEvent(DeviceKeyPressMask, DeviceKeyPress);
- AllowPropagateSuppress(DeviceKeyPressMask);
- SetCriticalEvent(DeviceKeyPress);
-
- SetMaskForExtEvent(DeviceKeyReleaseMask, DeviceKeyRelease);
- AllowPropagateSuppress(DeviceKeyReleaseMask);
- SetCriticalEvent(DeviceKeyRelease);
-
- SetMaskForExtEvent(DeviceButtonPressMask, DeviceButtonPress);
- AllowPropagateSuppress(DeviceButtonPressMask);
- SetCriticalEvent(DeviceButtonPress);
-
- SetMaskForExtEvent(DeviceButtonReleaseMask, DeviceButtonRelease);
- AllowPropagateSuppress(DeviceButtonReleaseMask);
- SetCriticalEvent(DeviceButtonRelease);
-
- SetMaskForExtEvent(DeviceProximityMask, ProximityIn);
- SetMaskForExtEvent(DeviceProximityMask, ProximityOut);
-
- SetMaskForExtEvent(DeviceStateNotifyMask, DeviceStateNotify);
-
- SetMaskForExtEvent(DevicePointerMotionMask, DeviceMotionNotify);
- AllowPropagateSuppress(DevicePointerMotionMask);
- SetCriticalEvent(DeviceMotionNotify);
-
- SetEventInfo(DevicePointerMotionHintMask, _devicePointerMotionHint);
- SetEventInfo(DeviceButton1MotionMask, _deviceButton1Motion);
- SetEventInfo(DeviceButton2MotionMask, _deviceButton2Motion);
- SetEventInfo(DeviceButton3MotionMask, _deviceButton3Motion);
- SetEventInfo(DeviceButton4MotionMask, _deviceButton4Motion);
- SetEventInfo(DeviceButton5MotionMask, _deviceButton5Motion);
- SetEventInfo(DeviceButtonMotionMask, _deviceButtonMotion);
-
- SetMaskForExtEvent(DeviceFocusChangeMask, DeviceFocusIn);
- SetMaskForExtEvent(DeviceFocusChangeMask, DeviceFocusOut);
-
- SetMaskForExtEvent(DeviceMappingNotifyMask, DeviceMappingNotify);
- SetMaskForExtEvent(ChangeDeviceNotifyMask, ChangeDeviceNotify);
-
- SetEventInfo(DeviceButtonGrabMask, _deviceButtonGrab);
- SetExclusiveAccess(DeviceButtonGrabMask);
-
- SetEventInfo(DeviceOwnerGrabButtonMask, _deviceOwnerGrabButton);
- SetEventInfo(DevicePresenceNotifyMask, _devicePresence);
- SetMaskForExtEvent(DevicePropertyNotifyMask, DevicePropertyNotify);
-
- SetEventInfo(0, _noExtensionEvent);
-}
-
-/************************************************************************
- *
- * This function restores extension event types and masks to their
- * initial state.
- *
- */
-
-static void
-RestoreExtensionEvents(void)
-{
- int i, j;
-
- IReqCode = 0;
- IEventBase = 0;
-
- for (i = 0; i < ExtEventIndex - 1; i++) {
- if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
- {
- for (j = 0; j < MAXDEVICES; j++)
- SetMaskForEvent(j, 0, EventInfo[i].type);
- }
- EventInfo[i].mask = 0;
- EventInfo[i].type = 0;
- }
- ExtEventIndex = 0;
- DeviceValuator = 0;
- DeviceKeyPress = 1;
- DeviceKeyRelease = 2;
- DeviceButtonPress = 3;
- DeviceButtonRelease = 4;
- DeviceMotionNotify = 5;
- DeviceFocusIn = 6;
- DeviceFocusOut = 7;
- ProximityIn = 8;
- ProximityOut = 9;
- DeviceStateNotify = 10;
- DeviceMappingNotify = 11;
- ChangeDeviceNotify = 12;
- DeviceKeyStateNotify = 13;
- DeviceButtonStateNotify = 13;
- DevicePresenceNotify = 14;
- DevicePropertyNotify = 15;
-
- BadDevice = 0;
- BadEvent = 1;
- BadMode = 2;
- DeviceBusy = 3;
- BadClass = 4;
-
-}
-
-/***********************************************************************
- *
- * IResetProc.
- * Remove reply-swapping routine.
- * Remove event-swapping routine.
- *
- */
-
-static void
-IResetProc(ExtensionEntry * unused)
-{
-
- ReplySwapVector[IReqCode] = ReplyNotSwappd;
- EventSwapVector[DeviceValuator] = NotImplemented;
- EventSwapVector[DeviceKeyPress] = NotImplemented;
- EventSwapVector[DeviceKeyRelease] = NotImplemented;
- EventSwapVector[DeviceButtonPress] = NotImplemented;
- EventSwapVector[DeviceButtonRelease] = NotImplemented;
- EventSwapVector[DeviceMotionNotify] = NotImplemented;
- EventSwapVector[DeviceFocusIn] = NotImplemented;
- EventSwapVector[DeviceFocusOut] = NotImplemented;
- EventSwapVector[ProximityIn] = NotImplemented;
- EventSwapVector[ProximityOut] = NotImplemented;
- EventSwapVector[DeviceStateNotify] = NotImplemented;
- EventSwapVector[DeviceKeyStateNotify] = NotImplemented;
- EventSwapVector[DeviceButtonStateNotify] = NotImplemented;
- EventSwapVector[DeviceMappingNotify] = NotImplemented;
- EventSwapVector[ChangeDeviceNotify] = NotImplemented;
- EventSwapVector[DevicePresenceNotify] = NotImplemented;
- EventSwapVector[DevicePropertyNotify] = NotImplemented;
- RestoreExtensionEvents();
-}
-
-
-/***********************************************************************
- *
- * Assign an id and type to an input device.
- *
- */
-
-void
-AssignTypeAndName(DeviceIntPtr dev, Atom type, char *name)
-{
- dev->xinput_type = type;
- dev->name = (char *)xalloc(strlen(name) + 1);
- strcpy(dev->name, name);
-}
-
-/***********************************************************************
- *
- * Make device type atoms.
- *
- */
-
-static void
-MakeDeviceTypeAtoms(void)
-{
- int i;
-
- for (i = 0; i < NUMTYPES; i++)
- dev_type[i].type =
- MakeAtom(dev_type[i].name, strlen(dev_type[i].name), 1);
-}
-
-/*****************************************************************************
- *
- * SEventIDispatch
- *
- * Swap any events defined in this extension.
- */
-#define DO_SWAP(func,type) func ((type *)from, (type *)to)
-
-static void
-SEventIDispatch(xEvent * from, xEvent * to)
-{
- int type = from->u.u.type & 0177;
-
- if (type == DeviceValuator)
- DO_SWAP(SEventDeviceValuator, deviceValuator);
- else if (type == DeviceKeyPress) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceKeyRelease) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceButtonPress) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceButtonRelease) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceMotionNotify) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceFocusIn)
- DO_SWAP(SEventFocus, deviceFocus);
- else if (type == DeviceFocusOut)
- DO_SWAP(SEventFocus, deviceFocus);
- else if (type == ProximityIn) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == ProximityOut) {
- SKeyButtonPtrEvent(from, to);
- to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
- } else if (type == DeviceStateNotify)
- DO_SWAP(SDeviceStateNotifyEvent, deviceStateNotify);
- else if (type == DeviceKeyStateNotify)
- DO_SWAP(SDeviceKeyStateNotifyEvent, deviceKeyStateNotify);
- else if (type == DeviceButtonStateNotify)
- DO_SWAP(SDeviceButtonStateNotifyEvent, deviceButtonStateNotify);
- else if (type == DeviceMappingNotify)
- DO_SWAP(SDeviceMappingNotifyEvent, deviceMappingNotify);
- else if (type == ChangeDeviceNotify)
- DO_SWAP(SChangeDeviceNotifyEvent, changeDeviceNotify);
- else if (type == DevicePresenceNotify)
- DO_SWAP(SDevicePresenceNotifyEvent, devicePresenceNotify);
- else if (type == DevicePropertyNotify)
- DO_SWAP(SDevicePropertyNotifyEvent, devicePropertyNotify);
- else {
- FatalError("XInputExtension: Impossible event!\n");
- }
-}
-
-/**********************************************************************
- *
- * IExtensionInit - initialize the input extension.
- *
- * Called from InitExtensions in main() or from QueryExtension() if the
- * extension is dynamically loaded.
- *
- * This extension has several events and errors.
- *
- * XI is mandatory nowadays, so if we fail to init XI, we die.
- */
-
-void
-XInputExtensionInit(void)
-{
- ExtensionEntry *extEntry;
- XExtensionVersion thisversion = { XI_Present,
- SERVER_XI_MAJOR_VERSION,
- SERVER_XI_MINOR_VERSION,
- };
-
- if (!dixRequestPrivate(XIClientPrivateKey, sizeof(XIClientRec)))
- FatalError("Cannot request private for XI.\n");
-
- if (!AddCallback(&ClientStateCallback, XIClientCallback, 0))
- FatalError("Failed to add callback to XI.\n");
-
- extEntry = AddExtension(INAME, IEVENTS, IERRORS, ProcIDispatch,
- SProcIDispatch, IResetProc, StandardMinorOpcode);
- if (extEntry) {
- IReqCode = extEntry->base;
- IEventBase = extEntry->eventBase;
- XIVersion = thisversion;
- MakeDeviceTypeAtoms();
- RT_INPUTCLIENT = CreateNewResourceType((DeleteType) InputClientGone,
- "INPUTCLIENT");
- if (!RT_INPUTCLIENT)
- FatalError("Failed to add resource type for XI.\n");
- FixExtensionEvents(extEntry);
- ReplySwapVector[IReqCode] = (ReplySwapPtr) SReplyIDispatch;
- EventSwapVector[DeviceValuator] = SEventIDispatch;
- EventSwapVector[DeviceKeyPress] = SEventIDispatch;
- EventSwapVector[DeviceKeyRelease] = SEventIDispatch;
- EventSwapVector[DeviceButtonPress] = SEventIDispatch;
- EventSwapVector[DeviceButtonRelease] = SEventIDispatch;
- EventSwapVector[DeviceMotionNotify] = SEventIDispatch;
- EventSwapVector[DeviceFocusIn] = SEventIDispatch;
- EventSwapVector[DeviceFocusOut] = SEventIDispatch;
- EventSwapVector[ProximityIn] = SEventIDispatch;
- EventSwapVector[ProximityOut] = SEventIDispatch;
- EventSwapVector[DeviceStateNotify] = SEventIDispatch;
- EventSwapVector[DeviceKeyStateNotify] = SEventIDispatch;
- EventSwapVector[DeviceButtonStateNotify] = SEventIDispatch;
- EventSwapVector[DeviceMappingNotify] = SEventIDispatch;
- EventSwapVector[ChangeDeviceNotify] = SEventIDispatch;
- EventSwapVector[DevicePresenceNotify] = SEventIDispatch;
-
- GERegisterExtension(IReqCode, XI2EventSwap);
-
-
- memset(&xi_all_devices, 0, sizeof(xi_all_devices));
- memset(&xi_all_master_devices, 0, sizeof(xi_all_master_devices));
- xi_all_devices.id = XIAllDevices;
- xi_all_devices.name = "XIAllDevices";
- xi_all_master_devices.id = XIAllMasterDevices;
- xi_all_master_devices.name = "XIAllMasterDevices";
-
- inputInfo.all_devices = &xi_all_devices;
- inputInfo.all_master_devices = &xi_all_master_devices;
- } else {
- FatalError("IExtensionInit: AddExtensions failed\n");
- }
-}
-
+/************************************************************
+
+Copyright 1989, 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 1989 by Hewlett-Packard Company, Palo Alto, California.
+
+ 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 Hewlett-Packard not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+HEWLETT-PACKARD 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.
+
+********************************************************/
+
+/********************************************************************
+ *
+ * Dispatch routines and initialization routines for the X input extension.
+ *
+ */
+
+#define NUMTYPES 15
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "inputstr.h"
+#include "gcstruct.h" /* pointer for extnsionst.h */
+#include "extnsionst.h" /* extension entry */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include <X11/extensions/XI2proto.h>
+#include <X11/extensions/geproto.h>
+#include "geext.h" /* extension interfaces for ge */
+
+#include "dixevents.h"
+#include "exevents.h"
+#include "extinit.h"
+#include "exglobals.h"
+#include "swaprep.h"
+#include "privates.h"
+#include "protocol-versions.h"
+
+/* modules local to Xi */
+#include "allowev.h"
+#include "chgdctl.h"
+#include "chgfctl.h"
+#include "chgkbd.h"
+#include "chgprop.h"
+#include "chgptr.h"
+#include "closedev.h"
+#include "devbell.h"
+#include "getbmap.h"
+#include "getbmap.h"
+#include "getdctl.h"
+#include "getfctl.h"
+#include "getfocus.h"
+#include "getkmap.h"
+#include "getmmap.h"
+#include "getprop.h"
+#include "getselev.h"
+#include "getvers.h"
+#include "getvers.h"
+#include "grabdev.h"
+#include "grabdevb.h"
+#include "grabdevk.h"
+#include "gtmotion.h"
+#include "listdev.h"
+#include "opendev.h"
+#include "queryst.h"
+#include "selectev.h"
+#include "sendexev.h"
+#include "chgkmap.h"
+#include "setbmap.h"
+#include "setdval.h"
+#include "setfocus.h"
+#include "setmmap.h"
+#include "setmode.h"
+#include "ungrdev.h"
+#include "ungrdevb.h"
+#include "ungrdevk.h"
+#include "xiallowev.h"
+#include "xiselectev.h"
+#include "xigrabdev.h"
+#include "xipassivegrab.h"
+#include "xisetdevfocus.h"
+#include "xiproperty.h"
+#include "xichangecursor.h"
+#include "xichangehierarchy.h"
+#include "xigetclientpointer.h"
+#include "xiquerydevice.h"
+#include "xiquerypointer.h"
+#include "xiqueryversion.h"
+#include "xisetclientpointer.h"
+#include "xiwarppointer.h"
+
+
+/* Masks for XI events have to be aligned with core event (partially anyway).
+ * If DeviceButtonMotionMask is != ButtonMotionMask, event delivery
+ * breaks down. The device needs the dev->button->motionMask. If DBMM is
+ * the same as BMM, we can ensure that both core and device events can be
+ * delivered, without the need for extra structures in the DeviceIntRec. */
+const Mask DeviceKeyPressMask = KeyPressMask;
+const Mask DeviceKeyReleaseMask = KeyReleaseMask;
+const Mask DeviceButtonPressMask = ButtonPressMask;
+const Mask DeviceButtonReleaseMask = ButtonReleaseMask;
+const Mask DeviceProximityMask = (1L << 4);
+const Mask DeviceStateNotifyMask = (1L << 5);
+const Mask DevicePointerMotionMask = PointerMotionMask;
+const Mask DevicePointerMotionHintMask = PointerMotionHintMask;
+const Mask DeviceButton1MotionMask = Button1MotionMask;
+const Mask DeviceButton2MotionMask = Button2MotionMask;
+const Mask DeviceButton3MotionMask = Button3MotionMask;
+const Mask DeviceButton4MotionMask = Button4MotionMask;
+const Mask DeviceButton5MotionMask = Button5MotionMask;
+const Mask DeviceButtonMotionMask = ButtonMotionMask;
+const Mask DeviceFocusChangeMask = (1L << 14);
+const Mask DeviceMappingNotifyMask = (1L << 15);
+const Mask ChangeDeviceNotifyMask = (1L << 16);
+const Mask DeviceButtonGrabMask = (1L << 17);
+const Mask DeviceOwnerGrabButtonMask = (1L << 17);
+const Mask DevicePresenceNotifyMask = (1L << 18);
+const Mask DeviceEnterWindowMask = (1L << 18);
+const Mask DeviceLeaveWindowMask = (1L << 19);
+const Mask DevicePropertyNotifyMask = (1L << 20);
+const Mask XIAllMasks = (1L << 21) - 1;
+
+int ExtEventIndex;
+Mask ExtExclusiveMasks[EMASKSIZE];
+
+static struct dev_type
+{
+ Atom type;
+ char *name;
+} dev_type[] = {
+ {
+ 0, XI_KEYBOARD}, {
+ 0, XI_MOUSE}, {
+ 0, XI_TABLET}, {
+ 0, XI_TOUCHSCREEN}, {
+ 0, XI_TOUCHPAD}, {
+ 0, XI_BARCODE}, {
+ 0, XI_BUTTONBOX}, {
+ 0, XI_KNOB_BOX}, {
+ 0, XI_ONE_KNOB}, {
+ 0, XI_NINE_KNOB}, {
+ 0, XI_TRACKBALL}, {
+ 0, XI_QUADRATURE}, {
+ 0, XI_ID_MODULE}, {
+ 0, XI_SPACEBALL}, {
+ 0, XI_DATAGLOVE}, {
+ 0, XI_EYETRACKER}, {
+ 0, XI_CURSORKEYS}, {
+0, XI_FOOTMOUSE}};
+
+CARD8 event_base[numInputClasses];
+XExtEventInfo EventInfo[32];
+
+static DeviceIntRec xi_all_devices;
+static DeviceIntRec xi_all_master_devices;
+
+/**
+ * Dispatch vector. Functions defined in here will be called when the matching
+ * request arrives.
+ */
+static int (*ProcIVector[])(ClientPtr) = {
+ NULL, /* 0 */
+ ProcXGetExtensionVersion, /* 1 */
+ ProcXListInputDevices, /* 2 */
+ ProcXOpenDevice, /* 3 */
+ ProcXCloseDevice, /* 4 */
+ ProcXSetDeviceMode, /* 5 */
+ ProcXSelectExtensionEvent, /* 6 */
+ ProcXGetSelectedExtensionEvents, /* 7 */
+ ProcXChangeDeviceDontPropagateList, /* 8 */
+ ProcXGetDeviceDontPropagateList, /* 9 */
+ ProcXGetDeviceMotionEvents, /* 10 */
+ ProcXChangeKeyboardDevice, /* 11 */
+ ProcXChangePointerDevice, /* 12 */
+ ProcXGrabDevice, /* 13 */
+ ProcXUngrabDevice, /* 14 */
+ ProcXGrabDeviceKey, /* 15 */
+ ProcXUngrabDeviceKey, /* 16 */
+ ProcXGrabDeviceButton, /* 17 */
+ ProcXUngrabDeviceButton, /* 18 */
+ ProcXAllowDeviceEvents, /* 19 */
+ ProcXGetDeviceFocus, /* 20 */
+ ProcXSetDeviceFocus, /* 21 */
+ ProcXGetFeedbackControl, /* 22 */
+ ProcXChangeFeedbackControl, /* 23 */
+ ProcXGetDeviceKeyMapping, /* 24 */
+ ProcXChangeDeviceKeyMapping, /* 25 */
+ ProcXGetDeviceModifierMapping, /* 26 */
+ ProcXSetDeviceModifierMapping, /* 27 */
+ ProcXGetDeviceButtonMapping, /* 28 */
+ ProcXSetDeviceButtonMapping, /* 29 */
+ ProcXQueryDeviceState, /* 30 */
+ ProcXSendExtensionEvent, /* 31 */
+ ProcXDeviceBell, /* 32 */
+ ProcXSetDeviceValuators, /* 33 */
+ ProcXGetDeviceControl, /* 34 */
+ ProcXChangeDeviceControl, /* 35 */
+ /* XI 1.5 */
+ ProcXListDeviceProperties, /* 36 */
+ ProcXChangeDeviceProperty, /* 37 */
+ ProcXDeleteDeviceProperty, /* 38 */
+ ProcXGetDeviceProperty, /* 39 */
+ /* XI 2 */
+ ProcXIQueryPointer, /* 40 */
+ ProcXIWarpPointer, /* 41 */
+ ProcXIChangeCursor, /* 42 */
+ ProcXIChangeHierarchy, /* 43 */
+ ProcXISetClientPointer, /* 44 */
+ ProcXIGetClientPointer, /* 45 */
+ ProcXISelectEvents, /* 46 */
+ ProcXIQueryVersion, /* 47 */
+ ProcXIQueryDevice, /* 48 */
+ ProcXISetFocus, /* 49 */
+ ProcXIGetFocus, /* 50 */
+ ProcXIGrabDevice, /* 51 */
+ ProcXIUngrabDevice, /* 52 */
+ ProcXIAllowEvents, /* 53 */
+ ProcXIPassiveGrabDevice, /* 54 */
+ ProcXIPassiveUngrabDevice, /* 55 */
+ ProcXIListProperties, /* 56 */
+ ProcXIChangeProperty, /* 57 */
+ ProcXIDeleteProperty, /* 58 */
+ ProcXIGetProperty, /* 59 */
+ ProcXIGetSelectedEvents /* 60 */
+};
+
+/* For swapped clients */
+static int (*SProcIVector[])(ClientPtr) = {
+ NULL, /* 0 */
+ SProcXGetExtensionVersion, /* 1 */
+ SProcXListInputDevices, /* 2 */
+ SProcXOpenDevice, /* 3 */
+ SProcXCloseDevice, /* 4 */
+ SProcXSetDeviceMode, /* 5 */
+ SProcXSelectExtensionEvent, /* 6 */
+ SProcXGetSelectedExtensionEvents, /* 7 */
+ SProcXChangeDeviceDontPropagateList, /* 8 */
+ SProcXGetDeviceDontPropagateList, /* 9 */
+ SProcXGetDeviceMotionEvents, /* 10 */
+ SProcXChangeKeyboardDevice, /* 11 */
+ SProcXChangePointerDevice, /* 12 */
+ SProcXGrabDevice, /* 13 */
+ SProcXUngrabDevice, /* 14 */
+ SProcXGrabDeviceKey, /* 15 */
+ SProcXUngrabDeviceKey, /* 16 */
+ SProcXGrabDeviceButton, /* 17 */
+ SProcXUngrabDeviceButton, /* 18 */
+ SProcXAllowDeviceEvents, /* 19 */
+ SProcXGetDeviceFocus, /* 20 */
+ SProcXSetDeviceFocus, /* 21 */
+ SProcXGetFeedbackControl, /* 22 */
+ SProcXChangeFeedbackControl, /* 23 */
+ SProcXGetDeviceKeyMapping, /* 24 */
+ SProcXChangeDeviceKeyMapping, /* 25 */
+ SProcXGetDeviceModifierMapping, /* 26 */
+ SProcXSetDeviceModifierMapping, /* 27 */
+ SProcXGetDeviceButtonMapping, /* 28 */
+ SProcXSetDeviceButtonMapping, /* 29 */
+ SProcXQueryDeviceState, /* 30 */
+ SProcXSendExtensionEvent, /* 31 */
+ SProcXDeviceBell, /* 32 */
+ SProcXSetDeviceValuators, /* 33 */
+ SProcXGetDeviceControl, /* 34 */
+ SProcXChangeDeviceControl, /* 35 */
+ SProcXListDeviceProperties, /* 36 */
+ SProcXChangeDeviceProperty, /* 37 */
+ SProcXDeleteDeviceProperty, /* 38 */
+ SProcXGetDeviceProperty, /* 39 */
+ SProcXIQueryPointer, /* 40 */
+ SProcXIWarpPointer, /* 41 */
+ SProcXIChangeCursor, /* 42 */
+ SProcXIChangeHierarchy, /* 43 */
+ SProcXISetClientPointer, /* 44 */
+ SProcXIGetClientPointer, /* 45 */
+ SProcXISelectEvents, /* 46 */
+ SProcXIQueryVersion, /* 47 */
+ SProcXIQueryDevice, /* 48 */
+ SProcXISetFocus, /* 49 */
+ SProcXIGetFocus, /* 50 */
+ SProcXIGrabDevice, /* 51 */
+ SProcXIUngrabDevice, /* 52 */
+ SProcXIAllowEvents, /* 53 */
+ SProcXIPassiveGrabDevice, /* 54 */
+ SProcXIPassiveUngrabDevice, /* 55 */
+ SProcXIListProperties, /* 56 */
+ SProcXIChangeProperty, /* 57 */
+ SProcXIDeleteProperty, /* 58 */
+ SProcXIGetProperty, /* 59 */
+ SProcXIGetSelectedEvents /* 60 */
+};
+
+/*****************************************************************
+ *
+ * Globals referenced elsewhere in the server.
+ *
+ */
+
+int IReqCode = 0;
+int IEventBase = 0;
+int BadDevice = 0;
+static int BadEvent = 1;
+int BadMode = 2;
+int DeviceBusy = 3;
+int BadClass = 4;
+
+int DeviceValuator;
+int DeviceKeyPress;
+int DeviceKeyRelease;
+int DeviceButtonPress;
+int DeviceButtonRelease;
+int DeviceMotionNotify;
+int DeviceFocusIn;
+int DeviceFocusOut;
+int ProximityIn;
+int ProximityOut;
+int DeviceStateNotify;
+int DeviceKeyStateNotify;
+int DeviceButtonStateNotify;
+int DeviceMappingNotify;
+int ChangeDeviceNotify;
+int DevicePresenceNotify;
+int DevicePropertyNotify;
+
+int RT_INPUTCLIENT;
+
+/*****************************************************************
+ *
+ * Externs defined elsewhere in the X server.
+ *
+ */
+
+extern XExtensionVersion XIVersion;
+
+
+Mask PropagateMask[MAXDEVICES];
+
+/*****************************************************************
+ *
+ * Versioning support
+ *
+ */
+
+static int XIClientPrivateKeyIndex;
+DevPrivateKey XIClientPrivateKey = &XIClientPrivateKeyIndex;
+
+
+/*****************************************************************
+ *
+ * Declarations of local routines.
+ *
+ */
+
+static void
+XIClientCallback(CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec*)data;
+ ClientPtr pClient = clientinfo->client;
+ XIClientPtr pXIClient;
+
+ pXIClient = dixLookupPrivate(&pClient->devPrivates, XIClientPrivateKey);
+ pXIClient->major_version = 0;
+ pXIClient->minor_version = 0;
+}
+
+/*************************************************************************
+ *
+ * ProcIDispatch - main dispatch routine for requests to this extension.
+ * This routine is used if server and client have the same byte ordering.
+ *
+ */
+
+static int
+ProcIDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data > (IREQUESTS + XI2REQUESTS) || !ProcIVector[stuff->data])
+ return BadRequest;
+
+ return (*ProcIVector[stuff->data])(client);
+}
+
+/*******************************************************************************
+ *
+ * SProcXDispatch
+ *
+ * Main swapped dispatch routine for requests to this extension.
+ * This routine is used if server and client do not have the same byte ordering.
+ *
+ */
+
+static int
+SProcIDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ if (stuff->data > IREQUESTS || !SProcIVector[stuff->data])
+ return BadRequest;
+
+ return (*SProcIVector[stuff->data])(client);
+}
+
+/**********************************************************************
+ *
+ * SReplyIDispatch
+ * Swap any replies defined in this extension.
+ *
+ */
+
+static void
+SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
+ /* All we look at is the type field */
+{ /* This is common to all replies */
+ if (rep->RepType == X_GetExtensionVersion)
+ SRepXGetExtensionVersion(client, len,
+ (xGetExtensionVersionReply *) rep);
+ else if (rep->RepType == X_ListInputDevices)
+ SRepXListInputDevices(client, len, (xListInputDevicesReply *) rep);
+ else if (rep->RepType == X_OpenDevice)
+ SRepXOpenDevice(client, len, (xOpenDeviceReply *) rep);
+ else if (rep->RepType == X_SetDeviceMode)
+ SRepXSetDeviceMode(client, len, (xSetDeviceModeReply *) rep);
+ else if (rep->RepType == X_GetSelectedExtensionEvents)
+ SRepXGetSelectedExtensionEvents(client, len,
+ (xGetSelectedExtensionEventsReply *)
+ rep);
+ else if (rep->RepType == X_GetDeviceDontPropagateList)
+ SRepXGetDeviceDontPropagateList(client, len,
+ (xGetDeviceDontPropagateListReply *)
+ rep);
+ else if (rep->RepType == X_GetDeviceMotionEvents)
+ SRepXGetDeviceMotionEvents(client, len,
+ (xGetDeviceMotionEventsReply *) rep);
+ else if (rep->RepType == X_GrabDevice)
+ SRepXGrabDevice(client, len, (xGrabDeviceReply *) rep);
+ else if (rep->RepType == X_GetDeviceFocus)
+ SRepXGetDeviceFocus(client, len, (xGetDeviceFocusReply *) rep);
+ else if (rep->RepType == X_GetFeedbackControl)
+ SRepXGetFeedbackControl(client, len, (xGetFeedbackControlReply *) rep);
+ else if (rep->RepType == X_GetDeviceKeyMapping)
+ SRepXGetDeviceKeyMapping(client, len,
+ (xGetDeviceKeyMappingReply *) rep);
+ else if (rep->RepType == X_GetDeviceModifierMapping)
+ SRepXGetDeviceModifierMapping(client, len,
+ (xGetDeviceModifierMappingReply *) rep);
+ else if (rep->RepType == X_SetDeviceModifierMapping)
+ SRepXSetDeviceModifierMapping(client, len,
+ (xSetDeviceModifierMappingReply *) rep);
+ else if (rep->RepType == X_GetDeviceButtonMapping)
+ SRepXGetDeviceButtonMapping(client, len,
+ (xGetDeviceButtonMappingReply *) rep);
+ else if (rep->RepType == X_SetDeviceButtonMapping)
+ SRepXSetDeviceButtonMapping(client, len,
+ (xSetDeviceButtonMappingReply *) rep);
+ else if (rep->RepType == X_QueryDeviceState)
+ SRepXQueryDeviceState(client, len, (xQueryDeviceStateReply *) rep);
+ else if (rep->RepType == X_SetDeviceValuators)
+ SRepXSetDeviceValuators(client, len, (xSetDeviceValuatorsReply *) rep);
+ else if (rep->RepType == X_GetDeviceControl)
+ SRepXGetDeviceControl(client, len, (xGetDeviceControlReply *) rep);
+ else if (rep->RepType == X_ChangeDeviceControl)
+ SRepXChangeDeviceControl(client, len,
+ (xChangeDeviceControlReply *) rep);
+ else if (rep->RepType == X_ListDeviceProperties)
+ SRepXListDeviceProperties(client, len, (xListDevicePropertiesReply*)rep);
+ else if (rep->RepType == X_GetDeviceProperty)
+ SRepXGetDeviceProperty(client, len, (xGetDevicePropertyReply *) rep);
+ else if (rep->RepType == X_XIQueryPointer)
+ SRepXIQueryPointer(client, len, (xXIQueryPointerReply *) rep);
+ else if (rep->RepType == X_XIGetClientPointer)
+ SRepXIGetClientPointer(client, len, (xXIGetClientPointerReply*) rep);
+ else if (rep->RepType == X_XIQueryVersion)
+ SRepXIQueryVersion(client, len, (xXIQueryVersionReply*)rep);
+ else if (rep->RepType == X_XIQueryDevice)
+ SRepXIQueryDevice(client, len, (xXIQueryDeviceReply*)rep);
+ else if (rep->RepType == X_XIGrabDevice)
+ SRepXIGrabDevice(client, len, (xXIGrabDeviceReply *) rep);
+ else if (rep->RepType == X_XIGrabDevice)
+ SRepXIPassiveGrabDevice(client, len, (xXIPassiveGrabDeviceReply *) rep);
+ else if (rep->RepType == X_XIListProperties)
+ SRepXIListProperties(client, len, (xXIListPropertiesReply *) rep);
+ else if (rep->RepType == X_XIGetProperty)
+ SRepXIGetProperty(client, len, (xXIGetPropertyReply *) rep);
+ else if (rep->RepType == X_XIGetSelectedEvents)
+ SRepXIGetSelectedEvents(client, len, (xXIGetSelectedEventsReply *) rep);
+ else if (rep->RepType == X_XIGetFocus)
+ SRepXIGetFocus(client, len, (xXIGetFocusReply *) rep);
+ else {
+ FatalError("XINPUT confused sending swapped reply");
+ }
+}
+
+/************************************************************************
+ *
+ * This function swaps the DeviceValuator event.
+ *
+ */
+
+static void
+SEventDeviceValuator(deviceValuator * from, deviceValuator * to)
+{
+ char n;
+ int i;
+ INT32 *ip B32;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swaps(&to->device_state, n);
+ ip = &to->valuator0;
+ for (i = 0; i < 6; i++) {
+ swapl((ip + i), n); /* macro - braces are required */
+ }
+}
+
+static void
+SEventFocus(deviceFocus * from, deviceFocus * to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->time, n);
+ swapl(&to->window, n);
+}
+
+static void
+SDeviceStateNotifyEvent(deviceStateNotify * from, deviceStateNotify * to)
+{
+ int i;
+ char n;
+ INT32 *ip B32;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->time, n);
+ ip = &to->valuator0;
+ for (i = 0; i < 3; i++) {
+ swapl((ip + i), n); /* macro - braces are required */
+ }
+}
+
+static void
+SDeviceKeyStateNotifyEvent(deviceKeyStateNotify * from,
+ deviceKeyStateNotify * to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+}
+
+static void
+SDeviceButtonStateNotifyEvent(deviceButtonStateNotify * from,
+ deviceButtonStateNotify * to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+}
+
+static void
+SChangeDeviceNotifyEvent(changeDeviceNotify * from, changeDeviceNotify * to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->time, n);
+}
+
+static void
+SDeviceMappingNotifyEvent(deviceMappingNotify * from, deviceMappingNotify * to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->time, n);
+}
+
+static void
+SDevicePresenceNotifyEvent (devicePresenceNotify *from, devicePresenceNotify *to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber,n);
+ swapl(&to->time, n);
+ swaps(&to->control, n);
+}
+
+static void
+SDevicePropertyNotifyEvent (devicePropertyNotify *from, devicePropertyNotify *to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber,n);
+ swapl(&to->time, n);
+ swapl(&to->atom, n);
+}
+
+static void
+SDeviceLeaveNotifyEvent (xXILeaveEvent *from, xXILeaveEvent *to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber,n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->time, n);
+ swapl(&to->root, n);
+ swapl(&to->event, n);
+ swapl(&to->child, n);
+ swapl(&to->root_x, n);
+ swapl(&to->root_y, n);
+ swapl(&to->event_x, n);
+ swapl(&to->event_y, n);
+ swaps(&to->sourceid, n);
+ swaps(&to->buttons_len, n);
+ swapl(&to->mods.base_mods, n);
+ swapl(&to->mods.latched_mods, n);
+ swapl(&to->mods.locked_mods, n);
+}
+
+static void
+SDeviceChangedEvent(xXIDeviceChangedEvent* from, xXIDeviceChangedEvent* to)
+{
+ char n;
+ int i, j;
+ xXIAnyInfo *any;
+
+ *to = *from;
+ memcpy(&to[1], &from[1], from->length * 4);
+
+ any = (xXIAnyInfo*)&to[1];
+ for (i = 0; i < to->num_classes; i++)
+ {
+ int length = any->length;
+
+ switch(any->type)
+ {
+ case KeyClass:
+ {
+ xXIKeyInfo *ki = (xXIKeyInfo*)any;
+ uint32_t *key = (uint32_t*)&ki[1];
+ for (j = 0; j < ki->num_keycodes; j++, key++)
+ swapl(key, n);
+ swaps(&ki->num_keycodes, n);
+ }
+ break;
+ case ButtonClass:
+ {
+ xXIButtonInfo *bi = (xXIButtonInfo*)any;
+ Atom *labels = (Atom*)((char*)bi + sizeof(xXIButtonInfo) +
+ pad_to_int32(bits_to_bytes(bi->num_buttons)));
+ for (j = 0; j < bi->num_buttons; j++)
+ swapl(&labels[j], n);
+ swaps(&bi->num_buttons, n);
+ }
+ break;
+ case ValuatorClass:
+ {
+ xXIValuatorInfo* ai = (xXIValuatorInfo*)any;
+ swapl(&ai->label, n);
+ swapl(&ai->min.integral, n);
+ swapl(&ai->min.frac, n);
+ swapl(&ai->max.integral, n);
+ swapl(&ai->max.frac, n);
+ swapl(&ai->resolution, n);
+ swaps(&ai->number, n);
+ }
+ break;
+ }
+
+ swaps(&any->type, n);
+ swaps(&any->length, n);
+ swaps(&any->sourceid, n);
+
+ any = (xXIAnyInfo*)((char*)any + length * 4);
+ }
+
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->time, n);
+ swaps(&to->num_classes, n);
+ swaps(&to->sourceid, n);
+
+}
+
+static void SDeviceEvent(xXIDeviceEvent *from, xXIDeviceEvent *to)
+{
+ int i;
+ char n;
+ char *ptr;
+ char *vmask;
+
+ memcpy(to, from, sizeof(xEvent) + from->length * 4);
+
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->time, n);
+ swapl(&to->detail, n);
+ swapl(&to->root, n);
+ swapl(&to->event, n);
+ swapl(&to->child, n);
+ swapl(&to->root_x, n);
+ swapl(&to->root_y, n);
+ swapl(&to->event_x, n);
+ swapl(&to->event_y, n);
+ swaps(&to->buttons_len, n);
+ swaps(&to->valuators_len, n);
+ swaps(&to->sourceid, n);
+ swapl(&to->mods.base_mods, n);
+ swapl(&to->mods.latched_mods, n);
+ swapl(&to->mods.locked_mods, n);
+ swapl(&to->mods.effective_mods, n);
+
+ ptr = (char*)(&to[1]);
+ ptr += from->buttons_len * 4;
+ vmask = ptr; /* valuator mask */
+ ptr += from->valuators_len * 4;
+ for (i = 0; i < from->valuators_len * 32; i++)
+ {
+ if (BitIsOn(vmask, i))
+ {
+ swapl(((uint32_t*)ptr), n);
+ ptr += 4;
+ swapl(((uint32_t*)ptr), n);
+ ptr += 4;
+ }
+ }
+}
+
+static void SDeviceHierarchyEvent(xXIHierarchyEvent *from,
+ xXIHierarchyEvent *to)
+{
+ int i;
+ char n;
+ xXIHierarchyInfo *info;
+
+ *to = *from;
+ memcpy(&to[1], &from[1], from->length * 4);
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->time, n);
+ swapl(&to->flags, n);
+ swaps(&to->num_info, n);
+
+ info = (xXIHierarchyInfo*)&to[1];
+ for (i = 0; i< from->num_info; i++)
+ {
+ swaps(&info->deviceid, n);
+ swaps(&info->attachment, n);
+ info++;
+ }
+}
+
+static void SXIPropertyEvent(xXIPropertyEvent *from, xXIPropertyEvent *to)
+{
+ char n;
+
+ *to = *from;
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->property, n);
+}
+
+static void SRawEvent(xXIRawEvent *from, xXIRawEvent *to)
+{
+ char n;
+ int i;
+ FP3232 *values;
+ unsigned char *mask;
+
+ memcpy(to, from, sizeof(xEvent) + from->length * 4);
+
+ swaps(&to->sequenceNumber, n);
+ swapl(&to->length, n);
+ swaps(&to->evtype, n);
+ swaps(&to->deviceid, n);
+ swapl(&to->time, n);
+ swapl(&to->detail, n);
+
+
+ mask = (unsigned char*)&to[1];
+ values = (FP3232*)(mask + from->valuators_len * 4);
+
+ for (i = 0; i < from->valuators_len * 4 * 8; i++)
+ {
+ if (BitIsOn(mask, i))
+ {
+ /* for each bit set there are two FP3232 values on the wire, in
+ * the order abcABC for data and data_raw. Here we swap as if
+ * they were in aAbBcC order because it's easier and really
+ * doesn't matter.
+ */
+ swapl(&values->integral, n);
+ swapl(&values->frac, n);
+ values++;
+ swapl(&values->integral, n);
+ swapl(&values->frac, n);
+ values++;
+ }
+ }
+
+ swaps(&to->valuators_len, n);
+}
+
+
+/** Event swapping function for XI2 events. */
+void
+XI2EventSwap(xGenericEvent *from, xGenericEvent *to)
+{
+ switch(from->evtype)
+ {
+ case XI_Enter:
+ case XI_Leave:
+ SDeviceLeaveNotifyEvent((xXILeaveEvent*)from, (xXILeaveEvent*)to);
+ break;
+ case XI_DeviceChanged:
+ SDeviceChangedEvent((xXIDeviceChangedEvent*)from,
+ (xXIDeviceChangedEvent*)to);
+ break;
+ case XI_HierarchyChanged:
+ SDeviceHierarchyEvent((xXIHierarchyEvent*)from, (xXIHierarchyEvent*)to);
+ break;
+ case XI_PropertyEvent:
+ SXIPropertyEvent((xXIPropertyEvent*)from,
+ (xXIPropertyEvent*)to);
+ break;
+ case XI_Motion:
+ case XI_KeyPress:
+ case XI_KeyRelease:
+ case XI_ButtonPress:
+ case XI_ButtonRelease:
+ SDeviceEvent((xXIDeviceEvent*)from, (xXIDeviceEvent*)to);
+ break;
+ case XI_RawMotion:
+ case XI_RawKeyPress:
+ case XI_RawKeyRelease:
+ case XI_RawButtonPress:
+ case XI_RawButtonRelease:
+ SRawEvent((xXIRawEvent*)from, (xXIRawEvent*)to);
+ break;
+ default:
+ ErrorF("[Xi] Unknown event type to swap. This is a bug.\n");
+ break;
+ }
+}
+
+/**************************************************************************
+ *
+ * Allow the specified event to have its propagation suppressed.
+ * The default is to not allow suppression of propagation.
+ *
+ */
+
+static void
+AllowPropagateSuppress(Mask mask)
+{
+ int i;
+
+ for (i = 0; i < MAXDEVICES; i++)
+ PropagateMask[i] |= mask;
+}
+
+/**************************************************************************
+ *
+ * Record an event mask where there is no unique corresponding event type.
+ * We can't call SetMaskForEvent, since that would clobber the existing
+ * mask for that event. MotionHint and ButtonMotion are examples.
+ *
+ * Since extension event types will never be less than 64, we can use
+ * 0-63 in the EventInfo array as the "type" to be used to look up this
+ * mask. This means that the corresponding macros such as
+ * DevicePointerMotionHint must have access to the same constants.
+ *
+ */
+
+static void
+SetEventInfo(Mask mask, int constant)
+{
+ EventInfo[ExtEventIndex].mask = mask;
+ EventInfo[ExtEventIndex++].type = constant;
+}
+
+/**************************************************************************
+ *
+ * Allow the specified event to be restricted to being selected by one
+ * client at a time.
+ * The default is to allow more than one client to select the event.
+ *
+ */
+
+static void
+SetExclusiveAccess(Mask mask)
+{
+ int i;
+
+ for (i = 0; i < MAXDEVICES; i++)
+ ExtExclusiveMasks[i] |= mask;
+}
+
+/**************************************************************************
+ *
+ * Assign the specified mask to the specified event.
+ *
+ */
+
+static void
+SetMaskForExtEvent(Mask mask, int event)
+{
+ int i;
+
+ EventInfo[ExtEventIndex].mask = mask;
+ EventInfo[ExtEventIndex++].type = event;
+
+ if ((event < LASTEvent) || (event >= 128))
+ FatalError("MaskForExtensionEvent: bogus event number");
+
+ for (i = 0; i < MAXDEVICES; i++)
+ SetMaskForEvent(i, mask, event);
+}
+
+/************************************************************************
+ *
+ * This function sets up extension event types and masks.
+ *
+ */
+
+static void
+FixExtensionEvents(ExtensionEntry * extEntry)
+{
+ DeviceValuator = extEntry->eventBase;
+ DeviceKeyPress = DeviceValuator + 1;
+ DeviceKeyRelease = DeviceKeyPress + 1;
+ DeviceButtonPress = DeviceKeyRelease + 1;
+ DeviceButtonRelease = DeviceButtonPress + 1;
+ DeviceMotionNotify = DeviceButtonRelease + 1;
+ DeviceFocusIn = DeviceMotionNotify + 1;
+ DeviceFocusOut = DeviceFocusIn + 1;
+ ProximityIn = DeviceFocusOut + 1;
+ ProximityOut = ProximityIn + 1;
+ DeviceStateNotify = ProximityOut + 1;
+ DeviceMappingNotify = DeviceStateNotify + 1;
+ ChangeDeviceNotify = DeviceMappingNotify + 1;
+ DeviceKeyStateNotify = ChangeDeviceNotify + 1;
+ DeviceButtonStateNotify = DeviceKeyStateNotify + 1;
+ DevicePresenceNotify = DeviceButtonStateNotify + 1;
+ DevicePropertyNotify = DevicePresenceNotify + 1;
+
+ event_base[KeyClass] = DeviceKeyPress;
+ event_base[ButtonClass] = DeviceButtonPress;
+ event_base[ValuatorClass] = DeviceMotionNotify;
+ event_base[ProximityClass] = ProximityIn;
+ event_base[FocusClass] = DeviceFocusIn;
+ event_base[OtherClass] = DeviceStateNotify;
+
+ BadDevice += extEntry->errorBase;
+ BadEvent += extEntry->errorBase;
+ BadMode += extEntry->errorBase;
+ DeviceBusy += extEntry->errorBase;
+ BadClass += extEntry->errorBase;
+
+ SetMaskForExtEvent(DeviceKeyPressMask, DeviceKeyPress);
+ AllowPropagateSuppress(DeviceKeyPressMask);
+ SetCriticalEvent(DeviceKeyPress);
+
+ SetMaskForExtEvent(DeviceKeyReleaseMask, DeviceKeyRelease);
+ AllowPropagateSuppress(DeviceKeyReleaseMask);
+ SetCriticalEvent(DeviceKeyRelease);
+
+ SetMaskForExtEvent(DeviceButtonPressMask, DeviceButtonPress);
+ AllowPropagateSuppress(DeviceButtonPressMask);
+ SetCriticalEvent(DeviceButtonPress);
+
+ SetMaskForExtEvent(DeviceButtonReleaseMask, DeviceButtonRelease);
+ AllowPropagateSuppress(DeviceButtonReleaseMask);
+ SetCriticalEvent(DeviceButtonRelease);
+
+ SetMaskForExtEvent(DeviceProximityMask, ProximityIn);
+ SetMaskForExtEvent(DeviceProximityMask, ProximityOut);
+
+ SetMaskForExtEvent(DeviceStateNotifyMask, DeviceStateNotify);
+
+ SetMaskForExtEvent(DevicePointerMotionMask, DeviceMotionNotify);
+ AllowPropagateSuppress(DevicePointerMotionMask);
+ SetCriticalEvent(DeviceMotionNotify);
+
+ SetEventInfo(DevicePointerMotionHintMask, _devicePointerMotionHint);
+ SetEventInfo(DeviceButton1MotionMask, _deviceButton1Motion);
+ SetEventInfo(DeviceButton2MotionMask, _deviceButton2Motion);
+ SetEventInfo(DeviceButton3MotionMask, _deviceButton3Motion);
+ SetEventInfo(DeviceButton4MotionMask, _deviceButton4Motion);
+ SetEventInfo(DeviceButton5MotionMask, _deviceButton5Motion);
+ SetEventInfo(DeviceButtonMotionMask, _deviceButtonMotion);
+
+ SetMaskForExtEvent(DeviceFocusChangeMask, DeviceFocusIn);
+ SetMaskForExtEvent(DeviceFocusChangeMask, DeviceFocusOut);
+
+ SetMaskForExtEvent(DeviceMappingNotifyMask, DeviceMappingNotify);
+ SetMaskForExtEvent(ChangeDeviceNotifyMask, ChangeDeviceNotify);
+
+ SetEventInfo(DeviceButtonGrabMask, _deviceButtonGrab);
+ SetExclusiveAccess(DeviceButtonGrabMask);
+
+ SetEventInfo(DeviceOwnerGrabButtonMask, _deviceOwnerGrabButton);
+ SetEventInfo(DevicePresenceNotifyMask, _devicePresence);
+ SetMaskForExtEvent(DevicePropertyNotifyMask, DevicePropertyNotify);
+
+ SetEventInfo(0, _noExtensionEvent);
+}
+
+/************************************************************************
+ *
+ * This function restores extension event types and masks to their
+ * initial state.
+ *
+ */
+
+static void
+RestoreExtensionEvents(void)
+{
+ int i, j;
+
+ IReqCode = 0;
+ IEventBase = 0;
+
+ for (i = 0; i < ExtEventIndex - 1; i++) {
+ if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128))
+ {
+ for (j = 0; j < MAXDEVICES; j++)
+ SetMaskForEvent(j, 0, EventInfo[i].type);
+ }
+ EventInfo[i].mask = 0;
+ EventInfo[i].type = 0;
+ }
+ ExtEventIndex = 0;
+ DeviceValuator = 0;
+ DeviceKeyPress = 1;
+ DeviceKeyRelease = 2;
+ DeviceButtonPress = 3;
+ DeviceButtonRelease = 4;
+ DeviceMotionNotify = 5;
+ DeviceFocusIn = 6;
+ DeviceFocusOut = 7;
+ ProximityIn = 8;
+ ProximityOut = 9;
+ DeviceStateNotify = 10;
+ DeviceMappingNotify = 11;
+ ChangeDeviceNotify = 12;
+ DeviceKeyStateNotify = 13;
+ DeviceButtonStateNotify = 13;
+ DevicePresenceNotify = 14;
+ DevicePropertyNotify = 15;
+
+ BadDevice = 0;
+ BadEvent = 1;
+ BadMode = 2;
+ DeviceBusy = 3;
+ BadClass = 4;
+
+}
+
+/***********************************************************************
+ *
+ * IResetProc.
+ * Remove reply-swapping routine.
+ * Remove event-swapping routine.
+ *
+ */
+
+static void
+IResetProc(ExtensionEntry * unused)
+{
+ XIResetProperties();
+
+ ReplySwapVector[IReqCode] = ReplyNotSwappd;
+ EventSwapVector[DeviceValuator] = NotImplemented;
+ EventSwapVector[DeviceKeyPress] = NotImplemented;
+ EventSwapVector[DeviceKeyRelease] = NotImplemented;
+ EventSwapVector[DeviceButtonPress] = NotImplemented;
+ EventSwapVector[DeviceButtonRelease] = NotImplemented;
+ EventSwapVector[DeviceMotionNotify] = NotImplemented;
+ EventSwapVector[DeviceFocusIn] = NotImplemented;
+ EventSwapVector[DeviceFocusOut] = NotImplemented;
+ EventSwapVector[ProximityIn] = NotImplemented;
+ EventSwapVector[ProximityOut] = NotImplemented;
+ EventSwapVector[DeviceStateNotify] = NotImplemented;
+ EventSwapVector[DeviceKeyStateNotify] = NotImplemented;
+ EventSwapVector[DeviceButtonStateNotify] = NotImplemented;
+ EventSwapVector[DeviceMappingNotify] = NotImplemented;
+ EventSwapVector[ChangeDeviceNotify] = NotImplemented;
+ EventSwapVector[DevicePresenceNotify] = NotImplemented;
+ EventSwapVector[DevicePropertyNotify] = NotImplemented;
+ RestoreExtensionEvents();
+}
+
+
+/***********************************************************************
+ *
+ * Assign an id and type to an input device.
+ *
+ */
+
+void
+AssignTypeAndName(DeviceIntPtr dev, Atom type, char *name)
+{
+ dev->xinput_type = type;
+ dev->name = (char *)xalloc(strlen(name) + 1);
+ strcpy(dev->name, name);
+}
+
+/***********************************************************************
+ *
+ * Make device type atoms.
+ *
+ */
+
+static void
+MakeDeviceTypeAtoms(void)
+{
+ int i;
+
+ for (i = 0; i < NUMTYPES; i++)
+ dev_type[i].type =
+ MakeAtom(dev_type[i].name, strlen(dev_type[i].name), 1);
+}
+
+/*****************************************************************************
+ *
+ * SEventIDispatch
+ *
+ * Swap any events defined in this extension.
+ */
+#define DO_SWAP(func,type) func ((type *)from, (type *)to)
+
+static void
+SEventIDispatch(xEvent * from, xEvent * to)
+{
+ int type = from->u.u.type & 0177;
+
+ if (type == DeviceValuator)
+ DO_SWAP(SEventDeviceValuator, deviceValuator);
+ else if (type == DeviceKeyPress) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceKeyRelease) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceButtonPress) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceButtonRelease) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceMotionNotify) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceFocusIn)
+ DO_SWAP(SEventFocus, deviceFocus);
+ else if (type == DeviceFocusOut)
+ DO_SWAP(SEventFocus, deviceFocus);
+ else if (type == ProximityIn) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == ProximityOut) {
+ SKeyButtonPtrEvent(from, to);
+ to->u.keyButtonPointer.pad1 = from->u.keyButtonPointer.pad1;
+ } else if (type == DeviceStateNotify)
+ DO_SWAP(SDeviceStateNotifyEvent, deviceStateNotify);
+ else if (type == DeviceKeyStateNotify)
+ DO_SWAP(SDeviceKeyStateNotifyEvent, deviceKeyStateNotify);
+ else if (type == DeviceButtonStateNotify)
+ DO_SWAP(SDeviceButtonStateNotifyEvent, deviceButtonStateNotify);
+ else if (type == DeviceMappingNotify)
+ DO_SWAP(SDeviceMappingNotifyEvent, deviceMappingNotify);
+ else if (type == ChangeDeviceNotify)
+ DO_SWAP(SChangeDeviceNotifyEvent, changeDeviceNotify);
+ else if (type == DevicePresenceNotify)
+ DO_SWAP(SDevicePresenceNotifyEvent, devicePresenceNotify);
+ else if (type == DevicePropertyNotify)
+ DO_SWAP(SDevicePropertyNotifyEvent, devicePropertyNotify);
+ else {
+ FatalError("XInputExtension: Impossible event!\n");
+ }
+}
+
+/**********************************************************************
+ *
+ * IExtensionInit - initialize the input extension.
+ *
+ * Called from InitExtensions in main() or from QueryExtension() if the
+ * extension is dynamically loaded.
+ *
+ * This extension has several events and errors.
+ *
+ * XI is mandatory nowadays, so if we fail to init XI, we die.
+ */
+
+void
+XInputExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+ XExtensionVersion thisversion = { XI_Present,
+ SERVER_XI_MAJOR_VERSION,
+ SERVER_XI_MINOR_VERSION,
+ };
+
+ if (!dixRequestPrivate(XIClientPrivateKey, sizeof(XIClientRec)))
+ FatalError("Cannot request private for XI.\n");
+
+ if (!AddCallback(&ClientStateCallback, XIClientCallback, 0))
+ FatalError("Failed to add callback to XI.\n");
+
+ extEntry = AddExtension(INAME, IEVENTS, IERRORS, ProcIDispatch,
+ SProcIDispatch, IResetProc, StandardMinorOpcode);
+ if (extEntry) {
+ IReqCode = extEntry->base;
+ IEventBase = extEntry->eventBase;
+ XIVersion = thisversion;
+ MakeDeviceTypeAtoms();
+ RT_INPUTCLIENT = CreateNewResourceType((DeleteType) InputClientGone,
+ "INPUTCLIENT");
+ if (!RT_INPUTCLIENT)
+ FatalError("Failed to add resource type for XI.\n");
+ FixExtensionEvents(extEntry);
+ ReplySwapVector[IReqCode] = (ReplySwapPtr) SReplyIDispatch;
+ EventSwapVector[DeviceValuator] = SEventIDispatch;
+ EventSwapVector[DeviceKeyPress] = SEventIDispatch;
+ EventSwapVector[DeviceKeyRelease] = SEventIDispatch;
+ EventSwapVector[DeviceButtonPress] = SEventIDispatch;
+ EventSwapVector[DeviceButtonRelease] = SEventIDispatch;
+ EventSwapVector[DeviceMotionNotify] = SEventIDispatch;
+ EventSwapVector[DeviceFocusIn] = SEventIDispatch;
+ EventSwapVector[DeviceFocusOut] = SEventIDispatch;
+ EventSwapVector[ProximityIn] = SEventIDispatch;
+ EventSwapVector[ProximityOut] = SEventIDispatch;
+ EventSwapVector[DeviceStateNotify] = SEventIDispatch;
+ EventSwapVector[DeviceKeyStateNotify] = SEventIDispatch;
+ EventSwapVector[DeviceButtonStateNotify] = SEventIDispatch;
+ EventSwapVector[DeviceMappingNotify] = SEventIDispatch;
+ EventSwapVector[ChangeDeviceNotify] = SEventIDispatch;
+ EventSwapVector[DevicePresenceNotify] = SEventIDispatch;
+
+ GERegisterExtension(IReqCode, XI2EventSwap);
+
+
+ memset(&xi_all_devices, 0, sizeof(xi_all_devices));
+ memset(&xi_all_master_devices, 0, sizeof(xi_all_master_devices));
+ xi_all_devices.id = XIAllDevices;
+ xi_all_devices.name = "XIAllDevices";
+ xi_all_master_devices.id = XIAllMasterDevices;
+ xi_all_master_devices.name = "XIAllMasterDevices";
+
+ inputInfo.all_devices = &xi_all_devices;
+ inputInfo.all_master_devices = &xi_all_master_devices;
+ } else {
+ FatalError("IExtensionInit: AddExtensions failed\n");
+ }
+}
+
diff --git a/xorg-server/Xi/xiproperty.c b/xorg-server/Xi/xiproperty.c
index be0783107..6e298b7d1 100644
--- a/xorg-server/Xi/xiproperty.c
+++ b/xorg-server/Xi/xiproperty.c
@@ -1,1354 +1,1363 @@
-/*
- * Copyright © 2006 Keith Packard
- * Copyright © 2008 Peter Hutterer
- *
- * 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 WAXIANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WAXIANTIES 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.
- *
- */
-
-/* This code is a modified version of randr/rrproperty.c */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "dix.h"
-#include "inputstr.h"
-#include <X11/extensions/XI.h>
-#include <X11/Xatom.h>
-#include <X11/extensions/XIproto.h>
-#include <X11/extensions/XI2proto.h>
-#include "exglobals.h"
-#include "exevents.h"
-#include "swaprep.h"
-
-#include "xiproperty.h"
-#include "xserver-properties.h"
-
-/**
- * Properties used or alloced from inside the server.
- */
-static struct dev_properties
-{
- Atom type;
- char *name;
-} dev_properties[] = {
- {0, XI_PROP_ENABLED},
- {0, XI_PROP_XTEST_DEVICE},
- {0, XATOM_FLOAT},
- {0, ACCEL_PROP_PROFILE_NUMBER},
- {0, ACCEL_PROP_CONSTANT_DECELERATION},
- {0, ACCEL_PROP_ADAPTIVE_DECELERATION},
- {0, ACCEL_PROP_VELOCITY_SCALING},
- {0, AXIS_LABEL_PROP},
- {0, AXIS_LABEL_PROP_REL_X},
- {0, AXIS_LABEL_PROP_REL_Y},
- {0, AXIS_LABEL_PROP_REL_Z},
- {0, AXIS_LABEL_PROP_REL_RX},
- {0, AXIS_LABEL_PROP_REL_RY},
- {0, AXIS_LABEL_PROP_REL_RZ},
- {0, AXIS_LABEL_PROP_REL_HWHEEL},
- {0, AXIS_LABEL_PROP_REL_DIAL},
- {0, AXIS_LABEL_PROP_REL_WHEEL},
- {0, AXIS_LABEL_PROP_REL_MISC},
- {0, AXIS_LABEL_PROP_ABS_X},
- {0, AXIS_LABEL_PROP_ABS_Y},
- {0, AXIS_LABEL_PROP_ABS_Z},
- {0, AXIS_LABEL_PROP_ABS_RX},
- {0, AXIS_LABEL_PROP_ABS_RY},
- {0, AXIS_LABEL_PROP_ABS_RZ},
- {0, AXIS_LABEL_PROP_ABS_THROTTLE},
- {0, AXIS_LABEL_PROP_ABS_RUDDER},
- {0, AXIS_LABEL_PROP_ABS_WHEEL},
- {0, AXIS_LABEL_PROP_ABS_GAS},
- {0, AXIS_LABEL_PROP_ABS_BRAKE},
- {0, AXIS_LABEL_PROP_ABS_HAT0X},
- {0, AXIS_LABEL_PROP_ABS_HAT0Y},
- {0, AXIS_LABEL_PROP_ABS_HAT1X},
- {0, AXIS_LABEL_PROP_ABS_HAT1Y},
- {0, AXIS_LABEL_PROP_ABS_HAT2X},
- {0, AXIS_LABEL_PROP_ABS_HAT2Y},
- {0, AXIS_LABEL_PROP_ABS_HAT3X},
- {0, AXIS_LABEL_PROP_ABS_HAT3Y},
- {0, AXIS_LABEL_PROP_ABS_PRESSURE},
- {0, AXIS_LABEL_PROP_ABS_DISTANCE},
- {0, AXIS_LABEL_PROP_ABS_TILT_X},
- {0, AXIS_LABEL_PROP_ABS_TILT_Y},
- {0, AXIS_LABEL_PROP_ABS_TOOL_WIDTH},
- {0, AXIS_LABEL_PROP_ABS_VOLUME},
- {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR},
- {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR},
- {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR},
- {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR},
- {0, AXIS_LABEL_PROP_ABS_MT_ORIENTATION},
- {0, AXIS_LABEL_PROP_ABS_MT_POSITION_X},
- {0, AXIS_LABEL_PROP_ABS_MT_POSITION_Y},
- {0, AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE},
- {0, AXIS_LABEL_PROP_ABS_MT_BLOB_ID},
- {0, AXIS_LABEL_PROP_ABS_MT_TRACKING_ID},
- {0, AXIS_LABEL_PROP_ABS_MT_PRESSURE},
- {0, AXIS_LABEL_PROP_ABS_MISC},
-
- {0, BTN_LABEL_PROP},
- {0, BTN_LABEL_PROP_BTN_UNKNOWN},
- {0, BTN_LABEL_PROP_BTN_WHEEL_UP},
- {0, BTN_LABEL_PROP_BTN_WHEEL_DOWN},
- {0, BTN_LABEL_PROP_BTN_HWHEEL_LEFT},
- {0, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT},
- {0, BTN_LABEL_PROP_BTN_0},
- {0, BTN_LABEL_PROP_BTN_1},
- {0, BTN_LABEL_PROP_BTN_2},
- {0, BTN_LABEL_PROP_BTN_3},
- {0, BTN_LABEL_PROP_BTN_4},
- {0, BTN_LABEL_PROP_BTN_5},
- {0, BTN_LABEL_PROP_BTN_6},
- {0, BTN_LABEL_PROP_BTN_7},
- {0, BTN_LABEL_PROP_BTN_8},
- {0, BTN_LABEL_PROP_BTN_9},
-
- {0, BTN_LABEL_PROP_BTN_LEFT},
- {0, BTN_LABEL_PROP_BTN_RIGHT},
- {0, BTN_LABEL_PROP_BTN_MIDDLE},
- {0, BTN_LABEL_PROP_BTN_SIDE},
- {0, BTN_LABEL_PROP_BTN_EXTRA},
- {0, BTN_LABEL_PROP_BTN_FORWARD},
- {0, BTN_LABEL_PROP_BTN_BACK},
- {0, BTN_LABEL_PROP_BTN_TASK},
-
- {0, BTN_LABEL_PROP_BTN_TRIGGER},
- {0, BTN_LABEL_PROP_BTN_THUMB},
- {0, BTN_LABEL_PROP_BTN_THUMB2},
- {0, BTN_LABEL_PROP_BTN_TOP},
- {0, BTN_LABEL_PROP_BTN_TOP2},
- {0, BTN_LABEL_PROP_BTN_PINKIE},
- {0, BTN_LABEL_PROP_BTN_BASE},
- {0, BTN_LABEL_PROP_BTN_BASE2},
- {0, BTN_LABEL_PROP_BTN_BASE3},
- {0, BTN_LABEL_PROP_BTN_BASE4},
- {0, BTN_LABEL_PROP_BTN_BASE5},
- {0, BTN_LABEL_PROP_BTN_BASE6},
- {0, BTN_LABEL_PROP_BTN_DEAD},
-
- {0, BTN_LABEL_PROP_BTN_A},
- {0, BTN_LABEL_PROP_BTN_B},
- {0, BTN_LABEL_PROP_BTN_C},
- {0, BTN_LABEL_PROP_BTN_X},
- {0, BTN_LABEL_PROP_BTN_Y},
- {0, BTN_LABEL_PROP_BTN_Z},
- {0, BTN_LABEL_PROP_BTN_TL},
- {0, BTN_LABEL_PROP_BTN_TR},
- {0, BTN_LABEL_PROP_BTN_TL2},
- {0, BTN_LABEL_PROP_BTN_TR2},
- {0, BTN_LABEL_PROP_BTN_SELECT},
- {0, BTN_LABEL_PROP_BTN_START},
- {0, BTN_LABEL_PROP_BTN_MODE},
- {0, BTN_LABEL_PROP_BTN_THUMBL},
- {0, BTN_LABEL_PROP_BTN_THUMBR},
-
- {0, BTN_LABEL_PROP_BTN_TOOL_PEN},
- {0, BTN_LABEL_PROP_BTN_TOOL_RUBBER},
- {0, BTN_LABEL_PROP_BTN_TOOL_BRUSH},
- {0, BTN_LABEL_PROP_BTN_TOOL_PENCIL},
- {0, BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH},
- {0, BTN_LABEL_PROP_BTN_TOOL_FINGER},
- {0, BTN_LABEL_PROP_BTN_TOOL_MOUSE},
- {0, BTN_LABEL_PROP_BTN_TOOL_LENS},
- {0, BTN_LABEL_PROP_BTN_TOUCH},
- {0, BTN_LABEL_PROP_BTN_STYLUS},
- {0, BTN_LABEL_PROP_BTN_STYLUS2},
- {0, BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP},
- {0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP},
-
- {0, BTN_LABEL_PROP_BTN_GEAR_DOWN},
- {0, BTN_LABEL_PROP_BTN_GEAR_UP}
-};
-
-static long XIPropHandlerID = 1;
-
-static void send_property_event(DeviceIntPtr dev, Atom property, int what)
-{
- devicePropertyNotify event;
- xXIPropertyEvent xi2;
- int state;
-
- if (what == XIPropertyDeleted)
- state = PropertyDelete;
- else
- state = PropertyNewValue;
-
- event.type = DevicePropertyNotify;
- event.deviceid = dev->id;
- event.state = state;
- event.atom = property;
- event.time = currentTime.milliseconds;
- SendEventToAllWindows(dev, DevicePropertyNotifyMask,
- (xEvent*)&event, 1);
-
- xi2.type = GenericEvent;
- xi2.extension = IReqCode;
- xi2.length = 0;
- xi2.evtype = XI_PropertyEvent;
- xi2.deviceid = dev->id;
- xi2.time = currentTime.milliseconds;
- xi2.property = property;
- xi2.what = what;
- SendEventToAllWindows(dev, GetEventFilter(dev, (xEvent*)&xi2),
- (xEvent*)&xi2, 1);
-}
-
-static int list_atoms(DeviceIntPtr dev, int *natoms, Atom **atoms_return)
-{
- XIPropertyPtr prop;
- Atom *atoms = NULL;
- int nprops = 0;
-
- for (prop = dev->properties.properties; prop; prop = prop->next)
- nprops++;
- if (nprops)
- {
- Atom *a;
-
- atoms = xalloc(nprops * sizeof(Atom));
- if(!atoms)
- return BadAlloc;
- a = atoms;
- for (prop = dev->properties.properties; prop; prop = prop->next, a++)
- *a = prop->propertyName;
- }
-
- *natoms = nprops;
- *atoms_return = atoms;
- return Success;
-}
-
-static int
-get_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
- BOOL delete, int offset, int length,
- int *bytes_after, Atom *type_return, int *format, int *nitems,
- int *length_return, char **data)
-{
- unsigned long n, len, ind;
- int rc;
- XIPropertyPtr prop;
- XIPropertyValuePtr prop_value;
-
- if (!ValidAtom(property))
- {
- client->errorValue = property;
- return(BadAtom);
- }
- if ((delete != xTrue) && (delete != xFalse))
- {
- client->errorValue = delete;
- return(BadValue);
- }
-
- if ((type != AnyPropertyType) && !ValidAtom(type))
- {
- client->errorValue = type;
- return(BadAtom);
- }
-
- for (prop = dev->properties.properties; prop; prop = prop->next)
- if (prop->propertyName == property)
- break;
-
- if (!prop)
- {
- *bytes_after = 0;
- *type_return = None;
- *format = 0;
- *nitems = 0;
- *length_return = 0;
- return Success;
- }
-
- rc = XIGetDeviceProperty(dev, property, &prop_value);
- if (rc != Success)
- {
- client->errorValue = property;
- return rc;
- }
-
- /* If the request type and actual type don't match. Return the
- property information, but not the data. */
-
- if (((type != prop_value->type) && (type != AnyPropertyType)))
- {
- *bytes_after = prop_value->size;
- *format = prop_value->format;
- *length_return = 0;
- *nitems = 0;
- *type_return = prop_value->type;
- return Success;
- }
-
- /* Return type, format, value to client */
- n = (prop_value->format/8) * prop_value->size; /* size (bytes) of prop */
- ind = offset << 2;
-
- /* If offset is invalid such that it causes "len" to
- be negative, it's a value error. */
-
- if (n < ind)
- {
- client->errorValue = offset;
- return BadValue;
- }
-
- len = min(n - ind, 4 * length);
-
- *bytes_after = n - (ind + len);
- *format = prop_value->format;
- *length_return = len;
- if (prop_value->format)
- *nitems = len / (prop_value->format / 8);
- else
- *nitems = 0;
- *type_return = prop_value->type;
-
- *data = (char*)prop_value->data + ind;
-
- return Success;
-}
-
-static int
-check_change_property(ClientPtr client, Atom property, Atom type, int format,
- int mode, int nitems)
-{
- if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
- (mode != PropModePrepend))
- {
- client->errorValue = mode;
- return BadValue;
- }
- if ((format != 8) && (format != 16) && (format != 32))
- {
- client->errorValue = format;
- return BadValue;
- }
-
- if (!ValidAtom(property))
- {
- client->errorValue = property;
- return(BadAtom);
- }
- if (!ValidAtom(type))
- {
- client->errorValue = type;
- return(BadAtom);
- }
-
- return Success;
-}
-
-static int
-change_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
- int format, int mode, int len, void *data)
-{
- int rc = Success;
-
- rc = XIChangeDeviceProperty(dev, property, type, format, mode, len, data, TRUE);
- if (rc != Success)
- client->errorValue = property;
-
- return rc;
-}
-
-/**
- * Return the atom assigned to the specified string or 0 if the atom isn't known
- * to the DIX.
- *
- * If name is NULL, None is returned.
- */
-Atom
-XIGetKnownProperty(char *name)
-{
- int i;
-
- if (!name)
- return None;
-
- for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++)
- {
- if (strcmp(name, dev_properties[i].name) == 0){
- if (dev_properties[i].type == None){
- dev_properties[i].type =
- MakeAtom(dev_properties[i].name,
- strlen(dev_properties[i].name),
- TRUE);
- }
-
- return dev_properties[i].type;
- }
- }
-
- return 0;
-}
-
-/**
- * Convert the given property's value(s) into @nelem_return integer values and
- * store them in @buf_return. If @nelem_return is larger than the number of
- * values in the property, @nelem_return is set to the number of values in the
- * property.
- *
- * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
- * automatically and must be freed by the caller.
- *
- * Possible return codes.
- * Success ... No error.
- * BadMatch ... Wrong atom type, atom is not XA_INTEGER
- * BadAlloc ... NULL passed as buffer and allocation failed.
- * BadLength ... @buff is NULL but @nelem_return is non-zero.
- *
- * @param val The property value
- * @param nelem_return The maximum number of elements to return.
- * @param buf_return Pointer to an array of at least @nelem_return values.
- * @return Success or the error code if an error occured.
- */
-_X_EXPORT int
-XIPropToInt(XIPropertyValuePtr val, int *nelem_return, int **buf_return)
-{
- int i;
- int *buf;
-
- if (val->type != XA_INTEGER)
- return BadMatch;
- if (!*buf_return && *nelem_return)
- return BadLength;
-
- switch(val->format)
- {
- case 8:
- case 16:
- case 32:
- break;
- default:
- return BadValue;
- }
-
- buf = *buf_return;
-
- if (!buf && !(*nelem_return))
- {
- buf = xcalloc(val->size, sizeof(int));
- if (!buf)
- return BadAlloc;
- *buf_return = buf;
- *nelem_return = val->size;
- } else if (val->size < *nelem_return)
- *nelem_return = val->size;
-
- for (i = 0; i < val->size && i < *nelem_return; i++)
- {
- switch(val->format)
- {
- case 8: buf[i] = ((CARD8*)val->data)[i]; break;
- case 16: buf[i] = ((CARD16*)val->data)[i]; break;
- case 32: buf[i] = ((CARD32*)val->data)[i]; break;
- }
- }
-
- return Success;
-}
-
-/**
- * Convert the given property's value(s) into @nelem_return float values and
- * store them in @buf_return. If @nelem_return is larger than the number of
- * values in the property, @nelem_return is set to the number of values in the
- * property.
- *
- * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
- * automatically and must be freed by the caller.
- *
- * Possible errors returned:
- * Success
- * BadMatch ... Wrong atom type, atom is not XA_FLOAT
- * BadValue ... Wrong format, format is not 32
- * BadAlloc ... NULL passed as buffer and allocation failed.
- * BadLength ... @buff is NULL but @nelem_return is non-zero.
- *
- * @param val The property value
- * @param nelem_return The maximum number of elements to return.
- * @param buf_return Pointer to an array of at least @nelem_return values.
- * @return Success or the error code if an error occured.
- */
-_X_EXPORT int
-XIPropToFloat(XIPropertyValuePtr val, int *nelem_return, float **buf_return)
-{
- int i;
- float *buf;
-
- if (!val->type || val->type != XIGetKnownProperty(XATOM_FLOAT))
- return BadMatch;
-
- if (val->format != 32)
- return BadValue;
- if (!*buf_return && *nelem_return)
- return BadLength;
-
- buf = *buf_return;
-
- if (!buf && !(*nelem_return))
- {
- buf = xcalloc(val->size, sizeof(float));
- if (!buf)
- return BadAlloc;
- *buf_return = buf;
- *nelem_return = val->size;
- } else if (val->size < *nelem_return)
- *nelem_return = val->size;
-
- for (i = 0; i < val->size && i < *nelem_return; i++)
- buf[i] = ((float*)val->data)[i];
-
- return Success;
-}
-
-/* Registers a new property handler on the given device and returns a unique
- * identifier for this handler. This identifier is required to unregister the
- * property handler again.
- * @return The handler's identifier or 0 if an error occured.
- */
-long
-XIRegisterPropertyHandler(DeviceIntPtr dev,
- int (*SetProperty) (DeviceIntPtr dev,
- Atom property,
- XIPropertyValuePtr prop,
- BOOL checkonly),
- int (*GetProperty) (DeviceIntPtr dev,
- Atom property),
- int (*DeleteProperty) (DeviceIntPtr dev,
- Atom property))
-{
- XIPropertyHandlerPtr new_handler;
-
- new_handler = xcalloc(1, sizeof(XIPropertyHandler));
- if (!new_handler)
- return 0;
-
- new_handler->id = XIPropHandlerID++;
- new_handler->SetProperty = SetProperty;
- new_handler->GetProperty = GetProperty;
- new_handler->DeleteProperty = DeleteProperty;
- new_handler->next = dev->properties.handlers;
- dev->properties.handlers = new_handler;
-
- return new_handler->id;
-}
-
-void
-XIUnregisterPropertyHandler(DeviceIntPtr dev, long id)
-{
- XIPropertyHandlerPtr curr, prev = NULL;
-
- curr = dev->properties.handlers;
- while(curr && curr->id != id)
- {
- prev = curr;
- curr = curr->next;
- }
-
- if (!curr)
- return;
-
- if (!prev) /* first one */
- dev->properties.handlers = curr->next;
- else
- prev->next = curr->next;
-
- xfree(curr);
-}
-
-static XIPropertyPtr
-XICreateDeviceProperty (Atom property)
-{
- XIPropertyPtr prop;
-
- prop = (XIPropertyPtr)xalloc(sizeof(XIPropertyRec));
- if (!prop)
- return NULL;
-
- prop->next = NULL;
- prop->propertyName = property;
- prop->value.type = None;
- prop->value.format = 0;
- prop->value.size = 0;
- prop->value.data = NULL;
- prop->deletable = TRUE;
-
- return prop;
-}
-
-static XIPropertyPtr
-XIFetchDeviceProperty(DeviceIntPtr dev, Atom property)
-{
- XIPropertyPtr prop;
-
- for (prop = dev->properties.properties; prop; prop = prop->next)
- if (prop->propertyName == property)
- return prop;
- return NULL;
-}
-
-static void
-XIDestroyDeviceProperty (XIPropertyPtr prop)
-{
- if (prop->value.data)
- xfree(prop->value.data);
- xfree(prop);
-}
-
-/* This function destroys all of the device's property-related stuff,
- * including removing all device handlers.
- * DO NOT CALL FROM THE DRIVER.
- */
-void
-XIDeleteAllDeviceProperties (DeviceIntPtr device)
-{
- XIPropertyPtr prop, next;
- XIPropertyHandlerPtr curr_handler, next_handler;
-
- for (prop = device->properties.properties; prop; prop = next)
- {
- next = prop->next;
- send_property_event(device, prop->propertyName, XIPropertyDeleted);
- XIDestroyDeviceProperty(prop);
- }
-
- device->properties.properties = NULL;
-
- /* Now free all handlers */
- curr_handler = device->properties.handlers;
- while(curr_handler)
- {
- next_handler = curr_handler->next;
- xfree(curr_handler);
- curr_handler = next_handler;
- }
-
- device->properties.handlers = NULL;
-}
-
-
-int
-XIDeleteDeviceProperty (DeviceIntPtr device, Atom property, Bool fromClient)
-{
- XIPropertyPtr prop, *prev;
- int rc = Success;
-
- for (prev = &device->properties.properties; (prop = *prev); prev = &(prop->next))
- if (prop->propertyName == property)
- break;
-
- if (!prop)
- return Success;
-
- if (fromClient && !prop->deletable)
- return BadAccess;
-
- /* Ask handlers if we may delete the property */
- if (device->properties.handlers)
- {
- XIPropertyHandlerPtr handler = device->properties.handlers;
- while(handler)
- {
- if (handler->DeleteProperty)
- rc = handler->DeleteProperty(device, prop->propertyName);
- if (rc != Success)
- return (rc);
- handler = handler->next;
- }
- }
-
- if (prop)
- {
- *prev = prop->next;
- send_property_event(device, prop->propertyName, XIPropertyDeleted);
- XIDestroyDeviceProperty (prop);
- }
-
- return Success;
-}
-
-int
-XIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type,
- int format, int mode, unsigned long len,
- pointer value, Bool sendevent)
-{
- XIPropertyPtr prop;
- int size_in_bytes;
- int total_size;
- unsigned long total_len;
- XIPropertyValuePtr prop_value;
- XIPropertyValueRec new_value;
- Bool add = FALSE;
- int rc;
-
- size_in_bytes = format >> 3;
-
- /* first see if property already exists */
- prop = XIFetchDeviceProperty (dev, property);
- if (!prop) /* just add to list */
- {
- prop = XICreateDeviceProperty (property);
- if (!prop)
- return(BadAlloc);
- add = TRUE;
- mode = PropModeReplace;
- }
- prop_value = &prop->value;
-
- /* To append or prepend to a property the request format and type
- must match those of the already defined property. The
- existing format and type are irrelevant when using the mode
- "PropModeReplace" since they will be written over. */
-
- if ((format != prop_value->format) && (mode != PropModeReplace))
- return(BadMatch);
- if ((prop_value->type != type) && (mode != PropModeReplace))
- return(BadMatch);
- new_value = *prop_value;
- if (mode == PropModeReplace)
- total_len = len;
- else
- total_len = prop_value->size + len;
-
- if (mode == PropModeReplace || len > 0)
- {
- pointer new_data = NULL, old_data = NULL;
-
- total_size = total_len * size_in_bytes;
- new_value.data = (pointer)xalloc (total_size);
- if (!new_value.data && total_size)
- {
- if (add)
- XIDestroyDeviceProperty (prop);
- return BadAlloc;
- }
- new_value.size = len;
- new_value.type = type;
- new_value.format = format;
-
- switch (mode) {
- case PropModeReplace:
- new_data = new_value.data;
- old_data = NULL;
- break;
- case PropModeAppend:
- new_data = (pointer) (((char *) new_value.data) +
- (prop_value->size * size_in_bytes));
- old_data = new_value.data;
- break;
- case PropModePrepend:
- new_data = new_value.data;
- old_data = (pointer) (((char *) new_value.data) +
- (prop_value->size * size_in_bytes));
- break;
- }
- if (new_data)
- memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
- if (old_data)
- memcpy ((char *) old_data, (char *) prop_value->data,
- prop_value->size * size_in_bytes);
-
- if (dev->properties.handlers)
- {
- XIPropertyHandlerPtr handler;
- BOOL checkonly = TRUE;
- /* run through all handlers with checkonly TRUE, then again with
- * checkonly FALSE. Handlers MUST return error codes on the
- * checkonly run, errors on the second run are ignored */
- do
- {
- handler = dev->properties.handlers;
- while(handler)
- {
- if (handler->SetProperty)
- {
- rc = handler->SetProperty(dev, prop->propertyName,
- &new_value, checkonly);
- if (checkonly && rc != Success)
- {
- if (new_value.data)
- xfree (new_value.data);
- return (rc);
- }
- }
- handler = handler->next;
- }
- checkonly = !checkonly;
- } while (!checkonly);
- }
- if (prop_value->data)
- xfree (prop_value->data);
- *prop_value = new_value;
- } else if (len == 0)
- {
- /* do nothing */
- }
-
- if (add)
- {
- prop->next = dev->properties.properties;
- dev->properties.properties = prop;
- }
-
- if (sendevent)
- send_property_event(dev, prop->propertyName,
- (add) ? XIPropertyCreated : XIPropertyModified);
-
- return(Success);
-}
-
-int
-XIGetDeviceProperty (DeviceIntPtr dev, Atom property, XIPropertyValuePtr *value)
-{
- XIPropertyPtr prop = XIFetchDeviceProperty (dev, property);
- int rc;
-
- if (!prop)
- {
- *value = NULL;
- return BadAtom;
- }
-
- /* If we can, try to update the property value first */
- if (dev->properties.handlers)
- {
- XIPropertyHandlerPtr handler = dev->properties.handlers;
- while(handler)
- {
- if (handler->GetProperty)
- {
- rc = handler->GetProperty(dev, prop->propertyName);
- if (rc != Success)
- {
- *value = NULL;
- return rc;
- }
- }
- handler = handler->next;
- }
- }
-
- *value = &prop->value;
- return Success;
-}
-
-int
-XISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable)
-{
- XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
-
- if (!prop)
- return BadAtom;
-
- prop->deletable = deletable;
- return Success;
-}
-
-int
-ProcXListDeviceProperties (ClientPtr client)
-{
- Atom *atoms;
- xListDevicePropertiesReply rep;
- int natoms;
- DeviceIntPtr dev;
- int rc = Success;
-
- REQUEST(xListDevicePropertiesReq);
- REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
-
- rc = dixLookupDevice (&dev, stuff->deviceid, client, DixListPropAccess);
- if (rc != Success)
- return rc;
-
- rc = list_atoms(dev, &natoms, &atoms);
- if (rc != Success)
- return rc;
-
- rep.repType = X_Reply;
- rep.RepType = X_ListDeviceProperties;
- rep.length = natoms;
- rep.sequenceNumber = client->sequence;
- rep.nAtoms = natoms;
-
- WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
- if (natoms)
- {
- client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
- WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
- xfree(atoms);
- }
- return rc;
-}
-
-int
-ProcXChangeDeviceProperty (ClientPtr client)
-{
- REQUEST(xChangeDevicePropertyReq);
- DeviceIntPtr dev;
- unsigned long len;
- int totalSize;
- int rc;
-
- REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
- UpdateCurrentTime();
-
- rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
- if (rc != Success)
- return rc;
-
- rc = check_change_property(client, stuff->property, stuff->type,
- stuff->format, stuff->mode, stuff->nUnits);
-
- len = stuff->nUnits;
- if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq))))
- return BadLength;
-
- totalSize = len * (stuff->format/8);
- REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
-
- rc = change_property(client, dev, stuff->property, stuff->type,
- stuff->format, stuff->mode, len, (void*)&stuff[1]);
- return rc;
-}
-
-int
-ProcXDeleteDeviceProperty (ClientPtr client)
-{
- REQUEST(xDeleteDevicePropertyReq);
- DeviceIntPtr dev;
- int rc;
-
- REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
- UpdateCurrentTime();
- rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
- if (rc != Success)
- return rc;
-
- if (!ValidAtom(stuff->property))
- {
- client->errorValue = stuff->property;
- return (BadAtom);
- }
-
- rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
- return rc;
-}
-
-int
-ProcXGetDeviceProperty (ClientPtr client)
-{
- REQUEST(xGetDevicePropertyReq);
- DeviceIntPtr dev;
- int length;
- int rc, format, nitems, bytes_after;
- char *data;
- Atom type;
- xGetDevicePropertyReply reply;
-
- REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
- if (stuff->delete)
- UpdateCurrentTime();
- rc = dixLookupDevice (&dev, stuff->deviceid, client,
- stuff->delete ? DixSetPropAccess :
- DixGetPropAccess);
- if (rc != Success)
- return rc;
-
- rc = get_property(client, dev, stuff->property, stuff->type,
- stuff->delete, stuff->longOffset, stuff->longLength,
- &bytes_after, &type, &format, &nitems, &length, &data);
-
- if (rc != Success)
- return rc;
-
- reply.repType = X_Reply;
- reply.RepType = X_GetDeviceProperty;
- reply.sequenceNumber = client->sequence;
- reply.deviceid = dev->id;
- reply.nItems = nitems;
- reply.format = format;
- reply.bytesAfter = bytes_after;
- reply.propertyType = type;
- reply.length = bytes_to_int32(length);
-
- if (stuff->delete && (reply.bytesAfter == 0))
- send_property_event(dev, stuff->property, XIPropertyDeleted);
-
- WriteReplyToClient(client, sizeof(xGenericReply), &reply);
-
- if (length)
- {
- switch (reply.format) {
- case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
- case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
- default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
- }
- WriteSwappedDataToClient(client, length, data);
- }
-
- /* delete the Property */
- if (stuff->delete && (reply.bytesAfter == 0))
- {
- XIPropertyPtr prop, *prev;
- for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next)
- {
- if (prop->propertyName == stuff->property)
- {
- *prev = prop->next;
- XIDestroyDeviceProperty(prop);
- break;
- }
- }
- }
- return Success;
-}
-
-
-int
-SProcXListDeviceProperties (ClientPtr client)
-{
- char n;
- REQUEST(xListDevicePropertiesReq);
-
- swaps(&stuff->length, n);
-
- REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
- return (ProcXListDeviceProperties(client));
-}
-
-int
-SProcXChangeDeviceProperty (ClientPtr client)
-{
- char n;
- REQUEST(xChangeDevicePropertyReq);
-
- swaps(&stuff->length, n);
- swapl(&stuff->property, n);
- swapl(&stuff->type, n);
- swapl(&stuff->nUnits, n);
- REQUEST_SIZE_MATCH(xChangeDevicePropertyReq);
- return (ProcXChangeDeviceProperty(client));
-}
-
-int
-SProcXDeleteDeviceProperty (ClientPtr client)
-{
- char n;
- REQUEST(xDeleteDevicePropertyReq);
-
- swaps(&stuff->length, n);
- swapl(&stuff->property, n);
- REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
- return (ProcXDeleteDeviceProperty(client));
-}
-
-int
-SProcXGetDeviceProperty (ClientPtr client)
-{
- char n;
- REQUEST(xGetDevicePropertyReq);
-
- swaps(&stuff->length, n);
- swapl(&stuff->property, n);
- swapl(&stuff->type, n);
- swapl(&stuff->longOffset, n);
- swapl(&stuff->longLength, n);
- REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
- return (ProcXGetDeviceProperty(client));
-}
-
-
-/* Reply swapping */
-
-void
-SRepXListDeviceProperties(ClientPtr client, int size,
- xListDevicePropertiesReply *rep)
-{
- char n;
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- swaps(&rep->nAtoms, n);
- /* properties will be swapped later, see ProcXListDeviceProperties */
- WriteToClient(client, size, (char*)rep);
-}
-
-void
-SRepXGetDeviceProperty(ClientPtr client, int size,
- xGetDevicePropertyReply *rep)
-{
- char n;
-
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- swapl(&rep->propertyType, n);
- swapl(&rep->bytesAfter, n);
- swapl(&rep->nItems, n);
- /* data will be swapped, see ProcXGetDeviceProperty */
- WriteToClient(client, size, (char*)rep);
-}
-
-/* XI2 Request/reply handling */
-int
-ProcXIListProperties(ClientPtr client)
-{
- Atom *atoms;
- xXIListPropertiesReply rep;
- int natoms;
- DeviceIntPtr dev;
- int rc = Success;
-
- REQUEST(xXIListPropertiesReq);
- REQUEST_SIZE_MATCH(xXIListPropertiesReq);
-
- rc = dixLookupDevice (&dev, stuff->deviceid, client, DixListPropAccess);
- if (rc != Success)
- return rc;
-
- rc = list_atoms(dev, &natoms, &atoms);
- if (rc != Success)
- return rc;
-
- rep.repType = X_Reply;
- rep.RepType = X_XIListProperties;
- rep.length = natoms;
- rep.sequenceNumber = client->sequence;
- rep.num_properties = natoms;
-
- WriteReplyToClient(client, sizeof(xXIListPropertiesReply), &rep);
- if (natoms)
- {
- client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
- WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
- xfree(atoms);
- }
- return rc;
-}
-
-int
-ProcXIChangeProperty(ClientPtr client)
-{
- int rc;
- DeviceIntPtr dev;
- int totalSize;
- unsigned long len;
-
- REQUEST(xXIChangePropertyReq);
- REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
- UpdateCurrentTime();
-
- rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
- if (rc != Success)
- return rc;
-
- rc = check_change_property(client, stuff->property, stuff->type,
- stuff->format, stuff->mode, stuff->num_items);
- len = stuff->num_items;
- if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq)))
- return BadLength;
-
- totalSize = len * (stuff->format/8);
- REQUEST_FIXED_SIZE(xXIChangePropertyReq, totalSize);
-
- rc = change_property(client, dev, stuff->property, stuff->type,
- stuff->format, stuff->mode, len, (void*)&stuff[1]);
- return rc;
-}
-
-int
-ProcXIDeleteProperty(ClientPtr client)
-{
- DeviceIntPtr dev;
- int rc;
- REQUEST(xXIDeletePropertyReq);
-
- REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
- UpdateCurrentTime();
- rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
- if (rc != Success)
- return rc;
-
- if (!ValidAtom(stuff->property))
- {
- client->errorValue = stuff->property;
- return (BadAtom);
- }
-
- rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
- return rc;
-}
-
-
-int
-ProcXIGetProperty(ClientPtr client)
-{
- REQUEST(xXIGetPropertyReq);
- DeviceIntPtr dev;
- xXIGetPropertyReply reply;
- int length;
- int rc, format, nitems, bytes_after;
- char *data;
- Atom type;
-
- REQUEST_SIZE_MATCH(xXIGetPropertyReq);
- if (stuff->delete)
- UpdateCurrentTime();
- rc = dixLookupDevice (&dev, stuff->deviceid, client,
- stuff->delete ? DixSetPropAccess :
- DixGetPropAccess);
- if (rc != Success)
- return rc;
-
- rc = get_property(client, dev, stuff->property, stuff->type,
- stuff->delete, stuff->offset, stuff->len,
- &bytes_after, &type, &format, &nitems, &length, &data);
-
- if (rc != Success)
- return rc;
-
- reply.repType = X_Reply;
- reply.RepType = X_XIGetProperty;
- reply.sequenceNumber = client->sequence;
- reply.num_items = nitems;
- reply.format = format;
- reply.bytes_after = bytes_after;
- reply.type = type;
- reply.length = bytes_to_int32(length);
-
- if (length && stuff->delete && (reply.bytes_after == 0))
- send_property_event(dev, stuff->property, XIPropertyDeleted);
-
- WriteReplyToClient(client, sizeof(xXIGetPropertyReply), &reply);
-
- if (length)
- {
- switch (reply.format) {
- case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
- case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
- default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
- }
- WriteSwappedDataToClient(client, length, data);
- }
-
- /* delete the Property */
- if (stuff->delete && (reply.bytes_after == 0))
- {
- XIPropertyPtr prop, *prev;
- for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next)
- {
- if (prop->propertyName == stuff->property)
- {
- *prev = prop->next;
- XIDestroyDeviceProperty(prop);
- break;
- }
- }
- }
-
- return Success;
-}
-
-int
-SProcXIListProperties(ClientPtr client)
-{
- char n;
- REQUEST(xXIListPropertiesReq);
-
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
-
- REQUEST_SIZE_MATCH(xXIListPropertiesReq);
- return (ProcXIListProperties(client));
-}
-
-int
-SProcXIChangeProperty(ClientPtr client)
-{
- char n;
- REQUEST(xXIChangePropertyReq);
-
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->property, n);
- swapl(&stuff->type, n);
- swapl(&stuff->num_items, n);
- REQUEST_SIZE_MATCH(xXIChangePropertyReq);
- return (ProcXIChangeProperty(client));
-}
-
-int
-SProcXIDeleteProperty(ClientPtr client)
-{
- char n;
- REQUEST(xXIDeletePropertyReq);
-
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->property, n);
- REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
- return (ProcXIDeleteProperty(client));
-}
-
-int
-SProcXIGetProperty(ClientPtr client)
-{
- char n;
- REQUEST(xXIGetPropertyReq);
-
- swaps(&stuff->length, n);
- swaps(&stuff->deviceid, n);
- swapl(&stuff->property, n);
- swapl(&stuff->type, n);
- swapl(&stuff->offset, n);
- swapl(&stuff->len, n);
- REQUEST_SIZE_MATCH(xXIGetPropertyReq);
- return (ProcXIGetProperty(client));
-}
-
-
-void
-SRepXIListProperties(ClientPtr client, int size,
- xXIListPropertiesReply *rep)
-{
- char n;
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- swaps(&rep->num_properties, n);
- /* properties will be swapped later, see ProcXIListProperties */
- WriteToClient(client, size, (char*)rep);
-}
-
-void
-SRepXIGetProperty(ClientPtr client, int size,
- xXIGetPropertyReply *rep)
-{
- char n;
-
- swaps(&rep->sequenceNumber, n);
- swapl(&rep->length, n);
- swapl(&rep->type, n);
- swapl(&rep->bytes_after, n);
- swapl(&rep->num_items, n);
- /* data will be swapped, see ProcXIGetProperty */
- WriteToClient(client, size, (char*)rep);
-}
+/*
+ * Copyright © 2006 Keith Packard
+ * Copyright © 2008 Peter Hutterer
+ *
+ * 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 WAXIANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WAXIANTIES 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.
+ *
+ */
+
+/* This code is a modified version of randr/rrproperty.c */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "dix.h"
+#include "inputstr.h"
+#include <X11/extensions/XI.h>
+#include <X11/Xatom.h>
+#include <X11/extensions/XIproto.h>
+#include <X11/extensions/XI2proto.h>
+#include "exglobals.h"
+#include "exevents.h"
+#include "swaprep.h"
+
+#include "xiproperty.h"
+#include "xserver-properties.h"
+
+/**
+ * Properties used or alloced from inside the server.
+ */
+static struct dev_properties
+{
+ Atom type;
+ char *name;
+} dev_properties[] = {
+ {0, XI_PROP_ENABLED},
+ {0, XI_PROP_XTEST_DEVICE},
+ {0, XATOM_FLOAT},
+ {0, ACCEL_PROP_PROFILE_NUMBER},
+ {0, ACCEL_PROP_CONSTANT_DECELERATION},
+ {0, ACCEL_PROP_ADAPTIVE_DECELERATION},
+ {0, ACCEL_PROP_VELOCITY_SCALING},
+ {0, AXIS_LABEL_PROP},
+ {0, AXIS_LABEL_PROP_REL_X},
+ {0, AXIS_LABEL_PROP_REL_Y},
+ {0, AXIS_LABEL_PROP_REL_Z},
+ {0, AXIS_LABEL_PROP_REL_RX},
+ {0, AXIS_LABEL_PROP_REL_RY},
+ {0, AXIS_LABEL_PROP_REL_RZ},
+ {0, AXIS_LABEL_PROP_REL_HWHEEL},
+ {0, AXIS_LABEL_PROP_REL_DIAL},
+ {0, AXIS_LABEL_PROP_REL_WHEEL},
+ {0, AXIS_LABEL_PROP_REL_MISC},
+ {0, AXIS_LABEL_PROP_ABS_X},
+ {0, AXIS_LABEL_PROP_ABS_Y},
+ {0, AXIS_LABEL_PROP_ABS_Z},
+ {0, AXIS_LABEL_PROP_ABS_RX},
+ {0, AXIS_LABEL_PROP_ABS_RY},
+ {0, AXIS_LABEL_PROP_ABS_RZ},
+ {0, AXIS_LABEL_PROP_ABS_THROTTLE},
+ {0, AXIS_LABEL_PROP_ABS_RUDDER},
+ {0, AXIS_LABEL_PROP_ABS_WHEEL},
+ {0, AXIS_LABEL_PROP_ABS_GAS},
+ {0, AXIS_LABEL_PROP_ABS_BRAKE},
+ {0, AXIS_LABEL_PROP_ABS_HAT0X},
+ {0, AXIS_LABEL_PROP_ABS_HAT0Y},
+ {0, AXIS_LABEL_PROP_ABS_HAT1X},
+ {0, AXIS_LABEL_PROP_ABS_HAT1Y},
+ {0, AXIS_LABEL_PROP_ABS_HAT2X},
+ {0, AXIS_LABEL_PROP_ABS_HAT2Y},
+ {0, AXIS_LABEL_PROP_ABS_HAT3X},
+ {0, AXIS_LABEL_PROP_ABS_HAT3Y},
+ {0, AXIS_LABEL_PROP_ABS_PRESSURE},
+ {0, AXIS_LABEL_PROP_ABS_DISTANCE},
+ {0, AXIS_LABEL_PROP_ABS_TILT_X},
+ {0, AXIS_LABEL_PROP_ABS_TILT_Y},
+ {0, AXIS_LABEL_PROP_ABS_TOOL_WIDTH},
+ {0, AXIS_LABEL_PROP_ABS_VOLUME},
+ {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MAJOR},
+ {0, AXIS_LABEL_PROP_ABS_MT_TOUCH_MINOR},
+ {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MAJOR},
+ {0, AXIS_LABEL_PROP_ABS_MT_WIDTH_MINOR},
+ {0, AXIS_LABEL_PROP_ABS_MT_ORIENTATION},
+ {0, AXIS_LABEL_PROP_ABS_MT_POSITION_X},
+ {0, AXIS_LABEL_PROP_ABS_MT_POSITION_Y},
+ {0, AXIS_LABEL_PROP_ABS_MT_TOOL_TYPE},
+ {0, AXIS_LABEL_PROP_ABS_MT_BLOB_ID},
+ {0, AXIS_LABEL_PROP_ABS_MT_TRACKING_ID},
+ {0, AXIS_LABEL_PROP_ABS_MT_PRESSURE},
+ {0, AXIS_LABEL_PROP_ABS_MISC},
+
+ {0, BTN_LABEL_PROP},
+ {0, BTN_LABEL_PROP_BTN_UNKNOWN},
+ {0, BTN_LABEL_PROP_BTN_WHEEL_UP},
+ {0, BTN_LABEL_PROP_BTN_WHEEL_DOWN},
+ {0, BTN_LABEL_PROP_BTN_HWHEEL_LEFT},
+ {0, BTN_LABEL_PROP_BTN_HWHEEL_RIGHT},
+ {0, BTN_LABEL_PROP_BTN_0},
+ {0, BTN_LABEL_PROP_BTN_1},
+ {0, BTN_LABEL_PROP_BTN_2},
+ {0, BTN_LABEL_PROP_BTN_3},
+ {0, BTN_LABEL_PROP_BTN_4},
+ {0, BTN_LABEL_PROP_BTN_5},
+ {0, BTN_LABEL_PROP_BTN_6},
+ {0, BTN_LABEL_PROP_BTN_7},
+ {0, BTN_LABEL_PROP_BTN_8},
+ {0, BTN_LABEL_PROP_BTN_9},
+
+ {0, BTN_LABEL_PROP_BTN_LEFT},
+ {0, BTN_LABEL_PROP_BTN_RIGHT},
+ {0, BTN_LABEL_PROP_BTN_MIDDLE},
+ {0, BTN_LABEL_PROP_BTN_SIDE},
+ {0, BTN_LABEL_PROP_BTN_EXTRA},
+ {0, BTN_LABEL_PROP_BTN_FORWARD},
+ {0, BTN_LABEL_PROP_BTN_BACK},
+ {0, BTN_LABEL_PROP_BTN_TASK},
+
+ {0, BTN_LABEL_PROP_BTN_TRIGGER},
+ {0, BTN_LABEL_PROP_BTN_THUMB},
+ {0, BTN_LABEL_PROP_BTN_THUMB2},
+ {0, BTN_LABEL_PROP_BTN_TOP},
+ {0, BTN_LABEL_PROP_BTN_TOP2},
+ {0, BTN_LABEL_PROP_BTN_PINKIE},
+ {0, BTN_LABEL_PROP_BTN_BASE},
+ {0, BTN_LABEL_PROP_BTN_BASE2},
+ {0, BTN_LABEL_PROP_BTN_BASE3},
+ {0, BTN_LABEL_PROP_BTN_BASE4},
+ {0, BTN_LABEL_PROP_BTN_BASE5},
+ {0, BTN_LABEL_PROP_BTN_BASE6},
+ {0, BTN_LABEL_PROP_BTN_DEAD},
+
+ {0, BTN_LABEL_PROP_BTN_A},
+ {0, BTN_LABEL_PROP_BTN_B},
+ {0, BTN_LABEL_PROP_BTN_C},
+ {0, BTN_LABEL_PROP_BTN_X},
+ {0, BTN_LABEL_PROP_BTN_Y},
+ {0, BTN_LABEL_PROP_BTN_Z},
+ {0, BTN_LABEL_PROP_BTN_TL},
+ {0, BTN_LABEL_PROP_BTN_TR},
+ {0, BTN_LABEL_PROP_BTN_TL2},
+ {0, BTN_LABEL_PROP_BTN_TR2},
+ {0, BTN_LABEL_PROP_BTN_SELECT},
+ {0, BTN_LABEL_PROP_BTN_START},
+ {0, BTN_LABEL_PROP_BTN_MODE},
+ {0, BTN_LABEL_PROP_BTN_THUMBL},
+ {0, BTN_LABEL_PROP_BTN_THUMBR},
+
+ {0, BTN_LABEL_PROP_BTN_TOOL_PEN},
+ {0, BTN_LABEL_PROP_BTN_TOOL_RUBBER},
+ {0, BTN_LABEL_PROP_BTN_TOOL_BRUSH},
+ {0, BTN_LABEL_PROP_BTN_TOOL_PENCIL},
+ {0, BTN_LABEL_PROP_BTN_TOOL_AIRBRUSH},
+ {0, BTN_LABEL_PROP_BTN_TOOL_FINGER},
+ {0, BTN_LABEL_PROP_BTN_TOOL_MOUSE},
+ {0, BTN_LABEL_PROP_BTN_TOOL_LENS},
+ {0, BTN_LABEL_PROP_BTN_TOUCH},
+ {0, BTN_LABEL_PROP_BTN_STYLUS},
+ {0, BTN_LABEL_PROP_BTN_STYLUS2},
+ {0, BTN_LABEL_PROP_BTN_TOOL_DOUBLETAP},
+ {0, BTN_LABEL_PROP_BTN_TOOL_TRIPLETAP},
+
+ {0, BTN_LABEL_PROP_BTN_GEAR_DOWN},
+ {0, BTN_LABEL_PROP_BTN_GEAR_UP}
+};
+
+static long XIPropHandlerID = 1;
+
+static void send_property_event(DeviceIntPtr dev, Atom property, int what)
+{
+ devicePropertyNotify event;
+ xXIPropertyEvent xi2;
+ int state;
+
+ if (what == XIPropertyDeleted)
+ state = PropertyDelete;
+ else
+ state = PropertyNewValue;
+
+ event.type = DevicePropertyNotify;
+ event.deviceid = dev->id;
+ event.state = state;
+ event.atom = property;
+ event.time = currentTime.milliseconds;
+ SendEventToAllWindows(dev, DevicePropertyNotifyMask,
+ (xEvent*)&event, 1);
+
+ xi2.type = GenericEvent;
+ xi2.extension = IReqCode;
+ xi2.length = 0;
+ xi2.evtype = XI_PropertyEvent;
+ xi2.deviceid = dev->id;
+ xi2.time = currentTime.milliseconds;
+ xi2.property = property;
+ xi2.what = what;
+ SendEventToAllWindows(dev, GetEventFilter(dev, (xEvent*)&xi2),
+ (xEvent*)&xi2, 1);
+}
+
+static int list_atoms(DeviceIntPtr dev, int *natoms, Atom **atoms_return)
+{
+ XIPropertyPtr prop;
+ Atom *atoms = NULL;
+ int nprops = 0;
+
+ for (prop = dev->properties.properties; prop; prop = prop->next)
+ nprops++;
+ if (nprops)
+ {
+ Atom *a;
+
+ atoms = xalloc(nprops * sizeof(Atom));
+ if(!atoms)
+ return BadAlloc;
+ a = atoms;
+ for (prop = dev->properties.properties; prop; prop = prop->next, a++)
+ *a = prop->propertyName;
+ }
+
+ *natoms = nprops;
+ *atoms_return = atoms;
+ return Success;
+}
+
+static int
+get_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
+ BOOL delete, int offset, int length,
+ int *bytes_after, Atom *type_return, int *format, int *nitems,
+ int *length_return, char **data)
+{
+ unsigned long n, len, ind;
+ int rc;
+ XIPropertyPtr prop;
+ XIPropertyValuePtr prop_value;
+
+ if (!ValidAtom(property))
+ {
+ client->errorValue = property;
+ return(BadAtom);
+ }
+ if ((delete != xTrue) && (delete != xFalse))
+ {
+ client->errorValue = delete;
+ return(BadValue);
+ }
+
+ if ((type != AnyPropertyType) && !ValidAtom(type))
+ {
+ client->errorValue = type;
+ return(BadAtom);
+ }
+
+ for (prop = dev->properties.properties; prop; prop = prop->next)
+ if (prop->propertyName == property)
+ break;
+
+ if (!prop)
+ {
+ *bytes_after = 0;
+ *type_return = None;
+ *format = 0;
+ *nitems = 0;
+ *length_return = 0;
+ return Success;
+ }
+
+ rc = XIGetDeviceProperty(dev, property, &prop_value);
+ if (rc != Success)
+ {
+ client->errorValue = property;
+ return rc;
+ }
+
+ /* If the request type and actual type don't match. Return the
+ property information, but not the data. */
+
+ if (((type != prop_value->type) && (type != AnyPropertyType)))
+ {
+ *bytes_after = prop_value->size;
+ *format = prop_value->format;
+ *length_return = 0;
+ *nitems = 0;
+ *type_return = prop_value->type;
+ return Success;
+ }
+
+ /* Return type, format, value to client */
+ n = (prop_value->format/8) * prop_value->size; /* size (bytes) of prop */
+ ind = offset << 2;
+
+ /* If offset is invalid such that it causes "len" to
+ be negative, it's a value error. */
+
+ if (n < ind)
+ {
+ client->errorValue = offset;
+ return BadValue;
+ }
+
+ len = min(n - ind, 4 * length);
+
+ *bytes_after = n - (ind + len);
+ *format = prop_value->format;
+ *length_return = len;
+ if (prop_value->format)
+ *nitems = len / (prop_value->format / 8);
+ else
+ *nitems = 0;
+ *type_return = prop_value->type;
+
+ *data = (char*)prop_value->data + ind;
+
+ return Success;
+}
+
+static int
+check_change_property(ClientPtr client, Atom property, Atom type, int format,
+ int mode, int nitems)
+{
+ if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
+ (mode != PropModePrepend))
+ {
+ client->errorValue = mode;
+ return BadValue;
+ }
+ if ((format != 8) && (format != 16) && (format != 32))
+ {
+ client->errorValue = format;
+ return BadValue;
+ }
+
+ if (!ValidAtom(property))
+ {
+ client->errorValue = property;
+ return(BadAtom);
+ }
+ if (!ValidAtom(type))
+ {
+ client->errorValue = type;
+ return(BadAtom);
+ }
+
+ return Success;
+}
+
+static int
+change_property(ClientPtr client, DeviceIntPtr dev, Atom property, Atom type,
+ int format, int mode, int len, void *data)
+{
+ int rc = Success;
+
+ rc = XIChangeDeviceProperty(dev, property, type, format, mode, len, data, TRUE);
+ if (rc != Success)
+ client->errorValue = property;
+
+ return rc;
+}
+
+/**
+ * Return the atom assigned to the specified string or 0 if the atom isn't known
+ * to the DIX.
+ *
+ * If name is NULL, None is returned.
+ */
+Atom
+XIGetKnownProperty(char *name)
+{
+ int i;
+
+ if (!name)
+ return None;
+
+ for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++)
+ {
+ if (strcmp(name, dev_properties[i].name) == 0){
+ if (dev_properties[i].type == None){
+ dev_properties[i].type =
+ MakeAtom(dev_properties[i].name,
+ strlen(dev_properties[i].name),
+ TRUE);
+ }
+
+ return dev_properties[i].type;
+ }
+ }
+
+ return 0;
+}
+
+void
+XIResetProperties(void)
+{
+ int i;
+
+ for (i = 0; i < (sizeof(dev_properties)/sizeof(struct dev_properties)); i++)
+ dev_properties[i].type = None;
+}
+
+/**
+ * Convert the given property's value(s) into @nelem_return integer values and
+ * store them in @buf_return. If @nelem_return is larger than the number of
+ * values in the property, @nelem_return is set to the number of values in the
+ * property.
+ *
+ * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
+ * automatically and must be freed by the caller.
+ *
+ * Possible return codes.
+ * Success ... No error.
+ * BadMatch ... Wrong atom type, atom is not XA_INTEGER
+ * BadAlloc ... NULL passed as buffer and allocation failed.
+ * BadLength ... @buff is NULL but @nelem_return is non-zero.
+ *
+ * @param val The property value
+ * @param nelem_return The maximum number of elements to return.
+ * @param buf_return Pointer to an array of at least @nelem_return values.
+ * @return Success or the error code if an error occured.
+ */
+_X_EXPORT int
+XIPropToInt(XIPropertyValuePtr val, int *nelem_return, int **buf_return)
+{
+ int i;
+ int *buf;
+
+ if (val->type != XA_INTEGER)
+ return BadMatch;
+ if (!*buf_return && *nelem_return)
+ return BadLength;
+
+ switch(val->format)
+ {
+ case 8:
+ case 16:
+ case 32:
+ break;
+ default:
+ return BadValue;
+ }
+
+ buf = *buf_return;
+
+ if (!buf && !(*nelem_return))
+ {
+ buf = xcalloc(val->size, sizeof(int));
+ if (!buf)
+ return BadAlloc;
+ *buf_return = buf;
+ *nelem_return = val->size;
+ } else if (val->size < *nelem_return)
+ *nelem_return = val->size;
+
+ for (i = 0; i < val->size && i < *nelem_return; i++)
+ {
+ switch(val->format)
+ {
+ case 8: buf[i] = ((CARD8*)val->data)[i]; break;
+ case 16: buf[i] = ((CARD16*)val->data)[i]; break;
+ case 32: buf[i] = ((CARD32*)val->data)[i]; break;
+ }
+ }
+
+ return Success;
+}
+
+/**
+ * Convert the given property's value(s) into @nelem_return float values and
+ * store them in @buf_return. If @nelem_return is larger than the number of
+ * values in the property, @nelem_return is set to the number of values in the
+ * property.
+ *
+ * If *@buf_return is NULL and @nelem_return is 0, memory is allocated
+ * automatically and must be freed by the caller.
+ *
+ * Possible errors returned:
+ * Success
+ * BadMatch ... Wrong atom type, atom is not XA_FLOAT
+ * BadValue ... Wrong format, format is not 32
+ * BadAlloc ... NULL passed as buffer and allocation failed.
+ * BadLength ... @buff is NULL but @nelem_return is non-zero.
+ *
+ * @param val The property value
+ * @param nelem_return The maximum number of elements to return.
+ * @param buf_return Pointer to an array of at least @nelem_return values.
+ * @return Success or the error code if an error occured.
+ */
+_X_EXPORT int
+XIPropToFloat(XIPropertyValuePtr val, int *nelem_return, float **buf_return)
+{
+ int i;
+ float *buf;
+
+ if (!val->type || val->type != XIGetKnownProperty(XATOM_FLOAT))
+ return BadMatch;
+
+ if (val->format != 32)
+ return BadValue;
+ if (!*buf_return && *nelem_return)
+ return BadLength;
+
+ buf = *buf_return;
+
+ if (!buf && !(*nelem_return))
+ {
+ buf = xcalloc(val->size, sizeof(float));
+ if (!buf)
+ return BadAlloc;
+ *buf_return = buf;
+ *nelem_return = val->size;
+ } else if (val->size < *nelem_return)
+ *nelem_return = val->size;
+
+ for (i = 0; i < val->size && i < *nelem_return; i++)
+ buf[i] = ((float*)val->data)[i];
+
+ return Success;
+}
+
+/* Registers a new property handler on the given device and returns a unique
+ * identifier for this handler. This identifier is required to unregister the
+ * property handler again.
+ * @return The handler's identifier or 0 if an error occured.
+ */
+long
+XIRegisterPropertyHandler(DeviceIntPtr dev,
+ int (*SetProperty) (DeviceIntPtr dev,
+ Atom property,
+ XIPropertyValuePtr prop,
+ BOOL checkonly),
+ int (*GetProperty) (DeviceIntPtr dev,
+ Atom property),
+ int (*DeleteProperty) (DeviceIntPtr dev,
+ Atom property))
+{
+ XIPropertyHandlerPtr new_handler;
+
+ new_handler = xcalloc(1, sizeof(XIPropertyHandler));
+ if (!new_handler)
+ return 0;
+
+ new_handler->id = XIPropHandlerID++;
+ new_handler->SetProperty = SetProperty;
+ new_handler->GetProperty = GetProperty;
+ new_handler->DeleteProperty = DeleteProperty;
+ new_handler->next = dev->properties.handlers;
+ dev->properties.handlers = new_handler;
+
+ return new_handler->id;
+}
+
+void
+XIUnregisterPropertyHandler(DeviceIntPtr dev, long id)
+{
+ XIPropertyHandlerPtr curr, prev = NULL;
+
+ curr = dev->properties.handlers;
+ while(curr && curr->id != id)
+ {
+ prev = curr;
+ curr = curr->next;
+ }
+
+ if (!curr)
+ return;
+
+ if (!prev) /* first one */
+ dev->properties.handlers = curr->next;
+ else
+ prev->next = curr->next;
+
+ xfree(curr);
+}
+
+static XIPropertyPtr
+XICreateDeviceProperty (Atom property)
+{
+ XIPropertyPtr prop;
+
+ prop = (XIPropertyPtr)xalloc(sizeof(XIPropertyRec));
+ if (!prop)
+ return NULL;
+
+ prop->next = NULL;
+ prop->propertyName = property;
+ prop->value.type = None;
+ prop->value.format = 0;
+ prop->value.size = 0;
+ prop->value.data = NULL;
+ prop->deletable = TRUE;
+
+ return prop;
+}
+
+static XIPropertyPtr
+XIFetchDeviceProperty(DeviceIntPtr dev, Atom property)
+{
+ XIPropertyPtr prop;
+
+ for (prop = dev->properties.properties; prop; prop = prop->next)
+ if (prop->propertyName == property)
+ return prop;
+ return NULL;
+}
+
+static void
+XIDestroyDeviceProperty (XIPropertyPtr prop)
+{
+ if (prop->value.data)
+ xfree(prop->value.data);
+ xfree(prop);
+}
+
+/* This function destroys all of the device's property-related stuff,
+ * including removing all device handlers.
+ * DO NOT CALL FROM THE DRIVER.
+ */
+void
+XIDeleteAllDeviceProperties (DeviceIntPtr device)
+{
+ XIPropertyPtr prop, next;
+ XIPropertyHandlerPtr curr_handler, next_handler;
+
+ for (prop = device->properties.properties; prop; prop = next)
+ {
+ next = prop->next;
+ send_property_event(device, prop->propertyName, XIPropertyDeleted);
+ XIDestroyDeviceProperty(prop);
+ }
+
+ device->properties.properties = NULL;
+
+ /* Now free all handlers */
+ curr_handler = device->properties.handlers;
+ while(curr_handler)
+ {
+ next_handler = curr_handler->next;
+ xfree(curr_handler);
+ curr_handler = next_handler;
+ }
+
+ device->properties.handlers = NULL;
+}
+
+
+int
+XIDeleteDeviceProperty (DeviceIntPtr device, Atom property, Bool fromClient)
+{
+ XIPropertyPtr prop, *prev;
+ int rc = Success;
+
+ for (prev = &device->properties.properties; (prop = *prev); prev = &(prop->next))
+ if (prop->propertyName == property)
+ break;
+
+ if (!prop)
+ return Success;
+
+ if (fromClient && !prop->deletable)
+ return BadAccess;
+
+ /* Ask handlers if we may delete the property */
+ if (device->properties.handlers)
+ {
+ XIPropertyHandlerPtr handler = device->properties.handlers;
+ while(handler)
+ {
+ if (handler->DeleteProperty)
+ rc = handler->DeleteProperty(device, prop->propertyName);
+ if (rc != Success)
+ return (rc);
+ handler = handler->next;
+ }
+ }
+
+ if (prop)
+ {
+ *prev = prop->next;
+ send_property_event(device, prop->propertyName, XIPropertyDeleted);
+ XIDestroyDeviceProperty (prop);
+ }
+
+ return Success;
+}
+
+int
+XIChangeDeviceProperty (DeviceIntPtr dev, Atom property, Atom type,
+ int format, int mode, unsigned long len,
+ pointer value, Bool sendevent)
+{
+ XIPropertyPtr prop;
+ int size_in_bytes;
+ int total_size;
+ unsigned long total_len;
+ XIPropertyValuePtr prop_value;
+ XIPropertyValueRec new_value;
+ Bool add = FALSE;
+ int rc;
+
+ size_in_bytes = format >> 3;
+
+ /* first see if property already exists */
+ prop = XIFetchDeviceProperty (dev, property);
+ if (!prop) /* just add to list */
+ {
+ prop = XICreateDeviceProperty (property);
+ if (!prop)
+ return(BadAlloc);
+ add = TRUE;
+ mode = PropModeReplace;
+ }
+ prop_value = &prop->value;
+
+ /* To append or prepend to a property the request format and type
+ must match those of the already defined property. The
+ existing format and type are irrelevant when using the mode
+ "PropModeReplace" since they will be written over. */
+
+ if ((format != prop_value->format) && (mode != PropModeReplace))
+ return(BadMatch);
+ if ((prop_value->type != type) && (mode != PropModeReplace))
+ return(BadMatch);
+ new_value = *prop_value;
+ if (mode == PropModeReplace)
+ total_len = len;
+ else
+ total_len = prop_value->size + len;
+
+ if (mode == PropModeReplace || len > 0)
+ {
+ pointer new_data = NULL, old_data = NULL;
+
+ total_size = total_len * size_in_bytes;
+ new_value.data = (pointer)xalloc (total_size);
+ if (!new_value.data && total_size)
+ {
+ if (add)
+ XIDestroyDeviceProperty (prop);
+ return BadAlloc;
+ }
+ new_value.size = len;
+ new_value.type = type;
+ new_value.format = format;
+
+ switch (mode) {
+ case PropModeReplace:
+ new_data = new_value.data;
+ old_data = NULL;
+ break;
+ case PropModeAppend:
+ new_data = (pointer) (((char *) new_value.data) +
+ (prop_value->size * size_in_bytes));
+ old_data = new_value.data;
+ break;
+ case PropModePrepend:
+ new_data = new_value.data;
+ old_data = (pointer) (((char *) new_value.data) +
+ (prop_value->size * size_in_bytes));
+ break;
+ }
+ if (new_data)
+ memcpy ((char *) new_data, (char *) value, len * size_in_bytes);
+ if (old_data)
+ memcpy ((char *) old_data, (char *) prop_value->data,
+ prop_value->size * size_in_bytes);
+
+ if (dev->properties.handlers)
+ {
+ XIPropertyHandlerPtr handler;
+ BOOL checkonly = TRUE;
+ /* run through all handlers with checkonly TRUE, then again with
+ * checkonly FALSE. Handlers MUST return error codes on the
+ * checkonly run, errors on the second run are ignored */
+ do
+ {
+ handler = dev->properties.handlers;
+ while(handler)
+ {
+ if (handler->SetProperty)
+ {
+ rc = handler->SetProperty(dev, prop->propertyName,
+ &new_value, checkonly);
+ if (checkonly && rc != Success)
+ {
+ if (new_value.data)
+ xfree (new_value.data);
+ return (rc);
+ }
+ }
+ handler = handler->next;
+ }
+ checkonly = !checkonly;
+ } while (!checkonly);
+ }
+ if (prop_value->data)
+ xfree (prop_value->data);
+ *prop_value = new_value;
+ } else if (len == 0)
+ {
+ /* do nothing */
+ }
+
+ if (add)
+ {
+ prop->next = dev->properties.properties;
+ dev->properties.properties = prop;
+ }
+
+ if (sendevent)
+ send_property_event(dev, prop->propertyName,
+ (add) ? XIPropertyCreated : XIPropertyModified);
+
+ return(Success);
+}
+
+int
+XIGetDeviceProperty (DeviceIntPtr dev, Atom property, XIPropertyValuePtr *value)
+{
+ XIPropertyPtr prop = XIFetchDeviceProperty (dev, property);
+ int rc;
+
+ if (!prop)
+ {
+ *value = NULL;
+ return BadAtom;
+ }
+
+ /* If we can, try to update the property value first */
+ if (dev->properties.handlers)
+ {
+ XIPropertyHandlerPtr handler = dev->properties.handlers;
+ while(handler)
+ {
+ if (handler->GetProperty)
+ {
+ rc = handler->GetProperty(dev, prop->propertyName);
+ if (rc != Success)
+ {
+ *value = NULL;
+ return rc;
+ }
+ }
+ handler = handler->next;
+ }
+ }
+
+ *value = &prop->value;
+ return Success;
+}
+
+int
+XISetDevicePropertyDeletable(DeviceIntPtr dev, Atom property, Bool deletable)
+{
+ XIPropertyPtr prop = XIFetchDeviceProperty(dev, property);
+
+ if (!prop)
+ return BadAtom;
+
+ prop->deletable = deletable;
+ return Success;
+}
+
+int
+ProcXListDeviceProperties (ClientPtr client)
+{
+ Atom *atoms;
+ xListDevicePropertiesReply rep;
+ int natoms;
+ DeviceIntPtr dev;
+ int rc = Success;
+
+ REQUEST(xListDevicePropertiesReq);
+ REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixListPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = list_atoms(dev, &natoms, &atoms);
+ if (rc != Success)
+ return rc;
+
+ rep.repType = X_Reply;
+ rep.RepType = X_ListDeviceProperties;
+ rep.length = natoms;
+ rep.sequenceNumber = client->sequence;
+ rep.nAtoms = natoms;
+
+ WriteReplyToClient(client, sizeof(xListDevicePropertiesReply), &rep);
+ if (natoms)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
+ WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
+ xfree(atoms);
+ }
+ return rc;
+}
+
+int
+ProcXChangeDeviceProperty (ClientPtr client)
+{
+ REQUEST(xChangeDevicePropertyReq);
+ DeviceIntPtr dev;
+ unsigned long len;
+ int totalSize;
+ int rc;
+
+ REQUEST_AT_LEAST_SIZE(xChangeDevicePropertyReq);
+ UpdateCurrentTime();
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = check_change_property(client, stuff->property, stuff->type,
+ stuff->format, stuff->mode, stuff->nUnits);
+
+ len = stuff->nUnits;
+ if (len > (bytes_to_int32(0xffffffff - sizeof(xChangeDevicePropertyReq))))
+ return BadLength;
+
+ totalSize = len * (stuff->format/8);
+ REQUEST_FIXED_SIZE(xChangeDevicePropertyReq, totalSize);
+
+ rc = change_property(client, dev, stuff->property, stuff->type,
+ stuff->format, stuff->mode, len, (void*)&stuff[1]);
+ return rc;
+}
+
+int
+ProcXDeleteDeviceProperty (ClientPtr client)
+{
+ REQUEST(xDeleteDevicePropertyReq);
+ DeviceIntPtr dev;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return (BadAtom);
+ }
+
+ rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
+ return rc;
+}
+
+int
+ProcXGetDeviceProperty (ClientPtr client)
+{
+ REQUEST(xGetDevicePropertyReq);
+ DeviceIntPtr dev;
+ int length;
+ int rc, format, nitems, bytes_after;
+ char *data;
+ Atom type;
+ xGetDevicePropertyReply reply;
+
+ REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
+ if (stuff->delete)
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client,
+ stuff->delete ? DixSetPropAccess :
+ DixGetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = get_property(client, dev, stuff->property, stuff->type,
+ stuff->delete, stuff->longOffset, stuff->longLength,
+ &bytes_after, &type, &format, &nitems, &length, &data);
+
+ if (rc != Success)
+ return rc;
+
+ reply.repType = X_Reply;
+ reply.RepType = X_GetDeviceProperty;
+ reply.sequenceNumber = client->sequence;
+ reply.deviceid = dev->id;
+ reply.nItems = nitems;
+ reply.format = format;
+ reply.bytesAfter = bytes_after;
+ reply.propertyType = type;
+ reply.length = bytes_to_int32(length);
+
+ if (stuff->delete && (reply.bytesAfter == 0))
+ send_property_event(dev, stuff->property, XIPropertyDeleted);
+
+ WriteReplyToClient(client, sizeof(xGenericReply), &reply);
+
+ if (length)
+ {
+ switch (reply.format) {
+ case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
+ case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
+ default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
+ }
+ WriteSwappedDataToClient(client, length, data);
+ }
+
+ /* delete the Property */
+ if (stuff->delete && (reply.bytesAfter == 0))
+ {
+ XIPropertyPtr prop, *prev;
+ for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next)
+ {
+ if (prop->propertyName == stuff->property)
+ {
+ *prev = prop->next;
+ XIDestroyDeviceProperty(prop);
+ break;
+ }
+ }
+ }
+ return Success;
+}
+
+
+int
+SProcXListDeviceProperties (ClientPtr client)
+{
+ char n;
+ REQUEST(xListDevicePropertiesReq);
+
+ swaps(&stuff->length, n);
+
+ REQUEST_SIZE_MATCH(xListDevicePropertiesReq);
+ return (ProcXListDeviceProperties(client));
+}
+
+int
+SProcXChangeDeviceProperty (ClientPtr client)
+{
+ char n;
+ REQUEST(xChangeDevicePropertyReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->nUnits, n);
+ REQUEST_SIZE_MATCH(xChangeDevicePropertyReq);
+ return (ProcXChangeDeviceProperty(client));
+}
+
+int
+SProcXDeleteDeviceProperty (ClientPtr client)
+{
+ char n;
+ REQUEST(xDeleteDevicePropertyReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->property, n);
+ REQUEST_SIZE_MATCH(xDeleteDevicePropertyReq);
+ return (ProcXDeleteDeviceProperty(client));
+}
+
+int
+SProcXGetDeviceProperty (ClientPtr client)
+{
+ char n;
+ REQUEST(xGetDevicePropertyReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->longOffset, n);
+ swapl(&stuff->longLength, n);
+ REQUEST_SIZE_MATCH(xGetDevicePropertyReq);
+ return (ProcXGetDeviceProperty(client));
+}
+
+
+/* Reply swapping */
+
+void
+SRepXListDeviceProperties(ClientPtr client, int size,
+ xListDevicePropertiesReply *rep)
+{
+ char n;
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->nAtoms, n);
+ /* properties will be swapped later, see ProcXListDeviceProperties */
+ WriteToClient(client, size, (char*)rep);
+}
+
+void
+SRepXGetDeviceProperty(ClientPtr client, int size,
+ xGetDevicePropertyReply *rep)
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swapl(&rep->propertyType, n);
+ swapl(&rep->bytesAfter, n);
+ swapl(&rep->nItems, n);
+ /* data will be swapped, see ProcXGetDeviceProperty */
+ WriteToClient(client, size, (char*)rep);
+}
+
+/* XI2 Request/reply handling */
+int
+ProcXIListProperties(ClientPtr client)
+{
+ Atom *atoms;
+ xXIListPropertiesReply rep;
+ int natoms;
+ DeviceIntPtr dev;
+ int rc = Success;
+
+ REQUEST(xXIListPropertiesReq);
+ REQUEST_SIZE_MATCH(xXIListPropertiesReq);
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixListPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = list_atoms(dev, &natoms, &atoms);
+ if (rc != Success)
+ return rc;
+
+ rep.repType = X_Reply;
+ rep.RepType = X_XIListProperties;
+ rep.length = natoms;
+ rep.sequenceNumber = client->sequence;
+ rep.num_properties = natoms;
+
+ WriteReplyToClient(client, sizeof(xXIListPropertiesReply), &rep);
+ if (natoms)
+ {
+ client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
+ WriteSwappedDataToClient(client, natoms * sizeof(Atom), atoms);
+ xfree(atoms);
+ }
+ return rc;
+}
+
+int
+ProcXIChangeProperty(ClientPtr client)
+{
+ int rc;
+ DeviceIntPtr dev;
+ int totalSize;
+ unsigned long len;
+
+ REQUEST(xXIChangePropertyReq);
+ REQUEST_AT_LEAST_SIZE(xXIChangePropertyReq);
+ UpdateCurrentTime();
+
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = check_change_property(client, stuff->property, stuff->type,
+ stuff->format, stuff->mode, stuff->num_items);
+ len = stuff->num_items;
+ if (len > bytes_to_int32(0xffffffff - sizeof(xXIChangePropertyReq)))
+ return BadLength;
+
+ totalSize = len * (stuff->format/8);
+ REQUEST_FIXED_SIZE(xXIChangePropertyReq, totalSize);
+
+ rc = change_property(client, dev, stuff->property, stuff->type,
+ stuff->format, stuff->mode, len, (void*)&stuff[1]);
+ return rc;
+}
+
+int
+ProcXIDeleteProperty(ClientPtr client)
+{
+ DeviceIntPtr dev;
+ int rc;
+ REQUEST(xXIDeletePropertyReq);
+
+ REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client, DixSetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ if (!ValidAtom(stuff->property))
+ {
+ client->errorValue = stuff->property;
+ return (BadAtom);
+ }
+
+ rc = XIDeleteDeviceProperty(dev, stuff->property, TRUE);
+ return rc;
+}
+
+
+int
+ProcXIGetProperty(ClientPtr client)
+{
+ REQUEST(xXIGetPropertyReq);
+ DeviceIntPtr dev;
+ xXIGetPropertyReply reply;
+ int length;
+ int rc, format, nitems, bytes_after;
+ char *data;
+ Atom type;
+
+ REQUEST_SIZE_MATCH(xXIGetPropertyReq);
+ if (stuff->delete)
+ UpdateCurrentTime();
+ rc = dixLookupDevice (&dev, stuff->deviceid, client,
+ stuff->delete ? DixSetPropAccess :
+ DixGetPropAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = get_property(client, dev, stuff->property, stuff->type,
+ stuff->delete, stuff->offset, stuff->len,
+ &bytes_after, &type, &format, &nitems, &length, &data);
+
+ if (rc != Success)
+ return rc;
+
+ reply.repType = X_Reply;
+ reply.RepType = X_XIGetProperty;
+ reply.sequenceNumber = client->sequence;
+ reply.num_items = nitems;
+ reply.format = format;
+ reply.bytes_after = bytes_after;
+ reply.type = type;
+ reply.length = bytes_to_int32(length);
+
+ if (length && stuff->delete && (reply.bytes_after == 0))
+ send_property_event(dev, stuff->property, XIPropertyDeleted);
+
+ WriteReplyToClient(client, sizeof(xXIGetPropertyReply), &reply);
+
+ if (length)
+ {
+ switch (reply.format) {
+ case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
+ case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
+ default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
+ }
+ WriteSwappedDataToClient(client, length, data);
+ }
+
+ /* delete the Property */
+ if (stuff->delete && (reply.bytes_after == 0))
+ {
+ XIPropertyPtr prop, *prev;
+ for (prev = &dev->properties.properties; (prop = *prev); prev = &prop->next)
+ {
+ if (prop->propertyName == stuff->property)
+ {
+ *prev = prop->next;
+ XIDestroyDeviceProperty(prop);
+ break;
+ }
+ }
+ }
+
+ return Success;
+}
+
+int
+SProcXIListProperties(ClientPtr client)
+{
+ char n;
+ REQUEST(xXIListPropertiesReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+
+ REQUEST_SIZE_MATCH(xXIListPropertiesReq);
+ return (ProcXIListProperties(client));
+}
+
+int
+SProcXIChangeProperty(ClientPtr client)
+{
+ char n;
+ REQUEST(xXIChangePropertyReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->num_items, n);
+ REQUEST_SIZE_MATCH(xXIChangePropertyReq);
+ return (ProcXIChangeProperty(client));
+}
+
+int
+SProcXIDeleteProperty(ClientPtr client)
+{
+ char n;
+ REQUEST(xXIDeletePropertyReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->property, n);
+ REQUEST_SIZE_MATCH(xXIDeletePropertyReq);
+ return (ProcXIDeleteProperty(client));
+}
+
+int
+SProcXIGetProperty(ClientPtr client)
+{
+ char n;
+ REQUEST(xXIGetPropertyReq);
+
+ swaps(&stuff->length, n);
+ swaps(&stuff->deviceid, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->offset, n);
+ swapl(&stuff->len, n);
+ REQUEST_SIZE_MATCH(xXIGetPropertyReq);
+ return (ProcXIGetProperty(client));
+}
+
+
+void
+SRepXIListProperties(ClientPtr client, int size,
+ xXIListPropertiesReply *rep)
+{
+ char n;
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swaps(&rep->num_properties, n);
+ /* properties will be swapped later, see ProcXIListProperties */
+ WriteToClient(client, size, (char*)rep);
+}
+
+void
+SRepXIGetProperty(ClientPtr client, int size,
+ xXIGetPropertyReply *rep)
+{
+ char n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swapl(&rep->type, n);
+ swapl(&rep->bytes_after, n);
+ swapl(&rep->num_items, n);
+ /* data will be swapped, see ProcXIGetProperty */
+ WriteToClient(client, size, (char*)rep);
+}
diff --git a/xorg-server/Xi/xiproperty.h b/xorg-server/Xi/xiproperty.h
index 69b41fafd..a610e083c 100644
--- a/xorg-server/Xi/xiproperty.h
+++ b/xorg-server/Xi/xiproperty.h
@@ -1,65 +1,68 @@
-/*
- * Copyright © 2008 Peter Hutterer
- *
- * 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.
- *
- * Author: Peter Hutterer
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifndef XIPROPERTY_H
-#define XIPROPERTY_H 1
-
-int ProcXListDeviceProperties (ClientPtr client);
-int ProcXChangeDeviceProperty (ClientPtr client);
-int ProcXDeleteDeviceProperty (ClientPtr client);
-int ProcXGetDeviceProperty (ClientPtr client);
-
-/* request swapping */
-int SProcXListDeviceProperties (ClientPtr client);
-int SProcXChangeDeviceProperty (ClientPtr client);
-int SProcXDeleteDeviceProperty (ClientPtr client);
-int SProcXGetDeviceProperty (ClientPtr client);
-
-/* reply swapping */
-void SRepXListDeviceProperties(ClientPtr client, int size,
- xListDevicePropertiesReply *rep);
-void SRepXGetDeviceProperty(ClientPtr client, int size,
- xGetDevicePropertyReply *rep);
-
-/* XI2 request/reply handling */
-int ProcXIListProperties (ClientPtr client);
-int ProcXIChangeProperty (ClientPtr client);
-int ProcXIDeleteProperty (ClientPtr client);
-int ProcXIGetProperty (ClientPtr client);
-
-int SProcXIListProperties (ClientPtr client);
-int SProcXIChangeProperty (ClientPtr client);
-int SProcXIDeleteProperty (ClientPtr client);
-int SProcXIGetProperty (ClientPtr client);
-
-void SRepXIListProperties(ClientPtr client, int size,
- xXIListPropertiesReply *rep);
-void SRepXIGetProperty(ClientPtr client, int size,
- xXIGetPropertyReply *rep);
-#endif /* XIPROPERTY_H */
+/*
+ * Copyright © 2008 Peter Hutterer
+ *
+ * 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.
+ *
+ * Author: Peter Hutterer
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef XIPROPERTY_H
+#define XIPROPERTY_H 1
+
+int ProcXListDeviceProperties (ClientPtr client);
+int ProcXChangeDeviceProperty (ClientPtr client);
+int ProcXDeleteDeviceProperty (ClientPtr client);
+int ProcXGetDeviceProperty (ClientPtr client);
+
+/* request swapping */
+int SProcXListDeviceProperties (ClientPtr client);
+int SProcXChangeDeviceProperty (ClientPtr client);
+int SProcXDeleteDeviceProperty (ClientPtr client);
+int SProcXGetDeviceProperty (ClientPtr client);
+
+/* reply swapping */
+void SRepXListDeviceProperties(ClientPtr client, int size,
+ xListDevicePropertiesReply *rep);
+void SRepXGetDeviceProperty(ClientPtr client, int size,
+ xGetDevicePropertyReply *rep);
+
+/* XI2 request/reply handling */
+int ProcXIListProperties (ClientPtr client);
+int ProcXIChangeProperty (ClientPtr client);
+int ProcXIDeleteProperty (ClientPtr client);
+int ProcXIGetProperty (ClientPtr client);
+
+int SProcXIListProperties (ClientPtr client);
+int SProcXIChangeProperty (ClientPtr client);
+int SProcXIDeleteProperty (ClientPtr client);
+int SProcXIGetProperty (ClientPtr client);
+
+void SRepXIListProperties(ClientPtr client, int size,
+ xXIListPropertiesReply *rep);
+void SRepXIGetProperty(ClientPtr client, int size,
+ xXIGetPropertyReply *rep);
+
+void XIResetProperties(void);
+
+#endif /* XIPROPERTY_H */
diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c
index b813136c7..3e5a7ac74 100644
--- a/xorg-server/dix/dispatch.c
+++ b/xorg-server/dix/dispatch.c
@@ -1324,22 +1324,13 @@ ProcQueryFont(ClientPtr client)
{
xQueryFontReply *reply;
FontPtr pFont;
- GC *pGC;
int rc;
REQUEST(xResourceReq);
REQUEST_SIZE_MATCH(xResourceReq);
- client->errorValue = stuff->id; /* EITHER font or gc */
- rc = dixLookupResourceByType((pointer *)&pFont, stuff->id, RT_FONT, client,
- DixGetAttrAccess);
- if (rc == BadValue) {
- rc = dixLookupResourceByType((pointer *)&pGC, stuff->id, RT_GC, client,
- DixGetAttrAccess);
- if (rc == Success)
- pFont = pGC->font;
- }
+ rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess);
if (rc != Success)
- return (rc == BadValue) ? BadFont: rc;
+ return rc;
{
xCharInfo *pmax = FONTINKMAX(pFont);
@@ -1380,24 +1371,15 @@ ProcQueryTextExtents(ClientPtr client)
{
xQueryTextExtentsReply reply;
FontPtr pFont;
- GC *pGC;
ExtentInfoRec info;
unsigned long length;
int rc;
REQUEST(xQueryTextExtentsReq);
REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
- client->errorValue = stuff->fid; /* EITHER font or gc */
- rc = dixLookupResourceByType((pointer *)&pFont, stuff->fid, RT_FONT, client,
- DixGetAttrAccess);
- if (rc == BadValue) {
- rc = dixLookupResourceByType((pointer *)&pGC, stuff->fid, RT_GC, client,
- DixGetAttrAccess);
- if (rc == Success)
- pFont = pGC->font;
- }
+ rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess);
if (rc != Success)
- return (rc == BadValue) ? BadFont: rc;
+ return rc;
length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq));
length = length << 1;
diff --git a/xorg-server/dix/dixutils.c b/xorg-server/dix/dixutils.c
index 8278d444b..4b84a446b 100644
--- a/xorg-server/dix/dixutils.c
+++ b/xorg-server/dix/dixutils.c
@@ -1,884 +1,902 @@
-/***********************************************************
-
-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.
-
-******************************************************************/
-
-/*
-
-(c)Copyright 1988,1991 Adobe Systems Incorporated. All rights reserved.
-
-Permission to use, copy, modify, distribute, and sublicense this software and its
-documentation for any purpose and without fee is hereby granted, provided that
-the above copyright notices appear in all copies and that both those copyright
-notices and this permission notice appear in supporting documentation and that
-the name of Adobe Systems Incorporated not be used in advertising or publicity
-pertaining to distribution of the software without specific, written prior
-permission. No trademark license to use the Adobe trademarks is hereby
-granted. If the Adobe trademark "Display PostScript"(tm) is used to describe
-this software, its functionality or for any other purpose, such use shall be
-limited to a statement that this software works in conjunction with the Display
-PostScript system. Proper trademark attribution to reflect Adobe's ownership
-of the trademark shall be given whenever any such reference to the Display
-PostScript system is made.
-
-ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY
-PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ADOBE
-DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
-WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
-INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE TO YOU
-OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
-DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT
-LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR
-PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER
-SUPPORT FOR THE SOFTWARE.
-
-Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
-Incorporated which may be registered in certain jurisdictions.
-
-Author: Adobe Systems Incorporated
-
-*/
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include <X11/Xmd.h>
-#include "misc.h"
-#include "windowstr.h"
-#include "dixstruct.h"
-#include "pixmapstr.h"
-#include "scrnintstr.h"
-#define XK_LATIN1
-#include <X11/keysymdef.h>
-#include "xace.h"
-
-/*
- * CompareTimeStamps returns -1, 0, or +1 depending on if the first
- * argument is less than, equal to or greater than the second argument.
- */
-
-int
-CompareTimeStamps(TimeStamp a, TimeStamp b)
-{
- if (a.months < b.months)
- return EARLIER;
- if (a.months > b.months)
- return LATER;
- if (a.milliseconds < b.milliseconds)
- return EARLIER;
- if (a.milliseconds > b.milliseconds)
- return LATER;
- return SAMETIME;
-}
-
-/*
- * convert client times to server TimeStamps
- */
-
-#define HALFMONTH ((unsigned long) 1<<31)
-TimeStamp
-ClientTimeToServerTime(CARD32 c)
-{
- TimeStamp ts;
- if (c == CurrentTime)
- return currentTime;
- ts.months = currentTime.months;
- ts.milliseconds = c;
- if (c > currentTime.milliseconds)
- {
- if (((unsigned long) c - currentTime.milliseconds) > HALFMONTH)
- ts.months -= 1;
- }
- else if (c < currentTime.milliseconds)
- {
- if (((unsigned long)currentTime.milliseconds - c) > HALFMONTH)
- ts.months += 1;
- }
- return ts;
-}
-
-/*
- * ISO Latin-1 case conversion routine
- *
- * this routine always null-terminates the result, so
- * beware of too-small buffers
- */
-
-static unsigned char
-ISOLatin1ToLower (unsigned char source)
-{
- unsigned char dest;
- if ((source >= XK_A) && (source <= XK_Z))
- dest = source + (XK_a - XK_A);
- else if ((source >= XK_Agrave) && (source <= XK_Odiaeresis))
- dest = source + (XK_agrave - XK_Agrave);
- else if ((source >= XK_Ooblique) && (source <= XK_Thorn))
- dest = source + (XK_oslash - XK_Ooblique);
- else
- dest = source;
- return dest;
-}
-
-
-int
-CompareISOLatin1Lowered(unsigned char *s1, int s1len,
- unsigned char *s2, int s2len)
-{
- unsigned char c1, c2;
-
- for (;;)
- {
- /* note -- compare against zero so that -1 ignores len */
- c1 = s1len-- ? *s1++ : '\0';
- c2 = s2len-- ? *s2++ : '\0';
- if (!c1 ||
- (c1 != c2 &&
- (c1 = ISOLatin1ToLower (c1)) != (c2 = ISOLatin1ToLower (c2))))
- break;
- }
- return (int) c1 - (int) c2;
-}
-
-/*
- * dixLookupWindow and dixLookupDrawable:
- * Look up the window/drawable taking into account the client doing the
- * lookup, the type of drawable desired, and the type of access desired.
- * Return Success with *pDraw set if the window/drawable exists and the client
- * is allowed access, else return an error code with *pDraw set to NULL. The
- * access mask values are defined in resource.h. The type mask values are
- * defined in pixmap.h, with zero equivalent to M_DRAWABLE.
- */
-int
-dixLookupDrawable(DrawablePtr *pDraw, XID id, ClientPtr client,
- Mask type, Mask access)
-{
- DrawablePtr pTmp;
- int rc;
-
- *pDraw = NULL;
- client->errorValue = id;
-
- if (id == INVALID)
- return BadDrawable;
-
- rc = dixLookupResourceByClass((pointer *)&pTmp, id, RC_DRAWABLE, client, access);
-
- if (rc == BadValue)
- return BadDrawable;
- if (rc != Success)
- return rc;
- if (!((1 << pTmp->type) & (type ? type : M_DRAWABLE)))
- return BadMatch;
-
- *pDraw = pTmp;
- return Success;
-}
-
-int
-dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access)
-{
- int rc;
- rc = dixLookupDrawable((DrawablePtr*)pWin, id, client, M_WINDOW, access);
- return (rc == BadDrawable) ? BadWindow : rc;
-}
-
-int
-dixLookupGC(GCPtr *pGC, XID id, ClientPtr client, Mask access)
-{
- int rc;
- rc = dixLookupResourceByType((pointer *)pGC, id, RT_GC, client, access);
- return (rc == BadValue) ? BadGC : rc;
-}
-
-int
-dixLookupClient(ClientPtr *pClient, XID rid, ClientPtr client, Mask access)
-{
- pointer pRes;
- int rc = BadValue, clientIndex = CLIENT_ID(rid);
-
- if (!clientIndex || !clients[clientIndex] || (rid & SERVER_BIT))
- goto bad;
-
- rc = dixLookupResourceByClass(&pRes, rid, RC_ANY, client, DixGetAttrAccess);
- if (rc != Success)
- goto bad;
-
- rc = XaceHook(XACE_CLIENT_ACCESS, client, clients[clientIndex], access);
- if (rc != Success)
- goto bad;
-
- *pClient = clients[clientIndex];
- return Success;
-bad:
- if(client)
- client->errorValue = rid;
- *pClient = NULL;
- return rc;
-}
-
-int
-AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode,
- Bool toRoot, Bool map)
-{
- int numnow;
- SaveSetElt *pTmp = NULL;
- int j;
-
- numnow = client->numSaved;
- j = 0;
- if (numnow)
- {
- pTmp = client->saveSet;
- while ((j < numnow) && (SaveSetWindow(pTmp[j]) != (pointer)pWin))
- j++;
- }
- if (mode == SetModeInsert)
- {
- if (j < numnow) /* duplicate */
- return(Success);
- numnow++;
- pTmp = (SaveSetElt *)xrealloc(client->saveSet, sizeof(*pTmp) * numnow);
- if (!pTmp)
- return(BadAlloc);
- client->saveSet = pTmp;
- client->numSaved = numnow;
- SaveSetAssignWindow(client->saveSet[numnow - 1], pWin);
- SaveSetAssignToRoot(client->saveSet[numnow - 1], toRoot);
- SaveSetAssignMap(client->saveSet[numnow - 1], map);
- return(Success);
- }
- else if ((mode == SetModeDelete) && (j < numnow))
- {
- while (j < numnow-1)
- {
- pTmp[j] = pTmp[j+1];
- j++;
- }
- numnow--;
- if (numnow)
- {
- pTmp = (SaveSetElt *)xrealloc(client->saveSet, sizeof(*pTmp) * numnow);
- if (pTmp)
- client->saveSet = pTmp;
- }
- else
- {
- xfree(client->saveSet);
- client->saveSet = (SaveSetElt *)NULL;
- }
- client->numSaved = numnow;
- return(Success);
- }
- return(Success);
-}
-
-void
-DeleteWindowFromAnySaveSet(WindowPtr pWin)
-{
- int i;
- ClientPtr client;
-
- for (i = 0; i< currentMaxClients; i++)
- {
- client = clients[i];
- if (client && client->numSaved)
- (void)AlterSaveSetForClient(client, pWin, SetModeDelete, FALSE, TRUE);
- }
-}
-
-/* No-op Don't Do Anything : sometimes we need to be able to call a procedure
- * that doesn't do anything. For example, on screen with only static
- * colormaps, if someone calls install colormap, it's easier to have a dummy
- * procedure to call than to check if there's a procedure
- */
-void
-NoopDDA(void)
-{
-}
-
-typedef struct _BlockHandler {
- BlockHandlerProcPtr BlockHandler;
- WakeupHandlerProcPtr WakeupHandler;
- pointer blockData;
- Bool deleted;
-} BlockHandlerRec, *BlockHandlerPtr;
-
-static BlockHandlerPtr handlers;
-static int numHandlers;
-static int sizeHandlers;
-static Bool inHandler;
-static Bool handlerDeleted;
-
-/**
- *
- * \param pTimeout DIX doesn't want to know how OS represents time
- * \param pReadMask nor how it represents the det of descriptors
- */
-void
-BlockHandler(pointer pTimeout, pointer pReadmask)
-{
- int i, j;
-
- ++inHandler;
- for (i = 0; i < screenInfo.numScreens; i++)
- (* screenInfo.screens[i]->BlockHandler)(i,
- screenInfo.screens[i]->blockData,
- pTimeout, pReadmask);
- for (i = 0; i < numHandlers; i++)
- (*handlers[i].BlockHandler) (handlers[i].blockData,
- pTimeout, pReadmask);
- if (handlerDeleted)
- {
- for (i = 0; i < numHandlers;)
- if (handlers[i].deleted)
- {
- for (j = i; j < numHandlers - 1; j++)
- handlers[j] = handlers[j+1];
- numHandlers--;
- }
- else
- i++;
- handlerDeleted = FALSE;
- }
- --inHandler;
-}
-
-/**
- *
- * \param result 32 bits of undefined result from the wait
- * \param pReadmask the resulting descriptor mask
- */
-void
-WakeupHandler(int result, pointer pReadmask)
-{
- int i, j;
-
- ++inHandler;
- for (i = numHandlers - 1; i >= 0; i--)
- (*handlers[i].WakeupHandler) (handlers[i].blockData,
- result, pReadmask);
- for (i = 0; i < screenInfo.numScreens; i++)
- (* screenInfo.screens[i]->WakeupHandler)(i,
- screenInfo.screens[i]->wakeupData,
- result, pReadmask);
- if (handlerDeleted)
- {
- for (i = 0; i < numHandlers;)
- if (handlers[i].deleted)
- {
- for (j = i; j < numHandlers - 1; j++)
- handlers[j] = handlers[j+1];
- numHandlers--;
- }
- else
- i++;
- handlerDeleted = FALSE;
- }
- --inHandler;
-}
-
-/**
- * Reentrant with BlockHandler and WakeupHandler, except wakeup won't
- * get called until next time
- */
-Bool
-RegisterBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler,
- WakeupHandlerProcPtr wakeupHandler,
- pointer blockData)
-{
- BlockHandlerPtr new;
-
- if (numHandlers >= sizeHandlers)
- {
- new = (BlockHandlerPtr) xrealloc (handlers, (numHandlers + 1) *
- sizeof (BlockHandlerRec));
- if (!new)
- return FALSE;
- handlers = new;
- sizeHandlers = numHandlers + 1;
- }
- handlers[numHandlers].BlockHandler = blockHandler;
- handlers[numHandlers].WakeupHandler = wakeupHandler;
- handlers[numHandlers].blockData = blockData;
- handlers[numHandlers].deleted = FALSE;
- numHandlers = numHandlers + 1;
- return TRUE;
-}
-
-void
-RemoveBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler,
- WakeupHandlerProcPtr wakeupHandler,
- pointer blockData)
-{
- int i;
-
- for (i = 0; i < numHandlers; i++)
- if (handlers[i].BlockHandler == blockHandler &&
- handlers[i].WakeupHandler == wakeupHandler &&
- handlers[i].blockData == blockData)
- {
- if (inHandler)
- {
- handlerDeleted = TRUE;
- handlers[i].deleted = TRUE;
- }
- else
- {
- for (; i < numHandlers - 1; i++)
- handlers[i] = handlers[i+1];
- numHandlers--;
- }
- break;
- }
-}
-
-void
-InitBlockAndWakeupHandlers (void)
-{
- xfree (handlers);
- handlers = (BlockHandlerPtr) 0;
- numHandlers = 0;
- sizeHandlers = 0;
-}
-
-/*
- * A general work queue. Perform some task before the server
- * sleeps for input.
- */
-
-WorkQueuePtr workQueue;
-static WorkQueuePtr *workQueueLast = &workQueue;
-
-void
-ProcessWorkQueue(void)
-{
- WorkQueuePtr q, *p;
-
- p = &workQueue;
- /*
- * Scan the work queue once, calling each function. Those
- * which return TRUE are removed from the queue, otherwise
- * they will be called again. This must be reentrant with
- * QueueWorkProc.
- */
- while ((q = *p))
- {
- if ((*q->function) (q->client, q->closure))
- {
- /* remove q from the list */
- *p = q->next; /* don't fetch until after func called */
- xfree (q);
- }
- else
- {
- p = &q->next; /* don't fetch until after func called */
- }
- }
- workQueueLast = p;
-}
-
-void
-ProcessWorkQueueZombies(void)
-{
- WorkQueuePtr q, *p;
-
- p = &workQueue;
- while ((q = *p))
- {
- if (q->client && q->client->clientGone)
- {
- (void) (*q->function) (q->client, q->closure);
- /* remove q from the list */
- *p = q->next; /* don't fetch until after func called */
- xfree (q);
- }
- else
- {
- p = &q->next; /* don't fetch until after func called */
- }
- }
- workQueueLast = p;
-}
-
-Bool
-QueueWorkProc (
- Bool (*function)(ClientPtr /* pClient */, pointer /* closure */),
- ClientPtr client, pointer closure)
-{
- WorkQueuePtr q;
-
- q = xalloc (sizeof *q);
- if (!q)
- return FALSE;
- q->function = function;
- q->client = client;
- q->closure = closure;
- q->next = NULL;
- *workQueueLast = q;
- workQueueLast = &q->next;
- return TRUE;
-}
-
-/*
- * Manage a queue of sleeping clients, awakening them
- * when requested, by using the OS functions IgnoreClient
- * and AttendClient. Note that this *ignores* the troubles
- * with request data interleaving itself with events, but
- * we'll leave that until a later time.
- */
-
-typedef struct _SleepQueue {
- struct _SleepQueue *next;
- ClientPtr client;
- ClientSleepProcPtr function;
- pointer closure;
-} SleepQueueRec, *SleepQueuePtr;
-
-static SleepQueuePtr sleepQueue = NULL;
-
-Bool
-ClientSleep (ClientPtr client, ClientSleepProcPtr function, pointer closure)
-{
- SleepQueuePtr q;
-
- q = xalloc (sizeof *q);
- if (!q)
- return FALSE;
-
- IgnoreClient (client);
- q->next = sleepQueue;
- q->client = client;
- q->function = function;
- q->closure = closure;
- sleepQueue = q;
- return TRUE;
-}
-
-Bool
-ClientSignal (ClientPtr client)
-{
- SleepQueuePtr q;
-
- for (q = sleepQueue; q; q = q->next)
- if (q->client == client)
- {
- return QueueWorkProc (q->function, q->client, q->closure);
- }
- return FALSE;
-}
-
-void
-ClientWakeup (ClientPtr client)
-{
- SleepQueuePtr q, *prev;
-
- prev = &sleepQueue;
- while ( (q = *prev) )
- {
- if (q->client == client)
- {
- *prev = q->next;
- xfree (q);
- if (client->clientGone)
- /* Oops -- new zombie cleanup code ensures this only
- * happens from inside CloseDownClient; don't want to
- * recurse here...
- */
- /* CloseDownClient(client) */;
- else
- AttendClient (client);
- break;
- }
- prev = &q->next;
- }
-}
-
-Bool
-ClientIsAsleep (ClientPtr client)
-{
- SleepQueuePtr q;
-
- for (q = sleepQueue; q; q = q->next)
- if (q->client == client)
- return TRUE;
- return FALSE;
-}
-
-/*
- * Generic Callback Manager
- */
-
-/* ===== Private Procedures ===== */
-
-static int numCallbackListsToCleanup = 0;
-static CallbackListPtr **listsToCleanup = NULL;
-
-static Bool
-_AddCallback(
- CallbackListPtr *pcbl,
- CallbackProcPtr callback,
- pointer data)
-{
- CallbackPtr cbr;
-
- cbr = xalloc(sizeof(CallbackRec));
- if (!cbr)
- return FALSE;
- cbr->proc = callback;
- cbr->data = data;
- cbr->next = (*pcbl)->list;
- cbr->deleted = FALSE;
- (*pcbl)->list = cbr;
- return TRUE;
-}
-
-static Bool
-_DeleteCallback(
- CallbackListPtr *pcbl,
- CallbackProcPtr callback,
- pointer data)
-{
- CallbackListPtr cbl = *pcbl;
- CallbackPtr cbr, pcbr;
-
- for (pcbr = NULL, cbr = cbl->list;
- cbr != NULL;
- pcbr = cbr, cbr = cbr->next)
- {
- if ((cbr->proc == callback) && (cbr->data == data))
- break;
- }
- if (cbr != NULL)
- {
- if (cbl->inCallback)
- {
- ++(cbl->numDeleted);
- cbr->deleted = TRUE;
- }
- else
- {
- if (pcbr == NULL)
- cbl->list = cbr->next;
- else
- pcbr->next = cbr->next;
- xfree(cbr);
- }
- return TRUE;
- }
- return FALSE;
-}
-
-static void
-_CallCallbacks(
- CallbackListPtr *pcbl,
- pointer call_data)
-{
- CallbackListPtr cbl = *pcbl;
- CallbackPtr cbr, pcbr;
-
- ++(cbl->inCallback);
- for (cbr = cbl->list; cbr != NULL; cbr = cbr->next)
- {
- (*(cbr->proc)) (pcbl, cbr->data, call_data);
- }
- --(cbl->inCallback);
-
- if (cbl->inCallback) return;
-
- /* Was the entire list marked for deletion? */
-
- if (cbl->deleted)
- {
- DeleteCallbackList(pcbl);
- return;
- }
-
- /* Were some individual callbacks on the list marked for deletion?
- * If so, do the deletions.
- */
-
- if (cbl->numDeleted)
- {
- for (pcbr = NULL, cbr = cbl->list; (cbr != NULL) && cbl->numDeleted; )
- {
- if (cbr->deleted)
- {
- if (pcbr)
- {
- cbr = cbr->next;
- xfree(pcbr->next);
- pcbr->next = cbr;
- } else
- {
- cbr = cbr->next;
- xfree(cbl->list);
- cbl->list = cbr;
- }
- cbl->numDeleted--;
- }
- else /* this one wasn't deleted */
- {
- pcbr = cbr;
- cbr = cbr->next;
- }
- }
- }
-}
-
-static void
-_DeleteCallbackList(
- CallbackListPtr *pcbl)
-{
- CallbackListPtr cbl = *pcbl;
- CallbackPtr cbr, nextcbr;
- int i;
-
- if (cbl->inCallback)
- {
- cbl->deleted = TRUE;
- return;
- }
-
- for (i = 0; i < numCallbackListsToCleanup; i++)
- {
- if (listsToCleanup[i] == pcbl)
- {
- listsToCleanup[i] = NULL;
- break;
- }
- }
-
- for (cbr = cbl->list; cbr != NULL; cbr = nextcbr)
- {
- nextcbr = cbr->next;
- xfree(cbr);
- }
- xfree(cbl);
- *pcbl = NULL;
-}
-
-static Bool
-CreateCallbackList(CallbackListPtr *pcbl)
-{
- CallbackListPtr cbl;
- int i;
-
- if (!pcbl) return FALSE;
- cbl = xalloc(sizeof(CallbackListRec));
- if (!cbl) return FALSE;
- cbl->inCallback = 0;
- cbl->deleted = FALSE;
- cbl->numDeleted = 0;
- cbl->list = NULL;
- *pcbl = cbl;
-
- for (i = 0; i < numCallbackListsToCleanup; i++)
- {
- if (!listsToCleanup[i])
- {
- listsToCleanup[i] = pcbl;
- return TRUE;
- }
- }
-
- listsToCleanup = (CallbackListPtr **)xnfrealloc(listsToCleanup,
- sizeof(CallbackListPtr *) * (numCallbackListsToCleanup+1));
- listsToCleanup[numCallbackListsToCleanup] = pcbl;
- numCallbackListsToCleanup++;
- return TRUE;
-}
-
-/* ===== Public Procedures ===== */
-
-Bool
-AddCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data)
-{
- if (!pcbl) return FALSE;
- if (!*pcbl)
- { /* list hasn't been created yet; go create it */
- if (!CreateCallbackList(pcbl))
- return FALSE;
- }
- return _AddCallback(pcbl, callback, data);
-}
-
-Bool
-DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data)
-{
- if (!pcbl || !*pcbl) return FALSE;
- return _DeleteCallback(pcbl, callback, data);
-}
-
-void
-CallCallbacks(CallbackListPtr *pcbl, pointer call_data)
-{
- if (!pcbl || !*pcbl) return;
- _CallCallbacks(pcbl, call_data);
-}
-
-void
-DeleteCallbackList(CallbackListPtr *pcbl)
-{
- if (!pcbl || !*pcbl) return;
- _DeleteCallbackList(pcbl);
-}
-
-void
-InitCallbackManager(void)
-{
- int i;
-
- for (i = 0; i < numCallbackListsToCleanup; i++)
- {
- DeleteCallbackList(listsToCleanup[i]);
- }
- if (listsToCleanup) xfree(listsToCleanup);
-
- numCallbackListsToCleanup = 0;
- listsToCleanup = NULL;
-}
+/***********************************************************
+
+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.
+
+******************************************************************/
+
+/*
+
+(c)Copyright 1988,1991 Adobe Systems Incorporated. All rights reserved.
+
+Permission to use, copy, modify, distribute, and sublicense this software and its
+documentation for any purpose and without fee is hereby granted, provided that
+the above copyright notices appear in all copies and that both those copyright
+notices and this permission notice appear in supporting documentation and that
+the name of Adobe Systems Incorporated not be used in advertising or publicity
+pertaining to distribution of the software without specific, written prior
+permission. No trademark license to use the Adobe trademarks is hereby
+granted. If the Adobe trademark "Display PostScript"(tm) is used to describe
+this software, its functionality or for any other purpose, such use shall be
+limited to a statement that this software works in conjunction with the Display
+PostScript system. Proper trademark attribution to reflect Adobe's ownership
+of the trademark shall be given whenever any such reference to the Display
+PostScript system is made.
+
+ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY
+PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ADOBE
+DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED
+WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-
+INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE TO YOU
+OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY
+DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT
+LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER
+SUPPORT FOR THE SOFTWARE.
+
+Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+Incorporated which may be registered in certain jurisdictions.
+
+Author: Adobe Systems Incorporated
+
+*/
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include <X11/Xmd.h>
+#include "misc.h"
+#include "windowstr.h"
+#include "dixstruct.h"
+#include "pixmapstr.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#define XK_LATIN1
+#include <X11/keysymdef.h>
+#include "xace.h"
+
+/*
+ * CompareTimeStamps returns -1, 0, or +1 depending on if the first
+ * argument is less than, equal to or greater than the second argument.
+ */
+
+int
+CompareTimeStamps(TimeStamp a, TimeStamp b)
+{
+ if (a.months < b.months)
+ return EARLIER;
+ if (a.months > b.months)
+ return LATER;
+ if (a.milliseconds < b.milliseconds)
+ return EARLIER;
+ if (a.milliseconds > b.milliseconds)
+ return LATER;
+ return SAMETIME;
+}
+
+/*
+ * convert client times to server TimeStamps
+ */
+
+#define HALFMONTH ((unsigned long) 1<<31)
+TimeStamp
+ClientTimeToServerTime(CARD32 c)
+{
+ TimeStamp ts;
+ if (c == CurrentTime)
+ return currentTime;
+ ts.months = currentTime.months;
+ ts.milliseconds = c;
+ if (c > currentTime.milliseconds)
+ {
+ if (((unsigned long) c - currentTime.milliseconds) > HALFMONTH)
+ ts.months -= 1;
+ }
+ else if (c < currentTime.milliseconds)
+ {
+ if (((unsigned long)currentTime.milliseconds - c) > HALFMONTH)
+ ts.months += 1;
+ }
+ return ts;
+}
+
+/*
+ * ISO Latin-1 case conversion routine
+ *
+ * this routine always null-terminates the result, so
+ * beware of too-small buffers
+ */
+
+static unsigned char
+ISOLatin1ToLower (unsigned char source)
+{
+ unsigned char dest;
+ if ((source >= XK_A) && (source <= XK_Z))
+ dest = source + (XK_a - XK_A);
+ else if ((source >= XK_Agrave) && (source <= XK_Odiaeresis))
+ dest = source + (XK_agrave - XK_Agrave);
+ else if ((source >= XK_Ooblique) && (source <= XK_Thorn))
+ dest = source + (XK_oslash - XK_Ooblique);
+ else
+ dest = source;
+ return dest;
+}
+
+
+int
+CompareISOLatin1Lowered(unsigned char *s1, int s1len,
+ unsigned char *s2, int s2len)
+{
+ unsigned char c1, c2;
+
+ for (;;)
+ {
+ /* note -- compare against zero so that -1 ignores len */
+ c1 = s1len-- ? *s1++ : '\0';
+ c2 = s2len-- ? *s2++ : '\0';
+ if (!c1 ||
+ (c1 != c2 &&
+ (c1 = ISOLatin1ToLower (c1)) != (c2 = ISOLatin1ToLower (c2))))
+ break;
+ }
+ return (int) c1 - (int) c2;
+}
+
+/*
+ * dixLookupWindow and dixLookupDrawable:
+ * Look up the window/drawable taking into account the client doing the
+ * lookup, the type of drawable desired, and the type of access desired.
+ * Return Success with *pDraw set if the window/drawable exists and the client
+ * is allowed access, else return an error code with *pDraw set to NULL. The
+ * access mask values are defined in resource.h. The type mask values are
+ * defined in pixmap.h, with zero equivalent to M_DRAWABLE.
+ */
+int
+dixLookupDrawable(DrawablePtr *pDraw, XID id, ClientPtr client,
+ Mask type, Mask access)
+{
+ DrawablePtr pTmp;
+ int rc;
+
+ *pDraw = NULL;
+ client->errorValue = id;
+
+ if (id == INVALID)
+ return BadDrawable;
+
+ rc = dixLookupResourceByClass((pointer *)&pTmp, id, RC_DRAWABLE, client, access);
+
+ if (rc == BadValue)
+ return BadDrawable;
+ if (rc != Success)
+ return rc;
+ if (!((1 << pTmp->type) & (type ? type : M_DRAWABLE)))
+ return BadMatch;
+
+ *pDraw = pTmp;
+ return Success;
+}
+
+int
+dixLookupWindow(WindowPtr *pWin, XID id, ClientPtr client, Mask access)
+{
+ int rc;
+ rc = dixLookupDrawable((DrawablePtr*)pWin, id, client, M_WINDOW, access);
+ return (rc == BadDrawable) ? BadWindow : rc;
+}
+
+int
+dixLookupGC(GCPtr *pGC, XID id, ClientPtr client, Mask access)
+{
+ int rc;
+ rc = dixLookupResourceByType((pointer *)pGC, id, RT_GC, client, access);
+ return (rc == BadValue) ? BadGC : rc;
+}
+
+int
+dixLookupFontable(FontPtr *pFont, XID id, ClientPtr client, Mask access)
+{
+ int rc;
+ GC *pGC;
+ client->errorValue = id; /* EITHER font or gc */
+ rc = dixLookupResourceByType((pointer *) pFont, id, RT_FONT, client, access);
+ if (rc != BadValue)
+ return rc;
+ rc = dixLookupResourceByType((pointer *) &pGC, id, RT_GC, client, access);
+ if (rc == BadValue)
+ return BadFont;
+ if (rc == Success)
+ *pFont = pGC->font;
+ return rc;
+}
+
+int
+dixLookupClient(ClientPtr *pClient, XID rid, ClientPtr client, Mask access)
+{
+ pointer pRes;
+ int rc = BadValue, clientIndex = CLIENT_ID(rid);
+
+ if (!clientIndex || !clients[clientIndex] || (rid & SERVER_BIT))
+ goto bad;
+
+ rc = dixLookupResourceByClass(&pRes, rid, RC_ANY, client, DixGetAttrAccess);
+ if (rc != Success)
+ goto bad;
+
+ rc = XaceHook(XACE_CLIENT_ACCESS, client, clients[clientIndex], access);
+ if (rc != Success)
+ goto bad;
+
+ *pClient = clients[clientIndex];
+ return Success;
+bad:
+ if(client)
+ client->errorValue = rid;
+ *pClient = NULL;
+ return rc;
+}
+
+int
+AlterSaveSetForClient(ClientPtr client, WindowPtr pWin, unsigned mode,
+ Bool toRoot, Bool map)
+{
+ int numnow;
+ SaveSetElt *pTmp = NULL;
+ int j;
+
+ numnow = client->numSaved;
+ j = 0;
+ if (numnow)
+ {
+ pTmp = client->saveSet;
+ while ((j < numnow) && (SaveSetWindow(pTmp[j]) != (pointer)pWin))
+ j++;
+ }
+ if (mode == SetModeInsert)
+ {
+ if (j < numnow) /* duplicate */
+ return(Success);
+ numnow++;
+ pTmp = (SaveSetElt *)xrealloc(client->saveSet, sizeof(*pTmp) * numnow);
+ if (!pTmp)
+ return(BadAlloc);
+ client->saveSet = pTmp;
+ client->numSaved = numnow;
+ SaveSetAssignWindow(client->saveSet[numnow - 1], pWin);
+ SaveSetAssignToRoot(client->saveSet[numnow - 1], toRoot);
+ SaveSetAssignMap(client->saveSet[numnow - 1], map);
+ return(Success);
+ }
+ else if ((mode == SetModeDelete) && (j < numnow))
+ {
+ while (j < numnow-1)
+ {
+ pTmp[j] = pTmp[j+1];
+ j++;
+ }
+ numnow--;
+ if (numnow)
+ {
+ pTmp = (SaveSetElt *)xrealloc(client->saveSet, sizeof(*pTmp) * numnow);
+ if (pTmp)
+ client->saveSet = pTmp;
+ }
+ else
+ {
+ xfree(client->saveSet);
+ client->saveSet = (SaveSetElt *)NULL;
+ }
+ client->numSaved = numnow;
+ return(Success);
+ }
+ return(Success);
+}
+
+void
+DeleteWindowFromAnySaveSet(WindowPtr pWin)
+{
+ int i;
+ ClientPtr client;
+
+ for (i = 0; i< currentMaxClients; i++)
+ {
+ client = clients[i];
+ if (client && client->numSaved)
+ (void)AlterSaveSetForClient(client, pWin, SetModeDelete, FALSE, TRUE);
+ }
+}
+
+/* No-op Don't Do Anything : sometimes we need to be able to call a procedure
+ * that doesn't do anything. For example, on screen with only static
+ * colormaps, if someone calls install colormap, it's easier to have a dummy
+ * procedure to call than to check if there's a procedure
+ */
+void
+NoopDDA(void)
+{
+}
+
+typedef struct _BlockHandler {
+ BlockHandlerProcPtr BlockHandler;
+ WakeupHandlerProcPtr WakeupHandler;
+ pointer blockData;
+ Bool deleted;
+} BlockHandlerRec, *BlockHandlerPtr;
+
+static BlockHandlerPtr handlers;
+static int numHandlers;
+static int sizeHandlers;
+static Bool inHandler;
+static Bool handlerDeleted;
+
+/**
+ *
+ * \param pTimeout DIX doesn't want to know how OS represents time
+ * \param pReadMask nor how it represents the det of descriptors
+ */
+void
+BlockHandler(pointer pTimeout, pointer pReadmask)
+{
+ int i, j;
+
+ ++inHandler;
+ for (i = 0; i < screenInfo.numScreens; i++)
+ (* screenInfo.screens[i]->BlockHandler)(i,
+ screenInfo.screens[i]->blockData,
+ pTimeout, pReadmask);
+ for (i = 0; i < numHandlers; i++)
+ (*handlers[i].BlockHandler) (handlers[i].blockData,
+ pTimeout, pReadmask);
+ if (handlerDeleted)
+ {
+ for (i = 0; i < numHandlers;)
+ if (handlers[i].deleted)
+ {
+ for (j = i; j < numHandlers - 1; j++)
+ handlers[j] = handlers[j+1];
+ numHandlers--;
+ }
+ else
+ i++;
+ handlerDeleted = FALSE;
+ }
+ --inHandler;
+}
+
+/**
+ *
+ * \param result 32 bits of undefined result from the wait
+ * \param pReadmask the resulting descriptor mask
+ */
+void
+WakeupHandler(int result, pointer pReadmask)
+{
+ int i, j;
+
+ ++inHandler;
+ for (i = numHandlers - 1; i >= 0; i--)
+ (*handlers[i].WakeupHandler) (handlers[i].blockData,
+ result, pReadmask);
+ for (i = 0; i < screenInfo.numScreens; i++)
+ (* screenInfo.screens[i]->WakeupHandler)(i,
+ screenInfo.screens[i]->wakeupData,
+ result, pReadmask);
+ if (handlerDeleted)
+ {
+ for (i = 0; i < numHandlers;)
+ if (handlers[i].deleted)
+ {
+ for (j = i; j < numHandlers - 1; j++)
+ handlers[j] = handlers[j+1];
+ numHandlers--;
+ }
+ else
+ i++;
+ handlerDeleted = FALSE;
+ }
+ --inHandler;
+}
+
+/**
+ * Reentrant with BlockHandler and WakeupHandler, except wakeup won't
+ * get called until next time
+ */
+Bool
+RegisterBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler,
+ WakeupHandlerProcPtr wakeupHandler,
+ pointer blockData)
+{
+ BlockHandlerPtr new;
+
+ if (numHandlers >= sizeHandlers)
+ {
+ new = (BlockHandlerPtr) xrealloc (handlers, (numHandlers + 1) *
+ sizeof (BlockHandlerRec));
+ if (!new)
+ return FALSE;
+ handlers = new;
+ sizeHandlers = numHandlers + 1;
+ }
+ handlers[numHandlers].BlockHandler = blockHandler;
+ handlers[numHandlers].WakeupHandler = wakeupHandler;
+ handlers[numHandlers].blockData = blockData;
+ handlers[numHandlers].deleted = FALSE;
+ numHandlers = numHandlers + 1;
+ return TRUE;
+}
+
+void
+RemoveBlockAndWakeupHandlers (BlockHandlerProcPtr blockHandler,
+ WakeupHandlerProcPtr wakeupHandler,
+ pointer blockData)
+{
+ int i;
+
+ for (i = 0; i < numHandlers; i++)
+ if (handlers[i].BlockHandler == blockHandler &&
+ handlers[i].WakeupHandler == wakeupHandler &&
+ handlers[i].blockData == blockData)
+ {
+ if (inHandler)
+ {
+ handlerDeleted = TRUE;
+ handlers[i].deleted = TRUE;
+ }
+ else
+ {
+ for (; i < numHandlers - 1; i++)
+ handlers[i] = handlers[i+1];
+ numHandlers--;
+ }
+ break;
+ }
+}
+
+void
+InitBlockAndWakeupHandlers (void)
+{
+ xfree (handlers);
+ handlers = (BlockHandlerPtr) 0;
+ numHandlers = 0;
+ sizeHandlers = 0;
+}
+
+/*
+ * A general work queue. Perform some task before the server
+ * sleeps for input.
+ */
+
+WorkQueuePtr workQueue;
+static WorkQueuePtr *workQueueLast = &workQueue;
+
+void
+ProcessWorkQueue(void)
+{
+ WorkQueuePtr q, *p;
+
+ p = &workQueue;
+ /*
+ * Scan the work queue once, calling each function. Those
+ * which return TRUE are removed from the queue, otherwise
+ * they will be called again. This must be reentrant with
+ * QueueWorkProc.
+ */
+ while ((q = *p))
+ {
+ if ((*q->function) (q->client, q->closure))
+ {
+ /* remove q from the list */
+ *p = q->next; /* don't fetch until after func called */
+ xfree (q);
+ }
+ else
+ {
+ p = &q->next; /* don't fetch until after func called */
+ }
+ }
+ workQueueLast = p;
+}
+
+void
+ProcessWorkQueueZombies(void)
+{
+ WorkQueuePtr q, *p;
+
+ p = &workQueue;
+ while ((q = *p))
+ {
+ if (q->client && q->client->clientGone)
+ {
+ (void) (*q->function) (q->client, q->closure);
+ /* remove q from the list */
+ *p = q->next; /* don't fetch until after func called */
+ xfree (q);
+ }
+ else
+ {
+ p = &q->next; /* don't fetch until after func called */
+ }
+ }
+ workQueueLast = p;
+}
+
+Bool
+QueueWorkProc (
+ Bool (*function)(ClientPtr /* pClient */, pointer /* closure */),
+ ClientPtr client, pointer closure)
+{
+ WorkQueuePtr q;
+
+ q = xalloc (sizeof *q);
+ if (!q)
+ return FALSE;
+ q->function = function;
+ q->client = client;
+ q->closure = closure;
+ q->next = NULL;
+ *workQueueLast = q;
+ workQueueLast = &q->next;
+ return TRUE;
+}
+
+/*
+ * Manage a queue of sleeping clients, awakening them
+ * when requested, by using the OS functions IgnoreClient
+ * and AttendClient. Note that this *ignores* the troubles
+ * with request data interleaving itself with events, but
+ * we'll leave that until a later time.
+ */
+
+typedef struct _SleepQueue {
+ struct _SleepQueue *next;
+ ClientPtr client;
+ ClientSleepProcPtr function;
+ pointer closure;
+} SleepQueueRec, *SleepQueuePtr;
+
+static SleepQueuePtr sleepQueue = NULL;
+
+Bool
+ClientSleep (ClientPtr client, ClientSleepProcPtr function, pointer closure)
+{
+ SleepQueuePtr q;
+
+ q = xalloc (sizeof *q);
+ if (!q)
+ return FALSE;
+
+ IgnoreClient (client);
+ q->next = sleepQueue;
+ q->client = client;
+ q->function = function;
+ q->closure = closure;
+ sleepQueue = q;
+ return TRUE;
+}
+
+Bool
+ClientSignal (ClientPtr client)
+{
+ SleepQueuePtr q;
+
+ for (q = sleepQueue; q; q = q->next)
+ if (q->client == client)
+ {
+ return QueueWorkProc (q->function, q->client, q->closure);
+ }
+ return FALSE;
+}
+
+void
+ClientWakeup (ClientPtr client)
+{
+ SleepQueuePtr q, *prev;
+
+ prev = &sleepQueue;
+ while ( (q = *prev) )
+ {
+ if (q->client == client)
+ {
+ *prev = q->next;
+ xfree (q);
+ if (client->clientGone)
+ /* Oops -- new zombie cleanup code ensures this only
+ * happens from inside CloseDownClient; don't want to
+ * recurse here...
+ */
+ /* CloseDownClient(client) */;
+ else
+ AttendClient (client);
+ break;
+ }
+ prev = &q->next;
+ }
+}
+
+Bool
+ClientIsAsleep (ClientPtr client)
+{
+ SleepQueuePtr q;
+
+ for (q = sleepQueue; q; q = q->next)
+ if (q->client == client)
+ return TRUE;
+ return FALSE;
+}
+
+/*
+ * Generic Callback Manager
+ */
+
+/* ===== Private Procedures ===== */
+
+static int numCallbackListsToCleanup = 0;
+static CallbackListPtr **listsToCleanup = NULL;
+
+static Bool
+_AddCallback(
+ CallbackListPtr *pcbl,
+ CallbackProcPtr callback,
+ pointer data)
+{
+ CallbackPtr cbr;
+
+ cbr = xalloc(sizeof(CallbackRec));
+ if (!cbr)
+ return FALSE;
+ cbr->proc = callback;
+ cbr->data = data;
+ cbr->next = (*pcbl)->list;
+ cbr->deleted = FALSE;
+ (*pcbl)->list = cbr;
+ return TRUE;
+}
+
+static Bool
+_DeleteCallback(
+ CallbackListPtr *pcbl,
+ CallbackProcPtr callback,
+ pointer data)
+{
+ CallbackListPtr cbl = *pcbl;
+ CallbackPtr cbr, pcbr;
+
+ for (pcbr = NULL, cbr = cbl->list;
+ cbr != NULL;
+ pcbr = cbr, cbr = cbr->next)
+ {
+ if ((cbr->proc == callback) && (cbr->data == data))
+ break;
+ }
+ if (cbr != NULL)
+ {
+ if (cbl->inCallback)
+ {
+ ++(cbl->numDeleted);
+ cbr->deleted = TRUE;
+ }
+ else
+ {
+ if (pcbr == NULL)
+ cbl->list = cbr->next;
+ else
+ pcbr->next = cbr->next;
+ xfree(cbr);
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+
+static void
+_CallCallbacks(
+ CallbackListPtr *pcbl,
+ pointer call_data)
+{
+ CallbackListPtr cbl = *pcbl;
+ CallbackPtr cbr, pcbr;
+
+ ++(cbl->inCallback);
+ for (cbr = cbl->list; cbr != NULL; cbr = cbr->next)
+ {
+ (*(cbr->proc)) (pcbl, cbr->data, call_data);
+ }
+ --(cbl->inCallback);
+
+ if (cbl->inCallback) return;
+
+ /* Was the entire list marked for deletion? */
+
+ if (cbl->deleted)
+ {
+ DeleteCallbackList(pcbl);
+ return;
+ }
+
+ /* Were some individual callbacks on the list marked for deletion?
+ * If so, do the deletions.
+ */
+
+ if (cbl->numDeleted)
+ {
+ for (pcbr = NULL, cbr = cbl->list; (cbr != NULL) && cbl->numDeleted; )
+ {
+ if (cbr->deleted)
+ {
+ if (pcbr)
+ {
+ cbr = cbr->next;
+ xfree(pcbr->next);
+ pcbr->next = cbr;
+ } else
+ {
+ cbr = cbr->next;
+ xfree(cbl->list);
+ cbl->list = cbr;
+ }
+ cbl->numDeleted--;
+ }
+ else /* this one wasn't deleted */
+ {
+ pcbr = cbr;
+ cbr = cbr->next;
+ }
+ }
+ }
+}
+
+static void
+_DeleteCallbackList(
+ CallbackListPtr *pcbl)
+{
+ CallbackListPtr cbl = *pcbl;
+ CallbackPtr cbr, nextcbr;
+ int i;
+
+ if (cbl->inCallback)
+ {
+ cbl->deleted = TRUE;
+ return;
+ }
+
+ for (i = 0; i < numCallbackListsToCleanup; i++)
+ {
+ if (listsToCleanup[i] == pcbl)
+ {
+ listsToCleanup[i] = NULL;
+ break;
+ }
+ }
+
+ for (cbr = cbl->list; cbr != NULL; cbr = nextcbr)
+ {
+ nextcbr = cbr->next;
+ xfree(cbr);
+ }
+ xfree(cbl);
+ *pcbl = NULL;
+}
+
+static Bool
+CreateCallbackList(CallbackListPtr *pcbl)
+{
+ CallbackListPtr cbl;
+ int i;
+
+ if (!pcbl) return FALSE;
+ cbl = xalloc(sizeof(CallbackListRec));
+ if (!cbl) return FALSE;
+ cbl->inCallback = 0;
+ cbl->deleted = FALSE;
+ cbl->numDeleted = 0;
+ cbl->list = NULL;
+ *pcbl = cbl;
+
+ for (i = 0; i < numCallbackListsToCleanup; i++)
+ {
+ if (!listsToCleanup[i])
+ {
+ listsToCleanup[i] = pcbl;
+ return TRUE;
+ }
+ }
+
+ listsToCleanup = (CallbackListPtr **)xnfrealloc(listsToCleanup,
+ sizeof(CallbackListPtr *) * (numCallbackListsToCleanup+1));
+ listsToCleanup[numCallbackListsToCleanup] = pcbl;
+ numCallbackListsToCleanup++;
+ return TRUE;
+}
+
+/* ===== Public Procedures ===== */
+
+Bool
+AddCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data)
+{
+ if (!pcbl) return FALSE;
+ if (!*pcbl)
+ { /* list hasn't been created yet; go create it */
+ if (!CreateCallbackList(pcbl))
+ return FALSE;
+ }
+ return _AddCallback(pcbl, callback, data);
+}
+
+Bool
+DeleteCallback(CallbackListPtr *pcbl, CallbackProcPtr callback, pointer data)
+{
+ if (!pcbl || !*pcbl) return FALSE;
+ return _DeleteCallback(pcbl, callback, data);
+}
+
+void
+CallCallbacks(CallbackListPtr *pcbl, pointer call_data)
+{
+ if (!pcbl || !*pcbl) return;
+ _CallCallbacks(pcbl, call_data);
+}
+
+void
+DeleteCallbackList(CallbackListPtr *pcbl)
+{
+ if (!pcbl || !*pcbl) return;
+ _DeleteCallbackList(pcbl);
+}
+
+void
+InitCallbackManager(void)
+{
+ int i;
+
+ for (i = 0; i < numCallbackListsToCleanup; i++)
+ {
+ DeleteCallbackList(listsToCleanup[i]);
+ }
+ if (listsToCleanup) xfree(listsToCleanup);
+
+ numCallbackListsToCleanup = 0;
+ listsToCleanup = NULL;
+}
diff --git a/xorg-server/glx/xfont.c b/xorg-server/glx/xfont.c
index 2af5996f3..a2573d4dd 100644
--- a/xorg-server/glx/xfont.c
+++ b/xorg-server/glx/xfont.c
@@ -1,204 +1,193 @@
-/*
- * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
- * Copyright (C) 1991-2000 Silicon Graphics, 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, 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 including the dates of first publication and
- * either this permission notice or a reference to
- * http://oss.sgi.com/projects/FreeB/
- * 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
- * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc.
- * shall not be used in advertising or otherwise to promote the sale, use or
- * other dealings in this Software without prior written authorization from
- * Silicon Graphics, Inc.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#else
-
-#include "glheader.h"
-
-#endif
-
-#include "glxserver.h"
-#include "glxutil.h"
-#include "unpack.h"
-#include "g_disptab.h"
-#include "glapitable.h"
-#include "glapi.h"
-#include "glthread.h"
-#include "dispatch.h"
-#include "indirect_dispatch.h"
-#include <GL/gl.h>
-#include <pixmapstr.h>
-#include <windowstr.h>
-#include <dixfontstr.h>
-
-extern XID clientErrorValue; /* imported kludge from dix layer */
-
-/*
-** Make a single GL bitmap from a single X glyph
-*/
-static int __glXMakeBitmapFromGlyph(FontPtr font, CharInfoPtr pci)
-{
- int i, j;
- int widthPadded; /* width of glyph in bytes, as padded by X */
- int allocBytes; /* bytes to allocate to store bitmap */
- int w; /* width of glyph in bits */
- int h; /* height of glyph */
- register unsigned char *pglyph;
- register unsigned char *p;
- unsigned char *allocbuf;
-#define __GL_CHAR_BUF_SIZE 2048
- unsigned char buf[__GL_CHAR_BUF_SIZE];
-
- w = GLYPHWIDTHPIXELS(pci);
- h = GLYPHHEIGHTPIXELS(pci);
- widthPadded = GLYPHWIDTHBYTESPADDED(pci);
-
- /*
- ** Use the local buf if possible, otherwise malloc.
- */
- allocBytes = widthPadded * h;
- if (allocBytes <= __GL_CHAR_BUF_SIZE) {
- p = buf;
- allocbuf = 0;
- } else {
- p = (unsigned char *) xalloc(allocBytes);
- if (!p)
- return BadAlloc;
- allocbuf = p;
- }
-
- /*
- ** We have to reverse the picture, top to bottom
- */
-
- pglyph = FONTGLYPHBITS(FONTGLYPHS(font), pci) + (h-1)*widthPadded;
- for (j=0; j < h; j++) {
- for (i=0; i < widthPadded; i++) {
- p[i] = pglyph[i];
- }
- pglyph -= widthPadded;
- p += widthPadded;
- }
- CALL_Bitmap( GET_DISPATCH(), (w, h, -pci->metrics.leftSideBearing,
- pci->metrics.descent,
- pci->metrics.characterWidth, 0,
- allocbuf ? allocbuf : buf) );
-
- if (allocbuf) {
- xfree(allocbuf);
- }
- return Success;
-#undef __GL_CHAR_BUF_SIZE
-}
-
-/*
-** Create a GL bitmap for each character in the X font. The bitmap is stored
-** in a display list.
-*/
-
-static int
-MakeBitmapsFromFont(FontPtr pFont, int first, int count, int list_base)
-{
- unsigned long i, nglyphs;
- CARD8 chs[2]; /* the font index we are going after */
- CharInfoPtr pci;
- int rv; /* return value */
- int encoding = (FONTLASTROW(pFont) == 0) ? Linear16Bit : TwoD16Bit;
-
- CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SWAP_BYTES, FALSE) );
- CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_LSB_FIRST, BITMAP_BIT_ORDER == LSBFirst) );
- CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH, 0) );
- CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, 0) );
- CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, 0) );
- CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ALIGNMENT, GLYPHPADBYTES) );
- for (i=0; i < count; i++) {
- chs[0] = (first + i) >> 8; /* high byte is first byte */
- chs[1] = first + i;
-
- (*pFont->get_glyphs)(pFont, 1, chs, (FontEncoding)encoding,
- &nglyphs, &pci);
-
- /*
- ** Define a display list containing just a glBitmap() call.
- */
- CALL_NewList( GET_DISPATCH(), (list_base + i, GL_COMPILE) );
- if (nglyphs ) {
- rv = __glXMakeBitmapFromGlyph(pFont, pci);
- if (rv) {
- return rv;
- }
- }
- CALL_EndList( GET_DISPATCH(), () );
- }
- return Success;
-}
-
-/************************************************************************/
-
-int __glXDisp_UseXFont(__GLXclientState *cl, GLbyte *pc)
-{
- ClientPtr client = cl->client;
- xGLXUseXFontReq *req;
- FontPtr pFont;
- GC *pGC;
- GLuint currentListIndex;
- __GLXcontext *cx;
- int error;
-
- req = (xGLXUseXFontReq *) pc;
- cx = __glXForceCurrent(cl, req->contextTag, &error);
- if (!cx) {
- return error;
- }
-
- CALL_GetIntegerv( GET_DISPATCH(), (GL_LIST_INDEX, (GLint*) &currentListIndex) );
- if (currentListIndex != 0) {
- /*
- ** A display list is currently being made. It is an error
- ** to try to make a font during another lists construction.
- */
- client->errorValue = cx->id;
- return __glXError(GLXBadContextState);
- }
-
- /*
- ** Font can actually be either the ID of a font or the ID of a GC
- ** containing a font.
- */
-
- error = dixLookupResourceByType((pointer *)&pFont,
- req->font, RT_FONT,
- client, DixReadAccess);
- if (error != Success) {
- error = dixLookupResourceByType((pointer *)&pGC,
- req->font, RT_GC,
- client, DixReadAccess);
- if (error != Success) {
- client->errorValue = req->font;
- return error == BadGC ? BadFont : error;
- }
- pFont = pGC->font;
- }
-
- return MakeBitmapsFromFont(pFont, req->first, req->count,
- req->listBase);
-}
+/*
+ * SGI FREE SOFTWARE LICENSE B (Version 2.0, Sept. 18, 2008)
+ * Copyright (C) 1991-2000 Silicon Graphics, 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, 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 including the dates of first publication and
+ * either this permission notice or a reference to
+ * http://oss.sgi.com/projects/FreeB/
+ * 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
+ * SILICON GRAPHICS, INC. 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 Silicon Graphics, Inc.
+ * shall not be used in advertising or otherwise to promote the sale, use or
+ * other dealings in this Software without prior written authorization from
+ * Silicon Graphics, Inc.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#else
+
+#include "glheader.h"
+
+#endif
+
+#include "glxserver.h"
+#include "glxutil.h"
+#include "unpack.h"
+#include "g_disptab.h"
+#include "glapitable.h"
+#include "glapi.h"
+#include "glthread.h"
+#include "dispatch.h"
+#include "indirect_dispatch.h"
+#include <GL/gl.h>
+#include <pixmapstr.h>
+#include <windowstr.h>
+#include <dixfontstr.h>
+
+extern XID clientErrorValue; /* imported kludge from dix layer */
+
+/*
+** Make a single GL bitmap from a single X glyph
+*/
+static int __glXMakeBitmapFromGlyph(FontPtr font, CharInfoPtr pci)
+{
+ int i, j;
+ int widthPadded; /* width of glyph in bytes, as padded by X */
+ int allocBytes; /* bytes to allocate to store bitmap */
+ int w; /* width of glyph in bits */
+ int h; /* height of glyph */
+ register unsigned char *pglyph;
+ register unsigned char *p;
+ unsigned char *allocbuf;
+#define __GL_CHAR_BUF_SIZE 2048
+ unsigned char buf[__GL_CHAR_BUF_SIZE];
+
+ w = GLYPHWIDTHPIXELS(pci);
+ h = GLYPHHEIGHTPIXELS(pci);
+ widthPadded = GLYPHWIDTHBYTESPADDED(pci);
+
+ /*
+ ** Use the local buf if possible, otherwise malloc.
+ */
+ allocBytes = widthPadded * h;
+ if (allocBytes <= __GL_CHAR_BUF_SIZE) {
+ p = buf;
+ allocbuf = 0;
+ } else {
+ p = (unsigned char *) xalloc(allocBytes);
+ if (!p)
+ return BadAlloc;
+ allocbuf = p;
+ }
+
+ /*
+ ** We have to reverse the picture, top to bottom
+ */
+
+ pglyph = FONTGLYPHBITS(FONTGLYPHS(font), pci) + (h-1)*widthPadded;
+ for (j=0; j < h; j++) {
+ for (i=0; i < widthPadded; i++) {
+ p[i] = pglyph[i];
+ }
+ pglyph -= widthPadded;
+ p += widthPadded;
+ }
+ CALL_Bitmap( GET_DISPATCH(), (w, h, -pci->metrics.leftSideBearing,
+ pci->metrics.descent,
+ pci->metrics.characterWidth, 0,
+ allocbuf ? allocbuf : buf) );
+
+ if (allocbuf) {
+ xfree(allocbuf);
+ }
+ return Success;
+#undef __GL_CHAR_BUF_SIZE
+}
+
+/*
+** Create a GL bitmap for each character in the X font. The bitmap is stored
+** in a display list.
+*/
+
+static int
+MakeBitmapsFromFont(FontPtr pFont, int first, int count, int list_base)
+{
+ unsigned long i, nglyphs;
+ CARD8 chs[2]; /* the font index we are going after */
+ CharInfoPtr pci;
+ int rv; /* return value */
+ int encoding = (FONTLASTROW(pFont) == 0) ? Linear16Bit : TwoD16Bit;
+
+ CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SWAP_BYTES, FALSE) );
+ CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_LSB_FIRST, BITMAP_BIT_ORDER == LSBFirst) );
+ CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ROW_LENGTH, 0) );
+ CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_ROWS, 0) );
+ CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_SKIP_PIXELS, 0) );
+ CALL_PixelStorei( GET_DISPATCH(), (GL_UNPACK_ALIGNMENT, GLYPHPADBYTES) );
+ for (i=0; i < count; i++) {
+ chs[0] = (first + i) >> 8; /* high byte is first byte */
+ chs[1] = first + i;
+
+ (*pFont->get_glyphs)(pFont, 1, chs, (FontEncoding)encoding,
+ &nglyphs, &pci);
+
+ /*
+ ** Define a display list containing just a glBitmap() call.
+ */
+ CALL_NewList( GET_DISPATCH(), (list_base + i, GL_COMPILE) );
+ if (nglyphs ) {
+ rv = __glXMakeBitmapFromGlyph(pFont, pci);
+ if (rv) {
+ return rv;
+ }
+ }
+ CALL_EndList( GET_DISPATCH(), () );
+ }
+ return Success;
+}
+
+/************************************************************************/
+
+int __glXDisp_UseXFont(__GLXclientState *cl, GLbyte *pc)
+{
+ ClientPtr client = cl->client;
+ xGLXUseXFontReq *req;
+ FontPtr pFont;
+ GLuint currentListIndex;
+ __GLXcontext *cx;
+ int error;
+
+ req = (xGLXUseXFontReq *) pc;
+ cx = __glXForceCurrent(cl, req->contextTag, &error);
+ if (!cx) {
+ return error;
+ }
+
+ CALL_GetIntegerv( GET_DISPATCH(), (GL_LIST_INDEX, (GLint*) &currentListIndex) );
+ if (currentListIndex != 0) {
+ /*
+ ** A display list is currently being made. It is an error
+ ** to try to make a font during another lists construction.
+ */
+ client->errorValue = cx->id;
+ return __glXError(GLXBadContextState);
+ }
+
+ /*
+ ** Font can actually be either the ID of a font or the ID of a GC
+ ** containing a font.
+ */
+
+ error = dixLookupFontable(&pFont, req->font, client, DixReadAccess);
+ if (error != Success)
+ return error;
+
+ return MakeBitmapsFromFont(pFont, req->first, req->count,
+ req->listBase);
+}
diff --git a/xorg-server/hw/dmx/dmxpict.c b/xorg-server/hw/dmx/dmxpict.c
index 072e3a61a..efb2e41c9 100644
--- a/xorg-server/hw/dmx/dmxpict.c
+++ b/xorg-server/hw/dmx/dmxpict.c
@@ -1,1316 +1,1314 @@
-/*
- * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
- *
- * 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 on 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
- * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
- * 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:
- * Kevin E. Martin <kem@redhat.com>
- *
- */
-
-/** \file
- * Provide support for the RENDER extension (version 0.8).
- */
-
-#ifdef HAVE_DMX_CONFIG_H
-#include <dmx-config.h>
-#endif
-
-#include "dmx.h"
-#include "dmxsync.h"
-#include "dmxpict.h"
-#include "dmxwindow.h"
-#include "dmxpixmap.h"
-
-#include "fb.h"
-#include "pixmapstr.h"
-#include "dixstruct.h"
-
-#include <X11/extensions/render.h>
-#include <X11/extensions/renderproto.h>
-#include <X11/extensions/Xfixes.h>
-#include "picture.h"
-#include "picturestr.h"
-#include "mipict.h"
-#include "fbpict.h"
-
-
-extern int RenderErrBase;
-extern int (*ProcRenderVector[RenderNumberRequests])(ClientPtr);
-
-static int (*dmxSaveRenderVector[RenderNumberRequests])(ClientPtr);
-
-
-static int dmxProcRenderCreateGlyphSet(ClientPtr client);
-static int dmxProcRenderFreeGlyphSet(ClientPtr client);
-static int dmxProcRenderAddGlyphs(ClientPtr client);
-static int dmxProcRenderFreeGlyphs(ClientPtr client);
-static int dmxProcRenderCompositeGlyphs(ClientPtr client);
-static int dmxProcRenderSetPictureTransform(ClientPtr client);
-static int dmxProcRenderSetPictureFilter(ClientPtr client);
-#if 0
-/* FIXME: Not (yet) supported */
-static int dmxProcRenderCreateCursor(ClientPtr client);
-static int dmxProcRenderCreateAnimCursor(ClientPtr client);
-#endif
-
-/** Catch errors that might occur when allocating Glyph Sets. Errors
- * are saved in dmxGlyphLastError for later handling. */
-static int dmxGlyphLastError;
-static int dmxGlyphErrorHandler(Display *dpy, XErrorEvent *ev)
-{
- dmxGlyphLastError = ev->error_code;
- return 0;
-}
-
-
-/** Initialize the Proc Vector for the RENDER extension. The functions
- * here cannot be handled by the mi layer RENDER hooks either because
- * the required information is no longer available when it reaches the
- * mi layer or no mi layer hooks exist. This function is called from
- * InitOutput() since it should be initialized only once per server
- * generation. */
-void dmxInitRender(void)
-{
- int i;
-
- for (i = 0; i < RenderNumberRequests; i++)
- dmxSaveRenderVector[i] = ProcRenderVector[i];
-
- ProcRenderVector[X_RenderCreateGlyphSet]
- = dmxProcRenderCreateGlyphSet;
- ProcRenderVector[X_RenderFreeGlyphSet]
- = dmxProcRenderFreeGlyphSet;
- ProcRenderVector[X_RenderAddGlyphs]
- = dmxProcRenderAddGlyphs;
- ProcRenderVector[X_RenderFreeGlyphs]
- = dmxProcRenderFreeGlyphs;
- ProcRenderVector[X_RenderCompositeGlyphs8]
- = dmxProcRenderCompositeGlyphs;
- ProcRenderVector[X_RenderCompositeGlyphs16]
- = dmxProcRenderCompositeGlyphs;
- ProcRenderVector[X_RenderCompositeGlyphs32]
- = dmxProcRenderCompositeGlyphs;
- ProcRenderVector[X_RenderSetPictureTransform]
- = dmxProcRenderSetPictureTransform;
- ProcRenderVector[X_RenderSetPictureFilter]
- = dmxProcRenderSetPictureFilter;
-}
-
-/** Reset the Proc Vector for the RENDER extension back to the original
- * functions. This function is called from dmxCloseScreen() during the
- * server reset (only for screen #0). */
-void dmxResetRender(void)
-{
- int i;
-
- for (i = 0; i < RenderNumberRequests; i++)
- ProcRenderVector[i] = dmxSaveRenderVector[i];
-}
-
-/** Initialize the RENDER extension, allocate the picture privates and
- * wrap mi function hooks. If the shadow frame buffer is used, then
- * call the appropriate fb initialization function. */
-Bool dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
-{
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps;
-
- /* The shadow framebuffer only relies on FB to be initialized */
- if (dmxShadowFB) return fbPictureInit(pScreen, formats, nformats);
-
- if (!miPictureInit(pScreen, formats, nformats))
- return FALSE;
-
- if (!dixRequestPrivate(dmxPictPrivateKey, sizeof(dmxPictPrivRec)))
- return FALSE;
-
- ps = GetPictureScreen(pScreen);
-
- DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
- DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
-
- DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
- DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
-
- DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
- DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
-
- DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
- DMX_WRAP(Glyphs, dmxGlyphs, dmxScreen, ps);
- DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
-
- DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
- DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
- DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps);
- DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps);
-
- return TRUE;
-}
-
-
-/** Find the appropriate format on the requested screen given the
- * internal format requested. The list of formats is searched
- * sequentially as the XRenderFindFormat() function does not always
- * find the appropriate format when a specific format is requested. */
-static XRenderPictFormat *dmxFindFormat(DMXScreenInfo *dmxScreen,
- PictFormatPtr pFmt)
-{
- XRenderPictFormat *pFormat = NULL;
- int i = 0;
-
- if (!pFmt || !dmxScreen->beDisplay) return pFormat;
-
- while (1) {
- pFormat = XRenderFindFormat(dmxScreen->beDisplay, 0, 0, i++);
- if (!pFormat) break;
-
- if (pFormat->type != pFmt->type) continue;
- if (pFormat->depth != pFmt->depth) continue;
- if (pFormat->direct.red != pFmt->direct.red) continue;
- if (pFormat->direct.redMask != pFmt->direct.redMask) continue;
- if (pFormat->direct.green != pFmt->direct.green) continue;
- if (pFormat->direct.greenMask != pFmt->direct.greenMask) continue;
- if (pFormat->direct.blue != pFmt->direct.blue) continue;
- if (pFormat->direct.blueMask != pFmt->direct.blueMask) continue;
- if (pFormat->direct.alpha != pFmt->direct.alpha) continue;
- if (pFormat->direct.alphaMask != pFmt->direct.alphaMask) continue;
-
- /* We have a match! */
- break;
- }
-
- return pFormat;
-}
-
-/** Free \a glyphSet on back-end screen number \a idx. */
-Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet)
-{
- dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
- int idx = pScreen->myNum;
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
-
- if (glyphPriv->glyphSets[idx]) {
- XRenderFreeGlyphSet(dmxScreen->beDisplay, glyphPriv->glyphSets[idx]);
- glyphPriv->glyphSets[idx] = (GlyphSet)0;
- return TRUE;
- }
-
- return FALSE;
-}
-
-/** Create \a glyphSet on the backend screen number \a idx. */
-int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet)
-{
- XRenderPictFormat *pFormat;
- DMXScreenInfo *dmxScreen = &dmxScreens[idx];
- dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
- PictFormatPtr pFmt = glyphSet->format;
- int (*oldErrorHandler)(Display *, XErrorEvent *);
-
- pFormat = dmxFindFormat(dmxScreen, pFmt);
- if (!pFormat) {
- return BadMatch;
- }
-
- dmxGlyphLastError = 0;
- oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler);
-
- /* Catch when this fails */
- glyphPriv->glyphSets[idx]
- = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat);
-
- XSetErrorHandler(oldErrorHandler);
-
- if (dmxGlyphLastError) {
- return dmxGlyphLastError;
- }
-
- return Success;
-}
-
-/** Create a Glyph Set on each screen. Save the glyphset ID from each
- * screen in the Glyph Set's private structure. Fail if the format
- * requested is not available or if the Glyph Set cannot be created on
- * the screen. */
-static int dmxProcRenderCreateGlyphSet(ClientPtr client)
-{
- int ret;
- REQUEST(xRenderCreateGlyphSetReq);
-
- ret = dmxSaveRenderVector[stuff->renderReqType](client);
-
- if (ret == Success) {
- GlyphSetPtr glyphSet;
- dmxGlyphPrivPtr glyphPriv;
- int i;
-
- /* Look up glyphSet that was just created ???? */
- /* Store glyphsets from backends in glyphSet->devPrivate ????? */
- /* Make sure we handle all errors here!! */
-
- glyphSet = SecurityLookupIDByType(client, stuff->gsid, GlyphSetType,
- DixDestroyAccess);
- glyphPriv = xalloc(sizeof(dmxGlyphPrivRec));
- if (!glyphPriv) return BadAlloc;
- glyphPriv->glyphSets = NULL;
- MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc);
- DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv);
-
- for (i = 0; i < dmxNumScreens; i++) {
- DMXScreenInfo *dmxScreen = &dmxScreens[i];
- int beret;
-
- if (!dmxScreen->beDisplay) {
- glyphPriv->glyphSets[i] = 0;
- continue;
- }
-
- if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) {
- int j;
-
- /* Free the glyph sets we've allocated thus far */
- for (j = 0; j < i; j++)
- dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet);
-
- /* Free the resource created by render */
- FreeResource(stuff->gsid, RT_NONE);
-
- return beret;
- }
- }
- }
-
- return ret;
-}
-
-/** Free the previously allocated Glyph Sets for each screen. */
-static int dmxProcRenderFreeGlyphSet(ClientPtr client)
-{
- GlyphSetPtr glyphSet;
- REQUEST(xRenderFreeGlyphSetReq);
-
- REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
- glyphSet = SecurityLookupIDByType(client, stuff->glyphset, GlyphSetType,
- DixDestroyAccess);
-
- if (glyphSet && glyphSet->refcnt == 1) {
- dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
- int i;
-
- for (i = 0; i < dmxNumScreens; i++) {
- DMXScreenInfo *dmxScreen = &dmxScreens[i];
-
- if (dmxScreen->beDisplay) {
- if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet))
- dmxSync(dmxScreen, FALSE);
- }
- }
-
- MAXSCREENSFREE(glyphPriv->glyphSets);
- xfree(glyphPriv);
- DMX_SET_GLYPH_PRIV(glyphSet, NULL);
- }
-
- return dmxSaveRenderVector[stuff->renderReqType](client);
-}
-
-/** Add glyphs to the Glyph Set on each screen. */
-static int dmxProcRenderAddGlyphs(ClientPtr client)
-{
- int ret;
- REQUEST(xRenderAddGlyphsReq);
-
- ret = dmxSaveRenderVector[stuff->renderReqType](client);
-
- if (ret == Success) {
- GlyphSetPtr glyphSet;
- dmxGlyphPrivPtr glyphPriv;
- int i;
- int nglyphs;
- CARD32 *gids;
- Glyph *gidsCopy;
- xGlyphInfo *gi;
- CARD8 *bits;
- int nbytes;
-
- glyphSet = SecurityLookupIDByType(client, stuff->glyphset,
- GlyphSetType, DixReadAccess);
- glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
-
- nglyphs = stuff->nglyphs;
- gids = (CARD32 *)(stuff + 1);
- gi = (xGlyphInfo *)(gids + nglyphs);
- bits = (CARD8 *)(gi + nglyphs);
- nbytes = ((stuff->length << 2) -
- sizeof(xRenderAddGlyphsReq) -
- (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs);
-
- gidsCopy = xalloc(sizeof(*gidsCopy) * nglyphs);
- for (i = 0; i < nglyphs; i++) gidsCopy[i] = gids[i];
-
- /* FIXME: Will this ever fail? */
- for (i = 0; i < dmxNumScreens; i++) {
- DMXScreenInfo *dmxScreen = &dmxScreens[i];
-
- if (dmxScreen->beDisplay) {
- XRenderAddGlyphs(dmxScreen->beDisplay,
- glyphPriv->glyphSets[i],
- gidsCopy,
- (XGlyphInfo *)gi,
- nglyphs,
- (char *)bits,
- nbytes);
- dmxSync(dmxScreen, FALSE);
- }
- }
- xfree(gidsCopy);
- }
-
- return ret;
-}
-
-/** Free glyphs from the Glyph Set for each screen. */
-static int dmxProcRenderFreeGlyphs(ClientPtr client)
-{
- GlyphSetPtr glyphSet;
- REQUEST(xRenderFreeGlyphsReq);
-
- REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
- glyphSet = SecurityLookupIDByType(client, stuff->glyphset, GlyphSetType,
- DixWriteAccess);
-
- if (glyphSet) {
- dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
- int i;
- int nglyphs;
- Glyph *gids;
-
- nglyphs = ((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq)) >> 2;
- if (nglyphs) {
- gids = xalloc(sizeof(*gids) * nglyphs);
- for (i = 0; i < nglyphs; i++)
- gids[i] = ((CARD32 *)(stuff + 1))[i];
-
- for (i = 0; i < dmxNumScreens; i++) {
- DMXScreenInfo *dmxScreen = &dmxScreens[i];
-
- if (dmxScreen->beDisplay) {
- XRenderFreeGlyphs(dmxScreen->beDisplay,
- glyphPriv->glyphSets[i], gids, nglyphs);
- dmxSync(dmxScreen, FALSE);
- }
- }
- xfree(gids);
- }
- }
-
- return dmxSaveRenderVector[stuff->renderReqType](client);
-}
-
-/** Composite glyphs on each screen into the requested picture. If
- * either the src or dest picture has not been allocated due to lazy
- * window creation, this request will gracefully return. */
-static int dmxProcRenderCompositeGlyphs(ClientPtr client)
-{
- int ret;
- REQUEST(xRenderCompositeGlyphsReq);
-
- ret = dmxSaveRenderVector[stuff->renderReqType](client);
-
- /* For the following to work with PanoramiX, it assumes that Render
- * wraps the ProcRenderVector after dmxRenderInit has been called.
- */
- if (ret == Success) {
- PicturePtr pSrc;
- dmxPictPrivPtr pSrcPriv;
- PicturePtr pDst;
- dmxPictPrivPtr pDstPriv;
- PictFormatPtr pFmt;
- XRenderPictFormat *pFormat;
- int size;
-
- int scrnNum;
- DMXScreenInfo *dmxScreen;
-
- CARD8 *buffer;
- CARD8 *end;
- int space;
-
- int nglyph;
- char *glyphs;
- char *curGlyph;
-
- xGlyphElt *elt;
- int nelt;
- XGlyphElt8 *elts;
- XGlyphElt8 *curElt;
-
- GlyphSetPtr glyphSet;
- dmxGlyphPrivPtr glyphPriv;
-
- pSrc = SecurityLookupIDByType(client, stuff->src, PictureType,
- DixReadAccess);
- pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
- if (!pSrcPriv->pict)
- return ret;
-
- pDst = SecurityLookupIDByType(client, stuff->dst, PictureType,
- DixWriteAccess);
- pDstPriv = DMX_GET_PICT_PRIV(pDst);
- if (!pDstPriv->pict)
- return ret;
-
- scrnNum = pDst->pDrawable->pScreen->myNum;
- dmxScreen = &dmxScreens[scrnNum];
-
- /* Note: If the back-end display has been detached, then it
- * should not be possible to reach here since the pSrcPriv->pict
- * and pDstPriv->pict will have already been set to 0.
- */
- if (!dmxScreen->beDisplay)
- return ret;
-
- if (stuff->maskFormat)
- pFmt = SecurityLookupIDByType(client, stuff->maskFormat,
- PictFormatType, DixReadAccess);
- else
- pFmt = NULL;
-
- pFormat = dmxFindFormat(dmxScreen, pFmt);
-
- switch (stuff->renderReqType) {
- case X_RenderCompositeGlyphs8: size = sizeof(CARD8); break;
- case X_RenderCompositeGlyphs16: size = sizeof(CARD16); break;
- case X_RenderCompositeGlyphs32: size = sizeof(CARD32); break;
- default: return BadPictOp; /* Can't happen */
- }
-
- buffer = (CARD8 *)(stuff + 1);
- end = (CARD8 *)stuff + (stuff->length << 2);
- nelt = 0;
- nglyph = 0;
- while (buffer + sizeof(xGlyphElt) < end) {
- elt = (xGlyphElt *)buffer;
- buffer += sizeof(xGlyphElt);
-
- if (elt->len == 0xff) {
- buffer += 4;
- } else {
- nelt++;
- nglyph += elt->len;
- space = size * elt->len;
- if (space & 3) space += 4 - (space & 3);
- buffer += space;
- }
- }
-
- /* The following only works for Render version > 0.2 */
-
- /* All of the XGlyphElt* structure sizes are identical */
- elts = xalloc(nelt * sizeof(XGlyphElt8));
- if (!elts)
- return BadAlloc;
-
- glyphs = xalloc(nglyph * size);
- if (!glyphs) {
- xfree(elts);
- return BadAlloc;
- }
-
- buffer = (CARD8 *)(stuff + 1);
- end = (CARD8 *)stuff + (stuff->length << 2);
- curGlyph = glyphs;
- curElt = elts;
-
- glyphSet = SecurityLookupIDByType(client, stuff->glyphset,
- GlyphSetType, DixReadAccess);
- glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
-
- while (buffer + sizeof(xGlyphElt) < end) {
- elt = (xGlyphElt *)buffer;
- buffer += sizeof(xGlyphElt);
-
- if (elt->len == 0xff) {
- glyphSet = SecurityLookupIDByType(client,
- *((CARD32 *)buffer),
- GlyphSetType,
- DixReadAccess);
- glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
- buffer += 4;
- } else {
- curElt->glyphset = glyphPriv->glyphSets[scrnNum];
- curElt->xOff = elt->deltax;
- curElt->yOff = elt->deltay;
- curElt->nchars = elt->len;
- curElt->chars = curGlyph;
-
- memcpy(curGlyph, buffer, size*elt->len);
- curGlyph += size * elt->len;
-
- curElt++;
-
- space = size * elt->len;
- if (space & 3) space += 4 - (space & 3);
- buffer += space;
- }
- }
-
- switch (stuff->renderReqType) {
- case X_RenderCompositeGlyphs8:
- XRenderCompositeText8(dmxScreen->beDisplay, stuff->op,
- pSrcPriv->pict, pDstPriv->pict,
- pFormat,
- stuff->xSrc, stuff->ySrc,
- 0, 0, elts, nelt);
- break;
- case X_RenderCompositeGlyphs16:
- XRenderCompositeText16(dmxScreen->beDisplay, stuff->op,
- pSrcPriv->pict, pDstPriv->pict,
- pFormat,
- stuff->xSrc, stuff->ySrc,
- 0, 0, (XGlyphElt16 *)elts, nelt);
- break;
- case X_RenderCompositeGlyphs32:
- XRenderCompositeText32(dmxScreen->beDisplay, stuff->op,
- pSrcPriv->pict, pDstPriv->pict,
- pFormat,
- stuff->xSrc, stuff->ySrc,
- 0, 0, (XGlyphElt32 *)elts, nelt);
- break;
- }
-
- dmxSync(dmxScreen, FALSE);
-
- xfree(elts);
- xfree(glyphs);
- }
-
- return ret;
-}
-
-/** Set the picture transform on each screen. */
-static int dmxProcRenderSetPictureTransform(ClientPtr client)
-{
- DMXScreenInfo *dmxScreen;
- PicturePtr pPicture;
- dmxPictPrivPtr pPictPriv;
- XTransform xform;
- REQUEST(xRenderSetPictureTransformReq);
-
- REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
- VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess,
- RenderErrBase + BadPicture);
-
- /* For the following to work with PanoramiX, it assumes that Render
- * wraps the ProcRenderVector after dmxRenderInit has been called.
- */
- dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
- pPictPriv = DMX_GET_PICT_PRIV(pPicture);
-
- if (pPictPriv->pict) {
- xform.matrix[0][0] = stuff->transform.matrix11;
- xform.matrix[0][1] = stuff->transform.matrix12;
- xform.matrix[0][2] = stuff->transform.matrix13;
- xform.matrix[1][0] = stuff->transform.matrix21;
- xform.matrix[1][1] = stuff->transform.matrix22;
- xform.matrix[1][2] = stuff->transform.matrix23;
- xform.matrix[2][0] = stuff->transform.matrix31;
- xform.matrix[2][1] = stuff->transform.matrix32;
- xform.matrix[2][2] = stuff->transform.matrix33;
-
- XRenderSetPictureTransform(dmxScreen->beDisplay,
- pPictPriv->pict,
- &xform);
- dmxSync(dmxScreen, FALSE);
- }
-
- return dmxSaveRenderVector[stuff->renderReqType](client);
-}
-
-/** Set the picture filter on each screen. */
-static int dmxProcRenderSetPictureFilter(ClientPtr client)
-{
- DMXScreenInfo *dmxScreen;
- PicturePtr pPicture;
- dmxPictPrivPtr pPictPriv;
- char *filter;
- XFixed *params;
- int nparams;
- REQUEST(xRenderSetPictureFilterReq);
-
- REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
- VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess,
- RenderErrBase + BadPicture);
-
- /* For the following to work with PanoramiX, it assumes that Render
- * wraps the ProcRenderVector after dmxRenderInit has been called.
- */
- dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
- pPictPriv = DMX_GET_PICT_PRIV(pPicture);
-
- if (pPictPriv->pict) {
- filter = (char *)(stuff + 1);
- params = (XFixed *)(filter + ((stuff->nbytes + 3) & ~3));
- nparams = ((XFixed *)stuff + client->req_len) - params;
-
- XRenderSetPictureFilter(dmxScreen->beDisplay,
- pPictPriv->pict,
- filter,
- params,
- nparams);
- dmxSync(dmxScreen, FALSE);
- }
-
- return dmxSaveRenderVector[stuff->renderReqType](client);
-}
-
-
-/** Create a picture on the appropriate screen. This is the actual
- * function that creates the picture. However, if the associated
- * window has not yet been created due to lazy window creation, then
- * delay the picture creation until the window is mapped. */
-static Picture dmxDoCreatePicture(PicturePtr pPicture)
-{
- DrawablePtr pDraw = pPicture->pDrawable;
- ScreenPtr pScreen = pDraw->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- XRenderPictFormat *pFormat;
- Drawable draw;
-
- if (pPicture->pDrawable->type == DRAWABLE_WINDOW) {
- dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr)(pDraw));
-
- if (!(draw = pWinPriv->window)) {
- /* Window has not been created yet due to the window
- * optimization. Delay picture creation until window is
- * mapped.
- */
- pWinPriv->hasPict = TRUE;
- return 0;
- }
- } else {
- dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr)(pDraw));
-
- if (!(draw = pPixPriv->pixmap)) {
- /* FIXME: Zero width/height pixmap?? */
- return 0;
- }
- }
-
- /* This should not be reached if the back-end display has been
- * detached because the pWinPriv->window or the pPixPriv->pixmap
- * will be NULL; however, we add it here for completeness
- */
- if (!dmxScreen->beDisplay)
- return 0;
-
- pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat);
-
- return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0);
-}
-
-/** Create a list of pictures. This function is called by
- * dmxCreateAndRealizeWindow() during the lazy window creation
- * realization process. It creates the entire list of pictures that
- * are associated with the given window. */
-void dmxCreatePictureList(WindowPtr pWindow)
-{
- PicturePtr pPicture = GetPictureWindow(pWindow);
-
- while (pPicture) {
- dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
-
- /* Create the picture for this window */
- pPictPriv->pict = dmxDoCreatePicture(pPicture);
-
- /* ValidatePicture takes care of the state changes */
-
- pPicture = pPicture->pNext;
- }
-}
-
-/** Create \a pPicture on the backend. */
-int dmxBECreatePicture(PicturePtr pPicture)
-{
- dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
-
- /* Create picutre on BE */
- pPictPriv->pict = dmxDoCreatePicture(pPicture);
-
- /* Flush changes to the backend server */
- dmxValidatePicture(pPicture, (1 << (CPLastBit+1)) - 1);
-
- return Success;
-}
-
-/** Create a picture. This function handles the CreatePicture
- * unwrapping/wrapping and calls dmxDoCreatePicture to actually create
- * the picture on the appropriate screen. */
-int dmxCreatePicture(PicturePtr pPicture)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
- int ret = Success;
-
- DMX_UNWRAP(CreatePicture, dmxScreen, ps);
-#if 1
- if (ps->CreatePicture)
- ret = ps->CreatePicture(pPicture);
-#endif
-
- /* Create picture on back-end server */
- pPictPriv->pict = dmxDoCreatePicture(pPicture);
- pPictPriv->savedMask = 0;
-
- DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
-
- return ret;
-}
-
-/** Destroy \a pPicture on the back-end server. */
-Bool dmxBEFreePicture(PicturePtr pPicture)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
-
- if (pPictPriv->pict) {
- XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict);
- pPictPriv->pict = (Picture)0;
- return TRUE;
- }
-
- return FALSE;
-}
-
-/** Destroy a list of pictures that are associated with the window that
- * is being destroyed. This function is called by #dmxDestroyWindow().
- * */
-Bool dmxDestroyPictureList(WindowPtr pWindow)
-{
- PicturePtr pPicture = GetPictureWindow(pWindow);
- Bool ret = FALSE;
-
- while (pPicture) {
- ret |= dmxBEFreePicture(pPicture);
- pPicture = pPicture->pNext;
- }
-
- return ret;
-}
-
-/** Destroy a picture. This function calls the wrapped function that
- * frees the resources in the DMX server associated with this
- * picture. */
-void dmxDestroyPicture(PicturePtr pPicture)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
-
- DMX_UNWRAP(DestroyPicture, dmxScreen, ps);
-
- /* Destroy picture on back-end server */
- if (dmxBEFreePicture(pPicture))
- dmxSync(dmxScreen, FALSE);
-
-#if 1
- if (ps->DestroyPicture)
- ps->DestroyPicture(pPicture);
-#endif
- DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
-}
-
-/** Change the picture's list of clip rectangles. */
-int dmxChangePictureClip(PicturePtr pPicture, int clipType,
- pointer value, int n)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
-
- DMX_UNWRAP(ChangePictureClip, dmxScreen, ps);
-#if 1
- if (ps->ChangePictureClip)
- ps->ChangePictureClip(pPicture, clipType, value, n);
-#endif
-
- /* Change picture clip rects on back-end server */
- if (pPictPriv->pict) {
- /* The clip has already been changed into a region by the mi
- * routine called above.
- */
- if (clipType == CT_NONE) {
- /* Disable clipping, show all */
- XFixesSetPictureClipRegion(dmxScreen->beDisplay,
- pPictPriv->pict, 0, 0, None);
- } else if (pPicture->clientClip) {
- RegionPtr pClip = pPicture->clientClip;
- BoxPtr pBox = REGION_RECTS(pClip);
- int nBox = REGION_NUM_RECTS(pClip);
- XRectangle *pRects;
- XRectangle *pRect;
- int nRects;
-
- nRects = nBox;
- pRects = pRect = xalloc(nRects * sizeof(*pRect));
-
- while (nBox--) {
- pRect->x = pBox->x1;
- pRect->y = pBox->y1;
- pRect->width = pBox->x2 - pBox->x1;
- pRect->height = pBox->y2 - pBox->y1;
- pBox++;
- pRect++;
- }
-
- XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
- pPictPriv->pict,
- 0, 0,
- pRects,
- nRects);
- xfree(pRects);
- } else {
- XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
- pPictPriv->pict,
- 0, 0, NULL, 0);
- }
- dmxSync(dmxScreen, FALSE);
- } else {
- /* FIXME: Handle saving clip region when offscreen */
- }
-
- DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
-
- return Success;
-}
-
-/** Destroy the picture's list of clip rectangles. */
-void dmxDestroyPictureClip(PicturePtr pPicture)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
-
- DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps);
-#if 1
- if (ps->DestroyPictureClip)
- ps->DestroyPictureClip(pPicture);
-#endif
-
- /* Destroy picture clip rects on back-end server */
- if (pPictPriv->pict) {
- XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
- pPictPriv->pict,
- 0, 0, NULL, 0);
- dmxSync(dmxScreen, FALSE);
- } else {
- /* FIXME: Handle destroying clip region when offscreen */
- }
-
- DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
-}
-
-/** Change the attributes of the pictures. If the picture has not yet
- * been created due to lazy window creation, save the mask so that it
- * can be used to appropriately initialize the picture's attributes
- * when it is created later. */
-void dmxChangePicture(PicturePtr pPicture, Mask mask)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
-
- DMX_UNWRAP(ChangePicture, dmxScreen, ps);
-#if 1
- if (ps->ChangePicture)
- ps->ChangePicture(pPicture, mask);
-#endif
-
- /* Picture attribute changes are handled in ValidatePicture */
- pPictPriv->savedMask |= mask;
-
- DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
-}
-
-/** Validate the picture's attributes before rendering to it. Update
- * any picture attributes that have been changed by one of the higher
- * layers. */
-void dmxValidatePicture(PicturePtr pPicture, Mask mask)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
-
- DMX_UNWRAP(ValidatePicture, dmxScreen, ps);
-
- /* Change picture attributes on back-end server */
- if (pPictPriv->pict) {
- XRenderPictureAttributes attribs;
-
- if (mask & CPRepeat) {
- attribs.repeat = pPicture->repeatType;
- }
- if (mask & CPAlphaMap) {
- if (pPicture->alphaMap) {
- dmxPictPrivPtr pAlphaPriv;
- pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap);
- if (pAlphaPriv->pict) {
- attribs.alpha_map = pAlphaPriv->pict;
- } else {
- /* FIXME: alpha picture drawable has not been created?? */
- return; /* or should this be: attribs.alpha_map = None; */
- }
- } else {
- attribs.alpha_map = None;
- }
- }
- if (mask & CPAlphaXOrigin)
- attribs.alpha_x_origin = pPicture->alphaOrigin.x;
- if (mask & CPAlphaYOrigin)
- attribs.alpha_y_origin = pPicture->alphaOrigin.y;
- if (mask & CPClipXOrigin)
- attribs.clip_x_origin = pPicture->clipOrigin.x;
- if (mask & CPClipYOrigin)
- attribs.clip_y_origin = pPicture->clipOrigin.y;
- if (mask & CPClipMask)
- mask &= ~CPClipMask; /* Handled in ChangePictureClip */
- if (mask & CPGraphicsExposure)
- attribs.graphics_exposures = pPicture->graphicsExposures;
- if (mask & CPSubwindowMode)
- attribs.subwindow_mode = pPicture->subWindowMode;
- if (mask & CPPolyEdge)
- attribs.poly_edge = pPicture->polyEdge;
- if (mask & CPPolyMode)
- attribs.poly_mode = pPicture->polyMode;
- if (mask & CPDither)
- attribs.dither = pPicture->dither;
- if (mask & CPComponentAlpha)
- attribs.component_alpha = pPicture->componentAlpha;
-
- XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict,
- mask, &attribs);
- dmxSync(dmxScreen, FALSE);
- } else {
- pPictPriv->savedMask |= mask;
- }
-
-#if 1
- if (ps->ValidatePicture)
- ps->ValidatePicture(pPicture, mask);
-#endif
-
- DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
-}
-
-/** Composite a picture on the appropriate screen by combining the
- * specified rectangle of the transformed src and mask operands with
- * the specified rectangle of the dst using op as the compositing
- * operator. For a complete description see the protocol document of
- * the RENDER library. */
-void dmxComposite(CARD8 op,
- PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
- INT16 xSrc, INT16 ySrc,
- INT16 xMask, INT16 yMask,
- INT16 xDst, INT16 yDst,
- CARD16 width, CARD16 height)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
- dmxPictPrivPtr pMaskPriv = NULL;
- dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
-
- if (pMask) pMaskPriv = DMX_GET_PICT_PRIV(pMask);
-
- DMX_UNWRAP(Composite, dmxScreen, ps);
-#if 0
- if (ps->Composite)
- ps->Composite(op, pSrc, pMask, pDst,
- xSrc, ySrc, xMask, yMask, xDst, yDst,
- width, height);
-#endif
-
- /* Composite on back-end server */
- if (pSrcPriv->pict && pDstPriv->pict &&
- ((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) {
- XRenderComposite(dmxScreen->beDisplay,
- op,
- pSrcPriv->pict,
- pMaskPriv ? pMaskPriv->pict : None,
- pDstPriv->pict,
- xSrc, ySrc,
- xMask, yMask,
- xDst, yDst,
- width, height);
- dmxSync(dmxScreen, FALSE);
- }
-
-
- DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
-}
-
-/** Null function to catch when/if RENDER calls lower level mi hooks.
- * Compositing glyphs is handled by dmxProcRenderCompositeGlyphs().
- * This function should never be called. */
-void dmxGlyphs(CARD8 op,
- PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc, INT16 ySrc,
- int nlists, GlyphListPtr lists, GlyphPtr *glyphs)
-{
- /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */
-}
-
-/** Fill a rectangle on the appropriate screen by combining the color
- * with the dest picture in the area specified by the list of
- * rectangles. For a complete description see the protocol document of
- * the RENDER library. */
-void dmxCompositeRects(CARD8 op,
- PicturePtr pDst,
- xRenderColor *color,
- int nRect, xRectangle *rects)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pDst);
-
- DMX_UNWRAP(CompositeRects, dmxScreen, ps);
-#if 0
- if (ps->CompositeRects)
- ps->CompositeRects(op, pDst, color, nRect, rects);
-#endif
-
- /* CompositeRects on back-end server */
- if (pPictPriv->pict) {
- XRenderFillRectangles(dmxScreen->beDisplay,
- op,
- pPictPriv->pict,
- (XRenderColor *)color,
- (XRectangle *)rects,
- nRect);
- dmxSync(dmxScreen, FALSE);
- }
-
- DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
-}
-
-/** Indexed color visuals are not yet supported. */
-Bool dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
-{
- return TRUE;
-}
-
-/** Indexed color visuals are not yet supported. */
-void dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
-{
-}
-
-/** Indexed color visuals are not yet supported. */
-void dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat,
- int ndef, xColorItem *pdef)
-{
-}
-
-/** Composite a list of trapezoids on the appropriate screen. For a
- * complete description see the protocol document of the RENDER
- * library. */
-void dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc, INT16 ySrc,
- int ntrap, xTrapezoid *traps)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
- dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
-
- DMX_UNWRAP(Trapezoids, dmxScreen, ps);
-#if 0
- if (ps->Trapezoids)
- ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps);
-#endif
-
- /* Draw trapezoids on back-end server */
- if (pDstPriv->pict) {
- XRenderPictFormat *pFormat;
-
- pFormat = dmxFindFormat(dmxScreen, maskFormat);
- if (!pFormat) {
- /* FIXME: Error! */
- }
-
- XRenderCompositeTrapezoids(dmxScreen->beDisplay,
- op,
- pSrcPriv->pict,
- pDstPriv->pict,
- pFormat,
- xSrc, ySrc,
- (XTrapezoid *)traps,
- ntrap);
- dmxSync(dmxScreen, FALSE);
- }
-
- DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
-}
-
-/** Composite a list of triangles on the appropriate screen. For a
- * complete description see the protocol document of the RENDER
- * library. */
-void dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc, INT16 ySrc,
- int ntri, xTriangle *tris)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
- dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
-
- DMX_UNWRAP(Triangles, dmxScreen, ps);
-#if 0
- if (ps->Triangles)
- ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris);
-#endif
-
- /* Draw trapezoids on back-end server */
- if (pDstPriv->pict) {
- XRenderPictFormat *pFormat;
-
- pFormat = dmxFindFormat(dmxScreen, maskFormat);
- if (!pFormat) {
- /* FIXME: Error! */
- }
-
- XRenderCompositeTriangles(dmxScreen->beDisplay,
- op,
- pSrcPriv->pict,
- pDstPriv->pict,
- pFormat,
- xSrc, ySrc,
- (XTriangle *)tris,
- ntri);
- dmxSync(dmxScreen, FALSE);
- }
-
- DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
-}
-
-/** Composite a triangle strip on the appropriate screen. For a
- * complete description see the protocol document of the RENDER
- * library. */
-void dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc, INT16 ySrc,
- int npoint, xPointFixed *points)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
- dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
-
- DMX_UNWRAP(TriStrip, dmxScreen, ps);
-#if 0
- if (ps->TriStrip)
- ps->TriStrip(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
-#endif
-
- /* Draw trapezoids on back-end server */
- if (pDstPriv->pict) {
- XRenderPictFormat *pFormat;
-
- pFormat = dmxFindFormat(dmxScreen, maskFormat);
- if (!pFormat) {
- /* FIXME: Error! */
- }
-
- XRenderCompositeTriStrip(dmxScreen->beDisplay,
- op,
- pSrcPriv->pict,
- pDstPriv->pict,
- pFormat,
- xSrc, ySrc,
- (XPointFixed *)points,
- npoint);
- dmxSync(dmxScreen, FALSE);
- }
-
- DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps);
-}
-
-/** Composite a triangle fan on the appropriate screen. For a complete
- * description see the protocol document of the RENDER library. */
-void dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc, INT16 ySrc,
- int npoint, xPointFixed *points)
-{
- ScreenPtr pScreen = pDst->pDrawable->pScreen;
- DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
- dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
-
- DMX_UNWRAP(TriFan, dmxScreen, ps);
-#if 0
- if (ps->TriFan)
- ps->TriFan(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
-#endif
-
- /* Draw trapezoids on back-end server */
- if (pDstPriv->pict) {
- XRenderPictFormat *pFormat;
-
- pFormat = dmxFindFormat(dmxScreen, maskFormat);
- if (!pFormat) {
- /* FIXME: Error! */
- }
-
- XRenderCompositeTriFan(dmxScreen->beDisplay,
- op,
- pSrcPriv->pict,
- pDstPriv->pict,
- pFormat,
- xSrc, ySrc,
- (XPointFixed *)points,
- npoint);
- dmxSync(dmxScreen, FALSE);
- }
-
- DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps);
-}
+/*
+ * Copyright 2001-2004 Red Hat Inc., Durham, North Carolina.
+ *
+ * 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 on 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
+ * NON-INFRINGEMENT. IN NO EVENT SHALL RED HAT AND/OR THEIR SUPPLIERS
+ * 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:
+ * Kevin E. Martin <kem@redhat.com>
+ *
+ */
+
+/** \file
+ * Provide support for the RENDER extension (version 0.8).
+ */
+
+#ifdef HAVE_DMX_CONFIG_H
+#include <dmx-config.h>
+#endif
+
+#include "dmx.h"
+#include "dmxsync.h"
+#include "dmxpict.h"
+#include "dmxwindow.h"
+#include "dmxpixmap.h"
+
+#include "fb.h"
+#include "pixmapstr.h"
+#include "dixstruct.h"
+
+#include <X11/extensions/render.h>
+#include <X11/extensions/renderproto.h>
+#include <X11/extensions/Xfixes.h>
+#include "picture.h"
+#include "picturestr.h"
+#include "mipict.h"
+#include "fbpict.h"
+
+
+extern int RenderErrBase;
+extern int (*ProcRenderVector[RenderNumberRequests])(ClientPtr);
+
+static int (*dmxSaveRenderVector[RenderNumberRequests])(ClientPtr);
+
+
+static int dmxProcRenderCreateGlyphSet(ClientPtr client);
+static int dmxProcRenderFreeGlyphSet(ClientPtr client);
+static int dmxProcRenderAddGlyphs(ClientPtr client);
+static int dmxProcRenderFreeGlyphs(ClientPtr client);
+static int dmxProcRenderCompositeGlyphs(ClientPtr client);
+static int dmxProcRenderSetPictureTransform(ClientPtr client);
+static int dmxProcRenderSetPictureFilter(ClientPtr client);
+#if 0
+/* FIXME: Not (yet) supported */
+static int dmxProcRenderCreateCursor(ClientPtr client);
+static int dmxProcRenderCreateAnimCursor(ClientPtr client);
+#endif
+
+/** Catch errors that might occur when allocating Glyph Sets. Errors
+ * are saved in dmxGlyphLastError for later handling. */
+static int dmxGlyphLastError;
+static int dmxGlyphErrorHandler(Display *dpy, XErrorEvent *ev)
+{
+ dmxGlyphLastError = ev->error_code;
+ return 0;
+}
+
+
+/** Initialize the Proc Vector for the RENDER extension. The functions
+ * here cannot be handled by the mi layer RENDER hooks either because
+ * the required information is no longer available when it reaches the
+ * mi layer or no mi layer hooks exist. This function is called from
+ * InitOutput() since it should be initialized only once per server
+ * generation. */
+void dmxInitRender(void)
+{
+ int i;
+
+ for (i = 0; i < RenderNumberRequests; i++)
+ dmxSaveRenderVector[i] = ProcRenderVector[i];
+
+ ProcRenderVector[X_RenderCreateGlyphSet]
+ = dmxProcRenderCreateGlyphSet;
+ ProcRenderVector[X_RenderFreeGlyphSet]
+ = dmxProcRenderFreeGlyphSet;
+ ProcRenderVector[X_RenderAddGlyphs]
+ = dmxProcRenderAddGlyphs;
+ ProcRenderVector[X_RenderFreeGlyphs]
+ = dmxProcRenderFreeGlyphs;
+ ProcRenderVector[X_RenderCompositeGlyphs8]
+ = dmxProcRenderCompositeGlyphs;
+ ProcRenderVector[X_RenderCompositeGlyphs16]
+ = dmxProcRenderCompositeGlyphs;
+ ProcRenderVector[X_RenderCompositeGlyphs32]
+ = dmxProcRenderCompositeGlyphs;
+ ProcRenderVector[X_RenderSetPictureTransform]
+ = dmxProcRenderSetPictureTransform;
+ ProcRenderVector[X_RenderSetPictureFilter]
+ = dmxProcRenderSetPictureFilter;
+}
+
+/** Reset the Proc Vector for the RENDER extension back to the original
+ * functions. This function is called from dmxCloseScreen() during the
+ * server reset (only for screen #0). */
+void dmxResetRender(void)
+{
+ int i;
+
+ for (i = 0; i < RenderNumberRequests; i++)
+ ProcRenderVector[i] = dmxSaveRenderVector[i];
+}
+
+/** Initialize the RENDER extension, allocate the picture privates and
+ * wrap mi function hooks. If the shadow frame buffer is used, then
+ * call the appropriate fb initialization function. */
+Bool dmxPictureInit(ScreenPtr pScreen, PictFormatPtr formats, int nformats)
+{
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps;
+
+ /* The shadow framebuffer only relies on FB to be initialized */
+ if (dmxShadowFB) return fbPictureInit(pScreen, formats, nformats);
+
+ if (!miPictureInit(pScreen, formats, nformats))
+ return FALSE;
+
+ if (!dixRequestPrivate(dmxPictPrivateKey, sizeof(dmxPictPrivRec)))
+ return FALSE;
+
+ ps = GetPictureScreen(pScreen);
+
+ DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
+ DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
+
+ DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
+ DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
+
+ DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
+ DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
+
+ DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
+ DMX_WRAP(Glyphs, dmxGlyphs, dmxScreen, ps);
+ DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
+
+ DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
+ DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
+ DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps);
+ DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps);
+
+ return TRUE;
+}
+
+
+/** Find the appropriate format on the requested screen given the
+ * internal format requested. The list of formats is searched
+ * sequentially as the XRenderFindFormat() function does not always
+ * find the appropriate format when a specific format is requested. */
+static XRenderPictFormat *dmxFindFormat(DMXScreenInfo *dmxScreen,
+ PictFormatPtr pFmt)
+{
+ XRenderPictFormat *pFormat = NULL;
+ int i = 0;
+
+ if (!pFmt || !dmxScreen->beDisplay) return pFormat;
+
+ while (1) {
+ pFormat = XRenderFindFormat(dmxScreen->beDisplay, 0, 0, i++);
+ if (!pFormat) break;
+
+ if (pFormat->type != pFmt->type) continue;
+ if (pFormat->depth != pFmt->depth) continue;
+ if (pFormat->direct.red != pFmt->direct.red) continue;
+ if (pFormat->direct.redMask != pFmt->direct.redMask) continue;
+ if (pFormat->direct.green != pFmt->direct.green) continue;
+ if (pFormat->direct.greenMask != pFmt->direct.greenMask) continue;
+ if (pFormat->direct.blue != pFmt->direct.blue) continue;
+ if (pFormat->direct.blueMask != pFmt->direct.blueMask) continue;
+ if (pFormat->direct.alpha != pFmt->direct.alpha) continue;
+ if (pFormat->direct.alphaMask != pFmt->direct.alphaMask) continue;
+
+ /* We have a match! */
+ break;
+ }
+
+ return pFormat;
+}
+
+/** Free \a glyphSet on back-end screen number \a idx. */
+Bool dmxBEFreeGlyphSet(ScreenPtr pScreen, GlyphSetPtr glyphSet)
+{
+ dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ int idx = pScreen->myNum;
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+
+ if (glyphPriv->glyphSets[idx]) {
+ XRenderFreeGlyphSet(dmxScreen->beDisplay, glyphPriv->glyphSets[idx]);
+ glyphPriv->glyphSets[idx] = (GlyphSet)0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/** Create \a glyphSet on the backend screen number \a idx. */
+int dmxBECreateGlyphSet(int idx, GlyphSetPtr glyphSet)
+{
+ XRenderPictFormat *pFormat;
+ DMXScreenInfo *dmxScreen = &dmxScreens[idx];
+ dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ PictFormatPtr pFmt = glyphSet->format;
+ int (*oldErrorHandler)(Display *, XErrorEvent *);
+
+ pFormat = dmxFindFormat(dmxScreen, pFmt);
+ if (!pFormat) {
+ return BadMatch;
+ }
+
+ dmxGlyphLastError = 0;
+ oldErrorHandler = XSetErrorHandler(dmxGlyphErrorHandler);
+
+ /* Catch when this fails */
+ glyphPriv->glyphSets[idx]
+ = XRenderCreateGlyphSet(dmxScreen->beDisplay, pFormat);
+
+ XSetErrorHandler(oldErrorHandler);
+
+ if (dmxGlyphLastError) {
+ return dmxGlyphLastError;
+ }
+
+ return Success;
+}
+
+/** Create a Glyph Set on each screen. Save the glyphset ID from each
+ * screen in the Glyph Set's private structure. Fail if the format
+ * requested is not available or if the Glyph Set cannot be created on
+ * the screen. */
+static int dmxProcRenderCreateGlyphSet(ClientPtr client)
+{
+ int ret;
+ REQUEST(xRenderCreateGlyphSetReq);
+
+ ret = dmxSaveRenderVector[stuff->renderReqType](client);
+
+ if (ret == Success) {
+ GlyphSetPtr glyphSet;
+ dmxGlyphPrivPtr glyphPriv;
+ int i;
+
+ /* Look up glyphSet that was just created ???? */
+ /* Store glyphsets from backends in glyphSet->devPrivate ????? */
+ /* Make sure we handle all errors here!! */
+
+ glyphSet = SecurityLookupIDByType(client, stuff->gsid, GlyphSetType,
+ DixDestroyAccess);
+ glyphPriv = xalloc(sizeof(dmxGlyphPrivRec));
+ if (!glyphPriv) return BadAlloc;
+ glyphPriv->glyphSets = NULL;
+ MAXSCREENSALLOC_RETURN(glyphPriv->glyphSets, BadAlloc);
+ DMX_SET_GLYPH_PRIV(glyphSet, glyphPriv);
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+ int beret;
+
+ if (!dmxScreen->beDisplay) {
+ glyphPriv->glyphSets[i] = 0;
+ continue;
+ }
+
+ if ((beret = dmxBECreateGlyphSet(i, glyphSet)) != Success) {
+ int j;
+
+ /* Free the glyph sets we've allocated thus far */
+ for (j = 0; j < i; j++)
+ dmxBEFreeGlyphSet(screenInfo.screens[j], glyphSet);
+
+ /* Free the resource created by render */
+ FreeResource(stuff->gsid, RT_NONE);
+
+ return beret;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/** Free the previously allocated Glyph Sets for each screen. */
+static int dmxProcRenderFreeGlyphSet(ClientPtr client)
+{
+ GlyphSetPtr glyphSet;
+ REQUEST(xRenderFreeGlyphSetReq);
+
+ REQUEST_SIZE_MATCH(xRenderFreeGlyphSetReq);
+ glyphSet = SecurityLookupIDByType(client, stuff->glyphset, GlyphSetType,
+ DixDestroyAccess);
+
+ if (glyphSet && glyphSet->refcnt == 1) {
+ dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ int i;
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+ if (dmxScreen->beDisplay) {
+ if (dmxBEFreeGlyphSet(screenInfo.screens[i], glyphSet))
+ dmxSync(dmxScreen, FALSE);
+ }
+ }
+
+ MAXSCREENSFREE(glyphPriv->glyphSets);
+ xfree(glyphPriv);
+ DMX_SET_GLYPH_PRIV(glyphSet, NULL);
+ }
+
+ return dmxSaveRenderVector[stuff->renderReqType](client);
+}
+
+/** Add glyphs to the Glyph Set on each screen. */
+static int dmxProcRenderAddGlyphs(ClientPtr client)
+{
+ int ret;
+ REQUEST(xRenderAddGlyphsReq);
+
+ ret = dmxSaveRenderVector[stuff->renderReqType](client);
+
+ if (ret == Success) {
+ GlyphSetPtr glyphSet;
+ dmxGlyphPrivPtr glyphPriv;
+ int i;
+ int nglyphs;
+ CARD32 *gids;
+ Glyph *gidsCopy;
+ xGlyphInfo *gi;
+ CARD8 *bits;
+ int nbytes;
+
+ glyphSet = SecurityLookupIDByType(client, stuff->glyphset,
+ GlyphSetType, DixReadAccess);
+ glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+
+ nglyphs = stuff->nglyphs;
+ gids = (CARD32 *)(stuff + 1);
+ gi = (xGlyphInfo *)(gids + nglyphs);
+ bits = (CARD8 *)(gi + nglyphs);
+ nbytes = ((stuff->length << 2) -
+ sizeof(xRenderAddGlyphsReq) -
+ (sizeof(CARD32) + sizeof(xGlyphInfo)) * nglyphs);
+
+ gidsCopy = xalloc(sizeof(*gidsCopy) * nglyphs);
+ for (i = 0; i < nglyphs; i++) gidsCopy[i] = gids[i];
+
+ /* FIXME: Will this ever fail? */
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+ if (dmxScreen->beDisplay) {
+ XRenderAddGlyphs(dmxScreen->beDisplay,
+ glyphPriv->glyphSets[i],
+ gidsCopy,
+ (XGlyphInfo *)gi,
+ nglyphs,
+ (char *)bits,
+ nbytes);
+ dmxSync(dmxScreen, FALSE);
+ }
+ }
+ xfree(gidsCopy);
+ }
+
+ return ret;
+}
+
+/** Free glyphs from the Glyph Set for each screen. */
+static int dmxProcRenderFreeGlyphs(ClientPtr client)
+{
+ GlyphSetPtr glyphSet;
+ REQUEST(xRenderFreeGlyphsReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderFreeGlyphsReq);
+ glyphSet = SecurityLookupIDByType(client, stuff->glyphset, GlyphSetType,
+ DixWriteAccess);
+
+ if (glyphSet) {
+ dmxGlyphPrivPtr glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ int i;
+ int nglyphs;
+ Glyph *gids;
+
+ nglyphs = ((client->req_len << 2) - sizeof(xRenderFreeGlyphsReq)) >> 2;
+ if (nglyphs) {
+ gids = xalloc(sizeof(*gids) * nglyphs);
+ for (i = 0; i < nglyphs; i++)
+ gids[i] = ((CARD32 *)(stuff + 1))[i];
+
+ for (i = 0; i < dmxNumScreens; i++) {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+ if (dmxScreen->beDisplay) {
+ XRenderFreeGlyphs(dmxScreen->beDisplay,
+ glyphPriv->glyphSets[i], gids, nglyphs);
+ dmxSync(dmxScreen, FALSE);
+ }
+ }
+ xfree(gids);
+ }
+ }
+
+ return dmxSaveRenderVector[stuff->renderReqType](client);
+}
+
+/** Composite glyphs on each screen into the requested picture. If
+ * either the src or dest picture has not been allocated due to lazy
+ * window creation, this request will gracefully return. */
+static int dmxProcRenderCompositeGlyphs(ClientPtr client)
+{
+ int ret;
+ REQUEST(xRenderCompositeGlyphsReq);
+
+ ret = dmxSaveRenderVector[stuff->renderReqType](client);
+
+ /* For the following to work with PanoramiX, it assumes that Render
+ * wraps the ProcRenderVector after dmxRenderInit has been called.
+ */
+ if (ret == Success) {
+ PicturePtr pSrc;
+ dmxPictPrivPtr pSrcPriv;
+ PicturePtr pDst;
+ dmxPictPrivPtr pDstPriv;
+ PictFormatPtr pFmt;
+ XRenderPictFormat *pFormat;
+ int size;
+
+ int scrnNum;
+ DMXScreenInfo *dmxScreen;
+
+ CARD8 *buffer;
+ CARD8 *end;
+ int space;
+
+ int nglyph;
+ char *glyphs;
+ char *curGlyph;
+
+ xGlyphElt *elt;
+ int nelt;
+ XGlyphElt8 *elts;
+ XGlyphElt8 *curElt;
+
+ GlyphSetPtr glyphSet;
+ dmxGlyphPrivPtr glyphPriv;
+
+ pSrc = SecurityLookupIDByType(client, stuff->src, PictureType,
+ DixReadAccess);
+ pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ if (!pSrcPriv->pict)
+ return ret;
+
+ pDst = SecurityLookupIDByType(client, stuff->dst, PictureType,
+ DixWriteAccess);
+ pDstPriv = DMX_GET_PICT_PRIV(pDst);
+ if (!pDstPriv->pict)
+ return ret;
+
+ scrnNum = pDst->pDrawable->pScreen->myNum;
+ dmxScreen = &dmxScreens[scrnNum];
+
+ /* Note: If the back-end display has been detached, then it
+ * should not be possible to reach here since the pSrcPriv->pict
+ * and pDstPriv->pict will have already been set to 0.
+ */
+ if (!dmxScreen->beDisplay)
+ return ret;
+
+ if (stuff->maskFormat)
+ pFmt = SecurityLookupIDByType(client, stuff->maskFormat,
+ PictFormatType, DixReadAccess);
+ else
+ pFmt = NULL;
+
+ pFormat = dmxFindFormat(dmxScreen, pFmt);
+
+ switch (stuff->renderReqType) {
+ case X_RenderCompositeGlyphs8: size = sizeof(CARD8); break;
+ case X_RenderCompositeGlyphs16: size = sizeof(CARD16); break;
+ case X_RenderCompositeGlyphs32: size = sizeof(CARD32); break;
+ default: return BadPictOp; /* Can't happen */
+ }
+
+ buffer = (CARD8 *)(stuff + 1);
+ end = (CARD8 *)stuff + (stuff->length << 2);
+ nelt = 0;
+ nglyph = 0;
+ while (buffer + sizeof(xGlyphElt) < end) {
+ elt = (xGlyphElt *)buffer;
+ buffer += sizeof(xGlyphElt);
+
+ if (elt->len == 0xff) {
+ buffer += 4;
+ } else {
+ nelt++;
+ nglyph += elt->len;
+ space = size * elt->len;
+ if (space & 3) space += 4 - (space & 3);
+ buffer += space;
+ }
+ }
+
+ /* The following only works for Render version > 0.2 */
+
+ /* All of the XGlyphElt* structure sizes are identical */
+ elts = xalloc(nelt * sizeof(XGlyphElt8));
+ if (!elts)
+ return BadAlloc;
+
+ glyphs = xalloc(nglyph * size);
+ if (!glyphs) {
+ xfree(elts);
+ return BadAlloc;
+ }
+
+ buffer = (CARD8 *)(stuff + 1);
+ end = (CARD8 *)stuff + (stuff->length << 2);
+ curGlyph = glyphs;
+ curElt = elts;
+
+ glyphSet = SecurityLookupIDByType(client, stuff->glyphset,
+ GlyphSetType, DixReadAccess);
+ glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+
+ while (buffer + sizeof(xGlyphElt) < end) {
+ elt = (xGlyphElt *)buffer;
+ buffer += sizeof(xGlyphElt);
+
+ if (elt->len == 0xff) {
+ glyphSet = SecurityLookupIDByType(client,
+ *((CARD32 *)buffer),
+ GlyphSetType,
+ DixReadAccess);
+ glyphPriv = DMX_GET_GLYPH_PRIV(glyphSet);
+ buffer += 4;
+ } else {
+ curElt->glyphset = glyphPriv->glyphSets[scrnNum];
+ curElt->xOff = elt->deltax;
+ curElt->yOff = elt->deltay;
+ curElt->nchars = elt->len;
+ curElt->chars = curGlyph;
+
+ memcpy(curGlyph, buffer, size*elt->len);
+ curGlyph += size * elt->len;
+
+ curElt++;
+
+ space = size * elt->len;
+ if (space & 3) space += 4 - (space & 3);
+ buffer += space;
+ }
+ }
+
+ switch (stuff->renderReqType) {
+ case X_RenderCompositeGlyphs8:
+ XRenderCompositeText8(dmxScreen->beDisplay, stuff->op,
+ pSrcPriv->pict, pDstPriv->pict,
+ pFormat,
+ stuff->xSrc, stuff->ySrc,
+ 0, 0, elts, nelt);
+ break;
+ case X_RenderCompositeGlyphs16:
+ XRenderCompositeText16(dmxScreen->beDisplay, stuff->op,
+ pSrcPriv->pict, pDstPriv->pict,
+ pFormat,
+ stuff->xSrc, stuff->ySrc,
+ 0, 0, (XGlyphElt16 *)elts, nelt);
+ break;
+ case X_RenderCompositeGlyphs32:
+ XRenderCompositeText32(dmxScreen->beDisplay, stuff->op,
+ pSrcPriv->pict, pDstPriv->pict,
+ pFormat,
+ stuff->xSrc, stuff->ySrc,
+ 0, 0, (XGlyphElt32 *)elts, nelt);
+ break;
+ }
+
+ dmxSync(dmxScreen, FALSE);
+
+ xfree(elts);
+ xfree(glyphs);
+ }
+
+ return ret;
+}
+
+/** Set the picture transform on each screen. */
+static int dmxProcRenderSetPictureTransform(ClientPtr client)
+{
+ DMXScreenInfo *dmxScreen;
+ PicturePtr pPicture;
+ dmxPictPrivPtr pPictPriv;
+ XTransform xform;
+ REQUEST(xRenderSetPictureTransformReq);
+
+ REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
+ VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
+
+ /* For the following to work with PanoramiX, it assumes that Render
+ * wraps the ProcRenderVector after dmxRenderInit has been called.
+ */
+ dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
+ pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ if (pPictPriv->pict) {
+ xform.matrix[0][0] = stuff->transform.matrix11;
+ xform.matrix[0][1] = stuff->transform.matrix12;
+ xform.matrix[0][2] = stuff->transform.matrix13;
+ xform.matrix[1][0] = stuff->transform.matrix21;
+ xform.matrix[1][1] = stuff->transform.matrix22;
+ xform.matrix[1][2] = stuff->transform.matrix23;
+ xform.matrix[2][0] = stuff->transform.matrix31;
+ xform.matrix[2][1] = stuff->transform.matrix32;
+ xform.matrix[2][2] = stuff->transform.matrix33;
+
+ XRenderSetPictureTransform(dmxScreen->beDisplay,
+ pPictPriv->pict,
+ &xform);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ return dmxSaveRenderVector[stuff->renderReqType](client);
+}
+
+/** Set the picture filter on each screen. */
+static int dmxProcRenderSetPictureFilter(ClientPtr client)
+{
+ DMXScreenInfo *dmxScreen;
+ PicturePtr pPicture;
+ dmxPictPrivPtr pPictPriv;
+ char *filter;
+ XFixed *params;
+ int nparams;
+ REQUEST(xRenderSetPictureFilterReq);
+
+ REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
+ VERIFY_PICTURE(pPicture, stuff->picture, client, DixWriteAccess);
+
+ /* For the following to work with PanoramiX, it assumes that Render
+ * wraps the ProcRenderVector after dmxRenderInit has been called.
+ */
+ dmxScreen = &dmxScreens[pPicture->pDrawable->pScreen->myNum];
+ pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ if (pPictPriv->pict) {
+ filter = (char *)(stuff + 1);
+ params = (XFixed *)(filter + ((stuff->nbytes + 3) & ~3));
+ nparams = ((XFixed *)stuff + client->req_len) - params;
+
+ XRenderSetPictureFilter(dmxScreen->beDisplay,
+ pPictPriv->pict,
+ filter,
+ params,
+ nparams);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ return dmxSaveRenderVector[stuff->renderReqType](client);
+}
+
+
+/** Create a picture on the appropriate screen. This is the actual
+ * function that creates the picture. However, if the associated
+ * window has not yet been created due to lazy window creation, then
+ * delay the picture creation until the window is mapped. */
+static Picture dmxDoCreatePicture(PicturePtr pPicture)
+{
+ DrawablePtr pDraw = pPicture->pDrawable;
+ ScreenPtr pScreen = pDraw->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ XRenderPictFormat *pFormat;
+ Drawable draw;
+
+ if (pPicture->pDrawable->type == DRAWABLE_WINDOW) {
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV((WindowPtr)(pDraw));
+
+ if (!(draw = pWinPriv->window)) {
+ /* Window has not been created yet due to the window
+ * optimization. Delay picture creation until window is
+ * mapped.
+ */
+ pWinPriv->hasPict = TRUE;
+ return 0;
+ }
+ } else {
+ dmxPixPrivPtr pPixPriv = DMX_GET_PIXMAP_PRIV((PixmapPtr)(pDraw));
+
+ if (!(draw = pPixPriv->pixmap)) {
+ /* FIXME: Zero width/height pixmap?? */
+ return 0;
+ }
+ }
+
+ /* This should not be reached if the back-end display has been
+ * detached because the pWinPriv->window or the pPixPriv->pixmap
+ * will be NULL; however, we add it here for completeness
+ */
+ if (!dmxScreen->beDisplay)
+ return 0;
+
+ pFormat = dmxFindFormat(dmxScreen, pPicture->pFormat);
+
+ return XRenderCreatePicture(dmxScreen->beDisplay, draw, pFormat, 0, 0);
+}
+
+/** Create a list of pictures. This function is called by
+ * dmxCreateAndRealizeWindow() during the lazy window creation
+ * realization process. It creates the entire list of pictures that
+ * are associated with the given window. */
+void dmxCreatePictureList(WindowPtr pWindow)
+{
+ PicturePtr pPicture = GetPictureWindow(pWindow);
+
+ while (pPicture) {
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ /* Create the picture for this window */
+ pPictPriv->pict = dmxDoCreatePicture(pPicture);
+
+ /* ValidatePicture takes care of the state changes */
+
+ pPicture = pPicture->pNext;
+ }
+}
+
+/** Create \a pPicture on the backend. */
+int dmxBECreatePicture(PicturePtr pPicture)
+{
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ /* Create picutre on BE */
+ pPictPriv->pict = dmxDoCreatePicture(pPicture);
+
+ /* Flush changes to the backend server */
+ dmxValidatePicture(pPicture, (1 << (CPLastBit+1)) - 1);
+
+ return Success;
+}
+
+/** Create a picture. This function handles the CreatePicture
+ * unwrapping/wrapping and calls dmxDoCreatePicture to actually create
+ * the picture on the appropriate screen. */
+int dmxCreatePicture(PicturePtr pPicture)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+ int ret = Success;
+
+ DMX_UNWRAP(CreatePicture, dmxScreen, ps);
+#if 1
+ if (ps->CreatePicture)
+ ret = ps->CreatePicture(pPicture);
+#endif
+
+ /* Create picture on back-end server */
+ pPictPriv->pict = dmxDoCreatePicture(pPicture);
+ pPictPriv->savedMask = 0;
+
+ DMX_WRAP(CreatePicture, dmxCreatePicture, dmxScreen, ps);
+
+ return ret;
+}
+
+/** Destroy \a pPicture on the back-end server. */
+Bool dmxBEFreePicture(PicturePtr pPicture)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ if (pPictPriv->pict) {
+ XRenderFreePicture(dmxScreen->beDisplay, pPictPriv->pict);
+ pPictPriv->pict = (Picture)0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+/** Destroy a list of pictures that are associated with the window that
+ * is being destroyed. This function is called by #dmxDestroyWindow().
+ * */
+Bool dmxDestroyPictureList(WindowPtr pWindow)
+{
+ PicturePtr pPicture = GetPictureWindow(pWindow);
+ Bool ret = FALSE;
+
+ while (pPicture) {
+ ret |= dmxBEFreePicture(pPicture);
+ pPicture = pPicture->pNext;
+ }
+
+ return ret;
+}
+
+/** Destroy a picture. This function calls the wrapped function that
+ * frees the resources in the DMX server associated with this
+ * picture. */
+void dmxDestroyPicture(PicturePtr pPicture)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ DMX_UNWRAP(DestroyPicture, dmxScreen, ps);
+
+ /* Destroy picture on back-end server */
+ if (dmxBEFreePicture(pPicture))
+ dmxSync(dmxScreen, FALSE);
+
+#if 1
+ if (ps->DestroyPicture)
+ ps->DestroyPicture(pPicture);
+#endif
+ DMX_WRAP(DestroyPicture, dmxDestroyPicture, dmxScreen, ps);
+}
+
+/** Change the picture's list of clip rectangles. */
+int dmxChangePictureClip(PicturePtr pPicture, int clipType,
+ pointer value, int n)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ DMX_UNWRAP(ChangePictureClip, dmxScreen, ps);
+#if 1
+ if (ps->ChangePictureClip)
+ ps->ChangePictureClip(pPicture, clipType, value, n);
+#endif
+
+ /* Change picture clip rects on back-end server */
+ if (pPictPriv->pict) {
+ /* The clip has already been changed into a region by the mi
+ * routine called above.
+ */
+ if (clipType == CT_NONE) {
+ /* Disable clipping, show all */
+ XFixesSetPictureClipRegion(dmxScreen->beDisplay,
+ pPictPriv->pict, 0, 0, None);
+ } else if (pPicture->clientClip) {
+ RegionPtr pClip = pPicture->clientClip;
+ BoxPtr pBox = REGION_RECTS(pClip);
+ int nBox = REGION_NUM_RECTS(pClip);
+ XRectangle *pRects;
+ XRectangle *pRect;
+ int nRects;
+
+ nRects = nBox;
+ pRects = pRect = xalloc(nRects * sizeof(*pRect));
+
+ while (nBox--) {
+ pRect->x = pBox->x1;
+ pRect->y = pBox->y1;
+ pRect->width = pBox->x2 - pBox->x1;
+ pRect->height = pBox->y2 - pBox->y1;
+ pBox++;
+ pRect++;
+ }
+
+ XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
+ pPictPriv->pict,
+ 0, 0,
+ pRects,
+ nRects);
+ xfree(pRects);
+ } else {
+ XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
+ pPictPriv->pict,
+ 0, 0, NULL, 0);
+ }
+ dmxSync(dmxScreen, FALSE);
+ } else {
+ /* FIXME: Handle saving clip region when offscreen */
+ }
+
+ DMX_WRAP(ChangePictureClip, dmxChangePictureClip, dmxScreen, ps);
+
+ return Success;
+}
+
+/** Destroy the picture's list of clip rectangles. */
+void dmxDestroyPictureClip(PicturePtr pPicture)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ DMX_UNWRAP(DestroyPictureClip, dmxScreen, ps);
+#if 1
+ if (ps->DestroyPictureClip)
+ ps->DestroyPictureClip(pPicture);
+#endif
+
+ /* Destroy picture clip rects on back-end server */
+ if (pPictPriv->pict) {
+ XRenderSetPictureClipRectangles(dmxScreen->beDisplay,
+ pPictPriv->pict,
+ 0, 0, NULL, 0);
+ dmxSync(dmxScreen, FALSE);
+ } else {
+ /* FIXME: Handle destroying clip region when offscreen */
+ }
+
+ DMX_WRAP(DestroyPictureClip, dmxDestroyPictureClip, dmxScreen, ps);
+}
+
+/** Change the attributes of the pictures. If the picture has not yet
+ * been created due to lazy window creation, save the mask so that it
+ * can be used to appropriately initialize the picture's attributes
+ * when it is created later. */
+void dmxChangePicture(PicturePtr pPicture, Mask mask)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ DMX_UNWRAP(ChangePicture, dmxScreen, ps);
+#if 1
+ if (ps->ChangePicture)
+ ps->ChangePicture(pPicture, mask);
+#endif
+
+ /* Picture attribute changes are handled in ValidatePicture */
+ pPictPriv->savedMask |= mask;
+
+ DMX_WRAP(ChangePicture, dmxChangePicture, dmxScreen, ps);
+}
+
+/** Validate the picture's attributes before rendering to it. Update
+ * any picture attributes that have been changed by one of the higher
+ * layers. */
+void dmxValidatePicture(PicturePtr pPicture, Mask mask)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pPicture);
+
+ DMX_UNWRAP(ValidatePicture, dmxScreen, ps);
+
+ /* Change picture attributes on back-end server */
+ if (pPictPriv->pict) {
+ XRenderPictureAttributes attribs;
+
+ if (mask & CPRepeat) {
+ attribs.repeat = pPicture->repeatType;
+ }
+ if (mask & CPAlphaMap) {
+ if (pPicture->alphaMap) {
+ dmxPictPrivPtr pAlphaPriv;
+ pAlphaPriv = DMX_GET_PICT_PRIV(pPicture->alphaMap);
+ if (pAlphaPriv->pict) {
+ attribs.alpha_map = pAlphaPriv->pict;
+ } else {
+ /* FIXME: alpha picture drawable has not been created?? */
+ return; /* or should this be: attribs.alpha_map = None; */
+ }
+ } else {
+ attribs.alpha_map = None;
+ }
+ }
+ if (mask & CPAlphaXOrigin)
+ attribs.alpha_x_origin = pPicture->alphaOrigin.x;
+ if (mask & CPAlphaYOrigin)
+ attribs.alpha_y_origin = pPicture->alphaOrigin.y;
+ if (mask & CPClipXOrigin)
+ attribs.clip_x_origin = pPicture->clipOrigin.x;
+ if (mask & CPClipYOrigin)
+ attribs.clip_y_origin = pPicture->clipOrigin.y;
+ if (mask & CPClipMask)
+ mask &= ~CPClipMask; /* Handled in ChangePictureClip */
+ if (mask & CPGraphicsExposure)
+ attribs.graphics_exposures = pPicture->graphicsExposures;
+ if (mask & CPSubwindowMode)
+ attribs.subwindow_mode = pPicture->subWindowMode;
+ if (mask & CPPolyEdge)
+ attribs.poly_edge = pPicture->polyEdge;
+ if (mask & CPPolyMode)
+ attribs.poly_mode = pPicture->polyMode;
+ if (mask & CPDither)
+ attribs.dither = pPicture->dither;
+ if (mask & CPComponentAlpha)
+ attribs.component_alpha = pPicture->componentAlpha;
+
+ XRenderChangePicture(dmxScreen->beDisplay, pPictPriv->pict,
+ mask, &attribs);
+ dmxSync(dmxScreen, FALSE);
+ } else {
+ pPictPriv->savedMask |= mask;
+ }
+
+#if 1
+ if (ps->ValidatePicture)
+ ps->ValidatePicture(pPicture, mask);
+#endif
+
+ DMX_WRAP(ValidatePicture, dmxValidatePicture, dmxScreen, ps);
+}
+
+/** Composite a picture on the appropriate screen by combining the
+ * specified rectangle of the transformed src and mask operands with
+ * the specified rectangle of the dst using op as the compositing
+ * operator. For a complete description see the protocol document of
+ * the RENDER library. */
+void dmxComposite(CARD8 op,
+ PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc,
+ INT16 xMask, INT16 yMask,
+ INT16 xDst, INT16 yDst,
+ CARD16 width, CARD16 height)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ dmxPictPrivPtr pMaskPriv = NULL;
+ dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
+
+ if (pMask) pMaskPriv = DMX_GET_PICT_PRIV(pMask);
+
+ DMX_UNWRAP(Composite, dmxScreen, ps);
+#if 0
+ if (ps->Composite)
+ ps->Composite(op, pSrc, pMask, pDst,
+ xSrc, ySrc, xMask, yMask, xDst, yDst,
+ width, height);
+#endif
+
+ /* Composite on back-end server */
+ if (pSrcPriv->pict && pDstPriv->pict &&
+ ((pMaskPriv && pMaskPriv->pict) || !pMaskPriv)) {
+ XRenderComposite(dmxScreen->beDisplay,
+ op,
+ pSrcPriv->pict,
+ pMaskPriv ? pMaskPriv->pict : None,
+ pDstPriv->pict,
+ xSrc, ySrc,
+ xMask, yMask,
+ xDst, yDst,
+ width, height);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+
+ DMX_WRAP(Composite, dmxComposite, dmxScreen, ps);
+}
+
+/** Null function to catch when/if RENDER calls lower level mi hooks.
+ * Compositing glyphs is handled by dmxProcRenderCompositeGlyphs().
+ * This function should never be called. */
+void dmxGlyphs(CARD8 op,
+ PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int nlists, GlyphListPtr lists, GlyphPtr *glyphs)
+{
+ /* This won't work, so we need to wrap ProcRenderCompositeGlyphs */
+}
+
+/** Fill a rectangle on the appropriate screen by combining the color
+ * with the dest picture in the area specified by the list of
+ * rectangles. For a complete description see the protocol document of
+ * the RENDER library. */
+void dmxCompositeRects(CARD8 op,
+ PicturePtr pDst,
+ xRenderColor *color,
+ int nRect, xRectangle *rects)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pPictPriv = DMX_GET_PICT_PRIV(pDst);
+
+ DMX_UNWRAP(CompositeRects, dmxScreen, ps);
+#if 0
+ if (ps->CompositeRects)
+ ps->CompositeRects(op, pDst, color, nRect, rects);
+#endif
+
+ /* CompositeRects on back-end server */
+ if (pPictPriv->pict) {
+ XRenderFillRectangles(dmxScreen->beDisplay,
+ op,
+ pPictPriv->pict,
+ (XRenderColor *)color,
+ (XRectangle *)rects,
+ nRect);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ DMX_WRAP(CompositeRects, dmxCompositeRects, dmxScreen, ps);
+}
+
+/** Indexed color visuals are not yet supported. */
+Bool dmxInitIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
+{
+ return TRUE;
+}
+
+/** Indexed color visuals are not yet supported. */
+void dmxCloseIndexed(ScreenPtr pScreen, PictFormatPtr pFormat)
+{
+}
+
+/** Indexed color visuals are not yet supported. */
+void dmxUpdateIndexed(ScreenPtr pScreen, PictFormatPtr pFormat,
+ int ndef, xColorItem *pdef)
+{
+}
+
+/** Composite a list of trapezoids on the appropriate screen. For a
+ * complete description see the protocol document of the RENDER
+ * library. */
+void dmxTrapezoids(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int ntrap, xTrapezoid *traps)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
+
+ DMX_UNWRAP(Trapezoids, dmxScreen, ps);
+#if 0
+ if (ps->Trapezoids)
+ ps->Trapezoids(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, *traps);
+#endif
+
+ /* Draw trapezoids on back-end server */
+ if (pDstPriv->pict) {
+ XRenderPictFormat *pFormat;
+
+ pFormat = dmxFindFormat(dmxScreen, maskFormat);
+ if (!pFormat) {
+ /* FIXME: Error! */
+ }
+
+ XRenderCompositeTrapezoids(dmxScreen->beDisplay,
+ op,
+ pSrcPriv->pict,
+ pDstPriv->pict,
+ pFormat,
+ xSrc, ySrc,
+ (XTrapezoid *)traps,
+ ntrap);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ DMX_WRAP(Trapezoids, dmxTrapezoids, dmxScreen, ps);
+}
+
+/** Composite a list of triangles on the appropriate screen. For a
+ * complete description see the protocol document of the RENDER
+ * library. */
+void dmxTriangles(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int ntri, xTriangle *tris)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
+
+ DMX_UNWRAP(Triangles, dmxScreen, ps);
+#if 0
+ if (ps->Triangles)
+ ps->Triangles(op, pSrc, pDst, maskFormat, xSrc, ySrc, ntri, *tris);
+#endif
+
+ /* Draw trapezoids on back-end server */
+ if (pDstPriv->pict) {
+ XRenderPictFormat *pFormat;
+
+ pFormat = dmxFindFormat(dmxScreen, maskFormat);
+ if (!pFormat) {
+ /* FIXME: Error! */
+ }
+
+ XRenderCompositeTriangles(dmxScreen->beDisplay,
+ op,
+ pSrcPriv->pict,
+ pDstPriv->pict,
+ pFormat,
+ xSrc, ySrc,
+ (XTriangle *)tris,
+ ntri);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ DMX_WRAP(Triangles, dmxTriangles, dmxScreen, ps);
+}
+
+/** Composite a triangle strip on the appropriate screen. For a
+ * complete description see the protocol document of the RENDER
+ * library. */
+void dmxTriStrip(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
+
+ DMX_UNWRAP(TriStrip, dmxScreen, ps);
+#if 0
+ if (ps->TriStrip)
+ ps->TriStrip(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
+#endif
+
+ /* Draw trapezoids on back-end server */
+ if (pDstPriv->pict) {
+ XRenderPictFormat *pFormat;
+
+ pFormat = dmxFindFormat(dmxScreen, maskFormat);
+ if (!pFormat) {
+ /* FIXME: Error! */
+ }
+
+ XRenderCompositeTriStrip(dmxScreen->beDisplay,
+ op,
+ pSrcPriv->pict,
+ pDstPriv->pict,
+ pFormat,
+ xSrc, ySrc,
+ (XPointFixed *)points,
+ npoint);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ DMX_WRAP(TriStrip, dmxTriStrip, dmxScreen, ps);
+}
+
+/** Composite a triangle fan on the appropriate screen. For a complete
+ * description see the protocol document of the RENDER library. */
+void dmxTriFan(CARD8 op, PicturePtr pSrc, PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc, INT16 ySrc,
+ int npoint, xPointFixed *points)
+{
+ ScreenPtr pScreen = pDst->pDrawable->pScreen;
+ DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ dmxPictPrivPtr pSrcPriv = DMX_GET_PICT_PRIV(pSrc);
+ dmxPictPrivPtr pDstPriv = DMX_GET_PICT_PRIV(pDst);
+
+ DMX_UNWRAP(TriFan, dmxScreen, ps);
+#if 0
+ if (ps->TriFan)
+ ps->TriFan(op, pSrc, pDst, maskFormat, xSrc, ySrc, npoint, *points);
+#endif
+
+ /* Draw trapezoids on back-end server */
+ if (pDstPriv->pict) {
+ XRenderPictFormat *pFormat;
+
+ pFormat = dmxFindFormat(dmxScreen, maskFormat);
+ if (!pFormat) {
+ /* FIXME: Error! */
+ }
+
+ XRenderCompositeTriFan(dmxScreen->beDisplay,
+ op,
+ pSrcPriv->pict,
+ pDstPriv->pict,
+ pFormat,
+ xSrc, ySrc,
+ (XPointFixed *)points,
+ npoint);
+ dmxSync(dmxScreen, FALSE);
+ }
+
+ DMX_WRAP(TriFan, dmxTriFan, dmxScreen, ps);
+}
diff --git a/xorg-server/hw/xquartz/bundle/Makefile.am b/xorg-server/hw/xquartz/bundle/Makefile.am
index f8b96d8c4..3a09f7427 100644
--- a/xorg-server/hw/xquartz/bundle/Makefile.am
+++ b/xorg-server/hw/xquartz/bundle/Makefile.am
@@ -1,86 +1,90 @@
-include cpprules.in
-
-CPP_FILES_FLAGS = \
- -DLAUNCHD_ID_PREFIX="$(LAUNCHD_ID_PREFIX)" \
- -DAPPLE_APPLICATION_NAME="$(APPLE_APPLICATION_NAME)"
-
-if XQUARTZ_SPARKLE
-CPP_FILES_FLAGS += -DXQUARTZ_SPARKLE
-endif
-
-install-data-hook:
- $(srcdir)/mk_bundke.sh $(srcdir) $(builddir) $(DESTDIR)$(APPLE_APPLICATIONS_DIR)/$(APPLE_APPLICATION_NAME).app install
-
-uninstall-hook:
- $(RM) -rf $(DESTDIR)$(APPLE_APPLICATIONS_DIR)/$(APPLE_APPLICATION_NAME).app
-
-noinst_PRE = Info.plist.cpp
-noinst_DATA = $(noinst_PRE:plist.cpp=plist)
-
-CLEANFILES = $(noinst_DATA)
-
-resourcedir=$(libdir)/X11/xserver
-resource_DATA = Xquartz.plist
-
-EXTRA_DIST = \
- mk_bundke.sh \
- X11.sh \
- Info.plist.cpp \
- PkgInfo \
- $(resource_DATA) \
- Resources/da.lproj/InfoPlist.strings \
- Resources/da.lproj/Localizable.strings \
- Resources/da.lproj/main.nib/keyedobjects.nib \
- Resources/Dutch.lproj/InfoPlist.strings \
- Resources/Dutch.lproj/Localizable.strings \
- Resources/Dutch.lproj/main.nib/keyedobjects.nib \
- Resources/English.lproj/InfoPlist.strings \
- Resources/English.lproj/Localizable.strings \
- Resources/English.lproj/main.nib/designable.nib \
- Resources/English.lproj/main.nib/keyedobjects.nib \
- Resources/fi.lproj/InfoPlist.strings \
- Resources/fi.lproj/Localizable.strings \
- Resources/fi.lproj/main.nib/keyedobjects.nib \
- Resources/French.lproj/InfoPlist.strings \
- Resources/French.lproj/Localizable.strings \
- Resources/French.lproj/main.nib/keyedobjects.nib \
- Resources/German.lproj/InfoPlist.strings \
- Resources/German.lproj/Localizable.strings \
- Resources/German.lproj/main.nib/keyedobjects.nib \
- Resources/Italian.lproj/InfoPlist.strings \
- Resources/Italian.lproj/Localizable.strings \
- Resources/Italian.lproj/main.nib/keyedobjects.nib \
- Resources/Japanese.lproj/InfoPlist.strings \
- Resources/Japanese.lproj/Localizable.strings \
- Resources/Japanese.lproj/main.nib/keyedobjects.nib \
- Resources/ko.lproj/InfoPlist.strings \
- Resources/ko.lproj/Localizable.strings \
- Resources/ko.lproj/main.nib/keyedobjects.nib \
- Resources/no.lproj/InfoPlist.strings \
- Resources/no.lproj/Localizable.strings \
- Resources/no.lproj/main.nib/keyedobjects.nib \
- Resources/pl.lproj/InfoPlist.strings \
- Resources/pl.lproj/Localizable.strings \
- Resources/pl.lproj/main.nib/keyedobjects.nib \
- Resources/pt.lproj/InfoPlist.strings \
- Resources/pt.lproj/Localizable.strings \
- Resources/pt.lproj/main.nib/keyedobjects.nib \
- Resources/pt_PT.lproj/InfoPlist.strings \
- Resources/pt_PT.lproj/Localizable.strings \
- Resources/pt_PT.lproj/main.nib/keyedobjects.nib \
- Resources/ru.lproj/InfoPlist.strings \
- Resources/ru.lproj/Localizable.strings \
- Resources/ru.lproj/main.nib/keyedobjects.nib \
- Resources/Spanish.lproj/InfoPlist.strings \
- Resources/Spanish.lproj/Localizable.strings \
- Resources/Spanish.lproj/main.nib/keyedobjects.nib \
- Resources/sv.lproj/InfoPlist.strings \
- Resources/sv.lproj/Localizable.strings \
- Resources/sv.lproj/main.nib/keyedobjects.nib \
- Resources/X11.icns \
- Resources/zh_CN.lproj/InfoPlist.strings \
- Resources/zh_CN.lproj/Localizable.strings \
- Resources/zh_CN.lproj/main.nib/keyedobjects.nib \
- Resources/zh_TW.lproj/InfoPlist.strings \
- Resources/zh_TW.lproj/Localizable.strings \
- Resources/zh_TW.lproj/main.nib/keyedobjects.nib
+include cpprules.in
+
+CPP_FILES_FLAGS = \
+ -DLAUNCHD_ID_PREFIX="$(LAUNCHD_ID_PREFIX)" \
+ -DAPPLE_APPLICATION_NAME="$(APPLE_APPLICATION_NAME)"
+
+if XQUARTZ_SPARKLE
+CPP_FILES_FLAGS += -DXQUARTZ_SPARKLE
+endif
+
+install-data-hook:
+ $(srcdir)/mk_bundke.sh $(srcdir) $(builddir) $(DESTDIR)$(APPLE_APPLICATIONS_DIR)/$(APPLE_APPLICATION_NAME).app install
+
+uninstall-hook:
+ $(RM) -rf $(DESTDIR)$(APPLE_APPLICATIONS_DIR)/$(APPLE_APPLICATION_NAME).app
+
+noinst_PRE = Info.plist.cpp
+noinst_DATA = $(noinst_PRE:plist.cpp=plist)
+
+CLEANFILES = $(noinst_DATA)
+
+resourcedir=$(libdir)/X11/xserver
+resource_DATA = Xquartz.plist
+
+EXTRA_DIST = \
+ mk_bundke.sh \
+ X11.sh \
+ Info.plist.cpp \
+ PkgInfo \
+ $(resource_DATA) \
+ Resources/ar.lproj/InfoPlist.strings \
+ Resources/ar.lproj/Localizable.strings \
+ Resources/ar.lproj/main.nib/designable.nib \
+ Resources/ar.lproj/main.nib/keyedobjects.nib \
+ Resources/da.lproj/InfoPlist.strings \
+ Resources/da.lproj/Localizable.strings \
+ Resources/da.lproj/main.nib/keyedobjects.nib \
+ Resources/Dutch.lproj/InfoPlist.strings \
+ Resources/Dutch.lproj/Localizable.strings \
+ Resources/Dutch.lproj/main.nib/keyedobjects.nib \
+ Resources/English.lproj/InfoPlist.strings \
+ Resources/English.lproj/Localizable.strings \
+ Resources/English.lproj/main.nib/designable.nib \
+ Resources/English.lproj/main.nib/keyedobjects.nib \
+ Resources/fi.lproj/InfoPlist.strings \
+ Resources/fi.lproj/Localizable.strings \
+ Resources/fi.lproj/main.nib/keyedobjects.nib \
+ Resources/French.lproj/InfoPlist.strings \
+ Resources/French.lproj/Localizable.strings \
+ Resources/French.lproj/main.nib/keyedobjects.nib \
+ Resources/German.lproj/InfoPlist.strings \
+ Resources/German.lproj/Localizable.strings \
+ Resources/German.lproj/main.nib/keyedobjects.nib \
+ Resources/Italian.lproj/InfoPlist.strings \
+ Resources/Italian.lproj/Localizable.strings \
+ Resources/Italian.lproj/main.nib/keyedobjects.nib \
+ Resources/Japanese.lproj/InfoPlist.strings \
+ Resources/Japanese.lproj/Localizable.strings \
+ Resources/Japanese.lproj/main.nib/keyedobjects.nib \
+ Resources/ko.lproj/InfoPlist.strings \
+ Resources/ko.lproj/Localizable.strings \
+ Resources/ko.lproj/main.nib/keyedobjects.nib \
+ Resources/no.lproj/InfoPlist.strings \
+ Resources/no.lproj/Localizable.strings \
+ Resources/no.lproj/main.nib/keyedobjects.nib \
+ Resources/pl.lproj/InfoPlist.strings \
+ Resources/pl.lproj/Localizable.strings \
+ Resources/pl.lproj/main.nib/keyedobjects.nib \
+ Resources/pt.lproj/InfoPlist.strings \
+ Resources/pt.lproj/Localizable.strings \
+ Resources/pt.lproj/main.nib/keyedobjects.nib \
+ Resources/pt_PT.lproj/InfoPlist.strings \
+ Resources/pt_PT.lproj/Localizable.strings \
+ Resources/pt_PT.lproj/main.nib/keyedobjects.nib \
+ Resources/ru.lproj/InfoPlist.strings \
+ Resources/ru.lproj/Localizable.strings \
+ Resources/ru.lproj/main.nib/keyedobjects.nib \
+ Resources/Spanish.lproj/InfoPlist.strings \
+ Resources/Spanish.lproj/Localizable.strings \
+ Resources/Spanish.lproj/main.nib/keyedobjects.nib \
+ Resources/sv.lproj/InfoPlist.strings \
+ Resources/sv.lproj/Localizable.strings \
+ Resources/sv.lproj/main.nib/keyedobjects.nib \
+ Resources/X11.icns \
+ Resources/zh_CN.lproj/InfoPlist.strings \
+ Resources/zh_CN.lproj/Localizable.strings \
+ Resources/zh_CN.lproj/main.nib/keyedobjects.nib \
+ Resources/zh_TW.lproj/InfoPlist.strings \
+ Resources/zh_TW.lproj/Localizable.strings \
+ Resources/zh_TW.lproj/main.nib/keyedobjects.nib
diff --git a/xorg-server/include/dix.h b/xorg-server/include/dix.h
index dc86257fb..7fe4407e3 100644
--- a/xorg-server/include/dix.h
+++ b/xorg-server/include/dix.h
@@ -1,596 +1,602 @@
-/***********************************************************
-
-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.
-
-******************************************************************/
-
-#ifndef DIX_H
-#define DIX_H
-
-#include "callback.h"
-#include "gc.h"
-#include "window.h"
-#include "input.h"
-#include "cursor.h"
-#include "geext.h"
-#include "events.h"
-#include <X11/extensions/XI.h>
-
-#define EARLIER -1
-#define SAMETIME 0
-#define LATER 1
-
-#define NullClient ((ClientPtr) 0)
-#define REQUEST(type) \
- type *stuff = (type *)client->requestBuffer
-
-
-#define REQUEST_SIZE_MATCH(req)\
- if ((sizeof(req) >> 2) != client->req_len)\
- return(BadLength)
-
-#define REQUEST_AT_LEAST_SIZE(req) \
- if ((sizeof(req) >> 2) > client->req_len )\
- return(BadLength)
-
-#define REQUEST_FIXED_SIZE(req, n)\
- if (((sizeof(req) >> 2) > client->req_len) || \
- (((sizeof(req) + (n) + 3) >> 2) != client->req_len)) \
- return(BadLength)
-
-#define LEGAL_NEW_RESOURCE(id,client)\
- if (!LegalNewID(id,client)) \
- {\
- client->errorValue = id;\
- return(BadIDChoice);\
- }
-
-#define VALIDATE_DRAWABLE_AND_GC(drawID, pDraw, mode)\
- {\
- int rc = dixLookupDrawable(&(pDraw), drawID, client, M_ANY, mode);\
- if (rc != Success)\
- return rc;\
- rc = dixLookupGC(&(pGC), stuff->gc, client, DixUseAccess);\
- if (rc != Success)\
- return rc;\
- if ((pGC->depth != pDraw->depth) || (pGC->pScreen != pDraw->pScreen))\
- return (BadMatch);\
- }\
- if (pGC->serialNumber != pDraw->serialNumber)\
- ValidateGC(pDraw, pGC);
-
-
-#define WriteReplyToClient(pClient, size, pReply) { \
- if ((pClient)->swapped) \
- (*ReplySwapVector[((xReq *)(pClient)->requestBuffer)->reqType]) \
- (pClient, (int)(size), pReply); \
- else (void) WriteToClient(pClient, (int)(size), (char *)(pReply)); }
-
-#define WriteSwappedDataToClient(pClient, size, pbuf) \
- if ((pClient)->swapped) \
- (*(pClient)->pSwapReplyFunc)(pClient, (int)(size), pbuf); \
- else (void) WriteToClient (pClient, (int)(size), (char *)(pbuf));
-
-typedef struct _TimeStamp *TimeStampPtr;
-
-#ifndef _XTYPEDEF_CLIENTPTR
-typedef struct _Client *ClientPtr; /* also in misc.h */
-#define _XTYPEDEF_CLIENTPTR
-#endif
-
-typedef struct _WorkQueue *WorkQueuePtr;
-
-extern _X_EXPORT ClientPtr clients[MAXCLIENTS];
-extern _X_EXPORT ClientPtr serverClient;
-extern _X_EXPORT int currentMaxClients;
-extern _X_EXPORT char dispatchExceptionAtReset;
-
-typedef int HWEventQueueType;
-typedef HWEventQueueType* HWEventQueuePtr;
-
-extern _X_EXPORT HWEventQueuePtr checkForInput[2];
-
-typedef struct _TimeStamp {
- CARD32 months; /* really ~49.7 days */
- CARD32 milliseconds;
-} TimeStamp;
-
-/* dispatch.c */
-
-extern _X_EXPORT void SetInputCheck(
- HWEventQueuePtr /*c0*/,
- HWEventQueuePtr /*c1*/);
-
-extern _X_EXPORT void CloseDownClient(
- ClientPtr /*client*/);
-
-extern _X_EXPORT void UpdateCurrentTime(void);
-
-extern _X_EXPORT void UpdateCurrentTimeIf(void);
-
-extern _X_EXPORT int dixDestroyPixmap(
- pointer /*value*/,
- XID /*pid*/);
-
-extern _X_EXPORT void InitClient(
- ClientPtr /*client*/,
- int /*i*/,
- pointer /*ospriv*/);
-
-extern _X_EXPORT ClientPtr NextAvailableClient(
- pointer /*ospriv*/);
-
-extern _X_EXPORT void SendErrorToClient(
- ClientPtr /*client*/,
- unsigned int /*majorCode*/,
- unsigned int /*minorCode*/,
- XID /*resId*/,
- int /*errorCode*/);
-
-extern _X_EXPORT void MarkClientException(
- ClientPtr /*client*/);
-
-extern _X_HIDDEN Bool CreateConnectionBlock(void);
-/* dixutils.c */
-
-extern _X_EXPORT int CompareISOLatin1Lowered(
- unsigned char * /*a*/,
- int alen,
- unsigned char * /*b*/,
- int blen);
-
-extern _X_EXPORT int dixLookupWindow(
- WindowPtr *result,
- XID id,
- ClientPtr client,
- Mask access_mode);
-
-extern _X_EXPORT int dixLookupDrawable(
- DrawablePtr *result,
- XID id,
- ClientPtr client,
- Mask type_mask,
- Mask access_mode);
-
-extern _X_EXPORT int dixLookupGC(
- GCPtr *result,
- XID id,
- ClientPtr client,
- Mask access_mode);
-
-extern _X_EXPORT int dixLookupClient(
- ClientPtr *result,
- XID id,
- ClientPtr client,
- Mask access_mode);
-
-extern _X_EXPORT void NoopDDA(void);
-
-extern _X_EXPORT int AlterSaveSetForClient(
- ClientPtr /*client*/,
- WindowPtr /*pWin*/,
- unsigned /*mode*/,
- Bool /*toRoot*/,
- Bool /*map*/);
-
-extern _X_EXPORT void DeleteWindowFromAnySaveSet(
- WindowPtr /*pWin*/);
-
-extern _X_EXPORT void BlockHandler(
- pointer /*pTimeout*/,
- pointer /*pReadmask*/);
-
-extern _X_EXPORT void WakeupHandler(
- int /*result*/,
- pointer /*pReadmask*/);
-
-void
-EnableLimitedSchedulingLatency(void);
-
-void
-DisableLimitedSchedulingLatency(void);
-
-typedef void (* WakeupHandlerProcPtr)(
- pointer /* blockData */,
- int /* result */,
- pointer /* pReadmask */);
-
-extern _X_EXPORT Bool RegisterBlockAndWakeupHandlers(
- BlockHandlerProcPtr /*blockHandler*/,
- WakeupHandlerProcPtr /*wakeupHandler*/,
- pointer /*blockData*/);
-
-extern _X_EXPORT void RemoveBlockAndWakeupHandlers(
- BlockHandlerProcPtr /*blockHandler*/,
- WakeupHandlerProcPtr /*wakeupHandler*/,
- pointer /*blockData*/);
-
-extern _X_EXPORT void InitBlockAndWakeupHandlers(void);
-
-extern _X_EXPORT void ProcessWorkQueue(void);
-
-extern _X_EXPORT void ProcessWorkQueueZombies(void);
-
-extern _X_EXPORT Bool QueueWorkProc(
- Bool (* /*function*/)(
- ClientPtr /*clientUnused*/,
- pointer /*closure*/),
- ClientPtr /*client*/,
- pointer /*closure*/
-);
-
-typedef Bool (* ClientSleepProcPtr)(
- ClientPtr /*client*/,
- pointer /*closure*/);
-
-extern _X_EXPORT Bool ClientSleep(
- ClientPtr /*client*/,
- ClientSleepProcPtr /* function */,
- pointer /*closure*/);
-
-#ifndef ___CLIENTSIGNAL_DEFINED___
-#define ___CLIENTSIGNAL_DEFINED___
-extern _X_EXPORT Bool ClientSignal(
- ClientPtr /*client*/);
-#endif /* ___CLIENTSIGNAL_DEFINED___ */
-
-extern _X_EXPORT void ClientWakeup(
- ClientPtr /*client*/);
-
-extern _X_EXPORT Bool ClientIsAsleep(
- ClientPtr /*client*/);
-
-/* atom.c */
-
-extern _X_EXPORT Atom MakeAtom(
- const char * /*string*/,
- unsigned /*len*/,
- Bool /*makeit*/);
-
-extern _X_EXPORT Bool ValidAtom(
- Atom /*atom*/);
-
-extern _X_EXPORT const char *NameForAtom(
- Atom /*atom*/);
-
-extern _X_EXPORT void AtomError(void);
-
-extern _X_EXPORT void FreeAllAtoms(void);
-
-extern _X_EXPORT void InitAtoms(void);
-
-/* main.c */
-
-extern _X_EXPORT void SetVendorRelease(int release);
-
-extern _X_EXPORT void SetVendorString(char *string);
-
-/* events.c */
-
-extern void SetMaskForEvent(
- int /* deviceid */,
- Mask /* mask */,
- int /* event */);
-
-extern _X_EXPORT void ConfineToShape(
- DeviceIntPtr /* pDev */,
- RegionPtr /* shape */,
- int* /* px */,
- int* /* py */);
-
-extern _X_EXPORT Bool IsParent(
- WindowPtr /* maybeparent */,
- WindowPtr /* child */);
-
-extern _X_EXPORT WindowPtr GetCurrentRootWindow(DeviceIntPtr pDev);
-
-extern _X_EXPORT WindowPtr GetSpriteWindow(DeviceIntPtr pDev);
-
-
-extern _X_EXPORT void NoticeEventTime(InternalEvent *ev);
-
-extern void EnqueueEvent(
- InternalEvent * /* ev */,
- DeviceIntPtr /* device */);
-
-extern void ActivatePointerGrab(
- DeviceIntPtr /* mouse */,
- GrabPtr /* grab */,
- TimeStamp /* time */,
- Bool /* autoGrab */);
-
-extern void DeactivatePointerGrab(
- DeviceIntPtr /* mouse */);
-
-extern void ActivateKeyboardGrab(
- DeviceIntPtr /* keybd */,
- GrabPtr /* grab */,
- TimeStamp /* time */,
- Bool /* passive */);
-
-extern void DeactivateKeyboardGrab(
- DeviceIntPtr /* keybd */);
-
-extern BOOL ActivateFocusInGrab(
- DeviceIntPtr /* dev */,
- WindowPtr /* old */,
- WindowPtr /* win */);
-
-extern void AllowSome(
- ClientPtr /* client */,
- TimeStamp /* time */,
- DeviceIntPtr /* thisDev */,
- int /* newState */);
-
-extern void ReleaseActiveGrabs(
- ClientPtr client);
-
-extern _X_EXPORT int DeliverEventsToWindow(
- DeviceIntPtr /* pWin */,
- WindowPtr /* pWin */,
- xEventPtr /* pEvents */,
- int /* count */,
- Mask /* filter */,
- GrabPtr /* grab */);
-
-extern int DeliverDeviceEvents(
- WindowPtr /* pWin */,
- InternalEvent* /* event */,
- GrabPtr /* grab */,
- WindowPtr /* stopAt */,
- DeviceIntPtr /* dev */);
-
-extern void InitializeSprite(
- DeviceIntPtr /* pDev */,
- WindowPtr /* pWin */);
-
-extern void UpdateSpriteForScreen(
- DeviceIntPtr /* pDev */,
- ScreenPtr /* pScreen */);
-
-extern _X_EXPORT void WindowHasNewCursor(
- WindowPtr /* pWin */);
-
-extern Bool CheckDeviceGrabs(
- DeviceIntPtr /* device */,
- DeviceEvent* /* event */,
- int /* checkFirst */);
-
-extern void DeliverFocusedEvent(
- DeviceIntPtr /* keybd */,
- InternalEvent* /* event */,
- WindowPtr /* window */);
-
-extern void DeliverGrabbedEvent(
- InternalEvent* /* event */,
- DeviceIntPtr /* thisDev */,
- Bool /* deactivateGrab */);
-
-extern void FixKeyState(
- DeviceEvent* /* event */,
- DeviceIntPtr /* keybd */);
-
-extern void RecalculateDeliverableEvents(
- WindowPtr /* pWin */);
-
-extern _X_EXPORT int OtherClientGone(
- pointer /* value */,
- XID /* id */);
-
-extern void DoFocusEvents(
- DeviceIntPtr /* dev */,
- WindowPtr /* fromWin */,
- WindowPtr /* toWin */,
- int /* mode */);
-
-extern int SetInputFocus(
- ClientPtr /* client */,
- DeviceIntPtr /* dev */,
- Window /* focusID */,
- CARD8 /* revertTo */,
- Time /* ctime */,
- Bool /* followOK */);
-
-extern int GrabDevice(
- ClientPtr /* client */,
- DeviceIntPtr /* dev */,
- unsigned /* this_mode */,
- unsigned /* other_mode */,
- Window /* grabWindow */,
- unsigned /* ownerEvents */,
- Time /* ctime */,
- GrabMask* /* mask */,
- int /* grabtype */,
- Cursor /* curs */,
- Window /* confineToWin */,
- CARD8 * /* status */);
-
-extern void InitEvents(void);
-
-extern void CloseDownEvents(void);
-
-extern void DeleteWindowFromAnyEvents(
- WindowPtr /* pWin */,
- Bool /* freeResources */);
-
-
-extern Mask EventMaskForClient(
- WindowPtr /* pWin */,
- ClientPtr /* client */);
-
-
-
-extern _X_EXPORT int DeliverEvents(
- WindowPtr /*pWin*/,
- xEventPtr /*xE*/,
- int /*count*/,
- WindowPtr /*otherParent*/);
-
-extern Bool CheckMotion(
- DeviceEvent* /* ev */,
- DeviceIntPtr /* pDev */);
-
-extern _X_EXPORT void WriteEventsToClient(
- ClientPtr /*pClient*/,
- int /*count*/,
- xEventPtr /*events*/);
-
-extern _X_EXPORT int TryClientEvents(
- ClientPtr /*client*/,
- DeviceIntPtr /* device */,
- xEventPtr /*pEvents*/,
- int /*count*/,
- Mask /*mask*/,
- Mask /*filter*/,
- GrabPtr /*grab*/);
-
-extern _X_EXPORT void WindowsRestructured(void);
-
-extern int SetClientPointer(
- ClientPtr /* client */,
- DeviceIntPtr /* device */);
-
-extern _X_EXPORT DeviceIntPtr PickPointer(
- ClientPtr /* client */);
-
-extern _X_EXPORT DeviceIntPtr PickKeyboard(
- ClientPtr /* client */);
-
-extern Bool IsInterferingGrab(
- ClientPtr /* client */,
- DeviceIntPtr /* dev */,
- xEvent* /* events */);
-
-#ifdef PANORAMIX
-extern _X_EXPORT void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff);
-#endif
-
-#ifdef RANDR
-extern _X_EXPORT void
-ScreenRestructured (ScreenPtr pScreen);
-#endif
-
-extern _X_EXPORT int ffs(int i);
-
-
-/*
- * ServerGrabCallback stuff
- */
-
-extern _X_EXPORT CallbackListPtr ServerGrabCallback;
-
-typedef enum {SERVER_GRABBED, SERVER_UNGRABBED,
- CLIENT_PERVIOUS, CLIENT_IMPERVIOUS } ServerGrabState;
-
-typedef struct {
- ClientPtr client;
- ServerGrabState grabstate;
-} ServerGrabInfoRec;
-
-/*
- * EventCallback stuff
- */
-
-extern _X_EXPORT CallbackListPtr EventCallback;
-
-typedef struct {
- ClientPtr client;
- xEventPtr events;
- int count;
-} EventInfoRec;
-
-/*
- * DeviceEventCallback stuff
- */
-
-extern _X_EXPORT CallbackListPtr DeviceEventCallback;
-
-typedef struct {
- InternalEvent *event;
- DeviceIntPtr device;
-} DeviceEventInfoRec;
-
-extern int XItoCoreType(int xi_type);
-extern Bool DevHasCursor(DeviceIntPtr pDev);
-extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev);
-extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev);
-extern Bool IsPointerEvent(InternalEvent *event);
-extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev);
-
-extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
-extern _X_HIDDEN int CorePointerProc(DeviceIntPtr dev, int what);
-extern _X_HIDDEN int CoreKeyboardProc(DeviceIntPtr dev, int what);
-
-
-/*
- * These are deprecated compatibility functions and will be removed soon!
- * Please use the noted replacements instead.
- */
-/* replaced by dixLookupWindow */
-extern _X_EXPORT WindowPtr SecurityLookupWindow(
- XID id,
- ClientPtr client,
- Mask access_mode);
-/* replaced by dixLookupWindow */
-extern _X_EXPORT WindowPtr LookupWindow(
- XID id,
- ClientPtr client);
-
-/* replaced by dixLookupDrawable */
-extern _X_EXPORT pointer SecurityLookupDrawable(
- XID id,
- ClientPtr client,
- Mask access_mode);
-
-/* replaced by dixLookupDrawable */
-extern _X_EXPORT pointer LookupDrawable(
- XID id,
- ClientPtr client);
-
-/* replaced by dixLookupClient */
-extern _X_EXPORT ClientPtr LookupClient(
- XID id,
- ClientPtr client);
-
-#endif /* DIX_H */
+/***********************************************************
+
+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.
+
+******************************************************************/
+
+#ifndef DIX_H
+#define DIX_H
+
+#include "callback.h"
+#include "gc.h"
+#include "window.h"
+#include "input.h"
+#include "cursor.h"
+#include "geext.h"
+#include "events.h"
+#include <X11/extensions/XI.h>
+
+#define EARLIER -1
+#define SAMETIME 0
+#define LATER 1
+
+#define NullClient ((ClientPtr) 0)
+#define REQUEST(type) \
+ type *stuff = (type *)client->requestBuffer
+
+
+#define REQUEST_SIZE_MATCH(req)\
+ if ((sizeof(req) >> 2) != client->req_len)\
+ return(BadLength)
+
+#define REQUEST_AT_LEAST_SIZE(req) \
+ if ((sizeof(req) >> 2) > client->req_len )\
+ return(BadLength)
+
+#define REQUEST_FIXED_SIZE(req, n)\
+ if (((sizeof(req) >> 2) > client->req_len) || \
+ (((sizeof(req) + (n) + 3) >> 2) != client->req_len)) \
+ return(BadLength)
+
+#define LEGAL_NEW_RESOURCE(id,client)\
+ if (!LegalNewID(id,client)) \
+ {\
+ client->errorValue = id;\
+ return(BadIDChoice);\
+ }
+
+#define VALIDATE_DRAWABLE_AND_GC(drawID, pDraw, mode)\
+ {\
+ int rc = dixLookupDrawable(&(pDraw), drawID, client, M_ANY, mode);\
+ if (rc != Success)\
+ return rc;\
+ rc = dixLookupGC(&(pGC), stuff->gc, client, DixUseAccess);\
+ if (rc != Success)\
+ return rc;\
+ if ((pGC->depth != pDraw->depth) || (pGC->pScreen != pDraw->pScreen))\
+ return (BadMatch);\
+ }\
+ if (pGC->serialNumber != pDraw->serialNumber)\
+ ValidateGC(pDraw, pGC);
+
+
+#define WriteReplyToClient(pClient, size, pReply) { \
+ if ((pClient)->swapped) \
+ (*ReplySwapVector[((xReq *)(pClient)->requestBuffer)->reqType]) \
+ (pClient, (int)(size), pReply); \
+ else (void) WriteToClient(pClient, (int)(size), (char *)(pReply)); }
+
+#define WriteSwappedDataToClient(pClient, size, pbuf) \
+ if ((pClient)->swapped) \
+ (*(pClient)->pSwapReplyFunc)(pClient, (int)(size), pbuf); \
+ else (void) WriteToClient (pClient, (int)(size), (char *)(pbuf));
+
+typedef struct _TimeStamp *TimeStampPtr;
+
+#ifndef _XTYPEDEF_CLIENTPTR
+typedef struct _Client *ClientPtr; /* also in misc.h */
+#define _XTYPEDEF_CLIENTPTR
+#endif
+
+typedef struct _WorkQueue *WorkQueuePtr;
+
+extern _X_EXPORT ClientPtr clients[MAXCLIENTS];
+extern _X_EXPORT ClientPtr serverClient;
+extern _X_EXPORT int currentMaxClients;
+extern _X_EXPORT char dispatchExceptionAtReset;
+
+typedef int HWEventQueueType;
+typedef HWEventQueueType* HWEventQueuePtr;
+
+extern _X_EXPORT HWEventQueuePtr checkForInput[2];
+
+typedef struct _TimeStamp {
+ CARD32 months; /* really ~49.7 days */
+ CARD32 milliseconds;
+} TimeStamp;
+
+/* dispatch.c */
+
+extern _X_EXPORT void SetInputCheck(
+ HWEventQueuePtr /*c0*/,
+ HWEventQueuePtr /*c1*/);
+
+extern _X_EXPORT void CloseDownClient(
+ ClientPtr /*client*/);
+
+extern _X_EXPORT void UpdateCurrentTime(void);
+
+extern _X_EXPORT void UpdateCurrentTimeIf(void);
+
+extern _X_EXPORT int dixDestroyPixmap(
+ pointer /*value*/,
+ XID /*pid*/);
+
+extern _X_EXPORT void InitClient(
+ ClientPtr /*client*/,
+ int /*i*/,
+ pointer /*ospriv*/);
+
+extern _X_EXPORT ClientPtr NextAvailableClient(
+ pointer /*ospriv*/);
+
+extern _X_EXPORT void SendErrorToClient(
+ ClientPtr /*client*/,
+ unsigned int /*majorCode*/,
+ unsigned int /*minorCode*/,
+ XID /*resId*/,
+ int /*errorCode*/);
+
+extern _X_EXPORT void MarkClientException(
+ ClientPtr /*client*/);
+
+extern _X_HIDDEN Bool CreateConnectionBlock(void);
+/* dixutils.c */
+
+extern _X_EXPORT int CompareISOLatin1Lowered(
+ unsigned char * /*a*/,
+ int alen,
+ unsigned char * /*b*/,
+ int blen);
+
+extern _X_EXPORT int dixLookupWindow(
+ WindowPtr *result,
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+
+extern _X_EXPORT int dixLookupDrawable(
+ DrawablePtr *result,
+ XID id,
+ ClientPtr client,
+ Mask type_mask,
+ Mask access_mode);
+
+extern _X_EXPORT int dixLookupGC(
+ GCPtr *result,
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+
+extern _X_EXPORT int dixLookupFontable(
+ FontPtr *result,
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+
+extern _X_EXPORT int dixLookupClient(
+ ClientPtr *result,
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+
+extern _X_EXPORT void NoopDDA(void);
+
+extern _X_EXPORT int AlterSaveSetForClient(
+ ClientPtr /*client*/,
+ WindowPtr /*pWin*/,
+ unsigned /*mode*/,
+ Bool /*toRoot*/,
+ Bool /*map*/);
+
+extern _X_EXPORT void DeleteWindowFromAnySaveSet(
+ WindowPtr /*pWin*/);
+
+extern _X_EXPORT void BlockHandler(
+ pointer /*pTimeout*/,
+ pointer /*pReadmask*/);
+
+extern _X_EXPORT void WakeupHandler(
+ int /*result*/,
+ pointer /*pReadmask*/);
+
+void
+EnableLimitedSchedulingLatency(void);
+
+void
+DisableLimitedSchedulingLatency(void);
+
+typedef void (* WakeupHandlerProcPtr)(
+ pointer /* blockData */,
+ int /* result */,
+ pointer /* pReadmask */);
+
+extern _X_EXPORT Bool RegisterBlockAndWakeupHandlers(
+ BlockHandlerProcPtr /*blockHandler*/,
+ WakeupHandlerProcPtr /*wakeupHandler*/,
+ pointer /*blockData*/);
+
+extern _X_EXPORT void RemoveBlockAndWakeupHandlers(
+ BlockHandlerProcPtr /*blockHandler*/,
+ WakeupHandlerProcPtr /*wakeupHandler*/,
+ pointer /*blockData*/);
+
+extern _X_EXPORT void InitBlockAndWakeupHandlers(void);
+
+extern _X_EXPORT void ProcessWorkQueue(void);
+
+extern _X_EXPORT void ProcessWorkQueueZombies(void);
+
+extern _X_EXPORT Bool QueueWorkProc(
+ Bool (* /*function*/)(
+ ClientPtr /*clientUnused*/,
+ pointer /*closure*/),
+ ClientPtr /*client*/,
+ pointer /*closure*/
+);
+
+typedef Bool (* ClientSleepProcPtr)(
+ ClientPtr /*client*/,
+ pointer /*closure*/);
+
+extern _X_EXPORT Bool ClientSleep(
+ ClientPtr /*client*/,
+ ClientSleepProcPtr /* function */,
+ pointer /*closure*/);
+
+#ifndef ___CLIENTSIGNAL_DEFINED___
+#define ___CLIENTSIGNAL_DEFINED___
+extern _X_EXPORT Bool ClientSignal(
+ ClientPtr /*client*/);
+#endif /* ___CLIENTSIGNAL_DEFINED___ */
+
+extern _X_EXPORT void ClientWakeup(
+ ClientPtr /*client*/);
+
+extern _X_EXPORT Bool ClientIsAsleep(
+ ClientPtr /*client*/);
+
+/* atom.c */
+
+extern _X_EXPORT Atom MakeAtom(
+ const char * /*string*/,
+ unsigned /*len*/,
+ Bool /*makeit*/);
+
+extern _X_EXPORT Bool ValidAtom(
+ Atom /*atom*/);
+
+extern _X_EXPORT const char *NameForAtom(
+ Atom /*atom*/);
+
+extern _X_EXPORT void AtomError(void);
+
+extern _X_EXPORT void FreeAllAtoms(void);
+
+extern _X_EXPORT void InitAtoms(void);
+
+/* main.c */
+
+extern _X_EXPORT void SetVendorRelease(int release);
+
+extern _X_EXPORT void SetVendorString(char *string);
+
+/* events.c */
+
+extern void SetMaskForEvent(
+ int /* deviceid */,
+ Mask /* mask */,
+ int /* event */);
+
+extern _X_EXPORT void ConfineToShape(
+ DeviceIntPtr /* pDev */,
+ RegionPtr /* shape */,
+ int* /* px */,
+ int* /* py */);
+
+extern _X_EXPORT Bool IsParent(
+ WindowPtr /* maybeparent */,
+ WindowPtr /* child */);
+
+extern _X_EXPORT WindowPtr GetCurrentRootWindow(DeviceIntPtr pDev);
+
+extern _X_EXPORT WindowPtr GetSpriteWindow(DeviceIntPtr pDev);
+
+
+extern _X_EXPORT void NoticeEventTime(InternalEvent *ev);
+
+extern void EnqueueEvent(
+ InternalEvent * /* ev */,
+ DeviceIntPtr /* device */);
+
+extern void ActivatePointerGrab(
+ DeviceIntPtr /* mouse */,
+ GrabPtr /* grab */,
+ TimeStamp /* time */,
+ Bool /* autoGrab */);
+
+extern void DeactivatePointerGrab(
+ DeviceIntPtr /* mouse */);
+
+extern void ActivateKeyboardGrab(
+ DeviceIntPtr /* keybd */,
+ GrabPtr /* grab */,
+ TimeStamp /* time */,
+ Bool /* passive */);
+
+extern void DeactivateKeyboardGrab(
+ DeviceIntPtr /* keybd */);
+
+extern BOOL ActivateFocusInGrab(
+ DeviceIntPtr /* dev */,
+ WindowPtr /* old */,
+ WindowPtr /* win */);
+
+extern void AllowSome(
+ ClientPtr /* client */,
+ TimeStamp /* time */,
+ DeviceIntPtr /* thisDev */,
+ int /* newState */);
+
+extern void ReleaseActiveGrabs(
+ ClientPtr client);
+
+extern _X_EXPORT int DeliverEventsToWindow(
+ DeviceIntPtr /* pWin */,
+ WindowPtr /* pWin */,
+ xEventPtr /* pEvents */,
+ int /* count */,
+ Mask /* filter */,
+ GrabPtr /* grab */);
+
+extern int DeliverDeviceEvents(
+ WindowPtr /* pWin */,
+ InternalEvent* /* event */,
+ GrabPtr /* grab */,
+ WindowPtr /* stopAt */,
+ DeviceIntPtr /* dev */);
+
+extern void InitializeSprite(
+ DeviceIntPtr /* pDev */,
+ WindowPtr /* pWin */);
+
+extern void UpdateSpriteForScreen(
+ DeviceIntPtr /* pDev */,
+ ScreenPtr /* pScreen */);
+
+extern _X_EXPORT void WindowHasNewCursor(
+ WindowPtr /* pWin */);
+
+extern Bool CheckDeviceGrabs(
+ DeviceIntPtr /* device */,
+ DeviceEvent* /* event */,
+ int /* checkFirst */);
+
+extern void DeliverFocusedEvent(
+ DeviceIntPtr /* keybd */,
+ InternalEvent* /* event */,
+ WindowPtr /* window */);
+
+extern void DeliverGrabbedEvent(
+ InternalEvent* /* event */,
+ DeviceIntPtr /* thisDev */,
+ Bool /* deactivateGrab */);
+
+extern void FixKeyState(
+ DeviceEvent* /* event */,
+ DeviceIntPtr /* keybd */);
+
+extern void RecalculateDeliverableEvents(
+ WindowPtr /* pWin */);
+
+extern _X_EXPORT int OtherClientGone(
+ pointer /* value */,
+ XID /* id */);
+
+extern void DoFocusEvents(
+ DeviceIntPtr /* dev */,
+ WindowPtr /* fromWin */,
+ WindowPtr /* toWin */,
+ int /* mode */);
+
+extern int SetInputFocus(
+ ClientPtr /* client */,
+ DeviceIntPtr /* dev */,
+ Window /* focusID */,
+ CARD8 /* revertTo */,
+ Time /* ctime */,
+ Bool /* followOK */);
+
+extern int GrabDevice(
+ ClientPtr /* client */,
+ DeviceIntPtr /* dev */,
+ unsigned /* this_mode */,
+ unsigned /* other_mode */,
+ Window /* grabWindow */,
+ unsigned /* ownerEvents */,
+ Time /* ctime */,
+ GrabMask* /* mask */,
+ int /* grabtype */,
+ Cursor /* curs */,
+ Window /* confineToWin */,
+ CARD8 * /* status */);
+
+extern void InitEvents(void);
+
+extern void CloseDownEvents(void);
+
+extern void DeleteWindowFromAnyEvents(
+ WindowPtr /* pWin */,
+ Bool /* freeResources */);
+
+
+extern Mask EventMaskForClient(
+ WindowPtr /* pWin */,
+ ClientPtr /* client */);
+
+
+
+extern _X_EXPORT int DeliverEvents(
+ WindowPtr /*pWin*/,
+ xEventPtr /*xE*/,
+ int /*count*/,
+ WindowPtr /*otherParent*/);
+
+extern Bool CheckMotion(
+ DeviceEvent* /* ev */,
+ DeviceIntPtr /* pDev */);
+
+extern _X_EXPORT void WriteEventsToClient(
+ ClientPtr /*pClient*/,
+ int /*count*/,
+ xEventPtr /*events*/);
+
+extern _X_EXPORT int TryClientEvents(
+ ClientPtr /*client*/,
+ DeviceIntPtr /* device */,
+ xEventPtr /*pEvents*/,
+ int /*count*/,
+ Mask /*mask*/,
+ Mask /*filter*/,
+ GrabPtr /*grab*/);
+
+extern _X_EXPORT void WindowsRestructured(void);
+
+extern int SetClientPointer(
+ ClientPtr /* client */,
+ DeviceIntPtr /* device */);
+
+extern _X_EXPORT DeviceIntPtr PickPointer(
+ ClientPtr /* client */);
+
+extern _X_EXPORT DeviceIntPtr PickKeyboard(
+ ClientPtr /* client */);
+
+extern Bool IsInterferingGrab(
+ ClientPtr /* client */,
+ DeviceIntPtr /* dev */,
+ xEvent* /* events */);
+
+#ifdef PANORAMIX
+extern _X_EXPORT void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff);
+#endif
+
+#ifdef RANDR
+extern _X_EXPORT void
+ScreenRestructured (ScreenPtr pScreen);
+#endif
+
+extern _X_EXPORT int ffs(int i);
+
+
+/*
+ * ServerGrabCallback stuff
+ */
+
+extern _X_EXPORT CallbackListPtr ServerGrabCallback;
+
+typedef enum {SERVER_GRABBED, SERVER_UNGRABBED,
+ CLIENT_PERVIOUS, CLIENT_IMPERVIOUS } ServerGrabState;
+
+typedef struct {
+ ClientPtr client;
+ ServerGrabState grabstate;
+} ServerGrabInfoRec;
+
+/*
+ * EventCallback stuff
+ */
+
+extern _X_EXPORT CallbackListPtr EventCallback;
+
+typedef struct {
+ ClientPtr client;
+ xEventPtr events;
+ int count;
+} EventInfoRec;
+
+/*
+ * DeviceEventCallback stuff
+ */
+
+extern _X_EXPORT CallbackListPtr DeviceEventCallback;
+
+typedef struct {
+ InternalEvent *event;
+ DeviceIntPtr device;
+} DeviceEventInfoRec;
+
+extern int XItoCoreType(int xi_type);
+extern Bool DevHasCursor(DeviceIntPtr pDev);
+extern Bool _X_EXPORT IsPointerDevice( DeviceIntPtr dev);
+extern Bool _X_EXPORT IsKeyboardDevice(DeviceIntPtr dev);
+extern Bool IsPointerEvent(InternalEvent *event);
+extern _X_EXPORT Bool IsMaster(DeviceIntPtr dev);
+
+extern _X_HIDDEN void CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master);
+extern _X_HIDDEN int CorePointerProc(DeviceIntPtr dev, int what);
+extern _X_HIDDEN int CoreKeyboardProc(DeviceIntPtr dev, int what);
+
+
+/*
+ * These are deprecated compatibility functions and will be removed soon!
+ * Please use the noted replacements instead.
+ */
+/* replaced by dixLookupWindow */
+extern _X_EXPORT WindowPtr SecurityLookupWindow(
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+/* replaced by dixLookupWindow */
+extern _X_EXPORT WindowPtr LookupWindow(
+ XID id,
+ ClientPtr client);
+
+/* replaced by dixLookupDrawable */
+extern _X_EXPORT pointer SecurityLookupDrawable(
+ XID id,
+ ClientPtr client,
+ Mask access_mode);
+
+/* replaced by dixLookupDrawable */
+extern _X_EXPORT pointer LookupDrawable(
+ XID id,
+ ClientPtr client);
+
+/* replaced by dixLookupClient */
+extern _X_EXPORT ClientPtr LookupClient(
+ XID id,
+ ClientPtr client);
+
+#endif /* DIX_H */
diff --git a/xorg-server/include/os.h b/xorg-server/include/os.h
index 02857cb01..00b91701d 100644
--- a/xorg-server/include/os.h
+++ b/xorg-server/include/os.h
@@ -1,537 +1,537 @@
-/***********************************************************
-
-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.
-
-******************************************************************/
-
-
-#ifndef OS_H
-#define OS_H
-
-#include "misc.h"
-#include <stdarg.h>
-
-#define SCREEN_SAVER_ON 0
-#define SCREEN_SAVER_OFF 1
-#define SCREEN_SAVER_FORCER 2
-#define SCREEN_SAVER_CYCLE 3
-
-#ifndef MAX_REQUEST_SIZE
-#define MAX_REQUEST_SIZE 65535
-#endif
-#ifndef MAX_BIG_REQUEST_SIZE
-#define MAX_BIG_REQUEST_SIZE 4194303
-#endif
-
-typedef struct _FontPathRec *FontPathPtr;
-typedef struct _NewClientRec *NewClientPtr;
-
-#ifndef xalloc
-#define xnfalloc(size) XNFalloc((unsigned long)(size))
-#define xnfcalloc(_num, _size) XNFcalloc((unsigned long)(_num)*(unsigned long)(_size))
-#define xnfrealloc(ptr, size) XNFrealloc((pointer)(ptr), (unsigned long)(size))
-
-#define xalloc(size) Xalloc((unsigned long)(size))
-#define xcalloc(_num, _size) Xcalloc((unsigned long)(_num)*(unsigned long)(_size))
-#define xrealloc(ptr, size) Xrealloc((pointer)(ptr), (unsigned long)(size))
-#define xfree(ptr) Xfree((pointer)(ptr))
-#define xstrdup(s) Xstrdup(s)
-#define xnfstrdup(s) XNFstrdup(s)
-#endif
-
-#include <stdio.h>
-#include <stdarg.h>
-
-#ifdef DDXBEFORERESET
-extern void ddxBeforeReset (void);
-#endif
-
-#ifdef DDXOSVERRORF
-extern _X_EXPORT void (*OsVendorVErrorFProc)(const char *, va_list args);
-#endif
-
-extern _X_EXPORT int WaitForSomething(
- int* /*pClientsReady*/
-);
-
-extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client*/);
-
-extern _X_EXPORT Bool InsertFakeRequest(
- ClientPtr /*client*/,
- char* /*data*/,
- int /*count*/);
-
-extern _X_EXPORT void ResetCurrentRequest(ClientPtr /*client*/);
-
-extern _X_EXPORT void FlushAllOutput(void);
-
-extern _X_EXPORT void FlushIfCriticalOutputPending(void);
-
-extern _X_EXPORT void SetCriticalOutputPending(void);
-
-extern _X_EXPORT int WriteToClient(ClientPtr /*who*/, int /*count*/, const void* /*buf*/);
-
-extern _X_EXPORT void ResetOsBuffers(void);
-
-extern _X_EXPORT int TransIsListening(char *protocol);
-
-extern _X_EXPORT void InitConnectionLimits(void);
-
-extern _X_EXPORT void NotifyParentProcess(void);
-
-extern _X_EXPORT void CreateWellKnownSockets(void);
-
-extern _X_EXPORT void ResetWellKnownSockets(void);
-
-extern _X_EXPORT void CloseWellKnownConnections(void);
-
-extern _X_EXPORT XID AuthorizationIDOfClient(ClientPtr /*client*/);
-
-extern _X_EXPORT char *ClientAuthorized(
- ClientPtr /*client*/,
- unsigned int /*proto_n*/,
- char* /*auth_proto*/,
- unsigned int /*string_n*/,
- char* /*auth_string*/);
-
-extern _X_EXPORT Bool EstablishNewConnections(
- ClientPtr /*clientUnused*/,
- pointer /*closure*/);
-
-extern _X_EXPORT void CheckConnections(void);
-
-extern _X_EXPORT void CloseDownConnection(ClientPtr /*client*/);
-
-extern _X_EXPORT void AddGeneralSocket(int /*fd*/);
-
-extern _X_EXPORT void RemoveGeneralSocket(int /*fd*/);
-
-extern _X_EXPORT void AddEnabledDevice(int /*fd*/);
-
-extern _X_EXPORT void RemoveEnabledDevice(int /*fd*/);
-
-extern _X_EXPORT int OnlyListenToOneClient(ClientPtr /*client*/);
-
-extern _X_EXPORT void ListenToAllClients(void);
-
-extern _X_EXPORT void IgnoreClient(ClientPtr /*client*/);
-
-extern _X_EXPORT void AttendClient(ClientPtr /*client*/);
-
-extern _X_EXPORT void MakeClientGrabImpervious(ClientPtr /*client*/);
-
-extern _X_EXPORT void MakeClientGrabPervious(ClientPtr /*client*/);
-
-#ifdef XQUARTZ
-extern void ListenOnOpenFD(int /* fd */, int /* noxauth */);
-#endif
-
-extern _X_EXPORT CARD32 GetTimeInMillis(void);
-
-extern _X_EXPORT void AdjustWaitForDelay(
- pointer /*waitTime*/,
- unsigned long /*newdelay*/);
-
-typedef struct _OsTimerRec *OsTimerPtr;
-
-typedef CARD32 (*OsTimerCallback)(
- OsTimerPtr /* timer */,
- CARD32 /* time */,
- pointer /* arg */);
-
-extern _X_EXPORT void TimerInit(void);
-
-extern _X_EXPORT Bool TimerForce(OsTimerPtr /* timer */);
-
-#define TimerAbsolute (1<<0)
-#define TimerForceOld (1<<1)
-
-extern _X_EXPORT OsTimerPtr TimerSet(
- OsTimerPtr /* timer */,
- int /* flags */,
- CARD32 /* millis */,
- OsTimerCallback /* func */,
- pointer /* arg */);
-
-extern _X_EXPORT void TimerCheck(void);
-extern _X_EXPORT void TimerCancel(OsTimerPtr /* pTimer */);
-extern _X_EXPORT void TimerFree(OsTimerPtr /* pTimer */);
-
-extern _X_EXPORT void SetScreenSaverTimer(void);
-extern _X_EXPORT void FreeScreenSaverTimer(void);
-
-extern _X_EXPORT void AutoResetServer(int /*sig*/);
-
-extern _X_EXPORT void GiveUp(int /*sig*/);
-
-extern _X_EXPORT void UseMsg(void);
-
-extern _X_EXPORT void ProcessCommandLine(int /*argc*/, char* /*argv*/[]);
-
-extern _X_EXPORT int set_font_authorizations(
- char ** /* authorizations */,
- int * /*authlen */,
- pointer /* client */);
-
-#ifndef _HAVE_XALLOC_DECLS
-#define _HAVE_XALLOC_DECLS
-extern _X_EXPORT pointer Xalloc(unsigned long /*amount*/);
-extern _X_EXPORT pointer Xcalloc(unsigned long /*amount*/);
-extern _X_EXPORT pointer Xrealloc(pointer /*ptr*/, unsigned long /*amount*/);
-extern _X_EXPORT void Xfree(pointer /*ptr*/);
-#endif
-
-extern _X_EXPORT pointer XNFalloc(unsigned long /*amount*/);
-extern _X_EXPORT pointer XNFcalloc(unsigned long /*amount*/);
-extern _X_EXPORT pointer XNFrealloc(pointer /*ptr*/, unsigned long /*amount*/);
-
-extern _X_EXPORT char *Xstrdup(const char *s);
-extern _X_EXPORT char *XNFstrdup(const char *s);
-extern _X_EXPORT char *Xprintf(const char *fmt, ...);
-extern _X_EXPORT char *Xvprintf(const char *fmt, va_list va);
-extern _X_EXPORT char *XNFprintf(const char *fmt, ...);
-extern _X_EXPORT char *XNFvprintf(const char *fmt, va_list va);
-
-typedef void (*OsSigHandlerPtr)(int /* sig */);
-typedef int (*OsSigWrapperPtr)(int /* sig */);
-
-extern _X_EXPORT OsSigHandlerPtr OsSignal(int /* sig */, OsSigHandlerPtr /* handler */);
-extern _X_EXPORT OsSigWrapperPtr OsRegisterSigWrapper(OsSigWrapperPtr newWrap);
-
-extern _X_EXPORT int auditTrailLevel;
-
-extern _X_EXPORT void LockServer(void);
-extern _X_EXPORT void UnlockServer(void);
-
-extern _X_EXPORT int OsLookupColor(
- int /*screen*/,
- char * /*name*/,
- unsigned /*len*/,
- unsigned short * /*pred*/,
- unsigned short * /*pgreen*/,
- unsigned short * /*pblue*/);
-
-extern _X_EXPORT void OsInit(void);
-
-extern _X_EXPORT void OsCleanup(Bool);
-
-extern _X_EXPORT void OsVendorFatalError(void);
-
-extern _X_EXPORT void OsVendorInit(void);
-
-extern _X_EXPORT void OsBlockSignals (void);
-
-extern _X_EXPORT void OsReleaseSignals (void);
-
-extern _X_EXPORT void OsAbort (void);
-
-#if !defined(WIN32)
-extern _X_EXPORT int System(char *);
-extern _X_EXPORT pointer Popen(char *, char *);
-extern _X_EXPORT int Pclose(pointer);
-extern _X_EXPORT pointer Fopen(char *, char *);
-extern _X_EXPORT int Fclose(pointer);
-#else
-#define System(a) system(a)
-#define Popen(a,b) popen(a,b)
-#define Pclose(a) pclose(a)
-#define Fopen(a,b) fopen(a,b)
-#define Fclose(a) fclose(a)
-#endif
-
-extern _X_EXPORT void CheckUserParameters(int argc, char **argv, char **envp);
-extern _X_EXPORT void CheckUserAuthorization(void);
-
-extern _X_EXPORT int AddHost(
- ClientPtr /*client*/,
- int /*family*/,
- unsigned /*length*/,
- pointer /*pAddr*/);
-
-extern _X_EXPORT Bool ForEachHostInFamily (
- int /*family*/,
- Bool (* /*func*/ )(
- unsigned char * /* addr */,
- short /* len */,
- pointer /* closure */),
- pointer /*closure*/);
-
-extern _X_EXPORT int RemoveHost(
- ClientPtr /*client*/,
- int /*family*/,
- unsigned /*length*/,
- pointer /*pAddr*/);
-
-extern _X_EXPORT int GetHosts(
- pointer * /*data*/,
- int * /*pnHosts*/,
- int * /*pLen*/,
- BOOL * /*pEnabled*/);
-
-typedef struct sockaddr * sockaddrPtr;
-
-extern _X_EXPORT int InvalidHost(sockaddrPtr /*saddr*/, int /*len*/, ClientPtr client);
-
-extern _X_EXPORT int LocalClient(ClientPtr /* client */);
-
-extern _X_EXPORT int LocalClientCred(ClientPtr, int *, int *);
-
-#define LCC_UID_SET (1 << 0)
-#define LCC_GID_SET (1 << 1)
-#define LCC_PID_SET (1 << 2)
-#define LCC_ZID_SET (1 << 3)
-
-typedef struct {
- int fieldsSet; /* Bit mask of fields set */
- int euid; /* Effective uid */
- int egid; /* Primary effective group id */
- int nSuppGids; /* Number of supplementary group ids */
- int *pSuppGids; /* Array of supplementary group ids */
- int pid; /* Process id */
- int zoneid; /* Only set on Solaris 10 & later */
-} LocalClientCredRec;
-
-extern _X_EXPORT int GetLocalClientCreds(ClientPtr, LocalClientCredRec **);
-extern _X_EXPORT void FreeLocalClientCreds(LocalClientCredRec *);
-
-extern _X_EXPORT int ChangeAccessControl(ClientPtr /*client*/, int /*fEnabled*/);
-
-extern _X_EXPORT int GetAccessControl(void);
-
-
-extern _X_EXPORT void AddLocalHosts(void);
-
-extern _X_EXPORT void ResetHosts(char *display);
-
-extern _X_EXPORT void EnableLocalHost(void);
-
-extern _X_EXPORT void DisableLocalHost(void);
-
-extern _X_EXPORT void AccessUsingXdmcp(void);
-
-extern _X_EXPORT void DefineSelf(int /*fd*/);
-
-#if XDMCP
-extern _X_EXPORT void AugmentSelf(pointer /*from*/, int /*len*/);
-
-extern _X_EXPORT void RegisterAuthorizations(void);
-#endif
-
-extern _X_EXPORT void InitAuthorization(char * /*filename*/);
-
-/* extern int LoadAuthorization(void); */
-
-extern _X_EXPORT int AuthorizationFromID (
- XID id,
- unsigned short *name_lenp,
- char **namep,
- unsigned short *data_lenp,
- char **datap);
-
-extern _X_EXPORT XID CheckAuthorization(
- unsigned int /*namelength*/,
- char * /*name*/,
- unsigned int /*datalength*/,
- char * /*data*/,
- ClientPtr /*client*/,
- char ** /*reason*/
-);
-
-extern _X_EXPORT void ResetAuthorization(void);
-
-extern _X_EXPORT int RemoveAuthorization (
- unsigned short name_length,
- char *name,
- unsigned short data_length,
- char *data);
-
-extern _X_EXPORT int AddAuthorization(
- unsigned int /*name_length*/,
- char * /*name*/,
- unsigned int /*data_length*/,
- char * /*data*/);
-
-#ifdef XCSECURITY
-extern _X_EXPORT XID GenerateAuthorization(
- unsigned int /* name_length */,
- char * /* name */,
- unsigned int /* data_length */,
- char * /* data */,
- unsigned int * /* data_length_return */,
- char ** /* data_return */);
-#endif
-
-extern _X_EXPORT int ddxProcessArgument(int /*argc*/, char * /*argv*/ [], int /*i*/);
-
-extern _X_EXPORT void ddxUseMsg(void);
-
-/* int ReqLen(xReq *req, ClientPtr client)
- * Given a pointer to a *complete* request, return its length in bytes.
- * Note that if the request is a big request (as defined in the Big
- * Requests extension), the macro lies by returning 4 less than the
- * length that it actually occupies in the request buffer. This is so you
- * can blindly compare the length with the various sz_<request> constants
- * in Xproto.h without having to know/care about big requests.
- */
-#define ReqLen(_pxReq, _client) \
- ((_pxReq->length ? \
- (_client->swapped ? lswaps(_pxReq->length) : _pxReq->length) \
- : ((_client->swapped ? \
- lswapl(((CARD32*)_pxReq)[1]) : ((CARD32*)_pxReq)[1])-1) \
- ) << 2)
-
-/* otherReqTypePtr CastxReq(xReq *req, otherReqTypePtr)
- * Cast the given request to one of type otherReqTypePtr to access
- * fields beyond the length field.
- */
-#define CastxReq(_pxReq, otherReqTypePtr) \
- (_pxReq->length ? (otherReqTypePtr)_pxReq \
- : (otherReqTypePtr)(((CARD32*)_pxReq)+1))
-
-/* stuff for ReplyCallback */
-extern _X_EXPORT CallbackListPtr ReplyCallback;
-typedef struct {
- ClientPtr client;
- const void *replyData;
- unsigned long dataLenBytes;
- unsigned long bytesRemaining;
- Bool startOfReply;
-} ReplyInfoRec;
-
-/* stuff for FlushCallback */
-extern _X_EXPORT CallbackListPtr FlushCallback;
-
-extern _X_EXPORT void AbortDDX(void);
-extern _X_EXPORT void ddxGiveUp(void);
-extern _X_EXPORT int TimeSinceLastInputEvent(void);
-
-/* strcasecmp.c */
-#if NEED_STRCASECMP
-#define strcasecmp xstrcasecmp
-extern _X_EXPORT int xstrcasecmp(const char *s1, const char *s2);
-#endif
-
-#if NEED_STRNCASECMP
-#define strncasecmp xstrncasecmp
-extern _X_EXPORT int xstrncasecmp(const char *s1, const char *s2, size_t n);
-#endif
-
-#if NEED_STRCASESTR
-#define strcasestr xstrcasestr
-extern _X_EXPORT char *xstrcasestr(const char *s, const char *find);
-#endif
-
-#ifndef HAS_STRLCPY
-extern _X_EXPORT size_t strlcpy(char *dst, const char *src, size_t siz);
-extern _X_EXPORT size_t strlcat(char *dst, const char *src, size_t siz);
-#endif
-
-/* Logging. */
-typedef enum _LogParameter {
- XLOG_FLUSH,
- XLOG_SYNC,
- XLOG_VERBOSITY,
- XLOG_FILE_VERBOSITY
-} LogParameter;
-
-/* Flags for log messages. */
-typedef enum {
- X_PROBED, /* Value was probed */
- X_CONFIG, /* Value was given in the config file */
- X_DEFAULT, /* Value is a default */
- X_CMDLINE, /* Value was given on the command line */
- X_NOTICE, /* Notice */
- X_ERROR, /* Error message */
- X_WARNING, /* Warning message */
- X_INFO, /* Informational message */
- X_NONE, /* No prefix */
- X_NOT_IMPLEMENTED, /* Not implemented */
- X_UNKNOWN = -1 /* unknown -- this must always be last */
-} MessageType;
-
-/* XXX Need to check which GCC versions have the format(printf) attribute. */
-#if defined(__GNUC__) && (__GNUC__ > 2)
-#define _printf_attribute(a,b) __attribute((format(__printf__,a,b)))
-#else
-#define _printf_attribute(a,b) /**/
-#endif
-
-extern _X_EXPORT const char *LogInit(const char *fname, const char *backup);
-extern _X_EXPORT void LogClose(void);
-extern _X_EXPORT Bool LogSetParameter(LogParameter param, int value);
-extern _X_EXPORT void LogVWrite(int verb, const char *f, va_list args);
-extern _X_EXPORT void LogWrite(int verb, const char *f, ...) _printf_attribute(2,3);
-extern _X_EXPORT void LogVMessageVerb(MessageType type, int verb, const char *format,
- va_list args);
-extern _X_EXPORT void LogMessageVerb(MessageType type, int verb, const char *format,
- ...) _printf_attribute(3,4);
-extern _X_EXPORT void LogMessage(MessageType type, const char *format, ...)
- _printf_attribute(2,3);
-extern _X_EXPORT void FreeAuditTimer(void);
-extern _X_EXPORT void AuditF(const char *f, ...) _printf_attribute(1,2);
-extern _X_EXPORT void VAuditF(const char *f, va_list args);
-extern _X_EXPORT void FatalError(const char *f, ...) _printf_attribute(1,2)
-#if defined(__GNUC__) && (__GNUC__ > 2)
-__attribute((noreturn))
-#endif
-;
-
-#ifdef DEBUG
-#define DebugF ErrorF
-#else
-#define DebugF(...) /* */
-#endif
-
-extern _X_EXPORT void VErrorF(const char *f, va_list args);
-extern _X_EXPORT void ErrorF(const char *f, ...) _printf_attribute(1,2);
-extern _X_EXPORT void Error(char *str);
-extern _X_EXPORT void LogPrintMarkers(void);
-
-extern _X_EXPORT void xorg_backtrace(void);
-
-#ifdef _MSC_VER
-#define snprintf _snprintf
-#endif
-
-#endif /* OS_H */
+/***********************************************************
+
+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.
+
+******************************************************************/
+
+
+#ifndef OS_H
+#define OS_H
+
+#include "misc.h"
+#include <stdarg.h>
+
+#define SCREEN_SAVER_ON 0
+#define SCREEN_SAVER_OFF 1
+#define SCREEN_SAVER_FORCER 2
+#define SCREEN_SAVER_CYCLE 3
+
+#ifndef MAX_REQUEST_SIZE
+#define MAX_REQUEST_SIZE 65535
+#endif
+#ifndef MAX_BIG_REQUEST_SIZE
+#define MAX_BIG_REQUEST_SIZE 4194303
+#endif
+
+typedef struct _FontPathRec *FontPathPtr;
+typedef struct _NewClientRec *NewClientPtr;
+
+#ifndef xalloc
+#define xnfalloc(size) XNFalloc((unsigned long)(size))
+#define xnfcalloc(_num, _size) XNFcalloc((unsigned long)(_num)*(unsigned long)(_size))
+#define xnfrealloc(ptr, size) XNFrealloc((pointer)(ptr), (unsigned long)(size))
+
+#define xalloc(size) Xalloc((unsigned long)(size))
+#define xcalloc(_num, _size) Xcalloc((unsigned long)(_num)*(unsigned long)(_size))
+#define xrealloc(ptr, size) Xrealloc((pointer)(ptr), (unsigned long)(size))
+#define xfree(ptr) Xfree((pointer)(ptr))
+#define xstrdup(s) Xstrdup(s)
+#define xnfstrdup(s) XNFstrdup(s)
+#endif
+
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef DDXBEFORERESET
+extern void ddxBeforeReset (void);
+#endif
+
+#ifdef DDXOSVERRORF
+extern _X_EXPORT void (*OsVendorVErrorFProc)(const char *, va_list args);
+#endif
+
+extern _X_EXPORT int WaitForSomething(
+ int* /*pClientsReady*/
+);
+
+extern _X_EXPORT int ReadRequestFromClient(ClientPtr /*client*/);
+
+extern _X_EXPORT Bool InsertFakeRequest(
+ ClientPtr /*client*/,
+ char* /*data*/,
+ int /*count*/);
+
+extern _X_EXPORT void ResetCurrentRequest(ClientPtr /*client*/);
+
+extern _X_EXPORT void FlushAllOutput(void);
+
+extern _X_EXPORT void FlushIfCriticalOutputPending(void);
+
+extern _X_EXPORT void SetCriticalOutputPending(void);
+
+extern _X_EXPORT int WriteToClient(ClientPtr /*who*/, int /*count*/, const void* /*buf*/);
+
+extern _X_EXPORT void ResetOsBuffers(void);
+
+extern _X_EXPORT int TransIsListening(char *protocol);
+
+extern _X_EXPORT void InitConnectionLimits(void);
+
+extern _X_EXPORT void NotifyParentProcess(void);
+
+extern _X_EXPORT void CreateWellKnownSockets(void);
+
+extern _X_EXPORT void ResetWellKnownSockets(void);
+
+extern _X_EXPORT void CloseWellKnownConnections(void);
+
+extern _X_EXPORT XID AuthorizationIDOfClient(ClientPtr /*client*/);
+
+extern _X_EXPORT char *ClientAuthorized(
+ ClientPtr /*client*/,
+ unsigned int /*proto_n*/,
+ char* /*auth_proto*/,
+ unsigned int /*string_n*/,
+ char* /*auth_string*/);
+
+extern _X_EXPORT Bool EstablishNewConnections(
+ ClientPtr /*clientUnused*/,
+ pointer /*closure*/);
+
+extern _X_EXPORT void CheckConnections(void);
+
+extern _X_EXPORT void CloseDownConnection(ClientPtr /*client*/);
+
+extern _X_EXPORT void AddGeneralSocket(int /*fd*/);
+
+extern _X_EXPORT void RemoveGeneralSocket(int /*fd*/);
+
+extern _X_EXPORT void AddEnabledDevice(int /*fd*/);
+
+extern _X_EXPORT void RemoveEnabledDevice(int /*fd*/);
+
+extern _X_EXPORT int OnlyListenToOneClient(ClientPtr /*client*/);
+
+extern _X_EXPORT void ListenToAllClients(void);
+
+extern _X_EXPORT void IgnoreClient(ClientPtr /*client*/);
+
+extern _X_EXPORT void AttendClient(ClientPtr /*client*/);
+
+extern _X_EXPORT void MakeClientGrabImpervious(ClientPtr /*client*/);
+
+extern _X_EXPORT void MakeClientGrabPervious(ClientPtr /*client*/);
+
+#ifdef XQUARTZ
+extern void ListenOnOpenFD(int /* fd */, int /* noxauth */);
+#endif
+
+extern _X_EXPORT CARD32 GetTimeInMillis(void);
+
+extern _X_EXPORT void AdjustWaitForDelay(
+ pointer /*waitTime*/,
+ unsigned long /*newdelay*/);
+
+typedef struct _OsTimerRec *OsTimerPtr;
+
+typedef CARD32 (*OsTimerCallback)(
+ OsTimerPtr /* timer */,
+ CARD32 /* time */,
+ pointer /* arg */);
+
+extern _X_EXPORT void TimerInit(void);
+
+extern _X_EXPORT Bool TimerForce(OsTimerPtr /* timer */);
+
+#define TimerAbsolute (1<<0)
+#define TimerForceOld (1<<1)
+
+extern _X_EXPORT OsTimerPtr TimerSet(
+ OsTimerPtr /* timer */,
+ int /* flags */,
+ CARD32 /* millis */,
+ OsTimerCallback /* func */,
+ pointer /* arg */);
+
+extern _X_EXPORT void TimerCheck(void);
+extern _X_EXPORT void TimerCancel(OsTimerPtr /* pTimer */);
+extern _X_EXPORT void TimerFree(OsTimerPtr /* pTimer */);
+
+extern _X_EXPORT void SetScreenSaverTimer(void);
+extern _X_EXPORT void FreeScreenSaverTimer(void);
+
+extern _X_EXPORT void AutoResetServer(int /*sig*/);
+
+extern _X_EXPORT void GiveUp(int /*sig*/);
+
+extern _X_EXPORT void UseMsg(void);
+
+extern _X_EXPORT void ProcessCommandLine(int /*argc*/, char* /*argv*/[]);
+
+extern _X_EXPORT int set_font_authorizations(
+ char ** /* authorizations */,
+ int * /*authlen */,
+ pointer /* client */);
+
+#ifndef _HAVE_XALLOC_DECLS
+#define _HAVE_XALLOC_DECLS
+extern _X_EXPORT pointer Xalloc(unsigned long /*amount*/);
+extern _X_EXPORT pointer Xcalloc(unsigned long /*amount*/);
+extern _X_EXPORT pointer Xrealloc(pointer /*ptr*/, unsigned long /*amount*/);
+extern _X_EXPORT void Xfree(pointer /*ptr*/);
+#endif
+
+extern _X_EXPORT pointer XNFalloc(unsigned long /*amount*/);
+extern _X_EXPORT pointer XNFcalloc(unsigned long /*amount*/);
+extern _X_EXPORT pointer XNFrealloc(pointer /*ptr*/, unsigned long /*amount*/);
+
+extern _X_EXPORT char *Xstrdup(const char *s);
+extern _X_EXPORT char *XNFstrdup(const char *s);
+extern _X_EXPORT char *Xprintf(const char *fmt, ...);
+extern _X_EXPORT char *Xvprintf(const char *fmt, va_list va);
+extern _X_EXPORT char *XNFprintf(const char *fmt, ...);
+extern _X_EXPORT char *XNFvprintf(const char *fmt, va_list va);
+
+typedef void (*OsSigHandlerPtr)(int /* sig */);
+typedef int (*OsSigWrapperPtr)(int /* sig */);
+
+extern _X_EXPORT OsSigHandlerPtr OsSignal(int /* sig */, OsSigHandlerPtr /* handler */);
+extern _X_EXPORT OsSigWrapperPtr OsRegisterSigWrapper(OsSigWrapperPtr newWrap);
+
+extern _X_EXPORT int auditTrailLevel;
+
+extern _X_EXPORT void LockServer(void);
+extern _X_EXPORT void UnlockServer(void);
+
+extern _X_EXPORT int OsLookupColor(
+ int /*screen*/,
+ char * /*name*/,
+ unsigned /*len*/,
+ unsigned short * /*pred*/,
+ unsigned short * /*pgreen*/,
+ unsigned short * /*pblue*/);
+
+extern _X_EXPORT void OsInit(void);
+
+extern _X_EXPORT void OsCleanup(Bool);
+
+extern _X_EXPORT void OsVendorFatalError(void);
+
+extern _X_EXPORT void OsVendorInit(void);
+
+extern _X_EXPORT void OsBlockSignals (void);
+
+extern _X_EXPORT void OsReleaseSignals (void);
+
+extern _X_EXPORT void OsAbort (void);
+
+#if !defined(WIN32)
+extern _X_EXPORT int System(char *);
+extern _X_EXPORT pointer Popen(char *, char *);
+extern _X_EXPORT int Pclose(pointer);
+extern _X_EXPORT pointer Fopen(char *, char *);
+extern _X_EXPORT int Fclose(pointer);
+#else
+#define System(a) system(a)
+#define Popen(a,b) popen(a,b)
+#define Pclose(a) pclose(a)
+#define Fopen(a,b) fopen(a,b)
+#define Fclose(a) fclose(a)
+#endif
+
+extern _X_EXPORT void CheckUserParameters(int argc, char **argv, char **envp);
+extern _X_EXPORT void CheckUserAuthorization(void);
+
+extern _X_EXPORT int AddHost(
+ ClientPtr /*client*/,
+ int /*family*/,
+ unsigned /*length*/,
+ const void * /*pAddr*/);
+
+extern _X_EXPORT Bool ForEachHostInFamily (
+ int /*family*/,
+ Bool (* /*func*/ )(
+ unsigned char * /* addr */,
+ short /* len */,
+ pointer /* closure */),
+ pointer /*closure*/);
+
+extern _X_EXPORT int RemoveHost(
+ ClientPtr /*client*/,
+ int /*family*/,
+ unsigned /*length*/,
+ pointer /*pAddr*/);
+
+extern _X_EXPORT int GetHosts(
+ pointer * /*data*/,
+ int * /*pnHosts*/,
+ int * /*pLen*/,
+ BOOL * /*pEnabled*/);
+
+typedef struct sockaddr * sockaddrPtr;
+
+extern _X_EXPORT int InvalidHost(sockaddrPtr /*saddr*/, int /*len*/, ClientPtr client);
+
+extern _X_EXPORT int LocalClient(ClientPtr /* client */);
+
+extern _X_EXPORT int LocalClientCred(ClientPtr, int *, int *);
+
+#define LCC_UID_SET (1 << 0)
+#define LCC_GID_SET (1 << 1)
+#define LCC_PID_SET (1 << 2)
+#define LCC_ZID_SET (1 << 3)
+
+typedef struct {
+ int fieldsSet; /* Bit mask of fields set */
+ int euid; /* Effective uid */
+ int egid; /* Primary effective group id */
+ int nSuppGids; /* Number of supplementary group ids */
+ int *pSuppGids; /* Array of supplementary group ids */
+ int pid; /* Process id */
+ int zoneid; /* Only set on Solaris 10 & later */
+} LocalClientCredRec;
+
+extern _X_EXPORT int GetLocalClientCreds(ClientPtr, LocalClientCredRec **);
+extern _X_EXPORT void FreeLocalClientCreds(LocalClientCredRec *);
+
+extern _X_EXPORT int ChangeAccessControl(ClientPtr /*client*/, int /*fEnabled*/);
+
+extern _X_EXPORT int GetAccessControl(void);
+
+
+extern _X_EXPORT void AddLocalHosts(void);
+
+extern _X_EXPORT void ResetHosts(char *display);
+
+extern _X_EXPORT void EnableLocalHost(void);
+
+extern _X_EXPORT void DisableLocalHost(void);
+
+extern _X_EXPORT void AccessUsingXdmcp(void);
+
+extern _X_EXPORT void DefineSelf(int /*fd*/);
+
+#if XDMCP
+extern _X_EXPORT void AugmentSelf(pointer /*from*/, int /*len*/);
+
+extern _X_EXPORT void RegisterAuthorizations(void);
+#endif
+
+extern _X_EXPORT void InitAuthorization(char * /*filename*/);
+
+/* extern int LoadAuthorization(void); */
+
+extern _X_EXPORT int AuthorizationFromID (
+ XID id,
+ unsigned short *name_lenp,
+ char **namep,
+ unsigned short *data_lenp,
+ char **datap);
+
+extern _X_EXPORT XID CheckAuthorization(
+ unsigned int /*namelength*/,
+ const char * /*name*/,
+ unsigned int /*datalength*/,
+ const char * /*data*/,
+ ClientPtr /*client*/,
+ char ** /*reason*/
+);
+
+extern _X_EXPORT void ResetAuthorization(void);
+
+extern _X_EXPORT int RemoveAuthorization (
+ unsigned short name_length,
+ const char *name,
+ unsigned short data_length,
+ const char *data);
+
+extern _X_EXPORT int AddAuthorization(
+ unsigned int /*name_length*/,
+ const char * /*name*/,
+ unsigned int /*data_length*/,
+ char * /*data*/);
+
+#ifdef XCSECURITY
+extern _X_EXPORT XID GenerateAuthorization(
+ unsigned int /* name_length */,
+ const char * /* name */,
+ unsigned int /* data_length */,
+ const char * /* data */,
+ unsigned int * /* data_length_return */,
+ char ** /* data_return */);
+#endif
+
+extern _X_EXPORT int ddxProcessArgument(int /*argc*/, char * /*argv*/ [], int /*i*/);
+
+extern _X_EXPORT void ddxUseMsg(void);
+
+/* int ReqLen(xReq *req, ClientPtr client)
+ * Given a pointer to a *complete* request, return its length in bytes.
+ * Note that if the request is a big request (as defined in the Big
+ * Requests extension), the macro lies by returning 4 less than the
+ * length that it actually occupies in the request buffer. This is so you
+ * can blindly compare the length with the various sz_<request> constants
+ * in Xproto.h without having to know/care about big requests.
+ */
+#define ReqLen(_pxReq, _client) \
+ ((_pxReq->length ? \
+ (_client->swapped ? lswaps(_pxReq->length) : _pxReq->length) \
+ : ((_client->swapped ? \
+ lswapl(((CARD32*)_pxReq)[1]) : ((CARD32*)_pxReq)[1])-1) \
+ ) << 2)
+
+/* otherReqTypePtr CastxReq(xReq *req, otherReqTypePtr)
+ * Cast the given request to one of type otherReqTypePtr to access
+ * fields beyond the length field.
+ */
+#define CastxReq(_pxReq, otherReqTypePtr) \
+ (_pxReq->length ? (otherReqTypePtr)_pxReq \
+ : (otherReqTypePtr)(((CARD32*)_pxReq)+1))
+
+/* stuff for ReplyCallback */
+extern _X_EXPORT CallbackListPtr ReplyCallback;
+typedef struct {
+ ClientPtr client;
+ const void *replyData;
+ unsigned long dataLenBytes;
+ unsigned long bytesRemaining;
+ Bool startOfReply;
+} ReplyInfoRec;
+
+/* stuff for FlushCallback */
+extern _X_EXPORT CallbackListPtr FlushCallback;
+
+extern _X_EXPORT void AbortDDX(void);
+extern _X_EXPORT void ddxGiveUp(void);
+extern _X_EXPORT int TimeSinceLastInputEvent(void);
+
+/* strcasecmp.c */
+#if NEED_STRCASECMP
+#define strcasecmp xstrcasecmp
+extern _X_EXPORT int xstrcasecmp(const char *s1, const char *s2);
+#endif
+
+#if NEED_STRNCASECMP
+#define strncasecmp xstrncasecmp
+extern _X_EXPORT int xstrncasecmp(const char *s1, const char *s2, size_t n);
+#endif
+
+#if NEED_STRCASESTR
+#define strcasestr xstrcasestr
+extern _X_EXPORT char *xstrcasestr(const char *s, const char *find);
+#endif
+
+#ifndef HAS_STRLCPY
+extern _X_EXPORT size_t strlcpy(char *dst, const char *src, size_t siz);
+extern _X_EXPORT size_t strlcat(char *dst, const char *src, size_t siz);
+#endif
+
+/* Logging. */
+typedef enum _LogParameter {
+ XLOG_FLUSH,
+ XLOG_SYNC,
+ XLOG_VERBOSITY,
+ XLOG_FILE_VERBOSITY
+} LogParameter;
+
+/* Flags for log messages. */
+typedef enum {
+ X_PROBED, /* Value was probed */
+ X_CONFIG, /* Value was given in the config file */
+ X_DEFAULT, /* Value is a default */
+ X_CMDLINE, /* Value was given on the command line */
+ X_NOTICE, /* Notice */
+ X_ERROR, /* Error message */
+ X_WARNING, /* Warning message */
+ X_INFO, /* Informational message */
+ X_NONE, /* No prefix */
+ X_NOT_IMPLEMENTED, /* Not implemented */
+ X_UNKNOWN = -1 /* unknown -- this must always be last */
+} MessageType;
+
+/* XXX Need to check which GCC versions have the format(printf) attribute. */
+#if defined(__GNUC__) && (__GNUC__ > 2)
+#define _printf_attribute(a,b) __attribute((format(__printf__,a,b)))
+#else
+#define _printf_attribute(a,b) /**/
+#endif
+
+extern _X_EXPORT const char *LogInit(const char *fname, const char *backup);
+extern _X_EXPORT void LogClose(void);
+extern _X_EXPORT Bool LogSetParameter(LogParameter param, int value);
+extern _X_EXPORT void LogVWrite(int verb, const char *f, va_list args);
+extern _X_EXPORT void LogWrite(int verb, const char *f, ...) _printf_attribute(2,3);
+extern _X_EXPORT void LogVMessageVerb(MessageType type, int verb, const char *format,
+ va_list args);
+extern _X_EXPORT void LogMessageVerb(MessageType type, int verb, const char *format,
+ ...) _printf_attribute(3,4);
+extern _X_EXPORT void LogMessage(MessageType type, const char *format, ...)
+ _printf_attribute(2,3);
+extern _X_EXPORT void FreeAuditTimer(void);
+extern _X_EXPORT void AuditF(const char *f, ...) _printf_attribute(1,2);
+extern _X_EXPORT void VAuditF(const char *f, va_list args);
+extern _X_EXPORT void FatalError(const char *f, ...) _printf_attribute(1,2)
+#if defined(__GNUC__) && (__GNUC__ > 2)
+__attribute((noreturn))
+#endif
+;
+
+#ifdef DEBUG
+#define DebugF ErrorF
+#else
+#define DebugF(...) /* */
+#endif
+
+extern _X_EXPORT void VErrorF(const char *f, va_list args);
+extern _X_EXPORT void ErrorF(const char *f, ...) _printf_attribute(1,2);
+extern _X_EXPORT void Error(char *str);
+extern _X_EXPORT void LogPrintMarkers(void);
+
+extern _X_EXPORT void xorg_backtrace(void);
+
+#ifdef _MSC_VER
+#define snprintf _snprintf
+#endif
+
+#endif /* OS_H */
diff --git a/xorg-server/include/xkbsrv.h b/xorg-server/include/xkbsrv.h
index e59f8a626..7a93ccfcd 100644
--- a/xorg-server/include/xkbsrv.h
+++ b/xorg-server/include/xkbsrv.h
@@ -906,7 +906,7 @@ extern Bool XkbCopyKeymap(
XkbDescPtr /* dst */,
XkbDescPtr /* src */);
-extern Bool XkbCopyDeviceKeymap(
+extern _X_EXPORT Bool XkbCopyDeviceKeymap(
DeviceIntPtr /* dst */,
DeviceIntPtr /* src */);
diff --git a/xorg-server/mi/miarc.c b/xorg-server/mi/miarc.c
index 4a4a05dc0..bdc08459e 100644
--- a/xorg-server/mi/miarc.c
+++ b/xorg-server/mi/miarc.c
@@ -1,3690 +1,3594 @@
-/***********************************************************
-
-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.
-
-******************************************************************/
-/* Author: Keith Packard and Bob Scheifler */
-/* Warning: this code is toxic, do not dally very long here. */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <math.h>
-#include <X11/X.h>
-#include <X11/Xprotostr.h>
-#include "misc.h"
-#include "gcstruct.h"
-#include "scrnintstr.h"
-#include "pixmapstr.h"
-#include "windowstr.h"
-#include "mifpoly.h"
-#include "mi.h"
-#include "mifillarc.h"
-#include <X11/Xfuncproto.h>
-
-#ifdef _MSC_VER
-#define hypot _hypot
-#endif
-
-static double miDsin(double a);
-static double miDcos(double a);
-static double miDasin(double v);
-static double miDatan2(double dy, double dx);
-
-#ifndef HAVE_CBRT
-static double
-cbrt(double x)
-{
- if (x > 0.0)
- return pow(x, 1.0/3.0);
- else
- return -pow(-x, 1.0/3.0);
-}
-#endif
-
-/*
- * some interesting sematic interpretation of the protocol:
- *
- * Self intersecting arcs (i.e. those spanning 360 degrees)
- * never join with other arcs, and are drawn without caps
- * (unless on/off dashed, in which case each dash segment
- * is capped, except when the last segment meets the
- * first segment, when no caps are drawn)
- *
- * double dash arcs are drawn in two parts, first the
- * odd dashes (drawn in background) then the even dashes
- * (drawn in foreground). This means that overlapping
- * sections of foreground/background are drawn twice,
- * first in background then in foreground. The double-draw
- * occurs even when the function uses the destination values
- * (e.g. xor mode). This is the same way the wide-line
- * code works and should be "fixed".
- *
- */
-
-#undef max
-#undef min
-
-_X_INLINE static int max (const int x, const int y)
-{
- return x>y? x:y;
-}
-
-_X_INLINE static int min (const int x, const int y)
-{
- return x<y? x:y;
-}
-
-struct bound {
- double min, max;
-};
-
-struct ibound {
- int min, max;
-};
-
-#define boundedLe(value, bounds)\
- ((bounds).min <= (value) && (value) <= (bounds).max)
-
-struct line {
- double m, b;
- int valid;
-};
-
-#define intersectLine(y,line) (line.m * (y) + line.b)
-
-/*
- * these are all y value bounds
- */
-
-struct arc_bound {
- struct bound ellipse;
- struct bound inner;
- struct bound outer;
- struct bound right;
- struct bound left;
- struct ibound inneri;
- struct ibound outeri;
-};
-
-struct accelerators {
- double tail_y;
- double h2;
- double w2;
- double h4;
- double w4;
- double h2mw2;
- double h2l;
- double w2l;
- double fromIntX;
- double fromIntY;
- struct line left, right;
- int yorgu;
- int yorgl;
- int xorg;
-};
-
-struct arc_def {
- double w, h, l;
- double a0, a1;
-};
-
-# define todeg(xAngle) (((double) (xAngle)) / 64.0)
-
-# define RIGHT_END 0
-# define LEFT_END 1
-
-typedef struct _miArcJoin {
- int arcIndex0, arcIndex1;
- int phase0, phase1;
- int end0, end1;
-} miArcJoinRec, *miArcJoinPtr;
-
-typedef struct _miArcCap {
- int arcIndex;
- int end;
-} miArcCapRec, *miArcCapPtr;
-
-typedef struct _miArcFace {
- SppPointRec clock;
- SppPointRec center;
- SppPointRec counterClock;
-} miArcFaceRec, *miArcFacePtr;
-
-typedef struct _miArcData {
- xArc arc;
- int render; /* non-zero means render after drawing */
- int join; /* related join */
- int cap; /* related cap */
- int selfJoin; /* final dash meets first dash */
- miArcFaceRec bounds[2];
- double x0, y0, x1, y1;
-} miArcDataRec, *miArcDataPtr;
-
-/*
- * This is an entire sequence of arcs, computed and categorized according
- * to operation. miDashArcs generates either one or two of these.
- */
-
-typedef struct _miPolyArc {
- int narcs;
- miArcDataPtr arcs;
- int ncaps;
- miArcCapPtr caps;
- int njoins;
- miArcJoinPtr joins;
-} miPolyArcRec, *miPolyArcPtr;
-
-#define GCValsFunction 0
-#define GCValsForeground 1
-#define GCValsBackground 2
-#define GCValsLineWidth 3
-#define GCValsCapStyle 4
-#define GCValsJoinStyle 5
-#define GCValsMask (GCFunction | GCForeground | GCBackground | \
- GCLineWidth | GCCapStyle | GCJoinStyle)
-static CARD32 gcvals[6];
-
-static void fillSpans(DrawablePtr pDrawable, GCPtr pGC);
-static void newFinalSpan(int y, int xmin, int xmax);
-static void drawArc(xArc *tarc, int l, int a0, int a1, miArcFacePtr right,
- miArcFacePtr left);
-static void drawZeroArc(DrawablePtr pDraw, GCPtr pGC, xArc *tarc, int lw,
- miArcFacePtr left, miArcFacePtr right);
-static void miArcJoin(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pLeft,
- miArcFacePtr pRight, int xOrgLeft, int yOrgLeft,
- double xFtransLeft, double yFtransLeft,
- int xOrgRight, int yOrgRight,
- double xFtransRight, double yFtransRight);
-static void miArcCap(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pFace,
- int end, int xOrg, int yOrg, double xFtrans,
- double yFtrans);
-static void miRoundCap(DrawablePtr pDraw, GCPtr pGC, SppPointRec pCenter,
- SppPointRec pEnd, SppPointRec pCorner,
- SppPointRec pOtherCorner, int fLineEnd,
- int xOrg, int yOrg, double xFtrans, double yFtrans);
-static void miFreeArcs(miPolyArcPtr arcs, GCPtr pGC);
-static miPolyArcPtr miComputeArcs(xArc *parcs, int narcs, GCPtr pGC);
-static int miGetArcPts(SppArcPtr parc, int cpt, SppPointPtr *ppPts);
-
-# define CUBED_ROOT_2 1.2599210498948732038115849718451499938964
-# define CUBED_ROOT_4 1.5874010519681993173435330390930175781250
-
-/*
- * draw one segment of the arc using the arc spans generation routines
- */
-
-static void
-miArcSegment(
- DrawablePtr pDraw,
- GCPtr pGC,
- xArc tarc,
- miArcFacePtr right,
- miArcFacePtr left)
-{
- int l = pGC->lineWidth;
- int a0, a1, startAngle, endAngle;
- miArcFacePtr temp;
-
- if (!l)
- l = 1;
-
- if (tarc.width == 0 || tarc.height == 0) {
- drawZeroArc (pDraw, pGC, &tarc, l, left, right);
- return;
- }
-
- if (pGC->miTranslate) {
- tarc.x += pDraw->x;
- tarc.y += pDraw->y;
- }
-
- a0 = tarc.angle1;
- a1 = tarc.angle2;
- if (a1 > FULLCIRCLE)
- a1 = FULLCIRCLE;
- else if (a1 < -FULLCIRCLE)
- a1 = -FULLCIRCLE;
- if (a1 < 0) {
- startAngle = a0 + a1;
- endAngle = a0;
- temp = right;
- right = left;
- left = temp;
- } else {
- startAngle = a0;
- endAngle = a0 + a1;
- }
- /*
- * bounds check the two angles
- */
- if (startAngle < 0)
- startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE;
- if (startAngle >= FULLCIRCLE)
- startAngle = startAngle % FULLCIRCLE;
- if (endAngle < 0)
- endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE;
- if (endAngle > FULLCIRCLE)
- endAngle = (endAngle-1) % FULLCIRCLE + 1;
- if ((startAngle == endAngle) && a1) {
- startAngle = 0;
- endAngle = FULLCIRCLE;
- }
-
- drawArc (&tarc, l, startAngle, endAngle, right, left);
-}
-
-/*
-
-Three equations combine to describe the boundaries of the arc
-
-x^2/w^2 + y^2/h^2 = 1 ellipse itself
-(X-x)^2 + (Y-y)^2 = r^2 circle at (x, y) on the ellipse
-(Y-y) = (X-x)*w^2*y/(h^2*x) normal at (x, y) on the ellipse
-
-These lead to a quartic relating Y and y
-
-y^4 - (2Y)y^3 + (Y^2 + (h^4 - w^2*r^2)/(w^2 - h^2))y^2
- - (2Y*h^4/(w^2 - h^2))y + (Y^2*h^4)/(w^2 - h^2) = 0
-
-The reducible cubic obtained from this quartic is
-
-z^3 - (3N)z^2 - 2V = 0
-
-where
-
-N = (Y^2 + (h^4 - w^2*r^2/(w^2 - h^2)))/6
-V = w^2*r^2*Y^2*h^4/(4 *(w^2 - h^2)^2)
-
-Let
-
-t = z - N
-p = -N^2
-q = -N^3 - V
-
-Then we get
-
-t^3 + 3pt + 2q = 0
-
-The discriminant of this cubic is
-
-D = q^2 + p^3
-
-When D > 0, a real root is obtained as
-
-z = N + cbrt(-q+sqrt(D)) + cbrt(-q-sqrt(D))
-
-When D < 0, a real root is obtained as
-
-z = N - 2m*cos(acos(-q/m^3)/3)
-
-where
-
-m = sqrt(|p|) * sign(q)
-
-Given a real root Z of the cubic, the roots of the quartic are the roots
-of the two quadratics
-
-y^2 + ((b+A)/2)y + (Z + (bZ - d)/A) = 0
-
-where
-
-A = +/- sqrt(8Z + b^2 - 4c)
-b, c, d are the cubic, quadratic, and linear coefficients of the quartic
-
-Some experimentation is then required to determine which solutions
-correspond to the inner and outer boundaries.
-
-*/
-
-typedef struct {
- short lx, lw, rx, rw;
-} miArcSpan;
-
-typedef struct {
- miArcSpan *spans;
- int count1, count2, k;
- char top, bot, hole;
-} miArcSpanData;
-
-typedef struct {
- unsigned long lrustamp;
- unsigned short lw;
- unsigned short width, height;
- miArcSpanData *spdata;
-} arcCacheRec;
-
-#define CACHESIZE 25
-
-static void drawQuadrant(struct arc_def *def, struct accelerators *acc,
- int a0, int a1, int mask, miArcFacePtr right,
- miArcFacePtr left, miArcSpanData *spdata);
-
-static arcCacheRec arcCache[CACHESIZE];
-static unsigned long lrustamp;
-static arcCacheRec *lastCacheHit = &arcCache[0];
-static RESTYPE cacheType;
-
-static int
-miFreeArcCache (pointer data, XID id)
-{
- int k;
- arcCacheRec *cent;
-
- if (id)
- cacheType = 0;
-
- for (k = CACHESIZE, cent = &arcCache[0]; --k >= 0; cent++)
- {
- if (cent->spdata)
- {
- cent->lrustamp = 0;
- cent->lw = 0;
- xfree(cent->spdata);
- cent->spdata = NULL;
- }
- }
- lrustamp = 0;
- return Success;
-}
-
-static void
-miComputeCircleSpans(
- int lw,
- xArc *parc,
- miArcSpanData *spdata)
-{
- miArcSpan *span;
- int doinner;
- int x, y, e;
- int xk, yk, xm, ym, dx, dy;
- int slw, inslw;
- int inx = 0, iny, ine = 0;
- int inxk = 0, inyk = 0, inxm = 0, inym = 0;
-
- doinner = -lw;
- slw = parc->width - doinner;
- y = parc->height >> 1;
- dy = parc->height & 1;
- dx = 1 - dy;
- MIWIDEARCSETUP(x, y, dy, slw, e, xk, xm, yk, ym);
- inslw = parc->width + doinner;
- if (inslw > 0)
- {
- spdata->hole = spdata->top;
- MIWIDEARCSETUP(inx, iny, dy, inslw, ine, inxk, inxm, inyk, inym);
- }
- else
- {
- spdata->hole = FALSE;
- doinner = -y;
- }
- spdata->count1 = -doinner - spdata->top;
- spdata->count2 = y + doinner;
- span = spdata->spans;
- while (y)
- {
- MIFILLARCSTEP(slw);
- span->lx = dy - x;
- if (++doinner <= 0)
- {
- span->lw = slw;
- span->rx = 0;
- span->rw = span->lx + slw;
- }
- else
- {
- MIFILLINARCSTEP(inslw);
- span->lw = x - inx;
- span->rx = dy - inx + inslw;
- span->rw = inx - x + slw - inslw;
- }
- span++;
- }
- if (spdata->bot)
- {
- if (spdata->count2)
- spdata->count2--;
- else
- {
- if (lw > (int)parc->height)
- span[-1].rx = span[-1].rw = -((lw - (int)parc->height) >> 1);
- else
- span[-1].rw = 0;
- spdata->count1--;
- }
- }
-}
-
-static void
-miComputeEllipseSpans(
- int lw,
- xArc *parc,
- miArcSpanData *spdata)
-{
- miArcSpan *span;
- double w, h, r, xorg;
- double Hs, Hf, WH, K, Vk, Nk, Fk, Vr, N, Nc, Z, rs;
- double A, T, b, d, x, y, t, inx, outx = 0.0, hepp, hepm;
- int flip, solution;
-
- w = (double)parc->width / 2.0;
- h = (double)parc->height / 2.0;
- r = lw / 2.0;
- rs = r * r;
- Hs = h * h;
- WH = w * w - Hs;
- Nk = w * r;
- Vk = (Nk * Hs) / (WH + WH);
- Hf = Hs * Hs;
- Nk = (Hf - Nk * Nk) / WH;
- Fk = Hf / WH;
- hepp = h + EPSILON;
- hepm = h - EPSILON;
- K = h + ((lw - 1) >> 1);
- span = spdata->spans;
- if (parc->width & 1)
- xorg = .5;
- else
- xorg = 0.0;
- if (spdata->top)
- {
- span->lx = 0;
- span->lw = 1;
- span++;
- }
- spdata->count1 = 0;
- spdata->count2 = 0;
- spdata->hole = (spdata->top &&
- (int)parc->height * lw <= (int)(parc->width * parc->width) &&
- lw < (int)parc->height);
- for (; K > 0.0; K -= 1.0)
- {
- N = (K * K + Nk) / 6.0;
- Nc = N * N * N;
- Vr = Vk * K;
- t = Nc + Vr * Vr;
- d = Nc + t;
- if (d < 0.0) {
- d = Nc;
- b = N;
- if ( (b < 0.0) == (t < 0.0) )
- {
- b = -b;
- d = -d;
- }
- Z = N - 2.0 * b * cos(acos(-t / d) / 3.0);
- if ( (Z < 0.0) == (Vr < 0.0) )
- flip = 2;
- else
- flip = 1;
- }
- else
- {
- d = Vr * sqrt(d);
- Z = N + cbrt(t + d) + cbrt(t - d);
- flip = 0;
- }
- A = sqrt((Z + Z) - Nk);
- T = (Fk - Z) * K / A;
- inx = 0.0;
- solution = FALSE;
- b = -A + K;
- d = b * b - 4 * (Z + T);
- if (d >= 0)
- {
- d = sqrt(d);
- y = (b + d) / 2;
- if ((y >= 0.0) && (y < hepp))
- {
- solution = TRUE;
- if (y > hepm)
- y = h;
- t = y / h;
- x = w * sqrt(1 - (t * t));
- t = K - y;
- if (rs - (t * t) >= 0)
- t = sqrt(rs - (t * t));
- else
- t = 0;
- if (flip == 2)
- inx = x - t;
- else
- outx = x + t;
- }
- }
- b = A + K;
- d = b * b - 4 * (Z - T);
- /* Because of the large magnitudes involved, we lose enough precision
- * that sometimes we end up with a negative value near the axis, when
- * it should be positive. This is a workaround.
- */
- if (d < 0 && !solution)
- d = 0.0;
- if (d >= 0) {
- d = sqrt(d);
- y = (b + d) / 2;
- if (y < hepp)
- {
- if (y > hepm)
- y = h;
- t = y / h;
- x = w * sqrt(1 - (t * t));
- t = K - y;
- if (rs - (t * t) >= 0)
- inx = x - sqrt(rs - (t * t));
- else
- inx = x;
- }
- y = (b - d) / 2;
- if (y >= 0.0)
- {
- if (y > hepm)
- y = h;
- t = y / h;
- x = w * sqrt(1 - (t * t));
- t = K - y;
- if (rs - (t * t) >= 0)
- t = sqrt(rs - (t * t));
- else
- t = 0;
- if (flip == 1)
- inx = x - t;
- else
- outx = x + t;
- }
- }
- span->lx = ICEIL(xorg - outx);
- if (inx <= 0.0)
- {
- spdata->count1++;
- span->lw = ICEIL(xorg + outx) - span->lx;
- span->rx = ICEIL(xorg + inx);
- span->rw = -ICEIL(xorg - inx);
- }
- else
- {
- spdata->count2++;
- span->lw = ICEIL(xorg - inx) - span->lx;
- span->rx = ICEIL(xorg + inx);
- span->rw = ICEIL(xorg + outx) - span->rx;
- }
- span++;
- }
- if (spdata->bot)
- {
- outx = w + r;
- if (r >= h && r <= w)
- inx = 0.0;
- else if (Nk < 0.0 && -Nk < Hs)
- {
- inx = w * sqrt(1 + Nk / Hs) - sqrt(rs + Nk);
- if (inx > w - r)
- inx = w - r;
- }
- else
- inx = w - r;
- span->lx = ICEIL(xorg - outx);
- if (inx <= 0.0)
- {
- span->lw = ICEIL(xorg + outx) - span->lx;
- span->rx = ICEIL(xorg + inx);
- span->rw = -ICEIL(xorg - inx);
- }
- else
- {
- span->lw = ICEIL(xorg - inx) - span->lx;
- span->rx = ICEIL(xorg + inx);
- span->rw = ICEIL(xorg + outx) - span->rx;
- }
- }
- if (spdata->hole)
- {
- span = &spdata->spans[spdata->count1];
- span->lw = -span->lx;
- span->rx = 1;
- span->rw = span->lw;
- spdata->count1--;
- spdata->count2++;
- }
-}
-
-static double
-tailX(
- double K,
- struct arc_def *def,
- struct arc_bound *bounds,
- struct accelerators *acc)
-{
- double w, h, r;
- double Hs, Hf, WH, Vk, Nk, Fk, Vr, N, Nc, Z, rs;
- double A, T, b, d, x, y, t, hepp, hepm;
- int flip, solution;
- double xs[2];
- double *xp;
-
- w = def->w;
- h = def->h;
- r = def->l;
- rs = r * r;
- Hs = acc->h2;
- WH = -acc->h2mw2;
- Nk = def->w * r;
- Vk = (Nk * Hs) / (WH + WH);
- Hf = acc->h4;
- Nk = (Hf - Nk * Nk) / WH;
- if (K == 0.0) {
- if (Nk < 0.0 && -Nk < Hs) {
- xs[0] = w * sqrt(1 + Nk / Hs) - sqrt(rs + Nk);
- xs[1] = w - r;
- if (acc->left.valid && boundedLe(K, bounds->left) &&
- !boundedLe(K, bounds->outer) && xs[0] >= 0.0 && xs[1] >= 0.0)
- return xs[1];
- if (acc->right.valid && boundedLe(K, bounds->right) &&
- !boundedLe(K, bounds->inner) && xs[0] <= 0.0 && xs[1] <= 0.0)
- return xs[1];
- return xs[0];
- }
- return w - r;
- }
- Fk = Hf / WH;
- hepp = h + EPSILON;
- hepm = h - EPSILON;
- N = (K * K + Nk) / 6.0;
- Nc = N * N * N;
- Vr = Vk * K;
- xp = xs;
- xs[0] = 0.0;
- t = Nc + Vr * Vr;
- d = Nc + t;
- if (d < 0.0) {
- d = Nc;
- b = N;
- if ( (b < 0.0) == (t < 0.0) )
- {
- b = -b;
- d = -d;
- }
- Z = N - 2.0 * b * cos(acos(-t / d) / 3.0);
- if ( (Z < 0.0) == (Vr < 0.0) )
- flip = 2;
- else
- flip = 1;
- }
- else
- {
- d = Vr * sqrt(d);
- Z = N + cbrt(t + d) + cbrt(t - d);
- flip = 0;
- }
- A = sqrt((Z + Z) - Nk);
- T = (Fk - Z) * K / A;
- solution = FALSE;
- b = -A + K;
- d = b * b - 4 * (Z + T);
- if (d >= 0 && flip == 2)
- {
- d = sqrt(d);
- y = (b + d) / 2;
- if ((y >= 0.0) && (y < hepp))
- {
- solution = TRUE;
- if (y > hepm)
- y = h;
- t = y / h;
- x = w * sqrt(1 - (t * t));
- t = K - y;
- if (rs - (t * t) >= 0)
- t = sqrt(rs - (t * t));
- else
- t = 0;
- *xp++ = x - t;
- }
- }
- b = A + K;
- d = b * b - 4 * (Z - T);
- /* Because of the large magnitudes involved, we lose enough precision
- * that sometimes we end up with a negative value near the axis, when
- * it should be positive. This is a workaround.
- */
- if (d < 0 && !solution)
- d = 0.0;
- if (d >= 0) {
- d = sqrt(d);
- y = (b + d) / 2;
- if (y < hepp)
- {
- if (y > hepm)
- y = h;
- t = y / h;
- x = w * sqrt(1 - (t * t));
- t = K - y;
- if (rs - (t * t) >= 0)
- *xp++ = x - sqrt(rs - (t * t));
- else
- *xp++ = x;
- }
- y = (b - d) / 2;
- if (y >= 0.0 && flip == 1)
- {
- if (y > hepm)
- y = h;
- t = y / h;
- x = w * sqrt(1 - (t * t));
- t = K - y;
- if (rs - (t * t) >= 0)
- t = sqrt(rs - (t * t));
- else
- t = 0;
- *xp++ = x - t;
- }
- }
- if (xp > &xs[1]) {
- if (acc->left.valid && boundedLe(K, bounds->left) &&
- !boundedLe(K, bounds->outer) && xs[0] >= 0.0 && xs[1] >= 0.0)
- return xs[1];
- if (acc->right.valid && boundedLe(K, bounds->right) &&
- !boundedLe(K, bounds->inner) && xs[0] <= 0.0 && xs[1] <= 0.0)
- return xs[1];
- }
- return xs[0];
-}
-
-static miArcSpanData *
-miComputeWideEllipse(
- int lw,
- xArc *parc,
- Bool *mustFree)
-{
- miArcSpanData *spdata;
- arcCacheRec *cent, *lruent;
- int k;
- arcCacheRec fakeent;
-
- if (!lw)
- lw = 1;
- if (parc->height <= 1500)
- {
- *mustFree = FALSE;
- cent = lastCacheHit;
- if (cent->lw == lw &&
- cent->width == parc->width && cent->height == parc->height)
- {
- cent->lrustamp = ++lrustamp;
- return cent->spdata;
- }
- lruent = &arcCache[0];
- for (k = CACHESIZE, cent = lruent; --k >= 0; cent++)
- {
- if (cent->lw == lw &&
- cent->width == parc->width && cent->height == parc->height)
- {
- cent->lrustamp = ++lrustamp;
- lastCacheHit = cent;
- return cent->spdata;
- }
- if (cent->lrustamp < lruent->lrustamp)
- lruent = cent;
- }
- if (!cacheType)
- {
- cacheType = CreateNewResourceType(miFreeArcCache, "miArcCache");
- (void) AddResource(FakeClientID(0), cacheType, NULL);
- }
- } else {
- lruent = &fakeent;
- lruent->spdata = NULL;
- *mustFree = TRUE;
- }
- k = (parc->height >> 1) + ((lw - 1) >> 1);
- spdata = lruent->spdata;
- if (!spdata || spdata->k != k)
- {
- if (spdata)
- xfree(spdata);
- spdata = xalloc(sizeof(miArcSpanData) + sizeof(miArcSpan) * (k + 2));
- lruent->spdata = spdata;
- if (!spdata)
- {
- lruent->lrustamp = 0;
- lruent->lw = 0;
- return spdata;
- }
- spdata->spans = (miArcSpan *)(spdata + 1);
- spdata->k = k;
- }
- spdata->top = !(lw & 1) && !(parc->width & 1);
- spdata->bot = !(parc->height & 1);
- lruent->lrustamp = ++lrustamp;
- lruent->lw = lw;
- lruent->width = parc->width;
- lruent->height = parc->height;
- if (lruent != &fakeent)
- lastCacheHit = lruent;
- if (parc->width == parc->height)
- miComputeCircleSpans(lw, parc, spdata);
- else
- miComputeEllipseSpans(lw, parc, spdata);
- return spdata;
-}
-
-static void
-miFillWideEllipse(
- DrawablePtr pDraw,
- GCPtr pGC,
- xArc *parc)
-{
- DDXPointPtr points;
- DDXPointPtr pts;
- int *widths;
- int *wids;
- miArcSpanData *spdata;
- Bool mustFree;
- miArcSpan *span;
- int xorg, yorgu, yorgl;
- int n;
-
- yorgu = parc->height + pGC->lineWidth;
- n = (sizeof(int) * 2) * yorgu;
- widths = xalloc(n + (sizeof(DDXPointRec) * 2) * yorgu);
- if (!widths)
- return;
- points = (DDXPointPtr)((char *)widths + n);
- spdata = miComputeWideEllipse((int)pGC->lineWidth, parc, &mustFree);
- if (!spdata)
- {
- xfree(widths);
- return;
- }
- pts = points;
- wids = widths;
- span = spdata->spans;
- xorg = parc->x + (parc->width >> 1);
- yorgu = parc->y + (parc->height >> 1);
- yorgl = yorgu + (parc->height & 1);
- if (pGC->miTranslate)
- {
- xorg += pDraw->x;
- yorgu += pDraw->y;
- yorgl += pDraw->y;
- }
- yorgu -= spdata->k;
- yorgl += spdata->k;
- if (spdata->top)
- {
- pts->x = xorg;
- pts->y = yorgu - 1;
- pts++;
- *wids++ = 1;
- span++;
- }
- for (n = spdata->count1; --n >= 0; )
- {
- pts[0].x = xorg + span->lx;
- pts[0].y = yorgu;
- wids[0] = span->lw;
- pts[1].x = pts[0].x;
- pts[1].y = yorgl;
- wids[1] = wids[0];
- yorgu++;
- yorgl--;
- pts += 2;
- wids += 2;
- span++;
- }
- if (spdata->hole)
- {
- pts[0].x = xorg;
- pts[0].y = yorgl;
- wids[0] = 1;
- pts++;
- wids++;
- }
- for (n = spdata->count2; --n >= 0; )
- {
- pts[0].x = xorg + span->lx;
- pts[0].y = yorgu;
- wids[0] = span->lw;
- pts[1].x = xorg + span->rx;
- pts[1].y = pts[0].y;
- wids[1] = span->rw;
- pts[2].x = pts[0].x;
- pts[2].y = yorgl;
- wids[2] = wids[0];
- pts[3].x = pts[1].x;
- pts[3].y = pts[2].y;
- wids[3] = wids[1];
- yorgu++;
- yorgl--;
- pts += 4;
- wids += 4;
- span++;
- }
- if (spdata->bot)
- {
- if (span->rw <= 0)
- {
- pts[0].x = xorg + span->lx;
- pts[0].y = yorgu;
- wids[0] = span->lw;
- pts++;
- wids++;
- }
- else
- {
- pts[0].x = xorg + span->lx;
- pts[0].y = yorgu;
- wids[0] = span->lw;
- pts[1].x = xorg + span->rx;
- pts[1].y = pts[0].y;
- wids[1] = span->rw;
- pts += 2;
- wids += 2;
- }
- }
- if (mustFree)
- xfree(spdata);
- (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
-
- xfree(widths);
-}
-
-/*
- * miPolyArc strategy:
- *
- * If arc is zero width and solid, we don't have to worry about the rasterop
- * or join styles. For wide solid circles, we use a fast integer algorithm.
- * For wide solid ellipses, we use special case floating point code.
- * Otherwise, we set up pDrawTo and pGCTo according to the rasterop, then
- * draw using pGCTo and pDrawTo. If the raster-op was "tricky," that is,
- * if it involves the destination, then we use PushPixels to move the bits
- * from the scratch drawable to pDraw. (See the wide line code for a
- * fuller explanation of this.)
- */
-
-void
-miPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs)
-{
- int i;
- xArc *parc;
- int xMin, xMax, yMin, yMax;
- int pixmapWidth = 0, pixmapHeight = 0;
- int xOrg = 0, yOrg = 0;
- int width;
- Bool fTricky;
- DrawablePtr pDrawTo;
- CARD32 fg, bg;
- GCPtr pGCTo;
- miPolyArcPtr polyArcs;
- int cap[2], join[2];
- int iphase;
- int halfWidth;
-
- width = pGC->lineWidth;
- if(width == 0 && pGC->lineStyle == LineSolid)
- {
- for(i = narcs, parc = parcs; --i >= 0; parc++)
- miArcSegment( pDraw, pGC, *parc,
- (miArcFacePtr) 0, (miArcFacePtr) 0 );
- fillSpans (pDraw, pGC);
- }
- else
- {
- if ((pGC->lineStyle == LineSolid) && narcs)
- {
- while (parcs->width && parcs->height &&
- (parcs->angle2 >= FULLCIRCLE ||
- parcs->angle2 <= -FULLCIRCLE))
- {
- miFillWideEllipse(pDraw, pGC, parcs);
- if (!--narcs)
- return;
- parcs++;
- }
- }
-
- /* Set up pDrawTo and pGCTo based on the rasterop */
- switch(pGC->alu)
- {
- case GXclear: /* 0 */
- case GXcopy: /* src */
- case GXcopyInverted: /* NOT src */
- case GXset: /* 1 */
- fTricky = FALSE;
- pDrawTo = pDraw;
- pGCTo = pGC;
- break;
- default:
- fTricky = TRUE;
-
- /* find bounding box around arcs */
- xMin = yMin = MAXSHORT;
- xMax = yMax = MINSHORT;
-
- for(i = narcs, parc = parcs; --i >= 0; parc++)
- {
- xMin = min (xMin, parc->x);
- yMin = min (yMin, parc->y);
- xMax = max (xMax, (parc->x + (int) parc->width));
- yMax = max (yMax, (parc->y + (int) parc->height));
- }
-
- /* expand box to deal with line widths */
- halfWidth = (width + 1)/2;
- xMin -= halfWidth;
- yMin -= halfWidth;
- xMax += halfWidth;
- yMax += halfWidth;
-
- /* compute pixmap size; limit it to size of drawable */
- xOrg = max(xMin, 0);
- yOrg = max(yMin, 0);
- pixmapWidth = min(xMax, pDraw->width) - xOrg;
- pixmapHeight = min(yMax, pDraw->height) - yOrg;
-
- /* if nothing left, return */
- if ( (pixmapWidth <= 0) || (pixmapHeight <= 0) ) return;
-
- for(i = narcs, parc = parcs; --i >= 0; parc++)
- {
- parc->x -= xOrg;
- parc->y -= yOrg;
- }
- if (pGC->miTranslate)
- {
- xOrg += pDraw->x;
- yOrg += pDraw->y;
- }
-
- /* set up scratch GC */
-
- pGCTo = GetScratchGC(1, pDraw->pScreen);
- if (!pGCTo)
- return;
- gcvals[GCValsFunction] = GXcopy;
- gcvals[GCValsForeground] = 1;
- gcvals[GCValsBackground] = 0;
- gcvals[GCValsLineWidth] = pGC->lineWidth;
- gcvals[GCValsCapStyle] = pGC->capStyle;
- gcvals[GCValsJoinStyle] = pGC->joinStyle;
- dixChangeGC(NullClient, pGCTo, GCValsMask, gcvals, NULL);
-
- /* allocate a 1 bit deep pixmap of the appropriate size, and
- * validate it */
- pDrawTo = (DrawablePtr)(*pDraw->pScreen->CreatePixmap)
- (pDraw->pScreen, pixmapWidth, pixmapHeight, 1,
- CREATE_PIXMAP_USAGE_SCRATCH);
- if (!pDrawTo)
- {
- FreeScratchGC(pGCTo);
- return;
- }
- ValidateGC(pDrawTo, pGCTo);
- miClearDrawable(pDrawTo, pGCTo);
- }
-
- fg = pGC->fgPixel;
- bg = pGC->bgPixel;
- if ((pGC->fillStyle == FillTiled) ||
- (pGC->fillStyle == FillOpaqueStippled))
- bg = fg; /* the protocol sez these don't cause color changes */
-
- polyArcs = miComputeArcs (parcs, narcs, pGC);
-
- if (!polyArcs)
- {
- if (fTricky) {
- (*pDraw->pScreen->DestroyPixmap) ((PixmapPtr)pDrawTo);
- FreeScratchGC (pGCTo);
- }
- return;
- }
-
- cap[0] = cap[1] = 0;
- join[0] = join[1] = 0;
- for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0);
- iphase >= 0;
- iphase--)
- {
- if (iphase == 1) {
- dixChangeGC (NullClient, pGC, GCForeground, &bg, NULL);
- ValidateGC (pDraw, pGC);
- } else if (pGC->lineStyle == LineDoubleDash) {
- dixChangeGC (NullClient, pGC, GCForeground, &fg, NULL);
- ValidateGC (pDraw, pGC);
- }
- for (i = 0; i < polyArcs[iphase].narcs; i++) {
- miArcDataPtr arcData;
-
- arcData = &polyArcs[iphase].arcs[i];
- miArcSegment(pDrawTo, pGCTo, arcData->arc,
- &arcData->bounds[RIGHT_END],
- &arcData->bounds[LEFT_END]);
- if (polyArcs[iphase].arcs[i].render) {
- fillSpans (pDrawTo, pGCTo);
- /*
- * don't cap self-joining arcs
- */
- if (polyArcs[iphase].arcs[i].selfJoin &&
- cap[iphase] < polyArcs[iphase].arcs[i].cap)
- cap[iphase]++;
- while (cap[iphase] < polyArcs[iphase].arcs[i].cap) {
- int arcIndex, end;
- miArcDataPtr arcData0;
-
- arcIndex = polyArcs[iphase].caps[cap[iphase]].arcIndex;
- end = polyArcs[iphase].caps[cap[iphase]].end;
- arcData0 = &polyArcs[iphase].arcs[arcIndex];
- miArcCap (pDrawTo, pGCTo,
- &arcData0->bounds[end], end,
- arcData0->arc.x, arcData0->arc.y,
- (double) arcData0->arc.width / 2.0,
- (double) arcData0->arc.height / 2.0);
- ++cap[iphase];
- }
- while (join[iphase] < polyArcs[iphase].arcs[i].join) {
- int arcIndex0, arcIndex1, end0, end1;
- int phase0, phase1;
- miArcDataPtr arcData0, arcData1;
- miArcJoinPtr joinp;
-
- joinp = &polyArcs[iphase].joins[join[iphase]];
- arcIndex0 = joinp->arcIndex0;
- end0 = joinp->end0;
- arcIndex1 = joinp->arcIndex1;
- end1 = joinp->end1;
- phase0 = joinp->phase0;
- phase1 = joinp->phase1;
- arcData0 = &polyArcs[phase0].arcs[arcIndex0];
- arcData1 = &polyArcs[phase1].arcs[arcIndex1];
- miArcJoin (pDrawTo, pGCTo,
- &arcData0->bounds[end0],
- &arcData1->bounds[end1],
- arcData0->arc.x, arcData0->arc.y,
- (double) arcData0->arc.width / 2.0,
- (double) arcData0->arc.height / 2.0,
- arcData1->arc.x, arcData1->arc.y,
- (double) arcData1->arc.width / 2.0,
- (double) arcData1->arc.height / 2.0);
- ++join[iphase];
- }
- if (fTricky) {
- if (pGC->serialNumber != pDraw->serialNumber)
- ValidateGC (pDraw, pGC);
- (*pGC->ops->PushPixels) (pGC, (PixmapPtr)pDrawTo,
- pDraw, pixmapWidth, pixmapHeight, xOrg, yOrg);
- miClearDrawable ((DrawablePtr) pDrawTo, pGCTo);
- }
- }
- }
- }
- miFreeArcs(polyArcs, pGC);
-
- if(fTricky)
- {
- (*pGCTo->pScreen->DestroyPixmap)((PixmapPtr)pDrawTo);
- FreeScratchGC(pGCTo);
- }
- }
-}
-
-static double
-angleBetween (SppPointRec center, SppPointRec point1, SppPointRec point2)
-{
- double a1, a2, a;
-
- /*
- * reflect from X coordinates back to ellipse
- * coordinates -- y increasing upwards
- */
- a1 = miDatan2 (- (point1.y - center.y), point1.x - center.x);
- a2 = miDatan2 (- (point2.y - center.y), point2.x - center.x);
- a = a2 - a1;
- if (a <= -180.0)
- a += 360.0;
- else if (a > 180.0)
- a -= 360.0;
- return a;
-}
-
-static void
-translateBounds (
- miArcFacePtr b,
- int x,
- int y,
- double fx,
- double fy)
-{
- fx += x;
- fy += y;
- b->clock.x -= fx;
- b->clock.y -= fy;
- b->center.x -= fx;
- b->center.y -= fy;
- b->counterClock.x -= fx;
- b->counterClock.y -= fy;
-}
-
-static void
-miArcJoin(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pLeft,
- miArcFacePtr pRight, int xOrgLeft, int yOrgLeft,
- double xFtransLeft, double yFtransLeft,
- int xOrgRight, int yOrgRight,
- double xFtransRight, double yFtransRight)
-{
- SppPointRec center, corner, otherCorner;
- SppPointRec poly[5], e;
- SppPointPtr pArcPts;
- int cpt;
- SppArcRec arc;
- miArcFaceRec Right, Left;
- int polyLen = 0;
- int xOrg, yOrg;
- double xFtrans, yFtrans;
- double a;
- double ae, ac2, ec2, bc2, de;
- double width;
-
- xOrg = (xOrgRight + xOrgLeft) / 2;
- yOrg = (yOrgRight + yOrgLeft) / 2;
- xFtrans = (xFtransLeft + xFtransRight) / 2;
- yFtrans = (yFtransLeft + yFtransRight) / 2;
- Right = *pRight;
- translateBounds (&Right, xOrg - xOrgRight, yOrg - yOrgRight,
- xFtrans - xFtransRight, yFtrans - yFtransRight);
- Left = *pLeft;
- translateBounds (&Left, xOrg - xOrgLeft, yOrg - yOrgLeft,
- xFtrans - xFtransLeft, yFtrans - yFtransLeft);
- pRight = &Right;
- pLeft = &Left;
-
- if (pRight->clock.x == pLeft->counterClock.x &&
- pRight->clock.y == pLeft->counterClock.y)
- return;
- center = pRight->center;
- if (0 <= (a = angleBetween (center, pRight->clock, pLeft->counterClock))
- && a <= 180.0)
- {
- corner = pRight->clock;
- otherCorner = pLeft->counterClock;
- } else {
- a = angleBetween (center, pLeft->clock, pRight->counterClock);
- corner = pLeft->clock;
- otherCorner = pRight->counterClock;
- }
- switch (pGC->joinStyle) {
- case JoinRound:
- width = (pGC->lineWidth ? (double)pGC->lineWidth : (double)1);
-
- arc.x = center.x - width/2;
- arc.y = center.y - width/2;
- arc.width = width;
- arc.height = width;
- arc.angle1 = -miDatan2 (corner.y - center.y, corner.x - center.x);
- arc.angle2 = a;
- pArcPts = xalloc (3 * sizeof (SppPointRec));
- if (!pArcPts)
- return;
- pArcPts[0].x = otherCorner.x;
- pArcPts[0].y = otherCorner.y;
- pArcPts[1].x = center.x;
- pArcPts[1].y = center.y;
- pArcPts[2].x = corner.x;
- pArcPts[2].y = corner.y;
- if( (cpt = miGetArcPts(&arc, 3, &pArcPts)) )
- {
- /* by drawing with miFillSppPoly and setting the endpoints of the arc
- * to be the corners, we assure that the cap will meet up with the
- * rest of the line */
- miFillSppPoly(pDraw, pGC, cpt, pArcPts, xOrg, yOrg, xFtrans, yFtrans);
- }
- xfree(pArcPts);
- return;
- case JoinMiter:
- /*
- * don't miter arcs with less than 11 degrees between them
- */
- if (a < 169.0) {
- poly[0] = corner;
- poly[1] = center;
- poly[2] = otherCorner;
- bc2 = (corner.x - otherCorner.x) * (corner.x - otherCorner.x) +
- (corner.y - otherCorner.y) * (corner.y - otherCorner.y);
- ec2 = bc2 / 4;
- ac2 = (corner.x - center.x) * (corner.x - center.x) +
- (corner.y - center.y) * (corner.y - center.y);
- ae = sqrt (ac2 - ec2);
- de = ec2 / ae;
- e.x = (corner.x + otherCorner.x) / 2;
- e.y = (corner.y + otherCorner.y) / 2;
- poly[3].x = e.x + de * (e.x - center.x) / ae;
- poly[3].y = e.y + de * (e.y - center.y) / ae;
- poly[4] = corner;
- polyLen = 5;
- break;
- }
- case JoinBevel:
- poly[0] = corner;
- poly[1] = center;
- poly[2] = otherCorner;
- poly[3] = corner;
- polyLen = 4;
- break;
- }
- miFillSppPoly (pDraw, pGC, polyLen, poly, xOrg, yOrg, xFtrans, yFtrans);
-}
-
-/*ARGSUSED*/
-static void
-miArcCap (
- DrawablePtr pDraw,
- GCPtr pGC,
- miArcFacePtr pFace,
- int end,
- int xOrg,
- int yOrg,
- double xFtrans,
- double yFtrans)
-{
- SppPointRec corner, otherCorner, center, endPoint, poly[5];
-
- corner = pFace->clock;
- otherCorner = pFace->counterClock;
- center = pFace->center;
- switch (pGC->capStyle) {
- case CapProjecting:
- poly[0].x = otherCorner.x;
- poly[0].y = otherCorner.y;
- poly[1].x = corner.x;
- poly[1].y = corner.y;
- poly[2].x = corner.x -
- (center.y - corner.y);
- poly[2].y = corner.y +
- (center.x - corner.x);
- poly[3].x = otherCorner.x -
- (otherCorner.y - center.y);
- poly[3].y = otherCorner.y +
- (otherCorner.x - center.x);
- poly[4].x = otherCorner.x;
- poly[4].y = otherCorner.y;
- miFillSppPoly (pDraw, pGC, 5, poly, xOrg, yOrg, xFtrans, yFtrans);
- break;
- case CapRound:
- /*
- * miRoundCap just needs these to be unequal.
- */
- endPoint = center;
- endPoint.x = endPoint.x + 100;
- miRoundCap (pDraw, pGC, center, endPoint, corner, otherCorner, 0,
- -xOrg, -yOrg, xFtrans, yFtrans);
- break;
- }
-}
-
-/* MIROUNDCAP -- a private helper function
- * Put Rounded cap on end. pCenter is the center of this end of the line
- * pEnd is the center of the other end of the line. pCorner is one of the
- * two corners at this end of the line.
- * NOTE: pOtherCorner must be counter-clockwise from pCorner.
- */
-/*ARGSUSED*/
-static void
-miRoundCap(
- DrawablePtr pDraw,
- GCPtr pGC,
- SppPointRec pCenter,
- SppPointRec pEnd,
- SppPointRec pCorner,
- SppPointRec pOtherCorner,
- int fLineEnd,
- int xOrg,
- int yOrg,
- double xFtrans,
- double yFtrans)
-{
- int cpt;
- double width;
- SppArcRec arc;
- SppPointPtr pArcPts;
-
- width = (pGC->lineWidth ? (double)pGC->lineWidth : (double)1);
-
- arc.x = pCenter.x - width/2;
- arc.y = pCenter.y - width/2;
- arc.width = width;
- arc.height = width;
- arc.angle1 = -miDatan2 (pCorner.y - pCenter.y, pCorner.x - pCenter.x);
- if(PTISEQUAL(pCenter, pEnd))
- arc.angle2 = - 180.0;
- else {
- arc.angle2 = -miDatan2 (pOtherCorner.y - pCenter.y, pOtherCorner.x - pCenter.x) - arc.angle1;
- if (arc.angle2 < 0)
- arc.angle2 += 360.0;
- }
- pArcPts = (SppPointPtr) NULL;
- if( (cpt = miGetArcPts(&arc, 0, &pArcPts)) )
- {
- /* by drawing with miFillSppPoly and setting the endpoints of the arc
- * to be the corners, we assure that the cap will meet up with the
- * rest of the line */
- miFillSppPoly(pDraw, pGC, cpt, pArcPts, -xOrg, -yOrg, xFtrans, yFtrans);
- }
- xfree(pArcPts);
-}
-
-/*
- * To avoid inaccuracy at the cardinal points, use trig functions
- * which are exact for those angles
- */
-
-#ifndef M_PI
-#define M_PI 3.14159265358979323846
-#endif
-#ifndef M_PI_2
-#define M_PI_2 1.57079632679489661923
-#endif
-
-# define Dsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
-# define Dcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
-# define mod(a,b) ((a) >= 0 ? (a) % (b) : (b) - (-a) % (b))
-
-static double
-miDcos (double a)
-{
- int i;
-
- if (floor (a/90) == a/90) {
- i = (int) (a/90.0);
- switch (mod (i, 4)) {
- case 0: return 1;
- case 1: return 0;
- case 2: return -1;
- case 3: return 0;
- }
- }
- return cos (a * M_PI / 180.0);
-}
-
-static double
-miDsin (double a)
-{
- int i;
-
- if (floor (a/90) == a/90) {
- i = (int) (a/90.0);
- switch (mod (i, 4)) {
- case 0: return 0;
- case 1: return 1;
- case 2: return 0;
- case 3: return -1;
- }
- }
- return sin (a * M_PI / 180.0);
-}
-
-static double
-miDasin (double v)
-{
- if (v == 0)
- return 0.0;
- if (v == 1.0)
- return 90.0;
- if (v == -1.0)
- return -90.0;
- return asin(v) * (180.0 / M_PI);
-}
-
-static double
-miDatan2 (double dy, double dx)
-{
- if (dy == 0) {
- if (dx >= 0)
- return 0.0;
- return 180.0;
- } else if (dx == 0) {
- if (dy > 0)
- return 90.0;
- return -90.0;
- } else if (Fabs (dy) == Fabs (dx)) {
- if (dy > 0) {
- if (dx > 0)
- return 45.0;
- return 135.0;
- } else {
- if (dx > 0)
- return 315.0;
- return 225.0;
- }
- } else {
- return atan2 (dy, dx) * (180.0 / M_PI);
- }
-}
-
-/* MIGETARCPTS -- Converts an arc into a set of line segments -- a helper
- * routine for filled arc and line (round cap) code.
- * Returns the number of points in the arc. Note that it takes a pointer
- * to a pointer to where it should put the points and an index (cpt).
- * This procedure allocates the space necessary to fit the arc points.
- * Sometimes it's convenient for those points to be at the end of an existing
- * array. (For example, if we want to leave a spare point to make sectors
- * instead of segments.) So we pass in the xalloc()ed chunk that contains the
- * array and an index saying where we should start stashing the points.
- * If there isn't an array already, we just pass in a null pointer and
- * count on xrealloc() to handle the null pointer correctly.
- */
-static int
-miGetArcPts(
- SppArcPtr parc, /* points to an arc */
- int cpt, /* number of points already in arc list */
- SppPointPtr *ppPts) /* pointer to pointer to arc-list -- modified */
-{
- double st, /* Start Theta, start angle */
- et, /* End Theta, offset from start theta */
- dt, /* Delta Theta, angle to sweep ellipse */
- cdt, /* Cos Delta Theta, actually 2 cos(dt) */
- x0, y0, /* the recurrence formula needs two points to start */
- x1, y1,
- x2, y2, /* this will be the new point generated */
- xc, yc; /* the center point */
- int count, i;
- SppPointPtr poly;
-
- /* The spec says that positive angles indicate counterclockwise motion.
- * Given our coordinate system (with 0,0 in the upper left corner),
- * the screen appears flipped in Y. The easiest fix is to negate the
- * angles given */
-
- st = - parc->angle1;
-
- et = - parc->angle2;
-
- /* Try to get a delta theta that is within 1/2 pixel. Then adjust it
- * so that it divides evenly into the total.
- * I'm just using cdt 'cause I'm lazy.
- */
- cdt = parc->width;
- if (parc->height > cdt)
- cdt = parc->height;
- cdt /= 2.0;
- if(cdt <= 0)
- return 0;
- if (cdt < 1.0)
- cdt = 1.0;
- dt = miDasin ( 1.0 / cdt ); /* minimum step necessary */
- count = et/dt;
- count = abs(count) + 1;
- dt = et/count;
- count++;
-
- cdt = 2 * miDcos(dt);
- if (!(poly = (SppPointPtr) xrealloc((pointer)*ppPts,
- (cpt + count) * sizeof(SppPointRec))))
- return(0);
- *ppPts = poly;
-
- xc = parc->width/2.0; /* store half width and half height */
- yc = parc->height/2.0;
-
- x0 = xc * miDcos(st);
- y0 = yc * miDsin(st);
- x1 = xc * miDcos(st + dt);
- y1 = yc * miDsin(st + dt);
- xc += parc->x; /* by adding initial point, these become */
- yc += parc->y; /* the center point */
-
- poly[cpt].x = (xc + x0);
- poly[cpt].y = (yc + y0);
- poly[cpt + 1].x = (xc + x1);
- poly[cpt + 1].y = (yc + y1);
-
- for(i = 2; i < count; i++)
- {
- x2 = cdt * x1 - x0;
- y2 = cdt * y1 - y0;
-
- poly[cpt + i].x = (xc + x2);
- poly[cpt + i].y = (yc + y2);
-
- x0 = x1; y0 = y1;
- x1 = x2; y1 = y2;
- }
- /* adjust the last point */
- if (abs(parc->angle2) >= 360.0)
- poly[cpt +i -1] = poly[0];
- else {
- poly[cpt +i -1].x = (miDcos(st + et) * parc->width/2.0 + xc);
- poly[cpt +i -1].y = (miDsin(st + et) * parc->height/2.0 + yc);
- }
-
- return(count);
-}
-
-struct arcData {
- double x0, y0, x1, y1;
- int selfJoin;
-};
-
-# define ADD_REALLOC_STEP 20
-
-static void
-addCap (
- miArcCapPtr *capsp,
- int *ncapsp,
- int *sizep,
- int end,
- int arcIndex)
-{
- int newsize;
- miArcCapPtr cap;
-
- if (*ncapsp == *sizep)
- {
- newsize = *sizep + ADD_REALLOC_STEP;
- cap = (miArcCapPtr) xrealloc (*capsp,
- newsize * sizeof (**capsp));
- if (!cap)
- return;
- *sizep = newsize;
- *capsp = cap;
- }
- cap = &(*capsp)[*ncapsp];
- cap->end = end;
- cap->arcIndex = arcIndex;
- ++*ncapsp;
-}
-
-static void
-addJoin (
- miArcJoinPtr *joinsp,
- int *njoinsp,
- int *sizep,
- int end0,
- int index0,
- int phase0,
- int end1,
- int index1,
- int phase1)
-{
- int newsize;
- miArcJoinPtr join;
-
- if (*njoinsp == *sizep)
- {
- newsize = *sizep + ADD_REALLOC_STEP;
- join = (miArcJoinPtr) xrealloc (*joinsp,
- newsize * sizeof (**joinsp));
- if (!join)
- return;
- *sizep = newsize;
- *joinsp = join;
- }
- join = &(*joinsp)[*njoinsp];
- join->end0 = end0;
- join->arcIndex0 = index0;
- join->phase0 = phase0;
- join->end1 = end1;
- join->arcIndex1 = index1;
- join->phase1 = phase1;
- ++*njoinsp;
-}
-
-static miArcDataPtr
-addArc (
- miArcDataPtr *arcsp,
- int *narcsp,
- int *sizep,
- xArc *xarc)
-{
- int newsize;
- miArcDataPtr arc;
-
- if (*narcsp == *sizep)
- {
- newsize = *sizep + ADD_REALLOC_STEP;
- arc = (miArcDataPtr) xrealloc (*arcsp,
- newsize * sizeof (**arcsp));
- if (!arc)
- return NULL;
- *sizep = newsize;
- *arcsp = arc;
- }
- arc = &(*arcsp)[*narcsp];
- arc->arc = *xarc;
- ++*narcsp;
- return arc;
-}
-
-static void
-miFreeArcs(
- miPolyArcPtr arcs,
- GCPtr pGC)
-{
- int iphase;
-
- for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0);
- iphase >= 0;
- iphase--)
- {
- if (arcs[iphase].narcs > 0)
- xfree(arcs[iphase].arcs);
- if (arcs[iphase].njoins > 0)
- xfree(arcs[iphase].joins);
- if (arcs[iphase].ncaps > 0)
- xfree(arcs[iphase].caps);
- }
- xfree(arcs);
-}
-
-/*
- * map angles to radial distance. This only deals with the first quadrant
- */
-
-/*
- * a polygonal approximation to the arc for computing arc lengths
- */
-
-# define DASH_MAP_SIZE 91
-
-# define dashIndexToAngle(di) ((((double) (di)) * 90.0) / ((double) DASH_MAP_SIZE - 1))
-# define xAngleToDashIndex(xa) ((((long) (xa)) * (DASH_MAP_SIZE - 1)) / (90 * 64))
-# define dashIndexToXAngle(di) ((((long) (di)) * (90 * 64)) / (DASH_MAP_SIZE - 1))
-# define dashXAngleStep (((double) (90 * 64)) / ((double) (DASH_MAP_SIZE - 1)))
-
-typedef struct {
- double map[DASH_MAP_SIZE];
-} dashMap;
-
-static int computeAngleFromPath(int startAngle, int endAngle, dashMap *map,
- int *lenp, int backwards);
-
-static void
-computeDashMap (
- xArc *arcp,
- dashMap *map)
-{
- int di;
- double a, x, y, prevx = 0.0, prevy = 0.0, dist;
-
- for (di = 0; di < DASH_MAP_SIZE; di++) {
- a = dashIndexToAngle (di);
- x = ((double) arcp->width / 2.0) * miDcos (a);
- y = ((double) arcp->height / 2.0) * miDsin (a);
- if (di == 0) {
- map->map[di] = 0.0;
- } else {
- dist = hypot (x - prevx, y - prevy);
- map->map[di] = map->map[di - 1] + dist;
- }
- prevx = x;
- prevy = y;
- }
-}
-
-typedef enum {HORIZONTAL, VERTICAL, OTHER} arcTypes;
-
-/* this routine is a bit gory */
-
-static miPolyArcPtr
-miComputeArcs (
- xArc *parcs,
- int narcs,
- GCPtr pGC)
-{
- int isDashed, isDoubleDash;
- int dashOffset;
- miPolyArcPtr arcs;
- int start, i, j, k = 0, nexti, nextk = 0;
- int joinSize[2];
- int capSize[2];
- int arcSize[2];
- int angle2;
- double a0, a1;
- struct arcData *data;
- miArcDataPtr arc;
- xArc xarc;
- int iphase, prevphase = 0, joinphase;
- int arcsJoin;
- int selfJoin;
-
- int iDash = 0, dashRemaining = 0;
- int iDashStart = 0, dashRemainingStart = 0, iphaseStart;
- int startAngle, spanAngle, endAngle, backwards = 0;
- int prevDashAngle, dashAngle;
- dashMap map;
-
- isDashed = !(pGC->lineStyle == LineSolid);
- isDoubleDash = (pGC->lineStyle == LineDoubleDash);
- dashOffset = pGC->dashOffset;
-
- data = xalloc (narcs * sizeof (struct arcData));
- if (!data)
- return NULL;
- arcs = xalloc (sizeof (*arcs) * (isDoubleDash ? 2 : 1));
- if (!arcs)
- {
- xfree(data);
- return NULL;
- }
- for (i = 0; i < narcs; i++) {
- a0 = todeg (parcs[i].angle1);
- angle2 = parcs[i].angle2;
- if (angle2 > FULLCIRCLE)
- angle2 = FULLCIRCLE;
- else if (angle2 < -FULLCIRCLE)
- angle2 = -FULLCIRCLE;
- data[i].selfJoin = angle2 == FULLCIRCLE || angle2 == -FULLCIRCLE;
- a1 = todeg (parcs[i].angle1 + angle2);
- data[i].x0 = parcs[i].x + (double) parcs[i].width / 2 * (1 + miDcos (a0));
- data[i].y0 = parcs[i].y + (double) parcs[i].height / 2 * (1 - miDsin (a0));
- data[i].x1 = parcs[i].x + (double) parcs[i].width / 2 * (1 + miDcos (a1));
- data[i].y1 = parcs[i].y + (double) parcs[i].height / 2 * (1 - miDsin (a1));
- }
-
- for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++) {
- arcs[iphase].njoins = 0;
- arcs[iphase].joins = 0;
- joinSize[iphase] = 0;
-
- arcs[iphase].ncaps = 0;
- arcs[iphase].caps = 0;
- capSize[iphase] = 0;
-
- arcs[iphase].narcs = 0;
- arcs[iphase].arcs = 0;
- arcSize[iphase] = 0;
- }
-
- iphase = 0;
- if (isDashed) {
- iDash = 0;
- dashRemaining = pGC->dash[0];
- while (dashOffset > 0) {
- if (dashOffset >= dashRemaining) {
- dashOffset -= dashRemaining;
- iphase = iphase ? 0 : 1;
- iDash++;
- if (iDash == pGC->numInDashList)
- iDash = 0;
- dashRemaining = pGC->dash[iDash];
- } else {
- dashRemaining -= dashOffset;
- dashOffset = 0;
- }
- }
- iDashStart = iDash;
- dashRemainingStart = dashRemaining;
- }
- iphaseStart = iphase;
-
- for (i = narcs - 1; i >= 0; i--) {
- j = i + 1;
- if (j == narcs)
- j = 0;
- if (data[i].selfJoin || i == j ||
- (UNEQUAL (data[i].x1, data[j].x0) ||
- UNEQUAL (data[i].y1, data[j].y0)))
- {
- if (iphase == 0 || isDoubleDash)
- addCap (&arcs[iphase].caps, &arcs[iphase].ncaps,
- &capSize[iphase], RIGHT_END, 0);
- break;
- }
- }
- start = i + 1;
- if (start == narcs)
- start = 0;
- i = start;
- for (;;) {
- j = i + 1;
- if (j == narcs)
- j = 0;
- nexti = i+1;
- if (nexti == narcs)
- nexti = 0;
- if (isDashed) {
- /*
- ** deal with dashed arcs. Use special rules for certain 0 area arcs.
- ** Presumably, the other 0 area arcs still aren't done right.
- */
- arcTypes arcType = OTHER;
- CARD16 thisLength;
-
- if (parcs[i].height == 0
- && (parcs[i].angle1 % FULLCIRCLE) == 0x2d00
- && parcs[i].angle2 == 0x2d00)
- arcType = HORIZONTAL;
- else if (parcs[i].width == 0
- && (parcs[i].angle1 % FULLCIRCLE) == 0x1680
- && parcs[i].angle2 == 0x2d00)
- arcType = VERTICAL;
- if (arcType == OTHER) {
- /*
- * precompute an approximation map
- */
- computeDashMap (&parcs[i], &map);
- /*
- * compute each individual dash segment using the path
- * length function
- */
- startAngle = parcs[i].angle1;
- spanAngle = parcs[i].angle2;
- if (spanAngle > FULLCIRCLE)
- spanAngle = FULLCIRCLE;
- else if (spanAngle < -FULLCIRCLE)
- spanAngle = -FULLCIRCLE;
- if (startAngle < 0)
- startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE;
- if (startAngle >= FULLCIRCLE)
- startAngle = startAngle % FULLCIRCLE;
- endAngle = startAngle + spanAngle;
- backwards = spanAngle < 0;
- } else {
- xarc = parcs[i];
- if (arcType == VERTICAL) {
- xarc.angle1 = 0x1680;
- startAngle = parcs[i].y;
- endAngle = startAngle + parcs[i].height;
- } else {
- xarc.angle1 = 0x2d00;
- startAngle = parcs[i].x;
- endAngle = startAngle + parcs[i].width;
- }
- }
- dashAngle = startAngle;
- selfJoin = data[i].selfJoin &&
- (iphase == 0 || isDoubleDash);
- /*
- * add dashed arcs to each bucket
- */
- arc = 0;
- while (dashAngle != endAngle) {
- prevDashAngle = dashAngle;
- if (arcType == OTHER) {
- dashAngle = computeAngleFromPath (prevDashAngle, endAngle,
- &map, &dashRemaining, backwards);
- /* avoid troubles with huge arcs and small dashes */
- if (dashAngle == prevDashAngle) {
- if (backwards)
- dashAngle--;
- else
- dashAngle++;
- }
- } else {
- thisLength = (dashAngle + dashRemaining <= endAngle) ?
- dashRemaining : endAngle - dashAngle;
- if (arcType == VERTICAL) {
- xarc.y = dashAngle;
- xarc.height = thisLength;
- } else {
- xarc.x = dashAngle;
- xarc.width = thisLength;
- }
- dashAngle += thisLength;
- dashRemaining -= thisLength;
- }
- if (iphase == 0 || isDoubleDash) {
- if (arcType == OTHER) {
- xarc = parcs[i];
- spanAngle = prevDashAngle;
- if (spanAngle < 0)
- spanAngle = FULLCIRCLE - (-spanAngle) % FULLCIRCLE;
- if (spanAngle >= FULLCIRCLE)
- spanAngle = spanAngle % FULLCIRCLE;
- xarc.angle1 = spanAngle;
- spanAngle = dashAngle - prevDashAngle;
- if (backwards) {
- if (dashAngle > prevDashAngle)
- spanAngle = - FULLCIRCLE + spanAngle;
- } else {
- if (dashAngle < prevDashAngle)
- spanAngle = FULLCIRCLE + spanAngle;
- }
- if (spanAngle > FULLCIRCLE)
- spanAngle = FULLCIRCLE;
- if (spanAngle < -FULLCIRCLE)
- spanAngle = -FULLCIRCLE;
- xarc.angle2 = spanAngle;
- }
- arc = addArc (&arcs[iphase].arcs, &arcs[iphase].narcs,
- &arcSize[iphase], &xarc);
- if (!arc)
- goto arcfail;
- /*
- * cap each end of an on/off dash
- */
- if (!isDoubleDash) {
- if (prevDashAngle != startAngle) {
- addCap (&arcs[iphase].caps,
- &arcs[iphase].ncaps,
- &capSize[iphase], RIGHT_END,
- arc - arcs[iphase].arcs);
-
- }
- if (dashAngle != endAngle) {
- addCap (&arcs[iphase].caps,
- &arcs[iphase].ncaps,
- &capSize[iphase], LEFT_END,
- arc - arcs[iphase].arcs);
- }
- }
- arc->cap = arcs[iphase].ncaps;
- arc->join = arcs[iphase].njoins;
- arc->render = 0;
- arc->selfJoin = 0;
- if (dashAngle == endAngle)
- arc->selfJoin = selfJoin;
- }
- prevphase = iphase;
- if (dashRemaining <= 0) {
- ++iDash;
- if (iDash == pGC->numInDashList)
- iDash = 0;
- iphase = iphase ? 0:1;
- dashRemaining = pGC->dash[iDash];
- }
- }
- /*
- * make sure a place exists for the position data when
- * drawing a zero-length arc
- */
- if (startAngle == endAngle) {
- prevphase = iphase;
- if (!isDoubleDash && iphase == 1)
- prevphase = 0;
- arc = addArc (&arcs[prevphase].arcs, &arcs[prevphase].narcs,
- &arcSize[prevphase], &parcs[i]);
- if (!arc)
- goto arcfail;
- arc->join = arcs[prevphase].njoins;
- arc->cap = arcs[prevphase].ncaps;
- arc->selfJoin = data[i].selfJoin;
- }
- } else {
- arc = addArc (&arcs[iphase].arcs, &arcs[iphase].narcs,
- &arcSize[iphase], &parcs[i]);
- if (!arc)
- goto arcfail;
- arc->join = arcs[iphase].njoins;
- arc->cap = arcs[iphase].ncaps;
- arc->selfJoin = data[i].selfJoin;
- prevphase = iphase;
- }
- if (prevphase == 0 || isDoubleDash)
- k = arcs[prevphase].narcs - 1;
- if (iphase == 0 || isDoubleDash)
- nextk = arcs[iphase].narcs;
- if (nexti == start) {
- nextk = 0;
- if (isDashed) {
- iDash = iDashStart;
- iphase = iphaseStart;
- dashRemaining = dashRemainingStart;
- }
- }
- arcsJoin = narcs > 1 && i != j &&
- ISEQUAL (data[i].x1, data[j].x0) &&
- ISEQUAL (data[i].y1, data[j].y0) &&
- !data[i].selfJoin && !data[j].selfJoin;
- if (arc)
- {
- if (arcsJoin)
- arc->render = 0;
- else
- arc->render = 1;
- }
- if (arcsJoin &&
- (prevphase == 0 || isDoubleDash) &&
- (iphase == 0 || isDoubleDash))
- {
- joinphase = iphase;
- if (isDoubleDash) {
- if (nexti == start)
- joinphase = iphaseStart;
- /*
- * if the join is right at the dash,
- * draw the join in foreground
- * This is because the foreground
- * arcs are computed second, the results
- * of which are needed to draw the join
- */
- if (joinphase != prevphase)
- joinphase = 0;
- }
- if (joinphase == 0 || isDoubleDash) {
- addJoin (&arcs[joinphase].joins,
- &arcs[joinphase].njoins,
- &joinSize[joinphase],
- LEFT_END, k, prevphase,
- RIGHT_END, nextk, iphase);
- arc->join = arcs[prevphase].njoins;
- }
- } else {
- /*
- * cap the left end of this arc
- * unless it joins itself
- */
- if ((prevphase == 0 || isDoubleDash) &&
- !arc->selfJoin)
- {
- addCap (&arcs[prevphase].caps, &arcs[prevphase].ncaps,
- &capSize[prevphase], LEFT_END, k);
- arc->cap = arcs[prevphase].ncaps;
- }
- if (isDashed && !arcsJoin) {
- iDash = iDashStart;
- iphase = iphaseStart;
- dashRemaining = dashRemainingStart;
- }
- nextk = arcs[iphase].narcs;
- if (nexti == start) {
- nextk = 0;
- iDash = iDashStart;
- iphase = iphaseStart;
- dashRemaining = dashRemainingStart;
- }
- /*
- * cap the right end of the next arc. If the
- * next arc is actually the first arc, only
- * cap it if it joins with this arc. This
- * case will occur when the final dash segment
- * of an on/off dash is off. Of course, this
- * cap will be drawn at a strange time, but that
- * hardly matters...
- */
- if ((iphase == 0 || isDoubleDash) &&
- (nexti != start || (arcsJoin && isDashed)))
- addCap (&arcs[iphase].caps, &arcs[iphase].ncaps,
- &capSize[iphase], RIGHT_END, nextk);
- }
- i = nexti;
- if (i == start)
- break;
- }
- /*
- * make sure the last section is rendered
- */
- for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++)
- if (arcs[iphase].narcs > 0) {
- arcs[iphase].arcs[arcs[iphase].narcs-1].render = 1;
- arcs[iphase].arcs[arcs[iphase].narcs-1].join =
- arcs[iphase].njoins;
- arcs[iphase].arcs[arcs[iphase].narcs-1].cap =
- arcs[iphase].ncaps;
- }
- xfree(data);
- return arcs;
-arcfail:
- miFreeArcs(arcs, pGC);
- xfree(data);
- return NULL;
-}
-
-static double
-angleToLength (
- int angle,
- dashMap *map)
-{
- double len, excesslen, sidelen = map->map[DASH_MAP_SIZE - 1], totallen;
- int di;
- int excess;
- Bool oddSide = FALSE;
-
- totallen = 0;
- if (angle >= 0) {
- while (angle >= 90 * 64) {
- angle -= 90 * 64;
- totallen += sidelen;
- oddSide = !oddSide;
- }
- } else {
- while (angle < 0) {
- angle += 90 * 64;
- totallen -= sidelen;
- oddSide = !oddSide;
- }
- }
- if (oddSide)
- angle = 90 * 64 - angle;
-
- di = xAngleToDashIndex (angle);
- excess = angle - dashIndexToXAngle (di);
-
- len = map->map[di];
- /*
- * linearly interpolate between this point and the next
- */
- if (excess > 0) {
- excesslen = (map->map[di + 1] - map->map[di]) *
- ((double) excess) / dashXAngleStep;
- len += excesslen;
- }
- if (oddSide)
- totallen += (sidelen - len);
- else
- totallen += len;
- return totallen;
-}
-
-/*
- * len is along the arc, but may be more than one rotation
- */
-
-static int
-lengthToAngle (
- double len,
- dashMap *map)
-{
- double sidelen = map->map[DASH_MAP_SIZE - 1];
- int angle, angleexcess;
- Bool oddSide = FALSE;
- int a0, a1, a;
-
- angle = 0;
- /*
- * step around the ellipse, subtracting sidelens and
- * adding 90 degrees. oddSide will tell if the
- * map should be interpolated in reverse
- */
- if (len >= 0) {
- if (sidelen == 0)
- return 2 * FULLCIRCLE; /* infinity */
- while (len >= sidelen) {
- angle += 90 * 64;
- len -= sidelen;
- oddSide = !oddSide;
- }
- } else {
- if (sidelen == 0)
- return -2 * FULLCIRCLE; /* infinity */
- while (len < 0) {
- angle -= 90 * 64;
- len += sidelen;
- oddSide = !oddSide;
- }
- }
- if (oddSide)
- len = sidelen - len;
- a0 = 0;
- a1 = DASH_MAP_SIZE - 1;
- /*
- * binary search for the closest pre-computed length
- */
- while (a1 - a0 > 1) {
- a = (a0 + a1) / 2;
- if (len > map->map[a])
- a0 = a;
- else
- a1 = a;
- }
- angleexcess = dashIndexToXAngle (a0);
- /*
- * linearly interpolate to the next point
- */
- angleexcess += (len - map->map[a0]) /
- (map->map[a0+1] - map->map[a0]) * dashXAngleStep;
- if (oddSide)
- angle += (90 * 64) - angleexcess;
- else
- angle += angleexcess;
- return angle;
-}
-
-/*
- * compute the angle of an ellipse which cooresponds to
- * the given path length. Note that the correct solution
- * to this problem is an eliptic integral, we'll punt and
- * approximate (it's only for dashes anyway). This
- * approximation uses a polygon.
- *
- * The remaining portion of len is stored in *lenp -
- * this will be negative if the arc extends beyond
- * len and positive if len extends beyond the arc.
- */
-
-static int
-computeAngleFromPath (
- int startAngle,
- int endAngle, /* normalized absolute angles in *64 degrees */
- dashMap *map,
- int *lenp,
- int backwards)
-{
- int a0, a1, a;
- double len0;
- int len;
-
- a0 = startAngle;
- a1 = endAngle;
- len = *lenp;
- if (backwards) {
- /*
- * flip the problem around to always be
- * forwards
- */
- a0 = FULLCIRCLE - a0;
- a1 = FULLCIRCLE - a1;
- }
- if (a1 < a0)
- a1 += FULLCIRCLE;
- len0 = angleToLength (a0, map);
- a = lengthToAngle (len0 + len, map);
- if (a > a1) {
- a = a1;
- len -= angleToLength (a1, map) - len0;
- } else
- len = 0;
- if (backwards)
- a = FULLCIRCLE - a;
- *lenp = len;
- return a;
-}
-
-/*
- * scan convert wide arcs.
- */
-
-/*
- * draw zero width/height arcs
- */
-
-static void
-drawZeroArc (
- DrawablePtr pDraw,
- GCPtr pGC,
- xArc *tarc,
- int lw,
- miArcFacePtr left,
- miArcFacePtr right)
-{
- double x0 = 0.0, y0 = 0.0, x1 = 0.0, y1 = 0.0, w, h, x, y;
- double xmax, ymax, xmin, ymin;
- int a0, a1;
- double a, startAngle, endAngle;
- double l, lx, ly;
-
- l = lw / 2.0;
- a0 = tarc->angle1;
- a1 = tarc->angle2;
- if (a1 > FULLCIRCLE)
- a1 = FULLCIRCLE;
- else if (a1 < -FULLCIRCLE)
- a1 = -FULLCIRCLE;
- w = (double)tarc->width / 2.0;
- h = (double)tarc->height / 2.0;
- /*
- * play in X coordinates right away
- */
- startAngle = - ((double) a0 / 64.0);
- endAngle = - ((double) (a0 + a1) / 64.0);
-
- xmax = -w;
- xmin = w;
- ymax = -h;
- ymin = h;
- a = startAngle;
- for (;;)
- {
- x = w * miDcos(a);
- y = h * miDsin(a);
- if (a == startAngle)
- {
- x0 = x;
- y0 = y;
- }
- if (a == endAngle)
- {
- x1 = x;
- y1 = y;
- }
- if (x > xmax)
- xmax = x;
- if (x < xmin)
- xmin = x;
- if (y > ymax)
- ymax = y;
- if (y < ymin)
- ymin = y;
- if (a == endAngle)
- break;
- if (a1 < 0) /* clockwise */
- {
- if (floor (a / 90.0) == floor (endAngle / 90.0))
- a = endAngle;
- else
- a = 90 * (floor (a/90.0) + 1);
- }
- else
- {
- if (ceil (a / 90.0) == ceil (endAngle / 90.0))
- a = endAngle;
- else
- a = 90 * (ceil (a/90.0) - 1);
- }
- }
- lx = ly = l;
- if ((x1 - x0) + (y1 - y0) < 0)
- lx = ly = -l;
- if (h)
- {
- ly = 0.0;
- lx = -lx;
- }
- else
- lx = 0.0;
- if (right)
- {
- right->center.x = x0;
- right->center.y = y0;
- right->clock.x = x0 - lx;
- right->clock.y = y0 - ly;
- right->counterClock.x = x0 + lx;
- right->counterClock.y = y0 + ly;
- }
- if (left)
- {
- left->center.x = x1;
- left->center.y = y1;
- left->clock.x = x1 + lx;
- left->clock.y = y1 + ly;
- left->counterClock.x = x1 - lx;
- left->counterClock.y = y1 - ly;
- }
-
- x0 = xmin;
- x1 = xmax;
- y0 = ymin;
- y1 = ymax;
- if (ymin != y1) {
- xmin = -l;
- xmax = l;
- } else {
- ymin = -l;
- ymax = l;
- }
- if (xmax != xmin && ymax != ymin) {
- int minx, maxx, miny, maxy;
- xRectangle rect;
-
- minx = ICEIL (xmin + w) + tarc->x;
- maxx = ICEIL (xmax + w) + tarc->x;
- miny = ICEIL (ymin + h) + tarc->y;
- maxy = ICEIL (ymax + h) + tarc->y;
- rect.x = minx;
- rect.y = miny;
- rect.width = maxx - minx;
- rect.height = maxy - miny;
- (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
- }
-}
-
-/*
- * this computes the ellipse y value associated with the
- * bottom of the tail.
- */
-
-static void
-tailEllipseY (
- struct arc_def *def,
- struct accelerators *acc)
-{
- double t;
-
- acc->tail_y = 0.0;
- if (def->w == def->h)
- return;
- t = def->l * def->w;
- if (def->w > def->h) {
- if (t < acc->h2)
- return;
- } else {
- if (t > acc->h2)
- return;
- }
- t = 2.0 * def->h * t;
- t = (CUBED_ROOT_4 * acc->h2 - cbrt(t * t)) / acc->h2mw2;
- if (t > 0.0)
- acc->tail_y = def->h / CUBED_ROOT_2 * sqrt(t);
-}
-
-/*
- * inverse functions -- compute edge coordinates
- * from the ellipse
- */
-
-static double
-outerXfromXY (
- double x,
- double y,
- struct arc_def *def,
- struct accelerators *acc)
-{
- return x + (x * acc->h2l) / sqrt (x*x * acc->h4 + y*y * acc->w4);
-}
-
-static double
-outerYfromXY (
- double x,
- double y,
- struct arc_def *def,
- struct accelerators *acc)
-{
- return y + (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4);
-}
-
-static double
-innerXfromXY (
- double x,
- double y,
- struct arc_def *def,
- struct accelerators *acc)
-{
- return x - (x * acc->h2l) / sqrt (x*x * acc->h4 + y*y * acc->w4);
-}
-
-static double
-innerYfromXY (
- double x,
- double y,
- struct arc_def *def,
- struct accelerators *acc)
-{
- return y - (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4);
-}
-
-static double
-innerYfromY (
- double y,
- struct arc_def *def,
- struct accelerators *acc)
-{
- double x;
-
- x = (def->w / def->h) * sqrt (acc->h2 - y*y);
-
- return y - (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4);
-}
-
-static void
-computeLine (
- double x1,
- double y1,
- double x2,
- double y2,
- struct line *line)
-{
- if (y1 == y2)
- line->valid = 0;
- else {
- line->m = (x1 - x2) / (y1 - y2);
- line->b = x1 - y1 * line->m;
- line->valid = 1;
- }
-}
-
-/*
- * compute various accelerators for an ellipse. These
- * are simply values that are used repeatedly in
- * the computations
- */
-
-static void
-computeAcc (
- xArc *tarc,
- int lw,
- struct arc_def *def,
- struct accelerators *acc)
-{
- def->w = ((double) tarc->width) / 2.0;
- def->h = ((double) tarc->height) / 2.0;
- def->l = ((double) lw) / 2.0;
- acc->h2 = def->h * def->h;
- acc->w2 = def->w * def->w;
- acc->h4 = acc->h2 * acc->h2;
- acc->w4 = acc->w2 * acc->w2;
- acc->h2l = acc->h2 * def->l;
- acc->w2l = acc->w2 * def->l;
- acc->h2mw2 = acc->h2 - acc->w2;
- acc->fromIntX = (tarc->width & 1) ? 0.5 : 0.0;
- acc->fromIntY = (tarc->height & 1) ? 0.5 : 0.0;
- acc->xorg = tarc->x + (tarc->width >> 1);
- acc->yorgu = tarc->y + (tarc->height >> 1);
- acc->yorgl = acc->yorgu + (tarc->height & 1);
- tailEllipseY (def, acc);
-}
-
-/*
- * compute y value bounds of various portions of the arc,
- * the outer edge, the ellipse and the inner edge.
- */
-
-static void
-computeBound (
- struct arc_def *def,
- struct arc_bound *bound,
- struct accelerators *acc,
- miArcFacePtr right,
- miArcFacePtr left)
-{
- double t;
- double innerTaily;
- double tail_y;
- struct bound innerx, outerx;
- struct bound ellipsex;
-
- bound->ellipse.min = Dsin (def->a0) * def->h;
- bound->ellipse.max = Dsin (def->a1) * def->h;
- if (def->a0 == 45 && def->w == def->h)
- ellipsex.min = bound->ellipse.min;
- else
- ellipsex.min = Dcos (def->a0) * def->w;
- if (def->a1 == 45 && def->w == def->h)
- ellipsex.max = bound->ellipse.max;
- else
- ellipsex.max = Dcos (def->a1) * def->w;
- bound->outer.min = outerYfromXY (ellipsex.min, bound->ellipse.min, def, acc);
- bound->outer.max = outerYfromXY (ellipsex.max, bound->ellipse.max, def, acc);
- bound->inner.min = innerYfromXY (ellipsex.min, bound->ellipse.min, def, acc);
- bound->inner.max = innerYfromXY (ellipsex.max, bound->ellipse.max, def, acc);
-
- outerx.min = outerXfromXY (ellipsex.min, bound->ellipse.min, def, acc);
- outerx.max = outerXfromXY (ellipsex.max, bound->ellipse.max, def, acc);
- innerx.min = innerXfromXY (ellipsex.min, bound->ellipse.min, def, acc);
- innerx.max = innerXfromXY (ellipsex.max, bound->ellipse.max, def, acc);
-
- /*
- * save the line end points for the
- * cap code to use. Careful here, these are
- * in cartesean coordinates (y increasing upwards)
- * while the cap code uses inverted coordinates
- * (y increasing downwards)
- */
-
- if (right) {
- right->counterClock.y = bound->outer.min;
- right->counterClock.x = outerx.min;
- right->center.y = bound->ellipse.min;
- right->center.x = ellipsex.min;
- right->clock.y = bound->inner.min;
- right->clock.x = innerx.min;
- }
-
- if (left) {
- left->clock.y = bound->outer.max;
- left->clock.x = outerx.max;
- left->center.y = bound->ellipse.max;
- left->center.x = ellipsex.max;
- left->counterClock.y = bound->inner.max;
- left->counterClock.x = innerx.max;
- }
-
- bound->left.min = bound->inner.max;
- bound->left.max = bound->outer.max;
- bound->right.min = bound->inner.min;
- bound->right.max = bound->outer.min;
-
- computeLine (innerx.min, bound->inner.min, outerx.min, bound->outer.min,
- &acc->right);
- computeLine (innerx.max, bound->inner.max, outerx.max, bound->outer.max,
- &acc->left);
-
- if (bound->inner.min > bound->inner.max) {
- t = bound->inner.min;
- bound->inner.min = bound->inner.max;
- bound->inner.max = t;
- }
- tail_y = acc->tail_y;
- if (tail_y > bound->ellipse.max)
- tail_y = bound->ellipse.max;
- else if (tail_y < bound->ellipse.min)
- tail_y = bound->ellipse.min;
- innerTaily = innerYfromY (tail_y, def, acc);
- if (bound->inner.min > innerTaily)
- bound->inner.min = innerTaily;
- if (bound->inner.max < innerTaily)
- bound->inner.max = innerTaily;
- bound->inneri.min = ICEIL(bound->inner.min - acc->fromIntY);
- bound->inneri.max = floor(bound->inner.max - acc->fromIntY);
- bound->outeri.min = ICEIL(bound->outer.min - acc->fromIntY);
- bound->outeri.max = floor(bound->outer.max - acc->fromIntY);
-}
-
-/*
- * this section computes the x value of the span at y
- * intersected with the specified face of the ellipse.
- *
- * this is the min/max X value over the set of normal
- * lines to the entire ellipse, the equation of the
- * normal lines is:
- *
- * ellipse_x h^2 h^2
- * x = ------------ y + ellipse_x (1 - --- )
- * ellipse_y w^2 w^2
- *
- * compute the derivative with-respect-to ellipse_y and solve
- * for zero:
- *
- * (w^2 - h^2) ellipse_y^3 + h^4 y
- * 0 = - ----------------------------------
- * h w ellipse_y^2 sqrt (h^2 - ellipse_y^2)
- *
- * ( h^4 y )
- * ellipse_y = ( ---------- ) ^ (1/3)
- * ( (h^2 - w^2) )
- *
- * The other two solutions to the equation are imaginary.
- *
- * This gives the position on the ellipse which generates
- * the normal with the largest/smallest x intersection point.
- *
- * Now compute the second derivative to check whether
- * the intersection is a minimum or maximum:
- *
- * h (y0^3 (w^2 - h^2) + h^2 y (3y0^2 - 2h^2))
- * - -------------------------------------------
- * w y0^3 (sqrt (h^2 - y^2)) ^ 3
- *
- * as we only care about the sign,
- *
- * - (y0^3 (w^2 - h^2) + h^2 y (3y0^2 - 2h^2))
- *
- * or (to use accelerators),
- *
- * y0^3 (h^2 - w^2) - h^2 y (3y0^2 - 2h^2)
- *
- */
-
-/*
- * computes the position on the ellipse whose normal line
- * intersects the given scan line maximally
- */
-
-static double
-hookEllipseY (
- double scan_y,
- struct arc_bound *bound,
- struct accelerators *acc,
- int left)
-{
- double ret;
-
- if (acc->h2mw2 == 0) {
- if ( (scan_y > 0 && !left) || (scan_y < 0 && left) )
- return bound->ellipse.min;
- return bound->ellipse.max;
- }
- ret = (acc->h4 * scan_y) / (acc->h2mw2);
- if (ret >= 0)
- return cbrt (ret);
- else
- return -cbrt (-ret);
-}
-
-/*
- * computes the X value of the intersection of the
- * given scan line with the right side of the lower hook
- */
-
-static double
-hookX (
- double scan_y,
- struct arc_def *def,
- struct arc_bound *bound,
- struct accelerators *acc,
- int left)
-{
- double ellipse_y, x;
- double maxMin;
-
- if (def->w != def->h) {
- ellipse_y = hookEllipseY (scan_y, bound, acc, left);
- if (boundedLe (ellipse_y, bound->ellipse)) {
- /*
- * compute the value of the second
- * derivative
- */
- maxMin = ellipse_y*ellipse_y*ellipse_y * acc->h2mw2 -
- acc->h2 * scan_y * (3 * ellipse_y*ellipse_y - 2*acc->h2);
- if ((left && maxMin > 0) || (!left && maxMin < 0)) {
- if (ellipse_y == 0)
- return def->w + left ? -def->l : def->l;
- x = (acc->h2 * scan_y - ellipse_y * acc->h2mw2) *
- sqrt (acc->h2 - ellipse_y * ellipse_y) /
- (def->h * def->w * ellipse_y);
- return x;
- }
- }
- }
- if (left) {
- if (acc->left.valid && boundedLe (scan_y, bound->left)) {
- x = intersectLine (scan_y, acc->left);
- } else {
- if (acc->right.valid)
- x = intersectLine (scan_y, acc->right);
- else
- x = def->w - def->l;
- }
- } else {
- if (acc->right.valid && boundedLe (scan_y, bound->right)) {
- x = intersectLine (scan_y, acc->right);
- } else {
- if (acc->left.valid)
- x = intersectLine (scan_y, acc->left);
- else
- x = def->w - def->l;
- }
- }
- return x;
-}
-
-/*
- * generate the set of spans with
- * the given y coordinate
- */
-
-static void
-arcSpan (
- int y,
- int lx,
- int lw,
- int rx,
- int rw,
- struct arc_def *def,
- struct arc_bound *bounds,
- struct accelerators *acc,
- int mask)
-{
- int linx, loutx, rinx, routx;
- double x, altx;
-
- if (boundedLe (y, bounds->inneri)) {
- linx = -(lx + lw);
- rinx = rx;
- } else {
- /*
- * intersection with left face
- */
- x = hookX (y + acc->fromIntY, def, bounds, acc, 1);
- if (acc->right.valid &&
- boundedLe (y + acc->fromIntY, bounds->right))
- {
- altx = intersectLine (y + acc->fromIntY, acc->right);
- if (altx < x)
- x = altx;
- }
- linx = -ICEIL(acc->fromIntX - x);
- rinx = ICEIL(acc->fromIntX + x);
- }
- if (boundedLe (y, bounds->outeri)) {
- loutx = -lx;
- routx = rx + rw;
- } else {
- /*
- * intersection with right face
- */
- x = hookX (y + acc->fromIntY, def, bounds, acc, 0);
- if (acc->left.valid &&
- boundedLe (y + acc->fromIntY, bounds->left))
- {
- altx = x;
- x = intersectLine (y + acc->fromIntY, acc->left);
- if (x < altx)
- x = altx;
- }
- loutx = -ICEIL(acc->fromIntX - x);
- routx = ICEIL(acc->fromIntX + x);
- }
- if (routx > rinx) {
- if (mask & 1)
- newFinalSpan (acc->yorgu - y,
- acc->xorg + rinx, acc->xorg + routx);
- if (mask & 8)
- newFinalSpan (acc->yorgl + y,
- acc->xorg + rinx, acc->xorg + routx);
- }
- if (loutx > linx) {
- if (mask & 2)
- newFinalSpan (acc->yorgu - y,
- acc->xorg - loutx, acc->xorg - linx);
- if (mask & 4)
- newFinalSpan (acc->yorgl + y,
- acc->xorg - loutx, acc->xorg - linx);
- }
-}
-
-static void
-arcSpan0 (
- int lx,
- int lw,
- int rx,
- int rw,
- struct arc_def *def,
- struct arc_bound *bounds,
- struct accelerators *acc,
- int mask)
-{
- double x;
-
- if (boundedLe (0, bounds->inneri) &&
- acc->left.valid && boundedLe (0, bounds->left) &&
- acc->left.b > 0)
- {
- x = def->w - def->l;
- if (acc->left.b < x)
- x = acc->left.b;
- lw = ICEIL(acc->fromIntX - x) - lx;
- rw += rx;
- rx = ICEIL(acc->fromIntX + x);
- rw -= rx;
- }
- arcSpan (0, lx, lw, rx, rw, def, bounds, acc, mask);
-}
-
-static void
-tailSpan (
- int y,
- int lw,
- int rw,
- struct arc_def *def,
- struct arc_bound *bounds,
- struct accelerators *acc,
- int mask)
-{
- double yy, xalt, x, lx, rx;
- int n;
-
- if (boundedLe(y, bounds->outeri))
- arcSpan (y, 0, lw, -rw, rw, def, bounds, acc, mask);
- else if (def->w != def->h) {
- yy = y + acc->fromIntY;
- x = tailX(yy, def, bounds, acc);
- if (yy == 0.0 && x == -rw - acc->fromIntX)
- return;
- if (acc->right.valid && boundedLe (yy, bounds->right)) {
- rx = x;
- lx = -x;
- xalt = intersectLine (yy, acc->right);
- if (xalt >= -rw - acc->fromIntX && xalt <= rx)
- rx = xalt;
- n = ICEIL(acc->fromIntX + lx);
- if (lw > n) {
- if (mask & 2)
- newFinalSpan (acc->yorgu - y,
- acc->xorg + n, acc->xorg + lw);
- if (mask & 4)
- newFinalSpan (acc->yorgl + y,
- acc->xorg + n, acc->xorg + lw);
- }
- n = ICEIL(acc->fromIntX + rx);
- if (n > -rw) {
- if (mask & 1)
- newFinalSpan (acc->yorgu - y,
- acc->xorg - rw, acc->xorg + n);
- if (mask & 8)
- newFinalSpan (acc->yorgl + y,
- acc->xorg - rw, acc->xorg + n);
- }
- }
- arcSpan (y,
- ICEIL(acc->fromIntX - x), 0,
- ICEIL(acc->fromIntX + x), 0,
- def, bounds, acc, mask);
- }
-}
-
-/*
- * create whole arcs out of pieces. This code is
- * very bad.
- */
-
-static struct finalSpan **finalSpans = NULL;
-static int finalMiny = 0, finalMaxy = -1;
-static int finalSize = 0;
-
-static int nspans = 0; /* total spans, not just y coords */
-
-struct finalSpan {
- struct finalSpan *next;
- int min, max; /* x values */
-};
-
-static struct finalSpan *freeFinalSpans, *tmpFinalSpan;
-
-# define allocFinalSpan() (freeFinalSpans ?\
- ((tmpFinalSpan = freeFinalSpans), \
- (freeFinalSpans = freeFinalSpans->next), \
- (tmpFinalSpan->next = 0), \
- tmpFinalSpan) : \
- realAllocSpan ())
-
-# define SPAN_CHUNK_SIZE 128
-
-struct finalSpanChunk {
- struct finalSpan data[SPAN_CHUNK_SIZE];
- struct finalSpanChunk *next;
-};
-
-static struct finalSpanChunk *chunks;
-
-static struct finalSpan *
-realAllocSpan (void)
-{
- struct finalSpanChunk *newChunk;
- struct finalSpan *span;
- int i;
-
- newChunk = xalloc (sizeof (struct finalSpanChunk));
- if (!newChunk)
- return (struct finalSpan *) NULL;
- newChunk->next = chunks;
- chunks = newChunk;
- freeFinalSpans = span = newChunk->data + 1;
- for (i = 1; i < SPAN_CHUNK_SIZE-1; i++) {
- span->next = span+1;
- span++;
- }
- span->next = 0;
- span = newChunk->data;
- span->next = 0;
- return span;
-}
-
-static void
-disposeFinalSpans (void)
-{
- struct finalSpanChunk *chunk, *next;
-
- for (chunk = chunks; chunk; chunk = next) {
- next = chunk->next;
- xfree (chunk);
- }
- chunks = 0;
- freeFinalSpans = 0;
- xfree(finalSpans);
- finalSpans = 0;
-}
-
-static void
-fillSpans (
- DrawablePtr pDrawable,
- GCPtr pGC)
-{
- struct finalSpan *span;
- DDXPointPtr xSpan;
- int *xWidth;
- int i;
- struct finalSpan **f;
- int spany;
- DDXPointPtr xSpans;
- int *xWidths;
-
- if (nspans == 0)
- return;
- xSpan = xSpans = xalloc (nspans * sizeof (DDXPointRec));
- xWidth = xWidths = xalloc (nspans * sizeof (int));
- if (xSpans && xWidths)
- {
- i = 0;
- f = finalSpans;
- for (spany = finalMiny; spany <= finalMaxy; spany++, f++) {
- for (span = *f; span; span=span->next) {
- if (span->max <= span->min)
- continue;
- xSpan->x = span->min;
- xSpan->y = spany;
- ++xSpan;
- *xWidth++ = span->max - span->min;
- ++i;
- }
- }
- (*pGC->ops->FillSpans) (pDrawable, pGC, i, xSpans, xWidths, TRUE);
- }
- disposeFinalSpans ();
- if (xSpans)
- xfree (xSpans);
- if (xWidths)
- xfree (xWidths);
- finalMiny = 0;
- finalMaxy = -1;
- finalSize = 0;
- nspans = 0;
-}
-
-# define SPAN_REALLOC 100
-
-# define findSpan(y) ((finalMiny <= (y) && (y) <= finalMaxy) ? \
- &finalSpans[(y) - finalMiny] : \
- realFindSpan (y))
-
-static struct finalSpan **
-realFindSpan (int y)
-{
- struct finalSpan **newSpans;
- int newSize, newMiny, newMaxy;
- int change;
- int i;
-
- if (y < finalMiny || y > finalMaxy) {
- if (!finalSize) {
- finalMiny = y;
- finalMaxy = y - 1;
- }
- if (y < finalMiny)
- change = finalMiny - y;
- else
- change = y - finalMaxy;
- if (change >= SPAN_REALLOC)
- change += SPAN_REALLOC;
- else
- change = SPAN_REALLOC;
- newSize = finalSize + change;
- newSpans = xalloc(newSize * sizeof (struct finalSpan *));
- if (!newSpans)
- return NULL;
- newMiny = finalMiny;
- newMaxy = finalMaxy;
- if (y < finalMiny)
- newMiny = finalMiny - change;
- else
- newMaxy = finalMaxy + change;
- if (finalSpans) {
- memmove(((char *) newSpans) + (finalMiny-newMiny) * sizeof (struct finalSpan *),
- (char *) finalSpans,
- finalSize * sizeof (struct finalSpan *));
- xfree (finalSpans);
- }
- if ((i = finalMiny - newMiny) > 0)
- bzero ((char *)newSpans, i * sizeof (struct finalSpan *));
- if ((i = newMaxy - finalMaxy) > 0)
- bzero ((char *)(newSpans + newSize - i),
- i * sizeof (struct finalSpan *));
- finalSpans = newSpans;
- finalMaxy = newMaxy;
- finalMiny = newMiny;
- finalSize = newSize;
- }
- return &finalSpans[y - finalMiny];
-}
-
-static void
-newFinalSpan (
- int y,
- int xmin,
- int xmax)
-{
- struct finalSpan *x;
- struct finalSpan **f;
- struct finalSpan *oldx;
- struct finalSpan *prev;
-
- f = findSpan (y);
- if (!f)
- return;
- oldx = 0;
- for (;;) {
- prev = 0;
- for (x = *f; x; x=x->next) {
- if (x == oldx) {
- prev = x;
- continue;
- }
- if (x->min <= xmax && xmin <= x->max) {
- if (oldx) {
- oldx->min = min (x->min, xmin);
- oldx->max = max (x->max, xmax);
- if (prev)
- prev->next = x->next;
- else
- *f = x->next;
- --nspans;
- } else {
- x->min = min (x->min, xmin);
- x->max = max (x->max, xmax);
- oldx = x;
- }
- xmin = oldx->min;
- xmax = oldx->max;
- break;
- }
- prev = x;
- }
- if (!x)
- break;
- }
- if (!oldx) {
- x = allocFinalSpan ();
- if (x)
- {
- x->min = xmin;
- x->max = xmax;
- x->next = *f;
- *f = x;
- ++nspans;
- }
- }
-}
-
-static void
-mirrorSppPoint (
- int quadrant,
- SppPointPtr sppPoint)
-{
- switch (quadrant) {
- case 0:
- break;
- case 1:
- sppPoint->x = -sppPoint->x;
- break;
- case 2:
- sppPoint->x = -sppPoint->x;
- sppPoint->y = -sppPoint->y;
- break;
- case 3:
- sppPoint->y = -sppPoint->y;
- break;
- }
- /*
- * and translate to X coordinate system
- */
- sppPoint->y = -sppPoint->y;
-}
-
-/*
- * split an arc into pieces which are scan-converted
- * in the first-quadrant and mirrored into position.
- * This is necessary as the scan-conversion code can
- * only deal with arcs completely contained in the
- * first quadrant.
- */
-
-static void
-drawArc (
- xArc *tarc,
- int l,
- int a0,
- int a1,
- miArcFacePtr right,
- miArcFacePtr left) /* save end line points */
-{
- struct arc_def def;
- struct accelerators acc;
- int startq, endq, curq;
- int rightq, leftq = 0, righta = 0, lefta = 0;
- miArcFacePtr passRight, passLeft;
- int q0 = 0, q1 = 0, mask;
- struct band {
- int a0, a1;
- int mask;
- } band[5], sweep[20];
- int bandno, sweepno;
- int i, j;
- int flipRight = 0, flipLeft = 0;
- int copyEnd = 0;
- miArcSpanData *spdata;
- Bool mustFree;
-
- spdata = miComputeWideEllipse(l, tarc, &mustFree);
- if (!spdata)
- return;
-
- if (a1 < a0)
- a1 += 360 * 64;
- startq = a0 / (90 * 64);
- if (a0 == a1)
- endq = startq;
- else
- endq = (a1-1) / (90 * 64);
- bandno = 0;
- curq = startq;
- rightq = -1;
- for (;;) {
- switch (curq) {
- case 0:
- if (a0 > 90 * 64)
- q0 = 0;
- else
- q0 = a0;
- if (a1 < 360 * 64)
- q1 = min (a1, 90 * 64);
- else
- q1 = 90 * 64;
- if (curq == startq && a0 == q0 && rightq < 0) {
- righta = q0;
- rightq = curq;
- }
- if (curq == endq && a1 == q1) {
- lefta = q1;
- leftq = curq;
- }
- break;
- case 1:
- if (a1 < 90 * 64)
- q0 = 0;
- else
- q0 = 180 * 64 - min (a1, 180 * 64);
- if (a0 > 180 * 64)
- q1 = 90 * 64;
- else
- q1 = 180 * 64 - max (a0, 90 * 64);
- if (curq == startq && 180 * 64 - a0 == q1) {
- righta = q1;
- rightq = curq;
- }
- if (curq == endq && 180 * 64 - a1 == q0) {
- lefta = q0;
- leftq = curq;
- }
- break;
- case 2:
- if (a0 > 270 * 64)
- q0 = 0;
- else
- q0 = max (a0, 180 * 64) - 180 * 64;
- if (a1 < 180 * 64)
- q1 = 90 * 64;
- else
- q1 = min (a1, 270 * 64) - 180 * 64;
- if (curq == startq && a0 - 180*64 == q0) {
- righta = q0;
- rightq = curq;
- }
- if (curq == endq && a1 - 180 * 64 == q1) {
- lefta = q1;
- leftq = curq;
- }
- break;
- case 3:
- if (a1 < 270 * 64)
- q0 = 0;
- else
- q0 = 360 * 64 - min (a1, 360 * 64);
- q1 = 360 * 64 - max (a0, 270 * 64);
- if (curq == startq && 360 * 64 - a0 == q1) {
- righta = q1;
- rightq = curq;
- }
- if (curq == endq && 360 * 64 - a1 == q0) {
- lefta = q0;
- leftq = curq;
- }
- break;
- }
- band[bandno].a0 = q0;
- band[bandno].a1 = q1;
- band[bandno].mask = 1 << curq;
- bandno++;
- if (curq == endq)
- break;
- curq++;
- if (curq == 4) {
- a0 = 0;
- a1 -= 360 * 64;
- curq = 0;
- endq -= 4;
- }
- }
- sweepno = 0;
- for (;;) {
- q0 = 90 * 64;
- mask = 0;
- /*
- * find left-most point
- */
- for (i = 0; i < bandno; i++)
- if (band[i].a0 <= q0) {
- q0 = band[i].a0;
- q1 = band[i].a1;
- mask = band[i].mask;
- }
- if (!mask)
- break;
- /*
- * locate next point of change
- */
- for (i = 0; i < bandno; i++)
- if (!(mask & band[i].mask)) {
- if (band[i].a0 == q0) {
- if (band[i].a1 < q1)
- q1 = band[i].a1;
- mask |= band[i].mask;
- } else if (band[i].a0 < q1)
- q1 = band[i].a0;
- }
- /*
- * create a new sweep
- */
- sweep[sweepno].a0 = q0;
- sweep[sweepno].a1 = q1;
- sweep[sweepno].mask = mask;
- sweepno++;
- /*
- * subtract the sweep from the affected bands
- */
- for (i = 0; i < bandno; i++)
- if (band[i].a0 == q0) {
- band[i].a0 = q1;
- /*
- * check if this band is empty
- */
- if (band[i].a0 == band[i].a1)
- band[i].a1 = band[i].a0 = 90 * 64 + 1;
- }
- }
- computeAcc (tarc, l, &def, &acc);
- for (j = 0; j < sweepno; j++) {
- mask = sweep[j].mask;
- passRight = passLeft = 0;
- if (mask & (1 << rightq)) {
- if (sweep[j].a0 == righta)
- passRight = right;
- else if (sweep[j].a1 == righta) {
- passLeft = right;
- flipRight = 1;
- }
- }
- if (mask & (1 << leftq)) {
- if (sweep[j].a1 == lefta)
- {
- if (passLeft)
- copyEnd = 1;
- passLeft = left;
- }
- else if (sweep[j].a0 == lefta) {
- if (passRight)
- copyEnd = 1;
- passRight = left;
- flipLeft = 1;
- }
- }
- drawQuadrant (&def, &acc, sweep[j].a0, sweep[j].a1, mask,
- passRight, passLeft, spdata);
- }
- /*
- * when copyEnd is set, both ends of the arc were computed
- * at the same time; drawQuadrant only takes one end though,
- * so the left end will be the only one holding the data. Copy
- * it from there.
- */
- if (copyEnd)
- *right = *left;
- /*
- * mirror the coordinates generated for the
- * faces of the arc
- */
- if (right) {
- mirrorSppPoint (rightq, &right->clock);
- mirrorSppPoint (rightq, &right->center);
- mirrorSppPoint (rightq, &right->counterClock);
- if (flipRight) {
- SppPointRec temp;
-
- temp = right->clock;
- right->clock = right->counterClock;
- right->counterClock = temp;
- }
- }
- if (left) {
- mirrorSppPoint (leftq, &left->counterClock);
- mirrorSppPoint (leftq, &left->center);
- mirrorSppPoint (leftq, &left->clock);
- if (flipLeft) {
- SppPointRec temp;
-
- temp = left->clock;
- left->clock = left->counterClock;
- left->counterClock = temp;
- }
- }
- if (mustFree)
- xfree(spdata);
-}
-
-static void
-drawQuadrant (
- struct arc_def *def,
- struct accelerators *acc,
- int a0,
- int a1,
- int mask,
- miArcFacePtr right,
- miArcFacePtr left,
- miArcSpanData *spdata)
-{
- struct arc_bound bound;
- double yy, x, xalt;
- int y, miny, maxy;
- int n;
- miArcSpan *span;
-
- def->a0 = ((double) a0) / 64.0;
- def->a1 = ((double) a1) / 64.0;
- computeBound (def, &bound, acc, right, left);
- yy = bound.inner.min;
- if (bound.outer.min < yy)
- yy = bound.outer.min;
- miny = ICEIL(yy - acc->fromIntY);
- yy = bound.inner.max;
- if (bound.outer.max > yy)
- yy = bound.outer.max;
- maxy = floor(yy - acc->fromIntY);
- y = spdata->k;
- span = spdata->spans;
- if (spdata->top)
- {
- if (a1 == 90 * 64 && (mask & 1))
- newFinalSpan (acc->yorgu - y - 1, acc->xorg, acc->xorg + 1);
- span++;
- }
- for (n = spdata->count1; --n >= 0; )
- {
- if (y < miny)
- return;
- if (y <= maxy) {
- arcSpan (y,
- span->lx, -span->lx, 0, span->lx + span->lw,
- def, &bound, acc, mask);
- if (span->rw + span->rx)
- tailSpan (y, -span->rw, -span->rx, def, &bound, acc, mask);
- }
- y--;
- span++;
- }
- if (y < miny)
- return;
- if (spdata->hole)
- {
- if (y <= maxy)
- arcSpan (y, 0, 0, 0, 1, def, &bound, acc, mask & 0xc);
- }
- for (n = spdata->count2; --n >= 0; )
- {
- if (y < miny)
- return;
- if (y <= maxy)
- arcSpan (y, span->lx, span->lw, span->rx, span->rw,
- def, &bound, acc, mask);
- y--;
- span++;
- }
- if (spdata->bot && miny <= y && y <= maxy)
- {
- n = mask;
- if (y == miny)
- n &= 0xc;
- if (span->rw <= 0) {
- arcSpan0 (span->lx, -span->lx, 0, span->lx + span->lw,
- def, &bound, acc, n);
- if (span->rw + span->rx)
- tailSpan (y, -span->rw, -span->rx, def, &bound, acc, n);
- }
- else
- arcSpan0 (span->lx, span->lw, span->rx, span->rw,
- def, &bound, acc, n);
- y--;
- }
- while (y >= miny) {
- yy = y + acc->fromIntY;
- if (def->w == def->h) {
- xalt = def->w - def->l;
- x = -sqrt(xalt * xalt - yy * yy);
- } else {
- x = tailX(yy, def, &bound, acc);
- if (acc->left.valid && boundedLe (yy, bound.left)) {
- xalt = intersectLine (yy, acc->left);
- if (xalt < x)
- x = xalt;
- }
- if (acc->right.valid && boundedLe (yy, bound.right)) {
- xalt = intersectLine (yy, acc->right);
- if (xalt < x)
- x = xalt;
- }
- }
- arcSpan (y,
- ICEIL(acc->fromIntX - x), 0,
- ICEIL(acc->fromIntX + x), 0,
- def, &bound, acc, mask);
- y--;
- }
-}
+/***********************************************************
+
+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.
+
+******************************************************************/
+/* Author: Keith Packard and Bob Scheifler */
+/* Warning: this code is toxic, do not dally very long here. */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <math.h>
+#include <X11/X.h>
+#include <X11/Xprotostr.h>
+#include "misc.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "windowstr.h"
+#include "mifpoly.h"
+#include "mi.h"
+#include "mifillarc.h"
+#include <X11/Xfuncproto.h>
+
+#ifdef _MSC_VER
+#define hypot _hypot
+#endif
+
+static double miDsin(double a);
+static double miDcos(double a);
+static double miDasin(double v);
+static double miDatan2(double dy, double dx);
+
+#ifndef HAVE_CBRT
+static double
+cbrt(double x)
+{
+ if (x > 0.0)
+ return pow(x, 1.0/3.0);
+ else
+ return -pow(-x, 1.0/3.0);
+}
+#endif
+
+/*
+ * some interesting sematic interpretation of the protocol:
+ *
+ * Self intersecting arcs (i.e. those spanning 360 degrees)
+ * never join with other arcs, and are drawn without caps
+ * (unless on/off dashed, in which case each dash segment
+ * is capped, except when the last segment meets the
+ * first segment, when no caps are drawn)
+ *
+ * double dash arcs are drawn in two parts, first the
+ * odd dashes (drawn in background) then the even dashes
+ * (drawn in foreground). This means that overlapping
+ * sections of foreground/background are drawn twice,
+ * first in background then in foreground. The double-draw
+ * occurs even when the function uses the destination values
+ * (e.g. xor mode). This is the same way the wide-line
+ * code works and should be "fixed".
+ *
+ */
+
+#undef max
+#undef min
+
+_X_INLINE static int max (const int x, const int y)
+{
+ return x>y? x:y;
+}
+
+_X_INLINE static int min (const int x, const int y)
+{
+ return x<y? x:y;
+}
+
+struct bound {
+ double min, max;
+};
+
+struct ibound {
+ int min, max;
+};
+
+#define boundedLe(value, bounds)\
+ ((bounds).min <= (value) && (value) <= (bounds).max)
+
+struct line {
+ double m, b;
+ int valid;
+};
+
+#define intersectLine(y,line) (line.m * (y) + line.b)
+
+/*
+ * these are all y value bounds
+ */
+
+struct arc_bound {
+ struct bound ellipse;
+ struct bound inner;
+ struct bound outer;
+ struct bound right;
+ struct bound left;
+ struct ibound inneri;
+ struct ibound outeri;
+};
+
+struct accelerators {
+ double tail_y;
+ double h2;
+ double w2;
+ double h4;
+ double w4;
+ double h2mw2;
+ double h2l;
+ double w2l;
+ double fromIntX;
+ double fromIntY;
+ struct line left, right;
+ int yorgu;
+ int yorgl;
+ int xorg;
+};
+
+struct arc_def {
+ double w, h, l;
+ double a0, a1;
+};
+
+# define todeg(xAngle) (((double) (xAngle)) / 64.0)
+
+# define RIGHT_END 0
+# define LEFT_END 1
+
+typedef struct _miArcJoin {
+ int arcIndex0, arcIndex1;
+ int phase0, phase1;
+ int end0, end1;
+} miArcJoinRec, *miArcJoinPtr;
+
+typedef struct _miArcCap {
+ int arcIndex;
+ int end;
+} miArcCapRec, *miArcCapPtr;
+
+typedef struct _miArcFace {
+ SppPointRec clock;
+ SppPointRec center;
+ SppPointRec counterClock;
+} miArcFaceRec, *miArcFacePtr;
+
+typedef struct _miArcData {
+ xArc arc;
+ int render; /* non-zero means render after drawing */
+ int join; /* related join */
+ int cap; /* related cap */
+ int selfJoin; /* final dash meets first dash */
+ miArcFaceRec bounds[2];
+ double x0, y0, x1, y1;
+} miArcDataRec, *miArcDataPtr;
+
+/*
+ * This is an entire sequence of arcs, computed and categorized according
+ * to operation. miDashArcs generates either one or two of these.
+ */
+
+typedef struct _miPolyArc {
+ int narcs;
+ miArcDataPtr arcs;
+ int ncaps;
+ miArcCapPtr caps;
+ int njoins;
+ miArcJoinPtr joins;
+} miPolyArcRec, *miPolyArcPtr;
+
+#define GCValsFunction 0
+#define GCValsForeground 1
+#define GCValsBackground 2
+#define GCValsLineWidth 3
+#define GCValsCapStyle 4
+#define GCValsJoinStyle 5
+#define GCValsMask (GCFunction | GCForeground | GCBackground | \
+ GCLineWidth | GCCapStyle | GCJoinStyle)
+static CARD32 gcvals[6];
+
+static void fillSpans(DrawablePtr pDrawable, GCPtr pGC);
+static void newFinalSpan(int y, int xmin, int xmax);
+static void drawArc(xArc *tarc, int l, int a0, int a1, miArcFacePtr right,
+ miArcFacePtr left);
+static void drawZeroArc(DrawablePtr pDraw, GCPtr pGC, xArc *tarc, int lw,
+ miArcFacePtr left, miArcFacePtr right);
+static void miArcJoin(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pLeft,
+ miArcFacePtr pRight, int xOrgLeft, int yOrgLeft,
+ double xFtransLeft, double yFtransLeft,
+ int xOrgRight, int yOrgRight,
+ double xFtransRight, double yFtransRight);
+static void miArcCap(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pFace,
+ int end, int xOrg, int yOrg, double xFtrans,
+ double yFtrans);
+static void miRoundCap(DrawablePtr pDraw, GCPtr pGC, SppPointRec pCenter,
+ SppPointRec pEnd, SppPointRec pCorner,
+ SppPointRec pOtherCorner, int fLineEnd,
+ int xOrg, int yOrg, double xFtrans, double yFtrans);
+static void miFreeArcs(miPolyArcPtr arcs, GCPtr pGC);
+static miPolyArcPtr miComputeArcs(xArc *parcs, int narcs, GCPtr pGC);
+static int miGetArcPts(SppArcPtr parc, int cpt, SppPointPtr *ppPts);
+
+# define CUBED_ROOT_2 1.2599210498948732038115849718451499938964
+# define CUBED_ROOT_4 1.5874010519681993173435330390930175781250
+
+/*
+ * draw one segment of the arc using the arc spans generation routines
+ */
+
+static void
+miArcSegment(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ xArc tarc,
+ miArcFacePtr right,
+ miArcFacePtr left)
+{
+ int l = pGC->lineWidth;
+ int a0, a1, startAngle, endAngle;
+ miArcFacePtr temp;
+
+ if (!l)
+ l = 1;
+
+ if (tarc.width == 0 || tarc.height == 0) {
+ drawZeroArc (pDraw, pGC, &tarc, l, left, right);
+ return;
+ }
+
+ if (pGC->miTranslate) {
+ tarc.x += pDraw->x;
+ tarc.y += pDraw->y;
+ }
+
+ a0 = tarc.angle1;
+ a1 = tarc.angle2;
+ if (a1 > FULLCIRCLE)
+ a1 = FULLCIRCLE;
+ else if (a1 < -FULLCIRCLE)
+ a1 = -FULLCIRCLE;
+ if (a1 < 0) {
+ startAngle = a0 + a1;
+ endAngle = a0;
+ temp = right;
+ right = left;
+ left = temp;
+ } else {
+ startAngle = a0;
+ endAngle = a0 + a1;
+ }
+ /*
+ * bounds check the two angles
+ */
+ if (startAngle < 0)
+ startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE;
+ if (startAngle >= FULLCIRCLE)
+ startAngle = startAngle % FULLCIRCLE;
+ if (endAngle < 0)
+ endAngle = FULLCIRCLE - (-endAngle) % FULLCIRCLE;
+ if (endAngle > FULLCIRCLE)
+ endAngle = (endAngle-1) % FULLCIRCLE + 1;
+ if ((startAngle == endAngle) && a1) {
+ startAngle = 0;
+ endAngle = FULLCIRCLE;
+ }
+
+ drawArc (&tarc, l, startAngle, endAngle, right, left);
+}
+
+/*
+
+Three equations combine to describe the boundaries of the arc
+
+x^2/w^2 + y^2/h^2 = 1 ellipse itself
+(X-x)^2 + (Y-y)^2 = r^2 circle at (x, y) on the ellipse
+(Y-y) = (X-x)*w^2*y/(h^2*x) normal at (x, y) on the ellipse
+
+These lead to a quartic relating Y and y
+
+y^4 - (2Y)y^3 + (Y^2 + (h^4 - w^2*r^2)/(w^2 - h^2))y^2
+ - (2Y*h^4/(w^2 - h^2))y + (Y^2*h^4)/(w^2 - h^2) = 0
+
+The reducible cubic obtained from this quartic is
+
+z^3 - (3N)z^2 - 2V = 0
+
+where
+
+N = (Y^2 + (h^4 - w^2*r^2/(w^2 - h^2)))/6
+V = w^2*r^2*Y^2*h^4/(4 *(w^2 - h^2)^2)
+
+Let
+
+t = z - N
+p = -N^2
+q = -N^3 - V
+
+Then we get
+
+t^3 + 3pt + 2q = 0
+
+The discriminant of this cubic is
+
+D = q^2 + p^3
+
+When D > 0, a real root is obtained as
+
+z = N + cbrt(-q+sqrt(D)) + cbrt(-q-sqrt(D))
+
+When D < 0, a real root is obtained as
+
+z = N - 2m*cos(acos(-q/m^3)/3)
+
+where
+
+m = sqrt(|p|) * sign(q)
+
+Given a real root Z of the cubic, the roots of the quartic are the roots
+of the two quadratics
+
+y^2 + ((b+A)/2)y + (Z + (bZ - d)/A) = 0
+
+where
+
+A = +/- sqrt(8Z + b^2 - 4c)
+b, c, d are the cubic, quadratic, and linear coefficients of the quartic
+
+Some experimentation is then required to determine which solutions
+correspond to the inner and outer boundaries.
+
+*/
+
+typedef struct {
+ short lx, lw, rx, rw;
+} miArcSpan;
+
+typedef struct {
+ miArcSpan *spans;
+ int count1, count2, k;
+ char top, bot, hole;
+} miArcSpanData;
+
+static void drawQuadrant(struct arc_def *def, struct accelerators *acc,
+ int a0, int a1, int mask, miArcFacePtr right,
+ miArcFacePtr left, miArcSpanData *spdata);
+
+static void
+miComputeCircleSpans(
+ int lw,
+ xArc *parc,
+ miArcSpanData *spdata)
+{
+ miArcSpan *span;
+ int doinner;
+ int x, y, e;
+ int xk, yk, xm, ym, dx, dy;
+ int slw, inslw;
+ int inx = 0, iny, ine = 0;
+ int inxk = 0, inyk = 0, inxm = 0, inym = 0;
+
+ doinner = -lw;
+ slw = parc->width - doinner;
+ y = parc->height >> 1;
+ dy = parc->height & 1;
+ dx = 1 - dy;
+ MIWIDEARCSETUP(x, y, dy, slw, e, xk, xm, yk, ym);
+ inslw = parc->width + doinner;
+ if (inslw > 0)
+ {
+ spdata->hole = spdata->top;
+ MIWIDEARCSETUP(inx, iny, dy, inslw, ine, inxk, inxm, inyk, inym);
+ }
+ else
+ {
+ spdata->hole = FALSE;
+ doinner = -y;
+ }
+ spdata->count1 = -doinner - spdata->top;
+ spdata->count2 = y + doinner;
+ span = spdata->spans;
+ while (y)
+ {
+ MIFILLARCSTEP(slw);
+ span->lx = dy - x;
+ if (++doinner <= 0)
+ {
+ span->lw = slw;
+ span->rx = 0;
+ span->rw = span->lx + slw;
+ }
+ else
+ {
+ MIFILLINARCSTEP(inslw);
+ span->lw = x - inx;
+ span->rx = dy - inx + inslw;
+ span->rw = inx - x + slw - inslw;
+ }
+ span++;
+ }
+ if (spdata->bot)
+ {
+ if (spdata->count2)
+ spdata->count2--;
+ else
+ {
+ if (lw > (int)parc->height)
+ span[-1].rx = span[-1].rw = -((lw - (int)parc->height) >> 1);
+ else
+ span[-1].rw = 0;
+ spdata->count1--;
+ }
+ }
+}
+
+static void
+miComputeEllipseSpans(
+ int lw,
+ xArc *parc,
+ miArcSpanData *spdata)
+{
+ miArcSpan *span;
+ double w, h, r, xorg;
+ double Hs, Hf, WH, K, Vk, Nk, Fk, Vr, N, Nc, Z, rs;
+ double A, T, b, d, x, y, t, inx, outx = 0.0, hepp, hepm;
+ int flip, solution;
+
+ w = (double)parc->width / 2.0;
+ h = (double)parc->height / 2.0;
+ r = lw / 2.0;
+ rs = r * r;
+ Hs = h * h;
+ WH = w * w - Hs;
+ Nk = w * r;
+ Vk = (Nk * Hs) / (WH + WH);
+ Hf = Hs * Hs;
+ Nk = (Hf - Nk * Nk) / WH;
+ Fk = Hf / WH;
+ hepp = h + EPSILON;
+ hepm = h - EPSILON;
+ K = h + ((lw - 1) >> 1);
+ span = spdata->spans;
+ if (parc->width & 1)
+ xorg = .5;
+ else
+ xorg = 0.0;
+ if (spdata->top)
+ {
+ span->lx = 0;
+ span->lw = 1;
+ span++;
+ }
+ spdata->count1 = 0;
+ spdata->count2 = 0;
+ spdata->hole = (spdata->top &&
+ (int)parc->height * lw <= (int)(parc->width * parc->width) &&
+ lw < (int)parc->height);
+ for (; K > 0.0; K -= 1.0)
+ {
+ N = (K * K + Nk) / 6.0;
+ Nc = N * N * N;
+ Vr = Vk * K;
+ t = Nc + Vr * Vr;
+ d = Nc + t;
+ if (d < 0.0) {
+ d = Nc;
+ b = N;
+ if ( (b < 0.0) == (t < 0.0) )
+ {
+ b = -b;
+ d = -d;
+ }
+ Z = N - 2.0 * b * cos(acos(-t / d) / 3.0);
+ if ( (Z < 0.0) == (Vr < 0.0) )
+ flip = 2;
+ else
+ flip = 1;
+ }
+ else
+ {
+ d = Vr * sqrt(d);
+ Z = N + cbrt(t + d) + cbrt(t - d);
+ flip = 0;
+ }
+ A = sqrt((Z + Z) - Nk);
+ T = (Fk - Z) * K / A;
+ inx = 0.0;
+ solution = FALSE;
+ b = -A + K;
+ d = b * b - 4 * (Z + T);
+ if (d >= 0)
+ {
+ d = sqrt(d);
+ y = (b + d) / 2;
+ if ((y >= 0.0) && (y < hepp))
+ {
+ solution = TRUE;
+ if (y > hepm)
+ y = h;
+ t = y / h;
+ x = w * sqrt(1 - (t * t));
+ t = K - y;
+ if (rs - (t * t) >= 0)
+ t = sqrt(rs - (t * t));
+ else
+ t = 0;
+ if (flip == 2)
+ inx = x - t;
+ else
+ outx = x + t;
+ }
+ }
+ b = A + K;
+ d = b * b - 4 * (Z - T);
+ /* Because of the large magnitudes involved, we lose enough precision
+ * that sometimes we end up with a negative value near the axis, when
+ * it should be positive. This is a workaround.
+ */
+ if (d < 0 && !solution)
+ d = 0.0;
+ if (d >= 0) {
+ d = sqrt(d);
+ y = (b + d) / 2;
+ if (y < hepp)
+ {
+ if (y > hepm)
+ y = h;
+ t = y / h;
+ x = w * sqrt(1 - (t * t));
+ t = K - y;
+ if (rs - (t * t) >= 0)
+ inx = x - sqrt(rs - (t * t));
+ else
+ inx = x;
+ }
+ y = (b - d) / 2;
+ if (y >= 0.0)
+ {
+ if (y > hepm)
+ y = h;
+ t = y / h;
+ x = w * sqrt(1 - (t * t));
+ t = K - y;
+ if (rs - (t * t) >= 0)
+ t = sqrt(rs - (t * t));
+ else
+ t = 0;
+ if (flip == 1)
+ inx = x - t;
+ else
+ outx = x + t;
+ }
+ }
+ span->lx = ICEIL(xorg - outx);
+ if (inx <= 0.0)
+ {
+ spdata->count1++;
+ span->lw = ICEIL(xorg + outx) - span->lx;
+ span->rx = ICEIL(xorg + inx);
+ span->rw = -ICEIL(xorg - inx);
+ }
+ else
+ {
+ spdata->count2++;
+ span->lw = ICEIL(xorg - inx) - span->lx;
+ span->rx = ICEIL(xorg + inx);
+ span->rw = ICEIL(xorg + outx) - span->rx;
+ }
+ span++;
+ }
+ if (spdata->bot)
+ {
+ outx = w + r;
+ if (r >= h && r <= w)
+ inx = 0.0;
+ else if (Nk < 0.0 && -Nk < Hs)
+ {
+ inx = w * sqrt(1 + Nk / Hs) - sqrt(rs + Nk);
+ if (inx > w - r)
+ inx = w - r;
+ }
+ else
+ inx = w - r;
+ span->lx = ICEIL(xorg - outx);
+ if (inx <= 0.0)
+ {
+ span->lw = ICEIL(xorg + outx) - span->lx;
+ span->rx = ICEIL(xorg + inx);
+ span->rw = -ICEIL(xorg - inx);
+ }
+ else
+ {
+ span->lw = ICEIL(xorg - inx) - span->lx;
+ span->rx = ICEIL(xorg + inx);
+ span->rw = ICEIL(xorg + outx) - span->rx;
+ }
+ }
+ if (spdata->hole)
+ {
+ span = &spdata->spans[spdata->count1];
+ span->lw = -span->lx;
+ span->rx = 1;
+ span->rw = span->lw;
+ spdata->count1--;
+ spdata->count2++;
+ }
+}
+
+static double
+tailX(
+ double K,
+ struct arc_def *def,
+ struct arc_bound *bounds,
+ struct accelerators *acc)
+{
+ double w, h, r;
+ double Hs, Hf, WH, Vk, Nk, Fk, Vr, N, Nc, Z, rs;
+ double A, T, b, d, x, y, t, hepp, hepm;
+ int flip, solution;
+ double xs[2];
+ double *xp;
+
+ w = def->w;
+ h = def->h;
+ r = def->l;
+ rs = r * r;
+ Hs = acc->h2;
+ WH = -acc->h2mw2;
+ Nk = def->w * r;
+ Vk = (Nk * Hs) / (WH + WH);
+ Hf = acc->h4;
+ Nk = (Hf - Nk * Nk) / WH;
+ if (K == 0.0) {
+ if (Nk < 0.0 && -Nk < Hs) {
+ xs[0] = w * sqrt(1 + Nk / Hs) - sqrt(rs + Nk);
+ xs[1] = w - r;
+ if (acc->left.valid && boundedLe(K, bounds->left) &&
+ !boundedLe(K, bounds->outer) && xs[0] >= 0.0 && xs[1] >= 0.0)
+ return xs[1];
+ if (acc->right.valid && boundedLe(K, bounds->right) &&
+ !boundedLe(K, bounds->inner) && xs[0] <= 0.0 && xs[1] <= 0.0)
+ return xs[1];
+ return xs[0];
+ }
+ return w - r;
+ }
+ Fk = Hf / WH;
+ hepp = h + EPSILON;
+ hepm = h - EPSILON;
+ N = (K * K + Nk) / 6.0;
+ Nc = N * N * N;
+ Vr = Vk * K;
+ xp = xs;
+ xs[0] = 0.0;
+ t = Nc + Vr * Vr;
+ d = Nc + t;
+ if (d < 0.0) {
+ d = Nc;
+ b = N;
+ if ( (b < 0.0) == (t < 0.0) )
+ {
+ b = -b;
+ d = -d;
+ }
+ Z = N - 2.0 * b * cos(acos(-t / d) / 3.0);
+ if ( (Z < 0.0) == (Vr < 0.0) )
+ flip = 2;
+ else
+ flip = 1;
+ }
+ else
+ {
+ d = Vr * sqrt(d);
+ Z = N + cbrt(t + d) + cbrt(t - d);
+ flip = 0;
+ }
+ A = sqrt((Z + Z) - Nk);
+ T = (Fk - Z) * K / A;
+ solution = FALSE;
+ b = -A + K;
+ d = b * b - 4 * (Z + T);
+ if (d >= 0 && flip == 2)
+ {
+ d = sqrt(d);
+ y = (b + d) / 2;
+ if ((y >= 0.0) && (y < hepp))
+ {
+ solution = TRUE;
+ if (y > hepm)
+ y = h;
+ t = y / h;
+ x = w * sqrt(1 - (t * t));
+ t = K - y;
+ if (rs - (t * t) >= 0)
+ t = sqrt(rs - (t * t));
+ else
+ t = 0;
+ *xp++ = x - t;
+ }
+ }
+ b = A + K;
+ d = b * b - 4 * (Z - T);
+ /* Because of the large magnitudes involved, we lose enough precision
+ * that sometimes we end up with a negative value near the axis, when
+ * it should be positive. This is a workaround.
+ */
+ if (d < 0 && !solution)
+ d = 0.0;
+ if (d >= 0) {
+ d = sqrt(d);
+ y = (b + d) / 2;
+ if (y < hepp)
+ {
+ if (y > hepm)
+ y = h;
+ t = y / h;
+ x = w * sqrt(1 - (t * t));
+ t = K - y;
+ if (rs - (t * t) >= 0)
+ *xp++ = x - sqrt(rs - (t * t));
+ else
+ *xp++ = x;
+ }
+ y = (b - d) / 2;
+ if (y >= 0.0 && flip == 1)
+ {
+ if (y > hepm)
+ y = h;
+ t = y / h;
+ x = w * sqrt(1 - (t * t));
+ t = K - y;
+ if (rs - (t * t) >= 0)
+ t = sqrt(rs - (t * t));
+ else
+ t = 0;
+ *xp++ = x - t;
+ }
+ }
+ if (xp > &xs[1]) {
+ if (acc->left.valid && boundedLe(K, bounds->left) &&
+ !boundedLe(K, bounds->outer) && xs[0] >= 0.0 && xs[1] >= 0.0)
+ return xs[1];
+ if (acc->right.valid && boundedLe(K, bounds->right) &&
+ !boundedLe(K, bounds->inner) && xs[0] <= 0.0 && xs[1] <= 0.0)
+ return xs[1];
+ }
+ return xs[0];
+}
+
+static miArcSpanData *
+miComputeWideEllipse(int lw, xArc *parc)
+{
+ miArcSpanData *spdata = NULL;
+ int k;
+
+ if (!lw)
+ lw = 1;
+ k = (parc->height >> 1) + ((lw - 1) >> 1);
+ spdata = xalloc(sizeof(miArcSpanData) + sizeof(miArcSpan) * (k + 2));
+ if (!spdata)
+ return NULL;
+ spdata->spans = (miArcSpan *)(spdata + 1);
+ spdata->k = k;
+ spdata->top = !(lw & 1) && !(parc->width & 1);
+ spdata->bot = !(parc->height & 1);
+ if (parc->width == parc->height)
+ miComputeCircleSpans(lw, parc, spdata);
+ else
+ miComputeEllipseSpans(lw, parc, spdata);
+ return spdata;
+}
+
+static void
+miFillWideEllipse(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ xArc *parc)
+{
+ DDXPointPtr points;
+ DDXPointPtr pts;
+ int *widths;
+ int *wids;
+ miArcSpanData *spdata;
+ miArcSpan *span;
+ int xorg, yorgu, yorgl;
+ int n;
+
+ yorgu = parc->height + pGC->lineWidth;
+ n = (sizeof(int) * 2) * yorgu;
+ widths = xalloc(n + (sizeof(DDXPointRec) * 2) * yorgu);
+ if (!widths)
+ return;
+ points = (DDXPointPtr)((char *)widths + n);
+ spdata = miComputeWideEllipse((int)pGC->lineWidth, parc);
+ if (!spdata)
+ {
+ xfree(widths);
+ return;
+ }
+ pts = points;
+ wids = widths;
+ span = spdata->spans;
+ xorg = parc->x + (parc->width >> 1);
+ yorgu = parc->y + (parc->height >> 1);
+ yorgl = yorgu + (parc->height & 1);
+ if (pGC->miTranslate)
+ {
+ xorg += pDraw->x;
+ yorgu += pDraw->y;
+ yorgl += pDraw->y;
+ }
+ yorgu -= spdata->k;
+ yorgl += spdata->k;
+ if (spdata->top)
+ {
+ pts->x = xorg;
+ pts->y = yorgu - 1;
+ pts++;
+ *wids++ = 1;
+ span++;
+ }
+ for (n = spdata->count1; --n >= 0; )
+ {
+ pts[0].x = xorg + span->lx;
+ pts[0].y = yorgu;
+ wids[0] = span->lw;
+ pts[1].x = pts[0].x;
+ pts[1].y = yorgl;
+ wids[1] = wids[0];
+ yorgu++;
+ yorgl--;
+ pts += 2;
+ wids += 2;
+ span++;
+ }
+ if (spdata->hole)
+ {
+ pts[0].x = xorg;
+ pts[0].y = yorgl;
+ wids[0] = 1;
+ pts++;
+ wids++;
+ }
+ for (n = spdata->count2; --n >= 0; )
+ {
+ pts[0].x = xorg + span->lx;
+ pts[0].y = yorgu;
+ wids[0] = span->lw;
+ pts[1].x = xorg + span->rx;
+ pts[1].y = pts[0].y;
+ wids[1] = span->rw;
+ pts[2].x = pts[0].x;
+ pts[2].y = yorgl;
+ wids[2] = wids[0];
+ pts[3].x = pts[1].x;
+ pts[3].y = pts[2].y;
+ wids[3] = wids[1];
+ yorgu++;
+ yorgl--;
+ pts += 4;
+ wids += 4;
+ span++;
+ }
+ if (spdata->bot)
+ {
+ if (span->rw <= 0)
+ {
+ pts[0].x = xorg + span->lx;
+ pts[0].y = yorgu;
+ wids[0] = span->lw;
+ pts++;
+ wids++;
+ }
+ else
+ {
+ pts[0].x = xorg + span->lx;
+ pts[0].y = yorgu;
+ wids[0] = span->lw;
+ pts[1].x = xorg + span->rx;
+ pts[1].y = pts[0].y;
+ wids[1] = span->rw;
+ pts += 2;
+ wids += 2;
+ }
+ }
+ xfree(spdata);
+ (*pGC->ops->FillSpans)(pDraw, pGC, pts - points, points, widths, FALSE);
+
+ xfree(widths);
+}
+
+/*
+ * miPolyArc strategy:
+ *
+ * If arc is zero width and solid, we don't have to worry about the rasterop
+ * or join styles. For wide solid circles, we use a fast integer algorithm.
+ * For wide solid ellipses, we use special case floating point code.
+ * Otherwise, we set up pDrawTo and pGCTo according to the rasterop, then
+ * draw using pGCTo and pDrawTo. If the raster-op was "tricky," that is,
+ * if it involves the destination, then we use PushPixels to move the bits
+ * from the scratch drawable to pDraw. (See the wide line code for a
+ * fuller explanation of this.)
+ */
+
+void
+miPolyArc(DrawablePtr pDraw, GCPtr pGC, int narcs, xArc *parcs)
+{
+ int i;
+ xArc *parc;
+ int xMin, xMax, yMin, yMax;
+ int pixmapWidth = 0, pixmapHeight = 0;
+ int xOrg = 0, yOrg = 0;
+ int width;
+ Bool fTricky;
+ DrawablePtr pDrawTo;
+ CARD32 fg, bg;
+ GCPtr pGCTo;
+ miPolyArcPtr polyArcs;
+ int cap[2], join[2];
+ int iphase;
+ int halfWidth;
+
+ width = pGC->lineWidth;
+ if(width == 0 && pGC->lineStyle == LineSolid)
+ {
+ for(i = narcs, parc = parcs; --i >= 0; parc++)
+ miArcSegment( pDraw, pGC, *parc,
+ (miArcFacePtr) 0, (miArcFacePtr) 0 );
+ fillSpans (pDraw, pGC);
+ }
+ else
+ {
+ if ((pGC->lineStyle == LineSolid) && narcs)
+ {
+ while (parcs->width && parcs->height &&
+ (parcs->angle2 >= FULLCIRCLE ||
+ parcs->angle2 <= -FULLCIRCLE))
+ {
+ miFillWideEllipse(pDraw, pGC, parcs);
+ if (!--narcs)
+ return;
+ parcs++;
+ }
+ }
+
+ /* Set up pDrawTo and pGCTo based on the rasterop */
+ switch(pGC->alu)
+ {
+ case GXclear: /* 0 */
+ case GXcopy: /* src */
+ case GXcopyInverted: /* NOT src */
+ case GXset: /* 1 */
+ fTricky = FALSE;
+ pDrawTo = pDraw;
+ pGCTo = pGC;
+ break;
+ default:
+ fTricky = TRUE;
+
+ /* find bounding box around arcs */
+ xMin = yMin = MAXSHORT;
+ xMax = yMax = MINSHORT;
+
+ for(i = narcs, parc = parcs; --i >= 0; parc++)
+ {
+ xMin = min (xMin, parc->x);
+ yMin = min (yMin, parc->y);
+ xMax = max (xMax, (parc->x + (int) parc->width));
+ yMax = max (yMax, (parc->y + (int) parc->height));
+ }
+
+ /* expand box to deal with line widths */
+ halfWidth = (width + 1)/2;
+ xMin -= halfWidth;
+ yMin -= halfWidth;
+ xMax += halfWidth;
+ yMax += halfWidth;
+
+ /* compute pixmap size; limit it to size of drawable */
+ xOrg = max(xMin, 0);
+ yOrg = max(yMin, 0);
+ pixmapWidth = min(xMax, pDraw->width) - xOrg;
+ pixmapHeight = min(yMax, pDraw->height) - yOrg;
+
+ /* if nothing left, return */
+ if ( (pixmapWidth <= 0) || (pixmapHeight <= 0) ) return;
+
+ for(i = narcs, parc = parcs; --i >= 0; parc++)
+ {
+ parc->x -= xOrg;
+ parc->y -= yOrg;
+ }
+ if (pGC->miTranslate)
+ {
+ xOrg += pDraw->x;
+ yOrg += pDraw->y;
+ }
+
+ /* set up scratch GC */
+
+ pGCTo = GetScratchGC(1, pDraw->pScreen);
+ if (!pGCTo)
+ return;
+ gcvals[GCValsFunction] = GXcopy;
+ gcvals[GCValsForeground] = 1;
+ gcvals[GCValsBackground] = 0;
+ gcvals[GCValsLineWidth] = pGC->lineWidth;
+ gcvals[GCValsCapStyle] = pGC->capStyle;
+ gcvals[GCValsJoinStyle] = pGC->joinStyle;
+ dixChangeGC(NullClient, pGCTo, GCValsMask, gcvals, NULL);
+
+ /* allocate a 1 bit deep pixmap of the appropriate size, and
+ * validate it */
+ pDrawTo = (DrawablePtr)(*pDraw->pScreen->CreatePixmap)
+ (pDraw->pScreen, pixmapWidth, pixmapHeight, 1,
+ CREATE_PIXMAP_USAGE_SCRATCH);
+ if (!pDrawTo)
+ {
+ FreeScratchGC(pGCTo);
+ return;
+ }
+ ValidateGC(pDrawTo, pGCTo);
+ miClearDrawable(pDrawTo, pGCTo);
+ }
+
+ fg = pGC->fgPixel;
+ bg = pGC->bgPixel;
+ if ((pGC->fillStyle == FillTiled) ||
+ (pGC->fillStyle == FillOpaqueStippled))
+ bg = fg; /* the protocol sez these don't cause color changes */
+
+ polyArcs = miComputeArcs (parcs, narcs, pGC);
+
+ if (!polyArcs)
+ {
+ if (fTricky) {
+ (*pDraw->pScreen->DestroyPixmap) ((PixmapPtr)pDrawTo);
+ FreeScratchGC (pGCTo);
+ }
+ return;
+ }
+
+ cap[0] = cap[1] = 0;
+ join[0] = join[1] = 0;
+ for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0);
+ iphase >= 0;
+ iphase--)
+ {
+ if (iphase == 1) {
+ dixChangeGC (NullClient, pGC, GCForeground, &bg, NULL);
+ ValidateGC (pDraw, pGC);
+ } else if (pGC->lineStyle == LineDoubleDash) {
+ dixChangeGC (NullClient, pGC, GCForeground, &fg, NULL);
+ ValidateGC (pDraw, pGC);
+ }
+ for (i = 0; i < polyArcs[iphase].narcs; i++) {
+ miArcDataPtr arcData;
+
+ arcData = &polyArcs[iphase].arcs[i];
+ miArcSegment(pDrawTo, pGCTo, arcData->arc,
+ &arcData->bounds[RIGHT_END],
+ &arcData->bounds[LEFT_END]);
+ if (polyArcs[iphase].arcs[i].render) {
+ fillSpans (pDrawTo, pGCTo);
+ /*
+ * don't cap self-joining arcs
+ */
+ if (polyArcs[iphase].arcs[i].selfJoin &&
+ cap[iphase] < polyArcs[iphase].arcs[i].cap)
+ cap[iphase]++;
+ while (cap[iphase] < polyArcs[iphase].arcs[i].cap) {
+ int arcIndex, end;
+ miArcDataPtr arcData0;
+
+ arcIndex = polyArcs[iphase].caps[cap[iphase]].arcIndex;
+ end = polyArcs[iphase].caps[cap[iphase]].end;
+ arcData0 = &polyArcs[iphase].arcs[arcIndex];
+ miArcCap (pDrawTo, pGCTo,
+ &arcData0->bounds[end], end,
+ arcData0->arc.x, arcData0->arc.y,
+ (double) arcData0->arc.width / 2.0,
+ (double) arcData0->arc.height / 2.0);
+ ++cap[iphase];
+ }
+ while (join[iphase] < polyArcs[iphase].arcs[i].join) {
+ int arcIndex0, arcIndex1, end0, end1;
+ int phase0, phase1;
+ miArcDataPtr arcData0, arcData1;
+ miArcJoinPtr joinp;
+
+ joinp = &polyArcs[iphase].joins[join[iphase]];
+ arcIndex0 = joinp->arcIndex0;
+ end0 = joinp->end0;
+ arcIndex1 = joinp->arcIndex1;
+ end1 = joinp->end1;
+ phase0 = joinp->phase0;
+ phase1 = joinp->phase1;
+ arcData0 = &polyArcs[phase0].arcs[arcIndex0];
+ arcData1 = &polyArcs[phase1].arcs[arcIndex1];
+ miArcJoin (pDrawTo, pGCTo,
+ &arcData0->bounds[end0],
+ &arcData1->bounds[end1],
+ arcData0->arc.x, arcData0->arc.y,
+ (double) arcData0->arc.width / 2.0,
+ (double) arcData0->arc.height / 2.0,
+ arcData1->arc.x, arcData1->arc.y,
+ (double) arcData1->arc.width / 2.0,
+ (double) arcData1->arc.height / 2.0);
+ ++join[iphase];
+ }
+ if (fTricky) {
+ if (pGC->serialNumber != pDraw->serialNumber)
+ ValidateGC (pDraw, pGC);
+ (*pGC->ops->PushPixels) (pGC, (PixmapPtr)pDrawTo,
+ pDraw, pixmapWidth, pixmapHeight, xOrg, yOrg);
+ miClearDrawable ((DrawablePtr) pDrawTo, pGCTo);
+ }
+ }
+ }
+ }
+ miFreeArcs(polyArcs, pGC);
+
+ if(fTricky)
+ {
+ (*pGCTo->pScreen->DestroyPixmap)((PixmapPtr)pDrawTo);
+ FreeScratchGC(pGCTo);
+ }
+ }
+}
+
+static double
+angleBetween (SppPointRec center, SppPointRec point1, SppPointRec point2)
+{
+ double a1, a2, a;
+
+ /*
+ * reflect from X coordinates back to ellipse
+ * coordinates -- y increasing upwards
+ */
+ a1 = miDatan2 (- (point1.y - center.y), point1.x - center.x);
+ a2 = miDatan2 (- (point2.y - center.y), point2.x - center.x);
+ a = a2 - a1;
+ if (a <= -180.0)
+ a += 360.0;
+ else if (a > 180.0)
+ a -= 360.0;
+ return a;
+}
+
+static void
+translateBounds (
+ miArcFacePtr b,
+ int x,
+ int y,
+ double fx,
+ double fy)
+{
+ fx += x;
+ fy += y;
+ b->clock.x -= fx;
+ b->clock.y -= fy;
+ b->center.x -= fx;
+ b->center.y -= fy;
+ b->counterClock.x -= fx;
+ b->counterClock.y -= fy;
+}
+
+static void
+miArcJoin(DrawablePtr pDraw, GCPtr pGC, miArcFacePtr pLeft,
+ miArcFacePtr pRight, int xOrgLeft, int yOrgLeft,
+ double xFtransLeft, double yFtransLeft,
+ int xOrgRight, int yOrgRight,
+ double xFtransRight, double yFtransRight)
+{
+ SppPointRec center, corner, otherCorner;
+ SppPointRec poly[5], e;
+ SppPointPtr pArcPts;
+ int cpt;
+ SppArcRec arc;
+ miArcFaceRec Right, Left;
+ int polyLen = 0;
+ int xOrg, yOrg;
+ double xFtrans, yFtrans;
+ double a;
+ double ae, ac2, ec2, bc2, de;
+ double width;
+
+ xOrg = (xOrgRight + xOrgLeft) / 2;
+ yOrg = (yOrgRight + yOrgLeft) / 2;
+ xFtrans = (xFtransLeft + xFtransRight) / 2;
+ yFtrans = (yFtransLeft + yFtransRight) / 2;
+ Right = *pRight;
+ translateBounds (&Right, xOrg - xOrgRight, yOrg - yOrgRight,
+ xFtrans - xFtransRight, yFtrans - yFtransRight);
+ Left = *pLeft;
+ translateBounds (&Left, xOrg - xOrgLeft, yOrg - yOrgLeft,
+ xFtrans - xFtransLeft, yFtrans - yFtransLeft);
+ pRight = &Right;
+ pLeft = &Left;
+
+ if (pRight->clock.x == pLeft->counterClock.x &&
+ pRight->clock.y == pLeft->counterClock.y)
+ return;
+ center = pRight->center;
+ if (0 <= (a = angleBetween (center, pRight->clock, pLeft->counterClock))
+ && a <= 180.0)
+ {
+ corner = pRight->clock;
+ otherCorner = pLeft->counterClock;
+ } else {
+ a = angleBetween (center, pLeft->clock, pRight->counterClock);
+ corner = pLeft->clock;
+ otherCorner = pRight->counterClock;
+ }
+ switch (pGC->joinStyle) {
+ case JoinRound:
+ width = (pGC->lineWidth ? (double)pGC->lineWidth : (double)1);
+
+ arc.x = center.x - width/2;
+ arc.y = center.y - width/2;
+ arc.width = width;
+ arc.height = width;
+ arc.angle1 = -miDatan2 (corner.y - center.y, corner.x - center.x);
+ arc.angle2 = a;
+ pArcPts = xalloc (3 * sizeof (SppPointRec));
+ if (!pArcPts)
+ return;
+ pArcPts[0].x = otherCorner.x;
+ pArcPts[0].y = otherCorner.y;
+ pArcPts[1].x = center.x;
+ pArcPts[1].y = center.y;
+ pArcPts[2].x = corner.x;
+ pArcPts[2].y = corner.y;
+ if( (cpt = miGetArcPts(&arc, 3, &pArcPts)) )
+ {
+ /* by drawing with miFillSppPoly and setting the endpoints of the arc
+ * to be the corners, we assure that the cap will meet up with the
+ * rest of the line */
+ miFillSppPoly(pDraw, pGC, cpt, pArcPts, xOrg, yOrg, xFtrans, yFtrans);
+ }
+ xfree(pArcPts);
+ return;
+ case JoinMiter:
+ /*
+ * don't miter arcs with less than 11 degrees between them
+ */
+ if (a < 169.0) {
+ poly[0] = corner;
+ poly[1] = center;
+ poly[2] = otherCorner;
+ bc2 = (corner.x - otherCorner.x) * (corner.x - otherCorner.x) +
+ (corner.y - otherCorner.y) * (corner.y - otherCorner.y);
+ ec2 = bc2 / 4;
+ ac2 = (corner.x - center.x) * (corner.x - center.x) +
+ (corner.y - center.y) * (corner.y - center.y);
+ ae = sqrt (ac2 - ec2);
+ de = ec2 / ae;
+ e.x = (corner.x + otherCorner.x) / 2;
+ e.y = (corner.y + otherCorner.y) / 2;
+ poly[3].x = e.x + de * (e.x - center.x) / ae;
+ poly[3].y = e.y + de * (e.y - center.y) / ae;
+ poly[4] = corner;
+ polyLen = 5;
+ break;
+ }
+ case JoinBevel:
+ poly[0] = corner;
+ poly[1] = center;
+ poly[2] = otherCorner;
+ poly[3] = corner;
+ polyLen = 4;
+ break;
+ }
+ miFillSppPoly (pDraw, pGC, polyLen, poly, xOrg, yOrg, xFtrans, yFtrans);
+}
+
+/*ARGSUSED*/
+static void
+miArcCap (
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ miArcFacePtr pFace,
+ int end,
+ int xOrg,
+ int yOrg,
+ double xFtrans,
+ double yFtrans)
+{
+ SppPointRec corner, otherCorner, center, endPoint, poly[5];
+
+ corner = pFace->clock;
+ otherCorner = pFace->counterClock;
+ center = pFace->center;
+ switch (pGC->capStyle) {
+ case CapProjecting:
+ poly[0].x = otherCorner.x;
+ poly[0].y = otherCorner.y;
+ poly[1].x = corner.x;
+ poly[1].y = corner.y;
+ poly[2].x = corner.x -
+ (center.y - corner.y);
+ poly[2].y = corner.y +
+ (center.x - corner.x);
+ poly[3].x = otherCorner.x -
+ (otherCorner.y - center.y);
+ poly[3].y = otherCorner.y +
+ (otherCorner.x - center.x);
+ poly[4].x = otherCorner.x;
+ poly[4].y = otherCorner.y;
+ miFillSppPoly (pDraw, pGC, 5, poly, xOrg, yOrg, xFtrans, yFtrans);
+ break;
+ case CapRound:
+ /*
+ * miRoundCap just needs these to be unequal.
+ */
+ endPoint = center;
+ endPoint.x = endPoint.x + 100;
+ miRoundCap (pDraw, pGC, center, endPoint, corner, otherCorner, 0,
+ -xOrg, -yOrg, xFtrans, yFtrans);
+ break;
+ }
+}
+
+/* MIROUNDCAP -- a private helper function
+ * Put Rounded cap on end. pCenter is the center of this end of the line
+ * pEnd is the center of the other end of the line. pCorner is one of the
+ * two corners at this end of the line.
+ * NOTE: pOtherCorner must be counter-clockwise from pCorner.
+ */
+/*ARGSUSED*/
+static void
+miRoundCap(
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ SppPointRec pCenter,
+ SppPointRec pEnd,
+ SppPointRec pCorner,
+ SppPointRec pOtherCorner,
+ int fLineEnd,
+ int xOrg,
+ int yOrg,
+ double xFtrans,
+ double yFtrans)
+{
+ int cpt;
+ double width;
+ SppArcRec arc;
+ SppPointPtr pArcPts;
+
+ width = (pGC->lineWidth ? (double)pGC->lineWidth : (double)1);
+
+ arc.x = pCenter.x - width/2;
+ arc.y = pCenter.y - width/2;
+ arc.width = width;
+ arc.height = width;
+ arc.angle1 = -miDatan2 (pCorner.y - pCenter.y, pCorner.x - pCenter.x);
+ if(PTISEQUAL(pCenter, pEnd))
+ arc.angle2 = - 180.0;
+ else {
+ arc.angle2 = -miDatan2 (pOtherCorner.y - pCenter.y, pOtherCorner.x - pCenter.x) - arc.angle1;
+ if (arc.angle2 < 0)
+ arc.angle2 += 360.0;
+ }
+ pArcPts = (SppPointPtr) NULL;
+ if( (cpt = miGetArcPts(&arc, 0, &pArcPts)) )
+ {
+ /* by drawing with miFillSppPoly and setting the endpoints of the arc
+ * to be the corners, we assure that the cap will meet up with the
+ * rest of the line */
+ miFillSppPoly(pDraw, pGC, cpt, pArcPts, -xOrg, -yOrg, xFtrans, yFtrans);
+ }
+ xfree(pArcPts);
+}
+
+/*
+ * To avoid inaccuracy at the cardinal points, use trig functions
+ * which are exact for those angles
+ */
+
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
+#ifndef M_PI_2
+#define M_PI_2 1.57079632679489661923
+#endif
+
+# define Dsin(d) ((d) == 0.0 ? 0.0 : ((d) == 90.0 ? 1.0 : sin(d*M_PI/180.0)))
+# define Dcos(d) ((d) == 0.0 ? 1.0 : ((d) == 90.0 ? 0.0 : cos(d*M_PI/180.0)))
+# define mod(a,b) ((a) >= 0 ? (a) % (b) : (b) - (-(a)) % (b))
+
+static double
+miDcos (double a)
+{
+ int i;
+
+ if (floor (a/90) == a/90) {
+ i = (int) (a/90.0);
+ switch (mod (i, 4)) {
+ case 0: return 1;
+ case 1: return 0;
+ case 2: return -1;
+ case 3: return 0;
+ }
+ }
+ return cos (a * M_PI / 180.0);
+}
+
+static double
+miDsin (double a)
+{
+ int i;
+
+ if (floor (a/90) == a/90) {
+ i = (int) (a/90.0);
+ switch (mod (i, 4)) {
+ case 0: return 0;
+ case 1: return 1;
+ case 2: return 0;
+ case 3: return -1;
+ }
+ }
+ return sin (a * M_PI / 180.0);
+}
+
+static double
+miDasin (double v)
+{
+ if (v == 0)
+ return 0.0;
+ if (v == 1.0)
+ return 90.0;
+ if (v == -1.0)
+ return -90.0;
+ return asin(v) * (180.0 / M_PI);
+}
+
+static double
+miDatan2 (double dy, double dx)
+{
+ if (dy == 0) {
+ if (dx >= 0)
+ return 0.0;
+ return 180.0;
+ } else if (dx == 0) {
+ if (dy > 0)
+ return 90.0;
+ return -90.0;
+ } else if (Fabs (dy) == Fabs (dx)) {
+ if (dy > 0) {
+ if (dx > 0)
+ return 45.0;
+ return 135.0;
+ } else {
+ if (dx > 0)
+ return 315.0;
+ return 225.0;
+ }
+ } else {
+ return atan2 (dy, dx) * (180.0 / M_PI);
+ }
+}
+
+/* MIGETARCPTS -- Converts an arc into a set of line segments -- a helper
+ * routine for filled arc and line (round cap) code.
+ * Returns the number of points in the arc. Note that it takes a pointer
+ * to a pointer to where it should put the points and an index (cpt).
+ * This procedure allocates the space necessary to fit the arc points.
+ * Sometimes it's convenient for those points to be at the end of an existing
+ * array. (For example, if we want to leave a spare point to make sectors
+ * instead of segments.) So we pass in the xalloc()ed chunk that contains the
+ * array and an index saying where we should start stashing the points.
+ * If there isn't an array already, we just pass in a null pointer and
+ * count on xrealloc() to handle the null pointer correctly.
+ */
+static int
+miGetArcPts(
+ SppArcPtr parc, /* points to an arc */
+ int cpt, /* number of points already in arc list */
+ SppPointPtr *ppPts) /* pointer to pointer to arc-list -- modified */
+{
+ double st, /* Start Theta, start angle */
+ et, /* End Theta, offset from start theta */
+ dt, /* Delta Theta, angle to sweep ellipse */
+ cdt, /* Cos Delta Theta, actually 2 cos(dt) */
+ x0, y0, /* the recurrence formula needs two points to start */
+ x1, y1,
+ x2, y2, /* this will be the new point generated */
+ xc, yc; /* the center point */
+ int count, i;
+ SppPointPtr poly;
+
+ /* The spec says that positive angles indicate counterclockwise motion.
+ * Given our coordinate system (with 0,0 in the upper left corner),
+ * the screen appears flipped in Y. The easiest fix is to negate the
+ * angles given */
+
+ st = - parc->angle1;
+
+ et = - parc->angle2;
+
+ /* Try to get a delta theta that is within 1/2 pixel. Then adjust it
+ * so that it divides evenly into the total.
+ * I'm just using cdt 'cause I'm lazy.
+ */
+ cdt = parc->width;
+ if (parc->height > cdt)
+ cdt = parc->height;
+ cdt /= 2.0;
+ if(cdt <= 0)
+ return 0;
+ if (cdt < 1.0)
+ cdt = 1.0;
+ dt = miDasin ( 1.0 / cdt ); /* minimum step necessary */
+ count = et/dt;
+ count = abs(count) + 1;
+ dt = et/count;
+ count++;
+
+ cdt = 2 * miDcos(dt);
+ if (!(poly = (SppPointPtr) xrealloc((pointer)*ppPts,
+ (cpt + count) * sizeof(SppPointRec))))
+ return(0);
+ *ppPts = poly;
+
+ xc = parc->width/2.0; /* store half width and half height */
+ yc = parc->height/2.0;
+
+ x0 = xc * miDcos(st);
+ y0 = yc * miDsin(st);
+ x1 = xc * miDcos(st + dt);
+ y1 = yc * miDsin(st + dt);
+ xc += parc->x; /* by adding initial point, these become */
+ yc += parc->y; /* the center point */
+
+ poly[cpt].x = (xc + x0);
+ poly[cpt].y = (yc + y0);
+ poly[cpt + 1].x = (xc + x1);
+ poly[cpt + 1].y = (yc + y1);
+
+ for(i = 2; i < count; i++)
+ {
+ x2 = cdt * x1 - x0;
+ y2 = cdt * y1 - y0;
+
+ poly[cpt + i].x = (xc + x2);
+ poly[cpt + i].y = (yc + y2);
+
+ x0 = x1; y0 = y1;
+ x1 = x2; y1 = y2;
+ }
+ /* adjust the last point */
+ if (abs(parc->angle2) >= 360.0)
+ poly[cpt +i -1] = poly[0];
+ else {
+ poly[cpt +i -1].x = (miDcos(st + et) * parc->width/2.0 + xc);
+ poly[cpt +i -1].y = (miDsin(st + et) * parc->height/2.0 + yc);
+ }
+
+ return(count);
+}
+
+struct arcData {
+ double x0, y0, x1, y1;
+ int selfJoin;
+};
+
+# define ADD_REALLOC_STEP 20
+
+static void
+addCap (
+ miArcCapPtr *capsp,
+ int *ncapsp,
+ int *sizep,
+ int end,
+ int arcIndex)
+{
+ int newsize;
+ miArcCapPtr cap;
+
+ if (*ncapsp == *sizep)
+ {
+ newsize = *sizep + ADD_REALLOC_STEP;
+ cap = (miArcCapPtr) xrealloc (*capsp,
+ newsize * sizeof (**capsp));
+ if (!cap)
+ return;
+ *sizep = newsize;
+ *capsp = cap;
+ }
+ cap = &(*capsp)[*ncapsp];
+ cap->end = end;
+ cap->arcIndex = arcIndex;
+ ++*ncapsp;
+}
+
+static void
+addJoin (
+ miArcJoinPtr *joinsp,
+ int *njoinsp,
+ int *sizep,
+ int end0,
+ int index0,
+ int phase0,
+ int end1,
+ int index1,
+ int phase1)
+{
+ int newsize;
+ miArcJoinPtr join;
+
+ if (*njoinsp == *sizep)
+ {
+ newsize = *sizep + ADD_REALLOC_STEP;
+ join = (miArcJoinPtr) xrealloc (*joinsp,
+ newsize * sizeof (**joinsp));
+ if (!join)
+ return;
+ *sizep = newsize;
+ *joinsp = join;
+ }
+ join = &(*joinsp)[*njoinsp];
+ join->end0 = end0;
+ join->arcIndex0 = index0;
+ join->phase0 = phase0;
+ join->end1 = end1;
+ join->arcIndex1 = index1;
+ join->phase1 = phase1;
+ ++*njoinsp;
+}
+
+static miArcDataPtr
+addArc (
+ miArcDataPtr *arcsp,
+ int *narcsp,
+ int *sizep,
+ xArc *xarc)
+{
+ int newsize;
+ miArcDataPtr arc;
+
+ if (*narcsp == *sizep)
+ {
+ newsize = *sizep + ADD_REALLOC_STEP;
+ arc = (miArcDataPtr) xrealloc (*arcsp,
+ newsize * sizeof (**arcsp));
+ if (!arc)
+ return NULL;
+ *sizep = newsize;
+ *arcsp = arc;
+ }
+ arc = &(*arcsp)[*narcsp];
+ arc->arc = *xarc;
+ ++*narcsp;
+ return arc;
+}
+
+static void
+miFreeArcs(
+ miPolyArcPtr arcs,
+ GCPtr pGC)
+{
+ int iphase;
+
+ for (iphase = ((pGC->lineStyle == LineDoubleDash) ? 1 : 0);
+ iphase >= 0;
+ iphase--)
+ {
+ if (arcs[iphase].narcs > 0)
+ xfree(arcs[iphase].arcs);
+ if (arcs[iphase].njoins > 0)
+ xfree(arcs[iphase].joins);
+ if (arcs[iphase].ncaps > 0)
+ xfree(arcs[iphase].caps);
+ }
+ xfree(arcs);
+}
+
+/*
+ * map angles to radial distance. This only deals with the first quadrant
+ */
+
+/*
+ * a polygonal approximation to the arc for computing arc lengths
+ */
+
+# define DASH_MAP_SIZE 91
+
+# define dashIndexToAngle(di) ((((double) (di)) * 90.0) / ((double) DASH_MAP_SIZE - 1))
+# define xAngleToDashIndex(xa) ((((long) (xa)) * (DASH_MAP_SIZE - 1)) / (90 * 64))
+# define dashIndexToXAngle(di) ((((long) (di)) * (90 * 64)) / (DASH_MAP_SIZE - 1))
+# define dashXAngleStep (((double) (90 * 64)) / ((double) (DASH_MAP_SIZE - 1)))
+
+typedef struct {
+ double map[DASH_MAP_SIZE];
+} dashMap;
+
+static int computeAngleFromPath(int startAngle, int endAngle, dashMap *map,
+ int *lenp, int backwards);
+
+static void
+computeDashMap (
+ xArc *arcp,
+ dashMap *map)
+{
+ int di;
+ double a, x, y, prevx = 0.0, prevy = 0.0, dist;
+
+ for (di = 0; di < DASH_MAP_SIZE; di++) {
+ a = dashIndexToAngle (di);
+ x = ((double) arcp->width / 2.0) * miDcos (a);
+ y = ((double) arcp->height / 2.0) * miDsin (a);
+ if (di == 0) {
+ map->map[di] = 0.0;
+ } else {
+ dist = hypot (x - prevx, y - prevy);
+ map->map[di] = map->map[di - 1] + dist;
+ }
+ prevx = x;
+ prevy = y;
+ }
+}
+
+typedef enum {HORIZONTAL, VERTICAL, OTHER} arcTypes;
+
+/* this routine is a bit gory */
+
+static miPolyArcPtr
+miComputeArcs (
+ xArc *parcs,
+ int narcs,
+ GCPtr pGC)
+{
+ int isDashed, isDoubleDash;
+ int dashOffset;
+ miPolyArcPtr arcs;
+ int start, i, j, k = 0, nexti, nextk = 0;
+ int joinSize[2];
+ int capSize[2];
+ int arcSize[2];
+ int angle2;
+ double a0, a1;
+ struct arcData *data;
+ miArcDataPtr arc;
+ xArc xarc;
+ int iphase, prevphase = 0, joinphase;
+ int arcsJoin;
+ int selfJoin;
+
+ int iDash = 0, dashRemaining = 0;
+ int iDashStart = 0, dashRemainingStart = 0, iphaseStart;
+ int startAngle, spanAngle, endAngle, backwards = 0;
+ int prevDashAngle, dashAngle;
+ dashMap map;
+
+ isDashed = !(pGC->lineStyle == LineSolid);
+ isDoubleDash = (pGC->lineStyle == LineDoubleDash);
+ dashOffset = pGC->dashOffset;
+
+ data = xalloc (narcs * sizeof (struct arcData));
+ if (!data)
+ return NULL;
+ arcs = xalloc (sizeof (*arcs) * (isDoubleDash ? 2 : 1));
+ if (!arcs)
+ {
+ xfree(data);
+ return NULL;
+ }
+ for (i = 0; i < narcs; i++) {
+ a0 = todeg (parcs[i].angle1);
+ angle2 = parcs[i].angle2;
+ if (angle2 > FULLCIRCLE)
+ angle2 = FULLCIRCLE;
+ else if (angle2 < -FULLCIRCLE)
+ angle2 = -FULLCIRCLE;
+ data[i].selfJoin = angle2 == FULLCIRCLE || angle2 == -FULLCIRCLE;
+ a1 = todeg (parcs[i].angle1 + angle2);
+ data[i].x0 = parcs[i].x + (double) parcs[i].width / 2 * (1 + miDcos (a0));
+ data[i].y0 = parcs[i].y + (double) parcs[i].height / 2 * (1 - miDsin (a0));
+ data[i].x1 = parcs[i].x + (double) parcs[i].width / 2 * (1 + miDcos (a1));
+ data[i].y1 = parcs[i].y + (double) parcs[i].height / 2 * (1 - miDsin (a1));
+ }
+
+ for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++) {
+ arcs[iphase].njoins = 0;
+ arcs[iphase].joins = 0;
+ joinSize[iphase] = 0;
+
+ arcs[iphase].ncaps = 0;
+ arcs[iphase].caps = 0;
+ capSize[iphase] = 0;
+
+ arcs[iphase].narcs = 0;
+ arcs[iphase].arcs = 0;
+ arcSize[iphase] = 0;
+ }
+
+ iphase = 0;
+ if (isDashed) {
+ iDash = 0;
+ dashRemaining = pGC->dash[0];
+ while (dashOffset > 0) {
+ if (dashOffset >= dashRemaining) {
+ dashOffset -= dashRemaining;
+ iphase = iphase ? 0 : 1;
+ iDash++;
+ if (iDash == pGC->numInDashList)
+ iDash = 0;
+ dashRemaining = pGC->dash[iDash];
+ } else {
+ dashRemaining -= dashOffset;
+ dashOffset = 0;
+ }
+ }
+ iDashStart = iDash;
+ dashRemainingStart = dashRemaining;
+ }
+ iphaseStart = iphase;
+
+ for (i = narcs - 1; i >= 0; i--) {
+ j = i + 1;
+ if (j == narcs)
+ j = 0;
+ if (data[i].selfJoin || i == j ||
+ (UNEQUAL (data[i].x1, data[j].x0) ||
+ UNEQUAL (data[i].y1, data[j].y0)))
+ {
+ if (iphase == 0 || isDoubleDash)
+ addCap (&arcs[iphase].caps, &arcs[iphase].ncaps,
+ &capSize[iphase], RIGHT_END, 0);
+ break;
+ }
+ }
+ start = i + 1;
+ if (start == narcs)
+ start = 0;
+ i = start;
+ for (;;) {
+ j = i + 1;
+ if (j == narcs)
+ j = 0;
+ nexti = i+1;
+ if (nexti == narcs)
+ nexti = 0;
+ if (isDashed) {
+ /*
+ ** deal with dashed arcs. Use special rules for certain 0 area arcs.
+ ** Presumably, the other 0 area arcs still aren't done right.
+ */
+ arcTypes arcType = OTHER;
+ CARD16 thisLength;
+
+ if (parcs[i].height == 0
+ && (parcs[i].angle1 % FULLCIRCLE) == 0x2d00
+ && parcs[i].angle2 == 0x2d00)
+ arcType = HORIZONTAL;
+ else if (parcs[i].width == 0
+ && (parcs[i].angle1 % FULLCIRCLE) == 0x1680
+ && parcs[i].angle2 == 0x2d00)
+ arcType = VERTICAL;
+ if (arcType == OTHER) {
+ /*
+ * precompute an approximation map
+ */
+ computeDashMap (&parcs[i], &map);
+ /*
+ * compute each individual dash segment using the path
+ * length function
+ */
+ startAngle = parcs[i].angle1;
+ spanAngle = parcs[i].angle2;
+ if (spanAngle > FULLCIRCLE)
+ spanAngle = FULLCIRCLE;
+ else if (spanAngle < -FULLCIRCLE)
+ spanAngle = -FULLCIRCLE;
+ if (startAngle < 0)
+ startAngle = FULLCIRCLE - (-startAngle) % FULLCIRCLE;
+ if (startAngle >= FULLCIRCLE)
+ startAngle = startAngle % FULLCIRCLE;
+ endAngle = startAngle + spanAngle;
+ backwards = spanAngle < 0;
+ } else {
+ xarc = parcs[i];
+ if (arcType == VERTICAL) {
+ xarc.angle1 = 0x1680;
+ startAngle = parcs[i].y;
+ endAngle = startAngle + parcs[i].height;
+ } else {
+ xarc.angle1 = 0x2d00;
+ startAngle = parcs[i].x;
+ endAngle = startAngle + parcs[i].width;
+ }
+ }
+ dashAngle = startAngle;
+ selfJoin = data[i].selfJoin &&
+ (iphase == 0 || isDoubleDash);
+ /*
+ * add dashed arcs to each bucket
+ */
+ arc = 0;
+ while (dashAngle != endAngle) {
+ prevDashAngle = dashAngle;
+ if (arcType == OTHER) {
+ dashAngle = computeAngleFromPath (prevDashAngle, endAngle,
+ &map, &dashRemaining, backwards);
+ /* avoid troubles with huge arcs and small dashes */
+ if (dashAngle == prevDashAngle) {
+ if (backwards)
+ dashAngle--;
+ else
+ dashAngle++;
+ }
+ } else {
+ thisLength = (dashAngle + dashRemaining <= endAngle) ?
+ dashRemaining : endAngle - dashAngle;
+ if (arcType == VERTICAL) {
+ xarc.y = dashAngle;
+ xarc.height = thisLength;
+ } else {
+ xarc.x = dashAngle;
+ xarc.width = thisLength;
+ }
+ dashAngle += thisLength;
+ dashRemaining -= thisLength;
+ }
+ if (iphase == 0 || isDoubleDash) {
+ if (arcType == OTHER) {
+ xarc = parcs[i];
+ spanAngle = prevDashAngle;
+ if (spanAngle < 0)
+ spanAngle = FULLCIRCLE - (-spanAngle) % FULLCIRCLE;
+ if (spanAngle >= FULLCIRCLE)
+ spanAngle = spanAngle % FULLCIRCLE;
+ xarc.angle1 = spanAngle;
+ spanAngle = dashAngle - prevDashAngle;
+ if (backwards) {
+ if (dashAngle > prevDashAngle)
+ spanAngle = - FULLCIRCLE + spanAngle;
+ } else {
+ if (dashAngle < prevDashAngle)
+ spanAngle = FULLCIRCLE + spanAngle;
+ }
+ if (spanAngle > FULLCIRCLE)
+ spanAngle = FULLCIRCLE;
+ if (spanAngle < -FULLCIRCLE)
+ spanAngle = -FULLCIRCLE;
+ xarc.angle2 = spanAngle;
+ }
+ arc = addArc (&arcs[iphase].arcs, &arcs[iphase].narcs,
+ &arcSize[iphase], &xarc);
+ if (!arc)
+ goto arcfail;
+ /*
+ * cap each end of an on/off dash
+ */
+ if (!isDoubleDash) {
+ if (prevDashAngle != startAngle) {
+ addCap (&arcs[iphase].caps,
+ &arcs[iphase].ncaps,
+ &capSize[iphase], RIGHT_END,
+ arc - arcs[iphase].arcs);
+
+ }
+ if (dashAngle != endAngle) {
+ addCap (&arcs[iphase].caps,
+ &arcs[iphase].ncaps,
+ &capSize[iphase], LEFT_END,
+ arc - arcs[iphase].arcs);
+ }
+ }
+ arc->cap = arcs[iphase].ncaps;
+ arc->join = arcs[iphase].njoins;
+ arc->render = 0;
+ arc->selfJoin = 0;
+ if (dashAngle == endAngle)
+ arc->selfJoin = selfJoin;
+ }
+ prevphase = iphase;
+ if (dashRemaining <= 0) {
+ ++iDash;
+ if (iDash == pGC->numInDashList)
+ iDash = 0;
+ iphase = iphase ? 0:1;
+ dashRemaining = pGC->dash[iDash];
+ }
+ }
+ /*
+ * make sure a place exists for the position data when
+ * drawing a zero-length arc
+ */
+ if (startAngle == endAngle) {
+ prevphase = iphase;
+ if (!isDoubleDash && iphase == 1)
+ prevphase = 0;
+ arc = addArc (&arcs[prevphase].arcs, &arcs[prevphase].narcs,
+ &arcSize[prevphase], &parcs[i]);
+ if (!arc)
+ goto arcfail;
+ arc->join = arcs[prevphase].njoins;
+ arc->cap = arcs[prevphase].ncaps;
+ arc->selfJoin = data[i].selfJoin;
+ }
+ } else {
+ arc = addArc (&arcs[iphase].arcs, &arcs[iphase].narcs,
+ &arcSize[iphase], &parcs[i]);
+ if (!arc)
+ goto arcfail;
+ arc->join = arcs[iphase].njoins;
+ arc->cap = arcs[iphase].ncaps;
+ arc->selfJoin = data[i].selfJoin;
+ prevphase = iphase;
+ }
+ if (prevphase == 0 || isDoubleDash)
+ k = arcs[prevphase].narcs - 1;
+ if (iphase == 0 || isDoubleDash)
+ nextk = arcs[iphase].narcs;
+ if (nexti == start) {
+ nextk = 0;
+ if (isDashed) {
+ iDash = iDashStart;
+ iphase = iphaseStart;
+ dashRemaining = dashRemainingStart;
+ }
+ }
+ arcsJoin = narcs > 1 && i != j &&
+ ISEQUAL (data[i].x1, data[j].x0) &&
+ ISEQUAL (data[i].y1, data[j].y0) &&
+ !data[i].selfJoin && !data[j].selfJoin;
+ if (arc)
+ {
+ if (arcsJoin)
+ arc->render = 0;
+ else
+ arc->render = 1;
+ }
+ if (arcsJoin &&
+ (prevphase == 0 || isDoubleDash) &&
+ (iphase == 0 || isDoubleDash))
+ {
+ joinphase = iphase;
+ if (isDoubleDash) {
+ if (nexti == start)
+ joinphase = iphaseStart;
+ /*
+ * if the join is right at the dash,
+ * draw the join in foreground
+ * This is because the foreground
+ * arcs are computed second, the results
+ * of which are needed to draw the join
+ */
+ if (joinphase != prevphase)
+ joinphase = 0;
+ }
+ if (joinphase == 0 || isDoubleDash) {
+ addJoin (&arcs[joinphase].joins,
+ &arcs[joinphase].njoins,
+ &joinSize[joinphase],
+ LEFT_END, k, prevphase,
+ RIGHT_END, nextk, iphase);
+ arc->join = arcs[prevphase].njoins;
+ }
+ } else {
+ /*
+ * cap the left end of this arc
+ * unless it joins itself
+ */
+ if ((prevphase == 0 || isDoubleDash) &&
+ !arc->selfJoin)
+ {
+ addCap (&arcs[prevphase].caps, &arcs[prevphase].ncaps,
+ &capSize[prevphase], LEFT_END, k);
+ arc->cap = arcs[prevphase].ncaps;
+ }
+ if (isDashed && !arcsJoin) {
+ iDash = iDashStart;
+ iphase = iphaseStart;
+ dashRemaining = dashRemainingStart;
+ }
+ nextk = arcs[iphase].narcs;
+ if (nexti == start) {
+ nextk = 0;
+ iDash = iDashStart;
+ iphase = iphaseStart;
+ dashRemaining = dashRemainingStart;
+ }
+ /*
+ * cap the right end of the next arc. If the
+ * next arc is actually the first arc, only
+ * cap it if it joins with this arc. This
+ * case will occur when the final dash segment
+ * of an on/off dash is off. Of course, this
+ * cap will be drawn at a strange time, but that
+ * hardly matters...
+ */
+ if ((iphase == 0 || isDoubleDash) &&
+ (nexti != start || (arcsJoin && isDashed)))
+ addCap (&arcs[iphase].caps, &arcs[iphase].ncaps,
+ &capSize[iphase], RIGHT_END, nextk);
+ }
+ i = nexti;
+ if (i == start)
+ break;
+ }
+ /*
+ * make sure the last section is rendered
+ */
+ for (iphase = 0; iphase < (isDoubleDash ? 2 : 1); iphase++)
+ if (arcs[iphase].narcs > 0) {
+ arcs[iphase].arcs[arcs[iphase].narcs-1].render = 1;
+ arcs[iphase].arcs[arcs[iphase].narcs-1].join =
+ arcs[iphase].njoins;
+ arcs[iphase].arcs[arcs[iphase].narcs-1].cap =
+ arcs[iphase].ncaps;
+ }
+ xfree(data);
+ return arcs;
+arcfail:
+ miFreeArcs(arcs, pGC);
+ xfree(data);
+ return NULL;
+}
+
+static double
+angleToLength (
+ int angle,
+ dashMap *map)
+{
+ double len, excesslen, sidelen = map->map[DASH_MAP_SIZE - 1], totallen;
+ int di;
+ int excess;
+ Bool oddSide = FALSE;
+
+ totallen = 0;
+ if (angle >= 0) {
+ while (angle >= 90 * 64) {
+ angle -= 90 * 64;
+ totallen += sidelen;
+ oddSide = !oddSide;
+ }
+ } else {
+ while (angle < 0) {
+ angle += 90 * 64;
+ totallen -= sidelen;
+ oddSide = !oddSide;
+ }
+ }
+ if (oddSide)
+ angle = 90 * 64 - angle;
+
+ di = xAngleToDashIndex (angle);
+ excess = angle - dashIndexToXAngle (di);
+
+ len = map->map[di];
+ /*
+ * linearly interpolate between this point and the next
+ */
+ if (excess > 0) {
+ excesslen = (map->map[di + 1] - map->map[di]) *
+ ((double) excess) / dashXAngleStep;
+ len += excesslen;
+ }
+ if (oddSide)
+ totallen += (sidelen - len);
+ else
+ totallen += len;
+ return totallen;
+}
+
+/*
+ * len is along the arc, but may be more than one rotation
+ */
+
+static int
+lengthToAngle (
+ double len,
+ dashMap *map)
+{
+ double sidelen = map->map[DASH_MAP_SIZE - 1];
+ int angle, angleexcess;
+ Bool oddSide = FALSE;
+ int a0, a1, a;
+
+ angle = 0;
+ /*
+ * step around the ellipse, subtracting sidelens and
+ * adding 90 degrees. oddSide will tell if the
+ * map should be interpolated in reverse
+ */
+ if (len >= 0) {
+ if (sidelen == 0)
+ return 2 * FULLCIRCLE; /* infinity */
+ while (len >= sidelen) {
+ angle += 90 * 64;
+ len -= sidelen;
+ oddSide = !oddSide;
+ }
+ } else {
+ if (sidelen == 0)
+ return -2 * FULLCIRCLE; /* infinity */
+ while (len < 0) {
+ angle -= 90 * 64;
+ len += sidelen;
+ oddSide = !oddSide;
+ }
+ }
+ if (oddSide)
+ len = sidelen - len;
+ a0 = 0;
+ a1 = DASH_MAP_SIZE - 1;
+ /*
+ * binary search for the closest pre-computed length
+ */
+ while (a1 - a0 > 1) {
+ a = (a0 + a1) / 2;
+ if (len > map->map[a])
+ a0 = a;
+ else
+ a1 = a;
+ }
+ angleexcess = dashIndexToXAngle (a0);
+ /*
+ * linearly interpolate to the next point
+ */
+ angleexcess += (len - map->map[a0]) /
+ (map->map[a0+1] - map->map[a0]) * dashXAngleStep;
+ if (oddSide)
+ angle += (90 * 64) - angleexcess;
+ else
+ angle += angleexcess;
+ return angle;
+}
+
+/*
+ * compute the angle of an ellipse which cooresponds to
+ * the given path length. Note that the correct solution
+ * to this problem is an eliptic integral, we'll punt and
+ * approximate (it's only for dashes anyway). This
+ * approximation uses a polygon.
+ *
+ * The remaining portion of len is stored in *lenp -
+ * this will be negative if the arc extends beyond
+ * len and positive if len extends beyond the arc.
+ */
+
+static int
+computeAngleFromPath (
+ int startAngle,
+ int endAngle, /* normalized absolute angles in *64 degrees */
+ dashMap *map,
+ int *lenp,
+ int backwards)
+{
+ int a0, a1, a;
+ double len0;
+ int len;
+
+ a0 = startAngle;
+ a1 = endAngle;
+ len = *lenp;
+ if (backwards) {
+ /*
+ * flip the problem around to always be
+ * forwards
+ */
+ a0 = FULLCIRCLE - a0;
+ a1 = FULLCIRCLE - a1;
+ }
+ if (a1 < a0)
+ a1 += FULLCIRCLE;
+ len0 = angleToLength (a0, map);
+ a = lengthToAngle (len0 + len, map);
+ if (a > a1) {
+ a = a1;
+ len -= angleToLength (a1, map) - len0;
+ } else
+ len = 0;
+ if (backwards)
+ a = FULLCIRCLE - a;
+ *lenp = len;
+ return a;
+}
+
+/*
+ * scan convert wide arcs.
+ */
+
+/*
+ * draw zero width/height arcs
+ */
+
+static void
+drawZeroArc (
+ DrawablePtr pDraw,
+ GCPtr pGC,
+ xArc *tarc,
+ int lw,
+ miArcFacePtr left,
+ miArcFacePtr right)
+{
+ double x0 = 0.0, y0 = 0.0, x1 = 0.0, y1 = 0.0, w, h, x, y;
+ double xmax, ymax, xmin, ymin;
+ int a0, a1;
+ double a, startAngle, endAngle;
+ double l, lx, ly;
+
+ l = lw / 2.0;
+ a0 = tarc->angle1;
+ a1 = tarc->angle2;
+ if (a1 > FULLCIRCLE)
+ a1 = FULLCIRCLE;
+ else if (a1 < -FULLCIRCLE)
+ a1 = -FULLCIRCLE;
+ w = (double)tarc->width / 2.0;
+ h = (double)tarc->height / 2.0;
+ /*
+ * play in X coordinates right away
+ */
+ startAngle = - ((double) a0 / 64.0);
+ endAngle = - ((double) (a0 + a1) / 64.0);
+
+ xmax = -w;
+ xmin = w;
+ ymax = -h;
+ ymin = h;
+ a = startAngle;
+ for (;;)
+ {
+ x = w * miDcos(a);
+ y = h * miDsin(a);
+ if (a == startAngle)
+ {
+ x0 = x;
+ y0 = y;
+ }
+ if (a == endAngle)
+ {
+ x1 = x;
+ y1 = y;
+ }
+ if (x > xmax)
+ xmax = x;
+ if (x < xmin)
+ xmin = x;
+ if (y > ymax)
+ ymax = y;
+ if (y < ymin)
+ ymin = y;
+ if (a == endAngle)
+ break;
+ if (a1 < 0) /* clockwise */
+ {
+ if (floor (a / 90.0) == floor (endAngle / 90.0))
+ a = endAngle;
+ else
+ a = 90 * (floor (a/90.0) + 1);
+ }
+ else
+ {
+ if (ceil (a / 90.0) == ceil (endAngle / 90.0))
+ a = endAngle;
+ else
+ a = 90 * (ceil (a/90.0) - 1);
+ }
+ }
+ lx = ly = l;
+ if ((x1 - x0) + (y1 - y0) < 0)
+ lx = ly = -l;
+ if (h)
+ {
+ ly = 0.0;
+ lx = -lx;
+ }
+ else
+ lx = 0.0;
+ if (right)
+ {
+ right->center.x = x0;
+ right->center.y = y0;
+ right->clock.x = x0 - lx;
+ right->clock.y = y0 - ly;
+ right->counterClock.x = x0 + lx;
+ right->counterClock.y = y0 + ly;
+ }
+ if (left)
+ {
+ left->center.x = x1;
+ left->center.y = y1;
+ left->clock.x = x1 + lx;
+ left->clock.y = y1 + ly;
+ left->counterClock.x = x1 - lx;
+ left->counterClock.y = y1 - ly;
+ }
+
+ x0 = xmin;
+ x1 = xmax;
+ y0 = ymin;
+ y1 = ymax;
+ if (ymin != y1) {
+ xmin = -l;
+ xmax = l;
+ } else {
+ ymin = -l;
+ ymax = l;
+ }
+ if (xmax != xmin && ymax != ymin) {
+ int minx, maxx, miny, maxy;
+ xRectangle rect;
+
+ minx = ICEIL (xmin + w) + tarc->x;
+ maxx = ICEIL (xmax + w) + tarc->x;
+ miny = ICEIL (ymin + h) + tarc->y;
+ maxy = ICEIL (ymax + h) + tarc->y;
+ rect.x = minx;
+ rect.y = miny;
+ rect.width = maxx - minx;
+ rect.height = maxy - miny;
+ (*pGC->ops->PolyFillRect) (pDraw, pGC, 1, &rect);
+ }
+}
+
+/*
+ * this computes the ellipse y value associated with the
+ * bottom of the tail.
+ */
+
+static void
+tailEllipseY (
+ struct arc_def *def,
+ struct accelerators *acc)
+{
+ double t;
+
+ acc->tail_y = 0.0;
+ if (def->w == def->h)
+ return;
+ t = def->l * def->w;
+ if (def->w > def->h) {
+ if (t < acc->h2)
+ return;
+ } else {
+ if (t > acc->h2)
+ return;
+ }
+ t = 2.0 * def->h * t;
+ t = (CUBED_ROOT_4 * acc->h2 - cbrt(t * t)) / acc->h2mw2;
+ if (t > 0.0)
+ acc->tail_y = def->h / CUBED_ROOT_2 * sqrt(t);
+}
+
+/*
+ * inverse functions -- compute edge coordinates
+ * from the ellipse
+ */
+
+static double
+outerXfromXY (
+ double x,
+ double y,
+ struct arc_def *def,
+ struct accelerators *acc)
+{
+ return x + (x * acc->h2l) / sqrt (x*x * acc->h4 + y*y * acc->w4);
+}
+
+static double
+outerYfromXY (
+ double x,
+ double y,
+ struct arc_def *def,
+ struct accelerators *acc)
+{
+ return y + (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4);
+}
+
+static double
+innerXfromXY (
+ double x,
+ double y,
+ struct arc_def *def,
+ struct accelerators *acc)
+{
+ return x - (x * acc->h2l) / sqrt (x*x * acc->h4 + y*y * acc->w4);
+}
+
+static double
+innerYfromXY (
+ double x,
+ double y,
+ struct arc_def *def,
+ struct accelerators *acc)
+{
+ return y - (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4);
+}
+
+static double
+innerYfromY (
+ double y,
+ struct arc_def *def,
+ struct accelerators *acc)
+{
+ double x;
+
+ x = (def->w / def->h) * sqrt (acc->h2 - y*y);
+
+ return y - (y * acc->w2l) / sqrt (x*x * acc->h4 + y*y * acc->w4);
+}
+
+static void
+computeLine (
+ double x1,
+ double y1,
+ double x2,
+ double y2,
+ struct line *line)
+{
+ if (y1 == y2)
+ line->valid = 0;
+ else {
+ line->m = (x1 - x2) / (y1 - y2);
+ line->b = x1 - y1 * line->m;
+ line->valid = 1;
+ }
+}
+
+/*
+ * compute various accelerators for an ellipse. These
+ * are simply values that are used repeatedly in
+ * the computations
+ */
+
+static void
+computeAcc (
+ xArc *tarc,
+ int lw,
+ struct arc_def *def,
+ struct accelerators *acc)
+{
+ def->w = ((double) tarc->width) / 2.0;
+ def->h = ((double) tarc->height) / 2.0;
+ def->l = ((double) lw) / 2.0;
+ acc->h2 = def->h * def->h;
+ acc->w2 = def->w * def->w;
+ acc->h4 = acc->h2 * acc->h2;
+ acc->w4 = acc->w2 * acc->w2;
+ acc->h2l = acc->h2 * def->l;
+ acc->w2l = acc->w2 * def->l;
+ acc->h2mw2 = acc->h2 - acc->w2;
+ acc->fromIntX = (tarc->width & 1) ? 0.5 : 0.0;
+ acc->fromIntY = (tarc->height & 1) ? 0.5 : 0.0;
+ acc->xorg = tarc->x + (tarc->width >> 1);
+ acc->yorgu = tarc->y + (tarc->height >> 1);
+ acc->yorgl = acc->yorgu + (tarc->height & 1);
+ tailEllipseY (def, acc);
+}
+
+/*
+ * compute y value bounds of various portions of the arc,
+ * the outer edge, the ellipse and the inner edge.
+ */
+
+static void
+computeBound (
+ struct arc_def *def,
+ struct arc_bound *bound,
+ struct accelerators *acc,
+ miArcFacePtr right,
+ miArcFacePtr left)
+{
+ double t;
+ double innerTaily;
+ double tail_y;
+ struct bound innerx, outerx;
+ struct bound ellipsex;
+
+ bound->ellipse.min = Dsin (def->a0) * def->h;
+ bound->ellipse.max = Dsin (def->a1) * def->h;
+ if (def->a0 == 45 && def->w == def->h)
+ ellipsex.min = bound->ellipse.min;
+ else
+ ellipsex.min = Dcos (def->a0) * def->w;
+ if (def->a1 == 45 && def->w == def->h)
+ ellipsex.max = bound->ellipse.max;
+ else
+ ellipsex.max = Dcos (def->a1) * def->w;
+ bound->outer.min = outerYfromXY (ellipsex.min, bound->ellipse.min, def, acc);
+ bound->outer.max = outerYfromXY (ellipsex.max, bound->ellipse.max, def, acc);
+ bound->inner.min = innerYfromXY (ellipsex.min, bound->ellipse.min, def, acc);
+ bound->inner.max = innerYfromXY (ellipsex.max, bound->ellipse.max, def, acc);
+
+ outerx.min = outerXfromXY (ellipsex.min, bound->ellipse.min, def, acc);
+ outerx.max = outerXfromXY (ellipsex.max, bound->ellipse.max, def, acc);
+ innerx.min = innerXfromXY (ellipsex.min, bound->ellipse.min, def, acc);
+ innerx.max = innerXfromXY (ellipsex.max, bound->ellipse.max, def, acc);
+
+ /*
+ * save the line end points for the
+ * cap code to use. Careful here, these are
+ * in cartesean coordinates (y increasing upwards)
+ * while the cap code uses inverted coordinates
+ * (y increasing downwards)
+ */
+
+ if (right) {
+ right->counterClock.y = bound->outer.min;
+ right->counterClock.x = outerx.min;
+ right->center.y = bound->ellipse.min;
+ right->center.x = ellipsex.min;
+ right->clock.y = bound->inner.min;
+ right->clock.x = innerx.min;
+ }
+
+ if (left) {
+ left->clock.y = bound->outer.max;
+ left->clock.x = outerx.max;
+ left->center.y = bound->ellipse.max;
+ left->center.x = ellipsex.max;
+ left->counterClock.y = bound->inner.max;
+ left->counterClock.x = innerx.max;
+ }
+
+ bound->left.min = bound->inner.max;
+ bound->left.max = bound->outer.max;
+ bound->right.min = bound->inner.min;
+ bound->right.max = bound->outer.min;
+
+ computeLine (innerx.min, bound->inner.min, outerx.min, bound->outer.min,
+ &acc->right);
+ computeLine (innerx.max, bound->inner.max, outerx.max, bound->outer.max,
+ &acc->left);
+
+ if (bound->inner.min > bound->inner.max) {
+ t = bound->inner.min;
+ bound->inner.min = bound->inner.max;
+ bound->inner.max = t;
+ }
+ tail_y = acc->tail_y;
+ if (tail_y > bound->ellipse.max)
+ tail_y = bound->ellipse.max;
+ else if (tail_y < bound->ellipse.min)
+ tail_y = bound->ellipse.min;
+ innerTaily = innerYfromY (tail_y, def, acc);
+ if (bound->inner.min > innerTaily)
+ bound->inner.min = innerTaily;
+ if (bound->inner.max < innerTaily)
+ bound->inner.max = innerTaily;
+ bound->inneri.min = ICEIL(bound->inner.min - acc->fromIntY);
+ bound->inneri.max = floor(bound->inner.max - acc->fromIntY);
+ bound->outeri.min = ICEIL(bound->outer.min - acc->fromIntY);
+ bound->outeri.max = floor(bound->outer.max - acc->fromIntY);
+}
+
+/*
+ * this section computes the x value of the span at y
+ * intersected with the specified face of the ellipse.
+ *
+ * this is the min/max X value over the set of normal
+ * lines to the entire ellipse, the equation of the
+ * normal lines is:
+ *
+ * ellipse_x h^2 h^2
+ * x = ------------ y + ellipse_x (1 - --- )
+ * ellipse_y w^2 w^2
+ *
+ * compute the derivative with-respect-to ellipse_y and solve
+ * for zero:
+ *
+ * (w^2 - h^2) ellipse_y^3 + h^4 y
+ * 0 = - ----------------------------------
+ * h w ellipse_y^2 sqrt (h^2 - ellipse_y^2)
+ *
+ * ( h^4 y )
+ * ellipse_y = ( ---------- ) ^ (1/3)
+ * ( (h^2 - w^2) )
+ *
+ * The other two solutions to the equation are imaginary.
+ *
+ * This gives the position on the ellipse which generates
+ * the normal with the largest/smallest x intersection point.
+ *
+ * Now compute the second derivative to check whether
+ * the intersection is a minimum or maximum:
+ *
+ * h (y0^3 (w^2 - h^2) + h^2 y (3y0^2 - 2h^2))
+ * - -------------------------------------------
+ * w y0^3 (sqrt (h^2 - y^2)) ^ 3
+ *
+ * as we only care about the sign,
+ *
+ * - (y0^3 (w^2 - h^2) + h^2 y (3y0^2 - 2h^2))
+ *
+ * or (to use accelerators),
+ *
+ * y0^3 (h^2 - w^2) - h^2 y (3y0^2 - 2h^2)
+ *
+ */
+
+/*
+ * computes the position on the ellipse whose normal line
+ * intersects the given scan line maximally
+ */
+
+static double
+hookEllipseY (
+ double scan_y,
+ struct arc_bound *bound,
+ struct accelerators *acc,
+ int left)
+{
+ double ret;
+
+ if (acc->h2mw2 == 0) {
+ if ( (scan_y > 0 && !left) || (scan_y < 0 && left) )
+ return bound->ellipse.min;
+ return bound->ellipse.max;
+ }
+ ret = (acc->h4 * scan_y) / (acc->h2mw2);
+ if (ret >= 0)
+ return cbrt (ret);
+ else
+ return -cbrt (-ret);
+}
+
+/*
+ * computes the X value of the intersection of the
+ * given scan line with the right side of the lower hook
+ */
+
+static double
+hookX (
+ double scan_y,
+ struct arc_def *def,
+ struct arc_bound *bound,
+ struct accelerators *acc,
+ int left)
+{
+ double ellipse_y, x;
+ double maxMin;
+
+ if (def->w != def->h) {
+ ellipse_y = hookEllipseY (scan_y, bound, acc, left);
+ if (boundedLe (ellipse_y, bound->ellipse)) {
+ /*
+ * compute the value of the second
+ * derivative
+ */
+ maxMin = ellipse_y*ellipse_y*ellipse_y * acc->h2mw2 -
+ acc->h2 * scan_y * (3 * ellipse_y*ellipse_y - 2*acc->h2);
+ if ((left && maxMin > 0) || (!left && maxMin < 0)) {
+ if (ellipse_y == 0)
+ return def->w + left ? -def->l : def->l;
+ x = (acc->h2 * scan_y - ellipse_y * acc->h2mw2) *
+ sqrt (acc->h2 - ellipse_y * ellipse_y) /
+ (def->h * def->w * ellipse_y);
+ return x;
+ }
+ }
+ }
+ if (left) {
+ if (acc->left.valid && boundedLe (scan_y, bound->left)) {
+ x = intersectLine (scan_y, acc->left);
+ } else {
+ if (acc->right.valid)
+ x = intersectLine (scan_y, acc->right);
+ else
+ x = def->w - def->l;
+ }
+ } else {
+ if (acc->right.valid && boundedLe (scan_y, bound->right)) {
+ x = intersectLine (scan_y, acc->right);
+ } else {
+ if (acc->left.valid)
+ x = intersectLine (scan_y, acc->left);
+ else
+ x = def->w - def->l;
+ }
+ }
+ return x;
+}
+
+/*
+ * generate the set of spans with
+ * the given y coordinate
+ */
+
+static void
+arcSpan (
+ int y,
+ int lx,
+ int lw,
+ int rx,
+ int rw,
+ struct arc_def *def,
+ struct arc_bound *bounds,
+ struct accelerators *acc,
+ int mask)
+{
+ int linx, loutx, rinx, routx;
+ double x, altx;
+
+ if (boundedLe (y, bounds->inneri)) {
+ linx = -(lx + lw);
+ rinx = rx;
+ } else {
+ /*
+ * intersection with left face
+ */
+ x = hookX (y + acc->fromIntY, def, bounds, acc, 1);
+ if (acc->right.valid &&
+ boundedLe (y + acc->fromIntY, bounds->right))
+ {
+ altx = intersectLine (y + acc->fromIntY, acc->right);
+ if (altx < x)
+ x = altx;
+ }
+ linx = -ICEIL(acc->fromIntX - x);
+ rinx = ICEIL(acc->fromIntX + x);
+ }
+ if (boundedLe (y, bounds->outeri)) {
+ loutx = -lx;
+ routx = rx + rw;
+ } else {
+ /*
+ * intersection with right face
+ */
+ x = hookX (y + acc->fromIntY, def, bounds, acc, 0);
+ if (acc->left.valid &&
+ boundedLe (y + acc->fromIntY, bounds->left))
+ {
+ altx = x;
+ x = intersectLine (y + acc->fromIntY, acc->left);
+ if (x < altx)
+ x = altx;
+ }
+ loutx = -ICEIL(acc->fromIntX - x);
+ routx = ICEIL(acc->fromIntX + x);
+ }
+ if (routx > rinx) {
+ if (mask & 1)
+ newFinalSpan (acc->yorgu - y,
+ acc->xorg + rinx, acc->xorg + routx);
+ if (mask & 8)
+ newFinalSpan (acc->yorgl + y,
+ acc->xorg + rinx, acc->xorg + routx);
+ }
+ if (loutx > linx) {
+ if (mask & 2)
+ newFinalSpan (acc->yorgu - y,
+ acc->xorg - loutx, acc->xorg - linx);
+ if (mask & 4)
+ newFinalSpan (acc->yorgl + y,
+ acc->xorg - loutx, acc->xorg - linx);
+ }
+}
+
+static void
+arcSpan0 (
+ int lx,
+ int lw,
+ int rx,
+ int rw,
+ struct arc_def *def,
+ struct arc_bound *bounds,
+ struct accelerators *acc,
+ int mask)
+{
+ double x;
+
+ if (boundedLe (0, bounds->inneri) &&
+ acc->left.valid && boundedLe (0, bounds->left) &&
+ acc->left.b > 0)
+ {
+ x = def->w - def->l;
+ if (acc->left.b < x)
+ x = acc->left.b;
+ lw = ICEIL(acc->fromIntX - x) - lx;
+ rw += rx;
+ rx = ICEIL(acc->fromIntX + x);
+ rw -= rx;
+ }
+ arcSpan (0, lx, lw, rx, rw, def, bounds, acc, mask);
+}
+
+static void
+tailSpan (
+ int y,
+ int lw,
+ int rw,
+ struct arc_def *def,
+ struct arc_bound *bounds,
+ struct accelerators *acc,
+ int mask)
+{
+ double yy, xalt, x, lx, rx;
+ int n;
+
+ if (boundedLe(y, bounds->outeri))
+ arcSpan (y, 0, lw, -rw, rw, def, bounds, acc, mask);
+ else if (def->w != def->h) {
+ yy = y + acc->fromIntY;
+ x = tailX(yy, def, bounds, acc);
+ if (yy == 0.0 && x == -rw - acc->fromIntX)
+ return;
+ if (acc->right.valid && boundedLe (yy, bounds->right)) {
+ rx = x;
+ lx = -x;
+ xalt = intersectLine (yy, acc->right);
+ if (xalt >= -rw - acc->fromIntX && xalt <= rx)
+ rx = xalt;
+ n = ICEIL(acc->fromIntX + lx);
+ if (lw > n) {
+ if (mask & 2)
+ newFinalSpan (acc->yorgu - y,
+ acc->xorg + n, acc->xorg + lw);
+ if (mask & 4)
+ newFinalSpan (acc->yorgl + y,
+ acc->xorg + n, acc->xorg + lw);
+ }
+ n = ICEIL(acc->fromIntX + rx);
+ if (n > -rw) {
+ if (mask & 1)
+ newFinalSpan (acc->yorgu - y,
+ acc->xorg - rw, acc->xorg + n);
+ if (mask & 8)
+ newFinalSpan (acc->yorgl + y,
+ acc->xorg - rw, acc->xorg + n);
+ }
+ }
+ arcSpan (y,
+ ICEIL(acc->fromIntX - x), 0,
+ ICEIL(acc->fromIntX + x), 0,
+ def, bounds, acc, mask);
+ }
+}
+
+/*
+ * create whole arcs out of pieces. This code is
+ * very bad.
+ */
+
+static struct finalSpan **finalSpans = NULL;
+static int finalMiny = 0, finalMaxy = -1;
+static int finalSize = 0;
+
+static int nspans = 0; /* total spans, not just y coords */
+
+struct finalSpan {
+ struct finalSpan *next;
+ int min, max; /* x values */
+};
+
+static struct finalSpan *freeFinalSpans, *tmpFinalSpan;
+
+# define allocFinalSpan() (freeFinalSpans ?\
+ ((tmpFinalSpan = freeFinalSpans), \
+ (freeFinalSpans = freeFinalSpans->next), \
+ (tmpFinalSpan->next = 0), \
+ tmpFinalSpan) : \
+ realAllocSpan ())
+
+# define SPAN_CHUNK_SIZE 128
+
+struct finalSpanChunk {
+ struct finalSpan data[SPAN_CHUNK_SIZE];
+ struct finalSpanChunk *next;
+};
+
+static struct finalSpanChunk *chunks;
+
+static struct finalSpan *
+realAllocSpan (void)
+{
+ struct finalSpanChunk *newChunk;
+ struct finalSpan *span;
+ int i;
+
+ newChunk = xalloc (sizeof (struct finalSpanChunk));
+ if (!newChunk)
+ return (struct finalSpan *) NULL;
+ newChunk->next = chunks;
+ chunks = newChunk;
+ freeFinalSpans = span = newChunk->data + 1;
+ for (i = 1; i < SPAN_CHUNK_SIZE-1; i++) {
+ span->next = span+1;
+ span++;
+ }
+ span->next = 0;
+ span = newChunk->data;
+ span->next = 0;
+ return span;
+}
+
+static void
+disposeFinalSpans (void)
+{
+ struct finalSpanChunk *chunk, *next;
+
+ for (chunk = chunks; chunk; chunk = next) {
+ next = chunk->next;
+ xfree (chunk);
+ }
+ chunks = 0;
+ freeFinalSpans = 0;
+ xfree(finalSpans);
+ finalSpans = 0;
+}
+
+static void
+fillSpans (
+ DrawablePtr pDrawable,
+ GCPtr pGC)
+{
+ struct finalSpan *span;
+ DDXPointPtr xSpan;
+ int *xWidth;
+ int i;
+ struct finalSpan **f;
+ int spany;
+ DDXPointPtr xSpans;
+ int *xWidths;
+
+ if (nspans == 0)
+ return;
+ xSpan = xSpans = xalloc (nspans * sizeof (DDXPointRec));
+ xWidth = xWidths = xalloc (nspans * sizeof (int));
+ if (xSpans && xWidths)
+ {
+ i = 0;
+ f = finalSpans;
+ for (spany = finalMiny; spany <= finalMaxy; spany++, f++) {
+ for (span = *f; span; span=span->next) {
+ if (span->max <= span->min)
+ continue;
+ xSpan->x = span->min;
+ xSpan->y = spany;
+ ++xSpan;
+ *xWidth++ = span->max - span->min;
+ ++i;
+ }
+ }
+ (*pGC->ops->FillSpans) (pDrawable, pGC, i, xSpans, xWidths, TRUE);
+ }
+ disposeFinalSpans ();
+ if (xSpans)
+ xfree (xSpans);
+ if (xWidths)
+ xfree (xWidths);
+ finalMiny = 0;
+ finalMaxy = -1;
+ finalSize = 0;
+ nspans = 0;
+}
+
+# define SPAN_REALLOC 100
+
+# define findSpan(y) ((finalMiny <= (y) && (y) <= finalMaxy) ? \
+ &finalSpans[(y) - finalMiny] : \
+ realFindSpan (y))
+
+static struct finalSpan **
+realFindSpan (int y)
+{
+ struct finalSpan **newSpans;
+ int newSize, newMiny, newMaxy;
+ int change;
+ int i;
+
+ if (y < finalMiny || y > finalMaxy) {
+ if (!finalSize) {
+ finalMiny = y;
+ finalMaxy = y - 1;
+ }
+ if (y < finalMiny)
+ change = finalMiny - y;
+ else
+ change = y - finalMaxy;
+ if (change >= SPAN_REALLOC)
+ change += SPAN_REALLOC;
+ else
+ change = SPAN_REALLOC;
+ newSize = finalSize + change;
+ newSpans = xalloc(newSize * sizeof (struct finalSpan *));
+ if (!newSpans)
+ return NULL;
+ newMiny = finalMiny;
+ newMaxy = finalMaxy;
+ if (y < finalMiny)
+ newMiny = finalMiny - change;
+ else
+ newMaxy = finalMaxy + change;
+ if (finalSpans) {
+ memmove(((char *) newSpans) + (finalMiny-newMiny) * sizeof (struct finalSpan *),
+ (char *) finalSpans,
+ finalSize * sizeof (struct finalSpan *));
+ xfree (finalSpans);
+ }
+ if ((i = finalMiny - newMiny) > 0)
+ bzero ((char *)newSpans, i * sizeof (struct finalSpan *));
+ if ((i = newMaxy - finalMaxy) > 0)
+ bzero ((char *)(newSpans + newSize - i),
+ i * sizeof (struct finalSpan *));
+ finalSpans = newSpans;
+ finalMaxy = newMaxy;
+ finalMiny = newMiny;
+ finalSize = newSize;
+ }
+ return &finalSpans[y - finalMiny];
+}
+
+static void
+newFinalSpan (
+ int y,
+ int xmin,
+ int xmax)
+{
+ struct finalSpan *x;
+ struct finalSpan **f;
+ struct finalSpan *oldx;
+ struct finalSpan *prev;
+
+ f = findSpan (y);
+ if (!f)
+ return;
+ oldx = 0;
+ for (;;) {
+ prev = 0;
+ for (x = *f; x; x=x->next) {
+ if (x == oldx) {
+ prev = x;
+ continue;
+ }
+ if (x->min <= xmax && xmin <= x->max) {
+ if (oldx) {
+ oldx->min = min (x->min, xmin);
+ oldx->max = max (x->max, xmax);
+ if (prev)
+ prev->next = x->next;
+ else
+ *f = x->next;
+ --nspans;
+ } else {
+ x->min = min (x->min, xmin);
+ x->max = max (x->max, xmax);
+ oldx = x;
+ }
+ xmin = oldx->min;
+ xmax = oldx->max;
+ break;
+ }
+ prev = x;
+ }
+ if (!x)
+ break;
+ }
+ if (!oldx) {
+ x = allocFinalSpan ();
+ if (x)
+ {
+ x->min = xmin;
+ x->max = xmax;
+ x->next = *f;
+ *f = x;
+ ++nspans;
+ }
+ }
+}
+
+static void
+mirrorSppPoint (
+ int quadrant,
+ SppPointPtr sppPoint)
+{
+ switch (quadrant) {
+ case 0:
+ break;
+ case 1:
+ sppPoint->x = -sppPoint->x;
+ break;
+ case 2:
+ sppPoint->x = -sppPoint->x;
+ sppPoint->y = -sppPoint->y;
+ break;
+ case 3:
+ sppPoint->y = -sppPoint->y;
+ break;
+ }
+ /*
+ * and translate to X coordinate system
+ */
+ sppPoint->y = -sppPoint->y;
+}
+
+/*
+ * split an arc into pieces which are scan-converted
+ * in the first-quadrant and mirrored into position.
+ * This is necessary as the scan-conversion code can
+ * only deal with arcs completely contained in the
+ * first quadrant.
+ */
+
+static void
+drawArc (
+ xArc *tarc,
+ int l,
+ int a0,
+ int a1,
+ miArcFacePtr right,
+ miArcFacePtr left) /* save end line points */
+{
+ struct arc_def def;
+ struct accelerators acc;
+ int startq, endq, curq;
+ int rightq, leftq = 0, righta = 0, lefta = 0;
+ miArcFacePtr passRight, passLeft;
+ int q0 = 0, q1 = 0, mask;
+ struct band {
+ int a0, a1;
+ int mask;
+ } band[5], sweep[20];
+ int bandno, sweepno;
+ int i, j;
+ int flipRight = 0, flipLeft = 0;
+ int copyEnd = 0;
+ miArcSpanData *spdata;
+
+ spdata = miComputeWideEllipse(l, tarc);
+ if (!spdata)
+ return;
+
+ if (a1 < a0)
+ a1 += 360 * 64;
+ startq = a0 / (90 * 64);
+ if (a0 == a1)
+ endq = startq;
+ else
+ endq = (a1-1) / (90 * 64);
+ bandno = 0;
+ curq = startq;
+ rightq = -1;
+ for (;;) {
+ switch (curq) {
+ case 0:
+ if (a0 > 90 * 64)
+ q0 = 0;
+ else
+ q0 = a0;
+ if (a1 < 360 * 64)
+ q1 = min (a1, 90 * 64);
+ else
+ q1 = 90 * 64;
+ if (curq == startq && a0 == q0 && rightq < 0) {
+ righta = q0;
+ rightq = curq;
+ }
+ if (curq == endq && a1 == q1) {
+ lefta = q1;
+ leftq = curq;
+ }
+ break;
+ case 1:
+ if (a1 < 90 * 64)
+ q0 = 0;
+ else
+ q0 = 180 * 64 - min (a1, 180 * 64);
+ if (a0 > 180 * 64)
+ q1 = 90 * 64;
+ else
+ q1 = 180 * 64 - max (a0, 90 * 64);
+ if (curq == startq && 180 * 64 - a0 == q1) {
+ righta = q1;
+ rightq = curq;
+ }
+ if (curq == endq && 180 * 64 - a1 == q0) {
+ lefta = q0;
+ leftq = curq;
+ }
+ break;
+ case 2:
+ if (a0 > 270 * 64)
+ q0 = 0;
+ else
+ q0 = max (a0, 180 * 64) - 180 * 64;
+ if (a1 < 180 * 64)
+ q1 = 90 * 64;
+ else
+ q1 = min (a1, 270 * 64) - 180 * 64;
+ if (curq == startq && a0 - 180*64 == q0) {
+ righta = q0;
+ rightq = curq;
+ }
+ if (curq == endq && a1 - 180 * 64 == q1) {
+ lefta = q1;
+ leftq = curq;
+ }
+ break;
+ case 3:
+ if (a1 < 270 * 64)
+ q0 = 0;
+ else
+ q0 = 360 * 64 - min (a1, 360 * 64);
+ q1 = 360 * 64 - max (a0, 270 * 64);
+ if (curq == startq && 360 * 64 - a0 == q1) {
+ righta = q1;
+ rightq = curq;
+ }
+ if (curq == endq && 360 * 64 - a1 == q0) {
+ lefta = q0;
+ leftq = curq;
+ }
+ break;
+ }
+ band[bandno].a0 = q0;
+ band[bandno].a1 = q1;
+ band[bandno].mask = 1 << curq;
+ bandno++;
+ if (curq == endq)
+ break;
+ curq++;
+ if (curq == 4) {
+ a0 = 0;
+ a1 -= 360 * 64;
+ curq = 0;
+ endq -= 4;
+ }
+ }
+ sweepno = 0;
+ for (;;) {
+ q0 = 90 * 64;
+ mask = 0;
+ /*
+ * find left-most point
+ */
+ for (i = 0; i < bandno; i++)
+ if (band[i].a0 <= q0) {
+ q0 = band[i].a0;
+ q1 = band[i].a1;
+ mask = band[i].mask;
+ }
+ if (!mask)
+ break;
+ /*
+ * locate next point of change
+ */
+ for (i = 0; i < bandno; i++)
+ if (!(mask & band[i].mask)) {
+ if (band[i].a0 == q0) {
+ if (band[i].a1 < q1)
+ q1 = band[i].a1;
+ mask |= band[i].mask;
+ } else if (band[i].a0 < q1)
+ q1 = band[i].a0;
+ }
+ /*
+ * create a new sweep
+ */
+ sweep[sweepno].a0 = q0;
+ sweep[sweepno].a1 = q1;
+ sweep[sweepno].mask = mask;
+ sweepno++;
+ /*
+ * subtract the sweep from the affected bands
+ */
+ for (i = 0; i < bandno; i++)
+ if (band[i].a0 == q0) {
+ band[i].a0 = q1;
+ /*
+ * check if this band is empty
+ */
+ if (band[i].a0 == band[i].a1)
+ band[i].a1 = band[i].a0 = 90 * 64 + 1;
+ }
+ }
+ computeAcc (tarc, l, &def, &acc);
+ for (j = 0; j < sweepno; j++) {
+ mask = sweep[j].mask;
+ passRight = passLeft = 0;
+ if (mask & (1 << rightq)) {
+ if (sweep[j].a0 == righta)
+ passRight = right;
+ else if (sweep[j].a1 == righta) {
+ passLeft = right;
+ flipRight = 1;
+ }
+ }
+ if (mask & (1 << leftq)) {
+ if (sweep[j].a1 == lefta)
+ {
+ if (passLeft)
+ copyEnd = 1;
+ passLeft = left;
+ }
+ else if (sweep[j].a0 == lefta) {
+ if (passRight)
+ copyEnd = 1;
+ passRight = left;
+ flipLeft = 1;
+ }
+ }
+ drawQuadrant (&def, &acc, sweep[j].a0, sweep[j].a1, mask,
+ passRight, passLeft, spdata);
+ }
+ /*
+ * when copyEnd is set, both ends of the arc were computed
+ * at the same time; drawQuadrant only takes one end though,
+ * so the left end will be the only one holding the data. Copy
+ * it from there.
+ */
+ if (copyEnd)
+ *right = *left;
+ /*
+ * mirror the coordinates generated for the
+ * faces of the arc
+ */
+ if (right) {
+ mirrorSppPoint (rightq, &right->clock);
+ mirrorSppPoint (rightq, &right->center);
+ mirrorSppPoint (rightq, &right->counterClock);
+ if (flipRight) {
+ SppPointRec temp;
+
+ temp = right->clock;
+ right->clock = right->counterClock;
+ right->counterClock = temp;
+ }
+ }
+ if (left) {
+ mirrorSppPoint (leftq, &left->counterClock);
+ mirrorSppPoint (leftq, &left->center);
+ mirrorSppPoint (leftq, &left->clock);
+ if (flipLeft) {
+ SppPointRec temp;
+
+ temp = left->clock;
+ left->clock = left->counterClock;
+ left->counterClock = temp;
+ }
+ }
+ xfree(spdata);
+}
+
+static void
+drawQuadrant (
+ struct arc_def *def,
+ struct accelerators *acc,
+ int a0,
+ int a1,
+ int mask,
+ miArcFacePtr right,
+ miArcFacePtr left,
+ miArcSpanData *spdata)
+{
+ struct arc_bound bound;
+ double yy, x, xalt;
+ int y, miny, maxy;
+ int n;
+ miArcSpan *span;
+
+ def->a0 = ((double) a0) / 64.0;
+ def->a1 = ((double) a1) / 64.0;
+ computeBound (def, &bound, acc, right, left);
+ yy = bound.inner.min;
+ if (bound.outer.min < yy)
+ yy = bound.outer.min;
+ miny = ICEIL(yy - acc->fromIntY);
+ yy = bound.inner.max;
+ if (bound.outer.max > yy)
+ yy = bound.outer.max;
+ maxy = floor(yy - acc->fromIntY);
+ y = spdata->k;
+ span = spdata->spans;
+ if (spdata->top)
+ {
+ if (a1 == 90 * 64 && (mask & 1))
+ newFinalSpan (acc->yorgu - y - 1, acc->xorg, acc->xorg + 1);
+ span++;
+ }
+ for (n = spdata->count1; --n >= 0; )
+ {
+ if (y < miny)
+ return;
+ if (y <= maxy) {
+ arcSpan (y,
+ span->lx, -span->lx, 0, span->lx + span->lw,
+ def, &bound, acc, mask);
+ if (span->rw + span->rx)
+ tailSpan (y, -span->rw, -span->rx, def, &bound, acc, mask);
+ }
+ y--;
+ span++;
+ }
+ if (y < miny)
+ return;
+ if (spdata->hole)
+ {
+ if (y <= maxy)
+ arcSpan (y, 0, 0, 0, 1, def, &bound, acc, mask & 0xc);
+ }
+ for (n = spdata->count2; --n >= 0; )
+ {
+ if (y < miny)
+ return;
+ if (y <= maxy)
+ arcSpan (y, span->lx, span->lw, span->rx, span->rw,
+ def, &bound, acc, mask);
+ y--;
+ span++;
+ }
+ if (spdata->bot && miny <= y && y <= maxy)
+ {
+ n = mask;
+ if (y == miny)
+ n &= 0xc;
+ if (span->rw <= 0) {
+ arcSpan0 (span->lx, -span->lx, 0, span->lx + span->lw,
+ def, &bound, acc, n);
+ if (span->rw + span->rx)
+ tailSpan (y, -span->rw, -span->rx, def, &bound, acc, n);
+ }
+ else
+ arcSpan0 (span->lx, span->lw, span->rx, span->rw,
+ def, &bound, acc, n);
+ y--;
+ }
+ while (y >= miny) {
+ yy = y + acc->fromIntY;
+ if (def->w == def->h) {
+ xalt = def->w - def->l;
+ x = -sqrt(xalt * xalt - yy * yy);
+ } else {
+ x = tailX(yy, def, &bound, acc);
+ if (acc->left.valid && boundedLe (yy, bound.left)) {
+ xalt = intersectLine (yy, acc->left);
+ if (xalt < x)
+ x = xalt;
+ }
+ if (acc->right.valid && boundedLe (yy, bound.right)) {
+ xalt = intersectLine (yy, acc->right);
+ if (xalt < x)
+ x = xalt;
+ }
+ }
+ arcSpan (y,
+ ICEIL(acc->fromIntX - x), 0,
+ ICEIL(acc->fromIntX + x), 0,
+ def, &bound, acc, mask);
+ y--;
+ }
+}
diff --git a/xorg-server/os/access.c b/xorg-server/os/access.c
index 74c340a43..603210f85 100644
--- a/xorg-server/os/access.c
+++ b/xorg-server/os/access.c
@@ -1,2202 +1,2202 @@
-/***********************************************************
-
-Copyright 1987, 1998 The Open Group
-
-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.
-
-X Window System is a trademark of 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.
-
-******************************************************************/
-
-/*
- * Copyright © 2004 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, 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.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifdef WIN32
-#include <X11/Xwinsock.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#define XSERV_t
-#define TRANS_SERVER
-#define TRANS_REOPEN
-#include <X11/Xtrans/Xtrans.h>
-#include <X11/Xauth.h>
-#include <X11/X.h>
-#include <X11/Xproto.h>
-#include "misc.h"
-#include "site.h"
-#include <errno.h>
-#include <sys/types.h>
-#ifndef WIN32
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <ctype.h>
-
-#if defined(TCPCONN) || defined(STREAMSCONN) || defined(__SCO__)
-#include <netinet/in.h>
-#endif /* TCPCONN || STREAMSCONN || ISC || __SCO__ */
-#ifdef DNETCONN
-#include <netdnet/dn.h>
-#include <netdnet/dnetdb.h>
-#endif
-
-#ifdef HAS_GETPEERUCRED
-# include <ucred.h>
-# ifdef sun
-# include <zone.h>
-# endif
-#endif
-
-#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__)
-# include <sys/utsname.h>
-#endif
-#if defined(SYSV) && defined(__i386__)
-# include <sys/stream.h>
-#endif
-#ifdef __GNU__
-#undef SIOCGIFCONF
-#include <netdb.h>
-#else /*!__GNU__*/
-# include <net/if.h>
-#endif /*__GNU__ */
-
-#ifdef SVR4
-#include <sys/sockio.h>
-#include <sys/stropts.h>
-#endif
-
-#include <netdb.h>
-
-#ifdef CSRG_BASED
-#include <sys/param.h>
-#if (BSD >= 199103)
-#define VARIABLE_IFREQ
-#endif
-#endif
-
-#ifdef BSD44SOCKETS
-#ifndef VARIABLE_IFREQ
-#define VARIABLE_IFREQ
-#endif
-#endif
-
-#ifdef HAS_GETIFADDRS
-#include <ifaddrs.h>
-#endif
-
-/* Solaris provides an extended interface SIOCGLIFCONF. Other systems
- * may have this as well, but the code has only been tested on Solaris
- * so far, so we only enable it there. Other platforms may be added as
- * needed.
- *
- * Test for Solaris commented out -- TSI @ UQV 2003.06.13
- */
-#ifdef SIOCGLIFCONF
-/* #if defined(sun) */
-#define USE_SIOCGLIFCONF
-/* #endif */
-#endif
-
-#endif /* WIN32 */
-
-#ifndef PATH_MAX
-#include <sys/param.h>
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX 1024
-#endif
-#endif
-#endif
-
-#ifdef __SCO__
-/* The system defined value is wrong. MAXPATHLEN is set in sco5.cf. */
-#undef PATH_MAX
-#endif
-
-#define X_INCLUDE_NETDB_H
-#include <X11/Xos_r.h>
-
-#include "dixstruct.h"
-#include "osdep.h"
-
-#include "xace.h"
-
-#ifndef PATH_MAX
-#ifdef MAXPATHLEN
-#define PATH_MAX MAXPATHLEN
-#else
-#define PATH_MAX 1024
-#endif
-#endif
-
-Bool defeatAccessControl = FALSE;
-
-#define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len)
-#define acopy(a1, a2, len) memmove((char *)(a2), (char *)(a1), len)
-#define addrEqual(fam, address, length, host) \
- ((fam) == (host)->family &&\
- (length) == (host)->len &&\
- !acmp (address, (host)->addr, length))
-
-static int ConvertAddr(struct sockaddr * /*saddr*/,
- int * /*len*/,
- pointer * /*addr*/);
-
-static int CheckAddr(int /*family*/,
- pointer /*pAddr*/,
- unsigned /*length*/);
-
-static Bool NewHost(int /*family*/,
- pointer /*addr*/,
- int /*len*/,
- int /* addingLocalHosts */);
-
-/* XFree86 bug #156: To keep track of which hosts were explicitly requested in
- /etc/X<display>.hosts, we've added a requested field to the HOST struct,
- and a LocalHostRequested variable. These default to FALSE, but are set
- to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are
- checked in DisableLocalHost(), which is called to disable the default
- local host entries when stronger authentication is turned on. */
-
-typedef struct _host {
- short family;
- short len;
- unsigned char *addr;
- struct _host *next;
- int requested;
-} HOST;
-
-#define MakeHost(h,l) (h)=xalloc(sizeof *(h)+(l));\
- if (h) { \
- (h)->addr=(unsigned char *) ((h) + 1);\
- (h)->requested = FALSE; \
- }
-#define FreeHost(h) xfree(h)
-static HOST *selfhosts = NULL;
-static HOST *validhosts = NULL;
-static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
-static int LocalHostEnabled = FALSE;
-static int LocalHostRequested = FALSE;
-static int UsingXdmcp = FALSE;
-
-/* FamilyServerInterpreted implementation */
-static Bool siAddrMatch(int family, pointer addr, int len, HOST *host,
- ClientPtr client);
-static int siCheckAddr(const char *addrString, int length);
-static void siTypesInitialize(void);
-
-/*
- * called when authorization is not enabled to add the
- * local host to the access list
- */
-
-void
-EnableLocalHost (void)
-{
- if (!UsingXdmcp)
- {
- LocalHostEnabled = TRUE;
- AddLocalHosts ();
- }
-}
-
-/*
- * called when authorization is enabled to keep us secure
- */
-void
-DisableLocalHost (void)
-{
- HOST *self;
-
- if (!LocalHostRequested) /* Fix for XFree86 bug #156 */
- LocalHostEnabled = FALSE;
- for (self = selfhosts; self; self = self->next) {
- if (!self->requested) /* Fix for XFree86 bug #156 */
- (void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (pointer)self->addr);
- }
-}
-
-/*
- * called at init time when XDMCP will be used; xdmcp always
- * adds local hosts manually when needed
- */
-
-void
-AccessUsingXdmcp (void)
-{
- UsingXdmcp = TRUE;
- LocalHostEnabled = FALSE;
-}
-
-
-#if defined(SVR4) && !defined(SCO325) && !defined(sun) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF)
-
-/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
-
-static int
-ifioctl (int fd, int cmd, char *arg)
-{
- struct strioctl ioc;
- int ret;
-
- bzero((char *) &ioc, sizeof(ioc));
- ioc.ic_cmd = cmd;
- ioc.ic_timout = 0;
- if (cmd == SIOCGIFCONF)
- {
- ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
- ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
- }
- else
- {
- ioc.ic_len = sizeof(struct ifreq);
- ioc.ic_dp = arg;
- }
- ret = ioctl(fd, I_STR, (char *) &ioc);
- if (ret >= 0 && cmd == SIOCGIFCONF)
-#ifdef SVR4
- ((struct ifconf *) arg)->ifc_len = ioc.ic_len;
-#endif
- return(ret);
-}
-#else /* Case sun, SCO325 and others */
-#define ifioctl ioctl
-#endif /* ((SVR4 && !sun !SCO325) || ISC) && SIOCGIFCONF */
-
-/*
- * DefineSelf (fd):
- *
- * Define this host for access control. Find all the hosts the OS knows about
- * for this fd and add them to the selfhosts list.
- */
-
-#if !defined(SIOCGIFCONF)
-void
-DefineSelf (int fd)
-{
-#if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN) && !defined(MNX_TCPCONN)
- return;
-#else
- register int n;
- int len;
- caddr_t addr;
- int family;
- register HOST *host;
-
-#ifndef WIN32
- struct utsname name;
-#else
- struct {
- char nodename[512];
- } name;
-#endif
-
- register struct hostent *hp;
-
- union {
- struct sockaddr sa;
- struct sockaddr_in in;
-#if defined(IPv6) && defined(AF_INET6)
- struct sockaddr_in6 in6;
-#endif
- } saddr;
-
- struct sockaddr_in *inetaddr;
- struct sockaddr_in6 *inet6addr;
- struct sockaddr_in broad_addr;
-#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
-#endif
-
- /* Why not use gethostname()? Well, at least on my system, I've had to
- * make an ugly kernel patch to get a name longer than 8 characters, and
- * uname() lets me access to the whole string (it smashes release, you
- * see), whereas gethostname() kindly truncates it for me.
- */
-#ifndef WIN32
- uname(&name);
-#else
- gethostname(name.nodename, sizeof(name.nodename));
-#endif
-
- hp = _XGethostbyname(name.nodename, hparams);
- if (hp != NULL)
- {
- saddr.sa.sa_family = hp->h_addrtype;
- switch (hp->h_addrtype) {
- case AF_INET:
- inetaddr = (struct sockaddr_in *) (&(saddr.sa));
- acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length);
- len = sizeof(saddr.sa);
- break;
-#if defined(IPv6) && defined(AF_INET6)
- case AF_INET6:
- inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
- acopy ( hp->h_addr, &(inet6addr->sin6_addr), hp->h_length);
- len = sizeof(saddr.in6);
- break;
-#endif
- default:
- goto DefineLocalHost;
- }
- family = ConvertAddr ( &(saddr.sa), &len, (pointer *)&addr);
- if ( family != -1 && family != FamilyLocal )
- {
- for (host = selfhosts;
- host && !addrEqual (family, addr, len, host);
- host = host->next) ;
- if (!host)
- {
- /* add this host to the host list. */
- MakeHost(host,len)
- if (host)
- {
- host->family = family;
- host->len = len;
- acopy ( addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
-#ifdef XDMCP
- /*
- * If this is an Internet Address, but not the localhost
- * address (127.0.0.1), nor the bogus address (0.0.0.0),
- * register it.
- */
- if (family == FamilyInternet &&
- !(len == 4 &&
- ((addr[0] == 127) ||
- (addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)))
- )
- {
- XdmcpRegisterConnection (family, (char *)addr, len);
- broad_addr = *inetaddr;
- ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
- htonl (INADDR_BROADCAST);
- XdmcpRegisterBroadcastAddress ((struct sockaddr_in *)
- &broad_addr);
- }
-#if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)))
- {
- XdmcpRegisterConnection (family, (char *)addr, len);
- }
-#endif
-
-#endif /* XDMCP */
- }
- }
- }
- /*
- * now add a host of family FamilyLocalHost...
- */
-DefineLocalHost:
- for (host = selfhosts;
- host && !addrEqual(FamilyLocalHost, "", 0, host);
- host = host->next);
- if (!host)
- {
- MakeHost(host, 0);
- if (host)
- {
- host->family = FamilyLocalHost;
- host->len = 0;
- acopy("", host->addr, 0);
- host->next = selfhosts;
- selfhosts = host;
- }
- }
-#endif /* !TCPCONN && !STREAMSCONN && !UNIXCONN && !MNX_TCPCONN */
-}
-
-#else
-
-#ifdef USE_SIOCGLIFCONF
-#define ifr_type struct lifreq
-#else
-#define ifr_type struct ifreq
-#endif
-
-#ifdef VARIABLE_IFREQ
-#define ifr_size(p) (sizeof (struct ifreq) + \
- (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
- p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
-#define ifraddr_size(a) (a.sa_len)
-#else
-#define ifr_size(p) (sizeof (ifr_type))
-#define ifraddr_size(a) (sizeof (a))
-#endif
-
-#if defined(IPv6) && defined(AF_INET6)
-#include <arpa/inet.h>
-#endif
-
-#if defined(IPv6) && defined(AF_INET6)
-static void
-in6_fillscopeid(struct sockaddr_in6 *sin6)
-{
-#if defined(__KAME__)
- if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
- sin6->sin6_scope_id =
- ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
- sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
- }
-#endif
-}
-#endif
-
-void
-DefineSelf (int fd)
-{
-#ifndef HAS_GETIFADDRS
- char *cp, *cplim;
-# ifdef USE_SIOCGLIFCONF
- struct sockaddr_storage buf[16];
- struct lifconf ifc;
- register struct lifreq *ifr;
-# ifdef SIOCGLIFNUM
- struct lifnum ifn;
-# endif
-# else /* !USE_SIOCGLIFCONF */
- char buf[2048];
- struct ifconf ifc;
- register struct ifreq *ifr;
-# endif
- void * bufptr = buf;
-#else /* HAS_GETIFADDRS */
- struct ifaddrs * ifap, *ifr;
-#endif
- int len;
- unsigned char * addr;
- int family;
- register HOST *host;
-
-#ifdef DNETCONN
- struct dn_naddr *dnaddr = getnodeadd();
- /*
- * AF_DECnet may not be listed in the interface list. Instead use
- * the supported library call to find out the local address (if any).
- */
- if (dnaddr)
- {
- addr = (unsigned char *) dnaddr;
- len = dnaddr->a_len + sizeof(dnaddr->a_len);
- family = FamilyDECnet;
- for (host = selfhosts;
- host && !addrEqual (family, addr, len, host);
- host = host->next)
- ;
- if (!host)
- {
- MakeHost(host,len)
- if (host)
- {
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
- }
- }
-#endif /* DNETCONN */
-#ifndef HAS_GETIFADDRS
-
- len = sizeof(buf);
-
-#ifdef USE_SIOCGLIFCONF
-
-#ifdef SIOCGLIFNUM
- ifn.lifn_family = AF_UNSPEC;
- ifn.lifn_flags = 0;
- if (ioctl (fd, SIOCGLIFNUM, (char *) &ifn) < 0)
- Error ("Getting interface count");
- if (len < (ifn.lifn_count * sizeof(struct lifreq))) {
- len = ifn.lifn_count * sizeof(struct lifreq);
- bufptr = xalloc(len);
- }
-#endif
-
- ifc.lifc_family = AF_UNSPEC;
- ifc.lifc_flags = 0;
- ifc.lifc_len = len;
- ifc.lifc_buf = bufptr;
-
-#define IFC_IOCTL_REQ SIOCGLIFCONF
-#define IFC_IFC_REQ ifc.lifc_req
-#define IFC_IFC_LEN ifc.lifc_len
-#define IFR_IFR_ADDR ifr->lifr_addr
-#define IFR_IFR_NAME ifr->lifr_name
-
-#else /* Use SIOCGIFCONF */
- ifc.ifc_len = len;
- ifc.ifc_buf = bufptr;
-
-#define IFC_IOCTL_REQ SIOCGIFCONF
-#define IFC_IFC_REQ ifc.ifc_req
-#define IFC_IFC_LEN ifc.ifc_len
-#define IFR_IFR_ADDR ifr->ifr_addr
-#define IFR_IFR_NAME ifr->ifr_name
-#endif
-
- if (ifioctl (fd, IFC_IOCTL_REQ, (pointer) &ifc) < 0)
- Error ("Getting interface configuration (4)");
-
- cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN;
-
- for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
- {
- ifr = (ifr_type *) cp;
- len = ifraddr_size (IFR_IFR_ADDR);
- family = ConvertAddr ((struct sockaddr *) &IFR_IFR_ADDR,
- &len, (pointer *)&addr);
-#ifdef DNETCONN
- /*
- * DECnet was handled up above.
- */
- if (family == AF_DECnet)
- continue;
-#endif /* DNETCONN */
- if (family == -1 || family == FamilyLocal)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- in6_fillscopeid((struct sockaddr_in6 *)&IFR_IFR_ADDR);
-#endif
- for (host = selfhosts;
- host && !addrEqual (family, addr, len, host);
- host = host->next)
- ;
- if (host)
- continue;
- MakeHost(host,len)
- if (host)
- {
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
-#ifdef XDMCP
- {
-#ifdef USE_SIOCGLIFCONF
- struct sockaddr_storage broad_addr;
-#else
- struct sockaddr broad_addr;
-#endif
-
- /*
- * If this isn't an Internet Address, don't register it.
- */
- if (family != FamilyInternet
-#if defined(IPv6) && defined(AF_INET6)
- && family != FamilyInternet6
-#endif
- )
- continue;
-
- /*
- * ignore 'localhost' entries as they're not useful
- * on the other end of the wire
- */
- if (family == FamilyInternet &&
- addr[0] == 127 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 1)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
- continue;
-#endif
-
- /*
- * Ignore '0.0.0.0' entries as they are
- * returned by some OSes for unconfigured NICs but they are
- * not useful on the other end of the wire.
- */
- if (len == 4 &&
- addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)
- continue;
-
- XdmcpRegisterConnection (family, (char *)addr, len);
-
-#if defined(IPv6) && defined(AF_INET6)
- /* IPv6 doesn't support broadcasting, so we drop out here */
- if (family == FamilyInternet6)
- continue;
-#endif
-
- broad_addr = IFR_IFR_ADDR;
-
- ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
- htonl (INADDR_BROADCAST);
-#if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR)
- {
- struct lifreq broad_req;
-
- broad_req = *ifr;
- if (ioctl (fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 &&
- (broad_req.lifr_flags & IFF_BROADCAST) &&
- (broad_req.lifr_flags & IFF_UP)
- )
- {
- broad_req = *ifr;
- if (ioctl (fd, SIOCGLIFBRDADDR, &broad_req) != -1)
- broad_addr = broad_req.lifr_broadaddr;
- else
- continue;
- }
- else
- continue;
- }
-
-#elif defined(SIOCGIFBRDADDR)
- {
- struct ifreq broad_req;
-
- broad_req = *ifr;
- if (ifioctl (fd, SIOCGIFFLAGS, (pointer) &broad_req) != -1 &&
- (broad_req.ifr_flags & IFF_BROADCAST) &&
- (broad_req.ifr_flags & IFF_UP)
- )
- {
- broad_req = *ifr;
- if (ifioctl (fd, SIOCGIFBRDADDR, (pointer) &broad_req) != -1)
- broad_addr = broad_req.ifr_addr;
- else
- continue;
- }
- else
- continue;
- }
-#endif /* SIOCGIFBRDADDR */
- XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr);
- }
-#endif /* XDMCP */
- }
- if (bufptr != buf)
- free(bufptr);
-#else /* HAS_GETIFADDRS */
- if (getifaddrs(&ifap) < 0) {
- ErrorF("Warning: getifaddrs returns %s\n", strerror(errno));
- return;
- }
- for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) {
- if (!ifr->ifa_addr)
- continue;
-#ifdef DNETCONN
- if (ifr->ifa_addr.sa_family == AF_DECnet)
- continue;
-#endif /* DNETCONN */
- len = sizeof(*(ifr->ifa_addr));
- family = ConvertAddr(ifr->ifa_addr, &len, (pointer *)&addr);
- if (family == -1 || family == FamilyLocal)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- in6_fillscopeid((struct sockaddr_in6 *)ifr->ifa_addr);
-#endif
-
- for (host = selfhosts;
- host != NULL && !addrEqual(family, addr, len, host);
- host = host->next)
- ;
- if (host != NULL)
- continue;
- MakeHost(host, len);
- if (host != NULL) {
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
- }
-#ifdef XDMCP
- {
- struct sockaddr broad_addr;
- /*
- * If this isn't an Internet Address, don't register it.
- */
- if (family != FamilyInternet
-#if defined(IPv6) && defined(AF_INET6)
- && family != FamilyInternet6
-#endif
- )
- continue;
-
- /*
- * ignore 'localhost' entries as they're not useful
- * on the other end of the wire
- */
- if (ifr->ifa_flags & IFF_LOOPBACK)
- continue;
-
- if (family == FamilyInternet &&
- addr[0] == 127 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 1)
- continue;
-
- /*
- * Ignore '0.0.0.0' entries as they are
- * returned by some OSes for unconfigured NICs but they are
- * not useful on the other end of the wire.
- */
- if (len == 4 &&
- addr[0] == 0 && addr[1] == 0 &&
- addr[2] == 0 && addr[3] == 0)
- continue;
-#if defined(IPv6) && defined(AF_INET6)
- else if (family == FamilyInternet6 &&
- IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
- continue;
-#endif
- XdmcpRegisterConnection(family, (char *)addr, len);
-#if defined(IPv6) && defined(AF_INET6)
- if (family == FamilyInternet6)
- /* IPv6 doesn't support broadcasting, so we drop out here */
- continue;
-#endif
- if ((ifr->ifa_flags & IFF_BROADCAST) &&
- (ifr->ifa_flags & IFF_UP) &&
- ifr->ifa_broadaddr)
- broad_addr = *ifr->ifa_broadaddr;
- else
- continue;
- XdmcpRegisterBroadcastAddress((struct sockaddr_in *)
- &broad_addr);
- }
-#endif /* XDMCP */
-
- } /* for */
- freeifaddrs(ifap);
-#endif /* HAS_GETIFADDRS */
-
- /*
- * add something of FamilyLocalHost
- */
- for (host = selfhosts;
- host && !addrEqual(FamilyLocalHost, "", 0, host);
- host = host->next);
- if (!host)
- {
- MakeHost(host, 0);
- if (host)
- {
- host->family = FamilyLocalHost;
- host->len = 0;
- acopy("", host->addr, 0);
- host->next = selfhosts;
- selfhosts = host;
- }
- }
-}
-#endif /* hpux && !HAS_IFREQ */
-
-#ifdef XDMCP
-void
-AugmentSelf(pointer from, int len)
-{
- int family;
- pointer addr;
- register HOST *host;
-
- family = ConvertAddr(from, &len, (pointer *)&addr);
- if (family == -1 || family == FamilyLocal)
- return;
- for (host = selfhosts; host; host = host->next)
- {
- if (addrEqual(family, addr, len, host))
- return;
- }
- MakeHost(host,len)
- if (!host)
- return;
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = selfhosts;
- selfhosts = host;
-}
-#endif
-
-void
-AddLocalHosts (void)
-{
- HOST *self;
-
- for (self = selfhosts; self; self = self->next)
- /* Fix for XFree86 bug #156: pass addingLocal = TRUE to
- * NewHost to tell that we are adding the default local
- * host entries and not to flag the entries as being
- * explicitely requested */
- (void) NewHost (self->family, self->addr, self->len, TRUE);
-}
-
-/* Reset access control list to initial hosts */
-void
-ResetHosts (char *display)
-{
- register HOST *host;
- char lhostname[120], ohostname[120];
- char *hostname = ohostname;
- char fname[PATH_MAX + 1];
- int fnamelen;
- FILE *fd;
- char *ptr;
- int i, hostlen;
-#if ((defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)) && \
- (!defined(IPv6) || !defined(AF_INET6))) || defined(DNETCONN)
- union {
- struct sockaddr sa;
-#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
- struct sockaddr_in in;
-#endif /* TCPCONN || STREAMSCONN */
-#ifdef DNETCONN
- struct sockaddr_dn dn;
-#endif
- } saddr;
-#endif
-#ifdef DNETCONN
- struct nodeent *np;
- struct dn_naddr dnaddr, *dnaddrp, *dnet_addr();
-#endif
- int family = 0;
- pointer addr;
- int len;
-
- siTypesInitialize();
- AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
- LocalHostEnabled = FALSE;
- while ((host = validhosts) != 0)
- {
- validhosts = host->next;
- FreeHost (host);
- }
-
-#if defined WIN32 && defined __MINGW32__
-#define ETC_HOST_PREFIX "X"
-#else
-#define ETC_HOST_PREFIX "/etc/X"
-#endif
-#define ETC_HOST_SUFFIX ".hosts"
- fnamelen = strlen(ETC_HOST_PREFIX) + strlen(ETC_HOST_SUFFIX) +
- strlen(display) + 1;
- if (fnamelen > sizeof(fname))
- FatalError("Display name `%s' is too long\n", display);
- snprintf(fname, sizeof(fname), ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX,
- display);
-
- if ((fd = fopen (fname, "r")) != 0)
- {
- while (fgets (ohostname, sizeof (ohostname), fd))
- {
- family = FamilyWild;
- if (*ohostname == '#')
- continue;
- if ((ptr = strchr(ohostname, '\n')) != 0)
- *ptr = 0;
- hostlen = strlen(ohostname) + 1;
- for (i = 0; i < hostlen; i++)
- lhostname[i] = tolower(ohostname[i]);
- hostname = ohostname;
- if (!strncmp("local:", lhostname, 6))
- {
- family = FamilyLocalHost;
- NewHost(family, "", 0, FALSE);
- LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */
- }
-#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
- else if (!strncmp("inet:", lhostname, 5))
- {
- family = FamilyInternet;
- hostname = ohostname + 5;
- }
-#if defined(IPv6) && defined(AF_INET6)
- else if (!strncmp("inet6:", lhostname, 6))
- {
- family = FamilyInternet6;
- hostname = ohostname + 6;
- }
-#endif
-#endif
-#ifdef DNETCONN
- else if (!strncmp("dnet:", lhostname, 5))
- {
- family = FamilyDECnet;
- hostname = ohostname + 5;
- }
-#endif
-#ifdef SECURE_RPC
- else if (!strncmp("nis:", lhostname, 4))
- {
- family = FamilyNetname;
- hostname = ohostname + 4;
- }
-#endif
- else if (!strncmp("si:", lhostname, 3))
- {
- family = FamilyServerInterpreted;
- hostname = ohostname + 3;
- hostlen -= 3;
- }
-
-
- if (family == FamilyServerInterpreted)
- {
- len = siCheckAddr(hostname, hostlen);
- if (len >= 0) {
- NewHost(family, hostname, len, FALSE);
- }
- }
- else
-#ifdef DNETCONN
- if ((family == FamilyDECnet) || ((family == FamilyWild) &&
- (ptr = strchr(hostname, ':')) && (*(ptr + 1) == ':') &&
- !(*ptr = '\0'))) /* bash trailing colons if necessary */
- {
- /* node name (DECnet names end in "::") */
- dnaddrp = dnet_addr(hostname);
- if (!dnaddrp && (np = getnodebyname (hostname)))
- {
- /* node was specified by name */
- saddr.sa.sa_family = np->n_addrtype;
- len = sizeof(saddr.sa);
- if (ConvertAddr (&saddr.sa, &len, (pointer *)&addr) == FamilyDECnet)
- {
- bzero ((char *) &dnaddr, sizeof (dnaddr));
- dnaddr.a_len = np->n_length;
- acopy (np->n_addr, dnaddr.a_addr, np->n_length);
- dnaddrp = &dnaddr;
- }
- }
- if (dnaddrp)
- (void) NewHost(FamilyDECnet, (pointer)dnaddrp,
- (int)(dnaddrp->a_len + sizeof(dnaddrp->a_len)), FALSE);
- }
- else
-#endif /* DNETCONN */
-#ifdef SECURE_RPC
- if ((family == FamilyNetname) || (strchr(hostname, '@')))
- {
- SecureRPCInit ();
- (void) NewHost (FamilyNetname, hostname, strlen (hostname), FALSE);
- }
- else
-#endif /* SECURE_RPC */
-#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
- {
-#if defined(IPv6) && defined(AF_INET6)
- if ( (family == FamilyInternet) || (family == FamilyInternet6) ||
- (family == FamilyWild) )
- {
- struct addrinfo *addresses;
- struct addrinfo *a;
- int f;
-
- if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
- for (a = addresses ; a != NULL ; a = a->ai_next) {
- len = a->ai_addrlen;
- f = ConvertAddr(a->ai_addr,&len,(pointer *)&addr);
- if ( (family == f) ||
- ((family == FamilyWild) && (f != -1)) ) {
- NewHost(f, addr, len, FALSE);
- }
- }
- freeaddrinfo(addresses);
- }
- }
-#else
-#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
-#endif
- register struct hostent *hp;
-
- /* host name */
- if ((family == FamilyInternet &&
- ((hp = _XGethostbyname(hostname, hparams)) != 0)) ||
- ((hp = _XGethostbyname(hostname, hparams)) != 0))
- {
- saddr.sa.sa_family = hp->h_addrtype;
- len = sizeof(saddr.sa);
- if ((family = ConvertAddr (&saddr.sa, &len, (pointer *)&addr)) != -1)
- {
-#ifdef h_addr /* new 4.3bsd version of gethostent */
- char **list;
-
- /* iterate over the addresses */
- for (list = hp->h_addr_list; *list; list++)
- (void) NewHost (family, (pointer)*list, len, FALSE);
-#else
- (void) NewHost (family, (pointer)hp->h_addr, len, FALSE);
-#endif
- }
- }
-#endif /* IPv6 */
- }
-#endif /* TCPCONN || STREAMSCONN */
- family = FamilyWild;
- }
- fclose (fd);
- }
-}
-
-/* Is client on the local host */
-Bool LocalClient(ClientPtr client)
-{
- int alen, family, notused;
- Xtransaddr *from = NULL;
- pointer addr;
- register HOST *host;
-
- if (!_XSERVTransGetPeerAddr (((OsCommPtr)client->osPrivate)->trans_conn,
- &notused, &alen, &from))
- {
- family = ConvertAddr ((struct sockaddr *) from,
- &alen, (pointer *)&addr);
- if (family == -1)
- {
- xfree (from);
- return FALSE;
- }
- if (family == FamilyLocal)
- {
- xfree (from);
- return TRUE;
- }
- for (host = selfhosts; host; host = host->next)
- {
- if (addrEqual (family, addr, alen, host))
- return TRUE;
- }
- xfree (from);
- }
- return FALSE;
-}
-
-/*
- * Return the uid and gid of a connected local client
- *
- * Used by XShm to test access rights to shared memory segments
- */
-int
-LocalClientCred(ClientPtr client, int *pUid, int *pGid)
-{
- LocalClientCredRec *lcc;
- int ret = GetLocalClientCreds(client, &lcc);
-
- if (ret == 0) {
-#ifdef HAVE_GETZONEID /* only local if in the same zone */
- if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
-#endif
- if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL))
- *pUid = lcc->euid;
- if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL))
- *pGid = lcc->egid;
- FreeLocalClientCreds(lcc);
- }
- return ret;
-}
-
-/*
- * Return the uid and all gids of a connected local client
- * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds
- *
- * Used by localuser & localgroup ServerInterpreted access control forms below
- * Used by AuthAudit to log who local connections came from
- */
-int
-GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp)
-{
-#if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED)
- int fd;
- XtransConnInfo ci;
- LocalClientCredRec *lcc;
-#ifdef HAS_GETPEEREID
- uid_t uid;
- gid_t gid;
-#elif defined(HAS_GETPEERUCRED)
- ucred_t *peercred = NULL;
- const gid_t *gids;
-#elif defined(SO_PEERCRED)
- struct ucred peercred;
- socklen_t so_len = sizeof(peercred);
-#endif
-
- if (client == NULL)
- return -1;
- ci = ((OsCommPtr)client->osPrivate)->trans_conn;
-#if !(defined(sun) && defined(HAS_GETPEERUCRED))
- /* Most implementations can only determine peer credentials for Unix
- * domain sockets - Solaris getpeerucred can work with a bit more, so
- * we just let it tell us if the connection type is supported or not
- */
- if (!_XSERVTransIsLocal(ci)) {
- return -1;
- }
-#endif
-
- *lccp = Xcalloc(sizeof(LocalClientCredRec));
- if (*lccp == NULL)
- return -1;
- lcc = *lccp;
-
- fd = _XSERVTransGetConnectionNumber(ci);
-#ifdef HAS_GETPEEREID
- if (getpeereid(fd, &uid, &gid) == -1) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
- lcc->euid = uid;
- lcc->egid = gid;
- lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET;
- return 0;
-#elif defined(HAS_GETPEERUCRED)
- if (getpeerucred(fd, &peercred) < 0) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
- lcc->euid = ucred_geteuid(peercred);
- if (lcc->euid != -1)
- lcc->fieldsSet |= LCC_UID_SET;
- lcc->egid = ucred_getegid(peercred);
- if (lcc->egid != -1)
- lcc->fieldsSet |= LCC_GID_SET;
- lcc->pid = ucred_getpid(peercred);
- if (lcc->pid != -1)
- lcc->fieldsSet |= LCC_PID_SET;
-#ifdef HAVE_GETZONEID
- lcc->zoneid = ucred_getzoneid(peercred);
- if (lcc->zoneid != -1)
- lcc->fieldsSet |= LCC_ZID_SET;
-#endif
- lcc->nSuppGids = ucred_getgroups(peercred, &gids);
- if (lcc->nSuppGids > 0) {
- lcc->pSuppGids = Xcalloc((lcc->nSuppGids) * sizeof(int));
- if (lcc->pSuppGids == NULL) {
- lcc->nSuppGids = 0;
- } else {
- int i;
- for (i = 0 ; i < lcc->nSuppGids; i++) {
- (lcc->pSuppGids)[i] = (int) gids[i];
- }
- }
- } else {
- lcc->nSuppGids = 0;
- }
- ucred_free(peercred);
- return 0;
-#elif defined(SO_PEERCRED)
- if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) {
- FreeLocalClientCreds(lcc);
- return -1;
- }
- lcc->euid = peercred.uid;
- lcc->egid = peercred.gid;
- lcc->pid = peercred.pid;
- lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET;
- return 0;
-#endif
-#else
- /* No system call available to get the credentials of the peer */
-#define NO_LOCAL_CLIENT_CRED
- return -1;
-#endif
-}
-
-void
-FreeLocalClientCreds(LocalClientCredRec *lcc)
-{
- if (lcc != NULL) {
- if (lcc->nSuppGids > 0) {
- Xfree(lcc->pSuppGids);
- }
- Xfree(lcc);
- }
-}
-
-static int
-AuthorizedClient(ClientPtr client)
-{
- int rc;
-
- if (!client || defeatAccessControl)
- return Success;
-
- /* untrusted clients can't change host access */
- rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
- if (rc != Success)
- return rc;
-
- return LocalClient(client) ? Success : BadAccess;
-}
-
-/* Add a host to the access control list. This is the external interface
- * called from the dispatcher */
-
-int
-AddHost (ClientPtr client,
- int family,
- unsigned length, /* of bytes in pAddr */
- pointer pAddr)
-{
- int rc, len;
-
- rc = AuthorizedClient(client);
- if (rc != Success)
- return rc;
- switch (family) {
- case FamilyLocalHost:
- len = length;
- LocalHostEnabled = TRUE;
- break;
-#ifdef SECURE_RPC
- case FamilyNetname:
- len = length;
- SecureRPCInit ();
- break;
-#endif
- case FamilyInternet:
-#if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
-#endif
- case FamilyDECnet:
- case FamilyChaos:
- case FamilyServerInterpreted:
- if ((len = CheckAddr (family, pAddr, length)) < 0)
- {
- client->errorValue = length;
- return (BadValue);
- }
- break;
- case FamilyLocal:
- default:
- client->errorValue = family;
- return (BadValue);
- }
- if (NewHost (family, pAddr, len, FALSE))
- return Success;
- return BadAlloc;
-}
-
-Bool
-ForEachHostInFamily (int family,
- Bool (*func)(
- unsigned char * /* addr */,
- short /* len */,
- pointer /* closure */),
- pointer closure)
-{
- HOST *host;
-
- for (host = validhosts; host; host = host->next)
- if (family == host->family && func (host->addr, host->len, closure))
- return TRUE;
- return FALSE;
-}
-
-/* Add a host to the access control list. This is the internal interface
- * called when starting or resetting the server */
-static Bool
-NewHost (int family,
- pointer addr,
- int len,
- int addingLocalHosts)
-{
- register HOST *host;
-
- for (host = validhosts; host; host = host->next)
- {
- if (addrEqual (family, addr, len, host))
- return TRUE;
- }
- if (!addingLocalHosts) { /* Fix for XFree86 bug #156 */
- for (host = selfhosts; host; host = host->next) {
- if (addrEqual (family, addr, len, host)) {
- host->requested = TRUE;
- break;
- }
- }
- }
- MakeHost(host,len)
- if (!host)
- return FALSE;
- host->family = family;
- host->len = len;
- acopy(addr, host->addr, len);
- host->next = validhosts;
- validhosts = host;
- return TRUE;
-}
-
-/* Remove a host from the access control list */
-
-int
-RemoveHost (
- ClientPtr client,
- int family,
- unsigned length, /* of bytes in pAddr */
- pointer pAddr)
-{
- int rc, len;
- register HOST *host, **prev;
-
- rc = AuthorizedClient(client);
- if (rc != Success)
- return rc;
- switch (family) {
- case FamilyLocalHost:
- len = length;
- LocalHostEnabled = FALSE;
- break;
-#ifdef SECURE_RPC
- case FamilyNetname:
- len = length;
- break;
-#endif
- case FamilyInternet:
-#if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
-#endif
- case FamilyDECnet:
- case FamilyChaos:
- case FamilyServerInterpreted:
- if ((len = CheckAddr (family, pAddr, length)) < 0)
- {
- client->errorValue = length;
- return(BadValue);
- }
- break;
- case FamilyLocal:
- default:
- client->errorValue = family;
- return(BadValue);
- }
- for (prev = &validhosts;
- (host = *prev) && (!addrEqual (family, pAddr, len, host));
- prev = &host->next)
- ;
- if (host)
- {
- *prev = host->next;
- FreeHost (host);
- }
- return (Success);
-}
-
-/* Get all hosts in the access control list */
-int
-GetHosts (
- pointer *data,
- int *pnHosts,
- int *pLen,
- BOOL *pEnabled)
-{
- int len;
- register int n = 0;
- register unsigned char *ptr;
- register HOST *host;
- int nHosts = 0;
-
- *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
- for (host = validhosts; host; host = host->next)
- {
- nHosts++;
- n += pad_to_int32(host->len) + sizeof(xHostEntry);
- }
- if (n)
- {
- *data = ptr = xalloc (n);
- if (!ptr)
- {
- return(BadAlloc);
- }
- for (host = validhosts; host; host = host->next)
- {
- len = host->len;
- ((xHostEntry *)ptr)->family = host->family;
- ((xHostEntry *)ptr)->length = len;
- ptr += sizeof(xHostEntry);
- acopy (host->addr, ptr, len);
- ptr += pad_to_int32(len);
- }
- } else {
- *data = NULL;
- }
- *pnHosts = nHosts;
- *pLen = n;
- return(Success);
-}
-
-/* Check for valid address family and length, and return address length. */
-
-/*ARGSUSED*/
-static int
-CheckAddr (
- int family,
- pointer pAddr,
- unsigned length)
-{
- int len;
-
- switch (family)
- {
-#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
- case FamilyInternet:
- if (length == sizeof (struct in_addr))
- len = length;
- else
- len = -1;
- break;
-#if defined(IPv6) && defined(AF_INET6)
- case FamilyInternet6:
- if (length == sizeof (struct in6_addr))
- len = length;
- else
- len = -1;
- break;
-#endif
-#endif
-#ifdef DNETCONN
- case FamilyDECnet:
- {
- struct dn_naddr *dnaddr = (struct dn_naddr *) pAddr;
-
- if ((length < sizeof(dnaddr->a_len)) ||
- (length < dnaddr->a_len + sizeof(dnaddr->a_len)))
- len = -1;
- else
- len = dnaddr->a_len + sizeof(dnaddr->a_len);
- if (len > sizeof(struct dn_naddr))
- len = -1;
- }
- break;
-#endif
- case FamilyServerInterpreted:
- len = siCheckAddr(pAddr, length);
- break;
- default:
- len = -1;
- }
- return (len);
-}
-
-/* Check if a host is not in the access control list.
- * Returns 1 if host is invalid, 0 if we've found it. */
-
-int
-InvalidHost (
- register struct sockaddr *saddr,
- int len,
- ClientPtr client)
-{
- int family;
- pointer addr;
- register HOST *selfhost, *host;
-
- if (!AccessEnabled) /* just let them in */
- return(0);
- family = ConvertAddr (saddr, &len, (pointer *)&addr);
- if (family == -1)
- return 1;
- if (family == FamilyLocal)
- {
- if (!LocalHostEnabled)
- {
- /*
- * check to see if any local address is enabled. This
- * implicitly enables local connections.
- */
- for (selfhost = selfhosts; selfhost; selfhost=selfhost->next)
- {
- for (host = validhosts; host; host=host->next)
- {
- if (addrEqual (selfhost->family, selfhost->addr,
- selfhost->len, host))
- return 0;
- }
- }
- } else
- return 0;
- }
- for (host = validhosts; host; host = host->next)
- {
- if ((host->family == FamilyServerInterpreted)) {
- if (siAddrMatch (family, addr, len, host, client)) {
- return (0);
- }
- } else {
- if (addrEqual (family, addr, len, host))
- return (0);
- }
-
- }
- return (1);
-}
-
-static int
-ConvertAddr (
- register struct sockaddr *saddr,
- int *len,
- pointer *addr)
-{
- if (*len == 0)
- return (FamilyLocal);
- switch (saddr->sa_family)
- {
- case AF_UNSPEC:
-#if defined(UNIXCONN) || defined(LOCALCONN)
- case AF_UNIX:
-#endif
- return FamilyLocal;
-#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
- case AF_INET:
-#ifdef WIN32
- if (16777343 == *(long*)&((struct sockaddr_in *) saddr)->sin_addr)
- return FamilyLocal;
-#endif
- *len = sizeof (struct in_addr);
- *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr);
- return FamilyInternet;
-#if defined(IPv6) && defined(AF_INET6)
- case AF_INET6:
- {
- struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
- if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) {
- *len = sizeof (struct in_addr);
- *addr = (pointer) &(saddr6->sin6_addr.s6_addr[12]);
- return FamilyInternet;
- } else {
- *len = sizeof (struct in6_addr);
- *addr = (pointer) &(saddr6->sin6_addr);
- return FamilyInternet6;
- }
- }
-#endif
-#endif
-#ifdef DNETCONN
- case AF_DECnet:
- {
- struct sockaddr_dn *sdn = (struct sockaddr_dn *) saddr;
- *len = sdn->sdn_nodeaddrl + sizeof(sdn->sdn_nodeaddrl);
- *addr = (pointer) &(sdn->sdn_add);
- }
- return FamilyDECnet;
-#endif
-#ifdef CHAOSCONN
- case AF_CHAOS:
- {
- not implemented
- }
- return FamilyChaos;
-#endif
- default:
- return -1;
- }
-}
-
-int
-ChangeAccessControl(
- ClientPtr client,
- int fEnabled)
-{
- int rc = AuthorizedClient(client);
- if (rc != Success)
- return rc;
- AccessEnabled = fEnabled;
- return Success;
-}
-
-/* returns FALSE if xhost + in effect, else TRUE */
-int
-GetAccessControl(void)
-{
- return AccessEnabled;
-}
-
-/*****************************************************************************
- * FamilyServerInterpreted host entry implementation
- *
- * Supports an extensible system of host types which the server can interpret
- * See the IPv6 extensions to the X11 protocol spec for the definition.
- *
- * Currently supported schemes:
- *
- * hostname - hostname as defined in IETF RFC 2396
- * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD>
- *
- * See xc/doc/specs/SIAddresses for formal definitions of each type.
- */
-
-/* These definitions and the siTypeAdd function could be exported in the
- * future to enable loading additional host types, but that was not done for
- * the initial implementation.
- */
-typedef Bool (*siAddrMatchFunc)(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *siTypePriv);
-typedef int (*siCheckAddrFunc)(const char *addrString, int length,
- void *siTypePriv);
-
-struct siType {
- struct siType * next;
- const char * typeName;
- siAddrMatchFunc addrMatch;
- siCheckAddrFunc checkAddr;
- void * typePriv; /* Private data for type routines */
-};
-
-static struct siType *siTypeList;
-
-static int
-siTypeAdd(const char *typeName, siAddrMatchFunc addrMatch,
- siCheckAddrFunc checkAddr, void *typePriv)
-{
- struct siType *s, *p;
-
- if ((typeName == NULL) || (addrMatch == NULL) || (checkAddr == NULL))
- return BadValue;
-
- for (s = siTypeList, p = NULL; s != NULL ; p = s, s = s->next) {
- if (strcmp(typeName, s->typeName) == 0) {
- s->addrMatch = addrMatch;
- s->checkAddr = checkAddr;
- s->typePriv = typePriv;
- return Success;
- }
- }
-
- s = xalloc(sizeof(struct siType));
- if (s == NULL)
- return BadAlloc;
-
- if (p == NULL)
- siTypeList = s;
- else
- p->next = s;
-
- s->next = NULL;
- s->typeName = typeName;
- s->addrMatch = addrMatch;
- s->checkAddr = checkAddr;
- s->typePriv = typePriv;
- return Success;
-}
-
-/* Checks to see if a host matches a server-interpreted host entry */
-static Bool
-siAddrMatch(int family, pointer addr, int len, HOST *host, ClientPtr client)
-{
- Bool matches = FALSE;
- struct siType *s;
- const char *valueString;
- int addrlen;
-
- valueString = (const char *) memchr(host->addr, '\0', host->len);
- if (valueString != NULL) {
- for (s = siTypeList; s != NULL ; s = s->next) {
- if (strcmp((char *) host->addr, s->typeName) == 0) {
- addrlen = host->len - (strlen((char *)host->addr) + 1);
- matches = s->addrMatch(family, addr, len,
- valueString + 1, addrlen, client, s->typePriv);
- break;
- }
- }
-#ifdef FAMILY_SI_DEBUG
- ErrorF(
- "Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n",
- host->addr, addrlen, addrlen, valueString + 1,
- (matches) ? "accepted" : "rejected");
-#endif
- }
- return matches;
-}
-
-static int
-siCheckAddr(const char *addrString, int length)
-{
- const char *valueString;
- int addrlen, typelen;
- int len = -1;
- struct siType *s;
-
- /* Make sure there is a \0 byte inside the specified length
- to separate the address type from the address value. */
- valueString = (const char *) memchr(addrString, '\0', length);
- if (valueString != NULL) {
- /* Make sure the first string is a recognized address type,
- * and the second string is a valid address of that type.
- */
- typelen = strlen(addrString) + 1;
- addrlen = length - typelen;
-
- for (s = siTypeList; s != NULL ; s = s->next) {
- if (strcmp(addrString, s->typeName) == 0) {
- len = s->checkAddr(valueString + 1, addrlen, s->typePriv);
- if (len >= 0) {
- len += typelen;
- }
- break;
- }
- }
-#ifdef FAMILY_SI_DEBUG
- {
- const char *resultMsg;
-
- if (s == NULL) {
- resultMsg = "type not registered";
- } else {
- if (len == -1)
- resultMsg = "rejected";
- else
- resultMsg = "accepted";
- }
-
- ErrorF("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n",
- addrString, addrlen, addrlen, valueString + 1, len, resultMsg);
- }
-#endif
- }
- return len;
-}
-
-
-/***
- * Hostname server-interpreted host type
- *
- * Stored as hostname string, explicitly defined to be resolved ONLY
- * at access check time, to allow for hosts with dynamic addresses
- * but static hostnames, such as found in some DHCP & mobile setups.
- *
- * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as:
- * hostname = *( domainlabel "." ) toplabel [ "." ]
- * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
- * toplabel = alpha | alpha *( alphanum | "-" ) alphanum
- */
-
-#ifdef NI_MAXHOST
-# define SI_HOSTNAME_MAXLEN NI_MAXHOST
-#else
-# ifdef MAXHOSTNAMELEN
-# define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN
-# else
-# define SI_HOSTNAME_MAXLEN 256
-# endif
-#endif
-
-static Bool
-siHostnameAddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrLen, ClientPtr client, void *typePriv)
-{
- Bool res = FALSE;
-
-/* Currently only supports checking against IPv4 & IPv6 connections, but
- * support for other address families, such as DECnet, could be added if
- * desired.
- */
-#if defined(IPv6) && defined(AF_INET6)
- if ((family == FamilyInternet) || (family == FamilyInternet6)) {
- char hostname[SI_HOSTNAME_MAXLEN];
- struct addrinfo *addresses;
- struct addrinfo *a;
- int f, hostaddrlen;
- pointer hostaddr;
-
- if (siAddrLen >= sizeof(hostname))
- return FALSE;
-
- strncpy(hostname, siAddr, siAddrLen);
- hostname[siAddrLen] = '\0';
-
- if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
- for (a = addresses ; a != NULL ; a = a->ai_next) {
- hostaddrlen = a->ai_addrlen;
- f = ConvertAddr(a->ai_addr,&hostaddrlen,&hostaddr);
- if ((f == family) && (len == hostaddrlen) &&
- (acmp (addr, hostaddr, len) == 0) ) {
- res = TRUE;
- break;
- }
- }
- freeaddrinfo(addresses);
- }
- }
-#else /* IPv6 not supported, use gethostbyname instead for IPv4 */
- if (family == FamilyInternet) {
- register struct hostent *hp;
-#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
-#endif
- char hostname[SI_HOSTNAME_MAXLEN];
- int f, hostaddrlen;
- pointer hostaddr;
- const char **addrlist;
-
- if (siAddrLen >= sizeof(hostname))
- return FALSE;
-
- strncpy(hostname, siAddr, siAddrLen);
- hostname[siAddrLen] = '\0';
-
- if ((hp = _XGethostbyname(hostname, hparams)) != NULL) {
-#ifdef h_addr /* new 4.3bsd version of gethostent */
- /* iterate over the addresses */
- for (addrlist = hp->h_addr_list; *addrlist; addrlist++)
-#else
- addrlist = &hp->h_addr;
-#endif
- {
- struct sockaddr_in sin;
-
- sin.sin_family = hp->h_addrtype;
- acopy ( *addrlist, &(sin.sin_addr), hp->h_length);
- hostaddrlen = sizeof(sin);
- f = ConvertAddr ((struct sockaddr *)&sin,
- &hostaddrlen, &hostaddr);
- if ((f == family) && (len == hostaddrlen) &&
- (acmp (addr, hostaddr, len) == 0) ) {
- res = TRUE;
- break;
- }
- }
- }
- }
-#endif
- return res;
-}
-
-
-static int
-siHostnameCheckAddr(const char *valueString, int length, void *typePriv)
-{
- /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition.
- * We do not use ctype functions here to avoid locale-specific
- * character sets. Hostnames must be pure ASCII.
- */
- int len = length;
- int i;
- Bool dotAllowed = FALSE;
- Bool dashAllowed = FALSE;
-
- if ((length <= 0) || (length >= SI_HOSTNAME_MAXLEN)) {
- len = -1;
- } else {
- for (i = 0; i < length; i++) {
- char c = valueString[i];
-
- if (c == 0x2E) { /* '.' */
- if (dotAllowed == FALSE) {
- len = -1;
- break;
- } else {
- dotAllowed = FALSE;
- dashAllowed = FALSE;
- }
- } else if (c == 0x2D) { /* '-' */
- if (dashAllowed == FALSE) {
- len = -1;
- break;
- } else {
- dotAllowed = FALSE;
- }
- } else if (((c >= 0x30) && (c <= 0x3A)) /* 0-9 */ ||
- ((c >= 0x61) && (c <= 0x7A)) /* a-z */ ||
- ((c >= 0x41) && (c <= 0x5A)) /* A-Z */) {
- dotAllowed = TRUE;
- dashAllowed = TRUE;
- } else { /* Invalid character */
- len = -1;
- break;
- }
- }
- }
- return len;
-}
-
-#if defined(IPv6) && defined(AF_INET6)
-/***
- * "ipv6" server interpreted type
- *
- * Currently supports only IPv6 literal address as specified in IETF RFC 3513
- *
- * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be
- * added for the scoped address format it specifies.
- */
-
-/* Maximum length of an IPv6 address string - increase when adding support
- * for scoped address qualifiers. Includes room for trailing NUL byte.
- */
-#define SI_IPv6_MAXLEN INET6_ADDRSTRLEN
-
-static Bool
-siIPv6AddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
-{
- struct in6_addr addr6;
- char addrbuf[SI_IPv6_MAXLEN];
-
- if ((family != FamilyInternet6) || (len != sizeof(addr6)))
- return FALSE;
-
- memcpy(addrbuf, siAddr, siAddrlen);
- addrbuf[siAddrlen] = '\0';
-
- if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
- perror("inet_pton");
- return FALSE;
- }
-
- if (memcmp(addr, &addr6, len) == 0) {
- return TRUE;
- } else {
- return FALSE;
- }
-}
-
-static int
-siIPv6CheckAddr(const char *addrString, int length, void *typePriv)
-{
- int len;
-
- /* Minimum length is 3 (smallest legal address is "::1") */
- if (length < 3) {
- /* Address is too short! */
- len = -1;
- } else if (length >= SI_IPv6_MAXLEN) {
- /* Address is too long! */
- len = -1;
- } else {
- /* Assume inet_pton is sufficient validation */
- struct in6_addr addr6;
- char addrbuf[SI_IPv6_MAXLEN];
-
- memcpy(addrbuf, addrString, length);
- addrbuf[length] = '\0';
-
- if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
- perror("inet_pton");
- len = -1;
- } else {
- len = length;
- }
- }
- return len;
-}
-#endif /* IPv6 */
-
-#if !defined(NO_LOCAL_CLIENT_CRED)
-/***
- * "localuser" & "localgroup" server interpreted types
- *
- * Allows local connections from a given local user or group
- */
-
-#include <pwd.h>
-#include <grp.h>
-
-#define LOCAL_USER 1
-#define LOCAL_GROUP 2
-
-typedef struct {
- int credType;
-} siLocalCredPrivRec, *siLocalCredPrivPtr;
-
-static siLocalCredPrivRec siLocalUserPriv = { LOCAL_USER };
-static siLocalCredPrivRec siLocalGroupPriv = { LOCAL_GROUP };
-
-static Bool
-siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id)
-{
- Bool parsedOK = FALSE;
- char *addrbuf = xalloc(len + 1);
-
- if (addrbuf == NULL) {
- return FALSE;
- }
-
- memcpy(addrbuf, addr, len);
- addrbuf[len] = '\0';
-
- if (addr[0] == '#') { /* numeric id */
- char *cp;
- errno = 0;
- *id = strtol(addrbuf + 1, &cp, 0);
- if ((errno == 0) && (cp != (addrbuf+1))) {
- parsedOK = TRUE;
- }
- } else { /* non-numeric name */
- if (lcPriv->credType == LOCAL_USER) {
- struct passwd *pw = getpwnam(addrbuf);
-
- if (pw != NULL) {
- *id = (int) pw->pw_uid;
- parsedOK = TRUE;
- }
- } else { /* group */
- struct group *gr = getgrnam(addrbuf);
-
- if (gr != NULL) {
- *id = (int) gr->gr_gid;
- parsedOK = TRUE;
- }
- }
- }
-
- xfree(addrbuf);
- return parsedOK;
-}
-
-static Bool
-siLocalCredAddrMatch(int family, pointer addr, int len,
- const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
-{
- int siAddrId;
- LocalClientCredRec *lcc;
- siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv;
-
- if (GetLocalClientCreds(client, &lcc) == -1) {
- return FALSE;
- }
-
-#ifdef HAVE_GETZONEID /* Ensure process is in the same zone */
- if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
- FreeLocalClientCreds(lcc);
- return FALSE;
- }
-#endif
-
- if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) {
- FreeLocalClientCreds(lcc);
- return FALSE;
- }
-
- if (lcPriv->credType == LOCAL_USER) {
- if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) {
- FreeLocalClientCreds(lcc);
- return TRUE;
- }
- } else {
- if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) {
- FreeLocalClientCreds(lcc);
- return TRUE;
- }
- if (lcc->pSuppGids != NULL) {
- int i;
-
- for (i = 0 ; i < lcc->nSuppGids; i++) {
- if (lcc->pSuppGids[i] == siAddrId) {
- FreeLocalClientCreds(lcc);
- return TRUE;
- }
- }
- }
- }
- FreeLocalClientCreds(lcc);
- return FALSE;
-}
-
-static int
-siLocalCredCheckAddr(const char *addrString, int length, void *typePriv)
-{
- int len = length;
- int id;
-
- if (siLocalCredGetId(addrString, length,
- (siLocalCredPrivPtr)typePriv, &id) == FALSE) {
- len = -1;
- }
- return len;
-}
-#endif /* localuser */
-
-static void
-siTypesInitialize(void)
-{
- siTypeAdd("hostname", siHostnameAddrMatch, siHostnameCheckAddr, NULL);
-#if defined(IPv6) && defined(AF_INET6)
- siTypeAdd("ipv6", siIPv6AddrMatch, siIPv6CheckAddr, NULL);
-#endif
-#if !defined(NO_LOCAL_CLIENT_CRED)
- siTypeAdd("localuser", siLocalCredAddrMatch, siLocalCredCheckAddr,
- &siLocalUserPriv);
- siTypeAdd("localgroup", siLocalCredAddrMatch, siLocalCredCheckAddr,
- &siLocalGroupPriv);
-#endif
-}
+/***********************************************************
+
+Copyright 1987, 1998 The Open Group
+
+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.
+
+X Window System is a trademark of 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.
+
+******************************************************************/
+
+/*
+ * Copyright © 2004 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, 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.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+#include <X11/Xauth.h>
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "site.h"
+#include <errno.h>
+#include <sys/types.h>
+#ifndef WIN32
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <ctype.h>
+
+#if defined(TCPCONN) || defined(STREAMSCONN) || defined(__SCO__)
+#include <netinet/in.h>
+#endif /* TCPCONN || STREAMSCONN || ISC || __SCO__ */
+#ifdef DNETCONN
+#include <netdnet/dn.h>
+#include <netdnet/dnetdb.h>
+#endif
+
+#ifdef HAS_GETPEERUCRED
+# include <ucred.h>
+# ifdef sun
+# include <zone.h>
+# endif
+#endif
+
+#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__)
+# include <sys/utsname.h>
+#endif
+#if defined(SYSV) && defined(__i386__)
+# include <sys/stream.h>
+#endif
+#ifdef __GNU__
+#undef SIOCGIFCONF
+#include <netdb.h>
+#else /*!__GNU__*/
+# include <net/if.h>
+#endif /*__GNU__ */
+
+#ifdef SVR4
+#include <sys/sockio.h>
+#include <sys/stropts.h>
+#endif
+
+#include <netdb.h>
+
+#ifdef CSRG_BASED
+#include <sys/param.h>
+#if (BSD >= 199103)
+#define VARIABLE_IFREQ
+#endif
+#endif
+
+#ifdef BSD44SOCKETS
+#ifndef VARIABLE_IFREQ
+#define VARIABLE_IFREQ
+#endif
+#endif
+
+#ifdef HAS_GETIFADDRS
+#include <ifaddrs.h>
+#endif
+
+/* Solaris provides an extended interface SIOCGLIFCONF. Other systems
+ * may have this as well, but the code has only been tested on Solaris
+ * so far, so we only enable it there. Other platforms may be added as
+ * needed.
+ *
+ * Test for Solaris commented out -- TSI @ UQV 2003.06.13
+ */
+#ifdef SIOCGLIFCONF
+/* #if defined(sun) */
+#define USE_SIOCGLIFCONF
+/* #endif */
+#endif
+
+#endif /* WIN32 */
+
+#ifndef PATH_MAX
+#include <sys/param.h>
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+#endif
+
+#ifdef __SCO__
+/* The system defined value is wrong. MAXPATHLEN is set in sco5.cf. */
+#undef PATH_MAX
+#endif
+
+#define X_INCLUDE_NETDB_H
+#include <X11/Xos_r.h>
+
+#include "dixstruct.h"
+#include "osdep.h"
+
+#include "xace.h"
+
+#ifndef PATH_MAX
+#ifdef MAXPATHLEN
+#define PATH_MAX MAXPATHLEN
+#else
+#define PATH_MAX 1024
+#endif
+#endif
+
+Bool defeatAccessControl = FALSE;
+
+#define acmp(a1, a2, len) memcmp((char *)(a1), (char *)(a2), len)
+#define acopy(a1, a2, len) memmove((char *)(a2), (char *)(a1), len)
+#define addrEqual(fam, address, length, host) \
+ ((fam) == (host)->family &&\
+ (length) == (host)->len &&\
+ !acmp (address, (host)->addr, length))
+
+static int ConvertAddr(struct sockaddr * /*saddr*/,
+ int * /*len*/,
+ pointer * /*addr*/);
+
+static int CheckAddr(int /*family*/,
+ const void * /*pAddr*/,
+ unsigned /*length*/);
+
+static Bool NewHost(int /*family*/,
+ const void * /*addr*/,
+ int /*len*/,
+ int /* addingLocalHosts */);
+
+/* XFree86 bug #156: To keep track of which hosts were explicitly requested in
+ /etc/X<display>.hosts, we've added a requested field to the HOST struct,
+ and a LocalHostRequested variable. These default to FALSE, but are set
+ to TRUE in ResetHosts when reading in /etc/X<display>.hosts. They are
+ checked in DisableLocalHost(), which is called to disable the default
+ local host entries when stronger authentication is turned on. */
+
+typedef struct _host {
+ short family;
+ short len;
+ unsigned char *addr;
+ struct _host *next;
+ int requested;
+} HOST;
+
+#define MakeHost(h,l) (h)=xalloc(sizeof *(h)+(l));\
+ if (h) { \
+ (h)->addr=(unsigned char *) ((h) + 1);\
+ (h)->requested = FALSE; \
+ }
+#define FreeHost(h) xfree(h)
+static HOST *selfhosts = NULL;
+static HOST *validhosts = NULL;
+static int AccessEnabled = DEFAULT_ACCESS_CONTROL;
+static int LocalHostEnabled = FALSE;
+static int LocalHostRequested = FALSE;
+static int UsingXdmcp = FALSE;
+
+/* FamilyServerInterpreted implementation */
+static Bool siAddrMatch(int family, pointer addr, int len, HOST *host,
+ ClientPtr client);
+static int siCheckAddr(const char *addrString, int length);
+static void siTypesInitialize(void);
+
+/*
+ * called when authorization is not enabled to add the
+ * local host to the access list
+ */
+
+void
+EnableLocalHost (void)
+{
+ if (!UsingXdmcp)
+ {
+ LocalHostEnabled = TRUE;
+ AddLocalHosts ();
+ }
+}
+
+/*
+ * called when authorization is enabled to keep us secure
+ */
+void
+DisableLocalHost (void)
+{
+ HOST *self;
+
+ if (!LocalHostRequested) /* Fix for XFree86 bug #156 */
+ LocalHostEnabled = FALSE;
+ for (self = selfhosts; self; self = self->next) {
+ if (!self->requested) /* Fix for XFree86 bug #156 */
+ (void) RemoveHost ((ClientPtr)NULL, self->family, self->len, (pointer)self->addr);
+ }
+}
+
+/*
+ * called at init time when XDMCP will be used; xdmcp always
+ * adds local hosts manually when needed
+ */
+
+void
+AccessUsingXdmcp (void)
+{
+ UsingXdmcp = TRUE;
+ LocalHostEnabled = FALSE;
+}
+
+
+#if defined(SVR4) && !defined(SCO325) && !defined(sun) && defined(SIOCGIFCONF) && !defined(USE_SIOCGLIFCONF)
+
+/* Deal with different SIOCGIFCONF ioctl semantics on these OSs */
+
+static int
+ifioctl (int fd, int cmd, char *arg)
+{
+ struct strioctl ioc;
+ int ret;
+
+ bzero((char *) &ioc, sizeof(ioc));
+ ioc.ic_cmd = cmd;
+ ioc.ic_timout = 0;
+ if (cmd == SIOCGIFCONF)
+ {
+ ioc.ic_len = ((struct ifconf *) arg)->ifc_len;
+ ioc.ic_dp = ((struct ifconf *) arg)->ifc_buf;
+ }
+ else
+ {
+ ioc.ic_len = sizeof(struct ifreq);
+ ioc.ic_dp = arg;
+ }
+ ret = ioctl(fd, I_STR, (char *) &ioc);
+ if (ret >= 0 && cmd == SIOCGIFCONF)
+#ifdef SVR4
+ ((struct ifconf *) arg)->ifc_len = ioc.ic_len;
+#endif
+ return(ret);
+}
+#else /* Case sun, SCO325 and others */
+#define ifioctl ioctl
+#endif /* ((SVR4 && !sun !SCO325) || ISC) && SIOCGIFCONF */
+
+/*
+ * DefineSelf (fd):
+ *
+ * Define this host for access control. Find all the hosts the OS knows about
+ * for this fd and add them to the selfhosts list.
+ */
+
+#if !defined(SIOCGIFCONF)
+void
+DefineSelf (int fd)
+{
+#if !defined(TCPCONN) && !defined(STREAMSCONN) && !defined(UNIXCONN) && !defined(MNX_TCPCONN)
+ return;
+#else
+ register int n;
+ int len;
+ caddr_t addr;
+ int family;
+ register HOST *host;
+
+#ifndef WIN32
+ struct utsname name;
+#else
+ struct {
+ char nodename[512];
+ } name;
+#endif
+
+ register struct hostent *hp;
+
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_in6 in6;
+#endif
+ } saddr;
+
+ struct sockaddr_in *inetaddr;
+ struct sockaddr_in6 *inet6addr;
+ struct sockaddr_in broad_addr;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+
+ /* Why not use gethostname()? Well, at least on my system, I've had to
+ * make an ugly kernel patch to get a name longer than 8 characters, and
+ * uname() lets me access to the whole string (it smashes release, you
+ * see), whereas gethostname() kindly truncates it for me.
+ */
+#ifndef WIN32
+ uname(&name);
+#else
+ gethostname(name.nodename, sizeof(name.nodename));
+#endif
+
+ hp = _XGethostbyname(name.nodename, hparams);
+ if (hp != NULL)
+ {
+ saddr.sa.sa_family = hp->h_addrtype;
+ switch (hp->h_addrtype) {
+ case AF_INET:
+ inetaddr = (struct sockaddr_in *) (&(saddr.sa));
+ acopy ( hp->h_addr, &(inetaddr->sin_addr), hp->h_length);
+ len = sizeof(saddr.sa);
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ inet6addr = (struct sockaddr_in6 *) (&(saddr.sa));
+ acopy ( hp->h_addr, &(inet6addr->sin6_addr), hp->h_length);
+ len = sizeof(saddr.in6);
+ break;
+#endif
+ default:
+ goto DefineLocalHost;
+ }
+ family = ConvertAddr ( &(saddr.sa), &len, (pointer *)&addr);
+ if ( family != -1 && family != FamilyLocal )
+ {
+ for (host = selfhosts;
+ host && !addrEqual (family, addr, len, host);
+ host = host->next) ;
+ if (!host)
+ {
+ /* add this host to the host list. */
+ MakeHost(host,len)
+ if (host)
+ {
+ host->family = family;
+ host->len = len;
+ acopy ( addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ /*
+ * If this is an Internet Address, but not the localhost
+ * address (127.0.0.1), nor the bogus address (0.0.0.0),
+ * register it.
+ */
+ if (family == FamilyInternet &&
+ !(len == 4 &&
+ ((addr[0] == 127) ||
+ (addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)))
+ )
+ {
+ XdmcpRegisterConnection (family, (char *)addr, len);
+ broad_addr = *inetaddr;
+ ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
+ htonl (INADDR_BROADCAST);
+ XdmcpRegisterBroadcastAddress ((struct sockaddr_in *)
+ &broad_addr);
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ !(IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr)))
+ {
+ XdmcpRegisterConnection (family, (char *)addr, len);
+ }
+#endif
+
+#endif /* XDMCP */
+ }
+ }
+ }
+ /*
+ * now add a host of family FamilyLocalHost...
+ */
+DefineLocalHost:
+ for (host = selfhosts;
+ host && !addrEqual(FamilyLocalHost, "", 0, host);
+ host = host->next);
+ if (!host)
+ {
+ MakeHost(host, 0);
+ if (host)
+ {
+ host->family = FamilyLocalHost;
+ host->len = 0;
+ acopy("", host->addr, 0);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ }
+#endif /* !TCPCONN && !STREAMSCONN && !UNIXCONN && !MNX_TCPCONN */
+}
+
+#else
+
+#ifdef USE_SIOCGLIFCONF
+#define ifr_type struct lifreq
+#else
+#define ifr_type struct ifreq
+#endif
+
+#ifdef VARIABLE_IFREQ
+#define ifr_size(p) (sizeof (struct ifreq) + \
+ (p->ifr_addr.sa_len > sizeof (p->ifr_addr) ? \
+ p->ifr_addr.sa_len - sizeof (p->ifr_addr) : 0))
+#define ifraddr_size(a) (a.sa_len)
+#else
+#define ifr_size(p) (sizeof (ifr_type))
+#define ifraddr_size(a) (sizeof (a))
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+#include <arpa/inet.h>
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+static void
+in6_fillscopeid(struct sockaddr_in6 *sin6)
+{
+#if defined(__KAME__)
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ sin6->sin6_scope_id =
+ ntohs(*(u_int16_t *)&sin6->sin6_addr.s6_addr[2]);
+ sin6->sin6_addr.s6_addr[2] = sin6->sin6_addr.s6_addr[3] = 0;
+ }
+#endif
+}
+#endif
+
+void
+DefineSelf (int fd)
+{
+#ifndef HAS_GETIFADDRS
+ char *cp, *cplim;
+# ifdef USE_SIOCGLIFCONF
+ struct sockaddr_storage buf[16];
+ struct lifconf ifc;
+ register struct lifreq *ifr;
+# ifdef SIOCGLIFNUM
+ struct lifnum ifn;
+# endif
+# else /* !USE_SIOCGLIFCONF */
+ char buf[2048];
+ struct ifconf ifc;
+ register struct ifreq *ifr;
+# endif
+ void * bufptr = buf;
+#else /* HAS_GETIFADDRS */
+ struct ifaddrs * ifap, *ifr;
+#endif
+ int len;
+ unsigned char * addr;
+ int family;
+ register HOST *host;
+
+#ifdef DNETCONN
+ struct dn_naddr *dnaddr = getnodeadd();
+ /*
+ * AF_DECnet may not be listed in the interface list. Instead use
+ * the supported library call to find out the local address (if any).
+ */
+ if (dnaddr)
+ {
+ addr = (unsigned char *) dnaddr;
+ len = dnaddr->a_len + sizeof(dnaddr->a_len);
+ family = FamilyDECnet;
+ for (host = selfhosts;
+ host && !addrEqual (family, addr, len, host);
+ host = host->next)
+ ;
+ if (!host)
+ {
+ MakeHost(host,len)
+ if (host)
+ {
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ }
+ }
+#endif /* DNETCONN */
+#ifndef HAS_GETIFADDRS
+
+ len = sizeof(buf);
+
+#ifdef USE_SIOCGLIFCONF
+
+#ifdef SIOCGLIFNUM
+ ifn.lifn_family = AF_UNSPEC;
+ ifn.lifn_flags = 0;
+ if (ioctl (fd, SIOCGLIFNUM, (char *) &ifn) < 0)
+ Error ("Getting interface count");
+ if (len < (ifn.lifn_count * sizeof(struct lifreq))) {
+ len = ifn.lifn_count * sizeof(struct lifreq);
+ bufptr = xalloc(len);
+ }
+#endif
+
+ ifc.lifc_family = AF_UNSPEC;
+ ifc.lifc_flags = 0;
+ ifc.lifc_len = len;
+ ifc.lifc_buf = bufptr;
+
+#define IFC_IOCTL_REQ SIOCGLIFCONF
+#define IFC_IFC_REQ ifc.lifc_req
+#define IFC_IFC_LEN ifc.lifc_len
+#define IFR_IFR_ADDR ifr->lifr_addr
+#define IFR_IFR_NAME ifr->lifr_name
+
+#else /* Use SIOCGIFCONF */
+ ifc.ifc_len = len;
+ ifc.ifc_buf = bufptr;
+
+#define IFC_IOCTL_REQ SIOCGIFCONF
+#define IFC_IFC_REQ ifc.ifc_req
+#define IFC_IFC_LEN ifc.ifc_len
+#define IFR_IFR_ADDR ifr->ifr_addr
+#define IFR_IFR_NAME ifr->ifr_name
+#endif
+
+ if (ifioctl (fd, IFC_IOCTL_REQ, (pointer) &ifc) < 0)
+ Error ("Getting interface configuration (4)");
+
+ cplim = (char *) IFC_IFC_REQ + IFC_IFC_LEN;
+
+ for (cp = (char *) IFC_IFC_REQ; cp < cplim; cp += ifr_size (ifr))
+ {
+ ifr = (ifr_type *) cp;
+ len = ifraddr_size (IFR_IFR_ADDR);
+ family = ConvertAddr ((struct sockaddr *) &IFR_IFR_ADDR,
+ &len, (pointer *)&addr);
+#ifdef DNETCONN
+ /*
+ * DECnet was handled up above.
+ */
+ if (family == AF_DECnet)
+ continue;
+#endif /* DNETCONN */
+ if (family == -1 || family == FamilyLocal)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ in6_fillscopeid((struct sockaddr_in6 *)&IFR_IFR_ADDR);
+#endif
+ for (host = selfhosts;
+ host && !addrEqual (family, addr, len, host);
+ host = host->next)
+ ;
+ if (host)
+ continue;
+ MakeHost(host,len)
+ if (host)
+ {
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ {
+#ifdef USE_SIOCGLIFCONF
+ struct sockaddr_storage broad_addr;
+#else
+ struct sockaddr broad_addr;
+#endif
+
+ /*
+ * If this isn't an Internet Address, don't register it.
+ */
+ if (family != FamilyInternet
+#if defined(IPv6) && defined(AF_INET6)
+ && family != FamilyInternet6
+#endif
+ )
+ continue;
+
+ /*
+ * ignore 'localhost' entries as they're not useful
+ * on the other end of the wire
+ */
+ if (family == FamilyInternet &&
+ addr[0] == 127 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 1)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
+ continue;
+#endif
+
+ /*
+ * Ignore '0.0.0.0' entries as they are
+ * returned by some OSes for unconfigured NICs but they are
+ * not useful on the other end of the wire.
+ */
+ if (len == 4 &&
+ addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)
+ continue;
+
+ XdmcpRegisterConnection (family, (char *)addr, len);
+
+#if defined(IPv6) && defined(AF_INET6)
+ /* IPv6 doesn't support broadcasting, so we drop out here */
+ if (family == FamilyInternet6)
+ continue;
+#endif
+
+ broad_addr = IFR_IFR_ADDR;
+
+ ((struct sockaddr_in *) &broad_addr)->sin_addr.s_addr =
+ htonl (INADDR_BROADCAST);
+#if defined(USE_SIOCGLIFCONF) && defined(SIOCGLIFBRDADDR)
+ {
+ struct lifreq broad_req;
+
+ broad_req = *ifr;
+ if (ioctl (fd, SIOCGLIFFLAGS, (char *) &broad_req) != -1 &&
+ (broad_req.lifr_flags & IFF_BROADCAST) &&
+ (broad_req.lifr_flags & IFF_UP)
+ )
+ {
+ broad_req = *ifr;
+ if (ioctl (fd, SIOCGLIFBRDADDR, &broad_req) != -1)
+ broad_addr = broad_req.lifr_broadaddr;
+ else
+ continue;
+ }
+ else
+ continue;
+ }
+
+#elif defined(SIOCGIFBRDADDR)
+ {
+ struct ifreq broad_req;
+
+ broad_req = *ifr;
+ if (ifioctl (fd, SIOCGIFFLAGS, (pointer) &broad_req) != -1 &&
+ (broad_req.ifr_flags & IFF_BROADCAST) &&
+ (broad_req.ifr_flags & IFF_UP)
+ )
+ {
+ broad_req = *ifr;
+ if (ifioctl (fd, SIOCGIFBRDADDR, (pointer) &broad_req) != -1)
+ broad_addr = broad_req.ifr_addr;
+ else
+ continue;
+ }
+ else
+ continue;
+ }
+#endif /* SIOCGIFBRDADDR */
+ XdmcpRegisterBroadcastAddress ((struct sockaddr_in *) &broad_addr);
+ }
+#endif /* XDMCP */
+ }
+ if (bufptr != buf)
+ free(bufptr);
+#else /* HAS_GETIFADDRS */
+ if (getifaddrs(&ifap) < 0) {
+ ErrorF("Warning: getifaddrs returns %s\n", strerror(errno));
+ return;
+ }
+ for (ifr = ifap; ifr != NULL; ifr = ifr->ifa_next) {
+ if (!ifr->ifa_addr)
+ continue;
+#ifdef DNETCONN
+ if (ifr->ifa_addr.sa_family == AF_DECnet)
+ continue;
+#endif /* DNETCONN */
+ len = sizeof(*(ifr->ifa_addr));
+ family = ConvertAddr(ifr->ifa_addr, &len, (pointer *)&addr);
+ if (family == -1 || family == FamilyLocal)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ in6_fillscopeid((struct sockaddr_in6 *)ifr->ifa_addr);
+#endif
+
+ for (host = selfhosts;
+ host != NULL && !addrEqual(family, addr, len, host);
+ host = host->next)
+ ;
+ if (host != NULL)
+ continue;
+ MakeHost(host, len);
+ if (host != NULL) {
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+#ifdef XDMCP
+ {
+ struct sockaddr broad_addr;
+ /*
+ * If this isn't an Internet Address, don't register it.
+ */
+ if (family != FamilyInternet
+#if defined(IPv6) && defined(AF_INET6)
+ && family != FamilyInternet6
+#endif
+ )
+ continue;
+
+ /*
+ * ignore 'localhost' entries as they're not useful
+ * on the other end of the wire
+ */
+ if (ifr->ifa_flags & IFF_LOOPBACK)
+ continue;
+
+ if (family == FamilyInternet &&
+ addr[0] == 127 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 1)
+ continue;
+
+ /*
+ * Ignore '0.0.0.0' entries as they are
+ * returned by some OSes for unconfigured NICs but they are
+ * not useful on the other end of the wire.
+ */
+ if (len == 4 &&
+ addr[0] == 0 && addr[1] == 0 &&
+ addr[2] == 0 && addr[3] == 0)
+ continue;
+#if defined(IPv6) && defined(AF_INET6)
+ else if (family == FamilyInternet6 &&
+ IN6_IS_ADDR_LOOPBACK((struct in6_addr *)addr))
+ continue;
+#endif
+ XdmcpRegisterConnection(family, (char *)addr, len);
+#if defined(IPv6) && defined(AF_INET6)
+ if (family == FamilyInternet6)
+ /* IPv6 doesn't support broadcasting, so we drop out here */
+ continue;
+#endif
+ if ((ifr->ifa_flags & IFF_BROADCAST) &&
+ (ifr->ifa_flags & IFF_UP) &&
+ ifr->ifa_broadaddr)
+ broad_addr = *ifr->ifa_broadaddr;
+ else
+ continue;
+ XdmcpRegisterBroadcastAddress((struct sockaddr_in *)
+ &broad_addr);
+ }
+#endif /* XDMCP */
+
+ } /* for */
+ freeifaddrs(ifap);
+#endif /* HAS_GETIFADDRS */
+
+ /*
+ * add something of FamilyLocalHost
+ */
+ for (host = selfhosts;
+ host && !addrEqual(FamilyLocalHost, "", 0, host);
+ host = host->next);
+ if (!host)
+ {
+ MakeHost(host, 0);
+ if (host)
+ {
+ host->family = FamilyLocalHost;
+ host->len = 0;
+ acopy("", host->addr, 0);
+ host->next = selfhosts;
+ selfhosts = host;
+ }
+ }
+}
+#endif /* hpux && !HAS_IFREQ */
+
+#ifdef XDMCP
+void
+AugmentSelf(pointer from, int len)
+{
+ int family;
+ pointer addr;
+ register HOST *host;
+
+ family = ConvertAddr(from, &len, (pointer *)&addr);
+ if (family == -1 || family == FamilyLocal)
+ return;
+ for (host = selfhosts; host; host = host->next)
+ {
+ if (addrEqual(family, addr, len, host))
+ return;
+ }
+ MakeHost(host,len)
+ if (!host)
+ return;
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = selfhosts;
+ selfhosts = host;
+}
+#endif
+
+void
+AddLocalHosts (void)
+{
+ HOST *self;
+
+ for (self = selfhosts; self; self = self->next)
+ /* Fix for XFree86 bug #156: pass addingLocal = TRUE to
+ * NewHost to tell that we are adding the default local
+ * host entries and not to flag the entries as being
+ * explicitely requested */
+ (void) NewHost (self->family, self->addr, self->len, TRUE);
+}
+
+/* Reset access control list to initial hosts */
+void
+ResetHosts (char *display)
+{
+ register HOST *host;
+ char lhostname[120], ohostname[120];
+ char *hostname = ohostname;
+ char fname[PATH_MAX + 1];
+ int fnamelen;
+ FILE *fd;
+ char *ptr;
+ int i, hostlen;
+#if ((defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)) && \
+ (!defined(IPv6) || !defined(AF_INET6))) || defined(DNETCONN)
+ union {
+ struct sockaddr sa;
+#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
+ struct sockaddr_in in;
+#endif /* TCPCONN || STREAMSCONN */
+#ifdef DNETCONN
+ struct sockaddr_dn dn;
+#endif
+ } saddr;
+#endif
+#ifdef DNETCONN
+ struct nodeent *np;
+ struct dn_naddr dnaddr, *dnaddrp, *dnet_addr();
+#endif
+ int family = 0;
+ pointer addr;
+ int len;
+
+ siTypesInitialize();
+ AccessEnabled = defeatAccessControl ? FALSE : DEFAULT_ACCESS_CONTROL;
+ LocalHostEnabled = FALSE;
+ while ((host = validhosts) != 0)
+ {
+ validhosts = host->next;
+ FreeHost (host);
+ }
+
+#if defined WIN32 && defined __MINGW32__
+#define ETC_HOST_PREFIX "X"
+#else
+#define ETC_HOST_PREFIX "/etc/X"
+#endif
+#define ETC_HOST_SUFFIX ".hosts"
+ fnamelen = strlen(ETC_HOST_PREFIX) + strlen(ETC_HOST_SUFFIX) +
+ strlen(display) + 1;
+ if (fnamelen > sizeof(fname))
+ FatalError("Display name `%s' is too long\n", display);
+ snprintf(fname, sizeof(fname), ETC_HOST_PREFIX "%s" ETC_HOST_SUFFIX,
+ display);
+
+ if ((fd = fopen (fname, "r")) != 0)
+ {
+ while (fgets (ohostname, sizeof (ohostname), fd))
+ {
+ family = FamilyWild;
+ if (*ohostname == '#')
+ continue;
+ if ((ptr = strchr(ohostname, '\n')) != 0)
+ *ptr = 0;
+ hostlen = strlen(ohostname) + 1;
+ for (i = 0; i < hostlen; i++)
+ lhostname[i] = tolower(ohostname[i]);
+ hostname = ohostname;
+ if (!strncmp("local:", lhostname, 6))
+ {
+ family = FamilyLocalHost;
+ NewHost(family, "", 0, FALSE);
+ LocalHostRequested = TRUE; /* Fix for XFree86 bug #156 */
+ }
+#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
+ else if (!strncmp("inet:", lhostname, 5))
+ {
+ family = FamilyInternet;
+ hostname = ohostname + 5;
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (!strncmp("inet6:", lhostname, 6))
+ {
+ family = FamilyInternet6;
+ hostname = ohostname + 6;
+ }
+#endif
+#endif
+#ifdef DNETCONN
+ else if (!strncmp("dnet:", lhostname, 5))
+ {
+ family = FamilyDECnet;
+ hostname = ohostname + 5;
+ }
+#endif
+#ifdef SECURE_RPC
+ else if (!strncmp("nis:", lhostname, 4))
+ {
+ family = FamilyNetname;
+ hostname = ohostname + 4;
+ }
+#endif
+ else if (!strncmp("si:", lhostname, 3))
+ {
+ family = FamilyServerInterpreted;
+ hostname = ohostname + 3;
+ hostlen -= 3;
+ }
+
+
+ if (family == FamilyServerInterpreted)
+ {
+ len = siCheckAddr(hostname, hostlen);
+ if (len >= 0) {
+ NewHost(family, hostname, len, FALSE);
+ }
+ }
+ else
+#ifdef DNETCONN
+ if ((family == FamilyDECnet) || ((family == FamilyWild) &&
+ (ptr = strchr(hostname, ':')) && (*(ptr + 1) == ':') &&
+ !(*ptr = '\0'))) /* bash trailing colons if necessary */
+ {
+ /* node name (DECnet names end in "::") */
+ dnaddrp = dnet_addr(hostname);
+ if (!dnaddrp && (np = getnodebyname (hostname)))
+ {
+ /* node was specified by name */
+ saddr.sa.sa_family = np->n_addrtype;
+ len = sizeof(saddr.sa);
+ if (ConvertAddr (&saddr.sa, &len, (pointer *)&addr) == FamilyDECnet)
+ {
+ bzero ((char *) &dnaddr, sizeof (dnaddr));
+ dnaddr.a_len = np->n_length;
+ acopy (np->n_addr, dnaddr.a_addr, np->n_length);
+ dnaddrp = &dnaddr;
+ }
+ }
+ if (dnaddrp)
+ (void) NewHost(FamilyDECnet, (pointer)dnaddrp,
+ (int)(dnaddrp->a_len + sizeof(dnaddrp->a_len)), FALSE);
+ }
+ else
+#endif /* DNETCONN */
+#ifdef SECURE_RPC
+ if ((family == FamilyNetname) || (strchr(hostname, '@')))
+ {
+ SecureRPCInit ();
+ (void) NewHost (FamilyNetname, hostname, strlen (hostname), FALSE);
+ }
+ else
+#endif /* SECURE_RPC */
+#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
+ {
+#if defined(IPv6) && defined(AF_INET6)
+ if ( (family == FamilyInternet) || (family == FamilyInternet6) ||
+ (family == FamilyWild) )
+ {
+ struct addrinfo *addresses;
+ struct addrinfo *a;
+ int f;
+
+ if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
+ for (a = addresses ; a != NULL ; a = a->ai_next) {
+ len = a->ai_addrlen;
+ f = ConvertAddr(a->ai_addr,&len,(pointer *)&addr);
+ if ( (family == f) ||
+ ((family == FamilyWild) && (f != -1)) ) {
+ NewHost(f, addr, len, FALSE);
+ }
+ }
+ freeaddrinfo(addresses);
+ }
+ }
+#else
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ register struct hostent *hp;
+
+ /* host name */
+ if ((family == FamilyInternet &&
+ ((hp = _XGethostbyname(hostname, hparams)) != 0)) ||
+ ((hp = _XGethostbyname(hostname, hparams)) != 0))
+ {
+ saddr.sa.sa_family = hp->h_addrtype;
+ len = sizeof(saddr.sa);
+ if ((family = ConvertAddr (&saddr.sa, &len, (pointer *)&addr)) != -1)
+ {
+#ifdef h_addr /* new 4.3bsd version of gethostent */
+ char **list;
+
+ /* iterate over the addresses */
+ for (list = hp->h_addr_list; *list; list++)
+ (void) NewHost (family, (pointer)*list, len, FALSE);
+#else
+ (void) NewHost (family, (pointer)hp->h_addr, len, FALSE);
+#endif
+ }
+ }
+#endif /* IPv6 */
+ }
+#endif /* TCPCONN || STREAMSCONN */
+ family = FamilyWild;
+ }
+ fclose (fd);
+ }
+}
+
+/* Is client on the local host */
+Bool LocalClient(ClientPtr client)
+{
+ int alen, family, notused;
+ Xtransaddr *from = NULL;
+ pointer addr;
+ register HOST *host;
+
+ if (!_XSERVTransGetPeerAddr (((OsCommPtr)client->osPrivate)->trans_conn,
+ &notused, &alen, &from))
+ {
+ family = ConvertAddr ((struct sockaddr *) from,
+ &alen, (pointer *)&addr);
+ if (family == -1)
+ {
+ xfree (from);
+ return FALSE;
+ }
+ if (family == FamilyLocal)
+ {
+ xfree (from);
+ return TRUE;
+ }
+ for (host = selfhosts; host; host = host->next)
+ {
+ if (addrEqual (family, addr, alen, host))
+ return TRUE;
+ }
+ xfree (from);
+ }
+ return FALSE;
+}
+
+/*
+ * Return the uid and gid of a connected local client
+ *
+ * Used by XShm to test access rights to shared memory segments
+ */
+int
+LocalClientCred(ClientPtr client, int *pUid, int *pGid)
+{
+ LocalClientCredRec *lcc;
+ int ret = GetLocalClientCreds(client, &lcc);
+
+ if (ret == 0) {
+#ifdef HAVE_GETZONEID /* only local if in the same zone */
+ if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+#endif
+ if ((lcc->fieldsSet & LCC_UID_SET) && (pUid != NULL))
+ *pUid = lcc->euid;
+ if ((lcc->fieldsSet & LCC_GID_SET) && (pGid != NULL))
+ *pGid = lcc->egid;
+ FreeLocalClientCreds(lcc);
+ }
+ return ret;
+}
+
+/*
+ * Return the uid and all gids of a connected local client
+ * Allocates a LocalClientCredRec - caller must call FreeLocalClientCreds
+ *
+ * Used by localuser & localgroup ServerInterpreted access control forms below
+ * Used by AuthAudit to log who local connections came from
+ */
+int
+GetLocalClientCreds(ClientPtr client, LocalClientCredRec **lccp)
+{
+#if defined(HAS_GETPEEREID) || defined(HAS_GETPEERUCRED) || defined(SO_PEERCRED)
+ int fd;
+ XtransConnInfo ci;
+ LocalClientCredRec *lcc;
+#ifdef HAS_GETPEEREID
+ uid_t uid;
+ gid_t gid;
+#elif defined(HAS_GETPEERUCRED)
+ ucred_t *peercred = NULL;
+ const gid_t *gids;
+#elif defined(SO_PEERCRED)
+ struct ucred peercred;
+ socklen_t so_len = sizeof(peercred);
+#endif
+
+ if (client == NULL)
+ return -1;
+ ci = ((OsCommPtr)client->osPrivate)->trans_conn;
+#if !(defined(sun) && defined(HAS_GETPEERUCRED))
+ /* Most implementations can only determine peer credentials for Unix
+ * domain sockets - Solaris getpeerucred can work with a bit more, so
+ * we just let it tell us if the connection type is supported or not
+ */
+ if (!_XSERVTransIsLocal(ci)) {
+ return -1;
+ }
+#endif
+
+ *lccp = Xcalloc(sizeof(LocalClientCredRec));
+ if (*lccp == NULL)
+ return -1;
+ lcc = *lccp;
+
+ fd = _XSERVTransGetConnectionNumber(ci);
+#ifdef HAS_GETPEEREID
+ if (getpeereid(fd, &uid, &gid) == -1) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+ lcc->euid = uid;
+ lcc->egid = gid;
+ lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET;
+ return 0;
+#elif defined(HAS_GETPEERUCRED)
+ if (getpeerucred(fd, &peercred) < 0) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+ lcc->euid = ucred_geteuid(peercred);
+ if (lcc->euid != -1)
+ lcc->fieldsSet |= LCC_UID_SET;
+ lcc->egid = ucred_getegid(peercred);
+ if (lcc->egid != -1)
+ lcc->fieldsSet |= LCC_GID_SET;
+ lcc->pid = ucred_getpid(peercred);
+ if (lcc->pid != -1)
+ lcc->fieldsSet |= LCC_PID_SET;
+#ifdef HAVE_GETZONEID
+ lcc->zoneid = ucred_getzoneid(peercred);
+ if (lcc->zoneid != -1)
+ lcc->fieldsSet |= LCC_ZID_SET;
+#endif
+ lcc->nSuppGids = ucred_getgroups(peercred, &gids);
+ if (lcc->nSuppGids > 0) {
+ lcc->pSuppGids = Xcalloc((lcc->nSuppGids) * sizeof(int));
+ if (lcc->pSuppGids == NULL) {
+ lcc->nSuppGids = 0;
+ } else {
+ int i;
+ for (i = 0 ; i < lcc->nSuppGids; i++) {
+ (lcc->pSuppGids)[i] = (int) gids[i];
+ }
+ }
+ } else {
+ lcc->nSuppGids = 0;
+ }
+ ucred_free(peercred);
+ return 0;
+#elif defined(SO_PEERCRED)
+ if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) == -1) {
+ FreeLocalClientCreds(lcc);
+ return -1;
+ }
+ lcc->euid = peercred.uid;
+ lcc->egid = peercred.gid;
+ lcc->pid = peercred.pid;
+ lcc->fieldsSet = LCC_UID_SET | LCC_GID_SET | LCC_PID_SET;
+ return 0;
+#endif
+#else
+ /* No system call available to get the credentials of the peer */
+#define NO_LOCAL_CLIENT_CRED
+ return -1;
+#endif
+}
+
+void
+FreeLocalClientCreds(LocalClientCredRec *lcc)
+{
+ if (lcc != NULL) {
+ if (lcc->nSuppGids > 0) {
+ Xfree(lcc->pSuppGids);
+ }
+ Xfree(lcc);
+ }
+}
+
+static int
+AuthorizedClient(ClientPtr client)
+{
+ int rc;
+
+ if (!client || defeatAccessControl)
+ return Success;
+
+ /* untrusted clients can't change host access */
+ rc = XaceHook(XACE_SERVER_ACCESS, client, DixManageAccess);
+ if (rc != Success)
+ return rc;
+
+ return LocalClient(client) ? Success : BadAccess;
+}
+
+/* Add a host to the access control list. This is the external interface
+ * called from the dispatcher */
+
+int
+AddHost (ClientPtr client,
+ int family,
+ unsigned length, /* of bytes in pAddr */
+ const void * pAddr)
+{
+ int rc, len;
+
+ rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ switch (family) {
+ case FamilyLocalHost:
+ len = length;
+ LocalHostEnabled = TRUE;
+ break;
+#ifdef SECURE_RPC
+ case FamilyNetname:
+ len = length;
+ SecureRPCInit ();
+ break;
+#endif
+ case FamilyInternet:
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+#endif
+ case FamilyDECnet:
+ case FamilyChaos:
+ case FamilyServerInterpreted:
+ if ((len = CheckAddr (family, pAddr, length)) < 0)
+ {
+ client->errorValue = length;
+ return (BadValue);
+ }
+ break;
+ case FamilyLocal:
+ default:
+ client->errorValue = family;
+ return (BadValue);
+ }
+ if (NewHost (family, pAddr, len, FALSE))
+ return Success;
+ return BadAlloc;
+}
+
+Bool
+ForEachHostInFamily (int family,
+ Bool (*func)(
+ unsigned char * /* addr */,
+ short /* len */,
+ pointer /* closure */),
+ pointer closure)
+{
+ HOST *host;
+
+ for (host = validhosts; host; host = host->next)
+ if (family == host->family && func (host->addr, host->len, closure))
+ return TRUE;
+ return FALSE;
+}
+
+/* Add a host to the access control list. This is the internal interface
+ * called when starting or resetting the server */
+static Bool
+NewHost (int family,
+ const void * addr,
+ int len,
+ int addingLocalHosts)
+{
+ register HOST *host;
+
+ for (host = validhosts; host; host = host->next)
+ {
+ if (addrEqual (family, addr, len, host))
+ return TRUE;
+ }
+ if (!addingLocalHosts) { /* Fix for XFree86 bug #156 */
+ for (host = selfhosts; host; host = host->next) {
+ if (addrEqual (family, addr, len, host)) {
+ host->requested = TRUE;
+ break;
+ }
+ }
+ }
+ MakeHost(host,len)
+ if (!host)
+ return FALSE;
+ host->family = family;
+ host->len = len;
+ acopy(addr, host->addr, len);
+ host->next = validhosts;
+ validhosts = host;
+ return TRUE;
+}
+
+/* Remove a host from the access control list */
+
+int
+RemoveHost (
+ ClientPtr client,
+ int family,
+ unsigned length, /* of bytes in pAddr */
+ pointer pAddr)
+{
+ int rc, len;
+ register HOST *host, **prev;
+
+ rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ switch (family) {
+ case FamilyLocalHost:
+ len = length;
+ LocalHostEnabled = FALSE;
+ break;
+#ifdef SECURE_RPC
+ case FamilyNetname:
+ len = length;
+ break;
+#endif
+ case FamilyInternet:
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+#endif
+ case FamilyDECnet:
+ case FamilyChaos:
+ case FamilyServerInterpreted:
+ if ((len = CheckAddr (family, pAddr, length)) < 0)
+ {
+ client->errorValue = length;
+ return(BadValue);
+ }
+ break;
+ case FamilyLocal:
+ default:
+ client->errorValue = family;
+ return(BadValue);
+ }
+ for (prev = &validhosts;
+ (host = *prev) && (!addrEqual (family, pAddr, len, host));
+ prev = &host->next)
+ ;
+ if (host)
+ {
+ *prev = host->next;
+ FreeHost (host);
+ }
+ return (Success);
+}
+
+/* Get all hosts in the access control list */
+int
+GetHosts (
+ pointer *data,
+ int *pnHosts,
+ int *pLen,
+ BOOL *pEnabled)
+{
+ int len;
+ register int n = 0;
+ register unsigned char *ptr;
+ register HOST *host;
+ int nHosts = 0;
+
+ *pEnabled = AccessEnabled ? EnableAccess : DisableAccess;
+ for (host = validhosts; host; host = host->next)
+ {
+ nHosts++;
+ n += pad_to_int32(host->len) + sizeof(xHostEntry);
+ }
+ if (n)
+ {
+ *data = ptr = xalloc (n);
+ if (!ptr)
+ {
+ return(BadAlloc);
+ }
+ for (host = validhosts; host; host = host->next)
+ {
+ len = host->len;
+ ((xHostEntry *)ptr)->family = host->family;
+ ((xHostEntry *)ptr)->length = len;
+ ptr += sizeof(xHostEntry);
+ acopy (host->addr, ptr, len);
+ ptr += pad_to_int32(len);
+ }
+ } else {
+ *data = NULL;
+ }
+ *pnHosts = nHosts;
+ *pLen = n;
+ return(Success);
+}
+
+/* Check for valid address family and length, and return address length. */
+
+/*ARGSUSED*/
+static int
+CheckAddr (
+ int family,
+ const void * pAddr,
+ unsigned length)
+{
+ int len;
+
+ switch (family)
+ {
+#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
+ case FamilyInternet:
+ if (length == sizeof (struct in_addr))
+ len = length;
+ else
+ len = -1;
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case FamilyInternet6:
+ if (length == sizeof (struct in6_addr))
+ len = length;
+ else
+ len = -1;
+ break;
+#endif
+#endif
+#ifdef DNETCONN
+ case FamilyDECnet:
+ {
+ struct dn_naddr *dnaddr = (struct dn_naddr *) pAddr;
+
+ if ((length < sizeof(dnaddr->a_len)) ||
+ (length < dnaddr->a_len + sizeof(dnaddr->a_len)))
+ len = -1;
+ else
+ len = dnaddr->a_len + sizeof(dnaddr->a_len);
+ if (len > sizeof(struct dn_naddr))
+ len = -1;
+ }
+ break;
+#endif
+ case FamilyServerInterpreted:
+ len = siCheckAddr(pAddr, length);
+ break;
+ default:
+ len = -1;
+ }
+ return (len);
+}
+
+/* Check if a host is not in the access control list.
+ * Returns 1 if host is invalid, 0 if we've found it. */
+
+int
+InvalidHost (
+ register struct sockaddr *saddr,
+ int len,
+ ClientPtr client)
+{
+ int family;
+ pointer addr;
+ register HOST *selfhost, *host;
+
+ if (!AccessEnabled) /* just let them in */
+ return(0);
+ family = ConvertAddr (saddr, &len, (pointer *)&addr);
+ if (family == -1)
+ return 1;
+ if (family == FamilyLocal)
+ {
+ if (!LocalHostEnabled)
+ {
+ /*
+ * check to see if any local address is enabled. This
+ * implicitly enables local connections.
+ */
+ for (selfhost = selfhosts; selfhost; selfhost=selfhost->next)
+ {
+ for (host = validhosts; host; host=host->next)
+ {
+ if (addrEqual (selfhost->family, selfhost->addr,
+ selfhost->len, host))
+ return 0;
+ }
+ }
+ } else
+ return 0;
+ }
+ for (host = validhosts; host; host = host->next)
+ {
+ if ((host->family == FamilyServerInterpreted)) {
+ if (siAddrMatch (family, addr, len, host, client)) {
+ return (0);
+ }
+ } else {
+ if (addrEqual (family, addr, len, host))
+ return (0);
+ }
+
+ }
+ return (1);
+}
+
+static int
+ConvertAddr (
+ register struct sockaddr *saddr,
+ int *len,
+ pointer *addr)
+{
+ if (*len == 0)
+ return (FamilyLocal);
+ switch (saddr->sa_family)
+ {
+ case AF_UNSPEC:
+#if defined(UNIXCONN) || defined(LOCALCONN)
+ case AF_UNIX:
+#endif
+ return FamilyLocal;
+#if defined(TCPCONN) || defined(STREAMSCONN) || defined(MNX_TCPCONN)
+ case AF_INET:
+#ifdef WIN32
+ if (16777343 == *(long*)&((struct sockaddr_in *) saddr)->sin_addr)
+ return FamilyLocal;
+#endif
+ *len = sizeof (struct in_addr);
+ *addr = (pointer) &(((struct sockaddr_in *) saddr)->sin_addr);
+ return FamilyInternet;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6:
+ {
+ struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *) saddr;
+ if (IN6_IS_ADDR_V4MAPPED(&(saddr6->sin6_addr))) {
+ *len = sizeof (struct in_addr);
+ *addr = (pointer) &(saddr6->sin6_addr.s6_addr[12]);
+ return FamilyInternet;
+ } else {
+ *len = sizeof (struct in6_addr);
+ *addr = (pointer) &(saddr6->sin6_addr);
+ return FamilyInternet6;
+ }
+ }
+#endif
+#endif
+#ifdef DNETCONN
+ case AF_DECnet:
+ {
+ struct sockaddr_dn *sdn = (struct sockaddr_dn *) saddr;
+ *len = sdn->sdn_nodeaddrl + sizeof(sdn->sdn_nodeaddrl);
+ *addr = (pointer) &(sdn->sdn_add);
+ }
+ return FamilyDECnet;
+#endif
+#ifdef CHAOSCONN
+ case AF_CHAOS:
+ {
+ not implemented
+ }
+ return FamilyChaos;
+#endif
+ default:
+ return -1;
+ }
+}
+
+int
+ChangeAccessControl(
+ ClientPtr client,
+ int fEnabled)
+{
+ int rc = AuthorizedClient(client);
+ if (rc != Success)
+ return rc;
+ AccessEnabled = fEnabled;
+ return Success;
+}
+
+/* returns FALSE if xhost + in effect, else TRUE */
+int
+GetAccessControl(void)
+{
+ return AccessEnabled;
+}
+
+/*****************************************************************************
+ * FamilyServerInterpreted host entry implementation
+ *
+ * Supports an extensible system of host types which the server can interpret
+ * See the IPv6 extensions to the X11 protocol spec for the definition.
+ *
+ * Currently supported schemes:
+ *
+ * hostname - hostname as defined in IETF RFC 2396
+ * ipv6 - IPv6 literal address as defined in IETF RFC's 3513 and <TBD>
+ *
+ * See xc/doc/specs/SIAddresses for formal definitions of each type.
+ */
+
+/* These definitions and the siTypeAdd function could be exported in the
+ * future to enable loading additional host types, but that was not done for
+ * the initial implementation.
+ */
+typedef Bool (*siAddrMatchFunc)(int family, pointer addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *siTypePriv);
+typedef int (*siCheckAddrFunc)(const char *addrString, int length,
+ void *siTypePriv);
+
+struct siType {
+ struct siType * next;
+ const char * typeName;
+ siAddrMatchFunc addrMatch;
+ siCheckAddrFunc checkAddr;
+ void * typePriv; /* Private data for type routines */
+};
+
+static struct siType *siTypeList;
+
+static int
+siTypeAdd(const char *typeName, siAddrMatchFunc addrMatch,
+ siCheckAddrFunc checkAddr, void *typePriv)
+{
+ struct siType *s, *p;
+
+ if ((typeName == NULL) || (addrMatch == NULL) || (checkAddr == NULL))
+ return BadValue;
+
+ for (s = siTypeList, p = NULL; s != NULL ; p = s, s = s->next) {
+ if (strcmp(typeName, s->typeName) == 0) {
+ s->addrMatch = addrMatch;
+ s->checkAddr = checkAddr;
+ s->typePriv = typePriv;
+ return Success;
+ }
+ }
+
+ s = xalloc(sizeof(struct siType));
+ if (s == NULL)
+ return BadAlloc;
+
+ if (p == NULL)
+ siTypeList = s;
+ else
+ p->next = s;
+
+ s->next = NULL;
+ s->typeName = typeName;
+ s->addrMatch = addrMatch;
+ s->checkAddr = checkAddr;
+ s->typePriv = typePriv;
+ return Success;
+}
+
+/* Checks to see if a host matches a server-interpreted host entry */
+static Bool
+siAddrMatch(int family, pointer addr, int len, HOST *host, ClientPtr client)
+{
+ Bool matches = FALSE;
+ struct siType *s;
+ const char *valueString;
+ int addrlen;
+
+ valueString = (const char *) memchr(host->addr, '\0', host->len);
+ if (valueString != NULL) {
+ for (s = siTypeList; s != NULL ; s = s->next) {
+ if (strcmp((char *) host->addr, s->typeName) == 0) {
+ addrlen = host->len - (strlen((char *)host->addr) + 1);
+ matches = s->addrMatch(family, addr, len,
+ valueString + 1, addrlen, client, s->typePriv);
+ break;
+ }
+ }
+#ifdef FAMILY_SI_DEBUG
+ ErrorF(
+ "Xserver: siAddrMatch(): type = %s, value = %*.*s -- %s\n",
+ host->addr, addrlen, addrlen, valueString + 1,
+ (matches) ? "accepted" : "rejected");
+#endif
+ }
+ return matches;
+}
+
+static int
+siCheckAddr(const char *addrString, int length)
+{
+ const char *valueString;
+ int addrlen, typelen;
+ int len = -1;
+ struct siType *s;
+
+ /* Make sure there is a \0 byte inside the specified length
+ to separate the address type from the address value. */
+ valueString = (const char *) memchr(addrString, '\0', length);
+ if (valueString != NULL) {
+ /* Make sure the first string is a recognized address type,
+ * and the second string is a valid address of that type.
+ */
+ typelen = strlen(addrString) + 1;
+ addrlen = length - typelen;
+
+ for (s = siTypeList; s != NULL ; s = s->next) {
+ if (strcmp(addrString, s->typeName) == 0) {
+ len = s->checkAddr(valueString + 1, addrlen, s->typePriv);
+ if (len >= 0) {
+ len += typelen;
+ }
+ break;
+ }
+ }
+#ifdef FAMILY_SI_DEBUG
+ {
+ const char *resultMsg;
+
+ if (s == NULL) {
+ resultMsg = "type not registered";
+ } else {
+ if (len == -1)
+ resultMsg = "rejected";
+ else
+ resultMsg = "accepted";
+ }
+
+ ErrorF("Xserver: siCheckAddr(): type = %s, value = %*.*s, len = %d -- %s\n",
+ addrString, addrlen, addrlen, valueString + 1, len, resultMsg);
+ }
+#endif
+ }
+ return len;
+}
+
+
+/***
+ * Hostname server-interpreted host type
+ *
+ * Stored as hostname string, explicitly defined to be resolved ONLY
+ * at access check time, to allow for hosts with dynamic addresses
+ * but static hostnames, such as found in some DHCP & mobile setups.
+ *
+ * Hostname must conform to IETF RFC 2396 sec. 3.2.2, which defines it as:
+ * hostname = *( domainlabel "." ) toplabel [ "." ]
+ * domainlabel = alphanum | alphanum *( alphanum | "-" ) alphanum
+ * toplabel = alpha | alpha *( alphanum | "-" ) alphanum
+ */
+
+#ifdef NI_MAXHOST
+# define SI_HOSTNAME_MAXLEN NI_MAXHOST
+#else
+# ifdef MAXHOSTNAMELEN
+# define SI_HOSTNAME_MAXLEN MAXHOSTNAMELEN
+# else
+# define SI_HOSTNAME_MAXLEN 256
+# endif
+#endif
+
+static Bool
+siHostnameAddrMatch(int family, pointer addr, int len,
+ const char *siAddr, int siAddrLen, ClientPtr client, void *typePriv)
+{
+ Bool res = FALSE;
+
+/* Currently only supports checking against IPv4 & IPv6 connections, but
+ * support for other address families, such as DECnet, could be added if
+ * desired.
+ */
+#if defined(IPv6) && defined(AF_INET6)
+ if ((family == FamilyInternet) || (family == FamilyInternet6)) {
+ char hostname[SI_HOSTNAME_MAXLEN];
+ struct addrinfo *addresses;
+ struct addrinfo *a;
+ int f, hostaddrlen;
+ pointer hostaddr;
+
+ if (siAddrLen >= sizeof(hostname))
+ return FALSE;
+
+ strncpy(hostname, siAddr, siAddrLen);
+ hostname[siAddrLen] = '\0';
+
+ if (getaddrinfo(hostname, NULL, NULL, &addresses) == 0) {
+ for (a = addresses ; a != NULL ; a = a->ai_next) {
+ hostaddrlen = a->ai_addrlen;
+ f = ConvertAddr(a->ai_addr,&hostaddrlen,&hostaddr);
+ if ((f == family) && (len == hostaddrlen) &&
+ (acmp (addr, hostaddr, len) == 0) ) {
+ res = TRUE;
+ break;
+ }
+ }
+ freeaddrinfo(addresses);
+ }
+ }
+#else /* IPv6 not supported, use gethostbyname instead for IPv4 */
+ if (family == FamilyInternet) {
+ register struct hostent *hp;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+ char hostname[SI_HOSTNAME_MAXLEN];
+ int f, hostaddrlen;
+ pointer hostaddr;
+ const char **addrlist;
+
+ if (siAddrLen >= sizeof(hostname))
+ return FALSE;
+
+ strncpy(hostname, siAddr, siAddrLen);
+ hostname[siAddrLen] = '\0';
+
+ if ((hp = _XGethostbyname(hostname, hparams)) != NULL) {
+#ifdef h_addr /* new 4.3bsd version of gethostent */
+ /* iterate over the addresses */
+ for (addrlist = hp->h_addr_list; *addrlist; addrlist++)
+#else
+ addrlist = &hp->h_addr;
+#endif
+ {
+ struct sockaddr_in sin;
+
+ sin.sin_family = hp->h_addrtype;
+ acopy ( *addrlist, &(sin.sin_addr), hp->h_length);
+ hostaddrlen = sizeof(sin);
+ f = ConvertAddr ((struct sockaddr *)&sin,
+ &hostaddrlen, &hostaddr);
+ if ((f == family) && (len == hostaddrlen) &&
+ (acmp (addr, hostaddr, len) == 0) ) {
+ res = TRUE;
+ break;
+ }
+ }
+ }
+ }
+#endif
+ return res;
+}
+
+
+static int
+siHostnameCheckAddr(const char *valueString, int length, void *typePriv)
+{
+ /* Check conformance of hostname to RFC 2396 sec. 3.2.2 definition.
+ * We do not use ctype functions here to avoid locale-specific
+ * character sets. Hostnames must be pure ASCII.
+ */
+ int len = length;
+ int i;
+ Bool dotAllowed = FALSE;
+ Bool dashAllowed = FALSE;
+
+ if ((length <= 0) || (length >= SI_HOSTNAME_MAXLEN)) {
+ len = -1;
+ } else {
+ for (i = 0; i < length; i++) {
+ char c = valueString[i];
+
+ if (c == 0x2E) { /* '.' */
+ if (dotAllowed == FALSE) {
+ len = -1;
+ break;
+ } else {
+ dotAllowed = FALSE;
+ dashAllowed = FALSE;
+ }
+ } else if (c == 0x2D) { /* '-' */
+ if (dashAllowed == FALSE) {
+ len = -1;
+ break;
+ } else {
+ dotAllowed = FALSE;
+ }
+ } else if (((c >= 0x30) && (c <= 0x3A)) /* 0-9 */ ||
+ ((c >= 0x61) && (c <= 0x7A)) /* a-z */ ||
+ ((c >= 0x41) && (c <= 0x5A)) /* A-Z */) {
+ dotAllowed = TRUE;
+ dashAllowed = TRUE;
+ } else { /* Invalid character */
+ len = -1;
+ break;
+ }
+ }
+ }
+ return len;
+}
+
+#if defined(IPv6) && defined(AF_INET6)
+/***
+ * "ipv6" server interpreted type
+ *
+ * Currently supports only IPv6 literal address as specified in IETF RFC 3513
+ *
+ * Once draft-ietf-ipv6-scoping-arch-00.txt becomes an RFC, support will be
+ * added for the scoped address format it specifies.
+ */
+
+/* Maximum length of an IPv6 address string - increase when adding support
+ * for scoped address qualifiers. Includes room for trailing NUL byte.
+ */
+#define SI_IPv6_MAXLEN INET6_ADDRSTRLEN
+
+static Bool
+siIPv6AddrMatch(int family, pointer addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
+{
+ struct in6_addr addr6;
+ char addrbuf[SI_IPv6_MAXLEN];
+
+ if ((family != FamilyInternet6) || (len != sizeof(addr6)))
+ return FALSE;
+
+ memcpy(addrbuf, siAddr, siAddrlen);
+ addrbuf[siAddrlen] = '\0';
+
+ if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
+ perror("inet_pton");
+ return FALSE;
+ }
+
+ if (memcmp(addr, &addr6, len) == 0) {
+ return TRUE;
+ } else {
+ return FALSE;
+ }
+}
+
+static int
+siIPv6CheckAddr(const char *addrString, int length, void *typePriv)
+{
+ int len;
+
+ /* Minimum length is 3 (smallest legal address is "::1") */
+ if (length < 3) {
+ /* Address is too short! */
+ len = -1;
+ } else if (length >= SI_IPv6_MAXLEN) {
+ /* Address is too long! */
+ len = -1;
+ } else {
+ /* Assume inet_pton is sufficient validation */
+ struct in6_addr addr6;
+ char addrbuf[SI_IPv6_MAXLEN];
+
+ memcpy(addrbuf, addrString, length);
+ addrbuf[length] = '\0';
+
+ if (inet_pton(AF_INET6, addrbuf, &addr6) != 1) {
+ perror("inet_pton");
+ len = -1;
+ } else {
+ len = length;
+ }
+ }
+ return len;
+}
+#endif /* IPv6 */
+
+#if !defined(NO_LOCAL_CLIENT_CRED)
+/***
+ * "localuser" & "localgroup" server interpreted types
+ *
+ * Allows local connections from a given local user or group
+ */
+
+#include <pwd.h>
+#include <grp.h>
+
+#define LOCAL_USER 1
+#define LOCAL_GROUP 2
+
+typedef struct {
+ int credType;
+} siLocalCredPrivRec, *siLocalCredPrivPtr;
+
+static siLocalCredPrivRec siLocalUserPriv = { LOCAL_USER };
+static siLocalCredPrivRec siLocalGroupPriv = { LOCAL_GROUP };
+
+static Bool
+siLocalCredGetId(const char *addr, int len, siLocalCredPrivPtr lcPriv, int *id)
+{
+ Bool parsedOK = FALSE;
+ char *addrbuf = xalloc(len + 1);
+
+ if (addrbuf == NULL) {
+ return FALSE;
+ }
+
+ memcpy(addrbuf, addr, len);
+ addrbuf[len] = '\0';
+
+ if (addr[0] == '#') { /* numeric id */
+ char *cp;
+ errno = 0;
+ *id = strtol(addrbuf + 1, &cp, 0);
+ if ((errno == 0) && (cp != (addrbuf+1))) {
+ parsedOK = TRUE;
+ }
+ } else { /* non-numeric name */
+ if (lcPriv->credType == LOCAL_USER) {
+ struct passwd *pw = getpwnam(addrbuf);
+
+ if (pw != NULL) {
+ *id = (int) pw->pw_uid;
+ parsedOK = TRUE;
+ }
+ } else { /* group */
+ struct group *gr = getgrnam(addrbuf);
+
+ if (gr != NULL) {
+ *id = (int) gr->gr_gid;
+ parsedOK = TRUE;
+ }
+ }
+ }
+
+ xfree(addrbuf);
+ return parsedOK;
+}
+
+static Bool
+siLocalCredAddrMatch(int family, pointer addr, int len,
+ const char *siAddr, int siAddrlen, ClientPtr client, void *typePriv)
+{
+ int siAddrId;
+ LocalClientCredRec *lcc;
+ siLocalCredPrivPtr lcPriv = (siLocalCredPrivPtr) typePriv;
+
+ if (GetLocalClientCreds(client, &lcc) == -1) {
+ return FALSE;
+ }
+
+#ifdef HAVE_GETZONEID /* Ensure process is in the same zone */
+ if ((lcc->fieldsSet & LCC_ZID_SET) && (lcc->zoneid != getzoneid())) {
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+ }
+#endif
+
+ if (siLocalCredGetId(siAddr, siAddrlen, lcPriv, &siAddrId) == FALSE) {
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+ }
+
+ if (lcPriv->credType == LOCAL_USER) {
+ if ((lcc->fieldsSet & LCC_UID_SET) && (lcc->euid == siAddrId)) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ } else {
+ if ((lcc->fieldsSet & LCC_GID_SET) && (lcc->egid == siAddrId)) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ if (lcc->pSuppGids != NULL) {
+ int i;
+
+ for (i = 0 ; i < lcc->nSuppGids; i++) {
+ if (lcc->pSuppGids[i] == siAddrId) {
+ FreeLocalClientCreds(lcc);
+ return TRUE;
+ }
+ }
+ }
+ }
+ FreeLocalClientCreds(lcc);
+ return FALSE;
+}
+
+static int
+siLocalCredCheckAddr(const char *addrString, int length, void *typePriv)
+{
+ int len = length;
+ int id;
+
+ if (siLocalCredGetId(addrString, length,
+ (siLocalCredPrivPtr)typePriv, &id) == FALSE) {
+ len = -1;
+ }
+ return len;
+}
+#endif /* localuser */
+
+static void
+siTypesInitialize(void)
+{
+ siTypeAdd("hostname", siHostnameAddrMatch, siHostnameCheckAddr, NULL);
+#if defined(IPv6) && defined(AF_INET6)
+ siTypeAdd("ipv6", siIPv6AddrMatch, siIPv6CheckAddr, NULL);
+#endif
+#if !defined(NO_LOCAL_CLIENT_CRED)
+ siTypeAdd("localuser", siLocalCredAddrMatch, siLocalCredCheckAddr,
+ &siLocalUserPriv);
+ siTypeAdd("localgroup", siLocalCredAddrMatch, siLocalCredCheckAddr,
+ &siLocalGroupPriv);
+#endif
+}
diff --git a/xorg-server/os/auth.c b/xorg-server/os/auth.c
index 0514d1788..f80e53155 100644
--- a/xorg-server/os/auth.c
+++ b/xorg-server/os/auth.c
@@ -1,339 +1,340 @@
-/*
-
-Copyright 1988, 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.
-
-*/
-
-/*
- * authorization hooks for the server
- * Author: Keith Packard, MIT X Consortium
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-# include <X11/X.h>
-# include <X11/Xauth.h>
-# include "misc.h"
-# include "osdep.h"
-# include "dixstruct.h"
-# include <sys/types.h>
-# include <sys/stat.h>
-#ifdef WIN32
-#include <X11/Xw32defs.h>
-#endif
-
-struct protocol {
- unsigned short name_length;
- char *name;
- AuthAddCFunc Add; /* new authorization data */
- AuthCheckFunc Check; /* verify client authorization data */
- AuthRstCFunc Reset; /* delete all authorization data entries */
- AuthToIDFunc ToID; /* convert cookie to ID */
- AuthFromIDFunc FromID; /* convert ID to cookie */
- AuthRemCFunc Remove; /* remove a specific cookie */
-#ifdef XCSECURITY
- AuthGenCFunc Generate;
-#endif
-};
-
-static struct protocol protocols[] = {
-{ (unsigned short) 18, "MIT-MAGIC-COOKIE-1",
- MitAddCookie, MitCheckCookie, MitResetCookie,
- MitToID, MitFromID, MitRemoveCookie,
-#ifdef XCSECURITY
- MitGenerateCookie
-#endif
-},
-#ifdef HASXDMAUTH
-{ (unsigned short) 19, "XDM-AUTHORIZATION-1",
- XdmAddCookie, XdmCheckCookie, XdmResetCookie,
- XdmToID, XdmFromID, XdmRemoveCookie,
-#ifdef XCSECURITY
- NULL
-#endif
-},
-#endif
-#ifdef SECURE_RPC
-{ (unsigned short) 9, "SUN-DES-1",
- SecureRPCAdd, SecureRPCCheck, SecureRPCReset,
- SecureRPCToID, SecureRPCFromID,SecureRPCRemove,
-#ifdef XCSECURITY
- NULL
-#endif
-},
-#endif
-};
-
-# define NUM_AUTHORIZATION (sizeof (protocols) /\
- sizeof (struct protocol))
-
-/*
- * Initialize all classes of authorization by reading the
- * specified authorization file
- */
-
-static char *authorization_file = (char *)NULL;
-
-static Bool ShouldLoadAuth = TRUE;
-
-void
-InitAuthorization (char *file_name)
-{
- authorization_file = file_name;
-}
-
-static int
-LoadAuthorization (void)
-{
- FILE *f;
- Xauth *auth;
- int i;
- int count = 0;
-
- ShouldLoadAuth = FALSE;
- if (!authorization_file)
- return 0;
-
- f = Fopen (authorization_file, "r");
- if (!f)
- return -1;
-
- while ((auth = XauReadAuth (f)) != 0) {
- for (i = 0; i < NUM_AUTHORIZATION; i++) {
- if (protocols[i].name_length == auth->name_length &&
- memcmp (protocols[i].name, auth->name, (int) auth->name_length) == 0 &&
- protocols[i].Add)
- {
- ++count;
- (*protocols[i].Add) (auth->data_length, auth->data,
- FakeClientID(0));
- }
- }
- XauDisposeAuth (auth);
- }
-
- Fclose (f);
- return count;
-}
-
-#ifdef XDMCP
-/*
- * XdmcpInit calls this function to discover all authorization
- * schemes supported by the display
- */
-void
-RegisterAuthorizations (void)
-{
- int i;
-
- for (i = 0; i < NUM_AUTHORIZATION; i++)
- XdmcpRegisterAuthorization (protocols[i].name,
- (int)protocols[i].name_length);
-}
-#endif
-
-XID
-CheckAuthorization (
- unsigned int name_length,
- char *name,
- unsigned int data_length,
- char *data,
- ClientPtr client,
- char **reason) /* failure message. NULL for default msg */
-{
- int i;
- struct stat buf;
- static time_t lastmod = 0;
- static Bool loaded = FALSE;
-
- if (!authorization_file || stat(authorization_file, &buf))
- {
- if (lastmod != 0) {
- lastmod = 0;
- ShouldLoadAuth = TRUE; /* stat lost, so force reload */
- }
- }
- else if (buf.st_mtime > lastmod)
- {
- lastmod = buf.st_mtime;
- ShouldLoadAuth = TRUE;
- }
- if (ShouldLoadAuth)
- {
- int loadauth = LoadAuthorization();
-
- /*
- * If the authorization file has at least one entry for this server,
- * disable local host access. (loadauth > 0)
- *
- * If there are zero entries (either initially or when the
- * authorization file is later reloaded), or if a valid
- * authorization file was never loaded, enable local host access.
- * (loadauth == 0 || !loaded)
- *
- * If the authorization file was loaded initially (with valid
- * entries for this server), and reloading it later fails, don't
- * change anything. (loadauth == -1 && loaded)
- */
-
- if (loadauth > 0)
- {
- DisableLocalHost(); /* got at least one */
- loaded = TRUE;
- }
- else if (loadauth == 0 || !loaded)
- EnableLocalHost ();
- }
- if (name_length) {
- for (i = 0; i < NUM_AUTHORIZATION; i++) {
- if (protocols[i].name_length == name_length &&
- memcmp (protocols[i].name, name, (int) name_length) == 0)
- {
- return (*protocols[i].Check) (data_length, data, client, reason);
- }
- *reason = "Protocol not supported by server\n";
- }
- } else *reason = "No protocol specified\n";
- return (XID) ~0L;
-}
-
-void
-ResetAuthorization (void)
-{
- int i;
-
- for (i = 0; i < NUM_AUTHORIZATION; i++)
- if (protocols[i].Reset)
- (*protocols[i].Reset)();
- ShouldLoadAuth = TRUE;
-}
-
-int
-AuthorizationFromID (
- XID id,
- unsigned short *name_lenp,
- char **namep,
- unsigned short *data_lenp,
- char **datap)
-{
- int i;
-
- for (i = 0; i < NUM_AUTHORIZATION; i++) {
- if (protocols[i].FromID &&
- (*protocols[i].FromID) (id, data_lenp, datap)) {
- *name_lenp = protocols[i].name_length;
- *namep = protocols[i].name;
- return 1;
- }
- }
- return 0;
-}
-
-int
-RemoveAuthorization (
- unsigned short name_length,
- char *name,
- unsigned short data_length,
- char *data)
-{
- int i;
-
- for (i = 0; i < NUM_AUTHORIZATION; i++) {
- if (protocols[i].name_length == name_length &&
- memcmp (protocols[i].name, name, (int) name_length) == 0 &&
- protocols[i].Remove)
- {
- return (*protocols[i].Remove) (data_length, data);
- }
- }
- return 0;
-}
-
-int
-AddAuthorization (unsigned name_length, char *name, unsigned data_length, char *data)
-{
- int i;
-
- for (i = 0; i < NUM_AUTHORIZATION; i++) {
- if (protocols[i].name_length == name_length &&
- memcmp (protocols[i].name, name, (int) name_length) == 0 &&
- protocols[i].Add)
- {
- return (*protocols[i].Add) (data_length, data, FakeClientID(0));
- }
- }
- return 0;
-}
-
-#ifdef XCSECURITY
-
-XID
-GenerateAuthorization(
- unsigned name_length,
- char *name,
- unsigned data_length,
- char *data,
- unsigned *data_length_return,
- char **data_return)
-{
- int i;
-
- for (i = 0; i < NUM_AUTHORIZATION; i++) {
- if (protocols[i].name_length == name_length &&
- memcmp (protocols[i].name, name, (int) name_length) == 0 &&
- protocols[i].Generate)
- {
- return (*protocols[i].Generate) (data_length, data,
- FakeClientID(0), data_length_return, data_return);
- }
- }
- return -1;
-}
-
-void
-GenerateRandomData (int len, char *buf)
-{
-#ifdef _MSC_VER
- static HANDLE hAdvApi32;
- static BOOLEAN (_stdcall * RtlGenRandom)(void *,unsigned long);
-
- if (!hAdvApi32)
- {
- hAdvApi32=LoadLibrary("advapi32.dll");
- RtlGenRandom=(BOOLEAN (_stdcall *)(void*,unsigned long))GetProcAddress(hAdvApi32,"SystemFunction036");
- }
- RtlGenRandom(buf, len);
-#else
- int fd;
-
- fd = open("/dev/urandom", O_RDONLY);
- read(fd, buf, len);
- close(fd);
-#endif
-}
-
-#endif /* XCSECURITY */
+/*
+
+Copyright 1988, 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.
+
+*/
+
+/*
+ * authorization hooks for the server
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+# include <X11/X.h>
+# include <X11/Xauth.h>
+# include "misc.h"
+# include "osdep.h"
+# include "dixstruct.h"
+# include <sys/types.h>
+# include <sys/stat.h>
+#ifdef WIN32
+#include <X11/Xw32defs.h>
+#endif
+
+struct protocol {
+ unsigned short name_length;
+ char *name;
+ AuthAddCFunc Add; /* new authorization data */
+ AuthCheckFunc Check; /* verify client authorization data */
+ AuthRstCFunc Reset; /* delete all authorization data entries */
+ AuthToIDFunc ToID; /* convert cookie to ID */
+ AuthFromIDFunc FromID; /* convert ID to cookie */
+ AuthRemCFunc Remove; /* remove a specific cookie */
+#ifdef XCSECURITY
+ AuthGenCFunc Generate;
+#endif
+};
+
+static struct protocol protocols[] = {
+{ (unsigned short) 18, "MIT-MAGIC-COOKIE-1",
+ MitAddCookie, MitCheckCookie, MitResetCookie,
+ MitToID, MitFromID, MitRemoveCookie,
+#ifdef XCSECURITY
+ MitGenerateCookie
+#endif
+},
+#ifdef HASXDMAUTH
+{ (unsigned short) 19, "XDM-AUTHORIZATION-1",
+ XdmAddCookie, XdmCheckCookie, XdmResetCookie,
+ XdmToID, XdmFromID, XdmRemoveCookie,
+#ifdef XCSECURITY
+ NULL
+#endif
+},
+#endif
+#ifdef SECURE_RPC
+{ (unsigned short) 9, "SUN-DES-1",
+ SecureRPCAdd, SecureRPCCheck, SecureRPCReset,
+ SecureRPCToID, SecureRPCFromID,SecureRPCRemove,
+#ifdef XCSECURITY
+ NULL
+#endif
+},
+#endif
+};
+
+# define NUM_AUTHORIZATION (sizeof (protocols) /\
+ sizeof (struct protocol))
+
+/*
+ * Initialize all classes of authorization by reading the
+ * specified authorization file
+ */
+
+static char *authorization_file = (char *)NULL;
+
+static Bool ShouldLoadAuth = TRUE;
+
+void
+InitAuthorization (char *file_name)
+{
+ authorization_file = file_name;
+}
+
+static int
+LoadAuthorization (void)
+{
+ FILE *f;
+ Xauth *auth;
+ int i;
+ int count = 0;
+
+ ShouldLoadAuth = FALSE;
+ if (!authorization_file)
+ return 0;
+
+ f = Fopen (authorization_file, "r");
+ if (!f)
+ return -1;
+
+ while ((auth = XauReadAuth (f)) != 0) {
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].name_length == auth->name_length &&
+ memcmp (protocols[i].name, auth->name, (int) auth->name_length) == 0 &&
+ protocols[i].Add)
+ {
+ ++count;
+ (*protocols[i].Add) (auth->data_length, auth->data,
+ FakeClientID(0));
+ }
+ }
+ XauDisposeAuth (auth);
+ }
+
+ Fclose (f);
+ return count;
+}
+
+#ifdef XDMCP
+/*
+ * XdmcpInit calls this function to discover all authorization
+ * schemes supported by the display
+ */
+void
+RegisterAuthorizations (void)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++)
+ XdmcpRegisterAuthorization (protocols[i].name,
+ (int)protocols[i].name_length);
+}
+#endif
+
+XID
+CheckAuthorization (
+ unsigned int name_length,
+ const char *name,
+ unsigned int data_length,
+ const char *data,
+ ClientPtr client,
+ char **reason) /* failure message. NULL for default msg */
+{
+ int i;
+ struct stat buf;
+ static time_t lastmod = 0;
+ static Bool loaded = FALSE;
+
+ if (!authorization_file || stat(authorization_file, &buf))
+ {
+ if (lastmod != 0) {
+ lastmod = 0;
+ ShouldLoadAuth = TRUE; /* stat lost, so force reload */
+ }
+ }
+ else if (buf.st_mtime > lastmod)
+ {
+ lastmod = buf.st_mtime;
+ ShouldLoadAuth = TRUE;
+ }
+ if (ShouldLoadAuth)
+ {
+ int loadauth = LoadAuthorization();
+
+ /*
+ * If the authorization file has at least one entry for this server,
+ * disable local host access. (loadauth > 0)
+ *
+ * If there are zero entries (either initially or when the
+ * authorization file is later reloaded), or if a valid
+ * authorization file was never loaded, enable local host access.
+ * (loadauth == 0 || !loaded)
+ *
+ * If the authorization file was loaded initially (with valid
+ * entries for this server), and reloading it later fails, don't
+ * change anything. (loadauth == -1 && loaded)
+ */
+
+ if (loadauth > 0)
+ {
+ DisableLocalHost(); /* got at least one */
+ loaded = TRUE;
+ }
+ else if (loadauth == 0 || !loaded)
+ EnableLocalHost ();
+ }
+ if (name_length) {
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].name_length == name_length &&
+ memcmp (protocols[i].name, name, (int) name_length) == 0)
+ {
+ return (*protocols[i].Check) (data_length, data, client, reason);
+ }
+ *reason = "Protocol not supported by server\n";
+ }
+ } else *reason = "No protocol specified\n";
+ return (XID) ~0L;
+}
+
+void
+ResetAuthorization (void)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++)
+ if (protocols[i].Reset)
+ (*protocols[i].Reset)();
+ ShouldLoadAuth = TRUE;
+}
+
+int
+AuthorizationFromID (
+ XID id,
+ unsigned short *name_lenp,
+ char **namep,
+ unsigned short *data_lenp,
+ char **datap)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].FromID &&
+ (*protocols[i].FromID) (id, data_lenp, datap)) {
+ *name_lenp = protocols[i].name_length;
+ *namep = protocols[i].name;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+RemoveAuthorization (
+ unsigned short name_length,
+ const char *name,
+ unsigned short data_length,
+ const char *data)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].name_length == name_length &&
+ memcmp (protocols[i].name, name, (int) name_length) == 0 &&
+ protocols[i].Remove)
+ {
+ return (*protocols[i].Remove) (data_length, data);
+ }
+ }
+ return 0;
+}
+
+int
+AddAuthorization (unsigned name_length, const char *name,
+ unsigned data_length, char *data)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].name_length == name_length &&
+ memcmp (protocols[i].name, name, (int) name_length) == 0 &&
+ protocols[i].Add)
+ {
+ return (*protocols[i].Add) (data_length, data, FakeClientID(0));
+ }
+ }
+ return 0;
+}
+
+#ifdef XCSECURITY
+
+XID
+GenerateAuthorization(
+ unsigned name_length,
+ const char *name,
+ unsigned data_length,
+ const char *data,
+ unsigned *data_length_return,
+ char **data_return)
+{
+ int i;
+
+ for (i = 0; i < NUM_AUTHORIZATION; i++) {
+ if (protocols[i].name_length == name_length &&
+ memcmp (protocols[i].name, name, (int) name_length) == 0 &&
+ protocols[i].Generate)
+ {
+ return (*protocols[i].Generate) (data_length, data,
+ FakeClientID(0), data_length_return, data_return);
+ }
+ }
+ return -1;
+}
+
+void
+GenerateRandomData (int len, char *buf)
+{
+#ifdef _MSC_VER
+ static HANDLE hAdvApi32;
+ static BOOLEAN (_stdcall * RtlGenRandom)(void *,unsigned long);
+
+ if (!hAdvApi32)
+ {
+ hAdvApi32=LoadLibrary("advapi32.dll");
+ RtlGenRandom=(BOOLEAN (_stdcall *)(void*,unsigned long))GetProcAddress(hAdvApi32,"SystemFunction036");
+ }
+ RtlGenRandom(buf, len);
+#else
+ int fd;
+
+ fd = open("/dev/urandom", O_RDONLY);
+ read(fd, buf, len);
+ close(fd);
+#endif
+}
+
+#endif /* XCSECURITY */
diff --git a/xorg-server/os/mitauth.c b/xorg-server/os/mitauth.c
index a7968cbd7..5baf552bc 100644
--- a/xorg-server/os/mitauth.c
+++ b/xorg-server/os/mitauth.c
@@ -1,197 +1,197 @@
-/*
-
-Copyright 1988, 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.
-
-*/
-
-/*
- * MIT-MAGIC-COOKIE-1 authorization scheme
- * Author: Keith Packard, MIT X Consortium
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <X11/X.h>
-#include "os.h"
-#include "osdep.h"
-#include "dixstruct.h"
-
-static struct auth {
- struct auth *next;
- unsigned short len;
- char *data;
- XID id;
-} *mit_auth;
-
-int
-MitAddCookie (
- unsigned short data_length,
- char *data,
- XID id)
-{
- struct auth *new;
-
- new = xalloc (sizeof (struct auth));
- if (!new)
- return 0;
- new->data = xalloc ((unsigned) data_length);
- if (!new->data) {
- xfree(new);
- return 0;
- }
- new->next = mit_auth;
- mit_auth = new;
- memmove(new->data, data, (int) data_length);
- new->len = data_length;
- new->id = id;
- return 1;
-}
-
-XID
-MitCheckCookie (
- unsigned short data_length,
- char *data,
- ClientPtr client,
- char **reason)
-{
- struct auth *auth;
-
- for (auth = mit_auth; auth; auth=auth->next) {
- if (data_length == auth->len &&
- memcmp (data, auth->data, (int) data_length) == 0)
- return auth->id;
- }
- *reason = "Invalid MIT-MAGIC-COOKIE-1 key";
- return (XID) -1;
-}
-
-int
-MitResetCookie (void)
-{
- struct auth *auth, *next;
-
- for (auth = mit_auth; auth; auth=next) {
- next = auth->next;
- xfree (auth->data);
- xfree (auth);
- }
- mit_auth = 0;
- return 0;
-}
-
-XID
-MitToID (
- unsigned short data_length,
- char *data)
-{
- struct auth *auth;
-
- for (auth = mit_auth; auth; auth=auth->next) {
- if (data_length == auth->len &&
- memcmp (data, auth->data, data_length) == 0)
- return auth->id;
- }
- return (XID) -1;
-}
-
-int
-MitFromID (
- XID id,
- unsigned short *data_lenp,
- char **datap)
-{
- struct auth *auth;
-
- for (auth = mit_auth; auth; auth=auth->next) {
- if (id == auth->id) {
- *data_lenp = auth->len;
- *datap = auth->data;
- return 1;
- }
- }
- return 0;
-}
-
-int
-MitRemoveCookie (
- unsigned short data_length,
- char *data)
-{
- struct auth *auth, *prev;
-
- prev = 0;
- for (auth = mit_auth; auth; prev = auth, auth=auth->next) {
- if (data_length == auth->len &&
- memcmp (data, auth->data, data_length) == 0)
- {
- if (prev)
- prev->next = auth->next;
- else
- mit_auth = auth->next;
- xfree (auth->data);
- xfree (auth);
- return 1;
- }
- }
- return 0;
-}
-
-#ifdef XCSECURITY
-
-static char cookie[16]; /* 128 bits */
-
-XID
-MitGenerateCookie (
- unsigned data_length,
- char *data,
- XID id,
- unsigned *data_length_return,
- char **data_return)
-{
- int i = 0;
- int status;
-
- while (data_length--)
- {
- cookie[i++] += *data++;
- if (i >= sizeof (cookie)) i = 0;
- }
- GenerateRandomData(sizeof (cookie), cookie);
- status = MitAddCookie(sizeof (cookie), cookie, id);
- if (!status)
- {
- id = -1;
- }
- else
- {
- *data_return = cookie;
- *data_length_return = sizeof (cookie);
- }
- return id;
-}
-
-#endif /* XCSECURITY */
+/*
+
+Copyright 1988, 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.
+
+*/
+
+/*
+ * MIT-MAGIC-COOKIE-1 authorization scheme
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h>
+#include "os.h"
+#include "osdep.h"
+#include "dixstruct.h"
+
+static struct auth {
+ struct auth *next;
+ unsigned short len;
+ char *data;
+ XID id;
+} *mit_auth;
+
+int
+MitAddCookie (
+ unsigned short data_length,
+ const char *data,
+ XID id)
+{
+ struct auth *new;
+
+ new = xalloc (sizeof (struct auth));
+ if (!new)
+ return 0;
+ new->data = xalloc ((unsigned) data_length);
+ if (!new->data) {
+ xfree(new);
+ return 0;
+ }
+ new->next = mit_auth;
+ mit_auth = new;
+ memmove(new->data, data, (int) data_length);
+ new->len = data_length;
+ new->id = id;
+ return 1;
+}
+
+XID
+MitCheckCookie (
+ unsigned short data_length,
+ const char *data,
+ ClientPtr client,
+ char **reason)
+{
+ struct auth *auth;
+
+ for (auth = mit_auth; auth; auth=auth->next) {
+ if (data_length == auth->len &&
+ memcmp (data, auth->data, (int) data_length) == 0)
+ return auth->id;
+ }
+ *reason = "Invalid MIT-MAGIC-COOKIE-1 key";
+ return (XID) -1;
+}
+
+int
+MitResetCookie (void)
+{
+ struct auth *auth, *next;
+
+ for (auth = mit_auth; auth; auth=next) {
+ next = auth->next;
+ xfree (auth->data);
+ xfree (auth);
+ }
+ mit_auth = 0;
+ return 0;
+}
+
+XID
+MitToID (
+ unsigned short data_length,
+ char *data)
+{
+ struct auth *auth;
+
+ for (auth = mit_auth; auth; auth=auth->next) {
+ if (data_length == auth->len &&
+ memcmp (data, auth->data, data_length) == 0)
+ return auth->id;
+ }
+ return (XID) -1;
+}
+
+int
+MitFromID (
+ XID id,
+ unsigned short *data_lenp,
+ char **datap)
+{
+ struct auth *auth;
+
+ for (auth = mit_auth; auth; auth=auth->next) {
+ if (id == auth->id) {
+ *data_lenp = auth->len;
+ *datap = auth->data;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+MitRemoveCookie (
+ unsigned short data_length,
+ const char *data)
+{
+ struct auth *auth, *prev;
+
+ prev = 0;
+ for (auth = mit_auth; auth; prev = auth, auth=auth->next) {
+ if (data_length == auth->len &&
+ memcmp (data, auth->data, data_length) == 0)
+ {
+ if (prev)
+ prev->next = auth->next;
+ else
+ mit_auth = auth->next;
+ xfree (auth->data);
+ xfree (auth);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#ifdef XCSECURITY
+
+static char cookie[16]; /* 128 bits */
+
+XID
+MitGenerateCookie (
+ unsigned data_length,
+ const char *data,
+ XID id,
+ unsigned *data_length_return,
+ char **data_return)
+{
+ int i = 0;
+ int status;
+
+ while (data_length--)
+ {
+ cookie[i++] += *data++;
+ if (i >= sizeof (cookie)) i = 0;
+ }
+ GenerateRandomData(sizeof (cookie), cookie);
+ status = MitAddCookie(sizeof (cookie), cookie, id);
+ if (!status)
+ {
+ id = -1;
+ }
+ else
+ {
+ *data_return = cookie;
+ *data_length_return = sizeof (cookie);
+ }
+ return id;
+}
+
+#endif /* XCSECURITY */
diff --git a/xorg-server/os/osdep.h b/xorg-server/os/osdep.h
index fda1edf72..32b4a6763 100644
--- a/xorg-server/os/osdep.h
+++ b/xorg-server/os/osdep.h
@@ -114,7 +114,8 @@ SOFTWARE.
#if defined(XDMCP) || defined(HASXDMAUTH)
typedef Bool (*ValidatorFunc)(ARRAY8Ptr Auth, ARRAY8Ptr Data, int packet_type);
typedef Bool (*GeneratorFunc)(ARRAY8Ptr Auth, ARRAY8Ptr Data, int packet_type);
-typedef Bool (*AddAuthorFunc)(unsigned name_length, char *name, unsigned data_length, char *data);
+typedef Bool (*AddAuthorFunc)(unsigned name_length, const char *name,
+ unsigned data_length, char *data);
#endif
typedef struct _connectionInput {
@@ -138,19 +139,19 @@ struct _osComm;
#define AuthInitArgs void
typedef void (*AuthInitFunc) (AuthInitArgs);
-#define AuthAddCArgs unsigned short data_length, char *data, XID id
+#define AuthAddCArgs unsigned short data_length, const char *data, XID id
typedef int (*AuthAddCFunc) (AuthAddCArgs);
-#define AuthCheckArgs unsigned short data_length, char *data, ClientPtr client, char **reason
+#define AuthCheckArgs unsigned short data_length, const char *data, ClientPtr client, char **reason
typedef XID (*AuthCheckFunc) (AuthCheckArgs);
#define AuthFromIDArgs XID id, unsigned short *data_lenp, char **datap
typedef int (*AuthFromIDFunc) (AuthFromIDArgs);
-#define AuthGenCArgs unsigned data_length, char *data, XID id, unsigned *data_length_return, char **data_return
+#define AuthGenCArgs unsigned data_length, const char *data, XID id, unsigned *data_length_return, char **data_return
typedef XID (*AuthGenCFunc) (AuthGenCArgs);
-#define AuthRemCArgs unsigned short data_length, char *data
+#define AuthRemCArgs unsigned short data_length, const char *data
typedef int (*AuthRemCFunc) (AuthRemCArgs);
#define AuthRstCArgs void
@@ -254,29 +255,29 @@ extern void XdmcpUseMsg (void);
extern int XdmcpOptions(int argc, char **argv, int i);
extern void XdmcpRegisterConnection (
int type,
- char *address,
+ const char *address,
int addrlen);
extern void XdmcpRegisterAuthorizations (void);
-extern void XdmcpRegisterAuthorization (char *name, int namelen);
+extern void XdmcpRegisterAuthorization (const char *name, int namelen);
extern void XdmcpInit (void);
extern void XdmcpReset (void);
extern void XdmcpOpenDisplay(int sock);
extern void XdmcpCloseDisplay(int sock);
extern void XdmcpRegisterAuthentication (
- char *name,
+ const char *name,
int namelen,
- char *data,
+ const char *data,
int datalen,
ValidatorFunc Validator,
GeneratorFunc Generator,
AddAuthorFunc AddAuth);
struct sockaddr_in;
-extern void XdmcpRegisterBroadcastAddress (struct sockaddr_in *addr);
+extern void XdmcpRegisterBroadcastAddress (const struct sockaddr_in *addr);
#endif
#ifdef HASXDMAUTH
-extern void XdmAuthenticationInit (char *cookie, int cookie_length);
+extern void XdmAuthenticationInit (const char *cookie, int cookie_length);
#endif
#endif /* _OSDEP_H_ */
diff --git a/xorg-server/os/rpcauth.c b/xorg-server/os/rpcauth.c
index 5ddbe210b..a63304375 100644
--- a/xorg-server/os/rpcauth.c
+++ b/xorg-server/os/rpcauth.c
@@ -1,193 +1,193 @@
-/*
-
-Copyright 1991, 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.
-
-*/
-
-/*
- * SUN-DES-1 authentication mechanism
- * Author: Mayank Choudhary, Sun Microsystems
- */
-
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifdef SECURE_RPC
-
-#include <X11/X.h>
-#include <X11/Xauth.h>
-#include "misc.h"
-#include "os.h"
-#include "osdep.h"
-#include "dixstruct.h"
-
-#include <rpc/rpc.h>
-
-#ifdef sun
-/* <rpc/auth.h> only includes this if _KERNEL is #defined... */
-extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *);
-#endif
-
-static enum auth_stat why;
-
-static char *
-authdes_ezdecode(char *inmsg, int len)
-{
- struct rpc_msg msg;
- char cred_area[MAX_AUTH_BYTES];
- char verf_area[MAX_AUTH_BYTES];
- char *temp_inmsg;
- struct svc_req r;
- bool_t res0, res1;
- XDR xdr;
- SVCXPRT xprt;
-
- temp_inmsg = xalloc(len);
- memmove(temp_inmsg, inmsg, len);
-
- memset((char *)&msg, 0, sizeof(msg));
- memset((char *)&r, 0, sizeof(r));
- memset(cred_area, 0, sizeof(cred_area));
- memset(verf_area, 0, sizeof(verf_area));
-
- msg.rm_call.cb_cred.oa_base = cred_area;
- msg.rm_call.cb_verf.oa_base = verf_area;
- why = AUTH_FAILED;
- xdrmem_create(&xdr, temp_inmsg, len, XDR_DECODE);
-
- if ((r.rq_clntcred = xalloc(MAX_AUTH_BYTES)) == NULL)
- goto bad1;
- r.rq_xprt = &xprt;
-
- /* decode into msg */
- res0 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_cred));
- res1 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_verf));
- if ( ! (res0 && res1) )
- goto bad2;
-
- /* do the authentication */
-
- r.rq_cred = msg.rm_call.cb_cred; /* read by opaque stuff */
- if (r.rq_cred.oa_flavor != AUTH_DES) {
- why = AUTH_TOOWEAK;
- goto bad2;
- }
-#ifdef SVR4
- if ((why = __authenticate(&r, &msg)) != AUTH_OK) {
-#else
- if ((why = _authenticate(&r, &msg)) != AUTH_OK) {
-#endif
- goto bad2;
- }
- return (((struct authdes_cred *) r.rq_clntcred)->adc_fullname.name);
-
-bad2:
- xfree(r.rq_clntcred);
-bad1:
- return ((char *)0); /* ((struct authdes_cred *) NULL); */
-}
-
-static XID rpc_id = (XID) ~0L;
-
-static Bool
-CheckNetName (
- unsigned char *addr,
- short len,
- pointer closure
-)
-{
- return (len == strlen ((char *) closure) &&
- strncmp ((char *) addr, (char *) closure, len) == 0);
-}
-
-static char rpc_error[MAXNETNAMELEN+50];
-
-_X_HIDDEN XID
-SecureRPCCheck (unsigned short data_length, char *data,
- ClientPtr client, char **reason)
-{
- char *fullname;
-
- if (rpc_id == (XID) ~0L) {
- *reason = "Secure RPC authorization not initialized";
- } else {
- fullname = authdes_ezdecode(data, data_length);
- if (fullname == (char *)0) {
- sprintf(rpc_error, "Unable to authenticate secure RPC client (why=%d)", why);
- *reason = rpc_error;
- } else {
- if (ForEachHostInFamily (FamilyNetname, CheckNetName, fullname))
- return rpc_id;
- sprintf(rpc_error, "Principal \"%s\" is not authorized to connect",
- fullname);
- *reason = rpc_error;
- }
- }
- return (XID) ~0L;
-}
-
-_X_HIDDEN void
-SecureRPCInit (void)
-{
- if (rpc_id == ~0L)
- AddAuthorization (9, "SUN-DES-1", 0, (char *) 0);
-}
-
-_X_HIDDEN int
-SecureRPCAdd (unsigned short data_length, char *data, XID id)
-{
- if (data_length)
- AddHost ((pointer) 0, FamilyNetname, data_length, data);
- rpc_id = id;
- return 1;
-}
-
-_X_HIDDEN int
-SecureRPCReset (void)
-{
- rpc_id = (XID) ~0L;
- return 1;
-}
-
-_X_HIDDEN XID
-SecureRPCToID (unsigned short data_length, char *data)
-{
- return rpc_id;
-}
-
-_X_HIDDEN int
-SecureRPCFromID (XID id, unsigned short *data_lenp, char **datap)
-{
- return 0;
-}
-
-_X_HIDDEN int
-SecureRPCRemove (unsigned short data_length, char *data)
-{
- return 0;
-}
-#endif /* SECURE_RPC */
+/*
+
+Copyright 1991, 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.
+
+*/
+
+/*
+ * SUN-DES-1 authentication mechanism
+ * Author: Mayank Choudhary, Sun Microsystems
+ */
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef SECURE_RPC
+
+#include <X11/X.h>
+#include <X11/Xauth.h>
+#include "misc.h"
+#include "os.h"
+#include "osdep.h"
+#include "dixstruct.h"
+
+#include <rpc/rpc.h>
+
+#ifdef sun
+/* <rpc/auth.h> only includes this if _KERNEL is #defined... */
+extern bool_t xdr_opaque_auth(XDR *, struct opaque_auth *);
+#endif
+
+static enum auth_stat why;
+
+static char *
+authdes_ezdecode(const char *inmsg, int len)
+{
+ struct rpc_msg msg;
+ char cred_area[MAX_AUTH_BYTES];
+ char verf_area[MAX_AUTH_BYTES];
+ char *temp_inmsg;
+ struct svc_req r;
+ bool_t res0, res1;
+ XDR xdr;
+ SVCXPRT xprt;
+
+ temp_inmsg = xalloc(len);
+ memmove(temp_inmsg, inmsg, len);
+
+ memset((char *)&msg, 0, sizeof(msg));
+ memset((char *)&r, 0, sizeof(r));
+ memset(cred_area, 0, sizeof(cred_area));
+ memset(verf_area, 0, sizeof(verf_area));
+
+ msg.rm_call.cb_cred.oa_base = cred_area;
+ msg.rm_call.cb_verf.oa_base = verf_area;
+ why = AUTH_FAILED;
+ xdrmem_create(&xdr, temp_inmsg, len, XDR_DECODE);
+
+ if ((r.rq_clntcred = xalloc(MAX_AUTH_BYTES)) == NULL)
+ goto bad1;
+ r.rq_xprt = &xprt;
+
+ /* decode into msg */
+ res0 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_cred));
+ res1 = xdr_opaque_auth(&xdr, &(msg.rm_call.cb_verf));
+ if ( ! (res0 && res1) )
+ goto bad2;
+
+ /* do the authentication */
+
+ r.rq_cred = msg.rm_call.cb_cred; /* read by opaque stuff */
+ if (r.rq_cred.oa_flavor != AUTH_DES) {
+ why = AUTH_TOOWEAK;
+ goto bad2;
+ }
+#ifdef SVR4
+ if ((why = __authenticate(&r, &msg)) != AUTH_OK) {
+#else
+ if ((why = _authenticate(&r, &msg)) != AUTH_OK) {
+#endif
+ goto bad2;
+ }
+ return (((struct authdes_cred *) r.rq_clntcred)->adc_fullname.name);
+
+bad2:
+ xfree(r.rq_clntcred);
+bad1:
+ return ((char *)0); /* ((struct authdes_cred *) NULL); */
+}
+
+static XID rpc_id = (XID) ~0L;
+
+static Bool
+CheckNetName (
+ unsigned char *addr,
+ short len,
+ pointer closure
+)
+{
+ return (len == strlen ((char *) closure) &&
+ strncmp ((char *) addr, (char *) closure, len) == 0);
+}
+
+static char rpc_error[MAXNETNAMELEN+50];
+
+_X_HIDDEN XID
+SecureRPCCheck (unsigned short data_length, const char *data,
+ ClientPtr client, char **reason)
+{
+ char *fullname;
+
+ if (rpc_id == (XID) ~0L) {
+ *reason = "Secure RPC authorization not initialized";
+ } else {
+ fullname = authdes_ezdecode(data, data_length);
+ if (fullname == (char *)0) {
+ sprintf(rpc_error, "Unable to authenticate secure RPC client (why=%d)", why);
+ *reason = rpc_error;
+ } else {
+ if (ForEachHostInFamily (FamilyNetname, CheckNetName, fullname))
+ return rpc_id;
+ sprintf(rpc_error, "Principal \"%s\" is not authorized to connect",
+ fullname);
+ *reason = rpc_error;
+ }
+ }
+ return (XID) ~0L;
+}
+
+_X_HIDDEN void
+SecureRPCInit (void)
+{
+ if (rpc_id == ~0L)
+ AddAuthorization (9, "SUN-DES-1", 0, (char *) 0);
+}
+
+_X_HIDDEN int
+SecureRPCAdd (unsigned short data_length, const char *data, XID id)
+{
+ if (data_length)
+ AddHost ((pointer) 0, FamilyNetname, data_length, data);
+ rpc_id = id;
+ return 1;
+}
+
+_X_HIDDEN int
+SecureRPCReset (void)
+{
+ rpc_id = (XID) ~0L;
+ return 1;
+}
+
+_X_HIDDEN XID
+SecureRPCToID (unsigned short data_length, char *data)
+{
+ return rpc_id;
+}
+
+_X_HIDDEN int
+SecureRPCFromID (XID id, unsigned short *data_lenp, char **datap)
+{
+ return 0;
+}
+
+_X_HIDDEN int
+SecureRPCRemove (unsigned short data_length, const char *data)
+{
+ return 0;
+}
+#endif /* SECURE_RPC */
diff --git a/xorg-server/os/xdmauth.c b/xorg-server/os/xdmauth.c
index e19e4f93d..7834b56f8 100644
--- a/xorg-server/os/xdmauth.c
+++ b/xorg-server/os/xdmauth.c
@@ -1,499 +1,499 @@
-/*
-
-Copyright 1988, 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.
-
-*/
-
-/*
- * XDM-AUTHENTICATION-1 (XDMCP authentication) and
- * XDM-AUTHORIZATION-1 (client authorization) protocols
- *
- * Author: Keith Packard, MIT X Consortium
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include <stdio.h>
-#include <X11/X.h>
-#define XSERV_t
-#define TRANS_SERVER
-#define TRANS_REOPEN
-#include <X11/Xtrans/Xtrans.h>
-#include "os.h"
-#include "osdep.h"
-#include "dixstruct.h"
-
-#ifdef HASXDMAUTH
-
-static Bool authFromXDMCP;
-
-#ifdef XDMCP
-#include <X11/Xmd.h>
-#undef REQUEST
-#include <X11/Xdmcp.h>
-
-/* XDM-AUTHENTICATION-1 */
-
-static XdmAuthKeyRec privateKey;
-static char XdmAuthenticationName[] = "XDM-AUTHENTICATION-1";
-#define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1)
-static XdmAuthKeyRec rho;
-
-static Bool
-XdmAuthenticationValidator (ARRAY8Ptr privateData, ARRAY8Ptr incomingData,
- xdmOpCode packet_type)
-{
- XdmAuthKeyPtr incoming;
-
- XdmcpUnwrap (incomingData->data, (unsigned char *)&privateKey,
- incomingData->data,incomingData->length);
- if (packet_type == ACCEPT) {
- if (incomingData->length != 8)
- return FALSE;
- incoming = (XdmAuthKeyPtr) incomingData->data;
- XdmcpDecrementKey (incoming);
- return XdmcpCompareKeys (incoming, &rho);
- }
- return FALSE;
-}
-
-static Bool
-XdmAuthenticationGenerator (ARRAY8Ptr privateData, ARRAY8Ptr outgoingData,
- xdmOpCode packet_type)
-{
- outgoingData->length = 0;
- outgoingData->data = 0;
- if (packet_type == REQUEST) {
- if (XdmcpAllocARRAY8 (outgoingData, 8))
- XdmcpWrap ((unsigned char *)&rho, (unsigned char *)&privateKey,
- outgoingData->data, 8);
- }
- return TRUE;
-}
-
-static Bool
-XdmAuthenticationAddAuth (int name_len, char *name,
- int data_len, char *data)
-{
- Bool ret;
- XdmcpUnwrap ((unsigned char *)data, (unsigned char *)&privateKey,
- (unsigned char *)data, data_len);
- authFromXDMCP = TRUE;
- ret = AddAuthorization (name_len, name, data_len, data);
- authFromXDMCP = FALSE;
- return ret;
-}
-
-
-#define atox(c) ('0' <= c && c <= '9' ? c - '0' : \
- 'a' <= c && c <= 'f' ? c - 'a' + 10 : \
- 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
-
-static int
-HexToBinary (char *in, char *out, int len)
-{
- int top, bottom;
-
- while (len > 0)
- {
- top = atox(in[0]);
- if (top == -1)
- return 0;
- bottom = atox(in[1]);
- if (bottom == -1)
- return 0;
- *out++ = (top << 4) | bottom;
- in += 2;
- len -= 2;
- }
- if (len)
- return 0;
- *out++ = '\0';
- return 1;
-}
-
-void
-XdmAuthenticationInit (char *cookie, int cookie_len)
-{
- bzero (privateKey.data, 8);
- if (!strncmp (cookie, "0x", 2) || !strncmp (cookie, "0X", 2))
- {
- if (cookie_len > 2 + 2 * 8)
- cookie_len = 2 + 2 * 8;
- HexToBinary (cookie + 2, (char *)privateKey.data, cookie_len - 2);
- }
- else
- {
- if (cookie_len > 7)
- cookie_len = 7;
- memmove (privateKey.data + 1, cookie, cookie_len);
- }
- XdmcpGenerateKey (&rho);
- XdmcpRegisterAuthentication (XdmAuthenticationName, XdmAuthenticationNameLen,
- (char *)&rho,
- sizeof (rho),
- (ValidatorFunc)XdmAuthenticationValidator,
- (GeneratorFunc)XdmAuthenticationGenerator,
- (AddAuthorFunc)XdmAuthenticationAddAuth);
-}
-
-#endif /* XDMCP */
-
-/* XDM-AUTHORIZATION-1 */
-typedef struct _XdmAuthorization {
- struct _XdmAuthorization *next;
- XdmAuthKeyRec rho;
- XdmAuthKeyRec key;
- XID id;
-} XdmAuthorizationRec, *XdmAuthorizationPtr;
-
-static XdmAuthorizationPtr xdmAuth;
-
-typedef struct _XdmClientAuth {
- struct _XdmClientAuth *next;
- XdmAuthKeyRec rho;
- char client[6];
- long time;
-} XdmClientAuthRec, *XdmClientAuthPtr;
-
-static XdmClientAuthPtr xdmClients;
-static long clockOffset;
-static Bool gotClock;
-
-#define TwentyMinutes (20 * 60)
-#define TwentyFiveMinutes (25 * 60)
-
-static Bool
-XdmClientAuthCompare (XdmClientAuthPtr a, XdmClientAuthPtr b)
-{
- int i;
-
- if (!XdmcpCompareKeys (&a->rho, &b->rho))
- return FALSE;
- for (i = 0; i < 6; i++)
- if (a->client[i] != b->client[i])
- return FALSE;
- return a->time == b->time;
-}
-
-static void
-XdmClientAuthDecode (unsigned char *plain, XdmClientAuthPtr auth)
-{
- int i, j;
-
- j = 0;
- for (i = 0; i < 8; i++)
- {
- auth->rho.data[i] = plain[j];
- ++j;
- }
- for (i = 0; i < 6; i++)
- {
- auth->client[i] = plain[j];
- ++j;
- }
- auth->time = 0;
- for (i = 0; i < 4; i++)
- {
- auth->time |= plain[j] << ((3 - i) << 3);
- j++;
- }
-}
-
-static void
-XdmClientAuthTimeout (long now)
-{
- XdmClientAuthPtr client, next, prev;
-
- prev = 0;
- for (client = xdmClients; client; client=next)
- {
- next = client->next;
- if (abs (now - client->time) > TwentyFiveMinutes)
- {
- if (prev)
- prev->next = next;
- else
- xdmClients = next;
- xfree (client);
- }
- else
- prev = client;
- }
-}
-
-static XdmClientAuthPtr
-XdmAuthorizationValidate (unsigned char *plain, int length,
- XdmAuthKeyPtr rho, ClientPtr xclient, char **reason)
-{
- XdmClientAuthPtr client, existing;
- long now;
- int i;
-
- if (length != (192 / 8)) {
- if (reason)
- *reason = "Bad XDM authorization key length";
- return NULL;
- }
- client = xalloc (sizeof (XdmClientAuthRec));
- if (!client)
- return NULL;
- XdmClientAuthDecode (plain, client);
- if (!XdmcpCompareKeys (&client->rho, rho))
- {
- xfree (client);
- if (reason)
- *reason = "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)";
- return NULL;
- }
- for (i = 18; i < 24; i++)
- if (plain[i] != 0) {
- xfree (client);
- if (reason)
- *reason = "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)";
- return NULL;
- }
- if (xclient) {
- int family, addr_len;
- Xtransaddr *addr;
-
- if (_XSERVTransGetPeerAddr(((OsCommPtr)xclient->osPrivate)->trans_conn,
- &family, &addr_len, &addr) == 0
- && _XSERVTransConvertAddress(&family, &addr_len, &addr) == 0) {
-#if defined(TCPCONN) || defined(STREAMSCONN)
- if (family == FamilyInternet &&
- memcmp((char *)addr, client->client, 4) != 0) {
- xfree (client);
- xfree (addr);
- if (reason)
- *reason = "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)";
- return NULL;
-
- }
-#endif
- xfree (addr);
- }
- }
- now = time(0);
- if (!gotClock)
- {
- clockOffset = client->time - now;
- gotClock = TRUE;
- }
- now += clockOffset;
- XdmClientAuthTimeout (now);
- if (abs (client->time - now) > TwentyMinutes)
- {
- xfree (client);
- if (reason)
- *reason = "Excessive XDM-AUTHORIZATION-1 time offset";
- return NULL;
- }
- for (existing = xdmClients; existing; existing=existing->next)
- {
- if (XdmClientAuthCompare (existing, client))
- {
- xfree (client);
- if (reason)
- *reason = "XDM authorization key matches an existing client!";
- return NULL;
- }
- }
- return client;
-}
-
-int
-XdmAddCookie (unsigned short data_length, char *data, XID id)
-{
- XdmAuthorizationPtr new;
- unsigned char *rho_bits, *key_bits;
-
- switch (data_length)
- {
- case 16: /* auth from files is 16 bytes long */
-#ifdef XDMCP
- if (authFromXDMCP)
- {
- /* R5 xdm sent bogus authorization data in the accept packet,
- * but we can recover */
- rho_bits = rho.data;
- key_bits = (unsigned char *) data;
- key_bits[0] = '\0';
- }
- else
-#endif
- {
- rho_bits = (unsigned char *) data;
- key_bits = (unsigned char *) (data + 8);
- }
- break;
-#ifdef XDMCP
- case 8: /* auth from XDMCP is 8 bytes long */
- rho_bits = rho.data;
- key_bits = (unsigned char *) data;
- break;
-#endif
- default:
- return 0;
- }
- /* the first octet of the key must be zero */
- if (key_bits[0] != '\0')
- return 0;
- new = xalloc (sizeof (XdmAuthorizationRec));
- if (!new)
- return 0;
- new->next = xdmAuth;
- xdmAuth = new;
- memmove (new->key.data, key_bits, (int) 8);
- memmove (new->rho.data, rho_bits, (int) 8);
- new->id = id;
- return 1;
-}
-
-XID
-XdmCheckCookie (unsigned short cookie_length, char *cookie,
- ClientPtr xclient, char **reason)
-{
- XdmAuthorizationPtr auth;
- XdmClientAuthPtr client;
- unsigned char *plain;
-
- /* Auth packets must be a multiple of 8 bytes long */
- if (cookie_length & 7)
- return (XID) -1;
- plain = xalloc (cookie_length);
- if (!plain)
- return (XID) -1;
- for (auth = xdmAuth; auth; auth=auth->next) {
- XdmcpUnwrap ((unsigned char *)cookie, (unsigned char *)&auth->key, plain, cookie_length);
- if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, xclient, reason)) != NULL)
- {
- client->next = xdmClients;
- xdmClients = client;
- xfree (plain);
- return auth->id;
- }
- }
- xfree (plain);
- return (XID) -1;
-}
-
-int
-XdmResetCookie (void)
-{
- XdmAuthorizationPtr auth, next_auth;
- XdmClientAuthPtr client, next_client;
-
- for (auth = xdmAuth; auth; auth=next_auth)
- {
- next_auth = auth->next;
- xfree (auth);
- }
- xdmAuth = 0;
- for (client = xdmClients; client; client=next_client)
- {
- next_client = client->next;
- xfree (client);
- }
- xdmClients = (XdmClientAuthPtr) 0;
- return 1;
-}
-
-XID
-XdmToID (unsigned short cookie_length, char *cookie)
-{
- XdmAuthorizationPtr auth;
- XdmClientAuthPtr client;
- unsigned char *plain;
-
- plain = xalloc (cookie_length);
- if (!plain)
- return (XID) -1;
- for (auth = xdmAuth; auth; auth=auth->next) {
- XdmcpUnwrap ((unsigned char *)cookie, (unsigned char *)&auth->key, plain, cookie_length);
- if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, NULL, NULL)) != NULL)
- {
- xfree (client);
- xfree (cookie);
- xfree (plain);
- return auth->id;
- }
- }
- xfree (cookie);
- xfree (plain);
- return (XID) -1;
-}
-
-int
-XdmFromID (XID id, unsigned short *data_lenp, char **datap)
-{
- XdmAuthorizationPtr auth;
-
- for (auth = xdmAuth; auth; auth=auth->next) {
- if (id == auth->id) {
- *data_lenp = 16;
- *datap = (char *) &auth->rho;
- return 1;
- }
- }
- return 0;
-}
-
-int
-XdmRemoveCookie (unsigned short data_length, char *data)
-{
- XdmAuthorizationPtr auth;
- XdmAuthKeyPtr key_bits, rho_bits;
-
- switch (data_length)
- {
- case 16:
- rho_bits = (XdmAuthKeyPtr) data;
- key_bits = (XdmAuthKeyPtr) (data + 8);
- break;
-#ifdef XDMCP
- case 8:
- rho_bits = &rho;
- key_bits = (XdmAuthKeyPtr) data;
- break;
-#endif
- default:
- return 0;
- }
- for (auth = xdmAuth; auth; auth=auth->next) {
- if (XdmcpCompareKeys (rho_bits, &auth->rho) &&
- XdmcpCompareKeys (key_bits, &auth->key))
- {
- xdmAuth = auth->next;
- xfree (auth);
- return 1;
- }
- }
- return 0;
-}
-
-#endif
+/*
+
+Copyright 1988, 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.
+
+*/
+
+/*
+ * XDM-AUTHENTICATION-1 (XDMCP authentication) and
+ * XDM-AUTHORIZATION-1 (client authorization) protocols
+ *
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <stdio.h>
+#include <X11/X.h>
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+#include "os.h"
+#include "osdep.h"
+#include "dixstruct.h"
+
+#ifdef HASXDMAUTH
+
+static Bool authFromXDMCP;
+
+#ifdef XDMCP
+#include <X11/Xmd.h>
+#undef REQUEST
+#include <X11/Xdmcp.h>
+
+/* XDM-AUTHENTICATION-1 */
+
+static XdmAuthKeyRec privateKey;
+static char XdmAuthenticationName[] = "XDM-AUTHENTICATION-1";
+#define XdmAuthenticationNameLen (sizeof XdmAuthenticationName - 1)
+static XdmAuthKeyRec rho;
+
+static Bool
+XdmAuthenticationValidator (ARRAY8Ptr privateData, ARRAY8Ptr incomingData,
+ xdmOpCode packet_type)
+{
+ XdmAuthKeyPtr incoming;
+
+ XdmcpUnwrap (incomingData->data, (unsigned char *)&privateKey,
+ incomingData->data,incomingData->length);
+ if (packet_type == ACCEPT) {
+ if (incomingData->length != 8)
+ return FALSE;
+ incoming = (XdmAuthKeyPtr) incomingData->data;
+ XdmcpDecrementKey (incoming);
+ return XdmcpCompareKeys (incoming, &rho);
+ }
+ return FALSE;
+}
+
+static Bool
+XdmAuthenticationGenerator (ARRAY8Ptr privateData, ARRAY8Ptr outgoingData,
+ xdmOpCode packet_type)
+{
+ outgoingData->length = 0;
+ outgoingData->data = 0;
+ if (packet_type == REQUEST) {
+ if (XdmcpAllocARRAY8 (outgoingData, 8))
+ XdmcpWrap ((unsigned char *)&rho, (unsigned char *)&privateKey,
+ outgoingData->data, 8);
+ }
+ return TRUE;
+}
+
+static Bool
+XdmAuthenticationAddAuth (int name_len, const char *name,
+ int data_len, char *data)
+{
+ Bool ret;
+ XdmcpUnwrap ((unsigned char *)data, (unsigned char *)&privateKey,
+ (unsigned char *)data, data_len);
+ authFromXDMCP = TRUE;
+ ret = AddAuthorization (name_len, name, data_len, data);
+ authFromXDMCP = FALSE;
+ return ret;
+}
+
+
+#define atox(c) ('0' <= c && c <= '9' ? c - '0' : \
+ 'a' <= c && c <= 'f' ? c - 'a' + 10 : \
+ 'A' <= c && c <= 'F' ? c - 'A' + 10 : -1)
+
+static int
+HexToBinary (const char *in, char *out, int len)
+{
+ int top, bottom;
+
+ while (len > 0)
+ {
+ top = atox(in[0]);
+ if (top == -1)
+ return 0;
+ bottom = atox(in[1]);
+ if (bottom == -1)
+ return 0;
+ *out++ = (top << 4) | bottom;
+ in += 2;
+ len -= 2;
+ }
+ if (len)
+ return 0;
+ *out++ = '\0';
+ return 1;
+}
+
+void
+XdmAuthenticationInit (const char *cookie, int cookie_len)
+{
+ bzero (privateKey.data, 8);
+ if (!strncmp (cookie, "0x", 2) || !strncmp (cookie, "0X", 2))
+ {
+ if (cookie_len > 2 + 2 * 8)
+ cookie_len = 2 + 2 * 8;
+ HexToBinary (cookie + 2, (char *)privateKey.data, cookie_len - 2);
+ }
+ else
+ {
+ if (cookie_len > 7)
+ cookie_len = 7;
+ memmove (privateKey.data + 1, cookie, cookie_len);
+ }
+ XdmcpGenerateKey (&rho);
+ XdmcpRegisterAuthentication (XdmAuthenticationName, XdmAuthenticationNameLen,
+ (char *)&rho,
+ sizeof (rho),
+ (ValidatorFunc)XdmAuthenticationValidator,
+ (GeneratorFunc)XdmAuthenticationGenerator,
+ (AddAuthorFunc)XdmAuthenticationAddAuth);
+}
+
+#endif /* XDMCP */
+
+/* XDM-AUTHORIZATION-1 */
+typedef struct _XdmAuthorization {
+ struct _XdmAuthorization *next;
+ XdmAuthKeyRec rho;
+ XdmAuthKeyRec key;
+ XID id;
+} XdmAuthorizationRec, *XdmAuthorizationPtr;
+
+static XdmAuthorizationPtr xdmAuth;
+
+typedef struct _XdmClientAuth {
+ struct _XdmClientAuth *next;
+ XdmAuthKeyRec rho;
+ char client[6];
+ long time;
+} XdmClientAuthRec, *XdmClientAuthPtr;
+
+static XdmClientAuthPtr xdmClients;
+static long clockOffset;
+static Bool gotClock;
+
+#define TwentyMinutes (20 * 60)
+#define TwentyFiveMinutes (25 * 60)
+
+static Bool
+XdmClientAuthCompare (const XdmClientAuthPtr a, const XdmClientAuthPtr b)
+{
+ int i;
+
+ if (!XdmcpCompareKeys (&a->rho, &b->rho))
+ return FALSE;
+ for (i = 0; i < 6; i++)
+ if (a->client[i] != b->client[i])
+ return FALSE;
+ return a->time == b->time;
+}
+
+static void
+XdmClientAuthDecode (const unsigned char *plain, XdmClientAuthPtr auth)
+{
+ int i, j;
+
+ j = 0;
+ for (i = 0; i < 8; i++)
+ {
+ auth->rho.data[i] = plain[j];
+ ++j;
+ }
+ for (i = 0; i < 6; i++)
+ {
+ auth->client[i] = plain[j];
+ ++j;
+ }
+ auth->time = 0;
+ for (i = 0; i < 4; i++)
+ {
+ auth->time |= plain[j] << ((3 - i) << 3);
+ j++;
+ }
+}
+
+static void
+XdmClientAuthTimeout (long now)
+{
+ XdmClientAuthPtr client, next, prev;
+
+ prev = 0;
+ for (client = xdmClients; client; client=next)
+ {
+ next = client->next;
+ if (abs (now - client->time) > TwentyFiveMinutes)
+ {
+ if (prev)
+ prev->next = next;
+ else
+ xdmClients = next;
+ xfree (client);
+ }
+ else
+ prev = client;
+ }
+}
+
+static XdmClientAuthPtr
+XdmAuthorizationValidate (unsigned char *plain, int length,
+ XdmAuthKeyPtr rho, ClientPtr xclient, char **reason)
+{
+ XdmClientAuthPtr client, existing;
+ long now;
+ int i;
+
+ if (length != (192 / 8)) {
+ if (reason)
+ *reason = "Bad XDM authorization key length";
+ return NULL;
+ }
+ client = xalloc (sizeof (XdmClientAuthRec));
+ if (!client)
+ return NULL;
+ XdmClientAuthDecode (plain, client);
+ if (!XdmcpCompareKeys (&client->rho, rho))
+ {
+ xfree (client);
+ if (reason)
+ *reason = "Invalid XDM-AUTHORIZATION-1 key (failed key comparison)";
+ return NULL;
+ }
+ for (i = 18; i < 24; i++)
+ if (plain[i] != 0) {
+ xfree (client);
+ if (reason)
+ *reason = "Invalid XDM-AUTHORIZATION-1 key (failed NULL check)";
+ return NULL;
+ }
+ if (xclient) {
+ int family, addr_len;
+ Xtransaddr *addr;
+
+ if (_XSERVTransGetPeerAddr(((OsCommPtr)xclient->osPrivate)->trans_conn,
+ &family, &addr_len, &addr) == 0
+ && _XSERVTransConvertAddress(&family, &addr_len, &addr) == 0) {
+#if defined(TCPCONN) || defined(STREAMSCONN)
+ if (family == FamilyInternet &&
+ memcmp((char *)addr, client->client, 4) != 0) {
+ xfree (client);
+ xfree (addr);
+ if (reason)
+ *reason = "Invalid XDM-AUTHORIZATION-1 key (failed address comparison)";
+ return NULL;
+
+ }
+#endif
+ xfree (addr);
+ }
+ }
+ now = time(0);
+ if (!gotClock)
+ {
+ clockOffset = client->time - now;
+ gotClock = TRUE;
+ }
+ now += clockOffset;
+ XdmClientAuthTimeout (now);
+ if (abs (client->time - now) > TwentyMinutes)
+ {
+ xfree (client);
+ if (reason)
+ *reason = "Excessive XDM-AUTHORIZATION-1 time offset";
+ return NULL;
+ }
+ for (existing = xdmClients; existing; existing=existing->next)
+ {
+ if (XdmClientAuthCompare (existing, client))
+ {
+ xfree (client);
+ if (reason)
+ *reason = "XDM authorization key matches an existing client!";
+ return NULL;
+ }
+ }
+ return client;
+}
+
+int
+XdmAddCookie (unsigned short data_length, const char *data, XID id)
+{
+ XdmAuthorizationPtr new;
+ unsigned char *rho_bits, *key_bits;
+
+ switch (data_length)
+ {
+ case 16: /* auth from files is 16 bytes long */
+#ifdef XDMCP
+ if (authFromXDMCP)
+ {
+ /* R5 xdm sent bogus authorization data in the accept packet,
+ * but we can recover */
+ rho_bits = rho.data;
+ key_bits = (unsigned char *) data;
+ key_bits[0] = '\0';
+ }
+ else
+#endif
+ {
+ rho_bits = (unsigned char *) data;
+ key_bits = (unsigned char *) (data + 8);
+ }
+ break;
+#ifdef XDMCP
+ case 8: /* auth from XDMCP is 8 bytes long */
+ rho_bits = rho.data;
+ key_bits = (unsigned char *) data;
+ break;
+#endif
+ default:
+ return 0;
+ }
+ /* the first octet of the key must be zero */
+ if (key_bits[0] != '\0')
+ return 0;
+ new = xalloc (sizeof (XdmAuthorizationRec));
+ if (!new)
+ return 0;
+ new->next = xdmAuth;
+ xdmAuth = new;
+ memmove (new->key.data, key_bits, (int) 8);
+ memmove (new->rho.data, rho_bits, (int) 8);
+ new->id = id;
+ return 1;
+}
+
+XID
+XdmCheckCookie (unsigned short cookie_length, const char *cookie,
+ ClientPtr xclient, char **reason)
+{
+ XdmAuthorizationPtr auth;
+ XdmClientAuthPtr client;
+ unsigned char *plain;
+
+ /* Auth packets must be a multiple of 8 bytes long */
+ if (cookie_length & 7)
+ return (XID) -1;
+ plain = xalloc (cookie_length);
+ if (!plain)
+ return (XID) -1;
+ for (auth = xdmAuth; auth; auth=auth->next) {
+ XdmcpUnwrap ((unsigned char *)cookie, (unsigned char *)&auth->key, plain, cookie_length);
+ if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, xclient, reason)) != NULL)
+ {
+ client->next = xdmClients;
+ xdmClients = client;
+ xfree (plain);
+ return auth->id;
+ }
+ }
+ xfree (plain);
+ return (XID) -1;
+}
+
+int
+XdmResetCookie (void)
+{
+ XdmAuthorizationPtr auth, next_auth;
+ XdmClientAuthPtr client, next_client;
+
+ for (auth = xdmAuth; auth; auth=next_auth)
+ {
+ next_auth = auth->next;
+ xfree (auth);
+ }
+ xdmAuth = 0;
+ for (client = xdmClients; client; client=next_client)
+ {
+ next_client = client->next;
+ xfree (client);
+ }
+ xdmClients = (XdmClientAuthPtr) 0;
+ return 1;
+}
+
+XID
+XdmToID (unsigned short cookie_length, char *cookie)
+{
+ XdmAuthorizationPtr auth;
+ XdmClientAuthPtr client;
+ unsigned char *plain;
+
+ plain = xalloc (cookie_length);
+ if (!plain)
+ return (XID) -1;
+ for (auth = xdmAuth; auth; auth=auth->next) {
+ XdmcpUnwrap ((unsigned char *)cookie, (unsigned char *)&auth->key, plain, cookie_length);
+ if ((client = XdmAuthorizationValidate (plain, cookie_length, &auth->rho, NULL, NULL)) != NULL)
+ {
+ xfree (client);
+ xfree (cookie);
+ xfree (plain);
+ return auth->id;
+ }
+ }
+ xfree (cookie);
+ xfree (plain);
+ return (XID) -1;
+}
+
+int
+XdmFromID (XID id, unsigned short *data_lenp, char **datap)
+{
+ XdmAuthorizationPtr auth;
+
+ for (auth = xdmAuth; auth; auth=auth->next) {
+ if (id == auth->id) {
+ *data_lenp = 16;
+ *datap = (char *) &auth->rho;
+ return 1;
+ }
+ }
+ return 0;
+}
+
+int
+XdmRemoveCookie (unsigned short data_length, const char *data)
+{
+ XdmAuthorizationPtr auth;
+ XdmAuthKeyPtr key_bits, rho_bits;
+
+ switch (data_length)
+ {
+ case 16:
+ rho_bits = (XdmAuthKeyPtr) data;
+ key_bits = (XdmAuthKeyPtr) (data + 8);
+ break;
+#ifdef XDMCP
+ case 8:
+ rho_bits = &rho;
+ key_bits = (XdmAuthKeyPtr) data;
+ break;
+#endif
+ default:
+ return 0;
+ }
+ for (auth = xdmAuth; auth; auth=auth->next) {
+ if (XdmcpCompareKeys (rho_bits, &auth->rho) &&
+ XdmcpCompareKeys (key_bits, &auth->key))
+ {
+ xdmAuth = auth->next;
+ xfree (auth);
+ return 1;
+ }
+ }
+ return 0;
+}
+
+#endif
diff --git a/xorg-server/os/xdmcp.c b/xorg-server/os/xdmcp.c
index d6447e50a..ca890871e 100644
--- a/xorg-server/os/xdmcp.c
+++ b/xorg-server/os/xdmcp.c
@@ -1,1666 +1,1666 @@
-/*
- * Copyright 1989 Network Computing Devices, Inc., Mountain View, California.
- *
- * 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 N.C.D. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. N.C.D. makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#ifdef WIN32
-#include <X11/Xwinsock.h>
-#endif
-
-#include <X11/Xos.h>
-
-#if !defined(WIN32)
-#include <sys/param.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netdb.h>
-#endif
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <X11/X.h>
-#include <X11/Xmd.h>
-#include "misc.h"
-#include <X11/Xpoll.h>
-#include "osdep.h"
-#include "input.h"
-#include "dixstruct.h"
-#include "opaque.h"
-#include "site.h"
-
-#ifdef STREAMSCONN
-#include <tiuser.h>
-#include <netconfig.h>
-#include <netdir.h>
-#endif
-
-#ifdef XDMCP
-#undef REQUEST
-
-#ifdef XDMCP_NO_IPV6
-#undef IPv6
-#endif
-
-#include <X11/Xdmcp.h>
-
-#define X_INCLUDE_NETDB_H
-#include <X11/Xos_r.h>
-
-static char *defaultDisplayClass = COMPILEDDISPLAYCLASS;
-
-static int xdmcpSocket, sessionSocket;
-static xdmcp_states state;
-#if defined(IPv6) && defined(AF_INET6)
-static int xdmcpSocket6;
-static struct sockaddr_storage req_sockaddr;
-#else
-static struct sockaddr_in req_sockaddr;
-#endif
-static int req_socklen;
-static CARD32 SessionID;
-static CARD32 timeOutTime;
-static int timeOutRtx;
-static CARD32 defaultKeepaliveDormancy = XDM_DEF_DORMANCY;
-static CARD32 keepaliveDormancy = XDM_DEF_DORMANCY;
-static CARD16 DisplayNumber;
-static xdmcp_states XDM_INIT_STATE = XDM_OFF;
-#ifdef HASXDMAUTH
-static char *xdmAuthCookie;
-#endif
-
-static XdmcpBuffer buffer;
-
-#if defined(IPv6) && defined(AF_INET6)
-
-static struct addrinfo *mgrAddr;
-static struct addrinfo *mgrAddrFirst;
-
-#define SOCKADDR_TYPE struct sockaddr_storage
-#define SOCKADDR_FAMILY(s) ((struct sockaddr *)&(s))->sa_family
-
-#ifdef BSD44SOCKETS
-#define SOCKLEN_FIELD(s) ((struct sockaddr *)&(s))->sa_len
-#define SOCKLEN_TYPE unsigned char
-#else
-#define SOCKLEN_TYPE unsigned int
-#endif
-
-#else
-
-#define SOCKADDR_TYPE struct sockaddr_in
-#define SOCKADDR_FAMILY(s) (s).sin_family
-
-#ifdef BSD44SOCKETS
-#define SOCKLEN_FIELD(s) (s).sin_len
-#define SOCKLEN_TYPE unsigned char
-#else
-#define SOCKLEN_TYPE size_t
-#endif
-
-#endif
-
-static SOCKADDR_TYPE ManagerAddress;
-static SOCKADDR_TYPE FromAddress;
-
-#ifdef SOCKLEN_FIELD
-#define ManagerAddressLen SOCKLEN_FIELD(ManagerAddress)
-#define FromAddressLen SOCKLEN_FIELD(FromAddress)
-#else
-static SOCKLEN_TYPE ManagerAddressLen, FromAddressLen;
-#endif
-
-#if defined(IPv6) && defined(AF_INET6)
-static struct multicastinfo {
- struct multicastinfo *next;
- struct addrinfo *ai;
- int hops;
-} *mcastlist;
-#endif
-
-static void XdmcpAddHost(
- struct sockaddr *from,
- int fromlen,
- ARRAY8Ptr AuthenticationName,
- ARRAY8Ptr hostname,
- ARRAY8Ptr status);
-
-static void XdmcpSelectHost(
- struct sockaddr *host_sockaddr,
- int host_len,
- ARRAY8Ptr AuthenticationName);
-
-static void get_xdmcp_sock(void);
-
-static void send_query_msg(void);
-
-static void recv_willing_msg(
- struct sockaddr * /*from*/,
- int /*fromlen*/,
- unsigned /*length*/);
-
-static void send_request_msg(void);
-
-static void recv_accept_msg(unsigned /*length*/);
-
-static void recv_decline_msg(unsigned /*length*/);
-
-static void send_manage_msg(void);
-
-static void recv_refuse_msg(unsigned /*length*/);
-
-static void recv_failed_msg(unsigned /*length*/);
-
-static void send_keepalive_msg(void);
-
-static void recv_alive_msg(unsigned /*length*/);
-
-static void XdmcpFatal(
- char * /*type*/,
- ARRAY8Ptr /*status*/);
-
-static void XdmcpWarning(char * /*str*/);
-
-static void get_manager_by_name(
- int /*argc*/,
- char ** /*argv*/,
- int /*i*/);
-
-static void get_fromaddr_by_name(int /*argc*/, char ** /*argv*/, int /*i*/);
-
-#if defined(IPv6) && defined(AF_INET6)
-static int get_mcast_options(int /*argc*/, char ** /*argv*/, int /*i*/);
-#endif
-
-static void receive_packet(int /*socketfd*/);
-
-static void send_packet(void);
-
-static void timeout(void);
-
-static void restart(void);
-
-static void XdmcpBlockHandler(
- pointer /*data*/,
- struct timeval ** /*wt*/,
- pointer /*LastSelectMask*/);
-
-static void XdmcpWakeupHandler(
- pointer /*data*/,
- int /*i*/,
- pointer /*LastSelectMask*/);
-
-#define XSERV_t
-#define TRANS_SERVER
-#define TRANS_REOPEN
-#include <X11/Xtrans/Xtrans.h>
-
-/*
- * Register the Manufacturer display ID
- */
-
-static ARRAY8 ManufacturerDisplayID;
-
-static void
-XdmcpRegisterManufacturerDisplayID (char *name, int length)
-{
- int i;
-
- XdmcpDisposeARRAY8 (&ManufacturerDisplayID);
- if (!XdmcpAllocARRAY8 (&ManufacturerDisplayID, length))
- return;
- for (i = 0; i < length; i++)
- ManufacturerDisplayID.data[i] = (CARD8) name[i];
-}
-
-static unsigned short xdm_udp_port = XDM_UDP_PORT;
-static Bool OneSession = FALSE;
-static const char *xdm_from = NULL;
-
-void
-XdmcpUseMsg (void)
-{
- ErrorF("-query host-name contact named host for XDMCP\n");
- ErrorF("-broadcast broadcast for XDMCP\n");
-#if defined(IPv6) && defined(AF_INET6)
- ErrorF("-multicast [addr [hops]] IPv6 multicast for XDMCP\n");
-#endif
- ErrorF("-indirect host-name contact named host for indirect XDMCP\n");
- ErrorF("-port port-num UDP port number to send messages to\n");
- ErrorF("-from local-address specify the local address to connect from\n");
- ErrorF("-once Terminate server after one session\n");
- ErrorF("-class display-class specify display class to send in manage\n");
-#ifdef HASXDMAUTH
- ErrorF("-cookie xdm-auth-bits specify the magic cookie for XDMCP\n");
-#endif
- ErrorF("-displayID display-id manufacturer display ID for request\n");
-}
-
-int
-XdmcpOptions(int argc, char **argv, int i)
-{
- if (strcmp(argv[i], "-query") == 0) {
- get_manager_by_name(argc, argv, i++);
- XDM_INIT_STATE = XDM_QUERY;
- AccessUsingXdmcp ();
- return (i + 1);
- }
- if (strcmp(argv[i], "-broadcast") == 0) {
- XDM_INIT_STATE = XDM_BROADCAST;
- AccessUsingXdmcp ();
- return (i + 1);
- }
-#if defined(IPv6) && defined(AF_INET6)
- if (strcmp(argv[i], "-multicast") == 0) {
- i = get_mcast_options(argc, argv, ++i);
- XDM_INIT_STATE = XDM_MULTICAST;
- AccessUsingXdmcp ();
- return (i + 1);
- }
-#endif
- if (strcmp(argv[i], "-indirect") == 0) {
- get_manager_by_name(argc, argv, i++);
- XDM_INIT_STATE = XDM_INDIRECT;
- AccessUsingXdmcp ();
- return (i + 1);
- }
- if (strcmp(argv[i], "-port") == 0) {
- if (++i == argc) {
- FatalError("Xserver: missing port number in command line\n");
- }
- xdm_udp_port = (unsigned short) atoi(argv[i]);
- return (i + 1);
- }
- if (strcmp(argv[i], "-from") == 0) {
- get_fromaddr_by_name(argc, argv, ++i);
- return (i + 1);
- }
- if (strcmp(argv[i], "-once") == 0) {
- OneSession = TRUE;
- return (i + 1);
- }
- if (strcmp(argv[i], "-class") == 0) {
- if (++i == argc) {
- FatalError("Xserver: missing class name in command line\n");
- }
- defaultDisplayClass = argv[i];
- return (i + 1);
- }
-#ifdef HASXDMAUTH
- if (strcmp(argv[i], "-cookie") == 0) {
- if (++i == argc) {
- FatalError("Xserver: missing cookie data in command line\n");
- }
- xdmAuthCookie = argv[i];
- return (i + 1);
- }
-#endif
- if (strcmp(argv[i], "-displayID") == 0) {
- if (++i == argc) {
- FatalError("Xserver: missing displayID in command line\n");
- }
- XdmcpRegisterManufacturerDisplayID (argv[i], strlen (argv[i]));
- return (i + 1);
- }
- return (i);
-}
-
-/*
- * This section is a collection of routines for
- * registering server-specific data with the XDMCP
- * state machine.
- */
-
-
-/*
- * Save all broadcast addresses away so BroadcastQuery
- * packets get sent everywhere
- */
-
-#define MAX_BROADCAST 10
-
-/* This stays sockaddr_in since IPv6 doesn't support broadcast */
-static struct sockaddr_in BroadcastAddresses[MAX_BROADCAST];
-static int NumBroadcastAddresses;
-
-void
-XdmcpRegisterBroadcastAddress (struct sockaddr_in *addr)
-{
- struct sockaddr_in *bcast;
- if (NumBroadcastAddresses >= MAX_BROADCAST)
- return;
- bcast = &BroadcastAddresses[NumBroadcastAddresses++];
- bzero (bcast, sizeof (struct sockaddr_in));
-#ifdef BSD44SOCKETS
- bcast->sin_len = addr->sin_len;
-#endif
- bcast->sin_family = addr->sin_family;
- bcast->sin_port = htons (xdm_udp_port);
- bcast->sin_addr = addr->sin_addr;
-}
-
-/*
- * Each authentication type is registered here; Validator
- * will be called to check all access attempts using
- * the specified authentication type
- */
-
-static ARRAYofARRAY8 AuthenticationNames, AuthenticationDatas;
-typedef struct _AuthenticationFuncs {
- ValidatorFunc Validator;
- GeneratorFunc Generator;
- AddAuthorFunc AddAuth;
-} AuthenticationFuncsRec, *AuthenticationFuncsPtr;
-
-static AuthenticationFuncsPtr AuthenticationFuncsList;
-
-void
-XdmcpRegisterAuthentication (
- char *name,
- int namelen,
- char *data,
- int datalen,
- ValidatorFunc Validator,
- GeneratorFunc Generator,
- AddAuthorFunc AddAuth)
-{
- int i;
- ARRAY8 AuthenticationName, AuthenticationData;
- static AuthenticationFuncsPtr newFuncs;
-
- if (!XdmcpAllocARRAY8 (&AuthenticationName, namelen))
- return;
- if (!XdmcpAllocARRAY8 (&AuthenticationData, datalen))
- {
- XdmcpDisposeARRAY8 (&AuthenticationName);
- return;
- }
- for (i = 0; i < namelen; i++)
- AuthenticationName.data[i] = name[i];
- for (i = 0; i < datalen; i++)
- AuthenticationData.data[i] = data[i];
- if (!(XdmcpReallocARRAYofARRAY8 (&AuthenticationNames,
- AuthenticationNames.length + 1) &&
- XdmcpReallocARRAYofARRAY8 (&AuthenticationDatas,
- AuthenticationDatas.length + 1) &&
- (newFuncs = xalloc ((AuthenticationNames.length + 1) * sizeof (AuthenticationFuncsRec)))))
- {
- XdmcpDisposeARRAY8 (&AuthenticationName);
- XdmcpDisposeARRAY8 (&AuthenticationData);
- return;
- }
- for (i = 0; i < AuthenticationNames.length - 1; i++)
- newFuncs[i] = AuthenticationFuncsList[i];
- newFuncs[AuthenticationNames.length-1].Validator = Validator;
- newFuncs[AuthenticationNames.length-1].Generator = Generator;
- newFuncs[AuthenticationNames.length-1].AddAuth = AddAuth;
- xfree (AuthenticationFuncsList);
- AuthenticationFuncsList = newFuncs;
- AuthenticationNames.data[AuthenticationNames.length-1] = AuthenticationName;
- AuthenticationDatas.data[AuthenticationDatas.length-1] = AuthenticationData;
-}
-
-/*
- * Select the authentication type to be used; this is
- * set by the manager of the host to be connected to.
- */
-
-static ARRAY8 noAuthenticationName = {(CARD16) 0, (CARD8Ptr) 0};
-static ARRAY8 noAuthenticationData = {(CARD16) 0, (CARD8Ptr) 0};
-static ARRAY8Ptr AuthenticationName = &noAuthenticationName;
-static ARRAY8Ptr AuthenticationData = &noAuthenticationData;
-static AuthenticationFuncsPtr AuthenticationFuncs;
-
-static void
-XdmcpSetAuthentication (ARRAY8Ptr name)
-{
- int i;
-
- for (i = 0; i < AuthenticationNames.length; i++)
- if (XdmcpARRAY8Equal (&AuthenticationNames.data[i], name))
- {
- AuthenticationName = &AuthenticationNames.data[i];
- AuthenticationData = &AuthenticationDatas.data[i];
- AuthenticationFuncs = &AuthenticationFuncsList[i];
- break;
- }
-}
-
-/*
- * Register the host address for the display
- */
-
-static ARRAY16 ConnectionTypes;
-static ARRAYofARRAY8 ConnectionAddresses;
-static long xdmcpGeneration;
-
-void
-XdmcpRegisterConnection (
- int type,
- char *address,
- int addrlen)
-{
- int i;
- CARD8 *newAddress;
-
- if (xdmcpGeneration != serverGeneration)
- {
- XdmcpDisposeARRAY16 (&ConnectionTypes);
- XdmcpDisposeARRAYofARRAY8 (&ConnectionAddresses);
- xdmcpGeneration = serverGeneration;
- }
- if (xdm_from != NULL) { /* Only register the requested address */
- const void *regAddr = address;
- const void *fromAddr = NULL;
- int regAddrlen = addrlen;
-
- if (addrlen == sizeof(struct in_addr)) {
- if (SOCKADDR_FAMILY(FromAddress) == AF_INET) {
- fromAddr = &((struct sockaddr_in *)&FromAddress)->sin_addr;
- }
-#if defined(IPv6) && defined(AF_INET6)
- else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET6) &&
- IN6_IS_ADDR_V4MAPPED(
- &((struct sockaddr_in6 *)&FromAddress)->sin6_addr)) {
- fromAddr = &((struct sockaddr_in6 *)&FromAddress)->sin6_addr.s6_addr[12];
- }
-#endif
- }
-#if defined(IPv6) && defined(AF_INET6)
- else if (addrlen == sizeof(struct in6_addr)) {
- if (SOCKADDR_FAMILY(FromAddress) == AF_INET6) {
- fromAddr = &((struct sockaddr_in6 *)&FromAddress)->sin6_addr;
- } else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET) &&
- IN6_IS_ADDR_V4MAPPED((struct in6_addr *) address)) {
- fromAddr = &((struct sockaddr_in *)&FromAddress)->sin_addr;
- regAddr = &((struct sockaddr_in6 *)&address)->sin6_addr.s6_addr[12];
- regAddrlen = sizeof(struct in_addr);
- }
- }
-#endif
- if (fromAddr && memcmp(regAddr, fromAddr, regAddrlen) != 0) {
- return;
- }
- }
- if (ConnectionAddresses.length + 1 == 256)
- return;
- newAddress = xalloc (addrlen * sizeof (CARD8));
- if (!newAddress)
- return;
- if (!XdmcpReallocARRAY16 (&ConnectionTypes, ConnectionTypes.length + 1))
- {
- xfree (newAddress);
- return;
- }
- if (!XdmcpReallocARRAYofARRAY8 (&ConnectionAddresses,
- ConnectionAddresses.length + 1))
- {
- xfree (newAddress);
- return;
- }
- ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type;
- for (i = 0; i < addrlen; i++)
- newAddress[i] = address[i];
- ConnectionAddresses.data[ConnectionAddresses.length-1].data = newAddress;
- ConnectionAddresses.data[ConnectionAddresses.length-1].length = addrlen;
-}
-
-/*
- * Register an Authorization Name. XDMCP advertises this list
- * to the manager.
- */
-
-static ARRAYofARRAY8 AuthorizationNames;
-
-void
-XdmcpRegisterAuthorizations (void)
-{
- XdmcpDisposeARRAYofARRAY8 (&AuthorizationNames);
- RegisterAuthorizations ();
-}
-
-void
-XdmcpRegisterAuthorization (char *name, int namelen)
-{
- ARRAY8 authName;
- int i;
-
- authName.data = xalloc (namelen * sizeof (CARD8));
- if (!authName.data)
- return;
- if (!XdmcpReallocARRAYofARRAY8 (&AuthorizationNames, AuthorizationNames.length +1))
- {
- xfree (authName.data);
- return;
- }
- for (i = 0; i < namelen; i++)
- authName.data[i] = (CARD8) name[i];
- authName.length = namelen;
- AuthorizationNames.data[AuthorizationNames.length-1] = authName;
-}
-
-/*
- * Register the DisplayClass string
- */
-
-static ARRAY8 DisplayClass;
-
-static void
-XdmcpRegisterDisplayClass (char *name, int length)
-{
- int i;
-
- XdmcpDisposeARRAY8 (&DisplayClass);
- if (!XdmcpAllocARRAY8 (&DisplayClass, length))
- return;
- for (i = 0; i < length; i++)
- DisplayClass.data[i] = (CARD8) name[i];
-}
-
-/*
- * initialize XDMCP; create the socket, compute the display
- * number, set up the state machine
- */
-
-void
-XdmcpInit(void)
-{
- state = XDM_INIT_STATE;
-#ifdef HASXDMAUTH
- if (xdmAuthCookie)
- XdmAuthenticationInit (xdmAuthCookie, strlen (xdmAuthCookie));
-#endif
- if (state != XDM_OFF)
- {
- XdmcpRegisterAuthorizations();
- XdmcpRegisterDisplayClass (defaultDisplayClass, strlen (defaultDisplayClass));
- AccessUsingXdmcp();
- RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler,
- (pointer) 0);
- timeOutRtx = 0;
- DisplayNumber = (CARD16) atoi(display);
- get_xdmcp_sock();
- send_packet();
- }
-}
-
-void
-XdmcpReset (void)
-{
- state = XDM_INIT_STATE;
- if (state != XDM_OFF)
- {
- RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler,
- (pointer) 0);
- timeOutRtx = 0;
- send_packet();
- }
-}
-
-/*
- * Called whenever a new connection is created; notices the
- * first connection and saves it to terminate the session
- * when it is closed
- */
-
-void
-XdmcpOpenDisplay(int sock)
-{
- if (state != XDM_AWAIT_MANAGE_RESPONSE)
- return;
- state = XDM_RUN_SESSION;
- sessionSocket = sock;
-}
-
-void
-XdmcpCloseDisplay(int sock)
-{
- if ((state != XDM_RUN_SESSION && state != XDM_AWAIT_ALIVE_RESPONSE)
- || sessionSocket != sock)
- return;
- state = XDM_INIT_STATE;
- if (OneSession)
- dispatchException |= DE_TERMINATE;
- else
- dispatchException |= DE_RESET;
- isItTimeToYield = TRUE;
-}
-
-/*
- * called before going to sleep, this routine
- * may modify the timeout value about to be sent
- * to select; in this way XDMCP can do appropriate things
- * dynamically while starting up
- */
-
-/*ARGSUSED*/
-static void
-XdmcpBlockHandler(
- pointer data, /* unused */
- struct timeval **wt,
- pointer pReadmask)
-{
- fd_set *LastSelectMask = (fd_set*)pReadmask;
- CARD32 millisToGo;
-
- if (state == XDM_OFF)
- return;
- FD_SET(xdmcpSocket, LastSelectMask);
-#if defined(IPv6) && defined(AF_INET6)
- if (xdmcpSocket6 >= 0)
- FD_SET(xdmcpSocket6, LastSelectMask);
-#endif
- if (timeOutTime == 0)
- return;
- millisToGo = timeOutTime - GetTimeInMillis();
- if ((int) millisToGo < 0)
- millisToGo = 0;
- AdjustWaitForDelay (wt, millisToGo);
-}
-
-/*
- * called after select returns; this routine will
- * recognise when XDMCP packets await and
- * process them appropriately
- */
-
-/*ARGSUSED*/
-static void
-XdmcpWakeupHandler(
- pointer data, /* unused */
- int i,
- pointer pReadmask)
-{
- fd_set* LastSelectMask = (fd_set*)pReadmask;
- fd_set devicesReadable;
-
- if (state == XDM_OFF)
- return;
- if (i > 0)
- {
- if (FD_ISSET(xdmcpSocket, LastSelectMask))
- {
- receive_packet(xdmcpSocket);
- FD_CLR(xdmcpSocket, LastSelectMask);
- }
-#if defined(IPv6) && defined(AF_INET6)
- if (xdmcpSocket6 >= 0 && FD_ISSET(xdmcpSocket6, LastSelectMask))
- {
- receive_packet(xdmcpSocket6);
- FD_CLR(xdmcpSocket6, LastSelectMask);
- }
-#endif
- XFD_ANDSET(&devicesReadable, LastSelectMask, &EnabledDevices);
- if (XFD_ANYSET(&devicesReadable))
- {
- if (state == XDM_AWAIT_USER_INPUT)
- restart();
- else if (state == XDM_RUN_SESSION)
- keepaliveDormancy = defaultKeepaliveDormancy;
- }
- if (XFD_ANYSET(&AllClients) && state == XDM_RUN_SESSION)
- timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000;
- }
- else if (timeOutTime && (int) (GetTimeInMillis() - timeOutTime) >= 0)
- {
- if (state == XDM_RUN_SESSION)
- {
- state = XDM_KEEPALIVE;
- send_packet();
- }
- else
- timeout();
- }
-}
-
-/*
- * This routine should be called from the routine that drives the
- * user's host menu when the user selects a host
- */
-
-static void
-XdmcpSelectHost(
- struct sockaddr *host_sockaddr,
- int host_len,
- ARRAY8Ptr AuthenticationName)
-{
- state = XDM_START_CONNECTION;
- memmove(&req_sockaddr, host_sockaddr, host_len);
- req_socklen = host_len;
- XdmcpSetAuthentication (AuthenticationName);
- send_packet();
-}
-
-/*
- * !!! this routine should be replaced by a routine that adds
- * the host to the user's host menu. the current version just
- * selects the first host to respond with willing message.
- */
-
-/*ARGSUSED*/
-static void
-XdmcpAddHost(
- struct sockaddr *from,
- int fromlen,
- ARRAY8Ptr AuthenticationName,
- ARRAY8Ptr hostname,
- ARRAY8Ptr status)
-{
- XdmcpSelectHost(from, fromlen, AuthenticationName);
-}
-
-/*
- * A message is queued on the socket; read it and
- * do the appropriate thing
- */
-
-static ARRAY8 UnwillingMessage = { (CARD8) 14, (CARD8 *) "Host unwilling" };
-
-static void
-receive_packet(int socketfd)
-{
-#if defined(IPv6) && defined(AF_INET6)
- struct sockaddr_storage from;
-#else
- struct sockaddr_in from;
-#endif
- int fromlen = sizeof(from);
- XdmcpHeader header;
-
- /* read message off socket */
- if (!XdmcpFill (socketfd, &buffer, (XdmcpNetaddr) &from, &fromlen))
- return;
-
- /* reset retransmission backoff */
- timeOutRtx = 0;
-
- if (!XdmcpReadHeader (&buffer, &header))
- return;
-
- if (header.version != XDM_PROTOCOL_VERSION)
- return;
-
- switch (header.opcode) {
- case WILLING:
- recv_willing_msg((struct sockaddr *) &from, fromlen, header.length);
- break;
- case UNWILLING:
- XdmcpFatal("Manager unwilling", &UnwillingMessage);
- break;
- case ACCEPT:
- recv_accept_msg(header.length);
- break;
- case DECLINE:
- recv_decline_msg(header.length);
- break;
- case REFUSE:
- recv_refuse_msg(header.length);
- break;
- case FAILED:
- recv_failed_msg(header.length);
- break;
- case ALIVE:
- recv_alive_msg(header.length);
- break;
- }
-}
-
-/*
- * send the appropriate message given the current state
- */
-
-static void
-send_packet(void)
-{
- int rtx;
- switch (state) {
- case XDM_QUERY:
- case XDM_BROADCAST:
- case XDM_INDIRECT:
-#if defined(IPv6) && defined(AF_INET6)
- case XDM_MULTICAST:
-#endif
- send_query_msg();
- break;
- case XDM_START_CONNECTION:
- send_request_msg();
- break;
- case XDM_MANAGE:
- send_manage_msg();
- break;
- case XDM_KEEPALIVE:
- send_keepalive_msg();
- break;
- default:
- break;
- }
- rtx = (XDM_MIN_RTX << timeOutRtx);
- if (rtx > XDM_MAX_RTX)
- rtx = XDM_MAX_RTX;
- timeOutTime = GetTimeInMillis() + rtx * 1000;
-}
-
-/*
- * The session is declared dead for some reason; too many
- * timeouts, or Keepalive failure.
- */
-
-static void
-XdmcpDeadSession (char *reason)
-{
- ErrorF ("XDM: %s, declaring session dead\n", reason);
- state = XDM_INIT_STATE;
- isItTimeToYield = TRUE;
- dispatchException |= DE_RESET;
- timeOutTime = 0;
- timeOutRtx = 0;
- send_packet();
-}
-
-/*
- * Timeout waiting for an XDMCP response.
- */
-
-static void
-timeout(void)
-{
- timeOutRtx++;
- if (state == XDM_AWAIT_ALIVE_RESPONSE && timeOutRtx >= XDM_KA_RTX_LIMIT )
- {
- XdmcpDeadSession ("too many keepalive retransmissions");
- return;
- }
- else if (timeOutRtx >= XDM_RTX_LIMIT)
- {
- /* Quit if "-once" specified, otherwise reset and try again. */
- if (OneSession) {
- dispatchException |= DE_TERMINATE;
- ErrorF("XDM: too many retransmissions\n");
- } else {
- XdmcpDeadSession("too many retransmissions");
- }
- return;
- }
-
-#if defined(IPv6) && defined(AF_INET6)
- if (state == XDM_COLLECT_QUERY || state == XDM_COLLECT_INDIRECT_QUERY) {
- /* Try next address */
- for (mgrAddr = mgrAddr->ai_next; ; mgrAddr = mgrAddr->ai_next) {
- if (mgrAddr == NULL) {
- mgrAddr = mgrAddrFirst;
- }
- if (mgrAddr->ai_family == AF_INET
- || mgrAddr->ai_family == AF_INET6)
- break;
- }
-#ifndef SIN6_LEN
- ManagerAddressLen = mgrAddr->ai_addrlen;
-#endif
- memcpy(&ManagerAddress, mgrAddr->ai_addr, mgrAddr->ai_addrlen);
- }
-#endif
-
- switch (state) {
- case XDM_COLLECT_QUERY:
- state = XDM_QUERY;
- break;
- case XDM_COLLECT_BROADCAST_QUERY:
- state = XDM_BROADCAST;
- break;
-#if defined(IPv6) && defined(AF_INET6)
- case XDM_COLLECT_MULTICAST_QUERY:
- state = XDM_MULTICAST;
- break;
-#endif
- case XDM_COLLECT_INDIRECT_QUERY:
- state = XDM_INDIRECT;
- break;
- case XDM_AWAIT_REQUEST_RESPONSE:
- state = XDM_START_CONNECTION;
- break;
- case XDM_AWAIT_MANAGE_RESPONSE:
- state = XDM_MANAGE;
- break;
- case XDM_AWAIT_ALIVE_RESPONSE:
- state = XDM_KEEPALIVE;
- break;
- default:
- break;
- }
- send_packet();
-}
-
-static void
-restart(void)
-{
- state = XDM_INIT_STATE;
- timeOutRtx = 0;
- send_packet();
-}
-
-static int
-XdmcpCheckAuthentication (ARRAY8Ptr Name, ARRAY8Ptr Data, int packet_type)
-{
- return (XdmcpARRAY8Equal (Name, AuthenticationName) &&
- (AuthenticationName->length == 0 ||
- (*AuthenticationFuncs->Validator) (AuthenticationData, Data, packet_type)));
-}
-
-static int
-XdmcpAddAuthorization (ARRAY8Ptr name, ARRAY8Ptr data)
-{
- AddAuthorFunc AddAuth;
-
- if (AuthenticationFuncs && AuthenticationFuncs->AddAuth)
- AddAuth = AuthenticationFuncs->AddAuth;
- else
- AddAuth = AddAuthorization;
- return (*AddAuth) ((unsigned short)name->length,
- (char *)name->data,
- (unsigned short)data->length,
- (char *)data->data);
-}
-
-/*
- * from here to the end of this file are routines private
- * to the state machine.
- */
-
-static void
-get_xdmcp_sock(void)
-{
-#ifdef STREAMSCONN
- struct netconfig *nconf;
-
- if ((xdmcpSocket = t_open("/dev/udp", O_RDWR, 0)) < 0) {
- XdmcpWarning("t_open() of /dev/udp failed");
- return;
- }
-
- if( t_bind(xdmcpSocket,NULL,NULL) < 0 ) {
- XdmcpWarning("UDP socket creation failed");
- t_error("t_bind(xdmcpSocket) failed" );
- t_close(xdmcpSocket);
- return;
- }
-
- /*
- * This part of the code looks contrived. It will actually fit in nicely
- * when the CLTS part of Xtrans is implemented.
- */
-
- if( (nconf=getnetconfigent("udp")) == NULL ) {
- XdmcpWarning("UDP socket creation failed: getnetconfigent()");
- t_unbind(xdmcpSocket);
- t_close(xdmcpSocket);
- return;
- }
-
- if( netdir_options(nconf, ND_SET_BROADCAST, xdmcpSocket, NULL) ) {
- XdmcpWarning("UDP set broadcast option failed: netdir_options()");
- freenetconfigent(nconf);
- t_unbind(xdmcpSocket);
- t_close(xdmcpSocket);
- return;
- }
-
- freenetconfigent(nconf);
-#else
- int soopts = 1;
-
-#if defined(IPv6) && defined(AF_INET6)
- if ((xdmcpSocket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
- XdmcpWarning("INET6 UDP socket creation failed");
-#endif
- if ((xdmcpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
- XdmcpWarning("UDP socket creation failed");
-#ifdef SO_BROADCAST
- else if (setsockopt(xdmcpSocket, SOL_SOCKET, SO_BROADCAST, (char *)&soopts,
- sizeof(soopts)) < 0)
- XdmcpWarning("UDP set broadcast socket-option failed");
-#endif /* SO_BROADCAST */
- if (xdmcpSocket >= 0 && xdm_from != NULL) {
- if (bind(xdmcpSocket, (struct sockaddr *)&FromAddress,
- FromAddressLen) < 0) {
- FatalError("Xserver: failed to bind to -from address: %s\n", xdm_from);
- }
- }
-#endif /* STREAMSCONN */
-}
-
-static void
-send_query_msg(void)
-{
- XdmcpHeader header;
- Bool broadcast = FALSE;
-#if defined(IPv6) && defined(AF_INET6)
- Bool multicast = FALSE;
-#endif
- int i;
- int socketfd = xdmcpSocket;
-
- header.version = XDM_PROTOCOL_VERSION;
- switch(state){
- case XDM_QUERY:
- header.opcode = (CARD16) QUERY;
- state = XDM_COLLECT_QUERY;
- break;
- case XDM_BROADCAST:
- header.opcode = (CARD16) BROADCAST_QUERY;
- state = XDM_COLLECT_BROADCAST_QUERY;
- broadcast = TRUE;
- break;
-#if defined(IPv6) && defined(AF_INET6)
- case XDM_MULTICAST:
- header.opcode = (CARD16) BROADCAST_QUERY;
- state = XDM_COLLECT_MULTICAST_QUERY;
- multicast = TRUE;
- break;
-#endif
- case XDM_INDIRECT:
- header.opcode = (CARD16) INDIRECT_QUERY;
- state = XDM_COLLECT_INDIRECT_QUERY;
- break;
- default:
- break;
- }
- header.length = 1;
- for (i = 0; i < AuthenticationNames.length; i++)
- header.length += 2 + AuthenticationNames.data[i].length;
-
- XdmcpWriteHeader (&buffer, &header);
- XdmcpWriteARRAYofARRAY8 (&buffer, &AuthenticationNames);
- if (broadcast)
- {
- int i;
-
- for (i = 0; i < NumBroadcastAddresses; i++)
- XdmcpFlush (xdmcpSocket, &buffer, (XdmcpNetaddr) &BroadcastAddresses[i],
- sizeof (struct sockaddr_in));
- }
-#if defined(IPv6) && defined(AF_INET6)
- else if (multicast)
- {
- struct multicastinfo *mcl;
- struct addrinfo *ai;
-
- for (mcl = mcastlist; mcl != NULL; mcl = mcl->next) {
- for (ai = mcl->ai ; ai != NULL; ai = ai->ai_next) {
- if (ai->ai_family == AF_INET) {
- unsigned char hopflag = (unsigned char) mcl->hops;
- socketfd = xdmcpSocket;
- setsockopt(socketfd, IPPROTO_IP, IP_MULTICAST_TTL,
- &hopflag, sizeof(hopflag));
- } else if (ai->ai_family == AF_INET6) {
- int hopflag6 = mcl->hops;
- socketfd = xdmcpSocket6;
- setsockopt(socketfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
- &hopflag6, sizeof(hopflag6));
- } else {
- continue;
- }
- XdmcpFlush (socketfd, &buffer,
- (XdmcpNetaddr) ai->ai_addr, ai->ai_addrlen);
- break;
- }
- }
- }
-#endif
- else
- {
-#if defined(IPv6) && defined(AF_INET6)
- if (SOCKADDR_FAMILY(ManagerAddress) == AF_INET6)
- socketfd = xdmcpSocket6;
-#endif
- XdmcpFlush (socketfd, &buffer, (XdmcpNetaddr) &ManagerAddress,
- ManagerAddressLen);
- }
-}
-
-static void
-recv_willing_msg(
- struct sockaddr *from,
- int fromlen,
- unsigned length)
-{
- ARRAY8 authenticationName;
- ARRAY8 hostname;
- ARRAY8 status;
-
- authenticationName.data = 0;
- hostname.data = 0;
- status.data = 0;
- if (XdmcpReadARRAY8 (&buffer, &authenticationName) &&
- XdmcpReadARRAY8 (&buffer, &hostname) &&
- XdmcpReadARRAY8 (&buffer, &status))
- {
- if (length == 6 + authenticationName.length +
- hostname.length + status.length)
- {
- switch (state)
- {
- case XDM_COLLECT_QUERY:
- XdmcpSelectHost(from, fromlen, &authenticationName);
- break;
- case XDM_COLLECT_BROADCAST_QUERY:
-#if defined(IPv6) && defined(AF_INET6)
- case XDM_COLLECT_MULTICAST_QUERY:
-#endif
- case XDM_COLLECT_INDIRECT_QUERY:
- XdmcpAddHost(from, fromlen, &authenticationName, &hostname, &status);
- break;
- default:
- break;
- }
- }
- }
- XdmcpDisposeARRAY8 (&authenticationName);
- XdmcpDisposeARRAY8 (&hostname);
- XdmcpDisposeARRAY8 (&status);
-}
-
-static void
-send_request_msg(void)
-{
- XdmcpHeader header;
- int length;
- int i;
- CARD16 XdmcpConnectionType;
- ARRAY8 authenticationData;
- int socketfd = xdmcpSocket;
-
- switch (SOCKADDR_FAMILY(ManagerAddress))
- {
- case AF_INET: XdmcpConnectionType=FamilyInternet; break;
-#if defined(IPv6) && defined(AF_INET6)
- case AF_INET6: XdmcpConnectionType=FamilyInternet6; break;
-#endif
- default: XdmcpConnectionType=0xffff; break;
- }
-
- header.version = XDM_PROTOCOL_VERSION;
- header.opcode = (CARD16) REQUEST;
-
- length = 2; /* display number */
- length += 1 + 2 * ConnectionTypes.length; /* connection types */
- length += 1; /* connection addresses */
- for (i = 0; i < ConnectionAddresses.length; i++)
- length += 2 + ConnectionAddresses.data[i].length;
- authenticationData.length = 0;
- authenticationData.data = 0;
- if (AuthenticationFuncs)
- {
- (*AuthenticationFuncs->Generator) (AuthenticationData,
- &authenticationData,
- REQUEST);
- }
- length += 2 + AuthenticationName->length; /* authentication name */
- length += 2 + authenticationData.length; /* authentication data */
- length += 1; /* authorization names */
- for (i = 0; i < AuthorizationNames.length; i++)
- length += 2 + AuthorizationNames.data[i].length;
- length += 2 + ManufacturerDisplayID.length; /* display ID */
- header.length = length;
-
- if (!XdmcpWriteHeader (&buffer, &header))
- {
- XdmcpDisposeARRAY8 (&authenticationData);
- return;
- }
- XdmcpWriteCARD16 (&buffer, DisplayNumber);
- XdmcpWriteCARD8 (&buffer, ConnectionTypes.length);
-
- /* The connection array is send reordered, so that connections of */
- /* the same address type as the XDMCP manager connection are send */
- /* first. This works around a bug in xdm. mario@klebsch.de */
- for (i = 0; i < (int)ConnectionTypes.length; i++)
- if (ConnectionTypes.data[i]==XdmcpConnectionType)
- XdmcpWriteCARD16 (&buffer, ConnectionTypes.data[i]);
- for (i = 0; i < (int)ConnectionTypes.length; i++)
- if (ConnectionTypes.data[i]!=XdmcpConnectionType)
- XdmcpWriteCARD16 (&buffer, ConnectionTypes.data[i]);
-
- XdmcpWriteCARD8 (&buffer, ConnectionAddresses.length);
- for (i = 0; i < (int)ConnectionAddresses.length; i++)
- if ( (i<ConnectionTypes.length) &&
- (ConnectionTypes.data[i]==XdmcpConnectionType) )
- XdmcpWriteARRAY8 (&buffer, &ConnectionAddresses.data[i]);
- for (i = 0; i < (int)ConnectionAddresses.length; i++)
- if ( (i>=ConnectionTypes.length) ||
- (ConnectionTypes.data[i]!=XdmcpConnectionType) )
- XdmcpWriteARRAY8 (&buffer, &ConnectionAddresses.data[i]);
-
- XdmcpWriteARRAY8 (&buffer, AuthenticationName);
- XdmcpWriteARRAY8 (&buffer, &authenticationData);
- XdmcpDisposeARRAY8 (&authenticationData);
- XdmcpWriteARRAYofARRAY8 (&buffer, &AuthorizationNames);
- XdmcpWriteARRAY8 (&buffer, &ManufacturerDisplayID);
-#if defined(IPv6) && defined(AF_INET6)
- if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
- socketfd = xdmcpSocket6;
-#endif
- if (XdmcpFlush (socketfd, &buffer,
- (XdmcpNetaddr) &req_sockaddr, req_socklen))
- state = XDM_AWAIT_REQUEST_RESPONSE;
-}
-
-static void
-recv_accept_msg(unsigned length)
-{
- CARD32 AcceptSessionID;
- ARRAY8 AcceptAuthenticationName, AcceptAuthenticationData;
- ARRAY8 AcceptAuthorizationName, AcceptAuthorizationData;
-
- if (state != XDM_AWAIT_REQUEST_RESPONSE)
- return;
- AcceptAuthenticationName.data = 0;
- AcceptAuthenticationData.data = 0;
- AcceptAuthorizationName.data = 0;
- AcceptAuthorizationData.data = 0;
- if (XdmcpReadCARD32 (&buffer, &AcceptSessionID) &&
- XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationName) &&
- XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationData) &&
- XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationName) &&
- XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationData))
- {
- if (length == 12 + AcceptAuthenticationName.length +
- AcceptAuthenticationData.length +
- AcceptAuthorizationName.length +
- AcceptAuthorizationData.length)
- {
- if (!XdmcpCheckAuthentication (&AcceptAuthenticationName,
- &AcceptAuthenticationData, ACCEPT))
- {
- XdmcpFatal ("Authentication Failure", &AcceptAuthenticationName);
- }
- /* permit access control manipulations from this host */
- AugmentSelf (&req_sockaddr, req_socklen);
- /* if the authorization specified in the packet fails
- * to be acceptable, enable the local addresses
- */
- if (!XdmcpAddAuthorization (&AcceptAuthorizationName,
- &AcceptAuthorizationData))
- {
- AddLocalHosts ();
- }
- SessionID = AcceptSessionID;
- state = XDM_MANAGE;
- send_packet();
- }
- }
- XdmcpDisposeARRAY8 (&AcceptAuthenticationName);
- XdmcpDisposeARRAY8 (&AcceptAuthenticationData);
- XdmcpDisposeARRAY8 (&AcceptAuthorizationName);
- XdmcpDisposeARRAY8 (&AcceptAuthorizationData);
-}
-
-static void
-recv_decline_msg(unsigned length)
-{
- ARRAY8 status, DeclineAuthenticationName, DeclineAuthenticationData;
-
- status.data = 0;
- DeclineAuthenticationName.data = 0;
- DeclineAuthenticationData.data = 0;
- if (XdmcpReadARRAY8 (&buffer, &status) &&
- XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationName) &&
- XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationData))
- {
- if (length == 6 + status.length +
- DeclineAuthenticationName.length +
- DeclineAuthenticationData.length &&
- XdmcpCheckAuthentication (&DeclineAuthenticationName,
- &DeclineAuthenticationData, DECLINE))
- {
- XdmcpFatal ("Session declined", &status);
- }
- }
- XdmcpDisposeARRAY8 (&status);
- XdmcpDisposeARRAY8 (&DeclineAuthenticationName);
- XdmcpDisposeARRAY8 (&DeclineAuthenticationData);
-}
-
-static void
-send_manage_msg(void)
-{
- XdmcpHeader header;
- int socketfd = xdmcpSocket;
-
- header.version = XDM_PROTOCOL_VERSION;
- header.opcode = (CARD16) MANAGE;
- header.length = 8 + DisplayClass.length;
-
- if (!XdmcpWriteHeader (&buffer, &header))
- return;
- XdmcpWriteCARD32 (&buffer, SessionID);
- XdmcpWriteCARD16 (&buffer, DisplayNumber);
- XdmcpWriteARRAY8 (&buffer, &DisplayClass);
- state = XDM_AWAIT_MANAGE_RESPONSE;
-#if defined(IPv6) && defined(AF_INET6)
- if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
- socketfd = xdmcpSocket6;
-#endif
- XdmcpFlush (socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen);
-}
-
-static void
-recv_refuse_msg(unsigned length)
-{
- CARD32 RefusedSessionID;
-
- if (state != XDM_AWAIT_MANAGE_RESPONSE)
- return;
- if (length != 4)
- return;
- if (XdmcpReadCARD32 (&buffer, &RefusedSessionID))
- {
- if (RefusedSessionID == SessionID)
- {
- state = XDM_START_CONNECTION;
- send_packet();
- }
- }
-}
-
-static void
-recv_failed_msg(unsigned length)
-{
- CARD32 FailedSessionID;
- ARRAY8 status;
-
- if (state != XDM_AWAIT_MANAGE_RESPONSE)
- return;
- status.data = 0;
- if (XdmcpReadCARD32 (&buffer, &FailedSessionID) &&
- XdmcpReadARRAY8 (&buffer, &status))
- {
- if (length == 6 + status.length &&
- SessionID == FailedSessionID)
- {
- XdmcpFatal ("Session failed", &status);
- }
- }
- XdmcpDisposeARRAY8 (&status);
-}
-
-static void
-send_keepalive_msg(void)
-{
- XdmcpHeader header;
- int socketfd = xdmcpSocket;
-
- header.version = XDM_PROTOCOL_VERSION;
- header.opcode = (CARD16) KEEPALIVE;
- header.length = 6;
-
- XdmcpWriteHeader (&buffer, &header);
- XdmcpWriteCARD16 (&buffer, DisplayNumber);
- XdmcpWriteCARD32 (&buffer, SessionID);
-
- state = XDM_AWAIT_ALIVE_RESPONSE;
-#if defined(IPv6) && defined(AF_INET6)
- if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
- socketfd = xdmcpSocket6;
-#endif
- XdmcpFlush (socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen);
-}
-
-static void
-recv_alive_msg (unsigned length)
-{
- CARD8 SessionRunning;
- CARD32 AliveSessionID;
-
- if (state != XDM_AWAIT_ALIVE_RESPONSE)
- return;
- if (length != 5)
- return;
- if (XdmcpReadCARD8 (&buffer, &SessionRunning) &&
- XdmcpReadCARD32 (&buffer, &AliveSessionID))
- {
- if (SessionRunning && AliveSessionID == SessionID)
- {
- /* backoff dormancy period */
- state = XDM_RUN_SESSION;
- if ((GetTimeInMillis() - lastDeviceEventTime.milliseconds) >
- keepaliveDormancy * 1000)
- {
- keepaliveDormancy <<= 1;
- if (keepaliveDormancy > XDM_MAX_DORMANCY)
- keepaliveDormancy = XDM_MAX_DORMANCY;
- }
- timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000;
- }
- else
- {
- XdmcpDeadSession ("Alive response indicates session dead");
- }
- }
-}
-
-static void
-XdmcpFatal (
- char *type,
- ARRAY8Ptr status)
-{
- FatalError ("XDMCP fatal error: %s %*.*s\n", type,
- status->length, status->length, status->data);
-}
-
-static void
-XdmcpWarning(char *str)
-{
- ErrorF("XDMCP warning: %s\n", str);
-}
-
-static void
-get_addr_by_name(
- char * argtype,
- char * namestr,
- int port,
- int socktype,
- SOCKADDR_TYPE *addr,
- SOCKLEN_TYPE *addrlen
-#if defined(IPv6) && defined(AF_INET6)
- ,
- struct addrinfo **aip,
- struct addrinfo **aifirstp
-#endif
- )
-{
-#if defined(IPv6) && defined(AF_INET6)
- struct addrinfo *ai;
- struct addrinfo hints;
- char portstr[6];
- char *pport = portstr;
- int gaierr;
-
- bzero(&hints, sizeof(hints));
- hints.ai_socktype = socktype;
-
- if (port == 0) {
- pport = NULL;
- } else if (port > 0 && port < 65535) {
- sprintf(portstr, "%d", port);
- } else {
- FatalError("Xserver: port out of range: %d\n", port);
- }
-
- if (*aifirstp != NULL) {
- freeaddrinfo(*aifirstp);
- *aifirstp = NULL;
- }
-
- if ((gaierr = getaddrinfo(namestr, pport, &hints, aifirstp)) == 0) {
- for (ai = *aifirstp; ai != NULL; ai = ai->ai_next) {
- if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6)
- break;
- }
- if ((ai == NULL) || (ai->ai_addrlen > sizeof(SOCKADDR_TYPE))) {
- FatalError ("Xserver: %s host %s not on supported network type\n",
- argtype, namestr);
- } else {
- *aip = ai;
- *addrlen = ai->ai_addrlen;
- memcpy(addr, ai->ai_addr, ai->ai_addrlen);
- }
- } else {
- FatalError("Xserver: %s: %s %s\n", gai_strerror(gaierr), argtype, namestr);
- }
-#else
- struct hostent *hep;
-#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
- _Xgethostbynameparams hparams;
-#endif
-#if defined(WIN32) && (defined(TCPCONN) || defined(DNETCONN))
- _XSERVTransWSAStartup();
-#endif
- if (!(hep = _XGethostbyname(namestr, hparams)))
- {
- FatalError("Xserver: %s unknown host: %s\n", argtype, namestr);
- }
- if (hep->h_length == sizeof (struct in_addr))
- {
- memmove(&addr->sin_addr, hep->h_addr, hep->h_length);
- *addrlen = sizeof(struct sockaddr_in);
- addr->sin_family = AF_INET;
- addr->sin_port = htons (port);
- }
- else
- {
- FatalError("Xserver: %s host on strange network %s\n", argtype, namestr);
- }
-#endif
-}
-
-static void
-get_manager_by_name(
- int argc,
- char **argv,
- int i)
-{
-
- if ((i + 1) == argc)
- {
- FatalError("Xserver: missing %s host name in command line\n", argv[i]);
- }
-
- get_addr_by_name(argv[i], argv[i+1], xdm_udp_port, SOCK_DGRAM,
- &ManagerAddress, &ManagerAddressLen
-#if defined(IPv6) && defined(AF_INET6)
- , &mgrAddr, &mgrAddrFirst
-#endif
- );
-}
-
-
-static void
-get_fromaddr_by_name(
- int argc,
- char **argv,
- int i)
-{
-#if defined(IPv6) && defined(AF_INET6)
- struct addrinfo *ai = NULL;
- struct addrinfo *aifirst = NULL;
-#endif
- if (i == argc)
- {
- FatalError("Xserver: missing -from host name in command line\n");
- }
- get_addr_by_name("-from", argv[i], 0, 0, &FromAddress, &FromAddressLen
-#if defined(IPv6) && defined(AF_INET6)
- , &ai, &aifirst
-#endif
- );
-#if defined(IPv6) && defined(AF_INET6)
- if (aifirst != NULL)
- freeaddrinfo(aifirst);
-#endif
- xdm_from = argv[i];
-}
-
-
-#if defined(IPv6) && defined(AF_INET6)
-static int
-get_mcast_options(int argc, char **argv, int i)
-{
- char *address = XDM_DEFAULT_MCAST_ADDR6;
- int hopcount = 1;
- struct addrinfo hints;
- char portstr[6];
- int gaierr;
- struct addrinfo *ai, *firstai;
-
- if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) {
- address = argv[i++];
- if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) {
- hopcount = strtol(argv[i++], NULL, 10);
- if ((hopcount < 1) || (hopcount > 255)) {
- FatalError("Xserver: multicast hop count out of range: %d\n",
- hopcount);
- }
- }
- }
-
- if (xdm_udp_port > 0 && xdm_udp_port < 65535) {
- sprintf(portstr, "%d", xdm_udp_port);
- } else {
- FatalError("Xserver: port out of range: %d\n", xdm_udp_port);
- }
- bzero(&hints, sizeof(hints));
- hints.ai_socktype = SOCK_DGRAM;
-
- if ((gaierr = getaddrinfo(address, portstr, &hints, &firstai)) == 0) {
- for (ai = firstai; ai != NULL; ai = ai->ai_next) {
- if (((ai->ai_family == AF_INET) &&
- IN_MULTICAST(((struct sockaddr_in *) ai->ai_addr)
- ->sin_addr.s_addr))
- || ((ai->ai_family == AF_INET6) &&
- IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *) ai->ai_addr)
- ->sin6_addr)))
- break;
- }
- if (ai == NULL) {
- FatalError ("Xserver: address not supported multicast type %s\n",
- address);
- } else {
- struct multicastinfo *mcastinfo, *mcl;
-
- mcastinfo = malloc(sizeof(struct multicastinfo));
- mcastinfo->next = NULL;
- mcastinfo->ai = firstai;
- mcastinfo->hops = hopcount;
-
- if (mcastlist == NULL) {
- mcastlist = mcastinfo;
- } else {
- for (mcl = mcastlist; mcl->next != NULL; mcl = mcl->next) {
- /* Do nothing - just find end of list */
- }
- mcl->next = mcastinfo;
- }
- }
- } else {
- FatalError("Xserver: %s: %s\n", gai_strerror(gaierr), address);
- }
- return i;
-}
-#endif
-
-#else
-static int xdmcp_non_empty; /* avoid complaint by ranlib */
-#endif /* XDMCP */
+/*
+ * Copyright 1989 Network Computing Devices, Inc., Mountain View, California.
+ *
+ * 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 N.C.D. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. N.C.D. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifdef WIN32
+#include <X11/Xwinsock.h>
+#endif
+
+#include <X11/Xos.h>
+
+#if !defined(WIN32)
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#endif
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <X11/X.h>
+#include <X11/Xmd.h>
+#include "misc.h"
+#include <X11/Xpoll.h>
+#include "osdep.h"
+#include "input.h"
+#include "dixstruct.h"
+#include "opaque.h"
+#include "site.h"
+
+#ifdef STREAMSCONN
+#include <tiuser.h>
+#include <netconfig.h>
+#include <netdir.h>
+#endif
+
+#ifdef XDMCP
+#undef REQUEST
+
+#ifdef XDMCP_NO_IPV6
+#undef IPv6
+#endif
+
+#include <X11/Xdmcp.h>
+
+#define X_INCLUDE_NETDB_H
+#include <X11/Xos_r.h>
+
+static char *defaultDisplayClass = COMPILEDDISPLAYCLASS;
+
+static int xdmcpSocket, sessionSocket;
+static xdmcp_states state;
+#if defined(IPv6) && defined(AF_INET6)
+static int xdmcpSocket6;
+static struct sockaddr_storage req_sockaddr;
+#else
+static struct sockaddr_in req_sockaddr;
+#endif
+static int req_socklen;
+static CARD32 SessionID;
+static CARD32 timeOutTime;
+static int timeOutRtx;
+static CARD32 defaultKeepaliveDormancy = XDM_DEF_DORMANCY;
+static CARD32 keepaliveDormancy = XDM_DEF_DORMANCY;
+static CARD16 DisplayNumber;
+static xdmcp_states XDM_INIT_STATE = XDM_OFF;
+#ifdef HASXDMAUTH
+static char *xdmAuthCookie;
+#endif
+
+static XdmcpBuffer buffer;
+
+#if defined(IPv6) && defined(AF_INET6)
+
+static struct addrinfo *mgrAddr;
+static struct addrinfo *mgrAddrFirst;
+
+#define SOCKADDR_TYPE struct sockaddr_storage
+#define SOCKADDR_FAMILY(s) ((struct sockaddr *)&(s))->sa_family
+
+#ifdef BSD44SOCKETS
+#define SOCKLEN_FIELD(s) ((struct sockaddr *)&(s))->sa_len
+#define SOCKLEN_TYPE unsigned char
+#else
+#define SOCKLEN_TYPE unsigned int
+#endif
+
+#else
+
+#define SOCKADDR_TYPE struct sockaddr_in
+#define SOCKADDR_FAMILY(s) (s).sin_family
+
+#ifdef BSD44SOCKETS
+#define SOCKLEN_FIELD(s) (s).sin_len
+#define SOCKLEN_TYPE unsigned char
+#else
+#define SOCKLEN_TYPE size_t
+#endif
+
+#endif
+
+static SOCKADDR_TYPE ManagerAddress;
+static SOCKADDR_TYPE FromAddress;
+
+#ifdef SOCKLEN_FIELD
+#define ManagerAddressLen SOCKLEN_FIELD(ManagerAddress)
+#define FromAddressLen SOCKLEN_FIELD(FromAddress)
+#else
+static SOCKLEN_TYPE ManagerAddressLen, FromAddressLen;
+#endif
+
+#if defined(IPv6) && defined(AF_INET6)
+static struct multicastinfo {
+ struct multicastinfo *next;
+ struct addrinfo *ai;
+ int hops;
+} *mcastlist;
+#endif
+
+static void XdmcpAddHost(
+ const struct sockaddr *from,
+ int fromlen,
+ ARRAY8Ptr AuthenticationName,
+ ARRAY8Ptr hostname,
+ ARRAY8Ptr status);
+
+static void XdmcpSelectHost(
+ const struct sockaddr *host_sockaddr,
+ int host_len,
+ ARRAY8Ptr AuthenticationName);
+
+static void get_xdmcp_sock(void);
+
+static void send_query_msg(void);
+
+static void recv_willing_msg(
+ struct sockaddr * /*from*/,
+ int /*fromlen*/,
+ unsigned /*length*/);
+
+static void send_request_msg(void);
+
+static void recv_accept_msg(unsigned /*length*/);
+
+static void recv_decline_msg(unsigned /*length*/);
+
+static void send_manage_msg(void);
+
+static void recv_refuse_msg(unsigned /*length*/);
+
+static void recv_failed_msg(unsigned /*length*/);
+
+static void send_keepalive_msg(void);
+
+static void recv_alive_msg(unsigned /*length*/);
+
+static void XdmcpFatal(
+ const char * /*type*/,
+ ARRAY8Ptr /*status*/);
+
+static void XdmcpWarning(const char * /*str*/);
+
+static void get_manager_by_name(
+ int /*argc*/,
+ char ** /*argv*/,
+ int /*i*/);
+
+static void get_fromaddr_by_name(int /*argc*/, char ** /*argv*/, int /*i*/);
+
+#if defined(IPv6) && defined(AF_INET6)
+static int get_mcast_options(int /*argc*/, char ** /*argv*/, int /*i*/);
+#endif
+
+static void receive_packet(int /*socketfd*/);
+
+static void send_packet(void);
+
+static void timeout(void);
+
+static void restart(void);
+
+static void XdmcpBlockHandler(
+ pointer /*data*/,
+ struct timeval ** /*wt*/,
+ pointer /*LastSelectMask*/);
+
+static void XdmcpWakeupHandler(
+ pointer /*data*/,
+ int /*i*/,
+ pointer /*LastSelectMask*/);
+
+#define XSERV_t
+#define TRANS_SERVER
+#define TRANS_REOPEN
+#include <X11/Xtrans/Xtrans.h>
+
+/*
+ * Register the Manufacturer display ID
+ */
+
+static ARRAY8 ManufacturerDisplayID;
+
+static void
+XdmcpRegisterManufacturerDisplayID (const char *name, int length)
+{
+ int i;
+
+ XdmcpDisposeARRAY8 (&ManufacturerDisplayID);
+ if (!XdmcpAllocARRAY8 (&ManufacturerDisplayID, length))
+ return;
+ for (i = 0; i < length; i++)
+ ManufacturerDisplayID.data[i] = (CARD8) name[i];
+}
+
+static unsigned short xdm_udp_port = XDM_UDP_PORT;
+static Bool OneSession = FALSE;
+static const char *xdm_from = NULL;
+
+void
+XdmcpUseMsg (void)
+{
+ ErrorF("-query host-name contact named host for XDMCP\n");
+ ErrorF("-broadcast broadcast for XDMCP\n");
+#if defined(IPv6) && defined(AF_INET6)
+ ErrorF("-multicast [addr [hops]] IPv6 multicast for XDMCP\n");
+#endif
+ ErrorF("-indirect host-name contact named host for indirect XDMCP\n");
+ ErrorF("-port port-num UDP port number to send messages to\n");
+ ErrorF("-from local-address specify the local address to connect from\n");
+ ErrorF("-once Terminate server after one session\n");
+ ErrorF("-class display-class specify display class to send in manage\n");
+#ifdef HASXDMAUTH
+ ErrorF("-cookie xdm-auth-bits specify the magic cookie for XDMCP\n");
+#endif
+ ErrorF("-displayID display-id manufacturer display ID for request\n");
+}
+
+int
+XdmcpOptions(int argc, char **argv, int i)
+{
+ if (strcmp(argv[i], "-query") == 0) {
+ get_manager_by_name(argc, argv, i++);
+ XDM_INIT_STATE = XDM_QUERY;
+ AccessUsingXdmcp ();
+ return (i + 1);
+ }
+ if (strcmp(argv[i], "-broadcast") == 0) {
+ XDM_INIT_STATE = XDM_BROADCAST;
+ AccessUsingXdmcp ();
+ return (i + 1);
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ if (strcmp(argv[i], "-multicast") == 0) {
+ i = get_mcast_options(argc, argv, ++i);
+ XDM_INIT_STATE = XDM_MULTICAST;
+ AccessUsingXdmcp ();
+ return (i + 1);
+ }
+#endif
+ if (strcmp(argv[i], "-indirect") == 0) {
+ get_manager_by_name(argc, argv, i++);
+ XDM_INIT_STATE = XDM_INDIRECT;
+ AccessUsingXdmcp ();
+ return (i + 1);
+ }
+ if (strcmp(argv[i], "-port") == 0) {
+ if (++i == argc) {
+ FatalError("Xserver: missing port number in command line\n");
+ }
+ xdm_udp_port = (unsigned short) atoi(argv[i]);
+ return (i + 1);
+ }
+ if (strcmp(argv[i], "-from") == 0) {
+ get_fromaddr_by_name(argc, argv, ++i);
+ return (i + 1);
+ }
+ if (strcmp(argv[i], "-once") == 0) {
+ OneSession = TRUE;
+ return (i + 1);
+ }
+ if (strcmp(argv[i], "-class") == 0) {
+ if (++i == argc) {
+ FatalError("Xserver: missing class name in command line\n");
+ }
+ defaultDisplayClass = argv[i];
+ return (i + 1);
+ }
+#ifdef HASXDMAUTH
+ if (strcmp(argv[i], "-cookie") == 0) {
+ if (++i == argc) {
+ FatalError("Xserver: missing cookie data in command line\n");
+ }
+ xdmAuthCookie = argv[i];
+ return (i + 1);
+ }
+#endif
+ if (strcmp(argv[i], "-displayID") == 0) {
+ if (++i == argc) {
+ FatalError("Xserver: missing displayID in command line\n");
+ }
+ XdmcpRegisterManufacturerDisplayID (argv[i], strlen (argv[i]));
+ return (i + 1);
+ }
+ return (i);
+}
+
+/*
+ * This section is a collection of routines for
+ * registering server-specific data with the XDMCP
+ * state machine.
+ */
+
+
+/*
+ * Save all broadcast addresses away so BroadcastQuery
+ * packets get sent everywhere
+ */
+
+#define MAX_BROADCAST 10
+
+/* This stays sockaddr_in since IPv6 doesn't support broadcast */
+static struct sockaddr_in BroadcastAddresses[MAX_BROADCAST];
+static int NumBroadcastAddresses;
+
+void
+XdmcpRegisterBroadcastAddress (const struct sockaddr_in *addr)
+{
+ struct sockaddr_in *bcast;
+ if (NumBroadcastAddresses >= MAX_BROADCAST)
+ return;
+ bcast = &BroadcastAddresses[NumBroadcastAddresses++];
+ bzero (bcast, sizeof (struct sockaddr_in));
+#ifdef BSD44SOCKETS
+ bcast->sin_len = addr->sin_len;
+#endif
+ bcast->sin_family = addr->sin_family;
+ bcast->sin_port = htons (xdm_udp_port);
+ bcast->sin_addr = addr->sin_addr;
+}
+
+/*
+ * Each authentication type is registered here; Validator
+ * will be called to check all access attempts using
+ * the specified authentication type
+ */
+
+static ARRAYofARRAY8 AuthenticationNames, AuthenticationDatas;
+typedef struct _AuthenticationFuncs {
+ ValidatorFunc Validator;
+ GeneratorFunc Generator;
+ AddAuthorFunc AddAuth;
+} AuthenticationFuncsRec, *AuthenticationFuncsPtr;
+
+static AuthenticationFuncsPtr AuthenticationFuncsList;
+
+void
+XdmcpRegisterAuthentication (
+ const char *name,
+ int namelen,
+ const char *data,
+ int datalen,
+ ValidatorFunc Validator,
+ GeneratorFunc Generator,
+ AddAuthorFunc AddAuth)
+{
+ int i;
+ ARRAY8 AuthenticationName, AuthenticationData;
+ static AuthenticationFuncsPtr newFuncs;
+
+ if (!XdmcpAllocARRAY8 (&AuthenticationName, namelen))
+ return;
+ if (!XdmcpAllocARRAY8 (&AuthenticationData, datalen))
+ {
+ XdmcpDisposeARRAY8 (&AuthenticationName);
+ return;
+ }
+ for (i = 0; i < namelen; i++)
+ AuthenticationName.data[i] = name[i];
+ for (i = 0; i < datalen; i++)
+ AuthenticationData.data[i] = data[i];
+ if (!(XdmcpReallocARRAYofARRAY8 (&AuthenticationNames,
+ AuthenticationNames.length + 1) &&
+ XdmcpReallocARRAYofARRAY8 (&AuthenticationDatas,
+ AuthenticationDatas.length + 1) &&
+ (newFuncs = xalloc ((AuthenticationNames.length + 1) * sizeof (AuthenticationFuncsRec)))))
+ {
+ XdmcpDisposeARRAY8 (&AuthenticationName);
+ XdmcpDisposeARRAY8 (&AuthenticationData);
+ return;
+ }
+ for (i = 0; i < AuthenticationNames.length - 1; i++)
+ newFuncs[i] = AuthenticationFuncsList[i];
+ newFuncs[AuthenticationNames.length-1].Validator = Validator;
+ newFuncs[AuthenticationNames.length-1].Generator = Generator;
+ newFuncs[AuthenticationNames.length-1].AddAuth = AddAuth;
+ xfree (AuthenticationFuncsList);
+ AuthenticationFuncsList = newFuncs;
+ AuthenticationNames.data[AuthenticationNames.length-1] = AuthenticationName;
+ AuthenticationDatas.data[AuthenticationDatas.length-1] = AuthenticationData;
+}
+
+/*
+ * Select the authentication type to be used; this is
+ * set by the manager of the host to be connected to.
+ */
+
+static ARRAY8 noAuthenticationName = {(CARD16) 0, (CARD8Ptr) 0};
+static ARRAY8 noAuthenticationData = {(CARD16) 0, (CARD8Ptr) 0};
+static ARRAY8Ptr AuthenticationName = &noAuthenticationName;
+static ARRAY8Ptr AuthenticationData = &noAuthenticationData;
+static AuthenticationFuncsPtr AuthenticationFuncs;
+
+static void
+XdmcpSetAuthentication (const ARRAY8Ptr name)
+{
+ int i;
+
+ for (i = 0; i < AuthenticationNames.length; i++)
+ if (XdmcpARRAY8Equal (&AuthenticationNames.data[i], name))
+ {
+ AuthenticationName = &AuthenticationNames.data[i];
+ AuthenticationData = &AuthenticationDatas.data[i];
+ AuthenticationFuncs = &AuthenticationFuncsList[i];
+ break;
+ }
+}
+
+/*
+ * Register the host address for the display
+ */
+
+static ARRAY16 ConnectionTypes;
+static ARRAYofARRAY8 ConnectionAddresses;
+static long xdmcpGeneration;
+
+void
+XdmcpRegisterConnection (
+ int type,
+ const char *address,
+ int addrlen)
+{
+ int i;
+ CARD8 *newAddress;
+
+ if (xdmcpGeneration != serverGeneration)
+ {
+ XdmcpDisposeARRAY16 (&ConnectionTypes);
+ XdmcpDisposeARRAYofARRAY8 (&ConnectionAddresses);
+ xdmcpGeneration = serverGeneration;
+ }
+ if (xdm_from != NULL) { /* Only register the requested address */
+ const void *regAddr = address;
+ const void *fromAddr = NULL;
+ int regAddrlen = addrlen;
+
+ if (addrlen == sizeof(struct in_addr)) {
+ if (SOCKADDR_FAMILY(FromAddress) == AF_INET) {
+ fromAddr = &((struct sockaddr_in *)&FromAddress)->sin_addr;
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET6) &&
+ IN6_IS_ADDR_V4MAPPED(
+ &((struct sockaddr_in6 *)&FromAddress)->sin6_addr)) {
+ fromAddr = &((struct sockaddr_in6 *)&FromAddress)->sin6_addr.s6_addr[12];
+ }
+#endif
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (addrlen == sizeof(struct in6_addr)) {
+ if (SOCKADDR_FAMILY(FromAddress) == AF_INET6) {
+ fromAddr = &((struct sockaddr_in6 *)&FromAddress)->sin6_addr;
+ } else if ((SOCKADDR_FAMILY(FromAddress) == AF_INET) &&
+ IN6_IS_ADDR_V4MAPPED((struct in6_addr *) address)) {
+ fromAddr = &((struct sockaddr_in *)&FromAddress)->sin_addr;
+ regAddr = &((struct sockaddr_in6 *)&address)->sin6_addr.s6_addr[12];
+ regAddrlen = sizeof(struct in_addr);
+ }
+ }
+#endif
+ if (fromAddr && memcmp(regAddr, fromAddr, regAddrlen) != 0) {
+ return;
+ }
+ }
+ if (ConnectionAddresses.length + 1 == 256)
+ return;
+ newAddress = xalloc (addrlen * sizeof (CARD8));
+ if (!newAddress)
+ return;
+ if (!XdmcpReallocARRAY16 (&ConnectionTypes, ConnectionTypes.length + 1))
+ {
+ xfree (newAddress);
+ return;
+ }
+ if (!XdmcpReallocARRAYofARRAY8 (&ConnectionAddresses,
+ ConnectionAddresses.length + 1))
+ {
+ xfree (newAddress);
+ return;
+ }
+ ConnectionTypes.data[ConnectionTypes.length - 1] = (CARD16) type;
+ for (i = 0; i < addrlen; i++)
+ newAddress[i] = address[i];
+ ConnectionAddresses.data[ConnectionAddresses.length-1].data = newAddress;
+ ConnectionAddresses.data[ConnectionAddresses.length-1].length = addrlen;
+}
+
+/*
+ * Register an Authorization Name. XDMCP advertises this list
+ * to the manager.
+ */
+
+static ARRAYofARRAY8 AuthorizationNames;
+
+void
+XdmcpRegisterAuthorizations (void)
+{
+ XdmcpDisposeARRAYofARRAY8 (&AuthorizationNames);
+ RegisterAuthorizations ();
+}
+
+void
+XdmcpRegisterAuthorization (const char *name, int namelen)
+{
+ ARRAY8 authName;
+ int i;
+
+ authName.data = xalloc (namelen * sizeof (CARD8));
+ if (!authName.data)
+ return;
+ if (!XdmcpReallocARRAYofARRAY8 (&AuthorizationNames, AuthorizationNames.length +1))
+ {
+ xfree (authName.data);
+ return;
+ }
+ for (i = 0; i < namelen; i++)
+ authName.data[i] = (CARD8) name[i];
+ authName.length = namelen;
+ AuthorizationNames.data[AuthorizationNames.length-1] = authName;
+}
+
+/*
+ * Register the DisplayClass string
+ */
+
+static ARRAY8 DisplayClass;
+
+static void
+XdmcpRegisterDisplayClass (const char *name, int length)
+{
+ int i;
+
+ XdmcpDisposeARRAY8 (&DisplayClass);
+ if (!XdmcpAllocARRAY8 (&DisplayClass, length))
+ return;
+ for (i = 0; i < length; i++)
+ DisplayClass.data[i] = (CARD8) name[i];
+}
+
+/*
+ * initialize XDMCP; create the socket, compute the display
+ * number, set up the state machine
+ */
+
+void
+XdmcpInit(void)
+{
+ state = XDM_INIT_STATE;
+#ifdef HASXDMAUTH
+ if (xdmAuthCookie)
+ XdmAuthenticationInit (xdmAuthCookie, strlen (xdmAuthCookie));
+#endif
+ if (state != XDM_OFF)
+ {
+ XdmcpRegisterAuthorizations();
+ XdmcpRegisterDisplayClass (defaultDisplayClass, strlen (defaultDisplayClass));
+ AccessUsingXdmcp();
+ RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler,
+ (pointer) 0);
+ timeOutRtx = 0;
+ DisplayNumber = (CARD16) atoi(display);
+ get_xdmcp_sock();
+ send_packet();
+ }
+}
+
+void
+XdmcpReset (void)
+{
+ state = XDM_INIT_STATE;
+ if (state != XDM_OFF)
+ {
+ RegisterBlockAndWakeupHandlers (XdmcpBlockHandler, XdmcpWakeupHandler,
+ (pointer) 0);
+ timeOutRtx = 0;
+ send_packet();
+ }
+}
+
+/*
+ * Called whenever a new connection is created; notices the
+ * first connection and saves it to terminate the session
+ * when it is closed
+ */
+
+void
+XdmcpOpenDisplay(int sock)
+{
+ if (state != XDM_AWAIT_MANAGE_RESPONSE)
+ return;
+ state = XDM_RUN_SESSION;
+ sessionSocket = sock;
+}
+
+void
+XdmcpCloseDisplay(int sock)
+{
+ if ((state != XDM_RUN_SESSION && state != XDM_AWAIT_ALIVE_RESPONSE)
+ || sessionSocket != sock)
+ return;
+ state = XDM_INIT_STATE;
+ if (OneSession)
+ dispatchException |= DE_TERMINATE;
+ else
+ dispatchException |= DE_RESET;
+ isItTimeToYield = TRUE;
+}
+
+/*
+ * called before going to sleep, this routine
+ * may modify the timeout value about to be sent
+ * to select; in this way XDMCP can do appropriate things
+ * dynamically while starting up
+ */
+
+/*ARGSUSED*/
+static void
+XdmcpBlockHandler(
+ pointer data, /* unused */
+ struct timeval **wt,
+ pointer pReadmask)
+{
+ fd_set *LastSelectMask = (fd_set*)pReadmask;
+ CARD32 millisToGo;
+
+ if (state == XDM_OFF)
+ return;
+ FD_SET(xdmcpSocket, LastSelectMask);
+#if defined(IPv6) && defined(AF_INET6)
+ if (xdmcpSocket6 >= 0)
+ FD_SET(xdmcpSocket6, LastSelectMask);
+#endif
+ if (timeOutTime == 0)
+ return;
+ millisToGo = timeOutTime - GetTimeInMillis();
+ if ((int) millisToGo < 0)
+ millisToGo = 0;
+ AdjustWaitForDelay (wt, millisToGo);
+}
+
+/*
+ * called after select returns; this routine will
+ * recognise when XDMCP packets await and
+ * process them appropriately
+ */
+
+/*ARGSUSED*/
+static void
+XdmcpWakeupHandler(
+ pointer data, /* unused */
+ int i,
+ pointer pReadmask)
+{
+ fd_set* LastSelectMask = (fd_set*)pReadmask;
+ fd_set devicesReadable;
+
+ if (state == XDM_OFF)
+ return;
+ if (i > 0)
+ {
+ if (FD_ISSET(xdmcpSocket, LastSelectMask))
+ {
+ receive_packet(xdmcpSocket);
+ FD_CLR(xdmcpSocket, LastSelectMask);
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ if (xdmcpSocket6 >= 0 && FD_ISSET(xdmcpSocket6, LastSelectMask))
+ {
+ receive_packet(xdmcpSocket6);
+ FD_CLR(xdmcpSocket6, LastSelectMask);
+ }
+#endif
+ XFD_ANDSET(&devicesReadable, LastSelectMask, &EnabledDevices);
+ if (XFD_ANYSET(&devicesReadable))
+ {
+ if (state == XDM_AWAIT_USER_INPUT)
+ restart();
+ else if (state == XDM_RUN_SESSION)
+ keepaliveDormancy = defaultKeepaliveDormancy;
+ }
+ if (XFD_ANYSET(&AllClients) && state == XDM_RUN_SESSION)
+ timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000;
+ }
+ else if (timeOutTime && (int) (GetTimeInMillis() - timeOutTime) >= 0)
+ {
+ if (state == XDM_RUN_SESSION)
+ {
+ state = XDM_KEEPALIVE;
+ send_packet();
+ }
+ else
+ timeout();
+ }
+}
+
+/*
+ * This routine should be called from the routine that drives the
+ * user's host menu when the user selects a host
+ */
+
+static void
+XdmcpSelectHost(
+ const struct sockaddr *host_sockaddr,
+ int host_len,
+ ARRAY8Ptr AuthenticationName)
+{
+ state = XDM_START_CONNECTION;
+ memmove(&req_sockaddr, host_sockaddr, host_len);
+ req_socklen = host_len;
+ XdmcpSetAuthentication (AuthenticationName);
+ send_packet();
+}
+
+/*
+ * !!! this routine should be replaced by a routine that adds
+ * the host to the user's host menu. the current version just
+ * selects the first host to respond with willing message.
+ */
+
+/*ARGSUSED*/
+static void
+XdmcpAddHost(
+ const struct sockaddr *from,
+ int fromlen,
+ ARRAY8Ptr AuthenticationName,
+ ARRAY8Ptr hostname,
+ ARRAY8Ptr status)
+{
+ XdmcpSelectHost(from, fromlen, AuthenticationName);
+}
+
+/*
+ * A message is queued on the socket; read it and
+ * do the appropriate thing
+ */
+
+static ARRAY8 UnwillingMessage = { (CARD8) 14, (CARD8 *) "Host unwilling" };
+
+static void
+receive_packet(int socketfd)
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct sockaddr_storage from;
+#else
+ struct sockaddr_in from;
+#endif
+ int fromlen = sizeof(from);
+ XdmcpHeader header;
+
+ /* read message off socket */
+ if (!XdmcpFill (socketfd, &buffer, (XdmcpNetaddr) &from, &fromlen))
+ return;
+
+ /* reset retransmission backoff */
+ timeOutRtx = 0;
+
+ if (!XdmcpReadHeader (&buffer, &header))
+ return;
+
+ if (header.version != XDM_PROTOCOL_VERSION)
+ return;
+
+ switch (header.opcode) {
+ case WILLING:
+ recv_willing_msg((struct sockaddr *) &from, fromlen, header.length);
+ break;
+ case UNWILLING:
+ XdmcpFatal("Manager unwilling", &UnwillingMessage);
+ break;
+ case ACCEPT:
+ recv_accept_msg(header.length);
+ break;
+ case DECLINE:
+ recv_decline_msg(header.length);
+ break;
+ case REFUSE:
+ recv_refuse_msg(header.length);
+ break;
+ case FAILED:
+ recv_failed_msg(header.length);
+ break;
+ case ALIVE:
+ recv_alive_msg(header.length);
+ break;
+ }
+}
+
+/*
+ * send the appropriate message given the current state
+ */
+
+static void
+send_packet(void)
+{
+ int rtx;
+ switch (state) {
+ case XDM_QUERY:
+ case XDM_BROADCAST:
+ case XDM_INDIRECT:
+#if defined(IPv6) && defined(AF_INET6)
+ case XDM_MULTICAST:
+#endif
+ send_query_msg();
+ break;
+ case XDM_START_CONNECTION:
+ send_request_msg();
+ break;
+ case XDM_MANAGE:
+ send_manage_msg();
+ break;
+ case XDM_KEEPALIVE:
+ send_keepalive_msg();
+ break;
+ default:
+ break;
+ }
+ rtx = (XDM_MIN_RTX << timeOutRtx);
+ if (rtx > XDM_MAX_RTX)
+ rtx = XDM_MAX_RTX;
+ timeOutTime = GetTimeInMillis() + rtx * 1000;
+}
+
+/*
+ * The session is declared dead for some reason; too many
+ * timeouts, or Keepalive failure.
+ */
+
+static void
+XdmcpDeadSession (const char *reason)
+{
+ ErrorF ("XDM: %s, declaring session dead\n", reason);
+ state = XDM_INIT_STATE;
+ isItTimeToYield = TRUE;
+ dispatchException |= DE_RESET;
+ timeOutTime = 0;
+ timeOutRtx = 0;
+ send_packet();
+}
+
+/*
+ * Timeout waiting for an XDMCP response.
+ */
+
+static void
+timeout(void)
+{
+ timeOutRtx++;
+ if (state == XDM_AWAIT_ALIVE_RESPONSE && timeOutRtx >= XDM_KA_RTX_LIMIT )
+ {
+ XdmcpDeadSession ("too many keepalive retransmissions");
+ return;
+ }
+ else if (timeOutRtx >= XDM_RTX_LIMIT)
+ {
+ /* Quit if "-once" specified, otherwise reset and try again. */
+ if (OneSession) {
+ dispatchException |= DE_TERMINATE;
+ ErrorF("XDM: too many retransmissions\n");
+ } else {
+ XdmcpDeadSession("too many retransmissions");
+ }
+ return;
+ }
+
+#if defined(IPv6) && defined(AF_INET6)
+ if (state == XDM_COLLECT_QUERY || state == XDM_COLLECT_INDIRECT_QUERY) {
+ /* Try next address */
+ for (mgrAddr = mgrAddr->ai_next; ; mgrAddr = mgrAddr->ai_next) {
+ if (mgrAddr == NULL) {
+ mgrAddr = mgrAddrFirst;
+ }
+ if (mgrAddr->ai_family == AF_INET
+ || mgrAddr->ai_family == AF_INET6)
+ break;
+ }
+#ifndef SIN6_LEN
+ ManagerAddressLen = mgrAddr->ai_addrlen;
+#endif
+ memcpy(&ManagerAddress, mgrAddr->ai_addr, mgrAddr->ai_addrlen);
+ }
+#endif
+
+ switch (state) {
+ case XDM_COLLECT_QUERY:
+ state = XDM_QUERY;
+ break;
+ case XDM_COLLECT_BROADCAST_QUERY:
+ state = XDM_BROADCAST;
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case XDM_COLLECT_MULTICAST_QUERY:
+ state = XDM_MULTICAST;
+ break;
+#endif
+ case XDM_COLLECT_INDIRECT_QUERY:
+ state = XDM_INDIRECT;
+ break;
+ case XDM_AWAIT_REQUEST_RESPONSE:
+ state = XDM_START_CONNECTION;
+ break;
+ case XDM_AWAIT_MANAGE_RESPONSE:
+ state = XDM_MANAGE;
+ break;
+ case XDM_AWAIT_ALIVE_RESPONSE:
+ state = XDM_KEEPALIVE;
+ break;
+ default:
+ break;
+ }
+ send_packet();
+}
+
+static void
+restart(void)
+{
+ state = XDM_INIT_STATE;
+ timeOutRtx = 0;
+ send_packet();
+}
+
+static int
+XdmcpCheckAuthentication (ARRAY8Ptr Name, ARRAY8Ptr Data, int packet_type)
+{
+ return (XdmcpARRAY8Equal (Name, AuthenticationName) &&
+ (AuthenticationName->length == 0 ||
+ (*AuthenticationFuncs->Validator) (AuthenticationData, Data, packet_type)));
+}
+
+static int
+XdmcpAddAuthorization (ARRAY8Ptr name, ARRAY8Ptr data)
+{
+ AddAuthorFunc AddAuth;
+
+ if (AuthenticationFuncs && AuthenticationFuncs->AddAuth)
+ AddAuth = AuthenticationFuncs->AddAuth;
+ else
+ AddAuth = AddAuthorization;
+ return (*AddAuth) ((unsigned short)name->length,
+ (char *)name->data,
+ (unsigned short)data->length,
+ (char *)data->data);
+}
+
+/*
+ * from here to the end of this file are routines private
+ * to the state machine.
+ */
+
+static void
+get_xdmcp_sock(void)
+{
+#ifdef STREAMSCONN
+ struct netconfig *nconf;
+
+ if ((xdmcpSocket = t_open("/dev/udp", O_RDWR, 0)) < 0) {
+ XdmcpWarning("t_open() of /dev/udp failed");
+ return;
+ }
+
+ if( t_bind(xdmcpSocket,NULL,NULL) < 0 ) {
+ XdmcpWarning("UDP socket creation failed");
+ t_error("t_bind(xdmcpSocket) failed" );
+ t_close(xdmcpSocket);
+ return;
+ }
+
+ /*
+ * This part of the code looks contrived. It will actually fit in nicely
+ * when the CLTS part of Xtrans is implemented.
+ */
+
+ if( (nconf=getnetconfigent("udp")) == NULL ) {
+ XdmcpWarning("UDP socket creation failed: getnetconfigent()");
+ t_unbind(xdmcpSocket);
+ t_close(xdmcpSocket);
+ return;
+ }
+
+ if( netdir_options(nconf, ND_SET_BROADCAST, xdmcpSocket, NULL) ) {
+ XdmcpWarning("UDP set broadcast option failed: netdir_options()");
+ freenetconfigent(nconf);
+ t_unbind(xdmcpSocket);
+ t_close(xdmcpSocket);
+ return;
+ }
+
+ freenetconfigent(nconf);
+#else
+ int soopts = 1;
+
+#if defined(IPv6) && defined(AF_INET6)
+ if ((xdmcpSocket6 = socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
+ XdmcpWarning("INET6 UDP socket creation failed");
+#endif
+ if ((xdmcpSocket = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ XdmcpWarning("UDP socket creation failed");
+#ifdef SO_BROADCAST
+ else if (setsockopt(xdmcpSocket, SOL_SOCKET, SO_BROADCAST, (char *)&soopts,
+ sizeof(soopts)) < 0)
+ XdmcpWarning("UDP set broadcast socket-option failed");
+#endif /* SO_BROADCAST */
+ if (xdmcpSocket >= 0 && xdm_from != NULL) {
+ if (bind(xdmcpSocket, (struct sockaddr *)&FromAddress,
+ FromAddressLen) < 0) {
+ FatalError("Xserver: failed to bind to -from address: %s\n", xdm_from);
+ }
+ }
+#endif /* STREAMSCONN */
+}
+
+static void
+send_query_msg(void)
+{
+ XdmcpHeader header;
+ Bool broadcast = FALSE;
+#if defined(IPv6) && defined(AF_INET6)
+ Bool multicast = FALSE;
+#endif
+ int i;
+ int socketfd = xdmcpSocket;
+
+ header.version = XDM_PROTOCOL_VERSION;
+ switch(state){
+ case XDM_QUERY:
+ header.opcode = (CARD16) QUERY;
+ state = XDM_COLLECT_QUERY;
+ break;
+ case XDM_BROADCAST:
+ header.opcode = (CARD16) BROADCAST_QUERY;
+ state = XDM_COLLECT_BROADCAST_QUERY;
+ broadcast = TRUE;
+ break;
+#if defined(IPv6) && defined(AF_INET6)
+ case XDM_MULTICAST:
+ header.opcode = (CARD16) BROADCAST_QUERY;
+ state = XDM_COLLECT_MULTICAST_QUERY;
+ multicast = TRUE;
+ break;
+#endif
+ case XDM_INDIRECT:
+ header.opcode = (CARD16) INDIRECT_QUERY;
+ state = XDM_COLLECT_INDIRECT_QUERY;
+ break;
+ default:
+ break;
+ }
+ header.length = 1;
+ for (i = 0; i < AuthenticationNames.length; i++)
+ header.length += 2 + AuthenticationNames.data[i].length;
+
+ XdmcpWriteHeader (&buffer, &header);
+ XdmcpWriteARRAYofARRAY8 (&buffer, &AuthenticationNames);
+ if (broadcast)
+ {
+ int i;
+
+ for (i = 0; i < NumBroadcastAddresses; i++)
+ XdmcpFlush (xdmcpSocket, &buffer, (XdmcpNetaddr) &BroadcastAddresses[i],
+ sizeof (struct sockaddr_in));
+ }
+#if defined(IPv6) && defined(AF_INET6)
+ else if (multicast)
+ {
+ struct multicastinfo *mcl;
+ struct addrinfo *ai;
+
+ for (mcl = mcastlist; mcl != NULL; mcl = mcl->next) {
+ for (ai = mcl->ai ; ai != NULL; ai = ai->ai_next) {
+ if (ai->ai_family == AF_INET) {
+ unsigned char hopflag = (unsigned char) mcl->hops;
+ socketfd = xdmcpSocket;
+ setsockopt(socketfd, IPPROTO_IP, IP_MULTICAST_TTL,
+ &hopflag, sizeof(hopflag));
+ } else if (ai->ai_family == AF_INET6) {
+ int hopflag6 = mcl->hops;
+ socketfd = xdmcpSocket6;
+ setsockopt(socketfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ &hopflag6, sizeof(hopflag6));
+ } else {
+ continue;
+ }
+ XdmcpFlush (socketfd, &buffer,
+ (XdmcpNetaddr) ai->ai_addr, ai->ai_addrlen);
+ break;
+ }
+ }
+ }
+#endif
+ else
+ {
+#if defined(IPv6) && defined(AF_INET6)
+ if (SOCKADDR_FAMILY(ManagerAddress) == AF_INET6)
+ socketfd = xdmcpSocket6;
+#endif
+ XdmcpFlush (socketfd, &buffer, (XdmcpNetaddr) &ManagerAddress,
+ ManagerAddressLen);
+ }
+}
+
+static void
+recv_willing_msg(
+ struct sockaddr *from,
+ int fromlen,
+ unsigned length)
+{
+ ARRAY8 authenticationName;
+ ARRAY8 hostname;
+ ARRAY8 status;
+
+ authenticationName.data = 0;
+ hostname.data = 0;
+ status.data = 0;
+ if (XdmcpReadARRAY8 (&buffer, &authenticationName) &&
+ XdmcpReadARRAY8 (&buffer, &hostname) &&
+ XdmcpReadARRAY8 (&buffer, &status))
+ {
+ if (length == 6 + authenticationName.length +
+ hostname.length + status.length)
+ {
+ switch (state)
+ {
+ case XDM_COLLECT_QUERY:
+ XdmcpSelectHost(from, fromlen, &authenticationName);
+ break;
+ case XDM_COLLECT_BROADCAST_QUERY:
+#if defined(IPv6) && defined(AF_INET6)
+ case XDM_COLLECT_MULTICAST_QUERY:
+#endif
+ case XDM_COLLECT_INDIRECT_QUERY:
+ XdmcpAddHost(from, fromlen, &authenticationName, &hostname, &status);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ XdmcpDisposeARRAY8 (&authenticationName);
+ XdmcpDisposeARRAY8 (&hostname);
+ XdmcpDisposeARRAY8 (&status);
+}
+
+static void
+send_request_msg(void)
+{
+ XdmcpHeader header;
+ int length;
+ int i;
+ CARD16 XdmcpConnectionType;
+ ARRAY8 authenticationData;
+ int socketfd = xdmcpSocket;
+
+ switch (SOCKADDR_FAMILY(ManagerAddress))
+ {
+ case AF_INET: XdmcpConnectionType=FamilyInternet; break;
+#if defined(IPv6) && defined(AF_INET6)
+ case AF_INET6: XdmcpConnectionType=FamilyInternet6; break;
+#endif
+ default: XdmcpConnectionType=0xffff; break;
+ }
+
+ header.version = XDM_PROTOCOL_VERSION;
+ header.opcode = (CARD16) REQUEST;
+
+ length = 2; /* display number */
+ length += 1 + 2 * ConnectionTypes.length; /* connection types */
+ length += 1; /* connection addresses */
+ for (i = 0; i < ConnectionAddresses.length; i++)
+ length += 2 + ConnectionAddresses.data[i].length;
+ authenticationData.length = 0;
+ authenticationData.data = 0;
+ if (AuthenticationFuncs)
+ {
+ (*AuthenticationFuncs->Generator) (AuthenticationData,
+ &authenticationData,
+ REQUEST);
+ }
+ length += 2 + AuthenticationName->length; /* authentication name */
+ length += 2 + authenticationData.length; /* authentication data */
+ length += 1; /* authorization names */
+ for (i = 0; i < AuthorizationNames.length; i++)
+ length += 2 + AuthorizationNames.data[i].length;
+ length += 2 + ManufacturerDisplayID.length; /* display ID */
+ header.length = length;
+
+ if (!XdmcpWriteHeader (&buffer, &header))
+ {
+ XdmcpDisposeARRAY8 (&authenticationData);
+ return;
+ }
+ XdmcpWriteCARD16 (&buffer, DisplayNumber);
+ XdmcpWriteCARD8 (&buffer, ConnectionTypes.length);
+
+ /* The connection array is send reordered, so that connections of */
+ /* the same address type as the XDMCP manager connection are send */
+ /* first. This works around a bug in xdm. mario@klebsch.de */
+ for (i = 0; i < (int)ConnectionTypes.length; i++)
+ if (ConnectionTypes.data[i]==XdmcpConnectionType)
+ XdmcpWriteCARD16 (&buffer, ConnectionTypes.data[i]);
+ for (i = 0; i < (int)ConnectionTypes.length; i++)
+ if (ConnectionTypes.data[i]!=XdmcpConnectionType)
+ XdmcpWriteCARD16 (&buffer, ConnectionTypes.data[i]);
+
+ XdmcpWriteCARD8 (&buffer, ConnectionAddresses.length);
+ for (i = 0; i < (int)ConnectionAddresses.length; i++)
+ if ( (i<ConnectionTypes.length) &&
+ (ConnectionTypes.data[i]==XdmcpConnectionType) )
+ XdmcpWriteARRAY8 (&buffer, &ConnectionAddresses.data[i]);
+ for (i = 0; i < (int)ConnectionAddresses.length; i++)
+ if ( (i>=ConnectionTypes.length) ||
+ (ConnectionTypes.data[i]!=XdmcpConnectionType) )
+ XdmcpWriteARRAY8 (&buffer, &ConnectionAddresses.data[i]);
+
+ XdmcpWriteARRAY8 (&buffer, AuthenticationName);
+ XdmcpWriteARRAY8 (&buffer, &authenticationData);
+ XdmcpDisposeARRAY8 (&authenticationData);
+ XdmcpWriteARRAYofARRAY8 (&buffer, &AuthorizationNames);
+ XdmcpWriteARRAY8 (&buffer, &ManufacturerDisplayID);
+#if defined(IPv6) && defined(AF_INET6)
+ if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
+ socketfd = xdmcpSocket6;
+#endif
+ if (XdmcpFlush (socketfd, &buffer,
+ (XdmcpNetaddr) &req_sockaddr, req_socklen))
+ state = XDM_AWAIT_REQUEST_RESPONSE;
+}
+
+static void
+recv_accept_msg(unsigned length)
+{
+ CARD32 AcceptSessionID;
+ ARRAY8 AcceptAuthenticationName, AcceptAuthenticationData;
+ ARRAY8 AcceptAuthorizationName, AcceptAuthorizationData;
+
+ if (state != XDM_AWAIT_REQUEST_RESPONSE)
+ return;
+ AcceptAuthenticationName.data = 0;
+ AcceptAuthenticationData.data = 0;
+ AcceptAuthorizationName.data = 0;
+ AcceptAuthorizationData.data = 0;
+ if (XdmcpReadCARD32 (&buffer, &AcceptSessionID) &&
+ XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationName) &&
+ XdmcpReadARRAY8 (&buffer, &AcceptAuthenticationData) &&
+ XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationName) &&
+ XdmcpReadARRAY8 (&buffer, &AcceptAuthorizationData))
+ {
+ if (length == 12 + AcceptAuthenticationName.length +
+ AcceptAuthenticationData.length +
+ AcceptAuthorizationName.length +
+ AcceptAuthorizationData.length)
+ {
+ if (!XdmcpCheckAuthentication (&AcceptAuthenticationName,
+ &AcceptAuthenticationData, ACCEPT))
+ {
+ XdmcpFatal ("Authentication Failure", &AcceptAuthenticationName);
+ }
+ /* permit access control manipulations from this host */
+ AugmentSelf (&req_sockaddr, req_socklen);
+ /* if the authorization specified in the packet fails
+ * to be acceptable, enable the local addresses
+ */
+ if (!XdmcpAddAuthorization (&AcceptAuthorizationName,
+ &AcceptAuthorizationData))
+ {
+ AddLocalHosts ();
+ }
+ SessionID = AcceptSessionID;
+ state = XDM_MANAGE;
+ send_packet();
+ }
+ }
+ XdmcpDisposeARRAY8 (&AcceptAuthenticationName);
+ XdmcpDisposeARRAY8 (&AcceptAuthenticationData);
+ XdmcpDisposeARRAY8 (&AcceptAuthorizationName);
+ XdmcpDisposeARRAY8 (&AcceptAuthorizationData);
+}
+
+static void
+recv_decline_msg(unsigned length)
+{
+ ARRAY8 status, DeclineAuthenticationName, DeclineAuthenticationData;
+
+ status.data = 0;
+ DeclineAuthenticationName.data = 0;
+ DeclineAuthenticationData.data = 0;
+ if (XdmcpReadARRAY8 (&buffer, &status) &&
+ XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationName) &&
+ XdmcpReadARRAY8 (&buffer, &DeclineAuthenticationData))
+ {
+ if (length == 6 + status.length +
+ DeclineAuthenticationName.length +
+ DeclineAuthenticationData.length &&
+ XdmcpCheckAuthentication (&DeclineAuthenticationName,
+ &DeclineAuthenticationData, DECLINE))
+ {
+ XdmcpFatal ("Session declined", &status);
+ }
+ }
+ XdmcpDisposeARRAY8 (&status);
+ XdmcpDisposeARRAY8 (&DeclineAuthenticationName);
+ XdmcpDisposeARRAY8 (&DeclineAuthenticationData);
+}
+
+static void
+send_manage_msg(void)
+{
+ XdmcpHeader header;
+ int socketfd = xdmcpSocket;
+
+ header.version = XDM_PROTOCOL_VERSION;
+ header.opcode = (CARD16) MANAGE;
+ header.length = 8 + DisplayClass.length;
+
+ if (!XdmcpWriteHeader (&buffer, &header))
+ return;
+ XdmcpWriteCARD32 (&buffer, SessionID);
+ XdmcpWriteCARD16 (&buffer, DisplayNumber);
+ XdmcpWriteARRAY8 (&buffer, &DisplayClass);
+ state = XDM_AWAIT_MANAGE_RESPONSE;
+#if defined(IPv6) && defined(AF_INET6)
+ if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
+ socketfd = xdmcpSocket6;
+#endif
+ XdmcpFlush (socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen);
+}
+
+static void
+recv_refuse_msg(unsigned length)
+{
+ CARD32 RefusedSessionID;
+
+ if (state != XDM_AWAIT_MANAGE_RESPONSE)
+ return;
+ if (length != 4)
+ return;
+ if (XdmcpReadCARD32 (&buffer, &RefusedSessionID))
+ {
+ if (RefusedSessionID == SessionID)
+ {
+ state = XDM_START_CONNECTION;
+ send_packet();
+ }
+ }
+}
+
+static void
+recv_failed_msg(unsigned length)
+{
+ CARD32 FailedSessionID;
+ ARRAY8 status;
+
+ if (state != XDM_AWAIT_MANAGE_RESPONSE)
+ return;
+ status.data = 0;
+ if (XdmcpReadCARD32 (&buffer, &FailedSessionID) &&
+ XdmcpReadARRAY8 (&buffer, &status))
+ {
+ if (length == 6 + status.length &&
+ SessionID == FailedSessionID)
+ {
+ XdmcpFatal ("Session failed", &status);
+ }
+ }
+ XdmcpDisposeARRAY8 (&status);
+}
+
+static void
+send_keepalive_msg(void)
+{
+ XdmcpHeader header;
+ int socketfd = xdmcpSocket;
+
+ header.version = XDM_PROTOCOL_VERSION;
+ header.opcode = (CARD16) KEEPALIVE;
+ header.length = 6;
+
+ XdmcpWriteHeader (&buffer, &header);
+ XdmcpWriteCARD16 (&buffer, DisplayNumber);
+ XdmcpWriteCARD32 (&buffer, SessionID);
+
+ state = XDM_AWAIT_ALIVE_RESPONSE;
+#if defined(IPv6) && defined(AF_INET6)
+ if (SOCKADDR_FAMILY(req_sockaddr) == AF_INET6)
+ socketfd = xdmcpSocket6;
+#endif
+ XdmcpFlush (socketfd, &buffer, (XdmcpNetaddr) &req_sockaddr, req_socklen);
+}
+
+static void
+recv_alive_msg (unsigned length)
+{
+ CARD8 SessionRunning;
+ CARD32 AliveSessionID;
+
+ if (state != XDM_AWAIT_ALIVE_RESPONSE)
+ return;
+ if (length != 5)
+ return;
+ if (XdmcpReadCARD8 (&buffer, &SessionRunning) &&
+ XdmcpReadCARD32 (&buffer, &AliveSessionID))
+ {
+ if (SessionRunning && AliveSessionID == SessionID)
+ {
+ /* backoff dormancy period */
+ state = XDM_RUN_SESSION;
+ if ((GetTimeInMillis() - lastDeviceEventTime.milliseconds) >
+ keepaliveDormancy * 1000)
+ {
+ keepaliveDormancy <<= 1;
+ if (keepaliveDormancy > XDM_MAX_DORMANCY)
+ keepaliveDormancy = XDM_MAX_DORMANCY;
+ }
+ timeOutTime = GetTimeInMillis() + keepaliveDormancy * 1000;
+ }
+ else
+ {
+ XdmcpDeadSession ("Alive response indicates session dead");
+ }
+ }
+}
+
+static void
+XdmcpFatal (
+ const char *type,
+ ARRAY8Ptr status)
+{
+ FatalError ("XDMCP fatal error: %s %*.*s\n", type,
+ status->length, status->length, status->data);
+}
+
+static void
+XdmcpWarning(const char *str)
+{
+ ErrorF("XDMCP warning: %s\n", str);
+}
+
+static void
+get_addr_by_name(
+ const char *argtype,
+ const char *namestr,
+ int port,
+ int socktype,
+ SOCKADDR_TYPE *addr,
+ SOCKLEN_TYPE *addrlen
+#if defined(IPv6) && defined(AF_INET6)
+ ,
+ struct addrinfo **aip,
+ struct addrinfo **aifirstp
+#endif
+ )
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct addrinfo *ai;
+ struct addrinfo hints;
+ char portstr[6];
+ char *pport = portstr;
+ int gaierr;
+
+ bzero(&hints, sizeof(hints));
+ hints.ai_socktype = socktype;
+
+ if (port == 0) {
+ pport = NULL;
+ } else if (port > 0 && port < 65535) {
+ sprintf(portstr, "%d", port);
+ } else {
+ FatalError("Xserver: port out of range: %d\n", port);
+ }
+
+ if (*aifirstp != NULL) {
+ freeaddrinfo(*aifirstp);
+ *aifirstp = NULL;
+ }
+
+ if ((gaierr = getaddrinfo(namestr, pport, &hints, aifirstp)) == 0) {
+ for (ai = *aifirstp; ai != NULL; ai = ai->ai_next) {
+ if (ai->ai_family == AF_INET || ai->ai_family == AF_INET6)
+ break;
+ }
+ if ((ai == NULL) || (ai->ai_addrlen > sizeof(SOCKADDR_TYPE))) {
+ FatalError ("Xserver: %s host %s not on supported network type\n",
+ argtype, namestr);
+ } else {
+ *aip = ai;
+ *addrlen = ai->ai_addrlen;
+ memcpy(addr, ai->ai_addr, ai->ai_addrlen);
+ }
+ } else {
+ FatalError("Xserver: %s: %s %s\n", gai_strerror(gaierr), argtype, namestr);
+ }
+#else
+ struct hostent *hep;
+#ifdef XTHREADS_NEEDS_BYNAMEPARAMS
+ _Xgethostbynameparams hparams;
+#endif
+#if defined(WIN32) && (defined(TCPCONN) || defined(DNETCONN))
+ _XSERVTransWSAStartup();
+#endif
+ if (!(hep = _XGethostbyname(namestr, hparams)))
+ {
+ FatalError("Xserver: %s unknown host: %s\n", argtype, namestr);
+ }
+ if (hep->h_length == sizeof (struct in_addr))
+ {
+ memmove(&addr->sin_addr, hep->h_addr, hep->h_length);
+ *addrlen = sizeof(struct sockaddr_in);
+ addr->sin_family = AF_INET;
+ addr->sin_port = htons (port);
+ }
+ else
+ {
+ FatalError("Xserver: %s host on strange network %s\n", argtype, namestr);
+ }
+#endif
+}
+
+static void
+get_manager_by_name(
+ int argc,
+ char **argv,
+ int i)
+{
+
+ if ((i + 1) == argc)
+ {
+ FatalError("Xserver: missing %s host name in command line\n", argv[i]);
+ }
+
+ get_addr_by_name(argv[i], argv[i+1], xdm_udp_port, SOCK_DGRAM,
+ &ManagerAddress, &ManagerAddressLen
+#if defined(IPv6) && defined(AF_INET6)
+ , &mgrAddr, &mgrAddrFirst
+#endif
+ );
+}
+
+
+static void
+get_fromaddr_by_name(
+ int argc,
+ char **argv,
+ int i)
+{
+#if defined(IPv6) && defined(AF_INET6)
+ struct addrinfo *ai = NULL;
+ struct addrinfo *aifirst = NULL;
+#endif
+ if (i == argc)
+ {
+ FatalError("Xserver: missing -from host name in command line\n");
+ }
+ get_addr_by_name("-from", argv[i], 0, 0, &FromAddress, &FromAddressLen
+#if defined(IPv6) && defined(AF_INET6)
+ , &ai, &aifirst
+#endif
+ );
+#if defined(IPv6) && defined(AF_INET6)
+ if (aifirst != NULL)
+ freeaddrinfo(aifirst);
+#endif
+ xdm_from = argv[i];
+}
+
+
+#if defined(IPv6) && defined(AF_INET6)
+static int
+get_mcast_options(int argc, char **argv, int i)
+{
+ char *address = XDM_DEFAULT_MCAST_ADDR6;
+ int hopcount = 1;
+ struct addrinfo hints;
+ char portstr[6];
+ int gaierr;
+ struct addrinfo *ai, *firstai;
+
+ if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) {
+ address = argv[i++];
+ if ((i < argc) && (argv[i][0] != '-') && (argv[i][0] != '+')) {
+ hopcount = strtol(argv[i++], NULL, 10);
+ if ((hopcount < 1) || (hopcount > 255)) {
+ FatalError("Xserver: multicast hop count out of range: %d\n",
+ hopcount);
+ }
+ }
+ }
+
+ if (xdm_udp_port > 0 && xdm_udp_port < 65535) {
+ sprintf(portstr, "%d", xdm_udp_port);
+ } else {
+ FatalError("Xserver: port out of range: %d\n", xdm_udp_port);
+ }
+ bzero(&hints, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM;
+
+ if ((gaierr = getaddrinfo(address, portstr, &hints, &firstai)) == 0) {
+ for (ai = firstai; ai != NULL; ai = ai->ai_next) {
+ if (((ai->ai_family == AF_INET) &&
+ IN_MULTICAST(((struct sockaddr_in *) ai->ai_addr)
+ ->sin_addr.s_addr))
+ || ((ai->ai_family == AF_INET6) &&
+ IN6_IS_ADDR_MULTICAST(&((struct sockaddr_in6 *) ai->ai_addr)
+ ->sin6_addr)))
+ break;
+ }
+ if (ai == NULL) {
+ FatalError ("Xserver: address not supported multicast type %s\n",
+ address);
+ } else {
+ struct multicastinfo *mcastinfo, *mcl;
+
+ mcastinfo = malloc(sizeof(struct multicastinfo));
+ mcastinfo->next = NULL;
+ mcastinfo->ai = firstai;
+ mcastinfo->hops = hopcount;
+
+ if (mcastlist == NULL) {
+ mcastlist = mcastinfo;
+ } else {
+ for (mcl = mcastlist; mcl->next != NULL; mcl = mcl->next) {
+ /* Do nothing - just find end of list */
+ }
+ mcl->next = mcastinfo;
+ }
+ }
+ } else {
+ FatalError("Xserver: %s: %s\n", gai_strerror(gaierr), address);
+ }
+ return i;
+}
+#endif
+
+#else
+static int xdmcp_non_empty; /* avoid complaint by ranlib */
+#endif /* XDMCP */
diff --git a/xorg-server/render/picture.c b/xorg-server/render/picture.c
index 18bfea29b..6005683c0 100644
--- a/xorg-server/render/picture.c
+++ b/xorg-server/render/picture.c
@@ -1,1821 +1,1821 @@
-/*
- *
- * Copyright © 2000 SuSE, Inc.
- *
- * 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, and that the name of SuSE not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. SuSE makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
- * 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.
- *
- * Author: Keith Packard, SuSE, Inc.
- */
-
-#ifdef HAVE_DIX_CONFIG_H
-#include <dix-config.h>
-#endif
-
-#include "misc.h"
-#include "scrnintstr.h"
-#include "os.h"
-#include "regionstr.h"
-#include "validate.h"
-#include "windowstr.h"
-#include "input.h"
-#include "resource.h"
-#include "colormapst.h"
-#include "cursorstr.h"
-#include "dixstruct.h"
-#include "gcstruct.h"
-#include "servermd.h"
-#include "picturestr.h"
-#include "xace.h"
-
-static int PictureScreenPrivateKeyIndex;
-DevPrivateKey PictureScreenPrivateKey = &PictureScreenPrivateKeyIndex;
-static int PictureWindowPrivateKeyIndex;
-DevPrivateKey PictureWindowPrivateKey = &PictureWindowPrivateKeyIndex;
-static int PictureGeneration;
-RESTYPE PictureType;
-RESTYPE PictFormatType;
-RESTYPE GlyphSetType;
-int PictureCmapPolicy = PictureCmapPolicyDefault;
-
-Bool
-PictureDestroyWindow (WindowPtr pWindow)
-{
- ScreenPtr pScreen = pWindow->drawable.pScreen;
- PicturePtr pPicture;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- Bool ret;
-
- while ((pPicture = GetPictureWindow(pWindow)))
- {
- SetPictureWindow(pWindow, pPicture->pNext);
- if (pPicture->id)
- FreeResource (pPicture->id, PictureType);
- FreePicture ((pointer) pPicture, pPicture->id);
- }
- pScreen->DestroyWindow = ps->DestroyWindow;
- ret = (*pScreen->DestroyWindow) (pWindow);
- ps->DestroyWindow = pScreen->DestroyWindow;
- pScreen->DestroyWindow = PictureDestroyWindow;
- return ret;
-}
-
-Bool
-PictureCloseScreen (int index, ScreenPtr pScreen)
-{
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- Bool ret;
- int n;
-
- pScreen->CloseScreen = ps->CloseScreen;
- ret = (*pScreen->CloseScreen) (index, pScreen);
- PictureResetFilters (pScreen);
- for (n = 0; n < ps->nformats; n++)
- if (ps->formats[n].type == PictTypeIndexed)
- (*ps->CloseIndexed) (pScreen, &ps->formats[n]);
- GlyphUninit (pScreen);
- SetPictureScreen(pScreen, 0);
- xfree (ps->formats);
- xfree (ps);
- return ret;
-}
-
-void
-PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef)
-{
- ScreenPtr pScreen = pColormap->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
-
- pScreen->StoreColors = ps->StoreColors;
- (*pScreen->StoreColors) (pColormap, ndef, pdef);
- ps->StoreColors = pScreen->StoreColors;
- pScreen->StoreColors = PictureStoreColors;
-
- if (pColormap->class == PseudoColor || pColormap->class == GrayScale)
- {
- PictFormatPtr format = ps->formats;
- int nformats = ps->nformats;
-
- while (nformats--)
- {
- if (format->type == PictTypeIndexed &&
- format->index.pColormap == pColormap)
- {
- (*ps->UpdateIndexed) (pScreen, format, ndef, pdef);
- break;
- }
- format++;
- }
- }
-}
-
-static int
-visualDepth (ScreenPtr pScreen, VisualPtr pVisual)
-{
- int d, v;
- DepthPtr pDepth;
-
- for (d = 0; d < pScreen->numDepths; d++)
- {
- pDepth = &pScreen->allowedDepths[d];
- for (v = 0; v < pDepth->numVids; v++)
- if (pDepth->vids[v] == pVisual->vid)
- return pDepth->depth;
- }
- return 0;
-}
-
-typedef struct _formatInit {
- CARD32 format;
- CARD8 depth;
-} FormatInitRec, *FormatInitPtr;
-
-static int
-addFormat (FormatInitRec formats[256],
- int nformat,
- CARD32 format,
- CARD8 depth)
-{
- int n;
-
- for (n = 0; n < nformat; n++)
- if (formats[n].format == format && formats[n].depth == depth)
- return nformat;
- formats[nformat].format = format;
- formats[nformat].depth = depth;
- return ++nformat;
-}
-
-#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1))
-
-PictFormatPtr
-PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp)
-{
- int nformats, f;
- PictFormatPtr pFormats;
- FormatInitRec formats[1024];
- CARD32 format;
- CARD8 depth;
- VisualPtr pVisual;
- int v;
- int bpp;
- int type;
- int r, g, b;
- int d;
- DepthPtr pDepth;
-
- nformats = 0;
- /* formats required by protocol */
- formats[nformats].format = PICT_a1;
- formats[nformats].depth = 1;
- nformats++;
- formats[nformats].format = PICT_FORMAT(BitsPerPixel(8),
- PICT_TYPE_A,
- 8, 0, 0, 0);
- formats[nformats].depth = 8;
- nformats++;
- formats[nformats].format = PICT_FORMAT(BitsPerPixel(4),
- PICT_TYPE_A,
- 4, 0, 0, 0);
- formats[nformats].depth = 4;
- nformats++;
- formats[nformats].format = PICT_a8r8g8b8;
- formats[nformats].depth = 32;
- nformats++;
- formats[nformats].format = PICT_x8r8g8b8;
- formats[nformats].depth = 32;
- nformats++;
- formats[nformats].format = PICT_b8g8r8a8;
- formats[nformats].depth = 32;
- nformats++;
- formats[nformats].format = PICT_b8g8r8x8;
- formats[nformats].depth = 32;
- nformats++;
-
- /* now look through the depths and visuals adding other formats */
- for (v = 0; v < pScreen->numVisuals; v++)
- {
- pVisual = &pScreen->visuals[v];
- depth = visualDepth (pScreen, pVisual);
- if (!depth)
- continue;
- bpp = BitsPerPixel (depth);
- switch (pVisual->class) {
- case DirectColor:
- case TrueColor:
- r = Ones (pVisual->redMask);
- g = Ones (pVisual->greenMask);
- b = Ones (pVisual->blueMask);
- type = PICT_TYPE_OTHER;
- /*
- * Current rendering code supports only three direct formats,
- * fields must be packed together at the bottom of the pixel
- */
- if (pVisual->offsetBlue == 0 &&
- pVisual->offsetGreen == b &&
- pVisual->offsetRed == b + g)
- {
- type = PICT_TYPE_ARGB;
- }
- else if (pVisual->offsetRed == 0 &&
- pVisual->offsetGreen == r &&
- pVisual->offsetBlue == r + g)
- {
- type = PICT_TYPE_ABGR;
- }
- else if (pVisual->offsetRed == pVisual->offsetGreen - r &&
- pVisual->offsetGreen == pVisual->offsetBlue - g &&
- pVisual->offsetBlue == bpp - b)
- {
- type = PICT_TYPE_BGRA;
- }
- if (type != PICT_TYPE_OTHER)
- {
- format = PICT_FORMAT(bpp, type, 0, r, g, b);
- nformats = addFormat (formats, nformats, format, depth);
- }
- break;
- case StaticColor:
- case PseudoColor:
- format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v);
- nformats = addFormat (formats, nformats, format, depth);
- break;
- case StaticGray:
- case GrayScale:
- format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v);
- nformats = addFormat (formats, nformats, format, depth);
- break;
- }
- }
- /*
- * Walk supported depths and add useful Direct formats
- */
- for (d = 0; d < pScreen->numDepths; d++)
- {
- pDepth = &pScreen->allowedDepths[d];
- bpp = BitsPerPixel (pDepth->depth);
- format = 0;
- switch (bpp) {
- case 16:
- /* depth 12 formats */
- if (pDepth->depth >= 12)
- {
- nformats = addFormat (formats, nformats,
- PICT_x4r4g4b4, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_x4b4g4r4, pDepth->depth);
- }
- /* depth 15 formats */
- if (pDepth->depth >= 15)
- {
- nformats = addFormat (formats, nformats,
- PICT_x1r5g5b5, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_x1b5g5r5, pDepth->depth);
- }
- /* depth 16 formats */
- if (pDepth->depth >= 16)
- {
- nformats = addFormat (formats, nformats,
- PICT_a1r5g5b5, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_a1b5g5r5, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_r5g6b5, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_b5g6r5, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_a4r4g4b4, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_a4b4g4r4, pDepth->depth);
- }
- break;
- case 24:
- if (pDepth->depth >= 24)
- {
- nformats = addFormat (formats, nformats,
- PICT_r8g8b8, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_b8g8r8, pDepth->depth);
- }
- break;
- case 32:
- if (pDepth->depth >= 24)
- {
- nformats = addFormat (formats, nformats,
- PICT_x8r8g8b8, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_x8b8g8r8, pDepth->depth);
- }
- if (pDepth->depth >= 30)
- {
- nformats = addFormat (formats, nformats,
- PICT_a2r10g10b10, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_x2r10g10b10, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_a2b10g10r10, pDepth->depth);
- nformats = addFormat (formats, nformats,
- PICT_x2b10g10r10, pDepth->depth);
- }
- break;
- }
- }
-
-
- pFormats = xcalloc (nformats, sizeof (PictFormatRec));
- if (!pFormats)
- return 0;
- for (f = 0; f < nformats; f++)
- {
- pFormats[f].id = FakeClientID (0);
- pFormats[f].depth = formats[f].depth;
- format = formats[f].format;
- pFormats[f].format = format;
- switch (PICT_FORMAT_TYPE(format)) {
- case PICT_TYPE_ARGB:
- pFormats[f].type = PictTypeDirect;
-
- pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
- if (pFormats[f].direct.alphaMask)
- pFormats[f].direct.alpha = (PICT_FORMAT_R(format) +
- PICT_FORMAT_G(format) +
- PICT_FORMAT_B(format));
-
- pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
- pFormats[f].direct.red = (PICT_FORMAT_G(format) +
- PICT_FORMAT_B(format));
-
- pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
- pFormats[f].direct.green = PICT_FORMAT_B(format);
-
- pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
- pFormats[f].direct.blue = 0;
- break;
-
- case PICT_TYPE_ABGR:
- pFormats[f].type = PictTypeDirect;
-
- pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
- if (pFormats[f].direct.alphaMask)
- pFormats[f].direct.alpha = (PICT_FORMAT_B(format) +
- PICT_FORMAT_G(format) +
- PICT_FORMAT_R(format));
-
- pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
- pFormats[f].direct.blue = (PICT_FORMAT_G(format) +
- PICT_FORMAT_R(format));
-
- pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
- pFormats[f].direct.green = PICT_FORMAT_R(format);
-
- pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
- pFormats[f].direct.red = 0;
- break;
-
- case PICT_TYPE_BGRA:
- pFormats[f].type = PictTypeDirect;
-
- pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
- pFormats[f].direct.blue = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format));
-
- pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
- pFormats[f].direct.green = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format) -
- PICT_FORMAT_G(format));
-
- pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
- pFormats[f].direct.red = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format) -
- PICT_FORMAT_G(format) - PICT_FORMAT_R(format));
-
- pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
- pFormats[f].direct.alpha = 0;
- break;
-
- case PICT_TYPE_A:
- pFormats[f].type = PictTypeDirect;
-
- pFormats[f].direct.alpha = 0;
- pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
-
- /* remaining fields already set to zero */
- break;
-
- case PICT_TYPE_COLOR:
- case PICT_TYPE_GRAY:
- pFormats[f].type = PictTypeIndexed;
- pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid;
- break;
- }
- }
- *nformatp = nformats;
- return pFormats;
-}
-
-static VisualPtr
-PictureFindVisual (ScreenPtr pScreen, VisualID visual)
-{
- int i;
- VisualPtr pVisual;
- for (i = 0, pVisual = pScreen->visuals;
- i < pScreen->numVisuals;
- i++, pVisual++)
- {
- if (pVisual->vid == visual)
- return pVisual;
- }
- return 0;
-}
-
-Bool
-PictureInitIndexedFormat(ScreenPtr pScreen, PictFormatPtr format)
-{
- PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
-
- if (format->type != PictTypeIndexed || format->index.pColormap)
- return TRUE;
-
- if (format->index.vid == pScreen->rootVisual) {
- dixLookupResourceByType((pointer *)&format->index.pColormap,
- pScreen->defColormap, RT_COLORMAP,
- serverClient, DixGetAttrAccess);
- } else {
- VisualPtr pVisual = PictureFindVisual(pScreen, format->index.vid);
- if (CreateColormap(FakeClientID (0), pScreen, pVisual,
- &format->index.pColormap, AllocNone, 0)
- != Success)
- return FALSE;
- }
- if (!ps->InitIndexed(pScreen, format))
- return FALSE;
- return TRUE;
-}
-
-static Bool
-PictureInitIndexedFormats (ScreenPtr pScreen)
-{
- PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
- PictFormatPtr format;
- int nformat;
-
- if (!ps)
- return FALSE;
- format = ps->formats;
- nformat = ps->nformats;
- while (nformat--)
- if (!PictureInitIndexedFormat(pScreen, format++))
- return FALSE;
- return TRUE;
-}
-
-Bool
-PictureFinishInit (void)
-{
- int s;
-
- for (s = 0; s < screenInfo.numScreens; s++)
- {
- if (!PictureInitIndexedFormats (screenInfo.screens[s]))
- return FALSE;
- (void) AnimCurInit (screenInfo.screens[s]);
- }
-
- return TRUE;
-}
-
-Bool
-PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel)
-{
- PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
-
- if (!ps)
- return FALSE;
- ps->subpixel = subpixel;
- return TRUE;
-
-}
-
-int
-PictureGetSubpixelOrder (ScreenPtr pScreen)
-{
- PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
-
- if (!ps)
- return SubPixelUnknown;
- return ps->subpixel;
-}
-
-PictFormatPtr
-PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual)
-{
- PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
- PictFormatPtr format;
- int nformat;
- int type;
-
- if (!ps)
- return 0;
- format = ps->formats;
- nformat = ps->nformats;
- switch (pVisual->class) {
- case StaticGray:
- case GrayScale:
- case StaticColor:
- case PseudoColor:
- type = PictTypeIndexed;
- break;
- case TrueColor:
- case DirectColor:
- type = PictTypeDirect;
- break;
- default:
- return 0;
- }
- while (nformat--)
- {
- if (format->depth == depth && format->type == type)
- {
- if (type == PictTypeIndexed)
- {
- if (format->index.vid == pVisual->vid)
- return format;
- }
- else
- {
- if (format->direct.redMask << format->direct.red ==
- pVisual->redMask &&
- format->direct.greenMask << format->direct.green ==
- pVisual->greenMask &&
- format->direct.blueMask << format->direct.blue ==
- pVisual->blueMask)
- {
- return format;
- }
- }
- }
- format++;
- }
- return 0;
-}
-
-PictFormatPtr
-PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f)
-{
- PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
- PictFormatPtr format;
- int nformat;
-
- if (!ps)
- return 0;
- format = ps->formats;
- nformat = ps->nformats;
- while (nformat--)
- {
- if (format->depth == depth && format->format == (f & 0xffffff))
- return format;
- format++;
- }
- return 0;
-}
-
-int
-PictureParseCmapPolicy (const char *name)
-{
- if ( strcmp (name, "default" ) == 0)
- return PictureCmapPolicyDefault;
- else if ( strcmp (name, "mono" ) == 0)
- return PictureCmapPolicyMono;
- else if ( strcmp (name, "gray" ) == 0)
- return PictureCmapPolicyGray;
- else if ( strcmp (name, "color" ) == 0)
- return PictureCmapPolicyColor;
- else if ( strcmp (name, "all" ) == 0)
- return PictureCmapPolicyAll;
- else
- return PictureCmapPolicyInvalid;
-}
-
-Bool
-PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
-{
- PictureScreenPtr ps;
- int n;
- CARD32 type, a, r, g, b;
-
- if (PictureGeneration != serverGeneration)
- {
- PictureType = CreateNewResourceType (FreePicture, "PICTURE");
- if (!PictureType)
- return FALSE;
- PictFormatType = CreateNewResourceType (FreePictFormat, "PICTFORMAT");
- if (!PictFormatType)
- return FALSE;
- GlyphSetType = CreateNewResourceType (FreeGlyphSet, "GLYPHSET");
- if (!GlyphSetType)
- return FALSE;
- PictureGeneration = serverGeneration;
- }
- if (!formats)
- {
- formats = PictureCreateDefaultFormats (pScreen, &nformats);
- if (!formats)
- return FALSE;
- }
- for (n = 0; n < nformats; n++)
- {
- if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n)))
- {
- xfree (formats);
- return FALSE;
- }
- if (formats[n].type == PictTypeIndexed)
- {
- VisualPtr pVisual = PictureFindVisual (pScreen, formats[n].index.vid);
- if ((pVisual->class | DynamicClass) == PseudoColor)
- type = PICT_TYPE_COLOR;
- else
- type = PICT_TYPE_GRAY;
- a = r = g = b = 0;
- }
- else
- {
- if ((formats[n].direct.redMask|
- formats[n].direct.blueMask|
- formats[n].direct.greenMask) == 0)
- type = PICT_TYPE_A;
- else if (formats[n].direct.red > formats[n].direct.blue)
- type = PICT_TYPE_ARGB;
- else if (formats[n].direct.red == 0)
- type = PICT_TYPE_ABGR;
- else
- type = PICT_TYPE_BGRA;
- a = Ones (formats[n].direct.alphaMask);
- r = Ones (formats[n].direct.redMask);
- g = Ones (formats[n].direct.greenMask);
- b = Ones (formats[n].direct.blueMask);
- }
- formats[n].format = PICT_FORMAT(0,type,a,r,g,b);
- }
- ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec));
- if (!ps)
- {
- xfree (formats);
- return FALSE;
- }
- SetPictureScreen(pScreen, ps);
-
- ps->formats = formats;
- ps->fallback = formats;
- ps->nformats = nformats;
-
- ps->filters = 0;
- ps->nfilters = 0;
- ps->filterAliases = 0;
- ps->nfilterAliases = 0;
-
- ps->subpixel = SubPixelUnknown;
-
- ps->CloseScreen = pScreen->CloseScreen;
- ps->DestroyWindow = pScreen->DestroyWindow;
- ps->StoreColors = pScreen->StoreColors;
- pScreen->DestroyWindow = PictureDestroyWindow;
- pScreen->CloseScreen = PictureCloseScreen;
- pScreen->StoreColors = PictureStoreColors;
-
- if (!PictureSetDefaultFilters (pScreen))
- {
- PictureResetFilters (pScreen);
- SetPictureScreen(pScreen, 0);
- xfree (formats);
- xfree (ps);
- return FALSE;
- }
-
- return TRUE;
-}
-
-void
-SetPictureToDefaults (PicturePtr pPicture)
-{
- pPicture->refcnt = 1;
- pPicture->repeat = 0;
- pPicture->graphicsExposures = FALSE;
- pPicture->subWindowMode = ClipByChildren;
- pPicture->polyEdge = PolyEdgeSharp;
- pPicture->polyMode = PolyModePrecise;
- pPicture->freeCompClip = FALSE;
- pPicture->clientClipType = CT_NONE;
- pPicture->componentAlpha = FALSE;
- pPicture->repeatType = RepeatNone;
-
- pPicture->alphaMap = 0;
- pPicture->alphaOrigin.x = 0;
- pPicture->alphaOrigin.y = 0;
-
- pPicture->clipOrigin.x = 0;
- pPicture->clipOrigin.y = 0;
- pPicture->clientClip = 0;
-
- pPicture->transform = 0;
-
- pPicture->dither = None;
- pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE);
- pPicture->filter_params = 0;
- pPicture->filter_nparams = 0;
-
- pPicture->serialNumber = GC_CHANGE_SERIAL_BIT;
- pPicture->stateChanges = (1 << (CPLastBit+1)) - 1;
- pPicture->pSourcePict = 0;
-}
-
-PicturePtr
-CreatePicture (Picture pid,
- DrawablePtr pDrawable,
- PictFormatPtr pFormat,
- Mask vmask,
- XID *vlist,
- ClientPtr client,
- int *error)
-{
- PicturePtr pPicture;
- PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen);
-
- pPicture = (PicturePtr)xalloc(sizeof(PictureRec));
- if (!pPicture)
- {
- *error = BadAlloc;
- return 0;
- }
-
- pPicture->id = pid;
- pPicture->pDrawable = pDrawable;
- pPicture->pFormat = pFormat;
- pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24);
- pPicture->devPrivates = NULL;
-
- /* security creation/labeling check */
- *error = XaceHook(XACE_RESOURCE_ACCESS, client, pid, PictureType, pPicture,
- RT_PIXMAP, pDrawable, DixCreateAccess|DixSetAttrAccess);
- if (*error != Success)
- goto out;
-
- if (pDrawable->type == DRAWABLE_PIXMAP)
- {
- ++((PixmapPtr)pDrawable)->refcnt;
- pPicture->pNext = 0;
- }
- else
- {
- pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable));
- SetPictureWindow(((WindowPtr) pDrawable), pPicture);
- }
-
- SetPictureToDefaults (pPicture);
-
- if (vmask)
- *error = ChangePicture (pPicture, vmask, vlist, 0, client);
- else
- *error = Success;
- if (*error == Success)
- *error = (*ps->CreatePicture) (pPicture);
-out:
- if (*error != Success)
- {
- FreePicture (pPicture, (XID) 0);
- pPicture = 0;
- }
- return pPicture;
-}
-
-static CARD32 xRenderColorToCard32(xRenderColor c)
-{
- return
- (c.alpha >> 8 << 24) |
- (c.red >> 8 << 16) |
- (c.green & 0xff00) |
- (c.blue >> 8);
-}
-
-static unsigned int premultiply(unsigned int x)
-{
- unsigned int a = x >> 24;
- unsigned int t = (x & 0xff00ff) * a + 0x800080;
- t = (t + ((t >> 8) & 0xff00ff)) >> 8;
- t &= 0xff00ff;
-
- x = ((x >> 8) & 0xff) * a + 0x80;
- x = (x + ((x >> 8) & 0xff));
- x &= 0xff00;
- x |= t | (a << 24);
- return x;
-}
-
-static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a,
- unsigned int y, unsigned int b)
-{
- CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
- t >>= 8;
- t &= 0xff00ff;
-
- x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
- x &= 0xff00ff00;
- x |= t;
- return x;
-}
-
-CARD32
-PictureGradientColor (PictGradientStopPtr stop1,
- PictGradientStopPtr stop2,
- CARD32 x)
-{
- CARD32 current_color, next_color;
- int dist, idist;
-
- current_color = xRenderColorToCard32 (stop1->color);
- next_color = xRenderColorToCard32 (stop2->color);
-
- dist = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x));
- idist = 256 - dist;
-
- return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist,
- next_color, dist));
-}
-
-static void initGradient(SourcePictPtr pGradient, int stopCount,
- xFixed *stopPoints, xRenderColor *stopColors, int *error)
-{
- int i;
- xFixed dpos;
-
- if (stopCount <= 0) {
- *error = BadValue;
- return;
- }
-
- dpos = -1;
- for (i = 0; i < stopCount; ++i) {
- if (stopPoints[i] < dpos || stopPoints[i] > (1<<16)) {
- *error = BadValue;
- return;
- }
- dpos = stopPoints[i];
- }
-
- pGradient->gradient.stops = xalloc(stopCount*sizeof(PictGradientStop));
- if (!pGradient->gradient.stops) {
- *error = BadAlloc;
- return;
- }
-
- pGradient->gradient.nstops = stopCount;
-
- for (i = 0; i < stopCount; ++i) {
- pGradient->gradient.stops[i].x = stopPoints[i];
- pGradient->gradient.stops[i].color = stopColors[i];
- }
-
- pGradient->gradient.class = SourcePictClassUnknown;
- pGradient->gradient.stopRange = 0xffff;
- pGradient->gradient.colorTable = NULL;
- pGradient->gradient.colorTableSize = 0;
-}
-
-static PicturePtr createSourcePicture(void)
-{
- PicturePtr pPicture;
- pPicture = (PicturePtr) xalloc(sizeof(PictureRec));
- pPicture->pDrawable = 0;
- pPicture->pFormat = 0;
- pPicture->pNext = 0;
- pPicture->format = PICT_a8r8g8b8;
- pPicture->devPrivates = 0;
-
- SetPictureToDefaults(pPicture);
- return pPicture;
-}
-
-PicturePtr
-CreateSolidPicture (Picture pid, xRenderColor *color, int *error)
-{
- PicturePtr pPicture;
- pPicture = createSourcePicture();
- if (!pPicture) {
- *error = BadAlloc;
- return 0;
- }
-
- pPicture->id = pid;
- pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictSolidFill));
- if (!pPicture->pSourcePict) {
- *error = BadAlloc;
- xfree(pPicture);
- return 0;
- }
- pPicture->pSourcePict->type = SourcePictTypeSolidFill;
- pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color);
- return pPicture;
-}
-
-PicturePtr
-CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2,
- int nStops, xFixed *stops, xRenderColor *colors, int *error)
-{
- PicturePtr pPicture;
-
- if (nStops < 2) {
- *error = BadValue;
- return 0;
- }
-
- pPicture = createSourcePicture();
- if (!pPicture) {
- *error = BadAlloc;
- return 0;
- }
-
- pPicture->id = pid;
- pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictLinearGradient));
- if (!pPicture->pSourcePict) {
- *error = BadAlloc;
- xfree(pPicture);
- return 0;
- }
-
- pPicture->pSourcePict->linear.type = SourcePictTypeLinear;
- pPicture->pSourcePict->linear.p1 = *p1;
- pPicture->pSourcePict->linear.p2 = *p2;
-
- initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
- if (*error) {
- xfree(pPicture);
- return 0;
- }
- return pPicture;
-}
-
-#define FixedToDouble(x) ((x)/65536.)
-
-PicturePtr
-CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer,
- xFixed innerRadius, xFixed outerRadius,
- int nStops, xFixed *stops, xRenderColor *colors, int *error)
-{
- PicturePtr pPicture;
- PictRadialGradient *radial;
-
- if (nStops < 2) {
- *error = BadValue;
- return 0;
- }
-
- pPicture = createSourcePicture();
- if (!pPicture) {
- *error = BadAlloc;
- return 0;
- }
-
- pPicture->id = pid;
- pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictRadialGradient));
- if (!pPicture->pSourcePict) {
- *error = BadAlloc;
- xfree(pPicture);
- return 0;
- }
- radial = &pPicture->pSourcePict->radial;
-
- radial->type = SourcePictTypeRadial;
- radial->c1.x = inner->x;
- radial->c1.y = inner->y;
- radial->c1.radius = innerRadius;
- radial->c2.x = outer->x;
- radial->c2.y = outer->y;
- radial->c2.radius = outerRadius;
- radial->cdx = (radial->c2.x - radial->c1.x) / 65536.;
- radial->cdy = (radial->c2.y - radial->c1.y) / 65536.;
- radial->dr = (radial->c2.radius - radial->c1.radius) / 65536.;
- radial->A = ( radial->cdx * radial->cdx
- + radial->cdy * radial->cdy
- - radial->dr * radial->dr);
-
- initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
- if (*error) {
- xfree(pPicture);
- return 0;
- }
- return pPicture;
-}
-
-PicturePtr
-CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle,
- int nStops, xFixed *stops, xRenderColor *colors, int *error)
-{
- PicturePtr pPicture;
-
- if (nStops < 2) {
- *error = BadValue;
- return 0;
- }
-
- pPicture = createSourcePicture();
- if (!pPicture) {
- *error = BadAlloc;
- return 0;
- }
-
- pPicture->id = pid;
- pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictConicalGradient));
- if (!pPicture->pSourcePict) {
- *error = BadAlloc;
- xfree(pPicture);
- return 0;
- }
-
- pPicture->pSourcePict->conical.type = SourcePictTypeConical;
- pPicture->pSourcePict->conical.center = *center;
- pPicture->pSourcePict->conical.angle = angle;
-
- initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
- if (*error) {
- xfree(pPicture);
- return 0;
- }
- return pPicture;
-}
-
-#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val)
-
-#define NEXT_PTR(_type) ((_type) ulist++->ptr)
-
-int
-ChangePicture (PicturePtr pPicture,
- Mask vmask,
- XID *vlist,
- DevUnion *ulist,
- ClientPtr client)
-{
- ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0;
- PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0;
- BITS32 index2;
- int error = 0;
- BITS32 maskQ;
-
- pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
- maskQ = vmask;
- while (vmask && !error)
- {
- index2 = (BITS32) lowbit (vmask);
- vmask &= ~index2;
- pPicture->stateChanges |= index2;
- switch (index2)
- {
- case CPRepeat:
- {
- unsigned int newr;
- newr = NEXT_VAL(unsigned int);
- if (newr <= RepeatReflect)
- {
- pPicture->repeat = (newr != RepeatNone);
- pPicture->repeatType = newr;
- }
- else
- {
- client->errorValue = newr;
- error = BadValue;
- }
- }
- break;
- case CPAlphaMap:
- {
- PicturePtr pAlpha;
-
- if (vlist)
- {
- Picture pid = NEXT_VAL(Picture);
-
- if (pid == None)
- pAlpha = 0;
- else
- {
- error = dixLookupResourceByType((pointer *)&pAlpha, pid,
- PictureType, client,
- DixReadAccess);
- if (error != Success)
- {
- client->errorValue = pid;
- error = (error == BadValue) ? BadPixmap : error;
- break;
- }
- if (pAlpha->pDrawable == NULL ||
- pAlpha->pDrawable->type != DRAWABLE_PIXMAP)
- {
- client->errorValue = pid;
- error = BadMatch;
- break;
- }
- }
- }
- else
- pAlpha = NEXT_PTR(PicturePtr);
- if (!error)
- {
- if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP)
- pAlpha->refcnt++;
- if (pPicture->alphaMap)
- FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
- pPicture->alphaMap = pAlpha;
- }
- }
- break;
- case CPAlphaXOrigin:
- pPicture->alphaOrigin.x = NEXT_VAL(INT16);
- break;
- case CPAlphaYOrigin:
- pPicture->alphaOrigin.y = NEXT_VAL(INT16);
- break;
- case CPClipXOrigin:
- pPicture->clipOrigin.x = NEXT_VAL(INT16);
- break;
- case CPClipYOrigin:
- pPicture->clipOrigin.y = NEXT_VAL(INT16);
- break;
- case CPClipMask:
- {
- Pixmap pid;
- PixmapPtr pPixmap;
- int clipType;
- if (!pScreen)
- return BadDrawable;
-
- if (vlist)
- {
- pid = NEXT_VAL(Pixmap);
- if (pid == None)
- {
- clipType = CT_NONE;
- pPixmap = NullPixmap;
- }
- else
- {
- clipType = CT_PIXMAP;
- error = dixLookupResourceByType((pointer *)&pPixmap, pid,
- RT_PIXMAP, client,
- DixReadAccess);
- if (error != Success)
- {
- client->errorValue = pid;
- error = (error == BadValue) ? BadPixmap : error;
- break;
- }
- }
- }
- else
- {
- pPixmap = NEXT_PTR(PixmapPtr);
- if (pPixmap)
- clipType = CT_PIXMAP;
- else
- clipType = CT_NONE;
- }
-
- if (pPixmap)
- {
- if ((pPixmap->drawable.depth != 1) ||
- (pPixmap->drawable.pScreen != pScreen))
- {
- error = BadMatch;
- break;
- }
- else
- {
- clipType = CT_PIXMAP;
- pPixmap->refcnt++;
- }
- }
- error = (*ps->ChangePictureClip)(pPicture, clipType,
- (pointer)pPixmap, 0);
- break;
- }
- case CPGraphicsExposure:
- {
- unsigned int newe;
- newe = NEXT_VAL(unsigned int);
- if (newe <= xTrue)
- pPicture->graphicsExposures = newe;
- else
- {
- client->errorValue = newe;
- error = BadValue;
- }
- }
- break;
- case CPSubwindowMode:
- {
- unsigned int news;
- news = NEXT_VAL(unsigned int);
- if (news == ClipByChildren || news == IncludeInferiors)
- pPicture->subWindowMode = news;
- else
- {
- client->errorValue = news;
- error = BadValue;
- }
- }
- break;
- case CPPolyEdge:
- {
- unsigned int newe;
- newe = NEXT_VAL(unsigned int);
- if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth)
- pPicture->polyEdge = newe;
- else
- {
- client->errorValue = newe;
- error = BadValue;
- }
- }
- break;
- case CPPolyMode:
- {
- unsigned int newm;
- newm = NEXT_VAL(unsigned int);
- if (newm == PolyModePrecise || newm == PolyModeImprecise)
- pPicture->polyMode = newm;
- else
- {
- client->errorValue = newm;
- error = BadValue;
- }
- }
- break;
- case CPDither:
- pPicture->dither = NEXT_VAL(Atom);
- break;
- case CPComponentAlpha:
- {
- unsigned int newca;
-
- newca = NEXT_VAL (unsigned int);
- if (newca <= xTrue)
- pPicture->componentAlpha = newca;
- else
- {
- client->errorValue = newca;
- error = BadValue;
- }
- }
- break;
- default:
- client->errorValue = maskQ;
- error = BadValue;
- break;
- }
- }
- if (ps)
- (*ps->ChangePicture) (pPicture, maskQ);
- return error;
-}
-
-int
-SetPictureClipRects (PicturePtr pPicture,
- int xOrigin,
- int yOrigin,
- int nRect,
- xRectangle *rects)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- RegionPtr clientClip;
- int result;
-
- clientClip = RECTS_TO_REGION(pScreen,
- nRect, rects, CT_UNSORTED);
- if (!clientClip)
- return BadAlloc;
- result =(*ps->ChangePictureClip) (pPicture, CT_REGION,
- (pointer) clientClip, 0);
- if (result == Success)
- {
- pPicture->clipOrigin.x = xOrigin;
- pPicture->clipOrigin.y = yOrigin;
- pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
- pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
- }
- return result;
-}
-
-int
-SetPictureClipRegion (PicturePtr pPicture,
- int xOrigin,
- int yOrigin,
- RegionPtr pRegion)
-{
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
- RegionPtr clientClip;
- int result;
- int type;
-
- if (pRegion)
- {
- type = CT_REGION;
- clientClip = REGION_CREATE (pScreen,
- REGION_EXTENTS(pScreen, pRegion),
- REGION_NUM_RECTS(pRegion));
- if (!clientClip)
- return BadAlloc;
- if (!REGION_COPY (pSCreen, clientClip, pRegion))
- {
- REGION_DESTROY (pScreen, clientClip);
- return BadAlloc;
- }
- }
- else
- {
- type = CT_NONE;
- clientClip = 0;
- }
-
- result =(*ps->ChangePictureClip) (pPicture, type,
- (pointer) clientClip, 0);
- if (result == Success)
- {
- pPicture->clipOrigin.x = xOrigin;
- pPicture->clipOrigin.y = yOrigin;
- pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
- pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
- }
- return result;
-}
-
-static Bool
-transformIsIdentity(PictTransform *t)
-{
- return ((t->matrix[0][0] == t->matrix[1][1]) &&
- (t->matrix[0][0] == t->matrix[2][2]) &&
- (t->matrix[0][0] != 0) &&
- (t->matrix[0][1] == 0) &&
- (t->matrix[0][2] == 0) &&
- (t->matrix[1][0] == 0) &&
- (t->matrix[1][2] == 0) &&
- (t->matrix[2][0] == 0) &&
- (t->matrix[2][1] == 0));
-}
-
-int
-SetPictureTransform (PicturePtr pPicture,
- PictTransform *transform)
-{
- if (transform && transformIsIdentity (transform))
- transform = 0;
-
- if (transform)
- {
- if (!pPicture->transform)
- {
- pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform));
- if (!pPicture->transform)
- return BadAlloc;
- }
- *pPicture->transform = *transform;
- }
- else
- {
- if (pPicture->transform)
- {
- xfree (pPicture->transform);
- pPicture->transform = 0;
- }
- }
- pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
-
- if (pPicture->pDrawable != NULL) {
- int result;
- PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
-
- result = (*ps->ChangePictureTransform) (pPicture, transform);
-
- return result;
- }
-
- return Success;
-}
-
-void
-CopyPicture (PicturePtr pSrc,
- Mask mask,
- PicturePtr pDst)
-{
- PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen);
- Mask origMask = mask;
-
- pDst->serialNumber |= GC_CHANGE_SERIAL_BIT;
- pDst->stateChanges |= mask;
-
- while (mask) {
- Mask bit = lowbit(mask);
-
- switch (bit)
- {
- case CPRepeat:
- pDst->repeat = pSrc->repeat;
- pDst->repeatType = pSrc->repeatType;
- break;
- case CPAlphaMap:
- if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP)
- pSrc->alphaMap->refcnt++;
- if (pDst->alphaMap)
- FreePicture ((pointer) pDst->alphaMap, (XID) 0);
- pDst->alphaMap = pSrc->alphaMap;
- break;
- case CPAlphaXOrigin:
- pDst->alphaOrigin.x = pSrc->alphaOrigin.x;
- break;
- case CPAlphaYOrigin:
- pDst->alphaOrigin.y = pSrc->alphaOrigin.y;
- break;
- case CPClipXOrigin:
- pDst->clipOrigin.x = pSrc->clipOrigin.x;
- break;
- case CPClipYOrigin:
- pDst->clipOrigin.y = pSrc->clipOrigin.y;
- break;
- case CPClipMask:
- switch (pSrc->clientClipType) {
- case CT_NONE:
- (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
- break;
- case CT_REGION:
- if (!pSrc->clientClip) {
- (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
- } else {
- RegionPtr clientClip;
- RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip;
-
- clientClip = REGION_CREATE(pSrc->pDrawable->pScreen,
- REGION_EXTENTS(pSrc->pDrawable->pScreen, srcClientClip),
- REGION_NUM_RECTS(srcClientClip));
- (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0);
- }
- break;
- default:
- /* XXX: CT_PIXMAP unimplemented */
- break;
- }
- break;
- case CPGraphicsExposure:
- pDst->graphicsExposures = pSrc->graphicsExposures;
- break;
- case CPPolyEdge:
- pDst->polyEdge = pSrc->polyEdge;
- break;
- case CPPolyMode:
- pDst->polyMode = pSrc->polyMode;
- break;
- case CPDither:
- pDst->dither = pSrc->dither;
- break;
- case CPComponentAlpha:
- pDst->componentAlpha = pSrc->componentAlpha;
- break;
- }
- mask &= ~bit;
- }
-
- (*ps->ChangePicture)(pDst, origMask);
-}
-
-static void
-ValidateOnePicture (PicturePtr pPicture)
-{
- if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber)
- {
- PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
-
- (*ps->ValidatePicture) (pPicture, pPicture->stateChanges);
- pPicture->stateChanges = 0;
- pPicture->serialNumber = pPicture->pDrawable->serialNumber;
- }
-}
-
-void
-ValidatePicture(PicturePtr pPicture)
-{
- ValidateOnePicture (pPicture);
- if (pPicture->alphaMap)
- ValidateOnePicture (pPicture->alphaMap);
-}
-
-int
-FreePicture (pointer value,
- XID pid)
-{
- PicturePtr pPicture = (PicturePtr) value;
-
- if (--pPicture->refcnt == 0)
- {
- if (pPicture->transform)
- xfree (pPicture->transform);
-
- if (pPicture->pSourcePict)
- {
- if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
- xfree(pPicture->pSourcePict->linear.stops);
-
- xfree(pPicture->pSourcePict);
- }
-
- if (pPicture->pDrawable)
- {
- ScreenPtr pScreen = pPicture->pDrawable->pScreen;
- PictureScreenPtr ps = GetPictureScreen(pScreen);
-
- if (pPicture->alphaMap)
- FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
- (*ps->DestroyPicture) (pPicture);
- (*ps->DestroyPictureClip) (pPicture);
- if (pPicture->pDrawable->type == DRAWABLE_WINDOW)
- {
- WindowPtr pWindow = (WindowPtr) pPicture->pDrawable;
- PicturePtr *pPrev;
-
- for (pPrev = (PicturePtr *)dixLookupPrivateAddr
- (&pWindow->devPrivates, PictureWindowPrivateKey);
- *pPrev;
- pPrev = &(*pPrev)->pNext)
- {
- if (*pPrev == pPicture)
- {
- *pPrev = pPicture->pNext;
- break;
- }
- }
- }
- else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP)
- {
- (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable);
- }
- }
- dixFreePrivates(pPicture->devPrivates);
- xfree (pPicture);
- }
- return Success;
-}
-
-int
-FreePictFormat (pointer pPictFormat,
- XID pid)
-{
- return Success;
-}
-
-/**
- * ReduceCompositeOp is used to choose simpler ops for cases where alpha
- * channels are always one and so math on the alpha channel per pixel becomes
- * unnecessary. It may also avoid destination reads sometimes if apps aren't
- * being careful to avoid these cases.
- */
-static CARD8
-ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
- INT16 xSrc, INT16 ySrc, CARD16 width, CARD16 height)
-{
- Bool no_src_alpha, no_dst_alpha;
-
- /* Sampling off the edge of a RepeatNone picture introduces alpha
- * even if the picture itself doesn't have alpha. We don't try to
- * detect every case where we don't sample off the edge, just the
- * simplest case where there is no transform on the source
- * picture.
- */
- no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) &&
- PICT_FORMAT_A(pSrc->format) == 0 &&
- (pSrc->repeatType != RepeatNone ||
- (!pSrc->transform &&
- xSrc >= 0 && ySrc >= 0 &&
- xSrc + width <= pSrc->pDrawable->width &&
- ySrc + height <= pSrc->pDrawable->height)) &&
- pSrc->alphaMap == NULL &&
- pMask == NULL;
- no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) &&
- PICT_FORMAT_A(pDst->format) == 0 &&
- pDst->alphaMap == NULL;
-
- /* TODO, maybe: Conjoint and Disjoint op reductions? */
-
- /* Deal with simplifications where the source alpha is always 1. */
- if (no_src_alpha)
- {
- switch (op) {
- case PictOpOver:
- op = PictOpSrc;
- break;
- case PictOpInReverse:
- op = PictOpDst;
- break;
- case PictOpOutReverse:
- op = PictOpClear;
- break;
- case PictOpAtop:
- op = PictOpIn;
- break;
- case PictOpAtopReverse:
- op = PictOpOverReverse;
- break;
- case PictOpXor:
- op = PictOpOut;
- break;
- default:
- break;
- }
- }
-
- /* Deal with simplifications when the destination alpha is always 1 */
- if (no_dst_alpha)
- {
- switch (op) {
- case PictOpOverReverse:
- op = PictOpDst;
- break;
- case PictOpIn:
- op = PictOpSrc;
- break;
- case PictOpOut:
- op = PictOpClear;
- break;
- case PictOpAtop:
- op = PictOpOver;
- break;
- case PictOpXor:
- op = PictOpOutReverse;
- break;
- default:
- break;
- }
- }
-
- /* Reduce some con/disjoint ops to the basic names. */
- switch (op) {
- case PictOpDisjointClear:
- case PictOpConjointClear:
- op = PictOpClear;
- break;
- case PictOpDisjointSrc:
- case PictOpConjointSrc:
- op = PictOpSrc;
- break;
- case PictOpDisjointDst:
- case PictOpConjointDst:
- op = PictOpDst;
- break;
- default:
- break;
- }
-
- return op;
-}
-
-void
-CompositePicture (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pMask,
- PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst,
- CARD16 width,
- CARD16 height)
-{
- PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
-
- ValidatePicture (pSrc);
- if (pMask)
- ValidatePicture (pMask);
- ValidatePicture (pDst);
-
- op = ReduceCompositeOp (op, pSrc, pMask, pDst, xSrc, ySrc, width, height);
- if (op == PictOpDst)
- return;
-
- (*ps->Composite) (op,
- pSrc,
- pMask,
- pDst,
- xSrc,
- ySrc,
- xMask,
- yMask,
- xDst,
- yDst,
- width,
- height);
-}
-
-void
-CompositeRects (CARD8 op,
- PicturePtr pDst,
- xRenderColor *color,
- int nRect,
- xRectangle *rects)
-{
- PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
-
- ValidatePicture (pDst);
- (*ps->CompositeRects) (op, pDst, color, nRect, rects);
-}
-
-void
-CompositeTrapezoids (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int ntrap,
- xTrapezoid *traps)
-{
- PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
-
- ValidatePicture (pSrc);
- ValidatePicture (pDst);
- (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps);
-}
-
-void
-CompositeTriangles (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int ntriangles,
- xTriangle *triangles)
-{
- PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
-
- ValidatePicture (pSrc);
- ValidatePicture (pDst);
- (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles);
-}
-
-void
-CompositeTriStrip (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int npoints,
- xPointFixed *points)
-{
- PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
-
- ValidatePicture (pSrc);
- ValidatePicture (pDst);
- (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
-}
-
-void
-CompositeTriFan (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int npoints,
- xPointFixed *points)
-{
- PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
-
- ValidatePicture (pSrc);
- ValidatePicture (pDst);
- (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
-}
-
-void
-AddTraps (PicturePtr pPicture,
- INT16 xOff,
- INT16 yOff,
- int ntrap,
- xTrap *traps)
-{
- PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
-
- ValidatePicture (pPicture);
- (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps);
-}
-
+/*
+ *
+ * Copyright © 2000 SuSE, Inc.
+ *
+ * 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, and that the name of SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include "misc.h"
+#include "scrnintstr.h"
+#include "os.h"
+#include "regionstr.h"
+#include "validate.h"
+#include "windowstr.h"
+#include "input.h"
+#include "resource.h"
+#include "colormapst.h"
+#include "cursorstr.h"
+#include "dixstruct.h"
+#include "gcstruct.h"
+#include "servermd.h"
+#include "picturestr.h"
+#include "xace.h"
+
+static int PictureScreenPrivateKeyIndex;
+DevPrivateKey PictureScreenPrivateKey = &PictureScreenPrivateKeyIndex;
+static int PictureWindowPrivateKeyIndex;
+DevPrivateKey PictureWindowPrivateKey = &PictureWindowPrivateKeyIndex;
+static int PictureGeneration;
+RESTYPE PictureType;
+RESTYPE PictFormatType;
+RESTYPE GlyphSetType;
+int PictureCmapPolicy = PictureCmapPolicyDefault;
+
+Bool
+PictureDestroyWindow (WindowPtr pWindow)
+{
+ ScreenPtr pScreen = pWindow->drawable.pScreen;
+ PicturePtr pPicture;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ Bool ret;
+
+ while ((pPicture = GetPictureWindow(pWindow)))
+ {
+ SetPictureWindow(pWindow, pPicture->pNext);
+ if (pPicture->id)
+ FreeResource (pPicture->id, PictureType);
+ FreePicture ((pointer) pPicture, pPicture->id);
+ }
+ pScreen->DestroyWindow = ps->DestroyWindow;
+ ret = (*pScreen->DestroyWindow) (pWindow);
+ ps->DestroyWindow = pScreen->DestroyWindow;
+ pScreen->DestroyWindow = PictureDestroyWindow;
+ return ret;
+}
+
+Bool
+PictureCloseScreen (int index, ScreenPtr pScreen)
+{
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ Bool ret;
+ int n;
+
+ pScreen->CloseScreen = ps->CloseScreen;
+ ret = (*pScreen->CloseScreen) (index, pScreen);
+ PictureResetFilters (pScreen);
+ for (n = 0; n < ps->nformats; n++)
+ if (ps->formats[n].type == PictTypeIndexed)
+ (*ps->CloseIndexed) (pScreen, &ps->formats[n]);
+ GlyphUninit (pScreen);
+ SetPictureScreen(pScreen, 0);
+ xfree (ps->formats);
+ xfree (ps);
+ return ret;
+}
+
+void
+PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef)
+{
+ ScreenPtr pScreen = pColormap->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ pScreen->StoreColors = ps->StoreColors;
+ (*pScreen->StoreColors) (pColormap, ndef, pdef);
+ ps->StoreColors = pScreen->StoreColors;
+ pScreen->StoreColors = PictureStoreColors;
+
+ if (pColormap->class == PseudoColor || pColormap->class == GrayScale)
+ {
+ PictFormatPtr format = ps->formats;
+ int nformats = ps->nformats;
+
+ while (nformats--)
+ {
+ if (format->type == PictTypeIndexed &&
+ format->index.pColormap == pColormap)
+ {
+ (*ps->UpdateIndexed) (pScreen, format, ndef, pdef);
+ break;
+ }
+ format++;
+ }
+ }
+}
+
+static int
+visualDepth (ScreenPtr pScreen, VisualPtr pVisual)
+{
+ int d, v;
+ DepthPtr pDepth;
+
+ for (d = 0; d < pScreen->numDepths; d++)
+ {
+ pDepth = &pScreen->allowedDepths[d];
+ for (v = 0; v < pDepth->numVids; v++)
+ if (pDepth->vids[v] == pVisual->vid)
+ return pDepth->depth;
+ }
+ return 0;
+}
+
+typedef struct _formatInit {
+ CARD32 format;
+ CARD8 depth;
+} FormatInitRec, *FormatInitPtr;
+
+static int
+addFormat (FormatInitRec formats[256],
+ int nformat,
+ CARD32 format,
+ CARD8 depth)
+{
+ int n;
+
+ for (n = 0; n < nformat; n++)
+ if (formats[n].format == format && formats[n].depth == depth)
+ return nformat;
+ formats[nformat].format = format;
+ formats[nformat].depth = depth;
+ return ++nformat;
+}
+
+#define Mask(n) ((n) == 32 ? 0xffffffff : ((1 << (n))-1))
+
+PictFormatPtr
+PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp)
+{
+ int nformats, f;
+ PictFormatPtr pFormats;
+ FormatInitRec formats[1024];
+ CARD32 format;
+ CARD8 depth;
+ VisualPtr pVisual;
+ int v;
+ int bpp;
+ int type;
+ int r, g, b;
+ int d;
+ DepthPtr pDepth;
+
+ nformats = 0;
+ /* formats required by protocol */
+ formats[nformats].format = PICT_a1;
+ formats[nformats].depth = 1;
+ nformats++;
+ formats[nformats].format = PICT_FORMAT(BitsPerPixel(8),
+ PICT_TYPE_A,
+ 8, 0, 0, 0);
+ formats[nformats].depth = 8;
+ nformats++;
+ formats[nformats].format = PICT_FORMAT(BitsPerPixel(4),
+ PICT_TYPE_A,
+ 4, 0, 0, 0);
+ formats[nformats].depth = 4;
+ nformats++;
+ formats[nformats].format = PICT_a8r8g8b8;
+ formats[nformats].depth = 32;
+ nformats++;
+ formats[nformats].format = PICT_x8r8g8b8;
+ formats[nformats].depth = 32;
+ nformats++;
+ formats[nformats].format = PICT_b8g8r8a8;
+ formats[nformats].depth = 32;
+ nformats++;
+ formats[nformats].format = PICT_b8g8r8x8;
+ formats[nformats].depth = 32;
+ nformats++;
+
+ /* now look through the depths and visuals adding other formats */
+ for (v = 0; v < pScreen->numVisuals; v++)
+ {
+ pVisual = &pScreen->visuals[v];
+ depth = visualDepth (pScreen, pVisual);
+ if (!depth)
+ continue;
+ bpp = BitsPerPixel (depth);
+ switch (pVisual->class) {
+ case DirectColor:
+ case TrueColor:
+ r = Ones (pVisual->redMask);
+ g = Ones (pVisual->greenMask);
+ b = Ones (pVisual->blueMask);
+ type = PICT_TYPE_OTHER;
+ /*
+ * Current rendering code supports only three direct formats,
+ * fields must be packed together at the bottom of the pixel
+ */
+ if (pVisual->offsetBlue == 0 &&
+ pVisual->offsetGreen == b &&
+ pVisual->offsetRed == b + g)
+ {
+ type = PICT_TYPE_ARGB;
+ }
+ else if (pVisual->offsetRed == 0 &&
+ pVisual->offsetGreen == r &&
+ pVisual->offsetBlue == r + g)
+ {
+ type = PICT_TYPE_ABGR;
+ }
+ else if (pVisual->offsetRed == pVisual->offsetGreen - r &&
+ pVisual->offsetGreen == pVisual->offsetBlue - g &&
+ pVisual->offsetBlue == bpp - b)
+ {
+ type = PICT_TYPE_BGRA;
+ }
+ if (type != PICT_TYPE_OTHER)
+ {
+ format = PICT_FORMAT(bpp, type, 0, r, g, b);
+ nformats = addFormat (formats, nformats, format, depth);
+ }
+ break;
+ case StaticColor:
+ case PseudoColor:
+ format = PICT_VISFORMAT (bpp, PICT_TYPE_COLOR, v);
+ nformats = addFormat (formats, nformats, format, depth);
+ break;
+ case StaticGray:
+ case GrayScale:
+ format = PICT_VISFORMAT (bpp, PICT_TYPE_GRAY, v);
+ nformats = addFormat (formats, nformats, format, depth);
+ break;
+ }
+ }
+ /*
+ * Walk supported depths and add useful Direct formats
+ */
+ for (d = 0; d < pScreen->numDepths; d++)
+ {
+ pDepth = &pScreen->allowedDepths[d];
+ bpp = BitsPerPixel (pDepth->depth);
+ format = 0;
+ switch (bpp) {
+ case 16:
+ /* depth 12 formats */
+ if (pDepth->depth >= 12)
+ {
+ nformats = addFormat (formats, nformats,
+ PICT_x4r4g4b4, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_x4b4g4r4, pDepth->depth);
+ }
+ /* depth 15 formats */
+ if (pDepth->depth >= 15)
+ {
+ nformats = addFormat (formats, nformats,
+ PICT_x1r5g5b5, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_x1b5g5r5, pDepth->depth);
+ }
+ /* depth 16 formats */
+ if (pDepth->depth >= 16)
+ {
+ nformats = addFormat (formats, nformats,
+ PICT_a1r5g5b5, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_a1b5g5r5, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_r5g6b5, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_b5g6r5, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_a4r4g4b4, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_a4b4g4r4, pDepth->depth);
+ }
+ break;
+ case 24:
+ if (pDepth->depth >= 24)
+ {
+ nformats = addFormat (formats, nformats,
+ PICT_r8g8b8, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_b8g8r8, pDepth->depth);
+ }
+ break;
+ case 32:
+ if (pDepth->depth >= 24)
+ {
+ nformats = addFormat (formats, nformats,
+ PICT_x8r8g8b8, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_x8b8g8r8, pDepth->depth);
+ }
+ if (pDepth->depth >= 30)
+ {
+ nformats = addFormat (formats, nformats,
+ PICT_a2r10g10b10, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_x2r10g10b10, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_a2b10g10r10, pDepth->depth);
+ nformats = addFormat (formats, nformats,
+ PICT_x2b10g10r10, pDepth->depth);
+ }
+ break;
+ }
+ }
+
+
+ pFormats = xcalloc (nformats, sizeof (PictFormatRec));
+ if (!pFormats)
+ return 0;
+ for (f = 0; f < nformats; f++)
+ {
+ pFormats[f].id = FakeClientID (0);
+ pFormats[f].depth = formats[f].depth;
+ format = formats[f].format;
+ pFormats[f].format = format;
+ switch (PICT_FORMAT_TYPE(format)) {
+ case PICT_TYPE_ARGB:
+ pFormats[f].type = PictTypeDirect;
+
+ pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
+ if (pFormats[f].direct.alphaMask)
+ pFormats[f].direct.alpha = (PICT_FORMAT_R(format) +
+ PICT_FORMAT_G(format) +
+ PICT_FORMAT_B(format));
+
+ pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
+ pFormats[f].direct.red = (PICT_FORMAT_G(format) +
+ PICT_FORMAT_B(format));
+
+ pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
+ pFormats[f].direct.green = PICT_FORMAT_B(format);
+
+ pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
+ pFormats[f].direct.blue = 0;
+ break;
+
+ case PICT_TYPE_ABGR:
+ pFormats[f].type = PictTypeDirect;
+
+ pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
+ if (pFormats[f].direct.alphaMask)
+ pFormats[f].direct.alpha = (PICT_FORMAT_B(format) +
+ PICT_FORMAT_G(format) +
+ PICT_FORMAT_R(format));
+
+ pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
+ pFormats[f].direct.blue = (PICT_FORMAT_G(format) +
+ PICT_FORMAT_R(format));
+
+ pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
+ pFormats[f].direct.green = PICT_FORMAT_R(format);
+
+ pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
+ pFormats[f].direct.red = 0;
+ break;
+
+ case PICT_TYPE_BGRA:
+ pFormats[f].type = PictTypeDirect;
+
+ pFormats[f].direct.blueMask = Mask(PICT_FORMAT_B(format));
+ pFormats[f].direct.blue = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format));
+
+ pFormats[f].direct.greenMask = Mask(PICT_FORMAT_G(format));
+ pFormats[f].direct.green = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format) -
+ PICT_FORMAT_G(format));
+
+ pFormats[f].direct.redMask = Mask(PICT_FORMAT_R(format));
+ pFormats[f].direct.red = (PICT_FORMAT_BPP(format) - PICT_FORMAT_B(format) -
+ PICT_FORMAT_G(format) - PICT_FORMAT_R(format));
+
+ pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
+ pFormats[f].direct.alpha = 0;
+ break;
+
+ case PICT_TYPE_A:
+ pFormats[f].type = PictTypeDirect;
+
+ pFormats[f].direct.alpha = 0;
+ pFormats[f].direct.alphaMask = Mask(PICT_FORMAT_A(format));
+
+ /* remaining fields already set to zero */
+ break;
+
+ case PICT_TYPE_COLOR:
+ case PICT_TYPE_GRAY:
+ pFormats[f].type = PictTypeIndexed;
+ pFormats[f].index.vid = pScreen->visuals[PICT_FORMAT_VIS(format)].vid;
+ break;
+ }
+ }
+ *nformatp = nformats;
+ return pFormats;
+}
+
+static VisualPtr
+PictureFindVisual (ScreenPtr pScreen, VisualID visual)
+{
+ int i;
+ VisualPtr pVisual;
+ for (i = 0, pVisual = pScreen->visuals;
+ i < pScreen->numVisuals;
+ i++, pVisual++)
+ {
+ if (pVisual->vid == visual)
+ return pVisual;
+ }
+ return 0;
+}
+
+Bool
+PictureInitIndexedFormat(ScreenPtr pScreen, PictFormatPtr format)
+{
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+
+ if (format->type != PictTypeIndexed || format->index.pColormap)
+ return TRUE;
+
+ if (format->index.vid == pScreen->rootVisual) {
+ dixLookupResourceByType((pointer *)&format->index.pColormap,
+ pScreen->defColormap, RT_COLORMAP,
+ serverClient, DixGetAttrAccess);
+ } else {
+ VisualPtr pVisual = PictureFindVisual(pScreen, format->index.vid);
+ if (CreateColormap(FakeClientID (0), pScreen, pVisual,
+ &format->index.pColormap, AllocNone, 0)
+ != Success)
+ return FALSE;
+ }
+ if (!ps->InitIndexed(pScreen, format))
+ return FALSE;
+ return TRUE;
+}
+
+static Bool
+PictureInitIndexedFormats (ScreenPtr pScreen)
+{
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+ PictFormatPtr format;
+ int nformat;
+
+ if (!ps)
+ return FALSE;
+ format = ps->formats;
+ nformat = ps->nformats;
+ while (nformat--)
+ if (!PictureInitIndexedFormat(pScreen, format++))
+ return FALSE;
+ return TRUE;
+}
+
+Bool
+PictureFinishInit (void)
+{
+ int s;
+
+ for (s = 0; s < screenInfo.numScreens; s++)
+ {
+ if (!PictureInitIndexedFormats (screenInfo.screens[s]))
+ return FALSE;
+ (void) AnimCurInit (screenInfo.screens[s]);
+ }
+
+ return TRUE;
+}
+
+Bool
+PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel)
+{
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+
+ if (!ps)
+ return FALSE;
+ ps->subpixel = subpixel;
+ return TRUE;
+
+}
+
+int
+PictureGetSubpixelOrder (ScreenPtr pScreen)
+{
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+
+ if (!ps)
+ return SubPixelUnknown;
+ return ps->subpixel;
+}
+
+PictFormatPtr
+PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual)
+{
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+ PictFormatPtr format;
+ int nformat;
+ int type;
+
+ if (!ps)
+ return 0;
+ format = ps->formats;
+ nformat = ps->nformats;
+ switch (pVisual->class) {
+ case StaticGray:
+ case GrayScale:
+ case StaticColor:
+ case PseudoColor:
+ type = PictTypeIndexed;
+ break;
+ case TrueColor:
+ case DirectColor:
+ type = PictTypeDirect;
+ break;
+ default:
+ return 0;
+ }
+ while (nformat--)
+ {
+ if (format->depth == depth && format->type == type)
+ {
+ if (type == PictTypeIndexed)
+ {
+ if (format->index.vid == pVisual->vid)
+ return format;
+ }
+ else
+ {
+ if (format->direct.redMask << format->direct.red ==
+ pVisual->redMask &&
+ format->direct.greenMask << format->direct.green ==
+ pVisual->greenMask &&
+ format->direct.blueMask << format->direct.blue ==
+ pVisual->blueMask)
+ {
+ return format;
+ }
+ }
+ }
+ format++;
+ }
+ return 0;
+}
+
+PictFormatPtr
+PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 f)
+{
+ PictureScreenPtr ps = GetPictureScreenIfSet(pScreen);
+ PictFormatPtr format;
+ int nformat;
+
+ if (!ps)
+ return 0;
+ format = ps->formats;
+ nformat = ps->nformats;
+ while (nformat--)
+ {
+ if (format->depth == depth && format->format == (f & 0xffffff))
+ return format;
+ format++;
+ }
+ return 0;
+}
+
+int
+PictureParseCmapPolicy (const char *name)
+{
+ if ( strcmp (name, "default" ) == 0)
+ return PictureCmapPolicyDefault;
+ else if ( strcmp (name, "mono" ) == 0)
+ return PictureCmapPolicyMono;
+ else if ( strcmp (name, "gray" ) == 0)
+ return PictureCmapPolicyGray;
+ else if ( strcmp (name, "color" ) == 0)
+ return PictureCmapPolicyColor;
+ else if ( strcmp (name, "all" ) == 0)
+ return PictureCmapPolicyAll;
+ else
+ return PictureCmapPolicyInvalid;
+}
+
+Bool
+PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats)
+{
+ PictureScreenPtr ps;
+ int n;
+ CARD32 type, a, r, g, b;
+
+ if (PictureGeneration != serverGeneration)
+ {
+ PictureType = CreateNewResourceType (FreePicture, "PICTURE");
+ if (!PictureType)
+ return FALSE;
+ PictFormatType = CreateNewResourceType (FreePictFormat, "PICTFORMAT");
+ if (!PictFormatType)
+ return FALSE;
+ GlyphSetType = CreateNewResourceType (FreeGlyphSet, "GLYPHSET");
+ if (!GlyphSetType)
+ return FALSE;
+ PictureGeneration = serverGeneration;
+ }
+ if (!formats)
+ {
+ formats = PictureCreateDefaultFormats (pScreen, &nformats);
+ if (!formats)
+ return FALSE;
+ }
+ for (n = 0; n < nformats; n++)
+ {
+ if (!AddResource (formats[n].id, PictFormatType, (pointer) (formats+n)))
+ {
+ xfree (formats);
+ return FALSE;
+ }
+ if (formats[n].type == PictTypeIndexed)
+ {
+ VisualPtr pVisual = PictureFindVisual (pScreen, formats[n].index.vid);
+ if ((pVisual->class | DynamicClass) == PseudoColor)
+ type = PICT_TYPE_COLOR;
+ else
+ type = PICT_TYPE_GRAY;
+ a = r = g = b = 0;
+ }
+ else
+ {
+ if ((formats[n].direct.redMask|
+ formats[n].direct.blueMask|
+ formats[n].direct.greenMask) == 0)
+ type = PICT_TYPE_A;
+ else if (formats[n].direct.red > formats[n].direct.blue)
+ type = PICT_TYPE_ARGB;
+ else if (formats[n].direct.red == 0)
+ type = PICT_TYPE_ABGR;
+ else
+ type = PICT_TYPE_BGRA;
+ a = Ones (formats[n].direct.alphaMask);
+ r = Ones (formats[n].direct.redMask);
+ g = Ones (formats[n].direct.greenMask);
+ b = Ones (formats[n].direct.blueMask);
+ }
+ formats[n].format = PICT_FORMAT(0,type,a,r,g,b);
+ }
+ ps = (PictureScreenPtr) xalloc (sizeof (PictureScreenRec));
+ if (!ps)
+ {
+ xfree (formats);
+ return FALSE;
+ }
+ SetPictureScreen(pScreen, ps);
+
+ ps->formats = formats;
+ ps->fallback = formats;
+ ps->nformats = nformats;
+
+ ps->filters = 0;
+ ps->nfilters = 0;
+ ps->filterAliases = 0;
+ ps->nfilterAliases = 0;
+
+ ps->subpixel = SubPixelUnknown;
+
+ ps->CloseScreen = pScreen->CloseScreen;
+ ps->DestroyWindow = pScreen->DestroyWindow;
+ ps->StoreColors = pScreen->StoreColors;
+ pScreen->DestroyWindow = PictureDestroyWindow;
+ pScreen->CloseScreen = PictureCloseScreen;
+ pScreen->StoreColors = PictureStoreColors;
+
+ if (!PictureSetDefaultFilters (pScreen))
+ {
+ PictureResetFilters (pScreen);
+ SetPictureScreen(pScreen, 0);
+ xfree (formats);
+ xfree (ps);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+void
+SetPictureToDefaults (PicturePtr pPicture)
+{
+ pPicture->refcnt = 1;
+ pPicture->repeat = 0;
+ pPicture->graphicsExposures = FALSE;
+ pPicture->subWindowMode = ClipByChildren;
+ pPicture->polyEdge = PolyEdgeSharp;
+ pPicture->polyMode = PolyModePrecise;
+ pPicture->freeCompClip = FALSE;
+ pPicture->clientClipType = CT_NONE;
+ pPicture->componentAlpha = FALSE;
+ pPicture->repeatType = RepeatNone;
+
+ pPicture->alphaMap = 0;
+ pPicture->alphaOrigin.x = 0;
+ pPicture->alphaOrigin.y = 0;
+
+ pPicture->clipOrigin.x = 0;
+ pPicture->clipOrigin.y = 0;
+ pPicture->clientClip = 0;
+
+ pPicture->transform = 0;
+
+ pPicture->dither = None;
+ pPicture->filter = PictureGetFilterId (FilterNearest, -1, TRUE);
+ pPicture->filter_params = 0;
+ pPicture->filter_nparams = 0;
+
+ pPicture->serialNumber = GC_CHANGE_SERIAL_BIT;
+ pPicture->stateChanges = (1 << (CPLastBit+1)) - 1;
+ pPicture->pSourcePict = 0;
+}
+
+PicturePtr
+CreatePicture (Picture pid,
+ DrawablePtr pDrawable,
+ PictFormatPtr pFormat,
+ Mask vmask,
+ XID *vlist,
+ ClientPtr client,
+ int *error)
+{
+ PicturePtr pPicture;
+ PictureScreenPtr ps = GetPictureScreen(pDrawable->pScreen);
+
+ pPicture = (PicturePtr)xalloc(sizeof(PictureRec));
+ if (!pPicture)
+ {
+ *error = BadAlloc;
+ return 0;
+ }
+
+ pPicture->id = pid;
+ pPicture->pDrawable = pDrawable;
+ pPicture->pFormat = pFormat;
+ pPicture->format = pFormat->format | (pDrawable->bitsPerPixel << 24);
+ pPicture->devPrivates = NULL;
+
+ /* security creation/labeling check */
+ *error = XaceHook(XACE_RESOURCE_ACCESS, client, pid, PictureType, pPicture,
+ RT_PIXMAP, pDrawable, DixCreateAccess|DixSetAttrAccess);
+ if (*error != Success)
+ goto out;
+
+ if (pDrawable->type == DRAWABLE_PIXMAP)
+ {
+ ++((PixmapPtr)pDrawable)->refcnt;
+ pPicture->pNext = 0;
+ }
+ else
+ {
+ pPicture->pNext = GetPictureWindow(((WindowPtr) pDrawable));
+ SetPictureWindow(((WindowPtr) pDrawable), pPicture);
+ }
+
+ SetPictureToDefaults (pPicture);
+
+ if (vmask)
+ *error = ChangePicture (pPicture, vmask, vlist, 0, client);
+ else
+ *error = Success;
+ if (*error == Success)
+ *error = (*ps->CreatePicture) (pPicture);
+out:
+ if (*error != Success)
+ {
+ FreePicture (pPicture, (XID) 0);
+ pPicture = 0;
+ }
+ return pPicture;
+}
+
+static CARD32 xRenderColorToCard32(xRenderColor c)
+{
+ return
+ (c.alpha >> 8 << 24) |
+ (c.red >> 8 << 16) |
+ (c.green & 0xff00) |
+ (c.blue >> 8);
+}
+
+static unsigned int premultiply(unsigned int x)
+{
+ unsigned int a = x >> 24;
+ unsigned int t = (x & 0xff00ff) * a + 0x800080;
+ t = (t + ((t >> 8) & 0xff00ff)) >> 8;
+ t &= 0xff00ff;
+
+ x = ((x >> 8) & 0xff) * a + 0x80;
+ x = (x + ((x >> 8) & 0xff));
+ x &= 0xff00;
+ x |= t | (a << 24);
+ return x;
+}
+
+static unsigned int INTERPOLATE_PIXEL_256(unsigned int x, unsigned int a,
+ unsigned int y, unsigned int b)
+{
+ CARD32 t = (x & 0xff00ff) * a + (y & 0xff00ff) * b;
+ t >>= 8;
+ t &= 0xff00ff;
+
+ x = ((x >> 8) & 0xff00ff) * a + ((y >> 8) & 0xff00ff) * b;
+ x &= 0xff00ff00;
+ x |= t;
+ return x;
+}
+
+CARD32
+PictureGradientColor (PictGradientStopPtr stop1,
+ PictGradientStopPtr stop2,
+ CARD32 x)
+{
+ CARD32 current_color, next_color;
+ int dist, idist;
+
+ current_color = xRenderColorToCard32 (stop1->color);
+ next_color = xRenderColorToCard32 (stop2->color);
+
+ dist = (int) (256 * (x - stop1->x) / (stop2->x - stop1->x));
+ idist = 256 - dist;
+
+ return premultiply (INTERPOLATE_PIXEL_256 (current_color, idist,
+ next_color, dist));
+}
+
+static void initGradient(SourcePictPtr pGradient, int stopCount,
+ xFixed *stopPoints, xRenderColor *stopColors, int *error)
+{
+ int i;
+ xFixed dpos;
+
+ if (stopCount <= 0) {
+ *error = BadValue;
+ return;
+ }
+
+ dpos = -1;
+ for (i = 0; i < stopCount; ++i) {
+ if (stopPoints[i] < dpos || stopPoints[i] > (1<<16)) {
+ *error = BadValue;
+ return;
+ }
+ dpos = stopPoints[i];
+ }
+
+ pGradient->gradient.stops = xalloc(stopCount*sizeof(PictGradientStop));
+ if (!pGradient->gradient.stops) {
+ *error = BadAlloc;
+ return;
+ }
+
+ pGradient->gradient.nstops = stopCount;
+
+ for (i = 0; i < stopCount; ++i) {
+ pGradient->gradient.stops[i].x = stopPoints[i];
+ pGradient->gradient.stops[i].color = stopColors[i];
+ }
+
+ pGradient->gradient.class = SourcePictClassUnknown;
+ pGradient->gradient.stopRange = 0xffff;
+ pGradient->gradient.colorTable = NULL;
+ pGradient->gradient.colorTableSize = 0;
+}
+
+static PicturePtr createSourcePicture(void)
+{
+ PicturePtr pPicture;
+ pPicture = (PicturePtr) xalloc(sizeof(PictureRec));
+ pPicture->pDrawable = 0;
+ pPicture->pFormat = 0;
+ pPicture->pNext = 0;
+ pPicture->format = PICT_a8r8g8b8;
+ pPicture->devPrivates = 0;
+
+ SetPictureToDefaults(pPicture);
+ return pPicture;
+}
+
+PicturePtr
+CreateSolidPicture (Picture pid, xRenderColor *color, int *error)
+{
+ PicturePtr pPicture;
+ pPicture = createSourcePicture();
+ if (!pPicture) {
+ *error = BadAlloc;
+ return 0;
+ }
+
+ pPicture->id = pid;
+ pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictSolidFill));
+ if (!pPicture->pSourcePict) {
+ *error = BadAlloc;
+ xfree(pPicture);
+ return 0;
+ }
+ pPicture->pSourcePict->type = SourcePictTypeSolidFill;
+ pPicture->pSourcePict->solidFill.color = xRenderColorToCard32(*color);
+ return pPicture;
+}
+
+PicturePtr
+CreateLinearGradientPicture (Picture pid, xPointFixed *p1, xPointFixed *p2,
+ int nStops, xFixed *stops, xRenderColor *colors, int *error)
+{
+ PicturePtr pPicture;
+
+ if (nStops < 2) {
+ *error = BadValue;
+ return 0;
+ }
+
+ pPicture = createSourcePicture();
+ if (!pPicture) {
+ *error = BadAlloc;
+ return 0;
+ }
+
+ pPicture->id = pid;
+ pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictLinearGradient));
+ if (!pPicture->pSourcePict) {
+ *error = BadAlloc;
+ xfree(pPicture);
+ return 0;
+ }
+
+ pPicture->pSourcePict->linear.type = SourcePictTypeLinear;
+ pPicture->pSourcePict->linear.p1 = *p1;
+ pPicture->pSourcePict->linear.p2 = *p2;
+
+ initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
+ if (*error) {
+ xfree(pPicture);
+ return 0;
+ }
+ return pPicture;
+}
+
+#define FixedToDouble(x) ((x)/65536.)
+
+PicturePtr
+CreateRadialGradientPicture (Picture pid, xPointFixed *inner, xPointFixed *outer,
+ xFixed innerRadius, xFixed outerRadius,
+ int nStops, xFixed *stops, xRenderColor *colors, int *error)
+{
+ PicturePtr pPicture;
+ PictRadialGradient *radial;
+
+ if (nStops < 2) {
+ *error = BadValue;
+ return 0;
+ }
+
+ pPicture = createSourcePicture();
+ if (!pPicture) {
+ *error = BadAlloc;
+ return 0;
+ }
+
+ pPicture->id = pid;
+ pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictRadialGradient));
+ if (!pPicture->pSourcePict) {
+ *error = BadAlloc;
+ xfree(pPicture);
+ return 0;
+ }
+ radial = &pPicture->pSourcePict->radial;
+
+ radial->type = SourcePictTypeRadial;
+ radial->c1.x = inner->x;
+ radial->c1.y = inner->y;
+ radial->c1.radius = innerRadius;
+ radial->c2.x = outer->x;
+ radial->c2.y = outer->y;
+ radial->c2.radius = outerRadius;
+ radial->cdx = (radial->c2.x - radial->c1.x) / 65536.;
+ radial->cdy = (radial->c2.y - radial->c1.y) / 65536.;
+ radial->dr = (radial->c2.radius - radial->c1.radius) / 65536.;
+ radial->A = ( radial->cdx * radial->cdx
+ + radial->cdy * radial->cdy
+ - radial->dr * radial->dr);
+
+ initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
+ if (*error) {
+ xfree(pPicture);
+ return 0;
+ }
+ return pPicture;
+}
+
+PicturePtr
+CreateConicalGradientPicture (Picture pid, xPointFixed *center, xFixed angle,
+ int nStops, xFixed *stops, xRenderColor *colors, int *error)
+{
+ PicturePtr pPicture;
+
+ if (nStops < 2) {
+ *error = BadValue;
+ return 0;
+ }
+
+ pPicture = createSourcePicture();
+ if (!pPicture) {
+ *error = BadAlloc;
+ return 0;
+ }
+
+ pPicture->id = pid;
+ pPicture->pSourcePict = (SourcePictPtr) xalloc(sizeof(PictConicalGradient));
+ if (!pPicture->pSourcePict) {
+ *error = BadAlloc;
+ xfree(pPicture);
+ return 0;
+ }
+
+ pPicture->pSourcePict->conical.type = SourcePictTypeConical;
+ pPicture->pSourcePict->conical.center = *center;
+ pPicture->pSourcePict->conical.angle = angle;
+
+ initGradient(pPicture->pSourcePict, nStops, stops, colors, error);
+ if (*error) {
+ xfree(pPicture);
+ return 0;
+ }
+ return pPicture;
+}
+
+#define NEXT_VAL(_type) (vlist ? (_type) *vlist++ : (_type) ulist++->val)
+
+#define NEXT_PTR(_type) ((_type) ulist++->ptr)
+
+int
+ChangePicture (PicturePtr pPicture,
+ Mask vmask,
+ XID *vlist,
+ DevUnion *ulist,
+ ClientPtr client)
+{
+ ScreenPtr pScreen = pPicture->pDrawable ? pPicture->pDrawable->pScreen : 0;
+ PictureScreenPtr ps = pScreen ? GetPictureScreen(pScreen) : 0;
+ BITS32 index2;
+ int error = 0;
+ BITS32 maskQ;
+
+ pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
+ maskQ = vmask;
+ while (vmask && !error)
+ {
+ index2 = (BITS32) lowbit (vmask);
+ vmask &= ~index2;
+ pPicture->stateChanges |= index2;
+ switch (index2)
+ {
+ case CPRepeat:
+ {
+ unsigned int newr;
+ newr = NEXT_VAL(unsigned int);
+ if (newr <= RepeatReflect)
+ {
+ pPicture->repeat = (newr != RepeatNone);
+ pPicture->repeatType = newr;
+ }
+ else
+ {
+ client->errorValue = newr;
+ error = BadValue;
+ }
+ }
+ break;
+ case CPAlphaMap:
+ {
+ PicturePtr pAlpha;
+
+ if (vlist)
+ {
+ Picture pid = NEXT_VAL(Picture);
+
+ if (pid == None)
+ pAlpha = 0;
+ else
+ {
+ error = dixLookupResourceByType((pointer *)&pAlpha, pid,
+ PictureType, client,
+ DixReadAccess);
+ if (error != Success)
+ {
+ client->errorValue = pid;
+ error = (error == BadValue) ? RenderErrBase + BadPicture : error;
+ break;
+ }
+ if (pAlpha->pDrawable == NULL ||
+ pAlpha->pDrawable->type != DRAWABLE_PIXMAP)
+ {
+ client->errorValue = pid;
+ error = BadMatch;
+ break;
+ }
+ }
+ }
+ else
+ pAlpha = NEXT_PTR(PicturePtr);
+ if (!error)
+ {
+ if (pAlpha && pAlpha->pDrawable->type == DRAWABLE_PIXMAP)
+ pAlpha->refcnt++;
+ if (pPicture->alphaMap)
+ FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
+ pPicture->alphaMap = pAlpha;
+ }
+ }
+ break;
+ case CPAlphaXOrigin:
+ pPicture->alphaOrigin.x = NEXT_VAL(INT16);
+ break;
+ case CPAlphaYOrigin:
+ pPicture->alphaOrigin.y = NEXT_VAL(INT16);
+ break;
+ case CPClipXOrigin:
+ pPicture->clipOrigin.x = NEXT_VAL(INT16);
+ break;
+ case CPClipYOrigin:
+ pPicture->clipOrigin.y = NEXT_VAL(INT16);
+ break;
+ case CPClipMask:
+ {
+ Pixmap pid;
+ PixmapPtr pPixmap;
+ int clipType;
+ if (!pScreen)
+ return BadDrawable;
+
+ if (vlist)
+ {
+ pid = NEXT_VAL(Pixmap);
+ if (pid == None)
+ {
+ clipType = CT_NONE;
+ pPixmap = NullPixmap;
+ }
+ else
+ {
+ clipType = CT_PIXMAP;
+ error = dixLookupResourceByType((pointer *)&pPixmap, pid,
+ RT_PIXMAP, client,
+ DixReadAccess);
+ if (error != Success)
+ {
+ client->errorValue = pid;
+ error = (error == BadValue) ? BadPixmap : error;
+ break;
+ }
+ }
+ }
+ else
+ {
+ pPixmap = NEXT_PTR(PixmapPtr);
+ if (pPixmap)
+ clipType = CT_PIXMAP;
+ else
+ clipType = CT_NONE;
+ }
+
+ if (pPixmap)
+ {
+ if ((pPixmap->drawable.depth != 1) ||
+ (pPixmap->drawable.pScreen != pScreen))
+ {
+ error = BadMatch;
+ break;
+ }
+ else
+ {
+ clipType = CT_PIXMAP;
+ pPixmap->refcnt++;
+ }
+ }
+ error = (*ps->ChangePictureClip)(pPicture, clipType,
+ (pointer)pPixmap, 0);
+ break;
+ }
+ case CPGraphicsExposure:
+ {
+ unsigned int newe;
+ newe = NEXT_VAL(unsigned int);
+ if (newe <= xTrue)
+ pPicture->graphicsExposures = newe;
+ else
+ {
+ client->errorValue = newe;
+ error = BadValue;
+ }
+ }
+ break;
+ case CPSubwindowMode:
+ {
+ unsigned int news;
+ news = NEXT_VAL(unsigned int);
+ if (news == ClipByChildren || news == IncludeInferiors)
+ pPicture->subWindowMode = news;
+ else
+ {
+ client->errorValue = news;
+ error = BadValue;
+ }
+ }
+ break;
+ case CPPolyEdge:
+ {
+ unsigned int newe;
+ newe = NEXT_VAL(unsigned int);
+ if (newe == PolyEdgeSharp || newe == PolyEdgeSmooth)
+ pPicture->polyEdge = newe;
+ else
+ {
+ client->errorValue = newe;
+ error = BadValue;
+ }
+ }
+ break;
+ case CPPolyMode:
+ {
+ unsigned int newm;
+ newm = NEXT_VAL(unsigned int);
+ if (newm == PolyModePrecise || newm == PolyModeImprecise)
+ pPicture->polyMode = newm;
+ else
+ {
+ client->errorValue = newm;
+ error = BadValue;
+ }
+ }
+ break;
+ case CPDither:
+ pPicture->dither = NEXT_VAL(Atom);
+ break;
+ case CPComponentAlpha:
+ {
+ unsigned int newca;
+
+ newca = NEXT_VAL (unsigned int);
+ if (newca <= xTrue)
+ pPicture->componentAlpha = newca;
+ else
+ {
+ client->errorValue = newca;
+ error = BadValue;
+ }
+ }
+ break;
+ default:
+ client->errorValue = maskQ;
+ error = BadValue;
+ break;
+ }
+ }
+ if (ps)
+ (*ps->ChangePicture) (pPicture, maskQ);
+ return error;
+}
+
+int
+SetPictureClipRects (PicturePtr pPicture,
+ int xOrigin,
+ int yOrigin,
+ int nRect,
+ xRectangle *rects)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ RegionPtr clientClip;
+ int result;
+
+ clientClip = RECTS_TO_REGION(pScreen,
+ nRect, rects, CT_UNSORTED);
+ if (!clientClip)
+ return BadAlloc;
+ result =(*ps->ChangePictureClip) (pPicture, CT_REGION,
+ (pointer) clientClip, 0);
+ if (result == Success)
+ {
+ pPicture->clipOrigin.x = xOrigin;
+ pPicture->clipOrigin.y = yOrigin;
+ pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
+ pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
+ }
+ return result;
+}
+
+int
+SetPictureClipRegion (PicturePtr pPicture,
+ int xOrigin,
+ int yOrigin,
+ RegionPtr pRegion)
+{
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+ RegionPtr clientClip;
+ int result;
+ int type;
+
+ if (pRegion)
+ {
+ type = CT_REGION;
+ clientClip = REGION_CREATE (pScreen,
+ REGION_EXTENTS(pScreen, pRegion),
+ REGION_NUM_RECTS(pRegion));
+ if (!clientClip)
+ return BadAlloc;
+ if (!REGION_COPY (pSCreen, clientClip, pRegion))
+ {
+ REGION_DESTROY (pScreen, clientClip);
+ return BadAlloc;
+ }
+ }
+ else
+ {
+ type = CT_NONE;
+ clientClip = 0;
+ }
+
+ result =(*ps->ChangePictureClip) (pPicture, type,
+ (pointer) clientClip, 0);
+ if (result == Success)
+ {
+ pPicture->clipOrigin.x = xOrigin;
+ pPicture->clipOrigin.y = yOrigin;
+ pPicture->stateChanges |= CPClipXOrigin|CPClipYOrigin|CPClipMask;
+ pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
+ }
+ return result;
+}
+
+static Bool
+transformIsIdentity(PictTransform *t)
+{
+ return ((t->matrix[0][0] == t->matrix[1][1]) &&
+ (t->matrix[0][0] == t->matrix[2][2]) &&
+ (t->matrix[0][0] != 0) &&
+ (t->matrix[0][1] == 0) &&
+ (t->matrix[0][2] == 0) &&
+ (t->matrix[1][0] == 0) &&
+ (t->matrix[1][2] == 0) &&
+ (t->matrix[2][0] == 0) &&
+ (t->matrix[2][1] == 0));
+}
+
+int
+SetPictureTransform (PicturePtr pPicture,
+ PictTransform *transform)
+{
+ if (transform && transformIsIdentity (transform))
+ transform = 0;
+
+ if (transform)
+ {
+ if (!pPicture->transform)
+ {
+ pPicture->transform = (PictTransform *) xalloc (sizeof (PictTransform));
+ if (!pPicture->transform)
+ return BadAlloc;
+ }
+ *pPicture->transform = *transform;
+ }
+ else
+ {
+ if (pPicture->transform)
+ {
+ xfree (pPicture->transform);
+ pPicture->transform = 0;
+ }
+ }
+ pPicture->serialNumber |= GC_CHANGE_SERIAL_BIT;
+
+ if (pPicture->pDrawable != NULL) {
+ int result;
+ PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
+
+ result = (*ps->ChangePictureTransform) (pPicture, transform);
+
+ return result;
+ }
+
+ return Success;
+}
+
+void
+CopyPicture (PicturePtr pSrc,
+ Mask mask,
+ PicturePtr pDst)
+{
+ PictureScreenPtr ps = GetPictureScreen(pSrc->pDrawable->pScreen);
+ Mask origMask = mask;
+
+ pDst->serialNumber |= GC_CHANGE_SERIAL_BIT;
+ pDst->stateChanges |= mask;
+
+ while (mask) {
+ Mask bit = lowbit(mask);
+
+ switch (bit)
+ {
+ case CPRepeat:
+ pDst->repeat = pSrc->repeat;
+ pDst->repeatType = pSrc->repeatType;
+ break;
+ case CPAlphaMap:
+ if (pSrc->alphaMap && pSrc->alphaMap->pDrawable->type == DRAWABLE_PIXMAP)
+ pSrc->alphaMap->refcnt++;
+ if (pDst->alphaMap)
+ FreePicture ((pointer) pDst->alphaMap, (XID) 0);
+ pDst->alphaMap = pSrc->alphaMap;
+ break;
+ case CPAlphaXOrigin:
+ pDst->alphaOrigin.x = pSrc->alphaOrigin.x;
+ break;
+ case CPAlphaYOrigin:
+ pDst->alphaOrigin.y = pSrc->alphaOrigin.y;
+ break;
+ case CPClipXOrigin:
+ pDst->clipOrigin.x = pSrc->clipOrigin.x;
+ break;
+ case CPClipYOrigin:
+ pDst->clipOrigin.y = pSrc->clipOrigin.y;
+ break;
+ case CPClipMask:
+ switch (pSrc->clientClipType) {
+ case CT_NONE:
+ (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
+ break;
+ case CT_REGION:
+ if (!pSrc->clientClip) {
+ (*ps->ChangePictureClip)(pDst, CT_NONE, NULL, 0);
+ } else {
+ RegionPtr clientClip;
+ RegionPtr srcClientClip = (RegionPtr)pSrc->clientClip;
+
+ clientClip = REGION_CREATE(pSrc->pDrawable->pScreen,
+ REGION_EXTENTS(pSrc->pDrawable->pScreen, srcClientClip),
+ REGION_NUM_RECTS(srcClientClip));
+ (*ps->ChangePictureClip)(pDst, CT_REGION, clientClip, 0);
+ }
+ break;
+ default:
+ /* XXX: CT_PIXMAP unimplemented */
+ break;
+ }
+ break;
+ case CPGraphicsExposure:
+ pDst->graphicsExposures = pSrc->graphicsExposures;
+ break;
+ case CPPolyEdge:
+ pDst->polyEdge = pSrc->polyEdge;
+ break;
+ case CPPolyMode:
+ pDst->polyMode = pSrc->polyMode;
+ break;
+ case CPDither:
+ pDst->dither = pSrc->dither;
+ break;
+ case CPComponentAlpha:
+ pDst->componentAlpha = pSrc->componentAlpha;
+ break;
+ }
+ mask &= ~bit;
+ }
+
+ (*ps->ChangePicture)(pDst, origMask);
+}
+
+static void
+ValidateOnePicture (PicturePtr pPicture)
+{
+ if (pPicture->pDrawable && pPicture->serialNumber != pPicture->pDrawable->serialNumber)
+ {
+ PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
+
+ (*ps->ValidatePicture) (pPicture, pPicture->stateChanges);
+ pPicture->stateChanges = 0;
+ pPicture->serialNumber = pPicture->pDrawable->serialNumber;
+ }
+}
+
+void
+ValidatePicture(PicturePtr pPicture)
+{
+ ValidateOnePicture (pPicture);
+ if (pPicture->alphaMap)
+ ValidateOnePicture (pPicture->alphaMap);
+}
+
+int
+FreePicture (pointer value,
+ XID pid)
+{
+ PicturePtr pPicture = (PicturePtr) value;
+
+ if (--pPicture->refcnt == 0)
+ {
+ if (pPicture->transform)
+ xfree (pPicture->transform);
+
+ if (pPicture->pSourcePict)
+ {
+ if (pPicture->pSourcePict->type != SourcePictTypeSolidFill)
+ xfree(pPicture->pSourcePict->linear.stops);
+
+ xfree(pPicture->pSourcePict);
+ }
+
+ if (pPicture->pDrawable)
+ {
+ ScreenPtr pScreen = pPicture->pDrawable->pScreen;
+ PictureScreenPtr ps = GetPictureScreen(pScreen);
+
+ if (pPicture->alphaMap)
+ FreePicture ((pointer) pPicture->alphaMap, (XID) 0);
+ (*ps->DestroyPicture) (pPicture);
+ (*ps->DestroyPictureClip) (pPicture);
+ if (pPicture->pDrawable->type == DRAWABLE_WINDOW)
+ {
+ WindowPtr pWindow = (WindowPtr) pPicture->pDrawable;
+ PicturePtr *pPrev;
+
+ for (pPrev = (PicturePtr *)dixLookupPrivateAddr
+ (&pWindow->devPrivates, PictureWindowPrivateKey);
+ *pPrev;
+ pPrev = &(*pPrev)->pNext)
+ {
+ if (*pPrev == pPicture)
+ {
+ *pPrev = pPicture->pNext;
+ break;
+ }
+ }
+ }
+ else if (pPicture->pDrawable->type == DRAWABLE_PIXMAP)
+ {
+ (*pScreen->DestroyPixmap) ((PixmapPtr)pPicture->pDrawable);
+ }
+ }
+ dixFreePrivates(pPicture->devPrivates);
+ xfree (pPicture);
+ }
+ return Success;
+}
+
+int
+FreePictFormat (pointer pPictFormat,
+ XID pid)
+{
+ return Success;
+}
+
+/**
+ * ReduceCompositeOp is used to choose simpler ops for cases where alpha
+ * channels are always one and so math on the alpha channel per pixel becomes
+ * unnecessary. It may also avoid destination reads sometimes if apps aren't
+ * being careful to avoid these cases.
+ */
+static CARD8
+ReduceCompositeOp (CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst,
+ INT16 xSrc, INT16 ySrc, CARD16 width, CARD16 height)
+{
+ Bool no_src_alpha, no_dst_alpha;
+
+ /* Sampling off the edge of a RepeatNone picture introduces alpha
+ * even if the picture itself doesn't have alpha. We don't try to
+ * detect every case where we don't sample off the edge, just the
+ * simplest case where there is no transform on the source
+ * picture.
+ */
+ no_src_alpha = PICT_FORMAT_COLOR(pSrc->format) &&
+ PICT_FORMAT_A(pSrc->format) == 0 &&
+ (pSrc->repeatType != RepeatNone ||
+ (!pSrc->transform &&
+ xSrc >= 0 && ySrc >= 0 &&
+ xSrc + width <= pSrc->pDrawable->width &&
+ ySrc + height <= pSrc->pDrawable->height)) &&
+ pSrc->alphaMap == NULL &&
+ pMask == NULL;
+ no_dst_alpha = PICT_FORMAT_COLOR(pDst->format) &&
+ PICT_FORMAT_A(pDst->format) == 0 &&
+ pDst->alphaMap == NULL;
+
+ /* TODO, maybe: Conjoint and Disjoint op reductions? */
+
+ /* Deal with simplifications where the source alpha is always 1. */
+ if (no_src_alpha)
+ {
+ switch (op) {
+ case PictOpOver:
+ op = PictOpSrc;
+ break;
+ case PictOpInReverse:
+ op = PictOpDst;
+ break;
+ case PictOpOutReverse:
+ op = PictOpClear;
+ break;
+ case PictOpAtop:
+ op = PictOpIn;
+ break;
+ case PictOpAtopReverse:
+ op = PictOpOverReverse;
+ break;
+ case PictOpXor:
+ op = PictOpOut;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Deal with simplifications when the destination alpha is always 1 */
+ if (no_dst_alpha)
+ {
+ switch (op) {
+ case PictOpOverReverse:
+ op = PictOpDst;
+ break;
+ case PictOpIn:
+ op = PictOpSrc;
+ break;
+ case PictOpOut:
+ op = PictOpClear;
+ break;
+ case PictOpAtop:
+ op = PictOpOver;
+ break;
+ case PictOpXor:
+ op = PictOpOutReverse;
+ break;
+ default:
+ break;
+ }
+ }
+
+ /* Reduce some con/disjoint ops to the basic names. */
+ switch (op) {
+ case PictOpDisjointClear:
+ case PictOpConjointClear:
+ op = PictOpClear;
+ break;
+ case PictOpDisjointSrc:
+ case PictOpConjointSrc:
+ op = PictOpSrc;
+ break;
+ case PictOpDisjointDst:
+ case PictOpConjointDst:
+ op = PictOpDst;
+ break;
+ default:
+ break;
+ }
+
+ return op;
+}
+
+void
+CompositePicture (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height)
+{
+ PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
+
+ ValidatePicture (pSrc);
+ if (pMask)
+ ValidatePicture (pMask);
+ ValidatePicture (pDst);
+
+ op = ReduceCompositeOp (op, pSrc, pMask, pDst, xSrc, ySrc, width, height);
+ if (op == PictOpDst)
+ return;
+
+ (*ps->Composite) (op,
+ pSrc,
+ pMask,
+ pDst,
+ xSrc,
+ ySrc,
+ xMask,
+ yMask,
+ xDst,
+ yDst,
+ width,
+ height);
+}
+
+void
+CompositeRects (CARD8 op,
+ PicturePtr pDst,
+ xRenderColor *color,
+ int nRect,
+ xRectangle *rects)
+{
+ PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
+
+ ValidatePicture (pDst);
+ (*ps->CompositeRects) (op, pDst, color, nRect, rects);
+}
+
+void
+CompositeTrapezoids (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int ntrap,
+ xTrapezoid *traps)
+{
+ PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
+
+ ValidatePicture (pSrc);
+ ValidatePicture (pDst);
+ (*ps->Trapezoids) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntrap, traps);
+}
+
+void
+CompositeTriangles (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int ntriangles,
+ xTriangle *triangles)
+{
+ PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
+
+ ValidatePicture (pSrc);
+ ValidatePicture (pDst);
+ (*ps->Triangles) (op, pSrc, pDst, maskFormat, xSrc, ySrc, ntriangles, triangles);
+}
+
+void
+CompositeTriStrip (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int npoints,
+ xPointFixed *points)
+{
+ PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
+
+ ValidatePicture (pSrc);
+ ValidatePicture (pDst);
+ (*ps->TriStrip) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
+}
+
+void
+CompositeTriFan (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int npoints,
+ xPointFixed *points)
+{
+ PictureScreenPtr ps = GetPictureScreen(pDst->pDrawable->pScreen);
+
+ ValidatePicture (pSrc);
+ ValidatePicture (pDst);
+ (*ps->TriFan) (op, pSrc, pDst, maskFormat, xSrc, ySrc, npoints, points);
+}
+
+void
+AddTraps (PicturePtr pPicture,
+ INT16 xOff,
+ INT16 yOff,
+ int ntrap,
+ xTrap *traps)
+{
+ PictureScreenPtr ps = GetPictureScreen(pPicture->pDrawable->pScreen);
+
+ ValidatePicture (pPicture);
+ (*ps->AddTraps) (pPicture, xOff, yOff, ntrap, traps);
+}
+
diff --git a/xorg-server/render/picturestr.h b/xorg-server/render/picturestr.h
index 6a8d76d99..6b265d77f 100644
--- a/xorg-server/render/picturestr.h
+++ b/xorg-server/render/picturestr.h
@@ -1,695 +1,695 @@
-/*
- * Copyright © 2000 SuSE, Inc.
- *
- * 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, and that the name of SuSE not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. SuSE makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
- * 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.
- *
- * Author: Keith Packard, SuSE, Inc.
- */
-
-#ifndef _PICTURESTR_H_
-#define _PICTURESTR_H_
-
-#include "scrnintstr.h"
-#include "glyphstr.h"
-#include "resource.h"
-#include "privates.h"
-
-typedef struct _DirectFormat {
- CARD16 red, redMask;
- CARD16 green, greenMask;
- CARD16 blue, blueMask;
- CARD16 alpha, alphaMask;
-} DirectFormatRec;
-
-typedef struct _IndexFormat {
- VisualID vid;
- ColormapPtr pColormap;
- int nvalues;
- xIndexValue *pValues;
- void *devPrivate;
-} IndexFormatRec;
-
-typedef struct _PictFormat {
- CARD32 id;
- CARD32 format; /* except bpp */
- unsigned char type;
- unsigned char depth;
- DirectFormatRec direct;
- IndexFormatRec index;
-} PictFormatRec;
-
-typedef struct pixman_vector PictVector, *PictVectorPtr;
-typedef struct pixman_transform PictTransform, *PictTransformPtr;
-
-#define pict_f_vector pixman_f_vector
-#define pict_f_transform pixman_f_transform
-
-#define PICT_GRADIENT_STOPTABLE_SIZE 1024
-#define SourcePictTypeSolidFill 0
-#define SourcePictTypeLinear 1
-#define SourcePictTypeRadial 2
-#define SourcePictTypeConical 3
-
-#define SourcePictClassUnknown 0
-#define SourcePictClassHorizontal 1
-#define SourcePictClassVertical 2
-
-typedef struct _PictSolidFill {
- unsigned int type;
- unsigned int class;
- CARD32 color;
-} PictSolidFill, *PictSolidFillPtr;
-
-typedef struct _PictGradientStop {
- xFixed x;
- xRenderColor color;
-} PictGradientStop, *PictGradientStopPtr;
-
-typedef struct _PictGradient {
- unsigned int type;
- unsigned int class;
- int nstops;
- PictGradientStopPtr stops;
- int stopRange;
- CARD32 *colorTable;
- int colorTableSize;
-} PictGradient, *PictGradientPtr;
-
-typedef struct _PictLinearGradient {
- unsigned int type;
- unsigned int class;
- int nstops;
- PictGradientStopPtr stops;
- int stopRange;
- CARD32 *colorTable;
- int colorTableSize;
- xPointFixed p1;
- xPointFixed p2;
-} PictLinearGradient, *PictLinearGradientPtr;
-
-typedef struct _PictCircle {
- xFixed x;
- xFixed y;
- xFixed radius;
-} PictCircle, *PictCirclePtr;
-
-typedef struct _PictRadialGradient {
- unsigned int type;
- unsigned int class;
- int nstops;
- PictGradientStopPtr stops;
- int stopRange;
- CARD32 *colorTable;
- int colorTableSize;
- PictCircle c1;
- PictCircle c2;
- double cdx;
- double cdy;
- double dr;
- double A;
-} PictRadialGradient, *PictRadialGradientPtr;
-
-typedef struct _PictConicalGradient {
- unsigned int type;
- unsigned int class;
- int nstops;
- PictGradientStopPtr stops;
- int stopRange;
- CARD32 *colorTable;
- int colorTableSize;
- xPointFixed center;
- xFixed angle;
-} PictConicalGradient, *PictConicalGradientPtr;
-
-typedef union _SourcePict {
- unsigned int type;
- PictSolidFill solidFill;
- PictGradient gradient;
- PictLinearGradient linear;
- PictRadialGradient radial;
- PictConicalGradient conical;
-} SourcePict, *SourcePictPtr;
-
-typedef struct _Picture {
- DrawablePtr pDrawable;
- PictFormatPtr pFormat;
- PictFormatShort format; /* PICT_FORMAT */
- int refcnt;
- CARD32 id;
- PicturePtr pNext; /* chain on same drawable */
-
- unsigned int repeat : 1;
- unsigned int graphicsExposures : 1;
- unsigned int subWindowMode : 1;
- unsigned int polyEdge : 1;
- unsigned int polyMode : 1;
- unsigned int freeCompClip : 1;
- unsigned int clientClipType : 2;
- unsigned int componentAlpha : 1;
- unsigned int repeatType : 2;
- unsigned int unused : 21;
-
- PicturePtr alphaMap;
- DDXPointRec alphaOrigin;
-
- DDXPointRec clipOrigin;
- pointer clientClip;
-
- Atom dither;
-
- unsigned long stateChanges;
- unsigned long serialNumber;
-
- RegionPtr pCompositeClip;
-
- PrivateRec *devPrivates;
-
- PictTransform *transform;
-
- int filter;
- xFixed *filter_params;
- int filter_nparams;
- SourcePictPtr pSourcePict;
-} PictureRec;
-
-typedef Bool (*PictFilterValidateParamsProcPtr) (ScreenPtr pScreen, int id,
- xFixed *params, int nparams,
- int *width, int *height);
-typedef struct {
- char *name;
- int id;
- PictFilterValidateParamsProcPtr ValidateParams;
- int width, height;
-} PictFilterRec, *PictFilterPtr;
-
-#define PictFilterNearest 0
-#define PictFilterBilinear 1
-
-#define PictFilterFast 2
-#define PictFilterGood 3
-#define PictFilterBest 4
-
-#define PictFilterConvolution 5
-
-typedef struct {
- char *alias;
- int alias_id;
- int filter_id;
-} PictFilterAliasRec, *PictFilterAliasPtr;
-
-typedef int (*CreatePictureProcPtr) (PicturePtr pPicture);
-typedef void (*DestroyPictureProcPtr) (PicturePtr pPicture);
-typedef int (*ChangePictureClipProcPtr) (PicturePtr pPicture,
- int clipType,
- pointer value,
- int n);
-typedef void (*DestroyPictureClipProcPtr)(PicturePtr pPicture);
-
-typedef int (*ChangePictureTransformProcPtr) (PicturePtr pPicture,
- PictTransform *transform);
-
-typedef int (*ChangePictureFilterProcPtr) (PicturePtr pPicture,
- int filter,
- xFixed *params,
- int nparams);
-
-typedef void (*DestroyPictureFilterProcPtr) (PicturePtr pPicture);
-
-typedef void (*ChangePictureProcPtr) (PicturePtr pPicture,
- Mask mask);
-typedef void (*ValidatePictureProcPtr) (PicturePtr pPicture,
- Mask mask);
-typedef void (*CompositeProcPtr) (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pMask,
- PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst,
- CARD16 width,
- CARD16 height);
-
-typedef void (*GlyphsProcPtr) (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int nlists,
- GlyphListPtr lists,
- GlyphPtr *glyphs);
-
-typedef void (*CompositeRectsProcPtr) (CARD8 op,
- PicturePtr pDst,
- xRenderColor *color,
- int nRect,
- xRectangle *rects);
-
-typedef void (*RasterizeTrapezoidProcPtr)(PicturePtr pMask,
- xTrapezoid *trap,
- int x_off,
- int y_off);
-
-typedef void (*TrapezoidsProcPtr) (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int ntrap,
- xTrapezoid *traps);
-
-typedef void (*TrianglesProcPtr) (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int ntri,
- xTriangle *tris);
-
-typedef void (*TriStripProcPtr) (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int npoint,
- xPointFixed *points);
-
-typedef void (*TriFanProcPtr) (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int npoint,
- xPointFixed *points);
-
-typedef Bool (*InitIndexedProcPtr) (ScreenPtr pScreen,
- PictFormatPtr pFormat);
-
-typedef void (*CloseIndexedProcPtr) (ScreenPtr pScreen,
- PictFormatPtr pFormat);
-
-typedef void (*UpdateIndexedProcPtr) (ScreenPtr pScreen,
- PictFormatPtr pFormat,
- int ndef,
- xColorItem *pdef);
-
-typedef void (*AddTrapsProcPtr) (PicturePtr pPicture,
- INT16 xOff,
- INT16 yOff,
- int ntrap,
- xTrap *traps);
-
-typedef void (*AddTrianglesProcPtr) (PicturePtr pPicture,
- INT16 xOff,
- INT16 yOff,
- int ntri,
- xTriangle *tris);
-
-typedef Bool (*RealizeGlyphProcPtr) (ScreenPtr pScreen,
- GlyphPtr glyph);
-
-typedef void (*UnrealizeGlyphProcPtr) (ScreenPtr pScreen,
- GlyphPtr glyph);
-
-typedef struct _PictureScreen {
- PictFormatPtr formats;
- PictFormatPtr fallback;
- int nformats;
-
- CreatePictureProcPtr CreatePicture;
- DestroyPictureProcPtr DestroyPicture;
- ChangePictureClipProcPtr ChangePictureClip;
- DestroyPictureClipProcPtr DestroyPictureClip;
-
- ChangePictureProcPtr ChangePicture;
- ValidatePictureProcPtr ValidatePicture;
-
- CompositeProcPtr Composite;
- GlyphsProcPtr Glyphs; /* unused */
- CompositeRectsProcPtr CompositeRects;
-
- DestroyWindowProcPtr DestroyWindow;
- CloseScreenProcPtr CloseScreen;
-
- StoreColorsProcPtr StoreColors;
-
- InitIndexedProcPtr InitIndexed;
- CloseIndexedProcPtr CloseIndexed;
- UpdateIndexedProcPtr UpdateIndexed;
-
- int subpixel;
-
- PictFilterPtr filters;
- int nfilters;
- PictFilterAliasPtr filterAliases;
- int nfilterAliases;
-
- /**
- * Called immediately after a picture's transform is changed through the
- * SetPictureTransform request. Not called for source-only pictures.
- */
- ChangePictureTransformProcPtr ChangePictureTransform;
-
- /**
- * Called immediately after a picture's transform is changed through the
- * SetPictureFilter request. Not called for source-only pictures.
- */
- ChangePictureFilterProcPtr ChangePictureFilter;
-
- DestroyPictureFilterProcPtr DestroyPictureFilter;
-
- TrapezoidsProcPtr Trapezoids;
- TrianglesProcPtr Triangles;
- TriStripProcPtr TriStrip;
- TriFanProcPtr TriFan;
-
- RasterizeTrapezoidProcPtr RasterizeTrapezoid;
-
- AddTrianglesProcPtr AddTriangles;
-
- AddTrapsProcPtr AddTraps;
-
- RealizeGlyphProcPtr RealizeGlyph;
- UnrealizeGlyphProcPtr UnrealizeGlyph;
-
-} PictureScreenRec, *PictureScreenPtr;
-
-extern _X_EXPORT DevPrivateKey PictureScreenPrivateKey;
-extern _X_EXPORT DevPrivateKey PictureWindowPrivateKey;
-extern _X_EXPORT RESTYPE PictureType;
-extern _X_EXPORT RESTYPE PictFormatType;
-extern _X_EXPORT RESTYPE GlyphSetType;
-
-#define GetPictureScreen(s) ((PictureScreenPtr)dixLookupPrivate(&(s)->devPrivates, PictureScreenPrivateKey))
-#define GetPictureScreenIfSet(s) GetPictureScreen(s)
-#define SetPictureScreen(s,p) dixSetPrivate(&(s)->devPrivates, PictureScreenPrivateKey, p)
-#define GetPictureWindow(w) ((PicturePtr)dixLookupPrivate(&(w)->devPrivates, PictureWindowPrivateKey))
-#define SetPictureWindow(w,p) dixSetPrivate(&(w)->devPrivates, PictureWindowPrivateKey, p)
-
-#define VERIFY_PICTURE(pPicture, pid, client, mode, err) {\
- int rc = dixLookupResourceByType((pointer)&(pPicture), pid,\
- PictureType, client, mode);\
- if (rc != Success)\
- return (rc == BadValue) ? err : rc;\
-}
-
-#define VERIFY_ALPHA(pPicture, pid, client, mode, err) {\
- if (pid == None) \
- pPicture = 0; \
- else { \
- VERIFY_PICTURE(pPicture, pid, client, mode, err); \
- } \
-} \
-
-extern _X_EXPORT Bool
-PictureDestroyWindow (WindowPtr pWindow);
-
-extern _X_EXPORT Bool
-PictureCloseScreen (int Index, ScreenPtr pScreen);
-
-extern _X_EXPORT void
-PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef);
-
-extern _X_EXPORT Bool
-PictureInitIndexedFormat (ScreenPtr pScreen, PictFormatPtr format);
-
-extern _X_EXPORT Bool
-PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel);
-
-extern _X_EXPORT int
-PictureGetSubpixelOrder (ScreenPtr pScreen);
-
-extern _X_EXPORT PictFormatPtr
-PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp);
-
-extern _X_EXPORT PictFormatPtr
-PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual);
-
-extern _X_EXPORT PictFormatPtr
-PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 format);
-
-extern _X_EXPORT Bool
-PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats);
-
-extern _X_EXPORT int
-PictureGetFilterId (char *filter, int len, Bool makeit);
-
-extern _X_EXPORT char *
-PictureGetFilterName (int id);
-
-extern _X_EXPORT int
-PictureAddFilter (ScreenPtr pScreen,
- char *filter,
- PictFilterValidateParamsProcPtr ValidateParams,
- int width,
- int height);
-
-extern _X_EXPORT Bool
-PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias);
-
-extern _X_EXPORT Bool
-PictureSetDefaultFilters (ScreenPtr pScreen);
-
-extern _X_EXPORT void
-PictureResetFilters (ScreenPtr pScreen);
-
-extern _X_EXPORT PictFilterPtr
-PictureFindFilter (ScreenPtr pScreen, char *name, int len);
-
-extern _X_EXPORT int
-SetPicturePictFilter (PicturePtr pPicture, PictFilterPtr pFilter,
- xFixed *params, int nparams);
-
-extern _X_EXPORT int
-SetPictureFilter (PicturePtr pPicture, char *name, int len,
- xFixed *params, int nparams);
-
-extern _X_EXPORT Bool
-PictureFinishInit (void);
-
-extern _X_EXPORT void
-SetPictureToDefaults (PicturePtr pPicture);
-
-extern _X_EXPORT PicturePtr
-CreatePicture (Picture pid,
- DrawablePtr pDrawable,
- PictFormatPtr pFormat,
- Mask mask,
- XID *list,
- ClientPtr client,
- int *error);
-
-extern _X_EXPORT int
-ChangePicture (PicturePtr pPicture,
- Mask vmask,
- XID *vlist,
- DevUnion *ulist,
- ClientPtr client);
-
-extern _X_EXPORT int
-SetPictureClipRects (PicturePtr pPicture,
- int xOrigin,
- int yOrigin,
- int nRect,
- xRectangle *rects);
-
-extern _X_EXPORT int
-SetPictureClipRegion (PicturePtr pPicture,
- int xOrigin,
- int yOrigin,
- RegionPtr pRegion);
-
-extern _X_EXPORT int
-SetPictureTransform (PicturePtr pPicture,
- PictTransform *transform);
-
-extern _X_EXPORT void
-CopyPicture (PicturePtr pSrc,
- Mask mask,
- PicturePtr pDst);
-
-extern _X_EXPORT void
-ValidatePicture(PicturePtr pPicture);
-
-extern _X_EXPORT int
-FreePicture (pointer pPicture,
- XID pid);
-
-extern _X_EXPORT int
-FreePictFormat (pointer pPictFormat,
- XID pid);
-
-extern _X_EXPORT void
-CompositePicture (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pMask,
- PicturePtr pDst,
- INT16 xSrc,
- INT16 ySrc,
- INT16 xMask,
- INT16 yMask,
- INT16 xDst,
- INT16 yDst,
- CARD16 width,
- CARD16 height);
-
-extern _X_EXPORT void
-CompositeGlyphs (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int nlist,
- GlyphListPtr lists,
- GlyphPtr *glyphs);
-
-extern _X_EXPORT void
-CompositeRects (CARD8 op,
- PicturePtr pDst,
- xRenderColor *color,
- int nRect,
- xRectangle *rects);
-
-extern _X_EXPORT void
-CompositeTrapezoids (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int ntrap,
- xTrapezoid *traps);
-
-extern _X_EXPORT void
-CompositeTriangles (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int ntriangles,
- xTriangle *triangles);
-
-extern _X_EXPORT void
-CompositeTriStrip (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int npoints,
- xPointFixed *points);
-
-extern _X_EXPORT void
-CompositeTriFan (CARD8 op,
- PicturePtr pSrc,
- PicturePtr pDst,
- PictFormatPtr maskFormat,
- INT16 xSrc,
- INT16 ySrc,
- int npoints,
- xPointFixed *points);
-
-extern _X_EXPORT CARD32
-PictureGradientColor (PictGradientStopPtr stop1,
- PictGradientStopPtr stop2,
- CARD32 x);
-
-extern _X_EXPORT void RenderExtensionInit (void);
-
-Bool
-AnimCurInit (ScreenPtr pScreen);
-
-int
-AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor, ClientPtr client, XID cid);
-
-extern _X_EXPORT void
-AddTraps (PicturePtr pPicture,
- INT16 xOff,
- INT16 yOff,
- int ntraps,
- xTrap *traps);
-
-extern _X_EXPORT PicturePtr
-CreateSolidPicture (Picture pid,
- xRenderColor *color,
- int *error);
-
-extern _X_EXPORT PicturePtr
-CreateLinearGradientPicture (Picture pid,
- xPointFixed *p1,
- xPointFixed *p2,
- int nStops,
- xFixed *stops,
- xRenderColor *colors,
- int *error);
-
-extern _X_EXPORT PicturePtr
-CreateRadialGradientPicture (Picture pid,
- xPointFixed *inner,
- xPointFixed *outer,
- xFixed innerRadius,
- xFixed outerRadius,
- int nStops,
- xFixed *stops,
- xRenderColor *colors,
- int *error);
-
-extern _X_EXPORT PicturePtr
-CreateConicalGradientPicture (Picture pid,
- xPointFixed *center,
- xFixed angle,
- int nStops,
- xFixed *stops,
- xRenderColor *colors,
- int *error);
-
-#ifdef PANORAMIX
-extern _X_EXPORT void PanoramiXRenderInit (void);
-extern _X_EXPORT void PanoramiXRenderReset (void);
-#endif
-
-/*
- * matrix.c
- */
-
-extern _X_EXPORT void
-PictTransform_from_xRenderTransform (PictTransformPtr pict,
- xRenderTransform *render);
-
-extern _X_EXPORT void
-xRenderTransform_from_PictTransform (xRenderTransform *render,
- PictTransformPtr pict);
-
-extern _X_EXPORT Bool
-PictureTransformPoint (PictTransformPtr transform,
- PictVectorPtr vector);
-
-extern _X_EXPORT Bool
-PictureTransformPoint3d (PictTransformPtr transform,
- PictVectorPtr vector);
-
-#endif /* _PICTURESTR_H_ */
+/*
+ * Copyright © 2000 SuSE, Inc.
+ *
+ * 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, and that the name of SuSE not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. SuSE makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
+ * 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.
+ *
+ * Author: Keith Packard, SuSE, Inc.
+ */
+
+#ifndef _PICTURESTR_H_
+#define _PICTURESTR_H_
+
+#include "scrnintstr.h"
+#include "glyphstr.h"
+#include "resource.h"
+#include "privates.h"
+
+typedef struct _DirectFormat {
+ CARD16 red, redMask;
+ CARD16 green, greenMask;
+ CARD16 blue, blueMask;
+ CARD16 alpha, alphaMask;
+} DirectFormatRec;
+
+typedef struct _IndexFormat {
+ VisualID vid;
+ ColormapPtr pColormap;
+ int nvalues;
+ xIndexValue *pValues;
+ void *devPrivate;
+} IndexFormatRec;
+
+typedef struct _PictFormat {
+ CARD32 id;
+ CARD32 format; /* except bpp */
+ unsigned char type;
+ unsigned char depth;
+ DirectFormatRec direct;
+ IndexFormatRec index;
+} PictFormatRec;
+
+typedef struct pixman_vector PictVector, *PictVectorPtr;
+typedef struct pixman_transform PictTransform, *PictTransformPtr;
+
+#define pict_f_vector pixman_f_vector
+#define pict_f_transform pixman_f_transform
+
+#define PICT_GRADIENT_STOPTABLE_SIZE 1024
+#define SourcePictTypeSolidFill 0
+#define SourcePictTypeLinear 1
+#define SourcePictTypeRadial 2
+#define SourcePictTypeConical 3
+
+#define SourcePictClassUnknown 0
+#define SourcePictClassHorizontal 1
+#define SourcePictClassVertical 2
+
+typedef struct _PictSolidFill {
+ unsigned int type;
+ unsigned int class;
+ CARD32 color;
+} PictSolidFill, *PictSolidFillPtr;
+
+typedef struct _PictGradientStop {
+ xFixed x;
+ xRenderColor color;
+} PictGradientStop, *PictGradientStopPtr;
+
+typedef struct _PictGradient {
+ unsigned int type;
+ unsigned int class;
+ int nstops;
+ PictGradientStopPtr stops;
+ int stopRange;
+ CARD32 *colorTable;
+ int colorTableSize;
+} PictGradient, *PictGradientPtr;
+
+typedef struct _PictLinearGradient {
+ unsigned int type;
+ unsigned int class;
+ int nstops;
+ PictGradientStopPtr stops;
+ int stopRange;
+ CARD32 *colorTable;
+ int colorTableSize;
+ xPointFixed p1;
+ xPointFixed p2;
+} PictLinearGradient, *PictLinearGradientPtr;
+
+typedef struct _PictCircle {
+ xFixed x;
+ xFixed y;
+ xFixed radius;
+} PictCircle, *PictCirclePtr;
+
+typedef struct _PictRadialGradient {
+ unsigned int type;
+ unsigned int class;
+ int nstops;
+ PictGradientStopPtr stops;
+ int stopRange;
+ CARD32 *colorTable;
+ int colorTableSize;
+ PictCircle c1;
+ PictCircle c2;
+ double cdx;
+ double cdy;
+ double dr;
+ double A;
+} PictRadialGradient, *PictRadialGradientPtr;
+
+typedef struct _PictConicalGradient {
+ unsigned int type;
+ unsigned int class;
+ int nstops;
+ PictGradientStopPtr stops;
+ int stopRange;
+ CARD32 *colorTable;
+ int colorTableSize;
+ xPointFixed center;
+ xFixed angle;
+} PictConicalGradient, *PictConicalGradientPtr;
+
+typedef union _SourcePict {
+ unsigned int type;
+ PictSolidFill solidFill;
+ PictGradient gradient;
+ PictLinearGradient linear;
+ PictRadialGradient radial;
+ PictConicalGradient conical;
+} SourcePict, *SourcePictPtr;
+
+typedef struct _Picture {
+ DrawablePtr pDrawable;
+ PictFormatPtr pFormat;
+ PictFormatShort format; /* PICT_FORMAT */
+ int refcnt;
+ CARD32 id;
+ PicturePtr pNext; /* chain on same drawable */
+
+ unsigned int repeat : 1;
+ unsigned int graphicsExposures : 1;
+ unsigned int subWindowMode : 1;
+ unsigned int polyEdge : 1;
+ unsigned int polyMode : 1;
+ unsigned int freeCompClip : 1;
+ unsigned int clientClipType : 2;
+ unsigned int componentAlpha : 1;
+ unsigned int repeatType : 2;
+ unsigned int unused : 21;
+
+ PicturePtr alphaMap;
+ DDXPointRec alphaOrigin;
+
+ DDXPointRec clipOrigin;
+ pointer clientClip;
+
+ Atom dither;
+
+ unsigned long stateChanges;
+ unsigned long serialNumber;
+
+ RegionPtr pCompositeClip;
+
+ PrivateRec *devPrivates;
+
+ PictTransform *transform;
+
+ int filter;
+ xFixed *filter_params;
+ int filter_nparams;
+ SourcePictPtr pSourcePict;
+} PictureRec;
+
+typedef Bool (*PictFilterValidateParamsProcPtr) (ScreenPtr pScreen, int id,
+ xFixed *params, int nparams,
+ int *width, int *height);
+typedef struct {
+ char *name;
+ int id;
+ PictFilterValidateParamsProcPtr ValidateParams;
+ int width, height;
+} PictFilterRec, *PictFilterPtr;
+
+#define PictFilterNearest 0
+#define PictFilterBilinear 1
+
+#define PictFilterFast 2
+#define PictFilterGood 3
+#define PictFilterBest 4
+
+#define PictFilterConvolution 5
+
+typedef struct {
+ char *alias;
+ int alias_id;
+ int filter_id;
+} PictFilterAliasRec, *PictFilterAliasPtr;
+
+typedef int (*CreatePictureProcPtr) (PicturePtr pPicture);
+typedef void (*DestroyPictureProcPtr) (PicturePtr pPicture);
+typedef int (*ChangePictureClipProcPtr) (PicturePtr pPicture,
+ int clipType,
+ pointer value,
+ int n);
+typedef void (*DestroyPictureClipProcPtr)(PicturePtr pPicture);
+
+typedef int (*ChangePictureTransformProcPtr) (PicturePtr pPicture,
+ PictTransform *transform);
+
+typedef int (*ChangePictureFilterProcPtr) (PicturePtr pPicture,
+ int filter,
+ xFixed *params,
+ int nparams);
+
+typedef void (*DestroyPictureFilterProcPtr) (PicturePtr pPicture);
+
+typedef void (*ChangePictureProcPtr) (PicturePtr pPicture,
+ Mask mask);
+typedef void (*ValidatePictureProcPtr) (PicturePtr pPicture,
+ Mask mask);
+typedef void (*CompositeProcPtr) (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+
+typedef void (*GlyphsProcPtr) (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int nlists,
+ GlyphListPtr lists,
+ GlyphPtr *glyphs);
+
+typedef void (*CompositeRectsProcPtr) (CARD8 op,
+ PicturePtr pDst,
+ xRenderColor *color,
+ int nRect,
+ xRectangle *rects);
+
+typedef void (*RasterizeTrapezoidProcPtr)(PicturePtr pMask,
+ xTrapezoid *trap,
+ int x_off,
+ int y_off);
+
+typedef void (*TrapezoidsProcPtr) (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int ntrap,
+ xTrapezoid *traps);
+
+typedef void (*TrianglesProcPtr) (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int ntri,
+ xTriangle *tris);
+
+typedef void (*TriStripProcPtr) (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int npoint,
+ xPointFixed *points);
+
+typedef void (*TriFanProcPtr) (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int npoint,
+ xPointFixed *points);
+
+typedef Bool (*InitIndexedProcPtr) (ScreenPtr pScreen,
+ PictFormatPtr pFormat);
+
+typedef void (*CloseIndexedProcPtr) (ScreenPtr pScreen,
+ PictFormatPtr pFormat);
+
+typedef void (*UpdateIndexedProcPtr) (ScreenPtr pScreen,
+ PictFormatPtr pFormat,
+ int ndef,
+ xColorItem *pdef);
+
+typedef void (*AddTrapsProcPtr) (PicturePtr pPicture,
+ INT16 xOff,
+ INT16 yOff,
+ int ntrap,
+ xTrap *traps);
+
+typedef void (*AddTrianglesProcPtr) (PicturePtr pPicture,
+ INT16 xOff,
+ INT16 yOff,
+ int ntri,
+ xTriangle *tris);
+
+typedef Bool (*RealizeGlyphProcPtr) (ScreenPtr pScreen,
+ GlyphPtr glyph);
+
+typedef void (*UnrealizeGlyphProcPtr) (ScreenPtr pScreen,
+ GlyphPtr glyph);
+
+typedef struct _PictureScreen {
+ PictFormatPtr formats;
+ PictFormatPtr fallback;
+ int nformats;
+
+ CreatePictureProcPtr CreatePicture;
+ DestroyPictureProcPtr DestroyPicture;
+ ChangePictureClipProcPtr ChangePictureClip;
+ DestroyPictureClipProcPtr DestroyPictureClip;
+
+ ChangePictureProcPtr ChangePicture;
+ ValidatePictureProcPtr ValidatePicture;
+
+ CompositeProcPtr Composite;
+ GlyphsProcPtr Glyphs; /* unused */
+ CompositeRectsProcPtr CompositeRects;
+
+ DestroyWindowProcPtr DestroyWindow;
+ CloseScreenProcPtr CloseScreen;
+
+ StoreColorsProcPtr StoreColors;
+
+ InitIndexedProcPtr InitIndexed;
+ CloseIndexedProcPtr CloseIndexed;
+ UpdateIndexedProcPtr UpdateIndexed;
+
+ int subpixel;
+
+ PictFilterPtr filters;
+ int nfilters;
+ PictFilterAliasPtr filterAliases;
+ int nfilterAliases;
+
+ /**
+ * Called immediately after a picture's transform is changed through the
+ * SetPictureTransform request. Not called for source-only pictures.
+ */
+ ChangePictureTransformProcPtr ChangePictureTransform;
+
+ /**
+ * Called immediately after a picture's transform is changed through the
+ * SetPictureFilter request. Not called for source-only pictures.
+ */
+ ChangePictureFilterProcPtr ChangePictureFilter;
+
+ DestroyPictureFilterProcPtr DestroyPictureFilter;
+
+ TrapezoidsProcPtr Trapezoids;
+ TrianglesProcPtr Triangles;
+ TriStripProcPtr TriStrip;
+ TriFanProcPtr TriFan;
+
+ RasterizeTrapezoidProcPtr RasterizeTrapezoid;
+
+ AddTrianglesProcPtr AddTriangles;
+
+ AddTrapsProcPtr AddTraps;
+
+ RealizeGlyphProcPtr RealizeGlyph;
+ UnrealizeGlyphProcPtr UnrealizeGlyph;
+
+} PictureScreenRec, *PictureScreenPtr;
+
+extern _X_EXPORT DevPrivateKey PictureScreenPrivateKey;
+extern _X_EXPORT DevPrivateKey PictureWindowPrivateKey;
+extern _X_EXPORT RESTYPE PictureType;
+extern _X_EXPORT RESTYPE PictFormatType;
+extern _X_EXPORT RESTYPE GlyphSetType;
+
+#define GetPictureScreen(s) ((PictureScreenPtr)dixLookupPrivate(&(s)->devPrivates, PictureScreenPrivateKey))
+#define GetPictureScreenIfSet(s) GetPictureScreen(s)
+#define SetPictureScreen(s,p) dixSetPrivate(&(s)->devPrivates, PictureScreenPrivateKey, p)
+#define GetPictureWindow(w) ((PicturePtr)dixLookupPrivate(&(w)->devPrivates, PictureWindowPrivateKey))
+#define SetPictureWindow(w,p) dixSetPrivate(&(w)->devPrivates, PictureWindowPrivateKey, p)
+
+#define VERIFY_PICTURE(pPicture, pid, client, mode) {\
+ int rc = dixLookupResourceByType((pointer)&(pPicture), pid,\
+ PictureType, client, mode);\
+ if (rc != Success)\
+ return (rc == BadValue) ? RenderErrBase + BadPicture : rc;\
+}
+
+#define VERIFY_ALPHA(pPicture, pid, client, mode) {\
+ if (pid == None) \
+ pPicture = 0; \
+ else { \
+ VERIFY_PICTURE(pPicture, pid, client, mode); \
+ } \
+} \
+
+extern _X_EXPORT Bool
+PictureDestroyWindow (WindowPtr pWindow);
+
+extern _X_EXPORT Bool
+PictureCloseScreen (int Index, ScreenPtr pScreen);
+
+extern _X_EXPORT void
+PictureStoreColors (ColormapPtr pColormap, int ndef, xColorItem *pdef);
+
+extern _X_EXPORT Bool
+PictureInitIndexedFormat (ScreenPtr pScreen, PictFormatPtr format);
+
+extern _X_EXPORT Bool
+PictureSetSubpixelOrder (ScreenPtr pScreen, int subpixel);
+
+extern _X_EXPORT int
+PictureGetSubpixelOrder (ScreenPtr pScreen);
+
+extern _X_EXPORT PictFormatPtr
+PictureCreateDefaultFormats (ScreenPtr pScreen, int *nformatp);
+
+extern _X_EXPORT PictFormatPtr
+PictureMatchVisual (ScreenPtr pScreen, int depth, VisualPtr pVisual);
+
+extern _X_EXPORT PictFormatPtr
+PictureMatchFormat (ScreenPtr pScreen, int depth, CARD32 format);
+
+extern _X_EXPORT Bool
+PictureInit (ScreenPtr pScreen, PictFormatPtr formats, int nformats);
+
+extern _X_EXPORT int
+PictureGetFilterId (char *filter, int len, Bool makeit);
+
+extern _X_EXPORT char *
+PictureGetFilterName (int id);
+
+extern _X_EXPORT int
+PictureAddFilter (ScreenPtr pScreen,
+ char *filter,
+ PictFilterValidateParamsProcPtr ValidateParams,
+ int width,
+ int height);
+
+extern _X_EXPORT Bool
+PictureSetFilterAlias (ScreenPtr pScreen, char *filter, char *alias);
+
+extern _X_EXPORT Bool
+PictureSetDefaultFilters (ScreenPtr pScreen);
+
+extern _X_EXPORT void
+PictureResetFilters (ScreenPtr pScreen);
+
+extern _X_EXPORT PictFilterPtr
+PictureFindFilter (ScreenPtr pScreen, char *name, int len);
+
+extern _X_EXPORT int
+SetPicturePictFilter (PicturePtr pPicture, PictFilterPtr pFilter,
+ xFixed *params, int nparams);
+
+extern _X_EXPORT int
+SetPictureFilter (PicturePtr pPicture, char *name, int len,
+ xFixed *params, int nparams);
+
+extern _X_EXPORT Bool
+PictureFinishInit (void);
+
+extern _X_EXPORT void
+SetPictureToDefaults (PicturePtr pPicture);
+
+extern _X_EXPORT PicturePtr
+CreatePicture (Picture pid,
+ DrawablePtr pDrawable,
+ PictFormatPtr pFormat,
+ Mask mask,
+ XID *list,
+ ClientPtr client,
+ int *error);
+
+extern _X_EXPORT int
+ChangePicture (PicturePtr pPicture,
+ Mask vmask,
+ XID *vlist,
+ DevUnion *ulist,
+ ClientPtr client);
+
+extern _X_EXPORT int
+SetPictureClipRects (PicturePtr pPicture,
+ int xOrigin,
+ int yOrigin,
+ int nRect,
+ xRectangle *rects);
+
+extern _X_EXPORT int
+SetPictureClipRegion (PicturePtr pPicture,
+ int xOrigin,
+ int yOrigin,
+ RegionPtr pRegion);
+
+extern _X_EXPORT int
+SetPictureTransform (PicturePtr pPicture,
+ PictTransform *transform);
+
+extern _X_EXPORT void
+CopyPicture (PicturePtr pSrc,
+ Mask mask,
+ PicturePtr pDst);
+
+extern _X_EXPORT void
+ValidatePicture(PicturePtr pPicture);
+
+extern _X_EXPORT int
+FreePicture (pointer pPicture,
+ XID pid);
+
+extern _X_EXPORT int
+FreePictFormat (pointer pPictFormat,
+ XID pid);
+
+extern _X_EXPORT void
+CompositePicture (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pMask,
+ PicturePtr pDst,
+ INT16 xSrc,
+ INT16 ySrc,
+ INT16 xMask,
+ INT16 yMask,
+ INT16 xDst,
+ INT16 yDst,
+ CARD16 width,
+ CARD16 height);
+
+extern _X_EXPORT void
+CompositeGlyphs (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int nlist,
+ GlyphListPtr lists,
+ GlyphPtr *glyphs);
+
+extern _X_EXPORT void
+CompositeRects (CARD8 op,
+ PicturePtr pDst,
+ xRenderColor *color,
+ int nRect,
+ xRectangle *rects);
+
+extern _X_EXPORT void
+CompositeTrapezoids (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int ntrap,
+ xTrapezoid *traps);
+
+extern _X_EXPORT void
+CompositeTriangles (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int ntriangles,
+ xTriangle *triangles);
+
+extern _X_EXPORT void
+CompositeTriStrip (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int npoints,
+ xPointFixed *points);
+
+extern _X_EXPORT void
+CompositeTriFan (CARD8 op,
+ PicturePtr pSrc,
+ PicturePtr pDst,
+ PictFormatPtr maskFormat,
+ INT16 xSrc,
+ INT16 ySrc,
+ int npoints,
+ xPointFixed *points);
+
+extern _X_EXPORT CARD32
+PictureGradientColor (PictGradientStopPtr stop1,
+ PictGradientStopPtr stop2,
+ CARD32 x);
+
+extern _X_EXPORT void RenderExtensionInit (void);
+
+Bool
+AnimCurInit (ScreenPtr pScreen);
+
+int
+AnimCursorCreate (CursorPtr *cursors, CARD32 *deltas, int ncursor, CursorPtr *ppCursor, ClientPtr client, XID cid);
+
+extern _X_EXPORT void
+AddTraps (PicturePtr pPicture,
+ INT16 xOff,
+ INT16 yOff,
+ int ntraps,
+ xTrap *traps);
+
+extern _X_EXPORT PicturePtr
+CreateSolidPicture (Picture pid,
+ xRenderColor *color,
+ int *error);
+
+extern _X_EXPORT PicturePtr
+CreateLinearGradientPicture (Picture pid,
+ xPointFixed *p1,
+ xPointFixed *p2,
+ int nStops,
+ xFixed *stops,
+ xRenderColor *colors,
+ int *error);
+
+extern _X_EXPORT PicturePtr
+CreateRadialGradientPicture (Picture pid,
+ xPointFixed *inner,
+ xPointFixed *outer,
+ xFixed innerRadius,
+ xFixed outerRadius,
+ int nStops,
+ xFixed *stops,
+ xRenderColor *colors,
+ int *error);
+
+extern _X_EXPORT PicturePtr
+CreateConicalGradientPicture (Picture pid,
+ xPointFixed *center,
+ xFixed angle,
+ int nStops,
+ xFixed *stops,
+ xRenderColor *colors,
+ int *error);
+
+#ifdef PANORAMIX
+extern _X_EXPORT void PanoramiXRenderInit (void);
+extern _X_EXPORT void PanoramiXRenderReset (void);
+#endif
+
+/*
+ * matrix.c
+ */
+
+extern _X_EXPORT void
+PictTransform_from_xRenderTransform (PictTransformPtr pict,
+ xRenderTransform *render);
+
+extern _X_EXPORT void
+xRenderTransform_from_PictTransform (xRenderTransform *render,
+ PictTransformPtr pict);
+
+extern _X_EXPORT Bool
+PictureTransformPoint (PictTransformPtr transform,
+ PictVectorPtr vector);
+
+extern _X_EXPORT Bool
+PictureTransformPoint3d (PictTransformPtr transform,
+ PictVectorPtr vector);
+
+#endif /* _PICTURESTR_H_ */
diff --git a/xorg-server/render/render.c b/xorg-server/render/render.c
index 7f3c10a93..9ccbf3937 100644
--- a/xorg-server/render/render.c
+++ b/xorg-server/render/render.c
@@ -631,8 +631,7 @@ ProcRenderChangePicture (ClientPtr client)
int len;
REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
- VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess);
len = client->req_len - bytes_to_int32(sizeof(xRenderChangePictureReq));
if (Ones(stuff->mask) != len)
@@ -651,8 +650,7 @@ ProcRenderSetPictureClipRectangles (ClientPtr client)
int result;
REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
- VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess);
if (!pPicture->pDrawable)
return BadDrawable;
@@ -677,8 +675,7 @@ ProcRenderFreePicture (ClientPtr client)
REQUEST_SIZE_MATCH(xRenderFreePictureReq);
- VERIFY_PICTURE (pPicture, stuff->picture, client, DixDestroyAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pPicture, stuff->picture, client, DixDestroyAccess);
FreeResource (stuff->picture, RT_NONE);
return(client->noClientException);
}
@@ -709,14 +706,11 @@ ProcRenderComposite (ClientPtr client)
client->errorValue = stuff->op;
return BadValue;
}
- VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess);
if (!pDst->pDrawable)
return BadDrawable;
- VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_ALPHA (pMask, stuff->mask, client, DixReadAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess);
+ VERIFY_ALPHA (pMask, stuff->mask, client, DixReadAccess);
if ((pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen) ||
(pMask && pMask->pDrawable && pDst->pDrawable->pScreen != pMask->pDrawable->pScreen))
return BadMatch;
@@ -755,10 +749,8 @@ ProcRenderTrapezoids (ClientPtr client)
client->errorValue = stuff->op;
return BadValue;
}
- VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess);
+ VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess);
if (!pDst->pDrawable)
return BadDrawable;
if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
@@ -797,10 +789,8 @@ ProcRenderTriangles (ClientPtr client)
client->errorValue = stuff->op;
return BadValue;
}
- VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess);
+ VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess);
if (!pDst->pDrawable)
return BadDrawable;
if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
@@ -839,10 +829,8 @@ ProcRenderTriStrip (ClientPtr client)
client->errorValue = stuff->op;
return BadValue;
}
- VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess);
+ VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess);
if (!pDst->pDrawable)
return BadDrawable;
if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
@@ -881,10 +869,8 @@ ProcRenderTriFan (ClientPtr client)
client->errorValue = stuff->op;
return BadValue;
}
- VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess);
+ VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess);
if (!pDst->pDrawable)
return BadDrawable;
if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
@@ -1301,10 +1287,8 @@ ProcRenderCompositeGlyphs (ClientPtr client)
client->errorValue = stuff->op;
return BadValue;
}
- VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess);
+ VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess);
if (!pDst->pDrawable)
return BadDrawable;
if (pSrc->pDrawable && pSrc->pDrawable->pScreen != pDst->pDrawable->pScreen)
@@ -1458,8 +1442,7 @@ ProcRenderFillRectangles (ClientPtr client)
client->errorValue = stuff->op;
return BadValue;
}
- VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pDst, stuff->dst, client, DixWriteAccess);
if (!pDst->pDrawable)
return BadDrawable;
@@ -1524,8 +1507,7 @@ ProcRenderCreateCursor (ClientPtr client)
REQUEST_SIZE_MATCH (xRenderCreateCursorReq);
LEGAL_NEW_RESOURCE(stuff->cid, client);
- VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pSrc, stuff->src, client, DixReadAccess);
if (!pSrc->pDrawable)
return BadDrawable;
pScreen = pSrc->pDrawable->pScreen;
@@ -1711,8 +1693,7 @@ ProcRenderSetPictureTransform (ClientPtr client)
int result;
REQUEST_SIZE_MATCH(xRenderSetPictureTransformReq);
- VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess);
result = SetPictureTransform (pPicture, (PictTransform *) &stuff->transform);
if (client->noClientException != Success)
return(client->noClientException);
@@ -1841,8 +1822,7 @@ ProcRenderSetPictureFilter (ClientPtr client)
char *name;
REQUEST_AT_LEAST_SIZE (xRenderSetPictureFilterReq);
- VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pPicture, stuff->picture, client, DixSetAttrAccess);
name = (char *) (stuff + 1);
params = (xFixed *) (name + pad_to_int32(stuff->nbytes));
nparams = ((xFixed *) stuff + client->req_len) - params;
@@ -1903,8 +1883,7 @@ ProcRenderAddTraps (ClientPtr client)
REQUEST(xRenderAddTrapsReq);
REQUEST_AT_LEAST_SIZE(xRenderAddTrapsReq);
- VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_PICTURE (pPicture, stuff->picture, client, DixWriteAccess);
if (!pPicture->pDrawable)
return BadDrawable;
ntraps = (client->req_len << 2) - sizeof (xRenderAddTrapsReq);
@@ -2659,18 +2638,18 @@ SProcRenderDispatch (ClientPtr client)
#include "panoramiX.h"
#include "panoramiXsrv.h"
-#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err) {\
+#define VERIFY_XIN_PICTURE(pPicture, pid, client, mode) {\
int rc = dixLookupResourceByType((pointer *)&(pPicture), pid,\
XRT_PICTURE, client, mode);\
if (rc != Success)\
- return (rc == BadValue) ? err : rc;\
+ return (rc == BadValue) ? RenderErrBase + BadPicture : rc;\
}
-#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode, err) {\
+#define VERIFY_XIN_ALPHA(pPicture, pid, client, mode) {\
if (pid == None) \
pPicture = 0; \
else { \
- VERIFY_XIN_PICTURE(pPicture, pid, client, mode, err); \
+ VERIFY_XIN_PICTURE(pPicture, pid, client, mode); \
} \
} \
@@ -2730,8 +2709,7 @@ PanoramiXRenderChangePicture (ClientPtr client)
REQUEST_AT_LEAST_SIZE(xRenderChangePictureReq);
- VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
FOR_NSCREENS_BACKWARD(j) {
stuff->picture = pict->info[j].id;
@@ -2751,8 +2729,7 @@ PanoramiXRenderSetPictureClipRectangles (ClientPtr client)
REQUEST_AT_LEAST_SIZE(xRenderSetPictureClipRectanglesReq);
- VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
FOR_NSCREENS_BACKWARD(j) {
stuff->picture = pict->info[j].id;
@@ -2772,8 +2749,7 @@ PanoramiXRenderSetPictureTransform (ClientPtr client)
REQUEST_AT_LEAST_SIZE(xRenderSetPictureTransformReq);
- VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
FOR_NSCREENS_BACKWARD(j) {
stuff->picture = pict->info[j].id;
@@ -2793,8 +2769,7 @@ PanoramiXRenderSetPictureFilter (ClientPtr client)
REQUEST_AT_LEAST_SIZE(xRenderSetPictureFilterReq);
- VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixWriteAccess);
FOR_NSCREENS_BACKWARD(j) {
stuff->picture = pict->info[j].id;
@@ -2816,8 +2791,7 @@ PanoramiXRenderFreePicture (ClientPtr client)
client->errorValue = stuff->picture;
- VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixDestroyAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE(pict, stuff->picture, client, DixDestroyAccess);
FOR_NSCREENS_BACKWARD(j) {
@@ -2842,12 +2816,9 @@ PanoramiXRenderComposite (ClientPtr client)
REQUEST_SIZE_MATCH(xRenderCompositeReq);
- VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_XIN_ALPHA (msk, stuff->mask, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess);
+ VERIFY_XIN_ALPHA (msk, stuff->mask, client, DixReadAccess);
+ VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess);
orig = *stuff;
@@ -2890,10 +2861,8 @@ PanoramiXRenderCompositeGlyphs (ClientPtr client)
INT16 xSrc, ySrc;
REQUEST_AT_LEAST_SIZE(xRenderCompositeGlyphsReq);
- VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess);
+ VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess);
if (client->req_len << 2 >= (sizeof (xRenderCompositeGlyphsReq) +
sizeof (xGlyphElt)))
@@ -2933,8 +2902,7 @@ PanoramiXRenderFillRectangles (ClientPtr client)
int extra_len;
REQUEST_AT_LEAST_SIZE (xRenderFillRectanglesReq);
- VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess);
extra_len = (client->req_len << 2) - sizeof (xRenderFillRectanglesReq);
if (extra_len &&
(extra = (char *) xalloc (extra_len)))
@@ -2980,10 +2948,8 @@ PanoramiXRenderTrapezoids(ClientPtr client)
REQUEST_AT_LEAST_SIZE (xRenderTrapezoidsReq);
- VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess);
+ VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess);
extra_len = (client->req_len << 2) - sizeof (xRenderTrapezoidsReq);
@@ -3042,10 +3008,8 @@ PanoramiXRenderTriangles(ClientPtr client)
REQUEST_AT_LEAST_SIZE (xRenderTrianglesReq);
- VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess);
+ VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess);
extra_len = (client->req_len << 2) - sizeof (xRenderTrianglesReq);
@@ -3100,10 +3064,8 @@ PanoramiXRenderTriStrip(ClientPtr client)
REQUEST_AT_LEAST_SIZE (xRenderTriStripReq);
- VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess);
+ VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess);
extra_len = (client->req_len << 2) - sizeof (xRenderTriStripReq);
@@ -3154,10 +3116,8 @@ PanoramiXRenderTriFan(ClientPtr client)
REQUEST_AT_LEAST_SIZE (xRenderTriFanReq);
- VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess,
- RenderErrBase + BadPicture);
- VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE (src, stuff->src, client, DixReadAccess);
+ VERIFY_XIN_PICTURE (dst, stuff->dst, client, DixWriteAccess);
extra_len = (client->req_len << 2) - sizeof (xRenderTriFanReq);
@@ -3208,8 +3168,7 @@ PanoramiXRenderAddTraps (ClientPtr client)
INT16 x_off, y_off;
REQUEST_AT_LEAST_SIZE (xRenderAddTrapsReq);
- VERIFY_XIN_PICTURE (picture, stuff->picture, client, DixWriteAccess,
- RenderErrBase + BadPicture);
+ VERIFY_XIN_PICTURE (picture, stuff->picture, client, DixWriteAccess);
extra_len = (client->req_len << 2) - sizeof (xRenderAddTrapsReq);
if (extra_len &&
(extra = (char *) xalloc (extra_len)))
diff --git a/xorg-server/xfixes/region.c b/xorg-server/xfixes/region.c
index 795caf013..dc050c9fc 100644
--- a/xorg-server/xfixes/region.c
+++ b/xorg-server/xfixes/region.c
@@ -1,857 +1,855 @@
-/*
- * Copyright © 2003 Keith Packard
- *
- * 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, and that the name of Keith Packard not be used in
- * advertising or publicity pertaining to distribution of the software without
- * specific, written prior permission. Keith Packard makes no
- * representations about the suitability of this software for any purpose. It
- * is provided "as is" without express or implied warranty.
- *
- * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
- * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
- * EVENT SHALL KEITH PACKARD 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 "xfixesint.h"
-#include "scrnintstr.h"
-#include <picturestr.h>
-extern int RenderErrBase;
-#include <regionstr.h>
-#include <gcstruct.h>
-#include <window.h>
-
-RESTYPE RegionResType;
-
-static int
-RegionResFree (pointer data, XID id)
-{
- RegionPtr pRegion = (RegionPtr) data;
-
- REGION_DESTROY (0, pRegion);
- return Success;
-}
-
-RegionPtr
-XFixesRegionCopy (RegionPtr pRegion)
-{
- RegionPtr pNew = REGION_CREATE (0, REGION_EXTENTS(0, pRegion),
- REGION_NUM_RECTS(pRegion));
- if (!pNew)
- return 0;
- if (!REGION_COPY (0, pNew, pRegion))
- {
- REGION_DESTROY (0, pNew);
- return 0;
- }
- return pNew;
-}
-
-Bool
-XFixesRegionInit (void)
-{
- RegionResType = CreateNewResourceType(RegionResFree, "XFixesRegion");
-
- return (RegionResType != 0);
-}
-
-int
-ProcXFixesCreateRegion (ClientPtr client)
-{
- int things;
- RegionPtr pRegion;
- REQUEST (xXFixesCreateRegionReq);
-
- REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq);
- LEGAL_NEW_RESOURCE (stuff->region, client);
-
- things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq);
- if (things & 4)
- return BadLength;
- things >>= 3;
-
- pRegion = RECTS_TO_REGION(0, things, (xRectangle *) (stuff + 1), CT_UNSORTED);
- if (!pRegion)
- return BadAlloc;
- if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
- return BadAlloc;
-
- return(client->noClientException);
-}
-
-int
-SProcXFixesCreateRegion (ClientPtr client)
-{
- register int n;
- REQUEST(xXFixesCreateRegionReq);
-
- swaps(&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq);
- swapl(&stuff->region, n);
- SwapRestS(stuff);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesCreateRegionFromBitmap (ClientPtr client)
-{
- RegionPtr pRegion;
- PixmapPtr pPixmap;
- int rc;
- REQUEST (xXFixesCreateRegionFromBitmapReq);
-
- REQUEST_SIZE_MATCH (xXFixesCreateRegionFromBitmapReq);
- LEGAL_NEW_RESOURCE (stuff->region, client);
-
- rc = dixLookupResourceByType((pointer *)&pPixmap, stuff->bitmap, RT_PIXMAP,
- client, DixReadAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->bitmap;
- return (rc == BadValue) ? BadPixmap : rc;
- }
- if (pPixmap->drawable.depth != 1)
- return BadMatch;
-
- pRegion = BITMAP_TO_REGION(pPixmap->drawable.pScreen, pPixmap);
-
- if (!pRegion)
- return BadAlloc;
-
- if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
- return BadAlloc;
-
- return(client->noClientException);
-}
-
-int
-SProcXFixesCreateRegionFromBitmap (ClientPtr client)
-{
- int n;
- REQUEST (xXFixesCreateRegionFromBitmapReq);
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xXFixesCreateRegionFromBitmapReq);
- swapl(&stuff->region, n);
- swapl(&stuff->bitmap, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesCreateRegionFromWindow (ClientPtr client)
-{
- RegionPtr pRegion;
- Bool copy = TRUE;
- WindowPtr pWin;
- int rc;
- REQUEST (xXFixesCreateRegionFromWindowReq);
-
- REQUEST_SIZE_MATCH (xXFixesCreateRegionFromWindowReq);
- LEGAL_NEW_RESOURCE (stuff->region, client);
- rc = dixLookupResourceByType((pointer *)&pWin, stuff->window, RT_WINDOW,
- client, DixGetAttrAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->window;
- return (rc == BadValue) ? BadWindow : rc;
- }
- switch (stuff->kind) {
- case WindowRegionBounding:
- pRegion = wBoundingShape(pWin);
- if (!pRegion)
- {
- pRegion = CreateBoundingShape (pWin);
- copy = FALSE;
- }
- break;
- case WindowRegionClip:
- pRegion = wClipShape(pWin);
- if (!pRegion)
- {
- pRegion = CreateClipShape (pWin);
- copy = FALSE;
- }
- break;
- default:
- client->errorValue = stuff->kind;
- return BadValue;
- }
- if (copy && pRegion)
- pRegion = XFixesRegionCopy (pRegion);
- if (!pRegion)
- return BadAlloc;
- if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
- return BadAlloc;
-
- return(client->noClientException);
-}
-
-int
-SProcXFixesCreateRegionFromWindow (ClientPtr client)
-{
- int n;
- REQUEST (xXFixesCreateRegionFromWindowReq);
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xXFixesCreateRegionFromWindowReq);
- swapl(&stuff->region, n);
- swapl(&stuff->window, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesCreateRegionFromGC (ClientPtr client)
-{
- RegionPtr pRegion, pClip;
- GCPtr pGC;
- int rc;
- REQUEST (xXFixesCreateRegionFromGCReq);
-
- REQUEST_SIZE_MATCH (xXFixesCreateRegionFromGCReq);
- LEGAL_NEW_RESOURCE (stuff->region, client);
-
- rc = dixLookupGC(&pGC, stuff->gc, client, DixGetAttrAccess);
- if (rc != Success)
- return rc;
-
- switch (pGC->clientClipType) {
- case CT_PIXMAP:
- pRegion = BITMAP_TO_REGION(pGC->pScreen, (PixmapPtr) pGC->clientClip);
- if (!pRegion)
- return BadAlloc;
- break;
- case CT_REGION:
- pClip = (RegionPtr) pGC->clientClip;
- pRegion = XFixesRegionCopy (pClip);
- if (!pRegion)
- return BadAlloc;
- break;
- default:
- return BadImplementation; /* assume sane server bits */
- }
-
- if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
- return BadAlloc;
-
- return(client->noClientException);
-}
-
-int
-SProcXFixesCreateRegionFromGC (ClientPtr client)
-{
- int n;
- REQUEST (xXFixesCreateRegionFromGCReq);
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xXFixesCreateRegionFromGCReq);
- swapl(&stuff->region, n);
- swapl(&stuff->gc, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesCreateRegionFromPicture (ClientPtr client)
-{
- RegionPtr pRegion;
- PicturePtr pPicture;
- REQUEST (xXFixesCreateRegionFromPictureReq);
-
- REQUEST_SIZE_MATCH (xXFixesCreateRegionFromPictureReq);
- LEGAL_NEW_RESOURCE (stuff->region, client);
-
- VERIFY_PICTURE(pPicture, stuff->picture, client, DixGetAttrAccess,
- RenderErrBase + BadPicture);
-
- switch (pPicture->clientClipType) {
- case CT_PIXMAP:
- pRegion = BITMAP_TO_REGION(pPicture->pDrawable->pScreen,
- (PixmapPtr) pPicture->clientClip);
- if (!pRegion)
- return BadAlloc;
- break;
- case CT_REGION:
- pRegion = XFixesRegionCopy ((RegionPtr) pPicture->clientClip);
- if (!pRegion)
- return BadAlloc;
- break;
- default:
- return BadImplementation; /* assume sane server bits */
- }
-
- if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
- return BadAlloc;
-
- return(client->noClientException);
-}
-
-int
-SProcXFixesCreateRegionFromPicture (ClientPtr client)
-{
- int n;
- REQUEST (xXFixesCreateRegionFromPictureReq);
-
- swaps(&stuff->length, n);
- REQUEST_SIZE_MATCH (xXFixesCreateRegionFromPictureReq);
- swapl(&stuff->region, n);
- swapl(&stuff->picture, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesDestroyRegion (ClientPtr client)
-{
- REQUEST (xXFixesDestroyRegionReq);
- RegionPtr pRegion;
-
- REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq);
- VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
- FreeResource (stuff->region, RT_NONE);
- return(client->noClientException);
-}
-
-int
-SProcXFixesDestroyRegion (ClientPtr client)
-{
- int n;
- REQUEST (xXFixesDestroyRegionReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq);
- swapl (&stuff->region, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesSetRegion (ClientPtr client)
-{
- int things;
- RegionPtr pRegion, pNew;
- REQUEST (xXFixesSetRegionReq);
-
- REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq);
- VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
-
- things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq);
- if (things & 4)
- return BadLength;
- things >>= 3;
-
- pNew = RECTS_TO_REGION(0, things, (xRectangle *) (stuff + 1), CT_UNSORTED);
- if (!pNew)
- return BadAlloc;
- if (!REGION_COPY (0, pRegion, pNew))
- {
- REGION_DESTROY (0, pNew);
- return BadAlloc;
- }
- REGION_DESTROY (0, pNew);
- return(client->noClientException);
-}
-
-int
-SProcXFixesSetRegion (ClientPtr client)
-{
- int n;
- REQUEST (xXFixesSetRegionReq);
-
- swaps (&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq);
- swapl (&stuff->region, n);
- SwapRestS(stuff);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesCopyRegion (ClientPtr client)
-{
- RegionPtr pSource, pDestination;
- REQUEST (xXFixesCopyRegionReq);
-
- VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
- VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
-
- if (!REGION_COPY(pScreen, pDestination, pSource))
- return BadAlloc;
-
- return(client->noClientException);
-}
-
-int
-SProcXFixesCopyRegion (ClientPtr client)
-{
- int n;
- REQUEST (xXFixesCopyRegionReq);
-
- swaps (&stuff->length, n);
- REQUEST_AT_LEAST_SIZE(xXFixesCopyRegionReq);
- swapl (&stuff->source, n);
- swapl (&stuff->destination, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesCombineRegion (ClientPtr client)
-{
- RegionPtr pSource1, pSource2, pDestination;
- int ret = Success;
- REQUEST (xXFixesCombineRegionReq);
-
- REQUEST_SIZE_MATCH (xXFixesCombineRegionReq);
- VERIFY_REGION(pSource1, stuff->source1, client, DixReadAccess);
- VERIFY_REGION(pSource2, stuff->source2, client, DixReadAccess);
- VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
-
- switch (stuff->xfixesReqType) {
- case X_XFixesUnionRegion:
- if (!REGION_UNION (0, pDestination, pSource1, pSource2))
- ret = BadAlloc;
- break;
- case X_XFixesIntersectRegion:
- if (!REGION_INTERSECT (0, pDestination, pSource1, pSource2))
- ret = BadAlloc;
- break;
- case X_XFixesSubtractRegion:
- if (!REGION_SUBTRACT (0, pDestination, pSource1, pSource2))
- ret = BadAlloc;
- break;
- }
-
- if (ret == Success)
- ret = client->noClientException;
- return ret;
-}
-
-int
-SProcXFixesCombineRegion (ClientPtr client)
-{
- int n;
- REQUEST (xXFixesCombineRegionReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH (xXFixesCombineRegionReq);
- swapl (&stuff->source1, n);
- swapl (&stuff->source2, n);
- swapl (&stuff->destination, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesInvertRegion (ClientPtr client)
-{
- RegionPtr pSource, pDestination;
- BoxRec bounds;
- int ret = Success;
- REQUEST(xXFixesInvertRegionReq);
-
- REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
- VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
- VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
-
- /* Compute bounds, limit to 16 bits */
- bounds.x1 = stuff->x;
- bounds.y1 = stuff->y;
- if ((int) stuff->x + (int) stuff->width > MAXSHORT)
- bounds.x2 = MAXSHORT;
- else
- bounds.x2 = stuff->x + stuff->width;
-
- if ((int) stuff->y + (int) stuff->height > MAXSHORT)
- bounds.y2 = MAXSHORT;
- else
- bounds.y2 = stuff->y + stuff->height;
-
- if (!REGION_INVERSE(0, pDestination, pSource, &bounds))
- ret = BadAlloc;
-
- if (ret == Success)
- ret = client->noClientException;
- return ret;
-}
-
-int
-SProcXFixesInvertRegion (ClientPtr client)
-{
- int n;
- REQUEST(xXFixesInvertRegionReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
- swapl (&stuff->source, n);
- swaps (&stuff->x, n);
- swaps (&stuff->y, n);
- swaps (&stuff->width, n);
- swaps (&stuff->height, n);
- swapl (&stuff->destination, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesTranslateRegion (ClientPtr client)
-{
- RegionPtr pRegion;
- REQUEST(xXFixesTranslateRegionReq);
-
- REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
- VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
-
- REGION_TRANSLATE(pScreen, pRegion, stuff->dx, stuff->dy);
- return (client->noClientException);
-}
-
-int
-SProcXFixesTranslateRegion (ClientPtr client)
-{
- int n;
- REQUEST(xXFixesTranslateRegionReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
- swapl (&stuff->region, n);
- swaps (&stuff->dx, n);
- swaps (&stuff->dy, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesRegionExtents (ClientPtr client)
-{
- RegionPtr pSource, pDestination;
- REQUEST(xXFixesRegionExtentsReq);
-
- REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
- VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
- VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
-
- REGION_RESET (0, pDestination, REGION_EXTENTS (0, pSource));
-
- return (client->noClientException);
-}
-
-int
-SProcXFixesRegionExtents (ClientPtr client)
-{
- int n;
- REQUEST(xXFixesRegionExtentsReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
- swapl (&stuff->source, n);
- swapl (&stuff->destination, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesFetchRegion (ClientPtr client)
-{
- RegionPtr pRegion;
- xXFixesFetchRegionReply *reply;
- xRectangle *pRect;
- BoxPtr pExtent;
- BoxPtr pBox;
- int i, nBox;
- REQUEST(xXFixesFetchRegionReq);
-
- REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
- VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess);
-
- pExtent = REGION_EXTENTS (0, pRegion);
- pBox = REGION_RECTS (pRegion);
- nBox = REGION_NUM_RECTS (pRegion);
-
- reply = xalloc (sizeof (xXFixesFetchRegionReply) +
- nBox * sizeof (xRectangle));
- if (!reply)
- return BadAlloc;
- reply->type = X_Reply;
- reply->sequenceNumber = client->sequence;
- reply->length = nBox << 1;
- reply->x = pExtent->x1;
- reply->y = pExtent->y1;
- reply->width = pExtent->x2 - pExtent->x1;
- reply->height = pExtent->y2 - pExtent->y1;
-
- pRect = (xRectangle *) (reply + 1);
- for (i = 0; i < nBox; i++)
- {
- pRect[i].x = pBox[i].x1;
- pRect[i].y = pBox[i].y1;
- pRect[i].width = pBox[i].x2 - pBox[i].x1;
- pRect[i].height = pBox[i].y2 - pBox[i].y1;
- }
- if (client->swapped)
- {
- int n;
- swaps (&reply->sequenceNumber, n);
- swapl (&reply->length, n);
- swaps (&reply->x, n);
- swaps (&reply->y, n);
- swaps (&reply->width, n);
- swaps (&reply->height, n);
- SwapShorts ((INT16 *) pRect, nBox * 4);
- }
- (void) WriteToClient(client, sizeof (xXFixesFetchRegionReply) +
- nBox * sizeof (xRectangle), (char *) reply);
- xfree (reply);
- return (client->noClientException);
-}
-
-int
-SProcXFixesFetchRegion (ClientPtr client)
-{
- int n;
- REQUEST(xXFixesFetchRegionReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
- swapl (&stuff->region, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesSetGCClipRegion (ClientPtr client)
-{
- GCPtr pGC;
- RegionPtr pRegion;
- XID vals[2];
- int rc;
- REQUEST(xXFixesSetGCClipRegionReq);
- REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
-
- rc = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
- if (rc != Success)
- return rc;
-
- VERIFY_REGION_OR_NONE (pRegion, stuff->region, client, DixReadAccess);
-
- if (pRegion)
- {
- pRegion = XFixesRegionCopy (pRegion);
- if (!pRegion)
- return BadAlloc;
- }
-
- vals[0] = stuff->xOrigin;
- vals[1] = stuff->yOrigin;
- DoChangeGC (pGC, GCClipXOrigin|GCClipYOrigin, vals, 0);
- (*pGC->funcs->ChangeClip)(pGC, pRegion ? CT_REGION : CT_NONE, (pointer)pRegion, 0);
-
- return (client->noClientException);
-}
-
-int
-SProcXFixesSetGCClipRegion (ClientPtr client)
-{
- int n;
- REQUEST(xXFixesSetGCClipRegionReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
- swapl (&stuff->gc, n);
- swapl (&stuff->region, n);
- swaps (&stuff->xOrigin, n);
- swaps (&stuff->yOrigin, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-typedef RegionPtr (*CreateDftPtr)(WindowPtr pWin);
-
-int
-ProcXFixesSetWindowShapeRegion (ClientPtr client)
-{
- WindowPtr pWin;
- ScreenPtr pScreen;
- RegionPtr pRegion;
- RegionPtr *pDestRegion;
- int rc;
- REQUEST(xXFixesSetWindowShapeRegionReq);
-
- REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
- rc = dixLookupResourceByType((pointer *)&pWin, stuff->dest, RT_WINDOW,
- client, DixSetAttrAccess);
- if (rc != Success)
- {
- client->errorValue = stuff->dest;
- return (rc == BadValue) ? BadWindow : rc;
- }
- VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixWriteAccess);
- pScreen = pWin->drawable.pScreen;
- switch (stuff->destKind) {
- case ShapeBounding:
- case ShapeClip:
- case ShapeInput:
- break;
- default:
- client->errorValue = stuff->destKind;
- return BadValue;
- }
- if (pRegion)
- {
- pRegion = XFixesRegionCopy (pRegion);
- if (!pRegion)
- return BadAlloc;
- if (!pWin->optional)
- MakeWindowOptional (pWin);
- switch (stuff->destKind) {
- default:
- case ShapeBounding:
- pDestRegion = &pWin->optional->boundingShape;
- break;
- case ShapeClip:
- pDestRegion = &pWin->optional->clipShape;
- break;
- case ShapeInput:
- pDestRegion = &pWin->optional->inputShape;
- break;
- }
- if (stuff->xOff || stuff->yOff)
- REGION_TRANSLATE (0, pRegion, stuff->xOff, stuff->yOff);
- }
- else
- {
- if (pWin->optional)
- {
- switch (stuff->destKind) {
- default:
- case ShapeBounding:
- pDestRegion = &pWin->optional->boundingShape;
- break;
- case ShapeClip:
- pDestRegion = &pWin->optional->clipShape;
- break;
- case ShapeInput:
- pDestRegion = &pWin->optional->inputShape;
- break;
- }
- }
- else
- pDestRegion = &pRegion; /* a NULL region pointer */
- }
- if (*pDestRegion)
- REGION_DESTROY(pScreen, *pDestRegion);
- *pDestRegion = pRegion;
- (*pScreen->SetShape) (pWin);
- SendShapeNotify (pWin, stuff->destKind);
- return (client->noClientException);
-}
-
-int
-SProcXFixesSetWindowShapeRegion (ClientPtr client)
-{
- int n;
- REQUEST(xXFixesSetWindowShapeRegionReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
- swapl (&stuff->dest, n);
- swaps (&stuff->xOff, n);
- swaps (&stuff->yOff, n);
- swapl (&stuff->region, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesSetPictureClipRegion (ClientPtr client)
-{
- PicturePtr pPicture;
- RegionPtr pRegion;
- ScreenPtr pScreen;
- PictureScreenPtr ps;
- REQUEST(xXFixesSetPictureClipRegionReq);
-
- REQUEST_SIZE_MATCH (xXFixesSetPictureClipRegionReq);
- VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess,
- RenderErrBase + BadPicture);
- pScreen = pPicture->pDrawable->pScreen;
- ps = GetPictureScreen (pScreen);
- VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixReadAccess);
-
- return SetPictureClipRegion (pPicture, stuff->xOrigin, stuff->yOrigin,
- pRegion);
-}
-
-int
-SProcXFixesSetPictureClipRegion (ClientPtr client)
-{
- int n;
- REQUEST(xXFixesSetPictureClipRegionReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH (xXFixesSetPictureClipRegionReq);
- swapl (&stuff->picture, n);
- swapl (&stuff->region, n);
- swaps (&stuff->xOrigin, n);
- swaps (&stuff->yOrigin, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
-int
-ProcXFixesExpandRegion (ClientPtr client)
-{
- RegionPtr pSource, pDestination;
- int ret = Success;
- REQUEST (xXFixesExpandRegionReq);
- BoxPtr pTmp;
- BoxPtr pSrc;
- int nBoxes;
- int i;
-
- REQUEST_SIZE_MATCH (xXFixesExpandRegionReq);
- VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
- VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
-
- nBoxes = REGION_NUM_RECTS(pSource);
- pSrc = REGION_RECTS(pSource);
- if (nBoxes)
- {
- pTmp = xalloc (nBoxes * sizeof (BoxRec));
- if (!pTmp)
- return BadAlloc;
- for (i = 0; i < nBoxes; i++)
- {
- pTmp[i].x1 = pSrc[i].x1 - stuff->left;
- pTmp[i].x2 = pSrc[i].x2 + stuff->right;
- pTmp[i].y1 = pSrc[i].y1 - stuff->top;
- pTmp[i].y2 = pSrc[i].y2 + stuff->bottom;
- }
- REGION_EMPTY (pScreen, pDestination);
- for (i = 0; i < nBoxes; i++)
- {
- RegionRec r;
- REGION_INIT (pScreen, &r, &pTmp[i], 0);
- REGION_UNION (pScreen, pDestination, pDestination, &r);
- }
- xfree(pTmp);
- }
- if (ret == Success)
- ret = client->noClientException;
- return ret;
-}
-
-int
-SProcXFixesExpandRegion (ClientPtr client)
-{
- int n;
- REQUEST (xXFixesExpandRegionReq);
-
- swaps (&stuff->length, n);
- REQUEST_SIZE_MATCH (xXFixesExpandRegionReq);
- swapl (&stuff->source, n);
- swapl (&stuff->destination, n);
- swaps (&stuff->left, n);
- swaps (&stuff->right, n);
- swaps (&stuff->top, n);
- swaps (&stuff->bottom, n);
- return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
-}
-
+/*
+ * Copyright © 2003 Keith Packard
+ *
+ * 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, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission. Keith Packard makes no
+ * representations about the suitability of this software for any purpose. It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD 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 "xfixesint.h"
+#include "scrnintstr.h"
+#include <picturestr.h>
+extern int RenderErrBase;
+#include <regionstr.h>
+#include <gcstruct.h>
+#include <window.h>
+
+RESTYPE RegionResType;
+
+static int
+RegionResFree (pointer data, XID id)
+{
+ RegionPtr pRegion = (RegionPtr) data;
+
+ REGION_DESTROY (0, pRegion);
+ return Success;
+}
+
+RegionPtr
+XFixesRegionCopy (RegionPtr pRegion)
+{
+ RegionPtr pNew = REGION_CREATE (0, REGION_EXTENTS(0, pRegion),
+ REGION_NUM_RECTS(pRegion));
+ if (!pNew)
+ return 0;
+ if (!REGION_COPY (0, pNew, pRegion))
+ {
+ REGION_DESTROY (0, pNew);
+ return 0;
+ }
+ return pNew;
+}
+
+Bool
+XFixesRegionInit (void)
+{
+ RegionResType = CreateNewResourceType(RegionResFree, "XFixesRegion");
+
+ return (RegionResType != 0);
+}
+
+int
+ProcXFixesCreateRegion (ClientPtr client)
+{
+ int things;
+ RegionPtr pRegion;
+ REQUEST (xXFixesCreateRegionReq);
+
+ REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq);
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+
+ things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq);
+ if (things & 4)
+ return BadLength;
+ things >>= 3;
+
+ pRegion = RECTS_TO_REGION(0, things, (xRectangle *) (stuff + 1), CT_UNSORTED);
+ if (!pRegion)
+ return BadAlloc;
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesCreateRegion (ClientPtr client)
+{
+ register int n;
+ REQUEST(xXFixesCreateRegionReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xXFixesCreateRegionReq);
+ swapl(&stuff->region, n);
+ SwapRestS(stuff);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCreateRegionFromBitmap (ClientPtr client)
+{
+ RegionPtr pRegion;
+ PixmapPtr pPixmap;
+ int rc;
+ REQUEST (xXFixesCreateRegionFromBitmapReq);
+
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromBitmapReq);
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+
+ rc = dixLookupResourceByType((pointer *)&pPixmap, stuff->bitmap, RT_PIXMAP,
+ client, DixReadAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->bitmap;
+ return (rc == BadValue) ? BadPixmap : rc;
+ }
+ if (pPixmap->drawable.depth != 1)
+ return BadMatch;
+
+ pRegion = BITMAP_TO_REGION(pPixmap->drawable.pScreen, pPixmap);
+
+ if (!pRegion)
+ return BadAlloc;
+
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesCreateRegionFromBitmap (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCreateRegionFromBitmapReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromBitmapReq);
+ swapl(&stuff->region, n);
+ swapl(&stuff->bitmap, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCreateRegionFromWindow (ClientPtr client)
+{
+ RegionPtr pRegion;
+ Bool copy = TRUE;
+ WindowPtr pWin;
+ int rc;
+ REQUEST (xXFixesCreateRegionFromWindowReq);
+
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromWindowReq);
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+ rc = dixLookupResourceByType((pointer *)&pWin, stuff->window, RT_WINDOW,
+ client, DixGetAttrAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->window;
+ return (rc == BadValue) ? BadWindow : rc;
+ }
+ switch (stuff->kind) {
+ case WindowRegionBounding:
+ pRegion = wBoundingShape(pWin);
+ if (!pRegion)
+ {
+ pRegion = CreateBoundingShape (pWin);
+ copy = FALSE;
+ }
+ break;
+ case WindowRegionClip:
+ pRegion = wClipShape(pWin);
+ if (!pRegion)
+ {
+ pRegion = CreateClipShape (pWin);
+ copy = FALSE;
+ }
+ break;
+ default:
+ client->errorValue = stuff->kind;
+ return BadValue;
+ }
+ if (copy && pRegion)
+ pRegion = XFixesRegionCopy (pRegion);
+ if (!pRegion)
+ return BadAlloc;
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesCreateRegionFromWindow (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCreateRegionFromWindowReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromWindowReq);
+ swapl(&stuff->region, n);
+ swapl(&stuff->window, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCreateRegionFromGC (ClientPtr client)
+{
+ RegionPtr pRegion, pClip;
+ GCPtr pGC;
+ int rc;
+ REQUEST (xXFixesCreateRegionFromGCReq);
+
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromGCReq);
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+
+ rc = dixLookupGC(&pGC, stuff->gc, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ switch (pGC->clientClipType) {
+ case CT_PIXMAP:
+ pRegion = BITMAP_TO_REGION(pGC->pScreen, (PixmapPtr) pGC->clientClip);
+ if (!pRegion)
+ return BadAlloc;
+ break;
+ case CT_REGION:
+ pClip = (RegionPtr) pGC->clientClip;
+ pRegion = XFixesRegionCopy (pClip);
+ if (!pRegion)
+ return BadAlloc;
+ break;
+ default:
+ return BadImplementation; /* assume sane server bits */
+ }
+
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesCreateRegionFromGC (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCreateRegionFromGCReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromGCReq);
+ swapl(&stuff->region, n);
+ swapl(&stuff->gc, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCreateRegionFromPicture (ClientPtr client)
+{
+ RegionPtr pRegion;
+ PicturePtr pPicture;
+ REQUEST (xXFixesCreateRegionFromPictureReq);
+
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromPictureReq);
+ LEGAL_NEW_RESOURCE (stuff->region, client);
+
+ VERIFY_PICTURE(pPicture, stuff->picture, client, DixGetAttrAccess);
+
+ switch (pPicture->clientClipType) {
+ case CT_PIXMAP:
+ pRegion = BITMAP_TO_REGION(pPicture->pDrawable->pScreen,
+ (PixmapPtr) pPicture->clientClip);
+ if (!pRegion)
+ return BadAlloc;
+ break;
+ case CT_REGION:
+ pRegion = XFixesRegionCopy ((RegionPtr) pPicture->clientClip);
+ if (!pRegion)
+ return BadAlloc;
+ break;
+ default:
+ return BadImplementation; /* assume sane server bits */
+ }
+
+ if (!AddResource (stuff->region, RegionResType, (pointer) pRegion))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesCreateRegionFromPicture (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCreateRegionFromPictureReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesCreateRegionFromPictureReq);
+ swapl(&stuff->region, n);
+ swapl(&stuff->picture, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesDestroyRegion (ClientPtr client)
+{
+ REQUEST (xXFixesDestroyRegionReq);
+ RegionPtr pRegion;
+
+ REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq);
+ VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
+ FreeResource (stuff->region, RT_NONE);
+ return(client->noClientException);
+}
+
+int
+SProcXFixesDestroyRegion (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesDestroyRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesDestroyRegionReq);
+ swapl (&stuff->region, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesSetRegion (ClientPtr client)
+{
+ int things;
+ RegionPtr pRegion, pNew;
+ REQUEST (xXFixesSetRegionReq);
+
+ REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq);
+ VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
+
+ things = (client->req_len << 2) - sizeof (xXFixesCreateRegionReq);
+ if (things & 4)
+ return BadLength;
+ things >>= 3;
+
+ pNew = RECTS_TO_REGION(0, things, (xRectangle *) (stuff + 1), CT_UNSORTED);
+ if (!pNew)
+ return BadAlloc;
+ if (!REGION_COPY (0, pRegion, pNew))
+ {
+ REGION_DESTROY (0, pNew);
+ return BadAlloc;
+ }
+ REGION_DESTROY (0, pNew);
+ return(client->noClientException);
+}
+
+int
+SProcXFixesSetRegion (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesSetRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xXFixesSetRegionReq);
+ swapl (&stuff->region, n);
+ SwapRestS(stuff);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCopyRegion (ClientPtr client)
+{
+ RegionPtr pSource, pDestination;
+ REQUEST (xXFixesCopyRegionReq);
+
+ VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
+ VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
+
+ if (!REGION_COPY(pScreen, pDestination, pSource))
+ return BadAlloc;
+
+ return(client->noClientException);
+}
+
+int
+SProcXFixesCopyRegion (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCopyRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xXFixesCopyRegionReq);
+ swapl (&stuff->source, n);
+ swapl (&stuff->destination, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesCombineRegion (ClientPtr client)
+{
+ RegionPtr pSource1, pSource2, pDestination;
+ int ret = Success;
+ REQUEST (xXFixesCombineRegionReq);
+
+ REQUEST_SIZE_MATCH (xXFixesCombineRegionReq);
+ VERIFY_REGION(pSource1, stuff->source1, client, DixReadAccess);
+ VERIFY_REGION(pSource2, stuff->source2, client, DixReadAccess);
+ VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
+
+ switch (stuff->xfixesReqType) {
+ case X_XFixesUnionRegion:
+ if (!REGION_UNION (0, pDestination, pSource1, pSource2))
+ ret = BadAlloc;
+ break;
+ case X_XFixesIntersectRegion:
+ if (!REGION_INTERSECT (0, pDestination, pSource1, pSource2))
+ ret = BadAlloc;
+ break;
+ case X_XFixesSubtractRegion:
+ if (!REGION_SUBTRACT (0, pDestination, pSource1, pSource2))
+ ret = BadAlloc;
+ break;
+ }
+
+ if (ret == Success)
+ ret = client->noClientException;
+ return ret;
+}
+
+int
+SProcXFixesCombineRegion (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesCombineRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesCombineRegionReq);
+ swapl (&stuff->source1, n);
+ swapl (&stuff->source2, n);
+ swapl (&stuff->destination, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesInvertRegion (ClientPtr client)
+{
+ RegionPtr pSource, pDestination;
+ BoxRec bounds;
+ int ret = Success;
+ REQUEST(xXFixesInvertRegionReq);
+
+ REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
+ VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
+ VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
+
+ /* Compute bounds, limit to 16 bits */
+ bounds.x1 = stuff->x;
+ bounds.y1 = stuff->y;
+ if ((int) stuff->x + (int) stuff->width > MAXSHORT)
+ bounds.x2 = MAXSHORT;
+ else
+ bounds.x2 = stuff->x + stuff->width;
+
+ if ((int) stuff->y + (int) stuff->height > MAXSHORT)
+ bounds.y2 = MAXSHORT;
+ else
+ bounds.y2 = stuff->y + stuff->height;
+
+ if (!REGION_INVERSE(0, pDestination, pSource, &bounds))
+ ret = BadAlloc;
+
+ if (ret == Success)
+ ret = client->noClientException;
+ return ret;
+}
+
+int
+SProcXFixesInvertRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesInvertRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesInvertRegionReq);
+ swapl (&stuff->source, n);
+ swaps (&stuff->x, n);
+ swaps (&stuff->y, n);
+ swaps (&stuff->width, n);
+ swaps (&stuff->height, n);
+ swapl (&stuff->destination, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesTranslateRegion (ClientPtr client)
+{
+ RegionPtr pRegion;
+ REQUEST(xXFixesTranslateRegionReq);
+
+ REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
+ VERIFY_REGION(pRegion, stuff->region, client, DixWriteAccess);
+
+ REGION_TRANSLATE(pScreen, pRegion, stuff->dx, stuff->dy);
+ return (client->noClientException);
+}
+
+int
+SProcXFixesTranslateRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesTranslateRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesTranslateRegionReq);
+ swapl (&stuff->region, n);
+ swaps (&stuff->dx, n);
+ swaps (&stuff->dy, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesRegionExtents (ClientPtr client)
+{
+ RegionPtr pSource, pDestination;
+ REQUEST(xXFixesRegionExtentsReq);
+
+ REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
+ VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
+ VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
+
+ REGION_RESET (0, pDestination, REGION_EXTENTS (0, pSource));
+
+ return (client->noClientException);
+}
+
+int
+SProcXFixesRegionExtents (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesRegionExtentsReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesRegionExtentsReq);
+ swapl (&stuff->source, n);
+ swapl (&stuff->destination, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesFetchRegion (ClientPtr client)
+{
+ RegionPtr pRegion;
+ xXFixesFetchRegionReply *reply;
+ xRectangle *pRect;
+ BoxPtr pExtent;
+ BoxPtr pBox;
+ int i, nBox;
+ REQUEST(xXFixesFetchRegionReq);
+
+ REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
+ VERIFY_REGION(pRegion, stuff->region, client, DixReadAccess);
+
+ pExtent = REGION_EXTENTS (0, pRegion);
+ pBox = REGION_RECTS (pRegion);
+ nBox = REGION_NUM_RECTS (pRegion);
+
+ reply = xalloc (sizeof (xXFixesFetchRegionReply) +
+ nBox * sizeof (xRectangle));
+ if (!reply)
+ return BadAlloc;
+ reply->type = X_Reply;
+ reply->sequenceNumber = client->sequence;
+ reply->length = nBox << 1;
+ reply->x = pExtent->x1;
+ reply->y = pExtent->y1;
+ reply->width = pExtent->x2 - pExtent->x1;
+ reply->height = pExtent->y2 - pExtent->y1;
+
+ pRect = (xRectangle *) (reply + 1);
+ for (i = 0; i < nBox; i++)
+ {
+ pRect[i].x = pBox[i].x1;
+ pRect[i].y = pBox[i].y1;
+ pRect[i].width = pBox[i].x2 - pBox[i].x1;
+ pRect[i].height = pBox[i].y2 - pBox[i].y1;
+ }
+ if (client->swapped)
+ {
+ int n;
+ swaps (&reply->sequenceNumber, n);
+ swapl (&reply->length, n);
+ swaps (&reply->x, n);
+ swaps (&reply->y, n);
+ swaps (&reply->width, n);
+ swaps (&reply->height, n);
+ SwapShorts ((INT16 *) pRect, nBox * 4);
+ }
+ (void) WriteToClient(client, sizeof (xXFixesFetchRegionReply) +
+ nBox * sizeof (xRectangle), (char *) reply);
+ xfree (reply);
+ return (client->noClientException);
+}
+
+int
+SProcXFixesFetchRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesFetchRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesFetchRegionReq);
+ swapl (&stuff->region, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesSetGCClipRegion (ClientPtr client)
+{
+ GCPtr pGC;
+ RegionPtr pRegion;
+ XID vals[2];
+ int rc;
+ REQUEST(xXFixesSetGCClipRegionReq);
+ REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
+
+ rc = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ VERIFY_REGION_OR_NONE (pRegion, stuff->region, client, DixReadAccess);
+
+ if (pRegion)
+ {
+ pRegion = XFixesRegionCopy (pRegion);
+ if (!pRegion)
+ return BadAlloc;
+ }
+
+ vals[0] = stuff->xOrigin;
+ vals[1] = stuff->yOrigin;
+ DoChangeGC (pGC, GCClipXOrigin|GCClipYOrigin, vals, 0);
+ (*pGC->funcs->ChangeClip)(pGC, pRegion ? CT_REGION : CT_NONE, (pointer)pRegion, 0);
+
+ return (client->noClientException);
+}
+
+int
+SProcXFixesSetGCClipRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesSetGCClipRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesSetGCClipRegionReq);
+ swapl (&stuff->gc, n);
+ swapl (&stuff->region, n);
+ swaps (&stuff->xOrigin, n);
+ swaps (&stuff->yOrigin, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+typedef RegionPtr (*CreateDftPtr)(WindowPtr pWin);
+
+int
+ProcXFixesSetWindowShapeRegion (ClientPtr client)
+{
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ RegionPtr pRegion;
+ RegionPtr *pDestRegion;
+ int rc;
+ REQUEST(xXFixesSetWindowShapeRegionReq);
+
+ REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
+ rc = dixLookupResourceByType((pointer *)&pWin, stuff->dest, RT_WINDOW,
+ client, DixSetAttrAccess);
+ if (rc != Success)
+ {
+ client->errorValue = stuff->dest;
+ return (rc == BadValue) ? BadWindow : rc;
+ }
+ VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixWriteAccess);
+ pScreen = pWin->drawable.pScreen;
+ switch (stuff->destKind) {
+ case ShapeBounding:
+ case ShapeClip:
+ case ShapeInput:
+ break;
+ default:
+ client->errorValue = stuff->destKind;
+ return BadValue;
+ }
+ if (pRegion)
+ {
+ pRegion = XFixesRegionCopy (pRegion);
+ if (!pRegion)
+ return BadAlloc;
+ if (!pWin->optional)
+ MakeWindowOptional (pWin);
+ switch (stuff->destKind) {
+ default:
+ case ShapeBounding:
+ pDestRegion = &pWin->optional->boundingShape;
+ break;
+ case ShapeClip:
+ pDestRegion = &pWin->optional->clipShape;
+ break;
+ case ShapeInput:
+ pDestRegion = &pWin->optional->inputShape;
+ break;
+ }
+ if (stuff->xOff || stuff->yOff)
+ REGION_TRANSLATE (0, pRegion, stuff->xOff, stuff->yOff);
+ }
+ else
+ {
+ if (pWin->optional)
+ {
+ switch (stuff->destKind) {
+ default:
+ case ShapeBounding:
+ pDestRegion = &pWin->optional->boundingShape;
+ break;
+ case ShapeClip:
+ pDestRegion = &pWin->optional->clipShape;
+ break;
+ case ShapeInput:
+ pDestRegion = &pWin->optional->inputShape;
+ break;
+ }
+ }
+ else
+ pDestRegion = &pRegion; /* a NULL region pointer */
+ }
+ if (*pDestRegion)
+ REGION_DESTROY(pScreen, *pDestRegion);
+ *pDestRegion = pRegion;
+ (*pScreen->SetShape) (pWin);
+ SendShapeNotify (pWin, stuff->destKind);
+ return (client->noClientException);
+}
+
+int
+SProcXFixesSetWindowShapeRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesSetWindowShapeRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXFixesSetWindowShapeRegionReq);
+ swapl (&stuff->dest, n);
+ swaps (&stuff->xOff, n);
+ swaps (&stuff->yOff, n);
+ swapl (&stuff->region, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesSetPictureClipRegion (ClientPtr client)
+{
+ PicturePtr pPicture;
+ RegionPtr pRegion;
+ ScreenPtr pScreen;
+ PictureScreenPtr ps;
+ REQUEST(xXFixesSetPictureClipRegionReq);
+
+ REQUEST_SIZE_MATCH (xXFixesSetPictureClipRegionReq);
+ VERIFY_PICTURE(pPicture, stuff->picture, client, DixSetAttrAccess);
+ pScreen = pPicture->pDrawable->pScreen;
+ ps = GetPictureScreen (pScreen);
+ VERIFY_REGION_OR_NONE(pRegion, stuff->region, client, DixReadAccess);
+
+ return SetPictureClipRegion (pPicture, stuff->xOrigin, stuff->yOrigin,
+ pRegion);
+}
+
+int
+SProcXFixesSetPictureClipRegion (ClientPtr client)
+{
+ int n;
+ REQUEST(xXFixesSetPictureClipRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesSetPictureClipRegionReq);
+ swapl (&stuff->picture, n);
+ swapl (&stuff->region, n);
+ swaps (&stuff->xOrigin, n);
+ swaps (&stuff->yOrigin, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
+int
+ProcXFixesExpandRegion (ClientPtr client)
+{
+ RegionPtr pSource, pDestination;
+ int ret = Success;
+ REQUEST (xXFixesExpandRegionReq);
+ BoxPtr pTmp;
+ BoxPtr pSrc;
+ int nBoxes;
+ int i;
+
+ REQUEST_SIZE_MATCH (xXFixesExpandRegionReq);
+ VERIFY_REGION(pSource, stuff->source, client, DixReadAccess);
+ VERIFY_REGION(pDestination, stuff->destination, client, DixWriteAccess);
+
+ nBoxes = REGION_NUM_RECTS(pSource);
+ pSrc = REGION_RECTS(pSource);
+ if (nBoxes)
+ {
+ pTmp = xalloc (nBoxes * sizeof (BoxRec));
+ if (!pTmp)
+ return BadAlloc;
+ for (i = 0; i < nBoxes; i++)
+ {
+ pTmp[i].x1 = pSrc[i].x1 - stuff->left;
+ pTmp[i].x2 = pSrc[i].x2 + stuff->right;
+ pTmp[i].y1 = pSrc[i].y1 - stuff->top;
+ pTmp[i].y2 = pSrc[i].y2 + stuff->bottom;
+ }
+ REGION_EMPTY (pScreen, pDestination);
+ for (i = 0; i < nBoxes; i++)
+ {
+ RegionRec r;
+ REGION_INIT (pScreen, &r, &pTmp[i], 0);
+ REGION_UNION (pScreen, pDestination, pDestination, &r);
+ }
+ xfree(pTmp);
+ }
+ if (ret == Success)
+ ret = client->noClientException;
+ return ret;
+}
+
+int
+SProcXFixesExpandRegion (ClientPtr client)
+{
+ int n;
+ REQUEST (xXFixesExpandRegionReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXFixesExpandRegionReq);
+ swapl (&stuff->source, n);
+ swapl (&stuff->destination, n);
+ swaps (&stuff->left, n);
+ swaps (&stuff->right, n);
+ swaps (&stuff->top, n);
+ swaps (&stuff->bottom, n);
+ return (*ProcXFixesVector[stuff->xfixesReqType]) (client);
+}
+
diff --git a/xorg-server/xkbdata.src/Makefile.am b/xorg-server/xkbdata.src/Makefile.am
index 48cdf4413..e98117e8e 100644
--- a/xorg-server/xkbdata.src/Makefile.am
+++ b/xorg-server/xkbdata.src/Makefile.am
@@ -1,16 +1,20 @@
-AUTOMAKE_OPTIONS = foreign
-
-SUBDIRS = compat geometry keycodes keymap po rules semantics symbols types docs
-
-EXTRA_DIST=config.rpath COPYING CREDITS README \
- autogen.sh \
- xkeyboard-config.spec \
- xkeyboard-config.spec.in \
- intltool-extract.in intltool-merge.in intltool-update.in
-
-DISTCLEANFILES=intltool-extract intltool-merge intltool-update
-
-# ACLOCAL_AMFLAGS = -I m4
-
-sync-po:
- rsync -Lrtvz translationproject.org::tp/latest/xkeyboard-config/ po
+AUTOMAKE_OPTIONS = foreign
+
+SUBDIRS = compat geometry keycodes keymap po rules semantics symbols types docs
+
+pkgconfigdir = $(datadir)/pkgconfig
+pkgconfig_DATA = xkeyboard-config.pc
+
+EXTRA_DIST=config.rpath COPYING CREDITS README \
+ autogen.sh \
+ xkeyboard-config.pc.in \
+ xkeyboard-config.spec \
+ xkeyboard-config.spec.in \
+ intltool-extract.in intltool-merge.in intltool-update.in
+
+DISTCLEANFILES=intltool-extract intltool-merge intltool-update
+
+# ACLOCAL_AMFLAGS = -I m4
+
+sync-po:
+ rsync -Lrtvz translationproject.org::tp/latest/xkeyboard-config/ po
diff --git a/xorg-server/xkbdata.src/configure.in b/xorg-server/xkbdata.src/configure.in
index ea1df8c4d..62a7fd00d 100644
--- a/xorg-server/xkbdata.src/configure.in
+++ b/xorg-server/xkbdata.src/configure.in
@@ -1,97 +1,98 @@
-AC_INIT(xkeyboard-config, 1.8)
-AC_CONFIG_SRCDIR(rules/base.xml.in)
-AM_INIT_AUTOMAKE([foreign dist-bzip2])
-AM_MAINTAINER_MODE
-
-AC_SUBST(VERSION)
-
-AC_PATH_PROG([XKBCOMP], [xkbcomp], [not_found])
-if test x$XKBCOMP = xnot_found ; then
- AC_ERROR([xkbcomp is required to install the xkb data files])
-fi
-
-AC_ARG_WITH( xkb_base,
- [AS_HELP_STRING([--with-xkb-base=DIR],[XKB base path @<:@DATADIR/X11/xkb@:>@])],
- xkb_base="$withval",
- xkb_base="\$(datadir)/X11/xkb" )
-
-AC_ARG_WITH( xkb_rules_symlink,
- [ --with-xkb-rules-symlink=NAME1(,NAME2)* create symlink(s) to "old style" rules files (xfree86 and/or xorg)],
- xkb_rules_symlink="$withval" )
-
-AC_ARG_ENABLE( compat_rules,
- [ --enable-compat-rules create compatibility rules],
- enable_compat_rules="$enableval",
- enable_compat_rules="yes" )
-
-AM_CONDITIONAL(CREATE_RULES_SYMLINK, test "x$xkb_rules_symlink" != "x")
-
-AM_CONDITIONAL(USE_COMPAT_RULES, test "x$enable_compat_rules" = "xyes")
-
-# ****
-# i18n
-# ****
-AC_PROG_INTLTOOL(0.30)
-
-GETTEXT_PACKAGE=xkeyboard-config
-AC_SUBST(GETTEXT_PACKAGE)
-AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Gettext package])
-
-AM_GLIB_GNU_GETTEXT
-
-ALL_LINGUAS="af az bg ca crh cs da de el en_GB eo es fi fr hu id it ka ko ky lt nb nl ru rw sk sl sq sr sv tr uk vi zh_CN zh_TW"
-
-AC_SUBST(xkb_base)
-AC_SUBST(xkb_rules_symlink)
-
-AC_OUTPUT([ po/Makefile.in
-Makefile
-compat/Makefile
-geometry/Makefile
-geometry/digital_vndr/Makefile
-geometry/sgi_vndr/Makefile
-keycodes/Makefile
-keycodes/digital_vndr/Makefile
-keycodes/sgi_vndr/Makefile
-keymap/Makefile
-keymap/digital_vndr/Makefile
-keymap/sgi_vndr/Makefile
-keymap/sun_vndr/Makefile
-semantics/Makefile
-rules/Makefile
-rules/bin/Makefile
-rules/compat/Makefile
-rules/extras/Makefile
-symbols/Makefile
-symbols/digital_vndr/Makefile
-symbols/fujitsu_vndr/Makefile
-symbols/hp_vndr/Makefile
-symbols/macintosh_vndr/Makefile
-symbols/nec_vndr/Makefile
-symbols/nokia_vndr/Makefile
-symbols/sgi_vndr/Makefile
-symbols/sony_vndr/Makefile
-symbols/sun_vndr/Makefile
-symbols/xfree68_vndr/Makefile
-symbols/extras/Makefile
-types/Makefile
-xkeyboard-config.spec
-docs/Makefile
-])
-
-echo '***********************************************************'
-echo " $PACKAGE_NAME is configured with the following parameters:"
-echo " XKB base directory: $xkb_base"
-if test -z "$xkb_rules_symlink" ; then
- echo " Symbolic link(s) to legacy rules are not created"
-else
- echo " Symbolic link(s) to legacy rules: $xkb_rules_symlink"
-fi
-
-if test "$enable_compat_rules" = "yes" ; then
- echo " Compatibility rules are included"
-else
- echo " Compatibility rules are not included"
-fi
-echo '***********************************************************'
-
+AC_INIT(xkeyboard-config, 1.8)
+AC_CONFIG_SRCDIR(rules/base.xml.in)
+AM_INIT_AUTOMAKE([foreign dist-bzip2])
+AM_MAINTAINER_MODE
+
+AC_SUBST(VERSION)
+
+AC_PATH_PROG([XKBCOMP], [xkbcomp], [not_found])
+if test x$XKBCOMP = xnot_found ; then
+ AC_ERROR([xkbcomp is required to install the xkb data files])
+fi
+
+AC_ARG_WITH( xkb_base,
+ [AS_HELP_STRING([--with-xkb-base=DIR],[XKB base path @<:@DATADIR/X11/xkb@:>@])],
+ xkb_base="$withval",
+ xkb_base="${datadir}/X11/xkb" )
+
+AC_ARG_WITH( xkb_rules_symlink,
+ [ --with-xkb-rules-symlink=NAME1(,NAME2)* create symlink(s) to "old style" rules files (xfree86 and/or xorg)],
+ xkb_rules_symlink="$withval" )
+
+AC_ARG_ENABLE( compat_rules,
+ [ --enable-compat-rules create compatibility rules],
+ enable_compat_rules="$enableval",
+ enable_compat_rules="yes" )
+
+AM_CONDITIONAL(CREATE_RULES_SYMLINK, test "x$xkb_rules_symlink" != "x")
+
+AM_CONDITIONAL(USE_COMPAT_RULES, test "x$enable_compat_rules" = "xyes")
+
+# ****
+# i18n
+# ****
+AC_PROG_INTLTOOL(0.30)
+
+GETTEXT_PACKAGE=xkeyboard-config
+AC_SUBST(GETTEXT_PACKAGE)
+AC_DEFINE_UNQUOTED(GETTEXT_PACKAGE, "$GETTEXT_PACKAGE", [Gettext package])
+
+AM_GLIB_GNU_GETTEXT
+
+ALL_LINGUAS="af az bg ca crh cs da de el en_GB eo es fi fr hu id it ka ko ky lt nb nl ru rw sk sl sq sr sv tr uk vi zh_CN zh_TW"
+
+AC_SUBST(xkb_base)
+AC_SUBST(xkb_rules_symlink)
+
+AC_OUTPUT([ po/Makefile.in
+Makefile
+compat/Makefile
+geometry/Makefile
+geometry/digital_vndr/Makefile
+geometry/sgi_vndr/Makefile
+keycodes/Makefile
+keycodes/digital_vndr/Makefile
+keycodes/sgi_vndr/Makefile
+keymap/Makefile
+keymap/digital_vndr/Makefile
+keymap/sgi_vndr/Makefile
+keymap/sun_vndr/Makefile
+semantics/Makefile
+rules/Makefile
+rules/bin/Makefile
+rules/compat/Makefile
+rules/extras/Makefile
+symbols/Makefile
+symbols/digital_vndr/Makefile
+symbols/fujitsu_vndr/Makefile
+symbols/hp_vndr/Makefile
+symbols/macintosh_vndr/Makefile
+symbols/nec_vndr/Makefile
+symbols/nokia_vndr/Makefile
+symbols/sgi_vndr/Makefile
+symbols/sony_vndr/Makefile
+symbols/sun_vndr/Makefile
+symbols/xfree68_vndr/Makefile
+symbols/extras/Makefile
+types/Makefile
+xkeyboard-config.pc
+xkeyboard-config.spec
+docs/Makefile
+])
+
+echo '***********************************************************'
+echo " $PACKAGE_NAME is configured with the following parameters:"
+echo " XKB base directory: $xkb_base"
+if test -z "$xkb_rules_symlink" ; then
+ echo " Symbolic link(s) to legacy rules are not created"
+else
+ echo " Symbolic link(s) to legacy rules: $xkb_rules_symlink"
+fi
+
+if test "$enable_compat_rules" = "yes" ; then
+ echo " Compatibility rules are included"
+else
+ echo " Compatibility rules are not included"
+fi
+echo '***********************************************************'
+
diff --git a/xorg-server/xkbdata.src/rules/base.xml.in b/xorg-server/xkbdata.src/rules/base.xml.in
index 3a2cfe251..969906b81 100644
--- a/xorg-server/xkbdata.src/rules/base.xml.in
+++ b/xorg-server/xkbdata.src/rules/base.xml.in
@@ -4437,6 +4437,23 @@
<_description>Kenya</_description>
<languageList><iso639Id>swa</iso639Id></languageList>
</configItem>
+ <variantList>
+ <variant>
+ <configItem>
+ <name>kik</name>
+ <_description>Kikuyu</_description>
+ <languageList><iso639Id>kik</iso639Id></languageList>
+ </configItem>
+ </variant>
+ </variantList>
+ </layout>
+ <layout>
+ <configItem>
+ <name>bw</name>
+ <_shortDescription>Bwa</_shortDescription>
+ <_description>Botswana</_description>
+ <languageList><iso639Id>tsn</iso639Id></languageList>
+ </configItem>
</layout>
</layoutList>
<optionList>
diff --git a/xorg-server/xkbdata.src/symbols/Makefile.am b/xorg-server/xkbdata.src/symbols/Makefile.am
index c9fcd4bb5..fc618a4b9 100644
--- a/xorg-server/xkbdata.src/symbols/Makefile.am
+++ b/xorg-server/xkbdata.src/symbols/Makefile.am
@@ -4,9 +4,9 @@ symbolsdir = $(xkb_base)/symbols
dist_symbols_DATA = \
ad af al \
am ara az \
-be bd \
-bg br ba \
-bt by brai \
+ba bd be \
+bg br brai \
+bt bw by \
ca cd \
ch cn cz \
de dk \
diff --git a/xorg-server/xkbdata.src/symbols/ara b/xorg-server/xkbdata.src/symbols/ara
index 9fa40e981..90a584475 100644
--- a/xorg-server/xkbdata.src/symbols/ara
+++ b/xorg-server/xkbdata.src/symbols/ara
@@ -31,30 +31,30 @@ xkb_symbols "basic" {
key <AD02> { [ Arabic_sad, Arabic_fathatan ] };
key <AD03> { [ Arabic_theh, Arabic_damma ] };
key <AD04> { [ Arabic_qaf, Arabic_dammatan ] };
- key <AD05> { [ Arabic_feh, 0x100fef9 ] };
+ key <AD05> { [ Arabic_feh, 0x100fef9, 0x10006a4 ] };
key <AD06> { [ Arabic_ghain, Arabic_hamzaunderalef ] };
key <AD07> { [ Arabic_ain, grave ] };
key <AD08> { [ Arabic_ha, division ] };
key <AD09> { [ Arabic_khah, multiply ] };
key <AD10> { [ Arabic_hah, Arabic_semicolon ] };
- key <AD11> { [ Arabic_jeem, less ] };
+ key <AD11> { [ Arabic_jeem, less, 0x1000686 ] };
key <AD12> { [ Arabic_dal, greater ] };
key <AC01> { [ Arabic_sheen, Arabic_kasra ] };
key <AC02> { [ Arabic_seen, Arabic_kasratan ] };
key <AC03> { [ Arabic_yeh, bracketright ] };
- key <AC04> { [ Arabic_beh, bracketleft ] };
+ key <AC04> { [ Arabic_beh, bracketleft, 0x100067e ] };
key <AC05> { [ Arabic_lam, 0x100fef7 ] };
key <AC06> { [ Arabic_alef, Arabic_hamzaonalef ] };
key <AC07> { [ Arabic_teh, Arabic_tatweel ] };
key <AC08> { [ Arabic_noon, Arabic_comma ] };
key <AC09> { [ Arabic_meem, slash ] };
- key <AC10> { [ Arabic_kaf, colon ] };
+ key <AC10> { [ Arabic_kaf, colon, 0x10006af ] };
key <AC11> { [ Arabic_tah, quotedbl ] };
key <LSGT> { [ bar, brokenbar ] };
- key <AB01> { [Arabic_hamzaonyeh, asciitilde ] };
- key <AB02> { [ Arabic_hamza, Arabic_sukun ] };
+ key <AB01> { [Arabic_hamzaonyeh, asciitilde, guillemotright ] };
+ key <AB02> { [ Arabic_hamza, Arabic_sukun, guillemotleft ] };
key <AB03> { [Arabic_hamzaonwaw, braceright ] };
key <AB04> { [ Arabic_ra, braceleft ] };
key <AB05> { [ 0x100fefb, 0x100fef5 ] };
@@ -64,6 +64,8 @@ xkb_symbols "basic" {
key <AB09> { [ Arabic_zain, period ] };
key <AB10> { [ Arabic_zah, Arabic_question_mark ] };
+ include "level3(ralt_switch)"
+
// End alphanumeric section
};
diff --git a/xorg-server/xkbdata.src/symbols/bw b/xorg-server/xkbdata.src/symbols/bw
new file mode 100644
index 000000000..ea5079e5d
--- /dev/null
+++ b/xorg-server/xkbdata.src/symbols/bw
@@ -0,0 +1,19 @@
+partial default alphanumeric_keys
+xkb_symbols "tswana" {
+
+ include "us"
+
+ name[Group1]= "Botswana";
+
+ key <AC10> { [ semicolon, colon, 0x01000324, 0x01000324 ] }; //COMBINING DIAERESIS BELOW
+ key <AC11> { [apostrophe, quotedbl, 0x01000301, 0x01000308 ] }; //COMBINING ACUTE ACCENT, COMBINING DIAERESIS
+ key <TLDE> { [ grave, asciitilde, 0x01000300, 0x01000303 ] }; //COMBINING GRAVE ACCENT, COMBINING TILDE
+ key <AE06> { [ 6, asciicircum, 0x01000302 ] }; //COMBINING CIRCUMFLEX ACCENT
+ key <AE08> { [ 8, asterisk, 0x01000307, 0x01000323 ] }; //COMBINING DOT ABOVE, COMBINING DOT BELOW
+ key <AE09> { [ 9, parenleft, 0x01000306 ] }; //COMBINING BREVE
+ key <AE10> { [ 0, parenright, 0x0100030c ] }; //COMBINING CARON
+ key <AE11> { [ minus, underscore, 0x01000304, 0x01000331 ] }; //COMBINING MACRON,COMBINING MACRON BELOW
+
+ include "level3(ralt_switch)"
+};
+
diff --git a/xorg-server/xkbdata.src/symbols/de b/xorg-server/xkbdata.src/symbols/de
index 60b53b545..c442e00ab 100644
--- a/xorg-server/xkbdata.src/symbols/de
+++ b/xorg-server/xkbdata.src/symbols/de
@@ -1,505 +1,505 @@
-
-// based on a keyboard map from an 'xkb/symbols/de' file
-//
-// $XKeyboardConfig$
-// $XFree86: xc/programs/xkbcomp/symbols/de,v 1.6 2003/09/08 13:12:51 pascal Exp $
-
-default
-xkb_symbols "basic" {
-
- include "latin(type4)"
-
- name[Group1]="Germany";
-
- key <AE02> { [ 2, quotedbl, twosuperior, oneeighth ] };
- key <AE03> { [ 3, section, threesuperior, sterling ] };
- key <AE04> { [ 4, dollar, onequarter, currency ] };
-
- key <AE11> {type[Group1]="FOUR_LEVEL_PLUS_LOCK", symbols[Group1]=
- [ssharp, question, backslash, questiondown, 0x1001E9E ]};
-// The unicode capital letter sharp s U+1E9E is transformed to "SS"
-// to match the rules for capitalizing sharp s in german.
-// If the capital sharp s is needed, delete the line
-// starting with <U1E9C> from /usr/share/X11/locale/iso8859-15/Compose.
-// If both doubled S and capital sharp s are needed, use 0x1001E9E
-// for capital sharp s and some free unicode codepoint like 0x1001E9C
-// for doubled S. Don`t forget to change this in the Compose file, too.
-
- key <AE12> { [dead_acute, dead_grave, dead_cedilla, dead_ogonek ] };
-
- key <AD03> { [ e, E, EuroSign, EuroSign ] };
- key <AD06> { [ z, Z, leftarrow, yen ] };
- key <AD11> { [udiaeresis, Udiaeresis, dead_diaeresis, dead_abovering ] };
- key <AD12> { [ plus, asterisk, dead_tilde, dead_macron ] };
-
- key <AC02> { [ s, S, U017F, U1E9E ] };
- key <AC07> { [ j, J, dead_belowdot, dead_abovedot ] };
- key <AC10> { [odiaeresis, Odiaeresis, dead_doubleacute, dead_belowdot ] };
- key <AC11> { [adiaeresis, Adiaeresis, dead_circumflex, dead_caron ] };
- key <TLDE> { [dead_circumflex, degree, U2032, U2033 ] };
-
- key <BKSL> { [numbersign, apostrophe, rightsinglequotemark, dead_breve ] };
- key <AB01> { [ y, Y, guillemotright, U203A ] };
- key <AB02> { [ x, X, guillemotleft, U2039 ] };
- key <AB04> { [ v, V, doublelowquotemark, singlelowquotemark ] };
- key <AB05> { [ b, B, leftdoublequotemark, leftsinglequotemark ] };
- key <AB06> { [ n, N, rightdoublequotemark, rightsinglequotemark ] };
- key <AB08> { [ comma, semicolon, periodcentered, multiply ] };
- key <AB09> { [ period, colon, U2026, division ] };
- key <AB10> { [ minus, underscore, endash, emdash ] };
-
- include "kpdl(comma)"
-
- include "level3(ralt_switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "nodeadkeys" {
-
- // modify the basic German layout to not have any dead keys
-
- include "de(basic)"
- name[Group1]="Germany - Eliminate dead keys";
-
- key <TLDE> { [asciicircum, degree, notsign, notsign ] };
- key <AE12> { [ acute, grave, cedilla, cedilla ] };
- key <AD11> { [udiaeresis, Udiaeresis, diaeresis, diaeresis ] };
- key <AD12> { [ plus, asterisk, asciitilde, macron ] };
- key <AC10> { [odiaeresis, Odiaeresis, doubleacute, doubleacute ] };
- key <AC11> { [adiaeresis, Adiaeresis, asciicircum, asciicircum ] };
- key <BKSL> { [numbersign, apostrophe, grave, grave ] };
- key <AB10> { [ minus, underscore, dead_belowdot, abovedot ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "deadgraveacute" {
- // modify the basic German layout to have only acute and grave
- // as dead keys (tilde and circumflex are needed as spacing characters
- // in many programming languages)
-
- include "de(basic)"
- name[Group1]="Germany - Dead grave acute";
-
- key <TLDE> { [asciicircum, degree, notsign, notsign ] };
- key <AD12> { [ plus, asterisk, asciitilde, dead_macron ] };
- key <BKSL> { [numbersign, apostrophe, grave, grave ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "deadacute" {
- // modify the basic German layout to have only acute as
- // dead keys (ASCII grave, tilde and circumflex are needed as
- // spacing characters in many programming languages and text formatters)
-
- include "de(deadgraveacute)"
-
- name[Group1]="Germany - Dead acute";
-
- key <AE12> { [dead_acute, grave, dead_cedilla, dead_ogonek ] };
- key <BKSL> { [numbersign, apostrophe, dead_grave, dead_grave ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "ro" {
- // add romanian-specific letters to the basic German layout.
- // Romanian symbols are accessible with combination of <AltGr> and
- // 'a', 's', 't', 'i', 'ä (&auml)' (+<Shift> for capital letters).
- // To view romanian-specific symbols, add "export LC_CTYPE=ro_RO"
- // or "export LC_CTYPE=de_DE.utf8" to your .profile.
-
- include "de(basic)"
-
- name[Group1]="Germany - Romanian keyboard with German letters";
-
- key <AD05> { [ t, T, tcedilla, Tcedilla ] };
- key <AD08> { [ i, I, icircumflex, Icircumflex ] };
- key <AC01> { [ a, A, acircumflex, Acircumflex ] };
- key <AC02> { [ s, S, scedilla, Scedilla ] };
- key <AC11> { [ adiaeresis, Adiaeresis, abreve, Abreve ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "ro_nodeadkeys" {
- // add romanian-specific letters to the German nodeadkeys layout.
- // Read the comment for de_ro !
-
- include "de(nodeadkeys)"
- name[Group1]="Germany - Romanian keyboard with German letters, eliminate dead keys";
-
- key <AD05> { [ t, T, tcedilla, Tcedilla ] };
- key <AD08> { [ i, I, icircumflex, Icircumflex ] };
- key <AC01> { [ a, A, acircumflex, Acircumflex ] };
- key <AC02> { [ s, S, scedilla, Scedilla ] };
- key <AC11> { [ adiaeresis, Adiaeresis, abreve, Abreve ] };
-};
-
-// German Dvorak keymap by Thorsten Staerk (www.staerk.de/thorsten)
-// Have acute and grave as dead keys, tilde and circumflex alive as they are needed
-// in many programming languages.
-// to use this keymap, use a 105-key-keyboard and the command setxkbmap -model pc105 -layout dvorak -variant de
-// source: http://www-lehre.informatik.uni-osnabrueck.de/~rfreund/dvorak.php
-partial alphanumeric_keys
-xkb_symbols "dvorak" {
- include "us(dvorak)"
-
- name[Group1]="Germany - Dvorak";
-
- key <TLDE> { [ asciicircum, degree ] };
-
- key <AE01> { [ 1, exclam, onesuperior ] };
- key <AE02> { [ 2, quotedbl, twosuperior ] };
- key <AE03> { [ 3, section, threesuperior ] };
- key <AE04> { [ 4, dollar, bar ] };
- key <AE05> { [ 5, percent, bar ] };
- key <AE06> { [ 6, ampersand, brokenbar ] };
- key <AE07> { [ 7, slash, braceleft ] };
- key <AE08> { [ 8, parenleft, bracketleft ] };
- key <AE09> { [ 9, parenright, bracketright ] };
- key <AE10> { [ 0, equal, braceright ] };
- key <AE11> { [ plus, asterisk, asciitilde ] };
- key <AE12> { [ less, greater, dead_grave ] };
-
- key <AD01> { [ udiaeresis, Udiaeresis, at ] };
- key <AD02> { [ comma, semicolon, dead_diaeresis ] };
- key <AD03> { [ period, colon ] };
- key <AD08> { [ c, C, copyright, Cacute ] };
- key <AD09> { [ t, T, trademark ] };
- key <AD10> { [ z, Z, zabovedot, Zabovedot ] };
- key <AD11> { [ question, ssharp ] };
- key <AD12> { [ slash, backslash, dead_acute ] };
-
- key <AC01> { [ a, A, at, aogonek ] };
- key <AC02> { [ o, O, oacute, Oacute ] };
- key <AC03> { [ e, E, EuroSign, eogonek ] };
- key <AC04> { [ i, I ] };
- key <AC05> { [ u, U ] };
- key <AC06> { [ h, H ] };
- key <AC07> { [ d, D ] };
- key <AC08> { [ r, R, registered ] };
- key <AC09> { [ n, N, nacute, Nacute ] };
- key <AC10> { [ s, S, sacute, Sacute] };
- key <AC11> { [ l, L, lstroke, Lstroke ] };
-
- key <AB01> { [ odiaeresis, Odiaeresis ] };
- key <AB02> { [ q, Q, at ] };
- key <AB07> { [ m, M, mu ] };
- key <AB10> { [ numbersign, apostrophe ] };
-
- key <BKSL> { [ minus, underscore, hyphen, diaeresis] };
-
- key <LSGT> { [ adiaeresis, Adiaeresis, bar ] };
-
- include "level3(ralt_switch)"
-};
-
-partial alphanumeric_keys
-xkb_symbols "Sundeadkeys" {
-
- // For naming consistency
-
- include "de(basic)"
-
-};
-
-partial alphanumeric_keys
-xkb_symbols "sundeadkeys" {
-
- // For naming consistency
-
- include "de(Sundeadkeys)"
-
- name[Group1]="Germany - Sun dead keys";
-};
-
-
-// German Neo-Layout Version 2
-// adopted 2004 by Hanno Behrens <Hanno.Behrens@gmx.de>
-// inspired by Dvorak/de-ergo http://www.goebel-consult.de/de-ergo/
-//
-// Authors:
-// Stephan Hilb <stephan at ehilb dot de>
-// <lucky at zankt dot net>
-// Benjamin Kellermann <Benjamin dot Kellermann at gmx dot Germany>
-// Erik Streb <mail at erikstreb dot de>
-// and many other contributors
-//
-// http://www.neo-layout.org
-//
-// $Revision$, $Date$
-
-partial alphanumeric_keys modifier_keys keypad_keys
-xkb_symbols "neo_base" {
-
- name[Group1]= "Germany - Neo 2";
-
- // Levels in Neo jargon
- // --------------------------------------------------------------
- // Ebene 1: normal
- // Ebene 2: Shift
- // Ebene 3: Mod3
- // Ebene 4: Mod4 (for marking something use Shift + Mod4)
- // Ebene 5: Shift + Mod3
- // Ebene 6: Mod3 + Mod4
- // Compose (not a level): Mod3 + Tab
- // Feststelltaste (Capslock): Shift + Shift
- // Mod4-Lock: Mod4 + Mod4
- // Mod4-Lock: Shift + Mod3 + Tab
-
- // Legend
- // ===============
- // Levels in Xkbmap jargon to be found here in the definitions.
- // These are the levels used, and Xorg's translations:
- // --------------------------------------------------------------
- // Xorg: Level1 Level2 Level3 Level4 Level5 Level6 Level7 Level8
- // Neo: Ebene1 Ebene2 Ebene3 Ebene5 Ebene4 Pseudo-Ebene Ebene6 ???
- // Keys (Neo): None Shift Mod3 Mod3 + Shift Mod4 Mod4 + Shift Mod3 + Mod4 Mod3 + Mod4 + Shift
-
-
- // Alphanumeric-keys
- // ===============
- key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK";
-
- // Tab as Multi_key (Compose)
- // --------------------------------------------------------------
- key <TAB> { [ Tab, ISO_Left_Tab, Multi_key, ISO_Level5_Lock, NoSymbol, NoSymbol, NoSymbol, ISO_Level5_Lock ] };
-
-
- // Number row
- // --------------------------------------------------------------
- key <TLDE> { [ dead_circumflex, dead_caron, U21BB, U02DE, dead_abovedot, Pointer_EnableKeys, dead_belowdot, NoSymbol ] };
-
- key <AE01> { [ 1, degree, onesuperior, onesubscript, ordfeminine, NoSymbol, notsign, NoSymbol ] };
- key <AE02> { [ 2, section, twosuperior, twosubscript, masculine, NoSymbol, logicalor, NoSymbol ] };
- key <AE03> { [ 3, U2113, threesuperior, threesubscript, numerosign, NoSymbol, logicaland, NoSymbol ] };
- key <AE04> { [ 4, guillemotright, U203A, femalesymbol, NoSymbol, NoSymbol, U22A5, NoSymbol ] };
- key <AE05> { [ 5, guillemotleft, U2039, malesymbol, periodcentered, NoSymbol, U2221, NoSymbol ] };
- key <AE06> { [ 6, dollar, cent, U26A5, sterling, NoSymbol, U2225, NoSymbol ] };
-
- key <AE07> { [ 7, EuroSign, yen, U03F0, currency, NoSymbol, rightarrow, NoSymbol ] };
- key <AE08> { [ 8, doublelowquotemark, singlelowquotemark, U27E8, Tab, ISO_Left_Tab, U221E, NoSymbol ] };
- key <AE09> { [ 9, leftdoublequotemark, leftsinglequotemark, U27E9, KP_Divide, KP_Divide, variation, NoSymbol ] };
- key <AE10> { [ 0, rightdoublequotemark, rightsinglequotemark, zerosubscript, KP_Multiply, KP_Multiply, emptyset, NoSymbol ] };
-
- key <AE11> { [ minus, emdash, NoSymbol, U2011, KP_Subtract, KP_Subtract, hyphen, NoSymbol ] };
- key <AE12> { [ dead_grave, dead_cedilla, dead_abovering, dead_dasia, dead_diaeresis, NoSymbol, dead_macron, NoSymbol ] };
-
- // Top row
- // --------------------------------------------------------------
- key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK";
- key <AD01> { [ x, X, ellipsis, Greek_xi, Prior, Prior, Greek_XI, NoSymbol ] };
- key <AD02> { [ v, V, underscore, NoSymbol, BackSpace, BackSpace, radical, NoSymbol ] };
- key <AD03> { [ l, L, bracketleft, Greek_lambda, Up, Up, Greek_LAMBDA, NoSymbol ] };
- key <AD04> { [ c, C, bracketright, Greek_chi, Delete, Delete, U2102, NoSymbol ] };
- key <AD05> { [ w, W, asciicircum, Greek_omega, Next, Next, Greek_OMEGA, NoSymbol ] };
-
- key <AD06> { [ k, K, exclam, Greek_kappa, exclamdown, NoSymbol, multiply, NoSymbol ] };
- key <AD07> { [ h, H, less, Greek_psi, KP_7, KP_7, Greek_PSI, NoSymbol ] };
- key <AD08> { [ g, G, greater, Greek_gamma, KP_8, KP_8, Greek_GAMMA, NoSymbol ] };
- key <AD09> { [ f, F, equal, Greek_phi, KP_9, KP_9, Greek_PHI, NoSymbol ] };
- key <AD10> { [ q, Q, ampersand, U03D5, KP_Add, KP_Add, U211A, NoSymbol ] };
-
- key <AD11> { [ ssharp, U1E9E, U017F, Greek_finalsmallsigma, U2212, NoSymbol, jot, NoSymbol ] };
-
- key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK";
- key <AD12> { [ dead_acute, dead_tilde, dead_stroke, dead_psili, dead_doubleacute, NoSymbol, dead_breve, NoSymbol ] };
-
- // Middle row
- // --------------------------------------------------------------
- key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK";
- key <AC01> { [ u, U, backslash, NoSymbol, Home, Home, includedin, NoSymbol ] };
- key <AC02> { [ i, I, slash, Greek_iota, Left, Left, integral, NoSymbol ] };
- key <AC03> { [ a, A, braceleft, Greek_alpha, Down, Down, U2200, NoSymbol ] };
- key <AC04> { [ e, E, braceright, Greek_epsilon, Right, Right, U2203, NoSymbol ] };
- key <AC05> { [ o, O, asterisk, Greek_omicron, End, End, elementof, NoSymbol ] };
-
- key <AC06> { [ s, S, question, Greek_sigma, questiondown, NoSymbol, Greek_SIGMA, NoSymbol ] };
- key <AC07> { [ n, N, parenleft, Greek_nu, KP_4, KP_4, U2115, NoSymbol ] };
- key <AC08> { [ r, R, parenright, Greek_rho, KP_5, KP_5, U211D, NoSymbol ] };
- key <AC09> { [ t, T, minus, Greek_tau, KP_6, KP_6, partialderivative, NoSymbol ] };
- key <AC10> { [ d, D, colon, Greek_delta, KP_Separator, comma, Greek_DELTA, NoSymbol ] };
-
- key <AC11> { [ y, Y, at, Greek_upsilon, period, KP_Decimal, nabla, NoSymbol ] };
-
- // Bottom row
- // --------------------------------------------------------------
- key <AB01> { [ udiaeresis, Udiaeresis, numbersign, NoSymbol, Escape, Escape, union, NoSymbol ] };
- key <AB02> { [ odiaeresis, Odiaeresis, dollar, U03F5, Tab, Tab, intersection, NoSymbol ] };
- key <AB03> { [ adiaeresis, Adiaeresis, bar, Greek_eta, Insert, Insert, U2135, NoSymbol ] };
- key <AB04> { [ p, P, asciitilde, Greek_pi, Return, Return, Greek_PI, NoSymbol ] };
- key <AB05> { [ z, Z, grave, Greek_zeta, Undo, Undo, U2124, NoSymbol ] };
-
- key <AB06> { [ b, B, plus, Greek_beta, colon, NoSymbol, U21D0, NoSymbol ] };
- key <AB07> { [ m, M, percent, Greek_mu, KP_1, KP_1, ifonlyif, NoSymbol ] };
- key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK";
- key <AB08> { [ comma, endash, quotedbl, U03F1, KP_2, KP_2, U21D2, NoSymbol ] };
- key <AB09> { [ period, enfilledcircbullet, apostrophe, U03D1, KP_3, KP_3, U21A6, NoSymbol ] };
- key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK";
- key <AB10> { [ j, J, semicolon, Greek_theta, semicolon, NoSymbol, Greek_THETA, NoSymbol ] };
- key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK";
-
- // Space key
- // --------------------------------------------------------------
- key <SPCE> { [ space, space, space, nobreakspace, KP_0, KP_0, U202F, NoSymbol ] };
-
-
- // Keypad-keys
- // ===============
-
- // The former Numlock key:
- key <NMLK> { [ Tab, ISO_Left_Tab, equal, approxeq, notequal, Pointer_EnableKeys, identical, NoSymbol ] };
-
- // Topmost row
- // --------------------------------------------------------------
- key <KPDV> { [ KP_Divide, KP_Divide, division, U2300, U2215, NoSymbol, U2223, NoSymbol ] };
- key <KPMU> { [ KP_Multiply, KP_Multiply, U2219, U2299, multiply, NoSymbol, U2297, NoSymbol ] };
- key <KPSU> { [ KP_Subtract, KP_Subtract, U2212, U2296, U2216, NoSymbol, U2238, NoSymbol ] };
-
- // Top row
- // --------------------------------------------------------------
- key <KP7> { [ KP_7, U2714, U2195, U226A, KP_Home, KP_Home, upstile, NoSymbol ] };
- key <KP8> { [ KP_8, U2718, uparrow, intersection, KP_Up, KP_Up, U22C2, NoSymbol ] };
- key <KP9> { [ KP_9, dagger, U20D7, U226B, KP_Prior, KP_Prior, U2309, NoSymbol ] };
- key <KPAD> { [ KP_Add, KP_Add, plusminus, U2295, U2213, NoSymbol, U2214, NoSymbol ] };
-
- // Middle row
- // --------------------------------------------------------------
- key <KP4> { [ KP_4, club, leftarrow, includedin, KP_Left, KP_Left, U2286, NoSymbol ] };
- key <KP5> { [ KP_5, EuroSign, colon, U22B6, KP_Begin, KP_Begin, U22B7, NoSymbol ] };
- key <KP6> { [ KP_6, U2023, rightarrow, includes, KP_Right, KP_Right, U2287, NoSymbol ] };
-
- // Bottom row
- // --------------------------------------------------------------
- key <KP1> { [ KP_1, diamond, U2194, lessthanequal, KP_End, KP_End, downstile, NoSymbol ] };
- key <KP2> { [ KP_2, heart, downarrow, union, KP_Down, KP_Down, U22C3, NoSymbol ] };
- key <KP3> { [ KP_3, U2660, U21CC, greaterthanequal, KP_Next, KP_Next, U230B, NoSymbol ] };
- key <KPEN> { [ KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, NoSymbol ] };
- key <KPEQ> { [ KP_Equal, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] };
-
- // Bottommost row
- // --------------------------------------------------------------
- key <KP0> { [ KP_0, U2423, percent, U2030, KP_Insert, KP_Insert, U25A1, NoSymbol ] };
- key <KPDL> { [ KP_Separator, period, comma, minutes, KP_Delete, KP_Delete, seconds, NoSymbol ] };
-};
-
-partial alphanumeric_keys modifier_keys keypad_keys
-xkb_symbols "neo" {
-
- include "de(neo_base)"
-
- include "shift(both_capslock)"
- include "level3(caps_switch)"
- include "level3(bksl_switch)"
- include "level5(lsgt_switch_lock)"
- include "level5(ralt_switch_lock)"
-};
-
-// Copied from macintosh_vndr/de
-// olh@suse.de very close to MacOS map
-
-partial alphanumeric_keys
-xkb_symbols "mac" {
-
- include "de"
- name[Group1]= "Germany - Macintosh";
-
- // Alphanumeric section
- key <AE01> { [ 1, exclam, exclamdown, at ] };
- key <AE05> { [ 5, percent, bracketleft ] };
- key <AE06> { [ 6, ampersand, bracketright ] };
- key <AE07> { [ 7, slash, bar, backslash ] };
- key <AE08> { [ 8, parenleft, braceleft, asciitilde ] };
- key <AE09> { [ 9, parenright, braceright ] };
- key <AD01> { [ q, Q, guillemotleft, guillemotright ] };
- key <AD04> { [ r, R, registered ] };
- key <AD07> { [ u, U, diaeresis, Aacute ] };
- key <AD08> { [ i, I, slash, Ucircumflex ] };
- key <AD11> { [ udiaeresis, Udiaeresis, periodcentered, degree ] };
- key <AD12> { [ plus, asterisk, asciitilde ] };
- key <AC01> { [ a, A, aring, Aring ] };
- key <AC05> { [ g, G, copyright ] };
- key <AC06> { [ h, H, ordfeminine ] };
- key <AC09> { [ l, L, at ] };
- key <AC10> { [ odiaeresis, Odiaeresis, dead_acute ] };
- key <AB06> { [ n, N, asciitilde ] };
-
-};
-
-partial alphanumeric_keys
-xkb_symbols "mac_nodeadkeys" {
- // modify the standard German mac layout to not have any dead keys
- include "de(mac)"
- name[Group1]= "Germany - Macintosh, eliminate dead keys";
- key <AE04> { [ 4, dollar, onequarter, currency ] };
-
- key <TLDE> { [ asciicircum, degree, notsign ] };
- key <AE12> { [ acute, grave, cedilla ] };
- key <AD11> { [ udiaeresis, Udiaeresis, diaeresis ] };
- key <AD12> { [ plus, asterisk, asciitilde, macron ] };
- key <AC10> { [ odiaeresis, Odiaeresis, acute ] };
- key <AC11> { [ adiaeresis, Adiaeresis, asciicircum ] };
-
- key <BKSL> { [ numbersign, apostrophe, grave ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "dsb"
-{
- name[Group1] = "Germany - Lower Sorbian";
- include "latin(basic)"
- include "level3(ralt_switch)"
- include "kpdl(comma)"
- key <AB01> { [ z, Z, zcaron, Zcaron ] };
- key <AB02> { [ x, X, zacute, Zacute ] };
- key <AB03> { [ c, C, cacute, Cacute ] };
- key <AB04> { [ v, V, ccaron, Ccaron ] };
- key <AB06> { [ n, N, nacute, Nacute ] };
- key <AC02> { [ s, S, sacute, Sacute ] };
- key <AC03> { [ d, D, scaron, Scaron ] };
- key <AC04> { [ f, F ] };
- key <AD01> { [ q, Q ] };
- key <AD02> { [ w, W ] };
- key <AD03> { [ e, E, ecaron, Ecaron ] };
- key <AD04> { [ r, R, racute, Racute ] };
- key <AD05> { [ t, T, U20B5, EuroSign ] };
- key <AD09> { [ o, O, oacute, Oacute ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "dsb_qwertz"
-{
- name[Group1] = "Germany - Lower Sorbian (qwertz)";
- include "latin(basic)"
- include "level3(ralt_switch)"
- include "kpdl(comma)"
- key <AB01> { [ y, Y ] };
- key <AB02> { [ x, X ] };
- key <AB03> { [ c, C, cacute, Cacute ] };
- key <AB04> { [ v, V, ccaron, Ccaron ] };
- key <AB06> { [ n, N, nacute, Nacute ] };
- key <AC02> { [ s, S, sacute, Sacute ] };
- key <AC03> { [ d, D, scaron, Scaron ] };
- key <AC04> { [ f, F ] };
- key <AD01> { [ q, Q ] };
- key <AD02> { [ w, W ] };
- key <AD03> { [ e, E, ecaron, Ecaron ] };
- key <AD04> { [ r, R, racute, Racute ] };
- key <AD05> { [ t, T, U20B5, EuroSign ] };
- key <AD06> { [ z, Z, zcaron, Zcaron ] };
- key <AD07> { [ u, U, zacute, Zacute ] };
- key <AD09> { [ o, O, oacute, Oacute ] };
-};
-
-partial alphanumeric_keys
-xkb_symbols "qwerty" {
-
- // This layout should work exactly as a de with the exception
- // of 'Z' and 'Y' keys, which are in the qwerty style (ie. swapped).
- // 2008 by Matej Košík <kosik@fiit.stuba.sk>
-
- include "de(basic)"
-
- name[Group1] = "Germany - qwerty";
-
- key <AB01> { [ z, Z, leftarrow, yen ] };
- key <AD06> { [ y, Y, guillemotleft, less ] };
-};
+
+// based on a keyboard map from an 'xkb/symbols/de' file
+//
+// $XKeyboardConfig$
+// $XFree86: xc/programs/xkbcomp/symbols/de,v 1.6 2003/09/08 13:12:51 pascal Exp $
+
+default
+xkb_symbols "basic" {
+
+ include "latin(type4)"
+
+ name[Group1]="Germany";
+
+ key <AE02> { [ 2, quotedbl, twosuperior, oneeighth ] };
+ key <AE03> { [ 3, section, threesuperior, sterling ] };
+ key <AE04> { [ 4, dollar, onequarter, currency ] };
+
+ key <AE11> {type[Group1]="FOUR_LEVEL_PLUS_LOCK", symbols[Group1]=
+ [ssharp, question, backslash, questiondown, 0x1001E9E ]};
+// The unicode capital letter sharp s U+1E9E is transformed to "SS"
+// to match the rules for capitalizing sharp s in german.
+// If the capital sharp s is needed, delete the line
+// starting with <U1E9C> from /usr/share/X11/locale/iso8859-15/Compose.
+// If both doubled S and capital sharp s are needed, use 0x1001E9E
+// for capital sharp s and some free unicode codepoint like 0x1001E9C
+// for doubled S. Don`t forget to change this in the Compose file, too.
+
+ key <AE12> { [dead_acute, dead_grave, dead_cedilla, dead_ogonek ] };
+
+ key <AD03> { [ e, E, EuroSign, EuroSign ] };
+ key <AD06> { [ z, Z, leftarrow, yen ] };
+ key <AD11> { [udiaeresis, Udiaeresis, dead_diaeresis, dead_abovering ] };
+ key <AD12> { [ plus, asterisk, dead_tilde, dead_macron ] };
+
+ key <AC02> { [ s, S, U017F, U1E9E ] };
+ key <AC07> { [ j, J, dead_belowdot, dead_abovedot ] };
+ key <AC10> { [odiaeresis, Odiaeresis, dead_doubleacute, dead_belowdot ] };
+ key <AC11> { [adiaeresis, Adiaeresis, dead_circumflex, dead_caron ] };
+ key <TLDE> { [dead_circumflex, degree, U2032, U2033 ] };
+
+ key <BKSL> { [numbersign, apostrophe, rightsinglequotemark, dead_breve ] };
+ key <AB01> { [ y, Y, guillemotright, U203A ] };
+ key <AB02> { [ x, X, guillemotleft, U2039 ] };
+ key <AB04> { [ v, V, doublelowquotemark, singlelowquotemark ] };
+ key <AB05> { [ b, B, leftdoublequotemark, leftsinglequotemark ] };
+ key <AB06> { [ n, N, rightdoublequotemark, rightsinglequotemark ] };
+ key <AB08> { [ comma, semicolon, periodcentered, multiply ] };
+ key <AB09> { [ period, colon, U2026, division ] };
+ key <AB10> { [ minus, underscore, endash, emdash ] };
+
+ include "kpdl(comma)"
+
+ include "level3(ralt_switch)"
+};
+
+partial alphanumeric_keys
+xkb_symbols "nodeadkeys" {
+
+ // modify the basic German layout to not have any dead keys
+
+ include "de(basic)"
+ name[Group1]="Germany - Eliminate dead keys";
+
+ key <TLDE> { [asciicircum, degree, notsign, notsign ] };
+ key <AE12> { [ acute, grave, cedilla, cedilla ] };
+ key <AD11> { [udiaeresis, Udiaeresis, diaeresis, diaeresis ] };
+ key <AD12> { [ plus, asterisk, asciitilde, macron ] };
+ key <AC10> { [odiaeresis, Odiaeresis, doubleacute, doubleacute ] };
+ key <AC11> { [adiaeresis, Adiaeresis, asciicircum, asciicircum ] };
+ key <BKSL> { [numbersign, apostrophe, grave, grave ] };
+ key <AB10> { [ minus, underscore, dead_belowdot, abovedot ] };
+};
+
+partial alphanumeric_keys
+xkb_symbols "deadgraveacute" {
+ // modify the basic German layout to have only acute and grave
+ // as dead keys (tilde and circumflex are needed as spacing characters
+ // in many programming languages)
+
+ include "de(basic)"
+ name[Group1]="Germany - Dead grave acute";
+
+ key <TLDE> { [asciicircum, degree, notsign, notsign ] };
+ key <AD12> { [ plus, asterisk, asciitilde, dead_macron ] };
+ key <BKSL> { [numbersign, apostrophe, grave, grave ] };
+};
+
+partial alphanumeric_keys
+xkb_symbols "deadacute" {
+ // modify the basic German layout to have only acute as
+ // dead keys (ASCII grave, tilde and circumflex are needed as
+ // spacing characters in many programming languages and text formatters)
+
+ include "de(deadgraveacute)"
+
+ name[Group1]="Germany - Dead acute";
+
+ key <AE12> { [dead_acute, grave, dead_cedilla, dead_ogonek ] };
+ key <BKSL> { [numbersign, apostrophe, dead_grave, dead_grave ] };
+};
+
+partial alphanumeric_keys
+xkb_symbols "ro" {
+ // add romanian-specific letters to the basic German layout.
+ // Romanian symbols are accessible with combination of <AltGr> and
+ // 'a', 's', 't', 'i', 'ä (&auml)' (+<Shift> for capital letters).
+ // To view romanian-specific symbols, add "export LC_CTYPE=ro_RO"
+ // or "export LC_CTYPE=de_DE.utf8" to your .profile.
+
+ include "de(basic)"
+
+ name[Group1]="Germany - Romanian keyboard with German letters";
+
+ key <AD05> { [ t, T, tcedilla, Tcedilla ] };
+ key <AD08> { [ i, I, icircumflex, Icircumflex ] };
+ key <AC01> { [ a, A, acircumflex, Acircumflex ] };
+ key <AC02> { [ s, S, scedilla, Scedilla ] };
+ key <AC11> { [ adiaeresis, Adiaeresis, abreve, Abreve ] };
+};
+
+partial alphanumeric_keys
+xkb_symbols "ro_nodeadkeys" {
+ // add romanian-specific letters to the German nodeadkeys layout.
+ // Read the comment for de_ro !
+
+ include "de(nodeadkeys)"
+ name[Group1]="Germany - Romanian keyboard with German letters, eliminate dead keys";
+
+ key <AD05> { [ t, T, tcedilla, Tcedilla ] };
+ key <AD08> { [ i, I, icircumflex, Icircumflex ] };
+ key <AC01> { [ a, A, acircumflex, Acircumflex ] };
+ key <AC02> { [ s, S, scedilla, Scedilla ] };
+ key <AC11> { [ adiaeresis, Adiaeresis, abreve, Abreve ] };
+};
+
+// German Dvorak keymap by Thorsten Staerk (www.staerk.de/thorsten)
+// Have acute and grave as dead keys, tilde and circumflex alive as they are needed
+// in many programming languages.
+// to use this keymap, use a 105-key-keyboard and the command setxkbmap -model pc105 -layout dvorak -variant de
+// source: http://www-lehre.informatik.uni-osnabrueck.de/~rfreund/dvorak.php
+partial alphanumeric_keys
+xkb_symbols "dvorak" {
+ include "us(dvorak)"
+
+ name[Group1]="Germany - Dvorak";
+
+ key <TLDE> { [ asciicircum, degree ] };
+
+ key <AE01> { [ 1, exclam, onesuperior ] };
+ key <AE02> { [ 2, quotedbl, twosuperior ] };
+ key <AE03> { [ 3, section, threesuperior ] };
+ key <AE04> { [ 4, dollar, bar ] };
+ key <AE05> { [ 5, percent, bar ] };
+ key <AE06> { [ 6, ampersand, brokenbar ] };
+ key <AE07> { [ 7, slash, braceleft ] };
+ key <AE08> { [ 8, parenleft, bracketleft ] };
+ key <AE09> { [ 9, parenright, bracketright ] };
+ key <AE10> { [ 0, equal, braceright ] };
+ key <AE11> { [ plus, asterisk, asciitilde ] };
+ key <AE12> { [ less, greater, dead_grave ] };
+
+ key <AD01> { [ udiaeresis, Udiaeresis, at ] };
+ key <AD02> { [ comma, semicolon, dead_diaeresis ] };
+ key <AD03> { [ period, colon ] };
+ key <AD08> { [ c, C, copyright, Cacute ] };
+ key <AD09> { [ t, T, trademark ] };
+ key <AD10> { [ z, Z, zabovedot, Zabovedot ] };
+ key <AD11> { [ question, ssharp ] };
+ key <AD12> { [ slash, backslash, dead_acute ] };
+
+ key <AC01> { [ a, A, at, aogonek ] };
+ key <AC02> { [ o, O, oacute, Oacute ] };
+ key <AC03> { [ e, E, EuroSign, eogonek ] };
+ key <AC04> { [ i, I ] };
+ key <AC05> { [ u, U ] };
+ key <AC06> { [ h, H ] };
+ key <AC07> { [ d, D ] };
+ key <AC08> { [ r, R, registered ] };
+ key <AC09> { [ n, N, nacute, Nacute ] };
+ key <AC10> { [ s, S, sacute, Sacute] };
+ key <AC11> { [ l, L, lstroke, Lstroke ] };
+
+ key <AB01> { [ odiaeresis, Odiaeresis ] };
+ key <AB02> { [ q, Q, at ] };
+ key <AB07> { [ m, M, mu ] };
+ key <AB10> { [ numbersign, apostrophe ] };
+
+ key <BKSL> { [ minus, underscore, hyphen, diaeresis] };
+
+ key <LSGT> { [ adiaeresis, Adiaeresis, bar ] };
+
+ include "level3(ralt_switch)"
+};
+
+partial alphanumeric_keys
+xkb_symbols "Sundeadkeys" {
+
+ // For naming consistency
+
+ include "de(basic)"
+
+};
+
+partial alphanumeric_keys
+xkb_symbols "sundeadkeys" {
+
+ // For naming consistency
+
+ include "de(Sundeadkeys)"
+
+ name[Group1]="Germany - Sun dead keys";
+};
+
+
+// German Neo-Layout Version 2
+// adopted 2004 by Hanno Behrens <Hanno.Behrens@gmx.de>
+// inspired by Dvorak/de-ergo http://www.goebel-consult.de/de-ergo/
+//
+// Authors:
+// Stephan Hilb <stephan at ehilb dot de>
+// <lucky at zankt dot net>
+// Benjamin Kellermann <Benjamin dot Kellermann at gmx dot Germany>
+// Erik Streb <mail at erikstreb dot de>
+// and many other contributors
+//
+// http://www.neo-layout.org
+//
+// $Revision$, $Date$
+
+partial alphanumeric_keys modifier_keys keypad_keys
+xkb_symbols "neo_base" {
+
+ name[Group1]= "Germany - Neo 2";
+
+ // Levels in Neo jargon
+ // --------------------------------------------------------------
+ // Ebene 1: normal
+ // Ebene 2: Shift
+ // Ebene 3: Mod3
+ // Ebene 4: Mod4 (for marking something use Shift + Mod4)
+ // Ebene 5: Shift + Mod3
+ // Ebene 6: Mod3 + Mod4
+ // Compose (not a level): Mod3 + Tab
+ // Feststelltaste (Capslock): Shift + Shift
+ // Mod4-Lock: Mod4 + Mod4
+ // Mod4-Lock: Shift + Mod3 + Tab
+
+ // Legend
+ // ===============
+ // Levels in Xkbmap jargon to be found here in the definitions.
+ // These are the levels used, and Xorg's translations:
+ // --------------------------------------------------------------
+ // Xorg: Level1 Level2 Level3 Level4 Level5 Level6 Level7 Level8
+ // Neo: Ebene1 Ebene2 Ebene3 Ebene5 Ebene4 Pseudo-Ebene Ebene6 ???
+ // Keys (Neo): None Shift Mod3 Mod3 + Shift Mod4 Mod4 + Shift Mod3 + Mod4 Mod3 + Mod4 + Shift
+
+
+ // Alphanumeric-keys
+ // ===============
+ key.type[Group1] = "EIGHT_LEVEL";
+
+ // Tab as Multi_key (Compose)
+ // --------------------------------------------------------------
+ key <TAB> { [ Tab, ISO_Left_Tab, Multi_key, ISO_Level5_Lock, NoSymbol, NoSymbol, NoSymbol, ISO_Level5_Lock ] };
+
+
+ // Number row
+ // --------------------------------------------------------------
+ key <TLDE> { [ dead_circumflex, dead_caron, U21BB, U02DE, dead_abovedot, Pointer_EnableKeys, dead_belowdot, NoSymbol ] };
+
+ key <AE01> { [ 1, degree, onesuperior, onesubscript, ordfeminine, NoSymbol, notsign, NoSymbol ] };
+ key <AE02> { [ 2, section, twosuperior, twosubscript, masculine, NoSymbol, logicalor, NoSymbol ] };
+ key <AE03> { [ 3, U2113, threesuperior, threesubscript, numerosign, NoSymbol, logicaland, NoSymbol ] };
+ key <AE04> { [ 4, guillemotright, U203A, femalesymbol, NoSymbol, NoSymbol, U22A5, NoSymbol ] };
+ key <AE05> { [ 5, guillemotleft, U2039, malesymbol, periodcentered, NoSymbol, U2221, NoSymbol ] };
+ key <AE06> { [ 6, dollar, cent, U26A5, sterling, NoSymbol, U2225, NoSymbol ] };
+
+ key <AE07> { [ 7, EuroSign, yen, U03F0, currency, NoSymbol, rightarrow, NoSymbol ] };
+ key <AE08> { [ 8, doublelowquotemark, singlelowquotemark, U27E8, Tab, ISO_Left_Tab, U221E, NoSymbol ] };
+ key <AE09> { [ 9, leftdoublequotemark, leftsinglequotemark, U27E9, KP_Divide, KP_Divide, variation, NoSymbol ] };
+ key <AE10> { [ 0, rightdoublequotemark, rightsinglequotemark, zerosubscript, KP_Multiply, KP_Multiply, emptyset, NoSymbol ] };
+
+ key <AE11> { [ minus, emdash, NoSymbol, U2011, KP_Subtract, KP_Subtract, hyphen, NoSymbol ] };
+ key <AE12> { [ dead_grave, dead_cedilla, dead_abovering, dead_dasia, dead_diaeresis, NoSymbol, dead_macron, NoSymbol ] };
+
+ // Top row
+ // --------------------------------------------------------------
+ key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC";
+ key <AD01> { [ x, X, ellipsis, Greek_xi, Prior, Prior, Greek_XI, NoSymbol ] };
+ key <AD02> { [ v, V, underscore, NoSymbol, BackSpace, BackSpace, radical, NoSymbol ] };
+ key <AD03> { [ l, L, bracketleft, Greek_lambda, Up, Up, Greek_LAMBDA, NoSymbol ] };
+ key <AD04> { [ c, C, bracketright, Greek_chi, Delete, Delete, U2102, NoSymbol ] };
+ key <AD05> { [ w, W, asciicircum, Greek_omega, Next, Next, Greek_OMEGA, NoSymbol ] };
+
+ key <AD06> { [ k, K, exclam, Greek_kappa, exclamdown, NoSymbol, multiply, NoSymbol ] };
+ key <AD07> { [ h, H, less, Greek_psi, KP_7, KP_7, Greek_PSI, NoSymbol ] };
+ key <AD08> { [ g, G, greater, Greek_gamma, KP_8, KP_8, Greek_GAMMA, NoSymbol ] };
+ key <AD09> { [ f, F, equal, Greek_phi, KP_9, KP_9, Greek_PHI, NoSymbol ] };
+ key <AD10> { [ q, Q, ampersand, U03D5, KP_Add, KP_Add, U211A, NoSymbol ] };
+
+ key <AD11> { [ ssharp, U1E9E, U017F, Greek_finalsmallsigma, U2212, NoSymbol, jot, NoSymbol ] };
+
+ key.type[Group1] = "EIGHT_LEVEL";
+ key <AD12> { [ dead_acute, dead_tilde, dead_stroke, dead_psili, dead_doubleacute, NoSymbol, dead_breve, NoSymbol ] };
+
+ // Middle row
+ // --------------------------------------------------------------
+ key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC";
+ key <AC01> { [ u, U, backslash, NoSymbol, Home, Home, includedin, NoSymbol ] };
+ key <AC02> { [ i, I, slash, Greek_iota, Left, Left, integral, NoSymbol ] };
+ key <AC03> { [ a, A, braceleft, Greek_alpha, Down, Down, U2200, NoSymbol ] };
+ key <AC04> { [ e, E, braceright, Greek_epsilon, Right, Right, U2203, NoSymbol ] };
+ key <AC05> { [ o, O, asterisk, Greek_omicron, End, End, elementof, NoSymbol ] };
+
+ key <AC06> { [ s, S, question, Greek_sigma, questiondown, NoSymbol, Greek_SIGMA, NoSymbol ] };
+ key <AC07> { [ n, N, parenleft, Greek_nu, KP_4, KP_4, U2115, NoSymbol ] };
+ key <AC08> { [ r, R, parenright, Greek_rho, KP_5, KP_5, U211D, NoSymbol ] };
+ key <AC09> { [ t, T, minus, Greek_tau, KP_6, KP_6, partialderivative, NoSymbol ] };
+ key <AC10> { [ d, D, colon, Greek_delta, KP_Separator, comma, Greek_DELTA, NoSymbol ] };
+
+ key <AC11> { [ y, Y, at, Greek_upsilon, period, KP_Decimal, nabla, NoSymbol ] };
+
+ // Bottom row
+ // --------------------------------------------------------------
+ key <AB01> { [ udiaeresis, Udiaeresis, numbersign, NoSymbol, Escape, Escape, union, NoSymbol ] };
+ key <AB02> { [ odiaeresis, Odiaeresis, dollar, U03F5, Tab, Tab, intersection, NoSymbol ] };
+ key <AB03> { [ adiaeresis, Adiaeresis, bar, Greek_eta, Insert, Insert, U2135, NoSymbol ] };
+ key <AB04> { [ p, P, asciitilde, Greek_pi, Return, Return, Greek_PI, NoSymbol ] };
+ key <AB05> { [ z, Z, grave, Greek_zeta, Undo, Undo, U2124, NoSymbol ] };
+
+ key <AB06> { [ b, B, plus, Greek_beta, colon, NoSymbol, U21D0, NoSymbol ] };
+ key <AB07> { [ m, M, percent, Greek_mu, KP_1, KP_1, ifonlyif, NoSymbol ] };
+ key.type[Group1] = "EIGHT_LEVEL";
+ key <AB08> { [ comma, endash, quotedbl, U03F1, KP_2, KP_2, U21D2, NoSymbol ] };
+ key <AB09> { [ period, enfilledcircbullet, apostrophe, U03D1, KP_3, KP_3, U21A6, NoSymbol ] };
+ key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC";
+ key <AB10> { [ j, J, semicolon, Greek_theta, semicolon, NoSymbol, Greek_THETA, NoSymbol ] };
+ key.type[Group1] = "EIGHT_LEVEL";
+
+ // Space key
+ // --------------------------------------------------------------
+ key <SPCE> { [ space, space, space, nobreakspace, KP_0, KP_0, U202F, NoSymbol ] };
+
+
+ // Keypad-keys
+ // ===============
+
+ // The former Numlock key:
+ key <NMLK> { [ Tab, ISO_Left_Tab, equal, approxeq, notequal, Pointer_EnableKeys, identical, NoSymbol ] };
+
+ // Topmost row
+ // --------------------------------------------------------------
+ key <KPDV> { [ KP_Divide, KP_Divide, division, U2300, U2215, NoSymbol, U2223, NoSymbol ] };
+ key <KPMU> { [ KP_Multiply, KP_Multiply, U2219, U2299, multiply, NoSymbol, U2297, NoSymbol ] };
+ key <KPSU> { [ KP_Subtract, KP_Subtract, U2212, U2296, U2216, NoSymbol, U2238, NoSymbol ] };
+
+ // Top row
+ // --------------------------------------------------------------
+ key <KP7> { [ KP_7, U2714, U2195, U226A, KP_Home, KP_Home, upstile, NoSymbol ] };
+ key <KP8> { [ KP_8, U2718, uparrow, intersection, KP_Up, KP_Up, U22C2, NoSymbol ] };
+ key <KP9> { [ KP_9, dagger, U20D7, U226B, KP_Prior, KP_Prior, U2309, NoSymbol ] };
+ key <KPAD> { [ KP_Add, KP_Add, plusminus, U2295, U2213, NoSymbol, U2214, NoSymbol ] };
+
+ // Middle row
+ // --------------------------------------------------------------
+ key <KP4> { [ KP_4, club, leftarrow, includedin, KP_Left, KP_Left, U2286, NoSymbol ] };
+ key <KP5> { [ KP_5, EuroSign, colon, U22B6, KP_Begin, KP_Begin, U22B7, NoSymbol ] };
+ key <KP6> { [ KP_6, U2023, rightarrow, includes, KP_Right, KP_Right, U2287, NoSymbol ] };
+
+ // Bottom row
+ // --------------------------------------------------------------
+ key <KP1> { [ KP_1, diamond, U2194, lessthanequal, KP_End, KP_End, downstile, NoSymbol ] };
+ key <KP2> { [ KP_2, heart, downarrow, union, KP_Down, KP_Down, U22C3, NoSymbol ] };
+ key <KP3> { [ KP_3, U2660, U21CC, greaterthanequal, KP_Next, KP_Next, U230B, NoSymbol ] };
+ key <KPEN> { [ KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, NoSymbol ] };
+ key <KPEQ> { [ KP_Equal, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] };
+
+ // Bottommost row
+ // --------------------------------------------------------------
+ key <KP0> { [ KP_0, U2423, percent, U2030, KP_Insert, KP_Insert, U25A1, NoSymbol ] };
+ key <KPDL> { [ KP_Separator, period, comma, minutes, KP_Delete, KP_Delete, seconds, NoSymbol ] };
+};
+
+partial alphanumeric_keys modifier_keys keypad_keys
+xkb_symbols "neo" {
+
+ include "de(neo_base)"
+
+ include "shift(both_capslock)"
+ include "level3(caps_switch)"
+ include "level3(bksl_switch)"
+ include "level5(lsgt_switch)"
+ include "level5(ralt_switch)"
+};
+
+// Copied from macintosh_vndr/de
+// olh@suse.de very close to MacOS map
+
+partial alphanumeric_keys
+xkb_symbols "mac" {
+
+ include "de"
+ name[Group1]= "Germany - Macintosh";
+
+ // Alphanumeric section
+ key <AE01> { [ 1, exclam, exclamdown, at ] };
+ key <AE05> { [ 5, percent, bracketleft ] };
+ key <AE06> { [ 6, ampersand, bracketright ] };
+ key <AE07> { [ 7, slash, bar, backslash ] };
+ key <AE08> { [ 8, parenleft, braceleft, asciitilde ] };
+ key <AE09> { [ 9, parenright, braceright ] };
+ key <AD01> { [ q, Q, guillemotleft, guillemotright ] };
+ key <AD04> { [ r, R, registered ] };
+ key <AD07> { [ u, U, diaeresis, Aacute ] };
+ key <AD08> { [ i, I, slash, Ucircumflex ] };
+ key <AD11> { [ udiaeresis, Udiaeresis, periodcentered, degree ] };
+ key <AD12> { [ plus, asterisk, asciitilde ] };
+ key <AC01> { [ a, A, aring, Aring ] };
+ key <AC05> { [ g, G, copyright ] };
+ key <AC06> { [ h, H, ordfeminine ] };
+ key <AC09> { [ l, L, at ] };
+ key <AC10> { [ odiaeresis, Odiaeresis, dead_acute ] };
+ key <AB06> { [ n, N, asciitilde ] };
+
+};
+
+partial alphanumeric_keys
+xkb_symbols "mac_nodeadkeys" {
+ // modify the standard German mac layout to not have any dead keys
+ include "de(mac)"
+ name[Group1]= "Germany - Macintosh, eliminate dead keys";
+ key <AE04> { [ 4, dollar, onequarter, currency ] };
+
+ key <TLDE> { [ asciicircum, degree, notsign ] };
+ key <AE12> { [ acute, grave, cedilla ] };
+ key <AD11> { [ udiaeresis, Udiaeresis, diaeresis ] };
+ key <AD12> { [ plus, asterisk, asciitilde, macron ] };
+ key <AC10> { [ odiaeresis, Odiaeresis, acute ] };
+ key <AC11> { [ adiaeresis, Adiaeresis, asciicircum ] };
+
+ key <BKSL> { [ numbersign, apostrophe, grave ] };
+};
+
+partial alphanumeric_keys
+xkb_symbols "dsb"
+{
+ name[Group1] = "Germany - Lower Sorbian";
+ include "latin(basic)"
+ include "level3(ralt_switch)"
+ include "kpdl(comma)"
+ key <AB01> { [ z, Z, zcaron, Zcaron ] };
+ key <AB02> { [ x, X, zacute, Zacute ] };
+ key <AB03> { [ c, C, cacute, Cacute ] };
+ key <AB04> { [ v, V, ccaron, Ccaron ] };
+ key <AB06> { [ n, N, nacute, Nacute ] };
+ key <AC02> { [ s, S, sacute, Sacute ] };
+ key <AC03> { [ d, D, scaron, Scaron ] };
+ key <AC04> { [ f, F ] };
+ key <AD01> { [ q, Q ] };
+ key <AD02> { [ w, W ] };
+ key <AD03> { [ e, E, ecaron, Ecaron ] };
+ key <AD04> { [ r, R, racute, Racute ] };
+ key <AD05> { [ t, T, U20B5, EuroSign ] };
+ key <AD09> { [ o, O, oacute, Oacute ] };
+};
+
+partial alphanumeric_keys
+xkb_symbols "dsb_qwertz"
+{
+ name[Group1] = "Germany - Lower Sorbian (qwertz)";
+ include "latin(basic)"
+ include "level3(ralt_switch)"
+ include "kpdl(comma)"
+ key <AB01> { [ y, Y ] };
+ key <AB02> { [ x, X ] };
+ key <AB03> { [ c, C, cacute, Cacute ] };
+ key <AB04> { [ v, V, ccaron, Ccaron ] };
+ key <AB06> { [ n, N, nacute, Nacute ] };
+ key <AC02> { [ s, S, sacute, Sacute ] };
+ key <AC03> { [ d, D, scaron, Scaron ] };
+ key <AC04> { [ f, F ] };
+ key <AD01> { [ q, Q ] };
+ key <AD02> { [ w, W ] };
+ key <AD03> { [ e, E, ecaron, Ecaron ] };
+ key <AD04> { [ r, R, racute, Racute ] };
+ key <AD05> { [ t, T, U20B5, EuroSign ] };
+ key <AD06> { [ z, Z, zcaron, Zcaron ] };
+ key <AD07> { [ u, U, zacute, Zacute ] };
+ key <AD09> { [ o, O, oacute, Oacute ] };
+};
+
+partial alphanumeric_keys
+xkb_symbols "qwerty" {
+
+ // This layout should work exactly as a de with the exception
+ // of 'Z' and 'Y' keys, which are in the qwerty style (ie. swapped).
+ // 2008 by Matej Košík <kosik@fiit.stuba.sk>
+
+ include "de(basic)"
+
+ name[Group1] = "Germany - qwerty";
+
+ key <AB01> { [ z, Z, leftarrow, yen ] };
+ key <AD06> { [ y, Y, guillemotleft, less ] };
+};
diff --git a/xorg-server/xkbdata.src/symbols/ke b/xorg-server/xkbdata.src/symbols/ke
index 71629b0c4..5ec174b7e 100644
--- a/xorg-server/xkbdata.src/symbols/ke
+++ b/xorg-server/xkbdata.src/symbols/ke
@@ -5,9 +5,40 @@
// Please notify any corrections or omissions to
// Kevin Donnelly (kevin@dotmon.com)
-partial default alphanumeric_keys
+partial default alphanumeric_keys
xkb_symbols "swa" {
- include "tz(swa)"
- name[Group1]= "Kenya";
+ include "us"
+
+ name[Group1]= "Kenya";
+
+ key <AC10> { [ semicolon, colon, 0x01000324, 0x01000324 ] }; //COMBINING DIAERESIS BELOW
+ key <AC11> { [apostrophe, quotedbl, 0x01000301, 0x01000308 ] }; //COMBINING ACUTE ACCENT, COMBINING DIAERESIS
+ key <TLDE> { [ grave, asciitilde, 0x01000300, 0x01000303 ] }; //COMBINING GRAVE ACCENT, COMBINING TILDE
+ key <AE06> { [ 6, asciicircum, 0x01000302 ] }; //COMBINING CIRCUMFLEX ACCENT
+ key <AE08> { [ 8, asterisk, 0x01000307, 0x01000323 ] }; //COMBINING DOT ABOVE, COMBINING DOT BELOW
+ key <AE09> { [ 9, parenleft, 0x01000306 ] }; //COMBINING BREVE
+ key <AE10> { [ 0, parenright, 0x0100030c ] }; //COMBINING CARON
+ key <AE11> { [ minus, underscore, 0x01000304, 0x01000331 ] }; //COMBINING MACRON,COMBINING MACRON BELOW
+
+ include "level3(ralt_switch)"
+};
+
+partial alphanumeric_keys
+xkb_symbols "kik" {
+
+ include "us"
+
+ name[Group1]= "Kenya - Kikuyu";
+
+ key <AC10> { [ semicolon, colon, 0x01000324, 0x01000324 ] }; //COMBINING DIAERESIS BELOW
+ key <AC11> { [apostrophe, quotedbl, 0x01000301, 0x01000308 ] }; //COMBINING ACUTE ACCENT, COMBINING DIAERESIS
+ key <TLDE> { [ grave, asciitilde, 0x01000300, 0x01000303 ] }; //COMBINING GRAVE ACCENT, COMBINING TILDE
+ key <AE06> { [ 6, asciicircum, 0x01000302 ] }; //COMBINING CIRCUMFLEX ACCENT
+ key <AE08> { [ 8, asterisk, 0x01000307, 0x01000323 ] }; //COMBINING DOT ABOVE, COMBINING DOT BELOW
+ key <AE09> { [ 9, parenleft, 0x01000306 ] }; //COMBINING BREVE
+ key <AE10> { [ 0, parenright, 0x0100030c ] }; //COMBINING CARON
+ key <AE11> { [ minus, underscore, 0x01000304, 0x01000331 ] }; //COMBINING MACRON,COMBINING MACRON BELOW
+
+ include "level3(ralt_switch)"
};
diff --git a/xorg-server/xkbdata.src/symbols/level5 b/xorg-server/xkbdata.src/symbols/level5
index 19db36ccd..99cb4601c 100644
--- a/xorg-server/xkbdata.src/symbols/level5
+++ b/xorg-server/xkbdata.src/symbols/level5
@@ -1,132 +1,151 @@
-// $XKeyboardConfig$
-
-// these variants assign various XKB keycodes to ISO_Level5_Shift so that
-// the third shift level can be reached
-//
-// $XFree86: xc/programs/xkbcomp/symbols/level3,v 1.7 2003/09/08 14:25:32 eich Exp $
-//
-
-// using the level(switch) map, the right Control key temporarily
-// chooses the fifth shift level (until it is released).
-partial modifier_keys
-xkb_symbols "rctrl_switch" {
- key <RCTL> {
- type[Group1]="ONE_LEVEL",
- symbols[Group1] = [ ISO_Level5_Shift ]
- };
- modifier_map Mod3 { ISO_Level5_Shift };
-};
-
-// The following modifier keys are used to switch to the third shift and to set a
-// corresponding lock, implemented as NumLock.
-
-partial modifier_keys
-xkb_symbols "lock" {
- // This adds the definitions needed to create a level5-lock behaviour, using
- // the real modifier NumLock as a lock indicator.
- // See also: types/level5 : EIGHT_LEVEL_LEVEL_FIVE_LOCK
- // See also: compat/level5(level5_lock)
- key.type[Group1] = "ONE_LEVEL";
-
- replace key <MDSW> {
- vmods = LevelFive,
- symbols[Group1] = [ ISO_Level5_Shift ],
- actions[Group1] = [ SetMods(modifiers=LevelFive) ]
- };
- modifier_map Mod3 { <MDSW> };
-
- replace key <HYPR> {
- vmods = NumLock,
- symbols[Group1] = [ NoSymbol ],
- actions[Group1] = [ SetMods(modifiers=NumLock) ]
- };
- modifier_map Mod2 { <HYPR> };
-};
-
-partial modifier_keys
-xkb_symbols "lsgt_switch_lock" {
-
- include "level5(lock)"
-
- key <LSGT> {
- type[Group1] = "EIGHT_LEVEL",
- symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
- };
-};
-
-partial modifier_keys
-xkb_symbols "lwin_switch_lock" {
-
- include "level5(lock)"
-
- key <LWIN> {
- type[Group1] = "EIGHT_LEVEL",
- symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
- };
-};
-
-partial modifier_keys
-xkb_symbols "ralt_switch_lock" {
-
- include "level5(lock)"
-
- key <RALT> {
- type[Group1] = "EIGHT_LEVEL",
- symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
- };
-};
-
-partial modifier_keys
-xkb_symbols "rwin_switch_lock" {
-
- include "level5(lock)"
-
- key <RWIN> {
- type[Group1] = "EIGHT_LEVEL",
- symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
- };
-};
-
-partial modifier_keys
-xkb_symbols "lsgt_switch_lock_cancel" {
-
- include "level5(lock)"
-
- key <LSGT> {
- type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK",
- symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
- };
-};
-
-partial modifier_keys
-xkb_symbols "lwin_switch_lock_cancel" {
-
- include "level5(lock)"
-
- key <LWIN> {
- type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK",
- symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
- };
-};
-
-partial modifier_keys
-xkb_symbols "ralt_switch_lock_cancel" {
-
- include "level5(lock)"
-
- key <RALT> {
- type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK",
- symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
- };
-};
-
-partial modifier_keys
-xkb_symbols "rwin_switch_lock_cancel" {
-
- include "level5(lock)"
-
- key <RWIN> {
- type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK",
- symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
- };
-};
+// $XKeyboardConfig$
+
+// these variants assign various XKB keycodes to ISO_Level5_Shift so that
+// the third shift level can be reached
+//
+// $XFree86: xc/programs/xkbcomp/symbols/level3,v 1.7 2003/09/08 14:25:32 eich Exp $
+//
+
+// using the level(switch) map, the right Control key temporarily
+// chooses the fifth shift level (until it is released).
+partial modifier_keys
+xkb_symbols "rctrl_switch" {
+ key <RCTL> {
+ type[Group1]="ONE_LEVEL",
+ symbols[Group1] = [ ISO_Level5_Shift ]
+ };
+ modifier_map Mod3 { ISO_Level5_Shift };
+};
+
+partial modifier_keys
+xkb_symbols "lsgt_switch" {
+ key <LSGT> {
+ type[Group1]="ONE_LEVEL",
+ symbols[Group1] = [ ISO_Level5_Shift ]
+ };
+ modifier_map Mod3 { ISO_Level5_Shift };
+};
+
+partial modifier_keys
+xkb_symbols "ralt_switch" {
+ key <RALT> {
+ type[Group1]="ONE_LEVEL",
+ symbols[Group1] = [ ISO_Level5_Shift ]
+ };
+ modifier_map Mod3 { ISO_Level5_Shift };
+};
+
+
+// The following modifier keys are used to switch to the third shift and to set a
+// corresponding lock, implemented as NumLock.
+
+partial modifier_keys
+xkb_symbols "lock" {
+ // This adds the definitions needed to create a level5-lock behaviour, using
+ // the real modifier NumLock as a lock indicator.
+ // See also: types/level5 : EIGHT_LEVEL_LEVEL_FIVE_LOCK
+ // See also: compat/level5(level5_lock)
+ key.type[Group1] = "ONE_LEVEL";
+
+ replace key <MDSW> {
+ vmods = LevelFive,
+ symbols[Group1] = [ ISO_Level5_Shift ],
+ actions[Group1] = [ SetMods(modifiers=LevelFive) ]
+ };
+ modifier_map Mod3 { <MDSW> };
+
+ replace key <HYPR> {
+ vmods = NumLock,
+ symbols[Group1] = [ NoSymbol ],
+ actions[Group1] = [ SetMods(modifiers=NumLock) ]
+ };
+ modifier_map Mod2 { <HYPR> };
+};
+
+partial modifier_keys
+xkb_symbols "lsgt_switch_lock" {
+
+ include "level5(lock)"
+
+ key <LSGT> {
+ type[Group1] = "EIGHT_LEVEL",
+ symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
+ };
+};
+
+partial modifier_keys
+xkb_symbols "lwin_switch_lock" {
+
+ include "level5(lock)"
+
+ key <LWIN> {
+ type[Group1] = "EIGHT_LEVEL",
+ symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
+ };
+};
+
+partial modifier_keys
+xkb_symbols "ralt_switch_lock" {
+
+ include "level5(lock)"
+
+ key <RALT> {
+ type[Group1] = "EIGHT_LEVEL",
+ symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
+ };
+};
+
+partial modifier_keys
+xkb_symbols "rwin_switch_lock" {
+
+ include "level5(lock)"
+
+ key <RWIN> {
+ type[Group1] = "EIGHT_LEVEL",
+ symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
+ };
+};
+
+partial modifier_keys
+xkb_symbols "lsgt_switch_lock_cancel" {
+
+ include "level5(lock)"
+
+ key <LSGT> {
+ type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK",
+ symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
+ };
+};
+
+partial modifier_keys
+xkb_symbols "lwin_switch_lock_cancel" {
+
+ include "level5(lock)"
+
+ key <LWIN> {
+ type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK",
+ symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
+ };
+};
+
+partial modifier_keys
+xkb_symbols "ralt_switch_lock_cancel" {
+
+ include "level5(lock)"
+
+ key <RALT> {
+ type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK",
+ symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
+ };
+};
+
+partial modifier_keys
+xkb_symbols "rwin_switch_lock_cancel" {
+
+ include "level5(lock)"
+
+ key <RWIN> {
+ type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK",
+ symbols[Group1] = [ ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Shift, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock, ISO_Level5_Lock ]
+ };
+};
diff --git a/xorg-server/xkbdata.src/xkeyboard-config.pc.in b/xorg-server/xkbdata.src/xkeyboard-config.pc.in
new file mode 100644
index 000000000..d44ba1482
--- /dev/null
+++ b/xorg-server/xkbdata.src/xkeyboard-config.pc.in
@@ -0,0 +1,8 @@
+prefix=@prefix@
+datarootdir=@datarootdir@
+datadir=@datadir@
+xkb_base=@xkb_base@
+
+Name: XKeyboardConfig
+Description: X Keyboard configuration data
+Version: @VERSION@