#include "stdafx.h"

//#define ONECPP_ARTBEAR
#include "TableEx.h"

#ifdef VK_1CPP_SourceTable

CMapStringToPtr DocNamesArrayArtbear;
struct SDocNames{
	DWORD id;
	CString strFolder;
};

typedef int(CBLContext::*P_CONT_CALLASP)(int,CValue * *);
typedef int(CBLContext::*P_CONT_CALLASF)(int,CValue &,CValue * *);
typedef int(CBLContext::*P_CONT_GETNPARAMS)(int);
typedef int(CBLContext::*P_CONT_HASRETVAL)(int);
typedef int(CBLContext::*P_CONT_GETPARAMDEFVALUE)(int,int,CValue*);
typedef void(CBLContext::*P_CONT_DECRREF)(void);

static P_CONT_CALLASP pCallAsProcDbl;

static P_CONT_CALLASP pCallAsProc;
static P_CONT_CALLASF pCallAsFunc;
static P_CONT_GETNPARAMS pGetNParams;
static P_CONT_GETPARAMDEFVALUE pGetParamDefValue;
static P_CONT_HASRETVAL pHasRetVal;
static P_CONT_DECRREF pDecrRef;

int iCountStream = 0;

int procGetAllTypedItem(class CString &str,long l1,long l2,enum PageType pt)
{
	if(str.CollateNoCase("ModuleText") == 0)
		return 1;

	CMetaDataCont *pMD = GetMetaData();
	CMetaDataObj* pMDO = pMD->FindObject(l1);
	CString str1 = GetModuleFullName(l1, str, 0, pMD);
	str1.MakeUpper();

	SDocNames *pDocNames = NULL;
	pDocNames = new SDocNames;
	pDocNames->id = l1;
	pDocNames->strFolder = str;
	DocNamesArrayArtbear.SetAt(str1,pDocNames);

	return 1;
}

void GetFirstTableName(CWorkBookDoc* pDoc, CString &TableName)
{
	CStringArray TableNamesArray;
	pDoc->GetTablesName(TableNamesArray);
	if (TableNamesArray.GetSize() > 0)
		TableName = TableNamesArray.GetAt(0);
}

void CTableWrapEx::SetPSheet()
{
	DWORD* pdw = (DWORD*)m_pSheetDocIn;
	m_pSheet = (CSheet*)&pdw[0x2C];
}

