/*  user.c   */
/*  Copyright 1989 Mountain Math Software  */
/*  All Rights Reserved                    */
#include <strstream.h>
#include <stream.h>
#include <string.h>
#include <ctype.h>
 
#include "outtok.h"
#include "baseio.h"
#include "yacintfc.h"
#include "interp.h"

#include "intfc.h"
#include "usercom.h"
#include "user.h"
#include "array.h"
#include "cgidbg.h"
#include "stattyp.h"
#include "dspguicom.h"
#include "mkstr.h"
#include "dspe_app.h"

static int ArrayConvertError()
{
	*Output + OutputCppHelp <<
		"Cannot make a scalar object from an array" ;
	return 0;
}

static int EntityConvertError()
{
	*Output + OutputCppHelp <<
		"Cannot make an object from a numeric value.\n" ;
	return 0;
}


static int ParameterError(const char * Name)
{
	*Output << "This error is in parameter `" << Name << "'.\n" ;
	return 0;
}

// Should be made a member function when we recompile **************
static DecType GetDecType(OneParameter& Parm)
{
	if (Parm.IntP) return DecInt ;
	if (Parm.FloatP) return DecFloat ;
	if (Parm.EntityP) return DecEnt ;
	if (Parm.StringP) return DecString ;
	if (!Parm.ArrayP) DbgError("GetDecType", "all null pointers");
	return Parm.ArrayP->Type ;
}


static int TypeCheckConvert(ValueType * Source, DecType DestType,
	int DestArray=0, int DestNumeric=0, DecType DestArrayType=DecInvalid)
{
	int SourceArray = !Source->IsScalar();
	// LogForm("Dest Array = %d, Source Array = %d", DestArray,SourceArray);
	DecType SourceType = Source->Type ;
	if (SourceArray && !DestArray) {
		*Output + OutputCppHelp <<
			"Cannot make a pointer from an object.\n" ;
		return  0;
	}
	if (!SourceArray && DestArray) {
		*Output + OutputCppHelp <<
		    "Cannot make an object from a pointer.\n" ;
		return 0;
	}
	if (DestArray && SourceArray) {
		if (DestArrayType != SourceType) {
		  *Output + OutputCppHelp <<
		    "Illegal pointer type.\n" ;
			return 0;
		}
		return 1 ;
	}
	if (!DestNumeric || !IsNumeric(SourceType)) {
		if (DecEnt == SourceType  && (DecEnt == DestType ||
		DecDspPP == DestType)) return 1 ;
		if (DecString == DestType ) {
			if (DecString == DestType || DecName == DestType)
				return 1;
			if (DecInt == DestType && !Source->Value.ValInt) {
				// LogOut << "TypeCheckConvert - to string\n" ;
				Source->Type = DecString ;
				Source->Value.ValName = 0 ;
				return 1 ;
			}
		}
		*Output + OutputCppHelp << "Invalid data type.\n" ;
		return 0;
	}
	if (IsComplex(SourceType)) {
		*Output + OutputCppHelp <<
			"Complex usage not supported.\n" ;
		return 0;
	}
	// OutTokens Out(&LogOut);
	// Source->Dump(Out,0);

	double DoubSource = ConvertToDouble(Source);

	if (SourceType == DecFloat && (DestType == DecMachWord ||
		DestType == DecAccMachWord)) DoubSource =
			NormToMachWord(DoubSource) ;

	// LogOut << "DoubSource = " << DoubSource << "\n" ;
	int Return = DoubleAssign(Source,DestType,&DoubSource);
	// Source->Dump(Out,0);
	return Return ;
	// if(IsBuiltInClass(DestType)) delete Dest->Value.ValBuiltInClass ;
}

int ReturnCheckConvert(ValueType * Source, DecType DestType)
{
	return TypeCheckConvert(Source,DestType);
}

static int TypeCheckConvert(ValueType * Val, OneParameter * Param)
{
	// LogOut << "TypeCheckConvert for " << Param->Name << "\n" ;
	DecType ArrayType = DecInvalid ;
	if (Param->ArrayP) ArrayType = Param->ArrayP->Type ;
	return TypeCheckConvert(Val,GetDecType(*Param),
		!Param->IsScalar(),Param->IsNumeric(),ArrayType);
} 

static const char * PrtNull(const char * Str)
{
	if (Str) return Str;
	return 	"" ;
	// return 	"NULL for object name" ;
}

/* static int TypeCheckConvert(ValueType * Val, OneParameter * Param)
 * {
 *	// OutTokens Temp(OutputCppHelp);
 *	// Val->Dump(Temp,0);
 *	// LogForm("TypeCheckConvert Val->Type = %d", Val->Type);
 *	int SourceArray = !Val->IsScalar();
 *	int DestArray = !Param->IsScalar();
 *	const char * Name = Param->Name;
 *	// LogForm("Source Array = %d, Dest Array = %d", SourceArray,DestArray);
 *	// LogMsg("Parameter Name -",Name);
 *	DecType SourceType = Val->Type ;
 *	if (DestArray && !SourceArray) {
 *		*Output + OutputCppHelp <<
 *			"Cannot make a pointer from an object.\n" ;
 *		return ParameterError(Name);
 *	}
 *	if (!DestArray && SourceArray) {
 *		*Output + OutputCppHelp <<
 *		    "Cannot make an object from a pointer for parameter\n" ;
 *		return ParameterError(Name) ;
 *	}
 *	if (SourceArray && DestArray) {
 *		if (SourceType != Param->ArrayP->Type) {
 *		  *Output + OutputCppHelp <<
 *		    "Pointer parameters must point to the same object type.\n";
 *		  return ParameterError(Name);
 *		}
 *		return 1 ;
 *	}
 *	if (!IsNumeric(SourceType) || !Param->IsNumeric()) {
 *		if (Param->EntityP && (DecEnt == SourceType ||
 *		DecDspPP == SourceType)) return 1 ;
 *		if (Param->StringP && (DecString == SourceType ||
 *			DecName == SourceType)) return 1;
 *		*Output + OutputCppHelp << "Invalid parameter type.\n" ;
 *		return ParameterError(Name) ;
 *	}
 *	if (IsComplex(SourceType) || Param->IsComplex()) {
 *		*Output + OutputCppHelp <<
 *			"Complex parameters are not supported.\n" ;
 *		return ParameterError(Name);
 *	}
 *	double Source = ConvertToDouble(Val);
 *	// LogMsg("Val = ",ConvertToString(Source));
 *	if (IsBuiltInClass(SourceType)) delete Val->Value.ValBuiltInClass ;
 *	DecType DestType = GetDecType(*Param);
 *	// LogForm("DestType = %d",DestType);
 *	return DoubleAssign(Val,DestType,&Source);
 * }
 */

static void UparErr(char * msg)
{
	DbgError("UserParameters::SetValues",msg);
}

static void too_many_parameters(ParameterList *List, int i)
{
	*Output + OutputCppHelp <<
		"There are too many parameters for the constructor of " 
		<< List->GetName() << ".\nExcluding the optional name " ;
		if (i>1) *Output << dec(i-1) ;
		else *Output << "none are allowed. " << List->Size() ;
		if (List->Size() > 1) *Output << " were specified.\n" ;
		else *Output << " was specified.\n" ;
}

int UserParameters::SetParamValues(int32 NextNameIndex, ValueType *Vals)
{
	if (Vals->Type != DecParam) UparErr("no parameters") ;

	ParameterList * List = Vals->Value.ValParam ;
	if (!List) UparErr("NULL parameter list");

	ParameterListIterator Next(*List);
	int i = 1;
	if (NextNameIndex < 0) {
		i = 0; // kludge to avoid recompiling
		NextNameIndex = 0;
	}
	int DefaultOk = 0 ;
	ValueType * Val ;
	while (Val = Next()) {
		if (!(Parameters+i)->Name) {
			too_many_parameters(List,i);
			return 0;
		}
		DefaultOk = DefaultOk || (Parameters+i)->FirstDefaultParameter;
		if (!TypeCheckConvert(Val,Parameters+i)) {
			*Output + OutputCppHelp <<
				"Conversion error in parameter "
				<< i << " (" << (Parameters+i)->Name <<
				").\n" ;
			return 0;
		}
		// *Output+OutputCppHelp<<"Calling Get parameter, Val = "<<
		// dec(Val->Value.ValInt) <<", i = " << dec(i) <<".\n";
		if (!(Parameters+i)->GetParameter(NextNameIndex,Val,i))
			return 0 ;
		i++;
	}
	return CompleteSetParamValues(i,DefaultOk, List->GetName(),
		NextNameIndex);
}

int UserParameters::CompleteSetParamValues(int i, int DefaultOk,
	const char * Name, int NextNameIndex)
{
	// LogOut << "UserParameters::CompleteSetParamValues\n" ;
	// LogOut << "i = " << i << ", Name = " << (void *) Name << "\n" ;
	// if (Name) LogOut << "Name = " << Name << "\n" ;
	for (;(Parameters+i)->Name;i++) {
		if (DefaultOk || (Parameters+i)->FirstDefaultParameter) {
			GetDefaultParameters(0, i);
		} else {
			State.Error("one or more parameters for `",Name, "' is missing.\n",
				"The first missing parameter is `",(Parameters+i)->Name,"'");
			return 0 ;
		}
	}
	if (Check) {
		if (!(Check)(CheckActionCheck,*this)) {
			return 0;
		}
	}
	return 1;
}

static void DeleteInitialNameParameter(ParameterList * List)
{
	ParameterListIterator Next(*List);
	ValueType * First = Next();
	if (First->Type != DecString) return ;
/*
 *	LogOut << "DeleteInitialNameParameter - \"" <<
 *		First->Value.ValName << "\" - \"" <<
 *		List->GetName() << "\"\n" ;
 */
	if (strcmp(First->Value.ValName,List->GetName())) return ;
	List->Get(); // delete first element from list
}

int UserParameters::SetValues(int32 NextNameIndex, ValueType *Vals)
{
	// LogOut << "UserParameters::SetValues(" << NextNameIndex << ",)\n" ;
	// start checking consistency
	// convention is that the first parameter is always the
	// node name and it is called Name
	// LogOut << "UserParameters::SetValues(" <<  NextNameIndex << ",)\n" ;
	if (strcmp(Parameters->Name,"Name") || !Parameters->StringP)
		UparErr("bad name");

	if (Vals->Type == DecName) {
		// no parameters specified - use defaults
		ValueType * NameParm = new ValueType(DecName,
			Vals->Value.ValName) ;
		Parameters->StringP->GetNameParameter(
			Parameters->Name,NextNameIndex,NameParm) ;
		if (State.IsError()) return 0 ;
		GetDefaultParameters() ;
		return 1;
	} else {
		ParameterList * List = Vals->Value.ValParam ;
		if (!List) UparErr("NULL parameter list");
		DeleteInitialNameParameter(List);
		ValueType * NameParm = new ValueType(DecName,List->GetName()) ;
		Parameters->StringP->GetNameParameter(
			Parameters->Name,NextNameIndex,NameParm) ;
		if (State.IsError()) return 0 ;
		return SetParamValues(NextNameIndex,Vals);
	}
}

int UserParameters::SetValues(ValueType * Vals)
{
	// LogOut << "UserParameters::SetValues()\n" ;
	// start checking consistency
	// convention is that the first parameter is always the
	// node name and it is called Name
	// LogOut << "UserParameters::SetValues()\n" ;
	if (Vals->Type == DecName) {
		// LogOut << "no parameters specified - use defaults/n" ;
		ValueType * NameParm = new ValueType(DecName,
			Vals->Value.ValName) ;
		GetDefaultParameters() ;
		return 1;
	} else {
		if (Vals->Type != DecParam) UparErr("no parameters") ;

		ParameterList * List = Vals->Value.ValParam ;
		if (!List) UparErr("NULL parameter list");

		int DefaultOk = 0 ;
		ParameterListIterator Next(*List);
		int i = 0;
		ValueType * Val ;
		while (Val = Next()) {
			if (!(Parameters+i)->Name) {
				too_many_parameters(List,i);
				return 0;
			}
			DefaultOk = DefaultOk ||
				(Parameters+i)->FirstDefaultParameter;
			if (!TypeCheckConvert(Val,Parameters+i)) return 0;
			// *Output+OutputCppHelp<<"Calling Get parameter, Val = "<<
			// dec(Val->Value.ValInt) <<", i = " << dec(i) <<".\n";
			if (!(Parameters+i)->GetParameter(0,Val,i)) return 0 ;
			i++;
		}
		return CompleteSetParamValues(i,DefaultOk,List->GetName());
	}
}
	
void UserParameters::GetDefaultParameters(UserEntity * TheObject, int i)
{
/*
 *	LogOut << "UserParameters::GetDefaultParameters(" << (void *) TheObject
 *		<< ", " << i << ")\n" ;
 */
	while (Parameters[i].Name)
		Parameters[i++].GetDefaultParameter(TheObject);
	// LogOut << "UserParameters::GetDefaultParameters exit\n" ;
}

int UserParameters::GetParameters(int32 NextNameIndex)
{
	StringParam * StrP = Parameters[0].StringP ;
	if (!StrP) DbgError("UserParameters::GetParameters","Name missing");
	StrP->GetNameParameter(Parameters[0].Name,NextNameIndex,0) ;
	if (State.IsError()) return 0 ;
	int i = 1 ;
	while (Parameters[i].Name)
		if (!Parameters[i++].GetParameter(NextNameIndex,0)) return 0 ;
	if (State.IsError()) return 0 ;
	return 1;
}

int32 UserParameters::GetIntParameterValue(const char * name)
{
	OneParameter * OneP = GetOneParameter(name);
	if (OneP) return OneP->GetIntParameterValue();
	DbgError("UserParameters::Int" , "no such int");
	return 0;
}

const char * UserParameters::GetStringParameterValue(const char * name)
{
	OneParameter * OneP = GetOneParameter(name);
	if (OneP) return OneP->GetStringParameterValue();
	DbgError("UserParameters::String" , "no such string");
	return 0;
}

UserEntity * UserParameters::GetEntityParameterValue(const char * name)
{
	OneParameter * OneP = GetOneParameter(name);
	if (OneP) return OneP->GetEntityParameterValue();
	DbgError("UserParameters::Entity" , "no such Entity");
	return 0;
}

double UserParameters::GetFloatParameterValue(const char * name)
{
	OneParameter * OneP = GetOneParameter(name);
	if (OneP) return OneP->GetFloatParameterValue();
	DbgError("UserParameters::Float" , "no such float");
	return 0;
}

void * UserParameters::GetArrayParameterValue(const char * name)
{
	OneParameter * OneP = GetOneParameter(name);
	if (OneP) return OneP->GetArrayParameterValue();
	DbgError("UserParameters::ArrrayP" , "no such ArrayP");
	return 0;
}

int32 UserParameters::GetLengthArrayParameterValue(const char * name)
{
	OneParameter * OneP = GetOneParameter(name);
	if (OneP) return OneP->GetLengthArrayParameterValue();
	DbgError("UserParameters::LengthArrayp" , "no such ArrayP");
	return 0;
}


void StringParam::GetNameParameter( const char *Name, int32 NextNameIndex,
	ValueType * Val)
{
	if (!State.IsInteractive() && !Val) {
		CurrentValue = 0 ;
		State.Error("missing parameter");
		return ;
	}
	*Output + OutputPrompt ;
	const char * LocalDefault = MakeString(Default,NextNameIndex) ;
	if (!Val) *Output + OutputPrompt << DspGuiCommon::default_prefix << 
		PrtNull(LocalDefault) << DspGuiCommon::default_suffix  <<
		Name << "':\n" ;
	int InteractiveInput = Val == 0 ;
	for (;;) {
		char Buf[BufSize] ;
		int OK=1;
		char * RawBuf ;
		if (InteractiveInput) {
			RawBuf = GetRawBufLine(InputPrompt) ;
			Buf[0] = *RawBuf ;
			if (!Buf[0]) CurrentValue = LocalDefault ;
			else {
				if (RawBuf[0] == '\03') {
					State.Error("user aborted input");
					return ;
				}
				istrstream Temp(RawBuf,BufSize-1);
				memset(Buf,'\0',BufSize);
				Temp >> Buf ;
				if (Temp.bad()) {
					*Output + OutputPrompt <<
						"Invalid C++ string input: `" <<
						RawBuf << "'.\n" ;
					OK=0;
				}
				if (!DspApplication::valid_object_name(Buf)) {
					*Output + OutputPrompt <<
                        "Invalid object name `" << Buf << "'. " <<
						DspApplication::explain_legal_object_name() <<  ".\n" ;
					OK=0 ;
				}
			}
		} else CurrentValue = strcpy(Buf,Val->Value.ValName) ;
		if (OK) {
			if (Buf[0]) if (Legal) if (!Legal(Buf)) OK=0;
			if (OK) {
				NameInUse InUse =
					AllEntityLists->CheckNameInUse(Buf);
				if (InUse != InUseNo) {
					*Output + OutputPrompt << "Name `" <<
						Buf << "' is used for " <<
						InUseString[InUse] << ".\n" ;
					OK=0;
				}
			}
			if (OK) {
				if (InteractiveInput) if (!Buf[0]) return ;
						// using current default
				CurrentValue = Concatenate(Buf) ;
					// strcpy(new char[strlen(Buf)+1],Buf) ;
				delete (char *) LocalDefault ;
				return  ;
			}
			if (Legal) {
				if (!InteractiveInput) *Output + OutputPrompt <<
					"String for parameter `" << Name << "' must " ; 
				else *Output + OutputPrompt << "Input string must " ;
					
				if (!strcmp(Legal(0),"OK")) *Output + OutputPrompt << Legal(0)
					<< "\nand must" ;
				*Output << " not be in use\n`" << CurrentValue <<
				"' is not valid.\n" ;
			}
			if (!State.IsInteractive()) {
				State.Error("bad parameter");
				return ;
			}
			InteractiveInput = 1 ;
		}
		*Output + OutputPrompt << DspGuiCommon::default_prefix <<
			LocalDefault << DspGuiCommon::default_suffix << Name << 
			"' or specify a new string:\n" ;
	}
}

void StringParam::GetDefaultParameter()
{
	CurrentValue = Default ;
}



void StringParam::GetParameter(const char *Name, int32 ,
	ValueType * Val,int index )
{
	// LogOut << "StringParam::GetParameter(" << Name << ",)\n" ;
	if (!State.IsInteractive() && !Val) {
		CurrentValue = 0 ;
		State.Error("missing parameter");
		return ;
	}
	const char * LocalDefault = Default ;

	if (!Val) *Output + OutputPrompt << DspGuiCommon::default_prefix << 
		PrtNull(LocalDefault) << DspGuiCommon::default_suffix <<
		Name << "':\n" ;
	int InteractiveInput = Val == 0 ;
	for (;;) {
		char Buf[BufSize] ;
		int OK=1;
		char * RawBuf ;
		if (InteractiveInput) {
			RawBuf = GetRawBufLine(InputPrompt) ;
			Buf[0] = *RawBuf ;
			if (!Buf[0]) {
				CurrentValue = LocalDefault ;
				if (!CurrentValue) return ;
			} else {
				if (RawBuf[0] == '\03') {
					State.Error("user aborted input");
					return ;
				}
				istrstream Temp(RawBuf,BufSize-1);
				memset(Buf,'\0',BufSize);
				Temp >> Buf;
				if (Temp.bad()) {
					*Output + OutputPrompt <<
					"Invalid C++ string input: `" <<
						RawBuf << "'.\n" ;
					OK=0;
				}
			}
		} else if (Val->Value.ValName)
			CurrentValue = strcpy(Buf,Val->Value.ValName) ;
		else {
			CurrentValue = 0 ;
			Buf[0] = 0;
			// LogOut << "Null Val.ValName\n" ;
		}
		if (OK) {
			if (Buf[0]) if (Legal) if (!Legal(Buf)) OK=0;
			if (OK) {
				if (InteractiveInput) if (!Buf[0]) return ;
						// using current default
				CurrentValue = Concatenate(Buf);
/*
 *				LogOut << "Returning CurrentValue = 0x"
 *					<< hex((long) CurrentValue)  << "\n" ;
 *				if (CurrentValue) LogOut << "CurrentValue is `" <<
 *						CurrentValue << "'\n" ;
 */
				return  ;
			}
			if (!InteractiveInput) *Output + OutputPrompt <<
				"String for parameter `" << Name << "' must " ; 
			else *Output + OutputPrompt << "Input string must " ;
			*Output + OutputPrompt << Legal(0) << ". `" <<
				PrtNull(CurrentValue) <<
				"' is not valid.\n" ;
			if (!State.IsInteractive()) {
				State.Error("bad parameter");
				return;
			}
			InteractiveInput = 1 ;
		}
		*Output + OutputPrompt << DspGuiCommon::default_prefix <<
			PrtNull(LocalDefault) << DspGuiCommon::default_suffix << Name ;
			if (index) *Output + OutputPrompt <<
				"', parameter " << dec(index) << "," ;
			else *Output + OutputPrompt << "'" ;
			*Output + OutputPrompt <<" or specify a new string:\n" ;
	}
}

const char * LegalEntityName(const char *nm )
{
	if (!nm) return 0 ;
	if (!*nm) return 0 ;
	// LogOut << "LegalEntityName(" << nm << ")\n" ;
	if (DspApplication::valid_object_name(nm)) return "OK" ;
	return 0 ;
}

const char * Procedure::GetTypeName()
{
	return TypeName ;
}

int Procedure::CppList(OutTokens& Out,CppListCmds)
{
	Out.NextFillOut(GetName()) ;
	Out.NextFillOut("Procedure C list not in yet") ;
	return 0 ;
}

void Procedure::Describe(OutTokens& Out,ListEntity)
{
	Out.NextFillOut(GetName()) ;
	Out.NextFillOut("Procedure describe not in yet");
}

void Procedure::Dump(OutTokens& Out,ValueTypeList*)
{
	Out.NextFillOut(GetName()) ;
	Out.NextFillOut("rest of Procedure dump not in");
}

OneParameter * InteractiveEntity::GetOneParameter(const char * Name)
{
	return Parameters->GetOneParameter(Name);
}

OneParameter * UserParameters::GetOneParameter(const char * Name)
{
	for (OneParameter * TheParameter = Parameters; TheParameter->Name;
		TheParameter++) if (!strcmp(TheParameter->Name,Name)) return
		TheParameter ;
	return 0;
}

Procedure::Procedure(const char * Name, UserProcedure call,
	UserParameters * parameters, const char * type,
	Procedure * Ovld, const char * MenuMessage):UserEntity(Name) 
{
/*
 *	LogForm ("Procedure::Procedure(0x%x, 0x%x)",(long) call,
 *		(long) parameters);
 *	LogMsg ("Name is -",Name);
 */
	Call = call;
	TheParameters = parameters ;
	TypeName = type ;
	Overload = Ovld ;
	MenuLine = MenuMessage ;
} 

ValueType * Procedure::DoCall(OutTokens& Out,EntityReq Req,UserEntity *Ent)
{
	// LogForm("InProcedure DoCall Call = 0x%x", (long) Call);
	return Call(Out,Req,TheParameters,Ent);
}

