/*
 *  FM_ARexx_React.c
 *
 *  functions for reaction-arexx.
 *
 *  $VER: V1.5, 06.06.2002
 *  Coded by Edgar Schwan
 */

#include <exec/ports.h>
#include <intuition/classusr.h>
#include <libraries/resource.h>
#include <reaction/reaction.h>
#include <classes/arexx.h>
#include <iffp/ilbmapp.h>
#include <devices/timer.h>
#include <datatypes/datatypesclass.h>
#include <datatypes/soundclass.h>
#include <libraries/asl.h>
#include <dos/dostags.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/intuition_protos.h>
#include <clib/resource_protos.h>
#include <clib/locale_protos.h>
#include <clib/rexxsyslib_protos.h>
#include <clib/iffparse_protos.h>
#include <clib/timer_protos.h>
#include <clib/datatypes_protos.h>
#include <clib/alib_protos.h>

#include <pragmas/exec_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/intuition_pragmas.h>
#include <pragmas/resource_pragmas.h>
#include <pragmas/locale_pragmas.h>
#include <pragmas/rexxsyslib_pragmas.h>
#include <pragmas/iffparse_pragmas.h>
#include <pragmas/timer_pragmas.h>
#include <pragmas/datatypes_pragmas.h>

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

#include "FM_ARexx_React.h"
#include "FM_ReactionBasics.h"
#include "FM_Reaction.h"
#include "FM_ReactionCD.h"
#include "FM_SysInfoReq_React.h"
#include "FM_ConfirmReq_React.h"
#include "FM_CoordReq_React.h"
#include "FM_InfoReq_React.h"
#include "FM_IntegerReq_React.h"
#include "FM_PalettePref_React.h"
#include "FlashMandel.h"
#include "Compilerspecific.h"

#ifdef FM_AREXX_SUPPORT

/* external vars */
extern struct Library *ResourceBase;
extern struct Catalog *CatalogPtr;
extern struct Library *DataTypesBase;
extern struct RxsLib *RexxSysBase;

extern LDouble RMIN, RMAX, IMIN, IMAX, JKRE, JKIM;
extern TEXT FMSCREENNAME[], MYPATH[];
extern WORD ZOOMLINE[];
extern struct ILBMInfo MYILBM;
extern struct BitMap *MYBITMAP;
extern struct Border MYBORDER;
extern ULONG ELAPSEDTIME, CPUINFO, COLORS, MASK, MAX_ITERATIONS;
extern CHIP UWORD ZoomPointer[];
extern struct Menu *MAINMENU;
extern BOOL res;
extern struct MandelChunk MANDChunk;
extern ULONG *PALETTE;
extern CPTR *VINFO;
extern struct Chunk SPECIAL_CHUNK;
extern struct Chunk USERNAME_CHUNK;
extern struct Chunk COPYRIGHT_CHUNK;
extern LONG PRIORITY, DELAY;
extern WORD MX1, MY1, MX2, MY2, W, H;
extern struct TextAttr MYFONTSTRUCT;
extern TEXT MYFONT[];
extern BOOL ForceAbort;
extern ULONG UPOWER;

/* external prototypes */
//BOOL NewCoords(struct Window *, const WORD, const WORD, const WORD, const WORD);
//struct BitMap *CopyBitMap(struct Window *, WORD, WORD, WORD, WORD);
//BOOL PasteBitMap(struct BitMap *, struct Window *, WORD, WORD);
//void SetMenuStart(struct Window *);
//void SetMenuStop(struct Window *);
//void PutPointer(struct Window *, UWORD *, LONG, LONG, LONG, LONG, UBYTE);
//ULONG DrawFractal(struct Window *, const WORD, const WORD, const WORD, const WORD, BOOL);
//void ShowTime(struct Window *, TEXT *, ULONG);
//void SaveCoords(struct Window *, BOOL);
//void SystemInfo(struct Window *Win);
//LONG About(struct Window *);
//LONG Choice(struct Window *, TEXT *, TEXT *);
//LONG WinDump(struct Window *);
//BOOL Fade(struct Window *, ULONG *, ULONG, ULONG, BOOL);
//BOOL Cycle(struct Window *, ULONG, BOOL);
//LONG QueryMandPic(struct ILBMInfo *, struct MandelChunk *, UBYTE *);
//LONG LoadMandPic(struct ILBMInfo *, UBYTE *, BOOL);
//LONG SaveMandPic(struct ILBMInfo *, struct Chunk *, struct Chunk *, UBYTE *);
//LONG LoadPalette(struct ILBMInfo *, UBYTE *, BOOL);
//LONG SavePalette(struct ILBMInfo *, struct Chunk *, UBYTE *);
//void CloseDisplay(struct ILBMInfo *, CPTR *);
//LONG MakeDisplay(struct ILBMInfo *);
//void CheckMenu(struct Window *);
//BOOL FileRequest(struct Window *, TEXT *, TEXT *, BOOL, BOOL);
//ULONG IntegerGad(struct Window *, TEXT *, TEXT *, TEXT *, ULONG);
//BOOL DrawFrame(struct Window *, const WORD, const WORD, const WORD, const WORD);
//BOOL Cycle(struct Window *, ULONG, BOOL);
//BOOL Preview(struct Window *, LONG, LONG);
//void RestoreCoords(struct Window *);
//BOOL ModifyPalette(struct Window *, WORD, WORD, ULONG *);
//BOOL ShowCoords(struct Window *);
//BOOL FontRequest(struct Window *);

/* global vars */
Object *ARexxObj = NULL;
ULONG arexxsignal = 0;
struct List ARexxEventList = {0};

/* local prototypes */
static BOOL AddARexxEvent(ULONG command, APTR args);
static void RemoveARexxEvent(struct FM_ARexxEvent *event);
static BOOL IsNumber(char *string);

/* InitARexx(): Initialize ARexx-Support

		SYNOPSIS: BOOL success = InitARexx
						(
						RESOURCEFILE		ResPtr;
						);

		INPUTS:		ResPtr:
							Pointer to the reaction-resource.

		RETURNS:		success:
							Is TRUE, if successfull.
*/

BOOL InitARexx(RESOURCEFILE ResPtr)
{
ULONG ARexxError = 0;

//NewList(&ARexxEventList);
//ARexxEventList.lh_Type = NT_USER;
if (ARexxObj = RL_NewObject(ResPtr, AREXX_128_ID, AREXX_ErrorCode, &ARexxError, TAG_END)) {
	GetAttr(AREXX_SigMask, ARexxObj, (ULONG *) &arexxsignal);
	return(TRUE);
	}
else {
	switch (ARexxError) {
		case RXERR_NO_COMMAND_LIST: {
			fprintf(stderr, "Can't init ARexx-Host - No commands defined.\n");
			break;
			}
		case RXERR_NO_PORT_NAME: {
			fprintf(stderr, "Can't init ARexx-Host - No portname defined.\n");
			break;
			}
		case RXERR_PORT_ALREADY_EXISTS: {
			fprintf(stderr, "Can't init ARexx-Host - portname already exists.\n");
			break;
			}
		case RXERR_OUT_OF_MEMORY: {
			fprintf(stderr, "Can't init ARexx-Host - Out of memory.\n");
			break;
			}
		default: {
			fprintf(stderr, "Can't init ARexx-Host.\n");
			break;
			}
		}
	}

FreeARexx(ResPtr);
return(FALSE);
}

/* FreeARexx(): Free ARexx-Support.

		SYNOPSIS: void = FreeARexx
						(
						RESOURCEFILE		ResPtr;
						);

		INPUTS:		ResPtr:
							Pointer to the reaction-resource.

		RETURNS:		-
*/
void FreeARexx(RESOURCEFILE ResPtr)
{
if (ARexxObj) {RL_DisposeObject(ResPtr, ARexxObj); ARexxObj = NULL;}
arexxsignal = 0;
}

/* AddARexxEvent(): Add an event to the ARexxEvent-List.

		SYNOPSIS: BOOL success = AddARexxEvent
						(
						ULONG		command;
						APTR		args;
						);

		INPUTS:		command:
							ID of the ARexx-command.

						args:
							Pointer to the command-specific arguments.

		RETURNS:		success:
							Is TRUE. if successfull.
*/

static BOOL AddARexxEvent(ULONG command, APTR args)
{
BOOL success = FALSE;
struct FM_ARexxEvent *event = NULL;

if (event = (struct FM_ARexxEvent *) AllocVec(sizeof(struct FM_ARexxEvent), MEMF_PUBLIC|MEMF_CLEAR)) {
	event->FMRXC_Command = command;
	event->FMRXC_Args = args;

	AddTail(&ARexxEventList, (struct Node *) event);
	success = TRUE;
	}
return(success);
}

/* RemoveARexxEvent(): Remove an event from the ARexxEvent-List.

		SYNOPSIS: void = RemoveARexxEvent
						(
						struct FM_ARexxEvent		*event;
						);

		INPUTS:		event:
							Pointer to the event-structure.

		RETURNS:		-
*/

static void RemoveARexxEvent(struct FM_ARexxEvent *event)
{
Remove((struct Node *) event);
if (event->FMRXC_Args) FreeVec(event->FMRXC_Args);
FreeVec((APTR) event);
}

/* IsNumber(): Check, if string is a number (float or int).

		SYNOPSIS: BOOL isnum = IsNumber
						(
						char		*string;
						);

		INPUTS:		string:
							Pointer to a string.

		RETURNS:		isnum:
							Is TRUE, if string is a number.
*/

static BOOL IsNumber(char *string)
{
if (!(*string)) return(FALSE);

if ((*string == '+') || (*string == '-')) string++;
while(*string) {
	if (!(isdigit(*string)))
		if (*string != '.') return(FALSE);
	string++;
	}
return(TRUE);
}

												/***  ARexx-functions  ***/

/* ARexxFunc_Test(): Handle ARexx-Command 'TEST'.   Template: "SWITCH/S,STRING/K,NUMBER/N,NEEDSTR/A,FOLLOW/F" */
void ARexxFunc_Test(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
struct FM_RxCmd_TEST *args = NULL;
ULONG size1 = 0, size2 = 0, size3 = 0, memsize;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available */

if (cmd->ac_ArgList[1]) size1 = strlen((const char *) cmd->ac_ArgList[1]) + 1;
if (cmd->ac_ArgList[3]) size2 = strlen((const char *) cmd->ac_ArgList[3]) + 1;
if (cmd->ac_ArgList[4]) size3 = strlen((const char *) cmd->ac_ArgList[4]) + 1;
memsize = sizeof(struct FM_RxCmd_TEST) + size1 + size2 + size3;

if (args = (struct FM_RxCmd_TEST *) AllocVec(memsize, MEMF_PUBLIC|MEMF_CLEAR)) {    /* Copy arguments */
	if (cmd->ac_ArgList[0]) args->FMRC_TEST_Switch = (BOOL) (cmd->ac_ArgList[0]);
	if (size1) {
		char *string = (char *) ((ULONG) args + sizeof(struct FM_RxCmd_TEST));
		strcpy(string, (const char *) cmd->ac_ArgList[1]);
		args->FMRC_TEST_String = string;
		}
	if (cmd->ac_ArgList[2]) args->FMRC_TEST_Number = *(LONG *) (cmd->ac_ArgList[2]);
	if (size2) {
		char *string = (char *) ((ULONG) args + sizeof(struct FM_RxCmd_TEST) + size1);
		strcpy(string, (const char *) cmd->ac_ArgList[3]);
		args->FMRC_TEST_NeedStr = string;
		}
	if (size3) {
		char *string = (char *) ((ULONG) args + sizeof(struct FM_RxCmd_TEST) + size1 + size2);
		strcpy(string, (const char *) cmd->ac_ArgList[4]);
		args->FMRC_TEST_Follow = string;
		}

	if (AddARexxEvent(0xFFFFFFFF, (APTR) args)) {
		cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
		}
	else FreeVec(args);
	}
}

                                     /****   PROJECT   ****/

/* ARexxFunc_About(): Handle ARexx-Command 'ABOUT'.    Template: - */
void ARexxFunc_About(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
#if 0		/* external */
cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available */
if (AddARexxEvent(ABOUT_MSG, NULL)) {
	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
#else		/* internal */
ModifyIDCMP (MYILBM.win, NULL);
ClearMenuStrip (MYILBM.win);
if (ResourceBase) {Do_InfoRequest(MYILBM.win, FMSCREENNAME, 0, 0);}
else {About (MYILBM.win);}
ResetMenuStrip (MYILBM.win, MAINMENU);
ModifyIDCMP (MYILBM.win, IDCMP_STANDARD);
#endif
}

/* ARexxFunc_SysInfo(): Handle ARexx-Command 'SYSINFO'.    Template: - */
void ARexxFunc_SysInfo(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
#if 0		/* external */
cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available */
if (AddARexxEvent(SYSINFO_MSG, NULL)) {
	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
#else		/* internal */
ModifyIDCMP (MYILBM.win, NULL);
ClearMenuStrip (MYILBM.win);
if (ResourceBase) {Do_SysInfoRequest(MYILBM.win, FMSCREENNAME, 0, 0);}
else {SystemInfo (MYILBM.win);}
ResetMenuStrip (MYILBM.win, MAINMENU);
ModifyIDCMP (MYILBM.win, IDCMP_STANDARD);
#endif
}

/* ARexxFunc_Help(): Handle ARexx-Command 'HELP'.   Template: - */
void ARexxFunc_Help(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
#if 0
cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available */
if (AddARexxEvent(SHOWGUIDE_MSG, NULL)) {
	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
#else
if (!(system(CATSTR(TXT_CMD_Guide)))) {
	cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_012; /* error return from function */
	}
#endif
}

/* ARexxFunc_LoadPicture(): Handle ARexx-Command 'LOAD_PICTURE'.   Template: "PATH,FAST/S" */
void ARexxFunc_LoadPicture(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *path = (char *) cmd->ac_ArgList[0];
BOOL fast = (ULONG) (cmd->ac_ArgList[1]);

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available */
#if 1		/* external */
{
struct FM_RxCmd_LOADPIC *args = NULL;
ULONG size1 = 0, memsize = 0;

if (path) size1 = strlen((const char *) path) + 1;
memsize = sizeof(struct FM_RxCmd_LOADPIC) + size1;

if (args = (struct FM_RxCmd_LOADPIC *) AllocVec(memsize, MEMF_PUBLIC|MEMF_CLEAR)) {    /* Copy arguments */
	args->FMRC_LOADPIC_Fast = fast;
	if (size1) {
		char *string = (char *) ((ULONG) args + sizeof(struct FM_RxCmd_LOADPIC));
		strcpy(string, (const char *) cmd->ac_ArgList[0]);
		args->FMRC_LOADPIC_Path = string;
		}
	else 	args->FMRC_LOADPIC_Path = NULL;

	if (AddARexxEvent(LOADPICTURE_MSG, (APTR) args)) {
		cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
		}
	else FreeVec(args);
	}
}
#else		/* internal */
{
LONG Error;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available */
if (path) {
	PutPointer(MYILBM.win, 0, 0, 0, 0, 0, BUSY_POINTER);
	if (MYILBM.ParseInfo.iff = AllocIFF()) {
		SaveCoords(MYILBM.win, TRUE);
		if (! (Error = QueryMandPic(&MYILBM, &MANDChunk, path))) {
			RMIN = MANDChunk.RMin;
			RMAX = MANDChunk.RMax;
			IMIN = MANDChunk.IMin;
			IMAX = MANDChunk.IMax;
			JKRE = MANDChunk.JKre;
			JKIM = MANDChunk.JKim;
			MAX_ITERATIONS = MANDChunk.Iterations - 1L;
			if (!(fast)) Fade(MYILBM.win, PALETTE, 25L, 1L, TOBLACK);
			CloseDisplay(&MYILBM, VINFO);
			MYILBM.IFFPFlags = IFFPF_BESTFIT;
			COLORS = MakeDisplay(&MYILBM);
			MYILBM.IFFPFlags = NULL;
			if (! COLORS) {
				DisplayError(MYILBM.win, TXT_ERR_MakeDisplay, 20L);
//				ARexxFunc_Quit(cmd, rm);
				return;
				}
			MASK &= ~ZMASK;
			COLORS -= RESERVED_PENS;
			if (TMASK & MASK) ShowTitle(MYILBM.scr, FALSE);
			if (LoadMandPic (&MYILBM, path, ~fast)) DisplayError(MYILBM.win, TXT_ERR_LoadMandPic, 5L);
			else {cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;}
			if (TMASK & MASK) ShowTitle(MYILBM.scr, TRUE);
			GetRGB32(MYILBM.vp->ColorMap, 0L, (ULONG) MYILBM.vp->ColorMap->Count, PALETTE + 1L);
			CheckMenu(MYILBM.win);
			}
		else {
			DisplayError(MYILBM.win, TXT_ERR_QueryMandPic, 0);
			cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_012; /* error return from function */
			}
		FreeIFF(MYILBM.ParseInfo.iff);
		}
	PutPointer(MYILBM.win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
	}
else {
	if (AddARexxEvent(LOADPICTURE_MSG, NULL)) {
		cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
		}
	}
}
#endif
}

/* ARexxFunc_SavePicture(): Handle ARexx-Command 'SAVE_PICTURE'.   Template: "PATH,FORCE/S" */
void ARexxFunc_SavePicture(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *path = (char *) cmd->ac_ArgList[0];		/* internal only */
BOOL force = (ULONG) (cmd->ac_ArgList[1]);
BPTR lock = NULL;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available */
if (!(path)) {
	if (!(FileRequest(MYILBM.win, CATSTR(TXT_SavePictureTitle), "FLASHMANDEL:Pictures", PICTURES_DRAWER, TRUE))) {
		cmd->ac_RC = RC_WARN; cmd->ac_RC2 = 0; return; /* request cancelled */
		}
	}
else strncpy(MYPATH, path, MAX_PATHLEN);

if (force == FALSE) {
	if (lock = Lock(MYPATH, ACCESS_READ)) {
		BOOL overwrite = FALSE;
		UnLock(lock);
		if (ResourceBase) overwrite = Do_OverwriteRequest(MYILBM.win, FMSCREENNAME, 0, 0);
		else {
			struct EasyStruct my_req = {sizeof(struct EasyStruct), 0, CATSTR(TITLE_OverwriteReq), CATSTR(OverWr_TXT_Question), CATSTR(TXT_YesNo)};
			overwrite = EasyRequest(MYILBM.win, &my_req, 0);
			}
		if (overwrite == FALSE) {DisplayBeep(NULL); cmd->ac_RC = RC_WARN; cmd->ac_RC2 = 0; return;} /* request cancelled */
		}
	}

PutPointer(MYILBM.win, 0, 0, 0, 0, 0, BUSY_POINTER);
if (MYILBM.ParseInfo.iff = AllocIFF()) {
	MANDChunk.LeftEdge = MYILBM.win->LeftEdge;
	MANDChunk.TopEdge = MYILBM.win->TopEdge;
	MANDChunk.Width = MYILBM.win->Width;
	MANDChunk.Height = MYILBM.win->Height;
	MANDChunk.RMin = RMIN;
	MANDChunk.RMax = RMAX;
	MANDChunk.IMin = IMIN;
	MANDChunk.IMax = IMAX;
	MANDChunk.JKre = JKRE;
	MANDChunk.JKim = JKIM;
	MANDChunk.Iterations = MAX_ITERATIONS + 1L;
	if (ZMASK & MASK) {
		DrawBorder(MYILBM.wrp, &MYBORDER, 0, 0);
		MASK &= ~ZMASK;
		}
	if (TMASK & MASK) ShowTitle(MYILBM.scr, FALSE);
	if (SaveMandPic(&MYILBM, &SPECIAL_CHUNK, &USERNAME_CHUNK, MYPATH))
		DisplayError(MYILBM.win, TXT_ERR_SaveMandPic, 5L);
	if (TMASK & MASK) ShowTitle(MYILBM.scr, TRUE);
	FreeIFF (MYILBM.ParseInfo.iff);
	}
PutPointer(MYILBM.win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
}

/* ARexxFunc_LoadPalette(): Handle ARexx-Command 'LOAD_PALETTE'.   Template: "PATH,FAST/S" */
void ARexxFunc_LoadPalette(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *path = (char *) cmd->ac_ArgList[0];		/* internal only */
BOOL fast = (ULONG) (cmd->ac_ArgList[1]);

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available */
if (!(path)) {
	if (!(FileRequest(MYILBM.win, CATSTR(TXT_LoadPaletteTitle), "FLASHMANDEL:Palettes", PALETTES_DRAWER, FALSE))) {
		cmd->ac_RC = RC_WARN; cmd->ac_RC2 = 0; return;
		}
	}
else strncpy(MYPATH, path, MAX_PATHLEN);

PutPointer(MYILBM.win, 0, 0, 0, 0, 0, BUSY_POINTER);
if (MYILBM.ParseInfo.iff = AllocIFF()) {
	if (LoadPalette(&MYILBM, MYPATH, ~fast)) DisplayError(MYILBM.win, TXT_ERR_LoadMandPal, 5L);
	GetRGB32(MYILBM.vp->ColorMap, 0L, (ULONG) MYILBM.vp->ColorMap->Count, PALETTE + 1L);
	FreeIFF(MYILBM.ParseInfo.iff);
	}
else DisplayError(MYILBM.win, TXT_ERR_NoMem, 5L);

PutPointer(MYILBM.win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
}

/* ARexxFunc_SavePalette(): Handle ARexx-Command 'SAVE_PALETTE'.   Template: "PATH,FORCE/S" */
void ARexxFunc_SavePalette(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *path = (char *) cmd->ac_ArgList[0];		/* internal only */
BOOL force = (ULONG) (cmd->ac_ArgList[1]);
BPTR lock = NULL;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available */
if (!(path)) {
	if (!(FileRequest(MYILBM.win, CATSTR(TXT_SavePaletteTitle), "FLASHMANDEL:Palettes", PALETTES_DRAWER, TRUE))) {
		cmd->ac_RC = RC_WARN; cmd->ac_RC2 = 0; return; /* request cancelled */
		}
	}
else strncpy(MYPATH, path, MAX_PATHLEN);

if (force == FALSE) {
	if (lock = Lock(MYPATH, ACCESS_READ)) {
		BOOL overwrite = FALSE;
		UnLock(lock);
		if (ResourceBase) overwrite = Do_OverwriteRequest(MYILBM.win, FMSCREENNAME, 0, 0);
		else {
			struct EasyStruct my_req = {sizeof(struct EasyStruct), 0, CATSTR(TITLE_OverwriteReq), CATSTR(OverWr_TXT_Question), CATSTR(TXT_YesNo)};
			overwrite = EasyRequest(MYILBM.win, &my_req, 0);
			}
		if (overwrite == FALSE) {cmd->ac_RC = RC_WARN; cmd->ac_RC2 = 0; return;} /* request cancelled */
		}
	}

PutPointer(MYILBM.win, 0, 0, 0, 0, 0, BUSY_POINTER);
if (MYILBM.ParseInfo.iff = AllocIFF()) {
	if (SavePalette(&MYILBM, &COPYRIGHT_CHUNK, MYPATH)) DisplayError(MYILBM.win, TXT_ERR_SaveMandPal, 5L);
	FreeIFF(MYILBM.ParseInfo.iff);
	}
else DisplayError(MYILBM.win, TXT_ERR_NoMem, 5L);

PutPointer(MYILBM.win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
}

/* ARexxFunc_Print(): Handle ARexx-Command 'PRINT'.   Template: "FORCE/S" */
void ARexxFunc_Print(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
BOOL force = (ULONG) (cmd->ac_ArgList[0]);
struct FM_RxCmd_PRINT *args = NULL;

#if 0		/* external */
cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available */
if (args = (struct FM_RxCmd_PRINT *) AllocVec(sizeof(struct FM_RxCmd_PRINT), MEMF_PUBLIC|MEMF_CLEAR)) {
	args->FMRC_PRINT_Force = (cmd->ac_ArgList[0]) ? TRUE : FALSE;
	if (AddARexxEvent(DUMP_MSG, (APTR) args)) {
		cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
		}
	else FreeVec(args);
	}
#else		/* internal */
ModifyIDCMP (MYILBM.win, NULL);
ClearMenuStrip (MYILBM.win);
PutPointer (MYILBM.win, 0, 0, 0, 0, 0, BUSY_POINTER);
if (!(force)) {
	if (ResourceBase) {res = Do_PrintRequest(MYILBM.win, FMSCREENNAME, 0, 0);}
	else {res = Choice (MYILBM.win,CATSTR(TITLE_PrintReq), CATSTR(Prt_TXT_AreYouSure));}
	}
else res = TRUE;
if (res) WinDump (MYILBM.win);
else {cmd->ac_RC = RC_WARN; cmd->ac_RC2 = 0;} /* user-abort */
PutPointer (MYILBM.win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
ResetMenuStrip (MYILBM.win, MAINMENU);
ModifyIDCMP (MYILBM.win, IDCMP_STANDARD);
#endif
}

/* ARexxFunc_Quit(): Handle ARexx-Command 'QUIT'.    Template: "FORCE/S,FAST/S" */
void ARexxFunc_Quit(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
BOOL force = (ULONG) (cmd->ac_ArgList[0]);
BOOL fast = (ULONG) (cmd->ac_ArgList[1]);
struct FM_RxCmd_QUIT *args = NULL;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available */
if (args = (struct FM_RxCmd_QUIT *) AllocVec(sizeof(struct FM_RxCmd_QUIT), MEMF_PUBLIC|MEMF_CLEAR)) {
	args->FMRC_QUIT_Force = force ? TRUE : FALSE;
	args->FMRC_QUIT_Fast = fast ? TRUE : FALSE;
	if (AddARexxEvent(EXIT_MSG, (APTR) args)) {
		cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
		}
	else FreeVec(args);
	}
}

                                     /****   OPTIONS   ****/

/* ARexxFunc_ShowTitle(): Handle ARexx-Command 'SHOW_TITLE'.  Template: "BOOLEAN/A/N" */

void ARexxFunc_ShowTitle(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
BOOL show = *(LONG *) (cmd->ac_ArgList[0]);

if (!(show)) MASK &= ~TMASK;
else MASK |= TMASK;
MYILBM.TBState = TMASK & MASK;
//ShowTitle(MYILBM.scr, (LONG) MYILBM.TBState);
ShowTitle(MYILBM.scr, (LONG) show);
cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
}

/* ARexxFunc_ShowElapsed(): Handle ARexx-Command 'SHOW_ELAPSED'.  Template: - */

void ARexxFunc_ShowElapsed(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
if (! (TMASK & MASK)) ShowTitle(MYILBM.scr, TRUE);
ShowTime(MYILBM.win, CATSTR(TXT_LastCalcTime), ELAPSEDTIME);
Delay(TWOSECS);
if (! (TMASK & MASK)) {
	ShowTitle(MYILBM.scr, FALSE);
	}
cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
}

/* ARexxFunc_SetCoordinates(): Handle ARexx-Command 'SET_COORDINATES'.   Template: "STEM" */
void ARexxFunc_SetCoordinates(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *stem = (char *) cmd->ac_ArgList[0];
char varbuf[100] = {0};
long double tmp_RMIN, tmp_RMAX, tmp_IMIN, tmp_IMAX;
//long long double tmp_JKRE, tmp_JKIM;    for gcc-support
long double tmp_JKRE, tmp_JKIM;
STRPTR value = NULL;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */
if (IsNumber(stem)) {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */

if (stem) {
	sprintf((char *) &varbuf, "%s.RMIN", stem);
	if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
		tmp_RMIN = atof((const char *) value);
		if ((errno != ERANGE) && (IsNumber((char *) value))) {
			sprintf((char *) &varbuf, "%s.RMAX", stem);
			if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
				tmp_RMAX = atof((const char *) value);
				if ((errno != ERANGE) && (IsNumber((char *) value))) {
					sprintf((char *) &varbuf, "%s.IMIN", stem);
					if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
						tmp_IMIN = atof((const char *) value);
						if ((errno != ERANGE) && (IsNumber((char *) value))) {
							sprintf((char *) &varbuf, "%s.IMAX", stem);
							if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
								tmp_IMAX = atof((const char *) value);
								if ((errno != ERANGE) && (IsNumber((char *) value))) {
									sprintf((char *) &varbuf, "%s.JKRE", stem);
									if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
										tmp_JKRE = atof((const char *) value);
										if ((errno != ERANGE) && (IsNumber((char *) value))) {
											sprintf((char *) &varbuf, "%s.JKIM", stem);
											if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
												tmp_JKIM = atof((const char *) value);
												if ((errno != ERANGE) && (IsNumber((char *) value))) {

													if ((tmp_RMIN >= tmp_RMAX) || (tmp_IMIN >= tmp_IMAX)) {
														cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */
														}
													else {
														SaveCoords(MYILBM.win, FALSE);
														RMIN = tmp_RMIN; RMAX = tmp_RMAX; IMIN = tmp_IMIN; IMAX = tmp_IMAX;
														JKRE = tmp_JKRE; JKIM = tmp_JKIM;
														cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
														}
													}
												else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018;} /* invalid argument to function */
												}
											}
										else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018;} /* invalid argument to function */
										}
									}
								else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018;} /* invalid argument to function */
								}
							}
						else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018;} /* invalid argument to function */
						}
					}
				else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018;} /* invalid argument to function */
				}
			}
		else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018;} /* invalid argument to function */
		}
	}
