824N/A/*
824N/A * dpsXpriv.c
824N/A *
824N/A * (c) Copyright 1988-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/dpsXpriv.c,v 1.7 2002/03/05 21:50:14 herrb Exp $ */
824N/A
824N/A#include <stdlib.h>
824N/A#include <stdio.h>
824N/A#include <errno.h>
824N/A#include <string.h>
824N/A#include <unistd.h>
824N/A#include <sys/time.h>
824N/A
824N/A#ifdef GC
824N/A#undef GC
824N/A#endif /* GC */
824N/A
824N/A#ifdef VMS
824N/A/* Xlib does not like UNIX defined to any value under VMS. */
824N/A#undef UNIX
824N/A#include <decw$include/X.h>
824N/A#include <decw$include/Xproto.h>
824N/A#include <decw$include/Xlib.h>
824N/A#include <decw$include/Xutil.h>
824N/A#else /* VMS */
824N/A#include <X11/X.h>
824N/A#include <X11/Xproto.h>
824N/A#include <X11/Xlib.h>
824N/A#include <X11/Xutil.h>
824N/A#endif /* VMS */
824N/A#include "DPS/XDPSlib.h"
824N/A#include "DPS/XDPS.h"
824N/A#include "dpsprivate.h"
824N/A#include "DPS/dpsconfig.h"
824N/A#include "publictypes.h"
824N/A#include "dpsXpriv.h"
824N/A#include "DPS/dpsXclient.h"
824N/A#include "DPS/dpsexcept.h"
824N/A#include "dpsassert.h"
824N/A
824N/A#ifdef ISC
824N/A#include <sys/bsdtypes.h>
824N/A#endif
824N/A
824N/A#ifdef __QNX__
824N/A#include <sys/select.h>
824N/A#endif
824N/A
824N/A#if defined(hpux) || defined(AIXV3)
824N/A#define SELECT_TYPE int *
824N/A#else
824N/A#define SELECT_TYPE fd_set *
824N/A#endif
824N/A
824N/Atypedef struct _RegstDPY
824N/A {
824N/A Display *dpy;
824N/A int firstEvent;
824N/A struct _RegstDPY *next;
824N/A unsigned char ctxtTokenType; /* establish for each context. */
824N/A unsigned char prefTokenType; /* ...of the server. */
824N/A } RegstDPYRec, *PRegstDPY;
824N/A
824N/A
824N/A/* XDPSContextTimedOut is set to true by the BlockForEvent routine
824N/A when expected return values are not received within a certain
824N/A amount of time. In this case, BlockForEvent will return and the
824N/A higher callers may take appropriate action to avoid deadlocks. */
824N/Aint XDPSContextTimedOut = false; /* Unimplemented */
824N/ADPSProcs XDPSconvProcs = NIL;
824N/ADPSProcs XDPSrawProcs = NIL;
824N/A
824N/A/* XDPSQuitBlocking is set to false by the BlockForEvent routine and
824N/A becomes true if either a zombie status event or an output event
824N/A is received for the context waiting for return values. */
824N/Aint XDPSQuitBlocking = false;
824N/A
824N/A
824N/Astatic DPSClientPrintProc clientPrintProc = NIL;
824N/Astatic PRegstDPY firstDPY = NIL;
824N/A/* operands for "setobjectformat" if we must agree with server. */
824N/Astatic char *format_operands[] = {"1", "2", "3", "4"};
824N/A
824N/A
824N/A
824N/Astatic PRegstDPY IsRegistered (
824N/A register Display *dpy)
824N/A{
824N/A register PRegstDPY rdpy;
824N/A
824N/A for (rdpy = firstDPY; rdpy != NIL; rdpy = rdpy->next)
824N/A if (rdpy->dpy == dpy)
824N/A return (rdpy);
824N/A return (NIL);
824N/A}
824N/A
824N/A
824N/Avoid XDPSPrivZapDpy(
824N/A register Display *dpy)
824N/A{
824N/A register PRegstDPY rdpy, prev = NIL;
824N/A
824N/A for (rdpy = firstDPY; rdpy != NIL; prev = rdpy,rdpy = rdpy->next)
824N/A if (rdpy->dpy == dpy)
824N/A {
824N/A if (prev == NIL)
824N/A firstDPY = rdpy->next;
824N/A else
824N/A prev->next = rdpy->next;
824N/A break;
824N/A }
824N/A free(rdpy);
824N/A}
824N/A
824N/A
824N/A/* ARGSUSED */
824N/Astatic int UsuallyFalse (
824N/A Display *dpy,
824N/A XEvent *event,
824N/A char *arg)
824N/A{
824N/A return((event->type & 0x7F) == X_Error);
824N/A}
824N/A
824N/Avoid XDPSForceEvents (
824N/A Display *dpy)
824N/A{
824N/A XEvent event;
824N/A
824N/A while (XCheckIfEvent (dpy, &event, UsuallyFalse, (char *) NULL)) {
824N/A int (*proc)(Display *, XErrorEvent *) = XSetErrorHandler(NULL);
824N/A (void) XSetErrorHandler(proc);
824N/A if (proc != 0 && event.type < 256)
824N/A (void)(*proc)(dpy, &event.xerror);
824N/A }
824N/A}
824N/A
824N/A
824N/Astatic void OutputEventHandler (
824N/A register XDPSLOutputEvent *event)
824N/A{
824N/A PRegstDPY rdpy;
824N/A register DPSContext ctxt;
824N/A
824N/A if ((rdpy = IsRegistered (event->display)) == NIL ||
824N/A rdpy->firstEvent != event->type)
824N/A return;
824N/A
824N/A ctxt = XDPSContextFromXID (event->display, event->cxid);
824N/A if (ctxt != NIL)
824N/A {
824N/A if (ctxt->resultTable != NIL)
824N/A XDPSQuitBlocking = true;
824N/A (*clientPrintProc) (ctxt, event->data, event->length);
824N/A }
824N/A}
824N/A
824N/A
824N/Astatic int BlockForEvent (
824N/A Display *dpy)
824N/A{
824N/A fd_set readfds;
824N/A
824N/A XDPSQuitBlocking = false;
824N/A /* XDPSQuitBlocking becomes true if a zombie status event or
824N/A any output event is received by the status event handler for
824N/A the currently-awaiting-results context. */
824N/A while (1) {
824N/A FD_SET(ConnectionNumber(dpy), &readfds);
824N/A if (select (ConnectionNumber(dpy)+1, (SELECT_TYPE) &readfds,
824N/A (SELECT_TYPE) NULL, (SELECT_TYPE) NULL,
824N/A (struct timeval *) NULL) < 0) {
824N/A if (errno == EINTR) {
824N/A /* Ignore interrupt signals */
824N/A errno = 0;
824N/A continue;
824N/A }
824N/A return (-1); /* Broken connection (errno == EBADF) */
824N/A } else {
824N/A XDPSForceEvents (dpy);
824N/A if (XDPSQuitBlocking) break;
824N/A XNoOp(dpy);
824N/A /* The noop is necessary to force proper behavior when the
824N/A connection goes away - listen carefully! When the dpy
824N/A connection is closed, the above select returns indicating
824N/A activity on the connection. We call XDPSForceEvents, which
824N/A calls XCheckIfEvent, which ultimately may call XFlush
824N/A (if there are no events queued). The XNoOp call puts
824N/A a message in the outgoing queue, so that XFlush is forced
824N/A to write on the connection. When it tries to write, the
824N/A error condition will be noted and XIOError will be called,
824N/A usually causing the application to terminate. Note that
824N/A the error won't happen until the second time thru this
824N/A loop, but that's ok. */
824N/A }
824N/A }
824N/A return (0);
824N/A}
824N/A
824N/A
824N/Avoid XDPSSetContextEncoding (
824N/A DPSContext ctxt,
824N/A DPSProgramEncoding progEncoding,
824N/A DPSNameEncoding nameEncoding)
824N/A{
824N/A /* This routine should not be called if ctxt is a text context */
824N/A
824N/A if ((nameEncoding != dps_indexed && nameEncoding != dps_strings) ||
824N/A (progEncoding != dps_ascii && progEncoding != dps_encodedTokens &&
824N/A progEncoding != dps_binObjSeq))
824N/A {
824N/A if (ctxt->errorProc != NIL)
824N/A (*ctxt->errorProc) (ctxt, dps_err_encodingCheck,
824N/A nameEncoding, progEncoding);
824N/A return;
824N/A }
824N/A else if (progEncoding == dps_ascii || progEncoding == dps_encodedTokens ||
824N/A nameEncoding == dps_strings)
824N/A ctxt->procs = XDPSconvProcs;
824N/A else
824N/A ctxt->procs = XDPSrawProcs;
824N/A
824N/A ctxt->nameEncoding = nameEncoding;
824N/A ctxt->programEncoding = progEncoding;
824N/A}
824N/A
824N/A
824N/A/* ARGSUSED */
824N/Avoid DPSDefaultTextBackstop (ctxt, buf, count)
824N/A DPSContext ctxt;
824N/A char *buf;
824N/A long unsigned int count;
824N/A{
824N/A if (buf == NULL || count == 0)
824N/A {
824N/A (void) fflush(stdout);
824N/A return;
824N/A }
824N/A (void) fwrite (buf, sizeof (char), count, stdout);
824N/A (void) fflush (stdout);
824N/A}
824N/A
824N/A/* ARGSUSED */
824N/Avoid DPSInitClient(
824N/A DPSTextProc textProc,
824N/A void (*releaseProc) (char *, char *))
824N/A{
824N/A DPSAssert (releaseProc != NIL);
824N/A XDPSSetProcs ();
824N/A DPSSetTextBackstop (DPSDefaultTextBackstop);
824N/A DPSSetErrorBackstop (DPSDefaultErrorProc);
824N/A}
824N/A
824N/A
824N/ADPSNumFormat XDPSNumFormat (
824N/A Display *dpy)
824N/A{
824N/A PRegstDPY rdpy;
824N/A
824N/A if ((rdpy = IsRegistered (dpy)) == NIL)
824N/A return ((DPSNumFormat) -1);
824N/A else
824N/A return ((rdpy->ctxtTokenType < DPS_HI_NATIVE) ? dps_ieee : dps_native);
824N/A}
824N/A
824N/AXDPSPrivContext XDPSCreatePrivContextRec (
824N/A Display *dpy,
824N/A Drawable drawable,
824N/A GC gc,
824N/A int x,
824N/A int y,
824N/A unsigned int eventmask,
824N/A XStandardColormap *grayramp,
824N/A XStandardColormap *ccube,
824N/A int actual,
824N/A int secure)
824N/A{
824N/A int event_base;
824N/A int token_type; /* From server. */
824N/A char *num_format_name; /* From server. */
824N/A PRegstDPY rdpy;
824N/A XDPSPrivContext wh;
824N/A
824N/A if (DPSInitialize() != 0) return(NULL);
824N/A if ((rdpy = IsRegistered (dpy)) == NIL)
824N/A {
824N/A /* DPS extension on this dpy? */
824N/A event_base = XDPSLInit (dpy, &token_type, &num_format_name);
824N/A if (event_base >= 0 &&
824N/A (rdpy = (PRegstDPY) calloc (sizeof (RegstDPYRec), 1)))
824N/A {
824N/A XDPSLSetTextEventHandler (dpy, (XDPSLEventHandler) OutputEventHandler);
824N/A XDPSLSetStatusEventHandler (dpy, (XDPSLEventHandler) XDPSStatusEventHandler);
824N/A XDPSLSetReadyEventHandler (dpy, (XDPSLEventHandler) XDPSReadyEventHandler);
824N/A XDPSLInitDisplayFlags(dpy);
824N/A rdpy->dpy = dpy;
824N/A rdpy->firstEvent = event_base;
824N/A rdpy->next = firstDPY;
824N/A
824N/A rdpy->prefTokenType = (unsigned char) token_type;
824N/A
824N/A if (strcmp (num_format_name, DPS_FORMATNAME) == 0)
824N/A rdpy->ctxtTokenType = DPS_DEF_TOKENTYPE;
824N/A else
824N/A /* Everybody must talk ieee! */
824N/A#if SWAPBITS
824N/A rdpy->ctxtTokenType = DPS_LO_IEEE;
824N/A#else /* SWAPBITS */
824N/A rdpy->ctxtTokenType = DPS_HI_IEEE;
824N/A#endif /* SWAPBITS */
824N/A
824N/A firstDPY = rdpy;
824N/A }
824N/A else
824N/A return (NULL);
824N/A }
824N/A
824N/A if ((wh = (XDPSPrivContext) calloc (sizeof (XDPSPrivContextRec), 1)) != 0)
824N/A {
824N/A wh->dpy = dpy;
824N/A wh->drawable = drawable;
824N/A wh->gc = gc;
824N/A wh->x = x;
824N/A wh->y = y;
824N/A wh->eventmask = eventmask;
824N/A wh->grayramp = grayramp;
824N/A wh->ccube = ccube;
824N/A wh->actual = actual;
824N/A wh->newObjFormat = format_operands[rdpy->ctxtTokenType - DPS_HI_IEEE];
824N/A wh->secure = secure;
824N/A return (wh);
824N/A }
824N/A else
824N/A return (NULL);
824N/A}
824N/A
824N/A
824N/ADPSNumFormat DPSCreatePrivContext (
824N/A XDPSPrivContext wh,
824N/A DPSContext ctxt,
824N/A ContextPSID *cidP,
824N/A SpaceXID *sxidP,
824N/A boolean newSpace,
824N/A DPSClientPrintProc printProc)
824N/A{
824N/A PRegstDPY rdpy;
824N/A
824N/A if (clientPrintProc == NIL)
824N/A clientPrintProc = printProc;
824N/A
824N/A if ((rdpy = IsRegistered (wh->dpy)) == NIL)
824N/A return ((DPSNumFormat) -1);
824N/A
824N/A if (newSpace || sxidP == NIL)
824N/A wh->cxid = XDPSLCreateContextAndSpace (wh->dpy, wh->drawable, wh->gc,
824N/A wh->x, wh->y, wh->eventmask,
824N/A wh->grayramp, wh->ccube,
824N/A wh->actual, cidP, sxidP,
824N/A wh->secure); /* L2-DPS/PROTO 9 */
824N/A else
824N/A wh->cxid = XDPSLCreateContext (wh->dpy, *sxidP, wh->drawable, wh->gc,
824N/A wh->x, wh->y, wh->eventmask,
824N/A wh->grayramp, wh->ccube, wh->actual, cidP,
824N/A wh->secure); /* L2-DPS/PROTO 9 */
824N/A if (wh->cxid == None) return((DPSNumFormat) -1);
824N/A wh->ctxt = ctxt;
824N/A if (wh->newObjFormat != NIL)
824N/A {
824N/A XDPSLGiveInput (wh->dpy, wh->cxid, wh->newObjFormat, 1);
824N/A XDPSLGiveInput (wh->dpy, wh->cxid, " setobjectformat\n", 17);
824N/A }
824N/A
824N/A if (rdpy->ctxtTokenType != DPS_DEF_TOKENTYPE)
824N/A ctxt->procs = XDPSconvProcs;
824N/A return ((rdpy->ctxtTokenType < DPS_HI_NATIVE) ? dps_ieee : dps_native);
824N/A}
824N/A
824N/A
824N/Avoid DPSIncludePrivContext (
824N/A XDPSPrivContext wh,
824N/A DPSContext ctxt,
824N/A ContextPSID cid,
824N/A SpaceXID sxid,
824N/A DPSClientPrintProc printProc)
824N/A{
824N/A XDPSPrivContext newWh;
824N/A SpaceXID space;
824N/A
824N/A if (clientPrintProc == NIL)
824N/A clientPrintProc = printProc;
824N/A
824N/A newWh = (XDPSPrivContext) calloc (sizeof (XDPSPrivContextRec), 1);
824N/A if (!newWh) DPSOutOfMemory();
824N/A *newWh = *wh;
824N/A if (IsRegistered (wh->dpy) != NIL)
824N/A {
824N/A newWh->cxid = XDPSLCreateContextFromID (wh->dpy, cid, &space);
824N/A DPSAssertWarn (space == sxid, ctxt, "attempting context from context ID from different space");
824N/A newWh->ctxt = ctxt;
824N/A /* Did we have to change object format for parent context? */
824N/A /* Note: the child context must inherit the object format of
824N/A its parent. When this happens in the server there
824N/A will be no need for the following code segment. */
824N/A if (wh->newObjFormat != NIL) /* Yes, do it for the child too. */
824N/A {
824N/A XDPSLGiveInput (wh->dpy, newWh->cxid, wh->newObjFormat, 1);
824N/A XDPSLGiveInput (wh->dpy, newWh->cxid, " setobjectformat\n", 17);
824N/A }
824N/A }
824N/A else
824N/A {
824N/A newWh->cxid = 0; /* Must not refer to a good context. */
824N/A newWh->ctxt = NIL;
824N/A }
824N/A
824N/A (void) DPSSetWh (ctxt, (char *) newWh);
824N/A}
824N/A
824N/A/* ARGSUSED */
824N/Avoid DPSSendPostScript (
824N/A register XDPSPrivContext wh,
824N/A DPSClientPrintProc printProc,
824N/A ContextPSID cid,
824N/A char *buffer,
824N/A long int count,
824N/A boolean (*returnControl)(void))
824N/A{
824N/A boolean blocking = buffer == NIL;
824N/A
824N/A if (IsRegistered (wh->dpy) == NIL)
824N/A (*printProc) (wh->ctxt, NIL, 0);
824N/A else {
824N/A if (count > 0)
824N/A XDPSLGiveInput (wh->dpy, wh->cxid, buffer, count);
824N/A
824N/A if (blocking) {
824N/A XDPSLFlush (wh->dpy);
824N/A if (BlockForEvent (wh->dpy) < 0 && wh->ctxt->errorProc != NIL) {
824N/A (*(wh->ctxt->errorProc)) (wh->ctxt, dps_err_closedDisplay,
824N/A ConnectionNumber(wh->dpy),
824N/A 0);
824N/A }
824N/A }
824N/A DPSCheckRaiseError(wh->ctxt);
824N/A }
824N/A}
824N/A
824N/A
824N/A/* ARGSUSED */
824N/Avoid DPSSendInterrupt (
824N/A XDPSPrivContext wh,
824N/A ContextPSID cid,
824N/A DPSClientPrintProc printProc)
824N/A{
824N/A XDPSLNotifyContext (wh->dpy, wh->cxid, PSINTERRUPT);
824N/A}
824N/A
824N/A
824N/A/* ARGSUSED */
824N/Avoid DPSSendEOF (
824N/A XDPSPrivContext wh,
824N/A ContextPSID cid,
824N/A DPSClientPrintProc printProc)
824N/A{
824N/A XDPSLReset (wh->dpy, wh->cxid);
824N/A}
824N/A
824N/A
824N/A/* ARGSUSED */
824N/Avoid DPSSendTerminate (
824N/A XDPSPrivContext wh,
824N/A ContextPSID cid,
824N/A DPSClientPrintProc printProc)
824N/A{
824N/A XDPSLNotifyContext (wh->dpy, wh->cxid, PSKILL);
824N/A}
824N/A
824N/A
824N/Avoid XDPSSendUnfreeze (
824N/A Display *dpy,
824N/A ContextXID cxid)
824N/A{
824N/A XDPSLNotifyContext (dpy, cxid, PSUNFREEZE);
824N/A}
824N/A
824N/A
824N/A/* ARGSUSED */
824N/Avoid DPSSendDestroySpace(
824N/A XDPSPrivContext wh,
824N/A SpaceXID sxid,
824N/A DPSClientPrintProc printProc)
824N/A{
824N/A XDPSLDestroySpace (wh->dpy, sxid);
824N/A}
824N/A
824N/A
824N/Avoid DPSOutOfMemory (void)
824N/A{
824N/A DPSFatalProc(NULL, "DPS Client Library Error: Out of memory.\n");
824N/A exit (1);
824N/A}