From 820fb66b3a3af37e8ecc87043445d992f07d433b Mon Sep 17 00:00:00 2001 From: "METANEOCORTEX\\Kotti" Date: Fri, 24 Feb 2023 16:52:58 +0100 Subject: [PATCH] +upd: grepWinNP3 update to ver 2.1.13. --- grepWinNP3/grepWinNP3.vcxproj | 12 +- grepWinNP3/packages.config | 6 +- grepWinNP3/src/RegexReplaceFormatter.h | 31 ++- grepWinNP3/src/Resources/grepWin.rc | Bin 41716 -> 41672 bytes grepWinNP3/src/Resources/grepWin_orig.rc | Bin 0 -> 41604 bytes grepWinNP3/src/SearchDlg.cpp | 255 ++++++++++++++++++----- grepWinNP3/src/SearchDlg.h | 8 +- grepWinNP3/src/SearchInfo.cpp | 24 ++- grepWinNP3/src/SearchInfo.h | 4 +- grepWinNP3/src/Settings.cpp | 4 +- grepWinNP3/src/ShellContextMenu.cpp | 33 ++- grepWinNP3/src/ShellContextMenu.h | 3 +- grepWinNP3/src/last/version.h | 14 +- grepWinNP3/version.build.in | 2 +- grepWinNP3/version.txt | 2 +- 15 files changed, 293 insertions(+), 105 deletions(-) create mode 100644 grepWinNP3/src/Resources/grepWin_orig.rc diff --git a/grepWinNP3/grepWinNP3.vcxproj b/grepWinNP3/grepWinNP3.vcxproj index 9012f64ce..09f1dc0c6 100644 --- a/grepWinNP3/grepWinNP3.vcxproj +++ b/grepWinNP3/grepWinNP3.vcxproj @@ -521,16 +521,16 @@ - - - + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - + + + \ No newline at end of file diff --git a/grepWinNP3/packages.config b/grepWinNP3/packages.config index 913e727a8..0202a93ad 100644 --- a/grepWinNP3/packages.config +++ b/grepWinNP3/packages.config @@ -1,6 +1,6 @@  - - - + + + \ No newline at end of file diff --git a/grepWinNP3/src/RegexReplaceFormatter.h b/grepWinNP3/src/RegexReplaceFormatter.h index d1741ad82..28c9d2d60 100644 --- a/grepWinNP3/src/RegexReplaceFormatter.h +++ b/grepWinNP3/src/RegexReplaceFormatter.h @@ -1,6 +1,6 @@ // grepWin - regex search and replace for Windows -// Copyright (C) 2011-2012, 2014-2015, 2021 - Stefan Kueng +// Copyright (C) 2011-2012, 2014-2015, 2021, 2023 - Stefan Kueng // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -21,11 +21,12 @@ #include #include #include +#include "StringUtils.h" #pragma warning(push) #pragma warning(disable : 4996) // warning STL4010: Various members of std::allocator are deprecated in C++17 #include -#include #include + #pragma warning(pop) class NumberReplacer @@ -160,7 +161,7 @@ public: if ((itBegin == sReplace.begin()) || ((*(itBegin - 1)) != '\\')) { auto itEnd = itBegin + it->expression.size(); - wchar_t format[10] = {0}; + wchar_t format[20] = {0}; if (it->padding) { if (it->leadZero) @@ -170,9 +171,18 @@ public: } else wcscpy_s(format, L"%d"); - wchar_t buf[50] = {0}; + if (it->padding < 50) + { + // for small strings, reserve space on the stack + wchar_t buf[128] = {0}; swprintf_s(buf, _countof(buf), format, it->start); sReplace.replace(itBegin, itEnd, buf); + } + else + { + auto s = CStringUtils::Format(format, it->start); + sReplace.replace(itBegin, itEnd, s); + } it->start += it->increment; } else if ((*(itBegin - 1)) == '\\') @@ -287,7 +297,7 @@ public: if ((itBegin == sReplace.begin()) || ((*(itBegin - 1)) != '\\')) { auto itEnd = itBegin + it->expression.size(); - char format[10] = {0}; + char format[20] = {0}; if (it->padding) { if (it->leadZero) @@ -297,9 +307,18 @@ public: } else strcpy_s(format, "%d"); - char buf[50] = {0}; + if (it->padding < 50) + { + // for small strings, reserve space on the stack + char buf[128] = {0}; sprintf_s(buf, _countof(buf), format, it->start); sReplace.replace(itBegin, itEnd, buf); + } + else + { + auto s = CStringUtils::Format(format, it->start); + sReplace.replace(itBegin, itEnd, s); + } it->start += it->increment; } else if ((*(itBegin - 1)) == '\\') diff --git a/grepWinNP3/src/Resources/grepWin.rc b/grepWinNP3/src/Resources/grepWin.rc index 772719163d2bf3d0d57847b540d399c353470ecd..db2b35c0eac1d5f89436d178aff699519e2b3776 100644 GIT binary patch delta 22 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 L9(k~3W#<0@DZQPT literal 0 HcmV?d00001 diff --git a/grepWinNP3/src/SearchDlg.cpp b/grepWinNP3/src/SearchDlg.cpp index 37b5fd844..b954ba3e8 100644 --- a/grepWinNP3/src/SearchDlg.cpp +++ b/grepWinNP3/src/SearchDlg.cpp @@ -143,6 +143,7 @@ CSearchDlg::CSearchDlg(HWND hParent) : m_hParent(hParent) //, m_dwThreadRunning(FALSE) //, m_cancelled(FALSE) + , m_bBlockUpdate(false) , m_bookmarksDlg(nullptr) , m_patternRegexC(false) , m_excludeDirsPatternRegexC(false) @@ -743,11 +744,8 @@ LRESULT CSearchDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara return DoCommand(LOWORD(wParam), HIWORD(wParam)); case WM_CONTEXTMENU: { - if (reinterpret_cast(wParam) == GetDlgItem(*this, IDC_RESULTLIST)) - { - ShowContextMenu(GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); + ShowContextMenu(reinterpret_cast(wParam), GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam)); } - } break; case WM_NOTIFY: { @@ -2101,62 +2099,206 @@ void CSearchDlg::FillResultList() RedrawWindow(hListControl, nullptr, nullptr, RDW_ERASE | RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN); } -void CSearchDlg::ShowContextMenu(int x, int y) +void CSearchDlg::ShowContextMenu(HWND hWnd, int x, int y) { HWND hListControl = GetDlgItem(*this, IDC_RESULTLIST); + if (hWnd != GetDlgItem(*this, IDC_RESULTLIST)) + return; + bool fileList = (IsDlgButtonChecked(*this, IDC_RESULTFILES) == BST_CHECKED); + // check if clicked on a header + POINT pt = {x, y}; + auto hHeader = ListView_GetHeader(hListControl); + RECT headerRc{}; + GetWindowRect(hHeader, &headerRc); + if (PtInRect(&headerRc, pt)) + { + int colCount = Header_GetItemCount(hHeader); + int clickedCol = -1; + for (int i = 0; i < colCount; ++i) + { + RECT iRc{}; + Header_GetItemRect(hHeader, i, &iRc); + MapWindowPoints(hHeader, nullptr, reinterpret_cast(&iRc), 2); + if (PtInRect(&iRc, pt)) + { + clickedCol = i; + break; + } + } + if (clickedCol >= 0) + { + HMENU hMenu = CreatePopupMenu(); + if (hMenu) + { + OnOutOfScope(DestroyMenu(hMenu)); + auto sCopyColumn = TranslatedString(hResource, IDS_COPY_COLUMN); + AppendMenu(hMenu, MF_STRING, 1, sCopyColumn.c_str()); + // Display the menu. + auto cmdId = TrackPopupMenu(hMenu, TPM_RETURNCMD, pt.x, pt.y, 0, *this, nullptr); + if (cmdId == 1) + { + int iItem = -1; + std::wstring copyText; + auto sReadError = TranslatedString(hResource, IDS_READERROR); + while ((iItem = ListView_GetNextItem(hListControl, iItem, LVNI_ALL)) != (-1)) + { + int selIndex = GetSelectedListIndex(fileList, iItem); + if ((selIndex < 0) || (selIndex >= static_cast(m_items.size()))) + continue; + if (!copyText.empty()) + copyText += L"\r\n"; + if (fileList) + { + const auto* pInfo = &m_items[selIndex]; + switch (clickedCol) + { + case 0: // name of the file + copyText += pInfo->filePath.substr(pInfo->filePath.find_last_of('\\') + 1); + break; + case 1: // file size + if (!pInfo->folder) + { + wchar_t buf[1024]{}; + StrFormatByteSizeW(pInfo->fileSize, buf, _countof(buf)); + copyText += buf; + } + break; + case 2: // match count or read error + if (pInfo->readError) + copyText += sReadError.c_str(); + else + copyText += std::to_wstring(pInfo->matchCount); + break; + case 3: // path + if (m_searchPath.find('|') != std::wstring::npos) + copyText += pInfo->filePath.substr(0, pInfo->filePath.size() - pInfo->filePath.substr(pInfo->filePath.find_last_of('\\')).size()); + else + { + auto filePart = pInfo->filePath.substr(pInfo->filePath.find_last_of('\\')); + auto len = pInfo->filePath.size() - m_searchPath.size() - filePart.size(); + if (len > 0) + --len; + if (m_searchPath.size() < pInfo->filePath.size()) + { + auto text = pInfo->filePath.substr(m_searchPath.size() + 1, len); + if (text.empty()) + text = L"\\."; + copyText += text; + } + else + copyText += pInfo->filePath.c_str(); + } + break; + case 4: // extension of the file + { + if (!pInfo->folder) + { + auto dotPos = pInfo->filePath.find_last_of('.'); + if (dotPos != std::wstring::npos) + { + if (pInfo->filePath.find('\\', dotPos) == std::wstring::npos) + copyText += pInfo->filePath.substr(dotPos + 1); + } + } + } + break; + case 5: // encoding + copyText += CTextFile::GetEncodingString(pInfo->encoding); + break; + case 6: // modification date + { + wchar_t buf[1024]{}; + FormatDate(buf, pInfo->modifiedTime, true); + copyText += buf; + } + break; + } + } + else + { + auto tup = m_listItems[iItem]; + auto index = std::get<0>(tup); + auto subIndex = std::get<1>(tup); + const auto& item = m_items[index]; + const auto& pInfo = &item; + switch (clickedCol) + { + case 0: // name of the file + copyText += pInfo->filePath.substr(pInfo->filePath.find_last_of('\\') + 1); + break; + case 1: // line number + copyText += std::to_wstring(pInfo->matchLinesNumbers[subIndex]); + break; + case 2: // line + { + std::wstring line; + if (pInfo->matchLines.size() > static_cast(subIndex)) + { + line = pInfo->matchLines[subIndex]; + std::ranges::replace(line, '\n', ' '); + std::ranges::replace(line, '\r', ' '); + } + copyText += line; + } + break; + case 3: // path + copyText += pInfo->filePath.substr(0, pInfo->filePath.size() - pInfo->filePath.substr(pInfo->filePath.find_last_of('\\') + 1).size() - 1); + break; + } + } + } + WriteAsciiStringToClipboard(copyText.c_str(), *this); + } + } + } + } + int nCount = ListView_GetItemCount(hListControl); if (nCount == 0) return; CShellContextMenu shellMenu; int iItem = -1; - std::vector paths; + std::unordered_map pathMap; + while ((iItem = ListView_GetNextItem(hListControl, iItem, LVNI_SELECTED)) != (-1)) { - int selIndex = GetSelectedListIndex(iItem); + int selIndex = GetSelectedListIndex(fileList, iItem); if ((selIndex < 0) || (selIndex >= static_cast(m_items.size()))) continue; - paths.push_back(m_items[selIndex]); + pathMap[selIndex] = m_items[selIndex].filePath; } - if (paths.empty()) + if (pathMap.empty()) return; std::vector lines; - bool fileList = (IsDlgButtonChecked(*this, IDC_RESULTFILES) == BST_CHECKED); if (!fileList) { - WCHAR numBuf[40] = {0}; - while ((iItem = ListView_GetNextItem(hListControl, iItem, LVNI_SELECTED)) != (-1)) - { - ListView_GetItemText(hListControl, iItem, 1, numBuf, 40); - DWORD line = _wtoi(numBuf); - if (line) + for (const auto& idx : pathMap | std::views::keys) { LineData data; - const CSearchInfo info = m_items[GetSelectedListIndex(iItem)]; - data.path = info.filePath; - const auto matchLinesNumbers = info.matchLinesNumbers; - size_t lineIndex = 0; - for (unsigned long matchlinesnumber : matchLinesNumbers) - { - if (matchlinesnumber == line) + const auto& info = m_items[idx]; + data.lines.reserve(info.matchLinesNumbers.size()); + for (size_t i = 0; i < info.matchLinesNumbers.size(); ++i) { LineDataLine dataLine; - dataLine.number = info.matchLinesNumbers[lineIndex]; - if (info.matchLines.size() > lineIndex) - dataLine.text = info.matchLines[lineIndex]; + if (info.matchLinesNumbers.size() > i) + dataLine.number = info.matchLinesNumbers[i]; + if (info.matchLines.size() > i) + dataLine.text = info.matchLines[i]; data.lines.push_back(dataLine); } - ++lineIndex; - } lines.push_back(data); } } + + std::vector vPaths; + for (const auto& idx : pathMap | std::views::keys) + { + vPaths.push_back(m_items[idx]); } + shellMenu.SetObjects(vPaths, lines); - shellMenu.SetObjects(paths, lines); - - POINT pt = {x, y}; if ((x == -1) && (y == -1)) { RECT rc; @@ -2199,11 +2341,17 @@ bool CSearchDlg::PreTranslateMessage(MSG* pMsg) if ((GetFocus() == hListControl) && bCtrl && !bShift && !bAlt) { // select all entries + m_bBlockUpdate = true; + SendMessage(hListControl, WM_SETREDRAW, FALSE, 0); int nCount = ListView_GetItemCount(hListControl); for (int i = 0; i < nCount; ++i) { ListView_SetItemState(hListControl, i, LVIS_SELECTED, LVIS_SELECTED); } + SendMessage(hListControl, WM_SETREDRAW, TRUE, 0); + m_bBlockUpdate = false; + m_selectedItems = ListView_GetSelectedCount(hListControl); + UpdateInfoLabel(); return true; } } @@ -2278,9 +2426,10 @@ bool CSearchDlg::PreTranslateMessage(MSG* pMsg) if (bCtrl && !bShift && !bAlt) { int iItem = -1; + bool fileList = (IsDlgButtonChecked(*this, IDC_RESULTFILES) == BST_CHECKED); while ((iItem = ListView_GetNextItem(hListControl, iItem, LVNI_SELECTED)) != (-1)) { - int selIndex = GetSelectedListIndex(iItem); + int selIndex = GetSelectedListIndex(fileList, iItem); if ((selIndex < 0) || (selIndex >= static_cast(m_items.size()))) continue; OpenFileAtListIndex(selIndex); @@ -2308,11 +2457,14 @@ void CSearchDlg::DoListNotify(LPNMITEMACTIVATE lpNMItemActivate) { if ((lpNMItemActivate->uOldState & LVIS_SELECTED) || (lpNMItemActivate->uNewState & LVIS_SELECTED)) { + if (!m_bBlockUpdate) + { HWND hListControl = GetDlgItem(*this, IDC_RESULTLIST); m_selectedItems = ListView_GetSelectedCount(hListControl); UpdateInfoLabel(); } } + } if (lpNMItemActivate->hdr.code == LVN_BEGINDRAG) { CDropFiles dropFiles; // class for creating DROPFILES struct @@ -2323,9 +2475,10 @@ void CSearchDlg::DoListNotify(LPNMITEMACTIVATE lpNMItemActivate) return; int iItem = -1; + bool fileList = (IsDlgButtonChecked(*this, IDC_RESULTFILES) == BST_CHECKED); while ((iItem = ListView_GetNextItem(hListControl, iItem, LVNI_SELECTED)) != (-1)) { - dropFiles.AddFile(m_items[GetSelectedListIndex(iItem)].filePath); + dropFiles.AddFile(m_items[GetSelectedListIndex(fileList, iItem)].filePath); } if (dropFiles.GetCount() > 0) @@ -2535,28 +2688,8 @@ void CSearchDlg::DoListNotify(LPNMITEMACTIVATE lpNMItemActivate) } break; case 5: // encoding - switch (pInfo->encoding) - { - case CTextFile::Ansi: - wcsncpy_s(pItem->pszText, pItem->cchTextMax, L"ANSI", pItem->cchTextMax - 1LL); + wcsncpy_s(pItem->pszText, pItem->cchTextMax, CTextFile::GetEncodingString(pInfo->encoding).c_str(), pItem->cchTextMax - 1LL); break; - case CTextFile::Unicode_Le: - wcsncpy_s(pItem->pszText, pItem->cchTextMax, L"UTF-16-LE", pItem->cchTextMax - 1LL); - break; - case CTextFile::Unicode_Be: - wcsncpy_s(pItem->pszText, pItem->cchTextMax, L"UTF-16-BE", pItem->cchTextMax - 1LL); - break; - case CTextFile::UTF8: - wcsncpy_s(pItem->pszText, pItem->cchTextMax, L"UTF8", pItem->cchTextMax - 1LL); - break; - case CTextFile::Binary: - wcsncpy_s(pItem->pszText, pItem->cchTextMax, L"BINARY", pItem->cchTextMax - 1LL); - break; - default: - wcsncpy_s(pItem->pszText, pItem->cchTextMax, L"", pItem->cchTextMax - 1LL); - break; - } - break; case 6: // modification date FormatDate(pItem->pszText, pInfo->modifiedTime, true); break; @@ -3216,10 +3349,17 @@ DWORD CSearchDlg::SearchThread() SendMessage(*this, SEARCH_START, 0, 0); std::wstring searchStringutf16; + for (auto c : m_searchString) { searchStringutf16 += c; + if (std::iswalpha(c) && ((c & 0xFF00) == 0)) searchStringutf16 += L"\\x00"; + else + { + searchStringutf16 = m_searchString; + break; + } } for (std::wstring searchPath : pathVector) @@ -3243,7 +3383,7 @@ DWORD CSearchDlg::SearchThread() bool bIsDirectory = false; CDirFileEnum fileEnumerator(searchPath.c_str()); if (!m_bIncludeSymLinks) - fileEnumerator.SetAttributesToIgnore(FILE_ATTRIBUTE_REPARSE_POINT | IO_REPARSE_TAG_MOUNT_POINT); + fileEnumerator.SetAttributesToIgnore(FILE_ATTRIBUTE_REPARSE_POINT); bool bRecurse = m_bIncludeSubfolders; std::wstring sPath; @@ -4439,6 +4579,11 @@ void CSearchDlg::AutoSizeAllColumns() int CSearchDlg::GetSelectedListIndex(int index) { bool fileList = (IsDlgButtonChecked(*this, IDC_RESULTFILES) == BST_CHECKED); + return GetSelectedListIndex(fileList, index); +} + +int CSearchDlg::GetSelectedListIndex(bool fileList, int index) const +{ if (fileList) return index; auto tup = m_listItems[index]; diff --git a/grepWinNP3/src/SearchDlg.h b/grepWinNP3/src/SearchDlg.h index 67e14e4b2..444e3313a 100644 --- a/grepWinNP3/src/SearchDlg.h +++ b/grepWinNP3/src/SearchDlg.h @@ -1,6 +1,6 @@ // grepWin - regex search and replace for Windows -// Copyright (C) 2007-2022 - Stefan Kueng +// Copyright (C) 2007-2023 - Stefan Kueng // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -126,12 +126,12 @@ public: inline void SetKeepFileDate(bool bSet) { m_bWholeWordsC = true; m_bWholeWords = bSet; } inline void SetWholeWords(bool bSet) { m_bWholeWordsC = true; m_bWholeWords = bSet; } inline void SetUTF8(bool bSet) { m_bUTF8C = true; m_bUTF8 = bSet; m_bForceBinary = false; } - inline void SetIncludeSymLinks(bool bSet) { m_bIncludeSymLinksC = true; m_bIncludeSymLinks = bSet; } inline void SetBinary(bool bSet) { m_bUTF8C = true; m_bForceBinary = bSet; m_bUTF8 = false; } inline void SetSize(uint64_t size, int cmp) { m_bSizeC = true; m_lSize = size << 10; m_sizeCmp = cmp; m_bAllSize = (m_lSize == MaxFileSize()) ? true : m_bAllSize; } inline void SetIncludeSystem(bool bSet) { m_bIncludeSystemC = true; m_bIncludeSystem = bSet; } inline void SetIncludeHidden(bool bSet) { m_bIncludeHiddenC = true; m_bIncludeHidden = bSet; } inline void SetIncludeSubfolders(bool bSet) { m_bIncludeSubfoldersC = true; m_bIncludeSubfolders = bSet; } + inline void SetIncludeSymLinks(bool bSet) { m_bIncludeSymLinksC = true; m_bIncludeSymLinks = bSet; } inline void SetIncludeBinary(bool bSet) { m_bIncludeBinaryC = true; m_bIncludeBinary = bSet; } inline void SetDateLimit(int datelimit, FILETIME t1, FILETIME t2) { m_bDateLimitC = true; m_dateLimit = datelimit; m_date1 = t1; m_date2 = t2; } inline void SetNoSaveSettings(bool nosave) { m_bNoSaveSettings = nosave; } @@ -152,7 +152,7 @@ protected: bool InitResultList(); void FillResultList(); bool AddFoundEntry(const CSearchInfo* pInfo, bool bOnlyListControl = false); - void ShowContextMenu(int x, int y); + void ShowContextMenu(HWND hWnd, int x, int y); void DoListNotify(LPNMITEMACTIVATE lpNMItemActivate); void OpenFileAtListIndex(int listIndex); void UpdateInfoLabel(); @@ -163,6 +163,7 @@ protected: bool MatchPath(LPCTSTR pathBuf) const; void AutoSizeAllColumns(); int GetSelectedListIndex(int index); + int GetSelectedListIndex(bool fileList, int index) const; static bool FailedShowMessage(HRESULT hr); #ifdef NP3_ALLOW_UPDATE void CheckForUpdates(bool force = false); @@ -177,6 +178,7 @@ private: HWND m_hParent; //std::atomic_bool LONG m_dwThreadRunning; //std::atomic_bool LONG m_cancelled; + bool m_bBlockUpdate; std::unique_ptr m_bookmarksDlg; ComPtr m_pTaskbarList; diff --git a/grepWinNP3/src/SearchInfo.cpp b/grepWinNP3/src/SearchInfo.cpp index dd0d0af19..954050b89 100644 --- a/grepWinNP3/src/SearchInfo.cpp +++ b/grepWinNP3/src/SearchInfo.cpp @@ -1,6 +1,6 @@ // grepWin - regex search and replace for Windows -// Copyright (C) 2007-2008, 2012-2014, 2021-2022 - Stefan Kueng +// Copyright (C) 2007-2008, 2012-2014, 2021-2023 - Stefan Kueng // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -141,3 +141,25 @@ bool CSearchInfo::ExtCompareDesc(const CSearchInfo& entry1, const CSearchInfo& e std::wstring ext2 = dotPos2 != std::wstring::npos ? entry2.filePath.substr(dotPos2 + 1) : L""; return StrCmpLogicalW(ext1.c_str(), ext2.c_str()) > 0; } + +bool CSearchInfo::operator<(const CSearchInfo& other) const +{ + auto res = _wcsicmp(filePath.c_str(), other.filePath.c_str()); + if (res != 0) + return res < 0; + if (fileSize != other.fileSize) + return fileSize < other.fileSize; + if (matchCount != other.matchCount) + return matchCount < matchCount; + if (readError != other.readError) + return readError != other.readError; + if (folder != other.folder) + return folder != other.folder; + if (CompareFileTime(&modifiedTime, &other.modifiedTime) != 0) + return CompareFileTime(&modifiedTime, &other.modifiedTime) < 0; + if (matchLinesNumbers != other.matchLinesNumbers) + return matchLinesNumbers < other.matchLinesNumbers; + if (matchLines != other.matchLines) + return matchLines < other.matchLines; + return false; +} diff --git a/grepWinNP3/src/SearchInfo.h b/grepWinNP3/src/SearchInfo.h index 9741c3be6..8126b516c 100644 --- a/grepWinNP3/src/SearchInfo.h +++ b/grepWinNP3/src/SearchInfo.h @@ -1,6 +1,6 @@ // grepWin - regex search and replace for Windows -// Copyright (C) 2007-2008, 2010, 2012-2013, 2021-2022 - Stefan Kueng +// Copyright (C) 2007-2008, 2010, 2012-2013, 2021-2023 - Stefan Kueng // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -44,6 +44,8 @@ public: static bool ModifiedTimeCompareDesc(const CSearchInfo& entry1, const CSearchInfo& entry2); static bool ExtCompareDesc(const CSearchInfo& entry1, const CSearchInfo& entry2); + bool operator<(const CSearchInfo& other) const; + std::wstring filePath; __int64 fileSize; std::vector matchLinesNumbers; diff --git a/grepWinNP3/src/Settings.cpp b/grepWinNP3/src/Settings.cpp index 813c8fe02..88f7df627 100644 --- a/grepWinNP3/src/Settings.cpp +++ b/grepWinNP3/src/Settings.cpp @@ -1,6 +1,6 @@ // grepWin - regex search and replace for Windows -// Copyright (C) 2012-2013, 2016-2021 - Stefan Kueng +// Copyright (C) 2012-2013, 2016-2021, 2023 - Stefan Kueng // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -254,7 +254,7 @@ LRESULT CSettingsDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa SendDlgItemMessage(hwndDlg, IDC_LANGUAGE, CB_SETCURSEL, langIndex, 0); SendDlgItemMessage(hwndDlg, IDC_ESCKEY, BM_SETCHECK, bPortable ? g_iniFile.GetBoolValue(L"settings", L"escclose", false) : !!DWORD(CRegStdDWORD(L"Software\\grepWinNP3\\escclose", FALSE)) ? BST_CHECKED : BST_UNCHECKED, 0); SendDlgItemMessage(hwndDlg, IDC_BACKUPINFOLDER, BM_SETCHECK, bPortable ? g_iniFile.GetBoolValue(L"settings", L"backupinfolder", false) : !!DWORD(CRegStdDWORD(L"Software\\grepWinNP3\\backupinfolder", FALSE)) ? BST_CHECKED : BST_UNCHECKED, 0); - SendDlgItemMessage(hwndDlg, IDC_NOWARNINGIFNOBACKUP, BM_SETCHECK, bPortable ? g_iniFile.GetBoolValue(L"settings", L"nowarnifnobackup", false) : !!DWORD(CRegStdDWORD(L"Software\\grepWin\\nowarnifnobackup", FALSE)) ? BST_CHECKED : BST_UNCHECKED, 0); + SendDlgItemMessage(hwndDlg, IDC_NOWARNINGIFNOBACKUP, BM_SETCHECK, bPortable ? g_iniFile.GetBoolValue(L"settings", L"nowarnifnobackup", false) : !!DWORD(CRegStdDWORD(L"Software\\grepWinNP3\\nowarnifnobackup", FALSE)) ? BST_CHECKED : BST_UNCHECKED, 0); SendDlgItemMessage(hwndDlg, IDC_ONLYONE, BM_SETCHECK, bPortable ? g_iniFile.GetBoolValue(L"global", L"onlyone", false) : !!DWORD(CRegStdDWORD(L"Software\\grepWinNP3\\onlyone", FALSE)) ? BST_CHECKED : BST_UNCHECKED, 0); #ifdef NP3_ALLOW_UPDATE SendDlgItemMessage(hwndDlg, IDC_DOUPDATECHECKS, BM_SETCHECK, bPortable ? g_iniFile.GetBoolValue(L"global", L"CheckForUpdates", false) : !!DWORD(CRegStdDWORD(L"Software\\grepWinNP3\\CheckForUpdates", FALSE)) ? BST_CHECKED : BST_UNCHECKED, 0); diff --git a/grepWinNP3/src/ShellContextMenu.cpp b/grepWinNP3/src/ShellContextMenu.cpp index 688dd8995..e4ae2e6c9 100644 --- a/grepWinNP3/src/ShellContextMenu.cpp +++ b/grepWinNP3/src/ShellContextMenu.cpp @@ -1,6 +1,6 @@ // grepWin - regex search and replace for Windows -// Copyright (C) 2007-2015, 2017, 2020-2021 - Stefan Kueng +// Copyright (C) 2007-2015, 2017, 2020-2021, 2023 - Stefan Kueng // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -44,8 +44,7 @@ struct ICompare }; CShellContextMenu::CShellContextMenu() - : m_nItems(0) - , bDelete(FALSE) + : bDelete(FALSE) , m_menu(nullptr) , m_psfFolder(nullptr) , m_pidlArray(nullptr) @@ -315,8 +314,6 @@ UINT CShellContextMenu::ShowContextMenu(HWND hWnd, POINT pt) std::wstring lines; for (auto it = m_lineVector.begin(); it != m_lineVector.end(); ++it) { - if (!lines.empty()) - lines += L"\r\n"; for (auto it2 = it->lines.cbegin(); it2 != it->lines.cend(); ++it2) { std::wstring l = it2->text; @@ -324,6 +321,8 @@ UINT CShellContextMenu::ShowContextMenu(HWND hWnd, POINT pt) std::replace(l.begin(), l.end(), '\n', ' '); std::replace(l.begin(), l.end(), '\r', ' '); + if (!lines.empty()) + lines += L"\r\n"; lines += l; } } @@ -419,35 +418,35 @@ void CShellContextMenu::SetObjects(const std::vector& strVector, co // but since we use the Desktop as our interface and the Desktop is the namespace root // that means that it's a fully qualified PIDL, which is what we need - m_nItems = strVector.size(); - m_pidlArray = static_cast(CoTaskMemAlloc((m_nItems + 10) * sizeof(LPITEMIDLIST))); - SecureZeroMemory(m_pidlArray, (m_nItems + 10) * sizeof(LPITEMIDLIST)); + auto nItems = strVector.size(); + m_pidlArray = static_cast(CoTaskMemAlloc((nItems + 10) * sizeof(LPITEMIDLIST))); + SecureZeroMemory(m_pidlArray, (nItems + 10) * sizeof(LPITEMIDLIST)); m_pidlArrayItems = 0; int succeededItems = 0; LPITEMIDLIST pidl = nullptr; m_strVector.clear(); m_lineVector.clear(); - m_strVector.reserve(m_nItems); - m_lineVector.reserve(m_nItems); + m_strVector.reserve(nItems); + m_lineVector.reserve(nItems); size_t bufSize = 1024; auto filePath = std::make_unique(bufSize); - for (size_t i = 0; i < m_nItems; i++) + for (const auto& sInfo : strVector) { - if (bufSize < strVector[i].filePath.size()) + if (bufSize < sInfo.filePath.size()) { - bufSize = strVector[i].filePath.size() + 3; + bufSize = sInfo.filePath.size() + 3; filePath = std::make_unique(bufSize); } - wcscpy_s(filePath.get(), bufSize, strVector[i].filePath.c_str()); + wcscpy_s(filePath.get(), bufSize, sInfo.filePath.c_str()); if (SUCCEEDED(m_psfFolder->ParseDisplayName(NULL, nullptr, filePath.get(), NULL, &pidl, NULL))) { m_pidlArray[succeededItems++] = pidl; // copy pidl to pidlArray - m_strVector.push_back(strVector[i]); - if (lineVector.size() > static_cast(i)) - m_lineVector.push_back(lineVector[i]); + m_strVector.push_back(sInfo); } } + m_lineVector = lineVector; + m_pidlArrayItems = succeededItems; bDelete = TRUE; // indicates that m_psfFolder should be deleted by CShellContextMenu diff --git a/grepWinNP3/src/ShellContextMenu.h b/grepWinNP3/src/ShellContextMenu.h index 4a198dfc5..2e3dbebdb 100644 --- a/grepWinNP3/src/ShellContextMenu.h +++ b/grepWinNP3/src/ShellContextMenu.h @@ -1,6 +1,6 @@ // grepWin - regex search and replace for Windows -// Copyright (C) 2007-2008, 2011-2015, 2021 - Stefan Kueng +// Copyright (C) 2007-2008, 2011-2015, 2021, 2023 - Stefan Kueng // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -35,7 +35,6 @@ public: virtual ~CShellContextMenu(); private: - size_t m_nItems; BOOL bDelete; HMENU m_menu; IShellFolder * m_psfFolder; diff --git a/grepWinNP3/src/last/version.h b/grepWinNP3/src/last/version.h index 7ffe8a04f..c64384a6b 100644 --- a/grepWinNP3/src/last/version.h +++ b/grepWinNP3/src/last/version.h @@ -6,13 +6,13 @@ //#pragma message(__LOC__"Run the NAnt script to get proper version info") -#define FILEVER 2, 1, 12, 43 -#define PRODUCTVER 2, 1, 12, 43 -#define STRFILEVER "2.1.12.43\0" -#define STRPRODUCTVER "2.1.12.43\0" +#define FILEVER 2, 1, 13, 44 +#define PRODUCTVER 2, 1, 13, 44 +#define STRFILEVER "2.1.13.44\0" +#define STRPRODUCTVER "2.1.13.44\0" #define GREPWIN_VERMAJOR 2 #define GREPWIN_VERMINOR 1 -#define GREPWIN_VERMICRO 12 -#define GREPWIN_VERBUILD 43 -#define GREPWIN_VERDATE "2023-02-22" +#define GREPWIN_VERMICRO 13 +#define GREPWIN_VERBUILD 44 +#define GREPWIN_VERDATE "2023-02-24" diff --git a/grepWinNP3/version.build.in b/grepWinNP3/version.build.in index bb21c8037..961c88bb6 100644 --- a/grepWinNP3/version.build.in +++ b/grepWinNP3/version.build.in @@ -4,7 +4,7 @@ - + diff --git a/grepWinNP3/version.txt b/grepWinNP3/version.txt index 2da9d348a..afd09e049 100644 --- a/grepWinNP3/version.txt +++ b/grepWinNP3/version.txt @@ -1,2 +1,2 @@ -2.0.12.1183 +2.0.13.1197 https://tools.stefankueng.com/grepWin.html