📄 ccrystaltextview.cpp
字号:
if (nLine2 == -1)
{
CRect rcInvalid;
GetClientRect(&rcInvalid);
if (! bInvalidateMargin)
rcInvalid.left += GetMarginWidth();
// rcInvalid.top = (nLine1 - m_nTopLine) * GetLineHeight();
rcInvalid.top = CalcVisibleLines(m_nTopLine, nLine1) * GetLineHeight();
InvalidateRect(&rcInvalid, FALSE);
}
else
{
if (nLine2 < nLine1)
{
int nTemp = nLine1;
nLine1 = nLine2;
nLine2 = nTemp;
}
CRect rcInvalid;
GetClientRect(&rcInvalid);
if (! bInvalidateMargin)
rcInvalid.left += GetMarginWidth();
rcInvalid.top = CalcVisibleLines(m_nTopLine, nLine1) * GetLineHeight();
rcInvalid.bottom = (CalcVisibleLines(m_nTopLine, nLine2) + 1) * GetLineHeight();
InvalidateRect(&rcInvalid, FALSE);
}
}
void CCrystalTextView::SetSelection(const CPoint &ptStart, const CPoint &ptEnd)
{
ASSERT_VALIDTEXTPOS(ptStart);
ASSERT_VALIDTEXTPOS(ptEnd);
if (m_ptSelStart == ptStart)
{
if (m_ptSelEnd != ptEnd)
InvalidateLines(ptEnd.y, m_ptSelEnd.y);
}
else
{
InvalidateLines(ptStart.y, ptEnd.y);
InvalidateLines(m_ptSelStart.y, m_ptSelEnd.y);
}
m_ptSelStart = ptStart;
m_ptSelEnd = ptEnd;
}
void CCrystalTextView::AdjustTextPoint(CPoint &point)
{
point.x += GetCharWidth() / 2; //todo
}
void CCrystalTextView::OnSetFocus(CWnd* pOldWnd)
{
CView::OnSetFocus(pOldWnd);
m_bFocused = TRUE;
if (m_ptSelStart != m_ptSelEnd)
InvalidateLines(m_ptSelStart.y, m_ptSelEnd.y);
UpdateCaret();
}
DWORD CCrystalTextView::ParseLine(DWORD dwCookie, int nLineIndex, TEXTBLOCK *pBuf, int &nActualItems)
{
return 0;
}
int CCrystalTextView::CalculateActualOffset(int nLineIndex, int nCharIndex)
{
// ASSERT(!IsLineHidden(nLineIndex));
int nLength = GetLineLength(nLineIndex);
ASSERT(nCharIndex >= 0 && nCharIndex <= nLength);
LPCTSTR pszChars = GetLineChars(nLineIndex);
int nOffset = 0;
int nTabSize = GetTabSize();
for (int I = 0; I < nCharIndex; I ++)
{
if (pszChars[I] == _T('\t'))
nOffset += (nTabSize - nOffset % nTabSize);
else
nOffset ++;
}
return nOffset;
}
int CCrystalTextView::ApproxActualOffset(int nLineIndex, int nOffset)
{
if (nOffset == 0)
return 0;
int nLength = GetLineLength(nLineIndex);
LPCTSTR pszChars = GetLineChars(nLineIndex);
int nCurrentOffset = 0;
int nTabSize = GetTabSize();
for (int I = 0; I < nLength; I ++)
{
if (pszChars[I] == _T('\t'))
nCurrentOffset += (nTabSize - nCurrentOffset % nTabSize);
else
nCurrentOffset ++;
if (nCurrentOffset >= nOffset)
{
if (nOffset <= nCurrentOffset - nTabSize / 2)
return I;
return I + 1;
}
}
return nLength;
}
void CCrystalTextView::EnsureVisible(CPoint pt)
{
ASSERT(!IsLineHidden(pt.y));
// Scroll vertically
int nLineCount = GetLineCount();
int nNewTopLine = m_nTopLine;
// MiK: bottom line (last visible)
int nBottomLine= FindVisibleLine(nNewTopLine, GetScreenLines() - 1);
if (pt.y > nBottomLine) // MiK (pt.y >= nNewTopLine + GetScreenLines())
{
nNewTopLine = FindVisibleLine(pt.y, -GetScreenLines() + 1); //MiK pt.y - GetScreenLines() + 1;
}
if (pt.y < nNewTopLine)
{
nNewTopLine = pt.y;
}
if (nNewTopLine < 0)
nNewTopLine = 0;
if (nNewTopLine >= nLineCount)
nNewTopLine = nLineCount - 1;
if (m_nTopLine != nNewTopLine)
{
ScrollToLine(nNewTopLine);
UpdateSiblingScrollPos(TRUE);
}
// Scroll horizontally
int nActualPos = CalculateActualOffset(pt.y, pt.x);
int nNewOffset = m_nOffsetChar;
if (nActualPos > nNewOffset + GetScreenChars())
{
nNewOffset = nActualPos - GetScreenChars();
}
if (nActualPos < nNewOffset)
{
nNewOffset = nActualPos;
}
if (nNewOffset >= GetMaxLineLength())
nNewOffset = GetMaxLineLength() - 1;
if (nNewOffset < 0)
nNewOffset = 0;
if (m_nOffsetChar != nNewOffset)
{
ScrollToChar(nNewOffset);
UpdateCaret();
UpdateSiblingScrollPos(FALSE);
}
}
void CCrystalTextView::OnKillFocus(CWnd* pNewWnd)
{
CView::OnKillFocus(pNewWnd);
m_bFocused = FALSE;
UpdateCaret();
if (m_ptSelStart != m_ptSelEnd)
InvalidateLines(m_ptSelStart.y, m_ptSelEnd.y);
if (m_bDragSelection)
{
ReleaseCapture();
KillTimer(m_nDragSelTimer);
m_bDragSelection = FALSE;
}
}
void CCrystalTextView::OnSysColorChange()
{
CView::OnSysColorChange();
Invalidate();
}
void CCrystalTextView::GetText(const CPoint &ptStart, const CPoint &ptEnd, CString &text)
{
if (m_pTextBuffer != NULL)
m_pTextBuffer->GetText(ptStart.y, ptStart.x, ptEnd.y, ptEnd.x, text);
else
text = _T("");
}
CString CCrystalTextView::GetCurLine()
{
int nLine= m_ptCursorPos.y;
if (m_pTextBuffer == 0 || nLine >= GetLineCount())
return _T("");
int nLength= GetLineLength(nLine);
if (nLength == 0)
return _T("");
CString str;
m_pTextBuffer->GetText(nLine, 0, nLine, nLength, str);
return str;
}
void CCrystalTextView::UpdateView(CCrystalTextView *pSource, CUpdateContext *pContext,
DWORD dwFlags, int nLineIndex /*= -1*/)
{
if (dwFlags & UPDATE_RESET)
{
ResetView();
RecalcVertScrollBar();
RecalcHorzScrollBar();
// MiK: parse all to update collapsible blocks
GetParseCookie(GetLineCount() - 1);
NotifyTextChanged();
return;
}
int nLineCount = GetLineCount();
ASSERT(nLineCount > 0);
ASSERT(nLineIndex >= -1 && nLineIndex < nLineCount);
if ((dwFlags & UPDATE_SINGLELINE) != 0)
{
ASSERT(nLineIndex != -1);
// All text below this line should be reparsed
if (m_pdwParseCookies != NULL)
{
ASSERT(m_nParseArraySize == nLineCount);
memset(m_pdwParseCookies + nLineIndex, 0xff, sizeof(DWORD) * (m_nParseArraySize - nLineIndex));
}
// This line'th actual length must be recalculated
if (m_pnActualLineLength != NULL)
{
ASSERT(m_nActualLengthArraySize == nLineCount);
m_pnActualLineLength[nLineIndex] = -1;
}
// Repaint the lines
InvalidateLines(nLineIndex, -1, TRUE);
}
else
{
if (nLineIndex == -1)
nLineIndex = 0; // Refresh all text
// All text below this line should be reparsed
if (m_pdwParseCookies != NULL)
{
if (m_nParseArraySize != nLineCount)
{
// Reallocate cookies array
DWORD *pdwNewArray = new DWORD[nLineCount];
if (nLineIndex > 0)
memcpy(pdwNewArray, m_pdwParseCookies, sizeof(DWORD) * nLineIndex);
delete m_pdwParseCookies;
m_nParseArraySize = nLineCount;
m_pdwParseCookies = pdwNewArray;
}
memset(m_pdwParseCookies + nLineIndex, 0xff, sizeof(DWORD) * (m_nParseArraySize - nLineIndex));
}
// Recalculate actual length for all lines below this
if (m_pnActualLineLength != NULL)
{
if (m_nActualLengthArraySize != nLineCount)
{
// Reallocate actual length array
int *pnNewArray = new int[nLineCount];
if (nLineIndex > 0)
memcpy(pnNewArray, m_pnActualLineLength, sizeof(int) * nLineIndex);
delete m_pnActualLineLength;
m_nActualLengthArraySize = nLineCount;
m_pnActualLineLength = pnNewArray;
}
memset(m_pnActualLineLength + nLineIndex, 0xff, sizeof(DWORD) * (m_nActualLengthArraySize - nLineIndex));
}
// Repaint the lines
InvalidateLines(nLineIndex, -1, TRUE);
}
// All those points must be recalculated and validated
if (pContext != NULL)
{
pContext->RecalcPoint(m_ptCursorPos);
pContext->RecalcPoint(m_ptSelStart);
pContext->RecalcPoint(m_ptSelEnd);
pContext->RecalcPoint(m_ptAnchor);
ASSERT_VALIDTEXTPOS(m_ptCursorPos);
ASSERT_VALIDTEXTPOS(m_ptSelStart);
ASSERT_VALIDTEXTPOS(m_ptSelEnd);
ASSERT_VALIDTEXTPOS(m_ptAnchor);
if (m_bDraggingText)
{
pContext->RecalcPoint(m_ptDraggedTextBegin);
pContext->RecalcPoint(m_ptDraggedTextEnd);
ASSERT_VALIDTEXTPOS(m_ptDraggedTextBegin);
ASSERT_VALIDTEXTPOS(m_ptDraggedTextEnd);
}
CPoint ptTopLine(0, m_nTopLine);
pContext->RecalcPoint(ptTopLine);
ASSERT_VALIDTEXTPOS(ptTopLine);
m_nTopLine = ptTopLine.y;
UpdateCaret();
}
// Recalculate vertical scrollbar, if needed
if ((dwFlags & UPDATE_VERTRANGE) != 0)
{
if (! m_bVertScrollBarLocked)
RecalcVertScrollBar();
}
// Recalculate horizontal scrollbar, if needed
if ((dwFlags & UPDATE_HORZRANGE) != 0)
{
m_nMaxLineLength = -1;
if (! m_bHorzScrollBarLocked)
RecalcHorzScrollBar();
}
if (dwFlags & (UPDATE_SINGLELINE | UPDATE_VERTRANGE))
NotifyTextChanged();
}
HINSTANCE CCrystalTextView::GetResourceHandle()
{
#ifdef CRYSEDIT_RES_HANDLE
return CRYSEDIT_RES_HANDLE;
#else
if (s_hResourceInst != NULL)
return s_hResourceInst;
return AfxGetResourceHandle();
#endif
}
int CCrystalTextView::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
// Note: CSampleDoc overwrites this logfont
memset(&m_lfBaseFont, 0, sizeof(m_lfBaseFont));
lstrcpy(m_lfBaseFont.lfFaceName, _T("Atari Mono"));
m_lfBaseFont.lfHeight = 0;
m_lfBaseFont.lfWeight = FW_NORMAL;
m_lfBaseFont.lfItalic = FALSE;
m_lfBaseFont.lfCharSet = DEFAULT_CHARSET;
m_lfBaseFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
m_lfBaseFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
m_lfBaseFont.lfQuality = DEFAULT_QUALITY;
m_lfBaseFont.lfPitchAndFamily = DEFAULT_PITCH;
if (CView::OnCreate(lpCreateStruct) == -1)
return -1;
ASSERT(m_hAccel == NULL);
m_hAccel = ::LoadAccelerators(GetResourceHandle(), MAKEINTRESOURCE(IDR_DEFAULT_ACCEL));
ASSERT(m_hAccel != NULL);
return 0;
}
void CCrystalTextView::SetAnchor(const CPoint &ptNewAnchor)
{
ASSERT_VALIDTEXTPOS(ptNewAnchor);
m_ptAnchor = ptNewAnchor;
}
void CCrystalTextView::OnEditOperation(int nAction, LPCTSTR pszText)
{
}
BOOL CCrystalTextView::PreTranslateMessage(MSG *pMsg)
{
if (pMsg->message >= WM_KEYFIRST && pMsg->message <= WM_KEYLAST)
{
if (m_hAccel != NULL)
{
if (::TranslateAccelerator(m_hWnd, m_hAccel, pMsg))
return TRUE;
}
}
return CView::PreTranslateMessage(pMsg);
}
CPoint CCrystalTextView::GetCursorPos()
{
return m_ptCursorPos;
}
void CCrystalTextView::SetCursorPos(const CPoint &ptCursorPos)
{
ASSERT_VALIDTEXTPOS(ptCursorPos);
m_ptCursorPos = ptCursorPos;
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
UpdateCaret();
}
void CCrystalTextView::SetSelectionMargin(BOOL bSelMargin)
{
if (m_bSelMargin != bSelMargin)
{
m_bSelMargin = bSelMargin;
if (::IsWindow(m_hWnd))
{
m_nScreenChars = -1;
Invalidate();
RecalcHorzScrollBar();
}
}
}
void CCrystalTextView::GetFont(LOGFONT &lf)
{
lf = m_lfBaseFont;
}
void CCrystalTextView::SetFont(const LOGFONT &lf)
{
m_lfBaseFont = lf;
m_nScreenLines = -1;
m_nScreenChars = -1;
m_nCharWidth = -1;
m_nLineHeight = -1;
if (m_pCacheBitmap != NULL)
{
m_pCacheBitmap->DeleteObject();
delete m_pCacheBitmap;
m_pCacheBitmap = 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 (::IsWindow(m_hWnd))
{
RecalcVertScrollBar();
RecalcHorzScrollBar();
UpdateCaret();
Invalidate();
}
}
void CCrystalTextView::OnUpdateIndicatorPosition(CCmdUI* pCmdUI)
{
ASSERT_VALIDTEXTPOS(m_ptCursorPos);
CString stat;
int nXPos= CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
stat.Format(_T("Ln %d, Col %d"), m_ptCursorPos.y + 1, nXPos + 1);
pCmdUI->SetText(stat);
}
void CCrystalTextView::OnUpdateIndicatorCRLF(CCmdUI* pCmdUI)
{
if (m_pTextBuffer != NULL)
{
int crlfMode = m_pTextBuffer->GetCRLFMode();
switch (crlfMode)
{
case CRLF_STYLE_DOS:
pCmdUI->SetText(_T("DOS"));
pCmdUI->Enable(TRUE);
break;
case CRLF_STYLE_UNIX:
pCmdUI->SetText(_T("UNIX"));
pCmdUI->Enable(TRUE);
break;
case CRLF_STYLE_MAC:
pCmdUI->SetText(_T("MAC"));
pCmdUI->Enable(TRUE);
break;
default:
pCmdUI->SetText(NULL);
pCmdUI->Enable(FALSE);
}
}
else
{
pCmdUI->SetText(NULL);
pCmdUI->Enable(FALSE);
}
}
void CCrystalTextView::OnToggleBookmark(UINT nCmdID)
{
int nBookmarkID = nCmdID - ID_EDIT_TOGGLE
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -