// CAtlGenerationManager.cpp
//
#include "stdafx.h"
#include "AtlGenerationManager.h"
#include "AtlClassGenerator.h"
#include "AtlClassArrayGenerator.h"
#include "AtlClassMapGenerator.h"
#include "AtlClassDialogGenerator.h"
#include "AtlCatListDialogGenerator.h"
#include "AtlGridDialogGenerator.h"
#include "AtlMainDialogGenerator.h"
#include "AtlMainDialogWrapperGenerator.h"
#include "AtlResourceGenerator.h"
#include "AtlTreeNodeInfoGenerator.h"
#include "AtlArrayDialogGenerator.h"
#include "AtlMapDialogGenerator.h"
#include "XmlProject.h"
#include "XmlProjectSettings.h"
#include "XmlClassInfo.h"
#include "XmlMemberInfo.h"
#include "XmlMemberValidation_StaticEnum.h"
#include "XmlMemberValidation_StaticEnumItem.h"
#include "CPathSplit.h"
#include "IGeneratorListener.h"
#include "AtlComObjectGenerator.h"

CAtlGenerationManager::CAtlGenerationManager():
	project_(NULL)
{
}

CAtlGenerationManager::~CAtlGenerationManager()
{

}

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

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

	// store data
	//
	project_ = project;
	currentDirectory_ = currentDirectory;
	projectSettings_ = project_->GetProjectSettings();
	atlSettings_ = projectSettings_->GetAtlSettings();

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


	cppGeneratedFiles_.clear();
	hGeneratedFiles_.clear();

	// check settings
	//
	listener_->OnNewTask(_T("Checking settings ..."));
	if (atlSettings_->GetClassPrefix().GetLength() == 0) {
		listener_->OnTaskFailed(_T("Class prefix is empty."));
		return false;
	}
	if (atlSettings_->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 IDL & rgs files ..."));
	GenerateIdl(project_->GetRootElement());
	GenerateClassRgsFile(project_->GetRootElement());
	GenerateMainDialogRgsFile();
	listener_->OnTaskComplete(_T("IDL & rgs Generation complete"));
	
	listener_->OnNewTask(_T("Generating classes ..."));
	parentStack.clear();
	GenerateClass(project_->GetRootElement(), parentStack);
	parentStack.clear();
	GenerateClassContainer(project_->GetRootElement(), parentStack);
	listener_->OnTaskComplete(_T("Class generation complete"));

	GenerateMainModuleFile();

	//GenerateComClass(project_->GetRootElement());
	parentStack.clear();
	GenerateClassContainer(project_->GetRootElement(), parentStack);
	if (project_->GetProjectSettings()->GetAtlSettings()->GetGUIGenerationEnabled()) {
		GenerateGuiClass(project_->GetRootElement(), parentStack);
		GenerateGuiManager();
		GenerateGuiResources();
		GenerateGuiTreeNodeInfo();
	}

	GenerateResourceHFile();

	GenerateCppComponentsFile();

	CopyComponentsFiles();
	GenerateCppFileList();
	CopyDllProjectFiles();
	GenerateDefFiles();

	GenerateDllBatch();
	CopyFiles();

	CopyHeaders();

	if (atlSettings_->GetTestPrjGenerationEnabled()) {
		listener_->OnNewTask(_T("Generating test project ..."));
		GenerateTestProject();
		listener_->OnTaskComplete(_T("Test project generated"));
	}

	return true;
}

void CAtlGenerationManager::GenerateClass(CXmlClassInfo* classInfo, vector<CXmlClassInfo*> parentStack)
{
	if (classInfo->GetDataType() != enDataType_Class ||
		classInfo->GetDefinitionInheritance())
		return;
	
	// generates data-class
	//
	CAtlClassGenerator 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 CAtlGenerationManager::GenerateComClass(CXmlClassInfo* classInfo, vector<CXmlClassInfo*> parentStack)
{
	if (classInfo->GetDataType() != enDataType_Class ||
		classInfo->GetDefinitionInheritance())
		return;
	
	// generates data-class
	//
	CAtlComObjectGenerator 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)
			GenerateComClass(dynamic_cast<CXmlClassInfo*>(member), parentStack);
	}
}


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

	if (classInfo->GetRenderingMode() != enRenderingMode_None ||
		classInfo->GetLockedByInheritance()) {
	
		// generates dialog-class
		//
		CAtlClassDialogGenerator dlgGenerator;
		CAtlCatListDialogGenerator catListGenerator;
		CAtlGridDialogGenerator gridGenerator;
		CAtlArrayDialogGenerator arrayDialogGenerator;
		CAtlMapDialogGenerator 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);
				//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 CAtlGenerationManager::GenerateGuiManager()
{
	CAtlMainDialogGenerator generator;
	vector<CXmlClassInfo*> parentStack;

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

	CAtlMainDialogWrapperGenerator wrapperGenerator;

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

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

void CAtlGenerationManager::CreateFolders(CXmlProjectSettings* projectSettings)
{
	cmString dirName;
	cmString generationPath;
	cmString classPrefix;
	cmString sourcePath;
	cmString tmp;

	generationPath = atlSettings_->GetGenerationPath();
	classPrefix = atlSettings_->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\\XmlParser");
	CreateDirectory(dirName, NULL);

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

	dirName = sourcePath + _T("\\components\\XmlParser\\include");
	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 (atlSettings_->GetTestPrjGenerationEnabled()) {
		dirName = sourcePath + _T("\\testProject\\");
		CreateDirectory(dirName, NULL);	
	}
}

void CAtlGenerationManager::GenerateGuiResources()
{
	CAtlResourceGenerator generator;
	vector<CXmlClassInfo*> parentStack;

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

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

	generationPath = atlSettings_->GetGenerationPath();
	sourcePath = GetCurDirectory();
	destPath += generationPath + _T("\\") + atlSettings_->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);
	***/

	// copy XmlSerializable files
	//
	cmString sourceFileName;
	cmString destFileName;

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

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

	// copy cmString files
	//
	/***
	sourceFileName = sourcePath + _T("\\templates\\projectStorageAtl\\cmString.h");
	destFileName = destPath + _T("\\include\\cmString.h");
	::CopyFile(sourceFileName, destFileName, FALSE);
	
	sourceFileName = sourcePath + _T("\\templates\\projectStorageAtl\\cmString.h");
	destFileName = globalPath + _T("\\cmString.h");
	::CopyFile(sourceFileName, destFileName, FALSE);

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

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

	generationPath = atlSettings_->GetGenerationPath();
	sourcePath = GetCurDirectory();
	destPath += generationPath + _T("\\") + atlSettings_->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.atl"), destPath + _T("components\\common"));

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

	genPath = atlSettings_->GetGenerationPath();
	prefix = atlSettings_->GetClassPrefix();

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

	for (it = icons->begin(); it != icons->end(); it++) {
		icon = it->second;

		sourceFileName = icon->GetFileName();
		pathSplit.Split(sourceFileName);
		
		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 TCHAR*)pathSplit.GetFileName();
		destFileName += (const TCHAR*)pathSplit.GetExtension();

		CopyFile(sourceFileName, destFileName, FALSE);
	}	

	
}

void CAtlGenerationManager::CopySingleFile(const cmString& source, const cmString& destination)
{
	cmString fileSource;
	cmString fileDestination;
	cmString generationPath;
	
	generationPath = project_->GetProjectSettings()->GetAtlSettings()->GetGenerationPath();

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

	DWORD ret = ::CopyFile(fileSource, fileDestination, FALSE);
	 
	ret = ::GetLastError();
}

void CAtlGenerationManager::GenerateGuiTreeNodeInfo()
{
	CAtlTreeNodeInfoGenerator generator;

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

void CAtlGenerationManager::CopyDllProjectFiles()
{
	cmString destPath;

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

	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\ProjectConfigAtl.clw"), destPath + _T("project\\ProjectConfigAtl.clw"));
	//CopySingleFile("\\templates\\ProjectConfigAtl\\ProjectConfigAtl.cpp", destPath + "project\\ProjectConfigAtl.cpp"); -> now generated
	//CopySingleFile(_T("\\templates\\ProjectConfigAtl\\ProjectConfigAtl.def"), destPath + _T("project\\ProjectConfigAtl.def"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\ProjectConfigAtl.dsp"), destPath + _T("project\\ProjectConfigAtl.dsp"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\ProjectConfigAtl.dsw"), destPath + _T("project\\ProjectConfigAtl.dsw"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\ProjectConfigAtl.ncb"), destPath + _T("project\\ProjectConfigAtl.ncb"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\ProjectConfigAtl.opt"), destPath + _T("project\\ProjectConfigAtl.opt"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\ProjectConfigAtl.rc"), destPath + _T("project\\ProjectConfigAtl.rc"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\MainTreeCtrl.h"), destPath + _T("project\\MainTreeCtrl.h"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\MainTreeCtrl.cpp"), destPath + _T("project\\MainTreeCtrl.cpp"));
	//CopySingleFile("\\templates\\ProjectConfigAtl\\Resource.h", destPath + "project\\Resource.h");
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\StdAfx.cpp"), destPath + _T("project\\StdAfx.cpp"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\StdAfx.h"), destPath + _T("project\\StdAfx.h"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\IMainTreeCtrlListener.h"), destPath + _T("project\\IMainTreeCtrlListener.h"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\cmSplitDialog.h"), destPath + _T("project\\cmSplitDialog.h"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\cmSplitDialog.cpp"), destPath + _T("project\\cmSplitDialog.cpp"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\InputBox.h"), destPath + _T("project\\InputBox.h"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\InputBox.cpp"), destPath + _T("project\\InputBox.cpp"));

	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\res\\ProjectConfigDll.rc2"), destPath + _T("project\\res\\ProjectConfigDll.rc2"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\res\\icon1.ico"), destPath + _T("project\\res\\icon1.ico"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\res\\chkChecked.ico"), destPath + _T("project\\res\\chkChecked.ico"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\res\\chkUnchecked.ico"), destPath + _T("project\\res\\chkUnchecked.ico"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\res\\combobox_normal.bmp"), destPath + _T("project\\res\\combobox_normal.bmp"));
	CopySingleFile(_T("\\templates\\ProjectConfigAtl\\res\\combobox_over.bmp"), destPath + _T("project\\res\\combobox_over.bmp"));

}

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

	destPath = projectSettings_->GetAtlSettings()->GetGenerationPath() + _T("\\") + projectSettings_->GetAtlSettings()->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 CAtlGenerationManager::GenerateDllBatch()
{
	cmString code;
	cmString fileName;
	cmString genPath;
	cmString prefix;
	enGeneratorConfig configId;

	genPath = atlSettings_->GetGenerationPath();
	prefix = atlSettings_->GetClassPrefix();
	configId = atlSettings_->GetPostGenerationStep()->GetConfigId();
	
	// generate debug configuration post-build batch file
	//
	fileName = genPath + _T("\\") + prefix + _T("\\project\\postbuild_debug.bat");
	GeneratePostBuildFile(fileName, _T("debug"), _T("_D"));
	
	// generate debug unicode configuration post-build batch file
	//
	fileName = genPath + _T("\\") + prefix + _T("\\project\\postbuild_debug_unicode.bat");
	GeneratePostBuildFile(fileName, _T("debugU"), _T("_UD"));

	// generate release min dependency configuration post-build batch file
	//
	fileName = genPath + _T("\\") + prefix + _T("\\project\\postbuild_release_min_dep.bat");
	GeneratePostBuildFile(fileName, _T("releaseMinDependency"), _T("_R"));

	// generate release min size configuration post-build batch file
	//
	fileName = genPath + _T("\\") + prefix + _T("\\project\\postbuild_release_min_size.bat");
	GeneratePostBuildFile(fileName, _T("releaseMinSize"), _T("_R"));

	// generate release UNICODE min dependency configuration post-build batch file
	//
	fileName = genPath + _T("\\") + prefix + _T("\\project\\postbuild_release_unicode_min_dep.bat");
	GeneratePostBuildFile(fileName, _T("releaseUMinDependency"), _T("_RU"));

	// generate release UNICODE min size configuration post-build batch file
	//
	fileName = genPath + _T("\\") + prefix + _T("\\project\\postbuild_release_unicode_min_size.bat");
	GeneratePostBuildFile(fileName, _T("releaseUMinSize"), _T("_RU"));
}

void CAtlGenerationManager::CopyHeaders()
{
	map<cmString, cmString>::iterator it;
	cmString sourceFileName;
	cmString destinationFileName;
	cmString genPath;
	cmString prefix;

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

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

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

	::CopyFile(sourceFileName, destinationFileName, NULL);
}

/*
void CAtlGenerationManager::CompileLibrary()
{
	string dllProjectFileName;
	string script;
		
	dllProjectFileName = project_->GetProjectSettings()->GetAtlSettings()->GetGenerationPath();
	dllProjectFileName += "\\";
	dllProjectFileName += project_->GetProjectSettings()->GetAtlSettings()->GetClassPrefix();
	dllProjectFileName += "\\project\\ProjectConfigAtl.dsw";

	
	script = "dim app" + xCrLf;
	script += xCrLf;

	script += "on error resume next" + xCrLf;

	script += "set app = createobject(\"msdev.application\")" + xCrLf;

	script += "app.documents.open(\"" + dllProjectFileName + "\")" + xCrLf;
	script += "app.visible = true" + xCrLf;
	script += "app.rebuildall" + xCrLf;
	script += "app.quit" + xCrLf;
	script += "set app = nothing" + xCrLf;

	SaveFile("runAtlVc.vbs", script);
	
	ShellExecute(NULL, "open", "runAtlVc.vbs", NULL, NULL, SW_HIDE);
}
*/

void CAtlGenerationManager::GenerateIdl(CXmlClassInfo* rootClassInfo)
{
	cmString idlCode;
	cmString prefix;
	CXmlProjectSettings_Atl* atlSettings;

	atlSettings = projectSettings_->GetAtlSettings();
	prefix = atlSettings->GetClassPrefix();
	interfaceCode_ = _T("");
	coclassCode_ = _T("");
	idlEnumsCode_ = _T("");
	enums_.clear();
	GenerateIdlForwardDeclaration(rootClassInfo);
	GenerateClassIdl(rootClassInfo);
	GenerateMainDialogIdl();

	idlCode += _T("// ProjectConfigAtl.idl : IDL source for ProjectConfigAtl.dll") + xCrLf;
	idlCode += _T("//") + xCrLf;
	idlCode += xCrLf;
	idlCode += _T("// This file will be processed by the MIDL tool to") + xCrLf;
	idlCode += _T("// produce the type library (ProjectConfigAtl.tlb) and marshalling code.") + xCrLf;
	idlCode += xCrLf;
	idlCode += _T("import \"oaidl.idl\";") + xCrLf;
	idlCode += _T("import \"ocidl.idl\";") + xCrLf;
	idlCode += xCrLf;
	idlCode += idlEnumsCode_;
	idlCode += xCrLf;
	idlCode += interfaceCode_;
	idlCode += xCrLf;
	idlCode += _T("[") + xCrLf;
	idlCode += xTab + _T("uuid(") + GetTypeLibraryGuid() + _T("),") + xCrLf;
	idlCode += xTab + _T("version(1.0),") + xCrLf;
	idlCode += xTab + _T("helpstring(\"") + atlSettings->GetTypeLibraryName() + _T("\")") + xCrLf;
	idlCode += _T("]") + xCrLf;
	idlCode += _T("library ") + ToUpperCase(prefix) + _T("Lib") + xCrLf;
	idlCode += _T("{") + xCrLf;
	idlCode += xTab + _T("importlib(\"stdole32.tlb\");") + xCrLf;
	idlCode += xTab + _T("importlib(\"stdole2.tlb\");") + xCrLf;
	idlCode += coclassCode_;
	idlCode += _T("};") + xCrLf;
	idlCode += xCrLf;

	cmString fileName;
	cmString genPath;

	genPath = projectSettings_->GetAtlSettings()->GetGenerationPath();

	fileName = genPath + _T("\\") + prefix + _T("\\project\\ProjectConfigAtl.idl");

	SaveFile(fileName, idlCode, false);
}

void CAtlGenerationManager::GenerateClassIdl(CXmlClassInfo* classInfo)
{
	if (classInfo->GetDefinitionInheritance())
		return;
	
	//////////////////////////////////////////////////////////////
	// loop children: code generation of class declarations must be done in reverse order !!!
	//
	CXmlBaseElement* member;
	ClassMemberMap* members;
	ClassMemberMap::iterator it;
	
	members = classInfo->GetMembers();
	for (it = members->begin(); it != members->end(); it++) {
		member = it->second;
		if (member->GetDataType() == enDataType_Class)
			GenerateClassIdl(dynamic_cast<CXmlClassInfo*>(member));
	}

	// generate enums
	//
	for (it = members->begin(); it != members->end(); it++) {
		member = it->second;
		if (member->GetDataType() != enDataType_Class) {
			CXmlMemberInfo* memberInfo;

			memberInfo = dynamic_cast<CXmlMemberInfo*>(member);

			if (memberInfo->GetValidationInfo()->GetValidationMode() == enValidationMode_StaticEnum) {
				CXmlMemberValidation_StaticEnum* staticEnum;
				CXmlMemberValidation_StaticEnumItem* item;
				StaticEnumItems* items;
				cmString enumName;

				enumName = _T("en") + member->GetName();
				
				if (enums_.find(enumName) == enums_.end()) {
					enums_.insert(enumName);

					staticEnum = memberInfo->GetValidationInfo()->GetStaticEnum();
					
					items = staticEnum->GetItems();
					idlEnumsCode_ += xTab + _T("// enum for member \"") + member->GetName() + _T("\"") + xCrLf;
					idlEnumsCode_ += xTab + _T("//") + xCrLf;
					idlEnumsCode_ += xTab + _T("typedef enum ") + enumName  + _T(" {") + xCrLf;

					for (int i = 0; i < items->size(); i++) {
						cmString tmp;

						item = (*items)[i];
						tmp.Format(_T("%ld"), item->GetItemEnumValue());
						if (i != 0)
							idlEnumsCode_  += _T(",") + xCrLf;
						idlEnumsCode_ += xTab + xTab + enumName  + _T("_") + item->GetEscapedItemValue();
						idlEnumsCode_ += _T(" = ");
						idlEnumsCode_ += tmp;
						
					}
					idlEnumsCode_  += xCrLf;
					idlEnumsCode_  += xTab + _T("} ") + enumName + _T(";") + xCrLf;
				}
			}
			
		}
	}

	// class interface generation
	//
	interfaceCode_ += xTab + _T("// declare interface I") + GetClassName(classInfo->GetName()) + xCrLf;
	interfaceCode_ += xTab + _T("//") + xCrLf;
	interfaceCode_ += xTab + _T("[") + xCrLf;
	interfaceCode_ += xTab + xTab + _T("object,") + xCrLf;
	interfaceCode_ += xTab + xTab + _T("uuid(") + GetInterfaceGuid(classInfo) + _T("),") + xCrLf;
	interfaceCode_ += xTab + xTab + _T("dual,") + xCrLf;
	interfaceCode_ += xTab + xTab + _T("helpstring(\"I") + GetClassName(classInfo->GetName()) + _T(" Interface\"),") + xCrLf;
	interfaceCode_ += xTab + xTab + _T("pointer_default(unique)") + xCrLf;
	interfaceCode_ += xTab + _T("]") + xCrLf;
	interfaceCode_ += xTab + _T("interface I") + GetClassName(classInfo->GetName()) + _T(" : IDispatch") + xCrLf;
	interfaceCode_ += xTab + _T("{") + xCrLf;
	
	interfaceCode_ += xTab + xTab + _T("[id(1), helpstring(\"method Save\")] HRESULT Save([in] BSTR fileName, [out, retval] VARIANT_BOOL* retval);") + xCrLf;	
	interfaceCode_ += xTab + xTab + _T("[id(2), helpstring(\"method Load\")] HRESULT Load([in] BSTR fileName, [out, retval] VARIANT_BOOL* retval);") + xCrLf;
	interfaceCode_ += xTab + xTab + _T("[id(3), helpstring(\"method CleanUp\")] HRESULT CleanUp();") + xCrLf;
	interfaceCode_ += xTab + xTab + _T("[id(4), helpstring(\"method RestoreDefaults\")] HRESULT RestoreDefaults();") + xCrLf;
	interfaceCode_ += xTab + xTab + _T("[id(5), helpstring(\"method Copy\")] HRESULT Copy([in] I") + GetClassName(classInfo->GetName()) + _T("* source);") + xCrLf;
	
	// add properties
	//
	
	int i = 6;
	cmString num;
	cmString name;
	
	members = classInfo->GetMembers();
	for (it = members->begin(); it != members->end(); it++) {
		member = it->second;
		name = member->GetName();
		
		num.Format(_T("%d"), i);
		
		if (member->GetDataType() != enDataType_Class) {
			
			cmString typeStr;
			
			CXmlMemberInfo* memberInfo;

			memberInfo = dynamic_cast<CXmlMemberInfo*>(member);

			typeStr = IdlTypeOf(member->GetDataType());

			if (memberInfo->GetValidationInfo()->GetValidationMode() == enValidationMode_StaticEnum) {
				// propget for "value"
				//
				interfaceCode_ += xTab + xTab + _T("[propget, id(") + num + _T("), helpstring(\"property ") + name + _T("_Value\")]") + xCrLf;
				interfaceCode_ += xTab + xTab + xTab + _T("HRESULT ") + name + _T("_Value ([out, retval] ") + typeStr + _T(" *pVal);") + xCrLf;
				interfaceCode_ += xCrLf;

				i++;
				typeStr = _T("en") + member->GetName();
				num.Format(_T("%d"), i);
				
			} else {
				typeStr = IdlTypeOf(member->GetDataType());
			}

			// propget
			//
			interfaceCode_ += xTab + xTab + _T("[propget, id(") + num + _T("), helpstring(\"property ") + name + _T("\")]") + xCrLf;
			interfaceCode_ += xTab + xTab + xTab + _T("HRESULT ") + name + _T(" ([out, retval] ") + typeStr + _T(" *pVal);") + xCrLf;
			interfaceCode_ += xCrLf;
			
			// propput
			//
			interfaceCode_ += xTab + xTab + _T("[propput, id(") + num + _T("), helpstring(\"property ") + name + _T("\")]") + xCrLf;
			interfaceCode_ += xTab + xTab + xTab + _T("HRESULT ") + name + _T(" ([in] ") + typeStr + _T(" newVal);") + xCrLf;
			interfaceCode_ += xCrLf;

			
		} else {
			CXmlClassInfo* classMember;
			cmString p;
			
			classMember = dynamic_cast<CXmlClassInfo*>(member);
			if (classMember->GetDefinitionInheritance())
				classMember = dynamic_cast<CXmlClassInfo*>(project_->GetRootElement()->GetMemberById(classMember->GetInherithClassId()));
			
			p = GetCardinalityPostfix(classMember);
			name = classMember->GetName() + p;
			
			// propget
			//
			interfaceCode_ += xTab + xTab + _T("[propget, id(") + num + _T("), helpstring(\"property ") + name + _T("\")]") + xCrLf;
			interfaceCode_ += xTab + xTab + xTab + _T("HRESULT ") + name + _T(" ([out, retval] I") + GetClassName(classMember->GetName()) + p + _T(" **pVal);") + xCrLf;
			interfaceCode_ += xCrLf;
			
			// propput
			//
			interfaceCode_ += xTab + xTab + _T("[propput, id(") + num + _T("), helpstring(\"property ") + name + _T("\")]") + xCrLf;
			interfaceCode_ += xTab + xTab + xTab + _T("HRESULT ") + name + _T(" ([in] I") + GetClassName(classMember->GetName()) + p + _T("* newVal);") + xCrLf;
			interfaceCode_ += xCrLf;
		}

		i++;
	}

	interfaceCode_ += xTab + _T("};") + xCrLf;
	interfaceCode_ += xCrLf;

	// coclass generation
	//
	//coclassCode_ += xTab + "// declare coclass " + GetClassName(classInfo->GetName()) + xCrLf;
	coclassCode_ += xTab + _T("// declare coclass ") + classInfo->GetName() + xCrLf;
	coclassCode_ += xTab +_T("//") + xCrLf;
	coclassCode_ += xTab + _T("[") + xCrLf;
	coclassCode_ += xTab + xTab + _T("uuid(")+ GetClassGuid(classInfo) + _T("),") + xCrLf;
	//coclassCode_ += xTab + xTab + "helpstring(\"" + GetClassName(classInfo->GetName()) + " Class\")" + xCrLf;
	coclassCode_ += xTab + xTab + _T("helpstring(\"") + classInfo->GetName() + _T(" Class\")") + xCrLf;
	coclassCode_ += xTab + _T("]") + xCrLf;
	//coclassCode_ += xTab + "coclass " + GetClassName(classInfo->GetName()) + xCrLf;
	coclassCode_ += xTab + _T("coclass ") + classInfo->GetName() + xCrLf;
	coclassCode_ += xTab + _T("{") + xCrLf;
	coclassCode_ += xTab + xTab + _T("[default] interface I") + GetClassName(classInfo->GetName()) + _T(";") + xCrLf;
	coclassCode_ += xTab + _T("};") + xCrLf;
	coclassCode_ += xCrLf;

	//////////////////////////////////////////////////////////////
	// class container declarations (if map or array)
	//
	if (classInfo->GetCardinalityInfo()->GetCardinality() == enCardinality_SingleInstance)
		return;

	// class interface generation
	//
	cmString p;
	cmString guid;
	enCardinality c;
	

	c = classInfo->GetCardinalityInfo()->GetCardinality();
	p = GetCardinalityPostfix(classInfo);
	name = GetClassName(classInfo->GetName());

	interfaceCode_ += xTab + _T("// declare interface I") + GetClassName(classInfo->GetName()) + p + xCrLf;
	interfaceCode_ += xTab + _T("//") + xCrLf;
	interfaceCode_ += xTab + _T("[") + xCrLf;
	interfaceCode_ += xTab + xTab + _T("object,") + xCrLf;
	if (c == enCardinality_Map) {
		guid = classInfo->GetCardinalityInfo()->GetMapInterfaceGuid();
		if (guid == _T("")) {
			guid = CreateGuid();
			classInfo->GetCardinalityInfo()->SetMapInterfaceGuid(guid);
		}
	} else {
		guid = classInfo->GetCardinalityInfo()->GetArrayInterfaceGuid();
		if (guid == _T("")) {
			guid = CreateGuid();
			classInfo->GetCardinalityInfo()->SetArrayInterfaceGuid(guid);
		}
	}
	interfaceCode_ += xTab + xTab + _T("uuid(") + guid + _T("),") + xCrLf;

	interfaceCode_ += xTab + xTab + _T("dual,") + xCrLf;
	interfaceCode_ += xTab + xTab + _T("helpstring(\"I") + GetClassName(classInfo->GetName()) + p + _T(" Interface\"),") + xCrLf;
	interfaceCode_ += xTab + xTab + _T("pointer_default(unique)") + xCrLf;
	interfaceCode_ += xTab + _T("]") + xCrLf;
	interfaceCode_ += xTab + _T("interface I") + GetClassName(classInfo->GetName()) + p + _T(" : IDispatch") + xCrLf;
	interfaceCode_ += xTab + _T("{") + xCrLf;
	
	if (c == enCardinality_Map) {
		// add methods and properties
		//
		interfaceCode_ += xTab + xTab + _T("[id(1), helpstring(\"method CleanUp\")] HRESULT CleanUp();") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(2), helpstring(\"method RestoreDefaults\")] HRESULT RestoreDefaults();") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(3), helpstring(\"method MoveFirst\")] HRESULT MoveFirst([out, retval] VARIANT_BOOL* retval);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(4), helpstring(\"method MoveNext\")] HRESULT MoveNext([out, retval] VARIANT_BOOL* retval);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(5), helpstring(\"method GetPair\")] HRESULT GetPair([out] BSTR* key, [out] I") + name + _T("** item, [out, retval] VARIANT_BOOL* retval);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(6), helpstring(\"method GetSize\")] HRESULT GetSize([out, retval] long* retval);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(7), helpstring(\"method FindItem\")] HRESULT FindItem([in] BSTR key, [out, retval] I") + name + _T("** retval);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(8), helpstring(\"method Insert\")] HRESULT Insert([in] I") + name + _T("* item);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(9), helpstring(\"method Delete\")] HRESULT Delete([in] BSTR key);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(10), helpstring(\"method Save\")] HRESULT Save([in] BSTR fileName, [out, retval] VARIANT_BOOL* retval);") + xCrLf;	
		interfaceCode_ += xTab + xTab + _T("[id(11), helpstring(\"method Load\")] HRESULT Load([in] BSTR fileName, [out, retval] VARIANT_BOOL* retval);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(12), helpstring(\"method Copy\")] HRESULT Copy([in] I") + GetClassName(classInfo->GetName()) + p + _T("* source);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(13), helpstring(\"method ReplaceKey\")] HRESULT ReplaceKey([in] BSTR currentKey, [in] BSTR newKey);") + xCrLf;
	} else {
		interfaceCode_ += xTab + xTab + _T("[id(1), helpstring(\"method CleanUp\")] HRESULT CleanUp();") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(2), helpstring(\"method RestoreDefaults\")] HRESULT RestoreDefaults();") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(3), helpstring(\"method GetSize\")] HRESULT GetSize([out, retval] long* retval);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(4), helpstring(\"method GetItem\")] HRESULT GetItem([in] long index, [out, retval] I") + name + _T("** retval);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(5), helpstring(\"method Insert\")] HRESULT Insert([in] long index, [in] I") + name + _T("* item);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(6), helpstring(\"method Delete\")] HRESULT Delete([in] long index);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(7), helpstring(\"method Append\")] HRESULT Append([in] I") + name + _T("* item);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(8), helpstring(\"method Save\")] HRESULT Save([in] BSTR fileName, [out, retval] VARIANT_BOOL* retval);") + xCrLf;	
		interfaceCode_ += xTab + xTab + _T("[id(9), helpstring(\"method Load\")] HRESULT Load([in] BSTR fileName, [out, retval] VARIANT_BOOL* retval);") + xCrLf;
		interfaceCode_ += xTab + xTab + _T("[id(10), helpstring(\"method Copy\")] HRESULT Copy([in] I") + GetClassName(classInfo->GetName()) + p + _T("* source);") + xCrLf;
	}
	
	interfaceCode_ += xTab + _T("};") + xCrLf;
	interfaceCode_ += xCrLf;

	// coclass generation
	//
	//coclassCode_ += xTab + "// declare coclass " + GetClassName(classInfo->GetName()) + p + xCrLf;
	coclassCode_ += xTab + _T("// declare coclass ") + classInfo->GetName() + p + xCrLf;
	coclassCode_ += xTab + _T("//") + xCrLf;
	coclassCode_ += xTab + _T("[") + xCrLf;
	if (c == enCardinality_Map) {
		guid = classInfo->GetCardinalityInfo()->GetMapClassGuid();
		if (guid == _T("")) {
			guid = CreateGuid();
			classInfo->GetCardinalityInfo()->SetMapClassGuid(guid);
		}
	} else {
		guid = classInfo->GetCardinalityInfo()->GetArrayClassGuid();
		if (guid == _T("")) {
			guid = CreateGuid();
			classInfo->GetCardinalityInfo()->SetArrayClassGuid(guid);
		}
	}
	
	coclassCode_ += xTab + xTab + _T("uuid(") + guid + _T("),") + xCrLf;
	
	//coclassCode_ += xTab + xTab + "helpstring(\"" + GetClassName(classInfo->GetName()) + "p Class\")" + xCrLf;
	coclassCode_ += xTab + xTab + _T("helpstring(\"") + classInfo->GetName() + p + _T(" Class\")") + xCrLf;
	coclassCode_ += xTab + _T("]") + xCrLf;
	//coclassCode_ += xTab + "coclass " + GetClassName(classInfo->GetName()) + p + xCrLf;
	coclassCode_ += xTab + _T("coclass ") + classInfo->GetName() + p + xCrLf;
	coclassCode_ += xTab + _T("{") + xCrLf;
	coclassCode_ += xTab + xTab + _T("[default] interface I") + GetClassName(classInfo->GetName()) + p + _T(";") + xCrLf;
	coclassCode_ += xTab + _T("};") + xCrLf;
	coclassCode_ += xCrLf;

	
}

cmString CAtlGenerationManager::GetTypeLibraryGuid()
{
	cmString typeLibGuid;

	typeLibGuid = projectSettings_->GetAtlSettings()->GetTypeLibraryGuid();
	if (typeLibGuid == _T("")) {
		typeLibGuid = CreateGuid();
		projectSettings_->GetAtlSettings()->SetTypeLibraryGuid(typeLibGuid);
	}
	
	return typeLibGuid;
}

cmString CAtlGenerationManager::CreateGuid()
{
	GUID guid;
		
	CoInitialize(NULL);
	CoCreateGuid(&guid);
	CoUninitialize();

	TCHAR* str;

	UuidToString((UUID*)&guid, &str);
	cmString unique(str);

	RpcStringFree(&str);

	unique.MakeUpper();

	return unique;
}

cmString CAtlGenerationManager::GetInterfaceGuid(CXmlClassInfo* classInfo)
{
	cmString interfaceGuid;

	interfaceGuid = classInfo->GetAtlInterfaceGuid();
	if (interfaceGuid == _T("")) {
		interfaceGuid = CreateGuid();
		classInfo->SetAtlInterfaceGuid(interfaceGuid);
	}
	
	return interfaceGuid;
}

cmString CAtlGenerationManager::GetClassGuid(CXmlClassInfo* classInfo)
{
	cmString classGuid;

	classGuid = classInfo->GetAtlClassGuid();
	if (classGuid == _T("")) {
		classGuid = CreateGuid();
		classInfo->SetAtlClassGuid(classGuid);
	}
	
	return classGuid;
}

void CAtlGenerationManager::GenerateResourceHFile()
{
	cmString code;
	cmString prefix;
	cmString fileName;
	cmString genPath;
	int index;
	genPath = projectSettings_->GetAtlSettings()->GetGenerationPath();
	prefix = projectSettings_->GetAtlSettings()->GetClassPrefix();

	code += _T("//{{NO_DEPENDENCIES}}") + xCrLf;
	code += _T("// Microsoft Developer Studio generated include file.") + xCrLf;
	code += _T("// Used by ATLPrj1.rc") + xCrLf;
	code += _T("//") + xCrLf;
	code += _T("#define ___LIB___NAME___ LIBID_") + ToUpperCase(prefix) + _T("Lib") + xCrLf; 
	if (atlSettings_->GetGUIGenerationEnabled()) {
		code += _T("#include \"TreeIcons.h\"") + xCrLf;
	}
	code += xCrLf;
	code += _T("#define IDS_PROJNAME                    100") + xCrLf;
	code += _T("#define IDR_MAINDIALOG	                 101") + xCrLf;
	
	index = 102;
	GenerateClassResource(code, index, project_->GetRootElement());
	
	code += xCrLf;
	code += _T("#define IDD_SPLITTERDLG                 1000") + xCrLf;
	code += _T("#define IDC_TXT_VALUE                   1000") + xCrLf;
	code += _T("#define IDD_CFG_TEMPLATE                1001") + xCrLf;
	code += _T("#define IDC_LBL_CAPTION                 1001") + xCrLf;
	code += _T("#define IDR_MNU_EDIT_ARRAY              1002") + xCrLf;
	code += _T("#define IDR_MNU_EDIT_ARRAY_ITEM         1003") + xCrLf;
	code += _T("#define IDR_MNU_EDIT_MAP                1004") + xCrLf;
	code += _T("#define IDR_MNU_EDIT_MAP_ITEM           1005") + xCrLf;
	code += _T("#define IDI_EMPTY                       1006") + xCrLf;
	code += _T("#define IDI_CHK_CHECKED                 1007") + xCrLf;
	code += _T("#define IDB_COMBO_BOX_OVER              1007") + xCrLf;
	code += _T("#define IDI_CHK_UNCHECKED               1008") + xCrLf;
	code += _T("#define IDB_COMBO_BOX_NORMAL            1008") + xCrLf;
	code += _T("#define IDD_INPUT_BOX                   1009") + xCrLf;
	code += _T("#define IDD_CONTAINER_TEMPLATE			 1010") + xCrLf;
	code += _T("#define IDC_CMD_INSERT                  1011") + xCrLf;
	code += _T("#define IDC_CMD_DELETE                  1012") + xCrLf;
	code += _T("#define IDC_CMD_APPEND                  1013") + xCrLf;
	code += _T("#define IDC_CMD_EDIT                    1014") + xCrLf;
	code += _T("#define IDC_ITEMLIST                    1015") + xCrLf;
	code += _T("#define ID_EDITARRAY_APPENDITEM         32771") + xCrLf;
	code += _T("#define ID_EDITARRAYITEM_INSERTITEM     32773") + xCrLf;
	code += _T("#define ID_EDITARRAYITEM_APPENDITEM     32774") + xCrLf;
	code += _T("#define ID_EDITARRAYITEM_REMOVEITEM     32775") + xCrLf;
	code += _T("#define ID_EDITMAP_CREATEITEM           32776") + xCrLf;
	code += _T("#define ID_EDITMAPITEM_REMOVEITEM       32777") + xCrLf;
	code += _T("#define ID_EDITMAPITEM_CREATEITEM       32778") + xCrLf;
	code += _T("#define IDC_TREE                        32779") + xCrLf;
	code += xCrLf;
	code += _T("// Next default values for new objects") + xCrLf;
	code += _T("// ") + xCrLf;
	code += _T("#ifdef APSTUDIO_INVOKED") + xCrLf;
	code += _T("#ifndef APSTUDIO_READONLY_SYMBOLS") + xCrLf;
	code += _T("#define _APS_NEXT_RESOURCE_VALUE        1016") + xCrLf;
	code += _T("#define _APS_NEXT_COMMAND_VALUE         3280") + xCrLf;
	code += _T("#define _APS_NEXT_CONTROL_VALUE         1002") + xCrLf;
	code += _T("#define _APS_NEXT_SYMED_VALUE           1000") + xCrLf;
	code += _T("#endif") + xCrLf;
	code += _T("#endif") + xCrLf;
	code += xCrLf;

	fileName = genPath + _T("\\") + prefix + _T("\\project\\resource.h");

	SaveFile(fileName, code, false);
}

void CAtlGenerationManager::GenerateClassResource(cmString& code, int& index, CXmlClassInfo* classInfo)
{
	TCHAR buf[10];
	cmString line;

	wsprintf(buf, _T(" %d\n"), index);
	index++;

	line = _T("#define IDR_") + ToUpperCase(classInfo->GetName());

	if (line.GetLength() < 30) {
		for (int i = line.GetLength(); i < 30; i++)
			line += _T(" ");
	}

	line += buf;
	code += line;

	if (classInfo->GetCardinalityInfo()->GetCardinality() != enCardinality_SingleInstance){
		wsprintf(buf, _T(" %d\n"), index);
		index++;

		line = _T("#define IDR_") + ToUpperCase(classInfo->GetName() + GetCardinalityPostfix(classInfo));

		if (line.GetLength() < 30) {
			for (int i = line.GetLength(); i < 30; i++)
				line += _T(" ");
		}

		line += buf;
		code += line;

	}


	// generate children resources id
	//
	ClassMemberMap* members;
	ClassMemberMap::iterator it;
	CXmlBaseElement* member;

	members = classInfo->GetMembers();
	for (it = members->begin(); it != members->end(); it++) {
		member = it->second;
		if (member->GetDataType() == enDataType_Class) {
			CXmlClassInfo* tmp;

			tmp = dynamic_cast<CXmlClassInfo*>(member);

			GenerateClassResource(code, index, tmp);
		}
	}
}

void CAtlGenerationManager::GenerateMainDialogIdl()
{
	cmString guid;
	cmString name;
	cmString prefix;
	cmString rootClassName;

	rootClassName = GetClassName(project_->GetRootElement()->GetName());

	guid = atlSettings_->GetMainDialogInterfaceGuid();
	if (guid == _T("")) {
		guid = CreateGuid();
		atlSettings_->SetMainDialogInterfaceGuid(guid);
	}

	prefix = atlSettings_->GetClassPrefix();
	name = prefix + _T("MainDialog");

	// interface declaration
	//
	interfaceCode_ += _T("// declare interface I") + name + xCrLf;
    interfaceCode_ += _T("//") + xCrLf;
    interfaceCode_ += _T("[") + xCrLf;
    interfaceCode_ += _T("    object,") + xCrLf;
    interfaceCode_ += _T("    uuid(") + guid + _T("),") + xCrLf;
    interfaceCode_ += _T("    dual,") + xCrLf;
    interfaceCode_ += _T("    helpstring(\"I") + name + _T(" Interface\"),") + xCrLf;
    interfaceCode_ += _T("    pointer_default(unique)") + xCrLf;
    interfaceCode_ += _T("]") + xCrLf;
    interfaceCode_ += _T("interface I") + name + _T(" : IDispatch") + xCrLf;
    interfaceCode_ += _T("{") + xCrLf;
    //interfaceCode_ += "    [id(1), helpstring(\"method GetData\")] HRESULT GetData([out, retval] I" + rootClassName + "** retval);" + xCrLf;
    //interfaceCode_ += "    [id(2), helpstring(\"method SetData\")] HRESULT SetData([in] I" + rootClassName + "* data);" + xCrLf;
    interfaceCode_ += _T("    [id(1), helpstring(\"method Display\")] HRESULT Display([in] I") + rootClassName + _T("* data, [out, retval] VARIANT_BOOL* retval);") + xCrLf;
    interfaceCode_ += _T("};") + xCrLf;
	interfaceCode_ += xCrLf;


	// coclass declaration
	//
	name = _T("MainDialog");

	coclassCode_ += xTab + _T("// declare coclass ") + name + xCrLf;
	coclassCode_ += xTab + _T("//") + xCrLf;
	coclassCode_ += xTab + _T("[") + xCrLf;
	
	guid = atlSettings_->GetMainDialogClassGuid();
	if (guid == _T("")) {
		guid = CreateGuid();
		atlSettings_->SetMainDialogClassGuid(guid);
	}
	
	coclassCode_ += xTab + xTab + _T("uuid(") + guid + _T("),") + xCrLf;
	
	coclassCode_ += xTab + xTab + _T("helpstring(\"Main Dialog ") + name + _T(" Class\")") + xCrLf;
	coclassCode_ += xTab + _T("]") + xCrLf;
	coclassCode_ += xTab + _T("coclass ") + name + xCrLf;
	coclassCode_ += xTab + _T("{") + xCrLf;
	coclassCode_ += xTab + xTab + _T("[default] interface I") + prefix + name + _T(";") + xCrLf;
	coclassCode_ += xTab + _T("};") + xCrLf;
	coclassCode_ += xCrLf;
}

void CAtlGenerationManager::GenerateClassRgsFile(CXmlClassInfo* classInfo)
{
	if (classInfo->GetDefinitionInheritance())
		return;

	cmString code;
	cmString guid;
	cmString className;
	cmString progId;
	cmString prefix;
	cmString fileName;
	cmString genPath;

	guid = classInfo->GetAtlClassGuid();
	if (guid == _T("")) {
		guid = CreateGuid();
		classInfo->SetAtlClassGuid(guid);
	}
	className = classInfo->GetName();
	prefix = atlSettings_->GetClassPrefix();
	progId = prefix + _T(".") + className;

	GenerateRgsFile(progId, className, guid);

	if (classInfo->GetCardinalityInfo()->GetCardinality() != enCardinality_SingleInstance) {
		cmString p;		

		p = GetCardinalityPostfix(classInfo);
		className = classInfo->GetName() + p;
		prefix = atlSettings_->GetClassPrefix();
		
		if (classInfo->GetCardinalityInfo()->GetCardinality() == enCardinality_Map) {
			guid = classInfo->GetCardinalityInfo()->GetMapClassGuid();
			if (guid == _T("")) {
				guid = CreateGuid();
				classInfo->GetCardinalityInfo()->SetMapClassGuid(guid);
			}
		} else {
			guid = classInfo->GetCardinalityInfo()->GetArrayClassGuid();
			if (guid == _T("")) {
				guid = CreateGuid();
				classInfo->GetCardinalityInfo()->SetArrayClassGuid(guid);
			}
		}

		progId = prefix + _T(".") + className;

		GenerateRgsFile(progId, className, guid);
	}

	ClassMemberMap* members;
	ClassMemberMap::iterator it;
	CXmlBaseElement* element;

	members = classInfo->GetMembers();
	for (it = members->begin(); it != members->end(); it++) {
		element = it->second;
		
		if (element->GetDataType() == enDataType_Class)
			GenerateClassRgsFile(dynamic_cast<CXmlClassInfo*>(element));
	}

}

void CAtlGenerationManager::GenerateMainModuleFile()
{
//////////////////////////////////////////////////////
	cmString code;

	code += _T("// ProjectConfigAtl.cpp : Implementation of DLL Exports.") + xCrLf;
	code += xCrLf;

	code += _T("// Note: Proxy/Stub Information") + xCrLf;
	code += _T("//      To build a separate proxy/stub DLL, ") + xCrLf;
	code += _T("//      run nmake -f ProjectConfigAtlps.mk in the project directory.") + xCrLf;
	code += xCrLf;
	code += _T("#include \"stdafx.h\"") + xCrLf;
	code += _T("#include \"resource.h\"") + xCrLf;
	code += _T("#include <initguid.h>") + xCrLf;
	code += _T("#include \"ProjectConfigAtl.h\"") + xCrLf;
	code += _T("#include \"ProjectConfigAtl_i.c\"") + xCrLf;
	code += _T("#include \"") + atlSettings_->GetClassPrefix() + _T("MainDialog.h\"") + xCrLf;
	code += xCrLf;

	code += _T("CComModule _Module;") + xCrLf;
	code += xCrLf;

	code += _T("BEGIN_OBJECT_MAP(ObjectMap)") + xCrLf;
	code += xTab + _T("OBJECT_ENTRY(CLSID_MainDialog, ") + atlSettings_->GetClassPrefix() + _T("MainDialog)") + xCrLf;
	GenerateObjectMapEntry(project_->GetRootElement(), code);
	code += _T("END_OBJECT_MAP()") + xCrLf;

	code += _T("class CProjectConfigAtlApp : public CWinApp") + xCrLf;
	code += _T("{") + xCrLf;
	code += _T("public:") + xCrLf;
	code += xCrLf;

	code += _T("// Overrides") + xCrLf;
	code += xTab + _T("// ClassWizard generated virtual function overrides") + xCrLf;
	code += xTab + _T("//{{AFX_VIRTUAL(CProjectConfigAtlApp)") + xCrLf;
	code += xTab + _T("public:")+ xCrLf;
    code += xTab + _T("virtual BOOL InitInstance();") + xCrLf;
    code += xTab + _T("virtual int ExitInstance();") + xCrLf;
	code += xTab + _T("//}}AFX_VIRTUAL") + xCrLf;
	code += xCrLf;

	code += xTab + _T("//{{AFX_MSG(CProjectConfigAtlApp)") + xCrLf;
	code += xTab + xTab + _T("// NOTE - the ClassWizard will add and remove member functions here.") + xCrLf;
	code += xTab + xTab + _T("//    DO NOT EDIT what you see in these blocks of generated code !") + xCrLf;
	code += xTab + _T("//}}AFX_MSG") + xCrLf;
	code += xTab + _T("DECLARE_MESSAGE_MAP()") + xCrLf;
	code += _T("};") + xCrLf;
	code += xCrLf;
	code += _T("BEGIN_MESSAGE_MAP(CProjectConfigAtlApp, CWinApp)") + xCrLf;
	code += _T("//{{AFX_MSG_MAP(CProjectConfigAtlApp)") + xCrLf;
	code += xTab + _T("// NOTE - the ClassWizard will add and remove mapping macros here.") + xCrLf;
	code += xTab + xTab + _T("//    DO NOT EDIT what you see in these blocks of generated code!") + xCrLf;
	code += _T("//}}AFX_MSG_MAP") + xCrLf;
	code += _T("END_MESSAGE_MAP()") + xCrLf;
	code += xCrLf;
	
	code += _T("CProjectConfigAtlApp theApp;") + xCrLf;
	code += xCrLf;

	code += _T("BOOL CProjectConfigAtlApp::InitInstance()") + xCrLf;
	code += _T("{") + xCrLf;
    code += xTab + _T("_Module.Init(ObjectMap, m_hInstance, &LIBID_") + ToUpperCase(atlSettings_->GetClassPrefix()) + _T("Lib);") + xCrLf;
    code += xTab + _T("return CWinApp::InitInstance();") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	code += _T("int CProjectConfigAtlApp::ExitInstance()") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + _T("_Module.Term();") + xCrLf;
	code += xTab + _T("return CWinApp::ExitInstance();") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	code += _T("/////////////////////////////////////////////////////////////////////////////") + xCrLf;
	code += _T("// Used to determine whether the DLL can be unloaded by OLE") + xCrLf;
	code += xCrLf;

	code += _T("STDAPI DllCanUnloadNow(void)") + xCrLf;
	code += _T("{") + xCrLf;
    code += xTab + _T("AFX_MANAGE_STATE(AfxGetStaticModuleState());") + xCrLf;
    code += xTab + _T("return (AfxDllCanUnloadNow()==S_OK && _Module.GetLockCount()==0) ? S_OK : S_FALSE;") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	code += _T("/////////////////////////////////////////////////////////////////////////////") + xCrLf;
	code += _T("// Returns a class factory to create an object of the requested type") + xCrLf;
	code += xCrLf;
	code += _T("STDAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, LPVOID* ppv)") + xCrLf;
	code += _T("{") + xCrLf;
    code += xTab + _T("return _Module.GetClassObject(rclsid, riid, ppv);") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	code += _T("/////////////////////////////////////////////////////////////////////////////") + xCrLf;
	code += _T("// DllRegisterServer - Adds entries to the system registry") + xCrLf;
	code += xCrLf;
	code += _T("STDAPI DllRegisterServer(void)") + xCrLf;
	code += _T("{") + xCrLf;
    code += xTab + _T("// registers object, typelib and all interfaces in typelib") + xCrLf;
    code += xTab + _T("return _Module.RegisterServer(TRUE);") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	code += _T("/////////////////////////////////////////////////////////////////////////////") + xCrLf;
	code += _T("// DllUnregisterServer - Removes entries from the system registry") + xCrLf;
	code += xCrLf;
	code += _T("STDAPI DllUnregisterServer(void)") + xCrLf;
	code += _T("{") + xCrLf;
    code += xTab + _T("return _Module.UnregisterServer(TRUE);") + xCrLf;
	code += _T("}") + xCrLf;
	code += xCrLf;

	cmString genPath;
	cmString fileName;

	genPath = atlSettings_->GetGenerationPath();
	fileName = genPath + _T("\\") + atlSettings_->GetClassPrefix() + _T("\\project\\ProjectConfigAtl.cpp");

	SaveFile(fileName, code, false);

}

void CAtlGenerationManager::GenerateObjectMapEntry(CXmlClassInfo* classInfo, cmString& code)
{
	if (classInfo->GetDefinitionInheritance())
		return;

	cmString className;
	cmString p;

	className = GetClassName(classInfo->GetName());
	p = GetCardinalityPostfix(classInfo);

	code += xTab + _T("OBJECT_ENTRY(CLSID_") + classInfo->GetName()+ _T(", ") + className + _T(")") + xCrLf;
	
	if (classInfo->GetCardinalityInfo()->GetCardinality() != enCardinality_SingleInstance)
		code += xTab + _T("OBJECT_ENTRY(CLSID_") + classInfo->GetName() + p + _T(", ") + className + p + _T(")") + xCrLf;
	
	ClassMemberMap* members;
	ClassMemberMap::iterator it;
	CXmlBaseElement* member;

	members = classInfo->GetMembers();
	for (it = members->begin(); it != members->end(); it++) {
		member = it->second;
		if (member->GetDataType() == enDataType_Class)
			GenerateObjectMapEntry(dynamic_cast<CXmlClassInfo*>(member), code);
	}
}

void CAtlGenerationManager::GenerateRgsFile(const cmString& progId, const cmString& className, const cmString& guid)
{
	cmString code;
	cmString genPath;
	cmString fileName;
	cmString prefix;

	code = _T("");
	code += _T("HKCR") + xCrLf;
	code += _T("{") + xCrLf;
	code += xTab + progId + _T(".1 = s '") + className + _T(" Class'") + xCrLf;
	code += xTab + _T("{") + xCrLf;
	code += xTab + xTab +  _T("CLSID = s '{") + guid + _T("}'") + xCrLf;
	code += xTab + _T("}") + xCrLf;
	code += xTab + progId + _T(" = s '") +  className + _T(" Class'") + xCrLf;
	code += xTab + _T("{") + xCrLf;
	code += xTab + xTab + _T("CLSID = s '{") + guid + _T("}'") + xCrLf;
	code += xTab + xTab + _T("CurVer = s '") + progId + _T(".1'") + xCrLf;
	code += xTab + _T("}") + xCrLf;
	code += xTab + _T("NoRemove CLSID") + xCrLf;
	code += xTab + _T("{") + xCrLf;
	code += xTab + xTab + _T("ForceRemove {") + guid + _T("} = s '") + className + _T(" Class'") + xCrLf;
	code += xTab + xTab + _T("{") + xCrLf;
	code += xTab + xTab + xTab + _T("ProgID = s '") + progId + _T(".1'") + xCrLf;
	code += xTab + xTab + xTab + _T("VersionIndependentProgID = s '") + progId + _T("'") + xCrLf;
	code += xTab + xTab + xTab + _T("ForceRemove 'Programmable'") + xCrLf;
	code += xTab + xTab + xTab + _T("InprocServer32 = s '%MODULE%'") + xCrLf;
	code += xTab + xTab + xTab + _T("{") + xCrLf;
	code += xTab + xTab + xTab + xTab + _T("val ThreadingModel = s 'Apartment'") + xCrLf;
	code += xTab + xTab + xTab + _T("}") + xCrLf;
	code += xTab + xTab + xTab + _T("'TypeLib' = s '{") + atlSettings_->GetTypeLibraryName() + _T("}'") + xCrLf;
	code += xTab + xTab + _T("}") + xCrLf;
	code += xTab + _T("}") + xCrLf;
	code += _T("}") + xCrLf;

	genPath = atlSettings_->GetGenerationPath();
	prefix = atlSettings_->GetClassPrefix();
	fileName = genPath +_T("\\") + prefix + _T("\\project\\") + className + _T(".rgs");

	SaveFile(fileName, code, false);	
}

void CAtlGenerationManager::GenerateMainDialogRgsFile()
{
	cmString progId;
	cmString prefix;
	cmString guid;

	guid = atlSettings_->GetMainDialogClassGuid();
	if (guid == _T("")) {
		guid = CreateGuid();
		atlSettings_->SetMainDialogClassGuid(guid);
	}

	prefix = atlSettings_->GetClassPrefix();
	progId = prefix + _T(".MainDialog");

	GenerateRgsFile(progId, _T("MainDialog"), guid);
}

void CAtlGenerationManager::GenerateIdlForwardDeclaration(CXmlClassInfo* classInfo)
{
	if (classInfo->GetDefinitionInheritance())
		return;

	ClassMemberMap* members;
	ClassMemberMap::iterator it;
	CXmlBaseElement* element;
	
	members = classInfo->GetMembers();
	for (it = members->begin(); it != members->end(); it++) {
		element = it->second;
		if (element->GetDataType() == enDataType_Class)
			GenerateIdlForwardDeclaration(dynamic_cast<CXmlClassInfo*>(element));
	}

	
	interfaceCode_ += _T("interface I") + GetClassName(classInfo->GetName()) + _T(";") + xCrLf;
	if (classInfo->GetCardinalityInfo()->GetCardinality() != enCardinality_SingleInstance)
		interfaceCode_ += _T("interface I") + GetClassName(classInfo->GetName()) + GetCardinalityPostfix(classInfo) + _T(";") + xCrLf;
}

void CAtlGenerationManager::GenerateClassContainer(CXmlClassInfo* classInfo, vector<CXmlClassInfo*> parentStack)
{
	if (classInfo->GetDataType() != enDataType_Class ||
		classInfo->GetDefinitionInheritance())
		return;
	
	// generates data-class-container
	//
	if (classInfo->GetCardinalityInfo()->GetCardinality() == enCardinality_Array) {
		CAtlClassArrayGenerator generator;
		
		generator.SetClassInfo(classInfo, parentStack);
		generator.SetProject(project_);
		generator.Generate();
	} else if (classInfo->GetCardinalityInfo()->GetCardinality() == enCardinality_Map) {
		CAtlClassMapGenerator 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 CAtlGenerationManager::RunCompiler()
{
	enGeneratorAction actionId;
	enGeneratorConfig configId;

	actionId = atlSettings_->GetPostGenerationStep()->GetActionId();
	if (actionId == enGeneratorAction_None)
		return;

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

	genPath = atlSettings_->GetGenerationPath();
	prefix = atlSettings_->GetClassPrefix();
	if (atlSettings_->GetPostBuildPath() != _T(""))
		dllPrefix = atlSettings_->GetPostBuildPath() + _T("\\");
	else
		dllPrefix = _T("..\\lib\\");

	if (atlSettings_->GetDllFileNamePrefix() != _T(""))
		dllPrefix += atlSettings_->GetDllFileNamePrefix();
	else
		dllPrefix += atlSettings_->GetClassPrefix();

	dllProjectFileName = atlSettings_->GetGenerationPath();
	dllProjectFileName += _T("\\");
	dllProjectFileName += atlSettings_->GetClassPrefix();
	dllProjectFileName += _T("\\project\\ProjectConfigAtl.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 += _T("set app = createobject(\"msdev.application\")") + 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;
	configId = atlSettings_->GetPostGenerationStep()->GetConfigId();
	
	script += _T("set cfg = prj.configurations.item(\"ProjectConfigAtl - Win32 Debug\")") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/out:\"\"") + dllPrefix + _T("_D.dll\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/def:\"\"") + prefix + _T("_D.def\"\"\"") + xCrLf;
	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_Debug) && 
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += xCrLf;
		
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;
	}

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

	script += _T("set cfg = prj.configurations.item(\"ProjectConfigAtl - Win32 Release MinDependency\")") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/out:\"\"") + dllPrefix + _T("_RU.dll\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/def:\"\"") + prefix + _T("_RU.def\"\"\"") + xCrLf;
	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_ReleaseMinDependency) &&
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += xCrLf;
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;
	}
	
	script += _T("set cfg = prj.configurations.item(\"ProjectConfigAtl - Win32 Unicode Release MinDependency\")") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/out:\"\"") + dllPrefix + _T("_RU.dll\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/def:\"\"") + prefix + _T("_RU.def\"\"\"") + xCrLf;
	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_UnicodeReleaseMinDependency) &&
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += xCrLf;
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;
	}

	script += _T("set cfg = prj.configurations.item(\"ProjectConfigAtl - Win32 Release MinSize\")") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/out:\"\"") + dllPrefix + _T("_R.dll\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/def:\"\"") + prefix + _T("_R.def\"\"\"") + xCrLf;
	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_ReleaseMinSize) &&
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += xCrLf;
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + xCrLf;
	}
	
	script += _T("set cfg = prj.configurations.item(\"ProjectConfigAtl - Win32 Unicode Release MinSize\")") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/out:\"\"..\\lib\\") + dllPrefix + _T("_RU.dll\"\"\"") + xCrLf;
	script += _T("cfg.AddToolSettings \"link.exe\", \"/def:\"\"") + prefix + _T("_RU.def\"\"\"") + xCrLf;
	if ((configId == enGeneratorConfig_All || configId == enGeneratorConfig_UnicodeReleaseMinSize) &&
		actionId == enGeneratorAction_GenerateAndCompile) {
		script += xCrLf;
		script += _T("app.clean cfg") + xCrLf;
		script += _T("app.build cfg") + 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\\runAtl.vbs");
	SaveFile(scriptFileName, script, false);
	
	ShellExecute(NULL, _T("open"), scriptFileName, NULL, NULL, SW_HIDE);

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

void CAtlGenerationManager::GenerateTestProject()
{
	cmString code;
	cmString testProjectName;
	cmString mainFormName;
	cmString libName;
	cmString prefix;
	cmString genPath;	

	genPath = atlSettings_->GetGenerationPath();
	prefix = atlSettings_->GetClassPrefix();
	
	// vbp file generation (for DEBUG version)
	//
	code += _T("Type=Exe") + xCrLf;
	code += _T("Reference=*\\G{00020430-0000-0000-C000-000000000046}#2.0#0#C:\\WINDOWS\\System32\\stdole2.tlb#OLE Automation")+ xCrLf;
	code += _T("Reference=*\\G{") + atlSettings_->GetTypeLibraryGuid() + _T("}#1.0#0#") + genPath + _T("\\lib\\") + prefix + _T("_D.dll#") + atlSettings_->GetTypeLibraryName() +  xCrLf;
	code += _T("Form=frmMain.frm") + xCrLf;
	code += _T("Startup=\"frmMain\"") + xCrLf;
	code += _T("Command32=\"\"") + xCrLf;
	code += _T("Name=\"Test\"") + xCrLf;
	code += _T("HelpContextID=\"0\"") + xCrLf;
	code += _T("CompatibleMode=\"0\"") + xCrLf;
	code += _T("MajorVer=1") + xCrLf;
	code += _T("MinorVer=0") + xCrLf;
	code += _T("RevisionVer=0") + xCrLf;
	code += _T("AutoIncrementVer=0") + xCrLf;
	code += _T("ServerSupportFiles=0") + xCrLf;
	code += _T("VersionCompanyName=\" .\"") + xCrLf;
	code += _T("CompilationType=0") + xCrLf;
	code += _T("OptimizationType=0") + xCrLf;
	code += _T("FavorPentiumPro(tm)=0") + xCrLf;
	code += _T("CodeViewDebugInfo=0") + xCrLf;
	code += _T("NoAliasing=0") + xCrLf;
	code += _T("BoundsCheck=0") + xCrLf;
	code += _T("OverflowCheck=0") + xCrLf;
	code += _T("FlPointCheck=0") + xCrLf;
	code += _T("FDIVCheck=0") + xCrLf;
	code += _T("UnroundedFP=0") + xCrLf;
	code += _T("StartMode=0") + xCrLf;
	code += _T("Unattended=0") + xCrLf;
	code += _T("Retained=0") + xCrLf;
	code += _T("ThreadPerObject=0") + xCrLf;
	code += _T("MaxNumberOfThreads=1") + xCrLf;
	code += xCrLf;
	code += _T("[MS Transaction Server]") + xCrLf;
	code += _T("AutoRefresh=1") + xCrLf;

	testProjectName = genPath + _T("\\") + prefix + _T("\\testProject\\testProject.vbp");
	SaveFile(testProjectName, code, false);

	// main form generation
	//
	code = _T("");
	code += _T("VERSION 5.00") + xCrLf;
	code += _T("Begin VB.Form frmMain") + xCrLf;
	code += xTab + _T("Caption         =   \"Cm_ConfigBuilder Vb Tester\"") + xCrLf;
	code += xTab + _T("ClientHeight    =   5430") + xCrLf;
	code += xTab + _T("ClientLeft      =   60") + xCrLf;
	code += xTab + _T("ClientTop       =   450") + xCrLf;
	code += xTab + _T("ClientWidth     =   8325") + xCrLf;
	code += xTab + _T("LinkTopic       =   \"frmMain\"") + xCrLf;
	code += xTab + _T("ScaleHeight     =   5430") + xCrLf;
	code += xTab + _T("ScaleWidth      =   8325") + xCrLf;
	code += xTab + _T("StartUpPosition =   3  'Windows Default") + xCrLf;
	code += xTab + _T("Begin VB.CommandButton CmdTest") + xCrLf; 
	code += xTab + xTab + _T("Caption         =   \"Test\"") + xCrLf;
	code += xTab + xTab + _T("Height          =   735") + xCrLf;
	code += xTab + xTab + _T("Left            =   840") + xCrLf;
	code += xTab + xTab + _T("TabIndex        =   0") + xCrLf;
	code += xTab + xTab + _T("Top             =   240") + xCrLf;
	code += xTab + xTab + _T("Width           =   3255") + xCrLf;
	code += xTab + _T("End") + xCrLf;
	code +=_T("End") + xCrLf;
	code += _T("Attribute VB_Name = \"frmMain\"") + xCrLf;
	code += _T("Attribute VB_GlobalNameSpace = False") + xCrLf;
	code += _T("Attribute VB_Creatable = False") + xCrLf;
	code += _T("Attribute VB_PredeclaredId = True") + xCrLf;
	code += _T("Attribute VB_Exposed = False") + xCrLf;
	code += _T("Option Explicit") + xCrLf;
	code += xCrLf;
	code += _T("Private Sub CmdTest_Click()") + xCrLf;
	code += xCrLf;
	code += xTab + _T("Dim cfg As New ") + ToUpperCase(prefix) + _T("Lib") + _T(".") + project_->GetRootElement()->GetName() + xCrLf;
	code += xTab + _T("Dim dlg As New ") + ToUpperCase(prefix) + _T("Lib") + _T(".MainDialog") + xCrLf;
    code += xTab + _T("Dim ret As Boolean") + xCrLf;
	code += xCrLf;
	code += xTab + _T("ret = cfg.Load(App.Path & \"\\mySettings.xml\")") + xCrLf;
	code += xCrLf;
	code += xTab + _T("ret = dlg.Display(cfg)") + xCrLf;
	code += xTab + _T("if ret then") + xCrLf;
	code += xTab + xTab + _T("cfg.Save App.Path & \"\\mySettings.xml\"") + xCrLf;
	code += xTab + _T("end if") + xCrLf;
	code += xCrLf;
	code += _T("End Sub") + xCrLf;

	mainFormName = genPath + _T("\\") + prefix + _T("\\testProject\\frmMain.frm");
	SaveFile(mainFormName, code, false);
}

void CAtlGenerationManager::RunTestProject()
{	
	cmString testProjectName;
	cmString prefix;
	cmString genPath;	

	genPath = atlSettings_->GetGenerationPath();
	prefix = atlSettings_->GetClassPrefix();

	//testProjectName = genPath + _T("\\") + prefix + _T("\\testProject\\testProject.vbp");
	//ShellExecute(NULL, _T("open"), testProjectName, NULL, NULL, SW_HIDE);
}

void CAtlGenerationManager::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 CAtlGenerationManager::GenerateCppComponentsFile()
{
	map<cmString/*fileName*/, cmString/*filePath*/> fileList;
	map<cmString, cmString>::iterator it;
	cmString destPath;
	cmString sourcePath;
	cmString generationPath;

	generationPath = atlSettings_->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.atl"), _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("\\") + atlSettings_->GetClassPrefix() + _T("\\");

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

void CAtlGenerationManager::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 CAtlGenerationManager::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 CAtlGenerationManager::GeneratePostBuildFile(const cmString& fileName, 
												  const cmString& sourceFolder, 
												  const cmString& filePostfix)
{											  
	cmString code;
	cmString tmp(sourceFolder);
	cmString dllPrefix;
	cmString prefix;
	cmString genPath;

	if (atlSettings_->GetDllFileNamePrefix() != _T(""))
		dllPrefix = atlSettings_->GetDllFileNamePrefix();
	else
		dllPrefix = atlSettings_->GetClassPrefix();
	prefix = atlSettings_->GetClassPrefix();
	genPath = atlSettings_->GetGenerationPath();
	tmp.MakeUpper();

	// commands to copy dll on lib directory
	//
	code += _T("echo *****************************************") + xCrLf;
	code += _T("echo * ") + tmp + _T(" dll post build batch            *") + xCrLf;
	
	// commands to copy .h and _i.c file
	//
	code += _T("echo copying header file to include directory ...") + xCrLf;
	code += _T("copy ProjectConfigAtl.h \"..\\..\\include\\") + prefix + _T(".h\"") + xCrLf;
	code += _T("echo copying _i.,c file to include directory ...") + xCrLf;
	code += _T("copy ProjectConfigAtl_i.c \"..\\..\\include\\") + prefix + _T("_i.c\"") + xCrLf;

	// command to register dll
	//
	code += _T("echo registering component ...") + xCrLf;
	code += _T("regsvr32 /s \"") + atlSettings_->GetPostBuildPath() + _T("\\") + dllPrefix + filePostfix + _T(".dll\"") + xCrLf; 
	code += _T("echo *     BATCH COMPLETE                    *") + xCrLf;
	code += _T("echo *****************************************") + xCrLf;
		
	SaveFile(fileName, code, false);
}

void CAtlGenerationManager::GenerateDefFiles()
{
	cmString code;
	cmString prefix;
	cmString fileName;
	cmString genPath;
	cmString dllPrefix;
	
	genPath = atlSettings_->GetGenerationPath();
	prefix = atlSettings_->GetClassPrefix();
	dllPrefix = atlSettings_->GetDllFileNamePrefix();

	// 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      \"") + dllPrefix + _T("_D\"") + xCrLf;
	code += xCrLf;
	code += _T("EXPORTS") + xCrLf;
    code += xTab + _T("DllCanUnloadNow     @1 PRIVATE") + xCrLf;
	code += xTab + _T("DllGetClassObject   @2 PRIVATE") + xCrLf;
	code += xTab + _T("DllRegisterServer   @3 PRIVATE") + xCrLf;
	code += xTab + _T("DllUnregisterServer @4 PRIVATE") + 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 (Unicode Debug Version).") + xCrLf;
	code += xCrLf;
	code += _T("LIBRARY      \"") + dllPrefix + _T("_DU\"") + xCrLf;
	code += xCrLf;
	code += _T("EXPORTS") + xCrLf;
    code += xTab + _T("DllCanUnloadNow     @1 PRIVATE") + xCrLf;
	code += xTab + _T("DllGetClassObject   @2 PRIVATE") + xCrLf;
	code += xTab + _T("DllRegisterServer   @3 PRIVATE") + xCrLf;
	code += xTab + _T("DllUnregisterServer @4 PRIVATE") + 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      \"") + dllPrefix + _T("_R\"") + xCrLf;
	code += xCrLf;
	code += _T("EXPORTS") + xCrLf;
    code += xTab + _T("DllCanUnloadNow     @1 PRIVATE") + xCrLf;
	code += xTab + _T("DllGetClassObject   @2 PRIVATE") + xCrLf;
	code += xTab + _T("DllRegisterServer   @3 PRIVATE") + xCrLf;
	code += xTab + _T("DllUnregisterServer @4 PRIVATE") + xCrLf;
	code += xCrLf;

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

	// unicode release def file
	//
	code.Empty();
	code += _T("; ") + prefix + _T("_RU.def : Declares the module parameters for the DLL (Unicode Release Version).") + xCrLf;
	code += xCrLf;
	code += _T("LIBRARY      \"") + dllPrefix + _T("_RU\"") + xCrLf;
	code += xCrLf;
	code += _T("EXPORTS") + xCrLf;
    code += xTab + _T("DllCanUnloadNow     @1 PRIVATE") + xCrLf;
	code += xTab + _T("DllGetClassObject   @2 PRIVATE") + xCrLf;
	code += xTab + _T("DllRegisterServer   @3 PRIVATE") + xCrLf;
	code += xTab + _T("DllUnregisterServer @4 PRIVATE") + xCrLf;
	code += xCrLf;

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