#include "X.h"
#include "Xmd.h"
#include "misc.h"
#include "windowstr.h"
#include "dixstruct.h"
#include "pixmapstr.h"
#include "scrnintstr.h"
#define XK_LATIN1
#include "keysymdef.h"
#ifdef XCSECURITY
#define _SECURITY_SERVER
#include "security.h"
#endif
int
CompareTimeStamps(a, b)
TimeStamp a, b;
{
if (a.months < b.months)
return EARLIER;
if (a.months > b.months)
return LATER;
if (a.milliseconds < b.milliseconds)
return EARLIER;
if (a.milliseconds > b.milliseconds)
return LATER;
return SAMETIME;
}
#define HALFMONTH ((unsigned long) 1<<31)
TimeStamp
ClientTimeToServerTime(c)
CARD32 c;
{
TimeStamp ts;
if (c == CurrentTime)
return currentTime;
ts.months = currentTime.months;
ts.milliseconds = c;
if (c > currentTime.milliseconds)
{
if (((unsigned long) c - currentTime.milliseconds) > HALFMONTH)
ts.months -= 1;
}
else if (c < currentTime.milliseconds)
{
if (((unsigned long)currentTime.milliseconds - c) > HALFMONTH)
ts.months += 1;
}
return ts;
}
void
CopyISOLatin1Lowered(dest, source, length)
register unsigned char *dest, *source;
int length;
{
register int i;
for (i = 0; i < length; i++, source++, dest++)
{
if ((*source >= XK_A) && (*source <= XK_Z))
*dest = *source + (XK_a - XK_A);
else if ((*source >= XK_Agrave) && (*source <= XK_Odiaeresis))
*dest = *source + (XK_agrave - XK_Agrave);
else if ((*source >= XK_Ooblique) && (*source <= XK_Thorn))
*dest = *source + (XK_oslash - XK_Ooblique);
else
*dest = *source;
}
*dest = '\0';
}
#ifdef XCSECURITY
WindowPtr
SecurityLookupWindow(rid, client, access_mode)
XID rid;
ClientPtr client;
Mask access_mode;
{
WindowPtr pWin;
client->errorValue = rid;
if(rid == INVALID)
return NULL;
if (client->trustLevel != XSecurityClientTrusted)
return (WindowPtr)SecurityLookupIDByType(client, rid, RT_WINDOW, access_mode);
if (client->lastDrawableID == rid)
{
if (client->lastDrawable->type == DRAWABLE_WINDOW)
return ((WindowPtr) client->lastDrawable);
return (WindowPtr) NULL;
}
pWin = (WindowPtr)SecurityLookupIDByType(client, rid, RT_WINDOW, access_mode);
if (pWin && pWin->drawable.type == DRAWABLE_WINDOW) {
client->lastDrawable = (DrawablePtr) pWin;
client->lastDrawableID = rid;
client->lastGCID = INVALID;
client->lastGC = (GCPtr)NULL;
}
return pWin;
}
pointer
SecurityLookupDrawable(rid, client, access_mode)
XID rid;
ClientPtr client;
Mask access_mode;
{
register DrawablePtr pDraw;
if(rid == INVALID)
return (pointer) NULL;
if (client->trustLevel != XSecurityClientTrusted)
return (DrawablePtr)SecurityLookupIDByClass(client, rid, RC_DRAWABLE,
access_mode);
if (client->lastDrawableID == rid)
return ((pointer) client->lastDrawable);
pDraw = (DrawablePtr)SecurityLookupIDByClass(client, rid, RC_DRAWABLE,
access_mode);
if (pDraw && (pDraw->type != UNDRAWABLE_WINDOW))
return (pointer)pDraw;
return (pointer)NULL;
}
WindowPtr
LookupWindow(rid, client)
XID rid;
ClientPtr client;
{
return SecurityLookupWindow(rid, client, SecurityUnknownAccess);
}
pointer
LookupDrawable(rid, client)
XID rid;
ClientPtr client;
{
return SecurityLookupDrawable(rid, client, SecurityUnknownAccess);
}
#else
WindowPtr
LookupWindow(rid, client)
XID rid;
ClientPtr client;
{
WindowPtr pWin;
client->errorValue = rid;
if(rid == INVALID)
return NULL;
if (client->lastDrawableID == rid)
{
if (client->lastDrawable->type == DRAWABLE_WINDOW)
return ((WindowPtr) client->lastDrawable);
return (WindowPtr) NULL;
}
pWin = (WindowPtr)LookupIDByType(rid, RT_WINDOW);
if (pWin && pWin->drawable.type == DRAWABLE_WINDOW) {
client->lastDrawable = (DrawablePtr) pWin;
client->lastDrawableID = rid;
client->lastGCID = INVALID;
client->lastGC = (GCPtr)NULL;
}
return pWin;
}
pointer
LookupDrawable(rid, client)
XID rid;
ClientPtr client;
{
register DrawablePtr pDraw;
if(rid == INVALID)
return (pointer) NULL;
if (client->lastDrawableID == rid)
return ((pointer) client->lastDrawable);
pDraw = (DrawablePtr)LookupIDByClass(rid, RC_DRAWABLE);
if (pDraw && (pDraw->type != UNDRAWABLE_WINDOW))
return (pointer)pDraw;
return (pointer)NULL;
}
#endif
ClientPtr
LookupClient(rid, client)
XID rid;
ClientPtr client;
{
pointer pRes = (pointer)SecurityLookupIDByClass(client, rid, RC_ANY,
SecurityReadAccess);
int clientIndex = CLIENT_ID(rid);
if (clientIndex && pRes && clients[clientIndex] && !(rid & SERVER_BIT))
{
return clients[clientIndex];
}
return (ClientPtr)NULL;
}
int
AlterSaveSetForClient(client, pWin, mode)
ClientPtr client;
WindowPtr pWin;
unsigned mode;
{
int numnow;
pointer *pTmp = NULL;
int j;
numnow = client->numSaved;
j = 0;
if (numnow)
{
pTmp = client->saveSet;
while ((j < numnow) && (pTmp[j] != (pointer)pWin))
j++;
}
if (mode == SetModeInsert)
{
if (j < numnow)
return(Success);
numnow++;
pTmp = (pointer *)xrealloc(client->saveSet, sizeof(pointer) * numnow);
if (!pTmp)
return(BadAlloc);
client->saveSet = pTmp;
client->numSaved = numnow;
client->saveSet[numnow - 1] = (pointer)pWin;
return(Success);
}
else if ((mode == SetModeDelete) && (j < numnow))
{
while (j < numnow-1)
{
pTmp[j] = pTmp[j+1];
j++;
}
numnow--;
if (numnow)
{
pTmp = (pointer *)xrealloc(client->saveSet,
sizeof(pointer) * numnow);
if (pTmp)
client->saveSet = pTmp;
}
else
{
xfree(client->saveSet);
client->saveSet = (pointer *)NULL;
}
client->numSaved = numnow;
return(Success);
}
return(Success);
}
void
DeleteWindowFromAnySaveSet(pWin)
WindowPtr pWin;
{
register int i;
register ClientPtr client;
for (i = 0; i< currentMaxClients; i++)
{
client = clients[i];
if (client && client->numSaved)
(void)AlterSaveSetForClient(client, pWin, SetModeDelete);
}
}
void
NoopDDA(void)
{
}
typedef struct _BlockHandler {
BlockHandlerProcPtr BlockHandler;
WakeupHandlerProcPtr WakeupHandler;
pointer blockData;
Bool deleted;
} BlockHandlerRec, *BlockHandlerPtr;
static BlockHandlerPtr handlers;
static int numHandlers;
static int sizeHandlers;
static Bool inHandler;
static Bool handlerDeleted;
void
BlockHandler(pTimeout, pReadmask)
pointer pTimeout;
pointer pReadmask;
{
register int i, j;
++inHandler;
for (i = 0; i < screenInfo.numScreens; i++)
(* screenInfo.screens[i]->BlockHandler)(i,
screenInfo.screens[i]->blockData,
pTimeout, pReadmask);
for (i = 0; i < numHandlers; i++)
(*handlers[i].BlockHandler) (handlers[i].blockData,
pTimeout, pReadmask);
if (handlerDeleted)
{
for (i = 0; i < numHandlers;)
if (handlers[i].deleted)
{
for (j = i; j < numHandlers - 1; j++)
handlers[j] = handlers[j+1];
numHandlers--;
}
else
i++;
handlerDeleted = FALSE;
}
--inHandler;
}
void
WakeupHandler(result, pReadmask)
int result;
pointer pReadmask;
{
register int i, j;
++inHandler;
for (i = numHandlers - 1; i >= 0; i--)
(*handlers[i].WakeupHandler) (handlers[i].blockData,
result, pReadmask);
for (i = 0; i < screenInfo.numScreens; i++)
(* screenInfo.screens[i]->WakeupHandler)(i,
screenInfo.screens[i]->wakeupData,
result, pReadmask);
if (handlerDeleted)
{
for (i = 0; i < numHandlers;)
if (handlers[i].deleted)
{
for (j = i; j < numHandlers - 1; j++)
handlers[j] = handlers[j+1];
numHandlers--;
}
else
i++;
handlerDeleted = FALSE;
}
--inHandler;
}
Bool
RegisterBlockAndWakeupHandlers (blockHandler, wakeupHandler, blockData)
BlockHandlerProcPtr blockHandler;
WakeupHandlerProcPtr wakeupHandler;
pointer blockData;
{
BlockHandlerPtr new;
if (numHandlers >= sizeHandlers)
{
new = (BlockHandlerPtr) xrealloc (handlers, (numHandlers + 1) *
sizeof (BlockHandlerRec));
if (!new)
return FALSE;
handlers = new;
sizeHandlers = numHandlers + 1;
}
handlers[numHandlers].BlockHandler = blockHandler;
handlers[numHandlers].WakeupHandler = wakeupHandler;
handlers[numHandlers].blockData = blockData;
handlers[numHandlers].deleted = FALSE;
numHandlers = numHandlers + 1;
return TRUE;
}
void
RemoveBlockAndWakeupHandlers (blockHandler, wakeupHandler, blockData)
BlockHandlerProcPtr blockHandler;
WakeupHandlerProcPtr wakeupHandler;
pointer blockData;
{
int i;
for (i = 0; i < numHandlers; i++)
if (handlers[i].BlockHandler == blockHandler &&
handlers[i].WakeupHandler == wakeupHandler &&
handlers[i].blockData == blockData)
{
if (inHandler)
{
handlerDeleted = TRUE;
handlers[i].deleted = TRUE;
}
else
{
for (; i < numHandlers - 1; i++)
handlers[i] = handlers[i+1];
numHandlers--;
}
break;
}
}
void
InitBlockAndWakeupHandlers ()
{
xfree (handlers);
handlers = (BlockHandlerPtr) 0;
numHandlers = 0;
sizeHandlers = 0;
}
WorkQueuePtr workQueue;
static WorkQueuePtr *workQueueLast = &workQueue;
void
ProcessWorkQueue(void)
{
WorkQueuePtr q, *p;
p = &workQueue;
while ((q = *p))
{
if ((*q->function) (q->client, q->closure))
{
*p = q->next;
xfree (q);
}
else
{
p = &q->next;
}
}
workQueueLast = p;
}
void
ProcessWorkQueueZombies(void)
{
WorkQueuePtr q, *p;
p = &workQueue;
while ((q = *p))
{
if (q->client && q->client->clientGone)
{
(void) (*q->function) (q->client, q->closure);
*p = q->next;
xfree (q);
}
else
{
p = &q->next;
}
}
workQueueLast = p;
}
Bool
QueueWorkProc (
Bool (*function)(
ClientPtr ,
pointer
),
ClientPtr client,
pointer closure)
{
WorkQueuePtr q;
q = (WorkQueuePtr) xalloc (sizeof *q);
if (!q)
return FALSE;
q->function = function;
q->client = client;
q->closure = closure;
q->next = NULL;
*workQueueLast = q;
workQueueLast = &q->next;
return TRUE;
}
typedef struct _SleepQueue {
struct _SleepQueue *next;
ClientPtr client;
ClientSleepProcPtr function;
pointer closure;
} SleepQueueRec, *SleepQueuePtr;
static SleepQueuePtr sleepQueue = NULL;
Bool
ClientSleep (client, function, closure)
ClientPtr client;
ClientSleepProcPtr function;
pointer closure;
{
SleepQueuePtr q;
q = (SleepQueuePtr) xalloc (sizeof *q);
if (!q)
return FALSE;
IgnoreClient (client);
q->next = sleepQueue;
q->client = client;
q->function = function;
q->closure = closure;
sleepQueue = q;
return TRUE;
}
Bool
ClientSignal (client)
ClientPtr client;
{
SleepQueuePtr q;
for (q = sleepQueue; q; q = q->next)
if (q->client == client)
{
return QueueWorkProc (q->function, q->client, q->closure);
}
return FALSE;
}
void
ClientWakeup (client)
ClientPtr client;
{
SleepQueuePtr q, *prev;
prev = &sleepQueue;
while ( (q = *prev) )
{
if (q->client == client)
{
*prev = q->next;
xfree (q);
if (client->clientGone)
;
else
AttendClient (client);
break;
}
prev = &q->next;
}
}
Bool
ClientIsAsleep (client)
ClientPtr client;
{
SleepQueuePtr q;
for (q = sleepQueue; q; q = q->next)
if (q->client == client)
return TRUE;
return FALSE;
}
static int numCallbackListsToCleanup = 0;
static CallbackListPtr **listsToCleanup = NULL;
static Bool
_AddCallback(
CallbackListPtr *pcbl,
CallbackProcPtr callback,
pointer data)
{
CallbackPtr cbr;
cbr = (CallbackPtr) xalloc(sizeof(CallbackRec));
if (!cbr)
return FALSE;
cbr->proc = callback;
cbr->data = data;
cbr->next = (*pcbl)->list;
cbr->deleted = FALSE;
(*pcbl)->list = cbr;
return TRUE;
}
static Bool
_DeleteCallback(
CallbackListPtr *pcbl,
CallbackProcPtr callback,
pointer data)
{
CallbackListPtr cbl = *pcbl;
CallbackPtr cbr, pcbr;
for (pcbr = NULL, cbr = cbl->list;
cbr != NULL;
pcbr = cbr, cbr = cbr->next)
{
if ((cbr->proc == callback) && (cbr->data == data))
break;
}
if (cbr != NULL)
{
if (cbl->inCallback)
{
++(cbl->numDeleted);
cbr->deleted = TRUE;
}
else
{
if (pcbr == NULL)
cbl->list = cbr->next;
else
pcbr->next = cbr->next;
xfree(cbr);
}
return TRUE;
}
return FALSE;
}
static void
_CallCallbacks(
CallbackListPtr *pcbl,
pointer call_data)
{
CallbackListPtr cbl = *pcbl;
CallbackPtr cbr, pcbr;
++(cbl->inCallback);
for (cbr = cbl->list; cbr != NULL; cbr = cbr->next)
{
(*(cbr->proc)) (pcbl, cbr->data, call_data);
}
--(cbl->inCallback);
if (cbl->inCallback) return;
if (cbl->deleted)
{
DeleteCallbackList(pcbl);
return;
}
if (cbl->numDeleted)
{
for (pcbr = NULL, cbr = cbl->list; (cbr != NULL) && cbl->numDeleted; )
{
if (cbr->deleted)
{
if (pcbr)
{
cbr = cbr->next;
xfree(pcbr->next);
pcbr->next = cbr;
} else
{
cbr = cbr->next;
xfree(cbl->list);
cbl->list = cbr;
}
cbl->numDeleted--;
}
else
{
pcbr = cbr;
cbr = cbr->next;
}
}
}
}
static void
_DeleteCallbackList(
CallbackListPtr *pcbl)
{
CallbackListPtr cbl = *pcbl;
CallbackPtr cbr, nextcbr;
int i;
if (cbl->inCallback)
{
cbl->deleted = TRUE;
return;
}
for (i = 0; i < numCallbackListsToCleanup; i++)
{
if ((listsToCleanup[i] = pcbl) != 0)
{
listsToCleanup[i] = NULL;
break;
}
}
for (cbr = cbl->list; cbr != NULL; cbr = nextcbr)
{
nextcbr = cbr->next;
xfree(cbr);
}
xfree(cbl);
*pcbl = NULL;
}
static CallbackFuncsRec default_cbfuncs =
{
_AddCallback,
_DeleteCallback,
_CallCallbacks,
_DeleteCallbackList
};
Bool
CreateCallbackList(pcbl, cbfuncs)
CallbackListPtr *pcbl;
CallbackFuncsPtr cbfuncs;
{
CallbackListPtr cbl;
int i;
if (!pcbl) return FALSE;
cbl = (CallbackListPtr) xalloc(sizeof(CallbackListRec));
if (!cbl) return FALSE;
cbl->funcs = cbfuncs ? *cbfuncs : default_cbfuncs;
cbl->inCallback = 0;
cbl->deleted = FALSE;
cbl->numDeleted = 0;
cbl->list = NULL;
*pcbl = cbl;
for (i = 0; i < numCallbackListsToCleanup; i++)
{
if (!listsToCleanup[i])
{
listsToCleanup[i] = pcbl;
return TRUE;
}
}
listsToCleanup = (CallbackListPtr **)xnfrealloc(listsToCleanup,
sizeof(CallbackListPtr *) * (numCallbackListsToCleanup+1));
listsToCleanup[numCallbackListsToCleanup] = pcbl;
numCallbackListsToCleanup++;
return TRUE;
}
Bool
AddCallback(pcbl, callback, data)
CallbackListPtr *pcbl;
CallbackProcPtr callback;
pointer data;
{
if (!pcbl) return FALSE;
if (!*pcbl)
{
if (!CreateCallbackList(pcbl, (CallbackFuncsPtr)NULL))
return FALSE;
}
return ((*(*pcbl)->funcs.AddCallback) (pcbl, callback, data));
}
Bool
DeleteCallback(pcbl, callback, data)
CallbackListPtr *pcbl;
CallbackProcPtr callback;
pointer data;
{
if (!pcbl || !*pcbl) return FALSE;
return ((*(*pcbl)->funcs.DeleteCallback) (pcbl, callback, data));
}
void
CallCallbacks(pcbl, call_data)
CallbackListPtr *pcbl;
pointer call_data;
{
if (!pcbl || !*pcbl) return;
(*(*pcbl)->funcs.CallCallbacks) (pcbl, call_data);
}
void
DeleteCallbackList(pcbl)
CallbackListPtr *pcbl;
{
if (!pcbl || !*pcbl) return;
(*(*pcbl)->funcs.DeleteCallbackList) (pcbl);
}
void
InitCallbackManager()
{
int i;
for (i = 0; i < numCallbackListsToCleanup; i++)
{
DeleteCallbackList(listsToCleanup[i]);
}
if (listsToCleanup) xfree(listsToCleanup);
numCallbackListsToCleanup = 0;
listsToCleanup = NULL;
}