/*  ARexx_Host module Demo   */


/*		Copyright © 1989 by Donald T. Meyer, Stormgate Software
 *		All Rights Reserved
 *
 *		This source code may be compiled and used in any software
 *		product.
 *		No portion of this source code is to be
 *		re-distributed or sold for profit without the written
 *		permission of the author, Donald T. Meyer.
 *
 *		Stormgate Software
 *		PO Box 383
 *		St. Peters, MO  63376
 *
 *		E-Mail can be sent to via the following:
 *		BIX:	donmeyer		(almost daily)
 *		GEnie:	D.MEYER			(weekly)
 *		PLINK:	Stormgate		(weekly)
 */



#include <libraries/dos.h>
#include <intuition/intuition.h>

#include <proto/intuition.h>
#include <proto/exec.h>
#include <proto/dos.h>
#include <string.h>
#include <stdio.h>



/*------------------------------------------------------------------*/
/*					External Function Declarations					*/
/*------------------------------------------------------------------*/


/*------------------------------------------------------------------*/
/*					Local Function Declarations						*/
/*------------------------------------------------------------------*/

/* Declare all of the host function functions */

void func_rats( struct RexxMsg * );
void func_dbeep( struct RexxMsg * );
void func_bigword( struct RexxMsg * );
void func_myerror( struct RexxMsg * );
void func_filename( struct RexxMsg * );



/*------------------------------------------------------------------*/
/*					Variable Definitions							*/
/*------------------------------------------------------------------*/

/* This is the stuff to let us become detached... */

long _stack = 4096;
long _priority = 0;
char *_procname = "Demo_ARexxHost";



char *hostname = "DEMO_FUNC_HOST";
int hostpri = 5;

ULONG client_event_flags = NULL;

char *hello_string = "\x1B[33mDemo ARexx Function Host\x1B[31m\
Version 1.2\n\
Copyright \xA9 1989 by Don Meyer, Stormgate Software\n";

char *success_string = "Function Host installation successful!\n";

char *removal_string = "Removing existing demo function host!\n";

char *redundant_string =
	"Oops, we already are running.  No action taken.\n";

char *noclone_string = "No existing demo host to remove!\n";


char *console_def_string = "CON:30/30/500/60/ARexx Function Host";



struct RexxFunction func_table[] = {
	{ "rats", &func_rats, 0, FALSE },
	{ "dbeep", &func_dbeep, 0, FALSE },
	{ "bigword", &func_bigword, 1, FALSE },
	{ "myerror", &func_myerror, -1, FALSE },
	{ "filename", &func_filename, 1, FALSE },

	/* Mark end-of-table */
	{ NULL, NULL, 0, FALSE }
};



/* These are needed only if these librarys will be opened and used. */

struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase *GfxBase = NULL;



/*------------------------------------------------------------------*/
/*					Functions										*/
/*------------------------------------------------------------------*/


		/*****************************************
		 **										**
		 **			The Host Functions			**
		 **										**
		 ****************************************/



/* Note that in the "manual method" of returning an argstring, there
 * is no checking for failure to allocate the argstring.  To be
 * robust, this should be done.  The SetResultString helper function
 * _does_ do this.  The "manual" method is shown more for illustration,
 * as SetResultString() is probably the best way to return an
 * argstring.  The notable exception would be when returning an
 * argstring with embedded nulls.  SetResultString() will see the
 * first null as the string terminator.
 */



/* A function which returns nothing */
/*
 *	call dbeep()
 */

void func_dbeep( struct RexxMsg *rexxmsg )
{
	DisplayBeep( NULL );

	/* We don't do anything to set a result, since we return nothing
	 * and there were no errors.
	 */
}



/* A function which returns a string */
/*
 *		say rats()
 */

void func_rats( struct RexxMsg *rexxmsg )
{
	SetResultString( rexxmsg, "Large Rodents!" );


/* "manual" method -----v										*/
/*																*/
/*	rexxmsg->rm_Result2 =										*/
/*		(ULONG)CreateArgstring( "Large Rodents!", (LONG)14 );	*/
/*																*/
}



/* A function which takes one argument and returns a boolean */
/*
 *		say bigword( "Supercalifragilisticexpaladouchs" )
 *
 *  Okay, okay, YOU spell it correctly!  Sheesh.
 */

void func_bigword( struct RexxMsg *rexxmsg )
{
	if(  LengthArgstring( (struct RexxArg *)ARG1(rexxmsg) ) > 15  )
	{
		SetResultString( rexxmsg, "1" );
	}
	else
	{
		SetResultString( rexxmsg, "0" );
	}
}



/* Returns a function error no matter what */

void func_myerror( struct RexxMsg *rexxmsg )
{
	SetResultString( rexxmsg, NULL );


/* "manual" method -----v										*/
/*																*/
/*	rexxmsg->rm_Result1 = RC_ERROR;								*/
/*	rexxmsg->rm_Result2 = ERR10_012								*/
}



/* Takes a fully qualified path and filename and returns just
 * the filename.  This function is NOT optimized, just
 * a quick-and-dirty example.  As a matter of fact, I am not
 * even going to proffess it to be bug-free! :-)
 *
 *		say( "df0:tests/startrek" )
 *
 *				returns -->  "startrek"
 */ 

void func_filename( struct RexxMsg *rexxmsg )
{
	char buf[256];
	int i;


	/* Copy to a buffer.  Not really neccessary, but this IS an
	 * example, so...
	 */
	if(  LengthArgstring( (struct RexxArg *)ARG1(rexxmsg) ) > 255  )
	{
		/* Won't fit in our buffer, return an error. */
		SetResultString( rexxmsg, NULL );
		return;
	}


	strcpy( buf, ARG1(rexxmsg) );

	/* Scan for a "/" character */
	for( i=strlen(buf)-1; i>=0; i-- )
	{
		if( buf[i] == '/' )
		{
			/* Found one! */
			SetResultString( rexxmsg, &buf[i+1] );
			return;
		}
	}

	/* Okay, no "/"s, then scan for a ":" character */
	for( i=strlen(buf)-1; i>=0; i-- )
	{
		if( buf[i] == ':' )
		{
			/* Found one! */
			SetResultString( rexxmsg, &buf[i+1] );
			return;
		}
	}

	/* Hmmm.  Must _already_ be just the file name! */
	SetResultString( rexxmsg, buf );
}



/*::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/


/* In this demo this is merely a dummy function.  In other hosts
 * this would handle any events caused by client-specific needs.
 */

void client_event_handler( ULONG flags )
{
}



/* These two functions will be called by the startup and cleanup.
 * Typical use is to open librarys, etc.
 */


/* This should return a pointer to an error message string to
 * indicate failure
 */

char *client_init( void )
{
	/*   Intuition   */
	if(  ! ( IntuitionBase = (struct IntuitionBase *)
		OpenLibrary("intuition.library", LIBRARY_VERSION) )  )
	{
		return( "Unable to open the Intuition Library" );
	}

	/*   Graphics   */
	if(  ! ( GfxBase = (struct GfxBase *)
		OpenLibrary("graphics.library", LIBRARY_VERSION) )  )
	{
		return( "Unable to open the Graphics Library" );
	}

	return( NULL );
}



/* This will be called prior to exiting.  Note that this will be
 * called no matter what the reason for exiting is (normal completion
 * or termination due to error).
 */

void client_cleanup( void )
{
	if( IntuitionBase )
		CloseLibrary( (struct Library *)IntuitionBase );

	if( GfxBase )
		CloseLibrary( (struct Library *)GfxBase );
}

