⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bcgpoutlineparser.cpp

📁 远程网络监视程序的源码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
	m_strOut.Empty ();

	CList <Lexeme, Lexeme&> lstStack;
	Lexeme lexemStackTop (0, LT_Eps, 0, 0);
	lstStack.AddTail (lexemStackTop);

	int nOffset	= nStartOffset;

	while (nOffset <= nEndOffset)
	{
		// Get next lexem:
		Lexeme lexemNext = GetNext (strBuffer, nOffset, nEndOffset);
		Lexeme lexemTop = lstStack.GetTail ();

		if (lexemNext.m_nType == LT_EndOfText)
		{
			break;
		}

		// Parser logic:
		switch (lexemNext.m_nType)
		{
		case LT_BlockStart:
			lstStack.AddTail (lexemNext);
			break;
		case LT_BlockEnd:
			if (lexemTop.m_nType == LT_BlockStart &&
				lexemTop.m_nBlockType == lexemNext.m_nBlockType)
			{
				// Push Block:
				lstStack.RemoveTail ();
				Lexeme lexemRes (lexemTop.m_nBlockType, LT_CompleteBlock, lexemTop.m_nStart, lexemNext.m_nEnd);
				PushResult (lexemRes, lstResults);
			}
			else
			{
				lstStack.AddTail (lexemNext);
			}
			break;
		case LT_CompleteBlock:
			{
				// Push Comment:
				PushResult (lexemNext, lstResults);
			}
			break;
		}
	}
	
	// Finish parsing:
	while (!lstStack.IsEmpty ())
	{
		Lexeme lexem = lstStack.RemoveTail ();
		PushResult (lexem, lstResults);
	}
}
//************************************************************************************
static void CalcMinMaxBounds (const CObList& lst, int& nMin, int& nMax)
{
	for (POSITION pos = lst.GetHeadPosition (); pos != NULL; )
	{
		CBCGPOutlineBaseNode* pNode = (CBCGPOutlineBaseNode*) lst.GetNext (pos);
		ASSERT_VALID (pNode);

		if (pNode->m_nStart < nMin)
		{
			nMin = pNode->m_nStart;
		}
		if (pNode->m_nEnd > nMax)
		{
			nMax = pNode->m_nEnd;
		}
	}
}
//************************************************************************************
void CBCGPOutlineParser::UpdateOutlining (CString& strBuffer, int nOffsetFrom, int nCharsCount,
							  CBCGPOutlineNode* pOutlineNode, BCGP_EDIT_OUTLINE_CHANGES& changes)
{
	ASSERT_VALID (this);
	ASSERT (nOffsetFrom >= 0);
	ASSERT (nCharsCount >= 0);
	ASSERT (nOffsetFrom + nCharsCount <= strBuffer.GetLength ());
	ASSERT_VALID (pOutlineNode);

	int nStartOffset = nOffsetFrom;
	int nEndOffset = nOffsetFrom + nCharsCount - 1;
	CBCGPOutlineNode* pChangedNode = GetRangeToReparse (pOutlineNode, nStartOffset, nEndOffset);
	nStartOffset = max (0, nStartOffset);
	nEndOffset = min (strBuffer.GetLength () - 1, nEndOffset);

	if (nStartOffset > nEndOffset)
	{
		return;	// no reparse needed
	}

	changes.m_nStartOffset = min (nStartOffset, changes.m_nStartOffset);
	changes.m_nEndOffset = max (nEndOffset, changes.m_nEndOffset);

	// --------------------------------------------------------------
	// 1) Parse text and find new blocks and part of blocks (markers)
	// --------------------------------------------------------------
	CObList lstBlocks;
	DoParse (strBuffer, nStartOffset, nEndOffset, lstBlocks);

		// ----------------------------------------------------------
		// Reparse text once more
		// if parser found blocks that are greater then parsing range 
		// ----------------------------------------------------------
		int nMin = nStartOffset, nMax = nEndOffset;
		CalcMinMaxBounds (lstBlocks, nMin, nMax);

		if (nMin < nStartOffset || nMax > nEndOffset)
		{
			nStartOffset = min (nMin, nStartOffset);
			nEndOffset = max (nMax, nEndOffset);

			pChangedNode = GetRangeToReparse (pOutlineNode, nStartOffset, nEndOffset);
			nStartOffset = max (0, nStartOffset);
			nEndOffset = min (strBuffer.GetLength () - 1, nEndOffset);

			changes.m_nStartOffset = min (nStartOffset, changes.m_nStartOffset);
			changes.m_nEndOffset = max (nEndOffset, changes.m_nEndOffset);

			while (!lstBlocks.IsEmpty ())
			{
				delete lstBlocks.RemoveTail ();
			}
			DoParse (strBuffer, nStartOffset, nEndOffset, lstBlocks);
		}

	// Update name offsets, start offsets and end offsets:
	DoUpdateOffsets (strBuffer, nStartOffset, nEndOffset, lstBlocks);

	// ------------------------
	// Reconstruct outline tree
	// ------------------------

	// 2) Del old blocks
	pOutlineNode->DeleteBlocksInRange (nStartOffset, nEndOffset, changes); // do not remove user blocks

	for (POSITION pos = lstBlocks.GetHeadPosition (); pos != NULL; )
	{
		POSITION posSave = pos;
		CBCGPOutlineNode* pNode = (CBCGPOutlineNode*) lstBlocks.GetNext (pos);
		ASSERT_VALID (pNode);

		BlockType* pBlockType = m_arrBlockTypes [pNode->m_nBlockType];
		if (pBlockType != NULL && !pBlockType->m_bIgnore)
		{
			if ((pNode->m_dwFlags & g_dwOBFComplete) != 0)
			{
				// 3) Add new blocks
				AddNode (pNode, pOutlineNode, changes);
			}
			else if ((pNode->m_dwFlags & g_dwOBFLeft) != 0 ||
					 (pNode->m_dwFlags & g_dwOBFRight) != 0)
			{
				// it's possible that pChangedNode was removed from outline tree
				POSITION posChangedNode = changes.m_lstRemoved.Find (pChangedNode);
				if (posChangedNode != NULL)
				{
					if ((pNode->m_dwFlags & g_dwOBFLeft) != 0)
					{
						pChangedNode = pOutlineNode->FindCollapsedBlock (pNode->m_nStart);
					}
					else if ((pNode->m_dwFlags & g_dwOBFRight) != 0)
					{
						pChangedNode = pOutlineNode->FindCollapsedBlock (pNode->m_nEnd);
					}
					if (pChangedNode == NULL)
					{
						pChangedNode = pOutlineNode;
					}
				}

				ASSERT_VALID (pChangedNode);

				// 4) Reconstruct outline tree (add new markers)
				if (!AddMarker (pNode, pChangedNode, changes))
				{
					lstBlocks.RemoveAt (posSave);
					delete pNode;	// to prevent memory leak
				}
			}
		}
		else
		{
			// delete temporary blocks:
			lstBlocks.RemoveAt (posSave);
			delete pNode;
		}
	}
}
//************************************************************************************
CBCGPOutlineNode* CBCGPOutlineParser::GetRangeToReparse (CBCGPOutlineNode* pOutlineNode,
														int& nStartOffset, int& nEndOffset) const
{
	ASSERT_VALID (pOutlineNode);
	
	// --------------------------------------
	// Enlarge to start close string lengths:
	// --------------------------------------
	int nMaxBlockOpenStrLen = 1;
	int nMaxBlockCloseStrLen = 1;
	for (int i = 0; i <= m_arrBlockTypes.GetUpperBound (); i++)
	{
		BlockType* pBlockType = m_arrBlockTypes [i];
		ASSERT (pBlockType != NULL);

		if (pBlockType->m_strOpen.GetLength () > nMaxBlockOpenStrLen)
		{
			nMaxBlockOpenStrLen = pBlockType->m_strOpen.GetLength ();
		}
		if (pBlockType->m_strClose.GetLength () > nMaxBlockCloseStrLen)
		{
			nMaxBlockCloseStrLen = pBlockType->m_strClose.GetLength ();
		}
	}
	nStartOffset -= nMaxBlockOpenStrLen - 1;
	nEndOffset += nMaxBlockCloseStrLen - 1;

	// ----------------------
	// Enlarge to block size:
	// ----------------------
	CBCGPOutlineNode* pParentNode = pOutlineNode;
	CBCGPOutlineNode* pNode = NULL;
	POSITION pos = pParentNode->GetNodes ()->GetHeadPosition ();

	// By offset:
	if (nStartOffset > nEndOffset) // no range - use nStartOffset:
	{
		pParentNode = pOutlineNode->GetInnermostBlock (nStartOffset);

		// Ensure the block it's not user block:
		while (pParentNode != NULL && pParentNode != pOutlineNode && 
			   pParentNode->m_nBlockType < 0)
		{
			pParentNode = pParentNode->GetParentNode ();
		}

		if (pParentNode != NULL && pParentNode != pOutlineNode)
		{
			nStartOffset = pParentNode->m_nStart - pParentNode->m_nNameOffset;
			nEndOffset = pParentNode->m_nEnd;
			return pParentNode;
		}
		else
		{
			return pOutlineNode;
		}
	}

	// By range:
	while (pos != NULL)
	{
		pNode = (CBCGPOutlineNode*) pParentNode->GetNodes ()->GetNext (pos);
		ASSERT_VALID (pNode);

		CBCGPOutlineBaseNode::CBCGPEditOutlineRange range = 
			pNode->IsInRangeByOffset (nStartOffset, nEndOffset);
		if (range == FULL_IN_RANGE ||
			(pNode->m_nStart - pNode->m_nNameOffset >= nStartOffset && 
			 pNode->m_nStart - pNode->m_nNameOffset <= nEndOffset))
		{
			// full in range 
			// or left side in range - enlarge nEndOffset:
			nStartOffset = min (nStartOffset, pNode->m_nStart - pNode->m_nNameOffset);
			nEndOffset = max (nEndOffset, pNode->m_nEnd);
		}
		else if (range == PARTIAL_IN_RANGE)
		{
			if (pNode->m_nEnd >= nStartOffset && 
				pNode->m_nEnd <= nEndOffset)
			{
				// right side in range - enlarge nStartOffset:
				nStartOffset = min (nStartOffset, pNode->m_nStart - pNode->m_nNameOffset);
				nEndOffset = max (nEndOffset, pNode->m_nEnd);
			}
			else
			{
				// middle in range - level down:
				pParentNode = pNode;
				pNode = NULL;
				pos = pParentNode->GetNodes ()->GetHeadPosition ();

				const BlockType* pBlockType = GetBlockType (pParentNode->m_nBlockType);
				if (pBlockType == NULL || !pBlockType->m_bAllowNestedBlocks)
				{
					nStartOffset = min (nStartOffset, pParentNode->m_nStart - pParentNode->m_nNameOffset);
					nEndOffset = max (nEndOffset, pParentNode->m_nEnd);
				}
			}
		}
	}

	if (pParentNode != NULL)
	{
		nStartOffset = min (nStartOffset, pParentNode->m_nStart - pParentNode->m_nNameOffset);
		nEndOffset = max (nEndOffset, pParentNode->m_nEnd);
	}
	return pParentNode;
}
//************************************************************************************
void CBCGPOutlineParser::DoUpdateOffsets (const CString& strBuffer, 
										  const int nStartOffset, const int nEndOffset, 
										  CObList& lstBlocks)
{
	// Update name offsets, start offsets and end offsets:
	CBCGPOutlineNode* pPreviousNode = NULL;
	CObList lstIgnoreBlocks;
	for (POSITION pos = lstBlocks.GetHeadPosition (); pos != NULL; )
	{
		CBCGPOutlineNode* pNode = (CBCGPOutlineNode*) lstBlocks.GetNext (pos);
		ASSERT_VALID (pNode);

		const BlockType* pBlockType = GetBlockType (pNode->m_nBlockType);
		if (pBlockType != NULL && !pBlockType->m_bIgnore)
		{
			// --------------------------------------
			// Update name offsets and start offsets:
			// --------------------------------------
			CString strName;
			int nSearchTo = nStartOffset;
			if (pPreviousNode != NULL && 
				pPreviousNode->m_nEnd < pNode->m_nStart &&
				pPreviousNode->m_nEnd > nStartOffset)
			{
				nSearchTo = pPreviousNode->m_nEnd;
			}
			pNode->m_nNameOffset = GetNameOffset (strBuffer, pNode->m_nStart, nSearchTo,
												  pBlockType, lstIgnoreBlocks, strName);
			int nNewStart = GetStartOffset (strBuffer, pNode->m_nStart, pNode->m_nStart - pNode->m_nNameOffset, lstIgnoreBlocks);
			ASSERT (nNewStart >= nSearchTo);

			int nDelta = nNewStart - pNode->m_nStart;
			pNode->m_nNameOffset += nDelta;
			pNode->m_nStart = nNewStart;
			// strName = strName.Left (strName.GetLength () + nDelta);
			// pNode->m_strName = strName;

			// -------------------
			// Update end offsets:
			// -------------------
			nSearchTo = nEndOffset;
			if (pos != NULL)
			{
				CBCGPOutlineNode* pNextNode = (CBCGPOutlineNode*) lstBlocks.GetAt (pos);
				ASSERT_VALID (pNextNode);

				if (pNextNode->m_nStart > pNode->m_nEnd &&
					pNextNode->m_nStart < nEndOffset)
				{
					nSearchTo = pNextNode->m_nStart;
				}
			}
			int nNewEnd = GetEndOffset (strBuffer, pNode->m_nEnd, nSearchTo);
			ASSERT (nNewEnd <= nSearchTo);
			pNode->m_nEnd = nNewEnd;

			pPreviousNode = pNode;
			lstIgnoreBlocks.AddTail (pNode);
		}
		else
		{
			lstIgnoreBlocks.AddTail (pNode);
		}
	}
}
//************************************************************************************
static BOOL IsInRange(CObList& lstIgnore, int nStart, int nEnd)
{
	for (POSITION pos = lstIgnore.GetTailPosition (); pos != NULL; )
	{
		CBCGPOutlineNode* pPrevNode = (CBCGPOutlineNode*) lstIgnore.GetPrev (pos);
		ASSERT_VALID (pPrevNode);

		if (pPrevNode->IsInRangeByOffset (nStart, nEnd) != NOT_IN_RANGE)
		{
			return TRUE;
		}
	}

	return FALSE;
}
//************************************************************************************
int CBCGPOutlineParser::GetNameOffset (const CString& strIn, int nStartFrom, int nSearchTo,

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -