/*
 * Source generated with ARexxBox 1.12 (May 18 1993)
 * which is Copyright (c) 1992,1993 Michael Balzer
 */

#include <exec/types.h>
#include <exec/memory.h>
#include <dos/dos.h>
#include <rexx/storage.h>
#include <rexx/rxslib.h>

#ifdef __GNUC__
/* GCC needs all struct defs */
#include <dos/exall.h>
#include <graphics/graphint.h>
#include <intuition/classes.h>
#include <devices/keymap.h>
#include <exec/semaphores.h>
#endif

#include <clib/alib_protos.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/rexxsyslib_protos.h>

#ifndef __NO_PRAGMAS

#ifdef AZTEC_C
#include <pragmas/exec_lib.h>
#include <pragmas/dos_lib.h>
#include <pragmas/rexxsyslib_lib.h>
#endif

#ifdef LATTICE
#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/rexxsyslib_pragmas.h>
#endif

#endif /* __NO_PRAGMAS */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#ifdef LATTICE
#undef toupper
#define inline __inline
#endif

#ifdef __GNUC__
#undef toupper
static inline char toupper( char c )
{
	return( islower(c) ? c - 'a' + 'A' : c );
}
#endif

#ifdef AZTEC_C
#define inline
#endif

#include "MPMorph.h"


extern struct ExecBase *SysBase;
extern struct DosLibrary *DOSBase;
extern struct RxsLib *RexxSysBase;


/* $ARB: I 812590887 */


/* $ARB: B 1 ADDGRID */
/****** MPMorph/--background-- ************************************************
*
*  The default portname for MPMorph is MPMORPH. This can be overidden by the
*  PORTNAME parameter.
*
*  If 'OPTIONS RESULTS' is on then when an error is returned then RC2 will
*  hold a supplementary error (number or text).
*
*  Shortened unique formats of commands can be used.
*
*****************************************************************************
*
*/
#include "/MPMorph-amiga.h"
#include "/MPMorph.h"
/****** MPMorph/ADDGRID ***********************************************
*
*   NAME   
*  ADDGRID -- Adds a grid of joined points.
*
*   SYNOPSIS
*  ADDGRID( X/K/A/N,Y/K/A/N,FORCE/S )
*
*   FUNCTION
*  Adds a grid of points joined by lines. Displays a requester if the 
*  current project is not saved.
*
*   INPUTS
*  X     - The X number of cells.
*  Y     - The Y number of cells.
*  FORCE - Prevents the unsaved project requester.
*
*   RESULT
*  Returns error 10 if X or Y are zero, or other error.
*
*   EXAMPLE
*  ADDGRID X 5 Y 5
*
*   NOTES
*  The number of points added is (X+1)*(Y+1).
*
*   BUGS
*
*   SEE ALSO
*  TRIANGULATE(), ADDPOINT(), LINKPOINTS().
*
*****************************************************************************
*
*/
void rx_addgrid( struct RexxHost *host, struct rxd_addgrid **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_addgrid *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (rd->arg.x && rd->arg.y &&
				 *(rd->arg.x) && *(rd->arg.y)) {
				if (rd->arg.force) {
					Saved = TRUE;
				}
				if (ReallyAddGrid(*(rd->arg.x),*(rd->arg.y))) {
					rd->rc = 0;
				}
				else {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_FAILGRID);
				}
			}
			else {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_XYNONZERO);
			}
			rd->rc = 0;
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 1 ADDGRID */

/* $ARB: B 2 ADDPOINT */
/****** MPMorph/ADDPOINT ***********************************************
*
*   NAME   
*  ADDPOINT -- Adds a point.
*
*   SYNOPSIS
*  ADDPOINT( X1/K/A/N,Y1/K/A/N,X2/K/A/N,Y2/K/A/N )
*
*   FUNCTION
*  Adds a point.
*
*   INPUTS
*  X1 - The X coord in image 1.
*  Y1 - The Y coord in image 1.
*  X2 - The X coord in image 2.
*  Y2 - The Y coord in image 2.
*
*   RESULT
*  Returns error 10 if out of memory.
*
*   EXAMPLE
*  ADDPOINT X1 5 Y1 5 X2 10 Y2 10
*
*   NOTES
*  The point is automatically restricted to the current output size.
*
*   BUGS
*
*   SEE ALSO
*  DELETEPOINT(), MOVEPOINT(), ADDGRID(), LINKPOINTS().
*
*****************************************************************************
*
*/
void rx_addpoint( struct RexxHost *host, struct rxd_addpoint **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_addpoint *rd = *rxd;
	struct MyPoint *MyPoint;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (MyPoint = AllocMem(sizeof(struct MyPoint),MEMF_CLEAR)) {
				LimitPoints(rd->arg.x1,rd->arg.y1,NULL);
				LimitPoints(rd->arg.x2,rd->arg.y2,NULL);
				MyPoint->x = *rd->arg.x1;
				MyPoint->y = *rd->arg.y1;
				MyPoint->x1 = *rd->arg.x2;
				MyPoint->y1 = *rd->arg.y2;
				MaxWidth = max(*rd->arg.x1,MaxWidth);
				MaxWidth = max(*rd->arg.x2,MaxWidth);
				MaxHeight = max(*rd->arg.y1,MaxHeight);
				MaxHeight = max(*rd->arg.y2,MaxHeight);
				AddTail(&PointList,(struct Node *)MyPoint);
				if (ControlWindow) {
					DrawPixels(&Pic1,MyPoint->x,MyPoint->y,NULL);
					DrawPixels(&Pic2,MyPoint->x1,MyPoint->y1,NULL);
					UpdatePens(MyPoint);
				}
				Record(MyGetMsg(MSG_RECADDP),(ULONG)MyPoint->x,(ULONG)MyPoint->y,(ULONG)MyPoint->x1,(ULONG)MyPoint->y1);
				Saved = FALSE;
				CurrentTime(&USecs,&Um);
				rd->rc = 0;
			}
			else {
				rd->rc = 10;
				rd->rc2 = ERROR_NO_FREE_STORE;
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 2 ADDPOINT */

/* $ARB: B 3 CLEAR */
/****** MPMorph/CLEAR *************************************************
*
*   NAME   
*  CLEAR -- Clears the current project creating a new unnamed project.
*
*   SYNOPSIS
*  CLEAR( FORCE/S )
*
*   FUNCTION
*  Clears the current project creating a new unnamed project.  Displays
*  a requester if the current project is not saved.
*
*   INPUTS
*  FORCE - Prevents the unsaved project requester.
*
*   RESULT
*  Returns error 10 if the unsaved project requester is cancelled, or
*  the image windows are open.
*
*   EXAMPLE
*  'CLEAR FORCE'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  NEWPOINTS(), OPEN().
*
*****************************************************************************
*
*/
void rx_clear( struct RexxHost *host, struct rxd_clear **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_clear *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (!ControlWindow) {
				if (rd->arg.force) {
					Saved = TRUE;
				}
				MPMorphMenuNew();
				if (Saved) {
					rd->rc = 0;
				}
				else {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_UNSAVEDP);
				}
			}
			else {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_IWOPEN);
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 3 CLEAR */

/* $ARB: B 4 DELETEPOINT */
/****** MPMorph/DELETEPOINT ********************************************
*
*   NAME   
*  DELETEPOINT -- Deletes a point.
*
*   SYNOPSIS
*  DELETEPOINT( X/K/A/N,Y/K/A/N )
*
*   FUNCTION
*  Deletes a point.
*
*   INPUTS
*  X - The X coord in image 1.
*  Y - The Y coord in image 1.
*
*   RESULT
*  Returns error where relevant.
*
*   EXAMPLE
*  DELETEPOINT X 5 Y 5
*
*   NOTES
*  The coords are of the point in image 1.
*
*   BUGS
*
*   SEE ALSO
*  ADDPOINT().
*
*****************************************************************************
*
*/
void rx_deletepoint( struct RexxHost *host, struct rxd_deletepoint **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_deletepoint *rd = *rxd;
	struct MyPoint *MyPoint,*p1=NULL;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			for (MyPoint = (struct MyPoint *)PointList.lh_Head;
					MyPoint->MyNode.mln_Succ;
					MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
				if ((MyPoint->x == *rd->arg.x) &&
					 (MyPoint->y == *rd->arg.y)) {
					p1 = MyPoint;
				}
			}
			if (!p1) {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_XYNOT);
			}
			else {
				Record(MyGetMsg(MSG_RECDELP),(ULONG)p1->x,(ULONG)p1->y);
				DeletePoint(p1);
				Saved = FALSE;
				CurrentTime(&USecs,&Um);
				rd->rc = 0;
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 4 DELETEPOINT */

/* $ARB: B 5 EDITPOINTS */
/****** MPMorph/EDITPOINTS **************************************************
*
*   NAME   
*  EDITPOINTS - Opens the image edit windows.
*
*   SYNOPSIS
*  EDITPOINTS( )
*
*   FUNCTION
*  Opens the control and edit windows. If they were all ready open then
*  brings the control window to the front and activates it.
*
*   INPUTS
*  None.
*
*   RESULT
*  None.
*
*   EXAMPLE
*  'EDITPOINTS'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  EXITPOINTS().
*
*****************************************************************************
*
*/
void rx_editpoints( struct RexxHost *host, struct rxd_editpoints **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_editpoints *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			MPMorphMenuEditPoints();
			rd->rc = 0;
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 5 EDITPOINTS */

/* $ARB: B 6 EXITPOINTS */
/****** MPMorph/EXITPOINTS **************************************************
*
*   NAME   
*  EXITPOINTS - Closes the image edit windows.
*
*   SYNOPSIS
*  EXITPOINTS( )
*
*   FUNCTION
*  Closes the control and edit windows.
*
*   INPUTS
*  None.
*
*   RESULT
*  Returns error 10 if the image windows are not open.
*
*   EXAMPLE
*  'EXITPOINTS'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  EDITPOINTS().
*
*****************************************************************************
*
*/
void rx_exitpoints( struct RexxHost *host, struct rxd_exitpoints **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_exitpoints *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (ControlWindow) {
				RexxQuitFlag = 2;
				rd->rc = 0;
			}
			else {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_IWNOTOPEN);
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 6 EXITPOINTS */

/* $ARB: B 7 GETATTR */
/****** MPMorph/GETATTR *************************************************
*
*   NAME   
*  GETATTR -- Gets the attributes of a variable etc.
*
*   SYNOPSIS
*  GETATTR( VAR/K,STEM/K,NAME/A ) => VALUE
*
*   FUNCTION
*  Returns the current value of a specified field.
*
*   INPUTS
*  VAR     - Variable to return result rather than RESULT.
*  STEM    - Stem variable for result.
*  NAME    - Name of variable to get attributes of:
*              SAVED      - 1 if project is saved, otherwise 0;
*              OPENPOINTS - 1 if image windows are open, otherwise 0;
*              FILENAME   - the current project name;
*              FILE1      - the first workbench image file;
*              FILE2      - the second workbench image file;
*              FILE241    - the first 24 bit image file;
*              FILE242    - the second 24 bit image file;
*              OUTPUT     - the output file name;
*              WIDTH      - the output image width;
*              HEIGHT     - the output image height;
*              SINGLE     - the type of morph
*                           0 - Morph, 1 - Warp
*                           2 - AnimMorph, 3 - AnimWarp;
*              FRAMES     - the number of frames;
*              START      - the start frame;
*              PUBSCREEN  - Name of public screen MPMorph is open on;
*              HOOK       - Address of progress hook;
*              LASTUPDATE - Time (seconds) of last update (V4.4)
*
*   RESULT
*  If STEM is provided then result is returned in stem.value, otherwise
*  if VAR is provided then result is in var, otherwise result is in
*  RESULT;
*
*  Returns error when required.
*
*   EXAMPLE
*  options results;getattr saved;say result -> 0
*
*   NOTES
*  HOOK is a "struct Hook *" and should be called with parameters as
*  for MPImage.library ProgressHook. See EdgePoints for an example.
*
*   BUGS
*
*   SEE ALSO
*  SETATTR().
*
*****************************************************************************
*
*/
void rx_getattr( struct RexxHost *host, struct rxd_getattr **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_getattr *rd = *rxd;
	char *val = NULL;
	char valnum[32];

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (!Stricmp(rd->arg.name,MyGetMsg(MSG_SAVED))) {
				if (Saved) {
					val = "1";
				}
				else {
					val = "0";
				}
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_OPENP))) {
				if (ControlWindow) {
					val = "1";
				}
				else {
					val = "0";
				}
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_FILENAME))) {
				val = savedfilename;
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_FILE1))) {
				val = GetString(MPMorphGadgets[GDX_FileOne]);
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_FILE2))) {
				val = GetString(MPMorphGadgets[GDX_FileTwo]);
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_FILE241))) {
				val = GetString(MPMorphGadgets[GDX_File241]);
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_FILE242))) {
				val = GetString(MPMorphGadgets[GDX_File242]);
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_OUTPUT))) {
				val = GetString(MPMorphGadgets[GDX_Name]);
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_WIDTH))) {
				val = valnum;
				sprintf(valnum,"%ld",Width);
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_HEIGHT))) {
				val = valnum;
				sprintf(valnum,"%ld",Height);
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_SINGLE))) {
				val = valnum;
				sprintf(valnum,"%ld",SinglePicture);
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_FRAMES))) {
				val = valnum;
				sprintf(valnum,"%ld",GetNumber(MPMorphGadgets[GDX_Frames]));
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_START))) {
				val = valnum;
				sprintf(valnum,"%ld",GetNumber(MPMorphGadgets[GDX_Start]));
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_PUBSCR))) {
				if (PubScreenName) {
					val = PubScreenName;
				}
				else {
					val = "";
				}
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_HOOK))) {
				val = valnum;
				sprintf(valnum,"%ld",&ProgressHook);
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_LASTUPDATE))) {
				val = valnum;
				sprintf(valnum,"%ld",USecs);
			}
			if (val) {
				if (rd->res.value = AllocVec(strlen(val)+1,MEMF_ANY)) {
					strcpy(rd->res.value,val);
				}
				else {
					rd->rc = 10;
					rd->rc2 = ERROR_NO_FREE_STORE;
					return;
				}
			}
			else {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_INVNAME);
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			if (rd->res.value) {
				FreeVec(rd->res.value);
			}
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 7 GETATTR */

/* $ARB: B 8 HELP */
/****** MPMorph/HELP *************************************************
*
*   NAME   
*  HELP -- returns help on commands.
*
*   SYNOPSIS
*  HELP( VAR/K,STEM/K,COMMAND,PROMPT/S ) => COMMANDDESC,COMMANDLIST/M
*
*   FUNCTION
*  Returns help on all or a specified command.
*
*   INPUTS
*  VAR     - Variable to return result rather than RESULT.
*  STEM    - Stem variable for result.
*  COMMAND - Command to provide template for.
*  PROMPT  - Uses Amigaguide to display help for COMMAND.
*
*   RESULT
*  If STEM is provided and COMMAND is not provided then the number of
*  commands is returned in stem.commandlist.count and the commands are
*  returned in stem.commandlist.n where n=1 to count.
*
*  If STEM is provided and COMMAND is also provided then the template
*  for the command is returned in stem.commanddec.
*
*  If STEM is not provided then the result is returned in the VAR (if
*  provided) otherwise result. If COMMAND is not provided then the
*  result is the number of commands followed by each command, otherwise
*  the result is the command template.
*
*  If PROMPT is supplied then no result is returned.
*
*  Returns error when required.
*
*   EXAMPLE
*  options results;help;say result -> 20 ADDGRID ADDPOINT ...
*
*  options results;help stem fred.;say fred.commandlist.count -> 20
*
*  options results;help quit var bill;say bill -> QUIT FORCE/S
*
*  help AR-Postscript PROMPT
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*
*****************************************************************************
*
*/
void rx_help( struct RexxHost *host, struct rxd_help **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_help *rd = *rxd;
	struct rxs_command *rxc;
	char buffer[256] = "";
	
	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:

			/* Insert your CODE here */
			strcpy(buffer,MyGetMsg(MSG_LINK));
			if( rd->arg.prompt )
			{
				strcat(buffer,rd->arg.command);
				SendAmigaGuideCmd(handle,buffer,NULL);
				rd->rc = 0;
				return;
			}
			
			if( rd->arg.command )
			{
				rxc = FindRXCommand( rd->arg.command );
				if( !rxc )
				{
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_UNKCOM);
					return;
				}
				
				if( rd->res.commanddesc = AllocVec(strlen(rxc->command)
					+ (rxc->args    ? strlen(rxc->args)    : 0)
					+ (rxc->results ? strlen(rxc->results) : 0) + 20,
					MEMF_ANY) )
				{
					sprintf( rd->res.commanddesc,
						"%s%lc%s%s%s%s%s",
						rxc->command, 
						(rxc->results || rxc->args) ? ' ' : '\0',
						rxc->results ? "VAR/K,STEM/K" : "",
						(rxc->results && rxc->args) ? "," : "",
						rxc->args ? rxc->args : "",
						rxc->results ? " => " : "",
						rxc->results ? rxc->results : "" );
				}
				else
				{
					rd->rc = 10;
					rd->rc2 = ERROR_NO_FREE_STORE;
					return;
				}
			}
			else
			{
				char **s;
				
				if( !(s = AllocVec(sizeof(char *) * command_cnt+1, MEMF_CLEAR)) )
				{
					rd->rc = 10;
					rd->rc2 = ERROR_NO_FREE_STORE;
					return;
				}
				rd->res.commandlist = s;
				
				rxc = rxs_commandlist;
				while( rxc->command )
				{
					*s = rxc->command;
					s++;
					rxc++;
				}
			}

			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			
			if( rd->res.commanddesc )
				FreeVec( rd->res.commanddesc );
			if( rd->res.commandlist )
				FreeVec( rd->res.commandlist );
			
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 8 HELP */

/* $ARB: B 9 LINKPOINTS */
/****** MPMorph/LINKPOINTS *********************************************
*
*   NAME   
*  LINKPOINTS -- Links two points.
*
*   SYNOPSIS
*  LINKPOINTS( X1/K/A/N,Y1/K/A/N,X2/K/A/N,Y2/K/A/N )
*
*   FUNCTION
*  Links two points.
*
*   INPUTS
*  X1 - The X coord of point 1 in image 1.
*  Y1 - The Y coord of point 1 in image 1.
*  X2 - The X coord of point 2 in image 1.
*  Y2 - The Y coord of point 2 in image 1.
*
*   RESULT
*  Returns error where relevant.
*
*   EXAMPLE
*  LINKPOINTS X1 5 Y1 5 X2 10 Y2 10
*
*   NOTES
*  The coords are of the points in image 1.
*
*   BUGS
*
*   SEE ALSO
*  UNLINKPOINTS(), ADDGRID(), ADDPOINT().
*
*****************************************************************************
*
*/
void rx_linkpoints( struct RexxHost *host, struct rxd_linkpoints **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_linkpoints *rd = *rxd;
	struct MyPoint *MyPoint,*p1=NULL,*p2=NULL;
	int k;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			for (MyPoint = (struct MyPoint *)PointList.lh_Head;
					MyPoint->MyNode.mln_Succ;
					MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
				if ((MyPoint->x == *rd->arg.x1) &&
					 (MyPoint->y == *rd->arg.y1)) {
					p1 = MyPoint;
				}
			}
			if (!p1) {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_X1Y1NOT);
			}
			else {
				if (p1->NumLinks == MAX_LINKS) {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_4POINTS);
				}
				else {
					for (MyPoint = (struct MyPoint *)PointList.lh_Head;
							MyPoint->MyNode.mln_Succ;
							MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
						if ((MyPoint->x == *rd->arg.x2) &&
							 (MyPoint->y == *rd->arg.y2)) {
							p2 = MyPoint;
						}
					}
					if (!p2) {
						rd->rc = -10;
						rd->rc2 = (long)MyGetMsg(MSG_X2Y2NOT);
					}
					else {
						if (p2->NumLinks == MAX_LINKS) {
							rd->rc = -10;
							rd->rc2 = (long)MyGetMsg(MSG_4POINTS);
						}
						else {
							rd->rc = 0;
							for (k = 0;
								  k < MAX_LINKS;
								  k++) {
								if (p1->p[k] == p2) {
									rd->rc = -10;
									rd->rc2 = (long)MyGetMsg(MSG_READYLI);
								}
							}
							if (!rd->rc) {
								LinkPoints(p1,p2);
								Record(MyGetMsg(MSG_RECLINK),(ULONG)p1->x,(ULONG)p1->y,(ULONG)p2->x,(ULONG)p2->y);
								Saved = FALSE;
								CurrentTime(&USecs,&Um);
							}
						}
					}
				}
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 9 LINKPOINTS */

/* $ARB: B 10 LOCKGUI */
/****** MPMorph/LOCKGUI ***********************************************
*
*   NAME   
*  LOCKGUI - Prevents user input.
*
*   SYNOPSIS
*  LOCKGUI( )
*
*   FUNCTION
*  Prevents gui input. Displays a short message to state that the
*  program is locked.
*
*   INPUTS
*  None.
*
*   RESULT
*  None.
*
*   EXAMPLE
*  'LOCKGUI'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  UNLOCKGUI().
*
*****************************************************************************
*
*/
void rx_lockgui( struct RexxHost *host, struct rxd_lockgui **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_lockgui *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			ARexxLock = TRUE;
			Record(MyGetMsg(MSG_RECLOCKG),NULL);
			DisableWindows(DI_Rexx);
			rd->rc = 0;
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 10 LOCKGUI */

/* $ARB: B 11 MOVEPOINT */
/****** MPMorph/MOVEPOINT **********************************************
*
*   NAME   
*  MOVEPOINT -- Moves a point.
*
*   SYNOPSIS
*  MOVEPOINT( X/K/A/N,Y/K/A/N,X1/K/A/N,Y1/K/A/N,X2/K/A/N,Y2/K/A/N )
*
*   FUNCTION
*  Moves a point.
*
*   INPUTS
*  X  - The old X coord of point in image 1.
*  Y  - The old Y coord of point in image 1.
*  X1 - The new X coord of point in image 1.
*  Y1 - The new Y coord of point in image 1.
*  X2 - The new X coord of point in image 2.
*  Y2 - The new Y coord of point in image 2.
*
*   RESULT
*  Returns error where relevant.
*
*   EXAMPLE
*  MOVEPOINT X 2 Y 2 X1 5 Y1 5 X2 10 Y2 10
*
*   NOTES
*  The point is automatically restricted to the current output size.
*  The old coords are of the point in image 1.
*
*   BUGS
*
*   SEE ALSO
*  ADDPOINT().
*
*****************************************************************************
*
*/
void rx_movepoint( struct RexxHost *host, struct rxd_movepoint **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_movepoint *rd = *rxd;
	struct MyPoint *MyPoint,*p1=NULL;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			for (MyPoint = (struct MyPoint *)PointList.lh_Head;
					MyPoint->MyNode.mln_Succ;
					MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
				if ((MyPoint->x == *rd->arg.x) &&
					 (MyPoint->y == *rd->arg.y)) {
					p1 = MyPoint;
				}
			}
			if (!p1) {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_XYNOT);
			}
			else {
				LimitPoints(rd->arg.x1,rd->arg.y1,NULL);
				LimitPoints(rd->arg.x2,rd->arg.y2,NULL);
				Record(MyGetMsg(MSG_RECMOVEP),(ULONG)p1->x,(ULONG)p1->y,
						(ULONG)*rd->arg.x1,(ULONG)*rd->arg.y1,(ULONG)*rd->arg.x2,(ULONG)*rd->arg.y2);
				if (ControlWindow) {
					DrawPixels(&Pic1,p1->x,p1->y,NULL);
					DrawPixels(&Pic2,p1->x1,p1->y1,NULL);
				}
				p1->x = *rd->arg.x1;
				p1->y = *rd->arg.y1;
				p1->x1 = *rd->arg.x2;
				p1->y1 = *rd->arg.y2;
				if (ControlWindow) {
					DrawPixels(&Pic1,p1->x,p1->y,NULL);
					DrawPixels(&Pic2,p1->x1,p1->y1,NULL);
				}
				Saved = FALSE;
				CurrentTime(&USecs,&Um);
				rd->rc = 0;
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 11 MOVEPOINT */

/* $ARB: B 12 NEWPOINTS */
/****** MPMorph/NEWPOINTS *************************************************
*
*   NAME   
*  NEWPOINTS -- Deletes all existing points.
*
*   SYNOPSIS
*  NEWPOINTS( FORCE/S )
*
*   FUNCTION
*  Deletes all existing points. Displays a requester if the current project
*  is not saved.
*
*   INPUTS
*  FORCE - Prevents the unsaved project requester.
*
*   RESULT
*  Returns error 10 if the image windows are not open, or save requester
*  cancelled.
*
*   EXAMPLE
*  'NEWPOINTS'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  CLEAR(), OPENPOINTS().
*
*****************************************************************************
*
*/
void rx_newpoints( struct RexxHost *host, struct rxd_newpoints **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_newpoints *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (ControlWindow) {
				DisableWindows(DI_New);
				if (rd->arg.force) {
					Saved = TRUE;
				}
				if (!Saved) {
					if (SaveRequester()) {
						Saved = TRUE;
					}
				}
				if (Saved) {
					Record(MyGetMsg(MSG_RECNEWP),NULL);
					DeleteAllPoints();
					MaxWidth = 0;
					MaxHeight = 0;
					Saved = FALSE;
					CurrentTime(&USecs,&Um);
					rd->rc = 0;
				}
				else {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_UNSAVEDP);
				}
				EnableWindows();
				rd->rc = 0;
			}
			else {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_IWNOTOPEN);
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 12 NEWPOINTS */

/* $ARB: B 13 OPEN */
/****** MPMorph/OPEN ************************************************
*
*   NAME   
*  OPEN -- Opens an existing project.
*
*   SYNOPSIS
*  OPEN( FILENAME/K,FORCE/S )
*
*   FUNCTION
*  Clears the existing project and then loads a new one from the supplied
*  project file. Displays a requester if the current project is not saved.
*
*   INPUTS
*  FILENAME - Name of file. If not supplied then requester is displayed.
*  FORCE    - Prevents the unsaved project requester.
*
*   RESULT
*  Returns error 10 if the image windows are open or the file can not be
*  loaded.
*
*   EXAMPLE
*  'OPEN FILENAME=ram:temp.p FORCE'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  CLEAR(), OPENPOINTS().
*
*****************************************************************************
*
*/
void rx_open( struct RexxHost *host, struct rxd_open **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_open *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (!ControlWindow) {
				if (rd->arg.force) {
					Saved = TRUE;
				}
				if (MyOpen(rd->arg.filename,FALSE,TRUE)) {
					rd->rc = 0;
				}
				else {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_FAILOPENF);
				}
			}
			else {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_IWOPEN);
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 13 OPEN */

/* $ARB: B 14 OPENPOINTS */
/****** MPMorph/OPENPOINTS ************************************************
*
*   NAME   
*  OPENPOINTS -- Deletes all existing points and loads from a file.
*
*   SYNOPSIS
*  OPENPOINTS( FILENAME/K,FORCE/S )
*
*   FUNCTION
*  Deletes all existing points and then loads new ones from the supplied
*  project file. Displays a requester if the current project is not saved.
*
*   INPUTS
*  FILENAME - File to open. If not supplied then requester is displayed.
*  FORCE    - Prevents the unsaved project requester.
*
*   RESULT
*  Returns error 10 if the image windows are not open or the file can not
*  be loaded.
*
*   EXAMPLE
*  'OPENPOINTS FILENAME=ram:temp.p'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  NEWPOINTS(), OPEN().
*
*****************************************************************************
*
*/
void rx_openpoints( struct RexxHost *host, struct rxd_openpoints **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_openpoints *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (ControlWindow) {
				if (rd->arg.force) {
					Saved = TRUE;
				}
				if (MyOpen(NULL,TRUE,TRUE)) {
					rd->rc = 0;
				}
				else {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_FAILOPENF);
				}
			}
			else {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_IWNOTOPEN);
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 14 OPENPOINTS */

/* $ARB: B 15 QUIT */
/****** MPMorph/QUIT **************************************************
*
*   NAME   
*  QUIT - Quits MPMorph.
*
*   SYNOPSIS
*  QUIT( FORCE/S )
*
*   FUNCTION
*  Quits MPMorph.
*
*   INPUTS
*  FORCE - Prevents the unsaved project requester.
*
*   RESULT
*  Returns error 10 if the requester is cancelled.
*
*   EXAMPLE
*  'QUIT FORCE'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*
*****************************************************************************
*
*/
void rx_quit( struct RexxHost *host, struct rxd_quit **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_quit *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (rd->arg.force) {
				Saved = TRUE;
			}
		  	if (!Saved) {
		 		if (SaveRequester()) {
		 			RexxQuitFlag = 0;
					rd->rc = 0;
		 		}
		 		else {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_UNSAVEDP);
				}
		  	}
		  	else {
  				RexxQuitFlag = 0;
				rd->rc = 0;
		  	}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 15 QUIT */

/* $ARB: B 16 SAVE */
/****** MPMorph/SAVE **************************************************
*
*   NAME   
*  SAVE - Saves the current project.
*
*   SYNOPSIS
*  SAVE( )
*
*   FUNCTION
*  Saves the current project. Displays a requester if the project
*  is unnamed.
*
*   INPUTS
*  None.
*
*   RESULT
*  Returns error 10 if error saving file.
*
*   EXAMPLE
*  'SAVE'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  SAVEAS()
*
*****************************************************************************
*
*/
void rx_save( struct RexxHost *host, struct rxd_save **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_save *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (SaveAs(savedfilename)) {
				rd->rc = 0;
			}
			else {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_FAILSAVE);
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 16 SAVE */

/* $ARB: B 17 SAVEAS */
/****** MPMorph/SAVEAS ************************************************
*
*   NAME   
*  SAVEAS - Saves the current project.
*
*   SYNOPSIS
*  SAVEAS( FILENAME/K COPY/S)
*
*   FUNCTION
*  Saves the current project using the supplied filename.
*
*   INPUTS
*  FILENAME - Name to save as. If not supplied then requester is displayed.
*  COPY     - If supplied then save a copy, no gui errors, no recording,
*             no icon, no updating filename, don't updated saved (V4.4)
*
*   RESULT
*  Returns error 10 if error saving file.
*
*   EXAMPLE
*  'SAVEAS FILENAME=ram:test.p'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  SAVE()
*
*****************************************************************************
*
*/
void rx_saveas( struct RexxHost *host, struct rxd_saveas **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_saveas *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (rd->arg.copy) {
				if (ISaveAs(rd->arg.filename,FALSE)) {
					rd->rc = 0;
				}
				else {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_FAILSAVE);
				}
			}
			else {
				if (SaveAs(rd->arg.filename)) {
					rd->rc = 0;
				}
				else {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_FAILSAVE);
				}
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 17 SAVEAS */

/* $ARB: B 18 SCALE */
/****** MPMorph/SCALE **************************************************
*
*   NAME   
*  SCALE - Scales the size of the points and rendered output.
*
*   SYNOPSIS
*  SCALE( X/K/A/N,Y/K/A/N,FORCE/S )
*
*   FUNCTION
*  Changes the size of the rendered output and scales the defined points
*  to the new size. Displays a requester if the project is not currently
*  saved.
*
*   INPUTS
*  X     - New width.
*  Y     - New Height.
*  FORCE - Prevents the unsaved project requester.
*
*   RESULT
*  Returns error 10 if X or Y are supplied as zero, or the unsaved
*  project requester is cancelled.
*
*   EXAMPLE
*  SCALE X 640 Y 512
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  SETSIZE().
*
*****************************************************************************
*
*/
void rx_scale( struct RexxHost *host, struct rxd_scale **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_scale *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (rd->arg.x && rd->arg.y &&
				 *(rd->arg.x) && *(rd->arg.y)) {
				if (rd->arg.force) {
					Saved = TRUE;
				}
				if (ReallyScale(*(rd->arg.x),*(rd->arg.y))) {
					rd->rc = 0;
				}
				else {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_UNSAVEDP);
				}
			}
			else {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_XYNONZERO);
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 18 SCALE */

/* $ARB: B 19 SETATTR */
/****** MPMorph/SETATTR *************************************************
*
*   NAME   
*  SETATTR -- Sets the attributes of a variable etc.
*
*   SYNOPSIS
*  SETATTR( NAME/A,VALUE/A )
*
*   FUNCTION
*  Sets the current value of a specified field.
*
*   INPUTS
*  NAME    - Name of variable to set attributes for:
*              FILE1      - the first workbench image file;
*              FILE2      - the second workbench image file;
*              FILE241    - the first 24 bit image file;
*              FILE242    - the second 24 bit image file;
*              OUTPUT     - the output file name;
*              SINGLE     - the type of morph
*                           0 - Morph, 1 - Warp
*                           2 - AnimMorph, 3 - AnimWarp;
*              FRAMES     - the number of frames;
*              START      - the start frame;
*              SAVED      - Update file saved status (V4.4)
*
*   RESULT
*  Returns error when required.
*
*   EXAMPLE
*  SETATTR FRAMES 10
*
*   NOTES
*  To set the image size use SETSIZE() or SCALE().
*
*   BUGS
*
*   SEE ALSO
*  GETATTR(), SETSIZE(), SCALE().
*
*****************************************************************************
*
*/
void rx_setattr( struct RexxHost *host, struct rxd_setattr **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_setattr *rd = *rxd;
	BOOL oldsaved;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			rd->rc = 0;
			oldsaved = Saved;
			Saved = FALSE;
			CurrentTime(&USecs,&Um);
			if (!Stricmp(rd->arg.name,MyGetMsg(MSG_FILE1))) {
				GT_SetGadgetAttrs(MPMorphGadgets[GDX_FileOne],MPMorphWnd,NULL,
										GTST_String, rd->arg.value,
										TAG_END );
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_FILE2))) {
				GT_SetGadgetAttrs(MPMorphGadgets[GDX_FileTwo],MPMorphWnd,NULL,
										GTST_String, rd->arg.value,
										TAG_END );
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_FILE241))) {
				GT_SetGadgetAttrs(MPMorphGadgets[GDX_File241],MPMorphWnd,NULL,
										GTST_String, rd->arg.value,
										TAG_END );
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_FILE242))) {
				GT_SetGadgetAttrs(MPMorphGadgets[GDX_File242],MPMorphWnd,NULL,
										GTST_String, rd->arg.value,
										TAG_END );
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_OUTPUT))) {
				GT_SetGadgetAttrs(MPMorphGadgets[GDX_Name],MPMorphWnd,NULL,
										GTST_String, rd->arg.value,
										TAG_END );
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_SINGLE))) {
				GT_SetGadgetAttrs(MPMorphGadgets[GDX_SinglePicture],MPMorphWnd,NULL,
										GTCY_Active,atol(rd->arg.value), TAG_END );
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_FRAMES))) {
				GT_SetGadgetAttrs(MPMorphGadgets[GDX_Frames],MPMorphWnd,NULL,
										GTIN_Number,atol(rd->arg.value), TAG_END );
			}
			else if (!Stricmp(rd->arg.name,MyGetMsg(MSG_START))) {
				GT_SetGadgetAttrs(MPMorphGadgets[GDX_Start],MPMorphWnd,NULL,
										GTIN_Number,atol(rd->arg.value), TAG_END );
			}
			else if (!stricmp(rd->arg.name,MyGetMsg(MSG_SAVED))) {
				Saved = atol(rd->arg.value);
			}
			else {
				Saved = oldsaved;
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_INVNAME);
			}
			if (!rd->rc) {
				Record(MyGetMsg(MSG_RECSETAT),(ULONG)rd->arg.name,(ULONG)rd->arg.value);
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 19 SETATTR */

/* $ARB: B 20 SETSIZE */
/****** MPMorph/SETSIZE **************************************************
*
*   NAME   
*  SETSIZE - Changes the size of the rendered output.
*
*   SYNOPSIS
*  SETSIZE( X/K/A/N,Y/K/A/N,FORCE/S )
*
*   FUNCTION
*  Changes the size of the rendered output. Deletes points outside the new
*  image size. Displays a requester if the project is not currently saved.
*
*   INPUTS
*  X     - New width.
*  Y     - New Height.
*  FORCE - Prevents the unsaved project requester.
*
*   RESULT
*  Returns error 10 if X or Y are supplied as zero, or the unsaved project
*  requester is cancelled.
*
*   EXAMPLE
*  SETSIZE X 320 Y 256 FORCE
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  SCALE().
*
*****************************************************************************
*
*/
void rx_setsize( struct RexxHost *host, struct rxd_setsize **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_setsize *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (rd->arg.x && rd->arg.y &&
				 *(rd->arg.x) && *(rd->arg.y)) {
				if (rd->arg.force) {
					Saved = TRUE;
				}
				if (ReallySetSize(*(rd->arg.x),*(rd->arg.y))) {
					rd->rc = 0;
				}
				else {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_UNSAVEDP);
				}
			}
			else {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_XYNONZERO);
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 20 SETSIZE */

/* $ARB: B 21 TRIANGULATE */
/****** MPMorph/TRIANGULATE ***********************************************
*
*   NAME   
*  TRIANGULATE -- Deletes all lines and redraws using triangles.
*
*   SYNOPSIS
*  TRIANGULATE( FORCE/S )
*
*   FUNCTION
*  Deletes all existing lines and then creates triangles joining all the 
*  points. Displays a requester if the current project is not saved.
*
*   INPUTS
*  FORCE - Prevents the unsaved project requester.
*
*   RESULT
*  Returns error 10 if the image windows are not open, or other error.
*
*   EXAMPLE
*  'TRIANGULATE FORCE'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  ADDGRID().
*
*****************************************************************************
*
*/
void rx_triangulate( struct RexxHost *host, struct rxd_triangulate **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_triangulate *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			if (ControlWindow) {
				if (rd->arg.force) {
					Saved = TRUE;
				}
				if (Triangulate()) {
					rd->rc = 0;
				}
				else {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_FAILURET);
				}
			}
			else {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_IWNOTOPEN);
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 21 TRIANGULATE */

/* $ARB: B 22 UNLINKPOINTS */
/****** MPMorph/UNLINKPOINTS *******************************************
*
*   NAME   
*  UNLINKPOINTS -- Unlinks two points.
*
*   SYNOPSIS
*  UNLINKPOINTS( X1/K/A/N,Y1/K/A/N,X2/K/A/N,Y2/K/A/N )
*
*   FUNCTION
*  Unlinks two points.
*
*   INPUTS
*  X1 - The X coord of point 1 in image 1.
*  Y1 - The Y coord of point 1 in image 1.
*  X2 - The X coord of point 2 in image 1.
*  Y2 - The Y coord of point 2 in image 1.
*
*   RESULT
*  Returns error where relevant.
*
*   EXAMPLE
*  UNLINKPOINTS X1 5 Y1 5 X2 10 Y2 10
*
*   NOTES
*  The coords are of the points in image 1.
*
*   BUGS
*
*   SEE ALSO
*  LINKPOINTS().
*
*****************************************************************************
*
*/
void rx_unlinkpoints( struct RexxHost *host, struct rxd_unlinkpoints **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_unlinkpoints *rd = *rxd;
	struct MyPoint *MyPoint,*p1=NULL,*p2=NULL;
	int k;
	BOOL found=FALSE;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			for (MyPoint = (struct MyPoint *)PointList.lh_Head;
					MyPoint->MyNode.mln_Succ;
					MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
				if ((MyPoint->x == *rd->arg.x1) &&
					 (MyPoint->y == *rd->arg.y1)) {
					p1 = MyPoint;
				}
			}
			if (!p1) {
				rd->rc = -10;
				rd->rc2 = (long)MyGetMsg(MSG_X1Y1NOT);
			}
			else {
				for (MyPoint = (struct MyPoint *)PointList.lh_Head;
						MyPoint->MyNode.mln_Succ;
						MyPoint = (struct MyPoint *)MyPoint->MyNode.mln_Succ) {
					if ((MyPoint->x == *rd->arg.x2) &&
						 (MyPoint->y == *rd->arg.y2)) {
						p2 = MyPoint;
					}
				}
				if (!p2) {
					rd->rc = -10;
					rd->rc2 = (long)MyGetMsg(MSG_X2Y2NOT);
				}
				else {
					rd->rc = 0;
					for (k = 0;
						  k < MAX_LINKS;
						  k++) {
						if (p1->p[k] == p2) {
							found = TRUE;
						}
					}
					if (!found) {
						rd->rc = -10;
						rd->rc2 = (long)MyGetMsg(MSG_NOTLINK);
					}
					if (!rd->rc) {
						UnlinkPoints(p1,p2,(BOOL)ControlWindow);
						Record(MyGetMsg(MSG_RECUNLINK),(ULONG)p1->x,(ULONG)p1->y,(ULONG)p2->x,(ULONG)p2->y);
						Saved = FALSE;
						CurrentTime(&USecs,&Um);
					}
				}
			}
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 22 UNLINKPOINTS */

/* $ARB: B 23 UNLOCKGUI */
/****** MPMorph/UNLOCKGUI ***********************************************
*
*   NAME   
*  UNLOCKGUI - Allows user input.
*
*   SYNOPSIS
*  UNLOCKGUI( )
*
*   FUNCTION
*  Allows gui input after LOCKGUI().
*
*   INPUTS
*  None.
*
*   RESULT
*  None.
*
*   EXAMPLE
*  'UNLOCKGUI'
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  LOCKGUI().
*
*****************************************************************************
*
*/
void rx_unlockgui( struct RexxHost *host, struct rxd_unlockgui **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_unlockgui *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			ARexxLock = FALSE;
			Record(MyGetMsg(MSG_UNLOCKG),NULL);
			EnableWindows();
			rd->rc = 0;
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 23 UNLOCKGUI */

/* $ARB: B 24 SETMAX */
/****** MPMorph/SETMAX *******************************************
*
*   NAME   
*  SETMAX -- Sets the current maximum for the progress
*
*   SYNOPSIS
*  SETMAX( N/A/N )
*
*   FUNCTION
*  Sets the maximum progress.
*
*   INPUTS
*  N - The maximum progress.
*
*   RESULT
*  None.
*
*   EXAMPLE
*  SETMAX 100
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  SETCURR(), SETMESSAGE().
*
*****************************************************************************
*
*/
void rx_setmax( struct RexxHost *host, struct rxd_setmax **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_setmax *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			SetMax(*(rd->arg.n));
			rd->rc = 0;
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 24 SETMAX */

/* $ARB: B 25 SETCURR */
/****** MPMorph/SETCURR *******************************************
*
*   NAME   
*  SETCURR -- Sets the current value for the progress
*
*   SYNOPSIS
*  SETCURR( N/A/N )
*
*   FUNCTION
*  Sets the current progress.
*
*   INPUTS
*  N - The current progress.
*
*   RESULT
*  None.
*
*   EXAMPLE
*  SETCURR 50
*
*   NOTES
*
*   BUGS
*
*   SEE ALSO
*  SETMAX(), SETMESSAGE().
*
*****************************************************************************
*
*/
void rx_setcurr( struct RexxHost *host, struct rxd_setcurr **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_setcurr *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			SetCurr(*(rd->arg.n));
			rd->rc = 0;
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 25 SETCURR */

/* $ARB: B 26 SETMESSAGE */
/****** MPMorph/SETMESSAGE *******************************************
*
*   NAME   
*  SETMESSAGE -- Sets the progress message.
*
*   SYNOPSIS
*  SETMESSAGE( MESSAGE/A )
*
*   FUNCTION
*  Sets the progress message.
*
*   INPUTS
*  MESSAGE - The message to display.
*
*   RESULT
*  None.
*
*   EXAMPLE
*  SETMESSAGE "Working..."
*
*   NOTES
*  May need to use non-break-spaces
*
*   BUGS
*
*   SEE ALSO
*  SETCURR(), SETMAX().
*
*****************************************************************************
*
*/
void rx_setmessage( struct RexxHost *host, struct rxd_setmessage **rxd, long action, struct RexxMsg *rexxmsg )
{
	struct rxd_setmessage *rd = *rxd;

	switch( action )
	{
		case RXIF_INIT:
			*rxd = AllocVec( sizeof *rd, MEMF_CLEAR );
			if( rd = *rxd )
			{
				/* set your DEFAULTS here */
			}
			break;
			
		case RXIF_ACTION:
			/* Insert your CODE here */
			SetMessage(rd->arg.message);
			rd->rc = 0;
			break;
		
		case RXIF_FREE:
			/* FREE your local data here */
			FreeVec( rd );
			break;
	}
	return;
}
/* $ARB: E 26 SETMESSAGE */


#ifndef RX_ALIAS_C
char *ExpandRXCommand( struct RexxHost *host, char *command )
{
	/* Insert your ALIAS-HANDLER here */
	return( NULL );
}
#endif

