extutil.c revision 6cda817a
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/* defined in Xge.c */ 59extern _X_HIDDEN Bool 60xgeExtRegister(Display* dpy, int extension, XExtensionHooks* callbacks); 61 62/* 63 * XextCreateExtension - return an extension descriptor containing context 64 * information for this extension. This object is passed to all Xext 65 * routines. 66 */ 67XExtensionInfo *XextCreateExtension (void) 68{ 69 register XExtensionInfo *info = 70 (XExtensionInfo *) Xmalloc (sizeof (XExtensionInfo)); 71 72 if (info) { 73 info->head = NULL; 74 info->cur = NULL; 75 info->ndisplays = 0; 76 } 77 return info; 78} 79 80 81/* 82 * XextDestroyExtension - free memory the given extension descriptor 83 */ 84void XextDestroyExtension (XExtensionInfo *info) 85{ 86 info->head = NULL; /* to catch refs after this */ 87 info->cur = NULL; 88 info->ndisplays = 0; 89 XFree ((char *) info); 90} 91 92 93 94/* 95 * XextAddDisplay - add a display to this extension 96 */ 97XExtDisplayInfo *XextAddDisplay ( 98 XExtensionInfo *extinfo, 99 Display *dpy, 100 char *ext_name, 101 XExtensionHooks *hooks, 102 int nevents, 103 XPointer data) 104{ 105 XExtDisplayInfo *dpyinfo; 106 107 dpyinfo = (XExtDisplayInfo *) Xmalloc (sizeof (XExtDisplayInfo)); 108 if (!dpyinfo) return NULL; 109 dpyinfo->display = dpy; 110 dpyinfo->data = data; 111 dpyinfo->codes = XInitExtension (dpy, ext_name); 112 113 /* 114 * if the server has the extension, then we can initialize the 115 * appropriate function vectors 116 */ 117 if (dpyinfo->codes) { 118 int i, j; 119 120 for (i = 0, j = dpyinfo->codes->first_event; i < nevents; i++, j++) { 121 XESetWireToEvent (dpy, j, hooks->wire_to_event); 122 XESetEventToWire (dpy, j, hooks->event_to_wire); 123 } 124 if (hooks->create_gc) 125 XESetCreateGC (dpy, dpyinfo->codes->extension, hooks->create_gc); 126 if (hooks->copy_gc) 127 XESetCopyGC (dpy, dpyinfo->codes->extension, hooks->copy_gc); 128 if (hooks->flush_gc) 129 XESetFlushGC (dpy, dpyinfo->codes->extension, hooks->flush_gc); 130 if (hooks->free_gc) 131 XESetFreeGC (dpy, dpyinfo->codes->extension, hooks->free_gc); 132 if (hooks->create_font) 133 XESetCreateFont (dpy, dpyinfo->codes->extension, hooks->create_font); 134 if (hooks->free_font) 135 XESetFreeFont (dpy, dpyinfo->codes->extension, hooks->free_font); 136 if (hooks->close_display) 137 XESetCloseDisplay (dpy, dpyinfo->codes->extension, 138 hooks->close_display); 139 if (hooks->error) 140 XESetError (dpy, dpyinfo->codes->extension, hooks->error); 141 if (hooks->error_string) 142 XESetErrorString (dpy, dpyinfo->codes->extension, 143 hooks->error_string); 144 } else if (hooks->close_display) { 145 /* The server doesn't have this extension. 146 * Use a private Xlib-internal extension to hang the close_display 147 * hook on so that the "cache" (extinfo->cur) is properly cleaned. 148 * (XBUG 7955) 149 */ 150 XExtCodes *codes = XAddExtension(dpy); 151 if (!codes) { 152 XFree(dpyinfo); 153 return NULL; 154 } 155 XESetCloseDisplay (dpy, codes->extension, hooks->close_display); 156 } 157 158 /* 159 * now, chain it onto the list 160 */ 161 _XLockMutex(_Xglobal_lock); 162 dpyinfo->next = extinfo->head; 163 extinfo->head = dpyinfo; 164 extinfo->cur = dpyinfo; 165 extinfo->ndisplays++; 166 _XUnlockMutex(_Xglobal_lock); 167 return dpyinfo; 168} 169 170 171/* 172 * XextRemoveDisplay - remove the indicated display from the extension object 173 */ 174int XextRemoveDisplay (XExtensionInfo *extinfo, Display *dpy) 175{ 176 XExtDisplayInfo *dpyinfo, *prev; 177 178 /* 179 * locate this display and its back link so that it can be removed 180 */ 181 _XLockMutex(_Xglobal_lock); 182 prev = NULL; 183 for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) { 184 if (dpyinfo->display == dpy) break; 185 prev = dpyinfo; 186 } 187 if (!dpyinfo) { 188 _XUnlockMutex(_Xglobal_lock); 189 return 0; /* hmm, actually an error */ 190 } 191 192 /* 193 * remove the display from the list; handles going to zero 194 */ 195 if (prev) 196 prev->next = dpyinfo->next; 197 else 198 extinfo->head = dpyinfo->next; 199 200 extinfo->ndisplays--; 201 if (dpyinfo == extinfo->cur) extinfo->cur = NULL; /* flush cache */ 202 _XUnlockMutex(_Xglobal_lock); 203 204 Xfree ((char *) dpyinfo); 205 return 1; 206} 207 208 209/* 210 * XextFindDisplay - look for a display in this extension; keeps a cache 211 * of the most-recently used for efficiency. 212 */ 213XExtDisplayInfo *XextFindDisplay (XExtensionInfo *extinfo, Display *dpy) 214{ 215 register XExtDisplayInfo *dpyinfo; 216 217 /* 218 * see if this was the most recently accessed display 219 */ 220 if ((dpyinfo = extinfo->cur)&& dpyinfo->display == dpy) return dpyinfo; 221 222 223 /* 224 * look for display in list 225 */ 226 _XLockMutex(_Xglobal_lock); 227 for (dpyinfo = extinfo->head; dpyinfo; dpyinfo = dpyinfo->next) { 228 if (dpyinfo->display == dpy) { 229 extinfo->cur = dpyinfo; /* cache most recently used */ 230 _XUnlockMutex(_Xglobal_lock); 231 return dpyinfo; 232 } 233 } 234 _XUnlockMutex(_Xglobal_lock); 235 236 return NULL; 237} 238 239 240 241static int _default_exterror (Display *dpy, char *ext_name, char *reason) 242{ 243 fprintf (stderr, "Xlib: extension \"%s\" %s on display \"%s\".\n", 244 ext_name, reason, DisplayString(dpy)); 245 return 0; 246} 247 248 249/* 250 * XSetExtensionErrorHandler - sets the handler that gets called when a 251 * requested extension is referenced. This should eventually move into Xlib. 252 */ 253 254extern XextErrorHandler _XExtensionErrorFunction; 255 256XextErrorHandler XSetExtensionErrorHandler (XextErrorHandler handler) 257{ 258 XextErrorHandler oldhandler = _XExtensionErrorFunction; 259 260 _XExtensionErrorFunction = (handler ? handler : 261 _default_exterror); 262 return oldhandler; 263} 264 265 266/* 267 * XMissingExtension - call the extension error handler 268 */ 269int XMissingExtension (Display *dpy, _Xconst char *ext_name) 270{ 271 int (*func)(Display*, char *, char *) = (_XExtensionErrorFunction ? 272 _XExtensionErrorFunction : _default_exterror); 273 274 if (!ext_name) ext_name = X_EXTENSION_UNKNOWN; 275 return (*func) (dpy, ext_name, X_EXTENSION_MISSING); 276} 277