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