mirror of
https://github.com/Stichting-MINIX-Research-Foundation/xsrc.git
synced 2025-09-09 12:49:44 -04:00
2236 lines
59 KiB
C
2236 lines
59 KiB
C
/*
|
|
* XDPS.c -- implementation of low-level Xlib routines for XDPS extension
|
|
*
|
|
* (c) Copyright 1989-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: xc/lib/dps/XDPS.c,v 1.5 2003/10/24 15:50:20 tsi Exp $ */
|
|
|
|
#define NEED_EVENTS
|
|
#define NEED_REPLIES
|
|
|
|
#include <stdio.h>
|
|
/* Include this first so that Xasync.h, included from Xlibint.h, can find
|
|
the definition of NOFILE */
|
|
#include <stdlib.h>
|
|
#include <sys/param.h>
|
|
#include <X11/Xlibint.h>
|
|
#include <X11/Xatom.h>
|
|
#include <X11/Xutil.h>
|
|
|
|
#include "DPS/XDPS.h"
|
|
#include "DPS/XDPSproto.h"
|
|
#include "DPS/XDPSlib.h"
|
|
#include "DPS/dpsNXargs.h"
|
|
|
|
#include "cslibint.h"
|
|
#include "dpsassert.h"
|
|
#include "DPSCAPClient.h"
|
|
|
|
#include "publictypes.h"
|
|
#include "dpsXpriv.h"
|
|
|
|
/* === DEFINITIONS === */
|
|
|
|
#ifndef _NFILE
|
|
#define DPSMAXDISPLAYS 128
|
|
#else
|
|
#define DPSMAXDISPLAYS _NFILE
|
|
#endif /* _NFILE */
|
|
|
|
#define MajorOpCode(dpy) (Codes[DPY_NUMBER(dpy)] ? \
|
|
Codes[DPY_NUMBER(dpy)]->major_opcode : \
|
|
Punt())
|
|
|
|
#define DPSCAP_INITCTXTS 4 /* per display */
|
|
|
|
/* === TYPES === */
|
|
|
|
typedef Status (*PSCMProc)(Display *, XEvent *, xEvent *);
|
|
|
|
typedef struct {
|
|
char passEvents;
|
|
char wrapWaiting;
|
|
char syncMask; /* CSDPS only */
|
|
char debugMask; /* CSDPS only */
|
|
} DPSDisplayFlags;
|
|
|
|
/* For now DPSDisplayFlags is no larger than a pointer. Revisit this if the
|
|
structure grows. */
|
|
|
|
typedef int (*GenericProcPtrReturnsInt)(Display *);
|
|
|
|
typedef struct _t_DPSCAPPausedContextData {
|
|
struct _t_DPSCAPPausedContextData *next;
|
|
Bool paused;
|
|
ContextXID cxid;
|
|
unsigned int seqnum;
|
|
} DPSCAPPausedContextData;
|
|
|
|
typedef struct {
|
|
char showSmallSizes;
|
|
char pixMem;
|
|
} DPSCAPAgentArgs;
|
|
|
|
typedef struct {
|
|
void (*Flush)(Display *);
|
|
int (*Read)(Display*, char*, long);
|
|
void (*ReadPad)(Display*, char*, long);
|
|
Status (*Reply)(Display*, xReply*, int, Bool);
|
|
void (*Send)(Display*, _Xconst char*, long);
|
|
} XDPSLIOProcs;
|
|
|
|
/* === GLOBALS === */
|
|
|
|
/* For debugging, allows client to force the library to use an agent */
|
|
int gForceCSDPS = 0;
|
|
|
|
/* Force all DPS NX protocol requests to flush if CSDPS */
|
|
int gAutoFlush = 1;
|
|
|
|
/* Force all NX XDPSLGiveInputs to flush independent of gAutoFlush */
|
|
int gForceFlush = 1;
|
|
|
|
/* Quick check for any paused contexts */
|
|
int gTotalPaused = 0;
|
|
|
|
/* === LOCALS === */
|
|
|
|
/* Common stuff */
|
|
static XExtCodes *Codes[DPSMAXDISPLAYS];
|
|
static int version[DPSMAXDISPLAYS];
|
|
static XDPSLEventHandler StatusProc[DPSMAXDISPLAYS];
|
|
static DPSDisplayFlags displayFlags[DPSMAXDISPLAYS];
|
|
static XDPSLEventHandler TextProc = NULL;
|
|
static XDPSLEventHandler ReadyProc[DPSMAXDISPLAYS]; /* L2-DPS/PROTO 9 */
|
|
static int NumberType[DPSMAXDISPLAYS]; /* Garbage okay after dpy closed */
|
|
static char *FloatingName[DPSMAXDISPLAYS]; /* Garbage okay after dpy closed */
|
|
|
|
/* CSDPS stuff */
|
|
static Display *ShuntMap[DPSMAXDISPLAYS];
|
|
static PSCMProc ClientMsgProc[DPSMAXDISPLAYS];
|
|
static GenericProcPtrReturnsInt AfterProcs[DPSMAXDISPLAYS];
|
|
static DPSCAPPausedContextData *PausedPerDisplay[DPSMAXDISPLAYS];
|
|
static DPSCAPAgentArgs AgentArgs[DPSMAXDISPLAYS];
|
|
static unsigned int LastXRequest[DPSMAXDISPLAYS];
|
|
static int GCFlushMode[DPSMAXDISPLAYS];
|
|
|
|
#ifdef VMS
|
|
static Display *dpys[DPSMAXDISPLAYS];
|
|
static nextDpy = 0;
|
|
#endif /* VMS */
|
|
|
|
static void DPSCAPInitGC(Display *dpy, Display *agent, GC gc);
|
|
static Status DPSCAPClientMessageProc(Display *dpy, XEvent *re, xEvent *event);
|
|
static int DPSCAPAfterProc(Display *xdpy);
|
|
static unsigned int DPSCAPSetPause(Display *xdpy, ContextXID cxid);
|
|
static Bool DPSCAPResumeContext(Display *xdpy, ContextXID cxid);
|
|
static Bool WaitForSyncProc(Display *xdpy, XEvent *event, char *arg);
|
|
|
|
static XDPSLIOProcs xlProcs = { /* Use these for DPS/X extension */
|
|
_XFlush,
|
|
_XRead,
|
|
_XReadPad,
|
|
_XReply,
|
|
_XSend
|
|
};
|
|
|
|
static XDPSLIOProcs nxlProcs = { /* Use these for NX */
|
|
N_XFlush,
|
|
N_XRead,
|
|
N_XReadPad,
|
|
N_XReply,
|
|
N_XSend
|
|
};
|
|
|
|
/* === MACROS === */
|
|
|
|
#define IFNXSETCALL(a, x) call = ((a) != (x)) ? &nxlProcs : &xlProcs
|
|
|
|
/* === PRIVATE PROCS === */
|
|
|
|
static int Punt(void)
|
|
{
|
|
DPSFatalProc(NULL, "Extension has not been initialized");
|
|
exit(1);
|
|
}
|
|
|
|
#ifdef VMS
|
|
/* This is a terribly inefficient way to find a per-display index, but we
|
|
need it till we get dpy->fd fixed in VMS%%%%%*/
|
|
static int FindDpyNum(Display *dpy)
|
|
{
|
|
int i;
|
|
for (i=0; dpys[i] != dpy ; i++)
|
|
{
|
|
if (i == nextDpy)
|
|
{
|
|
dpys[nextDpy++]=dpy;
|
|
break;
|
|
}
|
|
}
|
|
return i;
|
|
}
|
|
#define DPY_NUMBER(dpy) FindDpyNum(dpy)
|
|
#else /* VMS */
|
|
#define DPY_NUMBER(dpy) ((dpy)->fd)
|
|
#endif /* VMS */
|
|
|
|
/* === PROCEDURES === */
|
|
|
|
/* ARGSUSED */
|
|
void
|
|
XDPSLSetTextEventHandler(Display *dpy, XDPSLEventHandler proc)
|
|
{
|
|
TextProc = proc;
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
void
|
|
XDPSLCallOutputEventHandler(Display *dpy, XEvent *event)
|
|
{
|
|
(*TextProc)(event);
|
|
}
|
|
|
|
void
|
|
XDPSLSetStatusEventHandler(Display *dpy, XDPSLEventHandler proc)
|
|
{
|
|
StatusProc[DPY_NUMBER(dpy)] = proc;
|
|
}
|
|
|
|
void
|
|
XDPSLCallStatusEventHandler(Display *dpy, XEvent *event)
|
|
{
|
|
(*(StatusProc[DPY_NUMBER(dpy)]))(event);
|
|
}
|
|
|
|
/* Added for L2-DPS/PROTO 9 */
|
|
void
|
|
XDPSLSetReadyEventHandler(Display *dpy, XDPSLEventHandler proc)
|
|
{
|
|
ReadyProc[DPY_NUMBER(dpy)] = proc;
|
|
}
|
|
|
|
/* Added for L2-DPS/PROTO 9 */
|
|
void
|
|
XDPSLCallReadyEventHandler(Display *dpy, XEvent *event)
|
|
{
|
|
(*(ReadyProc[DPY_NUMBER(dpy)]))(event);
|
|
}
|
|
|
|
/* Added for L2-DPS/PROTO 9 */
|
|
int
|
|
XDPSLGetVersion(Display *dpy)
|
|
{
|
|
return(version[DPY_NUMBER(dpy)]);
|
|
}
|
|
/* See CSDPS additions for XDPSLSetVersion */
|
|
|
|
void
|
|
XDPSLInitDisplayFlags(Display *dpy)
|
|
{
|
|
int d = DPY_NUMBER(dpy);
|
|
displayFlags[d].wrapWaiting = False;
|
|
|
|
/* Instead of explicitly setting the pass-event flag, rely upon the fact
|
|
that it gets initialized to 0 by the compiler. This means that you
|
|
can set the event delivery mode on a display before creating any
|
|
contexts, which is a Good Thing */
|
|
}
|
|
|
|
XExtCodes *XDPSLGetCodes(Display *dpy)
|
|
{
|
|
return Codes[DPY_NUMBER(dpy)];
|
|
}
|
|
|
|
/* ARGSUSED */
|
|
static int
|
|
CloseDisplayProc(Display *dpy, XExtCodes *codes)
|
|
{
|
|
/* This proc is for native DPS/X only, not CSDPS */
|
|
Codes[DPY_NUMBER(dpy)] = NULL;
|
|
/* Clear list */
|
|
XDPSPrivZapDpy(dpy);
|
|
#ifdef VMS
|
|
dpys[DPY_NUMBER(dpy)] = NULL;
|
|
/*%%%%Temp till we fix dpy->fd*/
|
|
#endif /* VMS */
|
|
return 0; /* return-value is ignored */
|
|
}
|
|
|
|
Bool
|
|
XDPSLGetPassEventsFlag(Display *dpy)
|
|
{
|
|
return displayFlags[DPY_NUMBER(dpy)].passEvents;
|
|
}
|
|
|
|
void
|
|
XDPSLSetPassEventsFlag(Display *dpy, Bool flag)
|
|
{
|
|
displayFlags[DPY_NUMBER(dpy)].passEvents = flag;
|
|
}
|
|
|
|
Bool
|
|
XDPSLGetWrapWaitingFlag(Display *dpy)
|
|
{
|
|
return displayFlags[DPY_NUMBER(dpy)].wrapWaiting;
|
|
}
|
|
|
|
void
|
|
XDPSLSetWrapWaitingFlag(Display *dpy, Bool flag)
|
|
{
|
|
displayFlags[DPY_NUMBER(dpy)].wrapWaiting = flag;
|
|
}
|
|
|
|
static Status
|
|
ConvertOutputEvent(Display *dpy, XEvent *ce, xEvent *we)
|
|
{
|
|
register PSOutputEvent *wireevent = (PSOutputEvent *) we;
|
|
register XDPSLOutputEvent *clientevent = (XDPSLOutputEvent *) ce;
|
|
|
|
clientevent->type = wireevent->type & 0x7f;
|
|
clientevent->serial = _XSetLastRequestRead(dpy,
|
|
(xGenericReply *)wireevent);
|
|
clientevent->send_event = (wireevent->type & 0x80) != 0;
|
|
clientevent->display = dpy;
|
|
clientevent->cxid = wireevent->cxid;
|
|
clientevent->length = wireevent->length;
|
|
bcopy((char *) wireevent->data, clientevent->data, wireevent->length);
|
|
if (TextProc && !XDPSLGetPassEventsFlag(dpy)) {
|
|
(*TextProc)((XEvent *) clientevent);
|
|
return False;
|
|
}
|
|
return True;
|
|
}
|
|
|
|
static Status
|
|
ConvertStatusEvent(Display *dpy, XEvent *ce, xEvent *we)
|
|
{
|
|
register PSStatusEvent *wireevent = (PSStatusEvent *) we;
|
|
register XDPSLStatusEvent *clientevent = (XDPSLStatusEvent *) ce;
|
|
|
|
clientevent->type = wireevent->type & 0x7f;
|
|
clientevent->serial = _XSetLastRequestRead(dpy,
|
|
(xGenericReply *)wireevent);
|
|
clientevent->send_event = (wireevent->type & 0x80) != 0;
|
|
clientevent->display = dpy;
|
|
clientevent->cxid = wireevent->cxid;
|
|
clientevent->status = wireevent->status;
|
|
if (StatusProc[DPY_NUMBER(dpy)] && !XDPSLGetPassEventsFlag(dpy)) {
|
|
(*(StatusProc[DPY_NUMBER(dpy)]))((XEvent *) clientevent);
|
|
return False;
|
|
}
|
|
return True;
|
|
}
|
|
|
|
/* Added for L2-DPS/PROTO 9 */
|
|
static Status
|
|
ConvertReadyEvent(Display *dpy, XEvent *ce, xEvent *we)
|
|
{
|
|
register PSReadyEvent *wireevent = (PSReadyEvent *) we;
|
|
register XDPSLReadyEvent *clientevent = (XDPSLReadyEvent *) ce;
|
|
|
|
clientevent->type = wireevent->type & 0x7f;
|
|
clientevent->serial = _XSetLastRequestRead(dpy,
|
|
(xGenericReply *)wireevent);
|
|
clientevent->send_event = (wireevent->type & 0x80) != 0;
|
|
clientevent->display = dpy;
|
|
clientevent->cxid = wireevent->cxid;
|
|
clientevent->val[0] = wireevent->val1;
|
|
clientevent->val[1] = wireevent->val2;
|
|
clientevent->val[2] = wireevent->val3;
|
|
clientevent->val[3] = wireevent->val4;
|
|
if (ReadyProc[DPY_NUMBER(dpy)] && !XDPSLGetPassEventsFlag(dpy)) {
|
|
(*(ReadyProc[DPY_NUMBER(dpy)]))((XEvent *) clientevent);
|
|
return False;
|
|
}
|
|
return True;
|
|
}
|
|
|
|
/* Added for L2-DPS/PROTO 9 */
|
|
/* ARGSUSED */
|
|
|
|
static int
|
|
CatchBadMatch(Display *dpy, xError *err, XExtCodes *codes, int *ret_code)
|
|
{
|
|
if (err->errorCode == BadMatch)
|
|
{
|
|
*ret_code = 0;
|
|
return 1; /* suppress error */
|
|
}
|
|
else
|
|
{
|
|
*ret_code = 1;
|
|
return 0; /* pass error along */
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
XDPSLInit(
|
|
Display *dpy,
|
|
int *numberType, /* RETURN */
|
|
char **floatingName) /* RETURN: CALLER MUST NOT MODIFY OR FREE! */
|
|
{
|
|
XExtCodes *codes = (XExtCodes *)NULL;
|
|
register xPSInitReq *req;
|
|
xPSInitReply rep;
|
|
char *ptr;
|
|
int first_event;
|
|
|
|
{
|
|
char *ddt;
|
|
|
|
if ((ddt = getenv("DPSNXOVER")) != NULL) {
|
|
gForceCSDPS = (*ddt == 't' || *ddt == 'T');
|
|
if (gForceCSDPS)
|
|
DPSWarnProc(NULL, "*** USING DPS NX ***");
|
|
}
|
|
}
|
|
|
|
if ((codes = Codes[DPY_NUMBER(dpy)]) != NULL) {
|
|
if (numberType)
|
|
*numberType = NumberType[DPY_NUMBER(dpy)];
|
|
if (floatingName)
|
|
*floatingName = FloatingName[DPY_NUMBER(dpy)];
|
|
return codes->first_event;
|
|
} else {
|
|
if (gForceCSDPS)
|
|
goto try_dps_nx;
|
|
codes = XInitExtension(dpy, DPSNAME);
|
|
if (codes == NULL) {
|
|
/* try DEC UWS 2.2 server */
|
|
codes = XInitExtension(dpy, DECDPSNAME);
|
|
try_dps_nx:
|
|
if (codes == NULL) {
|
|
int myNumberType;
|
|
char *myFloatingName;
|
|
|
|
first_event = CSDPSInit(dpy, &myNumberType, &myFloatingName);
|
|
NumberType[DPY_NUMBER(dpy)] = myNumberType;
|
|
FloatingName[DPY_NUMBER(dpy)] = myFloatingName;
|
|
if (numberType)
|
|
*numberType = myNumberType;
|
|
if (floatingName)
|
|
*floatingName = myFloatingName;
|
|
return first_event;
|
|
}
|
|
}
|
|
Codes[DPY_NUMBER(dpy)] = codes;
|
|
ShuntMap[DPY_NUMBER(dpy)] = dpy;
|
|
/* set procs for native DPS/X */
|
|
XESetCloseDisplay(dpy, codes->extension, CloseDisplayProc);
|
|
XESetWireToEvent(dpy, codes->first_event + PSEVENTOUTPUT,
|
|
ConvertOutputEvent);
|
|
XESetWireToEvent(dpy, codes->first_event + PSEVENTSTATUS,
|
|
ConvertStatusEvent);
|
|
XESetWireToEvent(dpy, codes->first_event + PSEVENTREADY,
|
|
ConvertReadyEvent);
|
|
first_event = codes->first_event;
|
|
}
|
|
|
|
/* We have to handle a BadMatch error, in the case where
|
|
the client has a later (higher) version of
|
|
the protocol than the server */
|
|
{
|
|
int (*oldErrorProc)(Display*, xError*, XExtCodes*, int*);
|
|
int libVersion;
|
|
Bool doneIt;
|
|
|
|
XSync(dpy, False);
|
|
LockDisplay(dpy);
|
|
oldErrorProc = XESetError(dpy, codes->extension, CatchBadMatch);
|
|
libVersion = DPSPROTOCOLVERSION;
|
|
doneIt = False;
|
|
while (libVersion >= DPSPROTO_OLDEST)
|
|
{
|
|
GetReq(PSInit, req);
|
|
req->reqType = MajorOpCode(dpy);
|
|
req->dpsReqType = X_PSInit;
|
|
req->libraryversion = libVersion;
|
|
if (_XReply(dpy, (xReply *) &rep, 0, xFalse))
|
|
{
|
|
doneIt = True;
|
|
break;
|
|
}
|
|
/* otherwise, try previous version */
|
|
--libVersion;
|
|
}
|
|
oldErrorProc = XESetError(dpy, codes->extension, oldErrorProc);
|
|
if (!doneIt)
|
|
{
|
|
DPSFatalProc(NULL, "Incompatible protocol versions");
|
|
exit(1);
|
|
}
|
|
|
|
/* NOTE *************************************************
|
|
We made a boo-boo in the 1007.2 and earlier versions of
|
|
our X server glue code. Instead of sending a
|
|
BadMatch error if the client's version is newer (higher)
|
|
than the server's, it just replies with success. We
|
|
could test for that situation here by looking at
|
|
rep.serverversion, but it turns out that we don't need
|
|
to do anything special. Since rep.serverversion gets
|
|
assigned to our version[] array, it is as if we handled
|
|
the BadMatch correctly. Just for safety's sake, we'll
|
|
do some bulletproofing here instead.
|
|
Fixes 2ps_xdps BUG #6 */
|
|
|
|
else if (rep.serverversion < DPSPROTO_OLDEST
|
|
|| rep.serverversion > DPSPROTOCOLVERSION)
|
|
{
|
|
DPSFatalProc(NULL, "Server replied with bogus version");
|
|
exit(1);
|
|
}
|
|
}
|
|
|
|
version[DPY_NUMBER(dpy)] = rep.serverversion;
|
|
NumberType[DPY_NUMBER(dpy)] = rep.preferredNumberFormat;
|
|
if (numberType)
|
|
*numberType = rep.preferredNumberFormat;
|
|
|
|
ptr = (char *) Xmalloc(rep.floatingNameLength + 1);
|
|
_XReadPad(dpy, ptr, rep.floatingNameLength);
|
|
ptr[rep.floatingNameLength] = 0;
|
|
FloatingName[DPY_NUMBER(dpy)] = ptr;
|
|
if (floatingName)
|
|
*floatingName = ptr;
|
|
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
return first_event;
|
|
}
|
|
|
|
|
|
|
|
|
|
static void CopyColorMapsIntoCreateContextReq(
|
|
xPSCreateContextReq *req,
|
|
XStandardColormap *colorcube,
|
|
XStandardColormap *grayramp)
|
|
{
|
|
req->cmap = 0;
|
|
if (colorcube != NULL) {
|
|
req->cmap = colorcube->colormap;
|
|
req->redmax = colorcube->red_max;
|
|
req->redmult = colorcube->red_mult;
|
|
req->greenmax = colorcube->green_max;
|
|
req->greenmult = colorcube->green_mult;
|
|
req->bluemax = colorcube->blue_max;
|
|
req->bluemult = colorcube->blue_mult;
|
|
req->colorbase = colorcube->base_pixel;
|
|
}
|
|
else {
|
|
req->redmult = 0;
|
|
/* The rest of this shouldn't be necessary, but there are some
|
|
servers out there that erroneously check the other fields
|
|
even when redmult is 0 */
|
|
req->redmax = 0;
|
|
req->greenmult = 0;
|
|
req->greenmax = 0;
|
|
req->bluemult = 0;
|
|
req->bluemax = 0;
|
|
req->colorbase = 0;
|
|
}
|
|
|
|
if (grayramp != NULL) {
|
|
req->cmap = grayramp->colormap;
|
|
req->graymax = grayramp->red_max;
|
|
req->graymult = grayramp->red_mult;
|
|
req->graybase = grayramp->base_pixel;
|
|
}
|
|
else req->graymult = 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* ARGSUSED */
|
|
ContextXID
|
|
XDPSLCreateContextAndSpace(
|
|
register Display *xdpy,
|
|
Drawable draw,
|
|
GC gc,
|
|
int x, int y,
|
|
unsigned int eventMask,
|
|
XStandardColormap *grayRamp,
|
|
XStandardColormap *colorCube,
|
|
unsigned int actual,
|
|
ContextPSID *cpsid, /* RETURN */
|
|
SpaceXID *sxid, /* RETURN */
|
|
Bool secure) /* Added for L2-DPS/PROTO 9 */
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
ContextXID cxid;
|
|
register xPSCreateContextReq *req; /* Same struct for CreateSecureContext */
|
|
xPSCreateContextReply rep;
|
|
XStandardColormap defColorcube, defGrayramp;
|
|
XStandardColormap *requestCube, *requestRamp;
|
|
int index;
|
|
XDPSLIOProcs *call;
|
|
|
|
if (grayRamp == NULL && colorCube == NULL) return(None);
|
|
|
|
if (secure && version[dpyix] < DPSPROTO_V09)
|
|
return(None); /* No secure contexts before PROTO 9 */
|
|
|
|
/* Index gets encoded as follows:
|
|
*
|
|
* 0 grayRamp = Default, colorCube = Default
|
|
* 1 grayRamp = non-Default, colorcube = Default
|
|
* 2 grayRamp = Default, colorcube = non-Default
|
|
* 3 grayRamp = non-Default, colorcube = non-Default
|
|
*
|
|
*/
|
|
index = ((grayRamp == DefaultStdCMap || grayRamp == NULL) ? 0 : 1) +
|
|
(colorCube == DefaultStdCMap ? 0 : 2);
|
|
|
|
switch (index)
|
|
{
|
|
default:
|
|
case 0: /* Both are default */
|
|
XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
|
|
&defColorcube, &defGrayramp);
|
|
requestCube = &defColorcube;
|
|
requestRamp = &defGrayramp;
|
|
break;
|
|
|
|
case 1: /* gray specified, Color default */
|
|
XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
|
|
&defColorcube, (XStandardColormap *) NULL);
|
|
requestCube = &defColorcube;
|
|
requestRamp = grayRamp;
|
|
break;
|
|
|
|
case 2: /* gray default, Color specified */
|
|
XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
|
|
(XStandardColormap *) NULL, &defGrayramp);
|
|
requestCube = colorCube;
|
|
requestRamp = &defGrayramp;
|
|
break;
|
|
|
|
case 3: /* Both specified */
|
|
requestCube = colorCube;
|
|
requestRamp = grayRamp;
|
|
break;
|
|
}
|
|
|
|
if (gc != NULL)
|
|
XDPSLFlushGC(xdpy, gc);
|
|
if (dpy != xdpy)
|
|
{
|
|
int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
/* Don't worry about pauses here, since we are just
|
|
now creating the context! */
|
|
if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
|
|
XSync(xdpy, False);
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSCreateContext, req);
|
|
CopyColorMapsIntoCreateContextReq(req, requestCube, requestRamp);
|
|
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = (secure) ? X_PSCreateSecureContext : X_PSCreateContext;
|
|
req->x = x;
|
|
req->y = y;
|
|
req->drawable = draw;
|
|
req->gc = (gc != NULL) ? XGContextFromGC(gc) : None;
|
|
cxid = req->cxid = XAllocID(xdpy);
|
|
req->sxid = XAllocID(xdpy);
|
|
if (sxid)
|
|
*sxid = req->sxid;
|
|
req->eventmask = 0; /* %%% */
|
|
req->actual = actual;
|
|
IFNXSETCALL(dpy, xdpy);
|
|
(void) (*call->Reply) (dpy, (xReply *)&rep, 0, xTrue);
|
|
|
|
if (cpsid)
|
|
*cpsid = (int)rep.cpsid;
|
|
|
|
UnlockDisplay(dpy);
|
|
/* If the context creation succeeded and we are CSDPS, send GC values */
|
|
if (rep.cpsid && xdpy != dpy && gc != NULL)
|
|
{
|
|
DPSCAPInitGC(xdpy, dpy, gc);
|
|
}
|
|
SyncHandle();
|
|
|
|
if (dpy != xdpy)
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
return (cxid);
|
|
}
|
|
|
|
|
|
/* ARGSUSED */
|
|
ContextXID
|
|
XDPSLCreateContext(
|
|
register Display *xdpy,
|
|
SpaceXID sxid,
|
|
Drawable draw,
|
|
GC gc,
|
|
int x, int y,
|
|
unsigned int eventMask,
|
|
XStandardColormap *grayRamp,
|
|
XStandardColormap *colorCube,
|
|
unsigned int actual,
|
|
ContextPSID *cpsid, /* RETURN */
|
|
Bool secure) /* L2-DPS/PROTO 9 addition */
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSCreateContextReq *req;
|
|
xPSCreateContextReply rep;
|
|
ContextXID cxid; /* RETURN */
|
|
XStandardColormap defColorcube, defGrayramp;
|
|
XStandardColormap *requestCube, *requestRamp;
|
|
int index;
|
|
XDPSLIOProcs *call;
|
|
|
|
if (secure && version[dpyix] < DPSPROTO_V09)
|
|
return(None); /* No secure contexts before PROTO 9 */
|
|
|
|
/* Index gets encoded as follows:
|
|
*
|
|
* 0 grayRamp = Default, colorCube = Default
|
|
* 1 grayRamp = non-Default, colorcube = Default
|
|
* 2 grayRamp = Default, colorcube = non-Default
|
|
* 3 grayRamp = non-Default, colorcube = non-Default
|
|
*
|
|
* Note that only the first or last case should ever happen.
|
|
*/
|
|
index = ((grayRamp == DefaultStdCMap) ? 0 : 1) +
|
|
((colorCube == DefaultStdCMap) ? 0 : 2);
|
|
|
|
switch (index)
|
|
{
|
|
default:
|
|
case 0: /* Both are default */
|
|
XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
|
|
&defColorcube, &defGrayramp);
|
|
requestCube = &defColorcube;
|
|
requestRamp = &defGrayramp;
|
|
break;
|
|
|
|
case 1: /* gray specified, Color default */
|
|
XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
|
|
&defColorcube, (XStandardColormap *) NULL);
|
|
requestCube = &defColorcube;
|
|
requestRamp = grayRamp;
|
|
break;
|
|
|
|
case 2: /* gray default, Color specified */
|
|
XDPSGetDefaultColorMaps(xdpy, (Screen *) NULL, draw,
|
|
(XStandardColormap *) NULL, &defGrayramp);
|
|
requestCube = colorCube;
|
|
requestRamp = &defGrayramp;
|
|
break;
|
|
|
|
case 3: /* Both specified */
|
|
requestCube = colorCube;
|
|
requestRamp = grayRamp;
|
|
break;
|
|
}
|
|
|
|
|
|
if (gc != NULL)
|
|
XDPSLFlushGC(xdpy, gc);
|
|
if (dpy != xdpy)
|
|
{
|
|
int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
/* Don't worry about pauses here, since we are
|
|
just now creating this context! */
|
|
if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
|
|
XSync(xdpy, False);
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSCreateContext, req);
|
|
CopyColorMapsIntoCreateContextReq(req, requestCube, requestRamp);
|
|
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = (secure) ? X_PSCreateSecureContext : X_PSCreateContext;
|
|
req->x = x;
|
|
req->y = y;
|
|
req->drawable = draw;
|
|
req->gc = (gc != NULL) ? XGContextFromGC(gc) : None;
|
|
cxid = req->cxid = XAllocID(xdpy);
|
|
req->sxid = sxid;
|
|
req->actual = actual;
|
|
|
|
IFNXSETCALL(dpy, xdpy);
|
|
(void) (*call->Reply) (dpy, (xReply *)&rep, 0, xTrue);
|
|
if (cpsid)
|
|
*cpsid = (int)rep.cpsid;
|
|
|
|
UnlockDisplay(dpy);
|
|
/* If the context creation succeeded and we are CSDPS, send GC values */
|
|
if (rep.cpsid && xdpy != dpy && gc != NULL)
|
|
{
|
|
DPSCAPInitGC(xdpy, dpy, gc);
|
|
}
|
|
|
|
SyncHandle();
|
|
|
|
if (dpy != xdpy)
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
return cxid;
|
|
}
|
|
|
|
SpaceXID
|
|
XDPSLCreateSpace(Display *xdpy)
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSCreateSpaceReq *req;
|
|
SpaceXID sxid;
|
|
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSCreateSpace, req);
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = X_PSCreateSpace;
|
|
sxid = req->sxid = XAllocID(xdpy);
|
|
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
if (dpy != xdpy)
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
return sxid;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* I'm not sure how portable my coalescing code is, so I've provided the
|
|
* below define. If it turns out this code just breaks somewhere, you
|
|
* can simply undefine COALESCEGIVEINPUT, and then everything will work
|
|
* (but slower). 6/16/89 (tw)
|
|
*/
|
|
|
|
#define COALESCEGIVEINPUT
|
|
|
|
void
|
|
XDPSLGiveInput(Display *xdpy, ContextXID cxid, char *data, int length)
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSGiveInputReq *req;
|
|
Bool didFlush = False;
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
register int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
if (syncMask & DPSCAP_SYNCMASK_RECONCILE)
|
|
{
|
|
XDPSLReconcileRequests(xdpy, cxid);
|
|
didFlush = True;
|
|
}
|
|
|
|
/* If this context got paused, no matter how, ignore
|
|
mode and resume it */
|
|
if (gTotalPaused && DPSCAPResumeContext(xdpy, cxid))
|
|
{
|
|
/* xdpy was flushed by DPSCAPResumeContext */
|
|
if (!didFlush)
|
|
{
|
|
N_XFlush(dpy);
|
|
didFlush = True;
|
|
}
|
|
}
|
|
else if (syncMask & DPSCAP_SYNCMASK_SYNC)
|
|
{
|
|
didFlush = True;
|
|
XSync(xdpy, False);
|
|
}
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
#ifdef COALESCEGIVEINPUT
|
|
req = (xPSGiveInputReq *) dpy->last_req;
|
|
if (req->reqType == MajorOpCode(xdpy)
|
|
&& req->dpsReqType == X_PSGiveInput
|
|
&& req->cxid == cxid
|
|
&& dpy->bufptr + length + 3 < dpy->bufmax) {
|
|
bcopy(data, ((char *) req) + sizeof(xPSGiveInputReq) + req->nunits,
|
|
length);
|
|
req->nunits += length;
|
|
req->length = (sizeof(xPSGiveInputReq) + req->nunits + 3) >> 2;
|
|
dpy->bufptr = dpy->last_req + sizeof(xPSGiveInputReq) +
|
|
((req->nunits + 3) & ~3);
|
|
} else
|
|
#endif /* COALESCEGIVEINPUT */
|
|
{
|
|
int flushOnce = 1;
|
|
int maxedOutLen = xdpy->max_request_size - sizeof(xPSGiveInputReq) - 4;
|
|
int nunits;
|
|
|
|
/* We have the rare opportunity to chop up a buffer that is larger
|
|
than the max request size into separate requests, unlike
|
|
most other X requests (such as DrawText). The -4 is to
|
|
force these maxed out requests to be less than the maximum
|
|
padding that would ever be needed, and to minimize padding
|
|
in the case where the input buffer is several times
|
|
larger than max request length. */
|
|
|
|
nunits = maxedOutLen;
|
|
do {
|
|
if (length < maxedOutLen)
|
|
nunits = length; /* Normal size block */
|
|
NXMacroGetReq(PSGiveInput, req);
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = X_PSGiveInput;
|
|
req->cxid = cxid;
|
|
req->nunits = nunits;
|
|
req->length += ((nunits + 3) >> 2);
|
|
if (dpy != xdpy) {
|
|
if (flushOnce && !didFlush) {
|
|
LockDisplay(xdpy);
|
|
_XFlush(xdpy);
|
|
UnlockDisplay(xdpy);
|
|
flushOnce = 0;
|
|
}
|
|
NXProcData(dpy, (char *) data, nunits);
|
|
} else
|
|
{Data(dpy, (char *) data, nunits);}
|
|
data += nunits;
|
|
length -= nunits;
|
|
} while (length);
|
|
}
|
|
|
|
/* In the NX case (didFlush is always False for the non-NX case),
|
|
the xdpy may have been flushed, but there is stuff left
|
|
buffered in dpy (NX connection). We can't leave the stuff
|
|
there, since we may never call a DPS routine again. Until
|
|
we can be notified about xdpy being flushed, we have to
|
|
clear out the dpy buffer after we cleared out the xdpy
|
|
buffer (didFlush == True). */
|
|
|
|
if (dpy != xdpy
|
|
&& dpy->bufptr != dpy->buffer
|
|
&& (gForceFlush || didFlush))
|
|
N_XFlush(dpy);
|
|
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
if (dpy != xdpy)
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
}
|
|
|
|
|
|
int
|
|
XDPSLGetStatus(Display *xdpy, ContextXID cxid)
|
|
{
|
|
int dpyix;
|
|
Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSGetStatusReq *req;
|
|
xPSGetStatusReply rep;
|
|
XDPSLIOProcs *call;
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
register int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
/* ASSERT: There is no reason to pause the context for this
|
|
request, so just sync. */
|
|
if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
|
|
XSync(xdpy, False);
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSGetStatus, req);
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = X_PSGetStatus;
|
|
req->cxid = cxid;
|
|
req->notifyIfChange = 0;
|
|
|
|
IFNXSETCALL(dpy, xdpy);
|
|
if (! (*call->Reply)(dpy, (xReply *)&rep, 0, xTrue))
|
|
rep.status = PSSTATUSERROR;
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
/* For CSDPS, guarantee that status events arrive just like DPS/X */
|
|
if (dpy != xdpy)
|
|
{
|
|
XDPSLSync(xdpy);
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
}
|
|
return (int) rep.status;
|
|
}
|
|
|
|
void
|
|
XDPSLDestroySpace(Display *xdpy, SpaceXID sxid)
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSDestroySpaceReq *req;
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
/* ASSERT: There is no reason to pause the context for this
|
|
request, so just sync. */
|
|
if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
|
|
XSync(xdpy, False);
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSDestroySpace, req);
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = X_PSDestroySpace;
|
|
req->sxid = sxid;
|
|
|
|
if (gAutoFlush && dpy != xdpy)
|
|
{
|
|
N_XFlush(dpy);
|
|
}
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
if (dpy != xdpy)
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
}
|
|
|
|
|
|
void
|
|
XDPSLReset(Display *xdpy, ContextXID cxid)
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSResetReq *req;
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
register int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
/* ASSERT: There is no reason to pause the context for this
|
|
request, so just sync. */
|
|
if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
|
|
XSync(xdpy, False);
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSReset, req);
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = X_PSReset;
|
|
req->cxid = cxid;
|
|
|
|
if (gAutoFlush && dpy != xdpy)
|
|
{
|
|
N_XFlush(dpy);
|
|
}
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
if (dpy != xdpy)
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
}
|
|
|
|
void
|
|
XDPSLNotifyContext(
|
|
Display *xdpy,
|
|
ContextXID cxid,
|
|
int ntype) /* should this be an enum?? %%% */
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSNotifyContextReq *req;
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
register int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
/* ASSERT: There is no reason to pause the context for this
|
|
request, so just sync. */
|
|
if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
|
|
XSync(xdpy, False);
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSNotifyContext, req);
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = X_PSNotifyContext;
|
|
req->cxid = cxid;
|
|
req->notifyType = ntype;
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
N_XFlush(dpy); /* THIS IS CRITICAL TO AVOID HANGING! */
|
|
}
|
|
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
if (ntype == PSKILL)
|
|
XDPSLCleanContext(xdpy, cxid);
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
}
|
|
}
|
|
|
|
|
|
ContextXID
|
|
XDPSLCreateContextFromID(
|
|
Display *xdpy,
|
|
ContextPSID cpsid,
|
|
SpaceXID *sxid) /* RETURN */
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSCreateContextFromIDReq *req;
|
|
xPSCreateContextFromIDReply rep;
|
|
ContextXID cxid;
|
|
XDPSLIOProcs *call;
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
/* ASSERT: There is no reason to pause the context for this
|
|
request, so just sync. */
|
|
if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
|
|
XSync(xdpy, False);
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSCreateContextFromID, req);
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = X_PSCreateContextFromID;
|
|
req->cpsid = cpsid;
|
|
cxid = req->cxid = XAllocID(xdpy);
|
|
|
|
IFNXSETCALL(dpy, xdpy);
|
|
(void) (*call->Reply) (dpy, (xReply *)&rep, 0, xTrue);
|
|
if (sxid)
|
|
*sxid = (int)rep.sxid;
|
|
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
if (dpy != xdpy)
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
return(cxid);
|
|
}
|
|
|
|
|
|
/* Returns 1 on success, 0 on failure (cpsid not a valid context). */
|
|
|
|
Status
|
|
XDPSLIDFromContext(
|
|
Display *xdpy,
|
|
ContextPSID cpsid,
|
|
ContextXID *cxid, /* RETURN */
|
|
SpaceXID *sxid) /* RETURN */
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSXIDFromContextReq *req;
|
|
xPSXIDFromContextReply rep;
|
|
XDPSLIOProcs *call;
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
/* ASSERT: There is no reason to pause the context for this
|
|
request, so just sync. */
|
|
if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
|
|
XSync(xdpy, False);
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSXIDFromContext, req);
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = X_PSXIDFromContext;
|
|
req->cpsid = cpsid;
|
|
|
|
IFNXSETCALL(dpy, xdpy);
|
|
(void) (*call->Reply) (dpy, (xReply *)&rep, 0, xTrue);
|
|
*sxid = (int)rep.sxid;
|
|
*cxid = (int)rep.cxid;
|
|
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
|
|
if (dpy != xdpy)
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
return((Status)(*sxid != None && *cxid != None));
|
|
}
|
|
|
|
|
|
ContextPSID
|
|
XDPSLContextFromXID(Display *xdpy, ContextXID cxid)
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSContextFromXIDReq *req;
|
|
xPSContextFromXIDReply rep;
|
|
XDPSLIOProcs *call;
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
/* ASSERT: There is no reason to pause the context for this
|
|
request, so just sync. */
|
|
if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
|
|
XSync(xdpy, False);
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSContextFromXID, req);
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = X_PSContextFromXID;
|
|
req->cxid = cxid;
|
|
|
|
IFNXSETCALL(dpy, xdpy);
|
|
(void) (*call->Reply) (dpy, (xReply *)&rep, 0, xTrue);
|
|
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
|
|
if (dpy != xdpy)
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
return (int)rep.cpsid;
|
|
}
|
|
|
|
|
|
void
|
|
XDPSLSetStatusMask(
|
|
Display *xdpy,
|
|
ContextXID cxid,
|
|
unsigned int enableMask,
|
|
unsigned int disableMask,
|
|
unsigned int nextMask)
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSSetStatusMaskReq *req;
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
register int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
/* ASSERT: There is no reason to pause the context for this
|
|
request, so just sync. */
|
|
if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
|
|
XSync(xdpy, False);
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSSetStatusMask, req);
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = X_PSSetStatusMask;
|
|
req->cxid = cxid;
|
|
req->enableMask = enableMask;
|
|
req->disableMask = disableMask;
|
|
req->nextMask = nextMask;
|
|
|
|
if (gAutoFlush && dpy != xdpy)
|
|
{
|
|
N_XFlush(dpy);
|
|
}
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
if (dpy != xdpy)
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
}
|
|
|
|
|
|
#ifdef VMS
|
|
/*
|
|
* _XReadPad - Read bytes from the socket taking into account incomplete
|
|
* reads. If the number of bytes is not 0 mod 32, read additional pad
|
|
* bytes. This routine may have to be reworked if int < long.
|
|
*/
|
|
|
|
/* This is really in xlib, but is not in the sharable image transfer vector
|
|
* so I am copying it here for now. BF
|
|
|
|
The following notice applies only to the functions
|
|
_XReadPad and XFlush
|
|
|
|
Copyright 1985, 1986, 1987, 1988, 1989 by the
|
|
Massachusetts Institute of Technology
|
|
|
|
Permission to use, copy, modify, distribute, and sell this software and its
|
|
documentation for any purpose is hereby granted without fee, provided that
|
|
the above copyright notice appear in all copies and that both that
|
|
copyright notice and this permission notice appear in supporting
|
|
documentation, and that the name of M.I.T. not be used in advertising or
|
|
publicity pertaining to distribution of the software without specific,
|
|
written prior permission. M.I.T. makes no representations about the
|
|
suitability of this software for any purpose. It is provided "as is"
|
|
without express or implied warranty.
|
|
|
|
*/
|
|
void
|
|
_XReadPad (Display *dpy, char *data, long size)
|
|
{
|
|
static int padlength[4] = {0,3,2,1};
|
|
register long bytes_read;
|
|
char pad[3];
|
|
|
|
CheckLock(dpy);
|
|
if (size == 0) return;
|
|
_XRead( dpy, data, size );
|
|
if ( padlength[size & 3] ) {
|
|
_XRead( dpy, pad, padlength[size & 3] );
|
|
}
|
|
|
|
}
|
|
#endif /* VMS */
|
|
|
|
/* _____________ LEVEL 2 DPS/PROTOCOL 9 ADDITIONS _____________ */
|
|
|
|
void
|
|
XDPSLNotifyWhenReady(
|
|
Display *xdpy,
|
|
ContextXID cxid,
|
|
int val[4])
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xPSNotifyWhenReadyReq *req;
|
|
|
|
if (version[dpyix] < DPSPROTO_V09)
|
|
{
|
|
DPSWarnProc(NULL, "Attempted use of XDPSLNotifyWhenReady with incompatible server ignored");
|
|
return; /* PROTO 9 or later only */
|
|
}
|
|
|
|
if (dpy != xdpy)
|
|
{
|
|
register int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
if (syncMask & DPSCAP_SYNCMASK_RECONCILE)
|
|
XDPSLReconcileRequests(xdpy, cxid);
|
|
|
|
/* If this context got paused, no matter how, ignore
|
|
mode and resume it */
|
|
if (gTotalPaused && DPSCAPResumeContext(xdpy, cxid))
|
|
{
|
|
/* xdpy was flushed by DPSCAPResumeContext */
|
|
if (gAutoFlush)
|
|
N_XFlush(dpy);
|
|
}
|
|
else if (syncMask & DPSCAP_SYNCMASK_SYNC)
|
|
XSync(xdpy, False);
|
|
}
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(PSNotifyWhenReady, req);
|
|
req->reqType = MajorOpCode(xdpy);
|
|
req->dpsReqType = X_PSNotifyWhenReady;
|
|
req->cxid = cxid;
|
|
req->val1 = val[0];
|
|
req->val2 = val[1];
|
|
req->val3 = val[2];
|
|
req->val4 = val[3];
|
|
|
|
if (gAutoFlush && dpy != xdpy)
|
|
{
|
|
N_XFlush(dpy);
|
|
}
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
if (dpy != xdpy)
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
}
|
|
|
|
XDPSLPSErrors
|
|
XDPSLTestErrorCode(Display *dpy, int ecode)
|
|
{
|
|
XExtCodes *c = XDPSLGetCodes(dpy);
|
|
|
|
if (c == NULL)
|
|
return not_pserror;
|
|
|
|
switch (ecode - c->first_error)
|
|
{
|
|
case PSERRORBADCONTEXT: return(pserror_badcontext);
|
|
case PSERRORBADSPACE: return(pserror_badspace);
|
|
case PSERRORABORT:
|
|
if (version[DPY_NUMBER(dpy)] < DPSPROTO_V09)
|
|
return(not_pserror);
|
|
else
|
|
return(pserror_abort);
|
|
default: return(not_pserror);
|
|
}
|
|
}
|
|
|
|
/* _____________ CLIENT SIDE DPS ADDITIONS _____________ */
|
|
|
|
/* === NEW HOOKS INTO XDPS === */
|
|
|
|
void
|
|
XDPSLSetVersion(Display *dpy, unsigned ver)
|
|
{
|
|
version[DPY_NUMBER(dpy)] = ver;
|
|
}
|
|
|
|
void
|
|
XDPSLSetCodes(Display *dpy, XExtCodes *codes)
|
|
{
|
|
Codes[DPY_NUMBER(dpy)] = codes;
|
|
}
|
|
|
|
Display *
|
|
XDPSLGetShunt(Display *dpy_in)
|
|
{
|
|
return(ShuntMap[DPY_NUMBER(dpy_in)]);
|
|
}
|
|
|
|
void
|
|
XDPSLSetShunt(Display *dpy_in, Display *dpy_out)
|
|
{
|
|
ShuntMap[DPY_NUMBER(dpy_in)] = dpy_out;
|
|
}
|
|
|
|
int
|
|
XDPSLGetSyncMask(Display *dpy)
|
|
{
|
|
return (int)displayFlags[DPY_NUMBER(dpy)].syncMask;
|
|
}
|
|
|
|
void
|
|
XDPSLSetSyncMask(Display *dpy, int mask)
|
|
{
|
|
displayFlags[DPY_NUMBER(dpy)].syncMask = (char)mask;
|
|
gForceFlush = (mask & DPSCAP_SYNCMASK_RECONCILE);
|
|
}
|
|
|
|
void
|
|
XDPSLFlush(Display *xdpy)
|
|
{
|
|
register Display *dpy = ShuntMap[DPY_NUMBER(xdpy)];
|
|
|
|
_XFlush(xdpy);
|
|
if (dpy != xdpy)
|
|
N_XFlush(dpy);
|
|
}
|
|
|
|
void
|
|
XDPSLSyncGCClip(Display *xdpy, GC gc)
|
|
{
|
|
register unsigned long oldDirty;
|
|
register int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
|
|
/* We DON'T want to notice all gc changes, just the clip */
|
|
oldDirty = gc->dirty;
|
|
gc->dirty = (GCClipXOrigin|GCClipYOrigin);
|
|
XDPSLFlushGC(xdpy, gc);
|
|
gc->dirty = oldDirty;
|
|
if (dpy == xdpy || gNXSyncGCMode != 1) /* 1 means sync always */
|
|
{
|
|
/* For DPS NX and SLOW mode, flushing the gc cache has
|
|
the side-effect of synching agent and server connections.
|
|
So, to have consistent behavior, we sync for the DPS/X
|
|
or FAST cases too. */
|
|
|
|
if (GCFlushMode[dpyix] == XDPSNX_GC_UPDATES_FAST
|
|
|| dpy == xdpy)
|
|
XDPSLSync(xdpy);
|
|
}
|
|
}
|
|
|
|
|
|
#ifdef VMS
|
|
void
|
|
XDPSLSetDisplay(Display *dpy)
|
|
{
|
|
dpys[DPY_NUMBER(dpy)] = dpy;
|
|
}
|
|
#endif /* VMS */
|
|
|
|
char *
|
|
XDPSLSetAgentName(Display *dpy, char *name, int deflt)
|
|
{
|
|
char *old;
|
|
|
|
if (gCSDPS == NULL)
|
|
DPSCAPStartUp();
|
|
if (deflt)
|
|
{
|
|
old = gCSDPS->defaultAgentName;
|
|
gCSDPS->defaultAgentName = name;
|
|
}
|
|
else
|
|
{
|
|
old = gCSDPS->map[DPY_NUMBER(dpy)];
|
|
gCSDPS->map[DPY_NUMBER(dpy)] = name;
|
|
}
|
|
return(old);
|
|
}
|
|
|
|
|
|
void
|
|
XDPSLSetClientMessageHandler(Display *dpy)
|
|
{
|
|
if (dpy == NULL) return;
|
|
ClientMsgProc[DPY_NUMBER(dpy)] = XESetWireToEvent(
|
|
dpy,
|
|
ClientMessage,
|
|
DPSCAPClientMessageProc);
|
|
}
|
|
|
|
void
|
|
XDPSLSetAfterProc(Display *xdpy)
|
|
{
|
|
if (xdpy == NULL) return;
|
|
AfterProcs[DPY_NUMBER(xdpy)] = (GenericProcPtrReturnsInt)
|
|
XSetAfterFunction(xdpy, DPSCAPAfterProc);
|
|
/* +++ Consider using agent->synchandler to store old proc */
|
|
}
|
|
|
|
|
|
CSDPSFakeEventTypes
|
|
XDPSLGetCSDPSFakeEventType(Display *dpy, XEvent *event)
|
|
{
|
|
XExtCodes *codes = Codes[DPY_NUMBER(dpy)];
|
|
XExtData *extData;
|
|
DPSCAPData my;
|
|
|
|
if (event->type != ClientMessage || codes == NULL)
|
|
return(csdps_not);
|
|
extData = XFindOnExtensionList(
|
|
CSDPSHeadOfDpyExt(dpy),
|
|
codes->extension);
|
|
if (!extData)
|
|
return(csdps_not);
|
|
my = (DPSCAPData) extData->private_data;
|
|
|
|
if (event->xclient.message_type == my->typePSOutput)
|
|
return(csdps_output);
|
|
if (event->xclient.message_type == my->typePSOutputWithLen)
|
|
return(csdps_output_with_len);
|
|
if (event->xclient.message_type == my->typePSStatus)
|
|
return(csdps_status);
|
|
if (event->xclient.message_type == my->typeNoop)
|
|
return(csdps_noop);
|
|
if (event->xclient.message_type == my->typePSReady)
|
|
return(csdps_ready);
|
|
return(csdps_not);
|
|
}
|
|
|
|
Bool
|
|
XDPSLDispatchCSDPSFakeEvent(
|
|
Display *dpy,
|
|
XEvent *event,
|
|
CSDPSFakeEventTypes t)
|
|
{
|
|
register XDPSLOutputEvent *oce;
|
|
register DPSCAPOutputEvent *oev;
|
|
XDPSLOutputEvent fakeOutput;
|
|
XExtCodes *codes = Codes[DPY_NUMBER(dpy)];
|
|
|
|
if (codes == NULL)
|
|
return(False);
|
|
|
|
/* Fake up an event in the client's format. Bypasses
|
|
extension wire-to-event conversion */
|
|
switch (t)
|
|
{
|
|
case csdps_output:
|
|
oce = &fakeOutput;
|
|
oev = (DPSCAPOutputEvent *)event->xclient.data.b;
|
|
oce->length = DPSCAP_BYTESPEROUTPUTEVENT;
|
|
goto samo_samo;
|
|
case csdps_output_with_len:
|
|
oce = &fakeOutput;
|
|
oev = (DPSCAPOutputEvent *)event->xclient.data.b;
|
|
oce->length = oev->data[DPSCAP_DATA_LEN];
|
|
samo_samo:
|
|
oce->type = codes->first_event + PSEVENTOUTPUT;
|
|
oce->serial = event->xclient.serial;
|
|
oce->send_event = True; /* ??? */
|
|
oce->display = dpy;
|
|
oce->cxid = oev->cxid;
|
|
bcopy((char *) oev->data, oce->data, oce->length);
|
|
XDPSLCallOutputEventHandler(dpy, (XEvent *) oce);
|
|
break;
|
|
case csdps_status:
|
|
{
|
|
register XDPSLStatusEvent *sce;
|
|
register DPSCAPStatusEvent *sev;
|
|
XDPSLStatusEvent fakeStatus;
|
|
|
|
sev = (DPSCAPStatusEvent *)event->xclient.data.b;
|
|
sce = &fakeStatus;
|
|
sce->type = codes->first_event + PSEVENTSTATUS;
|
|
sce->serial = event->xclient.serial;
|
|
sce->send_event = True; /* ??? */
|
|
sce->display = dpy;
|
|
sce->status = sev->status;
|
|
sce->cxid = sev->cxid;
|
|
XDPSLCallStatusEventHandler(dpy, (XEvent *) sce);
|
|
break;
|
|
}
|
|
case csdps_ready: /* L2-DPS/PROTO 9 addition */
|
|
{
|
|
register XDPSLReadyEvent *rce;
|
|
XDPSLReadyEvent fakeReady;
|
|
|
|
rce = &fakeReady;
|
|
rce->type = codes->first_event + PSEVENTREADY;
|
|
rce->serial = event->xclient.serial;
|
|
rce->send_event = True;
|
|
rce->display = dpy;
|
|
rce->cxid = event->xclient.data.l[0];
|
|
rce->val[0] = event->xclient.data.l[1];
|
|
rce->val[1] = event->xclient.data.l[2];
|
|
rce->val[2] = event->xclient.data.l[3];
|
|
rce->val[3] = event->xclient.data.l[4];
|
|
XDPSLCallReadyEventHandler(dpy, (XEvent *) rce);
|
|
break;
|
|
}
|
|
default:
|
|
return(False);
|
|
}
|
|
return(True);
|
|
}
|
|
|
|
void
|
|
XDPSLGetCSDPSStatus(
|
|
Display *xdpy,
|
|
XEvent *event,
|
|
void **ret_ctxt,
|
|
int *ret_status)
|
|
{
|
|
register DPSCAPStatusEvent *sev;
|
|
|
|
/* Assert: event is ClientMessage with typePSStatus */
|
|
sev = (DPSCAPStatusEvent *)event->xclient.data.b;
|
|
|
|
if (ret_ctxt != NULL)
|
|
*ret_ctxt = XDPSContextFromXID(xdpy, sev->cxid);
|
|
if (ret_status != NULL)
|
|
*ret_status = sev->status;
|
|
}
|
|
|
|
void
|
|
XDPSLGetCSDPSReady(
|
|
Display *xdpy,
|
|
XEvent *event,
|
|
void **ret_ctxt,
|
|
int *ret_val)
|
|
{
|
|
/* Assert: event is ClientMessage with typePSReady */
|
|
|
|
if (ret_ctxt != NULL)
|
|
*ret_ctxt =
|
|
XDPSContextFromXID(xdpy, (ContextXID)event->xclient.data.l[0]);
|
|
if (ret_val != NULL)
|
|
{
|
|
ret_val[0] = event->xclient.data.l[1];
|
|
ret_val[1] = event->xclient.data.l[2];
|
|
ret_val[2] = event->xclient.data.l[3];
|
|
ret_val[3] = event->xclient.data.l[4];
|
|
}
|
|
}
|
|
|
|
void
|
|
XDPSLCAPNotify(
|
|
Display *xdpy,
|
|
ContextXID cxid,
|
|
unsigned int ntype, /* should this be an enum?? %%% */
|
|
unsigned int data,
|
|
unsigned int extra)
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
register xCAPNotifyReq *req;
|
|
|
|
if (dpy == xdpy) return;
|
|
|
|
/* We _have_ to sync client and server here in order to guarantee
|
|
correct execution sequencing. We call this procedure alot
|
|
to keep track of GC's going away, so this is a major
|
|
performance hit. */
|
|
if (ntype == DPSCAPNOTE_FREEGC)
|
|
XSync(xdpy, False);
|
|
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(CAPNotify, req);
|
|
req->reqType = DPSCAPOPCODEBASE;
|
|
req->type = X_CAPNotify;
|
|
req->cxid = cxid;
|
|
req->notification = ntype;
|
|
req->data = data;
|
|
req->extra = extra;
|
|
|
|
if (gAutoFlush)
|
|
N_XFlush(dpy);
|
|
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
}
|
|
|
|
void
|
|
XDPSLSync(Display *xdpy)
|
|
{
|
|
register Display *dpy = ShuntMap[DPY_NUMBER(xdpy)];
|
|
|
|
if (dpy == xdpy)
|
|
{
|
|
/* DPS/X */
|
|
XSync(dpy, False);
|
|
}
|
|
else
|
|
{
|
|
/* CSDPS */
|
|
XEvent event;
|
|
DPSCAPData my;
|
|
XExtData *extData;
|
|
XExtCodes *codes = Codes[DPY_NUMBER(xdpy)];
|
|
|
|
if (codes == NULL)
|
|
return;
|
|
/* Get private data */
|
|
extData = XFindOnExtensionList(
|
|
CSDPSHeadOfDpyExt(xdpy),
|
|
codes->extension);
|
|
if (!extData)
|
|
return;
|
|
my = (DPSCAPData) extData->private_data;
|
|
my->saveseq = XNextRequest(dpy)-1;
|
|
/* first send notification to agent */
|
|
XDPSLCAPNotify(xdpy, 0, DPSCAPNOTE_SYNC, my->saveseq, 0);
|
|
#ifdef XXX
|
|
fprintf(stderr, "\nXDPSLSync(DPSCAPNOTE_SYNC) sending ... ");
|
|
#endif
|
|
_XFlush(xdpy);
|
|
N_XFlush(dpy);
|
|
#ifdef XXX
|
|
fprintf(stderr, "sent.\nWaiting for reply ... ");
|
|
#endif
|
|
/* agent should send a ClientMessage, so wait for it */
|
|
XIfEvent(xdpy, &event, WaitForSyncProc, (char *) my);
|
|
|
|
#ifdef XXX
|
|
fprintf(stderr, "received.\n");
|
|
#endif
|
|
/* now client, agent, and server are synchronized */
|
|
}
|
|
}
|
|
|
|
void
|
|
XDPSLReconcileRequests(Display *xdpy, ContextXID cxid)
|
|
{
|
|
int dpyix;
|
|
unsigned int seqnum;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
|
|
if (dpy == xdpy)
|
|
return; /* No-op for DPS/X */
|
|
|
|
/* Get the sequence number and set the pause flag
|
|
IFF we are sure that some X protocol has occurred
|
|
since the last time we did a DPS request. This
|
|
minimizes pause/resume requests */
|
|
|
|
if (LastXRequest[dpyix] == XNextRequest(xdpy)-1)
|
|
{
|
|
if (gAutoFlush)
|
|
N_XFlush(dpy); /* This is what XDPSLCAPNotify would do */
|
|
return;
|
|
}
|
|
else
|
|
seqnum = DPSCAPSetPause(xdpy, cxid);
|
|
|
|
/* Pause the context specified. */
|
|
XDPSLCAPNotify(xdpy, cxid, DPSCAPNOTE_PAUSE, seqnum, 0);
|
|
|
|
/* We don't even need to flush. All we have to do is make
|
|
sure that the notify request is queued before any
|
|
DPS requests that follow. */
|
|
}
|
|
|
|
Status
|
|
XDPSLSetAgentArg(Display *xdpy, int arg, int val)
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
CARD32 capArg;
|
|
register xCAPSetArgReq *req;
|
|
|
|
if (dpy == xdpy)
|
|
return(Success); /* No-op for DPS/X */
|
|
|
|
/* dpy will be NIL if we haven't opened a connection yet,
|
|
but that's okay since we need to save the value anyway. */
|
|
|
|
if (dpy)
|
|
{
|
|
int syncMask = displayFlags[dpyix].syncMask;
|
|
|
|
/* ASSERT: There is no reason to pause the context for this
|
|
request, so just sync. */
|
|
if (syncMask & (DPSCAP_SYNCMASK_SYNC|DPSCAP_SYNCMASK_RECONCILE))
|
|
XSync(xdpy, False);
|
|
}
|
|
|
|
switch (arg)
|
|
{
|
|
case AGENT_ARG_SMALLFONTS:
|
|
AgentArgs[dpyix].showSmallSizes = val;
|
|
capArg = DPSCAP_ARG_SMALLFONTS;
|
|
break;
|
|
case AGENT_ARG_PIXMEM:
|
|
AgentArgs[dpyix].pixMem = val;
|
|
capArg = DPSCAP_ARG_PIXMEM;
|
|
break;
|
|
default:
|
|
return(!Success);
|
|
}
|
|
if (!dpy)
|
|
return(Success);
|
|
|
|
LockDisplay(dpy);
|
|
|
|
NXMacroGetReq(CAPSetArg, req);
|
|
req->reqType = DPSCAPOPCODEBASE;
|
|
req->type = X_CAPSetArg;
|
|
req->arg = capArg;
|
|
req->val = val;
|
|
|
|
if (gAutoFlush)
|
|
N_XFlush(dpy);
|
|
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
LastXRequest[dpyix] = XNextRequest(xdpy)-1;
|
|
return(Success);
|
|
}
|
|
|
|
|
|
void
|
|
XDPSLCleanAll(xdpy)
|
|
register Display *xdpy;
|
|
{
|
|
/* Clean up all state associated with dpy */
|
|
register DPSCAPPausedContextData *slot;
|
|
int dpyix = DPY_NUMBER(xdpy);
|
|
|
|
/* Clean up paused context list */
|
|
for (slot = PausedPerDisplay[dpyix]; slot; slot = PausedPerDisplay[dpyix])
|
|
{
|
|
PausedPerDisplay[dpyix] = slot->next;
|
|
Xfree(slot);
|
|
}
|
|
|
|
/* Clear agent args */
|
|
AgentArgs[dpyix].showSmallSizes = 0;
|
|
AgentArgs[dpyix].pixMem = 0;
|
|
}
|
|
|
|
void
|
|
XDPSLUpdateAgentArgs(xdpy)
|
|
register Display *xdpy;
|
|
{
|
|
int dpyix = DPY_NUMBER(xdpy);
|
|
|
|
if (AgentArgs[dpyix].showSmallSizes)
|
|
XDPSLSetAgentArg(xdpy, AGENT_ARG_SMALLFONTS, AgentArgs[dpyix].showSmallSizes);
|
|
if (AgentArgs[dpyix].pixMem)
|
|
XDPSLSetAgentArg(xdpy, AGENT_ARG_PIXMEM, AgentArgs[dpyix].pixMem);
|
|
}
|
|
|
|
void
|
|
XDPSLCleanContext(xdpy, cxid)
|
|
Display *xdpy;
|
|
ContextXID cxid;
|
|
{
|
|
/* Clean up all state associated with cxid on this dpy */
|
|
register DPSCAPPausedContextData *slot, *prev;
|
|
int dpyix = DPY_NUMBER(xdpy);
|
|
|
|
/* If this is DPS/X, then slot will never have been initialized.
|
|
See XDPSLNotifyContext */
|
|
|
|
/* Clean up paused context list */
|
|
prev = (DPSCAPPausedContextData *)NULL;
|
|
for (slot = PausedPerDisplay[dpyix]; slot; prev = slot, slot = slot->next)
|
|
{
|
|
if (slot->cxid != cxid)
|
|
continue;
|
|
if (!prev)
|
|
PausedPerDisplay[dpyix] = slot->next;
|
|
else
|
|
prev->next = slot->next;
|
|
Xfree(slot);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* DPS NX 2.0 */
|
|
void
|
|
XDPSLSetGCFlushMode(dpy, value)
|
|
Display *dpy;
|
|
int value;
|
|
{
|
|
int dpyix;
|
|
register Display *agent = ShuntMap[dpyix = DPY_NUMBER(dpy)];
|
|
|
|
if (value != XDPSNX_GC_UPDATES_SLOW && value != XDPSNX_GC_UPDATES_FAST)
|
|
{
|
|
DPSWarnProc(NULL, "DPS NX: Bogus GC flush mode.\n");
|
|
return;
|
|
}
|
|
/* 0 means no NX */
|
|
GCFlushMode[dpyix] = (agent == dpy) ? 0 : value;
|
|
}
|
|
|
|
int
|
|
XDPSLGetGCFlushMode(dpy)
|
|
Display *dpy;
|
|
{
|
|
return(GCFlushMode[DPY_NUMBER(dpy)]);
|
|
}
|
|
|
|
void
|
|
XDPSLFlushGC(xdpy, gc)
|
|
Display *xdpy;
|
|
GC gc;
|
|
{
|
|
int dpyix;
|
|
register Display *dpy = ShuntMap[dpyix = DPY_NUMBER(xdpy)];
|
|
|
|
if (!gc->dirty) return;
|
|
|
|
if (GCFlushMode[dpyix] == XDPSNX_GC_UPDATES_FAST)
|
|
{
|
|
XGCValues vals;
|
|
static unsigned long valuemask = DPSGCBITS & ~(GCClipMask);
|
|
|
|
/* Okay to call Xlib, since dpy isn't locked */
|
|
DPSAssertWarn(XGetGCValues(xdpy, gc, valuemask, &vals),
|
|
NULL, "DPS NX: XGetGCValues returned False\n");
|
|
vals.clip_mask = gc->values.clip_mask;
|
|
LockDisplay(dpy);
|
|
DPSCAPChangeGC(dpy, gc, DPSGCBITS, &vals);
|
|
UnlockDisplay(dpy);
|
|
SyncHandle();
|
|
}
|
|
/* Fall thru. Either the GCFlushMode is SLOW, which means
|
|
we will DPSCAPChangeGC as a side-effect of FlushGC when
|
|
the GC hook is called, or we just did it in the FAST case. */
|
|
FlushGC(xdpy, gc);
|
|
XDPSLFlush(xdpy);
|
|
}
|
|
|
|
/* === PRIVATE CSDPS PROCS === */
|
|
|
|
static Status
|
|
DPSCAPClientMessageProc(
|
|
Display *dpy,
|
|
XEvent *re,
|
|
xEvent *event)
|
|
{
|
|
register XDPSLOutputEvent *oce;
|
|
register DPSCAPOutputEvent *oev;
|
|
XDPSLOutputEvent fakeOutput;
|
|
XExtCodes *codes = Codes[DPY_NUMBER(dpy)];
|
|
PSCMProc oldProc = ClientMsgProc[DPY_NUMBER(dpy)];
|
|
|
|
if (codes != NULL)
|
|
{
|
|
/* Get private data */
|
|
XExtData *extData = XFindOnExtensionList(
|
|
CSDPSHeadOfDpyExt(dpy),
|
|
codes->extension);
|
|
DPSCAPData my;
|
|
|
|
/* There's no extension, or there is an extension but we are
|
|
passing events uninterpreted, so just pass it along
|
|
unless it is a DPSCAP error. */
|
|
|
|
if (!extData)
|
|
goto pass_the_buck;
|
|
my = (DPSCAPData) extData->private_data;
|
|
if (XDPSLGetPassEventsFlag(dpy) &&
|
|
(event->u.clientMessage.u.l.type != my->typeXError))
|
|
goto pass_the_buck;
|
|
|
|
/* Fake up a DPS extension event and handle it transparently,
|
|
without going through the Xlib event queue */
|
|
|
|
if (event->u.clientMessage.u.b.type == my->typePSOutput)
|
|
{
|
|
oce = &fakeOutput;
|
|
oce->length = DPSCAP_BYTESPEROUTPUTEVENT;
|
|
oev = (DPSCAPOutputEvent *)event->u.clientMessage.u.b.bytes;
|
|
goto common_stuff;
|
|
}
|
|
else if (event->u.clientMessage.u.b.type == my->typePSOutputWithLen)
|
|
{
|
|
oce = &fakeOutput;
|
|
oev = (DPSCAPOutputEvent *)event->u.clientMessage.u.b.bytes;
|
|
oce->length = oev->data[DPSCAP_DATA_LEN];
|
|
common_stuff:
|
|
oce->type = codes->first_event + PSEVENTOUTPUT;
|
|
oce->serial = _XSetLastRequestRead(dpy, (xGenericReply *)event);
|
|
oce->send_event = True; /* ??? */
|
|
oce->display = dpy;
|
|
oce->cxid = oev->cxid;
|
|
bcopy((char *) oev->data, oce->data, oce->length);
|
|
/* We've converted the event, give it to DPS */
|
|
if (TextProc)
|
|
(*TextProc)((XEvent *) oce);
|
|
return(False);
|
|
}
|
|
else if (event->u.clientMessage.u.b.type == my->typePSStatus)
|
|
{
|
|
register XDPSLStatusEvent *sce;
|
|
register DPSCAPStatusEvent *sev;
|
|
XDPSLStatusEvent fakeStatus;
|
|
|
|
sev = (DPSCAPStatusEvent *)event->u.clientMessage.u.b.bytes;
|
|
sce = &fakeStatus;
|
|
sce->type = codes->first_event + PSEVENTSTATUS;
|
|
sce->serial = _XSetLastRequestRead(dpy, (xGenericReply *)event);
|
|
sce->send_event = True; /* ??? */
|
|
sce->display = dpy;
|
|
sce->cxid = sev->cxid;
|
|
sce->status = sev->status;
|
|
/* We've converted the event, give it to DPS */
|
|
if (StatusProc[DPY_NUMBER(dpy)])
|
|
(*(StatusProc[DPY_NUMBER(dpy)]))((XEvent *) sce);
|
|
return(False);
|
|
}
|
|
else if (event->u.clientMessage.u.l.type == my->typeXError)
|
|
{
|
|
xError err;
|
|
register xError *e = &err;
|
|
|
|
e->type = X_Error;
|
|
e->errorCode = event->u.clientMessage.u.l.longs0;
|
|
e->sequenceNumber = event->u.u.sequenceNumber;
|
|
e->resourceID = event->u.clientMessage.u.l.longs3;
|
|
e->minorCode = event->u.clientMessage.u.l.longs2;
|
|
e->majorCode = event->u.clientMessage.u.l.longs1;
|
|
/* Smash the wire event here, before going off deep end */
|
|
event->u.clientMessage.u.l.type = my->typeNoop;
|
|
/* Jump! */
|
|
return(_XError(dpy, e));
|
|
}
|
|
else if (event->u.clientMessage.u.l.type == my->typePSReady)
|
|
/* L2-DPS/PROTO 9 addition */
|
|
{
|
|
register XDPSLReadyEvent *rce;
|
|
XDPSLReadyEvent fakeReady;
|
|
|
|
rce = &fakeReady;
|
|
rce->type = codes->first_event + PSEVENTREADY;
|
|
rce->serial = _XSetLastRequestRead(dpy, (xGenericReply *)event);
|
|
rce->send_event = True;
|
|
rce->display = dpy;
|
|
rce->cxid = event->u.clientMessage.u.l.longs0;
|
|
rce->val[0] = event->u.clientMessage.u.l.longs1;
|
|
rce->val[1] = event->u.clientMessage.u.l.longs2;
|
|
rce->val[2] = event->u.clientMessage.u.l.longs3;
|
|
rce->val[3] = event->u.clientMessage.u.l.longs4;
|
|
XDPSLCallReadyEventHandler(dpy, (XEvent *) rce);
|
|
return(False);
|
|
}
|
|
}
|
|
|
|
/* Put the event on the queue, so that Xlib is happy */
|
|
pass_the_buck:
|
|
return(oldProc(dpy, re, event));
|
|
}
|
|
|
|
|
|
static void
|
|
DPSCAPInitGC(Display *dpy, Display *agent, GC gc)
|
|
{
|
|
XGCValues values;
|
|
unsigned long valuemask = DPSGCBITS & ~(GCClipMask);
|
|
|
|
/* Okay to call Xlib, since dpy isn't locked */
|
|
DPSAssertWarn(XGetGCValues(dpy, gc, valuemask, &values),
|
|
NULL, "DPS NX: XGetGCValues returned False\n");
|
|
values.clip_mask = gc->values.clip_mask;
|
|
DPSCAPChangeGC(agent, gc, DPSGCBITS, &values);
|
|
SyncHandle();
|
|
XDPSLSync(dpy);
|
|
}
|
|
|
|
|
|
/* ARGSUSED */
|
|
|
|
static Bool
|
|
WaitForSyncProc(Display *xdpy, XEvent *event, char *arg)
|
|
{
|
|
DPSCAPData my = (DPSCAPData)arg;
|
|
|
|
if ((event->type & 0x7F) == ClientMessage
|
|
&& event->xclient.message_type == my->typeSync
|
|
&& event->xclient.data.l[0] == (long) my->saveseq) {
|
|
return(True);
|
|
} else {
|
|
return(False);
|
|
}
|
|
}
|
|
|
|
|
|
static int
|
|
DPSCAPAfterProc(Display *xdpy)
|
|
{
|
|
register Display *dpy = ShuntMap[DPY_NUMBER(xdpy)];
|
|
GenericProcPtrReturnsInt proc;
|
|
|
|
if (dpy != (Display *)NULL && dpy != xdpy)
|
|
{
|
|
LockDisplay(dpy);
|
|
N_XFlush(dpy);
|
|
UnlockDisplay(dpy);
|
|
LockDisplay(xdpy);
|
|
_XFlush(xdpy);
|
|
UnlockDisplay(xdpy);
|
|
}
|
|
if ((proc = AfterProcs[DPY_NUMBER(xdpy)]) != NULL)
|
|
return((*proc)(xdpy));
|
|
else
|
|
return(0);
|
|
}
|
|
|
|
|
|
static unsigned int
|
|
DPSCAPSetPause(Display *xdpy, ContextXID cxid)
|
|
{
|
|
register DPSCAPPausedContextData *slot;
|
|
int dpyix;
|
|
unsigned int ret;
|
|
|
|
/* Find or create slot */
|
|
|
|
slot = PausedPerDisplay[dpyix = DPY_NUMBER(xdpy)];
|
|
if (!slot)
|
|
{
|
|
slot = (DPSCAPPausedContextData *)
|
|
Xcalloc(1, sizeof(DPSCAPPausedContextData));
|
|
PausedPerDisplay[dpyix] = slot;
|
|
goto common_code;
|
|
/* IMPLICATION: it is okay to fall through common_code
|
|
and do test_ret. */
|
|
}
|
|
while (1)
|
|
if (slot->cxid == cxid)
|
|
{
|
|
if (!slot->paused)
|
|
{
|
|
slot->paused = True;
|
|
++gTotalPaused;
|
|
}
|
|
/* Back-to-back pauses get different sequence numbers */
|
|
ret = ++slot->seqnum;
|
|
goto test_ret;
|
|
}
|
|
else if (slot->next) slot = slot->next;
|
|
else break;
|
|
/* cxid wasn't found, so add it */
|
|
/* ASSERT: slot points to last record of the list */
|
|
slot->next = (DPSCAPPausedContextData *)
|
|
Xcalloc(1, sizeof(DPSCAPPausedContextData));
|
|
slot = slot->next;
|
|
common_code:
|
|
slot->paused = True;
|
|
++gTotalPaused;
|
|
slot->cxid = cxid;
|
|
ret = ++slot->seqnum;
|
|
test_ret:
|
|
if (!ret)
|
|
{
|
|
DPSWarnProc(NULL, "Pause sequence wrapped around!");
|
|
}
|
|
return(ret);
|
|
}
|
|
|
|
static Bool
|
|
DPSCAPResumeContext(Display *xdpy, ContextXID cxid)
|
|
{
|
|
register DPSCAPPausedContextData *slot;
|
|
int dpyix = DPY_NUMBER(xdpy);
|
|
|
|
/* Try to match cxid to list of paused contexts */
|
|
for (slot = PausedPerDisplay[dpyix]; slot; slot = slot->next)
|
|
if (slot->cxid == cxid && slot->paused)
|
|
{
|
|
/* Send resume event */
|
|
register XClientMessageEvent *ee;
|
|
XEvent e;
|
|
XExtData *extData;
|
|
DPSCAPData my;
|
|
XExtCodes *codes = Codes[dpyix];
|
|
|
|
extData = XFindOnExtensionList(
|
|
CSDPSHeadOfDpyExt(xdpy),
|
|
codes->extension);
|
|
if (!extData)
|
|
return(False);
|
|
my = (DPSCAPData) extData->private_data;
|
|
|
|
ee = &e.xclient;
|
|
ee->type = ClientMessage;
|
|
ee->display = xdpy;
|
|
ee->window = my->agentWindow;
|
|
ee->format = 32;
|
|
ee->message_type = my->typeResume;
|
|
ee->data.l[0] = cxid;
|
|
ee->data.l[1] = slot->seqnum;
|
|
(void) XSendEvent(
|
|
xdpy,
|
|
my->agentWindow,
|
|
False,
|
|
NoEventMask,
|
|
&e);
|
|
XFlush(xdpy);
|
|
/* Turn off flag */
|
|
slot->paused = False;
|
|
--gTotalPaused;
|
|
return(True);
|
|
}
|
|
/* Fall thru */
|
|
return(False);
|
|
}
|