aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/dps/XDPS.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/lib/dps/XDPS.c')
-rw-r--r--nx-X11/lib/dps/XDPS.c2235
1 files changed, 2235 insertions, 0 deletions
diff --git a/nx-X11/lib/dps/XDPS.c b/nx-X11/lib/dps/XDPS.c
new file mode 100644
index 000000000..5b1614e4c
--- /dev/null
+++ b/nx-X11/lib/dps/XDPS.c
@@ -0,0 +1,2235 @@
+/*
+ * XDPS.c -- implementation of low-level Xlib routines for XDPS extension
+ *
+ * (c) Copyright 1989-1994 Adobe Systems Incorporated.
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, distribute, and sublicense this software
+ * and its documentation for any purpose and without fee is hereby granted,
+ * provided that the above copyright notices appear in all copies and that
+ * both those copyright notices and this permission notice appear in
+ * supporting documentation and that the name of Adobe Systems Incorporated
+ * not be used in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. No trademark license
+ * to use the Adobe trademarks is hereby granted. If the Adobe trademark
+ * "Display PostScript"(tm) is used to describe this software, its
+ * functionality or for any other purpose, such use shall be limited to a
+ * statement that this software works in conjunction with the Display
+ * PostScript system. Proper trademark attribution to reflect Adobe's
+ * ownership of the trademark shall be given whenever any such reference to
+ * the Display PostScript system is made.
+ *
+ * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
+ * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
+ * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+ * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
+ * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
+ * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
+ * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
+ *
+ * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
+ * Incorporated which may be registered in certain jurisdictions
+ *
+ * Author: Adobe Systems Incorporated
+ */
+/* $XFree86: xc/lib/dps/XDPS.c,v 1.4tsi Exp $ */
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+
+#include <stdio.h>
+/* Include this first so that Xasync.h, included from Xlibint.h, can find
+ the definition of NOFILE */
+#include <stdlib.h>
+#include <sys/param.h>
+#include <X11/Xlibint.h>
+#include <X11/Xatom.h>
+#include <X11/Xutil.h>
+
+#include "DPS/XDPS.h"
+#include "DPS/XDPSproto.h"
+#include "DPS/XDPSlib.h"
+#include "DPS/dpsNXargs.h"
+
+#include "cslibint.h"
+#include "dpsassert.h"
+#include "DPSCAPClient.h"
+
+#include "publictypes.h"
+#include "dpsXpriv.h"
+
+/* === DEFINITIONS === */
+
+#ifndef _NFILE
+#define DPSMAXDISPLAYS 128
+#else
+#define DPSMAXDISPLAYS _NFILE
+#endif /* _NFILE */
+
+#define MajorOpCode(dpy) (Codes[DPY_NUMBER(dpy)] ? \
+ Codes[DPY_NUMBER(dpy)]->major_opcode : \
+ Punt())
+
+#define DPSCAP_INITCTXTS 4 /* per display */
+
+/* === TYPES === */
+
+typedef Status (*PSCMProc)(Display *, XEvent *, xEvent *);
+
+typedef struct {
+ char passEvents;
+ char wrapWaiting;
+ char syncMask; /* CSDPS only */
+ char debugMask; /* CSDPS only */
+} DPSDisplayFlags;
+
+/* For now DPSDisplayFlags is no larger than a pointer. Revisit this if the
+ structure grows. */
+
+typedef int (*GenericProcPtrReturnsInt)(Display *);
+
+typedef struct _t_DPSCAPPausedContextData {
+ struct _t_DPSCAPPausedContextData *next;
+ Bool paused;
+ ContextXID cxid;
+ unsigned int seqnum;
+} DPSCAPPausedContextData;
+
+typedef struct {
+ char showSmallSizes;
+ char pixMem;
+} DPSCAPAgentArgs;
+
+typedef struct {
+ void (*Flush)(Display *);
+ int (*Read)(Display*, char*, long);
+ void (*ReadPad)(Display*, char*, long);
+ Status (*Reply)(Display*, xReply*, int, Bool);
+ void (*Send)(Display*, _Xconst char*, long);
+} XDPSLIOProcs;
+
+/* === GLOBALS === */
+
+/* For debugging, allows client to force the library to use an agent */
+int gForceCSDPS = 0;
+
+/* Force all DPS NX protocol requests to flush if CSDPS */
+int gAutoFlush = 1;
+
+/* Force all NX XDPSLGiveInputs to flush independent of gAutoFlush */
+int gForceFlush = 1;
+
+/* Quick check for any paused contexts */
+int gTotalPaused = 0;
+
+/* === LOCALS === */
+
+/* Common stuff */
+static XExtCodes *Codes[DPSMAXDISPLAYS];
+static int version[DPSMAXDISPLAYS];
+static XDPSLEventHandler StatusProc[DPSMAXDISPLAYS];
+static DPSDisplayFlags displayFlags[DPSMAXDISPLAYS];
+static XDPSLEventHandler TextProc = NULL;
+static XDPSLEventHandler ReadyProc[DPSMAXDISPLAYS]; /* L2-DPS/PROTO 9 */
+static int NumberType[DPSMAXDISPLAYS]; /* Garbage okay after dpy closed */
+static char *FloatingName[DPSMAXDISPLAYS]; /* Garbage okay after dpy closed */
+
+/* CSDPS stuff */
+static Display *ShuntMap[DPSMAXDISPLAYS];
+static PSCMProc ClientMsgProc[DPSMAXDISPLAYS];
+static GenericProcPtrReturnsInt AfterProcs[DPSMAXDISPLAYS];
+static DPSCAPPausedContextData *PausedPerDisplay[DPSMAXDISPLAYS];
+static DPSCAPAgentArgs AgentArgs[DPSMAXDISPLAYS];
+static unsigned int LastXRequest[DPSMAXDISPLAYS];
+static int GCFlushMode[DPSMAXDISPLAYS];
+
+#ifdef VMS
+static Display *dpys[DPSMAXDISPLAYS];
+static nextDpy = 0;
+#endif /* VMS */
+
+static void DPSCAPInitGC(Display *dpy, Display *agent, GC gc);
+static Status DPSCAPClientMessageProc(Display *dpy, XEvent *re, xEvent *event);
+static int DPSCAPAfterProc(Display *xdpy);
+static unsigned int DPSCAPSetPause(Display *xdpy, ContextXID cxid);
+static Bool DPSCAPResumeContext(Display *xdpy, ContextXID cxid);
+static Bool WaitForSyncProc(Display *xdpy, XEvent *event, char *arg);
+
+static XDPSLIOProcs xlProcs = { /* Use these for DPS/X extension */
+ _XFlush,
+ _XRead,
+ _XReadPad,
+ _XReply,
+ _XSend
+ };
+
+static XDPSLIOProcs nxlProcs = { /* Use these for NX */
+ N_XFlush,
+ N_XRead,
+ N_XReadPad,
+ N_XReply,
+ N_XSend
+ };
+
+/* === MACROS === */
+
+#define IFNXSETCALL(a, x) call = ((a) != (x)) ? &nxlProcs : &xlProcs
+
+/* === PRIVATE PROCS === */
+
+static int Punt(void)
+{
+ DPSFatalProc(NULL, "Extension has not been initialized");
+ exit(1);
+}
+
+#ifdef VMS
+/* This is a terribly inefficient way to find a per-display index, but we
+ need it till we get dpy->fd fixed in VMS%%%%%*/
+static int FindDpyNum(Display *dpy)
+{
+int i;
+for (i=0; dpys[i] != dpy ; i++)
+ {
+ if (i == nextDpy)
+ {
+ dpys[nextDpy++]=dpy;
+ break;
+ }
+ }
+return i;
+}
+#define DPY_NUMBER(dpy) FindDpyNum(dpy)
+#else /* VMS */
+#define DPY_NUMBER(dpy) ((dpy)->fd)
+#endif /* VMS */
+
+/* === PROCEDURES === */
+
+/* ARGSUSED */
+void
+XDPSLSetTextEventHandler(Display *dpy, XDPSLEventHandler proc)
+{
+ TextProc = proc;
+}
+
+/* ARGSUSED */
+void
+XDPSLCallOutputEventHandler(Display *dpy, XEvent *event)
+{
+ (*TextProc)(event);
+}
+
+void
+XDPSLSetStatusEventHandler(Display *dpy, XDPSLEventHandler proc)
+{
+ StatusProc[DPY_NUMBER(dpy)] = proc;
+}
+
+void
+XDPSLCallStatusEventHandler(Display *dpy, XEvent *event)
+{
+ (*(StatusProc[DPY_NUMBER(dpy)]))(event);
+}
+
+/* Added for L2-DPS/PROTO 9 */
+void
+XDPSLSetReadyEventHandler(Display *dpy, XDPSLEventHandler proc)
+{
+ ReadyProc[DPY_NUMBER(dpy)] = proc;
+}
+
+/* Added for L2-DPS/PROTO 9 */
+void
+XDPSLCallReadyEventHandler(Display *dpy, XEvent *event)
+{
+ (*(ReadyProc[DPY_NUMBER(dpy)]))(event);
+}
+
+/* Added for L2-DPS/PROTO 9 */
+int
+XDPSLGetVersion(Display *dpy)
+{
+ return(version[DPY_NUMBER(dpy)]);
+}
+/* See CSDPS additions for XDPSLSetVersion */
+
+void
+XDPSLInitDisplayFlags(Display *dpy)
+{
+ int d = DPY_NUMBER(dpy);
+ displayFlags[d].wrapWaiting = False;
+
+ /* Instead of explicitly setting the pass-event flag, rely upon the fact
+ that it gets initialized to 0 by the compiler. This means that you
+ can set the event delivery mode on a display before creating any
+ contexts, which is a Good Thing */
+}
+
+XExtCodes *XDPSLGetCodes(Display *dpy)
+{
+ return Codes[DPY_NUMBER(dpy)];
+}
+
+/* ARGSUSED */
+static int
+CloseDisplayProc(Display *dpy, XExtCodes *codes)
+{
+ /* This proc is for native DPS/X only, not CSDPS */
+ Codes[DPY_NUMBER(dpy)] = NULL;
+ /* Clear list */
+ XDPSPrivZapDpy(dpy);
+#ifdef VMS
+ dpys[DPY_NUMBER(dpy)] = NULL;
+ /*%%%%Temp till we fix dpy->fd*/
+#endif /* VMS */
+ return 0; /* return-value is ignored */
+}
+
+Bool
+XDPSLGetPassEventsFlag(Display *dpy)
+{
+ return displayFlags[DPY_NUMBER(dpy)].passEvents;
+}
+
+void
+XDPSLSetPassEventsFlag(Display *dpy, Bool flag)
+{
+ displayFlags[DPY_NUMBER(dpy)].passEvents = flag;
+}
+
+Bool
+XDPSLGetWrapWaitingFlag(Display *dpy)
+{
+ return displayFlags[DPY_NUMBER(dpy)].wrapWaiting;
+}
+
+void
+XDPSLSetWrapWaitingFlag(Display *dpy, Bool flag)
+{
+ displayFlags[DPY_NUMBER(dpy)].wrapWaiting = flag;
+}
+
+static Status
+ConvertOutputEvent(Display *dpy, XEvent *ce, xEvent *we)
+{
+ register PSOutputEvent *wireevent = (PSOutputEvent *) we;
+ register XDPSLOutputEvent *clientevent = (XDPSLOutputEvent *) ce;
+
+ clientevent->type = wireevent->type & 0x7f;
+ clientevent->serial = _XSetLastRequestRead(dpy,
+ (xGenericReply *)wireevent);
+ clientevent->send_event = (wireevent->type & 0x80) != 0;
+ clientevent->display = dpy;
+ clientevent->cxid = wireevent->cxid;
+ clientevent->length = wireevent->length;
+ bcopy((char *) wireevent->data, clientevent->data, wireevent->length);
+ if (TextProc && !XDPSLGetPassEventsFlag(dpy)) {
+ (*TextProc)((XEvent *) clientevent);
+ return False;
+ }
+ return True;
+}
+
+static Status
+ConvertStatusEvent(Display *dpy, XEvent *ce, xEvent *we)
+{
+ register PSStatusEvent *wireevent = (PSStatusEvent *) we;
+ register XDPSLStatusEvent *clientevent = (XDPSLStatusEvent *) ce;
+
+ clientevent->type = wireevent->type & 0x7f;
+ clientevent->serial = _XSetLastRequestRead(dpy,
+ (xGenericReply *)wireevent);
+ clientevent->send_event = (wireevent->type & 0x80) != 0;
+ clientevent->display = dpy;
+ clientevent->cxid = wireevent->cxid;
+ clientevent->status = wireevent->status;
+ if (StatusProc[DPY_NUMBER(dpy)] && !XDPSLGetPassEventsFlag(dpy)) {
+ (*(StatusProc[DPY_NUMBER(dpy)]))((XEvent *) clientevent);
+ return False;
+ }
+ return True;
+}
+
+/* Added for L2-DPS/PROTO 9 */
+static Status
+ConvertReadyEvent(Display *dpy, XEvent *ce, xEvent *we)
+{
+ register PSReadyEvent *wireevent = (PSReadyEvent *) we;
+ register XDPSLReadyEvent *clientevent = (XDPSLReadyEvent *) ce;
+
+ clientevent->type = wireevent->type & 0x7f;
+ clientevent->serial = _XSetLastRequestRead(dpy,
+ (xGenericReply *)wireevent);
+ clientevent->send_event = (wireevent->type & 0x80) != 0;
+ clientevent->display = dpy;
+ clientevent->cxid = wireevent->cxid;
+ clientevent->val[0] = wireevent->val1;
+ clientevent->val[1] = wireevent->val2;
+ clientevent->val[2] = wireevent->val3;
+ clientevent->val[3] = wireevent->val4;
+ if (ReadyProc[DPY_NUMBER(dpy)] && !XDPSLGetPassEventsFlag(dpy)) {
+ (*(ReadyProc[DPY_NUMBER(dpy)]))((XEvent *) clientevent);
+ return False;
+ }
+ return True;
+}
+
+/* Added for L2-DPS/PROTO 9 */
+/* ARGSUSED */
+
+static int
+CatchBadMatch(Display *dpy, xError *err, XExtCodes *codes, int *ret_code)
+{
+ if (err->errorCode == BadMatch)
+ {
+ *ret_code = 0;
+ return 1; /* suppress error */
+ }
+ else
+ {
+ *ret_code = 1;
+ return 0; /* pass error along */
+ }
+}
+
+
+int
+XDPSLInit(
+ Display *dpy,
+ int *numberType, /* RETURN */
+ char **floatingName) /* RETURN: CALLER MUST NOT MODIFY OR FREE! */
+{
+ XExtCodes *codes = (XExtCodes *)NULL;
+ register xPSInitReq *req;
+ xPSInitReply rep;
+ char *ptr;
+ int first_event;
+
+ {
+ char *ddt;
+
+ if ((ddt = getenv("DPSNXOVER")) != NULL) {
+ gForceCSDPS = (*ddt == 't' || *ddt == 'T');
+ if (gForceCSDPS)
+ DPSWarnProc(NULL, "*** USING DPS NX ***");
+ }
+ }
+
+ if ((codes = Codes[DPY_NUMBER(dpy)]) != NULL) {
+ if (numberType)
+ *numberType = NumberType[DPY_NUMBER(dpy)];
+ if (floatingName)
+ *floatingName = FloatingName[DPY_NUMBER(dpy)];
+ return codes->first_event;
+ } else {
+ if (gForceCSDPS)
+ goto try_dps_nx;
+ codes = XInitExtension(dpy, DPSNAME);
+ if (codes == NULL) {
+ /* try DEC UWS 2.2 server */
+ codes = XInitExtension(dpy, DECDPSNAME);
+try_dps_nx:
+ if (codes == NULL) {
+ int myNumberType;
+ char *myFloatingName;
+
+ first_event = CSDPSInit(dpy, &myNumberType, &myFloatingName);
+ NumberType[DPY_NUMBER(dpy)] = myNumberType;
+ FloatingName[DPY_NUMBER(dpy)] = myFloatingName;
+ if (numberType)
+ *numberType = myNumberType;
+ if (floatingName)
+ *floatingName = myFloatingName;
+ return first_event;
+ }
+ }
+ Codes[DPY_NUMBER(dpy)] = codes;
+ ShuntMap[DPY_NUMBER(dpy)] = dpy;
+ /* set procs for native DPS/X */
+ XESetCloseDisplay(dpy, codes->extension, CloseDisplayProc);
+ XESetWireToEvent(dpy, codes->first_event + PSEVENTOUTPUT,
+ ConvertOutputEvent);
+ XESetWireToEvent(dpy, codes->first_event + PSEVENTSTATUS,
+ ConvertStatusEvent);
+ XESetWireToEvent(dpy, codes->first_event + PSEVENTREADY,
+ ConvertReadyEvent);
+ first_event = codes->first_event;
+ }
+
+ /* We have to handle a BadMatch error, in the case where
+ the client has a later (higher) version of
+ the protocol than the server */
+ {
+ int (*oldErrorProc)(Display*, xError*, XExtCodes*, int*);
+ int libVersion;
+ Bool doneIt;
+
+ XSync(dpy, False);
+ LockDisplay(dpy);
+ oldErrorProc = XESetError(dpy, codes->extension, CatchBadMatch);
+ libVersion = DPSPROTOCOLVERSION;
+ doneIt = False;
+ while (libVersion >= DPSPROTO_OLDEST)
+ {
+ GetReq(PSInit, req);
+ req->reqType = MajorOpCode(dpy);
+ req->dpsReqType = X_PSInit;
+ req->libraryversion = libVersion;
+ if (_XReply(dpy, (xReply *) &rep, 0, xFalse))
+ {
+ doneIt = True;
+ break;
+ }
+ /* otherwise, try previous version */
+ --libVersion;
+ }
+ oldErrorProc = XESetError(dpy, codes->extension, oldErrorProc);
+ if (!doneIt)
+ {
+ DPSFatalProc(NULL, "Incompatible protocol versions");
+ exit(1);
+ }
+
+ /* NOTE *************************************************
+ We made a boo-boo in the 1007.2 and earlier versions of
+ our X server glue code. Instead of sending a
+ BadMatch error if the client's version is newer (higher)
+ than the server's, it just replies with success. We
+ could test for that situation here by looking at
+ rep.serverversion, but it turns out that we don't need
+ to do anything special. Since rep.serverversion gets
+ assigned to our version[] array, it is as if we handled
+ the BadMatch correctly. Just for safety's sake, we'll
+ do some bulletproofing here instead.
+ Fixes 2ps_xdps BUG #6 */
+
+ else if (rep.serverversion < DPSPROTO_OLDEST
+ || rep.serverversion > DPSPROTOCOLVERSION)
+ {
+ DPSFatalProc(NULL, "Server replied with bogus version");
+ exit(1);
+ }
+ }
+
+ version[DPY_NUMBER(dpy)] = rep.serverversion;
+ NumberType[DPY_NUMBER(dpy)] = rep.preferredNumberFormat;
+ if (numberType)
+ *numberType = rep.preferredNumberFormat;
+
+ ptr = (char *) Xmalloc(rep.floatingNameLength + 1);
+ _XReadPad(dpy, ptr, rep.floatingNameLength);
+ ptr[rep.floatingNameLength] = 0;
+ FloatingName[DPY_NUMBER(dpy)] = ptr;
+ if (floatingName)
+ *floatingName = ptr;
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ return first_event;
+}
+
+
+
+
+static void CopyColorMapsIntoCreateContextReq(
+ xPSCreateContextReq *req,
+ XStandardColormap *colorcube,
+ XStandardColormap *grayramp)
+{
+ req->cmap = 0;
+ if (colorcube != NULL) {
+ req->cmap = colorcube->colormap;
+ req->redmax = colorcube->red_max;
+ req->redmult = colorcube->red_mult;
+ req->greenmax = colorcube->green_max;
+ req->greenmult = colorcube->green_mult;
+ req->bluemax = colorcube->blue_max;
+ req->bluemult = colorcube->blue_mult;
+ req->colorbase = colorcube->base_pixel;
+ }
+ else {
+ req->redmult = 0;
+ /* The rest of this shouldn't be necessary, but there are some
+ servers out there that erroneously check the other fields
+ even when redmult is 0 */
+ req->redmax = 0;
+ req->greenmult = 0;
+ req->greenmax = 0;
+ req->bluemult = 0;
+ req->bluemax = 0;
+ req->colorbase = 0;
+ }
+
+ if (grayramp != NULL) {
+ req->cmap = grayramp->colormap;
+ req->graymax = grayramp->red_max;
+ req->graymult = grayramp->red_mult;
+ req->graybase = grayramp->base_pixel;
+ }
+ else req->graymult = 0;
+}
+
+
+
+
+
+
+/* ARGSUSED */
+ContextXID
+XDPSLCreateContextAndSpace(
+ register Display *xdpy,
+ Drawable draw,
+ GC gc,
+ int x, int y,
+ unsigned int eventMask,
+ XStandardColormap *grayRamp,
+ XStandardColormap *colorCube,
+ unsigned int actual,
+ ContextPSID *cpsid, /* RETURN */
+ SpaceXID *sxid, /* RETURN */
+ Bool secure) /* Added for L2-DPS/PROTO 9 */
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ ContextXID cxid;
+ register xPSCreateContextReq *req; /* Same struct for CreateSecureContext */
+ xPSCreateContextReply rep;
+ XStandardColormap defColorcube, defGrayramp;
+ XStandardColormap *requestCube, *requestRamp;
+ int index;
+ XDPSLIOProcs *call;
+
+ if (grayRamp == NULL && colorCube == NULL) return(None);
+
+ if (secure && version[dpyix] < DPSPROTO_V09)
+ return(None); /* No secure contexts before PROTO 9 */
+
+ /* Index gets encoded as follows:
+ *
+ * 0 grayRamp = Default, colorCube = Default
+ * 1 grayRamp = non-Default, colorcube = Default
+ * 2 grayRamp = Default, colorcube = non-Default
+ * 3 grayRamp = non-Default, colorcube = non-Default
+ *
+ */
+ index = ((grayRamp == DefaultStdCMap || grayRamp == NULL) ? 0 : 1) +
+ (colorCube == DefaultStdCMap ? 0 : 2);
+
+ switch (index)
+ {
+ default:
+ case 0: /* Both are default */
+ XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
+ &defColorcube, &defGrayramp);
+ requestCube = &defColorcube;
+ requestRamp = &defGrayramp;
+ break;
+
+ case 1: /* gray specified, Color default */
+ XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
+ &defColorcube, (XStandardColormap *) NULL);
+ requestCube = &defColorcube;
+ requestRamp = grayRamp;
+ break;
+
+ case 2: /* gray default, Color specified */
+ XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
+ (XStandardColormap *) NULL, &defGrayramp);
+ requestCube = colorCube;
+ requestRamp = &defGrayramp;
+ break;
+
+ case 3: /* Both specified */
+ requestCube = colorCube;
+ requestRamp = grayRamp;
+ break;
+ }
+
+ if (gc != NULL)
+ XDPSLFlushGC(xdpy, gc);
+ if (dpy != xdpy)
+ {
+ int syncMask = displayFlags[dpyix].syncMask;
+
+ /* Don't worry about pauses here, since we are just
+ now creating the context! */
+ if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
+ XSync(xdpy, False);
+ }
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSCreateContext, req);
+ CopyColorMapsIntoCreateContextReq(req, requestCube, requestRamp);
+
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = (secure) ? X_PSCreateSecureContext : X_PSCreateContext;
+ req->x = x;
+ req->y = y;
+ req->drawable = draw;
+ req->gc = (gc != NULL) ? XGContextFromGC(gc) : None;
+ cxid = req->cxid = XAllocID(xdpy);
+ req->sxid = XAllocID(xdpy);
+ if (sxid)
+ *sxid = req->sxid;
+ req->eventmask = 0; /* %%% */
+ req->actual = actual;
+ IFNXSETCALL(dpy, xdpy);
+ (void) (*call->Reply) (dpy, (xReply *)&rep, 0, xTrue);
+
+ if (cpsid)
+ *cpsid = (int)rep.cpsid;
+
+ UnlockDisplay(dpy);
+ /* If the context creation succeeded and we are CSDPS, send GC values */
+ if (rep.cpsid && xdpy != dpy && gc != NULL)
+ {
+ DPSCAPInitGC(xdpy, dpy, gc);
+ }
+ SyncHandle();
+
+ if (dpy != xdpy)
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+ return (cxid);
+}
+
+
+/* ARGSUSED */
+ContextXID
+XDPSLCreateContext(
+ register Display *xdpy,
+ SpaceXID sxid,
+ Drawable draw,
+ GC gc,
+ int x, int y,
+ unsigned int eventMask,
+ XStandardColormap *grayRamp,
+ XStandardColormap *colorCube,
+ unsigned int actual,
+ ContextPSID *cpsid, /* RETURN */
+ Bool secure) /* L2-DPS/PROTO 9 addition */
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSCreateContextReq *req;
+ xPSCreateContextReply rep;
+ ContextXID cxid; /* RETURN */
+ XStandardColormap defColorcube, defGrayramp;
+ XStandardColormap *requestCube, *requestRamp;
+ int index;
+ XDPSLIOProcs *call;
+
+ if (secure && version[dpyix] < DPSPROTO_V09)
+ return(None); /* No secure contexts before PROTO 9 */
+
+ /* Index gets encoded as follows:
+ *
+ * 0 grayRamp = Default, colorCube = Default
+ * 1 grayRamp = non-Default, colorcube = Default
+ * 2 grayRamp = Default, colorcube = non-Default
+ * 3 grayRamp = non-Default, colorcube = non-Default
+ *
+ * Note that only the first or last case should ever happen.
+ */
+ index = ((grayRamp == DefaultStdCMap) ? 0 : 1) +
+ ((colorCube == DefaultStdCMap) ? 0 : 2);
+
+ switch (index)
+ {
+ default:
+ case 0: /* Both are default */
+ XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
+ &defColorcube, &defGrayramp);
+ requestCube = &defColorcube;
+ requestRamp = &defGrayramp;
+ break;
+
+ case 1: /* gray specified, Color default */
+ XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
+ &defColorcube, (XStandardColormap *) NULL);
+ requestCube = &defColorcube;
+ requestRamp = grayRamp;
+ break;
+
+ case 2: /* gray default, Color specified */
+ XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
+ (XStandardColormap *) NULL, &defGrayramp);
+ requestCube = colorCube;
+ requestRamp = &defGrayramp;
+ break;
+
+ case 3: /* Both specified */
+ requestCube = colorCube;
+ requestRamp = grayRamp;
+ break;
+ }
+
+
+ if (gc != NULL)
+ XDPSLFlushGC(xdpy, gc);
+ if (dpy != xdpy)
+ {
+ int syncMask = displayFlags[dpyix].syncMask;
+
+ /* Don't worry about pauses here, since we are
+ just now creating this context! */
+ if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
+ XSync(xdpy, False);
+ }
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSCreateContext, req);
+ CopyColorMapsIntoCreateContextReq(req, requestCube, requestRamp);
+
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = (secure) ? X_PSCreateSecureContext : X_PSCreateContext;
+ req->x = x;
+ req->y = y;
+ req->drawable = draw;
+ req->gc = (gc != NULL) ? XGContextFromGC(gc) : None;
+ cxid = req->cxid = XAllocID(xdpy);
+ req->sxid = sxid;
+ req->actual = actual;
+
+ IFNXSETCALL(dpy, xdpy);
+ (void) (*call->Reply) (dpy, (xReply *)&rep, 0, xTrue);
+ if (cpsid)
+ *cpsid = (int)rep.cpsid;
+
+ UnlockDisplay(dpy);
+ /* If the context creation succeeded and we are CSDPS, send GC values */
+ if (rep.cpsid && xdpy != dpy && gc != NULL)
+ {
+ DPSCAPInitGC(xdpy, dpy, gc);
+ }
+
+ SyncHandle();
+
+ if (dpy != xdpy)
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+ return cxid;
+}
+
+SpaceXID
+XDPSLCreateSpace(Display *xdpy)
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSCreateSpaceReq *req;
+ SpaceXID sxid;
+
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSCreateSpace, req);
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = X_PSCreateSpace;
+ sxid = req->sxid = XAllocID(xdpy);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ if (dpy != xdpy)
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+ return sxid;
+}
+
+
+
+/*
+ * I'm not sure how portable my coalescing code is, so I've provided the
+ * below define. If it turns out this code just breaks somewhere, you
+ * can simply undefine COALESCEGIVEINPUT, and then everything will work
+ * (but slower). 6/16/89 (tw)
+ */
+
+#define COALESCEGIVEINPUT
+
+void
+XDPSLGiveInput(Display *xdpy, ContextXID cxid, char *data, int length)
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSGiveInputReq *req;
+ Bool didFlush = False;
+
+ if (dpy != xdpy)
+ {
+ register int syncMask = displayFlags[dpyix].syncMask;
+
+ if (syncMask & DPSCAP_SYNCMASK_RECONCILE)
+ {
+ XDPSLReconcileRequests(xdpy, cxid);
+ didFlush = True;
+ }
+
+ /* If this context got paused, no matter how, ignore
+ mode and resume it */
+ if (gTotalPaused && DPSCAPResumeContext(xdpy, cxid))
+ {
+ /* xdpy was flushed by DPSCAPResumeContext */
+ if (!didFlush)
+ {
+ N_XFlush(dpy);
+ didFlush = True;
+ }
+ }
+ else if (syncMask & DPSCAP_SYNCMASK_SYNC)
+ {
+ didFlush = True;
+ XSync(xdpy, False);
+ }
+ }
+ LockDisplay(dpy);
+
+#ifdef COALESCEGIVEINPUT
+ req = (xPSGiveInputReq *) dpy->last_req;
+ if (req->reqType == MajorOpCode(xdpy)
+ && req->dpsReqType == X_PSGiveInput
+ && req->cxid == cxid
+ && dpy->bufptr + length + 3 < dpy->bufmax) {
+ bcopy(data, ((char *) req) + sizeof(xPSGiveInputReq) + req->nunits,
+ length);
+ req->nunits += length;
+ req->length = (sizeof(xPSGiveInputReq) + req->nunits + 3) >> 2;
+ dpy->bufptr = dpy->last_req + sizeof(xPSGiveInputReq) +
+ ((req->nunits + 3) & ~3);
+ } else
+#endif /* COALESCEGIVEINPUT */
+ {
+ int flushOnce = 1;
+ int maxedOutLen = xdpy->max_request_size - sizeof(xPSGiveInputReq) - 4;
+ int nunits;
+
+ /* We have the rare opportunity to chop up a buffer that is larger
+ than the max request size into separate requests, unlike
+ most other X requests (such as DrawText). The -4 is to
+ force these maxed out requests to be less than the maximum
+ padding that would ever be needed, and to minimize padding
+ in the case where the input buffer is several times
+ larger than max request length. */
+
+ nunits = maxedOutLen;
+ do {
+ if (length < maxedOutLen)
+ nunits = length; /* Normal size block */
+ NXMacroGetReq(PSGiveInput, req);
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = X_PSGiveInput;
+ req->cxid = cxid;
+ req->nunits = nunits;
+ req->length += ((nunits + 3) >> 2);
+ if (dpy != xdpy) {
+ if (flushOnce && !didFlush) {
+ LockDisplay(xdpy);
+ _XFlush(xdpy);
+ UnlockDisplay(xdpy);
+ flushOnce = 0;
+ }
+ NXProcData(dpy, (char *) data, nunits);
+ } else
+ {Data(dpy, (char *) data, nunits);}
+ data += nunits;
+ length -= nunits;
+ } while (length);
+ }
+
+ /* In the NX case (didFlush is always False for the non-NX case),
+ the xdpy may have been flushed, but there is stuff left
+ buffered in dpy (NX connection). We can't leave the stuff
+ there, since we may never call a DPS routine again. Until
+ we can be notified about xdpy being flushed, we have to
+ clear out the dpy buffer after we cleared out the xdpy
+ buffer (didFlush == True). */
+
+ if (dpy != xdpy
+ && dpy->bufptr != dpy->buffer
+ && (gForceFlush || didFlush))
+ N_XFlush(dpy);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ if (dpy != xdpy)
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+}
+
+
+int
+XDPSLGetStatus(Display *xdpy, ContextXID cxid)
+{
+ int dpyix;
+ Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSGetStatusReq *req;
+ xPSGetStatusReply rep;
+ XDPSLIOProcs *call;
+
+ if (dpy != xdpy)
+ {
+ register int syncMask = displayFlags[dpyix].syncMask;
+
+ /* ASSERT: There is no reason to pause the context for this
+ request, so just sync. */
+ if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
+ XSync(xdpy, False);
+ }
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSGetStatus, req);
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = X_PSGetStatus;
+ req->cxid = cxid;
+ req->notifyIfChange = 0;
+
+ IFNXSETCALL(dpy, xdpy);
+ if (! (*call->Reply)(dpy, (xReply *)&rep, 0, xTrue))
+ rep.status = PSSTATUSERROR;
+ UnlockDisplay(dpy);
+ SyncHandle();
+ /* For CSDPS, guarantee that status events arrive just like DPS/X */
+ if (dpy != xdpy)
+ {
+ XDPSLSync(xdpy);
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+ }
+ return (int) rep.status;
+}
+
+void
+XDPSLDestroySpace(Display *xdpy, SpaceXID sxid)
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSDestroySpaceReq *req;
+
+ if (dpy != xdpy)
+ {
+ int syncMask = displayFlags[dpyix].syncMask;
+
+ /* ASSERT: There is no reason to pause the context for this
+ request, so just sync. */
+ if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
+ XSync(xdpy, False);
+ }
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSDestroySpace, req);
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = X_PSDestroySpace;
+ req->sxid = sxid;
+
+ if (gAutoFlush && dpy != xdpy)
+ {
+ N_XFlush(dpy);
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ if (dpy != xdpy)
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+}
+
+
+void
+XDPSLReset(Display *xdpy, ContextXID cxid)
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSResetReq *req;
+
+ if (dpy != xdpy)
+ {
+ register int syncMask = displayFlags[dpyix].syncMask;
+
+ /* ASSERT: There is no reason to pause the context for this
+ request, so just sync. */
+ if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
+ XSync(xdpy, False);
+ }
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSReset, req);
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = X_PSReset;
+ req->cxid = cxid;
+
+ if (gAutoFlush && dpy != xdpy)
+ {
+ N_XFlush(dpy);
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ if (dpy != xdpy)
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+}
+
+void
+XDPSLNotifyContext(
+ Display *xdpy,
+ ContextXID cxid,
+ int ntype) /* should this be an enum?? %%% */
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSNotifyContextReq *req;
+
+ if (dpy != xdpy)
+ {
+ register int syncMask = displayFlags[dpyix].syncMask;
+
+ /* ASSERT: There is no reason to pause the context for this
+ request, so just sync. */
+ if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
+ XSync(xdpy, False);
+ }
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSNotifyContext, req);
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = X_PSNotifyContext;
+ req->cxid = cxid;
+ req->notifyType = ntype;
+
+ if (dpy != xdpy)
+ {
+ N_XFlush(dpy); /* THIS IS CRITICAL TO AVOID HANGING! */
+ }
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ if (dpy != xdpy)
+ {
+ if (ntype == PSKILL)
+ XDPSLCleanContext(xdpy, cxid);
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+ }
+}
+
+
+ContextXID
+XDPSLCreateContextFromID(
+ Display *xdpy,
+ ContextPSID cpsid,
+ SpaceXID *sxid) /* RETURN */
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSCreateContextFromIDReq *req;
+ xPSCreateContextFromIDReply rep;
+ ContextXID cxid;
+ XDPSLIOProcs *call;
+
+ if (dpy != xdpy)
+ {
+ int syncMask = displayFlags[dpyix].syncMask;
+
+ /* ASSERT: There is no reason to pause the context for this
+ request, so just sync. */
+ if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
+ XSync(xdpy, False);
+ }
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSCreateContextFromID, req);
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = X_PSCreateContextFromID;
+ req->cpsid = cpsid;
+ cxid = req->cxid = XAllocID(xdpy);
+
+ IFNXSETCALL(dpy, xdpy);
+ (void) (*call->Reply) (dpy, (xReply *)&rep, 0, xTrue);
+ if (sxid)
+ *sxid = (int)rep.sxid;
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ if (dpy != xdpy)
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+ return(cxid);
+}
+
+
+/* Returns 1 on success, 0 on failure (cpsid not a valid context). */
+
+Status
+XDPSLIDFromContext(
+ Display *xdpy,
+ ContextPSID cpsid,
+ ContextXID *cxid, /* RETURN */
+ SpaceXID *sxid) /* RETURN */
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSXIDFromContextReq *req;
+ xPSXIDFromContextReply rep;
+ XDPSLIOProcs *call;
+
+ if (dpy != xdpy)
+ {
+ int syncMask = displayFlags[dpyix].syncMask;
+
+ /* ASSERT: There is no reason to pause the context for this
+ request, so just sync. */
+ if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
+ XSync(xdpy, False);
+ }
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSXIDFromContext, req);
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = X_PSXIDFromContext;
+ req->cpsid = cpsid;
+
+ IFNXSETCALL(dpy, xdpy);
+ (void) (*call->Reply) (dpy, (xReply *)&rep, 0, xTrue);
+ *sxid = (int)rep.sxid;
+ *cxid = (int)rep.cxid;
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ if (dpy != xdpy)
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+ return((Status)(*sxid != None && *cxid != None));
+}
+
+
+ContextPSID
+XDPSLContextFromXID(Display *xdpy, ContextXID cxid)
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSContextFromXIDReq *req;
+ xPSContextFromXIDReply rep;
+ XDPSLIOProcs *call;
+
+ if (dpy != xdpy)
+ {
+ int syncMask = displayFlags[dpyix].syncMask;
+
+ /* ASSERT: There is no reason to pause the context for this
+ request, so just sync. */
+ if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
+ XSync(xdpy, False);
+ }
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSContextFromXID, req);
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = X_PSContextFromXID;
+ req->cxid = cxid;
+
+ IFNXSETCALL(dpy, xdpy);
+ (void) (*call->Reply) (dpy, (xReply *)&rep, 0, xTrue);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+
+ if (dpy != xdpy)
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+ return (int)rep.cpsid;
+}
+
+
+void
+XDPSLSetStatusMask(
+ Display *xdpy,
+ ContextXID cxid,
+ unsigned int enableMask,
+ unsigned int disableMask,
+ unsigned int nextMask)
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSSetStatusMaskReq *req;
+
+ if (dpy != xdpy)
+ {
+ register int syncMask = displayFlags[dpyix].syncMask;
+
+ /* ASSERT: There is no reason to pause the context for this
+ request, so just sync. */
+ if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
+ XSync(xdpy, False);
+ }
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSSetStatusMask, req);
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = X_PSSetStatusMask;
+ req->cxid = cxid;
+ req->enableMask = enableMask;
+ req->disableMask = disableMask;
+ req->nextMask = nextMask;
+
+ if (gAutoFlush && dpy != xdpy)
+ {
+ N_XFlush(dpy);
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ if (dpy != xdpy)
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+}
+
+
+#ifdef VMS
+/*
+ * _XReadPad - Read bytes from the socket taking into account incomplete
+ * reads. If the number of bytes is not 0 mod 32, read additional pad
+ * bytes. This routine may have to be reworked if int < long.
+ */
+
+/* This is really in xlib, but is not in the sharable image transfer vector
+ * so I am copying it here for now. BF
+
+The following notice applies only to the functions
+_XReadPad and XFlush
+
+Copyright 1985, 1986, 1987, 1988, 1989 by the
+Massachusetts Institute of Technology
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation, and that the name of M.I.T. not be used in advertising or
+publicity pertaining to distribution of the software without specific,
+written prior permission. M.I.T. makes no representations about the
+suitability of this software for any purpose. It is provided "as is"
+without express or implied warranty.
+
+*/
+void
+_XReadPad (Display *dpy, char *data, long size)
+{
+ static int padlength[4] = {0,3,2,1};
+ register long bytes_read;
+ char pad[3];
+
+ CheckLock(dpy);
+ if (size == 0) return;
+ _XRead( dpy, data, size );
+ if ( padlength[size & 3] ) {
+ _XRead( dpy, pad, padlength[size & 3] );
+ }
+
+}
+#endif /* VMS */
+
+/* _____________ LEVEL 2 DPS/PROTOCOL 9 ADDITIONS _____________ */
+
+void
+XDPSLNotifyWhenReady(
+ Display *xdpy,
+ ContextXID cxid,
+ int val[4])
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xPSNotifyWhenReadyReq *req;
+
+ if (version[dpyix] < DPSPROTO_V09)
+ {
+ DPSWarnProc(NULL, "Attempted use of XDPSLNotifyWhenReady with incompatible server ignored");
+ return; /* PROTO 9 or later only */
+ }
+
+ if (dpy != xdpy)
+ {
+ register int syncMask = displayFlags[dpyix].syncMask;
+
+ if (syncMask & DPSCAP_SYNCMASK_RECONCILE)
+ XDPSLReconcileRequests(xdpy, cxid);
+
+ /* If this context got paused, no matter how, ignore
+ mode and resume it */
+ if (gTotalPaused && DPSCAPResumeContext(xdpy, cxid))
+ {
+ /* xdpy was flushed by DPSCAPResumeContext */
+ if (gAutoFlush)
+ N_XFlush(dpy);
+ }
+ else if (syncMask & DPSCAP_SYNCMASK_SYNC)
+ XSync(xdpy, False);
+ }
+ LockDisplay(dpy);
+
+ NXMacroGetReq(PSNotifyWhenReady, req);
+ req->reqType = MajorOpCode(xdpy);
+ req->dpsReqType = X_PSNotifyWhenReady;
+ req->cxid = cxid;
+ req->val1 = val[0];
+ req->val2 = val[1];
+ req->val3 = val[2];
+ req->val4 = val[3];
+
+ if (gAutoFlush && dpy != xdpy)
+ {
+ N_XFlush(dpy);
+ }
+ UnlockDisplay(dpy);
+ SyncHandle();
+ if (dpy != xdpy)
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+}
+
+XDPSLPSErrors
+XDPSLTestErrorCode(Display *dpy, int ecode)
+{
+ XExtCodes *c = XDPSLGetCodes(dpy);
+
+ if (c == NULL)
+ return not_pserror;
+
+ switch (ecode - c->first_error)
+ {
+ case PSERRORBADCONTEXT: return(pserror_badcontext);
+ case PSERRORBADSPACE: return(pserror_badspace);
+ case PSERRORABORT:
+ if (version[DPY_NUMBER(dpy)] < DPSPROTO_V09)
+ return(not_pserror);
+ else
+ return(pserror_abort);
+ default: return(not_pserror);
+ }
+}
+
+/* _____________ CLIENT SIDE DPS ADDITIONS _____________ */
+
+/* === NEW HOOKS INTO XDPS === */
+
+void
+XDPSLSetVersion(Display *dpy, unsigned ver)
+{
+ version[DPY_NUMBER(dpy)] = ver;
+}
+
+void
+XDPSLSetCodes(Display *dpy, XExtCodes *codes)
+{
+ Codes[DPY_NUMBER(dpy)] = codes;
+}
+
+Display *
+XDPSLGetShunt(Display *dpy_in)
+{
+ return(ShuntMap[DPY_NUMBER(dpy_in)]);
+}
+
+void
+XDPSLSetShunt(Display *dpy_in, Display *dpy_out)
+{
+ ShuntMap[DPY_NUMBER(dpy_in)] = dpy_out;
+}
+
+int
+XDPSLGetSyncMask(Display *dpy)
+{
+ return (int)displayFlags[DPY_NUMBER(dpy)].syncMask;
+}
+
+void
+XDPSLSetSyncMask(Display *dpy, int mask)
+{
+ displayFlags[DPY_NUMBER(dpy)].syncMask = (char)mask;
+ gForceFlush = (mask & DPSCAP_SYNCMASK_RECONCILE);
+}
+
+void
+XDPSLFlush(Display *xdpy)
+{
+ register Display *dpy = ShuntMap[DPY_NUMBER(xdpy)];
+
+ _XFlush(xdpy);
+ if (dpy != xdpy)
+ N_XFlush(dpy);
+}
+
+void
+XDPSLSyncGCClip(Display *xdpy, GC gc)
+{
+ register unsigned long oldDirty;
+ register int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+
+ /* We DON'T want to notice all gc changes, just the clip */
+ oldDirty = gc->dirty;
+ gc->dirty = (GCClipXOrigin|GCClipYOrigin);
+ XDPSLFlushGC(xdpy, gc);
+ gc->dirty = oldDirty;
+ if (dpy == xdpy || gNXSyncGCMode != 1) /* 1 means sync always */
+ {
+ /* For DPS NX and SLOW mode, flushing the gc cache has
+ the side-effect of synching agent and server connections.
+ So, to have consistent behavior, we sync for the DPS/X
+ or FAST cases too. */
+
+ if (GCFlushMode[dpyix] == XDPSNX_GC_UPDATES_FAST
+ || dpy == xdpy)
+ XDPSLSync(xdpy);
+ }
+}
+
+
+#ifdef VMS
+void
+XDPSLSetDisplay(Display *dpy)
+{
+ dpys[DPY_NUMBER(dpy)] = dpy;
+}
+#endif /* VMS */
+
+char *
+XDPSLSetAgentName(Display *dpy, char *name, int deflt)
+{
+ char *old;
+
+ if (gCSDPS == NULL)
+ DPSCAPStartUp();
+ if (deflt)
+ {
+ old = gCSDPS->defaultAgentName;
+ gCSDPS->defaultAgentName = name;
+ }
+ else
+ {
+ old = gCSDPS->map[DPY_NUMBER(dpy)];
+ gCSDPS->map[DPY_NUMBER(dpy)] = name;
+ }
+ return(old);
+}
+
+
+void
+XDPSLSetClientMessageHandler(Display *dpy)
+{
+ if (dpy == NULL) return;
+ ClientMsgProc[DPY_NUMBER(dpy)] = XESetWireToEvent(
+ dpy,
+ ClientMessage,
+ DPSCAPClientMessageProc);
+}
+
+void
+XDPSLSetAfterProc(Display *xdpy)
+{
+ if (xdpy == NULL) return;
+ AfterProcs[DPY_NUMBER(xdpy)] = (GenericProcPtrReturnsInt)
+ XSetAfterFunction(xdpy, DPSCAPAfterProc);
+ /* +++ Consider using agent->synchandler to store old proc */
+}
+
+
+CSDPSFakeEventTypes
+XDPSLGetCSDPSFakeEventType(Display *dpy, XEvent *event)
+{
+ XExtCodes *codes = Codes[DPY_NUMBER(dpy)];
+ XExtData *extData;
+ DPSCAPData my;
+
+ if (event->type != ClientMessage || codes == NULL)
+ return(csdps_not);
+ extData = XFindOnExtensionList(
+ CSDPSHeadOfDpyExt(dpy),
+ codes->extension);
+ if (!extData)
+ return(csdps_not);
+ my = (DPSCAPData) extData->private_data;
+
+ if (event->xclient.message_type == my->typePSOutput)
+ return(csdps_output);
+ if (event->xclient.message_type == my->typePSOutputWithLen)
+ return(csdps_output_with_len);
+ if (event->xclient.message_type == my->typePSStatus)
+ return(csdps_status);
+ if (event->xclient.message_type == my->typeNoop)
+ return(csdps_noop);
+ if (event->xclient.message_type == my->typePSReady)
+ return(csdps_ready);
+ return(csdps_not);
+}
+
+Bool
+XDPSLDispatchCSDPSFakeEvent(
+ Display *dpy,
+ XEvent *event,
+ CSDPSFakeEventTypes t)
+{
+ register XDPSLOutputEvent *oce;
+ register DPSCAPOutputEvent *oev;
+ XDPSLOutputEvent fakeOutput;
+ XExtCodes *codes = Codes[DPY_NUMBER(dpy)];
+
+ if (codes == NULL)
+ return(False);
+
+ /* Fake up an event in the client's format. Bypasses
+ extension wire-to-event conversion */
+ switch (t)
+ {
+ case csdps_output:
+ oce = &fakeOutput;
+ oev = (DPSCAPOutputEvent *)event->xclient.data.b;
+ oce->length = DPSCAP_BYTESPEROUTPUTEVENT;
+ goto samo_samo;
+ case csdps_output_with_len:
+ oce = &fakeOutput;
+ oev = (DPSCAPOutputEvent *)event->xclient.data.b;
+ oce->length = oev->data[DPSCAP_DATA_LEN];
+samo_samo:
+ oce->type = codes->first_event + PSEVENTOUTPUT;
+ oce->serial = event->xclient.serial;
+ oce->send_event = True; /* ??? */
+ oce->display = dpy;
+ oce->cxid = oev->cxid;
+ bcopy((char *) oev->data, oce->data, oce->length);
+ XDPSLCallOutputEventHandler(dpy, (XEvent *) oce);
+ break;
+ case csdps_status:
+ {
+ register XDPSLStatusEvent *sce;
+ register DPSCAPStatusEvent *sev;
+ XDPSLStatusEvent fakeStatus;
+
+ sev = (DPSCAPStatusEvent *)event->xclient.data.b;
+ sce = &fakeStatus;
+ sce->type = codes->first_event + PSEVENTSTATUS;
+ sce->serial = event->xclient.serial;
+ sce->send_event = True; /* ??? */
+ sce->display = dpy;
+ sce->status = sev->status;
+ sce->cxid = sev->cxid;
+ XDPSLCallStatusEventHandler(dpy, (XEvent *) sce);
+ break;
+ }
+ case csdps_ready: /* L2-DPS/PROTO 9 addition */
+ {
+ register XDPSLReadyEvent *rce;
+ XDPSLReadyEvent fakeReady;
+
+ rce = &fakeReady;
+ rce->type = codes->first_event + PSEVENTREADY;
+ rce->serial = event->xclient.serial;
+ rce->send_event = True;
+ rce->display = dpy;
+ rce->cxid = event->xclient.data.l[0];
+ rce->val[0] = event->xclient.data.l[1];
+ rce->val[1] = event->xclient.data.l[2];
+ rce->val[2] = event->xclient.data.l[3];
+ rce->val[3] = event->xclient.data.l[4];
+ XDPSLCallReadyEventHandler(dpy, (XEvent *) rce);
+ break;
+ }
+ default:
+ return(False);
+ }
+ return(True);
+}
+
+void
+XDPSLGetCSDPSStatus(
+ Display *xdpy,
+ XEvent *event,
+ void **ret_ctxt,
+ int *ret_status)
+{
+ register DPSCAPStatusEvent *sev;
+
+ /* Assert: event is ClientMessage with typePSStatus */
+ sev = (DPSCAPStatusEvent *)event->xclient.data.b;
+
+ if (ret_ctxt != NULL)
+ *ret_ctxt = XDPSContextFromXID(xdpy, sev->cxid);
+ if (ret_status != NULL)
+ *ret_status = sev->status;
+}
+
+void
+XDPSLGetCSDPSReady(
+ Display *xdpy,
+ XEvent *event,
+ void **ret_ctxt,
+ int *ret_val)
+{
+ /* Assert: event is ClientMessage with typePSReady */
+
+ if (ret_ctxt != NULL)
+ *ret_ctxt =
+ XDPSContextFromXID(xdpy, (ContextXID)event->xclient.data.l[0]);
+ if (ret_val != NULL)
+ {
+ ret_val[0] = event->xclient.data.l[1];
+ ret_val[1] = event->xclient.data.l[2];
+ ret_val[2] = event->xclient.data.l[3];
+ ret_val[3] = event->xclient.data.l[4];
+ }
+}
+
+void
+XDPSLCAPNotify(
+ Display *xdpy,
+ ContextXID cxid,
+ unsigned int ntype, /* should this be an enum?? %%% */
+ unsigned int data,
+ unsigned int extra)
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ register xCAPNotifyReq *req;
+
+ if (dpy == xdpy) return;
+
+ /* We _have_ to sync client and server here in order to guarantee
+ correct execution sequencing. We call this procedure alot
+ to keep track of GC's going away, so this is a major
+ performance hit. */
+ if (ntype == DPSCAPNOTE_FREEGC)
+ XSync(xdpy, False);
+
+ LockDisplay(dpy);
+
+ NXMacroGetReq(CAPNotify, req);
+ req->reqType = DPSCAPOPCODEBASE;
+ req->type = X_CAPNotify;
+ req->cxid = cxid;
+ req->notification = ntype;
+ req->data = data;
+ req->extra = extra;
+
+ if (gAutoFlush)
+ N_XFlush(dpy);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+}
+
+void
+XDPSLSync(Display *xdpy)
+{
+ register Display *dpy = ShuntMap[DPY_NUMBER(xdpy)];
+
+ if (dpy == xdpy)
+ {
+ /* DPS/X */
+ XSync(dpy, False);
+ }
+ else
+ {
+ /* CSDPS */
+ XEvent event;
+ DPSCAPData my;
+ XExtData *extData;
+ XExtCodes *codes = Codes[DPY_NUMBER(xdpy)];
+
+ if (codes == NULL)
+ return;
+ /* Get private data */
+ extData = XFindOnExtensionList(
+ CSDPSHeadOfDpyExt(xdpy),
+ codes->extension);
+ if (!extData)
+ return;
+ my = (DPSCAPData) extData->private_data;
+ my->saveseq = XNextRequest(dpy)-1;
+ /* first send notification to agent */
+ XDPSLCAPNotify(xdpy, 0, DPSCAPNOTE_SYNC, my->saveseq, 0);
+#ifdef XXX
+fprintf(stderr, "\nXDPSLSync(DPSCAPNOTE_SYNC) sending ... ");
+#endif
+ _XFlush(xdpy);
+ N_XFlush(dpy);
+#ifdef XXX
+fprintf(stderr, "sent.\nWaiting for reply ... ");
+#endif
+ /* agent should send a ClientMessage, so wait for it */
+ XIfEvent(xdpy, &event, WaitForSyncProc, (char *) my);
+
+#ifdef XXX
+fprintf(stderr, "received.\n");
+#endif
+ /* now client, agent, and server are synchronized */
+ }
+}
+
+void
+XDPSLReconcileRequests(Display *xdpy, ContextXID cxid)
+{
+ int dpyix;
+ unsigned int seqnum;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+
+ if (dpy == xdpy)
+ return; /* No-op for DPS/X */
+
+ /* Get the sequence number and set the pause flag
+ IFF we are sure that some X protocol has occurred
+ since the last time we did a DPS request. This
+ minimizes pause/resume requests */
+
+ if (LastXRequest[dpyix] == XNextRequest(xdpy)-1)
+ {
+ if (gAutoFlush)
+ N_XFlush(dpy); /* This is what XDPSLCAPNotify would do */
+ return;
+ }
+ else
+ seqnum = DPSCAPSetPause(xdpy, cxid);
+
+ /* Pause the context specified. */
+ XDPSLCAPNotify(xdpy, cxid, DPSCAPNOTE_PAUSE, seqnum, 0);
+
+ /* We don't even need to flush. All we have to do is make
+ sure that the notify request is queued before any
+ DPS requests that follow. */
+}
+
+Status
+XDPSLSetAgentArg(Display *xdpy, int arg, int val)
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+ CARD32 capArg;
+ register xCAPSetArgReq *req;
+
+ if (dpy == xdpy)
+ return(Success); /* No-op for DPS/X */
+
+ /* dpy will be NIL if we haven't opened a connection yet,
+ but that's okay since we need to save the value anyway. */
+
+ if (dpy)
+ {
+ int syncMask = displayFlags[dpyix].syncMask;
+
+ /* ASSERT: There is no reason to pause the context for this
+ request, so just sync. */
+ if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
+ XSync(xdpy, False);
+ }
+
+ switch (arg)
+ {
+ case AGENT_ARG_SMALLFONTS:
+ AgentArgs[dpyix].showSmallSizes = val;
+ capArg = DPSCAP_ARG_SMALLFONTS;
+ break;
+ case AGENT_ARG_PIXMEM:
+ AgentArgs[dpyix].pixMem = val;
+ capArg = DPSCAP_ARG_PIXMEM;
+ break;
+ default:
+ return(!Success);
+ }
+ if (!dpy)
+ return(Success);
+
+ LockDisplay(dpy);
+
+ NXMacroGetReq(CAPSetArg, req);
+ req->reqType = DPSCAPOPCODEBASE;
+ req->type = X_CAPSetArg;
+ req->arg = capArg;
+ req->val = val;
+
+ if (gAutoFlush)
+ N_XFlush(dpy);
+
+ UnlockDisplay(dpy);
+ SyncHandle();
+ LastXRequest[dpyix] = XNextRequest(xdpy)-1;
+ return(Success);
+}
+
+
+void
+XDPSLCleanAll(xdpy)
+ register Display *xdpy;
+{
+ /* Clean up all state associated with dpy */
+ register DPSCAPPausedContextData *slot;
+ int dpyix = DPY_NUMBER(xdpy);
+
+ /* Clean up paused context list */
+ for (slot = PausedPerDisplay[dpyix]; slot; slot = PausedPerDisplay[dpyix])
+ {
+ PausedPerDisplay[dpyix] = slot->next;
+ Xfree(slot);
+ }
+
+ /* Clear agent args */
+ AgentArgs[dpyix].showSmallSizes = 0;
+ AgentArgs[dpyix].pixMem = 0;
+}
+
+void
+XDPSLUpdateAgentArgs(xdpy)
+ register Display *xdpy;
+{
+ int dpyix = DPY_NUMBER(xdpy);
+
+ if (AgentArgs[dpyix].showSmallSizes)
+ XDPSLSetAgentArg(xdpy, AGENT_ARG_SMALLFONTS, AgentArgs[dpyix].showSmallSizes);
+ if (AgentArgs[dpyix].pixMem)
+ XDPSLSetAgentArg(xdpy, AGENT_ARG_PIXMEM, AgentArgs[dpyix].pixMem);
+}
+
+void
+XDPSLCleanContext(xdpy, cxid)
+ Display *xdpy;
+ ContextXID cxid;
+{
+ /* Clean up all state associated with cxid on this dpy */
+ register DPSCAPPausedContextData *slot, *prev;
+ int dpyix = DPY_NUMBER(xdpy);
+
+ /* If this is DPS/X, then slot will never have been initialized.
+ See XDPSLNotifyContext */
+
+ /* Clean up paused context list */
+ prev = (DPSCAPPausedContextData *)NULL;
+ for (slot = PausedPerDisplay[dpyix]; slot; prev = slot, slot = slot->next)
+ {
+ if (slot->cxid != cxid)
+ continue;
+ if (!prev)
+ PausedPerDisplay[dpyix] = slot->next;
+ else
+ prev->next = slot->next;
+ Xfree(slot);
+ break;
+ }
+}
+
+/* DPS NX 2.0 */
+void
+XDPSLSetGCFlushMode(dpy, value)
+ Display *dpy;
+ int value;
+{
+ int dpyix;
+ register Display *agent = ShuntMap[dpyix = DPY_NUMBER(dpy)];
+
+ if (value != XDPSNX_GC_UPDATES_SLOW && value != XDPSNX_GC_UPDATES_FAST)
+ {
+ DPSWarnProc(NULL, "DPS NX: Bogus GC flush mode.\n");
+ return;
+ }
+ /* 0 means no NX */
+ GCFlushMode[dpyix] = (agent == dpy) ? 0 : value;
+}
+
+int
+XDPSLGetGCFlushMode(dpy)
+ Display *dpy;
+{
+ return(GCFlushMode[DPY_NUMBER(dpy)]);
+}
+
+void
+XDPSLFlushGC(xdpy, gc)
+ Display *xdpy;
+ GC gc;
+{
+ int dpyix;
+ register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
+
+ if (!gc->dirty) return;
+
+ if (GCFlushMode[dpyix] == XDPSNX_GC_UPDATES_FAST)
+ {
+ XGCValues vals;
+ static unsigned long valuemask = DPSGCBITS & ~(GCClipMask);
+
+ /* Okay to call Xlib, since dpy isn't locked */
+ DPSAssertWarn(XGetGCValues(xdpy, gc, valuemask, &vals),
+ NULL, "DPS NX: XGetGCValues returned False\n");
+ vals.clip_mask = gc->values.clip_mask;
+ LockDisplay(dpy);
+ DPSCAPChangeGC(dpy, gc, DPSGCBITS, &vals);
+ UnlockDisplay(dpy);
+ SyncHandle();
+ }
+ /* Fall thru. Either the GCFlushMode is SLOW, which means
+ we will DPSCAPChangeGC as a side-effect of FlushGC when
+ the GC hook is called, or we just did it in the FAST case. */
+ FlushGC(xdpy, gc);
+ XDPSLFlush(xdpy);
+}
+
+/* === PRIVATE CSDPS PROCS === */
+
+static Status
+DPSCAPClientMessageProc(
+ Display *dpy,
+ XEvent *re,
+ xEvent *event)
+{
+ register XDPSLOutputEvent *oce;
+ register DPSCAPOutputEvent *oev;
+ XDPSLOutputEvent fakeOutput;
+ XExtCodes *codes = Codes[DPY_NUMBER(dpy)];
+ PSCMProc oldProc = ClientMsgProc[DPY_NUMBER(dpy)];
+
+ if (codes != NULL)
+ {
+ /* Get private data */
+ XExtData *extData = XFindOnExtensionList(
+ CSDPSHeadOfDpyExt(dpy),
+ codes->extension);
+ DPSCAPData my;
+
+ /* There's no extension, or there is an extension but we are
+ passing events uninterpreted, so just pass it along
+ unless it is a DPSCAP error. */
+
+ if (!extData)
+ goto pass_the_buck;
+ my = (DPSCAPData) extData->private_data;
+ if (XDPSLGetPassEventsFlag(dpy) &&
+ (event->u.clientMessage.u.l.type != my->typeXError))
+ goto pass_the_buck;
+
+ /* Fake up a DPS extension event and handle it transparently,
+ without going through the Xlib event queue */
+
+ if (event->u.clientMessage.u.b.type == my->typePSOutput)
+ {
+ oce = &fakeOutput;
+ oce->length = DPSCAP_BYTESPEROUTPUTEVENT;
+ oev = (DPSCAPOutputEvent *)event->u.clientMessage.u.b.bytes;
+ goto common_stuff;
+ }
+ else if (event->u.clientMessage.u.b.type == my->typePSOutputWithLen)
+ {
+ oce = &fakeOutput;
+ oev = (DPSCAPOutputEvent *)event->u.clientMessage.u.b.bytes;
+ oce->length = oev->data[DPSCAP_DATA_LEN];
+common_stuff:
+ oce->type = codes->first_event + PSEVENTOUTPUT;
+ oce->serial = _XSetLastRequestRead(dpy, (xGenericReply *)event);
+ oce->send_event = True; /* ??? */
+ oce->display = dpy;
+ oce->cxid = oev->cxid;
+ bcopy((char *) oev->data, oce->data, oce->length);
+ /* We've converted the event, give it to DPS */
+ if (TextProc)
+ (*TextProc)((XEvent *) oce);
+ return(False);
+ }
+ else if (event->u.clientMessage.u.b.type == my->typePSStatus)
+ {
+ register XDPSLStatusEvent *sce;
+ register DPSCAPStatusEvent *sev;
+ XDPSLStatusEvent fakeStatus;
+
+ sev = (DPSCAPStatusEvent *)event->u.clientMessage.u.b.bytes;
+ sce = &fakeStatus;
+ sce->type = codes->first_event + PSEVENTSTATUS;
+ sce->serial = _XSetLastRequestRead(dpy, (xGenericReply *)event);
+ sce->send_event = True; /* ??? */
+ sce->display = dpy;
+ sce->cxid = sev->cxid;
+ sce->status = sev->status;
+ /* We've converted the event, give it to DPS */
+ if (StatusProc[DPY_NUMBER(dpy)])
+ (*(StatusProc[DPY_NUMBER(dpy)]))((XEvent *) sce);
+ return(False);
+ }
+ else if (event->u.clientMessage.u.l.type == my->typeXError)
+ {
+ xError err;
+ register xError *e = &err;
+
+ e->type = X_Error;
+ e->errorCode = event->u.clientMessage.u.l.longs0;
+ e->sequenceNumber = event->u.u.sequenceNumber;
+ e->resourceID = event->u.clientMessage.u.l.longs3;
+ e->minorCode = event->u.clientMessage.u.l.longs2;
+ e->majorCode = event->u.clientMessage.u.l.longs1;
+ /* Smash the wire event here, before going off deep end */
+ event->u.clientMessage.u.l.type = my->typeNoop;
+ /* Jump! */
+ return(_XError(dpy, e));
+ }
+ else if (event->u.clientMessage.u.l.type == my->typePSReady)
+ /* L2-DPS/PROTO 9 addition */
+ {
+ register XDPSLReadyEvent *rce;
+ XDPSLReadyEvent fakeReady;
+
+ rce = &fakeReady;
+ rce->type = codes->first_event + PSEVENTREADY;
+ rce->serial = _XSetLastRequestRead(dpy, (xGenericReply *)event);
+ rce->send_event = True;
+ rce->display = dpy;
+ rce->cxid = event->u.clientMessage.u.l.longs0;
+ rce->val[0] = event->u.clientMessage.u.l.longs1;
+ rce->val[1] = event->u.clientMessage.u.l.longs2;
+ rce->val[2] = event->u.clientMessage.u.l.longs3;
+ rce->val[3] = event->u.clientMessage.u.l.longs4;
+ XDPSLCallReadyEventHandler(dpy, (XEvent *) rce);
+ return(False);
+ }
+ }
+
+ /* Put the event on the queue, so that Xlib is happy */
+pass_the_buck:
+ return(oldProc(dpy, re, event));
+}
+
+
+static void
+DPSCAPInitGC(Display *dpy, Display *agent, GC gc)
+{
+ XGCValues values;
+ unsigned long valuemask = DPSGCBITS & ~(GCClipMask);
+
+ /* Okay to call Xlib, since dpy isn't locked */
+ DPSAssertWarn(XGetGCValues(dpy, gc, valuemask, &values),
+ NULL, "DPS NX: XGetGCValues returned False\n");
+ values.clip_mask = gc->values.clip_mask;
+ DPSCAPChangeGC(agent, gc, DPSGCBITS, &values);
+ SyncHandle();
+ XDPSLSync(dpy);
+}
+
+
+/* ARGSUSED */
+
+static Bool
+WaitForSyncProc(Display *xdpy, XEvent *event, char *arg)
+{
+ DPSCAPData my = (DPSCAPData)arg;
+
+ if ((event->type & 0x7F) == ClientMessage
+ && event->xclient.message_type == my->typeSync
+ && event->xclient.data.l[0] == (long) my->saveseq) {
+ return(True);
+ } else {
+ return(False);
+ }
+}
+
+
+static int
+DPSCAPAfterProc(Display *xdpy)
+{
+ register Display *dpy = ShuntMap[DPY_NUMBER(xdpy)];
+ GenericProcPtrReturnsInt proc;
+
+ if (dpy != (Display *)NULL && dpy != xdpy)
+ {
+ LockDisplay(dpy);
+ N_XFlush(dpy);
+ UnlockDisplay(dpy);
+ LockDisplay(xdpy);
+ _XFlush(xdpy);
+ UnlockDisplay(xdpy);
+ }
+ if ((proc = AfterProcs[DPY_NUMBER(xdpy)]) != NULL)
+ return((*proc)(xdpy));
+ else
+ return(0);
+}
+
+
+static unsigned int
+DPSCAPSetPause(Display *xdpy, ContextXID cxid)
+{
+ register DPSCAPPausedContextData *slot;
+ int dpyix;
+ unsigned int ret;
+
+ /* Find or create slot */
+
+ slot = PausedPerDisplay[dpyix = DPY_NUMBER(xdpy)];
+ if (!slot)
+ {
+ slot = (DPSCAPPausedContextData *)
+ Xcalloc(1, sizeof(DPSCAPPausedContextData));
+ PausedPerDisplay[dpyix] = slot;
+ goto common_code;
+ /* IMPLICATION: it is okay to fall through common_code
+ and do test_ret. */
+ }
+ while (1)
+ if (slot->cxid == cxid)
+ {
+ if (!slot->paused)
+ {
+ slot->paused = True;
+ ++gTotalPaused;
+ }
+ /* Back-to-back pauses get different sequence numbers */
+ ret = ++slot->seqnum;
+ goto test_ret;
+ }
+ else if (slot->next) slot = slot->next;
+ else break;
+ /* cxid wasn't found, so add it */
+ /* ASSERT: slot points to last record of the list */
+ slot->next = (DPSCAPPausedContextData *)
+ Xcalloc(1, sizeof(DPSCAPPausedContextData));
+ slot = slot->next;
+common_code:
+ slot->paused = True;
+ ++gTotalPaused;
+ slot->cxid = cxid;
+ ret = ++slot->seqnum;
+test_ret:
+ if (!ret)
+ {
+ DPSWarnProc(NULL, "Pause sequence wrapped around!");
+ }
+ return(ret);
+}
+
+static Bool
+DPSCAPResumeContext(Display *xdpy, ContextXID cxid)
+{
+ register DPSCAPPausedContextData *slot;
+ int dpyix = DPY_NUMBER(xdpy);
+
+ /* Try to match cxid to list of paused contexts */
+ for (slot = PausedPerDisplay[dpyix]; slot; slot = slot->next)
+ if (slot->cxid == cxid && slot->paused)
+ {
+ /* Send resume event */
+ register XClientMessageEvent *ee;
+ XEvent e;
+ XExtData *extData;
+ DPSCAPData my;
+ XExtCodes *codes = Codes[dpyix];
+
+ extData = XFindOnExtensionList(
+ CSDPSHeadOfDpyExt(xdpy),
+ codes->extension);
+ if (!extData)
+ return(False);
+ my = (DPSCAPData) extData->private_data;
+
+ ee = &e.xclient;
+ ee->type = ClientMessage;
+ ee->display = xdpy;
+ ee->window = my->agentWindow;
+ ee->format = 32;
+ ee->message_type = my->typeResume;
+ ee->data.l[0] = cxid;
+ ee->data.l[1] = slot->seqnum;
+ (void) XSendEvent(
+ xdpy,
+ my->agentWindow,
+ False,
+ NoEventMask,
+ &e);
+ XFlush(xdpy);
+ /* Turn off flag */
+ slot->paused = False;
+ --gTotalPaused;
+ return(True);
+ }
+ /* Fall thru */
+ return(False);
+}