2155 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			2155 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			C
		
	
	
	
/*****************************************************************************
 | 
						||
Copyright 1987, 1988, 1989, 1990, 1991 by Digital Equipment Corp., Maynard, MA
 | 
						||
X11R6 Changes Copyright (c) 1994 by Robert Chesler of Absol-Puter, Hudson, NH.
 | 
						||
 | 
						||
Permission to use, copy, modify, and distribute this software and its 
 | 
						||
documentation for any purpose and without fee is hereby granted, 
 | 
						||
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 Digital not be
 | 
						||
used in advertising or publicity pertaining to distribution of the
 | 
						||
software without specific, written prior permission.  
 | 
						||
 | 
						||
DIGITAL AND ABSOL-PUTER DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
 | 
						||
SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
 | 
						||
FITNESS, IN NO EVENT SHALL DIGITAL OR ABSOL-PUTER 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.
 | 
						||
 | 
						||
*****************************************************************************/
 | 
						||
/*
 | 
						||
 *  ABSTRACT:
 | 
						||
 *
 | 
						||
 *      This module is the main module for extension initialization and setup.
 | 
						||
 *      It is called by the server and by clients using the extension.
 | 
						||
 *      This is shared code and is subject to change only by team approval.
 | 
						||
 *
 | 
						||
 *  CONTRIBUTORS:
 | 
						||
 *
 | 
						||
 *      Dick Annicchiarico
 | 
						||
 *      Robert Chesler
 | 
						||
 *      Gene Durso
 | 
						||
 *      Marc Evans
 | 
						||
 *      Alan Jamison
 | 
						||
 *      Mark Henry
 | 
						||
 *      Ken Miller
 | 
						||
 *
 | 
						||
 *  CHANGES:
 | 
						||
 *
 | 
						||
 *	Robert Chesler - grab-impreviousness patch to improve grab behavior
 | 
						||
 *	Robert Chesler - add client arg to swapping routines for X11R6 port
 | 
						||
 *
 | 
						||
 */
 | 
						||
 | 
						||
/*-----------------*
 | 
						||
 *  Include Files  *
 | 
						||
 *-----------------*/
 | 
						||
 | 
						||
#define NEED_REPLIES
 | 
						||
#define NEED_EVENTS
 | 
						||
#ifdef HAVE_DIX_CONFIG_H
 | 
						||
#include <dix-config.h>
 | 
						||
#endif
 | 
						||
 | 
						||
#include <stdio.h>
 | 
						||
#include <errno.h>
 | 
						||
#include <X11/Xos.h>
 | 
						||
#include <X11/X.h>
 | 
						||
#include <X11/Xproto.h>
 | 
						||
#include "input.h"              /* Server DevicePtr definitions */
 | 
						||
#include "misc.h"               /* Server swapping macros */
 | 
						||
#include "dixstruct.h"          /* Server ClientRec definitions */
 | 
						||
#include "resource.h"           /* Used with the MakeAtom call */
 | 
						||
#ifdef PC
 | 
						||
# include "scrintst.h"          /* Screen struct */
 | 
						||
# include "extnsist.h"
 | 
						||
#else
 | 
						||
# include "extnsionst.h"        /* Server ExtensionEntry definitions */
 | 
						||
# include "scrnintstr.h"        /* Screen struct */
 | 
						||
#endif
 | 
						||
#include "pixmapstr.h"          /* DrawableRec */
 | 
						||
#include "windowstr.h"          /* Drawable Lookup structures */
 | 
						||
#include "inputstr.h"
 | 
						||
#include <X11/extensions/xtrapdi.h>
 | 
						||
#include <X11/extensions/xtrapddmi.h>
 | 
						||
#include <X11/extensions/xtrapproto.h>
 | 
						||
#include "colormapst.h"
 | 
						||
#ifdef PANORAMIX
 | 
						||
#include "panoramiX.h"
 | 
						||
#include "panoramiXsrv.h"
 | 
						||
#include "cursor.h"
 | 
						||
#endif
 | 
						||
 | 
						||
 | 
						||
/*----------------------------*
 | 
						||
 *  Global Data Declarations  *
 | 
						||
 *----------------------------*/
 | 
						||
 | 
						||
DevicePtr XETrapKbdDev                       = NULL;
 | 
						||
DevicePtr XETrapPtrDev                       = NULL;
 | 
						||
int    XETrapErrorBase                       = 0L;
 | 
						||
xXTrapGetAvailReply XETrap_avail;            /* What's available to clients */
 | 
						||
 | 
						||
globalref int_function XETrapDispatchVector[10L]; /* Vector of XTrap Rtns */
 | 
						||
globalref int_function XETSwDispatchVector[10L];  /* Swapped XTrap Rtns */
 | 
						||
 | 
						||
globalref int_function XETrapProcVector[256L]; /* The "shadowed" ProcVector */
 | 
						||
    /* The "real" EventVector (XTrap creates it till events 
 | 
						||
     * truly become vectored
 | 
						||
     */
 | 
						||
#ifndef VECTORED_EVENTS
 | 
						||
globalref int_function EventProcVector[XETrapCoreEvents];
 | 
						||
#else
 | 
						||
extern WindowPtr GetCurrentRootWindow(DeviceIntPtr);
 | 
						||
globalref int_function EventProcVector[128L];
 | 
						||
#endif
 | 
						||
static int_function keybd_process_inp = NULL;  /* Used for VECTORED_EVENTS */
 | 
						||
    /* The "shadowed" Event Vector */
 | 
						||
globalref int_function XETrapEventProcVector[XETrapCoreEvents];
 | 
						||
 | 
						||
globalref void_function XETSwProcVector[256L];/* Vector of Req swapping rtns */
 | 
						||
 | 
						||
/* This macro returns a true/false indicator based on whether it changes the
 | 
						||
 * environment state bits local to the server extension. This is based on the
 | 
						||
 * idea that if a valid flag is set and the corresponding data bit is not in
 | 
						||
 * the same state as desired, then true is returned, otherwise false is
 | 
						||
 * returned.
 | 
						||
 */
 | 
						||
#define _CheckChangeBit(valid,data,local,bit) \
 | 
						||
    (BitIsFalse(valid,bit) ? 0L :                                \
 | 
						||
        (((BitIsTrue(data,bit) && BitIsTrue(local,bit)) ||       \
 | 
						||
         (BitIsFalse(data,bit) && BitIsFalse(local,bit))) ? 0L : \
 | 
						||
         (BitToggle(local,bit), 1L)))
 | 
						||
 | 
						||
/* This macro is designed to return the number of elements in an
 | 
						||
 * automatically allocated array.
 | 
						||
 */
 | 
						||
#ifndef ASIZE
 | 
						||
#define ASIZE(array)    (sizeof(array)/sizeof(array[0L]))
 | 
						||
#endif
 | 
						||
 | 
						||
/* This macro is designed to return the number of long words beyond
 | 
						||
 * XETrapMinRepSize contained in a data structure.
 | 
						||
 */
 | 
						||
#ifndef XEXTRA
 | 
						||
#define XEXTRA(s) \
 | 
						||
    ((sizeof(s)+(sizeof(CARD32)-1L)-XETrapMinRepSize)/sizeof(CARD32))
 | 
						||
#endif
 | 
						||
 | 
						||
/* Static Declarations known to XTrap Only
 | 
						||
 * All XTrap clients refer to these single copies!
 | 
						||
 */
 | 
						||
/* This carries all of the information XTrap uses for internal information */
 | 
						||
static XETrapEnv *XETenv[MAXCLIENTS]         = {NULL};
 | 
						||
#ifndef RESTYPE
 | 
						||
#define RESTYPE unsigned long
 | 
						||
#endif
 | 
						||
static RESTYPE   XETrapClass = 0L;      /* Resource class for this extension */
 | 
						||
static RESTYPE   XETrapType  = 0L;      /* Resource type for this extension */
 | 
						||
static Bool      gate_closed = False;   /* The global "gatekeeper" */
 | 
						||
static Bool      key_ignore  = False;   /* The global "keymaster" */
 | 
						||
static Bool      ignore_grabs = False;
 | 
						||
static CARD8     next_key = XEKeyIsClear; /* Echo, Clear, or Other */
 | 
						||
#ifdef VECTORED_EVENTS
 | 
						||
static INT16     current_screen = -1L;   /* Current screen for events */
 | 
						||
#endif
 | 
						||
static INT16     vectored_requests[256L] = {0L}; /* cnt of vectoring clients */
 | 
						||
static INT16     vectored_events[KeyPress+MotionNotify]  = {0L};
 | 
						||
typedef struct _client_list
 | 
						||
{
 | 
						||
    struct _client_list    *next;
 | 
						||
    ClientPtr              client;
 | 
						||
} ClientList;
 | 
						||
static ClientList io_clients;  /* Linked-list of clients currently doing I/O */
 | 
						||
static ClientList stats_clients;  /* Linked-list of clients collecting stats */
 | 
						||
static ClientList cmd_clients;   /* Linked-list of clients using command key */
 | 
						||
 | 
						||
/*----------------------------*
 | 
						||
 *  Forward Declarations
 | 
						||
 *----------------------------*/
 | 
						||
static void _SwapProc (int (**f1 )(void), int (**f2 )(void));
 | 
						||
static void sXETrapEvent (xETrapDataEvent *from , xETrapDataEvent *to );
 | 
						||
static int add_accelerator_node (ClientPtr client , ClientList *accel );
 | 
						||
static void remove_accelerator_node (ClientPtr client , ClientList *accel );
 | 
						||
static void update_protocol (xXTrapGetReq *reqptr , ClientPtr client );
 | 
						||
#ifdef COLOR_REPLIES
 | 
						||
static void GetSendColorRep (ClientPtr client , xResourceReq *req );
 | 
						||
static void GetSendNamedColorRep (ClientPtr client , xResourceReq *req );
 | 
						||
static void GetSendColorCellsRep (ClientPtr client , xResourceReq *req );
 | 
						||
static void GetSendColorPlanesRep (ClientPtr client , xResourceReq *req );
 | 
						||
#endif
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This routine is called by the server when a given client
 | 
						||
 *      goes away (as identified by the first argument). All
 | 
						||
 *      memory allocations, misc. values specific to a given
 | 
						||
 *      client would be reset here.
 | 
						||
 *
 | 
						||
 */
 | 
						||
int XETrapDestroyEnv(pointer value, XID id)
 | 
						||
{
 | 
						||
    xXTrapReq request;
 | 
						||
    XETrapEnv *penv = XETenv[(long)value];
 | 
						||
 | 
						||
    XETrapReset(&request,penv->client);
 | 
						||
    /* Free any memory malloc'd for a particular client here */
 | 
						||
    /* In case stop I/O wasn't received for this client */
 | 
						||
    if (penv->stats)
 | 
						||
    {   /* Remove from client accelerator list */
 | 
						||
        remove_accelerator_node(penv->client, &stats_clients);
 | 
						||
        Xfree(penv->stats);     /* Free the stats buckets */
 | 
						||
    }
 | 
						||
    if (cmd_clients.next == NULL)
 | 
						||
    { /* No more command key clients!  Let's reset the gate */
 | 
						||
        gate_closed = False;
 | 
						||
        key_ignore  = False;
 | 
						||
        next_key = XEKeyIsClear;
 | 
						||
    }
 | 
						||
 | 
						||
#ifdef VECTORED_EVENTS
 | 
						||
    current_screen = -1L;       /* Invalidate current screen */
 | 
						||
#endif
 | 
						||
 | 
						||
#ifdef VERBOSE
 | 
						||
    ErrorF("%s:  Client '%d' Disconnected\n", XTrapExtName, 
 | 
						||
        penv->client->index);
 | 
						||
#endif
 | 
						||
 | 
						||
    Xfree(penv);
 | 
						||
    XETenv[(long)value] = NULL;
 | 
						||
 | 
						||
    return 0;
 | 
						||
}                       
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This routine is called by the server when the last client
 | 
						||
 *      (the session manager in most cases) goes away. This is server
 | 
						||
 *      reset. When the server comes back up, this extension will not
 | 
						||
 *      be loaded unless this routine makes the proper arrangements.
 | 
						||
 *
 | 
						||
 *      The real concern here is to unload the extension
 | 
						||
 *      and possibly make arragements to be called upon
 | 
						||
 *      server restart.
 | 
						||
 *
 | 
						||
 */
 | 
						||
void XETrapCloseDown(ExtensionEntry *extEntry)
 | 
						||
{                                           
 | 
						||
    long i;
 | 
						||
 | 
						||
    for (i=0L; i<MAXCLIENTS; i++)
 | 
						||
    {
 | 
						||
        if (XETenv[i] != NULL)
 | 
						||
        {
 | 
						||
            XETrapDestroyEnv((pointer)i,0L);
 | 
						||
        }
 | 
						||
    }
 | 
						||
    ignore_grabs = False;
 | 
						||
    return;
 | 
						||
}                       
 | 
						||
 | 
						||
/*
 | 
						||
 *
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This routine has been created because of the initialization
 | 
						||
 *      order that X uses, such that extensions are initialized before
 | 
						||
 *      devices. This means that this extension must perform a second
 | 
						||
 *      level of initialization to obtain the device references at some
 | 
						||
 *      point after they have been initialized. It is assumed that when
 | 
						||
 *      a client establishes communication with the extension that the
 | 
						||
 *      devices havae been initialized, and therefore this function can
 | 
						||
 *      obtain the information it needs.
 | 
						||
 *
 | 
						||
 *      In obtaining the information, this function also places its own
 | 
						||
 *      functions in place of the *standard* functions. The original
 | 
						||
 *      functions are retained for vectoring purposes.
 | 
						||
 */
 | 
						||
 | 
						||
Bool XETrapRedirectDevices()
 | 
						||
{
 | 
						||
    Bool retval = True;
 | 
						||
 | 
						||
    /* Do we need to redirect the keyboard device? */
 | 
						||
    if (XETrapKbdDev == NULL)
 | 
						||
    {
 | 
						||
        if ((XETrapKbdDev = LookupKeyboardDevice()) == NULL)
 | 
						||
        {
 | 
						||
            retval = False;
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            EventProcVector[KeyPress] =
 | 
						||
                (int_function)XETrapKbdDev->realInputProc;
 | 
						||
            EventProcVector[KeyRelease] =
 | 
						||
                (int_function)XETrapKbdDev->realInputProc;
 | 
						||
        }
 | 
						||
#ifdef VECTORED_EVENTS
 | 
						||
        keybd_process_inp = EventProcVector[KeyPress];
 | 
						||
        EventProcVector[KeyPress] = EventProcVector[KeyRelease] = NULL;
 | 
						||
        XETrapEventProcVector[KeyPress]   = XETrapEventVector;
 | 
						||
        XETrapEventProcVector[KeyRelease] = XETrapEventVector;
 | 
						||
#else   /* !VECTORED_EVENTS */
 | 
						||
        XETrapEventProcVector[KeyPress]   = XETrapKeyboard;
 | 
						||
        XETrapEventProcVector[KeyRelease] = XETrapKeyboard;
 | 
						||
#endif /* !VECTORED_EVENTS */
 | 
						||
    }
 | 
						||
    /* Do we need to redirect the pointer device? */
 | 
						||
#ifndef VECTORED_EVENTS
 | 
						||
    if (XETrapPtrDev == NULL)
 | 
						||
    {
 | 
						||
        if ((XETrapPtrDev = LookupPointerDevice()) == 0L)
 | 
						||
        {
 | 
						||
            retval = False;
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            EventProcVector[ButtonPress] = 
 | 
						||
                (int_function)XETrapPtrDev->realInputProc;
 | 
						||
            EventProcVector[ButtonRelease] = 
 | 
						||
                (int_function)XETrapPtrDev->realInputProc;
 | 
						||
            EventProcVector[MotionNotify] = 
 | 
						||
                (int_function)XETrapPtrDev->realInputProc;
 | 
						||
        }
 | 
						||
        XETrapEventProcVector[ButtonPress]   = XETrapPointer;
 | 
						||
        XETrapEventProcVector[ButtonRelease] = XETrapPointer;
 | 
						||
        XETrapEventProcVector[MotionNotify]  = XETrapPointer;
 | 
						||
    }
 | 
						||
#endif /* !VECTORED_EVENTS */
 | 
						||
    return(retval);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This routine is the main entry point for the Xtrap extension. It is
 | 
						||
 *      called by the server to inititalize the Xtrap extension.  Once the
 | 
						||
 *      extension is initialized, life is controlled by the XtrapDispatch
 | 
						||
 *      routine by the requests it will handle.
 | 
						||
 *
 | 
						||
 *      Initializes all the XTrap data structures with the proper
 | 
						||
 *      addresses of defined routines that will help control the extension.
 | 
						||
 *      It is vital that the extension state be kept accurate so that only
 | 
						||
 *      one call to this routine be made.
 | 
						||
 *
 | 
						||
 */
 | 
						||
 | 
						||
void DEC_XTRAPInit()
 | 
						||
{
 | 
						||
    register ExtensionEntry *extEntry;
 | 
						||
    unsigned int i;
 | 
						||
    Atom a;
 | 
						||
 | 
						||
    /* Make the extension known to the server. Must be done every time
 | 
						||
     * DEC_XTRAPInit is called, else server will think it failed.
 | 
						||
     */
 | 
						||
    if ((extEntry = AddExtension(XTrapExtName,XETrapNumEvents,
 | 
						||
        XETrapNumErrors,XETrapDispatch,sXETrapDispatch,XETrapCloseDown
 | 
						||
        ,StandardMinorOpcode)) == NULL)
 | 
						||
    {                                        
 | 
						||
        ErrorF("%s:  AddExtension Failed!\n", XTrapExtName); 
 | 
						||
        return;
 | 
						||
    }
 | 
						||
#ifdef VERBOSE
 | 
						||
        ErrorF("%s:  AddExtension assigned Major Opcode '%d'\n",
 | 
						||
            XTrapExtName, extEntry->base);
 | 
						||
#endif
 | 
						||
    XETrap_avail.data.major_opcode = extEntry->base;
 | 
						||
    XETrapErrorBase                = extEntry->errorBase;
 | 
						||
    XETrap_avail.data.event_base   = extEntry->eventBase;
 | 
						||
 | 
						||
    /* Set up our swapped reply vector */
 | 
						||
    ReplySwapVector[XETrap_avail.data.major_opcode] = 
 | 
						||
	(void_function) sReplyXTrapDispatch;
 | 
						||
 | 
						||
    /* Set up our swapped event vector */
 | 
						||
    EventSwapVector[extEntry->eventBase + XETrapData] = 
 | 
						||
	(EventSwapPtr) sXETrapEvent;
 | 
						||
 | 
						||
    /* make an atom saying that the extension is present.  The 
 | 
						||
     * adding of the resource occurs during XETrapCreateEnv().
 | 
						||
     */
 | 
						||
    if ((a = MakeAtom(XTrapExtName,strlen(XTrapExtName),1L)) == None ||
 | 
						||
        (XETrapType  = CreateNewResourceType(XETrapDestroyEnv)) == 0L)
 | 
						||
    {
 | 
						||
        ErrorF("%s:  Setup can't create new resource type (%d,%d,%d)\n",
 | 
						||
          XTrapExtName, (int)a,(int)XETrapClass,(int)XETrapType);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    /* initialize the GetAvailable info reply here */
 | 
						||
    XETrap_avail.hdr.type        = X_Reply;
 | 
						||
    XETrap_avail.hdr.length      = XEXTRA(xXTrapGetAvailReply);
 | 
						||
    XETrap_avail.data.xtrap_release  = XETrapRelease;
 | 
						||
    XETrap_avail.data.xtrap_version  = XETrapVersion;
 | 
						||
    XETrap_avail.data.xtrap_revision = XETrapRevision;
 | 
						||
    XETrap_avail.data.pf_ident       = XETrapPlatform;
 | 
						||
    XETrap_avail.data.max_pkt_size   = 0xFFFF;    /* very large number */
 | 
						||
    for (i=0L; i<ASIZE(XETrap_avail.data.valid); i++)
 | 
						||
    {
 | 
						||
        XETrap_avail.data.valid[i] = 0L; /* Clear bits initially */
 | 
						||
    }
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapTimestamp);
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapCmd);
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapCmdKeyMod);
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapRequest);
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapEvent);
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapMaxPacket);
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapStatistics);
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapWinXY);
 | 
						||
    /* Not yet implemented */
 | 
						||
    BitFalse(XETrap_avail.data.valid,XETrapCursor);
 | 
						||
#ifndef _XINPUT
 | 
						||
    BitFalse(XETrap_avail.data.valid,XETrapXInput);
 | 
						||
#else
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapXInput);
 | 
						||
#endif
 | 
						||
#ifndef VECTORED_EVENTS
 | 
						||
    BitFalse(XETrap_avail.data.valid,XETrapVectorEvents);
 | 
						||
#else
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapVectorEvents);
 | 
						||
#endif  /* VECTORED_EVENTS */
 | 
						||
#ifndef COLOR_REPLIES
 | 
						||
    BitFalse(XETrap_avail.data.valid,XETrapColorReplies);
 | 
						||
#else
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapColorReplies);
 | 
						||
#endif  /* COLOR_REPLIES */
 | 
						||
    BitTrue(XETrap_avail.data.valid,XETrapGrabServer);
 | 
						||
    /* initialize multi-client accelerator lists */
 | 
						||
    io_clients.next = NULL;
 | 
						||
    stats_clients.next = NULL;
 | 
						||
    cmd_clients.next = NULL;
 | 
						||
    for (i=0L; i<256L; i++)
 | 
						||
    {
 | 
						||
        vectored_requests[i] = 0L;
 | 
						||
    }
 | 
						||
    for (i=KeyPress; i<=MotionNotify; i++)
 | 
						||
    {
 | 
						||
        vectored_events[i] = 0L;
 | 
						||
    }
 | 
						||
    gate_closed = False;
 | 
						||
    key_ignore  = False;
 | 
						||
    next_key = XEKeyIsClear;
 | 
						||
        
 | 
						||
    XETrapPlatformSetup();
 | 
						||
    /* Initialize any local memory we use */
 | 
						||
    for (i=0L; i<ASIZE(EventProcVector); i++)
 | 
						||
    {
 | 
						||
        EventProcVector[i] = NULL;
 | 
						||
#ifndef VECTORED_EVENTS
 | 
						||
        XETrapEventProcVector[i] = NULL;
 | 
						||
#else
 | 
						||
        XETrapEventProcVector[i] = XETrapEventVector;
 | 
						||
#endif
 | 
						||
    }
 | 
						||
    XETrapKbdDev = NULL;
 | 
						||
    XETrapPtrDev = NULL;
 | 
						||
    for (i=0L; i<ASIZE(XETrapProcVector); i++)
 | 
						||
    {
 | 
						||
        XETrapProcVector[i] = XETrapRequestVector;
 | 
						||
    }
 | 
						||
    for (i=128L; i<=255L; i++)
 | 
						||
    {   /* Extension "swapped" requests are not implemented */
 | 
						||
        XETSwProcVector[i] = NotImplemented;
 | 
						||
    }
 | 
						||
#ifdef VERBOSE
 | 
						||
    ErrorF("%s:  Vers. %d.%d-%d successfully loaded\n", XTrapExtName,
 | 
						||
        XETrap_avail.data.xtrap_release, 
 | 
						||
        XETrap_avail.data.xtrap_version,
 | 
						||
        XETrap_avail.data.xtrap_revision);
 | 
						||
#endif
 | 
						||
 | 
						||
    return;
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This procedure is called upon dispatch to allocate an
 | 
						||
 *      environment structure for a new XTrap client.  The XETenv[]
 | 
						||
 *      entry is allocated and initialized with default values.
 | 
						||
 *      XETrapDestroyEnv() is responsible for deallocating this memory
 | 
						||
 *      upon client termination.
 | 
						||
 *
 | 
						||
 *      Note: the status of this routine is returned to the caller of
 | 
						||
 *      the Dispatch routine which will in turn SendErrorToClient if
 | 
						||
 *      necessary.
 | 
						||
 *
 | 
						||
 */
 | 
						||
 | 
						||
int XETrapCreateEnv(ClientPtr client)
 | 
						||
{
 | 
						||
    XETrapEnv *penv = NULL;
 | 
						||
    int status = Success;
 | 
						||
 | 
						||
    if (client->index > MAXCLIENTS)
 | 
						||
    {
 | 
						||
        status = BadImplementation;
 | 
						||
    }
 | 
						||
    else if ((XETenv[client->index] = (XETrapEnv *)Xcalloc(sizeof(XETrapEnv)))
 | 
						||
        == NULL)
 | 
						||
    {
 | 
						||
        status = BadAlloc;
 | 
						||
    }
 | 
						||
    if (status == Success)
 | 
						||
    {
 | 
						||
        penv = XETenv[client->index];
 | 
						||
        penv->client = client;
 | 
						||
        penv->protocol = 31;    /* default to backwards compatibility */
 | 
						||
        /* prep for client's departure (for memory dealloc, cleanup) */
 | 
						||
        AddResource(FakeClientID(client->index),XETrapType,
 | 
						||
            (pointer)(long)(client->index));
 | 
						||
        if (XETrapRedirectDevices() == False)
 | 
						||
        {
 | 
						||
            status = XETrapErrorBase + BadDevices;
 | 
						||
        }
 | 
						||
        /* Initialize the current state */
 | 
						||
        if (status == Success)
 | 
						||
        {
 | 
						||
            status = XETrapReset(NULL, penv->client);
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
#ifdef VECTORED_EVENTS
 | 
						||
    current_screen = -1L;       /* Invalidate current screen */
 | 
						||
#endif
 | 
						||
 | 
						||
#ifdef VERBOSE
 | 
						||
    if (status == Success)
 | 
						||
    {
 | 
						||
        ErrorF("%s:  Client '%d' Connection Accepted\n", XTrapExtName, 
 | 
						||
            penv->client->index);
 | 
						||
    }
 | 
						||
#endif
 | 
						||
 | 
						||
    return(status);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This procedure is defined for the call to AddExtension()
 | 
						||
 *      in which it is expected to be a parameter of the call.
 | 
						||
 *
 | 
						||
 *      This routine will be called by the server dispatcher
 | 
						||
 *      when a client makes a request that is handled
 | 
						||
 *      by the extension and the byte ordering of the client is the
 | 
						||
 *      SAME as that of the extension.
 | 
						||
 *
 | 
						||
 *      Note: the status of the requests is returned to the caller of
 | 
						||
 *      the Dispatch routine which will in turn SendErrorToClient if
 | 
						||
 *      necessary.
 | 
						||
 */
 | 
						||
 | 
						||
int XETrapDispatch(ClientPtr client)
 | 
						||
{
 | 
						||
 | 
						||
    REQUEST(xXTrapReq);
 | 
						||
    register int status = Success;
 | 
						||
 | 
						||
    REQUEST_AT_LEAST_SIZE(xXTrapReq);
 | 
						||
 | 
						||
    /* Have we seen this client before? */
 | 
						||
    if (XETenv[client->index] == NULL)
 | 
						||
    {
 | 
						||
        status = XETrapCreateEnv(client);
 | 
						||
    }
 | 
						||
    /* Do we have a valid request? */
 | 
						||
    if (status == Success)
 | 
						||
    {
 | 
						||
        if (stuff->minor_opcode < ASIZE(XETrapDispatchVector))
 | 
						||
        {
 | 
						||
            /* Then vector to the pointed to function */
 | 
						||
            status = 
 | 
						||
                (*(XETrapDispatchVector[stuff->minor_opcode]))(stuff,client);
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            status = BadRequest;
 | 
						||
        }
 | 
						||
    }
 | 
						||
    return(status);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *                     
 | 
						||
 *        This procedure is defined for the call to AddExtension()
 | 
						||
 *        in which it is expected to be a parameter of the call.
 | 
						||
 *
 | 
						||
 *        This routine would ordinarily be called by the server
 | 
						||
 *        dispatcher when a client makes a request that is handled
 | 
						||
 *        by the extension and the byte ordering of the client is
 | 
						||
 *        DIFFERENT than that of the extension.
 | 
						||
 */
 | 
						||
 | 
						||
int sXETrapDispatch(ClientPtr client)
 | 
						||
{
 | 
						||
 | 
						||
    REQUEST(xXTrapReq);
 | 
						||
    register int status = Success;
 | 
						||
 | 
						||
    REQUEST_AT_LEAST_SIZE(xXTrapReq);
 | 
						||
 | 
						||
    /* Have we seen this client before? */
 | 
						||
    if (XETenv[client->index] == NULL)
 | 
						||
    {
 | 
						||
        status = XETrapCreateEnv(client);
 | 
						||
    }
 | 
						||
    /* Do we have a valid request? */
 | 
						||
    if (status == Success)
 | 
						||
    {
 | 
						||
        if (stuff->minor_opcode < ASIZE(XETSwDispatchVector))
 | 
						||
        {
 | 
						||
            /* Then vector to the pointed to function */
 | 
						||
            status = 
 | 
						||
                (*(XETSwDispatchVector[stuff->minor_opcode]))(stuff,client);
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            status = BadRequest;
 | 
						||
        }
 | 
						||
    }
 | 
						||
    return(status);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This routine will place the extension in a steady and known 
 | 
						||
 *      state.  Any current state will be reset.  This is called either
 | 
						||
 *      by a client request (dispatched) or when a new client environment
 | 
						||
 *      is created.
 | 
						||
 *
 | 
						||
 */
 | 
						||
int XETrapReset(xXTrapReq *request, ClientPtr client)
 | 
						||
{
 | 
						||
    static xXTrapConfigReq DummyReq;
 | 
						||
    register int i;
 | 
						||
    register int status = Success;
 | 
						||
    XETrapEnv *penv = XETenv[client->index];
 | 
						||
 | 
						||
    /* in case any i/o's pending */
 | 
						||
    (void)XETrapStopTrap((xXTrapReq *)NULL, client);
 | 
						||
    penv->cur.hdr.type        = X_Reply;
 | 
						||
    penv->cur.hdr.length      = XEXTRA(xXTrapGetCurReply);
 | 
						||
    /* Fill in a dummy config request to clear all elements */
 | 
						||
    for (i=0L; i<ASIZE(DummyReq.config_flags_valid); i++)
 | 
						||
    {
 | 
						||
        DummyReq.config_flags_valid[i]  = 0xFFL;  /* set all the valid flags */
 | 
						||
        DummyReq.config_flags_data[i]   = 0L;     /* clear all data flags */
 | 
						||
    }
 | 
						||
    /* Don't reset grab server arbitrarily, it must be explicitly 
 | 
						||
     * de-configured.
 | 
						||
     */
 | 
						||
    BitSet(DummyReq.config_flags_data, XETrapGrabServer, ignore_grabs);
 | 
						||
    for (i=0L; i< ASIZE(DummyReq.config_flags_req); i++)
 | 
						||
    {
 | 
						||
       DummyReq.config_flags_req[i] = 0xFF; /* Clear all protocol requests */
 | 
						||
    }
 | 
						||
    for (i=0L; i< ASIZE(DummyReq.config_flags_event); i++)
 | 
						||
    {
 | 
						||
        DummyReq.config_flags_event[i] = 0xFF;  /* Clear all protocol events */
 | 
						||
    }
 | 
						||
    /* Call config routine to clear all configurable fields */
 | 
						||
    status = XETrapConfig(&DummyReq, client);
 | 
						||
    /* reset the environment */
 | 
						||
    for (i=0L; i<ASIZE(penv->cur.data_state_flags); i++)
 | 
						||
    {
 | 
						||
        penv->cur.data_state_flags[i] = 0L; /* Clear all env flags */
 | 
						||
    }
 | 
						||
    penv->cur.data_config_max_pkt_size  = XETrap_avail.data.max_pkt_size;
 | 
						||
   
 | 
						||
    return(status);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function sends a reply back to the requesting client indicating
 | 
						||
 *      the available states of the extension can be configured for.
 | 
						||
 */
 | 
						||
int XETrapGetAvailable(xXTrapGetReq *request, ClientPtr client)
 | 
						||
{
 | 
						||
    XETrapEnv *penv = XETenv[client->index];
 | 
						||
    update_protocol(request, client);
 | 
						||
    /* Initialize the reply as needed */
 | 
						||
    XETrap_avail.data.xtrap_protocol = penv->protocol;
 | 
						||
    XETrap_avail.hdr.detail = XETrap_GetAvailable;
 | 
						||
    XETrap_avail.hdr.sequenceNumber = client->sequence;
 | 
						||
    WriteReplyToClient(client, sizeof(xXTrapGetAvailReply), &XETrap_avail);
 | 
						||
    return(Success);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function sends a reply back to the requesting client indicating
 | 
						||
 *      the current state of the extension.
 | 
						||
 */
 | 
						||
int XETrapGetCurrent(xXTrapReq *request, ClientPtr client)
 | 
						||
{
 | 
						||
    XETrapEnv *penv = XETenv[client->index];
 | 
						||
    int rep_size = (penv->protocol == 31 ? 284 : sz_xXTrapGetCurReply);
 | 
						||
    penv->cur.hdr.length      = (rep_size - 32L) / SIZEOF(CARD32);
 | 
						||
 | 
						||
    /* Initialize the reply as needed */
 | 
						||
    penv->cur.hdr.detail = XETrap_GetCurrent;
 | 
						||
    penv->cur.hdr.sequenceNumber  = client->sequence;
 | 
						||
    WriteReplyToClient(client, rep_size, &(penv->cur));
 | 
						||
 | 
						||
    return(Success);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function sends a reply back to the requesting client dumping
 | 
						||
 *      statistics (counts) of requests and events.  If stat's isn't
 | 
						||
 *      configured, return failure.
 | 
						||
 */
 | 
						||
int XETrapGetStatistics(xXTrapReq *request, ClientPtr client)
 | 
						||
{
 | 
						||
    int status = Success;
 | 
						||
    XETrapEnv *penv = XETenv[client->index];
 | 
						||
 | 
						||
    if ((BitIsTrue(penv->cur.data_config_flags_data, XETrapStatistics)) &&
 | 
						||
        (penv->stats))
 | 
						||
    {
 | 
						||
        /* Initialize the reply as needed */
 | 
						||
        int rep_size = sizeof(xXTrapGetStatsReply);
 | 
						||
        penv->stats->detail = XETrap_GetStatistics;
 | 
						||
        penv->stats->sequenceNumber = client->sequence;
 | 
						||
        if (penv->protocol == 31)
 | 
						||
        {
 | 
						||
            xXTrapGetStatsReply  rep_stats;
 | 
						||
            rep_stats = *penv->stats;
 | 
						||
#ifndef VECTORED_EVENTS
 | 
						||
            rep_size         = 1060;
 | 
						||
#else
 | 
						||
            rep_size         = 1544;
 | 
						||
#endif
 | 
						||
            rep_stats.length = (rep_size - 32L) / SIZEOF(CARD32);
 | 
						||
            /* 
 | 
						||
             * Now we need to shift the data *into* the header area 
 | 
						||
             * for bug compatibility.
 | 
						||
             */
 | 
						||
            memcpy(&(rep_stats.pad0),&(penv->stats->data), 
 | 
						||
                sizeof(XETrapGetStatsRep));
 | 
						||
            WriteReplyToClient(client, rep_size, &rep_stats);
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            WriteReplyToClient(client, rep_size, penv->stats);
 | 
						||
        }
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        status = XETrapErrorBase + BadStatistics;
 | 
						||
    }
 | 
						||
    return(status);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function is dispatched when a client requests the extension to
 | 
						||
 *      be configured in some manner.
 | 
						||
 */
 | 
						||
int XETrapConfig(xXTrapConfigReq *request, ClientPtr client)
 | 
						||
{
 | 
						||
    UByteP vflags       = request->config_flags_valid;
 | 
						||
    UByteP dflags       = request->config_flags_data;
 | 
						||
    UByteP req_flags    = request->config_flags_req;
 | 
						||
    UByteP event_flags  = request->config_flags_event;
 | 
						||
    XETrapEnv *penv     = XETenv[client->index];
 | 
						||
    UByteP bit_flags    = penv->cur.data_config_flags_data;
 | 
						||
    int status          = Success;
 | 
						||
    CARD32 i            = 0L;
 | 
						||
 | 
						||
    /* Check events and swap if desired */
 | 
						||
    if (BitIsTrue(vflags,XETrapEvent))
 | 
						||
    {   /* Loop through all of the events */
 | 
						||
        for (i=0L; i<ASIZE(EventProcVector); i++)
 | 
						||
        {
 | 
						||
            if (BitIsTrue(event_flags,i) &&    /* Do we care about this one? */
 | 
						||
                (BitValue(dflags,XETrapEvent) ^           /* Exclusive Or */
 | 
						||
                (BitValue(penv->cur.data_config_flags_event,i))))
 | 
						||
            {   /* At this point we *know* there's a change.  The
 | 
						||
                 * only question remaining is are there any more
 | 
						||
                 * clients interested in this specific event.  If
 | 
						||
                 * so, *don't* swap this process!
 | 
						||
                 */
 | 
						||
                if (BitIsTrue(dflags,XETrapEvent))
 | 
						||
                {   /* Client wants the XTrap rtn */
 | 
						||
                    if (++(vectored_events[i]) <= 1L)
 | 
						||
                    {   /* first client, so do it */
 | 
						||
                        _SwapProc(&(XETrapEventProcVector[i]), 
 | 
						||
                            &(EventProcVector[i]));
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                else
 | 
						||
                {   /* Client wants the *real* rtn */
 | 
						||
                    if (--(vectored_events[i]) <= 0L)
 | 
						||
                    {   /* No more clients using, so do it */
 | 
						||
                        _SwapProc(&(XETrapEventProcVector[i]), 
 | 
						||
                            &(EventProcVector[i]));
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                switch(i)
 | 
						||
                {
 | 
						||
                    case KeyPress:  /* needed for command key processing */
 | 
						||
                    case KeyRelease:
 | 
						||
                        XETrapKbdDev->processInputProc = 
 | 
						||
                            (void_function)(EventProcVector[i] ? 
 | 
						||
                            (void_function)EventProcVector[i] : 
 | 
						||
                            (void_function)keybd_process_inp);
 | 
						||
                        XETrapKbdDev->realInputProc = 
 | 
						||
                            (void_function)(EventProcVector[i] ?
 | 
						||
                            (void_function)EventProcVector[i] : 
 | 
						||
                            (void_function)keybd_process_inp);
 | 
						||
                        break;
 | 
						||
#ifndef VECTORED_EVENTS
 | 
						||
                    case ButtonPress: /* hack until events become vectored */
 | 
						||
                    case ButtonRelease:
 | 
						||
                    case MotionNotify:
 | 
						||
                        XETrapPtrDev->processInputProc = 
 | 
						||
                            (void_function)EventProcVector[i];
 | 
						||
                        XETrapPtrDev->realInputProc = 
 | 
						||
                            (void_function)EventProcVector[i];
 | 
						||
                        break;
 | 
						||
                    default:
 | 
						||
                        status = BadImplementation;
 | 
						||
                        break;
 | 
						||
#endif /* !VECTORED_EVENTS */
 | 
						||
                }
 | 
						||
                BitToggle(penv->cur.data_config_flags_event,i);
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }
 | 
						||
    if ((status == Success) && 
 | 
						||
        (_CheckChangeBit(vflags,dflags,bit_flags,XETrapCmd)))
 | 
						||
    {
 | 
						||
        if (BitIsTrue(dflags, XETrapCmd))
 | 
						||
        {   /* Add accelerator entry to cmd_clients list iff necessary */
 | 
						||
            penv->cur.data_config_cmd_key = request->config_cmd_key;
 | 
						||
            status = add_accelerator_node(penv->client, &cmd_clients);
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            penv->cur.data_config_cmd_key = 0L; /* default no KeyCode */
 | 
						||
            remove_accelerator_node(penv->client, &cmd_clients);
 | 
						||
        }
 | 
						||
    }
 | 
						||
    if ((status == Success) &&
 | 
						||
        (_CheckChangeBit(vflags,dflags,bit_flags,XETrapMaxPacket)))
 | 
						||
    {
 | 
						||
        if (BitIsTrue(dflags,XETrapMaxPacket))
 | 
						||
        {   /* Set size to what's passed in */
 | 
						||
            if (request->config_max_pkt_size < XETrapMinPktSize)
 | 
						||
            {   /* Tell them the value is too small */
 | 
						||
                status = BadValue;
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                penv->cur.data_config_max_pkt_size = 
 | 
						||
                    request->config_max_pkt_size;
 | 
						||
            }
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {   /* Set it to the default (a *very* big number) */
 | 
						||
            penv->cur.data_config_max_pkt_size = 0xFFFF;
 | 
						||
        }
 | 
						||
    }
 | 
						||
    /* If the valid flag is set for requests, then each of the 
 | 
						||
     * requests is swapped if it's different from current state.
 | 
						||
     */
 | 
						||
    if (BitIsTrue(vflags,XETrapRequest) && status == Success)
 | 
						||
    {   /* Loop through all of the core requests */
 | 
						||
        for (i=0L; i<ASIZE(XETrapProcVector); i++)
 | 
						||
        {
 | 
						||
            if (BitIsTrue(req_flags,i) &&     /* Do we care about this one? */
 | 
						||
                (BitValue(dflags,XETrapRequest) ^          /* Exclusive Or */
 | 
						||
                (BitValue(penv->cur.data_config_flags_req,i))))
 | 
						||
            {   /* At this point we *know* there's a change.  The
 | 
						||
                 * only question remaining is are there any more
 | 
						||
                 * clients interested in this specific request.  If
 | 
						||
                 * so, *don't* swap this process!
 | 
						||
                 */
 | 
						||
                if (BitIsTrue(dflags,XETrapRequest))
 | 
						||
                {   /* Client wants the XTrap rtn */
 | 
						||
                    if (++(vectored_requests[i]) <= 1L)
 | 
						||
                    {   /* first client, so do it */
 | 
						||
                        _SwapProc(&(XETrapProcVector[i]), (int_function *)&(ProcVector[i]));
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                else
 | 
						||
                {   /* Client wants the *real* rtn */
 | 
						||
                    if (--(vectored_requests[i]) <= 0L)
 | 
						||
                    {   /* No more clients using, so do it */
 | 
						||
                        _SwapProc(&(XETrapProcVector[i]), (int_function *)&(ProcVector[i]));
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                if (status == Success)
 | 
						||
                {
 | 
						||
                    BitToggle(penv->cur.data_config_flags_req,i);
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }
 | 
						||
    /* Check & Set the boolean flags */
 | 
						||
    if (status == Success)
 | 
						||
    {
 | 
						||
        _CheckChangeBit(vflags,dflags,bit_flags,XETrapCmdKeyMod);
 | 
						||
        _CheckChangeBit(vflags,dflags,bit_flags,XETrapTimestamp);
 | 
						||
        _CheckChangeBit(vflags,dflags,bit_flags,XETrapWinXY);
 | 
						||
/*        _CheckChangeBit(vflags,dflags,bit_flags,XETrapCursor); */
 | 
						||
#ifdef COLOR_REPLIES
 | 
						||
        _CheckChangeBit(vflags,dflags,bit_flags,XETrapColorReplies);
 | 
						||
#endif /* COLOR_REPLIES */
 | 
						||
        if (_CheckChangeBit(vflags,dflags,bit_flags,XETrapGrabServer))
 | 
						||
        {   /* Let any client uncoditionally set/clear Grabs */
 | 
						||
            ignore_grabs = BitValue(dflags, XETrapGrabServer);
 | 
						||
        }
 | 
						||
    }
 | 
						||
    /* The statistics vflag/dflag mechanism is a little different
 | 
						||
     * from most.  The dflag is initially set to 0 to indicate no
 | 
						||
     * statistics.  When a config request comes in to request
 | 
						||
     * statistics, memory's allocated and the dflag is set.
 | 
						||
     * Thereafter, whenever a client wants to clear the counters, he
 | 
						||
     * simply sets the vflag and clears the dflag.  Multiple requests
 | 
						||
     * for statistics configuration are ignored, and the stats memory is
 | 
						||
     * free'd only when the client disconnects.
 | 
						||
     */
 | 
						||
    if (status == Success)
 | 
						||
    {
 | 
						||
        if (_CheckChangeBit(vflags,dflags,bit_flags,XETrapStatistics))
 | 
						||
        {
 | 
						||
            if (BitIsTrue(dflags,XETrapStatistics))
 | 
						||
            {   /* Do we need to allocate memory? */
 | 
						||
                if (penv->stats == NULL && (penv->stats =
 | 
						||
                    (xXTrapGetStatsReply *)Xcalloc(sizeof(xXTrapGetStatsReply)))
 | 
						||
                    != NULL)
 | 
						||
                {   /* Set up the reply header  */
 | 
						||
                    penv->stats->type  = X_Reply;
 | 
						||
                    penv->stats->length = XEXTRA(xXTrapGetStatsReply);
 | 
						||
                    /* add accelerator node for stats clients list */
 | 
						||
                    status = add_accelerator_node(penv->client, &stats_clients);
 | 
						||
                }
 | 
						||
                else if (penv->stats == NULL)
 | 
						||
                {   /* No Memory! */
 | 
						||
                    status = BadAlloc;
 | 
						||
                }
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {   /* Zero out counters */
 | 
						||
                (void)memset(penv->stats->data.requests, 0L, 
 | 
						||
                    sizeof(penv->stats->data.requests));
 | 
						||
                (void)memset(penv->stats->data.events, 0L,
 | 
						||
                    sizeof(penv->stats->data.events));
 | 
						||
                /* Re-cock the Stat's flag so that it'll
 | 
						||
                 * sense a change for next zero'ing out
 | 
						||
                 * of the counters.
 | 
						||
                 */
 | 
						||
                BitTrue(penv->cur.data_config_flags_data, XETrapStatistics);
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }    
 | 
						||
    return(status);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function sets the XETrapTrapActive bit to indicate that Trapping
 | 
						||
 *      of requests and/or core events to the client may take place.
 | 
						||
 *
 | 
						||
 */
 | 
						||
int XETrapStartTrap(xXTrapReq *request, ClientPtr client)
 | 
						||
{
 | 
						||
    XETrapEnv *penv = XETenv[client->index];
 | 
						||
    int status = add_accelerator_node(penv->client, &io_clients);
 | 
						||
    if (status == Success)
 | 
						||
    {
 | 
						||
        BitTrue(penv->cur.data_state_flags, XETrapTrapActive);
 | 
						||
    }
 | 
						||
    return(status);
 | 
						||
}
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function clears the XETrapTrapActive bit to indicate that Trapping
 | 
						||
 *      of requests and/or core events to the client may *not* take place.
 | 
						||
 *
 | 
						||
 */
 | 
						||
int XETrapStopTrap(xXTrapReq *request, ClientPtr client)
 | 
						||
{
 | 
						||
    XETrapEnv *penv = XETenv[client->index];
 | 
						||
 | 
						||
    remove_accelerator_node(penv->client, &io_clients);
 | 
						||
    BitFalse(penv->cur.data_state_flags, XETrapTrapActive);
 | 
						||
    return(Success);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function sends a reply back to the requesting client indicating
 | 
						||
 *      the specific XTrap version of this extension.
 | 
						||
 */
 | 
						||
int XETrapGetVersion(xXTrapGetReq *request, ClientPtr client)
 | 
						||
{
 | 
						||
    xXTrapGetVersReply ver_rep;
 | 
						||
    XETrapEnv *penv = XETenv[client->index];
 | 
						||
 | 
						||
    update_protocol(request,client);    /* to agree on protocol version */
 | 
						||
    /* Initialize the reply as needed */
 | 
						||
    ver_rep.hdr.type = X_Reply;
 | 
						||
    ver_rep.hdr.detail = XETrap_GetVersion;
 | 
						||
    ver_rep.hdr.sequenceNumber = client->sequence;
 | 
						||
    ver_rep.hdr.length = XEXTRA(xXTrapGetVersReply);
 | 
						||
    ver_rep.data.xtrap_release = XETrap_avail.data.xtrap_release;
 | 
						||
    ver_rep.data.xtrap_version = XETrap_avail.data.xtrap_version;
 | 
						||
    ver_rep.data.xtrap_revision = XETrap_avail.data.xtrap_revision;
 | 
						||
    ver_rep.data.xtrap_protocol = penv->protocol; /* return agreed protocol */
 | 
						||
    WriteReplyToClient(client, sizeof(xXTrapGetVersReply), &ver_rep);
 | 
						||
    return(Success);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function sends a reply back to the requesting client indicating
 | 
						||
 *      the specific XTrap version of this extension.
 | 
						||
 */
 | 
						||
int XETrapGetLastInpTime(xXTrapReq *request, ClientPtr client)
 | 
						||
{
 | 
						||
    xXTrapGetLITimReply tim_rep;
 | 
						||
    XETrapEnv *penv = XETenv[client->index];
 | 
						||
 | 
						||
    /* Initialize the reply as needed */
 | 
						||
    tim_rep.hdr.type = X_Reply;
 | 
						||
    tim_rep.hdr.detail = XETrap_GetLastInpTime;
 | 
						||
    tim_rep.hdr.sequenceNumber = client->sequence;
 | 
						||
    tim_rep.hdr.length = XEXTRA(xXTrapGetLITimReply);
 | 
						||
    tim_rep.data_last_time = penv->last_input_time;
 | 
						||
    WriteReplyToClient(client, sizeof(xXTrapGetLITimReply), &tim_rep);
 | 
						||
    return(Success);
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *  This routine is swapped in for the server's output request vectors.   
 | 
						||
 *  After writing the request to one (or more) XTrap client(s), this
 | 
						||
 *  routine ALWAYS returns by calling the REAL output request vector rtn.
 | 
						||
 * 
 | 
						||
 *  Note: Swapped Requests are handled automatically since the unswapped
 | 
						||
 *        vectored routine is called after the request has been swapped.
 | 
						||
 *        IOW, all requests are directed through ProcVector eventually and are
 | 
						||
 *        "unswapped" at that point.  It is necessary to swap the data
 | 
						||
 *        back if writing to a swapped client, however, and this is done
 | 
						||
 *        by calling the appropriate XETSwProcVector[] routine.
 | 
						||
 */
 | 
						||
int XETrapRequestVector(ClientPtr client)
 | 
						||
{
 | 
						||
    int status = True;
 | 
						||
    XETrapDatum *pdata, *spdata = NULL;
 | 
						||
    REQUEST(xResourceReq);
 | 
						||
    WindowPtr window_ptr;
 | 
						||
    XETrapEnv *penv;
 | 
						||
    BYTE *tptr;
 | 
						||
    ClientList *ioc = &io_clients;
 | 
						||
    ClientList *stc = &stats_clients;
 | 
						||
    INT32 asize = sizeof(pdata->hdr) + stuff->length * sizeof(CARD32);
 | 
						||
    INT32 size = MAX(asize,XETrapMinPktSize); /* Must be at least */
 | 
						||
    INT32 csize;    /* size of request to send to the XTrap client */
 | 
						||
 | 
						||
    /* Get memory for the data to be sent */
 | 
						||
    if ((pdata = (XETrapDatum *)Xcalloc(size)) == NULL)
 | 
						||
    {   /* Can't do anything accept set a flag since we don't
 | 
						||
         * know who to send the error to yet.
 | 
						||
         */
 | 
						||
        status = False;
 | 
						||
    }
 | 
						||
 | 
						||
    while (ioc->next != NULL)
 | 
						||
    {
 | 
						||
        ioc = ioc->next;
 | 
						||
        penv = XETenv[ioc->client->index];
 | 
						||
        if (status == False)
 | 
						||
        {   /* We didn't get the memory! Complain */
 | 
						||
            SendErrorToClient(penv->client,XETrap_avail.data.major_opcode,
 | 
						||
                stuff->reqType, 0L, BadAlloc);
 | 
						||
            break;
 | 
						||
        }
 | 
						||
        if (BitIsTrue(penv->cur.data_config_flags_req,stuff->reqType))
 | 
						||
        {   /* This particular client is interested in *this* request */
 | 
						||
            pdata->hdr.client = client->index;  /* stuff client index in hdr */
 | 
						||
            if (BitIsTrue(penv->cur.data_config_flags_data,XETrapWinXY))
 | 
						||
            {
 | 
						||
		if (Success != dixLookupDrawable(&window_ptr, stuff->id,
 | 
						||
						 client, 0, DixUnknownAccess))
 | 
						||
                {   /* Failed...invalidate the X and Y coordinate data. */
 | 
						||
                    pdata->hdr.win_x = -1L;
 | 
						||
                    pdata->hdr.win_y = -1L;
 | 
						||
                }
 | 
						||
                else
 | 
						||
                {
 | 
						||
                    pdata->hdr.screen = window_ptr->drawable.pScreen->myNum;
 | 
						||
                    pdata->hdr.win_x = window_ptr->drawable.x;
 | 
						||
                    pdata->hdr.win_y = window_ptr->drawable.y;
 | 
						||
                }
 | 
						||
            }
 | 
						||
            if (BitIsTrue(penv->cur.data_config_flags_data,XETrapTimestamp))
 | 
						||
            {
 | 
						||
                pdata->hdr.timestamp = GetTimeInMillis();
 | 
						||
            }
 | 
						||
            /* Copy the information to a location we can write it from */
 | 
						||
            (void) memcpy(&(pdata->u.req),stuff,stuff->length*sizeof(CARD32));
 | 
						||
            pdata->hdr.count = MIN(penv->cur.data_config_max_pkt_size,asize);
 | 
						||
            XETrapSetHeaderRequest(&(pdata->hdr));
 | 
						||
    
 | 
						||
            /* Perform any needed byte/word swapping. NOTE: This is not
 | 
						||
             * the "normal" technique that should be used to perform the
 | 
						||
             * swapping. The reason that we do it here is to be sure to
 | 
						||
             * do it only once in a controlled manner, which we can not
 | 
						||
             * guarentee in the case of the Xlib transport. Notice that
 | 
						||
             * we don't swap the XTRAP EVENT information.  This is done
 | 
						||
             * in the XETrapWriteXLib() routine.
 | 
						||
             */
 | 
						||
 | 
						||
            if (penv->client->swapped)
 | 
						||
            {   /* need to deal with swapped clients */
 | 
						||
                if (spdata == NULL)
 | 
						||
                {   /* Get memory for the swapped data to be sent */
 | 
						||
                    if ((spdata = (XETrapDatum *)Xcalloc(size)) == NULL)
 | 
						||
                    {
 | 
						||
                        SendErrorToClient(penv->client,
 | 
						||
                            XETrap_avail.data.major_opcode,
 | 
						||
                            stuff->reqType, 0L, BadAlloc);
 | 
						||
                        break;
 | 
						||
                    }
 | 
						||
 | 
						||
                    memcpy(spdata,pdata,size);  /* fill in the info */
 | 
						||
                    /* Now call the request-specific rtn to swap the request */
 | 
						||
                    if (stuff->reqType < 128)
 | 
						||
                    {   /* a core request, good */
 | 
						||
                        (*XETSwProcVector[stuff->reqType])(&(spdata->u.req),
 | 
						||
			    penv->client);	/* RTC X11R6 */
 | 
						||
                    }
 | 
						||
                    else if (penv->cur.data_config_max_pkt_size == 
 | 
						||
                        XETrapMinPktSize)
 | 
						||
                    {   /* Minimum size, so swap it as an ResourceReq */
 | 
						||
                        XETSwResourceReq(&(spdata->u.req));
 | 
						||
                    }
 | 
						||
                    else
 | 
						||
                    {   /* trying to swap an extension request! */
 | 
						||
                        SendErrorToClient(penv->client,
 | 
						||
                            XETrap_avail.data.major_opcode,
 | 
						||
                            stuff->reqType, 0L, XETrapErrorBase + BadSwapReq);
 | 
						||
                    }
 | 
						||
                }
 | 
						||
                /* need to stow in the latest header (count) */
 | 
						||
                memcpy(spdata,pdata,SIZEOF(XETrapHeader));
 | 
						||
                sXETrapHeader(&(spdata->hdr));  /* swap the XTrap Header */
 | 
						||
            }
 | 
						||
            /* Write as many bytes of information as the client wants */
 | 
						||
            tptr = (BYTE *)(penv->client->swapped ? spdata : pdata);
 | 
						||
            csize = MAX(pdata->hdr.count, XETrapMinPktSize);
 | 
						||
            if (XETrapWriteXLib(penv, tptr, csize) != csize)
 | 
						||
            {
 | 
						||
                SendErrorToClient(penv->client,XETrap_avail.data.major_opcode,
 | 
						||
                    stuff->reqType, 0L, XETrapErrorBase + BadIO);
 | 
						||
            }
 | 
						||
#ifdef COLOR_REPLIES
 | 
						||
            /* Process Color Replies, if desired, and applicable */
 | 
						||
            if (BitIsTrue(penv->cur.data_config_flags_data,XETrapColorReplies))
 | 
						||
            {    /* wants color replies */
 | 
						||
                switch(stuff->reqType)
 | 
						||
                {
 | 
						||
                    case X_AllocColor:
 | 
						||
                        GetSendColorRep(client, stuff);
 | 
						||
                        break;
 | 
						||
                    case X_AllocNamedColor:
 | 
						||
                        GetSendNamedColorRep(client, stuff);
 | 
						||
                        break;
 | 
						||
                    case X_AllocColorCells:
 | 
						||
                        GetSendColorCellsRep(client, stuff);
 | 
						||
                        break;
 | 
						||
                    case X_AllocColorPlanes:
 | 
						||
                        GetSendColorPlanesRep(client, stuff);
 | 
						||
                        break;
 | 
						||
                    default:
 | 
						||
                        break;
 | 
						||
                }
 | 
						||
            }
 | 
						||
#endif /* COLOR_REPLIES */
 | 
						||
        }
 | 
						||
    }
 | 
						||
    while (stc->next != NULL)
 | 
						||
    {   /* increment appropriate stats bucket for each interested client */
 | 
						||
        stc = stc->next;
 | 
						||
        penv = XETenv[stc->client->index];
 | 
						||
        if (BitIsTrue(penv->cur.data_config_flags_req,stuff->reqType))
 | 
						||
        {   /* This particular client would like this particular stat */
 | 
						||
            penv->stats->data.requests[stuff->reqType]++;
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    if (pdata)
 | 
						||
    {
 | 
						||
        Xfree(pdata);
 | 
						||
    }
 | 
						||
    if (spdata)
 | 
						||
    {
 | 
						||
        Xfree(spdata);
 | 
						||
    }
 | 
						||
    if (ignore_grabs == True &&
 | 
						||
        (stuff->reqType == X_GrabServer || stuff->reqType == X_UngrabServer))
 | 
						||
    {    /* doesn't want Grab's! Note: this is a "last configured" setting */
 | 
						||
#ifndef NO_NEW_XTRAP
 | 
						||
	int status;
 | 
						||
 | 
						||
	if (stuff->reqType == X_GrabServer)
 | 
						||
	{
 | 
						||
	    ClientList *pclient;
 | 
						||
 | 
						||
	    /* first call grab server procedure */
 | 
						||
	    status = (*XETrapProcVector[stuff->reqType])(client);
 | 
						||
 | 
						||
	    /* then add XTrap controlling clients */
 | 
						||
	    for (pclient = &io_clients; pclient; pclient = pclient->next)
 | 
						||
		if (pclient->client)
 | 
						||
		    MakeClientGrabImpervious(pclient->client);
 | 
						||
	}
 | 
						||
	else
 | 
						||
	{
 | 
						||
	    ClientList *pclient;
 | 
						||
 | 
						||
	    /* first drop XTrap controlling clients */
 | 
						||
	    for (pclient = &io_clients; pclient; pclient = pclient->next)
 | 
						||
		if (pclient->client)
 | 
						||
		    MakeClientGrabPervious(pclient->client);
 | 
						||
 | 
						||
	    /* then call ungrab server procedure */
 | 
						||
	    status = (*XETrapProcVector[stuff->reqType])(client);
 | 
						||
	}
 | 
						||
	return status;
 | 
						||
#else /* NO_NEW_XTRAP */
 | 
						||
        return(Success);
 | 
						||
#endif /* NO_NEW_XTRAP */
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        return((*XETrapProcVector[stuff->reqType])(client));
 | 
						||
    }
 | 
						||
}
 | 
						||
/*
 | 
						||
 *
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This routine intercepts input xEvents from the keyboard.
 | 
						||
 *      if XETrapTrapActive, will write record to client(s)
 | 
						||
 *      and then pass the event to the server iff not command
 | 
						||
 *      key and gate is open.  If it's a command key, then twiddle
 | 
						||
 *      the gate state as required (optional, see below).
 | 
						||
 *
 | 
						||
 *      This routine implements an optional user specified command key
 | 
						||
 *      that can be used to close the input pipe into the server
 | 
						||
 *      while a client command is generated.  The keypress of the
 | 
						||
 *      command key places this routine in command mode, the keyrelease
 | 
						||
 *      exits command mode.  
 | 
						||
 *
 | 
						||
 *      A keypress of the command key followed by the
 | 
						||
 *      optionally specified lock key will place this routine in continuous
 | 
						||
 *      command mode until the command key and lock key are pressed again
 | 
						||
 *      to exit command mode.  In the locked state, the client interprets
 | 
						||
 *      keystrokes as it wishes, as commands or as input to a prior command.
 | 
						||
 *
 | 
						||
 *      Both mechanisms can be used alternately.
 | 
						||
 *
 | 
						||
 *  IMPLICIT INPUTS :
 | 
						||
 *
 | 
						||
 *      penv->cur.data_config_cmd_key :
 | 
						||
 *                    This is the keycode of the key that is used to stop
 | 
						||
 *                    and restart the transmission of intercepted input 
 | 
						||
 *                    events to the server.  If specified, the gate_state
 | 
						||
 *                    flag will be set or cleared depending on the state of
 | 
						||
 *                    the command_key.
 | 
						||
 *
 | 
						||
 *      penv->cur.data_config_flags_data.XETrapCmdKeyMod:
 | 
						||
 *                    This is the value of the mode in which the command_key
 | 
						||
 *                    will operate.  It currently has two values: MODIFIER and
 | 
						||
 *                    COMMAND_LOCK.  MODIFIER mode clears gate_state on
 | 
						||
 *                    keypress, and sets gate_state on keyrelease.
 | 
						||
 *                    COMMAND_LOCK mode toggles gate_state on
 | 
						||
 *                    or off.
 | 
						||
 *
 | 
						||
 *      gate_closed:
 | 
						||
 *                    A flag that is set/cleared in the xtrap_keyboard
 | 
						||
 *                    routine that indicates whether intercepted input
 | 
						||
 *                    should be passed to the server at any particular
 | 
						||
 *                    instance.
 | 
						||
 *
 | 
						||
 *
 | 
						||
 *      next_key:
 | 
						||
 *                    This variable tracks the state of the next key to be
 | 
						||
 *                    pressed or released.  It allows the checking of double
 | 
						||
 *                    presses of the command key to be sent to the server and
 | 
						||
 *                    keeps good state order when the command key is used.
 | 
						||
 *
 | 
						||
 *      key_ignore:
 | 
						||
 *                   This variable indicates whether or not the specific
 | 
						||
 *                   key should be ignored for subsequent server processing.
 | 
						||
 *
 | 
						||
 */
 | 
						||
int XETrapKeyboard(xEvent *x_event, DevicePtr keybd, int count)
 | 
						||
{                     
 | 
						||
    register BYTE  type   = x_event->u.u.type;
 | 
						||
    register BYTE  detail = x_event->u.u.detail;
 | 
						||
    XETrapEnv *penv;
 | 
						||
    ClientList *stc = &stats_clients;
 | 
						||
    ClientList *cmc = &cmd_clients;
 | 
						||
    int_function cur_func = XETrapKeyboard;
 | 
						||
 | 
						||
#ifdef VERBOSE
 | 
						||
    if (count != 1L)
 | 
						||
    {   /* We haven't coded for this situation yet! */
 | 
						||
        ErrorF("Warning! Event count != 1 (%d)\n", count);
 | 
						||
    }
 | 
						||
#endif
 | 
						||
    while (stc->next != NULL)
 | 
						||
    {   /* increment appropriate stats bucket for each interested client */
 | 
						||
        stc = stc->next;
 | 
						||
        penv = XETenv[stc->client->index];
 | 
						||
        if (BitIsTrue(penv->cur.data_config_flags_event,type))
 | 
						||
        {   /* This particular client would like this particular stat */
 | 
						||
            penv->stats->data.events[type]++;
 | 
						||
        }
 | 
						||
    }
 | 
						||
#ifndef VECTORED_EVENTS
 | 
						||
    /* We *only* StampAndMail command keys with vectored events since
 | 
						||
     * we get much more data by waiting till we get called in XETrapEventVector
 | 
						||
     */
 | 
						||
    XETrapStampAndMail(x_event);  /* send to XTrap client if necessry */
 | 
						||
#endif
 | 
						||
    while (cmc->next != NULL)
 | 
						||
    {
 | 
						||
        cmc = cmc->next;
 | 
						||
        penv = XETenv[cmc->client->index];
 | 
						||
        key_ignore = False;
 | 
						||
        if (detail == penv->cur.data_config_cmd_key)
 | 
						||
        {
 | 
						||
            if (BitIsTrue(penv->cur.data_config_flags_data, XETrapCmdKeyMod))
 | 
						||
            {
 | 
						||
                switch (type) 
 | 
						||
                {
 | 
						||
                    case KeyPress:
 | 
						||
                        if (next_key == XEKeyIsEcho)
 | 
						||
                        {
 | 
						||
                            break;
 | 
						||
                        }
 | 
						||
                        gate_closed = True;
 | 
						||
                        next_key = XEKeyIsClear;
 | 
						||
                        break;
 | 
						||
    
 | 
						||
                    case KeyRelease:
 | 
						||
                        if (next_key == XEKeyIsEcho)
 | 
						||
                        {
 | 
						||
                            next_key = XEKeyIsClear;
 | 
						||
                            break;
 | 
						||
                        }
 | 
						||
                        if (next_key == XEKeyIsClear)
 | 
						||
                        {
 | 
						||
                            next_key = XEKeyIsEcho;
 | 
						||
                        }
 | 
						||
                        else
 | 
						||
                        {   /* it's Other, so Clear it */
 | 
						||
                            next_key = XEKeyIsClear;
 | 
						||
                        }
 | 
						||
                        gate_closed = False;
 | 
						||
                        key_ignore = True;
 | 
						||
                        break;
 | 
						||
    
 | 
						||
                    default: break;
 | 
						||
                }
 | 
						||
            }
 | 
						||
            else
 | 
						||
            {
 | 
						||
                switch (type)
 | 
						||
                {
 | 
						||
                    case KeyPress:
 | 
						||
                        if (next_key == XEKeyIsEcho)
 | 
						||
                        {
 | 
						||
                            gate_closed = False;
 | 
						||
                            break;
 | 
						||
                        }
 | 
						||
                        /* Open gate on cmd key release */
 | 
						||
                        if ((next_key == XEKeyIsOther) && 
 | 
						||
                            gate_closed == True)
 | 
						||
                        {
 | 
						||
                            break;
 | 
						||
                        }
 | 
						||
                        gate_closed = True;
 | 
						||
                        next_key = XEKeyIsClear;
 | 
						||
                        break;
 | 
						||
    
 | 
						||
                    case KeyRelease:
 | 
						||
                        if (next_key == XEKeyIsClear)
 | 
						||
                        {
 | 
						||
                            next_key = XEKeyIsEcho;
 | 
						||
                            break;
 | 
						||
                        }
 | 
						||
    
 | 
						||
                        if (next_key == XEKeyIsEcho)
 | 
						||
                        {
 | 
						||
                            next_key = XEKeyIsClear;
 | 
						||
                            break;
 | 
						||
                        }
 | 
						||
    
 | 
						||
                        gate_closed = False;
 | 
						||
                        key_ignore = True;
 | 
						||
                        next_key = XEKeyIsClear;
 | 
						||
                        break;
 | 
						||
    
 | 
						||
                    default: 
 | 
						||
                        break;
 | 
						||
                }
 | 
						||
            }
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            next_key = XEKeyIsOther;
 | 
						||
        }
 | 
						||
    }            
 | 
						||
 | 
						||
    /*
 | 
						||
     *  If the gate to the server is open, 
 | 
						||
     *  and we are not ignoring a keyrelease,
 | 
						||
     *  pass the event to the server for normal processing.
 | 
						||
     */
 | 
						||
#ifndef VECTORED_EVENTS
 | 
						||
    if ((gate_closed == False) && (key_ignore == False))
 | 
						||
    {
 | 
						||
        if (XETrapEventProcVector[type] != cur_func)
 | 
						||
        {   /* to protect us from infinite loops */
 | 
						||
            (void)(*XETrapEventProcVector[type])(x_event,keybd,count);
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            (void)(*EventProcVector[type])(x_event,keybd,count);
 | 
						||
        }
 | 
						||
    }
 | 
						||
#else  /* VECTORED_EVENTS */
 | 
						||
    if ((gate_closed == False) && (key_ignore == False))
 | 
						||
    {   /* send event on to server to be trapped again in XETrapEventVector */
 | 
						||
        (void)(*keybd_process_inp)(x_event,keybd,count);
 | 
						||
    }
 | 
						||
    else
 | 
						||
    {
 | 
						||
        XETrapStampAndMail(x_event);  /* send to XTrap client if necessry */
 | 
						||
    }
 | 
						||
#endif
 | 
						||
    key_ignore = False; /* reset for next time around */
 | 
						||
    return 0;
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This routine intercepts input xEvents from the pointer device
 | 
						||
 *      and passes the input event back to the server for normal processing.
 | 
						||
 *
 | 
						||
 *      This routine is sensitive to whether input is being passed
 | 
						||
 *      up to the server or not.  This state is set by the keyboard
 | 
						||
 *      input routine.
 | 
						||
 *
 | 
						||
 *
 | 
						||
 */
 | 
						||
#ifndef VECTORED_EVENTS
 | 
						||
int XETrapPointer(xEvent *x_event, DevicePtr ptrdev, int count)
 | 
						||
{
 | 
						||
    XETrapEnv *penv;
 | 
						||
    ClientList *stc = &stats_clients;
 | 
						||
    int_function cur_func = XETrapPointer;
 | 
						||
 | 
						||
#ifdef VERBOSE
 | 
						||
    if (count != 1L)
 | 
						||
    {   /* We haven't coded for this situation yet! */
 | 
						||
        ErrorF("Warning! Event count != 1 (%d)\n", count);
 | 
						||
    }
 | 
						||
#endif
 | 
						||
    while (stc->next != NULL)
 | 
						||
    {   /* increment appropriate stats bucket for each interested client */
 | 
						||
        stc = stc->next;
 | 
						||
        penv = XETenv[stc->client->index];
 | 
						||
        if (BitIsTrue(penv->cur.data_config_flags_event,x_event->u.u.type))
 | 
						||
        {   /* This particular client would like this particular stat */
 | 
						||
            penv->stats->data.events[x_event->u.u.type]++;
 | 
						||
        }
 | 
						||
    }
 | 
						||
    XETrapStampAndMail(x_event);  /* send to XTrap client if necessry */
 | 
						||
    /*
 | 
						||
     *  If the gate to the server is open,
 | 
						||
     *  pass the event up like nothing has happened.
 | 
						||
     */
 | 
						||
    if (gate_closed == False)
 | 
						||
    {
 | 
						||
        if (XETrapEventProcVector[x_event->u.u.type] != cur_func)
 | 
						||
        {   /* to protect us from infinite loops */
 | 
						||
            (void)(*XETrapEventProcVector[x_event->u.u.type])(x_event,ptrdev,
 | 
						||
                count);
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            (void)(*EventProcVector[x_event->u.u.type])(x_event,ptrdev,count);
 | 
						||
        }
 | 
						||
    }
 | 
						||
    return 0;
 | 
						||
}
 | 
						||
#endif /* !VECTORED_EVENTS */
 | 
						||
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This routine determines whether it needs to send event data
 | 
						||
 *      to the XTrap Client(s).  If so, it timestamps it appropriately
 | 
						||
 *      and writes out both the header and detail information.
 | 
						||
 *
 | 
						||
 */
 | 
						||
void XETrapStampAndMail(xEvent *x_event)
 | 
						||
{
 | 
						||
    XETrapDatum data;
 | 
						||
    register CARD32 size;
 | 
						||
    XETrapEnv *penv;
 | 
						||
    ClientList *ioc = &io_clients;
 | 
						||
 | 
						||
    /* Currently, we're intercepting core events *before* most
 | 
						||
     * of the event information's filled in.  Specifically, the
 | 
						||
     * only fields that are valid at this level are: type, detail,
 | 
						||
     * time, rootX, rootY, and state.
 | 
						||
     */
 | 
						||
    /* Loop through all clients wishing I/O */
 | 
						||
    while (ioc->next != NULL)
 | 
						||
    {
 | 
						||
        ioc = ioc->next;
 | 
						||
        penv = XETenv[ioc->client->index];
 | 
						||
        /* Do we have a valid fd? Do we care about this event? */
 | 
						||
        if (BitIsTrue(penv->cur.data_config_flags_event, x_event->u.u.type))
 | 
						||
        {
 | 
						||
            XETrapSetHeaderEvent(&(data.hdr));
 | 
						||
            data.hdr.win_x = data.hdr.win_y = -1L; /* Invalidate req draw */
 | 
						||
            data.hdr.screen = 0L;   /* not till Events are vectored! */
 | 
						||
            data.hdr.client = 0L;   /* not till Events are vectored! */
 | 
						||
            if (BitIsTrue(penv->cur.data_config_flags_data,
 | 
						||
                XETrapTimestamp))
 | 
						||
            {
 | 
						||
                data.hdr.timestamp = GetTimeInMillis();
 | 
						||
            }
 | 
						||
            size = data.hdr.count = XETrapMinPktSize; /* Always for evts */
 | 
						||
            penv->last_input_time = x_event->u.keyButtonPointer.time;
 | 
						||
            /* Copy the event information into our local memory */
 | 
						||
            (void)memcpy(&(data.u.event),x_event,sizeof(xEvent));
 | 
						||
 | 
						||
#ifdef PANORAMIX
 | 
						||
	    if (!noPanoramiXExtension &&
 | 
						||
                (data.u.event.u.u.type == MotionNotify ||
 | 
						||
                data.u.event.u.u.type == ButtonPress ||
 | 
						||
                data.u.event.u.u.type == ButtonRelease ||
 | 
						||
                data.u.event.u.u.type == KeyPress ||
 | 
						||
                data.u.event.u.u.type == KeyRelease)) {
 | 
						||
		    int scr = XineramaGetCursorScreen(inputInfo.pointer);
 | 
						||
		    data.u.event.u.keyButtonPointer.rootX +=
 | 
						||
			panoramiXdataPtr[scr].x - panoramiXdataPtr[0].x;
 | 
						||
		    data.u.event.u.keyButtonPointer.rootY +=
 | 
						||
			panoramiXdataPtr[scr].y - panoramiXdataPtr[0].y;
 | 
						||
	    }
 | 
						||
#endif
 | 
						||
 | 
						||
            if (penv->client->swapped)
 | 
						||
            {   /* 
 | 
						||
                 * Notice that we don't swap the XTRAP EVENT information.  
 | 
						||
                 * This is done in the XETrapWriteXLib() routine.
 | 
						||
                 */
 | 
						||
                xEvent ToEvent;
 | 
						||
                (*EventSwapVector[data.u.event.u.u.type & 0177])
 | 
						||
                    (&data.u.event,&ToEvent);
 | 
						||
                (void)memcpy(&(data.u.event),&ToEvent,sizeof(ToEvent));
 | 
						||
                sXETrapHeader(&(data.hdr));  /* swap the XTrap Header */
 | 
						||
            }
 | 
						||
            /* From this point on, the contents of data is swapped and
 | 
						||
             * therefore we should not refer to it for information.
 | 
						||
             */
 | 
						||
            if (XETrapWriteXLib(penv, (BYTE *)&data, size) != size)
 | 
						||
            {
 | 
						||
                SendErrorToClient(penv->client,
 | 
						||
                    XETrap_avail.data.major_opcode,
 | 
						||
                    x_event->u.u.type, 0L, XETrapErrorBase + BadIO);
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }
 | 
						||
    return;
 | 
						||
}
 | 
						||
#ifdef VECTORED_EVENTS
 | 
						||
int XETrapEventVector(ClientPtr client, xEvent *x_event)
 | 
						||
{
 | 
						||
    XETrapDatum data;
 | 
						||
    register CARD32 size;
 | 
						||
    XETrapEnv *penv;
 | 
						||
    ClientList *ioc = &io_clients;
 | 
						||
 | 
						||
    /* Loop through all clients wishing I/O */
 | 
						||
    while (ioc->next != NULL)
 | 
						||
    {
 | 
						||
        ioc = ioc->next;
 | 
						||
        penv = XETenv[ioc->client->index];
 | 
						||
        /* Do we care about this event? */
 | 
						||
        if (BitIsTrue(penv->cur.data_config_flags_event, x_event->u.u.type))
 | 
						||
        {
 | 
						||
            XETrapSetHeaderEvent(&(data.hdr));
 | 
						||
            data.hdr.client = client->index;
 | 
						||
            data.hdr.win_x = data.hdr.win_y = -1L; /* Invalidate req draw */
 | 
						||
            if ((current_screen < 0L) || ((x_event->u.u.type >= KeyPress) && 
 | 
						||
                (x_event->u.u.type <= MotionNotify) && 
 | 
						||
                (!x_event->u.keyButtonPointer.sameScreen)))
 | 
						||
            {   /* we've moved/warped to another screen */
 | 
						||
		/* XXX: we're getting the client's pointer root window.
 | 
						||
		 * is this correct?  Should it be the client's keyboard? */
 | 
						||
                WindowPtr root_win = GetCurrentRootWindow(PickPointer(client));
 | 
						||
                current_screen = root_win->drawable.pScreen->myNum;
 | 
						||
            }
 | 
						||
            data.hdr.screen = current_screen;
 | 
						||
            if (BitIsTrue(penv->cur.data_config_flags_data,
 | 
						||
                XETrapTimestamp))
 | 
						||
            {
 | 
						||
                data.hdr.timestamp = GetTimeInMillis();
 | 
						||
            }
 | 
						||
            size = data.hdr.count = XETrapMinPktSize; /* Always for evts */
 | 
						||
            penv->last_input_time = x_event->u.keyButtonPointer.time;
 | 
						||
            /* Copy the event information into our local memory */
 | 
						||
            (void)memcpy(&(data.u.event),x_event,sizeof(xEvent));
 | 
						||
    
 | 
						||
            if (penv->client->swapped)
 | 
						||
            {
 | 
						||
                xEvent ToEvent;
 | 
						||
                (*EventSwapVector[data.u.event.u.u.type & 0177])
 | 
						||
                    (&data.u.event,&ToEvent);
 | 
						||
                (void)memcpy(&(data.u.event),&ToEvent,sizeof(ToEvent));
 | 
						||
                sXETrapHeader(&(data.hdr));  /* swap the XTrap Header */
 | 
						||
            }
 | 
						||
            /* From this point on, the contents of pdata is swapped and
 | 
						||
             * therefore we should not refer to it for information.
 | 
						||
             */
 | 
						||
            if (XETrapWriteXLib(penv, (BYTE *)&data, size) != size)
 | 
						||
            {
 | 
						||
                SendErrorToClient(penv->client,
 | 
						||
                    XETrap_avail.data.major_opcode,
 | 
						||
                    x_event->u.u.type, 0L, XETrapErrorBase + BadIO);
 | 
						||
            }
 | 
						||
        }
 | 
						||
    }
 | 
						||
    return;
 | 
						||
}
 | 
						||
#endif /* VECTORED_EVENTS */
 | 
						||
void sReplyXTrapDispatch(ClientPtr client, int size, char *reply)
 | 
						||
{
 | 
						||
    register XETrapRepHdr *rep = (XETrapRepHdr *)reply;
 | 
						||
 | 
						||
    switch(rep->detail)
 | 
						||
    {   
 | 
						||
        case XETrap_GetAvailable:
 | 
						||
            {   
 | 
						||
                xXTrapGetAvailReply lrep;
 | 
						||
                (void)memcpy((char *)&lrep,reply,sizeof(lrep));
 | 
						||
                sReplyXETrapGetAvail(client,size,(char *)&lrep);
 | 
						||
            }
 | 
						||
            break;
 | 
						||
        case XETrap_GetCurrent:
 | 
						||
            {   
 | 
						||
                xXTrapGetCurReply lrep;
 | 
						||
                (void)memcpy((char *)&lrep,reply,sizeof(lrep));
 | 
						||
                sReplyXETrapGetCur(client,size,(char *)&lrep);
 | 
						||
            }
 | 
						||
            break;
 | 
						||
        case XETrap_GetStatistics:
 | 
						||
            {   
 | 
						||
                xXTrapGetStatsReply lrep;
 | 
						||
                (void)memcpy((char *)&lrep,reply,sizeof(lrep));
 | 
						||
                sReplyXETrapGetStats(client,size,(char *)&lrep);
 | 
						||
            }
 | 
						||
            break;
 | 
						||
        case XETrap_GetVersion:
 | 
						||
            {   
 | 
						||
                xXTrapGetVersReply lrep;
 | 
						||
                (void)memcpy((char *)&lrep,reply,sizeof(lrep));
 | 
						||
                sReplyXETrapGetVers(client,size,(char *)&lrep);
 | 
						||
            }
 | 
						||
            break;
 | 
						||
        case XETrap_GetLastInpTime:
 | 
						||
            {   
 | 
						||
                xXTrapGetLITimReply lrep;
 | 
						||
                (void)memcpy((char *)&lrep,reply,sizeof(lrep));
 | 
						||
                sReplyXETrapGetLITim(client,size,(char *)&lrep);
 | 
						||
            }
 | 
						||
            break;
 | 
						||
        default:
 | 
						||
            SendErrorToClient(client,XETrap_avail.data.major_opcode,
 | 
						||
                rep->detail, 0L, BadImplementation);
 | 
						||
            break;
 | 
						||
    }
 | 
						||
    return;
 | 
						||
}
 | 
						||
 | 
						||
/* 
 | 
						||
 * XLib communications routines 
 | 
						||
 */
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function performs the transport specific functions required
 | 
						||
 *      for writing data back to an XTrap client over XLib.  The trick is
 | 
						||
 *      packaging the data into <=32 byte packets to conform to the sizeof
 | 
						||
 *      an X Event.  nbytes must be at least equal to XETrapMinPktSize
 | 
						||
 *
 | 
						||
 */
 | 
						||
int XETrapWriteXLib(XETrapEnv *penv, BYTE *data, CARD32 nbytes)
 | 
						||
{
 | 
						||
    CARD32 size, total = 0L;
 | 
						||
    xETrapDataEvent event;
 | 
						||
 | 
						||
    /* Initialize the detail field to show the beginning of a datum */
 | 
						||
    event.detail = XETrapDataStart;
 | 
						||
    event.idx = 0L;
 | 
						||
 | 
						||
    /* This loop could be optimized by not calling Write until after all
 | 
						||
     * of the events are packaged. However, this would require memory
 | 
						||
     * games, and may not therefore be a win.
 | 
						||
     */
 | 
						||
    while (nbytes > 0L)
 | 
						||
    {   /* How many bytes can we send in this packet */
 | 
						||
        size = (nbytes > sz_EventData) ? sz_EventData : nbytes;
 | 
						||
 | 
						||
        /* Initialize the event */
 | 
						||
        event.type = XETrapData + XETrap_avail.data.event_base;
 | 
						||
        event.sequenceNumber = penv->client->sequence;
 | 
						||
 | 
						||
        /* Copy the data we are sending */
 | 
						||
        (void)memcpy(event.data,data,size);
 | 
						||
        if (size < sz_EventData)
 | 
						||
            (void)memset(event.data+size,0L,sz_EventData-size);
 | 
						||
        data += size;
 | 
						||
        nbytes -= size;
 | 
						||
        total += size;
 | 
						||
 | 
						||
        /* Set the detail field to show the continuation of datum */
 | 
						||
        if (total != size)
 | 
						||
        {   /* this is not the first one */
 | 
						||
            event.detail = (nbytes > 0) ? XETrapDataContinued : XETrapDataLast;
 | 
						||
        }
 | 
						||
 | 
						||
        /* Send this part to the client */
 | 
						||
        WriteEventsToClient(penv->client, 1L, (xEvent *) &event);
 | 
						||
        event.idx++;      /* Bump the index for the next event */
 | 
						||
    }
 | 
						||
    return(total);
 | 
						||
}
 | 
						||
 | 
						||
/*----------------------------*
 | 
						||
 *  Static Functions
 | 
						||
 *----------------------------*/
 | 
						||
 | 
						||
static void update_protocol(xXTrapGetReq *reqptr, ClientPtr client)
 | 
						||
{
 | 
						||
    XETrapEnv *penv = XETenv[client->index];
 | 
						||
    /* update protocol number */
 | 
						||
    switch (reqptr->protocol)
 | 
						||
    {
 | 
						||
        /* known acceptable protocols */
 | 
						||
        case 31:
 | 
						||
        case XETrapProtocol:
 | 
						||
            penv->protocol = reqptr->protocol;
 | 
						||
            break;
 | 
						||
        /* all else */
 | 
						||
        default:    /* stay backwards compatible */
 | 
						||
            penv->protocol = 31;
 | 
						||
            break;
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
/* Swap 2 functions. This is a function instead of a macro to help to keep
 | 
						||
 * lint from complaining about mixed types. It seems to work, but I would
 | 
						||
 * probably classify this as a hack.
 | 
						||
 */
 | 
						||
static void _SwapProc( register int (**f1)(void), register int (**f2)(void))
 | 
						||
{
 | 
						||
    register int (*t1)(void) = *f1;
 | 
						||
    *f1 = *f2;
 | 
						||
    *f2 = t1;
 | 
						||
 | 
						||
    return;
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function swaps the byte order of fields within
 | 
						||
 *      the XTrap Event Header.  It assumes the data will be
 | 
						||
 *	swapped by code in XETrapRequestVector().
 | 
						||
 *
 | 
						||
 */
 | 
						||
static void sXETrapEvent(xETrapDataEvent *from, xETrapDataEvent *to)
 | 
						||
{
 | 
						||
    to->type = from->type;
 | 
						||
    to->detail = from->detail;
 | 
						||
    cpswaps(from->sequenceNumber,to->sequenceNumber);
 | 
						||
    cpswapl(from->idx,to->idx);
 | 
						||
    /* Assumes that the data's already been swapped by XETrapRequestVector */
 | 
						||
    memcpy(to->data, from->data, SIZEOF(EventData));
 | 
						||
}
 | 
						||
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function adds a node from an accelerator linked-list
 | 
						||
 *      (either io_clients, stats_clients, or cmd_clients).
 | 
						||
 *
 | 
						||
 */
 | 
						||
static int add_accelerator_node(ClientPtr client, ClientList *accel)
 | 
						||
{
 | 
						||
    Bool found = False;
 | 
						||
    int status = Success;
 | 
						||
 | 
						||
    while (accel->next != NULL)
 | 
						||
    {
 | 
						||
        if (accel->client == client)
 | 
						||
        {
 | 
						||
            found = True;   /* Client's already known */
 | 
						||
            break;
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            accel = accel->next;
 | 
						||
        }
 | 
						||
    }
 | 
						||
    if (found == False)
 | 
						||
    {
 | 
						||
        if ((accel->next = (ClientList *)Xcalloc(sizeof(ClientList))) == NULL)
 | 
						||
        {
 | 
						||
            status = BadAlloc;
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {   /* fill in the node */
 | 
						||
            accel = accel->next;
 | 
						||
            accel->next   = NULL;
 | 
						||
            accel->client = client;
 | 
						||
        }
 | 
						||
    }
 | 
						||
    return(status);
 | 
						||
}
 | 
						||
/*
 | 
						||
 *  DESCRIPTION:
 | 
						||
 *
 | 
						||
 *      This function removes a node from an accelerator linked-list
 | 
						||
 *      (either io_clients, stats_clients, or cmd_clients).
 | 
						||
 *
 | 
						||
 */
 | 
						||
static void remove_accelerator_node(ClientPtr client, ClientList *accel)
 | 
						||
{
 | 
						||
    while (accel->next != NULL)
 | 
						||
    {
 | 
						||
        if (accel->next->client == client)
 | 
						||
        {
 | 
						||
            ClientList *tmp = accel->next->next;
 | 
						||
            Xfree(accel->next);
 | 
						||
            accel->next = tmp;
 | 
						||
            break;
 | 
						||
        }
 | 
						||
        else
 | 
						||
        {
 | 
						||
            accel = accel->next;
 | 
						||
        }
 | 
						||
    }
 | 
						||
 | 
						||
    return;
 | 
						||
}
 | 
						||
 | 
						||
#ifdef COLOR_REPLIES
 | 
						||
static void GetSendColorRep(ClientPtr client, xResourceReq *req)
 | 
						||
{   /* adapted from ProcAllocColor() in dispatch.c */
 | 
						||
    XETrapDatum data;
 | 
						||
    int retval;
 | 
						||
    XETrapEnv *penv = XETenv[client->index];
 | 
						||
    xAllocColorReply *crep = (xAllocColorReply *)&(data.u.reply);
 | 
						||
    xAllocColorReq   *creq = (xAllocColorReq *)req;
 | 
						||
    ColormapPtr pmap = (ColormapPtr )LookupIDByType(creq->cmap, RT_COLORMAP);
 | 
						||
 | 
						||
    /* Fill in the header fields */
 | 
						||
    data.hdr.count = XETrapMinPktSize; /* The color replies are 32 bytes */
 | 
						||
    XETrapSetHeaderReply(&(data.hdr));
 | 
						||
    /* Hack alert:
 | 
						||
     * We need to pass the "reply" type in the header since replies don't
 | 
						||
     * contain the id's themselves.  However, we're not changing the
 | 
						||
     * protocol to support this until we decide exactly how we want to
 | 
						||
     * do *all* replies (e.g. not just ColorReplies).  So until then, stow
 | 
						||
     * the reply id in the screen field which wouldn't normally be used in
 | 
						||
     * this context.
 | 
						||
     */
 | 
						||
    data.hdr.screen = req->reqType;
 | 
						||
    if (!pmap)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, BadColor);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    crep->red   = creq->red;
 | 
						||
    crep->green = creq->green;
 | 
						||
    crep->blue  = creq->blue;
 | 
						||
    crep->pixel = 0;
 | 
						||
    if ((retval = AllocColor(pmap, &(crep->red), &(crep->green),
 | 
						||
        &(crep->blue), &(crep->pixel), client->index)) != Success)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, retval);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    /* Swap data if necessary */
 | 
						||
    if (client->swapped)
 | 
						||
    {
 | 
						||
        INT32 n;
 | 
						||
        swaps(&(crep->red), n);
 | 
						||
        swaps(&(crep->green), n);
 | 
						||
        swaps(&(crep->blue), n);
 | 
						||
        swapl(&(crep->pixel), n);
 | 
						||
    }
 | 
						||
    /* Send data to client */
 | 
						||
    if (XETrapWriteXLib(penv, (BYTE *)&data, XETrapMinPktSize) 
 | 
						||
        != XETrapMinPktSize)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, XETrapErrorBase + BadIO);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
static void GetSendNamedColorRep(ClientPtr client, xResourceReq *req)
 | 
						||
{   /* adapted from ProcAllocNamedColor() in dispatch.c */
 | 
						||
    XETrapDatum data;
 | 
						||
    XETrapEnv *penv = XETenv[client->index];
 | 
						||
    int retval;
 | 
						||
    xAllocNamedColorReply *nrep = (xAllocNamedColorReply *)&(data.u.reply);
 | 
						||
    xAllocNamedColorReq   *nreq = (xAllocNamedColorReq *)req;
 | 
						||
    ColormapPtr pcmp = (ColormapPtr )LookupIDByType(nreq->cmap, RT_COLORMAP);
 | 
						||
 | 
						||
    data.hdr.count = XETrapMinPktSize; /* The color replies are 32 bytes */
 | 
						||
    XETrapSetHeaderReply(&(data.hdr));
 | 
						||
    /* Hack alert:
 | 
						||
     * We need to pass the "reply" type in the header since replies don't
 | 
						||
     * contain the id's themselves.  However, we're not changing the
 | 
						||
     * protocol to support this until we decide exactly how we want to
 | 
						||
     * do *all* replies (e.g. not just ColorReplies).  So until then, stow
 | 
						||
     * the reply id in the screen field which wouldn't normally be used in
 | 
						||
     * this context.
 | 
						||
     */
 | 
						||
    data.hdr.screen = req->reqType;
 | 
						||
    if (!pcmp)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, BadColor);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    if (!OsLookupColor(pcmp->pScreen->myNum, (char *)&nreq[1], 
 | 
						||
        nreq->nbytes, &(nrep->exactRed), &(nrep->exactGreen), 
 | 
						||
        &(nrep->exactBlue)))
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, BadName);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    nrep->screenRed     = nrep->exactRed;
 | 
						||
    nrep->screenGreen   = nrep->exactGreen;
 | 
						||
    nrep->screenBlue    = nrep->exactBlue;
 | 
						||
    nrep->pixel         = 0;
 | 
						||
    if ((retval = AllocColor(pcmp, &(nrep->screenRed), 
 | 
						||
        &(nrep->screenGreen), &(nrep->screenBlue), &(nrep->pixel), 
 | 
						||
        client->index)) != Success)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, retval);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    /* Swap data if necessary */
 | 
						||
    if (client->swapped)
 | 
						||
    {
 | 
						||
        INT32 n;
 | 
						||
        swapl(&(nrep->pixel), n);
 | 
						||
        swaps(&(nrep->exactRed), n);
 | 
						||
        swaps(&(nrep->exactGreen), n);
 | 
						||
        swaps(&(nrep->exactBlue), n);
 | 
						||
        swaps(&(nrep->screenRed), n);
 | 
						||
        swaps(&(nrep->screenGreen), n);
 | 
						||
        swaps(&(nrep->screenBlue), n);
 | 
						||
    }
 | 
						||
 | 
						||
    /* Send data to client */
 | 
						||
    if (XETrapWriteXLib(penv, (BYTE *)&data, XETrapMinPktSize) 
 | 
						||
        != XETrapMinPktSize)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, XETrapErrorBase + BadIO);
 | 
						||
    }
 | 
						||
}
 | 
						||
 | 
						||
static void GetSendColorCellsRep(ClientPtr client, xResourceReq *req)
 | 
						||
{   /* adapted from ProcAllocColorCells() in dispatch.c */
 | 
						||
    int                   retval;
 | 
						||
    int                   npixels, nmasks;
 | 
						||
    unsigned long         *ppixels, *pmasks;
 | 
						||
    long                  length;
 | 
						||
    XETrapDatum           *data;
 | 
						||
    XETrapEnv             *penv = XETenv[client->index];
 | 
						||
    xAllocColorCellsReply *crep;
 | 
						||
    xAllocColorCellsReq   *creq = (xAllocColorCellsReq *)req;
 | 
						||
    ColormapPtr pmap = (ColormapPtr )LookupIDByType(creq->cmap, RT_COLORMAP);
 | 
						||
 | 
						||
    if (!pmap)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, BadColor);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    npixels = creq->colors;
 | 
						||
    if (!npixels)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, BadValue);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    nmasks = creq->planes;
 | 
						||
    length = ((long)npixels + (long)nmasks) * sizeof(Pixel);
 | 
						||
    data = (XETrapDatum *)ALLOCATE_LOCAL(sizeof(XETrapDatum)+length);
 | 
						||
    if (!data)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, BadAlloc);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    data->hdr.count = MIN(penv->cur.data_config_max_pkt_size,
 | 
						||
        sizeof(XETrapDatum)+length);
 | 
						||
    XETrapSetHeaderReply(&(data->hdr));
 | 
						||
    data->hdr.screen = req->reqType;    /* hack! but necessary */
 | 
						||
    ppixels = (unsigned long *)((char *)data + sizeof(XETrapDatum));
 | 
						||
    pmasks = ppixels + npixels;
 | 
						||
    if ((retval = AllocColorCells(client->index, pmap, npixels, 
 | 
						||
        nmasks, (Bool)creq->contiguous, ppixels, pmasks)) != Success)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, retval);
 | 
						||
        DEALLOCATE_LOCAL(data);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    crep = (xAllocColorCellsReply *)&(data->u.reply);
 | 
						||
    crep->nPixels = npixels;
 | 
						||
    crep->nMasks  = nmasks;
 | 
						||
    /* Swap data if necessary */
 | 
						||
    if (client->swapped)
 | 
						||
    {
 | 
						||
        INT32 n, i, *ptr;
 | 
						||
        ptr=(INT32 *)ppixels;
 | 
						||
        swaps(&(crep->nPixels), n);
 | 
						||
        swaps(&(crep->nMasks), n);
 | 
						||
        for (i=0; i<length; i++)
 | 
						||
        {
 | 
						||
            swapl(&(ptr[i]), n);
 | 
						||
        }
 | 
						||
    }
 | 
						||
    /* Send data to client */
 | 
						||
    if (XETrapWriteXLib(penv, (BYTE *)&data, data->hdr.count) 
 | 
						||
        != data->hdr.count)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, XETrapErrorBase + BadIO);
 | 
						||
    }
 | 
						||
    DEALLOCATE_LOCAL(data);
 | 
						||
}
 | 
						||
static void GetSendColorPlanesRep(ClientPtr client, xResourceReq *req)
 | 
						||
{   /* adapted from ProcAllocColorPlanes() in dispatch.c */
 | 
						||
    int                   retval;
 | 
						||
    int                   npixels, nmasks;
 | 
						||
    unsigned long         *ppixels, *pmasks;
 | 
						||
    long                  length;
 | 
						||
    XETrapDatum           *data;
 | 
						||
    XETrapEnv             *penv = XETenv[client->index];
 | 
						||
    xAllocColorPlanesReply *crep;
 | 
						||
    xAllocColorPlanesReq   *creq = (xAllocColorPlanesReq *)req;
 | 
						||
    ColormapPtr pmap = (ColormapPtr )LookupIDByType(creq->cmap, RT_COLORMAP);
 | 
						||
 | 
						||
    if (!pmap)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, BadColor);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    npixels = creq->colors;
 | 
						||
    if (!npixels)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, BadValue);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    length = (long)npixels * sizeof(Pixel);
 | 
						||
    data = (XETrapDatum *)ALLOCATE_LOCAL(sizeof(XETrapDatum)+length);
 | 
						||
    if (!data)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, BadAlloc);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    data->hdr.count = MIN(penv->cur.data_config_max_pkt_size,
 | 
						||
        sizeof(XETrapDatum)+length);
 | 
						||
    XETrapSetHeaderReply(&(data->hdr));
 | 
						||
    data->hdr.screen = req->reqType;    /* hack! but necessary */
 | 
						||
    ppixels = (unsigned long *)((char *)data + sizeof(XETrapDatum));
 | 
						||
    crep = (xAllocColorPlanesReply *)&(data->u.reply);
 | 
						||
    if ((retval = AllocColorPlanes(client->index, pmap, npixels, 
 | 
						||
        (int)creq->red, (int)creq->green, (int)creq->blue, 
 | 
						||
        (int)creq->contiguous, ppixels, &(crep->redMask), &(crep->greenMask),
 | 
						||
        &(crep->blueMask))) != Success)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, retval);
 | 
						||
        DEALLOCATE_LOCAL(data);
 | 
						||
        return;
 | 
						||
    }
 | 
						||
    crep->nPixels = npixels;
 | 
						||
    /* Swap data if necessary */
 | 
						||
    if (client->swapped)
 | 
						||
    {
 | 
						||
        INT32 n, i, *ptr;
 | 
						||
        ptr=(INT32 *)ppixels;
 | 
						||
        swaps(&(crep->nPixels), n);
 | 
						||
        swapl(&(crep->redMask), n);
 | 
						||
        swapl(&(crep->greenMask), n);
 | 
						||
        swapl(&(crep->blueMask), n);
 | 
						||
        for (i=0; i<length; i++)
 | 
						||
        {
 | 
						||
            swapl(&(ptr[i]), n);
 | 
						||
        }
 | 
						||
    }
 | 
						||
    /* Send data to client */
 | 
						||
    if (XETrapWriteXLib(penv, (BYTE *)&data, data->hdr.count) 
 | 
						||
        != data->hdr.count)
 | 
						||
    {
 | 
						||
        SendErrorToClient(penv->client, XETrap_avail.data.major_opcode,
 | 
						||
            req->reqType, 0L, XETrapErrorBase + BadIO);
 | 
						||
    }
 | 
						||
    DEALLOCATE_LOCAL(data);
 | 
						||
}
 | 
						||
#endif /* COLOR_REPLIES */
 |