📄 ccrystaltextview.cpp
字号:
return;
int nLastLine= FindVisibleLine(nTopLine, nLines);
int nCount= nLastLine - nTopLine + 1;
m_vLineInsideBlock.resize(nCount);
// text block nesting depth
int nLevel= 0;
ASSERT(nTopLine >= 0);
int nLineFrom = nTopLine;
std::vector<bool>::iterator itInside= m_vLineInsideBlock.begin();
std::vector<bool>::iterator itEnd= m_vLineInsideBlock.end();
for (int nLine= nTopLine, nIndex= 0; nLines > 0; ++itInside)
{
DWORD dwFlags= m_pTextBuffer->GetLineFlags(nLine);
if (dwFlags & LF_COLLAPSIBLE_BLOCK_END)
--nLevel;
if (nLevel <= 0 && nLineFrom > 0)
{
// look outside (this is up); are we still inside a block?
int nLineIndex= nLineFrom - 1;
for (; nLineIndex >= 0; --nLineIndex)
{
DWORD dwFlags= m_pTextBuffer->GetLineFlags(nLineIndex);
if (dwFlags & LF_COLLAPSIBLE_BLOCK_END)
--nLevel;
if (dwFlags & LF_COLLAPSIBLE_BLOCK_START)
if (++nLevel > 0)
break;
}
nLineFrom = nLineIndex;
}
ASSERT(itInside < itEnd);
*itInside = nLevel > 0;
if (dwFlags & LF_COLLAPSIBLE_BLOCK_START)
++nLevel;
if (!IsLineHidden(nLine))
--nLines;
if (++nLine >= nLineCount)
break;
if (itInside == itEnd)
break;
}
std::fill(itInside, itEnd, false);
}
void CCrystalTextView::ResetView()
{
m_nTopLine = 0;
m_nOffsetChar = 0;
m_nLineHeight = -1;
m_nCharWidth = -1;
m_nTabSize = 4;
m_nMaxLineLength = -1;
m_nScreenLines = -1;
m_nScreenChars = -1;
m_nIdealCharPos = -1;
m_ptAnchor.x = 0;
m_ptAnchor.y = 0;
if (m_pIcons != NULL)
{
delete m_pIcons;
m_pIcons = NULL;
}
for (int I = 0; I < 4; I ++)
{
if (m_apFonts[I] != NULL)
{
m_apFonts[I]->DeleteObject();
delete m_apFonts[I];
m_apFonts[I] = NULL;
}
}
if (m_pdwParseCookies != NULL)
{
delete m_pdwParseCookies;
m_pdwParseCookies = NULL;
}
if (m_pnActualLineLength != NULL)
{
delete m_pnActualLineLength;
m_pnActualLineLength = NULL;
}
m_nParseArraySize = 0;
m_nActualLengthArraySize = 0;
m_ptCursorPos.x = 0;
m_ptCursorPos.y = 0;
m_ptSelStart = m_ptSelEnd = m_ptCursorPos;
m_bDragSelection = FALSE;
m_bVertScrollBarLocked = FALSE;
m_bHorzScrollBarLocked = FALSE;
if (::IsWindow(m_hWnd))
UpdateCaret();
m_bLastSearch = FALSE;
m_bShowInactiveSelection = FALSE;
m_bPrintHeader = FALSE;
m_bPrintFooter = TRUE;
m_bBookmarkExist = FALSE; // More bookmarks
m_bMultipleSearch = FALSE; // More search
}
void CCrystalTextView::UpdateCaret()
{
ASSERT_VALIDTEXTPOS(m_ptCursorPos);
if (m_bFocused && ! m_bCursorHidden &&
CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x) >= m_nOffsetChar)
{
CreateSolidCaret(2, GetLineHeight());
SetCaretPos(TextToClient(m_ptCursorPos));
ShowCaret();
}
else
{
HideCaret();
}
CaretMoved();
}
int CCrystalTextView::GetTabSize()
{
ASSERT(m_nTabSize >= 0 && m_nTabSize <= 64);
return m_nTabSize;
}
void CCrystalTextView::SetTabSize(int nTabSize)
{
ASSERT(nTabSize >= 0 && nTabSize <= 64);
if (m_nTabSize != nTabSize)
{
m_nTabSize = nTabSize;
if (m_pnActualLineLength != NULL)
{
delete m_pnActualLineLength;
m_pnActualLineLength = NULL;
}
m_nActualLengthArraySize = 0;
m_nMaxLineLength = -1;
RecalcHorzScrollBar();
Invalidate();
UpdateCaret();
}
}
CFont *CCrystalTextView::GetFont(BOOL bItalic /*= FALSE*/, BOOL bBold /*= FALSE*/)
{
int nIndex = 0;
if (bBold)
nIndex |= 1;
if (bItalic)
nIndex |= 2;
if (m_apFonts[nIndex] == NULL)
{
m_apFonts[nIndex] = new CFont;
m_lfBaseFont.lfWeight = bBold ? FW_BOLD : FW_NORMAL;
m_lfBaseFont.lfItalic = (BYTE) bItalic;
if (! m_apFonts[nIndex]->CreateFontIndirect(&m_lfBaseFont))
{
delete m_apFonts[nIndex];
m_apFonts[nIndex] = NULL;
return CView::GetFont();
}
}
return m_apFonts[nIndex];
}
void CCrystalTextView::CalcLineCharDim()
{
CDC *pdc = GetDC();
CFont *pOldFont = pdc->SelectObject(GetFont());
CSize szCharExt = pdc->GetTextExtent(_T("X"));
m_nLineHeight = szCharExt.cy;
if (m_nLineHeight < 1)
m_nLineHeight = 1;
m_nCharWidth = szCharExt.cx;
/*
TEXTMETRIC tm;
if (pdc->GetTextMetrics(&tm))
m_nCharWidth -= tm.tmOverhang;
*/
pdc->SelectObject(pOldFont);
ReleaseDC(pdc);
}
int CCrystalTextView::GetLineHeight()
{
if (m_nLineHeight == -1)
CalcLineCharDim();
return m_nLineHeight;
}
int CCrystalTextView::GetCharWidth()
{
if (m_nCharWidth == -1)
CalcLineCharDim();
return m_nCharWidth;
}
int CCrystalTextView::GetMaxLineLength()
{
if (m_nMaxLineLength == -1)
{
m_nMaxLineLength = 0;
int nLineCount = GetLineCount();
for (int I = 0; I < nLineCount; I ++)
{
int nActualLength = GetLineActualLength(I);
if (m_nMaxLineLength < nActualLength)
m_nMaxLineLength = nActualLength;
}
}
return m_nMaxLineLength;
}
CCrystalTextView *CCrystalTextView::GetSiblingView(int nRow, int nCol)
{
CSplitterWnd *pSplitter = GetParentSplitter(this, FALSE);
if (pSplitter == NULL)
return NULL;
CWnd *pWnd = CWnd::FromHandlePermanent(
::GetDlgItem(pSplitter->m_hWnd, pSplitter->IdFromRowCol(nRow, nCol)));
if (pWnd == NULL || ! pWnd->IsKindOf(RUNTIME_CLASS(CCrystalTextView)))
return NULL;
return (CCrystalTextView *) pWnd;
}
void CCrystalTextView::OnInitialUpdate()
{
CView::OnInitialUpdate();
AttachToBuffer(NULL);
CSplitterWnd *pSplitter = GetParentSplitter(this, FALSE);
if (pSplitter != NULL)
{
// See CSplitterWnd::IdFromRowCol() implementation
int nRow = (GetDlgCtrlID() - AFX_IDW_PANE_FIRST) / 16;
int nCol = (GetDlgCtrlID() - AFX_IDW_PANE_FIRST) % 16;
ASSERT(nRow >= 0 && nRow < pSplitter->GetRowCount());
ASSERT(nCol >= 0 && nCol < pSplitter->GetColumnCount());
if (nRow > 0)
{
CCrystalTextView *pSiblingView = GetSiblingView(0, nCol);
if (pSiblingView != NULL && pSiblingView != this)
{
m_nOffsetChar = pSiblingView->m_nOffsetChar;
ASSERT(m_nOffsetChar >= 0 && m_nOffsetChar <= GetMaxLineLength());
}
}
if (nCol > 0)
{
CCrystalTextView *pSiblingView = GetSiblingView(nRow, 0);
if (pSiblingView != NULL && pSiblingView != this)
{
m_nTopLine = pSiblingView->m_nTopLine;
ASSERT(m_nTopLine >= 0 && m_nTopLine < GetLineCount());
}
}
}
// MiK: parse all to update collapsible blocks
GetParseCookie(GetLineCount() - 1);
}
/////////////////////////////////////////////////////////////////////////////
// CCrystalTextView printing
void CCrystalTextView::OnPrepareDC(CDC* pDC, CPrintInfo* pInfo)
{
CView::OnPrepareDC(pDC, pInfo);
if (pInfo != NULL)
{
pInfo->m_bContinuePrinting = TRUE;
if (m_pnPages != NULL && (int) pInfo->m_nCurPage > m_nPrintPages)
pInfo->m_bContinuePrinting = FALSE;
}
}
BOOL CCrystalTextView::OnPreparePrinting(CPrintInfo* pInfo)
{
return DoPreparePrinting(pInfo);
}
int CCrystalTextView::PrintLineHeight(CDC *pdc, int nLine)
{
ASSERT(nLine >= 0 && nLine < GetLineCount());
ASSERT(m_nPrintLineHeight > 0);
int nLength = GetLineLength(nLine);
if (nLength == 0)
return m_nPrintLineHeight;
CString line;
LPCTSTR pszChars = GetLineChars(nLine);
ExpandChars(pszChars, 0, nLength, line);
CRect rcPrintArea = m_rcPrintArea;
pdc->DrawText(line, &rcPrintArea, DT_LEFT | DT_NOPREFIX | DT_TOP | DT_WORDBREAK | DT_CALCRECT);
return rcPrintArea.Height();
}
void CCrystalTextView::GetPrintHeaderText(int nPageNum, CString &text)
{
ASSERT(m_bPrintHeader);
text = _T("");
}
void CCrystalTextView::GetPrintFooterText(int nPageNum, CString &text)
{
ASSERT(m_bPrintFooter);
text.Format(_T("Page %d/%d"), nPageNum, m_nPrintPages);
}
void CCrystalTextView::PrintHeader(CDC *pdc, int nPageNum)
{
CRect rcHeader = m_rcPrintArea;
rcHeader.bottom = rcHeader.top;
rcHeader.top -= (m_nPrintLineHeight + m_nPrintLineHeight / 2);
CString text;
GetPrintHeaderText(nPageNum, text);
if (! text.IsEmpty())
pdc->DrawText(text, &rcHeader, DT_CENTER | DT_NOPREFIX | DT_TOP | DT_SINGLELINE);
}
void CCrystalTextView::PrintFooter(CDC *pdc, int nPageNum)
{
CRect rcFooter = m_rcPrintArea;
rcFooter.top = rcFooter.bottom;
rcFooter.bottom += (m_nPrintLineHeight + m_nPrintLineHeight / 2);
CString text;
GetPrintFooterText(nPageNum, text);
if (! text.IsEmpty())
pdc->DrawText(text, &rcFooter, DT_CENTER | DT_NOPREFIX | DT_BOTTOM | DT_SINGLELINE);
}
void CCrystalTextView::RecalcPageLayouts(CDC *pdc, CPrintInfo *pInfo)
{
m_ptPageArea = pInfo->m_rectDraw;
m_ptPageArea.NormalizeRect();
m_nPrintLineHeight = pdc->GetTextExtent(_T("X")).cy;
m_rcPrintArea = m_ptPageArea;
CSize szTopLeft, szBottomRight;
CWinApp *pApp = AfxGetApp();
ASSERT(pApp != NULL);
szTopLeft.cx = pApp->GetProfileInt(REG_PAGE_SUBKEY, REG_MARGIN_LEFT, DEFAULT_PRINT_MARGIN);
szBottomRight.cx = pApp->GetProfileInt(REG_PAGE_SUBKEY, REG_MARGIN_RIGHT, DEFAULT_PRINT_MARGIN);
szTopLeft.cy = pApp->GetProfileInt(REG_PAGE_SUBKEY, REG_MARGIN_TOP, DEFAULT_PRINT_MARGIN);
szBottomRight.cy = pApp->GetProfileInt(REG_PAGE_SUBKEY, REG_MARGIN_BOTTOM, DEFAULT_PRINT_MARGIN);
pdc->HIMETRICtoLP(&szTopLeft);
pdc->HIMETRICtoLP(&szBottomRight);
m_rcPrintArea.left += szTopLeft.cx;
m_rcPrintArea.right -= szBottomRight.cx;
m_rcPrintArea.top += szTopLeft.cy;
m_rcPrintArea.bottom -= szBottomRight.cy;
if (m_bPrintHeader)
m_rcPrintArea.top += m_nPrintLineHeight + m_nPrintLineHeight / 2;
if (m_bPrintFooter)
m_rcPrintArea.bottom += m_nPrintLineHeight + m_nPrintLineHeight / 2;
int nLimit = 32;
m_nPrintPages = 1;
m_pnPages = new int[nLimit];
m_pnPages[0] = 0;
int nLineCount = GetLineCount();
int nLine = 1;
int y = m_rcPrintArea.top + PrintLineHeight(pdc, 0);
while (nLine < nLineCount)
{
int nHeight = PrintLineHeight(pdc, nLine);
if (y + nHeight <= m_rcPrintArea.bottom)
{
y += nHeight;
}
else
{
ASSERT(nLimit >= m_nPrintPages);
if (nLimit <= m_nPrintPages)
{
nLimit += 32;
int *pnNewPages = new int[nLimit];
memcpy(pnNewPages, m_pnPages, sizeof(int) * m_nPrintPages);
delete m_pnPages;
m_pnPages = pnNewPages;
}
ASSERT(nLimit > m_nPrintPages);
m_pnPages[m_nPrintPages ++] = nLine;
y = m_rcPrintArea.top + nHeight;
}
nLine ++;
}
}
void CCrystalTextView::OnBeginPrinting(CDC *pdc, CPrintInfo *pInfo)
{
ASSERT(m_pnPages == NULL);
ASSERT(m_pPrintFont == NULL);
CFont *pDisplayFont = GetFont();
LOGFONT lf;
pDisplayFont->GetLogFont(&lf);
CDC *pDisplayDC = GetDC();
lf.lfHeight = MulDiv(lf.lfHeight, pdc->GetDeviceCaps(LOGPIXELSY), pDisplayDC->GetDeviceCaps(LOGPIXELSY) * 2);
lf.lfWidth = MulDiv(lf.lfWidth, pdc->GetDeviceCaps(LOGPIXELSX), pDisplayDC->GetDeviceCaps(LOGPIXELSX) * 2);
ReleaseDC(pDisplayDC);
m_pPrintFont = new CFont;
if (! m_pPrintFont->CreateFontIndirect(&lf))
{
delete m_pPrintFont;
m_pPrintFont = NULL;
return;
}
pdc->SelectObject(m_pPrintFont);
}
void CCrystalTextView::OnEndPrinting(CDC *pdc, CPrintInfo *pInfo)
{
if (m_pPrintFont != NULL)
{
delete m_pPrintFont;
m_pPrintFont = NULL;
}
if (m_pnPages != NULL)
{
delete m_pnPages;
m_pnPages = NULL;
}
m_nPrintPages = 0;
m_nPrintLineHeight = 0;
}
void CCrystalTextView::OnPrint(CDC* pdc, CPrintInfo* pInfo)
{
if (m_pnPages == NULL)
{
RecalcPageLayouts(pdc, pInfo);
ASSERT(m_pnPages != NULL);
}
ASSERT(pInfo->m_nCurPage >= 1 && (int) pInfo->m_nCurPage <= m_nPrintPages);
int nLine = m_pnPages[pInfo->m_nCurPage - 1];
int nEndLine = GetLineCount();
if ((int) pInfo->m_nCurPage < m_nPrintPages)
nEndLine = m_pnPages[pInfo->m_nCurPage];
TRACE(_T("Printing page %d of %d, lines %d - %d\n"), pInfo->m_nCurPage, m_nPrintPages,
nLine, nEndLine - 1);
if (m_bPrintHeader)
PrintHeader(pdc, pInfo->m_nCurPage);
if (m_bPrintFooter)
PrintFooter(pdc, pInfo->m_nCurPage);
int y = m_rcPrintArea.top;
for (; nLine < nEndLine; nLine ++)
{
int nLineLength = GetLineLength(nLine);
if (nLineLength == 0)
{
y += m_nPrintLineHeight;
continue;
}
CRect rcPrintRect = m_rcPrintArea;
rcPrintRect.top = y;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -