/************************************************************************
*
* Resource ID Organiser Core Library
*
* (c) Copyright 2000-2005 by Riverblade Limited (UK). All rights reserved.
*
************************************************************************
*
* Description : CResOrgSymbolsDoc - document class for a resource
* symbol file
*
* Compiler : Microsoft Visual C++ 6.0, Service Pack 3 or later
* Microsoft Visual C++ .NET 2003
*
* Target
* Environment : Windows 98/NT/2000/XP
*
* NOTE:
*
* This software is provided "as is". All title and copyrights in and
* to the software, including but not limited to any images, text etc.
* etc. incorporated into it, are the property of Anna-Jayne Metcalfe
* and Riverblade Limited, except where acknowledged otherwise.
*
* Your may freely use this code in your own products, PROVIDED
* this notice is not removed or modified.
*
* Please visit http://www.riverblade.co.uk/products/resorg
* or email support@riverblade.co.uk for latest updates and product support
*
************************************************************************
*
* MODIFICATION HISTORY:
*
* This is a controlled document. See project configuration
* control tool for latest version and full version history.
*
* $Archive: /Projects/AddIns/ResOrg/ResOrgCore/ResOrgSymbolsDoc.cpp $
* $Revision: 34 $
* $Date: 31/12/04 16:26 $
* $Author: Anna $
*
* $History: ResOrgSymbolsDoc.cpp $
*
* ***************** Version 34 *****************
* User: Anna Date: 31/12/04 Time: 16:26
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* 1. Added IDP_WARN_CONFIG_LOAD_FAILED and IDP_WARN_CONFIG_SAVE_FAILED
* string table prompts for use when loading/saving config files (debug
* builds only)
* 2. Updated file banners
*
* ***************** Version 33 *****************
* User: Anna Date: 28/12/04 Time: 9:30
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* CResOrgSymbolsDoc::Serialize() now only displays XML load/save failure
* message boxes in debug builds
*
* ***************** Version 32 *****************
* User: Anna Date: 29/08/04 Time: 22:00
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* CResOrgSymbolsDoc::Serialize() now checks if the filebeing saved
* exists before assuming it is read only
*
* ***************** Version 31 *****************
* User: Anna Date: 29/08/04 Time: 21:22
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* 1. CResOrgSymbolsDoc::OnCmdFileProperties() now handles the
* ID_SYM_PROPERTIES command in case CResOrgSymbolsListView didn't. This
* allows the properties of the associated file to be displayed if a
* single symbol isn't selected.
* 2. CResOrgSymbolsDoc::Serialize() now checks whether symbol config
* files exist (load) and are writeable (save) before proceeding.
*
* ***************** Version 30 *****************
* User: Anna Date: 24/08/04 Time: 0:14
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Fixed a compiler warning
*
* ***************** Version 29 *****************
* User: Anna Date: 23/08/04 Time: 21:40
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Added support for out of range symbols
*
* ***************** Version 28 *****************
* User: Anna Date: 11/07/04 Time: 16:21
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Added support for detection of out of range symbols
*
* ***************** Version 27 *****************
* User: Anna Date: 7/03/03 Time: 11:45
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Changed CException to CUserException so it will compile under VS.NET
* again...
*
* ***************** Version 26 *****************
* User: Anna Date: 4/03/03 Time: 20:51
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Added more information to the XML export file
*
* ***************** Version 25 *****************
* User: Anna Date: 3/03/03 Time: 23:31
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* CResOrgSymbolsDoc::OnCmdFileExport() now uses BXFileDialog if it can
*
* ***************** Version 24 *****************
* User: Anna Date: 3/03/03 Time: 20:10
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Moved XML code to its own class (CResOrgXmlWriter)
*
* ***************** Version 23 *****************
* User: Anna Date: 1/03/03 Time: 18:10
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* The user can now provide their own XSL stylesheet to generate an HTML
* report
*
* ***************** Version 22 *****************
* User: Anna Date: 25/02/03 Time: 21:24
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Minor correction in CResOrgSymbolsDoc::SaveXml()
*
* ***************** Version 21 *****************
* User: Anna Date: 19/02/03 Time: 19:20
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Started adding XML export and HTML reports
*
* ***************** Version 20 *****************
* User: Anna Date: 15/02/03 Time: 20:48
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Changed big BOOLs into little bools
*
* ***************** Version 19 *****************
* User: Anna Date: 28/01/03 Time: 21:19
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Improved multi-file support by allowing files to be Added/Removed from
* a multi-file display via the File Properties Dialog
*
* ***************** Version 18 *****************
* User: Anna Date: 19/01/03 Time: 17:17
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Made CResOrgSymbolsDoc::Add(), Set(), Remove() and
* CheckNextSymbolValues() virtual
*
* ***************** Version 17 *****************
* User: Anna Date: 2/01/03 Time: 0:05
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* The CResourceSymbolManager object used by the document is now held by
* pointer, to allow it's type to be customised in derived classes
*
* ***************** Version 16 *****************
* User: Anna Date: 25/11/02 Time: 15:14
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Changed website address in banner
*
* ***************** Version 15 *****************
* User: Anna Date: 22/10/02 Time: 13:24
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Changed name/mail address (at last!)
*
* ***************** Version 14 *****************
* User: Andy Date: 1/08/02 Time: 16:26
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Knock on changes from CResourceSymbolManager
*
* ***************** Version 13 *****************
* User: Andy Date: 7/06/02 Time: 17:04
* Updated in $/Projects/AddIns/ResOrg/ResOrgCore
* Renamed the ResOrgUtils module to ResOrgCore. Updated file banners
* accordingly
*
* ***************** Version 12 *****************
* User: Andy Date: 27/05/02 Time: 16:39
* Updated in $/Projects/AddIns/ResOrg/ResOrgUtils
* Knock on changes from CResourceSymbolBuffer (now
* CResourceSymbolManager)
*
* ***************** Version 11 *****************
* User: Andy Date: 12/28/01 Time: 12:53a
* Updated in $/Projects/AddIns/ResOrg/ResOrgUtils
* Added some new options
*
* ***************** Version 10 *****************
* User: Andy Date: 10/21/01 Time: 11:03p
* Updated in $/Projects/AddIns/ResOrg/ResOrgUtils
* 1. CResOrgSymbolsDoc::Serialize() no longer calls
* CResOrgSymbolsDoc::CheckNextSymbolValues() - the prompt is now done
* elseware
* 2. CResOrgSymbolsDoc::CheckNextSymbolValues() now takes a parameter to
* determine whether a prompt dialog should be shown
*
* ***************** Version 9 *****************
* User: Andy Date: 10/03/01 Time: 12:26p
* Updated in $/Projects/AddIns/ResOrg/ResOrgUtils
* 1. Added CResOrgSymbolsDoc::CheckNextSymbolValues() to prompt if the
* "Next Symbol" values are in use
* 2. CResOrgSymbolsDoc::Serialize() now calls CheckNextSymbolValues()
* after loading to ensure that the "Next Symbol" values are OK.
*
* ***************** Version 8 *****************
* User: Andy Date: 15/08/01 Time: 13:38
* Updated in $/Projects/AddIns/ResOrg/ResOrgUtils
* Replaced CReservedSymbolsDlg with CResourceSymbolFilePropertySheet
*
* ***************** Version 7 *****************
* User: Andy Date: 22/06/01 Time: 9:51
* Updated in $/Projects/AddIns/ResOrg/ResOrgUtils
* CResOrgSymbolsDoc::OnCmdRenumberSymbol() no longer marks the document
* as changed if the wizard is cancelled without changing anything
*
* ***************** Version 6 *****************
* User: Andy Date: 2/03/01 Time: 17:06
* Updated in $/Projects/AddIns/ResOrg/ResOrgUtils
* 1. Made view hints more specific to remove the need to rebuild the
* displays completely
* 2. CResOrgSymbolsDoc::OnCmdFileProperties() now handles the details of
* displaying the File Properties Dialog, rather than asking
* CResourceSymbolBuffer to do it
*
* ***************** Version 5 *****************
* User: Andy Date: 19/02/01 Time: 8:30
* Updated in $/Projects/AddIns/ResOrg/ResOrgUtils
* Better view hints
*
* ***************** Version 4 *****************
* User: Andy Date: 17/02/01 Time: 6:57
* Updated in $/Projects/AddIns/ResOrg/ResOrgUtils
* 1. Knock-on changes from renaming of CResOrgSymbolsView to
* CResOrgSymbolsListView
* 2. Added wrappers around commonly used CResourceSymbolBuffer methods
* [e.g. Set()] to remove the need for views to raise view hints
*
* ***************** Version 3 *****************
* User: Andy Date: 29/11/00 Time: 18:38
* Updated in $/Projects/AddIns/ResOrg/ResOrgUtils
* Added file banners
*
* $Nokeywords: $
*
************************************************************************/
#include "StdAfx.h"
#include "ResOrgCore_Priv.h"
#include "ResOrgCore_Globals.h"
#include "ResourceSymbol.h"
#include "RenumWizard.h"
#include "ResourceSymbolFilePropertySheet.h"
#include "ResOrgOptions.h"
#include "ResOrgCoreApp.h"
#include "ResOrgXmlWriter.h"
#include "ResOrgReportStyleSheetDlg.h"
#include "ResOrgSymbolsDoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
/////////////////////////////////////////////////////////////////////////////
// CResOrgSymbolsDoc
IMPLEMENT_DYNCREATE(CResOrgSymbolsDoc, CResOrgSymbolsDoc_BASE)
BEGIN_MESSAGE_MAP(CResOrgSymbolsDoc, CResOrgSymbolsDoc_BASE)
ON_COMMAND( ID_FILE_CLOSE, OnFileClose)
ON_COMMAND( ID_FILE_SAVE, OnFileSave)
ON_COMMAND( ID_FILE_SAVE_AS, OnFileSaveAs)
ON_COMMAND( ID_FILE_EXPORT, OnCmdFileExport)
ON_COMMAND( ID_FILE_PROPERTIES, OnCmdFileProperties)
ON_COMMAND( ID_SYM_PROPERTIES, OnCmdFileProperties)
ON_COMMAND( ID_FILE_PROPERTIES_STATISTICS, OnCmdFilePropertiesStatistics)
ON_COMMAND( ID_FILE_PROPERTIES_NEXT_SYMBOLS, OnCmdFilePropertiesNextSymbolValues)
ON_COMMAND( ID_FILE_CHANGED, OnCmdFileChanged)
ON_COMMAND( ID_TOOLS_RENUMBER, OnCmdRenumberSymbols)
ON_UPDATE_COMMAND_UI( ID_TOOLS_RENUMBER, OnUpdateRenumberSymbols)
ON_COMMAND( ID_TOOLS_REPORT, OnCmdReport)
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CResOrgSymbolsDoc construction/destruction
CResOrgSymbolsDoc::CResOrgSymbolsDoc(void)
{
m_pSymbolManager = NULL;
}
CResOrgSymbolsDoc::~CResOrgSymbolsDoc(void)
{
if (NULL != m_pSymbolManager)
{
delete m_pSymbolManager;
m_pSymbolManager = NULL;
}
}
/////////////////////////////////////////////////////////////////////////////
// CResOrgSymbolsDoc overrides
BOOL CResOrgSymbolsDoc::OnNewDocument(void)
{
BOOL bResult = CResOrgSymbolsDoc_BASE::OnNewDocument();
return bResult;
}
BOOL CResOrgSymbolsDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
BOOL bResult = CResOrgSymbolsDoc_BASE::OnOpenDocument(lpszPathName);
if (bResult)
{
StartFileChangeMonitor(lpszPathName);
}
return bResult;
}
BOOL CResOrgSymbolsDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
BOOL bResult = CResOrgSymbolsDoc_BASE::OnSaveDocument(lpszPathName);
if (bResult)
{
m_pSymbolManager->SetModifiedFlag(false);
StartFileChangeMonitor(lpszPathName);
UpdateAllViews(NULL, SYM_REFRESH);
}
return bResult;
}
void CResOrgSymbolsDoc::OnCloseDocument(void)
{
StopFileChangeMonitor();
CResOrgSymbolsDoc_BASE::OnCloseDocument();
}
void CResOrgSymbolsDoc::DeleteContents(void)
{
if (NULL != m_pSymbolManager)
{
m_pSymbolManager->RemoveAll();
}
else
{
VERIFY( CreateSymbolManager() );
}
UpdateAllViews(NULL, SYM_REFRESH);
CResOrgSymbolsDoc_BASE::DeleteContents();
}
/////////////////////////////////////////////////////////////////////////////
// CResOrgSymbolsDoc serialization
void CResOrgSymbolsDoc::Serialize(CArchive& ar)
{
if (NULL != m_pSymbolManager)
{
m_pSymbolManager->Serialize(ar);
if (Options.AutoSaveSymbolFileConfig() )
{
CString sConfigFilePathName = CResOrgXmlWriter::GetConfigFilePathName( m_pSymbolManager->GetPathName() );
CString sErrorMsg;
if (ar.IsLoading() )
{
if (::FileExists(sConfigFilePathName) )
{
if (!CResOrgXmlWriter::LoadSymbolFileConfig(m_pSymbolManager,
sConfigFilePathName,
&sErrorMsg) )
{
#ifdef _DEBUG
CNGSplitPath split(sConfigFilePathName);
CString sMsg;
sMsg.Format(IDP_WARN_CONFIG_LOAD_FAILED,
split.GetFileName() + split.GetExtension(),
sErrorMsg);
::AfxMessageBox( sMsg, MB_OK | MB_ICONEXCLAMATION);
#endif
}
}
}
else
{
// Determine whether the file exists and is read-only.
// If so, ask if the read only file should be overwritten.
DWORD dwAttrib = ::GetFileAttributes(sConfigFilePathName);
if (::FileExists(sConfigFilePathName) && (dwAttrib & FILE_ATTRIBUTE_READONLY) )
{
switch ( ::DoOverwritePrompt(sConfigFilePathName, false) )
{
case IDYES:
if (!::SetFileAttributes(sConfigFilePathName, dwAttrib & ~FILE_ATTRIBUTE_READONLY) )
{
::AfxMessageBox(IDP_SYM_FILE_ERR_FILE_ATTRIBUTES, MB_OK | MB_ICONSTOP);
return;
}
break;
case IDNO:
case IDCANCEL:
return;
default:
ASSERT(false);
break;
}
}
if (!CResOrgXmlWriter::SaveSymbolFileConfig(m_pSymbolManager,
sConfigFilePathName,
&sErrorMsg) )
{
#ifdef _DEBUG
CNGSplitPath split(sConfigFilePathName);
CString sMsg;
sMsg.Format(IDP_WARN_CONFIG_SAVE_FAILED,
split.GetFileName() + split.GetExtension(),
sErrorMsg);
::AfxMessageBox( sMsg, MB_OK | MB_ICONEXCLAMATION);
#endif
}
}
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CResOrgSymbolsDoc diagnostics
#ifdef _DEBUG
void CResOrgSymbolsDoc::AssertValid(void) const
{
CResOrgSymbolsDoc_BASE::AssertValid();
}
void CResOrgSymbolsDoc::Dump(CDumpContext& dc) const
{
CResOrgSymbolsDoc_BASE::Dump(dc);
}
#endif //_DEBUG
/////////////////////////////////////////////////////////////////////////////
// CResOrgSymbolsDoc operations
CResourceSymbol* CResOrgSymbolsDoc::Add(const CString& sSymbolName,
UINT uSymbolValue,
int nLineNo)
{
CResourceSymbol* pSymbol = m_pSymbolManager->Add( sSymbolName,
uSymbolValue,
nLineNo);
if (NULL != pSymbol)
{
if (Options.AutoFixNextSymbolValues() )
{
m_pSymbolManager->FixNextSymbolValues();
}
if (m_pSymbolManager->IsModified())
{
SetModifiedFlag(true);
}
UpdateAllViews(NULL, SYM_ADDED, (CObject*)pSymbol);
// Work out which symbols are affected so we can issue the right view hints
CResourceSymbolList listSymbols;
m_pSymbolManager->GetSymbols( uSymbolValue,
listSymbols);
POSITION pos = listSymbols.GetHeadPosition();
while (NULL != pos)
{
CResourceSymbol* pSymbol = listSymbols.GetNext(pos);
if (NULL != pSymbol)
{
UpdateAllViews(NULL, SYM_CHANGED, (CObject*)pSymbol);
}
}
}
return pSymbol;
}
bool CResOrgSymbolsDoc::Set(CResourceSymbol* pSymbol,
const CString& sName,
UINT uValue,
bool bReadOnly /*= false*/)
{
CResourceSymbolList listSymbols;
m_pSymbolManager->GetSymbols( pSymbol->GetValue(),
listSymbols);
// Work out which symbols are affected so we can issue the right view hints
CResourceSymbolList listSymbolsWithNewValue;
m_pSymbolManager->GetSymbols( uValue,
listSymbolsWithNewValue);
listSymbols.AddTail(&listSymbolsWithNewValue);
bool bResult = m_pSymbolManager->Set( pSymbol,
sName,
uValue,
bReadOnly);
if (bResult)
{
if (Options.AutoFixNextSymbolValues() )
{
m_pSymbolManager->FixNextSymbolValues();
}
if (m_pSymbolManager->IsModified())
{
SetModifiedFlag(true);
}
POSITION pos = listSymbols.GetHeadPosition();
while (NULL != pos)
{
CResourceSymbol* pSymbol = listSymbols.GetNext(pos);
if (NULL != pSymbol)
{
UpdateAllViews(NULL, SYM_CHANGED, (CObject*)pSymbol);
}
}
}
return bResult;
}
bool CResOrgSymbolsDoc::Remove(CResourceSymbol* pSymbol)
{
if (NULL != pSymbol)
{
UpdateAllViews(NULL, SYM_DELETED, (CObject*)pSymbol);
m_pSymbolManager->Remove(pSymbol);
// Work out which symbols are affected so we can issue the right view hints
CResourceSymbolList listSymbols;
m_pSymbolManager->GetSymbols( pSymbol->GetValue(),
listSymbols);
POSITION pos = listSymbols.GetHeadPosition();
while (NULL != pos)
{
CResourceSymbol* pSymbol = listSymbols.GetNext(pos);
if (NULL != pSymbol)
{
UpdateAllViews(NULL, SYM_CHANGED, (CObject*)pSymbol);
}
}
delete pSymbol;
SetModifiedFlag();
return true;
}
return false;
}
bool CResOrgSymbolsDoc::CheckNextSymbolValues(bool bPrompt /*= true*/)
{
if (m_pSymbolManager->AreNextSymbolValuesInUse() )
{
if (bPrompt && DoNextSymbolValuesInUsePrompt())
{
OnCmdFileProperties();
}
return true;
}
return false;
}
void CResOrgSymbolsDoc::ShowSymbolFileProperties(CRuntimeClass* pActivePageClass /*= NULL*/)
{
CResourceSymbolFilePropertySheet dlg(IDP_SYM_FILE_PROPERTIES_CAPTION, ::AfxGetMainWnd() );
dlg.Initialise(m_pSymbolManager, this);
if (NULL != pActivePageClass)
{
for (int nPage = 0; nPage < dlg.GetPageCount(); nPage++)
{
CPropertyPage* pPage = dlg.GetPage(nPage);
ASSERT(NULL != pPage);
if ( (NULL != pPage) && pPage->IsKindOf(pActivePageClass) )
{
dlg.SetActivePage(pPage);
break;
}
}
}
bool bCheckForOutOfRangeSymbols = m_pSymbolManager->CheckForOutOfRangeSymbols();
if (IDOK == dlg.DoModal())
{
SetModifiedFlag( m_pSymbolManager->IsModified() );
if (bCheckForOutOfRangeSymbols != m_pSymbolManager->CheckForOutOfRangeSymbols() )
{
UpdateAllViews(NULL, SYM_REFRESH);
}
}
}
/////////////////////////////////////////////////////////////////////////////
// CResOrgSymbolsDoc implementation
bool CResOrgSymbolsDoc::CreateSymbolManager(void)
{
if (NULL == m_pSymbolManager)
{
m_pSymbolManager = new CResourceSymbolManager;
return (NULL != m_pSymbolManager);
}
return false;
}
bool CResOrgSymbolsDoc::StartFileChangeMonitor(const CString& sPathName)
{
if (!m_FileChangeMonitor.IsMonitoring())
{
POSITION pos = GetFirstViewPosition();
if (pos != NULL)
{
CView* pView = GetNextView(pos);
return m_FileChangeMonitor.Start( sPathName,
pView,
WM_COMMAND,
ID_FILE_CHANGED,
THREAD_PRIORITY_LOWEST);
}
}
return false;
}
bool CResOrgSymbolsDoc::StopFileChangeMonitor(void)
{
if (m_FileChangeMonitor.IsMonitoring())
{
return m_FileChangeMonitor.Stop();
}
return false;
}
bool CResOrgSymbolsDoc::DoNextSymbolValuesInUsePrompt(void)
{
CNGSplitPath split(m_pSymbolManager->GetPathName() );
CString sFileName = split.GetFileName() + split.GetExtension();
CNGMessageBox dlg;
dlg.FormatMsgEx(MAKEINTRESOURCE(IDP_SYM_NEXT_VALUES_IN_USE),
_T("RTF"),
sFileName);
dlg.SetRtf();
//dlg.SetTitle();
dlg.SetStandardIcon(IDI_WARNING);
dlg.AddButton(IDYES, true, true, _T("&Yes") );
dlg.AddButton(IDNO, false, false, _T("&No") );
return (IDYES == dlg.DoModal() );
}
/////////////////////////////////////////////////////////////////////////////
// CResOrgSymbolsDoc message handlers
void CResOrgSymbolsDoc::OnCmdFileChanged(void)
{
CString sPathName = GetPathName();
CNGSplitPath split(sPathName);
CString sFileName = split.GetFileName() + split.GetExtension();
BOOL bModified = IsModified();
BOOL bPrompt = bModified || !Options.AutoReloadFiles();
BOOL bReload = !bModified && Options.AutoReloadFiles();
if (bPrompt)
{
CNGMessageBox dlg;
dlg.FormatMsgEx(MAKEINTRESOURCE( bModified ? IDP_SYM_FILE_CHANGED_EX : IDP_SYM_FILE_CHANGED),
_T("RTF"),
sFileName);
dlg.SetRtf();
dlg.SetStandardIcon(IDI_WARNING);
dlg.AddButton(IDYES, false, false, _T("&Yes") );
dlg.AddButton(IDNO, true, true, _T("&No") );
bReload = (IDYES == dlg.DoModal() );
}
if (bReload)
{
OnOpenDocument(sPathName);
UpdateAllViews(NULL, SYM_REFRESH);
}
else
{
StartFileChangeMonitor(sPathName);
}
}
void CResOrgSymbolsDoc::OnFileSave(void)
{
StopFileChangeMonitor();
CResOrgSymbolsDoc_BASE::OnFileSave();
}
void CResOrgSymbolsDoc::OnFileSaveAs(void)
{
StopFileChangeMonitor();
CResOrgSymbolsDoc_BASE::OnFileSaveAs();
}
/// Handler for ID_SYM_EXPORT command
void CResOrgSymbolsDoc::OnCmdFileExport(void)
{
CNGSplitPath split( m_pSymbolManager->GetPathName() );
CString sInitialFileName = split.GetFileName();
#if _MSC_VER < 1300 // BXFileDialog doesn't work with VC7 yet
BXFileDialog dlg( false, // Open
false, // No preview
true, // Resizeable
CString( (LPCTSTR)IDS_FILE_FILTER_EXPORT_FILES_EXT),// Default extension
sInitialFileName, // Default filename
OFN_PATHMUSTEXIST | OFN_ENABLESIZING, // Flags
CString( (LPCTSTR)IDS_FILE_FILTER_EXPORT_FILES), // File filter
::AfxGetMainWnd() ); // Parent window
DWORD dwVersion = LOWORD(::GetVersion() );
DWORD dwMajor = LOBYTE(dwVersion);
DWORD dwMinor = HIBYTE(dwVersion);
DWORD dwUseableVer = (dwMajor << 8) + dwMinor;
if (dwUseableVer >= 0x501)
{
// Use the VS.NET visual style on WinXP and later
dlg.SetAppearance(BXFileDialog::APPEARANCE_VSDOTNET);
}
#else
CFileDialog dlg(false, // Save As
CString( (LPCTSTR)IDS_FILE_FILTER_EXPORT_FILES_EXT),
// Default extension
sInitialFileName, // Default filename
OFN_PATHMUSTEXIST | OFN_ENABLESIZING, // Flags
CString( (LPCTSTR)IDS_FILE_FILTER_EXPORT_FILES),
// File filter
::AfxGetMainWnd() ); // Parent window
#endif
if (IDOK == dlg.DoModal())
{
CString sPathName = dlg.GetPathName();
ASSERT(!sPathName.IsEmpty() );
WriteXml(sPathName, NULL);
}
}
void CResOrgSymbolsDoc::OnCmdFileProperties(void)
{
ShowSymbolFileProperties();
}
void CResOrgSymbolsDoc::OnCmdFilePropertiesStatistics(void)
{
ShowSymbolFileProperties( RUNTIME_CLASS(CResourceSymbolFileStatisticsPage) );
}
void CResOrgSymbolsDoc::OnCmdFilePropertiesNextSymbolValues(void)
{
ShowSymbolFileProperties( RUNTIME_CLASS(CResourceSymbolFileNextValuesPage) );
}
// Renumber all symbols
void CResOrgSymbolsDoc::OnCmdRenumberSymbols(void)
{
// To renumber all the symbols in a given file we need to pick starting
// values for each of the four symbol catgories identified by the _APS_NEXT...
// symbols in each resource file.
//
// The Symbol Renumbering Wizard works this out by looking at the values
// of existing symbols in the resource symbol file.
//
CRenumWizard Wizard;
Wizard.Initialise(m_pSymbolManager);
if (ID_WIZFINISH == Wizard.DoModal() )
{
if (m_pSymbolManager->IsModified() )
{
SetModifiedFlag(true);
UpdateAllViews(NULL, SYM_REFRESH);
}
}
}
void CResOrgSymbolsDoc::OnUpdateRenumberSymbols(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_pSymbolManager->GetSymbolCount() > 0);
}
void CResOrgSymbolsDoc::OnCmdReport(void)
{
CString sErrorMsg;
CResOrgReportStyleSheetDlg dlg;
if (IDOK == dlg.DoModal() )
{
CString sStyleSheetText;
int nStyleSheetID = dlg.GetStyleSheetID();
if (nStyleSheetID > 0)
{
sStyleSheetText = LoadXsl(nStyleSheetID);
}
else
{
try
{
CStdioFile f( dlg.GetStyleSheetPathName(),
CFile::modeRead | CFile::shareDenyWrite);
while (true)
{
CString sLine;
if (!f.ReadString(sLine) )
{
break;
}
sStyleSheetText += sLine + _T("\r\n");
}
f.Close();
}
catch (CFileException* pError)
{
LPTSTR pszErrorMsg = sErrorMsg.GetBuffer(_MAX_PATH);
::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
pError->m_lOsError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
pszErrorMsg,
_MAX_PATH,
NULL);
sErrorMsg.ReleaseBuffer();
pError->Delete();
}
}
ASSERT(!sStyleSheetText.IsEmpty() );
if (!sStyleSheetText.IsEmpty() )
{
if (m_sTemporaryReportPathName.IsEmpty() )
{
m_sTemporaryReportPathName = GetTemporaryReportName();
}
ASSERT(!m_sTemporaryReportPathName.IsEmpty() );
if (!m_sTemporaryReportPathName.IsEmpty() )
{
CString sErrorMsg;
if (CreateReport(sStyleSheetText, m_sTemporaryReportPathName, &sErrorMsg) )
{
//static_cast<CResOrgCoreApp*>( ::AfxGetApp() )->OpenHtmlView( GetTitle() + _T(" - Report"), _T("file://") + m_sTemporaryReportPathName);
static_cast<CResOrgCoreApp*>( ::AfxGetApp() )->OpenHtmlView( GetTitle() + _T(" - Report"), m_sTemporaryReportPathName);
}
else
{
::AfxMessageBox(sErrorMsg, MB_OK | MB_ICONSTOP);
}
}
}
}
}
bool CResOrgSymbolsDoc::CreateReport(const CString& sStyleSheetText,
const CString& sPathName,
CString* psMsg /*= NULL*/)
{
bool bResult = false;
CString sErrorMsg;
CString sReportText = GenerateReportText(sStyleSheetText, psMsg);
if (!sReportText.IsEmpty() )
{
try
{
CStdioFile f(sPathName, CFile::modeCreate | CFile::modeWrite);
f.WriteString(sReportText);
f.Close();
bResult = true;
}
catch (CFileException* pError)
{
LPTSTR pszErrorMsg = sErrorMsg.GetBuffer(_MAX_PATH);
::FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
pError->m_lOsError,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
pszErrorMsg,
_MAX_PATH,
NULL);
sErrorMsg.ReleaseBuffer();
pError->Delete();
}
}
return bResult;
}
CString CResOrgSymbolsDoc::GenerateReportText(const CString& sStyleSheetText, CString* psMsg /*= NULL*/) const
{
CString sReportText, sErrorMsg;
try
{
MSXML2::IXMLDOMDocumentPtr ptrDOMDoc;
MSXML2::IXMLDOMDocumentPtr ptrXSLTDOMDoc;
// Create empty DOM
::CoInitialize(NULL);
HRESULT hr = ptrDOMDoc.CreateInstance("Msxml2.DOMDocument.4.0");
if (FAILED(hr) )
{
sErrorMsg.LoadString(IDP_REPORT_ERR_XML_DOM_CREATE);
throw new CUserException();
}
hr = ptrXSLTDOMDoc.CreateInstance("Msxml2.DOMDocument.4.0");
if (FAILED(hr) )
{
sErrorMsg.LoadString(IDP_REPORT_ERR_XSLT_DOM_CREATE);
throw new CUserException();
}
ptrXSLTDOMDoc->async = false;
ptrXSLTDOMDoc->loadXML( (LPCTSTR)sStyleSheetText);
sReportText = GenerateReport( (IXMLDOMDocument*)ptrDOMDoc.GetInterfacePtr(),
(IXMLDOMDocument*)ptrXSLTDOMDoc.GetInterfacePtr(),
psMsg);
}
catch(_com_error& e)
{
HRESULT hr = e.Error();
TRACE( _T("Unable to display report. Error code 0x%08x"), hr);
if (NULL != psMsg)
{
psMsg->Format( _T("CResOrgSymbolsDoc::GenerateReportText()\nException 0x%08x"), hr);
}
}
catch(CUserException* e)
{
if (NULL != psMsg)
{
psMsg->Format( _T("CResOrgSymbolsDoc::GenerateReportText()\n%s"), sErrorMsg);
}
e->Delete();
}
return sReportText;
}
CString CResOrgSymbolsDoc::GenerateReport( IXMLDOMDocument* pXmlDoc,
IXMLDOMDocument* pStyleSheetDoc,
CString* psMsg /*= NULL*/) const
{
MSXML2::IXMLDOMDocumentPtr ptrXmlDoc(pXmlDoc);
MSXML2::IXMLDOMDocumentPtr ptrStyleSheetDoc(pStyleSheetDoc);
CString sErrorMsg;
CString sReportText;
try
{
// tell our shape to save its state as XML (into ptrDOMDoc)
HRESULT hr = SaveXml( (IXMLDOMDocument*)ptrXmlDoc.GetInterfacePtr(), &sErrorMsg);
if (FAILED(hr) )
{
sErrorMsg = _T("Failed to generate XML stream - ") + sErrorMsg;
throw new CUserException();
}
ptrStyleSheetDoc->async = false;
// Perform the transformation
sReportText = (LPCTSTR)ptrXmlDoc->transformNode(ptrStyleSheetDoc);
}
catch (CUserException* pError)
{
// Nothing to do here - we already know what's wrong
pError->Delete();
}
if (sReportText.IsEmpty())
{
if ( (NULL != psMsg) && !sErrorMsg.IsEmpty() )
{
*psMsg = sErrorMsg;
}
TRACE("ERROR in CResOrgSymbolsDoc::GenerateReport(): %s\n", sErrorMsg);
}
return sReportText;
}
bool CResOrgSymbolsDoc::WriteXml(const CString& sPathName, CString* psMsg /*= NULL*/) const
{
ASSERT(!sPathName.IsEmpty() );
bool bResult = false;
CString sErrorMsg;
ASSERT(NULL != m_pSymbolManager);
if (!sPathName.IsEmpty() && (NULL != m_pSymbolManager) )
{
try
{
MSXML2::IXMLDOMDocumentPtr ptrDOMDoc;
// Create empty DOM
::CoInitialize(NULL);
HRESULT hr = ptrDOMDoc.CreateInstance("Msxml2.DOMDocument.4.0");
if (FAILED(hr) )
{
//sErrorMsg.LoadString(IDP_RESORG_ERR_XML_DOM_CREATE);
sErrorMsg = _T("Failed to create XML DOM");
throw new CUserException();
}
hr = SaveXml( (IXMLDOMDocument*)ptrDOMDoc.GetInterfacePtr(), &sErrorMsg);
if (FAILED(hr) )
{
sErrorMsg = _T("Failed to save XML stream - ") + sErrorMsg;
throw new CUserException();
}
try
{
_variant_t varPathName = (LPCTSTR)sPathName;
ptrDOMDoc->save(varPathName);
bResult = true;
}
catch(_com_error& e)
{
sErrorMsg = (LPCTSTR)e.Description();
}
}
catch (CUserException* pError)
{
// Nothing to do here - we already know what's wrong
pError->Delete();
}
}
if (!bResult)
{
if ( (NULL != psMsg) && !sErrorMsg.IsEmpty() )
{
*psMsg = sErrorMsg;
}
TRACE( _T("ERROR in CResOrgSymbolsDoc::WriteXml(): %s\n"), sErrorMsg);
}
return bResult;
}
HRESULT CResOrgSymbolsDoc::SaveXml( IXMLDOMDocument* pDOMDoc,
CString* psMsg /*= NULL*/) const
{
HRESULT hr = E_FAIL;
CString sErrorMsg;
ASSERT(NULL != m_pSymbolManager);
if (NULL != m_pSymbolManager)
{
try
{
hr = S_OK;
MSXML2::IXMLDOMDocumentPtr ptrDOMDoc(pDOMDoc);
// Add xml version node
CString sAttribs = _T("version=\"1.0\" encoding=\"iso-8859-1\"");
MSXML2::IXMLDOMProcessingInstructionPtr ptrIns;
ptrIns = ptrDOMDoc->createProcessingInstruction(_T("xml"), (LPCTSTR)sAttribs);
ptrDOMDoc->appendChild(ptrIns);
// Create root element
MSXML2::IXMLDOMElementPtr ptrRoot = ptrDOMDoc->createElement(_T("ResOrgExportFile") );
ptrDOMDoc->appendChild(ptrRoot);
CResOrgXmlWriter writer;
hr = writer.SaveXml( m_pSymbolManager,
(IXMLDOMDocument*)ptrDOMDoc.GetInterfacePtr(),
(IXMLDOMElement*)ptrRoot.GetInterfacePtr(),
&sErrorMsg);
MSXML2::IXMLDOMElementPtr ptrApplication = ptrDOMDoc->createElement( _T("Application") );
MSXML2::IXMLDOMAttributePtr ptrAppNameAttr = ptrDOMDoc->createAttribute(_T("name"));
ptrAppNameAttr->value = _T("ResOrg");
ptrApplication->setAttributeNode(ptrAppNameAttr);
ptrRoot->appendChild(ptrApplication);
CNGModuleVersion ver;
ver.GetFileVersionInfo();
MSXML2::IXMLDOMElementPtr ptrName = ptrDOMDoc->createElement( _T("Name") );
ptrName->text = (LPCTSTR)ver.GetValue( _T("ProductName") );
ptrApplication->appendChild(ptrName);
MSXML2::IXMLDOMElementPtr ptrVersion = ptrDOMDoc->createElement( _T("Version") );
ptrVersion->text = (LPCTSTR)ver.GetValue( _T("FileVersion") );
ptrApplication->appendChild(ptrVersion);
MSXML2::IXMLDOMElementPtr ptrWebUrl = ptrDOMDoc->createElement( _T("WebUrl") );
ptrWebUrl->text = (LPCTSTR)Options.GetWebURL();
ptrApplication->appendChild(ptrWebUrl);
MSXML2::IXMLDOMElementPtr ptrTimestamp = ptrDOMDoc->createElement( _T("Timestamp") );
CTime t = CTime::GetCurrentTime();
CString sTimestamp = t.Format( _T("%A, %B %d, %Y, %H:%M") );
ptrTimestamp->text = (LPCTSTR)sTimestamp;
ptrRoot->appendChild(ptrTimestamp);
if (FAILED(hr) )
{
sErrorMsg = _T("Failed to save XML stream - ") + sErrorMsg;
throw new CUserException();
}
}
catch(_com_error& e)
{
hr = e.Error();
}
}
if (FAILED(hr) )
{
if ( (NULL != psMsg) && !sErrorMsg.IsEmpty() )
{
*psMsg = sErrorMsg;
}
TRACE( _T("ERROR in CResOrgSymbolsDoc::SaveXml(): %s\n"), sErrorMsg);
}
return hr;
}
CString CResOrgSymbolsDoc::LoadXsl(UINT uResourceID) const
{
CString sTemplate;
CString sResType = _T("XSL");
HINSTANCE hInst = ::AfxFindResourceHandle(MAKEINTRESOURCE(uResourceID), sResType);
if (NULL != hInst)
{
HRSRC hRsrc = ::FindResource(hInst, MAKEINTRESOURCE(uResourceID), sResType);
if (NULL != hRsrc)
{
HGLOBAL hGlobal = ::LoadResource(hInst, hRsrc);
LPBYTE pBuffer = (LPBYTE)::LockResource(hGlobal);
sTemplate = (LPCTSTR)pBuffer;
}
}
return sTemplate;
}
CString CResOrgSymbolsDoc::GetTemporaryReportName(void) const
{
CString sPathName;
TCHAR szFolderPath[_MAX_PATH + 1];
::GetTempPath(_MAX_PATH, szFolderPath);
LPTSTR pszPathName = sPathName.GetBuffer(_MAX_PATH);
if (0 != ::GetTempFileName( szFolderPath,
_T("HTM"),
0,
pszPathName) )
{
sPathName.ReleaseBuffer();
PathRemoveExtension(sPathName);
PathAddExtension(sPathName, _T(".html") );
}
return sPathName;
}
void CResOrgSymbolsDoc::DeleteTemporaryReport(void)
{
if (!m_sTemporaryReportPathName.IsEmpty() )
{
// Delete temporary file if it exists
::_tremove(m_sTemporaryReportPathName);
m_sTemporaryReportPathName = _T("");
}
}
BOOL CResOrgSymbolsDoc::PathAddExtension(CString& rsPathName, const CString& sExtension) const
{
LPTSTR pszPathName = rsPathName.GetBuffer(_MAX_PATH);
BOOL bResult = ::PathAddExtension(pszPathName, sExtension);
rsPathName.ReleaseBuffer();
return bResult;
}
void CResOrgSymbolsDoc::PathRemoveExtension(CString& rsPathName) const
{
LPTSTR pszPathName = rsPathName.GetBuffer(_MAX_PATH);
::PathRemoveExtension(pszPathName);
rsPathName.ReleaseBuffer();
}