📄 crortextview.cpp
字号:
#include "stdafx.h"
#include <malloc.h>
#include "editcmd.h"
#include "CRorTextView.h"
#include "CRorTextBuffer.h"
#include "Change.h"
#include <assert.h>
#ifndef __AFXPRIV_H__
#pragma message("Include <afxpriv.h> in your stdafx.h to avoid this message")
#include <afxpriv.h>
#endif
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define TAB_CHARACTER _T('\xBB')
#define SPACE_CHARACTER _T('\x95')
#define DEFAULT_PRINT_MARGIN 1000 // 10 millimeters
#define SMOOTH_SCROLL_FACTOR 6
////////////////////////////////////////////////////////////////////////////
// CRorTextView
IMPLEMENT_DYNCREATE(CRorTextView, CView)
HINSTANCE CRorTextView::s_hResourceInst = NULL;
BEGIN_MESSAGE_MAP(CRorTextView, CView)
//{{AFX_MSG_MAP(CRorTextView)
ON_WM_DESTROY()
ON_WM_ERASEBKGND()
ON_WM_SIZE()
ON_WM_VSCROLL()
ON_WM_SETCURSOR()
ON_WM_LBUTTONDOWN()
ON_WM_SETFOCUS()
ON_WM_HSCROLL()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_WM_KILLFOCUS()
ON_WM_LBUTTONDBLCLK()
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
ON_WM_RBUTTONDOWN()
ON_WM_SYSCOLORCHANGE()
ON_WM_CREATE()
//}}AFX_MSG_MAP
ON_COMMAND(ID_EDIT_CHAR_LEFT, OnCharLeft)
ON_COMMAND(ID_EDIT_EXT_CHAR_LEFT, OnExtCharLeft)
ON_COMMAND(ID_EDIT_CHAR_RIGHT, OnCharRight)
ON_COMMAND(ID_EDIT_EXT_CHAR_RIGHT, OnExtCharRight)
ON_COMMAND(ID_EDIT_WORD_LEFT, OnWordLeft)
ON_COMMAND(ID_EDIT_EXT_WORD_LEFT, OnExtWordLeft)
ON_COMMAND(ID_EDIT_WORD_RIGHT, OnWordRight)
ON_COMMAND(ID_EDIT_EXT_WORD_RIGHT, OnExtWordRight)
ON_COMMAND(ID_EDIT_LINE_UP, OnLineUp)
ON_COMMAND(ID_EDIT_EXT_LINE_UP, OnExtLineUp)
ON_COMMAND(ID_EDIT_LINE_DOWN, OnLineDown)
ON_COMMAND(ID_EDIT_EXT_LINE_DOWN, OnExtLineDown)
ON_COMMAND(ID_EDIT_SCROLL_UP, ScrollUp)
ON_COMMAND(ID_EDIT_SCROLL_DOWN, ScrollDown)
ON_COMMAND(ID_EDIT_PAGE_UP, OnPageUp)
ON_COMMAND(ID_EDIT_EXT_PAGE_UP, OnExtPageUp)
ON_COMMAND(ID_EDIT_PAGE_DOWN, OnPageDown)
ON_COMMAND(ID_EDIT_EXT_PAGE_DOWN, OnExtPageDown)
ON_COMMAND(ID_EDIT_LINE_END, OnLineEnd)
ON_COMMAND(ID_EDIT_EXT_LINE_END, OnExtLineEnd)
ON_COMMAND(ID_EDIT_HOME, OnHome)
ON_COMMAND(ID_EDIT_EXT_HOME, OnExtHome)
ON_COMMAND(ID_EDIT_TEXT_BEGIN, OnTextBegin)
ON_COMMAND(ID_EDIT_EXT_TEXT_BEGIN, OnExtTextBegin)
ON_COMMAND(ID_EDIT_TEXT_END, OnTextEnd)
ON_COMMAND(ID_EDIT_EXT_TEXT_END, OnExtTextEnd)
// Standard printing commands
ON_COMMAND(ID_FILE_PRINT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_DIRECT, CView::OnFilePrint)
ON_COMMAND(ID_FILE_PRINT_PREVIEW, CView::OnFilePrintPreview)
// Status
END_MESSAGE_MAP()
#define EXPAND_PRIMITIVE(impl, func) \
void CRorTextView::On##func() { impl(FALSE); } \
void CRorTextView::OnExt##func() { impl(TRUE); }
EXPAND_PRIMITIVE(MoveLeft, CharLeft)
EXPAND_PRIMITIVE(MoveRight, CharRight)
EXPAND_PRIMITIVE(MoveWordLeft, WordLeft)
EXPAND_PRIMITIVE(MoveWordRight, WordRight)
EXPAND_PRIMITIVE(MoveUp, LineUp)
EXPAND_PRIMITIVE(MoveDown, LineDown)
EXPAND_PRIMITIVE(MovePgUp, PageUp)
EXPAND_PRIMITIVE(MovePgDn, PageDown)
EXPAND_PRIMITIVE(MoveHome, Home)
EXPAND_PRIMITIVE(MoveEnd, LineEnd)
EXPAND_PRIMITIVE(MoveCtrlHome, TextBegin)
EXPAND_PRIMITIVE(MoveCtrlEnd, TextEnd)
#undef EXPAND_PRIMITIVE
/////////////////////////////////////////////////////////////////////////////
// CRorTextView construction/destruction
CRorTextView::CRorTextView()
{
AFX_ZERO_INIT_OBJECT(CScrollView);
ResetView();
}
CRorTextView::~CRorTextView()
{
ASSERT(m_hAccel == NULL);
ASSERT(m_pCacheBitmap == NULL);
ASSERT(m_pTextBuffer == NULL); // Must be correctly detached
}
BOOL CRorTextView::PreCreateWindow(CREATESTRUCT& cs)
{
CWnd *pParentWnd = CWnd::FromHandlePermanent(cs.hwndParent);
if (pParentWnd == NULL || ! pParentWnd->IsKindOf(RUNTIME_CLASS(CSplitterWnd)))
{
// View must always create its own scrollbars,
// if only it's not used within splitter
cs.style |= (WS_HSCROLL | WS_VSCROLL);
}
cs.lpszClass = AfxRegisterWndClass(CS_DBLCLKS);
return CScrollView::PreCreateWindow(cs);
}
/////////////////////////////////////////////////////////////////////////////
// CRorTextView drawing
void CRorTextView::GetSelection(CPoint &ptStart, CPoint &ptEnd)
{
PrepareSelBounds();
ptStart = m_ptDrawSelStart;
ptEnd = m_ptDrawSelEnd;
}
CRorTextBuffer *CRorTextView::LocateTextBuffer()
{
return NULL;
}
void CRorTextView::ScrollToChar(int nNewOffsetChar)
{
// For now, ignoring bNoSmoothScroll and m_bSmoothScroll
if (m_nOffsetChar != nNewOffsetChar)
{
int nScrollChars = m_nOffsetChar - nNewOffsetChar;
m_nOffsetChar = nNewOffsetChar;
CRect rcScroll;
GetClientRect(&rcScroll);
ScrollWindow(nScrollChars * GetCharWidth(), 0, &rcScroll, &rcScroll);
UpdateWindow();
RecalcHorzScrollBar(TRUE);
}
}
void CRorTextView::ScrollToLine(int nNewTopLine, BOOL bNoSmoothScroll /*= FALSE*/, BOOL bTrackScrollBar /*= TRUE*/)
{
if (m_nTopLine != nNewTopLine)
{
int nScrollLines = m_nTopLine - nNewTopLine;
m_nTopLine = nNewTopLine;
ScrollWindow(0, nScrollLines * GetLineHeight());
UpdateWindow();
if (bTrackScrollBar)
RecalcVertScrollBar(TRUE);
}
}
void CRorTextView::PointTrans_ImageToChar(IN CPoint& pt1, OUT CPoint& pt2)
{
pt2.x = pt1.x / GetCharWidth();
pt2.y = pt1.y / GetLineHeight();
}
void CRorTextView::PointTrans_CharToImage(IN CPoint& pt1, OUT CPoint& pt2)
{
pt2.x = pt1.x * GetCharWidth();
pt2.y = pt1.y * GetLineHeight();
}
void CRorTextView::DrawLineHelperImpl(CDC *pdc, CPoint &ptOrigin,
LPCTSTR pszChars, int nCount)
{
//this->DrawLineHelperImpl_1(pdc,ptOrigin,pszChars,nCount);
//return;
CPoint ptchar;
PointTrans_ImageToChar(ptOrigin, ptchar);
//ptchar = ptOrigin;
this->DrawLineHelperImpl_1(pdc,ptchar,pszChars,nCount);
PointTrans_CharToImage(ptchar, ptOrigin);
}
void CRorTextView::DrawLineHelperImpl_1(CDC *pdc, CPoint &ptOrigin,
LPCTSTR pszChars, int nCount)
{
ASSERT(nCount >= 0);
if (nCount > 0)
{
VERIFY(pdc->ExtTextOut(ptOrigin.x * GetCharWidth(),
ptOrigin.y * GetLineHeight(),
ETO_CLIPPED, NULL, pszChars,
nCount,
NULL));
ptOrigin.x += nCount;
}
}
void CRorTextView::DrawLineHelper(CDC *pdc, CPoint &ptOrigin,
LPCTSTR pszChars, int nCount, CPoint ptTextPos)
{
if (nCount <= 0)
return;
//PointTrans_CharToImage(ptTextPos, ptOrigin);
//DrawLineHelperImpl(pdc, ptOrigin, pszChars, nCount);
//DrawLineHelperImpl(pdc, ptTextPos, pszChars, nCount);
//PointTrans_CharToImage(ptTextPos, ptOrigin);
//return;
//PointTrans_ImageToChar(ptOrigin, ptTextPos);
if (m_bFocused)
{
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, pszChars, nSelBegin);
}
if (nSelBegin < nSelEnd)
{
COLORREF crOldBk = pdc->SetBkColor(GetColor(COLORINDEX_SELBKGND));
COLORREF crOldText = pdc->SetTextColor(GetColor(COLORINDEX_SELTEXT));
DrawLineHelperImpl(pdc, ptOrigin, pszChars + nSelBegin, nSelEnd - nSelBegin);
pdc->SetBkColor(crOldBk);
pdc->SetTextColor(crOldText);
}
if (nSelEnd < nCount)
{
if (nSelEnd == 0)
{
//int yellow_begin = 0, yellow_end = 0;
//this->LocateTextBuffer()->
DrawLineHelperImpl(pdc, ptOrigin, pszChars, nCount);
}
else
DrawLineHelperImpl(pdc, ptOrigin, pszChars + nSelEnd, nCount - nSelEnd);
}
}
else
{
DrawLineHelperImpl(pdc, ptOrigin, pszChars, nCount);
}
}
void CRorTextView::func1(CDC *pdc, TEXTBLOCK *pBuf, int I, int nLength,
CPoint& origin,
LPCTSTR pszChars, int nLineIndex)
{
ASSERT(pBuf[I].m_nCharPos >= 0 && pBuf[I].m_nCharPos <= nLength);
pdc->SetTextColor(GetColor(pBuf[I].m_nColorIndex));
//pdc->SelectObject(GetFont_1());
DrawLineHelper(pdc, origin,
pszChars + pBuf[I].m_nCharPos,
pBuf[I + 1].m_nCharPos - pBuf[I].m_nCharPos,
CPoint(pBuf[I].m_nCharPos, nLineIndex));
}
void CRorTextView::DrawSingleLine(CDC *pdc, int nLineIndex)
{
return; //not use anymore
ASSERT(nLineIndex >= 0 && nLineIndex < GetLineCount());
// Acquire the background color for the current line
int nLength = GetLineLength(nLineIndex);
if (nLength == 0)
{
// Draw the empty line
if ((m_bFocused) && IsInsideSelBlock(CPoint(0, nLineIndex)))
{
pdc->FillSolidRect(0, 0, GetCharWidth(), 99,
GetColor(COLORINDEX_SELBKGND));
}
return;
}
// Parse the line
LPCTSTR pszChars = GetLineChars(nLineIndex);
TEXTBLOCK *pBuf = (TEXTBLOCK *) _alloca(sizeof(TEXTBLOCK) * nLength * 3);
//不需要 free ?
int nBlocks = 0;
this->m_pTextBuffer->Parse(nLineIndex, pBuf, nBlocks);
// Draw the line text
CPoint origin(0 - m_nOffsetChar * GetCharWidth(), 0);
if (nBlocks > 0)
{
ASSERT(pBuf[0].m_nCharPos >= 0 && pBuf[0].m_nCharPos <= nLength);
pdc->SetTextColor(GetColor(COLORINDEX_NORMALTEXT));
//pdc->SelectObject(GetFont_1());
DrawLineHelper(pdc, origin, pszChars, pBuf[0].m_nCharPos, CPoint(0, nLineIndex));
for (int I = 0; I < nBlocks - 1; I ++)
{
func1(pdc, pBuf, I, nLength, origin, pszChars, nLineIndex);
}
ASSERT(pBuf[nBlocks - 1].m_nCharPos >= 0 && pBuf[nBlocks - 1].m_nCharPos <= nLength);
pdc->SetTextColor(GetColor(pBuf[nBlocks - 1].m_nColorIndex));
//pdc->SelectObject(GetFont_1());
DrawLineHelper(pdc, origin,
pszChars + pBuf[nBlocks - 1].m_nCharPos,
nLength - pBuf[nBlocks - 1].m_nCharPos,
CPoint(pBuf[nBlocks - 1].m_nCharPos, nLineIndex));
}
else
{
pdc->SetTextColor(GetColor(COLORINDEX_NORMALTEXT));
//pdc->SelectObject(GetFont_1());
DrawLineHelper(pdc, origin, pszChars, nLength, CPoint(0, nLineIndex));
}
}
COLORREF CRorTextView::GetColor(int nColorIndex)
{
switch (nColorIndex)
{
case COLORINDEX_0: return RGB(25, 125, 125);
case COLORINDEX_func: return RGB(255, 25, 2);
case COLOR_Var:
case COLOR_VarH: return RGB(155, 205, 2);
case COLOR_Immed: return RGB(5, 125, 62);
case COLOR_ea: return RGB(95, 225, 2);
case COLOR_type: return RGB(195, 65, 82);
case COLOR_label: return RGB(82, 195, 25);
case COLORINDEX_WHITESPACE:
case COLORINDEX_BKGND:
return RGB(0, 0, 0);//::GetSysColor(COLOR_WINDOW);
case COLORINDEX_NORMALTEXT:
return RGB(250,250,250); //::GetSysColor(COLOR_WINDOWTEXT);
case COLORINDEX_SELMARGIN:
return ::GetSysColor(COLOR_SCROLLBAR);
case COLORINDEX_PREPROCESSOR:
return RGB(0, 128, 192);
case COLORINDEX_COMMENT:
return RGB(128, 128, 128);
// [JRT]: Enabled Support For Numbers...
case COLORINDEX_NUMBER:
return RGB(0x80, 0x00, 0x00);
// [JRT]: Support For C/C++ Operators
case COLORINDEX_OPERATOR:
return RGB(0x00, 0x00, 0x00);
case COLORINDEX_KEYWORD:
return RGB(0, 0, 255);
case COLORINDEX_SELBKGND:
return RGB(0, 0, 125);
case COLORINDEX_SELTEXT:
return RGB(255, 255, 255);
}
return RGB(255, 0, 0);
}
BOOL CRorTextView::IsInsideSelBlock(CPoint ptTextPos)
{
CPoint pt3 = ptTextPos;
CPoint pt1 = m_ptDrawSelStart;
CPoint pt2 = m_ptDrawSelEnd;
ASSERT_VALIDTEXTPOS(pt3);
if (pt3.y < pt1.y)
return FALSE;
if (pt3.y > pt2.y)
return FALSE;
if (pt3.y < pt2.y && pt3.y > pt1.y)
return TRUE;
if (pt1.y < pt2.y)
{
if (pt3.y == pt2.y)
return pt3.x < pt2.x;
ASSERT(pt3.y == pt1.y);
return pt3.x >= pt1.x;
}
ASSERT(pt1.y == pt2.y);
return pt3.x >= pt1.x && pt3.x < pt2.x;
}
BOOL CRorTextView::IsInsideSelection(const CPoint &ptTextPos)
{
PrepareSelBounds();
return IsInsideSelBlock(ptTextPos);
}
void CRorTextView::PrepareSelBounds()
{
if (m_ptSelStart.y < m_ptSelEnd.y ||
(m_ptSelStart.y == m_ptSelEnd.y && m_ptSelStart.x < m_ptSelEnd.x))
{
m_ptDrawSelStart = m_ptSelStart;
m_ptDrawSelEnd = m_ptSelEnd;
}
else
{
m_ptDrawSelStart = m_ptSelEnd;
m_ptDrawSelEnd = m_ptSelStart;
}
}
void CRorTextView::ResetView()
{
m_nTopLine = 0;
m_nOffsetChar = 0;
m_nLineHeight = -1;
m_nCharWidth = -1;
m_nMaxLineLength = -1;
m_nScreenLines = -1;
m_nScreenChars = -1;
m_ptAnchor.x = 0;
m_ptAnchor.y = 0;
if (m_pIcons != NULL)
{
delete m_pIcons;
m_pIcons = NULL;
}
{
if (m_apFont != NULL)
{
m_apFont->DeleteObject();
delete m_apFont;
m_apFont = NULL;
}
}
m_nParseArraySize = 0;
m_ptCursorPos.x = 0;
m_ptCursorPos.y = 0;
m_ptSelStart = m_ptSelEnd = m_ptCursorPos;
if (::IsWindow(m_hWnd))
UpdateCaret();
}
void CRorTextView::UpdateCaret()
{
ASSERT_VALIDTEXTPOS(m_ptCursorPos);
if (m_bFocused && m_ptCursorPos.x >= m_nOffsetChar)
{
CreateSolidCaret(2, GetLineHeight());
SetCaretPos(TextToClient(m_ptCursorPos));
ShowCaret();
}
else
{
HideCaret();
}
}
CFont *CRorTextView::GetFont_1()
{
if (m_apFont == NULL)
{
LOGFONT m_lfBaseFont;
memset(&m_lfBaseFont, 0, sizeof(m_lfBaseFont));
strcpy(m_lfBaseFont.lfFaceName, "Courier");
m_lfBaseFont.lfHeight = 0;
m_lfBaseFont.lfWeight = FW_NORMAL;
m_lfBaseFont.lfItalic = FALSE;
m_lfBaseFont.lfOutPrecision = OUT_DEFAULT_PRECIS;
m_lfBaseFont.lfClipPrecision = CLIP_DEFAULT_PRECIS;
m_lfBaseFont.lfQuality = DEFAULT_QUALITY;
m_lfBaseFont.lfCharSet = ANSI_CHARSET;
m_lfBaseFont.lfPitchAndFamily = DEFAULT_PITCH | FF_DONTCARE;
m_apFont = new CFont;
if (! m_apFont->CreateFontIndirect(&m_lfBaseFont))
{
delete m_apFont;
m_apFont = NULL;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -