diff --git a/scintilla/deelx/DeelxRegexSearch.cxx b/scintilla/deelx/DeelxRegexSearch.cxx index 3d82822f2..e702550c6 100644 --- a/scintilla/deelx/DeelxRegexSearch.cxx +++ b/scintilla/deelx/DeelxRegexSearch.cxx @@ -47,45 +47,47 @@ #include "deelx64.h" // DEELX - Regular Expression Engine (v1.3) // --------------------------------------------------------------- - using namespace Scintilla; +#define SciPos(pos) static_cast(pos) +#define SciLn(line) static_cast(line) +#define SciPosExt(pos) static_cast(pos) + +#define DeelXPos(pos) static_cast(pos) +#define Cast2int(n) static_cast(n) + +// --------------------------------------------------------------- + class DeelxRegexSearch : public RegexSearchBase { public: explicit DeelxRegexSearch(CharClassify* charClassTable) - : m_RegExpr() - ,m_Match() - ,m_MatchPos(-1) - ,m_MatchLength(0) - ,m_pContext(nullptr) - ,m_SubstitutionBuffer(nullptr) + : m_RegExprStrg() + , m_CompileFlags(-1) + , m_RegExpr() + , m_Match() + , m_MatchPos(-1) + , m_MatchLength(0) + , m_SubstitutionBuffer(nullptr) {} virtual ~DeelxRegexSearch() { ReleaseSubstitutionBuffer(); - ReleaseContext(); +// ReleaseContext(SciPos(-1), SciPos(-1)); + m_RegExprStrg.clear(); } - virtual long FindText(Document* doc,int minPos,int maxPos,const char* pattern, - bool caseSensitive,bool word,bool wordStart,int flags,int* length) override; + virtual long FindText(Document* doc, Sci::Position minPos, Sci::Position maxPos, const char* pattern, + bool caseSensitive, bool word, bool wordStart, int flags, Sci::Position* length) override; - virtual const char* SubstituteByPosition(Document* doc,const char* text,int* length) override; + virtual const char* SubstituteByPosition(Document* doc, const char* text, Sci::Position* length) override; private: - inline void ReleaseContext() - { - if (m_pContext != nullptr) { - m_RegExpr.ReleaseContext(m_pContext); - m_pContext = nullptr; - } - } - - inline void ReleaseSubstitutionBuffer() + __inline void ReleaseSubstitutionBuffer() { if (m_SubstitutionBuffer) { m_RegExpr.ReleaseString(m_SubstitutionBuffer); @@ -93,12 +95,17 @@ private: } } + std::string& translateRegExpr(std::string& regExprStr, bool wholeWord, bool wordStart); + std::string& convertReplExpr(std::string& replStr); + private: + + std::string m_RegExprStrg; + int m_CompileFlags; deelx::CRegexpT m_RegExpr; deelx::MatchResult m_Match; - deelx::index_t m_MatchPos; - deelx::index_t m_MatchLength; - deelx::CContext* m_pContext; + Sci::Position m_MatchPos; + Sci::Position m_MatchLength; char* m_SubstitutionBuffer; }; // ============================================================================ @@ -109,15 +116,6 @@ RegexSearchBase *Scintilla::CreateRegexSearch(CharClassify *charClassTable) return new DeelxRegexSearch(charClassTable); } -// ============================================================================ - -/** - * forward declaration of utility functions - */ -std::string& translateRegExpr(std::string& regExprStr,bool wholeWord,bool wordStart); -std::string& convertReplExpr(std::string& replStr); - - // ============================================================================ @@ -126,8 +124,8 @@ std::string& convertReplExpr(std::string& replStr); * searches (just pass minPos > maxPos to do a backward search) * Has not been tested with backwards DBCS searches yet. */ -long DeelxRegexSearch::FindText(Document* doc,int minPos,int maxPos,const char *pattern, - bool caseSensitive,bool word,bool wordStart,int searchFlags,int *length) +long DeelxRegexSearch::FindText(Document* doc, Sci::Position minPos, Sci::Position maxPos, const char *pattern, + bool caseSensitive, bool word, bool wordStart, int searchFlags, Sci::Position *length) { const bool right2left = false; // always left-to-right match mode const bool extended = false; // ignore spaces and use '#' as line-comment) @@ -137,80 +135,122 @@ long DeelxRegexSearch::FindText(Document* doc,int minPos,int maxPos,const char * maxPos = doc->MovePositionOutsideChar(maxPos,1,false); const bool findprevious = (minPos > maxPos); - int compileFlags = deelx::NO_FLAG; compileFlags |= (deelx::MULTILINE | deelx::GLOBAL); // the .(dot) does not match line-breaks //compileFlags |= (deelx::SINGLELINE | deelx::MULTILINE | deelx::GLOBAL); // the .(dot) also matches line-breaks compileFlags |= (extended) ? deelx::EXTENDED : deelx::NO_FLAG; - compileFlags |= (!caseSensitive) ? deelx::IGNORECASE : deelx::NO_FLAG; + compileFlags |= (caseSensitive) ? deelx::NO_FLAG : deelx::IGNORECASE; compileFlags |= (right2left) ? deelx::RIGHTTOLEFT : deelx::NO_FLAG; - std::string sRegExprStrg = translateRegExpr(std::string(pattern,*length),word,wordStart); + std::string sRegExprStrg = translateRegExpr(std::string(pattern),word,wordStart); - try { - m_RegExpr.Compile(sRegExprStrg.c_str(),compileFlags); - } - catch (...) { - return -2; // -1 is normally used for not found, -2 is used here for invalid regex + bool bReCompile = (m_CompileFlags != compileFlags) || (m_RegExprStrg.compare(sRegExprStrg) != 0); + + if (bReCompile) { + m_RegExprStrg = sRegExprStrg; + m_CompileFlags = compileFlags; + try { + m_RegExpr.Compile(m_RegExprStrg.c_str(), m_CompileFlags); + } + catch (...) { + return -2; // -1 is normally used for not found, -2 is used here for invalid regex + // DeelX is very fault tolerant and assumes what the user may want ... :-/ + // so -2 may not occur! + } } - int rangeBegin = (findprevious) ? maxPos : minPos; - int rangeLength = abs(maxPos - minPos); + Sci::Position rangeBegin = (findprevious) ? maxPos : minPos; + Sci::Position rangeEnd = (findprevious) ? minPos : maxPos; + + Sci::Line linesTotal = doc->LinesTotal(); + Sci::Position fileLastPos = SciPos(doc->Length()); - ReleaseContext(); - m_pContext = m_RegExpr.PrepareMatch(doc->RangePointer(rangeBegin,rangeLength)); + Sci::Line lineOfBegPos = SciLn(doc->LineFromPosition(SciPosExt(rangeBegin))); + Sci::Line lineOfEndPos = SciLn(doc->LineFromPosition(SciPosExt(rangeEnd))); - m_MatchPos = -1; // not found - m_MatchLength = 0; + Sci::Position lineStartOfBegPos = SciPos(doc->LineStart(SciPosExt(lineOfBegPos))); + Sci::Position lineEndOfEndPos = SciPos(doc->LineEnd(SciPosExt(lineOfEndPos))); - m_Match = m_RegExpr.Match(m_pContext); + // --- adapt range start/end according to search pattern --- + + size_t begMetaPos = m_RegExprStrg.find_first_of('^'); + bool bFoundBegMeta = (begMetaPos != std::string::npos) && + ((begMetaPos == 0) || (m_RegExprStrg.find_first_of('\\') != (begMetaPos - 1))); + if (bFoundBegMeta) { + if (lineStartOfBegPos != rangeBegin) { + rangeBegin = SciPos((lineOfBegPos < linesTotal) ? + doc->LineStart(SciPosExt(lineOfBegPos + 1)) : + doc->LineEnd(SciPosExt(linesTotal))); + rangeEnd = (rangeBegin <= rangeEnd) ? rangeEnd : rangeBegin; + } + } + + size_t endMetaPos = m_RegExprStrg.find_last_of('$'); + bool bFoundEndMeta = (endMetaPos != std::string::npos) && + ((endMetaPos == 0) || (m_RegExprStrg.find_last_of('\\') != (endMetaPos - 1))); + if (bFoundEndMeta) { + if (lineEndOfEndPos != rangeEnd) { + rangeEnd = SciPos((0 < lineOfEndPos) ? doc->LineEnd(SciPosExt(lineOfEndPos - 1)) : 0); + rangeBegin = (rangeBegin <= rangeEnd) ? rangeBegin : rangeEnd; + } + } + +//@@@ Sci::Position rangeLength = rangeEnd - rangeBegin; + + + // --- start search --- + + m_MatchPos = SciPos(-1); // not found + m_MatchLength = SciPos(0); + const deelx::index_t searchStop = DeelXPos(rangeEnd); if (findprevious) // search previous { + deelx::CContext* pContext = m_RegExpr.PrepareMatch(doc->RangePointer(0, fileLastPos), 0); + m_Match = m_RegExpr.Match(pContext); // search for last occurrence in range - while (m_Match.IsMatched() && (m_Match.GetStart() < rangeLength)) + while (m_Match.IsMatched() && (m_Match.GetStart() < searchStop)) { - m_MatchPos = rangeBegin + m_Match.GetStart(); - m_MatchLength = (m_Match.GetEnd() - m_Match.GetStart()); - - m_Match = m_RegExpr.Match(m_pContext); //next + m_MatchPos = SciPos(m_Match.GetStart()); + m_MatchLength = SciPos(m_Match.GetEnd() - m_Match.GetStart()); + m_Match = m_RegExpr.Match(pContext); //next } + m_RegExpr.ReleaseContext(pContext); } - else - { - if (m_Match.IsMatched() && (m_Match.GetStart() < rangeLength)) - { - m_MatchPos = rangeBegin + m_Match.GetStart(); - m_MatchLength = (m_Match.GetEnd() - m_Match.GetStart()); + else { + m_Match = m_RegExpr.Match(doc->RangePointer(0, fileLastPos), + DeelXPos(fileLastPos), DeelXPos(rangeBegin)); + if (m_Match.IsMatched() && (m_Match.GetStart() < searchStop)) { + m_MatchPos = SciPos(m_Match.GetStart()); + m_MatchLength = SciPos(m_Match.GetEnd() - m_Match.GetStart()); } } //NOTE: potential 64-bit-size issue at interface here: - *length = static_cast(m_MatchLength); + *length = SciPos(m_MatchLength); return static_cast(m_MatchPos); } // ============================================================================ -const char* DeelxRegexSearch::SubstituteByPosition(Document* doc,const char* text,int* length) +const char* DeelxRegexSearch::SubstituteByPosition(Document* doc, const char* text, Sci::Position* length) { if (!m_Match.IsMatched() || (m_MatchPos < 0)) { - *length = 0; + *length = SciPos(0); return nullptr; } std::string sReplStrg = convertReplExpr(std::string(text,*length)); + deelx::index_t replLength = DeelXPos(sReplStrg.length()); - //NOTE: potential 64-bit-size issue at interface here: - const char* pString = doc->RangePointer(static_cast(m_MatchPos),static_cast(m_MatchLength)); + const char* pString = doc->RangePointer(m_MatchPos,m_MatchLength); - deelx::index_t resLength; ReleaseSubstitutionBuffer(); - m_SubstitutionBuffer = m_RegExpr.Replace(pString,m_MatchLength,sReplStrg.c_str(), - static_cast(sReplStrg.length()),resLength); + deelx::index_t resLength; + m_SubstitutionBuffer = m_RegExpr.Replace(pString,m_MatchLength,sReplStrg.c_str(),replLength,resLength); //NOTE: potential 64-bit-size issue at interface here: - *length = static_cast(resLength); + *length = SciPos(resLength); return m_SubstitutionBuffer; } @@ -246,7 +286,7 @@ void replaceAll(std::string& source,const std::string& from,const std::string& t -std::string& translateRegExpr(std::string& regExprStr,bool wholeWord,bool wordStart) +std::string& DeelxRegexSearch::translateRegExpr(std::string& regExprStr,bool wholeWord,bool wordStart) { std::string tmpStr; @@ -270,7 +310,7 @@ std::string& translateRegExpr(std::string& regExprStr,bool wholeWord,bool wordSt -std::string& convertReplExpr(std::string& replStr) +std::string& DeelxRegexSearch::convertReplExpr(std::string& replStr) { std::string tmpStr; for (size_t i = 0; i < replStr.length(); ++i) { diff --git a/scintilla/deelx/deelx64.h b/scintilla/deelx/deelx64.h index b27d19725..a0b4b6845 100644 --- a/scintilla/deelx/deelx64.h +++ b/scintilla/deelx/deelx64.h @@ -29,14 +29,13 @@ #include #include #include - -#include +#include namespace deelx { // integer type for pointer arithmetic & casts (64-bit aware) //typedef int index_t; // preserve original "deelx.h" v1.3 behavior - using index_t = INT_PTR; + using index_t = ptrdiff_t; //INT_PTR extern "C" { using POSIX_FUNC = int(*)(int); @@ -3612,9 +3611,9 @@ public: public: MatchResult MatchExact(const CHART * tstring, CContext * pContext = nullptr) const; - MatchResult MatchExact(const CHART * tstring, int length, CContext * pContext = nullptr) const; - MatchResult Match(const CHART * tstring, int start = -1, CContext * pContext = nullptr) const; - MatchResult Match(const CHART * tstring, int length, int start, CContext * pContext = nullptr) const; + MatchResult MatchExact(const CHART * tstring, index_t length, CContext * pContext = nullptr) const; + MatchResult Match(const CHART * tstring, index_t start = -1, CContext * pContext = nullptr) const; + MatchResult Match(const CHART * tstring, index_t length, index_t start, CContext * pContext = nullptr) const; MatchResult Match(CContext * pContext) const; CContext * PrepareMatch(const CHART * tstring, index_t start = -1, CContext * pContext = nullptr) const; CContext * PrepareMatch(const CHART * tstring, index_t length, index_t start, CContext * pContext = nullptr) const; @@ -3659,7 +3658,7 @@ template inline MatchResult CRegexpT ::MatchExact(const CH return MatchExact(tstring, CBufferRefT(tstring).GetSize(), pContext); } -template MatchResult CRegexpT ::MatchExact(const CHART * tstring, int length, CContext * pContext) const +template MatchResult CRegexpT ::MatchExact(const CHART * tstring, index_t length, CContext * pContext) const { if (m_builder.m_pTopElx == 0) return nullptr; @@ -3725,12 +3724,12 @@ template MatchResult CRegexpT ::MatchExact(const CHART * t } } -template MatchResult CRegexpT ::Match(const CHART * tstring, int start, CContext * pContext) const +template MatchResult CRegexpT ::Match(const CHART * tstring, index_t start, CContext * pContext) const { return Match(tstring, CBufferRefT(tstring).GetSize(), start, pContext); } -template MatchResult CRegexpT ::Match(const CHART * tstring, int length, int start, CContext * pContext) const +template MatchResult CRegexpT ::Match(const CHART * tstring, index_t length, index_t start, CContext * pContext) const { if (m_builder.m_pTopElx == 0) return nullptr; diff --git a/src/Dialogs.c b/src/Dialogs.c index a3c864a60..00a4d40e6 100644 --- a/src/Dialogs.c +++ b/src/Dialogs.c @@ -386,7 +386,7 @@ INT_PTR CALLBACK RunDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam) if (StringCchLenW(args,COUNTOF(args))) bEnableOK = TRUE; - EnableWindow(GetDlgItem(hwnd,IDOK),bEnableOK); + DialogEnableWindow(hwnd,IDOK,bEnableOK); } break; @@ -565,7 +565,7 @@ INT_PTR CALLBACK OpenWithDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam case LVN_ITEMCHANGED: { NM_LISTVIEW *pnmlv = (NM_LISTVIEW*)lParam; - EnableWindow(GetDlgItem(hwnd,IDOK),(pnmlv->uNewState & LVIS_SELECTED)); + DialogEnableWindow(hwnd,IDOK,(pnmlv->uNewState & LVIS_SELECTED)); } break; @@ -762,7 +762,7 @@ INT_PTR CALLBACK FavoritesDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lPara case LVN_ITEMCHANGED: { NM_LISTVIEW *pnmlv = (NM_LISTVIEW*)lParam; - EnableWindow(GetDlgItem(hwnd,IDOK),(pnmlv->uNewState & LVIS_SELECTED)); + DialogEnableWindow(hwnd,IDOK,(pnmlv->uNewState & LVIS_SELECTED)); } break; @@ -876,7 +876,7 @@ INT_PTR CALLBACK AddToFavDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam { case 100: - EnableWindow(GetDlgItem(hwnd,IDOK),GetWindowTextLength(GetDlgItem(hwnd,100))); + DialogEnableWindow(hwnd,IDOK,GetWindowTextLength(GetDlgItem(hwnd,100))); break; @@ -1092,7 +1092,7 @@ INT_PTR CALLBACK FileMRUDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam) if (bPreserveCaretPos) CheckDlgButton(hwnd, IDC_PRESERVECARET, BST_CHECKED); - //if (!bSaveRecentFiles) EnableWindow(GetDlgItem(hwnd, IDC_PRESERVECARET), FALSE); + //if (!bSaveRecentFiles) DialogEnableWindow(hwnd,IDC_PRESERVECARET, FALSE); CenterDlgInParent(hwnd); } @@ -1231,8 +1231,8 @@ INT_PTR CALLBACK FileMRUDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam) case LVN_DELETEITEM: { UINT cnt = ListView_GetSelectedCount(GetDlgItem(hwnd, IDC_FILEMRU)); - EnableWindow(GetDlgItem(hwnd, IDOK), (cnt > 0)); - EnableWindow(GetDlgItem(hwnd, IDC_REMOVE), (cnt > 0)); + DialogEnableWindow(hwnd, IDOK, (cnt > 0)); + DialogEnableWindow(hwnd, IDC_REMOVE, (cnt > 0)); } break; } @@ -1344,12 +1344,12 @@ INT_PTR CALLBACK FileMRUDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam) // must use IDM_VIEW_REFRESH, index might change... SendMessage(hwnd,WM_COMMAND,MAKELONG(0x00A0,1),0); - //EnableWindow(GetDlgItem(hwnd,IDOK), + //DialogEnableWindow(hwnd,IDOK, // (LB_ERR != SendDlgItemMessage(hwnd,IDC_GOTO,LB_GETCURSEL,0,0))); cnt = ListView_GetSelectedCount(GetDlgItem(hwnd, IDC_FILEMRU)); - EnableWindow(GetDlgItem(hwnd, IDOK), (cnt > 0)); - EnableWindow(GetDlgItem(hwnd, IDC_REMOVE), (cnt > 0)); + DialogEnableWindow(hwnd, IDOK, (cnt > 0)); + DialogEnableWindow(hwnd, IDC_REMOVE, (cnt > 0)); } } @@ -2086,7 +2086,7 @@ INT_PTR CALLBACK SelectEncodingDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM case LVN_ITEMCHANGED: case LVN_DELETEITEM: { int i = ListView_GetNextItem(hwndLV,-1,LVNI_ALL | LVNI_SELECTED); - EnableWindow(GetDlgItem(hwnd,IDOK),i != -1); + DialogEnableWindow(hwnd,IDOK,i != -1); } break; } @@ -2313,7 +2313,7 @@ INT_PTR CALLBACK InfoBoxDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam) (WPARAM)LoadIcon(NULL,IDI_EXCLAMATION),0); SetDlgItemText(hwnd,IDC_INFOBOXTEXT,lpib->lpstrMessage); if (lpib->bDisableCheckBox) - EnableWindow(GetDlgItem(hwnd,IDC_INFOBOXCHECK),FALSE); + DialogEnableWindow(hwnd,IDC_INFOBOXCHECK,FALSE); LocalFree(lpib->lpstrMessage); CenterDlgInParent(hwnd); return TRUE; diff --git a/src/Edit.c b/src/Edit.c index b3828b763..8c85ed466 100644 --- a/src/Edit.c +++ b/src/Edit.c @@ -3280,7 +3280,7 @@ void EditStripTrailingBlanks(HWND hwnd,BOOL bIgnoreSelection) { if (SC_SEL_RECTANGLE != SendMessage(hwnd,SCI_GETSELECTIONMODE,0,0)) { - EDITFINDREPLACE efrTrim = { "[ \t]+$", "", "", "", SCFIND_REGEXP, 0, 0, 0, 0, 0, 0, NULL }; + EDITFINDREPLACE efrTrim = { "[ \t]+$", "", "", "", (SCFIND_REGEXP | SCFIND_POSIX), 0, 0, 0, 0, 0, 0, NULL }; efrTrim.hwnd = hwnd; EditReplaceAllInSelection(hwnd,&efrTrim,FALSE); @@ -4353,13 +4353,14 @@ void __fastcall EditSetSearchFlags(HWND hwnd, LPEDITFINDREPLACE lpefr) // Wildcard search uses the regexp engine to perform a simple search with * ? as wildcards // instead of more advanced and user-unfriendly regexp syntax +// for speed, we only need POSIX syntax here void __fastcall EscapeWildcards(char* szFind2, LPCEDITFINDREPLACE lpefr) { char szWildcardEscaped[FNDRPL_BUFFER] = { '\0' }; int iSource = 0; int iDest = 0; - lpefr->fuFlags |= SCFIND_REGEXP; + lpefr->fuFlags |= (SCFIND_REGEXP | SCFIND_POSIX); while (szFind2[iSource] != '\0') { @@ -4416,12 +4417,15 @@ int __fastcall EditGetFindStrg(HWND hwnd, LPCEDITFINDREPLACE lpefr, LPSTR szFind int slen = StringCchLenA(szFind, FNDRPL_BUFFER); - if (slen == 0) + if (slen == 0) { InfoBox(0, L"MsgNotFound", IDS_NOTFOUND); - else + } + else { if (lpefr->bWildcardSearch) EscapeWildcards(szFind, lpefr); + //@@@~TransformMetaChars(szFind, (lpefr->fuFlags & SCFIND_REGEXP), (int)SendMessage(hwnd, SCI_GETEOLMODE, 0, 0)); + } return slen; } @@ -4430,11 +4434,29 @@ int __fastcall EditGetFindStrg(HWND hwnd, LPCEDITFINDREPLACE lpefr, LPSTR szFind // // EditFindInTarget() // -int __fastcall EditFindInTarget(HWND hwnd, LPCSTR szFind, int length, int flags, int* start, int* end) +int __fastcall EditFindInTarget(HWND hwnd, LPCSTR szFind, int length, int flags, int* start, int* end, BOOL bForceNext) { + int _start = *start; + int _end = *end; + BOOL bFindPrev = (_start > _end); + SendMessage(hwnd, SCI_SETSEARCHFLAGS, flags, 0); - SendMessage(hwnd, SCI_SETTARGETRANGE, *start, *end); + SendMessage(hwnd, SCI_SETTARGETRANGE, _start, _end); int iPos = (int)SendMessage(hwnd, SCI_SEARCHINTARGET, length, (LPARAM)szFind); + // handle next in case of zero-length-matches (regex) ! + if ((iPos == _start) && bForceNext) { + int newStart = (int)(bFindPrev ? SendMessage(hwnd, SCI_POSITIONBEFORE, _start, 0) : + SendMessage(hwnd, SCI_POSITIONAFTER, _start, 0)); + if (newStart != _start) { + _start = newStart; + SendMessage(hwnd, SCI_SETTARGETRANGE, newStart, _end); + iPos = (int)SendMessage(hwnd, SCI_SEARCHINTARGET, length, (LPARAM)szFind); + } + else { + iPos = -1; // already at document begin or end => not found + } + } + if (iPos >= 0) { // found in range, set begin and end of finding *start = (int)SendMessage(hwnd, SCI_GETTARGETSTART, 0, 0); @@ -4454,13 +4476,11 @@ RegExResult_t __fastcall EditFindHasMatch(HWND hwnd, LPCEDITFINDREPLACE lpefr, B { char szFind[FNDRPL_BUFFER]; int slen = EditGetFindStrg(hwnd, lpefr, szFind, COUNTOF(szFind)); - if (slen <= 0) - return FALSE; int start = bFirstMatchOnly ? (int)SendMessage(hwnd, SCI_GETSELECTIONNSTART, 0, 0) : 0; int end = (int)SendMessage(hwnd, SCI_GETTEXTLENGTH, 0, 0); - int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); + int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end, FALSE); if (!bFirstMatchOnly) { @@ -4686,10 +4706,22 @@ INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wParam,LPARA } return FALSE; + + case WM_ACTIVATE: + if (bDoCheckAllOccurrences) { + bFlagsChanged = TRUE; + PostMessage(hwnd, WM_COMMAND, MAKELONG(IDC_FINDTEXT, 1), 0); + } + else { + DialogEnableWindow(hwnd, IDC_REPLACEINSEL, !(BOOL)SendMessage(hwndEdit, SCI_GETSELECTIONEMPTY, 0, 0)); + } + return FALSE; + + case WM_COMMAND: { lpefr = (LPEDITFINDREPLACE)GetWindowLongPtr(hwnd, DWLP_USER); - + switch (LOWORD(wParam)) { case IDC_FINDTEXT: case IDC_REPLACETEXT: @@ -4700,12 +4732,14 @@ INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wParam,LPARA BOOL bEnableR = (GetWindowTextLengthW(GetDlgItem(hwnd, IDC_REPLACETEXT)) || CB_ERR != SendDlgItemMessage(hwnd, IDC_REPLACETEXT, CB_GETCURSEL, 0, 0)); - EnableWindow(GetDlgItem(hwnd, IDOK), bEnableF); - EnableWindow(GetDlgItem(hwnd, IDC_FINDPREV), bEnableF); - EnableWindow(GetDlgItem(hwnd, IDC_REPLACE), bEnableF); - EnableWindow(GetDlgItem(hwnd, IDC_REPLACEALL), bEnableF); - EnableWindow(GetDlgItem(hwnd, IDC_REPLACEINSEL), bEnableF); - EnableWindow(GetDlgItem(hwnd, IDC_SWAPSTRG), bEnableF || bEnableR); + BOOL bEnableIS = !(BOOL)SendMessage(hwndEdit, SCI_GETSELECTIONEMPTY, 0, 0); + + DialogEnableWindow(hwnd, IDOK, bEnableF); + DialogEnableWindow(hwnd, IDC_FINDPREV, bEnableF); + DialogEnableWindow(hwnd, IDC_REPLACE, bEnableF); + DialogEnableWindow(hwnd, IDC_REPLACEALL, bEnableF); + DialogEnableWindow(hwnd, IDC_REPLACEINSEL, bEnableF && bEnableIS); + DialogEnableWindow(hwnd, IDC_SWAPSTRG, bEnableF || bEnableR); if (HIWORD(wParam) == CBN_CLOSEUP) { LONG lSelEnd; @@ -4719,8 +4753,7 @@ INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wParam,LPARA BeginWaitCursor(); StringCchCopyA(lastFind, COUNTOF(lastFind), lpefr->szFind); RegExResult_t match = NO_MATCH; - if (bEnableF) - match = EditFindHasMatch(hwndEdit, lpefr, (iSaveMarkOcc > 0), FALSE); + match = EditFindHasMatch(hwndEdit, lpefr, (iSaveMarkOcc > 0), FALSE); if (regexMatch != match) { regexMatch = match; InvalidateRect(GetDlgItem(hwnd, IDC_FINDTEXT), NULL, TRUE); @@ -4743,7 +4776,9 @@ INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wParam,LPARA lpefr->bWildcardSearch = FALSE; } else { - if (!(IsDlgButtonChecked(hwnd, IDC_WILDCARDSEARCH) == BST_CHECKED)) + if (IsDlgButtonChecked(hwnd, IDC_WILDCARDSEARCH) == BST_CHECKED) + lpefr->fuFlags |= (SCFIND_REGEXP | SCFIND_POSIX); + else lpefr->fuFlags ^= (SCFIND_REGEXP | SCFIND_POSIX); } bFlagsChanged = TRUE; @@ -4754,11 +4789,15 @@ INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wParam,LPARA if (IsDlgButtonChecked(hwnd, IDC_WILDCARDSEARCH) == BST_CHECKED) { CheckDlgButton(hwnd, IDC_FINDREGEXP, BST_UNCHECKED); lpefr->bWildcardSearch = TRUE; - lpefr->fuFlags = (SCFIND_REGEXP | SCFIND_POSIX); + lpefr->fuFlags |= (SCFIND_REGEXP | SCFIND_POSIX); } else { lpefr->bWildcardSearch = FALSE; - if (!(IsDlgButtonChecked(hwnd, IDC_FINDREGEXP) == BST_CHECKED)) + if (IsDlgButtonChecked(hwnd, IDC_FINDREGEXP) == BST_CHECKED) { + lpefr->fuFlags |= (SCFIND_REGEXP | SCFIND_POSIX); + //lpefr->fuFlags ^= SCFIND_POSIX; + } + else lpefr->fuFlags ^= (SCFIND_REGEXP | SCFIND_POSIX); } bFlagsChanged = TRUE; @@ -4817,13 +4856,13 @@ INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wParam,LPARA if (!bSwitchedFindReplace && !GetDlgItemTextW2A(uCPEdit, hwnd, IDC_FINDTEXT, lpefr->szFind, COUNTOF(lpefr->szFind))) { - EnableWindow(GetDlgItem(hwnd, IDOK), FALSE); - EnableWindow(GetDlgItem(hwnd, IDC_FINDPREV), FALSE); - EnableWindow(GetDlgItem(hwnd, IDC_REPLACE), FALSE); - EnableWindow(GetDlgItem(hwnd, IDC_REPLACEALL), FALSE); - EnableWindow(GetDlgItem(hwnd, IDC_REPLACEINSEL), FALSE); + DialogEnableWindow(hwnd, IDOK, FALSE); + DialogEnableWindow(hwnd, IDC_FINDPREV, FALSE); + DialogEnableWindow(hwnd, IDC_REPLACE, FALSE); + DialogEnableWindow(hwnd, IDC_REPLACEALL, FALSE); + DialogEnableWindow(hwnd, IDC_REPLACEINSEL, FALSE); if (!GetDlgItemTextW2A(uCPEdit, hwnd, IDC_REPLACETEXT, lpefr->szReplace, COUNTOF(lpefr->szReplace))) - EnableWindow(GetDlgItem(hwnd, IDC_SWAPSTRG), FALSE); + DialogEnableWindow(hwnd, IDC_SWAPSTRG, FALSE); return TRUE; } @@ -5032,8 +5071,8 @@ INT_PTR CALLBACK EditFindReplaceDlgProcW(HWND hwnd,UINT umsg,WPARAM wParam,LPARA case WM_NOTIFY: { LPNMHDR pnmhdr = (LPNMHDR)lParam; - switch (pnmhdr->code) { - + switch (pnmhdr->code) + { case NM_CLICK: case NM_RETURN: if (pnmhdr->idFrom == IDC_TOGGLEFINDREPLACE) { @@ -5129,36 +5168,6 @@ HWND EditFindReplaceDlg(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bReplace) } -//============================================================================= -// -// EditSetRegexStartAnchor() -// beware of zero-length-matches (regex) ! -// see also : https://www.regular-expressions.info/zerolength.html -// -void __fastcall EditRegexAdaptAnchors(HWND hwnd, LPSTR szFind, int* start, BOOL bFindNext) -{ - int len = StringCchLenA(szFind, FNDRPL_BUFFER); - int nx = 1; - char* pBeg = (char*)StrChrA(szFind, '^'); - BOOL esc1 = ((pBeg > szFind) && (*(--pBeg) == '\\')); - if (pBeg && !esc1) { - int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, *start, 0); - int iLnBeg = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, iLine, 0); - int iLnEnd = (int)SendMessage(hwnd, SCI_GETLINEENDPOSITION, iLine, 0); - if (bFindNext && ((iLnBeg != *start) || (iLnEnd == *start) || (len == 1))) - *start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (iLine + nx--), 0); - } - char* pEnd = (char*)StrChrA(szFind, '$'); - BOOL esc2 = ((pEnd > szFind) && (*(--pEnd) == '\\')); - if (pEnd && !esc2) { - int iLine = (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, *start, 0); - int iLnEnd = (int)SendMessage(hwnd, SCI_GETLINEENDPOSITION, iLine, 0); - if (bFindNext && (iLnEnd == *start)) - *start = (int)SendMessage(hwnd, SCI_POSITIONFROMLINE, (iLine + nx), 0); - } -} - - //============================================================================= // // EditFindNext() @@ -5177,9 +5186,6 @@ BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bExtendSelection) { int start = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); int end = iTextLength; - if (lpefr->fuFlags & SCFIND_REGEXP) { - EditRegexAdaptAnchors(hwnd, szFind, &start, TRUE); - } if (start > end) { if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { end = min(start, iTextLength); start = 0; @@ -5188,12 +5194,24 @@ BOOL EditFindNext(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bExtendSelection) { bSuppressNotFound = TRUE; } - int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); + int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end, TRUE); - if ((iPos < 0) && (start > 0) && !lpefr->bNoFindWrap && !bExtendSelection && !bSuppressNotFound) { - if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { + if ((iPos < -1) && (lpefr->fuFlags & SCFIND_REGEXP)) { + InfoBox(MBWARN, L"MsgInvalidRegex", IDS_REGEX_INVALID); + bSuppressNotFound = TRUE; + } + else if ((iPos < 0) && (start > 0) && !lpefr->bNoFindWrap && !bExtendSelection && !bSuppressNotFound) + { + if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap2", IDS_FIND_WRAPFW)) + { end = min(start, iTextLength); start = 0; - iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); + + iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end, FALSE); + + if ((iPos < -1) && (lpefr->fuFlags & SCFIND_REGEXP)) { + InfoBox(MBWARN, L"MsgInvalidRegex2", IDS_REGEX_INVALID); + bSuppressNotFound = TRUE; + } } else bSuppressNotFound = TRUE; @@ -5235,9 +5253,6 @@ BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bExtendSelection) { int start = max(0, (int)SendMessage(hwnd, SCI_GETSELECTIONSTART, 0, 0)); int end = 0; - if (lpefr->fuFlags & SCFIND_REGEXP) { - EditRegexAdaptAnchors(hwnd, szFind, &start, FALSE); - } if (start <= end) { if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap1", IDS_FIND_WRAPFW)) { end = start; start = iTextLength; @@ -5246,12 +5261,25 @@ BOOL EditFindPrev(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bExtendSelection) { bSuppressNotFound = TRUE; } - int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); + int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end, TRUE); - if ((iPos < 0) && (start <= iTextLength) && !lpefr->bNoFindWrap && !bExtendSelection && !bSuppressNotFound) { - if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap2", IDS_FIND_WRAPRE)) { + if ((iPos < -1) && (lpefr->fuFlags & SCFIND_REGEXP)) + { + InfoBox(MBWARN, L"MsgInvalidRegex", IDS_REGEX_INVALID); + bSuppressNotFound = TRUE; + } + else if ((iPos < 0) && (start <= iTextLength) && !lpefr->bNoFindWrap && !bExtendSelection && !bSuppressNotFound) + { + if (IDOK == InfoBox(MBOKCANCEL, L"MsgFindWrap2", IDS_FIND_WRAPRE)) + { end = start; start = iTextLength; - iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); + + iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end, FALSE); + + if ((iPos < -1) && (lpefr->fuFlags & SCFIND_REGEXP)) { + InfoBox(MBWARN, L"MsgInvalidRegex2", IDS_REGEX_INVALID); + bSuppressNotFound = TRUE; + } } else bSuppressNotFound = TRUE; @@ -5310,6 +5338,26 @@ BOOL EditReplace(HWND hwnd, LPCEDITFINDREPLACE lpefr) { return FALSE; // recoding of clipboard canceled // w/o selection, replacement string is put into current position + // but this mayby not intended here + if ((BOOL)SendMessage(hwnd, SCI_GETSELECTIONEMPTY, 0, 0)) { + int start = (int)SendMessage(hwnd, SCI_GETCURRENTPOS, 0, 0); + int end = (int)SendMessage(hwnd, SCI_GETTEXTLENGTH, start, 0); + int _start = start; + int iPos = EditFindInTarget(hwnd, lpefr->szFind, + StringCchLenA(lpefr->szFind, FNDRPL_BUFFER), + (int)(lpefr->fuFlags), &start, &end, FALSE); + if ((iPos < 0) || (_start != start) || (_start != end)) { + // empty-replace was not intended + LocalFree(pszReplace); + if (iPos < 0) + return EditFindNext(hwnd, lpefr, FALSE); + else { + EditSelectEx(hwnd, start, end); + return TRUE; + } + } + } + SendMessage(hwnd, SCI_TARGETFROMSELECTION, 0, 0); SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); @@ -5343,39 +5391,39 @@ int EditReplaceAllInRange(HWND hwnd, LPCEDITFINDREPLACE lpefr, BOOL bShowInfo, i if (!pszReplace) return -1; // recoding of clipboard canceled - int iDiffToDocEnd = (int)SendMessage(hwnd, SCI_GETTEXTLENGTH, 0, 0) - iEndPos; - - BeginWaitCursor(); - - int iPos = 0; int iCount = 0; int start = iStartPos; int end = iEndPos; - while ((iPos >= 0) && (start <= end) && (end <= iEndPos)) - { - iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end); + BeginWaitCursor(); - if ((iPos >= 0) && (end <= iEndPos)) { + int iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end, FALSE); - if (++iCount == 1) - SendMessage(hwnd, SCI_BEGINUNDOACTION, 0, 0); - - // replace - int iReplLen = (int)SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); - - // move start behind replacement; target region maybe extended by replacement - iEndPos = (int)SendMessage(hwnd, SCI_GETTEXTLENGTH, 0, 0) - iDiffToDocEnd; - start += iReplLen; - end = iEndPos; - - // correction for regex - if (lpefr->fuFlags & SCFIND_REGEXP) { - EditRegexAdaptAnchors(hwnd, szFind, &start, TRUE); - } - } + if ((iPos < -1) && (lpefr->fuFlags & SCFIND_REGEXP)) { + InfoBox(MBWARN, L"MsgInvalidRegex", IDS_REGEX_INVALID); + bShowInfo = FALSE; } + while ((iPos >= 0) && (start <= iEndPos)) + { + if (++iCount == 1) + SendMessage(hwnd, SCI_BEGINUNDOACTION, 0, 0); + + // replace + int iReplLen = (int)SendMessage(hwnd, iReplaceMsg, (WPARAM)-1, (LPARAM)pszReplace); + + // move start behind replacement; target region maybe extended by replacement + int iFoundLen = (end - start); + iEndPos += (iReplLen - iFoundLen); + start += iReplLen; + end = iEndPos; + + if (start <= iEndPos) + iPos = EditFindInTarget(hwnd, szFind, slen, (int)(lpefr->fuFlags), &start, &end, (iFoundLen == 0)); + else + iPos = -1; + } + EndWaitCursor(); LocalFree(pszReplace); @@ -5455,15 +5503,24 @@ BOOL EditReplaceAllInSelection(HWND hwnd,LPCEDITFINDREPLACE lpefr,BOOL bShowInfo //============================================================================= // -// EditMarkAll() -// Mark all occurrences of the text currently selected (by Aleksandar Lekov) +// EditClearAllMarks() // -void EditMarkAll(HWND hwnd, char* pszFind, int flags, BOOL bMatchCase, BOOL bMatchWords) +void EditClearAllMarks(HWND hwnd) { - // clear all marks SendMessage(hwnd, SCI_SETINDICATORCURRENT, INDIC_NP3_MARK_OCCURANCE, 0); SendMessage(hwnd, SCI_INDICATORCLEARRANGE, 0, (int)SendMessage(hwnd, SCI_GETLENGTH, 0, 0)); iMarkOccurrencesCount = -1; // -1 ! +} + + +//============================================================================= +// +// EditMarkAll() +// Mark all occurrences of the text currently selected (by Aleksandar Lekov) +// +void EditMarkAll(HWND hwnd, char* pszFind, int flags, BOOL bMatchCase, BOOL bMatchWords) +{ + EditClearAllMarks(hwnd); int iTextLength = (int)SendMessage(hwnd, SCI_GETTEXTLENGTH, 0, 0); int iFindLength = 0; @@ -5476,10 +5533,6 @@ void EditMarkAll(HWND hwnd, char* pszFind, int flags, BOOL bMatchCase, BOOL bMat int iSelEnd = (int)SendMessage(hwnd, SCI_GETSELECTIONEND, 0, 0); int iSelCount = iSelEnd - iSelStart; - // clear existing marker indicators - SendMessage(hwnd, SCI_SETINDICATORCURRENT, INDIC_NP3_MARK_OCCURANCE, 0); - SendMessage(hwnd, SCI_INDICATORCLEARRANGE, 0, iTextLength); - // if nothing selected or multiple lines are selected exit if ((iSelCount == 0) || (int)SendMessage(hwnd, SCI_LINEFROMPOSITION, iSelStart, 0) != @@ -5519,19 +5572,21 @@ void EditMarkAll(HWND hwnd, char* pszFind, int flags, BOOL bMatchCase, BOOL bMat while (++iMarkOccurrencesCount < iMarkOccurrencesMaxCount) { - iPos = EditFindInTarget(hwnd, pszText, iFindLength, flags, &start, &end); + iPos = EditFindInTarget(hwnd, pszText, iFindLength, flags, &start, &end, (end == start)); if (iPos < 0) break; // not found // mark this match SendMessage(hwnd, SCI_INDICATORFILLRANGE, iPos, (end - start)); - start = end + 1; end = iTextLength; + start = end; + end = iTextLength; if (start >= end) break; } + // free text buffer if not set from outside (pszFind) if (pszFind == NULL) LocalFree(pszText); @@ -5587,17 +5642,17 @@ void EditCompleteWord(HWND hwnd, BOOL autoInsert) { int start = 0; int end = iTextLength; - int iPosFind = EditFindInTarget(hwnd, pRoot, iRootLen, SCFIND_WORDSTART, &start, &end); + int iPosFind = EditFindInTarget(hwnd, pRoot, iRootLen, SCFIND_WORDSTART, &start, &end, FALSE); int iNumWords = 0; char* pWord = NULL; - while (iPosFind >= 0 && iPosFind < iTextLength) { + while (iPosFind >= 0 && iPosFind <= iTextLength) { int wordEnd = iPosFind + iRootLen; if (iPosFind != iCurrentPos - iRootLen) { - while (wordEnd < iTextLength && !StrChrIA(NON_WORD, (char)SendMessage(hwnd, SCI_GETCHARAT, (WPARAM)wordEnd, 0))) - wordEnd++; - + while (wordEnd < iTextLength && !StrChrIA(NON_WORD, (char)SendMessage(hwnd, SCI_GETCHARAT, (WPARAM)wordEnd, 0))) { + ++wordEnd; + } int wordLength = wordEnd - iPosFind; if (wordLength > iRootLen) { struct WLIST* p = lListHead; @@ -5642,8 +5697,9 @@ void EditCompleteWord(HWND hwnd, BOOL autoInsert) { LocalFree(pWord); } } - start = wordEnd; end = iTextLength; - iPosFind = EditFindInTarget(hwnd, pRoot, iRootLen, SCFIND_WORDSTART, &start, &end); + start = wordEnd; + end = iTextLength; + iPosFind = EditFindInTarget(hwnd, pRoot, iRootLen, SCFIND_WORDSTART, &start, &end, (end == start)); } if (iNumWords > 0) { @@ -6336,11 +6392,11 @@ INT_PTR CALLBACK EditSortDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam CheckRadioButton(hwnd,100,102,101); else if (*piSortFlags & SORT_SHUFFLE) { CheckRadioButton(hwnd,100,102,102); - EnableWindow(GetDlgItem(hwnd,103),FALSE); - EnableWindow(GetDlgItem(hwnd,104),FALSE); - EnableWindow(GetDlgItem(hwnd,105),FALSE); - EnableWindow(GetDlgItem(hwnd,106),FALSE); - EnableWindow(GetDlgItem(hwnd,107),FALSE); + DialogEnableWindow(hwnd,103,FALSE); + DialogEnableWindow(hwnd,104,FALSE); + DialogEnableWindow(hwnd,105,FALSE); + DialogEnableWindow(hwnd,106,FALSE); + DialogEnableWindow(hwnd,107,FALSE); } else CheckRadioButton(hwnd,100,102,100); @@ -6348,7 +6404,7 @@ INT_PTR CALLBACK EditSortDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam CheckDlgButton(hwnd,103,BST_CHECKED); if (*piSortFlags & SORT_UNIQDUP) { CheckDlgButton(hwnd,104,BST_CHECKED); - EnableWindow(GetDlgItem(hwnd,103),FALSE); + DialogEnableWindow(hwnd,103,FALSE); } if (*piSortFlags & SORT_UNIQUNIQ) CheckDlgButton(hwnd,105,BST_CHECKED); @@ -6360,12 +6416,12 @@ INT_PTR CALLBACK EditSortDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam bEnableLogicalSort = TRUE; } else { - EnableWindow(GetDlgItem(hwnd,107),FALSE); + DialogEnableWindow(hwnd,107,FALSE); bEnableLogicalSort = FALSE; } if (SC_SEL_RECTANGLE != SendMessage(hwndEdit,SCI_GETSELECTIONMODE,0,0)) { *piSortFlags &= ~SORT_COLUMN; - EnableWindow(GetDlgItem(hwnd,108),FALSE); + DialogEnableWindow(hwnd,108,FALSE); } else { *piSortFlags |= SORT_COLUMN; @@ -6403,21 +6459,21 @@ INT_PTR CALLBACK EditSortDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lParam break; case 100: case 101: - EnableWindow(GetDlgItem(hwnd,103),IsDlgButtonChecked(hwnd,105) != BST_CHECKED); - EnableWindow(GetDlgItem(hwnd,104),TRUE); - EnableWindow(GetDlgItem(hwnd,105),TRUE); - EnableWindow(GetDlgItem(hwnd,106),TRUE); - EnableWindow(GetDlgItem(hwnd,107),bEnableLogicalSort); + DialogEnableWindow(hwnd,103,IsDlgButtonChecked(hwnd,105) != BST_CHECKED); + DialogEnableWindow(hwnd,104,TRUE); + DialogEnableWindow(hwnd,105,TRUE); + DialogEnableWindow(hwnd,106,TRUE); + DialogEnableWindow(hwnd,107,bEnableLogicalSort); break; case 102: - EnableWindow(GetDlgItem(hwnd,103),FALSE); - EnableWindow(GetDlgItem(hwnd,104),FALSE); - EnableWindow(GetDlgItem(hwnd,105),FALSE); - EnableWindow(GetDlgItem(hwnd,106),FALSE); - EnableWindow(GetDlgItem(hwnd,107),FALSE); + DialogEnableWindow(hwnd,103,FALSE); + DialogEnableWindow(hwnd,104,FALSE); + DialogEnableWindow(hwnd,105,FALSE); + DialogEnableWindow(hwnd,106,FALSE); + DialogEnableWindow(hwnd,107,FALSE); break; case 104: - EnableWindow(GetDlgItem(hwnd,103),IsDlgButtonChecked(hwnd,104) != BST_CHECKED); + DialogEnableWindow(hwnd,103,IsDlgButtonChecked(hwnd,104) != BST_CHECKED); break; } return TRUE; diff --git a/src/Edit.h b/src/Edit.h index 67e272c22..053d5d167 100644 --- a/src/Edit.h +++ b/src/Edit.h @@ -116,6 +116,7 @@ BOOL EditPrint(HWND,LPCWSTR,LPCWSTR); void EditPrintSetup(HWND); void EditPrintInit(); void EditMatchBrace(HWND); +void EditClearAllMarks(HWND); void EditMarkAll(HWND,char*,int,BOOL,BOOL); void EditSetAccelWordNav(HWND,BOOL); void EditCompleteWord(HWND,BOOL); diff --git a/src/Helpers.c b/src/Helpers.c index bca2fbef8..78022a501 100644 --- a/src/Helpers.c +++ b/src/Helpers.c @@ -36,6 +36,7 @@ //#include #include "scintilla.h" #include "resource.h" +#include "edit.h" #include "helpers.h" @@ -2436,6 +2437,43 @@ void TransformBackslashes(char* pszInput,BOOL bRegEx,UINT cpEdit) } + +void TransformMetaChars(char* pszInput, BOOL bRegEx, int iEOLMode) +{ + if (!bRegEx) return; + + char buffer[FNDRPL_BUFFER + 1] = { '\0' }; + char* s = pszInput; + char* o = buffer; + while (*s) { + if ((s[0] != '\\') && (s[1] == '$')) { + *o = *s; ++o; ++s; + switch (iEOLMode) { + case SC_EOL_LF: + *o = '\n'; + break; + case SC_EOL_CR: + *o = '\r'; + break; + case SC_EOL_CRLF: + default: + *o = '\r'; ++o; *o = '\n'; + break; + } + ++s; // skip $ + } + else { + *o = *s; + } + ++o; + if (*s) ++s; + } + *o = '\0'; + StringCchCopyA(pszInput, FNDRPL_BUFFER, buffer); +} + + + /* MinimizeToTray - Copyright 2000 Matthew Ellis diff --git a/src/Helpers.h b/src/Helpers.h index 8a2291053..4d4b62630 100644 --- a/src/Helpers.h +++ b/src/Helpers.h @@ -156,6 +156,8 @@ BOOL IsCmdEnabled(HWND, UINT); #define EnableCmd(hmenu,id,b) EnableMenuItem(hmenu,id,(b)?MF_BYCOMMAND|MF_ENABLED:MF_BYCOMMAND|MF_GRAYED) #define CheckCmd(hmenu,id,b) CheckMenuItem(hmenu,id,(b)?MF_BYCOMMAND|MF_CHECKED:MF_BYCOMMAND|MF_UNCHECKED) +#define DialogEnableWindow(hdlg, id, b) { HWND hctrl = GetDlgItem((hdlg),(id)); if (!(b)) { \ + if (GetFocus() == hctrl) { SendMessage((hdlg), WM_NEXTDLGCTL, 0, FALSE); } }; EnableWindow(hctrl, (b)); } #define GetString(id,pb,cb) LoadString(g_hInstance,id,pb,cb) #define StrEnd(pStart) (pStart + lstrlen(pStart)) @@ -268,7 +270,7 @@ HWND CreateThemedDialogParam(HINSTANCE,LPCTSTR,HWND,DLGPROC,LPARAM); //==== UnSlash Functions ====================================================== void TransformBackslashes(char*,BOOL,UINT); - +void TransformMetaChars(char*,BOOL,int); //==== MinimizeToTray Functions - see comments in Helpers.c =================== BOOL GetDoAnimateMinimize(VOID); diff --git a/src/Notepad3.rc b/src/Notepad3.rc index a8bdc6076..436ef3893 100644 Binary files a/src/Notepad3.rc and b/src/Notepad3.rc differ diff --git a/src/Styles.c b/src/Styles.c index c2b5c2b34..aa6193ea8 100644 --- a/src/Styles.c +++ b/src/Styles.c @@ -4804,15 +4804,15 @@ INT_PTR CALLBACK Style_ConfigDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lP if (pCurrentLexer) { SetDlgItemText(hwnd,IDC_STYLELABEL,wch); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEEDIT),TRUE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEFONT),FALSE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEFORE),FALSE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEBACK),FALSE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEDEFAULT),TRUE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEBOLD),FALSE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEITALIC),FALSE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEUNDERLINE),FALSE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEEOLFILLED),FALSE); + DialogEnableWindow(hwnd,IDC_STYLEEDIT,TRUE); + DialogEnableWindow(hwnd,IDC_STYLEFONT,FALSE); + DialogEnableWindow(hwnd,IDC_STYLEFORE,FALSE); + DialogEnableWindow(hwnd,IDC_STYLEBACK,FALSE); + DialogEnableWindow(hwnd,IDC_STYLEDEFAULT,TRUE); + //DialogEnableWindow(hwnd,IDC_STYLEBOLD,FALSE); + //DialogEnableWindow(hwnd,IDC_STYLEITALIC,FALSE); + //DialogEnableWindow(hwnd,IDC_STYLEUNDERLINE,FALSE); + //DialogEnableWindow(hwnd,IDC_STYLEEOLFILLED,FALSE); //CheckDlgButton(hwnd,IDC_STYLEBOLD,BST_UNCHECKED); //CheckDlgButton(hwnd,IDC_STYLEITALIC,BST_UNCHECKED); //CheckDlgButton(hwnd,IDC_STYLEUNDERLINE,BST_UNCHECKED); @@ -4822,15 +4822,15 @@ INT_PTR CALLBACK Style_ConfigDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lP else { SetDlgItemText(hwnd,IDC_STYLELABEL,L""); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEEDIT),FALSE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEFONT),FALSE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEFORE),FALSE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEBACK),FALSE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEDEFAULT),FALSE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEBOLD),FALSE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEITALIC),FALSE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEUNDERLINE),FALSE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEEOLFILLED),FALSE); + DialogEnableWindow(hwnd,IDC_STYLEEDIT,FALSE); + DialogEnableWindow(hwnd,IDC_STYLEFONT,FALSE); + DialogEnableWindow(hwnd,IDC_STYLEFORE,FALSE); + DialogEnableWindow(hwnd,IDC_STYLEBACK,FALSE); + DialogEnableWindow(hwnd,IDC_STYLEDEFAULT,FALSE); + //DialogEnableWindow(hwnd,IDC_STYLEBOLD,FALSE); + //DialogEnableWindow(hwnd,IDC_STYLEITALIC,FALSE); + //DialogEnableWindow(hwnd,IDC_STYLEUNDERLINE,FALSE); + //DialogEnableWindow(hwnd,IDC_STYLEEOLFILLED,FALSE); //CheckDlgButton(hwnd,IDC_STYLEBOLD,BST_UNCHECKED); //CheckDlgButton(hwnd,IDC_STYLEITALIC,BST_UNCHECKED); //CheckDlgButton(hwnd,IDC_STYLEUNDERLINE,BST_UNCHECKED); @@ -4853,15 +4853,15 @@ INT_PTR CALLBACK Style_ConfigDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lP if (pCurrentStyle) { SetDlgItemText(hwnd,IDC_STYLELABEL,StrEnd(wch)+1); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEEDIT),TRUE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEFONT),TRUE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEFORE),TRUE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEBACK),TRUE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEDEFAULT),TRUE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEBOLD),TRUE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEITALIC),TRUE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEUNDERLINE),TRUE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEEOLFILLED),TRUE); + DialogEnableWindow(hwnd,IDC_STYLEEDIT,TRUE); + DialogEnableWindow(hwnd,IDC_STYLEFONT,TRUE); + DialogEnableWindow(hwnd,IDC_STYLEFORE,TRUE); + DialogEnableWindow(hwnd,IDC_STYLEBACK,TRUE); + DialogEnableWindow(hwnd,IDC_STYLEDEFAULT,TRUE); + //DialogEnableWindow(hwnd,IDC_STYLEBOLD,TRUE); + //DialogEnableWindow(hwnd,IDC_STYLEITALIC,TRUE); + //DialogEnableWindow(hwnd,IDC_STYLEUNDERLINE,TRUE); + //DialogEnableWindow(hwnd,IDC_STYLEEOLFILLED,TRUE); //CheckDlgButton(hwnd,IDC_STYLEBOLD,(Style_StrGetAttribute(pCurrentStyle->szValue,L"bold") ? BST_CHECKED : BST_UNCHECKED)); //CheckDlgButton(hwnd,IDC_STYLEITALIC,(Style_StrGetAttribute(pCurrentStyle->szValue,L"italic") ? BST_CHECKED : BST_UNCHECKED)); //CheckDlgButton(hwnd,IDC_STYLEUNDERLINE,(Style_StrGetAttribute(pCurrentStyle->szValue,L"underline") ? BST_CHECKED : BST_UNCHECKED)); @@ -4871,15 +4871,15 @@ INT_PTR CALLBACK Style_ConfigDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPARAM lP else { SetDlgItemText(hwnd,IDC_STYLELABEL,L""); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEEDIT),FALSE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEFONT),FALSE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEFORE),FALSE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEBACK),FALSE); - EnableWindow(GetDlgItem(hwnd,IDC_STYLEDEFAULT),FALSE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEBOLD),FALSE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEITALIC),FALSE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEUNDERLINE),FALSE); - //EnableWindow(GetDlgItem(hwnd,IDC_STYLEEOLFILLED),FALSE); + DialogEnableWindow(hwnd,IDC_STYLEEDIT,FALSE); + DialogEnableWindow(hwnd,IDC_STYLEFONT,FALSE); + DialogEnableWindow(hwnd,IDC_STYLEFORE,FALSE); + DialogEnableWindow(hwnd,IDC_STYLEBACK,FALSE); + DialogEnableWindow(hwnd,IDC_STYLEDEFAULT,FALSE); + //DialogEnableWindow(hwnd,IDC_STYLEBOLD,FALSE); + //DialogEnableWindow(hwnd,IDC_STYLEITALIC,FALSE); + //DialogEnableWindow(hwnd,IDC_STYLEUNDERLINE,FALSE); + //DialogEnableWindow(hwnd,IDC_STYLEEOLFILLED,FALSE); //CheckDlgButton(hwnd,IDC_STYLEBOLD,BST_UNCHECKED); //CheckDlgButton(hwnd,IDC_STYLEITALIC,BST_UNCHECKED); //CheckDlgButton(hwnd,IDC_STYLEUNDERLINE,BST_UNCHECKED); @@ -5463,8 +5463,8 @@ INT_PTR CALLBACK Style_SelectLexerDlgProc(HWND hwnd,UINT umsg,WPARAM wParam,LPAR CheckDlgButton(hwnd,IDC_DEFAULTSCHEME,BST_CHECKED); else CheckDlgButton(hwnd,IDC_DEFAULTSCHEME,BST_UNCHECKED); - EnableWindow(GetDlgItem(hwnd,IDC_DEFAULTSCHEME),i != -1); - EnableWindow(GetDlgItem(hwnd,IDOK),i != -1); + DialogEnableWindow(hwnd,IDC_DEFAULTSCHEME,i != -1); + DialogEnableWindow(hwnd,IDOK,i != -1); } break; } diff --git a/src/Version.h b/src/Version.h index a587e7f77..457fb37d2 100644 --- a/src/Version.h +++ b/src/Version.h @@ -41,7 +41,7 @@ #define VERSION_COMPANYNAME L"© Rizonesoft" #define VERSION_MODPAGEDISPLAY L"https://xhmikosr.github.io/notepad2-mod/" #define VERSION_WEBPAGE2DISPLAY L"http://www.flos-freeware.ch" -#define VERSION_SCIVERSION L"Scintilla Library Version: " STRINGIFY(SCINTILLA_VER) +#define VERSION_SCIVERSION L"Scintilla Library (RegEx:DeelX) Version: " STRINGIFY(SCINTILLA_VER) #if defined(_WIN64) // #define VERSION_FILEVERSION_LONG L"Notepad3 (64-bit) " STRINGIFY(VERSION_MAJOR) L" Build " \ diff --git a/src/resource.h b/src/resource.h index 0d983edec..80628c2c8 100644 --- a/src/resource.h +++ b/src/resource.h @@ -457,6 +457,7 @@ #define IDS_EXPORT_FAIL 50040 #define IDS_ERR_ACCESSDENIED 50041 #define IDS_WARN_UNKNOWN_EXT 50042 +#define IDS_REGEX_INVALID 50043 #define IDS_CMDLINEHELP 60000 #define IDM_EDIT_INSERT_GUID 60001 #define IDC_STATIC -1