aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/lib/dps/cslibext.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/lib/dps/cslibext.c')
-rw-r--r--nx-X11/lib/dps/cslibext.c762
1 files changed, 762 insertions, 0 deletions
diff --git a/nx-X11/lib/dps/cslibext.c b/nx-X11/lib/dps/cslibext.c
new file mode 100644
index 000000000..831f0ad65
--- /dev/null
+++ b/nx-X11/lib/dps/cslibext.c
@@ -0,0 +1,762 @@
+/*
+ * cslibext.c -- DPSCAP client Xlib extension hookup
+ *
+ * (c) Copyright 1991-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/cslibext.c,v 1.4tsi Exp $ */
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <sys/param.h> /* for MAXHOSTNAMELEN */
+#include <X11/X.h>
+#include <X11/Xlib.h>
+#include <X11/Xlibint.h>
+#include "cslibint.h"
+#include <DPS/XDPS.h>
+#include <DPS/XDPSproto.h>
+#include <DPS/dpsXclient.h>
+#include <DPS/dpsNXargs.h>
+#include "DPSCAPClient.h"
+#include "dpsassert.h"
+#include <DPS/XDPSlib.h>
+
+#include "publictypes.h"
+#include "dpsXpriv.h"
+
+/* === DEFINES === */
+
+#define DPSNXSYNCGCMODE_FLUSH 0
+#define DPSNXSYNCGCMODE_SYNC 1
+#define DPSNXSYNCGCMODE_DELAYED 2
+#define DPSNXSYNCGCMODE_DEFAULT DPSNXSYNCGCMODE_DELAYED
+
+/* === GLOBALS === */
+
+DPSCAPGlobals gCSDPS = NULL;
+
+#ifdef DPSLNKL
+#define ANXCYAN
+#define ANXMAGENTA
+#define ANXYELLOW
+#define ANXBLACK
+#define ANXSPOT
+#include "dpslnkl.inc"
+#endif /* DPSLNKL */
+
+int gNXSyncGCMode = DPSNXSYNCGCMODE_DEFAULT;
+
+/* === PUBLIC PROCS === */
+
+#ifdef MAHALO
+static int
+DPSCAPFlushAfterProc(Display *agent)
+{
+ LockDisplay(agent);
+ N_XFlush(agent);
+ UnlockDisplay(agent);
+}
+#endif
+
+int
+CSDPSInit(
+ Display *dpy,
+ int *numberType, /* RETURN */
+ char **floatingName) /* RETURN */
+{
+ register Display *agent;
+ register xCAPConnReplyPrefix *p;
+ register char *c;
+ DPSCAPData my;
+ xCAPConnSetupReq setup;
+ union {
+ xCAPConnSuccess good;
+ xCAPConnFailed bad;
+ } reply;
+ XExtData *extData;
+ XExtCodes *codes;
+ int indian;
+ int rest;
+ Window clientWindow;
+ char fullDisplayName[MAXHOSTNAMELEN+10];
+
+ if (gCSDPS == NULL)
+ DPSCAPStartUp();
+
+ /* To fix dps-nx #68, Motif too slow on HP */
+ if ((c = getenv("DPSNXGCMODE")) != 0)
+ {
+ gNXSyncGCMode = atoi(c);
+ if (gNXSyncGCMode < DPSNXSYNCGCMODE_FLUSH
+ || gNXSyncGCMode > DPSNXSYNCGCMODE_DELAYED)
+ gNXSyncGCMode = DPSNXSYNCGCMODE_DEFAULT;
+ }
+
+ /* We may have already called this routine via XDPSExtensionPresent,
+ so don't do it again! */
+
+ if ((codes = XDPSLGetCodes(dpy))
+ && (agent = XDPSLGetShunt(dpy))
+ && agent != dpy
+ && codes->major_opcode == DPSXOPCODEBASE)
+ return(DPSCAPSUCCESS);
+
+ /* Try to create a window for ClientMessage communication */
+
+ clientWindow = XCreateSimpleWindow(
+ dpy,
+ DefaultRootWindow(dpy),
+ 0, 0,
+ 1, 1,
+ 0,
+ BlackPixel(dpy, DefaultScreen(dpy)),
+ WhitePixel(dpy, DefaultScreen(dpy)));
+ if (clientWindow == None)
+ return(DPSCAPFAILED);
+
+ /* Try to open a connection to an agent */
+
+ if ((extData = DPSCAPOpenAgent(dpy, fullDisplayName)) == NULL)
+ {
+ XDestroyWindow(dpy, clientWindow);
+ return(DPSCAPFAILED);
+ }
+
+ /* DPSCAPOpenAgent only partially fills in extData, so finish it */
+
+ codes = XAddExtension(dpy);
+ codes->major_opcode = DPSXOPCODEBASE;
+ codes->first_event = 0; /* REQUIRED */
+ codes->first_error = FirstExtensionError;
+ extData->number = codes->extension;
+ extData->free_private = DPSCAPDestroy;
+ my = (DPSCAPData) extData->private_data;
+ my->codes = codes;
+ agent = my->agent;
+ /* +++ Is this all we have to do here? */
+
+ /* Send opening handshake */
+
+ indian = 1;
+ if (*(char *) &indian)
+ setup.byteorder = 'l';
+ else
+ setup.byteorder = 'B';
+ setup.dpscapVersion = DPSCAPPROTOVERSION;
+ setup.flags = DPSCAPNONEFLAG;
+ setup.libraryversion = DPSPROTOCOLVERSION;
+ setup.authProtoNameLength = 0;
+ setup.authProtoDataLength = 0;
+ setup.displayStringLength = strlen(fullDisplayName);
+ setup.nodeStringLength = 0;
+ setup.transportStringLength = 0;
+ setup.display = 0;
+ setup.screen = 0;
+ setup.reserved = 0;
+ setup.clientWindow = clientWindow;
+
+#ifndef DPSLNKL
+ DPSCAPWrite(agent, (char *)&setup, sizeof(xCAPConnSetupReq), dpscap_nopad,dpscap_insert);
+ DPSCAPWrite(agent, fullDisplayName, setup.displayStringLength, dpscap_pad, dpscap_append);
+ N_XFlush(agent);
+#else /* DPSLNKL */
+ if (CSDPSConfirmDisplay(agent, dpy, &setup, &reply, fullDisplayName) == 1)
+ {
+ p = (xCAPConnReplyPrefix *)&reply.good;
+ goto skip_read;
+ }
+ /* Read normal reply */
+#endif /* DPSLNKL */
+
+ /* Read common reply prefix */
+
+ p = (xCAPConnReplyPrefix *)&reply.good;
+ N_XRead(agent, (char *)p, (long)sizeof(xCAPConnReplyPrefix));
+#ifdef DPSLNKL
+skip_read:
+#endif
+ if (!p->success)
+ {
+ char mbuf[512];
+ /* read the rest */
+ c = (char *)&reply.bad.serverVersion;
+ N_XRead(agent, c, sz_xCAPConnFailed - sz_xCAPConnReplyPrefix);
+ sprintf(mbuf, "DPS NX: connection to \"%s\" refused by agent.", DisplayString(agent));
+ DPSWarnProc(NULL, mbuf);
+ c = (char *)Xmalloc(reply.bad.reasonLength);
+ if (!c) return(DPSCAPFAILED);
+ N_XReadPad(agent, c, (long)reply.bad.reasonLength);
+ if (!reply.bad.reasonLength)
+ sprintf(mbuf, "DPS NX: (no reason given)\n");
+ else
+ {
+ strcpy(mbuf, "DPS NX: ");
+ strncat(mbuf, c, reply.bad.reasonLength);
+ mbuf[reply.bad.reasonLength+7] = '\0';
+ }
+ DPSWarnProc(NULL, mbuf);
+ Xfree(c);
+ DPSCAPDestroy(extData);
+ Xfree(extData);
+ XDestroyWindow(dpy, clientWindow);
+ return(DPSCAPFAILED);
+ }
+
+ /* read the rest of the fixed length reply */
+ c = (char *)&reply.good.serverVersion;
+ rest = sizeof(xCAPConnSuccess) - sizeof(xCAPConnReplyPrefix);
+ N_XRead(agent, c, rest);
+
+ /* verify */
+
+ if (reply.good.serverVersion < DPSPROTOCOLVERSION)
+ {
+ /* Fine, we downgrade the client */
+ char qbuf[256];
+ sprintf(qbuf, "NX: server version %ld older than expected %d, client will downgrade", (long)reply.good.serverVersion, DPSPROTOCOLVERSION);
+ DPSWarnProc(NULL, qbuf);
+ }
+ my->dpscapVersion = reply.good.dpscapVersion;
+ if (my->dpscapVersion < DPSCAPPROTOVERSION)
+ {
+ /* Fine, we downgrade the client */
+ char kbuf[256];
+ sprintf(kbuf, "NX: agent version %d older than expected %d, client will downgrade", my->dpscapVersion, DPSCAPPROTOVERSION);
+ DPSWarnProc(NULL, kbuf);
+#ifdef XXX
+ /* Saving this code as a reminder about what needs to be
+ cleaned up if we exit here */
+ DPSCAPDestroy(extData);
+ Xfree(extData);
+ XDestroyWindow(clientWindow);
+ return(DPSCAPFAILED);
+#endif
+ }
+
+ if (numberType)
+ *numberType = reply.good.preferredNumberFormat;
+
+ /* read additional data */
+
+ c = (char *)Xmalloc(reply.good.floatingNameLength + 1);
+ N_XReadPad(agent, c, reply.good.floatingNameLength);
+ c[reply.good.floatingNameLength] = 0;
+ if (floatingName)
+ *floatingName = c;
+ else
+ Xfree(c);
+
+ /* set library extension data */
+
+ XDPSLSetVersion(agent, reply.good.serverVersion);
+ XDPSLSetVersion(dpy, reply.good.serverVersion);
+ XDPSLSetShunt(dpy, agent);
+ XDPSLSetCodes(dpy, codes);
+ if (XDPSLGetSyncMask(dpy) == DPSCAP_SYNCMASK_NONE)
+ XDPSLSetSyncMask(dpy, DPSCAP_SYNCMASK_DFLT);
+ my->agentWindow = reply.good.agentWindow;
+ XDPSLSetGCFlushMode(dpy, XDPSNX_GC_UPDATES_SLOW); /* default */
+
+ /* Hook my extension data on the dpy */
+
+ my->extData = extData;
+ XAddToExtensionList(CSDPSHeadOfDpyExt(dpy), extData);
+ (void) XESetCloseDisplay(dpy, codes->extension, DPSCAPCloseDisplayProc);
+ (void) XESetCopyGC(dpy, codes->extension, DPSCAPCopyGCProc);
+ (void) XESetFreeGC(dpy, codes->extension, DPSCAPFreeGCProc);
+ (void) XESetFlushGC(dpy, codes->extension, DPSCAPFlushGCProc);
+ XDPSLSetClientMessageHandler(dpy);
+
+ /* Chain my data on global list */
+
+ my->next = gCSDPS->head;
+ gCSDPS->head = my;
+
+#ifdef MAHALO
+ /* Set function that is called after every Xlib protocol proc */
+ XDPSLSetAfterProc(dpy);
+
+ /* All CSDPS protocol is auto-flushed */
+ (void) XSetAfterFunction(agent, DPSCAPFlushAfterProc);
+#endif /* MAHALO */
+
+ /* set agent arguments, if needed */
+ /* must follow setting of ShuntMap at least, so safest to
+ do here when everything has been setup */
+ XDPSLUpdateAgentArgs(dpy);
+
+ return(DPSCAPSUCCESS);
+}
+
+
+XExtData **
+CSDPSHeadOfDpyExt(
+ Display *dpy)
+{
+ XEDataObject object;
+
+ object.display = dpy;
+ return(XEHeadOfExtensionList(object));
+}
+
+void
+XDPSSyncGCClip(
+ register Display *dpy,
+ register GC gc)
+{
+ /* The primary utility of this function is for DPS NX correctness,
+ but it also helps DPS/X do less work in tracking GC changes. */
+ XDPSLSyncGCClip(dpy, gc);
+}
+
+void
+XDPSReconcileRequests(
+ register DPSContext ctxt)
+{
+ Display *dpy;
+ register ContextXID cxid;
+ register DPSContext curCtxt;
+
+ for (curCtxt = ctxt; curCtxt; curCtxt = curCtxt->chainChild)
+ {
+ cxid = XDPSXIDFromContext(&dpy, curCtxt);
+ if (dpy == (Display *)NULL || cxid == None)
+ break; /* Skip text contexts */
+ XDPSLReconcileRequests(dpy, cxid);
+ }
+}
+
+Status
+XDPSNXSetAgentArg(
+ Display *dpy,
+ int arg, int val)
+{
+ if (!dpy || arg >= 0 || arg < AGENTLASTARG)
+ return(!Success);
+ else
+ return(XDPSLSetAgentArg(dpy, arg, val));
+}
+
+/* New for DPS NX 2.0 */
+void
+XDPSFlushGC(
+ Display *dpy,
+ GC gc)
+{
+ if (dpy && gc)
+ XDPSLFlushGC(dpy, gc);
+}
+
+/* === SUPPORT PROCS === */
+
+void
+DPSCAPChangeGC(
+ register Display *agent,
+ GC gc,
+ unsigned long valuemask,
+ XGCValues *values)
+{
+ register xChangeGCReq *req;
+ unsigned long oldDirty = gc->dirty;
+
+ /* ASSERT: called from within LockDisplay section */
+
+ /* Always include the clip_mask */
+ valuemask |= GCClipMask;
+ /* +++ HACK! Hide the gc->rects flag in arc_mode */
+ valuemask |= GCArcMode;
+ valuemask &= (1L << (GCLastBit + 1)) - 1;
+
+ /* Stupid macro insists on Display being called 'dpy' */
+ {
+ Display *dpy = agent;
+ Display *xdpy = (Display *)NULL;
+ NXMacroGetReq(ChangeGC, req);
+ }
+ req->gc = XGContextFromGC(gc);
+ gc->dirty = req->mask = valuemask;
+ {
+/* Derived from MIT XCrGC.c, _XGenerateGCList:
+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.
+*/
+ /* Warning! This code assumes that "unsigned int" is 32-bits wide */
+
+ unsigned int vals[32];
+ register unsigned int *value = vals;
+ long nvalues;
+ register XGCValues *gv = values;
+ register unsigned long dirty = gc->dirty;
+
+ /*
+ * Note: The order of these tests are critical; the order must be the
+ * same as the GC mask bits in the word.
+ */
+ if (dirty & GCFunction) *value++ = gv->function;
+ if (dirty & GCPlaneMask) *value++ = gv->plane_mask;
+ if (dirty & GCForeground) *value++ = gv->foreground;
+ if (dirty & GCBackground) *value++ = gv->background;
+ if (dirty & GCLineWidth) *value++ = gv->line_width;
+ if (dirty & GCLineStyle) *value++ = gv->line_style;
+ if (dirty & GCCapStyle) *value++ = gv->cap_style;
+ if (dirty & GCJoinStyle) *value++ = gv->join_style;
+ if (dirty & GCFillStyle) *value++ = gv->fill_style;
+ if (dirty & GCFillRule) *value++ = gv->fill_rule;
+ if (dirty & GCTile) *value++ = gv->tile;
+ if (dirty & GCStipple) *value++ = gv->stipple;
+ if (dirty & GCTileStipXOrigin) *value++ = gv->ts_x_origin;
+ if (dirty & GCTileStipYOrigin) *value++ = gv->ts_y_origin;
+ if (dirty & GCFont) *value++ = gv->font;
+ if (dirty & GCSubwindowMode) *value++ = gv->subwindow_mode;
+ if (dirty & GCGraphicsExposures) *value++ = gv->graphics_exposures;
+ if (dirty & GCClipXOrigin) *value++ = gv->clip_x_origin;
+ if (dirty & GCClipYOrigin) *value++ = gv->clip_y_origin;
+ if (dirty & GCClipMask) *value++ = gv->clip_mask;
+ if (dirty & GCDashOffset) *value++ = gv->dash_offset;
+ if (dirty & GCDashList) *value++ = gv->dashes;
+ /* +++ HACK! Hide gc->rects flag in GCArcMode */
+ if (dirty & GCArcMode) *value++ = gc->rects;
+
+ req->length += (nvalues = value - vals);
+
+ /*
+ * note: Data is a macro that uses its arguments multiple
+ * times, so "nvalues" is changed in a separate assignment
+ * statement
+ */
+
+ nvalues <<= 2;
+ Data32 (agent, (long *) vals, nvalues);
+ }
+
+ gc->dirty = oldDirty;
+
+ /* ASSERT: SyncHandle called by caller */
+}
+
+
+DPSCAPData
+DPSCAPCreate(
+ Display *dpy, Display *agent)
+{
+ register DPSCAPData my = (DPSCAPData)Xcalloc(1, sizeof(DPSCAPDataRec));
+
+ if (my == (DPSCAPData)NULL) return(NULL);
+ my->dpy = dpy;
+ my->agent = agent;
+ my->typePSOutput = XInternAtom(
+ dpy,
+ DPSCAP_TYPE_PSOUTPUT,
+ False);
+ my->typePSOutputWithLen = XInternAtom(
+ dpy,
+ DPSCAP_TYPE_PSOUTPUT_LEN,
+ False);
+ my->typePSStatus = XInternAtom(
+ dpy,
+ DPSCAP_TYPE_PSSTATUS,
+ False);
+ my->typeNoop = XInternAtom(
+ dpy,
+ DPSCAP_TYPE_NOOP,
+ False);
+ my->typeSync = XInternAtom(
+ dpy,
+ DPSCAP_TYPE_SYNC,
+ False);
+ my->typeXError = XInternAtom(
+ dpy,
+ DPSCAP_TYPE_XERROR,
+ False);
+ my->typePSReady = XInternAtom(
+ dpy,
+ DPSCAP_TYPE_PSREADY,
+ False);
+ my->typeResume = XInternAtom(
+ dpy,
+ DPSCAP_TYPE_RESUME,
+ False);
+ return(my);
+}
+
+int
+DPSCAPDestroy(
+ XExtData *extData)
+{
+ register DPSCAPData my = (DPSCAPData) extData->private_data;
+ register DPSCAPData n;
+
+ if (my == (DPSCAPData)NULL) return(0);
+ DPSCAPCloseAgent(my->agent);
+ my->agent = NULL;
+ /* my->extData->private_data = NIL; ???? +++ */
+ if (my == gCSDPS->head)
+ gCSDPS->head = my->next;
+ else for (n = gCSDPS->head; n != NULL; n = n->next)
+ if (n->next == my)
+ {
+ n->next = my->next;
+ break;
+ }
+ Xfree(my);
+ /* extData freed by caller (e.g., _XFreeExtData) */
+ return(0);
+}
+
+void
+DPSCAPStartUp(void)
+{
+ gCSDPS = (DPSCAPGlobals)Xcalloc(1, sizeof(DPSCAPGlobalsRec));
+}
+
+
+static unsigned char padAdd[] = {0, 3, 2, 1};
+
+void
+DPSCAPWrite(
+ Display *agent,
+ char *buf,
+ unsigned len,
+ DPSCAPIOFlags writePad,
+ DPSCAPIOFlags bufMode)
+{
+ int pad = padAdd[len & 3];
+ unsigned fullLen = (writePad == dpscap_pad) ? len + pad : len;
+
+ if (agent->bufptr + fullLen > agent->bufmax)
+ N_XFlush(agent);
+ if (agent->max_request_size && fullLen > agent->max_request_size)
+ {
+ DPSWarnProc(NULL, "DPS Client Library: request length exceeds max request size. Truncated.\n");
+ len = agent->max_request_size;
+ pad = 0;
+ }
+ if (bufMode == dpscap_insert)
+ {
+ agent->last_req = agent->bufptr;
+ agent->request++;
+ }
+ bcopy(buf, agent->bufptr, len);
+ agent->bufptr += len;
+ if (writePad == dpscap_pad && pad)
+ {
+ bcopy((char *) padAdd, agent->bufptr, pad);
+ agent->bufptr += pad;
+ }
+}
+
+
+/* === EXT CALLBACK HOOKS === */
+
+int
+DPSCAPCloseDisplayProc(
+ Display *dpy,
+ XExtCodes *codes)
+{
+#ifdef CSDPS
+ fprintf(stderr, "NX: Closing agent \"%s\"\n", dpy->display_name);
+#endif
+
+ /* Although it seems that we should free codes here, we can't
+ because Xlib owns the storage */
+
+ XDPSLSetShunt(dpy, (Display *) NULL);
+ XDPSLSetCodes(dpy, (XExtCodes *) NULL);
+ XDPSLSetSyncMask(dpy, DPSCAP_SYNCMASK_NONE);
+ XDPSLCleanAll(dpy);
+ XDPSPrivZapDpy(dpy);
+ return(0);
+}
+
+
+int
+DPSCAPCopyGCProc(
+ Display *dpy,
+ GC gc,
+ XExtCodes *codes)
+{
+ XGCValues values;
+ DPSCAPData my;
+ XExtData *extData = XFindOnExtensionList(
+ CSDPSHeadOfDpyExt(dpy),
+ codes->extension);
+
+ if (extData)
+ my = (DPSCAPData) extData->private_data;
+ else
+ return(0);
+
+ /* We change the GC unconditionally, since friggin' XCopyGC
+ clears the dirty bits of the values that are copied! */
+
+ DPSAssertWarn(XGetGCValues(dpy, gc, DPSGCBITS & ~(GCClipMask), &values),
+ NULL, "DPS NX: XGetGCValues returned False\n");
+ values.clip_mask = gc->values.clip_mask;
+ DPSCAPChangeGC(my->agent, gc, DPSGCBITS, &values);
+ /* We have to make sure that the agent completely processes
+ the change to the GC. If we allow the agent to update the
+ GC in its own sweet time, the stupid client may delete the
+ GC after the agent has already queued a request to, e.g.,
+ copy the GC, but before the request is flushed. */
+ XDPSLSync(dpy);
+ return(1);
+}
+
+int
+DPSCAPFreeGCProc(
+ Display *pdpy,
+ GC gc,
+ XExtCodes *codes)
+{
+ register xCAPNotifyReq *req;
+ DPSCAPData my;
+ Display *dpy = pdpy; /* Stupid macros insists on Display being 'dpy' */
+ XExtData *extData = XFindOnExtensionList(
+ CSDPSHeadOfDpyExt(dpy),
+ codes->extension);
+
+ if (extData)
+ my = (DPSCAPData) extData->private_data;
+ else
+ return(0);
+
+ /* Notify the agent that the client deleted a GC. Let the
+ agent figure out if it cares. */
+
+ /* ASSERT: called from within LockDisplay section */
+
+ dpy = my->agent;
+ if (dpy == (Display *)NULL || dpy == pdpy)
+ return(0);
+
+ /* May need to sync changes to GC */
+ if (gNXSyncGCMode == DPSNXSYNCGCMODE_DELAYED)
+ XDPSLSync(pdpy);
+
+ {
+ Display *xdpy = pdpy; /* pdpy is X server */
+ NXMacroGetReq(CAPNotify, req);
+ }
+ req->reqType = DPSCAPOPCODEBASE;
+ req->type = X_CAPNotify;
+ req->cxid = 0;
+ req->notification = DPSCAPNOTE_FREEGC;
+ req->data = XGContextFromGC(gc);
+ req->extra = 0;
+ /* Guarantee that everyone sees GC go away */
+ XSync(pdpy, False); /* pdpy is X server */
+ if (gNXSyncGCMode == DPSNXSYNCGCMODE_FLUSH)
+ {
+ LockDisplay(dpy); /* dpy means agent here */
+ N_XFlush(dpy);
+ UnlockDisplay(dpy);
+ }
+ else
+ XDPSLSync(pdpy);
+
+ /* ASSERT: SynchHandle called by caller */
+ return(1);
+}
+
+#ifdef CSDPSDEBUG
+static unsigned int gcCountFlushedClean = 0;
+static unsigned int gcCountFlushedDirty = 0;
+#endif /* CSDPSDEBUG */
+
+int
+DPSCAPFlushGCProc(
+ Display *dpy,
+ GC gc,
+ XExtCodes *codes)
+{
+ XGCValues values;
+ DPSCAPData my;
+ XExtData *extData;
+#ifdef CSDPSDEBUG
+ unsigned long int dirty;
+#endif /* CSDPSDEBUG */
+
+ /* When GC is created, it is flushed with no dirty bits set,
+ so we have to notice that situation. */
+
+ if (gc->dirty)
+ {
+ if (XDPSLGetGCFlushMode(dpy) == XDPSNX_GC_UPDATES_FAST
+ || !(gc->dirty & DPSGCBITS))
+ return(0);
+ }
+ extData = XFindOnExtensionList(CSDPSHeadOfDpyExt(dpy), codes->extension);
+ if (extData)
+ my = (DPSCAPData) extData->private_data;
+ else
+ return(0);
+ /* HERE IF (gc->dirty & DPSGCBITS || !gc->dirty) */
+#ifdef CSDPSDEBUG
+ dirty = gc->dirty;
+#endif /* CSDPSDEBUG */
+ DPSAssertWarn(XGetGCValues(dpy, gc, DPSGCBITS & ~(GCClipMask), &values),
+ NULL, "NX: XGetGCValues returned False\n");
+ values.clip_mask = gc->values.clip_mask;
+ /* Must guarantee that gc change is registered by X server
+ before notification is sent to agent. */
+ XSync(dpy, False);
+ DPSCAPChangeGC(my->agent, gc, DPSGCBITS, &values);
+ /* We have to make sure that the agent completely processes
+ the change to the GC. If we allow the agent to update the
+ GC in its own sweet time, the stupid client may delete the
+ GC after the agent has already queued a request to, e.g.,
+ copy the GC, but before the request is flushed. */
+ if (gNXSyncGCMode == DPSNXSYNCGCMODE_SYNC)
+ XDPSLSync(dpy);
+ else
+ XDPSLFlush(dpy);
+#ifdef CSDPSDEBUG
+ if (dirty)
+ ++gcCountFlushedDirty;
+ else
+ ++gcCountFlushedClean;
+#endif /* CSDPSDEBUG */
+ return(1);
+}