Click here to Skip to main content
15,897,519 members
Articles / Mobile Apps

The StateWizard VC++ Add-in and Engine with Source Code

Rate me:
Please Sign up or sign in to vote.
4.73/5 (24 votes)
26 Mar 2009CPOL12 min read 191K   2.8K   132  
A cross-platform state-oriented application framework and a ClassWizard-like round-trip UML dynamic modeling/development tool that runs in popular IDEs. Aims at providing concurrent, distributed, and real-time application development tools for Win32/Linux
/**********************************************************************
UML StateWizard provides its software under the LGPL License and 
zlib/libpng License.

Email us at info@intelliwizard.com for any information, suggestions and 
feature requestions.

Home Page: http://www.intelliwizard.com
*************************************************************************/

// StateTreeStateParse.cpp : Implementation of CStateTreeCtrl
#include "stdafx.h"
#include "StateTreeCtrl.h"

/*
#include "AddAppDlg.h"
#include "AddEventDlg.h"
#include "CreateEventIdFileDlg.h"
#include "StateChartDlg.h"
#include "EventChange.h"
#include ".\statetreectrl.h"


#pragma comment(lib, "comctl32.lib")
*/

// CStateTreeCtrl
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif


// The group (s_AppName, s_ClassName, s_HdrTreeNode) to keep track of app,class header file node.
static CString s_AppName, s_ClassName;
static HTREEITEM s_HdrFileTreeNode=NULL;

