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