📄 editordoc.cpp
字号:
// EditorDoc.cpp : implementation of the CEditorDoc class
//
#include "stdafx.h"
#include <cassert>
#include "Quincy.h"
#include "EditorDoc.h"
#include "EditorView.h"
#include "EditorUndo.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
bool UndoEditorData::reportedundofull = false;
void UndoEditorData::TestUndoFull()
{
if (WasUndoDataDiscarded() && !reportedundofull) {
reportedundofull = true;
AfxMessageBox(
"The Undo buffer is at capacity.\n"
"Older undos are being discarded.\n"
"Consider increasing Maximum Undos\n"
"on Tools/Options/Editor");
}
}
/////////////////////////////////////////////////////////////////////////////
// CEditorDoc
IMPLEMENT_DYNCREATE(CEditorDoc, CDocument)
BEGIN_MESSAGE_MAP(CEditorDoc, CDocument)
//{{AFX_MSG_MAP(CEditorDoc)
ON_UPDATE_COMMAND_UI(ID_EDIT_UNDO, OnUpdateEditUndo)
ON_COMMAND(ID_EDIT_UNDO, OnEditUndo)
ON_UPDATE_COMMAND_UI(ID_EDIT_REDO, OnUpdateEditRedo)
ON_COMMAND(ID_EDIT_REDO, OnEditRedo)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CEditorDoc construction/destruction
CEditorDoc::CEditorDoc()
{
m_pUndoEditorData = 0;
m_linewidth = 0;
BuildEmptyDocument();
}
CEditorDoc::~CEditorDoc()
{
delete m_pUndoEditorData;
}
void CEditorDoc::BuildEmptyDocument()
{
doctext.clear();
m_linewidth = 0;
std::string str("");
doctext.push_back(str);
ResetUndoData();
}
void CEditorDoc::ResetUndoData()
{
delete m_pUndoEditorData;
m_pUndoEditorData = new UndoEditorData(this, theApp.MaxUndos());
undorow = undocolumn = -1;
}
BOOL CEditorDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
return CDocument::OnOpenDocument(lpszPathName);
}
BOOL CEditorDoc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return false;
if (!theApp.IsProjectFileLoaded())
theApp.CloseErrorLog();
BuildEmptyDocument();
return true;
}
void CEditorDoc::replaceline(unsigned int lineno, const std::string& str, bool bterminate)
{
undorow = undocolumn = -1;
if (m_pUndoEditorData)
m_pUndoEditorData->AddReplaceStrUndo(this, StrPosition(lineno), bterminate);
doctext[lineno] = str;
m_linewidth = max(m_linewidth, str.length());
SetModifiedFlag();
}
void CEditorDoc::insertline(unsigned int lineno, const std::string& str, bool bterminate)
{
undorow = undocolumn = -1;
if (m_pUndoEditorData)
m_pUndoEditorData->AddInsertStrUndo(this, StrPosition(lineno), bterminate);
std::vector<std::string>::iterator iter = &doctext[lineno];
doctext.insert(iter, str);
m_linewidth = max(m_linewidth, str.length());
theApp.InsertedTextLine(GetPathName(), lineno);
SetModifiedFlag();
}
void CEditorDoc::deleteline(unsigned int lineno, bool bterminate)
{
undorow = undocolumn = -1;
if (lineno < doctext.size()) {
if (m_pUndoEditorData)
m_pUndoEditorData->AddDeleteStrUndo(this, StrPosition(lineno), bterminate);
std::vector<std::string>::iterator iter = &doctext[lineno];
doctext.erase(iter);
if (doctext.size() == 0) {
std::string str("");
doctext.push_back(str);
}
theApp.DeletedTextLine(GetPathName(), lineno);
SetModifiedFlag();
}
}
void CEditorDoc::appendline(const std::string& str, bool bterminate)
{
undorow = undocolumn = -1;
if (m_pUndoEditorData)
m_pUndoEditorData->AddInsertStrUndo(this, StrPosition(doctext.size()), bterminate);
doctext.push_back(str);
m_linewidth = max(m_linewidth, str.length());
SetModifiedFlag();
}
void CEditorDoc::insertchar(char ch, unsigned int row, unsigned int column, bool bterminate)
{
SetModifiedFlag();
std::string& str = doctext[row];
if (ch == '\r') {
undorow = undocolumn = -1;
std::string strleft = str.substr(0, column);
std::string strright = str.substr(column, str.length() - column);
replaceline(row, strleft, bterminate);
insertline(row + 1, strright, false);
return;
}
if (m_pUndoEditorData) {
bool bulkundos = (ch == '\t' || row != undorow || column != undocolumn + 1);
undorow = row;
undocolumn = column;
m_pUndoEditorData->AddInsertCharUndo(this, CharPosition(row, column), bterminate && bulkundos);
}
str.insert(column, std::string(1, ch));
if (ch == '\t') {
int tabs = theApp.Tabstops();
while (++column % tabs)
str.insert(column, std::string(1, ' '));
}
m_linewidth = max(m_linewidth, str.length());
}
// --- delete a character. return true if deleting from inside text line
bool CEditorDoc::deletechar(unsigned int row, unsigned int column, bool bterminate)
{
undorow = undocolumn = -1;
SetModifiedFlag();
std::string& str = doctext[row];
if (column == str.length()) {
// --- deleting the \n at the end of the text line
if (row + 1 < doctext.size()) {
std::string str1 = str;
str1 += doctext[row + 1];
replaceline(row, str1, bterminate);
deleteline(row + 1, false);
}
return false;
}
// ---- deleting a character from within the text line
if (m_pUndoEditorData)
m_pUndoEditorData->AddDeleteCharUndo(this, CharPosition(row, column), bterminate);
char ch = str[column];
str.erase(column, 1);
int tabs = theApp.Tabstops();
if (ch == '\t') {
// --- deleting a tab; delete the trailing padding spaces
int x = column;
while ((++x) % tabs)
str.erase(column, 1);
}
else if (ch == '/' || ch == '*')
return false;
return true;
}
/////////////////////////////////////////////////////////////////////////////
// CEditorDoc serialization
void CEditorDoc::detab(std::string& str, int tabstops)
{
int x = 0;
std::string newstr;
int tabs = tabstops == -1 ? theApp.Tabstops() : tabstops;
for (int i = 0; i < str.length(); i++) {
char ch = str[i];
newstr += ch;
x++;
if (ch == '\t') {
while (x % tabs) {
newstr += ' ';
x++;
}
}
}
str = newstr;
}
void CEditorDoc::entab(std::string& str)
{
int x = 0;
std::string newstr;
int tabs = theApp.Tabstops();
for (int i = 0; i < str.length(); i++) {
char ch = str[i];
newstr += ch;
x++;
if (ch == '\t') {
while (x % tabs) {
i++;
x++;
}
}
}
str = newstr;
}
void CEditorDoc::Retab(int newtabstops)
{
std::vector<std::string>::iterator iter;
for (iter = doctext.begin(); iter != doctext.end(); iter++) {
entab(*iter);
detab(*iter, newtabstops);
}
}
void CEditorDoc::Serialize(CArchive& ar)
{
CString strText;
if (ar.IsStoring()) {
std::vector<std::string>::iterator iter;
for (iter = doctext.begin(); iter != doctext.end(); iter++) {
std::string str(*iter);
entab(str);
str += "\r\n";
strText = str.c_str();
ar.WriteString(strText);
}
}
else {
// if (theApp.GetProjectDocument() == 0)
// theApp.ClearBreakpoints();
doctext.clear();
int linecount = 0;
while (ar.ReadString(strText)) {
std::string str(strText.GetBuffer(0));
detab(str);
doctext.push_back(str);
m_linewidth = max(m_linewidth, str.length());
}
}
ResetUndoData();
}
/////////////////////////////////////////////////////////////////////////////
// CEditorDoc diagnostics
#ifdef _DEBUG
void CEditorDoc::AssertValid() const
{
CDocument::AssertValid();
}
void CEditorDoc::Dump(CDumpContext& dc) const
{
CDocument::Dump(dc);
}
#endif //_DEBUG
////////////////////////////////////////////////////////
//
// Undo/Redo functions
//
// --- called from within undo/redo library
void CEditorDoc::Insert(StrPosition pos, const std::string& rStr)
{
std::vector<std::string>::iterator iter = &doctext[pos.row];
doctext.insert(iter, rStr);
theApp.InsertedTextLine(GetPathName(), pos.row);
UpdateView();
}
void CEditorDoc::Delete(StrPosition pos)
{
std::vector<std::string>::iterator iter = &doctext[pos.row];
doctext.erase(iter);
theApp.DeletedTextLine(GetPathName(), pos.row);
UpdateView();
}
void CEditorDoc::Replace(DocPosition pos, const std::vector<std::string>& rDoc)
{
doctext.clear();
doctext = rDoc;
UpdateView();
}
const std::vector<std::string> CEditorDoc::GetDatum(DocPosition)
{
return doctext;
}
void CEditorDoc::Replace(StrPosition pos, const std::string& rStr)
{
doctext[pos.row] = rStr;
UpdateView();
}
const std::string& CEditorDoc::GetDatum(StrPosition pos)
{
return doctext[pos.row];
}
void CEditorDoc::Insert(CharPosition pos, char Char)
{
insertchar(Char, pos.row, pos.column);
UpdateView();
}
void CEditorDoc::Delete(CharPosition pos)
{
deletechar(pos.row, pos.column);
UpdateView();
}
void CEditorDoc::Replace(CharPosition pos, char Char)
{
deletechar(pos.row, pos.column);
insertchar(Char, pos.row, pos.column);
UpdateView();
}
char CEditorDoc::GetDatum(CharPosition pos)
{
return doctext[pos.row][pos.column];
}
CEditorView* CEditorDoc::GetView() const
{
CEditorView* pView = 0;
POSITION pos = GetFirstViewPosition();
if (pos != 0)
pView = static_cast<CEditorView*>(GetNextView(pos));
return pView;
}
void CEditorDoc::UpdateView()
{
CEditorView* pView = GetView();
if (pView != 0)
pView->Invalidate(false);
}
void CEditorDoc::SetUndoContext(ViewContext vc)
{
CEditorView* pView = GetView();
ASSERT(pView != 0);
pView->SetCurrentPosition(vc.scroller.row, vc.scroller.column, vc.pos.row, vc.pos.column);
}
ViewContext CEditorDoc::GetUndoContext() const
{
CEditorView* pView = GetView();
ASSERT(pView != 0);
ViewContext vc;
pView->GetCurrentPosition(vc.scroller.row, vc.scroller.column, vc.pos.row, vc.pos.column);
return vc;
}
/////////////////////////////////////////////////////////////////////////////
// CEditorDoc commands
bool CEditorDoc::CanUndo() const
{
return m_pUndoEditorData ? m_pUndoEditorData->IsUndoDataStored() : false;
}
bool CEditorDoc::CanRedo() const
{
return m_pUndoEditorData ? m_pUndoEditorData->IsRedoDataStored() : false;
}
void CEditorDoc::OnUpdateEditUndo(CCmdUI* pCmdUI)
{
pCmdUI->Enable(CanUndo());
}
void CEditorDoc::OnEditUndo()
{
if (m_pUndoEditorData) {
m_pUndoEditorData->UndoLastAction();
if (!m_pUndoEditorData->WasUndoDataDiscarded())
if (!m_pUndoEditorData->IsUndoDataStored())
SetModifiedFlag(false);
}
}
void CEditorDoc::OnUpdateEditRedo(CCmdUI* pCmdUI)
{
pCmdUI->Enable(CanRedo());
}
void CEditorDoc::OnEditRedo()
{
if (m_pUndoEditorData) {
m_pUndoEditorData->RedoLastUndo();
if (m_pUndoEditorData->IsUndoDataStored())
SetModifiedFlag(true);
}
}
BOOL CEditorDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
BOOL rtn = CDocument::OnSaveDocument(lpszPathName);
CEditorView* pView = GetView();
ASSERT(pView != 0);
pView->ResetKeywords();
return rtn;
}
void CEditorDoc::ReplaceDocument(std::vector<std::string>& newdoc)
{
theApp.ClearBreakpoints();
undorow = undocolumn = -1;
if (m_pUndoEditorData)
m_pUndoEditorData->AddReplaceDocUndo(this, DocPosition(), true);
doctext.clear();
doctext = newdoc;
SetModifiedFlag(true);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -