void SmartIndentPascal::DoUnIndent(cbEditor* ed, const wxString& WXUNUSED(langname)) const { cbStyledTextCtrl* stc = ed->GetControl(); wxString str = stc->GetLine(stc->GetCurrentLine()).Lower(); str.Trim(false); str.Trim(true); int pos = stc->GetCurrentPos() - 4; if ( str.Matches( wxT("end")) ) pos = FindBlockStart(stc, pos, wxT("begin"), wxT("end"), false ); else pos = -1; if (pos != -1) { wxString indent = ed->GetLineIndentString(stc->LineFromPosition(pos)); indent += str; stc->BeginUndoAction(); stc->DelLineLeft(); stc->DelLineRight(); pos = stc->GetCurrentPos(); stc->InsertText(pos, indent); stc->GotoPos(pos + indent.Length()); stc->ChooseCaretX(); stc->EndUndoAction(); } }
void CodeEditor::OnCharAdded(wxScintillaEvent &event) { char ch = event.GetKey(); int currentLine = GetCurrentLine(); int pos = GetCurrentPos(); if (ch == wxT('\n') && currentLine > 0) { BeginUndoAction(); wxString indent = GetLineIndentString(currentLine - 1); wxChar b = GetLastNonWhitespaceChar(); if(b == wxT('{')) { if(GetUseTabs()) indent << wxT("\t"); else indent << wxT(" "); } InsertText(pos, indent); GotoPos((int)(pos + indent.Length())); ChooseCaretX(); EndUndoAction(); } else if(ch == wxT('}')) { BeginUndoAction(); wxString line = GetLine(currentLine); line.Trim(false); line.Trim(true); if(line.Matches(wxT("}"))) { pos = GetCurrentPos() - 2; pos = FindBlockStart(pos, wxT('{'), wxT('}')); if(pos != -1) { wxString indent = GetLineIndentString(LineFromPosition(pos)); indent << wxT('}'); DelLineLeft(); DelLineRight(); pos = GetCurrentPos(); InsertText(pos, indent); GotoPos((int)(pos + indent.Length())); ChooseCaretX(); } } EndUndoAction(); } }
void SmartIndentCpp::DoSmartIndent(cbEditor* ed, const wxChar &ch)const { static bool autoIndentStart = false; static bool autoIndentDone = true; static int autoIndentLine = -1; static int autoIndentLineIndent = -1; static bool autoUnIndent = false; // for public: / case: / etc.. static int autoUnIndentValue = -1; static int autoUnIndentLine = -1; cbStyledTextCtrl* stc = ed->GetControl(); const int pos = stc->GetCurrentPos(); // indent if ( (ch == _T('\n')) || ( (stc->GetEOLMode() == wxSCI_EOL_CR) && (ch == _T('\r')) ) ) { stc->BeginUndoAction(); // new-line: adjust indentation bool autoIndent = AutoIndentEnabled(); bool smartIndent = SmartIndentEnabled(); int currLine = stc->LineFromPosition(pos); if (autoIndent && currLine > 0) { wxString indent; if (stc->GetCurLine().Trim().IsEmpty()) { // copy the indentation of the last non-empty line for (int i = currLine - 1; i >= 0; --i) { const wxString& prevLineStr = stc->GetLine(i); if (!(prevLineStr.IsEmpty() || prevLineStr[0] == _T('\n') || prevLineStr[0] == _T('\r'))) { indent = ed->GetLineIndentString(i); break; } } } else indent = ed->GetLineIndentString(currLine - 1); if (smartIndent) { wxChar b = GetLastNonWhitespaceChar(ed); // if the last entered char before newline was an opening curly brace, // increase indentation level (the closing brace is handled in another block) if (!BraceIndent(stc, indent)) { if (b == _T('{')) { int nonblankpos; wxChar c = GetNextNonWhitespaceCharOfLine(stc, pos, &nonblankpos); if ( c != _T('}') ) Indent(stc, indent); else { if ( pos != nonblankpos ) { stc->SetCurrentPos(nonblankpos); stc->DeleteBack(); } } } else if (b == _T(':')) Indent(stc, indent); } } stc->InsertText(pos, indent); stc->GotoPos(pos + indent.Length()); stc->ChooseCaretX(); } // smart indent if (smartIndent && currLine > 0) { if (!autoIndentDone) { bool valid = true; int line = stc->GetCurrentLine(); if (line < autoIndentLine) valid = false; else { while (--line > autoIndentLine) { if (stc->GetLineIndentation(line) < autoIndentLineIndent) { valid = false; break; } } } if (!valid) { autoIndentStart = false; autoIndentDone = true; autoIndentLine = -1; autoIndentLineIndent = -1; } } if (autoIndentDone) { const int ind_pos = stc->GetLineIndentPosition(currLine - 1); const wxString text = stc->GetTextRange(ind_pos, stc->WordEndPosition(ind_pos, true)); if ( text == _T("if") || text == _T("else") || text == _T("for") || text == _T("while") || text == _T("do") ) { const wxChar non_ws_ch = GetLastNonWhitespaceChar(ed); if (non_ws_ch != _T(';') && non_ws_ch != _T('}')) { autoIndentDone = false; autoIndentLine = currLine - 1; autoIndentLineIndent = stc->GetLineIndentation(currLine - 1); } } } if (!autoIndentDone) { if (autoIndentStart) { const wxChar non_ws_ch = GetLastNonWhitespaceChar(ed); if (non_ws_ch == _T(';') || non_ws_ch == _T('}')) { stc->SetLineIndentation(currLine, autoIndentLineIndent); stc->GotoPos(stc->GetLineEndPosition(currLine)); autoIndentStart = false; autoIndentDone = true; autoIndentLine = -1; autoIndentLineIndent = -1; } } else { int lastLine = currLine; while (--lastLine >= 0) { const int lineIndentPos = stc->GetLineIndentPosition(lastLine); const int start = stc->WordStartPosition(lineIndentPos, true); const int end = stc->WordEndPosition(lineIndentPos, true); const wxString last = stc->GetTextRange(start, end); if ( last == _T("if") || last == _T("else") || last == _T("for") || last == _T("while") || last == _T("do") ) { const wxString text = stc->GetTextRange(lineIndentPos + last.Len(), pos); int level = 0; for (size_t i = 0; i < text.Len(); ++i) { if (text[i] == _T('(')) { const int style = stc->GetStyleAt(pos - text.Len() + i); if ( stc->IsString(style) || stc->IsCharacter(style) || stc->IsComment(style) ) { continue; } ++level; } else if (text[i] == _T(')')) { const int style = stc->GetStyleAt(pos - text.Len() + i); if ( stc->IsString(style) || stc->IsCharacter(style) || stc->IsComment(style) ) { continue; } --level; } } if (!level) { autoIndentStart = true; int nonblankpos; wxChar c = GetNextNonWhitespaceCharOfLine(stc, pos, &nonblankpos); if (c == _T('}') && currLine == stc->LineFromPosition(nonblankpos)) { stc->NewLine(); stc->GotoPos(pos); autoIndentStart = false; autoIndentDone = true; autoIndentLine = -1; autoIndentLineIndent = -1; } stc->Tab(); } break; } } } } // smart un-indent if (autoUnIndent) { if ( GetLastNonWhitespaceChar(ed) == _T(':')) { stc->SetLineIndentation(autoUnIndentLine, autoUnIndentValue); stc->SetLineIndentation(currLine, autoUnIndentValue); stc->Tab(); } autoUnIndent = false; autoUnIndentValue = -1; autoUnIndentLine = -1; } } stc->EndUndoAction(); } // unindent else if (ch == _T('{')) { if (autoIndentStart) { bool valid = true; const int start = stc->PositionFromLine(autoIndentLine); const wxString text = stc->GetTextRange(start, pos); if (text.Find(_T('{')) != int(text.Len() - 1)) valid = false; else { int line = stc->GetCurrentLine(); if (line < autoIndentLine) valid = false; else { while (--line > autoIndentLine) { if (stc->GetLineIndentation(line) < autoIndentLineIndent) { valid = false; break; } } } } if (valid) { stc->BeginUndoAction(); stc->SetLineIndentation(stc->GetCurrentLine(), autoIndentLineIndent); stc->EndUndoAction(); } autoIndentStart = false; autoIndentDone = true; autoIndentLine = -1; autoIndentLineIndent = -1; } } // unindent else if (ch == _T('}')) { bool smartIndent = Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/smart_indent"), true); if ( smartIndent && ( (stc->GetLexer() == wxSCI_LEX_CPP) || (stc->GetLexer() == wxSCI_LEX_D) ) ) { stc->BeginUndoAction(); // undo block indentation, if needed wxString str = stc->GetLine(stc->GetCurrentLine()); str.Trim(false); str.Trim(true); if (str.Matches(_T("}"))) { // just the brace here; unindent // find opening brace (skipping nested blocks) int cur_pos = stc->GetCurrentPos() - 2; cur_pos = FindBlockStart(stc, cur_pos, _T('{'), _T('}')); if (cur_pos != -1) { wxString indent = ed->GetLineIndentString(stc->LineFromPosition(cur_pos)); indent << _T('}'); stc->DelLineLeft(); stc->DelLineRight(); cur_pos = stc->GetCurrentPos(); stc->InsertText(cur_pos, indent); stc->GotoPos(cur_pos + indent.Length()); stc->ChooseCaretX(); } } stc->EndUndoAction(); } } // unindent else if (ch == _T(':')) { bool smartIndent = Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/smart_indent"), true); if (smartIndent && stc->GetLexer() == wxSCI_LEX_CPP && !autoUnIndent) { const int curLine = stc->GetCurrentLine(); const int li_pos = stc->GetLineIndentPosition(curLine); const wxString text = stc->GetTextRange(li_pos, stc->WordEndPosition(li_pos, true)); if ( text == _T("public") || text == _T("protected") || text == _T("private") || text == _T("case") || text == _T("default") ) { const bool isSwitch = (text == _T("case") || text == _T("default")); int lastLine = curLine; int lastLineIndent = -1; while (--lastLine >= 0) { const int lineIndentPos = stc->GetLineIndentPosition(lastLine); const int start = stc->WordStartPosition(lineIndentPos, true); const int end = stc->WordEndPosition(lineIndentPos, true); const wxString last = stc->GetTextRange(start, end); if (last.IsEmpty()) continue; if (isSwitch) { if (last == _T("case")) { lastLineIndent = stc->GetLineIndentation(lastLine); break; } else if (last == _T("switch")) break; } else { if ( last == _T("public") || last == _T("protected") || last == _T("private") ) { lastLineIndent = stc->GetLineIndentation(lastLine); break; } else if (last == _T("class")) break; } } if (lastLineIndent != -1) { autoUnIndent = true; autoUnIndentValue = lastLineIndent; autoUnIndentLine = curLine; } else { const int curLineIndent = stc->GetLineIndentation(curLine); const int tabWidth = stc->GetTabWidth(); if (curLineIndent >= tabWidth) { autoUnIndent = true; autoUnIndentValue = curLineIndent - tabWidth; autoUnIndentLine = curLine; } } } } } }