diff --git a/editor/code_editor.cpp b/editor/code_editor.cpp index 7e07e626b13a..5f2338e8fbb8 100644 --- a/editor/code_editor.cpp +++ b/editor/code_editor.cpp @@ -347,18 +347,18 @@ void FindReplaceBar::_replace_all() { needs_to_count_results = true; } -void FindReplaceBar::_get_search_from(int &r_line, int &r_col, bool p_is_searching_next) { +void FindReplaceBar::_get_search_from(int &r_line, int &r_col, SearchMode p_search_mode) { if (!text_editor->has_selection(0) || is_selection_only()) { r_line = text_editor->get_caret_line(0); r_col = text_editor->get_caret_column(0); - if (!p_is_searching_next && r_line == result_line && r_col >= result_col && r_col <= result_col + get_search_text().length()) { + if (p_search_mode == SEARCH_PREV && r_line == result_line && r_col >= result_col && r_col <= result_col + get_search_text().length()) { r_col = result_col; } return; } - if (p_is_searching_next) { + if (p_search_mode == SEARCH_NEXT) { r_line = text_editor->get_selection_to_line(); r_col = text_editor->get_selection_to_column(); } else { @@ -368,7 +368,11 @@ void FindReplaceBar::_get_search_from(int &r_line, int &r_col, bool p_is_searchi } void FindReplaceBar::_update_results_count() { - if (!needs_to_count_results && (result_line != -1) && results_count_to_current > 0) { + int caret_line, caret_column; + _get_search_from(caret_line, caret_column, SEARCH_CURRENT); + bool match_selected = caret_line == result_line && caret_column == result_col && !is_selection_only() && text_editor->has_selection(0); + + if (match_selected && !needs_to_count_results && result_line != -1 && results_count_to_current > 0) { results_count_to_current += (flags & TextEdit::SEARCH_BACKWARDS) ? -1 : 1; if (results_count_to_current > results_count) { @@ -385,9 +389,10 @@ void FindReplaceBar::_update_results_count() { return; } - needs_to_count_results = false; + needs_to_count_results = !match_selected; results_count = 0; + results_count_to_current = 0; for (int i = 0; i < text_editor->get_line_count(); i++) { String line_text = text_editor->get_line(i); @@ -417,18 +422,26 @@ void FindReplaceBar::_update_results_count() { results_count++; - if (i == result_line) { - if (col_pos == result_col) { - results_count_to_current = results_count; - } else if (col_pos < result_col && col_pos + searched.length() > result_col) { - col_pos = result_col; - results_count_to_current = results_count; - } + if (i <= result_line && col_pos <= result_col) { + results_count_to_current = results_count; + } + if (i == result_line && col_pos < result_col && col_pos + searched.length() > result_col) { + // Searching forwards and backwards with repeating text can lead to different matches. + col_pos = result_col; } - col_pos += searched.length(); } } + if (!match_selected) { + // Current result should refer to the match before the caret, if the caret is not on a match. + if (caret_line != result_line || caret_column != result_col) { + results_count_to_current -= 1; + } + if (results_count_to_current == 0 && (caret_line > result_line || (caret_line == result_line && caret_column > result_col))) { + // Caret is after all matches. + results_count_to_current = results_count; + } + } } void FindReplaceBar::_update_matches_display() { @@ -457,7 +470,7 @@ bool FindReplaceBar::search_current() { _update_flags(false); int line, col; - _get_search_from(line, col); + _get_search_from(line, col, SEARCH_CURRENT); return _search(flags, line, col); } @@ -473,10 +486,14 @@ bool FindReplaceBar::search_prev() { String text = get_search_text(); + if ((flags & TextEdit::SEARCH_BACKWARDS) == 0) { + needs_to_count_results = true; + } + _update_flags(true); int line, col; - _get_search_from(line, col); + _get_search_from(line, col, SEARCH_PREV); col -= text.length(); if (col < 0) { @@ -499,10 +516,14 @@ bool FindReplaceBar::search_next() { popup_search(true); } + if (flags & TextEdit::SEARCH_BACKWARDS) { + needs_to_count_results = true; + } + _update_flags(false); int line, col; - _get_search_from(line, col, true); + _get_search_from(line, col, SEARCH_NEXT); return _search(flags, line, col); } diff --git a/editor/code_editor.h b/editor/code_editor.h index af33a3fac873..28f6944b6699 100644 --- a/editor/code_editor.h +++ b/editor/code_editor.h @@ -64,6 +64,12 @@ class CodeTextEditor; class FindReplaceBar : public HBoxContainer { GDCLASS(FindReplaceBar, HBoxContainer); + enum SearchMode { + SEARCH_CURRENT, + SEARCH_NEXT, + SEARCH_PREV, + }; + LineEdit *search_text = nullptr; Label *matches_label = nullptr; Button *find_prev = nullptr; @@ -94,7 +100,7 @@ class FindReplaceBar : public HBoxContainer { bool replace_all_mode = false; bool preserve_cursor = false; - void _get_search_from(int &r_line, int &r_col, bool p_is_searching_next = false); + void _get_search_from(int &r_line, int &r_col, SearchMode p_search_mode); void _update_results_count(); void _update_matches_display();