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