#include "StdAfx.h"
#include "ElementContainer.h"
#include "Gate.h"
#include "Block.h"
#include "Tag.h"
#include "Inv.h"

CElementContainer::CElementContainer()
{
	ClearParsedContent();
	m_GateMap.RemoveAll();
	m_BlockMap.RemoveAll();
}

CElementContainer::~CElementContainer()
{
	POSITION pos = m_GateMap.GetStartPosition();
	CCommonObject *pObj = NULL;
	CString str;
	while(pos){
		m_GateMap.GetNextAssoc(pos, str, pObj);
		SAFE_DELETE(pObj);
	}
	m_GateMap.RemoveAll();
	pos = m_BlockMap.GetStartPosition();
	while(pos){
		m_BlockMap.GetNextAssoc(pos, str, pObj);
		SAFE_DELETE(pObj);
	}
	m_BlockMap.RemoveAll();
	pos = m_OthersMap.GetStartPosition();
	while(pos){
		m_OthersMap.GetNextAssoc(pos, str, pObj);;
		SAFE_DELETE(pObj);
	}
}

void CElementContainer::ClearParsedContent()
{
	m_RectIn = NULL;
	m_RectOut = NULL;
	m_gPath.Reset();
	m_gPathText.Reset();
	m_strFileToParse.Empty();
	m_strFileToParsePath.Empty();
	m_strFilename.Empty();
	m_strFilePath.Empty();
	m_strDisplayName.Empty();
	m_strOrigin.Empty();
	m_strType.Empty();
	m_nType = -1;
	//m_strOriginF.Empty();
}

TiXmlDocument* CElementContainer::GetDoc(CString strFilename)
{
	if(!strFilename.GetLength())
		return NULL;

	char *pBuffer = new char[MAX_PATH];
	wcstombs(pBuffer, strFilename.GetBuffer(), MAX_PATH-1);
	TiXmlDocument *pDocument = new TiXmlDocument(pBuffer);

	SAFE_DELETE_ARRAY(pBuffer);
	strFilename.ReleaseBuffer();

	if(!pDocument->LoadFile()){
		SAFE_DELETE(pDocument);
		return NULL;
	}
	else
		return pDocument;
}

bool CElementContainer::OpenProject(CString strProject)
{
	int nSlash = strProject.ReverseFind(92);
	m_strFileToParsePath = strProject.Mid(0, nSlash+1);
	m_strFileToParse = strProject.Mid(nSlash+1);
	TiXmlDocument *pProject = GetDoc(strProject);
	if(!pProject){
		return false;
	}
	TiXmlElement *pRoot = pProject->FirstChildElement();
	if(!pRoot){
		SAFE_DELETE(pProject);
		return false;
	}

	m_strDisplayName = (CString)pRoot->Attribute("display");
	m_strFilename = (CString)pRoot->Attribute("filename");


	CString strProjectPath = strProject.Mid(0, strProject.ReverseFind('\\')+1);
	OpenProjectSpecific(strProjectPath, 0);
	SAFE_DELETE(pProject);
	return true;
}

bool CElementContainer::OpenProjectSpecific(CString strFilename)
{
	if(!strFilename.GetLength())
		return false;
	ParseFile(strFilename);
	return true;
}

bool CElementContainer::OpenProjectSpecific(CString strElementName, CString strProjectPath)
{
	// reads specific elem from project when needed
	CString strContentPath = strProjectPath;
	strContentPath.Append(_T("Content\\"));
	CString strFilename = AssociateFile(strElementName, strContentPath);
	if(strFilename.GetLength()){
		ParseFile(strFilename);
		return true;
	}

	CString strGatesPath = strProjectPath;
	strGatesPath.Append(_T("Content\\Gates\\"));

	strFilename = AssociateFile(strElementName, strGatesPath);
	if(strFilename.GetLength()){
		ParseFile(strFilename);
		return true;
	}

	CString strBlocksPath = strProjectPath;
	strBlocksPath.Append(_T("Content\\Blocks\\"));
	strFilename = AssociateFile(strElementName, strBlocksPath);
	if(strFilename.GetLength()){
		ParseFile(strFilename);
		return true;
	}

	return false;
}

void CElementContainer::OpenProjectSpecific(CString strProjectPath, int nWhich)
{
	CString strGatePath = strProjectPath;
	strGatePath.Append(_T("Content\\Gates\\"));

	CString strBlockPath = strProjectPath;
	strBlockPath.Append(_T("Content\\Blocks\\"));

	switch(nWhich){
		case 0:
			ParseDir(strGatePath);
			ParseDir(strBlockPath);
			break;
		case 1:
			ParseDir(strGatePath);
			break;
		case 2:
			ParseDir(strBlockPath);
			break;
	}
}

CString CElementContainer::AssociateFile(CString strElementName, CString strPath)
{
	// tries to find specific element in strPath
	TCHAR curDir[MAX_PATH];
	::GetCurrentDirectory(MAX_PATH, curDir);

	::SetCurrentDirectory(strPath);
	CFileFind ff;
	bool bWorking = ff.FindFile(_T("*.xml"));
	TiXmlDocument *pDocument;
	CString strFilename;
	CString strName;
	while(bWorking){
		bWorking = ff.FindNextFileW();
		strFilename = strPath;
		strFilename.Append(ff.GetFileName());
		pDocument = GetDoc(strFilename);
		if(pDocument){
			TiXmlElement *pRoot = pDocument->FirstChildElement();
			if(pRoot){
				TiXmlElement *pElem = pRoot->FirstChildElement("NAME");
				if(pElem){
					const char* str = pElem->GetText();
					strName += str;
					if(strName == strElementName){
						SAFE_DELETE(pDocument);
						::SetCurrentDirectory(curDir);
						return strFilename;
					}
					else{
						strName.Empty();
					}
				}
			}
			SAFE_DELETE(pDocument);
		}
	}
	::SetCurrentDirectory(curDir);
	return CString();
}


