From 4b4ee0dc63abddffdc64355429e4ea9ccaa4d36d Mon Sep 17 00:00:00 2001 From: marha Date: Sun, 9 May 2010 21:30:23 +0000 Subject: svn merge -r577:HEAD ^/branches/released . --- xorg-server/Xext/xf86bigfont.c | 1528 +++-- xorg-server/Xi/extinit.c | 2621 ++++----- xorg-server/Xi/xiproperty.c | 2717 ++++----- xorg-server/Xi/xiproperty.h | 133 +- xorg-server/dix/dispatch.c | 26 +- xorg-server/dix/dixutils.c | 1786 +++--- xorg-server/glx/xfont.c | 397 +- xorg-server/hw/dmx/dmxpict.c | 2630 +++++---- xorg-server/hw/xquartz/bundle/Makefile.am | 176 +- xorg-server/include/dix.h | 1198 ++-- xorg-server/include/os.h | 1074 ++-- xorg-server/include/xkbsrv.h | 2 +- xorg-server/mi/miarc.c | 7284 ++++++++++++------------ xorg-server/os/access.c | 4404 +++++++------- xorg-server/os/auth.c | 679 +-- xorg-server/os/mitauth.c | 394 +- xorg-server/os/osdep.h | 23 +- xorg-server/os/rpcauth.c | 386 +- xorg-server/os/xdmauth.c | 998 ++-- xorg-server/os/xdmcp.c | 3332 +++++------ xorg-server/render/picture.c | 3642 ++++++------ xorg-server/render/picturestr.h | 1390 ++--- xorg-server/render/render.c | 131 +- xorg-server/xfixes/region.c | 1712 +++--- xorg-server/xkbdata.src/Makefile.am | 36 +- xorg-server/xkbdata.src/configure.in | 195 +- xorg-server/xkbdata.src/rules/base.xml.in | 17 + xorg-server/xkbdata.src/symbols/Makefile.am | 6 +- xorg-server/xkbdata.src/symbols/ara | 14 +- xorg-server/xkbdata.src/symbols/bw | 19 + xorg-server/xkbdata.src/symbols/de | 1010 ++-- xorg-server/xkbdata.src/symbols/ke | 37 +- xorg-server/xkbdata.src/symbols/level5 | 283 +- xorg-server/xkbdata.src/xkeyboard-config.pc.in | 8 + 34 files changed, 20126 insertions(+), 20162 deletions(-) create mode 100644 xorg-server/xkbdata.src/symbols/bw create mode 100644 xorg-server/xkbdata.src/xkeyboard-config.pc.in 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 -#endif - -#include -#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 . */ -#include -#endif -#ifdef SVR4 -#include -#endif -#if defined(__CYGWIN__) || defined(__SCO__) -#include -#include -#endif -#include -#include -#include -#include -#include -#include -#include -#endif - -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "gcstruct.h" -#include "dixfontstr.h" -#include "extnsionst.h" -#include "protocol-versions.h" - -#include -#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 - -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 +#endif + +#include +#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 . */ +#include +#endif +#ifdef SVR4 +#include +#endif +#if defined(__CYGWIN__) || defined(__SCO__) +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "gcstruct.h" +#include "dixfontstr.h" +#include "extnsionst.h" +#include "protocol-versions.h" + +#include +#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 + +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 -#endif - -#include "inputstr.h" -#include "gcstruct.h" /* pointer for extnsionst.h */ -#include "extnsionst.h" /* extension entry */ -#include -#include -#include -#include -#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 +#endif + +#include "inputstr.h" +#include "gcstruct.h" /* pointer for extnsionst.h */ +#include "extnsionst.h" /* extension entry */ +#include +#include +#include +#include +#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 -#endif - -#include "dix.h" -#include "inputstr.h" -#include -#include -#include -#include -#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 +#endif + +#include "dix.h" +#include "inputstr.h" +#include +#include +#include +#include +#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 -#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 +#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 -#endif - -#include -#include -#include "misc.h" -#include "windowstr.h" -#include "dixstruct.h" -#include "pixmapstr.h" -#include "scrnintstr.h" -#define XK_LATIN1 -#include -#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 +#endif + +#include +#include +#include "misc.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#define XK_LATIN1 +#include +#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 -#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 -#include -#include -#include - -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*) ¤tListIndex) ); - 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 +#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 +#include +#include +#include + +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*) ¤tListIndex) ); + 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 - * - */ - -/** \file - * Provide support for the RENDER extension (version 0.8). - */ - -#ifdef HAVE_DMX_CONFIG_H -#include -#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 -#include -#include -#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 + * + */ + +/** \file + * Provide support for the RENDER extension (version 0.8). + */ + +#ifdef HAVE_DMX_CONFIG_H +#include +#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 +#include +#include +#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 - -#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 + +#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 - -#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 -#include - -#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_ 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 + +#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 +#include + +#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_ 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 -#endif - -#include -#include -#include -#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 - -#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 xlineWidth; - 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 +#endif + +#include +#include +#include +#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 + +#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 xlineWidth; + 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 -#endif - -#ifdef WIN32 -#include -#endif - -#include -#include -#define XSERV_t -#define TRANS_SERVER -#define TRANS_REOPEN -#include -#include -#include -#include -#include "misc.h" -#include "site.h" -#include -#include -#ifndef WIN32 -#include -#include -#include - -#if defined(TCPCONN) || defined(STREAMSCONN) || defined(__SCO__) -#include -#endif /* TCPCONN || STREAMSCONN || ISC || __SCO__ */ -#ifdef DNETCONN -#include -#include -#endif - -#ifdef HAS_GETPEERUCRED -# include -# ifdef sun -# include -# endif -#endif - -#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__) -# include -#endif -#if defined(SYSV) && defined(__i386__) -# include -#endif -#ifdef __GNU__ -#undef SIOCGIFCONF -#include -#else /*!__GNU__*/ -# include -#endif /*__GNU__ */ - -#ifdef SVR4 -#include -#include -#endif - -#include - -#ifdef CSRG_BASED -#include -#if (BSD >= 199103) -#define VARIABLE_IFREQ -#endif -#endif - -#ifdef BSD44SOCKETS -#ifndef VARIABLE_IFREQ -#define VARIABLE_IFREQ -#endif -#endif - -#ifdef HAS_GETIFADDRS -#include -#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 -#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 - -#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.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.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 -#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, - ¬used, &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 - * - * 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 -#include - -#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 +#endif + +#ifdef WIN32 +#include +#endif + +#include +#include +#define XSERV_t +#define TRANS_SERVER +#define TRANS_REOPEN +#include +#include +#include +#include +#include "misc.h" +#include "site.h" +#include +#include +#ifndef WIN32 +#include +#include +#include + +#if defined(TCPCONN) || defined(STREAMSCONN) || defined(__SCO__) +#include +#endif /* TCPCONN || STREAMSCONN || ISC || __SCO__ */ +#ifdef DNETCONN +#include +#include +#endif + +#ifdef HAS_GETPEERUCRED +# include +# ifdef sun +# include +# endif +#endif + +#if defined(SVR4) || (defined(SYSV) && defined(__i386__)) || defined(__GNU__) +# include +#endif +#if defined(SYSV) && defined(__i386__) +# include +#endif +#ifdef __GNU__ +#undef SIOCGIFCONF +#include +#else /*!__GNU__*/ +# include +#endif /*__GNU__ */ + +#ifdef SVR4 +#include +#include +#endif + +#include + +#ifdef CSRG_BASED +#include +#if (BSD >= 199103) +#define VARIABLE_IFREQ +#endif +#endif + +#ifdef BSD44SOCKETS +#ifndef VARIABLE_IFREQ +#define VARIABLE_IFREQ +#endif +#endif + +#ifdef HAS_GETIFADDRS +#include +#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 +#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 + +#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.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.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 +#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, + ¬used, &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 + * + * 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 +#include + +#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 -#endif - -# include -# include -# include "misc.h" -# include "osdep.h" -# include "dixstruct.h" -# include -# include -#ifdef WIN32 -#include -#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 +#endif + +# include +# include +# include "misc.h" +# include "osdep.h" +# include "dixstruct.h" +# include +# include +#ifdef WIN32 +#include +#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 -#endif - -#include -#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 +#endif + +#include +#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 -#endif - -#ifdef SECURE_RPC - -#include -#include -#include "misc.h" -#include "os.h" -#include "osdep.h" -#include "dixstruct.h" - -#include - -#ifdef sun -/* 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 +#endif + +#ifdef SECURE_RPC + +#include +#include +#include "misc.h" +#include "os.h" +#include "osdep.h" +#include "dixstruct.h" + +#include + +#ifdef sun +/* 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 -#endif - -#include -#include -#define XSERV_t -#define TRANS_SERVER -#define TRANS_REOPEN -#include -#include "os.h" -#include "osdep.h" -#include "dixstruct.h" - -#ifdef HASXDMAUTH - -static Bool authFromXDMCP; - -#ifdef XDMCP -#include -#undef REQUEST -#include - -/* 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 = ρ - 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 +#endif + +#include +#include +#define XSERV_t +#define TRANS_SERVER +#define TRANS_REOPEN +#include +#include "os.h" +#include "osdep.h" +#include "dixstruct.h" + +#ifdef HASXDMAUTH + +static Bool authFromXDMCP; + +#ifdef XDMCP +#include +#undef REQUEST +#include + +/* 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 = ρ + 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 -#endif - -#ifdef WIN32 -#include -#endif - -#include - -#if !defined(WIN32) -#include -#include -#include -#include -#endif - -#include -#include -#include -#include -#include "misc.h" -#include -#include "osdep.h" -#include "input.h" -#include "dixstruct.h" -#include "opaque.h" -#include "site.h" - -#ifdef STREAMSCONN -#include -#include -#include -#endif - -#ifdef XDMCP -#undef REQUEST - -#ifdef XDMCP_NO_IPV6 -#undef IPv6 -#endif - -#include - -#define X_INCLUDE_NETDB_H -#include - -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 - -/* - * 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]); - - 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 +#endif + +#ifdef WIN32 +#include +#endif + +#include + +#if !defined(WIN32) +#include +#include +#include +#include +#endif + +#include +#include +#include +#include +#include "misc.h" +#include +#include "osdep.h" +#include "input.h" +#include "dixstruct.h" +#include "opaque.h" +#include "site.h" + +#ifdef STREAMSCONN +#include +#include +#include +#endif + +#ifdef XDMCP +#undef REQUEST + +#ifdef XDMCP_NO_IPV6 +#undef IPv6 +#endif + +#include + +#define X_INCLUDE_NETDB_H +#include + +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 + +/* + * 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]); + + 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 -#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 +#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 -#endif - -#include "xfixesint.h" -#include "scrnintstr.h" -#include -extern int RenderErrBase; -#include -#include -#include - -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 +#endif + +#include "xfixesint.h" +#include "scrnintstr.h" +#include +extern int RenderErrBase; +#include +#include +#include + +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 swa + + + + kik + <_description>Kikuyu + kik + + + + + + + bw + <_shortDescription>Bwa + <_description>Botswana + tsn + 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 { [ Arabic_sad, Arabic_fathatan ] }; key { [ Arabic_theh, Arabic_damma ] }; key { [ Arabic_qaf, Arabic_dammatan ] }; - key { [ Arabic_feh, 0x100fef9 ] }; + key { [ Arabic_feh, 0x100fef9, 0x10006a4 ] }; key { [ Arabic_ghain, Arabic_hamzaunderalef ] }; key { [ Arabic_ain, grave ] }; key { [ Arabic_ha, division ] }; key { [ Arabic_khah, multiply ] }; key { [ Arabic_hah, Arabic_semicolon ] }; - key { [ Arabic_jeem, less ] }; + key { [ Arabic_jeem, less, 0x1000686 ] }; key { [ Arabic_dal, greater ] }; key { [ Arabic_sheen, Arabic_kasra ] }; key { [ Arabic_seen, Arabic_kasratan ] }; key { [ Arabic_yeh, bracketright ] }; - key { [ Arabic_beh, bracketleft ] }; + key { [ Arabic_beh, bracketleft, 0x100067e ] }; key { [ Arabic_lam, 0x100fef7 ] }; key { [ Arabic_alef, Arabic_hamzaonalef ] }; key { [ Arabic_teh, Arabic_tatweel ] }; key { [ Arabic_noon, Arabic_comma ] }; key { [ Arabic_meem, slash ] }; - key { [ Arabic_kaf, colon ] }; + key { [ Arabic_kaf, colon, 0x10006af ] }; key { [ Arabic_tah, quotedbl ] }; key { [ bar, brokenbar ] }; - key { [Arabic_hamzaonyeh, asciitilde ] }; - key { [ Arabic_hamza, Arabic_sukun ] }; + key { [Arabic_hamzaonyeh, asciitilde, guillemotright ] }; + key { [ Arabic_hamza, Arabic_sukun, guillemotleft ] }; key { [Arabic_hamzaonwaw, braceright ] }; key { [ Arabic_ra, braceleft ] }; key { [ 0x100fefb, 0x100fef5 ] }; @@ -64,6 +64,8 @@ xkb_symbols "basic" { key { [ Arabic_zain, period ] }; key { [ 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 { [ semicolon, colon, 0x01000324, 0x01000324 ] }; //COMBINING DIAERESIS BELOW + key { [apostrophe, quotedbl, 0x01000301, 0x01000308 ] }; //COMBINING ACUTE ACCENT, COMBINING DIAERESIS + key { [ grave, asciitilde, 0x01000300, 0x01000303 ] }; //COMBINING GRAVE ACCENT, COMBINING TILDE + key { [ 6, asciicircum, 0x01000302 ] }; //COMBINING CIRCUMFLEX ACCENT + key { [ 8, asterisk, 0x01000307, 0x01000323 ] }; //COMBINING DOT ABOVE, COMBINING DOT BELOW + key { [ 9, parenleft, 0x01000306 ] }; //COMBINING BREVE + key { [ 0, parenright, 0x0100030c ] }; //COMBINING CARON + key { [ 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 { [ 2, quotedbl, twosuperior, oneeighth ] }; - key { [ 3, section, threesuperior, sterling ] }; - key { [ 4, dollar, onequarter, currency ] }; - - key {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 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 { [dead_acute, dead_grave, dead_cedilla, dead_ogonek ] }; - - key { [ e, E, EuroSign, EuroSign ] }; - key { [ z, Z, leftarrow, yen ] }; - key { [udiaeresis, Udiaeresis, dead_diaeresis, dead_abovering ] }; - key { [ plus, asterisk, dead_tilde, dead_macron ] }; - - key { [ s, S, U017F, U1E9E ] }; - key { [ j, J, dead_belowdot, dead_abovedot ] }; - key { [odiaeresis, Odiaeresis, dead_doubleacute, dead_belowdot ] }; - key { [adiaeresis, Adiaeresis, dead_circumflex, dead_caron ] }; - key { [dead_circumflex, degree, U2032, U2033 ] }; - - key { [numbersign, apostrophe, rightsinglequotemark, dead_breve ] }; - key { [ y, Y, guillemotright, U203A ] }; - key { [ x, X, guillemotleft, U2039 ] }; - key { [ v, V, doublelowquotemark, singlelowquotemark ] }; - key { [ b, B, leftdoublequotemark, leftsinglequotemark ] }; - key { [ n, N, rightdoublequotemark, rightsinglequotemark ] }; - key { [ comma, semicolon, periodcentered, multiply ] }; - key { [ period, colon, U2026, division ] }; - key { [ 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 { [asciicircum, degree, notsign, notsign ] }; - key { [ acute, grave, cedilla, cedilla ] }; - key { [udiaeresis, Udiaeresis, diaeresis, diaeresis ] }; - key { [ plus, asterisk, asciitilde, macron ] }; - key { [odiaeresis, Odiaeresis, doubleacute, doubleacute ] }; - key { [adiaeresis, Adiaeresis, asciicircum, asciicircum ] }; - key { [numbersign, apostrophe, grave, grave ] }; - key { [ 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 { [asciicircum, degree, notsign, notsign ] }; - key { [ plus, asterisk, asciitilde, dead_macron ] }; - key { [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 { [dead_acute, grave, dead_cedilla, dead_ogonek ] }; - key { [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 and - // 'a', 's', 't', 'i', 'ä (ä)' (+ 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 { [ t, T, tcedilla, Tcedilla ] }; - key { [ i, I, icircumflex, Icircumflex ] }; - key { [ a, A, acircumflex, Acircumflex ] }; - key { [ s, S, scedilla, Scedilla ] }; - key { [ 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 { [ t, T, tcedilla, Tcedilla ] }; - key { [ i, I, icircumflex, Icircumflex ] }; - key { [ a, A, acircumflex, Acircumflex ] }; - key { [ s, S, scedilla, Scedilla ] }; - key { [ 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 { [ asciicircum, degree ] }; - - key { [ 1, exclam, onesuperior ] }; - key { [ 2, quotedbl, twosuperior ] }; - key { [ 3, section, threesuperior ] }; - key { [ 4, dollar, bar ] }; - key { [ 5, percent, bar ] }; - key { [ 6, ampersand, brokenbar ] }; - key { [ 7, slash, braceleft ] }; - key { [ 8, parenleft, bracketleft ] }; - key { [ 9, parenright, bracketright ] }; - key { [ 0, equal, braceright ] }; - key { [ plus, asterisk, asciitilde ] }; - key { [ less, greater, dead_grave ] }; - - key { [ udiaeresis, Udiaeresis, at ] }; - key { [ comma, semicolon, dead_diaeresis ] }; - key { [ period, colon ] }; - key { [ c, C, copyright, Cacute ] }; - key { [ t, T, trademark ] }; - key { [ z, Z, zabovedot, Zabovedot ] }; - key { [ question, ssharp ] }; - key { [ slash, backslash, dead_acute ] }; - - key { [ a, A, at, aogonek ] }; - key { [ o, O, oacute, Oacute ] }; - key { [ e, E, EuroSign, eogonek ] }; - key { [ i, I ] }; - key { [ u, U ] }; - key { [ h, H ] }; - key { [ d, D ] }; - key { [ r, R, registered ] }; - key { [ n, N, nacute, Nacute ] }; - key { [ s, S, sacute, Sacute] }; - key { [ l, L, lstroke, Lstroke ] }; - - key { [ odiaeresis, Odiaeresis ] }; - key { [ q, Q, at ] }; - key { [ m, M, mu ] }; - key { [ numbersign, apostrophe ] }; - - key { [ minus, underscore, hyphen, diaeresis] }; - - key { [ 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 -// inspired by Dvorak/de-ergo http://www.goebel-consult.de/de-ergo/ -// -// Authors: -// Stephan Hilb -// -// Benjamin Kellermann -// Erik Streb -// 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, ISO_Left_Tab, Multi_key, ISO_Level5_Lock, NoSymbol, NoSymbol, NoSymbol, ISO_Level5_Lock ] }; - - - // Number row - // -------------------------------------------------------------- - key { [ dead_circumflex, dead_caron, U21BB, U02DE, dead_abovedot, Pointer_EnableKeys, dead_belowdot, NoSymbol ] }; - - key { [ 1, degree, onesuperior, onesubscript, ordfeminine, NoSymbol, notsign, NoSymbol ] }; - key { [ 2, section, twosuperior, twosubscript, masculine, NoSymbol, logicalor, NoSymbol ] }; - key { [ 3, U2113, threesuperior, threesubscript, numerosign, NoSymbol, logicaland, NoSymbol ] }; - key { [ 4, guillemotright, U203A, femalesymbol, NoSymbol, NoSymbol, U22A5, NoSymbol ] }; - key { [ 5, guillemotleft, U2039, malesymbol, periodcentered, NoSymbol, U2221, NoSymbol ] }; - key { [ 6, dollar, cent, U26A5, sterling, NoSymbol, U2225, NoSymbol ] }; - - key { [ 7, EuroSign, yen, U03F0, currency, NoSymbol, rightarrow, NoSymbol ] }; - key { [ 8, doublelowquotemark, singlelowquotemark, U27E8, Tab, ISO_Left_Tab, U221E, NoSymbol ] }; - key { [ 9, leftdoublequotemark, leftsinglequotemark, U27E9, KP_Divide, KP_Divide, variation, NoSymbol ] }; - key { [ 0, rightdoublequotemark, rightsinglequotemark, zerosubscript, KP_Multiply, KP_Multiply, emptyset, NoSymbol ] }; - - key { [ minus, emdash, NoSymbol, U2011, KP_Subtract, KP_Subtract, hyphen, NoSymbol ] }; - key { [ 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 { [ x, X, ellipsis, Greek_xi, Prior, Prior, Greek_XI, NoSymbol ] }; - key { [ v, V, underscore, NoSymbol, BackSpace, BackSpace, radical, NoSymbol ] }; - key { [ l, L, bracketleft, Greek_lambda, Up, Up, Greek_LAMBDA, NoSymbol ] }; - key { [ c, C, bracketright, Greek_chi, Delete, Delete, U2102, NoSymbol ] }; - key { [ w, W, asciicircum, Greek_omega, Next, Next, Greek_OMEGA, NoSymbol ] }; - - key { [ k, K, exclam, Greek_kappa, exclamdown, NoSymbol, multiply, NoSymbol ] }; - key { [ h, H, less, Greek_psi, KP_7, KP_7, Greek_PSI, NoSymbol ] }; - key { [ g, G, greater, Greek_gamma, KP_8, KP_8, Greek_GAMMA, NoSymbol ] }; - key { [ f, F, equal, Greek_phi, KP_9, KP_9, Greek_PHI, NoSymbol ] }; - key { [ q, Q, ampersand, U03D5, KP_Add, KP_Add, U211A, NoSymbol ] }; - - key { [ ssharp, U1E9E, U017F, Greek_finalsmallsigma, U2212, NoSymbol, jot, NoSymbol ] }; - - key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; - key { [ 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 { [ u, U, backslash, NoSymbol, Home, Home, includedin, NoSymbol ] }; - key { [ i, I, slash, Greek_iota, Left, Left, integral, NoSymbol ] }; - key { [ a, A, braceleft, Greek_alpha, Down, Down, U2200, NoSymbol ] }; - key { [ e, E, braceright, Greek_epsilon, Right, Right, U2203, NoSymbol ] }; - key { [ o, O, asterisk, Greek_omicron, End, End, elementof, NoSymbol ] }; - - key { [ s, S, question, Greek_sigma, questiondown, NoSymbol, Greek_SIGMA, NoSymbol ] }; - key { [ n, N, parenleft, Greek_nu, KP_4, KP_4, U2115, NoSymbol ] }; - key { [ r, R, parenright, Greek_rho, KP_5, KP_5, U211D, NoSymbol ] }; - key { [ t, T, minus, Greek_tau, KP_6, KP_6, partialderivative, NoSymbol ] }; - key { [ d, D, colon, Greek_delta, KP_Separator, comma, Greek_DELTA, NoSymbol ] }; - - key { [ y, Y, at, Greek_upsilon, period, KP_Decimal, nabla, NoSymbol ] }; - - // Bottom row - // -------------------------------------------------------------- - key { [ udiaeresis, Udiaeresis, numbersign, NoSymbol, Escape, Escape, union, NoSymbol ] }; - key { [ odiaeresis, Odiaeresis, dollar, U03F5, Tab, Tab, intersection, NoSymbol ] }; - key { [ adiaeresis, Adiaeresis, bar, Greek_eta, Insert, Insert, U2135, NoSymbol ] }; - key { [ p, P, asciitilde, Greek_pi, Return, Return, Greek_PI, NoSymbol ] }; - key { [ z, Z, grave, Greek_zeta, Undo, Undo, U2124, NoSymbol ] }; - - key { [ b, B, plus, Greek_beta, colon, NoSymbol, U21D0, NoSymbol ] }; - key { [ m, M, percent, Greek_mu, KP_1, KP_1, ifonlyif, NoSymbol ] }; - key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; - key { [ comma, endash, quotedbl, U03F1, KP_2, KP_2, U21D2, NoSymbol ] }; - key { [ period, enfilledcircbullet, apostrophe, U03D1, KP_3, KP_3, U21A6, NoSymbol ] }; - key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC_LEVEL_FIVE_LOCK"; - key { [ j, J, semicolon, Greek_theta, semicolon, NoSymbol, Greek_THETA, NoSymbol ] }; - key.type[Group1] = "EIGHT_LEVEL_LEVEL_FIVE_LOCK"; - - // Space key - // -------------------------------------------------------------- - key { [ space, space, space, nobreakspace, KP_0, KP_0, U202F, NoSymbol ] }; - - - // Keypad-keys - // =============== - - // The former Numlock key: - key { [ Tab, ISO_Left_Tab, equal, approxeq, notequal, Pointer_EnableKeys, identical, NoSymbol ] }; - - // Topmost row - // -------------------------------------------------------------- - key { [ KP_Divide, KP_Divide, division, U2300, U2215, NoSymbol, U2223, NoSymbol ] }; - key { [ KP_Multiply, KP_Multiply, U2219, U2299, multiply, NoSymbol, U2297, NoSymbol ] }; - key { [ KP_Subtract, KP_Subtract, U2212, U2296, U2216, NoSymbol, U2238, NoSymbol ] }; - - // Top row - // -------------------------------------------------------------- - key { [ KP_7, U2714, U2195, U226A, KP_Home, KP_Home, upstile, NoSymbol ] }; - key { [ KP_8, U2718, uparrow, intersection, KP_Up, KP_Up, U22C2, NoSymbol ] }; - key { [ KP_9, dagger, U20D7, U226B, KP_Prior, KP_Prior, U2309, NoSymbol ] }; - key { [ KP_Add, KP_Add, plusminus, U2295, U2213, NoSymbol, U2214, NoSymbol ] }; - - // Middle row - // -------------------------------------------------------------- - key { [ KP_4, club, leftarrow, includedin, KP_Left, KP_Left, U2286, NoSymbol ] }; - key { [ KP_5, EuroSign, colon, U22B6, KP_Begin, KP_Begin, U22B7, NoSymbol ] }; - key { [ KP_6, U2023, rightarrow, includes, KP_Right, KP_Right, U2287, NoSymbol ] }; - - // Bottom row - // -------------------------------------------------------------- - key { [ KP_1, diamond, U2194, lessthanequal, KP_End, KP_End, downstile, NoSymbol ] }; - key { [ KP_2, heart, downarrow, union, KP_Down, KP_Down, U22C3, NoSymbol ] }; - key { [ KP_3, U2660, U21CC, greaterthanequal, KP_Next, KP_Next, U230B, NoSymbol ] }; - key { [ KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, NoSymbol ] }; - key { [ KP_Equal, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; - - // Bottommost row - // -------------------------------------------------------------- - key { [ KP_0, U2423, percent, U2030, KP_Insert, KP_Insert, U25A1, NoSymbol ] }; - key { [ 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 { [ 1, exclam, exclamdown, at ] }; - key { [ 5, percent, bracketleft ] }; - key { [ 6, ampersand, bracketright ] }; - key { [ 7, slash, bar, backslash ] }; - key { [ 8, parenleft, braceleft, asciitilde ] }; - key { [ 9, parenright, braceright ] }; - key { [ q, Q, guillemotleft, guillemotright ] }; - key { [ r, R, registered ] }; - key { [ u, U, diaeresis, Aacute ] }; - key { [ i, I, slash, Ucircumflex ] }; - key { [ udiaeresis, Udiaeresis, periodcentered, degree ] }; - key { [ plus, asterisk, asciitilde ] }; - key { [ a, A, aring, Aring ] }; - key { [ g, G, copyright ] }; - key { [ h, H, ordfeminine ] }; - key { [ l, L, at ] }; - key { [ odiaeresis, Odiaeresis, dead_acute ] }; - key { [ 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 { [ 4, dollar, onequarter, currency ] }; - - key { [ asciicircum, degree, notsign ] }; - key { [ acute, grave, cedilla ] }; - key { [ udiaeresis, Udiaeresis, diaeresis ] }; - key { [ plus, asterisk, asciitilde, macron ] }; - key { [ odiaeresis, Odiaeresis, acute ] }; - key { [ adiaeresis, Adiaeresis, asciicircum ] }; - - key { [ 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 { [ z, Z, zcaron, Zcaron ] }; - key { [ x, X, zacute, Zacute ] }; - key { [ c, C, cacute, Cacute ] }; - key { [ v, V, ccaron, Ccaron ] }; - key { [ n, N, nacute, Nacute ] }; - key { [ s, S, sacute, Sacute ] }; - key { [ d, D, scaron, Scaron ] }; - key { [ f, F ] }; - key { [ q, Q ] }; - key { [ w, W ] }; - key { [ e, E, ecaron, Ecaron ] }; - key { [ r, R, racute, Racute ] }; - key { [ t, T, U20B5, EuroSign ] }; - key { [ 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 { [ y, Y ] }; - key { [ x, X ] }; - key { [ c, C, cacute, Cacute ] }; - key { [ v, V, ccaron, Ccaron ] }; - key { [ n, N, nacute, Nacute ] }; - key { [ s, S, sacute, Sacute ] }; - key { [ d, D, scaron, Scaron ] }; - key { [ f, F ] }; - key { [ q, Q ] }; - key { [ w, W ] }; - key { [ e, E, ecaron, Ecaron ] }; - key { [ r, R, racute, Racute ] }; - key { [ t, T, U20B5, EuroSign ] }; - key { [ z, Z, zcaron, Zcaron ] }; - key { [ u, U, zacute, Zacute ] }; - key { [ 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 - - include "de(basic)" - - name[Group1] = "Germany - qwerty"; - - key { [ z, Z, leftarrow, yen ] }; - key { [ 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 { [ 2, quotedbl, twosuperior, oneeighth ] }; + key { [ 3, section, threesuperior, sterling ] }; + key { [ 4, dollar, onequarter, currency ] }; + + key {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 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 { [dead_acute, dead_grave, dead_cedilla, dead_ogonek ] }; + + key { [ e, E, EuroSign, EuroSign ] }; + key { [ z, Z, leftarrow, yen ] }; + key { [udiaeresis, Udiaeresis, dead_diaeresis, dead_abovering ] }; + key { [ plus, asterisk, dead_tilde, dead_macron ] }; + + key { [ s, S, U017F, U1E9E ] }; + key { [ j, J, dead_belowdot, dead_abovedot ] }; + key { [odiaeresis, Odiaeresis, dead_doubleacute, dead_belowdot ] }; + key { [adiaeresis, Adiaeresis, dead_circumflex, dead_caron ] }; + key { [dead_circumflex, degree, U2032, U2033 ] }; + + key { [numbersign, apostrophe, rightsinglequotemark, dead_breve ] }; + key { [ y, Y, guillemotright, U203A ] }; + key { [ x, X, guillemotleft, U2039 ] }; + key { [ v, V, doublelowquotemark, singlelowquotemark ] }; + key { [ b, B, leftdoublequotemark, leftsinglequotemark ] }; + key { [ n, N, rightdoublequotemark, rightsinglequotemark ] }; + key { [ comma, semicolon, periodcentered, multiply ] }; + key { [ period, colon, U2026, division ] }; + key { [ 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 { [asciicircum, degree, notsign, notsign ] }; + key { [ acute, grave, cedilla, cedilla ] }; + key { [udiaeresis, Udiaeresis, diaeresis, diaeresis ] }; + key { [ plus, asterisk, asciitilde, macron ] }; + key { [odiaeresis, Odiaeresis, doubleacute, doubleacute ] }; + key { [adiaeresis, Adiaeresis, asciicircum, asciicircum ] }; + key { [numbersign, apostrophe, grave, grave ] }; + key { [ 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 { [asciicircum, degree, notsign, notsign ] }; + key { [ plus, asterisk, asciitilde, dead_macron ] }; + key { [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 { [dead_acute, grave, dead_cedilla, dead_ogonek ] }; + key { [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 and + // 'a', 's', 't', 'i', 'ä (ä)' (+ 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 { [ t, T, tcedilla, Tcedilla ] }; + key { [ i, I, icircumflex, Icircumflex ] }; + key { [ a, A, acircumflex, Acircumflex ] }; + key { [ s, S, scedilla, Scedilla ] }; + key { [ 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 { [ t, T, tcedilla, Tcedilla ] }; + key { [ i, I, icircumflex, Icircumflex ] }; + key { [ a, A, acircumflex, Acircumflex ] }; + key { [ s, S, scedilla, Scedilla ] }; + key { [ 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 { [ asciicircum, degree ] }; + + key { [ 1, exclam, onesuperior ] }; + key { [ 2, quotedbl, twosuperior ] }; + key { [ 3, section, threesuperior ] }; + key { [ 4, dollar, bar ] }; + key { [ 5, percent, bar ] }; + key { [ 6, ampersand, brokenbar ] }; + key { [ 7, slash, braceleft ] }; + key { [ 8, parenleft, bracketleft ] }; + key { [ 9, parenright, bracketright ] }; + key { [ 0, equal, braceright ] }; + key { [ plus, asterisk, asciitilde ] }; + key { [ less, greater, dead_grave ] }; + + key { [ udiaeresis, Udiaeresis, at ] }; + key { [ comma, semicolon, dead_diaeresis ] }; + key { [ period, colon ] }; + key { [ c, C, copyright, Cacute ] }; + key { [ t, T, trademark ] }; + key { [ z, Z, zabovedot, Zabovedot ] }; + key { [ question, ssharp ] }; + key { [ slash, backslash, dead_acute ] }; + + key { [ a, A, at, aogonek ] }; + key { [ o, O, oacute, Oacute ] }; + key { [ e, E, EuroSign, eogonek ] }; + key { [ i, I ] }; + key { [ u, U ] }; + key { [ h, H ] }; + key { [ d, D ] }; + key { [ r, R, registered ] }; + key { [ n, N, nacute, Nacute ] }; + key { [ s, S, sacute, Sacute] }; + key { [ l, L, lstroke, Lstroke ] }; + + key { [ odiaeresis, Odiaeresis ] }; + key { [ q, Q, at ] }; + key { [ m, M, mu ] }; + key { [ numbersign, apostrophe ] }; + + key { [ minus, underscore, hyphen, diaeresis] }; + + key { [ 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 +// inspired by Dvorak/de-ergo http://www.goebel-consult.de/de-ergo/ +// +// Authors: +// Stephan Hilb +// +// Benjamin Kellermann +// Erik Streb +// 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, ISO_Left_Tab, Multi_key, ISO_Level5_Lock, NoSymbol, NoSymbol, NoSymbol, ISO_Level5_Lock ] }; + + + // Number row + // -------------------------------------------------------------- + key { [ dead_circumflex, dead_caron, U21BB, U02DE, dead_abovedot, Pointer_EnableKeys, dead_belowdot, NoSymbol ] }; + + key { [ 1, degree, onesuperior, onesubscript, ordfeminine, NoSymbol, notsign, NoSymbol ] }; + key { [ 2, section, twosuperior, twosubscript, masculine, NoSymbol, logicalor, NoSymbol ] }; + key { [ 3, U2113, threesuperior, threesubscript, numerosign, NoSymbol, logicaland, NoSymbol ] }; + key { [ 4, guillemotright, U203A, femalesymbol, NoSymbol, NoSymbol, U22A5, NoSymbol ] }; + key { [ 5, guillemotleft, U2039, malesymbol, periodcentered, NoSymbol, U2221, NoSymbol ] }; + key { [ 6, dollar, cent, U26A5, sterling, NoSymbol, U2225, NoSymbol ] }; + + key { [ 7, EuroSign, yen, U03F0, currency, NoSymbol, rightarrow, NoSymbol ] }; + key { [ 8, doublelowquotemark, singlelowquotemark, U27E8, Tab, ISO_Left_Tab, U221E, NoSymbol ] }; + key { [ 9, leftdoublequotemark, leftsinglequotemark, U27E9, KP_Divide, KP_Divide, variation, NoSymbol ] }; + key { [ 0, rightdoublequotemark, rightsinglequotemark, zerosubscript, KP_Multiply, KP_Multiply, emptyset, NoSymbol ] }; + + key { [ minus, emdash, NoSymbol, U2011, KP_Subtract, KP_Subtract, hyphen, NoSymbol ] }; + key { [ dead_grave, dead_cedilla, dead_abovering, dead_dasia, dead_diaeresis, NoSymbol, dead_macron, NoSymbol ] }; + + // Top row + // -------------------------------------------------------------- + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; + key { [ x, X, ellipsis, Greek_xi, Prior, Prior, Greek_XI, NoSymbol ] }; + key { [ v, V, underscore, NoSymbol, BackSpace, BackSpace, radical, NoSymbol ] }; + key { [ l, L, bracketleft, Greek_lambda, Up, Up, Greek_LAMBDA, NoSymbol ] }; + key { [ c, C, bracketright, Greek_chi, Delete, Delete, U2102, NoSymbol ] }; + key { [ w, W, asciicircum, Greek_omega, Next, Next, Greek_OMEGA, NoSymbol ] }; + + key { [ k, K, exclam, Greek_kappa, exclamdown, NoSymbol, multiply, NoSymbol ] }; + key { [ h, H, less, Greek_psi, KP_7, KP_7, Greek_PSI, NoSymbol ] }; + key { [ g, G, greater, Greek_gamma, KP_8, KP_8, Greek_GAMMA, NoSymbol ] }; + key { [ f, F, equal, Greek_phi, KP_9, KP_9, Greek_PHI, NoSymbol ] }; + key { [ q, Q, ampersand, U03D5, KP_Add, KP_Add, U211A, NoSymbol ] }; + + key { [ ssharp, U1E9E, U017F, Greek_finalsmallsigma, U2212, NoSymbol, jot, NoSymbol ] }; + + key.type[Group1] = "EIGHT_LEVEL"; + key { [ dead_acute, dead_tilde, dead_stroke, dead_psili, dead_doubleacute, NoSymbol, dead_breve, NoSymbol ] }; + + // Middle row + // -------------------------------------------------------------- + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; + key { [ u, U, backslash, NoSymbol, Home, Home, includedin, NoSymbol ] }; + key { [ i, I, slash, Greek_iota, Left, Left, integral, NoSymbol ] }; + key { [ a, A, braceleft, Greek_alpha, Down, Down, U2200, NoSymbol ] }; + key { [ e, E, braceright, Greek_epsilon, Right, Right, U2203, NoSymbol ] }; + key { [ o, O, asterisk, Greek_omicron, End, End, elementof, NoSymbol ] }; + + key { [ s, S, question, Greek_sigma, questiondown, NoSymbol, Greek_SIGMA, NoSymbol ] }; + key { [ n, N, parenleft, Greek_nu, KP_4, KP_4, U2115, NoSymbol ] }; + key { [ r, R, parenright, Greek_rho, KP_5, KP_5, U211D, NoSymbol ] }; + key { [ t, T, minus, Greek_tau, KP_6, KP_6, partialderivative, NoSymbol ] }; + key { [ d, D, colon, Greek_delta, KP_Separator, comma, Greek_DELTA, NoSymbol ] }; + + key { [ y, Y, at, Greek_upsilon, period, KP_Decimal, nabla, NoSymbol ] }; + + // Bottom row + // -------------------------------------------------------------- + key { [ udiaeresis, Udiaeresis, numbersign, NoSymbol, Escape, Escape, union, NoSymbol ] }; + key { [ odiaeresis, Odiaeresis, dollar, U03F5, Tab, Tab, intersection, NoSymbol ] }; + key { [ adiaeresis, Adiaeresis, bar, Greek_eta, Insert, Insert, U2135, NoSymbol ] }; + key { [ p, P, asciitilde, Greek_pi, Return, Return, Greek_PI, NoSymbol ] }; + key { [ z, Z, grave, Greek_zeta, Undo, Undo, U2124, NoSymbol ] }; + + key { [ b, B, plus, Greek_beta, colon, NoSymbol, U21D0, NoSymbol ] }; + key { [ m, M, percent, Greek_mu, KP_1, KP_1, ifonlyif, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL"; + key { [ comma, endash, quotedbl, U03F1, KP_2, KP_2, U21D2, NoSymbol ] }; + key { [ period, enfilledcircbullet, apostrophe, U03D1, KP_3, KP_3, U21A6, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL_ALPHABETIC"; + key { [ j, J, semicolon, Greek_theta, semicolon, NoSymbol, Greek_THETA, NoSymbol ] }; + key.type[Group1] = "EIGHT_LEVEL"; + + // Space key + // -------------------------------------------------------------- + key { [ space, space, space, nobreakspace, KP_0, KP_0, U202F, NoSymbol ] }; + + + // Keypad-keys + // =============== + + // The former Numlock key: + key { [ Tab, ISO_Left_Tab, equal, approxeq, notequal, Pointer_EnableKeys, identical, NoSymbol ] }; + + // Topmost row + // -------------------------------------------------------------- + key { [ KP_Divide, KP_Divide, division, U2300, U2215, NoSymbol, U2223, NoSymbol ] }; + key { [ KP_Multiply, KP_Multiply, U2219, U2299, multiply, NoSymbol, U2297, NoSymbol ] }; + key { [ KP_Subtract, KP_Subtract, U2212, U2296, U2216, NoSymbol, U2238, NoSymbol ] }; + + // Top row + // -------------------------------------------------------------- + key { [ KP_7, U2714, U2195, U226A, KP_Home, KP_Home, upstile, NoSymbol ] }; + key { [ KP_8, U2718, uparrow, intersection, KP_Up, KP_Up, U22C2, NoSymbol ] }; + key { [ KP_9, dagger, U20D7, U226B, KP_Prior, KP_Prior, U2309, NoSymbol ] }; + key { [ KP_Add, KP_Add, plusminus, U2295, U2213, NoSymbol, U2214, NoSymbol ] }; + + // Middle row + // -------------------------------------------------------------- + key { [ KP_4, club, leftarrow, includedin, KP_Left, KP_Left, U2286, NoSymbol ] }; + key { [ KP_5, EuroSign, colon, U22B6, KP_Begin, KP_Begin, U22B7, NoSymbol ] }; + key { [ KP_6, U2023, rightarrow, includes, KP_Right, KP_Right, U2287, NoSymbol ] }; + + // Bottom row + // -------------------------------------------------------------- + key { [ KP_1, diamond, U2194, lessthanequal, KP_End, KP_End, downstile, NoSymbol ] }; + key { [ KP_2, heart, downarrow, union, KP_Down, KP_Down, U22C3, NoSymbol ] }; + key { [ KP_3, U2660, U21CC, greaterthanequal, KP_Next, KP_Next, U230B, NoSymbol ] }; + key { [ KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, KP_Enter, NoSymbol ] }; + key { [ KP_Equal, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol, NoSymbol ] }; + + // Bottommost row + // -------------------------------------------------------------- + key { [ KP_0, U2423, percent, U2030, KP_Insert, KP_Insert, U25A1, NoSymbol ] }; + key { [ 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 { [ 1, exclam, exclamdown, at ] }; + key { [ 5, percent, bracketleft ] }; + key { [ 6, ampersand, bracketright ] }; + key { [ 7, slash, bar, backslash ] }; + key { [ 8, parenleft, braceleft, asciitilde ] }; + key { [ 9, parenright, braceright ] }; + key { [ q, Q, guillemotleft, guillemotright ] }; + key { [ r, R, registered ] }; + key { [ u, U, diaeresis, Aacute ] }; + key { [ i, I, slash, Ucircumflex ] }; + key { [ udiaeresis, Udiaeresis, periodcentered, degree ] }; + key { [ plus, asterisk, asciitilde ] }; + key { [ a, A, aring, Aring ] }; + key { [ g, G, copyright ] }; + key { [ h, H, ordfeminine ] }; + key { [ l, L, at ] }; + key { [ odiaeresis, Odiaeresis, dead_acute ] }; + key { [ 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 { [ 4, dollar, onequarter, currency ] }; + + key { [ asciicircum, degree, notsign ] }; + key { [ acute, grave, cedilla ] }; + key { [ udiaeresis, Udiaeresis, diaeresis ] }; + key { [ plus, asterisk, asciitilde, macron ] }; + key { [ odiaeresis, Odiaeresis, acute ] }; + key { [ adiaeresis, Adiaeresis, asciicircum ] }; + + key { [ 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 { [ z, Z, zcaron, Zcaron ] }; + key { [ x, X, zacute, Zacute ] }; + key { [ c, C, cacute, Cacute ] }; + key { [ v, V, ccaron, Ccaron ] }; + key { [ n, N, nacute, Nacute ] }; + key { [ s, S, sacute, Sacute ] }; + key { [ d, D, scaron, Scaron ] }; + key { [ f, F ] }; + key { [ q, Q ] }; + key { [ w, W ] }; + key { [ e, E, ecaron, Ecaron ] }; + key { [ r, R, racute, Racute ] }; + key { [ t, T, U20B5, EuroSign ] }; + key { [ 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 { [ y, Y ] }; + key { [ x, X ] }; + key { [ c, C, cacute, Cacute ] }; + key { [ v, V, ccaron, Ccaron ] }; + key { [ n, N, nacute, Nacute ] }; + key { [ s, S, sacute, Sacute ] }; + key { [ d, D, scaron, Scaron ] }; + key { [ f, F ] }; + key { [ q, Q ] }; + key { [ w, W ] }; + key { [ e, E, ecaron, Ecaron ] }; + key { [ r, R, racute, Racute ] }; + key { [ t, T, U20B5, EuroSign ] }; + key { [ z, Z, zcaron, Zcaron ] }; + key { [ u, U, zacute, Zacute ] }; + key { [ 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 + + include "de(basic)" + + name[Group1] = "Germany - qwerty"; + + key { [ z, Z, leftarrow, yen ] }; + key { [ 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 { [ semicolon, colon, 0x01000324, 0x01000324 ] }; //COMBINING DIAERESIS BELOW + key { [apostrophe, quotedbl, 0x01000301, 0x01000308 ] }; //COMBINING ACUTE ACCENT, COMBINING DIAERESIS + key { [ grave, asciitilde, 0x01000300, 0x01000303 ] }; //COMBINING GRAVE ACCENT, COMBINING TILDE + key { [ 6, asciicircum, 0x01000302 ] }; //COMBINING CIRCUMFLEX ACCENT + key { [ 8, asterisk, 0x01000307, 0x01000323 ] }; //COMBINING DOT ABOVE, COMBINING DOT BELOW + key { [ 9, parenleft, 0x01000306 ] }; //COMBINING BREVE + key { [ 0, parenright, 0x0100030c ] }; //COMBINING CARON + key { [ 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 { [ semicolon, colon, 0x01000324, 0x01000324 ] }; //COMBINING DIAERESIS BELOW + key { [apostrophe, quotedbl, 0x01000301, 0x01000308 ] }; //COMBINING ACUTE ACCENT, COMBINING DIAERESIS + key { [ grave, asciitilde, 0x01000300, 0x01000303 ] }; //COMBINING GRAVE ACCENT, COMBINING TILDE + key { [ 6, asciicircum, 0x01000302 ] }; //COMBINING CIRCUMFLEX ACCENT + key { [ 8, asterisk, 0x01000307, 0x01000323 ] }; //COMBINING DOT ABOVE, COMBINING DOT BELOW + key { [ 9, parenleft, 0x01000306 ] }; //COMBINING BREVE + key { [ 0, parenright, 0x0100030c ] }; //COMBINING CARON + key { [ 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 { - 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 { - vmods = LevelFive, - symbols[Group1] = [ ISO_Level5_Shift ], - actions[Group1] = [ SetMods(modifiers=LevelFive) ] - }; - modifier_map Mod3 { }; - - replace key { - vmods = NumLock, - symbols[Group1] = [ NoSymbol ], - actions[Group1] = [ SetMods(modifiers=NumLock) ] - }; - modifier_map Mod2 { }; -}; - -partial modifier_keys -xkb_symbols "lsgt_switch_lock" { - - include "level5(lock)" - - key { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { - 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 { + type[Group1]="ONE_LEVEL", + symbols[Group1] = [ ISO_Level5_Shift ] + }; + modifier_map Mod3 { ISO_Level5_Shift }; +}; + +partial modifier_keys +xkb_symbols "lsgt_switch" { + key { + type[Group1]="ONE_LEVEL", + symbols[Group1] = [ ISO_Level5_Shift ] + }; + modifier_map Mod3 { ISO_Level5_Shift }; +}; + +partial modifier_keys +xkb_symbols "ralt_switch" { + key { + 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 { + vmods = LevelFive, + symbols[Group1] = [ ISO_Level5_Shift ], + actions[Group1] = [ SetMods(modifiers=LevelFive) ] + }; + modifier_map Mod3 { }; + + replace key { + vmods = NumLock, + symbols[Group1] = [ NoSymbol ], + actions[Group1] = [ SetMods(modifiers=NumLock) ] + }; + modifier_map Mod2 { }; +}; + +partial modifier_keys +xkb_symbols "lsgt_switch_lock" { + + include "level5(lock)" + + key { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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 { + 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@ -- cgit v1.2.3