📄 ccrystaltextview.cpp
字号:
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();
}
}
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)
{
memset(&m_lfBaseFont, 0, sizeof(m_lfBaseFont));
lstrcpy(m_lfBaseFont.lfFaceName, _T("FixedSys"));
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;
stat.Format(_T("Ln %d, Col %d"), m_ptCursorPos.y + 1, m_ptCursorPos.x + 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_BOOKMARK0;
ASSERT(nBookmarkID >= 0 && nBookmarkID <= 9);
if (m_pTextBuffer != NULL)
{
DWORD dwFlags = GetLineFlags(m_ptCursorPos.y);
DWORD dwMask = LF_EXECUTION;
// LF_BOOKMARK(nBookmarkID);
m_pTextBuffer->SetLineFlag(m_ptCursorPos.y, dwMask, (dwFlags & dwMask) == 0);
}
}
void CCrystalTextView::OnGoBookmark(UINT nCmdID)
{
int nBookmarkID = nCmdID - ID_EDIT_GO_BOOKMARK0;
ASSERT(nBookmarkID >= 0 && nBookmarkID <= 9);
if (m_pTextBuffer != NULL)
{
int nLine = m_pTextBuffer->GetLineWithFlag(LF_BOOKMARK(nBookmarkID));
if (nLine >= 0)
{
CPoint pt(0, nLine);
ASSERT_VALIDTEXTPOS(pt);
SetCursorPos(pt);
SetSelection(pt, pt);
SetAnchor(pt);
EnsureVisible(pt);
}
}
}
void CCrystalTextView::OnClearBookmarks()
{
if (m_pTextBuffer != NULL)
{
for (int nBookmarkID = 0; nBookmarkID <= 9; nBookmarkID++)
{
int nLine = m_pTextBuffer->GetLineWithFlag(LF_BOOKMARK(nBookmarkID));
if (nLine >= 0)
{
m_pTextBuffer->SetLineFlag(nLine, LF_BOOKMARK(nBookmarkID), FALSE);
}
}
}
}
void CCrystalTextView::ShowCursor()
{
m_bCursorHidden = FALSE;
UpdateCaret();
}
void CCrystalTextView::HideCursor()
{
m_bCursorHidden = TRUE;
UpdateCaret();
}
DROPEFFECT CCrystalTextView::GetDropEffect()
{
return DROPEFFECT_COPY;
}
void CCrystalTextView::OnDropSource(DROPEFFECT de)
{
ASSERT(de == DROPEFFECT_COPY);
}
HGLOBAL CCrystalTextView::PrepareDragData()
{
PrepareSelBounds();
if (m_ptDrawSelStart == m_ptDrawSelEnd)
return NULL;
CString text;
GetText(m_ptDrawSelStart, m_ptDrawSelEnd, text);
HGLOBAL hData = ::GlobalAlloc(GMEM_MOVEABLE | GMEM_DDESHARE, lstrlen(text) + 1);
if (hData == NULL)
return NULL;
LPSTR pszData = (LPSTR) ::GlobalLock(hData);
USES_CONVERSION;
strcpy(pszData, T2A(text.GetBuffer(0)));
text.ReleaseBuffer();
::GlobalUnlock(hData);
m_ptDraggedTextBegin = m_ptDrawSelStart;
m_ptDraggedTextEnd = m_ptDrawSelEnd;
return hData;
}
static int FindStringHelper(LPCTSTR pszFindWhere, LPCTSTR pszFindWhat, BOOL bWholeWord)
{
ASSERT(pszFindWhere != NULL);
ASSERT(pszFindWhat != NULL);
int nCur = 0;
int nLength = lstrlen(pszFindWhat);
for (;;)
{
#ifdef _UNICODE
LPCTSTR pszPos = wcsstr(pszFindWhere, pszFindWhat);
#else
LPCTSTR pszPos = strstr(pszFindWhere, pszFindWhat);
#endif
if (pszPos == NULL)
return -1;
if (! bWholeWord)
return nCur + (pszPos - pszFindWhere);
if (pszPos > pszFindWhere && (isalnum(pszPos[-1]) || pszPos[-1] == _T('_')))
{
nCur += (pszPos - pszFindWhere);
pszFindWhere = pszPos + 1;
continue;
}
if (isalnum(pszPos[nLength]) || pszPos[nLength] == _T('_'))
{
nCur += (pszPos - pszFindWhere + 1);
pszFindWhere = pszPos + 1;
continue;
}
return nCur + (pszPos - pszFindWhere);
}
ASSERT(FALSE); // Unreachable
return -1;
}
BOOL CCrystalTextView::HighlightText(const CPoint &ptStartPos, int nLength)
{
ASSERT_VALIDTEXTPOS(ptStartPos);
m_ptCursorPos = ptStartPos;
m_ptCursorPos.x += nLength;
ASSERT_VALIDTEXTPOS(m_ptCursorPos); // Probably 'nLength' is bigger than expected...
m_ptAnchor = m_ptCursorPos;
SetSelection(ptStartPos, m_ptCursorPos);
UpdateCaret();
EnsureVisible(m_ptCursorPos);
return TRUE;
}
BOOL CCrystalTextView::FindText(LPCTSTR pszText, const CPoint &ptStartPos, DWORD dwFlags,
BOOL bWrapSearch, CPoint *pptFoundPos)
{
int nLineCount = GetLineCount();
return FindTextInBlock(pszText, ptStartPos, CPoint(0, 0),
CPoint(GetLineLength(nLineCount - 1), nLineCount - 1),
dwFlags, bWrapSearch, pptFoundPos);
}
BOOL CCrystalTextView::FindTextInBlock(LPCTSTR pszText, const CPoint &ptStartPosition,
const CPoint &ptBlockBegin, const CPoint &ptBlockEnd,
DWORD dwFlags, BOOL bWrapSearch, CPoint *pptFoundPos)
{
CPoint ptCurrentPos = ptStartPosition;
ASSERT(pszText != NULL && lstrlen(pszText) > 0);
ASSERT_VALIDTEXTPOS(ptCurrentPos);
ASSERT_VALIDTEXTPOS(ptBlockBegin);
ASSERT_VALIDTEXTPOS(ptBlockEnd);
ASSERT(ptBlockBegin.y < ptBlockEnd.y || ptBlockBegin.y == ptBlockEnd.y &&
ptBlockBegin.x <= ptBlockEnd.x);
if (ptBlockBegin == ptBlockEnd)
return FALSE;
if (ptCurrentPos.y < ptBlockBegin.y || ptCurrentPos.y == ptBlockBegin.y &&
ptCurrentPos.x < ptBlockBegin.x)
ptCurrentPos = ptBlockBegin;
CString what = pszText;
if ((dwFlags & FIND_MATCH_CASE) == 0)
what.MakeUpper();
if (dwFlags & FIND_DIRECTION_UP)
{
// Let's check if we deal with whole text.
// At this point, we cannot search *up* in selection
ASSERT(ptBlockBegin.x == 0 && ptBlockBegin.y == 0);
ASSERT(ptBlockEnd.x == GetLineLength(GetLineCount() - 1) &&
ptBlockEnd.y == GetLineCount() - 1);
// Proceed as if we have whole text search.
for (;;)
{
while (ptCurrentPos.y >= 0)
{
int nLineLength = GetLineLength(ptCurrentPos.y);
nLineLength -= ptCurrentPos.x;
if (nLineLength <= 0)
{
ptCurrentPos.x = 0;
ptCurrentPos.y --;
continue;
}
LPCTSTR pszChars = GetLineChars(ptCurrentPos.y);
pszChars += ptCurrentPos.x;
CString line;
lstrcpyn(line.GetBuffer(nLineLength + 1), pszChars, nLineLength + 1);
line.ReleaseBuffer();
if ((dwFlags & FIND_MATCH_CASE) == 0)
line.MakeUpper();
int nPos = ::FindStringHelper(line, what, (dwFlags & FIND_WHOLE_WORD) != 0);
if (nPos >= 0) // Found text!
{
ptCurrentPos.x += nPos;
*pptFoundPos = ptCurrentPos;
return TRUE;
}
ptCurrentPos.x = 0;
ptCurrentPos.y --;
}
// Beginning of text reached
if (! bWrapSearch)
return FALSE;
// Start again from the end of text
bWrapSearch = FALSE;
ptCurrentPos = CPoint(0, GetLineCount() - 1);
}
}
else
{
for (;;)
{
while (ptCurrentPos.y <= ptBlockEnd.y)
{
int nLineLength = GetLineLength(ptCurrentPos.y);
nLineLength -= ptCurrentPos.x;
if (nLineLength <= 0)
{
ptCurrentPos.x = 0;
ptCurrentPos.y ++;
continue;
}
LPCTSTR pszChars = GetLineChars(ptCurrentPos.y);
pszChars += ptCurrentPos.x;
// Prepare necessary part of line
CString line;
lstrcpyn(line.GetBuffer(nLineLength + 1), pszChars, nLineLength + 1);
line.ReleaseBuffer();
if ((dwFlags & FIND_MATCH_CASE) == 0)
line.MakeUpper();
// Perform search in the line
int nPos = ::FindStringHelper(line, what, (dwFlags & FIND_WHOLE_WORD) != 0);
if (nPos >= 0)
{
ptCurrentPos.x += nPos;
// Check of the text found is outside the block.
if (ptCurrentPos.y == ptBlockEnd.y && ptCurrentPos.x >= ptBlockEnd.x)
break;
*pptFoundPos = ptCurrentPos;
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -