#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <sys/time.h>
#ifdef GC
#undef GC
#endif
#ifdef VMS
#undef UNIX
#include <decw$include/X.h>
#include <decw$include/Xproto.h>
#include <decw$include/Xlib.h>
#include <decw$include/Xutil.h>
#else
#include <X11/X.h>
#include <X11/Xproto.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#endif
#include "DPS/XDPSlib.h"
#include "DPS/XDPS.h"
#include "dpsprivate.h"
#include "DPS/dpsconfig.h"
#include "publictypes.h"
#include "dpsXpriv.h"
#include "DPS/dpsXclient.h"
#include "DPS/dpsexcept.h"
#include "dpsassert.h"
#ifdef ISC
#include <sys/bsdtypes.h>
#endif
#ifdef __QNX__
#include <sys/select.h>
#endif
#if defined(hpux) || defined(AIXV3)
#define SELECT_TYPE int *
#else
#define SELECT_TYPE fd_set *
#endif
typedef struct _RegstDPY
{
Display *dpy;
int firstEvent;
struct _RegstDPY *next;
unsigned char ctxtTokenType;
unsigned char prefTokenType;
} RegstDPYRec, *PRegstDPY;
int XDPSContextTimedOut = false;
DPSProcs XDPSconvProcs = NIL;
DPSProcs XDPSrawProcs = NIL;
int XDPSQuitBlocking = false;
static DPSClientPrintProc clientPrintProc = NIL;
static PRegstDPY firstDPY = NIL;
static char *format_operands[] = {"1", "2", "3", "4"};
static PRegstDPY IsRegistered (
register Display *dpy)
{
register PRegstDPY rdpy;
for (rdpy = firstDPY; rdpy != NIL; rdpy = rdpy->next)
if (rdpy->dpy == dpy)
return (rdpy);
return (NIL);
}
void XDPSPrivZapDpy(
register Display *dpy)
{
register PRegstDPY rdpy, prev = NIL;
for (rdpy = firstDPY; rdpy != NIL; prev = rdpy,rdpy = rdpy->next)
if (rdpy->dpy == dpy)
{
if (prev == NIL)
firstDPY = rdpy->next;
else
prev->next = rdpy->next;
break;
}
free(rdpy);
}
static int UsuallyFalse (
Display *dpy,
XEvent *event,
char *arg)
{
return((event->type & 0x7F) == X_Error);
}
void XDPSForceEvents (
Display *dpy)
{
XEvent event;
while (XCheckIfEvent (dpy, &event, UsuallyFalse, (char *) NULL)) {
int (*proc)(Display *, XErrorEvent *) = XSetErrorHandler(NULL);
(void) XSetErrorHandler(proc);
if (proc != 0 && event.type < 256)
(void)(*proc)(dpy, &event.xerror);
}
}
static void OutputEventHandler (
register XDPSLOutputEvent *event)
{
PRegstDPY rdpy;
register DPSContext ctxt;
if ((rdpy = IsRegistered (event->display)) == NIL ||
rdpy->firstEvent != event->type)
return;
ctxt = XDPSContextFromXID (event->display, event->cxid);
if (ctxt != NIL)
{
if (ctxt->resultTable != NIL)
XDPSQuitBlocking = true;
(*clientPrintProc) (ctxt, event->data, event->length);
}
}
static int BlockForEvent (
Display *dpy)
{
fd_set readfds;
XDPSQuitBlocking = false;
while (1) {
FD_SET(ConnectionNumber(dpy), &readfds);
if (select (ConnectionNumber(dpy)+1, (SELECT_TYPE) &readfds,
(SELECT_TYPE) NULL, (SELECT_TYPE) NULL,
(struct timeval *) NULL) < 0) {
if (errno == EINTR) {
errno = 0;
continue;
}
return (-1);
} else {
XDPSForceEvents (dpy);
if (XDPSQuitBlocking) break;
XNoOp(dpy);
}
}
return (0);
}
void XDPSSetContextEncoding (
DPSContext ctxt,
DPSProgramEncoding progEncoding,
DPSNameEncoding nameEncoding)
{
if ((nameEncoding != dps_indexed && nameEncoding != dps_strings) ||
(progEncoding != dps_ascii && progEncoding != dps_encodedTokens &&
progEncoding != dps_binObjSeq))
{
if (ctxt->errorProc != NIL)
(*ctxt->errorProc) (ctxt, dps_err_encodingCheck,
nameEncoding, progEncoding);
return;
}
else if (progEncoding == dps_ascii || progEncoding == dps_encodedTokens ||
nameEncoding == dps_strings)
ctxt->procs = XDPSconvProcs;
else
ctxt->procs = XDPSrawProcs;
ctxt->nameEncoding = nameEncoding;
ctxt->programEncoding = progEncoding;
}
void DPSDefaultTextBackstop (ctxt, buf, count)
DPSContext ctxt;
char *buf;
long unsigned int count;
{
if (buf == NULL || count == 0)
{
(void) fflush(stdout);
return;
}
(void) fwrite (buf, sizeof (char), count, stdout);
(void) fflush (stdout);
}
void DPSInitClient(
DPSTextProc textProc,
void (*releaseProc) (char *, char *))
{
DPSAssert (releaseProc != NIL);
XDPSSetProcs ();
DPSSetTextBackstop (DPSDefaultTextBackstop);
DPSSetErrorBackstop (DPSDefaultErrorProc);
}
DPSNumFormat XDPSNumFormat (
Display *dpy)
{
PRegstDPY rdpy;
if ((rdpy = IsRegistered (dpy)) == NIL)
return ((DPSNumFormat) -1);
else
return ((rdpy->ctxtTokenType < DPS_HI_NATIVE) ? dps_ieee : dps_native);
}
XDPSPrivContext XDPSCreatePrivContextRec (
Display *dpy,
Drawable drawable,
GC gc,
int x,
int y,
unsigned int eventmask,
XStandardColormap *grayramp,
XStandardColormap *ccube,
int actual,
int secure)
{
int event_base;
int token_type;
char *num_format_name;
PRegstDPY rdpy;
XDPSPrivContext wh;
if (DPSInitialize() != 0) return(NULL);
if ((rdpy = IsRegistered (dpy)) == NIL)
{
event_base = XDPSLInit (dpy, &token_type, &num_format_name);
if (event_base >= 0 &&
(rdpy = (PRegstDPY) calloc (sizeof (RegstDPYRec), 1)))
{
XDPSLSetTextEventHandler (dpy, (XDPSLEventHandler) OutputEventHandler);
XDPSLSetStatusEventHandler (dpy, (XDPSLEventHandler) XDPSStatusEventHandler);
XDPSLSetReadyEventHandler (dpy, (XDPSLEventHandler) XDPSReadyEventHandler);
XDPSLInitDisplayFlags(dpy);
rdpy->dpy = dpy;
rdpy->firstEvent = event_base;
rdpy->next = firstDPY;
rdpy->prefTokenType = (unsigned char) token_type;
if (strcmp (num_format_name, DPS_FORMATNAME) == 0)
rdpy->ctxtTokenType = DPS_DEF_TOKENTYPE;
else
#if SWAPBITS
rdpy->ctxtTokenType = DPS_LO_IEEE;
#else
rdpy->ctxtTokenType = DPS_HI_IEEE;
#endif
firstDPY = rdpy;
}
else
return (NULL);
}
if ((wh = (XDPSPrivContext) calloc (sizeof (XDPSPrivContextRec), 1)) != 0)
{
wh->dpy = dpy;
wh->drawable = drawable;
wh->gc = gc;
wh->x = x;
wh->y = y;
wh->eventmask = eventmask;
wh->grayramp = grayramp;
wh->ccube = ccube;
wh->actual = actual;
wh->newObjFormat = format_operands[rdpy->ctxtTokenType - DPS_HI_IEEE];
wh->secure = secure;
return (wh);
}
else
return (NULL);
}
DPSNumFormat DPSCreatePrivContext (
XDPSPrivContext wh,
DPSContext ctxt,
ContextPSID *cidP,
SpaceXID *sxidP,
boolean newSpace,
DPSClientPrintProc printProc)
{
PRegstDPY rdpy;
if (clientPrintProc == NIL)
clientPrintProc = printProc;
if ((rdpy = IsRegistered (wh->dpy)) == NIL)
return ((DPSNumFormat) -1);
if (newSpace || sxidP == NIL)
wh->cxid = XDPSLCreateContextAndSpace (wh->dpy, wh->drawable, wh->gc,
wh->x, wh->y, wh->eventmask,
wh->grayramp, wh->ccube,
wh->actual, cidP, sxidP,
wh->secure);
else
wh->cxid = XDPSLCreateContext (wh->dpy, *sxidP, wh->drawable, wh->gc,
wh->x, wh->y, wh->eventmask,
wh->grayramp, wh->ccube, wh->actual, cidP,
wh->secure);
if (wh->cxid == None) return((DPSNumFormat) -1);
wh->ctxt = ctxt;
if (wh->newObjFormat != NIL)
{
XDPSLGiveInput (wh->dpy, wh->cxid, wh->newObjFormat, 1);
XDPSLGiveInput (wh->dpy, wh->cxid, " setobjectformat\n", 17);
}
if (rdpy->ctxtTokenType != DPS_DEF_TOKENTYPE)
ctxt->procs = XDPSconvProcs;
return ((rdpy->ctxtTokenType < DPS_HI_NATIVE) ? dps_ieee : dps_native);
}
void DPSIncludePrivContext (
XDPSPrivContext wh,
DPSContext ctxt,
ContextPSID cid,
SpaceXID sxid,
DPSClientPrintProc printProc)
{
XDPSPrivContext newWh;
SpaceXID space;
if (clientPrintProc == NIL)
clientPrintProc = printProc;
newWh = (XDPSPrivContext) calloc (sizeof (XDPSPrivContextRec), 1);
if (!newWh) DPSOutOfMemory();
*newWh = *wh;
if (IsRegistered (wh->dpy) != NIL)
{
newWh->cxid = XDPSLCreateContextFromID (wh->dpy, cid, &space);
DPSAssertWarn (space == sxid, ctxt, "attempting context from context ID from different space");
newWh->ctxt = ctxt;
if (wh->newObjFormat != NIL)
{
XDPSLGiveInput (wh->dpy, newWh->cxid, wh->newObjFormat, 1);
XDPSLGiveInput (wh->dpy, newWh->cxid, " setobjectformat\n", 17);
}
}
else
{
newWh->cxid = 0;
newWh->ctxt = NIL;
}
(void) DPSSetWh (ctxt, (char *) newWh);
}
void DPSSendPostScript (
register XDPSPrivContext wh,
DPSClientPrintProc printProc,
ContextPSID cid,
char *buffer,
long int count,
boolean (*returnControl)(void))
{
boolean blocking = buffer == NIL;
if (IsRegistered (wh->dpy) == NIL)
(*printProc) (wh->ctxt, NIL, 0);
else {
if (count > 0)
XDPSLGiveInput (wh->dpy, wh->cxid, buffer, count);
if (blocking) {
XDPSLFlush (wh->dpy);
if (BlockForEvent (wh->dpy) < 0 && wh->ctxt->errorProc != NIL) {
(*(wh->ctxt->errorProc)) (wh->ctxt, dps_err_closedDisplay,
ConnectionNumber(wh->dpy),
0);
}
}
DPSCheckRaiseError(wh->ctxt);
}
}
void DPSSendInterrupt (
XDPSPrivContext wh,
ContextPSID cid,
DPSClientPrintProc printProc)
{
XDPSLNotifyContext (wh->dpy, wh->cxid, PSINTERRUPT);
}
void DPSSendEOF (
XDPSPrivContext wh,
ContextPSID cid,
DPSClientPrintProc printProc)
{
XDPSLReset (wh->dpy, wh->cxid);
}
void DPSSendTerminate (
XDPSPrivContext wh,
ContextPSID cid,
DPSClientPrintProc printProc)
{
XDPSLNotifyContext (wh->dpy, wh->cxid, PSKILL);
}
void XDPSSendUnfreeze (
Display *dpy,
ContextXID cxid)
{
XDPSLNotifyContext (dpy, cxid, PSUNFREEZE);
}
void DPSSendDestroySpace(
XDPSPrivContext wh,
SpaceXID sxid,
DPSClientPrintProc printProc)
{
XDPSLDestroySpace (wh->dpy, sxid);
}
void DPSOutOfMemory (void)
{
DPSFatalProc(NULL, "DPS Client Library Error: Out of memory.\n");
exit (1);
}