void CElementContainer::ParseDir(CString strPath)
{
	TCHAR curDir[MAX_PATH];
	::GetCurrentDirectory(MAX_PATH, curDir);

	::SetCurrentDirectory(strPath);
	m_gPath.Reset();
	m_gPathText.Reset();
	CString gelemName = _T("");
	CString gelemType = _T("");
	int nIn, nOut;
	bool bOK = true;
	CRect *rectIn = NULL;
	CRect *rectOut = NULL;
	bool *bInvIn = NULL;
	bool *bInvOut = NULL;
	int nRecords;
	int nReadRecords = 0;
	int nType = -1;

	CString *strIns = NULL;
	CString *strOuts = NULL;

	CFileFind ff;
	CString strFilename;
	bool bWorking = ff.FindFile(_T("*.xml"));
	while(bWorking){
		nRecords = 0;
		nReadRecords = 0;
		m_gPath.Reset();
		m_gPathText.Reset();
		bWorking = ff.FindNextFileW();
		TRACE1("file: %s\n", ff.GetFileName());
		strFilename = strPath;
		strFilename.Append(ff.GetFileName());
		TiXmlDocument *pDocument = GetDoc(strFilename);
		if(pDocument){
			TiXmlElement* root = pDocument->FirstChildElement();
			if(root){
				// Type of GElement
				TiXmlElement* Type = root->FirstChildElement("TYPE");
				if(Type){
					
					gelemType += Type->GetText();
				}
				else
					bOK = false;

				// Name of GElement
				TiXmlElement* Name = root->FirstChildElement("NAME");
				if(Name){
					if(Name){
						gelemName += Name->GetText();
					}
				}
				else
					bOK = false;

				// Drawing information
				TiXmlElement *Drawing = root->FirstChildElement("DRAWING");
				if(Drawing){
					TiXmlElement *Body = Drawing->FirstChildElement("BODY");
					if(Body){
						const char* sRecords = Body->Attribute("nRecords", &nRecords);
						int x1, y1, x2, y2, x3, y3, x4, y4;
						int rx1, ry1, rx2, ry2;
						const char* text;
						CString actionType; // type of performed drawing action

						TiXmlElement *bodyparts = Body->FirstChildElement();
						while(bodyparts){
							actionType.Empty();
							text = bodyparts->GetText();
							actionType += text;
							if(actionType.CompareNoCase(_T("line")) == 0){
								// Add line to m_gPath
								bodyparts->Attribute("x1", &x1);
								bodyparts->Attribute("y1", &y1);
								bodyparts->Attribute("x2", &x2);
								bodyparts->Attribute("y2", &y2);
								m_gPath.AddLine(x1, y1, x2, y2);
							}
							else if(actionType.CompareNoCase(_T("bezier")) == 0){
								// Add bezier to m_gPath
								bodyparts->Attribute("x1", &x1);
								bodyparts->Attribute("y1", &y1);
								bodyparts->Attribute("x2", &x2);
								bodyparts->Attribute("y2", &y2);
								bodyparts->Attribute("x3", &x3);
								bodyparts->Attribute("y3", &y3);
								bodyparts->Attribute("x4", &x4);
								bodyparts->Attribute("y4", &y4);
								m_gPath.AddBezier(x1, y1, x2, y2, x3, y3, x4, y4);
							}
							else if(actionType.CompareNoCase(_T("arc")) == 0){
								// Add arc to m_gPath
								bodyparts->Attribute("rx1", &rx1);
								bodyparts->Attribute("ry1", &ry1);
								bodyparts->Attribute("rx2", &rx2);
								bodyparts->Attribute("ry2", &ry2);
								int nFrom, nTo;
								bodyparts->Attribute("nFrom", &nFrom);
								bodyparts->Attribute("nTo", &nTo);
								Rect r(rx1, ry1, rx2, ry2);
								m_gPath.AddArc(r, (REAL)nFrom, (REAL)nTo);
							}
							else if(actionType.CompareNoCase(_T("ellipse")) == 0){
								// Add ellipse to m_gPath
								bodyparts->Attribute("x1", &x1);
								bodyparts->Attribute("y1", &y1);
								bodyparts->Attribute("x2", &x2);
								bodyparts->Attribute("y2", &y2);
								m_gPath.AddEllipse(x1, y1, x2, y2); 
							}
							else if(actionType.CompareNoCase(_T("closefigure")) == 0){
								m_gPath.CloseAllFigures();
							}
							else{
								TRACE(_T("couldn't recognize action!\n"));
								bOK = false;
							}

							bodyparts = bodyparts->NextSiblingElement();
							nReadRecords++;
						}
						if(nReadRecords != nRecords){
							TRACE(_T("Read draw records don't match declared count!!!\n"
								));
							bOK = false;
						}
						nReadRecords = 0;
						m_gPath.CloseAllFigures();

						// Output Drawing information
						TiXmlElement *Outputs = Drawing->FirstChildElement("OUTPUTS");
						if(Outputs){
							Outputs->Attribute("nOut", &nOut);
							Outputs->Attribute("nRecords", &nRecords);
							bInvOut = new bool[nOut];
							strOuts = new CString[nOut];
							TiXmlElement *outputparts = Outputs->FirstChildElement();
							while(outputparts){
								actionType.Empty();
								text = outputparts->GetText();
								actionType += text;
								if(actionType.CompareNoCase(_T("line")) == 0){
									// Add line to m_gPath
									outputparts->Attribute("x1", &x1);
									outputparts->Attribute("y1", &y1);
									outputparts->Attribute("x2", &x2);
									outputparts->Attribute("y2", &y2);
									m_gPath.AddLine(x1, y1, x2, y2);
								}
								else if(actionType.CompareNoCase(_T("closefigure")) == 0){
									m_gPath.CloseAllFigures();
								}
								else if(actionType.CompareNoCase(_T("arc")) == 0){
									outputparts->Attribute("rx1", &rx1);
									outputparts->Attribute("ry1", &ry1);
									Rect Inv(rx1-4,ry1-4,8,8);
									m_gPath.AddArc(Inv, 0,360);
								}
								else if(actionType.CompareNoCase(_T("text")) == 0){
									int nPos;
									CString text;
									const char *cText = outputparts->Attribute("text");
									text += cText;
									outputparts->Attribute("pos", &nPos);
									strOuts[nPos] = text;
								}
								else{
									TRACE(_T("Unrecognized output action\n"));
									bOK = false;
								}
								outputparts = outputparts->NextSiblingElement();
								nReadRecords++;
							}
							if(nReadRecords != nRecords){
								TRACE(_T("Read output records don't match declared count!!!\n"));
								bOK = false;
							}
						}
						m_gPath.CloseAllFigures();
						nReadRecords = 0;

						// Input Drawing information
						TiXmlElement *Inputs = Drawing->FirstChildElement("INPUTS");
						if(Inputs){
							TiXmlElement *inputparts = Inputs->FirstChildElement();
							Inputs->Attribute("nIn", &nIn);
							Inputs->Attribute("nRecords", &nRecords);
							bInvIn = new bool[nIn];
							strIns = new CString[nIn];
							while(inputparts){
								actionType.Empty();
								text = inputparts->GetText();
								actionType += text;
								if(actionType.CompareNoCase(_T("line")) == 0){
									// Add line to m_gPath
									inputparts->Attribute("x1", &x1);
									inputparts->Attribute("y1", &y1);
									inputparts->Attribute("x2", &x2);
									inputparts->Attribute("y2", &y2);
									m_gPath.AddLine(x1, y1, x2, y2);
								}
								else if(actionType.CompareNoCase(_T("closefigure")) == 0){
									m_gPath.CloseAllFigures();
								}
								else if(actionType.CompareNoCase(_T("arc")) == 0){
									inputparts->Attribute("rx1", &rx1);
									inputparts->Attribute("ry1", &ry1);
									Rect Inv(rx1,ry1,8,8);
									m_gPath.AddArc(Inv, 0,360);
								}
								else if(actionType.CompareNoCase(_T("text")) == 0){
									int nPos;
									CString text;
									const char *cText = inputparts->Attribute("text");
									text += cText;
									inputparts->Attribute("pos", &nPos);
									strIns[nPos] = text;
								}
								else{
									TRACE(_T("Unrecognized input action\n"));
									bOK = false;
								}

								inputparts = inputparts->NextSiblingElement();
								nReadRecords++;
							}
							if(nReadRecords != nRecords){
								TRACE(_T("Read input records don't match declared count!!!\n"));
								bOK = false;
							}
						}
						m_gPath.CloseAllFigures();
						nReadRecords = 0;
					}
				}
				// Other information
				TiXmlElement *objInfo = root->FirstChildElement("COBJINFO");
				if(objInfo){
					TiXmlElement *outRect = objInfo->FirstChildElement("OUTPUTRECT");
					// Add rectangle of the output port
					if(outRect){
						rectOut = new CRect[nOut];
						int x1, y1, inv;
						outRect->Attribute("nRecords", &nRecords);
						nReadRecords = 0;
						TiXmlElement *outputPart = outRect->FirstChildElement("OUTPUT");
						while(outputPart && nRecords > nReadRecords){
							rectOut[nReadRecords].SetRect(0,0,8,8);
							outputPart->Attribute("x1", &x1);
							outputPart->Attribute("y1", &y1);
							outputPart->Attribute("inv", &inv);
							bInvOut[nReadRecords] = (bool)inv;
							rectOut[nReadRecords++].OffsetRect(x1-4, y1-4);
							outputPart = outputPart->NextSiblingElement();
						}
						if(nReadRecords != nRecords){
							TRACE(_T("Read output records don't match declared count!!!\n"));
							bOK = false;
						}
					}
					TiXmlElement *inRect = objInfo->FirstChildElement("INPUTRECT");
					// Add rectangle of the output port
					if(inRect){
						rectIn = new CRect[nIn];
						int x1, y1, inv;
						inRect->Attribute("nRecords", &nRecords);
						nReadRecords = 0;
						TiXmlElement *inputPart = inRect->FirstChildElement("INPUT");
						while(inputPart && nRecords > nReadRecords){
							rectIn[nReadRecords].SetRect(0,0,8,8);
							inputPart->Attribute("x1", &x1);
							inputPart->Attribute("y1", &y1);
							inputPart->Attribute("inv", &inv);
							bInvIn[nReadRecords] = (bool)inv;
							rectIn[nReadRecords++].OffsetRect(x1-4, y1-4);
							inputPart = inputPart->NextSiblingElement();
						}
						if(nReadRecords != nRecords){
							TRACE(_T("Read input records don't match declared count!!!\n"));
							bOK = false;
						}
					}
					TiXmlElement *blockInfo = objInfo->FirstChildElement("BLOCKINFO");
					if(blockInfo){
						/////////////////////////////////////////////////////////////
						/////////////////////////////////////////////////////////////
						/////////////////////////////////////////////////////////////
						/////////////////////////////////////////////////////////////
						/////////////////////////////////////////////////////////////
					}
				}
			}
			else{
				bOK = false;
			}
			if(bOK){
				if(gelemType.CompareNoCase(_T("Gate")) == 0){
					m_GateMap[gelemName] = new CGate(nIn, nOut, CPoint(0,0), gelemName, (CStringA)gelemName, &m_gPath, rectIn, rectOut, bInvIn, bInvOut);
				}
				else if(gelemType.CompareNoCase(_T("Block")) == 0){
					m_BlockMap[gelemName] = new CBlock(nIn, nOut, strIns, strOuts, gelemName, (CStringA)gelemName, CPoint(0,0), &m_gPath, NULL, rectIn, rectOut, bInvIn, bInvOut);
				}
			}
			else{
				TRACE1("Couldn't read file %s correctly!\n", ff.GetFileName());
			}
			//SAFE_DELETE_ARRAY(rectIn);
			//SAFE_DELETE_ARRAY(rectOut);
			SAFE_DELETE_ARRAY(bInvOut);
			SAFE_DELETE_ARRAY(bInvIn);

			SAFE_DELETE_ARRAY(strIns);
			SAFE_DELETE_ARRAY(strOuts);
			
			bOK = true;
			gelemName = _T("");
			gelemType = _T("");

			SAFE_DELETE(pDocument);
		}
		
	}
	::SetCurrentDirectory(curDir);
}


bool CElementContainer::OpenAppSpecific(CString strElemName)
{
	CString strGatePath = theApp.m_strAppPath;
	strGatePath.Append(_T("Additional\\Gates\\"));

	CString strBlockPath = theApp.m_strAppPath;
	strBlockPath.Append(_T("Additional\\Blocks\\"));

	// opens app specific elem
	CString strFile = AssociateFile(strElemName, theApp.m_strAppPath);
	if(strFile.GetLength()){
		ParseFile(strFile);
		return true;
	}
	strFile = AssociateFile(strElemName, strGatePath);
	if(strFile.GetLength()){
		ParseFile(strFile);
		return true;
	}
	strFile = AssociateFile(strElemName, strBlockPath);
	if(strFile.GetLength()){
		ParseFile(strFile);
		return true;
	}
	return false;
}

void CElementContainer::OpenAppSpecific(CString strAppPath, int nWhich)
{
	CString strGatePath = strAppPath;
	strGatePath.Append(_T("Additional\\Gates\\"));

	CString strBlockPath = strAppPath;
	strBlockPath.Append(_T("Additional\\Blocks\\"));

	switch(nWhich){
		case 0:
			ParseDir(strGatePath);
			ParseDir(strBlockPath);
			break;
		case 1:
			ParseDir(strGatePath);
			break;
		case 2:
			ParseDir(strBlockPath);
			break;
	}
	m_OthersMap[_T("InTag")] = new CTag(CPoint(0,0), _T("InTag"), true);
	m_OthersMap[_T("OutTag")] = new CTag(CPoint(0,0), _T("OutTag"), false);
	m_OthersMap[_T("Invertor")] = new CInv(CPoint(0,0), _T("Invertor"));
}

