From e27d1a94c9bf3ead4ef979cbc12624abb524c339 Mon Sep 17 00:00:00 2001 From: Udo Hoffmann Date: Wed, 20 May 2020 17:23:42 +0200 Subject: [PATCH] Prevent suggestion of autocompletion while word modifying Fix #330, close #8297 --- .../src/ScitillaComponent/AutoCompletion.cpp | 61 ++++++++++++++----- .../src/ScitillaComponent/AutoCompletion.h | 2 +- 2 files changed, 48 insertions(+), 15 deletions(-) diff --git a/PowerEditor/src/ScitillaComponent/AutoCompletion.cpp b/PowerEditor/src/ScitillaComponent/AutoCompletion.cpp index e661d2701..336b978a8 100644 --- a/PowerEditor/src/ScitillaComponent/AutoCompletion.cpp +++ b/PowerEditor/src/ScitillaComponent/AutoCompletion.cpp @@ -77,24 +77,37 @@ bool AutoCompletion::showApiComplete() bool AutoCompletion::showApiAndWordComplete() { + + // Get beginning of word and complete word + auto curPos = _pEditView->execute(SCI_GETCURRENTPOS); auto startPos = _pEditView->execute(SCI_WORDSTARTPOSITION, curPos, true); + auto endPos = _pEditView->execute(SCI_WORDENDPOSITION, curPos, true); if (curPos == startPos) return false; const size_t bufSize = 256; TCHAR beginChars[bufSize]; + TCHAR allChars[bufSize]; size_t len = (curPos > startPos)?(curPos - startPos):(startPos - curPos); if (len >= bufSize) return false; - // Get word array - vector wordArray; - _pEditView->getGenericText(beginChars, bufSize, startPos, curPos); + size_t lena = (endPos > startPos)?(endPos - startPos):(startPos - endPos); + if (lena >= bufSize) + return false; - getWordArray(wordArray, beginChars); + _pEditView->getGenericText(beginChars, bufSize, startPos, curPos); + _pEditView->getGenericText(allChars, bufSize, startPos, endPos); + + // Get word array containing all words beginning with beginChars, excluding word equal to allChars + + vector wordArray; + getWordArray(wordArray, beginChars, allChars); + + // Add keywords to word array bool canStop = false; for (size_t i = 0, kwlen = _keyWordArray.size(); i < kwlen; ++i) @@ -112,9 +125,10 @@ bool AutoCompletion::showApiAndWordComplete() } } + // Sort word array and convert it to a single string with space-separated words + sort(wordArray.begin(), wordArray.end()); - // Get word list generic_string words; for (size_t i = 0, wordArrayLen = wordArray.size(); i < wordArrayLen; ++i) @@ -124,6 +138,8 @@ bool AutoCompletion::showApiAndWordComplete() words += TEXT(" "); } + // Make Scintilla show the autocompletion menu + _pEditView->execute(SCI_AUTOCSETSEPARATOR, WPARAM(' ')); _pEditView->execute(SCI_AUTOCSETIGNORECASE, _ignoreCase); _pEditView->showAutoComletion(curPos - startPos, words.c_str()); @@ -131,7 +147,7 @@ bool AutoCompletion::showApiAndWordComplete() } -void AutoCompletion::getWordArray(vector & wordArray, TCHAR *beginChars) +void AutoCompletion::getWordArray(vector & wordArray, TCHAR *beginChars, TCHAR *allChars) { const size_t bufSize = 256; const NppGUI & nppGUI = NppParameters::getInstance().getNppGUI(); @@ -160,9 +176,11 @@ void AutoCompletion::getWordArray(vector & wordArray, TCHAR *beg { TCHAR w[bufSize]; _pEditView->getGenericText(w, bufSize, wordStart, wordEnd); - - if (!isInList(w, wordArray)) - wordArray.push_back(w); + if (!allChars || (generic_strncmp (w, allChars, bufSize) != 0)) + { + if (!isInList(w, wordArray)) + wordArray.push_back(w); + } } posFind = _pEditView->searchInTarget(expr.c_str(), static_cast(expr.length()), wordEnd, docLength); } @@ -325,27 +343,39 @@ void AutoCompletion::showPathCompletion() bool AutoCompletion::showWordComplete(bool autoInsert) { + // Get beginning of word and complete word + int curPos = int(_pEditView->execute(SCI_GETCURRENTPOS)); int startPos = int(_pEditView->execute(SCI_WORDSTARTPOSITION, curPos, true)); + int endPos = int(_pEditView->execute(SCI_WORDENDPOSITION, curPos, true)); if (curPos == startPos) return false; const size_t bufSize = 256; TCHAR beginChars[bufSize]; + TCHAR allChars[bufSize]; size_t len = (curPos > startPos)?(curPos - startPos):(startPos - curPos); if (len >= bufSize) return false; - // Get word array - vector wordArray; - _pEditView->getGenericText(beginChars, bufSize, startPos, curPos); + size_t lena = (endPos > startPos)?(endPos - startPos):(startPos - endPos); + if (lena >= bufSize) + return false; - getWordArray(wordArray, beginChars); + _pEditView->getGenericText(beginChars, bufSize, startPos, curPos); + _pEditView->getGenericText(allChars, bufSize, startPos, endPos); + + // Get word array containing all words beginning with beginChars, excluding word equal to allChars + + vector wordArray; + getWordArray(wordArray, beginChars, allChars); if (wordArray.size() == 0) return false; + // Optionally, auto-insert word + if (wordArray.size() == 1 && autoInsert) { int replacedLength = _pEditView->replaceTargetRegExMode(wordArray[0].c_str(), startPos, curPos); @@ -353,9 +383,10 @@ bool AutoCompletion::showWordComplete(bool autoInsert) return true; } + // Sort word array and convert it to a single string with space-separated words + sort(wordArray.begin(), wordArray.end()); - // Get word list generic_string words(TEXT("")); for (size_t i = 0, wordArrayLen = wordArray.size(); i < wordArrayLen; ++i) @@ -365,6 +396,8 @@ bool AutoCompletion::showWordComplete(bool autoInsert) words += TEXT(" "); } + // Make Scintilla show the autocompletion menu + _pEditView->execute(SCI_AUTOCSETSEPARATOR, WPARAM(' ')); _pEditView->execute(SCI_AUTOCSETIGNORECASE, _ignoreCase); _pEditView->showAutoComletion(curPos - startPos, words.c_str()); diff --git a/PowerEditor/src/ScitillaComponent/AutoCompletion.h b/PowerEditor/src/ScitillaComponent/AutoCompletion.h index ca88bbf48..ed95864fa 100644 --- a/PowerEditor/src/ScitillaComponent/AutoCompletion.h +++ b/PowerEditor/src/ScitillaComponent/AutoCompletion.h @@ -102,5 +102,5 @@ private: FunctionCallTip _funcCalltip; const TCHAR * getApiFileName(); - void getWordArray(std::vector & wordArray, TCHAR *beginChars); + void getWordArray(std::vector & wordArray, TCHAR *beginChars, TCHAR *excludeChars); };