// AddIn.cpp

#include "stdafx.h"
#include "mycontextbase.h"
#include "AddIn.h"
#include "ExecuteModule.h"
#include "WorkAsRegister.h"
#include "TemplateClass.h"
#include "EventManager.h"
#include "ComponentClass.h"
#include "HashMap.h"
#include "Delegate.h"
#include "Struct.h"
#include "DynaValue.h"
#include "DynaValueList.h"
#include "MySQL_Query.h"
#include "CreateMetaInfoClasses.h"

//{OAS
#include ".\\TurboBL\\gcboost.h"
//#include "loader.h"
//OAS}

#include "Service.h"
#include "FormEx.h"
#include "AttribEx.h"
#include "PaintHook.h"
#include "MDIClientWnd.h"
#include "WrapAboutDlg.h"
#include "v7Windows.h"
#include "InitFormEx.h"

#include ".\\SQL\\MetaDataWork.h"
#include ".\\ODBC\\1CPP_ODBCDatabase.h"
#include ".\\ODBC\\1CPP_ODBCRecordSet.h"
#include ".\\ODBC\\SQLLock.h"
#include "BinaryData.h"
#include "GUID.h"
#include "istrmap.h"
#include "Factory.h"
#include ".\\OLEDB\\sp_oledb.h"// Kirill
#include ".\\OLEDB\\sp_cooledb.h"// Kirill

#include "MethodsWrapper.h" // artbear
#include "TableEx.h" // artbear
#include ".\\System\\Settings.h" // artbear
// This global interface is for timer implementation only

class CDataBase7 * pDataBase7 = NULL;
class CMetaDataCont * pMetaDataCont = NULL;
class CBkEndUI * pBkEndUI;
class CAddIn * pMainAddIn;
CRuntimeClass* pCBLContextRuntimeClass;

IDispatch *pGlobalConnection = NULL;

CInitFormEx InitFormEx;
CInitTableWrap InitTableWrap; //artbear

//DMS:BEGIN
char buf[4096];
char **pst = 0;
//DMS:END

//+ kms
#include "System/compare.h"

// быстрые строчные компараторы
class CCompare FastCompare;
class CCompare FastCompareNoCase(0xFFFFFF00);
//- kms
/////////////////////////////////////////////////////////////////////////////
// CAddIn

BOOL CAddIn::LoadProperties()
{  

	m_EnableOptimizate = TRUE; // по умолчанию оптимизация включена

	m_PropertyCollection.Load(m_iProfile);

	return TRUE;
}   

void CAddIn::SaveProperties()
{
	m_PropertyCollection.Save(m_iProfile);
}

/* 
These two methods is convenient way to access function 
parameters from SAFEARRAY vector of variants
*/

/////////////////////////////////////////////////////////////////////////////
// IInitDone

/*#define COPY6(FromPtr, ToPtr) \
    BYTE* fp = (BYTE*)FromPtr; \
    BYTE* tp = (BYTE*)ToPtr; \
    for (int i = 0; i < 6; i++) *tp++ = *fp++;

#define SetWrapJmp(NativeFuncAdr, NewFuncAdr) \
    BYTE* p = NativeFuncAdr; \
    *p++ = 0xFF; \
    *p++ = 0x25; \
	*(DWORD*)p = (DWORD)&NewFuncAdr;*/

typedef CBLContext* (*PF_CreateInstance)(char const *);
/*static BYTE* adrNativeCreateInstance;
static PF_CreateInstance NewCreateInstance;
static BYTE NativeCreateInstanceBody[6];*/
CDllMethodWrapper<PF_CreateInstance> wrapperCreateInstance;

CIStringMapToOb* pClassNameHash;

