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