void SmartIndentCpp::OnEditorHook(cbEditor* ed, wxScintillaEvent& event) const { // check if smart indent is enabled // check the event type and the currently set language // if it is not a CharAdded event or the language is not C/C++, D, or Java return if (!ed) return; if ( !SmartIndentEnabled() ) return; wxEventType type = event.GetEventType(); if ( type != wxEVT_SCI_CHARADDED ) return; cbStyledTextCtrl* stc = ed->GetControl(); if (!stc) return; wxString langname = Manager::Get()->GetEditorManager()->GetColourSet()->GetLanguageName(ed->GetLanguage()); if ( langname != wxT("D") && (stc->GetLexer() != wxSCI_LEX_CPP || langname == wxT("Hitachi asm"))) return; ed->AutoIndentDone(); // we are responsible. const int pos = stc->GetCurrentPos(); int currLine = stc->LineFromPosition(pos); if (currLine == 0) return; const wxChar ch = event.GetKey(); if ( SelectionBraceCompletionEnabled() || stc->IsBraceShortcutActive() ) DoSelectionBraceCompletion(stc, ch); DoSmartIndent(ed, ch); if ( BraceCompletionEnabled() ) DoBraceCompletion(stc, ch); }
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; } } } } } }
void SmartIndentFortran::OnEditorHook(cbEditor* ed, wxScintillaEvent& event) const { // check if smart indent is enabled // check the event type and the currently set language // if it is not a CharAdded event or the language is not Fortran return if (!ed) return; if ( !SmartIndentEnabled() ) return; wxEventType type = event.GetEventType(); if ( type != wxEVT_SCI_CHARADDED ) return; cbStyledTextCtrl* stc = ed->GetControl(); if (!stc) return; wxString langname = Manager::Get()->GetEditorManager()->GetColourSet()->GetLanguageName(ed->GetLanguage()); if ( langname != wxT("Fortran") && langname != wxT("Fortran77") ) return; ed->AutoIndentDone(); // we are responsible. const int pos = stc->GetCurrentPos(); wxChar ch = event.GetKey(); if ( (ch == _T('\n')) || ( (stc->GetEOLMode() == wxSCI_EOL_CR) && (ch == _T('\r')) ) ) { const bool autoIndent = AutoIndentEnabled(); stc->BeginUndoAction(); int currLine = stc->LineFromPosition(pos); // auto indent if (autoIndent && currLine > 0) { wxString indent = ed->GetLineIndentString(currLine - 1); stc->InsertText(pos, indent); stc->GotoPos(pos + indent.Length()); stc->ChooseCaretX(); } // smart indent bool smartIndent = SmartIndentEnabled(); if (smartIndent && currLine > 0) { int start = stc->GetLineIndentPosition(currLine - 1); int endt = stc->WordEndPosition(start, true); wxString text = stc->GetTextRange(start, endt).Lower(); wxString lineText = stc->GetLine(currLine - 1).BeforeFirst('!').Lower(); wxString lastText = lineText.AfterLast(')').Trim().Trim(false); wxString secText = lineText.Trim(false).Mid(text.Length()).Trim(false); if ( (text == _T("if") && lastText == _T("then")) || text == _T("else") || text == _T("elseif") || text == _T("enum") ||(text == _T("where") && lastText.IsEmpty()) || text == _T("elsewhere") || text == _T("block") || text == _T("blockdata") ||(text == _T("forall") && lastText.IsEmpty()) || text == _T("while") || text == _T("case") || text == _T("associate") || text == _T("block") || text == _T("critical") || text == _T("do") ||(text == _T("type") && !secText.StartsWith(_T("("))) || text == _T("program") || text == _T("function") || text == _T("subroutine") || text == _T("interface") ||( text == _T("module") && !secText.StartsWith(_T("procedure ")) && !secText.StartsWith(_T("procedure:")) ) ) { stc->Tab(); } } stc->EndUndoAction(); } bool braceCompleted = false; if ( SelectionBraceCompletionEnabled() || stc->IsBraceShortcutActive() ) braceCompleted = stc->DoSelectionBraceCompletion(ch); if (!braceCompleted && BraceCompletionEnabled()) stc->DoBraceCompletion(ch); }