void RegisterCBLContext(CRuntimeClass* pRuntimeClass, LPCSTR szClassName, BOOL bNativeRegistration /*= TRUE*/)
{
    if (pClassNameHash->GetCount() * 1.2 > pClassNameHash->GetHashTableSize())
    {
        CIStringMapToOb* pNewHash = new CIStringMapToOb();
        pNewHash->InitHashTable((pClassNameHash->GetCount() + 11) * 1.2);
        POSITION pos = pClassNameHash->GetStartPosition();
        CString strCurName;
        CObject* pObject;
        while (pos)
        {
            pClassNameHash->GetNextAssoc(pos, strCurName, pObject);
            pNewHash->operator[](strCurName) = pObject;
        }
        delete pClassNameHash;
        pClassNameHash = pNewHash;

        /*
        CString s;
        s.Format("Class names hash table is grown to: %d", pClassNameHash->GetHashTableSize());
        pBkEndUI->DoMessageLine(s);
        */
    }
    if (bNativeRegistration)
        CBLContext::RegisterContextClass(pRuntimeClass, szClassName, CType(100));
    pClassNameHash->operator[](szClassName) = (CObject*)pRuntimeClass;
    /*
    CString s;
    s.Format("%s : %d", szClassName, pClassNameHash->GetCount());
    pBkEndUI->DoMessageLine(s);
    */
}

CBLContext* CreateInstanceBoosted(char const * szClassName)
{
    CBLContext* pBLContext;
    CRuntimeClass* pRuntimeClass;
    if (pClassNameHash->Lookup(szClassName, (CObject*&)pRuntimeClass))
    {
        pBLContext = (CBLContext*)pRuntimeClass->CreateObject();
        pBLContext->InitObject(szClassName);
    }
    else
    {
        //COPY6(NativeCreateInstanceBody, adrNativeCreateInstance);
		wrapperCreateInstance.RestoreOrigAddress();

        pBLContext = CBLContext::CreateInstance(szClassName);

        //SetWrapJmp(adrNativeCreateInstance, NewCreateInstance);
		wrapperCreateInstance.RestoreWrapAddress();

        if (pBLContext)
        {
            if (!pBLContext->IsOleContext())
                RegisterCBLContext(pBLContext->GetRuntimeClass(), szClassName, FALSE);
        }
    }
    return pBLContext;
}

// счетчик числа инициализаций компоненты
int CAddIn::m_nInitDoneCount = 0;

STDMETHODIMP CAddIn::Init(IDispatch *pConnection)
{
	// предотвращение повторной загрузки
	if (m_nInitDoneCount++)
		return(E_FAIL);

	pApp = AfxGetApp();
	pBkEndUI = GetBkEndUI();

	pConnection->QueryInterface(IID_IErrorLog,(void **)&m_iErrorLog);
	pConnection->QueryInterface(IID_IAsyncEvent,(void **)&m_iAsyncEvent);
	pConnection->QueryInterface(IID_IStatusLine,(void **)&m_iStatusLine);
	pConnection->QueryInterface(IID_IPropertyProfile,(void **)&m_iProfile);
	pConnection->QueryInterface(IID_IExtWndsSupport,(void **)&m_iExtWndsSupport);

	InitProperties(); // настройка свойств

	if (m_iProfile) 
	{
		bstr_t strProfile("1C++ Components & Class\\");
		strProfile += bstr_t(((CApp7*)pApp)->GetProps()->GetStringProp(0x12));
		HRESULT hr = m_iProfile->RegisterProfileAs(strProfile);

		if (!LoadProperties())
			return E_FAIL;
	}
	
	pGlobalConnection = pConnection;
	
	pDataBase7			= CDataBase7::GetDefault();
	pMetaDataCont		= pDataBase7->GetMD();

    //Ускорение создания объектов
    pClassNameHash = new CIStringMapToOb();
    //pClassNameHash->InitHashTable(5 * 1.2); //just for debug
    
	/*DWORD oldProtect;
    adrNativeCreateInstance = (BYTE*)GetProcAddress(::GetModuleHandle("bkend.dll"), "?CreateInstance@CBLContext@@SAPAV1@PBD@Z");
	VirtualProtect(adrNativeCreateInstance, 6, PAGE_EXECUTE_READWRITE, &oldProtect);
    COPY6(adrNativeCreateInstance, NativeCreateInstanceBody);
	NewCreateInstance = (PF_CreateInstance)CreateInstanceBoosted;
    SetWrapJmp(adrNativeCreateInstance, NewCreateInstance);*/

	wrapperCreateInstance.DoWrap(::GetModuleHandle("bkend.dll"), "?CreateInstance@CBLContext@@SAPAV1@PBD@Z", (PF_CreateInstance)CreateInstanceBoosted);
	
	//

	CBLContext::RegisterContextClass(RUNTIME_CLASS(CExecuteModule) ,"ExecuteModule",CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CExecuteModule) ,"ВыполняемыйМодуль",CType(100));

	CBLContext::RegisterContextClass(RUNTIME_CLASS(CWorkAsRegister), "WorkAsRegisterWin", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CWorkAsRegister), "РаботаСРегистромWin", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CWorkAsRegister), "RegistryWin", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CWorkAsRegister), "РеестрWin", CType(100));

	CBLContext::RegisterContextClass(RUNTIME_CLASS(CComponentClass), "CComponentClass", CType(100));

	CBLContext::RegisterContextClass(RUNTIME_CLASS(CEventManager), "EventManager", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CEventManager), "МенеджерСобытий", CType(100));

	CBLContext::RegisterContextClass(RUNTIME_CLASS(CDelegate), "Delegate", CType(100));  
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CDelegate), "Делегат", CType(100));  

	CBLContext::RegisterContextClass(RUNTIME_CLASS(CHashMap), "HashMap", CType(100));  

	CBLContext::RegisterContextClass(RUNTIME_CLASS(CStruct), "Struct", CType(100));    
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CStruct), "Структура", CType(100));    

	CBLContext::RegisterContextClass(RUNTIME_CLASS(CDynaValueList), "DynaValueList", CType(100));    
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CDynaValue), "DynaValue", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CDynaCrypt), "DynaCrypt", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CMySQL_Query), "SQL_Query", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CCreateMetaInfoClasses), "MetaInfoClasses", CType(100));
	
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CService) ,"ServiceFormEx", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CService) ,"СервисРасшФормы", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CService) ,"Service", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CService) ,"Сервис", CType(100));

	CBLContext::RegisterContextClass(RUNTIME_CLASS(CFormEx) ,"FormEx", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CFormEx) ,"РасширениеФормы", CType(100));

	CBLContext::RegisterContextClass(RUNTIME_CLASS(CAttribEx) ,"AttribEx", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CAttribEx) ,"АтрибутФормы", CType(100));

	CBLContext::RegisterContextClass(RUNTIME_CLASS(Cv7Windows)	,"Окна"		,CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(Cv7Windows)	,"Windows"	,CType(100));

	CBLContext::RegisterContextClass(RUNTIME_CLASS(CMetaDataWork) ,"MetaDataWork",CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(C1CPP_ODBCRecordSet) ,"ODBCRecordSet",CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(C1CPP_ODBCDatabase) ,"ODBCDatabase",CType(100));
	
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CSQLLock) ,"SQLLock",CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CBinaryData) ,"BinaryData",CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CGUID) ,"GUID",CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CObjectFactory) ,"ФабрикаОбъектов",CType(100));

	CBLContext::RegisterContextClass(RUNTIME_CLASS(COLEDBData), "OLEDBData", CType(100));// Kirill

//	CBLContext::RegisterContextClass(RUNTIME_CLASS(CTableEx), "ТаблицаРасширенная", CType(100));// artbear
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CSettings), "УправлениеНастройками", CType(100));
	CBLContext::RegisterContextClass(RUNTIME_CLASS(CSettings), "SettingsManager", CType(100));

	//CAttachedContext::Init();
	
    CMyContextBase::InitAllContextClasses();
	InitAllBoost();
	//OAS}
	
	hLibBasic = GetModuleHandle("Basic.dll");
	if (hLibBasic == NULL)  
		pBkEndUI->DoMessageLine("Неудачная попытка получить хендл модуля Basic.dll",mmInformation);  

	CSetOfHierarchy *pHierarchy = CSetOfHierarchy::GetHierarchy();
	
	pHierarchy->Init();
	pHierarchy->ProcessDefines();
	
	pHierarchy->RegistersContextClasses();
	
	pMainAddIn = this;
	
	CComponentClass::ExceptionValue = new CValue;
	
	if(!InitFormEx.Init()) return E_FAIL;
	if(!InitTableWrap.Init()) return E_FAIL;
	
	return S_OK;
}