int CTableWrapEx::SetTable(class CValue **ppValue)
{
	// возвращает:
	// 0 - таблица установлена
	// 1 - необходим вызов штатной обработки
	// 2 - ошибка пути
	// 3 - ошибка имени таблицы
	// 4 - прочие ошибки
	CString strPath = ppValue[1]->GetString();
	CString strName = ppValue[0]->GetString();
	strPath = AllTrim(strPath);
	if (strPath.IsEmpty())
		return 1;

	strPath.MakeUpper();

	if(strPath.Right(4).CompareNoCase(".MXL") == 0)
	{
		*ppValue[0] = strPath;
		return 1;
	}

	int mdPos = strPath.Find("@MD");
	if (mdPos >= 0)
	{
		CString strPathTemp = strPath.Left(mdPos);
		strPath = CString("MD.Обработка.")+AllTrim(strPathTemp)+".Форма";
		strPath.MakeUpper();
	}

	if(strPath.Left(3).CompareNoCase("MD.") == 0) // внутри md
	{
		CString strDoc = strPath.Mid(3);
		SDocNames *pDocNames = NULL;
		if (!DocNamesArrayArtbear.Lookup(strDoc, (void*&)pDocNames))
			return 2;

		CApp7* pApp7 = (CApp7*) AfxGetApp();
		CProfile7* pProfile7 = pApp7->GetProps();
		CString Prop8 = pProfile7->GetStringProp(0x08); // полный путь к файлу 1Cv7.MD (с именем файла)
		CString strFull = "";
		strFull.Format("%s\\%s\\%s_Number%d\\WorkBook",Prop8,pDocNames->strFolder,pDocNames->strFolder,pDocNames->id);
		CWorkBookDoc* pDoc = (CWorkBookDoc*)CConfigCont::PathToDocument(strFull);
		if (!pDoc)
		{
			CString str;
			CTypedCont *pTypedCont;
			if(CConfigCont::IDToPath(pDocNames->id, pDocNames->strFolder, str, &pTypedCont, 0))
				pDoc = pTypedCont->GetWorkBook();
		}
		if (!pDoc)
			return 4;

		if (strName.IsEmpty())
			GetFirstTableName(pDoc, strName);

		CSheetDoc* pSheetDoc = (CSheetDoc*)pDoc->FindDocument(strName);
		if (!pSheetDoc)
			return 3;

		m_pSheetDocIn = pSheetDoc;
		SetPSheet();
		if(m_pSheetDocOut && (CTemplate7::GetDocumentID(m_pSheetDocOut) != 0))
			m_pSheetDocOut->UpdateAllViews(NULL, 8, NULL);
		return 0;
	}

	// из внешнего отчета
	CTemplate7* pTempl = CTemplate7::FromID(0xBA);
	if (!pTempl)
		return 4;

	POSITION pos = pTempl->GetFirstDocPosition();
	while (pos)
	{
		CWorkBookDoc* pDoc = (CWorkBookDoc*)pTempl->GetNextDoc(pos);
		if (!pDoc)
			continue;

		CString strSrc = pDoc->GetSourcePathName();
		if (strSrc.CompareNoCase(strPath) != 0)
			continue;

		if (strName.IsEmpty()) 
			GetFirstTableName(pDoc, strName);

		CSheetDoc* pSheetDoc = (CSheetDoc*)pDoc->FindDocument(strName);
		if (!pSheetDoc)
			return 3;

		m_pSheetDocIn = pSheetDoc;
		SetPSheet();
		if(m_pSheetDocOut && (CTemplate7::GetDocumentID(m_pSheetDocOut) != 0))
			m_pSheetDocOut->UpdateAllViews(NULL, 8, NULL);
		return 0;
	}

	pTempl = CTemplate7::FromID(0xA1);

	if (!pTempl)
		return 4;

	if (strName.IsEmpty())
		strName = "Moxel WorkPlace";

	COleStorage pOleStorage(NULL);
	CFileException excepFile;
	if (!pOleStorage.Open(strPath, CFile::shareExclusive, &excepFile))
		return 2;

	int res = 4;
	COleStreamFile * pOleStream = pOleStorage.OpenStream(CContainer::GetContentsStreamName(), CFile::shareExclusive, &excepFile);
	if (pOleStream)
	{
		DWORD StreamLen = pOleStream->GetLength();
		char* buf = (char*)malloc(StreamLen);
		pOleStream->Read(buf, StreamLen);
		CItemList list1;
		int n = 0;
		CString strStreamName = "";
		list1.LoadFromString(buf, &n);
		for(int j = list1.FindGenericItem("Moxcel.Worksheet", -1); j >= 0; j = list1.FindGenericItem("Moxcel.Worksheet", ++j))
		{
			CItem* pItem = (CItem*)list1.GetItemAt(j);
			if(pItem->WhatIsIt() != 1)
				continue;

			CItem* pItem1 = (CItem*)((CGenericItem*)pItem)->m_array.GetAt(1);
			CItem* pItem2 = (CItem*)((CGenericItem*)pItem)->m_array.GetAt(2);
			if((strName.CompareNoCase(pItem2->m_str) == 0) ||
				((pItem2->m_str.CompareNoCase("Moxel WorkPlace") == 0) &&
				 (strName.CompareNoCase("Таблица") == 0)))
			{
				strStreamName = pItem1->m_str;
			}
		}
		free(buf);
		pOleStorage.ReleaseStream(pOleStream, TRUE);
		if (!strStreamName.IsEmpty())
		{
			if (pOleStream = pOleStorage.OpenStream(strStreamName, CFile::shareExclusive, &excepFile))
			{
				CArchive ar(pOleStream, CArchive::load);
				if (m_pSheetDocIn)
				{
					// пытаемся очистить ранее созданные нами CSheetDoc
					if (CTemplate7::GetDocumentID(m_pSheetDocIn) == 0)
						delete m_pSheetDocIn;
				}
				m_pSheetDocIn = (CSheetDoc*)CSheetDoc::CreateObject();//new CSheetDoc;
//				CTemplate7::RegisterDocument(m_pSheetDocIn);
//				pTempl->AddDocument(m_pSheetDocIn);

				m_pSheetDocIn->DeleteContents();
				m_pSheetDocIn->Serialize(ar);

				SetPSheet();
				if (m_pSheetDocOut && (CTemplate7::GetDocumentID(m_pSheetDocOut) != 0))
					m_pSheetDocOut->UpdateAllViews(NULL, 8, NULL);

				CTemplate7::UnRegisterDocument(m_pSheetDocIn);
				pOleStorage.ReleaseStream(pOleStream, TRUE);
				res = 0;
			}
			else
				res = 4;
		}
		else
			res = 3;
	}
	pOleStorage.Release(TRUE);

	return res;
}

static DWORD dwCSheetDocVTable = 0;
static int iMethNum_SourceTable = -1;
static int iMethNum_Options = -1;

void CTableWrapEx::DecrRef(void)
{
	int aRefCount = m_RefCount;
	CSheetDoc* pSheetDoc = m_pSheetDocIn;

	(this->*pDecrRef)();

	// пытаемся очистить ранее созданные нами CSheetDoc
	if (--aRefCount || !pSheetDoc) return;
	try {
		if (*(DWORD*)pSheetDoc != dwCSheetDocVTable) return;
	}
	catch (...) {}
	if (CTemplate7::GetDocumentID(pSheetDoc) == 0)
		delete pSheetDoc;
}

int CTableWrapEx::CallAsProc(int iMethNum,class CValue **ppValue)
{
	//CString strMeth = this->GetMethodName(iMethNum,1);
	//if(strMeth.CompareNoCase("ИсходнаяТаблица") == 0)
	if(iMethNum == iMethNum_SourceTable)
	{
		int res = SetTable(ppValue);
		int bCallExept = ppValue[2]->GetNumeric();
		if(bCallExept == 0)
			return S_OK;

		if(res == 0)
			return S_OK;
		else if(res != 1)
		{
			// 2 - ошибка пути
			// 3 - ошибка имени таблицы
			// 4 - прочие ошибки
			if(res == 2)
				CBLModule::RaiseExtRuntimeError("Неверно задан путь к исходной таблице!", mmRedErr);
			else if(res == 3)
				CBLModule::RaiseExtRuntimeError("Неверно задано имя исходной таблицы!", mmRedErr);
			else
				CBLModule::RaiseExtRuntimeError("Ошибка при установке исходной таблицы!", mmRedErr);
			return S_FALSE;
		}
	}
	//else if(strMeth.CompareNoCase("Опции") == 0)
	else if(iMethNum == iMethNum_Options)
	{
		int ret = (this->*pCallAsProc)(iMethNum, ppValue);

		POSITION pos = m_pSheetDocOut->GetFirstViewPosition();
		while(pos)
		{
			CSheetViewMy* pSheetView = (CSheetViewMy*)m_pSheetDocOut->GetNextView(pos);
			CSheetSelection pSel = *(pSheetView->GetTailSelection());
			int nPosVert = pSheetView->GetScrollPos(SB_VERT);
			int nPosHorz = pSheetView->GetScrollPos(SB_HORZ);
			pSheetView->OnInitialUpdate();
			pSheetView->ClearSelection();
			pSheetView->SelectArea(pSel);
			pSheetView->ScrollToPosition(nPosHorz,nPosVert);
		}

		return ret;
	}

	return (this->*pCallAsProc)(iMethNum, ppValue);
};

int CTableWrapEx::CallAsFunc(int iMethNum,class CValue & rValue,class CValue **ppValue)
{
	//CString strMeth = this->GetMethodName(iMethNum,1);
	//if(strMeth.CompareNoCase("ИсходнаяТаблица") == 0)
	if(iMethNum == iMethNum_SourceTable)
	{
		int res = SetTable(ppValue);
		int bCallExept = ppValue[2]->GetNumeric();
		rValue = res;

		if(bCallExept == 0)
			return S_OK;

		if(res == 0)
		{
			rValue = 1L;
			return S_OK;
		}
		else if(res != 1)
		{
			// 2 - ошибка пути
			// 3 - ошибка имени таблицы
			// 4 - прочие ошибки
			if(res == 2)
				CBLModule::RaiseExtRuntimeError("Неверно задан путь к исходной таблице!", mmRedErr);
			else if(res == 3)
				CBLModule::RaiseExtRuntimeError("Неверно задано имя исходной таблицы!", mmRedErr);
			else
				CBLModule::RaiseExtRuntimeError("Ошибка при установке исходной таблицы!", mmRedErr);
			return S_FALSE;
		}

		rValue = 2L;
		return (this->*pCallAsProc)(iMethNum, ppValue);
	}

	return (this->*pCallAsFunc)(iMethNum, rValue, ppValue);
};

int CTableWrapEx::HasRetVal(int iMethNum)const
{
	//CString strMeth = this->GetMethodName(iMethNum,1);
	//if(strMeth.CompareNoCase("ИсходнаяТаблица") == 0)
	if(iMethNum == iMethNum_SourceTable)
	{
		return 1;
	}

	return (this->*pHasRetVal)(iMethNum);
};

int CTableWrapEx::GetNParams(int iMethNum)const
{
	//CString strMeth = this->GetMethodName(iMethNum,1);
	//if(strMeth.CompareNoCase("ИсходнаяТаблица") == 0)
	if(iMethNum == iMethNum_SourceTable)
	{
		return 3;
	}

	return (this->*pGetNParams)(iMethNum);
};

int CTableWrapEx::GetParamDefValue(int iMethNum,int iParamNum,class CValue * pDefValue)const
{
	//CString strMeth = this->GetMethodName(iMethNum,1);
	//if(strMeth.CompareNoCase("ИсходнаяТаблица") == 0)
	if(iMethNum == iMethNum_SourceTable)
	{
		if(iParamNum == 1)
		{
			*pDefValue = "";
			return 1;
		}
		if(iParamNum == 2)
		{
			*pDefValue = 1;
			return 1;
		}
	}

	return (this->*pGetParamDefValue)(iMethNum, iParamNum, pDefValue);
};

union{
	void* pV;
	P_CONT_CALLASP pCallAsProcU;
	P_CONT_CALLASF pCallAsFuncU;
	P_CONT_GETNPARAMS pGetNParamsU;
	P_CONT_GETPARAMDEFVALUE pGetParamDefValueU;
	P_CONT_HASRETVAL pHasRetValU;
	P_CONT_DECRREF pDecrRefU;
	DWORD dwF;
} ConvCallTab;

void CTableWrapEx::SetTableWrap(CBLContext* pTabCont)
{
	CTableWrapEx* pTableWrapEx;
	pTableWrapEx = new CTableWrapEx;

	DWORD old;
	VirtualProtect(((BYTE*)*((DWORD*)pTabCont)),0x100,PAGE_EXECUTE_READWRITE,&old);

	CSheetDoc mSheetDoc;
	dwCSheetDocVTable = *(DWORD*)&mSheetDoc;
	//*/
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTabCont)+0x06);
	pDecrRef = ConvCallTab.pDecrRefU;
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTableWrapEx)+0x06);
	P_CONT_DECRREF pD = ConvCallTab.pDecrRefU;
	DWORD dwDecrRef = *(DWORD*)&pD;
	((DWORD*)*((DWORD*)pTabCont))[0x06] = dwDecrRef;
	//*/

	//*/
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTabCont)+0x20);
	pCallAsFunc = ConvCallTab.pCallAsFuncU;
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTableWrapEx)+0x20);
	P_CONT_CALLASF pF = ConvCallTab.pCallAsFuncU;
	DWORD dwCallAsFunc = *(DWORD*)&pF;
	((DWORD*)*((DWORD*)pTabCont))[0x20] = dwCallAsFunc;
	//*/

	//*/
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTabCont)+0x1F);
	pCallAsProc = ConvCallTab.pCallAsProcU;
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTableWrapEx)+0x1F);
	P_CONT_CALLASP pP = ConvCallTab.pCallAsProcU;
	DWORD dwCallAsProc = *(DWORD*)&pP;
	((DWORD*)*((DWORD*)pTabCont))[0x1F] = dwCallAsProc;
	//*/

	//*/
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTabCont)+0x1C);
	pGetNParams = ConvCallTab.pGetNParamsU;
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTableWrapEx)+0x1C);
	P_CONT_GETNPARAMS pGP = ConvCallTab.pGetNParamsU;
	DWORD dwGetNParams = *(DWORD*)&pGP;
	((DWORD*)*((DWORD*)pTabCont))[0x1C] = dwGetNParams;
	//*/

	//*/
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTabCont)+0x1D);
	pGetParamDefValue = ConvCallTab.pGetParamDefValueU;
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTableWrapEx)+0x1D);
	P_CONT_GETPARAMDEFVALUE pGD = ConvCallTab.pGetParamDefValueU;
	DWORD dwGetParamDefValue = *(DWORD*)&pGD;
	((DWORD*)*((DWORD*)pTabCont))[0x1D] = dwGetParamDefValue;
	//*/

	//*/
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTabCont)+0x1E);
	pHasRetVal = ConvCallTab.pHasRetValU;
	ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTableWrapEx)+0x1E);
	P_CONT_HASRETVAL pHRV = ConvCallTab.pHasRetValU;
	DWORD dwHasRetVal = *(DWORD*)&pHRV;
	((DWORD*)*((DWORD*)pTabCont))[0x1E] = dwHasRetVal;
	//*/

	iMethNum_SourceTable = pTabCont->FindMethod("SourceTable");
	iMethNum_Options = pTabCont->FindMethod("Options");
	delete pTableWrapEx;

	CTableWrapExDbl* pTableWrapExDbl;
	pTableWrapExDbl = new CTableWrapExDbl;

	//*/
	CGroupContext* pGrCont;
	pGrCont = (CGroupContext*)(RUNTIME_CLASS(CGroupContext)->CreateObject());
	if(pGrCont)
	{
		VirtualProtect(((BYTE*)*((DWORD*)pGrCont)),0x100,PAGE_EXECUTE_READWRITE,&old);

		ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pGrCont)+0x1F);
		pCallAsProcDbl = ConvCallTab.pCallAsProcU;
		ConvCallTab.dwF = *(((DWORD*)*(DWORD*)pTableWrapExDbl)+0x1F);
		P_CONT_CALLASP pP = ConvCallTab.pCallAsProcU;
		DWORD dwCallAsProc = *(DWORD*)&pP;
		((DWORD*)*((DWORD*)pGrCont))[0x1F] = dwCallAsProc;

		delete pGrCont;
	}
	//*/

	delete pTableWrapExDbl;

	iCountStream = 0;
	CConfigCont::GetAllTypedItem(procGetAllTypedItem,0,ptDialog,0);
};

int CTableWrapExDbl::CallAsProc(int iMethNum,class CValue **ppValue)
{
	CString strMeth = this->GetMethodName(iMethNum,1);

	int ret = (this->*pCallAsProcDbl)(iMethNum, ppValue);

	if(0 != strMeth.CompareNoCase("Опции"))
		return ret;

	int size = GetSize();
	for (int i = 0; i < size; i++) {
		CBLContext* pCont = GetContext(i);
		if (!pCont) continue;

		int n = pCont->FindMethod(strMeth);
		if (n < 0) continue;

		CTableWrapEx* pTabl = (CTableWrapEx*)pCont;
		POSITION pos = pTabl->m_pSheetDocOut->GetFirstViewPosition();
		while(pos)
		{
			CSheetViewMy* pSheetView = (CSheetViewMy*)pTabl->m_pSheetDocOut->GetNextView(pos);
			pSheetView->OnInitialUpdate();
		}
	}

	return ret;
};

bool CInitTableWrap::Init()
{
#ifdef VK_1CPP_SourceTable
//	if (!pMainAddIn->Property["EnableTableSourceTable"])
//		return true;

	// перехват объекта Таблица
	CBLContext* pTablCont = CBLContext::CreateInstance("Table");
	if(pTablCont)
		CTableWrapEx::SetTableWrap(pTablCont);
#endif
	return true;
}
#endif

#ifdef ONECPP_ARTBEAR

/******************************************************************************************/
// CTableEx class implementation
/******************************************************************************************/

/*enum {
    procFromString,
    funcToString,
    funcIsNil,
    procSetNil,
    funcIsEqual,
    procNew,
    lastDBGUIDMethod
};*/

class CObjID CTableEx::ObjID;
bool CTableEx::bIsInit = false;

//class CParamDefs CTableEx::defFnNames;

IMPLEMENT_DYNCREATE(CTableEx, CBLContext);

static DWORD dwCSheetDocVTable = 0;
static int iMethNum_SourceTable = -1;
static int iMethNum_Options = -1;


CMapStringToPtr DocNamesArray1;
struct SDocNames1{
	DWORD id;
	CString strFolder;
};

int procGetAllTypedItem1(class CString &str,long l1,long l2,enum PageType pt)
{
	if(str.CollateNoCase("ModuleText") == 0)
		return 1;

	CMetaDataCont *pMD = GetMetaData();
	CMetaDataObj* pMDO = pMD->FindObject(l1);
	CString str1 = GetModuleFullName(l1, str, 0, pMD);
	str1.MakeUpper();

	SDocNames1 *pDocNames = NULL;
	pDocNames = new SDocNames1;
	pDocNames->id = l1;
	pDocNames->strFolder = str;
	DocNamesArray1.SetAt(str1,pDocNames);

	return 1;
}


int CTableEx::SetTable(class CValue **ppValue)
{
	// возвращает:
	// 0 - таблица установлена
	// 1 - необходим вызов штатной обработки
	// 2 - ошибка пути
	// 3 - ошибка имени таблицы
	// 4 - прочие ошибки
	CString strPath = ppValue[1]->GetString();
	CString strName = ppValue[0]->GetString();
	strPath = AllTrim(strPath);
	if(strPath.IsEmpty())
		return 1;

	strPath.MakeUpper();
	if(strPath.Right(4).CompareNoCase(".MXL") == 0)
	{
		*ppValue[0] = strPath;
		return 1;
	}

	int mdPos = strPath.Find("@MD");
	if (mdPos >= 0)
	{
		CString strPathTemp = strPath.Left(mdPos);
		strPath = CString("MD.Обработка.")+AllTrim(strPathTemp)+".Форма";
		strPath.MakeUpper();
	}

	if (strPath.Left(3).CompareNoCase("MD.") == 0) // внутри md
	{
		CString strDoc = strPath.Mid(3);
		SDocNames1 *pDocNames = NULL;
		if (!DocNamesArray1.Lookup(strDoc, (void*&)pDocNames))
			return 2;

		CApp7* pApp7 = (CApp7*) AfxGetApp();
		CProfile7* pProfile7 = pApp7->GetProps();
		CString Prop8 = pProfile7->GetStringProp(0x08); // полный путь к файлу 1Cv7.MD (с именем файла)
		CString strFull = "";
		strFull.Format("%s\\%s\\%s_Number%d\\WorkBook",Prop8,pDocNames->strFolder,pDocNames->strFolder,pDocNames->id);
		CWorkBookDoc* pDoc = (CWorkBookDoc*)CConfigCont::PathToDocument(strFull);
		if (!pDoc)
		{
			CString str;
			CTypedCont *pTypedCont;
			if(CConfigCont::IDToPath(pDocNames->id, pDocNames->strFolder, str, &pTypedCont, 0))
				pDoc = pTypedCont->GetWorkBook();
		}
		if (!pDoc)
			return 4;

		if (strName.IsEmpty())
			GetFirstTableName(pDoc, strName);

		CSheetDoc* pSheetDoc = (CSheetDoc*)pDoc->FindDocument(strName);
		if (!pSheetDoc)
			return 3;

		m_pSheetDocIn = pSheetDoc;
		SetPSheet();
		if(m_pSheetDocOut && (CTemplate7::GetDocumentID(m_pSheetDocOut) != 0))
			m_pSheetDocOut->UpdateAllViews(NULL, 8, NULL);
		return 0;
	}

	// из внешнего отчета
	CTemplate7* pTempl = CTemplate7::FromID(0xBA);
	if (!pTempl)
		return 4;

	POSITION pos = pTempl->GetFirstDocPosition();
	while (pos)
	{
		CWorkBookDoc* pDoc = (CWorkBookDoc*)pTempl->GetNextDoc(pos);
		if (!pDoc)
			continue;

		CString strSrc = pDoc->GetSourcePathName();
		if (strSrc.CompareNoCase(strPath) != 0)
			continue;

		if (strName.IsEmpty()) 
			GetFirstTableName(pDoc, strName);

		CSheetDoc* pSheetDoc = (CSheetDoc*)pDoc->FindDocument(strName);
		if (!pSheetDoc)
			return 3;

		m_pSheetDocIn = pSheetDoc;
		SetPSheet();
		if(m_pSheetDocOut && (CTemplate7::GetDocumentID(m_pSheetDocOut) != 0))
			m_pSheetDocOut->UpdateAllViews(NULL, 8, NULL);
		return 0;
	}

	pTempl = CTemplate7::FromID(0xA1);

	if (!pTempl)
		return 4;

	if (strName.IsEmpty())
		strName = "Moxel WorkPlace";

	COleStorage pOleStorage(NULL);
	CFileException excepFile;
	if (!pOleStorage.Open(strPath, CFile::shareExclusive, &excepFile))
		return 2;

	int res = 4;
	COleStreamFile * pOleStream = pOleStorage.OpenStream(CContainer::GetContentsStreamName(), CFile::shareExclusive, &excepFile);
	if (pOleStream)
	{
		DWORD StreamLen = pOleStream->GetLength();
		char* buf = (char*)malloc(StreamLen);
		pOleStream->Read(buf, StreamLen);
		CItemList list1;
		int n = 0;
		CString strStreamName = "";
		list1.LoadFromString(buf, &n);
		for(int j = list1.FindGenericItem("Moxcel.Worksheet", -1); j >= 0; j = list1.FindGenericItem("Moxcel.Worksheet", ++j))
		{
			CItem* pItem = (CItem*)list1.GetItemAt(j);
			if(pItem->WhatIsIt() != 1)
				continue;

			CItem* pItem1 = (CItem*)((CGenericItem*)pItem)->m_array.GetAt(1);
			CItem* pItem2 = (CItem*)((CGenericItem*)pItem)->m_array.GetAt(2);
			if((strName.CompareNoCase(pItem2->m_str) == 0) ||
				((pItem2->m_str.CompareNoCase("Moxel WorkPlace") == 0) &&
				 (strName.CompareNoCase("Таблица") == 0)))
			{
				strStreamName = pItem1->m_str;
			}
		}
		free(buf);
		pOleStorage.ReleaseStream(pOleStream, TRUE);
		if (!strStreamName.IsEmpty())
		{
			if (pOleStream = pOleStorage.OpenStream(strStreamName, CFile::shareExclusive, &excepFile))
			{
				CArchive ar(pOleStream, CArchive::load);
				if (m_pSheetDocIn)
				{
					// пытаемся очистить ранее созданные нами CSheetDoc
					if (CTemplate7::GetDocumentID(m_pSheetDocIn) == 0)
						delete m_pSheetDocIn;
				}
				m_pSheetDocIn = (CSheetDoc*)CSheetDoc::CreateObject();//new CSheetDoc;
//				CTemplate7::RegisterDocument(m_pSheetDocIn);
//				pTempl->AddDocument(m_pSheetDocIn);

				m_pSheetDocIn->DeleteContents();
				m_pSheetDocIn->Serialize(ar);

				SetPSheet();
				if (m_pSheetDocOut && (CTemplate7::GetDocumentID(m_pSheetDocOut) != 0))
					m_pSheetDocOut->UpdateAllViews(NULL, 8, NULL);

				CTemplate7::UnRegisterDocument(m_pSheetDocIn);
				pOleStorage.ReleaseStream(pOleStream, TRUE);
				res = 0;
			}
			else
				res = 4;
		}
		else
			res = 3;
	}
	pOleStorage.Release(TRUE);

	return res;
}

CTableEx::CTableEx()
{
	// перехват объекта Таблица
	pTabCont = CBLContext::CreateInstance("Table");
	iMethNum_SourceTable = pTabCont->FindMethod("SourceTable");
	iMethNum_Options = pTabCont->FindMethod("Options");
}

CTableEx::~CTableEx()
{
	pTabCont->DecrRef();
	//delete pTabCont;
}

// CBLContext implementation

int  CTableEx::CallAsFunc(int iMethNum,class CValue & rValue,class CValue * *ppValue)
{
    int ret = 0;
	if(iMethNum == iMethNum_SourceTable)
	{
		int res = SetTable(ppValue);
		int bCallExept = ppValue[2]->GetNumeric();
		rValue = res;

		if(bCallExept == 0)
			return S_OK;

		if(res == 0)
		{
			rValue = 1L;
			return S_OK;
		}
		else if(res != 1)
		{
			// 2 - ошибка пути
			// 3 - ошибка имени таблицы
			// 4 - прочие ошибки
			if(res == 2)
				RuntimeError("Неверно задан путь к исходной таблице!", mmRedErr);
			else if(res == 3)
				RuntimeError("Неверно задано имя исходной таблицы!", mmRedErr);
			else
				RuntimeError("Ошибка при установке исходной таблицы!", mmRedErr);
			return S_FALSE;
		}

		rValue = 2L;
		return pTabCont->CallAsProc(iMethNum, ppValue);
	}

	return pTabCont->CallAsFunc(iMethNum, rValue, ppValue);
}


int  CTableEx::CallAsProc(int iMethNum,class CValue * * ppValue)
{
    int ret = 0;
	if(iMethNum == iMethNum_SourceTable)
	{
		int res = SetTable(ppValue);
		int bCallExept = ppValue[2]->GetNumeric();
		if(bCallExept == 0)
			return S_OK;

		if(res == 0)
			return S_OK;
		else if(res != 1)
		{
			// 2 - ошибка пути
			// 3 - ошибка имени таблицы
			// 4 - прочие ошибки
			if(res == 2)
				RuntimeError("Неверно задан путь к исходной таблице!", mmRedErr);
			else if(res == 3)
				RuntimeError("Неверно задано имя исходной таблицы!", mmRedErr);
			else
				RuntimeError("Ошибка при установке исходной таблицы!", mmRedErr);
			return S_FALSE;
		}
	}
	//else if(strMeth.CompareNoCase("Опции") == 0)
	else if(iMethNum == iMethNum_Options)
	{
		int ret = pTabCont->CallAsProc(iMethNum, ppValue);

		POSITION pos = m_pSheetDocOut->GetFirstViewPosition();
		while(pos)
		{
			CSheetViewMy* pSheetView = (CSheetViewMy*)m_pSheetDocOut->GetNextView(pos);
			CSheetSelection pSel = *(pSheetView->GetTailSelection());
			int nPosVert = pSheetView->GetScrollPos(SB_VERT);
			int nPosHorz = pSheetView->GetScrollPos(SB_HORZ);
			pSheetView->OnInitialUpdate();
			pSheetView->ClearSelection();
			pSheetView->SelectArea(pSel);
			pSheetView->ScrollToPosition(nPosHorz,nPosVert);
		}

		return ret;
	}

	return pTabCont->CallAsProc(iMethNum, ppValue);
}


int  CTableEx::FindMethod(char const * lpMethodName)const
{
	return pTabCont->FindMethod(lpMethodName);
}

char const *  CTableEx::GetMethodName(int iMethodNum,int iMethodAlias)const
{
  return pTabCont->GetMethodName(iMethodNum, iMethodAlias);
}

int  CTableEx::GetNMethods(void)const
{
  return pTabCont->GetNMethods();
}

int  CTableEx::HasRetVal(int iMethodNum)const
{
	if(iMethodNum == iMethNum_SourceTable)
	{
		return 1;
	}
	
	return pTabCont->HasRetVal(iMethodNum);
}

int CTableEx::GetNParams(int iMethodNum)const
{
	if(iMethodNum == iMethNum_SourceTable)
	{
		return 3;
	}

	return pTabCont->GetNParams(iMethodNum);
}

int  CTableEx::GetParamDefValue(int iMethodNum,int iParamNum,class CValue * pDefValue)const
{	
	if(iMethodNum == iMethNum_SourceTable)
	{
		if(iParamNum == 1)
		{
			*pDefValue = "";
			return 1;
		}
		if(iParamNum == 2)
		{
			*pDefValue = 1;
			return 1;
		}
	}

	return pTabCont->GetParamDefValue(iMethodNum, iParamNum, pDefValue);
}



void  CTableEx::DecrRef(void)
{
	int aRefCount = m_RefCount;
	CSheetDoc* pSheetDoc = m_pSheetDocIn;

	//(this->*pDecrRef)();

	// пытаемся очистить ранее созданные нами CSheetDoc
	if((--aRefCount == 0) && pSheetDoc && (*(DWORD*)pSheetDoc == dwCSheetDocVTable) && (CTemplate7::GetDocumentID(pSheetDoc) == 0))
				delete pSheetDoc;

	CBLContext::DecrRef();
}

char const *  CTableEx::GetCode(void)const
{
  return pTabCont->GetCode();
}

int  CTableEx::GetDestroyUnRefd(void)const
{
  return pTabCont->GetDestroyUnRefd();
}

void  CTableEx::GetExactValue(class CValue & vParam)
{
	CBLContext::GetExactValue(vParam);
	pTabCont->GetExactValue(vParam);
}

class CObjID   CTableEx::GetID(void)const
{
	return ObjID;
}

class CBLContextInternalData *  CTableEx::GetInternalData(void)
{
	return pTabCont->GetInternalData();
}

long  CTableEx::GetTypeID(void)const
{
	return 100;
}

char const *  CTableEx::GetTypeString(void)const
{
	return "ТаблицаРасширенная";
}

class CType   CTableEx::GetValueType(void)const
{
	CType tType(100);	
	return tType;
}


void  CTableEx::IncrRef(void)
{
	CBLContext::IncrRef();
}

void  CTableEx::InitObject(class CType const & tType)
{
	CBLContext::InitObject(tType);
	pTabCont->InitObject(tType);

	if (!bIsInit)
	{
		bIsInit = true;

		CSheetDoc mSheetDoc;
		dwCSheetDocVTable = *(DWORD*)&mSheetDoc;

		CConfigCont::GetAllTypedItem(procGetAllTypedItem1,0,ptDialog,0);
	}
}

void  CTableEx::InitObject(char const * strName)
{
	CBLContext::InitObject(strName);
	pTabCont->InitObject(strName);
	if (!bIsInit)
	{
		bIsInit = true;

		CSheetDoc mSheetDoc;
		dwCSheetDocVTable = *(DWORD*)&mSheetDoc;

		CConfigCont::GetAllTypedItem(procGetAllTypedItem1,0,ptDialog,0);
	}
}

int  CTableEx::IsExactValue(void)const
{
	return pTabCont->IsExactValue();
}

int  CTableEx::IsOleContext(void)const
{
	return pTabCont->IsOleContext();
}

int  CTableEx::IsPropReadable(int iPropNum)const
{
	return pTabCont->IsPropReadable(iPropNum);
}

int  CTableEx::IsPropWritable(int iPropNum)const
{
	return pTabCont->IsPropWritable(iPropNum);
}

int  CTableEx::IsSerializable(void)
{
	return 0;
}

int  CTableEx::SaveToString(class CString & csStr)
{	
	return 0;
}

void  CTableEx::SelectByID(class CObjID cID,long lNum)
{
	//CBLContext::SelectByID(cID,lNum);
	pTabCont->SelectByID(cID,lNum);
}


int  CTableEx::GetNProps(void)const
{
	return pTabCont->GetNProps();
}

char const *  CTableEx::GetPropName(int A,int B)const
{	
	return pTabCont->GetPropName(A, B);
}

int  CTableEx::GetPropVal(int iPropNum,class CValue & rValue)const
{
	return pTabCont->GetPropVal(iPropNum, rValue);
}

int  CTableEx::SetPropVal(int iPropNum,class CValue const & vValue)
{
	return pTabCont->SetPropVal(iPropNum, vValue);
}

int  CTableEx::FindProp(char const * Name)const
{
	return pTabCont->FindProp(Name);
}

#endif
