X-Git-Url: https://git.sesse.net/?p=rdpsrv;a=blobdiff_plain;f=Xserver%2Fprograms%2FXserver%2Fdix%2Fdixutils.c;fp=Xserver%2Fprograms%2FXserver%2Fdix%2Fdixutils.c;h=0000000000000000000000000000000000000000;hp=edabfd73572b17745d87e0591229e14270ae6767;hb=ce66b81460e5353db09d45c02339d4583fbda255;hpb=7772d71ffd742cfc9b7ff214659d16c5bb56a391 diff --git a/Xserver/programs/Xserver/dix/dixutils.c b/Xserver/programs/Xserver/dix/dixutils.c deleted file mode 100644 index edabfd7..0000000 --- a/Xserver/programs/Xserver/dix/dixutils.c +++ /dev/null @@ -1,1011 +0,0 @@ -/*********************************************************** - -Copyright (c) 1987 X Consortium - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of the X Consortium shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from the X Consortium. - - -Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -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 DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL 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. - -******************************************************************/ - -/* - -(c)Copyright 1988,1991 Adobe Systems Incorporated. All rights reserved. - -Permission to use, copy, modify, distribute, and sublicense this software and its -documentation for any purpose and without fee is hereby granted, provided that -the above copyright notices appear in all copies and that both those copyright -notices and this permission notice appear in supporting documentation and that -the name of Adobe Systems Incorporated not be used in advertising or publicity -pertaining to distribution of the software without specific, written prior -permission. No trademark license to use the Adobe trademarks is hereby -granted. If the Adobe trademark "Display PostScript"(tm) is used to describe -this software, its functionality or for any other purpose, such use shall be -limited to a statement that this software works in conjunction with the Display -PostScript system. Proper trademark attribution to reflect Adobe's ownership -of the trademark shall be given whenever any such reference to the Display -PostScript system is made. - -ADOBE MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THE SOFTWARE FOR ANY -PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. ADOBE -DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED -WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON- -INFRINGEMENT OF THIRD PARTY RIGHTS. IN NO EVENT SHALL ADOBE BE LIABLE TO YOU -OR ANY OTHER PARTY FOR ANY SPECIAL, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY -DAMAGES WHATSOEVER WHETHER IN AN ACTION OF CONTRACT,NEGLIGENCE, STRICT -LIABILITY OR ANY OTHER ACTION ARISING OUT OF OR IN CONNECTION WITH THE USE OR -PERFORMANCE OF THIS SOFTWARE. ADOBE WILL NOT PROVIDE ANY TRAINING OR OTHER -SUPPORT FOR THE SOFTWARE. - -Adobe, PostScript, and Display PostScript are trademarks of Adobe Systems -Incorporated which may be registered in certain jurisdictions. - -Author: Adobe Systems Incorporated - -*/ - -/* $TOG: dixutils.c /main/33 1997/05/22 10:02:20 kaleb $ */ - - - - -/* $XFree86: xc/programs/Xserver/dix/dixutils.c,v 3.1.2.1 1997/05/23 12:19:35 dawes Exp $ */ - -#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 "extensions/security.h" -#endif - -/* - * CompareTimeStamps returns -1, 0, or +1 depending on if the first - * argument is less than, equal to or greater than the second argument. - */ - -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; -} - -/* - * convert client times to server TimeStamps - */ - -#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; -} - -/* - * ISO Latin-1 case conversion routine - * - * this routine always null-terminates the result, so - * beware of too-small buffers - */ - -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 - -/* SecurityLookupWindow and SecurityLookupDrawable: - * Look up the window/drawable taking into account the client doing - * the lookup and the type of access desired. Return the window/drawable - * if it exists and the client is allowed access, else return NULL. - * Most Proc* functions should be calling these instead of - * LookupWindow and LookupDrawable, which do no access checks. - */ - -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; -} - -/* We can't replace the LookupWindow and LookupDrawable functions with - * macros because of compatibility with loadable servers. - */ - -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 /* not XCSECURITY */ - -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 /* XCSECURITY */ - -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; - 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) /* duplicate */ - 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); - } -} - -/* No-op Don't Do Anything : sometimes we need to be able to call a procedure - * that doesn't do anything. For example, on screen with only static - * colormaps, if someone calls install colormap, it's easier to have a dummy - * procedure to call than to check if there's a procedure - */ -void -NoopDDA( -#if NeedVarargsPrototypes - void* f, ... -#endif -) -{ -} - -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; - -/* called from the OS layer */ -void -BlockHandler(pTimeout, pReadmask) -pointer pTimeout; /* DIX doesn't want to know how OS represents time */ -pointer pReadmask; /* nor how it represents the set of descriptors */ -{ - 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; /* 32 bits of undefined result from the wait */ -pointer pReadmask; /* the resulting descriptor mask */ -{ - 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; -} - -/* Reentrant with BlockHandler and WakeupHandler, except wakeup won't - * get called until next time - */ - -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; -} - -/* - * A general work queue. Perform some task before the server - * sleeps for input. - */ - -WorkQueuePtr workQueue; -static WorkQueuePtr *workQueueLast = &workQueue; - -void -ProcessWorkQueue() -{ - WorkQueuePtr q, *p; - - p = &workQueue; - /* - * Scan the work queue once, calling each function. Those - * which return TRUE are removed from the queue, otherwise - * they will be called again. This must be reentrant with - * QueueWorkProc. - */ - while (q = *p) - { - if ((*q->function) (q->client, q->closure)) - { - /* remove q from the list */ - *p = q->next; /* don't fetch until after func called */ - xfree (q); - } - else - { - p = &q->next; /* don't fetch until after func called */ - } - } - workQueueLast = p; -} - -void -ProcessWorkQueueZombies() -{ - WorkQueuePtr q, *p; - - p = &workQueue; - while (q = *p) - { - if (q->client && q->client->clientGone) - { - (void) (*q->function) (q->client, q->closure); - /* remove q from the list */ - *p = q->next; /* don't fetch until after func called */ - xfree (q); - } - else - { - p = &q->next; /* don't fetch until after func called */ - } - } - workQueueLast = p; -} - -Bool -#if NeedFunctionPrototypes -QueueWorkProc ( - Bool (*function)( -#if NeedNestedPrototypes - ClientPtr /* pClient */, - pointer /* closure */ -#endif - ), - ClientPtr client, - pointer closure) -#else -QueueWorkProc (function, client, closure) - Bool (*function)(); - ClientPtr client; - pointer closure; -#endif -{ - 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; -} - -/* - * Manage a queue of sleeping clients, awakening them - * when requested, by using the OS functions IgnoreClient - * and AttendClient. Note that this *ignores* the troubles - * with request data interleaving itself with events, but - * we'll leave that until a later time. - */ - -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) - CloseDownClient(client); - 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; -} - -/* - * Generic Callback Manager - */ - -/* ===== Private Procedures ===== */ - -static int numCallbackListsToCleanup = 0; -static CallbackListPtr **listsToCleanup = NULL; - -static Bool -#if NeedFunctionPrototypes -_AddCallback( - CallbackListPtr *pcbl, - CallbackProcPtr callback, - pointer data) -#else -_AddCallback(pcbl, callback, data) - CallbackListPtr *pcbl; - CallbackProcPtr callback; - pointer data; -#endif -{ - 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 -#if NeedFunctionPrototypes -_DeleteCallback( - CallbackListPtr *pcbl, - CallbackProcPtr callback, - pointer data) -#else -_DeleteCallback(pcbl, callback, data) - CallbackListPtr *pcbl; - CallbackProcPtr callback; - pointer data; -#endif -{ - 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 -#if NeedFunctionPrototypes -_CallCallbacks( - CallbackListPtr *pcbl, - pointer call_data) -#else -_CallCallbacks(pcbl, call_data) - CallbackListPtr *pcbl; - pointer call_data; -#endif -{ - 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; - - /* Was the entire list marked for deletion? */ - - if (cbl->deleted) - { - DeleteCallbackList(pcbl); - return; - } - - /* Were some individual callbacks on the list marked for deletion? - * If so, do the deletions. - */ - - 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 /* this one wasn't deleted */ - { - pcbr = cbr; - cbr = cbr->next; - } - } - } -} - -static void -#if NeedFunctionPrototypes -_DeleteCallbackList( - CallbackListPtr *pcbl) -#else -_DeleteCallbackList(pcbl) - CallbackListPtr *pcbl; -#endif -{ - 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 -}; - -/* ===== Public Procedures ===== */ - -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) - { /* list hasn't been created yet; go create it */ - 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; -}