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