Blame src/CloseHook.c

Packit Service 2b1f13
/*
Packit Service 2b1f13
Copyright 1989, 1998  The Open Group
Packit Service 2b1f13
Packit Service 2b1f13
Permission to use, copy, modify, distribute, and sell this software and its
Packit Service 2b1f13
documentation for any purpose is hereby granted without fee, provided that
Packit Service 2b1f13
the above copyright notice appear in all copies and that both that
Packit Service 2b1f13
copyright notice and this permission notice appear in supporting
Packit Service 2b1f13
documentation.
Packit Service 2b1f13
Packit Service 2b1f13
The above copyright notice and this permission notice shall be included in
Packit Service 2b1f13
all copies or substantial portions of the Software.
Packit Service 2b1f13
Packit Service 2b1f13
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
Packit Service 2b1f13
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
Packit Service 2b1f13
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
Packit Service 2b1f13
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
Packit Service 2b1f13
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
Packit Service 2b1f13
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
Packit Service 2b1f13
Packit Service 2b1f13
Except as contained in this notice, the name of The Open Group shall not be
Packit Service 2b1f13
used in advertising or otherwise to promote the sale, use or other dealings
Packit Service 2b1f13
in this Software without prior written authorization from The Open Group.
Packit Service 2b1f13
Packit Service 2b1f13
*/
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * CloseDisplayHook package - provide callback on XCloseDisplay
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * *
Packit Service 2b1f13
 * Author:  Jim Fulton, MIT X Consortium
Packit Service 2b1f13
 *
Packit Service 2b1f13
 *
Packit Service 2b1f13
 *			      Public Entry Points
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * CloseHook XmuAddCloseDisplayHook (dpy, func, arg)
Packit Service 2b1f13
 *     Display *dpy;
Packit Service 2b1f13
 *     XmuCloseHookProc func;
Packit Service 2b1f13
 *     XPointer arg;
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * Bool XmuRemoveCloseDisplayHook (dpy, hook, func, arg)
Packit Service 2b1f13
 *     Display *dpy;
Packit Service 2b1f13
 *     CloseHook hook;
Packit Service 2b1f13
 *     XmuCloseHookProc func;
Packit Service 2b1f13
 *     XPointer arg;
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * Bool XmuLookupCloseDisplayHook (dpy, hook, func, arg)
Packit Service 2b1f13
 *     Display *dpy;
Packit Service 2b1f13
 *     CloseHook hook;
Packit Service 2b1f13
 *     XmuCloseHookProc func;
Packit Service 2b1f13
 *     XPointer arg;
Packit Service 2b1f13
 *
Packit Service 2b1f13
 */
Packit Service 2b1f13
Packit Service 2b1f13
#ifdef HAVE_CONFIG_H
Packit Service 2b1f13
#include <config.h>
Packit Service 2b1f13
#endif
Packit Service 2b1f13
#include <stdio.h>					/* for NULL */
Packit Service 2b1f13
#include <X11/Xos.h>
Packit Service 2b1f13
#include <X11/Xlib.h>
Packit Service 2b1f13
#include <X11/Xmu/CloseHook.h>
Packit Service 2b1f13
#include <stdlib.h>
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 *				 Private data
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * This is a list of display entries, each of which contains a list of callback
Packit Service 2b1f13
 * records.
Packit Service 2b1f13
 */
Packit Service 2b1f13
Packit Service 2b1f13
typedef struct _CallbackRec {
Packit Service 2b1f13
    struct _CallbackRec *next;		/* next link in chain */
Packit Service 2b1f13
    XmuCloseHookProc func;		/* function to call */
Packit Service 2b1f13
    XPointer arg;			/* argument to pass with function */
Packit Service 2b1f13
} CallbackRec;
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
typedef struct _DisplayEntry {
Packit Service 2b1f13
    struct _DisplayEntry *next;		/* next link in chain */
Packit Service 2b1f13
    Display *dpy;			/* the display this represents */
Packit Service 2b1f13
    int extension;			/* from XAddExtension */
Packit Service 2b1f13
    struct _CallbackRec *start, *end;	/* linked list of callbacks */
Packit Service 2b1f13
    struct _CallbackRec *calling;	/* currently being called back */
Packit Service 2b1f13
} DisplayEntry;
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * Prototypes
Packit Service 2b1f13
 */
Packit Service 2b1f13
static DisplayEntry *_FindDisplayEntry(Display*, DisplayEntry**);
Packit Service 2b1f13
static Bool _MakeExtension(Display*, int*);
Packit Service 2b1f13
Packit Service 2b1f13
static DisplayEntry *elist = NULL;
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 *****************************************************************************
Packit Service 2b1f13
 *			      Public Entry Points                            *
Packit Service 2b1f13
 *****************************************************************************
Packit Service 2b1f13
 */
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * Add - add a callback for the given display.  When the display is closed,
Packit Service 2b1f13
 * the given function will be called as:
