/** Dispatch.c
 *
 *   DESCRIPTION:
 *   ===========
 *
 * This function is called as the "query" entry point from the
 * library.  The arguments are contained in a RexxMsg structure, which is
 * used as a parameter block and doesn't need to be unlinked from a port.
 * Dispatch() searches a table to see whether the requested function is
 * contained in this library and calls it if it is found.  The "query"
 * function should never alter the message packet, as it must be passed
 * along to other libraries until the function is found.
 *
 *       Arguments:
 * Up to 15 arguments may be passed in the rm_Args[] array of the parameter
 * block.  Arguments are ALWAYS passed as argstrings and can generally be
 * treated like string pointers in a 'C' program.  The called function may
 * need to convert the strings to numeric values if arithmetic operations
 * are to be performed.  A NULL value in the argument slot means that the
 * argument was omitted from the function call.
 *
 * The total number of arguments (including the defaulted ones) is available
 * in the low-order byte of the action code field rm_Action.
 * Note that REXX supports function calls with varying numbers of arguments,
 * and that the called function can always determine how many were actually
 * passed.
 *
 * Error reporting:
 * The function must return an integer error code and a result string if no
 * errors were detected.  Errors are considered to be ARexx internal error
 * codes, so the function should make use of these values as appropriate.
 * A code of 0 is interpreted to mean that everything worked.
 *
 * Result strings:
 * The result string must be returned as an argstring, a pointer to the
 * string buffer of an RexxArg structure.  Argstrings can be created by a
 * call to the ARexx Systems library function CreateArgstring().
 * N.B. Never allocate a result string if the error code is non-zero!
 *
 *   PRIOR VERSION:
 *   ============
 *
 * This version is written for Aztec C and implements a basic AmigaREXX
 * ARP library. It is based on the example library by Jim Mackraz who
 * got some stuff from Neil Katin, and the Dispatch() routine by Bill Hawes.
 * All changes and additions by me.
 *
 *   AUTHOR/DATE:  W.G.J. Langeveld, November 1987.
 *   ============
 *
 *	CURRENT VERSION:
 *
 *	This version has been converted to SAS C 6.5 format. It has been modified
 *	for modern definition sequences for ANSI compilation.
 *
 * Latest change is to fix so it compiles with 3.9 NDK.
 *
 *   AUTHOR/DATE:  Joanne Dow, jdow@bix.com, June 1998.
 *   AUTHOR/DATE:  Joanne Dow, jdow@bix.com, 23 Apr 2002.
 *   ============
 *
**/
#include <functions.h>
#include "ralprotos.h"
#include <libraries/MyARP.h>
#include <intuition/intuitionbase.h>
#include <proto/rexxsyslib.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <simpreq.h>
#include "rexxarplib.h"

/*
 *   Library bases
 */
struct ArpBase       *ArpBase = NULL;
struct Library       *AslBase = NULL;
struct IntuitionBase *IntuitionBase = NULL;
struct GfxBase       *GfxBase = NULL;
struct Library       *DiskfontBase = NULL;
struct RxsLib 		 *RexxSysBase = NULL;
struct DosLibrary    *DOSBase = NULL;

/*
 *   The function table
 */
static struct RXfunc rxfs[] = 
{
	{
		rxf_getfile,   "GETFILE"       , 11, 0       
	}
	,
	{
		rxf_getsimp,   "REQUEST"       , 7 , 0       
	}
	,
	{
		rxf_getenv,    "GETENV"        , 1 , 1       
	}
	,
	{
		rxf_setenv,    "SETENV"        , 2 , 1       
	}
	,
	{
		rxf_postmsg,   "POSTMSG"       , 4 , 0       
	}
	,
	{
		rxf_stofront,  "SCREENTOFRONT" , 1 , 0       
	}
	,
	{
		rxf_stoback,   "SCREENTOBACK"  , 1 , 0       
	}
	,
	{
		rxf_srows,     "SCREENROWS"    , 1 , 0    
	}
	,
	{
		rxf_scols,     "SCREENCOLS"    , 1 , 0   // 8
	}
	,
	{
		rxf_slace,     "SCREENLACE"    , 1 , 0
	}
	,
	{
		rxf_sopen,     "OPENSCREEN"    , 9 , 5
	}
	,
	{
		rxf_sclose,    "CLOSESCREEN"   , 1 , 1
	}
	,
	{
		rxf_sendp,     "SENDPARSED"    , 15, 1
	}
	,
	{
		rxf_createhost,"CREATEHOST"    , 3 , 2
	}
	,
	{
		rxf_filelist,  "FILELIST"      , 4 , 2
	}
	,
	{
		rxf_scolor,    "SCREENCOLOR"   , 5 , 2
	}
	,
	{
		rxf_showtitle, "SHOWTITLE"     , 2 , 2	// 16
	}
	,
	{
		rxf_getfont,   "GETFONT"       , 14, 0
	}
	,
	{
		rxf_smove,     "MOVESCREEN"    , 3 , 1
	}
	,
	{
		rxf_getlist,   "REQUESTLIST"   , 10, 3
	}
	,
	{
		rxf_sshanghai,   "SETPUBSCREENMODE", 2, 0	// 20
	}
	,
	{
		rxf_sgdefpubscr,  "GETDEFPUBLICSCREEN", 0, 0	// 21
	}
	,
	{
		rxf_null,          NULL        , 2 , 0       
	}
};

/**
 *
 *   The dispatcher.
 *
**/
long __stdargs __saveds RALDispatch( struct RexxMsg *rmptr, char **resptr )
{
	int nargs = 0, ival = 0, done = FALSE;
	long result = 12L;
	char *ralpntr;
	
	DOSBase = (struct DosLibrary *) OpenLibrary("dos.library", 36);
	if (DOSBase == NULL)
		goto cleanup;
	
	ArpBase = (struct ArpBase*) OpenLibrary("arp.library", 0L);
	if (ArpBase == NULL)
		goto cleanup;
	
	AslBase = OpenLibrary("asl.library", 0L);
	
	DiskfontBase = (struct Library *) OpenLibrary("diskfont.library", 0L);
	
	RexxSysBase = (struct RxsLib*) OpenLibrary("rexxsyslib.library", 0L);
	if (RexxSysBase == NULL)
		goto cleanup;
	
	if (!SReqOpenLibs())
		goto cleanup;
	
	result = 1L;
	*resptr = NULL;
	/*
	 *   Get the number of provided arguments.
	 */
	nargs = (rmptr->rm_Action) & 0xFF;
	/*
	 *   Get the function index
	 */
	if ( strncmpu(rmptr->rm_Args[0], "RALP_", 5 ) == 0 )
		ralpntr = &rmptr->rm_Args[0][5];
	else
		ralpntr = rmptr->rm_Args[0];

	ival = rxhtable_index( ralpntr );
	if (ival >= 0) 
	{
		/*
		 *   Got a regular function. Make sure it is an exact match.
		 */
		if (( ival == 9 )
		&&  ( strcmpu( ralpntr, rxfs[ival].rexxname) != 0))
			ival = 20;
		if ( strcmpu( ralpntr, rxfs[ival].rexxname) == 0) 
		{
			result = 17L;
			/*
			 *   Check number of arguments
			 */
			if (nargs > rxfs[ival].nargs)
				goto cleanup;
			if (nargs < rxfs[ival].nargs_req)
				goto cleanup;
			/*
			 *   Call the function with the proper number of arguments.
			 *   14 is 'filelist'. Sorry 'bout the kludge... ;^)
			 *   17 is 'getfont'. Another kludge...
			 *   19 is 'requestlist', Another kludge...
			 */
			if (ival == 14 || ival == 0 || ival == 17 || ival == 19) 
			{
				*resptr = (*rxfs[ival].rexxfunc)(&result, nargs, (char **) rmptr);
			}
			else
			{
				*resptr = (*rxfs[ival].rexxfunc)(&result, nargs, &(rmptr->rm_Args[1]));
			}
			done = TRUE;
		}
	}
	
	if (!done) 
	{
		/*
		 *   If not a regular function, see if this is a window host function
		 */
		ival = whf_find(&result, nargs - 1, rmptr->rm_Args[0]);
		
		if (ival >= 0)
			*resptr = whf_sendp(&result, nargs + 1, &(rmptr->rm_Args[0]));
	}
	
	cleanup:
	SReqCloseLibs();
	if (RexxSysBase)
		CloseLibrary((struct Library*) RexxSysBase );
	if (DiskfontBase)
		CloseLibrary( DiskfontBase );
	if (ArpBase)
		CloseLibrary( ( struct Library * ) ArpBase );
	if (AslBase)
		CloseLibrary( AslBase );
	if (DOSBase)
		CloseLibrary( ( struct Library * ) DOSBase );
	
	return(result);
}


/**
 *
 *   The null function
 *
**/
char *rxf_null( long *err, int n, char **dummy )
{
	*err = 21L;
	return(0L);
}

