/* $XConsortium: lbxmain.c /main/73 1996/12/30 18:01:14 rws $ */ /* * Copyright 1992 Network Computing Devices * Copyright 1996 X Consortium, Inc. * * 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.5 1997/01/18 06:57:51 dawes Exp $ */ #include #define NEED_REPLIES #define NEED_EVENTS #include "X.h" #include "Xproto.h" #include "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" #include "lbxdeltastr.h" #define _XLBX_SERVER_ #include "lbxstr.h" #include "lbxserve.h" #include "lbximage.h" #include "lbxsrvopts.h" #include "Xfuncproto.h" #include #ifdef X_NOT_STDC_ENV extern int errno; #endif #ifndef Lynx #include #else #include #endif #include #ifndef X_NOT_POSIX #include #endif #define CloseLbxClient 0xff #define MAXBYTESDIFF 8 extern void LbxAllowMotion(); extern int LbxDecodePoints(); extern int LbxDecodeSegment(); extern int LbxDecodeRectangle(); extern int LbxDecodeArc(); extern int GrabInProgress; int LbxWhoAmI = 1; /* * for lbx zlib library to know who we are * server = 1 * proxy = 0 */ int ProcLbxDispatch(); extern int SProcLbxDispatch(); static void LbxResetProc(); static int DecodeLbxDelta(); static void LbxFreeClient (); static void LbxShutdownProxy (); 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])(); #ifdef DEBUG int lbxDebug = 0; #endif void LbxExtensionInit() { 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 (extEntry) ExtensionEntry *extEntry; { LbxResetTags(); uid_seed = 0; } void LbxCloseClient (client) 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(client, proxy, buf) 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(proxy, reply, len, buf) LbxProxyPtr proxy; char *reply; int len; char *buf; { int diffs; int cindex; int n; xLbxDeltaReq *p = (xLbxDeltaReq *)buf; diffs = LBXDeltaMinDiffs(&proxy->outdeltas, reply, len, min(MAXBYTESDIFF, (len - sz_xLbxDeltaReq) >> 1), &cindex); if (diffs < 0) { LBXAddDeltaOut(&proxy->outdeltas, reply, len); return 0; } LBXEncodeDelta(&proxy->outdeltas, reply, diffs, cindex, &buf[sz_xLbxDeltaReq]); LBXAddDeltaOut(&proxy->outdeltas, 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(client, pbuf, pcount, cbuf, ccount) 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(pcbl, nulldata, calldata) 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 (dummy1, dummy2) 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 (lbxClient) LbxClientPtr lbxClient; { LbxProxyPtr proxy = lbxClient->proxy; return (lbxClient->ignored || (GrabInProgress && lbxClient->client->index != GrabInProgress && lbxClient != proxy->lbxClients[0])); } static void LbxSwitchRecv (proxy, lbxClient) 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 (client, closure) 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(lbxClient) LbxClientPtr lbxClient; { lbxClient->reqs_pending++; if (!lbxClient->input_blocked) { lbxClient->input_blocked = TRUE; QueueWorkProc(LbxWaitForUnblocked, lbxClient->client, NULL); } } /* ARGSUSED */ static int LbxWaitForUngrab (client, closure) 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(proxy) 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 (client) 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 (proxy, client, id) 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 (client) 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 (proxy) 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(pid) int pid; { LbxProxyPtr proxy; for (proxy = proxyList; proxy; proxy = proxy->next) { if (proxy->pid == pid) return proxy; } return NULL; } static void LbxShutdownProxy (proxy) 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(client) register 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() { 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(client) register 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, &stuff[1], reqlen - sz_xLbxStartProxyReq, &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(client) register 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(client) register 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(client) register ClientPtr client; { REQUEST(xLbxBeginLargeRequestReq); client->sequence--; REQUEST_SIZE_MATCH(xLbxBeginLargeRequestReq); if (!AllocateLargeReqBuffer(client, stuff->largeReqLength << 2)) return BadAlloc; return Success; } int ProcLbxLargeRequestData(client) register 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(client) register ClientPtr client; { REQUEST(xReq); client->sequence--; REQUEST_SIZE_MATCH(xReq); return BadAlloc; } int ProcLbxInternAtoms(client) register 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(client) register 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(client) register 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(client) register 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 (client) register 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 (client) register ClientPtr client; { REQUEST(xLbxModifySequenceReq); REQUEST_SIZE_MATCH(xLbxModifySequenceReq); client->sequence += (stuff->adjust - 1); /* Dispatch() adds 1 */ return Success; } int ProcLbxAllowMotion (client) register ClientPtr client; { REQUEST(xLbxAllowMotionReq); client->sequence--; REQUEST_SIZE_MATCH(xLbxAllowMotionReq); LbxAllowMotion(client, stuff->num); return Success; } static int DecodeLbxDelta(client) register ClientPtr client; { REQUEST(xLbxDeltaReq); LbxClientPtr lbxClient = LbxClient(client); LbxProxyPtr proxy = lbxClient->proxy; int len; char *buf; /* Note that LBXDecodeDelta decodes and adds current msg to the cache */ len = LBXDecodeDelta(&proxy->indeltas, ((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(client) ClientPtr client; { REQUEST(xLbxGetModifierMappingReq); REQUEST_SIZE_MATCH(xLbxGetModifierMappingReq); return LbxGetModifierMapping(client); } int ProcLbxGetKeyboardMapping(client) ClientPtr client; { REQUEST(xLbxGetKeyboardMappingReq); REQUEST_SIZE_MATCH(xLbxGetKeyboardMappingReq); return LbxGetKeyboardMapping(client); } int ProcLbxQueryFont(client) ClientPtr client; { REQUEST(xLbxQueryFontReq); REQUEST_SIZE_MATCH(xLbxQueryFontReq); return LbxQueryFont(client); } int ProcLbxChangeProperty(client) ClientPtr client; { REQUEST(xLbxChangePropertyReq); REQUEST_SIZE_MATCH(xLbxChangePropertyReq); return LbxChangeProperty(client); } int ProcLbxGetProperty(client) ClientPtr client; { REQUEST(xLbxGetPropertyReq); REQUEST_SIZE_MATCH(xLbxGetPropertyReq); return LbxGetProperty(client); } int ProcLbxTagData(client) 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(client) ClientPtr client; { REQUEST(xLbxInvalidateTagReq); client->sequence--; REQUEST_SIZE_MATCH(xLbxInvalidateTagReq); return LbxInvalidateTag(client, stuff->tag); } int ProcLbxPolyPoint(client) register ClientPtr client; { return LbxDecodePoly(client, X_PolyPoint, LbxDecodePoints); } int ProcLbxPolyLine(client) register ClientPtr client; { return LbxDecodePoly(client, X_PolyLine, LbxDecodePoints); } int ProcLbxPolySegment(client) register ClientPtr client; { return LbxDecodePoly(client, X_PolySegment, LbxDecodeSegment); } int ProcLbxPolyRectangle(client) register ClientPtr client; { return LbxDecodePoly(client, X_PolyRectangle, LbxDecodeRectangle); } int ProcLbxPolyArc(client) register ClientPtr client; { return LbxDecodePoly(client, X_PolyArc, LbxDecodeArc); } int ProcLbxFillPoly(client) register ClientPtr client; { return LbxDecodeFillPoly(client); } int ProcLbxPolyFillRectangle(client) register ClientPtr client; { return LbxDecodePoly(client, X_PolyFillRectangle, LbxDecodeRectangle); } int ProcLbxPolyFillArc(client) register ClientPtr client; { return LbxDecodePoly(client, X_PolyFillArc, LbxDecodeArc); } int ProcLbxCopyArea (client) register ClientPtr client; { return LbxDecodeCopyArea(client); } int ProcLbxCopyPlane (client) register ClientPtr client; { return LbxDecodeCopyPlane(client); } int ProcLbxPolyText (client) register ClientPtr client; { return LbxDecodePolyText(client); } int ProcLbxImageText (client) register ClientPtr client; { return LbxDecodeImageText(client); } int ProcLbxQueryExtension(client) ClientPtr client; { REQUEST(xLbxQueryExtensionReq); char *ename; REQUEST_AT_LEAST_SIZE(xLbxQueryExtensionReq); ename = (char *) &stuff[1]; return LbxQueryExtension(client, ename, stuff->nbytes); } int ProcLbxPutImage(client) register ClientPtr client; { return LbxDecodePutImage(client); } int ProcLbxGetImage(client) register ClientPtr client; { return LbxDecodeGetImage(client); } int ProcLbxSync(client) register 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 (client) register 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; } }