else {
	BOOL res1 = FALSE, res2 = FALSE;
	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;

	ModifyIDCMP(MYILBM.win, NULL);
	ClearMenuStrip(MYILBM.win);
	if (ResourceBase) res1 = Do_CoordinatesRequest(MYILBM.win, FMSCREENNAME, 0, 0);
	else res1 = ShowCoords(MYILBM.win);
	if (res1) {
		if (ResourceBase) res2 = Do_RenderRequest(MYILBM.win, FMSCREENNAME, 0, 0);
		else res2 = Choice (MYILBM.win, CATSTR(TITLE_RenderReq), CATSTR(Rend_TXT_Question));
		}
	else cmd->ac_RC = RC_WARN;
	ResetMenuStrip(MYILBM.win, MAINMENU);
	ModifyIDCMP(MYILBM.win, IDCMP_STANDARD);

	if (res2) {
		if (ZMASK & MASK) {
			DrawBorder(MYILBM.wrp, &MYBORDER, 0, 0);
			MASK &= ~ZMASK;
			}
		SetMenuStop(MYILBM.win);
		PutPointer (MYILBM.win, 0, 0, 0, 0, 0, BUSY_POINTER);
		ELAPSEDTIME = DrawFractal(MYILBM.win, MYILBM.win->LeftEdge, MYILBM.win->TopEdge, MYILBM.win->Width, MYILBM.win->Height, TRUE);
		PutPointer(MYILBM.win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
		SetMenuStart(MYILBM.win);
		ShowTime(MYILBM.win, CATSTR(TXT_RecalculateTime), ELAPSEDTIME);
		}
	else cmd->ac_RC = RC_WARN;
	}
}

