From 50c7e228ff71379fb0177aebae36931a4631188d Mon Sep 17 00:00:00 2001 From: Don HO Date: Thu, 31 Mar 2016 09:35:18 +0200 Subject: [PATCH] Add new feature: Find in Finder After finding in files, user can launch the find in Finder dialog from the finder via its context menu command "Find in this finder...". Find in Finder feature searchs the other occurrence into found results,, that allow user to narrow down the search and to refine their search results. --- PowerEditor/src/Notepad_plus.cpp | 101 +++- PowerEditor/src/Notepad_plus.h | 3 + PowerEditor/src/NppBigSwitch.cpp | 38 +- .../src/ScitillaComponent/FindReplaceDlg.cpp | 509 ++++++++++++++---- .../src/ScitillaComponent/FindReplaceDlg.h | 108 ++-- .../src/ScitillaComponent/FindReplaceDlg.rc | 22 +- .../src/ScitillaComponent/FindReplaceDlg_rc.h | 13 + .../src/ScitillaComponent/ScintillaEditView.h | 24 +- .../ScitillaComponent/SmartHighlighter.cpp | 17 +- PowerEditor/src/WinControls/Window.h | 1 - PowerEditor/src/resource.h | 2 + 11 files changed, 668 insertions(+), 170 deletions(-) diff --git a/PowerEditor/src/Notepad_plus.cpp b/PowerEditor/src/Notepad_plus.cpp index b67d80f82..c9e34bad4 100644 --- a/PowerEditor/src/Notepad_plus.cpp +++ b/PowerEditor/src/Notepad_plus.cpp @@ -617,6 +617,7 @@ LRESULT Notepad_plus::init(HWND hwnd) //--Init dialogs--// _findReplaceDlg.init(_pPublicInterface->getHinst(), hwnd, &_pEditView); + _findInFinderDlg.init(_pPublicInterface->getHinst(), hwnd); _incrementFindDlg.init(_pPublicInterface->getHinst(), hwnd, &_findReplaceDlg, _nativeLangSpeaker.isRTL()); _incrementFindDlg.addToRebar(&_rebarBottom); _goToLineDlg.init(_pPublicInterface->getHinst(), hwnd, &_pEditView); @@ -1501,7 +1502,9 @@ bool Notepad_plus::replaceInFiles() _invisibleEditView.execute(SCI_SETCODEPAGE, pBuf->getUnicodeMode() == uni8Bit ? cp : SC_CP_UTF8); _invisibleEditView.setCurrentBuffer(pBuf); - int nbReplaced = _findReplaceDlg.processAll(ProcessReplaceAll, FindReplaceDlg::_env, true, fileNames.at(i).c_str()); + FindersInfo findersInfo; + findersInfo._pFileName = fileNames.at(i).c_str(); + int nbReplaced = _findReplaceDlg.processAll(ProcessReplaceAll, FindReplaceDlg::_env, true, &findersInfo); nbTotal += nbReplaced; if (nbReplaced) { @@ -1535,11 +1538,87 @@ bool Notepad_plus::replaceInFiles() return true; } +bool Notepad_plus::findInFinderFiles(FindersInfo *findInFolderInfo) +{ + int nbTotal = 0; + ScintillaEditView *pOldView = _pEditView; + _pEditView = &_invisibleEditView; + Document oldDoc = _invisibleEditView.execute(SCI_GETDOCPOINTER); + + vector patterns2Match; + _findReplaceDlg.getPatterns(patterns2Match); + if (patterns2Match.size() == 0) + { + _findReplaceDlg.setFindInFilesDirFilter(NULL, TEXT("*.*")); + _findReplaceDlg.getPatterns(patterns2Match); + } + + vector fileNames = findInFolderInfo->_pSourceFinder->getResultFilePaths(); + + findInFolderInfo->_pDestFinder->beginNewFilesSearch(); + findInFolderInfo->_pDestFinder->addSearchLine(findInFolderInfo->_findOption._str2Search.c_str()); + + Progress progress(_pPublicInterface->getHinst()); + + size_t filesCount = fileNames.size(); + size_t filesPerPercent = 1; + + if (filesCount > 1) + { + if (filesCount >= 200) + filesPerPercent = filesCount / 100; + progress.open(_findReplaceDlg.getHSelf(), TEXT("Find In Files progress...")); + } + + for (size_t i = 0, updateOnCount = filesPerPercent; i < filesCount; ++i) + { + if (progress.isCancelled()) break; + + bool closeBuf = false; + BufferID id = MainFileManager->getBufferFromName(fileNames.at(i).c_str()); + if (id == BUFFER_INVALID) + { + id = MainFileManager->loadFile(fileNames.at(i).c_str()); + closeBuf = true; + } + + if (id != BUFFER_INVALID) + { + Buffer * pBuf = MainFileManager->getBufferByID(id); + _invisibleEditView.execute(SCI_SETDOCPOINTER, 0, pBuf->getDocument()); + int cp = _invisibleEditView.execute(SCI_GETCODEPAGE); + _invisibleEditView.execute(SCI_SETCODEPAGE, pBuf->getUnicodeMode() == uni8Bit ? cp : SC_CP_UTF8); + + findInFolderInfo->_pFileName = fileNames.at(i).c_str(); + nbTotal += _findReplaceDlg.processAll(ProcessFindInFinder, &(findInFolderInfo->_findOption), true, findInFolderInfo); + if (closeBuf) + MainFileManager->closeBuffer(id, _pEditView); + } + if (i == updateOnCount) + { + updateOnCount += filesPerPercent; + progress.setPercent((i * 100) / filesCount, fileNames.at(i).c_str()); + } + else + { + progress.setInfo(fileNames.at(i).c_str()); + } + } + progress.close(); + + findInFolderInfo->_pDestFinder->finishFilesSearch(nbTotal, findInFolderInfo->_findOption._isMatchLineNumber); + + _invisibleEditView.execute(SCI_SETDOCPOINTER, 0, oldDoc); + _pEditView = pOldView; + + return true; +} + bool Notepad_plus::findInFiles() { const TCHAR *dir2Search = _findReplaceDlg.getDir2Search(); - if (!dir2Search[0] || !::PathFileExists(dir2Search)) + if (not dir2Search[0] || not ::PathFileExists(dir2Search)) { return false; } @@ -1558,6 +1637,7 @@ bool Notepad_plus::findInFiles() _findReplaceDlg.setFindInFilesDirFilter(NULL, TEXT("*.*")); _findReplaceDlg.getPatterns(patterns2Match); } + vector fileNames; getMatchedFileNames(dir2Search, patterns2Match, fileNames, isRecursive, isInHiddenDir); @@ -1593,8 +1673,9 @@ bool Notepad_plus::findInFiles() _invisibleEditView.execute(SCI_SETDOCPOINTER, 0, pBuf->getDocument()); int cp = _invisibleEditView.execute(SCI_GETCODEPAGE); _invisibleEditView.execute(SCI_SETCODEPAGE, pBuf->getUnicodeMode() == uni8Bit ? cp : SC_CP_UTF8); - - nbTotal += _findReplaceDlg.processAll(ProcessFindAll, FindReplaceDlg::_env, true, fileNames.at(i).c_str()); + FindersInfo findersInfo; + findersInfo._pFileName = fileNames.at(i).c_str(); + nbTotal += _findReplaceDlg.processAll(ProcessFindAll, FindReplaceDlg::_env, true, &findersInfo); if (closeBuf) MainFileManager->closeBuffer(id, _pEditView); } @@ -1646,7 +1727,9 @@ bool Notepad_plus::findInOpenedFiles() _invisibleEditView.execute(SCI_SETDOCPOINTER, 0, pBuf->getDocument()); int cp = _invisibleEditView.execute(SCI_GETCODEPAGE); _invisibleEditView.execute(SCI_SETCODEPAGE, pBuf->getUnicodeMode() == uni8Bit ? cp : SC_CP_UTF8); - nbTotal += _findReplaceDlg.processAll(ProcessFindAll, FindReplaceDlg::_env, isEntireDoc, pBuf->getFullPathName()); + FindersInfo findersInfo; + findersInfo._pFileName = pBuf->getFullPathName(); + nbTotal += _findReplaceDlg.processAll(ProcessFindAll, FindReplaceDlg::_env, isEntireDoc, &findersInfo); } } @@ -1658,7 +1741,9 @@ bool Notepad_plus::findInOpenedFiles() _invisibleEditView.execute(SCI_SETDOCPOINTER, 0, pBuf->getDocument()); int cp = _invisibleEditView.execute(SCI_GETCODEPAGE); _invisibleEditView.execute(SCI_SETCODEPAGE, pBuf->getUnicodeMode() == uni8Bit ? cp : SC_CP_UTF8); - nbTotal += _findReplaceDlg.processAll(ProcessFindAll, FindReplaceDlg::_env, isEntireDoc, pBuf->getFullPathName()); + FindersInfo findersInfo; + findersInfo._pFileName = pBuf->getFullPathName(); + nbTotal += _findReplaceDlg.processAll(ProcessFindAll, FindReplaceDlg::_env, isEntireDoc, &findersInfo); } } @@ -1691,7 +1776,9 @@ bool Notepad_plus::findInCurrentFile() _invisibleEditView.execute(SCI_SETDOCPOINTER, 0, pBuf->getDocument()); int cp = _invisibleEditView.execute(SCI_GETCODEPAGE); _invisibleEditView.execute(SCI_SETCODEPAGE, pBuf->getUnicodeMode() == uni8Bit ? cp : SC_CP_UTF8); - nbTotal += _findReplaceDlg.processAll(ProcessFindAll, FindReplaceDlg::_env, isEntireDoc, pBuf->getFullPathName()); + FindersInfo findersInfo; + findersInfo._pFileName = pBuf->getFullPathName(); + nbTotal += _findReplaceDlg.processAll(ProcessFindAll, FindReplaceDlg::_env, isEntireDoc, &findersInfo); _findReplaceDlg.finishFilesSearch(nbTotal); diff --git a/PowerEditor/src/Notepad_plus.h b/PowerEditor/src/Notepad_plus.h index de2d9daf5..bb9e60620 100644 --- a/PowerEditor/src/Notepad_plus.h +++ b/PowerEditor/src/Notepad_plus.h @@ -282,6 +282,7 @@ public: bool loadSession(Session & session, bool isSnapshotMode = false); void notifyBufferChanged(Buffer * buffer, int mask); + bool findInFinderFiles(FindersInfo *findInFolderInfo); bool findInFiles(); bool replaceInFiles(); void setFindReplaceFolderFilter(const TCHAR *dir, const TCHAR *filters); @@ -340,6 +341,8 @@ private: // Dialog FindReplaceDlg _findReplaceDlg; + FindInFinderDlg _findInFinderDlg; + FindIncrementDlg _incrementFindDlg; AboutDlg _aboutDlg; DebugInfoDlg _debugInfoDlg; diff --git a/PowerEditor/src/NppBigSwitch.cpp b/PowerEditor/src/NppBigSwitch.cpp index ea4b6ca2d..3eb204cc7 100644 --- a/PowerEditor/src/NppBigSwitch.cpp +++ b/PowerEditor/src/NppBigSwitch.cpp @@ -215,8 +215,7 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPa case WM_FINDALL_INCURRENTDOC: { - findInCurrentFile(); - return TRUE; + return findInCurrentFile(); } case WM_FINDINFILES: @@ -224,6 +223,21 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPa return findInFiles(); } + case WM_FINDALL_INCURRENTFINDER: + { + FindersInfo *findInFolderInfo = (FindersInfo *)wParam; + Finder * newFinder = _findReplaceDlg.createFinder(); + + findInFolderInfo->_pDestFinder = newFinder; + bool isOK = findInFinderFiles(findInFolderInfo); + return isOK; + } + /* + case NPPM_INTERNAL_REMOVEFINDER: + { + return _findReplaceDlg.removeFinder((Finder *)wParam); + } + */ case WM_REPLACEINFILES: { replaceInFiles(); @@ -249,6 +263,26 @@ LRESULT Notepad_plus::process(HWND hwnd, UINT Message, WPARAM wParam, LPARAM lPa return TRUE; } + case NPPM_INTERNAL_FINDINFINDERDLG: + { + const int strSize = FINDREPLACE_MAXLENGTH; + TCHAR str[strSize]; + Finder *launcher = (Finder *)wParam; + + bool isFirstTime = not _findInFinderDlg.isCreated(); + + _findInFinderDlg.doDialog(launcher, _nativeLangSpeaker.isRTL()); + + _pEditView->getGenericSelectedText(str, strSize); + _findReplaceDlg.setSearchText(str); + setFindReplaceFolderFilter(NULL, NULL); + + if (isFirstTime) + _nativeLangSpeaker.changeFindReplaceDlgLang(_findReplaceDlg); + + return TRUE; + } + case NPPM_DOOPEN: case WM_DOOPEN: { diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp index b952e2784..d1d591eec 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.cpp @@ -40,6 +40,29 @@ FindOption FindReplaceDlg::_options; #define SHIFTED 0x8000 +void addText2Combo(const TCHAR * txt2add, HWND hCombo) +{ + if (!hCombo) return; + if (!lstrcmp(txt2add, TEXT(""))) return; + + int i = 0; + + i = ::SendMessage(hCombo, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)txt2add); + if (i != CB_ERR) // found + { + ::SendMessage(hCombo, CB_DELETESTRING, i, 0); + } + + i = ::SendMessage(hCombo, CB_INSERTSTRING, 0, (LPARAM)txt2add); + ::SendMessage(hCombo, CB_SETCURSEL, i, 0); +}; + +generic_string getTextFromCombo(HWND hCombo) +{ + TCHAR str[FINDREPLACE_MAXLENGTH]; + ::SendMessage(hCombo, WM_GETTEXT, FINDREPLACE_MAXLENGTH - 1, (LPARAM)str); + return generic_string(str); +}; int Searching::convertExtendedToString(const TCHAR * query, TCHAR * result, int length) { //query may equal to result, since it always gets smaller @@ -199,32 +222,6 @@ void Searching::displaySectionCentered(int posStart, int posEnd, ScintillaEditVi LONG_PTR FindReplaceDlg::originalFinderProc = NULL; -void FindReplaceDlg::addText2Combo(const TCHAR * txt2add, HWND hCombo, bool) -{ - if (!hCombo) return; - if (!lstrcmp(txt2add, TEXT(""))) return; - - int i = 0; - - i = ::SendMessage(hCombo, CB_FINDSTRINGEXACT, (WPARAM)-1, (LPARAM)txt2add); - if (i != CB_ERR) // found - { - ::SendMessage(hCombo, CB_DELETESTRING, i, 0); - } - - i = ::SendMessage(hCombo, CB_INSERTSTRING, 0, (LPARAM)txt2add); - - ::SendMessage(hCombo, CB_SETCURSEL, i, 0); -} - -generic_string FindReplaceDlg::getTextFromCombo(HWND hCombo, bool) const -{ - TCHAR str[FINDREPLACE_MAXLENGTH]; - ::SendMessage(hCombo, WM_GETTEXT, FINDREPLACE_MAXLENGTH - 1, (LPARAM)str); - return generic_string(str); -} - - // important : to activate all styles const int STYLING_MASK = 255; @@ -233,7 +230,13 @@ FindReplaceDlg::~FindReplaceDlg() _tab.destroy(); if (_pFinder) delete _pFinder; - delete [] _uniFileName; + for (int n = _findersOfFinder.size() - 1; n >= 0; n--) + { + delete _findersOfFinder[n]; + _findersOfFinder.erase(_findersOfFinder.begin() + n); + } + + delete[] _uniFileName; } void FindReplaceDlg::create(int dialogID, bool isRTL) @@ -350,12 +353,11 @@ void FindReplaceDlg::fillFindHistory() void FindReplaceDlg::fillComboHistory(int id, const vector & strings) { - bool isUnicode = false; HWND hCombo = ::GetDlgItem(_hSelf, id); for (vector::const_reverse_iterator i = strings.rbegin() ; i != strings.rend(); ++i) { - addText2Combo(i->c_str(), hCombo, isUnicode); + addText2Combo(i->c_str(), hCombo); } ::SendMessage(hCombo, CB_SETCURSEL, 0, 0); // select first item } @@ -398,7 +400,13 @@ void FindReplaceDlg::updateCombos() updateCombo(IDFINDWHAT); } -FoundInfo Finder::EmptyFoundInfo(0, 0, TEXT("")); +void FindReplaceDlg::updateCombo(int comboID) +{ + HWND hCombo = ::GetDlgItem(_hSelf, comboID); + addText2Combo(getTextFromCombo(hCombo).c_str(), hCombo); +} + +FoundInfo Finder::EmptyFoundInfo(0, 0, 0, TEXT("")); SearchResultMarking Finder::EmptySearchResultMarking; bool Finder::notify(SCNotification *notification) @@ -512,6 +520,41 @@ void Finder::DeleteResult() assert(size_t(_scintView.execute(SCI_GETLINECOUNT)) == _pMainFoundInfos->size() + 1); } +vector Finder::getResultFilePaths() const +{ + vector paths; + size_t len = _pMainFoundInfos->size(); + for (size_t i = 0; i < len; ++i) + { + // make sure that path is not already in + generic_string & path2add = (*_pMainFoundInfos)[i]._fullPath; + bool found = path2add.empty(); + for (size_t j = 0; j < paths.size() && not found; ++j) + { + if (paths[j] == path2add) + found = true; + + } + if (not found) + paths.push_back(path2add); + } + return paths; +} + +bool Finder::canFind(const TCHAR *fileName, size_t lineNumber) const +{ + size_t len = _pMainFoundInfos->size(); + for (size_t i = 0; i < len; ++i) + { + if ((*_pMainFoundInfos)[i]._fullPath == fileName) + { + if (lineNumber == (*_pMainFoundInfos)[i]._lineNumber) + return true; + } + } + return false; +} + void Finder::gotoNextFoundResult(int direction) { int increment = direction < 0 ? -1 : 1; @@ -564,6 +607,67 @@ void Finder::gotoNextFoundResult(int direction) } } +void FindInFinderDlg::initFromOptions() +{ + HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT_FIFOLDER); + addText2Combo(_options._str2Search.c_str(), hFindCombo); + + ::SendDlgItemMessage(_hSelf, IDC_MATCHLINENUM_CHECK_FIFOLDER, BM_SETCHECK, _options._isMatchLineNumber ? BST_CHECKED : BST_UNCHECKED, 0); + ::SendDlgItemMessage(_hSelf, IDWHOLEWORD_FIFOLDER, BM_SETCHECK, _options._isWholeWord ? BST_CHECKED : BST_UNCHECKED, 0); + ::SendDlgItemMessage(_hSelf, IDMATCHCASE_FIFOLDER, BM_SETCHECK, _options._isMatchCase ? BST_CHECKED : BST_UNCHECKED, 0); + + ::SendDlgItemMessage(_hSelf, IDNORMAL_FIFOLDER, BM_SETCHECK, _options._searchType == FindNormal ? BST_CHECKED : BST_UNCHECKED, 0); + ::SendDlgItemMessage(_hSelf, IDEXTENDED_FIFOLDER, BM_SETCHECK, _options._searchType == FindExtended ? BST_CHECKED : BST_UNCHECKED, 0); + ::SendDlgItemMessage(_hSelf, IDREGEXP_FIFOLDER, BM_SETCHECK, _options._searchType == FindRegex ? BST_CHECKED : BST_UNCHECKED, 0); + + ::SendDlgItemMessage(_hSelf, IDREDOTMATCHNL_FIFOLDER, BM_SETCHECK, _options._dotMatchesNewline ? BST_CHECKED : BST_UNCHECKED, 0); +} + +void FindInFinderDlg::writeOptions() +{ + HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT_FIFOLDER); + _options._str2Search = getTextFromCombo(hFindCombo); + _options._isMatchLineNumber = isCheckedOrNot(IDC_MATCHLINENUM_CHECK_FIFOLDER); + _options._isWholeWord = isCheckedOrNot(IDWHOLEWORD_FIFOLDER); + _options._isMatchCase = isCheckedOrNot(IDMATCHCASE_FIFOLDER); + _options._searchType = isCheckedOrNot(IDREGEXP_FIFOLDER) ? FindRegex : isCheckedOrNot(IDEXTENDED_FIFOLDER) ? FindExtended : FindNormal; + + _options._dotMatchesNewline = isCheckedOrNot(IDREDOTMATCHNL_FIFOLDER); +} + +INT_PTR CALLBACK FindInFinderDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM /*lParam*/) +{ + switch (message) + { + case WM_INITDIALOG: + initFromOptions(); + return TRUE; + + case WM_COMMAND: + { + switch (LOWORD(wParam)) + { + case IDCANCEL: + ::EndDialog(_hSelf, -1); + return TRUE; + + case IDOK: + writeOptions(); + ::EndDialog(_hSelf, -1); + FindersInfo findersInfo; + findersInfo._pSourceFinder = _pFinder2Search; + findersInfo._findOption = _options; + ::SendMessage(_hParent, WM_FINDALL_INCURRENTFINDER, (WPARAM)&findersInfo, 0); + return TRUE; + } + return FALSE; + } + default: + return FALSE; + } +} + + INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) { switch (message) @@ -705,10 +809,9 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM case IDOK : // Find Next : only for FIND_DLG and REPLACE_DLG { setStatusbarMessage(generic_string(), FSNoMessage); - bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); - _options._str2Search = getTextFromCombo(hFindCombo, isUnicode); + _options._str2Search = getTextFromCombo(hFindCombo); updateCombo(IDFINDWHAT); nppParamInst->_isFindReplacing = true; @@ -732,11 +835,10 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM if (_currentStatus == REPLACE_DLG) { setStatusbarMessage(TEXT(""), FSNoMessage); - bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); HWND hReplaceCombo = ::GetDlgItem(_hSelf, IDREPLACEWITH); - _options._str2Search = getTextFromCombo(hFindCombo, isUnicode); - _options._str4Replace = getTextFromCombo(hReplaceCombo, isUnicode); + _options._str2Search = getTextFromCombo(hFindCombo); + _options._str4Replace = getTextFromCombo(hReplaceCombo); updateCombos(); nppParamInst->_isFindReplacing = true; @@ -752,10 +854,9 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM if (_currentStatus == FIND_DLG) { setStatusbarMessage(TEXT(""), FSNoMessage); - bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); combo2ExtendedMode(IDFINDWHAT); - _options._str2Search = getTextFromCombo(hFindCombo, isUnicode); + _options._str2Search = getTextFromCombo(hFindCombo); updateCombo(IDFINDWHAT); nppParamInst->_isFindReplacing = true; @@ -769,10 +870,9 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM case IDC_FINDALL_CURRENTFILE : { setStatusbarMessage(TEXT(""), FSNoMessage); - bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); combo2ExtendedMode(IDFINDWHAT); - _options._str2Search = getTextFromCombo(hFindCombo, isUnicode); + _options._str2Search = getTextFromCombo(hFindCombo); updateCombo(IDFINDWHAT); nppParamInst->_isFindReplacing = true; @@ -800,10 +900,9 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM if ((lstrlen(directory) > 0) && (directory[lstrlen(directory)-1] != '\\')) _options._directory += TEXT("\\"); - bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); combo2ExtendedMode(IDFINDWHAT); - _options._str2Search = getTextFromCombo(hFindCombo, isUnicode); + _options._str2Search = getTextFromCombo(hFindCombo); updateCombo(IDFINDWHAT); nppParamInst->_isFindReplacing = true; @@ -838,11 +937,10 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM if (::MessageBox(_hParent, msg.c_str(), TEXT("Are you sure?"), MB_OKCANCEL|MB_DEFBUTTON2) == IDOK) { - bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); - _options._str2Search = getTextFromCombo(hFindCombo, isUnicode); + _options._str2Search = getTextFromCombo(hFindCombo); HWND hReplaceCombo = ::GetDlgItem(_hSelf, IDREPLACEWITH); - _options._str4Replace = getTextFromCombo(hReplaceCombo, isUnicode); + _options._str4Replace = getTextFromCombo(hReplaceCombo); updateCombo(IDFINDWHAT); updateCombo(IDREPLACEWITH); @@ -860,11 +958,10 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM if (_currentStatus == REPLACE_DLG) { setStatusbarMessage(TEXT(""), FSNoMessage); - bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); - _options._str2Search = getTextFromCombo(hFindCombo, isUnicode); + _options._str2Search = getTextFromCombo(hFindCombo); HWND hReplaceCombo = ::GetDlgItem(_hSelf, IDREPLACEWITH); - _options._str4Replace = getTextFromCombo(hReplaceCombo, isUnicode); + _options._str4Replace = getTextFromCombo(hReplaceCombo); updateCombos(); nppParamInst->_isFindReplacing = true; @@ -888,11 +985,10 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM return TRUE; } - bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); - _options._str2Search = getTextFromCombo(hFindCombo, isUnicode); + _options._str2Search = getTextFromCombo(hFindCombo); HWND hReplaceCombo = ::GetDlgItem(_hSelf, IDREPLACEWITH); - _options._str4Replace = getTextFromCombo(hReplaceCombo, isUnicode); + _options._str4Replace = getTextFromCombo(hReplaceCombo); updateCombos(); nppParamInst->_isFindReplacing = true; @@ -927,10 +1023,9 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM if (_currentStatus == FIND_DLG) { setStatusbarMessage(TEXT(""), FSNoMessage); - bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); updateCombo(IDFINDWHAT); - _options._str2Search = getTextFromCombo(hFindCombo, isUnicode); + _options._str2Search = getTextFromCombo(hFindCombo); int nbCounted = processAll(ProcessCountAll, &_options); generic_string result = TEXT(""); @@ -959,9 +1054,8 @@ INT_PTR CALLBACK FindReplaceDlg::run_dlgProc(UINT message, WPARAM wParam, LPARAM if (_currentStatus == MARK_DLG) { setStatusbarMessage(TEXT(""), FSNoMessage); - bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); - _options._str2Search = getTextFromCombo(hFindCombo, isUnicode); + _options._str2Search = getTextFromCombo(hFindCombo); updateCombo(IDFINDWHAT); if (isMacroRecording) saveInMacro(wParam, FR_OP_FIND); @@ -1457,7 +1551,7 @@ int FindReplaceDlg::markAllInc(const FindOption *opt) return nbFound; } -int FindReplaceDlg::processAll(ProcessOperation op, const FindOption *opt, bool isEntire, const TCHAR *fileName, int colourStyleID) +int FindReplaceDlg::processAll(ProcessOperation op, const FindOption *opt, bool isEntire, const FindersInfo *pFindersInfo, int colourStyleID) { if (op == ProcessReplaceAll && (*_ppEditView)->getCurrentBuffer()->isReadOnly()) { @@ -1514,46 +1608,46 @@ int FindReplaceDlg::processAll(ProcessOperation op, const FindOption *opt, bool endPosition = docLength; } - return processRange(op, txt2find, txt2replace, startPosition, endPosition, fileName, pOptions, colourStyleID); + FindReplaceInfo findReplaceInfo; + findReplaceInfo._txt2find = txt2find; + findReplaceInfo._txt2replace = txt2replace; + findReplaceInfo._startRange = startPosition; + findReplaceInfo._endRange = endPosition; + return processRange(op, findReplaceInfo, pFindersInfo, pOptions, colourStyleID); } -int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, const TCHAR *txt2replace, int startRange, int endRange, const TCHAR *fileName, const FindOption *opt, int colourStyleID) +int FindReplaceDlg::processRange(ProcessOperation op, FindReplaceInfo & findReplaceInfo, const FindersInfo * pFindersInfo, const FindOption *opt, int colourStyleID) { int nbProcessed = 0; - if (!isCreated() && !txt2find) + if (!isCreated() && not findReplaceInfo._txt2find) return nbProcessed; if ((op == ProcessReplaceAll) && (*_ppEditView)->getCurrentBuffer()->isReadOnly()) return nbProcessed; - if (startRange == endRange) + if (findReplaceInfo._startRange == findReplaceInfo._endRange) return nbProcessed; - if (!fileName) - fileName = TEXT(""); - const FindOption *pOptions = opt?opt:_env; - //bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; - bool isUnicode = ((*_ppEditView)->execute(SCI_GETCODEPAGE) == SC_CP_UTF8); int stringSizeFind = 0; int stringSizeReplace = 0; TCHAR *pTextFind = NULL; - if (!txt2find) + if (not findReplaceInfo._txt2find) { HWND hFindCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); - generic_string str2Search = getTextFromCombo(hFindCombo, isUnicode); + generic_string str2Search = getTextFromCombo(hFindCombo); stringSizeFind = str2Search.length(); pTextFind = new TCHAR[stringSizeFind + 1]; lstrcpy(pTextFind, str2Search.c_str()); } else { - stringSizeFind = lstrlen(txt2find); + stringSizeFind = lstrlen(findReplaceInfo._txt2find); pTextFind = new TCHAR[stringSizeFind + 1]; - lstrcpy(pTextFind, txt2find); + lstrcpy(pTextFind, findReplaceInfo._txt2find); } if (!pTextFind[0]) @@ -1565,23 +1659,24 @@ int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, con TCHAR *pTextReplace = NULL; if (op == ProcessReplaceAll) { - if (!txt2replace) + if (not findReplaceInfo._txt2replace) { HWND hReplaceCombo = ::GetDlgItem(_hSelf, IDREPLACEWITH); - generic_string str2Replace = getTextFromCombo(hReplaceCombo, isUnicode); + generic_string str2Replace = getTextFromCombo(hReplaceCombo); stringSizeReplace = str2Replace.length(); pTextReplace = new TCHAR[stringSizeReplace + 1]; lstrcpy(pTextReplace, str2Replace.c_str()); } else { - stringSizeReplace = lstrlen(txt2replace); + stringSizeReplace = lstrlen(findReplaceInfo._txt2replace); pTextReplace = new TCHAR[stringSizeReplace + 1]; - lstrcpy(pTextReplace, txt2replace); + lstrcpy(pTextReplace, findReplaceInfo._txt2replace); } } - if (pOptions->_searchType == FindExtended) { + if (pOptions->_searchType == FindExtended) + { stringSizeFind = Searching::convertExtendedToString(pTextFind, pTextFind, stringSizeFind); if (op == ProcessReplaceAll) stringSizeReplace = Searching::convertExtendedToString(pTextReplace, pTextReplace, stringSizeReplace); @@ -1617,7 +1712,7 @@ int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, con while (targetStart != -1 && targetStart != -2) { - targetStart = (*_ppEditView)->searchInTarget(pTextFind, stringSizeFind, startRange, endRange); + targetStart = (*_ppEditView)->searchInTarget(pTextFind, stringSizeFind, findReplaceInfo._startRange, findReplaceInfo._endRange); // If we've not found anything, just break out of the loop if (targetStart == -1 || targetStart == -2) @@ -1625,7 +1720,7 @@ int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, con targetEnd = int((*_ppEditView)->execute(SCI_GETTARGETEND)); - if (targetEnd > endRange) { //we found a result but outside our range, therefore do not process it + if (targetEnd > findReplaceInfo._endRange) { //we found a result but outside our range, therefore do not process it break; } @@ -1637,9 +1732,13 @@ int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, con { case ProcessFindAll: { + const TCHAR *pFileName = TEXT(""); + if (pFindersInfo && pFindersInfo->_pFileName) + pFileName = pFindersInfo->_pFileName; + if (!findAllFileNameAdded) //add new filetitle in hits if we haven't already { - _pFinder->addFileNameTitle(fileName); + _pFinder->addFileNameTitle(pFileName); findAllFileNameAdded = true; } @@ -1664,11 +1763,58 @@ int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, con SearchResultMarking srm; srm._start = start_mark; srm._end = end_mark; - _pFinder->add(FoundInfo(targetStart, targetEnd, fileName), srm, line.c_str(), lineNumber + 1); + _pFinder->add(FoundInfo(targetStart, targetEnd, lineNumber + 1, pFileName), srm, line.c_str()); break; } + case ProcessFindInFinder: + { + if (not pFindersInfo || not pFindersInfo->_pSourceFinder || not pFindersInfo->_pDestFinder) + break; + + const TCHAR *pFileName = pFindersInfo->_pFileName ? pFindersInfo->_pFileName : TEXT(""); + + if (!findAllFileNameAdded) //add new filetitle in hits if we haven't already + { + pFindersInfo->_pDestFinder->addFileNameTitle(pFileName); + findAllFileNameAdded = true; + } + + int lineNumber = (*_ppEditView)->execute(SCI_LINEFROMPOSITION, targetStart); + int lend = (*_ppEditView)->execute(SCI_GETLINEENDPOSITION, lineNumber); + int lstart = (*_ppEditView)->execute(SCI_POSITIONFROMLINE, lineNumber); + int nbChar = lend - lstart; + + // use the static buffer + TCHAR lineBuf[1024]; + + if (nbChar > 1024 - 3) + lend = lstart + 1020; + + int start_mark = targetStart - lstart; + int end_mark = targetEnd - lstart; + + (*_ppEditView)->getGenericText(lineBuf, 1024, lstart, lend, &start_mark, &end_mark); + + generic_string line = lineBuf; + line += TEXT("\r\n"); + SearchResultMarking srm; + srm._start = start_mark; + srm._end = end_mark; + + if (pOptions->_isMatchLineNumber) + { + if (pFindersInfo->_pSourceFinder->canFind(pFileName, lineNumber + 1)) + pFindersInfo->_pDestFinder->add(FoundInfo(targetStart, targetEnd, lineNumber + 1, pFileName), srm, line.c_str()); + } + else + { + pFindersInfo->_pDestFinder->add(FoundInfo(targetStart, targetEnd, lineNumber + 1, pFileName), srm, line.c_str()); + } + break; + } + case ProcessReplaceAll: { int replacedLength; @@ -1755,23 +1901,34 @@ int FindReplaceDlg::processRange(ProcessOperation op, const TCHAR *txt2find, con // After the processing of the last string occurence the search loop should be stopped // This helps to avoid the endless replacement during the EOL ("$") searching - if( targetStart + foundTextLen == endRange ) + if (targetStart + foundTextLen == findReplaceInfo._endRange) break; - - - startRange = targetStart + foundTextLen + replaceDelta; //search from result onwards - endRange += replaceDelta; //adjust end of range in case of replace - - } - + findReplaceInfo._startRange = targetStart + foundTextLen + replaceDelta; //search from result onwards + findReplaceInfo._endRange += replaceDelta; //adjust end of range in case of replace + } delete [] pTextFind; delete [] pTextReplace; - if (nbProcessed > 0 && op == ProcessFindAll) - _pFinder->addFileHitCount(nbProcessed); + if (nbProcessed > 0) + { + Finder *pFinder = nullptr; + if (op == ProcessFindAll) + { + pFinder = _pFinder; + } + else if (op == ProcessFindInFinder) + { + if (pFindersInfo && pFindersInfo->_pDestFinder) + pFinder = pFindersInfo->_pDestFinder; + else + pFinder = _pFinder; + } + if (pFinder != nullptr) + pFinder->addFileHitCount(nbProcessed); + } return nbProcessed; } @@ -1787,6 +1944,7 @@ void FindReplaceDlg::findAllIn(InWhat op) { _pFinder = new Finder(); _pFinder->init(_hInst, _hSelf, _ppEditView); + _pFinder->setVolatiled(false); tTbData data = {0}; _pFinder->create(&data, false); @@ -1873,6 +2031,106 @@ void FindReplaceDlg::findAllIn(InWhat op) ::SendMessage(_hSelf, WM_NEXTDLGCTL, (WPARAM)::GetDlgItem(_hSelf, IDD_FINDINFILES_DIR_COMBO), TRUE); } +Finder * FindReplaceDlg::createFinder() +{ + Finder *pFinder = new Finder(); + + pFinder->init(_hInst, _hSelf, _ppEditView); + + tTbData data = { 0 }; + pFinder->create(&data, false); + ::SendMessage(_hParent, NPPM_MODELESSDIALOG, MODELESSDIALOGREMOVE, (WPARAM)pFinder->getHSelf()); + // define the default docking behaviour + data.uMask = DWS_DF_CONT_BOTTOM | DWS_ICONTAB | DWS_ADDINFO; + data.hIconTab = (HICON)::LoadImage(_hInst, MAKEINTRESOURCE(IDI_FIND_RESULT_ICON), IMAGE_ICON, 0, 0, LR_LOADMAP3DCOLORS | LR_LOADTRANSPARENT); + data.pszAddInfo = _findAllResultStr; + + data.pszModuleName = TEXT("dummy"); + + // the dlgDlg should be the index of funcItem where the current function pointer is + // in this case is DOCKABLE_DEMO_INDEX + data.dlgID = 0; + ::SendMessage(_hParent, NPPM_DMMREGASDCKDLG, 0, (LPARAM)&data); + + pFinder->_scintView.init(_hInst, pFinder->getHSelf()); + + // Subclass the ScintillaEditView for the Finder (Scintilla doesn't notify all key presses) + originalFinderProc = SetWindowLongPtr(pFinder->_scintView.getHSelf(), GWLP_WNDPROC, (LONG_PTR)finderProc); + + pFinder->setFinderReadOnly(true); + pFinder->_scintView.execute(SCI_SETCODEPAGE, SC_CP_UTF8); + pFinder->_scintView.execute(SCI_USEPOPUP, FALSE); + pFinder->_scintView.execute(SCI_SETUNDOCOLLECTION, false); //dont store any undo information + pFinder->_scintView.execute(SCI_SETCARETLINEVISIBLE, 1); + pFinder->_scintView.execute(SCI_SETCARETWIDTH, 0); + pFinder->_scintView.showMargin(ScintillaEditView::_SC_MARGE_FOLDER, true); + + // get the width of FindDlg + RECT findRect; + ::GetWindowRect(pFinder->getHSelf(), &findRect); + + // overwrite some default settings + pFinder->_scintView.showMargin(ScintillaEditView::_SC_MARGE_SYBOLE, false); + pFinder->_scintView.setMakerStyle(FOLDER_STYLE_SIMPLE); + + pFinder->_scintView.display(); + pFinder->display(); + //::SendMessage(_hParent, NPPM_DMMHIDE, 0, (LPARAM)pFinder->getHSelf()); + ::UpdateWindow(_hParent); + //justCreated = true; + + pFinder->setFinderStyle(); + + // Send the address of _MarkingsStruct to the lexer + char ptrword[sizeof(void*) * 2 + 1]; + sprintf(ptrword, "%p", &pFinder->_MarkingsStruct); + pFinder->_scintView.execute(SCI_SETPROPERTY, (WPARAM)"@MarkingsStruct", (LPARAM)ptrword); + + _findersOfFinder.push_back(pFinder); + + ::SendMessage(pFinder->getHSelf(), WM_SIZE, 0, 0); + + // Show finder + ::SendMessage(_hParent, NPPM_DMMSHOW, 0, (LPARAM)pFinder->getHSelf()); + pFinder->_scintView.getFocus(); + + return pFinder; + + /* + { + if (_findAllResult == 1) + wsprintf(_findAllResultStr, TEXT("1 hit")); + else + wsprintf(_findAllResultStr, TEXT("%d hits"), _findAllResult); + if (_findAllResult) + { + focusOnFinder(); + } + else + { + // Show finder + ::SendMessage(_hParent, NPPM_DMMSHOW, 0, (LPARAM)pFinder->getHSelf()); + getFocus(); // no hits + } + } + else // error - search folder doesn't exist + ::SendMessage(_hSelf, WM_NEXTDLGCTL, (WPARAM)::GetDlgItem(_hSelf, IDD_FINDINFILES_DIR_COMBO), TRUE); + */ +} + +bool FindReplaceDlg::removeFinder(Finder *finder2remove) +{ + for (vector::iterator i = _findersOfFinder.begin(); i != _findersOfFinder.end(); ++i) + { + if (*i == finder2remove) + { + delete finder2remove; + _findersOfFinder.erase(i); + return true; + } + } + return false; +} void FindReplaceDlg::setSearchText(TCHAR * txt2find) { HWND hCombo = ::GetDlgItem(_hSelf, IDFINDWHAT); @@ -2245,6 +2503,22 @@ void FindReplaceDlg::initOptionsFromDlg() _options._isInHiddenDir = isCheckedOrNot(IDD_FINDINFILES_INHIDDENDIR_CHECK); } +void FindInFinderDlg::doDialog(Finder *launcher, bool isRTL) +{ + _pFinder2Search = launcher; + if (isRTL) + { + DLGTEMPLATE *pMyDlgTemplate = NULL; + HGLOBAL hMyDlgTemplate = makeRTLResource(IDD_FINDINFINDER_DLG, &pMyDlgTemplate); + ::DialogBoxIndirectParam(_hInst, pMyDlgTemplate, _hParent, dlgProc, (LPARAM)this); + ::GlobalFree(hMyDlgTemplate); + } + else + ::DialogBoxParam(_hInst, MAKEINTRESOURCE(IDD_FINDINFINDER_DLG), _hParent, dlgProc, (LPARAM)this); + +} + + void FindReplaceDlg::doDialog(DIALOG_TYPE whichType, bool isRTL, bool toShow) { if (!isCreated()) @@ -2441,33 +2715,34 @@ void Finder::addFileHitCount(int count) setFinderReadOnly(false); _scintView.insertGenericTextFrom(_lastFileHeaderPos, text); setFinderReadOnly(true); - ++nFoundFiles; + ++_nbFoundFiles; } -void Finder::addSearchHitCount(int count) +void Finder::addSearchHitCount(int count, bool isMatchLines) { - TCHAR text[50]; - if(count == 1 && nFoundFiles == 1) - wsprintf(text, TEXT(" (1 hit in 1 file)")); - else if(count == 1 && nFoundFiles != 1) - wsprintf(text, TEXT(" (1 hit in %i files)"), nFoundFiles); - else if(count != 1 && nFoundFiles == 1) - wsprintf(text, TEXT(" (%i hits in 1 file)"), count); - else if(count != 1 && nFoundFiles != 1) - wsprintf(text, TEXT(" (%i hits in %i files)"), count, nFoundFiles); + TCHAR *moreInfo = isMatchLines ? TEXT(" - Line Filter Mode: only display the filtered results") :TEXT(""); + TCHAR text[100]; + if(count == 1 && _nbFoundFiles == 1) + wsprintf(text, TEXT(" (1 hit in 1 file%s)"), moreInfo); + else if(count == 1 && _nbFoundFiles != 1) + wsprintf(text, TEXT(" (1 hit in %i files%s)"), _nbFoundFiles, moreInfo); + else if(count != 1 && _nbFoundFiles == 1) + wsprintf(text, TEXT(" (%i hits in 1 file%s)"), count, moreInfo); + else if(count != 1 && _nbFoundFiles != 1) + wsprintf(text, TEXT(" (%i hits in %i files%s)"), count, _nbFoundFiles, moreInfo); setFinderReadOnly(false); _scintView.insertGenericTextFrom(_lastSearchHeaderPos, text); setFinderReadOnly(true); } -void Finder::add(FoundInfo fi, SearchResultMarking mi, const TCHAR* foundline, int lineNb) +void Finder::add(FoundInfo fi, SearchResultMarking mi, const TCHAR* foundline) { _pMainFoundInfos->push_back(fi); generic_string str = TEXT("\tLine "); TCHAR lnb[16]; - wsprintf(lnb, TEXT("%d"), lineNb); + wsprintf(lnb, TEXT("%d"), fi._lineNumber); str += lnb; str += TEXT(": "); mi._start += str.length(); @@ -2583,13 +2858,13 @@ void Finder::beginNewFilesSearch() _scintView.execute(SCI_SETCURRENTPOS, 0); _pMainFoundInfos = _pMainFoundInfos == &_foundInfos1 ? &_foundInfos2 : &_foundInfos1; _pMainMarkings = _pMainMarkings == &_markings1 ? &_markings2 : &_markings1; - nFoundFiles = 0; + _nbFoundFiles = 0; // fold all old searches (1st level only) _scintView.collapse(searchHeaderLevel - SC_FOLDLEVELBASE, fold_collapse); } -void Finder::finishFilesSearch(int count) +void Finder::finishFilesSearch(int count, bool isMatchLines) { std::vector* _pOldFoundInfos; std::vector* _pOldMarkings; @@ -2604,9 +2879,10 @@ void Finder::finishFilesSearch(int count) _pMainMarkings = _pOldMarkings; _MarkingsStruct._length = _pMainMarkings->size(); - _MarkingsStruct._markings = &((*_pMainMarkings)[0]); + if (_pMainMarkings->size() > 0) + _MarkingsStruct._markings = &((*_pMainMarkings)[0]); - addSearchHitCount(count); + addSearchHitCount(count, isMatchLines); _scintView.execute(SCI_SETSEL, 0, 0); _scintView.execute(SCI_SETLEXER, SCLEX_SEARCHRESULT); @@ -2674,6 +2950,24 @@ INT_PTR CALLBACK Finder::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) { switch (wParam) { + case NPPM_INTERNAL_FINDINFINDERDLG: + { + ::SendMessage(::GetParent(_hParent), NPPM_INTERNAL_FINDINFINDERDLG, (WPARAM)this, 0); + return TRUE; + } + + case NPPM_INTERNAL_REMOVEFINDER: + { + if (_canBeVolatiled) + { + ::SendMessage(::GetParent(_hParent), NPPM_DMMHIDE, 0, (LPARAM)_hSelf); + setClosed(true); + + //::SendMessage(::GetParent(_hParent), NPPM_INTERNAL_REMOVEFINDER, (WPARAM)this, 0); + } + return TRUE; + } + case NPPM_INTERNAL_SCINTILLAFINFERCOLLAPSE : { _scintView.foldAll(fold_collapse); @@ -2725,6 +3019,10 @@ INT_PTR CALLBACK Finder::run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam) ::GetCursorPos(&p); ContextMenu scintillaContextmenu; vector tmp; + tmp.push_back(MenuItemUnit(NPPM_INTERNAL_FINDINFINDERDLG, TEXT("Find in this finder..."))); + if (_canBeVolatiled) + tmp.push_back(MenuItemUnit(NPPM_INTERNAL_REMOVEFINDER, TEXT("Close this finder"))); + tmp.push_back(MenuItemUnit(0, TEXT("Separator"))); tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFERCOLLAPSE, TEXT("Collapse all"))); tmp.push_back(MenuItemUnit(NPPM_INTERNAL_SCINTILLAFINFERUNCOLLAPSE, TEXT("Uncollapse all"))); tmp.push_back(MenuItemUnit(0, TEXT("Separator"))); @@ -2881,8 +3179,7 @@ INT_PTR CALLBACK FindIncrementDlg::run_dlgProc(UINT message, WPARAM wParam, LPAR fo._whichDirection = forward ? DIR_DOWN : DIR_UP; fo._isMatchCase = (BST_CHECKED == ::SendDlgItemMessage(_hSelf, IDC_INCFINDMATCHCASE, BM_GETCHECK, 0, 0)); - bool isUnicode = (*(_pFRDlg->_ppEditView))->getCurrentBuffer()->getUnicodeMode() != uni8Bit; - generic_string str2Search = _pFRDlg->getTextFromCombo(::GetDlgItem(_hSelf, IDC_INCFINDTEXT), isUnicode); + generic_string str2Search = getTextFromCombo(::GetDlgItem(_hSelf, IDC_INCFINDTEXT)); if (updateSearch) { FindStatus findStatus = FSFound; diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h index b4f3f24ad..a023928c0 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.h @@ -59,10 +59,11 @@ enum DIALOG_TYPE {FIND_DLG, REPLACE_DLG, FINDINFILES_DLG, MARK_DLG}; enum InWhat{ALL_OPEN_DOCS, FILES_IN_DIR, CURRENT_DOC}; struct FoundInfo { - FoundInfo(int start, int end, const TCHAR *fullPath) - : _start(start), _end(end), _fullPath(fullPath) {}; + FoundInfo(int start, int end, size_t lineNumber, const TCHAR *fullPath) + : _start(start), _end(end), _lineNumber(lineNumber), _fullPath(fullPath) {}; int _start; int _end; + size_t _lineNumber; generic_string _fullPath; }; @@ -73,32 +74,27 @@ struct TargetRange { enum SearchIncrementalType { NotIncremental, FirstIncremental, NextIncremental }; enum SearchType { FindNormal, FindExtended, FindRegex }; -enum ProcessOperation { ProcessFindAll, ProcessReplaceAll, ProcessCountAll, ProcessMarkAll, ProcessMarkAll_2, ProcessMarkAll_IncSearch, ProcessMarkAllExt }; +enum ProcessOperation { ProcessFindAll, ProcessReplaceAll, ProcessCountAll, ProcessMarkAll, ProcessMarkAll_2, ProcessMarkAll_IncSearch, ProcessMarkAllExt, ProcessFindInFinder }; struct FindOption { - bool _isWholeWord; - bool _isMatchCase; - bool _isWrapAround; - bool _whichDirection; - SearchIncrementalType _incrementalType; - SearchType _searchType; - bool _doPurge; - bool _doMarkLine; - bool _isInSelection; + bool _isWholeWord = true; + bool _isMatchCase = true; + bool _isWrapAround = true; + bool _whichDirection = DIR_DOWN; + SearchIncrementalType _incrementalType = NotIncremental; + SearchType _searchType = FindNormal; + bool _doPurge = false; + bool _doMarkLine = false; + bool _isInSelection = false; generic_string _str2Search; generic_string _str4Replace; generic_string _filters; generic_string _directory; - bool _isRecursive; - bool _isInHiddenDir; - bool _dotMatchesNewline; - FindOption() : _isWholeWord(true), _isMatchCase(true), _searchType(FindNormal),\ - _isWrapAround(true), _whichDirection(DIR_DOWN), _incrementalType(NotIncremental), - _doPurge(false), _doMarkLine(false), - _isInSelection(false), _isRecursive(true), _isInHiddenDir(false), - _dotMatchesNewline(false), - _filters(TEXT("")), _directory(TEXT("")) {}; + bool _isRecursive = true; + bool _isInHiddenDir = false; + bool _dotMatchesNewline = false; + bool _isMatchLineNumber = true; // only for Find in Folder }; //This class contains generic search functions as static functions for easy access @@ -139,17 +135,20 @@ public: void addSearchLine(const TCHAR *searchName); void addFileNameTitle(const TCHAR * fileName); void addFileHitCount(int count); - void addSearchHitCount(int count); - void add(FoundInfo fi, SearchResultMarking mi, const TCHAR* foundline, int lineNb); + void addSearchHitCount(int count, bool isMatchLines = false); + void add(FoundInfo fi, SearchResultMarking mi, const TCHAR* foundline); void setFinderStyle(); void removeAll(); void openAll(); void copy(); void beginNewFilesSearch(); - void finishFilesSearch(int count); + void finishFilesSearch(int count, bool isMatchLines = false); void gotoNextFoundResult(int direction); void GotoFoundLine(); void DeleteResult(); + std::vector getResultFilePaths() const; + bool canFind(const TCHAR *fileName, size_t lineNumber) const; + void setVolatiled(bool val) { _canBeVolatiled = val; }; protected : virtual INT_PTR CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam); @@ -169,11 +168,14 @@ private: SearchResultMarkings _MarkingsStruct; ScintillaEditView _scintView; - unsigned int nFoundFiles; + unsigned int _nbFoundFiles = 0; int _lastFileHeaderPos; int _lastSearchHeaderPos; + bool _canBeVolatiled = true; + + void setFinderReadOnly(bool isReadOnly) { _scintView.execute(SCI_SETREADONLY, isReadOnly); }; @@ -194,6 +196,40 @@ enum FindNextType { FINDNEXTTYPE_FINDNEXTFORREPLACE }; +struct FindReplaceInfo +{ + const TCHAR *_txt2find = nullptr; + const TCHAR *_txt2replace = nullptr; + int _startRange = -1; + int _endRange = -1; +}; + +struct FindersInfo +{ + Finder *_pSourceFinder = nullptr; + Finder *_pDestFinder = nullptr; + const TCHAR *_pFileName = nullptr; + + FindOption _findOption; +}; + +class FindInFinderDlg : public StaticDialog +{ +public: + void init(HINSTANCE hInst, HWND hPere) { + Window::init(hInst, hPere); + }; + void doDialog(Finder *launcher, bool isRTL = false); + FindOption & getOption() { return _options; } + +private: + Finder *_pFinder2Search = nullptr; + FindOption _options; + + virtual INT_PTR CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam); + void initFromOptions(); + void writeOptions(); +}; class FindReplaceDlg : public StaticDialog { @@ -225,13 +261,12 @@ public : bool processReplace(const TCHAR *txt2find, const TCHAR *txt2replace, const FindOption *options = NULL); int markAll(const TCHAR *txt2find, int styleID, bool isWholeWordSelected); - //int markAll2(const TCHAR *str2find); int markAllInc(const FindOption *opt); - int processAll(ProcessOperation op, const FindOption *opt, bool isEntire = false, const TCHAR *fileName = NULL, int colourStyleID = -1); -// int processAll(ProcessOperation op, const TCHAR *txt2find, const TCHAR *txt2replace, bool isEntire = false, const TCHAR *fileName = NULL, const FindOption *opt = NULL, int colourStyleID = -1); - int processRange(ProcessOperation op, const TCHAR *txt2find, const TCHAR *txt2replace, int startRange, int endRange, const TCHAR *fileName = NULL, const FindOption *opt = NULL, int colourStyleID = -1); + int processAll(ProcessOperation op, const FindOption *opt, bool isEntire = false, const FindersInfo *pFindersInfo = nullptr, int colourStyleID = -1); + int processRange(ProcessOperation op, FindReplaceInfo & findReplaceInfo, const FindersInfo *pFindersInfo, const FindOption *opt = NULL, int colourStyleID = -1); + void replaceAllInOpenedDocs(); void findAllIn(InWhat op); void setSearchText(TCHAR * txt2find); @@ -302,12 +337,11 @@ public : void execSavedCommand(int cmd, int intValue, generic_string stringValue); void setStatusbarMessage(const generic_string & msg, FindStatus staus); - + Finder * createFinder(); + bool removeFinder(Finder *finder2remove); protected : virtual INT_PTR CALLBACK run_dlgProc(UINT message, WPARAM wParam, LPARAM lParam); - void addText2Combo(const TCHAR * txt2add, HWND comboID, bool isUTF8 = false); - generic_string getTextFromCombo(HWND hCombo, bool isUnicode = false) const; static LONG_PTR originalFinderProc; // Window procedure for the finder @@ -322,6 +356,10 @@ private : ScintillaEditView **_ppEditView; Finder *_pFinder; + + std::vector _findersOfFinder; + + bool _isRTL; int _findAllResult; @@ -358,11 +396,7 @@ private : } void updateCombos(); - void updateCombo(int comboID) { - bool isUnicode = (*_ppEditView)->getCurrentBuffer()->getUnicodeMode() != uni8Bit; - HWND hCombo = ::GetDlgItem(_hSelf, comboID); - addText2Combo(getTextFromCombo(hCombo, isUnicode).c_str(), hCombo, isUnicode); - }; + void updateCombo(int comboID); void fillFindHistory(); void fillComboHistory(int id, const std::vector & strings); int saveComboHistory(int id, int maxcount, std::vector & strings); diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.rc b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.rc index 7eaa2446b..351353aef 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg.rc +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg.rc @@ -91,7 +91,6 @@ IDB_INCREMENTAL_BG BITMAP "../icons/incrementalBg.bmp" IDD_INCREMENT_FIND DIALOGEX 0, 0, 400, 20 STYLE DS_SYSMODAL | DS_CONTROL | DS_FIXEDSYS | WS_CHILD | WS_CLIPCHILDREN -//EXSTYLE WS_EX_TRANSPARENT FONT 8, TEXT("MS Shell Dlg") BEGIN PUSHBUTTON "X",IDCANCEL,2,3,16,14 @@ -113,4 +112,25 @@ BEGIN DEFPUSHBUTTON ">",IDC_INCFINDNXTOK,243,0,16,14, NOT WS_VISIBLE END +IDD_FINDINFINDER_DLG DIALOGEX 36, 44, 367, 200 +STYLE DS_SETFONT | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU +EXSTYLE WS_EX_TOOLWINDOW +CAPTION "Find in finder" +FONT 8, "MS Shell Dlg", 0, 0, 0x0 +BEGIN + RTEXT "&Find what :",IDFINDWHAT_STATIC_FIFOLDER,6,22,75,8 + COMBOBOX IDFINDWHAT_FIFOLDER,83,20,178,150,CBS_DROPDOWN | CBS_AUTOHSCROLL | WS_TABSTOP + CONTROL "Search only in found lines",IDC_MATCHLINENUM_CHECK_FIFOLDER,"Button",BS_AUTOCHECKBOX | BS_MULTILINE | WS_TABSTOP,12,66,99,16 + CONTROL "Match &whole word only",IDWHOLEWORD_FIFOLDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,88,140,15 + CONTROL "Match &case",IDMATCHCASE_FIFOLDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,12,100,140,15 + + GROUPBOX "Search Mode",IDC_MODE_STATIC_FIFOLDER,6,131,159,48 + CONTROL "&Normal",IDNORMAL_FIFOLDER,"Button",BS_AUTORADIOBUTTON | WS_GROUP,12,143,126,10 + CONTROL "E&xtended (\\n, \\r, \\t, \\0, \\x...)",IDEXTENDED_FIFOLDER, "Button",BS_AUTORADIOBUTTON,12,155,145,10 + CONTROL "Re&gular expression",IDREGEXP_FIFOLDER,"Button",BS_AUTORADIOBUTTON,12,167,78,10 + CONTROL "&. matches newline",IDREDOTMATCHNL_FIFOLDER,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,93,167,67,9 + PUSHBUTTON "Find all",IDOK,268,20,90,14,WS_GROUP + PUSHBUTTON "Close",IDCANCEL,268,38,90,14 +END + #endif //FIND_REPLACE_DLG_RC diff --git a/PowerEditor/src/ScitillaComponent/FindReplaceDlg_rc.h b/PowerEditor/src/ScitillaComponent/FindReplaceDlg_rc.h index 6c7f3474f..b8e11daf2 100644 --- a/PowerEditor/src/ScitillaComponent/FindReplaceDlg_rc.h +++ b/PowerEditor/src/ScitillaComponent/FindReplaceDlg_rc.h @@ -122,4 +122,17 @@ #define IDREDOTMATCHNL 1703 #define IDF_REDOTMATCHNL 1024 + +#define IDD_FINDINFINDER_DLG 1710 +#define IDFINDWHAT_STATIC_FIFOLDER 1711 +#define IDFINDWHAT_FIFOLDER 1712 +#define IDC_MATCHLINENUM_CHECK_FIFOLDER 1713 +#define IDWHOLEWORD_FIFOLDER 1714 +#define IDMATCHCASE_FIFOLDER 1715 +#define IDC_MODE_STATIC_FIFOLDER 1716 +#define IDNORMAL_FIFOLDER 1717 +#define IDEXTENDED_FIFOLDER 1718 +#define IDREGEXP_FIFOLDER 1719 +#define IDREDOTMATCHNL_FIFOLDER 1720 + #endif //FINDREPLACE_DLG_H diff --git a/PowerEditor/src/ScitillaComponent/ScintillaEditView.h b/PowerEditor/src/ScitillaComponent/ScintillaEditView.h index 55498de55..7e930a253 100644 --- a/PowerEditor/src/ScitillaComponent/ScintillaEditView.h +++ b/PowerEditor/src/ScitillaComponent/ScintillaEditView.h @@ -88,17 +88,18 @@ typedef void * SCINTILLA_PTR; #define WM_DOCK_USERDEFINE_DLG (SCINTILLA_USER + 1) #define WM_UNDOCK_USERDEFINE_DLG (SCINTILLA_USER + 2) -#define WM_CLOSE_USERDEFINE_DLG (SCINTILLA_USER + 3) -#define WM_REMOVE_USERLANG (SCINTILLA_USER + 4) -#define WM_RENAME_USERLANG (SCINTILLA_USER + 5) -#define WM_REPLACEALL_INOPENEDDOC (SCINTILLA_USER + 6) -#define WM_FINDALL_INOPENEDDOC (SCINTILLA_USER + 7) -#define WM_DOOPEN (SCINTILLA_USER + 8) -#define WM_FINDINFILES (SCINTILLA_USER + 9) -#define WM_REPLACEINFILES (SCINTILLA_USER + 10) -#define WM_FINDALL_INCURRENTDOC (SCINTILLA_USER + 11) -#define WM_FRSAVE_INT (SCINTILLA_USER + 12) -#define WM_FRSAVE_STR (SCINTILLA_USER + 13) +#define WM_CLOSE_USERDEFINE_DLG (SCINTILLA_USER + 3) +#define WM_REMOVE_USERLANG (SCINTILLA_USER + 4) +#define WM_RENAME_USERLANG (SCINTILLA_USER + 5) +#define WM_REPLACEALL_INOPENEDDOC (SCINTILLA_USER + 6) +#define WM_FINDALL_INOPENEDDOC (SCINTILLA_USER + 7) +#define WM_DOOPEN (SCINTILLA_USER + 8) +#define WM_FINDINFILES (SCINTILLA_USER + 9) +#define WM_REPLACEINFILES (SCINTILLA_USER + 10) +#define WM_FINDALL_INCURRENTDOC (SCINTILLA_USER + 11) +#define WM_FRSAVE_INT (SCINTILLA_USER + 12) +#define WM_FRSAVE_STR (SCINTILLA_USER + 13) +#define WM_FINDALL_INCURRENTFINDER (SCINTILLA_USER + 14) const int NB_FOLDER_STATE = 7; @@ -229,6 +230,7 @@ public: } } }; + virtual void destroy() { ::DestroyWindow(_hSelf); diff --git a/PowerEditor/src/ScitillaComponent/SmartHighlighter.cpp b/PowerEditor/src/ScitillaComponent/SmartHighlighter.cpp index c91f1841d..db77d205d 100644 --- a/PowerEditor/src/ScitillaComponent/SmartHighlighter.cpp +++ b/PowerEditor/src/ScitillaComponent/SmartHighlighter.cpp @@ -122,12 +122,19 @@ void SmartHighlighter::highlightView(ScintillaEditView * pHighlightView) prevDocLineChecked = docLine; startPos = (int)pHighlightView->execute(SCI_POSITIONFROMLINE, docLine); endPos = (int)pHighlightView->execute(SCI_POSITIONFROMLINE, docLine+1); - if (endPos == -1) { //past EOF - endPos = (int)pHighlightView->getCurrentDocLen() - 1; - _pFRDlg->processRange(ProcessMarkAll_2, searchText, NULL, startPos, endPos, NULL, &fo); + FindReplaceInfo frInfo; + frInfo._txt2find = searchText; + frInfo._startRange = startPos; + frInfo._endRange = endPos; + if (endPos == -1) + { //past EOF + frInfo._endRange = (int)pHighlightView->getCurrentDocLen() - 1; + _pFRDlg->processRange(ProcessMarkAll_2, frInfo, NULL, &fo); break; - } else { - _pFRDlg->processRange(ProcessMarkAll_2, searchText, NULL, startPos, endPos, NULL, &fo); + } + else + { + _pFRDlg->processRange(ProcessMarkAll_2, frInfo, NULL, &fo); } } diff --git a/PowerEditor/src/WinControls/Window.h b/PowerEditor/src/WinControls/Window.h index 17f5b0ff9..dbc105f76 100644 --- a/PowerEditor/src/WinControls/Window.h +++ b/PowerEditor/src/WinControls/Window.h @@ -110,7 +110,6 @@ public: HWND getHSelf() const { - //assert(_hSelf != 0); return _hSelf; } diff --git a/PowerEditor/src/resource.h b/PowerEditor/src/resource.h index b7c40344d..fe133658f 100644 --- a/PowerEditor/src/resource.h +++ b/PowerEditor/src/resource.h @@ -401,6 +401,8 @@ #define NPPM_INTERNAL_GETSCINTEDTVIEW (NOTEPADPLUS_USER_INTERNAL + 37) #define NPPM_INTERNAL_ENABLESNAPSHOT (NOTEPADPLUS_USER_INTERNAL + 38) #define NPPM_INTERNAL_SAVECURRENTSESSION (NOTEPADPLUS_USER_INTERNAL + 39) + #define NPPM_INTERNAL_FINDINFINDERDLG (NOTEPADPLUS_USER_INTERNAL + 40) + #define NPPM_INTERNAL_REMOVEFINDER (NOTEPADPLUS_USER_INTERNAL + 41) //wParam: 0