Home | History | Annotate | Line # | Download | only in src
      1 /*
      2  *
      3 Copyright 1989, 1998  The Open Group
      4 
      5 Permission to use, copy, modify, distribute, and sell this software and its
      6 documentation for any purpose is hereby granted without fee, provided that
      7 the above copyright notice appear in all copies and that both that
      8 copyright notice and this permission notice appear in supporting
      9 documentation.
     10 
     11 The above copyright notice and this permission notice shall be included in
     12 all copies or substantial portions of the Software.
     13 
     14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     20 
     21 Except as contained in this notice, the name of The Open Group shall not be
     22 used in advertising or otherwise to promote the sale, use or other dealings
     23 in 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  */
     64 XExtensionInfo *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  */
     80 void 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  */
     93 XExtDisplayInfo *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  */
    175 int 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  */
    214 XExtDisplayInfo *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 
    242 static 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 
    255 extern XextErrorHandler _XExtensionErrorFunction;
    256 
    257 XextErrorHandler 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  */
    270 int 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