summaryrefslogtreecommitdiff
path: root/Xext
diff options
context:
space:
mode:
authorKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:54 +0000
committerKaleb Keithley <kaleb@freedesktop.org>2003-11-14 15:54:54 +0000
commitded6147bfb5d75ff1e67c858040a628b61bc17d1 (patch)
tree82355105e93cdac89ef7d987424351c77545faf0 /Xext
parentcb6ef07bf01e72d1a6e6e83ceb7f76d6534da941 (diff)
R6.6 is the Xorg base-lineXORG-MAIN
Diffstat (limited to 'Xext')
-rw-r--r--Xext/EVI.c179
-rw-r--r--Xext/EVIstruct.h53
-rw-r--r--Xext/README.xtest1-ddx90
-rw-r--r--Xext/SecurityPolicy88
-rw-r--r--Xext/appgroup.c810
-rw-r--r--Xext/bigreq.c86
-rw-r--r--Xext/cup.c340
-rw-r--r--Xext/dpms.c433
-rw-r--r--Xext/dpmsstubs.c48
-rw-r--r--Xext/mbuf.c2041
-rw-r--r--Xext/mbufbf.c1052
-rw-r--r--Xext/mbufpx.c646
-rw-r--r--Xext/mitmisc.c153
-rw-r--r--Xext/panoramiX.c780
-rw-r--r--Xext/panoramiXSwap.c158
-rw-r--r--Xext/panoramiXprocs.c3034
-rw-r--r--Xext/sampleEVI.c97
-rw-r--r--Xext/security.c1995
-rw-r--r--Xext/shape.c1217
-rw-r--r--Xext/shm.c1010
-rw-r--r--Xext/sleepuntil.c211
-rw-r--r--Xext/sync.c2322
-rw-r--r--Xext/xcmisc.c218
-rw-r--r--Xext/xprint.c2873
-rw-r--r--Xext/xtest.c533
-rw-r--r--Xext/xtest1dd.c1613
-rw-r--r--Xext/xtest1di.c966
27 files changed, 23046 insertions, 0 deletions
diff --git a/Xext/EVI.c b/Xext/EVI.c
new file mode 100644
index 000000000..8ccc31af2
--- /dev/null
+++ b/Xext/EVI.c
@@ -0,0 +1,179 @@
+/* $Xorg: EVI.c,v 1.3 2000/08/17 19:47:55 cpqbld Exp $ */
+/************************************************************
+Copyright (c) 1997 by Silicon Graphics Computer Systems, Inc.
+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 Silicon Graphics not be
+used in advertising or publicity pertaining to distribution
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS 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.
+********************************************************/
+#include "X.h"
+#include "Xproto.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "dix.h"
+#define _XEVI_SERVER_
+#include "XEVIstr.h"
+#include "EVIstruct.h"
+static unsigned char XEVIReqCode = 0;
+static EviPrivPtr eviPriv;
+static int
+ProcEVIQueryVersion(ClientPtr client)
+{
+ REQUEST(xEVIQueryVersionReq);
+ xEVIQueryVersionReply rep;
+ register int n;
+ REQUEST_SIZE_MATCH (xEVIQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = XEVI_MAJOR_VERSION;
+ rep.minorVersion = XEVI_MAJOR_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof (xEVIQueryVersionReply), (char *)&rep);
+ return (client->noClientException);
+}
+#define swapEviInfo(eviInfo, l) \
+{ \
+ int l1 = l; \
+ xExtendedVisualInfo *eviInfo1 = eviInfo; \
+ while (l1-- > 0) { \
+ swapl(&eviInfo1->core_visual_id, n); \
+ swapl(&eviInfo1->transparency_value, n); \
+ swaps(&eviInfo1->num_colormap_conflicts, n); \
+ eviInfo1++; \
+ } \
+}
+#define swapVisual(visual, l) \
+{ \
+ int l1 = l; \
+ VisualID32 *visual1 = visual; \
+ while (l1-- > 0) { \
+ swapl(visual1, n); \
+ visual1++; \
+ } \
+}
+static int
+ProcEVIGetVisualInfo(ClientPtr client)
+{
+ REQUEST(xEVIGetVisualInfoReq);
+ xEVIGetVisualInfoReply rep;
+ int n, n_conflict, n_info, sz_info, sz_conflict;
+ VisualID32 *conflict;
+ xExtendedVisualInfo *eviInfo;
+ int status;
+ REQUEST_FIXED_SIZE(xEVIGetVisualInfoReq, stuff->n_visual * sz_VisualID32);
+ status = eviPriv->getVisualInfo((VisualID32 *)&stuff[1], (int)stuff->n_visual,
+ &eviInfo, &n_info, &conflict, &n_conflict);
+ if (status != Success)
+ return status;
+ sz_info = n_info * sz_xExtendedVisualInfo;
+ sz_conflict = n_conflict * sz_VisualID32;
+ rep.type = X_Reply;
+ rep.n_info = n_info;
+ rep.n_conflicts = n_conflict;
+ rep.sequenceNumber = client->sequence;
+ rep.length = (sz_info + sz_conflict) >> 2;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.n_info, n);
+ swapl(&rep.n_conflicts, n);
+ swapEviInfo(eviInfo, n_info);
+ swapVisual(conflict, n_conflict);
+ }
+ WriteToClient(client, sz_xEVIGetVisualInfoReply, (char *)&rep);
+ WriteToClient(client, sz_info, (char *)eviInfo);
+ WriteToClient(client, sz_conflict, (char *)conflict);
+ eviPriv->freeVisualInfo(eviInfo, conflict);
+ return (client->noClientException);
+}
+static int
+ProcEVIDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ switch (stuff->data) {
+ case X_EVIQueryVersion:
+ return ProcEVIQueryVersion (client);
+ case X_EVIGetVisualInfo:
+ return ProcEVIGetVisualInfo (client);
+ default:
+ return BadRequest;
+ }
+}
+static int
+SProcEVIQueryVersion(client)
+ClientPtr client;
+{
+ REQUEST(xEVIQueryVersionReq);
+ int n;
+ swaps(&stuff->length, n);
+ return ProcEVIQueryVersion(client);
+}
+static int
+SProcEVIGetVisualInfo(ClientPtr client)
+{
+ register int n;
+ REQUEST(xEVIGetVisualInfoReq);
+ swaps(&stuff->length, n);
+ return ProcEVIGetVisualInfo(client);
+}
+static int
+SProcEVIDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_EVIQueryVersion:
+ return SProcEVIQueryVersion (client);
+ case X_EVIGetVisualInfo:
+ return SProcEVIGetVisualInfo (client);
+ default:
+ return BadRequest;
+ }
+}
+/*ARGSUSED*/
+static void
+EVIResetProc(ExtensionEntry *extEntry)
+{
+ eviDDXReset();
+}
+/****************
+ * XEVIExtensionInit
+ *
+ * Called from InitExtensions in main() or from QueryExtension() if the
+ * extension is dynamically loaded.
+ *
+ ****************/
+void
+EVIExtensionInit(void)
+{
+ ExtensionEntry *extEntry, *AddExtension();
+ if (extEntry = AddExtension(EVINAME, 0, 0,
+ ProcEVIDispatch,
+ SProcEVIDispatch,
+ EVIResetProc, StandardMinorOpcode))
+ {
+ XEVIReqCode = (unsigned char)extEntry->base;
+ eviPriv = eviDDXInit();
+ }
+}
diff --git a/Xext/EVIstruct.h b/Xext/EVIstruct.h
new file mode 100644
index 000000000..9bb24b0d2
--- /dev/null
+++ b/Xext/EVIstruct.h
@@ -0,0 +1,53 @@
+/* $Xorg: EVIstruct.h,v 1.3 2000/08/17 19:47:55 cpqbld Exp $ */
+/************************************************************
+Copyright (c) 1997 by Silicon Graphics Computer Systems, Inc.
+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 Silicon Graphics not be
+used in advertising or publicity pertaining to distribution
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS 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 EVI_STRUCT_H
+#define EVI_STRUCT_H
+/*
+ ******************************************************************************
+ ** Per-ddx data
+ ******************************************************************************
+ */
+typedef int (*GetVisualInfoProc)(
+#if NeedNestedPrototypes
+ VisualID32*,
+ int,
+ xExtendedVisualInfo**,
+ int*,
+ VisualID32**,
+ int*
+#endif
+);
+typedef void (*FreeVisualInfoProc)(
+#if NeedNestedPrototypes
+ xExtendedVisualInfo*,
+ VisualID32*
+#endif
+);
+typedef struct _EviPrivRec {
+ GetVisualInfoProc getVisualInfo;
+ FreeVisualInfoProc freeVisualInfo;
+} EviPrivRec, *EviPrivPtr;
+extern EviPrivPtr eviDDXInit();
+extern void eviDDXReset();
+#endif /* EVI_STRUCT_H */
diff --git a/Xext/README.xtest1-ddx b/Xext/README.xtest1-ddx
new file mode 100644
index 000000000..bdf7943b7
--- /dev/null
+++ b/Xext/README.xtest1-ddx
@@ -0,0 +1,90 @@
+There are several code fragments that need to be placed in the device
+dependent part of the server. These are described below. These code
+fragments are device and implementation dependent.
+
+This code fragment should go in your ddx InitInput() routine:
+
+#ifdef XTESTEXT1
+extern KeyCode xtest_command_key;
+#endif
+
+#ifdef XTESTEXT1
+ xtest_command_key = <whatever-is-a-good-keycode-for-your-keyboard>;
+#endif
+
+This code fragment should go at the front of the file that handles
+keyboards:
+
+#ifdef XTESTEXT1
+/*
+ * defined in xtestext1di.c
+ */
+extern int on_steal_input;
+extern Bool XTestStealKeyData();
+#endif XTESTEXT1
+
+This code fragment should go in the function that parses input from the
+keyboard or pointer after you know what input action has occurred, but before
+you have told the server about it. If conditionalizes the actual function
+call to pass the information on:
+
+#ifdef XTESTEXT1
+ if (!on_steal_input ||
+ XTestStealKeyData(code, direction, dev_type, x, y))
+#endif /* XTESTEXT1 */
+ handle_device_event(...);
+
+This code fragment should go in the function that handles mouse motion after
+you have figured out how much the mouse has moved:
+
+#ifdef XTESTEXT1
+ if (on_steal_input)
+ XTestStealMotionData(dx, dy, dev, x, y);
+#endif XTESTEXT1
+
+
+This code fragment should go at the front of the os-specific code where
+you wait (by doing a select on the socket in our implementation) for
+something to happen:
+
+#ifdef XTESTEXT1
+extern int playback_on;
+void XTestComputeWaitTime();
+#endif XTESTEXT1
+
+These code fragments should go in the os-specific code on both sides of
+where you wait (by doing a select on the socket in our implementation)
+for something to happen:
+
+#ifdef XTESTEXT1
+ if (playback_on)
+ XTestComputeWaitTime(wt = &waittime);
+#endif XTESTEXT1
+ ... code to do select ...
+ WakeupHandler(i, LastSelectMask);
+#ifdef XTESTEXT1
+ if (playback_on)
+ i = XTestProcessInputAction(i, &waittime);
+#endif XTESTEXT1
+
+
+You also need to implement the following routines (documentation
+is needed; for now, see server/ddx/hp/hp/x_hil.c):
+
+void
+XTestGenerateEvent(dev_type, keycode, keystate, mousex, mousey)
+ int dev_type;
+ int keycode;
+ int keystate;
+ int mousex;
+ int mousey;
+
+void
+XTestGetPointerPos(fmousex, fmousey)
+ short *fmousex, *fmousey;
+
+void
+XTestJumpPointer(jx, jy, dev_type)
+ int jx;
+ int jy;
+ int dev_type;
diff --git a/Xext/SecurityPolicy b/Xext/SecurityPolicy
new file mode 100644
index 000000000..cc521c263
--- /dev/null
+++ b/Xext/SecurityPolicy
@@ -0,0 +1,88 @@
+version-1
+
+# $Xorg: SecurityPolicy,v 1.3 2000/08/17 19:47:56 cpqbld Exp $
+
+# The site policy fields are interpreted by the XC-QUERY-SECURITY-1
+# authorization protocol. The values are arbitrary and site-specific.
+# Refer to the Security Extension Specification for the usage of the policies.
+#sitepolicy A
+#sitepolicy B
+#sitepolicy C
+
+# Property access rules:
+# property <property> <window> <permissions>
+# <window> ::= any | root | <propertyselector>
+# <propertyselector> ::= <property> | <property>=<value>
+# <permissions> :== [ <operation> | <action> | <space> ]*
+# <operation> :== r | w | d
+# r read
+# w write
+# d delete
+# <action> :== a | i | e
+# a allow
+# i ignore
+# e error
+
+# Allow reading of application resources, but not writing.
+property RESOURCE_MANAGER root ar iw
+property SCREEN_RESOURCES root ar iw
+
+# Ignore attempts to use cut buffers. Giving errors causes apps to crash,
+# and allowing access may give away too much information.
+property CUT_BUFFER0 root irw
+property CUT_BUFFER1 root irw
+property CUT_BUFFER2 root irw
+property CUT_BUFFER3 root irw
+property CUT_BUFFER4 root irw
+property CUT_BUFFER5 root irw
+property CUT_BUFFER6 root irw
+property CUT_BUFFER7 root irw
+
+# If you are using Motif, you probably want these.
+property _MOTIF_DEFAULT_BINDINGS root ar iw
+property _MOTIF_DRAG_WINDOW root ar iw
+property _MOTIF_DRAG_TARGETS any ar iw
+property _MOTIF_DRAG_ATOMS any ar iw
+property _MOTIF_DRAG_ATOM_PAIRS any ar iw
+
+# If you are running CDE you also need these
+property _MOTIF_WM_INFO root arw
+property TT_SESSION root irw
+property WM_ICON_SIZE root irw
+property "SDT Pixel Set" any irw
+
+# The next two rules let xwininfo -tree work when untrusted.
+property WM_NAME any ar
+
+# Allow read of WM_CLASS, but only for windows with WM_NAME.
+# This might be more restrictive than necessary, but demonstrates
+# the <required property> facility, and is also an attempt to
+# say "top level windows only."
+property WM_CLASS WM_NAME ar
+
+# These next three let xlsclients work untrusted. Think carefully
+# before including these; giving away the client machine name and command
+# may be exposing too much.
+property WM_STATE WM_NAME ar
+property WM_CLIENT_MACHINE WM_NAME ar
+property WM_COMMAND WM_NAME ar
+
+# To let untrusted clients use the standard colormaps created by
+# xstdcmap, include these lines.
+property RGB_DEFAULT_MAP root ar
+property RGB_BEST_MAP root ar
+property RGB_RED_MAP root ar
+property RGB_GREEN_MAP root ar
+property RGB_BLUE_MAP root ar
+property RGB_GRAY_MAP root ar
+
+# To let untrusted clients use the color management database created
+# by xcmsdb, include these lines.
+property XDCCC_LINEAR_RGB_CORRECTION root ar
+property XDCCC_LINEAR_RGB_MATRICES root ar
+property XDCCC_GRAY_SCREENWHITEPOINT root ar
+property XDCCC_GRAY_CORRECTION root ar
+
+# To let untrusted clients use the overlay visuals that many vendors
+# support, include this line.
+property SERVER_OVERLAY_VISUALS root ar
diff --git a/Xext/appgroup.c b/Xext/appgroup.c
new file mode 100644
index 000000000..71e74da38
--- /dev/null
+++ b/Xext/appgroup.c
@@ -0,0 +1,810 @@
+/*
+Copyright 1996, 1998, 2001 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.
+*/
+/* $Xorg: appgroup.c,v 1.6 2001/02/09 02:04:32 xorgcvs Exp $ */
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "colormapst.h"
+#include "servermd.h"
+#define _XAG_SERVER_
+#include "Xagstr.h"
+#define _SECURITY_SERVER
+#include "security.h"
+#include "Xfuncproto.h"
+
+#define XSERV_t
+#include <X11/Xtrans.h>
+#include "../os/osdep.h"
+
+#include <stdio.h>
+
+typedef struct _AppGroupRec {
+ struct _AppGroupRec* next;
+ XID appgroupId;
+ ClientPtr* clients;
+ int nclients;
+ ClientPtr leader;
+ Bool single_screen;
+ Window default_root;
+ VisualID root_visual;
+ Colormap default_colormap;
+ Pixel black_pixel;
+ Pixel white_pixel;
+ xConnSetupPrefix connSetupPrefix;
+ char* ConnectionInfo;
+} AppGroupRec, *AppGroupPtr;
+
+static int ProcXagDispatch (), SProcXagDispatch ();
+static void XagResetProc ();
+
+static unsigned char XagReqCode = 0;
+static int XagErrorBase;
+static int XagCallbackRefCount = 0;
+
+static RESTYPE RT_APPGROUP;
+static AppGroupPtr appGrpList = NULL;
+
+extern WindowPtr* WindowTable;
+extern xConnSetupPrefix connSetupPrefix;
+extern char* ConnectionInfo;
+
+static
+int XagAppGroupFree (what, id)
+ pointer what;
+ XID id; /* unused */
+{
+ int i;
+ AppGroupPtr pAppGrp = (AppGroupPtr) what;
+
+ if (pAppGrp->leader)
+ for (i = 0; i < pAppGrp->nclients; i++) {
+ pAppGrp->clients[i]->appgroup = NULL;
+ CloseDownClient (pAppGrp->clients[i]);
+ }
+
+ if (pAppGrp == appGrpList)
+ appGrpList = appGrpList->next;
+ else {
+ AppGroupPtr tpAppGrp;
+ for (tpAppGrp = appGrpList;
+ tpAppGrp->next != NULL;
+ tpAppGrp = tpAppGrp->next) {
+ if (tpAppGrp->next == pAppGrp) {
+ tpAppGrp->next = tpAppGrp->next->next;
+ break;
+ }
+ }
+ }
+ (void) xfree (pAppGrp->clients);
+ (void) xfree (pAppGrp->ConnectionInfo);
+ (void) xfree (what);
+ return Success;
+}
+
+/* static */
+void XagClientStateChange (pcbl, nulldata, calldata)
+ CallbackListPtr* pcbl;
+ pointer nulldata;
+ pointer calldata;
+{
+ SecurityAuthorizationPtr pAuth;
+ NewClientInfoRec* pci = (NewClientInfoRec*) calldata;
+ ClientPtr pClient = pci->client;
+ AppGroupPtr pAppGrp;
+ XID authId;
+
+ if (!pClient->appgroup) {
+ switch (pClient->clientState) {
+
+ case ClientStateAuthenticating:
+ case ClientStateRunning:
+ case ClientStateCheckingSecurity:
+ return;
+
+ case ClientStateInitial:
+ case ClientStateCheckedSecurity:
+ /*
+ * If the client is connecting via a firewall proxy (which
+ * uses XC-QUERY-SECURITY-1, then the authId is available
+ * during ClientStateCheckedSecurity, otherwise it's
+ * available during ClientStateInitial.
+ *
+ * Don't get it from pClient because can't guarantee the order
+ * of the callbacks and the security extension might not have
+ * plugged it in yet.
+ */
+ authId = AuthorizationIDOfClient(pClient);
+ break;
+
+ case ClientStateGone:
+ case ClientStateRetained:
+ /*
+ * Don't get if from AuthorizationIDOfClient because can't
+ * guarantee the order of the callbacks and the security
+ * extension may have torn down the client's private data
+ */
+ authId = pClient->authId;
+ break;
+ }
+
+ if (authId == None)
+ return;
+
+ pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(pClient,
+ authId, SecurityAuthorizationResType, SecurityReadAccess);
+
+ if (pAuth == NULL)
+ return;
+
+ for (pAppGrp = appGrpList; pAppGrp != NULL; pAppGrp = pAppGrp->next)
+ if (pAppGrp->appgroupId == pAuth->group) break;
+ } else {
+ pAppGrp = pClient->appgroup;
+ }
+
+ if (!pAppGrp)
+ return;
+
+ switch (pClient->clientState) {
+ case ClientStateAuthenticating:
+ case ClientStateRunning:
+ case ClientStateCheckingSecurity:
+ break;
+
+ case ClientStateInitial:
+ case ClientStateCheckedSecurity:
+ /* see the comment above about Initial vs. CheckedSecurity */
+ {
+ /* if this client already in AppGroup, don't add it again */
+ int i;
+ for (i = 0; i < pAppGrp->nclients; i++)
+ if (pClient == pAppGrp->clients[i]) return;
+ }
+ pAppGrp->clients = (ClientPtr*) xrealloc (pAppGrp->clients,
+ ++pAppGrp->nclients * sizeof (ClientPtr));
+ pAppGrp->clients[pAppGrp->nclients - 1] = pClient;
+ pClient->appgroup = pAppGrp;
+ break;
+
+ case ClientStateGone:
+ case ClientStateRetained: /* client disconnected, dump it */
+ {
+ int i;
+ for (i = 0; i < pAppGrp->nclients; i++)
+ if (pAppGrp->clients[i] == pClient) {
+ pAppGrp->clients[i] = NULL;
+ break;
+ }
+ for (i = 0; i < pAppGrp->nclients; i++)
+ if (pAppGrp->clients[i] == NULL && i + 1 < pAppGrp->nclients)
+ pAppGrp->clients[i] = pAppGrp->clients[i + 1];
+ pAppGrp->nclients--;
+ }
+ pClient->appgroup = NULL; /* redundant, pClient will be freed */
+ break;
+ }
+}
+
+void
+XagExtensionInit ()
+{
+ ExtensionEntry* extEntry;
+
+ if (extEntry = AddExtension (XAGNAME,
+ 0,
+ XagNumberErrors,
+ ProcXagDispatch,
+ SProcXagDispatch,
+ XagResetProc,
+ StandardMinorOpcode)) {
+ XagReqCode = (unsigned char)extEntry->base;
+ XagErrorBase = extEntry->errorBase;
+ RT_APPGROUP = CreateNewResourceType (XagAppGroupFree);
+ }
+}
+
+/*ARGSUSED*/
+static
+void XagResetProc (extEntry)
+ ExtensionEntry* extEntry;
+{
+ DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL);
+ XagCallbackRefCount = 0;
+ while (appGrpList) XagAppGroupFree ((pointer) appGrpList, 0);
+}
+
+static
+int ProcXagQueryVersion (client)
+ register ClientPtr client;
+{
+ REQUEST (xXagQueryVersionReq);
+ xXagQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xXagQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequence_number = client->sequence;
+ rep.server_major_version = XAG_MAJOR_VERSION;
+ rep.server_minor_version = XAG_MINOR_VERSION;
+ if (client->swapped) {
+ swaps (&rep.sequence_number, n);
+ swapl (&rep.length, n);
+ swaps (&rep.server_major_version, n);
+ swaps (&rep.server_minor_version, n);
+ }
+ WriteToClient (client, sizeof (xXagQueryVersionReply), (char *)&rep);
+ return client->noClientException;
+}
+
+static
+void ProcessAttr (pAppGrp, client, attrib_mask, attribs)
+ AppGroupPtr pAppGrp;
+ ClientPtr client;
+ unsigned int attrib_mask;
+ CARD32* attribs;
+{
+ int i;
+
+ for (i = 0; i <= XagNappGroupLeader; i++) {
+ switch (attrib_mask & (1 << i)) {
+ case XagSingleScreenMask:
+ pAppGrp->single_screen = *attribs;
+ break;
+ case XagDefaultRootMask:
+ pAppGrp->default_root = *attribs;
+ break;
+ case XagRootVisualMask:
+ pAppGrp->root_visual = *attribs;
+ break;
+ case XagDefaultColormapMask:
+ pAppGrp->default_colormap = *attribs;
+ break;
+ case XagBlackPixelMask:
+ pAppGrp->black_pixel = *attribs;
+ break;
+ case XagWhitePixelMask:
+ pAppGrp->white_pixel = *attribs;
+ break;
+ case XagAppGroupLeaderMask:
+ pAppGrp->leader = client;
+ break;
+ default: continue;
+ }
+ attribs++;
+ }
+}
+
+static
+void CreateConnectionInfo (pAppGrp)
+ AppGroupPtr pAppGrp;
+{
+ extern int connBlockScreenStart;
+ xConnSetup *setup = (xConnSetup*) ConnectionInfo;
+ xWindowRoot* rootp;
+ xWindowRoot* roots[MAXSCREENS];
+ unsigned int rootlens[MAXSCREENS];
+ xDepth* depth;
+ int olen;
+ int snum, i;
+
+ rootp = (xWindowRoot*) (ConnectionInfo + connBlockScreenStart);
+ for (snum = 0; snum < screenInfo.numScreens; snum++) {
+
+ rootlens[snum] = sizeof (xWindowRoot);
+ roots[snum] = rootp;
+
+ depth = (xDepth*) (rootp + 1);
+ for (i = 0; i < rootp->nDepths; i++) {
+ rootlens[snum] += sizeof (xDepth) +
+ depth->nVisuals * sizeof (xVisualType);
+ depth = (xDepth *)(((char*)(depth + 1)) +
+ depth->nVisuals * sizeof (xVisualType));
+ }
+ rootp = (xWindowRoot*) depth;
+ }
+ snum = 0;
+ if (pAppGrp->default_root) {
+ for (; snum < screenInfo.numVideoScreens; snum++) {
+ if (roots[snum]->windowId == pAppGrp->default_root)
+ break;
+ }
+ }
+ olen = connBlockScreenStart + rootlens[snum];
+ for (i = screenInfo.numVideoScreens; i < screenInfo.numScreens; i++)
+ olen += rootlens[i];
+ pAppGrp->ConnectionInfo = (char*) xalloc (olen);
+ if (!pAppGrp->ConnectionInfo)
+ return;
+ memmove (pAppGrp->ConnectionInfo, ConnectionInfo, connBlockScreenStart);
+ ((xConnSetup*) (pAppGrp->ConnectionInfo))->numRoots =
+ 1 + screenInfo.numScreens - screenInfo.numVideoScreens;
+ memmove (pAppGrp->ConnectionInfo + connBlockScreenStart,
+ (void*) roots[snum], rootlens[snum]);
+ rootp = (xWindowRoot*) (pAppGrp->ConnectionInfo + connBlockScreenStart);
+ if (pAppGrp->default_colormap) {
+ rootp->defaultColormap = pAppGrp->default_colormap;
+ rootp->whitePixel = pAppGrp->white_pixel;
+ rootp->blackPixel = pAppGrp->black_pixel;
+ }
+ if (pAppGrp->root_visual)
+ rootp->rootVisualID = pAppGrp->root_visual;
+ rootp = (xWindowRoot*) (((char*)rootp) + rootlens[snum]);
+ for (i = screenInfo.numVideoScreens; i < screenInfo.numScreens; i++) {
+ memmove ((void*) rootp, (void*) roots[i], rootlens[i]);
+ rootp = (xWindowRoot*) (((char*) rootp) + rootlens[i]);
+ }
+ pAppGrp->connSetupPrefix = connSetupPrefix;
+ pAppGrp->connSetupPrefix.length = olen >> 2;
+}
+
+static
+AppGroupPtr CreateAppGroup (client, appgroupId, attrib_mask, attribs)
+ ClientPtr client;
+ XID appgroupId;
+ unsigned int attrib_mask;
+ CARD32* attribs;
+{
+ AppGroupPtr pAppGrp;
+ int i;
+
+ pAppGrp = (AppGroupPtr) xalloc (sizeof(AppGroupRec));
+ if (pAppGrp) {
+ pAppGrp->next = appGrpList;
+ appGrpList = pAppGrp;
+ pAppGrp->appgroupId = appgroupId;
+ pAppGrp->clients = (ClientPtr*) xalloc (0);
+ pAppGrp->nclients = 0;
+ pAppGrp->leader = NULL;
+ pAppGrp->default_root = 0;
+ pAppGrp->root_visual = 0;
+ pAppGrp->default_colormap = 0;
+ pAppGrp->black_pixel = -1;
+ pAppGrp->white_pixel = -1;
+ pAppGrp->ConnectionInfo = NULL;
+ ProcessAttr (pAppGrp, client, attrib_mask, attribs);
+ }
+ return pAppGrp;
+}
+
+static
+int AttrValidate (client, attrib_mask, pAppGrp)
+ ClientPtr client;
+ int attrib_mask;
+ AppGroupPtr pAppGrp;
+{
+ WindowPtr pWin;
+ int idepth, ivids, found;
+ ScreenPtr pScreen;
+ DepthPtr pDepth;
+ ColormapPtr pColormap;
+
+ pWin = LookupWindow (pAppGrp->default_root, client);
+ /* XXX check that pWin is not NULL */
+ pScreen = pWin->drawable.pScreen;
+ if (WindowTable[pScreen->myNum]->drawable.id != pAppGrp->default_root)
+ return BadWindow;
+ pDepth = pScreen->allowedDepths;
+ if (pAppGrp->root_visual) {
+ found = FALSE;
+ for (idepth = 0; idepth < pScreen->numDepths; idepth++, pDepth++) {
+ for (ivids = 0; ivids < pDepth->numVids; ivids++) {
+ if (pAppGrp->root_visual == pDepth->vids[ivids]) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+ if (!found)
+ return BadMatch;
+ }
+ if (pAppGrp->default_colormap) {
+
+ pColormap = (ColormapPtr)LookupIDByType (pAppGrp->default_colormap, RT_COLORMAP);
+ /* XXX check that pColormap is not NULL */
+ if (pColormap->pScreen != pScreen)
+ return BadColor;
+ if (pColormap->pVisual->vid != (pAppGrp->root_visual ? pAppGrp->root_visual : pScreen->rootVisual))
+ return BadMatch;
+ }
+ return client->noClientException;
+}
+
+/* static */
+int ProcXagCreate (client)
+ register ClientPtr client;
+{
+ REQUEST (xXagCreateReq);
+ AppGroupPtr pAppGrp;
+ int ret;
+
+ REQUEST_AT_LEAST_SIZE (xXagCreateReq);
+
+ LEGAL_NEW_RESOURCE (stuff->app_group, client);
+ pAppGrp = CreateAppGroup (client, stuff->app_group,
+ stuff->attrib_mask, (CARD32*) &stuff[1]);
+ if (!pAppGrp)
+ return BadAlloc;
+ ret = AttrValidate (client, stuff->attrib_mask, pAppGrp);
+ if (ret != Success) {
+ XagAppGroupFree ((pointer)pAppGrp, (XID)0);
+ return ret;
+ }
+ if (pAppGrp->single_screen) {
+ CreateConnectionInfo (pAppGrp);
+ if (!pAppGrp->ConnectionInfo)
+ return BadAlloc;
+ }
+ if (!AddResource (stuff->app_group, RT_APPGROUP, (pointer)pAppGrp))
+ return BadAlloc;
+ if (XagCallbackRefCount++ == 0)
+ (void) AddCallback (&ClientStateCallback, XagClientStateChange, NULL);
+ return client->noClientException;
+}
+
+/* static */
+int ProcXagDestroy (client)
+ register ClientPtr client;
+{
+ AppGroupPtr pAppGrp;
+ REQUEST (xXagDestroyReq);
+
+ REQUEST_SIZE_MATCH (xXagDestroyReq);
+ pAppGrp = (AppGroupPtr)SecurityLookupIDByType (client,
+ (XID)stuff->app_group, RT_APPGROUP, SecurityReadAccess);
+ if (!pAppGrp) return XagBadAppGroup;
+ FreeResource ((XID)stuff->app_group, RT_NONE);
+ if (--XagCallbackRefCount == 0)
+ (void) DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL);
+ return client->noClientException;
+}
+
+static
+int ProcXagGetAttr (client)
+ register ClientPtr client;
+{
+ AppGroupPtr pAppGrp;
+ REQUEST (xXagGetAttrReq);
+ xXagGetAttrReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH (xXagGetAttrReq);
+ pAppGrp = (AppGroupPtr)SecurityLookupIDByType (client,
+ (XID)stuff->app_group, RT_APPGROUP, SecurityReadAccess);
+ if (!pAppGrp) return XagBadAppGroup;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequence_number = client->sequence;
+ rep.default_root = pAppGrp->default_root;
+ rep.root_visual = pAppGrp->root_visual;
+ rep.default_colormap = pAppGrp->default_colormap;
+ rep.black_pixel = pAppGrp->black_pixel;
+ rep.white_pixel = pAppGrp->white_pixel;
+ rep.single_screen = pAppGrp->single_screen;
+ rep.app_group_leader = (pAppGrp->leader) ? 1 : 0;
+ if (client->swapped) {
+ swaps (&rep.sequence_number, n);
+ swapl (&rep.length, n);
+ swapl (&rep.default_root, n);
+ swapl (&rep.root_visual, n);
+ swapl (&rep.default_colormap, n);
+ swapl (&rep.black_pixel, n);
+ swapl (&rep.white_pixel, n);
+ }
+ WriteToClient (client, sizeof (xXagGetAttrReply), (char *)&rep);
+ return client->noClientException;
+}
+
+static
+int ProcXagQuery (client)
+ register ClientPtr client;
+{
+ ClientPtr pClient;
+ AppGroupPtr pAppGrp;
+ REQUEST (xXagQueryReq);
+ int n;
+
+ REQUEST_SIZE_MATCH (xXagQueryReq);
+ pClient = LookupClient (stuff->resource, client);
+ for (pAppGrp = appGrpList; pAppGrp != NULL; pAppGrp = pAppGrp->next)
+ for (n = 0; n < pAppGrp->nclients; n++)
+ if (pAppGrp->clients[n] == pClient) {
+ xXagQueryReply rep;
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequence_number = client->sequence;
+ rep.app_group = pAppGrp->appgroupId;
+ if (client->swapped) {
+ swaps (&rep.sequence_number, n);
+ swapl (&rep.length, n);
+ swapl (&rep.app_group, n);
+ }
+ WriteToClient (client, sizeof (xXagQueryReply), (char *)&rep);
+ return client->noClientException;
+ }
+
+ return BadMatch;
+}
+
+static
+int ProcXagCreateAssoc (client)
+ register ClientPtr client;
+{
+ REQUEST (xXagCreateAssocReq);
+
+ REQUEST_SIZE_MATCH (xXagCreateAssocReq);
+#ifdef WIN32
+ if (stuff->window_type != XagWindowTypeWin32)
+#else
+ if (stuff->window_type != XagWindowTypeX11)
+#endif
+ return BadMatch;
+#ifdef WIN32 /* and Mac, etc */
+ if (!LocalClient (client))
+ return BadAccess;
+#endif
+
+/* Macintosh, OS/2, and MS-Windows servers have some work to do here */
+
+ return client->noClientException;
+}
+
+static
+int ProcXagDestroyAssoc (client)
+ register ClientPtr client;
+{
+ REQUEST (xXagDestroyAssocReq);
+
+ REQUEST_SIZE_MATCH (xXagDestroyAssocReq);
+/* Macintosh, OS/2, and MS-Windows servers have some work to do here */
+ return client->noClientException;
+}
+
+static
+int ProcXagDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST (xReq);
+ switch (stuff->data)
+ {
+ case X_XagQueryVersion:
+ return ProcXagQueryVersion (client);
+ case X_XagCreate:
+ return ProcXagCreate (client);
+ case X_XagDestroy:
+ return ProcXagDestroy (client);
+ case X_XagGetAttr:
+ return ProcXagGetAttr (client);
+ case X_XagQuery:
+ return ProcXagQuery (client);
+ case X_XagCreateAssoc:
+ return ProcXagCreateAssoc (client);
+ case X_XagDestroyAssoc:
+ return ProcXagDestroyAssoc (client);
+ default:
+ return BadRequest;
+ }
+}
+
+static
+int SProcXagQueryVersion (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xXagQueryVersionReq);
+ swaps(&stuff->length, n);
+ return ProcXagQueryVersion(client);
+}
+
+static
+int SProcXagCreate (client)
+ ClientPtr client;
+{
+ register int n;
+ REQUEST (xXagCreateReq);
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE (xXagCreateReq);
+ swapl (&stuff->app_group, n);
+ swapl (&stuff->attrib_mask, n);
+ SwapRestL (stuff);
+ return ProcXagCreate (client);
+}
+
+static
+int SProcXagDestroy (client)
+ ClientPtr client;
+{
+ register int n;
+ REQUEST (xXagDestroyReq);
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXagDestroyReq);
+ swapl (&stuff->app_group, n);
+ return ProcXagDestroy (client);
+}
+
+static
+int SProcXagGetAttr (client)
+ ClientPtr client;
+{
+ register int n;
+ REQUEST (xXagGetAttrReq);
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXagGetAttrReq);
+ swapl (&stuff->app_group, n);
+ return ProcXagGetAttr (client);
+}
+
+static
+int SProcXagQuery (client)
+ ClientPtr client;
+{
+ register int n;
+ REQUEST (xXagQueryReq);
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXagQueryReq);
+ swapl (&stuff->resource, n);
+ return ProcXagQuery (client);
+}
+
+static
+int SProcXagCreateAssoc (client)
+ ClientPtr client;
+{
+ register int n;
+ REQUEST (xXagCreateAssocReq);
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXagCreateAssocReq);
+ swapl (&stuff->window, n);
+ swapl (&stuff->window_type, n);
+ swaps (&stuff->system_window_len, n);
+ return ProcXagCreateAssoc (client);
+}
+
+static
+int SProcXagDestroyAssoc (client)
+ ClientPtr client;
+{
+ register int n;
+ REQUEST (xXagDestroyAssocReq);
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xXagDestroyAssocReq);
+ swapl (&stuff->window, n);
+ return ProcXagDestroyAssoc (client);
+}
+
+static
+int SProcXagDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_XagQueryVersion:
+ return SProcXagQueryVersion (client);
+ case X_XagCreate:
+ return SProcXagCreate (client);
+ case X_XagDestroy:
+ return SProcXagDestroy (client);
+ case X_XagGetAttr:
+ return SProcXagGetAttr (client);
+ case X_XagQuery:
+ return SProcXagQuery (client);
+ case X_XagCreateAssoc:
+ return SProcXagCreateAssoc (client);
+ case X_XagDestroyAssoc:
+ return SProcXagDestroyAssoc (client);
+ default:
+ return BadRequest;
+ }
+}
+
+Colormap XagDefaultColormap (client)
+ ClientPtr client;
+{
+ return (client->appgroup ? client->appgroup->default_colormap : None);
+}
+
+VisualID XagRootVisual (client)
+ ClientPtr client;
+{
+ return (client->appgroup ? client->appgroup->root_visual : 0);
+}
+
+ClientPtr XagLeader (client)
+ ClientPtr client;
+{
+ return (client->appgroup ? client->appgroup->leader : NULL);
+}
+
+/*
+ * Return whether the Map request event should be sent to the appgroup leader.
+ * We don't want to send it to the leader when the window is on a different
+ * screen, e.g. a print screen.
+ */
+Bool XagIsControlledRoot (client, pParent)
+ ClientPtr client;
+ WindowPtr pParent;
+{
+ if (client->appgroup) {
+ if (client->appgroup->single_screen &&
+ pParent->drawable.id == client->appgroup->default_root)
+ return TRUE;
+ else if (!pParent->parent)
+ return TRUE;
+ else
+ return FALSE;
+ }
+ return FALSE;
+}
+
+void XagConnectionInfo (client, conn_prefix, conn_info, num_screen)
+ ClientPtr client;
+ xConnSetupPrefix** conn_prefix;
+ char** conn_info;
+ int* num_screen;
+{
+ if (client->appgroup && client->appgroup->ConnectionInfo) {
+ *conn_prefix = &client->appgroup->connSetupPrefix;
+ *conn_info = client->appgroup->ConnectionInfo;
+ *num_screen = ((xConnSetup*)(client->appgroup->ConnectionInfo))->numRoots;
+ }
+}
+
+XID XagId (client)
+ ClientPtr client;
+{
+ return (client->appgroup ? client->appgroup->appgroupId : 0);
+}
+
+void XagGetDeltaInfo (client, buf)
+ ClientPtr client;
+ CARD32* buf;
+{
+ *buf++ = (CARD32) client->appgroup->default_root;
+ *buf++ = (CARD32) client->appgroup->root_visual;
+ *buf++ = (CARD32) client->appgroup->default_colormap;
+ *buf++ = (CARD32) client->appgroup->black_pixel;
+ *buf = (CARD32) client->appgroup->white_pixel;
+}
+
+void XagCallClientStateChange (client)
+ ClientPtr client;
+{
+ if (appGrpList) {
+ NewClientInfoRec clientinfo;
+
+ clientinfo.client = client;
+ XagClientStateChange (NULL, NULL, (pointer)&clientinfo);
+ }
+}
diff --git a/Xext/bigreq.c b/Xext/bigreq.c
new file mode 100644
index 000000000..4f4bf5c02
--- /dev/null
+++ b/Xext/bigreq.c
@@ -0,0 +1,86 @@
+/* $Xorg: bigreq.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */
+/*
+
+Copyright 1992, 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.
+
+*/
+
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "bigreqstr.h"
+
+static unsigned char XBigReqCode;
+static int ProcBigReqDispatch();
+static void BigReqResetProc();
+
+void
+BigReqExtensionInit()
+{
+ ExtensionEntry *extEntry, *AddExtension();
+
+ if (extEntry = AddExtension(XBigReqExtensionName, 0, 0,
+ ProcBigReqDispatch, ProcBigReqDispatch,
+ BigReqResetProc, StandardMinorOpcode))
+ XBigReqCode = (unsigned char)extEntry->base;
+ DeclareExtensionSecurity(XBigReqExtensionName, TRUE);
+}
+
+/*ARGSUSED*/
+static void
+BigReqResetProc (extEntry)
+ ExtensionEntry *extEntry;
+{
+}
+
+static int
+ProcBigReqDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xBigReqEnableReq);
+ xBigReqEnableReply rep;
+ register int n;
+
+ if (client->swapped) {
+ swaps(&stuff->length, n);
+ }
+ if (stuff->brReqType != X_BigReqEnable)
+ return BadRequest;
+ REQUEST_SIZE_MATCH(xBigReqEnableReq);
+ client->big_requests = TRUE;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.max_request_size = MAX_BIG_REQUEST_SIZE;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.max_request_size, n);
+ }
+ WriteToClient(client, sizeof(xBigReqEnableReply), (char *)&rep);
+ return(client->noClientException);
+}
diff --git a/Xext/cup.c b/Xext/cup.c
new file mode 100644
index 000000000..4e8cf66b4
--- /dev/null
+++ b/Xext/cup.c
@@ -0,0 +1,340 @@
+/* $Xorg: cup.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */
+/*
+
+Copyright 1997, 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.
+
+*/
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "colormapst.h"
+#include "scrnintstr.h"
+#include "servermd.h"
+#define _XCUP_SERVER_
+#include "Xcupstr.h"
+#include "Xfuncproto.h"
+
+#include "../os/osdep.h"
+
+static int ProcDispatch (), SProcDispatch ();
+static void ResetProc ();
+
+static unsigned char ReqCode = 0;
+static int ErrorBase;
+
+#if defined(WIN32) || defined(TESTWIN32)
+#define HAVE_SPECIAL_DESKTOP_COLORS
+#endif
+
+static xColorItem citems[] = {
+#ifndef HAVE_SPECIAL_DESKTOP_COLORS
+#define CUP_BLACK_PIXEL 0
+#define CUP_WHITE_PIXEL 1
+ /* pix red green blue */
+ { 0, 0, 0, 0, 0, 0 },
+ { 1, 0xffff, 0xffff, 0xffff, 0, 0 }
+#else
+#ifndef WIN32
+ /*
+ This approximates the MS-Windows desktop colormap for testing
+ purposes but has black and white pixels in the typical Unix
+ locations, which should be switched if necessary if your system
+ has blackPixel and whitePixel swapped. No entries are provided
+ for colormap entries 254 and 255 because AllocColor/FindColor
+ will reuse entries zero and one.
+ */
+ { 0, 0, 0, 0, 0, 0 },
+ { 1, 0xffff, 0xffff, 0xffff, 0, 0 },
+ { 2, 0x8000, 0, 0, 0, 0 },
+ { 3, 0, 0x8000, 0, 0, 0 },
+ { 4, 0x8000, 0x8000, 0, 0, 0 },
+ { 5, 0, 0, 0x8000, 0, 0 },
+ { 6, 0x8000, 0, 0x8000, 0, 0 },
+ { 7, 0, 0x8000, 0x8000, 0, 0 },
+ { 8, 0xc000, 0xc000, 0xc000, 0, 0 },
+ { 9, 0xc000, 0xdc00, 0xc000, 0, 0 },
+ { 246, 0xa000, 0xa000, 0xa000, 0, 0 },
+ { 247, 0x8000, 0x8000, 0x8000, 0, 0 },
+ { 248, 0xffff, 0, 0, 0, 0 },
+ { 249, 0, 0xffff, 0, 0, 0 },
+ { 250, 0xffff, 0xffff, 0, 0, 0 },
+ { 251, 0, 0, 0xffff, 0, 0 },
+ { 252, 0xffff, 0, 0xffff, 0, 0 },
+ { 253, 0, 0xffff, 0xffff, 0, 0 }
+#else
+ /*
+ this is the MS-Windows desktop, adjusted for X's 16-bit color
+ specifications.
+ */
+ { 0, 0, 0, 0, 0, 0 },
+ { 1, 0x8000, 0, 0, 0, 0 },
+ { 2, 0, 0x8000, 0, 0, 0 },
+ { 3, 0x8000, 0x8000, 0, 0, 0 },
+ { 4, 0, 0, 0x8000, 0, 0 },
+ { 5, 0x8000, 0, 0x8000, 0, 0 },
+ { 6, 0, 0x8000, 0x8000, 0, 0 },
+ { 7, 0xc000, 0xc000, 0xc000, 0, 0 },
+ { 8, 0xc000, 0xdc00, 0xc000, 0, 0 },
+ { 9, 0xa600, 0xca00, 0xf000, 0, 0 },
+ { 246, 0xff00, 0xfb00, 0xf000, 0, 0 },
+ { 247, 0xa000, 0xa000, 0xa400, 0, 0 },
+ { 248, 0x8000, 0x8000, 0x8000, 0, 0 },
+ { 249, 0xff00, 0, 0, 0, 0 },
+ { 250, 0, 0xff00, 0, 0, 0 },
+ { 251, 0xff00, 0xff00, 0, 0, 0 },
+ { 252, 0, 0, 0xff00, 0, 0 },
+ { 253, 0xff00, 0, 0xff00, 0, 0 },
+ { 254, 0, 0xff00, 0xff00, 0, 0 },
+ { 255, 0xff00, 0xff00, 0xff00, 0, 0 }
+#endif
+#endif
+};
+#define NUM_DESKTOP_COLORS (sizeof citems / sizeof citems[0])
+
+void
+XcupExtensionInit ()
+{
+ ExtensionEntry* extEntry;
+
+ if (extEntry = AddExtension (XCUPNAME,
+ 0,
+ XcupNumberErrors,
+ ProcDispatch,
+ SProcDispatch,
+ ResetProc,
+ StandardMinorOpcode)) {
+ ReqCode = (unsigned char)extEntry->base;
+ ErrorBase = extEntry->errorBase;
+ }
+
+ /* PC servers initialize the desktop colors (citems) here! */
+}
+
+/*ARGSUSED*/
+static
+void ResetProc (extEntry)
+ ExtensionEntry* extEntry;
+{
+}
+
+static
+int ProcQueryVersion (client)
+ register ClientPtr client;
+{
+ REQUEST (xXcupQueryVersionReq);
+ xXcupQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xXcupQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequence_number = client->sequence;
+ rep.server_major_version = XCUP_MAJOR_VERSION;
+ rep.server_minor_version = XCUP_MINOR_VERSION;
+ if (client->swapped) {
+ swaps (&rep.sequence_number, n);
+ swapl (&rep.length, n);
+ swaps (&rep.server_major_version, n);
+ swaps (&rep.server_minor_version, n);
+ }
+ WriteToClient (client, sizeof (xXcupQueryVersionReply), (char *)&rep);
+ return client->noClientException;
+}
+
+static
+int ProcGetReservedColormapEntries (client)
+ register ClientPtr client;
+{
+ REQUEST (xXcupGetReservedColormapEntriesReq);
+ xXcupGetReservedColormapEntriesReply rep;
+ xColorItem* cptr;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xXcupGetReservedColormapEntriesReq);
+
+#ifndef HAVE_SPECIAL_DESKTOP_COLORS
+ citems[CUP_BLACK_PIXEL].pixel =
+ screenInfo.screens[stuff->screen]->blackPixel;
+ citems[CUP_WHITE_PIXEL].pixel =
+ screenInfo.screens[stuff->screen]->whitePixel;
+#endif
+
+ rep.type = X_Reply;
+ rep.sequence_number = client->sequence;
+ rep.length = NUM_DESKTOP_COLORS * 3;
+ if (client->swapped) {
+ swaps (&rep.sequence_number, n);
+ swapl (&rep.length, n);
+ }
+ WriteToClient (client, sizeof (xXcupGetReservedColormapEntriesReply), (char *)&rep);
+ for (n = 0, cptr = citems; n < NUM_DESKTOP_COLORS; n++, cptr++) {
+ if (client->swapped) SwapColorItem (cptr);
+ WriteToClient (client, SIZEOF(xColorItem), (char *)cptr);
+ }
+ return client->noClientException;
+}
+
+static
+int ProcStoreColors (client)
+ register ClientPtr client;
+{
+ REQUEST (xXcupStoreColorsReq);
+ ColormapPtr pcmp;
+
+ REQUEST_AT_LEAST_SIZE (xXcupStoreColorsReq);
+ pcmp = (ColormapPtr) SecurityLookupIDByType (client, stuff->cmap,
+ RT_COLORMAP, SecurityWriteAccess);
+
+ if (pcmp) {
+ int ncolors, n;
+ xXcupStoreColorsReply rep;
+ xColorItem* cptr;
+ Pixel pixel;
+
+ if (!(pcmp->class & DynamicClass))
+ return BadMatch;
+
+ ncolors = (client->req_len << 2) - SIZEOF (xXcupStoreColorsReq);
+ if (ncolors % SIZEOF(xColorItem))
+ return BadLength;
+
+ ncolors /= SIZEOF (xColorItem);
+
+
+ for (n = 0, cptr = (xColorItem*) &stuff[1]; n < ncolors; n++) {
+ Pixel pixel = cptr->pixel;
+
+ if (AllocColor (pcmp,
+ &cptr->red, &cptr->green, &cptr->blue,
+ &pixel, client->index) == Success) {
+ cptr->pixel = pixel;
+ cptr->flags = 0x08;
+ } else
+ cptr->flags = 0;
+ cptr = (xColorItem*) (((char*)cptr) + SIZEOF(xColorItem));
+ }
+
+ rep.type = X_Reply;
+ rep.sequence_number = client->sequence;
+ rep.length = ncolors * 3;
+ if (client->swapped) {
+ swaps (&rep.sequence_number, n);
+ swapl (&rep.length, n);
+ }
+ WriteToClient (client, sizeof (xXcupGetReservedColormapEntriesReply), (char *)&rep);
+ for (n = 0, cptr = (xColorItem*) &stuff[1]; n < ncolors; n++) {
+ if (client->swapped) SwapColorItem (cptr);
+ WriteToClient (client, SIZEOF(xColorItem), (char *)cptr);
+ cptr = (xColorItem*) (((char*)cptr) + SIZEOF(xColorItem));
+ }
+ return client->noClientException;
+ } else {
+ client->errorValue = stuff->cmap;
+ return BadColor;
+ }
+}
+
+static
+int ProcDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST (xReq);
+ switch (stuff->data)
+ {
+ case X_XcupQueryVersion:
+ return ProcQueryVersion (client);
+ case X_XcupGetReservedColormapEntries:
+ return ProcGetReservedColormapEntries (client);
+ case X_XcupStoreColors:
+ return ProcStoreColors (client);
+ default:
+ return BadRequest;
+ }
+}
+
+static
+int SProcQueryVersion (client)
+ register ClientPtr client;
+{
+ register int n;
+
+ REQUEST(xXcupQueryVersionReq);
+ swaps(&stuff->length, n);
+ return ProcQueryVersion(client);
+}
+
+static
+int SProcGetReservedColormapEntries (client)
+ ClientPtr client;
+{
+ register int n;
+
+ REQUEST (xXcupGetReservedColormapEntriesReq);
+ swaps (&stuff->length, n);
+ swapl (&stuff->screen, n);
+ REQUEST_AT_LEAST_SIZE (xXcupGetReservedColormapEntriesReq);
+ return ProcGetReservedColormapEntries (client);
+}
+
+static
+int SProcStoreColors (client)
+ ClientPtr client;
+{
+ register int n;
+ int count;
+ xColorItem* pItem;
+
+ REQUEST (xXcupStoreColorsReq);
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE (xXcupStoreColorsReq);
+ swapl(&stuff->cmap, n);
+ pItem = (xColorItem*) &stuff[1];
+ for(count = LengthRestB(stuff)/sizeof(xColorItem); --count >= 0; )
+ SwapColorItem(pItem++);
+ return ProcStoreColors (client);
+}
+
+static
+int SProcDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_XcupQueryVersion:
+ return SProcQueryVersion (client);
+ case X_XcupGetReservedColormapEntries:
+ return SProcGetReservedColormapEntries (client);
+ case X_XcupStoreColors:
+ return SProcStoreColors (client);
+ default:
+ return BadRequest;
+ }
+}
+
+
diff --git a/Xext/dpms.c b/Xext/dpms.c
new file mode 100644
index 000000000..ebc992dc2
--- /dev/null
+++ b/Xext/dpms.c
@@ -0,0 +1,433 @@
+/* $Xorg: dpms.c,v 1.3 2000/08/17 19:47:56 cpqbld Exp $ */
+/*****************************************************************
+
+Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "dpms.h"
+#include "dpmsstr.h"
+#include <stdio.h>
+
+static unsigned char DPMSCode;
+static int ProcDPMSDispatch(), SProcDPMSDispatch();
+static void DPMSResetProc();
+static int ProcDPMSGetVersion(), SProcDPMSGetVersion();
+static int ProcDPMSGetTimeouts(), SProcDPMSGetTimeouts();
+static int ProcDPMSSetTimeouts(), ProcDPMSSetTimeouts();
+static int ProcDPMSEnable(), ProcDPMSEnable();
+static int ProcDPMSDisable(), ProcDPMSDisable();
+static int ProcDPMSForceLevel(), ProcDPMSForceLevel();
+
+extern void Swap32Write(); /* XXX should be in header file */
+extern CARD32 ScreenSaverTime;
+extern CARD32 DPMSStandbyTime;
+extern CARD32 DPMSSuspendTime;
+extern CARD32 DPMSOffTime;
+extern BOOL DPMSCapableFlag;
+extern BOOL DPMSEnabled;
+extern CARD16 DPMSPowerLevel;
+
+void
+DPMSExtensionInit()
+{
+ ExtensionEntry *extEntry, *AddExtension();
+
+ if (extEntry = AddExtension(DPMSExtensionName, 0, 0,
+ ProcDPMSDispatch, SProcDPMSDispatch,
+ DPMSResetProc, StandardMinorOpcode))
+ DPMSCode = (unsigned char)extEntry->base;
+ return;
+}
+
+/*ARGSUSED*/
+static void
+DPMSResetProc (extEntry)
+ ExtensionEntry *extEntry;
+{
+}
+
+static int
+ProcDPMSGetVersion(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSGetVersionReq);
+ xDPMSGetVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xDPMSGetVersionReq);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = DPMSMajorVersion;
+ rep.minorVersion = DPMSMinorVersion;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof(xDPMSGetVersionReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcDPMSCapable(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSCapableReq);
+ xDPMSCapableReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xDPMSCapableReq);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.capable = DPMSCapableFlag;
+
+ WriteToClient(client, sizeof(xDPMSCapableReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcDPMSGetTimeouts(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSGetTimeoutsReq);
+ xDPMSGetTimeoutsReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.standby = DPMSStandbyTime / MILLI_PER_SECOND;
+ rep.suspend = DPMSSuspendTime / MILLI_PER_SECOND;
+ rep.off = DPMSOffTime / MILLI_PER_SECOND;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.standby, n);
+ swaps(&rep.suspend, n);
+ swaps(&rep.off, n);
+ }
+ WriteToClient(client, sizeof(xDPMSGetTimeoutsReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcDPMSSetTimeouts(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSSetTimeoutsReq);
+ register int n;
+
+ REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq);
+
+ if ((stuff->off != 0)&&(stuff->off < stuff->suspend))
+ {
+ client->errorValue = stuff->off;
+ return BadValue;
+ }
+ if ((stuff->suspend != 0)&&(stuff->suspend < stuff->standby))
+ {
+ client->errorValue = stuff->suspend;
+ return BadValue;
+ }
+
+ DPMSStandbyTime = stuff->standby * MILLI_PER_SECOND;
+ DPMSSuspendTime = stuff->suspend * MILLI_PER_SECOND;
+ DPMSOffTime = stuff->off * MILLI_PER_SECOND;
+
+ return(client->noClientException);
+}
+
+static int
+ProcDPMSEnable(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSEnableReq);
+
+ REQUEST_SIZE_MATCH(xDPMSEnableReq);
+
+ if (DPMSCapableFlag)
+ DPMSEnabled = TRUE;
+
+ return(client->noClientException);
+}
+
+static int
+ProcDPMSDisable(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSDisableReq);
+
+ REQUEST_SIZE_MATCH(xDPMSDisableReq);
+
+#ifdef DPMSExtension
+ DPMSSet(DPMSModeOn);
+#endif
+
+ DPMSEnabled = FALSE;
+
+ return(client->noClientException);
+}
+
+static int
+ProcDPMSForceLevel(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSForceLevelReq);
+
+ REQUEST_SIZE_MATCH(xDPMSForceLevelReq);
+
+ if (!DPMSEnabled)
+ return BadMatch;
+
+ if (stuff->level == DPMSModeOn) {
+ lastDeviceEventTime.milliseconds =
+ GetTimeInMillis();
+ }
+#if 0
+ else if (stuff->level == DPMSModeStandby) {
+ lastDeviceEventTime.milliseconds =
+ GetTimeInMillis() - DPMSStandbyTime;
+ } else if (stuff->level == DPMSModeSuspend) {
+ lastDeviceEventTime.milliseconds =
+ GetTimeInMillis() - DPMSSuspendTime;
+ } else if (stuff->level == DPMSModeOff) {
+ lastDeviceEventTime.milliseconds =
+ GetTimeInMillis() - DPMSOffTime;
+ } else {
+ client->errorValue = stuff->level;
+ return BadValue;
+ }
+#endif
+
+#ifdef DPMSExtension
+ DPMSSet(stuff->level);
+#endif
+
+ return(client->noClientException);
+}
+
+static int
+ProcDPMSInfo(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSInfoReq);
+ xDPMSInfoReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xDPMSInfoReq);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.power_level = DPMSPowerLevel;
+ rep.state = DPMSEnabled;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.power_level, n);
+ }
+ WriteToClient(client, sizeof(xDPMSInfoReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcDPMSDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_DPMSGetVersion:
+ return ProcDPMSGetVersion(client);
+ case X_DPMSCapable:
+ return ProcDPMSCapable(client);
+ case X_DPMSGetTimeouts:
+ return ProcDPMSGetTimeouts(client);
+ case X_DPMSSetTimeouts:
+ return ProcDPMSSetTimeouts(client);
+ case X_DPMSEnable:
+ return ProcDPMSEnable(client);
+ case X_DPMSDisable:
+ return ProcDPMSDisable(client);
+ case X_DPMSForceLevel:
+ return ProcDPMSForceLevel(client);
+ case X_DPMSInfo:
+ return ProcDPMSInfo(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcDPMSGetVersion(client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xDPMSGetVersionReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSGetVersionReq);
+ swaps(&stuff->majorVersion, n);
+ swaps(&stuff->minorVersion, n);
+ return ProcDPMSGetVersion(client);
+}
+
+static int
+SProcDPMSCapable(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSCapableReq);
+ register int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSCapableReq);
+
+ return ProcDPMSCapable(client);
+}
+
+static int
+SProcDPMSGetTimeouts(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSGetTimeoutsReq);
+ register int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq);
+
+ return ProcDPMSGetTimeouts(client);
+}
+
+static int
+SProcDPMSSetTimeouts(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSSetTimeoutsReq);
+ register int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq);
+
+ swaps(&stuff->standby, n);
+ swaps(&stuff->suspend, n);
+ swaps(&stuff->off, n);
+ return ProcDPMSSetTimeouts(client);
+}
+
+static int
+SProcDPMSEnable(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSEnableReq);
+ register int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSEnableReq);
+
+ return ProcDPMSEnable(client);
+}
+
+static int
+SProcDPMSDisable(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSDisableReq);
+ register int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSDisableReq);
+
+ return ProcDPMSDisable(client);
+}
+
+static int
+SProcDPMSForceLevel(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSForceLevelReq);
+ register int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSForceLevelReq);
+
+ swaps(&stuff->level, n);
+
+ return ProcDPMSForceLevel(client);
+}
+
+static int
+SProcDPMSInfo(client)
+ register ClientPtr client;
+{
+ REQUEST(xDPMSInfoReq);
+ register int n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xDPMSInfoReq);
+
+ return ProcDPMSInfo(client);
+}
+
+static int
+SProcDPMSDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_DPMSGetVersion:
+ return SProcDPMSGetVersion(client);
+ case X_DPMSCapable:
+ return SProcDPMSCapable(client);
+ case X_DPMSGetTimeouts:
+ return SProcDPMSGetTimeouts(client);
+ case X_DPMSSetTimeouts:
+ return SProcDPMSSetTimeouts(client);
+ case X_DPMSEnable:
+ return SProcDPMSEnable(client);
+ case X_DPMSDisable:
+ return SProcDPMSDisable(client);
+ case X_DPMSForceLevel:
+ return SProcDPMSForceLevel(client);
+ case X_DPMSInfo:
+ return SProcDPMSInfo(client);
+ default:
+ return BadRequest;
+ }
+}
diff --git a/Xext/dpmsstubs.c b/Xext/dpmsstubs.c
new file mode 100644
index 000000000..6f635f42b
--- /dev/null
+++ b/Xext/dpmsstubs.c
@@ -0,0 +1,48 @@
+/* $Xorg: dpmsstubs.c,v 1.3 2000/08/17 19:47:56 cpqbld Exp $ */
+/*****************************************************************
+
+Copyright (c) 1996 Digital Equipment Corporation, Maynard, Massachusetts.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+
+typedef int Bool;
+
+#define FALSE 0
+
+Bool DPMSSupported()
+{
+ return FALSE;
+}
+
+int DPSMGet(level)
+ int *level;
+{
+ return -1;
+}
+
+void DPMSSet(level)
+{
+
+}
diff --git a/Xext/mbuf.c b/Xext/mbuf.c
new file mode 100644
index 000000000..c65ed3dd2
--- /dev/null
+++ b/Xext/mbuf.c
@@ -0,0 +1,2041 @@
+/************************************************************
+
+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.
+
+********************************************************/
+
+/* $Xorg: mbuf.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <stdio.h>
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "opaque.h"
+#define _MULTIBUF_SERVER_ /* don't want Xlib structures */
+#include "multibufst.h"
+#include "regionstr.h"
+#include "gcstruct.h"
+#include "inputstr.h"
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#endif
+
+/* given an OtherClientPtr obj, get the ClientPtr */
+#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
+
+/* given a MultibufferPtr b, get the ClientPtr */
+#define bClient(b) (clients[CLIENT_ID(b->pPixmap->drawable.id)])
+
+#define ValidEventMasks (ExposureMask|MultibufferClobberNotifyMask|MultibufferUpdateNotifyMask)
+
+#ifdef PANORAMIX
+extern int PanoramiXNumScreens;
+extern Bool noPanoramiXExtension;
+extern PanoramiXWindow *PanoramiXWinRoot;
+extern PanoramiXPmap *PanoramiXPmapRoot;
+extern PanoramiXData *panoramiXdataPtr;
+#endif
+
+/* The _Multibuffer and _Multibuffers structures below refer to each other,
+ * so we need this forward declaration
+ */
+
+typedef struct _Multibuffers *MultibuffersPtr;
+
+/*
+ * per-Multibuffer data
+ */
+
+typedef struct _Multibuffer {
+ MultibuffersPtr pMultibuffers; /* associated window data */
+ Mask eventMask; /* MultibufferClobberNotifyMask|ExposureMask|MultibufferUpdateNotifyMask */
+ Mask otherEventMask; /* mask of all other clients event masks */
+ OtherClients *otherClients; /* other clients that want events */
+ int number; /* index of this buffer into array */
+ int side; /* always Mono */
+ int clobber; /* Unclobbered, PartiallyClobbered, FullClobbered */
+ PixmapPtr pPixmap; /* associated pixmap */
+} MultibufferRec, *MultibufferPtr;
+
+/*
+ * per-window data
+ */
+
+typedef struct _Multibuffers {
+ WindowPtr pWindow; /* associated window */
+ int numMultibuffer; /* count of buffers */
+ int refcnt; /* ref count for delete */
+ int displayedMultibuffer; /* currently active buffer */
+ int updateAction; /* Undefined, Background, Untouched, Copied */
+ int updateHint; /* Frequent, Intermittent, Static */
+ int windowMode; /* always Mono */
+
+ TimeStamp lastUpdate; /* time of last update */
+
+ unsigned short width, height; /* last known window size */
+ short x, y; /* for static gravity */
+
+ MultibufferPtr buffers; /* array of numMultibuffer buffers */
+} MultibuffersRec;
+
+/*
+ * per-screen data
+ */
+typedef struct _MultibufferScreen {
+ Bool (*PositionWindow)();
+} MultibufferScreenRec, *MultibufferScreenPtr;
+
+/*
+ * per display-image-buffers request data.
+ */
+
+typedef struct _DisplayRequest {
+ struct _DisplayRequest *next;
+ TimeStamp activateTime;
+ ClientPtr pClient;
+ XID id;
+} DisplayRequestRec, *DisplayRequestPtr;
+
+static unsigned char MultibufferReqCode;
+static int MultibufferEventBase;
+static int MultibufferErrorBase;
+int MultibufferScreenIndex = -1;
+int MultibufferWindowIndex = -1;
+
+static void PerformDisplayRequest ();
+static void DisposeDisplayRequest ();
+static Bool QueueDisplayRequest ();
+
+static void BumpTimeStamp ();
+
+void MultibufferExpose ();
+void MultibufferUpdate ();
+static void AliasMultibuffer ();
+int CreateImageBuffers ();
+void DestroyImageBuffers ();
+int DisplayImageBuffers ();
+static void RecalculateMultibufferOtherEvents ();
+static int EventSelectForMultibuffer();
+
+
+/*
+ * The Pixmap associated with a buffer can be found as a resource
+ * with this type
+ */
+RESTYPE MultibufferDrawableResType;
+static int MultibufferDrawableDelete ();
+/*
+ * The per-buffer data can be found as a resource with this type.
+ * the resource id of the per-buffer data is the same as the resource
+ * id of the pixmap
+ */
+static RESTYPE MultibufferResType;
+static int MultibufferDelete ();
+/*
+ * The per-window data can be found as a resource with this type,
+ * using the window resource id
+ */
+static RESTYPE MultibuffersResType;
+static int MultibuffersDelete ();
+/*
+ * Clients other than the buffer creator attach event masks in
+ * OtherClient structures; each has a resource of this type.
+ */
+static RESTYPE OtherClientResType;
+static int OtherClientDelete ();
+
+/****************
+ * MultibufferExtensionInit
+ *
+ * Called from InitExtensions in main()
+ *
+ ****************/
+
+static int ProcMultibufferDispatch(), SProcMultibufferDispatch();
+static void MultibufferResetProc();
+static void SClobberNotifyEvent(), SUpdateNotifyEvent();
+static Bool MultibufferPositionWindow();
+
+void
+MultibufferExtensionInit()
+{
+ ExtensionEntry *extEntry;
+ int i, j;
+ ScreenPtr pScreen;
+ MultibufferScreenPtr pMultibufferScreen;
+
+ /*
+ * allocate private pointers in windows and screens. Allocating
+ * window privates may seem like an unnecessary expense, but every
+ * PositionWindow call must check to see if the window is
+ * multi-buffered; a resource lookup is too expensive.
+ */
+ MultibufferScreenIndex = AllocateScreenPrivateIndex ();
+ if (MultibufferScreenIndex < 0)
+ return;
+ MultibufferWindowIndex = AllocateWindowPrivateIndex ();
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+ if (!AllocateWindowPrivate (pScreen, MultibufferWindowIndex, 0) ||
+ !(pMultibufferScreen = (MultibufferScreenPtr) xalloc (sizeof (MultibufferScreenRec))))
+ {
+ for (j = 0; j < i; j++)
+ xfree (screenInfo.screens[j]->devPrivates[MultibufferScreenIndex].ptr);
+ return;
+ }
+ pScreen->devPrivates[MultibufferScreenIndex].ptr = (pointer) pMultibufferScreen;
+ /*
+ * wrap PositionWindow to resize the pixmap when the window
+ * changes size
+ */
+ pMultibufferScreen->PositionWindow = pScreen->PositionWindow;
+ pScreen->PositionWindow = MultibufferPositionWindow;
+ }
+ /*
+ * create the resource types
+ */
+ MultibufferDrawableResType =
+ CreateNewResourceType(MultibufferDrawableDelete)|RC_CACHED|RC_DRAWABLE;
+ MultibufferResType = CreateNewResourceType(MultibufferDelete);
+ MultibuffersResType = CreateNewResourceType(MultibuffersDelete);
+ OtherClientResType = CreateNewResourceType(OtherClientDelete);
+ if (MultibufferDrawableResType && MultibufferResType &&
+ MultibuffersResType && OtherClientResType &&
+ (extEntry = AddExtension(MULTIBUFFER_PROTOCOL_NAME,
+ MultibufferNumberEvents,
+ MultibufferNumberErrors,
+ ProcMultibufferDispatch, SProcMultibufferDispatch,
+ MultibufferResetProc, StandardMinorOpcode)))
+ {
+ MultibufferReqCode = (unsigned char)extEntry->base;
+ MultibufferEventBase = extEntry->eventBase;
+ MultibufferErrorBase = extEntry->errorBase;
+ EventSwapVector[MultibufferEventBase + MultibufferClobberNotify] = SClobberNotifyEvent;
+ EventSwapVector[MultibufferEventBase + MultibufferUpdateNotify] = SUpdateNotifyEvent;
+ }
+}
+
+/*ARGSUSED*/
+static void
+MultibufferResetProc (extEntry)
+ExtensionEntry *extEntry;
+{
+ int i;
+ ScreenPtr pScreen;
+ MultibufferScreenPtr pMultibufferScreen;
+
+ if (MultibufferScreenIndex < 0)
+ return;
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ pScreen = screenInfo.screens[i];
+ if (pScreen->devPrivates[MultibufferScreenIndex].ptr)
+ {
+ pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr;
+ pScreen->PositionWindow = pMultibufferScreen->PositionWindow;
+ xfree (pMultibufferScreen);
+ }
+ }
+}
+
+static int
+ProcGetBufferVersion (client)
+ register ClientPtr client;
+{
+ REQUEST(xMbufGetBufferVersionReq);
+ xMbufGetBufferVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xMbufGetBufferVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = MULTIBUFFER_MAJOR_VERSION;
+ rep.minorVersion = MULTIBUFFER_MINOR_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient(client, sizeof (xMbufGetBufferVersionReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static void
+SetupBackgroundPainter (pWin, pGC)
+ WindowPtr pWin;
+ GCPtr pGC;
+{
+ pointer gcvalues[4];
+ int ts_x_origin, ts_y_origin;
+ PixUnion background;
+ int backgroundState;
+ Mask gcmask;
+
+ /*
+ * First take care of any ParentRelative stuff by altering the
+ * tile/stipple origin to match the coordinates of the upper-left
+ * corner of the first ancestor without a ParentRelative background.
+ * This coordinate is, of course, negative.
+ */
+
+ ts_x_origin = ts_y_origin = 0;
+ while (pWin->backgroundState == ParentRelative) {
+ ts_x_origin -= pWin->origin.x;
+ ts_y_origin -= pWin->origin.y;
+ pWin = pWin->parent;
+ }
+ backgroundState = pWin->backgroundState;
+ background = pWin->background;
+
+ switch (backgroundState)
+ {
+ case BackgroundPixel:
+ gcvalues[0] = (pointer) background.pixel;
+ gcvalues[1] = (pointer) FillSolid;
+ gcmask = GCForeground|GCFillStyle;
+ break;
+
+ case BackgroundPixmap:
+ gcvalues[0] = (pointer) FillTiled;
+ gcvalues[1] = (pointer) background.pixmap;
+ gcvalues[2] = (pointer) ts_x_origin;
+ gcvalues[3] = (pointer) ts_y_origin;
+ gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin;
+ break;
+
+ default:
+ gcvalues[0] = (pointer) GXnoop;
+ gcmask = GCFunction;
+ }
+ DoChangeGC(pGC, gcmask, (XID *)gcvalues, TRUE);
+}
+
+int
+CreateImageBuffers (pWin, nbuf, ids, action, hint)
+ WindowPtr pWin;
+ int nbuf;
+ XID *ids;
+ int action;
+ int hint;
+{
+ MultibuffersPtr pMultibuffers;
+ MultibufferPtr pMultibuffer;
+ ScreenPtr pScreen;
+ int width, height, depth;
+ int i;
+ GCPtr pClearGC = NULL;
+ xRectangle clearRect;
+
+ DestroyImageBuffers(pWin);
+ pMultibuffers = (MultibuffersPtr) xalloc (sizeof (MultibuffersRec) +
+ nbuf * sizeof (MultibufferRec));
+ if (!pMultibuffers)
+ return BadAlloc;
+ pMultibuffers->pWindow = pWin;
+ pMultibuffers->buffers = (MultibufferPtr) (pMultibuffers + 1);
+ pMultibuffers->refcnt = pMultibuffers->numMultibuffer = 0;
+ if (!AddResource (pWin->drawable.id, MultibuffersResType, (pointer) pMultibuffers))
+ return BadAlloc;
+ width = pWin->drawable.width;
+ height = pWin->drawable.height;
+ depth = pWin->drawable.depth;
+ pScreen = pWin->drawable.pScreen;
+
+ if (pWin->backgroundState != None)
+ {
+ pClearGC = GetScratchGC (pWin->drawable.depth, pScreen);
+ SetupBackgroundPainter (pWin, pClearGC);
+ clearRect.x = clearRect.y = 0;
+ clearRect.width = width;
+ clearRect.height = height;
+ }
+
+ for (i = 0; i < nbuf; i++)
+ {
+ pMultibuffer = &pMultibuffers->buffers[i];
+ pMultibuffer->eventMask = 0L;
+ pMultibuffer->otherEventMask = 0L;
+ pMultibuffer->otherClients = (OtherClientsPtr) NULL;
+ pMultibuffer->number = i;
+ pMultibuffer->side = MultibufferSideMono;
+ pMultibuffer->clobber = MultibufferUnclobbered;
+ pMultibuffer->pMultibuffers = pMultibuffers;
+ if (!AddResource (ids[i], MultibufferResType, (pointer) pMultibuffer))
+ break;
+ pMultibuffer->pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, depth);
+ if (!pMultibuffer->pPixmap)
+ break;
+ if (!AddResource (ids[i], MultibufferDrawableResType, (pointer) pMultibuffer->pPixmap))
+ {
+ FreeResource (ids[i], MultibufferResType);
+ (*pScreen->DestroyPixmap) (pMultibuffer->pPixmap);
+ break;
+ }
+ pMultibuffer->pPixmap->drawable.id = ids[i];
+
+ if (i > 0 && pClearGC)
+ {
+ ValidateGC((DrawablePtr)pMultibuffer->pPixmap, pClearGC);
+ (*pClearGC->ops->PolyFillRect)((DrawablePtr)pMultibuffer->pPixmap,
+ pClearGC, 1, &clearRect);
+ }
+ }
+ pMultibuffers->numMultibuffer = i;
+ pMultibuffers->refcnt = i;
+ pMultibuffers->displayedMultibuffer = -1;
+ if (i > 0)
+ AliasMultibuffer (pMultibuffers, 0);
+ pMultibuffers->updateAction = action;
+ pMultibuffers->updateHint = hint;
+ pMultibuffers->windowMode = MultibufferModeMono;
+ pMultibuffers->lastUpdate.months = 0;
+ pMultibuffers->lastUpdate.milliseconds = 0;
+ pMultibuffers->width = width;
+ pMultibuffers->height = height;
+ pWin->devPrivates[MultibufferWindowIndex].ptr = (pointer) pMultibuffers;
+ if (pClearGC) FreeScratchGC(pClearGC);
+ return Success;
+}
+
+#ifdef PANORAMIX
+static int
+ProcPanoramiXCreateImageBuffers (client)
+ register ClientPtr client;
+{
+ REQUEST(xMbufCreateImageBuffersReq);
+
+ register int result;
+ int i, j, k, len;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ PanoramiXWindow *next;
+ PanoramiXWindow *pPanoramiXids;
+ PanoramiXWindow *pPanoramiXPrev_ids;
+ PanoramiXPmap *local;
+ PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot;
+ CARD32 *value, *orig_ids;
+ XID *ids;
+ XID ID;
+ DrawablePtr pDrawable;
+
+ REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
+ PANORAMIXFIND_ID(pPanoramiXWin,stuff->window);
+ IF_RETURN(!pPanoramiXWin, BadRequest);
+ len = stuff->length - (sizeof(xMbufCreateImageBuffersReq) >> 2);
+ ids = (XID *)ALLOCATE_LOCAL(sizeof(XID)*len);
+ orig_ids = (XID *)ALLOCATE_LOCAL(sizeof(XID)*len);
+ if (!ids)
+ return BadAlloc;
+ memcpy((char *)orig_ids, (char *) &stuff[1], len * sizeof(XID));
+ value = (CARD32 *)&stuff[1];
+ /* New resources are pixmaps */
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) {
+ stuff->window = pPanoramiXWin->info[j].id;
+ for (i = 0; i < len; i++) {
+ ids[i] = (XID)orig_ids[i];
+ /* These will be MultibufferDrawableResType & MultibufferResType */
+ pPanoramiXPmap = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXPmap, ids[i]);
+ if (!pPanoramiXPmap) {
+ local = (PanoramiXWindow *)Xcalloc(sizeof(PanoramiXWindow));
+ for (k = 0; k <= PanoramiXNumScreens - 1; k++) {
+ ID = k ? FakeClientID(client->index) : ids[i];
+ local->info[k].id = ID;
+ }
+ local->FreeMe = FALSE;
+ PANORAMIXFIND_LAST(pPanoramiXPmap, PanoramiXPmapRoot);
+ pPanoramiXPmap->next = local;
+ value[i] = local->info[j].id;
+ }else
+ value[i] = pPanoramiXPmap->info[j].id;
+ }
+ if (!j)
+ noPanoramiXExtension = TRUE;
+ result = ProcCreateImageBuffers (client);
+ noPanoramiXExtension = FALSE;
+ BREAK_IF(result != Success);
+ }
+ if (result != Success) {
+ if (ids)
+ Xfree(ids);
+ if (orig_ids)
+ Xfree(orig_ids);
+ if (local)
+ Xfree(local);
+ }
+ return (result);
+}
+#endif
+
+#ifdef PANORAMIX
+int
+#else
+static int
+#endif
+ProcCreateImageBuffers (client)
+ register ClientPtr client;
+{
+ REQUEST(xMbufCreateImageBuffersReq);
+ xMbufCreateImageBuffersReply rep;
+ register int n;
+ WindowPtr pWin;
+ XID *ids;
+ int len, nbuf;
+ int i;
+ int err;
+
+ REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
+ len = stuff->length - (sizeof(xMbufCreateImageBuffersReq) >> 2);
+ if (len == 0)
+ return BadLength;
+ if (!(pWin = LookupWindow (stuff->window, client)))
+ return BadWindow;
+ if (pWin->drawable.class == InputOnly)
+ return BadMatch;
+ switch (stuff->updateAction)
+ {
+ case MultibufferUpdateActionUndefined:
+ case MultibufferUpdateActionBackground:
+ case MultibufferUpdateActionUntouched:
+ case MultibufferUpdateActionCopied:
+ break;
+ default:
+ client->errorValue = stuff->updateAction;
+ return BadValue;
+ }
+ switch (stuff->updateHint)
+ {
+ case MultibufferUpdateHintFrequent:
+ case MultibufferUpdateHintIntermittent:
+ case MultibufferUpdateHintStatic:
+ break;
+ default:
+ client->errorValue = stuff->updateHint;
+ return BadValue;
+ }
+ nbuf = len;
+ ids = (XID *) &stuff[1];
+ for (i = 0; i < nbuf; i++)
+ {
+ LEGAL_NEW_RESOURCE(ids[i], client);
+ }
+ err = CreateImageBuffers (pWin, nbuf, ids,
+ stuff->updateAction, stuff->updateHint);
+ if (err != Success)
+ return err;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.numberBuffer = ((MultibuffersPtr) (pWin->devPrivates[MultibufferWindowIndex].ptr))->numMultibuffer;
+ if (client->swapped)
+ {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.numberBuffer, n);
+ }
+#ifdef PANORAMIX
+ if (noPanoramiXExtension)
+#endif
+ WriteToClient(client, sizeof (xMbufCreateImageBuffersReply), (char*)&rep);
+ return (client->noClientException);
+}
+
+static int
+ProcDisplayImageBuffers (client)
+ register ClientPtr client;
+{
+ REQUEST(xMbufDisplayImageBuffersReq);
+ MultibufferPtr *pMultibuffer;
+ MultibuffersPtr *ppMultibuffers;
+ int nbuf;
+ XID *ids;
+ int i, j;
+ CARD32 minDelay;
+ TimeStamp activateTime, bufferTime;
+
+#ifdef PANORAMIX
+ WindowPtr pWndw;
+ PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot;
+ MultibufferPtr *pScrn0Multibuffer;
+ MultibuffersPtr *ppScrn0Multibuffers;
+ int k;
+ int panoramiX_buf = 0;
+ Bool FoundScreen;
+
+#endif
+
+ REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq);
+ nbuf = stuff->length - (sizeof (xMbufDisplayImageBuffersReq) >> 2);
+ if (!nbuf)
+ return Success;
+ minDelay = stuff->minDelay;
+ ids = (XID *) &stuff[1];
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ {
+ int maxbuf = 0;
+ maxbuf = nbuf * PanoramiXNumScreens;
+ ppScrn0Multibuffers = (MultibuffersPtr *) xalloc(maxbuf * sizeof (MultibuffersPtr));
+ pScrn0Multibuffer = (MultibufferPtr *) xalloc (maxbuf * sizeof(MultibufferPtr));
+ if (!ppScrn0Multibuffers || !pScrn0Multibuffer)
+ {
+ if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids);
+ xfree (ppScrn0Multibuffers);
+ xfree (pScrn0Multibuffer);
+ client->errorValue = 0;
+ return BadAlloc;
+ }
+ }
+#endif
+ ppMultibuffers = (MultibuffersPtr *) ALLOCATE_LOCAL(nbuf * sizeof (MultibuffersPtr));
+ pMultibuffer = (MultibufferPtr *) ALLOCATE_LOCAL(nbuf * sizeof (MultibufferPtr));
+ if (!ppMultibuffers || !pMultibuffer)
+ {
+ if (ppMultibuffers) DEALLOCATE_LOCAL(ppMultibuffers);
+ if (pMultibuffer) DEALLOCATE_LOCAL(pMultibuffer);
+ client->errorValue = 0;
+ return BadAlloc;
+ }
+ activateTime.months = 0;
+ activateTime.milliseconds = 0;
+ for (i = 0; i < nbuf; i++)
+ {
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension) {
+ pPanoramiXPmap = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXPmap, ids[i]);
+ if (!pPanoramiXPmap){
+ if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids);
+ xfree (ppMultibuffers);
+ xfree (pMultibuffer);
+ client->errorValue = ids[i];
+ return MultibufferErrorBase + MultibufferBadBuffer;
+ }
+ FoundScreen = FALSE;
+ pScrn0Multibuffer[panoramiX_buf] = (MultibufferPtr)
+ LookupIDByType (ids[i], MultibufferResType);
+ ppScrn0Multibuffers[i] = pScrn0Multibuffer[i]->pMultibuffers;
+ pWndw = ppScrn0Multibuffers[i]->pWindow;
+ for (k = 0; (k < PanoramiXNumScreens && !FoundScreen); k++) {
+ pMultibuffer[panoramiX_buf] = (MultibufferPtr)
+ LookupIDByType (pPanoramiXPmap->info[k].id, MultibufferResType);
+ if (!pMultibuffer[i])
+ {
+ if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids);
+ xfree (ppMultibuffers);
+ xfree (pMultibuffer);
+ client->errorValue = ids[i];
+ return MultibufferErrorBase + MultibufferBadBuffer;
+ }
+ ppMultibuffers[panoramiX_buf] = pMultibuffer[panoramiX_buf]->pMultibuffers;
+ /* Figure out where the buffer resides, which screens */
+ if ( ((pWndw->drawable.x < 0) &&
+ (pWndw->drawable.x + pWndw->drawable.width < 0))
+ || ( (pWndw->drawable.x >
+ panoramiXdataPtr[k].x + panoramiXdataPtr[k].width) &&
+ (pWndw->drawable.x + pWndw->drawable.width >
+ panoramiXdataPtr[k].x + panoramiXdataPtr[k].width)))
+ /* its not on screen - k -, try next screen */
+ continue;
+ if ( ((pWndw->drawable.y < 0) &&
+ (pWndw->drawable.y + pWndw->drawable.height < 0))
+ || ( (pWndw->drawable.y >
+ panoramiXdataPtr[k].y + panoramiXdataPtr[k].height) &&
+ (pWndw->drawable.y + pWndw->drawable.height >
+ panoramiXdataPtr[k].y + panoramiXdataPtr[k].height)))
+ /* its not on screen - k -, try next screen */
+ continue;
+
+ /* The window resides on screen k, which means we need to
+ keep the buffer information for this screen */
+ panoramiX_buf++;
+
+ /* Is it only on this screen, or does it enter onto another
+ screen */
+ if ( ((pWndw->drawable.x + pWndw->drawable.width) <=
+ (panoramiXdataPtr[k].x + panoramiXdataPtr[k].width)) &&
+ ((pWndw->drawable.y + pWndw->drawable.height) <=
+ (panoramiXdataPtr[k].y +
+ panoramiXdataPtr[k].height )) )
+ FoundScreen = TRUE;
+ } /* for each screen k */
+ for (j = 0; j < i; j++)
+ {
+ if (ppScrn0Multibuffers[i] == ppScrn0Multibuffers[j])
+ {
+ if ( sizeof (long) != sizeof(CARD32) ) DEALLOCATE_LOCAL(ids);
+ DEALLOCATE_LOCAL(ppScrn0Multibuffers);
+ DEALLOCATE_LOCAL(pScrn0Multibuffer);
+ DEALLOCATE_LOCAL(ppMultibuffers);
+ DEALLOCATE_LOCAL(pMultibuffer);
+ client->errorValue = ids[i];
+ return BadMatch;
+ }
+ }
+ bufferTime = ppScrn0Multibuffers[i]->lastUpdate;
+ }else {
+#endif
+ pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i],
+MultibufferResType);
+ if (!pMultibuffer[i])
+ {
+ DEALLOCATE_LOCAL(ppMultibuffers);
+ DEALLOCATE_LOCAL(pMultibuffer);
+ client->errorValue = ids[i];
+ return MultibufferErrorBase + MultibufferBadBuffer;
+ }
+ ppMultibuffers[i] = pMultibuffer[i]->pMultibuffers;
+ for (j = 0; j < i; j++)
+ {
+ if (ppMultibuffers[i] == ppMultibuffers[j])
+ {
+ DEALLOCATE_LOCAL(ppMultibuffers);
+ DEALLOCATE_LOCAL(pMultibuffer);
+ client->errorValue = ids[i];
+ return BadMatch;
+ }
+ }
+ bufferTime = ppMultibuffers[i]->lastUpdate;
+#ifdef PANORAMIX
+ }
+#endif
+ BumpTimeStamp (&bufferTime, minDelay);
+ if (CompareTimeStamps (bufferTime, activateTime) == LATER)
+ activateTime = bufferTime;
+ }
+ UpdateCurrentTime ();
+ if (CompareTimeStamps (activateTime, currentTime) == LATER &&
+ QueueDisplayRequest (client, activateTime))
+ {
+ ;
+ }
+ else
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension){
+ PerformDisplayRequest (ppMultibuffers, pMultibuffer, panoramiX_buf);
+ }else
+#endif
+ PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf);
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension){
+ DEALLOCATE_LOCAL(ppScrn0Multibuffers);
+ DEALLOCATE_LOCAL(pScrn0Multibuffer);
+ }
+#endif
+
+ DEALLOCATE_LOCAL(ppMultibuffers);
+ DEALLOCATE_LOCAL(pMultibuffer);
+ return Success;
+}
+
+#ifdef PANORAMIX
+static int
+ProcPanoramiXDestroyImageBuffers (client)
+ ClientPtr client;
+{
+ REQUEST (xMbufDestroyImageBuffersReq);
+ WindowPtr pWin;
+
+ register int result;
+ int j;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+
+ REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
+ PANORAMIXFIND_ID(pPanoramiXWin,stuff->window);
+ IF_RETURN(!pPanoramiXWin, BadRequest);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) {
+ stuff->window = pPanoramiXWin->info[j].id;
+ result = ProcDestroyImageBuffers (client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+#endif
+
+#ifdef PANORAMIX
+int
+#else
+static int
+#endif
+ProcDestroyImageBuffers (client)
+ register ClientPtr client;
+{
+ REQUEST (xMbufDestroyImageBuffersReq);
+ WindowPtr pWin;
+
+ REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
+ if (!(pWin = LookupWindow (stuff->window, client)))
+ return BadWindow;
+ DestroyImageBuffers (pWin);
+ return Success;
+}
+
+#ifdef PANORAMIX
+static int
+ProcPanoramiXSetMBufferAttributes (client)
+ ClientPtr client;
+{
+ REQUEST (xMbufSetMBufferAttributesReq);
+ WindowPtr pWin;
+
+ register int result;
+ int j;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+
+ REQUEST_SIZE_MATCH (xMbufSetMBufferAttributesReq);
+ PANORAMIXFIND_ID(pPanoramiXWin,stuff->window);
+ IF_RETURN(!pPanoramiXWin, BadRequest);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) {
+ stuff->window = pPanoramiXWin->info[j].id;
+ result = ProcSetMBufferAttributes (client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+#endif
+#ifdef PANORAMIX
+int
+#else
+static int
+#endif
+ProcSetMBufferAttributes (client)
+ register ClientPtr client;
+{
+ REQUEST (xMbufSetMBufferAttributesReq);
+ WindowPtr pWin;
+ MultibuffersPtr pMultibuffers;
+ int len;
+ Mask vmask;
+ Mask index;
+ CARD32 updateHint;
+ XID *vlist;
+
+ REQUEST_AT_LEAST_SIZE (xMbufSetMBufferAttributesReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType);
+ if (!pMultibuffers)
+ return BadMatch;
+ len = stuff->length - (sizeof (xMbufSetMBufferAttributesReq) >> 2);
+ vmask = stuff->valueMask;
+ if (len != Ones (vmask))
+ return BadLength;
+ vlist = (XID *) &stuff[1];
+ while (vmask)
+ {
+ index = (Mask) lowbit (vmask);
+ vmask &= ~index;
+ switch (index)
+ {
+ case MultibufferWindowUpdateHint:
+ updateHint = (CARD32) *vlist;
+ switch (updateHint)
+ {
+ case MultibufferUpdateHintFrequent:
+ case MultibufferUpdateHintIntermittent:
+ case MultibufferUpdateHintStatic:
+ pMultibuffers->updateHint = updateHint;
+ break;
+ default:
+ client->errorValue = updateHint;
+ return BadValue;
+ }
+ vlist++;
+ break;
+ default:
+ client->errorValue = stuff->valueMask;
+ return BadValue;
+ }
+ }
+ return Success;
+}
+
+static int
+ProcGetMBufferAttributes (client)
+ ClientPtr client;
+{
+ REQUEST (xMbufGetMBufferAttributesReq);
+ WindowPtr pWin;
+ MultibuffersPtr pMultibuffers;
+ XID *ids;
+ xMbufGetMBufferAttributesReply rep;
+ int i, n;
+
+ REQUEST_SIZE_MATCH (xMbufGetMBufferAttributesReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ pMultibuffers = (MultibuffersPtr)LookupIDByType (pWin->drawable.id, MultibuffersResType);
+ if (!pMultibuffers)
+ return BadAccess;
+ ids = (XID *) ALLOCATE_LOCAL (pMultibuffers->numMultibuffer * sizeof (XID));
+ if (!ids)
+ return BadAlloc;
+ for (i = 0; i < pMultibuffers->numMultibuffer; i++)
+ ids[i] = pMultibuffers->buffers[i].pPixmap->drawable.id;
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = pMultibuffers->numMultibuffer;
+ rep.displayedBuffer = pMultibuffers->displayedMultibuffer;
+ rep.updateAction = pMultibuffers->updateAction;
+ rep.updateHint = pMultibuffers->updateHint;
+ rep.windowMode = pMultibuffers->windowMode;
+ if (client->swapped)
+ {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.displayedBuffer, n);
+ SwapLongs (ids, pMultibuffers->numMultibuffer);
+ }
+ WriteToClient (client, sizeof(xMbufGetMBufferAttributesReply),
+ (char *)&rep);
+ WriteToClient (client, (int)(pMultibuffers->numMultibuffer * sizeof (XID)),
+ (char *)ids);
+ DEALLOCATE_LOCAL((pointer) ids);
+ return client->noClientException;
+}
+
+static int
+ProcSetBufferAttributes (client)
+ register ClientPtr client;
+{
+ REQUEST(xMbufSetBufferAttributesReq);
+ MultibufferPtr pMultibuffer;
+ int len;
+ Mask vmask, index;
+ XID *vlist;
+ Mask eventMask;
+ int result;
+
+ REQUEST_AT_LEAST_SIZE (xMbufSetBufferAttributesReq);
+ pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
+ if (!pMultibuffer)
+ return MultibufferErrorBase + MultibufferBadBuffer;
+ len = stuff->length - (sizeof (xMbufSetBufferAttributesReq) >> 2);
+ vmask = stuff->valueMask;
+ if (len != Ones (vmask))
+ return BadLength;
+ vlist = (XID *) &stuff[1];
+ while (vmask)
+ {
+ index = (Mask) lowbit (vmask);
+ vmask &= ~index;
+ switch (index)
+ {
+ case MultibufferBufferEventMask:
+ eventMask = (Mask) *vlist;
+ vlist++;
+ result = EventSelectForMultibuffer (pMultibuffer, client, eventMask);
+ if (result != Success)
+ return result;
+ break;
+ default:
+ client->errorValue = stuff->valueMask;
+ return BadValue;
+ }
+ }
+ return Success;
+}
+
+ProcGetBufferAttributes (client)
+ register ClientPtr client;
+{
+ REQUEST(xMbufGetBufferAttributesReq);
+ MultibufferPtr pMultibuffer;
+ xMbufGetBufferAttributesReply rep;
+ OtherClientsPtr other;
+ int n;
+
+ REQUEST_SIZE_MATCH (xMbufGetBufferAttributesReq);
+ pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
+ if (!pMultibuffer)
+ return MultibufferErrorBase + MultibufferBadBuffer;
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.window = pMultibuffer->pMultibuffers->pWindow->drawable.id;
+ if (bClient (pMultibuffer) == client)
+ rep.eventMask = pMultibuffer->eventMask;
+ else
+ {
+ rep.eventMask = (Mask) 0L;
+ for (other = pMultibuffer->otherClients; other; other = other->next)
+ if (SameClient (other, client))
+ {
+ rep.eventMask = other->mask;
+ break;
+ }
+ }
+ rep.bufferIndex = pMultibuffer->number;
+ rep.side = pMultibuffer->side;
+ if (client->swapped)
+ {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.window, n);
+ swapl(&rep.eventMask, n);
+ swaps(&rep.bufferIndex, n);
+ }
+ WriteToClient(client, sizeof (xMbufGetBufferAttributesReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int
+ProcGetBufferInfo (client)
+ register ClientPtr client;
+{
+ REQUEST (xMbufGetBufferInfoReq);
+ DrawablePtr pDrawable;
+ xMbufGetBufferInfoReply rep;
+ ScreenPtr pScreen;
+ int i, j, k;
+ int n;
+ xMbufBufferInfo *pInfo;
+ int nInfo;
+ DepthPtr pDepth;
+
+ pDrawable = (DrawablePtr) LookupDrawable (stuff->drawable, client);
+ if (!pDrawable)
+ return BadDrawable;
+ pScreen = pDrawable->pScreen;
+ nInfo = 0;
+ for (i = 0; i < pScreen->numDepths; i++)
+ {
+ pDepth = &pScreen->allowedDepths[i];
+ nInfo += pDepth->numVids;
+ }
+ pInfo = (xMbufBufferInfo *)
+ ALLOCATE_LOCAL (nInfo * sizeof (xMbufBufferInfo));
+ if (!pInfo)
+ return BadAlloc;
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = nInfo * (sizeof (xMbufBufferInfo) >> 2);
+ rep.normalInfo = nInfo;
+ rep.stereoInfo = 0;
+ if (client->swapped)
+ {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.normalInfo, n);
+ swaps(&rep.stereoInfo, n);
+ }
+
+ k = 0;
+ for (i = 0; i < pScreen->numDepths; i++)
+ {
+ pDepth = &pScreen->allowedDepths[i];
+ for (j = 0; j < pDepth->numVids; j++)
+ {
+ pInfo[k].visualID = pDepth->vids[j];
+ pInfo[k].maxBuffers = 0;
+ pInfo[k].depth = pDepth->depth;
+ if (client->swapped)
+ {
+ swapl (&pInfo[k].visualID, n);
+ swaps (&pInfo[k].maxBuffers, n);
+ }
+ k++;
+ }
+ }
+ WriteToClient (client, sizeof (xMbufGetBufferInfoReply), (pointer) &rep);
+ WriteToClient (client, (int) nInfo * sizeof (xMbufBufferInfo), (pointer) pInfo);
+ DEALLOCATE_LOCAL ((pointer) pInfo);
+ return client->noClientException;
+}
+
+static int
+ProcClearImageBufferArea (client)
+ register ClientPtr client;
+{
+ REQUEST (xMbufClearImageBufferAreaReq);
+ MultibufferPtr pMultibuffer;
+ WindowPtr pWin;
+ xRectangle clearRect;
+ int width, height;
+ DrawablePtr pDrawable;
+ ScreenPtr pScreen;
+
+ REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq);
+ pMultibuffer = (MultibufferPtr) LookupIDByType (stuff->buffer, MultibufferResType);
+ if (!pMultibuffer)
+ return MultibufferErrorBase + MultibufferBadBuffer;
+ if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse))
+ {
+ client->errorValue = stuff->exposures;
+ return(BadValue);
+ }
+ pWin = pMultibuffer->pMultibuffers->pWindow;
+ width = pWin->drawable.width;
+ height = pWin->drawable.height;
+ pScreen = pWin->drawable.pScreen;
+
+ clearRect.x = stuff->x;
+ clearRect.y = stuff->y;
+ clearRect.width = stuff->width ? stuff->width : width;
+ clearRect.height = stuff->height ? stuff->height : height;
+
+ if (pWin->backgroundState != None)
+ {
+ GCPtr pClearGC;
+ pClearGC = GetScratchGC (pWin->drawable.depth, pScreen);
+ SetupBackgroundPainter (pWin, pClearGC);
+
+ if (pMultibuffer->number == pMultibuffer->pMultibuffers->displayedMultibuffer)
+ pDrawable = (DrawablePtr)pWin;
+ else
+ pDrawable = (DrawablePtr)pMultibuffer->pPixmap;
+
+ ValidateGC(pDrawable, pClearGC);
+ (*pClearGC->ops->PolyFillRect) (pDrawable, pClearGC, 1, &clearRect);
+ FreeScratchGC(pClearGC);
+ }
+
+ if (stuff->exposures)
+ {
+ RegionRec region;
+ BoxRec box;
+ box.x1 = clearRect.x;
+ box.y1 = clearRect.y;
+ box.x2 = clearRect.x + clearRect.width;
+ box.y2 = clearRect.y + clearRect.height;
+ REGION_INIT(pScreen, &region, &box, 1);
+ MultibufferExpose(pMultibuffer, &region);
+ REGION_UNINIT(pScreen, &region);
+ }
+ return Success;
+}
+
+static int
+ProcMultibufferDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data) {
+ case X_MbufGetBufferVersion:
+ return ProcGetBufferVersion (client);
+ case X_MbufCreateImageBuffers:
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ return ProcPanoramiXCreateImageBuffers (client);
+ else
+ return ProcCreateImageBuffers (client);
+#else
+ return ProcCreateImageBuffers (client);
+#endif
+ case X_MbufDisplayImageBuffers:
+ return ProcDisplayImageBuffers (client);
+ case X_MbufDestroyImageBuffers:
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ return ProcPanoramiXDestroyImageBuffers (client);
+ else
+ return ProcDestroyImageBuffers (client);
+#else
+ return ProcDestroyImageBuffers (client);
+#endif
+ case X_MbufSetMBufferAttributes:
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ return ProcPanoramiXSetMBufferAttributes (client);
+ else
+ return ProcSetMBufferAttributes (client);
+#else
+ return ProcSetMBufferAttributes (client);
+#endif
+ case X_MbufGetMBufferAttributes:
+ return ProcGetMBufferAttributes (client);
+ case X_MbufSetBufferAttributes:
+ return ProcSetBufferAttributes (client);
+ case X_MbufGetBufferAttributes:
+ return ProcGetBufferAttributes (client);
+ case X_MbufGetBufferInfo:
+ return ProcGetBufferInfo (client);
+ case X_MbufClearImageBufferArea:
+ return ProcClearImageBufferArea (client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcGetBufferVersion (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST (xMbufGetBufferVersionReq);
+
+ swaps (&stuff->length, n);
+ return ProcGetBufferVersion (client);
+}
+
+static int
+SProcCreateImageBuffers (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST (xMbufCreateImageBuffersReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE (xMbufCreateImageBuffersReq);
+ swapl (&stuff->window, n);
+ SwapRestL(stuff);
+ return ProcCreateImageBuffers (client);
+}
+
+static int
+SProcDisplayImageBuffers (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST (xMbufDisplayImageBuffersReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE (xMbufDisplayImageBuffersReq);
+ swaps (&stuff->minDelay, n);
+ swaps (&stuff->maxDelay, n);
+ SwapRestL(stuff);
+ return ProcDisplayImageBuffers (client);
+}
+
+static int
+SProcDestroyImageBuffers (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST (xMbufDestroyImageBuffersReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xMbufDestroyImageBuffersReq);
+ swapl (&stuff->window, n);
+ return ProcDestroyImageBuffers (client);
+}
+
+static int
+SProcSetMBufferAttributes (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST (xMbufSetMBufferAttributesReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xMbufSetMBufferAttributesReq);
+ swapl (&stuff->window, n);
+ swapl (&stuff->valueMask, n);
+ SwapRestL(stuff);
+ return ProcSetMBufferAttributes (client);
+}
+
+static int
+SProcGetMBufferAttributes (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST (xMbufGetMBufferAttributesReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xMbufGetMBufferAttributesReq);
+ swapl (&stuff->window, n);
+ return ProcGetMBufferAttributes (client);
+}
+
+static int
+SProcSetBufferAttributes (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST (xMbufSetBufferAttributesReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xMbufSetBufferAttributesReq);
+ swapl (&stuff->buffer, n);
+ swapl (&stuff->valueMask, n);
+ SwapRestL(stuff);
+ return ProcSetBufferAttributes (client);
+}
+
+static int
+SProcGetBufferAttributes (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST (xMbufGetBufferAttributesReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xMbufGetBufferAttributesReq);
+ swapl (&stuff->buffer, n);
+ return ProcGetBufferAttributes (client);
+}
+
+static int
+SProcGetBufferInfo (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST (xMbufGetBufferInfoReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xMbufGetBufferInfoReq);
+ swapl (&stuff->drawable, n);
+ return ProcGetBufferInfo (client);
+}
+
+static int
+SProcClearImageBufferArea(client)
+ register ClientPtr client;
+{
+ register char n;
+ REQUEST(xMbufClearImageBufferAreaReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xMbufClearImageBufferAreaReq);
+ swapl(&stuff->buffer, n);
+ swaps(&stuff->x, n);
+ swaps(&stuff->y, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ return ProcClearImageBufferArea(client);
+}
+
+static int
+SProcMultibufferDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data) {
+ case X_MbufGetBufferVersion:
+ return SProcGetBufferVersion (client);
+ case X_MbufCreateImageBuffers:
+ return SProcCreateImageBuffers (client);
+ case X_MbufDisplayImageBuffers:
+ return SProcDisplayImageBuffers (client);
+ case X_MbufDestroyImageBuffers:
+ return SProcDestroyImageBuffers (client);
+ case X_MbufSetMBufferAttributes:
+ return SProcSetMBufferAttributes (client);
+ case X_MbufGetMBufferAttributes:
+ return SProcGetMBufferAttributes (client);
+ case X_MbufSetBufferAttributes:
+ return SProcSetBufferAttributes (client);
+ case X_MbufGetBufferAttributes:
+ return SProcGetBufferAttributes (client);
+ case X_MbufGetBufferInfo:
+ return SProcGetBufferInfo (client);
+ case X_MbufClearImageBufferArea:
+ return SProcClearImageBufferArea (client);
+ default:
+ return BadRequest;
+ }
+}
+
+static void
+SUpdateNotifyEvent (from, to)
+ xMbufUpdateNotifyEvent *from, *to;
+{
+ to->type = from->type;
+ cpswaps (from->sequenceNumber, to->sequenceNumber);
+ cpswapl (from->buffer, to->buffer);
+ cpswapl (from->timeStamp, to->timeStamp);
+}
+
+static void
+SClobberNotifyEvent (from, to)
+ xMbufClobberNotifyEvent *from, *to;
+{
+ to->type = from->type;
+ cpswaps (from->sequenceNumber, to->sequenceNumber);
+ cpswapl (from->buffer, to->buffer);
+ to->state = from->state;
+}
+
+static void
+PerformDisplayRequest (ppMultibuffers, pMultibuffer, nbuf)
+ MultibufferPtr *pMultibuffer;
+ MultibuffersPtr *ppMultibuffers;
+ int nbuf;
+{
+ GCPtr pGC;
+ PixmapPtr pPrevPixmap, pNewPixmap;
+ xRectangle clearRect;
+ WindowPtr pWin;
+ RegionPtr pExposed;
+ int i;
+ MultibufferPtr pPrevMultibuffer;
+ XID graphicsExpose;
+
+ UpdateCurrentTime ();
+ for (i = 0; i < nbuf; i++)
+ {
+ pWin = ppMultibuffers[i]->pWindow;
+ pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen);
+ pPrevMultibuffer =
+ &ppMultibuffers[i]->buffers[ppMultibuffers[i]->displayedMultibuffer];
+ pPrevPixmap = pPrevMultibuffer->pPixmap;
+ pNewPixmap = pMultibuffer[i]->pPixmap;
+ switch (ppMultibuffers[i]->updateAction)
+ {
+ case MultibufferUpdateActionUndefined:
+ break;
+ case MultibufferUpdateActionBackground:
+ SetupBackgroundPainter (pWin, pGC);
+ ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
+ clearRect.x = 0;
+ clearRect.y = 0;
+ clearRect.width = pPrevPixmap->drawable.width;
+ clearRect.height = pPrevPixmap->drawable.height;
+ (*pGC->ops->PolyFillRect) ((DrawablePtr)pPrevPixmap, pGC,
+ 1, &clearRect);
+ break;
+ case MultibufferUpdateActionUntouched:
+ /* copy the window to the pixmap that represents the
+ * currently displayed buffer
+ */
+ if (pPrevMultibuffer->eventMask & ExposureMask)
+ {
+ graphicsExpose = TRUE;
+ DoChangeGC (pGC, GCGraphicsExposures, &graphicsExpose, FALSE);
+ }
+ ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
+ pExposed = (*pGC->ops->CopyArea)
+ ((DrawablePtr) pWin,
+ (DrawablePtr) pPrevPixmap,
+ pGC,
+ 0, 0,
+ pWin->drawable.width, pWin->drawable.height,
+ 0, 0);
+
+ /* if we couldn't copy the whole window to the buffer,
+ * send expose events (if any client wants them)
+ */
+ if (pPrevMultibuffer->eventMask & ExposureMask)
+ { /* some client wants expose events */
+ if (pExposed)
+ {
+ RegionPtr pWinSize;
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ extern RegionPtr CreateUnclippedWinSize();
+
+ pWinSize = CreateUnclippedWinSize (pWin);
+ /* pExposed is window-relative, but at this point
+ * pWinSize is screen-relative. Make pWinSize be
+ * window-relative so that region ops involving
+ * pExposed and pWinSize behave sensibly.
+ */
+ REGION_TRANSLATE(pScreen, pWinSize,
+ -pWin->drawable.x,
+ -pWin->drawable.y);
+ REGION_INTERSECT(pScreen, pExposed, pExposed, pWinSize);
+ REGION_DESTROY(pScreen, pWinSize);
+ MultibufferExpose (pPrevMultibuffer, pExposed);
+ REGION_DESTROY(pScreen, pExposed);
+ }
+ graphicsExpose = FALSE;
+ DoChangeGC (pGC, GCGraphicsExposures, &graphicsExpose, FALSE);
+ }
+ break; /* end case MultibufferUpdateActionUntouched */
+
+ case MultibufferUpdateActionCopied:
+ ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
+ (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap,
+ (DrawablePtr)pPrevPixmap, pGC,
+ 0, 0,
+ pWin->drawable.width, pWin->drawable.height,
+ 0, 0);
+ break;
+ } /* end switch on update action */
+
+ /* display the new buffer */
+ ValidateGC ((DrawablePtr)pWin, pGC);
+ (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, (DrawablePtr)pWin, pGC,
+ 0, 0,
+ pWin->drawable.width, pWin->drawable.height,
+ 0, 0);
+ ppMultibuffers[i]->lastUpdate = currentTime;
+ MultibufferUpdate (pMultibuffer[i],
+ ppMultibuffers[i]->lastUpdate.milliseconds);
+ AliasMultibuffer (ppMultibuffers[i],
+ pMultibuffer[i] - ppMultibuffers[i]->buffers);
+ FreeScratchGC (pGC);
+ }
+}
+
+DrawablePtr
+GetBufferPointer (pWin, i)
+ WindowPtr pWin;
+ int i;
+{
+ MultibuffersPtr pMultibuffers;
+
+ if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr))
+ return NULL;
+ return (DrawablePtr) pMultibuffers->buffers[i].pPixmap;
+}
+
+int
+DisplayImageBuffers (ids, nbuf)
+ XID *ids;
+ int nbuf;
+{
+ MultibufferPtr *pMultibuffer;
+ MultibuffersPtr *pMultibuffers;
+ int i, j;
+
+ pMultibuffer = (MultibufferPtr *) ALLOCATE_LOCAL (nbuf * sizeof *pMultibuffer +
+ nbuf * sizeof *pMultibuffers);
+ if (!pMultibuffer)
+ return BadAlloc;
+ pMultibuffers = (MultibuffersPtr *) (pMultibuffer + nbuf);
+ for (i = 0; i < nbuf; i++)
+ {
+ pMultibuffer[i] = (MultibufferPtr) LookupIDByType (ids[i], MultibufferResType);
+ if (!pMultibuffer[i])
+ {
+ DEALLOCATE_LOCAL (pMultibuffer);
+ return MultibufferErrorBase + MultibufferBadBuffer;
+ }
+ pMultibuffers[i] = pMultibuffer[i]->pMultibuffers;
+ for (j = 0; j < i; j++)
+ if (pMultibuffers[i] == pMultibuffers[j])
+ {
+ DEALLOCATE_LOCAL (pMultibuffer);
+ return BadMatch;
+ }
+ }
+ PerformDisplayRequest (pMultibuffers, pMultibuffer, nbuf);
+ DEALLOCATE_LOCAL (pMultibuffer);
+ return Success;
+}
+
+
+static Bool
+QueueDisplayRequest (client, activateTime)
+ ClientPtr client;
+ TimeStamp activateTime;
+{
+ /* see xtest.c:ProcXTestFakeInput for code similar to this */
+
+ if (!ClientSleepUntil(client, &activateTime, NULL, NULL))
+ {
+ return FALSE;
+ }
+ /* swap the request back so we can simply re-execute it */
+ if (client->swapped)
+ {
+ register int n;
+ REQUEST (xMbufDisplayImageBuffersReq);
+
+ SwapRestL(stuff);
+ swaps (&stuff->length, n);
+ swaps (&stuff->minDelay, n);
+ swaps (&stuff->maxDelay, n);
+ }
+ ResetCurrentRequest (client);
+ client->sequence--;
+ return TRUE;
+}
+
+
+/*
+ * Deliver events to a buffer
+ */
+
+static int
+DeliverEventsToMultibuffer (pMultibuffer, pEvents, count, filter)
+ MultibufferPtr pMultibuffer;
+ xEvent *pEvents;
+ int count;
+ Mask filter;
+{
+ int deliveries = 0, nondeliveries = 0;
+ int attempt;
+ OtherClients *other;
+
+ /* if nobody wants the event, we're done */
+ if (!((pMultibuffer->otherEventMask|pMultibuffer->eventMask) & filter))
+ return 0;
+
+ /* maybe send event to owner */
+ if (attempt = TryClientEvents(
+ bClient(pMultibuffer), pEvents, count, pMultibuffer->eventMask, filter, (GrabPtr) 0))
+ {
+ if (attempt > 0)
+ deliveries++;
+ else
+ nondeliveries--;
+ }
+
+ /* maybe send event to other clients */
+ for (other = pMultibuffer->otherClients; other; other=other->next)
+ {
+ if (attempt = TryClientEvents(
+ rClient(other), pEvents, count, other->mask, filter, (GrabPtr) 0))
+ {
+ if (attempt > 0)
+ deliveries++;
+ else
+ nondeliveries--;
+ }
+ }
+ if (deliveries)
+ return deliveries;
+ return nondeliveries;
+}
+
+/*
+ * Send Expose events to interested clients
+ */
+
+void
+MultibufferExpose (pMultibuffer, pRegion)
+ MultibufferPtr pMultibuffer;
+ RegionPtr pRegion;
+{
+ if (pRegion && !REGION_NIL(pRegion))
+ {
+ xEvent *pEvent;
+ PixmapPtr pPixmap;
+ register xEvent *pe;
+ register BoxPtr pBox;
+ register int i;
+ int numRects;
+
+ pPixmap = pMultibuffer->pPixmap;
+ REGION_TRANSLATE(pPixmap->drawable.pScreen, pRegion,
+ -pPixmap->drawable.x, -pPixmap->drawable.y);
+ /* XXX MultibufferExpose "knows" the region representation */
+ numRects = REGION_NUM_RECTS(pRegion);
+ pBox = REGION_RECTS(pRegion);
+
+ pEvent = (xEvent *) ALLOCATE_LOCAL(numRects * sizeof(xEvent));
+ if (pEvent) {
+ pe = pEvent;
+
+ for (i=1; i<=numRects; i++, pe++, pBox++)
+ {
+ pe->u.u.type = Expose;
+ pe->u.expose.window = pPixmap->drawable.id;
+ pe->u.expose.x = pBox->x1;
+ pe->u.expose.y = pBox->y1;
+ pe->u.expose.width = pBox->x2 - pBox->x1;
+ pe->u.expose.height = pBox->y2 - pBox->y1;
+ pe->u.expose.count = (numRects - i);
+ }
+ (void) DeliverEventsToMultibuffer (pMultibuffer, pEvent, numRects,
+ ExposureMask);
+ DEALLOCATE_LOCAL(pEvent);
+ }
+ }
+}
+
+/* send UpdateNotify event */
+void
+MultibufferUpdate (pMultibuffer, time)
+ MultibufferPtr pMultibuffer;
+ CARD32 time;
+{
+ xMbufUpdateNotifyEvent event;
+
+ event.type = MultibufferEventBase + MultibufferUpdateNotify;
+ event.buffer = pMultibuffer->pPixmap->drawable.id;
+ event.timeStamp = time;
+ (void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event,
+ 1, (Mask)MultibufferUpdateNotifyMask);
+}
+
+/*
+ * The sample implementation will never generate MultibufferClobberNotify
+ * events
+ */
+
+void
+MultibufferClobber (pMultibuffer)
+ MultibufferPtr pMultibuffer;
+{
+ xMbufClobberNotifyEvent event;
+
+ event.type = MultibufferEventBase + MultibufferClobberNotify;
+ event.buffer = pMultibuffer->pPixmap->drawable.id;
+ event.state = pMultibuffer->clobber;
+ (void) DeliverEventsToMultibuffer (pMultibuffer, (xEvent *)&event,
+ 1, (Mask)MultibufferClobberNotifyMask);
+}
+
+/*
+ * make the resource id for buffer i refer to the window
+ * drawable instead of the pixmap;
+ */
+
+static void
+AliasMultibuffer (pMultibuffers, i)
+ MultibuffersPtr pMultibuffers;
+ int i;
+{
+ MultibufferPtr pMultibuffer;
+
+ if (i == pMultibuffers->displayedMultibuffer)
+ return;
+ /*
+ * remove the old association
+ */
+ if (pMultibuffers->displayedMultibuffer >= 0)
+ {
+ pMultibuffer = &pMultibuffers->buffers[pMultibuffers->displayedMultibuffer];
+ ChangeResourceValue (pMultibuffer->pPixmap->drawable.id,
+ MultibufferDrawableResType,
+ (pointer) pMultibuffer->pPixmap);
+ }
+ /*
+ * make the new association
+ */
+ pMultibuffer = &pMultibuffers->buffers[i];
+ ChangeResourceValue (pMultibuffer->pPixmap->drawable.id,
+ MultibufferDrawableResType,
+ (pointer) pMultibuffers->pWindow);
+ pMultibuffers->displayedMultibuffer = i;
+}
+
+/*
+ * free everything associated with multibuffering for this
+ * window
+ */
+
+void
+DestroyImageBuffers (pWin)
+ WindowPtr pWin;
+{
+ FreeResourceByType (pWin->drawable.id, MultibuffersResType, FALSE);
+ /* Zero out the window's pointer to the buffers so they won't be reused */
+ pWin->devPrivates[MultibufferWindowIndex].ptr = NULL;
+}
+
+/*
+ * resize the buffers when the window is resized
+ */
+
+static Bool
+MultibufferPositionWindow (pWin, x, y)
+ WindowPtr pWin;
+ int x, y;
+{
+ ScreenPtr pScreen;
+ MultibufferScreenPtr pMultibufferScreen;
+ MultibuffersPtr pMultibuffers;
+ MultibufferPtr pMultibuffer;
+ int width, height;
+ int i;
+ int dx, dy, dw, dh;
+ int sourcex, sourcey;
+ int destx, desty;
+ PixmapPtr pPixmap;
+ GCPtr pGC;
+ int savewidth, saveheight;
+ xRectangle clearRect;
+ Bool clear;
+
+ pScreen = pWin->drawable.pScreen;
+ pMultibufferScreen = (MultibufferScreenPtr) pScreen->devPrivates[MultibufferScreenIndex].ptr;
+ (*pMultibufferScreen->PositionWindow) (pWin, x, y);
+
+ /* if this window is not multibuffered, we're done */
+ if (!(pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr))
+ return TRUE;
+
+ /* if new size is same as old, we're done */
+ if (pMultibuffers->width == pWin->drawable.width &&
+ pMultibuffers->height == pWin->drawable.height)
+ return TRUE;
+
+ width = pWin->drawable.width;
+ height = pWin->drawable.height;
+ dx = pWin->drawable.x - pMultibuffers->x;
+ dy = pWin->drawable.x - pMultibuffers->y;
+ dw = width - pMultibuffers->width;
+ dh = height - pMultibuffers->height;
+ GravityTranslate (0, 0, -dx, -dy, dw, dh,
+ pWin->bitGravity, &destx, &desty);
+
+ /* if the window grew, remember to paint the window background,
+ * and maybe send expose events, for the new areas of the buffers
+ */
+ clear = pMultibuffers->width < width || pMultibuffers->height < height ||
+ pWin->bitGravity == ForgetGravity;
+
+ sourcex = 0;
+ sourcey = 0;
+ savewidth = pMultibuffers->width;
+ saveheight = pMultibuffers->height;
+ /* clip rectangle to source and destination */
+ if (destx < 0)
+ {
+ savewidth += destx;
+ sourcex -= destx;
+ destx = 0;
+ }
+ if (destx + savewidth > width)
+ savewidth = width - destx;
+ if (desty < 0)
+ {
+ saveheight += desty;
+ sourcey -= desty;
+ desty = 0;
+ }
+ if (desty + saveheight > height)
+ saveheight = height - desty;
+
+ pMultibuffers->width = width;
+ pMultibuffers->height = height;
+ pMultibuffers->x = pWin->drawable.x;
+ pMultibuffers->y = pWin->drawable.y;
+
+ pGC = GetScratchGC (pWin->drawable.depth, pScreen);
+ if (clear)
+ {
+ SetupBackgroundPainter (pWin, pGC);
+ clearRect.x = 0;
+ clearRect.y = 0;
+ clearRect.width = width;
+ clearRect.height = height;
+ }
+ for (i = 0; i < pMultibuffers->numMultibuffer; i++)
+ {
+ pMultibuffer = &pMultibuffers->buffers[i];
+ pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height,
+ pWin->drawable.depth);
+ if (!pPixmap)
+ {
+ DestroyImageBuffers (pWin);
+ break;
+ }
+ ValidateGC ((DrawablePtr)pPixmap, pGC);
+ /*
+ * I suppose this could avoid quite a bit of work if
+ * it computed the minimal area required.
+ */
+ if (clear)
+ (*pGC->ops->PolyFillRect) ((DrawablePtr)pPixmap, pGC, 1, &clearRect);
+ if (pWin->bitGravity != ForgetGravity)
+ {
+ (*pGC->ops->CopyArea) ((DrawablePtr)pMultibuffer->pPixmap,
+ (DrawablePtr)pPixmap, pGC,
+ sourcex, sourcey, savewidth, saveheight,
+ destx, desty);
+ }
+ pPixmap->drawable.id = pMultibuffer->pPixmap->drawable.id;
+ (*pScreen->DestroyPixmap) (pMultibuffer->pPixmap);
+ pMultibuffer->pPixmap = pPixmap;
+ if (i != pMultibuffers->displayedMultibuffer)
+ {
+ ChangeResourceValue (pPixmap->drawable.id,
+ MultibufferDrawableResType,
+ (pointer) pPixmap);
+ }
+ }
+ FreeScratchGC (pGC);
+ return TRUE;
+}
+
+/* Resource delete func for MultibufferDrawableResType */
+/*ARGSUSED*/
+static int
+MultibufferDrawableDelete (value, id)
+ pointer value;
+ XID id;
+{
+ DrawablePtr pDrawable = (DrawablePtr)value;
+ WindowPtr pWin;
+ MultibuffersPtr pMultibuffers;
+ PixmapPtr pPixmap;
+
+ if (pDrawable->type == DRAWABLE_WINDOW)
+ {
+ pWin = (WindowPtr) pDrawable;
+ pMultibuffers = (MultibuffersPtr) pWin->devPrivates[MultibufferWindowIndex].ptr;
+ pPixmap = pMultibuffers->buffers[pMultibuffers->displayedMultibuffer].pPixmap;
+ }
+ else
+ {
+ pPixmap = (PixmapPtr) pDrawable;
+ }
+ (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
+ return Success;
+}
+
+/* Resource delete func for MultibufferResType */
+/*ARGSUSED*/
+static int
+MultibufferDelete (value, id)
+ pointer value;
+ XID id;
+{
+ MultibufferPtr pMultibuffer = (MultibufferPtr)value;
+ MultibuffersPtr pMultibuffers;
+
+ pMultibuffers = pMultibuffer->pMultibuffers;
+ if (--pMultibuffers->refcnt == 0)
+ {
+ FreeResourceByType (pMultibuffers->pWindow->drawable.id,
+ MultibuffersResType, TRUE);
+ xfree (pMultibuffers);
+ }
+ return Success;
+}
+
+/* Resource delete func for MultibuffersResType */
+/*ARGSUSED*/
+static int
+MultibuffersDelete (value, id)
+ pointer value;
+ XID id;
+{
+ MultibuffersPtr pMultibuffers = (MultibuffersPtr)value;
+ int i;
+
+ if (pMultibuffers->refcnt == pMultibuffers->numMultibuffer)
+ {
+ for (i = pMultibuffers->numMultibuffer; --i >= 0; )
+ FreeResource (pMultibuffers->buffers[i].pPixmap->drawable.id, 0);
+ }
+ return Success;
+}
+
+/* Resource delete func for OtherClientResType */
+static int
+OtherClientDelete (value, id)
+ pointer value;
+ XID id;
+{
+ MultibufferPtr pMultibuffer = (MultibufferPtr)value;
+ register OtherClientsPtr other, prev;
+
+ prev = 0;
+ for (other = pMultibuffer->otherClients; other; other = other->next)
+ {
+ if (other->resource == id)
+ {
+ if (prev)
+ prev->next = other->next;
+ else
+ pMultibuffer->otherClients = other->next;
+ xfree (other);
+ RecalculateMultibufferOtherEvents (pMultibuffer);
+ break;
+ }
+ prev = other;
+ }
+ return Success;
+}
+
+static int
+EventSelectForMultibuffer (pMultibuffer, client, mask)
+ MultibufferPtr pMultibuffer;
+ ClientPtr client;
+ Mask mask;
+{
+ OtherClientsPtr other;
+
+ if (mask & ~ValidEventMasks)
+ {
+ client->errorValue = mask;
+ return BadValue;
+ }
+ if (bClient (pMultibuffer) == client)
+ {
+ pMultibuffer->eventMask = mask;
+ }
+ else /* some other client besides the creator wants events */
+ {
+ for (other = pMultibuffer->otherClients; other; other = other->next)
+ {
+ if (SameClient (other, client))
+ {
+ if (mask == 0)
+ {
+ FreeResource (other->resource, RT_NONE);
+ break;
+ }
+ other->mask = mask;
+ break;
+ }
+ }
+ if (!other)
+ { /* new client that never selected events on this buffer before */
+ other = (OtherClients *) xalloc (sizeof (OtherClients));
+ if (!other)
+ return BadAlloc;
+ other->mask = mask;
+ other->resource = FakeClientID (client->index);
+ if (!AddResource (other->resource, OtherClientResType, (pointer) pMultibuffer))
+ {
+ xfree (other);
+ return BadAlloc;
+ }
+ other->next = pMultibuffer->otherClients;
+ pMultibuffer->otherClients = other;
+ }
+ RecalculateMultibufferOtherEvents (pMultibuffer);
+ }
+ return (client->noClientException);
+}
+
+/* or together all the otherClients event masks */
+static void
+RecalculateMultibufferOtherEvents (pMultibuffer)
+ MultibufferPtr pMultibuffer;
+{
+ Mask otherEventMask;
+ OtherClients *other;
+
+ otherEventMask = 0L;
+ for (other = pMultibuffer->otherClients; other; other = other->next)
+ otherEventMask |= other->mask;
+ pMultibuffer->otherEventMask = otherEventMask;
+}
+
+/* add milliseconds to a timestamp, handling overflow */
+static void
+BumpTimeStamp (ts, inc)
+TimeStamp *ts;
+CARD32 inc;
+{
+ CARD32 newms;
+
+ newms = ts->milliseconds + inc;
+ if (newms < ts->milliseconds)
+ ts->months++;
+ ts->milliseconds = newms;
+}
diff --git a/Xext/mbufbf.c b/Xext/mbufbf.c
new file mode 100644
index 000000000..3c873086f
--- /dev/null
+++ b/Xext/mbufbf.c
@@ -0,0 +1,1052 @@
+/*
+
+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.
+
+*/
+
+/* $Xorg: mbufbf.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <stdio.h>
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "opaque.h"
+#include "regionstr.h"
+#include "gcstruct.h"
+#include "inputstr.h"
+#include "validate.h"
+#include <sys/time.h>
+
+#define _MULTIBUF_SERVER_ /* don't want Xlib structures */
+#define _MULTIBUF_BUFFER_
+#include "multibufst.h"
+
+/*
+Support for doublebuffer hardare
+
+This code is designed to support doublebuffer hardware where the
+displayed buffer is selected on a per-pixel basis by an additional bit
+plane, called the select plane. It could probably be easily modified
+to work with systems that use window-id planes.
+
+This is done by creating a new drawable type, DRAWABLE_BUFFER. The
+type has the same exact layout as a window drawable. Your code should
+treat a DRAWABLE_BUFFER the same as it would tread a DRAWABLE_WINDOW
+when handling the gc drawing functions. In addition, PaintWindowBackground,
+CopyWindow, and all of the gc drawing functions to be able to draw into both
+framebuffers. Which framebuffer to draw into is selected by the contents of
+ pWin->devPrivates[frameWindowPrivateIndex].
+The content of the devPrivate is either from frameBuffer[0] or
+frameBuffer[1], depending on which buffer is being drawn into. When
+ pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[0],
+the functions should draw into the front framebuffer. When
+ pWin->devPrivates[frameWindowPrivateIndex] == frameBuffer[1],
+the functions should draw into the back framebuffer.
+
+In addition, you need to provide a function that allows you to copy
+bits between the buffers (optional since CopyArea can be used) and a
+function that draws into the select plane. Then, you need to register
+your functions and other information, by calling:
+
+void
+RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane,
+ CopyBufferBitsFunc, DrawSelectPlaneFunc)
+ int nInfo;
+ xMbufBufferInfo *pInfo;
+ DevUnion *frameBuffer;
+ DevUnion selectPlane;
+
+"pInfo" is an array indicating which visuals and depths that double
+buffering is supported on. "nInfo" is the length of the array.
+
+"frameBuffer" is array of length 2. The contents of the array element
+is ddx-specific. The content of frameBuffer[0] should, when placed in
+the window private, indicate that framebuffer 0 should be drawn into.
+The contents of frameBuffer[1], when placed into the window private,
+should indicate that framebuffer 1 should be drawn into.
+
+"selectPlane" is ddx-specific. It should contain information
+neccessary for your displayProc to access the select plane.
+It is passed to DrawSelectPlaneFunc.
+
+"CopyBufferBitsFunc" is a ddx-specific function that copies from one
+buffer of a multibuffered window to another buffer. If the CopyBufferBitsFunc
+is NULL, a default function will be used that calls pScreen->CopyArea.
+
+ void CopyBufferBitsFunc(pMBWindow, srcBufferNum, dstBufferNum)
+ mbufWindowPtr pMBWindow;
+ int srcBufferNum, dstBufferNum;
+
+"DrawSelectPlaneFunc" is a ddx-specific function that fills the
+regions "prgn" of select plane with the value "bufferNum". If
+selectPlane is a DrawablePtr (such as a PixmapPtr), you can pass
+NULL for DrawSelectPlaneFunc, a default function will be used that
+calls FillRectangle on the selectPlane.
+
+ void DrawSelectPlaneFunc(pScreen, selectPlane, prgn, bufferNum)
+ ScreenPtr pScreen;
+ DevUnion selectPlane;
+ RegionPtr prgn;
+ long bufferNum;
+
+...
+...
+...
+
+*/
+
+#define MAX_BUFFERS 2 /* Only supports 2 buffers */
+#define FRONT_BUFFER 0
+#define BACK_BUFFER 1
+
+
+/* Buffer drawables have the same structure as window drawables */
+typedef WindowRec BufferRec;
+typedef WindowPtr BufferPtr;
+
+
+/*
+ * Call RegisterHdwrBuffer for every screen that has doublebuffer hardware.
+ */
+
+static int bufNumInfo[MAXSCREENS];
+static xMbufBufferInfo *bufInfo[MAXSCREENS];
+static DevUnion *bufFrameBuffer[MAXSCREENS];
+static DevUnion bufselectPlane[MAXSCREENS];
+static void (* bufCopyBufferBitsFunc[MAXSCREENS])();
+static void (* bufDrawSelectPlaneFunc[MAXSCREENS])();
+
+static Bool bufMultibufferInit();
+
+
+void
+RegisterDoubleBufferHardware(pScreen, nInfo, pInfo, frameBuffer, selectPlane,
+ CopyBufferBitsFunc, DrawSelectPlaneFunc)
+ ScreenPtr pScreen;
+ int nInfo;
+ xMbufBufferInfo *pInfo;
+ DevUnion *frameBuffer;
+ DevUnion selectPlane;
+ void (* CopyBufferBitsFunc)();
+ void (* DrawSelectPlaneFunc)();
+{
+ bufNumInfo[pScreen->myNum] = nInfo;
+ bufInfo[pScreen->myNum] = pInfo;
+ bufFrameBuffer[pScreen->myNum] = frameBuffer;
+ bufselectPlane[pScreen->myNum] = selectPlane;
+
+ bufCopyBufferBitsFunc[pScreen->myNum] = CopyBufferBitsFunc;
+ bufDrawSelectPlaneFunc[pScreen->myNum] = DrawSelectPlaneFunc;
+
+ /* Register ourselves with device-independent multibuffers code */
+ RegisterMultibufferInit(pScreen, bufMultibufferInit);
+}
+
+
+/*
+ * Called by Multibuffer extension initialization.
+ * Initializes mbufScreenRec and its devPrivate.
+ */
+
+static Bool NoopDDA_True() { return TRUE; }
+static Bool bufPositionWindow();
+static int bufCreateImageBuffers();
+static void bufDestroyImageBuffers();
+static void bufDisplayImageBuffers();
+static void bufClearImageBufferArea();
+static void bufDestroyBuffer();
+static void bufCopyBufferBits();
+static void bufDrawSelectPlane();
+static void bufWrapScreenFuncs();
+static void bufResetProc();
+
+static void bufPostValidateTree();
+static void bufClipNotify();
+static void bufWindowExposures();
+static Bool bufChangeWindowAttributes();
+static void bufClearToBackground();
+static void bufCopyWindow();
+
+extern WindowPtr *WindowTable;
+
+static Bool
+bufMultibufferInit(pScreen, pMBScreen)
+ ScreenPtr pScreen;
+ mbufScreenPtr pMBScreen;
+{
+ mbufBufferPrivPtr pMBPriv;
+ BoxRec box;
+
+ /* Multibuffer info */
+ pMBScreen->nInfo = bufNumInfo[pScreen->myNum];
+ pMBScreen->pInfo = bufInfo[pScreen->myNum];
+
+ /* Hooks */
+ pMBScreen->CreateImageBuffers = bufCreateImageBuffers;
+ pMBScreen->DestroyImageBuffers = bufDestroyImageBuffers;
+ pMBScreen->DisplayImageBuffers = bufDisplayImageBuffers;
+ pMBScreen->ClearImageBufferArea = bufClearImageBufferArea;
+ pMBScreen->ChangeMBufferAttributes = NoopDDA_True;
+ pMBScreen->ChangeBufferAttributes = NoopDDA_True;
+ pMBScreen->DeleteBufferDrawable = bufDestroyBuffer;
+ pMBScreen->WrapScreenFuncs = bufWrapScreenFuncs;
+ pMBScreen->ResetProc = bufResetProc;
+ /* Create devPrivate part */
+ pMBPriv = (mbufBufferPrivPtr) xalloc(sizeof *pMBPriv);
+ if (!pMBPriv)
+ return (FALSE);
+
+ pMBScreen->devPrivate.ptr = (pointer) pMBPriv;
+ pMBPriv->frameBuffer = bufFrameBuffer[pScreen->myNum];
+ pMBPriv->selectPlane = bufselectPlane[pScreen->myNum];
+
+ /*
+ * Initializing the subtractRgn to the screen area will ensure that
+ * the selectPlane will get cleared on the first PostValidateTree.
+ */
+
+ box.x1 = 0;
+ box.y1 = 0;
+ box.x2 = pScreen->width;
+ box.y2 = pScreen->height;
+
+ pMBPriv->rgnChanged = TRUE;
+ REGION_INIT(pScreen, &pMBPriv->backBuffer, &box, 1);
+ REGION_INIT(pScreen, &pMBPriv->subtractRgn, &box, 1);
+ REGION_INIT(pScreen, &pMBPriv->unionRgn, NullBox, 0);
+
+ /* Misc functions */
+ pMBPriv->CopyBufferBits = bufCopyBufferBitsFunc[pScreen->myNum];
+ pMBPriv->DrawSelectPlane = bufDrawSelectPlaneFunc[pScreen->myNum];
+
+ if (!pMBPriv->CopyBufferBits)
+ pMBPriv->CopyBufferBits = bufCopyBufferBits;
+
+ if (!pMBPriv->DrawSelectPlane)
+ pMBPriv->DrawSelectPlane = bufDrawSelectPlane;
+
+ /* screen functions */
+ pMBPriv->funcsWrapped = 0;
+ pMBPriv->inClearToBackground = FALSE;
+ pMBPriv->WindowExposures = NULL;
+ pMBPriv->CopyWindow = NULL;
+ pMBPriv->ClearToBackground = NULL;
+ pMBPriv->ClipNotify = NULL;
+ pMBPriv->ChangeWindowAttributes = NULL;
+
+ /* Start out wrapped to clear select plane */
+ WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree);
+ return TRUE;
+}
+
+static void
+UpdateBufferFromWindow(pBuffer, pWin)
+ BufferPtr pBuffer;
+ WindowPtr pWin;
+{
+ pBuffer->drawable.x = pWin->drawable.x;
+ pBuffer->drawable.y = pWin->drawable.y;
+ pBuffer->drawable.width = pWin->drawable.width;
+ pBuffer->drawable.height = pWin->drawable.height;
+
+ pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+
+ /* Update for PaintWindowBackground */
+ pBuffer->parent = pWin->parent;
+
+ /*
+ * Make the borderClip the same as the clipList so
+ * NotClippedByChildren comes out with just clipList.
+ */
+
+ pBuffer->clipList = pWin->clipList;
+ pBuffer->borderClip = pWin->clipList;
+ pBuffer->winSize = pWin->winSize;
+ pBuffer->borderSize = pWin->borderSize;
+
+ pBuffer->origin = pWin->origin;
+}
+
+static BufferPtr
+bufCreateBuffer(pScreen, pWin, bufferNum)
+ ScreenPtr pScreen;
+ WindowPtr pWin;
+ int bufferNum;
+{
+ mbufBufferPrivPtr pMBPriv;
+ DevUnion *devPrivates;
+ BufferPtr pBuffer;
+ int i;
+
+ pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
+
+ pBuffer = AllocateWindow(pWin->drawable.pScreen);
+ if (!pBuffer)
+ return (NULL);
+
+ /* XXX- Until we know what is needed, copy everything. */
+ devPrivates = pBuffer->devPrivates;
+ *pBuffer = *pWin;
+ pBuffer->devPrivates = devPrivates;
+
+ pBuffer->drawable.type = DRAWABLE_BUFFER;
+ pBuffer->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+
+ pBuffer->nextSib = NULL;
+ pBuffer->prevSib = NULL;
+ pBuffer->firstChild = NULL;
+ pBuffer->lastChild = NULL;
+
+ /* XXX - Worry about backingstore later */
+ pBuffer->backStorage = NULL;
+ pBuffer->backingStore = NotUseful;
+
+ /* XXX - Need to call pScreen->CreateWindow for tile/stipples
+ * or should I just copy the devPrivates?
+ */
+
+ for (i=0; i < pScreen->WindowPrivateLen; i++)
+ pBuffer->devPrivates[i] = pWin->devPrivates[i];
+
+ pBuffer->devPrivates[frameWindowPrivateIndex] =
+ pMBPriv->frameBuffer[bufferNum];
+
+ return pBuffer;
+}
+
+static void
+bufDestroyBuffer(pDrawable)
+ DrawablePtr pDrawable;
+{
+ xfree(pDrawable);
+}
+
+/*ARGSUSED*/
+static int
+bufCreateImageBuffers (pWin, nbuf, ids, action, hint)
+ WindowPtr pWin;
+ int nbuf;
+ XID *ids;
+ int action;
+ int hint;
+{
+ ScreenPtr pScreen;
+ mbufScreenPtr pMBScreen;
+ mbufWindowPtr pMBWindow;
+ mbufBufferPtr pMBBuffer;
+ int i;
+
+ pScreen = pWin->drawable.pScreen;
+ pMBScreen = MB_SCREEN_PRIV(pScreen);
+ pMBWindow = MB_WINDOW_PRIV(pWin);
+
+ pMBWindow->devPrivate.ptr = (pointer) REGION_CREATE(pScreen, 0,0);
+ if (!pMBWindow->devPrivate.ptr)
+ return(0);
+ REGION_COPY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr,
+ &pWin->clipList);
+
+ for (i = 0; i < nbuf; i++)
+ {
+ pMBBuffer = pMBWindow->buffers + i;
+ pMBBuffer->pDrawable = (DrawablePtr) bufCreateBuffer(pScreen,pWin,i);
+
+ if (!pMBBuffer->pDrawable)
+ break;
+
+ if (!AddResource (ids[i], MultibufferDrawableResType,
+ (pointer) pMBBuffer->pDrawable))
+ {
+ bufDestroyBuffer((BufferPtr) pMBBuffer->pDrawable);
+ break;
+ }
+ pMBBuffer->pDrawable->id = ids[i];
+
+ /*
+ * If window is already mapped, generate exposures and
+ * clear the area of the newly buffers.
+ */
+
+ if ((pWin->realized) && (i != pMBWindow->displayedMultibuffer))
+ (* pMBScreen->ClearImageBufferArea)(pMBBuffer, 0,0, 0,0, TRUE);
+ }
+
+ return i;
+}
+
+static void
+bufDestroyImageBuffers(pWin)
+ WindowPtr pWin;
+{
+ ScreenPtr pScreen;
+ mbufWindowPtr pMBWindow;
+
+ pScreen = pWin->drawable.pScreen;
+
+ if (pMBWindow = MB_WINDOW_PRIV(pWin))
+ {
+ mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
+
+ /*
+ * if the backbuffer is currently being displayed, move the bits
+ * to the frontbuffer and display it instead.
+ */
+
+ if (pWin->realized && (pMBWindow->displayedMultibuffer == BACK_BUFFER))
+ {
+ (* pMBPriv->CopyBufferBits)(pMBWindow, BACK_BUFFER, FRONT_BUFFER);
+ REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer,
+ &pMBPriv->backBuffer, &pWin->clipList);
+ (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
+ &pWin->clipList, FRONT_BUFFER);
+ }
+
+ /* Switch window rendering to front buffer */
+ pWin->devPrivates[frameWindowPrivateIndex] =
+ pMBPriv->frameBuffer[FRONT_BUFFER];
+
+ REGION_DESTROY(pScreen, (RegionPtr) pMBWindow->devPrivate.ptr);
+ pMBWindow->devPrivate.ptr = NULL;
+ }
+}
+
+/*
+ * Can be replaced by pScreen->ClearToBackground if pBuffer->eventMask
+ * and wOtherEventsMasks(pBuffer) were setup.
+ */
+
+static void
+bufClearImageBufferArea(pMBBuffer, x,y, w,h, generateExposures)
+ mbufBufferPtr pMBBuffer;
+ short x,y;
+ unsigned short w,h;
+ Bool generateExposures;
+{
+ BoxRec box;
+ RegionRec reg;
+ RegionPtr pBSReg = NullRegion;
+ ScreenPtr pScreen;
+ BoxPtr extents;
+ int x1, y1, x2, y2;
+ BufferPtr pBuffer;
+
+ pBuffer = (BufferPtr) pMBBuffer->pDrawable;
+ /* compute everything using ints to avoid overflow */
+
+ x1 = pBuffer->drawable.x + x;
+ y1 = pBuffer->drawable.y + y;
+ if (w)
+ x2 = x1 + (int) w;
+ else
+ x2 = x1 + (int) pBuffer->drawable.width - (int) x;
+ if (h)
+ y2 = y1 + h;
+ else
+ y2 = y1 + (int) pBuffer->drawable.height - (int) y;
+
+ extents = &pBuffer->clipList.extents;
+
+ /* clip the resulting rectangle to the window clipList extents. This
+ * makes sure that the result will fit in a box, given that the
+ * screen is < 32768 on a side.
+ */
+
+ if (x1 < extents->x1)
+ x1 = extents->x1;
+ if (x2 > extents->x2)
+ x2 = extents->x2;
+ if (y1 < extents->y1)
+ y1 = extents->y1;
+ if (y2 > extents->y2)
+ y2 = extents->y2;
+
+ if (x2 <= x1 || y2 <= y1)
+ {
+ x2 = x1 = 0;
+ y2 = y1 = 0;
+ }
+
+ box.x1 = x1;
+ box.x2 = x2;
+ box.y1 = y1;
+ box.y2 = y2;
+
+ pScreen = pBuffer->drawable.pScreen;
+ REGION_INIT(pScreen, &reg, &box, 1);
+ if (pBuffer->backStorage)
+ {
+ /*
+ * If the window has backing-store on, call through the
+ * ClearToBackground vector to handle the special semantics
+ * (i.e. things backing store is to be cleared out and
+ * an Expose event is to be generated for those areas in backing
+ * store if generateExposures is TRUE).
+ */
+ pBSReg = (* pScreen->ClearBackingStore)(pBuffer, x, y, w, h,
+ generateExposures);
+ }
+
+ REGION_INTERSECT(pScreen, &reg, &reg, &pBuffer->clipList);
+ if (pBuffer->backgroundState != None)
+ (*pScreen->PaintWindowBackground)(pBuffer, &reg, PW_BACKGROUND);
+ if (generateExposures)
+ MultibufferExpose(pMBBuffer, &reg);
+#ifdef _notdef
+ /* XXBS - This is the original miClearToBackground code.
+ * WindowExposures needs to be called (or the functionality emulated)
+ * in order for backingStore to work, but first, pBuffer->eventMask
+ * and wOtherEventsMasks(pBuffer) need to be setup correctly.
+ */
+
+ if (generateExposures)
+ (*pScreen->WindowExposures)(pBuffer, &reg, pBSReg);
+ else if (pBuffer->backgroundState != None)
+ (*pScreen->PaintWindowBackground)(pBuffer, &reg, PW_BACKGROUND);
+#endif
+ REGION_UNINIT(pScreen, &reg);
+ if (pBSReg)
+ REGION_DESTROY(pScreen, pBSReg);
+}
+
+static void
+bufWrapScreenFuncs(pScreen)
+ ScreenPtr pScreen;
+{
+ mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
+
+ WRAP_SCREEN_FUNC(pScreen,pMBPriv,PostValidateTree, bufPostValidateTree);
+ WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClipNotify, bufClipNotify);
+ WRAP_SCREEN_FUNC(pScreen,pMBPriv,WindowExposures,bufWindowExposures);
+ WRAP_SCREEN_FUNC(pScreen,pMBPriv,ChangeWindowAttributes, bufChangeWindowAttributes);
+ WRAP_SCREEN_FUNC(pScreen,pMBPriv,ClearToBackground,bufClearToBackground);
+ WRAP_SCREEN_FUNC(pScreen,pMBPriv,CopyWindow,bufCopyWindow);
+}
+
+static void
+bufResetProc(pScreen)
+ ScreenPtr pScreen;
+{
+ mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
+
+ /*
+ * frameBuffer, selectPlane, and pInfo should be freed by
+ * whoever called RegisterDoubleBufferHardware
+ */
+
+ REGION_UNINIT(pScreen, &pMBPriv->backBuffer);
+ REGION_UNINIT(pScreen, &pMBPriv->subtractRgn);
+ REGION_UNINIT(pScreen, &pMBPriv->unionRgn);
+ xfree(pMBPriv);
+}
+
+/*---------------------------------------------------------------------------*/
+
+/*
+ * Used if CopyBufferBitsFunc is not provided when registering.
+ * This should work for everybody since CopyArea needs to support
+ * copying between buffers anyway.
+ */
+
+static void
+bufCopyBufferBits(pMBWindow, srcBufferNum, dstBufferNum)
+ mbufWindowPtr pMBWindow;
+ int srcBufferNum, dstBufferNum;
+{
+ DrawablePtr pSrcBuffer, pDstBuffer;
+ GCPtr pGC;
+
+ pSrcBuffer = pMBWindow->buffers[srcBufferNum].pDrawable;
+ pDstBuffer = pMBWindow->buffers[dstBufferNum].pDrawable;
+
+ pGC = GetScratchGC (pDstBuffer->depth, pDstBuffer->pScreen);
+ if (!pGC)
+ return;
+
+ ValidateGC (pDstBuffer, pGC);
+ (* pGC->ops->CopyArea) (pSrcBuffer, pDstBuffer, pGC,
+ 0,0, pDstBuffer->width, pDstBuffer->height, 0,0);
+ FreeScratchGC (pGC);
+}
+
+/*
+ * Used if DrawSelectPlanFunc is not provided for when registering.
+ * However, it only works if selectPlane.ptr is a drawable. Also
+ * assumes that painting with color 0 selects the front buffer,
+ * while color 1 selects the back buffer.
+ */
+
+static void
+bufDrawSelectPlane(pScreen, selectPlane, prgn, bufferNum)
+ ScreenPtr pScreen;
+ DevUnion selectPlane;
+ RegionPtr prgn;
+ long bufferNum;
+{
+ DrawablePtr pDrawable;
+ GCPtr pGC;
+ register int i;
+ register BoxPtr pbox;
+ register xRectangle *prect;
+ int numRects;
+ XID value;
+
+ if (REGION_NUM_RECTS(prgn) == 0)
+ return;
+
+ pDrawable = (DrawablePtr) selectPlane.ptr;
+ pGC = GetScratchGC (pDrawable->depth, pScreen);
+ if (!pGC)
+ return;
+
+ prect = (xRectangle *)ALLOCATE_LOCAL(REGION_NUM_RECTS(prgn) *
+ sizeof(xRectangle));
+ if (!prect)
+ {
+ FreeScratchGC(pGC);
+ return;
+ }
+
+ value = (XID) bufferNum;
+ DoChangeGC(pGC, GCForeground, &value, 0);
+ ValidateGC(pDrawable, pGC);
+
+ numRects = REGION_NUM_RECTS(prgn);
+ pbox = REGION_RECTS(prgn);
+ for (i= numRects; --i >= 0; pbox++, prect++)
+ {
+ prect->x = pbox->x1;
+ prect->y = pbox->y1;
+ prect->width = pbox->x2 - pbox->x1;
+ prect->height = pbox->y2 - pbox->y1;
+ }
+ prect -= numRects;
+ (* pGC->ops->PolyFillRect)(pDrawable, pGC, numRects, prect);
+
+ DEALLOCATE_LOCAL(prect);
+ FreeScratchGC (pGC);
+}
+
+
+static void
+bufDisplayImageBuffers(pScreen, ppMBWindow, ppMBBuffer, nbuf)
+ ScreenPtr pScreen;
+ mbufBufferPtr *ppMBBuffer;
+ mbufWindowPtr *ppMBWindow;
+ int nbuf;
+{
+ WindowPtr pWin;
+ BufferPtr pPrevBuffer, pNewBuffer;
+ int i, number;
+ mbufBufferPrivPtr pMBPriv;
+ mbufBufferPtr pPrevMBBuffer;
+
+ pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
+
+ for (i = 0; i < nbuf; i++)
+ {
+ number = ppMBBuffer[i]->number; /* 0=frontbuffer, 1=backbuffer */
+ pWin = ppMBWindow[i]->pWindow;
+ pPrevMBBuffer = MB_DISPLAYED_BUFFER(ppMBWindow[i]);
+
+ pPrevBuffer = (BufferPtr) pPrevMBBuffer->pDrawable;
+ pNewBuffer = (BufferPtr) ppMBBuffer[i]->pDrawable;
+
+ if (pPrevBuffer != pNewBuffer)
+ {
+ RegionPtr backBuffer = &pMBPriv->backBuffer;
+
+ /*
+ * Update the select plane and the backBuffer region.
+ */
+
+ (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
+ &pWin->clipList, number);
+
+ if (number == BACK_BUFFER)
+ REGION_UNION(pScreen, backBuffer, backBuffer,
+ &pWin->clipList);
+ else
+ REGION_SUBTRACT(pScreen, backBuffer, backBuffer,
+ &pWin->clipList);
+
+ /* Switch which framebuffer the window draws into */
+ pWin->devPrivates[frameWindowPrivateIndex] =
+ pMBPriv->frameBuffer[number];
+ }
+
+ switch (ppMBWindow[i]->updateAction)
+ {
+ case MultibufferUpdateActionUndefined:
+ break;
+ case MultibufferUpdateActionBackground:
+ (* MB_SCREEN_PRIV(pScreen)->ClearImageBufferArea)
+ (pPrevMBBuffer, 0,0, 0,0, FALSE);
+ break;
+ case MultibufferUpdateActionUntouched:
+ break;
+ case MultibufferUpdateActionCopied:
+ if (pPrevBuffer != pNewBuffer)
+ {
+ (* pMBPriv->CopyBufferBits) (ppMBWindow[i],
+ ppMBBuffer[i]->number, pPrevMBBuffer->number);
+ }
+ break;
+ }
+ }
+}
+
+/* Updates the backBuffer region and paints the selectPlane. */
+
+static void
+bufPostValidateTree(pParent, pChild, kind)
+ WindowPtr pParent, pChild;
+ VTKind kind;
+{
+ ScreenPtr pScreen;
+ mbufBufferPrivPtr pMBPriv;
+
+ if (pParent)
+ pScreen = pParent->drawable.pScreen;
+ else if (pChild)
+ pScreen = pChild->drawable.pScreen;
+ else
+ return; /* Hopeless */
+
+ pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
+
+ UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree);
+ if (pScreen->PostValidateTree)
+ (* pScreen->PostValidateTree)(pParent, pChild, kind);
+ REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, PostValidateTree);
+
+ /* Does backBuffer need to change? */
+ if (pMBPriv->rgnChanged)
+ {
+ RegionRec exposed;
+ RegionPtr pSubtractRgn, pUnionRgn;
+ Bool overlap;
+
+ pMBPriv->rgnChanged = FALSE;
+
+ pSubtractRgn = &pMBPriv->subtractRgn;
+ pUnionRgn = &pMBPriv->unionRgn;
+ REGION_VALIDATE(pScreen, pSubtractRgn, &overlap);
+#ifdef DEBUG
+ if (overlap)
+ FatalError("bufPostValidateTree: subtractRgn overlaps");
+#endif
+ REGION_VALIDATE(pScreen, pUnionRgn, &overlap);
+#ifdef DEBUG
+ if (overlap)
+ FatalError("bufPostValidateTree: unionRgn overlaps");
+#endif
+
+ /* Update backBuffer: subtract must come before union */
+ REGION_SUBTRACT(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer,
+ pSubtractRgn);
+ REGION_UNION(pScreen, &pMBPriv->backBuffer, &pMBPriv->backBuffer,
+ pUnionRgn);
+
+ /* Paint gained and lost backbuffer areas in select plane */
+ REGION_INIT(pScreen, &exposed, NullBox, 0);
+ REGION_SUBTRACT(pScreen, &exposed, pSubtractRgn, pUnionRgn);
+ (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
+ &exposed, FRONT_BUFFER);
+
+ REGION_SUBTRACT(pScreen, &exposed, pUnionRgn, pSubtractRgn);
+ (* pMBPriv->DrawSelectPlane)(pScreen, pMBPriv->selectPlane,
+ &exposed, BACK_BUFFER);
+
+ REGION_UNINIT(pScreen, &exposed);
+ REGION_EMPTY(pScreen, pSubtractRgn);
+ REGION_EMPTY(pScreen, pUnionRgn);
+ }
+}
+
+/* XXX - Knows region internals. */
+
+static Bool
+RegionsEqual(reg1, reg2)
+ RegionPtr reg1;
+ RegionPtr reg2;
+{
+ int i;
+ BoxPtr rects1, rects2;
+
+ if (reg1->extents.x1 != reg2->extents.x1) return FALSE;
+ if (reg1->extents.x2 != reg2->extents.x2) return FALSE;
+ if (reg1->extents.y1 != reg2->extents.y1) return FALSE;
+ if (reg1->extents.y2 != reg2->extents.y2) return FALSE;
+ if (REGION_NUM_RECTS(reg1) != REGION_NUM_RECTS(reg2)) return FALSE;
+
+ rects1 = REGION_RECTS(reg1);
+ rects2 = REGION_RECTS(reg2);
+ for (i = 0; i != REGION_NUM_RECTS(reg1); i++) {
+ if (rects1[i].x1 != rects2[i].x1) return FALSE;
+ if (rects1[i].x2 != rects2[i].x2) return FALSE;
+ if (rects1[i].y1 != rects2[i].y1) return FALSE;
+ if (rects1[i].y2 != rects2[i].y2) return FALSE;
+ }
+ return TRUE;
+}
+
+/*
+ * If the window is multibuffered and displaying the backbuffer,
+ * add the old clipList to the subtractRgn and add the new clipList
+ * to the unionRgn. PostValidateTree will use subtractRgn and unionRgn
+ * to update the backBuffer region and the selectPlane.
+ *
+ * Copy changes to the window structure into the buffers.
+ * Send ClobberNotify events.
+ */
+
+static void
+bufClipNotify(pWin, dx,dy)
+ WindowPtr pWin;
+ int dx,dy;
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
+ mbufWindowPtr pMBWindow;
+ int i;
+
+ UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify);
+ if (pScreen->ClipNotify)
+ (* pScreen->ClipNotify)(pWin, dx,dy);
+ REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClipNotify);
+
+ if (pMBWindow = MB_WINDOW_PRIV(pWin))
+ {
+ RegionPtr pOldClipList = (RegionPtr) pMBWindow->devPrivate.ptr;
+
+ if (! RegionsEqual(pOldClipList, &pWin->clipList))
+ {
+ if (pMBWindow->displayedMultibuffer == BACK_BUFFER)
+ {
+ pMBPriv->rgnChanged = TRUE;
+ REGION_APPEND(pScreen, &pMBPriv->subtractRgn, pOldClipList);
+ REGION_APPEND(pScreen, &pMBPriv->unionRgn, &pWin->clipList);
+ }
+
+ REGION_COPY(pScreen, pOldClipList,&pWin->clipList);
+ }
+
+ /* Update buffer x,y,w,h, and clipList */
+ for (i=0; i<pMBWindow->numMultibuffer; i++)
+ {
+ mbufBufferPtr pMBBuffer = pMBWindow->buffers + i;
+ if (pMBBuffer->clobber != pWin->visibility)
+ {
+ pMBBuffer->clobber = pWin->visibility;
+ MultibufferClobber(pMBBuffer);
+ }
+ UpdateBufferFromWindow(pMBBuffer->pDrawable, pWin);
+ }
+ }
+}
+
+/*
+ * Updates buffer's background fields when the window's changes.
+ * This is necessary because pScreen->PaintWindowBackground
+ * is used to paint the buffer.
+ *
+ * XXBS - Backingstore state will have be tracked too if it is supported.
+ */
+
+static Bool
+bufChangeWindowAttributes(pWin, mask)
+ WindowPtr pWin;
+ unsigned long mask;
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
+ mbufWindowPtr pMBWindow;
+ Bool ret;
+
+ UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes);
+ ret = (* pScreen->ChangeWindowAttributes)(pWin, mask);
+ REWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, ChangeWindowAttributes);
+
+ if (pMBWindow = MB_WINDOW_PRIV(pWin))
+ {
+ if (mask & (CWBackPixmap | CWBackPixel))
+ {
+ BufferPtr pBuffer;
+ int i;
+
+ for (i=0; i<pMBWindow->displayedMultibuffer; i++)
+ {
+ pBuffer = (BufferPtr) pMBWindow->buffers[i].pDrawable;
+ pBuffer->backgroundState = pWin->backgroundState;
+ pBuffer->background = pWin->background;
+ }
+ }
+ }
+ return ret;
+}
+
+/*
+ * Send exposures and clear the background for a buffer whenever
+ * its corresponding window is exposed, except when called by
+ * ClearToBackground.
+ */
+
+static void
+bufWindowExposures(pWin, prgn, other_exposed)
+ WindowPtr pWin;
+ register RegionPtr prgn, other_exposed;
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ mbufWindowPtr pMBWindow = MB_WINDOW_PRIV(pWin);
+ mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
+ RegionRec tmp_rgn;
+ int i;
+ Bool handleBuffers;
+
+ handleBuffers = (!pMBPriv->inClearToBackground) &&
+ (pWin->drawable.type == DRAWABLE_WINDOW) &&
+ pMBWindow && (prgn && !REGION_NIL(prgn));
+
+ /* miWindowExposures munges prgn and other_exposed. */
+ if (handleBuffers)
+ {
+ REGION_INIT(pScreen, &tmp_rgn, NullBox, 0);
+ REGION_COPY(pScreen, &tmp_rgn,prgn);
+ }
+
+ UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures);
+ (* pScreen->WindowExposures) (pWin, prgn, other_exposed);
+ REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, WindowExposures);
+
+ if (!handleBuffers)
+ return;
+
+ /*
+ * Send expose events to all clients. Paint the exposed region for all
+ * buffers except the displayed buffer since it is handled when the
+ * window is painted.
+ *
+ * XXBS - Will have to be re-written to handle BackingStore on buffers.
+ */
+
+ for (i=0; i<pMBWindow->numMultibuffer; i++)
+ {
+ mbufBufferPtr pMBBuffer;
+ BufferPtr pBuffer;
+
+ pMBBuffer = pMBWindow->buffers + i;
+ pBuffer = (BufferPtr) pMBBuffer->pDrawable;
+
+ if (i != pMBWindow->displayedMultibuffer)
+ (* pScreen->PaintWindowBackground)(pBuffer,&tmp_rgn,PW_BACKGROUND);
+ if ((pMBBuffer->otherEventMask | pMBBuffer->eventMask) & ExposureMask)
+ MultibufferExpose(pMBBuffer, &tmp_rgn);
+ }
+
+ REGION_UNINIT(pScreen, &tmp_rgn);
+}
+
+/*
+ * Set ``inClearToBackground'' so that WindowExposures does not attempt
+ * to send expose events or clear the background on the buffers.
+ */
+
+static void
+bufClearToBackground(pWin, x,y,w,h, sendExpose)
+ WindowPtr pWin;
+ int x,y, w,h;
+ Bool sendExpose;
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
+
+ pMBPriv->inClearToBackground = TRUE;
+
+ UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground);
+ (* pScreen->ClearToBackground)(pWin, x,y,w,h, sendExpose);
+ REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, ClearToBackground);
+
+ pMBPriv->inClearToBackground = FALSE;
+}
+
+/*
+ * Move bits in both buffers. It does this by calling pScreen->CopyWindow
+ * twice, once with the root window's devPrivate[frameWindowPrivateIndex]
+ * pointing to the frontbuffer pixmap and once with it pointed to the
+ * backbuffer pixmap. It does this if there are *any* existing multibuffered
+ * window... a possible optimization is to copy the backbuffer only if this
+ * window or its inferiors are multibuffered. May be faster, maybe not.
+ *
+ * XXX - Only works if your CopyWindow checks the root window's devPrivate
+ * to see which buffer to draw into. Works for cfbPaintWindow.
+ */
+
+/*ARGSUSED*/
+static void
+bufCopyWindow(pWin, ptOldOrg, prgnSrc)
+ WindowPtr pWin;
+ DDXPointRec ptOldOrg;
+ RegionPtr prgnSrc;
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ mbufBufferPrivPtr pMBPriv = MB_SCREEN_PRIV_BUFFER(pScreen);
+ WindowPtr pwinroot;
+ DevUnion save;
+
+ UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow);
+
+ pwinroot = WindowTable[pScreen->myNum];
+ save = pwinroot->devPrivates[frameWindowPrivateIndex];
+
+ /*
+ * Copy front buffer
+ */
+
+ pwinroot->devPrivates[frameWindowPrivateIndex] =
+ pMBPriv->frameBuffer[FRONT_BUFFER];
+ (* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
+
+ /*
+ * Copy back buffer
+ */
+
+ /* CopyWindow translates prgnSrc... translate it back for 2nd call. */
+ REGION_TRANSLATE(pScreen, prgnSrc,
+ ptOldOrg.x - pWin->drawable.x,
+ ptOldOrg.y - pWin->drawable.y);
+ pwinroot->devPrivates[frameWindowPrivateIndex] =
+ pMBPriv->frameBuffer[BACK_BUFFER];
+ (* pScreen->CopyWindow)(pWin, ptOldOrg, prgnSrc);
+
+ pwinroot->devPrivates[frameWindowPrivateIndex] = save;
+ REWRAP_SCREEN_FUNC(pScreen, pMBPriv, void, CopyWindow);
+}
diff --git a/Xext/mbufpx.c b/Xext/mbufpx.c
new file mode 100644
index 000000000..9474cc9aa
--- /dev/null
+++ b/Xext/mbufpx.c
@@ -0,0 +1,646 @@
+/************************************************************
+
+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.
+
+********************************************************/
+
+/* $Xorg: mbufpx.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <stdio.h>
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "opaque.h"
+#include "regionstr.h"
+#include "gcstruct.h"
+#include "inputstr.h"
+#include <sys/time.h>
+
+#define _MULTIBUF_SERVER_ /* don't want Xlib structures */
+#define _MULTIBUF_PIXMAP_
+#include "multibufst.h"
+
+
+static Bool NoopDDA_True() { return TRUE; }
+
+static Bool pixPositionWindow();
+static int pixCreateImageBuffers();
+static void pixDisplayImageBuffers();
+static void pixClearImageBufferArea();
+static void pixDeleteBufferDrawable();
+static void pixWrapScreenFuncs();
+static void pixResetProc();
+
+Bool
+pixMultibufferInit(pScreen, pMBScreen)
+ ScreenPtr pScreen;
+ mbufScreenPtr pMBScreen;
+{
+ int i, j, k;
+ xMbufBufferInfo *pInfo;
+ int nInfo;
+ DepthPtr pDepth;
+ mbufPixmapPrivPtr pMBPriv;
+
+ pMBScreen->CreateImageBuffers = pixCreateImageBuffers;
+ pMBScreen->DestroyImageBuffers = (void (*)())NoopDDA;
+ pMBScreen->DisplayImageBuffers = pixDisplayImageBuffers;
+ pMBScreen->ClearImageBufferArea = pixClearImageBufferArea;
+ pMBScreen->ChangeMBufferAttributes = NoopDDA_True;
+ pMBScreen->ChangeBufferAttributes = NoopDDA_True;
+ pMBScreen->DeleteBufferDrawable = pixDeleteBufferDrawable;
+ pMBScreen->WrapScreenFuncs = pixWrapScreenFuncs;
+ pMBScreen->ResetProc = pixResetProc;
+
+ /* Support every depth and visual combination that the screen does */
+
+ nInfo = 0;
+ for (i = 0; i < pScreen->numDepths; i++)
+ {
+ pDepth = &pScreen->allowedDepths[i];
+ nInfo += pDepth->numVids;
+ }
+
+ pInfo = (xMbufBufferInfo *) xalloc (nInfo * sizeof (xMbufBufferInfo));
+ if (!pInfo)
+ return FALSE;
+
+ k = 0;
+ for (i = 0; i < pScreen->numDepths; i++)
+ {
+ pDepth = &pScreen->allowedDepths[i];
+ for (j = 0; j < pDepth->numVids; j++)
+ {
+ pInfo[k].visualID = pDepth->vids[j];
+ pInfo[k].maxBuffers = 0;
+ pInfo[k].depth = pDepth->depth;
+ k++;
+ }
+ }
+
+ pMBScreen->nInfo = nInfo;
+ pMBScreen->pInfo = pInfo;
+
+ /*
+ * Setup the devPrivate to mbufScreenRec
+ */
+
+ pMBPriv = (mbufPixmapPrivPtr) xalloc(sizeof(* pMBPriv));
+ if (!pMBPriv)
+ {
+ xfree(pInfo);
+ return (FALSE);
+ }
+ pMBScreen->devPrivate.ptr = (pointer) pMBPriv;
+ pMBPriv->PositionWindow = NULL;
+ pMBPriv->funcsWrapped = 0;
+
+ return TRUE;
+}
+
+/*ARGSUSED*/
+static int
+pixCreateImageBuffers (pWin, nbuf, ids, action, hint)
+ WindowPtr pWin;
+ int nbuf;
+ XID *ids;
+ int action;
+ int hint;
+{
+ mbufWindowPtr pMBWindow;
+ mbufBufferPtr pMBBuffer;
+ ScreenPtr pScreen;
+ int width, height, depth;
+ int i;
+
+ pMBWindow = MB_WINDOW_PRIV(pWin);
+
+ width = pWin->drawable.width;
+ height = pWin->drawable.height;
+ depth = pWin->drawable.depth;
+ pScreen = pWin->drawable.pScreen;
+
+ for (i = 0; i < nbuf; i++)
+ {
+ pMBBuffer = &pMBWindow->buffers[i];
+ pMBBuffer->pDrawable = (DrawablePtr)
+ (*pScreen->CreatePixmap) (pScreen, width, height, depth);
+ if (!pMBBuffer->pDrawable)
+ break;
+
+ if (!AddResource (ids[i], MultibufferDrawableResType,
+ (pointer) pMBBuffer->pDrawable))
+ {
+ (*pScreen->DestroyPixmap) ((PixmapPtr) pMBBuffer->pDrawable);
+ break;
+ }
+ pMBBuffer->pDrawable->id = ids[i];
+
+ /*
+ * In the description of the CreateImageBuffers request:
+ * "If the window is mapped, or if these image buffers have
+ * backing store, their contents will be tiled with the window
+ * background, and zero or more expose events will be generated
+ * for each of these buffers."
+ */
+
+ (* MB_SCREEN_PRIV(pScreen)->ClearImageBufferArea)
+ (pMBBuffer, 0,0, 0,0, TRUE);
+ }
+
+ return i;
+}
+
+/*
+ * set up the gc to clear the pixmaps;
+ */
+static Bool
+SetupBackgroundPainter (pWin, pGC)
+ WindowPtr pWin;
+ GCPtr pGC;
+{
+ XID gcvalues[4];
+ int ts_x_origin, ts_y_origin;
+ PixUnion background;
+ int backgroundState;
+ Mask gcmask;
+
+ /*
+ * First take care of any ParentRelative stuff by altering the
+ * tile/stipple origin to match the coordinates of the upper-left
+ * corner of the first ancestor without a ParentRelative background.
+ * This coordinate is, of course, negative.
+ */
+
+ ts_x_origin = ts_y_origin = 0;
+ while (pWin->backgroundState == ParentRelative) {
+ ts_x_origin -= pWin->origin.x;
+ ts_y_origin -= pWin->origin.y;
+ pWin = pWin->parent;
+ }
+ backgroundState = pWin->backgroundState;
+ background = pWin->background;
+
+ switch (backgroundState)
+ {
+ case BackgroundPixel:
+ gcvalues[0] = (XID) background.pixel;
+ gcvalues[1] = FillSolid;
+ gcmask = GCForeground|GCFillStyle;
+ break;
+
+ case BackgroundPixmap:
+ gcvalues[0] = FillTiled;
+ gcvalues[1] = (XID) background.pixmap;
+ gcvalues[2] = ts_x_origin;
+ gcvalues[3] = ts_y_origin;
+ gcmask = GCFillStyle|GCTile|GCTileStipXOrigin|GCTileStipYOrigin;
+ break;
+
+ default:
+ return FALSE;
+ }
+ DoChangeGC(pGC, gcmask, gcvalues, TRUE);
+ return TRUE;
+}
+
+static void
+MultibufferPaintBackgroundRectangles(pWin, pDrawable, nrects, pRects)
+ WindowPtr pWin;
+ DrawablePtr pDrawable;
+ int nrects;
+ xRectangle *pRects;
+{
+ GCPtr pGC;
+
+ pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen);
+ if (SetupBackgroundPainter(pWin, pGC))
+ {
+ ValidateGC(pDrawable, pGC);
+ (*pGC->ops->PolyFillRect) (pDrawable, pGC, nrects, pRects);
+ }
+ FreeScratchGC(pGC);
+}
+
+static void
+MultibufferPaintBackgroundRegion(pWin, pDrawable, pRegion)
+ WindowPtr pWin;
+ DrawablePtr pDrawable;
+ RegionPtr pRegion;
+{
+ xRectangle *pRects;
+ int nrects = REGION_NUM_RECTS(pRegion);
+ BoxPtr pbox = REGION_RECTS(pRegion);
+
+ pRects = (xRectangle *)ALLOCATE_LOCAL(nrects * sizeof(xRectangle));
+ if (pRects)
+ {
+ int i;
+ for (i = 0; i < nrects; i++)
+ {
+ pRects[i].x = pbox->x1;
+ pRects[i].y = pbox->y1;
+ pRects[i].width = pbox->x2 - pbox->x1;
+ pRects[i].height = pbox->y2 - pbox->y1;
+ }
+ MultibufferPaintBackgroundRectangles(pWin, pDrawable, nrects, pRects);
+ DEALLOCATE_LOCAL(pRects);
+ }
+}
+
+static void
+pixDisplayImageBuffers(pScreen, ppMBWindow, ppMBBuffer, nbuf)
+ mbufBufferPtr *ppMBBuffer;
+ mbufWindowPtr *ppMBWindow;
+ int nbuf;
+{
+ GCPtr pGC = NULL;
+ PixmapPtr pPrevPixmap, pNewPixmap;
+ WindowPtr pWin;
+ RegionPtr pExposed;
+ int i;
+ mbufBufferPtr pPrevMBBuffer;
+ XID bool;
+ xRectangle r;
+
+ UpdateCurrentTime ();
+ for (i = 0; i < nbuf; i++)
+ {
+ pWin = ppMBWindow[i]->pWindow;
+
+ /* Time to get a different scratch GC? */
+
+ if (!pGC
+ || pGC->depth != pWin->drawable.depth
+ || pGC->pScreen != pWin->drawable.pScreen)
+ {
+ if (pGC) FreeScratchGC(pGC);
+ pGC = GetScratchGC (pWin->drawable.depth, pWin->drawable.pScreen);
+ }
+ pPrevMBBuffer = MB_DISPLAYED_BUFFER(ppMBWindow[i]);
+ pPrevPixmap = (PixmapPtr) pPrevMBBuffer->pDrawable;
+ pNewPixmap = (PixmapPtr) ppMBBuffer[i]->pDrawable;
+
+ if (pPrevPixmap == pNewPixmap)
+ {
+ /* "If a specified buffer is already displayed, any delays and
+ * update action will still be performed for that buffer."
+ *
+ * We special-case this because applications do occasionally
+ * request a redundant DisplayImageBuffers, and we can save
+ * strokes by recognizing that the only update action that will
+ * change the buffer contents in this case is Background.
+ */
+ if (ppMBWindow[i]->updateAction == MultibufferUpdateActionBackground)
+ {
+ r.x = r.y = 0;
+ r.width = pWin->drawable.width;
+ r.height = pWin->drawable.height;
+ MultibufferPaintBackgroundRectangles(pWin, (DrawablePtr)pWin,
+ 1, &r);
+ }
+ }
+ else /* different buffer is being displayed */
+ {
+ /* perform update action */
+
+ switch (ppMBWindow[i]->updateAction)
+ {
+ case MultibufferUpdateActionUndefined:
+ break;
+
+ case MultibufferUpdateActionBackground:
+
+ r.x = r.y = 0;
+ r.width = pPrevPixmap->drawable.width;
+ r.height = pPrevPixmap->drawable.height;
+ MultibufferPaintBackgroundRectangles(pWin,
+ (DrawablePtr)pPrevPixmap,
+ 1, &r);
+ break;
+
+ case MultibufferUpdateActionUntouched:
+
+ /* copy the window to the pixmap that represents the
+ * currently displayed buffer
+ */
+
+ if (pPrevMBBuffer->eventMask & ExposureMask)
+ {
+ bool = TRUE;
+ DoChangeGC (pGC, GCGraphicsExposures, &bool, FALSE);
+ }
+ ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
+ pExposed = (*pGC->ops->CopyArea)((DrawablePtr) pWin,
+ (DrawablePtr) pPrevPixmap,
+ pGC,
+ 0, 0,
+ pWin->drawable.width,
+ pWin->drawable.height,
+ 0, 0);
+
+ /* if we couldn't copy the whole window to the buffer,
+ * send expose events (if any client wants them)
+ */
+
+ if (pPrevMBBuffer->eventMask & ExposureMask)
+ { /* some client wants expose events */
+ if (pExposed)
+ {
+ RegionPtr pWinSize;
+ extern RegionPtr CreateUnclippedWinSize();
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+ pWinSize = CreateUnclippedWinSize (pWin);
+ /*
+ * pExposed is window-relative, but at this point
+ * pWinSize is screen-relative. Make pWinSize be
+ * window-relative so that region ops involving
+ * pExposed and pWinSize behave sensibly.
+ */
+ REGION_TRANSLATE(pScreen, pWinSize,
+ -pWin->drawable.x,
+ -pWin->drawable.y);
+ REGION_INTERSECT(pScreen, pExposed, pExposed, pWinSize);
+ REGION_DESTROY(pScreen, pWinSize);
+ MultibufferExpose (pPrevMBBuffer, pExposed);
+ REGION_DESTROY(pScreen, pExposed);
+ }
+ bool = FALSE;
+ DoChangeGC (pGC, GCGraphicsExposures, &bool, FALSE);
+ } /* end some client wants expose events */
+
+ break; /* end case MultibufferUpdateActionUntouched */
+
+ case MultibufferUpdateActionCopied:
+
+ ValidateGC ((DrawablePtr)pPrevPixmap, pGC);
+ (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap,
+ (DrawablePtr)pPrevPixmap, pGC,
+ 0, 0, pWin->drawable.width,
+ pWin->drawable.height, 0, 0);
+ break;
+
+ } /* end switch on update action */
+
+ /* display the new buffer */
+
+ ValidateGC ((DrawablePtr)pWin, pGC);
+ (*pGC->ops->CopyArea) ((DrawablePtr)pNewPixmap, (DrawablePtr)pWin,
+ pGC, 0, 0,
+ pWin->drawable.width, pWin->drawable.height,
+ 0, 0);
+ }
+
+ ppMBWindow[i]->lastUpdate = currentTime;
+ }
+
+ if (pGC) FreeScratchGC (pGC);
+ return;
+}
+
+/*
+ * resize the buffers when the window is resized
+ */
+
+static Bool
+pixPositionWindow (pWin, x, y)
+ WindowPtr pWin;
+ int x, y;
+{
+ ScreenPtr pScreen;
+ mbufPixmapPrivPtr pMBPriv;
+ mbufWindowPtr pMBWindow;
+ mbufBufferPtr pMBBuffer;
+ int width, height;
+ int i;
+ int dx, dy, dw, dh;
+ int sourcex, sourcey;
+ int destx, desty;
+ PixmapPtr pPixmap;
+ GCPtr pGC;
+ int savewidth, saveheight;
+ Bool clear;
+ RegionRec exposedRegion;
+ Bool ret;
+
+ pScreen = pWin->drawable.pScreen;
+ pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen);
+
+ UNWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, PositionWindow);
+ ret = (* pScreen->PositionWindow) (pWin, x, y);
+ REWRAP_SCREEN_FUNC(pScreen, pMBPriv, Bool, PositionWindow);
+
+ if (!(pMBWindow = MB_WINDOW_PRIV(pWin)))
+ return ret;
+
+ /* if new size is same as old, we're done */
+
+ if (pMBWindow->width == pWin->drawable.width &&
+ pMBWindow->height == pWin->drawable.height)
+ return ret;
+
+ width = pWin->drawable.width;
+ height = pWin->drawable.height;
+ dx = pWin->drawable.x - pMBWindow->x;
+ dy = pWin->drawable.x - pMBWindow->y;
+ dw = width - pMBWindow->width;
+ dh = height - pMBWindow->height;
+ GravityTranslate (0, 0, -dx, -dy, dw, dh,
+ pWin->bitGravity, &destx, &desty);
+
+ /* if the window grew, remember to paint the window background,
+ * and maybe send expose events, for the new areas of the buffers
+ */
+
+ clear = pMBWindow->width < width || pMBWindow->height < height ||
+ pWin->bitGravity == ForgetGravity;
+
+ sourcex = 0;
+ sourcey = 0;
+ savewidth = pMBWindow->width;
+ saveheight = pMBWindow->height;
+ /* clip rectangle to source and destination */
+ if (destx < 0)
+ {
+ savewidth += destx;
+ sourcex -= destx;
+ destx = 0;
+ }
+ if (destx + savewidth > width)
+ savewidth = width - destx;
+ if (desty < 0)
+ {
+ saveheight += desty;
+ sourcey -= desty;
+ desty = 0;
+ }
+ if (desty + saveheight > height)
+ saveheight = height - desty;
+
+ pMBWindow->width = width;
+ pMBWindow->height = height;
+ pMBWindow->x = pWin->drawable.x;
+ pMBWindow->y = pWin->drawable.y;
+
+ if (clear)
+ {
+ BoxRec box;
+
+ box.x1 = box.y1 = 0;
+ box.x2 = width;
+ box.y2 = height;
+ REGION_INIT(pScreen, &exposedRegion, &box, 1);
+ if (pWin->bitGravity != ForgetGravity)
+ {
+ RegionRec preservedRegion;
+ box.x1 = destx;
+ box.y1 = desty;
+ box.x2 = destx + savewidth;
+ box.y2 = desty + saveheight;
+ REGION_INIT(pScreen, &preservedRegion, &box, 1);
+ REGION_SUBTRACT(pScreen, &exposedRegion, &exposedRegion, &preservedRegion);
+ REGION_UNINIT(pScreen, &preservedRegion);
+ }
+
+ } /* end if (clear) */
+
+ pGC = GetScratchGC (pWin->drawable.depth, pScreen);
+
+ /* create buffers with new window size */
+
+ for (i = 0; i < pMBWindow->numMultibuffer; i++)
+ {
+ pMBBuffer = &pMBWindow->buffers[i];
+ pPixmap = (*pScreen->CreatePixmap) (pScreen, width, height, pWin->drawable.depth);
+ if (!pPixmap)
+ {
+ (* MB_SCREEN_PRIV(pScreen)->DestroyImageBuffers)(pWin);
+ break;
+ }
+ if (clear)
+ {
+ MultibufferPaintBackgroundRegion(pWin, (DrawablePtr)pPixmap, &exposedRegion);
+ MultibufferExpose(pMBBuffer, &exposedRegion);
+ }
+ if (pWin->bitGravity != ForgetGravity)
+ {
+ ValidateGC ((DrawablePtr)pPixmap, pGC);
+ (*pGC->ops->CopyArea) (pMBBuffer->pDrawable, (DrawablePtr)pPixmap,
+ pGC,
+ sourcex, sourcey, savewidth, saveheight,
+ destx, desty);
+ }
+ pPixmap->drawable.id = pMBBuffer->pDrawable->id;
+ (*pScreen->DestroyPixmap) ((PixmapPtr) pMBBuffer->pDrawable);
+ pMBBuffer->pDrawable = (DrawablePtr) pPixmap;
+ if (i != pMBWindow->displayedMultibuffer)
+ {
+ ChangeResourceValue (pPixmap->drawable.id,
+ MultibufferDrawableResType,
+ (pointer) pPixmap);
+ }
+ }
+ FreeScratchGC (pGC);
+ if (clear)
+ REGION_UNINIT(pScreen, &exposedRegion);
+ return TRUE;
+}
+
+static void
+pixWrapScreenFuncs(pScreen)
+ ScreenPtr pScreen;
+{
+ mbufPixmapPrivPtr pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen);
+ WRAP_SCREEN_FUNC(pScreen, pMBPriv, PositionWindow, pixPositionWindow);
+}
+
+static void
+pixResetProc(pScreen)
+ ScreenPtr pScreen;
+{
+ mbufScreenPtr pMBScreen = MB_SCREEN_PRIV(pScreen);
+ mbufPixmapPrivPtr pMBPriv = MB_SCREEN_PRIV_PIXMAP(pScreen);
+
+ xfree(pMBScreen->pInfo);
+ xfree(pMBPriv);
+}
+
+static void
+pixClearImageBufferArea(pMBBuffer, x,y, width,height, exposures)
+ mbufBufferPtr pMBBuffer;
+ short x, y;
+ unsigned short width, height;
+ Bool exposures;
+{
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ BoxRec box;
+ RegionRec region;
+ int w_width, w_height;
+ DrawablePtr pDrawable;
+
+ pWin = pMBBuffer->pMBWindow->pWindow;
+ pScreen = pWin->drawable.pScreen;
+
+ w_width = pWin->drawable.width;
+ w_height = pWin->drawable.height;
+
+ box.x1 = x;
+ box.y1 = y;
+ box.x2 = width ? (box.x1 + width) : w_width;
+ box.y2 = height ? (box.y1 + height) : w_height;
+
+ if (box.x1 < 0) box.x1 = 0;
+ if (box.y1 < 0) box.y1 = 0;
+ if (box.x2 > w_width) box.x2 = w_width;
+ if (box.y2 > w_height) box.y2 = w_height;
+
+ REGION_INIT(pScreen, &region, &box, 1);
+
+ if (pMBBuffer->number == pMBBuffer->pMBWindow->displayedMultibuffer)
+ pDrawable = (DrawablePtr) pWin;
+ else
+ pDrawable = pMBBuffer->pDrawable;
+
+ MultibufferPaintBackgroundRegion(pWin, pDrawable, &region);
+
+ if (exposures)
+ MultibufferExpose(pMBBuffer, &region);
+
+ REGION_UNINIT(pScreen, &region);
+}
+
+static void
+pixDeleteBufferDrawable(pDrawable)
+ DrawablePtr pDrawable;
+{
+ (* pDrawable->pScreen->DestroyPixmap)((PixmapPtr) pDrawable);
+}
diff --git a/Xext/mitmisc.c b/Xext/mitmisc.c
new file mode 100644
index 000000000..63e496209
--- /dev/null
+++ b/Xext/mitmisc.c
@@ -0,0 +1,153 @@
+/************************************************************
+
+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.
+
+********************************************************/
+
+/* RANDOM CRUFT! THIS HAS NO OFFICIAL X CONSORTIUM OR X PROJECT TEAM BLESSING */
+
+/* $Xorg: mitmisc.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */
+
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#define _MITMISC_SERVER_
+#include "mitmiscstr.h"
+
+extern Bool permitOldBugs;
+
+static unsigned char MITReqCode;
+static int ProcMITDispatch(), SProcMITDispatch();
+static void MITResetProc();
+
+void
+MITMiscExtensionInit()
+{
+ ExtensionEntry *extEntry, *AddExtension();
+
+ if (extEntry = AddExtension(MITMISCNAME, 0, 0,
+ ProcMITDispatch, SProcMITDispatch,
+ MITResetProc, StandardMinorOpcode))
+ MITReqCode = (unsigned char)extEntry->base;
+}
+
+/*ARGSUSED*/
+static void
+MITResetProc (extEntry)
+ExtensionEntry *extEntry;
+{
+}
+
+static int
+ProcMITSetBugMode(client)
+ register ClientPtr client;
+{
+ REQUEST(xMITSetBugModeReq);
+
+ REQUEST_SIZE_MATCH(xMITSetBugModeReq);
+ if ((stuff->onOff != xTrue) && (stuff->onOff != xFalse))
+ {
+ client->errorValue = stuff->onOff;
+ return BadValue;
+ }
+ permitOldBugs = stuff->onOff;
+ return(client->noClientException);
+}
+
+static int
+ProcMITGetBugMode(client)
+ register ClientPtr client;
+{
+ REQUEST(xMITGetBugModeReq);
+ xMITGetBugModeReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xMITGetBugModeReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.onOff = permitOldBugs;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient(client, sizeof(xMITGetBugModeReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcMITDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_MITSetBugMode:
+ return ProcMITSetBugMode(client);
+ case X_MITGetBugMode:
+ return ProcMITGetBugMode(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcMITSetBugMode(client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xMITSetBugModeReq);
+
+ swaps(&stuff->length, n);
+ return ProcMITSetBugMode(client);
+}
+
+static int
+SProcMITGetBugMode(client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xMITGetBugModeReq);
+
+ swaps(&stuff->length, n);
+ return ProcMITGetBugMode(client);
+}
+
+static int
+SProcMITDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_MITSetBugMode:
+ return SProcMITSetBugMode(client);
+ case X_MITGetBugMode:
+ return SProcMITGetBugMode(client);
+ default:
+ return BadRequest;
+ }
+}
diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c
new file mode 100644
index 000000000..2d3eb7c42
--- /dev/null
+++ b/Xext/panoramiX.c
@@ -0,0 +1,780 @@
+/* $Xorg: panoramiX.c,v 1.5 2000/08/17 19:47:57 cpqbld Exp $ */
+/*****************************************************************
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+******************************************************************/
+
+#define NEED_REPLIES
+#include <stdio.h>
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "cursor.h"
+#include "cursorstr.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "gc.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#include "window.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#if 0
+#include <sys/workstation.h>
+#include <X11/Xserver/ws.h>
+#endif
+#include "panoramiX.h"
+#include "panoramiXproto.h"
+
+static unsigned char PanoramiXReqCode = 0;
+/*
+ * PanoramiX data declarations
+ */
+
+int PanoramiXPixWidth;
+int PanoramiXPixHeight;
+int PanoramiXNumScreens;
+
+PanoramiXData *panoramiXdataPtr;
+PanoramiXWindow *PanoramiXWinRoot;
+PanoramiXGC *PanoramiXGCRoot;
+PanoramiXCmap *PanoramiXCmapRoot;
+PanoramiXPmap *PanoramiXPmapRoot;
+
+PanoramiXEdge panoramiXEdgePtr[MAXSCREENS];
+RegionRec PanoramiXScreenRegion[MAXSCREENS];
+PanoramiXCDT PanoramiXColorDepthTable[MAXSCREENS];
+PanoramiXDepth PanoramiXLargestScreenDepth;
+
+int (* SavedProcVector[256]) ();
+ScreenInfo *GlobalScrInfo;
+
+static int panoramiXGeneration;
+static int ProcPanoramiXDispatch();
+/*
+ * Function prototypes
+ */
+
+static void locate_neighbors(int);
+static void PanoramiXResetProc(ExtensionEntry*);
+
+/*
+ * External references for data variables
+ */
+
+extern int SProcPanoramiXDispatch();
+extern Bool noPanoramiXExtension;
+extern Bool PanoramiXVisibilityNotifySent;
+extern WindowPtr *WindowTable;
+#if 0
+extern ScreenArgsRec screenArgs[MAXSCREENS];
+#endif
+extern int defaultBackingStore;
+extern char *ConnectionInfo;
+extern int connBlockScreenStart;
+extern int (* ProcVector[256]) ();
+
+/*
+ * Server dispatcher function replacements
+ */
+
+int PanoramiXCreateWindow(), PanoramiXChangeWindowAttributes();
+int PanoramiXDestroyWindow(), PanoramiXDestroySubwindows();
+int PanoramiXChangeSaveSet(), PanoramiXReparentWindow();
+int PanoramiXMapWindow(), PanoramiXMapSubwindows();
+int PanoramiXUnmapWindow(), PanoramiXUnmapSubwindows();
+int PanoramiXConfigureWindow(), PanoramiXCirculateWindow();
+int PanoramiXGetGeometry(), PanoramiXChangeProperty();
+int PanoramiXDeleteProperty(), PanoramiXSendEvent();
+int PanoramiXCreatePixmap(), PanoramiXFreePixmap();
+int PanoramiXCreateGC(), PanoramiXChangeGC();
+int PanoramiXCopyGC();
+int PanoramiXSetDashes(), PanoramiXSetClipRectangles();
+int PanoramiXFreeGC(), PanoramiXClearToBackground();
+int PanoramiXCopyArea(), PanoramiXCopyPlane();
+int PanoramiXPolyPoint(), PanoramiXPolyLine();
+int PanoramiXPolySegment(), PanoramiXPolyRectangle();
+int PanoramiXPolyArc(), PanoramiXFillPoly();
+int PanoramiXPolyFillArc(), PanoramiXPolyFillRectangle();
+int PanoramiXPutImage(), PanoramiXGetImage();
+int PanoramiXPolyText8(), PanoramiXPolyText16();
+int PanoramiXImageText8(), PanoramiXImageText16();
+int PanoramiXCreateColormap(), PanoramiXFreeColormap();
+int PanoramiXInstallColormap(), PanoramiXUninstallColormap();
+int PanoramiXAllocColor(), PanoramiXAllocNamedColor();
+int PanoramiXAllocColorCells();
+int PanoramiXFreeColors(), PanoramiXStoreColors();
+
+/*
+ * PanoramiXExtensionInit():
+ * Called from InitExtensions in main().
+ * Register PanoramiXeen Extension
+ * Initialize global variables.
+ */
+
+void PanoramiXExtensionInit(int argc, char *argv[])
+{
+ int i, j, PhyScrNum, ArgScrNum;
+ Bool success = FALSE;
+ ExtensionEntry *extEntry, *AddExtension();
+ PanoramiXData *panoramiXtempPtr;
+ ScreenPtr pScreen;
+
+ if (!noPanoramiXExtension)
+ {
+ GlobalScrInfo = &screenInfo; /* For debug visibility */
+ PanoramiXNumScreens = screenInfo.numScreens;
+ if (PanoramiXNumScreens == 1) { /* Only 1 screen */
+ noPanoramiXExtension = TRUE;
+ return;
+ }
+
+ while (panoramiXGeneration != serverGeneration) {
+ extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0,
+ ProcPanoramiXDispatch,
+ SProcPanoramiXDispatch, PanoramiXResetProc,
+ StandardMinorOpcode);
+ if (!extEntry) {
+ ErrorF("PanoramiXExtensionInit(): failed to AddExtension\n");
+ break;
+ }
+ PanoramiXReqCode = (unsigned char)extEntry->base;
+
+ /*
+ * First make sure all the basic allocations succeed. If not,
+ * run in non-PanoramiXeen mode.
+ */
+
+ panoramiXdataPtr = (PanoramiXData *) Xcalloc(PanoramiXNumScreens * sizeof(PanoramiXData));
+ PanoramiXWinRoot = (PanoramiXWindow *) Xcalloc(sizeof(PanoramiXWindow));
+ PanoramiXGCRoot = (PanoramiXGC *) Xcalloc(sizeof(PanoramiXGC));
+ PanoramiXCmapRoot = (PanoramiXCmap *) Xcalloc(sizeof(PanoramiXCmap));
+ PanoramiXPmapRoot = (PanoramiXPmap *) Xcalloc(sizeof(PanoramiXPmap));
+ BREAK_IF(!(panoramiXdataPtr && PanoramiXWinRoot && PanoramiXGCRoot &&
+ PanoramiXCmapRoot && PanoramiXPmapRoot));
+
+ panoramiXGeneration = serverGeneration;
+ success = TRUE;
+ }
+
+ if (!success) {
+ noPanoramiXExtension = TRUE;
+ ErrorF("%s Extension failed to initialize\n", PANORAMIX_PROTOCOL_NAME);
+ return;
+ }
+
+ /* Set up a default configuration base on horizontal ordering */
+ for (i = PanoramiXNumScreens -1; i >= 0 ; i--) {
+ panoramiXdataPtr[i].above = panoramiXdataPtr[i].below = -1;
+ panoramiXdataPtr[i].left = panoramiXdataPtr[i].right = -1;
+ panoramiXEdgePtr[i].no_edges = TRUE;
+ }
+ for (i = PanoramiXNumScreens - 1; i >= 0; i--) {
+ panoramiXdataPtr[i].left = i - 1;
+ panoramiXdataPtr[i].right = i + 1;
+ }
+ panoramiXdataPtr[PanoramiXNumScreens - 1].right = -1;
+
+ /*
+ * Position the screens relative to each other based on
+ * command line options.
+ */
+
+#if 0
+ for (PhyScrNum = PanoramiXNumScreens - 1; PhyScrNum >= 0; PhyScrNum--) {
+ if (wsRemapPhysToLogScreens)
+ i = wsPhysToLogScreens[PhyScrNum];
+ else
+ i = PhyScrNum;
+ if (i < 0)
+ continue;
+ panoramiXdataPtr[i].width = (screenInfo.screens[i])->width;
+ panoramiXdataPtr[i].height = (screenInfo.screens[i])->height;
+ if (screenArgs[i].flags & ARG_EDGE_L) {
+ ArgScrNum = screenArgs[PhyScrNum].edge_left;
+ if (ArgScrNum < 0)
+ j = -1;
+ else {
+ if (wsRemapPhysToLogScreens)
+ j = wsPhysToLogScreens[ArgScrNum];
+ else
+ j = ArgScrNum;
+ }
+ panoramiXdataPtr[i].left = j;
+ panoramiXEdgePtr[i].no_edges = FALSE;
+ if ( j >= 0)
+ panoramiXdataPtr[j].right = i;
+ else {
+ if ( i >= 1 )
+ panoramiXdataPtr[i - 1].right = -1;
+ }
+ }
+ if (screenArgs[i].flags & ARG_EDGE_R) {
+ ArgScrNum = screenArgs[PhyScrNum].edge_right;
+ if (ArgScrNum < 0)
+ j = -1;
+ else {
+ if (wsRemapPhysToLogScreens)
+ j = wsPhysToLogScreens[ArgScrNum];
+ else
+ j = ArgScrNum;
+ }
+ panoramiXdataPtr[i].right = j;
+ panoramiXEdgePtr[i].no_edges = FALSE;
+ if ( j >= 0)
+ panoramiXdataPtr[j].left = i;
+ }
+ if (screenArgs[i].flags & ARG_EDGE_T) {
+ ArgScrNum = screenArgs[PhyScrNum].edge_top;
+ if (ArgScrNum < 0)
+ j = -1;
+ else {
+ if (wsRemapPhysToLogScreens)
+ j = wsPhysToLogScreens[ArgScrNum];
+ else
+ j = ArgScrNum;
+ }
+ panoramiXdataPtr[i].above = j;
+ panoramiXEdgePtr[i].no_edges = FALSE;
+ if ( j >= 0)
+ panoramiXdataPtr[j].below = i;
+ }
+ if (screenArgs[i].flags & ARG_EDGE_B) {
+ ArgScrNum = screenArgs[PhyScrNum].edge_bottom;
+ if (ArgScrNum < 0)
+ j = -1;
+ else {
+ if (wsRemapPhysToLogScreens)
+ j = wsPhysToLogScreens[ArgScrNum];
+ else
+ j = ArgScrNum;
+ }
+ panoramiXdataPtr[i].below = j;
+ panoramiXEdgePtr[i].no_edges = FALSE;
+ if ( j >= 0)
+ panoramiXdataPtr[j].above = i;
+ }
+ }
+#else
+ for (PhyScrNum = PanoramiXNumScreens - 1; PhyScrNum >= 0; PhyScrNum--) {
+ i = PhyScrNum;
+ if (i < 0)
+ continue;
+ panoramiXdataPtr[i].width = (screenInfo.screens[i])->width;
+ panoramiXdataPtr[i].height = (screenInfo.screens[i])->height;
+ }
+#endif
+
+ /*
+ * Find the upper-left screen and then locate all the others
+ */
+ panoramiXtempPtr = panoramiXdataPtr;
+ for (i = PanoramiXNumScreens; i; i--, panoramiXtempPtr++)
+ if (panoramiXtempPtr->above == -1 && panoramiXtempPtr->left == -1)
+ break;
+ locate_neighbors(PanoramiXNumScreens - i);
+
+ /*
+ * Put our processes into the ProcVector
+ */
+
+ for (i = 256; i--; )
+ SavedProcVector[i] = ProcVector[i];
+
+ ProcVector[X_CreateWindow] = PanoramiXCreateWindow;
+ ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes;
+ ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow;
+ ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows;
+ ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet;
+ ProcVector[X_ReparentWindow] = PanoramiXReparentWindow;
+ ProcVector[X_MapWindow] = PanoramiXMapWindow;
+ ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows;
+ ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow;
+ ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows;
+ ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow;
+ ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow;
+ ProcVector[X_GetGeometry] = PanoramiXGetGeometry;
+ ProcVector[X_ChangeProperty] = PanoramiXChangeProperty;
+ ProcVector[X_DeleteProperty] = PanoramiXDeleteProperty;
+ ProcVector[X_SendEvent] = PanoramiXSendEvent;
+ ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap;
+ ProcVector[X_FreePixmap] = PanoramiXFreePixmap;
+ ProcVector[X_CreateGC] = PanoramiXCreateGC;
+ ProcVector[X_ChangeGC] = PanoramiXChangeGC;
+ ProcVector[X_CopyGC] = PanoramiXCopyGC;
+ ProcVector[X_SetDashes] = PanoramiXSetDashes;
+ ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles;
+ ProcVector[X_FreeGC] = PanoramiXFreeGC;
+ ProcVector[X_ClearArea] = PanoramiXClearToBackground;
+ ProcVector[X_CopyArea] = PanoramiXCopyArea;;
+ ProcVector[X_CopyPlane] = PanoramiXCopyPlane;;
+ ProcVector[X_PolyPoint] = PanoramiXPolyPoint;
+ ProcVector[X_PolyLine] = PanoramiXPolyLine;
+ ProcVector[X_PolySegment] = PanoramiXPolySegment;
+ ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle;
+ ProcVector[X_PolyArc] = PanoramiXPolyArc;
+ ProcVector[X_FillPoly] = PanoramiXFillPoly;
+ ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle;
+ ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc;
+ ProcVector[X_PutImage] = PanoramiXPutImage;
+ ProcVector[X_GetImage] = PanoramiXGetImage;
+ ProcVector[X_PolyText8] = PanoramiXPolyText8;
+ ProcVector[X_PolyText16] = PanoramiXPolyText16;
+ ProcVector[X_ImageText8] = PanoramiXImageText8;
+ ProcVector[X_ImageText16] = PanoramiXImageText16;
+ ProcVector[X_CreateColormap] = PanoramiXCreateColormap;
+ ProcVector[X_FreeColormap] = PanoramiXFreeColormap;
+ ProcVector[X_InstallColormap] = PanoramiXInstallColormap;
+ ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap;
+ ProcVector[X_AllocColor] = PanoramiXAllocColor;
+ ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor;
+ ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells;
+ ProcVector[X_FreeColors] = PanoramiXFreeColors;
+ ProcVector[X_StoreColors] = PanoramiXStoreColors;
+
+ }
+ else
+ return;
+}
+extern
+Bool PanoramiXCreateConnectionBlock(void)
+{
+ int i;
+ int old_width, old_height;
+ int width_mult, height_mult;
+ xWindowRoot *root;
+ xConnSetup *setup;
+
+ /*
+ * Do normal CreateConnectionBlock but faking it for only one screen
+ */
+
+ if (!CreateConnectionBlock()) {
+ return FALSE;
+ }
+
+ /*
+ * OK, change some dimensions so it looks as if it were one big screen
+ */
+
+ setup = (xConnSetup *) ConnectionInfo;
+ setup->numRoots = 1;
+ root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart);
+
+ old_width = root->pixWidth;
+ old_height = root->pixHeight;
+ for (i = PanoramiXNumScreens - 1; i >= 0; i--) {
+ if (panoramiXdataPtr[i].right == -1 )
+ root->pixWidth = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width;
+ if (panoramiXdataPtr[i].below == -1)
+ root->pixHeight = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height;
+ }
+ PanoramiXPixWidth = root->pixWidth;
+ PanoramiXPixHeight = root->pixHeight;
+ width_mult = root->pixWidth / old_width;
+ height_mult = root->pixHeight / old_height;
+ root->mmWidth *= width_mult;
+ root->mmHeight *= height_mult;
+ return TRUE;
+}
+
+extern
+Bool PanoramiXCreateScreenRegion(pWin)
+WindowPtr pWin;
+{
+ ScreenPtr pScreen;
+ BoxRec box;
+ int i;
+ Bool ret;
+
+ pScreen = pWin->drawable.pScreen;
+ for (i = 0; i < PanoramiXNumScreens; i++) {
+ box.x1 = 0 - panoramiXdataPtr[i].x;
+ box.x2 = box.x1 + PanoramiXPixWidth;
+ box.y1 = 0 - panoramiXdataPtr[i].y;
+ box.y2 = box.y1 + PanoramiXPixHeight;
+ REGION_INIT(pScreen, &PanoramiXScreenRegion[i], &box, 1);
+ ret = REGION_NOTEMPTY(pScreen, &PanoramiXScreenRegion[i]);
+ if (!ret)
+ return ret;
+ }
+ return ret;
+}
+
+extern
+void PanoramiXDestroyScreenRegion(pWin)
+WindowPtr pWin;
+{
+ ScreenPtr pScreen;
+ int i;
+ Bool ret;
+
+ pScreen = pWin->drawable.pScreen;
+ for (i = 0; i < PanoramiXNumScreens; i++)
+ REGION_DESTROY(pScreen, &PanoramiXScreenRegion[i]);
+}
+
+/*
+ * Assign the Root window and colormap ID's in the PanoramiXScreen Root
+ * linked lists. Note: WindowTable gets setup in dix_main by
+ * InitRootWindow, and GlobalScrInfo is screenInfo which gets setup
+ * by InitOutput.
+ */
+extern
+void PanoramiXConsolidate(void)
+{
+ int i,j,k,v,d,n, thisMaxDepth;
+ int depthIndex;
+ DepthPtr pDepth, pLargeDepth;
+ VisualPtr pVisual;
+ VisualID it;
+ register WindowPtr pWin, pLargeWin;
+ Bool SameDepth;
+
+ PanoramiXLargestScreenDepth.numDepths = (screenInfo.screens[PanoramiXNumScreens -1])->numDepths;
+ PanoramiXLargestScreenDepth.screenNum = PanoramiXNumScreens - 1;
+ SameDepth = TRUE;
+ for (i = 0; i < 2; i++)
+ {
+ for (j =0; j < 6; j++)
+ {
+ PanoramiXColorDepthTable[i].panoramiXScreenMap[j].numDepths=0;
+ for (n = 0; n < 6; n++)
+ {
+ PanoramiXColorDepthTable[i].panoramiXScreenMap[j].listDepths[n]=0;
+ }
+ for (k = 0; k < 33; k++)
+ {
+ PanoramiXColorDepthTable[i].panoramiXScreenMap[j].vmap[k].numVids=0;
+ for (v = 0; v < 10; v++)
+ {
+ PanoramiXColorDepthTable[i].panoramiXScreenMap[j].vmap[k].vid[v]=0;
+ }
+ }
+ }
+ }
+ for (i = PanoramiXNumScreens - 1; i >= 0; i--)
+ {
+ PanoramiXWinRoot->info[i].id = WindowTable[i]->drawable.id;
+ PanoramiXCmapRoot->info[i].id = (screenInfo.screens[i])->defColormap;
+
+ /* Create a Color-Depth-Table, this will help us deal
+ with mixing graphics boards and visuals, of course
+ given that the boards support multi-screen to begin
+ with. Fill the panoramiXCDT table by screen, then
+ visual type and allowable depths.
+ */
+ pWin = WindowTable[i];
+ if ( (screenInfo.screens[i])->numDepths >
+ PanoramiXLargestScreenDepth.numDepths )
+ {
+ PanoramiXLargestScreenDepth.numDepths = (screenInfo.screens[i])->numDepths;
+ PanoramiXLargestScreenDepth.screenNum = i;
+ SameDepth = FALSE;
+ }
+ for (v = 0, pVisual = pWin->drawable.pScreen->visuals;
+ v < pWin->drawable.pScreen->numVisuals; v++, pVisual++)
+ {
+ PanoramiXColorDepthTable[i].panoramiXScreenMap[pVisual->class].numDepths = (screenInfo.screens[i])->numDepths;
+ for ( j = 0; j < (screenInfo.screens[i])->numDepths; j++)
+ {
+ pDepth = (DepthPtr) &pWin->drawable.pScreen->allowedDepths[j];
+ PanoramiXColorDepthTable[i].panoramiXScreenMap[pVisual->class].listDepths[j] = pDepth->depth;
+ for (d = 0; d < pDepth->numVids; d++)
+ {
+ if (pVisual->vid == pDepth->vids[d])
+ {
+ PanoramiXColorDepthTable[i].
+ panoramiXScreenMap[pVisual->class].vmap[pDepth->depth].
+ vid[
+ PanoramiXColorDepthTable[i].
+ panoramiXScreenMap[pVisual->class].
+ vmap[pDepth->depth].numVids++
+ ]
+ = pDepth->vids[d];
+ }
+ }
+ }
+ }
+ PanoramiXColorDepthTable[i].numVisuals = 6;
+ } /* for each screen */
+ /* Fill in ColorDepthTable for mixed visuals with varying depth.
+ Can't do that until we figure out how to handle mixed visuals
+ and varying card visual/depth initialization. If we can decide
+ how to map the relationship, then we can use this table to
+ shove the information into and use for cross-referencing when
+ necessary.
+
+ In the meantime, check to see if the screens are the same,
+ if they don't then disable panoramiX, print out a message,
+ don't support this mode.
+ */
+}
+
+/* Since locate_neighbors is recursive, a quick simple example
+ is in order.This mostly so you can see what the initial values are.
+
+ Given 3 screens:
+ upperleft screen[0]
+ panoramiXdataPtr[0].x = 0
+ panoramiXdataPtr[0].y = 0
+ panoramiXdataPtr[0].width = 640
+ panoramiXdataPtr[0].height = 480
+ panoramiXdataPtr[0].below = -1
+ panoramiXdataPtr[0].right = 1
+ panoramiXdataPtr[0].above = -1
+ panoramiXdataPtr[0].left = -1
+ middle screen[1]
+ panoramiXdataPtr[1].x = 0
+ panoramiXdataPtr[1].y = 0
+ panoramiXdataPtr[1].width = 640
+ panoramiXdataPtr[1].height = 480
+ panoramiXdataPtr[1].below = -1
+ panoramiXdataPtr[1].right = 2
+ panoramiXdataPtr[1].above = -1
+ panoramiXdataPtr[1].left = 0
+ last right screen[2]
+ panoramiXdataPtr[2].x = 0
+ panoramiXdataPtr[2].y = 0
+ panoramiXdataPtr[2].width = 640
+ panoramiXdataPtr[2].height = 480
+ panoramiXdataPtr[2].below = -1
+ panoramiXdataPtr[2].right = -1
+ panoramiXdataPtr[2].above = -1
+ panoramiXdataPtr[2].left = 1
+
+ Calling locate_neighbors(0) results in:
+ panoramiXdataPtr[0].x = 0
+ panoramiXdataPtr[0].y = 0
+ panoramiXdataPtr[1].x = 640
+ panoramiXdataPtr[1].y = 0
+ panoramiXdataPtr[2].x = 1280
+ panoramiXdataPtr[2].y = 0
+*/
+
+static void locate_neighbors(int i)
+{
+ int j;
+
+ j = panoramiXdataPtr[i].right;
+ if ((j != -1) && !panoramiXdataPtr[j].x && !panoramiXdataPtr[j].y) {
+ panoramiXdataPtr[j].x = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width;
+ panoramiXdataPtr[j].y = panoramiXdataPtr[i].y;
+ locate_neighbors(j);
+ }
+ j = panoramiXdataPtr[i].below;
+ if ((j != -1) && !panoramiXdataPtr[j].x && !panoramiXdataPtr[j].y) {
+ panoramiXdataPtr[j].y = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height;
+ panoramiXdataPtr[j].x = panoramiXdataPtr[i].x;
+ locate_neighbors(j);
+ }
+}
+
+
+
+/*
+ * PanoramiXResetProc()
+ * Exit, deallocating as needed.
+ */
+
+static void PanoramiXResetProc(extEntry)
+ ExtensionEntry* extEntry;
+{
+ int i;
+ PanoramiXList *pPanoramiXList;
+ PanoramiXList *tempList;
+
+ for (pPanoramiXList = PanoramiXPmapRoot; pPanoramiXList; pPanoramiXList = tempList){
+ tempList = pPanoramiXList->next;
+ Xfree(pPanoramiXList);
+ }
+ for (pPanoramiXList = PanoramiXCmapRoot; pPanoramiXList; pPanoramiXList = tempList){
+ tempList = pPanoramiXList->next;
+ Xfree(pPanoramiXList);
+ }
+ for (pPanoramiXList = PanoramiXGCRoot; pPanoramiXList; pPanoramiXList = tempList) {
+ tempList = pPanoramiXList->next;
+ Xfree(pPanoramiXList);
+ }
+ for (pPanoramiXList = PanoramiXWinRoot; pPanoramiXList; pPanoramiXList = tempList) {
+ tempList = pPanoramiXList->next;
+ Xfree(pPanoramiXList);
+ }
+ screenInfo.numScreens = PanoramiXNumScreens;
+ for (i = 256; i--; )
+ ProcVector[i] = SavedProcVector[i];
+ Xfree(panoramiXdataPtr);
+
+}
+
+
+int
+#if NeedFunctionPrototypes
+ProcPanoramiXQueryVersion (ClientPtr client)
+#else
+ProcPanoramiXQueryVersion (client)
+ register ClientPtr client;
+#endif
+{
+ REQUEST(xPanoramiXQueryVersionReq);
+ xPanoramiXQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = PANORAMIX_MAJOR_VERSION;
+ rep.minorVersion = PANORAMIX_MINOR_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ }
+ WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+int
+#if NeedFunctionPrototypes
+ProcPanoramiXGetState(ClientPtr client)
+#else
+ProcPanoramiXGetState(client)
+ register ClientPtr client;
+#endif
+{
+ REQUEST(xPanoramiXGetStateReq);
+ WindowPtr pWin;
+ xPanoramiXGetStateReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.state = !noPanoramiXExtension;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swaps (&rep.state, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep);
+ return client->noClientException;
+
+}
+
+int
+#if NeedFunctionPrototypes
+ProcPanoramiXGetScreenCount(ClientPtr client)
+#else
+ProcPanoramiXGetScreenCount(client)
+ register ClientPtr client;
+#endif
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenCountReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.ScreenCount = PanoramiXNumScreens;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swaps (&rep.ScreenCount, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep);
+ return client->noClientException;
+}
+
+int
+#if NeedFunctionPrototypes
+ProcPanoramiXGetScreenSize(ClientPtr client)
+#else
+ProcPanoramiXGetScreenSize(client)
+ register ClientPtr client;
+#endif
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ WindowPtr pWin;
+ xPanoramiXGetScreenSizeReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ /* screen dimensions */
+ rep.width = panoramiXdataPtr[stuff->screen].width;
+ rep.height = panoramiXdataPtr[stuff->screen].height;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swaps (rep.width, n);
+ swaps (rep.height, n);
+ }
+ WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep);
+ return client->noClientException;
+}
+
+
+void PrintList(PanoramiXList *head)
+{
+ int i = 0;
+
+ for (; head; i++, head = head->next)
+ fprintf(stderr, "%2d next = 0x%010lx, id[0] = 0x%08x, id[1] = 0x%08x\n",
+ i, head->next, head->info[0].id, head->info[1].id);
+}
+static int
+#if NeedFunctionPrototypes
+ProcPanoramiXDispatch (ClientPtr client)
+#else
+ProcPanoramiXDispatch (client)
+ ClientPtr client;
+#endif
+{ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_PanoramiXQueryVersion:
+ return ProcPanoramiXQueryVersion(client);
+ case X_PanoramiXGetState:
+ return ProcPanoramiXGetState(client);
+ case X_PanoramiXGetScreenCount:
+ return ProcPanoramiXGetScreenCount(client);
+ case X_PanoramiXGetScreenSize:
+ return ProcPanoramiXGetScreenSize(client);
+ }
+ return BadRequest;
+}
diff --git a/Xext/panoramiXSwap.c b/Xext/panoramiXSwap.c
new file mode 100644
index 000000000..c6bb5071e
--- /dev/null
+++ b/Xext/panoramiXSwap.c
@@ -0,0 +1,158 @@
+/* $Xorg: panoramiXSwap.c,v 1.4 2000/08/17 19:47:57 cpqbld Exp $ */
+/*****************************************************************
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+******************************************************************/
+
+#include <stdio.h>
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "cursor.h"
+#include "cursorstr.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "gc.h"
+#include "gcstruct.h"
+#include "scrnintstr.h"
+#include "window.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#if 0
+#include <sys/workstation.h>
+#include <X11/Xserver/ws.h>
+#endif
+#include "panoramiX.h"
+#include "panoramiXproto.h"
+
+
+/*
+/*
+ * External references for data variables
+ */
+
+extern Bool noPanoramiXExtension;
+extern Bool PanoramiXVisibilityNotifySent;
+extern WindowPtr *WindowTable;
+extern int defaultBackingStore;
+extern char *ConnectionInfo;
+extern int connBlockScreenStart;
+extern int (* ProcVector[256]) ();
+
+#if NeedFunctionPrototypes
+#define PROC_EXTERN(pfunc) extern int pfunc(ClientPtr)
+#else
+#define PROC_EXTERN(pfunc) extern int pfunc()
+#endif
+
+PROC_EXTERN(ProcPanoramiXQueryVersion);
+PROC_EXTERN(ProcPanoramiXGetState);
+PROC_EXTERN(ProcPanoramiXGetScreenCount);
+PROC_EXTERN(PropPanoramiXGetScreenSize);
+
+static int
+#if NeedFunctionPrototypes
+SProcPanoramiXQueryVersion (ClientPtr client)
+#else
+SProcPanoramiXQueryVersion (client)
+ register ClientPtr client;
+#endif
+{
+ register int n;
+ REQUEST(xPanoramiXQueryVersionReq);
+
+ swaps(&stuff->length,n);
+ REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq);
+ return ProcPanoramiXQueryVersion(client);
+}
+
+static int
+#if NeedFunctionPrototypes
+SProcPanoramiXGetState(ClientPtr client)
+#else
+SProcPanoramiXGetState(client)
+ register ClientPtr client;
+#endif
+{
+ REQUEST(xPanoramiXGetStateReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetStateReq);
+
+}
+
+static int
+#if NeedFunctionPrototypes
+SProcPanoramiXGetScreenCount(ClientPtr client)
+#else
+SProcPanoramixGetScreenCount(client)
+ register ClientPtr client;
+#endif
+{
+ REQUEST(xPanoramiXGetScreenCountReq);
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq);
+ return ProcPanoramiXGetScreenCount(client);
+}
+
+static int
+#if NeedFunctionPrototypes
+SProcPanoramiXGetScreenSize(ClientPtr client)
+#else
+SProcPanoramiXGetScreenSize(client)
+ register ClientPtr client;
+#endif
+{
+ REQUEST(xPanoramiXGetScreenSizeReq);
+ WindowPtr pWin;
+ register int n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq);
+ return ProcPanoramiXGetScreenSize(client);
+}
+
+int
+#if NeedFunctionPrototypes
+SProcPanoramiXDispatch (ClientPtr client)
+#else
+SProcPanoramiXDispatch (client)
+ ClientPtr client;
+#endif
+{ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_PanoramiXQueryVersion:
+ return SProcPanoramiXQueryVersion(client);
+ case X_PanoramiXGetState:
+ return SProcPanoramiXGetState(client);
+ case X_PanoramiXGetScreenCount:
+ return SProcPanoramiXGetScreenCount(client);
+ case X_PanoramiXGetScreenSize:
+ return SProcPanoramiXGetScreenSize(client);
+ return BadRequest;
+ }
+}
diff --git a/Xext/panoramiXprocs.c b/Xext/panoramiXprocs.c
new file mode 100644
index 000000000..cd54bdcb3
--- /dev/null
+++ b/Xext/panoramiXprocs.c
@@ -0,0 +1,3034 @@
+/* $Xorg: panoramiXprocs.c,v 1.5 2000/08/17 19:47:57 cpqbld Exp $ */
+/*****************************************************************
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+******************************************************************/
+
+#include <stdio.h>
+#include "X.h"
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "Xproto.h"
+#include "windowstr.h"
+#include "dixfontstr.h"
+#include "gcstruct.h"
+#include "colormapst.h"
+#include "scrnintstr.h"
+#include "opaque.h"
+#include "inputstr.h"
+#include "migc.h"
+#include "misc.h"
+#include "dixstruct.h"
+#include "panoramiX.h"
+
+extern Bool noPanoramiXExtension;
+extern Bool PanoramiXVisibilityNotifySent;
+extern Bool PanoramiXMapped;
+extern int PanoramiXNumScreens;
+extern int PanoramiXPixWidth;
+extern int PanoramiXPixHeight;
+extern PanoramiXWindow *PanoramiXWinRoot;
+extern PanoramiXGC *PanoramiXGCRoot;
+extern PanoramiXCmap *PanoramiXCmapRoot;
+extern PanoramiXPmap *PanoramiXPmapRoot;
+extern PanoramiXData *panoramiXdataPtr;
+extern PanoramiXCDT PanoramiXColorDepthTable[MAXSCREENS];
+extern ScreenInfo *GlobalScrInfo;
+extern int (* SavedProcVector[256])();
+extern void (* ReplySwapVector[256])();
+extern WindowPtr *WindowTable;
+extern char *ConnectionInfo;
+extern int connBlockScreenStart;
+
+extern XID clientErrorValue;
+
+extern void Swap32Write();
+
+extern long defaultScreenSaverTime;
+extern long defaultScreenSaverInterval;
+extern int defaultScreenSaverBlanking;
+extern int defaultScreenSaverAllowExposures;
+static ClientPtr onlyClient;
+static Bool grabbingClient = FALSE;
+#ifdef __alpha /* THIS NEEDS TO BE LONG !!!! Change driver! */
+int *checkForInput[2];
+#else
+long *checkForInput[2];
+#endif
+extern int connBlockScreenStart;
+
+extern int (* InitialVector[3]) ();
+extern int (* ProcVector[256]) ();
+extern int (* SwappedProcVector[256]) ();
+extern void (* EventSwapVector[128]) ();
+extern void (* ReplySwapVector[256]) ();
+extern void Swap32Write(), SLHostsExtend(), SQColorsExtend(),
+WriteSConnectionInfo();
+extern void WriteSConnSetupPrefix();
+extern char *ClientAuthorized();
+extern Bool InsertFakeRequest();
+static void KillAllClients();
+static void DeleteClientFromAnySelections();
+extern void ProcessWorkQueue();
+
+
+static int nextFreeClientID; /* always MIN free client ID */
+
+static int nClients; /* number active clients */
+
+char isItTimeToYield;
+
+/* Various of the DIX function interfaces were not designed to allow
+ * the client->errorValue to be set on BadValue and other errors.
+ * Rather than changing interfaces and breaking untold code we introduce
+ * a new global that dispatch can use.
+ */
+XID clientErrorValue; /* XXX this is a kludge */
+
+
+#define SAME_SCREENS(a, b) (\
+ (a.pScreen == b.pScreen))
+
+
+
+extern int Ones();
+
+int PanoramiXCreateWindow(register ClientPtr client)
+{
+ register WindowPtr pParent, pWin;
+ REQUEST(xCreateWindowReq);
+ int result, j = 0;
+ unsigned len;
+ Bool FoundIt = FALSE;
+ Window winID;
+ Window parID;
+ PanoramiXWindow *localWin;
+ PanoramiXWindow *parentWin = PanoramiXWinRoot;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ PanoramiXCmap *pPanoramiXCmap = NULL;
+ PanoramiXPmap *pBackgndPmap = NULL;
+ PanoramiXPmap *pBorderPmap = NULL;
+ VisualID orig_visual;
+ XID orig_wid;
+ int orig_x, orig_y;
+ register Mask orig_mask;
+ int cmap_offset = 0;
+ int pback_offset = 0;
+ int pbord_offset = 0;
+ int class_index, this_class_index;
+ int vid_index, this_vid_index;
+
+ REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
+
+ len = client->req_len - (sizeof(xCreateWindowReq) >> 2);
+ IF_RETURN((Ones((Mask)stuff->mask) != len), BadLength);
+ orig_mask = stuff->mask;
+ PANORAMIXFIND_ID(parentWin, stuff->parent);
+ if (parentWin) {
+ localWin = (PanoramiXWindow *)Xcalloc(sizeof(PanoramiXWindow));
+ IF_RETURN(!localWin, BadAlloc);
+ } else {
+ return BadWindow;
+ }
+ if ((PanoramiXNumScreens - 1) && ((Mask)stuff->mask & CWBackPixmap)) {
+ XID pmapID;
+
+ pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1));
+ pmapID = *((CARD32 *) &stuff[1] + pback_offset);
+ if (pmapID) {
+ pBackgndPmap = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pBackgndPmap, pmapID);
+ }
+ }
+ if ((PanoramiXNumScreens - 1) && ((Mask)stuff->mask & CWBorderPixmap)) {
+ XID pmapID;
+
+ pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1));
+ pmapID = *((CARD32 *) &stuff[1] + pbord_offset);
+ if (pmapID) {
+ pBorderPmap = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pBorderPmap, pmapID);
+ }
+ }
+ if ((PanoramiXNumScreens - 1) && ((Mask)stuff->mask & CWColormap)) {
+ Colormap cmapID;
+
+ cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1));
+ cmapID = *((CARD32 *) &stuff[1] + cmap_offset);
+ if (cmapID) {
+ pPanoramiXCmap = PanoramiXCmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXCmap, cmapID);
+ }
+ }
+ orig_x = stuff->x;
+ orig_y = stuff->y;
+ orig_wid = stuff->wid;
+ orig_visual = stuff->visual;
+ for (j = 0; j <= PanoramiXNumScreens - 1; j++) {
+ winID = j ? FakeClientID(client->index) : orig_wid;
+ localWin->info[j].id = winID;
+ }
+ localWin->FreeMe = FALSE;
+ localWin->visibility = VisibilityNotViewable;
+ localWin->VisibilitySent = FALSE;
+ PANORAMIXFIND_LAST(pPanoramiXWin, PanoramiXWinRoot);
+ pPanoramiXWin->next = localWin;
+ if ( (stuff->visual != CopyFromParent) && (stuff->depth != 0))
+ {
+ /* Find the correct visual for this screen */
+ for (class_index = 0; class_index < PanoramiXColorDepthTable[0].numVisuals;
+class_index++)
+ {
+ for (vid_index = 0; vid_index < PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[stuff->depth].numVids; vid_index++)
+ {
+ if ( stuff->visual == PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[stuff->depth].vid[vid_index] )
+ {
+ this_class_index = class_index;
+ this_vid_index = vid_index;
+ FoundIt = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ if (parentWin == PanoramiXWinRoot) {
+ stuff->x = orig_x - panoramiXdataPtr[j].x;
+ stuff->y = orig_y - panoramiXdataPtr[j].y;
+ }
+ stuff->wid = localWin->info[j].id;
+ parID = (XID)(parentWin->info[j].id);
+ pParent = (WindowPtr)SecurityLookupWindow(parID, client,SecurityReadAccess);
+ IF_RETURN((!pParent),BadWindow);
+ stuff->parent = parID;
+ if ( (orig_visual != CopyFromParent) && (stuff->depth != 0) && FoundIt )
+ {
+ stuff->visual = PanoramiXColorDepthTable[j].panoramiXScreenMap[this_class_index].vmap[stuff->depth].vid[this_vid_index];
+ }
+ if (pBackgndPmap)
+ *((CARD32 *) &stuff[1] + pback_offset) = pBackgndPmap->info[j].id;
+ if (pBorderPmap)
+ *((CARD32 *) &stuff[1] + pbord_offset) = pBorderPmap->info[j].id;
+ if (pPanoramiXCmap)
+ *((CARD32 *) &stuff[1] + cmap_offset) = pPanoramiXCmap->info[j].id;
+ stuff->mask = orig_mask;
+ result = (*SavedProcVector[X_CreateWindow])(client);
+ BREAK_IF(result != Success);
+ }
+ if (result != Success) {
+ pPanoramiXWin->next = NULL;
+ if (localWin)
+ Xfree(localWin);
+ }
+ return (result);
+}
+
+
+
+int PanoramiXChangeWindowAttributes(register ClientPtr client)
+{
+ register WindowPtr pWin;
+ REQUEST(xChangeWindowAttributesReq);
+ register int result;
+ int len;
+ int j;
+ Window winID;
+ Mask orig_valueMask;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ PanoramiXWindow *pPanoramiXWinback = NULL;
+ PanoramiXCmap *pPanoramiXCmap = NULL;
+ PanoramiXPmap *pBackgndPmap = NULL;
+ PanoramiXPmap *pBorderPmap = NULL;
+ int cmap_offset = 0;
+ int pback_offset = 0;
+ int pbord_offset = 0;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
+ len = client->req_len - (sizeof(xChangeWindowAttributesReq) >> 2);
+ IF_RETURN((len != Ones((Mask) stuff->valueMask)), BadLength);
+ orig_valueMask = stuff->valueMask;
+ winID = stuff->window;
+ for (; pPanoramiXWin && (pPanoramiXWin->info[0].id != stuff->window);
+ pPanoramiXWin = pPanoramiXWin->next)
+ pPanoramiXWinback = pPanoramiXWin;
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, winID);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ if ((PanoramiXNumScreens - 1) && ((Mask)stuff->valueMask & CWBackPixmap)) {
+ XID pmapID;
+
+ pback_offset = Ones((Mask)stuff->valueMask & (CWBackPixmap - 1));
+ pmapID = *((CARD32 *) &stuff[1] + pback_offset);
+ if (pmapID) {
+ pBackgndPmap = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pBackgndPmap, pmapID);
+ }
+ }
+ if ((PanoramiXNumScreens - 1) && ((Mask)stuff->valueMask & CWBorderPixmap)) {
+ XID pmapID;
+
+ pbord_offset = Ones((Mask)stuff->valueMask & (CWBorderPixmap - 1));
+ pmapID = *((CARD32 *) &stuff[1] + pbord_offset);
+ if (pmapID) {
+ pBorderPmap = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pBorderPmap, pmapID);
+ }
+ }
+ if ((PanoramiXNumScreens - 1) && ((Mask)stuff->valueMask & CWColormap )) {
+ Colormap cmapID;
+
+ cmap_offset = Ones((Mask)stuff->valueMask & (CWColormap - 1));
+ cmapID = *((CARD32 *) &stuff[1] + cmap_offset);
+ if (cmapID) {
+ pPanoramiXCmap = PanoramiXCmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXCmap, cmapID);
+ }
+ }
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->window = pPanoramiXWin->info[j].id;
+ stuff->valueMask = orig_valueMask;
+ if (pBackgndPmap)
+ *((CARD32 *) &stuff[1] + pback_offset) = pBackgndPmap->info[j].id;
+ if (pBorderPmap)
+ *((CARD32 *) &stuff[1] + pbord_offset) = pBorderPmap->info[j].id;
+ if (pPanoramiXCmap)
+ *((CARD32 *) &stuff[1] + cmap_offset) = pPanoramiXCmap->info[j].id;
+ result = (*SavedProcVector[X_ChangeWindowAttributes])(client);
+ BREAK_IF(result != Success);
+ }
+ if ((result == Success) && pPanoramiXWinback &&
+ pPanoramiXWin && pPanoramiXWin->FreeMe) {
+ pPanoramiXWinback->next = pPanoramiXWin->next;
+ Xfree(pPanoramiXWin);
+ }
+ return (result);
+}
+
+
+int PanoramiXDestroyWindow(ClientPtr client)
+{
+ REQUEST(xResourceReq);
+ int j, result;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ PanoramiXWindow *pPanoramiXWinback = NULL;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ for (; pPanoramiXWin && (pPanoramiXWin->info[0].id != stuff->id);
+ pPanoramiXWin = pPanoramiXWin->next)
+ pPanoramiXWinback = pPanoramiXWin;
+ IF_RETURN(!pPanoramiXWin,BadWindow);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->id = pPanoramiXWin->info[j].id;
+ result = (* SavedProcVector[X_DestroyWindow])(client);
+ BREAK_IF(result != Success);
+ }
+ if ((result == Success) && pPanoramiXWinback &&
+ pPanoramiXWin && pPanoramiXWin->FreeMe) {
+ pPanoramiXWinback->next = pPanoramiXWin->next;
+ Xfree(pPanoramiXWin);
+ }
+ PANORAMIX_FREE(client);
+ return (result);
+}
+
+
+int PanoramiXDestroySubwindows(ClientPtr client)
+{
+ REQUEST(xResourceReq);
+ int j,result;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ PanoramiXWindow *pPanoramiXWinback = NULL;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ for (; pPanoramiXWin && (pPanoramiXWin->info[0].id != stuff->id);
+ pPanoramiXWin = pPanoramiXWin->next)
+ pPanoramiXWinback = pPanoramiXWin;
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->id = pPanoramiXWin->info[j].id;
+ result = (* SavedProcVector[X_DestroySubwindows])(client);
+ }
+ if ((result == Success) && pPanoramiXWinback &&
+ pPanoramiXWin && pPanoramiXWin->FreeMe) {
+ pPanoramiXWinback->next = pPanoramiXWin->next;
+ Xfree(pPanoramiXWin);
+ }
+ PANORAMIX_FREE(client);
+ return (result);
+}
+
+
+int PanoramiXChangeSaveSet(ClientPtr client)
+{
+ REQUEST(xChangeSaveSetReq);
+ int j, result;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+
+ REQUEST_SIZE_MATCH(xChangeSaveSetReq);
+ if (!stuff->window)
+ result = (* SavedProcVector[X_ChangeSaveSet])(client);
+ else {
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->window);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->window = pPanoramiXWin->info[j].id;
+ result = (* SavedProcVector[X_ChangeSaveSet])(client);
+ }
+ }
+ return (result);
+}
+
+
+int PanoramiXReparentWindow(register ClientPtr client)
+{
+ register WindowPtr pWin, pParent;
+ REQUEST(xReparentWindowReq);
+ register int result;
+ int j;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ PanoramiXWindow *pPanoramiXPar = PanoramiXWinRoot;
+
+ REQUEST_SIZE_MATCH(xReparentWindowReq);
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->window);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ PANORAMIXFIND_ID(pPanoramiXPar, stuff->parent);
+ IF_RETURN(!pPanoramiXPar, BadWindow);
+ FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXPar), j) {
+ stuff->window = pPanoramiXWin->info[j].id;
+ stuff->parent = pPanoramiXPar->info[j].id;
+ result = (*SavedProcVector[X_ReparentWindow])(client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+
+
+int PanoramiXMapWindow(register ClientPtr client)
+{
+ REQUEST(xResourceReq);
+ int j,result;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ register WindowPtr pWin, pChild;
+ Window winID;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ /* initialize visibility */
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client,
+SecurityReadAccess);
+ IF_RETURN(!pWin, BadWindow);
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id);
+ if (pPanoramiXWin)
+ pPanoramiXWin->VisibilitySent = FALSE;
+ }
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->id);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ PanoramiXMapped = TRUE;
+ PanoramiXVisibilityNotifySent = FALSE;
+ pPanoramiXWin->VisibilitySent = FALSE;
+ for (j = 0; j <= (PanoramiXNumScreens - 1); j++)
+ {
+ winID = pPanoramiXWin->info[j].id;
+ pWin = (WindowPtr) SecurityLookupWindow(winID,
+client,SecurityReadAccess);
+ IF_RETURN((!pWin), BadWindow);
+ stuff->id = winID;
+ result = (*SavedProcVector[X_MapWindow])(client);
+ }
+ /* clean up */
+ PanoramiXMapped = FALSE;
+ PanoramiXVisibilityNotifySent = FALSE;
+ pPanoramiXWin->VisibilitySent = FALSE;
+ pWin = (WindowPtr) SecurityLookupWindow(stuff->id,
+client,SecurityReadAccess);
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id);
+ if (pPanoramiXWin)
+ pPanoramiXWin->VisibilitySent = FALSE;
+ }
+ return (result);
+}
+
+
+int PanoramiXMapSubwindows(register ClientPtr client)
+{
+ REQUEST(xResourceReq);
+ int j,result;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ register WindowPtr pWin, pChild;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ /* initialize visibility values */
+ pWin = (WindowPtr) SecurityLookupWindow(stuff->id,
+client,SecurityReadAccess);
+ IF_RETURN(!pWin, BadWindow);
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id);
+ if (pPanoramiXWin)
+ pPanoramiXWin->VisibilitySent = FALSE;
+ }
+
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->id);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ PanoramiXMapped = TRUE;
+ PanoramiXVisibilityNotifySent = FALSE;
+ pPanoramiXWin->VisibilitySent = FALSE;
+ for (j = 0; j <= (PanoramiXNumScreens - 1); j++)
+ {
+ stuff->id = pPanoramiXWin->info[j].id;
+ result = (*SavedProcVector[X_MapSubwindows])(client);
+ }
+ /* clean up */
+ PanoramiXMapped = FALSE;
+ PanoramiXVisibilityNotifySent = FALSE;
+ pPanoramiXWin->VisibilitySent = FALSE;
+ pWin = (WindowPtr) SecurityLookupWindow(stuff->id,
+client,SecurityReadAccess);
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id);
+ if (pPanoramiXWin)
+ pPanoramiXWin->VisibilitySent = FALSE;
+ }
+ PANORAMIX_FREE(client);
+ return (result);
+}
+
+
+int PanoramiXUnmapWindow(register ClientPtr client)
+{
+ REQUEST(xResourceReq);
+ int j, result;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ register WindowPtr pWin, pChild;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ /* initialize visibility values */
+ pWin = (WindowPtr) SecurityLookupWindow(stuff->id,
+client,SecurityReadAccess);
+ IF_RETURN(!pWin, BadWindow);
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, pWin->drawable.id);
+ if (pPanoramiXWin)
+ pPanoramiXWin->VisibilitySent = FALSE;
+ }
+
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->id);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ PanoramiXMapped = TRUE;
+ PanoramiXVisibilityNotifySent = FALSE;
+ pPanoramiXWin->VisibilitySent = FALSE;
+ for (j = 0; j <= (PanoramiXNumScreens - 1); j++)
+ {
+ stuff->id = pPanoramiXWin->info[j].id;
+ result = (*SavedProcVector[X_UnmapWindow])(client);
+ }
+
+ /* clean up */
+ PanoramiXMapped = FALSE;
+ PanoramiXVisibilityNotifySent = FALSE;
+ pPanoramiXWin->VisibilitySent = FALSE;
+ pWin = (WindowPtr) SecurityLookupWindow(stuff->id,
+client,SecurityReadAccess);
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) {
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, pChild->drawable.id);
+ if (pPanoramiXWin)
+ pPanoramiXWin->VisibilitySent = FALSE;
+ }
+ PANORAMIX_FREE(client);
+ return (client->noClientException);
+}
+
+
+int PanoramiXUnmapSubwindows(register ClientPtr client)
+{
+ REQUEST(xResourceReq);
+ int j, result;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ register WindowPtr pWin, pChild;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ /* initialize visibility values */
+ pWin = (WindowPtr) SecurityLookupWindow(stuff->id,
+client,SecurityReadAccess);
+ IF_RETURN(!pWin, BadWindow);
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, pWin->drawable.id);
+ if (pPanoramiXWin)
+ pPanoramiXWin->VisibilitySent = FALSE;
+ }
+
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->id);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ PanoramiXMapped = TRUE;
+ PanoramiXVisibilityNotifySent = FALSE;
+ pPanoramiXWin->VisibilitySent = FALSE;
+ for (j = 0; j <= (PanoramiXNumScreens - 1); j++)
+ {
+ stuff->id = pPanoramiXWin->info[j].id;
+ result = (*SavedProcVector[X_UnmapSubwindows])(client);
+ }
+
+ /* clean up */
+ PanoramiXMapped = FALSE;
+ PanoramiXVisibilityNotifySent = FALSE;
+ pPanoramiXWin->VisibilitySent = FALSE;
+ pWin = (WindowPtr) SecurityLookupWindow(stuff->id,
+client,SecurityReadAccess);
+ for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib){
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, pWin->drawable.id);
+ if (pPanoramiXWin)
+ pPanoramiXWin->VisibilitySent = FALSE;
+ }
+ PANORAMIX_FREE(client);
+ return (client->noClientException);
+}
+
+
+int PanoramiXConfigureWindow(register ClientPtr client)
+{
+ register WindowPtr pWin;
+ REQUEST(xConfigureWindowReq);
+ register int result;
+ unsigned len, i, things;
+ XID changes[32];
+ register Mask orig_mask;
+ int j, sib_position;
+ Window winID;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ PanoramiXWindow *pPanoramiXSib = NULL;
+ int x_off = 0, y_off = 0;
+ XID *pStuff;
+ XID *origStuff, *modStuff;
+ Mask local_mask;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
+ len = client->req_len - (sizeof(xConfigureWindowReq) >> 2);
+ things = Ones((Mask)stuff->mask);
+ IF_RETURN((things != len), BadLength);
+ orig_mask = stuff->mask;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->window);
+ if (!pPanoramiXWin) {
+ client->errorValue = stuff->window;
+ return (BadWindow);
+ }
+ if (things > 0) {
+ pStuff = (XID *) ALLOCATE_LOCAL(things * sizeof(XID));
+ memcpy((char *) pStuff, (char *) &stuff[1], things * sizeof(XID));
+ local_mask = (CWSibling | CWX | CWY) & ((Mask) stuff->mask);
+ if (local_mask & CWSibling) {
+ sib_position = Ones((Mask) stuff->mask & (CWSibling - 1));
+ pPanoramiXSib = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXSib, *(pStuff + sib_position));
+ }
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ winID = pPanoramiXWin->info[j].id;
+ pWin = (WindowPtr)SecurityLookupWindow(winID, client,SecurityReadAccess);
+ if (!pWin) {
+ client->errorValue = pPanoramiXWin->info[0].id;
+ return (BadWindow);
+ }
+ stuff->window = winID;
+ if (pWin->parent
+ && (pWin->parent->drawable.id == PanoramiXWinRoot->info[j].id)) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }
+ modStuff = (XID *) &stuff[1];
+ origStuff = pStuff;
+ i = things;
+ if (local_mask & CWX) {
+ *modStuff++ = *origStuff++ - x_off;
+ i--;
+ }
+ if (local_mask & CWY) {
+ *modStuff++ = *origStuff++ - y_off;
+ i--;
+ }
+ for ( ; i; i--)
+ *modStuff++ = *origStuff++;
+ if (pPanoramiXSib)
+ *((XID *) &stuff[1] + sib_position) = pPanoramiXSib->info[j].id;
+ stuff->mask = orig_mask;
+ result = (*SavedProcVector[X_ConfigureWindow])(client);
+ }
+ DEALLOCATE_LOCAL(pStuff);
+ PANORAMIX_FREE(client);
+ return (result);
+ } else
+ return (client->noClientException);
+}
+
+
+int PanoramiXCirculateWindow(register ClientPtr client)
+{
+ REQUEST(xCirculateWindowReq);
+ int j,result;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xCirculateWindowReq);
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->window);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->window = pPanoramiXWin->info[j].id;
+ result = (*SavedProcVector[X_CirculateWindow])(client);
+ }
+ return (result);
+}
+
+
+int PanoramiXGetGeometry(register ClientPtr client)
+{
+ xGetGeometryReply rep;
+ register DrawablePtr pDraw;
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ VERIFY_GEOMETRABLE (pDraw, stuff->id, client);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.root = WindowTable[pDraw->pScreen->myNum]->drawable.id;
+ rep.depth = pDraw->depth;
+
+ if (stuff->id == PanoramiXWinRoot->info[0].id) {
+ xConnSetup *setup = (xConnSetup *) ConnectionInfo;
+ xWindowRoot *root = (xWindowRoot *)
+ (ConnectionInfo + connBlockScreenStart);
+
+ rep.width = root->pixWidth;
+ rep.height = root->pixHeight;
+ } else {
+ rep.width = pDraw->width;
+ rep.height = pDraw->height;
+ }
+
+ /* XXX - Because the pixmap-implementation of the multibuffer extension
+ * may have the buffer-id's drawable resource value be a pointer
+ * to the buffer's window instead of the buffer itself
+ * (this happens if the buffer is the displayed buffer),
+ * we also have to check that the id matches before we can
+ * truly say that it is a DRAWABLE_WINDOW.
+ */
+
+ if ((pDraw->type == UNDRAWABLE_WINDOW) ||
+ ((pDraw->type == DRAWABLE_WINDOW) && (stuff->id == pDraw->id))) {
+ register WindowPtr pWin = (WindowPtr)pDraw;
+ rep.x = pWin->origin.x - wBorderWidth (pWin);
+ rep.y = pWin->origin.y - wBorderWidth (pWin);
+ rep.borderWidth = pWin->borderWidth;
+ } else { /* DRAWABLE_PIXMAP or DRAWABLE_BUFFER */
+ rep.x = rep.y = rep.borderWidth = 0;
+ }
+ WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
+ return (client->noClientException);
+}
+
+
+int PanoramiXChangeProperty(ClientPtr client)
+{
+ int result, j;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ REQUEST(xChangePropertyReq);
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->window);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->window = pPanoramiXWin->info[j].id;
+ result = (* SavedProcVector[X_ChangeProperty])(client);
+ if (result != Success) {
+ stuff->window = pPanoramiXWin->info[0].id;
+ break;
+ }
+ }
+ return (result);
+}
+
+
+int PanoramiXDeleteProperty(ClientPtr client)
+{
+ int result, j;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ REQUEST(xDeletePropertyReq);
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xDeletePropertyReq);
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->window);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->window = pPanoramiXWin->info[j].id;
+ result = (* SavedProcVector[X_DeleteProperty])(client);
+ BREAK_IF(result != Success);
+ }
+ PANORAMIX_FREE(client);
+ return (result);
+}
+
+
+int PanoramiXSendEvent(ClientPtr client)
+{
+ int result, j;
+ BYTE orig_type;
+ Mask orig_eventMask;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ REQUEST(xSendEventReq);
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xSendEventReq);
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->destination);
+ orig_type = stuff->event.u.u.type;
+ orig_eventMask = stuff->eventMask;
+ if (!pPanoramiXWin) {
+ noPanoramiXExtension = TRUE;
+ result = (* SavedProcVector[X_SendEvent])(client);
+ noPanoramiXExtension = FALSE;
+ }
+ else {
+ noPanoramiXExtension = FALSE;
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->destination = pPanoramiXWin->info[j].id;
+ stuff->eventMask = orig_eventMask;
+ stuff->event.u.u.type = orig_type;
+ if (!j)
+ noPanoramiXExtension = TRUE;
+ result = (* SavedProcVector[X_SendEvent])(client);
+ noPanoramiXExtension = FALSE;
+ }
+ }
+ return (result);
+}
+
+
+int PanoramiXCreatePixmap(register ClientPtr client)
+{
+ PixmapPtr pMap;
+ register DrawablePtr pDraw;
+ REQUEST(xCreatePixmapReq);
+ DepthPtr pDepth;
+ int result, j;
+ Pixmap pmapID;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXPmap *pPanoramiXPmap;
+ PanoramiXPmap *localPmap;
+ XID orig_pid;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xCreatePixmapReq);
+ client->errorValue = stuff->pid;
+
+ localPmap =(PanoramiXPmap *) Xcalloc(sizeof(PanoramiXPmap));
+ IF_RETURN(!localPmap, BadAlloc);
+
+ pDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable,
+RC_DRAWABLE,
+ SecurityReadAccess);
+ IF_RETURN(!pDraw, BadDrawable);
+
+ pPanoramiXWin = (pDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+
+ orig_pid = stuff->pid;
+ FOR_NSCREENS_OR_ONCE(pPanoramiXPmap, j) {
+ pmapID = j ? FakeClientID(client->index) : orig_pid;
+ localPmap->info[j].id = pmapID;
+ }
+ localPmap->FreeMe = FALSE;
+ PANORAMIXFIND_LAST(pPanoramiXPmap, PanoramiXPmapRoot);
+ pPanoramiXPmap->next = localPmap;
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->pid = localPmap->info[j].id;
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ result = (* SavedProcVector[X_CreatePixmap])(client);
+ BREAK_IF(result != Success);
+ }
+ if (result != Success) {
+ pPanoramiXPmap->next = NULL;
+ if (localPmap)
+ Xfree(localPmap);
+ }
+ return (result);
+}
+
+
+int PanoramiXFreePixmap(ClientPtr client)
+{
+ PixmapPtr pMap;
+ int result, j;
+ PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot;
+ PanoramiXPmap *pPanoramiXPmapback = NULL;
+ REQUEST(xResourceReq);
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ for (; pPanoramiXPmap && (pPanoramiXPmap->info[0].id != stuff->id);
+ pPanoramiXPmap = pPanoramiXPmap->next)
+ pPanoramiXPmapback = pPanoramiXPmap;
+ if (!pPanoramiXPmap)
+ result = (* SavedProcVector[X_FreePixmap])(client);
+ else {
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->id = pPanoramiXPmap->info[j].id;
+ result = (* SavedProcVector[X_FreePixmap])(client);
+ }
+ if ((result == Success) && pPanoramiXPmapback &&
+ pPanoramiXPmap && pPanoramiXPmap->FreeMe ) {
+ pPanoramiXPmapback->next = pPanoramiXPmap->next;
+ Xfree(pPanoramiXPmap);
+ }
+ }
+ return (result);
+}
+
+
+int PanoramiXCreateGC(register ClientPtr client)
+{
+ int result, j;
+ GC *pGC;
+ DrawablePtr pDraw;
+ unsigned len, i;
+ REQUEST(xCreateGCReq);
+ GContext GCID;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *localGC;
+ PanoramiXGC *pPanoramiXGC;
+ PanoramiXPmap *pPanoramiXTile = NULL, *pPanoramiXStip = NULL;
+ PanoramiXPmap *pPanoramiXClip = NULL;
+ int tile_offset, stip_offset, clip_offset;
+ XID orig_GC;
+
+ REQUEST_AT_LEAST_SIZE(xCreateGCReq);
+ client->errorValue = stuff->gc;
+ pDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable,
+RC_DRAWABLE,
+ SecurityReadAccess);
+ IF_RETURN(!pDraw, BadDrawable);
+ pPanoramiXWin = (pDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+
+ len = client->req_len - (sizeof(xCreateGCReq) >> 2);
+ IF_RETURN((len != Ones((Mask)stuff->mask)), BadLength);
+ localGC = (PanoramiXGC *) Xcalloc(sizeof(PanoramiXGC));
+ IF_RETURN(!localGC, BadAlloc);
+ orig_GC = stuff->gc;
+ if ((Mask)stuff->mask & GCTile) {
+ XID tileID;
+
+ tile_offset = Ones((Mask)stuff->mask & (GCTile - 1));
+ tileID = *((CARD32 *) &stuff[1] + tile_offset);
+ if (tileID) {
+ pPanoramiXTile = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXTile, tileID);
+ }
+ }
+ if ((Mask)stuff->mask & GCStipple) {
+ XID stipID;
+
+ stip_offset = Ones((Mask)stuff->mask & (GCStipple - 1));
+ stipID = *((CARD32 *) &stuff[1] + stip_offset);
+ if (stipID) {
+ pPanoramiXStip = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXStip, stipID);
+ }
+ }
+ if ((Mask)stuff->mask & GCClipMask) {
+ XID clipID;
+
+ clip_offset = Ones((Mask)stuff->mask & (GCClipMask - 1));
+ clipID = *((CARD32 *) &stuff[1] + clip_offset);
+ if (clipID) {
+ pPanoramiXClip = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXClip, clipID);
+ }
+ }
+ FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) {
+ GCID = j ? FakeClientID(client->index) : orig_GC;
+ localGC->info[j].id = GCID;
+ }
+ localGC->FreeMe = FALSE;
+ PANORAMIXFIND_LAST(pPanoramiXGC, PanoramiXGCRoot);
+ pPanoramiXGC->next = localGC;
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->gc = localGC->info[j].id;
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ if (pPanoramiXTile)
+ *((CARD32 *) &stuff[1] + tile_offset) = pPanoramiXTile->info[j].id;
+ if (pPanoramiXStip)
+ *((CARD32 *) &stuff[1] + stip_offset) = pPanoramiXStip->info[j].id;
+ if (pPanoramiXClip)
+ *((CARD32 *) &stuff[1] + clip_offset) = pPanoramiXClip->info[j].id;
+ result = (* SavedProcVector[X_CreateGC])(client);
+ BREAK_IF(result != Success);
+ }
+ if (result != Success) {
+ pPanoramiXGC->next = NULL;
+ Xfree(localGC);
+ }
+ return (result);
+}
+
+
+int PanoramiXChangeGC(ClientPtr client)
+{
+ GC *pGC;
+ REQUEST(xChangeGCReq);
+ int result, j;
+ unsigned len;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ PanoramiXPmap *pPanoramiXTile = NULL, *pPanoramiXStip = NULL;
+ PanoramiXPmap *pPanoramiXClip = NULL;
+ int tile_offset, stip_offset, clip_offset;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_AT_LEAST_SIZE(xChangeGCReq);
+ VERIFY_GC(pGC, stuff->gc, client);
+ len = client->req_len - (sizeof(xChangeGCReq) >> 2);
+ IF_RETURN((len != Ones((Mask)stuff->mask)), BadLength);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ if ((Mask)stuff->mask & GCTile) {
+ XID tileID;
+
+ tile_offset = Ones((Mask)stuff->mask & (GCTile -1) );
+ tileID = *((CARD32 *) &stuff[1] + tile_offset);
+ if (tileID) {
+ pPanoramiXTile = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXTile, tileID);
+ }
+ }
+ if ((Mask)stuff->mask & GCStipple) {
+ XID stipID;
+
+ stip_offset = Ones((Mask)stuff->mask & (GCStipple -1 ));
+ stipID = *((CARD32 *) &stuff[1] + stip_offset);
+ if (stipID) {
+ pPanoramiXStip = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXStip, stipID);
+ }
+ }
+ if ((Mask)stuff->mask & GCClipMask) {
+ XID clipID;
+
+ clip_offset = Ones((Mask)stuff->mask & (GCClipMask -1));
+ clipID = *((CARD32 *) &stuff[1] + clip_offset);
+ if (clipID) {
+ pPanoramiXClip = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXClip, clipID);
+ }
+ }
+ FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) {
+ stuff->gc = pPanoramiXGC->info[j].id;
+ if (pPanoramiXTile)
+ *((CARD32 *) &stuff[1] + tile_offset) = pPanoramiXTile->info[j].id;
+ if (pPanoramiXStip)
+ *((CARD32 *) &stuff[1] + stip_offset) = pPanoramiXStip->info[j].id;
+ if (pPanoramiXClip)
+ *((CARD32 *) &stuff[1] + clip_offset) = pPanoramiXClip->info[j].id;
+ result = (* SavedProcVector[X_ChangeGC])(client);
+ BREAK_IF(result != Success);
+ }
+ PANORAMIX_FREE(client);
+ return (result);
+}
+
+
+int PanoramiXCopyGC(ClientPtr client)
+{
+ int j, result;
+ PanoramiXGC *pPanoramiXGCSrc = PanoramiXGCRoot;
+ PanoramiXGC *pPanoramiXGCDst = PanoramiXGCRoot;
+ REQUEST(xCopyGCReq);
+
+ REQUEST_SIZE_MATCH(xCopyGCReq);
+ PANORAMIXFIND_ID(pPanoramiXGCSrc, stuff->srcGC);
+ IF_RETURN(!pPanoramiXGCSrc, BadGC);
+ PANORAMIXFIND_ID(pPanoramiXGCDst, stuff->dstGC);
+ IF_RETURN(!pPanoramiXGCDst, BadGC);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXGCDst, j) {
+ stuff->srcGC = pPanoramiXGCSrc->info[j].id;
+ stuff->dstGC = pPanoramiXGCDst->info[j].id;
+ result = (* SavedProcVector[X_CopyGC])(client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+
+
+int PanoramiXSetDashes(ClientPtr client)
+{
+ GC *pGC;
+ REQUEST(xSetDashesReq);
+ int result, j;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+
+ REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
+ VERIFY_GC(pGC, stuff->gc, client);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) {
+ stuff->gc = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_SetDashes])(client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+
+
+int PanoramiXSetClipRectangles(register ClientPtr client)
+{
+ int result;
+ register GC *pGC;
+ REQUEST(xSetClipRectanglesReq);
+ int j;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+
+ REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) {
+ stuff->gc = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_SetClipRectangles])(client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+
+
+int PanoramiXFreeGC(ClientPtr client)
+{
+ register GC *pGC;
+ REQUEST(xResourceReq);
+ int result, j;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ PanoramiXGC *pPanoramiXGCback = NULL;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ for (; pPanoramiXGC && (pPanoramiXGC->info[0].id != stuff->id);
+ pPanoramiXGC = pPanoramiXGC->next)
+ pPanoramiXGCback = pPanoramiXGC;
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXGC, j) {
+ stuff->id = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_FreeGC])(client);
+ BREAK_IF(result != Success);
+ }
+ if ((result == Success) && pPanoramiXGCback &&
+ pPanoramiXGC && pPanoramiXGC->FreeMe) {
+ pPanoramiXGCback->next = pPanoramiXGC->next;
+ if (pPanoramiXGC)
+ Xfree(pPanoramiXGC);
+ }
+ PANORAMIX_FREE(client);
+ return (result);
+}
+
+
+int PanoramiXClearToBackground(register ClientPtr client)
+{
+ REQUEST(xClearAreaReq);
+ register WindowPtr pWin;
+ int result, j;
+ Window winID;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ int orig_x, orig_y;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xClearAreaReq);
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->window);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ orig_x = stuff->x;
+ orig_y = stuff->y;
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ winID = pPanoramiXWin->info[j].id;
+ pWin = (WindowPtr) SecurityLookupWindow(winID, client, SecurityReadAccess);
+ if (!pWin) {
+ client->errorValue = pPanoramiXWin->info[0].id;
+ return (BadWindow);
+ }
+ stuff->window = winID;
+ if (pWin->drawable.id == PanoramiXWinRoot->info[j].id) {
+ stuff->x = orig_x - panoramiXdataPtr[j].x;
+ stuff->y = orig_y - panoramiXdataPtr[j].y;
+ }
+ result = (*SavedProcVector[X_ClearArea])(client);
+ }
+ PANORAMIX_FREE(client);
+ return (result);
+}
+
+
+int PanoramiXCopyArea(ClientPtr client)
+{
+ int j, result;
+ Window srcID, dstID;
+ DrawablePtr pSrc, pDst;
+ GContext GCID;
+ GC *pGC;
+ PanoramiXWindow *pPanoramiXSrcRoot;
+ PanoramiXWindow *pPanoramiXDstRoot;
+ PanoramiXWindow *pPanoramiXSrc;
+ PanoramiXWindow *pPanoramiXDst;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ REQUEST(xCopyAreaReq);
+ int srcx = stuff->srcX, srcy = stuff->srcY;
+ int dstx = stuff->dstX, dsty = stuff->dstY;
+
+ REQUEST_SIZE_MATCH(xCopyAreaReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client);
+ if (stuff->dstDrawable != stuff->srcDrawable) {
+ VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client);
+ if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) {
+ client->errorValue = stuff->dstDrawable;
+ return (BadMatch);
+ }
+ } else {
+ pSrc = pDst;
+ }
+ pPanoramiXSrcRoot = (pSrc->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ pPanoramiXDstRoot = (pDst->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ pPanoramiXSrc = pPanoramiXSrcRoot;
+ pPanoramiXDst = pPanoramiXDstRoot;
+ PANORAMIXFIND_ID(pPanoramiXSrc, stuff->srcDrawable);
+ IF_RETURN(!pPanoramiXSrc, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXDst, stuff->dstDrawable);
+ IF_RETURN(!pPanoramiXDst, BadDrawable);
+ GCID = stuff->gc;
+ PANORAMIXFIND_ID(pPanoramiXGC, GCID);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+
+ FOR_NSCREENS_OR_ONCE(pPanoramiXSrc, j) {
+ stuff->dstDrawable = pPanoramiXDst->info[j].id;
+ stuff->srcDrawable = pPanoramiXSrc->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ if (pPanoramiXSrc == pPanoramiXSrcRoot) {
+ stuff->srcX = srcx - panoramiXdataPtr[j].x;
+ stuff->srcY = srcy - panoramiXdataPtr[j].y;
+ }
+ if (pPanoramiXDst == pPanoramiXDstRoot) {
+ stuff->dstX = dstx - panoramiXdataPtr[j].x;
+ stuff->dstY = dsty - panoramiXdataPtr[j].y;
+ }
+ result = (* SavedProcVector[X_CopyArea])(client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+
+int PanoramiXCopyPlane(ClientPtr client)
+{
+ int SrcScr = -1, DstScr = -1;
+ PixmapPtr pMap = NULL;
+ Pixmap pmapID;
+ PanoramiXRect SrcRect, DstRect;
+ int i, j, k;
+ Window srcID, dstID;
+ DrawablePtr pSrc, pDst;
+ GContext GCID;
+ GContext GCIDbase;
+ GC *pGC;
+ PanoramiXWindow *pPanoramiXSrc;
+ PanoramiXWindow *pPanoramiXDst;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ RegionPtr *PanoramiXRgnPtrs;
+ RegionPtr *FetchRgnPtrs = NULL;
+ RegionPtr pRgn;
+ REQUEST(xCopyPlaneReq);
+ int srcx = stuff->srcX, srcy = stuff->srcY;
+ int dstx = stuff->dstX, dsty = stuff->dstY;
+ int width = stuff->width, height = stuff->height;
+
+ REQUEST_SIZE_MATCH(xCopyPlaneReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, pGC, client);
+ if (stuff->dstDrawable != stuff->srcDrawable) {
+ VERIFY_DRAWABLE(pSrc, stuff->srcDrawable, client);
+ if (pDst->pScreen != pSrc->pScreen) {
+ client->errorValue = stuff->dstDrawable;
+ return (BadMatch);
+ }
+ } else {
+ pSrc = pDst;
+ }
+
+ /*
+ * Check to see if stuff->bitPlane has exactly ONE good bit set
+ */
+
+
+ if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
+ (stuff->bitPlane > (1L << (pSrc->depth - 1))))
+ {
+ client->errorValue = stuff->bitPlane;
+ return(BadValue);
+ }
+
+ pPanoramiXSrc = (pSrc->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ pPanoramiXDst = (pDst->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXSrc, stuff->srcDrawable);
+ IF_RETURN(!pPanoramiXSrc, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXDst, stuff->dstDrawable);
+ IF_RETURN(!pPanoramiXDst, BadDrawable);
+ GCIDbase = stuff->gc;
+ PANORAMIXFIND_ID(pPanoramiXGC, GCIDbase);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+
+ /*
+ * Unless both are pixmaps, need to do special things to accomodate
+ * being on multiple screens, different screens, etc.
+ */
+
+ if (pSrc->type != DRAWABLE_PIXMAP) {
+ SrcRect.x = pSrc->x + srcx;
+ SrcRect.y = pSrc->y + srcy;
+ SrcRect.width = width;
+ SrcRect.height = height;
+ for (SrcScr = PanoramiXNumScreens - 1; SrcScr>=0; SrcScr-- )
+ if (RECTA_SUBSUMES_RECTB(panoramiXdataPtr[SrcScr], SrcRect))
+ break;
+ }
+ if (pDst->type != DRAWABLE_PIXMAP) {
+ DstRect.x = pDst->x + dstx;
+ DstRect.y = pDst->y + dsty;
+ DstRect.width = width;
+ DstRect.height = height;
+ for (DstScr = PanoramiXNumScreens - 1; DstScr>=0; DstScr--)
+ if (RECTA_SUBSUMES_RECTB(panoramiXdataPtr[DstScr], DstRect))
+ break;
+ }
+
+ /*
+ * If source is on multiple screens, different screen from destination,
+ * destination is on multiple screens, or destination is a pixmap,
+ * need to get info into local pixmap for subsequent transfer.
+ */
+
+
+ if ((pSrc->type != DRAWABLE_PIXMAP) &&
+ (SrcScr < 0 || DstScr < 0 || SrcScr != DstScr
+ || pDst->type == DRAWABLE_PIXMAP)) {
+ unsigned char save_alu;
+ RegionRec tempReg;
+ RegionPtr pCompositeClip;
+ PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot;
+
+ pMap = (PixmapPtr) (*pSrc->pScreen->CreatePixmap)(pSrc->pScreen,
+ width, height, pGC->depth);
+ PANORAMIXFIND_LAST(pPanoramiXPmap, PanoramiXPmapRoot);
+ pPanoramiXPmap->next =
+ (PanoramiXPmap *)Xcalloc(sizeof(PanoramiXPmap));
+ pPanoramiXPmap = pPanoramiXPmap->next;
+ pmapID = FakeClientID(0);
+ AddResource(pmapID, RT_PIXMAP, (pointer)pMap);
+ for (j = PanoramiXNumScreens - 1; j>=0; j--)
+ pPanoramiXPmap->info[j].id = pmapID;
+ tempReg.extents.x1 = 0;
+ tempReg.extents.y1 = 0;
+ tempReg.extents.x2 = width;
+ tempReg.extents.y2 = height;
+ tempReg.data = NULL;
+ FetchRgnPtrs =
+ (RegionPtr *) ALLOCATE_LOCAL(PanoramiXNumScreens * sizeof(RegionPtr));
+ i = 0;
+ FOR_NSCREENS_OR_ONCE(pPanoramiXSrc, j) {
+ if ((SrcScr >= 0) && pPanoramiXSrc)
+ j = SrcScr;
+ srcID = pPanoramiXSrc->info[j].id;
+ pSrc = (DrawablePtr) SecurityLookupIDByClass(client, srcID, RC_DRAWABLE,
+ SecurityReadAccess);
+ GCID = pPanoramiXGC->info[j].id;
+ pGC = (GC *) LookupIDByType(GCID, RT_GC);
+ pMap->drawable.pScreen = pSrc->pScreen;
+ pGC->pScreen = pSrc->pScreen;
+ save_alu = pGC->alu;
+ pGC->alu = GXcopy;
+ pCompositeClip = ((miPrivGC*)
+ (pGC->devPrivates[miGCPrivateIndex].ptr))->pCompositeClip;
+ ((miPrivGC*)(pGC->devPrivates[miGCPrivateIndex].ptr))->pCompositeClip =
+&tempReg;
+ FetchRgnPtrs[i++] = (*pGC->ops->CopyPlane)(pSrc, (DrawablePtr) pMap,
+ pGC, srcx, srcy, width, height, 0, 0, stuff->bitPlane);
+ pGC->alu = save_alu;
+ ((miPrivGC*) (pGC->devPrivates[miGCPrivateIndex].ptr))->pCompositeClip =
+pCompositeClip;
+ if (SrcScr >= 0)
+ j = 0;
+ }
+ }
+
+ if (pMap) {
+ pSrc = (DrawablePtr) pMap;
+ srcx = 0;
+ srcy = 0;
+ }
+ PanoramiXRgnPtrs =
+ (RegionPtr *) ALLOCATE_LOCAL(PanoramiXNumScreens * sizeof(RegionPtr));
+ k = 0;
+ /* if src and dst are entirely on one screen,
+ then we only need one simple transfer */
+ if ((DstScr >= 0) && (pMap || (SrcScr >=0))) {
+ dstID = pPanoramiXDst->info[DstScr].id;
+ pDst = (DrawablePtr) SecurityLookupIDByClass(client, dstID, RC_DRAWABLE,
+ SecurityReadAccess);
+ GCID = pPanoramiXGC->info[DstScr].id;
+ pGC = (GC *) LookupIDByType(GCID, RT_GC);
+ ValidateGC(pDst, pGC);
+ if (pMap) {
+ pMap->drawable.pScreen = pDst->pScreen;
+ } else {
+ srcID = pPanoramiXSrc->info[SrcScr].id;
+ if (srcID != dstID) {
+ pSrc = (DrawablePtr) SecurityLookupIDByClass(client, srcID, RC_DRAWABLE,
+ SecurityReadAccess);
+ } else
+ pSrc = pDst;
+ }
+ if (pMap)
+ PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
+ srcx, srcy, width, height, dstx, dsty,
+ 1);
+ else
+ PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
+ srcx, srcy, width, height, dstx, dsty,
+ stuff->bitPlane);
+ }else {
+ FOR_NSCREENS_OR_ONCE(pPanoramiXDst, j) {
+ if (DstScr >= 0) {
+ dstID = pPanoramiXDst->info[DstScr].id;
+ GCID = pPanoramiXGC->info[DstScr].id;
+ } else {
+ dstID = pPanoramiXDst->info[j].id;
+ GCID = pPanoramiXGC->info[j].id;
+ }
+ pDst = (DrawablePtr) SecurityLookupIDByClass(client, dstID, RC_DRAWABLE,
+ SecurityReadAccess);
+ pGC = (GC *) LookupIDByType(GCID, RT_GC);
+ ValidateGC(pDst, pGC);
+ if (pMap) {
+ pMap->drawable.pScreen = pDst->pScreen;
+ } else {
+ srcID = pPanoramiXSrc->info[j].id;
+ if (srcID != dstID) {
+ pSrc = (DrawablePtr) SecurityLookupIDByClass(client, srcID, RC_DRAWABLE,
+ SecurityReadAccess);
+ } else {
+ pSrc = pDst;
+ }
+ }
+ if (pMap)
+ PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
+ srcx, srcy, width, height, dstx, dsty,
+ 1);
+ else
+ PanoramiXRgnPtrs[k++] = (*pGC->ops->CopyPlane)(pSrc, pDst, pGC,
+ srcx, srcy, width, height, dstx, dsty,
+ stuff->bitPlane);
+ }
+ }
+
+ if (pMap) {
+ for (j = PanoramiXNumScreens - 1; j>=0; j--)
+ if (PanoramiXRgnPtrs[j])
+ (*pDst->pScreen->RegionDestroy) (PanoramiXRgnPtrs[j]);
+ DEALLOCATE_LOCAL(PanoramiXRgnPtrs);
+ PanoramiXRgnPtrs = FetchRgnPtrs;
+ k = i;
+ }
+ j = 1;
+ i = 0;
+ pRgn = PanoramiXRgnPtrs[i];
+ while ((j < k) && pRgn && !REGION_NIL(pRgn)) {
+ if (PanoramiXRgnPtrs[j]) {
+ (*pGC->pScreen->Intersect)(pRgn, pRgn, PanoramiXRgnPtrs[j++]);
+ } else {
+ pRgn = PanoramiXRgnPtrs[i++];
+ }
+ }
+ for (j = 0 ; j < k; j++) {
+ pRgn = PanoramiXRgnPtrs[j];
+ GCID = pPanoramiXGC->info[j].id;
+ pGC = (GC *) LookupIDByType(GCID, RT_GC);
+ if (pGC && pGC->graphicsExposures)
+ (*pDst->pScreen->SendGraphicsExpose) (client, pRgn,
+ stuff->dstDrawable, X_CopyPlane, 0);
+ if (pRgn)
+ (*pDst->pScreen->RegionDestroy) (pRgn);
+ }
+ DEALLOCATE_LOCAL(PanoramiXRgnPtrs);
+ if (pMap) {
+ PanoramiXPmap *pPanoramiXPmap = PanoramiXPmapRoot;
+ PanoramiXPmap *pback = PanoramiXPmapRoot;
+
+ for (; pPanoramiXPmap && (pPanoramiXPmap->info[0].id != pmapID);
+ pPanoramiXPmap = pPanoramiXPmap->next)
+ pback = pPanoramiXPmap;
+ FreeResource(pPanoramiXPmap->info[0].id, RT_NONE);
+ if (pback) {
+ pback->next = pPanoramiXPmap->next;
+ Xfree(pPanoramiXPmap);
+ }
+ }
+ return (client->noClientException);
+}
+
+
+int PanoramiXPolyPoint(ClientPtr client)
+{
+ int result, npoint, i, j;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr locDraw;
+ int x_off = 0, y_off = 0;
+ xPoint *origPts;
+ xPoint *origPtr, *modPtr;
+ REQUEST(xPolyPointReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyPointReq);
+ locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable,
+RC_DRAWABLE,
+ SecurityReadAccess);
+ IF_RETURN(!locDraw, BadDrawable);
+ pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, locDraw->id);
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ npoint = ((client->req_len << 2) - sizeof(xPolyPointReq)) >> 2;
+ if (npoint > 0) {
+ origPts = (xPoint *) ALLOCATE_LOCAL(npoint * sizeof(xPoint));
+ memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint));
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ if (pPanoramiXWin == PanoramiXWinRoot) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }else {
+ if ( (locDraw->type == DRAWABLE_PIXMAP) &&
+ /* add special case check for root window */
+ (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }
+ }
+ modPtr = (xPoint *) &stuff[1];
+ origPtr = origPts;
+ for (i = npoint; i; i--) {
+ modPtr->x = origPtr->x - x_off;
+ modPtr++->y = origPtr++->y - y_off;
+ }
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_PolyPoint])(client);
+ BREAK_IF(result != Success);
+ }
+ DEALLOCATE_LOCAL(origPts);
+ return (result);
+ }else
+ return (client->noClientException);
+
+}
+
+
+int PanoramiXPolyLine(ClientPtr client)
+{
+ int result, npoint, i, j;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr locDraw;
+ int x_off = 0, y_off = 0;
+ xPoint *origPts;
+ xPoint *origPtr, *modPtr;
+ REQUEST(xPolyLineReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyLineReq);
+ locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable,
+RC_DRAWABLE,
+ SecurityReadAccess);
+ IF_RETURN(!locDraw, BadDrawable);
+ pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, locDraw->id);
+ /* In the case of Multibuffering, we need to make sure the drawable
+ isn't really a pixmap associated to a drawable */
+ if (!pPanoramiXWin && (stuff->drawable != locDraw->id)) {
+ pPanoramiXWin = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ }
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ npoint = ((client->req_len << 2) - sizeof(xPolyLineReq)) >> 2;
+ if (npoint > 0){
+ origPts = (xPoint *) ALLOCATE_LOCAL(npoint * sizeof(xPoint));
+ memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint));
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ if (pPanoramiXWin == PanoramiXWinRoot) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }else {
+ if ( (locDraw->type == DRAWABLE_PIXMAP) &&
+ /* add special case check for root window */
+ (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }
+ }
+ modPtr = (xPoint *) &stuff[1];
+ origPtr = origPts;
+ for (i = npoint; i; i--) {
+ modPtr->x = origPtr->x - x_off;
+ modPtr++->y = origPtr++->y - y_off;
+ }
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_PolyLine])(client);
+ BREAK_IF(result != Success);
+ }
+ DEALLOCATE_LOCAL(origPts);
+ return (result);
+ }else
+ return (client->noClientException);
+}
+
+
+int PanoramiXPolySegment(ClientPtr client)
+{
+ int result, nsegs, i, j;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr locDraw;
+ int x_off = 0, y_off = 0;
+ xSegment *origSegs;
+ xSegment *origPtr, *modPtr;
+ REQUEST(xPolySegmentReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
+ locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable,
+RC_DRAWABLE,
+ SecurityReadAccess);
+ IF_RETURN(!locDraw, BadDrawable);
+ pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ /* In the case of Multibuffering, we need to make sure the drawable
+ isn't really a pixmap associated to a drawable */
+ if (!pPanoramiXWin && (stuff->drawable != locDraw->id)) {
+ pPanoramiXWin = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ }
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
+ IF_RETURN((nsegs & 4), BadLength);
+ nsegs >>= 3;
+ if (nsegs > 0) {
+ origSegs = (xSegment *) ALLOCATE_LOCAL(nsegs * sizeof(xSegment));
+ memcpy((char *) origSegs, (char *) &stuff[1], nsegs *
+sizeof(xSegment));
+ FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) {
+ if (pPanoramiXWin == PanoramiXWinRoot) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }else {
+ if ( (locDraw->type == DRAWABLE_PIXMAP) &&
+ /* add special case check for root window */
+ (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }
+ }
+ modPtr = (xSegment *) &stuff[1];
+ origPtr = origSegs;
+ for (i = nsegs; i; i--) {
+ modPtr->x1 = origPtr->x1 - x_off;
+ modPtr->y1 = origPtr->y1 - y_off;
+ modPtr->x2 = origPtr->x2 - x_off;
+ modPtr++->y2 = origPtr++->y2 - y_off;
+ }
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_PolySegment])(client);
+ BREAK_IF(result != Success);
+ }
+ DEALLOCATE_LOCAL(origSegs);
+ return (result);
+ }else
+ return (client->noClientException);
+}
+
+
+int PanoramiXPolyRectangle(ClientPtr client)
+{
+ int result, nrects, i, j;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr locDraw;
+ int x_off = 0, y_off = 0;
+ xRectangle *origRecs;
+ xRectangle *origPtr, *modPtr;
+ REQUEST(xPolyRectangleReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
+ locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable,
+RC_DRAWABLE,
+ SecurityReadAccess);
+ IF_RETURN(!locDraw, BadDrawable);
+ pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
+ IF_RETURN((nrects & 4), BadLength);
+ nrects >>= 3;
+ if (nrects > 0){
+ origRecs = (xRectangle *) ALLOCATE_LOCAL(nrects * sizeof(xRectangle));
+ memcpy((char *) origRecs, (char *) &stuff[1], nrects *
+sizeof(xRectangle));
+ FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) {
+ if (pPanoramiXWin == PanoramiXWinRoot) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }else {
+ if ( (locDraw->type == DRAWABLE_PIXMAP) &&
+ /* add special case check for root window */
+ (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }
+ }
+ modPtr = (xRectangle *) &stuff[1];
+ origPtr = origRecs;
+ for (i = nrects; i; i--) {
+ modPtr->x = origPtr->x - x_off;
+ modPtr->y = origPtr->y - y_off;
+ modPtr->width = origPtr->width - x_off;
+ modPtr++->height = origPtr++->height - y_off;
+ }
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_PolyRectangle])(client);
+ BREAK_IF(result != Success);
+ }
+ DEALLOCATE_LOCAL(origRecs);
+ return (result);
+ }else
+ return (client->noClientException);
+}
+
+
+int PanoramiXPolyArc(ClientPtr client)
+{
+ int result, narcs, i, j;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr locDraw;
+ GCPtr locGC;
+ int x_off = 0, y_off = 0;
+ xArc *origArcs;
+ xArc *origPtr, *modPtr;
+ REQUEST(xPolyArcReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyArcReq);
+ locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable,
+RC_DRAWABLE,
+ SecurityReadAccess);
+ IF_RETURN(!locDraw, BadDrawable);
+ pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot :
+PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
+ IF_RETURN((narcs % sizeof(xArc)), BadLength);
+ narcs /= sizeof(xArc);
+ if (narcs > 0){
+ origArcs = (xArc *) ALLOCATE_LOCAL(narcs * sizeof(xArc));
+ memcpy((char *) origArcs, (char *) &stuff[1], narcs * sizeof(xArc));
+ FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) {
+ if (pPanoramiXWin == PanoramiXWinRoot) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }else {
+ if ( (locDraw->type == DRAWABLE_PIXMAP) &&
+ /* add special case check for root window */
+ (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }
+ }
+ modPtr = (xArc *) &stuff[1];
+ origPtr = origArcs;
+ for (i = narcs; i; i--) {
+ modPtr->x = origPtr->x - x_off;
+ modPtr++->y = origPtr++->y - y_off;
+ }
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_PolyArc])(client);
+ BREAK_IF(result != Success);
+ }
+ DEALLOCATE_LOCAL(origArcs);
+ return (result);
+ }else
+ return (client->noClientException);
+}
+
+
+int PanoramiXFillPoly(ClientPtr client)
+{
+ int result, count, i, j;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr locDraw;
+ GCPtr locGC;
+ int x_off = 0, y_off = 0;
+ DDXPointPtr locPts;
+ DDXPointPtr origPts, modPts;
+ REQUEST(xFillPolyReq);
+
+ REQUEST_AT_LEAST_SIZE(xFillPolyReq);
+ locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable,
+RC_DRAWABLE,
+ SecurityReadAccess);
+ IF_RETURN(!locDraw, BadDrawable);
+ pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ count = ((client->req_len << 2) - sizeof(xFillPolyReq)) >> 2;
+ if (count > 0){
+ locPts = (DDXPointPtr) ALLOCATE_LOCAL(count * sizeof(DDXPointRec));
+ memcpy((char *) locPts, (char *) &stuff[1], count *
+sizeof(DDXPointRec));
+ FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) {
+ if (pPanoramiXWin == PanoramiXWinRoot) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }else {
+ if ( (locDraw->type == DRAWABLE_PIXMAP) &&
+ /* add special case check for root window */
+ (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }
+ }
+ modPts = (DDXPointPtr) &stuff[1];
+ origPts = locPts;
+ for (i = count; i; i--) {
+ modPts->x = origPts->x - x_off;
+ modPts++->y = origPts++->y - y_off;
+ }
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_FillPoly])(client);
+ BREAK_IF(result != Success);
+ }
+ DEALLOCATE_LOCAL(locPts);
+ return (result);
+ }else
+ return (client->noClientException);
+}
+
+
+int PanoramiXPolyFillRectangle(ClientPtr client)
+{
+ int result, things, i, j;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr locDraw;
+ GCPtr locGC;
+ int x_off = 0, y_off = 0;
+ xRectangle *origThings;
+ xRectangle *origPtr, *modPtr;
+ REQUEST(xPolyFillRectangleReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
+ locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable,
+RC_DRAWABLE,
+ SecurityReadAccess);
+ IF_RETURN(!locDraw, BadDrawable);
+ pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot :
+PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
+ IF_RETURN((things & 4), BadLength);
+ things >>= 3;
+ if (things > 0){
+ origThings = (xRectangle *) ALLOCATE_LOCAL(things * sizeof(xRectangle));
+ memcpy((char *) origThings, (char *)&stuff[1], things *
+sizeof(xRectangle));
+ FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) {
+ if (pPanoramiXWin == PanoramiXWinRoot) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }else {
+ if ( (locDraw->type == DRAWABLE_PIXMAP) &&
+ /* add special case check for root window */
+ (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }
+ }
+ modPtr = (xRectangle *) &stuff[1];
+ origPtr = origThings;
+ for (i = things; i; i--) {
+ modPtr->x = origPtr->x - x_off;
+ modPtr++->y = origPtr++->y - y_off;
+ }
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_PolyFillRectangle])(client);
+ BREAK_IF(result != Success);
+ }
+ DEALLOCATE_LOCAL(origThings);
+ return (result);
+ }else
+ return (client->noClientException);
+}
+
+
+int PanoramiXPolyFillArc(ClientPtr client)
+{
+ int result, arcs, i, j;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr locDraw;
+ GCPtr locGC;
+ int x_off = 0, y_off = 0;
+ xArc *origArcs;
+ xArc *origPtr, *modPtr;
+ REQUEST(xPolyFillArcReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
+ locDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable,
+RC_DRAWABLE,
+ SecurityReadAccess);
+ IF_RETURN(!locDraw, BadDrawable);
+ pPanoramiXWin = (locDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot :
+PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ arcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
+ IF_RETURN((arcs % sizeof(xArc)), BadLength);
+ arcs /= sizeof(xArc);
+ if (arcs > 0) {
+ origArcs = (xArc *) ALLOCATE_LOCAL(arcs * sizeof(xArc));
+ memcpy((char *) origArcs, (char *)&stuff[1], arcs * sizeof(xArc));
+ FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) {
+ if (pPanoramiXWin == PanoramiXWinRoot) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }else {
+ if ( (locDraw->type == DRAWABLE_PIXMAP) &&
+ /* add special case check for root window */
+ (locDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ x_off = panoramiXdataPtr[j].x;
+ y_off = panoramiXdataPtr[j].y;
+ }
+ }
+ modPtr = (xArc *) &stuff[1];
+ origPtr = origArcs;
+ for (i = arcs; i; i--) {
+ modPtr->x = origPtr->x - x_off;
+ modPtr++->y = origPtr++->y - y_off;
+ }
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_PolyFillArc])(client);
+ BREAK_IF(result != Success);
+ }
+ DEALLOCATE_LOCAL(origArcs);
+ return (result);
+ }else
+ return (client->noClientException);
+}
+
+
+/* 64-bit server notes: the protocol restricts padding of images to
+ * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
+ * to use internally. Removes need for internal alignment checking.
+ * All of the PutImage functions could be changed individually, but
+ * as currently written, they call other routines which require things
+ * to be 64-bit padded on scanlines, so we changed things here.
+ * If an image would be padded differently for 64- versus 32-, then
+ * copy each scanline to a 64-bit padded scanline.
+ * Also, we need to make sure that the image is aligned on a 64-bit
+ * boundary, even if the scanlines are padded to our satisfaction.
+ */
+
+int PanoramiXPutImage(register ClientPtr client)
+{
+ register GC *pGC;
+ register DrawablePtr pDraw;
+ long lengthProto, /* length of scanline protocl padded */
+ length; /* length of scanline server padded */
+ char *tmpImage;
+ int j;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXWindow *pPanoramiXRoot;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ int orig_x, orig_y;
+ int result;
+
+
+ REQUEST(xPutImageReq);
+
+ REQUEST_AT_LEAST_SIZE(xPutImageReq);
+ pDraw = (DrawablePtr) SecurityLookupIDByClass(client, stuff->drawable,
+RC_DRAWABLE,
+ SecurityReadAccess);
+ IF_RETURN(!pDraw, BadDrawable);
+ pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ pPanoramiXWin = pPanoramiXRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ IF_RETURN(!pPanoramiXWin,BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ orig_x = stuff->dstX;
+ orig_y = stuff->dstY;
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ if (pPanoramiXWin == pPanoramiXRoot) {
+ stuff->dstX = orig_x - panoramiXdataPtr[j].x;
+ stuff->dstY = orig_y - panoramiXdataPtr[j].y;
+ }
+ if (pDraw->type == DRAWABLE_PIXMAP) {
+ if (stuff->width > panoramiXdataPtr[j].width)
+ stuff->dstX = orig_x - panoramiXdataPtr[j].x;
+ if (stuff->height > panoramiXdataPtr[j].height)
+ stuff->dstY = orig_y - panoramiXdataPtr[j].y;
+ }
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ result = (* SavedProcVector[X_PutImage])(client);
+ }
+ return(result);
+}
+
+
+typedef struct _SrcParts{
+ int x1, y1, x2, y2, width, ByteWidth;
+ char *buf;
+} SrcPartsRec;
+
+
+int PanoramiXGetImage(register ClientPtr client)
+{
+ register DrawablePtr pDraw;
+ int nlines, linesPerBuf;
+ register int height, linesDone;
+ long widthBytesLine, length;
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ long widthBytesLineProto, lengthProto;
+ char *tmpImage;
+#endif
+ Mask plane;
+ char *pBuf;
+ xGetImageReply xgi;
+ int j, k, ScrNum;
+ DrawablePtr locDraw;
+ SrcPartsRec srcParts;
+ BoxRec SrcBox;
+ char *BufPtr, *PartPtr;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+
+ REQUEST(xGetImageReq);
+
+ height = stuff->height;
+ REQUEST_SIZE_MATCH(xGetImageReq);
+ if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) {
+ client->errorValue = stuff->format;
+ return(BadValue);
+ }
+ VERIFY_DRAWABLE(pDraw, stuff->drawable, client);
+ ScrNum = 0;
+ if (stuff->drawable == PanoramiXWinRoot->info[0].id) {
+ for (j = 0; j <= (PanoramiXNumScreens - 1); j++) {
+ ScrNum = j;
+ VERIFY_DRAWABLE(pDraw, pPanoramiXWin->info[ScrNum].id, client);
+ if (stuff->x < panoramiXdataPtr[ScrNum].x &&
+ stuff->y < panoramiXdataPtr[ScrNum].y )
+ break;
+ }
+ }
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ if (!((WindowPtr) pDraw)->realized /* Check for viewable */
+ || pDraw->x + stuff->x < 0 /* Check for on screen */
+ || pDraw->x + stuff->x + (int)stuff->width > PanoramiXPixWidth
+ || pDraw->y + stuff->y < 0
+ || pDraw->y + stuff->y + height > PanoramiXPixHeight
+ || stuff->x < - wBorderWidth((WindowPtr)pDraw) /* Inside border */
+ || stuff->x + (int)stuff->width >
+ wBorderWidth((WindowPtr)pDraw) + (int) pDraw->width
+ + panoramiXdataPtr[ScrNum].x
+ || stuff->y < -wBorderWidth((WindowPtr)pDraw)
+ || stuff->y + height >
+ wBorderWidth ((WindowPtr)pDraw) + (int) pDraw->height
+ + panoramiXdataPtr[ScrNum].y)
+ return(BadMatch);
+ VERIFY_DRAWABLE(pDraw, stuff->drawable, client);
+ xgi.visual = wVisual (((WindowPtr) pDraw));
+ pPanoramiXWin = PanoramiXWinRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ IF_RETURN(!pPanoramiXWin, BadWindow);
+ } else {
+ if (stuff->x < 0 || stuff->x + (int)stuff->width > pDraw->width
+ || stuff->y < 0 || stuff->y + height > pDraw->height)
+ return(BadMatch);
+ xgi.visual = None;
+ }
+ xgi.type = X_Reply;
+ xgi.sequenceNumber = client->sequence;
+ xgi.depth = pDraw->depth;
+ if (stuff->format == ZPixmap) {
+ widthBytesLine = PixmapBytePad(stuff->width, pDraw->depth);
+ length = widthBytesLine * height;
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ widthBytesLineProto = PixmapBytePadProto(stuff->width, pDraw->depth);
+ lengthProto = widthBytesLineProto * height;
+#endif
+ } else {
+ widthBytesLine = BitmapBytePad(stuff->width);
+ plane = ((Mask)1) << (pDraw->depth - 1);
+ /* only planes asked for */
+ length = widthBytesLine * height *
+ Ones(stuff->planeMask & (plane | (plane - 1)));
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ widthBytesLineProto = BitmapBytePadProto(stuff->width);
+ lengthProto = widthBytesLineProto * height *
+ Ones(stuff->planeMask & (plane | (plane - 1)));
+#endif
+ }
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ xgi.length = (lengthProto + 3) >> 2;
+#else
+ xgi.length = (length + 3) >> 2;
+#endif
+
+ if (widthBytesLine == 0 || height == 0) {
+ linesPerBuf = 0;
+ } else if (widthBytesLine >= IMAGE_BUFSIZE) {
+ linesPerBuf = 1;
+ } else {
+ linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
+ if (linesPerBuf > height)
+ linesPerBuf = height;
+ }
+ length = linesPerBuf * widthBytesLine;
+ if (linesPerBuf < height) {
+
+ /*
+ * Have to make sure intermediate buffers don't need padding
+ */
+
+ while ((linesPerBuf > 1)
+ && (length & ((1 << LOG2_BYTES_PER_SCANLINE_PAD)-1))) {
+ linesPerBuf--;
+ length -= widthBytesLine;
+ }
+ while (length & ((1 << LOG2_BYTES_PER_SCANLINE_PAD)-1)) {
+ linesPerBuf++;
+ length += widthBytesLine;
+ }
+ }
+ IF_RETURN((!(pBuf = (char *) ALLOCATE_LOCAL(length))), BadAlloc);
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ /*
+ * Check for protocol/server padding differences
+ */
+
+ if (widthBytesLine != widthBytesLineProto)
+ if (!(tmpImage = (char *) ALLOCATE_LOCAL(length))) {
+ DEALLOCATE_LOCAL(pBuf);
+ return (BadAlloc);
+ }
+#endif
+
+ WriteReplyToClient(client, sizeof (xGetImageReply), &xgi);
+
+ if (linesPerBuf == 0) {
+
+ /*
+ * Nothing to do
+ */
+
+ } else if (stuff->format == ZPixmap) {
+ linesDone = 0;
+ while (height - linesDone > 0) {
+ nlines = min(linesPerBuf, height - linesDone);
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ SrcBox.x1 = pDraw->x + stuff->x;
+ SrcBox.y1 = pDraw->y + stuff->y + linesDone;
+ SrcBox.x2 = SrcBox.x1 + stuff->width;
+ SrcBox.y2 = SrcBox.y1 + nlines;
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+
+ /*
+ * If it isn't even on this screen, just continue.
+ */
+
+ if ((SrcBox.x1 >= panoramiXdataPtr[j].x + panoramiXdataPtr[j].width)
+ || (SrcBox.x2 <= panoramiXdataPtr[j].x)
+ || (SrcBox.y1 >= panoramiXdataPtr[j].y+panoramiXdataPtr[j].height)
+ || (SrcBox.y2 <= panoramiXdataPtr[j].y))
+ continue;
+
+ srcParts.x1 = max(SrcBox.x1 - panoramiXdataPtr[j].x, 0);
+ srcParts.x2 = min(SrcBox.x2 - panoramiXdataPtr[j].x,
+ panoramiXdataPtr[j].width);
+ srcParts.y1 = max(SrcBox.y1 - panoramiXdataPtr[j].y, 0);
+ srcParts.y2 = min(SrcBox.y2 - panoramiXdataPtr[j].y,
+ panoramiXdataPtr[j].height);
+ srcParts.width = srcParts.x2 - srcParts.x1;
+ srcParts.ByteWidth = PixmapBytePad(srcParts.width,pDraw->depth);
+ srcParts.buf = (char *) Xalloc(nlines * srcParts.ByteWidth);
+ locDraw = (DrawablePtr) SecurityLookupIDByClass(client,
+ pPanoramiXWin->info[j].id,
+ RC_DRAWABLE,
+ SecurityReadAccess);
+ (*pDraw->pScreen->GetImage)(locDraw,
+ srcParts.x1 - locDraw->x,
+ srcParts.y1 - locDraw->y,
+ srcParts.width,
+ srcParts.y2 - srcParts.y1,
+ stuff->format,
+ (unsigned long)stuff->planeMask,
+ srcParts.buf);
+ BufPtr = pBuf
+ + srcParts.x1 - stuff->x - (pDraw->x - panoramiXdataPtr[j].x)
+ + widthBytesLine * (srcParts.y1 - stuff->y
+ - (pDraw->y + linesDone - panoramiXdataPtr[j].y));
+ PartPtr = srcParts.buf;
+ for (k = (srcParts.y2 - srcParts.y1); k; k--) {
+ bcopy(PartPtr, BufPtr, srcParts.width);
+ BufPtr += widthBytesLine;
+ PartPtr += srcParts.ByteWidth;
+ }
+ Xfree(srcParts.buf);
+ }
+ } else {
+ (*pDraw->pScreen->GetImage) (pDraw, stuff->x, stuff->y + linesDone,
+ stuff->width, nlines, stuff->format,
+ (unsigned long)stuff->planeMask, pBuf);
+ }
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ /*
+ * For 64-bit server, convert image to pad to 32 bits
+ */
+
+ if ( widthBytesLine != widthBytesLineProto ) {
+ register char * bufPtr, * protoPtr;
+ register int i;
+
+ bzero(tmpImage,length);
+
+ for (i = 0, bufPtr = pBuf, protoPtr = tmpImage; i < nlines;
+ bufPtr += widthBytesLine, protoPtr += widthBytesLineProto,
+ i++)
+ memmove(protoPtr,bufPtr,widthBytesLineProto);
+
+ /*
+ * Note this is NOT a call to WriteSwappedDataToClient,
+ * as we do NOT byte swap
+ */
+
+ (void)WriteToClient(client,
+ (int)(nlines * widthBytesLineProto), tmpImage);
+ } else
+#endif
+ {
+
+ /*
+ * Note this is NOT a call to WriteSwappedDataToClient,
+ * as we do NOT byte swap
+ */
+
+ (void)WriteToClient(client,
+ (int)(nlines * widthBytesLine), pBuf);
+ }
+ linesDone += nlines;
+ }
+ } else { /* XYPixmap */
+ for (; plane; plane >>= 1) {
+ if (stuff->planeMask & plane) {
+ linesDone = 0;
+ while (height - linesDone > 0) {
+ nlines = min(linesPerBuf, height - linesDone);
+ (*pDraw->pScreen->GetImage) (pDraw,
+ stuff->x,
+ stuff->y + linesDone,
+ stuff->width,
+ nlines,
+ stuff->format,
+ (unsigned long)plane,
+ pBuf);
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ /*
+ * For 64-bit server, convert image to pad to 32 bits
+ */
+
+ if (widthBytesLine != widthBytesLineProto) {
+ register char * bufPtr, * protoPtr;
+ register int i;
+
+ bzero(tmpImage, length);
+
+ for (i = 0,bufPtr = pBuf,protoPtr =tmpImage; i < nlines;
+ bufPtr += widthBytesLine,
+ protoPtr += widthBytesLineProto,
+ i++)
+ bcopy(bufPtr, protoPtr, widthBytesLineProto);
+
+ /*
+ * Note: NOT a call to WriteSwappedDataToClient,
+ * as we do NOT byte swap
+ */
+
+ (void)WriteToClient(client,
+ (int)(nlines * widthBytesLineProto), tmpImage);
+ } else
+#endif
+ {
+
+ /*
+ * Note: NOT a call to WriteSwappedDataToClient,
+ * as we do NOT byte swap
+ */
+
+ (void)WriteToClient(client,
+ (int)(nlines * widthBytesLine), pBuf);
+ }
+ linesDone += nlines;
+ }
+ }
+ }
+ }
+ DEALLOCATE_LOCAL(pBuf);
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ if (widthBytesLine != widthBytesLineProto)
+ DEALLOCATE_LOCAL(tmpImage);
+#endif
+ return (client->noClientException);
+}
+
+
+int
+PanoramiXPolyText8(register ClientPtr client)
+{
+ int result, j;
+
+ PanoramiXWindow *pPanoramiXRoot;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr pDraw;
+ PixmapPtr pPixmap;
+ GC *pGC;
+ int orig_x, orig_y;
+ REQUEST(xPolyTextReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ pPanoramiXWin = pPanoramiXRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ /* In the case of Multibuffering, we need to make sure the drawable
+ isn't really a pixmap associated to a drawable */
+ if (!pPanoramiXWin && (stuff->drawable != pDraw->id)) {
+ pPanoramiXWin = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ }
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ orig_x = stuff->x;
+ orig_y = stuff->y;
+ FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) {
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ stuff->x = orig_x;
+ stuff->y = orig_y;
+ if (pPanoramiXWin == pPanoramiXRoot) {
+ stuff->x = orig_x - panoramiXdataPtr[j].x;
+ stuff->y = orig_y - panoramiXdataPtr[j].y;
+ } else {
+ if ( (pDraw->type == DRAWABLE_PIXMAP) &&
+ /* special case root window bitmap */
+ (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ stuff->x = orig_x - panoramiXdataPtr[j].x;
+ stuff->y = orig_y - panoramiXdataPtr[j].y;
+ }
+ }
+ if (!j)
+ noPanoramiXExtension = TRUE;
+ result = (*SavedProcVector[X_PolyText8])(client);
+ noPanoramiXExtension = FALSE;
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+
+int
+PanoramiXPolyText16(register ClientPtr client)
+{
+ int result, j;
+
+ PanoramiXWindow *pPanoramiXRoot;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr pDraw;
+ GC *pGC;
+ int orig_x, orig_y;
+ REQUEST(xPolyTextReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ pPanoramiXWin = pPanoramiXRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ /* In the case of Multibuffering, we need to make sure the drawable
+ isn't really a pixmap associated to a drawable */
+ if (!pPanoramiXWin && (stuff->drawable != pDraw->id)) {
+ pPanoramiXWin = PanoramiXPmapRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ }
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ orig_x = stuff->x;
+ orig_y = stuff->y;
+ FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) {
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ stuff->x = orig_x;
+ stuff->y = orig_y;
+ if (pPanoramiXWin == pPanoramiXRoot) {
+ stuff->x = orig_x - panoramiXdataPtr[j].x;
+ stuff->y = orig_y - panoramiXdataPtr[j].y;
+ } else {
+ if ( (pDraw->type == DRAWABLE_PIXMAP) &&
+ /* special case root window bitmap */
+ (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ stuff->x = orig_x - panoramiXdataPtr[j].x;
+ stuff->y = orig_y - panoramiXdataPtr[j].y;
+ }
+ }
+ if (!j)
+ noPanoramiXExtension = TRUE;
+ result = (*SavedProcVector[X_PolyText16])(client);
+ noPanoramiXExtension = FALSE;
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+
+
+
+int PanoramiXImageText8(ClientPtr client)
+{
+ int result, j;
+ PanoramiXWindow *pPanoramiXRoot;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr pDraw;
+ GCPtr pGC;
+ int orig_x, orig_y;
+ REQUEST(xImageTextReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ pPanoramiXWin = pPanoramiXRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ orig_x = stuff->x;
+ orig_y = stuff->y;
+ FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) {
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ if (pPanoramiXWin == pPanoramiXRoot) {
+ stuff->x = orig_x - panoramiXdataPtr[j].x;
+ stuff->y = orig_y - panoramiXdataPtr[j].y;
+ }else {
+ if ( (pDraw->type == DRAWABLE_PIXMAP) &&
+ /* special case root window bitmap */
+ (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ stuff->x = orig_x - panoramiXdataPtr[j].x;
+ stuff->y = orig_y - panoramiXdataPtr[j].y;
+ }
+ }
+ result = (*SavedProcVector[X_ImageText8])(client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+
+
+int PanoramiXImageText16(ClientPtr client)
+{
+ int result, j;
+ PanoramiXWindow *pPanoramiXRoot;
+ PanoramiXWindow *pPanoramiXWin;
+ PanoramiXGC *pPanoramiXGC = PanoramiXGCRoot;
+ DrawablePtr pDraw;
+ GCPtr pGC;
+ int orig_x, orig_y;
+ REQUEST(xImageTextReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ pPanoramiXRoot = (pDraw->type == DRAWABLE_PIXMAP)
+ ? PanoramiXPmapRoot : PanoramiXWinRoot;
+ pPanoramiXWin = pPanoramiXRoot;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->drawable);
+ IF_RETURN(!pPanoramiXWin, BadDrawable);
+ PANORAMIXFIND_ID(pPanoramiXGC, stuff->gc);
+ IF_RETURN(!pPanoramiXGC, BadGC);
+ orig_x = stuff->x;
+ orig_y = stuff->y;
+ FOR_NSCREENS_OR_ONCE((pPanoramiXWin && pPanoramiXGC), j) {
+ stuff->drawable = pPanoramiXWin->info[j].id;
+ stuff->gc = pPanoramiXGC->info[j].id;
+ if (pPanoramiXWin == pPanoramiXRoot) {
+ stuff->x = orig_x - panoramiXdataPtr[j].x;
+ stuff->y = orig_y - panoramiXdataPtr[j].y;
+ }else {
+ if ( (pDraw->type == DRAWABLE_PIXMAP) &&
+ /* special case root window bitmap */
+ (pDraw->width == (panoramiXdataPtr[PanoramiXNumScreens-1].x +
+ panoramiXdataPtr[PanoramiXNumScreens-1].width)) ) {
+ stuff->x = orig_x - panoramiXdataPtr[j].x;
+ stuff->y = orig_y - panoramiXdataPtr[j].y;
+ }
+ }
+ result = (*SavedProcVector[X_ImageText16])(client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+
+
+int PanoramiXCreateColormap(register ClientPtr client)
+{
+ VisualPtr pVisual;
+ ColormapPtr pmap;
+ Colormap mid;
+ register WindowPtr pWin;
+ ScreenPtr pScreen;
+ DepthPtr pDepth;
+
+ REQUEST(xCreateColormapReq);
+
+ int i, result;
+ int vid_index, class_index;
+ int this_vid_index, this_class_index, this_depth;
+ int j = 0;
+ VisualID orig_visual;
+ Colormap cmapID;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ PanoramiXCmap *localCmap;
+ PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot;
+ short VisualClass;
+ Bool ClassKnown;
+ Bool FoundIt = FALSE;
+
+ REQUEST_SIZE_MATCH(xCreateColormapReq);
+
+ mid = stuff->mid;
+ orig_visual = stuff->visual;
+ j = 0;
+ PANORAMIXFIND_ID(pPanoramiXWin, stuff->window);
+ if (pPanoramiXWin) {
+ localCmap = (PanoramiXCmap *)Xcalloc(sizeof(PanoramiXCmap));
+ IF_RETURN(!localCmap, BadAlloc);
+ } else {
+ return BadWindow;
+ }
+ for (j = 0; j <= PanoramiXNumScreens - 1; j++) {
+ cmapID = j ? FakeClientID(client->index) : mid;
+ localCmap->info[j].id = cmapID;
+ }
+ localCmap->FreeMe = FALSE;
+ PANORAMIXFIND_LAST(pPanoramiXCmap, PanoramiXCmapRoot);
+ pPanoramiXCmap->next = localCmap;
+
+ /* Use Screen 0 to get the matching Visual ID */
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+ SecurityReadAccess);
+ if ( stuff->visual != CopyFromParent)
+ {
+ /* Find the correct visual for screen 0 */
+ for (class_index = 0; class_index < PanoramiXColorDepthTable[0].numVisuals;
+class_index++)
+ {
+ for (j = 0; j < PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index
+].numDepths; j++ )
+ {
+ pDepth = (DepthPtr) &pWin->drawable.pScreen->allowedDepths[j];
+ for (vid_index = 0; vid_index < PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[pDepth->depth].numVids; vid_index++)
+ {
+ if ( stuff->visual == PanoramiXColorDepthTable[0].panoramiXScreenMap[class_index].vmap[pDepth->depth].vid[vid_index] )
+ {
+ this_class_index = class_index;
+ this_vid_index = vid_index;
+ this_depth = pDepth->depth;
+ FoundIt = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (!pWin)
+ return(BadWindow);
+ pScreen = pWin->drawable.pScreen;
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin, j) {
+ stuff->mid = localCmap->info[j].id;
+ stuff->window = pPanoramiXWin->info[j].id;
+ /* Look for the matching visual class, and use its
+ visual id for creating this colormap. */
+ if ( orig_visual != CopyFromParent && FoundIt )
+ {
+ stuff->visual = PanoramiXColorDepthTable[j].panoramiXScreenMap[this_class_index].vmap[this_depth].vid[this_vid_index];
+ }
+ result = (* SavedProcVector[X_CreateColormap])(client);
+ BREAK_IF(result != Success);
+ }
+ if (result != Success) {
+ pPanoramiXCmap->next = NULL ;
+ if (localCmap)
+ Xfree(localCmap);
+ }
+ return (result);
+}
+
+
+int PanoramiXFreeColormap(ClientPtr client)
+{
+ ColormapPtr pmap;
+ REQUEST(xResourceReq);
+ int result, j;
+ PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot;
+ PanoramiXCmap *pPanoramiXCmapback = NULL;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ for (; pPanoramiXCmap && (pPanoramiXCmap->info[0].id != stuff->id);
+ pPanoramiXCmap = pPanoramiXCmap->next)
+ pPanoramiXCmapback = pPanoramiXCmap;
+ IF_RETURN(!pPanoramiXCmap, BadColor);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) {
+ stuff->id = pPanoramiXCmap->info[j].id;
+ result = (* SavedProcVector[X_FreeColormap])(client);
+ BREAK_IF(result != Success);
+ }
+ if ((result == Success) && pPanoramiXCmapback &&
+ pPanoramiXCmap && pPanoramiXCmap->FreeMe) {
+ pPanoramiXCmapback->next = pPanoramiXCmap->next;
+ Xfree(pPanoramiXCmap);
+ }
+ PANORAMIX_FREE(client);
+ return (result);
+}
+
+
+int PanoramiXInstallColormap(register ClientPtr client)
+{
+ ColormapPtr pcmp;
+ REQUEST(xResourceReq);
+ int result, j;
+ PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ PANORAMIXFIND_ID(pPanoramiXCmap, stuff->id);
+ IF_RETURN(!pPanoramiXCmap, BadColor);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) {
+ stuff->id = pPanoramiXCmap->info[j].id;
+ result = (* SavedProcVector[X_InstallColormap])(client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+
+
+int PanoramiXUninstallColormap(register ClientPtr client)
+{
+ ColormapPtr pcmp;
+ REQUEST(xResourceReq);
+ int result, j;
+ PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot;
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ PANORAMIXFIND_ID(pPanoramiXCmap, stuff->id);
+ IF_RETURN(!pPanoramiXCmap, BadColor);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) {
+ stuff->id = pPanoramiXCmap->info[j].id;
+ result = (* SavedProcVector[X_UninstallColormap])(client);
+ BREAK_IF(result != Success);
+ }
+ PANORAMIX_FREE(client);
+ return (result);
+}
+
+
+int PanoramiXAllocColor(ClientPtr client)
+{
+ int result, j;
+ PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot;
+ REQUEST(xAllocColorReq);
+
+ REQUEST_SIZE_MATCH(xAllocColorReq);
+ PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap);
+ if (!pPanoramiXCmap){
+ noPanoramiXExtension = TRUE;
+ result = (* SavedProcVector[X_AllocColor])(client);
+ noPanoramiXExtension = FALSE;
+ }else {
+ FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) {
+ stuff->cmap = pPanoramiXCmap->info[j].id;
+ if (!j)
+ noPanoramiXExtension = TRUE;
+ result = (* SavedProcVector[X_AllocColor])(client);
+ noPanoramiXExtension = FALSE;
+ BREAK_IF(result != Success);
+ }
+ }
+ return (result);
+}
+
+
+int PanoramiXAllocNamedColor(ClientPtr client)
+{
+ int result, j;
+ PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot;
+ REQUEST(xAllocNamedColorReq);
+
+ REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
+ PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap);
+ IF_RETURN(!pPanoramiXCmap, BadColor);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) {
+ stuff->cmap = pPanoramiXCmap->info[j].id;
+ if (!j)
+ noPanoramiXExtension = TRUE;
+ result = (* SavedProcVector[X_AllocNamedColor])(client);
+ noPanoramiXExtension = FALSE;
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+
+
+int PanoramiXAllocColorCells(ClientPtr client)
+{
+ int result, j;
+ PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot;
+ REQUEST(xAllocColorCellsReq);
+
+ REQUEST_SIZE_MATCH(xAllocColorCellsReq);
+ PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap);
+ if (!pPanoramiXCmap) {
+ noPanoramiXExtension = TRUE;
+ result = (* SavedProcVector[X_AllocColorCells])(client);
+ noPanoramiXExtension = FALSE;
+ }else {
+ FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) {
+ stuff->cmap = pPanoramiXCmap->info[j].id;
+ if (!j)
+ noPanoramiXExtension = TRUE;
+ result = (* SavedProcVector[X_AllocColorCells])(client);
+ noPanoramiXExtension = FALSE;
+ /* Because id's are eventually searched for in
+ some client list, we don't check for success
+ on fake id's last id will be real, we really
+ only care about results related to real id's
+ BREAK_IF(result != Success);
+ */
+ }
+ }
+ return (result);
+}
+
+
+int PanoramiXFreeColors(register ClientPtr client)
+{
+ int result, j;
+ PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot;
+ REQUEST(xFreeColorsReq);
+
+ PanoramiXGC *pPanoramiXFreeGC;
+ PanoramiXGC *pPanoramiXFreeGCback = NULL;
+ PanoramiXWindow *pPanoramiXFreeWin;
+ PanoramiXWindow *pPanoramiXFreeWinback = NULL;
+ PanoramiXCmap *pPanoramiXFreeCmap;
+ PanoramiXCmap *pPanoramiXFreeCmapback = NULL;
+ PanoramiXPmap *pPanoramiXFreePmap;
+ PanoramiXPmap *pPanoramiXFreePmapback = NULL;
+
+ REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
+ PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap);
+ IF_RETURN(!pPanoramiXCmap, BadColor);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) {
+ stuff->cmap = pPanoramiXCmap->info[j].id;
+ result = (* SavedProcVector[X_FreeColors])(client);
+ /* Because id's are eventually searched for in
+ some client list, we don't check for success
+ on fake id's last id will be real, we really
+ only care about results related to real id's */
+ }
+ PANORAMIX_FREE(client);
+ return (result);
+}
+
+
+int PanoramiXStoreColors(ClientPtr client)
+{
+ int result, j;
+ PanoramiXCmap *pPanoramiXCmap = PanoramiXCmapRoot;
+ REQUEST(xStoreColorsReq);
+
+ REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
+ PANORAMIXFIND_ID(pPanoramiXCmap, stuff->cmap);
+ if (!pPanoramiXCmap)
+ result = (* SavedProcVector[X_StoreColors])(client);
+ else {
+ FOR_NSCREENS_OR_ONCE(pPanoramiXCmap, j) {
+ stuff->cmap = pPanoramiXCmap->info[j].id;
+ result = (* SavedProcVector[X_StoreColors])(client);
+ BREAK_IF(result != Success);
+ }
+ }
+ return (result);
+}
diff --git a/Xext/sampleEVI.c b/Xext/sampleEVI.c
new file mode 100644
index 000000000..43265a73d
--- /dev/null
+++ b/Xext/sampleEVI.c
@@ -0,0 +1,97 @@
+/* $Xorg: sampleEVI.c,v 1.3 2000/08/17 19:47:58 cpqbld Exp $ */
+/************************************************************
+Copyright (c) 1997 by Silicon Graphics Computer Systems, Inc.
+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 Silicon Graphics not be
+used in advertising or publicity pertaining to distribution
+of the software without specific prior written permission.
+Silicon Graphics makes no representation about the suitability
+of this software for any purpose. It is provided "as is"
+without any express or implied warranty.
+SILICON GRAPHICS DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SILICON
+GRAPHICS 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.
+********************************************************/
+#include "X.h"
+#include "Xproto.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "dix.h"
+#define _XEVI_SERVER_
+#include "XEVIstr.h"
+#include "EVIstruct.h"
+#include "scrnintstr.h"
+static int sampleGetVisualInfo(
+ VisualID32 *visual,
+ int n_visual,
+ xExtendedVisualInfo **evi_rn,
+ int *n_info_rn,
+ VisualID32 **conflict_rn,
+ int *n_conflict_rn)
+{
+ int max_sz_evi = n_visual * sz_xExtendedVisualInfo * screenInfo.numScreens;
+ VisualID32 *temp_conflict;
+ xExtendedVisualInfo *evi;
+ int max_visuals = 0, max_sz_conflict, sz_conflict = 0;
+ register int visualI, scrI, sz_evi = 0, conflictI, n_conflict;
+ *evi_rn = evi = (xExtendedVisualInfo *)xalloc(max_sz_evi);
+ if (!*evi_rn)
+ return BadAlloc;
+ for (scrI = 0; scrI < screenInfo.numScreens; scrI++) {
+ if (screenInfo.screens[scrI]->numVisuals > max_visuals)
+ max_visuals = screenInfo.screens[scrI]->numVisuals;
+ }
+ max_sz_conflict = n_visual * sz_VisualID32 * screenInfo.numScreens * max_visuals;
+ temp_conflict = (VisualID32 *)xalloc(max_sz_conflict);
+ if (!temp_conflict) {
+ xfree(*evi_rn);
+ return BadAlloc;
+ }
+ for (scrI = 0; scrI < screenInfo.numScreens; scrI++) {
+ for (visualI = 0; visualI < n_visual; visualI++) {
+ evi[sz_evi].core_visual_id = visual[visualI];
+ evi[sz_evi].screen = scrI;
+ evi[sz_evi].level = 0;
+ evi[sz_evi].transparency_type = XEVI_TRANSPARENCY_NONE;
+ evi[sz_evi].transparency_value = 0;
+ evi[sz_evi].min_hw_colormaps = 1;
+ evi[sz_evi].max_hw_colormaps = 1;
+ evi[sz_evi].num_colormap_conflicts = n_conflict = 0;
+ for (conflictI = 0; conflictI < n_conflict; conflictI++)
+ temp_conflict[sz_conflict++] = visual[visualI];
+ sz_evi++;
+ }
+ }
+ *conflict_rn = temp_conflict;
+ *n_conflict_rn = sz_conflict;
+ *n_info_rn = sz_evi;
+ return Success;
+}
+static void sampleFreeVisualInfo(
+ xExtendedVisualInfo *evi,
+ VisualID32 *conflict)
+{
+ if (evi)
+ xfree(evi);
+ if (conflict)
+ xfree(conflict);
+}
+EviPrivPtr eviDDXInit()
+{
+ static EviPrivRec eviPriv;
+ eviPriv.getVisualInfo = sampleGetVisualInfo;
+ eviPriv.freeVisualInfo = sampleFreeVisualInfo;
+ return &eviPriv;
+}
+void eviDDXReset()
+{
+}
diff --git a/Xext/security.c b/Xext/security.c
new file mode 100644
index 000000000..c2db8f4dd
--- /dev/null
+++ b/Xext/security.c
@@ -0,0 +1,1995 @@
+/* $Xorg: security.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */
+/*
+
+Copyright 1996, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "windowstr.h"
+#include "inputstr.h"
+#include "gcstruct.h"
+#include "colormapst.h"
+#include "propertyst.h"
+#define _SECURITY_SERVER
+#include "securstr.h"
+#include <assert.h>
+#include <stdarg.h>
+#ifdef LBX
+#define _XLBX_SERVER_
+#include "XLbx.h"
+extern unsigned char LbxReqCode;
+#endif
+#ifdef XAPPGROUP
+#include "Xagsrv.h"
+#endif
+#include <stdio.h> /* for file reading operations */
+#include "Xatom.h" /* for XA_STRING */
+
+#ifndef DEFAULTPOLICYFILE
+# define DEFAULTPOLICYFILE NULL
+#endif
+#ifdef WIN32
+#include <X11/Xos.h>
+#undef index
+#endif
+
+static int SecurityErrorBase; /* first Security error number */
+static int SecurityEventBase; /* first Security event number */
+
+CallbackListPtr SecurityValidateGroupCallback = NULL; /* see security.h */
+
+RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */
+
+static RESTYPE RTEventClient;
+
+/* Proc vectors for untrusted clients, swapped and unswapped versions.
+ * These are the same as the normal proc vectors except that extensions
+ * that haven't declared themselves secure will have ProcBadRequest plugged
+ * in for their major opcode dispatcher. This prevents untrusted clients
+ * from guessing extension major opcodes and using the extension even though
+ * the extension can't be listed or queried.
+ */
+int (*UntrustedProcVector[256])(
+#if NeedNestedPrototypes
+ ClientPtr /*client*/
+#endif
+);
+int (*SwappedUntrustedProcVector[256])(
+#if NeedNestedPrototypes
+ ClientPtr /*client*/
+#endif
+);
+
+extern int ProcBadRequest();
+
+
+/* SecurityAudit
+ *
+ * Arguments:
+ * format is the formatting string to be used to interpret the
+ * remaining arguments.
+ *
+ * Returns: nothing.
+ *
+ * Side Effects:
+ * Writes the message to the log file if security logging is on.
+ */
+
+void
+SecurityAudit(char *format, ...)
+{
+ va_list args;
+
+ if (auditTrailLevel < SECURITY_AUDIT_LEVEL)
+ return;
+ AuditPrefix(format);
+ va_start(args, format);
+ VErrorF(format, args);
+ va_end(args);
+} /* SecurityAudit */
+
+#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
+
+/* SecurityDeleteAuthorization
+ *
+ * Arguments:
+ * value is the authorization to delete.
+ * id is its resource ID.
+ *
+ * Returns: Success.
+ *
+ * Side Effects:
+ * Frees everything associated with the authorization.
+ */
+
+static int
+SecurityDeleteAuthorization(value, id)
+ pointer value;
+ XID id;
+{
+ SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value;
+ unsigned short name_len, data_len;
+ char *name, *data;
+ int status;
+ int i;
+ OtherClientsPtr pEventClient;
+
+ /* Remove the auth using the os layer auth manager */
+
+ status = AuthorizationFromID(pAuth->id, &name_len, &name,
+ &data_len, &data);
+ assert(status);
+ status = RemoveAuthorization(name_len, name, data_len, data);
+ assert(status);
+
+ /* free the auth timer if there is one */
+
+ if (pAuth->timer) TimerFree(pAuth->timer);
+
+ /* send revoke events */
+
+ while (pEventClient = pAuth->eventClients)
+ {
+ /* send revocation event event */
+ ClientPtr client = rClient(pEventClient);
+
+ if (!client->clientGone)
+ {
+ xSecurityAuthorizationRevokedEvent are;
+ are.type = SecurityEventBase + XSecurityAuthorizationRevoked;
+ are.sequenceNumber = client->sequence;
+ are.authId = pAuth->id;
+ WriteEventsToClient(client, 1, (xEvent *)&are);
+ }
+ FreeResource(pEventClient->resource, RT_NONE);
+ }
+
+ /* kill all clients using this auth */
+
+ for (i = 1; i<currentMaxClients; i++)
+ {
+ if (clients[i] && (clients[i]->authId == pAuth->id))
+ CloseDownClient(clients[i]);
+ }
+
+ SecurityAudit("revoked authorization ID %d\n", pAuth->id);
+ xfree(pAuth);
+ return Success;
+
+} /* SecurityDeleteAuthorization */
+
+
+/* resource delete function for RTEventClient */
+static int
+SecurityDeleteAuthorizationEventClient(value, id)
+ pointer value;
+ XID id;
+{
+ OtherClientsPtr pEventClient, prev = NULL;
+ SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value;
+
+ for (pEventClient = pAuth->eventClients;
+ pEventClient;
+ pEventClient = pEventClient->next)
+ {
+ if (pEventClient->resource == id)
+ {
+ if (prev)
+ prev->next = pEventClient->next;
+ else
+ pAuth->eventClients = pEventClient->next;
+ xfree(pEventClient);
+ return(Success);
+ }
+ prev = pEventClient;
+ }
+ /*NOTREACHED*/
+ return -1; /* make compiler happy */
+} /* SecurityDeleteAuthorizationEventClient */
+
+
+/* SecurityComputeAuthorizationTimeout
+ *
+ * Arguments:
+ * pAuth is the authorization for which we are computing the timeout
+ * seconds is the number of seconds we want to wait
+ *
+ * Returns:
+ * the number of milliseconds that the auth timer should be set to
+ *
+ * Side Effects:
+ * Sets pAuth->secondsRemaining to any "overflow" amount of time
+ * that didn't fit in 32 bits worth of milliseconds
+ */
+
+static CARD32
+SecurityComputeAuthorizationTimeout(pAuth, seconds)
+ SecurityAuthorizationPtr pAuth;
+ unsigned int seconds;
+{
+ /* maxSecs is the number of full seconds that can be expressed in
+ * 32 bits worth of milliseconds
+ */
+ CARD32 maxSecs = (CARD32)(~0) / (CARD32)MILLI_PER_SECOND;
+
+ if (seconds > maxSecs)
+ { /* only come here if we want to wait more than 49 days */
+ pAuth->secondsRemaining = seconds - maxSecs;
+ return maxSecs * MILLI_PER_SECOND;
+ }
+ else
+ { /* by far the common case */
+ pAuth->secondsRemaining = 0;
+ return seconds * MILLI_PER_SECOND;
+ }
+} /* SecurityStartAuthorizationTimer */
+
+/* SecurityAuthorizationExpired
+ *
+ * This function is passed as an argument to TimerSet and gets called from
+ * the timer manager in the os layer when its time is up.
+ *
+ * Arguments:
+ * timer is the timer for this authorization.
+ * time is the current time.
+ * pval is the authorization whose time is up.
+ *
+ * Returns:
+ * A new time delay in milliseconds if the timer should wait some
+ * more, else zero.
+ *
+ * Side Effects:
+ * Frees the authorization resource if the timeout period is really
+ * over, otherwise recomputes pAuth->secondsRemaining.
+ */
+
+static CARD32
+SecurityAuthorizationExpired(timer, time, pval)
+ OsTimerPtr timer;
+ CARD32 time;
+ pointer pval;
+{
+ SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)pval;
+
+ assert(pAuth->timer == timer);
+
+ if (pAuth->secondsRemaining)
+ {
+ return SecurityComputeAuthorizationTimeout(pAuth,
+ pAuth->secondsRemaining);
+ }
+ else
+ {
+ FreeResource(pAuth->id, RT_NONE);
+ return 0;
+ }
+} /* SecurityAuthorizationExpired */
+
+/* SecurityStartAuthorizationTimer
+ *
+ * Arguments:
+ * pAuth is the authorization whose timer should be started.
+ *
+ * Returns: nothing.
+ *
+ * Side Effects:
+ * A timer is started, set to expire after the timeout period for
+ * this authorization. When it expires, the function
+ * SecurityAuthorizationExpired will be called.
+ */
+
+static void
+SecurityStartAuthorizationTimer(pAuth)
+ SecurityAuthorizationPtr pAuth;
+{
+ pAuth->timer = TimerSet(pAuth->timer, 0,
+ SecurityComputeAuthorizationTimeout(pAuth, pAuth->timeout),
+ SecurityAuthorizationExpired, pAuth);
+} /* SecurityStartAuthorizationTimer */
+
+
+/* Proc functions all take a client argument, execute the request in
+ * client->requestBuffer, and return a protocol error status.
+ */
+
+static int
+ProcSecurityQueryVersion(client)
+ ClientPtr client;
+{
+ REQUEST(xSecurityQueryVersionReq);
+ xSecurityQueryVersionReply rep;
+
+ /* paranoia: this "can't happen" because this extension is hidden
+ * from untrusted clients, but just in case...
+ */
+ if (client->trustLevel != XSecurityClientTrusted)
+ return BadRequest;
+
+ REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.majorVersion = SECURITY_MAJOR_VERSION;
+ rep.minorVersion = SECURITY_MINOR_VERSION;
+ if(client->swapped)
+ {
+ register char n;
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ (void)WriteToClient(client, SIZEOF(xSecurityQueryVersionReply),
+ (char *)&rep);
+ return (client->noClientException);
+} /* ProcSecurityQueryVersion */
+
+
+static int
+SecurityEventSelectForAuthorization(pAuth, client, mask)
+ SecurityAuthorizationPtr pAuth;
+ ClientPtr client;
+ Mask mask;
+{
+ OtherClients *pEventClient;
+
+ for (pEventClient = pAuth->eventClients;
+ pEventClient;
+ pEventClient = pEventClient->next)
+ {
+ if (SameClient(pEventClient, client))
+ {
+ if (mask == 0)
+ FreeResource(pEventClient->resource, RT_NONE);
+ else
+ pEventClient->mask = mask;
+ return Success;
+ }
+ }
+
+ pEventClient = (OtherClients *) xalloc(sizeof(OtherClients));
+ if (!pEventClient)
+ return BadAlloc;
+ pEventClient->mask = mask;
+ pEventClient->resource = FakeClientID(client->index);
+ pEventClient->next = pAuth->eventClients;
+ if (!AddResource(pEventClient->resource, RTEventClient,
+ (pointer)pAuth))
+ {
+ xfree(pEventClient);
+ return BadAlloc;
+ }
+ pAuth->eventClients = pEventClient;
+
+ return Success;
+} /* SecurityEventSelectForAuthorization */
+
+
+static int
+ProcSecurityGenerateAuthorization(client)
+ ClientPtr client;
+{
+ REQUEST(xSecurityGenerateAuthorizationReq);
+ int len; /* request length in CARD32s*/
+ Bool removeAuth = FALSE; /* if bailout, call RemoveAuthorization? */
+ SecurityAuthorizationPtr pAuth = NULL; /* auth we are creating */
+ int err; /* error to return from this function */
+ int status; /* return value from os functions */
+ XID authId; /* authorization ID assigned by os layer */
+ xSecurityGenerateAuthorizationReply rep; /* reply struct */
+ unsigned int trustLevel; /* trust level of new auth */
+ XID group; /* group of new auth */
+ CARD32 timeout; /* timeout of new auth */
+ CARD32 *values; /* list of supplied attributes */
+ char *protoname; /* auth proto name sent in request */
+ char *protodata; /* auth proto data sent in request */
+ unsigned int authdata_len; /* # bytes of generated auth data */
+ char *pAuthdata; /* generated auth data */
+ Mask eventMask; /* what events on this auth does client want */
+
+ /* paranoia: this "can't happen" because this extension is hidden
+ * from untrusted clients, but just in case...
+ */
+ if (client->trustLevel != XSecurityClientTrusted)
+ return BadRequest;
+
+ /* check request length */
+
+ REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq);
+ len = SIZEOF(xSecurityGenerateAuthorizationReq) >> 2;
+ len += (stuff->nbytesAuthProto + (unsigned)3) >> 2;
+ len += (stuff->nbytesAuthData + (unsigned)3) >> 2;
+ values = ((CARD32 *)stuff) + len;
+ len += Ones(stuff->valueMask);
+ if (client->req_len != len)
+ return BadLength;
+
+ /* check valuemask */
+ if (stuff->valueMask & ~XSecurityAllAuthorizationAttributes)
+ {
+ client->errorValue = stuff->valueMask;
+ return BadValue;
+ }
+
+ /* check timeout */
+ timeout = 60;
+ if (stuff->valueMask & XSecurityTimeout)
+ {
+ timeout = *values++;
+ }
+
+ /* check trustLevel */
+ trustLevel = XSecurityClientUntrusted;
+ if (stuff->valueMask & XSecurityTrustLevel)
+ {
+ trustLevel = *values++;
+ if (trustLevel != XSecurityClientTrusted &&
+ trustLevel != XSecurityClientUntrusted)
+ {
+ client->errorValue = trustLevel;
+ return BadValue;
+ }
+ }
+
+ /* check group */
+ group = None;
+ if (stuff->valueMask & XSecurityGroup)
+ {
+ group = *values++;
+ if (SecurityValidateGroupCallback)
+ {
+ SecurityValidateGroupInfoRec vgi;
+ vgi.group = group;
+ vgi.valid = FALSE;
+ CallCallbacks(&SecurityValidateGroupCallback, (pointer)&vgi);
+
+ /* if nobody said they recognized it, it's an error */
+
+ if (!vgi.valid)
+ {
+ client->errorValue = group;
+ return BadValue;
+ }
+ }
+ }
+
+ /* check event mask */
+ eventMask = 0;
+ if (stuff->valueMask & XSecurityEventMask)
+ {
+ eventMask = *values++;
+ if (eventMask & ~XSecurityAllEventMasks)
+ {
+ client->errorValue = eventMask;
+ return BadValue;
+ }
+ }
+
+ protoname = (char *)&stuff[1];
+ protodata = protoname + ((stuff->nbytesAuthProto + (unsigned)3) >> 2);
+
+ /* call os layer to generate the authorization */
+
+ authId = GenerateAuthorization(stuff->nbytesAuthProto, protoname,
+ stuff->nbytesAuthData, protodata,
+ &authdata_len, &pAuthdata);
+ if ((XID) ~0L == authId)
+ {
+ err = SecurityErrorBase + XSecurityBadAuthorizationProtocol;
+ goto bailout;
+ }
+
+ /* now that we've added the auth, remember to remove it if we have to
+ * abort the request for some reason (like allocation failure)
+ */
+ removeAuth = TRUE;
+
+ /* associate additional information with this auth ID */
+
+ pAuth = (SecurityAuthorizationPtr)xalloc(sizeof(SecurityAuthorizationRec));
+ if (!pAuth)
+ {
+ err = BadAlloc;
+ goto bailout;
+ }
+
+ /* fill in the auth fields */
+
+ pAuth->id = authId;
+ pAuth->timeout = timeout;
+ pAuth->group = group;
+ pAuth->trustLevel = trustLevel;
+ pAuth->refcnt = 0; /* the auth was just created; nobody's using it yet */
+ pAuth->secondsRemaining = 0;
+ pAuth->timer = NULL;
+ pAuth->eventClients = NULL;
+
+ /* handle event selection */
+ if (eventMask)
+ {
+ err = SecurityEventSelectForAuthorization(pAuth, client, eventMask);
+ if (err != Success)
+ goto bailout;
+ }
+
+ if (!AddResource(authId, SecurityAuthorizationResType, pAuth))
+ {
+ err = BadAlloc;
+ goto bailout;
+ }
+
+ /* start the timer ticking */
+
+ if (pAuth->timeout != 0)
+ SecurityStartAuthorizationTimer(pAuth);
+
+ /* tell client the auth id and data */
+
+ rep.type = X_Reply;
+ rep.length = (authdata_len + 3) >> 2;
+ rep.sequenceNumber = client->sequence;
+ rep.authId = authId;
+ rep.dataLength = authdata_len;
+
+ if (client->swapped)
+ {
+ register char n;
+ swapl(&rep.length, n);
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.authId, n);
+ swaps(&rep.dataLength, n);
+ }
+
+ WriteToClient(client, SIZEOF(xSecurityGenerateAuthorizationReply),
+ (char *)&rep);
+ WriteToClient(client, authdata_len, pAuthdata);
+
+ SecurityAudit("client %d generated authorization %d trust %d timeout %d group %d events %d\n",
+ client->index, pAuth->id, pAuth->trustLevel, pAuth->timeout,
+ pAuth->group, eventMask);
+
+ /* the request succeeded; don't call RemoveAuthorization or free pAuth */
+
+ removeAuth = FALSE;
+ pAuth = NULL;
+ err = client->noClientException;
+
+bailout:
+ if (removeAuth)
+ RemoveAuthorization(stuff->nbytesAuthProto, protoname,
+ authdata_len, pAuthdata);
+ if (pAuth) xfree(pAuth);
+ return err;
+
+} /* ProcSecurityGenerateAuthorization */
+
+static int
+ProcSecurityRevokeAuthorization(client)
+ ClientPtr client;
+{
+ REQUEST(xSecurityRevokeAuthorizationReq);
+ SecurityAuthorizationPtr pAuth;
+
+ /* paranoia: this "can't happen" because this extension is hidden
+ * from untrusted clients, but just in case...
+ */
+ if (client->trustLevel != XSecurityClientTrusted)
+ return BadRequest;
+
+ REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
+
+ pAuth = (SecurityAuthorizationPtr)SecurityLookupIDByType(client,
+ stuff->authId, SecurityAuthorizationResType, SecurityDestroyAccess);
+ if (!pAuth)
+ return SecurityErrorBase + XSecurityBadAuthorization;
+
+ FreeResource(stuff->authId, RT_NONE);
+ return Success;
+} /* ProcSecurityRevokeAuthorization */
+
+
+static int
+ProcSecurityDispatch(client)
+ ClientPtr client;
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_SecurityQueryVersion:
+ return ProcSecurityQueryVersion(client);
+ case X_SecurityGenerateAuthorization:
+ return ProcSecurityGenerateAuthorization(client);
+ case X_SecurityRevokeAuthorization:
+ return ProcSecurityRevokeAuthorization(client);
+ default:
+ return BadRequest;
+ }
+} /* ProcSecurityDispatch */
+
+static int
+SProcSecurityQueryVersion(client)
+ ClientPtr client;
+{
+ REQUEST(xSecurityQueryVersionReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xSecurityQueryVersionReq);
+ swaps(&stuff->majorVersion, n);
+ swaps(&stuff->minorVersion,n);
+ return ProcSecurityQueryVersion(client);
+} /* SProcSecurityQueryVersion */
+
+
+static int
+SProcSecurityGenerateAuthorization(client)
+ ClientPtr client;
+{
+ REQUEST(xSecurityGenerateAuthorizationReq);
+ register char n;
+ CARD32 *values;
+ unsigned long nvalues;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq);
+ swaps(&stuff->nbytesAuthProto, n);
+ swaps(&stuff->nbytesAuthData, n);
+ swapl(&stuff->valueMask, n);
+ values = (CARD32 *)(&stuff[1]) +
+ ((stuff->nbytesAuthProto + (unsigned)3) >> 2) +
+ ((stuff->nbytesAuthData + (unsigned)3) >> 2);
+ nvalues = (((CARD32 *)stuff) + stuff->length) - values;
+ SwapLongs(values, nvalues);
+ return ProcSecurityGenerateAuthorization(client);
+} /* SProcSecurityGenerateAuthorization */
+
+
+static int
+SProcSecurityRevokeAuthorization(client)
+ ClientPtr client;
+{
+ REQUEST(xSecurityRevokeAuthorizationReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq);
+ swapl(&stuff->authId, n);
+ return ProcSecurityRevokeAuthorization(client);
+} /* SProcSecurityRevokeAuthorization */
+
+
+static int
+SProcSecurityDispatch(client)
+ ClientPtr client;
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_SecurityQueryVersion:
+ return SProcSecurityQueryVersion(client);
+ case X_SecurityGenerateAuthorization:
+ return SProcSecurityGenerateAuthorization(client);
+ case X_SecurityRevokeAuthorization:
+ return SProcSecurityRevokeAuthorization(client);
+ default:
+ return BadRequest;
+ }
+} /* SProcSecurityDispatch */
+
+static void
+SwapSecurityAuthorizationRevokedEvent(from, to)
+ xSecurityAuthorizationRevokedEvent *from, *to;
+{
+ to->type = from->type;
+ to->detail = from->detail;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->authId, to->authId);
+}
+
+/* SecurityDetermineEventPropogationLimits
+ *
+ * This is a helper function for SecurityCheckDeviceAccess.
+ *
+ * Arguments:
+ * dev is the device for which the starting and stopping windows for
+ * event propogation should be determined.
+ * The values pointed to by ppWin and ppStopWin are not used.
+ *
+ * Returns:
+ * ppWin is filled in with a pointer to the window at which event
+ * propogation for the given device should start given the current
+ * state of the server (pointer position, window layout, etc.)
+ * ppStopWin is filled in with the window at which event propogation
+ * should stop; events should not go to ppStopWin.
+ *
+ * Side Effects: none.
+ */
+
+static void
+SecurityDetermineEventPropogationLimits(dev, ppWin, ppStopWin)
+ DeviceIntPtr dev;
+ WindowPtr *ppWin;
+ WindowPtr *ppStopWin;
+{
+ WindowPtr pFocusWin = dev->focus ? dev->focus->win : NoneWin;
+
+ if (pFocusWin == NoneWin)
+ { /* no focus -- events don't go anywhere */
+ *ppWin = *ppStopWin = NULL;
+ return;
+ }
+
+ if (pFocusWin == PointerRootWin)
+ { /* focus follows the pointer */
+ *ppWin = GetSpriteWindow();
+ *ppStopWin = NULL; /* propogate all the way to the root */
+ }
+ else
+ { /* a real window is set for the focus */
+ WindowPtr pSpriteWin = GetSpriteWindow();
+ *ppStopWin = pFocusWin->parent; /* don't go past the focus window */
+
+ /* if the pointer is in a subwindow of the focus window, start
+ * at that subwindow, else start at the focus window itself
+ */
+ if (IsParent(pFocusWin, pSpriteWin))
+ *ppWin = pSpriteWin;
+ else *ppWin = pFocusWin;
+ }
+} /* SecurityDetermineEventPropogationLimits */
+
+
+/* SecurityCheckDeviceAccess
+ *
+ * Arguments:
+ * client is the client attempting to access a device.
+ * dev is the device being accessed.
+ * fromRequest is TRUE if the device access is a direct result of
+ * the client executing some request and FALSE if it is a
+ * result of the server trying to send an event (e.g. KeymapNotify)
+ * to the client.
+ * Returns:
+ * TRUE if the device access should be allowed, else FALSE.
+ *
+ * Side Effects:
+ * An audit message is generated if access is denied.
+ */
+
+Bool
+SecurityCheckDeviceAccess(client, dev, fromRequest)
+ ClientPtr client;
+ DeviceIntPtr dev;
+ Bool fromRequest;
+{
+ WindowPtr pWin, pStopWin;
+ Bool untrusted_got_event;
+ Bool found_event_window;
+ Mask eventmask;
+ int reqtype;
+
+ /* trusted clients always allowed to do anything */
+ if (client->trustLevel == XSecurityClientTrusted)
+ return TRUE;
+
+ /* device security other than keyboard is not implemented yet */
+ if (dev != inputInfo.keyboard)
+ return TRUE;
+
+ /* some untrusted client wants access */
+
+ if (fromRequest)
+ {
+ reqtype = ((xReq *)client->requestBuffer)->reqType;
+ switch (reqtype)
+ {
+ /* never allow these */
+ case X_ChangeKeyboardMapping:
+ case X_ChangeKeyboardControl:
+ case X_SetModifierMapping:
+ SecurityAudit("client %d attempted request %d\n",
+ client->index, reqtype);
+ return FALSE;
+ default:
+ break;
+ }
+ }
+
+ untrusted_got_event = FALSE;
+ found_event_window = FALSE;
+
+ if (dev->grab)
+ {
+ untrusted_got_event =
+ ((rClient(dev->grab))->trustLevel != XSecurityClientTrusted);
+ }
+ else
+ {
+ SecurityDetermineEventPropogationLimits(dev, &pWin, &pStopWin);
+
+ eventmask = KeyPressMask | KeyReleaseMask;
+ while ( (pWin != pStopWin) && !found_event_window)
+ {
+ OtherClients *other;
+
+ if (pWin->eventMask & eventmask)
+ {
+ found_event_window = TRUE;
+ client = wClient(pWin);
+ if (client->trustLevel != XSecurityClientTrusted)
+ {
+ untrusted_got_event = TRUE;
+ }
+ }
+ if (wOtherEventMasks(pWin) & eventmask)
+ {
+ found_event_window = TRUE;
+ for (other = wOtherClients(pWin); other; other = other->next)
+ {
+ if (other->mask & eventmask)
+ {
+ client = rClient(other);
+ if (client->trustLevel != XSecurityClientTrusted)
+ {
+ untrusted_got_event = TRUE;
+ break;
+ }
+ }
+ }
+ }
+ if (wDontPropagateMask(pWin) & eventmask)
+ break;
+ pWin = pWin->parent;
+ } /* while propogating the event */
+ }
+
+ /* allow access by untrusted clients only if an event would have gone
+ * to an untrusted client
+ */
+
+ if (!untrusted_got_event)
+ {
+ char *devname = dev->name;
+ if (!devname) devname = "unnamed";
+ if (fromRequest)
+ SecurityAudit("client %d attempted request %d device %d (%s)\n",
+ client->index, reqtype, dev->id, devname);
+ else
+ SecurityAudit("client %d attempted to access device %d (%s)\n",
+ client->index, dev->id, devname);
+ }
+ return untrusted_got_event;
+} /* SecurityCheckDeviceAccess */
+
+
+
+/* SecurityAuditResourceIDAccess
+ *
+ * Arguments:
+ * client is the client doing the resource access.
+ * id is the resource id.
+ *
+ * Returns: NULL
+ *
+ * Side Effects:
+ * An audit message is generated with details of the denied
+ * resource access.
+ */
+
+static pointer
+SecurityAuditResourceIDAccess(client, id)
+ ClientPtr client;
+ XID id;
+{
+ int cid = CLIENT_ID(id);
+ int reqtype = ((xReq *)client->requestBuffer)->reqType;
+ switch (reqtype)
+ {
+ case X_ChangeProperty:
+ case X_DeleteProperty:
+ case X_GetProperty:
+ {
+ xChangePropertyReq *req =
+ (xChangePropertyReq *)client->requestBuffer;
+ int propertyatom = req->property;
+ char *propertyname = NameForAtom(propertyatom);
+
+ SecurityAudit("client %d attempted request %d with window 0x%x property %s of client %d\n",
+ client->index, reqtype, id, propertyname, cid);
+ break;
+ }
+ default:
+ {
+ SecurityAudit("client %d attempted request %d with resource 0x%x of client %d\n",
+ client->index, reqtype, id, cid);
+ break;
+ }
+ }
+ return NULL;
+} /* SecurityAuditResourceIDAccess */
+
+
+/* SecurityCheckResourceIDAccess
+ *
+ * This function gets plugged into client->CheckAccess and is called from
+ * SecurityLookupIDByType/Class to determine if the client can access the
+ * resource.
+ *
+ * Arguments:
+ * client is the client doing the resource access.
+ * id is the resource id.
+ * rtype is its type or class.
+ * access_mode represents the intended use of the resource; see
+ * resource.h.
+ * rval is a pointer to the resource structure for this resource.
+ *
+ * Returns:
+ * If access is granted, the value of rval that was passed in, else NULL.
+ *
+ * Side Effects:
+ * Disallowed resource accesses are audited.
+ */
+
+static pointer
+SecurityCheckResourceIDAccess(client, id, rtype, access_mode, rval)
+ ClientPtr client;
+ XID id;
+ RESTYPE rtype;
+ Mask access_mode;
+ pointer rval;
+{
+ int cid = CLIENT_ID(id);
+ int reqtype = ((xReq *)client->requestBuffer)->reqType;
+
+ if (SecurityUnknownAccess == access_mode)
+ return rval; /* for compatibility, we have to allow access */
+
+ switch (reqtype)
+ { /* these are always allowed */
+ case X_QueryTree:
+ case X_TranslateCoords:
+ case X_GetGeometry:
+ /* property access is controlled in SecurityCheckPropertyAccess */
+ case X_GetProperty:
+ case X_ChangeProperty:
+ case X_DeleteProperty:
+ case X_RotateProperties:
+ case X_ListProperties:
+ return rval;
+ default:
+ break;
+ }
+
+ if (cid != 0)
+ { /* not a server-owned resource */
+ /*
+ * The following 'if' restricts clients to only access resources at
+ * the same trustLevel. Since there are currently only two trust levels,
+ * and trusted clients never call this function, this degenerates into
+ * saying that untrusted clients can only access resources of other
+ * untrusted clients. One way to add the notion of groups would be to
+ * allow values other than Trusted (0) and Untrusted (1) for this field.
+ * Clients at the same trust level would be able to use each other's
+ * resources, but not those of clients at other trust levels. I haven't
+ * tried it, but this probably mostly works already. The obvious
+ * competing alternative for grouping clients for security purposes is to
+ * use app groups. dpw
+ */
+ if (client->trustLevel == clients[cid]->trustLevel
+#ifdef XAPPGROUP
+ || (RT_COLORMAP == rtype &&
+ XagDefaultColormap (client) == (Colormap) id)
+#endif
+ )
+ return rval;
+ else
+ return SecurityAuditResourceIDAccess(client, id);
+ }
+ else /* server-owned resource - probably a default colormap or root window */
+ {
+ if (RT_WINDOW == rtype || RC_DRAWABLE == rtype)
+ {
+ switch (reqtype)
+ { /* the following operations are allowed on root windows */
+ case X_CreatePixmap:
+ case X_CreateGC:
+ case X_CreateWindow:
+ case X_CreateColormap:
+ case X_ListProperties:
+ case X_GrabPointer:
+ case X_UngrabButton:
+ case X_QueryBestSize:
+ case X_GetWindowAttributes:
+ break;
+ case X_SendEvent:
+ { /* see if it is an event specified by the ICCCM */
+ xSendEventReq *req = (xSendEventReq *)
+ (client->requestBuffer);
+ if (req->propagate == xTrue
+ ||
+ (req->eventMask != ColormapChangeMask &&
+ req->eventMask != StructureNotifyMask &&
+ req->eventMask !=
+ (SubstructureRedirectMask|SubstructureNotifyMask)
+ )
+ ||
+ (req->event.u.u.type != UnmapNotify &&
+ req->event.u.u.type != ConfigureRequest &&
+ req->event.u.u.type != ClientMessage
+ )
+ )
+ { /* not an ICCCM event */
+ return SecurityAuditResourceIDAccess(client, id);
+ }
+ break;
+ } /* case X_SendEvent on root */
+
+ case X_ChangeWindowAttributes:
+ { /* Allow selection of PropertyNotify and StructureNotify
+ * events on the root.
+ */
+ xChangeWindowAttributesReq *req =
+ (xChangeWindowAttributesReq *)(client->requestBuffer);
+ if (req->valueMask == CWEventMask)
+ {
+ CARD32 value = *((CARD32 *)(req + 1));
+ if ( (value &
+ ~(PropertyChangeMask|StructureNotifyMask)) == 0)
+ break;
+ }
+ return SecurityAuditResourceIDAccess(client, id);
+ } /* case X_ChangeWindowAttributes on root */
+
+ default:
+ {
+#ifdef LBX
+ /* XXX really need per extension dispatching */
+ if (reqtype == LbxReqCode) {
+ switch (((xReq *)client->requestBuffer)->data) {
+ case X_LbxGetProperty:
+ case X_LbxChangeProperty:
+ return rval;
+ default:
+ break;
+ }
+ }
+#endif
+ /* others not allowed */
+ return SecurityAuditResourceIDAccess(client, id);
+ }
+ }
+ } /* end server-owned window or drawable */
+ else if (SecurityAuthorizationResType == rtype)
+ {
+ SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)rval;
+ if (pAuth->trustLevel != client->trustLevel)
+ return SecurityAuditResourceIDAccess(client, id);
+ }
+ else if (RT_COLORMAP != rtype)
+ { /* don't allow anything else besides colormaps */
+ return SecurityAuditResourceIDAccess(client, id);
+ }
+ }
+ return rval;
+} /* SecurityCheckResourceIDAccess */
+
+
+/* SecurityClientStateCallback
+ *
+ * Arguments:
+ * pcbl is &ClientStateCallback.
+ * nullata is NULL.
+ * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h)
+ * which contains information about client state changes.
+ *
+ * Returns: nothing.
+ *
+ * Side Effects:
+ *
+ * If a new client is connecting, its authorization ID is copied to
+ * client->authID. If this is a generated authorization, its reference
+ * count is bumped, its timer is cancelled if it was running, and its
+ * trustlevel is copied to client->trustLevel.
+ *
+ * If a client is disconnecting and the client was using a generated
+ * authorization, the authorization's reference count is decremented, and
+ * if it is now zero, the timer for this authorization is started.
+ */
+
+static void
+SecurityClientStateCallback(pcbl, nulldata, calldata)
+ CallbackListPtr *pcbl;
+ pointer nulldata;
+ pointer calldata;
+{
+ NewClientInfoRec *pci = (NewClientInfoRec *)calldata;
+ ClientPtr client = pci->client;
+
+ switch (client->clientState)
+ {
+ case ClientStateRunning:
+ {
+ XID authId = AuthorizationIDOfClient(client);
+ SecurityAuthorizationPtr pAuth;
+
+ client->authId = authId;
+ pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId,
+ SecurityAuthorizationResType);
+ if (pAuth)
+ { /* it is a generated authorization */
+ pAuth->refcnt++;
+ if (pAuth->refcnt == 1)
+ {
+ if (pAuth->timer) TimerCancel(pAuth->timer);
+ }
+ client->trustLevel = pAuth->trustLevel;
+ if (client->trustLevel != XSecurityClientTrusted)
+ {
+ client->CheckAccess = SecurityCheckResourceIDAccess;
+ client->requestVector = client->swapped ?
+ SwappedUntrustedProcVector : UntrustedProcVector;
+ }
+ }
+ break;
+ }
+ case ClientStateGone:
+ case ClientStateRetained: /* client disconnected */
+ {
+ XID authId = client->authId;
+ SecurityAuthorizationPtr pAuth;
+
+ pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId,
+ SecurityAuthorizationResType);
+ if (pAuth)
+ { /* it is a generated authorization */
+ pAuth->refcnt--;
+ if (pAuth->refcnt == 0)
+ {
+ SecurityStartAuthorizationTimer(pAuth);
+ }
+ }
+ break;
+ }
+ default: break;
+ }
+} /* SecurityClientStateCallback */
+
+#ifdef LBX
+Bool
+SecuritySameLevel(client, authId)
+ ClientPtr client;
+ XID authId;
+{
+ SecurityAuthorizationPtr pAuth;
+
+ pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId,
+ SecurityAuthorizationResType);
+ if (pAuth)
+ return client->trustLevel == pAuth->trustLevel;
+ return client->trustLevel == XSecurityClientTrusted;
+}
+#endif
+
+/* SecurityCensorImage
+ *
+ * Called after pScreen->GetImage to prevent pieces or trusted windows from
+ * being returned in image data from an untrusted window.
+ *
+ * Arguments:
+ * client is the client doing the GetImage.
+ * pVisibleRegion is the visible region of the window.
+ * widthBytesLine is the width in bytes of one horizontal line in pBuf.
+ * pDraw is the source window.
+ * x, y, w, h is the rectangle of image data from pDraw in pBuf.
+ * format is the format of the image data in pBuf: ZPixmap or XYPixmap.
+ * pBuf is the image data.
+ *
+ * Returns: nothing.
+ *
+ * Side Effects:
+ * Any part of the rectangle (x, y, w, h) that is outside the visible
+ * region of the window will be destroyed (overwritten) in pBuf.
+ */
+void
+SecurityCensorImage(client, pVisibleRegion, widthBytesLine, pDraw, x, y, w, h,
+ format, pBuf)
+ ClientPtr client;
+ RegionPtr pVisibleRegion;
+ long widthBytesLine;
+ DrawablePtr pDraw;
+ int x, y, w, h;
+ unsigned int format;
+ char * pBuf;
+{
+ RegionRec imageRegion; /* region representing x,y,w,h */
+ RegionRec censorRegion; /* region to obliterate */
+ BoxRec imageBox;
+ int nRects;
+
+ imageBox.x1 = x;
+ imageBox.y1 = y;
+ imageBox.x2 = x + w;
+ imageBox.y2 = y + h;
+ REGION_INIT(pScreen, &imageRegion, &imageBox, 1);
+ REGION_INIT(pScreen, &censorRegion, NullBox, 0);
+
+ /* censorRegion = imageRegion - visibleRegion */
+ REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion);
+ nRects = REGION_NUM_RECTS(&censorRegion);
+ if (nRects > 0)
+ { /* we have something to censor */
+ GCPtr pScratchGC = NULL;
+ PixmapPtr pPix = NULL;
+ xRectangle *pRects = NULL;
+ Bool failed = FALSE;
+ int depth = 1;
+ int bitsPerPixel = 1;
+ int i;
+ BoxPtr pBox;
+
+ /* convert region to list-of-rectangles for PolyFillRect */
+
+ pRects = (xRectangle *)ALLOCATE_LOCAL(nRects * sizeof(xRectangle *));
+ if (!pRects)
+ {
+ failed = TRUE;
+ goto failSafe;
+ }
+ for (pBox = REGION_RECTS(&censorRegion), i = 0;
+ i < nRects;
+ i++, pBox++)
+ {
+ pRects[i].x = pBox->x1;
+ pRects[i].y = pBox->y1 - imageBox.y1;
+ pRects[i].width = pBox->x2 - pBox->x1;
+ pRects[i].height = pBox->y2 - pBox->y1;
+ }
+
+ /* use pBuf as a fake pixmap */
+
+ if (format == ZPixmap)
+ {
+ depth = pDraw->depth;
+ bitsPerPixel = pDraw->bitsPerPixel;
+ }
+
+ pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h,
+ depth, bitsPerPixel,
+ widthBytesLine, (pointer)pBuf);
+ if (!pPix)
+ {
+ failed = TRUE;
+ goto failSafe;
+ }
+
+ pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen);
+ if (!pScratchGC)
+ {
+ failed = TRUE;
+ goto failSafe;
+ }
+
+ ValidateGC(&pPix->drawable, pScratchGC);
+ (* pScratchGC->ops->PolyFillRect)(&pPix->drawable,
+ pScratchGC, nRects, pRects);
+
+ failSafe:
+ if (failed)
+ {
+ /* Censoring was not completed above. To be safe, wipe out
+ * all the image data so that nothing trusted gets out.
+ */
+ bzero(pBuf, (int)(widthBytesLine * h));
+ }
+ if (pRects) DEALLOCATE_LOCAL(pRects);
+ if (pScratchGC) FreeScratchGC(pScratchGC);
+ if (pPix) FreeScratchPixmapHeader(pPix);
+ }
+ REGION_UNINIT(pScreen, &imageRegion);
+ REGION_UNINIT(pScreen, &censorRegion);
+} /* SecurityCensorImage */
+
+/**********************************************************************/
+
+typedef struct _PropertyAccessRec {
+ ATOM name;
+ ATOM mustHaveProperty;
+ char *mustHaveValue;
+ char windowRestriction;
+#define SecurityAnyWindow 0
+#define SecurityRootWindow 1
+#define SecurityWindowWithProperty 2
+ char readAction;
+ char writeAction;
+ char destroyAction;
+ struct _PropertyAccessRec *next;
+} PropertyAccessRec, *PropertyAccessPtr;
+
+static PropertyAccessPtr PropertyAccessList = NULL;
+static char SecurityDefaultAction = SecurityErrorOperation;
+static char *SecurityPolicyFile = DEFAULTPOLICYFILE;
+static ATOM SecurityMaxPropertyName = 0;
+
+static char *SecurityKeywords[] = {
+#define SecurityKeywordComment 0
+ "#",
+#define SecurityKeywordProperty 1
+ "property",
+#define SecurityKeywordSitePolicy 2
+ "sitepolicy",
+#define SecurityKeywordRoot 3
+ "root",
+#define SecurityKeywordAny 4
+ "any"
+};
+
+#define NUMKEYWORDS (sizeof(SecurityKeywords) / sizeof(char *))
+
+#undef PROPDEBUG
+/*#define PROPDEBUG 1*/
+
+static void
+SecurityFreePropertyAccessList()
+{
+ while (PropertyAccessList)
+ {
+ PropertyAccessPtr freeit = PropertyAccessList;
+ PropertyAccessList = PropertyAccessList->next;
+ xfree(freeit);
+ }
+} /* SecurityFreePropertyAccessList */
+
+
+#define SecurityIsWhitespace(c) ( (c == ' ') || (c == '\t') || (c == '\n') )
+
+static char *
+SecuritySkipWhitespace(p)
+ char *p;
+{
+ while (SecurityIsWhitespace(*p))
+ p++;
+ return p;
+} /* SecuritySkipWhitespace */
+
+
+static char *
+SecurityParseString(rest)
+ char **rest;
+{
+ char *startOfString;
+ char *s = *rest;
+ char endChar = 0;
+
+ s = SecuritySkipWhitespace(s);
+
+ if (*s == '"' || *s == '\'')
+ {
+ endChar = *s++;
+ startOfString = s;
+ while (*s && (*s != endChar))
+ s++;
+ }
+ else
+ {
+ startOfString = s;
+ while (*s && !SecurityIsWhitespace(*s))
+ s++;
+ }
+ if (*s)
+ {
+ *s = '\0';
+ *rest = s + 1;
+ return startOfString;
+ }
+ else
+ {
+ *rest = s;
+ return (endChar) ? NULL : startOfString;
+ }
+} /* SecurityParseString */
+
+
+static int
+SecurityParseKeyword(p)
+ char **p;
+{
+ int i;
+ char *s = *p;
+ s = SecuritySkipWhitespace(s);
+ for (i = 0; i < NUMKEYWORDS; i++)
+ {
+ int len = strlen(SecurityKeywords[i]);
+ if (strncmp(s, SecurityKeywords[i], len) == 0)
+ {
+ *p = s + len;
+ return (i);
+ }
+ }
+ *p = s;
+ return -1;
+} /* SecurityParseKeyword */
+
+
+static Bool
+SecurityParsePropertyAccessRule(p)
+ char *p;
+{
+ char *propname;
+ char c;
+ char action = SecurityDefaultAction;
+ char readAction, writeAction, destroyAction;
+ PropertyAccessPtr pacl, prev, cur;
+ ATOM atom;
+ char *mustHaveProperty = NULL;
+ char *mustHaveValue = NULL;
+ Bool invalid;
+ char windowRestriction;
+ int size;
+ int keyword;
+
+ /* get property name */
+ propname = SecurityParseString(&p);
+ if (!propname || (strlen(propname) == 0))
+ return FALSE;
+
+ /* get window on which property must reside for rule to apply */
+
+ keyword = SecurityParseKeyword(&p);
+ if (keyword == SecurityKeywordRoot)
+ windowRestriction = SecurityRootWindow;
+ else if (keyword == SecurityKeywordAny)
+ windowRestriction = SecurityAnyWindow;
+ else /* not root or any, must be a property name */
+ {
+ mustHaveProperty = SecurityParseString(&p);
+ if (!mustHaveProperty || (strlen(mustHaveProperty) == 0))
+ return FALSE;
+ windowRestriction = SecurityWindowWithProperty;
+ p = SecuritySkipWhitespace(p);
+ if (*p == '=')
+ { /* property value is specified too */
+ p++; /* skip over '=' */
+ mustHaveValue = SecurityParseString(&p);
+ if (!mustHaveValue)
+ return FALSE;
+ }
+ }
+
+ /* get operations and actions */
+
+ invalid = FALSE;
+ readAction = writeAction = destroyAction = SecurityDefaultAction;
+ while ( (c = *p++) && !invalid)
+ {
+ switch (c)
+ {
+ case 'i': action = SecurityIgnoreOperation; break;
+ case 'a': action = SecurityAllowOperation; break;
+ case 'e': action = SecurityErrorOperation; break;
+
+ case 'r': readAction = action; break;
+ case 'w': writeAction = action; break;
+ case 'd': destroyAction = action; break;
+
+ default :
+ if (!SecurityIsWhitespace(c))
+ invalid = TRUE;
+ break;
+ }
+ }
+ if (invalid)
+ return FALSE;
+
+ /* We've successfully collected all the information needed for this
+ * property access rule. Now record it in a PropertyAccessRec.
+ */
+ size = sizeof(PropertyAccessRec);
+
+ /* If there is a property value string, allocate space for it
+ * right after the PropertyAccessRec.
+ */
+ if (mustHaveValue)
+ size += strlen(mustHaveValue) + 1;
+ pacl = (PropertyAccessPtr)Xalloc(size);
+ if (!pacl)
+ return FALSE;
+
+ pacl->name = MakeAtom(propname, strlen(propname), TRUE);
+ if (pacl->name == BAD_RESOURCE)
+ {
+ Xfree(pacl);
+ return FALSE;
+ }
+ if (mustHaveProperty)
+ {
+ pacl->mustHaveProperty = MakeAtom(mustHaveProperty,
+ strlen(mustHaveProperty), TRUE);
+ if (pacl->mustHaveProperty == BAD_RESOURCE)
+ {
+ Xfree(pacl);
+ return FALSE;
+ }
+ }
+ else
+ pacl->mustHaveProperty = 0;
+
+ if (mustHaveValue)
+ {
+ pacl->mustHaveValue = (char *)(pacl + 1);
+ strcpy(pacl->mustHaveValue, mustHaveValue);
+ }
+ else
+ pacl->mustHaveValue = NULL;
+
+ SecurityMaxPropertyName = max(SecurityMaxPropertyName, pacl->name);
+
+ pacl->windowRestriction = windowRestriction;
+ pacl->readAction = readAction;
+ pacl->writeAction = writeAction;
+ pacl->destroyAction = destroyAction;
+
+ /* link the new rule into the list of rules in order of increasing
+ * property name (atom) value to make searching easier
+ */
+
+ for (prev = NULL, cur = PropertyAccessList;
+ cur && cur->name <= pacl->name;
+ prev = cur, cur = cur->next)
+ ;
+ if (!prev)
+ {
+ pacl->next = cur;
+ PropertyAccessList = pacl;
+ }
+ else
+ {
+ prev->next = pacl;
+ pacl->next = cur;
+ }
+ return TRUE;
+} /* SecurityParsePropertyAccessRule */
+
+static char **SecurityPolicyStrings = NULL;
+static int nSecurityPolicyStrings = 0;
+
+static Bool
+SecurityParseSitePolicy(p)
+ char *p;
+{
+ char *policyStr = SecurityParseString(&p);
+ char *copyPolicyStr;
+ char **newStrings;
+
+ if (!policyStr)
+ return FALSE;
+
+ copyPolicyStr = (char *)Xalloc(strlen(policyStr) + 1);
+ if (!copyPolicyStr)
+ return TRUE;
+ strcpy(copyPolicyStr, policyStr);
+ newStrings = (char **)Xrealloc(SecurityPolicyStrings,
+ sizeof (char *) * (nSecurityPolicyStrings + 1));
+ if (!newStrings)
+ {
+ Xfree(copyPolicyStr);
+ return TRUE;
+ }
+
+ SecurityPolicyStrings = newStrings;
+ SecurityPolicyStrings[nSecurityPolicyStrings++] = copyPolicyStr;
+
+ return TRUE;
+
+} /* SecurityParseSitePolicy */
+
+
+char **
+SecurityGetSitePolicyStrings(n)
+ int *n;
+{
+ *n = nSecurityPolicyStrings;
+ return SecurityPolicyStrings;
+} /* SecurityGetSitePolicyStrings */
+
+static void
+SecurityFreeSitePolicyStrings()
+{
+ if (SecurityPolicyStrings)
+ {
+ assert(nSecurityPolicyStrings);
+ while (nSecurityPolicyStrings--)
+ {
+ Xfree(SecurityPolicyStrings[nSecurityPolicyStrings]);
+ }
+ Xfree(SecurityPolicyStrings);
+ SecurityPolicyStrings = NULL;
+ nSecurityPolicyStrings = 0;
+ }
+} /* SecurityFreeSitePolicyStrings */
+
+
+static void
+SecurityLoadPropertyAccessList()
+{
+ FILE *f;
+ int lineNumber = 0;
+
+ SecurityMaxPropertyName = 0;
+
+ if (!SecurityPolicyFile)
+ return;
+
+ f = fopen(SecurityPolicyFile, "r");
+ if (!f)
+ {
+ ErrorF("error opening security policy file %s\n",
+ SecurityPolicyFile);
+ return;
+ }
+
+ while (!feof(f))
+ {
+ char buf[200];
+ Bool validLine;
+ char *p;
+
+ if (!(p = fgets(buf, sizeof(buf), f)))
+ break;
+ lineNumber++;
+
+ /* if first line, check version number */
+ if (lineNumber == 1)
+ {
+ char *v = SecurityParseString(&p);
+ if (strcmp(v, SECURITY_POLICY_FILE_VERSION) != 0)
+ {
+ ErrorF("%s: invalid security policy file version, ignoring file\n",
+ SecurityPolicyFile);
+ break;
+ }
+ validLine = TRUE;
+ }
+ else
+ {
+ switch (SecurityParseKeyword(&p))
+ {
+ case SecurityKeywordComment:
+ validLine = TRUE;
+ break;
+
+ case SecurityKeywordProperty:
+ validLine = SecurityParsePropertyAccessRule(p);
+ break;
+
+ case SecurityKeywordSitePolicy:
+ validLine = SecurityParseSitePolicy(p);
+ break;
+
+ default:
+ validLine = (*p == '\0'); /* blank lines OK, others not */
+ break;
+ }
+ }
+
+ if (!validLine)
+ ErrorF("Line %d of %s invalid, ignoring\n",
+ lineNumber, SecurityPolicyFile);
+ } /* end while more input */
+
+#ifdef PROPDEBUG
+ {
+ PropertyAccessPtr pacl;
+ char *op = "aie";
+ for (pacl = PropertyAccessList; pacl; pacl = pacl->next)
+ {
+ ErrorF("property %s ", NameForAtom(pacl->name));
+ switch (pacl->windowRestriction)
+ {
+ case SecurityAnyWindow: ErrorF("any "); break;
+ case SecurityRootWindow: ErrorF("root "); break;
+ case SecurityWindowWithProperty:
+ {
+ ErrorF("%s ", NameForAtom(pacl->mustHaveProperty));
+ if (pacl->mustHaveValue)
+ ErrorF(" = \"%s\" ", pacl->mustHaveValue);
+
+ }
+ break;
+ }
+ ErrorF("%cr %cw %cd\n", op[pacl->readAction],
+ op[pacl->writeAction], op[pacl->destroyAction]);
+ }
+ }
+#endif /* PROPDEBUG */
+
+ fclose(f);
+} /* SecurityLoadPropertyAccessList */
+
+
+static Bool
+SecurityMatchString(ws, cs)
+ char *ws;
+ char *cs;
+{
+ while (*ws && *cs)
+ {
+ if (*ws == '*')
+ {
+ Bool match = FALSE;
+ ws++;
+ while (!(match = SecurityMatchString(ws, cs)) && *cs)
+ {
+ cs++;
+ }
+ return match;
+ }
+ else if (*ws == *cs)
+ {
+ ws++;
+ cs++;
+ }
+ else break;
+ }
+ return ( ( (*ws == '\0') || ((*ws == '*') && *(ws+1) == '\0') )
+ && (*cs == '\0') );
+} /* SecurityMatchString */
+
+#ifdef PROPDEBUG
+#include <sys/types.h>
+#include <sys/stat.h>
+#endif
+
+
+char
+SecurityCheckPropertyAccess(client, pWin, propertyName, access_mode)
+ ClientPtr client;
+ WindowPtr pWin;
+ ATOM propertyName;
+ Mask access_mode;
+{
+ PropertyAccessPtr pacl;
+ char action = SecurityDefaultAction;
+
+ /* if client trusted or window untrusted, allow operation */
+
+ if ( (client->trustLevel == XSecurityClientTrusted) ||
+ (wClient(pWin)->trustLevel != XSecurityClientTrusted) )
+ return SecurityAllowOperation;
+
+#ifdef PROPDEBUG
+ /* For testing, it's more convenient if the property rules file gets
+ * reloaded whenever it changes, so we can rapidly try things without
+ * having to reset the server.
+ */
+ {
+ struct stat buf;
+ static time_t lastmod = 0;
+ int ret = stat(SecurityPolicyFile , &buf);
+ if ( (ret == 0) && (buf.st_mtime > lastmod) )
+ {
+ ErrorF("reloading property rules\n");
+ SecurityFreePropertyAccessList();
+ SecurityLoadPropertyAccessList();
+ lastmod = buf.st_mtime;
+ }
+ }
+#endif
+
+ /* If the property atom is bigger than any atoms on the list,
+ * we know we won't find it, so don't even bother looking.
+ */
+ if (propertyName <= SecurityMaxPropertyName)
+ {
+ /* untrusted client operating on trusted window; see if it's allowed */
+
+ for (pacl = PropertyAccessList; pacl; pacl = pacl->next)
+ {
+ if (pacl->name < propertyName)
+ continue;
+ if (pacl->name > propertyName)
+ break;
+
+ /* pacl->name == propertyName, so see if it applies to this window */
+
+ switch (pacl->windowRestriction)
+ {
+ case SecurityAnyWindow: /* always applies */
+ break;
+
+ case SecurityRootWindow:
+ {
+ /* if not a root window, this rule doesn't apply */
+ if (pWin->parent)
+ continue;
+ }
+ break;
+
+ case SecurityWindowWithProperty:
+ {
+ PropertyPtr pProp = wUserProps (pWin);
+ Bool match = FALSE;
+ char *p;
+ char *pEndData;
+
+ while (pProp)
+ {
+ if (pProp->propertyName == pacl->mustHaveProperty)
+ break;
+ pProp = pProp->next;
+ }
+ if (!pProp)
+ continue;
+ if (!pacl->mustHaveValue)
+ break;
+ if (pProp->type != XA_STRING || pProp->format != 8)
+ continue;
+
+ p = pProp->data;
+ pEndData = ((char *)pProp->data) + pProp->size;
+ while (!match && p < pEndData)
+ {
+ if (SecurityMatchString(pacl->mustHaveValue, p))
+ match = TRUE;
+ else
+ { /* skip to the next string */
+ while (*p++ && p < pEndData)
+ ;
+ }
+ }
+ if (!match)
+ continue;
+ }
+ break; /* end case SecurityWindowWithProperty */
+ } /* end switch on windowRestriction */
+
+ /* If we get here, the property access rule pacl applies.
+ * If pacl doesn't apply, something above should have
+ * executed a continue, which will skip the follwing code.
+ */
+ action = SecurityAllowOperation;
+ if (access_mode & SecurityReadAccess)
+ action = max(action, pacl->readAction);
+ if (access_mode & SecurityWriteAccess)
+ action = max(action, pacl->writeAction);
+ if (access_mode & SecurityDestroyAccess)
+ action = max(action, pacl->destroyAction);
+ break;
+ } /* end for each pacl */
+ } /* end if propertyName <= SecurityMaxPropertyName */
+
+ if (SecurityAllowOperation != action)
+ { /* audit the access violation */
+ int cid = CLIENT_ID(pWin->drawable.id);
+ int reqtype = ((xReq *)client->requestBuffer)->reqType;
+ char *actionstr = (SecurityIgnoreOperation == action) ?
+ "ignored" : "error";
+ SecurityAudit("client %d attempted request %d with window 0x%x property %s (atom 0x%x) of client %d, %s\n",
+ client->index, reqtype, pWin->drawable.id,
+ NameForAtom(propertyName), propertyName, cid, actionstr);
+ }
+ return action;
+} /* SecurityCheckPropertyAccess */
+
+
+/* SecurityResetProc
+ *
+ * Arguments:
+ * extEntry is the extension information for the security extension.
+ *
+ * Returns: nothing.
+ *
+ * Side Effects:
+ * Performs any cleanup needed by Security at server shutdown time.
+ */
+
+static void
+SecurityResetProc(extEntry)
+ ExtensionEntry *extEntry;
+{
+ SecurityFreePropertyAccessList();
+ SecurityFreeSitePolicyStrings();
+} /* SecurityResetProc */
+
+
+int
+XSecurityOptions(argc, argv, i)
+ int argc;
+ char **argv;
+ int i;
+{
+ if (strcmp(argv[i], "-sp") == 0)
+ {
+ if (i < argc)
+ SecurityPolicyFile = argv[++i];
+ return (i + 1);
+ }
+ return (i);
+} /* XSecurityOptions */
+
+
+
+/* SecurityExtensionInit
+ *
+ * Arguments: none.
+ *
+ * Returns: nothing.
+ *
+ * Side Effects:
+ * Enables the Security extension if possible.
+ */
+
+void
+SecurityExtensionInit()
+{
+ ExtensionEntry *extEntry;
+ int i;
+
+ SecurityAuthorizationResType =
+ CreateNewResourceType(SecurityDeleteAuthorization);
+
+ RTEventClient = CreateNewResourceType(
+ SecurityDeleteAuthorizationEventClient);
+
+ if (!SecurityAuthorizationResType || !RTEventClient)
+ return;
+
+ RTEventClient |= RC_NEVERRETAIN;
+
+ if (!AddCallback(&ClientStateCallback, SecurityClientStateCallback, NULL))
+ return;
+
+ extEntry = AddExtension(SECURITY_EXTENSION_NAME,
+ XSecurityNumberEvents, XSecurityNumberErrors,
+ ProcSecurityDispatch, SProcSecurityDispatch,
+ SecurityResetProc, StandardMinorOpcode);
+
+ SecurityErrorBase = extEntry->errorBase;
+ SecurityEventBase = extEntry->eventBase;
+
+ EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] =
+ SwapSecurityAuthorizationRevokedEvent;
+
+ /* initialize untrusted proc vectors */
+
+ for (i = 0; i < 128; i++)
+ {
+ UntrustedProcVector[i] = ProcVector[i];
+ SwappedUntrustedProcVector[i] = SwappedProcVector[i];
+ }
+
+ /* make sure insecure extensions are not allowed */
+
+ for (i = 128; i < 256; i++)
+ {
+ if (!UntrustedProcVector[i])
+ {
+ UntrustedProcVector[i] = ProcBadRequest;
+ SwappedUntrustedProcVector[i] = ProcBadRequest;
+ }
+ }
+
+ SecurityLoadPropertyAccessList();
+
+} /* SecurityExtensionInit */
diff --git a/Xext/shape.c b/Xext/shape.c
new file mode 100644
index 000000000..bff7d2502
--- /dev/null
+++ b/Xext/shape.c
@@ -0,0 +1,1217 @@
+/************************************************************
+
+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.
+
+********************************************************/
+
+/* $Xorg: shape.c,v 1.4 2001/02/09 02:04:32 xorgcvs Exp $ */
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <stdio.h>
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "opaque.h"
+#define _SHAPE_SERVER_ /* don't want Xlib structures */
+#include "shapestr.h"
+#include "regionstr.h"
+#include "gcstruct.h"
+
+#ifdef PANORAMIX
+#include "panoramiX.h"
+#endif
+
+static int ShapeFreeClient(), ShapeFreeEvents();
+static void SendShapeNotify();
+static int ProcShapeDispatch(), SProcShapeDispatch();
+static void ShapeResetProc(), SShapeNotifyEvent();
+
+static unsigned char ShapeReqCode = 0;
+static int ShapeEventBase = 0;
+static RESTYPE ClientType, EventType; /* resource types for event masks */
+
+#ifdef PANORAMIX
+extern int PanoramiXNumScreens;
+extern Bool noPanoramiXExtension;
+extern PanoramiXWindow *PanoramiXWinRoot;
+extern PanoramiXPmap *PanoramiXPmapRoot;
+#endif
+/*
+ * each window has a list of clients requesting
+ * ShapeNotify events. Each client has a resource
+ * for each window it selects ShapeNotify input for,
+ * this resource is used to delete the ShapeNotifyRec
+ * entry from the per-window queue.
+ */
+
+typedef struct _ShapeEvent *ShapeEventPtr;
+
+typedef struct _ShapeEvent {
+ ShapeEventPtr next;
+ ClientPtr client;
+ WindowPtr window;
+ XID clientResource;
+} ShapeEventRec;
+
+/****************
+ * ShapeExtensionInit
+ *
+ * Called from InitExtensions in main() or from QueryExtension() if the
+ * extension is dynamically loaded.
+ *
+ ****************/
+
+void
+ShapeExtensionInit()
+{
+ ExtensionEntry *extEntry, *AddExtension();
+
+ ClientType = CreateNewResourceType(ShapeFreeClient);
+ EventType = CreateNewResourceType(ShapeFreeEvents);
+ if (ClientType && EventType &&
+ (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0,
+ ProcShapeDispatch, SProcShapeDispatch,
+ ShapeResetProc, StandardMinorOpcode)))
+ {
+ ShapeReqCode = (unsigned char)extEntry->base;
+ ShapeEventBase = extEntry->eventBase;
+ EventSwapVector[ShapeEventBase] = SShapeNotifyEvent;
+ }
+}
+
+/*ARGSUSED*/
+static void
+ShapeResetProc (extEntry)
+ExtensionEntry *extEntry;
+{
+}
+
+static
+RegionOperate (client, pWin, kind, destRgnp, srcRgn, op, xoff, yoff, create)
+ ClientPtr client;
+ WindowPtr pWin;
+ int kind;
+ RegionPtr *destRgnp, srcRgn;
+ int op;
+ int xoff, yoff;
+ RegionPtr (*create)(); /* creates a reasonable *destRgnp */
+{
+ ScreenPtr pScreen = pWin->drawable.pScreen;
+
+ if (srcRgn && (xoff || yoff))
+ REGION_TRANSLATE(pScreen, srcRgn, xoff, yoff);
+ if (!pWin->parent)
+ {
+ if (srcRgn)
+ REGION_DESTROY(pScreen, srcRgn);
+ return Success;
+ }
+ switch (op) {
+ case ShapeSet:
+ if (*destRgnp)
+ REGION_DESTROY(pScreen, *destRgnp);
+ *destRgnp = srcRgn;
+ srcRgn = 0;
+ break;
+ case ShapeUnion:
+ if (*destRgnp)
+ REGION_UNION(pScreen, *destRgnp, *destRgnp, srcRgn);
+ break;
+ case ShapeIntersect:
+ if (*destRgnp)
+ REGION_INTERSECT(pScreen, *destRgnp, *destRgnp, srcRgn);
+ else {
+ *destRgnp = srcRgn;
+ srcRgn = 0;
+ }
+ break;
+ case ShapeSubtract:
+ if (!*destRgnp)
+ *destRgnp = (*create)(pWin);
+ REGION_SUBTRACT(pScreen, *destRgnp, *destRgnp, srcRgn);
+ break;
+ case ShapeInvert:
+ if (!*destRgnp)
+ *destRgnp = REGION_CREATE(pScreen, (BoxPtr) 0, 0);
+ else
+ REGION_SUBTRACT(pScreen, *destRgnp, srcRgn, *destRgnp);
+ break;
+ default:
+ client->errorValue = op;
+ return BadValue;
+ }
+ if (srcRgn)
+ REGION_DESTROY(pScreen, srcRgn);
+ (*pScreen->SetShape) (pWin);
+ SendShapeNotify (pWin, kind);
+ return Success;
+}
+
+static RegionPtr
+CreateBoundingShape (pWin)
+ WindowPtr pWin;
+{
+ BoxRec extents;
+
+ extents.x1 = -wBorderWidth (pWin);
+ extents.y1 = -wBorderWidth (pWin);
+ extents.x2 = pWin->drawable.width + wBorderWidth (pWin);
+ extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
+ return REGION_CREATE(pWin->drawable.pScreen, &extents, 1);
+}
+
+static RegionPtr
+CreateClipShape (pWin)
+ WindowPtr pWin;
+{
+ BoxRec extents;
+
+ extents.x1 = 0;
+ extents.y1 = 0;
+ extents.x2 = pWin->drawable.width;
+ extents.y2 = pWin->drawable.height;
+ return REGION_CREATE(pWin->drawable.pScreen, &extents, 1);
+}
+
+static int
+ProcShapeQueryVersion (client)
+ register ClientPtr client;
+{
+ REQUEST(xShapeQueryVersionReq);
+ xShapeQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xShapeQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = SHAPE_MAJOR_VERSION;
+ rep.minorVersion = SHAPE_MINOR_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof (xShapeQueryVersionReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+/*****************
+ * ProcShapeRectangles
+ *
+ *****************/
+#ifdef PANORAMIX
+static int
+ProcPanoramiXShapeRectangles (client)
+ register ClientPtr client;
+{
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ REQUEST(xShapeRectanglesReq);
+ xRectangle *prects;
+ int nrects, ctype;
+ RegionPtr srcRgn;
+ RegionPtr *destRgn;
+ RegionPtr (*createDefault)();
+ int destBounding;
+
+ register int result;
+ int j;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+
+ REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq);
+ PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest);
+ IF_RETURN(!pPanoramiXWin, BadRequest);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) {
+ stuff->dest = pPanoramiXWin->info[j].id;
+ result = ProcShapeRectangles (client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+#endif
+
+#ifdef PANORAMIX
+int
+#else
+static int
+#endif
+ProcShapeRectangles (client)
+ register ClientPtr client;
+{
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ REQUEST(xShapeRectanglesReq);
+ xRectangle *prects;
+ int nrects, ctype;
+ RegionPtr srcRgn;
+ RegionPtr *destRgn;
+ RegionPtr (*createDefault)();
+ int destBounding;
+
+ REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq);
+ UpdateCurrentTime();
+ pWin = LookupWindow (stuff->dest, client);
+ if (!pWin)
+ return BadWindow;
+ switch (stuff->destKind) {
+ case ShapeBounding:
+ destBounding = 1;
+ createDefault = CreateBoundingShape;
+ break;
+ case ShapeClip:
+ destBounding = 0;
+ createDefault = CreateClipShape;
+ break;
+ default:
+ client->errorValue = stuff->destKind;
+ return BadValue;
+ }
+ if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
+ (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded))
+ {
+ client->errorValue = stuff->ordering;
+ return BadValue;
+ }
+ pScreen = pWin->drawable.pScreen;
+ nrects = ((stuff->length << 2) - sizeof(xShapeRectanglesReq));
+ if (nrects & 4)
+ return BadLength;
+ nrects >>= 3;
+ prects = (xRectangle *) &stuff[1];
+ ctype = VerifyRectOrder(nrects, prects, (int)stuff->ordering);
+ if (ctype < 0)
+ return BadMatch;
+ srcRgn = RECTS_TO_REGION(pScreen, nrects, prects, ctype);
+
+ if (!pWin->optional)
+ MakeWindowOptional (pWin);
+ if (destBounding)
+ destRgn = &pWin->optional->boundingShape;
+ else
+ destRgn = &pWin->optional->clipShape;
+
+ return RegionOperate (client, pWin, (int)stuff->destKind,
+ destRgn, srcRgn, (int)stuff->op,
+ stuff->xOff, stuff->yOff, createDefault);
+}
+
+/**************
+ * ProcShapeMask
+ **************/
+
+#ifdef PANORAMIX
+static int
+ProcPanoramiXShapeMask (client)
+ register ClientPtr client;
+{
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ REQUEST(xShapeMaskReq);
+ RegionPtr srcRgn;
+ RegionPtr *destRgn;
+ PixmapPtr pPixmap;
+ RegionPtr (*createDefault)();
+ int destBounding;
+
+ register int result;
+ int j;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+ PanoramiXPmap *pPmap = PanoramiXPmapRoot;
+
+ REQUEST_SIZE_MATCH (xShapeMaskReq);
+ PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest);
+ IF_RETURN(!pPanoramiXWin, BadRequest);
+ PANORAMIXFIND_ID(pPmap, stuff->src);
+ IF_RETURN(!pPmap, BadRequest);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) {
+ stuff->dest = pPanoramiXWin->info[j].id;
+ stuff->src = pPmap->info[j].id;
+ result = ProcShapeMask (client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+#endif
+
+#ifdef PANORAMIX
+int
+#else
+static int
+#endif
+ProcShapeMask (client)
+ register ClientPtr client;
+{
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ REQUEST(xShapeMaskReq);
+ RegionPtr srcRgn;
+ RegionPtr *destRgn;
+ PixmapPtr pPixmap;
+ RegionPtr (*createDefault)();
+ int destBounding;
+
+ REQUEST_SIZE_MATCH (xShapeMaskReq);
+ UpdateCurrentTime();
+ pWin = SecurityLookupWindow (stuff->dest, client, SecurityWriteAccess);
+ if (!pWin)
+ return BadWindow;
+ switch (stuff->destKind) {
+ case ShapeBounding:
+ destBounding = 1;
+ createDefault = CreateBoundingShape;
+ break;
+ case ShapeClip:
+ destBounding = 0;
+ createDefault = CreateClipShape;
+ break;
+ default:
+ client->errorValue = stuff->destKind;
+ return BadValue;
+ }
+ pScreen = pWin->drawable.pScreen;
+ if (stuff->src == None)
+ srcRgn = 0;
+ else {
+ pPixmap = (PixmapPtr) SecurityLookupIDByType(client, stuff->src,
+ RT_PIXMAP, SecurityReadAccess);
+ if (!pPixmap)
+ return BadPixmap;
+ if (pPixmap->drawable.pScreen != pScreen ||
+ pPixmap->drawable.depth != 1)
+ return BadMatch;
+ srcRgn = BITMAP_TO_REGION(pScreen, pPixmap);
+ if (!srcRgn)
+ return BadAlloc;
+ }
+
+ if (!pWin->optional)
+ MakeWindowOptional (pWin);
+ if (destBounding)
+ destRgn = &pWin->optional->boundingShape;
+ else
+ destRgn = &pWin->optional->clipShape;
+
+ return RegionOperate (client, pWin, (int)stuff->destKind,
+ destRgn, srcRgn, (int)stuff->op,
+ stuff->xOff, stuff->yOff, createDefault);
+}
+
+/************
+ * ProcShapeCombine
+ ************/
+#ifdef PANORAMIX
+static int
+ProcPanoramiXShapeCombine (client)
+ register ClientPtr client;
+{
+ WindowPtr pSrcWin, pDestWin;
+ ScreenPtr pScreen;
+ REQUEST(xShapeCombineReq);
+ RegionPtr srcRgn;
+ RegionPtr *destRgn;
+ RegionPtr (*createDefault)();
+ RegionPtr (*createSrc)();
+ RegionPtr tmp;
+ int destBounding;
+
+ register int result;
+ int j;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+
+ REQUEST_AT_LEAST_SIZE (xShapeCombineReq);
+ PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest);
+ IF_RETURN(!pPanoramiXWin, BadRequest);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) {
+ stuff->dest = pPanoramiXWin->info[j].id;
+ result = ProcShapeCombine (client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+#endif
+
+#ifdef PANORAMIX
+int
+#else
+static int
+#endif
+ProcShapeCombine (client)
+ register ClientPtr client;
+{
+ WindowPtr pSrcWin, pDestWin;
+ ScreenPtr pScreen;
+ REQUEST(xShapeCombineReq);
+ RegionPtr srcRgn;
+ RegionPtr *destRgn;
+ RegionPtr (*createDefault)();
+ RegionPtr (*createSrc)();
+ RegionPtr tmp;
+ int destBounding;
+
+ REQUEST_SIZE_MATCH (xShapeCombineReq);
+ UpdateCurrentTime();
+ pDestWin = LookupWindow (stuff->dest, client);
+ if (!pDestWin)
+ return BadWindow;
+ if (!pDestWin->optional)
+ MakeWindowOptional (pDestWin);
+ switch (stuff->destKind) {
+ case ShapeBounding:
+ destBounding = 1;
+ createDefault = CreateBoundingShape;
+ break;
+ case ShapeClip:
+ destBounding = 0;
+ createDefault = CreateClipShape;
+ break;
+ default:
+ client->errorValue = stuff->destKind;
+ return BadValue;
+ }
+ pScreen = pDestWin->drawable.pScreen;
+
+ pSrcWin = LookupWindow (stuff->src, client);
+ if (!pSrcWin)
+ return BadWindow;
+ switch (stuff->srcKind) {
+ case ShapeBounding:
+ srcRgn = wBoundingShape (pSrcWin);
+ createSrc = CreateBoundingShape;
+ break;
+ case ShapeClip:
+ srcRgn = wClipShape (pSrcWin);
+ createSrc = CreateClipShape;
+ break;
+ default:
+ client->errorValue = stuff->srcKind;
+ return BadValue;
+ }
+ if (pSrcWin->drawable.pScreen != pScreen)
+ {
+ return BadMatch;
+ }
+
+ if (srcRgn) {
+ tmp = REGION_CREATE(pScreen, (BoxPtr) 0, 0);
+ REGION_COPY(pScreen, tmp, srcRgn);
+ srcRgn = tmp;
+ } else
+ srcRgn = (*createSrc) (pSrcWin);
+
+ if (!pDestWin->optional)
+ MakeWindowOptional (pDestWin);
+ if (destBounding)
+ destRgn = &pDestWin->optional->boundingShape;
+ else
+ destRgn = &pDestWin->optional->clipShape;
+
+ return RegionOperate (client, pDestWin, (int)stuff->destKind,
+ destRgn, srcRgn, (int)stuff->op,
+ stuff->xOff, stuff->yOff, createDefault);
+}
+
+/*************
+ * ProcShapeOffset
+ *************/
+#ifdef PANORAMIX
+static int
+ProcPanoramiXShapeOffset (client)
+ register ClientPtr client;
+{
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ REQUEST(xShapeOffsetReq);
+ RegionPtr srcRgn;
+
+ register int result;
+ int j;
+ PanoramiXWindow *pPanoramiXWin = PanoramiXWinRoot;
+
+ REQUEST_AT_LEAST_SIZE (xShapeOffsetReq);
+ PANORAMIXFIND_ID(pPanoramiXWin,stuff->dest);
+ IF_RETURN(!pPanoramiXWin, BadRequest);
+ FOR_NSCREENS_OR_ONCE(pPanoramiXWin , j) {
+ stuff->dest = pPanoramiXWin->info[j].id;
+ result = ProcShapeOffset (client);
+ BREAK_IF(result != Success);
+ }
+ return (result);
+}
+#endif
+
+#ifdef PANORAMIX
+int
+#else
+static int
+#endif
+ProcShapeOffset (client)
+ register ClientPtr client;
+{
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+ REQUEST(xShapeOffsetReq);
+ RegionPtr srcRgn;
+
+ REQUEST_SIZE_MATCH (xShapeOffsetReq);
+ UpdateCurrentTime();
+ pWin = LookupWindow (stuff->dest, client);
+ if (!pWin)
+ return BadWindow;
+ switch (stuff->destKind) {
+ case ShapeBounding:
+ srcRgn = wBoundingShape (pWin);
+ break;
+ case ShapeClip:
+ srcRgn = wClipShape(pWin);
+ break;
+ default:
+ client->errorValue = stuff->destKind;
+ return BadValue;
+ }
+ pScreen = pWin->drawable.pScreen;
+ if (srcRgn)
+ {
+ REGION_TRANSLATE(pScreen, srcRgn, stuff->xOff, stuff->yOff);
+ (*pScreen->SetShape) (pWin);
+ }
+ SendShapeNotify (pWin, (int)stuff->destKind);
+ return Success;
+}
+
+static int
+ProcShapeQueryExtents (client)
+ register ClientPtr client;
+{
+ REQUEST(xShapeQueryExtentsReq);
+ WindowPtr pWin;
+ xShapeQueryExtentsReply rep;
+ BoxRec extents, *pExtents;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xShapeQueryExtentsReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.boundingShaped = (wBoundingShape(pWin) != 0);
+ rep.clipShaped = (wClipShape(pWin) != 0);
+ if (wBoundingShape(pWin)) {
+ /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */
+ pExtents = REGION_EXTENTS(pWin->drawable.pScreen, wBoundingShape(pWin));
+ extents = *pExtents;
+ } else {
+ extents.x1 = -wBorderWidth (pWin);
+ extents.y1 = -wBorderWidth (pWin);
+ extents.x2 = pWin->drawable.width + wBorderWidth (pWin);
+ extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
+ }
+ rep.xBoundingShape = extents.x1;
+ rep.yBoundingShape = extents.y1;
+ rep.widthBoundingShape = extents.x2 - extents.x1;
+ rep.heightBoundingShape = extents.y2 - extents.y1;
+ if (wClipShape(pWin)) {
+ /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */
+ pExtents = REGION_EXTENTS(pWin->drawable.pScreen, wClipShape(pWin));
+ extents = *pExtents;
+ } else {
+ extents.x1 = 0;
+ extents.y1 = 0;
+ extents.x2 = pWin->drawable.width;
+ extents.y2 = pWin->drawable.height;
+ }
+ rep.xClipShape = extents.x1;
+ rep.yClipShape = extents.y1;
+ rep.widthClipShape = extents.x2 - extents.x1;
+ rep.heightClipShape = extents.y2 - extents.y1;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.xBoundingShape, n);
+ swaps(&rep.yBoundingShape, n);
+ swaps(&rep.widthBoundingShape, n);
+ swaps(&rep.heightBoundingShape, n);
+ swaps(&rep.xClipShape, n);
+ swaps(&rep.yClipShape, n);
+ swaps(&rep.widthClipShape, n);
+ swaps(&rep.heightClipShape, n);
+ }
+ WriteToClient(client, sizeof (xShapeQueryExtentsReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+/*ARGSUSED*/
+static int
+ShapeFreeClient (data, id)
+ pointer data;
+ XID id;
+{
+ ShapeEventPtr pShapeEvent;
+ WindowPtr pWin;
+ ShapeEventPtr *pHead, pCur, pPrev;
+
+ pShapeEvent = (ShapeEventPtr) data;
+ pWin = pShapeEvent->window;
+ pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType);
+ if (pHead) {
+ pPrev = 0;
+ for (pCur = *pHead; pCur && pCur != pShapeEvent; pCur=pCur->next)
+ pPrev = pCur;
+ if (pCur)
+ {
+ if (pPrev)
+ pPrev->next = pShapeEvent->next;
+ else
+ *pHead = pShapeEvent->next;
+ }
+ }
+ xfree ((pointer) pShapeEvent);
+ return 1;
+}
+
+/*ARGSUSED*/
+static int
+ShapeFreeEvents (data, id)
+ pointer data;
+ XID id;
+{
+ ShapeEventPtr *pHead, pCur, pNext;
+
+ pHead = (ShapeEventPtr *) data;
+ for (pCur = *pHead; pCur; pCur = pNext) {
+ pNext = pCur->next;
+ FreeResource (pCur->clientResource, ClientType);
+ xfree ((pointer) pCur);
+ }
+ xfree ((pointer) pHead);
+ return 1;
+}
+
+static int
+ProcShapeSelectInput (client)
+ register ClientPtr client;
+{
+ REQUEST(xShapeSelectInputReq);
+ WindowPtr pWin;
+ ShapeEventPtr pShapeEvent, pNewShapeEvent, *pHead;
+ XID clientResource;
+
+ REQUEST_SIZE_MATCH (xShapeSelectInputReq);
+ pWin = SecurityLookupWindow (stuff->window, client, SecurityWriteAccess);
+ if (!pWin)
+ return BadWindow;
+ pHead = (ShapeEventPtr *)SecurityLookupIDByType(client,
+ pWin->drawable.id, EventType, SecurityWriteAccess);
+ switch (stuff->enable) {
+ case xTrue:
+ if (pHead) {
+
+ /* check for existing entry. */
+ for (pShapeEvent = *pHead;
+ pShapeEvent;
+ pShapeEvent = pShapeEvent->next)
+ {
+ if (pShapeEvent->client == client)
+ return Success;
+ }
+ }
+
+ /* build the entry */
+ pNewShapeEvent = (ShapeEventPtr)
+ xalloc (sizeof (ShapeEventRec));
+ if (!pNewShapeEvent)
+ return BadAlloc;
+ pNewShapeEvent->next = 0;
+ pNewShapeEvent->client = client;
+ pNewShapeEvent->window = pWin;
+ /*
+ * add a resource that will be deleted when
+ * the client goes away
+ */
+ clientResource = FakeClientID (client->index);
+ pNewShapeEvent->clientResource = clientResource;
+ if (!AddResource (clientResource, ClientType, (pointer)pNewShapeEvent))
+ return BadAlloc;
+ /*
+ * create a resource to contain a pointer to the list
+ * of clients selecting input. This must be indirect as
+ * the list may be arbitrarily rearranged which cannot be
+ * done through the resource database.
+ */
+ if (!pHead)
+ {
+ pHead = (ShapeEventPtr *) xalloc (sizeof (ShapeEventPtr));
+ if (!pHead ||
+ !AddResource (pWin->drawable.id, EventType, (pointer)pHead))
+ {
+ FreeResource (clientResource, RT_NONE);
+ return BadAlloc;
+ }
+ *pHead = 0;
+ }
+ pNewShapeEvent->next = *pHead;
+ *pHead = pNewShapeEvent;
+ break;
+ case xFalse:
+ /* delete the interest */
+ if (pHead) {
+ pNewShapeEvent = 0;
+ for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
+ if (pShapeEvent->client == client)
+ break;
+ pNewShapeEvent = pShapeEvent;
+ }
+ if (pShapeEvent) {
+ FreeResource (pShapeEvent->clientResource, ClientType);
+ if (pNewShapeEvent)
+ pNewShapeEvent->next = pShapeEvent->next;
+ else
+ *pHead = pShapeEvent->next;
+ xfree (pShapeEvent);
+ }
+ }
+ break;
+ default:
+ client->errorValue = stuff->enable;
+ return BadValue;
+ }
+ return Success;
+}
+
+/*
+ * deliver the event
+ */
+
+static void
+SendShapeNotify (pWin, which)
+ WindowPtr pWin;
+ int which;
+{
+ ShapeEventPtr *pHead, pShapeEvent;
+ ClientPtr client;
+ xShapeNotifyEvent se;
+ BoxRec extents;
+ RegionPtr region;
+ BYTE shaped;
+
+ pHead = (ShapeEventPtr *) LookupIDByType(pWin->drawable.id, EventType);
+ if (!pHead)
+ return;
+ if (which == ShapeBounding) {
+ region = wBoundingShape(pWin);
+ if (region) {
+ extents = *REGION_EXTENTS(pWin->drawable.pScreen, region);
+ shaped = xTrue;
+ } else {
+ extents.x1 = -wBorderWidth (pWin);
+ extents.y1 = -wBorderWidth (pWin);
+ extents.x2 = pWin->drawable.width + wBorderWidth (pWin);
+ extents.y2 = pWin->drawable.height + wBorderWidth (pWin);
+ shaped = xFalse;
+ }
+ } else {
+ region = wClipShape(pWin);
+ if (region) {
+ extents = *REGION_EXTENTS(pWin->drawable.pScreen, region);
+ shaped = xTrue;
+ } else {
+ extents.x1 = 0;
+ extents.y1 = 0;
+ extents.x2 = pWin->drawable.width;
+ extents.y2 = pWin->drawable.height;
+ shaped = xFalse;
+ }
+ }
+ for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) {
+ client = pShapeEvent->client;
+ if (client == serverClient || client->clientGone)
+ continue;
+ se.type = ShapeNotify + ShapeEventBase;
+ se.kind = which;
+ se.window = pWin->drawable.id;
+ se.sequenceNumber = client->sequence;
+ se.x = extents.x1;
+ se.y = extents.y1;
+ se.width = extents.x2 - extents.x1;
+ se.height = extents.y2 - extents.y1;
+ se.time = currentTime.milliseconds;
+ se.shaped = shaped;
+ WriteEventsToClient (client, 1, (xEvent *) &se);
+ }
+}
+
+static int
+ProcShapeInputSelected (client)
+ register ClientPtr client;
+{
+ REQUEST(xShapeInputSelectedReq);
+ WindowPtr pWin;
+ ShapeEventPtr pShapeEvent, *pHead;
+ int enabled;
+ xShapeInputSelectedReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH (xShapeInputSelectedReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ pHead = (ShapeEventPtr *) SecurityLookupIDByType(client,
+ pWin->drawable.id, EventType, SecurityReadAccess);
+ enabled = xFalse;
+ if (pHead) {
+ for (pShapeEvent = *pHead;
+ pShapeEvent;
+ pShapeEvent = pShapeEvent->next)
+ {
+ if (pShapeEvent->client == client) {
+ enabled = xTrue;
+ break;
+ }
+ }
+ }
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.enabled = enabled;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ }
+ WriteToClient (client, sizeof (xShapeInputSelectedReply), (char *) &rep);
+ return (client->noClientException);
+}
+
+static int
+ProcShapeGetRectangles (client)
+ register ClientPtr client;
+{
+ REQUEST(xShapeGetRectanglesReq);
+ WindowPtr pWin;
+ xShapeGetRectanglesReply rep;
+ xRectangle *rects;
+ int nrects, i;
+ RegionPtr region;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
+ pWin = LookupWindow (stuff->window, client);
+ if (!pWin)
+ return BadWindow;
+ switch (stuff->kind) {
+ case ShapeBounding:
+ region = wBoundingShape(pWin);
+ break;
+ case ShapeClip:
+ region = wClipShape(pWin);
+ break;
+ default:
+ client->errorValue = stuff->kind;
+ return BadValue;
+ }
+ if (!region) {
+ nrects = 1;
+ rects = (xRectangle *) ALLOCATE_LOCAL (sizeof (xRectangle));
+ if (!rects)
+ return BadAlloc;
+ switch (stuff->kind) {
+ case ShapeBounding:
+ rects->x = - (int) wBorderWidth (pWin);
+ rects->y = - (int) wBorderWidth (pWin);
+ rects->width = pWin->drawable.width + wBorderWidth (pWin);
+ rects->height = pWin->drawable.height + wBorderWidth (pWin);
+ break;
+ case ShapeClip:
+ rects->x = 0;
+ rects->y = 0;
+ rects->width = pWin->drawable.width;
+ rects->height = pWin->drawable.height;
+ break;
+ }
+ } else {
+ BoxPtr box;
+ nrects = REGION_NUM_RECTS(region);
+ box = REGION_RECTS(region);
+ rects = (xRectangle *) ALLOCATE_LOCAL (nrects * sizeof (xRectangle));
+ if (!rects && nrects)
+ return BadAlloc;
+ for (i = 0; i < nrects; i++, box++) {
+ rects[i].x = box->x1;
+ rects[i].y = box->y1;
+ rects[i].width = box->x2 - box->x1;
+ rects[i].height = box->y2 - box->y1;
+ }
+ }
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = (nrects * sizeof (xRectangle)) >> 2;
+ rep.ordering = YXBanded;
+ rep.nrects = nrects;
+ if (client->swapped) {
+ swaps (&rep.sequenceNumber, n);
+ swapl (&rep.length, n);
+ swapl (&rep.nrects, n);
+ SwapShorts ((short *)rects, (unsigned long)nrects * 4);
+ }
+ WriteToClient (client, sizeof (rep), (char *) &rep);
+ WriteToClient (client, nrects * sizeof (xRectangle), (char *) rects);
+ DEALLOCATE_LOCAL (rects);
+ return client->noClientException;
+}
+
+static int
+ProcShapeDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data) {
+ case X_ShapeQueryVersion:
+ return ProcShapeQueryVersion (client);
+ case X_ShapeRectangles:
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ return ProcPanoramiXShapeRectangles (client);
+ else
+ return ProcShapeRectangles (client);
+#else
+ return ProcShapeRectangles (client);
+#endif
+ case X_ShapeMask:
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ return ProcPanoramiXShapeMask (client);
+ else
+ return ProcShapeMask (client);
+#else
+ return ProcShapeMask (client);
+#endif
+ case X_ShapeCombine:
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ return ProcPanoramiXShapeCombine (client);
+ else
+ return ProcShapeCombine (client);
+#else
+ return ProcShapeCombine (client);
+#endif
+ case X_ShapeOffset:
+#ifdef PANORAMIX
+ if ( !noPanoramiXExtension )
+ return ProcPanoramiXShapeOffset (client);
+ else
+ return ProcShapeOffset (client);
+#else
+ return ProcShapeOffset (client);
+#endif
+ case X_ShapeQueryExtents:
+ return ProcShapeQueryExtents (client);
+ case X_ShapeSelectInput:
+ return ProcShapeSelectInput (client);
+ case X_ShapeInputSelected:
+ return ProcShapeInputSelected (client);
+ case X_ShapeGetRectangles:
+ return ProcShapeGetRectangles (client);
+ default:
+ return BadRequest;
+ }
+}
+
+static void
+SShapeNotifyEvent(from, to)
+ xShapeNotifyEvent *from, *to;
+{
+ to->type = from->type;
+ to->kind = from->kind;
+ cpswapl (from->window, to->window);
+ cpswaps (from->sequenceNumber, to->sequenceNumber);
+ cpswaps (from->x, to->x);
+ cpswaps (from->y, to->y);
+ cpswaps (from->width, to->width);
+ cpswaps (from->height, to->height);
+ cpswapl (from->time, to->time);
+ to->shaped = from->shaped;
+}
+
+static int
+SProcShapeQueryVersion (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST (xShapeQueryVersionReq);
+
+ swaps (&stuff->length, n);
+ return ProcShapeQueryVersion (client);
+}
+
+static int
+SProcShapeRectangles (client)
+ register ClientPtr client;
+{
+ register char n;
+ REQUEST (xShapeRectanglesReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq);
+ swapl (&stuff->dest, n);
+ swaps (&stuff->xOff, n);
+ swaps (&stuff->yOff, n);
+ SwapRestS(stuff);
+ return ProcShapeRectangles (client);
+}
+
+static int
+SProcShapeMask (client)
+ register ClientPtr client;
+{
+ register char n;
+ REQUEST (xShapeMaskReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xShapeMaskReq);
+ swapl (&stuff->dest, n);
+ swaps (&stuff->xOff, n);
+ swaps (&stuff->yOff, n);
+ swapl (&stuff->src, n);
+ return ProcShapeMask (client);
+}
+
+static int
+SProcShapeCombine (client)
+ register ClientPtr client;
+{
+ register char n;
+ REQUEST (xShapeCombineReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xShapeCombineReq);
+ swapl (&stuff->dest, n);
+ swaps (&stuff->xOff, n);
+ swaps (&stuff->yOff, n);
+ swapl (&stuff->src, n);
+ return ProcShapeCombine (client);
+}
+
+static int
+SProcShapeOffset (client)
+ register ClientPtr client;
+{
+ register char n;
+ REQUEST (xShapeOffsetReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xShapeOffsetReq);
+ swapl (&stuff->dest, n);
+ swaps (&stuff->xOff, n);
+ swaps (&stuff->yOff, n);
+ return ProcShapeOffset (client);
+}
+
+static int
+SProcShapeQueryExtents (client)
+ register ClientPtr client;
+{
+ register char n;
+ REQUEST (xShapeQueryExtentsReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xShapeQueryExtentsReq);
+ swapl (&stuff->window, n);
+ return ProcShapeQueryExtents (client);
+}
+
+static int
+SProcShapeSelectInput (client)
+ register ClientPtr client;
+{
+ register char n;
+ REQUEST (xShapeSelectInputReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xShapeSelectInputReq);
+ swapl (&stuff->window, n);
+ return ProcShapeSelectInput (client);
+}
+
+static int
+SProcShapeInputSelected (client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST (xShapeInputSelectedReq);
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH (xShapeInputSelectedReq);
+ swapl (&stuff->window, n);
+ return ProcShapeInputSelected (client);
+}
+
+static int
+SProcShapeGetRectangles (client)
+ register ClientPtr client;
+{
+ REQUEST(xShapeGetRectanglesReq);
+ register char n;
+
+ swaps (&stuff->length, n);
+ REQUEST_SIZE_MATCH(xShapeGetRectanglesReq);
+ swapl (&stuff->window, n);
+ return ProcShapeGetRectangles (client);
+}
+
+static int
+SProcShapeDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data) {
+ case X_ShapeQueryVersion:
+ return SProcShapeQueryVersion (client);
+ case X_ShapeRectangles:
+ return SProcShapeRectangles (client);
+ case X_ShapeMask:
+ return SProcShapeMask (client);
+ case X_ShapeCombine:
+ return SProcShapeCombine (client);
+ case X_ShapeOffset:
+ return SProcShapeOffset (client);
+ case X_ShapeQueryExtents:
+ return SProcShapeQueryExtents (client);
+ case X_ShapeSelectInput:
+ return SProcShapeSelectInput (client);
+ case X_ShapeInputSelected:
+ return SProcShapeInputSelected (client);
+ case X_ShapeGetRectangles:
+ return SProcShapeGetRectangles (client);
+ default:
+ return BadRequest;
+ }
+}
diff --git a/Xext/shm.c b/Xext/shm.c
new file mode 100644
index 000000000..0a9f3af59
--- /dev/null
+++ b/Xext/shm.c
@@ -0,0 +1,1010 @@
+/************************************************************
+
+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.
+
+********************************************************/
+
+/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */
+
+/* $Xorg: shm.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "gcstruct.h"
+#include "extnsionst.h"
+#include "servermd.h"
+#define _XSHM_SERVER_
+#include "shmstr.h"
+#include "Xfuncproto.h"
+
+typedef struct _ShmDesc {
+ struct _ShmDesc *next;
+ int shmid;
+ int refcnt;
+ char *addr;
+ Bool writable;
+ unsigned long size;
+} ShmDescRec, *ShmDescPtr;
+
+static void miShmPutImage(), fbShmPutImage();
+static PixmapPtr fbShmCreatePixmap();
+static int ProcShmDispatch(), SProcShmDispatch();
+static int ShmDetachSegment();
+static void ShmResetProc(), SShmCompletionEvent();
+
+static unsigned char ShmReqCode;
+static int ShmCompletionCode;
+static int BadShmSegCode;
+static RESTYPE ShmSegType, ShmPixType;
+static ShmDescPtr Shmsegs;
+static Bool sharedPixmaps;
+static int pixmapFormat;
+static int shmPixFormat[MAXSCREENS];
+static ShmFuncsPtr shmFuncs[MAXSCREENS];
+static ShmFuncs miFuncs = {NULL, miShmPutImage};
+static ShmFuncs fbFuncs = {fbShmCreatePixmap, fbShmPutImage};
+
+#define VERIFY_SHMSEG(shmseg,shmdesc,client) \
+{ \
+ shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \
+ if (!shmdesc) \
+ { \
+ client->errorValue = shmseg; \
+ return BadShmSegCode; \
+ } \
+}
+
+#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \
+{ \
+ VERIFY_SHMSEG(shmseg, shmdesc, client); \
+ if ((offset & 3) || (offset > shmdesc->size)) \
+ { \
+ client->errorValue = offset; \
+ return BadValue; \
+ } \
+ if (needwrite && !shmdesc->writable) \
+ return BadAccess; \
+}
+
+#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \
+{ \
+ if ((offset + len) > shmdesc->size) \
+ { \
+ return BadAccess; \
+ } \
+}
+
+void
+ShmExtensionInit()
+{
+ ExtensionEntry *extEntry;
+ int i;
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ sharedPixmaps = xFalse;
+ pixmapFormat = 0;
+#else
+ sharedPixmaps = xTrue;
+ pixmapFormat = shmPixFormat[0];
+ for (i = 0; i < screenInfo.numScreens; i++)
+ {
+ if (!shmFuncs[i])
+ shmFuncs[i] = &miFuncs;
+ if (!shmFuncs[i]->CreatePixmap)
+ sharedPixmaps = xFalse;
+ if (shmPixFormat[i] && (shmPixFormat[i] != pixmapFormat))
+ {
+ sharedPixmaps = xFalse;
+ pixmapFormat = 0;
+ }
+ }
+ if (!pixmapFormat)
+ pixmapFormat = ZPixmap;
+#endif
+ ShmSegType = CreateNewResourceType(ShmDetachSegment);
+ ShmPixType = CreateNewResourceType(ShmDetachSegment);
+ if (ShmSegType && ShmPixType &&
+ (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors,
+ ProcShmDispatch, SProcShmDispatch,
+ ShmResetProc, StandardMinorOpcode)))
+ {
+ ShmReqCode = (unsigned char)extEntry->base;
+ ShmCompletionCode = extEntry->eventBase;
+ BadShmSegCode = extEntry->errorBase;
+ EventSwapVector[ShmCompletionCode] = SShmCompletionEvent;
+ }
+}
+
+/*ARGSUSED*/
+static void
+ShmResetProc (extEntry)
+ExtensionEntry *extEntry;
+{
+ int i;
+
+ for (i = 0; i < MAXSCREENS; i++)
+ {
+ shmFuncs[i] = (ShmFuncsPtr)NULL;
+ shmPixFormat[i] = 0;
+ }
+}
+
+void
+ShmRegisterFuncs(pScreen, funcs)
+ ScreenPtr pScreen;
+ ShmFuncsPtr funcs;
+{
+ shmFuncs[pScreen->myNum] = funcs;
+}
+
+void
+ShmSetPixmapFormat(pScreen, format)
+ ScreenPtr pScreen;
+ int format;
+{
+ shmPixFormat[pScreen->myNum] = format;
+}
+
+void
+ShmRegisterFbFuncs(pScreen)
+ ScreenPtr pScreen;
+{
+ shmFuncs[pScreen->myNum] = &fbFuncs;
+}
+
+static int
+ProcShmQueryVersion(client)
+ register ClientPtr client;
+{
+ REQUEST(xShmQueryVersionReq);
+ xShmQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xShmQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.sharedPixmaps = sharedPixmaps;
+ rep.pixmapFormat = pixmapFormat;
+ rep.majorVersion = SHM_MAJOR_VERSION;
+ rep.minorVersion = SHM_MINOR_VERSION;
+ rep.uid = geteuid();
+ rep.gid = getegid();
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ swaps(&rep.uid, n);
+ swaps(&rep.gid, n);
+ }
+ WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int
+ProcShmAttach(client)
+ register ClientPtr client;
+{
+ struct shmid_ds buf;
+ ShmDescPtr shmdesc;
+ REQUEST(xShmAttachReq);
+
+ REQUEST_SIZE_MATCH(xShmAttachReq);
+ LEGAL_NEW_RESOURCE(stuff->shmseg, client);
+ if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse))
+ {
+ client->errorValue = stuff->readOnly;
+ return(BadValue);
+ }
+ for (shmdesc = Shmsegs;
+ shmdesc && (shmdesc->shmid != stuff->shmid);
+ shmdesc = shmdesc->next)
+ ;
+ if (shmdesc)
+ {
+ if (!stuff->readOnly && !shmdesc->writable)
+ return BadAccess;
+ shmdesc->refcnt++;
+ }
+ else
+ {
+ shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec));
+ if (!shmdesc)
+ return BadAlloc;
+ shmdesc->addr = shmat(stuff->shmid, 0,
+ stuff->readOnly ? SHM_RDONLY : 0);
+ if ((shmdesc->addr == ((char *)-1)) ||
+ shmctl(stuff->shmid, IPC_STAT, &buf))
+ {
+ xfree(shmdesc);
+ return BadAccess;
+ }
+ shmdesc->shmid = stuff->shmid;
+ shmdesc->refcnt = 1;
+ shmdesc->writable = !stuff->readOnly;
+ shmdesc->size = buf.shm_segsz;
+ shmdesc->next = Shmsegs;
+ Shmsegs = shmdesc;
+ }
+ if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc))
+ return BadAlloc;
+ return(client->noClientException);
+}
+
+/*ARGSUSED*/
+static int
+ShmDetachSegment(value, shmseg)
+ pointer value; /* must conform to DeleteType */
+ XID shmseg;
+{
+ ShmDescPtr shmdesc = (ShmDescPtr)value;
+ ShmDescPtr *prev;
+
+ if (--shmdesc->refcnt)
+ return TRUE;
+ shmdt(shmdesc->addr);
+ for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next)
+ ;
+ *prev = shmdesc->next;
+ xfree(shmdesc);
+ return Success;
+}
+
+static int
+ProcShmDetach(client)
+ register ClientPtr client;
+{
+ ShmDescPtr shmdesc;
+ REQUEST(xShmDetachReq);
+
+ REQUEST_SIZE_MATCH(xShmDetachReq);
+ VERIFY_SHMSEG(stuff->shmseg, shmdesc, client);
+ FreeResource(stuff->shmseg, RT_NONE);
+ return(client->noClientException);
+}
+
+static void
+miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data)
+ DrawablePtr dst;
+ GCPtr pGC;
+ int depth, w, h, sx, sy, sw, sh, dx, dy;
+ unsigned int format;
+ char *data;
+{
+ PixmapPtr pmap;
+ GCPtr putGC;
+
+ putGC = GetScratchGC(depth, dst->pScreen);
+ if (!putGC)
+ return;
+ pmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth);
+ if (!pmap)
+ {
+ FreeScratchGC(putGC);
+ return;
+ }
+ ValidateGC((DrawablePtr)pmap, putGC);
+ (*putGC->ops->PutImage)((DrawablePtr)pmap, putGC, depth, -sx, -sy, w, h, 0,
+ (format == XYPixmap) ? XYPixmap : ZPixmap, data);
+ FreeScratchGC(putGC);
+ if (format == XYBitmap)
+ (void)(*pGC->ops->CopyPlane)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh,
+ dx, dy, 1L);
+ else
+ (void)(*pGC->ops->CopyArea)((DrawablePtr)pmap, dst, pGC, 0, 0, sw, sh,
+ dx, dy);
+ (*pmap->drawable.pScreen->DestroyPixmap)(pmap);
+}
+
+static void
+fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data)
+ DrawablePtr dst;
+ GCPtr pGC;
+ int depth, w, h, sx, sy, sw, sh, dx, dy;
+ unsigned int format;
+ char *data;
+{
+ if ((format == ZPixmap) || (depth == 1))
+ {
+ PixmapPtr pPixmap;
+
+ pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth,
+ /*XXX*/depth, PixmapBytePad(w, depth), (pointer)data);
+ if (!pPixmap)
+ return;
+ if (format == XYBitmap)
+ (void)(*pGC->ops->CopyPlane)((DrawablePtr)pPixmap, dst, pGC,
+ sx, sy, sw, sh, dx, dy, 1L);
+ else
+ (void)(*pGC->ops->CopyArea)((DrawablePtr)pPixmap, dst, pGC,
+ sx, sy, sw, sh, dx, dy);
+ FreeScratchPixmapHeader(pPixmap);
+ }
+ else
+ miShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy,
+ data);
+}
+
+static int
+ProcShmPutImage(client)
+ register ClientPtr client;
+{
+ register GCPtr pGC;
+ register DrawablePtr pDraw;
+ long length;
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ long lengthProto;
+ char *tmpImage;
+ int tmpAlloced = 0;
+#endif
+ ShmDescPtr shmdesc;
+ REQUEST(xShmPutImageReq);
+
+ REQUEST_SIZE_MATCH(xShmPutImageReq);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, pGC, client);
+ VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client);
+ if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse))
+ return BadValue;
+ if (stuff->format == XYBitmap)
+ {
+ if (stuff->depth != 1)
+ return BadMatch;
+ length = PixmapBytePad(stuff->totalWidth, 1);
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ lengthProto = PixmapBytePadProto(stuff->totalWidth, 1);
+#endif
+ }
+ else if (stuff->format == XYPixmap)
+ {
+ if (pDraw->depth != stuff->depth)
+ return BadMatch;
+ length = PixmapBytePad(stuff->totalWidth, 1);
+ length *= stuff->depth;
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ lengthProto = PixmapBytePadProto(stuff->totalWidth, 1);
+ lengthProto *= stuff->depth;
+#endif
+ }
+ else if (stuff->format == ZPixmap)
+ {
+ if (pDraw->depth != stuff->depth)
+ return BadMatch;
+ length = PixmapBytePad(stuff->totalWidth, stuff->depth);
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ lengthProto = PixmapBytePadProto(stuff->totalWidth, stuff->depth);
+#endif
+ }
+ else
+ {
+ client->errorValue = stuff->format;
+ return BadValue;
+ }
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ VERIFY_SHMSIZE(shmdesc, stuff->offset, lengthProto * stuff->totalHeight,
+ client);
+#else
+ VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
+ client);
+#endif
+ if (stuff->srcX > stuff->totalWidth)
+ {
+ client->errorValue = stuff->srcX;
+ return BadValue;
+ }
+ if (stuff->srcY > stuff->totalHeight)
+ {
+ client->errorValue = stuff->srcY;
+ return BadValue;
+ }
+ if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth)
+ {
+ client->errorValue = stuff->srcWidth;
+ return BadValue;
+ }
+ if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight)
+ {
+ client->errorValue = stuff->srcHeight;
+ return BadValue;
+ }
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ /* handle 64 bit case where protocol may pad to 32 and we want 64
+ * In this case, length is what the server wants and lengthProto is
+ * what the protocol thinks it is. If the the two are different,
+ * copy the protocol version (i.e. the memory shared between the
+ * server and the client) to a version with a scanline pad of 64.
+ */
+ if (length != lengthProto)
+ {
+ register int i;
+ char * stuffptr, /* pointer into protocol data */
+ * tmpptr; /* new location to copy to */
+
+ if(!(tmpImage = (char *) ALLOCATE_LOCAL(length*stuff->totalHeight)))
+ return (BadAlloc);
+ tmpAlloced = 1;
+
+ bzero(tmpImage,length*stuff->totalHeight);
+
+ if (stuff->format == XYPixmap)
+ {
+ int lineBytes = PixmapBytePad(stuff->totalWidth, 1);
+ int lineBytesProto = PixmapBytePadProto(stuff->totalWidth, 1);
+ int depth = stuff->depth;
+
+ stuffptr = shmdesc->addr + stuff->offset ;
+ tmpptr = tmpImage;
+ for (i = 0; i < stuff->totalHeight*stuff->depth;
+ stuffptr += lineBytesProto,tmpptr += lineBytes, i++)
+ bcopy(stuffptr,tmpptr,lineBytesProto);
+ }
+ else
+ {
+ for (i = 0,
+ stuffptr = shmdesc->addr + stuff->offset,
+ tmpptr=tmpImage;
+ i < stuff->totalHeight;
+ stuffptr += lengthProto,tmpptr += length, i++)
+ bcopy(stuffptr,tmpptr,lengthProto);
+ }
+ }
+ /* handle 64-bit case where stuff is not 64-bit aligned
+ */
+ else if ((unsigned long)(shmdesc->addr+stuff->offset) &
+ (sizeof(long)-1))
+ {
+ if(!(tmpImage = (char *) ALLOCATE_LOCAL(length*stuff->totalHeight)))
+ return (BadAlloc);
+ tmpAlloced = 1;
+ bcopy((char *)(shmdesc->addr+stuff->offset),
+ tmpImage,
+ length*stuff->totalHeight);
+ }
+ else
+ tmpImage = (char *)(shmdesc->addr+stuff->offset);
+#endif
+
+ if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) ||
+ ((stuff->format != ZPixmap) &&
+ (stuff->srcX < screenInfo.bitmapScanlinePad) &&
+ ((stuff->format == XYBitmap) ||
+ ((stuff->srcY == 0) &&
+ (stuff->srcHeight == stuff->totalHeight))))) &&
+ ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth))
+ (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth,
+ stuff->dstX, stuff->dstY,
+ stuff->totalWidth, stuff->srcHeight,
+ stuff->srcX, stuff->format,
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ tmpImage +
+#else
+ shmdesc->addr + stuff->offset +
+#endif
+ (stuff->srcY * length));
+ else
+ (*shmFuncs[pDraw->pScreen->myNum]->PutImage)(
+ pDraw, pGC, stuff->depth, stuff->format,
+ stuff->totalWidth, stuff->totalHeight,
+ stuff->srcX, stuff->srcY,
+ stuff->srcWidth, stuff->srcHeight,
+ stuff->dstX, stuff->dstY,
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ tmpImage);
+
+#else
+ shmdesc->addr + stuff->offset);
+#endif
+
+ if (stuff->sendEvent)
+ {
+ xShmCompletionEvent ev;
+
+ ev.type = ShmCompletionCode;
+ ev.drawable = stuff->drawable;
+ ev.sequenceNumber = client->sequence;
+ ev.minorEvent = X_ShmPutImage;
+ ev.majorEvent = ShmReqCode;
+ ev.shmseg = stuff->shmseg;
+ ev.offset = stuff->offset;
+ WriteEventsToClient(client, 1, (xEvent *) &ev);
+ }
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ if (tmpAlloced)
+ DEALLOCATE_LOCAL(tmpImage);
+#endif
+
+ return (client->noClientException);
+}
+
+
+
+static int
+ProcShmGetImage(client)
+ register ClientPtr client;
+{
+ register DrawablePtr pDraw;
+ long lenPer, length;
+ Mask plane;
+ xShmGetImageReply xgi;
+ ShmDescPtr shmdesc;
+ int n;
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ long widthBytesLine,widthBytesLineProto;
+ long lenPerProto,lengthProto;
+ char *tmpImage;
+ int tmpAlloced = 0;
+#endif
+
+ REQUEST(xShmGetImageReq);
+
+ REQUEST_SIZE_MATCH(xShmGetImageReq);
+ if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap))
+ {
+ client->errorValue = stuff->format;
+ return(BadValue);
+ }
+ VERIFY_DRAWABLE(pDraw, stuff->drawable, client);
+ VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
+ if (pDraw->type == DRAWABLE_WINDOW)
+ {
+ if( /* check for being viewable */
+ !((WindowPtr) pDraw)->realized ||
+ /* check for being on screen */
+ pDraw->x + stuff->x < 0 ||
+ pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width ||
+ pDraw->y + stuff->y < 0 ||
+ pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height ||
+ /* check for being inside of border */
+ stuff->x < - wBorderWidth((WindowPtr)pDraw) ||
+ stuff->x + (int)stuff->width >
+ wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
+ stuff->y < -wBorderWidth((WindowPtr)pDraw) ||
+ stuff->y + (int)stuff->height >
+ wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height
+ )
+ return(BadMatch);
+ xgi.visual = wVisual(((WindowPtr)pDraw));
+ }
+ else
+ {
+ if (stuff->x < 0 ||
+ stuff->x+(int)stuff->width > pDraw->width ||
+ stuff->y < 0 ||
+ stuff->y+(int)stuff->height > pDraw->height
+ )
+ return(BadMatch);
+ xgi.visual = None;
+ }
+ xgi.type = X_Reply;
+ xgi.length = 0;
+ xgi.sequenceNumber = client->sequence;
+ xgi.depth = pDraw->depth;
+ if(stuff->format == ZPixmap)
+ {
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ widthBytesLine = PixmapBytePad(stuff->width, pDraw->depth);
+ length = widthBytesLine * stuff->height;
+ widthBytesLineProto = PixmapBytePadProto(stuff->width, pDraw->depth);
+ lengthProto = widthBytesLineProto * stuff->height;
+#else
+ length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height;
+#endif
+ }
+ else
+ {
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ widthBytesLine = PixmapBytePad(stuff->width, 1);
+ lenPer = widthBytesLine * stuff->height;
+ plane = ((Mask)1) << (pDraw->depth - 1);
+ /* only planes asked for */
+ length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1)));
+
+ widthBytesLineProto = PixmapBytePadProto(stuff->width, 1);
+ lenPerProto = widthBytesLineProto * stuff->height;
+ lengthProto = lenPerProto * Ones(stuff->planeMask &
+ (plane | (plane - 1)));
+#else
+ lenPer = PixmapBytePad(stuff->width, 1) * stuff->height;
+ plane = ((Mask)1) << (pDraw->depth - 1);
+ /* only planes asked for */
+ length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1)));
+#endif
+ }
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ VERIFY_SHMSIZE(shmdesc, stuff->offset, lengthProto, client);
+ xgi.size = lengthProto;
+#else
+ VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client);
+ xgi.size = length;
+#endif
+
+ if (length == 0)
+ {
+ /* nothing to do */
+ }
+ else if (stuff->format == ZPixmap)
+ {
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ /* check for protocol/server padding differences.
+ */
+ if ((widthBytesLine != widthBytesLineProto) ||
+ ((unsigned long)shmdesc->addr + stuff->offset & (sizeof(long)-1)))
+ {
+ /* temp stuff for 64 bit alignment stuff */
+ register char * bufPtr, * protoPtr;
+ register int i;
+
+ if(!(tmpImage = (char *) ALLOCATE_LOCAL(length)))
+ return (BadAlloc);
+ tmpAlloced = 1;
+
+ (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y,
+ stuff->width, stuff->height,
+ stuff->format, stuff->planeMask,
+ tmpImage);
+
+ /* for 64-bit server, convert image to pad to 32 bits
+ */
+ bzero(shmdesc->addr + stuff->offset,lengthProto);
+
+ for (i=0,bufPtr=tmpImage,protoPtr=shmdesc->addr + stuff->offset;
+ i < stuff->height;
+ bufPtr += widthBytesLine,protoPtr += widthBytesLineProto,
+ i++)
+ bcopy(bufPtr,protoPtr,widthBytesLineProto);
+ }
+ else
+ {
+ (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y,
+ stuff->width, stuff->height,
+ stuff->format, stuff->planeMask,
+ shmdesc->addr + stuff->offset);
+ }
+#else
+ (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y,
+ stuff->width, stuff->height,
+ stuff->format, stuff->planeMask,
+ shmdesc->addr + stuff->offset);
+#endif
+ }
+ else
+ {
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ /* check for protocol/server padding differences.
+ */
+ if ((widthBytesLine != widthBytesLineProto) ||
+ ((unsigned long)shmdesc->addr + stuff->offset &
+ (sizeof(long)-1)))
+ {
+ if(!(tmpImage = (char *) ALLOCATE_LOCAL(length)))
+ return (BadAlloc);
+ tmpAlloced = 1;
+ }
+#endif
+
+ length = stuff->offset;
+ for (; plane; plane >>= 1)
+ {
+ if (stuff->planeMask & plane)
+ {
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ if ((widthBytesLine != widthBytesLineProto) ||
+ ((unsigned long)shmdesc->addr + stuff->offset &
+ (sizeof(long)-1)))
+ {
+ /* get image for each plane.
+ */
+ (*pDraw->pScreen->GetImage)(pDraw,
+ stuff->x, stuff->y,
+ stuff->width, stuff->height,
+ stuff->format, plane,
+ tmpImage);
+
+ /* for 64-bit server, convert image to pad to 32 bits */
+ bzero(shmdesc->addr+length, widthBytesLine);
+ bcopy(tmpImage, shmdesc->addr+length, widthBytesLineProto);
+ /* increment length */
+ length += lenPerProto;
+ }
+ else /* no diff between protocol and server */
+ {
+ (*pDraw->pScreen->GetImage)(pDraw,
+ stuff->x, stuff->y,
+ stuff->width, stuff->height,
+ stuff->format, plane,
+ shmdesc->addr + length);
+ length += lenPer;
+ }
+#else
+ (*pDraw->pScreen->GetImage)(pDraw,
+ stuff->x, stuff->y,
+ stuff->width, stuff->height,
+ stuff->format, plane,
+ shmdesc->addr + length);
+ length += lenPer;
+#endif
+ }
+ }
+ }
+
+ if (client->swapped) {
+ swaps(&xgi.sequenceNumber, n);
+ swapl(&xgi.length, n);
+ swapl(&xgi.visual, n);
+ swapl(&xgi.size, n);
+ }
+ WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi);
+
+#ifdef INTERNAL_VS_EXTERNAL_PADDING
+ if (tmpAlloced)
+ DEALLOCATE_LOCAL(tmpImage);
+#endif
+
+ return(client->noClientException);
+}
+
+static PixmapPtr
+fbShmCreatePixmap (pScreen, width, height, depth, addr)
+ ScreenPtr pScreen;
+ int width;
+ int height;
+ int depth;
+ char *addr;
+{
+ register PixmapPtr pPixmap;
+
+ pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth);
+ if (!pPixmap)
+ return NullPixmap;
+
+ if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth,
+ /*XXX*/depth, PixmapBytePad(width, depth), (pointer)addr))
+ return NullPixmap;
+ return pPixmap;
+}
+
+static int
+ProcShmCreatePixmap(client)
+ register ClientPtr client;
+{
+ PixmapPtr pMap;
+ register DrawablePtr pDraw;
+ DepthPtr pDepth;
+ register int i;
+ ShmDescPtr shmdesc;
+ REQUEST(xShmCreatePixmapReq);
+
+ REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
+ client->errorValue = stuff->pid;
+ if (!sharedPixmaps)
+ return BadImplementation;
+ LEGAL_NEW_RESOURCE(stuff->pid, client);
+ VERIFY_GEOMETRABLE(pDraw, stuff->drawable, client);
+ VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
+ if (!stuff->width || !stuff->height)
+ {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ if (stuff->depth != 1)
+ {
+ pDepth = pDraw->pScreen->allowedDepths;
+ for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
+ if (pDepth->depth == stuff->depth)
+ goto CreatePmap;
+ client->errorValue = stuff->depth;
+ return BadValue;
+ }
+CreatePmap:
+ VERIFY_SHMSIZE(shmdesc, stuff->offset,
+ PixmapBytePad(stuff->width, stuff->depth) * stuff->height,
+ client);
+ pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)(
+ pDraw->pScreen, stuff->width,
+ stuff->height, stuff->depth,
+ shmdesc->addr + stuff->offset);
+ if (pMap)
+ {
+ pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pMap->drawable.id = stuff->pid;
+ if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap))
+ {
+ shmdesc->refcnt++;
+ if (AddResource(stuff->pid, ShmPixType, (pointer)shmdesc))
+ return(client->noClientException);
+ FreeResource(stuff->pid, RT_NONE);
+ }
+ }
+ return (BadAlloc);
+}
+
+static int
+ProcShmDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_ShmQueryVersion:
+ return ProcShmQueryVersion(client);
+ case X_ShmAttach:
+ return ProcShmAttach(client);
+ case X_ShmDetach:
+ return ProcShmDetach(client);
+ case X_ShmPutImage:
+ return ProcShmPutImage(client);
+ case X_ShmGetImage:
+ return ProcShmGetImage(client);
+ case X_ShmCreatePixmap:
+ return ProcShmCreatePixmap(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static void
+SShmCompletionEvent(from, to)
+ xShmCompletionEvent *from, *to;
+{
+ to->type = from->type;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->drawable, to->drawable);
+ cpswaps(from->minorEvent, to->minorEvent);
+ to->majorEvent = from->majorEvent;
+ cpswapl(from->shmseg, to->shmseg);
+ cpswapl(from->offset, to->offset);
+}
+
+static int
+SProcShmQueryVersion(client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xShmQueryVersionReq);
+
+ swaps(&stuff->length, n);
+ return ProcShmQueryVersion(client);
+}
+
+static int
+SProcShmAttach(client)
+ ClientPtr client;
+{
+ register int n;
+ REQUEST(xShmAttachReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xShmAttachReq);
+ swapl(&stuff->shmseg, n);
+ swapl(&stuff->shmid, n);
+ return ProcShmAttach(client);
+}
+
+static int
+SProcShmDetach(client)
+ ClientPtr client;
+{
+ register int n;
+ REQUEST(xShmDetachReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xShmDetachReq);
+ swapl(&stuff->shmseg, n);
+ return ProcShmDetach(client);
+}
+
+static int
+SProcShmPutImage(client)
+ ClientPtr client;
+{
+ register int n;
+ REQUEST(xShmPutImageReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xShmPutImageReq);
+ swapl(&stuff->drawable, n);
+ swapl(&stuff->gc, n);
+ swaps(&stuff->totalWidth, n);
+ swaps(&stuff->totalHeight, n);
+ swaps(&stuff->srcX, n);
+ swaps(&stuff->srcY, n);
+ swaps(&stuff->srcWidth, n);
+ swaps(&stuff->srcHeight, n);
+ swaps(&stuff->dstX, n);
+ swaps(&stuff->dstY, n);
+ swapl(&stuff->shmseg, n);
+ swapl(&stuff->offset, n);
+ return ProcShmPutImage(client);
+}
+
+static int
+SProcShmGetImage(client)
+ ClientPtr client;
+{
+ register int n;
+ REQUEST(xShmGetImageReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xShmGetImageReq);
+ swapl(&stuff->drawable, n);
+ swaps(&stuff->x, n);
+ swaps(&stuff->y, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ swapl(&stuff->planeMask, n);
+ swapl(&stuff->shmseg, n);
+ swapl(&stuff->offset, n);
+ return ProcShmGetImage(client);
+}
+
+static int
+SProcShmCreatePixmap(client)
+ ClientPtr client;
+{
+ register int n;
+ REQUEST(xShmCreatePixmapReq);
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
+ swapl(&stuff->drawable, n);
+ swaps(&stuff->width, n);
+ swaps(&stuff->height, n);
+ swapl(&stuff->shmseg, n);
+ swapl(&stuff->offset, n);
+ return ProcShmCreatePixmap(client);
+}
+
+static int
+SProcShmDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_ShmQueryVersion:
+ return SProcShmQueryVersion(client);
+ case X_ShmAttach:
+ return SProcShmAttach(client);
+ case X_ShmDetach:
+ return SProcShmDetach(client);
+ case X_ShmPutImage:
+ return SProcShmPutImage(client);
+ case X_ShmGetImage:
+ return SProcShmGetImage(client);
+ case X_ShmCreatePixmap:
+ return SProcShmCreatePixmap(client);
+ default:
+ return BadRequest;
+ }
+}
diff --git a/Xext/sleepuntil.c b/Xext/sleepuntil.c
new file mode 100644
index 000000000..292924ed6
--- /dev/null
+++ b/Xext/sleepuntil.c
@@ -0,0 +1,211 @@
+/*
+ * $Xorg: sleepuntil.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $
+ *
+Copyright 1992, 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.
+ *
+ * Author: Keith Packard, MIT X Consortium
+ */
+
+/* dixsleep.c - implement millisecond timeouts for X clients */
+
+#include "X.h"
+#include "Xmd.h"
+#include "misc.h"
+#include "windowstr.h"
+#include "dixstruct.h"
+#include "pixmapstr.h"
+#include "scrnintstr.h"
+
+typedef struct _Sertafied {
+ struct _Sertafied *next;
+ TimeStamp revive;
+ ClientPtr pClient;
+ XID id;
+ void (*notifyFunc)();
+ pointer closure;
+} SertafiedRec, *SertafiedPtr;
+
+static SertafiedPtr pPending;
+static RESTYPE SertafiedResType;
+static Bool BlockHandlerRegistered;
+static int SertafiedGeneration;
+static void ClientAwaken();
+static int SertafiedDelete();
+static void SertafiedBlockHandler();
+static void SertafiedWakeupHandler();
+
+ClientSleepUntil (client, revive, notifyFunc, closure)
+ ClientPtr client;
+ TimeStamp *revive;
+ void (*notifyFunc)();
+ pointer closure;
+{
+ SertafiedPtr pRequest, pReq, pPrev;
+
+ if (SertafiedGeneration != serverGeneration)
+ {
+ SertafiedResType = CreateNewResourceType (SertafiedDelete);
+ if (!SertafiedResType)
+ return FALSE;
+ SertafiedGeneration = serverGeneration;
+ BlockHandlerRegistered = FALSE;
+ }
+ pRequest = (SertafiedPtr) xalloc (sizeof (SertafiedRec));
+ if (!pRequest)
+ return FALSE;
+ pRequest->pClient = client;
+ pRequest->revive = *revive;
+ pRequest->id = FakeClientID (client->index);
+ pRequest->closure = closure;
+ if (!BlockHandlerRegistered)
+ {
+ if (!RegisterBlockAndWakeupHandlers (SertafiedBlockHandler,
+ SertafiedWakeupHandler,
+ (pointer) 0))
+ {
+ xfree (pRequest);
+ return FALSE;
+ }
+ BlockHandlerRegistered = TRUE;
+ }
+ pRequest->notifyFunc = 0;
+ if (!AddResource (pRequest->id, SertafiedResType, (pointer) pRequest))
+ return FALSE;
+ if (!notifyFunc)
+ notifyFunc = ClientAwaken;
+ pRequest->notifyFunc = notifyFunc;
+ /* Insert into time-ordered queue, with earliest activation time coming first. */
+ pPrev = 0;
+ for (pReq = pPending; pReq; pReq = pReq->next)
+ {
+ if (CompareTimeStamps (pReq->revive, *revive) == LATER)
+ break;
+ pPrev = pReq;
+ }
+ if (pPrev)
+ pPrev->next = pRequest;
+ else
+ pPending = pRequest;
+ pRequest->next = pReq;
+ IgnoreClient (client);
+ return TRUE;
+}
+
+static void
+ClientAwaken (client, closure)
+ ClientPtr client;
+ pointer closure;
+{
+ if (!client->clientGone)
+ AttendClient (client);
+}
+
+
+static int
+SertafiedDelete (value, id)
+ pointer value;
+ XID id;
+{
+ SertafiedPtr pRequest = (SertafiedPtr)value;
+ SertafiedPtr pReq, pPrev;
+
+ pPrev = 0;
+ for (pReq = pPending; pReq; pPrev = pReq, pReq = pReq->next)
+ if (pReq == pRequest)
+ {
+ if (pPrev)
+ pPrev->next = pReq->next;
+ else
+ pPending = pReq->next;
+ break;
+ }
+ if (pRequest->notifyFunc)
+ (*pRequest->notifyFunc) (pRequest->pClient, pRequest->closure);
+ xfree (pRequest);
+ return TRUE;
+}
+
+static void
+SertafiedBlockHandler (data, wt, LastSelectMask)
+ pointer data; /* unused */
+ OSTimePtr wt; /* wait time */
+ pointer LastSelectMask;
+{
+ SertafiedPtr pReq, pNext;
+ unsigned long newdelay, olddelay;
+ TimeStamp now;
+
+ if (!pPending)
+ return;
+ now.milliseconds = GetTimeInMillis ();
+ now.months = currentTime.months;
+ if ((int) (now.milliseconds - currentTime.milliseconds) < 0)
+ now.months++;
+ for (pReq = pPending; pReq; pReq = pNext)
+ {
+ pNext = pReq->next;
+ if (CompareTimeStamps (pReq->revive, now) == LATER)
+ break;
+ FreeResource (pReq->id, RT_NONE);
+
+ /* AttendClient() may have been called via the resource delete
+ * function so a client may have input to be processed and so
+ * set delay to 0 to prevent blocking in WaitForSomething().
+ */
+ AdjustWaitForDelay (wt, 0);
+ }
+ pReq = pPending;
+ if (!pReq)
+ return;
+ newdelay = pReq->revive.milliseconds - now.milliseconds;
+ AdjustWaitForDelay (wt, newdelay);
+}
+
+static void
+SertafiedWakeupHandler (data, i, LastSelectMask)
+ pointer data;
+ int i;
+ pointer LastSelectMask;
+{
+ SertafiedPtr pReq, pNext;
+ TimeStamp now;
+
+ now.milliseconds = GetTimeInMillis ();
+ now.months = currentTime.months;
+ if ((int) (now.milliseconds - currentTime.milliseconds) < 0)
+ now.months++;
+ for (pReq = pPending; pReq; pReq = pNext)
+ {
+ pNext = pReq->next;
+ if (CompareTimeStamps (pReq->revive, now) == LATER)
+ break;
+ FreeResource (pReq->id, RT_NONE);
+ }
+ if (!pPending)
+ {
+ RemoveBlockAndWakeupHandlers (SertafiedBlockHandler,
+ SertafiedWakeupHandler,
+ (pointer) 0);
+ BlockHandlerRegistered = FALSE;
+ }
+}
diff --git a/Xext/sync.c b/Xext/sync.c
new file mode 100644
index 000000000..8274d2522
--- /dev/null
+++ b/Xext/sync.c
@@ -0,0 +1,2322 @@
+/* $Xorg: sync.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */
+/*
+
+Copyright 1991, 1993, 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 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts,
+and Olivetti Research Limited, Cambridge, England.
+
+ 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 names of Digital or Olivetti
+not be used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission. Digital and Olivetti
+make no representations about the suitability of this software
+for any purpose. It is provided "as is" without express or implied warranty.
+
+DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
+SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL THEY 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.
+
+*/
+
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <stdio.h>
+#include "X.h"
+#include "Xproto.h"
+#include "Xmd.h"
+#include "misc.h"
+#include "os.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "opaque.h"
+#define _SYNC_SERVER
+#include "sync.h"
+#include "syncstr.h"
+
+/*
+ * Local Global Variables
+ */
+static int SyncReqCode;
+static int SyncEventBase;
+static int SyncErrorBase;
+static RESTYPE RTCounter = 0;
+static RESTYPE RTAwait;
+static RESTYPE RTAlarm;
+static RESTYPE RTAlarmClient;
+static int SyncNumSystemCounters = 0;
+static SyncCounter **SysCounterList = NULL;
+
+#define IsSystemCounter(pCounter) \
+ (pCounter && (pCounter->client == NULL))
+
+/* these are all the alarm attributes that pertain to the alarm's trigger */
+#define XSyncCAAllTrigger \
+ (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType)
+
+static void SyncComputeBracketValues(
+#if NeedFunctionPrototypes
+ SyncCounter * /* pCounter */,
+ Bool /* startOver */
+#endif
+);
+
+/* Each counter maintains a simple linked list of triggers that are
+ * interested in the counter. The two functions below are used to
+ * delete and add triggers on this list.
+ */
+static void
+SyncDeleteTriggerFromCounter(pTrigger)
+ SyncTrigger *pTrigger;
+{
+ SyncTriggerList *pCur, *pPrev = NULL;
+
+ /* pCounter needs to be stored in pTrigger before calling here. */
+
+ if (!pTrigger->pCounter)
+ return;
+
+ for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
+ {
+ if (pCur->pTrigger == pTrigger)
+ {
+ if (pPrev)
+ pPrev->next = pCur->next;
+ else
+ pTrigger->pCounter->pTriglist = pCur->next;
+ xfree(pCur);
+ break;
+ }
+ }
+
+ if (IsSystemCounter(pTrigger->pCounter))
+ SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
+}
+
+
+static int
+SyncAddTriggerToCounter(pTrigger)
+ SyncTrigger *pTrigger;
+{
+ SyncTriggerList *pCur;
+
+ if (!pTrigger->pCounter)
+ return Success;
+
+ /* don't do anything if it's already there */
+ for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next)
+ {
+ if (pCur->pTrigger == pTrigger)
+ return Success;
+ }
+
+ if (!(pCur = (SyncTriggerList *)xalloc(sizeof(SyncTriggerList))))
+ return BadAlloc;
+
+ pCur->pTrigger = pTrigger;
+ pCur->next = pTrigger->pCounter->pTriglist;
+ pTrigger->pCounter->pTriglist = pCur;
+
+ if (IsSystemCounter(pTrigger->pCounter))
+ SyncComputeBracketValues(pTrigger->pCounter, /*startOver*/ TRUE);
+
+ return Success;
+}
+
+
+/* Below are four possible functions that can be plugged into
+ * pTrigger->CheckTrigger, corresponding to the four possible
+ * test-types. These functions are called after the counter's
+ * value changes but are also passed the old counter value
+ * so they can inspect both the old and new values.
+ * (PositiveTransition and NegativeTransition need to see both
+ * pieces of information.) These functions return the truth value
+ * of the trigger.
+ *
+ * All of them include the condition pTrigger->pCounter == NULL.
+ * This is because the spec says that a trigger with a counter value
+ * of None is always TRUE.
+ */
+
+static Bool
+SyncCheckTriggerPositiveComparison(pTrigger, oldval)
+ SyncTrigger *pTrigger;
+ CARD64 oldval;
+{
+ return (pTrigger->pCounter == NULL ||
+ XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
+ pTrigger->test_value));
+}
+
+static Bool
+SyncCheckTriggerNegativeComparison(pTrigger, oldval)
+ SyncTrigger *pTrigger;
+ CARD64 oldval;
+{
+ return (pTrigger->pCounter == NULL ||
+ XSyncValueLessOrEqual(pTrigger->pCounter->value,
+ pTrigger->test_value));
+}
+
+static Bool
+SyncCheckTriggerPositiveTransition(pTrigger, oldval)
+ SyncTrigger *pTrigger;
+ CARD64 oldval;
+{
+ return (pTrigger->pCounter == NULL ||
+ (XSyncValueLessThan(oldval, pTrigger->test_value) &&
+ XSyncValueGreaterOrEqual(pTrigger->pCounter->value,
+ pTrigger->test_value)));
+}
+
+static Bool
+SyncCheckTriggerNegativeTransition(pTrigger, oldval)
+ SyncTrigger *pTrigger;
+ CARD64 oldval;
+{
+ return (pTrigger->pCounter == NULL ||
+ (XSyncValueGreaterThan(oldval, pTrigger->test_value) &&
+ XSyncValueLessOrEqual(pTrigger->pCounter->value,
+ pTrigger->test_value)));
+}
+
+
+
+static int
+SyncInitTrigger(client, pTrigger, counter, changes)
+ ClientPtr client; /* so we can set errorValue */
+ SyncTrigger *pTrigger;
+ XSyncCounter counter;
+ Mask changes;
+{
+ SyncCounter *pCounter = pTrigger->pCounter;
+ int status;
+ Bool newcounter = FALSE;
+
+ if (changes & XSyncCACounter)
+ {
+ if (counter == None)
+ pCounter = NULL;
+ else if (!(pCounter = (SyncCounter *)SecurityLookupIDByType(
+ client, counter, RTCounter, SecurityReadAccess)))
+ {
+ client->errorValue = counter;
+ return SyncErrorBase + XSyncBadCounter;
+ }
+ if (pCounter != pTrigger->pCounter)
+ { /* new counter for trigger */
+ SyncDeleteTriggerFromCounter(pTrigger);
+ pTrigger->pCounter = pCounter;
+ newcounter = TRUE;
+ }
+ }
+
+ /* if system counter, ask it what the current value is */
+
+ if (IsSystemCounter(pCounter))
+ {
+ (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
+ &pCounter->value);
+ }
+
+ if (changes & XSyncCAValueType)
+ {
+ if (pTrigger->value_type != XSyncRelative &&
+ pTrigger->value_type != XSyncAbsolute)
+ {
+ client->errorValue = pTrigger->value_type;
+ return BadValue;
+ }
+ }
+
+ if (changes & XSyncCATestType)
+ {
+ if (pTrigger->test_type != XSyncPositiveTransition &&
+ pTrigger->test_type != XSyncNegativeTransition &&
+ pTrigger->test_type != XSyncPositiveComparison &&
+ pTrigger->test_type != XSyncNegativeComparison)
+ {
+ client->errorValue = pTrigger->test_type;
+ return BadValue;
+ }
+ /* select appropriate CheckTrigger function */
+
+ switch (pTrigger->test_type)
+ {
+ case XSyncPositiveTransition:
+ pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition;
+ break;
+ case XSyncNegativeTransition:
+ pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition;
+ break;
+ case XSyncPositiveComparison:
+ pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison;
+ break;
+ case XSyncNegativeComparison:
+ pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison;
+ break;
+ }
+ }
+
+ if (changes & (XSyncCAValueType | XSyncCAValue))
+ {
+ if (pTrigger->value_type == XSyncAbsolute)
+ pTrigger->test_value = pTrigger->wait_value;
+ else /* relative */
+ {
+ Bool overflow;
+ if (pCounter == NULL)
+ return BadMatch;
+
+ XSyncValueAdd(&pTrigger->test_value, pCounter->value,
+ pTrigger->wait_value, &overflow);
+ if (overflow)
+ {
+ client->errorValue = XSyncValueHigh32(pTrigger->wait_value);
+ return BadValue;
+ }
+ }
+ }
+
+ /* we wait until we're sure there are no errors before registering
+ * a new counter on a trigger
+ */
+ if (newcounter)
+ {
+ if ((status = SyncAddTriggerToCounter(pTrigger)) != Success)
+ return status;
+ }
+ else if (IsSystemCounter(pCounter))
+ {
+ SyncComputeBracketValues(pCounter, /*startOver*/ TRUE);
+ }
+
+ return Success;
+}
+
+/* AlarmNotify events happen in response to actions taken on an Alarm or
+ * the counter used by the alarm. AlarmNotify may be sent to multiple
+ * clients. The alarm maintains a list of clients interested in events.
+ */
+static void
+SyncSendAlarmNotifyEvents(pAlarm)
+ SyncAlarm *pAlarm;
+{
+ SyncAlarmClientList *pcl;
+ xSyncAlarmNotifyEvent ane;
+ SyncTrigger *pTrigger = &pAlarm->trigger;
+
+ UpdateCurrentTime();
+
+ ane.type = SyncEventBase + XSyncAlarmNotify;
+ ane.kind = XSyncAlarmNotify;
+ ane.sequenceNumber = pAlarm->client->sequence;
+ ane.alarm = pAlarm->alarm_id;
+ if (pTrigger->pCounter)
+ {
+ ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
+ ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
+ }
+ else
+ { /* XXX what else can we do if there's no counter? */
+ ane.counter_value_hi = ane.counter_value_lo = 0;
+ }
+
+ ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value);
+ ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value);
+ ane.time = currentTime.milliseconds;
+ ane.state = pAlarm->state;
+
+ /* send to owner */
+ if (pAlarm->events && !pAlarm->client->clientGone)
+ WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane);
+
+ /* send to other interested clients */
+ for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next)
+ {
+ if (!pAlarm->client->clientGone)
+ {
+ ane.sequenceNumber = pcl->client->sequence;
+ WriteEventsToClient(pcl->client, 1, (xEvent *) &ane);
+ }
+ }
+}
+
+
+/* CounterNotify events only occur in response to an Await. The events
+ * go only to the Awaiting client.
+ */
+static void
+SyncSendCounterNotifyEvents(client, ppAwait, num_events)
+ ClientPtr client;
+ SyncAwait **ppAwait;
+ int num_events;
+{
+ xSyncCounterNotifyEvent *pEvents, *pev;
+ int i;
+
+ if (client->clientGone)
+ return;
+ pev = pEvents = (xSyncCounterNotifyEvent *)
+ ALLOCATE_LOCAL(num_events * sizeof(xSyncCounterNotifyEvent));
+ if (!pEvents)
+ return;
+ UpdateCurrentTime();
+ for (i = 0; i < num_events; i++, ppAwait++, pev++)
+ {
+ SyncTrigger *pTrigger = &(*ppAwait)->trigger;
+ pev->type = SyncEventBase + XSyncCounterNotify;
+ pev->kind = XSyncCounterNotify;
+ pev->sequenceNumber = client->sequence;
+ pev->counter = pTrigger->pCounter->id;
+ pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value);
+ pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
+ pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value);
+ pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value);
+ pev->time = currentTime.milliseconds;
+ pev->count = num_events - i - 1; /* events remaining */
+ pev->destroyed = pTrigger->pCounter->beingDestroyed;
+ }
+ /* swapping will be taken care of by this */
+ WriteEventsToClient(client, num_events, (xEvent *)pEvents);
+ DEALLOCATE_LOCAL(pEvents);
+}
+
+
+/* This function is called when an alarm's counter is destroyed.
+ * It is plugged into pTrigger->CounterDestroyed (for alarm triggers).
+ */
+void
+SyncAlarmCounterDestroyed(pTrigger)
+ SyncTrigger *pTrigger;
+{
+ SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
+
+ pAlarm->state = XSyncAlarmInactive;
+ SyncSendAlarmNotifyEvents(pAlarm);
+ pTrigger->pCounter = NULL;
+}
+
+
+/* This function is called when an alarm "goes off."
+ * It is plugged into pTrigger->TriggerFired (for alarm triggers).
+ */
+static void
+SyncAlarmTriggerFired(pTrigger)
+ SyncTrigger *pTrigger;
+{
+ SyncAlarm *pAlarm = (SyncAlarm *)pTrigger;
+ CARD64 new_test_value;
+
+ /* no need to check alarm unless it's active */
+ if (pAlarm->state != XSyncAlarmActive)
+ return;
+
+ /* " if the counter value is None, or if the delta is 0 and
+ * the test-type is PositiveComparison or NegativeComparison,
+ * no change is made to value (test-value) and the alarm
+ * state is changed to Inactive before the event is generated."
+ */
+ if (pAlarm->trigger.pCounter == NULL
+ || (XSyncValueIsZero(pAlarm->delta)
+ && (pAlarm->trigger.test_type == XSyncPositiveComparison
+ || pAlarm->trigger.test_type == XSyncNegativeComparison)))
+ pAlarm->state = XSyncAlarmInactive;
+
+ new_test_value = pAlarm->trigger.test_value;
+
+ if (pAlarm->state == XSyncAlarmActive)
+ {
+ Bool overflow;
+ CARD64 oldvalue;
+ SyncTrigger *pTrigger = &pAlarm->trigger;
+
+ /* "The alarm is updated by repeatedly adding delta to the
+ * value of the trigger and re-initializing it until it
+ * becomes FALSE."
+ */
+ oldvalue = pTrigger->test_value;
+
+ /* XXX really should do something smarter here */
+
+ do
+ {
+ XSyncValueAdd(&pTrigger->test_value, pTrigger->test_value,
+ pAlarm->delta, &overflow);
+ } while (!overflow &&
+ (*pTrigger->CheckTrigger)(pTrigger,
+ pTrigger->pCounter->value));
+
+ new_test_value = pTrigger->test_value;
+ pTrigger->test_value = oldvalue;
+
+ /* "If this update would cause value to fall outside the range
+ * for an INT64...no change is made to value (test-value) and
+ * the alarm state is changed to Inactive before the event is
+ * generated."
+ */
+ if (overflow)
+ {
+ new_test_value = oldvalue;
+ pAlarm->state = XSyncAlarmInactive;
+ }
+ }
+ /* The AlarmNotify event has to have the "new state of the alarm"
+ * which we can't be sure of until this point. However, it has
+ * to have the "old" trigger test value. That's the reason for
+ * all the newvalue/oldvalue shuffling above. After we send the
+ * events, give the trigger its new test value.
+ */
+ SyncSendAlarmNotifyEvents(pAlarm);
+ pTrigger->test_value = new_test_value;
+}
+
+
+/* This function is called when an Await unblocks, either as a result
+ * of the trigger firing OR the counter being destroyed.
+ * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed
+ * (for Await triggers).
+ */
+static void
+SyncAwaitTriggerFired(pTrigger)
+ SyncTrigger *pTrigger;
+{
+ SyncAwait *pAwait = (SyncAwait *)pTrigger;
+ int numwaits;
+ SyncAwaitUnion *pAwaitUnion;
+ SyncAwait **ppAwait;
+ int num_events = 0;
+
+ pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader;
+ numwaits = pAwaitUnion->header.num_waitconditions;
+ ppAwait = (SyncAwait **)ALLOCATE_LOCAL(numwaits * sizeof(SyncAwait *));
+ if (!ppAwait)
+ goto bail;
+
+ pAwait = &(pAwaitUnion+1)->await;
+
+ /* "When a client is unblocked, all the CounterNotify events for
+ * the Await request are generated contiguously. If count is 0
+ * there are no more events to follow for this request. If
+ * count is n, there are at least n more events to follow."
+ *
+ * Thus, it is best to find all the counters for which events
+ * need to be sent first, so that an accurate count field can
+ * be stored in the events.
+ */
+ for ( ; numwaits; numwaits--, pAwait++)
+ {
+ CARD64 diff;
+ Bool overflow, diffgreater, diffequal;
+
+ /* "A CounterNotify event with the destroyed flag set to TRUE is
+ * always generated if the counter for one of the triggers is
+ * destroyed."
+ */
+ if (pAwait->trigger.pCounter->beingDestroyed)
+ {
+ ppAwait[num_events++] = pAwait;
+ continue;
+ }
+
+ /* "The difference between the counter and the test value is
+ * calculated by subtracting the test value from the value of
+ * the counter."
+ */
+ XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value,
+ pAwait->trigger.test_value, &overflow);
+
+ /* "If the difference lies outside the range for an INT64, an
+ * event is not generated."
+ */
+ if (overflow)
+ continue;
+ diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold);
+ diffequal = XSyncValueEqual(diff, pAwait->event_threshold);
+
+ /* "If the test-type is PositiveTransition or
+ * PositiveComparison, a CounterNotify event is generated if
+ * the difference is at least event-threshold. If the test-type
+ * is NegativeTransition or NegativeComparison, a CounterNotify
+ * event is generated if the difference is at most
+ * event-threshold."
+ */
+
+ if ( ((pAwait->trigger.test_type == XSyncPositiveComparison ||
+ pAwait->trigger.test_type == XSyncPositiveTransition)
+ && (diffgreater || diffequal))
+ ||
+ ((pAwait->trigger.test_type == XSyncNegativeComparison ||
+ pAwait->trigger.test_type == XSyncNegativeTransition)
+ && (!diffgreater) /* less or equal */
+ )
+ )
+ {
+ ppAwait[num_events++] = pAwait;
+ }
+ }
+ if (num_events)
+ SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait,
+ num_events);
+ DEALLOCATE_LOCAL(ppAwait);
+
+bail:
+ /* unblock the client */
+ AttendClient(pAwaitUnion->header.client);
+ /* delete the await */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+}
+
+
+/* This function should always be used to change a counter's value so that
+ * any triggers depending on the counter will be checked.
+ */
+void
+SyncChangeCounter(pCounter, newval)
+ SyncCounter *pCounter;
+ CARD64 newval;
+{
+ SyncTriggerList *ptl, *pnext;
+ CARD64 oldval;
+
+ oldval = pCounter->value;
+ pCounter->value = newval;
+
+ /* run through triggers to see if any become true */
+ for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
+ {
+ pnext = ptl->next;
+ if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval))
+ (*ptl->pTrigger->TriggerFired)(ptl->pTrigger);
+ }
+
+ if (IsSystemCounter(pCounter))
+ {
+ SyncComputeBracketValues(pCounter, /* startOver */ FALSE);
+ }
+}
+
+
+/* loosely based on dix/events.c/EventSelectForWindow */
+static Bool
+SyncEventSelectForAlarm(pAlarm, client, wantevents)
+ SyncAlarm *pAlarm;
+ ClientPtr client;
+ Bool wantevents;
+{
+ SyncAlarmClientList *pClients;
+
+ if (client == pAlarm->client) /* alarm owner */
+ {
+ pAlarm->events = wantevents;
+ return Success;
+ }
+
+ /* see if the client is already on the list (has events selected) */
+
+ for (pClients = pAlarm->pEventClients; pClients;
+ pClients = pClients->next)
+ {
+ if (pClients->client == client)
+ {
+ /* client's presence on the list indicates desire for
+ * events. If the client doesn't want events, remove it
+ * from the list. If the client does want events, do
+ * nothing, since it's already got them.
+ */
+ if (!wantevents)
+ {
+ FreeResource(pClients->delete_id, RT_NONE);
+ }
+ return Success;
+ }
+ }
+
+ /* if we get here, this client does not currently have
+ * events selected on the alarm
+ */
+
+ if (!wantevents)
+ /* client doesn't want events, and we just discovered that it
+ * doesn't have them, so there's nothing to do.
+ */
+ return Success;
+
+ /* add new client to pAlarm->pEventClients */
+
+ pClients = (SyncAlarmClientList *) xalloc(sizeof(SyncAlarmClientList));
+ if (!pClients)
+ return BadAlloc;
+
+ /* register it as a resource so it will be cleaned up
+ * if the client dies
+ */
+
+ pClients->delete_id = FakeClientID(client->index);
+ if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm))
+ {
+ xfree(pClients);
+ return BadAlloc;
+ }
+
+ /* link it into list after we know all the allocations succeed */
+
+ pClients->next = pAlarm->pEventClients;
+ pAlarm->pEventClients = pClients;
+ pClients->client = client;
+ return Success;
+}
+
+/*
+ * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm
+ */
+static int
+SyncChangeAlarmAttributes(client, pAlarm, mask, values)
+ ClientPtr client;
+ SyncAlarm *pAlarm;
+ Mask mask;
+ CARD32 *values;
+{
+ SyncAlarmClientList *pClients;
+ int status;
+ XSyncCounter counter;
+ Mask origmask = mask;
+
+ counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None;
+
+ while (mask)
+ {
+ int index = lowbit(mask);
+ mask &= ~index;
+ switch (index)
+ {
+ case XSyncCACounter:
+ mask &= ~XSyncCACounter;
+ /* sanity check in SyncInitTrigger */
+ counter = *values++;
+ break;
+
+ case XSyncCAValueType:
+ mask &= ~XSyncCAValueType;
+ /* sanity check in SyncInitTrigger */
+ pAlarm->trigger.value_type = *values++;
+ break;
+
+ case XSyncCAValue:
+ mask &= ~XSyncCAValue;
+ XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]);
+ values += 2;
+ break;
+
+ case XSyncCATestType:
+ mask &= ~XSyncCATestType;
+ /* sanity check in SyncInitTrigger */
+ pAlarm->trigger.test_type = *values++;
+ break;
+
+ case XSyncCADelta:
+ mask &= ~XSyncCADelta;
+ XSyncIntsToValue(&pAlarm->delta, values[1], values[0]);
+ values += 2;
+ break;
+
+ case XSyncCAEvents:
+ mask &= ~XSyncCAEvents;
+ if ((*values != xTrue) && (*values != xFalse))
+ {
+ client->errorValue = *values;
+ return BadValue;
+ }
+ status = SyncEventSelectForAlarm(pAlarm, client,
+ (Bool)(*values++));
+ if (status != Success)
+ return status;
+ break;
+
+ default:
+ client->errorValue = mask;
+ return BadValue;
+ }
+ }
+
+ /* "If the test-type is PositiveComparison or PositiveTransition
+ * and delta is less than zero, or if the test-type is
+ * NegativeComparison or NegativeTransition and delta is
+ * greater than zero, a Match error is generated."
+ */
+ if (origmask & (XSyncCADelta|XSyncCATestType))
+ {
+ CARD64 zero;
+ XSyncIntToValue(&zero, 0);
+ if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) ||
+ (pAlarm->trigger.test_type == XSyncPositiveTransition))
+ && XSyncValueLessThan(pAlarm->delta, zero))
+ ||
+ (((pAlarm->trigger.test_type == XSyncNegativeComparison) ||
+ (pAlarm->trigger.test_type == XSyncNegativeTransition))
+ && XSyncValueGreaterThan(pAlarm->delta, zero))
+ )
+ {
+ return BadMatch;
+ }
+ }
+
+ /* postpone this until now, when we're sure nothing else can go wrong */
+ if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter,
+ origmask & XSyncCAAllTrigger)) != Success)
+ return status;
+
+ /* XXX spec does not really say to do this - needs clarification */
+ pAlarm->state = XSyncAlarmActive;
+ return Success;
+}
+
+
+static SyncCounter *
+SyncCreateCounter(client, id, initialvalue)
+ ClientPtr client;
+ XSyncCounter id;
+ CARD64 initialvalue;
+{
+ SyncCounter *pCounter;
+
+ if (!(pCounter = (SyncCounter *) xalloc(sizeof(SyncCounter))))
+ return (SyncCounter *)NULL;
+
+ if (!AddResource(id, RTCounter, (pointer) pCounter))
+ {
+ xfree((pointer) pCounter);
+ return (SyncCounter *)NULL;
+ }
+
+ pCounter->client = client;
+ pCounter->id = id;
+ pCounter->value = initialvalue;
+ pCounter->pTriglist = NULL;
+ pCounter->beingDestroyed = FALSE;
+ pCounter->pSysCounterInfo = NULL;
+ return pCounter;
+}
+
+static int FreeCounter(
+#if NeedFunctionPrototypes
+ pointer /*env*/,
+ XID /*id*/
+#endif
+);
+
+/*
+ * ***** System Counter utilities
+ */
+
+pointer
+SyncCreateSystemCounter(name, initial, resolution, counterType,
+ QueryValue, BracketValues)
+ char *name;
+ CARD64 initial;
+ CARD64 resolution;
+ SyncCounterType counterType;
+ void (*QueryValue) ();
+ void (*BracketValues) ();
+{
+ SyncCounter *pCounter;
+
+ SysCounterList = (SyncCounter **)xrealloc(SysCounterList,
+ (SyncNumSystemCounters+1)*sizeof(SyncCounter *));
+ if (!SysCounterList)
+ return (pointer)NULL;
+
+ /* this function may be called before SYNC has been initialized, so we
+ * have to make sure RTCounter is created.
+ */
+ if (RTCounter == 0)
+ {
+ RTCounter = CreateNewResourceType(FreeCounter);
+ if (RTCounter == 0)
+ {
+ return (pointer)NULL;
+ }
+ }
+
+ pCounter = SyncCreateCounter((ClientPtr)NULL, FakeClientID(0), initial);
+
+ if (pCounter)
+ {
+ SysCounterInfo *psci;
+
+ psci = (SysCounterInfo *)xalloc(sizeof(SysCounterInfo));
+ if (!psci)
+ {
+ FreeResource(pCounter->id, RT_NONE);
+ return (pointer) pCounter;
+ }
+ pCounter->pSysCounterInfo = psci;
+ psci->name = name;
+ psci->resolution = resolution;
+ psci->counterType = counterType;
+ psci->QueryValue = QueryValue;
+ psci->BracketValues = BracketValues;
+ XSyncMaxValue(&psci->bracket_greater);
+ XSyncMinValue(&psci->bracket_less);
+ SysCounterList[SyncNumSystemCounters++] = pCounter;
+ }
+ return (pointer) pCounter;
+}
+
+void
+SyncDestroySystemCounter(pSysCounter)
+ pointer pSysCounter;
+{
+ SyncCounter *pCounter = (SyncCounter *)pSysCounter;
+ FreeResource(pCounter->id, RT_NONE);
+}
+
+static void
+SyncComputeBracketValues(pCounter, startOver)
+ SyncCounter *pCounter;
+ Bool startOver;
+{
+ SyncTriggerList *pCur;
+ SyncTrigger *pTrigger;
+ SysCounterInfo *psci = pCounter->pSysCounterInfo;
+ CARD64 *pnewgtval = NULL;
+ CARD64 *pnewltval = NULL;
+ SyncCounterType ct;
+
+ if (!pCounter)
+ return;
+
+ ct = pCounter->pSysCounterInfo->counterType;
+ if (ct == XSyncCounterNeverChanges)
+ return;
+
+ if (startOver)
+ {
+ XSyncMaxValue(&psci->bracket_greater);
+ XSyncMinValue(&psci->bracket_less);
+ }
+
+ for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next)
+ {
+ pTrigger = pCur->pTrigger;
+
+ if (pTrigger->test_type == XSyncPositiveComparison &&
+ ct != XSyncCounterNeverIncreases)
+ {
+ if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) &&
+ XSyncValueLessThan(pTrigger->test_value,
+ psci->bracket_greater))
+ {
+ psci->bracket_greater = pTrigger->test_value;
+ pnewgtval = &psci->bracket_greater;
+ }
+ }
+ else if (pTrigger->test_type == XSyncNegativeComparison &&
+ ct != XSyncCounterNeverDecreases)
+ {
+ if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) &&
+ XSyncValueGreaterThan(pTrigger->test_value,
+ psci->bracket_less))
+ {
+ psci->bracket_less = pTrigger->test_value;
+ pnewltval = &psci->bracket_less;
+ }
+ }
+ else if ( (pTrigger->test_type == XSyncPositiveTransition &&
+ ct != XSyncCounterNeverIncreases)
+ ||
+ (pTrigger->test_type == XSyncNegativeTransition &&
+ ct != XSyncCounterNeverDecreases)
+ )
+ {
+ if (XSyncValueLessThan(pCounter->value, pTrigger->test_value))
+ {
+ if (XSyncValueLessThan(pTrigger->test_value,
+ psci->bracket_greater))
+ {
+ psci->bracket_greater = pTrigger->test_value;
+ pnewgtval = &psci->bracket_greater;
+ }
+ else
+ if (XSyncValueGreaterThan(pTrigger->test_value,
+ psci->bracket_less))
+ {
+ psci->bracket_less = pTrigger->test_value;
+ pnewltval = &psci->bracket_less;
+ }
+ }
+ }
+ } /* end for each trigger */
+
+ if (pnewgtval || pnewltval)
+ {
+ (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval);
+ }
+}
+
+/*
+ * ***** Resource delete functions
+ */
+
+/* ARGSUSED */
+static int
+FreeAlarm(addr, id)
+ pointer addr;
+ XID id;
+{
+ SyncAlarm *pAlarm = (SyncAlarm *) addr;
+ SyncAlarmClientList *pClient;
+
+ pAlarm->state = XSyncAlarmDestroyed;
+
+ SyncSendAlarmNotifyEvents(pAlarm);
+
+ /* delete event selections */
+
+ while (pAlarm->pEventClients)
+ FreeResource(pAlarm->pEventClients->delete_id, RT_NONE);
+
+ SyncDeleteTriggerFromCounter(&pAlarm->trigger);
+
+ xfree(pAlarm);
+ return Success;
+}
+
+
+/*
+ * ** Cleanup after the destruction of a Counter
+ */
+/* ARGSUSED */
+static int
+FreeCounter(env, id)
+ pointer env;
+ XID id;
+{
+ SyncCounter *pCounter = (SyncCounter *) env;
+ SyncTriggerList *ptl, *pnext;
+
+ pCounter->beingDestroyed = TRUE;
+ /* tell all the counter's triggers that the counter has been destroyed */
+ for (ptl = pCounter->pTriglist; ptl; ptl = pnext)
+ {
+ (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger);
+ pnext = ptl->next;
+ xfree(ptl); /* destroy the trigger list as we go */
+ }
+ if (IsSystemCounter(pCounter))
+ {
+ int i, found = 0;
+
+ xfree(pCounter->pSysCounterInfo);
+
+ /* find the counter in the list of system counters and remove it */
+
+ if (SysCounterList)
+ {
+ for (i = 0; i < SyncNumSystemCounters; i++)
+ {
+ if (SysCounterList[i] == pCounter)
+ {
+ found = i;
+ break;
+ }
+ }
+ if (found < (SyncNumSystemCounters-1))
+ {
+ for (i = found; i < SyncNumSystemCounters-1; i++)
+ {
+ SysCounterList[i] = SysCounterList[i+1];
+ }
+ }
+ }
+ SyncNumSystemCounters--;
+ }
+ xfree(pCounter);
+ return Success;
+}
+
+/*
+ * ** Cleanup after Await
+ */
+/* ARGSUSED */
+static int
+FreeAwait(addr, id)
+ pointer addr;
+ XID id;
+{
+ SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr;
+ SyncAwait *pAwait;
+ int numwaits;
+
+ pAwait = &(pAwaitUnion+1)->await; /* first await on list */
+
+ /* remove triggers from counters */
+
+ for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits;
+ numwaits--, pAwait++)
+ {
+ /* If the counter is being destroyed, FreeCounter will delete
+ * the trigger list itself, so don't do it here.
+ */
+ SyncCounter *pCounter = pAwait->trigger.pCounter;
+ if (pCounter && !pCounter->beingDestroyed)
+ SyncDeleteTriggerFromCounter(&pAwait->trigger);
+ }
+ xfree(pAwaitUnion);
+ return Success;
+}
+
+/* loosely based on dix/events.c/OtherClientGone */
+static int
+FreeAlarmClient(value, id)
+ pointer value; /* must conform to DeleteType */
+ XID id;
+{
+ SyncAlarm *pAlarm = (SyncAlarm *)value;
+ SyncAlarmClientList *pCur, *pPrev;
+
+ for (pPrev = NULL, pCur = pAlarm->pEventClients;
+ pCur;
+ pPrev = pCur, pCur = pCur->next)
+ {
+ if (pCur->delete_id == id)
+ {
+ if (pPrev)
+ pPrev->next = pCur->next;
+ else
+ pAlarm->pEventClients = pCur->next;
+ xfree(pCur);
+ return(Success);
+ }
+ }
+ FatalError("alarm client not on event list");
+ /*NOTREACHED*/
+}
+
+
+/*
+ * ***** Proc functions
+ */
+
+
+/*
+ * ** Initialize the extension
+ */
+static int
+ProcSyncInitialize(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncInitializeReq);
+ xSyncInitializeReply rep;
+ int n;
+
+ REQUEST_SIZE_MATCH(xSyncInitializeReq);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = SYNC_MAJOR_VERSION;
+ rep.minorVersion = SYNC_MINOR_VERSION;
+ rep.length = 0;
+
+ if (client->swapped)
+ {
+ swaps(&rep.sequenceNumber, n);
+ }
+ WriteToClient(client, sizeof(rep), (char *) &rep);
+ return (client->noClientException);
+}
+
+/*
+ * ** Get list of system counters available through the extension
+ */
+static int
+ProcSyncListSystemCounters(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncListSystemCountersReq);
+ xSyncListSystemCountersReply rep;
+ int i, len;
+ xSyncSystemCounter *list, *walklist;
+
+ REQUEST_SIZE_MATCH(xSyncListSystemCountersReq);
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.nCounters = SyncNumSystemCounters;
+
+ for (i = len = 0; i < SyncNumSystemCounters; i++)
+ {
+ char *name = SysCounterList[i]->pSysCounterInfo->name;
+ /* pad to 4 byte boundary */
+ len += (sz_xSyncSystemCounter + strlen(name) + 3) & ~3;
+ }
+
+ if (len)
+ {
+ walklist = list = (xSyncSystemCounter *) ALLOCATE_LOCAL(len);
+ if (!list)
+ return BadAlloc;
+ }
+
+ rep.length = len >> 2;
+
+ if (client->swapped)
+ {
+ register char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.nCounters, n);
+ }
+
+ for (i = 0; i < SyncNumSystemCounters; i++)
+ {
+ int namelen;
+ char *pname_in_reply;
+ SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo;
+
+ walklist->counter = SysCounterList[i]->id;
+ walklist->resolution_hi = XSyncValueHigh32(psci->resolution);
+ walklist->resolution_lo = XSyncValueLow32(psci->resolution);
+ namelen = strlen(psci->name);
+ walklist->name_length = namelen;
+
+ if (client->swapped)
+ {
+ register char n;
+ swapl(&walklist->counter, n);
+ swapl(&walklist->resolution_hi, n);
+ swapl(&walklist->resolution_lo, n);
+ swaps(&walklist->name_length, n);
+ }
+
+ pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter;
+ strncpy(pname_in_reply, psci->name, namelen);
+ walklist = (xSyncSystemCounter *) (((char *)walklist) +
+ ((sz_xSyncSystemCounter + namelen + 3) & ~3));
+ }
+
+ WriteToClient(client, sizeof(rep), (char *) &rep);
+ if (len)
+ {
+ WriteToClient(client, len, (char *) list);
+ DEALLOCATE_LOCAL(list);
+ }
+
+ return (client->noClientException);
+}
+
+/*
+ * ** Set client Priority
+ */
+static int
+ProcSyncSetPriority(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncSetPriorityReq);
+ ClientPtr priorityclient;
+
+ REQUEST_SIZE_MATCH(xSyncSetPriorityReq);
+
+ if (stuff->id == None)
+ priorityclient = client;
+ else if (!(priorityclient = LookupClient(stuff->id, client)))
+ {
+ client->errorValue = stuff->id;
+ return BadMatch;
+ }
+
+ if (priorityclient->priority != stuff->priority)
+ {
+ priorityclient->priority = stuff->priority;
+
+ /* The following will force the server back into WaitForSomething
+ * so that the change in this client's priority is immediately
+ * reflected.
+ */
+ isItTimeToYield = TRUE;
+ dispatchException |= DE_PRIORITYCHANGE;
+ }
+ return Success;
+}
+
+/*
+ * ** Get client Priority
+ */
+static int
+ProcSyncGetPriority(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncGetPriorityReq);
+ xSyncGetPriorityReply rep;
+ ClientPtr priorityclient;
+
+ REQUEST_SIZE_MATCH(xSyncGetPriorityReq);
+
+ if (stuff->id == None)
+ priorityclient = client;
+ else if (!(priorityclient = LookupClient(stuff->id, client)))
+ {
+ client->errorValue = stuff->id;
+ return BadMatch;
+ }
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.priority = priorityclient->priority;
+
+ if (client->swapped)
+ {
+ register char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.priority, n);
+ }
+
+ WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep);
+
+ return (client->noClientException);
+}
+
+/*
+ * ** Create a new counter
+ */
+static int
+ProcSyncCreateCounter(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncCreateCounterReq);
+ SyncCounter *pCounter;
+ CARD64 initial;
+
+ REQUEST_SIZE_MATCH(xSyncCreateCounterReq);
+
+ LEGAL_NEW_RESOURCE(stuff->cid, client);
+
+ XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi);
+ if (!SyncCreateCounter(client, stuff->cid, initial))
+ return BadAlloc;
+
+ return (client->noClientException);
+}
+
+/*
+ * ** Set Counter value
+ */
+static int
+ProcSyncSetCounter(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncSetCounterReq);
+ SyncCounter *pCounter;
+ CARD64 newvalue;
+
+ pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->cid,
+ RTCounter, SecurityWriteAccess);
+ if (pCounter == NULL)
+ {
+ client->errorValue = stuff->cid;
+ return SyncErrorBase + XSyncBadCounter;
+ }
+
+ if (IsSystemCounter(pCounter))
+ {
+ client->errorValue = stuff->cid;
+ return BadAccess;
+ }
+
+ XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
+ SyncChangeCounter(pCounter, newvalue);
+ return Success;
+}
+
+/*
+ * ** Change Counter value
+ */
+static int
+ProcSyncChangeCounter(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncChangeCounterReq);
+ SyncCounter *pCounter;
+ CARD64 newvalue;
+ Bool overflow;
+
+ REQUEST_SIZE_MATCH(xSyncChangeCounterReq);
+
+ pCounter = (SyncCounter *) SecurityLookupIDByType(client, stuff->cid,
+ RTCounter, SecurityWriteAccess);
+ if (pCounter == NULL)
+ {
+ client->errorValue = stuff->cid;
+ return SyncErrorBase + XSyncBadCounter;
+ }
+
+ if (IsSystemCounter(pCounter))
+ {
+ client->errorValue = stuff->cid;
+ return BadAccess;
+ }
+
+ XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi);
+ XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow);
+ if (overflow)
+ {
+ /* XXX 64 bit value can't fit in 32 bits; do the best we can */
+ client->errorValue = stuff->value_hi;
+ return BadValue;
+ }
+ SyncChangeCounter(pCounter, newvalue);
+ return Success;
+}
+
+/*
+ * ** Destroy a counter
+ */
+static int
+ProcSyncDestroyCounter(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncDestroyCounterReq);
+ SyncCounter *pCounter;
+
+ REQUEST_SIZE_MATCH(xSyncDestroyCounterReq);
+
+ pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
+ RTCounter, SecurityDestroyAccess);
+ if (pCounter == NULL)
+ {
+ client->errorValue = stuff->counter;
+ return SyncErrorBase + XSyncBadCounter;
+ }
+ if (IsSystemCounter(pCounter))
+ {
+ client->errorValue = stuff->counter;
+ return BadAccess;
+ }
+ FreeResource(pCounter->id, RT_NONE);
+ return Success;
+}
+
+
+/*
+ * ** Await
+ */
+static int
+ProcSyncAwait(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncAwaitReq);
+ int len, items;
+ int n, i;
+ xSyncWaitCondition *pProtocolWaitConds;
+ int ret;
+ SyncAwaitUnion *pAwaitUnion;
+ SyncAwait *pAwait;
+ int status;
+
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
+
+ len = client->req_len << 2;
+ len -= sz_xSyncAwaitReq;
+ items = len / sz_xSyncWaitCondition;
+
+ if (items * sz_xSyncWaitCondition != len)
+ {
+ return BadLength;
+ }
+ if (items == 0)
+ {
+ client->errorValue = items; /* XXX protocol change */
+ return BadValue;
+ }
+
+ pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1];
+
+ /* all the memory for the entire await list is allocated
+ * here in one chunk
+ */
+ pAwaitUnion = (SyncAwaitUnion *)xalloc((items+1) * sizeof(SyncAwaitUnion));
+ if (!pAwaitUnion)
+ return BadAlloc;
+
+ /* first item is the header, remainder are real wait conditions */
+
+ pAwaitUnion->header.delete_id = FakeClientID(client->index);
+ if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion))
+ {
+ xfree(pAwaitUnion);
+ return BadAlloc;
+ }
+
+ /* don't need to do any more memory allocation for this request! */
+
+ pAwaitUnion->header.client = client;
+ pAwaitUnion->header.num_waitconditions = 0;
+
+ pAwait = &(pAwaitUnion+1)->await; /* skip over header */
+ for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++)
+ {
+ if (pProtocolWaitConds->counter == None) /* XXX protocol change */
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on counters
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ client->errorValue = pProtocolWaitConds->counter;
+ return SyncErrorBase + XSyncBadCounter;
+ }
+
+ /* sanity checks are in SyncInitTrigger */
+ pAwait->trigger.pCounter = NULL;
+ pAwait->trigger.value_type = pProtocolWaitConds->value_type;
+ XSyncIntsToValue(&pAwait->trigger.wait_value,
+ pProtocolWaitConds->wait_value_lo,
+ pProtocolWaitConds->wait_value_hi);
+ pAwait->trigger.test_type = pProtocolWaitConds->test_type;
+
+ status = SyncInitTrigger(client, &pAwait->trigger,
+ pProtocolWaitConds->counter, XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ /* this should take care of removing any triggers created by
+ * this request that have already been registered on counters
+ */
+ FreeResource(pAwaitUnion->header.delete_id, RT_NONE);
+ return status;
+ }
+ /* this is not a mistake -- same function works for both cases */
+ pAwait->trigger.TriggerFired = SyncAwaitTriggerFired;
+ pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired;
+ XSyncIntsToValue(&pAwait->event_threshold,
+ pProtocolWaitConds->event_threshold_lo,
+ pProtocolWaitConds->event_threshold_hi);
+ pAwait->pHeader = &pAwaitUnion->header;
+ pAwaitUnion->header.num_waitconditions++;
+ }
+
+ IgnoreClient(client);
+
+ /* see if any of the triggers are already true */
+
+ pAwait = &(pAwaitUnion+1)->await; /* skip over header */
+ for (i = 0; i < items; i++, pAwait++)
+ {
+ /* don't have to worry about NULL counters because the request
+ * errors before we get here out if they occur
+ */
+ if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger,
+ pAwait->trigger.pCounter->value))
+ {
+ (*pAwait->trigger.TriggerFired)(&pAwait->trigger);
+ break; /* once is enough */
+ }
+ }
+ return Success;
+}
+
+
+/*
+ * ** Query a counter
+ */
+static int
+ProcSyncQueryCounter(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncQueryCounterReq);
+ xSyncQueryCounterReply rep;
+ SyncCounter *pCounter;
+
+ REQUEST_SIZE_MATCH(xSyncQueryCounterReq);
+
+ pCounter = (SyncCounter *)SecurityLookupIDByType(client, stuff->counter,
+ RTCounter, SecurityReadAccess);
+ if (pCounter == NULL)
+ {
+ client->errorValue = stuff->counter;
+ return SyncErrorBase + XSyncBadCounter;
+ }
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ /* if system counter, ask it what the current value is */
+
+ if (IsSystemCounter(pCounter))
+ {
+ (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter,
+ &pCounter->value);
+ }
+
+ rep.value_hi = XSyncValueHigh32(pCounter->value);
+ rep.value_lo = XSyncValueLow32(pCounter->value);
+ if (client->swapped)
+ {
+ register char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.value_hi, n);
+ swapl(&rep.value_lo, n);
+ }
+ WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep);
+ return (client->noClientException);
+}
+
+
+/*
+ * ** Create Alarm
+ */
+static int
+ProcSyncCreateAlarm(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncCreateAlarmReq);
+ SyncAlarm *pAlarm;
+ int status;
+ int i;
+ unsigned long len, vmask;
+ SyncTrigger *pTrigger;
+
+ REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
+
+ LEGAL_NEW_RESOURCE(stuff->id, client);
+
+ vmask = stuff->valueMask;
+ len = client->req_len - (sizeof(xSyncCreateAlarmReq) >> 2);
+ /* the "extra" call to Ones accounts for the presence of 64 bit values */
+ if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
+ return BadLength;
+
+ if (!(pAlarm = (SyncAlarm *) xalloc(sizeof(SyncAlarm))))
+ {
+ return BadAlloc;
+ }
+
+ /* set up defaults */
+
+ pTrigger = &pAlarm->trigger;
+ pTrigger->pCounter = NULL;
+ pTrigger->value_type = XSyncAbsolute;
+ XSyncIntToValue(&pTrigger->wait_value, 0L);
+ pTrigger->test_type = XSyncPositiveComparison;
+ pTrigger->TriggerFired = SyncAlarmTriggerFired;
+ pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed;
+ status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger);
+ if (status != Success)
+ {
+ xfree(pAlarm);
+ return status;
+ }
+
+ pAlarm->client = client;
+ pAlarm->alarm_id = stuff->id;
+ XSyncIntToValue(&pAlarm->delta, 1L);
+ pAlarm->events = TRUE;
+ pAlarm->state = XSyncAlarmInactive;
+ pAlarm->pEventClients = NULL;
+ status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
+ (CARD32 *)&stuff[1]);
+ if (status != Success)
+ {
+ xfree(pAlarm);
+ return status;
+ }
+
+ if (!AddResource(stuff->id, RTAlarm, pAlarm))
+ {
+ xfree(pAlarm);
+ return BadAlloc;
+ }
+
+ /* see if alarm already triggered. NULL counter will not trigger
+ * in CreateAlarm and sets alarm state to Inactive.
+ */
+
+ if (!pTrigger->pCounter)
+ {
+ pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */
+ }
+ else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value))
+ {
+ (*pTrigger->TriggerFired)(pTrigger);
+ }
+
+ return Success;
+}
+
+/*
+ * ** Change Alarm
+ */
+static int
+ProcSyncChangeAlarm(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncChangeAlarmReq);
+ SyncAlarm *pAlarm;
+ long vmask;
+ int len, status;
+
+ REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
+
+ if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
+ RTAlarm, SecurityWriteAccess)))
+ {
+ client->errorValue = stuff->alarm;
+ return SyncErrorBase + XSyncBadAlarm;
+ }
+
+ vmask = stuff->valueMask;
+ len = client->req_len - (sizeof(xSyncChangeAlarmReq) >> 2);
+ /* the "extra" call to Ones accounts for the presence of 64 bit values */
+ if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta))))
+ return BadLength;
+
+ if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask,
+ (CARD32 *)&stuff[1])) != Success)
+ return status;
+
+ /* see if alarm already triggered. NULL counter WILL trigger
+ * in ChangeAlarm.
+ */
+
+ if (!pAlarm->trigger.pCounter ||
+ (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger,
+ pAlarm->trigger.pCounter->value))
+ {
+ (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger);
+ }
+ return Success;
+}
+
+static int
+ProcSyncQueryAlarm(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncQueryAlarmReq);
+ SyncAlarm *pAlarm;
+ xSyncQueryAlarmReply rep;
+ SyncTrigger *pTrigger;
+
+ REQUEST_SIZE_MATCH(xSyncQueryAlarmReq);
+
+ pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
+ RTAlarm, SecurityReadAccess);
+ if (!pAlarm)
+ {
+ client->errorValue = stuff->alarm;
+ return (SyncErrorBase + XSyncBadAlarm);
+ }
+
+ rep.type = X_Reply;
+ rep.length = (sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)) >> 2;
+ rep.sequenceNumber = client->sequence;
+
+ pTrigger = &pAlarm->trigger;
+ rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None;
+
+#if 0 /* XXX unclear what to do, depends on whether relative value-types
+ * are "consumed" immediately and are considered absolute from then
+ * on.
+ */
+ rep.value_type = pTrigger->value_type;
+ rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value);
+ rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value);
+#else
+ rep.value_type = XSyncAbsolute;
+ rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value);
+ rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value);
+#endif
+
+ rep.test_type = pTrigger->test_type;
+ rep.delta_hi = XSyncValueHigh32(pAlarm->delta);
+ rep.delta_lo = XSyncValueLow32(pAlarm->delta);
+ rep.events = pAlarm->events;
+ rep.state = pAlarm->state;
+
+ if (client->swapped)
+ {
+ register char n;
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.counter, n);
+ swapl(&rep.wait_value_hi, n);
+ swapl(&rep.wait_value_lo, n);
+ swapl(&rep.test_type, n);
+ swapl(&rep.delta_hi, n);
+ swapl(&rep.delta_lo, n);
+ }
+
+ WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep);
+ return (client->noClientException);
+}
+
+
+static int
+ProcSyncDestroyAlarm(client)
+ ClientPtr client;
+{
+ SyncAlarm *pAlarm;
+ REQUEST(xSyncDestroyAlarmReq);
+
+ REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq);
+
+ if (!(pAlarm = (SyncAlarm *)SecurityLookupIDByType(client, stuff->alarm,
+ RTAlarm, SecurityDestroyAccess)))
+ {
+ client->errorValue = stuff->alarm;
+ return SyncErrorBase + XSyncBadAlarm;
+ }
+
+ FreeResource(stuff->alarm, RT_NONE);
+ return (client->noClientException);
+}
+
+/*
+ * ** Given an extension request, call the appropriate request procedure
+ */
+static int
+ProcSyncDispatch(client)
+ ClientPtr client;
+{
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+
+ case X_SyncInitialize:
+ return ProcSyncInitialize(client);
+ case X_SyncListSystemCounters:
+ return ProcSyncListSystemCounters(client);
+ case X_SyncCreateCounter:
+ return ProcSyncCreateCounter(client);
+ case X_SyncSetCounter:
+ return ProcSyncSetCounter(client);
+ case X_SyncChangeCounter:
+ return ProcSyncChangeCounter(client);
+ case X_SyncQueryCounter:
+ return ProcSyncQueryCounter(client);
+ case X_SyncDestroyCounter:
+ return ProcSyncDestroyCounter(client);
+ case X_SyncAwait:
+ return ProcSyncAwait(client);
+ case X_SyncCreateAlarm:
+ return ProcSyncCreateAlarm(client);
+ case X_SyncChangeAlarm:
+ return ProcSyncChangeAlarm(client);
+ case X_SyncQueryAlarm:
+ return ProcSyncQueryAlarm(client);
+ case X_SyncDestroyAlarm:
+ return ProcSyncDestroyAlarm(client);
+ case X_SyncSetPriority:
+ return ProcSyncSetPriority(client);
+ case X_SyncGetPriority:
+ return ProcSyncGetPriority(client);
+ default:
+ return BadRequest;
+ }
+}
+
+/*
+ * Boring Swapping stuff ...
+ */
+
+static int
+SProcSyncInitialize(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncInitializeReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncInitializeReq);
+
+ return ProcSyncInitialize(client);
+}
+
+static int
+SProcSyncListSystemCounters(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncListSystemCountersReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncListSystemCountersReq);
+
+ return ProcSyncListSystemCounters(client);
+}
+
+static int
+SProcSyncCreateCounter(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncCreateCounterReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncCreateCounterReq);
+ swapl(&stuff->cid, n);
+ swapl(&stuff->initial_value_lo, n);
+ swapl(&stuff->initial_value_hi, n);
+
+ return ProcSyncCreateCounter(client);
+}
+
+static int
+SProcSyncSetCounter(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncSetCounterReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncSetCounterReq);
+ swapl(&stuff->cid, n);
+ swapl(&stuff->value_lo, n);
+ swapl(&stuff->value_hi, n);
+
+ return ProcSyncSetCounter(client);
+}
+
+static int
+SProcSyncChangeCounter(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncChangeCounterReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncChangeCounterReq);
+ swapl(&stuff->cid, n);
+ swapl(&stuff->value_lo, n);
+ swapl(&stuff->value_hi, n);
+
+ return ProcSyncChangeCounter(client);
+}
+
+static int
+SProcSyncQueryCounter(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncQueryCounterReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncQueryCounterReq);
+ swapl(&stuff->counter, n);
+
+ return ProcSyncQueryCounter(client);
+}
+
+static int
+SProcSyncDestroyCounter(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncDestroyCounterReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncDestroyCounterReq);
+ swapl(&stuff->counter, n);
+
+ return ProcSyncDestroyCounter(client);
+}
+
+static int
+SProcSyncAwait(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncAwaitReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncAwaitReq);
+ SwapRestL(stuff);
+
+ return ProcSyncAwait(client);
+}
+
+
+static int
+SProcSyncCreateAlarm(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncCreateAlarmReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq);
+ swapl(&stuff->id, n);
+ swapl(&stuff->valueMask, n);
+ SwapRestL(stuff);
+
+ return ProcSyncCreateAlarm(client);
+}
+
+static int
+SProcSyncChangeAlarm(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncChangeAlarmReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq);
+ swapl(&stuff->alarm, n);
+ swapl(&stuff->valueMask, n);
+ SwapRestL(stuff);
+ return ProcSyncChangeAlarm(client);
+}
+
+static int
+SProcSyncQueryAlarm(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncQueryAlarmReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncQueryAlarmReq);
+ swapl(&stuff->alarm, n);
+
+ return ProcSyncQueryAlarm(client);
+}
+
+static int
+SProcSyncDestroyAlarm(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncDestroyAlarmReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq);
+ swapl(&stuff->alarm, n);
+
+ return ProcSyncDestroyAlarm(client);
+}
+
+static int
+SProcSyncSetPriority(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncSetPriorityReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncSetPriorityReq);
+ swapl(&stuff->id, n);
+ swapl(&stuff->priority, n);
+
+ return ProcSyncSetPriority(client);
+}
+
+static int
+SProcSyncGetPriority(client)
+ ClientPtr client;
+{
+ REQUEST(xSyncGetPriorityReq);
+ register char n;
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH (xSyncGetPriorityReq);
+ swapl(&stuff->id, n);
+
+ return ProcSyncGetPriority(client);
+}
+
+
+static int
+SProcSyncDispatch(client)
+ ClientPtr client;
+{
+ int n;
+
+ REQUEST(xReq);
+
+ switch (stuff->data)
+ {
+ case X_SyncInitialize:
+ return SProcSyncInitialize(client);
+ case X_SyncListSystemCounters:
+ return SProcSyncListSystemCounters(client);
+ case X_SyncCreateCounter:
+ return SProcSyncCreateCounter(client);
+ case X_SyncSetCounter:
+ return SProcSyncSetCounter(client);
+ case X_SyncChangeCounter:
+ return SProcSyncChangeCounter(client);
+ case X_SyncQueryCounter:
+ return SProcSyncQueryCounter(client);
+ case X_SyncDestroyCounter:
+ return SProcSyncDestroyCounter(client);
+ case X_SyncAwait:
+ return SProcSyncAwait(client);
+ case X_SyncCreateAlarm:
+ return SProcSyncCreateAlarm(client);
+ case X_SyncChangeAlarm:
+ return SProcSyncChangeAlarm(client);
+ case X_SyncQueryAlarm:
+ return SProcSyncQueryAlarm(client);
+ case X_SyncDestroyAlarm:
+ return SProcSyncDestroyAlarm(client);
+ case X_SyncSetPriority:
+ return SProcSyncSetPriority(client);
+ case X_SyncGetPriority:
+ return SProcSyncGetPriority(client);
+ default:
+ return BadRequest;
+ }
+}
+
+/*
+ * Event Swapping
+ */
+
+static void
+SCounterNotifyEvent(from, to)
+ xSyncCounterNotifyEvent *from, *to;
+{
+ to->type = from->type;
+ to->kind = from->kind;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->counter, to->counter);
+ cpswapl(from->wait_value_lo, to->wait_value_lo);
+ cpswapl(from->wait_value_hi, to->wait_value_hi);
+ cpswapl(from->counter_value_lo, to->counter_value_lo);
+ cpswapl(from->counter_value_hi, to->counter_value_hi);
+ cpswapl(from->time, to->time);
+ cpswaps(from->count, to->count);
+ to->destroyed = from->destroyed;
+}
+
+
+static void
+SAlarmNotifyEvent(from, to)
+ xSyncAlarmNotifyEvent *from, *to;
+{
+ to->type = from->type;
+ to->kind = from->kind;
+ cpswaps(from->sequenceNumber, to->sequenceNumber);
+ cpswapl(from->alarm, to->alarm);
+ cpswapl(from->counter_value_lo, to->counter_value_lo);
+ cpswapl(from->counter_value_hi, to->counter_value_hi);
+ cpswapl(from->alarm_value_lo, to->alarm_value_lo);
+ cpswapl(from->alarm_value_hi, to->alarm_value_hi);
+ cpswapl(from->time, to->time);
+ to->state = from->state;
+}
+
+/*
+ * ** Close everything down. ** This is fairly simple for now.
+ */
+/* ARGSUSED */
+static void
+SyncResetProc(extEntry)
+ ExtensionEntry *extEntry;
+{
+ xfree(SysCounterList);
+ SysCounterList = NULL;
+ RTCounter = 0;
+}
+
+
+static void SyncInitServerTime();
+
+/*
+ * ** Initialise the extension.
+ */
+void
+SyncExtensionInit()
+{
+ ExtensionEntry *extEntry;
+
+ if (RTCounter == 0)
+ {
+ RTCounter = CreateNewResourceType(FreeCounter);
+ }
+ RTAlarm = CreateNewResourceType(FreeAlarm);
+ RTAwait = CreateNewResourceType(FreeAwait)|RC_NEVERRETAIN;
+ RTAlarmClient = CreateNewResourceType(FreeAlarmClient)|RC_NEVERRETAIN;
+
+ if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 ||
+ RTAlarmClient == 0 ||
+ (extEntry = AddExtension(SYNC_NAME,
+ XSyncNumberEvents, XSyncNumberErrors,
+ ProcSyncDispatch, SProcSyncDispatch,
+ SyncResetProc,
+ StandardMinorOpcode)) == NULL)
+ {
+ ErrorF("Sync Extension %d.%d failed to Initialise\n",
+ SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
+ return;
+ }
+
+ SyncReqCode = extEntry->base;
+ SyncEventBase = extEntry->eventBase;
+ SyncErrorBase = extEntry->errorBase;
+ EventSwapVector[SyncEventBase + XSyncCounterNotify] = SCounterNotifyEvent;
+ EventSwapVector[SyncEventBase + XSyncAlarmNotify] = SAlarmNotifyEvent;
+
+ /*
+ * Although SERVERTIME is implemented by the OS layer, we initialise it
+ * here because doing it in OsInit() is too early. The resource database
+ * is not initialised when OsInit() is called. This is just about OK
+ * because there is always a servertime counter.
+ */
+ SyncInitServerTime();
+
+#ifdef DEBUG
+ fprintf(stderr, "Sync Extension %d.%d\n",
+ SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION);
+#endif
+}
+
+
+/*
+ * ***** SERVERTIME implementation - should go in its own file in OS directory?
+ */
+
+
+#ifndef WIN32
+#include <sys/time.h>
+#endif
+
+static pointer ServertimeCounter;
+static XSyncValue Now;
+static XSyncValue *pnext_time;
+
+#define GetTime()\
+{\
+ unsigned long millis = GetTimeInMillis();\
+ unsigned long maxis = XSyncValueHigh32(Now);\
+ if (millis < XSyncValueLow32(Now)) maxis++;\
+ XSyncIntsToValue(&Now, millis, maxis);\
+}
+
+/*
+*** Server Block Handler
+*** code inspired by multibuffer extension
+ */
+/*ARGSUSED*/
+static void ServertimeBlockHandler(env, wt, LastSelectMask)
+pointer env;
+struct timeval **wt;
+pointer LastSelectMask;
+{
+ XSyncValue delay;
+ unsigned long timeout;
+
+ if (pnext_time)
+ {
+ GetTime();
+
+ if (XSyncValueGreaterOrEqual(Now, *pnext_time))
+ {
+ timeout = 0;
+ }
+ else
+ {
+ Bool overflow;
+ XSyncValueSubtract(&delay, *pnext_time, Now, &overflow);
+ timeout = XSyncValueLow32(delay);
+ }
+ AdjustWaitForDelay(wt, timeout); /* os/utils.c */
+ }
+}
+
+/*
+*** Wakeup Handler
+ */
+/*ARGSUSED*/
+static void ServertimeWakeupHandler(env, rc, LastSelectMask)
+pointer env;
+int rc;
+pointer LastSelectMask;
+{
+ if (pnext_time)
+ {
+ GetTime();
+
+ if (XSyncValueGreaterOrEqual(Now, *pnext_time))
+ {
+ SyncChangeCounter(ServertimeCounter, Now);
+ }
+ }
+}
+
+static void
+ServertimeQueryValue(pCounter, pValue_return)
+ pointer pCounter;
+ CARD64 *pValue_return;
+{
+ GetTime();
+ *pValue_return = Now;
+}
+
+static void
+ServertimeBracketValues(pCounter, pbracket_less, pbracket_greater)
+ pointer pCounter;
+ CARD64 *pbracket_less;
+ CARD64 *pbracket_greater;
+{
+ if (!pnext_time && pbracket_greater)
+ {
+ RegisterBlockAndWakeupHandlers(ServertimeBlockHandler,
+ ServertimeWakeupHandler,
+ NULL);
+ }
+ else if (pnext_time && !pbracket_greater)
+ {
+ RemoveBlockAndWakeupHandlers(ServertimeBlockHandler,
+ ServertimeWakeupHandler,
+ NULL);
+ }
+ pnext_time = pbracket_greater;
+}
+
+static void
+SyncInitServerTime()
+{
+ CARD64 resolution;
+
+ XSyncIntsToValue(&Now, GetTimeInMillis(), 0);
+ XSyncIntToValue(&resolution, 4);
+ ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution,
+ XSyncCounterNeverDecreases,
+ ServertimeQueryValue, ServertimeBracketValues);
+ pnext_time = NULL;
+}
diff --git a/Xext/xcmisc.c b/Xext/xcmisc.c
new file mode 100644
index 000000000..4977fdf88
--- /dev/null
+++ b/Xext/xcmisc.c
@@ -0,0 +1,218 @@
+/* $Xorg: xcmisc.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */
+/*
+
+Copyright 1993, 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.
+
+*/
+
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "xcmiscstr.h"
+
+static unsigned char XCMiscCode;
+static int ProcXCMiscDispatch(), SProcXCMiscDispatch();
+static void XCMiscResetProc();
+extern void Swap32Write(); /* XXX should be in header file */
+
+void
+XCMiscExtensionInit()
+{
+ ExtensionEntry *extEntry, *AddExtension();
+
+ if (extEntry = AddExtension(XCMiscExtensionName, 0, 0,
+ ProcXCMiscDispatch, SProcXCMiscDispatch,
+ XCMiscResetProc, StandardMinorOpcode))
+ XCMiscCode = (unsigned char)extEntry->base;
+ DeclareExtensionSecurity(XCMiscExtensionName, TRUE);
+}
+
+/*ARGSUSED*/
+static void
+XCMiscResetProc (extEntry)
+ ExtensionEntry *extEntry;
+{
+}
+
+static int
+ProcXCMiscGetVersion(client)
+ register ClientPtr client;
+{
+ REQUEST(xXCMiscGetVersionReq);
+ xXCMiscGetVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xXCMiscGetVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = XCMiscMajorVersion;
+ rep.minorVersion = XCMiscMinorVersion;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof(xXCMiscGetVersionReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcXCMiscGetXIDRange(client)
+ register ClientPtr client;
+{
+ REQUEST(xXCMiscGetXIDRangeReq);
+ xXCMiscGetXIDRangeReply rep;
+ register int n;
+ XID min_id, max_id;
+
+ REQUEST_SIZE_MATCH(xXCMiscGetXIDRangeReq);
+ GetXIDRange(client->index, FALSE, &min_id, &max_id);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.start_id = min_id;
+ rep.count = max_id - min_id + 1;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.start_id, n);
+ swapl(&rep.count, n);
+ }
+ WriteToClient(client, sizeof(xXCMiscGetXIDRangeReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcXCMiscGetXIDList(client)
+ register ClientPtr client;
+{
+ REQUEST(xXCMiscGetXIDListReq);
+ xXCMiscGetXIDListReply rep;
+ register int n;
+ XID *pids;
+ unsigned int count;
+
+ REQUEST_SIZE_MATCH(xXCMiscGetXIDListReq);
+
+ pids = (XID *)ALLOCATE_LOCAL(stuff->count * sizeof(XID));
+ if (!pids)
+ {
+ return BadAlloc;
+ }
+ count = GetXIDList(client, stuff->count, pids);
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = count;
+ rep.count = count;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swapl(&rep.count, n);
+ }
+ WriteToClient(client, sizeof(xXCMiscGetXIDListReply), (char *)&rep);
+ if (count)
+ {
+ client->pSwapReplyFunc = Swap32Write;
+ WriteSwappedDataToClient(client, count * sizeof(XID), pids);
+ }
+ DEALLOCATE_LOCAL(pids);
+ return(client->noClientException);
+}
+
+static int
+ProcXCMiscDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_XCMiscGetVersion:
+ return ProcXCMiscGetVersion(client);
+ case X_XCMiscGetXIDRange:
+ return ProcXCMiscGetXIDRange(client);
+ case X_XCMiscGetXIDList:
+ return ProcXCMiscGetXIDList(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcXCMiscGetVersion(client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xXCMiscGetVersionReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXCMiscGetVersionReq);
+ swaps(&stuff->majorVersion, n);
+ swaps(&stuff->minorVersion, n);
+ return ProcXCMiscGetVersion(client);
+}
+
+static int
+SProcXCMiscGetXIDRange(client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xReq);
+
+ swaps(&stuff->length, n);
+ return ProcXCMiscGetXIDRange(client);
+}
+
+static int
+SProcXCMiscGetXIDList(client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xXCMiscGetXIDListReq);
+
+ swaps(&stuff->length, n);
+ swapl(&stuff->count, n);
+ return ProcXCMiscGetXIDList(client);
+}
+
+static int
+SProcXCMiscDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_XCMiscGetVersion:
+ return SProcXCMiscGetVersion(client);
+ case X_XCMiscGetXIDRange:
+ return SProcXCMiscGetXIDRange(client);
+ case X_XCMiscGetXIDList:
+ return SProcXCMiscGetXIDList(client);
+ default:
+ return BadRequest;
+ }
+}
diff --git a/Xext/xprint.c b/Xext/xprint.c
new file mode 100644
index 000000000..6e2013140
--- /dev/null
+++ b/Xext/xprint.c
@@ -0,0 +1,2873 @@
+/* $Xorg: xprint.c,v 1.5 2001/03/05 20:42:36 pookie Exp $ */
+/*
+(c) Copyright 1996 Hewlett-Packard Company
+(c) Copyright 1996 International Business Machines Corp.
+(c) Copyright 1996 Sun Microsystems, Inc.
+(c) Copyright 1996 Novell, Inc.
+(c) Copyright 1996 Digital Equipment Corp.
+(c) Copyright 1996 Fujitsu Limited
+(c) Copyright 1996 Hitachi, Ltd.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+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.
+
+Except as contained in this notice, the names of the copyright holders shall
+not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from said
+copyright holders.
+*/
+/*******************************************************************
+**
+** *********************************************************
+** *
+** * File: xprint.c
+** *
+** * Copyright: Copyright 1993, 1995 Hewlett-Packard Company
+** *
+** * Copyright 1989 by The Massachusetts Institute of Technology
+** *
+** * 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 MIT not be used in
+** * advertising or publicity pertaining to distribution of the
+** * software without specific prior written permission.
+** * M.I.T. makes no representation about the suitability of
+** * this software for any purpose. It is provided "as is"
+** * without any express or implied warranty.
+** *
+** * MIT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+** * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT-
+** * NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MIT BE LI-
+** * ABLE 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.
+** *
+** *********************************************************
+**
+********************************************************************/
+
+#include "X.h"
+#define NEED_EVENTS
+#include "Xproto.h"
+#undef NEED_EVENTS
+#include "misc.h"
+#include "windowstr.h"
+#include "scrnintstr.h"
+#include "pixmapstr.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "Xatom.h"
+#define _XP_PRINT_SERVER_
+#include "Print.h"
+#include "Printstr.h"
+#undef _XP_PRINT_SERVER_
+#include "../Xprint/DiPrint.h"
+
+extern WindowPtr *WindowTable; /* declared in dix:globals.c */
+
+extern WindowPtr XpDiValidatePrinter();
+extern char *XpDiGetDriverName();
+extern char *XpGetAttributes();
+extern char *XpGetOneAttribute();
+extern int XpRehashPrinterList();
+extern void XpSetFontResFunc();
+
+static void XpResetProc();
+
+static int ProcXpDispatch();
+static int ProcXpSwappedDispatch();
+
+static int ProcXpQueryVersion();
+static int ProcXpGetPrinterList();
+static int ProcXpCreateContext();
+static int ProcXpSetContext();
+static int ProcXpGetContext();
+static int ProcXpDestroyContext();
+static int ProcXpGetContextScreen();
+static int ProcXpStartJob();
+static int ProcXpEndJob();
+static int ProcXpStartDoc();
+static int ProcXpEndDoc();
+static int ProcXpStartPage();
+static int ProcXpEndPage();
+static int ProcXpSelectInput();
+static int ProcXpInputSelected();
+static int ProcXpPutDocumentData();
+static int ProcXpGetDocumentData();
+static int ProcXpGetAttributes();
+static int ProcXpGetOneAttribute();
+static int ProcXpSetAttributes();
+static int ProcXpRehashPrinterList();
+static int ProcXpQueryScreens();
+static int ProcXpGetPageDimensions();
+static int ProcXpSetImageResolution();
+static int ProcXpGetImageResolution();
+
+static void SwapXpNotifyEvent();
+static void SwapXpAttributeEvent();
+
+static int SProcXpGetPrinterList();
+static int SProcXpCreateContext();
+static int SProcXpSetContext();
+static int SProcXpGetContext();
+static int SProcXpDestroyContext();
+static int SProcXpGetContextScreen();
+static int SProcXpStartJob();
+static int SProcXpEndJob();
+static int SProcXpStartDoc();
+static int SProcXpEndDoc();
+static int SProcXpStartPage();
+static int SProcXpEndPage();
+static int SProcXpSelectInput();
+static int SProcXpInputSelected();
+static int SProcXpPutDocumentData();
+static int SProcXpGetDocumentData();
+static int SProcXpGetAttributes();
+static int SProcXpGetOneAttribute();
+static int SProcXpSetAttributes();
+static int SProcXpRehashPrinterList();
+static int SProcXpGetPageDimensions();
+static int SProcXpSetImageResolution();
+static int SProcXpGetImageResolution();
+
+static void SendXpNotify();
+static void SendAttributeNotify();
+static int XpFreeClient();
+static int XpFreeContext();
+static int XpFreePage();
+static int XpFreeEvents();
+static Bool XpCloseScreen();
+static CARD32 GetAllEventMasks();
+static struct _XpEvent *AddEventRec();
+static void DeleteEventRec();
+static struct _XpEvent *FindEventRec();
+static struct _XpClient *CreateXpClient();
+static void FreeXpClient();
+static void InitContextPrivates();
+static void ResetContextPrivates();
+static struct _XpClient *FindClient();
+static struct _XpClient *AcquireClient();
+
+typedef struct _driver {
+ struct _driver *next;
+ char *name;
+ int (* CreateContext)();
+} XpDriverRec, *XpDriverPtr;
+
+typedef struct _xpScreen {
+ Bool (* CloseScreen)();
+ struct _driver *drivers;
+} XpScreenRec, *XpScreenPtr;
+
+/*
+ * Each context has a list of XpClients indicating which clients have
+ * associated this context with their connection.
+ * Each such client has a RTclient resource allocated for it,
+ * and this per-client
+ * resource is used to delete the XpClientRec if/when the client closes
+ * its connection.
+ * The list of XpClients is also walked if/when the context is destroyed
+ * so that the ContextPtr can be removed from the client's devPrivates.
+ */
+typedef struct _XpClient {
+ struct _XpClient *pNext;
+ ClientPtr client;
+ XpContextPtr context;
+ CARD32 eventMask;
+ XID contextClientID; /* unneeded sanity check? */
+} XpClientRec, *XpClientPtr;
+
+/*
+ * Each StartPage request specifies a window which forms the top level
+ * window of the page. One of the following structs is created as a
+ * RTpage resource with the same ID as the window itself. This enables
+ * us to clean up when/if the window is destroyed, and to prevent the
+ * same window from being simultaneously referenced in multiple contexts.
+ * The page resource is created at the first StartPage on a given window,
+ * and is only destroyed when/if the window is destroyed. When the
+ * EndPage is recieved (or an EndDoc or EndJob) the context field is
+ * set to NULL, but the resource remains alive.
+ */
+typedef struct _XpPage {
+ XpContextPtr context;
+} XpPageRec, *XpPagePtr;
+
+typedef struct _XpStPageRec {
+ XpContextPtr pContext;
+ Bool slept;
+ XpPagePtr pPage;
+ WindowPtr pWin;
+} XpStPageRec, *XpStPagePtr;
+
+typedef struct _XpStDocRec {
+ XpContextPtr pContext;
+ Bool slept;
+ CARD8 type;
+} XpStDocRec, *XpStDocPtr;
+
+#define QUADPAD(x) ((((x)+3)>>2)<<2)
+
+/*
+ * Possible bit-mask values in the "state" field of a XpContextRec.
+ */
+#define JOB_STARTED (1 << 0)
+#define DOC_RAW_STARTED (1 << 1)
+#define DOC_COOKED_STARTED (1 << 2)
+#define PAGE_STARTED (1 << 3)
+#define GET_DOC_DATA_STARTED (1 << 4)
+#define JOB_GET_DATA (1 << 5)
+
+static XpScreenPtr XpScreens[MAXSCREENS];
+static unsigned char XpReqCode;
+static int XpEventBase;
+static int XpErrorBase;
+static int XpGeneration = 0;
+static int XpWindowPrivateIndex;
+static int XpClientPrivateIndex;
+
+/* Variables for the context private machinery.
+ * These must be initialized at compile time because
+ * main() calls InitOutput before InitExtensions, and the
+ * output drivers are likely to call AllocateContextPrivate.
+ * These variables are reset at CloseScreen time. CloseScreen
+ * is used because it occurs after FreeAllResources, and before
+ * the next InitOutput cycle.
+ */
+static int contextPrivateCount = 0;
+static int contextPrivateLen = 0;
+static unsigned *contextPrivateSizes = (unsigned *)NULL;
+static unsigned totalContextSize = sizeof(XpContextRec);
+
+/*
+ * There are three types of resources involved. One is the resource associated
+ * with the context itself, with an ID specified by a printing client. The
+ * next is a resource created by us on the client's behalf (and unknown to
+ * the client) when a client inits or sets a context which allows us to
+ * track each client's interest in events
+ * on a particular context, and also allows us to clean up this interest
+ * record when/if the client's connection is closed. Finally, there is
+ * a resource created for each window that's specified in a StartPage. This
+ * resource carries the same ID as the window itself, and enables us to
+ * easily prevent the same window being referenced in multiple contexts
+ * simultaneously, and enables us to clean up if the window is destroyed
+ * before the EndPage.
+ */
+static RESTYPE RTclient, RTcontext, RTpage;
+
+/*
+ * allEvents is the OR of all the legal event mask bits.
+ */
+static CARD32 allEvents = XPPrintMask | XPAttributeMask;
+
+
+/*******************************************************************************
+ *
+ * ExtensionInit, Driver Init functions, QueryVersion, and Dispatch procs
+ *
+ ******************************************************************************/
+
+/*
+ * XpExtensionInit
+ *
+ * Called from InitExtensions in main() usually through miinitextension
+ *
+ */
+
+void
+XpExtensionInit()
+{
+ ExtensionEntry *extEntry, *AddExtension();
+ int i;
+
+ RTclient = CreateNewResourceType(XpFreeClient);
+ RTcontext = CreateNewResourceType(XpFreeContext);
+ RTpage = CreateNewResourceType(XpFreePage);
+ if (RTclient && RTcontext && RTpage &&
+ (extEntry = AddExtension(XP_PRINTNAME, XP_EVENTS, XP_ERRORS,
+ ProcXpDispatch, ProcXpSwappedDispatch,
+ XpResetProc, StandardMinorOpcode)))
+ {
+ XpReqCode = (unsigned char)extEntry->base;
+ XpEventBase = extEntry->eventBase;
+ XpErrorBase = extEntry->errorBase;
+ EventSwapVector[XpEventBase] = SwapXpNotifyEvent;
+ EventSwapVector[XpEventBase+1] = SwapXpAttributeEvent;
+ }
+
+ if(XpGeneration != serverGeneration)
+ {
+ XpClientPrivateIndex = AllocateClientPrivateIndex();
+ /*
+ * We allocate 0 length & simply stuff a pointer to the
+ * ContextRec in the DevUnion.
+ */
+ if(AllocateClientPrivate(XpClientPrivateIndex, 0) != TRUE)
+ {
+ /* we can't alloc a client private, should we bail??? XXX */
+ }
+ XpGeneration = serverGeneration;
+ }
+
+ for(i = 0; i < MAXSCREENS; i++)
+ {
+ /*
+ * If a screen has registered with our extension, then we
+ * wrap the screen's CloseScreen function to allow us to
+ * reset our ContextPrivate stuff. Note that this
+ * requires a printing DDX to call XpRegisterInitFunc
+ * _before_ this extension is initialized - i.e. at screen init
+ * time, _not_ at root window creation time.
+ */
+ if(XpScreens[i] != (XpScreenPtr)NULL)
+ {
+ XpScreens[i]->CloseScreen = screenInfo.screens[i]->CloseScreen;
+ screenInfo.screens[i]->CloseScreen = XpCloseScreen;
+ }
+ }
+ DeclareExtensionSecurity(XP_PRINTNAME, TRUE);
+}
+
+static void
+XpResetProc(extEntry)
+ ExtensionEntry extEntry;
+{
+ int i;
+
+ /*
+ * We can't free up the XpScreens recs here, because extensions are
+ * closed before screens, and our CloseScreen function uses the XpScreens
+ * recs.
+ for(i = 0; i < MAXSCREENS; i++)
+ {
+ if(XpScreens[i] != (XpScreenPtr)NULL)
+ Xfree(XpScreens[i]);
+ XpScreens[i] = (XpScreenPtr)NULL;
+ }
+ */
+}
+
+static Bool
+XpCloseScreen(index, pScreen)
+ int index;
+ ScreenPtr pScreen;
+{
+ Bool (* CloseScreen)();
+
+ CloseScreen = XpScreens[index]->CloseScreen;
+ if(XpScreens[index] != (XpScreenPtr)NULL)
+ {
+ XpDriverPtr pDriv, nextDriv;
+
+ pDriv = XpScreens[index]->drivers;
+ while(pDriv != (XpDriverPtr)NULL)
+ {
+ nextDriv = pDriv->next;
+ Xfree(pDriv);
+ pDriv = nextDriv;
+ }
+ Xfree(XpScreens[index]);
+ }
+ XpScreens[index] = (XpScreenPtr)NULL;
+
+ /*
+ * It's wasteful to call ResetContextPrivates() at every CloseScreen,
+ * but it's the best we know how to do for now. We do this because we
+ * have to wait until after all resources have been freed (so we know
+ * how to free the ContextRecs), and before the next InitOutput cycle.
+ * See dix/main.c for the order of initialization and reset.
+ */
+ ResetContextPrivates();
+ return (*CloseScreen)(index, pScreen);
+}
+
+static void
+FreeScreenEntry(pScreenEntry)
+ XpScreenPtr pScreenEntry;
+{
+ XpDriverPtr pDriver;
+
+ pDriver = pScreenEntry->drivers;
+ while(pDriver != (XpDriverPtr)NULL)
+ {
+ XpDriverPtr tmp;
+
+ tmp = pDriver->next;
+ xfree(pDriver);
+ pDriver = tmp;
+ }
+ xfree(pScreenEntry);
+}
+
+/*
+ * XpRegisterInitFunc tells the print extension which screens
+ * are printers as opposed to displays, and what drivers are
+ * supported on each screen. This eliminates the need of
+ * allocating print-related private structures on windows on _all_ screens.
+ * It also hands the extension a pointer to the routine to be called
+ * whenever a context gets created for a particular driver on this screen.
+ */
+void
+XpRegisterInitFunc(pScreen, driverName, initContext)
+ ScreenPtr pScreen;
+ char *driverName;
+ int (*initContext)();
+{
+ XpDriverPtr pDriver;
+
+ if(XpScreens[pScreen->myNum] == (XpScreenPtr)NULL)
+ {
+ if((XpScreens[pScreen->myNum] =
+ (XpScreenPtr) Xalloc(sizeof(XpScreenRec))) == (XpScreenPtr)NULL)
+ return;
+ XpScreens[pScreen->myNum]->CloseScreen = (Bool(*)())NULL;
+ XpScreens[pScreen->myNum]->drivers = (XpDriverPtr)NULL;
+ }
+
+ if((pDriver = (XpDriverPtr)Xalloc(sizeof(XpDriverRec))) ==
+ (XpDriverPtr)NULL)
+ return;
+ pDriver->next = XpScreens[pScreen->myNum]->drivers;
+ pDriver->name = driverName;
+ pDriver->CreateContext = initContext;
+ XpScreens[pScreen->myNum]->drivers = pDriver;
+}
+
+static int
+ProcXpDispatch(client)
+ ClientPtr client;
+{
+ REQUEST(xReq);
+
+ switch(stuff->data)
+ {
+ case X_PrintQueryVersion:
+ return ProcXpQueryVersion(client);
+ case X_PrintGetPrinterList:
+ return ProcXpGetPrinterList(client);
+ case X_PrintCreateContext:
+ return ProcXpCreateContext(client);
+ case X_PrintSetContext:
+ return ProcXpSetContext(client);
+ case X_PrintGetContext:
+ return ProcXpGetContext(client);
+ case X_PrintDestroyContext:
+ return ProcXpDestroyContext(client);
+ case X_PrintGetContextScreen:
+ return ProcXpGetContextScreen(client);
+ case X_PrintStartJob:
+ return ProcXpStartJob(client);
+ case X_PrintEndJob:
+ return ProcXpEndJob(client);
+ case X_PrintStartDoc:
+ return ProcXpStartDoc(client);
+ case X_PrintEndDoc:
+ return ProcXpEndDoc(client);
+ case X_PrintStartPage:
+ return ProcXpStartPage(client);
+ case X_PrintEndPage:
+ return ProcXpEndPage(client);
+ case X_PrintSelectInput:
+ return ProcXpSelectInput(client);
+ case X_PrintInputSelected:
+ return ProcXpInputSelected(client);
+ case X_PrintPutDocumentData:
+ return ProcXpPutDocumentData(client);
+ case X_PrintGetDocumentData:
+ return ProcXpGetDocumentData(client);
+ case X_PrintSetAttributes:
+ return ProcXpSetAttributes(client);
+ case X_PrintGetAttributes:
+ return ProcXpGetAttributes(client);
+ case X_PrintGetOneAttribute:
+ return ProcXpGetOneAttribute(client);
+ case X_PrintRehashPrinterList:
+ return ProcXpRehashPrinterList(client);
+ case X_PrintQueryScreens:
+ return ProcXpQueryScreens(client);
+ case X_PrintGetPageDimensions:
+ return ProcXpGetPageDimensions(client);
+ case X_PrintSetImageResolution:
+ return ProcXpSetImageResolution(client);
+ case X_PrintGetImageResolution:
+ return ProcXpGetImageResolution(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+ProcXpSwappedDispatch(client)
+ ClientPtr client;
+{
+ int temp;
+ REQUEST(xReq);
+
+ switch(stuff->data)
+ {
+ case X_PrintQueryVersion:
+ swaps(&stuff->length, temp);
+ return ProcXpQueryVersion(client);
+ case X_PrintGetPrinterList:
+ return SProcXpGetPrinterList(client);
+ case X_PrintCreateContext:
+ return SProcXpCreateContext(client);
+ case X_PrintSetContext:
+ return SProcXpSetContext(client);
+ case X_PrintGetContext:
+ return SProcXpGetContext(client);
+ case X_PrintDestroyContext:
+ return SProcXpDestroyContext(client);
+ case X_PrintGetContextScreen:
+ return SProcXpGetContextScreen(client);
+ case X_PrintStartJob:
+ return SProcXpStartJob(client);
+ case X_PrintEndJob:
+ return SProcXpEndJob(client);
+ case X_PrintStartDoc:
+ return SProcXpStartDoc(client);
+ case X_PrintEndDoc:
+ return SProcXpEndDoc(client);
+ case X_PrintStartPage:
+ return SProcXpStartPage(client);
+ case X_PrintEndPage:
+ return SProcXpEndPage(client);
+ case X_PrintSelectInput:
+ return SProcXpSelectInput(client);
+ case X_PrintInputSelected:
+ return SProcXpInputSelected(client);
+ case X_PrintPutDocumentData:
+ return SProcXpPutDocumentData(client);
+ case X_PrintGetDocumentData:
+ return SProcXpGetDocumentData(client);
+ case X_PrintSetAttributes:
+ return SProcXpSetAttributes(client);
+ case X_PrintGetAttributes:
+ return SProcXpGetAttributes(client);
+ case X_PrintGetOneAttribute:
+ return SProcXpGetOneAttribute(client);
+ case X_PrintRehashPrinterList:
+ return SProcXpRehashPrinterList(client);
+ case X_PrintQueryScreens:
+ swaps(&stuff->length, temp);
+ return ProcXpQueryScreens(client);
+ case X_PrintGetPageDimensions:
+ return SProcXpGetPageDimensions(client);
+ case X_PrintSetImageResolution:
+ return SProcXpSetImageResolution(client);
+ case X_PrintGetImageResolution:
+ return SProcXpGetImageResolution(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+ProcXpQueryVersion(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintQueryVersionReq);
+ xPrintQueryVersionReply rep;
+ register int n;
+ long l;
+
+ REQUEST_SIZE_MATCH(xPrintQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = XP_MAJOR_VERSION;
+ rep.minorVersion = XP_MINOR_VERSION;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, l);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sz_xPrintQueryVersionReply, (char *)&rep);
+ return client->noClientException;
+}
+
+/*******************************************************************************
+ *
+ * GetPrinterList : Return a list of all printers associated with this
+ * server. Calls XpDiGetPrinterList, which is defined in
+ * the device-independent code in Xserver/Xprint.
+ *
+ ******************************************************************************/
+
+static int
+ProcXpGetPrinterList(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintGetPrinterListReq);
+ int totalSize, numEntries;
+ XpDiListEntry **pList, *pEntry;
+ xPrintGetPrinterListReply *rep;
+ int n, i, totalBytes;
+ long l;
+ char *curByte;
+
+ REQUEST_AT_LEAST_SIZE(xPrintGetPrinterListReq);
+
+ totalSize = ((sz_xPrintGetPrinterListReq) >> 2) +
+ ((stuff->printerNameLen + 3) >> 2) +
+ ((stuff->localeLen + 3) >> 2);
+ if(totalSize != client->req_len)
+ return BadLength;
+
+ pList = XpDiGetPrinterList(stuff->printerNameLen, (char *)(stuff + 1),
+ stuff->localeLen, (char *)((stuff + 1) +
+ QUADPAD(stuff->printerNameLen)));
+
+ for(numEntries = 0, totalBytes = sz_xPrintGetPrinterListReply;
+ pList[numEntries] != (XpDiListEntry *)NULL;
+ numEntries++)
+ {
+ totalBytes += 2 * sizeof(CARD32);
+ totalBytes += QUADPAD(strlen(pList[numEntries]->name));
+ totalBytes += QUADPAD(strlen(pList[numEntries]->description));
+ }
+
+ if((rep = (xPrintGetPrinterListReply *)xalloc(totalBytes)) ==
+ (xPrintGetPrinterListReply *)NULL)
+ return BadAlloc;
+
+ rep->type = X_Reply;
+ rep->length = (totalBytes - sz_xPrintGetPrinterListReply) >> 2;
+ rep->sequenceNumber = client->sequence;
+ rep->listCount = numEntries;
+ if (client->swapped) {
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, l);
+ swapl(&rep->listCount, l);
+ }
+
+ for(i = 0, curByte = (char *)(rep + 1); i < numEntries; i++)
+ {
+ CARD32 *pCrd;
+ int len;
+
+ pCrd = (CARD32 *)curByte;
+ len = strlen(pList[i]->name);
+ *pCrd = len;
+ if (client->swapped)
+ swapl((long *)curByte, l);
+ curByte += sizeof(CARD32);
+ strncpy(curByte, pList[i]->name, len);
+ curByte += QUADPAD(len);
+
+ pCrd = (CARD32 *)curByte;
+ len = strlen(pList[i]->description);
+ *pCrd = len;
+ if (client->swapped)
+ swapl((long *)curByte, l);
+ curByte += sizeof(CARD32);
+ strncpy(curByte, pList[i]->description, len);
+ curByte += QUADPAD(len);
+ }
+
+ XpDiFreePrinterList(pList);
+
+ WriteToClient(client, totalBytes, (char *)rep);
+ xfree(rep);
+ return client->noClientException;
+}
+
+/*******************************************************************************
+ *
+ * QueryScreens: Returns the list of screens which are associated with
+ * print drivers.
+ *
+ ******************************************************************************/
+
+static int
+ProcXpQueryScreens(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintQueryScreensReq);
+ int i, numPrintScreens, totalSize;
+ WINDOW *pWinId;
+ xPrintQueryScreensReply *rep;
+ long l;
+
+ REQUEST_SIZE_MATCH(xPrintQueryScreensReq);
+
+ rep = (xPrintQueryScreensReply *)xalloc(sz_xPrintQueryScreensReply);
+ pWinId = (WINDOW *)(rep + 1);
+
+ for(i = 0, numPrintScreens = 0, totalSize = sz_xPrintQueryScreensReply;
+ i < MAXSCREENS; i++)
+ {
+ /*
+ * If a screen has registered with our extension, then it's
+ * a printer screen.
+ */
+ if(XpScreens[i] != (XpScreenPtr)NULL)
+ {
+ numPrintScreens++;
+ totalSize += sizeof(WINDOW);
+ rep = (xPrintQueryScreensReply *)xrealloc(rep, totalSize);
+ /* fix of bug: pWinId should be set again after reallocate rep */
+ pWinId = (WINDOW *)(rep + 1);
+ *pWinId = WindowTable[i]->drawable.id;
+ if (client->swapped)
+ swapl((long *)pWinId, l);
+ }
+ }
+
+ rep->type = X_Reply;
+ rep->sequenceNumber = client->sequence;
+ rep->length = (totalSize - sz_xPrintQueryScreensReply) >> 2;
+ rep->listCount = numPrintScreens;
+ if (client->swapped)
+ {
+ int n;
+
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, l);
+ swapl(&rep->listCount, l);
+ }
+
+ WriteToClient(client, totalSize, (char *)rep);
+ xfree(rep);
+ return client->noClientException;
+}
+
+static int
+ProcXpGetPageDimensions(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintGetPageDimensionsReq);
+ CARD16 width, height;
+ xRectangle rect;
+ xPrintGetPageDimensionsReply rep;
+ XpContextPtr pContext;
+ int result;
+
+ REQUEST_SIZE_MATCH(xPrintGetPageDimensionsReq);
+
+ if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
+ stuff->printContext,
+ RTcontext,
+ SecurityReadAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ if(pContext->funcs.GetMediumDimensions != (int (*)())NULL)
+ result = pContext->funcs.GetMediumDimensions(pContext, &width, &height);
+ else
+ return BadImplementation;
+
+ if(pContext->funcs.GetReproducibleArea != (int (*)())NULL)
+ result = pContext->funcs.GetReproducibleArea(pContext, &rect);
+ else
+ return BadImplementation;
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.width = width;
+ rep.height = height;
+ rep.rx = rect.x;
+ rep.ry = rect.y;
+ rep.rwidth = rect.width;
+ rep.rheight = rect.height;
+
+ if(client->swapped)
+ {
+ int n;
+ long l;
+
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, l);
+ swaps(&rep.width, n);
+ swaps(&rep.height, n);
+ swaps(&rep.rx, n);
+ swaps(&rep.ry, n);
+ swaps(&rep.rwidth, n);
+ swaps(&rep.rheight, n);
+ }
+
+ WriteToClient(client, sz_xPrintGetPageDimensionsReply, (char *)&rep);
+ return client->noClientException;
+}
+
+static int
+ProcXpSetImageResolution(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintSetImageResolutionReq);
+ xPrintSetImageResolutionReply rep;
+ XpContextPtr pContext;
+ Bool status;
+ int result;
+
+ REQUEST_SIZE_MATCH(xPrintSetImageResolutionReq);
+
+ if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
+ stuff->printContext,
+ RTcontext,
+ SecurityWriteAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ rep.prevRes = pContext->imageRes;
+ if(pContext->funcs.SetImageResolution != (int (*)())NULL)
+ result = pContext->funcs.SetImageResolution(pContext,
+ (int)stuff->imageRes,
+ &status);
+ else
+ status = FALSE;
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.status = status;
+
+ if(client->swapped)
+ {
+ int n;
+ long l;
+
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, l);
+ swaps(&rep.prevRes, n);
+ }
+
+ WriteToClient(client, sz_xPrintSetImageResolutionReply, (char *)&rep);
+ return client->noClientException;
+}
+
+static int
+ProcXpGetImageResolution(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintGetImageResolutionReq);
+ xPrintGetImageResolutionReply rep;
+ XpContextPtr pContext;
+ Bool status;
+ int result;
+
+ REQUEST_SIZE_MATCH(xPrintGetImageResolutionReq);
+
+ if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
+ stuff->printContext,
+ RTcontext,
+ SecurityReadAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.imageRes = pContext->imageRes;
+
+ if(client->swapped)
+ {
+ int n;
+ long l;
+
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, l);
+ swaps(&rep.imageRes, n);
+ }
+
+ WriteToClient(client, sz_xPrintGetImageResolutionReply, (char *)&rep);
+ return client->noClientException;
+}
+
+/*******************************************************************************
+ *
+ * RehashPrinterList : Cause the server's list of printers to be rebuilt.
+ * This allows new printers to be added, or old ones
+ * deleted without needing to restart the server.
+ *
+ ******************************************************************************/
+
+static int
+ProcXpRehashPrinterList(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintRehashPrinterListReq);
+
+ REQUEST_SIZE_MATCH(xPrintRehashPrinterListReq);
+
+ return XpRehashPrinterList();
+}
+
+/******************************************************************************
+ *
+ * Context functions: Init, Set, Destroy, FreeContext
+ * AllocateContextPrivateIndex, AllocateContextPrivate
+ * and supporting functions.
+ *
+ * Init creates a context, creates a XpClientRec for the calling
+ * client, and stores the contextPtr in the client's devPrivates.
+ *
+ * Set creates a XpClientRec for the calling client, and stores the
+ * contextPtr in the client's devPrivates unless the context is None.
+ * If the context is None, then the client's connection association
+ * with any context is removed.
+ *
+ * Destroy frees any and all XpClientRecs associated with the context,
+ * frees the context itself, and removes the contextPtr from any
+ * relevant client devPrivates.
+ *
+ * FreeContext is called by FreeResource to free up a context.
+ *
+ ******************************************************************************/
+
+/*
+ * CreateContext creates and initializes the memory for the context itself.
+ * The driver's CreateContext function
+ * is then called.
+ */
+static int
+ProcXpCreateContext(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintCreateContextReq);
+ XpScreenPtr pPrintScreen;
+ WindowPtr pRoot;
+ char *printerName, *driverName;
+ XpContextPtr pContext;
+ XpClientPtr pNewPrintClient;
+ int result = Success;
+ XpDriverPtr pDriver;
+
+ REQUEST_AT_LEAST_SIZE(xPrintCreateContextReq);
+
+ LEGAL_NEW_RESOURCE(stuff->contextID, client);
+
+ /*
+ * Check to see if the printer name is valid.
+ */
+ if((pRoot = XpDiValidatePrinter(stuff + 1, stuff->printerNameLen)) ==
+ (WindowPtr)NULL)
+ return BadMatch;
+
+ pPrintScreen = XpScreens[pRoot->drawable.pScreen->myNum];
+
+ /*
+ * Allocate and add the context resource.
+ */
+ if((pContext = (XpContextPtr) xalloc(totalContextSize)) ==
+ (XpContextPtr) NULL)
+ return BadAlloc;
+
+ InitContextPrivates(pContext);
+
+ if(AddResource(stuff->contextID, RTcontext, (pointer) pContext)
+ != TRUE)
+ {
+ xfree(pContext);
+ return BadAlloc;
+ }
+
+ pContext->contextID = stuff->contextID;
+ pContext->clientHead = (XpClientPtr)NULL;
+ pContext->screenNum = pRoot->drawable.pScreen->myNum;
+ pContext->state = 0;
+ pContext->clientSlept = (ClientPtr)NULL;
+ pContext->imageRes = 0;
+
+ pContext->funcs.DestroyContext = (int (*)())NULL;
+ pContext->funcs.StartJob = (int (*)())NULL;
+ pContext->funcs.EndJob = (int (*)())NULL;
+ pContext->funcs.StartDoc = (int (*)())NULL;
+ pContext->funcs.EndDoc = (int (*)())NULL;
+ pContext->funcs.StartPage = (int (*)())NULL;
+ pContext->funcs.EndPage = (int (*)())NULL;
+ pContext->funcs.PutDocumentData = (int (*)())NULL;
+ pContext->funcs.GetDocumentData = (int (*)())NULL;
+ pContext->funcs.GetAttributes = (char * (*)())NULL;
+ pContext->funcs.GetOneAttribute = (char * (*)())NULL;
+ pContext->funcs.SetAttributes = (int (*)())NULL;
+ pContext->funcs.AugmentAttributes = (int (*)())NULL;
+ pContext->funcs.GetMediumDimensions = (int (*)())NULL;
+ pContext->funcs.GetReproducibleArea = (int (*)())NULL;
+ pContext->funcs.SetImageResolution = (int (*)())NULL;
+
+ if((pContext->printerName = (char *)xalloc(stuff->printerNameLen + 1)) ==
+ (char *)NULL)
+ {
+ /* Freeing the context also causes the XpClients to be freed. */
+ FreeResource(stuff->contextID, RT_NONE);
+ return BadAlloc;
+ }
+ strncpy(pContext->printerName, (char *)(stuff + 1), stuff->printerNameLen);
+ pContext->printerName[stuff->printerNameLen] = (char)'\0';
+
+ driverName = XpDiGetDriverName(pRoot->drawable.pScreen->myNum,
+ pContext->printerName);
+
+ for(pDriver = pPrintScreen->drivers;
+ pDriver != (XpDriverPtr)NULL;
+ pDriver = pDriver->next)
+ {
+ if(!strcmp(driverName, pDriver->name))
+ {
+ if(pDriver->CreateContext != (Bool (*)())NULL)
+ pDriver->CreateContext(pContext);
+ else
+ return BadImplementation;
+ break;
+ }
+ }
+
+ if (client->noClientException != Success)
+ return client->noClientException;
+ else
+ return result;
+}
+
+/*
+ * SetContext creates the calling client's contextClient resource,
+ * and stashes the contextID in the client's devPrivate.
+ */
+static int
+ProcXpSetContext(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintSetContextReq);
+
+ XpContextPtr pContext;
+ XpClientPtr pPrintClient;
+ int result = Success;
+
+ REQUEST_AT_LEAST_SIZE(xPrintSetContextReq);
+
+ if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) !=
+ (pointer)NULL)
+ {
+ /*
+ * Erase this client's knowledge of its old context, if any.
+ */
+ if((pPrintClient = FindClient(pContext, client)) != (XpClientPtr)NULL)
+ {
+ XpUnsetFontResFunc(client);
+
+ if(pPrintClient->eventMask == 0)
+ FreeXpClient(pPrintClient, TRUE);
+ }
+
+ client->devPrivates[XpClientPrivateIndex].ptr = (pointer)NULL;
+ }
+ if(stuff->printContext == None)
+ return Success;
+
+ /*
+ * Check to see that the supplied XID is really a valid print context
+ * in this server.
+ */
+ if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
+ stuff->printContext,
+ RTcontext,
+ SecurityWriteAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL)
+ return BadAlloc;
+
+ client->devPrivates[XpClientPrivateIndex].ptr = pContext;
+
+ XpSetFontResFunc(client);
+
+ if (client->noClientException != Success)
+ return client->noClientException;
+ else
+ return result;
+}
+
+XpContextPtr
+XpGetPrintContext(client)
+ ClientPtr client;
+{
+ return (client->devPrivates[XpClientPrivateIndex].ptr);
+}
+
+static int
+ProcXpGetContext(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintGetContextReq);
+ xPrintGetContextReply rep;
+
+ XpContextPtr pContext;
+ XpClientPtr pNewPrintClient;
+ int result = Success;
+ register int n;
+ register long l;
+
+ REQUEST_SIZE_MATCH(xPrintGetContextReq);
+
+ if((pContext = client->devPrivates[XpClientPrivateIndex].ptr) ==
+ (pointer)NULL)
+ rep.printContext = None;
+ else
+ rep.printContext = pContext->contextID;
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, l);
+ swapl(&rep.printContext, l);
+ }
+ WriteToClient(client, sz_xPrintGetContextReply, (char *)&rep);
+ return client->noClientException;
+}
+
+
+/*
+ * DestroyContext frees the context associated with the calling client.
+ * It operates by freeing the context resource ID, thus causing XpFreeContext
+ * to be called.
+ */
+static int
+ProcXpDestroyContext(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintDestroyContextReq);
+
+ XpContextPtr pContext;
+ XpClientPtr pXpClient;
+ ClientPtr curClient;
+
+ REQUEST_SIZE_MATCH(xPrintDestroyContextReq);
+
+ if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
+ stuff->printContext,
+ RTcontext,
+ SecurityDestroyAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ XpUnsetFontResFunc(client);
+
+ FreeResource(pContext->contextID, RT_NONE);
+
+ return Success;
+}
+
+static int
+ProcXpGetContextScreen(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintGetContextScreenReq);
+ xPrintGetContextScreenReply rep;
+ XpContextPtr pContext;
+ int n;
+ long l;
+
+ if((pContext =(XpContextPtr)SecurityLookupIDByType(client,
+ stuff->printContext,
+ RTcontext,
+ SecurityReadAccess))
+ == (XpContextPtr)NULL)
+ return XpErrorBase+XPBadContext;
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.rootWindow = WindowTable[pContext->screenNum]->drawable.id;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, l);
+ swapl(&rep.rootWindow, l);
+ }
+
+ WriteToClient(client, sz_xPrintGetContextScreenReply, (char *)&rep);
+ return client->noClientException;
+}
+
+/*
+ * XpFreeContext is the routine called by dix:FreeResource when a context
+ * resource ID is freed.
+ * It checks to see if there's a partial job pending on the context, and
+ * if so it calls the appropriate End procs with the cancel flag set.
+ * It calls the driver's DestroyContext routine to allow the driver to clean
+ * up any context-related memory or state.
+ * It calls FreeXpClient to free all the
+ * associated XpClientRecs and to set all the client->devPrivates to NULL.
+ * It frees the printer name string, and frees the context
+ * itself.
+ */
+static int
+XpFreeContext(data, id)
+ pointer data;
+ XID id;
+{
+ XpContextPtr pContext = (XpContextPtr)data;
+
+ /* Clean up any pending job on this context */
+ if(pContext->state != 0)
+ {
+ if(pContext->state & PAGE_STARTED)
+ {
+ WindowPtr pWin = (WindowPtr )LookupIDByType(
+ pContext->pageWin, RT_WINDOW);
+ XpPagePtr pPage = (XpPagePtr)LookupIDByType(
+ pContext->pageWin, RTpage);
+
+ pContext->funcs.EndPage(pContext, pWin, TRUE);
+ SendXpNotify(pContext, XPEndPageNotify, TRUE);
+ pContext->state &= ~PAGE_STARTED;
+ if(pPage)
+ pPage->context = (XpContextPtr)NULL;
+ }
+ if((pContext->state & DOC_RAW_STARTED) ||
+ (pContext->state & DOC_COOKED_STARTED))
+ {
+ pContext->funcs.EndDoc(pContext, TRUE);
+ SendXpNotify(pContext, XPEndDocNotify, TRUE);
+ pContext->state &= ~DOC_RAW_STARTED;
+ pContext->state &= ~DOC_COOKED_STARTED;
+ }
+ if(pContext->funcs.EndJob != (int (*)())NULL)
+ {
+ pContext->funcs.EndJob(pContext, TRUE);
+ SendXpNotify(pContext, XPEndJobNotify, TRUE);
+ pContext->state &= ~JOB_STARTED;
+ pContext->state &= ~GET_DOC_DATA_STARTED;
+ }
+ }
+
+ /*
+ * Tell the driver we're destroying the context
+ * This allows the driver to free and ContextPrivate data
+ */
+ if(pContext->funcs.DestroyContext != (int (*)())NULL)
+ pContext->funcs.DestroyContext(pContext);
+
+ /* Free up all the XpClientRecs */
+ while(pContext->clientHead != (XpClientPtr)NULL)
+ {
+ FreeXpClient(pContext->clientHead, TRUE);
+ }
+
+ xfree(pContext->printerName);
+ xfree(pContext);
+ return Success; /* ??? */
+}
+
+/*
+ * XpFreeClient is the routine called by dix:FreeResource when a RTclient
+ * is freed. It simply calls the FreeXpClient routine to do the work.
+ */
+static int
+XpFreeClient(data, id)
+ pointer data;
+ XID id;
+{
+ FreeXpClient((XpClientPtr)data, TRUE);
+}
+
+/*
+ * FreeXpClient
+ * frees the ClientRec passed in, and sets the client->devPrivates to NULL
+ * if the client->devPrivates points to the same context as the XpClient.
+ * Called from XpFreeContext(from FreeResource), and
+ * XpFreeClient. The boolean freeResource specifies whether or not to call
+ * FreeResource for the XpClientRec's XID. We should free it except if we're
+ * called from XpFreeClient (which is itself called from FreeResource for the
+ * XpClientRec's XID).
+ */
+static void
+FreeXpClient(pXpClient, freeResource)
+ XpClientPtr pXpClient;
+ Bool freeResource;
+{
+ XpClientPtr pCurrent, pPrev;
+ XpContextPtr pContext = pXpClient->context;
+
+ /*
+ * If we're freeing the clientRec associated with the context tied
+ * to the client's devPrivates, then we need to clear the devPrivates.
+ */
+ if(pXpClient->client->devPrivates[XpClientPrivateIndex].ptr ==
+ pXpClient->context)
+ {
+ pXpClient->client->devPrivates[XpClientPrivateIndex].ptr =
+ (pointer)NULL;
+ }
+
+ for(pPrev = (XpClientPtr)NULL, pCurrent = pContext->clientHead;
+ pCurrent != (XpClientPtr)NULL;
+ pCurrent = pCurrent->pNext)
+ {
+ if(pCurrent == pXpClient)
+ {
+ if(freeResource == TRUE)
+ FreeResource (pCurrent->contextClientID, RTclient);
+
+ if (pPrev != (XpClientPtr)NULL)
+ pPrev->pNext = pCurrent->pNext;
+ else
+ pContext->clientHead = pCurrent->pNext;
+
+ xfree (pCurrent);
+ break;
+ }
+ pPrev = pCurrent;
+ }
+}
+
+/*
+ * CreateXpClient takes a ClientPtr and returns a pointer to a
+ * XpClientRec which it allocates. It also initializes the Rec,
+ * including adding a resource on behalf of the client to enable the
+ * freeing of the Rec when the client's connection is closed.
+ */
+static XpClientPtr
+CreateXpClient(client)
+ ClientPtr client;
+{
+ XpClientPtr pNewPrintClient;
+ XID clientResource;
+
+ if((pNewPrintClient = (XpClientPtr)xalloc(sizeof(XpClientRec))) ==
+ (XpClientPtr)NULL)
+ return (XpClientPtr)NULL;
+
+ clientResource = FakeClientID(client->index);
+ if(!AddResource(clientResource, RTclient, (pointer)pNewPrintClient))
+ {
+ xfree (pNewPrintClient);
+ return (XpClientPtr)NULL;
+ }
+
+ pNewPrintClient->pNext = (XpClientPtr)NULL;
+ pNewPrintClient->client = client;
+ pNewPrintClient->context = (XpContextPtr)NULL;
+ pNewPrintClient->eventMask = 0;
+ pNewPrintClient->contextClientID = clientResource;
+
+ return pNewPrintClient;
+}
+
+/*
+ * XpFreePage is the routine called by dix:FreeResource to free the page
+ * resource built with the same ID as a page window. It checks to see
+ * if we're in the middle of a page, and if so calls the driver's EndPage
+ * function with 'cancel' set TRUE. It frees the memory associated with
+ * the page resource.
+ */
+static int
+XpFreePage(data, id)
+ pointer data;
+ XID id;
+{
+ XpPagePtr page = (XpPagePtr)data;
+ int result = Success;
+ WindowPtr pWin = (WindowPtr )LookupIDByType(id, RT_WINDOW);
+
+ /* Check to see if the window's being deleted in the middle of a page */
+ if(page->context != (XpContextPtr)NULL &&
+ page->context->state & PAGE_STARTED)
+ {
+ XpScreenPtr pPrintScreen = XpScreens[page->context->screenNum];
+ if(page->context->funcs.EndPage != (int (*)())NULL)
+ result = page->context->funcs.EndPage(page->context, pWin, TRUE);
+ SendXpNotify(page->context, XPEndPageNotify, (int)TRUE);
+ page->context->pageWin = 0; /* None, NULL??? XXX */
+ }
+
+ xfree(page);
+ return result;
+}
+
+/*
+ * ContextPrivate machinery.
+ * Context privates are intended for use by the drivers, allowing the
+ * drivers to maintain context-specific data. The driver should free
+ * the associated data at DestroyContext time.
+ */
+
+static void
+InitContextPrivates(context)
+ XpContextPtr context;
+{
+ register char *ptr;
+ DevUnion *ppriv;
+ register unsigned *sizes;
+ register unsigned size;
+ register int i;
+
+ if (totalContextSize == sizeof(XpContextRec))
+ ppriv = (DevUnion *)NULL;
+ else
+ ppriv = (DevUnion *)(context + 1);
+
+ context->devPrivates = ppriv;
+ sizes = contextPrivateSizes;
+ ptr = (char *)(ppriv + contextPrivateLen);
+ for (i = contextPrivateLen; --i >= 0; ppriv++, sizes++)
+ {
+ if ( (size = *sizes) )
+ {
+ ppriv->ptr = (pointer)ptr;
+ ptr += size;
+ }
+ else
+ ppriv->ptr = (pointer)NULL;
+ }
+}
+
+static void
+ResetContextPrivates()
+{
+ contextPrivateCount = 0;
+ contextPrivateLen = 0;
+ xfree(contextPrivateSizes);
+ contextPrivateSizes = (unsigned *)NULL;
+ totalContextSize = sizeof(XpContextRec);
+
+}
+
+int
+XpAllocateContextPrivateIndex()
+{
+ return contextPrivateCount++;
+}
+
+Bool
+XpAllocateContextPrivate(index, amount)
+ int index;
+ unsigned amount;
+{
+ unsigned oldamount;
+
+ if (index >= contextPrivateLen)
+ {
+ unsigned *nsizes;
+ nsizes = (unsigned *)xrealloc(contextPrivateSizes,
+ (index + 1) * sizeof(unsigned));
+ if (!nsizes)
+ return FALSE;
+ while (contextPrivateLen <= index)
+ {
+ nsizes[contextPrivateLen++] = 0;
+ totalContextSize += sizeof(DevUnion);
+ }
+ contextPrivateSizes = nsizes;
+ }
+ oldamount = contextPrivateSizes[index];
+ if (amount > oldamount)
+ {
+ contextPrivateSizes[index] = amount;
+ totalContextSize += (amount - oldamount);
+ }
+ return TRUE;
+}
+
+static XpClientPtr
+AcquireClient(pContext, client)
+ XpContextPtr pContext;
+ ClientPtr client;
+{
+ XpClientPtr pXpClient;
+
+ if((pXpClient = FindClient(pContext, client)) != (XpClientPtr)NULL)
+ return pXpClient;
+
+ if((pXpClient = CreateXpClient(client)) == (XpClientPtr)NULL)
+ return (XpClientPtr)NULL;
+
+ pXpClient->context = pContext;
+ pXpClient->pNext = pContext->clientHead;
+ pContext->clientHead = pXpClient;
+
+ return pXpClient;
+}
+
+static XpClientPtr
+FindClient(pContext, client)
+ XpContextPtr pContext;
+ ClientPtr client;
+{
+ XpClientPtr pXpClient;
+
+ for(pXpClient = pContext->clientHead; pXpClient != (XpClientPtr)NULL;
+ pXpClient = pXpClient->pNext)
+ {
+ if(pXpClient->client == client) return pXpClient;
+ }
+ return (XpClientPtr)NULL;
+}
+
+
+/******************************************************************************
+ *
+ * Start/End Functions: StartJob, EndJob, StartDoc, EndDoc, StartPage, EndPage
+ *
+ ******************************************************************************/
+
+static int
+ProcXpStartJob(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintStartJobReq);
+ XpContextPtr pContext;
+ int result = Success;
+ XpScreenPtr pPrintScreen;
+
+ REQUEST_SIZE_MATCH(xPrintStartJobReq);
+
+ /* Check to see that a context has been established by this client. */
+ if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
+ == (XpContextPtr)NULL)
+ return XpErrorBase+XPBadContext;
+
+ if(pContext->state != 0)
+ return XpErrorBase+XPBadSequence;
+
+ if(stuff->saveData != XPSpool && stuff->saveData != XPGetData)
+ {
+ client->errorValue = stuff->saveData;
+ return BadValue;
+ }
+
+ pPrintScreen = XpScreens[pContext->screenNum];
+ if(pContext->funcs.StartJob != (int (*)())NULL)
+ result = pContext->funcs.StartJob(pContext,
+ (stuff->saveData == XPGetData)? TRUE:FALSE);
+ else
+ return BadImplementation;
+
+ pContext->state = JOB_STARTED;
+ if(stuff->saveData == XPGetData)
+ pContext->state |= JOB_GET_DATA;
+
+ SendXpNotify(pContext, XPStartJobNotify, FALSE);
+
+ if (client->noClientException != Success)
+ return client->noClientException;
+ else
+ return result;
+}
+
+static int
+ProcXpEndJob(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintEndJobReq);
+ XpScreenPtr pPrintScreen;
+ WindowPtr pWin;
+ int result = Success;
+ XpContextPtr pContext;
+
+ REQUEST_SIZE_MATCH(xPrintEndJobReq);
+
+ if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
+ == (XpContextPtr)NULL)
+ return XpErrorBase+XPBadSequence;
+
+ pPrintScreen = XpScreens[pContext->screenNum];
+
+ if(!(pContext->state & JOB_STARTED))
+ return XpErrorBase+XPBadSequence;
+
+ /* Check for missing EndDoc */
+ if((pContext->state & DOC_RAW_STARTED) ||
+ (pContext->state & DOC_COOKED_STARTED))
+ {
+ if(pContext->state & PAGE_STARTED)
+ {
+ WindowPtr pWin = (WindowPtr )LookupIDByType(
+ pContext->pageWin, RT_WINDOW);
+ XpPagePtr pPage = (XpPagePtr)LookupIDByType(
+ pContext->pageWin, RTpage);
+
+ if(stuff->cancel != TRUE)
+ return XpErrorBase+XPBadSequence;
+
+ if(pContext->funcs.EndPage != (int (*)())NULL)
+ result = pContext->funcs.EndPage(pContext, pWin, TRUE);
+ else
+ return BadImplementation;
+
+ SendXpNotify(pContext, XPEndPageNotify, TRUE);
+
+ pContext->state &= ~PAGE_STARTED;
+
+ if(pPage)
+ pPage->context = (XpContextPtr)NULL;
+
+ if(result != Success) return result;
+ }
+
+ if(pContext->funcs.EndDoc != (int (*)())NULL)
+ result = pContext->funcs.EndDoc(pContext, stuff->cancel);
+ else
+ return BadImplementation;
+
+ SendXpNotify(pContext, XPEndDocNotify, stuff->cancel);
+ }
+
+ if(pContext->funcs.EndJob != (int (*)())NULL)
+ result = pContext->funcs.EndJob(pContext, stuff->cancel);
+ else
+ return BadImplementation;
+
+ pContext->state = 0;
+
+ SendXpNotify(pContext, XPEndJobNotify, stuff->cancel);
+
+ if (client->noClientException != Success)
+ return client->noClientException;
+ else
+ return result;
+}
+
+static Bool
+DoStartDoc(client, c)
+ ClientPtr client;
+ XpStDocPtr c;
+{
+ XpScreenPtr pPrintScreen;
+ int result = Success;
+ XpContextPtr pContext = c->pContext;
+
+ if(c->pContext->state & JOB_GET_DATA &&
+ !(c->pContext->state & GET_DOC_DATA_STARTED))
+ {
+ if(!c->slept)
+ {
+ c->slept = TRUE;
+ ClientSleep(client, DoStartDoc, (pointer) c);
+ c->pContext->clientSlept = client;
+ }
+ return TRUE;
+ }
+
+ pPrintScreen = XpScreens[pContext->screenNum];
+
+ if(pContext->funcs.StartDoc != (int (*)())NULL)
+ result = pContext->funcs.StartDoc(pContext, c->type);
+ else
+ {
+ SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
+ BadImplementation);
+ return TRUE;
+ }
+
+ if(c->type == XPDocNormal)
+ pContext->state |= DOC_COOKED_STARTED;
+ else
+ pContext->state |= DOC_RAW_STARTED;
+
+ SendXpNotify(pContext, XPStartDocNotify, (int)FALSE);
+
+ xfree(c);
+ return TRUE;
+}
+
+static int
+ProcXpStartDoc(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintStartDocReq);
+ XpScreenPtr pPrintScreen;
+ int result = Success;
+ XpContextPtr pContext;
+ XpStDocPtr c;
+
+ REQUEST_SIZE_MATCH(xPrintStartDocReq);
+
+ if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
+ == (XpContextPtr)NULL)
+ return XpErrorBase+XPBadSequence;
+
+ if(!(pContext->state & JOB_STARTED) ||
+ pContext->state & DOC_RAW_STARTED ||
+ pContext->state & DOC_COOKED_STARTED)
+ return XpErrorBase+XPBadSequence;
+
+ if(stuff->type != XPDocNormal && stuff->type != XPDocRaw)
+ {
+ client->errorValue = stuff->type;
+ return BadValue;
+ }
+
+ c = (XpStDocPtr)xalloc(sizeof(XpStDocRec));
+ c->pContext = pContext;
+ c->type = stuff->type;
+ c->slept = FALSE;
+ (void)DoStartDoc(client, c);
+
+ if (client->noClientException != Success)
+ return client->noClientException;
+ else
+ return result;
+}
+
+static int
+ProcXpEndDoc(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintEndDocReq);
+ XpScreenPtr pPrintScreen;
+ XpContextPtr pContext;
+ int result = Success;
+
+ REQUEST_SIZE_MATCH(xPrintEndDocReq);
+
+ if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
+ == (XpContextPtr)NULL)
+ return XpErrorBase+XPBadSequence;
+
+ pPrintScreen = XpScreens[pContext->screenNum];
+
+ if(!(pContext->state & DOC_RAW_STARTED) &&
+ !(pContext->state & DOC_COOKED_STARTED))
+ return XpErrorBase+XPBadSequence;
+
+ if(pContext->state & PAGE_STARTED)
+ {
+ if(stuff->cancel == TRUE)
+ {
+ WindowPtr pWin = (WindowPtr )LookupIDByType(
+ pContext->pageWin, RT_WINDOW);
+ XpPagePtr pPage = (XpPagePtr)LookupIDByType(
+ pContext->pageWin, RTpage);
+
+ if(pContext->funcs.EndPage != (int (*)())NULL)
+ result = pContext->funcs.EndPage(pContext, pWin, TRUE);
+ else
+ return BadImplementation;
+
+ SendXpNotify(pContext, XPEndPageNotify, TRUE);
+
+ if(pPage)
+ pPage->context = (XpContextPtr)NULL;
+ }
+ else
+ return XpErrorBase+XPBadSequence;
+ if(result != Success)
+ return result;
+ }
+
+ if(pContext->funcs.EndDoc != (int (*)())NULL)
+ result = pContext->funcs.EndDoc(pContext, stuff->cancel);
+ else
+ return BadImplementation;
+
+ pContext->state &= ~DOC_RAW_STARTED;
+ pContext->state &= ~DOC_COOKED_STARTED;
+
+ SendXpNotify(pContext, XPEndDocNotify, stuff->cancel);
+
+ if (client->noClientException != Success)
+ return client->noClientException;
+ else
+ return result;
+}
+
+static Bool
+DoStartPage(client, c)
+ ClientPtr client;
+ XpStPagePtr c;
+{
+ XpScreenPtr pPrintScreen;
+ WindowPtr pWin = c->pWin;
+ int result = Success;
+ XpContextPtr pContext = c->pContext;
+ XpPagePtr pPage;
+
+ if(c->pContext->state & JOB_GET_DATA &&
+ !(c->pContext->state & GET_DOC_DATA_STARTED))
+ {
+ if(!c->slept)
+ {
+ c->slept = TRUE;
+ ClientSleep(client, DoStartPage, (pointer) c);
+ c->pContext->clientSlept = client;
+ }
+ return TRUE;
+ }
+
+ if(!(pContext->state & DOC_COOKED_STARTED))
+ {
+ /* Implied StartDoc if it was omitted */
+ if(pContext->funcs.StartDoc != (int (*)())NULL)
+ result = pContext->funcs.StartDoc(pContext, XPDocNormal);
+ else
+ {
+ SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
+ BadImplementation);
+ return TRUE;
+ }
+
+ if(result != Success)
+ {
+ SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0, result);
+ return TRUE;
+ }
+
+ pContext->state |= DOC_COOKED_STARTED;
+ SendXpNotify(pContext, XPStartDocNotify, (int)FALSE);
+ }
+
+ /* ensure the window's not already being used as a page */
+ if((pPage = (XpPagePtr)LookupIDByType(c->pWin->drawable.id, RTpage)) !=
+ (XpPagePtr)NULL)
+ {
+ if(pPage->context != (XpContextPtr)NULL)
+ {
+ SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
+ BadWindow);
+ return TRUE;
+ }
+ }
+ else
+ {
+ if((pPage = (XpPagePtr)xalloc(sizeof(XpPageRec))) == (XpPagePtr)NULL)
+ {
+ SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
+ BadAlloc);
+ return TRUE;
+ }
+ if(AddResource(c->pWin->drawable.id, RTpage, pPage) == FALSE)
+ {
+ xfree(pPage);
+ SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
+ BadAlloc);
+ return TRUE;
+ }
+ }
+
+ pPage->context = pContext;
+ pContext->pageWin = c->pWin->drawable.id;
+
+ pPrintScreen = XpScreens[pContext->screenNum];
+
+
+ if(pContext->funcs.StartPage != (int (*)())NULL)
+ result = pContext->funcs.StartPage(pContext, pWin);
+ else
+ {
+ SendErrorToClient(client, XpReqCode, X_PrintStartPage, 0,
+ BadImplementation);
+ return TRUE;
+ }
+
+ pContext->state |= PAGE_STARTED;
+
+ (void)MapWindow(pWin, client);
+
+ SendXpNotify(pContext, XPStartPageNotify, (int)FALSE);
+
+ return TRUE;
+}
+
+static int
+ProcXpStartPage(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintStartPageReq);
+ XpScreenPtr pPrintScreen;
+ WindowPtr pWin;
+ int result = Success;
+ XpContextPtr pContext;
+ XpPagePtr pPage;
+ XpStPagePtr c;
+
+ REQUEST_SIZE_MATCH(xPrintStartPageReq);
+
+ if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
+ == (XpContextPtr)NULL)
+ return XpErrorBase+XPBadSequence;
+
+ if(!(pContext->state & JOB_STARTED))
+ return XpErrorBase+XPBadSequence;
+
+ /* can't have pages in a raw documented */
+ if(pContext->state & DOC_RAW_STARTED)
+ return XpErrorBase+XPBadSequence;
+
+ if(pContext->state & PAGE_STARTED)
+ return XpErrorBase+XPBadSequence;
+
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->window, client,
+ SecurityWriteAccess);
+ if (!pWin || pWin->drawable.pScreen->myNum != pContext->screenNum)
+ return BadWindow;
+
+ if((c = (XpStPagePtr)xalloc(sizeof(XpStPageRec))) == (XpStPagePtr)NULL)
+ return BadAlloc;
+ c->pContext = pContext;
+ c->slept = FALSE;
+ c->pWin = pWin;
+
+ (void)DoStartPage(client, c);
+
+ if (client->noClientException != Success)
+ return client->noClientException;
+ else
+ return result;
+}
+
+static int
+ProcXpEndPage(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintEndPageReq);
+ XpScreenPtr pPrintScreen;
+ int result = Success;
+ XpContextPtr pContext;
+ XpPagePtr page;
+ WindowPtr pWin;
+
+ REQUEST_SIZE_MATCH(xPrintEndPageReq);
+
+ if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
+ == (XpContextPtr)NULL)
+ return XpErrorBase+XPBadSequence;
+
+ if(!(pContext->state & PAGE_STARTED))
+ return XpErrorBase+XPBadSequence;
+
+ pPrintScreen = XpScreens[pContext->screenNum];
+ pWin = (WindowPtr )LookupIDByType(pContext->pageWin, RT_WINDOW);
+
+ /* Call the ddx's EndPage proc. */
+ if(pContext->funcs.EndPage != (int (*)())NULL)
+ result = pContext->funcs.EndPage(pContext, pWin, stuff->cancel);
+ else
+ return BadImplementation;
+
+ if((page = (XpPagePtr)LookupIDByType(pContext->pageWin, RTpage)) !=
+ (XpPagePtr)NULL)
+ page->context = (XpContextPtr)NULL;
+
+ pContext->state &= ~PAGE_STARTED;
+ pContext->pageWin = 0; /* None, NULL??? XXX */
+
+ (void)UnmapWindow(pWin, FALSE);
+
+ SendXpNotify(pContext, XPEndPageNotify, stuff->cancel);
+
+ if (client->noClientException != Success)
+ return client->noClientException;
+ else
+ return result;
+}
+
+/*******************************************************************************
+ *
+ * Document Data Functions: PutDocumentData, GetDocumentData
+ *
+ ******************************************************************************/
+
+static int
+ProcXpPutDocumentData(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintPutDocumentDataReq);
+ XpContextPtr pContext;
+ DrawablePtr pDraw;
+ int result = Success;
+ int len, totalSize;
+ char *pData, *pDoc_fmt, *pOptions;
+
+ REQUEST_AT_LEAST_SIZE(xPrintPutDocumentDataReq);
+
+ if((pContext = (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr)
+ == (XpContextPtr)NULL)
+ return XpErrorBase+XPBadSequence;
+
+ if(!(pContext->state & DOC_RAW_STARTED) &&
+ !(pContext->state & DOC_COOKED_STARTED))
+ return XpErrorBase+XPBadSequence;
+
+ if (stuff->drawable) {
+ if (pContext->state & DOC_RAW_STARTED)
+ return BadDrawable;
+ pDraw = (DrawablePtr)LookupDrawable(stuff->drawable, client);
+ if (!pDraw || pDraw->pScreen->myNum != pContext->screenNum)
+ return BadDrawable;
+ } else {
+ if (pContext->state & DOC_COOKED_STARTED)
+ return BadDrawable;
+ pDraw = NULL;
+ }
+
+ pData = (char *)(&stuff[1]);
+
+ totalSize = (stuff->len_data + 3) >> 2;
+ pDoc_fmt = pData + (totalSize << 2);
+
+ totalSize += (stuff->len_fmt + 3) >> 2;
+ pOptions = pData + (totalSize << 2);
+
+ totalSize += (stuff->len_options + 3) >> 2;
+ if((totalSize + (sz_xPrintPutDocumentDataReq >> 2)) != client->req_len)
+ return BadLength;
+
+ if(pContext->funcs.PutDocumentData != (int (*)())NULL)
+ {
+ result = (*pContext->funcs.PutDocumentData)(pContext, pDraw,
+ pData, stuff->len_data,
+ pDoc_fmt, stuff->len_fmt,
+ pOptions, stuff->len_options,
+ client);
+ }
+ else
+ return BadImplementation;
+
+ if (client->noClientException != Success)
+ return client->noClientException;
+ else
+ return result;
+}
+
+static int
+ProcXpGetDocumentData(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintGetDocumentDataReq);
+ xPrintGetDocumentDataReply rep;
+ XpScreenPtr pPrintScreen;
+ XpContextPtr pContext;
+ int result = Success;
+
+ REQUEST_SIZE_MATCH(xPrintGetDocumentDataReq);
+
+ if((pContext = (XpContextPtr)SecurityLookupIDByType(client,
+ stuff->printContext,
+ RTcontext,
+ SecurityWriteAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ if(pContext->funcs.GetDocumentData == (int (*)())NULL)
+ return BadImplementation;
+
+ if(!(pContext->state & JOB_GET_DATA) ||
+ pContext->state & GET_DOC_DATA_STARTED)
+ return XpErrorBase+XPBadSequence;
+
+ if(stuff->maxBufferSize <= 0)
+ {
+ client->errorValue = stuff->maxBufferSize;
+ return BadValue; /* gotta have a positive buffer size */
+ }
+
+ result = (*pContext->funcs.GetDocumentData)(pContext, client,
+ stuff->maxBufferSize);
+ if(result != Success)
+ {
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.dataLen = 0;
+ rep.statusCode = 1;
+ rep.finishedFlag = TRUE;
+ if (client->swapped) {
+ int n;
+ long l;
+
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.statusCode, l); /* XXX Why are these longs??? */
+ swapl(&rep.finishedFlag, l); /* XXX Why are these longs??? */
+ }
+ (void)WriteToClient(client,sz_xPrintGetDocumentDataReply,(char *)&rep);
+ }
+ else
+ pContext->state |= GET_DOC_DATA_STARTED;
+
+ if(pContext->clientSlept != (ClientPtr)NULL)
+ {
+ ClientSignal(pContext->clientSlept);
+ ClientWakeup(pContext->clientSlept);
+ pContext->clientSlept = (ClientPtr)NULL;
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+ *
+ * Attribute requests: GetAttributes, SetAttributes, GetOneAttribute
+ *
+ ******************************************************************************/
+
+static int
+ProcXpGetAttributes(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintGetAttributesReq);
+ XpContextPtr pContext;
+ char *attrs;
+ xPrintGetAttributesReply *pRep;
+ int totalSize, n;
+ unsigned long l;
+
+ REQUEST_SIZE_MATCH(xPrintGetAttributesReq);
+
+ if(stuff->type < XPJobAttr || stuff->type > XPServerAttr)
+ {
+ client->errorValue = stuff->type;
+ return BadValue;
+ }
+
+ if(stuff->type != XPServerAttr)
+ {
+ if((pContext = (XpContextPtr)SecurityLookupIDByType(
+ client,
+ stuff->printContext,
+ RTcontext,
+ SecurityReadAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ if(pContext->funcs.GetAttributes == (char *(*)())NULL)
+ return BadImplementation;
+ if((attrs = (*pContext->funcs.GetAttributes)(pContext, stuff->type)) ==
+ (char *)NULL)
+ return BadAlloc;
+ }
+ else
+ {
+ if((attrs = XpGetAttributes((XpContextPtr)NULL, XPServerAttr)) ==
+ (char *)NULL)
+ return BadAlloc;
+ }
+
+ totalSize = sz_xPrintGetAttributesReply + QUADPAD(strlen(attrs));
+ if((pRep = (xPrintGetAttributesReply *)malloc(totalSize)) ==
+ (xPrintGetAttributesReply *)NULL)
+ return BadAlloc;
+
+ pRep->type = X_Reply;
+ pRep->length = (totalSize - sz_xPrintGetAttributesReply) >> 2;
+ pRep->sequenceNumber = client->sequence;
+ pRep->stringLen = strlen(attrs);
+
+ if (client->swapped) {
+ swaps(&pRep->sequenceNumber, n);
+ swapl(&pRep->length, l);
+ swapl(&pRep->stringLen, l);
+ }
+
+ strncpy((char*)(pRep + 1), attrs, strlen(attrs));
+ xfree(attrs);
+
+ WriteToClient(client, totalSize, (char *)pRep);
+
+ xfree(pRep);
+
+ return client->noClientException;
+}
+
+static int
+ProcXpSetAttributes(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintSetAttributesReq);
+ int result = Success;
+ XpContextPtr pContext;
+ char *attr;
+
+ REQUEST_AT_LEAST_SIZE(xPrintSetAttributesReq);
+
+ if(stuff->type < XPJobAttr || stuff->type > XPServerAttr)
+ {
+ client->errorValue = stuff->type;
+ return BadValue;
+ }
+
+ /*
+ * Disallow changing of read-only attribute pools
+ */
+ if(stuff->type == XPPrinterAttr || stuff->type == XPServerAttr)
+ return BadMatch;
+
+ if((pContext = (XpContextPtr)SecurityLookupIDByType(
+ client,
+ stuff->printContext,
+ RTcontext,
+ SecurityWriteAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ if(pContext->funcs.SetAttributes == (int (*)())NULL)
+ return BadImplementation;
+
+ /*
+ * Check for attributes being set after their relevant phase
+ * has already begun (e.g. Job attributes set after StartJob).
+ */
+ if((pContext->state & JOB_STARTED) && stuff->type == XPJobAttr)
+ return XpErrorBase+XPBadSequence;
+ if(((pContext->state & DOC_RAW_STARTED) ||
+ (pContext->state & DOC_COOKED_STARTED)) && stuff->type == XPDocAttr)
+ return XpErrorBase+XPBadSequence;
+ if((pContext->state & PAGE_STARTED) && stuff->type == XPPageAttr)
+ return XpErrorBase+XPBadSequence;
+
+ if((attr = (char *)malloc(stuff->stringLen + 1)) == (char *)NULL)
+ return BadAlloc;
+
+ strncpy(attr, (char *)(stuff + 1), stuff->stringLen);
+ attr[stuff->stringLen] = (char)'\0';
+
+ if(stuff->rule == XPAttrReplace)
+ (*pContext->funcs.SetAttributes)(pContext, stuff->type, attr);
+ else if(stuff->rule == XPAttrMerge)
+ (*pContext->funcs.AugmentAttributes)(pContext, stuff->type, attr);
+ else
+ {
+ client->errorValue = stuff->rule;
+ result = BadValue;
+ }
+
+ xfree(attr);
+
+ SendAttributeNotify(pContext, stuff->type);
+
+ return result;
+}
+
+static int
+ProcXpGetOneAttribute(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintGetOneAttributeReq);
+ XpContextPtr pContext;
+ char *value, *attrName;
+ xPrintGetOneAttributeReply *pRep;
+ int totalSize, n;
+ unsigned long l;
+
+ REQUEST_AT_LEAST_SIZE(xPrintGetOneAttributeReq);
+
+ totalSize = ((sz_xPrintGetOneAttributeReq) >> 2) +
+ ((stuff->nameLen + 3) >> 2);
+ if(totalSize != client->req_len)
+ return BadLength;
+
+ if(stuff->type < XPJobAttr || stuff->type > XPServerAttr)
+ {
+ client->errorValue = stuff->type;
+ return BadValue;
+ }
+
+ if((attrName = (char *)malloc(stuff->nameLen + 1)) == (char *)NULL)
+ return BadAlloc;
+ strncpy(attrName, (char *)(stuff+1), stuff->nameLen);
+ attrName[stuff->nameLen] = (char)'\0';
+
+ if(stuff->type != XPServerAttr)
+ {
+ if((pContext = (XpContextPtr)SecurityLookupIDByType(
+ client,
+ stuff->printContext,
+ RTcontext,
+ SecurityReadAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ if(pContext->funcs.GetOneAttribute == (char *(*)())NULL)
+ return BadImplementation;
+ if((value = (*pContext->funcs.GetOneAttribute)(pContext, stuff->type,
+ attrName)) == (char *)NULL)
+ return BadAlloc;
+ }
+ else
+ {
+ if((value = XpGetOneAttribute((XpContextPtr)NULL, XPServerAttr,
+ attrName)) == (char *)NULL)
+ return BadAlloc;
+ }
+
+ free(attrName);
+
+ totalSize = sz_xPrintGetOneAttributeReply + QUADPAD(strlen(value));
+ if((pRep = (xPrintGetOneAttributeReply *)malloc(totalSize)) ==
+ (xPrintGetOneAttributeReply *)NULL)
+ return BadAlloc;
+
+ pRep->type = X_Reply;
+ pRep->length = (totalSize - sz_xPrintGetOneAttributeReply) >> 2;
+ pRep->sequenceNumber = client->sequence;
+ pRep->valueLen = strlen(value);
+
+ if (client->swapped) {
+ swaps(&pRep->sequenceNumber, n);
+ swapl(&pRep->length, l);
+ swapl(&pRep->valueLen, l);
+ }
+
+ strncpy((char*)(pRep + 1), value, strlen(value));
+
+ WriteToClient(client, totalSize, (char *)pRep);
+
+ xfree(pRep);
+
+ return client->noClientException;
+}
+
+/*******************************************************************************
+ *
+ * Print Event requests: SelectInput InputSelected, SendXpNotify
+ *
+ ******************************************************************************/
+
+
+static int
+ProcXpSelectInput(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintSelectInputReq);
+ int result = Success;
+ XpContextPtr pContext;
+ XpClientPtr pPrintClient;
+
+ REQUEST_SIZE_MATCH(xPrintSelectInputReq);
+
+ /*
+ * Check to see that the supplied XID is really a valid print context
+ * in this server.
+ */
+ if((pContext=(XpContextPtr)SecurityLookupIDByType(client,
+ stuff->printContext,
+ RTcontext,
+ SecurityWriteAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ if(stuff->eventMask & ~allEvents)
+ {
+ client->errorValue = stuff->eventMask;
+ return BadValue; /* bogus event mask bits */
+ }
+
+ if((pPrintClient = AcquireClient(pContext, client)) == (XpClientPtr)NULL)
+ return BadAlloc;
+
+ pPrintClient->eventMask = stuff->eventMask;
+
+ return result;
+}
+
+static int
+ProcXpInputSelected(client)
+ ClientPtr client;
+{
+ REQUEST(xPrintInputSelectedReq);
+ xPrintInputSelectedReply rep;
+ register int n;
+ long l, allMask;
+ WindowPtr pWin;
+ XpClientPtr pXpClient;
+ XpContextPtr pContext;
+
+ REQUEST_SIZE_MATCH(xPrintInputSelectedReq);
+
+ if((pContext=(XpContextPtr)SecurityLookupIDByType(client,
+ stuff->printContext,
+ RTcontext,
+ SecurityReadAccess))
+ == (XpContextPtr)NULL)
+ {
+ client->errorValue = stuff->printContext;
+ return XpErrorBase+XPBadContext;
+ }
+
+ pXpClient = FindClient(pContext, client);
+
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.eventMask = (pXpClient != (XpClientPtr)NULL)? pXpClient->eventMask : 0;
+ rep.allEventsMask = GetAllEventMasks(pContext);
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, l);
+ swapl(&rep.eventMask, l);
+ swapl(&rep.allEventsMask, l);
+ }
+
+ WriteToClient(client, sz_xPrintInputSelectedReply, (char *)&rep);
+ return client->noClientException;
+}
+
+static void
+SendAttributeNotify(pContext, which)
+ XpContextPtr pContext;
+ int which;
+{
+ XpClientPtr pXpClient;
+ xPrintAttributeEvent ae;
+ ClientPtr client;
+
+ pXpClient = pContext->clientHead;
+ if(pXpClient == (XpClientPtr)NULL)
+ return; /* Nobody's interested in the events (or this context). */
+
+ for (pXpClient = pContext->clientHead;
+ pXpClient != (XpClientPtr)NULL;
+ pXpClient = pXpClient->pNext)
+ {
+ client = pXpClient->client;
+ if (client == serverClient || client->clientGone ||
+ !(pXpClient->eventMask & XPAttributeMask))
+ continue;
+ ae.type = XPAttributeNotify + XpEventBase;
+ ae.detail = which;
+ ae.printContext = pContext->contextID;
+ ae.sequenceNumber = client->sequence;
+ WriteEventsToClient (client, 1, (xEvent *) &ae);
+ }
+}
+static void
+SendXpNotify(pContext, which, val)
+ XpContextPtr pContext;
+ int which;
+ int val;
+{
+ XpClientPtr pXpClient;
+ xPrintPrintEvent pe;
+ ClientPtr client;
+
+ pXpClient = pContext->clientHead;
+ if(pXpClient == (XpClientPtr)NULL)
+ return; /* Nobody's interested in the events (or this context). */
+
+ for (pXpClient = pContext->clientHead;
+ pXpClient != (XpClientPtr)NULL;
+ pXpClient = pXpClient->pNext)
+ {
+ client = pXpClient->client;
+ if (client == serverClient || client->clientGone ||
+ !(pXpClient->eventMask & XPPrintMask))
+ continue;
+ pe.type = XPPrintNotify + XpEventBase;
+ pe.detail = which;
+ pe.printContext = pContext->contextID;
+ pe.cancel = (Bool)val;
+ pe.sequenceNumber = client->sequence;
+ WriteEventsToClient (client, 1, (xEvent *) &pe);
+ }
+}
+
+static CARD32
+GetAllEventMasks(pContext)
+ XpContextPtr pContext;
+{
+ XpClientPtr pPrintClient;
+ CARD32 totalMask = (CARD32)0;
+
+ for (pPrintClient = pContext->clientHead;
+ pPrintClient != (XpClientPtr)NULL;
+ pPrintClient = pPrintClient->pNext)
+ {
+ totalMask |= pPrintClient->eventMask;
+ }
+ return totalMask;
+}
+
+/*
+ * XpContextOfClient - returns the XpContextPtr to the context
+ * associated with the specified client, or NULL if the client
+ * does not currently have a context set.
+ */
+XpContextPtr
+XpContextOfClient(client)
+ ClientPtr client;
+{
+ XpContextPtr pContext;
+
+ return (XpContextPtr)client->devPrivates[XpClientPrivateIndex].ptr;
+}
+
+
+/*******************************************************************************
+ *
+ * Swap-request functions
+ *
+ ******************************************************************************/
+
+static int
+SProcXpCreateContext(client)
+ ClientPtr client;
+{
+ int i;
+ long n;
+
+ REQUEST(xPrintCreateContextReq);
+
+ swaps(&stuff->length, i);
+ swapl(&stuff->contextID, n);
+ swapl(&stuff->printerNameLen, n);
+ swapl(&stuff->localeLen, n);
+ return ProcXpCreateContext(client);
+}
+
+static int
+SProcXpGetPrinterList(client)
+ ClientPtr client;
+{
+ int i;
+ long n;
+
+ REQUEST(xPrintGetPrinterListReq);
+
+ swaps(&stuff->length, i);
+ swapl(&stuff->printerNameLen, n);
+ swapl(&stuff->localeLen, n);
+ return ProcXpGetPrinterList(client);
+}
+
+static int
+SProcXpRehashPrinterList(client)
+ ClientPtr client;
+{
+ int i;
+ long n;
+
+ REQUEST(xPrintRehashPrinterListReq);
+ swaps(&stuff->length, i);
+ return ProcXpRehashPrinterList(client);
+}
+
+static int
+SProcXpSetContext(client)
+ ClientPtr client;
+{
+ int i;
+ long n;
+
+ REQUEST(xPrintSetContextReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->printContext, i);
+ return ProcXpSetContext(client);
+}
+
+static int
+SProcXpGetContext(client)
+ ClientPtr client;
+{
+ int i;
+
+ REQUEST(xPrintGetContextReq);
+ swaps(&stuff->length, i);
+ return ProcXpGetContext(client);
+}
+
+static int
+SProcXpDestroyContext(client)
+ ClientPtr client;
+{
+ int i;
+ long n;
+
+ REQUEST(xPrintDestroyContextReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->printContext, n);
+ return ProcXpDestroyContext(client);
+}
+
+static int
+SProcXpGetContextScreen(client)
+ ClientPtr client;
+{
+ int i;
+ long n;
+
+ REQUEST(xPrintGetContextScreenReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->printContext, n);
+ return ProcXpGetContextScreen(client);
+}
+
+static int
+SProcXpInputSelected(client)
+ ClientPtr client;
+{
+ int i;
+ long n;
+
+ REQUEST(xPrintInputSelectedReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->printContext, n);
+ return ProcXpInputSelected(client);
+}
+
+static int
+SProcXpStartJob(client)
+ ClientPtr client;
+{
+ int i;
+
+ REQUEST(xPrintStartJobReq);
+ swaps(&stuff->length, i);
+ return ProcXpStartJob(client);
+}
+
+static int
+SProcXpEndJob(client)
+ ClientPtr client;
+{
+ int i;
+
+ REQUEST(xPrintEndJobReq);
+ swaps(&stuff->length, i);
+ return ProcXpEndJob(client);
+}
+
+static int
+SProcXpStartDoc(client)
+ ClientPtr client;
+{
+ int i;
+
+ REQUEST(xPrintStartDocReq);
+ swaps(&stuff->length, i);
+ return ProcXpStartDoc(client);
+}
+
+static int
+SProcXpEndDoc(client)
+ ClientPtr client;
+{
+ int i;
+
+ REQUEST(xPrintEndDocReq);
+ swaps(&stuff->length, i);
+ return ProcXpEndDoc(client);
+}
+
+static int
+SProcXpStartPage(client)
+ ClientPtr client;
+{
+ int i;
+ long n;
+
+ REQUEST(xPrintStartPageReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->window, n);
+ return ProcXpStartPage(client);
+}
+
+static int
+SProcXpEndPage(client)
+ ClientPtr client;
+{
+ int i;
+
+ REQUEST(xPrintEndPageReq);
+ swaps(&stuff->length, i);
+ return ProcXpEndPage(client);
+}
+
+static int
+SProcXpPutDocumentData(client)
+ ClientPtr client;
+{
+ long n;
+ int i;
+
+ REQUEST(xPrintPutDocumentDataReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->drawable, n);
+ swapl(&stuff->len_data, n);
+ swaps(&stuff->len_fmt, i);
+ swaps(&stuff->len_options, i);
+ return ProcXpPutDocumentData(client);
+}
+
+static int
+SProcXpGetDocumentData(client)
+ ClientPtr client;
+{
+ long n;
+ int i;
+
+ REQUEST(xPrintGetDocumentDataReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->printContext, n);
+ swapl(&stuff->maxBufferSize, n);
+ return ProcXpGetDocumentData(client);
+}
+
+static int
+SProcXpGetAttributes(client)
+ ClientPtr client;
+{
+ long n;
+ int i;
+
+ REQUEST(xPrintGetAttributesReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->printContext, n);
+ return ProcXpGetAttributes(client);
+}
+
+static int
+SProcXpSetAttributes(client)
+ ClientPtr client;
+{
+ long n;
+ int i;
+
+ REQUEST(xPrintSetAttributesReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->printContext, n);
+ swapl(&stuff->stringLen, n);
+ return ProcXpSetAttributes(client);
+}
+
+static int
+SProcXpGetOneAttribute(client)
+ ClientPtr client;
+{
+ long n;
+ int i;
+
+ REQUEST(xPrintGetOneAttributeReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->printContext, n);
+ swapl(&stuff->nameLen, n);
+ return ProcXpGetOneAttribute(client);
+}
+
+static int
+SProcXpSelectInput(client)
+ ClientPtr client;
+{
+ long n;
+ int i;
+
+ REQUEST(xPrintSelectInputReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->eventMask, n);
+ swapl(&stuff->printContext, n);
+ return ProcXpSelectInput(client);
+}
+static int
+SProcXpGetPageDimensions(client)
+ ClientPtr client;
+{
+ long n;
+ int i;
+
+ REQUEST(xPrintGetPageDimensionsReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->printContext, n);
+ return ProcXpGetPageDimensions(client);
+}
+static int
+SProcXpSetImageResolution(client)
+ ClientPtr client;
+{
+ long n;
+ int i;
+
+ REQUEST(xPrintSetImageResolutionReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->printContext, n);
+ swaps(&stuff->imageRes, i);
+ return ProcXpSetImageResolution(client);
+}
+static int
+SProcXpGetImageResolution(client)
+ ClientPtr client;
+{
+ long n;
+ int i;
+
+ REQUEST(xPrintGetImageResolutionReq);
+ swaps(&stuff->length, i);
+ swapl(&stuff->printContext, n);
+ return ProcXpGetImageResolution(client);
+}
+
+static void
+SwapXpNotifyEvent(src, dst)
+ xPrintPrintEvent *src, *dst;
+{
+ /*
+ * Swap the sequence number and context fields.
+ */
+ cpswaps(src->sequenceNumber, dst->sequenceNumber);
+ cpswapl(src->printContext, dst->printContext);
+
+ /*
+ * Copy the byte-long fields.
+ */
+ dst->type = src->type;
+ dst->detail = src->detail;
+ dst->cancel = src->cancel;
+}
+
+static void
+SwapXpAttributeEvent(src, dst)
+ xPrintAttributeEvent *src, *dst;
+{
+ /*
+ * Swap the sequence number and context fields.
+ */
+ cpswaps(src->sequenceNumber, dst->sequenceNumber);
+ cpswapl(src->printContext, dst->printContext);
+
+ /*
+ * Copy the byte-long fields.
+ */
+ dst->type = src->type;
+ dst->detail = src->detail;
+}
diff --git a/Xext/xtest.c b/Xext/xtest.c
new file mode 100644
index 000000000..a07cf6186
--- /dev/null
+++ b/Xext/xtest.c
@@ -0,0 +1,533 @@
+/* $Xorg: xtest.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */
+/*
+
+Copyright 1992, 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.
+
+*/
+
+#include "X.h"
+#define NEED_EVENTS
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include "windowstr.h"
+#include "inputstr.h"
+#include "scrnintstr.h"
+#define _XTEST_SERVER_
+#include "XTest.h"
+#include "xteststr.h"
+#ifdef XINPUT
+#include "XI.h"
+#include "XIproto.h"
+#define EXTENSION_EVENT_BASE 64
+#endif /* XINPUT */
+
+static unsigned char XTestReqCode;
+static int ProcXTestDispatch(), SProcXTestDispatch();
+static void XTestResetProc();
+static int XTestSwapFakeInput();
+CursorPtr GetSpriteCursor();
+WindowPtr GetCurrentRootWindow();
+#ifdef XINPUT
+extern int DeviceValuator;
+DeviceIntPtr LookupDeviceIntRec();
+#endif /* XINPUT */
+
+void
+XTestExtensionInit()
+{
+ ExtensionEntry *extEntry, *AddExtension();
+
+ if (extEntry = AddExtension(XTestExtensionName, 0, 0,
+ ProcXTestDispatch, SProcXTestDispatch,
+ XTestResetProc, StandardMinorOpcode))
+ XTestReqCode = (unsigned char)extEntry->base;
+}
+
+/*ARGSUSED*/
+static void
+XTestResetProc (extEntry)
+ExtensionEntry *extEntry;
+{
+}
+
+static int
+ProcXTestGetVersion(client)
+ register ClientPtr client;
+{
+ REQUEST(xXTestGetVersionReq);
+ xXTestGetVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xXTestGetVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = XTestMajorVersion;
+ rep.minorVersion = XTestMinorVersion;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swaps(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcXTestCompareCursor(client)
+ register ClientPtr client;
+{
+ REQUEST(xXTestCompareCursorReq);
+ xXTestCompareCursorReply rep;
+ WindowPtr pWin;
+ CursorPtr pCursor;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
+ pWin = (WindowPtr)LookupWindow(stuff->window, client);
+ if (!pWin)
+ return(BadWindow);
+ if (stuff->cursor == None)
+ pCursor = NullCursor;
+ else if (stuff->cursor == XTestCurrentCursor)
+ pCursor = GetSpriteCursor();
+ else {
+ pCursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR);
+ if (!pCursor)
+ {
+ client->errorValue = stuff->cursor;
+ return (BadCursor);
+ }
+ }
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.same = (wCursor(pWin) == pCursor);
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ }
+ WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep);
+ return(client->noClientException);
+}
+
+static int
+ProcXTestFakeInput(client)
+ register ClientPtr client;
+{
+ REQUEST(xXTestFakeInputReq);
+ int nev;
+ int n;
+ xEvent *ev;
+ DeviceIntPtr dev;
+ WindowPtr root;
+ int type;
+#ifdef XINPUT
+ Bool extension = FALSE;
+ deviceValuator *dv;
+ int base;
+ int *values;
+#endif /* XINPUT */
+
+ nev = (stuff->length << 2) - sizeof(xReq);
+ if ((nev % sizeof(xEvent)) || !nev)
+ return BadLength;
+ nev /= sizeof(xEvent);
+ UpdateCurrentTime();
+ ev = (xEvent *)&((xReq *)stuff)[1];
+ type = ev->u.u.type & 0177;
+#ifdef XINPUT
+ if (type >= EXTENSION_EVENT_BASE)
+ {
+ type -= DeviceValuator;
+ switch (type) {
+ case XI_DeviceKeyPress:
+ case XI_DeviceKeyRelease:
+ case XI_DeviceButtonPress:
+ case XI_DeviceButtonRelease:
+ case XI_DeviceMotionNotify:
+ case XI_ProximityIn:
+ case XI_ProximityOut:
+ break;
+ default:
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+ if (nev == 1 && type == XI_DeviceMotionNotify)
+ return BadLength;
+ if (type == XI_DeviceMotionNotify)
+ base = ((deviceValuator *)(ev+1))->first_valuator;
+ else
+ base = 0;
+ for (n = 1; n < nev; n++)
+ {
+ dv = (deviceValuator *)(ev + n);
+ if (dv->type != DeviceValuator)
+ {
+ client->errorValue = dv->type;
+ return BadValue;
+ }
+ if (dv->first_valuator != base)
+ {
+ client->errorValue = dv->first_valuator;
+ return BadValue;
+ }
+ if (!dv->num_valuators || dv->num_valuators > 6)
+ {
+ client->errorValue = dv->num_valuators;
+ return BadValue;
+ }
+ base += dv->num_valuators;
+ }
+ type = type - XI_DeviceKeyPress + KeyPress;
+ extension = TRUE;
+ }
+ else
+#endif /* XINPUT */
+ {
+ if (nev != 1)
+ return BadLength;
+ switch (type)
+ {
+ case KeyPress:
+ case KeyRelease:
+ case MotionNotify:
+ case ButtonPress:
+ case ButtonRelease:
+ break;
+ default:
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+ }
+ if (ev->u.keyButtonPointer.time)
+ {
+ TimeStamp activateTime;
+ CARD32 ms;
+
+ activateTime = currentTime;
+ ms = activateTime.milliseconds + ev->u.keyButtonPointer.time;
+ if (ms < activateTime.milliseconds)
+ activateTime.months++;
+ activateTime.milliseconds = ms;
+ ev->u.keyButtonPointer.time = 0;
+
+ /* see mbuf.c:QueueDisplayRequest for code similar to this */
+
+ if (!ClientSleepUntil(client, &activateTime, NULL, NULL))
+ {
+ return BadAlloc;
+ }
+ /* swap the request back so we can simply re-execute it */
+ if (client->swapped)
+ {
+ (void) XTestSwapFakeInput(client, (xReq *)stuff);
+ swaps(&stuff->length, n);
+ }
+ ResetCurrentRequest (client);
+ client->sequence--;
+ return Success;
+ }
+#ifdef XINPUT
+ if (extension)
+ {
+ dev = LookupDeviceIntRec(stuff->deviceid & 0177);
+ if (!dev)
+ {
+ client->errorValue = stuff->deviceid & 0177;
+ return BadValue;
+ }
+ if (nev > 1)
+ {
+ dv = (deviceValuator *)(ev + 1);
+ if (!dev->valuator || dv->first_valuator >= dev->valuator->numAxes)
+ {
+ client->errorValue = dv->first_valuator;
+ return BadValue;
+ }
+ if (dv->first_valuator + dv->num_valuators >
+ dev->valuator->numAxes)
+ {
+ client->errorValue = dv->num_valuators;
+ return BadValue;
+ }
+ }
+ }
+#endif /* XINPUT */
+ switch (type)
+ {
+ case KeyPress:
+ case KeyRelease:
+#ifdef XINPUT
+ if (!extension)
+#endif /* XINPUT */
+ dev = (DeviceIntPtr)LookupKeyboardDevice();
+ if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode ||
+ ev->u.u.detail > dev->key->curKeySyms.maxKeyCode)
+ {
+ client->errorValue = ev->u.u.detail;
+ return BadValue;
+ }
+ break;
+ case MotionNotify:
+#ifdef XINPUT
+ if (extension)
+ {
+ if (ev->u.u.detail != xFalse && ev->u.u.detail != xTrue)
+ {
+ client->errorValue = ev->u.u.detail;
+ return BadValue;
+ }
+ if (ev->u.u.detail == xTrue && dev->valuator->mode == Absolute)
+ {
+ values = dev->valuator->axisVal + dv->first_valuator;
+ for (n = 1; n < nev; n++)
+ {
+ dv = (deviceValuator *)(ev + n);
+ switch (dv->num_valuators)
+ {
+ case 6:
+ dv->valuator5 += values[5];
+ case 5:
+ dv->valuator4 += values[4];
+ case 4:
+ dv->valuator3 += values[3];
+ case 3:
+ dv->valuator2 += values[2];
+ case 2:
+ dv->valuator1 += values[1];
+ case 1:
+ dv->valuator0 += values[0];
+ }
+ values += 6;
+ }
+ }
+ break;
+ }
+#endif /* XINPUT */
+ dev = (DeviceIntPtr)LookupPointerDevice();
+ if (ev->u.keyButtonPointer.root == None)
+ root = GetCurrentRootWindow();
+ else
+ {
+ root = LookupWindow(ev->u.keyButtonPointer.root, client);
+ if (!root)
+ return BadWindow;
+ if (root->parent)
+ {
+ client->errorValue = ev->u.keyButtonPointer.root;
+ return BadValue;
+ }
+ }
+ if (ev->u.u.detail == xTrue)
+ {
+ int x, y;
+ GetSpritePosition(&x, &y);
+ ev->u.keyButtonPointer.rootX += x;
+ ev->u.keyButtonPointer.rootY += y;
+ }
+ else if (ev->u.u.detail != xFalse)
+ {
+ client->errorValue = ev->u.u.detail;
+ return BadValue;
+ }
+ if (ev->u.keyButtonPointer.rootX < 0)
+ ev->u.keyButtonPointer.rootX = 0;
+ else if (ev->u.keyButtonPointer.rootX >= root->drawable.width)
+ ev->u.keyButtonPointer.rootX = root->drawable.width - 1;
+ if (ev->u.keyButtonPointer.rootY < 0)
+ ev->u.keyButtonPointer.rootY = 0;
+ else if (ev->u.keyButtonPointer.rootY >= root->drawable.height)
+ ev->u.keyButtonPointer.rootY = root->drawable.height - 1;
+ if (root != GetCurrentRootWindow())
+ {
+ NewCurrentScreen(root->drawable.pScreen,
+ ev->u.keyButtonPointer.rootX,
+ ev->u.keyButtonPointer.rootY);
+ return client->noClientException;
+ }
+ (*root->drawable.pScreen->SetCursorPosition)
+ (root->drawable.pScreen,
+ ev->u.keyButtonPointer.rootX,
+ ev->u.keyButtonPointer.rootY, FALSE);
+ break;
+ case ButtonPress:
+ case ButtonRelease:
+#ifdef XINPUT
+ if (!extension)
+#endif /* XINPUT */
+ dev = (DeviceIntPtr)LookupPointerDevice();
+ if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons)
+ {
+ client->errorValue = ev->u.u.detail;
+ return BadValue;
+ }
+ break;
+ }
+ if (screenIsSaved == SCREEN_SAVER_ON)
+ SaveScreens(SCREEN_SAVER_OFF, ScreenSaverReset);
+ ev->u.keyButtonPointer.time = currentTime.milliseconds;
+ (*dev->public.processInputProc)(ev, dev, nev);
+ return client->noClientException;
+}
+
+static int
+ProcXTestGrabControl(client)
+ register ClientPtr client;
+{
+ REQUEST(xXTestGrabControlReq);
+
+ REQUEST_SIZE_MATCH(xXTestGrabControlReq);
+ if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse))
+ {
+ client->errorValue = stuff->impervious;
+ return(BadValue);
+ }
+ if (stuff->impervious)
+ MakeClientGrabImpervious(client);
+ else
+ MakeClientGrabPervious(client);
+ return(client->noClientException);
+}
+
+static int
+ProcXTestDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_XTestGetVersion:
+ return ProcXTestGetVersion(client);
+ case X_XTestCompareCursor:
+ return ProcXTestCompareCursor(client);
+ case X_XTestFakeInput:
+ return ProcXTestFakeInput(client);
+ case X_XTestGrabControl:
+ return ProcXTestGrabControl(client);
+ default:
+ return BadRequest;
+ }
+}
+
+static int
+SProcXTestGetVersion(client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xXTestGetVersionReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXTestGetVersionReq);
+ swaps(&stuff->minorVersion, n);
+ return ProcXTestGetVersion(client);
+}
+
+static int
+SProcXTestCompareCursor(client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xXTestCompareCursorReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXTestCompareCursorReq);
+ swapl(&stuff->window, n);
+ swapl(&stuff->cursor, n);
+ return ProcXTestCompareCursor(client);
+}
+
+static int
+XTestSwapFakeInput(client, req)
+ register ClientPtr client;
+ xReq *req;
+{
+ register int nev;
+ register xEvent *ev;
+ xEvent sev;
+ void (*proc)(), NotImplemented();
+
+ nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent);
+ for (ev = (xEvent *)&req[1]; --nev >= 0; ev++)
+ {
+ /* Swap event */
+ proc = EventSwapVector[ev->u.u.type & 0177];
+ /* no swapping proc; invalid event type? */
+ if (!proc || (int (*)()) proc == (int (*)()) NotImplemented) {
+ client->errorValue = ev->u.u.type;
+ return BadValue;
+ }
+ (*proc)(ev, &sev);
+ *ev = sev;
+ }
+ return Success;
+}
+
+static int
+SProcXTestFakeInput(client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xReq);
+
+ swaps(&stuff->length, n);
+ n = XTestSwapFakeInput(client, stuff);
+ if (n != Success)
+ return n;
+ return ProcXTestFakeInput(client);
+}
+
+static int
+SProcXTestGrabControl(client)
+ register ClientPtr client;
+{
+ register int n;
+ REQUEST(xXTestGrabControlReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xXTestGrabControlReq);
+ return ProcXTestGrabControl(client);
+}
+
+static int
+SProcXTestDispatch (client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_XTestGetVersion:
+ return SProcXTestGetVersion(client);
+ case X_XTestCompareCursor:
+ return SProcXTestCompareCursor(client);
+ case X_XTestFakeInput:
+ return SProcXTestFakeInput(client);
+ case X_XTestGrabControl:
+ return SProcXTestGrabControl(client);
+ default:
+ return BadRequest;
+ }
+}
diff --git a/Xext/xtest1dd.c b/Xext/xtest1dd.c
new file mode 100644
index 000000000..38c977557
--- /dev/null
+++ b/Xext/xtest1dd.c
@@ -0,0 +1,1613 @@
+/* $Xorg: xtest1dd.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */
+/*
+ * File: xtest1dd.c
+ *
+ * This file contains the device dependent parts of the input
+ * synthesis extension.
+ */
+
+/*
+
+
+Copyright 1986, 1987, 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.
+
+
+Copyright 1986, 1987, 1988 by Hewlett-Packard Corporation
+
+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 makes no representations about the
+suitability of this software for any purpose. It is provided
+"as is" without express or implied warranty.
+
+This software is not subject to any license of the American
+Telephone and Telegraph Company or of the Regents of the
+University of California.
+
+*/
+
+/***************************************************************
+ * include files
+ ***************************************************************/
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+
+#include <stdio.h>
+#include "Xos.h"
+#include "X.h"
+#include "Xmd.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "dixstruct.h"
+#define XTestSERVER_SIDE
+#include "xtestext1.h"
+
+/***************************************************************
+ * defines
+ ***************************************************************/
+
+/*
+ * the size of the fake input action array
+ */
+#define ACTION_ARRAY_SIZE 100
+
+/***************************************************************
+ * externals
+ ***************************************************************/
+
+/*
+ * Holds the xTestInputAction event type code.
+ * This is defined in xtestext1di.c.
+ */
+extern int XTestInputActionType;
+/*
+ * Holds the xTestFakeAck event type code.
+ * This is defined in xtestext1di.c.
+ */
+extern int XTestFakeAckType;
+/*
+ * used in the WriteReplyToClient macro
+ */
+extern void (* ReplySwapVector[256]) ();
+
+extern int exclusive_steal;
+
+/***************************************************************
+ * variables
+ ***************************************************************/
+
+/*
+ * array to hold fake input actions
+ */
+struct {
+ /*
+ * holds the action type, one of: XTestDELAY_ACTION,
+ * XTestKEY_ACTION, XTestMOTION_ACTION, XTestJUMP_ACTION
+ */
+ CARD8 type;
+ /*
+ * holds the device type, in the range 0 to 15
+ */
+ CARD8 device;
+ /*
+ * for XTestKEY_ACTION type, holds the keycode
+ */
+ CARD8 keycode;
+ /*
+ * for XTestKEY_ACTION type, holds the key up/down state
+ */
+ CARD8 keystate;
+ /*
+ * for XTestMOTION_ACTION and XTestJUMP_ACTION types,
+ * holds the x and y coordinates to move the mouse to
+ */
+ int x;
+ int y;
+ /*
+ * holds the time to delay (in milliseconds) before performing
+ * the action
+ */
+ CARD32 delay_time;
+}action_array[ACTION_ARRAY_SIZE];
+
+/*
+ * write index for input action array
+ */
+static int write_index = 0;
+/*
+ * read index for input action array
+ */
+static int read_index = 0;
+/*
+ * this is where the input actions are accumulated until they are sent
+ * to a client (in a wire event)
+ */
+static xTestInputActionEvent input_action_packet;
+/*
+ * holds the index (in bytes) into the input actions buffer in the
+ * current input action event
+ */
+static int packet_index;
+/*
+ * set to 1 when the input action event is full and needs to be sent to the
+ * client
+ */
+static int input_action_event_full = 0;
+/*
+ * logical x position of the mouse during input action gathering
+ */
+short xtest_mousex;
+/*
+ * logical y position of the mouse during input action gathering
+ */
+short xtest_mousey;
+/*
+ * logical x position of the mouse during input action playback
+ */
+static short mx;
+/*
+ * logical y position of the mouse during input action playback
+ */
+static short my;
+/*
+ * logical x position of the mouse while we are reading fake input actions
+ * from the client and putting them into the fake input action array
+ */
+static short pmousex;
+/*
+ * logical y position of the mouse while we are reading fake input actions
+ * from the client and putting them into the fake input action array
+ */
+static short pmousey;
+/*
+ * The playback_on flag is set to 1 while there are input actions in the
+ * input action array. It is set to 0 when the server has received all of
+ * the user actions.
+ */
+int playback_on = 0;
+/*
+ * identity of the client using XTestGetInput to get user input actions
+ */
+ClientPtr current_xtest_client;
+/*
+ * if 1 send multiple input actions per XTestInputAction event;
+ * if 0 send one input action per XTestInputAction event
+ */
+static char packed_mode;
+/*
+ * identity of the client using the XTestFakeInput function to send some
+ * fake input actions to the server
+ */
+ClientPtr playback_client = NULL;
+/*
+ * Set to 1 when the XTestFAKE_ACK_REQUEST flag is set in a XTestFakeInput
+ * request. Set back to 0 when all of the input actions have been sent
+ * to the server.
+ */
+static int acknowledge = 0;
+/*
+ * The server's idea of the current time is saved in these variables when
+ * a XTestFakeInput request is received. It is restored when all fake input
+ * actions are sent to the server or when the playback client disconnects.
+ */
+static int saved_sec;
+static int saved_usec;
+/*
+ * Set to 1 when there is a valid time in saved_sec and saved_usec.
+ */
+static int time_saved = 0;
+/*
+ * holds the extension's notion of what the current time is while it is
+ * sending input actions to a client
+ */
+static struct timeval current_time;
+/*
+ * holds the time when the extension should place the next fake input action
+ * into the server's normal events queue
+ */
+static struct timeval play_time;
+/*
+ * set to 1 when play_time is first set, cleared to 0 when the
+ * client using the extension disconnects, or when XTestReset is called
+ */
+static char play_clock = 0;
+/*
+ * holds the amount of time left until the next input action from the
+ * input action array can be sent to the server
+ */
+static struct timeval rtime;
+/*
+ * Set to 1 after the extension is done waiting for the correct time delay
+ * for an input action to be sent to the server. Remains a 1 until the time
+ * delay for the next input action is computed. Then set to 0 if the
+ * extension has to wait for the correct time delay.
+ */
+static int go_for_next = 1;
+/*
+ * needed to restore waitime if playback is to be aborted
+ */
+static struct timeval *restorewait;
+/*
+ * tmon special command key
+ *
+ * To use the test monitor program (called tmon) efficiently, it is
+ * desirable to have the extension be able to recognize a special "trigger"
+ * key. If the extension did not do this, tmon would have to have the
+ * extension send all keyboard user input actions exclusively to tmon,
+ * only to have tmon send them right back if they were not the command key.
+ *
+ * If the extension can recognize the command key, then tmon can let the
+ * extension handle keyboard user input actions normally until the command
+ * key is pressed (and released), and only then have the extension start
+ * sending keyboard user input actions exclusively to tmon.
+ *
+ * Any key on the keyboard can be used for this command key. It is most
+ * convenient if it is a low-frequency key. If you want to generate a
+ * normal occurrance of this key to a client, just hit it twice. Tmon
+ * will recognize the first occurrance of the key, take control of the input
+ * actions, and wait for certain keys. If it sees another occurrance of the
+ * command key, it will send one occurrance of the command key to the
+ * extension, and go back to waiting.
+ *
+ * set and also referenced in device layer
+ * XXX there should be a way to set this through the protocol
+ */
+KeyCode xtest_command_key = 0;
+
+/***************************************************************
+ * function declarations
+ ***************************************************************/
+
+void flush_input_actions();
+void XTestStealJumpData();
+void XTestGenerateEvent();
+void XTestGetPointerPos();
+void XTestJumpPointer();
+
+static void parse_key_fake();
+static void parse_motion_fake();
+static void parse_jump_fake();
+static void parse_delay_fake();
+static void send_ack();
+static void start_play_clock();
+static void compute_action_time();
+static int find_residual_time();
+
+static CARD16 check_time_event();
+static CARD32 current_ms();
+static int there_is_room();
+
+/******************************************************************************
+ *
+ * stop_stealing_input
+ *
+ * Stop stealing input actions.
+ */
+void
+stop_stealing_input()
+{
+/*
+ * put any code that you might need to stop stealing input actions here
+ */
+ if (packet_index != 0)
+ {
+ /*
+ * if there is a partially full input action event waiting
+ * when this function is called, send it to the client
+ */
+ flush_input_actions();
+ }
+}
+
+/******************************************************************************
+ *
+ * steal_input
+ *
+ * Start stealing input actions and sending them to the passed-in client.
+ */
+void
+steal_input(client, mode)
+/*
+ * which client is to receive the input action events
+ */
+ClientPtr client;
+/*
+ * what input action packing mode to use. one of 0, XTestPACKED_MOTION,
+ * or XTestPACKED_ACTIONS; optionally 'or'ed with XTestEXCLUSIVE,
+ */
+CARD32 mode;
+{
+ if (packet_index != 0)
+ {
+ /*
+ * if there is a partially full input action event waiting
+ * when this function is called, send it to the client
+ */
+ flush_input_actions();
+ }
+ else
+ {
+ /*
+ * otherwise, set up a new input action event
+ */
+ input_action_packet.type = XTestInputActionType;
+ packet_index = 0;
+ }
+ /*
+ * set up the new input action packing mode
+ */
+ packed_mode = mode & ~(XTestEXCLUSIVE);
+ /*
+ * keep track of where the mouse is
+ */
+ XTestGetPointerPos(&xtest_mousex, &xtest_mousey);
+ /*
+ * keep track of which client is getting input actions
+ */
+ current_xtest_client = client;
+ /*
+ * find out what time it is
+ */
+ X_GETTIMEOFDAY(&current_time);
+ /*
+ * jump to the initial position of the mouse, using a device type of 0.
+ */
+ XTestStealJumpData(xtest_mousex, xtest_mousey, 0);
+}
+
+/******************************************************************************
+ *
+ * flush_input_actions
+ *
+ * Write the input actions event to the current requesting client
+ * and re-initialize the input action event.
+ */
+void
+flush_input_actions()
+{
+ /*
+ * pointer to the input action event
+ */
+ char *rep;
+ /*
+ * loop index
+ */
+ int i;
+
+ if (packet_index == 0)
+ {
+ /*
+ * empty input actions event
+ */
+ return;
+ }
+ else if (packet_index < XTestACTIONS_SIZE)
+ {
+ /*
+ * fill to the end of the input actions event with 0's
+ */
+ for (i = packet_index; i <XTestACTIONS_SIZE; i++)
+ {
+ input_action_packet.actions[i] = 0;
+ }
+ }
+ rep = (char *) (&input_action_packet);
+
+ /*
+ * set the serial number of the input action event
+ */
+ input_action_packet.sequenceNumber = current_xtest_client->sequence;
+ /*
+ * send the input action event to the client
+ */
+ WriteEventsToClient(current_xtest_client, 1, (xEvent *) rep);
+ /*
+ * re-initialize the input action event
+ */
+ input_action_event_full = 0;
+ input_action_packet.type = XTestInputActionType;
+ packet_index = 0;
+}
+
+/******************************************************************************
+ *
+ * XTestStealJumpData
+ *
+ * Create one or more input actions and put them in the input action
+ * event. The input actions will be an (maybe) XTestDELAY_ACTION
+ * and an XTestJUMP_ACTION.
+ */
+void
+XTestStealJumpData(jx, jy, dev_type)
+/*
+ * the x and y coordinates to jump to
+ */
+short jx;
+short jy;
+/*
+ * which device caused the jump
+ */
+int dev_type;
+{
+ XTestJumpInfo *jmp_ptr;
+ /*
+ * time delta (in ms) from previous event
+ */
+ CARD16 tchar;
+
+ /*
+ * Get the time delta from the previous event. If needed,
+ * the check_time_event routine will put an XTestDELAY_ACTION
+ * type action in the input action event.
+ */
+ tchar = check_time_event();
+ if (!there_is_room(sizeof(XTestJumpInfo)))
+ {
+ /*
+ * If there isn't room in the input action event for
+ * an XTestJUMP_ACTION, then send that event to the
+ * client and start filling an empty one.
+ */
+ flush_input_actions();
+ }
+ /*
+ * update the logical mouse position
+ */
+ xtest_mousex = jx;
+ xtest_mousey = jy;
+ /*
+ * point jmp_ptr to the correct place in the input action event
+ */
+ jmp_ptr = (XTestJumpInfo *)
+ &(input_action_packet.actions[packet_index]);
+ /*
+ * compute the input action header
+ */
+ jmp_ptr->header = (XTestPackDeviceID(dev_type) | XTestJUMP_ACTION);
+ /*
+ * set the x and y coordinates to jump to in the input action
+ */
+ jmp_ptr->jumpx = jx;
+ jmp_ptr->jumpy = jy;
+ /*
+ * set the delay time in the input action
+ */
+ jmp_ptr->delay_time = tchar;
+ /*
+ * increment the packet index by the size of the input action
+ */
+ packet_index = packet_index + sizeof(XTestJumpInfo);
+ if (packed_mode == 0)
+ {
+ /*
+ * if input actions are not packed, send the input
+ * action event to the client
+ */
+ flush_input_actions();
+ }
+}
+
+/******************************************************************************
+ *
+ * current_ms
+ *
+ * Returns the number of milliseconds from the passed-in time to the
+ * current time, and then updates the passed-in time to the current time.
+ */
+static CARD32
+current_ms(otime)
+struct timeval *otime;
+{
+ struct timeval tval;
+ unsigned long ctime;
+ unsigned long sec;
+ unsigned long usec;
+
+ /*
+ * get the current time
+ */
+ X_GETTIMEOFDAY(&tval);
+ if (tval.tv_usec < otime->tv_usec)
+ {
+ /*
+ * borrow a second's worth of microseconds if needed
+ */
+ usec = tval.tv_usec - otime->tv_usec + 1000000;
+ sec = tval.tv_sec - 1 - otime->tv_sec;
+ }
+ else
+ {
+ usec = tval.tv_usec - otime->tv_usec;
+ sec = tval.tv_sec - otime->tv_sec;
+ }
+ /*
+ * update the passed-in time to the new time
+ */
+ *otime = tval;
+ /*
+ * compute the number of milliseconds contained in
+ * 'sec' seconds and 'usec' microseconds
+ */
+ ctime = (sec * 1000000 + usec) / 1000;
+ return (ctime);
+}
+
+/******************************************************************************
+ *
+ * check_time_event
+ *
+ * If time delta is > XTestSHORT_DELAY_TIME then insert a time event
+ * and return 0; else return the delay time.
+ */
+static CARD16
+check_time_event()
+{
+ CARD32 tstamp;
+ CARD16 tchar;
+ XTestDelayInfo *tptr;
+
+ /*
+ * get the number of milliseconds between input actions
+ */
+ tstamp = current_ms(&current_time);
+ /*
+ * if the number of milliseconds is too large to fit in a CARD16,
+ * then add a XTestDELAY_ACTION to the input action event.
+ */
+ if (tstamp > XTestSHORT_DELAY_TIME)
+ {
+ /*
+ * If there isn't room in the input action event for
+ * an XTestDELAY_ACTION, then send that event to the
+ * client and start filling an empty one.
+ */
+ if (!there_is_room(sizeof(XTestDelayInfo)))
+ {
+ flush_input_actions();
+ }
+ /*
+ * point tptr to the correct place in the input action event
+ */
+ tptr = (XTestDelayInfo *)
+ (&(input_action_packet.actions[packet_index]));
+ /*
+ * compute the input action header
+ */
+ tptr->header = XTestPackDeviceID(XTestDELAY_DEVICE_ID) |
+ XTestDELAY_ACTION;
+ /*
+ * set the delay time in the input action
+ */
+ tptr->delay_time = tstamp;
+ /*
+ * increment the packet index by the size of the input action
+ */
+ packet_index = packet_index + (sizeof(XTestDelayInfo));
+ if (packed_mode != XTestPACKED_ACTIONS)
+ {
+ /*
+ * if input actions are not packed, send the input
+ * action event to the client
+ */
+ flush_input_actions();
+ }
+ /*
+ * set the returned delay time to 0
+ */
+ tchar = 0;
+ }
+ else
+ {
+ /*
+ * set the returned delay time to the computed delay time
+ */
+ tchar = tstamp;
+ }
+ return(tchar);
+}
+
+/******************************************************************************
+ *
+ * there_is_room
+ *
+ * Checks if there is room in the input_action_packet for an input action
+ * of the size actsize bytes. Returns 1 if there is space, 0 otherwise.
+ *
+ */
+static int
+there_is_room(actsize)
+/*
+ * the number of bytes of space needed
+ */
+int actsize;
+{
+ if ((packet_index + actsize) > XTestACTIONS_SIZE)
+ {
+ input_action_event_full = 1;
+ return(0);
+ }
+ else
+ {
+ return(1);
+ }
+}
+
+/******************************************************************************
+ *
+ * XTestStealMotionData
+ *
+ * Put motion information from the locator into an input action.
+ *
+ * called from x_hil.c
+ */
+void
+XTestStealMotionData(dx, dy, dev_type, mx, my)
+/*
+ * the x and y delta motion of the locator
+ */
+short dx;
+short dy;
+/*
+ * which locator did the moving
+ */
+int dev_type;
+/*
+ * the x and y position of the locator before the delta motion
+ */
+short mx;
+short my;
+{
+ /*
+ * pointer to a XTestMOTION_ACTION input action
+ */
+ XTestMotionInfo *fm;
+ /*
+ * time delta from previous event
+ */
+ CARD16 tchar;
+
+ /*
+ * if the current position of the locator is not the same as
+ * the logical position, then update the logical position
+ */
+ if ((mx != xtest_mousex) || (my != xtest_mousey))
+ {
+ XTestStealJumpData(mx, my, dev_type);
+ }
+ /*
+ * if the delta motion is outside the range that can
+ * be held in a motion input action, use a jump input action
+ */
+ if ((dx > XTestMOTION_MAX) || (dx < XTestMOTION_MIN) ||
+ (dy > XTestMOTION_MAX) || (dy < XTestMOTION_MIN))
+ {
+ XTestStealJumpData((xtest_mousex + dx),
+ (xtest_mousey + dy), dev_type);
+ }
+ else
+ {
+ /*
+ * compute the new logical position of the mouse
+ */
+ xtest_mousex += dx;
+ xtest_mousey += dy;
+ /*
+ * Get the time delta from the previous event. If needed,
+ * the check_time_event routine will put an XTestDELAY_ACTION
+ * type action in the input action event.
+ */
+ tchar = check_time_event();
+ /*
+ * If there isn't room in the input action event for
+ * an XTestDELAY_ACTION, then send that event to the
+ * client and start filling an empty one.
+ */
+ if (!there_is_room(sizeof(XTestMotionInfo)))
+ {
+ flush_input_actions();
+ /*
+ * point fm to the correct place in the input action event
+ */
+ }
+ fm = (XTestMotionInfo *)
+ &(input_action_packet.actions[packet_index]);
+ /*
+ * compute the input action header
+ */
+ fm->header = XTestMOTION_ACTION;
+ if (dx < 0)
+ {
+ fm->header |= XTestX_NEGATIVE;
+ dx = abs(dx);
+ }
+ if (dy < 0)
+ {
+ fm->header |= XTestY_NEGATIVE;
+ dy = abs(dy);
+ }
+ fm->header |= XTestPackDeviceID(dev_type);
+ /*
+ * compute the motion data byte
+ */
+ fm->motion_data = XTestPackYMotionValue(dy);
+ fm->motion_data |= XTestPackXMotionValue(dx);
+ /*
+ * set the delay time in the input action
+ */
+ fm->delay_time = tchar;
+ /*
+ * increment the packet index by the size of the input action
+ */
+ packet_index = packet_index + sizeof(XTestMotionInfo);
+ if (packed_mode == 0)
+ {
+ /*
+ * if input actions are not packed, send the input
+ * action event to the client
+ */
+ flush_input_actions();
+ }
+
+ }
+}
+
+/******************************************************************************
+ *
+ * XTestStealKeyData
+ *
+ * Place this key data in the input_action_packet.
+ *
+ */
+Bool
+XTestStealKeyData(keycode, keystate, dev_type, locx, locy)
+/*
+ * which key/button moved
+ */
+CARD8 keycode;
+/*
+ * whether the key/button was pressed or released
+ */
+char keystate;
+/*
+ * which device caused the input action
+ */
+int dev_type;
+/*
+ * the x and y coordinates of the locator when the action happenned
+ */
+short locx;
+short locy;
+{
+ /*
+ * pointer to key/button motion input action
+ */
+ XTestKeyInfo *kp;
+ /*
+ * time delta from previous event
+ */
+ CARD16 tchar;
+ char keytrans;
+
+ /*
+ * update the logical position of the locator if the physical position
+ * of the locator is not the same as the logical position.
+ */
+ if ((locx != xtest_mousex) || (locy != xtest_mousey))
+ {
+ XTestStealJumpData(locx, locy, dev_type);
+ }
+ /*
+ * Get the time delta from the previous event. If needed,
+ * the check_time_event routine will put an XTestDELAY_ACTION
+ * type action in the input action event.
+ */
+ tchar = check_time_event();
+ if (!there_is_room(sizeof(XTestKeyInfo)))
+ {
+ /*
+ * If there isn't room in the input action event for
+ * an XTestDELAY_ACTION, then send that event to the
+ * client and start filling an empty one.
+ */
+ flush_input_actions();
+ }
+ /*
+ * point kp to the correct place in the input action event
+ */
+ kp = (XTestKeyInfo *)
+ (&(input_action_packet.actions[packet_index]));
+ /*
+ * compute the input action header
+ */
+ kp->header = XTestPackDeviceID(dev_type);
+ if ((keystate == KeyRelease) || (keystate == ButtonRelease))
+ {
+ keytrans = XTestKEY_UP;
+ }
+ else if ((keystate == KeyPress) || (keystate == ButtonPress))
+ {
+ keytrans = XTestKEY_DOWN;
+ }
+ else
+ {
+ printf("%s: invalid key/button state %d.\n",
+ XTestEXTENSION_NAME,
+ keystate);
+ }
+ kp->header = kp->header | keytrans | XTestKEY_ACTION;
+ /*
+ * set the keycode in the input action
+ */
+ kp->keycode = keycode;
+ /*
+ * set the delay time in the input action
+ */
+ kp->delay_time = tchar;
+ /*
+ * increment the packet index by the size of the input action
+ */
+ packet_index = packet_index + sizeof(XTestKeyInfo);
+ /*
+ * if the command key has been released or input actions are not
+ * packed, send the input action event to the client
+ */
+ if(((keycode == xtest_command_key) && (keystate == KeyRelease)) ||
+ (packed_mode != XTestPACKED_ACTIONS))
+ {
+ flush_input_actions();
+ }
+ /* return TRUE if the event should be passed on to DIX */
+ if (exclusive_steal)
+ return ((keystate == KeyRelease) &&
+ (keycode == xtest_command_key));
+ else
+ return ((keystate != KeyRelease) ||
+ (keycode != xtest_command_key));
+}
+
+/******************************************************************************
+ *
+ * parse_fake_input
+ *
+ * Parsing routine for a XTestFakeInput request. It will take a request
+ * and parse its contents into the input action array. Eventually the
+ * XTestProcessInputAction routine will be called to take input actions
+ * from the input action array and send them to the server to be handled.
+ */
+void
+parse_fake_input(client, req)
+/*
+ * which client did the XTestFakeInput request
+ */
+ClientPtr client;
+/*
+ * a pointer to the xTestFakeInputReq structure sent by the client
+ */
+char *req;
+{
+ /*
+ * if set to 1, done processing input actions from the request
+ */
+ int done = 0;
+ /*
+ * type of input action
+ */
+ CARD8 action_type;
+ /*
+ * device type
+ */
+ CARD8 dev_type;
+ /*
+ * pointer to an xTestFakeInputReq structure
+ */
+ xTestFakeInputReq *request;
+ /*
+ * holds the index into the action list in the request
+ */
+ int parse_index;
+
+ /*
+ * get a correct-type pointer to the client-supplied request data
+ */
+ request = (xTestFakeInputReq *) req;
+ /*
+ * save the acknowledge requested state for use in
+ * XTestProcessInputAction
+ */
+ acknowledge = request->ack;
+ /*
+ * set up an index into the action list in the request
+ */
+ parse_index = 0;
+ if (write_index >= ACTION_ARRAY_SIZE)
+ {
+ /*
+ * if the input action array is full, don't add any more
+ */
+ done = 1;
+ }
+ while (!done)
+ {
+ /*
+ * get the type of input action in the list
+ */
+ action_type = (request->action_list[parse_index])
+ & XTestACTION_TYPE_MASK;
+ /*
+ * get the type of device in the list
+ */
+ dev_type = XTestUnpackDeviceID(request->action_list[parse_index]);
+ /*
+ * process the input action appropriately
+ */
+ switch (action_type)
+ {
+ case XTestKEY_ACTION:
+ parse_key_fake((XTestKeyInfo *)
+ &(request->action_list[parse_index]));
+ parse_index = parse_index + sizeof(XTestKeyInfo);
+ break;
+ case XTestMOTION_ACTION:
+ parse_motion_fake((XTestMotionInfo *)
+ &(request->action_list[parse_index]));
+ parse_index = parse_index + sizeof(XTestMotionInfo);
+ break;
+ case XTestJUMP_ACTION:
+ parse_jump_fake((XTestJumpInfo *)
+ &(request->action_list[parse_index]));
+ parse_index = parse_index + sizeof(XTestJumpInfo);
+ break;
+ case XTestDELAY_ACTION:
+ if (dev_type == XTestDELAY_DEVICE_ID)
+ {
+ parse_delay_fake((XTestDelayInfo *)
+ &(request->action_list[parse_index]));
+ parse_index = parse_index +
+ sizeof(XTestDelayInfo);
+ }
+ else
+ {
+ /*
+ * An invalid input action header byte has
+ * been detected, so there are no more
+ * input actions in this request.
+ * The intended invalid action header byte
+ * for this case should have a value of 0.
+ */
+ done = 1;
+ }
+ break;
+ }
+ if (parse_index >= XTestMAX_ACTION_LIST_SIZE)
+ {
+ /*
+ * entire XTestFakeInput request has been processed
+ */
+ done = 1;
+ }
+ if (write_index >= ACTION_ARRAY_SIZE)
+ {
+ /*
+ * no room in the input actions array
+ */
+ done = 1;
+ }
+ }
+ if (write_index > read_index)
+ {
+ /*
+ * there are fake input actions in the input action array
+ * to be given to the server
+ */
+ playback_on = 1;
+ playback_client = client;
+ }
+}
+
+/******************************************************************************
+ *
+ * parse_key_fake
+ *
+ * Called from parse_fake_input.
+ *
+ * Copy the fake key input action from its packed form into the array of
+ * pending input events.
+ */
+static void
+parse_key_fake(fkey)
+XTestKeyInfo *fkey;
+{
+ action_array[write_index].type = XTestKEY_ACTION;
+ action_array[write_index].device = XTestUnpackDeviceID(fkey->header);
+ action_array[write_index].keycode = fkey->keycode;
+ action_array[write_index].keystate = fkey->header & XTestKEY_STATE_MASK;
+ action_array[write_index].delay_time = fkey->delay_time;
+ write_index++;
+}
+
+/******************************************************************************
+ *
+ * parse_motion_fake
+ *
+ * Called from parse_fake_input.
+ *
+ * Copy the fake motion input action from its packed form into the array of
+ * pending input events.
+ */
+static void
+parse_motion_fake(fmotion)
+XTestMotionInfo *fmotion;
+{
+ int dx;
+ int dy;
+
+ dx = (XTestUnpackXMotionValue(fmotion->motion_data));
+ dy = (XTestUnpackYMotionValue(fmotion->motion_data));
+ if (((fmotion->header) & XTestX_SIGN_BIT_MASK) == XTestX_NEGATIVE)
+ {
+ pmousex -= dx;
+ }
+ else
+ {
+ pmousex += dx;
+ }
+ if (((fmotion->header) & XTestY_SIGN_BIT_MASK) == XTestY_NEGATIVE)
+ {
+ pmousey -= dy;
+ }
+ else
+ {
+ pmousey += dy;
+ }
+ action_array[write_index].type = XTestJUMP_ACTION;
+ action_array[write_index].device = XTestUnpackDeviceID(fmotion->header);
+ action_array[write_index].x = pmousex;
+ action_array[write_index].y = pmousey;
+ action_array[write_index].delay_time = fmotion->delay_time;
+ write_index++;
+}
+
+/******************************************************************************
+ *
+ * parse_jump_fake
+ *
+ * Called from parse_fake_input.
+ *
+ * Copy the fake jump input action from its packed form into the array of
+ * pending input events.
+ */
+static void
+parse_jump_fake(fjump)
+XTestJumpInfo *fjump;
+{
+ pmousex = fjump->jumpx;
+ pmousey = fjump->jumpy;
+ action_array[write_index].type = XTestJUMP_ACTION;
+ action_array[write_index].device = XTestUnpackDeviceID(fjump->header);
+ action_array[write_index].x = pmousex;
+ action_array[write_index].y = pmousey;
+ action_array[write_index].delay_time = fjump->delay_time;
+ write_index++;
+}
+
+/******************************************************************************
+ *
+ * parse_delay_fake
+ *
+ * Called from parse_fake_input.
+ *
+ * Copy the fake delay input action from its packed form into the array of
+ * pending input events.
+ */
+static void
+parse_delay_fake(tevent)
+XTestDelayInfo *tevent;
+{
+ action_array[write_index].type = XTestDELAY_ACTION;
+ action_array[write_index].delay_time = tevent->delay_time;
+ write_index++;
+}
+
+/******************************************************************************
+ *
+ * XTestComputeWaitTime
+ *
+ * Compute the amount of time the server should wait before sending the
+ * next monitor event in playback mode.
+ */
+void
+XTestComputeWaitTime(waittime)
+struct timeval *waittime;
+{
+ /*
+ * The playback_on flag is set to 1 in parse_fake_input. It is set to
+ * 0 in XTestProcessInputAction if the server has replayed all input
+ * actions.
+ */
+ if (playback_on)
+ {
+ if (!play_clock)
+ {
+ /*
+ * if the playback clock has never been set,
+ * then do it now
+ */
+ start_play_clock();
+ }
+ /*
+ * We need to save the waittime the first time through. This
+ * is a value the server uses, and we have to restore it when
+ * all of the input actions are processed by the server.
+ */
+ if (!time_saved)
+ {
+ saved_sec = waittime->tv_sec;
+ saved_usec = waittime->tv_usec;
+ time_saved = 1;
+ }
+ if (go_for_next)
+ {
+ /*
+ * if we just processed an input action, figure out
+ * how long to wait for the next input action
+ */
+ compute_action_time(&rtime);
+ }
+ else
+ {
+ /*
+ * else just find out how much more time to wait
+ * on the current input action
+ */
+ (void)find_residual_time(&rtime);
+ }
+ waittime->tv_sec = rtime.tv_sec;
+ waittime->tv_usec = rtime.tv_usec;
+ }
+}
+
+/******************************************************************************
+ *
+ * XTestProcessInputAction
+ *
+ * If there are any input actions in the input action array,
+ * then take one out and process it.
+ *
+ */
+int
+XTestProcessInputAction(readable, waittime)
+/*
+ * This is the value that a 'select' function returned just before this
+ * routine was called. If the select timed out, this value will be 0.
+ *
+ * This extension modifies the select call's timeout value to cause the
+ * select to time out when the next input action is ready to given to
+ * the server. This routine is called immediately after the select, to
+ * give it a chance to process an input action. If we have an input action
+ * to process and the only reason that the select returned was because it
+ * timed out, then we change the select value to 1 and return 1 instead of 0.
+ */
+int readable;
+/*
+ * this is the timeout value that the select was called with
+ */
+struct timeval *waittime;
+{
+int mousex, mousey;
+ /*
+ * if playback_on is 0, then the input action array is empty
+ */
+ if (playback_on)
+ {
+ restorewait = waittime;
+ /*
+ * figure out if we need to wait for the next input action
+ */
+ if (find_residual_time(&rtime) > 0)
+ {
+ /*
+ * still have to wait before processing the current
+ * input action
+ */
+ go_for_next = 0;
+ }
+ else
+ {
+ /*
+ * don't have to wait any longer before processing
+ * the current input action
+ */
+ go_for_next = 1;
+ }
+ /*
+ * if we have an input action to process and the only reason
+ * that the select returned was because it timed out, then we
+ * change the select value to 1 and return 1 instead of 0
+ */
+ if (readable == 0)
+ {
+ readable++;
+ }
+ /*
+ * if we don't need to wait, then get an input action from
+ * the input action array and process it
+ */
+ if (go_for_next)
+ {
+ /*
+ * There are three possible types of input actions in
+ * the input action array (motion input actions are
+ * converted to jump input actions before being put
+ * into the input action array). Delay input actions
+ * are processed by the compute_action_time function
+ * which is called from XTestComputeWaitTime. The
+ * other two types of input actions are processed here.
+ */
+ if (action_array[read_index].type == XTestJUMP_ACTION)
+ {
+ XTestJumpPointer(
+ action_array[read_index].x,
+ action_array[read_index].y,
+ action_array[read_index].device);
+ mx = action_array[read_index].x;
+ my = action_array[read_index].y;
+ }
+ if (action_array[read_index].type == XTestKEY_ACTION)
+ {
+ GetSpritePosition(&mousex, &mousey);
+ XTestGenerateEvent(
+ action_array[read_index].device,
+ action_array[read_index].keycode,
+ action_array[read_index].keystate,
+ mousex,
+ mousey);
+ }
+ read_index++;
+ /*
+ * if all input actions are processed, then restore
+ * the server state
+ */
+ if (read_index >= write_index)
+ {
+ waittime->tv_sec = saved_sec;
+ waittime->tv_usec = saved_usec;
+ time_saved = 0;
+ playback_on = 0;
+ if (acknowledge)
+ {
+ /*
+ * if the playback client is waiting
+ * for an xTestFakeAck event, send
+ * it to him
+ */
+ send_ack(playback_client);
+ acknowledge = 0;
+ }
+ write_index = 0;
+ read_index = 0;
+ playback_client = (ClientPtr) NULL;
+ play_clock = 0;
+ }
+ }
+ }
+ return(readable);
+}
+
+/******************************************************************************
+ *
+ * send_ack
+ *
+ * send an xTestFakeAck event to the client
+ */
+static void
+send_ack(client)
+ClientPtr client;
+{
+ xTestFakeAckEvent rep;
+
+ /*
+ * set the serial number of the xTestFakeAck event
+ */
+ rep.sequenceNumber = client->sequence;
+ rep.type = XTestFakeAckType;
+ WriteEventsToClient(client, 1, (xEvent *) &rep);
+}
+
+/******************************************************************************
+ *
+ * start_play_clock
+ *
+ * start the clock for play back.
+ */
+static void
+start_play_clock()
+{
+ X_GETTIMEOFDAY(&play_time);
+ /*
+ * flag that play_time is valid
+ */
+ play_clock = 1;
+}
+
+/******************************************************************************
+ *
+ * compute_action_time
+ *
+ * Set the play clock to the time when the next input action should be put
+ * into the server's input queue. Fill the rtime structure with values
+ * for the delta until the time for the next input action.
+ */
+static void
+compute_action_time(rtime)
+struct timeval *rtime;
+{
+ /*
+ * holds the delay time in milliseconds
+ */
+ unsigned long dtime;
+ /*
+ * holds the number of microseconds in the sum of the dtime value
+ * and the play_time value
+ */
+ unsigned long tot_usec;
+ /*
+ * holds the number of seconds and microseconds in the
+ * dtime value
+ */
+ unsigned long sec;
+ unsigned long usec;
+ /*
+ * holds the current time
+ */
+ struct timeval btime;
+
+ /*
+ * Put the time from the current input action in dtime
+ */
+ dtime = action_array[read_index].delay_time;
+ /*
+ * If the current input action is a delay input action,
+ * add in the time from the following input action.
+ */
+ if ((action_array[read_index].type == XTestDELAY_ACTION) &&
+ ((read_index + 1) < write_index))
+ {
+ read_index++;
+ dtime = dtime + action_array[read_index].delay_time;
+ }
+ /*
+ * compute the number of seconds and microseconds in the
+ * dtime value
+ */
+ sec = dtime / 1000;
+ usec = (dtime % 1000) * 1000;
+ /*
+ * get the current time in btime
+ */
+ X_GETTIMEOFDAY(&btime);
+ /*
+ * compute the number of microseconds in the sum of the dtime value
+ * and the current usec value
+ */
+ tot_usec = btime.tv_usec + usec;
+ /*
+ * if it is greater than one second's worth, adjust the seconds
+ */
+ if (tot_usec >= 1000000)
+ {
+ tot_usec -= 1000000;
+ sec++;
+ }
+ play_time.tv_usec = tot_usec;
+ play_time.tv_sec = btime.tv_sec + sec;
+ /*
+ * put the time until the next input action in rtime
+ */
+ rtime->tv_sec = sec;
+ rtime->tv_usec = usec;
+}
+
+/******************************************************************************
+ *
+ * find_residual_time
+ *
+ * Find the time interval from the current time to the value in play_time.
+ * This is the time to wait till putting the next input action into the
+ * server's input queue. If the time is already up, reset play_time to
+ * the current time.
+ */
+static int
+find_residual_time(rtime)
+struct timeval *rtime;
+{
+ /*
+ * if > 0, there is time to wait. If < 0, then don't wait
+ */
+ int wait = 1;
+ /*
+ * holds the current time
+ */
+ struct timeval btime;
+ /*
+ * holds the current time in seconds and microseconds
+ */
+ unsigned long bsec;
+ unsigned long busec;
+ /*
+ * holds the playback time in seconds and microseconds
+ */
+ unsigned long psec;
+ unsigned long pusec;
+
+ /*
+ * get the current time in btime
+ */
+ X_GETTIMEOFDAY(&btime);
+ /*
+ * get the current time in seconds and microseconds
+ */
+ bsec = btime.tv_sec;
+ busec = btime.tv_usec;
+ /*
+ * get the playback time in seconds and microseconds
+ */
+ psec = play_time.tv_sec;
+ pusec = play_time.tv_usec;
+ /*
+ * if the current time is already later than the playback time,
+ * we don't need to wait
+ */
+ if (bsec > psec)
+ {
+ wait = -1;
+ }
+ else
+ {
+ if (bsec == psec)
+ {
+ /*
+ * if the current and playback times have the same
+ * second value, then compare the microsecond values
+ */
+ if ( busec >= pusec)
+ {
+ /*
+ * if the current time is already later than
+ * the playback time, we don't need to wait
+ */
+ wait = -1;
+ }
+ else
+ {
+ rtime->tv_usec = pusec - busec;
+ rtime->tv_sec = 0;
+ }
+ }
+ else
+ {
+ if (busec > pusec)
+ {
+ /*
+ * 'borrow' a second's worth of microseconds
+ * from the seconds left to wait
+ */
+ rtime->tv_usec = 1000000 - busec + pusec;
+ psec--;
+ rtime->tv_sec = psec - bsec;
+ }
+ else
+ {
+ rtime->tv_sec = psec - bsec;
+ rtime->tv_usec = pusec - busec;
+ }
+ }
+ }
+ if (wait < 0)
+ {
+ /*
+ * if don't need to wait, set the playback time
+ * to the current time
+ */
+ X_GETTIMEOFDAY(&play_time);
+ /*
+ * set the time to wait to 0
+ */
+ rtime->tv_sec = 0;
+ rtime->tv_usec = 0;
+ }
+ return(wait);
+}
+
+/******************************************************************************
+ *
+ * abort_play_back
+ */
+void
+abort_play_back()
+{
+ /*
+ * If we were playing back input actions at the time of the abort,
+ * restore the original wait time for the select in the main wait
+ * loop of the server
+ */
+ if (playback_on)
+ {
+ restorewait->tv_sec = saved_sec;
+ restorewait->tv_usec = saved_usec;
+ }
+ /*
+ * make the input action array empty
+ */
+ read_index = 0;
+ write_index = 0;
+ /*
+ * we are no longer playing back anything
+ */
+ playback_on = 0;
+ play_clock = 0;
+ go_for_next = 1;
+ /*
+ * there is no valid wait time saved any more
+ */
+ time_saved = 0;
+ /*
+ * there are no valid clients using this extension
+ */
+ playback_client = (ClientPtr) NULL;
+ current_xtest_client = (ClientPtr) NULL;
+}
+
+/******************************************************************************
+ *
+ * return_input_array_size
+ *
+ * Return the number of input actions in the input action array.
+ */
+void
+return_input_array_size(client)
+/*
+ * which client to send the reply to
+ */
+ClientPtr client;
+{
+ xTestQueryInputSizeReply rep;
+
+ rep.type = X_Reply;
+ /*
+ * set the serial number of the reply
+ */
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.size_return = ACTION_ARRAY_SIZE;
+ WriteReplyToClient(client,
+ sizeof(xTestQueryInputSizeReply),
+ (pointer) &rep);
+}
diff --git a/Xext/xtest1di.c b/Xext/xtest1di.c
new file mode 100644
index 000000000..cd8f5e727
--- /dev/null
+++ b/Xext/xtest1di.c
@@ -0,0 +1,966 @@
+/* $Xorg: xtest1di.c,v 1.4 2001/02/09 02:04:33 xorgcvs Exp $ */
+/*
+ * File: xtest1di.c
+ *
+ * This file contains the device independent parts of the input
+ * synthesis extension.
+ */
+
+/*
+
+
+Copyright 1986, 1987, 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.
+
+
+Copyright 1986, 1987, 1988 by Hewlett-Packard Corporation
+
+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 makes no representations about the
+suitability of this software for any purpose. It is provided
+"as is" without express or implied warranty.
+
+This software is not subject to any license of the American
+Telephone and Telegraph Company or of the Regents of the
+University of California.
+
+*/
+
+/*****************************************************************************
+ * include files
+ ****************************************************************************/
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+
+#include <stdio.h>
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "gcstruct.h"
+#include "extnsionst.h"
+#include "dixstruct.h"
+#include "opaque.h"
+#define XTestSERVER_SIDE
+#include "xtestext1.h"
+
+/*****************************************************************************
+ * defines
+ ****************************************************************************/
+
+/*****************************************************************************
+ * externals
+ ****************************************************************************/
+
+/*
+ * holds the addresses of the routines that handle byte-swapping of replys
+ */
+extern void (* ReplySwapVector[256]) ();
+/*
+ * id of client using XTestGetInput
+ *
+ * defined in xtest1dd.c
+ */
+extern ClientPtr current_xtest_client;
+/*
+ * id of client using XTestFakeInput
+ *
+ * defined in xtest1dd.c
+ */
+extern ClientPtr playback_client;
+
+/*****************************************************************************
+ * variables
+ ****************************************************************************/
+
+/*
+ * Holds the request type code for this extension. The request type code
+ * for this extension may vary depending on how many extensions are installed
+ * already, so the initial value given below will be added to the base request
+ * code that is aquired when this extension is installed.
+ */
+static int XTestReqCode = 0;
+/*
+ * Holds the two event type codes for this extension. The event type codes
+ * for this extension may vary depending on how many extensions are installed
+ * already, so the initial values given below will be added to the base event
+ * code that is aquired when this extension is installed.
+ */
+int XTestInputActionType = 0;
+int XTestFakeAckType = 1;
+/*
+ * true => monitor stealing input
+ */
+int on_steal_input = FALSE;
+/*
+ * true => monitor alone getting input
+ */
+int exclusive_steal = FALSE;
+/*
+ * holds the resource type assigned to this extension
+ */
+static RESTYPE XTestType;
+/*
+ * holds the resource ID for the client currently using XTestGetInput
+ */
+static XID current_client_id;
+
+/*****************************************************************************
+ * function declarations
+ ****************************************************************************/
+
+static int ProcXTestDispatch();
+static int SProcXTestDispatch();
+static void XTestResetProc();
+static int ProcTestFakeInput();
+static int SProcTestFakeInput();
+static int ProcTestGetInput();
+static int SProcTestGetInput();
+static int ProcTestStopInput();
+static int SProcTestStopInput();
+static int ProcTestReset();
+static int SProcTestReset();
+static int ProcTestQueryInputSize();
+static int SProcTestQueryInputSize();
+static void SReplyXTestDispatch();
+static void SEventXTestDispatch();
+void NotImplemented();
+
+void abort_play_back();
+void return_input_array_size();
+void steal_input();
+void stop_stealing_input();
+void flush_input_actions();
+void parse_fake_input();
+
+static int XTestCurrentClientGone();
+
+/*****************************************************************************
+ *
+ * XTestExtension1Init
+ *
+ * Called from InitExtensions in main() or from QueryExtension() if the
+ * extension is dynamically loaded.
+ *
+ * XTestExtension1Init has no events or errors
+ * (other than the core errors).
+ */
+void
+XTestExtension1Init()
+{
+ /*
+ * holds the pointer to the extension entry structure
+ */
+ ExtensionEntry *extEntry;
+ /*
+ * This routine adds the extension to the server extension table.
+ */
+ ExtensionEntry *AddExtension();
+
+ extEntry = AddExtension(XTestEXTENSION_NAME,
+ XTestEVENT_COUNT,
+ 0,
+ ProcXTestDispatch,
+ SProcXTestDispatch,
+ XTestResetProc,
+ StandardMinorOpcode);
+ if (extEntry)
+ {
+ /*
+ * remember the request code assigned to this extension
+ */
+ XTestReqCode = extEntry->base;
+ /*
+ * make an atom saying that this extension is present
+ */
+ (void) MakeAtom(XTestEXTENSION_NAME,
+ strlen(XTestEXTENSION_NAME),
+ TRUE);
+ /*
+ * remember the event codes assigned to this extension
+ */
+ XTestInputActionType += extEntry->eventBase;
+ XTestFakeAckType += extEntry->eventBase;
+ /*
+ * install the routine to handle byte-swapping the replies
+ * for this extension in the ReplySwapVector table
+ */
+ ReplySwapVector[XTestReqCode] = SReplyXTestDispatch;
+ /*
+ * install the routine to handle byte-swapping the events
+ * for this extension in the EventSwapVector table
+ */
+ EventSwapVector[XTestInputActionType] = SEventXTestDispatch;
+ EventSwapVector[XTestFakeAckType] = SEventXTestDispatch;
+ /*
+ * get the resource type for this extension
+ */
+ XTestType = CreateNewResourceType(XTestCurrentClientGone);
+ if (XTestType == 0)
+ {
+ FatalError("XTestExtension1Init: CreateNewResourceType failed\n");
+ }
+ }
+ else
+ {
+ FatalError("XTestExtension1Init: AddExtensions failed\n");
+ }
+}
+
+/*****************************************************************************
+ *
+ * ProcXTestDispatch
+ *
+ *
+ */
+static int
+ProcXTestDispatch(client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ if (stuff->data == X_TestFakeInput)
+ {
+ return(ProcTestFakeInput(client));
+ }
+ else if (stuff->data == X_TestGetInput)
+ {
+ return(ProcTestGetInput(client));
+ }
+ else if (stuff->data == X_TestStopInput)
+ {
+ return(ProcTestStopInput(client));
+ }
+ else if (stuff->data == X_TestReset)
+ {
+ return(ProcTestReset(client));
+ }
+ else if (stuff->data == X_TestQueryInputSize)
+ {
+ return(ProcTestQueryInputSize(client));
+ }
+ else
+ {
+ SendErrorToClient(client,
+ XTestReqCode,
+ stuff->data,
+ None,
+ BadRequest);
+ return(BadRequest);
+ }
+}
+
+/*****************************************************************************
+ *
+ * SProcXTestDispatch
+ *
+ *
+ */
+static int
+SProcXTestDispatch(client)
+ register ClientPtr client;
+{
+ REQUEST(xReq);
+ if (stuff->data == X_TestFakeInput)
+ {
+ return(SProcTestFakeInput(client));
+ }
+ else if (stuff->data == X_TestGetInput)
+ {
+ return(SProcTestGetInput(client));
+ }
+ else if (stuff->data == X_TestStopInput)
+ {
+ return(SProcTestStopInput(client));
+ }
+ else if (stuff->data == X_TestReset)
+ {
+ return(SProcTestReset(client));
+ }
+ else if (stuff->data == X_TestQueryInputSize)
+ {
+ return(SProcTestQueryInputSize(client));
+ }
+ else
+ {
+ SendErrorToClient(client,
+ XTestReqCode,
+ stuff->data,
+ None,
+ BadRequest);
+ return(BadRequest);
+ }
+}
+
+/*****************************************************************************
+ *
+ * SProcTestFakeInput
+ *
+ *
+ */
+static int
+SProcTestFakeInput(client)
+ register ClientPtr client;
+{
+ /*
+ * used in the swaps and swapl macros for temporary storage space
+ */
+ register char n;
+ /*
+ * index counter
+ */
+ int i;
+ /*
+ * pointer to the next input action in the request
+ */
+ CARD8 *input_action_ptr;
+ /*
+ * holds the type of the next input action in the request
+ */
+ int input_action_type;
+
+ REQUEST(xTestFakeInputReq);
+ /*
+ * byte-swap the fields in the request
+ */
+ swaps(&stuff->length, n);
+ swapl(&stuff->ack, n);
+ /*
+ * have to parse and then byte-swap the input action list here
+ */
+ for (i = 0; i < XTestMAX_ACTION_LIST_SIZE;)
+ {
+ /*
+ * point to the next input action in the request
+ */
+ input_action_ptr = &(((xTestFakeInputReq *) stuff)->action_list[i]);
+ /*
+ * figure out what type of input action it is
+ */
+ input_action_type = (*input_action_ptr) & XTestACTION_TYPE_MASK;
+ /*
+ * byte-swap the input action according to it's type
+ */
+ switch (input_action_type)
+ {
+ case XTestKEY_ACTION:
+ /*
+ * byte-swap the delay_time field
+ */
+ swaps(&(((XTestKeyInfo *) input_action_ptr)->delay_time), n);
+ /*
+ * advance to the next input action
+ */
+ i += sizeof(XTestKeyInfo);
+ break;
+ case XTestMOTION_ACTION:
+ /*
+ * byte-swap the delay_time field
+ */
+ swaps(&(((XTestMotionInfo *) input_action_ptr)->delay_time), n);
+ /*
+ * advance to the next input action
+ */
+ i += sizeof(XTestMotionInfo);
+ break;
+ case XTestJUMP_ACTION:
+ /*
+ * byte-swap the jumpx field
+ */
+ swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpx), n);
+ /*
+ * byte-swap the jumpy field
+ */
+ swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpy), n);
+ /*
+ * byte-swap the delay_time field
+ */
+ swaps(&(((XTestJumpInfo *) input_action_ptr)->delay_time), n);
+ /*
+ * advance to the next input action
+ */
+ i += sizeof(XTestJumpInfo);
+ break;
+ default:
+ /*
+ * if this is a delay input action, then byte-swap it,
+ * otherwise we have reached the end of the input
+ * actions in this request
+ */
+ if (XTestUnpackDeviceID(*input_action_ptr) ==
+ XTestDELAY_DEVICE_ID)
+ {
+ /*
+ * byte-swap the delay_time field
+ */
+ swapl(&(((XTestDelayInfo *) input_action_ptr)->delay_time), n);
+ /*
+ * advance to the next input action
+ */
+ i += sizeof(XTestDelayInfo);
+ }
+ else
+ {
+ /*
+ * if the input action header byte is 0 or
+ * ill-formed, then there are no more input
+ * actions in this request
+ */
+ i = XTestMAX_ACTION_LIST_SIZE;
+ }
+ break;
+ }
+ }
+ return(ProcTestFakeInput(client));
+}
+
+/*****************************************************************************
+ *
+ * SProcTestGetInput
+ *
+ *
+ */
+static int
+SProcTestGetInput(client)
+ register ClientPtr client;
+{
+ /*
+ * used in the swaps and swapl macros for temporary storage space
+ */
+ register char n;
+
+ REQUEST(xTestGetInputReq);
+ /*
+ * byte-swap the fields in the request
+ */
+ swaps(&stuff->length, n);
+ swapl(&stuff->mode, n);
+ return(ProcTestGetInput(client));
+}
+
+/*****************************************************************************
+ *
+ * SProcTestStopInput
+ *
+ *
+ */
+static int
+SProcTestStopInput(client)
+ register ClientPtr client;
+{
+ /*
+ * used in the swaps and swapl macros for temporary storage space
+ */
+ register char n;
+
+ REQUEST(xTestStopInputReq);
+ /*
+ * byte-swap the length field in the request
+ */
+ swaps(&stuff->length, n);
+ return(ProcTestStopInput(client));
+}
+
+/*****************************************************************************
+ *
+ * SProcTestReset
+ *
+ *
+ */
+static int
+SProcTestReset(client)
+ register ClientPtr client;
+{
+ /*
+ * used in the swaps and swapl macros for temporary storage space
+ */
+ register char n;
+
+ REQUEST(xTestResetReq);
+ /*
+ * byte-swap the length field in the request
+ */
+ swaps(&stuff->length, n);
+ return(ProcTestReset(client));
+}
+
+/*****************************************************************************
+ *
+ * SProcTestQueryInputSize
+ *
+ *
+ */
+static int
+SProcTestQueryInputSize(client)
+ register ClientPtr client;
+{
+ /*
+ * used in the swaps and swapl macros for temporary storage space
+ */
+ register char n;
+
+ REQUEST(xTestQueryInputSizeReq);
+ /*
+ * byte-swap the length field in the request
+ */
+ swaps(&stuff->length, n);
+ return(ProcTestQueryInputSize(client));
+}
+
+/*****************************************************************************
+ *
+ * ProcTestFakeInput
+ *
+ *
+ */
+static int
+ProcTestFakeInput(client)
+ register ClientPtr client;
+{
+ REQUEST(xTestFakeInputReq);
+ REQUEST_SIZE_MATCH(xTestFakeInputReq);
+
+ if (playback_client == NULL)
+ {
+ playback_client = client;
+ current_client_id = FakeClientID(client->index);
+ AddResource(current_client_id,
+ XTestType,
+ 0);
+ MakeClientGrabImpervious(client);
+ }
+ if (playback_client == client)
+ {
+ /*
+ * This extension does not need to clean up any
+ * server state when a client using this function
+ * "goes away". The server will just process any
+ * input actions that have already been sent to it,
+ * and will then reset its association with a client.
+ */
+ parse_fake_input(client, (char *)stuff);
+ return(Success);
+ }
+ else
+ {
+ /*
+ * this is a request by another client to send fake
+ * input while the server is still being used
+ */
+ SendErrorToClient(client,
+ XTestReqCode,
+ X_TestFakeInput,
+ None,
+ BadAccess);
+ return(BadAccess);
+ }
+}
+
+/*****************************************************************************
+ *
+ * ProcTestGetInput
+ *
+ *
+ */
+static int
+ProcTestGetInput(client)
+ register ClientPtr client;
+{
+ REQUEST(xTestGetInputReq);
+ REQUEST_SIZE_MATCH(xTestGetInputReq);
+ if (on_steal_input)
+ {
+ /*
+ * this is a request by another client to get fake input
+ * while the server is still sending input to the first client
+ */
+ SendErrorToClient(client,
+ XTestReqCode,
+ X_TestGetInput,
+ None,
+ BadAccess);
+ return(BadAccess);
+ }
+ else
+ {
+ /*
+ * Set up a resource associated with the client using this
+ * function so that this extension gets called when the
+ * client "goes away". This allows this extension to
+ * clean up the server state.
+ */
+ current_client_id = FakeClientID(client->index);
+ AddResource(current_client_id,
+ XTestType,
+ 0);
+ /*
+ * indicate that a client is stealing input
+ */
+ on_steal_input = TRUE;
+ if ((stuff->mode & XTestEXCLUSIVE) == 0)
+ {
+ exclusive_steal = FALSE;
+ }
+ else
+ {
+ exclusive_steal = TRUE;
+ }
+ steal_input(client, stuff->mode);
+ return(Success);
+ }
+}
+
+/*****************************************************************************
+ *
+ * ProcTestStopInput
+ *
+ *
+ */
+static int
+ProcTestStopInput(client)
+ register ClientPtr client;
+{
+ REQUEST(xTestStopInputReq);
+ REQUEST_SIZE_MATCH(xTestStopInputReq);
+ if (on_steal_input && (current_xtest_client == client))
+ {
+ on_steal_input = FALSE;
+ exclusive_steal = FALSE;
+ stop_stealing_input();
+ /*
+ * remove the resource associated with this client
+ */
+ FreeResource(current_client_id, RT_NONE);
+ return(Success);
+ }
+ else
+ {
+ /*
+ * this is a request to stop fake input when fake input has
+ * never been started or from a client that hasn't started
+ * fake input
+ */
+ SendErrorToClient(client,
+ XTestReqCode,
+ X_TestStopInput,
+ None,
+ BadAccess);
+ return(BadAccess);
+ }
+}
+
+/*****************************************************************************
+ *
+ * ProcTestReset
+ *
+ *
+ */
+static int
+ProcTestReset(client)
+ register ClientPtr client;
+{
+ REQUEST(xTestResetReq);
+ REQUEST_SIZE_MATCH(xTestResetReq);
+ on_steal_input = FALSE;
+ exclusive_steal = FALSE;
+ /*
+ * defined in xtest1dd.c
+ */
+ stop_stealing_input();
+ /*
+ * defined in xtest1dd.c
+ */
+ abort_play_back();
+ return(Success);
+}
+
+/*****************************************************************************
+ *
+ * ProcTestQueryInputSize
+ *
+ *
+ */
+static int
+ProcTestQueryInputSize(client)
+ register ClientPtr client;
+{
+ REQUEST(xTestQueryInputSizeReq);
+ REQUEST_SIZE_MATCH(xTestQueryInputSizeReq);
+ /*
+ * defined in xtest1dd.c
+ */
+ return_input_array_size(client);
+ return(Success);
+}
+
+/*****************************************************************************
+ *
+ * XTestResetProc
+ *
+ * This function is called by the server when the server has no clients
+ * connected to it. It must put eveything back the way it was before
+ * this extension was installed.
+ */
+static void
+XTestResetProc()
+{
+ /*
+ * remove the routine to handle byte-swapping the replies
+ * for this extension in the ReplySwapVector table
+ */
+ ReplySwapVector[XTestReqCode] = NotImplemented;
+ /*
+ * remove the routine to handle byte-swapping the events
+ * for this extension in the EventSwapVector table
+ */
+ EventSwapVector[XTestInputActionType] = NotImplemented;
+ EventSwapVector[XTestFakeAckType] = NotImplemented;
+ /*
+ * reset the variables initialized just once at load time
+ */
+ XTestReqCode = 0;
+ XTestInputActionType = 0;
+ XTestFakeAckType = 1;
+ on_steal_input = FALSE;
+ exclusive_steal = FALSE;
+ playback_client = 0; /* Don't really need this but it looks nice */
+}
+
+/*****************************************************************************
+ *
+ * ProcTestQueryInputSize
+ *
+ * This routine is called when a client that has asked for input actions
+ * to be sent to it "goes away". This routine must clean up the
+ * server state.
+ */
+/*ARGSUSED*/
+static int
+XTestCurrentClientGone(value, id)
+ pointer value;
+ XID id;
+{
+ /*
+ * defined in xtest1dd.c
+ */
+ on_steal_input = FALSE;
+ exclusive_steal = FALSE;
+ /*
+ * defined in xtestdd.c
+ */
+ playback_client = 0;
+ abort_play_back();
+ return TRUE;
+}
+
+/*****************************************************************************
+ *
+ * SReplyXTestDispatch
+ *
+ * Swap any replies defined in this extension.
+ */
+static void
+SReplyXTestDispatch(client_ptr, size, reply_ptr)
+ ClientPtr client_ptr;
+ int size;
+ char *reply_ptr;
+{
+ /*
+ * used in the swaps and swapl macros for temporary storage space
+ */
+ register char n;
+ /*
+ * pointer to xTestQueryInputSizeReply
+ */
+ xTestQueryInputSizeReply *rep_ptr;
+
+ /*
+ * there is only one reply in this extension, so byte-swap it
+ */
+ rep_ptr = (xTestQueryInputSizeReply *) reply_ptr;
+ swaps(&(rep_ptr->sequenceNumber), n);
+ swapl(&(rep_ptr->length), n);
+ swapl(&(rep_ptr->size_return), n);
+ /*
+ * now write the swapped reply to the client
+ */
+ WriteToClient(client_ptr, size, reply_ptr);
+}
+
+/*****************************************************************************
+ *
+ * SEventXTestDispatch
+ *
+ * Swap any events defined in this extension.
+ */
+static void
+SEventXTestDispatch(from, to)
+ xEvent *from;
+ xEvent *to;
+{
+ /*
+ * used in the swaps and swapl macros for temporary storage space
+ */
+ register char n;
+ /*
+ * index counter
+ */
+ int i;
+ /*
+ * pointer to the next input action in the event
+ */
+ CARD8 *input_action_ptr;
+ /*
+ * holds the type of the next input action in the event
+ */
+ int input_action_type;
+
+
+ /*
+ * copy the type information from the "from" event to the "to" event
+ */
+ ((xTestInputActionEvent *) to)->type =
+ ((xTestInputActionEvent *) from)->type;
+ /*
+ * copy the sequence number information from the "from" event to the
+ * "to" event
+ */
+ ((xTestInputActionEvent *) to)->sequenceNumber =
+ ((xTestInputActionEvent *) from)->sequenceNumber;
+ /*
+ * byte-swap the sequence number in the "to" event
+ */
+ swaps(&(((xTestInputActionEvent *) to)->sequenceNumber), n);
+ /*
+ * If the event is an xTestInputActionEvent, then it needs more
+ * processing. Otherwise, it is an xTestFakeAckEvent, which
+ * has no other information in it.
+ */
+ if ((((xTestInputActionEvent *) to)->type & 0x7f) ==
+ XTestInputActionType)
+ {
+ /*
+ * copy the input actions from the "from" event
+ * to the "to" event
+ */
+ for (i = 0; i < XTestACTIONS_SIZE; i++)
+ {
+ ((xTestInputActionEvent *) to)->actions[i] =
+ ((xTestInputActionEvent *) from)->actions[i];
+ }
+ /*
+ * byte-swap the input actions in the "to" event
+ */
+ for (i = 0; i < XTestACTIONS_SIZE; i++)
+ {
+ /*
+ * point to the next input action in the event
+ */
+ input_action_ptr = &(((xTestInputActionEvent *) to)->actions[i]);
+ /*
+ * figure out what type of input action it is
+ */
+ input_action_type = (*input_action_ptr) &
+ XTestACTION_TYPE_MASK;
+ /*
+ * byte-swap the input action according to it's type
+ */
+ switch (input_action_type)
+ {
+ case XTestKEY_ACTION:
+ /*
+ * byte-swap the delay_time field
+ */
+ swaps(&(((XTestKeyInfo *) input_action_ptr)->delay_time), n);
+ /*
+ * advance to the next input action
+ */
+ i += sizeof(XTestKeyInfo);
+ break;
+ case XTestMOTION_ACTION:
+ /*
+ * byte-swap the delay_time field
+ */
+ swaps(&(((XTestMotionInfo *) input_action_ptr)->delay_time), n);
+ /*
+ * advance to the next input action
+ */
+ i += sizeof(XTestMotionInfo);
+ break;
+ case XTestJUMP_ACTION:
+ /*
+ * byte-swap the jumpx field
+ */
+ swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpx), n);
+ /*
+ * byte-swap the jumpy field
+ */
+ swaps(&(((XTestJumpInfo *) input_action_ptr)->jumpy), n);
+ /*
+ * byte-swap the delay_time field
+ */
+ swaps(&(((XTestJumpInfo *) input_action_ptr)->delay_time), n);
+ /*
+ * advance to the next input action
+ */
+ i += sizeof(XTestJumpInfo);
+ break;
+ default:
+ /*
+ * if this is a delay input action, then
+ * byte-swap it, otherwise we have reached the
+ * end of the input actions in this event
+ */
+ if (XTestUnpackDeviceID(*input_action_ptr) ==
+ XTestDELAY_DEVICE_ID)
+ {
+ /*
+ * byte-swap the delay_time field
+ */
+ swapl(&(((XTestDelayInfo *) input_action_ptr)->delay_time), n);
+ /*
+ * advance to the next input action
+ */
+ i += sizeof(XTestDelayInfo);
+ }
+ else
+ {
+ /*
+ * if the input action header byte is 0
+ * or ill-formed, then there are no
+ * more input actions in this event
+ */
+ i = XTestACTIONS_SIZE;
+ }
+ break;
+ }
+ }
+ }
+}