/*  menucmdd.c   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */
#include <string.h>
#include "newaloc.h"
#include "shared.h"
#include "menucmdd.h"
#include "tremfnc.h"
#include "cgidbg.h"
#include "dspe_app.h"
#include "yacintfc.h"

ExecuteCmdDsp Master ;

static void DumpLimits(ParameterLimits * Lim)
{
	TheLog << "Limits are: int = " << Lim->IntLimits << ", float  = " <<
		Lim->FloatLimits << "\n\tstring = " << 
		Lim->StringLimits << ", stack = " << Lim->StackLimits <<
		"\n" ;
}

void InterpretMenuCommand(PacketHeader& Head, const char * Buffer)
{
	// LogOut << "InterpretmenuCommand`" << Buffer << "'\n" ;
	Master.SetParameters(Head,Buffer);
	// LogOut << "Back from SetParameters\n" ;
	State.ClearError();
	State.clear_warn();
	Master.Execute();
	// LogOut << "Back from Execute\n" ;
	State.clear_warn(1);
	State.ClearError();
	DspApplication::check_redisplay();
}

void ExecuteCmdDsp::Init(CommandParameters * params)
{
	if (params) Params = params ;
	else {
		Params = new CommandParameters ;
		Params->IntParameters = 0;
		Params->StringParameters = 0;
		Params->FloatParameters = 0;
		Params->StackParameters = 0;
	}
}

const char * ExecuteCmdDsp::GetMenuStackName(int index)
{
	return Params->StringParameters[index];
}

void ExecuteCmdDsp::Execute()
{
	TheCall = AllActions[Params->RoutineIndex-1];
/*
 *	LogOut << "Calling " << Params->RoutineIndex-1 << " with parameters "
 *		<< Params->ParameterType << "\n" ;
 */
	DoCall();
	// LogOut << "Back from DoCall\n" ;
}


void ExecuteCmdDsp::SetParameters(PacketHeader& Head, const char *Data)
{
	const StringBufSize = 1024 ;
	static char StringBuf[StringBufSize+1];
	enum State{StateClear,StateIntParameters,StateStringParameters,
		StateFloatParameters};
	static State TheState = StateClear;
	static char SaveBuf[MaxPacketSize];
	static int BytesNeeded ;
	static int StringsNeeded ;
	static char * Dest ;
	static ParameterLimits * Lim ;
	int Size = Head.DataSize ;
	int BytesToMove ;
	char ** CurrentString ;
	int i;
	// LogOut << "Start SetParameters - TheState = " << TheState << "\n" ;
	switch (TheState) {
case StateClear:
		Params->IntParameters = 0 ;
		Params->StringParameters = 0 ;
		Params->FloatParameters = 0;
		Params->StackParameters = 0;
		Params->RoutineIndex = Head.Identifier ;
		TheState = StateIntParameters ;
		BytesToMove = sizeof(Params->ParameterType) ;
		MoveNBytes((char *) &(Params->ParameterType),Data,BytesToMove);
		Data += BytesToMove ;
		Size -= BytesToMove ;
		TheState = StateIntParameters ;
		Lim = RemoteParamLimits + Params->ParameterType;
		// DumpLimits(Lim);
		BytesNeeded =
			sizeof(*(Params->IntParameters)) * Lim->IntLimits ;
		if (Lim->IntLimits) Params->IntParameters =
			new int[Lim->IntLimits];
		Dest = (char *) Params->IntParameters ;	
case StateIntParameters:
/*
 *		LogOut << "In StateIntParameters, BytesNeeded = " <<
 *			BytesNeeded << "\n" ;
 */
		BytesToMove = BytesNeeded ;
		if (BytesToMove > Size) BytesToMove = Size ;
		if (BytesToMove) {
			MoveNBytes((char *)Params->IntParameters,
				Data,BytesToMove);
			Data += BytesToMove ;
			Size -= BytesToMove ;
			Dest += BytesToMove ;
			BytesNeeded -= BytesToMove ;
		}
		if (BytesNeeded > 0) return ;
		StringsNeeded = Lim->StringLimits + Lim->StackLimits ;
		Params->StackParameters = new int[Lim->StackLimits];
		for (i = 0 ; i < Lim->StackLimits;i++)
			Params->StackParameters[i] = i + Lim->StringLimits;
		if (StringsNeeded) {
			Params->StringParameters = new char * [StringsNeeded];
			CurrentString = Params->StringParameters;
			Dest = StringBuf ;
		}
case StateStringParameters:
/*
 *		LogOut << "In StateStringParameters StringsNeeded = " <<
 *			StringsNeeded << "\n" ;
 */
		while (StringsNeeded) {
			while (Size && *Data &&
				(Dest < StringBuf + StringBufSize)) {
				// LogOut << "String::" << Data << "\n" ;
				*Dest++ = *Data++ ;
				Size--;
			}
			if (!*Data) {
				*Dest++ = *Data++ ;
				// LogOut << "Got :: " << StringBuf << "\n" ;
				int Length = strlen(StringBuf);
				*CurrentString = new char[Length+1];
				strcpy(*CurrentString++,StringBuf);
				Dest = StringBuf ;
				StringsNeeded-- ;
			} else if(!Size) return ;
			else DbgError(
				"CommandParameters::SetParameters",
				"string too long");
		}
		
		TheState = StateFloatParameters ;
		BytesNeeded = sizeof(*(Params->FloatParameters)) *
			Lim->FloatLimits ;
		if (Lim->FloatLimits) Params->FloatParameters = new
			double[Lim->FloatLimits];
		Dest = (char *) Params->FloatParameters ;	
case StateFloatParameters:
/*
 *		LogOut << "In StateFloatParameters, BytesNeeded = " <<
 *			BytesNeeded << "\n" ;
 */
		BytesToMove = BytesNeeded ;
		if (BytesToMove > Size) BytesToMove = Size ;
		if (BytesToMove) {
			MoveNBytes((char *)Params->FloatParameters,
				Data,BytesToMove);
			Data += BytesToMove ;
			Size -= BytesToMove ;
			Dest += BytesToMove ;
			BytesNeeded -= BytesToMove ;
		}
		if (BytesNeeded > 0) return ;
/*
 *		TheState = StateStackParameters ;
 *		BytesNeeded = sizeof(*StackParameters)*Lim->StackLimits ;
 *		if (Lim->StackLimits) StackParameters = new
 *			int[Lim->StackLimits];
 *		Dest = (char *) StackParameters ;	
 * case StateStackParameters:
 *		BytesToMove = BytesNeeded ;
 *		if (BytesToMove > Size) BytesToMove = Size ;
 *		if (BytesToMove) {
 *			MoveNBytes((char *)StackParameters,Data,BytesToMove);
 *			Data += BytesToMove ;
 *			Size -= BytesToMove ;
 *			Dest += BytesToMove ;
 *			BytesNeeded -= BytesToMove ;
 *		}
 *		if (BytesNeeded > 0) return ;
 */
		TheState = StateClear ;
	}
}

