1
0
mirror of synced 2024-11-12 02:00:52 +01:00

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:
paxcut 2024-09-15 06:32:10 -07:00 committed by GitHub
parent 866b956680
commit 96a588bd86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 75 additions and 27 deletions

View File

@ -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);

View File

@ -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) {