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 772719163..db2b35c0e 100644 Binary files a/grepWinNP3/src/Resources/grepWin.rc and b/grepWinNP3/src/Resources/grepWin.rc differ diff --git a/grepWinNP3/src/Resources/grepWin_orig.rc b/grepWinNP3/src/Resources/grepWin_orig.rc new file mode 100644 index 000000000..29d64c69d Binary files /dev/null and b/grepWinNP3/src/Resources/grepWin_orig.rc differ 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