Catch regex search exceptions and show exception message

Fix #9565, close #9566
This commit is contained in:
Udo Hoffmann 2021-02-23 19:04:12 +01:00 committed by Don HO
parent 854f49c61c
commit 926e6e97d8
17 changed files with 173 additions and 26 deletions

View File

@ -1330,6 +1330,7 @@ Find in all files except exe, obj && log:
<find-status-replaceinopenedfiles-nb-replaced value="Replace in Opened Files: $INT_REPLACE$ occurrences were replaced"/>
<find-status-mark-re-malformed value="Mark: The regular expression to search is malformed"/>
<find-status-invalid-re value="Find: Invalid regular expression"/>
<find-status-search-failed value="Find: Search failed"/>
<find-status-mark-1-match value="Mark: 1 match"/>
<find-status-mark-nb-matches value="Mark: $INT_REPLACE$ matches"/>
<find-status-count-re-malformed value="Count: The regular expression to search is malformed"/>

View File

@ -1018,6 +1018,48 @@ HWND CreateToolTip(int toolID, HWND hDlg, HINSTANCE hInst, const PTSTR pszText)
return hwndTip;
}
HWND CreateToolTipRect(int toolID, HWND hWnd, HINSTANCE hInst, const PTSTR pszText, const RECT rc)
{
if (!toolID || !hWnd || !pszText)
{
return NULL;
}
// Create the tooltip. g_hInst is the global instance handle.
HWND hwndTip = CreateWindowEx(0, TOOLTIPS_CLASS, NULL,
WS_POPUP | TTS_ALWAYSTIP | TTS_BALLOON,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
hWnd, NULL,
hInst, NULL);
if (!hwndTip)
{
return NULL;
}
// Associate the tooltip with the tool.
TOOLINFO toolInfo = { 0 };
toolInfo.cbSize = sizeof(toolInfo);
toolInfo.hwnd = hWnd;
toolInfo.uFlags = TTF_SUBCLASS;
toolInfo.uId = toolID;
toolInfo.lpszText = pszText;
toolInfo.rect = rc;
if (!SendMessage(hwndTip, TTM_ADDTOOL, 0, (LPARAM)&toolInfo))
{
DestroyWindow(hwndTip);
return NULL;
}
SendMessage(hwndTip, TTM_ACTIVATE, TRUE, 0);
SendMessage(hwndTip, TTM_SETMAXTIPWIDTH, 0, 200);
// Make tip stay 15 seconds
SendMessage(hwndTip, TTM_SETDELAYTIME, TTDT_AUTOPOP, MAKELPARAM((15000), (0)));
return hwndTip;
}
bool isCertificateValidated(const generic_string & fullFilePath, const generic_string & subjectName2check)
{
bool isOK = false;

View File

@ -186,6 +186,7 @@ generic_string intToString(int val);
generic_string uintToString(unsigned int val);
HWND CreateToolTip(int toolID, HWND hDlg, HINSTANCE hInst, const PTSTR pszText);
HWND CreateToolTipRect(int toolID, HWND hWnd, HINSTANCE hInst, const PTSTR pszText, const RECT rc);
bool isCertificateValidated(const generic_string & fullFilePath, const generic_string & subjectName2check);
bool isAssoCommandExisting(LPCTSTR FullPathName);

View File

@ -991,7 +991,7 @@ int Notepad_plus::getHtmlXmlEncoding(const TCHAR *fileName) const
_invisibleEditView.execute(SCI_SETTARGETRANGE, startPos, endPos);
auto posFound = _invisibleEditView.execute(SCI_SEARCHINTARGET, strlen(xmlHeaderRegExpr), reinterpret_cast<LPARAM>(xmlHeaderRegExpr));
if (posFound != -1 && posFound != -2)
if (posFound >= 0)
{
const char *encodingBlockRegExpr = "encoding[ \\t]*=[ \\t]*\"[^\".]+\"";
_invisibleEditView.execute(SCI_SEARCHINTARGET, strlen(encodingBlockRegExpr), reinterpret_cast<LPARAM>(encodingBlockRegExpr));
@ -1035,10 +1035,10 @@ int Notepad_plus::getHtmlXmlEncoding(const TCHAR *fileName) const
int posFound = static_cast<int32_t>(_invisibleEditView.execute(SCI_SEARCHINTARGET, strlen(htmlHeaderRegExpr), reinterpret_cast<LPARAM>(htmlHeaderRegExpr)));
if (posFound == -1 || posFound == -2)
if (posFound < 0)
{
posFound = static_cast<int32_t>(_invisibleEditView.execute(SCI_SEARCHINTARGET, strlen(htmlHeaderRegExpr2), reinterpret_cast<LPARAM>(htmlHeaderRegExpr2)));
if (posFound == -1 || posFound == -2)
if (posFound < 0)
return -1;
}
_invisibleEditView.execute(SCI_SEARCHINTARGET, strlen(charsetBlock), reinterpret_cast<LPARAM>(charsetBlock));
@ -3000,7 +3000,7 @@ bool Notepad_plus::isConditionExprLine(int lineNumber)
const char ifElseForWhileExpr[] = "((else[ \t]+)?if|for|while)[ \t]*[(].*[)][ \t]*|else[ \t]*";
auto posFound = _pEditView->execute(SCI_SEARCHINTARGET, strlen(ifElseForWhileExpr), reinterpret_cast<LPARAM>(ifElseForWhileExpr));
if (posFound != -1 && posFound != -2)
if (posFound >= 0)
{
auto end = _pEditView->execute(SCI_GETTARGETEND);
if (end == endPos)
@ -3147,7 +3147,7 @@ void Notepad_plus::maintainIndentation(TCHAR ch)
const char braceExpr[] = "[ \t]*\\{.*";
int posFound = static_cast<int32_t>(_pEditView->execute(SCI_SEARCHINTARGET, strlen(braceExpr), reinterpret_cast<LPARAM>(braceExpr)));
if (posFound != -1 && posFound != -2)
if (posFound >= 0)
{
int end = int(_pEditView->execute(SCI_GETTARGETEND));
if (end == endPos2)

View File

@ -218,6 +218,7 @@ IDI_VIEW_FILEBROWSER_OFF_ICON ICON "icons/fileBrowser_off.ico"
IDI_VIEW_MONITORING_ON_ICON ICON "icons/monitoring_on.ico"
IDI_VIEW_MONITORING_OFF_ICON ICON "icons/monitoring_off.ico"
IDI_MORE_ON_TOOLTIP ICON "icons/MoreOnTooltip.ico"
IDR_M30_MENU MENU
BEGIN

View File

@ -155,7 +155,7 @@ void AutoCompletion::getWordArray(vector<generic_string> & wordArray, TCHAR *beg
_pEditView->execute(SCI_SETSEARCHFLAGS, flags);
int posFind = _pEditView->searchInTarget(expr.c_str(), int(expr.length()), 0, docLength);
while (posFind != -1 && posFind != -2)
while (posFind >= 0)
{
int wordStart = int(_pEditView->execute(SCI_GETTARGETSTART));
int wordEnd = int(_pEditView->execute(SCI_GETTARGETEND));
@ -432,7 +432,7 @@ void AutoCompletion::getCloseTag(char *closeTag, size_t closeTagSize, size_t car
int targetStart = _pEditView->searchInTarget(tag2find, lstrlen(tag2find), caretPos, 0);
if (targetStart == -1 || targetStart == -2)
if (targetStart < 0)
return;
int targetEnd = int(_pEditView->execute(SCI_GETTARGETEND));

View File

@ -1840,7 +1840,7 @@ bool FindReplaceDlg::processFindNext(const TCHAR *txt2find, const FindOption *op
}
if (posFind == -1)
{
{ // not found
if (oFindStatus)
*oFindStatus = FSNotFound;
//failed, or failed twice with wrap
@ -1866,11 +1866,22 @@ bool FindReplaceDlg::processFindNext(const TCHAR *txt2find, const FindOption *op
return false;
}
}
else if (posFind == -2) // Invalid Regular expression
{
else if (posFind < -1)
{ // error
NativeLangSpeaker *pNativeSpeaker = (NppParameters::getInstance()).getNativeLangSpeaker();
generic_string msg = pNativeSpeaker->getLocalizedStrFromID("find-status-invalid-re", TEXT("Find: Invalid regular expression"));
setStatusbarMessage(msg, FSNotFound);
generic_string msgGeneral;
if (posFind == -2)
{
msgGeneral = pNativeSpeaker->getLocalizedStrFromID("find-status-invalid-re", TEXT("Find: Invalid regular expression"));
}
else
{
msgGeneral = pNativeSpeaker->getLocalizedStrFromID("find-status-search-failed", TEXT("Find: Search failed"));
}
char szMsg [511] = "";
(*_ppEditView)->execute (SCI_GETBOOSTREGEXERRMSG, _countof (szMsg), reinterpret_cast<LPARAM>(szMsg));
setStatusbarMessage(msgGeneral, FSNotFound, szMsg);
return false;
}
@ -2202,7 +2213,7 @@ int FindReplaceDlg::processRange(ProcessOperation op, FindReplaceInfo & findRepl
bool findAllFileNameAdded = false;
while (targetStart != -1 && targetStart != -2)
while (targetStart >= 0)
{
targetStart = pEditView->searchInTarget(pTextFind, stringSizeFind, findReplaceInfo._startRange, findReplaceInfo._endRange);
@ -2899,8 +2910,15 @@ void FindReplaceDlg::saveInMacro(size_t cmd, int cmdType)
::SendMessage(_hParent, WM_FRSAVE_INT, IDC_FRCOMMAND_EXEC, cmd);
}
void FindReplaceDlg::setStatusbarMessage(const generic_string & msg, FindStatus staus)
void FindReplaceDlg::setStatusbarMessage(const generic_string & msg, FindStatus staus, char const *pTooltipMsg)
{
if (_statusbarTooltipWnd)
{
::DestroyWindow(_statusbarTooltipWnd);
_statusbarTooltipWnd = nullptr;
}
_statusbarTooltipMsg = (pTooltipMsg && (*pTooltipMsg)) ? s2ws(pTooltipMsg) : TEXT("");
if (staus == FSNotFound)
{
if (!NppParameters::getInstance().getNppGUI()._muteSounds)
@ -3599,6 +3617,41 @@ void FindReplaceDlg::drawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
RECT rect;
_statusBar.getClientRect(rect);
::DrawText(lpDrawItemStruct->hDC, ptStr, lstrlen(ptStr), &rect, DT_SINGLELINE | DT_VCENTER | DT_LEFT);
if (_statusbarTooltipMsg.length() == 0) return;
SIZE size;
::GetTextExtentPoint32(lpDrawItemStruct->hDC, ptStr, lstrlen(ptStr), &size);
int s = (rect.bottom - rect.top) & 0x70; // limit s to available icon sizes and avoid uneven scalings
if (s > 0)
{
if (_statusbarTooltipIcon && (_statusbarTooltipIconSize != s))
{
DestroyIcon (_statusbarTooltipIcon);
_statusbarTooltipIcon = nullptr;
}
if (!_statusbarTooltipIcon)
_statusbarTooltipIcon = (HICON)::LoadImage(_hInst, MAKEINTRESOURCE(IDI_MORE_ON_TOOLTIP), IMAGE_ICON, s, s, 0);
if (_statusbarTooltipIcon)
{
_statusbarTooltipIconSize = s;
rect.left = rect.left + size.cx + s / 2;
rect.top = (rect.top + rect.bottom - s) / 2;
DrawIconEx (lpDrawItemStruct->hDC, rect.left, rect.top, _statusbarTooltipIcon, s, s, 0, NULL, DI_NORMAL);
if (!_statusbarTooltipWnd)
{
rect.right = rect.left + s;
rect.bottom = rect.top + s;
_statusbarTooltipWnd = CreateToolTipRect(1, _statusBar.getHSelf(), _hInst, const_cast<PTSTR>(_statusbarTooltipMsg.c_str()), rect);
}
}
else
{
_statusbarTooltipIconSize = 0;
}
}
}
bool FindReplaceDlg::replaceInFilesConfirmCheck(generic_string directory, generic_string fileTypes)

View File

@ -339,7 +339,7 @@ public :
void execSavedCommand(int cmd, uptr_t intValue, const generic_string& stringValue);
void clearMarks(const FindOption& opt);
void setStatusbarMessage(const generic_string & msg, FindStatus staus);
void setStatusbarMessage(const generic_string & msg, FindStatus staus, char const *pTooltipMsg = NULL);
generic_string getScopeInfoForStatusBar(FindOption const *pFindOpt) const;
Finder * createFinder();
bool removeFinder(Finder *finder2remove);
@ -391,6 +391,11 @@ private :
StatusBar _statusBar;
FindStatus _statusbarFindStatus;
generic_string _statusbarTooltipMsg;
HWND _statusbarTooltipWnd = nullptr;
HICON _statusbarTooltipIcon = nullptr;
int _statusbarTooltipIconSize = 0;
HFONT _hMonospaceFont = nullptr;
std::map<int, bool> _controlEnableMap;

View File

@ -615,6 +615,7 @@ public:
protected:
static HINSTANCE _hLib;
static int _refCount;
static UserDefineDialog _userDefineDlg;

View File

@ -100,13 +100,13 @@ size_t FunctionListPanel::getBodyClosePos(size_t begin, const TCHAR *bodyOpenSym
do
{
if (targetStart != -1 && targetStart != -2) // found open or close symbol
if (targetStart >= 0) // found open or close symbol
{
targetEnd = int((*_ppEditView)->execute(SCI_GETTARGETEND));
// Now we determinate the symbol (open or close)
int tmpStart = (*_ppEditView)->searchInTarget(bodyOpenSymbol, lstrlen(bodyOpenSymbol), targetStart, targetEnd);
if (tmpStart != -1 && tmpStart != -2) // open symbol found
if (tmpStart >= 0) // open symbol found
{
++cntOpen;
}
@ -145,7 +145,7 @@ generic_string FunctionListPanel::parseSubLevel(size_t begin, size_t end, std::v
const TCHAR *regExpr2search = dataToSearch[0].c_str();
int targetStart = (*_ppEditView)->searchInTarget(regExpr2search, lstrlen(regExpr2search), begin, end);
if (targetStart == -1 || targetStart == -2)
if (targetStart < 0)
{
foundPos = -1;
return TEXT("");

View File

@ -392,7 +392,7 @@ void FunctionParser::funcParse(std::vector<foundInfo> & foundInfos, size_t begin
int targetEnd = 0;
//foundInfos.clear();
while (targetStart != -1 && targetStart != -2)
while (targetStart >= 0)
{
targetStart = int((*ppEditView)->execute(SCI_GETTARGETSTART));
targetEnd = int((*ppEditView)->execute(SCI_GETTARGETEND));
@ -471,7 +471,7 @@ generic_string FunctionParser::parseSubLevel(size_t begin, size_t end, std::vect
const TCHAR *regExpr2search = dataToSearch[0].c_str();
int targetStart = (*ppEditView)->searchInTarget(regExpr2search, lstrlen(regExpr2search), begin, end);
if (targetStart == -1 || targetStart == -2)
if (targetStart < 0)
{
foundPos = -1;
return generic_string();
@ -532,7 +532,7 @@ size_t FunctionZoneParser::getBodyClosePos(size_t begin, const TCHAR *bodyOpenSy
do
{
if (targetStart != -1 && targetStart != -2) // found open or close symbol
if (targetStart >= 0) // found open or close symbol
{
targetEnd = (*ppEditView)->execute(SCI_GETTARGETEND);
@ -541,7 +541,7 @@ size_t FunctionZoneParser::getBodyClosePos(size_t begin, const TCHAR *bodyOpenSy
{
// Now we determinate the symbol (open or close)
int tmpStart = (*ppEditView)->searchInTarget(bodyOpenSymbol, lstrlen(bodyOpenSymbol), targetStart, targetEnd);
if (tmpStart != -1 && tmpStart != -2) // open symbol found
if (tmpStart >= 0) // open symbol found
{
++cntOpen;
}
@ -576,7 +576,7 @@ void FunctionZoneParser::classParse(vector<foundInfo> & foundInfos, vector< pair
int targetEnd = 0;
while (targetStart != -1 && targetStart != -2)
while (targetStart >= 0)
{
targetEnd = int((*ppEditView)->execute(SCI_GETTARGETEND));
@ -622,7 +622,7 @@ void FunctionParser::getCommentZones(vector< pair<int, int> > & commentZone, siz
int targetStart = (*ppEditView)->searchInTarget(_commentExpr.c_str(), _commentExpr.length(), begin, end);
int targetEnd = 0;
while (targetStart != -1 && targetStart != -2)
while (targetStart >= 0)
{
targetStart = int((*ppEditView)->execute(SCI_GETTARGETSTART));
targetEnd = int((*ppEditView)->execute(SCI_GETTARGETEND));

Binary file not shown.

After

Width:  |  Height:  |  Size: 905 B

View File

@ -161,6 +161,8 @@
#define IDI_VIEW_MONITORING_ON_ICON 639
#define IDI_VIEW_MONITORING_OFF_ICON 640
#define IDI_MORE_ON_TOOLTIP 641
#define IDC_MY_CUR 1402

View File

@ -12,7 +12,6 @@
#include <stdlib.h>
#include <iterator>
#include <vector>
#include "Scintilla.h"
#include "Platform.h"
#include "ILoader.h"
@ -251,6 +250,8 @@ RegexSearchBase *CreateRegexSearch(CharClassify* /* charClassTable */)
#endif
}
std::string g_exceptionMessage;
/**
* Find text in document, supporting both forward and backward
* searches (just pass startPosition > endPosition to do a backward search).
@ -259,6 +260,7 @@ RegexSearchBase *CreateRegexSearch(CharClassify* /* charClassTable */)
Sci::Position BoostRegexSearch::FindText(Document* doc, Sci::Position startPosition, Sci::Position endPosition, const char *regexString,
bool caseSensitive, bool /*word*/, bool /*wordStart*/, int sciSearchFlags, Sci::Position *lengthRet)
{
g_exceptionMessage.clear();
try {
SearchParameters search;
@ -319,11 +321,24 @@ Sci::Position BoostRegexSearch::FindText(Document* doc, Sci::Position startPosit
}
}
catch(regex_error& /*ex*/)
catch(regex_error& ex)
{
// -1 is normally used for not found, -2 is used here for invalid regex
g_exceptionMessage = ex.what();
return -2;
}
catch(boost::wrapexcept<std::runtime_error>& ex)
{
g_exceptionMessage = ex.what();
return -3;
}
catch(...)
{
g_exceptionMessage = "Unexpected exception while searching";
return -3;
}
}
template <class CharT, class CharacterIterator>

View File

@ -9,4 +9,8 @@
#define SCFIND_REGEXP_EMPTYMATCH_ALLOWATSTART 0x80000000
#define SCFIND_REGEXP_SKIPCRLFASONE 0x08000000
#ifdef SCI_OWNREGEX
extern std::string g_exceptionMessage;
#endif
#endif

View File

@ -1173,6 +1173,8 @@ typedef sptr_t (*SciFnDirect)(sptr_t ptr, unsigned int iMessage, uptr_t wParam,
#define SCI_INDEXPOSITIONFROMLINE 2714
#endif
#define SCI_GETBOOSTREGEXERRMSG 5000
#define SCN_SCROLLED 2080
#define SCN_FOLDINGSTATECHANGED 2081

View File

@ -88,6 +88,7 @@
#include "PlatWin.h"
#include "HanjaDic.h"
#include "ScintillaWin.h"
#include "BoostRegexSearch.h"
#ifndef SPI_GETWHEELSCROLLLINES
#define SPI_GETWHEELSCROLLLINES 104
@ -1800,6 +1801,22 @@ sptr_t ScintillaWin::SciMessage(unsigned int iMessage, uptr_t wParam, sptr_t lPa
case SCI_GETDIRECTPOINTER:
return reinterpret_cast<sptr_t>(this);
#ifdef SCI_OWNREGEX
case SCI_GETBOOSTREGEXERRMSG:
{
// copies behavior of SCI_GETTEXT
if (lParam == 0)
return g_exceptionMessage.length() + 1;
if (wParam == 0)
return 0;
char *ptr = CharPtrFromSPtr(lParam);
const Sci_Position len = std::min<Sci_Position>(wParam - 1, g_exceptionMessage.length());
strncpy (ptr, g_exceptionMessage.c_str(), len);
ptr [len] = '\0';
return len;
}
#endif
case SCI_GRABFOCUS:
::SetFocus(MainHWND());
break;
@ -2031,6 +2048,9 @@ sptr_t ScintillaWin::WndProc(unsigned int iMessage, uptr_t wParam, sptr_t lParam
case SCI_GETDIRECTFUNCTION:
case SCI_GETDIRECTPOINTER:
#ifdef SCI_OWNREGEX
case SCI_GETBOOSTREGEXERRMSG:
#endif
case SCI_GRABFOCUS:
#ifdef INCLUDE_DEPRECATED_FEATURES
case SCI_SETKEYSUNICODE: