📄 bcgpoutlineparser.cpp
字号:
const BlockType* pBlockType, CObList& lstIgnore,
CString& strName)
{
ASSERT (nStartFrom >= 0);
ASSERT (nSearchTo >= 0);
ASSERT (pBlockType != NULL);
int nOffset = nStartFrom - 1;
const int nCharsMaxNum = 256;
nSearchTo = max (nSearchTo, nStartFrom - nCharsMaxNum);
LPCTSTR lpszDelimiters = _T(";{}");
const CStringList* pListKeywords = &(pBlockType->m_lstKeywords);
ASSERT_VALID (pListKeywords);
while (nOffset >= nSearchTo)
{
CString strWord;
nOffset = GetPrevWord (strIn, nOffset, nSearchTo, lpszDelimiters, strWord);
if (nOffset >= nSearchTo &&
!IsInRange (lstIgnore, nOffset, nOffset + strWord.GetLength ()))
{
// Compare strWord with keywords
if (pListKeywords->Find (strWord) != NULL)
{
strName = strWord;
return nStartFrom - nOffset;
}
else if (IsBlockName (strIn, strWord, nOffset, nStartFrom))
{
strName = strWord;
return nStartFrom - nOffset;
}
}
nOffset--;
}
strName = _T("");
return 0;
}
//************************************************************************************
int CBCGPOutlineParser::GetPrevWord (const CString& strIn, int nStartFrom,
int nSearchTo, LPCTSTR lpszStopDelimiters, CString& strWord)
{
ASSERT (nStartFrom >= 0);
ASSERT (nStartFrom < strIn.GetLength ());
ASSERT (nSearchTo >= 0);
ASSERT (lpszStopDelimiters != NULL);
CString strStopDelimiters = lpszStopDelimiters;
CString strWordDelimeters = _T(" \t\n,./?><;:\"'{[}]~`%^&*()-+=!");
// -------------------------------------------------------------------
// Reverse search for a word till nSearchTo or one of spec delimiters:
// -------------------------------------------------------------------
strWord.Empty ();
int i = nStartFrom;
if (i >= nSearchTo &&
strWordDelimeters.Find (strIn [i]) != -1)
{
// Inside delimiters - move to end of delimiters string:
for (; i >= nSearchTo; i--)
{
TCHAR chNext = strIn.GetAt (i);
if (strStopDelimiters.Find (chNext) != -1)
{
return -1;
}
if (strWordDelimeters.Find (chNext) == -1)
{
break;
}
}
}
if (i >= nSearchTo &&
strWordDelimeters.Find (strIn [i]) == -1)
{
// Inside word - move to end of word:
int iWordEnd = i;
for (; i >= nSearchTo; i--)
{
TCHAR chNext = strIn.GetAt (i);
if (strStopDelimiters.Find (chNext) != -1)
{
break;
}
if (strWordDelimeters.Find (chNext) != -1)
{
break;
}
}
if (i < iWordEnd)
{
strWord = strIn.Mid (i + 1, iWordEnd - i);
return i + 1;
}
}
return -1;
}
//************************************************************************************
BOOL CBCGPOutlineParser::IsBlockName (const CString& strIn, CString& strWord, const int nOffset, const int nSearchTo)
{
ASSERT (nOffset >= 0);
ASSERT (nSearchTo >=0);
CString strDelimeters = _T(" \t\n");
int const nWordLength = strWord.GetLength ();
// skip delimiters:
int i = nOffset + nWordLength;
int iMax = min (nSearchTo, strIn.GetLength ());
while (i < iMax && strDelimeters.Find (strIn [i]) >= 0)
{
i++;
}
if (strIn [i] == _T('('))
{
strWord += strIn.Mid (i, iMax - i);
return TRUE;
}
return FALSE;
}
//************************************************************************************
int CBCGPOutlineParser::GetStartOffset (const CString& strIn, int nStartFrom, int nSearchTo, CObList& lstIgnore)
{
ASSERT (nStartFrom >= 0);
ASSERT (nSearchTo >= 0);
CString strDelimeters = _T(" \t\n");
int i = nStartFrom;
while (i > nSearchTo)
{
i--;
if (strDelimeters.Find (strIn[i]) == -1 &&
!IsInRange (lstIgnore, i, i))
{
nStartFrom = i + 1;
break;
}
}
return nStartFrom;
}
//************************************************************************************
int CBCGPOutlineParser::GetEndOffset (const CString& strIn, int nStartFrom, int nSearchTo)
{
return nStartFrom;
}
//************************************************************************************
BOOL CBCGPOutlineParser::AddMarker (CBCGPOutlineNode* pMarkerBlock, CBCGPOutlineNode* pParentNode,
BCGP_EDIT_OUTLINE_CHANGES& changes) const
{
ASSERT_VALID (pMarkerBlock);
ASSERT_VALID (pParentNode);
ASSERT ((pMarkerBlock->m_dwFlags & g_dwOBFLeft) != 0 ||
(pMarkerBlock->m_dwFlags & g_dwOBFRight) != 0);
// ---------------------------------------
// Search for marker fitting for this one:
// ---------------------------------------
CBCGPOutlineNode* pComposeWith = FindFittingBlock (pMarkerBlock, pParentNode);
if (pComposeWith != NULL)
{
ASSERT_VALID (pComposeWith);
// ---------------------------------------------------------
// Combine new marker with existed block or with pair marker
// ---------------------------------------------------------
CBCGPOutlineBaseNode* pLeft = NULL;
CBCGPOutlineBaseNode* pRight = NULL;
if ((pMarkerBlock->m_dwFlags & g_dwOBFLeft) != 0)
{
ASSERT ((pComposeWith->m_dwFlags & g_dwOBFComplete) != 0 ||
(pComposeWith->m_dwFlags & g_dwOBFRight) != 0);
pLeft = pMarkerBlock;
pRight = pComposeWith;
}
else if ((pMarkerBlock->m_dwFlags & g_dwOBFRight) != 0)
{
ASSERT ((pComposeWith->m_dwFlags & g_dwOBFComplete) != 0 ||
(pComposeWith->m_dwFlags & g_dwOBFLeft) != 0);
pLeft = pComposeWith;
pRight = pMarkerBlock;
}
else
{
ASSERT (FALSE);
return FALSE;
}
CBCGPOutlineNode* pParent = pComposeWith->GetParentNode ();
ASSERT_VALID (pParent);
if (pLeft != NULL && pRight != NULL)
{
ASSERT (pLeft->m_nStart < pRight->m_nEnd);
ASSERT (pLeft->m_strReplace == pRight->m_strReplace);
// ---------------
// Make new block:
// ---------------
RemoveNode (pComposeWith, pParent, changes);
CBCGPOutlineNode* pNewBlock = new CBCGPOutlineNode (*pLeft);
pNewBlock->m_dwFlags &= ~g_dwOBFLeft;
pNewBlock->m_dwFlags |= g_dwOBFComplete;
pNewBlock->m_bCollapsed = FALSE;
pNewBlock->m_nEnd = pRight->m_nEnd;
AddNode (pNewBlock, pParent, changes);
}
else
{
ASSERT (FALSE);
return FALSE;
}
if ((pComposeWith->m_dwFlags & g_dwOBFComplete) != 0)
{
// ----------------------------------------------------------------------
// The rest of old block contains start/close sequence - add it as marker
// ----------------------------------------------------------------------
CBCGPOutlineNode* pNewMarker = new CBCGPOutlineNode (*pComposeWith->GetValue ());
const BlockType* pBlockType = GetBlockType (pNewMarker->m_nBlockType);
if ((pMarkerBlock->m_dwFlags & g_dwOBFLeft) != 0)
{
// add start marker (g_dwOBFLeft):
const int nOpenStrLen = (pBlockType != NULL) ? pBlockType->m_strOpen.GetLength () : 1;
pNewMarker->m_dwFlags &= ~g_dwOBFComplete;
pNewMarker->m_dwFlags |= g_dwOBFLeft;
pNewMarker->m_bCollapsed = FALSE;
pNewMarker->m_nEnd = pNewMarker->m_nStart + nOpenStrLen - 1;
}
else if ((pMarkerBlock->m_dwFlags & g_dwOBFRight) != 0)
{
// add end marker (g_dwOBFRight):
const int nCloseStrLen = (pBlockType != NULL) ? pBlockType->m_strClose.GetLength () : 1;
pNewMarker->m_dwFlags &= ~g_dwOBFComplete;
pNewMarker->m_dwFlags |= g_dwOBFRight;
pNewMarker->m_bCollapsed = FALSE;
pNewMarker->m_nStart = pNewMarker->m_nEnd - nCloseStrLen - 1;
pNewMarker->DestroyData (); // end marker has no data
}
// Recursive call:
AddMarker (pNewMarker, pParent, changes);
}
// ------------------
// Delete old blocks:
// ------------------
delete pMarkerBlock;
}
else
{
// --------------------------------------------
// Add non-completed block (marker) in the root
// --------------------------------------------
CBCGPOutlineNode* pRoot = pParentNode;
while (pRoot->GetParentNode () != NULL)
{
ASSERT_VALID (pRoot);
pRoot = pParentNode->GetParentNode ();
}
AddNode (pMarkerBlock, pRoot, changes);
}
return TRUE;
}
//************************************************************************************
CBCGPOutlineNode* CBCGPOutlineParser::FindFittingBlock (CBCGPOutlineNode* pBlock, CBCGPOutlineNode* pParentNode) const
{
ASSERT_VALID (pBlock);
if ((pBlock->m_dwFlags & g_dwOBFComplete) != 0)
{
return NULL;
}
if (pParentNode == NULL)
{
return NULL;
}
ASSERT_VALID (pParentNode);
// ----------------------------------------------------------------------
// Search through the current level for the block fitting for this marker
// ----------------------------------------------------------------------
if ((pBlock->m_dwFlags & g_dwOBFLeft) != 0)
{
for (POSITION pos = pParentNode->GetNodes ()->GetHeadPosition (); pos != NULL;)
{
CBCGPOutlineNode* pNode = (CBCGPOutlineNode*) pParentNode->GetNodes ()->GetNext (pos);
ASSERT_VALID (pNode);
if (pNode->m_nBlockType == pBlock->m_nBlockType)
{
if ((pNode->m_dwFlags & g_dwOBFComplete) != 0 &&
pBlock->m_nEnd < pNode->m_nEnd &&
pBlock->m_nStart > pNode->m_nStart)
{
return pNode;
}
else if ((pNode->m_dwFlags & g_dwOBFRight) != 0 &&
pBlock->m_nStart < pNode->m_nStart)
{
return pNode;
}
}
}
// Recursive call:
return FindFittingBlock (pBlock, pParentNode->GetParentNode ());
}
else if ((pBlock->m_dwFlags & g_dwOBFRight) != 0)
{
for (POSITION pos = pParentNode->GetNodes ()->GetTailPosition (); pos != NULL;)
{
CBCGPOutlineNode* pNode = (CBCGPOutlineNode*) pParentNode->GetNodes ()->GetPrev (pos);
ASSERT_VALID (pNode);
if (pNode->m_nBlockType == pBlock->m_nBlockType)
{
if ((pNode->m_dwFlags & g_dwOBFComplete) != 0 &&
pBlock->m_nStart > pNode->m_nStart &&
pBlock->m_nEnd < pNode->m_nEnd)
{
return pNode;
}
else if ((pNode->m_dwFlags & g_dwOBFLeft) != 0 &&
pBlock->m_nStart > pNode->m_nStart)
{
return pNode;
}
}
}
// Recursive call:
return FindFittingBlock (pBlock, pParentNode->GetParentNode ());
}
return NULL;
}
CBCGPOutlineNode* CBCGPOutlineParser::AddNode (CBCGPOutlineNode* pNewNode, CBCGPOutlineNode* pParentNode,
BCGP_EDIT_OUTLINE_CHANGES& changes) const
{
ASSERT_VALID (pParentNode);
const BlockType* pBlockTypeDef = GetBlockType (pNewNode->m_nBlockType);
if (pBlockTypeDef != NULL && !pBlockTypeDef->m_bAllowNestedBlocks)
{
// Nested blocks are not allowed - delete nested blocks:
pParentNode->DeleteBlocksInRange (
pNewNode->m_nStart - pNewNode->m_nNameOffset,
pNewNode->m_nEnd, changes);
}
return pParentNode->AddNode (pNewNode, changes);
}
CBCGPOutlineNode* CBCGPOutlineParser::RemoveNode (CBCGPOutlineNode* pNode, CBCGPOutlineNode* pParentNode,
BCGP_EDIT_OUTLINE_CHANGES& changes,
BOOL bRemoveSubNodes) const
{
ASSERT_VALID (pNode);
ASSERT_VALID (pParentNode);
POSITION posNode = pParentNode->m_lstNodes.Find (pNode);
ASSERT (posNode != NULL);
return pParentNode->RemoveNode (posNode, changes, bRemoveSubNodes);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -