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