Logo Search packages:      
Sourcecode: xorg-server version File versions  Download package

lbxmain.c

/* $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;
    }
}

Generated by  Doxygen 1.6.0   Back to index