/***************************************************************************
**
**    $Header:   D:/ECB2S/SRC/LOG/SPATDOC.CPP   1.2.1.4   17 Apr 1997 16:00:08   ZJRD  $
**
**    $Log:   D:/ECB2S/SRC/LOG/SPATDOC.CPP  $
** 
**    Rev 1.2.1.4   17 Apr 1997 16:00:08   ZJRD
** No change.
** 
**    Rev 1.2.1.3   16 Apr 1997 10:32:56   ZJRD
** No change.
** 
**    Rev 1.2.1.2   10 Apr 1997 15:42:28   ZJRD
** No change.
** 
**    Rev 1.2.1.1   03 Apr 1997 15:21:14   ZJRD
** No change.
** 
**    Rev 1.2.1.0   28 Mar 1997 10:25:28   ZJRD
** easy pack sld 2.09d
** 
**    Rev 1.1   19 Mar 1997 11:35:24   ZJRD
** No change.
** 
**    Rev 1.0   12 Mar 1997 14:49:56   ZJRD
** Initial revision.
** 
**    Rev 1.0.1.0   11 Nov 1996 12:59:24   ZJRD
** EasyPack/SLD Version 2.01
** 
**    Rev 1.4   09 Sep 1996 13:18:08   ZJRD
** No change.
** 
**    Rev 1.3   05 Sep 1996 11:29:38   ZJRD
** No change.
** 
**    Rev 1.2   02 Sep 1996 09:56:42   ZJRD
** No change.
** 
**    Rev 1.1   28 Aug 1996 15:52:32   ZJRD
** EasyPack/SLD Version 1.9b
** 
**    Rev 1.0   12 Aug 1996 10:56:00   ZJRD
** Initial revision.
** 
****************************************************************************/

/////////////////////////////////////////////////////////////////////////////
//
//  File name: SPATDOC.CPP
//
//  Description: The implementation file for the class: CSpaTextDoc.
//
//  Author: Chen Jun
//
//  Date: 06/19/96
//
//  Modification:
//      1. 06/19/96, Initial version of the class: CSpaTextDoc.
//
//  Copyright (C) 1996 Microtek International. All rights reserved.
//
/////////////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "resource.h"

#include "spamsg.h"
#include "spafrm.h"
#include "spaline.h"
#include "spatdoc.h"
#include "spatvw.h"

#include "symblsvr.h"


#ifdef _DEBUG
#undef THIS_FILE
static char BASED_CODE THIS_FILE[] = __FILE__;
#endif


/////////////////////////////////////////////////////////////////////////////
// Global variables.
extern CSpaCodeFrame* pSpaCodeWnd;
int SymToAddr(char* lpStr , U8* lpType , U32* lpAddr);
int GetCurrentBank(void);

/////////////////////////////////////////////////////////////////////////////
// CSpaTextDoc

IMPLEMENT_SERIAL(CSpaTextDoc, CDocument, 0)

CSpaTextDoc::CSpaTextDoc()
	: m_nMaxLine(0), m_nMaxLength(0)
{
	// Allocate space.
	m_pLineList = new CObList;
	m_pLineList->RemoveAll();
}

BOOL CSpaTextDoc::OnNewDocument()
{
	if (!CDocument::OnNewDocument())
		return FALSE;
		
	// Set title.
	CString strTitle;
	strTitle.LoadString(IDR_SPA);
	SetTitle(strTitle);

	return TRUE;
}

CSpaTextDoc::~CSpaTextDoc()
{
	// Release space.
	POSITION pos = m_pLineList->GetHeadPosition();
	while ( pos ) {
		CSpaTextLine* pObj = (CSpaTextLine*)m_pLineList->GetNext(pos);
		delete pObj;
	}
	m_pLineList->RemoveAll();
	delete m_pLineList;
}


BEGIN_MESSAGE_MAP(CSpaTextDoc, CDocument)
	//{{AFX_MSG_MAP(CSpaTextDoc)
		// NOTE - the ClassWizard will add and remove mapping macros here.
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()


/////////////////////////////////////////////////////////////////////////////
// CSpaTextDoc common routines.

CSize CSpaTextDoc::GetTotalSize(void) const
{
	// cx: max length of lines; cy: max line of the file.
	return CSize(m_nMaxLength, m_nMaxLine);
}

void CSpaTextDoc::UpdateDocument(const CString& strFile)
{
	// If the file exist.
    CFileStatus status;
	if ( !CFile::GetStatus(strFile, status) ) {
		return;
	}
	m_pLineList->RemoveAll();
	
	// Open the specific file.
	UINT nOpenFlag = CFile::modeRead | CFile::typeText;
	CStdioFile* fp = new CStdioFile(strFile, nOpenFlag);
	int nMax = 512;
	char* pszLine = new char[nMax+4];
	m_nMaxLine = 0;
	while ( fp->ReadString(pszLine, nMax) ) {
		CString strLine(_T(""));
		for ( int i(0); i < int(strlen(pszLine)); i++ ) {
			if ( pszLine[i] >= 0x20 && pszLine[i] <= 0x7F ) {
				strLine += pszLine[i];
			}
			else if ( '\t' == pszLine[i] ) {
				strLine += "    ";
			}
		}
		m_pLineList->AddTail(new CSpaTextLine(strLine, IsGrayedLine(m_nMaxLine++)));
		m_nMaxLength = max(m_nMaxLength, strLine.GetLength());
	}
	delete []pszLine;
	
	// Close the specific file.
	fp->Close();
	delete fp;
}

BOOL CSpaTextDoc::IsGrayedLine(int nLine) const
{
	// Normalize the line number.
	ASSERT(::pSpaCodeWnd);
	CComboBox* pModule = (CComboBox*)::pSpaCodeWnd->m_wndMsgBar.GetDlgItem(IDC_COMBO_SPA_MESSAGEBAR_MODULE);
	CString str, strModule, strLine;
	pModule->GetWindowText(strModule);
	strLine.Format("%d", nLine+1);
	str = '#';
	str += strModule;
	str += '#';
	str += strLine;

	// Query from symbol server.
	BYTE bType;
	DWORD dwAddr;
	if ( 0 != ::SymToAddr(str.GetBuffer(str.GetLength()), &bType, &dwAddr) ) {
		return TRUE;
	}
	
	WORD wLine;
	DWORD dwStart, dwEnd;
	int nBank = ::GetCurrentBank();
	if ( 0 != ::SrcAddr2LinenumRange(nBank, dwAddr, wLine, dwStart, dwEnd) ) {
		return TRUE;
	}
	
	// It's comment line.
	if ( nLine + 1 != int(wLine) ) {
		return TRUE;
	}

	// Compare with m_CodeData.
	ASSERT(dwStart <= dwEnd);
	for ( int i(0); i <= m_CodeData.uchNumber*2-1; i += 2 ) {
		if ( dwStart >= m_CodeData.usAddr[i] && dwStart <= m_CodeData.usAddr[i+1] ) {
			return FALSE;
		}
		if ( dwEnd >= m_CodeData.usAddr[i] && dwEnd <= m_CodeData.usAddr[i+1] ) {
			return FALSE;
		}
	}
	return TRUE;
}

void CSpaTextDoc::SetCoverageData(const COVERAGEGETINFO& CodeData)
{
	// Get from the dialog.
	memcpy(&m_CodeData, &CodeData, sizeof(COVERAGEGETINFO));
}


/////////////////////////////////////////////////////////////////////////////
// CSpaTextDoc diagnostics

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

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

/////////////////////////////////////////////////////////////////////////////
// CSpaTextDoc serialization

void CSpaTextDoc::Serialize(CArchive& ar)
{
	if (ar.IsStoring())
	{
		// TODO: add storing code here
	}
	else
	{
		// TODO: add loading code here
	}
}

/////////////////////////////////////////////////////////////////////////////
// CSpaTextDoc commands
