/***************************************************************************
 *
 *  INVESTMENT INTELLIGENCE SYSTEMS CORPORATION
 *
 *	userfunc.c
 *
 *	@(#)userfunc.c	3.3.1.2	98/08/11
 *
 *	This boundin provides the user with some sample boundin functions.
 *
 *
 ***************************************************************************
 */

#if defined(WIN32)
#include <windows.h>
#endif
#define	numfuncs	5
#include "Boundin.h"
#include <stdio.h>

IATFUNC	Factorial(PVAL, PVAL);
IATFUNC	MultOrCat(PVAL, PVAL);
IATFUNC	Factorial(PVAL, PVAL);
IATFUNC	MultOrCat(PVAL, PVAL);
IATFUNC	AddCat3(PVAL, PVAL);
IATFUNC	MyIncr(PVAL, PVAL);
IATFUNC	AddCat5(PVAL, PVAL);

/* BDROUT defines the Wingz/Boundin interface */
BDROUT rout =
{
	numfuncs, XFDEF(NULL),
	{
		{ XFDEF(Factorial),	"\004Fact",			1 | NORMAL},
		{ XFDEF(MultOrCat),	"\011MultOrCat",	2 | NORMAL},
		{ XFDEF(MyIncr),	"\006MyIncr",		1 | NORMAL},
		{ XFDEF(AddCat3),	"\007AddCat3",		3 | NORMAL},
		{ XFDEF(AddCat5),	"\007AddCat5",		5 | NORMAL},
	}
};

/* Function descriptions (appear in function glossary) */
BDFUNCLIST =
{
	(PCHAR)"Userfunc Boundin",
	(PCHAR)"Fact(number)",
	(PCHAR)"Calculates the factorial of the supplied number",
	RETNUMERIC,

	(PCHAR)"Userfunc Boundin",
	(PCHAR)"MultOrCat(arg1, arg2)",
	(PCHAR)"Multiplies two numbers or concatenates two strings",
	RETNUMERIC,

	(PCHAR)"Userfunc Boundin",
	(PCHAR)"MyIncr(number)",
	(PCHAR)"Returns the result of incrementing the supplied number by one",
	RETNUMERIC,

	(PCHAR)"Userfunc Boundin",
	(PCHAR)"AddCat3(arg1, arg2, arg3)",
	(PCHAR)"Adds three numeric arguments or concatenates three strings",
	RETNUMERIC,

	(PCHAR)"Userfunc Boundin",
	(PCHAR)"AddCat5(arg1, arg2, arg3, arg4, arg5)",
	(PCHAR)"Adds five numeric arguments or concatenates five strings",
	RETNUMERIC,

	NULL, NULL, NULL, 0
};


#if defined(WIN32)
BOOL APIENTRY DllMain(HANDLE hModule, DWORD dwReason, LPVOID lpReserved)
{
	return TRUE;
}
#endif

/* Point of entry */
BDMAINFUNC(BoundinCalls * calls)
{
    return &rout;
}


IATFUNC Factorial(PVAL pret, PVAL parg)
{
	int	ii;

	if (parg[0].flag == NUMERIC && parg[0].val.numeric >= 0)
	{
		pret->flag = NUMERIC;
		for (pret->val.numeric = 1, ii = parg[0].val.numeric; ii; --ii)
			pret->val.numeric *= ii;

		return;
	}
	else
	{
		xfSetErr(pret, ARGBAD);
		return;
	}
}


