/*
* dpsXclient.c -- Implementation of the Display PostScript Client Library.
*
* (c) Copyright 1988-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$ */
#include <stdlib.h>
#include <unistd.h> /* sleep() */
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#ifdef VMS
/* Xlib does not like UNIX defined to any value under VMS. */
#undef UNIX
#include <decw$include/X.h>
#include <decw$include/Xlib.h>
#else /* VMS */
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif /* VMS */
#include "DPS/XDPSlib.h"
#include "DPS/XDPS.h"
#include "publictypes.h"
#include "DPS/dpsclient.h"
#include "dpsprivate.h"
#include "dpsXpriv.h"
#include "DPS/dpsXclient.h"
#include "dpsdict.h"
#include "DPS/dpsexcept.h"
#include "dpsXint.h"
static DPSPrivContext FindPrivContext (
Display * dpy,
long int cid)
{
DPSPrivSpace ss;
DPSPrivContext cc;
for (ss = spaces; ss != NIL; ss = ss->next)
for (cc = ss->firstContext; cc != NIL; cc = cc->next)
if (cc->cid == cid && ((XDPSPrivContext) cc->wh)->dpy == dpy)
return (cc);
return (NIL);
}
DPSContext XDPSFindContext (
Display * dpy,
int cid)
{
return ((DPSContext) FindPrivContext (dpy, cid));
}
DPSContext DPSContextFromContextID(
DPSContext ctxt,
int contextID,
DPSTextProc textProc,
DPSErrorProc errorProc)
{
DPSPrivSpace ss;
Display *dpy = ((XDPSPrivContext) ((DPSPrivContext) ctxt)->wh)->dpy;
DPSPrivContext c, cc = FindPrivContext (dpy, contextID);
DPSPrivContext oldc = (DPSPrivContext)ctxt;
if (cc != NIL) return (DPSContext)cc;
c = (DPSPrivContext)DPScalloc(sizeof(DPSPrivContextRec), 1);
if (!c) return NIL;
*c = *oldc;
ss = (DPSPrivSpace)c->space;
if (textProc) c->textProc = textProc;
if (errorProc) c->errorProc = errorProc;
c->eofReceived = false;
c->cid = contextID;
c->buf = c->outBuf = c->objBuf = NIL;
c->chainParent = c->chainChild = NIL;
c->nBufChars = c->nOutBufChars = c->nObjBufChars = 0;
c->next = ss->firstContext;
DPSAssert(c->next != c);
ss->firstContext = c;
/* Note: there's no way to determine whether the new context id was obtained
** as a result of a fork operation or from another application. so, it must
** be assumed that the application is the creator of the new context.
** Otherwise, it would have called the XDPSContextFromSharedID.
*/
c->creator = true;
c->zombie = false;
c->numstringOffsets = NULL;
DPSIncludePrivContext(
(XDPSPrivContext) c->wh, (DPSContext)c, c->cid, ss->sid, DPSclientPrintProc);
return (DPSContext)c;
}
boolean DPSPrivateCheckWait(
DPSContext ctxt)
{
DPSPrivContext cc = (DPSPrivContext) ctxt;
if (!cc->creator || cc->zombie) {
DPSSafeSetLastNameIndex(ctxt);
if (cc->errorProc != NIL) {
(*cc->errorProc) (ctxt, cc->zombie ? dps_err_deadContext :
dps_err_invalidAccess,
(unsigned long) ctxt, 0);
}
return true;
}
return false;
}
static void procFlushContext(
DPSContext ctxt)
{
DPSPrivContext c = (DPSPrivContext) ctxt;
XDPSLFlush (((XDPSPrivContext) c->wh)->dpy);
if (ctxt->chainChild != NIL) DPSFlushContext(ctxt->chainChild);
}
/* ARGSUSED */
static Bool FindDPSEvent(
Display *dpy,
XEvent *event,
char *arg)
{
return XDPSIsDPSEvent(event);
}
static void procAwaitReturnValues(DPSContext ctxt)
{
DPSPrivContext c = (DPSPrivContext)ctxt;
XDPSPrivContext xwh = (XDPSPrivContext) c->wh;
XEvent ev;
/* Output currently goes only to creator! */
if (!c->creator)
{
DPSSafeSetLastNameIndex(ctxt);
c->resultTable = NIL;
c->resultTableLength = 0;
if (c->errorProc != NIL)
(*c->errorProc) (ctxt, dps_err_invalidAccess, 0, 0);
return;
}
if (c->resultTable != NIL)
{
DPSCheckInitClientGlobals();
if (XDPSLGetWrapWaitingFlag(xwh->dpy)) {
DPSSafeSetLastNameIndex(ctxt);
c->resultTable = NIL;
c->resultTableLength = 0;
if (c->errorProc != NIL)
(*c->errorProc) (ctxt, dps_err_recursiveWait,
(unsigned long) xwh->dpy, 0);
return;
}
XDPSLSetWrapWaitingFlag(xwh->dpy, True);
DURING
DPSFlushContext(ctxt);
while (c->resultTable != NIL)
{
/* We may block indefinitely if the context is frozen or it
somehow needs more input. */
if (c->zombie)
{
DPSSafeSetLastNameIndex(ctxt);
c->resultTable = NIL;
c->resultTableLength = 0;
if (c->errorProc != NIL)
(*c->errorProc) (ctxt, dps_err_deadContext, (unsigned long) c, 0);
XDPSLSetWrapWaitingFlag(xwh->dpy, False);
E_RTRN_VOID;
}
/* Someone could conceivably change the event delivery mode in the
middle of this...best to check every time */
if (XDPSLGetPassEventsFlag(xwh->dpy)) {
XIfEvent(xwh->dpy, &ev, FindDPSEvent, (char *) NULL);
if (!XDPSDispatchEvent(&ev)) DPSCantHappen();
} else DPSSendPostScript((XDPSPrivContext) c->wh, DPSclientPrintProc,
c->cid, NIL, 0, NIL);
}
HANDLER
XDPSLSetWrapWaitingFlag(xwh->dpy, False);
RERAISE;
END_HANDLER
XDPSLSetWrapWaitingFlag(xwh->dpy, False);
}
/* update space's name map.
space->lastNameIndex is the highest index known to be known to the
server for this space.
c->lastNameIndex is the highest index sent so far to the context
*/
if (((DPSPrivSpace)(c->space))->lastNameIndex < c->lastNameIndex)
((DPSPrivSpace)(c->space))->lastNameIndex = c->lastNameIndex;
}
void DPSinnerProcWriteData(
DPSContext ctxt,
char *buf,
unsigned int count)
{
DPSPrivContext c = (DPSPrivContext) ctxt;
/* ASSERT: safe to call with chain */
/* No local buffering */
DPSSendPostScript ((XDPSPrivContext) c->wh, DPSclientPrintProc,
c->cid, buf, count, NIL);
} /* DPSinnerProcWriteData */
static void procResetContext(DPSContext ctxt)
{
DPSPrivContext c = (DPSPrivContext) ctxt;
int currStatus;
register XDPSPrivContext xwh = (XDPSPrivContext) c->wh;
int retries = 0;
int backoff = 2;
/* First make sure context isn't frozen, try to unfreeze. */
#define DPS_SLEEP_SECS 2
while((currStatus = XDPSLGetStatus(xwh->dpy, xwh->cxid)) == PSFROZEN)
{
XDPSLNotifyContext(xwh->dpy, xwh->cxid, PSUNFREEZE);
sleep(DPS_SLEEP_SECS);
/* Okay if context is PSRUNNING, since the EOF will
be handled at the next PSNEEDSINPUT */
}
/* Remove events from Xlib Qs before sending the reset request. */
XDPSForceEvents (xwh->dpy);
if (currStatus == PSSTATUSERROR)
/* +++ report error? */;
else /* Didn't become zombie. */
{
currStatus = 0;
XDPSLReset(xwh->dpy, xwh->cxid);
XDPSLFlush(xwh->dpy);
/* Be optmistic for the first try. Assume the app set up a status mask
correctly, we should get a status event without asking the
server for status. */
XDPSForceEvents(xwh->dpy);
currStatus = c->statusFromEvent;
while (currStatus != PSNEEDSINPUT && currStatus != PSZOMBIE)
{
if (currStatus == PSFROZEN)
XDPSLNotifyContext(xwh->dpy, xwh->cxid, PSUNFREEZE);
if (retries > backoff)
{
/* Optimism failed. App probably didn't set up a status mask.
Ask the server for status. */
currStatus = XDPSLGetStatus(xwh->dpy, xwh->cxid);
retries = 0;
backoff = (backoff > 30) ? 2 : backoff + 1;
continue;
}
else
++retries;
sleep(DPS_SLEEP_SECS);
XDPSForceEvents(xwh->dpy);
currStatus = c->statusFromEvent;
}
}
c->eofReceived = false;
}
void DPSPrivateDestroyContext(DPSContext ctxt)
{
DPSPrivContext c = (DPSPrivContext)ctxt;
DPSPrivSpace s = (DPSPrivSpace) c->space;
if (c->creator)
DPSSendTerminate((XDPSPrivContext) c->wh, c->cid, DPSclientPrintProc);
else
XDPSSetStatusMask(ctxt, 0, XDPSL_ALL_EVENTS, 0); /* Stop status events */
/* Don't free the space's wh out from under it */
if (c->wh != s->wh) free(c->wh);
}
void DPSPrivateDestroySpace(DPSSpace space)
{
DPSPrivSpace ss = (DPSPrivSpace) space;
if (ss->creator) DPSSendDestroySpace((XDPSPrivContext) ss->wh, ss->sid,
DPSclientPrintProc);
free (ss->wh);
}
boolean DPSCheckShared(DPSPrivContext ctxt)
{
return ctxt->creator == false && ctxt->resultTable != NIL;
/* let procAwaitReturnValues generate error */
}
/* ARGSUSED */
void DPSServicePostScript(boolean (*returnControl)(void))
{
} /* DPSServicePostScript */
void DPSHandleBogusError(DPSContext ctxt, char *prefix, char *suffix)
{
char *buf = "bogus error output from context";
DPSDefaultPrivateHandler(ctxt, dps_err_warning,
(long unsigned int)buf, 0, prefix, suffix);
}
void DPSDefaultPrivateHandler(
DPSContext ctxt,
DPSErrorCode errorCode,
long unsigned int arg1,
long unsigned int arg2,
char *prefix,
char *suffix)
{
DPSTextProc textProc = DPSGetCurrentTextBackstop();
switch (errorCode) {
case dps_err_invalidAccess:
if (textProc != NIL)
{
char m[100];
(void) sprintf (m, "%sInvalid context access.%s", prefix, suffix);
(*textProc) (ctxt, m, strlen (m));
}
break;
case dps_err_encodingCheck:
if (textProc != NIL)
{
char m[100];
(void) sprintf (m, "%sInvalid name/program encoding: %d/%d.%s",
prefix, (int) arg1, (int) arg2, suffix);
(*textProc) (ctxt, m, strlen (m));
}
break;
case dps_err_closedDisplay:
if (textProc != NIL)
{
char m[100];
(void) sprintf (m, "%sBroken display connection %d.%s",
prefix, (int) arg1, suffix);
(*textProc) (ctxt, m, strlen (m));
}
break;
case dps_err_deadContext:
if (textProc != NIL)
{
char m[100];
(void) sprintf (m, "%sDead context 0x0%x.%s", prefix,
(int) arg1, suffix);
(*textProc) (ctxt, m, strlen (m));
}
break;
case dps_err_warning:
if (textProc != NIL)
{
char *warn = (char *)arg1;
char *msg = "%% DPS Client Library Warning:\n ";
(*textProc)(ctxt, msg, strlen(msg));
(*textProc)(ctxt, warn, strlen(warn));
msg = "\n";
(*textProc)(ctxt, msg, strlen(msg));
/* flush convention */
(*textProc)(ctxt, msg, 0);
}
break;
case dps_err_fatal:
if (textProc != NIL)
{
char *fatal = (char *)arg1;
char *msg = "%% DPS Client Library Fatal Internal Error:\n ";
(*textProc)(ctxt, msg, strlen(msg));
(*textProc)(ctxt, fatal, strlen(fatal));
msg = ".\nAborting ...\n";
(*textProc)(ctxt, msg, strlen(msg));
/* flush convention */
(*textProc)(ctxt, msg, 0);
abort();
}
break;
case dps_err_recursiveWait:
if (textProc != NIL)
{
char m[100];
(void) sprintf (m,
"%sRecursive wait for return values, display 0x%x.%s",
prefix, (int) arg1, suffix);
(*textProc) (ctxt, m, strlen (m));
}
break;
}
}
void DPSInitPrivateSpaceFields(DPSPrivSpace s)
{
s->creator = true;
}
void DPSInitPrivateContextFields(DPSPrivContext c, DPSPrivSpace s)
{
c->creator = true;
c->zombie = false;
if (!s->creator) {
c->procs = XDPSconvProcs;
c->nameEncoding = dps_strings;
}
}
void DPSInitPrivateTextContextFields(DPSPrivContext c, DPSPrivSpace s)
{
c->creator = true;
c->zombie = false;
c->space = (DPSSpace) s;
c->next = s->firstContext;
s->firstContext = c;
}
long int DPSLastUserObjectIndex = 0;
long int DPSNewUserObjectIndex (void)
{
return (DPSLastUserObjectIndex++);
}
void XDPSSetProcs (void)
{
DPSCheckInitClientGlobals ();
if (!textCtxProcs)
{
textCtxProcs = (DPSProcs) DPScalloc (sizeof (DPSProcsRec), 1);
DPSInitCommonTextContextProcs(textCtxProcs);
DPSInitSysNames();
}
if (!ctxProcs)
{
ctxProcs = (DPSProcs) DPScalloc (sizeof (DPSProcsRec), 1);
DPSInitCommonContextProcs(ctxProcs);
DPSInitPrivateContextProcs(ctxProcs);
}
if (!XDPSconvProcs)
XDPSconvProcs = (DPSProcs) DPScalloc (sizeof (DPSProcsRec), 1);
if (!XDPSrawProcs)
XDPSrawProcs = ctxProcs;
*XDPSconvProcs = *ctxProcs;
XDPSconvProcs->BinObjSeqWrite = textCtxProcs->BinObjSeqWrite;
XDPSconvProcs->WriteStringChars = textCtxProcs->WriteStringChars;
XDPSconvProcs->WritePostScript = textCtxProcs->WritePostScript;
XDPSconvProcs->WriteNumString = textCtxProcs->WriteNumString;
}
void DPSInitPrivateContextProcs(DPSProcs p)
{
p->FlushContext = procFlushContext;
p->ResetContext = procResetContext;
p->AwaitReturnValues = procAwaitReturnValues;
}
DPSContext XDPSCreateSimpleContext (
Display *dpy,
Drawable draw,
GC gc,
int x,
int y,
DPSTextProc textProc,
DPSErrorProc errorProc,
DPSSpace space)
{
XDPSPrivContext xwh = XDPSCreatePrivContextRec (dpy, draw, gc, x, y,
0, DefaultStdCMap,
DefaultStdCMap, 0, false);
DPSContext newCtxt;
if (xwh == NIL)
return (NIL);
else
{
newCtxt = DPSCreateContext ((char *) xwh, textProc, errorProc, space);
if (newCtxt == NIL)
free ((char *) xwh);
return (newCtxt);
}
}
DPSContext XDPSCreateContext (
Display *dpy,
Drawable draw,
GC gc,
int x,
int y,
unsigned int eventmask,
XStandardColormap *grayramp,
XStandardColormap *ccube,
int actual,
DPSTextProc textProc,
DPSErrorProc errorProc,
DPSSpace space)
{
XDPSPrivContext xwh = XDPSCreatePrivContextRec (dpy, draw, gc, x, y,
eventmask, grayramp,
ccube, actual, false);
DPSContext newCtxt;
if (xwh == NIL)
return (NIL);
else
{
newCtxt = DPSCreateContext ((char *) xwh, textProc, errorProc, space);
if (newCtxt == NIL)
free ((char *) xwh);
return (newCtxt);
}
}
DPSContext XDPSCreateSecureContext (
Display *dpy,
Drawable draw,
GC gc,
int x,
int y,
unsigned int eventmask,
XStandardColormap *grayramp,
XStandardColormap *ccube,
int actual,
DPSTextProc textProc,
DPSErrorProc errorProc,
DPSSpace space)
{
XDPSPrivContext xwh = XDPSCreatePrivContextRec (dpy, draw, gc, x, y,
eventmask, grayramp,
ccube, actual, true);
DPSContext newCtxt;
if (xwh == NIL)
return (NIL);
else
{
newCtxt = DPSCreateContext ((char *) xwh, textProc, errorProc, space);
if (newCtxt == NIL)
free ((char *) xwh);
return (newCtxt);
}
}
DPSContext XDPSContextFromSharedID (dpy, cid, textProc, errorProc)
Display *dpy;
ContextPSID cid;
DPSTextProc textProc;
DPSErrorProc errorProc;
{
DPSPrivContext c;
DPSPrivSpace s;
ContextXID cxid;
SpaceXID sxid;
XDPSPrivContext xwh;
if (DPSInitialize () != 0)
return (NIL);
c = FindPrivContext (dpy, cid);
if (c != NIL)
return ((DPSContext) c);
xwh = XDPSCreatePrivContextRec (dpy, 0, 0, 0, 0, 0, NIL, NIL, 0, false);
if (xwh == NIL)
return (NIL);
else if (XDPSLIDFromContext (dpy, cid, &cxid, &sxid) != 1)
{
free ((char *) xwh);
return (NIL);
}
xwh->cxid = cxid;
if (spaceProcs == NIL)
{
spaceProcs = (DPSSpaceProcs) DPScalloc (sizeof (DPSSpaceProcsRec), 1);
DPSInitCommonSpaceProcs(spaceProcs);
}
s = spaces;
while (s != NIL)
if ((SpaceXID)s->sid == sxid && ((XDPSPrivContext) s->wh)->dpy == dpy)
break;
else
s = s->next;
if (s == NIL) /* Create new space record. */
{
s = (DPSPrivSpace) DPScalloc (sizeof (DPSPrivSpaceRec), 1);
s->procs = spaceProcs;
s->lastNameIndex = -1;
s->sid = sxid;
s->wh = (char *) xwh;
s->creator = false;
s->next = spaces;
spaces = s;
}
c = (DPSPrivContext) DPScalloc (sizeof (DPSPrivContextRec), 1);
c->space = (DPSSpace) s;
c->procs = XDPSconvProcs;
c->textProc = textProc;
c->errorProc = errorProc;
c->programEncoding = DPSDefaultProgramEncoding;
c->nameEncoding = dps_strings;
c->next = s->firstContext;
s->firstContext = c;
c->lastNameIndex = s->lastNameIndex;
c->cid = cid;
c->numstringOffsets = NULL;
c->creator = false;
c->zombie = false;
c->numFormat = XDPSNumFormat (dpy);
c->wh = (char *) xwh;
xwh->ctxt = (DPSContext) c;
return ((DPSContext) c);
}
void DPSChangeEncoding (ctxt, newProgEncoding, newNameEncoding)
DPSContext ctxt;
DPSProgramEncoding newProgEncoding;
DPSNameEncoding newNameEncoding;
{
if (ctxt->programEncoding != newProgEncoding ||
ctxt->nameEncoding != newNameEncoding)
{
DPSPrivContext cc = (DPSPrivContext) ctxt;
DPSPrivSpace ss = (DPSPrivSpace) (cc->space);
if ((!cc->creator || !ss->creator) && newNameEncoding != dps_strings)
{
DPSSafeSetLastNameIndex(ctxt);
if (cc->errorProc != NIL)
(*cc->errorProc) (ctxt, dps_err_encodingCheck,
(unsigned long) newNameEncoding,
(unsigned long) newProgEncoding);
return;
}
if (ctxt->procs == textCtxProcs)
{
ctxt->programEncoding = newProgEncoding;
ctxt->nameEncoding = newNameEncoding;
}
else
XDPSSetContextEncoding (ctxt, newProgEncoding, newNameEncoding);
}
}
DPSSpace XDPSSpaceFromSharedID (dpy, sid)
Display *dpy;
SpaceXID sid;
{
DPSPrivSpace s;
XDPSPrivContext xwh;
if (DPSInitialize () != 0)
return (NIL);
if (spaceProcs == NIL)
{
spaceProcs = (DPSSpaceProcs) DPScalloc (sizeof (DPSSpaceProcsRec), 1);
DPSInitCommonSpaceProcs(spaceProcs);
}
s = spaces;
while (s != NIL)
if ((SpaceXID)s->sid == sid && ((XDPSPrivContext) s->wh)->dpy == dpy)
break;
else
s = s->next;
if (s == NIL) /* Create new space record. */
{
xwh = XDPSCreatePrivContextRec (dpy, 0, 0, 0, 0, 0, NIL, NIL, 0, false);
if (xwh == NIL)
return (NIL);
s = (DPSPrivSpace) DPScalloc (sizeof (DPSPrivSpaceRec), 1);
s->procs = spaceProcs;
s->lastNameIndex = -1;
s->sid = sid;
s->wh = (char *) xwh;
s->creator = false;
s->next = spaces;
spaces = s;
}
return ((DPSSpace) s);
}
void XDPSUnfreezeContext (ctxt)
DPSContext ctxt;
{
XDPSPrivContext wh = (XDPSPrivContext) (((DPSPrivContext) ctxt)->wh);
if (wh != NIL && wh->cxid != 0)
XDPSSendUnfreeze (wh->dpy, wh->cxid);
}
ContextXID XDPSXIDFromContext (Pdpy, ctxt)
Display **Pdpy;
DPSContext ctxt;
{
XDPSPrivContext xwh = (XDPSPrivContext) (((DPSPrivContext) ctxt)->wh);
if (xwh == NIL || xwh->cxid == 0)
{
*Pdpy = NULL;
return (0);
}
else
{
*Pdpy = xwh->dpy;
return (xwh->cxid);
}
}
SpaceXID XDPSXIDFromSpace (Pdpy, space)
Display **Pdpy;
DPSSpace space;
{
DPSPrivSpace ss = (DPSPrivSpace) space;
XDPSPrivContext xwh = (XDPSPrivContext) ss->wh;
if (xwh != NIL && xwh->dpy != NULL)
{
*Pdpy = xwh->dpy;
return (ss->sid);
}
else
{
*Pdpy = NULL;
return (0);
}
}
DPSContext XDPSContextFromXID (dpy, cxid)
Display *dpy;
ContextXID cxid;
{
DPSPrivContext c;
DPSPrivSpace ss;
for (ss = spaces; ss != NIL; ss = ss->next)
if (((XDPSPrivContext) ss->wh)->dpy == dpy)
for (c = ss->firstContext; c != NIL; c = c->next)
if (((XDPSPrivContext) c->wh)->cxid == cxid)
return ((DPSContext) c);
return (NIL);
}
DPSSpace XDPSSpaceFromXID (dpy, sxid)
Display *dpy;
SpaceXID sxid;
{
DPSPrivSpace ss;
for (ss = spaces; ss != NIL; ss = ss->next)
if ((SpaceXID)ss->sid == sxid && ((XDPSPrivContext) ss->wh)->dpy == dpy)
return ((DPSSpace) ss);
return (NIL);
}
XDPSStatusProc XDPSRegisterStatusProc (ctxt, statusProc)
DPSContext ctxt;
XDPSStatusProc statusProc;
{
DPSPrivContext c = (DPSPrivContext) ctxt;
XDPSStatusProc old = c->statusProc;
if (c->wh != NIL) c->statusProc = statusProc;
return old;
}
XDPSReadyProc XDPSRegisterReadyProc (ctxt, readyProc)
DPSContext ctxt;
XDPSReadyProc readyProc;
{
DPSPrivContext c = (DPSPrivContext) ctxt;
XDPSReadyProc old = c->readyProc;
if (c->wh != NIL) c->readyProc = readyProc;
return old;
}
void XDPSSetStatusMask(ctxt, enableMask, disableMask, nextMask)
DPSContext ctxt;
unsigned long enableMask, disableMask, nextMask;
{
XDPSPrivContext xwh = (XDPSPrivContext) (((DPSPrivContext) ctxt)->wh);
if (xwh != NIL && xwh->cxid != 0)
XDPSLSetStatusMask(xwh->dpy, xwh->cxid, enableMask, disableMask, nextMask);
}
int XDPSGetContextStatus(ctxt)
DPSContext ctxt;
{
DPSPrivContext c = (DPSPrivContext) ctxt;
XDPSPrivContext xwh = (XDPSPrivContext) c->wh;
if (xwh != NIL && xwh->cxid != 0)
return (XDPSLGetStatus(xwh->dpy, xwh->cxid));
else
return (0);
}
void XDPSNotifyWhenReady(ctxt, i0, i1, i2, i3)
DPSContext ctxt;
int i0, i1, i2, i3;
{
DPSPrivContext c = (DPSPrivContext) ctxt;
XDPSPrivContext xwh = (XDPSPrivContext) c->wh;
int i[4];
i[0] = i0;
i[1] = i1;
i[2] = i2;
i[3] = i3;
XDPSLNotifyWhenReady(xwh->dpy, xwh->cxid, i);
}
void XDPSStatusEventHandler (e)
XDPSLStatusEvent *e;
{
DPSPrivContext c = (DPSPrivContext) XDPSContextFromXID(e->display, e->cxid);
if (c == NIL)
return;
c->statusFromEvent = e->status;
if (e->status == PSZOMBIE)
{
c->zombie = true;
if (c->resultTable != NIL) /* Currently waiting for results */
XDPSQuitBlocking = true;
}
if (c->statusProc != NIL)
(*(c->statusProc)) ((DPSContext) c, e->status);
}
void XDPSReadyEventHandler (e)
XDPSLReadyEvent *e;
{
DPSPrivContext c = (DPSPrivContext) XDPSContextFromXID(e->display, e->cxid);
if (c == NIL)
return;
if (c->readyProc != NIL)
(*(c->readyProc)) ((DPSContext) c, e->val);
}
void DPSWarnProc(
DPSContext ctxt,
char *msg)
{
DPSErrorProc ep;
if (DPSInitialize() != 0) return;
ep = DPSGetCurrentErrorBackstop();
if (ep == NULL) ep = DPSDefaultErrorProc;
(*ep)(ctxt, dps_err_warning, (long unsigned int)msg, 0);
}
void DPSFatalProc(
DPSContext ctxt,
char *msg)
{
DPSErrorProc ep;
if (DPSInitialize() != 0) return;
ep = DPSGetCurrentErrorBackstop();
if (ep == NULL) ep = DPSDefaultErrorProc;
(*ep)(ctxt, dps_err_fatal, (long unsigned int)msg, 0);
}
void DPSCantHappen(void)
{
static int locked = 0;
char *msg = "assertion failure or DPSCantHappen";
if (locked > 0) abort();
++locked;
DPSFatalProc((DPSContext)NULL, msg);
/* Fatal proc shouldn't return, but client can override and do anything. */
--locked;
}
/* Procedures for delayed event dispatching */
DPSEventDelivery XDPSSetEventDelivery(
Display *dpy,
DPSEventDelivery newMode)
{
Bool old = XDPSLGetPassEventsFlag(dpy);
switch (newMode) {
case dps_event_pass_through:
XDPSLSetPassEventsFlag(dpy, True);
break;
case dps_event_internal_dispatch:
XDPSLSetPassEventsFlag(dpy, False);
break;
default:
break;
}
if (old) return dps_event_pass_through;
else return dps_event_internal_dispatch;
}
Bool XDPSIsStatusEvent(
XEvent *event,
DPSContext *ctxt,
int *status)
{
Display *d = event->xany.display;
XExtCodes *c = XDPSLGetCodes(d);
XDPSLStatusEvent *se = (XDPSLStatusEvent *) event;
if (c == NULL) return False; /* Not inited on that display;
must be False */
if (!c->first_event) /* Check CSDPS first */
{
if (XDPSLGetCSDPSFakeEventType(d, event) == csdps_status)
{ /* Check CSDPS first */
XDPSLGetCSDPSStatus(d, event, (void **)ctxt, status);
return True;
}
else
return False;
}
if (event->type != c->first_event + PSEVENTSTATUS) return False;
if (ctxt != NULL) *ctxt = XDPSContextFromXID(d, se->cxid);
if (status != NULL) *status = se->status;
return True;
}
Bool XDPSIsOutputEvent(
XEvent *event)
{
Display *d = event->xany.display;
XExtCodes *c = XDPSLGetCodes(d);
CSDPSFakeEventTypes t;
if (c == NULL) return False; /* Not inited on that display;
must be False */
if (!c->first_event) /* Check CSDPS first */
{
if ((t = XDPSLGetCSDPSFakeEventType(d, event)) == csdps_output
|| t == csdps_output_with_len)
return True;
else
return False;
}
return event->type == c->first_event + PSEVENTOUTPUT;
}
Bool XDPSIsDPSEvent(
XEvent *event)
{
Display *d = event->xany.display;
XExtCodes *c = XDPSLGetCodes(d);
if (c == NULL) return False; /* Not inited on that display;
must be False */
if (!c->first_event) /* Check CSDPS first */
{
if (XDPSLGetCSDPSFakeEventType(d, event) != csdps_not)
return True;
else
return False;
}
return event->type >= c->first_event &&
event->type < c->first_event + NPSEVENTS;
}
Bool XDPSDispatchEvent(
XEvent *event)
{
Display *d = event->xany.display;
XExtCodes *c = XDPSLGetCodes(d);
CSDPSFakeEventTypes t;
if (c == NULL) return False; /* Not inited on that display;
must be False */
if (!c->first_event) /* Check CSDPS first */
{
if ((t = XDPSLGetCSDPSFakeEventType(d, event)) != csdps_not)
return(XDPSLDispatchCSDPSFakeEvent(d, event, t));
else
return False;
}
if (event->type == c->first_event + PSEVENTSTATUS) {
XDPSLCallStatusEventHandler(d, event);
} else if (event->type == c->first_event + PSEVENTOUTPUT) {
XDPSLCallOutputEventHandler(d, event);
} else if (event->type == c->first_event + PSEVENTREADY) {
XDPSLCallReadyEventHandler(d, event);
} else return False;
return True;
}
/* L2-DPS/PROTO 9 addition */
Bool XDPSIsReadyEvent(
XEvent *event,
DPSContext *ctxt,
int *val)
{
Display *d = event->xany.display;
XExtCodes *c = XDPSLGetCodes(d);
XDPSLReadyEvent *re = (XDPSLReadyEvent *) event;
if (c == NULL) return False; /* Not inited on that display;
must be False */
if (!c->first_event) /* Check CSDPS first */
{
if (XDPSLGetCSDPSFakeEventType(d, event) == csdps_ready)
{
XDPSLGetCSDPSReady(d, event, (void **)ctxt, val);
return True;
}
else
return False;
}
if (event->type != c->first_event + PSEVENTREADY) return False;
if (ctxt != NULL) *ctxt = XDPSContextFromXID(d, re->cxid);
if (val != NULL) {
val[0] = re->val[0];
val[1] = re->val[1];
val[2] = re->val[2];
val[4] = re->val[3];
}
return True;
}
int XDPSGetProtocolVersion(
Display *dpy)
{
return XDPSLGetVersion(dpy);
}