/**********************************************************************
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;
}