#include <complex.h>
#include <stream.h>
#include "ObjProArith/hrdarth.h"
#include "ObjProComGui/cgidbg.h"
#include "ObjProGui/dyntextd.h"
#include "ObjProNet/dfnode.h"

#include "ObjProUsr/hexlist.h"
#include "ObjProGen/outtok.h"
#include "ObjProGui/intfc.h"
#include "ObjProGui/remmen.h"
#include "ObjProGui/user.h"
#include "ObjProGui/dynmnu.h"
#include "ObjProArith/typout.h"
#include "ObjProGui/array.h"
#include "ObjProGui/interinit.h"
#include "ObjProGen/stattyp.h"
#include "ObjProDSPcom/disphnd.h"
static EntityList * HexListNodeList = 0 ;
static InteractiveEntity * IntEntHexList ;
void HexListNodesInit();
HexList::HexList (const char * Name, int16 Channels, const char * Caption):
	DisplayNodeStr(Name, Channels, 1, 
	 new StreamStr(SizeVariable , SizeVariable , (ArithType::ArithCapabilities)(ArithType::ArithCapabilityAnyInt)), TimingTypeLinear)
,
	Channels_1(Channels),
	Caption_2(Caption)
{
	if (!HexListNodeList) HexListNodesInit() ;
	HexListNodeList->Append(MakeDeclaredEntity(this, IntEntHexList)) ;
	InitArithType(TheArithType);
	NewMenuItem("HexList",GetName());
#line 89 "../hexlist.usr"
 
#ifdef INTERACTIVE
	GetWindowHandle(DisplayHandle,GetName(),GetCaption());
#endif
	Modulus = 0 ;
	Multi = 0 ;
	FirstTime = 1 ;
	MultiChan = GetChannels() > 1;
	SavedBinaryWords = 0 ;
	NextBitToSet = 0 ;
	IndexOut = 1 ;
	Index = 0;
	DisplayHandle = 0 ;
	WindowId = 0 ;
	Mask = 0 ;
	NumberBits = 8 * sizeof(MachWord) ;
	for (int i = 0 ; i < NumberBits ;i++) Mask = (Mask << 1) | 1 ;
#line 52 "../hexlist.cxx"
} // end constructor

HexList::~HexList()
{
	TheMenuServer->DeleteMenuItem("HexList",GetName());
	HexListNodeList->Delete(GetName()) ;
#line 109 "../hexlist.usr"
 
	delete SavedBinaryWords ;
	delete NextBitToSet ;
#line 63 "../hexlist.cxx"
} // end destructor

int HexList::CheckSafeDelete()
{
	int Safe_Check_Return = DfNode::CheckSafeDelete();
	if (!Safe_Check_Return) return 0;
	return 1;
} // end check safe delete

double HexList::TimeFirst( DfNodeInLink * , DfNodeOutLink * )
{
#line 131 "../hexlist.usr"
	return 0.0;
	// timing is irrelevant for a node with no output channels
#line 78 "../hexlist.cxx"
} // end timing code

HexList * HexListDef;

ErrCode HexList::DoNode(int32 k)
{
#line 135 "../hexlist.usr"
 
	if (FirstTime) {
#ifdef INTERACTIVE
		while (!DisplayHandle)
			TheDynamicTextController->CheckForPacket();
		TheDynamicTextController->OpenWindowAndWait(DisplayHandle,
			&WindowId);
#endif
		FirstTime = 0;
		Modulus = 6 / (GetInEltSize() * GetChannels());
		if (!Modulus) Modulus = 1;
		Multi = GetInEltSize() > 1;
	}
	for (int32 i = 0 ; i < k ; i++,Index++ ) 
	  for (int ii = 0; ii < GetChannels(); ii++) {
		if (IndexOut) {
#ifdef __NT_VC__
			char buf[32] ;
			sprintf(buf,"%0x4",Index);
			DISPLAY_OUT << "[ 0x" << buf ;
#else
			DISPLAY_OUT << "[ 0x" << hex(Index,4) ;
#endif
			if (MultiChan) *Output << ", " << ii ;
			*Output << "] =" ;
		}
		IndexOut = 0;
		if (Multi) DISPLAY_OUT << " (" ;
		for (int16 j = 0 ; j < GetInEltSize(); j++) {
			if (j)  {
				*Output << "," ;
				if (((j-1) %4)==3) *Output << "\n\t" ;
			}
			uint32 Value ;
			uint8 * val8;
			uint16 * val16;
			uint32 * val32 ;
			MachWord In = ReadWord(ii) ;
			switch (NumberBits) {
case 8:
				val8 = (uint8 *) &In ;
				Value = (uint32) * val8 ;
				break ;
case 16:
				val16 = (uint16 *) &In ;
				Value = (uint32) * val16 ;
				break ;
case 32:
				val32 = (uint32 *) &In ;
				Value = (uint32) * val32 ;
				break ;
default:		
				DbgError("HexList.usr","bad word size");
			}
#ifdef __NT_VC__
			char buf[32] ;
			sprintf(buf,"%0x4",Value & Mask );
			DISPLAY_OUT << " 0x" << buf ;
#else
			DISPLAY_OUT << " 0x" << hex(Value & Mask) ;
#endif
		}
		if (Multi) *Output << ")" ;
		if ((Index % Modulus) == (Modulus -1)) {
			*Output << "\n" ;
			IndexOut =1 ;
		}
	}
	return OK ;
#line 155 "../hexlist.cxx"
} // end kernel code

static UserEntity * MakeHexList(OutTokens& Out, EntityReq Request,
	InteractiveEntity& IntNode,
	ArithType::ArithCapabilities arith = (ArithType::ArithCapabilities) TheArithType) ;
int HexList::CppList(OutTokens& Out, CppListCmds Cmd)
{
	return IntEntHexList->CppList(Out,Cmd,this);
}

void HexList::Describe(OutTokens& Out, ListEntity Option)
{
	switch(Option) {
case ListSingleEntity:
		Out.NewLine();
		MakeHexList(Out,EntityReqDescribeFull,*IntEntHexList, (ArithType::ArithCapabilities) TheArithType);
		Out.NewLine();
		Out.NextQuoteOut("HexList");
		Out.NextFillOut("lists");
		Out.NextQuoteOut("Channels");
		Out.NextFillOut("(");
		Out.NextFillOut(TypeToString(GetChannels()));
		Out.NextFillOut(")");
		Out.NextFillOut("signals of integer data in  a");
		Out.NextFillOut("hexadecimal format.");
		Out.NextQuoteOut("Caption");
		Out.NextQuoteOut(GetCaption());
		Out.NextFillOut("specifies a caption that will appear at the");
		Out.NextFillOut("head of the listing. If no caption is specified");
		Out.NextFillOut("(default 0) then the node name will be used.");
		Out.NextFillOut("The caption cannot contain blanks. Use underscore instead.");
		Out.NewLine();
		break;
case ListEntityMembers:
		Out.NextOut(GetName());
		break;
case ListGlobalClasses:
case ListEntityClasses:
		break ;
case ListSetParameterValues:
		IntEntHexList->GetOneParameter("Channels")->
			IntP->CurrentValue = Channels_1;
		IntEntHexList->GetOneParameter("Caption")->
			StringP->CurrentValue = Caption_2;
		break;
	}
} // end  list entity switch

void HexListNodesInit()
{
	if (HexListNodeList)  return ;

	static StringParam HexListNameParam =
		{"HexList", MakeNewEntityName, 0, LegalEntityName};
	static IntParam HexListChannelsParam = {
		 1, 0,  0,  1,  0,  32};
	static StringParam HexListCaptionParam = {
		 0, 0, 0};

	static OneParameter HexListParArray[] = {
		{"Name", 0, "node name", 0, 0, &HexListNameParam},
		{"Channels", 0, 
			"number of input channels",
			&HexListChannelsParam},
		{"Caption", 0, 
			"list caption",
			0, 0, &HexListCaptionParam},
		{0}
	};

	HexListNodeList = new EntityList;
	IntEntHexList = new InteractiveEntity("HexList", HexListNodeList,
		MakeHexList, InteractiveDisplay, "hexlist.h",
		0, "DisplayNodeStr");
	IntEntHexList->SetParameters(new UserParameters(HexListParArray));
	TheNodes->Append(IntEntHexList);
} // end initalization

static UserEntity * MakeHexList(OutTokens& Out, EntityReq Request,
	InteractiveEntity& IntNode,
	ArithType::ArithCapabilities arith)
{
	switch(Request) {
case EntityReqDescribe:

case EntityReqDescribeFull:
		Out.NextQuoteOut("HexList");
		Out.NextFillOut("displays");
		Out.NextQuoteOut("Channels");
		Out.NextFillOut("signals on a single list.");
		Out.NextFillOut("If you only want to display a single channel the `HexList'");
		Out.NextFillOut("option in `Listing' may be more convenient.");
		Out.NextFillOut("In a floating point simulator the input to");
		Out.NextQuoteOut("HexList");
		Out.NextFillOut("must");
		Out.NextFillOut("be an integer format. You can use `ToInteger' to do the conversion.");
		Out.NextFillOut("`BlockSize' and `ElementSize' are set when the first input");
		Out.NextFillOut("channel is linked. All subsequent input channels must have the same values.");
		Out.NewLine();
		break;

case EntityReqCreate:
	{
		const char * Name = IntNode.GetStringParameterValue("Name");
		int16 Channels =
			IntNode.GetIntParameterValue("Channels");
		const char * Caption =
			IntNode.GetStringParameterValue("Caption");
		return new HexList(Name, Channels, Caption);

	}
	}
	return 0;
}

static InitObj LocalInit(HexListNodesInit, "HexList", "DisplayNodeStr");

