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