2158 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			2158 lines
		
	
	
		
			74 KiB
		
	
	
	
		
			C
		
	
	
	
| /* $XdotOrg: xc/programs/Xserver/XTrap/xtrapdi.c,v 1.2 2004/04/23 18:44:40 eich Exp $ */
 | ||
| /* $XFree86: xc/programs/Xserver/XTrap/xtrapdi.c,v 1.6tsi Exp $ */
 | ||
| /*****************************************************************************
 | ||
| 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
 | ||
| 
 | ||
| #ifndef EXTMODULE
 | ||
| #include <stdio.h>
 | ||
| #include <errno.h>
 | ||
| #include <X11/Xos.h>
 | ||
| #else
 | ||
| #include "xf86_ansic.h"
 | ||
| #endif
 | ||
| #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 <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();
 | ||
| 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 )(), int (**f2 )());
 | ||
| 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]), &(ProcVector[i]));
 | ||
|                     }
 | ||
|                 }
 | ||
|                 else
 | ||
|                 {   /* Client wants the *real* rtn */
 | ||
|                     if (--(vectored_requests[i]) <= 0L)
 | ||
|                     {   /* No more clients using, so do it */
 | ||
|                         _SwapProc(&(XETrapProcVector[i]), &(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))
 | ||
|             {
 | ||
|                 window_ptr = (WindowPtr) LookupDrawable(stuff->id, client);
 | ||
|                 if (window_ptr == 0L)
 | ||
|                 {   /* 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();
 | ||
| 		    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 */
 | ||
|                 WindowPtr root_win = GetCurrentRootWindow();
 | ||
|                 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)(), register int (**f2)())
 | ||
| {
 | ||
|     register int (*t1)() = *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 */
 |