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

📄 ccrystaltextview.cpp

📁 一个完整的编辑器的代码(很值得参考
💻 CPP
📖 第 1 页 / 共 5 页
字号:
}

void CCrystalTextView::
DrawLineHelper (CDC * pdc, CPoint & ptOrigin, const CRect & rcClip, int nColorIndex,
                LPCTSTR pszChars, int nOffset, int nCount, CPoint ptTextPos)
{
  if (nCount > 0)
    {
      if (m_bFocused || m_bShowInactiveSelection)
        {
          int nSelBegin = 0, nSelEnd = 0;
          if (m_ptDrawSelStart.y > ptTextPos.y)
            {
              nSelBegin = nCount;
            }
          else if (m_ptDrawSelStart.y == ptTextPos.y)
            {
              nSelBegin = m_ptDrawSelStart.x - ptTextPos.x;
              if (nSelBegin < 0)
                nSelBegin = 0;
              if (nSelBegin > nCount)
                nSelBegin = nCount;
            }
          if (m_ptDrawSelEnd.y > ptTextPos.y)
            {
              nSelEnd = nCount;
            }
          else if (m_ptDrawSelEnd.y == ptTextPos.y)
            {
              nSelEnd = m_ptDrawSelEnd.x - ptTextPos.x;
              if (nSelEnd < 0)
                nSelEnd = 0;
              if (nSelEnd > nCount)
                nSelEnd = nCount;
            }

          ASSERT (nSelBegin >= 0 && nSelBegin <= nCount);
          ASSERT (nSelEnd >= 0 && nSelEnd <= nCount);
          ASSERT (nSelBegin <= nSelEnd);

          //  Draw part of the text before selection
          if (nSelBegin > 0)
            {
              DrawLineHelperImpl (pdc, ptOrigin, rcClip, pszChars, nOffset, nSelBegin);
            }
          if (nSelBegin < nSelEnd)
            {
              COLORREF crOldBk = pdc->SetBkColor (GetColor (COLORINDEX_SELBKGND));
              COLORREF crOldText = pdc->SetTextColor (GetColor (COLORINDEX_SELTEXT));
              DrawLineHelperImpl (pdc, ptOrigin, rcClip, pszChars, nOffset + nSelBegin, nSelEnd - nSelBegin);
              pdc->SetBkColor (crOldBk);
              pdc->SetTextColor (crOldText);
            }
          if (nSelEnd < nCount)
            {
              DrawLineHelperImpl (pdc, ptOrigin, rcClip, pszChars, nOffset + nSelEnd, nCount - nSelEnd);
            }
        }
      else
        {
          DrawLineHelperImpl (pdc, ptOrigin, rcClip, pszChars, nOffset, nCount);
        }
    }
}

void CCrystalTextView::
GetLineColors (int nLineIndex, COLORREF & crBkgnd,
               COLORREF & crText, BOOL & bDrawWhitespace)
{
  DWORD dwLineFlags = GetLineFlags (nLineIndex);
  bDrawWhitespace = TRUE;
  crText = RGB (255, 255, 255);
  if (dwLineFlags & LF_EXECUTION)
    {
      crBkgnd = RGB (0, 128, 0);
      return;
    }
  if (dwLineFlags & LF_BREAKPOINT)
    {
      crBkgnd = RGB (255, 0, 0);
      return;
    }
  if (dwLineFlags & LF_INVALID_BREAKPOINT)
    {
      crBkgnd = RGB (128, 128, 0);
      return;
    }
  crBkgnd = CLR_NONE;
  crText = CLR_NONE;
  bDrawWhitespace = FALSE;
}

DWORD CCrystalTextView::
GetParseCookie (int nLineIndex)
{
  int nLineCount = GetLineCount ();
  if (m_pdwParseCookies == NULL)
    {
      m_nParseArraySize = nLineCount;
      m_pdwParseCookies = new DWORD[nLineCount];
      memset (m_pdwParseCookies, 0xff, nLineCount * sizeof (DWORD));
    }

  if (nLineIndex < 0)
    return 0;
  if (m_pdwParseCookies[nLineIndex] != (DWORD) - 1)
    return m_pdwParseCookies[nLineIndex];

  int L = nLineIndex;
  while (L >= 0 && m_pdwParseCookies[L] == (DWORD) - 1)
    L--;
  L++;

  int nBlocks;
  while (L <= nLineIndex)
    {
      DWORD dwCookie = 0;
      if (L > 0)
        dwCookie = m_pdwParseCookies[L - 1];
      ASSERT (dwCookie != (DWORD) - 1);
      m_pdwParseCookies[L] = ParseLine (dwCookie, L, NULL, nBlocks);
      ASSERT (m_pdwParseCookies[L] != (DWORD) - 1);
      L++;
    }

  return m_pdwParseCookies[nLineIndex];
}

//BEGIN SW
void CCrystalTextView::WrapLine( int nLineIndex, int nMaxLineWidth, int *anBreaks, int &nBreaks )
{
	// There must be a parser attached to this view
	if( !m_pParser )
		return;

	m_pParser->WrapLine( nLineIndex, nMaxLineWidth, anBreaks, nBreaks );
}


void CCrystalTextView::WrapLineCached( 
										int nLineIndex, int nMaxLineWidth, int *anBreaks, int &nBreaks )
{
	// if word wrap is not active, there is not any break in the line
	if( !m_bWordWrap )
	{
		nBreaks = 0;
		return;
	}

	// word wrap is active
	if( nLineIndex < m_panSubLines->GetSize() && !anBreaks && (*m_panSubLines)[nLineIndex] > -1 )
		// return cached data
		nBreaks = (*m_panSubLines)[nLineIndex] - 1;
	else
	{
		// recompute line wrap
		nBreaks = 0;
		WrapLine( nLineIndex, nMaxLineWidth, anBreaks, nBreaks );

		// cache data
		ASSERT( nBreaks > -1 );
		m_panSubLines->SetAtGrow( nLineIndex, nBreaks + 1 );

		// RecalcVertScrollBar();
	}
}


void CCrystalTextView::InvalidateLineCache( int nLineIndex1, int nLineIndex2 /*= -1*/ )
{
	// invalidate cached sub line count

	if( nLineIndex2 == -1 && nLineIndex1 < m_panSubLines->GetSize() )
		for( int i = nLineIndex1; i < m_panSubLines->GetSize(); i++ )
			(*m_panSubLines)[i] = -1;
	else
	{
		if( nLineIndex1 > nLineIndex2 )
		{
			int	nStorage = nLineIndex1;
			nLineIndex1 = nLineIndex2;
			nLineIndex2 = nStorage;
		}

		if( nLineIndex1 >= m_panSubLines->GetSize() )
			return;

		if( nLineIndex2 >= m_panSubLines->GetSize() )
			nLineIndex2 = m_panSubLines->GetUpperBound();

		for( int i = nLineIndex1; i <= nLineIndex2; i++ )
			if( i >= 0 && i < m_panSubLines->GetSize() )
				(*m_panSubLines)[i] = -1;
	}
}


void CCrystalTextView::DrawScreenLine( CDC *pdc, CPoint &ptOrigin, const CRect &rcClip,
																			TEXTBLOCK *pBuf, int nBlocks, int &nActualItem, 
																			COLORREF crText, COLORREF crBkgnd, BOOL bDrawWhitespace,
																			LPCTSTR pszChars, 
																			int nOffset, int nCount, CPoint ptTextPos )
{
	CPoint	originalOrigin = ptOrigin;
	CRect		frect = rcClip;
	int			nLength = GetLineLength( ptTextPos.y );

	frect.top = ptOrigin.y;
	frect.bottom = frect.top + GetLineHeight();

	ASSERT( nActualItem < nBlocks );

	if (crText == CLR_NONE)
		pdc->SetTextColor(GetColor(pBuf[nActualItem].m_nColorIndex));
	pdc->SelectObject(
		GetFont(GetItalic(pBuf[nActualItem].m_nColorIndex), 
		GetBold(pBuf[nActualItem].m_nColorIndex)));

	if( nBlocks > 0 && nActualItem < nBlocks - 1 && 
		pBuf[nActualItem + 1].m_nCharPos >= nOffset && 
		pBuf[nActualItem + 1].m_nCharPos <= nOffset + nCount )
	{
		ASSERT(pBuf[nActualItem].m_nCharPos >= 0 && pBuf[nActualItem].m_nCharPos <= nLength);

		/*
		pdc->SelectObject(GetFont(GetItalic(COLORINDEX_NORMALTEXT), GetBold(COLORINDEX_NORMALTEXT)));
		DrawLineHelper(
			pdc, ptOrigin, rcClip, pBuf[nActualItem].m_nColorIndex, pszChars, 
			nOffset, pBuf[nActualItem].m_nCharPos, ptTextPos);
		*/
		for (int I = nActualItem; I < nBlocks - 1 && pBuf[I + 1].m_nCharPos <= nOffset + nCount; I ++)
		{
			ASSERT(pBuf[I].m_nCharPos >= 0 && pBuf[I].m_nCharPos <= nLength);
			if (crText == CLR_NONE)
				pdc->SetTextColor(GetColor(pBuf[I].m_nColorIndex));

			pdc->SelectObject(GetFont(GetItalic(pBuf[I].m_nColorIndex), GetBold(pBuf[I].m_nColorIndex)));

			int nOffsetToUse = (nOffset > pBuf[I].m_nCharPos)? nOffset : pBuf[I].m_nCharPos;
			DrawLineHelper(pdc, ptOrigin, rcClip, pBuf[I].m_nColorIndex, pszChars,
					(nOffset > pBuf[I].m_nCharPos)? nOffset : pBuf[I].m_nCharPos, 
					pBuf[I + 1].m_nCharPos - nOffsetToUse,
					CPoint( nOffsetToUse, ptTextPos.y ));
		}

		nActualItem = I;

		ASSERT(pBuf[nActualItem].m_nCharPos >= 0 && pBuf[nActualItem].m_nCharPos <= nLength);
		if (crText == CLR_NONE)
			pdc->SetTextColor(GetColor(pBuf[nActualItem].m_nColorIndex));

		pdc->SelectObject(GetFont(GetItalic(pBuf[nActualItem].m_nColorIndex),
							GetBold(pBuf[nActualItem].m_nColorIndex)));
		DrawLineHelper(pdc, ptOrigin, rcClip, pBuf[nActualItem].m_nColorIndex, pszChars,
							pBuf[nActualItem].m_nCharPos, nOffset + nCount - pBuf[nActualItem].m_nCharPos,
							CPoint(pBuf[nActualItem].m_nCharPos, ptTextPos.y));
	}
	else
	{
		DrawLineHelper(
			pdc, ptOrigin, rcClip, pBuf[nActualItem].m_nColorIndex, 
			pszChars, nOffset, nCount, ptTextPos);
	}

	// Draw space on the right of the text
	if (ptOrigin.x > frect.left)
		frect.left = ptOrigin.x;
	if (frect.right > frect.left)
	{
		if ((m_bFocused || m_bShowInactiveSelection) 
			&& IsInsideSelBlock(CPoint(GetLineLength( ptTextPos.y ), ptTextPos.y)) 
			&& (nOffset + nCount) == GetLineLength( ptTextPos.y ) )
		{
			pdc->FillSolidRect(frect.left, frect.top, GetCharWidth(), frect.Height(),
												GetColor(COLORINDEX_SELBKGND));
			frect.left += GetCharWidth();
		}
		if (frect.right > frect.left)
			pdc->FillSolidRect(frect, bDrawWhitespace ? crBkgnd : GetColor(COLORINDEX_WHITESPACE));
	}

	// set origin to beginning of next screen line
	ptOrigin.x = originalOrigin.x;
	ptOrigin.y+= GetLineHeight();
}
//END SW

void CCrystalTextView::
DrawSingleLine (CDC * pdc, const CRect & rc, int nLineIndex)
{
  ASSERT (nLineIndex >= -1 && nLineIndex < GetLineCount ());

  if (nLineIndex == -1)
    {
      //  Draw line beyond the text
      pdc->FillSolidRect (rc, GetColor (COLORINDEX_WHITESPACE));
      return;
    }

  //  Acquire the background color for the current line
  BOOL bDrawWhitespace = FALSE;
  COLORREF crBkgnd, crText;
  GetLineColors (nLineIndex, crBkgnd, crText, bDrawWhitespace);
  if (crBkgnd == CLR_NONE)
    crBkgnd = GetColor (COLORINDEX_BKGND);

  int nLength = GetLineLength (nLineIndex);
  if (nLength == 0)
    {
      //  Draw the empty line
      CRect rect = rc;
      if ((m_bFocused || m_bShowInactiveSelection) && IsInsideSelBlock (CPoint (0, nLineIndex)))
        {
          pdc->FillSolidRect (rect.left, rect.top, GetCharWidth (), rect.Height (), GetColor (COLORINDEX_SELBKGND));
          rect.left += GetCharWidth ();
        }
      pdc->FillSolidRect (rect, bDrawWhitespace ? crBkgnd : GetColor (COLORINDEX_WHITESPACE));
      return;
    }

  //  Parse the line
  LPCTSTR pszChars = GetLineChars (nLineIndex);
  DWORD dwCookie = GetParseCookie (nLineIndex - 1);
  TEXTBLOCK *pBuf = (TEXTBLOCK *) _alloca (sizeof (TEXTBLOCK) * nLength * 3);
  int nBlocks = 0;
	//BEGIN SW
	// insert at least one textblock of normal color at the beginning
	pBuf[0].m_nCharPos = 0;
	pBuf[0].m_nColorIndex = COLORINDEX_NORMALTEXT;
	nBlocks++;
	//END SW
  m_pdwParseCookies[nLineIndex] = ParseLine (dwCookie, nLineIndex, pBuf, nBlocks);
  ASSERT (m_pdwParseCookies[nLineIndex] != (DWORD) - 1);

	//BEGIN SW
	int nActualItem = 0;

	// Wrap the line
	int *anBreaks = (int*)_alloca( sizeof( int ) * nLength );
	int	nBreaks = 0;

	WrapLineCached( nLineIndex, GetScreenChars(), anBreaks, nBreaks );
	//END SW

  //  Draw the line text
  CPoint origin (rc.left - m_nOffsetChar * GetCharWidth (), rc.top);
  pdc->SetBkColor (crBkgnd);
  if (crText != CLR_NONE)
    pdc->SetTextColor (crText);
	BOOL bColorSet = FALSE;

	//BEGIN SW
	/*ORIGINAL
	if (nBlocks > 0)
	{
		ASSERT(pBuf[0].m_nCharPos >= 0 && pBuf[0].m_nCharPos <= nLength);
		if (crText == CLR_NONE)
			pdc->SetTextColor(GetColor(COLORINDEX_NORMALTEXT));
		pdc->SelectObject(GetFont(GetItalic(COLORINDEX_NORMALTEXT), GetBold(COLORINDEX_NORMALTEXT)));
		DrawLineHelper(pdc, origin, rc, COLORINDEX_NORMALTEXT, pszChars, 0, pBuf[0].m_nCharPos, CPoint(0, nLineIndex));
		for (int I = 0; I < nBlocks - 1; I ++)
		{
			ASSERT(pBuf[I].m_nCharPos >= 0 && pBuf[I].m_nCharPos <= nLength);
			if (crText == CLR_NONE)
				pdc->SetTextColor(GetColor(pBuf[I].m_nColorIndex));
			pdc->SelectObject(GetFont(GetItalic(pBuf[I].m_nColorIndex), GetBold(pBuf[I].m_nColorIndex)));
			DrawLineHelper(pdc, origin, rc, pBuf[I].m_nColorIndex, pszChars,
							pBuf[I].m_nCharPos, pBuf[I + 1].m_nCharPos - pBuf[I].m_nCharPos,
							CPoint(pBuf[I].m_nCharPos, nLineIndex));
		}
		ASSERT(pBuf[nBlocks - 1].m_nCharPos >= 0 && pBuf[nBlocks - 1].m_nCharPos <= nLength);
		if (crText == CLR_NONE)
			pdc->SetTextColor(GetColor(pBuf[nBlocks - 1].m_nColorIndex));
		pdc->SelectObject(GetFont(GetItalic(pBuf[nBlocks - 1].m_nColorIndex),
							GetBold(pBuf[nBlocks - 1].m_nColorIndex)));
		DrawLineHelper(pdc, origin, rc, pBuf[nBlocks - 1].m_nColorIndex, pszChars,
							pBuf[nBlocks - 1].m_nCharPos, nLength - pBuf[nBlocks - 1].m_nCharPos,
							CPoint(pBuf[nBlocks - 1].m_nCharPos, nLineIndex));
	}
	else
	*/
	//END SW

	// BEGIN SW
	if( nBreaks > 0 )
	{
		// Draw all the screen lines of the wrapped line
		ASSERT( anBreaks[0] < nLength );
		
		// draw start of line to first break
		DrawScreenLine(
			pdc, origin, rc,
			pBuf, nBlocks, nActualItem,
			crText, crBkgnd, bDrawWhitespace,
			pszChars, 0, anBreaks[0], CPoint( 0, nLineIndex ) );
		
		// draw from first break to last break
		for( int i = 0; i < nBreaks - 1; i++ )
		{
			ASSERT( anBreaks[i] >= 0 && anBreaks[i] < nLength );
			DrawScreenLine(
				pdc, origin, rc,
				pBuf, nBlocks, nActualItem,
				crText, crBkgnd, bDrawWhitespace,
				pszChars, anBreaks[i], anBreaks[i + 1] - anBreaks[i],
				CPoint( anBreaks[i], nLineIndex ) );
		}
		
		// draw from last break till end of line
		DrawScreenLine(
			pdc, origin, rc,
			pBuf, nBlocks, nActualItem,
			crText, crBkgnd, bDrawWhitespace,
			pszChars, anBreaks[i], nLength - anBreaks[i],
			CPoint( anBreaks[i], nLineIndex ) );

⌨️ 快捷键说明

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