STDMETHODIMP CAddIn::Done()
{
	// предотвращение повторной загрузки
	if (--m_nInitDoneCount)
		return S_OK;

	AFX_MANAGE_STATE(AfxGetStaticModuleState())
		//    if (m_uiTimer != 0) ::KillTimer(NULL,m_uiTimer);
		SaveProperties();
	
	if (m_iStatusLine) m_iStatusLine->Release();
	if (m_iProfile) m_iProfile->Release();
	if (m_iAsyncEvent) m_iAsyncEvent->Release();
	if (m_iErrorLog) m_iErrorLog->Release();
	if (m_iExtWndsSupport) m_iExtWndsSupport->Release();
	
    //Отмена ускорения создания объектов
	if (pClassNameHash)
	{
		delete pClassNameHash;
		//COPY6(NativeCreateInstanceBody, adrNativeCreateInstance);
		wrapperCreateInstance.RestoreOrigAddress();
	}
    //
    
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CExecuteModule));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CExecuteModule));	
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CWorkAsRegister));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CWorkAsRegister));	
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CComponentClass));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CEventManager));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CEventManager));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CDelegate));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CDelegate));  
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CStruct));    
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CStruct));    
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CDynaValueList));    
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CDynaValue));    
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CDynaCrypt));      
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CMySQL_Query));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CCreateMetaInfoClasses));  
	
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(Cv7Windows));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(Cv7Windows));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CAttribEx));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CAttribEx));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CFormEx));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CFormEx));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CService));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CService));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CService));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CService));
	
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CMetaDataWork));
	
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(C1CPP_ODBCRecordSet));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(C1CPP_ODBCDatabase));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CSQLLock));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CBinaryData));
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CGUID));
	
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(COLEDBData));// Kirill

//	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CTableEx));// artbear
	CBLContext::UnRegisterContextClass(RUNTIME_CLASS(CSettings));
	
	if (hLibBasic != NULL)  
		FreeLibrary(hLibBasic);
	
	CSetOfHierarchy::DeInitHierarchy();
	
	InitFormEx.Destroy();
	
	pMainAddIn = NULL;

	return S_OK;
}

STDMETHODIMP CAddIn::GetInfo(SAFEARRAY **pInfo)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())
		
		// Component should put supported component technology version 
		// in VARIANT at index 0     
		long lInd = 0;
    VARIANT varVersion;
    V_VT(&varVersion) = VT_I4;
	// This component supports 1.0 version
    V_I4(&varVersion) = 2000;
    SafeArrayPutElement(*pInfo,&lInd,&varVersion);
    
	return S_OK;
}

/////////////////////////////////////////////////////////////////////////////
// ILanguageExtender

STDMETHODIMP CAddIn::RegisterExtensionAs(BSTR *bstrExtensionName)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())
		
		// You may delete next lines and add your own implementation code here
		
		// Name of extension should be changed avoiding conflicts 
		CString csExtenderName = "1C++";
    *bstrExtensionName = csExtenderName.AllocSysString();
	
	return NULL;
}

/////////////////////////////////////////////////////////////////////////////
// IPropertyPage

/*STDMETHODIMP CAddIn::SetPageSite(IPropertyPageSite *pPageSite)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())
m_pPageSite = pPageSite;
// TODO: Add your implementation code here

  return S_OK;
}*/

/*STDMETHODIMP CAddIn::Activate(HWND hWndParent,LPCRECT prc,BOOL bModal)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())

  // TODO: Add your implementation code here
  
    return IPropertyPageImpl<CAddIn>::Activate(hWndParent,prc,bModal);
}*/

STDMETHODIMP CAddIn::Deactivate()
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())
		
		IPropertyPageImpl<CAddIn>::Deactivate();
	
    // Don't forget to detach controls!
	m_boxEnabledCheckType.Detach();
	m_boxOptimizate.Detach();
	m_boxEnableDebugging.Detach();  
	m_boxEnabledColor.Detach();
	m_boxLocalColor.Detach();
	m_boxShowKL.Detach();
	
	return S_OK;
}

/*STDMETHODIMP CAddIn::GetPageInfo(PROPPAGEINFO *pPageInfo)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())

  // TODO: Add your implementation code here
  
	return S_OK;
	}
	
	  STDMETHODIMP CAddIn::SetObjects(ULONG cObjects,IUnknown **ppUnk)
	  {
	  AFX_MANAGE_STATE(AfxGetStaticModuleState())
	  
		// TODO: Add your implementation code here
		
		  return IPropertyPageImpl<CAddIn>::SetObjects(cObjects,ppUnk);
		  }
		  
			/*STDMETHODIMP CAddIn::Show(UINT nCmdShow)
			{
			AFX_MANAGE_STATE(AfxGetStaticModuleState())
			
			  // TODO: Add your implementation code here
			  
				return S_OK;
				}
				
				  STDMETHODIMP CAddIn::Move(LPCRECT prc)
				  {
				  AFX_MANAGE_STATE(AfxGetStaticModuleState())
				  
					// TODO: Add your implementation code here
					
					  return S_OK;
					  }
					  
						STDMETHODIMP CAddIn::IsPageDirty()
						{
						AFX_MANAGE_STATE(AfxGetStaticModuleState())
						
						  // TODO: Add your implementation code here
						  
							return S_OK;
}*/

STDMETHODIMP CAddIn::Apply()
{	
	InitFormEx.BeforeApply();

	{
		AFX_MANAGE_STATE(AfxGetStaticModuleState())
			BOOL boolEnabled;    
		IPropertyLink *pLink = NULL;    
		m_ppUnk[0]->QueryInterface(IID_IPropertyLink,(LPVOID *)&pLink);
		if (pLink != NULL)
		{
			boolEnabled = m_boxEnabledCheckType.GetCheck()?TRUE:FALSE;
			pLink->put_Enabled((unsigned char *)&boolEnabled, IDC_CHECK_TYPE);
			boolEnabled = m_boxOptimizate.GetCheck()?TRUE:FALSE;
			pLink->put_Enabled((unsigned char *)&boolEnabled, IDC_OPTIMIZATE);
			
			boolEnabled = m_boxEnableDebugging.GetCheck()?TRUE:FALSE;
			pLink->put_Enabled((unsigned char *)&boolEnabled, IDC_ENABLE_DEBUGGING);
			
			boolEnabled = m_boxEnabledColor.GetCheck()?TRUE:FALSE;
			pLink->put_Enabled((unsigned char *)&boolEnabled, IDC_ENCOLOR);
			
			boolEnabled = m_boxLocalColor.GetCheck()?TRUE:FALSE;
			pLink->put_Enabled((unsigned char *)&boolEnabled, IDC_LOCALCOLOR);
			
			boolEnabled = m_boxShowKL.GetCheck()?TRUE:FALSE;
			pLink->put_Enabled((unsigned char *)&boolEnabled, IDC_SHOWKL);
			
			pLink->Release();
		}
		SetDirty(FALSE);
	}

	InitFormEx.Apply();

	return S_OK;
}

/*STDMETHODIMP CAddIn::Help(LPCOLESTR pszHelpDir)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState())

  // TODO: Add your implementation code here
  
	return S_OK;
	}
	
	  STDMETHODIMP CAddIn::TranslateAccelerator(LPMSG pMsg)
	  {
	  AFX_MANAGE_STATE(AfxGetStaticModuleState())
	  
		// TODO: Add your implementation code here
		
		  return S_OK;
}*/