Packit Service 2b1f13
 *
Packit Service 2b1f13
 *         (*func) (dpy, arg)
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * This function is declared to return an int even though the value is ignored
Packit Service 2b1f13
 * because some compilers have problems with functions returning void.
Packit Service 2b1f13
 *
Packit Service 2b1f13
 * This routine returns NULL if it was unable to add the callback, otherwise
Packit Service 2b1f13
 * it returns an untyped pointer that can be used with Remove or Lookup, but
Packit Service 2b1f13
 * not dereferenced.
Packit Service 2b1f13
 */
Packit Service 2b1f13
CloseHook
Packit Service 2b1f13
XmuAddCloseDisplayHook(Display *dpy, XmuCloseHookProc func, XPointer arg)
Packit Service 2b1f13
{
Packit Service 2b1f13
    DisplayEntry *de;
Packit Service 2b1f13
    CallbackRec *cb;
Packit Service 2b1f13
Packit Service 2b1f13
    /* allocate ahead of time so that we can fail atomically */
Packit Service 2b1f13
    cb = (CallbackRec *) malloc (sizeof (CallbackRec));
Packit Service 2b1f13
    if (!cb) return ((XPointer) NULL);
Packit Service 2b1f13
Packit Service 2b1f13
    de = _FindDisplayEntry (dpy, NULL);
Packit Service 2b1f13
    if (!de) {
Packit Service 2b1f13
	if ((de = (DisplayEntry *) malloc (sizeof (DisplayEntry))) == NULL ||
Packit Service 2b1f13
	    !_MakeExtension (dpy, &de->extension)) {
Packit Service 2b1f13
	    free ((char *) cb);
Packit Service 2b1f13
	    if (de) free ((char *) de);
Packit Service 2b1f13
	    return ((CloseHook) NULL);
Packit Service 2b1f13
	}
Packit Service 2b1f13
	de->dpy = dpy;
Packit Service 2b1f13
	de->start = de->end = NULL;
Packit Service 2b1f13
	de->calling = NULL;
Packit Service 2b1f13
	de->next = elist;
Packit Service 2b1f13
	elist = de;
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    /* add to end of list of callback recordss */
Packit Service 2b1f13
    cb->func = func;
Packit Service 2b1f13
    cb->arg = arg;
Packit Service 2b1f13
    cb->next = NULL;
Packit Service 2b1f13
    if (de->end) {
Packit Service 2b1f13
	de->end->next = cb;
Packit Service 2b1f13
    } else {
Packit Service 2b1f13
	de->start = cb;
Packit Service 2b1f13
    }
Packit Service 2b1f13
    de->end = cb;
Packit Service 2b1f13
Packit Service 2b1f13
    return ((CloseHook) cb);
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * Remove - get rid of a callback.  If handle is non-null, use that to compare
Packit Service 2b1f13
 * entries.  Otherwise, remove first instance of the function/argument pair.
Packit Service 2b1f13
 */
Packit Service 2b1f13
Bool
Packit Service 2b1f13
XmuRemoveCloseDisplayHook(Display *dpy, CloseHook handle,
Packit Service 2b1f13
			  XmuCloseHookProc func, XPointer arg)
Packit Service 2b1f13
{
Packit Service 2b1f13
    DisplayEntry *de = _FindDisplayEntry (dpy, NULL);
Packit Service 2b1f13
    register CallbackRec *h, *prev;
Packit Service 2b1f13
Packit Service 2b1f13
    if (!de) return False;
Packit Service 2b1f13
Packit Service 2b1f13
    /* look for handle or function/argument pair */
Packit Service 2b1f13
    for (h = de->start, prev = NULL; h; h = h->next) {
Packit Service 2b1f13
	if (handle) {
Packit Service 2b1f13
	    if (h == (CallbackRec *) handle) break;
Packit Service 2b1f13
	} else {
Packit Service 2b1f13
	    if (h->func == func && h->arg == arg) break;
Packit Service 2b1f13
	}
Packit Service 2b1f13
	prev = h;
Packit Service 2b1f13
    }
Packit Service 2b1f13
    if (!h) return False;
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
    /* remove from list, watch head and tail */
Packit Service 2b1f13
    if (de->start == h) {
Packit Service 2b1f13
	de->start = h->next;
Packit Service 2b1f13
    } else {
Packit Service 2b1f13
	prev->next = h->next;
Packit Service 2b1f13
    }
Packit Service 2b1f13
    if (de->end == h) de->end = prev;
Packit Service 2b1f13
    if (de->calling != h) free ((char *) h);
Packit Service 2b1f13
    return True;
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * Lookup - see whether or not a handle has been installed.  If handle is
Packit Service 2b1f13
 * non-NULL, look for an entry that matches it; otherwise look for an entry
Packit Service 2b1f13
 * with the same function/argument pair.
Packit Service 2b1f13
 */
Packit Service 2b1f13
Bool
Packit Service 2b1f13
XmuLookupCloseDisplayHook(Display *dpy, CloseHook handle,
Packit Service 2b1f13
			  XmuCloseHookProc func, XPointer arg)
Packit Service 2b1f13
{
Packit Service 2b1f13
    DisplayEntry *de = _FindDisplayEntry (dpy, NULL);
Packit Service 2b1f13
    register CallbackRec *h;
Packit Service 2b1f13
Packit Service 2b1f13
    if (!de) return False;
Packit Service 2b1f13
Packit Service 2b1f13
    for (h = de->start; h; h = h->next) {
Packit Service 2b1f13
	if (handle) {
Packit Service 2b1f13
	    if (h == (CallbackRec *) handle) break;
Packit Service 2b1f13
	} else {
Packit Service 2b1f13
	    if (h->func == func && h->arg == arg) break;
Packit Service 2b1f13
	}
Packit Service 2b1f13
    }
Packit Service 2b1f13
    return (h ? True : False);
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 *****************************************************************************
Packit Service 2b1f13
 *			       internal routines                             *
Packit Service 2b1f13
 *****************************************************************************
Packit Service 2b1f13
 */
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * Find the specified display on the linked list of displays.  Also return
Packit Service 2b1f13
 * the preceeding link so that the display can be unlinked without having
Packit Service 2b1f13
 * back pointers.
Packit Service 2b1f13
 */
Packit Service 2b1f13
static DisplayEntry *
Packit Service 2b1f13
_FindDisplayEntry(register Display *dpy, DisplayEntry **prevp)
Packit Service 2b1f13
{
Packit Service 2b1f13
    register DisplayEntry *d, *prev;
Packit Service 2b1f13
Packit Service 2b1f13
    for (d = elist, prev = NULL; d; d = d->next) {
Packit Service 2b1f13
	if (d->dpy == dpy) {
Packit Service 2b1f13
	    if (prevp) *prevp = prev;
Packit Service 2b1f13
	    return d;
Packit Service 2b1f13
	}
Packit Service 2b1f13
	prev = d;
Packit Service 2b1f13
    }
Packit Service 2b1f13
    return NULL;
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * _DoCallbacks - process all of the callbacks for this display and free
Packit Service 2b1f13
 * the associated callback data (callback records and display entries).
Packit Service 2b1f13
 */
Packit Service 2b1f13
/* ARGSUSED */
Packit Service 2b1f13
static int
Packit Service 2b1f13
_DoCallbacks(Display *dpy, XExtCodes *codes)
Packit Service 2b1f13
{
Packit Service 2b1f13
    register CallbackRec *h;
Packit Service 2b1f13
    DisplayEntry *prev;
Packit Service 2b1f13
    DisplayEntry *de = _FindDisplayEntry (dpy, &prev;;
Packit Service 2b1f13
Packit Service 2b1f13
    if (!de) return 0;
Packit Service 2b1f13
Packit Service 2b1f13
    /* walk the list doing the callbacks and freeing callback record */
Packit Service 2b1f13
    for (h = de->start; h;) {
Packit Service 2b1f13
	register CallbackRec *nexth = h->next;
Packit Service 2b1f13
	de->calling = h;		/* let remove know we'll free it */
Packit Service 2b1f13
	(*(h->func)) (dpy, h->arg);
Packit Service 2b1f13
	de->calling = NULL;
Packit Service 2b1f13
	free ((char *) h);
Packit Service 2b1f13
	h = nexth;
Packit Service 2b1f13
    }
Packit Service 2b1f13
Packit Service 2b1f13
    /* unlink this display from chain */
Packit Service 2b1f13
    if (elist == de) {
Packit Service 2b1f13
	elist = de->next;
Packit Service 2b1f13
    } else {
Packit Service 2b1f13
	prev->next = de->next;
Packit Service 2b1f13
    }
Packit Service 2b1f13
    free ((char *) de);
Packit Service 2b1f13
    return 1;
Packit Service 2b1f13
}
Packit Service 2b1f13
Packit Service 2b1f13
Packit Service 2b1f13
/*
Packit Service 2b1f13
 * _MakeExtension - create an extension for this display; done once per display
Packit Service 2b1f13
 */
Packit Service 2b1f13
static Bool
Packit Service 2b1f13
_MakeExtension(Display *dpy, int *extensionp)
Packit Service 2b1f13
{
Packit Service 2b1f13
    XExtCodes *codes;
Packit Service 2b1f13
Packit Service 2b1f13
    codes = XAddExtension (dpy);
Packit Service 2b1f13
    if (!codes) return False;
Packit Service 2b1f13
Packit Service 2b1f13
    (void) XESetCloseDisplay (dpy, codes->extension, _DoCallbacks);
Packit Service 2b1f13
Packit Service 2b1f13
    *extensionp = codes->extension;
Packit Service 2b1f13
    return True;
Packit Service 2b1f13
}