TNTmips

HOME

FREE PRODUCTS
  TNTlite
  TNTatlas
  TNTsim3D

DOWNLOADS
  Release Version
  Development Version
  FTP
  Language Kits
  Sample Geodata
  Reseller Resources
  Promotional

DOCUMENTATION
  Tutorials
  Technical Guides
  Quick Guides

SITE MAP

 

smlapp.c


/* SMLSDK.c
 *
 * example of extending SML functions with SDK
 *
 * See instr.sml for sample usage 
 *
 * !!! YOU MUST COMPILE smlsdk.c AND RUN IT'S EXECUTABLE BEFORE USING instr.sml !!!
 *
 * Follow these steps - Windows 95
 *
 * 1. Build instr.exe - the sample make file is for Windows 95 machines
 * 2. Move instr.exe to your TNTMips directory
 * 3. Start TNTMips
 * 4. Using Windows Explorer or MS-DOS Window - execute instr.exe
 *
 *    TNTMips should start an SML session with the custom functions installed
 *
 * This example program updated 30 April 1998.
 * Now shows how to access a raster variable passed to a function.
 */

//#define ALLOW_GRE			// Uncomment this if you want display functions
//#define ALLOW_MIE			// Uncomment this if you want import/export
									// Note, MIE requires you to link to a bunch
									// of extra libs too.  See comment in the makefile.
#ifdef ALLOW_GRE
#define SML_DEFINE_SML_TNTDISP_ONLY_FUNCS
#include <mi32/gre.h>
#endif
#ifdef ALLOW_MIE
#include <mi32/mie.h>
#endif
#include <mi32/sml.h>
#include <mi32/smlfuncs.h>
#include <mgui/appmain.h>
#include <mi32/mdlg.h>

/*****************************************************************************/
/*
**  InStr(searchstr$, find$, start)
**
** function to find substring in a string
** starts searching at char position defined by start
**	if start is greater than length of searchstr
**
**	When creating your own function, name the function however you want
**	it to show up in SML.  In this example, we're creating a function named
**	InStr.
**
**	The names of the SMLPARM array must be the same as the function with
**	_Parms append to the end (ie: InStr_Parms).  You must also #define the
**	_CreateDate, _ModDate, and _FuncType.  The macro SMLFUNCDEF2 uses
**	these #defines.  This allows everything about the function to be
**	defined in one place.  
*/

/* SMLPARM structures sent to function - form is */
/* name, type STYPE_Xxxxx (see sml.h), PARM_Optional (1) or 0 if required */

static SMLPARM InStr_Parms [] = {
	{"searchstr$", STYPE_String,		0},		/* the string to search */
	{"findstr$",	STYPE_String,		0},		/* the substring to search for */
	{"start",		STYPE_Constant,	0},		/* where to start searching */
	{ NULL }
	};

#define InStr_CreateDate	19980101		/* Date function written (YYYYMMDD) */
#define InStr_ModDate		19980430		/* Date function last modified */
#define InStr_FuncType		STYPE_BFunction	/* or STYPE_BProcedure if void */

static double InStr (
	int numargs, 	/* Number of parameters the user actually passed */
	SMLARG *arg, 	/* Array of parameters */
	UINT8 *type, 	/* Parameter types. Usually ignored (see comment below) */
	SMLCONTEXT *context	/* context for various functions that need it */
	) {
	int MaxArg = numargs - 1;
	int startPos, srchLen, findLen;
	double pos;
		
	enum { ParmSearchStr, ParmFindStr, ParmStart };

	/* Note: You don't actually have to do this check unless the parm
	* Is marked as being PARM_Optional */
	if (MaxArg < ParmSearchStr) {
		context->SetArgError(SML_ENotEnoughArgs, ParmSearchStr, NULL);
		return(-1);
		}

	/* 
	**  Make sure the parameters are the correct type
	**
	**  Note, you don't actually have to do this unless
	**	   the parameter list specifies STYPE_AnyVal.  In
	**		that case, the user could pass an STYPE_String
	**		or an STYPE_Constant.   If your parameter list
	**		requests a specific type, you'll get it or the
	**		script will get a syntax error
	*/
	if (type[ParmSearchStr] != STYPE_String) {
		context->SetArgError(SML_EArgNotString, ParmSearchStr, NULL);
		return(-1);
		}

	if (type[ParmFindStr] != STYPE_String) {
		context->SetArgError(SML_EArgNotString, ParmFindStr, NULL);
		return(-1);
		}

	/* first char in SML is 1 - but we want it to be zero for "C" */
	startPos = (int)arg[ParmStart].val - 1;
	
	if (startPos < 0) { 
		context->SetArgError(SML_EBadParmAssign, ParmStart, NULL);
		return(-1);
		}

	/*
	**	Get the strings
	*/
	const MISTRING ucSearchStr = *arg[ParmSearchStr].str;
	srchLen = ucSearchStr.GetLength();

	const MISTRING ucFindStr = *arg[ParmSearchStr].str;
	findLen = ucFindStr.GetLength();
	
	/* check for start position past the end of search string */
	/*  - if it is then return 0 */
	if (startPos < srchLen) { 
		pos = ucSearchStr.FindNextOf(ucFindStr, startPos);
		}
	else {
		pos = 0;
		}
	return((double) pos);
	}

/*************************************************************************
*
*	Another sample SML Function:  This function does nothing useful, it just 
*		demonstrates how to do several things.  As an example, it takes
*		a raster and sets it to a constant.  (something better done in
*		SML by the command:
*				R = x
*		But hey, this is an exmaple.
*
**************************************************************************/

/* The parameters for the function SetRast */
static SMLPARM SetRast_Parms[] = {
	{"Raster",	STYPE_Raster,		0},
	{"number",	STYPE_Constant,	0},
	{"name$",	STYPE_String,		PARM_Optional},
	{ NULL }	/* Must always end with a NULL */
	};

#define SetRast_CreateDate	19980429			/* created April 29, 1998 */
#define SetRast_ModDate		19980429			/* Last modified April 29, 1998 */
#define SetRast_FuncType	STYPE_BProcedure	/* Function returns nothing */

static void SetRast (		/* The function name given here is what it will be called in SML */
	int numargs,				/* Number of parameters passed to the function */
	SMLARG *args,				/* Array of parameters passed to the function */
	UINT8 *type,				/* Array of parameter types (usually ignored) */
	SMLCONTEXT *context		/* SMLCONTEXT needed for many SML_Xxxx functions */
	) {
	UINT8 *buf = NULL;
	SMLRASTEROBJECT *srast;
	int i, err;

	args[0].sym->GetObject(&srast);
	if (srast == NULL) return;

	/*
	**	Closing the object flushes SML's buffers.  If the object
	**  isn't open, it does nothing.
	*/
	srast->Close();

	/* Make sure the raster is open for writing */
	err = srast->Open(RVCMODE_RW);
	if (err < 0) {
		context->SetErrorCode(err);	/* Will cause script to exit */
		return;
		}

	if ((err = MmAllocC((void **)&buf, srast->GetNumCols())) < 0) {
		context->SetErrorCode(err);	/* Will cause script to exit */
		return;
		}

	/* Show accessing a Unicode string parameter */
	if (numargs > 2) {	/* Since it was optional above */
		MISTRING mistr = *args[2].str;
		/* 
		 * Do whatever you need to do with the string here 
		 * This function doesn't actually need a string parameter.
		 * I just put this here to show how to access the string.
		 * An MISTRING can be treated like a Unicode string
		 */
		}

	/* Fill a buffer with whatver the 2nd parameter was (args[1]) */
	for (i = 0 ; i < srast->GetNumLins() ; ++i) {
		buf[i] = (UINT8)args[1].val;
		}

	/*
	*  Fill the raster with the buffer.  You could allocate an array of
	*  doubles instead of UINT8 and use RASTMODE_ConvToDouble, but if
	*  you know the raster will be 8-bit unsigned, this is faster
   */
	for (i = 0 ; i < srast->GetNumLins() ; ++i) {
		err = MfWriteRastConv(srast->GetObjHandle(), i, 0, srast->GetNumCols(), buf, RASTMODE_ConvToByte);
		if (err < 0) {
			context->SetErrorCode(err);	/* Will cause script to exit */
			MmFree(buf);
			return;
			}
		}
	MmFree(buf);

	/* We don't need to close the raster.  SML will do it later */
	return;
	}

/*****************************************************************************/
/*
**	List of functions to install.  There can be as many functions in the
**	list as you want.
*/

static SMLFUNC MyFuncList[] = {
	SMLFUNCDEF2 (InStr),
	SMLFUNCDEF2 (SetRast),
	{ NULL }		/* NULL indicates end of list */
	};

/*****************************************************************************/
/*
**	Function for SML to call after it creates the context.  You can
**	install your own functions here.  You could do other things too
**	if you wanted to.  
**
**	When installing the functions, this example will create a "Custom"
**	group for the functions to go into.  If you wanted to put them into
**	an existing group, you'd just use that group's name.  If you wanted
**	to install to more than one group, you'd create a function list for
**	each group and install them separately.
*/
	
static void MCB_InstallMyFuncs (
	SMLCALLBACKSTRUCT *cbs, 
	void *
	) {
	cbs->context->InstallFunctions("Custom", MyFuncList);
#ifdef ALLOW_GRE
	// The following line will add all of the functions that standalone SML
	// would have when run from tntdisp (where it resides).  Without it, you
	// dont get all of the GRE classes and display functions, but your program
	// would be much smaller.
	cbs->context->InstallFunctionList(SML_TNTDispFuncList);
#endif
	}

/***********************************************************************
* 					Main routine to install custom functions
***********************************************************************/

class APP_SML : public MGUI::APP_BASE {
	public:
		APP_SML() { }
	private:
			// overrides from APP_BASE
			virtual const char* v_GetProcessName (
				) const {
				return "SML_SDK_Example";
				}
			
			virtual void v_ExitInstance();
			virtual bool v_InitInstance();
			};
		

void APP_SML::v_ExitInstance (
	) {
#ifdef ALLOW_GRE
	GRE_SYSTEM::StopX();	
#endif
	}

bool APP_SML::v_InitInstance (
	) {
	Widget toplevel = MxInitLegacy(LEGACYINIT_NoAutoSetExit|LEGACYINIT_NoRealize);
	SMLCONTEXT::CallbackAddGlobal((McbCallbackFunc)MCB_InstallMyFuncs, 0, MsmlCR_InstallFuncsSML);

#ifdef ALLOW_MIE
	MieAddFormatsAll();		
	SML_EnableImportExport();
#endif

#ifdef ALLOW_GRE
	GRE_SYSTEM::InitX();		// Uncomment these if you want GRE support
	GRE_SYSTEM::RegisterLayoutLayerTypes();
#endif

	ERRVALUE err;
	SMLCONTEXT* context = 0;
	if ((err = SML_InitExt(&context)) < 0) {
		MdlgShowErrorCode(0, err);
		return(false);
		}
	SIMPLE_ARRAY<const char*> cmdparms;
	cmdparms.Reserve(GetCmdParmCount());
	for (int i = 1; (i < GetCmdParmCount()) ; ++i) {
		cmdparms.Append(GetCmdParm(i));
		}
	if ((err = SML_Main(toplevel, context, cmdparms, cmdparms.GetNumItems(), QFLAG_NonModal|QFLAG_SML|QFLAG_SetExitOnQuit)) < 0) {
		MdlgShowErrorCode(0, err);
		return(false);
		}
	return(true);
	}

class MAIN : public MGUI::APP_MAIN {
	public:
		MAIN () : m_pApp(new APP_SML) {}
		~MAIN() {}
	private:
		APP_SML* m_pApp;
	};

static MAIN MainApp;


Back Home ©MicroImages, Inc. 2008 Published in the United States of America
11th Floor - Sharp Tower, 206 South 13th Street, Lincoln NE 68508-2010   USA
Business & Sales: (402)477-9554  Support: (402)477-9562  Fax: (402)477-9559
Business info@microimages.com  Support support@microimages.com  Web webmaster@microimages.com

site update: 03 July 08

page update: 13 Jun 07