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