bool CElementContainer::ContainsElement(CString strElementName)
{
	if(!strElementName.GetLength())	// !!temp!! - for wire
		return false;
	if(m_GateMap.PLookup(strElementName) || m_BlockMap.PLookup(strElementName) || m_OthersMap.PLookup(strElementName))
		return true;
	return false;
}

bool CElementContainer::CanAppContainElement(CString strElementName)
{
	// or in app directory?
	if(strElementName == _T("InTag") || strElementName == _T("OutTag") || strElementName == _T("Invertor"))
		return true;
	CString strApp = theApp.m_strAppPath;
	strApp.Append(_T("Additional\\"));

	CString strAppFile = AssociateFile(strElementName, strApp);
	if(strAppFile.GetLength())
		return true;
	CString strAppGates = strApp + _T("Gates\\");
	strAppFile = AssociateFile(strElementName, strAppGates);
	if(strAppFile.GetLength())
		return true;

	strApp.Append(_T("Blocks\\"));
	strAppFile = AssociateFile(strElementName, strApp);
	if(strAppFile.GetLength())
		return true;
	return false;
}

bool CElementContainer::CanProContainElement(CString strElementName)
{
	CString strPro = theApp.m_pOpenedProjectDoc->m_ProjectDoc.m_strProjectPath;
	strPro.Append(_T("Content\\"));

	// is element in project directory?
	CString strProFile = AssociateFile(strElementName, strPro);
	if(strProFile.GetLength())
		return true;

	CString strProGates = strPro + _T("Gates\\");
	strProFile = AssociateFile(strElementName, strProGates);
	if(strProFile.GetLength())
		return true;

	strPro.Append(_T("Blocks\\"));
	strProFile = AssociateFile(strElementName, strPro);
	if(strProFile.GetLength())
		return true;
	return false;
}

bool CElementContainer::CanContainElement(CString strElementName)
{
	if(CanProContainElement(strElementName) || CanAppContainElement(strElementName))
		return true;
	return false;
}

CCommonObject* CElementContainer::GetCommonObject(CString strElement)
{
	CMap<CString, LPCTSTR, CCommonObject*, CCommonObject*>::CPair *pObj = m_GateMap.PLookup(strElement);
	if(pObj)
		return pObj->value;

	pObj = m_BlockMap.PLookup(strElement);
	if(pObj)
		return pObj->value;

	pObj = m_OthersMap.PLookup(strElement);
	if(pObj)
		return pObj->value;

	return NULL;
}

bool CElementContainer::OpenFile(CString strFilename, CString strPath)
{
	return false;
}

void CElementContainer::ParseFile(CString strFile)
{
	m_gPath.Reset();
	m_gPathText.Reset();
	CString gelemName = _T("");
	CString gelemType = _T("");
	int nIn = 0;
	int nOut = 0;
	bool bOK = true;
	CRect *rectIn = NULL;
	CRect *rectOut = NULL;
	bool *bInvIn = NULL;
	bool *bInvOut = NULL;
	int nRecords;
	int nReadRecords = 0;
	int nType = -1;

	CString *strIns = NULL;
	CString *strOuts = NULL;

	nRecords = 0;
	nReadRecords = 0;
	m_gPath.Reset();
	m_gPathText.Reset();

	TiXmlDocument *pDocument = GetDoc(strFile);
	if(pDocument){
		TiXmlElement* root = pDocument->FirstChildElement();
		if(root){
			// Type of GElement
			TiXmlElement* Type = root->FirstChildElement("TYPE");
			if(Type){
				gelemType += Type->GetText();
			}
			else
				bOK = false;

			// Name of GElement
			TiXmlElement* Name = root->FirstChildElement("NAME");
			if(Name){
				if(Name){
					gelemName += Name->GetText();
				}
			}
			else
				bOK = false;

			// Drawing information
			TiXmlElement *Drawing = root->FirstChildElement("DRAWING");
			if(Drawing){
				TiXmlElement *Body = Drawing->FirstChildElement("BODY");
				if(Body){
					const char* sRecords = Body->Attribute("nRecords", &nRecords);
					int x1, y1, x2, y2, x3, y3, x4, y4;
					int rx1, ry1, rx2, ry2;
					const char* text;
					CString actionType; // type of performed drawing action

					TiXmlElement *bodyparts = Body->FirstChildElement();
					while(bodyparts){
						actionType.Empty();
						text = bodyparts->GetText();
						actionType += text;
						if(actionType.CompareNoCase(_T("line")) == 0){
							// Add line to m_gPath
							bodyparts->Attribute("x1", &x1);
							bodyparts->Attribute("y1", &y1);
							bodyparts->Attribute("x2", &x2);
							bodyparts->Attribute("y2", &y2);
							m_gPath.AddLine(x1, y1, x2, y2);
						}
						else if(actionType.CompareNoCase(_T("bezier")) == 0){
							// Add bezier to m_gPath
							bodyparts->Attribute("x1", &x1);
							bodyparts->Attribute("y1", &y1);
							bodyparts->Attribute("x2", &x2);
							bodyparts->Attribute("y2", &y2);
							bodyparts->Attribute("x3", &x3);
							bodyparts->Attribute("y3", &y3);
							bodyparts->Attribute("x4", &x4);
							bodyparts->Attribute("y4", &y4);
							m_gPath.AddBezier(x1, y1, x2, y2, x3, y3, x4, y4);
						}
						else if(actionType.CompareNoCase(_T("arc")) == 0){
							// Add arc to m_gPath
							bodyparts->Attribute("rx1", &rx1);
							bodyparts->Attribute("ry1", &ry1);
							bodyparts->Attribute("rx2", &rx2);
							bodyparts->Attribute("ry2", &ry2);
							int nFrom, nTo;
							bodyparts->Attribute("nFrom", &nFrom);
							bodyparts->Attribute("nTo", &nTo);
							Rect r(rx1, ry1, rx2, ry2);
							m_gPath.AddArc(r, (REAL)nFrom, (REAL)nTo);
						}
						else if(actionType.CompareNoCase(_T("ellipse")) == 0){
							// Add ellipse to m_gPath
							bodyparts->Attribute("x1", &x1);
							bodyparts->Attribute("y1", &y1);
							bodyparts->Attribute("x2", &x2);
							bodyparts->Attribute("y2", &y2);
							m_gPath.AddEllipse(x1, y1, x2, y2); 
						}
						else if(actionType.CompareNoCase(_T("closefigure")) == 0){
							m_gPath.CloseAllFigures();
						}
						else{
							TRACE(_T("couldn't recognize action!\n"));
							bOK = false;
						}

						bodyparts = bodyparts->NextSiblingElement();
						nReadRecords++;
					}
					if(nReadRecords != nRecords){
						TRACE(_T("Read draw records don't match declared count!!!\n"
							));
						bOK = false;
					}
					nReadRecords = 0;
					m_gPath.CloseAllFigures();

					// Output Drawing information
					TiXmlElement *Outputs = Drawing->FirstChildElement("OUTPUTS");
					if(Outputs){
						Outputs->Attribute("nOut", &nOut);
						Outputs->Attribute("nRecords", &nRecords);
						rectOut = new CRect[nOut];
						bInvOut = new bool[nOut];
						strOuts = new CString[nOut];
						TiXmlElement *outputparts = Outputs->FirstChildElement();
						while(outputparts){
							actionType.Empty();
							text = outputparts->GetText();
							actionType += text;
							if(actionType.CompareNoCase(_T("line")) == 0){
								// Add line to m_gPath
								outputparts->Attribute("x1", &x1);
								outputparts->Attribute("y1", &y1);
								outputparts->Attribute("x2", &x2);
								outputparts->Attribute("y2", &y2);
								m_gPath.AddLine(x1, y1, x2, y2);
							}
							else if(actionType.CompareNoCase(_T("closefigure")) == 0){
								m_gPath.CloseAllFigures();
							}
							else if(actionType.CompareNoCase(_T("arc")) == 0){
								outputparts->Attribute("rx1", &rx1);
								outputparts->Attribute("ry1", &ry1);
								Rect Inv(rx1-4,ry1-4,8,8);
								m_gPath.AddArc(Inv, 0,360);
							}
							else if(actionType.CompareNoCase(_T("text")) == 0){
								int nPos;
								CString text;
								const char *cText = outputparts->Attribute("text");
								text += cText;
								outputparts->Attribute("pos", &nPos);
								strOuts[nPos] = text;
							}
							else{
								TRACE(_T("Unrecognized output action\n"));
								bOK = false;
							}
							outputparts = outputparts->NextSiblingElement();
							nReadRecords++;
						}
						if(nReadRecords != nRecords){
							TRACE(_T("Read output records don't match declared count!!!\n"));
							bOK = false;
						}
					}
					m_gPath.CloseAllFigures();
					nReadRecords = 0;

					// Input Drawing information
					TiXmlElement *Inputs = Drawing->FirstChildElement("INPUTS");
					if(Inputs){
						TiXmlElement *inputparts = Inputs->FirstChildElement();
						Inputs->Attribute("nIn", &nIn);
						Inputs->Attribute("nRecords", &nRecords);
						bInvIn = new bool[nIn];
						strIns = new CString[nIn];
						while(inputparts){
							actionType.Empty();
							text = inputparts->GetText();
							actionType += text;
							if(actionType.CompareNoCase(_T("line")) == 0){
								// Add line to m_gPath
								inputparts->Attribute("x1", &x1);
								inputparts->Attribute("y1", &y1);
								inputparts->Attribute("x2", &x2);
								inputparts->Attribute("y2", &y2);
								m_gPath.AddLine(x1, y1, x2, y2);
							}
							else if(actionType.CompareNoCase(_T("closefigure")) == 0){
								m_gPath.CloseAllFigures();
							}
							else if(actionType.CompareNoCase(_T("arc")) == 0){
								inputparts->Attribute("rx1", &rx1);
								inputparts->Attribute("ry1", &ry1);
								Rect Inv(rx1,ry1,8,8);
								m_gPath.AddArc(Inv, 0,360);
							}
							else if(actionType.CompareNoCase(_T("text")) == 0){
								int nPos;
								CString text;
								const char *cText = inputparts->Attribute("text");
								text += cText;
								inputparts->Attribute("pos", &nPos);
								strIns[nPos] = text;
							}
							else{
								TRACE(_T("Unrecognized input action\n"));
								bOK = false;
							}

							inputparts = inputparts->NextSiblingElement();
							nReadRecords++;
						}
						if(nReadRecords != nRecords){
							TRACE(_T("Read input records don't match declared count!!!\n"));
							bOK = false;
						}
					}
					m_gPath.CloseAllFigures();
					nReadRecords = 0;
				}
			}
			// Other information
			TiXmlElement *objInfo = root->FirstChildElement("COBJINFO");
			if(objInfo){
				TiXmlElement *outRect = objInfo->FirstChildElement("OUTPUTRECT");
				// Add rectangle of the output port
				if(outRect){
					rectOut = new CRect[nOut];
					int x1, y1, inv;
					outRect->Attribute("nRecords", &nRecords);
					nReadRecords = 0;
					TiXmlElement *outputPart = outRect->FirstChildElement("OUTPUT");
					while(outputPart && nRecords > nReadRecords){
						rectOut[nReadRecords].SetRect(0,0,8,8);
						outputPart->Attribute("x1", &x1);
						outputPart->Attribute("y1", &y1);
						outputPart->Attribute("inv", &inv);
						bInvOut[nReadRecords] = (bool)inv;
						rectOut[nReadRecords++].OffsetRect(x1-4, y1-4);
						outputPart = outputPart->NextSiblingElement();
					}
					if(nReadRecords != nRecords){
						TRACE(_T("Read output records don't match declared count!!!\n"));
						bOK = false;
					}
				}
				TiXmlElement *inRect = objInfo->FirstChildElement("INPUTRECT");
				// Add rectangle of the output port
				if(inRect){
					rectIn = new CRect[nIn];
					int x1, y1, inv;
					inRect->Attribute("nRecords", &nRecords);
					nReadRecords = 0;
					TiXmlElement *inputPart = inRect->FirstChildElement("INPUT");
					while(inputPart && nRecords > nReadRecords){
						rectIn[nReadRecords].SetRect(0,0,8,8);
						inputPart->Attribute("x1", &x1);
						inputPart->Attribute("y1", &y1);
						inputPart->Attribute("inv", &inv);
						bInvIn[nReadRecords] = (bool)inv;
						rectIn[nReadRecords++].OffsetRect(x1-4, y1-4);
						inputPart = inputPart->NextSiblingElement();
					}
					if(nReadRecords != nRecords){
						TRACE(_T("Read input records don't match declared count!!!\n"));
						bOK = false;
					}
				}
				TiXmlElement *blockInfo = objInfo->FirstChildElement("BLOCKINFO");
				if(blockInfo){
					/////////////////////////////////////////////////////////////
					/////////////////////////////////////////////////////////////
					/////////////////////////////////////////////////////////////
					/////////////////////////////////////////////////////////////
					/////////////////////////////////////////////////////////////
				}
			}
		}
		else{
			bOK = false;
		}
		if(bOK){
			if(gelemType.CompareNoCase(_T("Gate")) == 0){
				m_GateMap[gelemName] = new CGate(nIn, nOut, CPoint(0,0), gelemName, (CStringA)gelemName, &m_gPath, rectIn, rectOut, bInvIn, bInvOut);
			}
			else if(gelemType.CompareNoCase(_T("Block")) == 0){
				m_BlockMap[gelemName] = new CBlock(nIn, nOut, strIns, strOuts, gelemName, (CStringA)gelemName, CPoint(0,0), &m_gPath, NULL, rectIn, rectOut, bInvIn, bInvOut);
			}
		}
		else{
			MessageBox(AfxGetMainWnd()->m_hWnd, _T("Couldn't read file correctly!"), _T("Error"), MB_ICONERROR);
			return;
			//TRACE1("Couldn't read file %s correctly!\n", ff.GetFileName());
		}
		SAFE_DELETE_ARRAY(strIns);
		//SAFE_DELETE(strOuts);
		//SAFE_DELETE(rectIn);
		//SAFE_DELETE(rectOut);
		SAFE_DELETE(bInvIn);
		SAFE_DELETE(bInvOut);
		bOK = true;
		gelemName = _T("");
		gelemType = _T("");

		SAFE_DELETE(pDocument);
	}
	
}