LRESULT CAddIn::OnInitDialog(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())
		IPropertyLink *pLink = NULL;
	m_ppUnk[0]->QueryInterface(IID_IPropertyLink,(LPVOID *)&pLink);
	m_boxEnabledCheckType.Attach(GetDlgItem(IDC_CHECK_TYPE));
	m_boxOptimizate.Attach(GetDlgItem(IDC_OPTIMIZATE));
	m_boxEnableDebugging.Attach(GetDlgItem(IDC_ENABLE_DEBUGGING));
	
	if (pLink != NULL)
	{
		pLink->get_Enabled((unsigned char *)&m_EnabledCheckType, IDC_CHECK_TYPE);        
		pLink->get_Enabled((unsigned char *)&m_EnableOptimizate, IDC_OPTIMIZATE);                
		pLink->get_Enabled((unsigned char *)&m_EnableDebugging, IDC_ENABLE_DEBUGGING);
		
		pLink->get_Enabled((unsigned char *)&m_bEnabledColor, IDC_ENCOLOR);        
		pLink->get_Enabled((unsigned char *)&m_bLocalColor, IDC_LOCALCOLOR);                
		pLink->get_Enabled((unsigned char *)&m_bShowKL, IDC_SHOWKL);
		
		pLink->Release();
		
	}
	
	
	m_boxEnabledCheckType.SetCheck(m_EnabledCheckType?1:0);    
	m_boxOptimizate.SetCheck(m_EnableOptimizate?1:0);
	m_boxEnableDebugging.SetCheck(m_EnableDebugging?1:0);
	
	m_boxEnabledCheckType.EnableWindow(m_AccessCheckType);
	m_boxOptimizate.EnableWindow(m_AccessOptimizate);
	m_boxEnableDebugging.EnableWindow(m_AccessEnableDebugging);
	
	m_boxEnabledColor.Attach(GetDlgItem(IDC_ENCOLOR));
	m_boxEnabledColor.SetCheck(m_bEnabledColor?1:0);
	
	m_boxLocalColor.Attach(GetDlgItem(IDC_LOCALCOLOR));
	m_boxLocalColor.SetCheck(m_bLocalColor?1:0);
	
	m_boxShowKL.Attach(GetDlgItem(IDC_SHOWKL));
	m_boxShowKL.SetCheck(m_bShowKL?1:0);
	
	
	CSetOfHierarchy* pHierarchy = CSetOfHierarchy::GetHierarchy();
	CString text;
	if (pHierarchy)
		text.Format("Всего зарегистрировано классов: %d\r\nВсего объявлено методов: %d\r\nОпределенные директивы препроцессора:\r\n%s\r\nВложенные файлы:\r\n%s\r\nИмена зарегистрированных классов:\r\n%s\r\nИмена псевдонимов и их пути:\r\n%s",pHierarchy->GetCountClasses(), pHierarchy->GetCountMethods(), pHierarchy->GetDefSymbolOfPreproc(),pHierarchy->GetLoadIncludeFiles(),pHierarchy->GetAllClassesNames(), pHierarchy->GetAllAliasAndPath());
	
	SetDlgItemText(IDC_EDIT1,text);
	
	SetDirty(FALSE);
	m_pPageSite->OnStatusChange(0);
	bHandled = FALSE;
	
	GetDlgItemText(IDC_ABOUT_STATIC, text.GetBufferSetLength(250), 250);
    text.ReleaseBuffer();
    CString sVersion = ::GetVersionField("FileVersion");
    sVersion.Replace(" ", "");
    sVersion.Replace(',', '.');
    CString sPrivateBuild = ::GetVersionField("PrivateBuild");
    if (!sPrivateBuild.IsEmpty())
    {
        sVersion += ' ';
        sVersion += sPrivateBuild;
    }
    CString sSpecialBuild = ::GetVersionField("SpecialBuild");
    if (!sSpecialBuild.IsEmpty())
    {
        sVersion += ' ';
        sVersion += sSpecialBuild;
    }
    text.Replace("_VersionInfo_", sVersion);
    SetDlgItemText(IDC_ABOUT_STATIC, text);

	return 0; 
}

LRESULT CAddIn::OnCommand(WORD wNotifyCode, WORD nID, HWND hWndCtl, BOOL& bHandled)
{
	SetDirty(TRUE);
	
	/*switch(nID)
	{
    case IDC_OPTIMIZATE:
	{        
	EnableWindow(IDC_ENABLE_DEBUGGING,m_EnableDebugging);
	}
	break;
	default:
	break;
}*/
	bHandled = FALSE;
	return 0;
}

/////////////////////////////////////////////////////////////////////////////
// IPropertyLink

STDMETHODIMP CAddIn::get_Enabled(unsigned char* pData, int Id)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	CString key = m_PropertyCollection.GetKeyByDialogID(Id);
	BOOL* boolEnabled = (BOOL*)pData;
	*boolEnabled = m_PropertyCollection.Item[key];

	return S_OK;
}

STDMETHODIMP CAddIn::put_Enabled(unsigned char* pData, int Id)
{
	AFX_MANAGE_STATE(AfxGetStaticModuleState())

	CString key = m_PropertyCollection.GetKeyByDialogID(Id);
	BOOL* boolEnabled = (BOOL*)pData;
	m_PropertyCollection.Item[key] = *boolEnabled;

	SaveProperties(); //TODO
	return S_OK;
}


STDMETHODIMP CAddIn::CallAsFunc(long,struct tagVARIANT *,struct tagSAFEARRAY * *)
{
	return S_OK;
}

STDMETHODIMP CAddIn::CallAsProc(long,struct tagSAFEARRAY * *)
{
	return S_OK;
}

STDMETHODIMP CAddIn::HasRetVal(long,int * ipRes)
{
	*ipRes	= 0;
	
	return S_OK;
}

STDMETHODIMP CAddIn::GetParamDefValue(long,long,struct tagVARIANT *)
{
	return S_OK;
}

STDMETHODIMP CAddIn::GetNParams(long,long * lpParams)
{
	*lpParams	= 0;
	return S_OK;
}

STDMETHODIMP CAddIn::GetMethodName(long,long,unsigned short * *)
{
	return S_OK;
}

STDMETHODIMP CAddIn::FindMethod(unsigned short *,long *)
{
	return S_OK;
}

STDMETHODIMP CAddIn::GetNMethods(long * lpRes)
{
	*lpRes = 0;
	return S_OK;
}

STDMETHODIMP CAddIn::IsPropWritable(long,int *)
{
	return S_OK;
}
STDMETHODIMP CAddIn::IsPropReadable(long,int *)
{
	return S_OK;
}
STDMETHODIMP CAddIn::SetPropVal(long,struct tagVARIANT *)
{
	return S_OK;
}
STDMETHODIMP CAddIn::GetPropVal(long,struct tagVARIANT *)
{
	return S_OK;
}
STDMETHODIMP CAddIn::GetPropName(long,long,unsigned short * *)
{
	return S_OK;
}
STDMETHODIMP CAddIn::FindProp(unsigned short *,long *)
{
	return S_OK;
}
STDMETHODIMP CAddIn::GetNProps(long * lpNum)
{
	*lpNum = 0;
	return S_OK;
}

//custom funcs
int IsDMSContext(const char *name)
{
	return cFeatureList.FindName(name) ? 1 : 0;
}

BOOL CAddIn::get_Property(CString key)
{
	return m_PropertyCollection.Item[key];
}

void CAddIn::put_Property(CString key, BOOL newValue)
{
	m_PropertyCollection.Item[key] = newValue;
}

// только настраивает свойства, из реестра ничего не читается !!
void CAddIn::InitProperties() 
{
	CString key; int dialogID;

	key = "EnabledCheckType";
    dialogID = IDC_CHECK_TYPE;
	m_PropertyCollection.Add(key, dialogID, 1, 2, 1, &(this->m_EnabledCheckType));

	key = "EnableOptimizate";
    dialogID = IDC_OPTIMIZATE;
	m_PropertyCollection.Add(key, dialogID, 2, 2, 1, &(this->m_EnableOptimizate));
	
	key = "EnableDebugging";
    dialogID = IDC_ENABLE_DEBUGGING;
	m_PropertyCollection.Add(key, dialogID, 1, 2, 1, &(this->m_EnableDebugging));
	
	key = "EnabledColor";
    dialogID = IDC_ENCOLOR;
	m_PropertyCollection.Add(key, dialogID, 0, 1, 0, &m_bEnabledColor);
	
	key = "LocalColor";
    dialogID = IDC_LOCALCOLOR;
	m_PropertyCollection.Add(key, dialogID, 0, 1, 0, &m_bLocalColor);
	
	key = "ShowKeyboardLayout";
    dialogID = IDC_SHOWKL;
	m_PropertyCollection.Add(key, dialogID, 0, 1, 0, &m_bShowKL);
	
	key = "EnableTableSourceTable";
    dialogID = 0;
	m_PropertyCollection.Add(key, dialogID, 0, 1, 0);

}

/////////////////////////////////////////////////////////////////////////////
// class CAddInPropertyCollection

BOOL CAddInPropertyCollection::get_Item(CString key)
{
	BOOL value;
	if (!m_PropertyMap.Lookup(key, value))
		RuntimeError("Не существует свойства с именем %s", key);
	//return m_PropertyMap[key];
	return value;
}

void CAddInPropertyCollection::put_Item(CString key, BOOL newValue)
{
	BOOL value;
	if (m_PropertyMap.Lookup(key, value))
	{
		m_PropertyMap[key] = newValue;
		*(m_PropertyFieldsMap[key]->pRealVariable) = newValue;
	}
	else
		RuntimeError("Не существует свойства с именем %s", key);
}

CString CAddInPropertyCollection::GetKeyByDialogID(int dialogID)
{
	return m_PropertyKeyMapOnDialogID[dialogID];
}

void CAddInPropertyCollection::Add(CString key, int DialogID, BOOL defaultValue, BOOL trueValue, BOOL falseValue, BOOL* pRealVariable)
{
	m_PropertyKeyMapOnDialogID.SetAt(DialogID, key);

	m_PropertyMap[key] = defaultValue;

	CPropertyFields* fields = new CPropertyFields;
	fields->defaultValue = defaultValue;
	fields->trueValue = trueValue;
	fields->falseValue = falseValue;
	
	if (pRealVariable) // удобно использовать, если есть глобальная переменная или переменная, которая хранится в другом классе
		fields->pRealVariable = pRealVariable;
	else
		fields->pRealVariable = &(m_PropertyMap[key]);

	m_PropertyFieldsMap[key] = fields;
}

CAddInPropertyCollection::~CAddInPropertyCollection()
{
	// TODO удалить CPropertyFields
}

bool CAddInPropertyCollection::LoadOneProperty(IPropertyProfile *m_iProfile, CString key, BOOL defaultValue, BOOL trueValue)
{
	variant_t var;
	V_VT(&var) = VT_I4;

	char s[2]; // TODO для других типов другое количество
	s[0] = defaultValue ? '1' : '0';
	s[1] = '\0';

	CString name = key+":"+*s;
	CWChar wStorName(name);
	bool ret = S_OK==m_iProfile->Read(wStorName, &var, NULL);

	Item[key] = ret && V_I4(&var)==trueValue;

	return ret;
}

void CAddInPropertyCollection::Load(IPropertyProfile *m_iProfile)
{

    POSITION pos;
    CString key;
    BOOL val;
    for (pos = m_PropertyMap.GetStartPosition(); pos != NULL;)
    {
		m_PropertyMap.GetNextAssoc( pos, key, val );
		CPropertyFields* fields = m_PropertyFieldsMap[key];

		LoadOneProperty(m_iProfile, key, fields->defaultValue, fields->trueValue);
    }    

}

bool CAddInPropertyCollection::SaveOneProperty(IPropertyProfile *m_iProfile, CString key, BOOL trueValue, BOOL falseValue)
{
    variant_t var;
    V_VT(&var) = VT_I4;
	
	V_I4(&var) = Item[key] ? trueValue : falseValue;
	
	CWChar wStorName(key);
    m_iProfile->Write(wStorName, &var);

	return true;
}

void CAddInPropertyCollection::Save(IPropertyProfile *m_iProfile)
{
    POSITION pos;
    CString key;
    BOOL val;
    for (pos = m_PropertyMap.GetStartPosition(); pos != NULL;)
    {
		m_PropertyMap.GetNextAssoc( pos, key, val );
		CPropertyFields* fields = m_PropertyFieldsMap[key];

		SaveOneProperty(m_iProfile, key, fields->trueValue, fields->falseValue);
    }    
}
