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