#include "copyright.h"

/* $XConsortium: XInitExt.c,v 11.17 88/10/22 11:15:09 rws Exp $ */
/* Copyright  Massachusetts Institute of Technology 1987 */

#include "Xlibint.h"
#include <stdio.h>

extern Bool _XUnknownWireEvent();
extern Status _XUnknownNativeEvent();

/*
 * This routine is used to link a extension in so it will be called
 * at appropriate times.
 */

XExtCodes *XInitExtension (dpy, name)
	Display *dpy;
	char *name;
{
	XExtCodes codes;	/* temp. place for extension information. */
	register _XExtension *ext;/* need a place to build it all */
	if (!XQueryExtension(dpy, name, 
		&codes.major_opcode, &codes.first_event,
		&codes.first_error)) return (NULL);

	LockDisplay (dpy);
	ext = (_XExtension *) Xcalloc (1, sizeof (_XExtension));
	codes.extension = dpy->ext_number++;
	ext->codes = codes;
	
	/* chain it onto the display list */
	ext->next = dpy->ext_procs;
	dpy->ext_procs = ext;
	UnlockDisplay (dpy);

	return (&ext->codes);		/* tell him which extension */
}

XExtCodes *XAddExtension (dpy)
    Display *dpy;
{
    register _XExtension *ext;

    LockDisplay (dpy);
    ext = (_XExtension *) Xcalloc (1, sizeof (_XExtension));
    ext->codes.extension = dpy->ext_number++;

    /* chain it onto the display list */
    ext->next = dpy->ext_procs;
    dpy->ext_procs = ext;
    UnlockDisplay (dpy);

    return (&ext->codes);		/* tell him which extension */
}

static _XExtension *XLookupExtension (dpy, extension)
	register Display *dpy;	/* display */
	register int extension;	/* extension number */
{
	register _XExtension *ext = dpy->ext_procs;
	while (ext != NULL) {
		if (ext->codes.extension == extension) return (ext);
		ext = ext->next;
	}
	return (NULL);
}

XExtData **XEHeadOfExtensionList(object)
    XEDataObject object;
{
    return *(XExtData ***)&object;
}

XExtData *XFindOnExtensionList(structure, number)
    XExtData **structure;
    int number;
{
    XExtData *ext;

    ext = *structure;
    while (ext && (ext->number != number))
	ext = ext->next;
    return ext;
}

/*
 * Routines to hang procs on the extension structure.
 */
int (*XESetCreateGC(dpy, extension, proc))()
	Display *dpy;		/* display */
	int extension;		/* extension number */
	int (*proc)();		/* routine to call when GC created */
{
	register _XExtension *e;	/* for lookup of extension */
	register int (*oldproc)();
	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);

	oldproc = e->create_GC;
	e->create_GC = proc;

	return (oldproc);
}
int (*XESetCopyGC(dpy, extension, proc))()
	Display *dpy;		/* display */
	int extension;		/* extension number */
	int (*proc)();		/* routine to call when GC copied */
{
	register _XExtension *e;	/* for lookup of extension */
	register int (*oldproc)();
	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);

	oldproc = e->copy_GC;
	e->copy_GC = proc;

	return (oldproc);
}
int (*XESetFlushGC(dpy, extension, proc))()
	Display *dpy;		/* display */
	int extension;		/* extension number */
	int (*proc)();		/* routine to call when GC copied */
{
	register _XExtension *e;	/* for lookup of extension */
	register int (*oldproc)();
	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);

	oldproc = e->flush_GC;
	e->flush_GC = proc;

	return (oldproc);
}

int (*XESetFreeGC(dpy, extension, proc))()
	Display *dpy;		/* display */
	int extension;		/* extension number */
	int (*proc)();		/* routine to call when GC freed */
{
	register _XExtension *e;	/* for lookup of extension */
	register int (*oldproc)();
	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);

	oldproc = e->free_GC;
	e->free_GC = proc;

	return (oldproc);
}

int (*XESetCreateFont(dpy, extension, proc))()
	Display *dpy;		/* display */
	int extension;		/* extension number */
	int (*proc)();		/* routine to call when font created */
{
	register _XExtension *e;	/* for lookup of extension */
	register int (*oldproc)();
	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);

	oldproc = e->create_Font;
	e->create_Font = proc;

	return (oldproc);
}

int (*XESetFreeFont(dpy, extension, proc))()
	Display *dpy;		/* display */
	int extension;		/* extension number */
	int (*proc)();		/* routine to call when font freed */
{
	register _XExtension *e;	/* for lookup of extension */
	register int (*oldproc)();
	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);

	oldproc = e->free_Font;
	e->free_Font = proc;

	return (oldproc);
}

int (*XESetCloseDisplay(dpy, extension, proc))()
	Display *dpy;		/* display */
	int extension;		/* extension number */
	int (*proc)();		/* routine to call when display closed */
{
	register _XExtension *e;	/* for lookup of extension */
	register int (*oldproc)();
	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);

	oldproc = e->close_display;
	e->close_display = proc;

	return (oldproc);
}
Bool (*XESetWireToEvent(dpy, event_number, proc))()
	Display *dpy;		/* display */
	Bool (*proc)();		/* routine to call when converting event */
	int event_number;	/* event routine to replace */
{
	register Bool (*oldproc)();
	if (proc == NULL) proc = _XUnknownWireEvent;
	LockDisplay (dpy);
	oldproc = dpy->event_vec[event_number];
	dpy->event_vec[event_number] = proc;
	UnlockDisplay (dpy);

	return (oldproc);
}
Status (*XESetEventToWire(dpy, event_number, proc))()
	Display *dpy;		/* display */
	Status (*proc)();	/* routine to call when converting event */
	int event_number;	/* event routine to replace */
{
	register Status (*oldproc)();
	if (proc == NULL) proc = _XUnknownNativeEvent;
	LockDisplay (dpy);
	oldproc = dpy->wire_vec[event_number];
	dpy->wire_vec[event_number] = proc;
	return (oldproc);
}
int (*XESetError(dpy, extension, proc))()
	Display *dpy;		/* display */
	int extension;		/* extension number */
	int (*proc)();		/* routine to call when X error happens */
{
	register _XExtension *e;	/* for lookup of extension */
	register int (*oldproc)();
	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);

	oldproc = e->error;
	e->error = proc;

	return (oldproc);
}
int (*XESetErrorString(dpy, extension, proc))()
	Display *dpy;		/* display */
	int extension;		/* extension number */
	int (*proc)();		/* routine to call when I/O error happens */
{
	register _XExtension *e;	/* for lookup of extension */
	register int (*oldproc)();
	if ((e = XLookupExtension (dpy, extension)) == NULL) return (NULL);

	oldproc = e->error_string;
	e->error_string = proc;

	return (oldproc);
}
