/*
** This file holds the bulk of the hand-written code that is wrapped
** by SWIG.  All of it would be here, but some of it has to go after
** the machine-generated part of the SWIG input.
*/

%include "pointer.i"

%{

#include <X11/Intrinsic.h>
#include <X11/Wc/WcCreateP.h>
#include <X11/Wc/MapAg.h>
#include <X11/Xmp/Xmp.h>
#include <X11/Xmp/Table.h>
#include <Xm/XmAll.h>

/*
** global variables that we use
*/
static MapAg _X11_Wcl_agent;
static WcLateBind saved_lb;

/*
** This is a callback installed by calling a Wcl function; it saves an
** internal Wcl parameter that allows us to do some special processing
** for callbacks.
*/
static Boolean
_X11_Wcl_save_lb(XtPointer hookData, WcLateBind lb)
{
	saved_lb = lb;
	return False;
}

/*
** This function is used when Wcl wants to load a resource file.  It
** does the same thing that Wcl does by default, except that it pulls
** the resources from a PERL variable if the file name passed to it
** starts with "$".
*/
static XrmDatabase
_X11_Wcl_database_function(char *filename)
{
	if (filename && *filename == '$') {
		SV *x = perl_get_sv(filename + 1, FALSE);
		if (x) {
			int len = 0;
			return(XrmGetStringDatabase(SvPV(x, len)));
		} else {
			warn("X11::Wcl: no such variable: (%s)", filename);
			return(XrmGetStringDatabase(""));
		}
	} else {
		return(XrmGetFileDatabase(filename));
	}
}

/*
** All Wcl callbacks go through this C function.  It simply formats
** the callback arguments into something acceptable to the PERL
** function that handles all callbacks, and calls it.
*/
static void
_X11_Wcl_do_callback(Widget widget, XtPointer x1, XtPointer x2)
{
	char *argv[4];
	char buffer1[20];
	char buffer2[20];

	sprintf(buffer1, "%d", (int)x1);
	sprintf(buffer2, "%d", (int)x2);

	/* name of callback function */
	argv[0] = XrmQuarkToString(saved_lb->nameQ);
	argv[1] = buffer1;
	argv[2] = buffer2;
	argv[3] = 0;

	/* do the callback */
	perl_call_argv("X11::Wcl::do_callback", G_DISCARD, argv);
}

/*
** The constructor functions that get generated for structs all
** basically do the same thing, so they call this function.
**
** This function can construct from existing memory, or can allocate
** memory for a completely new structure.
*/
static char *
_X11_Wcl_do_constructor(int address, int count, int size)
{
	if (address) {
		/* construct from existing memory */
		return((char *)address);
	} else {
		/* construct from new memory */
		char *x = calloc((count ? count : 1), size);
		/* remember that we did the construction */
		MapAg_Define(_X11_Wcl_agent, x, 0, 0, 1);
		return(x);
	}
}

/*
** This is the standard destructor, that complements the standard
** consutructor.
*/
static void
_X11_Wcl_do_destructor(char *self)
{
	if (MapAg_Find(_X11_Wcl_agent, self, 0, 0)) {
		MapAg_Forget(_X11_Wcl_agent, self, 0, 0);
		free(self);
	}
}

%}

%init %{

/*
** C initialization for this module.
*/
WcAddLateBinderHook(_X11_Wcl_save_lb, (XtPointer)0);
WcSetDatabaseFunction(_X11_Wcl_database_function);
_X11_Wcl_agent = MapAg_New();

%}

/*
** Rename the wrapper around the Wcl library function so that we can
** have a public PERL function by that name.
*/
%rename WcRegisterCallback _X11_Wcl_WcRegisterCallback;
