/*
*******************************************************************************
* Copyright (c) 1996-97 Digi International Inc., All Rights Reserved          *
*                                                                             *
* This  software  contains  proprietary  and  confidential   information   of *
* Digi International  Inc.   By  accepting  transfer  of this copy, Recipient *
* agrees to retain this software in  confidence,  to  prevent  disclosure  to *
* others,  and  to make no  use of this software other than that for which it *
* was delivered.  This is an unpublished copyright work  Digi   International *
* Inc.    Except   as   permitted   by  federal  law,  17 USC 117, copying is *
* strictly prohibited.                                                        *
*                                                                             *
* Digi  International  Inc.  CONFIDENTIAL  -   (Digi    International    Inc. *
* Confidential  when   combined   with   the   aggregated  modules  for  this *
* product) OBJECT CODE ONLY SOURCE MATERIALS                                  *
*                                                                             *
* (C) COPYRIGHT Digi International Inc. 1996-97                               *
*                                                                             *
* All Rights Reserved                                                         *
*                                                                             *
* US   Government   Users   Restricted   Rights   -   Use,   duplication   or *
* disclosure  restricted by GSA ADP Schedule Contract with Digi International *
* Inc.                                                                        *
*                                                                             *
*******************************************************************************
*/
// DiagDoc.cpp : implementation of the CDiagDoc class
//
/*
		The is the document class used by the trace capture frame window
		and a frame list frame window. Frame window refers to the Windows SDK
		definition of a frame window. Where as frame list is the array of data
		frames captured during a trace. This document is written/read from disk.
		it has only one data member that is a CTraceData dervied class. All of the
		panes attached to this document use it to gain access to the CTraceData class.
		While a trace is in progress the CTraceData class is held by the current data
		source, i.e. theApp::GetCurDataSource(). When the user views a trace or load
		a saved trace the document holds the pointer to the CTraceData class.

		this document contains handlers to save/open files, display the capture
		summary info and the filter dialog box. The CTraceData class does all the
		work.

		The document and the views attached to this document communicate with each
		other using CDocument::UpdateAllDocuments(). The hint paramater tells what
		needs to be done. Not all the panes respond to the update.
		The constants used are below:

	uavFrameListSelChange =	called when the use changes the selection in the ListView
	uavFrameListRepSelChange =	called when the user holds a key down when the ListView has focus
	uavFrameTreeSelChange =			called when the user changes selection in the TreeView
	uavByteViewSelChange =			caled when the user clicks in the ScrollView display the frame as bytes

Revision History:

   $History: DiagDoc.cpp $
 * 
 * *****************  Version 24  *****************
 * User: Mikez        Date: 7/11/97    Time: 5:01p
 * Branched in $/Components/Windows/NT/Sync/Build/Diag
 * 
 * *****************  Version 23  *****************
 * User: Rodgerb      Date: 1/27/97    Time: 1:18p
 * Updated in $/Components/Windows/NT/Sync/rev2diag
 * 1) documentation
 * 2) added some new params to Physical layer stats
*/

#include "stdafx.h"
#include "Diagnostic.h"
#include "DiagDoc.h"

#include "DataSource.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CDiagDoc

IMPLEMENT_DYNCREATE(CDiagDoc, CDocument)

BEGIN_MESSAGE_MAP(CDiagDoc, CDocument)
	//{{AFX_MSG_MAP(CDiagDoc)
	ON_COMMAND(ID_CAPTURE_SUMMARYINFO, OnCaptureSummaryinfo)
	ON_UPDATE_COMMAND_UI(ID_CAPTURE_SUMMARYINFO, OnUpdateCaptureSummaryinfo)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE, OnUpdateFileSave)
	ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_AS, OnUpdateFileSaveAs)
	ON_COMMAND(ID_TRACECAPTURE_TRACESTATISTICS, OnTracecaptureTracestatistics)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDiagDoc construction/destruction

CDiagDoc::CDiagDoc()
{
	// TODO: add one-time construction code here
	m_TraceData = NULL;
	m_Properties = NULL;
}

CDiagDoc::~CDiagDoc()
{
	if (m_Properties)
		m_Properties->DestroyWindow();
	delete m_TraceData;
}

BOOL CDiagDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;

	// TODO: add reinitialization code here
	// (SDI documents will reuse this document)
	return TRUE;
}

/////////////////////////////////////////////////////////////////////////////
// CDiagDoc serialization

void CDiagDoc::Serialize(CMyArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
		ASSERT(FALSE);
	}
	else
	{
		// TODO: add loading code here
		m_TraceData = (CTraceData *)ar.ReadObject(NULL);
	}
}

void CDiagDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
		ar.WriteObject(m_TraceData);
	}
	else
	{
		// TODO: add loading code here
		ASSERT(FALSE);
	}
}

/////////////////////////////////////////////////////////////////////////////
// CDiagDoc diagnostics

#ifdef _DEBUG
void CDiagDoc::AssertValid() const
{
	CDocument::AssertValid();
}

void CDiagDoc::Dump(CDumpContext& dc) const
{
	CDocument::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CDiagDoc commands

void CDiagDoc::OnCaptureSummaryinfo() 
{
	// TODO: Add your command handler code here
	if (GetTraceData() != NULL) {
		POSITION pos = GetFirstViewPosition();
		CView *pView = GetNextView(pos);

		if (GetTraceData()->DoCaptureSummaryDlg(pView->GetParentFrame()))
			SetModifiedFlag();
		}
}

void CDiagDoc::OnUpdateCaptureSummaryinfo(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(GetTraceData() != NULL);
}

void CDiagDoc::OnUpdateFileSave(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(m_TraceData != NULL);
}

void CDiagDoc::OnUpdateFileSaveAs(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	pCmdUI->Enable(m_TraceData != NULL);
}

// special exception handling just for MFC library implementation
#ifndef _AFX_OLD_EXCEPTIONS

#define DELETE_EXCEPTION(e) do { e->Delete(); } while (0)

#else   //!_AFX_OLD_EXCEPTIONS

// In this case, the TRY..CATCH macros provide auto-delete semantics, so
//  it is not necessary to explicitly delete exception objects at the catch site.

#define DELETE_EXCEPTION(e)

#endif  //_AFX_OLD_EXCEPTIONS

BOOL CDiagDoc::OnOpenDocument(LPCTSTR lpszPathName) 
{
	if (IsModified())
		TRACE0("Warning: OnOpenDocument replaces an unsaved document.\n");

	CFileException fe;
	CFile* pFile = GetFile(lpszPathName,
		CFile::modeRead|CFile::shareDenyWrite, &fe);
	if (pFile == NULL)
	{
		ReportSaveLoadException(lpszPathName, &fe,
			FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
		return FALSE;
	}

	DeleteContents();
	SetModifiedFlag();  // dirty during de-serialize

	CMyArchive loadArchive(pFile, CArchive::load | CArchive::bNoFlushOnDelete, 1 << 16);
	loadArchive.m_pDocument = this;
	loadArchive.m_bForceFlat = FALSE;
	TRY
	{
		CWaitCursor wait;
		if (pFile->GetLength() != 0)
			Serialize(loadArchive);     // load me
		loadArchive.Close();
		ReleaseFile(pFile, FALSE);
	}
	CATCH_ALL(e)
	{
		ReleaseFile(pFile, TRUE);
		DeleteContents();   // remove failed contents

		TRY
		{
			ReportSaveLoadException(lpszPathName, e,
				FALSE, AFX_IDP_FAILED_TO_OPEN_DOC);
		}
		END_TRY
		DELETE_EXCEPTION(e);
		return FALSE;
	}
	END_CATCH_ALL

	SetModifiedFlag(FALSE);     // start off with unmodified

#ifdef _MAC
	WIN32_FIND_DATA fileData;
	HANDLE hFind = FindFirstFile(lpszPathName, &fileData);
	ASSERT(hFind != (HANDLE)-1);
	VERIFY(FindClose(hFind));

	if ((fileData.wFinderFlags & kIsStationery) != 0)
	{
		SetModifiedFlag();
		if (m_pDocTemplate != NULL)
			m_pDocTemplate->SetDefaultTitle(this);

		// normally SetPathName would do this, but we aren't calling it
		AfxGetApp()->AddToRecentFileList(lpszPathName);
	}
#endif

	return TRUE;
}

#define wNullTag        ((WORD)0)           // special tag indicating NULL ptrs
#define wNewClassTag    ((WORD)0xFFFF)      // special tag indicating new CRuntimeClass
#define wClassTag       ((WORD)0x8000)      // 0x8000 indicates class tag (OR'd)
#define dwBigClassTag   ((DWORD)0x80000000) // 0x8000000 indicates big class tag (OR'd)
#define wBigObjectTag   ((WORD)0x7FFF)      // 0x7FFF indicates DWORD object tag
#define nMaxMapCount    ((DWORD)0x3FFFFFFE) // 0x3FFFFFFE last valid mapCount

CObject *CMyArchive::ReadObject(const CRuntimeClass* pClassRefRequested)
{
	ASSERT(pClassRefRequested == NULL ||
		AfxIsValidAddress(pClassRefRequested, sizeof(CRuntimeClass), FALSE));
	ASSERT(IsLoading());    // proper direction
	ASSERT(wNullTag == 0);
	ASSERT((wClassTag << 16) == dwBigClassTag);
	ASSERT((wNewClassTag & wClassTag) == wClassTag);

	// attempt to load next stream as CRuntimeClass
	UINT nSchema;
	DWORD obTag;
	CRuntimeClass* pClassRef = ReadClass(pClassRefRequested, &nSchema, &obTag);

	// check to see if tag to already loaded object
	CObject* pOb;
	if (pClassRef == NULL)
	{
		if (obTag > (DWORD)m_pLoadArray->GetUpperBound())
		{
			// tag is too large for the number of objects read so far
			AfxThrowArchiveException(CArchiveException::badIndex,
				m_strFileName);
		}

		pOb = (CObject*)m_pLoadArray->GetAt(obTag);
		if (pOb != NULL && pClassRefRequested != NULL &&
			 !pOb->IsKindOf(pClassRefRequested))
		{
			// loaded an object but of the wrong class
			AfxThrowArchiveException(CArchiveException::badClass,
				m_strFileName);
		}
	}
	else
	{
		// allocate a new object based on the class just acquired
		pOb = pClassRef->CreateObject();
		if (pOb == NULL)
			AfxThrowMemoryException();

		// Add to mapping array BEFORE de-serializing
		CheckCount();
		m_pLoadArray->InsertAt(m_nMapCount++, pOb);

		// Serialize the object with the schema number set in the archive
		UINT nSchemaSave = m_nObjectSchema;
		m_nObjectSchema = nSchema;

		TRY 
		{
			pOb->Serialize(*this);
			m_nObjectSchema = nSchemaSave;
			ASSERT_VALID(pOb);
		}
		CATCH_ALL(e)
		{
			delete pOb;
			THROW_LAST();
		}
		END_CATCH_ALL
	}

	return pOb;
}

void CDiagDoc::SetTitle(LPCTSTR lpszTitle) 
{
	// TODO: Add your specialized code here and/or call the base class
	if (m_Properties != NULL) {
		CString title = "Trace statisics from - ";
		
		title += m_TraceData->GetDataSourceName() + " - (" + lpszTitle + ')'; 
		m_Properties->SetWindowText(title);
		}
	
	CDocument::SetTitle(lpszTitle);
}

void CDiagDoc::OnTracecaptureTracestatistics() 
{
	// TODO: Add your command handler code here
	if (m_Properties)
		m_Properties->ShowWindow(SW_SHOW);
	else {
		m_Properties = new CTraceMiniFrame(m_TraceData->CreateTraceSheet());

		if (!m_Properties->Create(NULL,
															_T(""),
															MFS_MOVEFRAME | MFS_4THICKFRAME | MFS_SYNCACTIVE | MFS_THICKFRAME |
															WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU,
															CRect(20, 20, 20, 20),
															AfxGetMainWnd()->GetWindow(GW_CHILD)))
			m_Properties = NULL;

		SetTitle(GetTitle());
		}	
}