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