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