InitExt.c revision 7d2c738b
1/*
2
3Copyright 1987, 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
12in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20OTHER DEALINGS IN THE SOFTWARE.
21
22Except as contained in this notice, the name of The Open Group shall
23not be used in advertising or otherwise to promote the sale, use or
24other dealings in this Software without prior written authorization
25from The Open Group.
26
27*/
28
29#ifdef HAVE_CONFIG_H
30#include <config.h>
31#endif
32#include <X11/Xlibint.h>
33#include <X11/Xos.h>
34#include <stdio.h>
35
36/* The X11 protocol spec reserves events 64 through 127 for extensions */
37#ifndef LastExtensionEvent
38#define LastExtensionEvent 127
39#endif
40
41/* The X11 protocol spec reserves requests 128 through 255 for extensions */
42#ifndef LastExtensionRequest
43#define FirstExtensionRequest 128
44#define LastExtensionRequest 255
45#endif
46
47
48/*
49 * This routine is used to link a extension in so it will be called
50 * at appropriate times.
51 */
52
53XExtCodes *XInitExtension (
54	Display *dpy,
55	_Xconst char *name)
56{
57	XExtCodes codes;	/* temp. place for extension information. */
58	register _XExtension *ext;/* need a place to build it all */
59	if (!XQueryExtension(dpy, name,
60		&codes.major_opcode, &codes.first_event,
61		&codes.first_error)) return (NULL);
62
63	LockDisplay (dpy);
64	if (! (ext = Xcalloc (1, sizeof (_XExtension))) ||
65	    ! (ext->name = strdup(name))) {
66	    Xfree(ext);
67	    UnlockDisplay(dpy);
68	    return (XExtCodes *) NULL;
69	}
70	codes.extension = dpy->ext_number++;
71	ext->codes = codes;
72
73	/* chain it onto the display list */
74	ext->next = dpy->ext_procs;
75	dpy->ext_procs = ext;
76	UnlockDisplay (dpy);
77
78	return (&ext->codes);		/* tell him which extension */
79}
80
81XExtCodes *XAddExtension (Display *dpy)
82{
83    register _XExtension *ext;
84
85    LockDisplay (dpy);
86    if (! (ext = Xcalloc (1, sizeof (_XExtension)))) {
87	UnlockDisplay(dpy);
88	return (XExtCodes *) NULL;
89    }
90    ext->codes.extension = dpy->ext_number++;
91
92    /* chain it onto the display list */
93    ext->next = dpy->ext_procs;
94    dpy->ext_procs = ext;
95    UnlockDisplay (dpy);
96
97    return (&ext->codes);		/* tell him which extension */
98}
99
100static _XExtension *XLookupExtension (
101	register Display *dpy,	/* display */
102	register int extension)	/* extension number */
103{
104	register _XExtension *ext;
105	for (ext = dpy->ext_procs; ext; ext = ext->next)
106	    if (ext->codes.extension == extension) return (ext);
107	return (NULL);
108}
109
110XExtData **XEHeadOfExtensionList(XEDataObject object)
111{
112    return *(XExtData ***)&object;
113}
114
115int
116XAddToExtensionList(
117    XExtData **structure,
118    XExtData *ext_data)
119{
120    ext_data->next = *structure;
121    *structure = ext_data;
122    return 1;
123}
124
125XExtData *XFindOnExtensionList(
126    XExtData **structure,
127    int number)
128{
129    XExtData *ext;
130
131    ext = *structure;
132    while (ext && (ext->number != number))
133	ext = ext->next;
134    return ext;
135}
136
137/*
138 * Routines to hang procs on the extension structure.
139 */
140CreateGCType XESetCreateGC(
141	Display *dpy,		/* display */
142	int extension,		/* extension number */
143	CreateGCType proc)	/* routine to call when GC created */
144{
145	register _XExtension *e;	/* for lookup of extension */
146	register CreateGCType oldproc;
147	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
148	LockDisplay(dpy);
149	oldproc = e->create_GC;
150	e->create_GC = proc;
151	UnlockDisplay(dpy);
152	return (CreateGCType)oldproc;
153}
154
155CopyGCType XESetCopyGC(
156	Display *dpy,		/* display */
157	int extension,		/* extension number */
158	CopyGCType proc)	/* routine to call when GC copied */
159{
160	register _XExtension *e;	/* for lookup of extension */
161	register CopyGCType oldproc;
162	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
163	LockDisplay(dpy);
164	oldproc = e->copy_GC;
165	e->copy_GC = proc;
166	UnlockDisplay(dpy);
167	return (CopyGCType)oldproc;
168}
169
170FlushGCType XESetFlushGC(
171	Display *dpy,		/* display */
172	int extension,		/* extension number */
173	FlushGCType proc)	/* routine to call when GC copied */
174{
175	register _XExtension *e;	/* for lookup of extension */
176	register FlushGCType oldproc;
177	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
178	LockDisplay(dpy);
179	oldproc = e->flush_GC;
180	e->flush_GC = proc;
181	UnlockDisplay(dpy);
182	return (FlushGCType)oldproc;
183}
184
185FreeGCType XESetFreeGC(
186	Display *dpy,		/* display */
187	int extension,		/* extension number */
188	FreeGCType proc)	/* routine to call when GC freed */
189{
190	register _XExtension *e;	/* for lookup of extension */
191	register FreeGCType oldproc;
192	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
193	LockDisplay(dpy);
194	oldproc = e->free_GC;
195	e->free_GC = proc;
196	UnlockDisplay(dpy);
197	return (FreeGCType)oldproc;
198}
199
200CreateFontType XESetCreateFont(
201	Display *dpy,		/* display */
202	int extension,		/* extension number */
203	CreateFontType proc)	/* routine to call when font created */
204{
205	register _XExtension *e;	/* for lookup of extension */
206	register CreateFontType oldproc;
207	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
208	LockDisplay(dpy);
209	oldproc = e->create_Font;
210	e->create_Font = proc;
211	UnlockDisplay(dpy);
212	return (CreateFontType)oldproc;
213}
214
215FreeFontType XESetFreeFont(
216	Display *dpy,		/* display */
217	int extension,		/* extension number */
218	FreeFontType proc)	/* routine to call when font freed */
219{
220	register _XExtension *e;	/* for lookup of extension */
221	register FreeFontType oldproc;
222	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
223	LockDisplay(dpy);
224	oldproc = e->free_Font;
225	e->free_Font = proc;
226	UnlockDisplay(dpy);
227	return (FreeFontType)oldproc;
228}
229
230CloseDisplayType XESetCloseDisplay(
231	Display *dpy,		/* display */
232	int extension,		/* extension number */
233	CloseDisplayType proc)	/* routine to call when display closed */
234{
235	register _XExtension *e;	/* for lookup of extension */
236	register CloseDisplayType oldproc;
237	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
238	LockDisplay(dpy);
239	oldproc = e->close_display;
240	e->close_display = proc;
241	UnlockDisplay(dpy);
242	return (CloseDisplayType)oldproc;
243}
244
245typedef Bool (*WireToEventType) (
246    Display*	/* display */,
247    XEvent*	/* re */,
248    xEvent*	/* event */
249);
250
251WireToEventType XESetWireToEvent(
252	Display *dpy,		/* display */
253	int event_number,	/* event routine to replace */
254	WireToEventType proc)	/* routine to call when converting event */
255{
256	register WireToEventType oldproc;
257	if (event_number < 0 ||
258	    event_number > LastExtensionEvent) {
259	    fprintf(stderr, "Xlib: ignoring invalid extension event %d\n",
260		    event_number);
261	    return (WireToEventType)_XUnknownWireEvent;
262	}
263	if (proc == NULL) proc = (WireToEventType)_XUnknownWireEvent;
264	LockDisplay (dpy);
265	oldproc = dpy->event_vec[event_number];
266	dpy->event_vec[event_number] = proc;
267	UnlockDisplay (dpy);
268	return (WireToEventType)oldproc;
269}
270
271typedef Bool (*WireToEventCookieType) (
272    Display*	/* display */,
273    XGenericEventCookie*	/* re */,
274    xEvent*	/* event */
275);
276
277WireToEventCookieType XESetWireToEventCookie(
278    Display *dpy,       /* display */
279    int extension,      /* extension major opcode */
280    WireToEventCookieType proc /* routine to call for generic events */
281    )
282{
283	WireToEventCookieType oldproc;
284	if (extension < FirstExtensionRequest ||
285	    extension > LastExtensionRequest) {
286	    fprintf(stderr, "Xlib: ignoring invalid extension opcode %d\n",
287		    extension);
288	    return (WireToEventCookieType)_XUnknownWireEventCookie;
289	}
290	if (proc == NULL) proc = (WireToEventCookieType)_XUnknownWireEventCookie;
291	LockDisplay (dpy);
292	oldproc = dpy->generic_event_vec[extension & 0x7F];
293	dpy->generic_event_vec[extension & 0x7F] = proc;
294	UnlockDisplay (dpy);
295	return (WireToEventCookieType)oldproc;
296}
297
298typedef Bool (*CopyEventCookieType) (
299    Display*	/* display */,
300    XGenericEventCookie*	/* in */,
301    XGenericEventCookie*	/* out */
302);
303
304CopyEventCookieType XESetCopyEventCookie(
305    Display *dpy,       /* display */
306    int extension,      /* extension major opcode */
307    CopyEventCookieType proc /* routine to copy generic events */
308    )
309{
310	CopyEventCookieType oldproc;
311	if (extension < FirstExtensionRequest ||
312	    extension > LastExtensionRequest) {
313	    fprintf(stderr, "Xlib: ignoring invalid extension opcode %d\n",
314		    extension);
315	    return (CopyEventCookieType)_XUnknownCopyEventCookie;
316	}
317	if (proc == NULL) proc = (CopyEventCookieType)_XUnknownCopyEventCookie;
318	LockDisplay (dpy);
319	oldproc = dpy->generic_event_copy_vec[extension & 0x7F];
320	dpy->generic_event_copy_vec[extension & 0x7F] = proc;
321	UnlockDisplay (dpy);
322	return (CopyEventCookieType)oldproc;
323}
324
325
326typedef Status (*EventToWireType) (
327    Display*	/* display */,
328    XEvent*	/* re */,
329    xEvent*	/* event */
330);
331
332EventToWireType XESetEventToWire(
333	Display *dpy,		/* display */
334	int event_number,	/* event routine to replace */
335	EventToWireType proc)	/* routine to call when converting event */
336{
337	register EventToWireType oldproc;
338	if (event_number < 0 ||
339	    event_number > LastExtensionEvent) {
340	    fprintf(stderr, "Xlib: ignoring invalid extension event %d\n",
341		    event_number);
342	    return (EventToWireType)_XUnknownNativeEvent;
343	}
344	if (proc == NULL) proc = (EventToWireType) _XUnknownNativeEvent;
345	LockDisplay (dpy);
346	oldproc = dpy->wire_vec[event_number];
347	dpy->wire_vec[event_number] = proc;
348	UnlockDisplay(dpy);
349	return (EventToWireType)oldproc;
350}
351
352typedef Bool (*WireToErrorType) (
353    Display*	/* display */,
354    XErrorEvent* /* he */,
355    xError*	/* we */
356);
357
358WireToErrorType XESetWireToError(
359	Display *dpy,		/* display */
360	int error_number,	/* error routine to replace */
361	WireToErrorType proc)	/* routine to call when converting error */
362{
363	register WireToErrorType oldproc = NULL;
364	if (error_number < 0 ||
365	    error_number > LastExtensionError) {
366	   fprintf(stderr, "Xlib: ignoring invalid extension error %d\n",
367		    error_number);
368	   return (WireToErrorType)_XDefaultWireError;
369	}
370	if (proc == NULL) proc = (WireToErrorType)_XDefaultWireError;
371	LockDisplay (dpy);
372	if (!dpy->error_vec) {
373	    int i;
374	    dpy->error_vec = Xmalloc(256 * sizeof(oldproc));
375	    for (i = 1; i < 256; i++)
376		dpy->error_vec[i] = _XDefaultWireError;
377	}
378	if (dpy->error_vec) {
379	    oldproc = dpy->error_vec[error_number];
380	    dpy->error_vec[error_number] = proc;
381	}
382	UnlockDisplay (dpy);
383	return (WireToErrorType)oldproc;
384}
385
386ErrorType XESetError(
387	Display *dpy,		/* display */
388	int extension,		/* extension number */
389	ErrorType proc)		/* routine to call when X error happens */
390{
391	register _XExtension *e;	/* for lookup of extension */
392	register ErrorType oldproc;
393	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
394	LockDisplay(dpy);
395	oldproc = e->error;
396	e->error = proc;
397	UnlockDisplay(dpy);
398	return (ErrorType)oldproc;
399}
400
401ErrorStringType XESetErrorString(
402	Display *dpy,		/* display */
403	int extension,		/* extension number */
404	ErrorStringType proc)	/* routine to call when I/O error happens */
405{
406	register _XExtension *e;	/* for lookup of extension */
407	register ErrorStringType oldproc;
408	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
409	LockDisplay(dpy);
410	oldproc = e->error_string;
411	e->error_string = proc;
412	UnlockDisplay(dpy);
413	return (ErrorStringType)oldproc;
414}
415
416PrintErrorType XESetPrintErrorValues(
417	Display *dpy,		/* display */
418	int extension,		/* extension number */
419	PrintErrorType proc)	/* routine to call to print */
420{
421	register _XExtension *e;	/* for lookup of extension */
422	register PrintErrorType oldproc;
423	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
424	LockDisplay(dpy);
425	oldproc = e->error_values;
426	e->error_values = proc;
427	UnlockDisplay(dpy);
428	return (PrintErrorType)oldproc;
429}
430
431BeforeFlushType XESetBeforeFlush(
432	Display *dpy,		/* display */
433	int extension,		/* extension number */
434	BeforeFlushType proc)	/* routine to call on flush */
435{
436	register _XExtension *e;	/* for lookup of extension */
437	register BeforeFlushType oldproc;
438	register _XExtension *ext;
439	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);
440	LockDisplay(dpy);
441	oldproc = e->before_flush;
442	e->before_flush = proc;
443	for (ext = dpy->flushes; ext && ext != e; ext = ext->next)
444	    ;
445	if (!ext) {
446	    e->next_flush = dpy->flushes;
447	    dpy->flushes = e;
448	}
449	UnlockDisplay(dpy);
450	return (BeforeFlushType)oldproc;
451}
452