CloseHook.c

Go to the documentation of this file.
00001 /* $Xorg: CloseHook.c,v 1.4 2001/02/09 02:03:51 xorgcvs Exp $ */
00002 
00003 /* 
00004 Copyright 1989, 1998  The Open Group
00005 
00006 Permission to use, copy, modify, distribute, and sell this software and its
00007 documentation for any purpose is hereby granted without fee, provided that
00008 the above copyright notice appear in all copies and that both that
00009 copyright notice and this permission notice appear in supporting
00010 documentation.
00011 
00012 The above copyright notice and this permission notice shall be included in
00013 all copies or substantial portions of the Software.
00014 
00015 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00016 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00017 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
00018 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
00019 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
00020 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
00021 
00022 Except as contained in this notice, the name of The Open Group shall not be
00023 used in advertising or otherwise to promote the sale, use or other dealings
00024 in this Software without prior written authorization from The Open Group.
00025 
00026 */
00027 /* $XFree86: xc/lib/Xmu/CloseHook.c,v 3.5 2001/07/25 15:04:50 dawes Exp $ */
00028 
00029 /*
00030  * CloseDisplayHook package - provide callback on XCloseDisplay
00031  *
00032  * *
00033  * Author:  Jim Fulton, MIT X Consortium
00034  * 
00035  * 
00036  *                            Public Entry Points
00037  * 
00038  * CloseHook XmuAddCloseDisplayHook (dpy, func, arg)
00039  *     Display *dpy;
00040  *     XmuCloseHookProc func;
00041  *     XPointer arg;
00042  * 
00043  * Bool XmuRemoveCloseDisplayHook (dpy, hook, func, arg)
00044  *     Display *dpy;
00045  *     CloseHook hook;
00046  *     XmuCloseHookProc func;
00047  *     XPointer arg;
00048  * 
00049  * Bool XmuLookupCloseDisplayHook (dpy, hook, func, arg)
00050  *     Display *dpy;
00051  *     CloseHook hook;
00052  *     XmuCloseHookProc func;
00053  *     XPointer arg;
00054  * 
00055  */
00056 
00057 #include <stdio.h>                                      /* for NULL */
00058 #include <X11/Xos.h>
00059 #include <X11/Xlib.h>
00060 #include <X11/Xmu/CloseHook.h>
00061 #include <stdlib.h>
00062 
00063 /*
00064  *                               Private data
00065  *
00066  * This is a list of display entries, each of which contains a list of callback
00067  * records.
00068  */
00069 
00070 typedef struct _CallbackRec {
00071     struct _CallbackRec *next;          /* next link in chain */
00072     XmuCloseHookProc func;              /* function to call */
00073     XPointer arg;                       /* argument to pass with function */
00074 } CallbackRec;
00075 
00076 
00077 typedef struct _DisplayEntry {
00078     struct _DisplayEntry *next;         /* next link in chain */
00079     Display *dpy;                       /* the display this represents */
00080     int extension;                      /* from XAddExtension */
00081     struct _CallbackRec *start, *end;   /* linked list of callbacks */
00082     struct _CallbackRec *calling;       /* currently being called back */
00083 } DisplayEntry;
00084 
00085 /*
00086  * Prototypes
00087  */
00088 static DisplayEntry *_FindDisplayEntry(Display*, DisplayEntry**);
00089 static Bool _MakeExtension(Display*, int*);
00090 
00091 static DisplayEntry *elist = NULL;
00092 
00093 
00094 /*
00095  *****************************************************************************
00096  *                            Public Entry Points                            *
00097  *****************************************************************************
00098  */
00099 
00100 /*
00101  * Add - add a callback for the given display.  When the display is closed,
00102  * the given function will be called as:
00103  *
00104  *         (*func) (dpy, arg)
00105  *
00106  * This function is declared to return an int even though the value is ignored
00107  * because some compilers have problems with functions returning void.
00108  *
00109  * This routine returns NULL if it was unable to add the callback, otherwise
00110  * it returns an untyped pointer that can be used with Remove or Lookup, but
00111  * not dereferenced.
00112  */
00113 CloseHook
00114 XmuAddCloseDisplayHook(Display *dpy, XmuCloseHookProc func, XPointer arg)
00115 {
00116     DisplayEntry *de;
00117     CallbackRec *cb;
00118 
00119     /* allocate ahead of time so that we can fail atomically */
00120     cb = (CallbackRec *) malloc (sizeof (CallbackRec));
00121     if (!cb) return ((XPointer) NULL);
00122 
00123     de = _FindDisplayEntry (dpy, NULL);
00124     if (!de) {
00125         if ((de = (DisplayEntry *) malloc (sizeof (DisplayEntry))) == NULL ||
00126             !_MakeExtension (dpy, &de->extension)) {
00127             free ((char *) cb);
00128             if (de) free ((char *) de);
00129             return ((CloseHook) NULL);
00130         }
00131         de->dpy = dpy;
00132         de->start = de->end = NULL;
00133         de->calling = NULL;
00134         de->next = elist;
00135         elist = de;
00136     }
00137 
00138     /* add to end of list of callback recordss */
00139     cb->func = func;
00140     cb->arg = arg;
00141     cb->next = NULL;
00142     if (de->end) {
00143         de->end->next = cb;
00144     } else {
00145         de->start = cb;
00146     }
00147     de->end = cb;
00148 
00149     return ((CloseHook) cb);
00150 }
00151 
00152 
00153 /*
00154  * Remove - get rid of a callback.  If handle is non-null, use that to compare
00155  * entries.  Otherwise, remove first instance of the function/argument pair.
00156  */
00157 Bool
00158 XmuRemoveCloseDisplayHook(Display *dpy, CloseHook handle,
00159                           XmuCloseHookProc func, XPointer arg)
00160 {
00161     DisplayEntry *de = _FindDisplayEntry (dpy, NULL);
00162     register CallbackRec *h, *prev;
00163 
00164     if (!de) return False;
00165 
00166     /* look for handle or function/argument pair */
00167     for (h = de->start, prev = NULL; h; h = h->next) {
00168         if (handle) {
00169             if (h == (CallbackRec *) handle) break;
00170         } else {
00171             if (h->func == func && h->arg == arg) break;
00172         }
00173         prev = h;
00174     }
00175     if (!h) return False;
00176 
00177 
00178     /* remove from list, watch head and tail */
00179     if (de->start == h) {
00180         de->start = h->next;
00181     } else {
00182         prev->next = h->next;
00183     }
00184     if (de->end == h) de->end = prev;
00185     if (de->calling != h) free ((char *) h);
00186     return True;
00187 }
00188 
00189 
00190 /*
00191  * Lookup - see whether or not a handle has been installed.  If handle is 
00192  * non-NULL, look for an entry that matches it; otherwise look for an entry 
00193  * with the same function/argument pair.
00194  */
00195 Bool
00196 XmuLookupCloseDisplayHook(Display *dpy, CloseHook handle,
00197                           XmuCloseHookProc func, XPointer arg)
00198 {
00199     DisplayEntry *de = _FindDisplayEntry (dpy, NULL);
00200     register CallbackRec *h;
00201 
00202     if (!de) return False;
00203 
00204     for (h = de->start; h; h = h->next) {
00205         if (handle) {
00206             if (h == (CallbackRec *) handle) break;
00207         } else {
00208             if (h->func == func && h->arg == arg) break;
00209         }
00210     }
00211     return (h ? True : False);
00212 }
00213 
00214 
00215 /*
00216  *****************************************************************************
00217  *                             internal routines                             *
00218  *****************************************************************************
00219  */
00220 
00221 
00222 /*
00223  * Find the specified display on the linked list of displays.  Also return
00224  * the preceeding link so that the display can be unlinked without having
00225  * back pointers.
00226  */
00227 static DisplayEntry *
00228 _FindDisplayEntry(register Display *dpy, DisplayEntry **prevp)
00229 {
00230     register DisplayEntry *d, *prev;
00231 
00232     for (d = elist, prev = NULL; d; d = d->next) {
00233         if (d->dpy == dpy) {
00234             if (prevp) *prevp = prev;
00235             return d;
00236         }
00237         prev = d;
00238     }
00239     return NULL;
00240 }
00241 
00242 
00243 
00244 /*
00245  * _DoCallbacks - process all of the callbacks for this display and free
00246  * the associated callback data (callback records and display entries).
00247  */
00248 /* ARGSUSED */
00249 static int
00250 _DoCallbacks(Display *dpy, XExtCodes *codes)
00251 {
00252     register CallbackRec *h;
00253     DisplayEntry *prev;
00254     DisplayEntry *de = _FindDisplayEntry (dpy, &prev);
00255 
00256     if (!de) return 0;
00257 
00258     /* walk the list doing the callbacks and freeing callback record */
00259     for (h = de->start; h;) {
00260         register CallbackRec *nexth = h->next;
00261         de->calling = h;                /* let remove know we'll free it */
00262         (*(h->func)) (dpy, h->arg);
00263         de->calling = NULL;
00264         free ((char *) h);
00265         h = nexth;
00266     }
00267 
00268     /* unlink this display from chain */
00269     if (elist == de) {
00270         elist = de->next;
00271     } else {
00272         prev->next = de->next;
00273     }
00274     free ((char *) de);
00275     return 1;
00276 }
00277 
00278 
00279 /*
00280  * _MakeExtension - create an extension for this display; done once per display
00281  */
00282 static Bool
00283 _MakeExtension(Display *dpy, int *extensionp)
00284 {
00285     XExtCodes *codes;
00286 
00287     codes = XAddExtension (dpy);
00288     if (!codes) return False;
00289 
00290     (void) XESetCloseDisplay (dpy, codes->extension, _DoCallbacks);
00291 
00292     *extensionp = codes->extension;
00293     return True;
00294 }

Generated on Sun Mar 4 15:03:56 2007 for Scilab [trunk] by  doxygen 1.5.1