📄 ccrystaltextview.cpp
字号:
}
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 + -