///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Update state tree when the modified file is saved
// INPUT:  1) hItem: Handle of tree item which corresponds to saved file
//         2) hParent: Handle of corresponding project node item
//         3) sFilePath: Full path of saved file name
// OUTPUT: 1) TRUE: 2)FALSE
// NOTE: Search m_tagDBIndex to get indicated tag database item which is relative to saved
//		 file. Update corresponding database item and delete tree item in state tree. Then,
//	     Insert new tree item under relative project tree item.	
///////////////////////////////////////////////////////////////////////////////////////////
BOOL CStateTreeCtrl::UpdateStateTree(HTREEITEM hItem, HTREEITEM hProject, LPCTSTR sFilePath)
{	
	//Clear list to store the file path of event id list
	m_EventIdPathList.RemoveAll();

	TAG_DB_INDEX_T* pDBIndexItem;
	TAG_DB_FILE_INFO_T* pDBFileItem;
	TAG_DB_FUNC_INFO_T* pDBFuncItem;
	CString sPrjName = tree.GetItemText(hProject);
	sPrjName.Replace(" application(s)", NULL);
	sPrjName.TrimLeft();
	sPrjName.TrimRight();

	// Get modified project tag database item
	int nPrjSeqNum = 0;
	for (nPrjSeqNum = 0; nPrjSeqNum < m_tagDBIndex.GetSize(); nPrjSeqNum++)
	{
		pDBIndexItem = (TAG_DB_INDEX_T*)m_tagDBIndex[nPrjSeqNum];

		if (sPrjName.CompareNoCase(pDBIndexItem->sPrjName) == 0)
			break;
	}

	pDBFileItem = pDBIndexItem->pDBFile;	
	// Clear memory of previous record
	while (true)
	{
		if (NULL == pDBFileItem)
			break;
		if (!stricmp(sFilePath, pDBFileItem->sFilePath))
			break;
		pDBFileItem = (TAG_DB_FILE_INFO_T*)pDBFileItem->pNextFile;
	}
	pDBFuncItem = pDBFileItem->pFuncList;

	if (pDBFuncItem != NULL)
	{
		while (true)
		{
			if (NULL == pDBFuncItem)
				break;

			TAG_DB_FUNC_INFO_T* pDelItem = pDBFuncItem;
			pDBFuncItem = (TAG_DB_FUNC_INFO_T*)pDBFuncItem->pNextFunction;
			delete(pDelItem->key);
			delete(pDelItem->paramNameList);
			delete(pDelItem);
		}
		pDBFileItem->pFuncList = NULL;
	}

	if (tree.GetItemData(hItem) & STATE_TREE_APPLICATION_MASK)
	{
		CString sAppName = tree.GetItemText(hItem);
		APP_FILE_INFO_T* pAppFileItem = (APP_FILE_INFO_T*)m_appSrcHdrFiles[nPrjSeqNum];

		while (true)
		{
			if (NULL == pAppFileItem)
				break;

			if (!sAppName.Compare(pAppFileItem->sAppName))
			{
				if (pAppFileItem->sHdrFilePath != NULL)
				{
					if (!stricmp(pAppFileItem->sHdrFilePath, sFilePath))
					{
						delete(pAppFileItem->sHdrFilePath);
						pAppFileItem->sHdrFilePath = NULL;
					}
				}
				if (pAppFileItem->sSrcFilePath != NULL)
				{
					if (!stricmp(pAppFileItem->sSrcFilePath, sFilePath))
					{
						delete(pAppFileItem->sSrcFilePath);
						pAppFileItem->sSrcFilePath = NULL;
					}
				}
				break;
			}
			pAppFileItem = (APP_FILE_INFO_T*)pAppFileItem->pNextApp;
		}
	}
	tree.SelectItem(hProject);

	CStdioFile OpenedFile;		
	if (!OpenedFile.Open(sFilePath, CFile::modeRead| CFile::typeText ))
	{
		// File exists in dsp file but does not exist in disk
#ifdef _DEBUG
		afxDump << "failure in create tag db: open a file\n";
#endif				
		return FALSE;
	}	
	UCHAR nCommentFlag = NO_COMMENTS_STATE; // flag used to distinguish whether in code line or comments
	UCHAR nTagDBFlag = TAG_DB_CLASS_BEGIN_STATE; 
	UCHAR nReverseStateTreeFlag = TREE_GENERATION_BEGIN_STATE; // flag used in marking process status in generating state tree
	CString sCurrentLine = ""; // current line 
	CString sPrefixLine = ""; 
	CString sClassHead = "";
	CStringList ClassNameList;
	ClassNameList.RemoveAll();
	UINT nClassBraceNum[MAX_EMBEDDED_CLASS_DEPTH];
	for (int j = 0; j < MAX_EMBEDDED_CLASS_DEPTH; j++)
		nClassBraceNum[j] = 0;
	UINT nFuncPos = 0; // record the { postion in function implementation
	UINT nFuncBraceNum = 0; // record the number of { and } in function implementation
	int nErrorPos;

	CStringArray DefaultStateNameList; //record all default states in state tree
	std::vector<HTREEITEM> TreeItemList;

	DefaultStateNameList.RemoveAll();
	TreeItemList.clear();
	CString sContexJoint = "";
	while (true)
	{
		// Read in a line from the file.
		if (!OpenedFile.ReadString(sCurrentLine))
			break;
		// Build state tree
		if ((nErrorPos = GenerateStateTree(TRUE, hItem, sCurrentLine, nPrjSeqNum, nReverseStateTreeFlag, TreeItemList, DefaultStateNameList, OpenedFile)) <= 0)
		{
			break;
		}

		BSTR bstr = sCurrentLine.AllocSysString();


		CComVariant CountResultArray;
		CountResultArray.puintVal=NULL;
		CComVariant pFuncPos;
		pFuncPos.puintVal=&nFuncPos;

		Fire_ParseCommentState(bstr, nCommentFlag, CountResultArray,pFuncPos);
		nFuncPos=*(data.pFuncPosLine);

		::SysFreeString(bstr);

		sCurrentLine = (wchar_t*)data.sCleanLine;
		nCommentFlag = (UCHAR)data.CommentState;

		// Whether mix code and comment?
		if (data.isParseCommentStateOk == TRUE)
		{
			sContexJoint += sCurrentLine;
			continue;
		}


		if (!sContexJoint.IsEmpty())
		{
			CString sMergedLine;

			sMergedLine = sContexJoint;				
			sMergedLine += sCurrentLine;
			sCurrentLine = sMergedLine;
			sContexJoint = "";
		}
		if (sCurrentLine == "")// case 1: comments line; case 2: blank line
			continue;
		ParseToTagDB(sCurrentLine, sClassHead, &nTagDBFlag,&nFuncBraceNum,sPrefixLine,nFuncPos,&(pDBFileItem->pFuncList), ClassNameList, nClassBraceNum);

	}

	if (nReverseStateTreeFlag == TREE_GENERATION_BEGIN_STATE)
	{	
		HTREEITEM hNonEventSrcFile = tree.GetChildItem(hProject);

		while (true)
		{
			if (NULL == hNonEventSrcFile)
				break;
			if (tree.GetItemData(hNonEventSrcFile) & STATE_TREE_OTHER_SOURCE_MASK)
				break;
			hNonEventSrcFile = tree.GetNextSiblingItem(hNonEventSrcFile);
		}
		AddNonHdlerSrcToStateTree(TRUE, pDBFileItem, hNonEventSrcFile);

		TV_SORTCB SortCB;
		SortCB.hParent = hNonEventSrcFile;
		SortCB.lpfnCompare = CompareFunc;
		SortCB.lParam = 0;

		tree.SortChildrenCB(&SortCB);

		SortCB.hParent = hProject;
		SortCB.lpfnCompare = CompareFunc;
		SortCB.lParam = 0;
		tree.SortChildrenCB(&SortCB);
	}

	if (nReverseStateTreeFlag == TREE_GENERATION_END_STATE)
	{

		// Non event handlers in application files
		HTREEITEM hApp;

		hApp = m_NewApp;
		//				if (TreeItemList.size() != 0)
		//				{
		// In normal case, TreeItemList will not decrease to 0
		// but such condition is in case that exception happens
		// in parsing file.(Like: Build tree flag also exists in 
		// other source file which they are not meant to be tree 
		// flag ,instead, they are used by users by mistaken)
		//					hApp = *(TreeItemList.begin());
		//				}

		AddNonHdlerSrcToStateTree(TRUE, pDBFileItem, hApp);

		TV_SORTCB SortCB;
		SortCB.hParent = hApp;
		SortCB.lpfnCompare = CompareFunc;
		SortCB.lParam = 0;

		tree.SortChildrenCB(&SortCB);

		SortCB.hParent = hProject;
		SortCB.lpfnCompare = CompareFunc;
		SortCB.lParam = 0;
		tree.SortChildrenCB(&SortCB);
	}

	BOOL bUpdateSuccess = TRUE;
	if (nReverseStateTreeFlag == TREE_GENERATION_STATE_TREE_DEFINE ||
		nReverseStateTreeFlag == TREE_GENERATION_STATE_DECLARE ||
		nReverseStateTreeFlag == TREE_GENERATION_EXCEPTION_STATE ||
		nReverseStateTreeFlag == TREE_GENERATION_EXCEPTION_STATE_NO_TREE_HDR ||
		nReverseStateTreeFlag == TREE_GENERATION_EXCEPTION_STATE_NO_STATE_DECL_HDR ||
		nReverseStateTreeFlag == TREE_GENERATION_EXCEPTION_STATE_NO_APP_CLASS_DECL_HDR ||
		nReverseStateTreeFlag == TREE_GENERATION_EXCEPTION_STATE_HANDLER_ERR)
	{
		//////////////  Update failed ////////////////
		bUpdateSuccess = FALSE;

		// damaged application file 
		if (TreeItemList.size() != 0)
		{
			std::vector<HTREEITEM>::iterator pHItem = TreeItemList.begin();
			HTREEITEM hApp = (*pHItem);
			tree.DeleteItem(hApp);
		}
		else
			tree.DeleteItem(hItem);

		if (nReverseStateTreeFlag != TREE_GENERATION_EXCEPTION_STATE_HANDLER_ERR)
		{
			// Print error message.
			CString sWarningMsg;

			if (nErrorPos < 0)
				nErrorPos *= (-1);
			else
				nErrorPos = nFuncPos+1;

			switch (nReverseStateTreeFlag)
			{
			case TREE_GENERATION_EXCEPTION_STATE_NO_TREE_HDR:
				sWarningMsg.Format("%s(Line %d):	error: no header of the state tree definition, although the tail is found."
					,OpenedFile.GetFileName(), nErrorPos);
				break;
			case TREE_GENERATION_EXCEPTION_STATE_NO_STATE_DECL_HDR:
				sWarningMsg.Format("%s(Line %d):	error: no header of the state declaration, although the tail is found."
					,OpenedFile.GetFileName(), nErrorPos);
				break;
			case TREE_GENERATION_EXCEPTION_STATE_NO_APP_CLASS_DECL_HDR:
				sWarningMsg.Format("%s(Line %d):	error: no header of the application class declaration, although the tail is found."
					,OpenedFile.GetFileName(), nErrorPos);
				break;
			default:
				sWarningMsg.Format("%s(Line %d):	error: illegal syntax",OpenedFile.GetFileName(), nErrorPos);
				break;
			}

			_bstr_t bError(sWarningMsg.GetBuffer());
			Fire_OutPutStringToPane(bError.GetBSTR());
			sWarningMsg.ReleaseBuffer();
		}

	}
	// Confirm whether current saved file is the original file which stores event list
	// If both are the same, Set ST_EVENT_HDR_FILE_UPDATE: The updated file is the event id header file. StateWizard should 
	// parse the event id header file again.
	// Otherwise, Set ST_NORMAL_UPDATE: The updated file is not event id header file.

	if (m_EventIdFilePath.CompareNoCase(sFilePath) == 0)
		GetEventIdListFilePath(ST_EVENT_HDR_FILE_UPDATE);
	else 
		GetEventIdListFilePath(ST_NORMAL_UPDATE);
	OpenedFile.Close();
	DefaultStateNameList.RemoveAll();
	TreeItemList.clear();


	// Get file path to be updated 
	CStringArray AppFileList;
	AppFileList.RemoveAll();

	if (tree.GetItemData(hItem) & STATE_TREE_APPLICATION_MASK)
	{
		// If update failed ,the application item will be deleted. Thus
		// there is no need to clear any flag used to rebuild the tree.
		if (bUpdateSuccess == FALSE)
		{
			return FALSE;
		}
		GetAppSrcHdrPath(AppFileList, (LPCTSTR)(tree.GetItemText(hItem)), hItem);
		if (((CString)AppFileList[0]).CompareNoCase(sFilePath) == 0)
		{
			// Update header file
			HTREEITEM hChild;
			hChild = tree.GetChildItem(hItem);

			while (true)
			{
				if (NULL == hChild)
					break;
				if (tree.GetItemData(hChild) & STATE_TREE_APPLICATION_HEADER_FILE_MASK)
				{
					hItem = hChild;
					break;
				}
				hChild = tree.GetNextSiblingItem(hChild);
			}
			DelOldTreeItem(hItem);
			ClearOldItemFlag(hItem);
		}
		else
		{
			// Update source file
			HTREEITEM hChild;
			hChild = tree.GetChildItem(hItem);

			while (true)
			{
				if (NULL == hChild)
					break;

				if (tree.GetItemData(hChild) & STATE_TREE_APPLICATION_HEADER_FILE_MASK)
				{
					DWORD lparam = tree.GetItemData(hChild);

					lparam |= STATE_TREE_IS_ORIGINAL_ITEM;
					tree.SetItemData(hChild, lparam);

					HTREEITEM hFuncItem = tree.GetChildItem(hChild);
					while (true)
					{
						if (NULL == hFuncItem)
							break;
						lparam = tree.GetItemData(hFuncItem);
						lparam |= STATE_TREE_IS_ORIGINAL_ITEM;
						tree.SetItemData(hFuncItem, lparam);
						hFuncItem = tree.GetNextSiblingItem(hFuncItem);
					}
					break;
				}
				hChild = tree.GetNextSiblingItem(hChild);
			}
			DelOldTreeItem(hItem);
			ClearOldItemFlag(hItem);
		}
	}
	else
	{
		DelOldTreeItem(hItem);
		ClearOldItemFlag(hItem);
	}
	return TRUE;
}

