extutil.c revision c585b9bd
1caade7ccSmrg/* 2caade7ccSmrg * $Xorg: extutil.c,v 1.4 2001/02/09 02:03:49 xorgcvs Exp $ 3caade7ccSmrg * 4caade7ccSmrgCopyright 1989, 1998 The Open Group 5caade7ccSmrg 6caade7ccSmrgPermission to use, copy, modify, distribute, and sell this software and its 7caade7ccSmrgdocumentation for any purpose is hereby granted without fee, provided that 8caade7ccSmrgthe above copyright notice appear in all copies and that both that 9caade7ccSmrgcopyright notice and this permission notice appear in supporting 10caade7ccSmrgdocumentation. 11caade7ccSmrg 12caade7ccSmrgThe above copyright notice and this permission notice shall be included in 13caade7ccSmrgall copies or substantial portions of the Software. 14caade7ccSmrg 15caade7ccSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16caade7ccSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17caade7ccSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18caade7ccSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 19caade7ccSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20caade7ccSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21caade7ccSmrg 22caade7ccSmrgExcept as contained in this notice, the name of The Open Group shall not be 23caade7ccSmrgused in advertising or otherwise to promote the sale, use or other dealings 24caade7ccSmrgin this Software without prior written authorization from The Open Group. 25caade7ccSmrg * 26caade7ccSmrg * Author: Jim Fulton, MIT X Consortium 27caade7ccSmrg * 28caade7ccSmrg * 29caade7ccSmrg * Xlib Extension-Writing Utilities 30caade7ccSmrg * 31caade7ccSmrg * This package contains utilities for writing the client API for various 32caade7ccSmrg * protocol extensions. THESE INTERFACES ARE NOT PART OF THE X STANDARD AND 33caade7ccSmrg * ARE SUBJECT TO CHANGE! 34caade7ccSmrg * 35caade7ccSmrg * Routines include: 36caade7ccSmrg * 37caade7ccSmrg * XextCreateExtension called once per extension 38caade7ccSmrg * XextDestroyExtension if no longer using extension 39caade7ccSmrg * XextAddDisplay add another display 40caade7ccSmrg * XextRemoveDisplay remove a display 41caade7ccSmrg * XextFindDisplay is a display open 42caade7ccSmrg * 43caade7ccSmrg * In addition, the following Xlib-style interfaces are provided: 44caade7ccSmrg * 45caade7ccSmrg * XSetExtensionErrorHandler establish an extension error handler 46caade7ccSmrg * XMissingExtension raise an error about missing ext 47caade7ccSmrg */ 48caade7ccSmrg/* $XFree86: xc/lib/Xext/extutil.c,v 1.5 2002/10/16 00:37:27 dawes Exp $ */ 49caade7ccSmrg 50caade7ccSmrg#ifdef HAVE_CONFIG_H 51caade7ccSmrg#include <config.h> 52caade7ccSmrg#endif 53caade7ccSmrg#include <stdio.h> 54caade7ccSmrg#include <X11/Xlibint.h> 55caade7ccSmrg#include <X11/extensions/Xext.h> 56caade7ccSmrg#include <X11/extensions/extutil.h> 57caade7ccSmrg 58caade7ccSmrg 59caade7ccSmrg/* 60caade7ccSmrg * XextCreateExtension - return an extension descriptor containing context 61caade7ccSmrg * information for this extension. This object is passed to all Xext 62caade7ccSmrg * routines. 63caade7ccSmrg */ 64caade7ccSmrgXExtensionInfo *XextCreateExtension (void) 65caade7ccSmrg{ 66caade7ccSmrg register XExtensionInfo *info = 67caade7ccSmrg (XExtensionInfo *) Xmalloc (sizeof (XExtensionInfo)); 68caade7ccSmrg 69caade7ccSmrg if (info) { 70caade7ccSmrg info->head = NULL; 71caade7ccSmrg info->cur = NULL; 72caade7ccSmrg info->ndisplays = 0; 73caade7ccSmrg } 74caade7ccSmrg return info; 75caade7ccSmrg} 76caade7ccSmrg 77caade7ccSmrg 78caade7ccSmrg/* 79caade7ccSmrg * XextDestroyExtension - free memory the given extension descriptor 80caade7ccSmrg */ 81caade7ccSmrgvoid XextDestroyExtension (XExtensionInfo *info) 82caade7ccSmrg{ 83caade7ccSmrg info->head = NULL; /* to catch refs after this */ 84caade7ccSmrg info->cur = NULL; 85caade7ccSmrg info->ndisplays = 0; 86caade7ccSmrg XFree ((char *) info); 87caade7ccSmrg} 88caade7ccSmrg 89caade7ccSmrg 90caade7ccSmrg 91caade7ccSmrg/* 92caade7ccSmrg * XextAddDisplay - add a display to this extension 93caade7ccSmrg */ 94caade7ccSmrgXExtDisplayInfo *XextAddDisplay ( 95caade7ccSmrg XExtensionInfo *extinfo, 96caade7ccSmrg Display *dpy, 97caade7ccSmrg char *ext_name, 98caade7ccSmrg XExtensionHooks *hooks, 99caade7ccSmrg int nevents, 100caade7ccSmrg XPointer data) 101caade7ccSmrg{ 102caade7ccSmrg XExtDisplayInfo *dpyinfo; 103caade7ccSmrg 104caade7ccSmrg dpyinfo = (XExtDisplayInfo *) Xmalloc (sizeof (XExtDisplayInfo)); 105caade7ccSmrg if (!dpyinfo) return NULL; 106caade7ccSmrg dpyinfo->display = dpy; 107caade7ccSmrg dpyinfo->data = data; 108caade7ccSmrg dpyinfo->codes = XInitExtension (dpy, ext_name); 109caade7ccSmrg 110caade7ccSmrg /* 111caade7ccSmrg * if the server has the extension, then we can initialize the 112caade7ccSmrg * appropriate function vectors 113caade7ccSmrg */ 114caade7ccSmrg if (dpyinfo->codes) { 115caade7ccSmrg int i, j; 116caade7ccSmrg 117caade7ccSmrg for (i = 0, j = dpyinfo->codes->first_event; i < nevents; i++, j++) { 118caade7ccSmrg XESetWireToEvent (dpy, j, hooks->wire_to_event); 119caade7ccSmrg XESetEventToWire (dpy, j, hooks->event_to_wire); 120caade7ccSmrg } 121caade7ccSmrg if (hooks->create_gc) 122caade7ccSmrg XESetCreateGC (dpy, dpyinfo->codes->extension, hooks->create_gc); 123caade7ccSmrg if (hooks->copy_gc) 124caade7ccSmrg XESetCopyGC (dpy, dpyinfo->codes->extension, hooks->copy_gc); 125caade7ccSmrg if (hooks->flush_gc) 126caade7ccSmrg XESetFlushGC (dpy, dpyinfo->codes->extension, hooks->flush_gc); 127caade7ccSmrg if (hooks->free_gc) 128caade7ccSmrg XESetFreeGC (dpy, dpyinfo->codes->extension, hooks->free_gc); 129caade7ccSmrg if (hooks->create_font) 130caade7ccSmrg XESetCreateFont (dpy, dpyinfo->codes->extension, hooks->create_font); 131caade7ccSmrg if (hooks->free_font) 132caade7ccSmrg XESetFreeFont (dpy, dpyinfo->codes->extension, hooks->free_font); 133caade7ccSmrg if (hooks->close_display) 134caade7ccSmrg XESetCloseDisplay (dpy, dpyinfo->codes->extension, 135caade7ccSmrg hooks->close_display); 136caade7ccSmrg if (hooks->error) 137caade7ccSmrg XESetError (dpy, dpyinfo->codes->extension, hooks->error); 138caade7ccSmrg if (hooks->error_string) 139caade7ccSmrg XESetErrorString (dpy, dpyinfo->codes->extension, 140caade7ccSmrg hooks->error_string); 141caade7ccSmrg } else if (hooks->close_display) { 142caade7ccSmrg /* The server doesn't have this extension. 143caade7ccSmrg * Use a private Xlib-internal extension to hang the close_display 144caade7ccSmrg * hook on so that the "cache" (extinfo->cur) is properly cleaned. 145caade7ccSmrg * (XBUG 7955) 146caade7ccSmrg */ 147caade7ccSmrg XExtCodes *codes = XAddExtension(dpy); 148caade7ccSmrg if (!codes) { 149caade7ccSmrg XFree(dpyinfo); 150caade7ccSmrg return NULL; 151caade7ccSmrg } 152caade7ccSmrg XESetCloseDisplay (dpy, codes->extension, hooks->close_display); 153caade7ccSmrg } 154caade7ccSmrg 155caade7ccSmrg /* 156caade7ccSmrg * now, chain it onto the list 157caade7ccSmrg */ 158caade7ccSmrg _XLockMutex(_Xglobal_lock); 159caade7ccSmrg dpyinfo->next = extinfo->head; 160caade7ccSmrg extinfo->head = dpyinfo; 161caade7ccSmrg extinfo->cur = dpyinfo; 162caade7ccSmrg extinfo->ndisplays++; 163caade7ccSmrg _XUnlockMutex(_Xglobal_lock); 164caade7ccSmrg return dpyinfo; 165caade7ccSmrg} 166caade7ccSmrg 167caade7ccSmrg 168caade7ccSmrg/* 169caade7ccSmrg * XextRemoveDisplay - remove the indicated display from the extension object 170caade7ccSmrg */ 171caade7ccSmrgint XextRemoveDisplay (XExtensionInfo *extinfo, Display *dpy) 172caade7ccSmrg{ 173caade7ccSmrg XExtDisplayInfo *dpyinfo, *prev; 174caade7ccSmrg 175caade7ccSmrg /* 176caade7ccSmrg * locate this display and its back link so that it can be removed 177caade7ccSmrg */ 178caade7ccSmrg _XLockMutex(_Xglobal_lock); 179caade7ccSmrg prev = NULL; 180caade7ccSmrg for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) { 181caade7ccSmrg if (dpyinfo->display == dpy) break; 182caade7ccSmrg prev = dpyinfo; 183caade7ccSmrg } 184caade7ccSmrg if (!dpyinfo) { 185caade7ccSmrg _XUnlockMutex(_Xglobal_lock); 186caade7ccSmrg return 0; /* hmm, actually an error */ 187caade7ccSmrg } 188caade7ccSmrg 189caade7ccSmrg /* 190caade7ccSmrg * remove the display from the list; handles going to zero 191caade7ccSmrg */ 192caade7ccSmrg if (prev) 193caade7ccSmrg prev->next = dpyinfo->next; 194caade7ccSmrg else 195caade7ccSmrg extinfo->head = dpyinfo->next; 196caade7ccSmrg 197caade7ccSmrg extinfo->ndisplays--; 198caade7ccSmrg if (dpyinfo == extinfo->cur) extinfo->cur = NULL; /* flush cache */ 199caade7ccSmrg _XUnlockMutex(_Xglobal_lock); 200caade7ccSmrg 201caade7ccSmrg Xfree ((char *) dpyinfo); 202caade7ccSmrg return 1; 203caade7ccSmrg} 204caade7ccSmrg 205caade7ccSmrg 206caade7ccSmrg/* 207caade7ccSmrg * XextFindDisplay - look for a display in this extension; keeps a cache 208caade7ccSmrg * of the most-recently used for efficiency. 209caade7ccSmrg */ 210caade7ccSmrgXExtDisplayInfo *XextFindDisplay (XExtensionInfo *extinfo, Display *dpy) 211caade7ccSmrg{ 212caade7ccSmrg register XExtDisplayInfo *dpyinfo; 213caade7ccSmrg 214caade7ccSmrg /* 215caade7ccSmrg * see if this was the most recently accessed display 216caade7ccSmrg */ 217caade7ccSmrg if ((dpyinfo = extinfo->cur)&& dpyinfo->display == dpy) return dpyinfo; 218caade7ccSmrg 219caade7ccSmrg 220caade7ccSmrg /* 221caade7ccSmrg * look for display in list 222caade7ccSmrg */ 223caade7ccSmrg _XLockMutex(_Xglobal_lock); 224caade7ccSmrg for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) { 225caade7ccSmrg if (dpyinfo->display == dpy) { 226caade7ccSmrg extinfo->cur = dpyinfo; /* cache most recently used */ 227caade7ccSmrg _XUnlockMutex(_Xglobal_lock); 228caade7ccSmrg return dpyinfo; 229caade7ccSmrg } 230caade7ccSmrg } 231caade7ccSmrg _XUnlockMutex(_Xglobal_lock); 232caade7ccSmrg 233caade7ccSmrg return NULL; 234caade7ccSmrg} 235caade7ccSmrg 236caade7ccSmrg 237caade7ccSmrg 238caade7ccSmrgstatic int _default_exterror (Display *dpy, char *ext_name, char *reason) 239caade7ccSmrg{ 240caade7ccSmrg fprintf (stderr, "Xlib: extension \"%s\" %s on display \"%s\".\n", 241caade7ccSmrg ext_name, reason, DisplayString(dpy)); 242caade7ccSmrg return 0; 243caade7ccSmrg} 244caade7ccSmrg 245caade7ccSmrg 246caade7ccSmrg/* 247caade7ccSmrg * XSetExtensionErrorHandler - sets the handler that gets called when a 248caade7ccSmrg * requested extension is referenced. This should eventually move into Xlib. 249caade7ccSmrg */ 250caade7ccSmrg 251c585b9bdSmrgextern XextErrorHandler _XExtensionErrorFunction; 252caade7ccSmrg 253c585b9bdSmrgXextErrorHandler XSetExtensionErrorHandler (XextErrorHandler handler) 254caade7ccSmrg{ 255c585b9bdSmrg XextErrorHandler oldhandler = _XExtensionErrorFunction; 256caade7ccSmrg 257caade7ccSmrg _XExtensionErrorFunction = (handler ? handler : 258caade7ccSmrg _default_exterror); 259caade7ccSmrg return oldhandler; 260caade7ccSmrg} 261caade7ccSmrg 262caade7ccSmrg 263caade7ccSmrg/* 264caade7ccSmrg * XMissingExtension - call the extension error handler 265caade7ccSmrg */ 266caade7ccSmrgint XMissingExtension (Display *dpy, _Xconst char *ext_name) 267caade7ccSmrg{ 268caade7ccSmrg int (*func)(Display*, char *, char *) = (_XExtensionErrorFunction ? 269caade7ccSmrg _XExtensionErrorFunction : _default_exterror); 270caade7ccSmrg 271caade7ccSmrg if (!ext_name) ext_name = X_EXTENSION_UNKNOWN; 272caade7ccSmrg return (*func) (dpy, ext_name, X_EXTENSION_MISSING); 273caade7ccSmrg} 274