824N/A/*
824N/A * cslibext.c -- DPSCAP client Xlib extension hookup
824N/A *
824N/A * (c) Copyright 1991-1994 Adobe Systems Incorporated.
824N/A * All rights reserved.
824N/A *
824N/A * Permission to use, copy, modify, distribute, and sublicense this software
824N/A * and its documentation for any purpose and without fee is hereby granted,
824N/A * provided that the above copyright notices appear in all copies and that
824N/A * both those copyright notices and this permission notice appear in
824N/A * supporting documentation and that the name of Adobe Systems Incorporated
824N/A * not be used in advertising or publicity pertaining to distribution of the
824N/A * software without specific, written prior permission. No trademark license
824N/A * to use the Adobe trademarks is hereby granted. If the Adobe trademark
824N/A * "Display PostScript"(tm) is used to describe this software, its
824N/A * functionality or for any other purpose, such use shall be limited to a
824N/A * statement that this software works in conjunction with the Display
824N/A * PostScript system. Proper trademark attribution to reflect Adobe's
824N/A * ownership of the trademark shall be given whenever any such reference to
824N/A * the Display PostScript system is made.
824N/A *
824N/A * ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR
824N/A * ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
824N/A * ADOBE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
824N/A * IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
824N/A * NON- INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE
824N/A * TO YOU OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL
824N/A * DAMAGES OR ANY DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,
824N/A * NEGLIGENCE, STRICT LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN
824N/A * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT
824N/A * PROVIDE ANY TRAINING OR OTHER SUPPORT FOR THE SOFTWARE.
824N/A *
824N/A * Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems
824N/A * Incorporated which may be registered in certain jurisdictions
824N/A *
824N/A * Author: Adobe Systems Incorporated
824N/A */
824N/A/* $XFree86: xc/lib/dps/cslibext.c,v 1.4tsi Exp $ */
824N/A
824N/A#include <stdio.h>
824N/A#include <stdlib.h>
824N/A
824N/A#include <sys/param.h> /* for MAXHOSTNAMELEN */
824N/A#include <X11/X.h>
824N/A#include <X11/Xlib.h>
824N/A#include <X11/Xlibint.h>
824N/A#include "cslibint.h"
824N/A#include <DPS/XDPS.h>
824N/A#include <DPS/XDPSproto.h>
824N/A#include <DPS/dpsXclient.h>
824N/A#include <DPS/dpsNXargs.h>
824N/A#include "DPSCAPClient.h"
824N/A#include "dpsassert.h"
824N/A#include <DPS/XDPSlib.h>
824N/A
824N/A#include "publictypes.h"
824N/A#include "dpsXpriv.h"
824N/A
824N/A/* === DEFINES === */
824N/A
824N/A#define DPSNXSYNCGCMODE_FLUSH 0
824N/A#define DPSNXSYNCGCMODE_SYNC 1
824N/A#define DPSNXSYNCGCMODE_DELAYED 2
824N/A#define DPSNXSYNCGCMODE_DEFAULT DPSNXSYNCGCMODE_DELAYED
824N/A
824N/A/* === GLOBALS === */
824N/A
824N/ADPSCAPGlobals gCSDPS = NULL;
824N/A
824N/A#ifdef DPSLNKL
824N/A#define ANXCYAN
824N/A#define ANXMAGENTA
824N/A#define ANXYELLOW
824N/A#define ANXBLACK
824N/A#define ANXSPOT
824N/A#include "dpslnkl.inc"
824N/A#endif /* DPSLNKL */
824N/A
824N/Aint gNXSyncGCMode = DPSNXSYNCGCMODE_DEFAULT;
824N/A
824N/A/* === PUBLIC PROCS === */
824N/A
824N/A#ifdef MAHALO
824N/Astatic int
824N/ADPSCAPFlushAfterProc(Display *agent)
824N/A{
824N/A LockDisplay(agent);
824N/A N_XFlush(agent);
824N/A UnlockDisplay(agent);
824N/A}
824N/A#endif
824N/A
824N/Aint
824N/ACSDPSInit(
824N/A Display *dpy,
824N/A int *numberType, /* RETURN */
824N/A char **floatingName) /* RETURN */
824N/A{
824N/A register Display *agent;
824N/A register xCAPConnReplyPrefix *p;
824N/A register char *c;
824N/A DPSCAPData my;
824N/A xCAPConnSetupReq setup;
824N/A union {
824N/A xCAPConnSuccess good;
824N/A xCAPConnFailed bad;
824N/A } reply;
824N/A XExtData *extData;
824N/A XExtCodes *codes;
824N/A int indian;
824N/A int rest;
824N/A Window clientWindow;
824N/A char fullDisplayName[MAXHOSTNAMELEN+10];
824N/A
824N/A if (gCSDPS == NULL)
824N/A DPSCAPStartUp();
824N/A
824N/A /* To fix dps-nx #68, Motif too slow on HP */
824N/A if ((c = getenv("DPSNXGCMODE")) != 0)
824N/A {
824N/A gNXSyncGCMode = atoi(c);
824N/A if (gNXSyncGCMode < DPSNXSYNCGCMODE_FLUSH
824N/A || gNXSyncGCMode > DPSNXSYNCGCMODE_DELAYED)
824N/A gNXSyncGCMode = DPSNXSYNCGCMODE_DEFAULT;
824N/A }
824N/A
824N/A /* We may have already called this routine via XDPSExtensionPresent,
824N/A so don't do it again! */
824N/A
824N/A if ((codes = XDPSLGetCodes(dpy))
824N/A && (agent = XDPSLGetShunt(dpy))
824N/A && agent != dpy
824N/A && codes->major_opcode == DPSXOPCODEBASE)
824N/A return(DPSCAPSUCCESS);
824N/A
824N/A /* Try to create a window for ClientMessage communication */
824N/A
824N/A clientWindow = XCreateSimpleWindow(
824N/A dpy,
824N/A DefaultRootWindow(dpy),
824N/A 0, 0,
824N/A 1, 1,
824N/A 0,
824N/A BlackPixel(dpy, DefaultScreen(dpy)),
824N/A WhitePixel(dpy, DefaultScreen(dpy)));
824N/A if (clientWindow == None)
824N/A return(DPSCAPFAILED);
824N/A
824N/A /* Try to open a connection to an agent */
824N/A
824N/A if ((extData = DPSCAPOpenAgent(dpy, fullDisplayName)) == NULL)
824N/A {
824N/A XDestroyWindow(dpy, clientWindow);
824N/A return(DPSCAPFAILED);
824N/A }
824N/A
824N/A /* DPSCAPOpenAgent only partially fills in extData, so finish it */
824N/A
824N/A codes = XAddExtension(dpy);
824N/A codes->major_opcode = DPSXOPCODEBASE;
824N/A codes->first_event = 0; /* REQUIRED */
824N/A codes->first_error = FirstExtensionError;
824N/A extData->number = codes->extension;
824N/A extData->free_private = DPSCAPDestroy;
824N/A my = (DPSCAPData) extData->private_data;
824N/A my->codes = codes;
824N/A agent = my->agent;
824N/A /* +++ Is this all we have to do here? */
824N/A
824N/A /* Send opening handshake */
824N/A
824N/A indian = 1;
824N/A if (*(char *) &indian)
824N/A setup.byteorder = 'l';
824N/A else
824N/A setup.byteorder = 'B';
824N/A setup.dpscapVersion = DPSCAPPROTOVERSION;
824N/A setup.flags = DPSCAPNONEFLAG;
824N/A setup.libraryversion = DPSPROTOCOLVERSION;
824N/A setup.authProtoNameLength = 0;
824N/A setup.authProtoDataLength = 0;
824N/A setup.displayStringLength = strlen(fullDisplayName);
824N/A setup.nodeStringLength = 0;
824N/A setup.transportStringLength = 0;
824N/A setup.display = 0;
824N/A setup.screen = 0;
824N/A setup.reserved = 0;
824N/A setup.clientWindow = clientWindow;
824N/A
824N/A#ifndef DPSLNKL
824N/A DPSCAPWrite(agent, (char *)&setup, sizeof(xCAPConnSetupReq), dpscap_nopad,dpscap_insert);
824N/A DPSCAPWrite(agent, fullDisplayName, setup.displayStringLength, dpscap_pad, dpscap_append);
824N/A N_XFlush(agent);
824N/A#else /* DPSLNKL */
824N/A if (CSDPSConfirmDisplay(agent, dpy, &setup, &reply, fullDisplayName) == 1)
824N/A {
824N/A p = (xCAPConnReplyPrefix *)&reply.good;
824N/A goto skip_read;
824N/A }
824N/A /* Read normal reply */
824N/A#endif /* DPSLNKL */
824N/A
824N/A /* Read common reply prefix */
824N/A
824N/A p = (xCAPConnReplyPrefix *)&reply.good;
824N/A N_XRead(agent, (char *)p, (long)sizeof(xCAPConnReplyPrefix));
824N/A#ifdef DPSLNKL
824N/Askip_read:
824N/A#endif
824N/A if (!p->success)
824N/A {
824N/A char mbuf[512];
824N/A /* read the rest */
824N/A c = (char *)&reply.bad.serverVersion;
824N/A N_XRead(agent, c, sz_xCAPConnFailed - sz_xCAPConnReplyPrefix);
824N/A sprintf(mbuf, "DPS NX: connection to \"%s\" refused by agent.", DisplayString(agent));
824N/A DPSWarnProc(NULL, mbuf);
824N/A c = (char *)Xmalloc(reply.bad.reasonLength);
824N/A if (!c) return(DPSCAPFAILED);
824N/A N_XReadPad(agent, c, (long)reply.bad.reasonLength);
824N/A if (!reply.bad.reasonLength)
824N/A sprintf(mbuf, "DPS NX: (no reason given)\n");
824N/A else
824N/A {
824N/A strcpy(mbuf, "DPS NX: ");
824N/A strncat(mbuf, c, reply.bad.reasonLength);
824N/A mbuf[reply.bad.reasonLength+7] = '\0';
824N/A }
824N/A DPSWarnProc(NULL, mbuf);
824N/A Xfree(c);
824N/A DPSCAPDestroy(extData);
824N/A Xfree(extData);
824N/A XDestroyWindow(dpy, clientWindow);
824N/A return(DPSCAPFAILED);
824N/A }
824N/A
824N/A /* read the rest of the fixed length reply */
824N/A c = (char *)&reply.good.serverVersion;
824N/A rest = sizeof(xCAPConnSuccess) - sizeof(xCAPConnReplyPrefix);
824N/A N_XRead(agent, c, rest);
824N/A
824N/A /* verify */
824N/A
824N/A if (reply.good.serverVersion < DPSPROTOCOLVERSION)
824N/A {
824N/A /* Fine, we downgrade the client */
824N/A char qbuf[256];
824N/A sprintf(qbuf, "NX: server version %ld older than expected %d, client will downgrade", (long)reply.good.serverVersion, DPSPROTOCOLVERSION);
824N/A DPSWarnProc(NULL, qbuf);
824N/A }
824N/A my->dpscapVersion = reply.good.dpscapVersion;
824N/A if (my->dpscapVersion < DPSCAPPROTOVERSION)
824N/A {
824N/A /* Fine, we downgrade the client */
824N/A char kbuf[256];
824N/A sprintf(kbuf, "NX: agent version %d older than expected %d, client will downgrade", my->dpscapVersion, DPSCAPPROTOVERSION);
824N/A DPSWarnProc(NULL, kbuf);
824N/A#ifdef XXX
824N/A /* Saving this code as a reminder about what needs to be
824N/A cleaned up if we exit here */
824N/A DPSCAPDestroy(extData);
824N/A Xfree(extData);
824N/A XDestroyWindow(clientWindow);
824N/A return(DPSCAPFAILED);
824N/A#endif
824N/A }
824N/A
824N/A if (numberType)
824N/A *numberType = reply.good.preferredNumberFormat;
824N/A
824N/A /* read additional data */
824N/A
824N/A c = (char *)Xmalloc(reply.good.floatingNameLength + 1);
824N/A N_XReadPad(agent, c, reply.good.floatingNameLength);
824N/A c[reply.good.floatingNameLength] = 0;
824N/A if (floatingName)
824N/A *floatingName = c;
824N/A else
824N/A Xfree(c);
824N/A
824N/A /* set library extension data */
824N/A
824N/A XDPSLSetVersion(agent, reply.good.serverVersion);
824N/A XDPSLSetVersion(dpy, reply.good.serverVersion);
824N/A XDPSLSetShunt(dpy, agent);
824N/A XDPSLSetCodes(dpy, codes);
824N/A if (XDPSLGetSyncMask(dpy) == DPSCAP_SYNCMASK_NONE)
824N/A XDPSLSetSyncMask(dpy, DPSCAP_SYNCMASK_DFLT);
824N/A my->agentWindow = reply.good.agentWindow;
824N/A XDPSLSetGCFlushMode(dpy, XDPSNX_GC_UPDATES_SLOW); /* default */
824N/A
824N/A /* Hook my extension data on the dpy */
824N/A
824N/A my->extData = extData;
824N/A XAddToExtensionList(CSDPSHeadOfDpyExt(dpy), extData);
824N/A (void) XESetCloseDisplay(dpy, codes->extension, DPSCAPCloseDisplayProc);
824N/A (void) XESetCopyGC(dpy, codes->extension, DPSCAPCopyGCProc);
824N/A (void) XESetFreeGC(dpy, codes->extension, DPSCAPFreeGCProc);
824N/A (void) XESetFlushGC(dpy, codes->extension, DPSCAPFlushGCProc);
824N/A XDPSLSetClientMessageHandler(dpy);
824N/A
824N/A /* Chain my data on global list */
824N/A
824N/A my->next = gCSDPS->head;
824N/A gCSDPS->head = my;
824N/A
824N/A#ifdef MAHALO
824N/A /* Set function that is called after every Xlib protocol proc */
824N/A XDPSLSetAfterProc(dpy);
824N/A
824N/A /* All CSDPS protocol is auto-flushed */
824N/A (void) XSetAfterFunction(agent, DPSCAPFlushAfterProc);
824N/A#endif /* MAHALO */
824N/A
824N/A /* set agent arguments, if needed */
824N/A /* must follow setting of ShuntMap at least, so safest to
824N/A do here when everything has been setup */
824N/A XDPSLUpdateAgentArgs(dpy);
824N/A
824N/A return(DPSCAPSUCCESS);
824N/A}
824N/A
824N/A
824N/AXExtData **
824N/ACSDPSHeadOfDpyExt(
824N/A Display *dpy)
824N/A{
824N/A XEDataObject object;
824N/A
824N/A object.display = dpy;
824N/A return(XEHeadOfExtensionList(object));
824N/A}
824N/A
824N/Avoid
824N/AXDPSSyncGCClip(
824N/A register Display *dpy,
824N/A register GC gc)
824N/A{
824N/A /* The primary utility of this function is for DPS NX correctness,
824N/A but it also helps DPS/X do less work in tracking GC changes. */
824N/A XDPSLSyncGCClip(dpy, gc);
824N/A}
824N/A
824N/Avoid
824N/AXDPSReconcileRequests(
824N/A register DPSContext ctxt)
824N/A{
824N/A Display *dpy;
824N/A register ContextXID cxid;
824N/A register DPSContext curCtxt;
824N/A
824N/A for (curCtxt = ctxt; curCtxt; curCtxt = curCtxt->chainChild)
824N/A {
824N/A cxid = XDPSXIDFromContext(&dpy, curCtxt);
824N/A if (dpy == (Display *)NULL || cxid == None)
824N/A break; /* Skip text contexts */
824N/A XDPSLReconcileRequests(dpy, cxid);
824N/A }
824N/A}
824N/A
824N/AStatus
824N/AXDPSNXSetAgentArg(
824N/A Display *dpy,
824N/A int arg, int val)
824N/A{
824N/A if (!dpy || arg >= 0 || arg < AGENTLASTARG)
824N/A return(!Success);
824N/A else
824N/A return(XDPSLSetAgentArg(dpy, arg, val));
824N/A}
824N/A
824N/A/* New for DPS NX 2.0 */
824N/Avoid
824N/AXDPSFlushGC(
824N/A Display *dpy,
824N/A GC gc)
824N/A{
824N/A if (dpy && gc)
824N/A XDPSLFlushGC(dpy, gc);
824N/A}
824N/A
824N/A/* === SUPPORT PROCS === */
824N/A
824N/Avoid
824N/ADPSCAPChangeGC(
824N/A register Display *agent,
824N/A GC gc,
824N/A unsigned long valuemask,
824N/A XGCValues *values)
824N/A{
824N/A register xChangeGCReq *req;
824N/A unsigned long oldDirty = gc->dirty;
824N/A
824N/A /* ASSERT: called from within LockDisplay section */
824N/A
824N/A /* Always include the clip_mask */
824N/A valuemask |= GCClipMask;
824N/A /* +++ HACK! Hide the gc->rects flag in arc_mode */
824N/A valuemask |= GCArcMode;
824N/A valuemask &= (1L << (GCLastBit + 1)) - 1;
824N/A
824N/A /* Stupid macro insists on Display being called 'dpy' */
824N/A {
824N/A Display *dpy = agent;
824N/A Display *xdpy = (Display *)NULL;
824N/A NXMacroGetReq(ChangeGC, req);
824N/A }
824N/A req->gc = XGContextFromGC(gc);
824N/A gc->dirty = req->mask = valuemask;
824N/A {
824N/A/* Derived from MIT XCrGC.c, _XGenerateGCList:
824N/ACopyright 1985, 1986, 1987, 1988, 1989 by the
824N/AMassachusetts Institute of Technology
824N/A
824N/APermission to use, copy, modify, distribute, and sell this software and its
824N/Adocumentation for any purpose is hereby granted without fee, provided that
824N/Athe above copyright notice appear in all copies and that both that
824N/Acopyright notice and this permission notice appear in supporting
824N/Adocumentation, and that the name of M.I.T. not be used in advertising or
824N/Apublicity pertaining to distribution of the software without specific,
824N/Awritten prior permission. M.I.T. makes no representations about the
824N/Asuitability of this software for any purpose. It is provided "as is"
824N/Awithout express or implied warranty.
824N/A*/
824N/A /* Warning! This code assumes that "unsigned int" is 32-bits wide */
824N/A
824N/A unsigned int vals[32];
824N/A register unsigned int *value = vals;
824N/A long nvalues;
824N/A register XGCValues *gv = values;
824N/A register unsigned long dirty = gc->dirty;
824N/A
824N/A /*
824N/A * Note: The order of these tests are critical; the order must be the
824N/A * same as the GC mask bits in the word.
824N/A */
824N/A if (dirty & GCFunction) *value++ = gv->function;
824N/A if (dirty & GCPlaneMask) *value++ = gv->plane_mask;
824N/A if (dirty & GCForeground) *value++ = gv->foreground;
824N/A if (dirty & GCBackground) *value++ = gv->background;
824N/A if (dirty & GCLineWidth) *value++ = gv->line_width;
824N/A if (dirty & GCLineStyle) *value++ = gv->line_style;
824N/A if (dirty & GCCapStyle) *value++ = gv->cap_style;
824N/A if (dirty & GCJoinStyle) *value++ = gv->join_style;
824N/A if (dirty & GCFillStyle) *value++ = gv->fill_style;
824N/A if (dirty & GCFillRule) *value++ = gv->fill_rule;
824N/A if (dirty & GCTile) *value++ = gv->tile;
824N/A if (dirty & GCStipple) *value++ = gv->stipple;
824N/A if (dirty & GCTileStipXOrigin) *value++ = gv->ts_x_origin;
824N/A if (dirty & GCTileStipYOrigin) *value++ = gv->ts_y_origin;
824N/A if (dirty & GCFont) *value++ = gv->font;
824N/A if (dirty & GCSubwindowMode) *value++ = gv->subwindow_mode;
824N/A if (dirty & GCGraphicsExposures) *value++ = gv->graphics_exposures;
824N/A if (dirty & GCClipXOrigin) *value++ = gv->clip_x_origin;
824N/A if (dirty & GCClipYOrigin) *value++ = gv->clip_y_origin;
824N/A if (dirty & GCClipMask) *value++ = gv->clip_mask;
824N/A if (dirty & GCDashOffset) *value++ = gv->dash_offset;
824N/A if (dirty & GCDashList) *value++ = gv->dashes;
824N/A /* +++ HACK! Hide gc->rects flag in GCArcMode */
824N/A if (dirty & GCArcMode) *value++ = gc->rects;
824N/A
824N/A req->length += (nvalues = value - vals);
824N/A
824N/A /*
824N/A * note: Data is a macro that uses its arguments multiple
824N/A * times, so "nvalues" is changed in a separate assignment
824N/A * statement
824N/A */
824N/A
824N/A nvalues <<= 2;
824N/A Data32 (agent, (long *) vals, nvalues);
824N/A }
824N/A
824N/A gc->dirty = oldDirty;
824N/A
824N/A /* ASSERT: SyncHandle called by caller */
824N/A}
824N/A
824N/A
824N/ADPSCAPData
824N/ADPSCAPCreate(
824N/A Display *dpy, Display *agent)
824N/A{
824N/A register DPSCAPData my = (DPSCAPData)Xcalloc(1, sizeof(DPSCAPDataRec));
824N/A
824N/A if (my == (DPSCAPData)NULL) return(NULL);
824N/A my->dpy = dpy;
824N/A my->agent = agent;
824N/A my->typePSOutput = XInternAtom(
824N/A dpy,
824N/A DPSCAP_TYPE_PSOUTPUT,
824N/A False);
824N/A my->typePSOutputWithLen = XInternAtom(
824N/A dpy,
824N/A DPSCAP_TYPE_PSOUTPUT_LEN,
824N/A False);
824N/A my->typePSStatus = XInternAtom(
824N/A dpy,
824N/A DPSCAP_TYPE_PSSTATUS,
824N/A False);
824N/A my->typeNoop = XInternAtom(
824N/A dpy,
824N/A DPSCAP_TYPE_NOOP,
824N/A False);
824N/A my->typeSync = XInternAtom(
824N/A dpy,
824N/A DPSCAP_TYPE_SYNC,
824N/A False);
824N/A my->typeXError = XInternAtom(
824N/A dpy,
824N/A DPSCAP_TYPE_XERROR,
824N/A False);
824N/A my->typePSReady = XInternAtom(
824N/A dpy,
824N/A DPSCAP_TYPE_PSREADY,
824N/A False);
824N/A my->typeResume = XInternAtom(
824N/A dpy,
824N/A DPSCAP_TYPE_RESUME,
824N/A False);
824N/A return(my);
824N/A}
824N/A
824N/Aint
824N/ADPSCAPDestroy(
824N/A XExtData *extData)
824N/A{
824N/A register DPSCAPData my = (DPSCAPData) extData->private_data;
824N/A register DPSCAPData n;
824N/A
824N/A if (my == (DPSCAPData)NULL) return(0);
824N/A DPSCAPCloseAgent(my->agent);
824N/A my->agent = NULL;
824N/A /* my->extData->private_data = NIL; ???? +++ */
824N/A if (my == gCSDPS->head)
824N/A gCSDPS->head = my->next;
824N/A else for (n = gCSDPS->head; n != NULL; n = n->next)
824N/A if (n->next == my)
824N/A {
824N/A n->next = my->next;
824N/A break;
824N/A }
824N/A Xfree(my);
824N/A /* extData freed by caller (e.g., _XFreeExtData) */
824N/A return(0);
824N/A}
824N/A
824N/Avoid
824N/ADPSCAPStartUp(void)
824N/A{
824N/A gCSDPS = (DPSCAPGlobals)Xcalloc(1, sizeof(DPSCAPGlobalsRec));
824N/A}
824N/A
824N/A
824N/Astatic unsigned char padAdd[] = {0, 3, 2, 1};
824N/A
824N/Avoid
824N/ADPSCAPWrite(
824N/A Display *agent,
824N/A char *buf,
824N/A unsigned len,
824N/A DPSCAPIOFlags writePad,
824N/A DPSCAPIOFlags bufMode)
824N/A{
824N/A int pad = padAdd[len & 3];
824N/A unsigned fullLen = (writePad == dpscap_pad) ? len + pad : len;
824N/A
824N/A if (agent->bufptr + fullLen > agent->bufmax)
824N/A N_XFlush(agent);
824N/A if (agent->max_request_size && fullLen > agent->max_request_size)
824N/A {
824N/A DPSWarnProc(NULL, "DPS Client Library: request length exceeds max request size. Truncated.\n");
824N/A len = agent->max_request_size;
824N/A pad = 0;
824N/A }
824N/A if (bufMode == dpscap_insert)
824N/A {
824N/A agent->last_req = agent->bufptr;
824N/A agent->request++;
824N/A }
824N/A bcopy(buf, agent->bufptr, len);
824N/A agent->bufptr += len;
824N/A if (writePad == dpscap_pad && pad)
824N/A {
824N/A bcopy((char *) padAdd, agent->bufptr, pad);
824N/A agent->bufptr += pad;
824N/A }
824N/A}
824N/A
824N/A
824N/A/* === EXT CALLBACK HOOKS === */
824N/A
824N/Aint
824N/ADPSCAPCloseDisplayProc(
824N/A Display *dpy,
824N/A XExtCodes *codes)
824N/A{
824N/A#ifdef CSDPS
824N/A fprintf(stderr, "NX: Closing agent \"%s\"\n", dpy->display_name);
824N/A#endif
824N/A
824N/A /* Although it seems that we should free codes here, we can't
824N/A because Xlib owns the storage */
824N/A
824N/A XDPSLSetShunt(dpy, (Display *) NULL);
824N/A XDPSLSetCodes(dpy, (XExtCodes *) NULL);
824N/A XDPSLSetSyncMask(dpy, DPSCAP_SYNCMASK_NONE);
824N/A XDPSLCleanAll(dpy);
824N/A XDPSPrivZapDpy(dpy);
824N/A return(0);
824N/A}
824N/A
824N/A
824N/Aint
824N/ADPSCAPCopyGCProc(
824N/A Display *dpy,
824N/A GC gc,
824N/A XExtCodes *codes)
824N/A{
824N/A XGCValues values;
824N/A DPSCAPData my;
824N/A XExtData *extData = XFindOnExtensionList(
824N/A CSDPSHeadOfDpyExt(dpy),
824N/A codes->extension);
824N/A
824N/A if (extData)
824N/A my = (DPSCAPData) extData->private_data;
824N/A else
824N/A return(0);
824N/A
824N/A /* We change the GC unconditionally, since friggin' XCopyGC
824N/A clears the dirty bits of the values that are copied! */
824N/A
824N/A DPSAssertWarn(XGetGCValues(dpy, gc, DPSGCBITS & ~(GCClipMask), &values),
824N/A NULL, "DPS NX: XGetGCValues returned False\n");
824N/A values.clip_mask = gc->values.clip_mask;
824N/A DPSCAPChangeGC(my->agent, gc, DPSGCBITS, &values);
824N/A /* We have to make sure that the agent completely processes
824N/A the change to the GC. If we allow the agent to update the
824N/A GC in its own sweet time, the stupid client may delete the
824N/A GC after the agent has already queued a request to, e.g.,
824N/A copy the GC, but before the request is flushed. */
824N/A XDPSLSync(dpy);
824N/A return(1);
824N/A}
824N/A
824N/Aint
824N/ADPSCAPFreeGCProc(
824N/A Display *pdpy,
824N/A GC gc,
824N/A XExtCodes *codes)
824N/A{
824N/A register xCAPNotifyReq *req;
824N/A DPSCAPData my;
824N/A Display *dpy = pdpy; /* Stupid macros insists on Display being 'dpy' */
824N/A XExtData *extData = XFindOnExtensionList(
824N/A CSDPSHeadOfDpyExt(dpy),
824N/A codes->extension);
824N/A
824N/A if (extData)
824N/A my = (DPSCAPData) extData->private_data;
824N/A else
824N/A return(0);
824N/A
824N/A /* Notify the agent that the client deleted a GC. Let the
824N/A agent figure out if it cares. */
824N/A
824N/A /* ASSERT: called from within LockDisplay section */
824N/A
824N/A dpy = my->agent;
824N/A if (dpy == (Display *)NULL || dpy == pdpy)
824N/A return(0);
824N/A
824N/A /* May need to sync changes to GC */
824N/A if (gNXSyncGCMode == DPSNXSYNCGCMODE_DELAYED)
824N/A XDPSLSync(pdpy);
824N/A
824N/A {
824N/A Display *xdpy = pdpy; /* pdpy is X server */
824N/A NXMacroGetReq(CAPNotify, req);
824N/A }
824N/A req->reqType = DPSCAPOPCODEBASE;
824N/A req->type = X_CAPNotify;
824N/A req->cxid = 0;
824N/A req->notification = DPSCAPNOTE_FREEGC;
824N/A req->data = XGContextFromGC(gc);
824N/A req->extra = 0;
824N/A /* Guarantee that everyone sees GC go away */
824N/A XSync(pdpy, False); /* pdpy is X server */
824N/A if (gNXSyncGCMode == DPSNXSYNCGCMODE_FLUSH)
824N/A {
824N/A LockDisplay(dpy); /* dpy means agent here */
824N/A N_XFlush(dpy);
824N/A UnlockDisplay(dpy);
824N/A }
824N/A else
824N/A XDPSLSync(pdpy);
824N/A
824N/A /* ASSERT: SynchHandle called by caller */
824N/A return(1);
824N/A}
824N/A
824N/A#ifdef CSDPSDEBUG
824N/Astatic unsigned int gcCountFlushedClean = 0;
824N/Astatic unsigned int gcCountFlushedDirty = 0;
824N/A#endif /* CSDPSDEBUG */
824N/A
824N/Aint
824N/ADPSCAPFlushGCProc(
824N/A Display *dpy,
824N/A GC gc,
824N/A XExtCodes *codes)
824N/A{
824N/A XGCValues values;
824N/A DPSCAPData my;
824N/A XExtData *extData;
824N/A#ifdef CSDPSDEBUG
824N/A unsigned long int dirty;
824N/A#endif /* CSDPSDEBUG */
824N/A
824N/A /* When GC is created, it is flushed with no dirty bits set,
824N/A so we have to notice that situation. */
824N/A
824N/A if (gc->dirty)
824N/A {
824N/A if (XDPSLGetGCFlushMode(dpy) == XDPSNX_GC_UPDATES_FAST
824N/A || !(gc->dirty & DPSGCBITS))
824N/A return(0);
824N/A }
824N/A extData = XFindOnExtensionList(CSDPSHeadOfDpyExt(dpy), codes->extension);
824N/A if (extData)
824N/A my = (DPSCAPData) extData->private_data;
824N/A else
824N/A return(0);
824N/A /* HERE IF (gc->dirty & DPSGCBITS || !gc->dirty) */
824N/A#ifdef CSDPSDEBUG
824N/A dirty = gc->dirty;
824N/A#endif /* CSDPSDEBUG */
824N/A DPSAssertWarn(XGetGCValues(dpy, gc, DPSGCBITS & ~(GCClipMask), &values),
824N/A NULL, "NX: XGetGCValues returned False\n");
824N/A values.clip_mask = gc->values.clip_mask;
824N/A /* Must guarantee that gc change is registered by X server
824N/A before notification is sent to agent. */
824N/A XSync(dpy, False);
824N/A DPSCAPChangeGC(my->agent, gc, DPSGCBITS, &values);
824N/A /* We have to make sure that the agent completely processes
824N/A the change to the GC. If we allow the agent to update the
824N/A GC in its own sweet time, the stupid client may delete the
824N/A GC after the agent has already queued a request to, e.g.,
824N/A copy the GC, but before the request is flushed. */
824N/A if (gNXSyncGCMode == DPSNXSYNCGCMODE_SYNC)
824N/A XDPSLSync(dpy);
824N/A else
824N/A XDPSLFlush(dpy);
824N/A#ifdef CSDPSDEBUG
824N/A if (dirty)
824N/A ++gcCountFlushedDirty;
824N/A else
824N/A ++gcCountFlushedClean;
824N/A#endif /* CSDPSDEBUG */
824N/A return(1);
824N/A}