2 Copyright 1989, 1998 The Open Group
4 Permission to use, copy, modify, distribute, and sell this software and its
5 documentation for any purpose is hereby granted without fee, provided that
6 the above copyright notice appear in all copies and that both that
7 copyright notice and this permission notice appear in supporting
10 The above copyright notice and this permission notice shall be included in
11 all copies or substantial portions of the Software.
13 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
17 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
18 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20 Except as contained in this notice, the name of The Open Group shall not be
21 used in advertising or otherwise to promote the sale, use or other dealings
22 in this Software without prior written authorization from The Open Group.
27 * CloseDisplayHook package - provide callback on XCloseDisplay
30 * Author: Jim Fulton, MIT X Consortium
35 * CloseHook XmuAddCloseDisplayHook (dpy, func, arg)
37 * XmuCloseHookProc func;
40 * Bool XmuRemoveCloseDisplayHook (dpy, hook, func, arg)
43 * XmuCloseHookProc func;
46 * Bool XmuLookupCloseDisplayHook (dpy, hook, func, arg)
49 * XmuCloseHookProc func;
57 #include <stdio.h> /* for NULL */
60 #include <X11/Xmu/CloseHook.h>
66 * This is a list of display entries, each of which contains a list of callback
70 typedef struct _CallbackRec {
71 struct _CallbackRec *next; /* next link in chain */
72 XmuCloseHookProc func; /* function to call */
73 XPointer arg; /* argument to pass with function */
77 typedef struct _DisplayEntry {
78 struct _DisplayEntry *next; /* next link in chain */
79 Display *dpy; /* the display this represents */
80 int extension; /* from XAddExtension */
81 struct _CallbackRec *start, *end; /* linked list of callbacks */
82 struct _CallbackRec *calling; /* currently being called back */
88 static DisplayEntry *_FindDisplayEntry(Display*, DisplayEntry**);
89 static Bool _MakeExtension(Display*, int*);
91 static DisplayEntry *elist = NULL;
95 *****************************************************************************
96 * Public Entry Points *
97 *****************************************************************************
101 * Add - add a callback for the given display. When the display is closed,
102 * the given function will be called as:
106 * This function is declared to return an int even though the value is ignored
107 * because some compilers have problems with functions returning void.
109 * This routine returns NULL if it was unable to add the callback, otherwise
110 * it returns an untyped pointer that can be used with Remove or Lookup, but
114 XmuAddCloseDisplayHook(Display *dpy, XmuCloseHookProc func, XPointer arg)
119 /* allocate ahead of time so that we can fail atomically */
120 cb = (CallbackRec *) malloc (sizeof (CallbackRec));
121 if (!cb) return ((XPointer) NULL);
123 de = _FindDisplayEntry (dpy, NULL);
125 if ((de = (DisplayEntry *) malloc (sizeof (DisplayEntry))) == NULL ||
126 !_MakeExtension (dpy, &de->extension)) {
128 if (de) free ((char *) de);
129 return ((CloseHook) NULL);
132 de->start = de->end = NULL;
138 /* add to end of list of callback recordss */
149 return ((CloseHook) cb);
154 * Remove - get rid of a callback. If handle is non-null, use that to compare
155 * entries. Otherwise, remove first instance of the function/argument pair.
158 XmuRemoveCloseDisplayHook(Display *dpy, CloseHook handle,
159 XmuCloseHookProc func, XPointer arg)
161 DisplayEntry *de = _FindDisplayEntry (dpy, NULL);
162 register CallbackRec *h, *prev;
164 if (!de) return False;
166 /* look for handle or function/argument pair */
167 for (h = de->start, prev = NULL; h; h = h->next) {
169 if (h == (CallbackRec *) handle) break;
171 if (h->func == func && h->arg == arg) break;
175 if (!h) return False;
178 /* remove from list, watch head and tail */
179 if (de->start == h) {
182 prev->next = h->next;
184 if (de->end == h) de->end = prev;
185 if (de->calling != h) free ((char *) h);
191 * Lookup - see whether or not a handle has been installed. If handle is
192 * non-NULL, look for an entry that matches it; otherwise look for an entry
193 * with the same function/argument pair.
196 XmuLookupCloseDisplayHook(Display *dpy, CloseHook handle,
197 XmuCloseHookProc func, XPointer arg)
199 DisplayEntry *de = _FindDisplayEntry (dpy, NULL);
200 register CallbackRec *h;
202 if (!de) return False;
204 for (h = de->start; h; h = h->next) {
206 if (h == (CallbackRec *) handle) break;
208 if (h->func == func && h->arg == arg) break;
211 return (h ? True : False);
216 *****************************************************************************
217 * internal routines *
218 *****************************************************************************
223 * Find the specified display on the linked list of displays. Also return
224 * the preceeding link so that the display can be unlinked without having
227 static DisplayEntry *
228 _FindDisplayEntry(register Display *dpy, DisplayEntry **prevp)
230 register DisplayEntry *d, *prev;
232 for (d = elist, prev = NULL; d; d = d->next) {
234 if (prevp) *prevp = prev;
245 * _DoCallbacks - process all of the callbacks for this display and free
246 * the associated callback data (callback records and display entries).
250 _DoCallbacks(Display *dpy, XExtCodes *codes)
252 register CallbackRec *h;
254 DisplayEntry *de = _FindDisplayEntry (dpy, &prev);
258 /* walk the list doing the callbacks and freeing callback record */
259 for (h = de->start; h;) {
260 register CallbackRec *nexth = h->next;
261 de->calling = h; /* let remove know we'll free it */
262 (*(h->func)) (dpy, h->arg);
268 /* unlink this display from chain */
272 prev->next = de->next;
280 * _MakeExtension - create an extension for this display; done once per display
283 _MakeExtension(Display *dpy, int *extensionp)
287 codes = XAddExtension (dpy);
288 if (!codes) return False;
290 (void) XESetCloseDisplay (dpy, codes->extension, _DoCallbacks);
292 *extensionp = codes->extension;