📄 editorview.cpp
字号:
void CEditorView::OnEditPaste()
{
OpenClipboard();
HANDLE hClipboardData = GetClipboardData(CF_TEXT);
std::vector<std::string> strs;
bool bsel = m_pEditorSelection->IsSelectionMarked();
if (hClipboardData != 0) {
char* cp = (char*) GlobalLock(hClipboardData);
if (cp != 0) {
if (bsel)
DeleteSelection();
// --- build a vector of strings from the clipboard \r\n terminated strings
StringToVector(strs, cp);
}
GlobalUnlock(hClipboardData);
}
CloseClipboard();
if (strs.size() > 0) {
InsertStringsIntoDocument(strs, !bsel);
Invalidate(false);
SetCaretPosition();
}
}
////////////////////////////////////////////////////////
// search and replace functions
void CEditorView::OnEditFind()
{
m_ctrldown = false; // in case of Ctrl+F
FindReplace(true);
}
void CEditorView::OnEditReplace()
{
m_ctrldown = false; // in case of Ctrl+H
FindReplace(false);
}
void CEditorView::OnUpdateEditFindNext(CCmdUI* pCmdUI)
{
pCmdUI->Enable(m_findtext.length() != 0);
}
void CEditorView::OnEditFindNext()
{
FindNext();
}
void CEditorView::FindReplace(bool findonly)
{
std::string str = SelectedText();
if (!str.empty())
m_findtext = str;
m_pEditorSelection->UnmarkSelection();
m_wasfound = m_found = m_bchanged = false;
delete m_pFindDlg;
m_pFindDlg = new CFindReplaceDialog;
m_pFindDlg->Create(findonly, m_findtext.c_str(), m_replacetext.empty() ? 0 : m_replacetext.c_str(), m_nfrflags, this);
}
void CEditorView::FindNext()
{
m_pEditorSelection->UnmarkSelection();
if (m_nfrflags & FR_DOWN)
FindTextForward();
else
FindTextBackward();
if (m_found) {
int len = m_findtext.length();
m_currentrow = m_findrow;
m_currentcolumn = m_findcol;
if (m_nfrflags & FR_DOWN)
m_currentcolumn += len;
else
m_findcol += len;
m_pEditorSelection->SetMarking(ViewIndex(this, m_findrow, m_findcol));
m_pEditorSelection->ExtendSelection(ViewIndex(this, m_currentrow, m_currentcolumn));
AdjustScrollQuietly();
}
}
LONG CEditorView::OnFindReplace(WPARAM wParam, LPARAM lParam)
{
LPFINDREPLACE fr = (LPFINDREPLACE)lParam;
m_findtext = fr->lpstrFindWhat;
m_replacetext = fr->lpstrReplaceWith;
m_nfrflags = fr->Flags;
if (m_nfrflags & FR_DIALOGTERM) {
m_pFindDlg = 0;
m_wasfound = m_found = m_bchanged = false;
m_nfrflags &= ~FR_DIALOGTERM;
return 0;
}
int saverow = m_currentrow;
int savecol = m_currentcolumn;
if (m_nfrflags & FR_REPLACEALL)
m_currentrow = m_currentcolumn = 0;
bool bterminate = true;
for (;;) {
if (((m_nfrflags & FR_REPLACE) || (m_nfrflags & FR_REPLACEALL)) && m_found) {
assert(m_pEditorSelection->IsSelectionMarked());
ViewIndex start, stop;
m_pEditorSelection->GetSelectionMarkers(start, stop);
m_pEditorSelection->UnmarkSelection();
assert(start.row == stop.row);
assert(start.column < stop.column);
const std::string& line = GetDocument()->textline(start.row);
std::string first = line.substr(0, start.column);
std::string last = line.substr(stop.column, line.length() - stop.column);
std::string mid(m_replacetext);
std::string line1 = first + mid + last;
GetDocument()->replaceline(start.row, line1, bterminate);
m_currentrow = start.row;
m_currentcolumn = start.column + m_replacetext.length();
bterminate = false;
m_bchanged = true;
m_buildcomments = true;
}
else
m_pEditorSelection->UnmarkSelection();
int len = m_findtext.length();
FindNext();
m_wasfound |= m_found;
if (!m_found) {
if (!m_wasfound) {
CString msg("Cannot find \"");
msg += m_findtext.c_str();
msg += '"';
AfxMessageBox(msg, MB_ICONEXCLAMATION);
m_currentrow = saverow;
m_currentcolumn = savecol;
}
break;
}
if (!(m_nfrflags & FR_REPLACEALL))
break;
}
if (m_bchanged)
AdjustScrollQuietly();
return 0;
}
bool CEditorView::isword(const char* cp, int col, int len)
{
if (col == 0 || isspace(cp[col-1]) || ispunct(cp[col-1]))
if (cp[col + len] == '\0' || isspace(cp[col + len]) || ispunct(cp[col + len]))
return true;
return false;
}
void CEditorView::FindTextForward()
{
m_found = false;
m_findrow = m_currentrow;
m_findcol = m_currentcolumn;
int len = m_findtext.length();
while (m_findrow < GetDocument()->linecount()) {
const std::string& line = GetDocument()->textline(m_findrow);
while (m_findcol + len <= line.length()) {
bool whole = (m_nfrflags & FR_WHOLEWORD) != 0;
if ((m_nfrflags & FR_MATCHCASE) == 0) {
if (strnicmp(m_findtext.c_str(), line.c_str() + m_findcol, len) == 0) {
if (!whole || isword(line.c_str(), m_findcol, len)) {
m_found = true;
return;
}
}
}
else if (strncmp(m_findtext.c_str(), line.c_str() + m_findcol, len) == 0) {
if (!whole || isword(line.c_str(), m_findcol, len)) {
m_found = true;
return;
}
}
m_findcol++;
}
m_findcol = 0;
m_findrow++;
}
}
void CEditorView::FindTextBackward()
{
m_found = false;
m_findrow = m_currentrow;
m_findcol = m_currentcolumn;
int len = m_findtext.length();
while (m_findrow >= 0) {
const std::string& line = GetDocument()->textline(m_findrow);
m_findcol -= len;
while (m_findcol >= 0) {
bool whole = (m_nfrflags & FR_WHOLEWORD) != 0;
if ((m_nfrflags & FR_MATCHCASE) == 0) {
if (strnicmp(m_findtext.c_str(), line.c_str() + m_findcol, len) == 0) {
if (!whole || isword(line.c_str(), m_findcol, len)) {
m_found = true;
return;
}
}
}
else if (strncmp(m_findtext.c_str(), line.c_str() + m_findcol, len) == 0) {
if (!whole || isword(line.c_str(), m_findcol, len)) {
m_found = true;
return;
}
}
--m_findcol;
}
if (--m_findrow >= 0)
m_findcol = GetDocument()->textline(m_findrow).length();
}
}
////////////////////////////////////////////////////////
// undo/redo functions
void CEditorView::OnEditUndo()
{
m_buildcomments = true;
m_pEditorSelection->UnmarkSelection();
GetDocument()->OnEditUndo();
}
void CEditorView::OnEditRedo()
{
m_buildcomments = true;
m_pEditorSelection->UnmarkSelection();
GetDocument()->OnEditRedo();
}
BOOL CEditorView::OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message)
{
SetCursor(m_recording ? m_hRecordCursor : m_hArrowCursor);
return true;
}
void CEditorView::OnFileOpen()
{
m_buildcomments = true;
m_ctrldown = false; // in case of Ctrl+O
theApp.OnFileOpen();
}
void CEditorView::OnFilePrint()
{
m_ctrldown = false; // in case of Ctrl+P
CView::OnFilePrint();
}
void CEditorView::OnUpdateFileSaveAll(CCmdUI* pCmdUI)
{
pCmdUI->Enable(true);
}
// ------- brace matching
void CEditorView::OnUpdateBracematch(CCmdUI* pCmdUI)
{
pCmdUI->Enable(IsSourceCodeFile() && CanMatchBraces());
}
void CEditorView::OnUpdateBeautify(CCmdUI* pCmdUI)
{
pCmdUI->Enable(pEditor == 0 && theApp.BeautifierIsInstalled() && IsSourceCodeFile());
}
// --- ensure that brace character is not character or string literal
// and not in a comment
bool CEditorView::IsSpecificBrace(char ch, int row, int col)
{
if (GetDocument()->textchar(row, col) != ch)
return false;
if (col > 0) {
if (IsCharLiteral(row, col))
return false;
if (IsContextElement(row, col))
return false;
}
return true;
}
#ifdef _DEBUG
void CEditorView::DumpContextTable()
{
std::set<CodeElement>::iterator iter;
TRACE("\n -------- Context Table ----------");
for (iter = m_contexttable.begin(); iter != m_contexttable.end(); iter++) {
CodeElement cmt = *iter;
TRACE("\nLine %02d: Char %02d: Clr %06x", cmt.line, cmt.charpos, cmt.color);
}
TRACE("\n -------- End of Context Table ----------\n");
}
#endif
bool CEditorView::IsContextElement(int row, int col)
{
CodeElement ce;
ce.line = row;
ce.charpos = col;
std::set<CodeElement>::const_iterator it = std::lower_bound(m_contexttable.begin(), m_contexttable.end(), ce);
if (it == m_contexttable.end())
return false;
if (it != m_contexttable.begin())
--it;
return (*it).color != theApp.NormalColor();
}
bool CEditorView::IsCharLiteral(int row, int col)
{
const std::string& str = GetDocument()->textline(row);
if (col < str.length()-1) {
if (GetDocument()->textchar(row, col-1) == '\'')
if (GetDocument()->textchar(row, col+1) == '\'')
return true;
}
return false;
}
void CEditorView::Beautify()
{
PageHome();
m_pEditorSelection->UnmarkSelection();
beautifiedtext.clear();
CString strExe = theApp.Enquote(theApp.QuincyBinPath() + "\\astyle.exe ");
CString strArgs(theApp.BeautifierCommand());
delete m_pConsoleApp;
m_pConsoleApp = new ConsoleApp(strExe, &Notify, &Collect);
try {
m_pConsoleApp->Run(strArgs);
int lines = GetDocument()->linecount();
if (lines != 0) {
for (int i = 0; i < lines; i++) {
std::string str = GetDocument()->textline(i);
CEditorDoc::entab(str);
m_pConsoleApp->WriteConsole(str.c_str());
// TRACE("\nOUT: %s", str.c_str());
}
}
char ctrlz[2] = {26,0};
m_pConsoleApp->WriteConsole(ctrlz);
}
catch(...) {
AfxMessageBox("\nCannot execute Astyle", MB_ICONSTOP);
}
}
// --- called from the console application thread while beautifying is going on
void CEditorView::Collect(DWORD bufct)
{
ASSERT(pEditor != 0);
pEditor->CollectSourceLines(bufct);
}
void CEditorView::CollectSourceLines(DWORD bufct)
{
char *line = new char[bufct+1];
ASSERT(m_pConsoleApp);
if (m_pConsoleApp->ReadConsole(line, bufct) != 0) {
// TRACE("\nIN: %s", line);
std::string str(line);
CEditorDoc::detab(str);
beautifiedtext.push_back(str);
}
delete [] line;
}
void CEditorView::Notify()
{
ASSERT(pEditor != 0);
pEditor->NotifyTermination();
}
void CEditorView::NotifyTermination()
{
// TRACE("\n---done---\n");
beautifiedtext.push_back(std::string());
GetDocument()->ReplaceDocument(beautifiedtext);
beautifiedtext.clear();
BuildContextHighlightTable();
Invalidate(TRUE);
delete m_pConsoleApp;
m_pConsoleApp = 0;
pEditor = 0;
}
void CEditorView::OnBeautify()
{
CBeautifier bt;
bt.m_style = theApp.BeautifierStyle();
bt.m_Cmdline = theApp.BeautifierCommand();
if (bt.DoModal() == IDOK) {
pEditor = this;
theApp.SetBeautifierStyle(bt.m_style);
theApp.SetBeautifierCommand(bt.m_Cmdline);
Beautify();
}
}
void CEditorView::OnBracematch()
{
#ifdef _DEBUG
// DumpContextTable();
#endif
// --- these are zero-based
int row = m_currentrow;
int col = m_currentcolumn;
int lines = GetDocument()->linecount();
if (IsLeftBrace(row, col)) {
int nests = 0;
bool bmatch = false;
while (row < lines) {
int len = GetDocument()->textline(row).length();
while (col < len) {
if (IsLeftBrace(row, col))
nests++;
else if (IsRightBrace(row, col)) {
if ((bmatch = --nests == 0) == true)
break;
}
if (bmatch)
break;
col++;
}
if (bmatch)
break;
row++;
col = 0;
}
if (bmatch) {
m_currentrow = row;
m_currentcolumn = col;
AdjustScrollQuietly();
}
else {
AfxMessageBox("No matching '}'", MB_ICONSTOP);
m_ctrldown = false;
}
}
else if (IsRightBrace(row, col)) {
int nests = 0;
bool bmatch = false;
while (row >= 0) {
while (col >= 0) {
if (IsRightBrace(row, col))
nests++;
else if (IsLeftBrace(row, col)) {
if ((bmatch = --nests == 0) == true)
break;
}
if (bmatch)
break;
--col;
}
if (bmatch)
break;
if (--row >= 0)
col = GetDocument()->textline(row).length() - 1;
}
if (bmatch) {
m_currentrow = row;
m_currentcolumn = col;
AdjustScrollQuietly();
}
else
AfxMessageBox("No matching '}'", MB_ICONSTOP);
}
}
// ---- Editor calls this function for every character typed.
// Use the CEditorView and CEditorDoc APIs to extend the editor.
// return true if you don't want Editor to further process the keystroke
bool CEditorView::ExtendEditor(UINT nChar)
{
if (theApp.AutoIndentOption() && nChar == VK_RETURN) {
AutoIndent();
return true;
}
return false;
}
// --- automatic indenting puts insertion caret and any following text
// under leftmost character of previous line after user presses Enter key
void CEditorView::AutoIndent()
{
int lno = CurrentLineNumber(); // one-based line number
ASSERT(lno > 0);
const std::string& line = GetDocument()->textline(lno-1); // zero-based to get current line
SplitLine();
CaretRight();
int len = line.length();
int i;
for (i = 0; i < len; i++)
if (line[i] != '\t' && line[i] != ' ')
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -