📄 editorview.cpp
字号:
// EditorView.cpp : implementation of the CEditorView class
//
#include "stdafx.h"
#include <string>
#include <cassert>
#include <algorithm>
#include "Quincy.h"
#include "MainFrm.h"
#include "ChildFrm.h"
#include "EditorDoc.h"
#include "EditorView.h"
#include "QuincyPrintDialog.h"
#include "Beautifier.h"
#include "QuincyDoc.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
#define PRINTMARGIN 2
/////////////////////////////////////////////////////////////////////////////
// EditorSelection
EditorSelection::EditorSelection(CEditorView& view)
: sel::Selection<ViewIndex, CEditorView>(view)
{
}
/////////////////////////////////////////////////////////////////////////////
// ViewIndex
ViewIndex& ViewIndex::operator=(const ViewIndex& view)
{
if (this != &view) {
pView = view.pView;
row = view.row;
column = view.column;
}
return *this;
}
bool ViewIndex::operator==(const ViewIndex& view) const
{
return pView == view.pView && row == view.row && column == view.column;
}
bool ViewIndex::operator<(const ViewIndex& view) const
{
if (pView == 0 && view.pView != 0)
return true;
if (pView != 0 && view.pView == 0)
return false;
if (row == view.row)
return column < view.column;
return row < view.row;
}
/////////////////////////////////////////////////////////////////////////////
// CEditorView
CFindReplaceDialog* CEditorView::m_pFindDlg;
std::string CEditorView::m_findtext;
std::string CEditorView::m_replacetext;
int CEditorView::m_nfrflags;
CEditorView* CEditorView::pEditor;
bool CEditorView::CodeElement::operator<(const struct CodeElement& ce) const
{
if (line == ce.line)
return (charpos < ce.charpos);
return line < ce.line;
}
IMPLEMENT_DYNCREATE(CEditorView, CView)
static UINT WM_FINDREPLACE = ::RegisterWindowMessage(FINDMSGSTRING);
BEGIN_MESSAGE_MAP(CEditorView, CView)
//{{AFX_MSG_MAP(CEditorView)
ON_WM_VSCROLL()
ON_WM_HSCROLL()
ON_WM_KILLFOCUS()
ON_WM_SETFOCUS()
ON_WM_LBUTTONDOWN()
ON_WM_LBUTTONDBLCLK()
ON_WM_KEYDOWN()
ON_WM_KEYUP()
ON_WM_CHAR()
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_TIMER()
ON_UPDATE_COMMAND_UI(ID_EDIT_CUT, OnUpdateEditCut)
// ON_UPDATE_COMMAND_UI(ID_EDIT_COPY, OnUpdateEditCopy)
ON_UPDATE_COMMAND_UI(ID_EDIT_PASTE, OnUpdateEditPaste)
ON_COMMAND(ID_EDIT_CUT, OnEditCut)
ON_COMMAND(ID_EDIT_COPY, OnEditCopy)
ON_COMMAND(ID_EDIT_PASTE, OnEditPaste)
ON_UPDATE_COMMAND_UI(ID_EDIT_CLEAR, OnUpdateEditClear)
ON_COMMAND(ID_EDIT_CLEAR, OnEditClear)
ON_COMMAND(ID_EDIT_SELECT_ALL, OnEditSelectAll)
ON_COMMAND(ID_EDIT_FIND, OnEditFind)
ON_COMMAND(ID_EDIT_REPLACE, OnEditReplace)
ON_COMMAND(ID_EDIT_FIND_NEXT, OnEditFindNext)
ON_UPDATE_COMMAND_UI(ID_EDIT_FIND_NEXT, OnUpdateEditFindNext)
ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
ON_COMMAND(ID_EDIT_REDO, OnEditRedo)
ON_COMMAND(ID_RECORD, OnRecord)
ON_COMMAND(ID_STOPRECORD, OnStopRecord)
ON_WM_SETCURSOR()
ON_UPDATE_COMMAND_UI(ID_PLAYBACK, OnUpdatePlayback)
ON_UPDATE_COMMAND_UI(ID_RECORD, OnUpdateRecord)
ON_UPDATE_COMMAND_UI(ID_STOPRECORD, OnUpdateStopRecord)
ON_COMMAND(ID_PLAYBACK, OnPlayback)
ON_COMMAND(ID_FILE_OPEN, OnFileOpen)
ON_COMMAND(ID_FILE_PRINT, OnFilePrint)
ON_UPDATE_COMMAND_UI(ID_FILE_SAVE_ALL, OnUpdateFileSaveAll)
ON_UPDATE_COMMAND_UI(ID_BRACEMATCH, OnUpdateBracematch)
ON_COMMAND(ID_BRACEMATCH, OnBracematch)
ON_UPDATE_COMMAND_UI(ID_ASTYLE, OnUpdateBeautify)
ON_COMMAND(ID_ASTYLE, OnBeautify)
//}}AFX_MSG_MAP
// 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)
ON_REGISTERED_MESSAGE(WM_FINDREPLACE, OnFindReplace)
END_MESSAGE_MAP()
// C/C++ keywords
std::string CEditorView::ckeys[] = {
"#define",
"#elif",
"#else",
"#endif",
"#error",
"#if",
"#ifdef",
"#ifndef",
"#include",
"#line",
"#pragma",
"#undef",
"asm",
"auto",
"bool",
"break",
"case",
"char",
"const",
"continue",
"default",
"do",
"double",
"else",
"enum",
"extern",
"float",
"for",
"goto",
"if",
"int",
"long",
"register",
"return",
"short",
"signed",
"sizeof",
"static",
"struct",
"switch",
"typedef",
"union",
"unsigned",
"void",
"volatile",
"while"
};
// C++ keywords
std::string CEditorView::cppkeys[] = {
"and",
"and_eq",
"bitand",
"bitor",
"catch",
"class",
"compl",
"const_cast",
"delete",
"dynamic_cast",
"explicit",
"false",
"friend",
"inline",
"mutable",
"namespace",
"new",
"not",
"not_eq",
"operator",
"or",
"or_eq",
"private",
"protected",
"public",
"reinterpret_cast",
"static_cast",
"template",
"this",
"throw",
"true",
"try",
"typeid",
"typename",
"using",
"virtual",
"wchar_t",
"xor",
"xor_e"
};
/////////////////////////////////////////////////////////////////////////////
// CEditorView construction/destruction
CEditorView::CEditorView()
{
m_pscreenfont = 0;
m_pConsoleApp = 0;
m_pClearBrush = 0;
m_pMarginBrush = 0;
m_pFindDlg = 0;
m_fontheight = theApp.FontHeight();
m_fontwidth = theApp.FontWidth();
m_fontweight = theApp.FontWeight();
m_leftcolumn = 0;
m_toprow = 0;
m_bottomrow = 0;
m_windowrows = 0;
m_windowcolumns = 0;
m_currentrow = 0;
m_currentcolumn = 0;
m_margin = theApp.GetMargin() * 8;// m_fontwidth;
m_ctrldown = false;
m_shiftdown = false;
m_pEditorSelection = new EditorSelection(*this);
m_mousemarking = false;
m_dragging = false;
m_recording = false;
m_selectionmarked = false;
((CMainFrame*)theApp.m_pMainWnd)->SetRowColumn(1, 1);
m_hOldCursor = 0;
m_hMoveCursor = theApp.LoadCursor(IDC_POINTER_MOVE);
m_hCopyCursor = theApp.LoadCursor(IDC_POINTER_COPY);
m_hRecordCursor = theApp.LoadCursor(IDC_POINTER_RECORD);
m_hArrowCursor = theApp.LoadStandardCursor(IDC_ARROW);
m_pFindDlg = 0;
m_nfrflags = FR_DOWN;
m_buildcomments = true;
m_linelength = 0;
m_linecount = 0;
m_linescount = 0;
m_charcount = 0;
m_inccomment = false;
m_incppcomment = false;
m_instringliteral = false;
m_incharliteral = false;
m_found = false;
m_wasfound = false;
m_bchanged = false;
}
CEditorView::~CEditorView()
{
delete m_pConsoleApp;
delete m_pClearBrush;
delete m_pMarginBrush;
delete m_pEditorSelection;
delete m_pFindDlg;
delete m_pscreenfont;
DeleteMacros();
}
BOOL CEditorView::PreCreateWindow(CREATESTRUCT& cs)
{
cs.style |= WS_HSCROLL | WS_VSCROLL;
return CView::PreCreateWindow(cs);
}
void CEditorView::RebuildFont()
{
delete m_pscreenfont;
m_pscreenfont = new CFont;
m_fontheight = theApp.FontHeight();
m_fontwidth = theApp.FontWidth();
m_fontweight = theApp.FontWeight();
theApp.EditorScreenFont(m_pscreenfont, m_fontheight,m_fontwidth,m_fontweight);
CClientDC cdc(this);
CFont* pOldFont = cdc.SelectObject(m_pscreenfont);
TEXTMETRIC tm;
cdc.GetTextMetrics(&tm);
m_fontheight = tm.tmHeight;
m_fontwidth = tm.tmMaxCharWidth;
theApp.SetFontHeight(m_fontheight);
theApp.SetFontWidth(m_fontwidth);
theApp.SetFontWeight(m_fontweight);
cdc.SelectObject(pOldFont);
CreateSolidCaret(2, m_fontheight);
SetScrollPosition(SB_VERT, m_toprow);
SetCaretPosition();
AdjustScroll();
}
BOOL CEditorView::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
bool rtn = CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
// --- register with parent frame class
CChildFrame* pParent = (CChildFrame*)GetParentFrame();
ASSERT(pParent != 0);
pParent->RegisterView(this);
m_pClearBrush = new CBrush(RGB(255,255,255));
m_pMarginBrush = new CBrush(RGB(192,192,192));
RebuildFont();
return rtn;
}
/////////////////////////////////////////////////////////////////////////////
// CEditorView drawing
void CEditorView::AddColorToTable(int line, int charpos, COLORREF clr)
{
CodeElement ce = {line, charpos, clr};
std::set<CodeElement>::iterator it = m_contexttable.find(ce);
if (it != m_contexttable.end())
m_contexttable.erase(it);
m_contexttable.insert(ce);
m_prevcolor = clr;
}
int CEditorView::GetNextSourceChar()
{
if (m_charcount >= m_linelength) {
// --- end of line
KeywordSearch();
if (m_incppcomment) {
// --- end of C++ comment is at end of line
m_incppcomment = false;
m_prevcolor = theApp.NormalColor();
}
m_incharliteral = false;
m_charcount = 0;
if (m_linecount >= m_linescount)
return -1;
AddColorToTable(m_linecount, 0, m_prevcolor);
m_linestr = GetDocument()->textline(m_linecount++);
m_linelength = m_linestr.length();
}
return m_linestr[m_charcount++];
}
void CEditorView::KeywordSearch()
{
if (kword.length() > 0) {
if (keywords.find(kword) != keywords.end()) {
int ln = m_linecount-1;
int col = m_charcount - 1;
if (m_charcount == m_linelength && m_charcount == kword.length())
col++; // keyword is only thing on line
AddColorToTable(ln, col-kword.length(), theApp.KeywordColor());
AddColorToTable(ln, col, theApp.NormalColor());
}
kword.erase();
}
}
void CEditorView::BuildContextHighlightTable()
{
m_linecount = 0;
m_linescount = GetDocument()->linecount();
m_charcount = 0;
m_linestr.erase();
m_linelength = 0;
m_contexttable.clear();
m_inccomment = false;
m_incppcomment = false;
m_instringliteral = false;
m_incharliteral = false;
m_prevcolor = theApp.NormalColor();
char ch;
while ((ch = GetNextSourceChar()) != -1) {
if (m_incppcomment)
// --- in a C++ comment, scan until end of line
continue;
if (!m_inccomment && !m_instringliteral && !m_incharliteral) {
// --- not currently in C comment, string literal, or char literal
if (ch == '"') {
// --- start of a string literal
KeywordSearch();
m_instringliteral = true;
AddColorToTable(m_linecount-1, m_charcount-1, theApp.StringColor());
}
else if (ch == '\'') {
// --- start of a character literal
m_incharliteral = true;
}
else if (ch == '/') {
// --- possible start of a comment
KeywordSearch();
if ((ch = GetNextSourceChar()) == -1)
break;
if (m_charcount < 2)
// --- ch is the first character of a line
continue;
if (ch == '/')
// --- start of a C++ comment
m_incppcomment = true;
if (ch == '*')
// --- begin token ( /* ) of a C comment
m_inccomment = true;
if (m_incppcomment || m_inccomment)
// --- save the starting position of the comment
AddColorToTable(m_linecount-1, m_charcount-2, theApp.CommentColor());
}
else {
// --- potential keyword
if ((kword.length() == 0 && ch == '#') || isalpha(ch) || ch == '_')
kword += ch; // collect a word
else
KeywordSearch();
}
continue;
}
if (m_instringliteral) {
// --- parsing a string literal
if (ch == '\\') {
// --- bypass escape sequences
if ((ch = GetNextSourceChar()) == -1)
break;
continue;
}
if (ch == '"') {
// --- end of string literal
m_instringliteral = false;
AddColorToTable(m_linecount-1, m_charcount, theApp.NormalColor());
}
}
else if (m_incharliteral) {
// --- parsing a character literal
if (ch == '\\') {
// --- bypass escape sequences
if ((ch = GetNextSourceChar()) == -1)
break;
continue;
}
if (ch == '\'')
// --- end of character literal
m_incharliteral = false;
}
else if (m_inccomment) {
while (ch == '*') {
if ((ch = GetNextSourceChar()) == -1)
break;
if (m_charcount > 1 && ch == '/') {
// --- end token ( * / ) of a C comment
m_inccomment = false;
AddColorToTable(m_linecount-1, m_charcount-1, theApp.NormalColor());
break;
}
}
if (ch == -1)
break;
}
}
#ifdef _DEBUG
// DumpContextTable();
#endif
}
void CEditorView::DisplayText(CDC* pDC, int beg, int len, int line, COLORREF color)
{
std::string str = GetDocument()->textline(line).substr(beg, len);
CRect rc;
GetClientRect(&rc);
rc.left = m_margin;
int length = str.length();
// ---- hide the tab control characters in the text line
for (int i = 0; i < length; i++) {
if (str[i] == '\t')
str[i] = ' ';
}
pDC->SetBkColor(theApp.BackgroundColor());
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -