/* * 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 #include /* sleep() */ #include #include #include #ifdef VMS /* Xlib does not like UNIX defined to any value under VMS. */ #undef UNIX #include #include #else /* VMS */ #include #include #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); }