/**********************************************************************
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
*************************************************************************/
#include "stdafx.h"
#include "DSUtils.h"
#include "stringop.h"
#include "..\Common\ParamStore.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
using namespace std;
/*
#ifdef VS2005
using namespace EnvDTE80;
extern CComPtr<EnvDTE::DTE2> g_pDTE;
#else
extern CComPtr<EnvDTE::_DTE> g_pDTE;
#endif
*/
#define START_COL_POS 5
#define OUTPUT_WINDOW_NAME L"StateWizard"
// set g_nMaxLevelNum for limiting level of chart to be shown
int g_nMaxLevelNum = CParamStore::GetInstance().GetIntValue("StateChart","MaxLevel") == -1
? DEF_STATE_CHART_MAX_LEVEL : CParamStore::GetInstance().GetIntValue("StateChart","MaxLevel");
int g_nFileType = CParamStore::GetInstance().GetIntValue("StateChart","FileType") == -1
? 0 : CParamStore::GetInstance().GetIntValue("StateChart","FileType");//0 means *.cpp,1 means *.c
//////////////////////////////////////////////////////////////////////////////////////////////////////////
void TrimSpace(CString& sStr)
{
sStr.TrimLeft();
sStr.TrimRight();
sStr.Replace("\t", NULL);
sStr.Replace(" ", NULL);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////
CString BSTR2CString(BSTR bstr)
{
char* bstrPath = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrPath);
delete[]bstrPath;
return sResult;
}
DSUtils::DSUtils()
{
/*HRESULT re = g_pDTE->get_Solution(&m_pSolution);
ATLASSERT(SUCCEEDED(re));
re = m_pSolution->get_Projects(&m_pProjects);
ATLASSERT(SUCCEEDED(re));
re = g_pDTE->get_ItemOperations(&m_pItemOperation);
ATLASSERT(SUCCEEDED(re));
prjCount = GetProjectCount();*/
}
DSUtils::~DSUtils()
{
/*m_pSolution = NULL;
m_pItemOperation = NULL;
prjCount = -1;*/
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION:Get the full path of the solution
// INPUT: None
// OUTPUT: The full path
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
_bstr_t DSUtils::GetSlnPath()
{
BSTR bstrRet;
CComPtr<EnvDTE::_Solution> m_pSolution;
HRESULT re = g_pDTE->get_Solution(&m_pSolution);
ATLASSERT(SUCCEEDED(re));
m_pSolution->get_FullName(&bstrRet);
return _bstr_t(bstrRet,false);
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get the solution name from its file path name
// INPUT: None
// OUTPUT: The solution name
// NOTE:Using GetSlnPath get the full path and then cut into filename
///////////////////////////////////////////////////////////////////////////////////////////
_bstr_t DSUtils::GetSlnName()
{
_bstr_t bstrPath = GetSlnPath();
_bstr_t bstrRet;
do
{
if (bstrPath.length() < 5)
break;
wstring strSolution = static_cast<WCHAR*>(bstrPath);
StringOp<wchar_t>::ReplaceChr(strSolution,L'/',L'\\');
StringOp<wchar_t>::size_type idxBegin = strSolution.find_last_of(L'\\');
StringOp<wchar_t>::size_type idxLast = strSolution.find_last_of(L'.');
if(-1 == idxBegin||-1 == idxLast)
break;
strSolution = strSolution.substr(idxBegin+1,idxLast-idxBegin-1);
bstrRet = _bstr_t(strSolution.c_str());
} while(false);
return bstrRet;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Retrieve the given project directory name
// INPUT: Project name
// OUTPUT: Project directory name
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
_bstr_t DSUtils::GetProjectDir(const _bstr_t &sProject)
{
ATLASSERT(g_pDTE != NULL );
_bstr_t bstrRet = "";
BSTR bstr = NULL;
// if don't get the project then return NULL
if(!sProject)
return _bstr_t(NULL, false);
else
{
CComPtr<EnvDTE::Project> prj = GetProject(sProject);
if(prj!= NULL)
{
prj->get_FullName(&bstr);
}
else
return _bstr_t(NULL, false);
}
wchar_t *p = wcsrchr(bstr, L'\\');
if(NULL != p)
{
BSTR bstrPath = ::SysAllocStringLen(bstr, (UINT)(p-bstr));
bstrRet = _bstr_t(bstrPath, false);
}
::SysFreeString(bstr);
ATLASSERT(0 != bstrRet.length());
return bstrRet;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Open file in client window
// INPUT: The file name
// OUTPUT: TRUE:Success FALSE: Failed
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::OpenFile(_bstr_t &sFile)
{
ATLASSERT(g_pDTE != NULL );
CComPtr<EnvDTE::ItemOperations> m_pItemOperation;
HRESULT re = g_pDTE->get_ItemOperations(&m_pItemOperation);
ATLASSERT(SUCCEEDED(re));
CComBSTR viewTye(EnvDTE::vsViewKindCode);
CComPtr<EnvDTE::Window> pWindows =NULL;
re = m_pItemOperation->OpenFile(sFile.GetBSTR(),viewTye,&pWindows);
return SUCCEEDED(re);
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION:If has any c/cpp/h file opened in DTE
// INPUT: NO
// OUTPUT: True means there are c/cpp/h file opened in DTE,FALSE means there is not.....
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::HasCodeFileOpen()
{
long count = 0;
CComPtr<EnvDTE::Documents> docs;
g_pDTE->get_Documents(&docs);
docs->get_Count(&count);
if(count>0)
{
for(long i = 1;i<=count;i++)
{
CComVariant var(i);
CComPtr<EnvDTE::Document> doc;
docs->Item(var,&doc);
BSTR fileName;
doc->get_FullName(&fileName);
_bstr_t fileNameWapper(fileName,false);
CString FileName(fileName);
FileName.MakeLower();
if(FileName.Right(2)==".c"||FileName.Right(4)==".cpp"||FileName.Right(2)==".h")
{
return TRUE;
}
}
return FALSE;
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get project count in workspace/solution.
// INPUT: None
// OUTPUT: The number of projects.
///////////////////////////////////////////////////////////////////////////////////////////
long DSUtils::GetProjectCount()
{
ATLASSERT(g_pDTE != NULL );
CComPtr<EnvDTE::_Solution> m_pSolution;
CComPtr<EnvDTE::Projects> m_pProjects;
HRESULT re = g_pDTE->get_Solution(&m_pSolution);
ATLASSERT(SUCCEEDED(re));
re = m_pSolution->get_Projects(&m_pProjects);
ATLASSERT(SUCCEEDED(re));
long lCount = 0;
re = m_pProjects->get_Count(&lCount);
ATLASSERT(SUCCEEDED(re));
return lCount;
}
/*******************************************************************************************
DESCRIPTION: Get project object in workspace/solution.
INPUT: Project name if bIsFileName is FALSE by default
or the relative file name if bIsFileName is TRUE.
OUTPUT: The project object.
*******************************************************************************************/
CComPtr<EnvDTE::Project> DSUtils::GetProject(const _bstr_t &sProject, BOOL bIsFileName)
{
CComPtr<EnvDTE::_Solution> m_pSolution;
CComPtr<EnvDTE::Projects> m_pProjects;
HRESULT re = g_pDTE->get_Solution(&m_pSolution);
ATLASSERT(SUCCEEDED(re));
re = m_pSolution->get_Projects(&m_pProjects);
ATLASSERT(SUCCEEDED(re));
CComPtr<EnvDTE::Project> spFoundProj = NULL;
ATLASSERT(g_pDTE != NULL );
ATLASSERT(m_pProjects!=NULL);
long count = GetProjectCount();
VARIANT va;
VariantInit(&va);
V_VT(&va)= VT_UINT;
for(long i = 1;i<= count;i++)
{
V_UINT(&va) = i;
CComPtr<EnvDTE::Project> spTempProj;
m_pSolution->Item(va,&spTempProj);
BSTR pname = NULL;
if (bIsFileName)
{
spTempProj->get_FullName(&pname);
CString sFullFileName(pname), sFile(static_cast<wchar_t*>(sProject));
sFullFileName.MakeLower();
sFile.MakeLower();
int nLen = sProject.length();
if (sFullFileName.Right(nLen) == sFile)
{
spFoundProj = spTempProj;
break;
}
}
else
{
spTempProj->get_Name(&pname);
_bstr_t s(pname, false);
if(0 == wcsicmp(s, sProject)) // not case sensitive
{
spFoundProj = spTempProj;
break;
}
}
}
VariantClear(&va);
return spFoundProj;
}
/*******************************************************************************************
DESCRIPTION: Get project object in workspace/solution.
INPUT: The project name
OUTPUT: The project object.
*******************************************************************************************/
CComPtr<EnvDTE::Project> DSUtils::GetProjectByFileName(const _bstr_t &sPrjFileName)
{
return GetProject(sPrjFileName, TRUE);
}
void DSUtils::GetProjectList(vector<_bstr_t>& PrjFullNameList)
{
CComPtr<EnvDTE::_Solution> m_pSolution;
CComPtr<EnvDTE::Projects> m_pProjects;
HRESULT re = g_pDTE->get_Solution(&m_pSolution);
ATLASSERT(SUCCEEDED(re));
re = m_pSolution->get_Projects(&m_pProjects);
ATLASSERT(SUCCEEDED(re));
long n = GetProjectCount();
VARIANT va;
VariantInit(&va);
V_VT(&va)= VT_UINT;
PrjFullNameList.clear();
for(long count = 1 ; count<= n;count++)
{
V_UINT(&va) = count;
CComPtr<EnvDTE::Project> prj;
HRESULT re = m_pProjects->Item(va,&prj);
ATLASSERT(SUCCEEDED(re));
BSTR sPrjName, sPrjFullName;
re = prj->get_FullName(&sPrjFullName);
re = prj->get_Name(&sPrjName); // Jerry Ding. Use project name intead.
/* NOTE: In some cases, there is a project named "Miscellaneous Files" in VS.NET English edition. WHY???
The full path name is empty.
*/
if (sPrjFullName == NULL || sPrjFullName[0] == 0)
continue;
if(wcslen(static_cast<wchar_t*>(sPrjName))>0)
PrjFullNameList.push_back(sPrjName);
}
VariantClear(&va);
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get the header or source file full name list
// INPUT:
// OUTPUT: 1) Header file list; 2) Source file list.
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::GetSrcFileList(CComPtr<EnvDTE::Project>& prj, vector<_bstr_t>& HeaderFileList, vector<_bstr_t>& SourceFileList)
{
ATLASSERT(prj!=NULL);
SourceFileList.clear();
HeaderFileList.clear();
CComPtr<EnvDTE::ProjectItems> prjItems;
prj->get_ProjectItems(&prjItems);
if (prjItems==NULL)
return FALSE;
return GetFileFromPrjItems(prjItems, HeaderFileList, SourceFileList);
/*
long n ;
prjItems->get_Count(&n);
for(long count = 1 ; count<= n;count++)
{
CComVariant var(count);
CComPtr<EnvDTE::ProjectItem> prjItem;
HRESULT re = prjItems->Item(var,&prjItem);
if(prjItem!=NULL)
{
short fileCount;
BSTR wa;
prjItem->get_Name(&wa);
_bstr_t fileListName(wa,false);
TAG_FILELIST_STATE fileListState;
if(wcsstr(static_cast<wchar_t*>(fileListName),L"Source Files")!=NULL)
{
fileListState = TAG_SOURCE_FILE_STATE;
}
else if(wcsstr(static_cast<wchar_t*>(fileListName),L"Header Files")!=NULL)
{
fileListState = TAG_HEAD_FILE_STATE;
}
else
{
fileListState = TAG_OTHER_FILE_STATE;
continue;//to the next item
}
prjItem->get_FileCount(&fileCount);
CComPtr<EnvDTE::ProjectItems> items;
prjItem->get_ProjectItems(&items);
for(short i = 1;i<= fileCount; i++)
{
CComPtr<EnvDTE::ProjectItem> itemContainFile;
items->Item(CComVariant(i),&itemContainFile);
BSTR fileName;
itemContainFile->get_FileNames(1,&fileName);
_bstr_t fileNameWapper(fileName,false);
if(fileListState==TAG_SOURCE_FILE_STATE)
{
SourceFileList.push_back(fileNameWapper);
}
if(fileListState ==TAG_HEAD_FILE_STATE)
{
HeaderFileList.push_back(fileNameWapper);
}
}
}
}
*/
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: By giving the Project Items ,get the head file list & the source file list
// INPUT: Project Items Object
// OUTPUT: 1) Header file list; 2) Source file list.
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::GetFileFromPrjItems(CComPtr<EnvDTE::ProjectItems> prjItems,vector<_bstr_t>& HeaderFileList, vector<_bstr_t>& SourceFileList)
{
if (prjItems==NULL)
return FALSE;
//ATLASSERT(prjItems!=NULL);
long count;
HRESULT re = prjItems->get_Count(&count);
ATLASSERT(SUCCEEDED(re));
if(count==0)
{
return TRUE;
}
for(long i = 1;i<=count;i++)
{
CComVariant var(i);
CComPtr<EnvDTE::ProjectItem> prjItem;
HRESULT re = prjItems->Item(var,&prjItem);
if(prjItem!=NULL)
{
// leaf
BSTR fileName;
prjItem->get_FileNames(1,&fileName);
CString sFileName(fileName);
_bstr_t fileNameWapper(fileName,false);
sFileName.MakeLower();
size_t len = wcslen(fileName);
if (sFileName.Right(2) == ".c" || sFileName.Right(4) == ".cpp")
SourceFileList.push_back(fileNameWapper);
else if (sFileName.Right(2) == ".h")
HeaderFileList.push_back(fileNameWapper);
CComPtr<EnvDTE::ProjectItems> ChildPrjItems;
re = prjItem->get_ProjectItems(&ChildPrjItems);
ATLASSERT(SUCCEEDED(re));
GetFileFromPrjItems(ChildPrjItems, HeaderFileList, SourceFileList);
}
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION:Delete the specific src file&source file from projectitems
// INPUT: 1)prjItems: ProjectItems to be deleted fils.
// 2)srcFile: Header file path where moved item locates
// 3)headFile: State name of moved item
// OUTPUT: 1)TRUE: SUCCESS
// 2)FALSE: There are no items in the ProjectItems.
// NOTE: srcFile,headFile need to been maked lower before being passed to this function.
//////////////////////////////////////////////////////////////////////////
BOOL DSUtils::DelSrcHldFilesFromPrjItems(CComPtr<EnvDTE::ProjectItems> prjItems,CString& srcFile, CString& headFile/*make sure that the srcFile& headFile has been maked lower.*/)
{
if (prjItems==NULL)
return FALSE;
long count;
HRESULT re = prjItems->get_Count(&count);
ATLASSERT(SUCCEEDED(re));
if(count==0)
{
return TRUE;
}
for(long i = 1;i<=count;i++)
{
CComVariant var(i);
CComPtr<EnvDTE::ProjectItem> prjItem;
HRESULT re = prjItems->Item(var,&prjItem);
if(prjItem!=NULL)
{
// leaf
BSTR fileName;
prjItem->get_FileNames(1,&fileName);
CString sFileName(fileName);
_bstr_t fileNameWapper(fileName,false);
sFileName.MakeLower();
if(sFileName==srcFile||sFileName==headFile)
{
prjItem->Remove();
continue;
}
CComPtr<EnvDTE::ProjectItems> ChildPrjItems;
re = prjItem->get_ProjectItems(&ChildPrjItems);
ATLASSERT(SUCCEEDED(re));
DelSrcHldFilesFromPrjItems(ChildPrjItems, srcFile, headFile);
}
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get active project. In VS.NET, return the first startup project.
// INPUT: None
// OUTPUT: Active project object.
// NOTE: DTE::Solution::solutionBuild::StartupProjects[0]
// StartupProjects contains a list of projects that "start" when the Run command is issued.
///////////////////////////////////////////////////////////////////////////////////////////
CComPtr<EnvDTE::Project> DSUtils::GetActiveProject()
{
CComPtr<EnvDTE::Project> prj = GetFirstStartupProject();
if (prj) return prj;
// IMPORTANT NOTE: Startup project may be empty.
// ATLASSERT(prj!=NULL);
// Temp solution: use ActiveSolutionProjects[0] instead.
VARIANT actPrjs;
HRESULT re=g_pDTE->get_ActiveSolutionProjects(&actPrjs);
ATLASSERT(SUCCEEDED(re));
SAFEARRAY *a=actPrjs.parray;
VARIANT tempVariant;
LONG i[1]={a->rgsabound[0].lLbound};
for(LONG p = i[0];p<static_cast<long>(a->rgsabound[0].cElements);p++)
{
HRESULT re = SafeArrayGetElement(a,&p,&tempVariant);
if(FAILED(re))break;
IDispatch* idp = tempVariant.pdispVal;
CComPtr<EnvDTE::Project> tempPrj;
idp->QueryInterface(__uuidof(EnvDTE::Project), (LPVOID*)&tempPrj);
if(tempPrj)
{
return tempPrj;
}
}
return NULL;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get active project. In VS.NET, return the first startup project.
// INPUT: None
// OUTPUT: First startup project object.
// NOTE: DTE::Solution::solutionBuild::StartupProjects[0]
// StartupProjects contains a list of projects that "start" when the Run command is issued.
// Return value may be empty, for example App.vcproj, the project name is App1.
///////////////////////////////////////////////////////////////////////////////////////////
CComPtr<EnvDTE::Project> DSUtils::GetFirstStartupProject()
{
CComPtr<EnvDTE::_Solution> so;
HRESULT re = g_pDTE->get_Solution(&so);
ATLASSERT(SUCCEEDED(re));
CComPtr<EnvDTE::SolutionBuild> sb;
re = so->get_SolutionBuild(&sb);
ATLASSERT(SUCCEEDED(re));
BSTR s;
so->get_FileName(&s);
CComVariant variant;
sb->get_StartupProjects(&variant);
if(variant.vt == VT_EMPTY)
return NULL;
SAFEARRAY* array = variant.parray;
long ix = 0;
VARIANT var;
if(SafeArrayGetElement(array, &ix, &var) != S_OK)
return NULL;
//_bstr_t startUpRrjName(var.bstrVal,false);
// The return startup project is subdir\file.vcproj for example: App\App.vcproj. Remove the file name.
/*
CString sFile(var.bstrVal);
int nBegin = sFile.ReverseFind('\\');
nBegin ++;
int nEnd = sFile.ReverseFind('.');
if (nEnd==-1) nBegin = 999;
CString sPrj = sFile.Mid(nBegin,nEnd-nBegin);
*/
_bstr_t startUpRrjName(var.bstrVal);
CComPtr<EnvDTE::Project> prj = GetProjectByFileName(startUpRrjName);
return prj;
// IMPORTANT NOTE: Startup project may be empty.
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get active project name
// INPUT: None
// OUTPUT: The active project name.
///////////////////////////////////////////////////////////////////////////////////////////
_bstr_t DSUtils::GetActiveProjectName()
{
BSTR bstr = NULL;
// if don't get the active project then return NULL
if(!GetActiveProject())
return _bstr_t(NULL, false);
else
GetActiveProject()->get_Name(&bstr); /* here don't alloc memory to bstr */
_bstr_t bstrRet = _bstr_t(bstr, false);
return bstrRet;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get the mapfile full path.
// INPUT: 1)sMapfilePath: a string to record the mapfile path
// OUTPUT: zero or nonzero
// NOTE:
//////////////////////////////////////////////////////////////////////////
/*BOOL DSUtils::GetRcfilePath(CString &sRcFilePath)
{
CComPtr<EnvDTE::Project> activeProject = GetActiveProject();
CComPtr<EnvDTE::ProjectItems> prjItems;
activeProject->get_ProjectItems(&prjItems);
long n ;
prjItems->get_Count(&n);
for(long count = 1 ; count<= n;count++)
{
CComVariant var(count);
CComPtr<EnvDTE::ProjectItem> prjItem;
HRESULT re = prjItems->Item(var,&prjItem);
if(prjItem!=NULL)
{
short fileCount;
BSTR wa;
prjItem->get_Name(&wa);
_bstr_t fileListName(wa,false);
TAG_FILELIST_STATE fileListState;
if(wcsstr(static_cast<wchar_t*>(fileListName),L"Resource Files")!=NULL)
{
fileListState = TAG_RESOURCE_FILE_STATE;
}
else
{
fileListState = TAG_OTHER_FILE_STATE;
continue;//to the next item
}
prjItem->get_FileCount(&fileCount);
CComPtr<EnvDTE::ProjectItems> items;
prjItem->get_ProjectItems(&items);
for(short i = 1;i<= fileCount; i++)
{
CComPtr<EnvDTE::ProjectItem> itemContainFile;
items->Item(CComVariant(i),&itemContainFile);
BSTR fileName;
itemContainFile->get_FileNames(1,&fileName);
_bstr_t fileNameWapper(fileName,false);
if(wcsstr(static_cast<wchar_t*>(fileNameWapper),L".rc")!=NULL)
{
sRcFilePath = static_cast<WCHAR*>(fileNameWapper);
return TRUE;
}
}
}
}
return FALSE;
}*/
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get active project file list including head files and source files.
// INPUT: 1) PrjFileList: a project file list Array.
// OUTPUT: None.
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
void DSUtils::GetProjectFileList(CComPtr<EnvDTE::Project> prj, vector<_bstr_t> &PrjFileList)
{
CComPtr<EnvDTE::Project> prjTemp = prj;
if(prj==NULL)
{
prjTemp = GetActiveProject();
}
vector<_bstr_t> HeadFileList,SourceFileList,TotalFileList;
GetSrcFileList(prjTemp,HeadFileList,SourceFileList);
PrjFileList.clear();
PrjFileList.insert(PrjFileList.begin(),SourceFileList.begin(),SourceFileList.end());
PrjFileList.insert(PrjFileList.begin(),HeadFileList.begin(),HeadFileList.end());
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Test the given document is opened or not
// INPUT: 1) sFullPath: a given File full path.
// 2) bAutoSave: Automatically save current file
// OUTPUT: None.
// NOTE: The pattern of function implementation if <FunctionName> ... {
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::TestOpenedDocIsModified(LPCSTR sFullPath, BOOL bAutoSave)
{
ATLASSERT(g_pDTE!=NULL);
CComPtr<EnvDTE::Documents> tDocuments;
g_pDTE->get_Documents(&tDocuments);
CComQIPtr<EnvDTE::Documents,&EnvDTE::IID_Documents> spActiveDocs(tDocuments);
ATLASSERT(spActiveDocs);
//record the num of opened documents
long openedDocNum = 0;
// get active document num in documents
spActiveDocs->get_Count(&openedDocNum);
// resource file should not be opened
for (long i = 1L; i <= openedDocNum; i++)
{
BSTR bstr = NULL;
_bstr_t bstrRet("");
CComPtr<EnvDTE::Document> spDoc;
spActiveDocs->Item(_variant_t(i, VT_I4),&spDoc);
CComQIPtr<EnvDTE::Document,&EnvDTE::IID_Document> pGenericDocQIPtr(spDoc);
pGenericDocQIPtr->get_FullName(&bstr);
bstrRet = _bstr_t(bstr, false);
char* docPath = _com_util::ConvertBSTRToString(bstrRet.GetBSTR());
CString sOpenedDocPath(docPath);
delete []docPath;
VARIANT_BOOL vbSaved;
if (!sOpenedDocPath.CompareNoCase(sFullPath))
{
pGenericDocQIPtr->get_Saved(&vbSaved);
if (vbSaved == VARIANT_FALSE)
{
if (bAutoSave == TRUE)
{
EnvDTE::vsSaveStatus retval;
CComBSTR sBfullPath(sFullPath);
pGenericDocQIPtr->Save(sBfullPath,&retval);
// Save twice to ensure to save file which is opened by another editor.
pGenericDocQIPtr->get_Saved(&vbSaved);
if (vbSaved == VARIANT_FALSE)
pGenericDocQIPtr->Save(sBfullPath.m_str,&retval);
}
return TRUE;
}
else
return FALSE;
}
}
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Parse the state of the given line.
// INPUT: 1) sCleanLine: a given line string.
// 2) nCommentState: the comment state of the given line.
// including (NO_COMMENT_STATE,SLASH_COMMENT_STATE,ASTERISK_COMMENT_STATE,SLASH_CODE_STATE).
// 3) CountResultArray: Record the different state line's number.
// 4) nFuncPosLine: Record the function existed linenumber.
// OUTPUT:
// *) sCleanLine: the code string with comment removed.
// *) nCommentState: the code parsing state.
// *) return: whether mix code and comment.
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
//***************************** never tested *****************************
BOOL DSUtils::ParseCommentState(CString &sCleanLine, UCHAR &nCommentState, UINT *CountResultArray, UINT *nFuncPosLine)
{
int pastParseFlag = -1;
sCleanLine.TrimLeft();
CString sCurrentLine = sCleanLine;
sCleanLine= "";
BOOL bInvokedByTagDB = FALSE;
BOOL bIsContexJoint = FALSE;
if (CountResultArray == NULL)
bInvokedByTagDB = TRUE;
if (bInvokedByTagDB)
(*nFuncPosLine)++;
if (sCurrentLine.IsEmpty())
{
if (!bInvokedByTagDB)
CountResultArray[BLANK_LINES]++;
return FALSE;
}
while(true)
{
// Case with no comments before or met with matched asterisk comments
if (nCommentState == NO_COMMENTS_STATE)
{
if (sCurrentLine.IsEmpty())
break;
int nSlashPos = sCurrentLine.Find("//");
int nAsteriskPos = sCurrentLine.Find("/*");
// Calculate relative line attribute
if (-1 == nSlashPos && nAsteriskPos == -1)
{
if (sCurrentLine.GetAt(sCurrentLine.GetLength()-1) == '\\')
{
bIsContexJoint = TRUE;
nCommentState = SLASH_CODES_STATE;
}
if (!bInvokedByTagDB)
{
if ((pastParseFlag != MIXED_LINES) &&
(pastParseFlag != CODE_LINES))
{
CountResultArray[CODE_LINES]++;
pastParseFlag = CODE_LINES;
}
}
else
{
if (bIsContexJoint == TRUE)
sCurrentLine = sCurrentLine.Left(sCurrentLine.GetLength()-1);
sCleanLine += sCurrentLine;
}
}else if (0 == nSlashPos || nAsteriskPos == 0)
{
if (!bInvokedByTagDB)
{
if ((pastParseFlag != COMMENT_LINES) &&
(pastParseFlag != MIXED_LINES))
{
CountResultArray[COMMENT_LINES]++;
pastParseFlag = COMMENT_LINES;
}
}
}
else
{
if (!bInvokedByTagDB)
{
if (pastParseFlag != MIXED_LINES)
{
if (pastParseFlag == COMMENT_LINES)
CountResultArray[COMMENT_LINES]--;
if (pastParseFlag == CODE_LINES)
CountResultArray[CODE_LINES]--;
CountResultArray[COMMENT_LINES]++;
CountResultArray[CODE_LINES]++;
CountResultArray[MIXED_LINES]++;
pastParseFlag = MIXED_LINES;
}
}
}
////////////////make markup
if (nSlashPos == 0 ||
nAsteriskPos > nSlashPos && nSlashPos != -1 ||
nSlashPos != -1 && nAsteriskPos == -1)
{
nCommentState = SLASH_COMMENTS_STATE;
if (bInvokedByTagDB)
sCleanLine += sCurrentLine.Left(nSlashPos);
continue;
}
if (nAsteriskPos == 0 ||
nSlashPos > nAsteriskPos && nAsteriskPos != -1 ||
nAsteriskPos != -1 && nSlashPos == -1)
{
nCommentState = ASTERISK_COMMENTS_STATE;
if (bInvokedByTagDB)
sCleanLine += sCurrentLine.Left(nAsteriskPos);
sCurrentLine = sCurrentLine.Right(sCurrentLine.GetLength() - nAsteriskPos -2);
sCurrentLine.TrimLeft();
continue;
}
break;
}
else if (nCommentState == ASTERISK_COMMENTS_STATE)
{
if (sCurrentLine.IsEmpty())
break;
int antiAsterIdx = sCurrentLine.Find("*/");
if (!bInvokedByTagDB)
{
if ((pastParseFlag != MIXED_LINES) &&
(pastParseFlag != COMMENT_LINES))
{
CountResultArray[COMMENT_LINES]++;
pastParseFlag = COMMENT_LINES;
}
}
if (antiAsterIdx != -1)
{
nCommentState = NO_COMMENTS_STATE;
sCurrentLine = sCurrentLine.Right(sCurrentLine.GetLength() - antiAsterIdx -2);
int len = sCurrentLine.GetLength();
sCurrentLine.TrimLeft();
if (bInvokedByTagDB)
{
int trimSpaceNum = len-sCurrentLine.GetLength();
for (int i = 0; i < trimSpaceNum; i++)
sCleanLine += " ";
}
continue;
}
break;
}
else if (nCommentState == SLASH_COMMENTS_STATE)
{
if (!bInvokedByTagDB)
{
if ((pastParseFlag != MIXED_LINES) &&
(pastParseFlag != COMMENT_LINES))
CountResultArray[COMMENT_LINES]++;
}
if (sCurrentLine.GetAt(sCurrentLine.GetLength()-1) != '\\')
nCommentState = NO_COMMENTS_STATE;
break;
}
else
{
if (!bInvokedByTagDB)
CountResultArray[CODE_LINES]--;
nCommentState = NO_COMMENTS_STATE;
continue;
}
}
sCleanLine.TrimLeft();
sCleanLine.TrimRight();
return bIsContexJoint;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Deal with code change in source file when moving state item
// INPUT: 1)pTextSrcSelQIPtr: Text selection of source file
// 2)sSrcFilePath: Source file path
// 3)nHdrStateLineNo: Line number of moved state in header file
// 4)nHdrNewParSibLineNo: Line number to be inserted in
// 5)nMoveStateSum: Sum of states under moved state item
// 6)nStartLineNo: Start line number denoting where white space clearing starts
// 7)nEndLineNo: End line number denoting where white space clearing ends
//
// OUTPUT: 1)TRUE: Success
// 2)FALSE: Fail
// NOTE:
//////////////////////////////////////////////////////////////////////////
BOOL DSUtils::MoveStateDef(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSrcSelQIPtr,
LPCTSTR sSrcFilePath,
LPCTSTR sNewParentName,
LPCTSTR sAppName,
long nSrcStateLine,
long nSrcParSibLine,
long nMoveStateSum,
long nStartLineNo,
long nEndlLineNo)
{
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//EnvDTE::DsMovementOptions::dsExtend))))//dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->MoveTo(nSrcStateLine, 1,VARIANT_BOOL(EnvDTE::dsMove))))// CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend))))//CComVariant(dsExtend))))
return FALSE;
// Get the wanted to be modified line
BSTR bstrChangeLine;
//pTextSrcSelQIPtr->SelectLine();
if(FAILED(pTextSrcSelQIPtr->get_Text(&bstrChangeLine)))
return FALSE;
char* ChangeLine = _com_util::ConvertBSTRToString(bstrChangeLine);
CString sLine=ChangeLine;
delete[]ChangeLine;
::SysFreeString(bstrChangeLine);
int idx = sLine.ReverseFind(',');
if (idx == -1)
{
CString sWarningMsg;
sWarningMsg.Format("%s(%d) error: illegal syntax", (CString)sSrcFilePath, nSrcStateLine);
return FALSE;
}
CString sDefaultState = sLine.Right(sLine.GetLength()-idx);
sLine=sLine.Left(idx);
idx = sLine.ReverseFind(',');
if (idx == -1)
{
CString sWarningMsg;
sWarningMsg.Format("%s(%d) error: illegal syntax", (CString)sSrcFilePath, nSrcStateLine);
return FALSE;
}
sLine = sLine.Left(idx+1);
if (((CString)sNewParentName).CompareNoCase(sAppName) == 0)
sLine = sLine+"0"+sDefaultState;
else
sLine = sLine+sNewParentName+sDefaultState;
// Put the modified line text
if (FAILED(pTextSrcSelQIPtr->put_Text(CComBSTR(sLine))))
return FALSE;
////////////////////////////////////////////////////////////////////////////////////
if (FAILED(pTextSrcSelQIPtr->MoveTo(nSrcStateLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
VARIANT_BOOL vbFound;
while (true)
{
if (nMoveStateSum == 0)
break;
//if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR("SME_STATE"), EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR("SME_STATE"),EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
//MessageBox(_T((CString)sSrcFilePath+" error:SME_STATE expected."),MB_ICONERROR|MB_OK);
return FALSE;
}
else
nMoveStateSum--;
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
}
long nMovedStateEndLineNo;
pTextSrcSelQIPtr->get_CurrentLine(&nMovedStateEndLineNo);
// Select the lines from nSrcStateLine to nMovedStateEndLineNo
if (FAILED(pTextSrcSelQIPtr->MoveTo(nSrcStateLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->MoveTo(nMovedStateEndLineNo+1, 1 , VARIANT_BOOL(EnvDTE::dsExtend)))) // 1: Moves the insertion point to the first column.
return FALSE;
if (FAILED(pTextSrcSelQIPtr->Cut()))
return FALSE;
// Past the selection to the new insert line
int nNewInsertLine;
if (nSrcParSibLine > nSrcStateLine)
nNewInsertLine= nSrcParSibLine-(nMovedStateEndLineNo-nSrcStateLine+1);
else
nNewInsertLine= nSrcParSibLine;
if (FAILED(pTextSrcSelQIPtr->MoveTo(nNewInsertLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->Paste()))
return FALSE;
// Release the selection.
pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Deal with state declaration code change in header file when moving state item
// INPUT: 1)pTextHdrSelQIPtr: Text selection of header file
// 2)sHdrFilePath: Header file path
// 3)nHdrStateLineNo: Line number of moved state in header file
// 4)nHdrNewParSibLineNo: Line number to be inserted in
// 5)nMoveStateSum: Sum of states under moved state item
//
// OUTPUT: 1)TRUE: Success
// 2)FALSE: Fail
// NOTE: Cut the lines between nHdrStateLineNo and nInsertEndlineNo to the original line point nHdrNewParSibLineNo.
/////////////////////////////////////////////////////////////////////////
BOOL DSUtils::MoveStateDec(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr,
LPCTSTR sHdrFilePath,
long nHdrStateLineNo,
long nHdrNewParSibLineNo,
long nMoveStateSum)
{
//////////////////////////////////////////////////////////
// Move state declaration.
if (nHdrNewParSibLineNo == nHdrStateLineNo) // Copy/Paste to the same location.
return TRUE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrStateLineNo, 1,VARIANT_BOOL(EnvDTE::dsMove))))// CComVariant(dsMove))))
return FALSE;
long nMovedStateEndLineNo;
VARIANT_BOOL vbFound;
while (true)
{
if (nMoveStateSum == 0)
break;
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR("SME_STATE_DECLARE"), EnvDTE::dsMatchForward, &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
//AfxMessageBox(_T((CString)sHdrFilePath+" error:SME_STATE_DECLARE expected."),MB_ICONERROR|MB_OK);
return FALSE;
}
else
nMoveStateSum--;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
}
pTextHdrSelQIPtr->get_CurrentLine(&nMovedStateEndLineNo);
// Select the lines from nHdrStateLineNo to nMovedStateEndLineNo
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrStateLineNo, 1, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nMovedStateEndLineNo+1, 1 , VARIANT_BOOL(EnvDTE::dsExtend)))) // 1: Moves the insertion point to the first column.
return FALSE;
if (FAILED(pTextHdrSelQIPtr->Cut()))
return FALSE;
// Past the selection to the new insert line
int nNewInsertLine;
if (nHdrNewParSibLineNo > nHdrStateLineNo)
nNewInsertLine= nHdrNewParSibLineNo-(nMovedStateEndLineNo-nHdrStateLineNo+1);
else
nNewInsertLine= nHdrNewParSibLineNo;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nNewInsertLine, 1,VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->Paste()))
return FALSE;
// Release the selection.
pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove);
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Deal with app class code change in header file when moving state item
// INPUT: 1)pTextHdrSelQIPtr: Text selection of header file
// 2)sHdrFilePath: Header file path
// 3)nHdrStateLineNo: Line number of moved state in header file
// 4)nHdrNewParSibLineNo: Line number to be inserted in
// 5)nMoveStateSum: Sum of states under moved state item
//
// OUTPUT: 1)TRUE: Success
// 2)FALSE: Fail
// NOTE: Cut the lines between nHdrStateLineNo and nInsertEndlineNo to the original line point nHdrNewParSibLineNo.
/////////////////////////////////////////////////////////////////////////
BOOL DSUtils::MoveAppClassDec(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr,
LPCTSTR sAppName,
LPCTSTR sStateName,
LPCTSTR sNewParent,
LPCTSTR sNewSibling,
long nMoveStateSum)
{
//////////////////////////////////////////////////////////
// Move application class declaration.
CString sStartTag = "/*{{";
CString sEndTag = "/*}}";
CString sHdrDecTag = "SME_STATE_EVT_HDL_TBL_DEC";
CString sHdrNewParentDec = sHdrDecTag+"("+sNewParent+")";
CString sHdrStateDec = sHdrDecTag+"("+sStateName+")";
CString sHdrSibParDec = sHdrDecTag+"("+sNewSibling+")"; //sNewSibling may be NULL
CString sHdrStateDecEnd = CString("SME_STATE_TREE_DEC(") + sAppName + ")";
CString sHdrAppClassHead = CString("/*{{SME_APP_CLASS_DECLARE(") + sAppName + ",";
VARIANT_BOOL vbFound;
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sHdrAppClassHead), EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
return TRUE;
long nHdrStartLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nHdrStartLineNo);
long nHdrLine=nHdrStartLineNo+1;
long nHdrStateLineNo, nHdrNewParLineNo, nHdrNewParSibLineNo;
nHdrStateLineNo=nHdrNewParLineNo=nHdrNewParSibLineNo=-1;
long nMovedStateEndLineNo=-1;
while (true)
{
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend))))
return FALSE;
BSTR bstr = NULL;
pTextHdrSelQIPtr->get_Text(&bstr);
CString sResult = BSTR2CString(bstr);
TrimSpace(sResult);
if ((!sResult.IsEmpty()) && (sResult == sHdrStateDecEnd))
{
if (sNewSibling==NULL)
nHdrNewParSibLineNo = nHdrLine;
break;
}
if ((sResult.IsEmpty()) || (sResult.Find("SME_STATE_EVT_HDL_TBL_DEC") == -1))
{
break;
}
if ((!sResult.IsEmpty()) && (sResult == sHdrStateDec))
{
nHdrStateLineNo = nHdrLine;
}
if ((!sResult.IsEmpty()) && (sResult == sHdrNewParentDec))
{
nHdrNewParLineNo = nHdrLine;
}
if ((nHdrNewParSibLineNo == -1) &&(!sResult.IsEmpty()) && (sResult == sHdrSibParDec))
{
nHdrNewParSibLineNo = nHdrLine;
}
if (!sResult.IsEmpty() && nHdrStateLineNo!=-1)
{
nMoveStateSum--;
if (nMoveStateSum==0)
nMovedStateEndLineNo = nHdrLine;
}
nHdrLine++;
}
if (nHdrStateLineNo==-1 || nMovedStateEndLineNo==-1)
return FALSE;
if (nHdrNewParSibLineNo == nHdrStateLineNo) // Copy/Paste to the same location.
return TRUE;
// Select the lines from nHdrStateLineNo to nInsertEndLineNo
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrStateLineNo, 1, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nMovedStateEndLineNo+1, 1 , VARIANT_BOOL(EnvDTE::dsExtend)))) // 1: Moves the insertion point to the first column.
return FALSE;
if (FAILED(pTextHdrSelQIPtr->Cut()))
return FALSE;
// Past the selection to the new insert line
int nNewInsertLine;
if (nHdrNewParSibLineNo > nHdrStateLineNo) // new location is below the original location.
nNewInsertLine = nHdrNewParSibLineNo-(nMovedStateEndLineNo-nHdrStateLineNo+1);
else
nNewInsertLine = nHdrNewParSibLineNo;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nNewInsertLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->Paste()))
return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Whether work space is a normal one according to file extension .dsw
// INPUT: None
// OUTPUT: None
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::IsNormalSln()
{
_bstr_t bstrPath = GetSlnPath();
BOOL bRet = FALSE;
do
{
if (bstrPath.length() < 3)
break;
char* filePath = _com_util::ConvertBSTRToString(bstrPath.GetBSTR());
CString strWorkspace = filePath;
delete []filePath;
strWorkspace = strWorkspace.Right(3);
bRet = (0 == _tcsicmp(strWorkspace, _T("sln")));
} while(FALSE);
return bRet;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Whether debugger is active.
// INPUT:
// OUTPUT: zero or nonzero
// NOTE:
//////////////////////////////////////////////////////////////////////////
BOOL DSUtils::IsDebuggerActive()
{
CComPtr<EnvDTE::Debugger> pDebuggerIPtr;
g_pDTE->get_Debugger(&pDebuggerIPtr);
CComQIPtr<EnvDTE::Debugger, &EnvDTE::IID_Debugger> pDebuggerQIPtr(pDebuggerIPtr);
//DsExecutionState nDebuggerState;
EnvDTE::dbgDebugMode nDebuggerState;
pDebuggerQIPtr->get_CurrentMode(&nDebuggerState);//get_State(&nDebuggerState);
if (nDebuggerState != 1) //////dbgDesignMode=1//////dte.tlh
{
return TRUE;
}
return FALSE;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get the map file name.
// INPUT: 1)lpFilePath: a point to the dsp full path.
// 2)lpDspName: a point to the dsp name.
// 3)sMapfileName: a refference to the string of the mapfilename
// OUTPUT: zero or nonzero
// NOTE:
//////////////////////////////////////////////////////////////////////////
BOOL DSUtils::GetMapfileName(LPCTSTR lpFilePath, LPCTSTR lpDspName, LPCTSTR lpDswFullPath, CString &sMapfileName, bool &bUnopen)
{
return FALSE;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get the map file full path.
// INPUT: 1)sMapfilePath: a string to record the mapfile path
// OUTPUT: zero or nonzero
// NOTE:
//////////////////////////////////////////////////////////////////////////
BOOL DSUtils::GetMapfilePath(CString &sMapfilePath, bool &bUnopen)
{
// First save all
g_pDTE->ExecuteCommand(CComBSTR("File.SaveAll"), CComBSTR(""));
// Get the sln path
char *temp=_com_util::ConvertBSTRToString(GetSlnPath().GetBSTR());
CString sSlnPath = temp;
delete[] temp;
sSlnPath = sSlnPath.Left(sSlnPath.ReverseFind('\\'));
//open map file
CString strFilter = "mapfile|*.map||";
CFileDialog dlg(TRUE, NULL, NULL, OFN_PATHMUSTEXIST|OFN_FILEMUSTEXIST, strFilter, NULL);
dlg.m_ofn.lpstrTitle = "Open Mapfile";
dlg.m_ofn.lpstrInitialDir = sSlnPath;
if (dlg.DoModal() == IDOK)
sMapfilePath = dlg.GetPathName();
else
bUnopen = TRUE;
if (!sMapfilePath.IsEmpty())
return TRUE;
return FALSE;;
}
/*******************************************************************************************
** DESCRIPTION: Add source file and header file to the specific VC project.
** INPUT:
** 1) prj: The project to be added files;
** 2) srcFile: Source file name
** 3) headFile: Header file name
** OUTPUT: TRUE: Insert successfully. FALSE: Failed to insert.
** NOTE:
Translate Project object to VCProject object.
**
*******************************************************************************************/
BOOL DSUtils::AddSrcHdrFilesToPrj(CComPtr<EnvDTE::Project>& prj, _bstr_t& srcFile, _bstr_t& headFile, _bstr_t& EventIdFile)
{
ATLASSERT(g_pDTE != NULL );
g_pDTE->ExecuteCommand(CComBSTR("File.SaveAll"), CComBSTR("")); //???
CComPtr<IDispatch> pDispProject;
if (FAILED(prj->get_Object(&pDispProject))) return FALSE;
#ifdef VS2005
CComQIPtr<VCProjectEngineLibrary::VCProject> pVCProject;
if (FAILED(pDispProject->QueryInterface(&pVCProject))) return FALSE;
pVCProject = pDispProject; ///?? Faile for VS2005
#else
CComQIPtr<VCProject> pVCProject;
pVCProject = pDispProject;
#endif
HRESULT ree=S_OK;
BOOL bAddEventIdFile = FALSE;
if (EventIdFile.length()!=0)
bAddEventIdFile = TRUE;
#ifdef VS2005
CComPtr<IDispatch> spDispFile;
if(!bAddEventIdFile){
CComPtr<IDispatch> retSrc,retHead;
spDispFile=NULL;
//ree = pVCProject->AddFile(srcFile.GetBSTR(),&spDispFile);
ree = pVCProject->AddFile(srcFile.GetBSTR());
if(!SUCCEEDED(ree))MessageBox(NULL,"Failed to add head files to current project!","Error",0);
spDispFile=NULL;
//ree = pVCProject->AddFile(headFile.GetBSTR(),&spDispFile);
ree = pVCProject->AddFile(headFile.GetBSTR());
if(!SUCCEEDED(ree))MessageBox(NULL,"Failed to add c/cpp files to current project!","Error",0);
}
else
{
CComPtr<IDispatch> retEventId;
spDispFile=NULL;
//ree = pVCProject->AddFile(EventIdFile.GetBSTR(),&spDispFile);
ree = pVCProject->AddFile(EventIdFile.GetBSTR());
if(!SUCCEEDED(ree))MessageBox(NULL,"Failed to add eventid files to current project!","Error",0);
}
#else
if(!bAddEventIdFile){
CComPtr<IDispatch> retSrc,retHead;
ree = pVCProject->AddFile(srcFile.GetBSTR());
if(!SUCCEEDED(ree))MessageBox(NULL,"Failed to add head files to current project!","Error",0);
ree = pVCProject->AddFile(headFile.GetBSTR());
if(!SUCCEEDED(ree))MessageBox(NULL,"Failed to add c/cpp files to current project!","Error",0);
}
else
{
CComPtr<IDispatch> retEventId;
ree = pVCProject->AddFile(EventIdFile.GetBSTR());
if(!SUCCEEDED(ree))MessageBox(NULL,"Failed to add eventid files to current project!","Error",0);
}
#endif
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Del source file and header file from the specific VC project.
// INPUT: 1) prj: The project to be deleted files;
// 2) srcFile: Source file name
// 3) headFile: Header file name
// OUTPUT: None.
// NOTE:
//
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::DelSrcHdrFilesFromPrj(CComPtr<EnvDTE::Project>& prj, _bstr_t& srcFile, _bstr_t& headFile)
{
ATLASSERT(prj!=NULL);
g_pDTE->ExecuteCommand(CComBSTR("File.SaveAll"), CComBSTR("")); //???
CString SrcFile(srcFile.GetBSTR()),HeadFile(headFile.GetBSTR());
SrcFile.MakeLower();
HeadFile.MakeLower();
char ifSuccess = 0;
CComPtr<EnvDTE::ProjectItems> prjItems;
prj->get_ProjectItems(&prjItems);
if(prjItems==NULL)return FALSE;
return DelSrcHldFilesFromPrjItems(prjItems,SrcFile,HeadFile);
/*long n ;
prjItems->get_Count(&n);
for(long count = 1 ; count<= n;count++)
{
CComVariant var(count);
CComPtr<EnvDTE::ProjectItem> prjItem;
HRESULT re = prjItems->Item(var,&prjItem);
if(prjItem!=NULL)
{
short fileCount;
BSTR wa;
prjItem->get_Name(&wa);
_bstr_t fileListName(wa,false);
TAG_FILELIST_STATE fileListState;
if(wcsstr(static_cast<wchar_t*>(fileListName),L"Source Files")!=NULL)
{
fileListState = TAG_SOURCE_FILE_STATE;
}
else if(wcsstr(static_cast<wchar_t*>(fileListName),L"Header Files")!=NULL)
{
fileListState = TAG_HEAD_FILE_STATE;
}
else
{
fileListState = TAG_OTHER_FILE_STATE;
continue;//to the next item
}
prjItem->get_FileCount(&fileCount);
CComPtr<EnvDTE::ProjectItems> items;
prjItem->get_ProjectItems(&items);
for(short i = 1;i<= fileCount; i++)
{
CComPtr<EnvDTE::ProjectItem> itemContainFile;
items->Item(CComVariant(i),&itemContainFile);
BSTR fileName;
itemContainFile->get_FileNames(1,&fileName);
_bstr_t fileNameWapper(fileName,false);
if(fileListState==TAG_SOURCE_FILE_STATE)
{
if(wcsstr(fileNameWapper.GetBSTR(),srcFile.GetBSTR()))
{
itemContainFile->Remove();
ifSuccess++;
break;
}
}
if(fileListState ==TAG_HEAD_FILE_STATE)
{
if(wcsstr(fileNameWapper.GetBSTR(),headFile.GetBSTR()))
{
itemContainFile->Remove();
ifSuccess+=2;
break;
}
}
}
}
}
if(ifSuccess==3)
{
return TRUE;
}
else
if(ifSuccess==1)
{
MessageBox(NULL,"Failed when attempting to remove one head file from project.","Error",0);
return FALSE;
}
else
if(ifSuccess==2)
{
MessageBox(NULL,"Failed when attempting to remove one c/cpp file from project.","Error",0);
return FALSE;
}
else
{
MessageBox(NULL,"Failed when attempting to remove one c/cpp file & one head file from project.","Error",0);
return FALSE;
}*/
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Check legality of syntax when moving state to another
// INPUT: 1)sSrcFilePath: Source file path where moved item locates
// 2)sHdrFilePath: Header file path where moved item locates
// 3)sStatename: State name of moved item
// 4)sNewParent: Parent state name of moved item
// 5)sNewSibling: Parent state's sibling
// 6)sAppName: Application name
// 7)nState: Sum of states under moved item(including moved item)
//
// OUTPUT: 1)TRUE: Syntax is legal for coming move action.
// 2)FALSE: Syntax is illegal for coming move action.
// NOTE: sNewSibling == Null when there is no sibling of parent, that is,
// the moved item is under the bottom of state tree.
//////////////////////////////////////////////////////////////////////////
//Need an interface for communication !
BOOL DSUtils::CheckMoveStateAtomic(LPCTSTR sSrcFilePath, LPCTSTR sHdrFilePath, LPCSTR sStatename, LPCTSTR sNewParent,
LPCTSTR sNewSibling, LPCTSTR sAppName, UINT nState)
{
// Open file
CComPtr<EnvDTE::Documents> pOpenDocsIPtr;
CComPtr<EnvDTE::Document> pHdrDocIPtr;
g_pDTE->get_Documents(&pOpenDocsIPtr);
if (pOpenDocsIPtr == NULL)
return FALSE;
//CComQIPtr<EnvDTE::Documents, &EnvDTE::IID_Documents> pOpenDocsQIPtr(pOpenDocsIPtr);
if (FAILED(pOpenDocsIPtr->Open(CComBSTR(sHdrFilePath), CComBSTR("Text"),VARIANT_FALSE, &pHdrDocIPtr)))
{
MessageBox(NULL,_T("Application "+(CString)sAppName+"'s header file failed to open."),NULL , MB_ICONERROR|MB_OK);
return FALSE;
}
// Get Text Selection
//CComQIPtr<EnvDTE::TextDocument, &EnvDTE::IID_TextDocument> pTextHdrDocQIPtr(pHdrDocIPtr);
//CComPtr<EnvDTE::TextSelection> pTextHdrSelIPtr;
CComPtr<IDispatch> pDTextHdrSelIPtr;
if (FAILED(pHdrDocIPtr->get_Selection(&pDTextHdrSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr(pDTextHdrSelIPtr);
//pTextHdrSelQIPtr->SelectAll();
pTextHdrSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
CString sStartTag = "/*{{";
CString sEndTag = "/*}}";
CString sHdrDecTag = "SME_STATE_DECLARE";
CString sHdrStateDecHead = sStartTag+sHdrDecTag+"("+sAppName+")*/";
CString sHdrStateDecEnd = sEndTag+sHdrDecTag+"*/";
CString sHdrMaxStateDec = "SME_MAX_STATE(";
sHdrMaxStateDec = sHdrMaxStateDec + sAppName+")";
CString sHdrNewParentDec = sHdrDecTag+"("+sNewParent+")";
CString sHdrStateDec = sHdrDecTag+"("+sStatename+")";
CString sHdrSibParDec = sHdrDecTag+"("+sNewSibling+")";
VARIANT_BOOL vbFound;
// search for the StateHead declaration
//EnvDTE::vsFindOptions
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sHdrStateDecHead), EnvDTE::dsMatchFromStart, &vbFound)) || ! vbFound)// EnvDTE::dsMatchFromStart, &vbFound)) || ! vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error:" + sHdrStateDecHead + " expected."),NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error:"+ sHdrStateDecHead + " expected")));
return FALSE;
}
// move the cursor to the end of matching line
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nHdrStartLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nHdrStartLineNo);
// Search for StateEnd declaration
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sHdrStateDecEnd), EnvDTE::dsMatchForward,&vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error:" + sHdrStateDecEnd + " expected."),NULL, MB_ICONERROR|MB_OK);
//OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sHdrStateDecEnd)));
return FALSE;
}
// Move the cursor to the end of matching line
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nHdrEndLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nHdrEndLineNo);
long nHdrStateLineNo = -1;
long nHdrNewParLineNo = -1;
long nHdrNewParSibLineNo = -1;
long nHdrLine = nHdrStartLineNo+1;
// No new sibling state.
if (sNewSibling == NULL)
nHdrNewParSibLineNo = nHdrEndLineNo;
while (true)
{
if (nHdrLine >= nHdrEndLineNo)
break;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrLine,1,VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
//EnvDTE::vsStartOfLineOptions ss;
if (FAILED(pTextHdrSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextHdrSelQIPtr->SelectLine();
pTextHdrSelQIPtr->get_Text(&bstr);
char* bstrPath = _com_util::ConvertBSTRToString(bstr);//////////////////////////////////////***************************************
CString sResult(bstrPath);
delete[]bstrPath;
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if ((!sResult.IsEmpty()) && (sResult == sHdrStateDec))
{
nHdrStateLineNo = nHdrLine;
}
if ((!sResult.IsEmpty()) && (sResult == sHdrNewParentDec))
{
nHdrNewParLineNo = nHdrLine;
}
if ((nHdrNewParSibLineNo == -1) &&(!sResult.IsEmpty()) && (sResult == sHdrSibParDec))
{
nHdrNewParSibLineNo = nHdrLine;
}
// No new sibling state. Insert point is the end of state declaration.
if ((!sResult.IsEmpty()) && (sResult == sHdrMaxStateDec))
{
if (nHdrNewParSibLineNo == nHdrEndLineNo)
nHdrNewParSibLineNo = nHdrLine;
}
nHdrLine++;
}
if (nHdrStateLineNo == -1)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error:" + sHdrStateDec+ " expected."),NULL, MB_ICONERROR|MB_OK);
//OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sStateDecParent)));
return FALSE;
}
if (nHdrNewParLineNo == -1)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error:" + sHdrNewParentDec+ " expected."), NULL,MB_ICONERROR|MB_OK);
// OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sStateDecParent)));
return FALSE;
}
if (nHdrNewParSibLineNo == -1)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error:" + sHdrMaxStateDec + " expected."),NULL, MB_ICONERROR|MB_OK);
//OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sStateDecParent)));
return FALSE;
}
// Check source file all-or-nothing
CComPtr<EnvDTE::Document> pTextSrcDocIPtr;
if (FAILED(pOpenDocsIPtr->Open(CComBSTR(sSrcFilePath), CComBSTR("Text"), VARIANT_FALSE, &pTextSrcDocIPtr)))
{
MessageBox(NULL,_T("Application "+(CString)sAppName+"'s source file failed to open."), NULL,MB_ICONERROR|MB_OK);
return FALSE;
}
// Get Text Selection
/*CComQIPtr<EnvDTE::TextDocument, &EnvDTE::IID_TextDocument> pTextSrcDocQIPtr(pTextSrcDocIPtr);
CComPtr<EnvDTE::TextSelection> pTextSrcSelIPtr;
if (FAILED(pTextSrcDocQIPtr->get_Selection(&pTextSrcSelIPtr)))
{
return FALSE;
}*/
CComPtr<IDispatch> pTextSrcSelIPtr;
if (FAILED(pTextSrcDocIPtr->get_Selection(&pTextSrcSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSrcSelQIPtr(pTextSrcSelIPtr);
CString sSeparator="/*{{SME_STATE_STATETREE_SEPARATOR}}*/";
//////////////////////////////////////$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$////////////////////////////
if(FAILED(pTextSrcSelQIPtr->MoveTo(1,1,EnvDTE::dsMove)))
{
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sSeparator), EnvDTE::dsMatchForward, &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:" + sSeparator + " expected."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
CString strStateName=CString(sStatename);
CString strNewParent=CString(sNewParent);
CString strNewParSibling;
if (sNewSibling != NULL)
strNewParSibling=CString(sNewSibling);
else
strNewParSibling="";
CString strAppName=CString(sAppName);
CString sStateTreeDef = "SME_STATE_TREE_DEF";
CString sStateTreeDefHead = sStartTag+sStateTreeDef+"("+strAppName+")*/";
CString sStateTreeDefEnd = sEndTag+sStateTreeDef+"*/";
CString sStateTreeFind = CString("SME_STATE(")+strAppName+","+strAppName+",";
CString sStateFind= CString("SME_STATE(")+strAppName+","+strStateName+","; // IMPORTANT: Should end with , to prevent
CString sStateNewParentFind=CString("SME_STATE(")+strAppName+","+strNewParent+",";
CString sNewParSibFind=CString("SME_STATE(")+strAppName+","+strNewParSibling+",";
if (strNewParSibling == "")
sNewParSibFind = "";
//pTextSrcSelQIPtr->SelectAll();
pTextSrcSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
// Find the state tree definition head
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateTreeDefHead), EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)// EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:" + sStateTreeDefHead + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateTreeDefHead)));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nSrcStartLineNo = 0;
if (FAILED(pTextSrcSelQIPtr->get_CurrentLine(&nSrcStartLineNo)))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateTreeDefEnd), EnvDTE::dsMatchForward, &vbFound)) || !vbFound)// EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:"+sStateTreeDefEnd+" expected."), NULL,MB_ICONERROR|MB_OK);
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nSrcEndLineNo = 0;
pTextSrcSelQIPtr->get_CurrentLine(&nSrcEndLineNo);
long nSrcLine = nSrcStartLineNo+1;
long nSrcStateLine = -1;
long nSrcNewParLine = -1;
long nSrcParSibLine = -1;
while (true)
{
if (nSrcLine >= nSrcEndLineNo)
break;
if (FAILED(pTextSrcSelQIPtr->MoveTo(nSrcLine, 1,VARIANT_BOOL(EnvDTE::dsMove))))// CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend))))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextSrcSelQIPtr->SelectLine();
pTextSrcSelQIPtr->get_Text(&bstr);
char* bstrPath = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrPath);
delete[]bstrPath;
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if (!sResult.IsEmpty())
{
if ((sResult.Find(sStateFind) != -1))
{
CString sTemp = sResult;
sTemp.Replace(sStateFind, NULL);
int idx = sTemp.Find(')');
if (idx == sTemp.GetLength() -1)
{
int nCommaNum = 0;
while (true)
{
if (nCommaNum > 1)
break;
int commaIdx = sTemp.Find(',');
if (commaIdx == -1)
break;
sTemp.SetAt(commaIdx, ' ');
nCommaNum++;
}
if (nCommaNum == 1)
{
// SME_STATE(MyApp2,State2,0,-1)
nSrcStateLine = nSrcLine;
}
else
return FALSE;
}
}
if (sResult.Find(sStateTreeFind) != -1)
{
CString sTemp = sResult;
sTemp.Replace(sStateTreeFind, NULL);
int idx = sTemp.Find(')');
if (idx == sTemp.GetLength() -1)
{
int nCommaNum = 0;
while (true)
{
if (nCommaNum > 1)
break;
int commaIdx = sTemp.Find(',');
if (commaIdx == -1)
break;
sTemp.SetAt(commaIdx, ' ');
nCommaNum++;
}
if (nCommaNum != 1)
{
return FALSE;
}
}
}
if (sResult.Find(sStateNewParentFind) != -1)
{
CString sTemp = sResult;
sTemp.Replace(sStateNewParentFind, NULL);
int idx = sTemp.Find(')');
if (idx == sTemp.GetLength() -1)
{
int nCommaNum = 0;
while (true)
{
if (nCommaNum > 1)
break;
int commaIdx = sTemp.Find(',');
if (commaIdx == -1)
break;
sTemp.SetAt(commaIdx, ' ');
nCommaNum++;
}
if (nCommaNum == 1)
{
nSrcNewParLine = nSrcLine;
}
else
return FALSE;
}
}
if ((sNewParSibFind != "") && sResult.Find(sNewParSibFind) != -1)
{
CString sTemp = sResult;
sTemp.Replace(sNewParSibFind, NULL);
int idx = sTemp.Find(')');
if (idx == sTemp.GetLength() -1)
{
int nCommaNum = 0;
while (true)
{
if (nCommaNum > 1)
break;
int commaIdx = sTemp.Find(',');
if (commaIdx == -1)
break;
sTemp.SetAt(commaIdx, ' ');
nCommaNum++;
}
if (nCommaNum == 1)
{
nSrcParSibLine = nSrcLine;
}
else
return FALSE;
}
}
}
nSrcLine++;
}
if (nSrcParSibLine < 0)
nSrcParSibLine = nSrcEndLineNo;
if (nSrcNewParLine < 0)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:" + sStateNewParentFind + " expected."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
if (nSrcStateLine < 0)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:" + sStateFind + " expected."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
if (MoveStateDec(pTextHdrSelQIPtr, sHdrFilePath, nHdrStateLineNo, nHdrNewParSibLineNo, nState) == FALSE)
return FALSE;
MoveAppClassDec(pTextHdrSelQIPtr, sAppName, sStatename, sNewParent, sNewSibling, nState);
if (MoveStateDef(pTextSrcSelQIPtr, sSrcFilePath, sNewParent, sAppName, nSrcStateLine, nSrcParSibLine, nState, nSrcStartLineNo, nSrcEndLineNo+nState) == FALSE)
return FALSE;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Check atomic attribute of editing an event handler
// INPUT: 1) sSrcFilePath: Full path of application source file.
// 2) sHdrFilePath: Full path of application header file.
// 3) sAppName: Application name.
// 4) sStateName: State name which owns to-be-edited event.
// 5) sOriginEvent: Event's original name.
// 6) sEventName: New event name.
// 7) sDestState: New transition state name if it exists.
// 8) sActionName: New action name if it exists.
//
// OUTPUT: 1)TRUE: 2)FALSE:
// NOTE:
//
//////////////////////////////////////////////////////////////////////////
BOOL DSUtils::EditEventHdlDec(LPCTSTR sSrcFilePath,
LPCTSTR sHdrFilePath,
LPCTSTR sAppName,
LPCTSTR sFuncClassPrefix,
LPCTSTR sStateName,
LPCTSTR sOriginEvent,
LPCTSTR sEventName,
LPCTSTR sDestState,
LPCTSTR sActionName)
{
CComPtr<EnvDTE::Documents>pOpenDocsIPtr;
CComPtr<EnvDTE::Document>pTextDocIPtr;
g_pDTE->get_Documents(&pOpenDocsIPtr);
if (pOpenDocsIPtr == NULL)
return FALSE;
CComQIPtr<EnvDTE::Documents, &EnvDTE::IID_Documents> pOpenDocsQIPtr(pOpenDocsIPtr);
if (FAILED(pOpenDocsQIPtr->Open(CComBSTR(sSrcFilePath), CComBSTR("Text"), VARIANT_FALSE, &pTextDocIPtr)))
{
return FALSE;
}
/////////////////// Get Text Selection
//CComQIPtr<EnvDTE::TextDocument, &EnvDTE::IID_TextDocument> pTextDocQIPtr(pTextDocIPtr);
//CComPtr<EnvDTE::TextSelection> pTextSelIPtr;
//if (FAILED(pTextDocQIPtr->get_Selection(&pTextSelIPtr)))
//{
// return FALSE;
//}
CComPtr<IDispatch> pDTextSelIPtr;
if (FAILED(pTextDocIPtr->get_Selection(&pDTextSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSelQIPtr(pDTextSelIPtr);
//pTextSelQIPtr->SelectAll();
pTextSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
CString sStartTag = "/*{{SME_STATE_DEF";
CString sEndTag = "/*}}SME_STATE_DEF*/";
CString sStateDefHead = sStartTag+"("+sAppName+","+sStateName+")*/";
CString sStateDefEnd = sEndTag;
CString sEvntHead = "SME_ON_EVENT(";
CString sEditEventDec = sEvntHead + sOriginEvent+",";
VARIANT_BOOL vbFound;
// Find the state definition head);
if (FAILED(pTextSelQIPtr->FindText(CComBSTR(sStateDefHead), EnvDTE::dsMatchFromStart,&vbFound)) || !vbFound)// EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: " + sStateDefHead + " expected."), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateDefHead)));
return FALSE;
}
if (FAILED(pTextSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nStartLineNo;
if (FAILED(pTextSelQIPtr->get_CurrentLine(&nStartLineNo)))
return FALSE;
//EnvDTE::vsFindOptions
if (FAILED(pTextSelQIPtr->FindText(CComBSTR(sStateDefEnd), EnvDTE::dsMatchForward, &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: " + sStateDefEnd + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateDefEnd)));
return FALSE;
}
if (FAILED(pTextSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nEndLineNo;
if (FAILED(pTextSelQIPtr->get_CurrentLine(&nEndLineNo)))
return FALSE;
long nLine = nStartLineNo+1;
CString sOriginAction;
while (true)
{
if (nLine >= nEndLineNo)
break;
if (FAILED(pTextSelQIPtr->MoveTo(nLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend))))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextSelQIPtr->SelectLine();
pTextSelQIPtr->get_Text(&bstr);
char* bstrPath = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrPath);
delete[]bstrPath;
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if ((!sResult.IsEmpty()) && (sResult.Find(sEditEventDec) != -1))
{
sResult.Replace(sEditEventDec, NULL);
int idx = sResult.Find(')');
if (idx != sResult.GetLength()-1)
{
CString sWarningMsg;
sWarningMsg.Format("%s(Line %d) error: %s expected.", (CString)sSrcFilePath, nLine, sEditEventDec);
AfxMessageBox(_T(sWarningMsg), MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T(sWarningMsg)));
return FALSE;
}
sResult.Replace(")", NULL);
idx = sResult.Find(',');
if (idx == -1)
{
CString sWarningMsg;
sWarningMsg.Format("%s(Line %d) error: %s expected.", (CString)sSrcFilePath, nLine, sEditEventDec);
MessageBox(NULL,_T(sWarningMsg), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T(sWarningMsg)));
return FALSE;
}
sOriginAction = sResult.Left(idx);
sResult.SetAt(idx, ' ');
idx = sResult.Find(',');
if (idx != -1)
{
CString sWarningMsg;
sWarningMsg.Format("%s(Line %d) error: %s expected.", (CString)sSrcFilePath, nLine, sEditEventDec);
MessageBox(NULL,_T(sWarningMsg),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T(sWarningMsg)));
return FALSE;
}
break;
}
nLine++;
// Format: SME_ON_EVENT(eventid,action,transition state)
}
if (nLine >= nEndLineNo)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: " + sEditEventDec + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sEditEventDec)));
return FALSE;
}
long nFuncLineNo=0;
if ((((CString)sActionName == "SME_NULL") && (sOriginAction != "SME_NULL" && sOriginAction != "0")) ||
(((CString)sActionName != "SME_NULL") && ((CString)sActionName != sOriginAction)))
{
if (EditEventHdlFunc(sHdrFilePath, sAppName, sOriginAction, sActionName) == FALSE)
return FALSE;
if(FAILED(pTextSelQIPtr->EndOfDocument(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
pTextSelQIPtr->get_CurrentLine(&nFuncLineNo);
if (CString(sActionName) != "SME_NULL")
{
if(FAILED(pTextSelQIPtr->put_Text(CComBSTR(CString("\nint ")+sFuncClassPrefix+CString(sActionName)+"(struct SME_APP_T *pApp, struct SME_EVENT_T *pEvent)\n{\nreturn 0;\n}\n\n"))))
return FALSE;
}
}
// Move to the finded line
if (FAILED(pTextSelQIPtr->MoveTo(nLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend))))//CComVariant(dsExtend))))
return FALSE;
CString sNewText;
CString sTemp = sDestState;
sTemp.TrimLeft();
sTemp.TrimRight();
if (!sTemp.IsEmpty())
sNewText = sEvntHead + (CString)sEventName + "," + (CString)sActionName + "," + (CString)sDestState + ")";
else
sNewText = sEvntHead + (CString)sEventName + "," + (CString)sActionName + "," + "SME_INTERNAL_TRAN" + ")";
// delete the finded line
if (FAILED(pTextSelQIPtr->put_Text(CComBSTR(sNewText))))
return FALSE;
// Move to the function.
if (nFuncLineNo>0)
if (FAILED(pTextSelQIPtr->MoveTo(nFuncLineNo+3, START_COL_POS, EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Edit handler declaration in application header file
// INPUT: 1) sHdrFilePath: Full path of application header file
// 2) sAppName: Application name.
// 3) sOriginAction: Original action name.
// 4) sNewAction: New action name.
//
// OUTPUT: 1) TRUE: 2)FALSE��
// NOTE: If new action name has existed already, it will notify users. But it
// will still re-declaration that event handler again at this version.
//
//////////////////////////////////////////////////////////////////////////
BOOL DSUtils::EditEventHdlFunc(LPCTSTR sHdrFilePath,
LPCTSTR sAppName,
LPCTSTR sOriginAction,
LPCTSTR sNewAction)
{
if (sHdrFilePath == NULL)
return FALSE;
// Open file
//CComPtr<IDispatch> pOpenDocsIPtr, pTextDocIPtr;
CComPtr<EnvDTE::Documents>pOpenDocsIPtr;CComPtr<EnvDTE::Document>pTextDocIPtr;
g_pDTE->get_Documents(&pOpenDocsIPtr);
if (pOpenDocsIPtr == NULL)
return FALSE;
CComQIPtr<EnvDTE::Documents, &EnvDTE::IID_Documents> pOpenDocsQIPtr(pOpenDocsIPtr);
if (FAILED(pOpenDocsQIPtr->Open(CComBSTR(sHdrFilePath), CComBSTR("Text"), VARIANT_FALSE, &pTextDocIPtr)))
{
MessageBox(NULL,_T("Application "+(CString)sAppName+"'s header file failed to open."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
// Get Text Selection
//CComQIPtr<ITextDocument, &IID_ITextDocument> pTextDocQIPtr(pTextDocIPtr);
CComPtr<IDispatch> pTextSelIPtr;
if (FAILED(pTextDocIPtr->get_Selection(&pTextSelIPtr)))//get_Selection(&pTextSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSelQIPtr(pTextSelIPtr);
//pTextSelQIPtr->SelectAll();
pTextSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
CString sStartFlag = "/*{{SME_BEGIN_EVENT_HANDLER(";
sStartFlag = sStartFlag + sAppName +")*/";
CString sEndFlag = "/*}}SME_END_EVENT_HANDLER*/";
VARIANT_BOOL vbFound;
// Search for the event handler function name
//$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$/////////////////////
if (FAILED(pTextSelQIPtr->FindText(CComBSTR(sStartFlag),EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error: " + sStartFlag + " expected."), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sStartFlag)));
return FALSE;
}
// move the cursor to the end of matching line
if (FAILED(pTextSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nStartLineNo;
pTextSelQIPtr->get_CurrentLine(&nStartLineNo);
// Search for StateEnd declaration
if (FAILED(pTextSelQIPtr->FindText(CComBSTR(sEndFlag), EnvDTE::dsMatchForward,&vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error: "+ sEndFlag+" expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sEndFlag)));
return FALSE;
}
// Move the cursor to the end of matching line
if (FAILED(pTextSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nEndLineNo;
pTextSelQIPtr->get_CurrentLine(&nEndLineNo);
// Record the line number
long nFuncStartLinePos = 0;
long nFuncStartColPos = 0;
long nFuncEndLinePos = 0;
long nFuncEndColPos = 0;
BOOL bOldHdlIsFound = FALSE;
BOOL bNewHdlIsFound = FALSE;
long nHdrLineNo = nStartLineNo+1;
CString sLastLine ="";
// Initialize the line number and column number
nFuncStartLinePos = nStartLineNo+1;
nFuncStartColPos = 1;
while (true)
{
if (nHdrLineNo >= nEndLineNo)
break;
long nHeadSpaceNo = 0;
if (FAILED(pTextSelQIPtr->MoveTo(nHdrLineNo, 1,VARIANT_BOOL(EnvDTE::dsMove))))// CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSelQIPtr->get_CurrentColumn(&nHeadSpaceNo)))
return FALSE;
if (FAILED(pTextSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend))))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextSelQIPtr->SelectLine();
pTextSelQIPtr->get_Text(&bstr);
char* bstrTemp = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrTemp);
delete[]bstrTemp;
sResult.TrimLeft();
//int State2Exit(struct SME_APP_T *pApp, struct SME_EVENT_T *pEvent);
if (!sResult.IsEmpty())
{
while (true)
{
int idx = sResult.Find(';');
if (-1 == idx)
{
sLastLine += " ";
sLastLine += sResult;
break;
}
if (bOldHdlIsFound == FALSE)
{
if (nFuncEndLinePos == nHdrLineNo)
nFuncEndColPos = nFuncEndColPos + idx +1;
else
{
nFuncEndLinePos = nHdrLineNo;
nFuncEndColPos = nHeadSpaceNo+idx+1;
}
}
sLastLine += " ";
CString sCurrentLine = sLastLine + sResult.Left(idx+1);
// Initialize for the next loop
sLastLine = "";
sResult = sResult.Right(sResult.GetLength()-idx-1);
idx = sCurrentLine.Find('(');
// idx == -1 ?????????
CString sFuncName = sCurrentLine.Left(idx);
sFuncName.TrimRight();
sFuncName.Replace('\t', ' ');
idx = sFuncName.ReverseFind(' ');
sFuncName = sFuncName.Right(sFuncName.GetLength()-idx-1);
if ((sFuncName == (CString)sOriginAction) && (CString)sOriginAction != "SME_NULL")
{
bOldHdlIsFound = TRUE;
}
if (sFuncName == (CString)sNewAction)
{
bNewHdlIsFound = TRUE;
}
if (bOldHdlIsFound == FALSE)
{
nFuncStartLinePos = nHdrLineNo;
nFuncStartColPos = nFuncEndColPos;
}
}
}
nHdrLineNo++;
}
if (bOldHdlIsFound == FALSE && (CString)sOriginAction != "SME_NULL")
{
MessageBox(NULL,_T((CString)sHdrFilePath+" Error! int "+sOriginAction+"(struct SME_APP_T *pApp, struct SME_EVENT_T *pEvent); not found."), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" Error! int "+sOriginAction+"(struct SME_APP_T *pApp, struct SME_EVENT_T *pEvent); not found.")));
}
if (bNewHdlIsFound == TRUE)
{
MessageBox(NULL,_T("The action "+(CString)sNewAction+"already exists."), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T("Error! The action "+(CString)sNewAction+"already exists.")));
}
// This action must do before next, because any delete operations will cause line number changes
if (CString(sNewAction) != "SME_NULL")
{
if (FAILED(pTextSelQIPtr->MoveTo(nEndLineNo, 1, VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
//long nFuncLineNo;
//pTextSelQIPtr->get_CurrentLine(&nFuncLineNo);
if(FAILED(pTextSelQIPtr->put_Text(CComBSTR("int "+CString(sNewAction)+STR_HDLER_PROTOTYPE+";\n"))))
return FALSE;
// Move to the function.
//if (FAILED(pTextSelQIPtr->MoveTo(nFuncLineNo+3, START_COL_POS, EnvDTE::dsMove)))//CComVariant(dsMove))))
// return FALSE;
}
if (bOldHdlIsFound == TRUE)
{
if (FAILED(pTextSelQIPtr->MoveTo(nFuncStartLinePos, nFuncStartColPos, VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSelQIPtr->MoveTo(nFuncEndLinePos, nFuncEndColPos,VARIANT_BOOL(EnvDTE::dsExtend))))//CComVariant(dsExtend))))
return FALSE;
//pTextSelQIPtr->SelectLine();//%%
if (FAILED(pTextSelQIPtr->Delete(1)))//CComVariant(1)))) // delete 2 twice ????maybe
return FALSE;
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Modify the declaration of the event handler function in the head file.
// INPUT: 1) sHFilePath: head file full path name.
// 2) sDelAction: the event handler function's name.
// OUTPUT: TRUE: modified successfully. FALSE: Failed to modify.
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::DelEventHdlFunc(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr,
long nStartLineNo,
long nStartColNo,
long nEndLineNo,
long nEndColNo)
{
if (FAILED(pTextHdrSelQIPtr->MoveTo(nStartLineNo, nStartColNo,VARIANT_BOOL(EnvDTE::dsMove)))) //CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nEndLineNo, nEndColNo,VARIANT_BOOL(EnvDTE::dsExtend))))// CComVariant(dsExtend))))
return FALSE;
//pTextHdrSelQIPtr->SelectLine();//%%
if (FAILED(pTextHdrSelQIPtr->Delete(1)))//CComVariant(1))))
return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Delete state declaration and handler declaration from the header file.
// INPUT: 1) pTextHdrSelQIPtr: Text selection of application header file.
// 2) DelHandlerList: List of handler name to be deleted.
// 3) DelStateList: List of state name to be deleted.
// 4) sAppName: Application name.
// 5) nStateTreeDecStart: Line number of state start declaration.
//
//
// OUTPUT: 1) TRUE: 2)FALSE:
// NOTE:
//
//
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::DeleteStateHandlerDec(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr,
vector<CString> &DelHandlerList,
vector<CString> &DelStateList,
LPCTSTR sAppName,
long nStateTreeDecStart,
long nAppClassStateLine)
{
//////////////////////////////////////////////////////////////////////////
// Delete state declarations
vector<CString> DelStateListForAppClass(DelStateList);
long nHdrLine = nStateTreeDecStart+1;
VARIANT_BOOL vbFound;
BOOL bStateDecFound = FALSE;
//pTextHdrSelQIPtr->SelectAll();
pTextHdrSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(CString("/*{{SME_STATE_DECLARE(")+sAppName+")*/"), EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
return FALSE;
}
// search for the first /*}}SME_STATE_DECLARE*/ from the position /*{{SME_STATE_DECLARE(sAppName)
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(CString("SME_MAX_STATE(")+sAppName+")"), EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))
return FALSE;
long nHdrEndLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nHdrEndLineNo);
while (true)
{
if (nHdrLine >= nHdrEndLineNo)
break;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstColumn,VARIANT_BOOL(EnvDTE::dsMove))))// StartOfLine(EnvDTE::dsFirstColumn, EnvDTE::dsMove)))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend))))
return FALSE;
BSTR bstr = NULL;
pTextHdrSelQIPtr->get_Text(&bstr);
CString sResult = BSTR2CString(bstr);
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if (!sResult.IsEmpty() && sResult.Find("SME_STATE_DECLARE")==-1)
break;
// Traverse the to-be-deleted state name array
int nSelSeq = 0;
while (true)
{
if (nSelSeq >= (int) DelStateList.size())
break;
//Format: SME_STATE_DECLARE(TestApp)
CString sDelStateDec = "SME_STATE_DECLARE(";
CString sStateName = DelStateList[nSelSeq];
sDelStateDec += sStateName;
sDelStateDec += ")";
if (sResult == sDelStateDec)
{
bStateDecFound = TRUE;
pTextHdrSelQIPtr->Delete(2); //here delete use twice because we are sure it is a line
DelStateList.erase(DelStateList.begin()+nSelSeq);//RemoveAt(nSelSeq);
break;
}
nSelSeq++;
}
if (bStateDecFound == TRUE)
{
bStateDecFound = FALSE;
} else nHdrLine++;
}
//////////////////////////////////////////////////////////////////////////
// Delete app class declarations
if (nAppClassStateLine>0)
{
long nHdrLine = nAppClassStateLine+1;
VARIANT_BOOL vbFound;
BOOL bStateDecFound = FALSE;
//pTextHdrSelQIPtr->SelectAll();
pTextHdrSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(CString("/*{{SME_APP_CLASS_DECLARE(")+sAppName+","), EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
return FALSE;
}
// search for the first /*}}SME_APP_CLASS_DECLARE*/ from the position /*{{SME_APP_CLASS_DECLARE(sAppName)
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR("/*}}SME_APP_CLASS_DECLARE*/"), EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
long nHdrEndLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nHdrEndLineNo);
while (true)
{
if (nHdrLine >= nHdrEndLineNo)
break;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstColumn,VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend))))
return FALSE;
BSTR bstr = NULL;
pTextHdrSelQIPtr->get_Text(&bstr);
CString sResult = BSTR2CString(bstr);
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if (!sResult.IsEmpty() && sResult.Find("SME_STATE_EVT_HDL_TBL_DEC")==-1)
break;
// Traverse the to-be-deleted state name array
int nSelSeq = 0;
while (true)
{
if (nSelSeq >= (int) DelStateListForAppClass.size())
break;
//Format: SME_STATE_DECLARE(TestApp)
CString sDelStateDec = "SME_STATE_EVT_HDL_TBL_DEC(";
CString sStateName = DelStateListForAppClass[nSelSeq];
sDelStateDec += sStateName;
sDelStateDec += ")";
if (sResult == sDelStateDec)
{
bStateDecFound = TRUE;
pTextHdrSelQIPtr->Delete(2); //here delete use twice because we are sure it is a line
DelStateListForAppClass.erase(DelStateListForAppClass.begin()+nSelSeq);// RemoveAt(nSelSeq);
break;
}
nSelSeq++;
}
if (bStateDecFound == TRUE)
{
bStateDecFound = FALSE;
} else nHdrLine++;
}
}
//////////////////////////////////////////////////////////////////////////
// Delete event handlers
CString sHandlerDecStartFlag = "/*{{SME_BEGIN_EVENT_HANDLER(";
sHandlerDecStartFlag += sAppName;
sHandlerDecStartFlag += ")*/";
CString sHandlerDecEndFlag = "/*}}SME_END_EVENT_HANDLER*/";
//////////////////////////////////////////////////////////////////////////
BOOL bDelete = FALSE;
//pTextHdrSelQIPtr->SelectAll();
pTextHdrSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
while (true)
{
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sHandlerDecStartFlag), EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)// EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
//OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sHandlerDecStartFlag)));
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
// Get start flag line number of handler declaration
long nHdrHdlStartLine = 0;
pTextHdrSelQIPtr->get_CurrentLine(&nHdrHdlStartLine);
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sHandlerDecEndFlag), EnvDTE::dsMatchForward,&vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
//OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sHandlerDecEndFlag)));
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nHdrHdlEndLine = 0;
pTextHdrSelQIPtr->get_CurrentLine(&nHdrHdlEndLine);
// Record the line number
long nFuncStartLinePos = 0;
long nFuncStartColPos = 0;
long nFuncEndLinePos = 0;
long nFuncEndColPos = 0;
long nHdrLineNo = nHdrHdlStartLine+1;
CString sLastLine ="";
// Initialize the line number and column number
nFuncStartLinePos = nHdrHdlStartLine+1;
nFuncStartColPos = 1;
while (true)
{
if (nHdrLineNo >= nHdrHdlEndLine)
break;
long nHeadSpaceNo = 0;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrLineNo, 1,VARIANT_BOOL(EnvDTE::dsMove))))// CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->get_CurrentColumn(&nHeadSpaceNo)))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend))))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextHdrSelQIPtr->SelectLine();
pTextHdrSelQIPtr->get_Text(&bstr);
char* bstrTemp = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrTemp);
delete [] bstrTemp;
sResult.TrimLeft();
//int State2Exit(struct SME_APP_T *pApp, struct SME_EVENT_T *pEvent);
if (!sResult.IsEmpty())
{
while (true)
{
int idx = sResult.Find(';');
if (-1 == idx)
{
sLastLine += " ";
sLastLine += sResult;
break;
}
if (nFuncEndLinePos == nHdrLineNo)
nFuncEndColPos = nFuncEndColPos + idx +1;
else
{
nFuncEndLinePos = nHdrLineNo;
nFuncEndColPos = nHeadSpaceNo+idx+1;
}
sLastLine += " ";
CString sCurrentLine = sLastLine + sResult.Left(idx+1);
// Initialize for the next loop
sLastLine = "";
sResult = sResult.Right(sResult.GetLength()-idx-1);
idx = sCurrentLine.Find('(');
// idx == -1 ?????????
CString sFuncName = sCurrentLine.Left(idx);
sFuncName.TrimRight();
sFuncName.Replace('\t', ' ');
idx = sFuncName.ReverseFind(' ');
sFuncName = sFuncName.Right(sFuncName.GetLength()-idx-1);
int nSelSeq = 0;
while (true)
{
if (nSelSeq >=(int) DelHandlerList.size())
break;
if (!DelHandlerList.at(nSelSeq).Compare(sFuncName))//if (sFuncName == DelHandlerList.GetAt(nSelSeq))
{
bDelete = TRUE;
DelEventHdlFunc(pTextHdrSelQIPtr, nFuncStartLinePos, nFuncStartColPos, nFuncEndLinePos, nFuncEndColPos);
DelHandlerList.erase(DelHandlerList.begin()+nSelSeq);
break;
}
nSelSeq++;
}
nFuncStartLinePos = nHdrLineNo;
nFuncStartColPos = nFuncEndColPos;
}
}
if (bDelete == TRUE)
{
bDelete = FALSE;
break;
}
nHdrLineNo++;
}
if (nHdrLineNo >= nHdrHdlEndLine)
break;
}
// Release the selection
pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Delete state definition and corresponding state tree declaration
// INPUT: 1) pTextSrcSelQIPtr: Text selection of application source file.
// 2) DelStateList: List of states name to be deleted.
// 3) sAppName: Application name.
// 4) nStateTreeDefStart: Line number of state tree start flag.
// 5) nStateTreeDefEnd: Line number of state tree end flag.
//
//
// OUTPUT: 1) TRUE: 2)FALSE:
// NOTE: Delete corresponding information in state tree definition.
// Delete corresponding state definition.
// Users may delete such information by hand, so it will ignore it.
//
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::DeleteStateFromStateTree(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSrcSelQIPtr,
vector<CString> &DelStateList,
LPCTSTR sAppName,
long nStateTreeDefStart)
{
// Copy a temporarily to-be-deleted state name list
vector<CString> TmpDelStateList;
TmpDelStateList.clear();
//vector <int>::iterator Iter;
//?the second parameter of assign means the first element beyond the range of elements to be copied?
//TmpDelStateList.assign(DelStateList.begin(),DelStateList.end());
//TmpDelStateList.push_back(DelStateList.end());
int NomOfEle=(int)DelStateList.size();
for(int i=0;i<NomOfEle;i++)
{
CString t=DelStateList.at(i);
TmpDelStateList.push_back(t);
}
long nSrcLine = nStateTreeDefStart+1;
BOOL bStateFound = FALSE;
VARIANT_BOOL vbFound;
while (true)
{
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR("/*}}SME_STATE_TREE_DEF*/"),EnvDTE::dsMatchForward,&vbFound)) || !vbFound)// EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nStateTreeDefEnd;
pTextSrcSelQIPtr->get_CurrentLine(&nStateTreeDefEnd);
nSrcLine = nStateTreeDefStart+1;
while (true)
{
if (nSrcLine >= nStateTreeDefEnd)
break;
if (FAILED(pTextSrcSelQIPtr->MoveTo(nSrcLine, 1,VARIANT_BOOL(EnvDTE::dsMove))))// CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstColumn,VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsFirstColumn), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend))))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextSrcSelQIPtr->SelectLine();
pTextSrcSelQIPtr->get_Text(&bstr);
char* bstrTemp = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrTemp);
delete[] bstrTemp;
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if (!sResult.IsEmpty())
{
// Traverse the to-be-deleted state name array
int nDelSeq = 0;
while (true)
{
if (nDelSeq >= (int)TmpDelStateList.size())
break;
//Format: SME_STATE(TestApp,s11,State1,s111)
CString sDelStateDef = "SME_STATE(";
CString sStateName = TmpDelStateList.at(nDelSeq);
sDelStateDef += sAppName;
sDelStateDef += ",";
sDelStateDef += sStateName;
sDelStateDef += ",";
if (sResult.Find(sDelStateDef) != -1)
{
bStateFound = TRUE;
//pTextSrcSelQIPtr->SelectLine();//%%
pTextSrcSelQIPtr->Delete(2);//CComVariant(2)); //here delete use twice because we are sure
//it is a line
break;
}
nDelSeq++;
}
if (bStateFound == TRUE)
{
bStateFound = FALSE;
break;
}
}
nSrcLine++;
}
if (nSrcLine >= nStateTreeDefEnd)
break;
}
while (true)
{
if ((int)TmpDelStateList.size() == 0)
break;
// Get to-be-found flag names
CString sStateName = TmpDelStateList.at(0);
CString sStateStartFlag = "/*{{SME_STATE_DEF(";
sStateStartFlag += sAppName;
sStateStartFlag += ",";
sStateStartFlag += sStateName;
sStateStartFlag += ")";
CString sStateMacroStart = "";
CString sStateMacroEnd = "";
sStateMacroEnd = "SME_END_STATE_DEF";
// VARIANT_BOOL vcFound;
//pTextSrcSelQIPtr->SelectAll();////$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$$4/////////
pTextSrcSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateStartFlag), EnvDTE::dsMatchFromStart, &vbFound))|| !vbFound)//EnvDTE::dsMatchFromStart, &vbFound))|| !vbFound)
{
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
if (vbFound == -1) //%% Only do such operations when state macro definition exists
{
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateMacroEnd),EnvDTE::dsMatchForward,&vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
// OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateMacroEnd)));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nDelEndLineNo = 0;
pTextSrcSelQIPtr->get_CurrentLine(&nDelEndLineNo);
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR("SME_BEGIN_STATE_DEF"), EnvDTE::dsMatchBackward, &vbFound)) || !vbFound)//CComVariant(dsMatchBackward), &vbFound)) || !vbFound)
{
//OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion SME_BEGIN_STATE_DEF")));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nDelStartLineNo = 0;
pTextSrcSelQIPtr->get_CurrentLine(&nDelStartLineNo);
// Go to the end of state macro definition
if (FAILED(pTextSrcSelQIPtr->MoveTo(nDelEndLineNo, 1 ,VARIANT_BOOL(EnvDTE::dsMove))))// CComVariant(dsMove))))
return FALSE;
// Move to the end of line
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
// Go to the beginning of state macro definition
if (FAILED(pTextSrcSelQIPtr->MoveTo(nDelStartLineNo, 1,VARIANT_BOOL(EnvDTE::dsExtend))))// CComVariant(dsExtend))))
return FALSE;
// Delete lines from (nDelStartLineNo) to nDelEndLineNo
pTextSrcSelQIPtr->Delete(2);//CComVariant(2));
long nLineNo = 0;
pTextSrcSelQIPtr->get_CurrentLine(&nLineNo);
ClearSpace(pTextSrcSelQIPtr, nLineNo, nLineNo);
}
TmpDelStateList.erase(TmpDelStateList.begin());//.RemoveAt(0); //delete current state from list
}
return TRUE;
}
/*****************************************************************************************************
// DESCRIPTION: Whether a text line is blank or not.
// INPUT:
// 1) pTextSelQIPtr: Text selection denoting which file is to be cleared
// 2) nLineNo:
//
// OUTPUT: 1)TRUE 2)FALSE
/*****************************************************************************************************/
BOOL DSUtils::IsLineBlank(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSelQIPtr, long nLine)
{
if (FAILED(pTextSelQIPtr->MoveTo(nLine, 1, EnvDTE::dsMove)))
return FALSE;
if (FAILED(pTextSelQIPtr->SelectLine()))
return FALSE;
BSTR bstr = NULL;
pTextSelQIPtr->get_Text(&bstr);
CString sResult(static_cast<WCHAR*>(bstr));
TrimSpace(sResult);
// Release the selection
pTextSelQIPtr->EndOfLine(EnvDTE::dsMove);
return (sResult.IsEmpty());
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Clear white space in files
// INPUT:
// 1) pTextSelQIPtr: Text selection denoting which file is to be cleared
// 2)nStartLineNo: Start line number denoting where white space clearing starts
// 3)nEndLineNo: End line number denoting where white space clearing ends
//
// OUTPUT: 1)TRUE 2)FALSE
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::ClearSpace(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSelQIPtr,
long nStartLineNo,
long nEndLineNo)
{
while (true)
{
if (nStartLineNo > nEndLineNo)
break;
if (IsLineBlank(pTextSelQIPtr, nStartLineNo))
{
if (FAILED(pTextSelQIPtr->MoveTo(nStartLineNo, 1, EnvDTE::dsMove)))
return FALSE;
if (FAILED(pTextSelQIPtr->SelectLine()))
return FALSE;
if (FAILED(pTextSelQIPtr->Delete(1))) // Delete only once because SelectLine() selected whole line.
return FALSE;
nStartLineNo--;
nEndLineNo--;
}
nStartLineNo++;
}
// Release the selection
pTextSelQIPtr->EndOfLine(EnvDTE::dsMove);
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Delete handler declaration in the application source file.
// INPUT: 1) pTextSrcSelQIPtr: Text selection of application source file.
// 2) nDelLineNo: Line number of deleted event handler.
//
// OUTPUT: 1) TRUE: 2) FALSE:
// NOTE:
//
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::DelHdlerDec(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSrcSelQIPtr,long nDelLineNo)
{
// Move to the finded line
if (FAILED(pTextSrcSelQIPtr->MoveTo(nDelLineNo, 1,EnvDTE::dsMove)))// CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->MoveTo(nDelLineNo+1,1,EnvDTE::dsExtend)))//EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
// delete the finded line
//if (FAILED(pTextSrcSelQIPtr->put_Text(CComBSTR(""))))
// return FALSE;
//if (FAILED(pTextSrcSelQIPtr->Backspace(1)))
// return FALSE;
if(FAILED(pTextSrcSelQIPtr->Delete(1)))
return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Check atomic attribute of doing deleting state operations.
// INPUT: 1) DelStateList: List of total to-be-deleted state name.
// 2) DelHanderList: List of total to-be-deleted handler name(without parameters).
// 3) sHdrFilePath: Full path of application header file.
// 4) sSrcFilePath: Full path of application source file.
// 5) sAppName: Application name.
// 6) sParentName: To-be-deleted state's parent name.
//
// OUTPUT: 1) TRUE: 2)FALSE:
// NOTE: Check deleted state's parent state definition in state tree.
// Check deleted state definition macro start and end flag
// Check deleted handler declaration start and end flag
// Check deleted state declaration macro start and end flag.
// Not Check deleted state's macro in state tree definition.
// Not Check deleted state's internal handlers plus entry, exit handlers' completeness.
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::CheckDelStateAtomic(vector<CString> &DelStateList,
vector<CString> &DelHanderList,
LPCTSTR sHdrFilePath,
LPCTSTR sSrcFilePath,
LPCTSTR sAppName,
LPCTSTR sParentName)
{
// Copy a temporarily to-be-deleted state name list
vector<CString> TmpDelStateList;
TmpDelStateList.clear();
//vector <int>::iterator Iter;
//?the second parameter of assign means the first element beyond the range of elements to be copied?
//TmpDelStateList.assign(DelStateList.begin(),DelStateList.end());
//TmpDelStateList.push_back(DelStateList.end());
int NomOfEle=(int)DelStateList.size();
for(int i=0;i<NomOfEle;i++)
{
CString t=DelStateList.at(i);
TmpDelStateList.push_back(t);
}
/////////////////// Open source file
CComPtr<EnvDTE::Documents> pOpenDocsIPtr;
CComPtr<EnvDTE::Document>pTextSrcDocIPtr;
g_pDTE->get_Documents(&pOpenDocsIPtr);
if (pOpenDocsIPtr == NULL)
return FALSE;
CComQIPtr<EnvDTE::Documents, &EnvDTE::IID_Documents> pOpenDocsQIPtr(pOpenDocsIPtr);
if (FAILED(pOpenDocsQIPtr->Open(CComBSTR(sSrcFilePath), CComBSTR("Text"), VARIANT_FALSE, &pTextSrcDocIPtr)))
{
MessageBox(NULL,_T("Application "+(CString)sAppName+"'s source file failed to open."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
/////////////////// Get Source File Text Selection
//CComQIPtr<ITextDocument, &IID_ITextDocument> pTextSrcDocQIPtr(pTextSrcDocIPtr);
CComPtr<IDispatch> pTextSrcSelIPtr;
if (FAILED(pTextSrcDocIPtr->get_Selection(&pTextSrcSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSrcSelQIPtr(pTextSrcSelIPtr);
// Open header file
CComPtr<EnvDTE::Document> pTextHdrDocIPtr;
if (FAILED(pOpenDocsQIPtr->Open(CComBSTR(sHdrFilePath), CComBSTR("Text"), VARIANT_FALSE, &pTextHdrDocIPtr)))
{
MessageBox(NULL,_T("Application "+(CString)sAppName+"'s header file failed to open."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
// Get Header Text Selection
//CComQIPtr<ITextDocument, &IID_ITextDocument> pTextHdrDocQIPtr(pTextHdrDocIPtr);
CComPtr<IDispatch> pTextHdrSelIPtr;
if (FAILED(pTextHdrDocIPtr->get_Selection(&pTextHdrSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr(pTextHdrSelIPtr);
//////////////////////////////////////////////////////////////////////////
//Format
/*{{SME_STATE_DECLARE(TestApp)*/
/*}}SME_STATE_DECLARE*/
/*{{SME_STATE_TREE_DEF(TestApp)*/
/*}}SME_STATE_TREE_DEF*/
/*{{SME_STATE_DEF(TestApp,State)*/
/*}}SME_STATE_DEF*/
/*{{SME_BEGIN_EVENT_HANDLER(TestApp)*/
/*}}SME_END_EVENT_HANDLER*/
// SME_STATE(TestApp,s11,State1,s111)
// SME_BEGIN_STATE_DEF(TestApp,State3)
// SME_END_STATE_DEF
CString sStateTreeStartFlag;
CString sStateTreeEndFlag;
CString sParentFlag; //need check parent state definition in case that default state changes
sStateTreeStartFlag = "/*{{SME_STATE_TREE_DEF(";
sStateTreeStartFlag += sAppName;
sStateTreeStartFlag += ")*/";
sStateTreeEndFlag = "/*}}SME_STATE_TREE_DEF*/";
sParentFlag = "SME_STATE(";
sParentFlag += sAppName;
sParentFlag += ",";
sParentFlag += sParentName;
sParentFlag += ",";
VARIANT_BOOL vbFound;
// Find the state definition head
//pTextSrcSelQIPtr->SelectAll();//////////$$$$$$$$$$$$$$$////////////
pTextSrcSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateTreeStartFlag),EnvDTE::dsMatchFromStart,&vbFound)) || !vbFound)// EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: "+sStateTreeStartFlag+" expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateTreeStartFlag)));
return FALSE;
}
// Move to the end of line to do the next fine operation
// or it will fail in continuous find operations
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nSrcStateTreeStart = 0;
pTextSrcSelQIPtr->get_CurrentLine(&nSrcStateTreeStart);
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateTreeEndFlag), EnvDTE::dsMatchForward, &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: "+ sStateTreeEndFlag + " expected."), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateTreeEndFlag)));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nSrcStateTreeEnd = 0;
pTextSrcSelQIPtr->get_CurrentLine(&nSrcStateTreeEnd);
long nSrcStateTreeLine = nSrcStateTreeStart+1;
while (true)
{
if (nSrcStateTreeLine >= nSrcStateTreeEnd)
break;
if (FAILED(pTextSrcSelQIPtr->MoveTo(nSrcStateTreeLine,1, EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,EnvDTE::dsMove)))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
// Get selection line
BSTR bstr = NULL;
//pTextSrcSelQIPtr->SelectLine();
pTextSrcSelQIPtr->get_Text(&bstr);
char* bstrTemp = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstr);
delete[]bstrTemp;
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
// Check syntax of parent state in state tree in case that deletion of state will
// effect its parent state
if (sResult.Find(sParentFlag) == 0)
{
// SME_STATE(TestApp,State2,0,s21)
sResult.Replace(sParentFlag, NULL);
int idx = sResult.Find(')');
if (idx == sResult.GetLength() -1 )
{
sResult.Replace(")", NULL);
idx = sResult.Find(',');
if (idx != -1)
{
sResult.Replace(",", NULL);
idx = sResult.Find(' ');
if (idx == -1)
break;
}
}
}
nSrcStateTreeLine++;
}
if (nSrcStateTreeLine >= nSrcStateTreeEnd)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: " + sParentFlag + " expected."), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sParentFlag)));
return FALSE;
}
// Check deleted state definition syntax if they exist
while (true)
{
if (0 == (int)TmpDelStateList.size())
break;
// SME_STATE(TestApp,s11,State1,s111)
// SME_BEGIN_STATE_DEF(TestApp,State3)
// SME_END_STATE_DEF
// Get to-be-found flag names
CString sStateName = TmpDelStateList.at(0);
CString sStateStartFlag = "/*{{SME_STATE_DEF(";
sStateStartFlag += sAppName;
sStateStartFlag += ",";
sStateStartFlag += sStateName;
sStateStartFlag += ")";
CString sStateEndFlag = "/*}}SME_STATE_DEF*/";
CString sStateMacroStart = "";
CString sStateMacroEnd = "";
sStateMacroStart = "SME_BEGIN_STATE_DEF(";
sStateMacroStart += sAppName;
sStateMacroStart += ",";
sStateMacroStart += sStateName;
sStateMacroStart += ")";
sStateMacroEnd = "SME_END_STATE_DEF";
//pTextSrcSelQIPtr->SelectAll();//////$$$$$$$$$$$$$$$$$$$$//////////////
pTextSrcSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateStartFlag), EnvDTE::dsMatchFromStart,&vbFound)) || !vbFound)//EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" Warning: macro expansion " + sStateStartFlag+" not found")));
}
// Move to the end of line to do the next fine operation
// or it will fail in continuous find operations
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
// Check if users has deleted them already , there is no need to delete at all
if (vbFound == -1)//%%
{
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateEndFlag), EnvDTE::dsMatchForward, &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: "+sStateEndFlag+" expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateEndFlag)));
return FALSE;
}
// Move to the end of line to do the next fine operation
// or it will fail in continuous find operations
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateMacroEnd),EnvDTE::dsMatchForward,&vbFound)) || !vbFound)// EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: " + sStateMacroEnd + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateMacroEnd)));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR("SME_BEGIN_STATE_DEF"), EnvDTE::dsMatchBackward, &vbFound)) || !vbFound)//CComVariant(dsMatchBackward), &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: SME_BEGIN_STATE_DEF expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion SME_BEGIN_STATE_DEF")));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,EnvDTE::dsMove)))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
// Get selection line
BSTR bstr = NULL;
//pTextSrcSelQIPtr->SelectLine();
pTextSrcSelQIPtr->get_Text(&bstr);
char* bstrTemp = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstr);
delete[] bstrTemp;
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
// Match the wanted line to the beginning macro definition
if (sResult != sStateMacroStart)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: "+sStateMacroStart+" expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion "+sStateMacroStart)));
return FALSE;
}
}
TmpDelStateList.erase(TmpDelStateList.begin());
}
CString sStateDecStartFlag = "/*{{SME_STATE_DECLARE(";
sStateDecStartFlag += sAppName;
sStateDecStartFlag += ")*/";
CString sStateDecEndFlag = CString("SME_MAX_STATE(") + sAppName + ")"; //"/*}}SME_STATE_DECLARE*/";
CString sHandlerDecStartFlag = "/*{{SME_BEGIN_EVENT_HANDLER(";
sHandlerDecStartFlag += sAppName;
sHandlerDecStartFlag += ")*/";
CString sHandlerDecEndFlag = "/*}}SME_END_EVENT_HANDLER*/";
CString sAppClassDecStartFlag=CString("/*{{SME_APP_CLASS_DECLARE(")+sAppName+",";
// Note: we can not located "/*}}SME_APP_CLASS_DECLARE*/" as the end of app class declaration, because if there are more than 1
// app header is located at a same file
CString sAppClassDecEndFlag=CString("SME_STATE_TREE_DEC(")+sAppName+")";
// CString sAppClassDecEndFlag="/*}}SME_APP_CLASS_DECLARE*/";
///////////////////////////////////////////////////////////
// Search for the state declaration header.
//pTextHdrSelQIPtr->SelectAll();
pTextHdrSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sStateDecStartFlag),EnvDTE::dsMatchFromStart , &vbFound)) || !vbFound)//EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error: " + sStateDecStartFlag + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sStateDecStartFlag)));
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
// Get Start Line No
long nHdrStartLineNo = 0;
pTextHdrSelQIPtr->get_CurrentLine(&nHdrStartLineNo);
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sStateDecEndFlag),EnvDTE::dsMatchForward , &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error: "+sStateDecEndFlag+" expected."), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sStateDecEndFlag)));
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
// long nHdrEndLineNo = 0;
// pTextHdrSelQIPtr->get_CurrentLine(&nHdrEndLineNo);
///////////////////////////////////////////////////////////
// Search for the app class declaration header.
//pTextHdrSelQIPtr->SelectAll();
pTextHdrSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
long nAppClassStateLine=-1;
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sAppClassDecStartFlag), EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
} else
{
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove)))) //CComVariant(dsMove)
return FALSE;
pTextHdrSelQIPtr->get_CurrentLine(&nAppClassStateLine);
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sAppClassDecEndFlag), EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
AfxMessageBox(_T((CString)sHdrFilePath+" error: "+sAppClassDecEndFlag+" expected."), MB_ICONERROR|MB_OK);
return FALSE;
}
}
///////////////////////////////////////////////////////////
// Search for the event handler header.
//pTextHdrSelQIPtr->SelectAll();
pTextHdrSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sHandlerDecStartFlag),EnvDTE::dsMatchFromStart , &vbFound)) || !vbFound)//EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error: "+sHandlerDecStartFlag+" expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sHandlerDecStartFlag)));
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sHandlerDecEndFlag),EnvDTE::dsMatchForward , &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error: "+sHandlerDecEndFlag+" expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sHandlerDecEndFlag)));
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
DeleteStateFromStateTree(pTextSrcSelQIPtr, DelStateList, sAppName, nSrcStateTreeStart);
DeleteStateHandlerDec(pTextHdrSelQIPtr, DelHanderList, DelStateList, sAppName, nHdrStartLineNo, nAppClassStateLine);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Add state tree declaration to application source file.
// INPUT: 1) pTextSelQIPtr: Text selection of application source file
// 2) sStatename: State name.
// 3) sParent: Current state's parent's name.
// 4) sAppName: Application name.
// 5) sDefChild: Default child state name.
// 6) nSkippedLinNumFromApp: Number of states above the state to be inserted.
// 7) nParStateTreeDecLineNo: Line number of inserted state's parent state tree declaration
// 8) nAppStateTreeDecLineNo: Line number of inserted state's application declation in
// state tree.
//
// OUTPUT: 1) TRUE: 2)FALSE
// NOTE: Do this operation after checking atomic attribute operations
//
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::DeclareStateTree(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSrcSelQIPtr,
LPCTSTR sStatename,
LPCSTR sParent,
LPCTSTR sAppname,
LPCTSTR sDefChild,
UINT nSkippedLinNumFromApp,
long nParStateTreeDecLineNo,
long nAppStateTreeDecLineNo)
{
CString strStateName=CString(sStatename);
CString strParent=CString(sParent);
CString strAppName=CString(sAppname);
CString strDefChild=CString(sDefChild);
CString strParetname;
CString sStateTreeDef = "SME_STATE";
CString sStateTreeFind = sStateTreeDef+"("+strAppName+","+strAppName;
CString sStateParentFind=sStateTreeDef+"("+strAppName+","+strParent;
if (!strDefChild.IsEmpty())
{
if (FAILED(pTextSrcSelQIPtr->MoveTo(nParStateTreeDecLineNo, 1, EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,EnvDTE::dsMove)))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
pTextSrcSelQIPtr->get_Text(&bstr);
CString sResult(bstr);
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
sResult.Replace("-1",LPCTSTR(strDefChild));
if (FAILED(pTextSrcSelQIPtr->put_Text(CComBSTR(sResult))))
return FALSE;
}
UINT nItemNum = 0;
long nInsertLineNo = nAppStateTreeDecLineNo;
while (true)
{
if (nItemNum >= nSkippedLinNumFromApp)
break;
if (FAILED(pTextSrcSelQIPtr->MoveTo(nInsertLineNo, 1,EnvDTE::dsMove)))// CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,EnvDTE::dsMove)))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextSrcSelQIPtr->SelectLine();
pTextSrcSelQIPtr->get_Text(&bstr);
CString sResult(bstr);
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if (!sResult.IsEmpty())
{
nItemNum++;
}
nInsertLineNo++;
}
// Move the cursor to the end of matching line
if (FAILED(pTextSrcSelQIPtr->MoveTo(nInsertLineNo, 1,EnvDTE::dsMove)))// CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->Indent(1)))//EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
// Set the parent name
if (!strAppName.Compare(LPCTSTR(strParent)))
{
strParetname="0";
}
else
strParetname=strParent;
// Put a item of the state to the state tree definition
if (FAILED(pTextSrcSelQIPtr->put_Text(CComBSTR(sStateTreeDef+"("+strAppName+","+strStateName+","+strParetname+","+"-1"+")"))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->NewLine(1)))//EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Declare new state and add declaration to the application header files
// INPUT: 1) pTextHdrSelQIPtr: Text selection of application header file
// 2) sStatename: State name.
// 3) sEntryFuncName: Entry function name.
// 4) sExitFuncName: Exit function name.
// 5) nSkippedLinNumFromApp: Number of states above the state to be inserted.
// 6) nStateDecInsertLine: Line number of state declaration insert point
// *) nAppClassInsertLine: SME_STATE_EVT_HDL_TBL_DEC() insert point
// *) nHdrHdlDecLine: Line number of handler declaration start flag
//
// OUTPUT: 1) TRUE: Add declaration successfully. 2) FALST:
// NOTE: Do this operation after checking atomic attribute of adding state operations
//
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::DeclareNewState(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr,
LPCSTR sStatename,
LPCTSTR sEntryFuncName,
LPCTSTR sExitFuncName,
UINT nSkippedLinNumFromApp,
long nStateDecInsertLine,
long nAppClassInsertLine,
long nHdrHdlDecLine)
{
CString strEntryFunc = "";
CString strExitFunc = "";
// Adjust insert point line for 3 new insert lines because operation above has added some additional new lines to the original text
int nFuncNum=0;
if (strEntryFunc != "")
nFuncNum++;
if (strExitFunc != "")
nFuncNum++;
int nOffsetStateDec = ((nStateDecInsertLine>nAppClassInsertLine && nAppClassInsertLine>0) ?1:0) + (nStateDecInsertLine>nHdrHdlDecLine?nFuncNum:0);
int nOffsetAppClassDec = (nAppClassInsertLine>nStateDecInsertLine?1:0) + (nAppClassInsertLine>nHdrHdlDecLine?nFuncNum:0);
int nOffsetHdlDec = (nHdrHdlDecLine>nStateDecInsertLine?1:0) + ((nHdrHdlDecLine>nAppClassInsertLine && nAppClassInsertLine>0)?1:0);
nStateDecInsertLine+=nOffsetStateDec;
nAppClassInsertLine+=nOffsetAppClassDec;
nHdrHdlDecLine+=nOffsetHdlDec;
if (strcmp(sEntryFuncName, "SME_NULL") != 0)
strEntryFunc="int "+CString(sEntryFuncName)+ STR_HDLER_PROTOTYPE + ";\n";
if (strcmp(sExitFuncName, "SME_NULL") != 0)
strExitFunc="int "+CString(sExitFuncName)+ STR_HDLER_PROTOTYPE + ";\n";
// Insert SME_STATE_DECLARE([state])
if (FAILED(pTextHdrSelQIPtr->MoveTo(nStateDecInsertLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
// make the tab line
if (FAILED(pTextHdrSelQIPtr->Indent(1)))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->put_Text(CComBSTR(CString("SME_STATE_DECLARE(")+sStatename+")"))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->NewLine(1)))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
// Insert SME_STATE_EVT_HDL_TBL_DEC([state])
if (nAppClassInsertLine>0)
{
if (FAILED(pTextHdrSelQIPtr->MoveTo(nAppClassInsertLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
// make the tab line
if (FAILED(pTextHdrSelQIPtr->Indent(1)))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->put_Text(CComBSTR(CString("SME_STATE_EVT_HDL_TBL_DEC(")+sStatename+")"))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->NewLine(1)))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMatchForward)))
return FALSE;
};
if (strEntryFunc != "" || (strExitFunc != ""))
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrHdlDecLine,1,EnvDTE::dsMatchForward)))
return FALSE;
if (strEntryFunc != "")
{
// Put the declaration of the entry function
if (FAILED(pTextHdrSelQIPtr->put_Text(CComBSTR(strEntryFunc))))
return FALSE;
}
if (strExitFunc != "")
{
// Put the declaration of the exit function
if (FAILED(pTextHdrSelQIPtr->put_Text(CComBSTR(strExitFunc))))
return FALSE;
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Declare event handler to application header file.
// INPUT: 1) pTextHdrSelQIPtr: Text selection of application header file
// 2) sAppName: Application name.
// 3) sHandlerName: Event handler name(without parameters).
// 4) nHdlDecLineNo: Event handler declaration start flag.
// OUTPUT: 1) TRUE: 2)FALSE
// NOTE:
//
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::DeclareEventHandler(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr,
LPCTSTR sAppname,
LPCTSTR sFuncClassPrefix,
LPCTSTR sHandlerName,
long nHdlDecLineNo)
{
// Move the curse to the finded number
// No function class prefix in header file.
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdlDecLineNo, 1, EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
if(FAILED(pTextHdrSelQIPtr->put_Text(CComBSTR("int "+CString(sHandlerName)+STR_HDLER_PROTOTYPE + ";\n"))))
return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Add state definition to application source
// file.
// INPUT: 1) pTextSrcSelQIPtr: Text selection of application source file.
// 2) sStateName: State name.
// 3) sAppName: Application name.
// 4) sEntryFuncName: Entry function name.
// 5) sExitFuncName: Exit function name.
// sAppClassPrefix: App class with :: if app is a class.
// OUTPUT: 1) TRUE: 2)FALSE
// NOTE: Do this operation after checking atomic attribute of adding a new state operations
//
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::CreateStateDef(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSrcSelQIPtr,
LPCTSTR sStateName,
LPCTSTR sAppName,
LPCTSTR sFuncClassPrefix,
LPCTSTR sEntryFuncName,
LPCTSTR sExitFuncName)
{
CString sText;
CString sSeparator="/*{{SME_STATE_STATETREE_SEPARATOR}}*/";
//sText =CComBSTR("\nSME_BEGIN_STATE_DEF("+CString(sAppName)+","+CString(sStateName)+")\n\t/*{{SME_STATE_DEF("+sAppName+","+sStateName+
// ")*/\n\tSME_STATE_ENTRY_FUNC("+sEntryFuncName+")\n\tSME_STATE_EXIT_FUNC("+sExitFuncName+
// ")\n\t/*}}SME_STATE_DEF*/\nSME_END_STATE_DEF\n");
sText = "\nSME_BEGIN_STATE_DEF("+CString(sAppName)+","+CString(sStateName)+")\n\t/*{{SME_STATE_DEF("+sAppName+","+sStateName+
")*/\nSME_STATE_ENTRY_FUNC("+sEntryFuncName+")\nSME_STATE_EXIT_FUNC("+sExitFuncName+
")\n/*}}SME_STATE_DEF*/\n";
CString sTextEnd="SME_END_STATE_DEF\n";
CString strEntryFunc = "";
CString strExitFunc = "";
VARIANT_BOOL vbFound;
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sSeparator),EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nStateTreeSepNo = 0;
pTextSrcSelQIPtr->get_CurrentLine(&nStateTreeSepNo);
if (strcmp(sEntryFuncName, "SME_NULL") != 0)
strEntryFunc=CString("\nint ") + sFuncClassPrefix + CString(sEntryFuncName) + STR_HDLER_PROTOTYPE + "\n{\n\treturn 0;\n}\n\n";
if (strcmp(sExitFuncName, "SME_NULL") != 0)
strExitFunc=CString("\nint ") + sFuncClassPrefix + CString(sExitFuncName)+ STR_HDLER_PROTOTYPE + "\n{\n\treturn 0;\n}\n\n";
CString strEntryExit=strEntryFunc+strExitFunc;
if (IsLineBlank(pTextSrcSelQIPtr, nStateTreeSepNo-1))
{
if (FAILED(pTextSrcSelQIPtr->MoveTo(nStateTreeSepNo-1, 1, EnvDTE::dsMove)))
return FALSE;
} else
if (FAILED(pTextSrcSelQIPtr->MoveTo(nStateTreeSepNo, 1, EnvDTE::dsMove)))
return FALSE;
// Put a state definition
if (FAILED(pTextSrcSelQIPtr->put_Text(CComBSTR(sText))))
return FALSE;
if(FAILED(pTextSrcSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstColumn,EnvDTE::dsMove)))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->put_Text(CComBSTR(sTextEnd))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->EndOfDocument(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nEntryOrExitLineNo;
pTextSrcSelQIPtr->get_CurrentLine(&nEntryOrExitLineNo);
// Put the entry function and the exit function declaration of the state
if (strEntryExit != "")
{
if (FAILED(pTextSrcSelQIPtr->put_Text(CComBSTR(strEntryExit))))
return FALSE;
}
// Move to the entry function.
if (FAILED(pTextSrcSelQIPtr->MoveTo(nEntryOrExitLineNo+3, START_COL_POS, EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Create service file for storing event id list if necessary
// INPUT:
// OUTPUT: 1)TRUE 2)FALSE
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::CreateServiceFile(LPCTSTR sFilePath)
{
CString sFileName = sFilePath;
int idx = sFileName.ReverseFind('\\');
sFileName = sFileName.Right(sFileName.GetLength()-idx-1);
CString sPreProcFileName = sFileName;
sPreProcFileName.Replace('.', '_');
sPreProcFileName.MakeUpper();
CStdioFile ServiceFile; // .c file to be created
// Create the head file
if(! ServiceFile.Open(LPCTSTR(sFilePath),CFile::modeCreate|CFile::modeReadWrite|CFile::typeText))
{
#ifdef _DEBUG
afxDump<<"Service file could not be opened"<<"\n";
#endif
return FALSE;//exit(1);
}
char *sNote = "NOTE: The StateWizard will add mapping macros between /*{{ and /*}}. Do NOT modify manually.";
CString sHeaderFormat = "/*\nFILE:";
sHeaderFormat += sFileName;
sHeaderFormat += "\n%s\n*/\n\n#ifndef ";
sHeaderFormat += sPreProcFileName;
sHeaderFormat += "\n#define ";
sHeaderFormat += sPreProcFileName;
sHeaderFormat += "\n\n#include \"sme.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
CString sHeader;
sHeader.Format(sHeaderFormat, sNote);
CString sServiceDeclare;
sServiceDeclare = "enum\n{\n\t/*{{SME_EVENT_ID_LIST_DECLARE*/\n";
CString sEnd = "\t/*}}SME_EVENT_ID_LIST_DECLARE*/\n};\n\n#ifdef __cplusplus\n}\n#endif\n\n#endif\n\n";
sServiceDeclare += sEnd;
ServiceFile.WriteString(LPCTSTR(sHeader));
ServiceFile.WriteString(LPCTSTR(sServiceDeclare));
ServiceFile.Close();
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Add handler implementation and macro definition to application source file.
// INPUT: 1) pTextSrcSelQIPtr: Text selection of application source file.
// 2) sAppName: Application name.
// 3) sSrcState: Current state name.
// 4) sDestState: Transition state name.
// 5) sEventID: Event name.
// 6) sHandlerName: Event handler name.
// 7) nStateDefEndFlag: Line number of state definition macro start flag which owns
// current event handler.
//
// OUTPUT: 1)TRUE 2)FALSE
// NOTE:
//
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::CreateHandlerDef(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSrcSelQIPtr,
LPCTSTR sAppname,
LPCTSTR sFuncClassPrefix,
LPCTSTR sSrcState,
LPCTSTR sDestState,
LPCTSTR sEventID,
LPCTSTR sHandlerName,
long nStateDefEndFlag)
{
CString sEventDef = "SME_ON_EVENT";
if (FAILED(pTextSrcSelQIPtr->MoveTo(nStateDefEndFlag, 1,EnvDTE::dsMove)))// CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->Indent(1)))//EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
//if(sDestState==NULL)
if ( CComBSTR(sDestState) == "")
sDestState = "SME_INTERNAL_TRAN";
// Add the event handler definition to a state declaration
if (FAILED(pTextSrcSelQIPtr->put_Text(CComBSTR(sEventDef+"("+sEventID+","+sHandlerName+
","+sDestState+")"))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->NewLine(1)))//EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
// Add a handler function implementation to source file
// If handler has been used by some other events ,it will not
// redefine the handler function
if (strcmp(sHandlerName, "SME_NULL") != 0)
{
if(FAILED(pTextSrcSelQIPtr->EndOfDocument(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nFuncLineNo;
pTextSrcSelQIPtr->get_CurrentLine(&nFuncLineNo);
if(FAILED(pTextSrcSelQIPtr->put_Text(CComBSTR(CString("\nint ")+ sFuncClassPrefix + CString(sHandlerName)+"(struct SME_APP_T *pApp, struct SME_EVENT_T *pEvent)\n{\nreturn 0;\n}\n\n"))))
return FALSE;
// Move to the function.
if (FAILED(pTextSrcSelQIPtr->MoveTo(nFuncLineNo+3, START_COL_POS, EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
}
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Calculator the code line number of the given file.
// INPUT: 1) sFilePath: File full path.
// 2) CountResultArray: Record the different state line's number.
// OUTPUT: None.
// NOTE: The pattern of function implementation if <FunctionName> ... {
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::CodeLineCalculator(CString sFilePath, UINT *CountResultArray)
{
UCHAR nCommentState = NO_COMMENTS_STATE;
CStdioFile stdFile;
// Open the given file for read only
if (!stdFile.Open(sFilePath, CFile::modeRead | CFile::typeText ))
{
if (!stdFile.Open(sFilePath, CFile::modeCreate | CFile::modeWrite | CFile::typeText ))
return FALSE;
return TRUE;
}
CString sCurrentLine;
while (true)
{
// Read in a line from the file.
if (!stdFile.ReadString(sCurrentLine))
break;
ParseCommentState(sCurrentLine, nCommentState, CountResultArray, NULL);
}
stdFile.Close();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Check atomic attribute of deleting an event handler
// INPUT: 1) sSrcFilePath: Full path of application source file.
// 2) sHdrFilePath: Full path of application header file.
// 3) appName: Application name.
// 4) stateName: State name which owns to-be-deleted event.
// 5) eventName: Event name to be deleted.
// 6) sDelAction: Action name to be deleted.
//
// OUTPUT: 1)TRUE: 2)FALSE:
// NOTE: If the event handler to be deleted has been deleted by users already,
// it will notify users about this.
//
//////////////////////////////////////////////////////////////////////////
BOOL DSUtils::CheckDelEventAtomic(LPCTSTR sSrcFilePath,
LPCTSTR sHdrFilePath,
LPCTSTR appName,
LPCTSTR stateName,
LPCTSTR eventName,
LPCTSTR sDelAction)
{
CString sAppName = appName;
CString sStateName = stateName;
/////////////////// Open file
CComPtr<EnvDTE::Documents> pOpenDocsIPtr;
CComPtr<EnvDTE::Document> pTextSrcDocIPtr;
g_pDTE->get_Documents(&pOpenDocsIPtr);
if (pOpenDocsIPtr == NULL)
return FALSE;
CComQIPtr<EnvDTE::Documents, &EnvDTE::IID_Documents> pOpenDocsQIPtr(pOpenDocsIPtr);
if (FAILED(pOpenDocsQIPtr->Open(CComBSTR(sSrcFilePath), CComBSTR("Text"), VARIANT_FALSE, &pTextSrcDocIPtr)))
{
MessageBox(NULL,_T("Application "+(CString)sAppName+"'s source file failed to open."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
/////////////////// Get Text Selection
//CComQIPtr<ITextDocument, &IID_ITextDocument> pTextSrcDocQIPtr(pTextSrcDocIPtr);
CComPtr<IDispatch> pTextSrcSelIPtr;
if (FAILED(pTextSrcDocIPtr->get_Selection(&pTextSrcSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSrcSelQIPtr(pTextSrcSelIPtr);
//pTextSrcSelQIPtr->SelectAll();
pTextSrcSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
CString sStartTag = "/*{{SME_STATE_DEF";
CString sEndTag = "/*}}SME_STATE_DEF*/";
CString sStateDefHead = sStartTag+"("+sAppName+","+sStateName+")*/";
CString sStateDefEnd = sEndTag;
CString sEvntHead = "SME_ON_EVENT(";
CString sDelEventDec = sEvntHead + eventName+",";
VARIANT_BOOL vbFound;
// Find the state definition head
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateDefHead),EnvDTE::dsMatchFromStart,&vbFound)) || !vbFound)// EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: " + sStateDefHead + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateDefHead)));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nStartLineNo;
if (FAILED(pTextSrcSelQIPtr->get_CurrentLine(&nStartLineNo)))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateDefEnd), EnvDTE::dsMatchForward,&vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: " + sStateDefEnd + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateDefEnd)));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nEndLineNo;
if (FAILED(pTextSrcSelQIPtr->get_CurrentLine(&nEndLineNo)))
return FALSE;
long nLine = nStartLineNo+1;
BOOL bIsFound = FALSE;
while (true)
{
if (nLine >= nEndLineNo)
break;
if (FAILED(pTextSrcSelQIPtr->MoveTo(nLine, 1,EnvDTE::dsMove)))// CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,EnvDTE::dsMove)))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextSrcSelQIPtr->SelectLine();
pTextSrcSelQIPtr->get_Text(&bstr);
char* bstrTemp = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrTemp);
delete[]bstrTemp;
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
// Format: SME_ON_EVENT(event2,OnState1event2,State2)
if ((!sResult.IsEmpty()) && (sResult.Find(sDelEventDec) != -1))
{
bIsFound = TRUE;
sResult.Replace(sDelEventDec, NULL);
int idx = sResult.Find(')');
if (idx != sResult.GetLength()-1)
{
CString sWarningMsg;
sWarningMsg.Format("%s(Line %d) error: %s expected.", (CString)sSrcFilePath, nLine, sDelEventDec);
MessageBox(NULL,_T(sWarningMsg),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T(sWarningMsg)));
return FALSE;
}
sResult.Replace(")", NULL);
idx = sResult.Find(',');
if (idx == -1)
{
CString sWarningMsg;
sWarningMsg.Format("%s(Line %d) error: %s expected.", (CString)sSrcFilePath, nLine, sDelEventDec);
MessageBox(NULL,_T(sWarningMsg), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T(sWarningMsg)));
return FALSE;
}
sResult.SetAt(idx, ' ');
idx = sResult.Find(',');
if (idx != -1)
{
CString sWarningMsg;
sWarningMsg.Format("%s(Line %d) error: %s expected.", (CString)sSrcFilePath, nLine, sDelEventDec);
MessageBox(NULL,_T(sWarningMsg), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T(sWarningMsg)));
return FALSE;
}
break;
}
nLine++;
}
if (nLine >= nEndLineNo)
{
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" Warning: " + sDelEventDec+" not found")));
}
// Modify the declaration of the event handler function in the head file
if (strcmp(sDelAction, "SME_NULL") != 0)
{
// Open file
CComPtr<EnvDTE::Document> pTextHdrDocIPtr;
if (FAILED(pOpenDocsQIPtr->Open(CComBSTR(sHdrFilePath), CComBSTR("Text"),VARIANT_FALSE, &pTextHdrDocIPtr)))
{
MessageBox(NULL,_T("Application "+(CString)sAppName+"'s header file failed to open."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
// Get Text Selection
//CComQIPtr<ITextDocument, &IID_ITextDocument> pTextHdrDocQIPtr(pTextHdrDocIPtr);
CComPtr<IDispatch> pTextHdrSelIPtr;
if (FAILED(pTextHdrDocIPtr->get_Selection(&pTextHdrSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr(pTextHdrSelIPtr);
CString sEventHdlStartFlag = "/*{{SME_BEGIN_EVENT_HANDLER(";
sEventHdlStartFlag = sEventHdlStartFlag + sAppName +")*/";
CString sEventHdlEndFlag = "/*}}SME_END_EVENT_HANDLER*/";
// Search for the event handler function name
if(FAILED(pTextHdrSelQIPtr->MoveTo(1,1,EnvDTE::dsMove)))
{
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sEventHdlStartFlag),EnvDTE::dsMatchForward, &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error: "+ sEventHdlStartFlag + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sEventHdlStartFlag)));
return FALSE;
}
// move the cursor to the end of matching line
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nHdrStartLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nHdrStartLineNo);
// Search for StateEnd declaration
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sEventHdlEndFlag),EnvDTE::dsMatchForward , &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error: "+ sEventHdlEndFlag + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sEventHdlEndFlag)));
return FALSE;
}
// Move the cursor to the end of matching line
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nHdrEndLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nHdrEndLineNo);
//////////////////////////////////////////////////////////////////////////
// Record the line number
long nFuncStartLinePos = 0;
long nFuncStartColPos = 0;
long nFuncEndLinePos = 0;
long nFuncEndColPos = 0;
long nHdrLineNo = nHdrStartLineNo+1;
BOOL bHdlIsFound = FALSE;
CString sLastLine ="";
// Initialize the line number and column number
nFuncStartLinePos = nHdrStartLineNo+1;
nFuncStartColPos = 1;
while (true)
{
if (nHdrLineNo >= nHdrEndLineNo)
break;
long nHeadSpaceNo = 0;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrLineNo, 1,EnvDTE::dsMove)))// CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,EnvDTE::dsMove)))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->get_CurrentColumn(&nHeadSpaceNo)))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextHdrSelQIPtr->SelectLine();
pTextHdrSelQIPtr->get_Text(&bstr);
char* bstrTemp = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrTemp);
delete[]bstrTemp;
sResult.TrimLeft();
//int State2Exit(struct SME_APP_T *pApp, struct SME_EVENT_T *pEvent);
if (!sResult.IsEmpty())
{
while (true)
{
int idx = sResult.Find(';');
if (-1 == idx)
{
sLastLine += " ";
sLastLine += sResult;
break;
}
if (nFuncEndLinePos == nHdrLineNo)
nFuncEndColPos = nFuncEndColPos + idx +1;
else
{
nFuncEndLinePos = nHdrLineNo;
nFuncEndColPos = nHeadSpaceNo+idx+1;
}
sLastLine += " ";
CString sCurrentLine = sLastLine + sResult.Left(idx+1);
// Initialize for the next loop
sLastLine = "";
sResult = sResult.Right(sResult.GetLength()-idx-1);
idx = sCurrentLine.Find('(');
// idx == -1 ?????????
CString sFuncName = sCurrentLine.Left(idx);
sFuncName.TrimRight();
sFuncName.Replace('\t', ' ');
idx = sFuncName.ReverseFind(' ');
sFuncName = sFuncName.Right(sFuncName.GetLength()-idx-1);
if (sFuncName == (CString)sDelAction)
{
bHdlIsFound = TRUE;
break;
}
nFuncStartLinePos = nHdrLineNo;
nFuncStartColPos = nFuncEndColPos;
}
if (bHdlIsFound == TRUE)
break;
}
nHdrLineNo++;
}
if (bHdlIsFound == FALSE)
{
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" Warning: int "+sDelAction+"(struct SME_APP_T *pApp, struct SME_EVENT_T *pEvent); not found")));
}
else
{
if (DelEventHdlFunc(pTextHdrSelQIPtr, nFuncStartLinePos, nFuncStartColPos ,nFuncEndLinePos, nFuncEndColPos) == FALSE)
return FALSE;
}
}
if (bIsFound == TRUE)
DelHdlerDec(pTextSrcSelQIPtr, nLine);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Check atomic attribute of adding state operations.
// INPUT: 1) sSrcFilePath: Full path of application source file.
// 2) sHdrFilePath: Full path of application header file.
// 3) sStatename: State name.
// 4) sParent: Current state's parent's name.
// 5) sAppName: Application name.
// 6) sDefChild: Default child state name.
// 7) nSkippedLinNumFromApp: Num of sibling child state of the same parent
// 8) sEntryFuncName: Entry function name.
// 9) sExitFuncName: Exit function name.
// OUTPUT: 1) TRUE: 2) FALSE: Error in any key word or macro definition
// NOTE:
//
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::CheckAddStateAtomic(LPCTSTR sSrcFilePath, LPCTSTR sHdrFilePath, LPCSTR sStatename,
LPCTSTR sParent, LPCTSTR sAppName, LPCTSTR sFuncClassPrefix, LPCTSTR sDefChild,
UINT nSkippedLinNumFromApp, LPCTSTR sEntryFuncName, LPCTSTR sExitFuncName)
{
// Open file
CComPtr<EnvDTE::Documents> pOpenDocsIPtr;
CComPtr<EnvDTE::Document>pTextHdrDocIPtr;
g_pDTE->get_Documents(&pOpenDocsIPtr);
if (pOpenDocsIPtr == NULL)
return FALSE;
CComQIPtr<EnvDTE::Documents, &EnvDTE::IID_Documents> pOpenDocsQIPtr(pOpenDocsIPtr);
if (FAILED(pOpenDocsQIPtr->Open(CComBSTR(sHdrFilePath), CComBSTR("Text"),VARIANT_FALSE, &pTextHdrDocIPtr)))
{
MessageBox(NULL,_T("Application "+(CString)sAppName+"'s header file failed to open."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
// Get Text Selection
//CComQIPtr<ITextDocument, &IID_ITextDocument> pTextHdrDocQIPtr(pTextHdrDocIPtr);
CComPtr<IDispatch> pTextHdrSelIPtr;
if (FAILED(pTextHdrDocIPtr->get_Selection(&pTextHdrSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr(pTextHdrSelIPtr);
//pTextHdrSelQIPtr->SelectAll();
pTextHdrSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
CString sStateDecHead = CString("/*{{SME_STATE_DECLARE(")+sAppName+")*/";
CString sStateDecEnd = "/*}}SME_STATE_DECLARE*/";
CString sStateDecParent = CString("SME_STATE_DECLARE(")+sAppName+")";
CString sClassDecHead = CString("/*{{SME_APP_CLASS_DECLARE(")+sAppName+","; // IMPORTANT: should define a tail.
CString sClassDecEnd = CString("SME_STATE_TREE_DEC(") + sAppName + ")"; //"/*}}SME_APP_CLASS_DECLARE*/";
CString sEventHandlerEnd = "/*}}SME_END_EVENT_HANDLER*/";
VARIANT_BOOL vbFound;
// search for the state enumeration declaration
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sStateDecHead), EnvDTE::dsMatchFromStart , &vbFound)) || ! vbFound)//EnvDTE::dsMatchFromStart, &vbFound)) || ! vbFound)
// EnvDTE::dsMatchFromStart
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error:" + sStateDecHead + " expected."),NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error:"+ sStateDecHead + " expected")));
return FALSE;
}
// move the cursor to the end of matching line
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nStartLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nStartLineNo);
// Search for StateEnd declaration
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sStateDecEnd),EnvDTE::dsMatchForward , &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error:" + sStateDecEnd + " expected."), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sStateDecEnd)));
return FALSE;
}
// Move the cursor to the end of matching line
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nEndLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nEndLineNo);
// Search for the parent state and record down the line of insert point
unsigned int nItemNum = 0;
long nHdrStateDecLine = nStartLineNo+1;
long nStateDecInsertLine = nHdrStateDecLine;
BOOL bParentStateFound=FALSE;
while (true)
{
if (nHdrStateDecLine >= nEndLineNo)
break;
if (nItemNum >= nSkippedLinNumFromApp && bParentStateFound==TRUE)
break;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrStateDecLine, 1,EnvDTE::dsMove))) //CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,EnvDTE::dsMove)))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextHdrSelQIPtr->SelectLine();
pTextHdrSelQIPtr->get_Text(&bstr);
char* bstrTemp = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrTemp);
delete[]bstrTemp;
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if (!sResult.IsEmpty())
{
nItemNum++;
if (nItemNum == nSkippedLinNumFromApp )
nStateDecInsertLine = nHdrStateDecLine+1;
}
if ((!sResult.IsEmpty()) && (sResult == sStateDecParent))
bParentStateFound=TRUE;
nHdrStateDecLine++;
}
if (bParentStateFound==FALSE)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error:" + sStateDecParent+ " expected."), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sStateDecParent)));
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
///////////////////////////////////////////////////////////////////////////
// Search for the app class declaration
BOOL bExistClassDec=FALSE;
long nAppClassDecStartLine = -1;
long nAppClassDecEndLine = -1;
long nAppClassInserLine =-1;
//pTextHdrSelQIPtr->SelectAll();
pTextHdrSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sClassDecHead), EnvDTE::dsMatchFromStart, &vbFound)) || ! vbFound)
{
bExistClassDec = FALSE;
} else
{
bExistClassDec = TRUE;
// move the cursor to the end of matching line
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
pTextHdrSelQIPtr->get_CurrentLine(&nAppClassDecStartLine);
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sClassDecEnd), EnvDTE::dsMatchForward, &vbFound)) || ! vbFound)
{
AfxMessageBox(_T((CString)sHdrFilePath+" error:" + sClassDecEnd+ " expected."), MB_ICONERROR|MB_OK);
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
// Record the line no of the /*}}SME_STATE_DECLARE*/
pTextHdrSelQIPtr->get_CurrentLine(&nAppClassDecEndLine);
// Locate the insert point of SME_STATE_DECLARE.
nItemNum = 0;
long nDecLine = nAppClassDecStartLine+1;
nAppClassInserLine = nDecLine;
bParentStateFound=FALSE;
while (true)
{
if (nDecLine >= nAppClassDecEndLine)
break;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nDecLine, 1, VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,VARIANT_BOOL(EnvDTE::dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend)))) //EndOfLine(CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
pTextHdrSelQIPtr->get_Text(&bstr);
CString sResult = BSTR2CString(bstr);
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if (!sResult.IsEmpty())
{
nItemNum++;
if (nItemNum == nSkippedLinNumFromApp )
{
nAppClassInserLine = nDecLine+1;
break;
}
}
nDecLine++;
}
}
///////////////////////////////////////////////////////////////////////////
// Search for the end of event handler tables
if (!bExistClassDec)
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sStateDecHead), EnvDTE::dsMatchFromStart , &vbFound)) || ! vbFound)
return FALSE;
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sEventHandlerEnd),EnvDTE::dsMatchForward, &vbFound)) || !vbFound)// EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error:" + sEventHandlerEnd+" expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sEventHandlerEnd)));
return FALSE;
}
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
long nHdrHdlDecLine = 0;
pTextHdrSelQIPtr->get_CurrentLine(&nHdrHdlDecLine);
///////////////////////////////////////////////////////////////////////////
// Check source file all-or-nothing
CComPtr<EnvDTE::Document> pTextSrcDocIPtr;
if (FAILED(pOpenDocsQIPtr->Open(CComBSTR(sSrcFilePath), CComBSTR("Text"),VARIANT_FALSE, &pTextSrcDocIPtr)))
{
MessageBox(NULL,_T("Application "+(CString)sAppName+"'s source file failed to open."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
// Get Text Selection
//CComQIPtr<ITextDocument, &IID_ITextDocument> pTextSrcDocQIPtr(pTextSrcDocIPtr);
CComPtr<IDispatch> pTextSrcSelIPtr;
if (FAILED(pTextSrcDocIPtr->get_Selection(&pTextSrcSelIPtr)))
{
return FALSE;
}
///////////////////////////////////////////////////////////////////////////
// Search for the state tree definition
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSrcSelQIPtr(pTextSrcSelIPtr);
CString sSeparator="/*{{SME_STATE_STATETREE_SEPARATOR}}*/";
//pTextSrcSelQIPtr->SelectAll();
pTextSrcSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sSeparator),EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:" + sSeparator + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in seperater flag " + sSeparator)));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
CString strStateName=CString(sStatename);
CString strParent=CString(sParent);
CString strAppName=CString(sAppName);
CString strDefChild=CString(sDefChild);
CString sStateTreeDefHead = CString("/*{{SME_STATE_TREE_DEF(")+strAppName+")*/";
CString sStateTreeDefEnd = "/*}}SME_STATE_TREE_DEF*/";
CString sStateTreeFind = CString("SME_STATE(")+strAppName+","+strAppName+","; // SHOULD add , as separator
CString sStateParentFind=CString("SME_STATE(")+strAppName+","+strParent+","; // SHOULD add , as separator
//pTextSrcSelQIPtr->SelectAll();
pTextSrcSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
// Find the state tree definition head
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateTreeDefHead),EnvDTE::dsMatchFromStart , &vbFound)) || !vbFound)//EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:" + sStateTreeDefHead + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateTreeDefHead)));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
nStartLineNo = 0;
if (FAILED(pTextSrcSelQIPtr->get_CurrentLine(&nStartLineNo)))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateTreeDefEnd),EnvDTE::dsMatchForward , &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:"+sStateTreeDefEnd+" expected."), NULL,MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateTreeDefEnd)));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
nEndLineNo = 0;
pTextSrcSelQIPtr->get_CurrentLine(&nEndLineNo);
BOOL bUpdateDfltChild = FALSE;
long nLine = nStartLineNo+1;
long nFlagLineNo = -1;
long nParentLineNo = 0;
while (true)
{
if (nLine >= nEndLineNo)
break;
if (FAILED(pTextSrcSelQIPtr->MoveTo(nLine, 1,EnvDTE::dsMove))) //CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,EnvDTE::dsMove)))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextSrcSelQIPtr->SelectLine();
pTextSrcSelQIPtr->get_Text(&bstr);
char* bstrTemp = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrTemp);
delete[]bstrTemp;
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if (!sResult.IsEmpty())
{
if (!strDefChild.IsEmpty()&& (sResult.Find(sStateParentFind) != -1))
{
// SME_STATE(MyApp2,State2,0,-1)
bUpdateDfltChild = TRUE;
nParentLineNo = nLine;
}
if (sResult.Find(sStateTreeFind) != -1)
{
nFlagLineNo = nLine;
}
}
nLine++;
}
if (nFlagLineNo < 0)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:" + sStateTreeFind + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateTreeFind)));
return FALSE;
}
if ((!strDefChild.IsEmpty()) && (bUpdateDfltChild == FALSE))
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:"+ sStateParentFind+" expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateParentFind)));
return FALSE;
}
DeclareNewState(pTextHdrSelQIPtr, sStatename, sEntryFuncName, sExitFuncName, nSkippedLinNumFromApp
, nStateDecInsertLine, nAppClassInserLine, nHdrHdlDecLine);
DeclareStateTree(pTextSrcSelQIPtr, sStatename, sParent, sAppName, sDefChild, nSkippedLinNumFromApp
, nParentLineNo, nFlagLineNo);
CreateStateDef(pTextSrcSelQIPtr, sStatename, sAppName, sFuncClassPrefix, sEntryFuncName, sExitFuncName);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Check atomic attribute of adding an event operations.
// INPUT: 1) sSrcFilePath: Full path of application source file.
// 2) sHdrFilePath: Full path of application header file.
// 3) sAppName: Application name.
// 4) sSrcState: Current state name.
// 5) sDestState: Transition state name.
// 6) sEventID: Event ID of new event.
// 7) sHandlerName: Handler name of event handler(without parameters)
//
// OUTPUT: 1) TRUE: 2)FALSE
// Note:
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::CheckAddEventAtomic(LPCTSTR sSrcFilePath,
LPCTSTR sHdrFilePath,
LPCTSTR sAppname,
LPCTSTR sFuncClassPrefix,
LPCTSTR sSrcState,
LPCTSTR sDestState,
LPCTSTR sEventID,
LPCTSTR sHandlerName)
{
CComPtr<EnvDTE::Documents> pOpenDocsIPtr;
g_pDTE->get_Documents(&pOpenDocsIPtr);
if (pOpenDocsIPtr == NULL)
return FALSE;
CComPtr<EnvDTE::Document> pTextHdrDocIPtr, pTextSrcDocIPtr;
CComQIPtr<EnvDTE::Documents, &EnvDTE::IID_Documents> pOpenDocsQIPtr(pOpenDocsIPtr);
// Open Header file
if (FAILED(pOpenDocsQIPtr->Open(CComBSTR(sHdrFilePath), CComBSTR("Text"), VARIANT_FALSE, &pTextHdrDocIPtr)))
{
MessageBox(NULL,_T("Application "+(CString)sAppname+"'s header file failed to open."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
// Get Text Selection
//CComQIPtr<ITextDocument, &IID_ITextDocument> pTextHdrDocQIPtr(pTextHdrDocIPtr);
CComPtr<IDispatch> pTextHdrSelIPtr;
if (FAILED(pTextHdrDocIPtr->get_Selection(&pTextHdrSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr(pTextHdrSelIPtr);
if(FAILED(pTextHdrSelQIPtr->MoveTo(1,1,EnvDTE::dsMove)))
{
return FALSE;
}
BOOL bHdlIsNULL = TRUE;
long nHdrHdlDecLine = 0;
if (strcmp(sHandlerName, "SME_NULL") != 0)
{
bHdlIsNULL = FALSE;
CString sStartFlag = "/*{{SME_BEGIN_EVENT_HANDLER(";
sStartFlag = sStartFlag + sAppname +")*/";
CString sEndFlag = "/*}}SME_END_EVENT_HANDLER*/";
VARIANT_BOOL vbFound;
// Search for the event handler function name
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sStartFlag),EnvDTE::dsMatchForward , &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error:" + sStartFlag + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sStartFlag)));
return FALSE;
}
// move the cursor to the end of matching line
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nStartLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nStartLineNo);
// Search for StateEnd declaration
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR(sEndFlag),EnvDTE::dsMatchForward, &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sHdrFilePath+" error:"+sEndFlag+" expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sHdrFilePath+" error: unexpected composition in macro expansion " + sEndFlag)));
return FALSE;
}
// Move the cursor to the end of matching line
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nEndLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nEndLineNo);
// Record the line number
long nLineNo = nStartLineNo+1;
CString sLastLine ="";
while (true)
{
if (nLineNo >= nEndLineNo)
{
sLastLine.TrimLeft();
sLastLine.TrimRight();
if (!sLastLine.IsEmpty())
{
int idx = sLastLine.Find('(');
CString sFuncName = sLastLine.Left(idx);
sFuncName.TrimRight();
idx = sFuncName.ReverseFind(' ');
sFuncName = sFuncName.Right(sFuncName.GetLength()-idx-1);
if (sFuncName == (CString)sHandlerName)
{
bHdlIsNULL = TRUE;
}
}
break;
}
if (FAILED(pTextHdrSelQIPtr->MoveTo(nLineNo, 1, EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,EnvDTE::dsMove)))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextHdrSelQIPtr->SelectLine();
pTextHdrSelQIPtr->get_Text(&bstr);
char* bstrTemp = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrTemp);
delete[]bstrTemp;
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace('\t', ' ');
CString sTemp = " ";
sTemp+=sResult;
sResult = sTemp;
//int State2Exit(struct SME_APP_T *pApp, struct SME_EVENT_T *pEvent);
if (!sResult.IsEmpty())
{
int idx = sResult.Find(';');
if (idx == -1)
{
sLastLine += sResult;
nLineNo++;
continue;
}
CString sCurrentLine = sLastLine + sResult.Left(idx+1);
sLastLine = sResult.Right(sResult.GetLength()-idx-1);
idx = sCurrentLine.Find('(');
CString sFuncName = sCurrentLine.Left(idx);
sFuncName.TrimRight();
idx = sFuncName.ReverseFind(' ');
sFuncName = sFuncName.Right(sFuncName.GetLength()-idx-1);
if (sFuncName == (CString)sHandlerName)
{
bHdlIsNULL = TRUE;
break;
}
}
nLineNo++;
}
// Check the name of the event handler whether is already existed
// CString sDupli = "int "+CString(sHandlerName)+"(struct SME_APP_T *pApp, struct SME_EVENT_T *pEvent)";
if (bHdlIsNULL == TRUE)
{
MessageBox(NULL,_T("Error! The action "+(CString)sHandlerName+"already exists."),NULL, MB_ICONERROR|MB_OK);
// return FALSE;
OutPutStringToPane(_bstr_t(_T("Error! The action "+(CString)sHandlerName+" already exists.")));
}
nHdrHdlDecLine = nEndLineNo;
}
// Open file
if (FAILED(pOpenDocsQIPtr->Open(CComBSTR(sSrcFilePath), CComBSTR("Text"),VARIANT_FALSE, &pTextSrcDocIPtr)))
{
MessageBox(NULL,_T("Application "+(CString)sAppname+"'s source file failed to open."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
// Get Text Selection
//CComQIPtr<ITextDocument, &IID_ITextDocument> pTextSrcDocQIPtr(pTextSrcDocIPtr);
CComPtr<IDispatch> pTextSrcSelIPtr;
if (FAILED(pTextSrcDocIPtr->get_Selection(&pTextSrcSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSrcSelQIPtr(pTextSrcSelIPtr);
//pTextSrcSelQIPtr->SelectAll();
pTextSrcSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
CString sStartTag = "/*{{SME_STATE_DEF";
CString sEndTag = "/*}}SME_STATE_DEF*/";
CString sStateDefHead = sStartTag+"("+sAppname+","+sSrcState+")*/";
CString sStateDefEnd = sEndTag;
VARIANT_BOOL vbFound;
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateDefHead), EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)//EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:" + sStateDefHead + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateDefHead)));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSrcSelQIPtr->FindText(CComBSTR(sStateDefEnd),EnvDTE::dsMatchForward , &vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error:" + sStateDefHead + " expected."),NULL, MB_ICONERROR|MB_OK);
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: unexpected composition in macro expansion " + sStateDefHead)));
return FALSE;
}
if (FAILED(pTextSrcSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nStateDefEndFlag = 0;
if (FAILED(pTextSrcSelQIPtr->get_CurrentLine(&nStateDefEndFlag)))
return FALSE;
// Add code to header file
if (bHdlIsNULL == FALSE)
{
DeclareEventHandler(pTextHdrSelQIPtr, sAppname, sFuncClassPrefix, sHandlerName, nHdrHdlDecLine);
}
CreateHandlerDef(pTextSrcSelQIPtr, sAppname, sFuncClassPrefix, sSrcState, sDestState, sEventID, sHandlerName, nStateDefEndFlag);
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Delete one state declaration from the head file.
// INPUT: 1) sApp: an application name.
// 2) sParent: the name of a parent of the selected item.
// 3) sSelected: the selected item's name.
// OUTPUT: None.
// NOTE: The pattern of function implementation if <FunctionName> ... {
//
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::ChangeDefaultState(LPCTSTR sSrcFilePath, LPCTSTR sApp, LPCTSTR sParent, LPCTSTR sSelected)
{
CString sAppName=CString(sApp);
CString sParentName=CString(sParent);
CString sSelectedName=CString(sSelected);
/////////////////// Open file
CComPtr<EnvDTE::Documents> pOpenDocsIPtr;
CComPtr<EnvDTE::Document>pTextDocIPtr;
g_pDTE->get_Documents(&pOpenDocsIPtr);
if (pOpenDocsIPtr == NULL)
return FALSE;
CComQIPtr<EnvDTE::Documents, &EnvDTE::IID_Documents> pOpenDocsQIPtr(pOpenDocsIPtr);
if (FAILED(pOpenDocsQIPtr->Open(CComBSTR(sSrcFilePath), CComBSTR("Text"),VARIANT_FALSE, &pTextDocIPtr)))
{
return FALSE;
}
/////////////////// Get Text Selection
//CComQIPtr<ITextDocument, &IID_ITextDocument> pTextDocQIPtr(pTextDocIPtr);
CComPtr<IDispatch> pTextSelIPtr;
if (FAILED(pTextDocIPtr->get_Selection(&pTextSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextSelQIPtr(pTextSelIPtr);
//pTextSelQIPtr->SelectAll();
pTextSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
CString sStartTag = "/*{{";
CString sEndTag = "/*}}";
CString sStateTreeDef = "SME_STATE_TREE_DEF";
CString sStateTreeDefHead = sStartTag+sStateTreeDef+"("+sAppName+")*/";
CString sStateTreeDefEnd = sEndTag+sStateTreeDef+"*/";
CString sStateParentFind=sStateTreeDef.Left(9)+"("+sAppName+","+sParentName+",";
VARIANT_BOOL vbFound;
// Fine the state tree definition head
if (FAILED(pTextSelQIPtr->FindText(CComBSTR(sStateTreeDefHead),EnvDTE::dsMatchFromStart , &vbFound)) || !vbFound)//EnvDTE::dsMatchFromStart, &vbFound)) || !vbFound)
{
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: "+ sStateTreeDefHead + " expected" )));
return FALSE;
}
if (FAILED(pTextSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nStartLineNo;
if (FAILED(pTextSelQIPtr->get_CurrentLine(&nStartLineNo)))
return FALSE;
if (FAILED(pTextSelQIPtr->FindText(CComBSTR(sStateTreeDefEnd),EnvDTE::dsMatchForward, &vbFound)) || !vbFound)// EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
OutPutStringToPane(_bstr_t(_T((CString)sSrcFilePath+" error: "+ sStateTreeDefEnd + " expected")));
return FALSE;
}
if (FAILED(pTextSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nEndLineNo;
if (FAILED(pTextSelQIPtr->get_CurrentLine(&nEndLineNo)))
return FALSE;
long nLineNo = nStartLineNo+1;
while (true)
{
if (nLineNo >= nEndLineNo)
break;
if (FAILED(pTextSelQIPtr->MoveTo(nLineNo, 1, EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,EnvDTE::dsMove)))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
//pTextSelQIPtr->SelectLine();
pTextSelQIPtr->get_Text(&bstr);
char* bstrTemp = _com_util::ConvertBSTRToString(bstr);
CString sResult(bstrTemp);
delete[]bstrTemp;
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if ((!sResult.IsEmpty()) && (sResult.Find(sStateParentFind) == 0))
{
sResult.Replace(sStateParentFind, NULL);
int idx = sResult.Find(')');
if (idx == sResult.GetLength()-1)
{
sResult.Replace(")", NULL);
idx = sResult.Find(',');
if (idx != -1)
{
break;
}
}
}
nLineNo++;
}
if (nLineNo >= nEndLineNo)
{
MessageBox(NULL,_T((CString)sSrcFilePath+" error: "+ sStateParentFind + " expected."),NULL,MB_ICONERROR|MB_OK);
return FALSE;
}
// Move to the finded line
if (FAILED(pTextSelQIPtr->MoveTo(nLineNo, 1,EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextSelQIPtr->EndOfLine(EnvDTE::dsExtend)))//CComVariant(dsExtend))))
return FALSE;
// Get the wanted to be modified line
BSTR bstrChangeLine;
if(FAILED(pTextSelQIPtr->get_Text(&bstrChangeLine)))
return FALSE;
CString sLine=CString(bstrChangeLine);
int idx = sLine.ReverseFind(',');
if (idx == -1)
{
CString sWarningMsg;
sWarningMsg.Format("%s(%d) error: illegal syntax", (CString)sSrcFilePath, nLineNo);
OutPutStringToPane(_bstr_t(_T(sWarningMsg)));
return FALSE;
}
sLine=sLine.Left(idx);
sLine=sLine+","+sSelectedName+")";
// Put the modified line text
if (FAILED(pTextSelQIPtr->put_Text(CComBSTR(sLine))))
return FALSE;
return TRUE;
}
BOOL DSUtils::CheckAddAppAtomic(LPCTSTR sPrjName/*no path just the name*/, LPCTSTR sAppName)
{
char *sNote = "NOTE: The StateWizard will add mapping macros between /*{{ and /*}}. Do NOT modify manually.";
_bstr_t bstrPath = GetProjectDir(_bstr_t(sPrjName));
CString strPrjPath = _com_util::ConvertBSTRToString(bstrPath.GetBSTR());
CString strAppName = sAppName;
CString sFileHFullPath = strPrjPath + "\\"+sAppName+".h";
CString sFileCFullPath;
if(g_nFileType==APPTYPE_CLASS || g_nFileType==APPTYPE_CPP_FILE)
sFileCFullPath = strPrjPath + "\\"+sAppName+".cpp";
else
sFileCFullPath = strPrjPath + "\\"+sAppName+".c";
CString sPrjFullPath;
vector<_bstr_t> sPrjFileList;
sPrjFileList.clear();
CComPtr<EnvDTE::Project> prj = NULL;
prj = GetProject(_bstr_t(sPrjName));
if(prj==NULL)
return FALSE;
GetProjectFileList(prj, sPrjFileList);
int nFileNum = 0;
while (true)
{
if (nFileNum == sPrjFileList.size())
break;
_bstr_t sFilePath = sPrjFileList[nFileNum];
char* filePath = _com_util::ConvertBSTRToString(sFilePath.GetBSTR());
if (sFileHFullPath.CompareNoCase(filePath) == 0)
{
delete [] filePath;
AfxMessageBox(_T("A file with the name you specified already exists."), MB_ICONERROR|MB_OK);
return FALSE;
}
if (sFileCFullPath.CompareNoCase(filePath) == 0)
{
delete [] filePath;
AfxMessageBox(_T("A file with the name you specified already exists."), MB_ICONERROR|MB_OK);
return FALSE;
}
delete [] filePath;
nFileNum++;
}
CStdioFile AppHFile; // .h file to be created
CStdioFile AppCFile; // .c file to be created
if (AppHFile.Open(LPCTSTR(sFileHFullPath),CFile::modeRead | CFile::typeText ))
{
AppHFile.Close();
AfxMessageBox(_T("The file: "+(CString)sFileHFullPath + " already exists."), MB_ICONERROR|MB_OK);
return FALSE;
}
if (AppCFile.Open(LPCTSTR(sFileCFullPath),CFile::modeRead | CFile::typeText ))
{
AppCFile.Close();
AfxMessageBox(_T("The file: "+(CString)sFileCFullPath + " already exists."), MB_ICONERROR|MB_OK);
return FALSE;
}
/*
// Create the head file
if(! AppHFile.Open(LPCTSTR(sFileHFullPath),CFile::modeCreate|CFile::modeReadWrite|CFile::typeText))
{
AfxMessageBox(_T("Application "+(CString)sAppName+"'s header file failed to open."), MB_ICONERROR|MB_OK);
return FALSE; //exit(1);
}
AppHFile.Close();
// Create the source file
if(! AppCFile.Open(LPCTSTR(sFileCFullPath),CFile::modeCreate|CFile::modeReadWrite|CFile::typeText))
{
AfxMessageBox(_T("Application "+(CString)sAppName+"'s source file failed to open."), MB_ICONERROR|MB_OK);
#ifdef _DEBUG
afxDump<<"AppCFile could not be opened"<<"\n";
#endif
return FALSE; // exit(1)
}
AppCFile.Close();
*/
CString sSrcFileName;
if(g_nFileType==APPTYPE_CLASS || g_nFileType==APPTYPE_CPP_FILE)
sSrcFileName = ".\\"+strAppName+".cpp";
else
sSrcFileName = ".\\"+strAppName+".c";
CString sHdrFileName=".\\"+strAppName+".h";
if (AddSrcHdrFilesToPrj(prj, _bstr_t(sSrcFileName), _bstr_t(sHdrFileName), _bstr_t("")))
{
return TRUE;
}
// Delete relative files when ops failed
/*
::DeleteFile(sFileHFullPath);
::DeleteFile(sFileCFullPath);
*/
return FALSE;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get Event id list by calling ParseEventIdList function
// INPUT: 1)sServiceHdrPath: Text selection of header file
// 2)EventIdList: Header file path
//
// OUTPUT: 1)TRUE: Success
// 2)FALSE: Fail
//
// Note: If the document is opened already, there is no necessary to open again.
// Otherwise, open it right now.
/////////////////////////////////////////////////////////////////////////
BOOL DSUtils::GetEventIdList(LPCTSTR sServiceHdrPath,vector<_bstr_t> &EventIdList)
{
// Open file
CComPtr<EnvDTE::Documents> pOpenDocsIPtr;
CComPtr<EnvDTE::Document>pTextHdrDocIPtr;
g_pDTE->get_Documents(&pOpenDocsIPtr);
if (pOpenDocsIPtr == NULL)
return FALSE;
CComQIPtr<EnvDTE::Documents,&EnvDTE::IID_Documents> spActiveDocs(pOpenDocsIPtr);
ATLASSERT(spActiveDocs);
//record the num of opened documents
long openedDocNum = 0;
// get active document num in documents
spActiveDocs->get_Count(&openedDocNum);
// resource file should not be opened
for (long i = 1L; i <= openedDocNum; i++)
{
CComPtr<EnvDTE::Document> pGenericDocIPtr;
BSTR bstr = NULL;
_bstr_t bstrRet("");
spActiveDocs->Item(_variant_t(i, VT_I4), &pGenericDocIPtr);
pGenericDocIPtr->get_FullName(&bstr);
bstrRet = _bstr_t(bstr, false);
char* docPath = _com_util::ConvertBSTRToString(bstrRet.GetBSTR());
CString sOpenedDocPath = docPath;
delete[] docPath;
// Confirm whether service file has already opened
if (!sOpenedDocPath.CompareNoCase(sServiceHdrPath))
{
//CComQIPtr<ITextDocument, &IID_ITextDocument> pTextHdrDocQIPtr(pGenericDocIPtr);
CComPtr<IDispatch> pTextHdrSelIPtr;
if (FAILED(pGenericDocIPtr->get_Selection(&pTextHdrSelIPtr)))
{
return FALSE;
}
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr(pTextHdrSelIPtr);
ParseEventIdListFromWnd(pTextHdrSelQIPtr, sServiceHdrPath, EventIdList);
return TRUE;
}
}
ParseEventIdListFromFile(sServiceHdrPath, EventIdList);
size_t size = EventIdList.size();
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get Event id list by calling ParseEventIdList function
// INPUT: 1)sServiceHdrPath: Text selection of header file
// 2)EventIdList: Header file path
//
// OUTPUT: 1)TRUE: Success
// 2)FALSE: Fail
//
// Note: If the document is opened already, there is no necessary to open again.
// Otherwise, open it right now.
/////////////////////////////////////////////////////////////////////////
BOOL DSUtils::CreateAppFiles(LPCTSTR sPrjName, LPCTSTR sAppName, LPCTSTR sEntryFuncName, LPCSTR sExitFuncName)
{
char *sNote = "NOTE: The StateWizard will add mapping macros between /*{{ and /*}}. Do NOT modify manually.";
_bstr_t bstrPath = GetProjectDir(sPrjName);
char* tempPath = _com_util::ConvertBSTRToString(bstrPath.GetBSTR());
CString strPrjPath = tempPath;
delete []tempPath;
CString strAppName = sAppName;
CString sFileHFullPath = strPrjPath + "\\"+sAppName+".h";
CString sFileCFullPath;
if(g_nFileType==APPTYPE_CLASS || g_nFileType==APPTYPE_CPP_FILE)
sFileCFullPath = strPrjPath + "\\"+sAppName+".cpp";
else
sFileCFullPath = strPrjPath + "\\"+sAppName+".c";
CStdioFile AppHFile; // .h file to be created
CStdioFile AppCFile; // .c file to be created
CString sAppClass="C" + strAppName;
CString sFuncClassPrev;
if (g_nFileType==APPTYPE_CLASS)
sFuncClassPrev = sAppClass + "::";
// Create the head file
if(! AppHFile.Open(LPCTSTR(sFileHFullPath),CFile::modeCreate|CFile::modeReadWrite|CFile::typeText))
{
#ifdef _DEBUG
afxDump<<"AppHFile could not be opened"<<"\n";
#endif
return FALSE;// exit(1);
}
else
{
CString sUpperAppName = strAppName;
sUpperAppName.MakeUpper();
CString sHeaderFormat = "/*\nFILE:%s.h\n%s\n*/\n\n#ifndef %s_H\n#define %s_H\n\n#include \"sme.h\"\n\n#ifdef __cplusplus\nextern \"C\" {\n#endif\n\n";
CString sHeader;
sHeader.Format(sHeaderFormat, strAppName, sNote, sUpperAppName, sUpperAppName);
CString sStateDeclare;
sStateDeclare = "SME_BEGIN_STATE_DECLARE("+strAppName+")\n\t/*{{SME_STATE_DECLARE("+strAppName+
")*/\n\tSME_STATE_DECLARE("+strAppName+")\n\tSME_MAX_STATE("+strAppName+
")\n\t/*}}SME_STATE_DECLARE*/\nSME_END_STATE_DECLARE\n\n";
CString sBegin = "/*{{SME_BEGIN_EVENT_HANDLER("+strAppName+")*/\n";
CString sEndHdndler = "/*}}SME_END_EVENT_HANDLER*/\n\n";
CString sEndHdr = "#ifdef __cplusplus\n}\n#endif\n\n#endif\n\n";
CString sBaseClass="SME_APP_T";
CString sAppClassHdr;
sAppClassHdr="class " + sAppClass+": public SME_APP_T\n{\npublic:\n\t" + sAppClass
+ "(const char* _sAppName, const struct SME_STATE_TREE_TABLE_T *_pStateTree):" + sBaseClass + "(_sAppName, _pStateTree) {};\n\n";
CString sAppClassDeclare;
sAppClassDeclare = "SME_BEGIN_APP_CLASS_DECLARE("+sAppClass+","+sBaseClass+")\n\t/*{{SME_APP_CLASS_DECLARE("+strAppName+","+sAppClass+","+sBaseClass+
")*/\n\tSME_STATE_EVT_HDL_TBL_DEC("+strAppName+")\n\tSME_STATE_TREE_DEC("+strAppName+
")\n\t/*}}SME_APP_CLASS_DECLARE*/\nSME_END_APP_CLASS_DECLARE\n\n";
CString sEntryFunc = "";
CString sExitFunc = "";
// No function class prefix in header file.
if (strcmp(sEntryFuncName, "SME_NULL") != 0)
sEntryFunc = "int "+ CString(sEntryFuncName)+STR_HDLER_PROTOTYPE + ";\n";
if (strcmp(sExitFuncName, "SME_NULL") != 0)
sExitFunc = "int "+ CString(sExitFuncName)+STR_HDLER_PROTOTYPE + ";\n";
AppHFile.WriteString(LPCTSTR(sHeader));
if (g_nFileType==APPTYPE_CLASS)
AppHFile.WriteString(LPCTSTR(sAppClassHdr));
AppHFile.WriteString(LPCTSTR(sStateDeclare));
if (g_nFileType==APPTYPE_CLASS)
AppHFile.WriteString(LPCTSTR(sAppClassDeclare));
AppHFile.WriteString(LPCTSTR(sBegin));
if (sEntryFunc != "")
AppHFile.WriteString(LPCTSTR(sEntryFunc));
if (sExitFunc != "")
AppHFile.WriteString(LPCTSTR(sExitFunc));
AppHFile.WriteString(LPCTSTR(sEndHdndler));
if (g_nFileType==APPTYPE_CLASS)
AppHFile.WriteString("};\n\n");
AppHFile.WriteString(LPCTSTR(sEndHdr));
AppHFile.Close();
}
// Create the source file
if(! AppCFile.Open(LPCTSTR(sFileCFullPath),CFile::modeCreate|CFile::modeReadWrite|CFile::typeText))
{
#ifdef _DEBUG
afxDump<<"AppCFile could not be opened"<<"\n";
#endif
return FALSE; //exit(1);
}
else
{
CString sText;
sText.Format("/*\nFILE: %s.c/cpp\n%s\n*/\n\n#include \"sme.h\"\n#include \"%s.h\"\n\n", strAppName, sNote, strAppName);
CString sHandlerClass;
if (g_nFileType==APPTYPE_CLASS)
sHandlerClass.Format("SME_HANDLER_CLASS_DEF(%s)\n\n", strAppName);
CString sAppDef = "SME_BEGIN_STATE_DEF("+strAppName+ ","+strAppName+")\n\t/*{{SME_STATE_DEF("+strAppName+","+strAppName+
")*/\n\tSME_STATE_ENTRY_FUNC("+sEntryFuncName+")\n\tSME_STATE_EXIT_FUNC("+sExitFuncName+
")\n\t/*}}SME_STATE_DEF*/\nSME_END_STATE_DEF\n\n";
sAppDef =sText+sHandlerClass+sAppDef;
CString sSeparator1="/*{{SME_STATE_STATETREE_SEPARATOR}}*/\n\n";
CString sStateTreeDEF;
sStateTreeDEF="SME_BEGIN_STATE_TREE_DEF("+strAppName+
")\n\t/*{{SME_STATE_TREE_DEF("+strAppName+")*/\n\tSME_STATE("+strAppName+","+
strAppName+",SME_INVALID_STATE,-1)\n\t/*}}SME_STATE_TREE_DEF*/\nSME_END_STATE_TREE_DEF\n\n";
CString sSepatator2;
sSepatator2.Format("/*{{SME_DEC_IMP_SEPARATOR}}*/\n\nSME_APPLICATION_DEF(%s, \"%s\")\n\n", strAppName, strAppName);
CString sEntryFunc = "";
CString sExitFunc = "";
if (strcmp(sEntryFuncName, "SME_NULL") != 0)
sEntryFunc="int "+ sFuncClassPrev + CString(sEntryFuncName)+STR_HDLER_PROTOTYPE + "\n{\n\treturn 0;\n}\n\n";
if (strcmp(sExitFuncName, "SME_NULL") != 0)
sExitFunc="int "+ sFuncClassPrev + CString(sExitFuncName)+STR_HDLER_PROTOTYPE + "\n{\n\treturn 0;\n}\n\n";
AppCFile.WriteString(LPCTSTR(sAppDef));
AppCFile.WriteString(LPCTSTR(sSeparator1));
AppCFile.WriteString(LPCTSTR(sStateTreeDEF));
AppCFile.WriteString(LPCTSTR(sSepatator2));
if (sEntryFunc != "")
AppCFile.WriteString(LPCTSTR(sEntryFunc));
if (sExitFunc != "")
AppCFile.WriteString(LPCTSTR(sExitFunc));
AppCFile.Close();
}
return TRUE;
}
BOOL DSUtils::ExecuteCommand(_bstr_t &commandName)
{
HRESULT re = g_pDTE->ExecuteCommand(commandName.GetBSTR(),CComBSTR(""));
if(SUCCEEDED(re))
return TRUE;
else
return FALSE;
}
BOOL DSUtils::IsFileOpen(_bstr_t& FileName)
{
ATLASSERT(g_pDTE != NULL );
CComPtr<EnvDTE::ItemOperations> m_pItemOperation;
HRESULT re = g_pDTE->get_ItemOperations(&m_pItemOperation);
ATLASSERT(SUCCEEDED(re));
CComBSTR viewTye(EnvDTE::vsViewKindCode);
VARIANT_BOOL ifOpen;
re = m_pItemOperation->IsFileOpen(FileName.GetBSTR(),viewTye,&ifOpen);
ATLASSERT(SUCCEEDED(re));
return ifOpen==-1 ? TRUE:FALSE ;
}
// If lineNumber is -1; just activate the file only.
BOOL DSUtils::OpenFileAndMoveLineTo(_bstr_t& FilePath,long lineNumber)
{
if(!IsFileOpen(FilePath))
{
if(!OpenFile(FilePath))
return FALSE;
}
CComPtr<EnvDTE::Documents> docs = NULL;
g_pDTE->get_Documents(&docs);
long docCount;
docs->get_Count(&docCount);
for(long i=1;i<=docCount;i++)
{
CComVariant var(i);
CComPtr<EnvDTE::Document> doc;
docs->Item(var,&doc);
BSTR fileFullName;
doc->get_FullName(&fileFullName);
if(wcscmp(FilePath.GetBSTR(),fileFullName)==0)
{
doc->Activate();
if (lineNumber!=-1)
{
CComPtr<IDispatch> docDispatch;
doc->get_Selection(&docDispatch);
CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> textSel(docDispatch);
//Edited By Fengxin
textSel->GotoLine(lineNumber,VARIANT_FALSE);
//textSel->MoveTo(lineNumber,0,VARIANT_BOOL(EnvDTE::dsMove));
}
return TRUE; //??????? Memory Leaks
}
::SysFreeString(fileFullName); //?????????????????????
}
return FALSE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Store the parameter to the ini file
// INPUT: 1).The section name 2)The key name 3) The value according to the key
// OUTPUT: True:Success False: Failed
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::PutParamStoreValue(LPCTSTR sSection, LPCTSTR sKey, LPCTSTR Value)
{
return CParamStore::GetInstance().PutValue(sSection,sKey,Value);
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get the max level of displaying the state tree
// INPUT:
// OUTPUT: The max level
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
int DSUtils::GetGMaxLevelNul()
{
return g_nMaxLevelNum;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION:Get the file Type
// INPUT:
// OUTPUT: 0 means *.cpp,1 means *.c
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
int DSUtils::GetGFileType()
{
return g_nFileType;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Parse file syntax to get list of event id
// INPUT: 1)pTextHdrSelQIPtr: Text selection of header file
// 2)sServiceHdrPath: Header file path
// 3)EventIdList: Array to store event id
//
// OUTPUT: 1)TRUE: Success
// 2)FALSE: Fail
//
// Note: Key word to match is /*{{SME_EVENT_ID_LIST_DECLARE*/ and
// /*}}SME_EVENT_ID_LIST_DECLARE*/. They give the boundary of declared
// event id list.
/////////////////////////////////////////////////////////////////////////
BOOL DSUtils::ParseEventIdListFromWnd(CComQIPtr<EnvDTE::TextSelection, &EnvDTE::IID_TextSelection> pTextHdrSelQIPtr,
LPCTSTR sServiceHdrPath,
vector<_bstr_t> &EventIdList)
{
long nOriginLineNo;
pTextHdrSelQIPtr->get_CurrentLine(&nOriginLineNo);
long nOriginColNo;
pTextHdrSelQIPtr->get_CurrentColumn(&nOriginColNo);
VARIANT_BOOL vbFound;
// search for the StateHead declaration
//pTextHdrSelQIPtr->SelectAll();
pTextHdrSelQIPtr->EndOfDocument(VARIANT_FALSE);// NOTE: ? Move to the end of document, FindText() will take effect.
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR("/*{{SME_EVENT_ID_LIST_DECLARE*/"), EnvDTE::dsMatchFromStart, &vbFound)) || ! vbFound)//EnvDTE::dsMatchFromStart, &vbFound)) || ! vbFound)
{
MessageBox(NULL,_T((CString)sServiceHdrPath+" error:/*{{SME_EVENT_ID_LIST_DECLARE*/ expected."),NULL,MB_ICONERROR|MB_OK);
return FALSE;
}
// move the cursor to the end of matching line
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nBeginLine;
pTextHdrSelQIPtr->get_CurrentLine(&nBeginLine);
// Search for StateEnd declaration
if (FAILED(pTextHdrSelQIPtr->FindText(CComBSTR("/*}}SME_EVENT_ID_LIST_DECLARE*/"), EnvDTE::dsMatchForward,&vbFound)) || !vbFound)//EnvDTE::dsMatchForward, &vbFound)) || !vbFound)
{
MessageBox(NULL,_T((CString)sServiceHdrPath+" error:/*}}SME_EVENT_ID_LIST_DECLARE*/ expected."),NULL, MB_ICONERROR|MB_OK);
return FALSE;
}
// Move the cursor to the end of matching line
if (FAILED(pTextHdrSelQIPtr->EndOfLine(EnvDTE::dsMove)))//CComVariant(dsMove))))
return FALSE;
long nEndLine;
pTextHdrSelQIPtr->get_CurrentLine(&nEndLine);
long nHdrLine = nBeginLine+1;
CString sText = "";
BOOL bStillComment = FALSE; // Mark whether it is backslash at the end of line. If it is, then need to concatenate two lines
// Eliminate // comments
while (true)
{
if (nHdrLine >= nEndLine)
break;
if (FAILED(pTextHdrSelQIPtr->MoveTo(nHdrLine, 1,VARIANT_BOOL(EnvDTE::dsExtend)))) //CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->StartOfLine(EnvDTE::vsStartOfLineOptionsFirstText,EnvDTE::dsMove)))//CComVariant(dsFirstText), CComVariant(dsMove))))
return FALSE;
if (FAILED(pTextHdrSelQIPtr->EndOfLine(VARIANT_BOOL(EnvDTE::dsExtend))))//CComVariant(dsExtend))))
return FALSE;
BSTR bstr = NULL;
pTextHdrSelQIPtr->get_Text(&bstr);
CString sResult(bstr);
sResult.TrimLeft();
sResult.TrimRight();
sResult.Replace("\t", NULL);
sResult.Replace(" ", NULL);
if (!sResult.IsEmpty())
{
int idx = sResult.Find("//");
int slashIdx = sResult.ReverseFind('\\');
if (bStillComment == TRUE)
{
if (slashIdx != (sResult.GetLength()-1))
bStillComment = FALSE;
}
else
{
if (idx != -1)
{
sText += (sResult.Left(idx));
if (slashIdx == (sResult.GetLength()-1))
bStillComment = TRUE;
}
else
{
if (slashIdx == (sResult.GetLength()-1))
sResult=sResult.Left(sResult.GetLength()-1);
sText = sText + sResult;
}
}
}
nHdrLine++;
}
// Eliminate /**/ comments
while (true)
{
int idx1 = sText.Find("/*");
if (idx1 != -1)
{
int idx2 = sText.Find("*/", idx1+1);
ATLASSERT(idx2 != -1);
CString sTemp = sText.Left(idx1);
sTemp += sText.Right(sText.GetLength()-idx2-2);
sText = sTemp;
}
else
break;
}
// Parse to get event id which is separated by comma
EventIdList.clear();//.RemoveAll();
while (true)
{
int idx = sText.Find(",");
if (idx == -1)
{
sText.TrimLeft();
sText.TrimRight();
if (!sText.IsEmpty())
{
idx = sText.Find("=");
if (idx != -1)
{
sText = sText.Left(idx);
sText.TrimRight();
}
EventIdList.insert(EventIdList.end(),(_bstr_t)sText);//Add(sText);
}
break;
}
else
{
CString sEventId = sText.Left(idx);
sText = sText.Right(sText.GetLength()-idx-1);
sEventId.TrimLeft();
sEventId.TrimRight();
if (!sEventId.IsEmpty())
{
idx = sEventId.Find("=");
if (idx != -1)
{
sEventId = sEventId.Left(idx);
sEventId.TrimRight();
}
EventIdList.insert(EventIdList.end(),(_bstr_t)sEventId);//Add(sEventId);
}
}
}
if (FAILED(pTextHdrSelQIPtr->MoveTo(nOriginLineNo, nOriginColNo, VARIANT_BOOL(EnvDTE::dsMove))))//CComVariant(dsMove))))
return FALSE;
return TRUE;
}
///////////////////////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Get eventid List from eventid.h file
// INPUT: the full path of eventid.h file
// OUTPUT: EventIdList
// NOTE:
///////////////////////////////////////////////////////////////////////////////////////////
BOOL DSUtils::ParseEventIdListFromFile(LPCTSTR sServiceHdrPath,
vector<_bstr_t> &EventIdList)
{
CStdioFile OpenedFile;
if (OpenedFile.Open(sServiceHdrPath, CFile::modeRead | CFile::typeText ) == 0)
{
// File exists in dsp file but does not exist in disk
// DSUtils(m_pApp).OutPutStringToPane("failure in create tag db: open a file\n");
OutPutStringToPane(_bstr_t(_T((CString)sServiceHdrPath+" error: unexpected failure to open this file. \n")));
return FALSE;
}
CString sCurrentLine = "";
CString sText = "";
BOOL bIsFound = FALSE;
BOOL bStillComment = FALSE;
while (true)
{
// Read a line from the file.
if (!OpenedFile.ReadString(sCurrentLine))
{
bIsFound = FALSE;
break;
}
sCurrentLine.TrimLeft();
sCurrentLine.TrimRight();
if (sCurrentLine.IsEmpty())
continue;
if (bIsFound == TRUE)
{
int idx = sCurrentLine.Find("//");
int slashIdx = sCurrentLine.ReverseFind('\\');
int nLen = sCurrentLine.GetLength();
if (bStillComment == TRUE)
{
if (slashIdx != (nLen-1))
bStillComment = FALSE;
}
else
{
if (idx != -1)
{
sText += (sCurrentLine.Left(idx));
if (slashIdx == (nLen-1))
bStillComment = TRUE;
}
else
{
if (slashIdx == (nLen-1))
sCurrentLine = sCurrentLine.Left(nLen-1);
sText = sText + sCurrentLine;
}
}
}
if (sCurrentLine.Compare("/*{{SME_EVENT_ID_LIST_DECLARE*/") == 0)
bIsFound = TRUE;
if (sCurrentLine.Compare("/*}}SME_EVENT_ID_LIST_DECLARE*/") == 0)
break;
}
if (bIsFound == FALSE)
return FALSE;
OpenedFile.Close();
// Eliminate /**/ comments
while (true)
{
int idx1 = sText.Find("/*");
if (idx1 != -1)
{
int idx2 = sText.Find("*/", idx1+1);
ATLASSERT(idx2 != -1);
CString sTemp = sText.Left(idx1);
sTemp += sText.Right(sText.GetLength()-idx2-2);
sText = sTemp;
}
else
break;
}
// Parse to get event id which is separated by comma
EventIdList.clear();//RemoveAll();
while (true)
{
int idx = sText.Find(",");
if (idx == -1)
{
sText.TrimLeft();
sText.TrimRight();
if (!sText.IsEmpty())
{
idx = sText.Find("=");
if (idx != -1)
{
sText = sText.Left(idx);
sText.TrimRight();
}
EventIdList.insert(EventIdList.end(),(_bstr_t)sText);//Add(sText);
}
break;
}
else
{
CString sEventId = sText.Left(idx);
sText = sText.Right(sText.GetLength()-idx-1);
sEventId.TrimLeft();
sEventId.TrimRight();
if (!sEventId.IsEmpty())
{
idx = sEventId.Find("=");
if (idx != -1)
{
sEventId = sEventId.Left(idx);
sEventId.TrimRight();
}
EventIdList.insert(EventIdList.end(),(_bstr_t)sEventId);//Add(sEventId);
}
}
}
return TRUE;
}
/////////////////////////////////////////////////////////////////////////
// DESCRIPTION: Output string to output window
// INPUT: 1)bstrText: string needs to be output
//
// OUTPUT: 1)TRUE: Success
// 2)FALSE: Fail
/////////////////////////////////////////////////////////////////////////
BOOL DSUtils::OutPutStringToPane(_bstr_t bstrText)
{
CComPtr<EnvDTE::Windows> wins = NULL;
HRESULT re = g_pDTE->get_Windows(&wins);
if (FAILED(re) || wins == NULL)
return FALSE;
CComPtr<EnvDTE::Window> win;
re = wins->Item(CComVariant(CComBSTR(EnvDTE::vsWindowKindOutput)),&win);
if (FAILED(re) || win == NULL)
return FALSE;
CComPtr<IDispatch> spOutputWindowDisp;
re = win->get_Object(&spOutputWindowDisp);
if (FAILED(re) || spOutputWindowDisp == NULL)
return FALSE;
CComQIPtr<EnvDTE::OutputWindow> spOutputWindow = spOutputWindowDisp;
if (spOutputWindow == NULL)
return FALSE;
CComPtr<EnvDTE::OutputWindowPanes> spOutputWindowPanes;
re = spOutputWindow->get_OutputWindowPanes(&spOutputWindowPanes);
if (FAILED(re) || spOutputWindowPanes == NULL)
return FALSE;
//first we should find if the out put window has exits
long wincount = 0;
BOOL IfNeedCreate = TRUE;
spOutputWindowPanes->get_Count(&wincount);
CComPtr<EnvDTE::OutputWindowPane> pan = NULL;
if(wincount>0)
{
for(long i = 1;i<=wincount;i++)
{
CComVariant var(i);
CComPtr<EnvDTE::OutputWindowPane> Pane;
spOutputWindowPanes->Item(var,&Pane);
BSTR paneName;
Pane->get_Name(&paneName);
_bstr_t fileNameWapper(paneName,false);
if(fileNameWapper==_bstr_t(CComBSTR(OUTPUT_WINDOW_NAME),false))
{
IfNeedCreate = FALSE;
pan = Pane;
break;
}
}
}
if(IfNeedCreate==TRUE)
{
CComPtr<EnvDTE::OutputWindowPane> spOutputWindowPane;
re = spOutputWindowPanes->Add(CComBSTR(OUTPUT_WINDOW_NAME), &spOutputWindowPane);
if (FAILED(re) || spOutputWindowPane == NULL)
return FALSE;
spOutputWindowPane->OutputString(bstrText.GetBSTR());
spOutputWindowPane->OutputString(CComBSTR(L"\r\n"));
}
else
{
pan->OutputString(bstrText.GetBSTR());
pan->OutputString(CComBSTR(L"\r\n"));
}
return TRUE;
}
BOOL DSUtils::CleanPane()
{
CComPtr<EnvDTE::Windows> wins = NULL;
HRESULT re = g_pDTE->get_Windows(&wins);
if (FAILED(re) || wins == NULL)
return FALSE;
CComPtr<EnvDTE::Window> win;
re = wins->Item(CComVariant(CComBSTR(EnvDTE::vsWindowKindOutput)),&win);
if (FAILED(re) || win == NULL)
return FALSE;
CComPtr<IDispatch> spOutputWindowDisp;
re = win->get_Object(&spOutputWindowDisp);
if (FAILED(re) || spOutputWindowDisp == NULL)
return FALSE;
CComQIPtr<EnvDTE::OutputWindow> spOutputWindow = spOutputWindowDisp;
if (spOutputWindow == NULL)
return FALSE;
CComPtr<EnvDTE::OutputWindowPanes> spOutputWindowPanes;
re = spOutputWindow->get_OutputWindowPanes(&spOutputWindowPanes);
if (FAILED(re) || spOutputWindowPanes == NULL)
return FALSE;
//first we should find if the out put window has exits
long wincount = 0;
BOOL IfNeedCreate = TRUE;
spOutputWindowPanes->get_Count(&wincount);
CComPtr<EnvDTE::OutputWindowPane> pan = NULL;
if(wincount>0)
{
for(long i = 1;i<=wincount;i++)
{
CComVariant var(i);
CComPtr<EnvDTE::OutputWindowPane> Pane;
spOutputWindowPanes->Item(var,&Pane);
BSTR paneName;
Pane->get_Name(&paneName);
_bstr_t fileNameWapper(paneName,false);
if(fileNameWapper==_bstr_t(CComBSTR(OUTPUT_WINDOW_NAME),false))
{
IfNeedCreate = FALSE;
pan = Pane;
break;
}
}
}
if(IfNeedCreate==TRUE)
{
CComPtr<EnvDTE::OutputWindowPane> spOutputWindowPane;
re = spOutputWindowPanes->Add(CComBSTR(OUTPUT_WINDOW_NAME), &spOutputWindowPane);
if (FAILED(re) || spOutputWindowPane == NULL)
return FALSE;
}
else
{
pan->Clear();
}
return TRUE;
}