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