Skip to content

Commit 4a05246

Browse files
committed
Merge pull request #106342 from Ivorforce/fix-text-edit-search
Refactor `TextEdit::search` to be more robust to failure.
2 parents d0693d6 + 581e899 commit 4a05246

File tree

2 files changed

+43
-79
lines changed

2 files changed

+43
-79
lines changed

scene/gui/text_edit.cpp

Lines changed: 42 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -212,8 +212,9 @@ float TextEdit::Text::get_indent_offset(int p_line, bool p_rtl) const {
212212
return text_line.indent_ofs;
213213
}
214214

215-
_FORCE_INLINE_ String TextEdit::Text::operator[](int p_line) const {
216-
ERR_FAIL_INDEX_V(p_line, text.size(), "");
215+
_FORCE_INLINE_ const String &TextEdit::Text::operator[](int p_line) const {
216+
static const String empty;
217+
ERR_FAIL_INDEX_V(p_line, text.size(), empty);
217218
return text[p_line].data;
218219
}
219220

@@ -4696,113 +4697,76 @@ void TextEdit::set_search_flags(uint32_t p_flags) {
46964697
}
46974698

46984699
Point2i TextEdit::search(const String &p_key, uint32_t p_search_flags, int p_from_line, int p_from_column) const {
4699-
if (p_key.length() == 0) {
4700+
if (p_key.is_empty()) {
47004701
return Point2(-1, -1);
47014702
}
47024703
ERR_FAIL_INDEX_V(p_from_line, text.size(), Point2i(-1, -1));
47034704
ERR_FAIL_INDEX_V(p_from_column, text[p_from_line].length() + 1, Point2i(-1, -1));
47044705

4705-
// Search through the whole document, but start by current line.
4706-
4707-
int line = p_from_line;
4708-
int pos = -1;
4706+
const bool key_start_is_symbol = is_symbol(p_key[0]);
4707+
const bool key_end_is_symbol = is_symbol(p_key[p_key.length() - 1]);
47094708

4710-
bool key_start_is_symbol = is_symbol(p_key[0]);
4711-
bool key_end_is_symbol = is_symbol(p_key[p_key.length() - 1]);
4709+
// Search the whole document, starting from the current line.
4710+
// We'll auto-wrap through the start / end to search every line.
4711+
int current_line = p_from_line;
4712+
int current_column = p_from_column;
47124713

4714+
// + 1 because we'll search p_from_line twice - starting from p_from_column, and then again at the very end.
47134715
for (int i = 0; i < text.size() + 1; i++) {
4714-
if (line < 0) {
4715-
line = text.size() - 1;
4716-
}
4717-
if (line == text.size()) {
4718-
line = 0;
4719-
}
4720-
4721-
String text_line = text[line];
4722-
int from_column = 0;
4723-
if (line == p_from_line) {
4724-
if (i == text.size()) {
4725-
// Wrapped.
4716+
const String &text_line = text[current_line];
47264717

4727-
if (p_search_flags & SEARCH_BACKWARDS) {
4728-
from_column = text_line.length();
4729-
} else {
4730-
from_column = 0;
4731-
}
4732-
4733-
} else {
4734-
from_column = p_from_column;
4735-
}
4736-
4737-
} else {
4718+
// Search the current line as often as necessary.
4719+
while (true) {
47384720
if (p_search_flags & SEARCH_BACKWARDS) {
4739-
from_column = text_line.length() - 1;
4721+
current_column = (p_search_flags & SEARCH_MATCH_CASE) ? text_line.rfind(p_key, current_column) : text_line.rfindn(p_key, current_column);
47404722
} else {
4741-
from_column = 0;
4723+
current_column = (p_search_flags & SEARCH_MATCH_CASE) ? text_line.find(p_key, current_column) : text_line.findn(p_key, current_column);
47424724
}
4743-
}
47444725

4745-
pos = -1;
4746-
4747-
int pos_from = (p_search_flags & SEARCH_BACKWARDS) ? text_line.length() : 0;
4748-
int last_pos = -1;
4749-
4750-
while (true) {
4751-
if (p_search_flags & SEARCH_BACKWARDS) {
4752-
while ((last_pos = (p_search_flags & SEARCH_MATCH_CASE) ? text_line.rfind(p_key, pos_from) : text_line.rfindn(p_key, pos_from)) != -1) {
4753-
if (last_pos <= from_column) {
4754-
pos = last_pos;
4755-
break;
4756-
}
4757-
pos_from = last_pos - p_key.length();
4758-
if (pos_from < 0) {
4759-
break;
4760-
}
4761-
}
4762-
} else {
4763-
while ((last_pos = (p_search_flags & SEARCH_MATCH_CASE) ? text_line.find(p_key, pos_from) : text_line.findn(p_key, pos_from)) != -1) {
4764-
if (last_pos >= from_column) {
4765-
pos = last_pos;
4766-
break;
4767-
}
4768-
pos_from = last_pos + p_key.length();
4769-
}
4726+
if (current_column == -1) {
4727+
break; // Nothing else found on the current line.
47704728
}
47714729

47724730
bool is_match = true;
47734731

4774-
if (pos != -1 && (p_search_flags & SEARCH_WHOLE_WORDS)) {
4732+
if (p_search_flags & SEARCH_WHOLE_WORDS) {
47754733
// Validate for whole words.
4776-
if (!key_start_is_symbol && pos > 0 && !is_symbol(text_line[pos - 1])) {
4734+
if (!key_start_is_symbol && current_column > 0 && !is_symbol(text_line[current_column - 1])) {
47774735
is_match = false;
4778-
} else if (!key_end_is_symbol && pos + p_key.length() < text_line.length() && !is_symbol(text_line[pos + p_key.length()])) {
4736+
} else if (!key_end_is_symbol && current_column + p_key.length() < text_line.length() && !is_symbol(text_line[current_column + p_key.length()])) {
47794737
is_match = false;
47804738
}
47814739
}
47824740

4783-
if (pos_from == -1) {
4784-
pos = -1;
4741+
if (is_match) {
4742+
// Found the string!
4743+
return Point2i(current_column, current_line);
47854744
}
47864745

4787-
if (is_match || last_pos == -1 || pos == -1) {
4788-
break;
4789-
}
4790-
4791-
pos_from = (p_search_flags & SEARCH_BACKWARDS) ? pos - 1 : pos + 1;
4792-
pos = -1;
4793-
}
4794-
4795-
if (pos != -1) {
4796-
break;
4746+
// Advance past the current occurrence.
4747+
current_column += p_search_flags & SEARCH_BACKWARDS ? -1 : 1;
47974748
}
47984749

4750+
// Prepare for next iteration.
47994751
if (p_search_flags & SEARCH_BACKWARDS) {
4800-
line--;
4752+
current_column = -1;
4753+
current_line--;
4754+
if (current_line < 0) {
4755+
// Searched the whole document backwards; wrap to end.
4756+
current_line = text.size() - 1;
4757+
}
48014758
} else {
4802-
line++;
4759+
current_line++;
4760+
current_column = 0;
4761+
if (current_line == text.size()) {
4762+
// Searched the whole document forwards; wrap to start.
4763+
current_line = 0;
4764+
}
48034765
}
48044766
}
4805-
return (pos == -1) ? Point2i(-1, -1) : Point2i(pos, line);
4767+
4768+
// Nothing found!
4769+
return Point2i(-1, -1);
48064770
}
48074771

48084772
/* Mouse */

scene/gui/text_edit.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,7 @@ class TextEdit : public Control {
256256
void invalidate_all();
257257
void invalidate_all_lines();
258258

259-
_FORCE_INLINE_ String operator[](int p_line) const;
259+
_FORCE_INLINE_ const String &operator[](int p_line) const;
260260
_FORCE_INLINE_ const String &get_text_with_ime(int p_line) const;
261261

262262
/* Gutters. */

0 commit comments

Comments
 (0)