// CCppGenerationManager.cpp
//
#include "stdafx.h"
#include "CppGenerationManager.h"
#include "CppClassGenerator.h"
#include "CppClassArrayGenerator.h"
#include "CppClassMapGenerator.h"
#include "CppClassDialogGenerator.h"
#include "CppCatListDialogGenerator.h"
#include "CppGridDialogGenerator.h"
#include "CppMainDialogGenerator.h"
#include "CppResourceGenerator.h"
#include "CppTreeNodeInfoGenerator.h"
#include "CppArrayDialogGenerator.h"
#include "CppMapDialogGenerator.h"
#include "XmlProject.h"
#include "XmlProjectSettings.h"
#include "XmlClassInfo.h"
#include "CPathSplit.h"
#include "IGeneratorListener.h"
#include <vector>
#include <map>
#include "enums.h"

CCppGenerationManager::CCppGenerationManager():
	project_(NULL),
	listener_(NULL)
{
}

CCppGenerationManager::~CCppGenerationManager()
{

}

void CCppGenerationManager::RegisterListener(IGeneratorListener* listener)
{
	listener_ = listener;
}

bool CCppGenerationManager::Generate(const cmString& currentDirectory, 
									 CXmlProject* project)
{
	vector<CXmlClassInfo*> parentStack;

	// store data
	//
	project_ = project;
	currentDirectory_ = currentDirectory;
	projectSettings_ = project_->GetProjectSettings();
	cppSettings_ = projectSettings_->GetCppSettings();

	if (!cppSettings_->GetEnabled() || 
		cppSettings_->GetPostGenerationStep()->GetActionId() == enGeneratorAction_None) {
		listener_->OnTaskComplete(_T("MFC dll generation disabled"));
		return true;
	}

	cppGeneratedFiles_.clear();
	hGeneratedFiles_.clear();
	
	// check settings
	//
	listener_->OnNewTask(_T("Checking settings ..."));
	if (cppSettings_->GetClassPrefix().GetLength() == 0) {
		listener_->OnTaskFailed(_T("Class prefix is empty."));
		return false;
	}
	if (cppSettings_->GetGenerationPath().GetLength() == 0) {
		listener_->OnTaskFailed(_T("Invalid generation path"));
		return false;
	}
	listener_->OnTaskComplete(_T("Settings checked."));

	// create folders
	//
	listener_->OnNewTask(_T("Creating folder structure ..."));
	CreateFolders(project_->GetProjectSettings());
	listener_->OnTaskComplete(_T("Folder structure created."));
	
	listener_->OnNewTask(_T("Generating classes ..."));
	parentStack.clear();
	GenerateClass(project_->GetRootElement(), parentStack);
	parentStack.clear();
	GenerateClassContainer(project_->GetRootElement(), parentStack);
	if (project_->GetProjectSettings()->GetCppSettings()->GetGUIGenerationEnabled()) {
		GenerateGuiClass(project_->GetRootElement(), parentStack);
		GenerateGuiManager();
		GenerateGuiTreeNodeInfo();
	}

	GenerateGuiResources();

	GenerateCppComponentsFile();
	listener_->OnTaskComplete(_T("Classes generation complete."));

	listener_->OnNewTask(_T("Copying files ..."));
	CopyComponentsFiles();
	GenerateCppFileList();
	CopyDllProjectFiles();
	GenerateDefFile();

	GenerateDllBatch();
	CopyFiles();

	CopyHeaders();
	listener_->OnTaskComplete(_T("All files have been copied."));
	
	if (cppSettings_->GetTestPrjGenerationEnabled()) {
		listener_->OnNewTask(_T("Creating Test Project ..."));
		CopyTestProjectFiles();
		GenerateTestProjectDialog();	
		listener_->OnTaskComplete(_T("Test Project Created."));
	}

	return true;
}

void CCppGenerationManager::GenerateClass(CXmlClassInfo* classInfo, vector<CXmlClassInfo*> parentStack)
{
	if (classInfo->GetDataType() != enDataType_Class ||
		classInfo->GetDefinitionInheritance())
		return;
	
	// generates data-class
	//
	CCppClassGenerator generator;
	
	generator.SetClassInfo(classInfo, parentStack);
	generator.SetProject(project_);
	generator.Generate();

	// generates children data-classes
	//
	ClassMemberMap* members;
	ClassMemberMap::iterator it;
	CXmlBaseElement* member;

	parentStack.push_back(classInfo);
	members = classInfo->GetMembers();
	for (it = members->begin(); it != members->end(); it++) {
		member = it->second;

		if (member->GetDataType() == enDataType_Class)
			GenerateClass(dynamic_cast<CXmlClassInfo*>(member), parentStack);
	}
}

void CCppGenerationManager::GenerateClassContainer(CXmlClassInfo* classInfo, vector<CXmlClassInfo*> parentStack)
{
	if (classInfo->GetDataType() != enDataType_Class ||
		classInfo->GetDefinitionInheritance())
		return;
	
	// generates data-class-container
	//
	if (classInfo->GetCardinalityInfo()->GetCardinality() == enCardinality_Array) {
		CCppClassArrayGenerator generator;
		
		generator.SetClassInfo(classInfo, parentStack);
		generator.SetProject(project_);
		generator.Generate();
	} else if (classInfo->GetCardinalityInfo()->GetCardinality() == enCardinality_Map) {
		CCppClassMapGenerator generator;
		
		generator.SetClassInfo(classInfo, parentStack);
		generator.SetProject(project_);
		generator.Generate();
	}

	// generates children data-classes
	//
	ClassMemberMap* members;
	ClassMemberMap::iterator it;
	CXmlBaseElement* member;

	parentStack.push_back(classInfo);
	members = classInfo->GetMembers();
	for (it = members->begin(); it != members->end(); it++) {
		member = it->second;

		if (member->GetDataType() == enDataType_Class)
			GenerateClassContainer(dynamic_cast<CXmlClassInfo*>(member), parentStack);
	}
}

void CCppGenerationManager::GenerateGuiClass(CXmlClassInfo* classInfo, vector<CXmlClassInfo*> parentStack)
{
	if (classInfo->GetDataType() != enDataType_Class)
		return;

	if (classInfo->GetRenderingMode() != enRenderingMode_None ||
		classInfo->GetLockedByInheritance()) {

		// generates dialog-class
		//
		CCppClassDialogGenerator dlgGenerator;
		CCppCatListDialogGenerator catListGenerator;
		CCppGridDialogGenerator gridGenerator;
		CCppArrayDialogGenerator arrayDialogGenerator;
		CCppMapDialogGenerator mapDialogGenerator;

		switch (classInfo->GetRenderingMode()) {
			case enRenderingMode_None:
				break;

			case enRenderingMode_FlatList:
				break;

			case enRenderingMode_CategoryList:
				catListGenerator.SetClassInfo(classInfo, parentStack);
				catListGenerator.SetProject(project_);
				catListGenerator.Generate();
				break;

			case enRenderingMode_Grid:
				gridGenerator.SetClassInfo(classInfo, parentStack);
				gridGenerator.SetProject(project_);
				gridGenerator.Generate();
				break;

			case enRenderingMode_CustomDialog:
				//dlgGenerator.SetClassInfo(classInfo, parentStack);
				//dlgGenerator.SetProject(project_);
				//dlgGenerator.Generate();
				break;
		
		}
		
		if (classInfo->GetRenderingMode() != enRenderingMode_Grid) {
			switch (classInfo->GetCardinalityInfo()->GetCardinality()) {
				case enCardinality_Array:
					arrayDialogGenerator.SetClassInfo(classInfo, parentStack);
					arrayDialogGenerator.SetProject(project_);
					arrayDialogGenerator.Generate();
					break;

				case enCardinality_Map:
					mapDialogGenerator.SetClassInfo(classInfo, parentStack);
					mapDialogGenerator.SetProject(project_);
					mapDialogGenerator.Generate();
					break;
			}
		}
	}

	// generates children data-classes
	//
	ClassMemberMap* members;
	ClassMemberMap::iterator it;
	CXmlBaseElement* member;

	parentStack.push_back(classInfo);
	members = classInfo->GetMembers();
	for (it = members->begin(); it != members->end(); it++) {
		member = it->second;

		if (member->GetDataType() == enDataType_Class)
			GenerateGuiClass(dynamic_cast<CXmlClassInfo*>(member), parentStack);
	}
}

void CCppGenerationManager::GenerateGuiManager()
{
	CCppMainDialogGenerator generator;
	vector<CXmlClassInfo*> parentStack;

	generator.SetProject(project_);
	generator.SetClassInfo(project_->GetRootElement(), parentStack);
	generator.Generate();
}

cmString CCppGenerationManager::GetCurDirectory()
{
	return currentDirectory_;
}

void CCppGenerationManager::CreateFolders(CXmlProjectSettings* projectSettings)
{
	cmString dirName;
	cmString generationPath;
	cmString classPrefix;
	cmString sourcePath;
	cmString tmp;
	
	generationPath = projectSettings->GetCppSettings()->GetGenerationPath();
	classPrefix = projectSettings->GetCppSettings()->GetClassPrefix();
	sourcePath = generationPath + _T("\\") + classPrefix;

	CreateDirectory(generationPath, NULL);
	tmp = generationPath + _T("\\include");
	CreateDirectory(tmp, NULL);
	tmp = generationPath + _T("\\lib");
	CreateDirectory(tmp, NULL);
	CreateDirectory(sourcePath, NULL);
	dirName = sourcePath + _T("\\src");
	CreateDirectory(dirName, NULL);

	dirName = sourcePath + _T("\\include");
	CreateDirectory(dirName, NULL);

	dirName = sourcePath + _T("\\lib");
	CreateDirectory(dirName, NULL);

	dirName = sourcePath + _T("\\components");
	CreateDirectory(dirName, NULL);

	dirName = sourcePath + _T("\\project");
	CreateDirectory(dirName, NULL);

	dirName = sourcePath + _T("\\project\\res");
	CreateDirectory(dirName, NULL);
	
	dirName = sourcePath + _T("\\components\\cmOptionList");
	CreateDirectory(dirName, NULL);
	
	dirName = sourcePath + _T("\\components\\cmTable");
	CreateDirectory(dirName, NULL);

	dirName = sourcePath + _T("\\components\\common");
	CreateDirectory(dirName, NULL);

	if (cppSettings_->GetTestPrjGenerationEnabled()) {
		dirName = sourcePath + _T("\\testProject\\");
		CreateDirectory(dirName, NULL);	

		dirName = sourcePath + _T("\\testProject\\res");
		CreateDirectory(dirName, NULL);	
	}

}

void CCppGenerationManager::GenerateGuiResources()
{
	CCppResourceGenerator generator;
	vector<CXmlClassInfo*> parentStack;

	generator.SetProject(project_);
	generator.SetClassInfo(project_->GetRootElement(), parentStack);
	generator.Generate();
}

void CCppGenerationManager::CopyFiles()
{
	cmString destPath;
	cmString globalPath;
	cmString sourcePath;
	cmString generationPath;

	generationPath = project_->GetProjectSettings()->GetCppSettings()->GetGenerationPath();
	sourcePath = GetCurDirectory();
	destPath += generationPath + _T("\\") + projectSettings_->GetCppSettings()->GetClassPrefix();
	globalPath = generationPath + _T("\\include");

	// copy xmlparser library to specific include directory
	//
	/***
	CopyDirectory(sourcePath + _T("\\templates\\xmlparser\\lib"), destPath + _T("\\components\\xmlParser\\lib"));
	CopyDirectory(sourcePath + _T("\\templates\\xmlparser\\lib"), generationPath + _T("\\lib"));
	CopyDirectory(sourcePath + _T("\\templates\\xmlparser\\include"), destPath + _T("\\components\\xmlParser\\include"));
	CopyDirectory(sourcePath + _T("\\templates\\xmlparser\\include"), destPath + _T("\\include"));
	CopyDirectory(sourcePath + _T("\\templates\\xmlparser\\include"), globalPath);
	if (cppSettings_->GetTestPrjGenerationEnabled())
		CopyDirectory(sourcePath + _T("\\templates\\xmlparser\\lib"), generationPath + _T("\\testProject"));
	***/
	// copy XmlSerializable files
	//
	cmString sourceFileName;
	cmString destFileName;

	sourceFileName = sourcePath + _T("\\templates\\projectStorage\\XmlSerializable.h");
	destFileName = destPath + _T("\\include\\XmlSerializable.h");
	::CopyFile(sourceFileName, destFileName, FALSE);
	
	sourceFileName = sourcePath + _T("\\templates\\projectStorage\\XmlSerializable.h");
	destFileName = globalPath + _T("\\XmlSerializable.h");
	::CopyFile(sourceFileName, destFileName, FALSE);

	sourceFileName = sourcePath + _T("\\templates\\projectStorage\\XmlSerializable.cpp");
	destFileName = destPath + _T("\\src\\XmlSerializable.cpp");
	::CopyFile(sourceFileName, destFileName, FALSE);

	// copy cmString files
	//
	sourceFileName = sourcePath + _T("\\templates\\guiComponents\\common.cpp\\cmString.h");
	destFileName = globalPath + _T("\\cmString.h");
	::CopyFile(sourceFileName, destFileName, FALSE);

	/***
	sourceFileName = sourcePath + _T("\\templates\\projectStorage\\cmString.h");
	destFileName = destPath + _T("\\components\\common\\cmString.h");
	::CopyFile(sourceFileName, destFileName, FALSE);
	
	
	sourceFileName = sourcePath + _T("\\templates\\projectStorage\\cmString.h");
	destFileName = globalPath + _T("\\cmString.h");
	::CopyFile(sourceFileName, destFileName, FALSE);
	
	sourceFileName = sourcePath + _T("\\templates\\projectStorage\\cmString.cpp");
	destFileName = destPath + _T("\\src\\cmString.cpp");
	::CopyFile(sourceFileName, destFileName, FALSE);
	***/
}

void CCppGenerationManager::CopyComponentsFiles()
{
	cmString destPath;
	cmString sourcePath;
	cmString generationPath;

	generationPath = project_->GetProjectSettings()->GetCppSettings()->GetGenerationPath();
	sourcePath = GetCurDirectory();
	destPath += generationPath + _T("\\") + projectSettings_->GetCppSettings()->GetClassPrefix() + _T("\\");

	// Copy components folders
	//
	CopyDirectory(sourcePath + _T("\\templates\\GuiComponents\\cmOptionList"), destPath + _T("components\\cmOptionList"));
	CopyDirectory(sourcePath + _T("\\templates\\GuiComponents\\cmTable"), destPath + _T("components\\cmTable"));
	CopyDirectory(sourcePath + _T("\\templates\\GuiComponents\\common"), destPath + _T("components\\common"));
	CopyDirectory(sourcePath + _T("\\templates\\GuiComponents\\common.cpp"), destPath + _T("components\\common"));

	// Copy icons
	//
	IconMap::iterator it;
	IconMap* icons;
	CPathSplit pathSplit;
	cmString genPath;
	cmString prefix;
	cmString sourceFileName;
	cmString destFileName;
	CXmlIcon* icon;

	genPath = projectSettings_->GetCppSettings()->GetGenerationPath();
	prefix = projectSettings_->GetCppSettings()->GetClassPrefix();

	icons = project_->GetProjectIcons()->GetIconList();

	for (it = icons->begin(); it != icons->end(); it++) {
		icon = it->second;
				
		destFileName = genPath;
		destFileName += _T("\\");
		destFileName += prefix;
		destFileName += _T("\\project\\res\\");
		destFileName += icon->GetFileName();
		
		icon->WriteToFile(destFileName);
	}

	if (project_->GetMainDialog()->GetIconFileName().GetLength()) {
		sourceFileName = project_->GetMainDialog()->GetIconFileName();
		pathSplit.Split(sourceFileName);

		destFileName = genPath;
		destFileName += _T("\\");
		destFileName += prefix;
		destFileName += _T("\\project\\res\\");
		destFileName += (const wchar_t*)pathSplit.GetFileName();
		destFileName += (const wchar_t*)pathSplit.GetExtension();

		CopyFile(sourceFileName, destFileName, FALSE);
	}	
}

void CCppGenerationManager::CopySingleFile(const cmString& source, const cmString& destination)
{
	cmString fileSource;
	cmString fileDestination;
	cmString generationPath;
	BOOL ret;

	generationPath = project_->GetProjectSettings()->GetCppSettings()->GetGenerationPath();

	fileSource = GetCurDirectory() + source;
	if (destination == _T(""))
		fileDestination = generationPath + source;
	else
		fileDestination = generationPath + destination;

	ret = ::CopyFile(fileSource, fileDestination, FALSE);
	if(!ret) {
		DWORD ret;
		cmString msg;

		ret = ::GetLastError();

		msg.Format(_T("Unable to copy file %s to %s (errCode=0x%08X)"), fileSource.c_str(), fileDestination.c_str(), ret);
		listener_->OnTaskFailed(msg);
	}
}

void CCppGenerationManager::GenerateGuiTreeNodeInfo()
{
	CCppTreeNodeInfoGenerator generator;

	generator.SetProject(project_);
	generator.Generate();
}

void CCppGenerationManager::CopyDllProjectFiles()
{
	cmString destPath;

	destPath += _T("\\") + projectSettings_->GetCppSettings()->GetClassPrefix() + _T("\\");

	CopySingleFile(_T("\\templates\\ProjectConfigDll\\ProjectConfigDll.cpp"), destPath + _T("project\\ProjectConfigDll.cpp"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\ProjectConfigDll.dsp"), destPath + _T("project\\ProjectConfigDll.dsp"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\ProjectConfigDll.dsw"), destPath + _T("project\\ProjectConfigDll.dsw"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\ProjectConfigDll.rc"), destPath + _T("project\\ProjectConfigDll.rc"));

	CopySingleFile(_T("\\templates\\ProjectConfigDll\\cmSplitDialog.h"), destPath + _T("project\\cmSplitDialog.h"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\cmSplitDialog.cpp"), destPath + _T("project\\cmSplitDialog.cpp"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\Resource.h"), destPath + _T("project\\Resource.h"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\StdAfx.cpp"), destPath + _T("project\\StdAfx.cpp"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\StdAfx.h"), destPath + _T("project\\StdAfx.h"));
	//CopySingleFile(_T("\\templates\\ProjectConfigDll\\IMainTreeCtrlListener.h"), destPath + _T("project\\IMainTreeCtrlListener.h"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\InputBox.h"), destPath + _T("project\\InputBox.h"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\InputBox.cpp"), destPath + _T("project\\InputBox.cpp"));
	
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\res\\ProjectConfigDll.rc2"), destPath + _T("project\\res\\ProjectConfigDll.rc2"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\res\\icon1.ico"), destPath + _T("project\\res\\icon1.ico"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\res\\chkChecked.ico"), destPath + _T("project\\res\\chkChecked.ico"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\res\\chkUnchecked.ico"), destPath + _T("project\\res\\chkUnchecked.ico"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\res\\combobox_normal.bmp"), destPath + _T("project\\res\\combobox_normal.bmp"));
	CopySingleFile(_T("\\templates\\ProjectConfigDll\\res\\combobox_over.bmp"), destPath + _T("project\\res\\combobox_over.bmp"));

}

void CCppGenerationManager::GenerateCppFileList()
{
	map<cmString, cmString>::iterator it;
	cmString code;
	cmString destPath;
	cmString fileName;

	destPath = projectSettings_->GetCppSettings()->GetGenerationPath() + _T("\\") + projectSettings_->GetCppSettings()->GetClassPrefix() + _T("\\project\\");

	code += _T("// all.cpp") + xCrLf;
	code += _T("//") + xCrLf;
	code += xCrLf;
	code += _T("#include \"stdafx.h\"") + xCrLf + xCrLf;

	for (it = cppGeneratedFiles_.begin(); it != cppGeneratedFiles_.end(); it++) {
		fileName = it->first;
		code += _T("#pragma message(\"") + fileName + _T("\")") + xCrLf;
		code += _T("#include \"..\\src\\") + fileName + _T("\"") + xCrLf;
	}
	code += _T("#pragma message(\"XMLSerializable.cpp\")") + xCrLf;
	code += _T("#include \"..\\src\\XMLSerializable.cpp\"") + xCrLf;

	SaveFile(destPath + _T("all.cpp"), code, false);
}

void CCppGenerationManager::GenerateDllBatch()
{
	cmString code;
	cmString fileName;
	cmString genPath;
	cmString prefix;
	cmString libPath;
	enGeneratorConfig configId;
	
	genPath = cppSettings_->GetGenerationPath();
	prefix = cppSettings_->GetClassPrefix();
	configId = cppSettings_->GetPostGenerationStep()->GetConfigId();
	
	libPath = genPath + _T("\\") + prefix + _T("\\lib");

	// debug configuration post-build file
	//
	fileName = genPath + _T("\\") + prefix + _T("\\project\\postbuild_D.bat");
	GeneratePostBuildFile(fileName, _T("_D"), libPath);
	
	// release configuration post-build file
	//
	fileName = genPath + _T("\\") + prefix + _T("\\project\\postbuild_R.bat");
	GeneratePostBuildFile(fileName, _T("_R"), libPath);

	// debug_unicode configuration post-build file
	//
	fileName = genPath + _T("\\") + prefix + _T("\\project\\postbuild_DU.bat");
	GeneratePostBuildFile(fileName, _T("_DU"), libPath);
	
	// release configuration post-build file
	//
	fileName = genPath + _T("\\") + prefix + _T("\\project\\postbuild_RU.bat");
	GeneratePostBuildFile(fileName, _T("_RU"), libPath);
}

void CCppGenerationManager::GenerateDefFile()
{
	cmString code;
	cmString prefix;
	cmString fileName;
	cmString genPath;
	
	genPath = projectSettings_->GetCppSettings()->GetGenerationPath();
	prefix = projectSettings_->GetCppSettings()->GetClassPrefix();

	// debug def file
	//
	code.Empty();
	code += _T("; ") + prefix + _T("_D.def : Declares the module parameters for the DLL (Debug Version).") + xCrLf;
	code += xCrLf;
	code += _T("LIBRARY      \"") + prefix + _T("_D\"") + xCrLf;
	code += _T("DESCRIPTION  '") + prefix + _T(" Windows Dynamic Link Library (Debug Version)'") + xCrLf;
	code += xCrLf;
	code += _T("EXPORTS") + xCrLf;
    code += _T("; Explicit exports can go here") + xCrLf;
	code += xCrLf;

	fileName = genPath + _T("\\") + prefix + _T("\\project\\") + prefix + _T("_D.def");
	SaveFile(fileName, code, false);

	// debug unicode def file
	//
	code.Empty();
	code += _T("; ") + prefix + _T("_DU.def : Declares the module parameters for the DLL (Debug Unicode Version).") + xCrLf;
	code += xCrLf;
	code += _T("LIBRARY      \"") + prefix + _T("_DU\"") + xCrLf;
	code += _T("DESCRIPTION  '") + prefix + _T(" Windows Dynamic Link Library (Debug Unicode Version)'") + xCrLf;
	code += xCrLf;
	code += _T("EXPORTS") + xCrLf;
    code += _T("; Explicit exports can go here") + xCrLf;
	code += xCrLf;

	fileName = genPath + _T("\\") + prefix + _T("\\project\\") + prefix + _T("_DU.def");
	SaveFile(fileName, code, false);

	// release def file
	//
	code.Empty();
	code += _T("; ") + prefix + _T("_R.def : Declares the module parameters for the DLL (Release Version).") + xCrLf;
	code += xCrLf;
	code += _T("LIBRARY      \"") + prefix + _T("_R\"") + xCrLf;
	code += _T("DESCRIPTION  '") + prefix + _T(" Windows Dynamic Link Library (Release Version)'") + xCrLf;
	code += xCrLf;
	code += _T("EXPORTS") + xCrLf;
    code += _T("; Explicit exports can go here") + xCrLf;
	code += xCrLf;

	fileName = genPath + _T("\\") + prefix + _T("\\project\\") + prefix + _T("_R.def");
	SaveFile(fileName, code, false);

	// release unicode def file
	//
	code.Empty();
	code += _T("; ") + prefix + _T("_RU.def : Declares the module parameters for the DLL (Release UnicodeVersion).") + xCrLf;
	code += xCrLf;
	code += _T("LIBRARY      \"") + prefix + _T("_RU\"") + xCrLf;
	code += _T("DESCRIPTION  '") + prefix + _T(" Windows Dynamic Link Library (Release Unicode Version)'") + xCrLf;
	code += xCrLf;
	code += _T("EXPORTS") + xCrLf;
    code += _T("; Explicit exports can go here") + xCrLf;
	code += xCrLf;

	fileName = genPath + _T("\\") + prefix + _T("\\project\\") + prefix + _T("_RU.def");
	SaveFile(fileName, code, false);
}

void CCppGenerationManager::CopyHeaders()
{
	map<cmString, cmString>::iterator it;
	cmString sourceFileName;
	cmString destinationFileName;
	cmString genPath;
	cmString prefix;
	BOOL ret;
	DWORD err;

	genPath = projectSettings_->GetCppSettings()->GetGenerationPath();
	prefix = projectSettings_->GetCppSettings()->GetClassPrefix();

	for (it = hGeneratedFiles_.begin(); it != hGeneratedFiles_.end(); it++) {
		sourceFileName = genPath + _T("\\") + prefix + _T("\\include\\") + it->first;
		destinationFileName = genPath + _T("\\include\\") + it->first;

		ret = ::CopyFile(sourceFileName, destinationFileName, FALSE);
	 
		err = ::GetLastError();
	}
	
	sourceFileName = genPath + _T("\\") + prefix + _T("\\project\\cmSplitDialog.h");
	destinationFileName = genPath + _T("\\include\\cmSplitDialog.h");

	::CopyFile(sourceFileName, destinationFileName, NULL);

	destinationFileName = genPath + _T("\\") + prefix + _T("\\include\\cmSplitDialog.h");
	::CopyFile(sourceFileName, destinationFileName, NULL);
}

void CCppGenerationManager::RunCompiler()
{
	enGeneratorAction actionId;
	enGeneratorConfig configId;
	
	actionId = cppSettings_->GetPostGenerationStep()->GetActionId();
	if (actionId == enGeneratorAction_None)
		return;

	cmString dllProjectFileName;
	cmString script;
	cmString prefix;
	cmString genPath;	

	genPath = projectSettings_->GetCppSettings()->GetGenerationPath();
	prefix = projectSettings_->GetCppSettings()->GetClassPrefix();

	dllProjectFileName = cppSettings_->GetGenerationPath();
	dllProjectFileName += _T("\\");
	dllProjectFileName += cppSettings_->GetClassPrefix();
	dllProjectFileName += _T("\\project\\ProjectConfigDll.dsw");

	configId = cppSettings_->GetPostGenerationStep()->GetConfigId();

	listener_->OnNewTask(_T("Running Visual C++"));
	script += _T("dim app") + xCrLf;
	script += _T("dim prj") + xCrLf;
	script += _T("dim cfg") + xCrLf;
	script += xCrLf;
	script += _T("on error resume next") + xCrLf;
	script += xCrLf;
	script += _T("set app = createobject(\"msdev.application\")") + xCrLf;
	script += xCrLf;
	script += _T("app.documents.open(\"") + dllProjectFileName + _T("\")") + xCrLf;
	
	if (actionId == enGeneratorAction_GenerateAndCompile || actionId == enGeneratorAction_GenerateAndOpen)
		script += _T("app.visible = true") + xCrLf;
	else
		script += _T("app.visible = false") + xCrLf;

	script += _T("Set prj = app.ActiveProject") + xCrLf;

	script += xCrLf;
	script += _T("set cfg = prj.configurations.item(\"ProjectConfigDll - Win32 Debug\")") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/out:\"\"..\\lib\\") + prefix + _T("_D.dll\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/implib:\"\"..\\lib\\") + prefix + _T("_D.lib\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/def:\"\"") + prefix + _T("_D.def\"\"\"") + xCrLf;
	
	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_Debug) && 
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;	
	}

	script += xCrLf;
	script += _T("set cfg = prj.configurations.item(\"ProjectConfigDll - Win32 Debug Unicode\")") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/out:\"\"..\\lib\\") + prefix + _T("_DU.dll\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/implib:\"\"..\\lib\\") + prefix + _T("_DU.lib\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/def:\"\"") + prefix + _T("_DU.def\"\"\"") + xCrLf;
	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_UnicodeDebug) && 
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;
	}

	script += xCrLf;
	script += _T("set cfg = prj.configurations.item(\"ProjectConfigDll - Win32 Release\")") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/out:\"\"..\\lib\\") + prefix + _T("_R.dll\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/implib:\"\"..\\lib\\") + prefix + _T("_R.lib\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/def:\"\"") + prefix + _T("_R.def\"\"\"") + xCrLf;
	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_Release) &&
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;
	}
	
	script += xCrLf;
	script += _T("set cfg = prj.configurations.item(\"ProjectConfigDll - Win32 Release Unicode\")") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/out:\"\"..\\lib\\") + prefix + _T("_RU.dll\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/implib:\"\"..\\lib\\") + prefix + _T("_RU.lib\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/def:\"\"") + prefix + _T("_RU.def\"\"\"") + xCrLf;
	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_UnicodeRelease) &&
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;
	}
	
	script += xCrLf;
	script += _T("app.documents.saveall") + xCrLf;

	if (actionId == enGeneratorAction_GenerateAndCompile || 
		actionId == enGeneratorAction_GenerateOnly) {
		script += _T("app.quit") + xCrLf;
		script += _T("set app = nothing") + xCrLf;
	}

	cmString scriptFileName;

	scriptFileName = genPath;
	scriptFileName += _T("\\");
	scriptFileName += prefix;
	scriptFileName += _T("\\project\\runVc.vbs");
	SaveFile(scriptFileName, script, false);
	
	ShellExecute(NULL, _T("open"), scriptFileName, NULL, NULL, SW_HIDE);

	listener_->OnTaskComplete(_T("Visual C++ executing."));

	/***
	enGeneratorAction actionId;
	enGeneratorConfig configId;
	
	actionId = cppSettings_->GetPostGenerationStep()->GetActionId();
	if (actionId == enGeneratorAction_None || actionId == enGeneratorAction_GenerateOnly)
		return;

	cmString dllProjectFileName;
	cmString script;
	cmString prefix;
	cmString genPath;	

	genPath = projectSettings_->GetCppSettings()->GetGenerationPath();
	prefix = projectSettings_->GetCppSettings()->GetClassPrefix();

	dllProjectFileName = cppSettings_->GetGenerationPath();
	dllProjectFileName += _T("\\");
	dllProjectFileName += cppSettings_->GetClassPrefix();
	dllProjectFileName += _T("\\project\\ProjectConfigDll.dsw");

	listener_->OnNewTask(_T("Running Visual C++"));
	script += _T("dim app") + xCrLf;
	script += _T("dim prj") + xCrLf;
	script += _T("dim cfg") + xCrLf;
	script += xCrLf;
	script += _T("on error resume next") + xCrLf;
	script += xCrLf;
	script += _T("set app = createobject(\"msdev.application\")") + xCrLf;
	script += xCrLf;
	script += _T("app.documents.open(\"") + dllProjectFileName + _T("\")") + xCrLf;
	script += _T("app.visible = true") + xCrLf;
	script += _T("Set prj = app.ActiveProject") + xCrLf;
	script += xCrLf;

	configId = cppSettings_->GetPostGenerationStep()->GetConfigId();
	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_Debug) && 
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += xCrLf;
		script += _T("set cfg = prj.configurations.item(\"ProjectConfigDll - Win32 Debug\")") + xCrLf;
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;
	}

	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_UnicodeDebug) && 
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += xCrLf;
		script += _T("set cfg = prj.configurations.item(\"ProjectConfigDll - Win32 Debug Unicode\")") + xCrLf;
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;
	}

	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_Release) &&
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += xCrLf;
		script += _T("set cfg = prj.configurations.item(\"ProjectConfigDll - Win32 Release\")") + xCrLf;
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;
	}
	
	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_UnicodeRelease) &&
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += xCrLf;
		script += _T("set cfg = prj.configurations.item(\"ProjectConfigDll - Win32 Release Unicode\")") + xCrLf;
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;
	}

	if (actionId == enGeneratorAction_GenerateAndCompile) {
		script += _T("app.quit") + xCrLf;
		script += _T("set app = nothing") + xCrLf;
	}

	cmString scriptFileName;

	scriptFileName = genPath;
	scriptFileName += _T("\\");
	scriptFileName += prefix;
	scriptFileName += _T("\\project\\runVc.vbs");
	SaveFile(scriptFileName, script, false);
	
	ShellExecute(NULL, _T("open"), scriptFileName, NULL, NULL, SW_HIDE);

	listener_->OnTaskComplete(_T("Visual C++ executing."));
	***/
}

void CCppGenerationManager::CopyDirectory(cmString sourcePath, cmString destinationPath)
{
	vector<cmString> filesToCopy;
	WIN32_FIND_DATA findData;
	HANDLE hFind;
	BOOL ret;
	cmString filePattern;
	cmString sourceFileName;
	cmString destinationFileName;
	
	if (sourcePath.GetLength() && sourcePath[sourcePath.GetLength() - 1] != '\\')
		sourcePath += _T("\\");

	if (destinationPath.GetLength() && destinationPath[destinationPath.GetLength() - 1] != '\\')
		destinationPath += _T("\\");

	filePattern = sourcePath + _T("*.*");

	hFind = FindFirstFile(filePattern, &findData);
	if (hFind == INVALID_HANDLE_VALUE)
		return;

	ret = TRUE;
	while (ret) {
		
		if (wcscmp(findData.cFileName, _T(".")) && wcscmp(findData.cFileName, _T("..")))
			filesToCopy.push_back(findData.cFileName);

		ret = FindNextFile(hFind, &findData);
	}

	FindClose(hFind);

	for (int i = 0; i < filesToCopy.size(); i++) {	
		BOOL ret;
		sourceFileName = sourcePath + filesToCopy[i];
		destinationFileName = destinationPath + filesToCopy[i];
		
		ret = ::CopyFile(sourceFileName, destinationFileName, FALSE);
	}
}


void CCppGenerationManager::GenerateCppComponentsFile()
{
	map<cmString/*fileName*/, cmString/*filePath*/> fileList;
	map<cmString, cmString>::iterator it;
	cmString destPath;
	cmString sourcePath;
	cmString generationPath;

	generationPath = project_->GetProjectSettings()->GetCppSettings()->GetGenerationPath();
	sourcePath = GetCurDirectory();
		
	BuildComponentFileList(sourcePath + _T("\\templates\\GuiComponents\\cmOptionList"), _T("..\\components\\cmOptionList"), fileList);
	BuildComponentFileList(sourcePath + _T("\\templates\\GuiComponents\\cmTable"), _T("..\\components\\cmTable"), fileList);
	BuildComponentFileList(sourcePath + _T("\\templates\\GuiComponents\\common"), _T("..\\components\\common"), fileList);
	BuildComponentFileList(sourcePath + _T("\\templates\\GuiComponents\\common.cpp"), _T("..\\components\\common"), fileList);

	// generate file "AllComponents.h"
	//
	cmString code;

	code += _T("// components.cpp") + xCrLf;
	code += _T("//") + xCrLf;
	code += xCrLf;
	code += _T("#ifdef _DEBUG") + xCrLf;
	code += _T("#undef THIS_FILE") + xCrLf;
	code += _T("static char THIS_FILE[]=__FILE__;") + xCrLf;
	code += _T("#define new DEBUG_NEW") + xCrLf;
	code += _T("#endif") + xCrLf;
	code += xCrLf;
	code += _T("#include \"stdafx.h\"") + xCrLf;
	code += xCrLf;

	code += _T("// source files of all components") + xCrLf;
	code += _T("//") + xCrLf;

	for (it = fileList.begin(); it != fileList.end(); it++) {
		code += _T("#pragma message(\"Compiling ") + it->first + _T("\")") + xCrLf;
		code += _T("#include \"") + it->second + _T("\\") + it->first + _T("\"") + xCrLf;
		code += xCrLf;
	} code += xCrLf;

	destPath = generationPath + _T("\\") + projectSettings_->GetCppSettings()->GetClassPrefix() + _T("\\");

	SaveFile(destPath + _T("project\\AllComponents.cpp"), code, false);
}

void CCppGenerationManager::BuildComponentFileList(const cmString& pathName, const cmString& destinationPathName, map<cmString, cmString>& fileList)
{
	vector<cmString> tmpList;

	GetDirectoryFiles(pathName, _T("*.cpp"), tmpList);
	
	for (int i = 0; i < tmpList.size(); i++) {
		fileList[tmpList[i]] = destinationPathName;
	}
}

void CCppGenerationManager::GetDirectoryFiles(cmString pathName, const cmString& pattern, vector<cmString>& fileList)
{
	WIN32_FIND_DATA findData;
	HANDLE hFind;
	BOOL ret;
	cmString filePattern;
	cmString sourceFileName;
	cmString destinationFileName;
	
	fileList.clear();

	if (pathName.GetLength() && pathName[pathName.GetLength() - 1] != '\\')
		pathName += _T("\\");

	filePattern = pathName + pattern;

	hFind = FindFirstFile(filePattern, &findData);
	if (hFind == INVALID_HANDLE_VALUE) {
		DWORD err;

		err = GetLastError();
		return;
	}
	ret = TRUE;
	while (ret) {
		
		if (wcscmp(findData.cFileName, _T(".")) && wcscmp(findData.cFileName, _T("..")))
			fileList.push_back(findData.cFileName);

		ret = FindNextFile(hFind, &findData);
	}

	FindClose(hFind);
}

void CCppGenerationManager::RunTestProjectScript()
{
	cmString code;
	cmString testProjectName;
	cmString libName;
	cmString prefix;
	cmString genPath;	

	genPath = projectSettings_->GetCppSettings()->GetGenerationPath();
	prefix = projectSettings_->GetCppSettings()->GetClassPrefix();
	
	testProjectName = genPath + _T("\\") + prefix + _T("\\testProject\\testProject.dsw");
	
	code += _T("dim app") + xCrLf;
	code += xCrLf;
	code += _T("on error resume next") + xCrLf;
	code += _T("set app = createobject(\"msdev.application\")") + xCrLf;
	code += xCrLf;
	code += _T("app.documents.open(\"") + testProjectName + _T("\")") + xCrLf;
	code += _T("app.visible = false") + xCrLf;
	code += _T("AddLibFiles()") + xCrLf;
	code += _T("app.documents.SaveAll") + xCrLf;
	code += _T("app.quit") + xCrLf;
	code += xCrLf;
	code += _T("Sub AddLibFiles") + xCrLf;
	code += _T("	Dim buildPrj") + xCrLf;
	code += _T("	Dim config") + xCrLf;
	code += xCrLf;	
	code += _T("	' get first (and unique) project") + xCrLf;
	code += _T("	set buildPrj = app.Projects.item(1)") + xCrLf;
	
	libName = prefix + _T("_D.lib");
	code += _T("	set config = buildPrj.Configurations.item(\"TestProject - Win32 Debug\")") + xCrLf;
	code += _T("	config.AddToolSettings \"link.exe\", \"/libpath:\"\"..\\lib\"\"\"") + xCrLf;
	code += _T("	config.AddToolSettings \"link.exe\", \"") + libName + _T("\"") + xCrLf;
	code += xCrLf;	

	libName = prefix + _T("_DU.lib");
	code += _T("	set config = buildPrj.Configurations.item(\"TestProject - Win32 Debug Unicode\")") + xCrLf;
	code += _T("	config.AddToolSettings \"link.exe\", \"/libpath:\"\"..\\lib\"\"\"") + xCrLf;
	code += _T("	config.AddToolSettings \"link.exe\", \"") + libName + _T("\"") + xCrLf;
	code += xCrLf;	

	libName = prefix + _T("_R.lib");
	code += _T("	set config = buildPrj.Configurations.item(\"TestProject - Win32 Release\")") + xCrLf;
	code += _T("	config.AddToolSettings \"link.exe\", \"/libpath:\"\"..\\lib\"\"\"") + xCrLf;
	code += _T("	config.AddToolSettings \"link.exe\", \"") + libName + _T("\"") + xCrLf;
	code += xCrLf;	

	libName = prefix + _T("_RU.lib");
	code += _T("	set config = buildPrj.Configurations.item(\"TestProject - Win32 Release Unicode\")") + xCrLf;
	code += _T("	config.AddToolSettings \"link.exe\", \"/libpath:\"\"..\\lib\"\"\"") + xCrLf;
	code += _T("	config.AddToolSettings \"link.exe\", \"") + libName + _T("\"") + xCrLf;
	code += xCrLf;	

	/***
	code += _T("app.documents.open(\"") + testProjectName + _T("\")") + xCrLf;
	code += _T("app.visible = false") + xCrLf;
	code += _T("AddLibFile()") + xCrLf;
	code += _T("app.SaveAll") + xCrLf;
	code += _T("app.quit") + xCrLf;
	code += xCrLf;
	code += _T("Sub AddLibFile") + xCrLf;
	code += _T("	Dim projCol") + xCrLf;
	code += _T("	Dim configCol") + xCrLf;
	code += _T("	Dim numProjects") + xCrLf;
	code += _T("	Dim numConfigs") + xCrLf;
	code += _T("	Dim i") + xCrLf;
	code += _T("	Dim j") + xCrLf;
	code += xCrLf;	
	code += _T("	set projCol = app.Projects") + xCrLf;
	code += _T("	numProjects = projCol.Count") + xCrLf;
	code += xCrLf;	
	code += _T("	For i=1 To numProjects") + xCrLf;
	code += _T("		Dim proj") + xCrLf;
	code += _T("		set proj = projCol(i)") + xCrLf;
	code += xCrLf;		
	code += _T("		If proj.Type = \"Build\" Then") + xCrLf;
	code += xCrLf;	
	code += _T("			proj.AddFile (\"") + libName + _T("\")") + xCrLf;
	code += _T("		End If") + xCrLf;
	code += _T("	Next") + xCrLf;
	code += xCrLf;	
	***/
	code += _T("End Sub") + xCrLf;
	code += xCrLf;

	cmString scriptFileName;

	scriptFileName = genPath;
	scriptFileName += _T("\\");
	scriptFileName += prefix;
	scriptFileName += _T("\\testProject\\testProjectVc.vbs");
	
	SaveFile(scriptFileName, code, false);
	
	ShellExecute(NULL, _T("open"), scriptFileName, NULL, NULL, SW_HIDE);
}

void CCppGenerationManager::RunTestProject()
{
	enTestProjectAction actionId;

	actionId = cppSettings_->GetPostGenerationStep()->GetTestProjectActionId();
	if (actionId == enTestProjectAction_None ||
		actionId == enTestProjectAction_GenerateOnly ||
		!cppSettings_->GetTestPrjGenerationEnabled()) 
		return;

	cmString testProjectName;
	cmString prefix;
	cmString genPath;	

	listener_->OnNewTask(_T("Starting test project ..."));
	genPath = projectSettings_->GetCppSettings()->GetGenerationPath();
	prefix = projectSettings_->GetCppSettings()->GetClassPrefix();
	
	testProjectName = _T("\"") + genPath + _T("\\") + prefix + _T("\\testProject\\testProject.dsw\"");
	
	ShellExecute(NULL, _T("open"), _T("msdev.exe"), testProjectName, NULL, SW_NORMAL);
	listener_->OnTaskComplete(_T("Visual C++ (test project) started."));	
}

void CCppGenerationManager::CopyTestProjectFiles()
{
	cmString prefix;
	cmString genPath;	

	genPath = projectSettings_->GetCppSettings()->GetGenerationPath();
	prefix = projectSettings_->GetCppSettings()->GetClassPrefix();

	CopyDirectory(GetCurDirectory() + _T("\\templates\\testProject"), genPath + _T("\\") + prefix + _T("\\testProject"));
	CopyDirectory(GetCurDirectory() + _T("\\templates\\testProject\\res"), genPath + _T("\\") + prefix + _T("\\testProject\\res"));
	
	RunTestProjectScript();
}

void CCppGenerationManager::GenerateTestProjectDialog()
{
	cmString prefix;
	cmString genPath;	
	cmString fileName;
	cmString code;

	genPath = projectSettings_->GetCppSettings()->GetGenerationPath();
	prefix = projectSettings_->GetCppSettings()->GetClassPrefix();

	fileName = genPath + _T("\\") + prefix + _T("\\testProject\\TestProjectDlg.cpp");
	
	code += _T("// TestProjectDlg.cpp : implementation file") + xCrLf;
	code += _T("//") + xCrLf;
	code += xCrLf;
	code += _T("#include \"stdafx.h\"") + xCrLf;
	code += _T("#include \"TestProject.h\"") + xCrLf;
	code += _T("#include \"TestProjectDlg.h\"") + xCrLf;
	code += _T("#include \"") + prefix + _T("CfgManagerDlg.h\"") + xCrLf;
	code += xCrLf;
	code += _T("#ifdef _DEBUG") + xCrLf;
	code += _T("#define new DEBUG_NEW") + xCrLf;
	code += _T("#undef THIS_FILE") + xCrLf;
	code += _T("static char THIS_FILE[] = __FILE__;") + xCrLf;
	code += _T("#endif") + xCrLf;
	code += xCrLf;

	code += _T("/////////////////////////////////////////////////////////////////////////////") + xCrLf;
	code += _T("// CAboutDlg dialog used for App About") + xCrLf;

	code += _T("class CAboutDlg : public CDialog") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + _T("public:") + xCrLf;
	code += xTab + xTab + _T("CAboutDlg();") + xCrLf;
	code += xCrLf;

	code += xTab + _T("// Dialog Data") + xCrLf;
	code += xTab + _T("//{{AFX_DATA(CAboutDlg)") + xCrLf;
	code += xTab + xTab + _T("enum { IDD = IDD_ABOUTBOX };") + xCrLf;
	code += xTab + _T("//}}AFX_DATA") + xCrLf;
	code += xCrLf;
	code += xTab + _T("// ClassWizard generated virtual function overrides") + xCrLf;
	code += xTab + _T("//{{AFX_VIRTUAL(CAboutDlg)") + xCrLf;
	code += xTab + _T("protected:") + xCrLf;
	code += xTab + _T("virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support") + xCrLf;
	code += xTab + _T("//}}AFX_VIRTUAL") + xCrLf;
	code += xCrLf;
	code += xTab + _T("// Implementation") + xCrLf;
	code += xTab + _T("protected:") + xCrLf;
	code += xTab + _T("//{{AFX_MSG(CAboutDlg)") + xCrLf;
	code += xTab + xTab + _T("//}}AFX_MSG") + xCrLf;
	code += xTab + xTab + _T("DECLARE_MESSAGE_MAP()") + xCrLf;
	code += xTab + _T("};") + xCrLf;

	code += _T("CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + _T("//{{AFX_DATA_INIT(CAboutDlg)") + xCrLf;
	code += xTab + _T("//}}AFX_DATA_INIT") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	code += _T("void CAboutDlg::DoDataExchange(CDataExchange* pDX)") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + _T("CDialog::DoDataExchange(pDX);") + xCrLf;
	code += xTab + _T("//{{AFX_DATA_MAP(CAboutDlg)") + xCrLf;
	code += xTab + _T("//}}AFX_DATA_MAP") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	code += _T("BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)") + xCrLf;
	code += xTab + _T("//{{AFX_MSG_MAP(CAboutDlg)") + xCrLf;
	code += xTab + _T("// No message handlers") + xCrLf;
	code += xTab + _T("//}}AFX_MSG_MAP") + xCrLf;
	code += _T("END_MESSAGE_MAP()") + xCrLf;
	code += xCrLf;

	code += _T("/////////////////////////////////////////////////////////////////////////////") + xCrLf;
	code += _T("// CTestProjectDlg dialog") + xCrLf;
	code += xCrLf;
	code += _T("CTestProjectDlg::CTestProjectDlg(CWnd* pParent /*=NULL*/)") + xCrLf;
	code += xTab + _T(": CDialog(CTestProjectDlg::IDD, pParent)") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + _T("//{{AFX_DATA_INIT(CTestProjectDlg)") + xCrLf;
	code += xTab + xTab + _T("// NOTE: the ClassWizard will add member initialization here") + xCrLf;
	code += xTab + _T("//}}AFX_DATA_INIT") + xCrLf;
	code += xTab + _T("// Note that LoadIcon does not require a subsequent DestroyIcon in Win32") + xCrLf;
	code += xTab + _T("m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	code += _T("void CTestProjectDlg::DoDataExchange(CDataExchange* pDX)") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + _T("CDialog::DoDataExchange(pDX);") + xCrLf;
	code += xTab + _T("//{{AFX_DATA_MAP(CTestProjectDlg)") + xCrLf;
	code += xTab + xTab + _T("// NOTE: the ClassWizard will add DDX and DDV calls here") + xCrLf;
	code += xTab + _T("//}}AFX_DATA_MAP") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	code += _T("BEGIN_MESSAGE_MAP(CTestProjectDlg, CDialog)") + xCrLf;
	code += _T("//{{AFX_MSG_MAP(CTestProjectDlg)") + xCrLf;
	code += xTab + _T("ON_WM_SYSCOMMAND()") + xCrLf;
	code += xTab + _T("ON_WM_PAINT()") + xCrLf;
	code += xTab + _T("ON_WM_QUERYDRAGICON()") + xCrLf;
	code += xTab + _T("ON_BN_CLICKED(IDC_CMD_RUNTEST, OnCmdRuntest)") + xCrLf;
	code += _T("//}}AFX_MSG_MAP") + xCrLf;
	code += _T("END_MESSAGE_MAP()") + xCrLf;
	code += xCrLf;

	code += _T("/////////////////////////////////////////////////////////////////////////////") + xCrLf;
	code += _T("// CTestProjectDlg message handlers") + xCrLf;
	code += xCrLf;
	code += _T("BOOL CTestProjectDlg::OnInitDialog()") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + _T("CDialog::OnInitDialog();") + xCrLf;
	code += xCrLf;
	code += xTab + _T("// Add \"About...\" menu item to system menu.") + xCrLf;
	code += xCrLf;
	code += xTab + _T("// IDM_ABOUTBOX must be in the system command range.") + xCrLf;
	code += xTab + _T("ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX);") + xCrLf;
	code += xTab + _T("ASSERT(IDM_ABOUTBOX < 0xF000);") + xCrLf;
	code += xCrLf;
	code += xTab + _T("CMenu* pSysMenu = GetSystemMenu(FALSE);") + xCrLf;
	code += xTab + _T("if (pSysMenu != NULL)") + xCrLf;
	code += xTab + _T("{") + xCrLf;
	code += xTab + xTab + _T("CString strAboutMenu;") + xCrLf;
	code += xTab + xTab + _T("strAboutMenu.LoadString(IDS_ABOUTBOX);") + xCrLf;
	code += xTab + xTab + _T("if (!strAboutMenu.IsEmpty())") + xCrLf;
	code += xTab + xTab +_T("{") + xCrLf;
	code += xTab + xTab + xTab + _T("pSysMenu->AppendMenu(MF_SEPARATOR);") + xCrLf;
	code += xTab + xTab + xTab + _T("pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);") + xCrLf;
	code += xTab + xTab + _T("}") + xCrLf;
	code += xTab + _T("}") + xCrLf;
	code += xCrLf;
	code += xCrLf;
	code += xTab + _T("// Set the icon for this dialog.  The framework does this automatically") + xCrLf;
	code += xTab + _T("//  when the application's main window is not a dialog") + xCrLf;
	code += xTab + _T("SetIcon(m_hIcon, TRUE);			// Set big icon") + xCrLf;
	code += xTab + _T("SetIcon(m_hIcon, FALSE);		// Set small icon") + xCrLf;
	code += xCrLf;
	code += xTab + _T("// TODO: Add extra initialization here") + xCrLf;
	code += xCrLf;
	code += xTab + _T("return TRUE;  // return TRUE  unless you set the focus to a control") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	code += _T("void CTestProjectDlg::OnSysCommand(UINT nID, LPARAM lParam)") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + _T("if ((nID & 0xFFF0) == IDM_ABOUTBOX)") + xCrLf;
	code += xTab + _T("{") + xCrLf;
	code += xTab + xTab + _T("CAboutDlg dlgAbout;") + xCrLf;
	code += xTab + xTab + _T("dlgAbout.DoModal();") + xCrLf;
	code += xTab + _T("}") + xCrLf;
	code += xTab + _T("else") + xCrLf;
	code += xTab + _T("{") + xCrLf;
	code += xTab + xTab + _T("CDialog::OnSysCommand(nID, lParam);") + xCrLf;
	code += xTab + _T("}") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;
	code += _T("// If you add a minimize button to your dialog, you will need the code below") + xCrLf;
	code += _T("//  to draw the icon.  For MFC applications using the document/view model,") + xCrLf;
	code += _T("//  this is automatically done for you by the framework.") + xCrLf;
	code += xCrLf;

	code += _T("void CTestProjectDlg::OnPaint() ") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + _T("if (IsIconic())") + xCrLf;
	code += xTab + _T("{") + xCrLf;
	code += xTab + xTab + _T("CPaintDC dc(this); // device context for painting") + xCrLf;
	code += xCrLf;
	code += xTab + xTab + _T("SendMessage(WM_ICONERASEBKGND, (WPARAM) dc.GetSafeHdc(), 0);") + xCrLf;
	code += xCrLf;
	code += xTab + xTab + _T("// Center icon in client rectangle") + xCrLf;
	code += xTab + xTab + _T("int cxIcon = GetSystemMetrics(SM_CXICON);") + xCrLf;
	code += xTab + xTab + _T("int cyIcon = GetSystemMetrics(SM_CYICON);") + xCrLf;
	code += xTab + xTab + _T("CRect rect;") + xCrLf;
	code += xTab + xTab + _T("GetClientRect(&rect);") + xCrLf;
	code += xTab + xTab + _T("int x = (rect.Width() - cxIcon + 1) / 2;") + xCrLf;
	code += xTab + xTab +_T("int y = (rect.Height() - cyIcon + 1) / 2;") + xCrLf;
	code += xCrLf;
	code += xTab + xTab + _T("// Draw the icon") + xCrLf;
	code += xTab + xTab + _T("dc.DrawIcon(x, y, m_hIcon);") + xCrLf;
	code += xTab + _T("}") + xCrLf;
	code += xTab + _T("else") + xCrLf;
	code += xTab + _T("{") + xCrLf;
	code += xTab + xTab + _T("CDialog::OnPaint();") + xCrLf;
	code += xTab + _T("}") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;
	code += _T("// The system calls this to obtain the cursor to display while the user drags") + xCrLf;
	code += _T("//  the minimized window.") + xCrLf;
	code += _T("HCURSOR CTestProjectDlg::OnQueryDragIcon()") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + _T("return (HCURSOR) m_hIcon;") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;
	code += _T("void CTestProjectDlg::OnCmdRuntest() ") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + prefix + _T("CfgManagerDlg dlg;") + xCrLf;
	code += xTab + GetClassName(project_->GetRootElement()->GetName()) + _T(" t;") + xCrLf;
	code += xCrLf;
	code += xTab + _T("t.LoadFromXmlFile(_T(\"test.xml\"));") + xCrLf;
	code += xTab + _T("dlg.SetData(t);") + xCrLf;
	code += xTab + _T("if (dlg.DoModal() == IDOK) {") + xCrLf;
	code += xTab + xTab + _T("t = dlg.GetData();") + xCrLf;
	code += xTab + xTab + _T("t.SaveToXmlFile(_T(\"test.xml\"));") + xCrLf;
	code += xTab + _T("}") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	SaveFile(fileName, code, false);
}

void CCppGenerationManager::GeneratePostBuildFile(const cmString& fileName, 
												  const cmString& filePostfix,
												  const cmString& sourceFolder)
{
	cmString code;
	cmString tmp(sourceFolder);
	cmString prefix;
	cmString dllFileName;
	cmString libFileName;

	tmp.MakeUpper();
	prefix = cppSettings_->GetClassPrefix();
	dllFileName = prefix + filePostfix + _T(".dll");
	libFileName = prefix + filePostfix + _T(".lib");

	code = _T("");	

	// commands to copy files to general lib directory
	//
	code += _T("echo \"copying ") + tmp + _T(" lib and dll to main lib directory\"") + xCrLf;
	code += _T("copy \"") + sourceFolder + _T("\\") + dllFileName + _T("\" ..\\..\\lib\\") + dllFileName + xCrLf;
	code += _T("copy \"") + sourceFolder + _T("\\") + libFileName + _T("\" ..\\..\\lib\\") + libFileName + xCrLf;
	code += xCrLf;

	if (cppSettings_->GetPostBuildPath().GetLength()) {
		code += _T("echo \"copying ") + tmp + _T(" dll to project directory\"") + xCrLf;
		code += _T("copy \"") + sourceFolder + _T("\\") + dllFileName + _T("\" \"") + cppSettings_->GetPostBuildPath() + _T("\\") + prefix + filePostfix + _T(".dll\"") + xCrLf;
	}

	if (cppSettings_->GetTestPrjGenerationEnabled()) {
		code += _T("echo \"copying dll to test project directory\"") + xCrLf;
		code += _T("copy \"") + sourceFolder + _T("\\") + dllFileName + _T("\" \"..\\testProject\\") + prefix + filePostfix + _T(".dll\"") + xCrLf;
		code += xCrLf;
	}
	
	SaveFile(fileName, code, false);
}