/* ARexxFunc_GetCoordinates(): Handle ARexx-Command 'GET_COORDINATES'.   Template: "STEM/A" */
void ARexxFunc_GetCoordinates(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *stem = (char *) cmd->ac_ArgList[0];
char varbuf[100] = {0};
char valbuf[100] = {0};

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */
if (IsNumber(stem)) {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */

sprintf((char *) &varbuf, "%s.RMIN", stem); sprintf((char *) &valbuf, "%f", RMIN);
if (!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

	sprintf((char *) &varbuf, "%s.RMAX", stem); sprintf((char *) &valbuf, "%f", RMAX);
	if (!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

		sprintf((char *) &varbuf, "%s.IMIN", stem); sprintf((char *) &valbuf, "%f", IMIN);
		if	(!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

			sprintf((char *) &varbuf, "%s.IMAX", stem); sprintf((char *) &valbuf, "%f", IMAX);
			if (!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

				sprintf((char *) &varbuf, "%s.JKRE", stem); sprintf((char *) &valbuf, "%f", JKRE);
				if (!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

					sprintf((char *) &varbuf, "%s.JKIM", stem); sprintf((char *) &valbuf, "%f", JKIM);
					if (!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

						cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
						}
					}
				}
			}
		}
	}
}

/* ARexxFunc_SetIterations(): Handle ARexx-Command 'SET_ITERATIONS'.  Template: "NUMBER/N" */

void ARexxFunc_SetIterations(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
LONG iterations = *(LONG *) (cmd->ac_ArgList[0]);
UWORD i;
BOOL def = FALSE;
CONST WORD iter_item[9][2] = {{255, 0}, {319, 1}, {511, 2}, {1023, 3}, {2047, 4}, {4095, 5},
										{8191, 6}, {16383, 7}, {32767, 8}};

if (!(iterations)) {
	ModifyIDCMP(MYILBM.win, NULL);
	ClearMenuStrip(MYILBM.win);
	while (1L) {
		if (ResourceBase) {
			MAX_ITERATIONS = Do_IterationsRequest(MYILBM.win, FMSCREENNAME, 0, 0, MAX_ITERATIONS + 1L) - 1L;
			}
		else {
			MAX_ITERATIONS = (UWORD) IntegerGad(MYILBM.win, CATSTR(TITLE_IterationsReq), CATSTR(TXT_ScrTitle_It), CATSTR(It_TXT_Iterations),MAX_ITERATIONS + 1L) - 1L;
			}
		if ((MAX_ITERATIONS >= MIN_ITERATIONS) && (MAX_ITERATIONS <= MAX_ALLOWED_ITERATIONS)) break;
		DisplayBeep(MYILBM.scr);
		}
	ResetMenuStrip(MYILBM.win, MAINMENU);
	ModifyIDCMP(MYILBM.win, IDCMP_STANDARD);
	}

else {
	if ((iterations < (MIN_ITERATIONS + 1)) || (iterations > (MAX_ALLOWED_ITERATIONS + 1))) {
		cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return; /* invalid argument to function */
		}
	MAX_ITERATIONS = iterations - 1L;
	}

ItemAddress(MAINMENU, FULLMENUNUM(1, 2, 10))->Flags &= ~CHECKED;
for (i = 0; i < 9; i++) {
	if (MAX_ITERATIONS == iter_item[i][0]) {
		ItemAddress(MAINMENU, FULLMENUNUM(1, 2, iter_item[i][1]))->Flags |= CHECKED;
		def = TRUE;
		}
	else ItemAddress(MAINMENU, FULLMENUNUM(1, 2, iter_item[i][1]))->Flags &= ~CHECKED;
	}
if (def == FALSE) ItemAddress(MAINMENU, FULLMENUNUM(1, 2, 10))->Flags |= CHECKED;

cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
}

/* ARexxFunc_GetIterations(): Handle ARexx-Command 'GET_ITERATIONS'.  Template: "VAR/A" */

void ARexxFunc_GetIterations(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *var = (char *) cmd->ac_ArgList[0];
char valbuf[100] = {0};
 
cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */
if (IsNumber(var)) return;

sprintf((char *) &valbuf, "%d", MAX_ITERATIONS + 1);
if (!(SetRexxVar(rm, (STRPTR) var, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {
	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
}

/* ARexxFunc_SetPower(): Handle ARexx-Command 'SET_POWER'.  Template: "INDEX/A/N" */

void ARexxFunc_SetPower(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
LONG Index = *(LONG *) (cmd->ac_ArgList[0]);
int s;

cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */

if ((Index >= 1) && (Index <= 11)) {
	for (s = Index - 1; s < 11; s++) {
		ItemAddress(MAINMENU, FULLMENUNUM(1, 3, s))->Flags &= ~CHECKED;
		}

	MANDChunk.Power = Index - 1;
	ItemAddress(MAINMENU, FULLMENUNUM(1, 3, Index - 1))->Flags |= CHECKED;

	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
}

/* ARexxFunc_GetPower(): Handle ARexx-Command 'GET_POWER'.  Template: "VAR/A" */

void ARexxFunc_GetPower(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *var = (char *) cmd->ac_ArgList[0];
char valbuf[100] = {0};

cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */
if (IsNumber(var)) return;

sprintf((char *) &valbuf, "%d", MANDChunk.Power + 1);
if (!(SetRexxVar(rm, (STRPTR) var, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {
	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
}

/* ARexxFunc_SetPriority(): Handle ARexx-Command 'SET_PRIORITY'.  Template: "PRI/A" */

void ARexxFunc_SetPriority(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *pristr = (char *) cmd->ac_ArgList[0];
LONG pri, p;
CONST WORD pri_item[11][2] = {{-5, 0}, {-4, 1}, {-3, 2}, {-2, 3}, {-1, 4}, {0, 6}, {1, 8}, {2, 9},
										{3, 10}, {4, 11}, {5, 12}};

cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */

if (!(IsNumber(pristr))) return;

pri = atol(pristr); if (errno != ERANGE) {
	if ((pri <= 5L) && (pri >= -5L)) {
		PRIORITY = pri;

		for (p = 0; p < 11; p++) {
			if (pri == pri_item[p][0]) ItemAddress(MAINMENU, FULLMENUNUM(1, 4, pri_item[p][1]))->Flags |= CHECKED;
			else ItemAddress(MAINMENU, FULLMENUNUM(1, 4, pri_item[p][1]))->Flags &= ~CHECKED;
			}
		cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
		}
	}
}

/* ARexxFunc_GetPriority(): Handle ARexx-Command 'GET_PRIORITY'.  Template: "VAR/A" */

void ARexxFunc_GetPriority(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *var = (char *) cmd->ac_ArgList[0];
char valbuf[100] = {0};

cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */
if (IsNumber(var)) return;

sprintf((char *) &valbuf, "%d", PRIORITY);
if (!(SetRexxVar(rm, (STRPTR) var, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {
	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
}

/* ARexxFunc_SetColorRemap(): Handle ARexx-Command 'SET_COLOR_REMAP'.  Template: "INDEX/A/N" */

void ARexxFunc_SetColorRemap(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
LONG Index = *(LONG *) (cmd->ac_ArgList[0]);
int s;
CONST ULONG bit_item[MAX_COLOR_REMAP][2] = {{LINEAR_BIT, 0}, {LOG_BIT, 1}, {REPEATED_BIT, 2}, {SQUARE_BIT, 3},
														 {ONE_BIT, 4}, {TWO_BIT, 5}, {THREE_BIT, 6}, {FOUR_BIT, 7}};

cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */

if ((Index >= MIN_COLOR_REMAP) && (Index <= MAX_COLOR_REMAP)) {
	for (s = MIN_COLOR_REMAP - 1; s < MAX_COLOR_REMAP; s++) {
		ItemAddress(MAINMENU, FULLMENUNUM(1, 5, s))->Flags &= ~CHECKED;
		MANDChunk.Flags &= ~bit_item[s][0];
		}

	MANDChunk.Flags |= bit_item[Index - 1][0];
	ItemAddress(MAINMENU, FULLMENUNUM(1, 5, bit_item[Index - 1][1]))->Flags |= CHECKED;

	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
}

/* ARexxFunc_GetColorRemap(): Handle ARexx-Command 'GET_COLOR_REMAP'.  Template: "VAR/A" */

void ARexxFunc_GetColorRemap(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *var = (char *) cmd->ac_ArgList[0];
char valbuf[100] = {0};
int s;
LONG Index = 0;
CONST ULONG bit_idx[MAX_COLOR_REMAP][2] = {{LINEAR_BIT, 1}, {LOG_BIT, 2}, {REPEATED_BIT, 3}, {SQUARE_BIT, 4},
														{ONE_BIT, 5}, {TWO_BIT, 6}, {THREE_BIT, 7}, {FOUR_BIT, 8}};

cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */
if (IsNumber(var)) return;

for (s = MIN_COLOR_REMAP - 1; s < MAX_COLOR_REMAP; s++) {	
	if (MANDChunk.Flags & bit_idx[s][0]) {Index = bit_idx[s][1]; break;}
	}

if (!(Index)) {cmd->ac_RC2 = 0; return;}

sprintf((char *) &valbuf, "%d", Index);
if (!(SetRexxVar(rm, (STRPTR) var, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {
	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
}

/* ARexxFunc_SetFractalType(): Handle ARexx-Command 'SET_FRACTAL_TYPE'.  Template: "INDEX/A/N" */

void ARexxFunc_SetFractalType(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
LONG Index = *(LONG *) (cmd->ac_ArgList[0]);

switch (Index) {
	case 1:
		MANDChunk.Flags &= ~MANDEL_BIT;
		MANDChunk.Flags |= JULIA_BIT;
		ItemAddress(MAINMENU, FULLMENUNUM(1, 6, 0))->Flags |= CHECKED;
		ItemAddress(MAINMENU, FULLMENUNUM(1, 6, 1))->Flags &= ~CHECKED;
		break;
	case 2:
		MANDChunk.Flags &= ~JULIA_BIT;
		MANDChunk.Flags |= MANDEL_BIT;
		ItemAddress(MAINMENU, FULLMENUNUM(1, 6, 0))->Flags &= ~CHECKED;
		ItemAddress(MAINMENU, FULLMENUNUM(1, 6, 1))->Flags |= CHECKED;
		break;
	default:
		cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */
		return;
	}

cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
}

/* ARexxFunc_GetFractalType(): Handle ARexx-Command 'GET_FRACTAL_TYPE'.  Template: "VAR/A" */

void ARexxFunc_GetFractalType(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *var = (char *) cmd->ac_ArgList[0];
char valbuf[100] = {0};
int Index = 0;

cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */
if (IsNumber(var)) return;

if (MANDChunk.Flags & MANDEL_BIT) Index = 2;
	else if (MANDChunk.Flags & JULIA_BIT) Index = 1;
		else return;

sprintf((char *) &valbuf, "%d", Index);
if (!(SetRexxVar(rm, (STRPTR) var, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {
	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
}

/* ARexxFunc_SetCPUType(): Handle ARexx-Command 'SET_CPU_TYPE'.  Template: "INDEX/A/N" */

void ARexxFunc_SetCPUType(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
LONG Index = *(LONG *) (cmd->ac_ArgList[0]);

switch (Index) {
	case 2:
		MANDChunk.Flags &= ~MC68K_BIT;
		MANDChunk.Flags |= PPC_BIT;
		if (CPUINFO & (CPU_603|CPU_603e|CPU_604|CPU_604e|CPU_620)) {
			ItemAddress(MAINMENU, FULLMENUNUM(1, 7, 0))->Flags &= ~CHECKED;
			ItemAddress(MAINMENU, FULLMENUNUM(1, 7, 1))->Flags |= CHECKED;
			break;
			}
	case 1:
		MANDChunk.Flags &= ~PPC_BIT;
		MANDChunk.Flags |= MC68K_BIT;
		ItemAddress(MAINMENU, FULLMENUNUM(1, 7, 0))->Flags |= CHECKED;
		ItemAddress(MAINMENU, FULLMENUNUM(1, 7, 1))->Flags &= ~CHECKED;
		break;
	default:
		cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */
	}

cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
}

/* ARexxFunc_GetCPUType(): Handle ARexx-Command 'GET_CPU_TYPE'.  Template: "VAR/A" */

void ARexxFunc_GetCPUType(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *var = (char *) cmd->ac_ArgList[0];
char valbuf[100] = {0};
int Index = 0;

cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */
if (IsNumber(var)) return;

if (MANDChunk.Flags & MC68K_BIT) Index = 1;
	else if (MANDChunk.Flags & PPC_BIT) Index = 2;
		else return;

sprintf((char *) &valbuf, "%d", Index);
if (!(SetRexxVar(rm, (STRPTR) var, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {
	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
}

                                     /****      ****/

/* ARexxFunc_ShowPreview(): Handle ARexx-Command 'SHOW_PREVIEW'.  Template: - */

void ARexxFunc_ShowPreview(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
if (NewCoords (MYILBM.win, ZOOMLINE[6], ZOOMLINE[3], ZOOMLINE[4], ZOOMLINE[5])) {
	ModifyIDCMP(MYILBM.win, NULL);
	ClearMenuStrip(MYILBM.win);
	Preview(MYILBM.win, MYILBM.win->Width, MYILBM.win->Height);
	ResetMenuStrip(MYILBM.win, MAINMENU);
	ModifyIDCMP(MYILBM.win, IDCMP_STANDARD);
	RestoreCoords(MYILBM.win);
	}
}

/* ARexxFunc_Render(): Handle ARexx-Command 'RENDER'.   Template: "FORCE/S" */
void ARexxFunc_Render(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
BOOL force = (ULONG) (cmd->ac_ArgList[0]);
struct FM_RxCmd_RENDER *args = NULL;

if (force == FALSE) {
	if (ResourceBase) res = Do_RenderRequest(MYILBM.win, FMSCREENNAME,0,0);
	else res = Choice(MYILBM.win, CATSTR(TITLE_RenderReq), CATSTR(NewScr_TXT_Question));
	if (res == FALSE) {cmd->ac_RC = RC_WARN; cmd->ac_RC2 = 0; return;}
	}

#if 0		/* external */
cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */
if (args = (struct FM_RxCmd_RENDER *) AllocVec(sizeof(struct FM_RxCmd_RENDER), MEMF_PUBLIC|MEMF_CLEAR)) {
	args->FMRC_RENDER_Force = (cmd->ac_ArgList[0]) ? TRUE : FALSE;
	if (AddARexxEvent(REDRAW_MSG, (APTR) args)) {
		cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
		}
	else FreeVec(args);
	}
#else		/* internal */
if (ZMASK & MASK) {
	DrawBorder(MYILBM.wrp, &MYBORDER, 0, 0);
	MASK &= ~ZMASK;
	}
SetMenuStop(MYILBM.win);
PutPointer (MYILBM.win, 0, 0, 0, 0, 0, BUSY_POINTER);
ELAPSEDTIME = DrawFractal(MYILBM.win, MYILBM.win->LeftEdge, MYILBM.win->TopEdge, MYILBM.win->Width, MYILBM.win->Height, TRUE);
PutPointer(MYILBM.win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
SetMenuStart(MYILBM.win);
ShowTime(MYILBM.win, CATSTR(TXT_RecalculateTime), ELAPSEDTIME);

if (rm->rm_Action & RXFF_RESULT) {
	char string[50];
	STRPTR ResultString;

	sprintf((STRPTR) &string, "%ld", ELAPSEDTIME);
	if (ResultString = CreateArgstring((STRPTR) &string, strlen((const char *) &string))) {
		cmd->ac_Result = ResultString;
		}
	}
#endif
}

/* ARexxFunc_Undo(): Handle ARexx-Command 'UNDO'.  Template: - */

void ARexxFunc_Undo(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
RestoreCoords(MYILBM.win);
}

/* ARexxFunc_SetFrame(): Handle ARexx-Command 'SET_FRAME'.   Template: "STEM/A" */
void ARexxFunc_SetFrame(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *stem = (char *) cmd->ac_ArgList[0];
char varbuf[100] = {0};
WORD tmp_left, tmp_top, tmp_right, tmp_bottom;
STRPTR value = NULL;
struct Screen *scr = NULL;

cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */
if (IsNumber(stem)) return;

if (scr = LockPubScreen(FMSCREENNAME)) {
	if (stem) {
		sprintf((char *) &varbuf, "%s.LEFT", stem);					/* frame-left */
		if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
			tmp_left = atol((const char *) value);
			if ((errno == ERANGE) || (!(IsNumber((char *) value))) || (tmp_left < 0)) goto Error;

			sprintf((char *) &varbuf, "%s.TOP", stem);					/* frame-top */
			if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
				tmp_top = atol((const char *) value);
				if ((errno == ERANGE) || (!(IsNumber((char *) value))) || (tmp_top < 0)) goto Error;

				sprintf((char *) &varbuf, "%s.RIGHT", stem);					/* frame-right */
				if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
					tmp_right = atol((const char *) value);
					if ((errno == ERANGE) || (!(IsNumber((char *) value))) || (tmp_right < 0)) goto Error;

					sprintf((char *) &varbuf, "%s.BOTTOM", stem);				/* frame-bottom */
					if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
						tmp_bottom = atol((const char *) value);
						if ((errno == ERANGE) || (!(IsNumber((char *) value))) || (tmp_bottom < 0)) goto Error;

						if (tmp_right > (scr->Width - 1)) tmp_right = scr->Width -1;
						if (tmp_bottom > (scr->Height - 1)) tmp_bottom = scr->Height -1;

						if ((tmp_right > tmp_left) && (tmp_bottom > tmp_top) && (tmp_right < scr->Width) && (tmp_bottom < scr->Height)) {
							WORD width = tmp_right - tmp_left + 1;
							WORD height = tmp_bottom - tmp_top + 1;

							if (ZMASK & MASK) {
								DrawBorder(MYILBM.wrp, &MYBORDER, 0, 0);
								MASK &= ~ZMASK;
								}

							if (width > height) (width = ScalerDiv((LONG) height,(ULONG) MYILBM.win->Width,(ULONG) MYILBM.win->Height));
							else (height = ScalerDiv((LONG) width,(ULONG) MYILBM.win->Height,(ULONG) MYILBM.win->Width));

							ZOOMLINE [8] = ZOOMLINE [0] = ZOOMLINE [6] = tmp_left;
							ZOOMLINE [1] = ZOOMLINE [3] = ZOOMLINE [9] = tmp_top;
							ZOOMLINE [2] = ZOOMLINE [4] = tmp_left + width - 1;
							ZOOMLINE [5] = ZOOMLINE [7] = tmp_top + height - 1;
							MX1 = tmp_left; MY1 = tmp_top;
							W = width, H = height;

							DrawBorder(MYILBM.wrp, &MYBORDER, 0, 0);
							MASK |= ZMASK;

							cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
							}
						else MASK &= ~ZMASK;

						if (ZMASK & MASK) {
							OnMenu(MYILBM.win, FULLMENUNUM(2, 0, NOSUB));
							OnMenu(MYILBM.win, FULLMENUNUM(2, 6, NOSUB));
							}
						else {
							OffMenu(MYILBM.win, FULLMENUNUM(2, 0, NOSUB));
							OffMenu(MYILBM.win, FULLMENUNUM(2, 6, NOSUB));
							}
						}
					}
				}
			}
		}
Error:
	UnlockPubScreen(FMSCREENNAME, scr); return;
	}
}

/* ARexxFunc_GetFrame(): Handle ARexx-Command 'GET_FRAME'.   Template: "STEM/A" */
void ARexxFunc_GetFrame(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *stem = (char *) cmd->ac_ArgList[0];
char varbuf[100] = {0};
char valbuf[100] = {0};

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */

sprintf((char *) &varbuf, "%s.LEFT", stem); sprintf((char *) &valbuf, "%d", ZOOMLINE[6]);
if	(!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

	sprintf((char *) &varbuf, "%s.TOP", stem); sprintf((char *) &valbuf, "%d", ZOOMLINE[3]);
	if	(!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

		sprintf((char *) &varbuf, "%s.RIGHT", stem); sprintf((char *) &valbuf, "%d", ZOOMLINE[4]);
		if (!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

			sprintf((char *) &varbuf, "%s.BOTTOM", stem); sprintf((char *) &valbuf, "%d", ZOOMLINE[5]);
			if (!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

				cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
				}
			}
		}
	}
}

/* ARexxFunc_Zoom(): Handle ARexx-Command 'ZOOM'.   Template: "LEFT/A/N,TOP/A/N,WIDTH/A/N,HEIGHT/A/N,REPEATS/N,FAST/S,STEPS/N" */
void ARexxFunc_Zoom(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_003; /* no memory available	*/

#if 0		/* external */
{
struct FM_RxCmd_ZOOM *args = NULL;

if (args = (struct FM_RxCmd_ZOOM *) AllocVec(sizeof(struct FM_RxCmd_ZOOM), MEMF_PUBLIC|MEMF_CLEAR)) {    /* Copy arguments */
	args->FMRC_ZOOM_Left = *(LONG *) (cmd->ac_ArgList[0]);
	args->FMRC_ZOOM_Top = *(LONG *) (cmd->ac_ArgList[1]);
	args->FMRC_ZOOM_Width = *(LONG *) (cmd->ac_ArgList[2]);
	args->FMRC_ZOOM_Height = *(LONG *) (cmd->ac_ArgList[3]);
	args->FMRC_ZOOM_Repeats = cmd->ac_ArgList[4] ? *(LONG *) (cmd->ac_ArgList[4]) : 1;
	args->FMRC_ZOOM_Fast = cmd->ac_ArgList[5] ? (ULONG) (cmd->ac_ArgList[5]) : FALSE;
	args->FMRC_ZOOM_Steps = cmd->ac_ArgList[6] ? *(LONG *) (cmd->ac_ArgList[6]) : 1;  /* not supported yet */
	if (AddARexxEvent(DRAW_MSG, (APTR) args)) {
		cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
		return;
		}
	else FreeVec(args);
	}
}
#else		/* internal */
{
LONG left = *(LONG *) (cmd->ac_ArgList[0]), top = *(LONG *) (cmd->ac_ArgList[1]);
LONG right = left + (*(LONG *) (cmd->ac_ArgList[2])) - 1;
LONG bottom = top + (*(LONG *) (cmd->ac_ArgList[3])) - 1;
LONG repeats = 1, steps = 1, elapsed = 0;
BOOL fast = (ULONG) (cmd->ac_ArgList[5]);
int i;
struct Screen *scr = NULL;
WORD scrwidth = 0, scrheight = 0;

if (cmd->ac_ArgList[4]) repeats = *(LONG *) (cmd->ac_ArgList[4]);
if (cmd->ac_ArgList[6]) steps = *(LONG *) (cmd->ac_ArgList[6]);  /* not supported yet */

if (scr = LockPubScreen(FMSCREENNAME)) {
	scrwidth = scr->Width; scrheight = scr->Height;
	UnlockPubScreen(FMSCREENNAME, scr);
	}
else {cmd->ac_RC2 = ERR10_012; return;}  /* error return from function */

 /* Check parameters */
if ((left < 0) || (top < 0) || (right > (scrwidth - 1)) || (bottom > (scrheight - 1)) || (repeats < 0)) {
	cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return; /* invalid argument to function */
	}

if (fast == FALSE) {
	for (i = 0; i < repeats; i++) {
		ZOOMLINE[6] = left; ZOOMLINE[3] = top; ZOOMLINE[4] = right; ZOOMLINE[5] = bottom;
		if (ZMASK & MASK) {
			DrawBorder(MYILBM.wrp, &MYBORDER, 0, 0);
			MASK &= ~ZMASK;
			}
		if (NewCoords(MYILBM.win, ZOOMLINE[6], ZOOMLINE[3], ZOOMLINE[4], ZOOMLINE[5])) {
			MYBITMAP = CopyBitMap(MYILBM.win, ZOOMLINE[6], ZOOMLINE[3], ZOOMLINE[4]-ZOOMLINE[6]+1, ZOOMLINE[5]-ZOOMLINE[3]+1);
			PasteBitMap(MYBITMAP, MYILBM.win, ZOOMLINE[4]-ZOOMLINE[6]+1, ZOOMLINE[5]-ZOOMLINE[3]+1);
			SetMenuStop(MYILBM.win);
			PutPointer(MYILBM.win, 0, 0, 0, 0, 0, BUSY_POINTER);
			elapsed += DrawFractal(MYILBM.win, MYILBM.win->LeftEdge, MYILBM.win->TopEdge, MYILBM.win->Width, MYILBM.win->Height, FALSE);
			PutPointer(MYILBM.win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
			SetMenuStart(MYILBM.win);
			}
		}
	}
else {
	SetMenuStop(MYILBM.win);
	for (i = 0; i < repeats; i++) {
		ZOOMLINE[6] = left; ZOOMLINE[3] = top; ZOOMLINE[4] = right; ZOOMLINE[5] = bottom;
		if (NewCoords(MYILBM.win, ZOOMLINE[6], ZOOMLINE[3], ZOOMLINE[4], ZOOMLINE[5])) {
			elapsed += DrawFractal(MYILBM.win, MYILBM.win->LeftEdge, MYILBM.win->TopEdge, MYILBM.win->Width, MYILBM.win->Height, FALSE);
			}
		}
	SetMenuStart(MYILBM.win);
	}

ELAPSEDTIME = elapsed;
ShowTime(MYILBM.win, CATSTR(TXT_ZoomTime), ELAPSEDTIME);
cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
if (rm->rm_Action & RXFF_RESULT) {
	char string[50];
	STRPTR ResultString;

	sprintf((STRPTR) &string, "%ld", elapsed);
	if (ResultString = CreateArgstring((STRPTR) &string, strlen((const char *) &string))) {
		cmd->ac_Result = ResultString;
		}
	}
}
#endif
}

                                     /****   DISPLAY   ****/

/* ARexxFunc_DoColorcycling(): Handle ARexx-Command 'DO_COLORCYCLING'.  Template: "FORWARD/S,BACKWARD/S" */

void ARexxFunc_DoColorcycling(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
BOOL forward = (ULONG) (cmd->ac_ArgList[0]);
BOOL backward = (ULONG) (cmd->ac_ArgList[1]);
BOOL flag = SHIFTLEFT;

cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; /* invalid argument to function */

if ((forward && backward) || (!forward && !backward)) return;
if (forward) flag = SHIFTRIGHT;

ModifyIDCMP(MYILBM.win, IDCMP_MOUSEBUTTONS|IDCMP_RAWKEY|IDCMP_MENUPICK);
if (TMASK & MASK) ShowTitle(MYILBM.scr, FALSE);
ClearMenuStrip (MYILBM.win);
PutPointer(MYILBM.win, 0, 0, 0, 0, 0, BUSY_POINTER);
Cycle(MYILBM.win, DELAY, flag);
PutPointer(MYILBM.win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
ResetMenuStrip(MYILBM.win, MAINMENU);
if (TMASK & MASK) ShowTitle(MYILBM.scr, TRUE);
LoadRGB32(MYILBM.vp, PALETTE);
ModifyIDCMP(MYILBM.win, IDCMP_STANDARD);
cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
}

/* ARexxFunc_SetDelay(): Handle ARexx-Command 'SET_DELAY'.  Template: "SECONDS/N" */

void ARexxFunc_SetDelay(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
LONG tmp_DELAY = *(LONG *) cmd->ac_ArgList[0];

cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;

if (!(tmp_DELAY)) {
	while (1L) {
		if (ResourceBase) tmp_DELAY = Do_CycleDelayRequest(MYILBM.win, FMSCREENNAME, 0, 0, DELAY);
		else tmp_DELAY = IntegerGad(MYILBM.win, CATSTR(TITLE_CycleDelayReq), CATSTR(TXT_ScrTitle_Cyc), CATSTR(Cyc_TXT_DelayTime), DELAY);
		if ((tmp_DELAY >= 0L) && (tmp_DELAY <= 200)) {DELAY = tmp_DELAY; return;}
		}
	}

else {
	if ((tmp_DELAY >= 0L) && (tmp_DELAY <= 200)) {DELAY = tmp_DELAY; return;}
	}

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */
DisplayBeep (MYILBM.scr);
}

/* ARexxFunc_GetDelay(): Handle ARexx-Command 'GET_DELAY'.  Template: "VAR/A" */

void ARexxFunc_GetDelay(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *var = (char *) cmd->ac_ArgList[0];
char valbuf[100] = {0};

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */

sprintf((char *) &valbuf, "%d", DELAY);
if (!(SetRexxVar(rm, (STRPTR) var, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {
	cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
	}
}

/* ARexxFunc_SetPalette(): Handle ARexx-Command 'SET_PALETTE'.  Template: "STEM,FAST/S" */

void ARexxFunc_SetPalette(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *stem = (char *) cmd->ac_ArgList[0];
BOOL fast = (ULONG) cmd->ac_ArgList[1];
char varbuf[100] = {0};

ULONG pal_length, num_colors;
struct loadrgb *TempPal = NULL;
struct RGB (*TempPalColors) [1] = NULL;
struct RGB (*PaletteColors) [1] = (struct RGB (*) [1]) (((ULONG) *(&PALETTE)) + sizeof(struct loadrgb_head));
struct DrawInfo *dri = NULL;
UWORD pen;
BOOL success = FALSE;
ULONG *value = NULL, cval, rgb8 = 0L;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */
if (IsNumber(stem)) {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */

if (stem) {
	if (dri = GetScreenDrawInfo(MYILBM.win->WScreen)) {
		num_colors = 1L << dri->dri_Depth;
		pal_length = sizeof(struct loadrgb_head) + ((num_colors + 1) * sizeof(struct RGB));
		if (TempPal = (struct loadrgb *) AllocVec(pal_length, MEMF_PUBLIC|MEMF_CLEAR)) {
			TempPal->loadrgb_lrgb.lrgb_count = num_colors;
			TempPal->loadrgb_lrgb.lrgb_first = 0;
			TempPalColors = (struct RGB (*) [1]) (((ULONG) *(&TempPal)) + sizeof(struct loadrgb_head));
			GetRGB32(ViewPortAddress(MYILBM.win)->ColorMap, 0L, num_colors, (ULONG *) TempPalColors);

			for (pen = 0; pen < num_colors; pen++) {
				sprintf((char *) &varbuf, "%s.%u", stem, pen);
				if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
					if (value) {
						rgb8 = *value;
						cval = rgb8 & 0xFF; rgb8 >>= 8;
						TempPalColors[pen]->RGB_Blue = cval | (cval << 8) | (cval << 16) | (cval << 24);
						cval = rgb8 & 0xFF; rgb8 >>= 8;
						TempPalColors[pen]->RGB_Green = cval | (cval << 8) | (cval << 16) | (cval << 24);
						cval = rgb8 & 0xFF;
						TempPalColors[pen]->RGB_Red = cval | (cval << 8) | (cval << 16) | (cval << 24);

						success = TRUE;
						}
					}
				else {success = FALSE; break;}
				}

			if (success == TRUE) {
				if (fast) LoadRGB32(ViewPortAddress(MYILBM.win), (APTR) TempPal);
				else Fade(MYILBM.win, (ULONG *) TempPal, 25L, 1L, FROMBLACK);
				GetRGB32(ViewPortAddress(MYILBM.win)->ColorMap, 0L, num_colors, (ULONG *) PaletteColors);
				cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
				}
			else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018;} /* invalid argument to function */

			FreeVec(TempPal);
			}
		else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_003;} /* no memory available	*/
		FreeScreenDrawInfo(MYILBM.win->WScreen, dri);
		}
	}

else {
	ModifyIDCMP(MYILBM.win, NULL);
	ClearMenuStrip(MYILBM.win);
	if (ResourceBase) res = Do_PalettePrefRequest(MYILBM.win, FMSCREENNAME, 0, 0, (struct loadrgb *) PALETTE);
	else res = ModifyPalette(MYILBM.win, MYILBM.win->LeftEdge + 25, MYILBM.win->TopEdge + 35, PALETTE);
	if (!res) {
		DisplayError(MYILBM.win, TXT_ERR_PaletteRequester, 15L);
		cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_012; /* error return from function */
		}
	else {cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;}
	ResetMenuStrip(MYILBM.win, MAINMENU);
	ModifyIDCMP(MYILBM.win, IDCMP_STANDARD);
	}
}

/* ARexxFunc_GetPalette(): Handle ARexx-Command 'GET_PALETTE'.  Template: "STEM/A" */

void ARexxFunc_GetPalette(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *stem = (char *) cmd->ac_ArgList[0];
char varbuf[100] = {0};
char valbuf[100] = {0};
struct RGB (*PaletteColors) [1] = (struct RGB (*) [1]) (((ULONG) *(&PALETTE)) + sizeof(struct loadrgb_head));
struct DrawInfo *dri = NULL;
UWORD pen;
ULONG value = 0L, num_colors;

BOOL success = TRUE;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */
if (IsNumber(stem)) {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */

if (dri = GetScreenDrawInfo(MYILBM.win->WScreen)) {
	num_colors = 1L << dri->dri_Depth;

	for (pen = 0; pen < num_colors; pen++) {
		value = (PaletteColors[pen]->RGB_Blue & 0xFF) | 
					(PaletteColors[pen]->RGB_Green & 0xFF00) |
					(PaletteColors[pen]->RGB_Red & 0xFF0000);
		sprintf((char *) &varbuf, "%s.%u", stem, pen);
		if	(SetRexxVar(rm, (CONST_STRPTR) &varbuf, (CONST_STRPTR) &value, sizeof(ULONG))) {
			success = FALSE;
			break;
			}
		}
	FreeScreenDrawInfo(MYILBM.win->WScreen, dri);
	}
if (success != FALSE) {cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;}
}

/* ARexxFunc_SetScreenAttrs(): Handle ARexx-Command 'SET_SCREENATTRS'.   Template: "STEM,FAST/S" */
void ARexxFunc_SetScreenAttrs(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *stem = (char *) cmd->ac_ArgList[0];
BOOL fast = (ULONG) cmd->ac_ArgList[1];
char varbuf[100] = {0};
struct FM_RxCmd_SET_SCREENATTRS *args = NULL;
ULONG tmp_mode;
WORD tmp_width, tmp_height, tmp_depth, tmp_oscan;
ULONG *value = NULL;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */
if (IsNumber(stem)) {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */

if (stem) {
	sprintf((char *) &varbuf, "%s.MODE", stem);							/* screen-mode */
	if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
		tmp_mode = *value;
		if (!(ModeNotAvailable(tmp_mode))) {

			sprintf((char *) &varbuf, "%s.WIDTH", stem);						/* screen-width */
			if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
				tmp_width = atol((const char *) value);
				if ((errno != ERANGE) && (IsNumber((char *) value))) {
					if (!tmp_width) tmp_width = STDSCREENWIDTH;

					sprintf((char *) &varbuf, "%s.HEIGHT", stem);				/* screen-height */
					if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
						tmp_height = atol((const char *) value);
						if ((errno != ERANGE) && (IsNumber((char *) value))) {
							if (!tmp_height) tmp_height = STDSCREENHEIGHT;

							sprintf((char *) &varbuf, "%s.DEPTH", stem);				/* screen-depth */
							if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
								tmp_depth = atol((const char *) value);
								if ((errno != ERANGE) && (IsNumber((char *) value))) {
									if (!tmp_depth) tmp_depth = 8;

									sprintf((char *) &varbuf, "%s.OSCANTYPE", stem);	/* overscan-type */
									if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
										char *tmpstr = (char *) value;
										if (!(strcmp(tmpstr, "TEXT"))) tmp_oscan = OSCAN_TEXT;
										else if (!(strcmp(tmpstr, "STANDARD"))) tmp_oscan = OSCAN_STANDARD;
											else if (!(strcmp(tmpstr, "MAX"))) tmp_oscan = OSCAN_MAX;
												else if (!(strcmp(tmpstr, "VIDEO"))) tmp_oscan = OSCAN_VIDEO;
													else tmp_oscan = OSCAN_TEXT;
										}
									else return;
									}
								else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */
								}
							else return;
							}
						else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */
						}
					else return;
					}
				else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */
				}
			else return;
			}
		else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */
		}
	else return;
	}
else {
	tmp_mode = INVALID_ID; tmp_width = STDSCREENWIDTH; tmp_height = STDSCREENHEIGHT, tmp_depth = 8;
	tmp_oscan = OSCAN_TEXT;
	}

#if 1								/* external */
if (args = (struct FM_RxCmd_SET_SCREENATTRS *) AllocVec(sizeof(struct FM_RxCmd_SET_SCREENATTRS), MEMF_PUBLIC|MEMF_CLEAR)) {
	args->FMRC_SETSCR_ModeID = tmp_mode;
	args->FMRC_SETSCR_Width = tmp_width;
	args->FMRC_SETSCR_Height = tmp_height;
	args->FMRC_SETSCR_Depth = tmp_depth;
	args->FMRC_SETSCR_OScanType = tmp_oscan;
	args->FMRC_SETSCR_Fast = fast;
	if (AddARexxEvent(NEWDISPLAY_MSG, (APTR) args)) {
		cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
		}
	else FreeVec(args);
	}
#else								/* internal */
;
#endif
}

/* ARexxFunc_GetScreenAttrs(): Handle ARexx-Command 'GET_SCREENATTRS'.   Template: "STEM/A" */
void ARexxFunc_GetScreenAttrs(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *stem = (char *) cmd->ac_ArgList[0];
char varbuf[100] = {0};
char valbuf[100] = {0};
struct Screen *scr = NULL;
struct DrawInfo *di = NULL;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */
if (IsNumber(stem)) {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */

if (scr = LockPubScreen(FMSCREENNAME)) {
	if (di = GetScreenDrawInfo(scr)) {
		ULONG modeid = GetVPModeID((CONST struct ViewPort *) &scr->ViewPort);

		sprintf((char *) &varbuf, "%s.MODE", stem); //sprintf((char *) &valbuf, "'%X'x", modeid);
		if	(!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &modeid, sizeof(ULONG)))) {

			sprintf((char *) &varbuf, "%s.WIDTH", stem); sprintf((char *) &valbuf, "%d", scr->Width);
			if	(!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

				sprintf((char *) &varbuf, "%s.HEIGHT", stem); sprintf((char *) &valbuf, "%d", scr->Height);
				if (!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

					sprintf((char *) &varbuf, "%s.DEPTH", stem); sprintf((char *) &valbuf, "%d", di->dri_Depth);
					if (!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

						cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
						}
					}
				}
			}
		FreeScreenDrawInfo(scr, di);
		}
	UnlockPubScreen(FMSCREENNAME, scr);
	}
}

/* ARexxFunc_SetFont(): Handle ARexx-Command 'SET_FONT'.  Template: "STEM,FAST/S" */

void ARexxFunc_SetFont(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *stem = (char *) cmd->ac_ArgList[0];
BOOL fast = (ULONG) (cmd->ac_ArgList[1]);
char varbuf[100] = {0};
struct FM_RxCmd_SET_FONT *args = NULL;
STRPTR tmp_fontname = DEF_FONTNAMESTR;
UWORD tmp_size = DEF_FONTSIZE, size1 = 0, temp;
UWORD tmp_style = MYFONTSTRUCT.ta_Style & ~(FSF_UNDERLINED | FSF_BOLD | FSF_ITALIC | FSF_EXTENDED);
STRPTR tmp_style_str = NULL;
ULONG *value = NULL;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */
if (IsNumber(stem)) {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */

if (stem) {
	sprintf((char *) &varbuf, "%s.FONTNAME", stem);						/* font-name */
	if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
		if (value) tmp_fontname = (STRPTR) value;

		sprintf((char *) &varbuf, "%s.SIZE", stem);							/* font-size */
		if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
			temp = atol((const char *) value);
			if ((errno |= ERANGE) && (IsNumber((char *) value))) {
				if (temp) tmp_size = temp;

				sprintf((char *) &varbuf, "%s.STYLE", stem);						/* font-style */
				if (!(GetRexxVar(rm, (STRPTR) &varbuf, (STRPTR *) &value))) {
					tmp_style_str = (STRPTR) value;
					if (!(tmp_style_str)) tmp_style_str = "NORMAL";

					if (strcmp(tmp_style_str, "NORMAL")) {
						char *result = NULL;
						char *templ = tmp_style_str;

						while (1L) {
							if (!(result = strtok(templ, ","))) break;
							if (!(strcmp(result, "ITALIC"))) tmp_style |= FSF_ITALIC;
								else if (!(strcmp(result, "BOLD"))) tmp_style |= FSF_BOLD;
									else if (!(strcmp(result, "UNDERLINED"))) tmp_style |= FSF_UNDERLINED;
										else if (!(strcmp(result, "EXTENDED"))) tmp_style |= FSF_EXTENDED;
							templ = NULL;
							}

						}
					}
				else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */
				}
			else return;
			}
		else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */
		}
	else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */
	}
else tmp_fontname = NULL;

#if 1								/* external */
if (tmp_fontname) size1 = strlen((const char *) tmp_fontname) + 1;
if (args = (struct FM_RxCmd_SET_FONT *) AllocVec(sizeof(struct FM_RxCmd_SET_FONT) + size1, MEMF_PUBLIC|MEMF_CLEAR)) {
	if (size1) {
		char *Str = (char *) ((ULONG) args + sizeof(struct FM_RxCmd_SET_FONT));
		strcpy(Str, (const char *) tmp_fontname);
		args->FMRC_SETFNT_FontName = (STRPTR) Str;
		}
	else args->FMRC_SETFNT_FontName = NULL;
	args->FMRC_SETFNT_Size = tmp_size;
	args->FMRC_SETFNT_Style = tmp_style;
	if (AddARexxEvent(FONTREQ_MSG, (APTR) args)) {
		cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
		}
	else FreeVec(args);
	}
#else								/* internal */
;
#endif
}

/* ARexxFunc_GetFont(): Handle ARexx-Command 'GET_FONT'.  Template: "STEM/A" */

void ARexxFunc_GetFont(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *stem = (char *) cmd->ac_ArgList[0];
char varbuf[100] = {0};
char valbuf[100] = {0};
ULONG offset = 0;

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */
if (IsNumber(stem)) {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018; return;} /* invalid argument to function */

sprintf((char *) &varbuf, "%s.FONTNAME", stem); sprintf((char *) &valbuf, "%s", MYFONTSTRUCT.ta_Name);
if	(!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

	sprintf((char *) &varbuf, "%s.SIZE", stem); sprintf((char *) &valbuf, "%d", MYFONTSTRUCT.ta_YSize);
	if	(!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {

		UWORD style = MYFONTSTRUCT.ta_Style;
		if (style & FSF_ITALIC) offset += sprintf((char *) ((ULONG) &valbuf + offset), "ITALIC,");
		if (style & FSF_BOLD) offset += sprintf((char *) ((ULONG) &valbuf + offset), "BOLD,");
		if (style & FSF_UNDERLINED) offset += sprintf((char *) ((ULONG) &valbuf + offset), "UNDERLINED,");
		if (style & FSF_EXTENDED) offset += sprintf((char *) ((ULONG) &valbuf + offset), "EXTENDED,");
		if (offset) valbuf[--offset] = 0;
		else strcpy((char *) &valbuf, "NORMAL");
		sprintf((char *) &varbuf, "%s.STYLE", stem);

		if (!(SetRexxVar(rm, (STRPTR) &varbuf, (STRPTR) &valbuf, (LONG) strlen((const char *) &valbuf)))) {
			cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
			}
		}
	}
}

/* ARexxFunc_StartTimer(): Handle ARexx-Command 'START_TIMER'.  Template: -  */

struct timeval timer1;			/* global vars */
BOOL timer_started = FALSE;

void ARexxFunc_StartTimer(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
GetSysTime(&timer1);
timer_started = TRUE;
}

/* ARexxFunc_StopTimer(): Handle ARexx-Command 'STOP_TIMER'.  Template: -  */

void ARexxFunc_StopTimer(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
struct timeval timer2 = {0};

cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;

if (timer_started == TRUE) {
	GetSysTime(&timer2);
	SubTime(&timer2, &timer1);
	timer_started = FALSE;

	if (rm->rm_Action & RXFF_RESULT) {
		char string[100];
		STRPTR ResultString;

		sprintf((STRPTR) &string, "%lu.%07lu", timer2.tv_secs, timer2.tv_micro);
		if (ResultString = CreateArgstring((STRPTR) &string, strlen((const char *) &string))) {
			cmd->ac_Result = ResultString;
			}
		}
	}

else {
	cmd->ac_RC = RC_WARN; cmd->ac_RC2 = 0; /* timer not started */
	DisplayBeep(MYILBM.scr);
	}
}

/* ARexxFunc_PlaySound(): Handle ARexx-Command 'PLAY_SOUND'.  Template: "PATH/A,ASYNC/S,REPEAT/S" */

Object *SoundObject = NULL;

void ARexxFunc_PlaySound(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
char *filename = (char *) cmd->ac_ArgList[0];
BOOL async = (ULONG) (cmd->ac_ArgList[1]);
BOOL repeat = (ULONG) (cmd->ac_ArgList[2]);

cmd->ac_RC = RC_FATAL; cmd->ac_RC2 = ERR10_012; /* error return from function */

if (async == FALSE) repeat = FALSE; /* repeat only in async-mode */
if ((async == FALSE) && (DataTypesBase->lib_Version < 40)) return; /* Need V40 for sync, because of SDTA_SignalTask ... */
if (SoundObject) DisposeDTObject(SoundObject); /* if async */

PutPointer(MYILBM.win, 0, 0, 0, 0, 0, BUSY_POINTER);
if (SoundObject = NewDTObject(filename, DTA_SourceType, DTST_FILE,
													 DTA_GroupID, GID_SOUND, DTA_Repeat, repeat,
													 TAG_DONE)) {
	if (async == FALSE) {
		ULONG readysig = 0L, readymask = 0L;
		struct Task *owntask;
		if ((readysig = AllocSignal(-1)) != -1) {
			readymask = 1 << readysig;
			owntask = FindTask(NULL);
			SetDTAttrs(SoundObject, MYILBM.win, NULL,
						  SDTA_SignalTask, owntask,
						  SDTA_SignalBitMask, readymask, TAG_DONE);
			DoDTMethod(SoundObject, NULL, NULL, DTM_TRIGGER, NULL, STM_PLAY, NULL);
			Wait(readymask|SIGBREAKF_CTRL_C);
			DisposeDTObject(SoundObject); SoundObject = NULL;
			FreeSignal(readysig);
			cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
			}
		}
	else {
		DoDTMethod(SoundObject, NULL, NULL, DTM_TRIGGER, NULL, STM_PLAY, NULL);
		cmd->ac_RC = RC_OK; cmd->ac_RC2 = 0;
		}
	}

else {cmd->ac_RC = RC_ERROR; cmd->ac_RC2 = ERR10_018;} /* invalid argument to function */
PutPointer(MYILBM.win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
}

/* ARexxFunc_StopSound(): Handle ARexx-Command 'STOP_SOUND'.  Template: - */

void ARexxFunc_StopSound(REG(a0, struct ARexxCmd *cmd), REG(a1, struct RexxMsg *rm))
{
if (SoundObject) {DisposeDTObject(SoundObject); SoundObject = NULL;}
}

/* HandleARexxEvents(): Handle external arexx-events.

		SYNOPSIS: ULONG retcode = HandleARexxEvents
						(
						struct ILBMInfo  *Ilbm;
						LONG				  *Error;
						);

		INPUTS:		Ilbm:
							Pointer to the ILBMInfo-structure.

						Error:
							Pointer to a ULONG-var, to return a error.code.

		RETURNS:		retcode:
							Messagecode or 0;
*/

ULONG HandleARexxEvents(struct ILBMInfo *Ilbm, LONG *Error)
{
ULONG retcode = 0;
struct FM_ARexxEvent *act_event = NULL;

while (IsListEmpty(&ARexxEventList) == FALSE) {
	act_event = (struct FM_ARexxEvent *) ARexxEventList.lh_Head;

	switch (act_event->FMRXC_Command) {

		case EXIT_MSG: {							/* EXIT_MSG - "QUIT" */
			struct FM_RxCmd_QUIT *args = (struct FM_RxCmd_QUIT *) act_event->FMRXC_Args;
			retcode = EXIT_MSG;
			ForceAbort = args->FMRC_QUIT_Force;
			break;
			}

		case LOADPICTURE_MSG: {					/* LOADPICTURE_MSG - "LOAD_PICTURE" */
			struct FM_RxCmd_LOADPIC *msg_loadpic = (struct FM_RxCmd_LOADPIC *) act_event->FMRXC_Args;

			if (!(msg_loadpic->FMRC_LOADPIC_Path)) {
				if (!(FileRequest(Ilbm->win, CATSTR(TXT_LoadPictureTitle), "FLASHMANDEL:Pictures", PICTURES_DRAWER, FALSE))) {
					goto LOAD_PIC_END;
					}
				}
			else strncpy(MYPATH, msg_loadpic->FMRC_LOADPIC_Path, MAX_PATHLEN);
			PutPointer(Ilbm->win, 0, 0, 0, 0, 0, BUSY_POINTER);
			if (Ilbm->ParseInfo.iff = AllocIFF()) {
				SaveCoords (Ilbm->win, TRUE);
				if (! (*Error = QueryMandPic(Ilbm, &MANDChunk, MYPATH))) {
					RMIN = MANDChunk.RMin;
					RMAX = MANDChunk.RMax;
					IMIN = MANDChunk.IMin;
					IMAX = MANDChunk.IMax;
					JKRE  = MANDChunk.JKre;
					JKIM  = MANDChunk.JKim;
					MAX_ITERATIONS = MANDChunk.Iterations - 1L;
					if (msg_loadpic->FMRC_LOADPIC_Fast == FALSE) {
						Fade(MYILBM.win, PALETTE, 25L, 1L, TOBLACK);
						}
					CloseDisplay(Ilbm, VINFO);
					Ilbm->IFFPFlags = IFFPF_BESTFIT;
					COLORS = MakeDisplay(Ilbm);
					Ilbm->IFFPFlags = NULL;
					if (! COLORS) {
						DisplayError(Ilbm->win, TXT_ERR_MakeDisplay, 20L);
						retcode = EXIT_MSG;
						break;
						}
					MASK &= ~ZMASK;
					COLORS -= RESERVED_PENS;
					if (TMASK & MASK) ShowTitle(Ilbm->scr, FALSE);
					if (LoadMandPic(Ilbm, MYPATH, ~msg_loadpic->FMRC_LOADPIC_Fast)) DisplayError(Ilbm->win, TXT_ERR_LoadMandPic, 5L);
					if (TMASK & MASK) ShowTitle(Ilbm->scr, TRUE);
					GetRGB32(Ilbm->vp->ColorMap, 0L, (ULONG) Ilbm->vp->ColorMap->Count, PALETTE + 1L);
					CheckMenu(Ilbm->win);
					}
				else DisplayError(Ilbm->win, TXT_ERR_QueryMandPic, 0);
				FreeIFF(Ilbm->ParseInfo.iff);
				}
			LOAD_PIC_END:
			PutPointer(Ilbm->win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
			break;
			}

		case NEWDISPLAY_MSG:	{					/* NEWDISPLAY_MSG - "SET_SCREENATTRS" */
			struct FM_RxCmd_SET_SCREENATTRS *msg_setscr = (struct FM_RxCmd_SET_SCREENATTRS *) act_event->FMRXC_Args;
			if (msg_setscr->FMRC_SETSCR_ModeID == INVALID_ID) {
				retcode = NEWDISPLAY_MSG;
				break;
				}
			else {
				Ilbm->camg = msg_setscr->FMRC_SETSCR_ModeID;
				Ilbm->Bmhd.w = msg_setscr->FMRC_SETSCR_Width;
				Ilbm->Bmhd.h = msg_setscr->FMRC_SETSCR_Height;
				Ilbm->Bmhd.nPlanes = msg_setscr->FMRC_SETSCR_Depth;
				Ilbm->ucliptype = msg_setscr->FMRC_SETSCR_OScanType;

				if (ZMASK & MASK) {
					DrawBorder(Ilbm->wrp, &MYBORDER, 0, 0);
					MASK &= ~ZMASK;
					}
				if (Ilbm->win->RPort->BitMap->Depth <= Ilbm->Bmhd.nPlanes) {
					MYBITMAP = CopyBitMap(Ilbm->win, Ilbm->win->LeftEdge, Ilbm->win->TopEdge, Ilbm->win->Width, Ilbm->win->Height);
					}
				Fade(Ilbm->win, PALETTE, 25L, 1L, TOBLACK);
				CloseDisplay(&MYILBM, VINFO);
				Ilbm->Bmhd.pageWidth = 0;
				Ilbm->Bmhd.pageHeight = 0;
				COLORS = MakeDisplay(Ilbm);
				if (COLORS) {
					COLORS -= RESERVED_PENS;
					PasteBitMap(MYBITMAP,Ilbm->win, (WORD) GetBitMapAttr(MYBITMAP, BMA_WIDTH), (WORD) GetBitMapAttr(MYBITMAP, BMA_HEIGHT));
					if (ResourceBase) res = Do_RenderRequest(Ilbm->win, FMSCREENNAME, 0, 0);
					else res = Choice(Ilbm->win, CATSTR(TITLE_RenderReq), CATSTR(NewScr_TXT_Question));
					if (res) {
						SetMenuStop(Ilbm->win);
						PutPointer(Ilbm->win, 0, 0, 0, 0, 0, BUSY_POINTER);
						ELAPSEDTIME = DrawFractal(Ilbm->win, Ilbm->win->LeftEdge, Ilbm->win->TopEdge, Ilbm->win->Width, Ilbm->win->Height, TRUE);
						PutPointer(Ilbm->win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
						SetMenuStart(Ilbm->win);
						ShowTime (Ilbm->win, CATSTR(TXT_RenderTime),ELAPSEDTIME);
						}
					}
				else DisplayError(NULL, TXT_ERR_MakeDisplay, 20L);
				}
			break;
			}

		case FONTREQ_MSG:	{						/* FONTREQ_MSG - "SET_FONT" */
			struct FM_RxCmd_SET_FONT *msg_setfnt = (struct FM_RxCmd_SET_FONT *) act_event->FMRXC_Args;
			if (msg_setfnt->FMRC_SETFNT_FontName) {
				MYFONTSTRUCT.ta_Name = MYFONT;
				strncpy(MYFONTSTRUCT.ta_Name, msg_setfnt->FMRC_SETFNT_FontName, MAX_FILELEN);
				MYFONTSTRUCT.ta_YSize = msg_setfnt->FMRC_SETFNT_Size;
				MYFONTSTRUCT.ta_Style = msg_setfnt->FMRC_SETFNT_Style;
				MYFONTSTRUCT.ta_Flags = FPF_DISKFONT;
				}
			else {
				if (!(FontRequest(Ilbm->win))) break;
				}
			if (ZMASK & MASK) {
				DrawBorder(Ilbm->wrp, &MYBORDER, 0, 0);
				MASK &= ~ZMASK;
				}
			PutPointer(Ilbm->win, 0, 0, 0, 0, 0, BUSY_POINTER);
			MYBITMAP = CopyBitMap(Ilbm->win, Ilbm->win->LeftEdge, Ilbm->win->TopEdge, Ilbm->win->Width, Ilbm->win->Height);
			if (msg_setfnt->FMRC_SETFNT_Fast == FALSE) Fade(Ilbm->win, PALETTE, 25L, 1L, TOBLACK);
			CloseDisplay(Ilbm, VINFO);
			if (! MakeDisplay(Ilbm)) {
				DisplayError(Ilbm->win, TXT_ERR_MakeDisplay, 20L);
				retcode = EXIT_MSG;
				break;
				}
			PasteBitMap(MYBITMAP, Ilbm->win, Ilbm->win->Width, Ilbm->win->Height);
			PutPointer(Ilbm->win, ZoomPointer, ZPW, ZPH, ZPXO, ZPYO, ZOOM_POINTER);
			break;
			}
		}
	RemoveARexxEvent(act_event);
	}

return(retcode);
}

#else /* FM_AREXX_SUPPORT */
extern struct Library *ResourceBase;  /* dummy */
#endif /* FM_AREXX_SUPPORT */
