fix: F3 failed to locate the correct set of matches if file was edited after doing a search (#1867)
### Problem description The bug can be reproduced as follows: 1) Using Ctrl-F do a search for a term that occurs several times in the file. and press F3 to visit them. 2) Go back to the fop of the file and insert 3 blank lines. 3) Pressing F3 once or many times will not find the term entered above. ### Implementation description The reason for this bug is that the positions of the matches are not being reset when changes can potentially move them. The fix consists on resetting the search locations when changing the contents of the file and redoing the search after the changes are made. The bug was specially problematic when doing replace because the replacement position would be identified as a match. This PR fixes replace as well. --------- Co-authored-by: Nik <werwolv98@gmail.com>
This commit is contained in:
parent
866b956680
commit
96a588bd86
@ -275,7 +275,7 @@ public:
|
||||
|
||||
ImVec2 &GetCharAdvance() { return mCharAdvance; }
|
||||
|
||||
bool CanUndo() const;
|
||||
bool CanUndo();
|
||||
bool CanRedo() const;
|
||||
void Undo(int aSteps = 1);
|
||||
void Redo(int aSteps = 1);
|
||||
|
@ -794,7 +794,8 @@ void TextEditor::HandleMouseInputs() {
|
||||
mSelectionMode = SelectionMode::Normal;
|
||||
}
|
||||
SetSelection(mInteractiveStart, mInteractiveEnd, mSelectionMode);
|
||||
resetBlinking=true;
|
||||
ResetCursorBlinkTime();
|
||||
|
||||
EnsureCursorVisible();
|
||||
mLastClick = (float)ImGui::GetTime();
|
||||
}
|
||||
@ -1412,6 +1413,13 @@ void TextEditor::EnterCharacter(ImWchar aChar, bool aShift) {
|
||||
AddUndo(u);
|
||||
|
||||
Colorize(coord.mLine - 1, 3);
|
||||
|
||||
std::string findWord = mFindReplaceHandler.GetFindWord();
|
||||
if (!findWord.empty()) {
|
||||
mFindReplaceHandler.resetMatches();
|
||||
mFindReplaceHandler.FindAllMatches(this, findWord);
|
||||
}
|
||||
|
||||
EnsureCursorVisible();
|
||||
}
|
||||
|
||||
@ -1499,6 +1507,12 @@ void TextEditor::InsertText(const char *aValue) {
|
||||
|
||||
SetSelection(pos, pos);
|
||||
SetCursorPosition(pos);
|
||||
|
||||
std::string findWord = mFindReplaceHandler.GetFindWord();
|
||||
if (!findWord.empty()) {
|
||||
mFindReplaceHandler.resetMatches();
|
||||
mFindReplaceHandler.FindAllMatches(this, findWord);
|
||||
}
|
||||
Colorize(start.mLine - 1, totalLines + 2);
|
||||
}
|
||||
|
||||
@ -1512,6 +1526,11 @@ void TextEditor::DeleteSelection() {
|
||||
|
||||
SetSelection(mState.mSelectionStart, mState.mSelectionStart);
|
||||
SetCursorPosition(mState.mSelectionStart);
|
||||
std::string findWord = mFindReplaceHandler.GetFindWord();
|
||||
if (!findWord.empty()) {
|
||||
mFindReplaceHandler.resetMatches();
|
||||
mFindReplaceHandler.FindAllMatches(this, findWord);
|
||||
}
|
||||
Colorize(mState.mSelectionStart.mLine, 1);
|
||||
}
|
||||
|
||||
@ -1798,6 +1817,11 @@ void TextEditor::Delete() {
|
||||
|
||||
u.mAfter = mState;
|
||||
AddUndo(u);
|
||||
std::string findWord = mFindReplaceHandler.GetFindWord();
|
||||
if (!findWord.empty()) {
|
||||
mFindReplaceHandler.resetMatches();
|
||||
mFindReplaceHandler.FindAllMatches(this, findWord);
|
||||
}
|
||||
}
|
||||
|
||||
void TextEditor::Backspace() {
|
||||
@ -1866,6 +1890,11 @@ void TextEditor::Backspace() {
|
||||
|
||||
u.mAfter = mState;
|
||||
AddUndo(u);
|
||||
std::string findWord = mFindReplaceHandler.GetFindWord();
|
||||
if (!findWord.empty()) {
|
||||
mFindReplaceHandler.resetMatches();
|
||||
mFindReplaceHandler.FindAllMatches(this, findWord);
|
||||
}
|
||||
}
|
||||
|
||||
void TextEditor::SelectWordUnderCursor() {
|
||||
@ -1913,6 +1942,11 @@ void TextEditor::Cut() {
|
||||
AddUndo(u);
|
||||
}
|
||||
}
|
||||
std::string findWord = mFindReplaceHandler.GetFindWord();
|
||||
if (!findWord.empty()) {
|
||||
mFindReplaceHandler.resetMatches();
|
||||
mFindReplaceHandler.FindAllMatches(this, findWord);
|
||||
}
|
||||
}
|
||||
|
||||
void TextEditor::Paste() {
|
||||
@ -1940,9 +1974,14 @@ void TextEditor::Paste() {
|
||||
u.mAfter = mState;
|
||||
AddUndo(u);
|
||||
}
|
||||
std::string findWord = mFindReplaceHandler.GetFindWord();
|
||||
if (!findWord.empty()) {
|
||||
mFindReplaceHandler.resetMatches();
|
||||
mFindReplaceHandler.FindAllMatches(this, findWord);
|
||||
}
|
||||
}
|
||||
|
||||
bool TextEditor::CanUndo() const {
|
||||
bool TextEditor::CanUndo() {
|
||||
return !mReadOnly && mUndoIndex > 0;
|
||||
}
|
||||
|
||||
@ -1953,11 +1992,21 @@ bool TextEditor::CanRedo() const {
|
||||
void TextEditor::Undo(int aSteps) {
|
||||
while (CanUndo() && aSteps-- > 0)
|
||||
mUndoBuffer[--mUndoIndex].Undo(this);
|
||||
std::string findWord = mFindReplaceHandler.GetFindWord();
|
||||
if (!findWord.empty()) {
|
||||
mFindReplaceHandler.resetMatches();
|
||||
mFindReplaceHandler.FindAllMatches(this, findWord);
|
||||
}
|
||||
}
|
||||
|
||||
void TextEditor::Redo(int aSteps) {
|
||||
while (CanRedo() && aSteps-- > 0)
|
||||
mUndoBuffer[mUndoIndex++].Redo(this);
|
||||
std::string findWord = mFindReplaceHandler.GetFindWord();
|
||||
if (!findWord.empty()) {
|
||||
mFindReplaceHandler.resetMatches();
|
||||
mFindReplaceHandler.FindAllMatches(this, findWord);
|
||||
}
|
||||
}
|
||||
|
||||
// the index here is array index so zero based
|
||||
@ -2096,7 +2145,7 @@ bool TextEditor::FindReplaceHandler::FindNext(TextEditor *editor, bool wrapAroun
|
||||
curPos.mLine = mMatches.empty() ? editor->mState.mCursorPosition.mLine : mMatches.back().mCursorPosition.mLine;
|
||||
curPos.mColumn = mMatches.empty() ? editor->mState.mCursorPosition.mColumn : editor->Utf8CharsToBytes(
|
||||
mMatches.back().mCursorPosition);
|
||||
|
||||
|
||||
unsigned long selectionLength = editor->GetStringCharacterCount(mFindWord);
|
||||
size_t byteIndex = 0;
|
||||
|
||||
@ -2123,13 +2172,13 @@ bool TextEditor::FindReplaceHandler::FindNext(TextEditor *editor, bool wrapAroun
|
||||
if (GetFindRegEx()) {
|
||||
try {
|
||||
regularExpression.assign(wordLower);
|
||||
} catch (std::regex_error &e) {
|
||||
} catch (const std::regex_error &e) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
try {
|
||||
regularExpression.assign(make_wholeWord(wordLower));
|
||||
} catch (std::regex_error &e) {
|
||||
} catch (const std::regex_error &e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@ -2159,10 +2208,8 @@ bool TextEditor::FindReplaceHandler::FindNext(TextEditor *editor, bool wrapAroun
|
||||
|
||||
textLoc = pos;
|
||||
if (wrapAround) {
|
||||
if (iter == end) {
|
||||
pos = firstLoc;
|
||||
if (iter == end)
|
||||
selectionLength = firstLength;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// non regex search
|
||||
@ -2203,16 +2250,18 @@ bool TextEditor::FindReplaceHandler::FindNext(TextEditor *editor, bool wrapAroun
|
||||
selStart.mColumn = editor->Utf8BytesToChars(curPos);
|
||||
selEnd = selStart;
|
||||
selEnd.mColumn += selectionLength;
|
||||
editor->SetSelection(selStart, selEnd);
|
||||
editor->SetCursorPosition(selEnd);
|
||||
editor->mScrollToCursor = true;
|
||||
TextEditor::EditorState state;
|
||||
state.mSelectionStart = selStart;
|
||||
state.mSelectionEnd = selEnd;
|
||||
state.mCursorPosition = selEnd;
|
||||
mMatches.push_back(state);
|
||||
return true;
|
||||
}
|
||||
|
||||
void TextEditor::FindReplaceHandler::FindAllMatches(TextEditor *editor,std::string findWord) {
|
||||
|
||||
if (findWord.empty()) {
|
||||
editor->mScrollToCursor = true;
|
||||
editor->EnsureCursorVisible();
|
||||
mFindWord = "";
|
||||
mMatches.clear();
|
||||
return;
|
||||
@ -2227,32 +2276,30 @@ void TextEditor::FindReplaceHandler::FindAllMatches(TextEditor *editor,std::stri
|
||||
mMatches.clear();
|
||||
mFindWord = findWord;
|
||||
auto startingPos = editor->mState.mCursorPosition;
|
||||
auto state = editor->mState;
|
||||
auto saveState = editor->mState;
|
||||
Coordinates begin = Coordinates(0,0);
|
||||
editor->mState.mCursorPosition = begin;
|
||||
|
||||
if (!FindNext(editor,false)) {
|
||||
editor->mState = state;
|
||||
editor->mScrollToCursor = true;
|
||||
editor->mState = saveState;
|
||||
editor->EnsureCursorVisible();
|
||||
return;
|
||||
}
|
||||
auto initialPos = editor->mState.mCursorPosition;
|
||||
mMatches.push_back(editor->mState);
|
||||
TextEditor::EditorState state = mMatches.back();
|
||||
|
||||
while( editor->mState.mCursorPosition < startingPos) {
|
||||
while( state.mCursorPosition < startingPos) {
|
||||
if (!FindNext(editor,false)) {
|
||||
editor->mState = state;
|
||||
editor->mScrollToCursor = true;
|
||||
editor->mState = saveState;
|
||||
editor->EnsureCursorVisible();
|
||||
return;
|
||||
}
|
||||
mMatches.push_back(editor->mState);
|
||||
state = mMatches.back();
|
||||
}
|
||||
|
||||
while (FindNext(editor,false))
|
||||
mMatches.push_back(editor->mState);
|
||||
while (FindNext(editor,false));
|
||||
|
||||
editor->mState = state;
|
||||
editor->mScrollToCursor = true;
|
||||
editor->mState = saveState;
|
||||
editor->EnsureCursorVisible();
|
||||
return;
|
||||
}
|
||||
|
||||
@ -2299,7 +2346,7 @@ bool TextEditor::FindReplaceHandler::Replace(TextEditor *editor, bool next) {
|
||||
|
||||
u.mAddedEnd = editor->GetActualCursorCoordinates();
|
||||
|
||||
editor->mScrollToCursor = true;
|
||||
editor->EnsureCursorVisible();
|
||||
ImGui::SetKeyboardFocusHere(0);
|
||||
|
||||
u.mAfter = editor->mState;
|
||||
@ -2885,6 +2932,7 @@ void TextEditor::UndoRecord::Redo(TextEditor *aEditor) {
|
||||
|
||||
aEditor->mState = mAfter;
|
||||
aEditor->EnsureCursorVisible();
|
||||
|
||||
}
|
||||
|
||||
bool TokenizeCStyleString(const char *in_begin, const char *in_end, const char *&out_begin, const char *&out_end) {
|
||||
|
Loading…
Reference in New Issue
Block a user