📄 ccrystaltextview2.cpp
字号:
////////////////////////////////////////////////////////////////////////////
// File: CCrystalTextView2.cpp
// Version: 1.0.0.0
// Created: 29-Dec-1998
//
// Author: Stcherbatchenko Andrei
// E-mail: windfall@gmx.de
//
// Implementation of the CCrystalTextView class, a part of Crystal Edit -
// syntax coloring text editor.
//
// You are free to use or modify this code to the following restrictions:
// - Acknowledge me somewhere in your about box, simple "Parts of code by.."
// will be enough. If you can't (or don't want to), contact me personally.
// - LEAVE THIS HEADER INTACT
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// 21-Feb-99
// Paul Selormey, James R. Twine:
// + FEATURE: description for Undo/Redo actions
// + FEATURE: multiple MSVC-like bookmarks
// + FEATURE: 'Disable backspace at beginning of line' option
// + FEATURE: 'Disable drag-n-drop editing' option
////////////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "editcmd.h"
#include "CCrystalTextView.h"
#include "CCrystalTextBuffer.h"
#include <malloc.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 CRYSTAL_TIMER_DRAGSEL 1001
/////////////////////////////////////////////////////////////////////////////
// CCrystalTextView
void CCrystalTextView::MoveLeft(BOOL bSelect)
{
PrepareSelBounds();
if (m_ptDrawSelStart != m_ptDrawSelEnd && ! bSelect)
{
m_ptCursorPos = m_ptDrawSelStart;
}
else
{
if (m_ptCursorPos.x == 0)
{
if (m_ptCursorPos.y > 0)
{
m_ptCursorPos.y --;
m_ptCursorPos.x = GetLineLength(m_ptCursorPos.y);
}
}
else
m_ptCursorPos.x --;
}
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
EnsureVisible(m_ptCursorPos);
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::MoveRight(BOOL bSelect)
{
PrepareSelBounds();
if (m_ptDrawSelStart != m_ptDrawSelEnd && ! bSelect)
{
m_ptCursorPos = m_ptDrawSelEnd;
}
else
{
if (m_ptCursorPos.x == GetLineLength(m_ptCursorPos.y))
{
if (m_ptCursorPos.y < GetLineCount() - 1)
{
m_ptCursorPos.y ++;
m_ptCursorPos.x = 0;
}
}
else
m_ptCursorPos.x ++;
}
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
EnsureVisible(m_ptCursorPos);
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::MoveWordLeft(BOOL bSelect)
{
PrepareSelBounds();
if (m_ptDrawSelStart != m_ptDrawSelEnd && ! bSelect)
{
MoveLeft(bSelect);
return;
}
if (m_ptCursorPos.x == 0)
{
if (m_ptCursorPos.y == 0)
return;
m_ptCursorPos.y --;
m_ptCursorPos.x = GetLineLength(m_ptCursorPos.y);
}
LPCTSTR pszChars = GetLineChars(m_ptCursorPos.y);
int nPos = m_ptCursorPos.x;
while (nPos > 0 && isspace(pszChars[nPos - 1]))
nPos --;
if (nPos > 0)
{
nPos --;
if (isalnum(pszChars[nPos]) || pszChars[nPos] == _T('_'))
{
while (nPos > 0 && (isalnum(pszChars[nPos - 1]) || pszChars[nPos - 1] == _T('_')))
nPos --;
}
else
{
while (nPos > 0 && ! isalnum(pszChars[nPos - 1])
&& pszChars[nPos - 1] != _T('_') && ! isspace(pszChars[nPos - 1]))
nPos --;
}
}
m_ptCursorPos.x = nPos;
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
EnsureVisible(m_ptCursorPos);
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::MoveWordRight(BOOL bSelect)
{
PrepareSelBounds();
if (m_ptDrawSelStart != m_ptDrawSelEnd && ! bSelect)
{
MoveRight(bSelect);
return;
}
if (m_ptCursorPos.x == GetLineLength(m_ptCursorPos.y))
{
if (m_ptCursorPos.y == GetLineCount() - 1)
return;
m_ptCursorPos.y ++;
m_ptCursorPos.x = 0;
}
int nLength = GetLineLength(m_ptCursorPos.y);
if (m_ptCursorPos.x == nLength)
{
MoveRight(bSelect);
return;
}
LPCTSTR pszChars = GetLineChars(m_ptCursorPos.y);
int nPos = m_ptCursorPos.x;
if (isalnum(pszChars[nPos]) || pszChars[nPos] == _T('_'))
{
while (nPos < nLength && isalnum(pszChars[nPos]) || pszChars[nPos] == _T('_'))
nPos ++;
}
else
{
while (nPos < nLength && ! isalnum(pszChars[nPos])
&& pszChars[nPos] != _T('_') && ! isspace(pszChars[nPos]))
nPos ++;
}
while (nPos < nLength && isspace(pszChars[nPos]))
nPos ++;
m_ptCursorPos.x = nPos;
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
EnsureVisible(m_ptCursorPos);
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::MoveUp(BOOL bSelect)
{
PrepareSelBounds();
if (m_ptDrawSelStart != m_ptDrawSelEnd && ! bSelect)
m_ptCursorPos = m_ptDrawSelStart;
if (m_ptCursorPos.y > 0)
{
if (m_nIdealCharPos == -1)
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
m_ptCursorPos.y --;
m_ptCursorPos.x = ApproxActualOffset(m_ptCursorPos.y, m_nIdealCharPos);
if (m_ptCursorPos.x > GetLineLength(m_ptCursorPos.y))
m_ptCursorPos.x = GetLineLength(m_ptCursorPos.y);
}
EnsureVisible(m_ptCursorPos);
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::MoveDown(BOOL bSelect)
{
PrepareSelBounds();
if (m_ptDrawSelStart != m_ptDrawSelEnd && ! bSelect)
m_ptCursorPos = m_ptDrawSelEnd;
if (m_ptCursorPos.y < GetLineCount() - 1)
{
if (m_nIdealCharPos == -1)
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
m_ptCursorPos.y ++;
m_ptCursorPos.x = ApproxActualOffset(m_ptCursorPos.y, m_nIdealCharPos);
if (m_ptCursorPos.x > GetLineLength(m_ptCursorPos.y))
m_ptCursorPos.x = GetLineLength(m_ptCursorPos.y);
}
EnsureVisible(m_ptCursorPos);
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::MoveHome(BOOL bSelect)
{
int nLength = GetLineLength(m_ptCursorPos.y);
LPCTSTR pszChars = GetLineChars(m_ptCursorPos.y);
int nHomePos = 0;
while (nHomePos < nLength && isspace(pszChars[nHomePos]))
nHomePos ++;
if (nHomePos == nLength || m_ptCursorPos.x == nHomePos)
m_ptCursorPos.x = 0;
else
m_ptCursorPos.x = nHomePos;
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
EnsureVisible(m_ptCursorPos);
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::MoveEnd(BOOL bSelect)
{
m_ptCursorPos.x = GetLineLength(m_ptCursorPos.y);
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
EnsureVisible(m_ptCursorPos);
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::MovePgUp(BOOL bSelect)
{
int nNewTopLine = m_nTopLine - GetScreenLines() + 1;
if (nNewTopLine < 0)
nNewTopLine = 0;
if (m_nTopLine != nNewTopLine)
{
ScrollToLine(nNewTopLine);
UpdateSiblingScrollPos(TRUE);
}
m_ptCursorPos.y -= GetScreenLines() - 1;
if (m_ptCursorPos.y < 0)
m_ptCursorPos.y = 0;
if (m_ptCursorPos.x > GetLineLength(m_ptCursorPos.y))
m_ptCursorPos.x = GetLineLength(m_ptCursorPos.y);
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
EnsureVisible(m_ptCursorPos); //todo: no vertical scroll
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::MovePgDn(BOOL bSelect)
{
int nNewTopLine = m_nTopLine + GetScreenLines() - 1;
if (nNewTopLine >= GetLineCount())
nNewTopLine = GetLineCount() - 1;
if (m_nTopLine != nNewTopLine)
{
ScrollToLine(nNewTopLine);
UpdateSiblingScrollPos(TRUE);
}
m_ptCursorPos.y += GetScreenLines() - 1;
if (m_ptCursorPos.y >= GetLineCount())
m_ptCursorPos.y = GetLineCount() - 1;
if (m_ptCursorPos.x > GetLineLength(m_ptCursorPos.y))
m_ptCursorPos.x = GetLineLength(m_ptCursorPos.y);
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
EnsureVisible(m_ptCursorPos); //todo: no vertical scroll
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::MoveCtrlHome(BOOL bSelect)
{
m_ptCursorPos.x = 0;
m_ptCursorPos.y = 0;
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
EnsureVisible(m_ptCursorPos);
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::MoveCtrlEnd(BOOL bSelect)
{
m_ptCursorPos.y = GetLineCount() - 1;
m_ptCursorPos.x = GetLineLength(m_ptCursorPos.y);
m_nIdealCharPos = CalculateActualOffset(m_ptCursorPos.y, m_ptCursorPos.x);
EnsureVisible(m_ptCursorPos);
UpdateCaret();
if (! bSelect)
m_ptAnchor = m_ptCursorPos;
SetSelection(m_ptAnchor, m_ptCursorPos);
}
void CCrystalTextView::ScrollUp()
{
if (m_nTopLine > 0)
{
ScrollToLine(m_nTopLine - 1);
UpdateSiblingScrollPos(TRUE);
}
}
void CCrystalTextView::ScrollDown()
{
if (m_nTopLine < GetLineCount() - 1)
{
ScrollToLine(m_nTopLine + 1);
UpdateSiblingScrollPos(TRUE);
}
}
void CCrystalTextView::ScrollLeft()
{
if (m_nOffsetChar > 0)
{
ScrollToChar(m_nOffsetChar - 1);
UpdateCaret();
}
}
void CCrystalTextView::ScrollRight()
{
if (m_nOffsetChar < GetMaxLineLength() - 1)
{
ScrollToChar(m_nOffsetChar + 1);
UpdateCaret();
}
}
CPoint CCrystalTextView::WordToRight(CPoint pt)
{
ASSERT_VALIDTEXTPOS(pt);
int nLength = GetLineLength(pt.y);
LPCTSTR pszChars = GetLineChars(pt.y);
while (pt.x < nLength)
{
if (! isalnum(pszChars[pt.x]) && pszChars[pt.x] != _T('_'))
break;
pt.x ++;
}
ASSERT_VALIDTEXTPOS(pt);
return pt;
}
CPoint CCrystalTextView::WordToLeft(CPoint pt)
{
ASSERT_VALIDTEXTPOS(pt);
LPCTSTR pszChars = GetLineChars(pt.y);
while (pt.x > 0)
{
if (! isalnum(pszChars[pt.x - 1]) && pszChars[pt.x - 1] != _T('_'))
break;
pt.x --;
}
ASSERT_VALIDTEXTPOS(pt);
return pt;
}
void CCrystalTextView::SelectAll()
{
int nLineCount = GetLineCount();
m_ptCursorPos.x = GetLineLength(nLineCount - 1);
m_ptCursorPos.y = nLineCount - 1;
SetSelection(CPoint(0, 0), m_ptCursorPos);
UpdateCaret();
}
void CCrystalTextView::OnLButtonDown(UINT nFlags, CPoint point)
{
CView::OnLButtonDown(nFlags, point);
BOOL bShift = GetKeyState(VK_SHIFT) & 0x8000;
BOOL bControl = GetKeyState(VK_CONTROL) & 0x8000;
if (point.x < GetMarginWidth())
{
AdjustTextPoint(point);
if (bControl)
{
SelectAll();
}
else
{
m_ptCursorPos = ClientToText(point);
m_ptCursorPos.x = 0; // Force beginning of the line
if (! bShift)
m_ptAnchor = m_ptCursorPos;
CPoint ptStart, ptEnd;
ptStart = m_ptAnchor;
if (ptStart.y == GetLineCount() - 1)
ptStart.x = GetLineLength(ptStart.y);
else
{
ptStart.y ++;
ptStart.x = 0;
}
ptEnd = m_ptCursorPos;
ptEnd.x = 0;
m_ptCursorPos = ptEnd;
UpdateCaret();
EnsureVisible(m_ptCursorPos);
SetSelection(ptStart, ptEnd);
SetCapture();
m_nDragSelTimer = SetTimer(CRYSTAL_TIMER_DRAGSEL, 100, NULL);
ASSERT(m_nDragSelTimer != 0);
m_bWordSelection = FALSE;
m_bLineSelection = TRUE;
m_bDragSelection = TRUE;
}
}
else
{
CPoint ptText = ClientToText(point);
PrepareSelBounds();
// [JRT]: Support For Disabling Drag and Drop...
if ((IsInsideSelBlock(ptText)) && // If Inside Selection Area
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -