home products news downloads documentation support gallery online maps resellers search
TNTmips

HOME

PROFESSIONAL
  TNTmips
  TNTedit
  TNTview
  TNTsdk
  Prices
  How To Order

CONTACT MI
  Resellers
  Consultants
  MicroImages
  About MI
  Visiting
  Prices
  Send Email
  Reseller Resources

SHOWROOM
  Gallery
  Technical Guides
  New Features
  Testimonials
  Reviews
  World Languages

FREE PRODUCTS
  TNTmips Free
  TNTatlas

  MI/X
  FAQ

DOCUMENTATION

SCRIPTING

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. 2013 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

25 March 2009

page update: 26 May 11