aboutsummaryrefslogtreecommitdiff
path: root/nx-X11/programs/Xserver/lbx/lbxmain.c
diff options
context:
space:
mode:
Diffstat (limited to 'nx-X11/programs/Xserver/lbx/lbxmain.c')
-rw-r--r--nx-X11/programs/Xserver/lbx/lbxmain.c1760
1 files changed, 1760 insertions, 0 deletions
diff --git a/nx-X11/programs/Xserver/lbx/lbxmain.c b/nx-X11/programs/Xserver/lbx/lbxmain.c
new file mode 100644
index 000000000..9139dfbed
--- /dev/null
+++ b/nx-X11/programs/Xserver/lbx/lbxmain.c
@@ -0,0 +1,1760 @@
+/* $Xorg: lbxmain.c,v 1.4 2001/02/09 02:05:16 xorgcvs Exp $ */
+/*
+
+Copyright 1996, 1998 The Open Group
+
+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.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/*
+ * Copyright 1992 Network Computing Devices
+ *
+ * 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 NCD. not be used in advertising or
+ * publicity pertaining to distribution of the software without specific,
+ * written prior permission. NCD. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ *
+ * NCD. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL NCD.
+ * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+/* $XFree86: xc/programs/Xserver/lbx/lbxmain.c,v 1.12 2001/10/28 03:34:12 tsi Exp $ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <sys/types.h>
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include <X11/Xos.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "scrnintstr.h"
+#include "windowstr.h"
+#include "pixmapstr.h"
+#include "gcstruct.h"
+#include "extnsionst.h"
+#include "servermd.h"
+#define _XLBX_SERVER_
+#include <X11/extensions/lbxstr.h>
+#include <X11/extensions/lbxdeltastr.h>
+#include "lbxserve.h"
+#include <X11/extensions/lbximage.h>
+#include "lbxsrvopts.h"
+#include "lbxtags.h"
+#include <X11/Xfuncproto.h>
+#include <errno.h>
+#ifndef Lynx
+#include <sys/uio.h>
+#else
+#include <uio.h>
+#endif
+#include <stdio.h>
+
+#ifndef X_NOT_POSIX
+#include <unistd.h>
+#endif
+
+#define CloseLbxClient 0xff
+
+#define MAXBYTESDIFF 8
+
+int LbxWhoAmI = 1; /*
+ * for lbx zlib library to know who we are
+ * server = 1
+ * proxy = 0
+ */
+
+
+static void LbxResetProc ( ExtensionEntry *extEntry );
+static void LbxFreeClient ( ClientPtr client );
+static void LbxShutdownProxy ( LbxProxyPtr proxy );
+static int DecodeLbxDelta ( ClientPtr client );
+
+static LbxProxyPtr proxyList;
+unsigned char LbxReqCode;
+int LbxEventCode;
+static int BadLbxClientCode;
+static int uid_seed;
+
+static int lbxCompressWorkProcCount;
+
+LbxClientPtr lbxClients[MAXCLIENTS];
+
+extern xConnSetupPrefix connSetupPrefix;
+extern char *ConnectionInfo;
+extern int (*LbxInitialVector[3])(ClientPtr);
+
+#ifdef DEBUG
+int lbxDebug = 0;
+#endif
+
+
+void
+LbxExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+
+ lbxCompressWorkProcCount = 0;
+ proxyList = NULL;
+ uid_seed = 0;
+ if ((extEntry = AddExtension(LBXNAME, LbxNumberEvents, LbxNumberErrors,
+ ProcLbxDispatch, SProcLbxDispatch,
+ LbxResetProc, StandardMinorOpcode)))
+ {
+ LbxReqCode = (unsigned char)extEntry->base;
+ LbxEventCode = extEntry->eventBase;
+ BadLbxClientCode = extEntry->errorBase + BadLbxClient;
+ LbxDixInit();
+
+ LbxCmapInit ();
+ DeclareExtensionSecurity(LBXNAME, TRUE);
+ }
+}
+
+/*ARGSUSED*/
+static void
+LbxResetProc (ExtensionEntry *extEntry)
+{
+ LbxResetTags();
+ uid_seed = 0;
+}
+
+void
+LbxCloseClient (ClientPtr client)
+{
+ xLbxCloseEvent closeEvent;
+ ClientPtr master;
+ LbxProxyPtr proxy;
+ LbxClientPtr lbxClient = LbxClient(client);
+ CARD32 id;
+
+ if (!lbxClient)
+ return;
+ id = lbxClient->id;
+ proxy = lbxClient->proxy;
+
+ DBG (DBG_CLIENT, (stderr, "Close client %d\n", client->index));
+ LbxFreeClient (client);
+ if (!id)
+ {
+ isItTimeToYield = TRUE;
+ CloseDownFileDescriptor (client);
+ LbxShutdownProxy (proxy);
+ }
+ else
+ {
+ master = NULL;
+ if (proxy->lbxClients[0])
+ master = LbxProxyClient(proxy);
+ if (master && !master->clientGone)
+ {
+ closeEvent.type = LbxEventCode;
+ closeEvent.lbxType = LbxCloseEvent;
+ closeEvent.client = id;
+ closeEvent.sequenceNumber = master->sequence;
+ closeEvent.pad1 = closeEvent.pad2 = closeEvent.pad3 =
+ closeEvent.pad4 = closeEvent.pad5 = closeEvent.pad6 = 0;
+ if (master->swapped) {
+ int n;
+
+ swaps(&closeEvent.sequenceNumber, n);
+ swapl(&closeEvent.client, n);
+ }
+ WriteToClient(master, sizeof (closeEvent), (char *)&closeEvent);
+ LbxForceOutput(proxy);
+ }
+ }
+}
+
+static int
+LbxReencodeEvent(ClientPtr client,
+ LbxProxyPtr proxy,
+ char *buf)
+{
+ xEvent *ev = (xEvent *)buf;
+ int n;
+ lbxMotionCache *motionCache = &proxy->motionCache;
+ int motionDelta = 0;
+ Bool swapCache;
+ xEvent tev, *sev;
+
+ if (ev->u.u.type != MotionNotify) {
+ if (proxy->dosquishing)
+ return LbxSquishEvent(buf);
+ return 0;
+ }
+
+ /*
+ * Check if we can generate a motion delta event.
+ *
+ * The motion cache contains the last motion event the server sent.
+ *
+ * The following are always stored in the cache in the server's
+ * byte order:
+ * sequenceNumber, time, rootX, rootY, eventX, eventY
+ * This is because when determining if we can do a delta, all
+ * arithmetic must be done using the server's byte order.
+ *
+ * The following are stored in the byte order of the latest client
+ * receiving a motion event (indicated by motionCache->swapped):
+ * root, event, child, state
+ * These fields do not need to be stored in the server's byte order
+ * because we only use the '==' operator on them.
+ */
+
+ if (!proxy->motion_allowed_events) {
+ DBG(DBG_CLIENT, (stderr, "throttling motion event for client %d\n", client->index));
+ return sz_xEvent;
+ }
+ proxy->motion_allowed_events--;
+
+ motionCache = &proxy->motionCache;
+
+ if (!client->swapped)
+ {
+ swapCache = motionCache->swapped;
+ sev = ev;
+ }
+ else
+ {
+ swapCache = !motionCache->swapped;
+ sev = &tev;
+ cpswaps (ev->u.keyButtonPointer.rootX,
+ sev->u.keyButtonPointer.rootX);
+ cpswaps (ev->u.keyButtonPointer.rootY,
+ sev->u.keyButtonPointer.rootY);
+ cpswaps (ev->u.keyButtonPointer.eventX,
+ sev->u.keyButtonPointer.eventX);
+ cpswaps (ev->u.keyButtonPointer.eventY,
+ sev->u.keyButtonPointer.eventY);
+ cpswaps (ev->u.u.sequenceNumber,
+ sev->u.u.sequenceNumber);
+ cpswapl (ev->u.keyButtonPointer.time,
+ sev->u.keyButtonPointer.time);
+ }
+
+ if (swapCache)
+ {
+ swapl (&motionCache->root, n);
+ swapl (&motionCache->event, n);
+ swapl (&motionCache->child, n);
+ swaps (&motionCache->state, n);
+
+ motionCache->swapped = !motionCache->swapped;
+ }
+
+ motionDelta = 0;
+
+ if (ev->u.u.detail == motionCache->detail &&
+ ev->u.keyButtonPointer.root == motionCache->root &&
+ ev->u.keyButtonPointer.event == motionCache->event &&
+ ev->u.keyButtonPointer.child == motionCache->child &&
+ ev->u.keyButtonPointer.state == motionCache->state &&
+ ev->u.keyButtonPointer.sameScreen == motionCache->sameScreen) {
+
+ int root_delta_x =
+ sev->u.keyButtonPointer.rootX - motionCache->rootX;
+ int root_delta_y =
+ sev->u.keyButtonPointer.rootY - motionCache->rootY;
+ int event_delta_x =
+ sev->u.keyButtonPointer.eventX - motionCache->eventX;
+ int event_delta_y =
+ sev->u.keyButtonPointer.eventY - motionCache->eventY;
+ unsigned long sequence_delta =
+ sev->u.u.sequenceNumber - motionCache->sequenceNumber;
+ unsigned long time_delta =
+ sev->u.keyButtonPointer.time - motionCache->time;
+
+ if (root_delta_x == event_delta_x &&
+ event_delta_x >= -128 && event_delta_x < 128 &&
+ root_delta_y == event_delta_y &&
+ event_delta_y >= -128 && event_delta_y < 128) {
+
+ if (sequence_delta == 0 && time_delta < 256) {
+
+ lbxQuickMotionDeltaEvent *mev =
+ (lbxQuickMotionDeltaEvent *)(buf + sz_xEvent -
+ sz_lbxQuickMotionDeltaEvent);
+
+ mev->type = LbxEventCode + LbxQuickMotionDeltaEvent;
+ mev->deltaTime = time_delta;
+ mev->deltaX = event_delta_x;
+ mev->deltaY = event_delta_y;
+
+ motionDelta = sz_xEvent - sz_lbxQuickMotionDeltaEvent;
+
+ } else if (sequence_delta < 65536 && time_delta < 65536) {
+
+ lbxMotionDeltaEvent *mev =
+ (lbxMotionDeltaEvent *)(buf + sz_xEvent -
+ sz_lbxMotionDeltaEvent);
+
+ mev->type = LbxEventCode;
+ mev->lbxType = LbxMotionDeltaEvent;
+ mev->deltaTime = time_delta;
+ mev->deltaSequence = sequence_delta;
+ mev->deltaX = event_delta_x;
+ mev->deltaY = event_delta_y;
+
+ if (LbxProxyClient(proxy)->swapped)
+ {
+ swaps (&mev->deltaTime, n);
+ swaps (&mev->deltaSequence, n);
+ }
+
+ motionDelta = sz_xEvent - sz_lbxMotionDeltaEvent;
+ }
+ }
+ }
+
+ motionCache->sequenceNumber = sev->u.u.sequenceNumber;
+ motionCache->time = sev->u.keyButtonPointer.time;
+ motionCache->rootX = sev->u.keyButtonPointer.rootX;
+ motionCache->rootY = sev->u.keyButtonPointer.rootY;
+ motionCache->eventX = sev->u.keyButtonPointer.eventX;
+ motionCache->eventY = sev->u.keyButtonPointer.eventY;
+
+ if (motionDelta)
+ return motionDelta;
+
+ ev->u.keyButtonPointer.pad1 = 0;
+ motionCache->detail = ev->u.u.detail;
+ motionCache->root = ev->u.keyButtonPointer.root;
+ motionCache->event = ev->u.keyButtonPointer.event;
+ motionCache->child = ev->u.keyButtonPointer.child;
+ motionCache->state = ev->u.keyButtonPointer.state;
+ motionCache->sameScreen = ev->u.keyButtonPointer.sameScreen;
+ return 0;
+}
+
+static int
+LbxComposeDelta(LbxProxyPtr proxy,
+ char *reply,
+ int len,
+ char *buf)
+{
+ int diffs;
+ int cindex;
+ int n;
+ xLbxDeltaReq *p = (xLbxDeltaReq *)buf;
+
+ diffs = LBXDeltaMinDiffs(&proxy->outdeltas, (unsigned char *)reply, len,
+ min(MAXBYTESDIFF, (len - sz_xLbxDeltaReq) >> 1),
+ &cindex);
+ if (diffs < 0) {
+ LBXAddDeltaOut(&proxy->outdeltas, (unsigned char *)reply, len);
+ return 0;
+ }
+ LBXEncodeDelta(&proxy->outdeltas, (unsigned char *)reply, diffs, cindex,
+ (unsigned char *)(&buf[sz_xLbxDeltaReq]));
+ LBXAddDeltaOut(&proxy->outdeltas, (unsigned char *)reply, len);
+ p->reqType = LbxEventCode;
+ p->lbxReqType = LbxDeltaEvent;
+ p->diffs = diffs;
+ p->cindex = cindex;
+ len = (sz_xLbxDeltaReq + sz_xLbxDiffItem * diffs + 3) & ~3;
+ p->length = len >> 2;
+ if (LbxProxyClient(proxy)->swapped) {
+ swaps(&p->length, n);
+ }
+ return len;
+}
+
+void
+LbxReencodeOutput(ClientPtr client,
+ char *pbuf,
+ int *pcount,
+ char *cbuf,
+ int *ccount)
+{
+ LbxClientPtr lbxClient = LbxClient(client);
+ LbxProxyPtr proxy = lbxClient->proxy;
+ CARD32 len;
+ int n;
+ int count = *ccount;
+ char *obuf = cbuf;
+
+ if (client->clientState != ClientStateRunning) {
+ if (DELTA_CACHEABLE(&proxy->outdeltas, count) &&
+ (n = LbxComposeDelta(proxy, cbuf, count, proxy->oDeltaBuf))) {
+ memcpy(obuf, proxy->oDeltaBuf, n);
+ *ccount -= (count - n);
+ }
+ return;
+ }
+ if (lbxClient->bytes_remaining) {
+ if (count < lbxClient->bytes_remaining) {
+ lbxClient->bytes_remaining -= count;
+ return;
+ }
+ if (DELTA_CACHEABLE(&proxy->outdeltas, lbxClient->bytes_in_reply)) {
+ len = lbxClient->bytes_in_reply - lbxClient->bytes_remaining;
+ pbuf += (*pcount - len);
+ memcpy(proxy->replyBuf, pbuf, len);
+ memcpy(proxy->replyBuf + len, cbuf, lbxClient->bytes_remaining);
+ n = LbxComposeDelta(proxy, proxy->replyBuf,
+ lbxClient->bytes_in_reply, proxy->oDeltaBuf);
+ if (!n)
+ obuf += lbxClient->bytes_remaining;
+ else if (n <= len) {
+ memcpy(pbuf, proxy->oDeltaBuf, n);
+ *pcount -= (len - n);
+ *ccount -= lbxClient->bytes_remaining;
+ } else {
+ memcpy(pbuf, proxy->oDeltaBuf, len);
+ memcpy(obuf, proxy->oDeltaBuf + len, n - len);
+ *ccount -= lbxClient->bytes_remaining - (n - len);
+ obuf += n - len;
+ }
+ } else
+ obuf += lbxClient->bytes_remaining;
+ cbuf += lbxClient->bytes_remaining;
+ count -= lbxClient->bytes_remaining;
+ lbxClient->bytes_remaining = 0;
+ }
+ while (count) {
+ lbxClient->bytes_in_reply = sz_xEvent;
+ if (((xGenericReply *)cbuf)->type == X_Reply) {
+ len = ((xGenericReply *)cbuf)->length;
+ if (client->swapped) {
+ swapl(&len, n);
+ }
+ lbxClient->bytes_in_reply += (len << 2);
+ if (LbxProxyClient(proxy)->swapped != client->swapped) {
+ swapl(&((xGenericReply *)cbuf)->length, n);
+ }
+ if (count < lbxClient->bytes_in_reply) {
+ lbxClient->bytes_remaining = lbxClient->bytes_in_reply - count;
+ if (obuf != cbuf)
+ memmove(obuf, cbuf, count);
+ return;
+ }
+ } else if (((xGenericReply *)cbuf)->type > X_Reply &&
+ ((xGenericReply *)cbuf)->type < LASTEvent &&
+ (n = LbxReencodeEvent(client, proxy, cbuf))) {
+ cbuf += n;
+ *ccount -= n;
+ count -= n;
+ if (n == sz_xEvent)
+ continue;
+ lbxClient->bytes_in_reply -= n;
+ }
+ if (DELTA_CACHEABLE(&proxy->outdeltas, lbxClient->bytes_in_reply) &&
+ (n = LbxComposeDelta(proxy, cbuf, lbxClient->bytes_in_reply,
+ proxy->oDeltaBuf))) {
+ memcpy(obuf, proxy->oDeltaBuf, n);
+ obuf += n;
+ *ccount -= (lbxClient->bytes_in_reply - n);
+ } else {
+ if (obuf != cbuf)
+ memmove(obuf, cbuf, lbxClient->bytes_in_reply);
+ obuf += lbxClient->bytes_in_reply;
+ }
+ cbuf += lbxClient->bytes_in_reply;
+ count -= lbxClient->bytes_in_reply;
+ }
+}
+
+/*ARGSUSED*/
+static void
+LbxReplyCallback(CallbackListPtr *pcbl,
+ pointer nulldata,
+ pointer calldata)
+{
+ ReplyInfoRec *pri = (ReplyInfoRec *)calldata;
+ ClientPtr client = pri->client;
+ LbxClientPtr lbxClient;
+ REQUEST(xReq);
+
+ if (!pri->startOfReply || stuff->reqType > 127)
+ return;
+ lbxClient = LbxClient(client);
+ if (lbxClient)
+ ZeroReplyPadBytes(pri->replyData, stuff->reqType);
+}
+
+/*
+ * XXX If you think this is moronic, you're in good company,
+ * but things definitely hang if we don't have this.
+ */
+/* ARGSUSED */
+static Bool
+LbxCheckCompressInput (ClientPtr dummy1,
+ pointer dummy2)
+{
+ LbxProxyPtr proxy;
+
+ if (!lbxCompressWorkProcCount)
+ return TRUE;
+
+ for (proxy = proxyList; proxy; proxy = proxy->next) {
+ if (proxy->compHandle &&
+ proxy->streamOpts.streamCompInputAvail(proxy->fd))
+ AvailableClientInput (LbxProxyClient(proxy));
+ }
+ return FALSE;
+}
+
+static Bool
+LbxIsClientBlocked (LbxClientPtr lbxClient)
+{
+ LbxProxyPtr proxy = lbxClient->proxy;
+
+ return (lbxClient->ignored ||
+ (GrabInProgress && lbxClient->client->index != GrabInProgress &&
+ lbxClient != proxy->lbxClients[0]));
+}
+
+static void
+LbxSwitchRecv (LbxProxyPtr proxy,
+ LbxClientPtr lbxClient)
+{
+ ClientPtr client;
+
+ proxy->curRecv = lbxClient;
+ if (!lbxClient || lbxClient->client->clientGone)
+ {
+ DBG(DBG_CLIENT, (stderr, "switching to dispose input\n"));
+ lbxClient = proxy->lbxClients[0];
+ if (!lbxClient)
+ return;
+ }
+ client = lbxClient->client;
+ DBG (DBG_SWITCH, (stderr, "switching input to client %d\n", client->index));
+
+ SwitchClientInput (client, FALSE);
+ proxy->curDix = lbxClient;
+}
+
+/* ARGSUSED */
+static Bool
+LbxWaitForUnblocked (ClientPtr client,
+ pointer closure)
+{
+ LbxClientPtr lbxClient;
+ LbxProxyPtr proxy;
+
+ if (client->clientGone)
+ return TRUE;
+ lbxClient = LbxClient(client);
+ if (!lbxClient)
+ return TRUE;
+ proxy = lbxClient->proxy;
+ if (LbxIsClientBlocked (lbxClient) ||
+ ((lbxClient != proxy->curDix) && proxy->curDix->reqs_pending &&
+ !LbxIsClientBlocked(proxy->curDix)))
+ return FALSE;
+ lbxClient->input_blocked = FALSE;
+ DBG (DBG_BLOCK, (stderr, "client %d no longer blocked, switching\n",
+ client->index));
+ SwitchClientInput (client, TRUE);
+ proxy->curDix = lbxClient;
+ return TRUE;
+}
+
+void
+LbxSetForBlock(LbxClientPtr lbxClient)
+{
+ lbxClient->reqs_pending++;
+ if (!lbxClient->input_blocked)
+ {
+ lbxClient->input_blocked = TRUE;
+ QueueWorkProc(LbxWaitForUnblocked, lbxClient->client, NULL);
+ }
+}
+
+/* ARGSUSED */
+static int
+LbxWaitForUngrab (ClientPtr client,
+ pointer closure)
+{
+ LbxClientPtr lbxClient = LbxClient(client);
+ LbxProxyPtr proxy;
+ xLbxListenToAllEvent ungrabEvent;
+
+ if (client->clientGone || !lbxClient)
+ return TRUE;
+ if (GrabInProgress)
+ return FALSE;
+ proxy = lbxClient->proxy;
+ proxy->grabClient = 0;
+ ungrabEvent.type = LbxEventCode;
+ ungrabEvent.lbxType = LbxListenToAll;
+ ungrabEvent.pad1 = ungrabEvent.pad2 = ungrabEvent.pad3 =
+ ungrabEvent.pad4 = ungrabEvent.pad5 = ungrabEvent.pad6 =
+ ungrabEvent.pad7 = 0;
+ WriteToClient (client,
+ sizeof(xLbxListenToAllEvent), (char *)&ungrabEvent);
+ LbxForceOutput(proxy);
+ return TRUE;
+}
+
+static void
+LbxServerGrab(LbxProxyPtr proxy)
+{
+ LbxClientPtr grabbingLbxClient;
+ xLbxListenToOneEvent grabEvent;
+
+ /*
+ * If the current grabbing client has changed, then we need
+ * to send a message to update the proxy.
+ */
+
+ grabEvent.type = LbxEventCode;
+ grabEvent.lbxType = LbxListenToOne;
+ if (!(grabbingLbxClient = lbxClients[GrabInProgress]) ||
+ grabbingLbxClient->proxy != proxy)
+ grabEvent.client = 0xffffffff; /* client other than a proxy client */
+ else
+ grabEvent.client = grabbingLbxClient->id;
+ grabEvent.pad1 = grabEvent.pad2 = grabEvent.pad3 =
+ grabEvent.pad4 = grabEvent.pad5 = grabEvent.pad6 = 0;
+ if (LbxProxyClient(proxy)->swapped) {
+ int n;
+ swapl(&grabEvent.client, n);
+ }
+ WriteToClient(LbxProxyClient(proxy),
+ sizeof(xLbxListenToOneEvent), (char *)&grabEvent);
+ LbxForceOutput(proxy);
+ if (!proxy->grabClient)
+ QueueWorkProc(LbxWaitForUngrab, LbxProxyClient(proxy), NULL);
+ proxy->grabClient = GrabInProgress;
+}
+
+#define MAJOROP(client) ((xReq *)client->requestBuffer)->reqType
+#define MINOROP(client) ((xReq *)client->requestBuffer)->data
+
+static Bool lbxCacheable[] = {
+ FALSE, /* LbxQueryVersion 0 */
+ FALSE, /* LbxStartProxy 1 */
+ TRUE, /* LbxStopProxy 2 */
+ FALSE, /* LbxSwitch 3 */
+ FALSE, /* LbxNewClient 4 */
+ TRUE, /* LbxCloseClient 5 */
+ TRUE, /* LbxModifySequence 6 */
+ FALSE, /* LbxAllowMotion 7 */
+ TRUE, /* LbxIncrementPixel 8 */
+ FALSE, /* LbxDelta 9 */
+ TRUE, /* LbxGetModifierMapping 10 */
+ FALSE, /* nothing 11 */
+ TRUE, /* LbxInvalidateTag 12 */
+ TRUE, /* LbxPolyPoint 13 */
+ TRUE, /* LbxPolyLine 14 */
+ TRUE, /* LbxPolySegment 15 */
+ TRUE, /* LbxPolyRectangle 16 */
+ TRUE, /* LbxPolyArc 17 */
+ TRUE, /* LbxFillPoly 18 */
+ TRUE, /* LbxPolyFillRectangle 19 */
+ TRUE, /* LbxPolyFillArc 20 */
+ TRUE, /* LbxGetKeyboardMapping 21 */
+ TRUE, /* LbxQueryFont 22 */
+ TRUE, /* LbxChangeProperty 23 */
+ TRUE, /* LbxGetProperty 24 */
+ TRUE, /* LbxTagData 25 */
+ TRUE, /* LbxCopyArea 26 */
+ TRUE, /* LbxCopyPlane 27 */
+ TRUE, /* LbxPolyText8 28 */
+ TRUE, /* LbxPolyText16 29 */
+ TRUE, /* LbxImageText8 30 */
+ TRUE, /* LbxImageText16 31 */
+ FALSE, /* LbxQueryExtension 32 */
+ TRUE, /* LbxPutImage 33 */
+ TRUE, /* LbxGetImage 34 */
+ FALSE, /* LbxBeginLargeRequest 35 */
+ FALSE, /* LbxLargeRequestData 36 */
+ FALSE, /* LbxEndLargeRequest 37 */
+ FALSE, /* LbxInternAtoms 38 */
+ TRUE, /* LbxGetWinAttrAndGeom 39 */
+ TRUE, /* LbxGrabCmap 40 */
+ TRUE, /* LbxReleaseCmap 41 */
+ TRUE, /* LbxAllocColor 42 */
+ TRUE, /* LbxSync 43 */
+};
+
+#define NUM(a) (sizeof (a) / sizeof (a[0]))
+
+static int
+LbxReadRequestFromClient (ClientPtr client)
+{
+ int ret;
+ LbxClientPtr lbxClient = LbxClient(client);
+ LbxProxyPtr proxy = lbxClient->proxy;
+ ClientPtr masterClient = LbxProxyClient(proxy);
+ Bool isblocked;
+ Bool cacheable;
+
+ DBG (DBG_READ_REQ, (stderr, "Reading request from client %d\n", client->index));
+
+ if (GrabInProgress && (proxy->grabClient != GrabInProgress))
+ LbxServerGrab(proxy);
+ isblocked = LbxIsClientBlocked(lbxClient);
+
+ if (lbxClient->reqs_pending && !isblocked) {
+ ret = StandardReadRequestFromClient(client);
+ if (ret > 0 && (MAJOROP(client) == LbxReqCode) &&
+ (MINOROP(client) == X_LbxEndLargeRequest))
+ ret = PrepareLargeReqBuffer(client);
+ if (!--lbxClient->reqs_pending && (lbxClient != proxy->curRecv))
+ LbxSwitchRecv (proxy, proxy->curRecv);
+ return ret;
+ }
+ while (1) {
+ ret = StandardReadRequestFromClient(masterClient);
+ if (ret <= 0)
+ return ret;
+ client->requestBuffer = masterClient->requestBuffer;
+ client->req_len = masterClient->req_len;
+ cacheable = client->clientState == ClientStateRunning;
+ if (cacheable && (MAJOROP(client) == LbxReqCode)) {
+ /* Check to see if this request is delta cached */
+ if (MINOROP(client) < NUM(lbxCacheable))
+ cacheable = lbxCacheable[MINOROP(client)];
+ switch (MINOROP(client)) {
+ case X_LbxSwitch:
+ /* Switch is sent by proxy */
+ if (masterClient->swapped)
+ SProcLbxSwitch (client);
+ else
+ ProcLbxSwitch (client);
+ return 0;
+ case X_LbxDelta:
+ ret = DecodeLbxDelta (client);
+ DBG(DBG_DELTA,
+ (stderr,"delta decompressed msg %d, len = %d\n",
+ (unsigned)((unsigned char *)client->requestBuffer)[0],
+ ret));
+ break;
+ case X_LbxEndLargeRequest:
+ if (!isblocked)
+ ret = PrepareLargeReqBuffer(client);
+ break;
+ }
+ }
+ if (cacheable && DELTA_CACHEABLE(&proxy->indeltas, ret)) {
+ DBG(DBG_DELTA,
+ (stderr, "caching msg %d, len = %d, index = %d\n",
+ (unsigned)((unsigned char *)client->requestBuffer)[0],
+ ret, proxy->indeltas.nextDelta));
+ LBXAddDeltaIn(&proxy->indeltas, client->requestBuffer, ret);
+ }
+ if (client->swapped != masterClient->swapped) {
+ char n;
+ /* put length in client order */
+ swaps(&((xReq *)client->requestBuffer)->length, n);
+ }
+ if (!isblocked)
+ return ret;
+ DBG (DBG_BLOCK, (stderr, "Stashing %d bytes for %d\n",
+ ret, client->index));
+ AppendFakeRequest (client, client->requestBuffer, ret);
+ LbxSetForBlock(lbxClient);
+ }
+}
+
+static LbxClientPtr
+LbxInitClient (LbxProxyPtr proxy,
+ ClientPtr client,
+ CARD32 id)
+{
+ LbxClientPtr lbxClient;
+ int i;
+
+ lbxClient = (LbxClientPtr) xalloc (sizeof (LbxClientRec));
+ if (!lbxClient)
+ return NULL;
+ lbxClient->id = id;
+ lbxClient->client = client;
+ lbxClient->proxy = proxy;
+ lbxClient->ignored = FALSE;
+ lbxClient->input_blocked = FALSE;
+ lbxClient->reqs_pending = 0;
+ lbxClient->bytes_in_reply = 0;
+ lbxClient->bytes_remaining = 0;
+ client->readRequest = LbxReadRequestFromClient;
+ bzero (lbxClient->drawableCache, sizeof (lbxClient->drawableCache));
+ bzero (lbxClient->gcontextCache, sizeof (lbxClient->gcontextCache));
+ lbxClients[client->index] = lbxClient;
+ for (i = 0; proxy->lbxClients[i]; i++)
+ ;
+ if (i > proxy->maxIndex)
+ proxy->maxIndex = i;
+ proxy->lbxClients[i] = lbxClient;
+ proxy->numClients++;
+ lbxClient->gfx_buffer = (pointer) NULL;
+ lbxClient->gb_size = 0;
+ return lbxClient;
+}
+
+static void
+LbxFreeClient (ClientPtr client)
+{
+ LbxClientPtr lbxClient = LbxClient(client);
+ LbxProxyPtr proxy = lbxClient->proxy;
+ int i;
+
+ if (lbxClient != proxy->lbxClients[0]) {
+ if (lbxClient == proxy->curRecv)
+ LbxSwitchRecv(proxy, NULL);
+ else if (lbxClient == proxy->curDix)
+ LbxSwitchRecv(proxy, proxy->curRecv);
+ }
+
+ --proxy->numClients;
+ lbxClients[client->index] = NULL;
+ for (i = 0; i <= proxy->maxIndex; i++) {
+ if (proxy->lbxClients[i] == lbxClient) {
+ proxy->lbxClients[i] = NULL;
+ break;
+ }
+ }
+ while (proxy->maxIndex >= 0 && !proxy->lbxClients[proxy->maxIndex])
+ --proxy->maxIndex;
+ xfree(lbxClient->gfx_buffer);
+ client->readRequest = StandardReadRequestFromClient;
+ xfree (lbxClient);
+}
+
+static void
+LbxFreeProxy (LbxProxyPtr proxy)
+{
+ LbxProxyPtr *p;
+
+ LBXFreeDeltaCache(&proxy->indeltas);
+ LBXFreeDeltaCache(&proxy->outdeltas);
+ LbxFreeOsBuffers(proxy);
+ if (proxy->iDeltaBuf)
+ xfree(proxy->iDeltaBuf);
+ if (proxy->replyBuf)
+ xfree(proxy->replyBuf);
+ if (proxy->oDeltaBuf)
+ xfree(proxy->oDeltaBuf);
+ if (proxy->compHandle)
+ proxy->streamOpts.streamCompFreeHandle(proxy->compHandle);
+ if (proxy->bitmapCompMethods)
+ xfree (proxy->bitmapCompMethods);
+ if (proxy->pixmapCompMethods)
+ xfree (proxy->pixmapCompMethods);
+ if (proxy->pixmapCompDepths)
+ {
+ int i;
+ for (i = 0; i < proxy->numPixmapCompMethods; i++)
+ xfree (proxy->pixmapCompDepths[i]);
+ xfree (proxy->pixmapCompDepths);
+ }
+
+ for (p = &proxyList; *p; p = &(*p)->next) {
+ if (*p == proxy) {
+ *p = proxy->next;
+ break;
+ }
+ }
+ if (!proxyList)
+ DeleteCallback(&ReplyCallback, LbxReplyCallback, NULL);
+
+ xfree (proxy);
+}
+
+LbxProxyPtr
+LbxPidToProxy(int pid)
+{
+ LbxProxyPtr proxy;
+
+ for (proxy = proxyList; proxy; proxy = proxy->next) {
+ if (proxy->pid == pid)
+ return proxy;
+ }
+ return NULL;
+}
+
+static void
+LbxShutdownProxy (LbxProxyPtr proxy)
+{
+ int i;
+ ClientPtr client;
+
+ if (proxy->compHandle)
+ --lbxCompressWorkProcCount;
+ while (proxy->grabbedCmaps)
+ LbxReleaseCmap(proxy->grabbedCmaps, FALSE);
+ for (i = 0; i <= proxy->maxIndex; i++)
+ {
+ if (proxy->lbxClients[i])
+ {
+ client = proxy->lbxClients[i]->client;
+ if (!client->clientGone)
+ CloseDownClient (client);
+ }
+ }
+ LbxFlushTags(proxy);
+ LbxFreeProxy(proxy);
+}
+
+
+int
+ProcLbxQueryVersion (ClientPtr client)
+{
+ /* REQUEST(xLbxQueryVersionReq); */
+ xLbxQueryVersionReply rep;
+ register int n;
+
+ REQUEST_SIZE_MATCH(xLbxQueryVersionReq);
+ rep.type = X_Reply;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+ rep.majorVersion = LBX_MAJOR_VERSION;
+ rep.minorVersion = LBX_MINOR_VERSION;
+ rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
+
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+ WriteToClient(client, sizeof(xLbxQueryVersionReply), (char *)&rep);
+ return (client->noClientException);
+}
+
+static int
+NextProxyID (void)
+{
+ LbxProxyPtr proxy;
+ int id;
+
+ for (id = 1; id < MAX_NUM_PROXIES; id++) {
+ for (proxy = proxyList; proxy && proxy->pid != id; proxy = proxy->next)
+ ;
+ if (!proxy)
+ return id;
+ }
+ return -1;
+}
+
+int
+ProcLbxStartProxy (ClientPtr client)
+{
+ REQUEST(xLbxStartProxyReq);
+ LbxProxyPtr proxy;
+ LbxClientPtr lbxClient;
+ int reqlen;
+ int replylen;
+ xLbxStartReply *replybuf;
+ LbxNegOptsRec negopt;
+ register int n;
+ pointer compHandle = NULL;
+
+ REQUEST_AT_LEAST_SIZE(xLbxStartProxyReq);
+ if (lbxClients[client->index])
+ return BadLbxClientCode;
+ proxy = (LbxProxyPtr) xalloc (sizeof (LbxProxyRec));
+ if (!proxy)
+ return BadAlloc;
+ bzero(proxy, sizeof (LbxProxyRec));
+ proxy->pid = NextProxyID();
+ if (proxy->pid < 0) { /* too many proxies */
+ xfree(proxy);
+ return BadAlloc;
+ }
+ proxy->uid = ++uid_seed;
+ if (!proxyList)
+ AddCallback(&ReplyCallback, LbxReplyCallback, NULL);
+
+ if(!proxyList)
+ proxyList = proxy;
+ else{
+ proxy->next = proxyList;
+ proxyList = proxy;
+ }
+
+ /*
+ * Don't know exactly how big the reply will be, but it won't be
+ * bigger than the request
+ */
+ reqlen = client->req_len << 2;
+ replybuf = (xLbxStartReply *) xalloc(max(reqlen, sz_xLbxStartReply));
+ if (!replybuf) {
+ LbxFreeProxy(proxy);
+ return BadAlloc;
+ }
+
+ LbxOptionInit(&negopt);
+
+ replylen = LbxOptionParse(&negopt,
+ (unsigned char *)&stuff[1],
+ reqlen - sz_xLbxStartProxyReq,
+ (unsigned char *)&replybuf->optDataStart);
+ if (replylen < 0) {
+ /*
+ * Didn't understand option format, so we'll just end up
+ * using the defaults. Set nopts so that the proxy will
+ * be informed that we rejected the options because of
+ * decoding problems.
+ */
+ LbxOptionInit(&negopt);
+ negopt.nopts = 0xff;
+ replylen = 0;
+ }
+
+ if (LBXInitDeltaCache(&proxy->indeltas, negopt.proxyDeltaN,
+ negopt.proxyDeltaMaxLen) < 0
+ ||
+ LBXInitDeltaCache(&proxy->outdeltas, negopt.serverDeltaN,
+ negopt.serverDeltaMaxLen) < 0) {
+ LbxFreeProxy(proxy);
+ xfree(replybuf);
+ return BadAlloc;
+ }
+
+ n = 0;
+ if (negopt.proxyDeltaN)
+ n = negopt.proxyDeltaMaxLen;
+ if (negopt.serverDeltaN && negopt.serverDeltaMaxLen > n)
+ n = negopt.serverDeltaMaxLen;
+ if (n &&
+ (!(proxy->iDeltaBuf = (char *)xalloc (n)) ||
+ !(proxy->replyBuf = (char *)xalloc (n)) ||
+ !(proxy->oDeltaBuf = (char *)xalloc (n)))) {
+ LbxFreeProxy(proxy);
+ xfree(replybuf);
+ return BadAlloc;
+ }
+
+ MakeClientGrabImpervious(client); /* proxy needs to be grab-proof */
+ proxy->fd = ClientConnectionNumber(client);
+ if (negopt.streamOpts.streamCompInit) {
+ compHandle =
+ (*negopt.streamOpts.streamCompInit)(proxy->fd, negopt.streamOpts.streamCompArg);
+ if (!compHandle) {
+ LbxFreeProxy(proxy);
+ xfree(replybuf);
+ return BadAlloc;
+ }
+ }
+ proxy->ofirst = NULL;
+ proxy->olast = NULL;
+ if (!LbxInitClient (proxy, client, 0))
+ {
+ LbxFreeProxy(proxy);
+ xfree(replybuf);
+ return BadAlloc;
+ }
+ proxy->dosquishing = negopt.squish;
+ proxy->numBitmapCompMethods = negopt.numBitmapCompMethods;
+ proxy->bitmapCompMethods = negopt.bitmapCompMethods;
+ proxy->numPixmapCompMethods = negopt.numPixmapCompMethods;
+ proxy->pixmapCompMethods = negopt.pixmapCompMethods;
+ proxy->pixmapCompDepths = negopt.pixmapCompDepths;
+
+ proxy->streamOpts = negopt.streamOpts;
+ proxy->useTags = negopt.useTags;
+
+ proxy->grabbedCmaps = NULL;
+
+ /* send reply */
+ replybuf->type = X_Reply;
+ replybuf->nOpts = negopt.nopts;
+ replybuf->sequenceNumber = client->sequence;
+
+ replylen += sz_xLbxStartReplyHdr;
+ if (replylen < sz_xLbxStartReply)
+ replylen = sz_xLbxStartReply;
+ replybuf->length = (replylen - sz_xLbxStartReply + 3) >> 2;
+ if (client->swapped) {
+ swaps(&replybuf->sequenceNumber, n);
+ swapl(&replybuf->length, n);
+ }
+ lbxClient = LbxClient(client);
+ WriteToClient(client, replylen, (char *)replybuf);
+
+ LbxProxyConnection(client, proxy);
+ lbxClient = proxy->lbxClients[0];
+ proxy->curDix = lbxClient;
+ proxy->curRecv = lbxClient;
+ proxy->compHandle = compHandle;
+
+ if (proxy->compHandle && !lbxCompressWorkProcCount++)
+ QueueWorkProc(LbxCheckCompressInput, NULL, NULL);
+
+ xfree(replybuf);
+ return Success;
+}
+
+int
+ProcLbxStopProxy(ClientPtr client)
+{
+ /* REQUEST(xLbxStopProxyReq); */
+ LbxProxyPtr proxy;
+ LbxClientPtr lbxClient = LbxClient(client);
+
+ REQUEST_SIZE_MATCH(xLbxStopProxyReq);
+
+ if (!lbxClient)
+ return BadLbxClientCode;
+ if (lbxClient->id)
+ return BadLbxClientCode;
+
+ proxy = lbxClient->proxy;
+ LbxFreeClient (client);
+ LbxShutdownProxy (proxy);
+ return Success;
+}
+
+int
+ProcLbxSwitch(ClientPtr client)
+{
+ REQUEST(xLbxSwitchReq);
+ LbxProxyPtr proxy = LbxMaybeProxy(client);
+ LbxClientPtr lbxClient;
+ int i;
+
+ REQUEST_SIZE_MATCH(xLbxSwitchReq);
+ if (!proxy)
+ return BadLbxClientCode;
+ for (i = 0; i <= proxy->maxIndex; i++) {
+ lbxClient = proxy->lbxClients[i];
+ if (lbxClient && lbxClient->id == stuff->client) {
+ LbxSwitchRecv (proxy, lbxClient);
+ return Success;
+ }
+ }
+ LbxSwitchRecv (proxy, NULL);
+ return BadLbxClientCode;
+}
+
+int
+ProcLbxBeginLargeRequest(ClientPtr client)
+{
+ REQUEST(xLbxBeginLargeRequestReq);
+
+ client->sequence--;
+ REQUEST_SIZE_MATCH(xLbxBeginLargeRequestReq);
+ if (!AllocateLargeReqBuffer(client, stuff->largeReqLength << 2))
+ return BadAlloc;
+ return Success;
+}
+
+
+int
+ProcLbxLargeRequestData(ClientPtr client)
+{
+ REQUEST(xLbxLargeRequestDataReq);
+
+ client->sequence--;
+ REQUEST_AT_LEAST_SIZE(xLbxLargeRequestDataReq);
+ if (!AddToLargeReqBuffer(client, (char *) (stuff + 1),
+ (client->req_len - 1) << 2))
+ return BadAlloc;
+ return Success;
+}
+
+
+int
+ProcLbxEndLargeRequest(ClientPtr client)
+{
+ /* REQUEST(xReq); */
+
+ client->sequence--;
+ REQUEST_SIZE_MATCH(xReq);
+ return BadAlloc;
+}
+
+
+int
+ProcLbxInternAtoms(ClientPtr client)
+{
+ REQUEST(xLbxInternAtomsReq);
+ LbxClientPtr lbxClient = LbxClient(client);
+ xLbxInternAtomsReply *replyRet;
+ char *ptr = (char *) stuff + sz_xLbxInternAtomsReq;
+ Atom *atomsRet;
+ int replyLen, i;
+ char lenbuf[2];
+ CARD16 len;
+ char n;
+
+ REQUEST_AT_LEAST_SIZE(xLbxInternAtomsReq);
+
+ if (!lbxClient)
+ return BadLbxClientCode;
+ if (lbxClient->id)
+ return BadLbxClientCode;
+
+ replyLen = sz_xLbxInternAtomsReplyHdr + stuff->num * sizeof (Atom);
+ if (replyLen < sz_xLbxInternAtomsReply)
+ replyLen = sz_xLbxInternAtomsReply;
+
+ if (!(replyRet = (xLbxInternAtomsReply *) xalloc (replyLen)))
+ return BadAlloc;
+
+ atomsRet = (Atom *) ((char *) replyRet + sz_xLbxInternAtomsReplyHdr);
+
+ for (i = 0; i < stuff->num; i++)
+ {
+ lenbuf[0] = ptr[0];
+ lenbuf[1] = ptr[1];
+ len = *((CARD16 *) lenbuf);
+ ptr += 2;
+
+ if ((atomsRet[i] = MakeAtom (ptr, len, TRUE)) == BAD_RESOURCE)
+ {
+ xfree (replyRet);
+ return BadAlloc;
+ }
+
+ ptr += len;
+ }
+
+ if (client->swapped)
+ for (i = 0; i < stuff->num; i++)
+ swapl (&atomsRet[i], n);
+
+ replyRet->type = X_Reply;
+ replyRet->sequenceNumber = client->sequence;
+ replyRet->length = (replyLen - sz_xLbxInternAtomsReply + 3) >> 2;
+
+ if (client->swapped) {
+ swaps(&replyRet->sequenceNumber, n);
+ swapl(&replyRet->length, n);
+ }
+
+ WriteToClient (client, replyLen, (char *) replyRet);
+
+ xfree (replyRet);
+
+ return Success;
+}
+
+
+int
+ProcLbxGetWinAttrAndGeom(ClientPtr client)
+{
+ REQUEST(xLbxGetWinAttrAndGeomReq);
+ xGetWindowAttributesReply wa;
+ xGetGeometryReply wg;
+ xLbxGetWinAttrAndGeomReply reply;
+ WindowPtr pWin;
+ int status;
+
+ REQUEST_SIZE_MATCH(xLbxGetWinAttrAndGeomReq);
+ pWin = (WindowPtr)SecurityLookupWindow(stuff->id, client,
+ SecurityReadAccess);
+ if (!pWin)
+ return(BadWindow);
+ GetWindowAttributes(pWin, client, &wa);
+
+ if ((status = GetGeometry(client, &wg)) != Success)
+ return status;
+
+ reply.type = X_Reply;
+ reply.length = (sz_xLbxGetWinAttrAndGeomReply - 32) >> 2;
+ reply.sequenceNumber = client->sequence;
+
+ reply.backingStore = wa.backingStore;
+ reply.visualID = wa.visualID;
+#if defined(__cplusplus) || defined(c_plusplus)
+ reply.c_class = wa.c_class;
+#else
+ reply.class = wa.class;
+#endif
+ reply.bitGravity = wa.bitGravity;
+ reply.winGravity = wa.winGravity;
+ reply.backingBitPlanes = wa.backingBitPlanes;
+ reply.backingPixel = wa.backingPixel;
+ reply.saveUnder = wa.saveUnder;
+ reply.mapInstalled = wa.mapInstalled;
+ reply.mapState = wa.mapState;
+ reply.override = wa.override;
+ reply.colormap = wa.colormap;
+ reply.allEventMasks = wa.allEventMasks;
+ reply.yourEventMask = wa.yourEventMask;
+ reply.doNotPropagateMask = wa.doNotPropagateMask;
+ reply.pad1 = 0;
+ reply.root = wg.root;
+ reply.x = wg.x;
+ reply.y = wg.y;
+ reply.width = wg.width;
+ reply.height = wg.height;
+ reply.borderWidth = wg.borderWidth;
+ reply.depth = wg.depth;
+ reply.pad2 = 0;
+
+ if (client->swapped)
+ {
+ register char n;
+
+ swaps(&reply.sequenceNumber, n);
+ swapl(&reply.length, n);
+ swapl(&reply.visualID, n);
+ swaps(&reply.class, n);
+ swapl(&reply.backingBitPlanes, n);
+ swapl(&reply.backingPixel, n);
+ swapl(&reply.colormap, n);
+ swapl(&reply.allEventMasks, n);
+ swapl(&reply.yourEventMask, n);
+ swaps(&reply.doNotPropagateMask, n);
+ swapl(&reply.root, n);
+ swaps(&reply.x, n);
+ swaps(&reply.y, n);
+ swaps(&reply.width, n);
+ swaps(&reply.height, n);
+ swaps(&reply.borderWidth, n);
+ }
+
+ WriteToClient(client, sizeof(xLbxGetWinAttrAndGeomReply), (char *)&reply);
+ return(client->noClientException);
+}
+
+int
+ProcLbxNewClient(ClientPtr client)
+{
+ REQUEST(xLbxNewClientReq);
+ ClientPtr newClient;
+ LbxProxyPtr proxy = LbxMaybeProxy(client);
+ CARD32 id;
+ int len, i;
+ char *setupbuf;
+ LbxClientPtr lbxClient;
+
+ REQUEST_AT_LEAST_SIZE(xLbxNewClientReq);
+
+ /* save info before our request disappears */
+ id = stuff->client;
+ if (!proxy || !id)
+ return BadLbxClientCode;
+ if (proxy->numClients == MAX_LBX_CLIENTS)
+ return BadAlloc;
+ for (i = 1; i <= proxy->maxIndex; i++) {
+ if (proxy->lbxClients[i] && proxy->lbxClients[i]->id == id)
+ return BadLbxClientCode;
+ }
+ len = (client->req_len << 2) - sizeof(xLbxNewClientReq);
+ setupbuf = (char *)xalloc (len);
+ if (!setupbuf)
+ return BadAlloc;
+ memcpy (setupbuf, (char *)&stuff[1], len);
+
+ newClient = AllocLbxClientConnection (client, proxy);
+ if (!newClient)
+ return BadAlloc;
+ newClient->requestVector = LbxInitialVector;
+ lbxClient = LbxInitClient (proxy, newClient, id);
+ if (!lbxClient)
+ {
+ CloseDownClient (newClient);
+ return BadAlloc;
+ }
+
+ AppendFakeRequest (newClient, setupbuf, len);
+ xfree (setupbuf);
+ LbxSetForBlock(lbxClient);
+
+ DBG (DBG_CLIENT, (stderr, "lbxNewClient X %d\n", newClient->index));
+ return Success;
+}
+
+int
+ProcLbxEstablishConnection(ClientPtr client)
+{
+ char *reason = NULL;
+ char *auth_proto, *auth_string;
+ register xConnClientPrefix *prefix;
+ REQUEST(xReq);
+
+ prefix = (xConnClientPrefix *)((char *)stuff + sz_xReq);
+ auth_proto = (char *)prefix + sz_xConnClientPrefix;
+ auth_string = auth_proto + ((prefix->nbytesAuthProto + 3) & ~3);
+ if ((prefix->majorVersion != X_PROTOCOL) ||
+ (prefix->minorVersion != X_PROTOCOL_REVISION))
+ reason = "Protocol version mismatch";
+ else
+ reason = ClientAuthorized(client,
+ prefix->nbytesAuthProto,
+ auth_proto,
+ prefix->nbytesAuthString,
+ auth_string);
+
+ if (client->clientState == ClientStateCheckingSecurity ||
+ client->clientState == ClientStateAuthenticating)
+ return (client->noClientException = -1); /* XXX some day */
+ return(LbxSendConnSetup(client, reason));
+}
+
+int
+ProcLbxCloseClient (ClientPtr client)
+{
+ REQUEST(xLbxCloseClientReq);
+ LbxClientPtr lbxClient = LbxClient(client);
+
+ REQUEST_SIZE_MATCH(xLbxCloseClientReq);
+ if (!lbxClient || lbxClient->id != stuff->client)
+ return BadLbxClientCode;
+
+ /* this will cause the client to be closed down back in Dispatch() */
+ return(client->noClientException = CloseLbxClient);
+}
+
+int
+ProcLbxModifySequence (ClientPtr client)
+{
+ REQUEST(xLbxModifySequenceReq);
+
+ REQUEST_SIZE_MATCH(xLbxModifySequenceReq);
+ client->sequence += (stuff->adjust - 1); /* Dispatch() adds 1 */
+ return Success;
+}
+
+int
+ProcLbxAllowMotion (ClientPtr client)
+{
+ REQUEST(xLbxAllowMotionReq);
+
+ client->sequence--;
+ REQUEST_SIZE_MATCH(xLbxAllowMotionReq);
+ LbxAllowMotion(client, stuff->num);
+ return Success;
+}
+
+
+static int
+DecodeLbxDelta (ClientPtr client)
+{
+ REQUEST(xLbxDeltaReq);
+ LbxClientPtr lbxClient = LbxClient(client);
+ LbxProxyPtr proxy = lbxClient->proxy;
+ int len;
+ unsigned char *buf;
+
+ /* Note that LBXDecodeDelta decodes and adds current msg to the cache */
+ len = LBXDecodeDelta(&proxy->indeltas,
+ (xLbxDiffItem *)(((char *)stuff) + sz_xLbxDeltaReq),
+ stuff->diffs, stuff->cindex, &buf);
+ /*
+ * Some requests, such as FillPoly, result in the protocol input
+ * buffer being modified. So we need to copy the request
+ * into a temporary buffer where a write would be harmless.
+ * Maybe some day do this copying on a case by case basis,
+ * since not all requests are guilty of this.
+ */
+ memcpy(proxy->iDeltaBuf, buf, len);
+
+ client->requestBuffer = proxy->iDeltaBuf;
+ client->req_len = len >> 2;
+ return len;
+}
+
+int
+ProcLbxGetModifierMapping(ClientPtr client)
+{
+ /* REQUEST(xLbxGetModifierMappingReq); */
+
+ REQUEST_SIZE_MATCH(xLbxGetModifierMappingReq);
+ return LbxGetModifierMapping(client);
+}
+
+int
+ProcLbxGetKeyboardMapping(ClientPtr client)
+{
+ /* REQUEST(xLbxGetKeyboardMappingReq); */
+
+ REQUEST_SIZE_MATCH(xLbxGetKeyboardMappingReq);
+ return LbxGetKeyboardMapping(client);
+}
+
+int
+ProcLbxQueryFont(ClientPtr client)
+{
+ /* REQUEST(xLbxQueryFontReq); */
+
+ REQUEST_SIZE_MATCH(xLbxQueryFontReq);
+ return LbxQueryFont(client);
+}
+
+int
+ProcLbxChangeProperty(ClientPtr client)
+{
+ /* REQUEST(xLbxChangePropertyReq); */
+
+ REQUEST_SIZE_MATCH(xLbxChangePropertyReq);
+ return LbxChangeProperty(client);
+}
+
+int
+ProcLbxGetProperty(ClientPtr client)
+{
+ /* REQUEST(xLbxGetPropertyReq); */
+
+ REQUEST_SIZE_MATCH(xLbxGetPropertyReq);
+ return LbxGetProperty(client);
+}
+
+int
+ProcLbxTagData(ClientPtr client)
+{
+ REQUEST(xLbxTagDataReq);
+
+ client->sequence--; /* not a counted request */
+ REQUEST_AT_LEAST_SIZE(xLbxTagDataReq);
+
+ return LbxTagData(client, stuff->tag, stuff->real_length,
+ (pointer)&stuff[1]); /* better not give any errors */
+}
+
+int
+ProcLbxInvalidateTag(ClientPtr client)
+{
+ REQUEST(xLbxInvalidateTagReq);
+
+ client->sequence--;
+ REQUEST_SIZE_MATCH(xLbxInvalidateTagReq);
+ return LbxInvalidateTag(client, stuff->tag);
+}
+
+int
+ProcLbxPolyPoint(ClientPtr client)
+{
+ return LbxDecodePoly(client, X_PolyPoint, LbxDecodePoints);
+}
+
+int
+ProcLbxPolyLine(ClientPtr client)
+{
+ return LbxDecodePoly(client, X_PolyLine, LbxDecodePoints);
+}
+
+int
+ProcLbxPolySegment(ClientPtr client)
+{
+ return LbxDecodePoly(client, X_PolySegment, LbxDecodeSegment);
+}
+
+int
+ProcLbxPolyRectangle(ClientPtr client)
+{
+ return LbxDecodePoly(client, X_PolyRectangle, LbxDecodeRectangle);
+}
+
+int
+ProcLbxPolyArc(ClientPtr client)
+{
+ return LbxDecodePoly(client, X_PolyArc, LbxDecodeArc);
+}
+
+int
+ProcLbxFillPoly(ClientPtr client)
+{
+ return LbxDecodeFillPoly(client);
+}
+
+int
+ProcLbxPolyFillRectangle(ClientPtr client)
+{
+ return LbxDecodePoly(client, X_PolyFillRectangle, LbxDecodeRectangle);
+}
+
+int
+ProcLbxPolyFillArc(ClientPtr client)
+{
+ return LbxDecodePoly(client, X_PolyFillArc, LbxDecodeArc);
+}
+
+int
+ProcLbxCopyArea(ClientPtr client)
+{
+ return LbxDecodeCopyArea(client);
+}
+
+int
+ProcLbxCopyPlane(ClientPtr client)
+{
+ return LbxDecodeCopyPlane(client);
+}
+
+
+int
+ProcLbxPolyText(ClientPtr client)
+{
+ return LbxDecodePolyText(client);
+}
+
+int
+ProcLbxImageText(ClientPtr client)
+{
+ return LbxDecodeImageText(client);
+}
+
+int
+ProcLbxQueryExtension(ClientPtr client)
+{
+ REQUEST(xLbxQueryExtensionReq);
+ char *ename;
+
+ REQUEST_AT_LEAST_SIZE(xLbxQueryExtensionReq);
+ ename = (char *) &stuff[1];
+ return LbxQueryExtension(client, ename, stuff->nbytes);
+}
+
+int
+ProcLbxPutImage(ClientPtr client)
+{
+ return LbxDecodePutImage(client);
+}
+
+int
+ProcLbxGetImage(ClientPtr client)
+{
+ return LbxDecodeGetImage(client);
+}
+
+
+int
+ProcLbxSync(ClientPtr client)
+{
+ xLbxSyncReply reply;
+
+ client->sequence--; /* not a counted request */
+
+#ifdef COLOR_DEBUG
+ fprintf (stderr, "Got LBX sync, seq = 0x%x\n", client->sequence);
+#endif
+
+ reply.type = X_Reply;
+ reply.length = 0;
+ reply.sequenceNumber = client->sequence;
+ reply.pad0 = reply.pad1 = reply.pad2 = reply.pad3 = reply.pad4 =
+ reply.pad5 = reply.pad6 = 0;
+
+ if (client->swapped)
+ {
+ register char n;
+ swaps (&reply.sequenceNumber, n);
+ }
+
+ WriteToClient (client, sz_xLbxSyncReply, (char *)&reply);
+
+ return (client->noClientException);
+}
+
+
+int
+ProcLbxDispatch(ClientPtr client)
+{
+ REQUEST(xReq);
+ switch (stuff->data)
+ {
+ case X_LbxQueryVersion:
+ return ProcLbxQueryVersion(client);
+ case X_LbxStartProxy:
+ return ProcLbxStartProxy(client);
+ case X_LbxStopProxy:
+ return ProcLbxStopProxy(client);
+ case X_LbxNewClient:
+ return ProcLbxNewClient(client);
+ case X_LbxCloseClient:
+ return ProcLbxCloseClient(client);
+ case X_LbxModifySequence:
+ return ProcLbxModifySequence(client);
+ case X_LbxAllowMotion:
+ return ProcLbxAllowMotion(client);
+ case X_LbxIncrementPixel:
+ return ProcLbxIncrementPixel(client);
+ case X_LbxGrabCmap:
+ return ProcLbxGrabCmap(client);
+ case X_LbxReleaseCmap:
+ return ProcLbxReleaseCmap(client);
+ case X_LbxAllocColor:
+ return ProcLbxAllocColor(client);
+ case X_LbxGetModifierMapping:
+ return ProcLbxGetModifierMapping(client);
+ case X_LbxGetKeyboardMapping:
+ return ProcLbxGetKeyboardMapping(client);
+ case X_LbxInvalidateTag:
+ return ProcLbxInvalidateTag(client);
+ case X_LbxPolyPoint:
+ return ProcLbxPolyPoint (client);
+ case X_LbxPolyLine:
+ return ProcLbxPolyLine (client);
+ case X_LbxPolySegment:
+ return ProcLbxPolySegment (client);
+ case X_LbxPolyRectangle:
+ return ProcLbxPolyRectangle (client);
+ case X_LbxPolyArc:
+ return ProcLbxPolyArc (client);
+ case X_LbxFillPoly:
+ return ProcLbxFillPoly (client);
+ case X_LbxPolyFillRectangle:
+ return ProcLbxPolyFillRectangle (client);
+ case X_LbxPolyFillArc:
+ return ProcLbxPolyFillArc (client);
+ case X_LbxQueryFont:
+ return ProcLbxQueryFont (client);
+ case X_LbxChangeProperty:
+ return ProcLbxChangeProperty (client);
+ case X_LbxGetProperty:
+ return ProcLbxGetProperty (client);
+ case X_LbxTagData:
+ return ProcLbxTagData (client);
+ case X_LbxCopyArea:
+ return ProcLbxCopyArea (client);
+ case X_LbxCopyPlane:
+ return ProcLbxCopyPlane (client);
+ case X_LbxPolyText8:
+ case X_LbxPolyText16:
+ return ProcLbxPolyText (client);
+ case X_LbxImageText8:
+ case X_LbxImageText16:
+ return ProcLbxImageText (client);
+ case X_LbxQueryExtension:
+ return ProcLbxQueryExtension (client);
+ case X_LbxPutImage:
+ return ProcLbxPutImage (client);
+ case X_LbxGetImage:
+ return ProcLbxGetImage (client);
+ case X_LbxInternAtoms:
+ return ProcLbxInternAtoms(client);
+ case X_LbxGetWinAttrAndGeom:
+ return ProcLbxGetWinAttrAndGeom(client);
+ case X_LbxSync:
+ return ProcLbxSync(client);
+ case X_LbxBeginLargeRequest:
+ return ProcLbxBeginLargeRequest(client);
+ case X_LbxLargeRequestData:
+ return ProcLbxLargeRequestData(client);
+ case X_LbxEndLargeRequest:
+ return ProcLbxLargeRequestData(client);
+ default:
+ return BadRequest;
+ }
+}