#define NEED_REPLIES
#define NEED_EVENTS
#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"
#include "misc.h"
#include "dixstruct.h"
#include "resource.h"
#ifdef PC
# include "scrintst.h"
# include "extnsist.h"
#else
# include "extnsionst.h"
# include "scrnintstr.h"
#endif
#include "pixmapstr.h"
#include "windowstr.h"
#include <X11/extensions/xtrapdi.h>
#include <X11/extensions/xtrapddmi.h>
#include <X11/extensions/xtrapproto.h>
#include "colormapst.h"
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#include "cursor.h"
#endif
DevicePtr XETrapKbdDev = NULL;
DevicePtr XETrapPtrDev = NULL;
int XETrapErrorBase = 0L;
xXTrapGetAvailReply XETrap_avail;
globalref int_function XETrapDispatchVector[10L];
globalref int_function XETSwDispatchVector[10L];
globalref int_function XETrapProcVector[256L];
#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;
globalref int_function XETrapEventProcVector[XETrapCoreEvents];
globalref void_function XETSwProcVector[256L];
#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)))
#ifndef ASIZE
#define ASIZE(array) (sizeof(array)/sizeof(array[0L]))
#endif
#ifndef XEXTRA
#define XEXTRA(s) \
((sizeof(s)+(sizeof(CARD32)-1L)-XETrapMinRepSize)/sizeof(CARD32))
#endif
static XETrapEnv *XETenv[MAXCLIENTS] = {NULL};
#ifndef RESTYPE
#define RESTYPE unsigned long
#endif
static RESTYPE XETrapClass = 0L;
static RESTYPE XETrapType = 0L;
static Bool gate_closed = False;
static Bool key_ignore = False;
static Bool ignore_grabs = False;
static CARD8 next_key = XEKeyIsClear;
#ifdef VECTORED_EVENTS
static INT16 current_screen = -1L;
#endif
static INT16 vectored_requests[256L] = {0L};
static INT16 vectored_events[KeyPress+MotionNotify] = {0L};
typedef struct _client_list
{
struct _client_list *next;
ClientPtr client;
} ClientList;
static ClientList io_clients;
static ClientList stats_clients;
static ClientList cmd_clients;
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
int XETrapDestroyEnv(pointer value, XID id)
{
xXTrapReq request;
XETrapEnv *penv = XETenv[(long)value];
XETrapReset(&request,penv->client);
if (penv->stats)
{
remove_accelerator_node(penv->client, &stats_clients);
Xfree(penv->stats);
}
if (cmd_clients.next == NULL)
{
gate_closed = False;
key_ignore = False;
next_key = XEKeyIsClear;
}
#ifdef VECTORED_EVENTS
current_screen = -1L;
#endif
#ifdef VERBOSE
ErrorF("%s: Client '%d' Disconnected\n", XTrapExtName,
penv->client->index);
#endif
Xfree(penv);
XETenv[(long)value] = NULL;
return 0;
}
void XETrapCloseDown(ExtensionEntry *extEntry)
{
long i;
for (i=0L; i<MAXCLIENTS; i++)
{
if (XETenv[i] != NULL)
{
XETrapDestroyEnv((pointer)i,0L);
}
}
ignore_grabs = False;
return;
}
Bool XETrapRedirectDevices()
{
Bool retval = True;
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
XETrapEventProcVector[KeyPress] = XETrapKeyboard;
XETrapEventProcVector[KeyRelease] = XETrapKeyboard;
#endif
}
#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
return(retval);
}
void DEC_XTRAPInit()
{
register ExtensionEntry *extEntry;
unsigned int i;
Atom a;
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;
ReplySwapVector[XETrap_avail.data.major_opcode] =
(void_function) sReplyXTrapDispatch;
EventSwapVector[extEntry->eventBase + XETrapData] =
(EventSwapPtr) sXETrapEvent;
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;
}
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;
for (i=0L; i<ASIZE(XETrap_avail.data.valid); i++)
{
XETrap_avail.data.valid[i] = 0L;
}
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);
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
#ifndef COLOR_REPLIES
BitFalse(XETrap_avail.data.valid,XETrapColorReplies);
#else
BitTrue(XETrap_avail.data.valid,XETrapColorReplies);
#endif
BitTrue(XETrap_avail.data.valid,XETrapGrabServer);
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();
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++)
{
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;
}
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;
AddResource(FakeClientID(client->index),XETrapType,
(pointer)(long)(client->index));
if (XETrapRedirectDevices() == False)
{
status = XETrapErrorBase + BadDevices;
}
if (status == Success)
{
status = XETrapReset(NULL, penv->client);
}
}
#ifdef VECTORED_EVENTS
current_screen = -1L;
#endif
#ifdef VERBOSE
if (status == Success)
{
ErrorF("%s: Client '%d' Connection Accepted\n", XTrapExtName,
penv->client->index);
}
#endif
return(status);
}
int XETrapDispatch(ClientPtr client)
{
REQUEST(xXTrapReq);
register int status = Success;
REQUEST_AT_LEAST_SIZE(xXTrapReq);
if (XETenv[client->index] == NULL)
{
status = XETrapCreateEnv(client);
}
if (status == Success)
{
if (stuff->minor_opcode < ASIZE(XETrapDispatchVector))
{
status =
(*(XETrapDispatchVector[stuff->minor_opcode]))(stuff,client);
}
else
{
status = BadRequest;
}
}
return(status);
}
int sXETrapDispatch(ClientPtr client)
{
REQUEST(xXTrapReq);
register int status = Success;
REQUEST_AT_LEAST_SIZE(xXTrapReq);
if (XETenv[client->index] == NULL)
{
status = XETrapCreateEnv(client);
}
if (status == Success)
{
if (stuff->minor_opcode < ASIZE(XETSwDispatchVector))
{
status =
(*(XETSwDispatchVector[stuff->minor_opcode]))(stuff,client);
}
else
{
status = BadRequest;
}
}
return(status);
}
int XETrapReset(xXTrapReq *request, ClientPtr client)
{
static xXTrapConfigReq DummyReq;
register int i;
register int status = Success;
XETrapEnv *penv = XETenv[client->index];
(void)XETrapStopTrap((xXTrapReq *)NULL, client);
penv->cur.hdr.type = X_Reply;
penv->cur.hdr.length = XEXTRA(xXTrapGetCurReply);
for (i=0L; i<ASIZE(DummyReq.config_flags_valid); i++)
{
DummyReq.config_flags_valid[i] = 0xFFL;
DummyReq.config_flags_data[i] = 0L;
}
BitSet(DummyReq.config_flags_data, XETrapGrabServer, ignore_grabs);
for (i=0L; i< ASIZE(DummyReq.config_flags_req); i++)
{
DummyReq.config_flags_req[i] = 0xFF;
}
for (i=0L; i< ASIZE(DummyReq.config_flags_event); i++)
{
DummyReq.config_flags_event[i] = 0xFF;
}
status = XETrapConfig(&DummyReq, client);
for (i=0L; i<ASIZE(penv->cur.data_state_flags); i++)
{
penv->cur.data_state_flags[i] = 0L;
}
penv->cur.data_config_max_pkt_size = XETrap_avail.data.max_pkt_size;
return(status);
}
int XETrapGetAvailable(xXTrapGetReq *request, ClientPtr client)
{
XETrapEnv *penv = XETenv[client->index];
update_protocol(request, client);
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);
}
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);
penv->cur.hdr.detail = XETrap_GetCurrent;
penv->cur.hdr.sequenceNumber = client->sequence;
WriteReplyToClient(client, rep_size, &(penv->cur));
return(Success);
}
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))
{
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);
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);
}
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;
if (BitIsTrue(vflags,XETrapEvent))
{
for (i=0L; i<ASIZE(EventProcVector); i++)
{
if (BitIsTrue(event_flags,i) &&
(BitValue(dflags,XETrapEvent) ^
(BitValue(penv->cur.data_config_flags_event,i))))
{
if (BitIsTrue(dflags,XETrapEvent))
{
if (++(vectored_events[i]) <= 1L)
{
_SwapProc(&(XETrapEventProcVector[i]),
&(EventProcVector[i]));
}
}
else
{
if (--(vectored_events[i]) <= 0L)
{
_SwapProc(&(XETrapEventProcVector[i]),
&(EventProcVector[i]));
}
}
switch(i)
{
case KeyPress:
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:
case ButtonRelease:
case MotionNotify:
XETrapPtrDev->processInputProc =
(void_function)EventProcVector[i];
XETrapPtrDev->realInputProc =
(void_function)EventProcVector[i];
break;
default:
status = BadImplementation;
break;
#endif
}
BitToggle(penv->cur.data_config_flags_event,i);
}
}
}
if ((status == Success) &&
(_CheckChangeBit(vflags,dflags,bit_flags,XETrapCmd)))
{
if (BitIsTrue(dflags, XETrapCmd))
{
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;
remove_accelerator_node(penv->client, &cmd_clients);
}
}
if ((status == Success) &&
(_CheckChangeBit(vflags,dflags,bit_flags,XETrapMaxPacket)))
{
if (BitIsTrue(dflags,XETrapMaxPacket))
{
if (request->config_max_pkt_size < XETrapMinPktSize)
{
status = BadValue;
}
else
{
penv->cur.data_config_max_pkt_size =
request->config_max_pkt_size;
}
}
else
{
penv->cur.data_config_max_pkt_size = 0xFFFF;
}
}
if (BitIsTrue(vflags,XETrapRequest) && status == Success)
{
for (i=0L; i<ASIZE(XETrapProcVector); i++)
{
if (BitIsTrue(req_flags,i) &&
(BitValue(dflags,XETrapRequest) ^
(BitValue(penv->cur.data_config_flags_req,i))))
{
if (BitIsTrue(dflags,XETrapRequest))
{
if (++(vectored_requests[i]) <= 1L)
{
_SwapProc(&(XETrapProcVector[i]), &(ProcVector[i]));
}
}
else
{
if (--(vectored_requests[i]) <= 0L)
{
_SwapProc(&(XETrapProcVector[i]), &(ProcVector[i]));
}
}
if (status == Success)
{
BitToggle(penv->cur.data_config_flags_req,i);
}
}
}
}
if (status == Success)
{
_CheckChangeBit(vflags,dflags,bit_flags,XETrapCmdKeyMod);
_CheckChangeBit(vflags,dflags,bit_flags,XETrapTimestamp);
_CheckChangeBit(vflags,dflags,bit_flags,XETrapWinXY);
#ifdef COLOR_REPLIES
_CheckChangeBit(vflags,dflags,bit_flags,XETrapColorReplies);
#endif
if (_CheckChangeBit(vflags,dflags,bit_flags,XETrapGrabServer))
{
ignore_grabs = BitValue(dflags, XETrapGrabServer);
}
}
if (status == Success)
{
if (_CheckChangeBit(vflags,dflags,bit_flags,XETrapStatistics))
{
if (BitIsTrue(dflags,XETrapStatistics))
{
if (penv->stats == NULL && (penv->stats =
(xXTrapGetStatsReply *)Xcalloc(sizeof(xXTrapGetStatsReply)))
!= NULL)
{
penv->stats->type = X_Reply;
penv->stats->length = XEXTRA(xXTrapGetStatsReply);
status = add_accelerator_node(penv->client, &stats_clients);
}
else if (penv->stats == NULL)
{
status = BadAlloc;
}
}
else
{
(void)memset(penv->stats->data.requests, 0L,
sizeof(penv->stats->data.requests));
(void)memset(penv->stats->data.events, 0L,
sizeof(penv->stats->data.events));
BitTrue(penv->cur.data_config_flags_data, XETrapStatistics);
}
}
}
return(status);
}
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);
}
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);
}
int XETrapGetVersion(xXTrapGetReq *request, ClientPtr client)
{
xXTrapGetVersReply ver_rep;
XETrapEnv *penv = XETenv[client->index];
update_protocol(request,client);
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;
WriteReplyToClient(client, sizeof(xXTrapGetVersReply), &ver_rep);
return(Success);
}
int XETrapGetLastInpTime(xXTrapReq *request, ClientPtr client)
{
xXTrapGetLITimReply tim_rep;
XETrapEnv *penv = XETenv[client->index];
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);
}
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);
INT32 csize;
if ((pdata = (XETrapDatum *)Xcalloc(size)) == NULL)
{
status = False;
}
while (ioc->next != NULL)
{
ioc = ioc->next;
penv = XETenv[ioc->client->index];
if (status == False)
{
SendErrorToClient(penv->client,XETrap_avail.data.major_opcode,
stuff->reqType, 0L, BadAlloc);
break;
}
if (BitIsTrue(penv->cur.data_config_flags_req,stuff->reqType))
{
pdata->hdr.client = client->index;
if (BitIsTrue(penv->cur.data_config_flags_data,XETrapWinXY))
{
window_ptr = (WindowPtr) LookupDrawable(stuff->id, client);
if (window_ptr == 0L)
{
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();
}
(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));
if (penv->client->swapped)
{
if (spdata == NULL)
{
if ((spdata = (XETrapDatum *)Xcalloc(size)) == NULL)
{
SendErrorToClient(penv->client,
XETrap_avail.data.major_opcode,
stuff->reqType, 0L, BadAlloc);
break;
}
memcpy(spdata,pdata,size);
if (stuff->reqType < 128)
{
(*XETSwProcVector[stuff->reqType])(&(spdata->u.req),
penv->client);
}
else if (penv->cur.data_config_max_pkt_size ==
XETrapMinPktSize)
{
XETSwResourceReq(&(spdata->u.req));
}
else
{
SendErrorToClient(penv->client,
XETrap_avail.data.major_opcode,
stuff->reqType, 0L, XETrapErrorBase + BadSwapReq);
}
}
memcpy(spdata,pdata,SIZEOF(XETrapHeader));
sXETrapHeader(&(spdata->hdr));
}
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
if (BitIsTrue(penv->cur.data_config_flags_data,XETrapColorReplies))
{
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
}
}
while (stc->next != NULL)
{
stc = stc->next;
penv = XETenv[stc->client->index];
if (BitIsTrue(penv->cur.data_config_flags_req,stuff->reqType))
{
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))
{
#ifndef NO_NEW_XTRAP
int status;
if (stuff->reqType == X_GrabServer)
{
ClientList *pclient;
status = (*XETrapProcVector[stuff->reqType])(client);
for (pclient = &io_clients; pclient; pclient = pclient->next)
if (pclient->client)
MakeClientGrabImpervious(pclient->client);
}
else
{
ClientList *pclient;
for (pclient = &io_clients; pclient; pclient = pclient->next)
if (pclient->client)
MakeClientGrabPervious(pclient->client);
status = (*XETrapProcVector[stuff->reqType])(client);
}
return status;
#else
return(Success);
#endif
}
else
{
return((*XETrapProcVector[stuff->reqType])(client));
}
}
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)
{
ErrorF("Warning! Event count != 1 (%d)\n", count);
}
#endif
while (stc->next != NULL)
{
stc = stc->next;
penv = XETenv[stc->client->index];
if (BitIsTrue(penv->cur.data_config_flags_event,type))
{
penv->stats->data.events[type]++;
}
}
#ifndef VECTORED_EVENTS
XETrapStampAndMail(x_event);
#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
{
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;
}
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;
}
}
#ifndef VECTORED_EVENTS
if ((gate_closed == False) && (key_ignore == False))
{
if (XETrapEventProcVector[type] != cur_func)
{
(void)(*XETrapEventProcVector[type])(x_event,keybd,count);
}
else
{
(void)(*EventProcVector[type])(x_event,keybd,count);
}
}
#else
if ((gate_closed == False) && (key_ignore == False))
{
(void)(*keybd_process_inp)(x_event,keybd,count);
}
else
{
XETrapStampAndMail(x_event);
}
#endif
key_ignore = False;
return 0;
}
#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)
{
ErrorF("Warning! Event count != 1 (%d)\n", count);
}
#endif
while (stc->next != NULL)
{
stc = stc->next;
penv = XETenv[stc->client->index];
if (BitIsTrue(penv->cur.data_config_flags_event,x_event->u.u.type))
{
penv->stats->data.events[x_event->u.u.type]++;
}
}
XETrapStampAndMail(x_event);
if (gate_closed == False)
{
if (XETrapEventProcVector[x_event->u.u.type] != cur_func)
{
(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
void XETrapStampAndMail(xEvent *x_event)
{
XETrapDatum data;
register CARD32 size;
XETrapEnv *penv;
ClientList *ioc = &io_clients;
while (ioc->next != NULL)
{
ioc = ioc->next;
penv = XETenv[ioc->client->index];
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;
data.hdr.screen = 0L;
data.hdr.client = 0L;
if (BitIsTrue(penv->cur.data_config_flags_data,
XETrapTimestamp))
{
data.hdr.timestamp = GetTimeInMillis();
}
size = data.hdr.count = XETrapMinPktSize;
penv->last_input_time = x_event->u.keyButtonPointer.time;
(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)
{
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));
}
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;
while (ioc->next != NULL)
{
ioc = ioc->next;
penv = XETenv[ioc->client->index];
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;
if ((current_screen < 0L) || ((x_event->u.u.type >= KeyPress) &&
(x_event->u.u.type <= MotionNotify) &&
(!x_event->u.keyButtonPointer.sameScreen)))
{
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;
penv->last_input_time = x_event->u.keyButtonPointer.time;
(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));
}
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
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;
}
int XETrapWriteXLib(XETrapEnv *penv, BYTE *data, CARD32 nbytes)
{
CARD32 size, total = 0L;
xETrapDataEvent event;
event.detail = XETrapDataStart;
event.idx = 0L;
while (nbytes > 0L)
{
size = (nbytes > sz_EventData) ? sz_EventData : nbytes;
event.type = XETrapData + XETrap_avail.data.event_base;
event.sequenceNumber = penv->client->sequence;
(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;
if (total != size)
{
event.detail = (nbytes > 0) ? XETrapDataContinued : XETrapDataLast;
}
WriteEventsToClient(penv->client, 1L, (xEvent *) &event);
event.idx++;
}
return(total);
}
static void update_protocol(xXTrapGetReq *reqptr, ClientPtr client)
{
XETrapEnv *penv = XETenv[client->index];
switch (reqptr->protocol)
{
case 31:
case XETrapProtocol:
penv->protocol = reqptr->protocol;
break;
default:
penv->protocol = 31;
break;
}
}
static void _SwapProc( register int (**f1)(), register int (**f2)())
{
register int (*t1)() = *f1;
*f1 = *f2;
*f2 = t1;
return;
}
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);
memcpy(to->data, from->data, SIZEOF(EventData));
}
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;
break;
}
else
{
accel = accel->next;
}
}
if (found == False)
{
if ((accel->next = (ClientList *)Xcalloc(sizeof(ClientList))) == NULL)
{
status = BadAlloc;
}
else
{
accel = accel->next;
accel->next = NULL;
accel->client = client;
}
}
return(status);
}
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)
{
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);
data.hdr.count = XETrapMinPktSize;
XETrapSetHeaderReply(&(data.hdr));
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;
}
if (client->swapped)
{
INT32 n;
swaps(&(crep->red), n);
swaps(&(crep->green), n);
swaps(&(crep->blue), n);
swapl(&(crep->pixel), n);
}
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)
{
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;
XETrapSetHeaderReply(&(data.hdr));
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;
}
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);
}
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)
{
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;
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;
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);
}
}
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)
{
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;
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;
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);
}
}
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