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