//////////////////////////////////////////////////////////////////////////
//  Build state tree
//
//
// DESCRIPTION: Generate state tree according to information of application files
// INPUT: 
//        *) bIsUpdate: To update state tree when the modified file is saved
//        *) hItem: Handle of tree item which corresponds to the saved file
//        *) sText: Current line of text to be parsed.
//        *) nPrjSeqNum: Sequence number of current project in project lists
//        *) nReverseStateTreeFlag: Flag to be used in building state tree
//        *) TreeItemList: Record tree item in the process of building tree
//        *) DefaultStateNameList: Record default state in the application to be built 
//        *) OpenedFile: Current opened file
//        
// OUTPUT: 1) TRUE: 2)FALSE
// m_EventIdPathList: event id header file list. 
// NOTE: 
//
///////////////////////////////////////////////////////////////////////////////////////////
int CStateTreeCtrl::GenerateStateTree(BOOL bIsUpdate, HTREEITEM hOriginalItem, CString sText, UINT nPrjSeqNum, UCHAR &nReverseStateTreeFlag, 
									  std::vector<HTREEITEM> &TreeItemList, CStringArray &DefaultStateNameList, CStdioFile &OpenedFile)
{
	sText.TrimLeft();
	sText.TrimRight();

	if (sText.IsEmpty())
		return TRUE;

	// Get event id file path. If number of path stored in m_EventIdPathList is even
	// then it is correct syntax. Otherwise, it is illegal syntax to be ignored.
	if ((sText.Compare("/*}}SME_EVENT_ID_LIST_DECLARE*/") == 0) ||
		(sText.Compare("/*{{SME_EVENT_ID_LIST_DECLARE*/")) == 0)
	{
		TRACE("m_EventIdPathList.Add: %s\n", OpenedFile.GetFilePath());
		m_EventIdPathList.Add(OpenedFile.GetFilePath());
	}

	/// ERROR cases: Meet the end of state tree definition, however there is no beginer.
	if (sText.Compare("/*}}SME_STATE_TREE_DEF*/") == 0 
		&& nReverseStateTreeFlag != TREE_GENERATION_STATE_TREE_DEFINE)
	{
		// Can not found the header of state tree definition.
		nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE_NO_TREE_HDR;
		return FALSE;
	}

	/// ERROR cases: Meet the end of app class decalration, however there is no beginer.
	if (sText.Compare("/*}}SME_APP_CLASS_DECLARE*/") == 0 
		&& nReverseStateTreeFlag != TREE_GENERATION_APP_CLASS_DECLARE)
	{
		// Can not found the header of state tree definition.
		nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE_NO_APP_CLASS_DECL_HDR;
		return FALSE;
	}

	/// ERROR cases: Meet the end of state decalration, however there is no beginer.
	if (sText.Compare("/*}}SME_STATE_DECLARE*/") == 0 
		&& nReverseStateTreeFlag != TREE_GENERATION_STATE_DECLARE)
	{
		// Can not found the header of state tree definition.
		nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE_NO_STATE_DECL_HDR;
		return FALSE;
	}

	// Case: meet state declaration
	if (nReverseStateTreeFlag == TREE_GENERATION_STATE_DECLARE)
	{
		if (sText.Compare("/*}}SME_STATE_DECLARE*/") == 0)
		{
			nReverseStateTreeFlag = TREE_GENERATION_END_STATE;
			m_NewApp = *TreeItemList.begin(); 
			TreeItemList.clear();
			return TRUE;
		}else if (sText.Find("SME_STATE_DECLARE(")!=0 && sText.Find("SME_MAX_STATE(")!=0)
		{
			// ERROR: Can not find the ender of state declaration.
			nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
			return FALSE;
		}
	}


	// Case: meet application class declaration
	if (nReverseStateTreeFlag == TREE_GENERATION_APP_CLASS_DECLARE)
	{
		if (sText.Compare("/*}}SME_APP_CLASS_DECLARE*/") == 0)
		{
			nReverseStateTreeFlag = TREE_GENERATION_END_STATE;
			TreeItemList.clear();
			return TRUE;
		}else if (sText.Find("SME_STATE_EVT_HDL_TBL_DEC(")!=0 && sText.Find("SME_STATE_TREE_DEC(")!=0)
		{
			// ERROR: Can not find the event handler table or the ender of application class declaration. 
			nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
			return FALSE;
		}
	}

	// Case: meet state tree definition
	if (nReverseStateTreeFlag == TREE_GENERATION_STATE_TREE_DEFINE)
	{
		if (sText.Compare("/*}}SME_STATE_TREE_DEF*/") == 0)
		{
			// End of one state definition
			nReverseStateTreeFlag = TREE_GENERATION_END_STATE;

			m_NewApp = *TreeItemList.begin(); 
			TreeItemList.clear();
			DefaultStateNameList.RemoveAll();
			return TRUE;
		}

		// Format: 	SME_STATE(MyApp2,MyApp2,SME_INVALID_STATE,State2)
		CString sAppName; // current application name
		CString sNewState;// new state name
		CString sDfltChld;// default child state name
		CString sParState;// parent state name

		int idx = sText.Find("SME_STATE");
		if (idx != 0)
		{
			// ERROR
			nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
			return FALSE;
		}
		sText.Replace("SME_STATE", NULL);
		sText.TrimLeft();
		sText.TrimRight();
		idx = sText.Find('(');
		if (idx != 0)
		{
			// ERROR
			nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
			return FALSE;
		}
		idx = sText.ReverseFind(')');
		if (idx != sText.GetLength()-1)
		{
			// ERROR
			nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
			return FALSE;
		}
		sText.Replace("(", NULL);
		sText.Replace(")", NULL);

		int nCommaNo = 0;
		while (true)
		{
			if (nCommaNo > 3)
				break;
			idx = sText.Find(',');
			if (idx == -1)
				break;
			nCommaNo++;

			CString sName = sText.Left(idx);
			sName.TrimLeft();
			sName.TrimRight();
			if (sName.Find(' ') != -1 || sName.Find('\t') != -1)
			{
				// ERROR
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}
			sText = sText.Right(sText.GetLength()-idx-1);
			if (nCommaNo == 1)
			{
				sAppName = sName;
			}
			if (nCommaNo == 2)
			{
				sNewState = sName;
			}
			if (nCommaNo == 3)
			{
				sParState = sName;
			}
		}
		if (nCommaNo == 3)
		{
			sText.TrimLeft();
			sText.TrimRight();
			if (sText.Find(' ') != -1 || sText.Find('\t') != -1)
			{
				// ERROR
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}
			sDfltChld = sText;
		}
		else
		{
			// ERROR
			nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
			return FALSE;
		}

		CString sName = "";
		HTREEITEM hParent;
		HTREEITEM hInsert;
		HTREEITEM hNewItem;
		DWORD lparam;

		// The parent state is SME_INVALID_STATE or -1 in state tree defination.
		if ((sParState.Find("SME_INVALID_STATE") >= 0) || (sParState.Find("-1") >= 0))
		{
			if (bIsUpdate == TRUE)
			{
				if (sNewState.Compare(tree.GetItemText(hOriginalItem)) != 0)
				{
					tree.SetItemText(hOriginalItem, sNewState);
				}

				hInsert = tree.GetChildItem(hOriginalItem);
				while (true)
				{
					if (hInsert == NULL)
						break;
					if (tree.GetItemData(hInsert) & STATE_TREE_APPLICATION_SOURCE_FILE_MASK)
					{
						CString sNonEventSrcName = "";//"Non event handler: ";
						sNonEventSrcName += OpenedFile.GetFileName();

						if (sNonEventSrcName.Compare(tree.GetItemText(hInsert)) != 0)
							tree.SetItemText(hInsert, sNonEventSrcName);
						lparam = tree.GetItemData(hInsert);
						lparam |= STATE_TREE_IS_ORIGINAL_ITEM;
						tree.SetItemData(hInsert, lparam);
						break;
					}
					hInsert = tree.GetNextSiblingItem(hInsert);
				}

				lparam = STATE_TREE_APPLICATION_MASK|STATE_TREE_IS_ORIGINAL_ITEM;
				// Default state is NOT SME_INVALID_STATE and -1
				// if (sDfltChld.Compare("-1") != 0)
				if ((sDfltChld.Find("-1") == -1) && (sDfltChld.Find("SME_INVALID_STATE") == -1))
				{
					DefaultStateNameList.Add(sDfltChld);
					lparam |= STATE_TREE_HAS_DEFAULT_CHILD_STATE;
				}
				tree.SetItemData(hOriginalItem, lparam);
				TreeItemList.push_back(hOriginalItem);
				hNewItem = hOriginalItem;
			}
			else
			{
				// Add application node
				hParent = tree.GetSelectedItem();
				hInsert = tree.GetChildItem(hParent);

				// Check whether application node has been built
				while (true)
				{
					if (NULL == hInsert)
						break;

					if ((tree.GetItemData(hInsert) & STATE_TREE_APPLICATION_MASK) != 0)
					{
						if (sNewState.Compare(tree.GetItemText(hInsert)) == 0)
						{
							// Default state is NOT SME_INVALID_STATE and -1
							// if (sDfltChld.Compare("-1") != 0)
							if ((sDfltChld.Find("-1") == -1) && (sDfltChld.Find("SME_INVALID_STATE") == -1))
							{
								DefaultStateNameList.Add(sDfltChld);
								lparam = STATE_TREE_HAS_DEFAULT_CHILD_STATE | STATE_TREE_APPLICATION_MASK;
								tree.SetItemData(hInsert, lparam);
							}
							break;
						}
					}
					hInsert = tree.GetNextSiblingItem(hInsert);
				}
				if (NULL == hInsert)
				{
					// RULE: If in the state tree defination, the parent state is SME_INVALID_STATE or -1, record the application name.
					// Add application node
					lparam = STATE_TREE_APPLICATION_MASK;
					// Default state is NOT SME_INVALID_STATE and -1
					if ((sDfltChld.Find("-1") == -1) && (sDfltChld.Find("SME_INVALID_STATE") == -1))
					{
						DefaultStateNameList.Add(sDfltChld);
						lparam |= STATE_TREE_HAS_DEFAULT_CHILD_STATE;
					}

					TVINSERTSTRUCT Inserter;

					Inserter.hParent = hParent;
					Inserter.hInsertAfter = TVI_SORT;
					Inserter.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
					Inserter.item.pszText = (LPTSTR)(LPCTSTR)sNewState;
					Inserter.item.iImage = 2;
					Inserter.item.iSelectedImage = 2;
					hInsert = tree.InsertItem(&Inserter);

					tree.SetItemData(hInsert, lparam);
					tree.SetItemImage(hInsert, 2, 2);	
				}
				TreeItemList.push_back(hInsert);
				hNewItem = hInsert;

				// Add non event handler node for source file
				CString sNonEventSrcName = "";//"Non event handler: ";
				sNonEventSrcName += OpenedFile.GetFileName();

				TVINSERTSTRUCT Inserter;

				Inserter.hParent = hInsert;
				Inserter.hInsertAfter = TVI_LAST;
				Inserter.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
				Inserter.item.pszText = (LPTSTR)(LPCTSTR)sNonEventSrcName;
				Inserter.item.iImage = 7;
				Inserter.item.iSelectedImage = 7;
				hInsert = tree.InsertItem(&Inserter);

				// RULE: If in the state tree defination, the parent state is SME_INVALID_STATE or -1, record the CPP file name.
				tree.SetItemData(hInsert, STATE_TREE_APPLICATION_SOURCE_FILE_MASK);
				tree.SetItemImage(hInsert, 7, 7);
			}

		}	// Application item.
		else // The parent state is a valid one.
		{
			// Add a new state node
			sName = "";
			sName += sNewState;
			if (IsDefaultState(DefaultStateNameList, sNewState) == TRUE)
			{
				sName += "  (default)";
				lparam = STATE_TREE_STATE_MASK|STATE_TREE_DEFAULT_STATE;
			}
			else
				lparam = STATE_TREE_STATE_MASK;

			if ((sDfltChld.Find("-1") == -1) && (sDfltChld.Find("SME_INVALID_STATE") == -1))
			{
				// Has default child state
				DefaultStateNameList.Add(sDfltChld); // store default child state name
				lparam |= STATE_TREE_HAS_DEFAULT_CHILD_STATE;
			}
			// Get handler of parent item by parent state name
			hParent = GetParentTreeItem(TreeItemList, sParState);
			if (NULL == hParent)
			{
				// Exception 
				// ERROR
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}

			BOOL bFound = FALSE;
			if (bIsUpdate == TRUE)
			{
				hInsert = tree.GetChildItem(hParent);
				while (true)
				{
					if (NULL == hInsert)
						break;
					if (tree.GetItemData(hInsert) & STATE_TREE_STATE_MASK)
					{
						if (sName.Compare(tree.GetItemText(hInsert)) == 0)
						{
							lparam = tree.GetItemData(hInsert);
							lparam |= STATE_TREE_IS_ORIGINAL_ITEM;
							tree.SetItemData(hInsert, lparam);
							bFound = TRUE;
							break;
						}
					}
					hInsert = tree.GetNextSiblingItem(hInsert);
				}
			}
			if (bFound == FALSE)
			{
				TVINSERTSTRUCT Inserter;

				Inserter.hParent = hParent;
				Inserter.hInsertAfter = TVI_LAST;
				Inserter.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
				Inserter.item.pszText = (LPTSTR)(LPCTSTR)sName;
				Inserter.item.iImage = 3;
				Inserter.item.iSelectedImage = 3;
				hInsert = tree.InsertItem(&Inserter);

				if (bIsUpdate)
					lparam |= STATE_TREE_IS_ORIGINAL_ITEM;
				tree.SetItemData(hInsert, lparam);
				tree.SetItemImage(hInsert, 3, 3);
			}

			TreeItemList.push_back(hInsert); // store current built item handler
			hNewItem = hInsert;
		}
		// Build state related handler function nodes
		int nErrorPos;
		if ((nErrorPos = GenerateHandlerNode(bIsUpdate, hNewItem, sNewState, sAppName, OpenedFile)) <= 0)
		{
			if (nErrorPos==0)
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE_HANDLER_ERR; // StatWizard will not output error information.
			else
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
			return nErrorPos;
		}
		return TRUE;
	} // end of Case: meet state tree definition


	// Case: initialized status
	if (nReverseStateTreeFlag == TREE_GENERATION_BEGIN_STATE ||
		nReverseStateTreeFlag == TREE_GENERATION_END_STATE)
	{
		// Meet state tree definition header 
		// Format: /*{{SME_STATE_TREE_DEF(application)*/
		if ((sText.Left(23).Compare("/*{{SME_STATE_TREE_DEF(") == 0))
		{
			int idx = sText.Find("*/");
			if (idx != sText.GetLength()-2)
			{
				// ERROR
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}
			sText.Replace("*/", NULL);
			sText = sText.Right(sText.GetLength()-23);
			idx = sText.Find(')');
			if (idx != sText.GetLength()-1)
			{
				// ERROR
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}
			sText.Replace(")", NULL);
			CString sAppName = sText;
			if (sAppName.Find(' ') != -1 || sAppName.Find('\t') != -1)
			{
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}

			// Add application node
			HTREEITEM hParent = tree.GetSelectedItem();
			HTREEITEM hInsert = tree.GetChildItem(hParent);
			// Check whether application node has been built
			while (true)
			{
				if (NULL == hInsert)
					break;

				if ((tree.GetItemData(hInsert) & STATE_TREE_APPLICATION_MASK) != 0)
				{
					if (sAppName.Compare(tree.GetItemText(hInsert)) == 0)
					{
						break;
					}
				}
				hInsert = tree.GetNextSiblingItem(hInsert);
			}
			if (NULL != hInsert)
			{
				TreeItemList.push_back(hInsert);
			}

			// Get current opened file path
			CString sFilePath = OpenedFile.GetFilePath();

			APP_FILE_INFO_T* pAppFileItem; 
			BOOL bFound = FALSE;

			if (m_appSrcHdrFiles.GetSize()-1 >= (int)nPrjSeqNum)
			{
				// Applications in this project have ever been met
				pAppFileItem = (APP_FILE_INFO_T*)m_appSrcHdrFiles[nPrjSeqNum]; // get application file information structrue

				// Check whether APP_FILE_INFO_T has been allocated memory
				while(true)
				{
					if (NULL == pAppFileItem)
						break; //has not been allocated memory

					if (sAppName.Compare(pAppFileItem->sAppName) == 0)
					{
						// Found application structure
						if (NULL != pAppFileItem->sSrcFilePath)
							delete(pAppFileItem->sSrcFilePath); // clear original memory
						pAppFileItem->sSrcFilePath = NULL;
						pAppFileItem->sSrcFilePath = new char[sFilePath.GetLength()+1];
						ASSERT(NULL != pAppFileItem->sSrcFilePath);
						memcpy(pAppFileItem->sSrcFilePath, (LPCTSTR)sFilePath, sFilePath.GetLength()+1);
						bFound = TRUE;
						break;
					}
					pAppFileItem = (APP_FILE_INFO_T*)pAppFileItem->pNextApp;
				}
				if (bFound == FALSE)
				{
					APP_FILE_INFO_T *pAppNewItem = new(APP_FILE_INFO_T);
					pAppNewItem->pNextApp = NULL;
					pAppNewItem->sHdrFilePath = NULL;
					pAppNewItem->sAppName = new char[sAppName.GetLength()+1];
					ASSERT(NULL != pAppNewItem->sAppName);
					memcpy(pAppNewItem->sAppName, (LPCTSTR)sAppName, sAppName.GetLength()+1);
					pAppNewItem->sSrcFilePath = new char[sFilePath.GetLength()+1];
					ASSERT(NULL != pAppNewItem->sSrcFilePath);
					memcpy(pAppNewItem->sSrcFilePath, (LPCTSTR)sFilePath, sFilePath.GetLength()+1);
					pAppFileItem = (APP_FILE_INFO_T*)(m_appSrcHdrFiles[nPrjSeqNum]);
					pAppNewItem->pNextApp = pAppFileItem;
					// Modify head in m_appSrcHdrFiles
					m_appSrcHdrFiles.SetAt(nPrjSeqNum, pAppNewItem);			
				}
			}
			else
			{
				// Applications in this project have never been met
				APP_FILE_INFO_T *pAppNewItem = new(APP_FILE_INFO_T);
				pAppNewItem->pNextApp = NULL;
				pAppNewItem->sHdrFilePath = NULL;
				pAppNewItem->sAppName = new char[sAppName.GetLength()+1];
				ASSERT(NULL != pAppNewItem->sAppName);
				memcpy(pAppNewItem->sAppName, (LPCTSTR)sAppName, sAppName.GetLength()+1);
				pAppNewItem->sSrcFilePath = new char[sFilePath.GetLength()+1];
				ASSERT(NULL != pAppNewItem->sSrcFilePath);
				memcpy(pAppNewItem->sSrcFilePath, (LPCTSTR)sFilePath, sFilePath.GetLength()+1);

				m_appSrcHdrFiles.Add(pAppNewItem);
			}
			nReverseStateTreeFlag = TREE_GENERATION_STATE_TREE_DEFINE;
			return TRUE;
		}

		// Meet app class enumeration declaration
		if (sText.Left(26).Compare("/*{{SME_APP_CLASS_DECLARE(") == 0) 
		{
			// Format: /*{{SME_APP_CLASS_DECLARE(app, app class, base class)*/
			// Get application class name
			int idx = sText.Find("*/");
			if (idx != sText.GetLength()-2)
			{
				// ERROR
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}
			sText.Replace("*/", NULL);
			sText = sText.Right(sText.GetLength()-26);
			idx = sText.Find(',');
			if (idx==-1)
			{
				// ERROR
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}

			CString sApp = sText.Left(idx);
			sText = sText.Mid(idx+1);
			sApp.TrimLeft();
			sApp.TrimRight();

			idx = sText.Find(',');
			if (idx==-1)
			{
				// ERROR
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}

			CString sAppClass = sText.Left(idx);
			sText = sText.Mid(idx+1);
			sAppClass.TrimLeft();
			sAppClass.TrimRight();

			idx = sText.Find(')');
			if (idx==-1)
			{
				// ERROR
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}

			CString sBaseClass = sText.Left(idx);
			sBaseClass.TrimLeft();
			sBaseClass.TrimRight();

			if (s_HdrFileTreeNode!=NULL && s_AppName.Compare(sApp)==0)
			{
				// {{SME_STATE_DECLARE is located in front of {{SME_APP_CLASS_DECLARE. Revise the tree node of app header file.
				CString sItemText= tree.GetItemText(s_HdrFileTreeNode) + STR_APP_CLASS_FLAG + sAppClass;
				tree.SetItemText(s_HdrFileTreeNode, sItemText);
				tree.SetItemData(s_HdrFileTreeNode,STATE_TREE_APPLICATION_HEADER_FILE_MASK|STATE_TREE_APP_IS_A_CLASS);
				// Reset app class info for the header file node
				s_HdrFileTreeNode = NULL;
				s_AppName.Empty();
				s_ClassName.Empty();
			} else
			{
				s_AppName= sApp;
				s_ClassName=sAppClass;
			}
			// Enter app class declaration state.
			nReverseStateTreeFlag = TREE_GENERATION_APP_CLASS_DECLARE;
		}


		// Meet state enumeration declaration
		if (sText.Left(22).Compare("/*{{SME_STATE_DECLARE(") == 0) 
		{
			// Format: /*{{SME_STATE_DECLARE(application)*/
			// Get application name
			int idx = sText.Find("*/");
			if (idx != sText.GetLength()-2)
			{
				// ERROR
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}
			sText.Replace("*/", NULL);
			sText = sText.Right(sText.GetLength()-22);
			idx = sText.Find(')');
			if (idx != sText.GetLength()-1)
			{
				// ERROR
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}
			sText.Replace(")", NULL);
			CString sAppName = sText;
			if (sAppName.Find(' ') != -1 || sAppName.Find('\t') != -1)
			{
				nReverseStateTreeFlag = TREE_GENERATION_EXCEPTION_STATE;
				return FALSE;
			}

			HTREEITEM hParent;
			HTREEITEM hInsert;
			if (bIsUpdate == TRUE)
			{			
				hInsert = tree.GetChildItem(hOriginalItem);
				while (true)
				{
					if (hInsert == NULL)
						break;
					if (tree.GetItemData(hInsert) & STATE_TREE_APPLICATION_HEADER_FILE_MASK)
					{
						CString sNonEventSrcName = "";//"Non event handler: ";
						sNonEventSrcName += OpenedFile.GetFileName();

						CString sItemFileName = tree.GetItemFileName(hInsert);
						
						if (sNonEventSrcName.Compare(sItemFileName) != 0)
							tree.SetItemText(hInsert, sNonEventSrcName);
						DWORD lparam = tree.GetItemData(hInsert);
						lparam |= STATE_TREE_IS_ORIGINAL_ITEM;
						tree.SetItemData(hInsert, lparam);
						break;
					}
					hInsert = tree.GetNextSiblingItem(hInsert);
				}
				TreeItemList.push_back(hOriginalItem);
			}
			else
			{
				hParent = tree.GetSelectedItem();
				hInsert = tree.GetChildItem(hParent);

				// Check whether application node has been built
				while (true)
				{
					if (NULL == hInsert)
						break;

					if ((tree.GetItemData(hInsert) & STATE_TREE_APPLICATION_MASK) != 0)
					{
						if (sAppName.Compare(tree.GetItemText(hInsert)) == 0)
							break; // found the application node			
					}
					hInsert = tree.GetNextSiblingItem(hInsert);
				}
				// No application node has built
				if (NULL == hInsert)
				{
					TVINSERTSTRUCT Inserter;

					Inserter.hParent = hParent;
					Inserter.hInsertAfter = TVI_SORT;
					Inserter.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
					Inserter.item.pszText = (LPTSTR)(LPCTSTR)sAppName;
					Inserter.item.iImage = 2;
					Inserter.item.iSelectedImage = 2;
					hInsert = tree.InsertItem(&Inserter);

					tree.SetItemData(hInsert, STATE_TREE_APPLICATION_MASK);
					tree.SetItemImage(hInsert, 2, 2);
				}
				//			Expand(hParent, TVE_EXPAND);
				TreeItemList.push_back(hInsert); // record application handler here to
				// in case that error happens in building

				// Add application header node
				CString sNonEventHdrName = "";//"Non event handler: ";
				sNonEventHdrName += OpenedFile.GetFileName();
				DWORD ItemData=0;

				TVINSERTSTRUCT Inserter;

				Inserter.hParent = hInsert;
				Inserter.hInsertAfter = TVI_LAST;
				Inserter.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE|TVIF_SELECTEDIMAGE;
				Inserter.item.iImage = 7;
				Inserter.item.iSelectedImage = 7;

				if (sAppName == s_AppName && !s_ClassName.IsEmpty())
				{
					// App Class definition is located in front of state enumeration.
					sNonEventHdrName += STR_APP_CLASS_FLAG + s_ClassName;
					s_ClassName.Empty();
					ItemData = STATE_TREE_APPLICATION_HEADER_FILE_MASK | STATE_TREE_APP_IS_A_CLASS;

					Inserter.item.pszText = (LPTSTR)(LPCTSTR)sNonEventHdrName;
					hInsert = tree.InsertItem(&Inserter);

					// Reset app class info for the header file node.
					s_HdrFileTreeNode=NULL;
					s_AppName.Empty();
				} else
				{
					ItemData = STATE_TREE_APPLICATION_HEADER_FILE_MASK;

					Inserter.item.pszText = (LPTSTR)(LPCTSTR)sNonEventHdrName;
					hInsert = tree.InsertItem(&Inserter);

					s_HdrFileTreeNode = hInsert; // Keep track of the header file node.
					s_AppName=sAppName;
				}


				tree.SetItemData(hInsert,ItemData);
				tree.SetItemImage(hInsert, 7, 7);
			}

			// Add application header file information to m_appSrcHdrFils
			CString sFilePath = OpenedFile.GetFilePath();
			BOOL bFound = FALSE;
			APP_FILE_INFO_T* pAppFileItem; 

			if (m_appSrcHdrFiles.GetSize()-1 >= (int)nPrjSeqNum)
			{
				pAppFileItem = (APP_FILE_INFO_T*)m_appSrcHdrFiles[nPrjSeqNum];

				while(true)
				{
					if (NULL == pAppFileItem)
						break;

					if (sAppName.Compare(pAppFileItem->sAppName) == 0)
					{
						if (NULL != pAppFileItem->sHdrFilePath)
							delete(pAppFileItem->sHdrFilePath);
						pAppFileItem->sHdrFilePath = NULL;
						pAppFileItem->sHdrFilePath = new char[sFilePath.GetLength()+1];
						ASSERT(NULL != pAppFileItem->sHdrFilePath);
						memcpy(pAppFileItem->sHdrFilePath, (LPCTSTR)sFilePath, sFilePath.GetLength()+1);
						bFound = TRUE;
						break;
					}
					pAppFileItem = (APP_FILE_INFO_T*)pAppFileItem->pNextApp;
				}
				if (bFound == FALSE)
				{
					APP_FILE_INFO_T *pAppNewItem = new(APP_FILE_INFO_T);
					pAppNewItem->pNextApp = NULL;
					pAppNewItem->sSrcFilePath = NULL;
					pAppNewItem->sAppName = new char[sAppName.GetLength()+1];
					ASSERT(NULL != pAppNewItem->sAppName);
					memcpy(pAppNewItem->sAppName, (LPCTSTR)sAppName, sAppName.GetLength()+1);
					pAppNewItem->sHdrFilePath = new char[sFilePath.GetLength()+1];
					ASSERT(NULL != pAppNewItem->sHdrFilePath);
					memcpy(pAppNewItem->sHdrFilePath, (LPCTSTR)sFilePath, sFilePath.GetLength()+1);

					pAppFileItem = (APP_FILE_INFO_T*)m_appSrcHdrFiles[nPrjSeqNum];
					pAppNewItem->pNextApp = pAppFileItem;	
					m_appSrcHdrFiles.SetAt(nPrjSeqNum, pAppNewItem);				
				}
			}
			else
			{
				// memory release
				APP_FILE_INFO_T *pAppNewItem = new(APP_FILE_INFO_T);
				pAppNewItem->pNextApp = NULL;
				pAppNewItem->sSrcFilePath = NULL;
				pAppNewItem->sAppName = new char[sAppName.GetLength()+1];
				ASSERT(NULL != pAppNewItem->sAppName);
				memcpy(pAppNewItem->sAppName, (LPCTSTR)sAppName, sAppName.GetLength()+1);
				pAppNewItem->sHdrFilePath = new char[sFilePath.GetLength()+1];
				ASSERT(NULL != pAppNewItem->sHdrFilePath);
				memcpy(pAppNewItem->sHdrFilePath, (LPCTSTR)sFilePath, sFilePath.GetLength()+1);

				m_appSrcHdrFiles.Add(pAppNewItem);
			}
			// Enter state enumeration declaration state.
			nReverseStateTreeFlag = TREE_GENERATION_STATE_DECLARE;
			return TRUE;
		} // end of SME_STATE_DECLARE
		return TRUE;
	} // end of init state


	return TRUE;
}

///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get parent state item in state tree in building state tree
// INPUT:  1) TreeItemList: Handle of tree item in building state tree
//         2) sParName: Handle of corresponding project node item
//        
// OUTPUT: 1) TRUE: 2)FALSE
// NOTE: 
///////////////////////////////////////////////////////////////////////////////////////////
int CStateTreeCtrl::GenerateHandlerNode(BOOL bIsUpdate,HTREEITEM hSelector, CString sSelName, CString sAppName, CStdioFile &OpenedFile)
{
	// Record current opened file's pointer's position
	DWORD nFilePos = (DWORD)OpenedFile.GetPosition();

	// Convert file pointer to the beginning of the file
	OpenedFile.SeekToBegin();
	CString sCurLine;
	CString sDefBegin = "/*{{SME_STATE_DEF";	/*{SME_STATE_DEF(application, state 1)*/
	sDefBegin = sDefBegin+ "("+sAppName+","+sSelName+")*/";
	CString sDefEnd = "/*}}SME_STATE_DEF*/";
	CString sName; 
	CString sInsertText;
	BOOL bMacroFound = FALSE;
	HTREEITEM hInsert = NULL;
	HTREEITEM hParent = NULL;

	int nErrorPos = 0;
	while(true)
	{
		if (!(OpenedFile).ReadString(sCurLine))
		{
			CString s;
			if (bMacroFound == FALSE)
				s = OpenedFile.GetFilePath()+":	error: unexpected composition in macro "+sDefBegin;
			else
				s = OpenedFile.GetFilePath()+":	error: unexpected composition in macro "+sDefEnd;

		_bstr_t bError(s.GetBuffer());
		Fire_OutPutStringToPane(bError.GetBSTR());
		s.ReleaseBuffer();
	
			return FALSE;
		}
		nErrorPos++;
		sCurLine.TrimLeft();
		sCurLine.TrimRight();

		if (sCurLine.IsEmpty())
			continue;
		if (bMacroFound)
		{
			//if (!sCurLine.Compare(sDefEnd))
			if (sCurLine.Compare(sDefEnd) == 0) // Find it 
				break;

			TV_INSERTSTRUCT Inserter;//inserting item structure
			Inserter.hInsertAfter = TVI_LAST;//set inserting order
			Inserter.hParent = hSelector;
			Inserter.item.mask = TVIF_TEXT|TVIF_PARAM|TVIF_IMAGE;//set mask

			if (sCurLine.Find("SME_STATE_ENTRY_FUNC(") == 0 && sCurLine.ReverseFind(')') == sCurLine.GetLength()-1)
			{
				sInsertText = sCurLine.Mid(21,sCurLine.GetLength()-22);
				sInsertText.TrimLeft();
				sInsertText.TrimRight();

				if (sInsertText.IsEmpty() || sInsertText.Find(' ') != -1 || sInsertText.Find('\t') != -1)
					return nErrorPos*(-1);

				sName = "Entry: ";
				// Test whether it is a empty node
				if (sInsertText.Compare("SME_NULL") != 0 && sInsertText.Compare("0") != 0)
				{
					sName += sInsertText;
					sName += STR_HDLER_PROTOTYPE;
				}

				BOOL bFound = FALSE;
				if (bIsUpdate == TRUE)
				{
					hInsert = tree.GetChildItem(hSelector);
					while (true)
					{
						if (NULL == hInsert)
							break;
						if (tree.GetItemData(hInsert) & STATE_TREE_ENTRY_EXIT_HANDLER_MASK)
						{
							if (sName.Compare(tree.GetItemText(hInsert)) == 0)
							{
								bFound = TRUE;
								DWORD lparam = tree.GetItemData(hInsert);
								lparam |= STATE_TREE_IS_ORIGINAL_ITEM;
								tree.SetItemData(hInsert, lparam);
								break;
							}
						}
						hInsert = tree.GetNextSiblingItem(hInsert);
					}
				}
				if (bFound == FALSE)
				{
					Inserter.item.pszText = (LPTSTR)(LPCSTR)sName;
					Inserter.item.lParam = STATE_TREE_ENTRY_EXIT_HANDLER_MASK;
					if (bIsUpdate == TRUE)
						Inserter.item.lParam |= STATE_TREE_IS_ORIGINAL_ITEM;
					hInsert = tree.InsertItem(&Inserter);
					tree.SetItemImage(hInsert, 4, 4);
				}
				//				Expand(hSelector, TVE_EXPAND);
			}
			else if (sCurLine.Find("SME_STATE_EXIT_FUNC(") == 0 && sCurLine.ReverseFind(')') == sCurLine.GetLength()-1)
			{
				sInsertText = sCurLine.Mid(20,sCurLine.GetLength()-21);
				sInsertText.TrimLeft();
				sInsertText.TrimRight();

				if (sInsertText.IsEmpty() || sInsertText.Find(' ') != -1 || sInsertText.Find('\t') != -1)
					return nErrorPos*(-1);

				sName = "Exit: ";
				// Test whether it is a empty node
				if (sInsertText.Compare("SME_NULL") != 0 && sInsertText.Compare("0") != 0)
				{
					sName += sInsertText;
					sName += STR_HDLER_PROTOTYPE;
				}

				BOOL bFound = FALSE;
				if (bIsUpdate == TRUE)
				{
					hInsert = tree.GetChildItem(hSelector);
					while (true)
					{
						if (NULL == hInsert)
							break;
						if (tree.GetItemData(hInsert) & STATE_TREE_ENTRY_EXIT_HANDLER_MASK)
						{
							if (sName.Compare(tree.GetItemText(hInsert)) == 0)
							{
								bFound = TRUE;
								DWORD lparam = tree.GetItemData(hInsert);
								lparam |= STATE_TREE_IS_ORIGINAL_ITEM;
								tree.SetItemData(hInsert, lparam);
								break;
							}
						}
						hInsert = tree.GetNextSiblingItem(hInsert);
					}
				}

				if (bFound == FALSE)
				{
					Inserter.item.pszText = (LPTSTR)(LPCTSTR)sName;
					Inserter.item.lParam = STATE_TREE_ENTRY_EXIT_HANDLER_MASK;
					if (bIsUpdate == TRUE)
						Inserter.item.lParam |= STATE_TREE_IS_ORIGINAL_ITEM; 
					hInsert = tree.InsertItem(&Inserter);
					tree.SetItemImage(hInsert, 4, 4);
				}
				//				Expand(hSelector, TVE_EXPAND);
			}
			else if (!sCurLine.Find("SME_ON_EVENT(") && sCurLine.ReverseFind(')') == sCurLine.GetLength()-1)
			{
				sInsertText = sCurLine.Mid(13, sCurLine.GetLength()-14);
				sInsertText.TrimLeft();
				sInsertText.TrimRight();

				int nPrePos = sInsertText.Find(',');
				if (nPrePos == -1)
					return nErrorPos*(-1);
				int nBackPos = sInsertText.ReverseFind(',');
				if (nBackPos == -1 || nBackPos == nPrePos)
					return nErrorPos*(-1);

				CString sEvtName = sInsertText.Left(nPrePos);
				sEvtName.TrimLeft();
				sEvtName.TrimRight();
				CString sTransName = sInsertText.Right(sInsertText.GetLength()-nBackPos-1);
				sTransName.TrimLeft();
				sTransName.TrimRight();
				CString sActionName = sInsertText.Mid(nPrePos+1, nBackPos-nPrePos-1);
				sActionName.TrimLeft();
				sActionName.TrimRight();

				if (sEvtName.IsEmpty() || sEvtName.Find(' ') != -1 || sEvtName.Find('\t') != -1 ||
					sTransName.IsEmpty() || sTransName.Find(' ') != -1 || sTransName.Find('\t') != -1 ||
					sActionName.IsEmpty() || sActionName.Find(' ') != -1 || sActionName.Find('\t') != -1)
					return nErrorPos*(-1);
				sName = "";//"Event name:  ";
				sName += sEvtName;

				BOOL bFound = FALSE;
				if (bIsUpdate == TRUE)
				{
					hInsert = tree.GetChildItem(hSelector);
					while (true)
					{
						if (NULL == hInsert)
							break;
						if (tree.GetItemData(hInsert) & STATE_TREE_EVENT_ID_MASK)
						{
							if (sName.Compare(tree.GetItemText(hInsert)) == 0)
							{
								bFound = TRUE;
								DWORD lparam = tree.GetItemData(hInsert);
								if (lparam & STATE_TREE_IS_ORIGINAL_ITEM)
								{
									MessageBox("Error!\nThe duplicate name already exists.","warning", MB_OK|MB_ICONERROR);
									break;
								}
								lparam |= STATE_TREE_IS_ORIGINAL_ITEM;
								tree.SetItemData(hInsert, lparam);
								break;
							}
						}
						hInsert = tree.GetNextSiblingItem(hInsert);
					}
					hParent = hInsert;
				}
				if (bFound == FALSE)
				{
					Inserter.item.pszText = (LPTSTR)(LPCTSTR)sName;
					Inserter.item.lParam = STATE_TREE_EVENT_ID_MASK;

					if (bIsUpdate == TRUE)
						Inserter.item.lParam |= STATE_TREE_IS_ORIGINAL_ITEM;
					hParent = tree.InsertItem(&Inserter);
					tree.SetItemImage(hParent,6,6);
				}


				Inserter.hParent = hParent;
				Inserter.hInsertAfter = TVI_LAST;
				Inserter.item.mask = TVIF_TEXT | TVIF_PARAM | TVIF_IMAGE;
				Inserter.item.lParam = STATE_TREE_TRANSITION_MASK;
				sName = "Transit to:  ";
				if (!sTransName.Compare("SME_INTERNAL_TRAN"))
				{
					Inserter.item.pszText = STR_INTERNAL_TRAN;
					sName = STR_INTERNAL_TRAN;
				}
				else
				{
					sName += sTransName;
					Inserter.item.pszText = (LPTSTR)(LPCTSTR)sName;
				}

				if (bIsUpdate == TRUE)
				{
					hInsert = tree.GetChildItem(hParent);

					if (hInsert == NULL) 
					{
						Inserter.item.lParam |= STATE_TREE_IS_ORIGINAL_ITEM;
						hInsert = tree.InsertItem(&Inserter);
						tree.SetItemImage(hInsert, 5, 5);
					}
					else
					{
						while (true)
						{
							if (tree.GetItemData(hInsert) & STATE_TREE_TRANSITION_MASK)
							{
								if (sName.Compare(tree.GetItemText(hInsert)) != 0)
									tree.SetItemText(hInsert, sName);

								DWORD lparam = tree.GetItemData(hInsert);
								lparam |= STATE_TREE_IS_ORIGINAL_ITEM;
								tree.SetItemData(hInsert, lparam);
								break;
							}
							hInsert = tree.GetNextSiblingItem(hInsert);	
						}
					}
				}
				else
				{
					hInsert = tree.InsertItem(&Inserter);
					tree.SetItemImage(hInsert, 5, 5);
				}

				sName = "Action:  ";

				if (sActionName.Compare("SME_NULL") != 0 && sInsertText.Compare("0") != 0)
				{
					sName += sActionName;
					sName += STR_HDLER_PROTOTYPE;
				}
				Inserter.item.pszText = (LPTSTR)(LPCTSTR)sName;
				Inserter.item.lParam = STATE_TREE_EVENT_HANDLER_MASK;

				if (bIsUpdate == TRUE)
				{
					hInsert = tree.GetChildItem(hParent);
					hInsert = tree.GetNextSiblingItem(hInsert);

					if (hInsert == NULL) 
					{
						Inserter.item.lParam |= STATE_TREE_IS_ORIGINAL_ITEM;
						hInsert = tree.InsertItem(&Inserter);
						tree.SetItemImage(hInsert, 4, 4);
					}
					else
					{
						while (true)
						{
							if (tree.GetItemData(hInsert) & STATE_TREE_EVENT_HANDLER_MASK)
							{
								if (sName.Compare(tree.GetItemText(hInsert)) != 0)
									tree.SetItemText(hInsert, sName);

								DWORD lparam = tree.GetItemData(hInsert);
								lparam |= STATE_TREE_IS_ORIGINAL_ITEM;
								tree.SetItemData(hInsert, lparam);
								break;
							}
							hInsert = tree.GetNextSiblingItem(hInsert);
						}
					}
				}
				else
				{
					hInsert= tree.InsertItem(&Inserter);
					tree.SetItemImage(hInsert, 4, 4);
				}
			}
			else
			{
				return nErrorPos*(-1);
			}
		}
		else
		{
			//if (!sCurLine.Compare(sDefBegin))
			if (sCurLine.Compare(sDefBegin) == 0) // Find it 
				bMacroFound = TRUE;
		}
	}
	(OpenedFile).Seek(nFilePos,CFile::begin);
	return TRUE;
}



By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Alex "Question is more important than the answer."

Comments and Discussions