IATFUNC MultOrCat(PVAL pret, PVAL parg)
{
	int	ii = 0;								/* Index Variable */
	int n;									/* String Length */
	unsigned long int just = 0;
	unsigned char			CStrng[256];	/* 'C' String */
	static unsigned char	Result[257];

	if (parg[0].flag == STRING && parg[1].flag == STRING)
	{
		pret->flag = STRING;
		Result[1] = '\0';
		for (ii = 0; ii < 2; ++ii)
		{
			n = (unsigned char) parg[ii].val.string[0];
			just = (char) parg[ii].val.string[0];
			strcpy (CStrng, &parg[ii].val.string[1]);
			CStrng[n] = '\0';
			Result[0] = strlen (&Result[1]);
			strncat (&Result[1], CStrng, (255 - Result[0]));
		}

		Result[0] = strlen (&Result[1]);
		pret->val.string = Result;
		return;
	}
	else if (parg[0].flag == NUMERIC && parg[1].flag == NUMERIC)
	{
		xfSetLong(pret, parg[0].val.numeric * parg[1].val.numeric);
		return;

	}
	else
	{
		/* Bad Arguments */
		xfSetErr(pret, ARGBAD);
	}
}


IATFUNC AddCat3(PVAL pret, PVAL parg)
{
	int	ii = 0;
	int n;									/* String Length */
	unsigned char			CStrng[256];	/* 'C' String */
	static unsigned char	Result[257];

	if (parg[0].flag == STRING)
	{
		if (parg[1].flag != STRING || parg[2].flag != STRING)
		{
			xfSetErr(pret, ARGBAD);
			return;
		}
	}
	else if (parg[0].flag == NUMERIC)
	{
		if (parg[1].flag != NUMERIC || parg[2].flag != NUMERIC)
		{
			xfSetErr(pret, ARGBAD);
			return;
		}
	}

	if (parg[0].flag == STRING)
	{
		pret->flag = STRING;
		Result[1] = '\0';

		for (ii = 0; ii < 3; ++ii)
		{
			n = (unsigned char) parg[ii].val.string[0];
			strncpy (CStrng, &parg[ii].val.string[1], n);
			CStrng[n] = '\0';
			Result[0] = strlen (&Result[1]);
			strncat (&Result[1], CStrng, (255 - Result[0]));
		}

		Result[0] = strlen (&Result[1]);
		pret->val.string = Result;
		return;
	}
	else
	{
		pret->flag = NUMERIC;
		pret->val.numeric = 0;
		for (ii = 0; ii < 3; ++ii)
			pret->val.numeric += parg[ii].val.numeric;
		return;
	}
}


IATFUNC MyIncr(PVAL pret, PVAL parg)
{
	if (parg[0].flag == NUMERIC)
	{
		xfSetLong(pret, parg[0].val.numeric + 1);
		return;
	}
	else
	{
		xfSetErr(pret, ARGBAD);
		return;
	}
}


IATFUNC AddCat5(PVAL pret, PVAL parg)
{
	int	ii = 0;
	int	n;									/* String Length */
	unsigned char			CStrng[256];	/* 'C' String */
	static unsigned char	Result[257];

	if (parg[0].flag == STRING)
	{
		if (parg[1].flag != STRING ||
			parg[2].flag != STRING ||
			parg[3].flag != STRING ||
			parg[4].flag != STRING)
		{
			xfSetErr(pret, ARGBAD);
			return;
		}
	}
	else if (parg[0].flag == NUMERIC)
	{
		if (parg[1].flag != NUMERIC ||
			parg[2].flag != NUMERIC ||
			parg[3].flag != NUMERIC ||
			parg[4].flag != NUMERIC)
		{
			xfSetErr(pret, ARGBAD);
			return;
		}
	}

	if (parg[0].flag == STRING)
	{
		pret->flag = STRING;
		Result[1] = '\0';
		for (ii = 0; ii < 5; ++ii)
		{
			n = (unsigned char) parg[ii].val.string[0];
	       	strncpy (CStrng, &parg[ii].val.string[1], n);
       		CStrng[n] = '\0';
			Result[0] = strlen (&Result[1]);
			strncat (&Result[1], CStrng, (255 - Result[0]));
		}
		Result[0] = strlen (&Result[1]);
		pret->val.string = Result;
		return;
	}
	else
	{
		xfSetLong(pret, 0);
		for (ii = 0; ii < 5; ++ii)
			pret->val.numeric += parg[ii].val.numeric;
		return;
	}
}