int EntityParam::CppListDec(OutTokens& Out, CppListCmds)
{
	if (!CurrentValue) return 1;
	// LogOut << "EntityParam::CppListDec - " << CurrentValue->GetName()
	//	<< "\n" ;
	return CurrentValue->SaveState(Out,CppListCtor);
}

void UserParameters::GetDefaultName(InteractiveEntity * ent)
{
	Parameters->GetDefaultName(ent);
}

void OneParameter::GetDefaultName(InteractiveEntity * ent)
{
	if(!StringP) DbgError("OneParameter::GetDefaultName","not a string");
	StringP->GetDefaultName(ent);
}

int OneParameter::CppListDec(OutTokens& Out, CppListCmds Cmd,
	UserEntity * ThisObject) 
{
	if (!EntityP && !ArrayP) return 1 ;
	if (!ThisObject) {
		// LogOut << "OneParameter::CppListDec null Object\n" ;
		return 0;
	}
	ThisObject->Describe(Out,ListSetParameterValues);
	// Set to current object value - may have changed in
	// declaraing undeclared parameters
	if (EntityP) return EntityP->CppListDec(Out,Cmd);
	else return ArrayP->CppListDec(Out,Cmd);
}

int UserParameters::CppListDec(OutTokens& Out, CppListCmds Cmd,
	UserEntity * ThisObject) 
{
	int Ok = 1;
	for (OneParameter * ParameterPtr = GetAllParameters();
		ParameterPtr->GetName(); ParameterPtr++)  {
		int Error = ParameterPtr->CppListDec(Out,Cmd,ThisObject);
		Ok &= Error ;
	}
	return Ok;
}


int UserParameters::CppList(OutTokens& Out, CppListCmds Cmd)
{
	int Ok = 1;
	int Index = 0;
	for (OneParameter * ParameterPtr = GetAllParameters();
		ParameterPtr->GetName(); ParameterPtr++)  {
		if (!Index++) continue ; // name is output 
					 // from calling procedure
		Out.NextConcat(",");
		int Error = ParameterPtr->CppList(Out,Cmd);
		Ok &= Error ;
	}
	return Ok;
}

int OneParameter::CppList(OutTokens& Out, CppListCmds Cmd)
{
	if (IntP) return IntP->CppList(Out,Cmd);
	if (FloatP) return FloatP->CppList(Out,Cmd);
	if (StringP) return StringP->CppList(Out,Cmd) ;
	if (EntityP) return EntityP->CppList(Out,Cmd) ;
	if (ArrayP) return ArrayP->CppList(Out,Cmd) ;
	DbgError("OneParameter::CppList","NULL Parameter pointer");
	return 0;
}

int IntParam::CppList(OutTokens& Out, CppListCmds)
{
	const BufSize = 64 ;
	char Buf[BufSize] ;
	for (int i = 0 ; i < BufSize;i++) Buf[i] = '\0' ;
	ostrstream Strm(Buf,BufSize);
	Strm << CurrentValue ;
	Out.NextFillOut(Buf);
	return 1;
}


int FloatParam::CppList(OutTokens& Out, CppListCmds)
{
	// char Buf[32];
	if (CurrentValue == 0.0) Out.NextFillOut("0.0");
	else Out.NextFillOut(FullDoubleValue(CurrentValue)) ;
	return 1;
}

void StringParam::GetDefaultName(InteractiveEntity * ent)
{
	
	CurrentValue = MakeNewEntityName(ent->GetClassName(),ent->ListSize());
}

int StringParam::CppList(OutTokens& Out, CppListCmds)
{
	if (CurrentValue) Out.NextDblQuoteOut(CurrentValue);
	else Out.NextFillOut("0");
	return 1 ;
}

int EntityParam::CppList(OutTokens& Out, CppListCmds)
{
	if (!CurrentValue) Out.NextFillOut("0");
	else Out.NextFillOut(CurrentValue->GetName());
	return 1 ;
}




