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