From 18cc667a7938ed2c8dc2debd4814d78e9f8df493 Mon Sep 17 00:00:00 2001 From: Rainer Kottenhoff Date: Sun, 17 May 2020 12:22:57 +0200 Subject: [PATCH] + upd: merging current grepWin dev -> grepWinNP3 --- grepWinNP3/sktoolslib_mod/StringUtils.h | 84 ++++++++-- grepWinNP3/src/Bookmarks.cpp | 33 ++-- grepWinNP3/src/Resources/grepWin.rc | 108 ++++++------- grepWinNP3/src/SearchDlg.cpp | 145 +++++++++++++----- grepWinNP3/src/SearchDlg.h | 3 +- grepWinNP3/src/Settings.cpp | 5 + grepWinNP3/src/Theme.cpp | 25 ++- grepWinNP3/src/grepWin.cpp | 8 +- grepWinNP3/src/last/version.h | 12 +- grepWinNP3/src/resource.h | 4 +- .../Deutsch (Deutschland) [de-DE].lang | 4 + .../English (United Kingdom) [en-GB].lang | 4 + .../English (United States) [en-US].lang | 6 +- 13 files changed, 298 insertions(+), 143 deletions(-) diff --git a/grepWinNP3/sktoolslib_mod/StringUtils.h b/grepWinNP3/sktoolslib_mod/StringUtils.h index fdad2ae7e..19325640c 100644 --- a/grepWinNP3/sktoolslib_mod/StringUtils.h +++ b/grepWinNP3/sktoolslib_mod/StringUtils.h @@ -1,6 +1,6 @@ // sktoolslib - common files for SK tools -// Copyright (C) 2012-2019 - Stefan Kueng +// Copyright (C) 2012-2020 - Stefan Kueng // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License @@ -294,36 +294,98 @@ class CStringUtils { public: // trim from both ends - static inline std::string &trim(std::string &s) { + static inline std::string& trim(std::string& s) + { return ltrim(rtrim(s)); } + static inline std::string& trim(std::string& s, const std::string& trimchars) + { + return ltrim(rtrim(s, trimchars), trimchars); + } + static inline std::string& trim(std::string& s, wint_t trimchar) + { + return ltrim(rtrim(s, trimchar), trimchar); + } // trim from start - static inline std::string <rim(std::string &s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](wint_t c) {return !iswspace(c); })); + static inline std::string& ltrim(std::string& s) + { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](wint_t c) { return !iswspace(c); })); + return s; + } + static inline std::string& ltrim(std::string& s, const std::string& trimchars) + { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [&trimchars](wint_t c) { return trimchars.find((char)c) == std::string::npos; })); + return s; + } + static inline std::string& ltrim(std::string& s, wint_t trimchar) + { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [&trimchar](wint_t c) { return c != trimchar; })); return s; } // trim from end - static inline std::string &rtrim(std::string &s) { - s.erase(std::find_if(s.rbegin(), s.rend(), [](wint_t c) {return !iswspace(c); }).base(), s.end()); + static inline std::string& rtrim(std::string& s) + { + s.erase(std::find_if(s.rbegin(), s.rend(), [](wint_t c) { return !iswspace(c); }).base(), s.end()); + return s; + } + static inline std::string& rtrim(std::string& s, const std::string& trimchars) + { + s.erase(std::find_if(s.rbegin(), s.rend(), [&trimchars](wint_t c) { return trimchars.find((char)c) == std::string::npos; }).base(), s.end()); + return s; + } + static inline std::string& rtrim(std::string& s, wint_t trimchar) + { + s.erase(std::find_if(s.rbegin(), s.rend(), [&trimchar](wint_t c) { return c != trimchar; }).base(), s.end()); return s; } // trim from both ends - static inline std::wstring &trim(std::wstring &s) { + static inline std::wstring& trim(std::wstring& s) + { return ltrim(rtrim(s)); } + static inline std::wstring& trim(std::wstring& s, const std::wstring& trimchars) + { + return ltrim(rtrim(s, trimchars), trimchars); + } + static inline std::wstring& trim(std::wstring& s, wint_t trimchar) + { + return ltrim(rtrim(s, trimchar), trimchar); + } // trim from start - static inline std::wstring <rim(std::wstring &s) { - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](wint_t c) {return !iswspace(c); })); + static inline std::wstring& ltrim(std::wstring& s) + { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](wint_t c) { return !iswspace(c); })); + return s; + } + static inline std::wstring& ltrim(std::wstring& s, const std::wstring& trimchars) + { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [&trimchars](wint_t c) { return trimchars.find(c) == std::wstring::npos; })); + return s; + } + static inline std::wstring& ltrim(std::wstring& s, wint_t trimchar) + { + s.erase(s.begin(), std::find_if(s.begin(), s.end(), [&trimchar](wint_t c) { return c != trimchar; })); return s; } // trim from end - static inline std::wstring &rtrim(std::wstring &s) { - s.erase(std::find_if(s.rbegin(), s.rend(), [](wint_t c) {return !iswspace(c); }).base(), s.end()); + static inline std::wstring& rtrim(std::wstring& s) + { + s.erase(std::find_if(s.rbegin(), s.rend(), [](wint_t c) { return !iswspace(c); }).base(), s.end()); + return s; + } + static inline std::wstring& rtrim(std::wstring& s, const std::wstring& trimchars) + { + s.erase(std::find_if(s.rbegin(), s.rend(), [&trimchars](wint_t c) { return trimchars.find(c) == std::wstring::npos; }).base(), s.end()); + return s; + } + static inline std::wstring& rtrim(std::wstring& s, wint_t trimchar) + { + s.erase(std::find_if(s.rbegin(), s.rend(), [&trimchar](wint_t c) { return c != trimchar; }).base(), s.end()); return s; } diff --git a/grepWinNP3/src/Bookmarks.cpp b/grepWinNP3/src/Bookmarks.cpp index a17960c4a..4d68041c0 100644 --- a/grepWinNP3/src/Bookmarks.cpp +++ b/grepWinNP3/src/Bookmarks.cpp @@ -131,21 +131,24 @@ void CBookmarks::RemoveBookmark(const std::wstring& name) Bookmark CBookmarks::GetBookmark( const std::wstring& name ) { Bookmark bk; - bk.Name = name; - bk.Search = GetValue(name.c_str(), L"searchString", L""); - bk.Replace = GetValue(name.c_str(), L"replaceString", L""); - bk.UseRegex = wcscmp(GetValue(name.c_str(), L"useregex", L"false"), L"true") == 0; - bk.CaseSensitive = wcscmp(GetValue(name.c_str(), L"casesensitive", L"false"), L"true") == 0; - bk.DotMatchesNewline = wcscmp(GetValue(name.c_str(), L"dotmatchesnewline", L"false"), L"true") == 0; - bk.Backup = wcscmp(GetValue(name.c_str(), L"backup", L"false"), L"true") == 0; - bk.Utf8 = wcscmp(GetValue(name.c_str(), L"utf8", L"false"), L"true") == 0; - bk.IncludeSystem = wcscmp(GetValue(name.c_str(), L"includesystem", L"false"), L"true") == 0; - bk.IncludeFolder = wcscmp(GetValue(name.c_str(), L"includefolder", L"false"), L"true") == 0; - bk.IncludeHidden = wcscmp(GetValue(name.c_str(), L"includehidden", L"false"), L"true") == 0; - bk.IncludeBinary = wcscmp(GetValue(name.c_str(), L"includebinary", L"false"), L"true") == 0; - bk.ExcludeDirs = GetValue(name.c_str(), L"excludedirs", L""); - bk.FileMatch = GetValue(name.c_str(), L"filematch", L""); - bk.FileMatchRegex = wcscmp(GetValue(name.c_str(), L"filematchregex", L"false"), L"true") == 0; + if (GetSectionSize(name.c_str()) >= 0) + { + bk.Name = name; + bk.Search = GetValue(name.c_str(), L"searchString", L""); + bk.Replace = GetValue(name.c_str(), L"replaceString", L""); + bk.UseRegex = wcscmp(GetValue(name.c_str(), L"useregex", L"false"), L"true") == 0; + bk.CaseSensitive = wcscmp(GetValue(name.c_str(), L"casesensitive", L"false"), L"true") == 0; + bk.DotMatchesNewline = wcscmp(GetValue(name.c_str(), L"dotmatchesnewline", L"false"), L"true") == 0; + bk.Backup = wcscmp(GetValue(name.c_str(), L"backup", L"false"), L"true") == 0; + bk.Utf8 = wcscmp(GetValue(name.c_str(), L"utf8", L"false"), L"true") == 0; + bk.IncludeSystem = wcscmp(GetValue(name.c_str(), L"includesystem", L"false"), L"true") == 0; + bk.IncludeFolder = wcscmp(GetValue(name.c_str(), L"includefolder", L"false"), L"true") == 0; + bk.IncludeHidden = wcscmp(GetValue(name.c_str(), L"includehidden", L"false"), L"true") == 0; + bk.IncludeBinary = wcscmp(GetValue(name.c_str(), L"includebinary", L"false"), L"true") == 0; + bk.ExcludeDirs = GetValue(name.c_str(), L"excludedirs", L""); + bk.FileMatch = GetValue(name.c_str(), L"filematch", L""); + bk.FileMatchRegex = wcscmp(GetValue(name.c_str(), L"filematchregex", L"false"), L"true") == 0; + } return bk; } diff --git a/grepWinNP3/src/Resources/grepWin.rc b/grepWinNP3/src/Resources/grepWin.rc index 26c6fd292..cf1ee315a 100644 --- a/grepWinNP3/src/Resources/grepWin.rc +++ b/grepWinNP3/src/Resources/grepWin.rc @@ -32,16 +32,6 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL // remains consistent on all systems. IDI_GREPWIN ICON "grepWinNP3.ico" -#endif // Neutral resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// Neutral resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -#pragma code_page(1252) ///////////////////////////////////////////////////////////////////////////// // @@ -153,7 +143,7 @@ BEGIN END IDD_ABOUT DIALOGEX 0, 0, 263, 86 -STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU +STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "About grepWinNP3" FONT 9, "MS Shell Dlg 2", 400, 0, 0x1 BEGIN @@ -175,7 +165,7 @@ BEGIN CONTROL "",IDC_TEXTCONTENT,"RichEdit20W",WS_VSCROLL | WS_TABSTOP | 0x1084,7,7,303,96 END -IDD_SETTINGS DIALOGEX 0, 0, 317, 189 +IDD_SETTINGS DIALOGEX 0, 0, 317, 209 STYLE DS_SETFONT | WS_POPUP | WS_CAPTION | WS_SYSMENU | WS_THICKFRAME CAPTION "grepWinNP3 Settings" FONT 9, "MS Shell Dlg 2", 400, 0, 0x1 @@ -189,17 +179,19 @@ BEGIN LTEXT "This adds a new entry to the context menu named 'Open with Editor'",IDC_STATIC3,13,66,288,16 LTEXT "Language:",IDC_STATIC4,16,92,119,8 COMBOBOX IDC_LANGUAGE,151,90,159,30,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP - CONTROL "Escape key closes grepWinNP3",IDC_ESCKEY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,106,183,10 + CONTROL "Escape key closes grepWinNP3",IDC_ESCKEY,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,106,252,10 CONTROL "Create backup files in a separate folder",IDC_BACKUPINFOLDER, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,119,148,10 - DEFPUSHBUTTON "OK",IDOK,204,168,50,13 - PUSHBUTTON "Cancel",IDCANCEL,260,168,50,13 - CONTROL "Only one instance",IDC_ONLYONE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,131,138,10 - CONTROL "Dark mode",IDC_DARKMODE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,143,150,10 - LTEXT "",IDC_DARKMODEINFO,17,154,179,23,WS_DISABLED - RTEXT "Max # of concurrent worker",IDC_TEXT_NUMOFWORKER,147,144,119,9,0,WS_EX_RIGHT - EDITTEXT IDC_MAXNUMWORKER,270,142,31,13,ES_RIGHT | ES_NUMBER | WS_GROUP,WS_EX_RIGHT - CONTROL "",IDC_SPIN_MAXWORKER,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNLEFT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_GROUP,271,142,10,13 + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,119,249,10 + CONTROL "Don't warn when replacing without creating backups",IDC_NOWARNINGIFNOBACKUP, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,131,250,10 + DEFPUSHBUTTON "OK",IDOK,204,180,50,13 + PUSHBUTTON "Cancel",IDCANCEL,260,180,50,13 + CONTROL "Only one instance",IDC_ONLYONE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,143,150,10 + CONTROL "Dark mode",IDC_DARKMODE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,155,157,10 + LTEXT "",IDC_DARKMODEINFO,17,170,180,23,WS_DISABLED + RTEXT "Max # of concurrent worker",IDC_TEXT_NUMOFWORKER,156,156,107,9,0,WS_EX_RIGHT + EDITTEXT IDC_MAXNUMWORKER,271,154,31,13,ES_RIGHT | ES_NUMBER | WS_GROUP,WS_EX_RIGHT + CONTROL "",IDC_SPIN_MAXWORKER,"msctls_updown32",UDS_SETBUDDYINT | UDS_ALIGNLEFT | UDS_AUTOBUDDY | UDS_ARROWKEYS | WS_GROUP,271,154,10,13 END @@ -278,7 +270,7 @@ BEGIN VERTGUIDE, 13 VERTGUIDE, 301 TOPMARGIN, 7 - BOTTOMMARGIN, 181 + BOTTOMMARGIN, 201 END END #endif // APSTUDIO_INVOKED @@ -318,6 +310,36 @@ END IDR_INFODLG HTML "infodlg.htm" +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE +BEGIN + "..\\resource.h\0" +END + +2 TEXTINCLUDE +BEGIN + "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#include ""windows.h""\r\n" + "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" + "#ifndef APSTUDIO_INVOKED\r\n" + "#include ""grepWin.rc2""\r\n" + "#endif\0" +END + +3 TEXTINCLUDE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + ///////////////////////////////////////////////////////////////////////////// // // String Table @@ -401,46 +423,6 @@ BEGIN IDS_ERR_PATHNOTEXIST "Path does not exist or is not accessible!" END -#endif // Neutral resources -///////////////////////////////////////////////////////////////////////////// - - -///////////////////////////////////////////////////////////////////////////// -// Neutral resources - -#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) -LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -#pragma code_page(1252) - -#ifdef APSTUDIO_INVOKED -///////////////////////////////////////////////////////////////////////////// -// -// TEXTINCLUDE -// - -1 TEXTINCLUDE -BEGIN - "..\\resource.h\0" -END - -2 TEXTINCLUDE -BEGIN - "#define APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#include ""windows.h""\r\n" - "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n" - "#ifndef APSTUDIO_INVOKED\r\n" - "#include ""grepWin.rc2""\r\n" - "#endif\0" -END - -3 TEXTINCLUDE -BEGIN - "\r\n" - "\0" -END - -#endif // APSTUDIO_INVOKED - #endif // Neutral resources ///////////////////////////////////////////////////////////////////////////// diff --git a/grepWinNP3/src/SearchDlg.cpp b/grepWinNP3/src/SearchDlg.cpp index e7a6eb85d..d5180ef77 100644 --- a/grepWinNP3/src/SearchDlg.cpp +++ b/grepWinNP3/src/SearchDlg.cpp @@ -191,6 +191,19 @@ LRESULT CSearchDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara { case WM_INITDIALOG: { + SHAutoComplete(GetDlgItem(*this, IDC_SEARCHPATH), SHACF_FILESYSTEM|SHACF_AUTOSUGGEST_FORCE_ON); + + m_AutoCompleteFilePatterns.Load(_T("Software\\grepWinNP3\\History"), _T("FilePattern")); + m_AutoCompleteFilePatterns.Init(GetDlgItem(hwndDlg, IDC_PATTERN)); + m_AutoCompleteExcludeDirsPatterns.Load(_T("Software\\grepWinNP3\\History"), _T("ExcludeDirsPattern")); + m_AutoCompleteExcludeDirsPatterns.Init(GetDlgItem(hwndDlg, IDC_EXCLUDEDIRSPATTERN)); + m_AutoCompleteSearchPatterns.Load(_T("Software\\grepWinNP3\\History"), _T("SearchPattern")); + m_AutoCompleteSearchPatterns.Init(GetDlgItem(hwndDlg, IDC_SEARCHTEXT)); + m_AutoCompleteReplacePatterns.Load(_T("Software\\grepWinNP3\\History"), _T("ReplacePattern")); + m_AutoCompleteReplacePatterns.Init(GetDlgItem(hwndDlg, IDC_REPLACETEXT)); + m_AutoCompleteSearchPaths.Load(_T("Software\\grepWinNP3\\History"), _T("SearchPaths")); + m_AutoCompleteSearchPaths.Init(GetDlgItem(hwndDlg, IDC_SEARCHPATH)); + m_themeCallbackId = CTheme::Instance().RegisterThemeChangeCallback( [this]() { auto bDark = CTheme::Instance().IsDarkTheme(); @@ -277,18 +290,6 @@ LRESULT CSearchDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara m_pDropTarget->AddSuportedFormat(ftetc); ftetc.cfFormat=CF_HDROP; m_pDropTarget->AddSuportedFormat(ftetc); - SHAutoComplete(GetDlgItem(*this, IDC_SEARCHPATH), SHACF_FILESYSTEM|SHACF_AUTOSUGGEST_FORCE_ON); - - m_AutoCompleteFilePatterns.Load(_T("Software\\grepWinNP3\\History"), _T("FilePattern")); - m_AutoCompleteFilePatterns.Init(GetDlgItem(hwndDlg, IDC_PATTERN)); - m_AutoCompleteExcludeDirsPatterns.Load(_T("Software\\grepWinNP3\\History"), _T("ExcludeDirsPattern")); - m_AutoCompleteExcludeDirsPatterns.Init(GetDlgItem(hwndDlg, IDC_EXCLUDEDIRSPATTERN)); - m_AutoCompleteSearchPatterns.Load(_T("Software\\grepWinNP3\\History"), _T("SearchPattern")); - m_AutoCompleteSearchPatterns.Init(GetDlgItem(hwndDlg, IDC_SEARCHTEXT)); - m_AutoCompleteReplacePatterns.Load(_T("Software\\grepWinNP3\\History"), _T("ReplacePattern")); - m_AutoCompleteReplacePatterns.Init(GetDlgItem(hwndDlg, IDC_REPLACETEXT)); - m_AutoCompleteSearchPaths.Load(_T("Software\\grepWinNP3\\History"), _T("SearchPaths")); - m_AutoCompleteSearchPaths.Init(GetDlgItem(hwndDlg, IDC_SEARCHPATH)); m_editFilePatterns.Subclass(hwndDlg, IDC_PATTERN); m_editExcludeDirsPatterns.Subclass(hwndDlg, IDC_EXCLUDEDIRSPATTERN); @@ -392,7 +393,7 @@ LRESULT CSearchDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPara { if (bPortable) { - m_showContent = wcscmp(g_iniFile.GetValue(L"global", L"showcontent", L"0"), L"0") == 0; + m_showContent = g_iniFile.GetBoolValue(L"global", L"showcontent", false); } else { @@ -799,6 +800,8 @@ LRESULT CSearchDlg::DoCommand(int id, int msg) if (!SaveSettings()) break; + CStringUtils::rtrim(m_searchpath, L"\\/"); + if (PathIsRelative(m_searchpath.c_str())) { ShowEditBalloon(IDC_SEARCHPATH, TranslatedString(hResource, IDS_ERR_INVALID_PATH).c_str(), TranslatedString(hResource, IDS_ERR_RELATIVEPATH).c_str()); @@ -844,19 +847,23 @@ LRESULT CSearchDlg::DoCommand(int id, int msg) if (m_bReplace && (!m_bCreateBackup || m_replaceString.empty()) && m_bConfirmationOnReplace) { - auto msgtext = CStringUtils::Format((LPCWSTR)TranslatedString(hResource, IDS_REPLACECONFIRM).c_str(), - m_searchString.c_str(), - m_replaceString.empty() ? (LPCWSTR)TranslatedString(hResource, IDS_ANEMPTYSTRING).c_str() : m_replaceString.c_str()); - if (::MessageBox(*this, msgtext.c_str(), _T("grepWinNP3"), MB_ICONQUESTION | MB_YESNO) != IDYES) + auto nowarnifnobackup = bPortable ? g_iniFile.GetBoolValue(L"settings", L"nowarnifnobackup", false) : DWORD(CRegStdDWORD(L"Software\\grepWinNP3\\nowarnifnobackup", FALSE)); + if (!nowarnifnobackup) { - break; + auto msgtext = CStringUtils::Format((LPCWSTR)TranslatedString(hResource, IDS_REPLACECONFIRM).c_str(), + m_searchString.c_str(), + m_replaceString.empty() ? (LPCWSTR)TranslatedString(hResource, IDS_ANEMPTYSTRING).c_str() : m_replaceString.c_str()); + if (::MessageBox(*this, msgtext.c_str(), _T("grepWinNP3"), MB_ICONQUESTION | MB_YESNO) != IDYES) + { + break; + } } } m_bConfirmationOnReplace = true; InterlockedExchange(&s_Cancelled, FALSE); InterlockedExchange(&s_NOTSearch, ((GetKeyState(VK_SHIFT) & 0x8000) != 0) ? TRUE : FALSE); ShowWindow(GetDlgItem(*this, IDC_PROGRESS), SW_SHOW); - EnableWindow(GetDlgItem(*this, IDC_SETTINGSBUTTON), FALSE); + EnableWindow(GetDlgItem(*this, IDC_SETTINGSBUTTON), FALSE); // now start the thread which does the searching InterlockedExchange(&s_SearchThreadRunning, TRUE); @@ -1780,15 +1787,29 @@ void CSearchDlg::DoListNotify(LPNMITEMACTIVATE lpNMItemActivate) swprintf_s(pItem->pszText, pItem->cchTextMax, L"%lld", pInfo->matchcount); break; case 3: // path - wcsncpy_s(pItem->pszText, pItem->cchTextMax, pInfo->filepath.substr(0, pInfo->filepath.size() - pInfo->filepath.substr(pInfo->filepath.find_last_of('\\') + 1).size() - 1).c_str(), pItem->cchTextMax - 1); + if (m_searchpath.find('|') != std::wstring::npos) + wcsncpy_s(pItem->pszText, pItem->cchTextMax, pInfo->filepath.substr(0, pInfo->filepath.size() - pInfo->filepath.substr(pInfo->filepath.find_last_of('\\')).size()).c_str(), pItem->cchTextMax - 1); + 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; + wcsncpy_s(pItem->pszText, pItem->cchTextMax, pInfo->filepath.substr(m_searchpath.size() + 1, len).c_str(), pItem->cchTextMax - 1); + } break; case 4: // extension of the file { - auto dotpos = pInfo->filepath.find_last_of('.'); - if (dotpos != std::wstring::npos) - wcsncpy_s(pItem->pszText, pItem->cchTextMax, pInfo->filepath.substr(dotpos + 1).c_str(), pItem->cchTextMax - 1); - else - pItem->pszText[0] = L'\0'; + pItem->pszText[0] = 0; + if (!pInfo->folder) + { + auto dotpos = pInfo->filepath.find_last_of('.'); + if (dotpos != std::wstring::npos) + { + if (pInfo->filepath.find('\\', dotpos) == std::wstring::npos) + wcsncpy_s(pItem->pszText, pItem->cchTextMax, pInfo->filepath.substr(dotpos + 1).c_str(), pItem->cchTextMax - 1); + } + } } break; case 5: // encoding @@ -2481,7 +2502,7 @@ DWORD CSearchDlg::SearchThread() DWORD const nMaxNumOfWorker = std::thread::hardware_concurrency() << 2; DWORD const nOfWorker = max(min(bPortable ? g_iniFile.GetLongValue(L"global", L"MaxNumOfWorker", nMaxNumOfWorker >> 1) : - DWORD(CRegStdDWORD(L"Software\\grepWinNP3\\MaxNumOfWorker", nMaxNumOfWorker >> 1)), nMaxNumOfWorker), 1); + DWORD(CRegStdDWORD(L"Software\\grepWinNP3\\MaxNumOfWorker", nMaxNumOfWorker >> 1)), nMaxNumOfWorker), 1); s_SearchThreadMap.clear(); s_SearchThreadMap.set_max_worker(nOfWorker); @@ -2507,6 +2528,7 @@ DWORD CSearchDlg::SearchThread() } found = s.find_first_of('\\', found + 1); } + CStringUtils::rtrim(s, L"\\/"); pathvector.push_back(s); } pBufSearchPath += pos; @@ -2657,11 +2679,11 @@ DWORD CSearchDlg::SearchThread() m_bCreateBackup, (DWORD(m_regBackupInFolder) != 0), m_bReplace - }; + }; if (nOfWorker > 1) { - if ((bSearch && bPattern) || bAlwaysSearch) + if ((bSearch && bPattern) || bAlwaysSearch) { if (m_searchString.empty()) { @@ -2675,10 +2697,10 @@ DWORD CSearchDlg::SearchThread() s_SearchThreadMap.insert_future(sInfoPtr, foundFuture); } } - else - { - s_SearchThreadMap.insert_ready(sInfoPtr, -1); - } + else + { + s_SearchThreadMap.insert_ready(sInfoPtr, -1); + } } else { @@ -2745,19 +2767,19 @@ DWORD CSearchDlg::SearchThread() } // empty searchpath } // pathvector - if (nOfWorker <= 1) + if (nOfWorker <= 1) { SendMessage(*this, SEARCH_END, 0, 0); - // refresh cursor + // refresh cursor POINT pt; GetCursorPos(&pt); SetCursorPos(pt.x, pt.y); - PostMessage(m_hwnd, WM_GREPWIN_THREADEND, 0, 0); - } + PostMessage(m_hwnd, WM_GREPWIN_THREADEND, 0, 0); + } - InterlockedExchange(&s_SearchThreadRunning, FALSE); + InterlockedExchange(&s_SearchThreadRunning, FALSE); return 0L; } @@ -2805,7 +2827,56 @@ DWORD WINAPI EvaluationThreadEntry(LPVOID lpParam) return 0L; } +void CSearchDlg::SetPreset(const std::wstring& preset) +{ + CBookmarks bookmarks; + bookmarks.Load(); + auto bk = bookmarks.GetBookmark(preset); + if (bk.Name == preset) + { + auto RemoveQuotes = [](std::wstring& str) { + if (!str.empty()) + { + if (str[0] == '"') + str = str.substr(1); + if (!str.empty()) + { + if (str[str.size() - 1] == '"') + str = str.substr(0, str.size() - 1); + } + } + }; + m_searchString = bk.Search; + m_replaceString = bk.Replace; + m_bUseRegex = bk.UseRegex; + m_bCaseSensitive = bk.CaseSensitive; + m_bDotMatchesNewline = bk.DotMatchesNewline; + m_bCreateBackup = bk.Backup; + m_bUTF8 = bk.Utf8; + m_bIncludeSystem = bk.IncludeSystem; + m_bIncludeSubfolders = bk.IncludeFolder; + m_bIncludeHidden = bk.IncludeHidden; + m_bIncludeBinary = bk.IncludeBinary; + m_excludedirspatternregex = bk.ExcludeDirs; + m_patternregex = bk.FileMatch; + m_bUseRegexForPaths = bk.FileMatchRegex; + m_bIncludeSystemC = true; + m_bIncludeHiddenC = true; + m_bIncludeSubfoldersC = true; + m_bIncludeBinaryC = true; + m_bCreateBackupC = true; + m_bCreateBackupInFoldersC = true; + m_bUTF8C = true; + m_bCaseSensitiveC = true; + m_bDotMatchesNewlineC = true; + + RemoveQuotes(m_searchString); + RemoveQuotes(m_replaceString); + RemoveQuotes(m_excludedirspatternregex); + RemoveQuotes(m_patternregex); + } +} bool CSearchDlg::MatchPath(LPCTSTR pathbuf) { diff --git a/grepWinNP3/src/SearchDlg.h b/grepWinNP3/src/SearchDlg.h index e2551477a..7aff7a0f1 100644 --- a/grepWinNP3/src/SearchDlg.h +++ b/grepWinNP3/src/SearchDlg.h @@ -76,9 +76,10 @@ public: void SetSearchPath(const std::wstring& path) {m_searchpath = path; SearchReplace(m_searchpath, L"/", L"\\"); } void SetSearchString(const std::wstring& search) {m_searchString = search;} void SetFileMask(const std::wstring& mask, bool reg) {m_patternregex = mask; m_bUseRegexForPaths = reg;} - void SetExcludeFileMask(const std::wstring& mask) {m_excludedirspatternregex = mask;} + void SetDirExcludeRegexMask(const std::wstring& mask) {m_excludedirspatternregex = mask;} void SetReplaceWith(const std::wstring& replace) { m_replaceString = replace; } void SetUseRegex(bool reg) { m_bUseRegex = reg; } + void SetPreset(const std::wstring& preset); void SetCaseSensitive(bool bSet) {m_bCaseSensitiveC = true; m_bCaseSensitive = bSet;} void SetMatchesNewline(bool bSet) {m_bDotMatchesNewlineC = true; m_bDotMatchesNewline = bSet;} diff --git a/grepWinNP3/src/Settings.cpp b/grepWinNP3/src/Settings.cpp index c359536e8..8d05aba9a 100644 --- a/grepWinNP3/src/Settings.cpp +++ b/grepWinNP3/src/Settings.cpp @@ -182,6 +182,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_ONLYONE, BM_SETCHECK, bPortable ? g_iniFile.GetBoolValue(L"global", L"onlyone", false) : !!DWORD(CRegStdDWORD(L"Software\\grepWinNP3\\onlyone", FALSE)) ? BST_CHECKED : BST_UNCHECKED, 0); SendDlgItemMessage(hwndDlg, IDC_DARKMODE, BM_SETCHECK, CTheme::Instance().IsDarkTheme() ? BST_CHECKED : BST_UNCHECKED, 0); EnableWindow(GetDlgItem(*this, IDC_DARKMODE), CTheme::Instance().IsDarkModeAllowed()); @@ -209,6 +210,7 @@ LRESULT CSettingsDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lPa m_resizer.AddControl(hwndDlg, IDC_LANGUAGE, RESIZER_TOPRIGHT); m_resizer.AddControl(hwndDlg, IDC_ESCKEY, RESIZER_TOPLEFTRIGHT); m_resizer.AddControl(hwndDlg, IDC_BACKUPINFOLDER, RESIZER_TOPLEFTRIGHT); + m_resizer.AddControl(hwndDlg, IDC_NOWARNINGIFNOBACKUP, RESIZER_TOPLEFTRIGHT); m_resizer.AddControl(hwndDlg, IDC_ONLYONE, RESIZER_TOPLEFTRIGHT); m_resizer.AddControl(hwndDlg, IDC_DARKMODE, RESIZER_TOPLEFT); m_resizer.AddControl(hwndDlg, IDC_DARKMODEINFO, RESIZER_TOPLEFTRIGHT); @@ -298,6 +300,7 @@ LRESULT CSettingsDlg::DoCommand(int id, int /*msg*/) { g_iniFile.SetBoolValue(L"settings", L"escclose", (IsDlgButtonChecked(*this, IDC_ESCKEY) == BST_CHECKED)); g_iniFile.SetBoolValue(L"settings", L"backupinfolder", (IsDlgButtonChecked(*this, IDC_BACKUPINFOLDER) == BST_CHECKED)); + g_iniFile.SetBoolValue(L"settings", L"nowarnifnobackup", (IsDlgButtonChecked(*this, IDC_NOWARNINGIFNOBACKUP) == BST_CHECKED)); g_iniFile.SetBoolValue(L"global", L"onlyone", (IsDlgButtonChecked(*this, IDC_ONLYONE) == BST_CHECKED)); g_iniFile.SetLongValue(L"global", L"MaxNumOfWorker", nWorker); } @@ -307,6 +310,8 @@ LRESULT CSettingsDlg::DoCommand(int id, int /*msg*/) esc = (IsDlgButtonChecked(*this, IDC_ESCKEY) == BST_CHECKED); CRegStdDWORD backup(L"Software\\grepWinNP3\\backupinfolder", FALSE); backup = (IsDlgButtonChecked(*this, IDC_BACKUPINFOLDER) == BST_CHECKED); + CRegStdDWORD nowarn(L"Software\\grepWinNP3\\nowarnifnobackup", FALSE); + nowarn = (IsDlgButtonChecked(*this, IDC_NOWARNINGIFNOBACKUP) == BST_CHECKED); CRegStdDWORD regOnlyOne(L"Software\\grepWinNP3\\onlyone", FALSE); regOnlyOne = (IsDlgButtonChecked(*this, IDC_ONLYONE) == BST_CHECKED); CRegStdDWORD nwrk(L"Software\\grepWinNP3\\MaxNumOfWorker", 1); diff --git a/grepWinNP3/src/Theme.cpp b/grepWinNP3/src/Theme.cpp index 4db2afd99..1af9ce707 100644 --- a/grepWinNP3/src/Theme.cpp +++ b/grepWinNP3/src/Theme.cpp @@ -149,6 +149,7 @@ bool CTheme::SetThemeForDialog(HWND hWnd, bool bDark) RemoveWindowSubclass(hWnd, MainSubclassProc, SubclassID); } EnumChildWindows(hWnd, AdjustThemeForChildrenProc, bDark ? TRUE : FALSE); + EnumThreadWindows(GetCurrentThreadId(), AdjustThemeForChildrenProc, bDark ? TRUE : FALSE); ::RedrawWindow(hWnd, nullptr, nullptr, RDW_FRAME | RDW_INVALIDATE | RDW_ERASE | RDW_INTERNALPAINT | RDW_ALLCHILDREN | RDW_UPDATENOW); } return true; @@ -219,11 +220,11 @@ BOOL CTheme::AdjustThemeForChildrenProc(HWND hwnd, LPARAM lParam) else if ((wcscmp(szWndClassName, WC_COMBOBOXEX) == 0) || (wcscmp(szWndClassName, WC_COMBOBOX) == 0)) { - SetWindowTheme(hwnd, L"DarkMode_Explorer", nullptr); + SetWindowTheme(hwnd, L"Explorer", nullptr); HWND hCombo = hwnd; if (wcscmp(szWndClassName, WC_COMBOBOXEX) == 0) { - SendMessage(hwnd, CBEM_SETWINDOWTHEME, 0, (LPARAM)L"DarkMode_Explorer"); + SendMessage(hwnd, CBEM_SETWINDOWTHEME, 0, (LPARAM)L"Explorer"); hCombo = (HWND)SendMessage(hwnd, CBEM_GETCOMBOCONTROL, 0, 0); } if (hCombo) @@ -237,9 +238,9 @@ BOOL CTheme::AdjustThemeForChildrenProc(HWND hwnd, LPARAM lParam) DarkModeHelper::Instance().AllowDarkModeForWindow(info.hwndItem, (BOOL)lParam); DarkModeHelper::Instance().AllowDarkModeForWindow(info.hwndCombo, (BOOL)lParam); - SetWindowTheme(info.hwndList, L"DarkMode_Explorer", nullptr); - SetWindowTheme(info.hwndItem, L"DarkMode_Explorer", nullptr); - SetWindowTheme(info.hwndCombo, L"DarkMode_Explorer", nullptr); + SetWindowTheme(info.hwndList, L"Explorer", nullptr); + SetWindowTheme(info.hwndItem, L"Explorer", nullptr); + SetWindowTheme(info.hwndCombo, L"Explorer", nullptr); } } } @@ -272,7 +273,19 @@ BOOL CTheme::AdjustThemeForChildrenProc(HWND hwnd, LPARAM lParam) SendMessage(hwnd, PBM_SETBKCOLOR, 0, (LPARAM)darkBkColor); SendMessage(hwnd, PBM_SETBARCOLOR, 0, (LPARAM)RGB(100,100,0)); } - else if (FAILED(SetWindowTheme(hwnd, L"DarkMode_Explorer", nullptr))) + else if (wcscmp(szWndClassName, L"Auto-Suggest Dropdown") == 0) + { + SetWindowTheme(hwnd, L"Explorer", nullptr); + // note: since the list control used to show the suggest dropdown has + // the style LVS_OWNERDRAWFIXED setting the theme has no effect. + // that's why we don't enumerate over the children of the "Auto-Suggest Dropdown" + //EnumChildWindows(hwnd, AdjustThemeForChildrenProc, lParam); + } + else if (wcscmp(szWndClassName, TOOLTIPS_CLASSW) == 0) + { + SetWindowTheme(hwnd, L"Explorer", nullptr); + } + else SetWindowTheme(hwnd, L"Explorer", nullptr); } else diff --git a/grepWinNP3/src/grepWin.cpp b/grepWinNP3/src/grepWin.cpp index a03375e0a..57e0f3754 100644 --- a/grepWinNP3/src/grepWin.cpp +++ b/grepWinNP3/src/grepWin.cpp @@ -283,10 +283,14 @@ int APIENTRY _tWinMain(HINSTANCE hInstance, searchDlg.SetFileMask(parser.GetVal(_T("filemaskregex")), true); if (parser.HasVal(_T("filemask"))) searchDlg.SetFileMask(parser.GetVal(_T("filemask")), false); - if (parser.HasVal(_T("filemaskexclude"))) - searchDlg.SetExcludeFileMask(parser.GetVal(_T("filemaskexclude"))); + if (parser.HasVal(_T("direxcluderegex"))) + searchDlg.SetDirExcludeRegexMask(parser.GetVal(_T("direxcluderegex"))); + else if (parser.HasVal(_T("filemaskexclude"))) + searchDlg.SetDirExcludeRegexMask(parser.GetVal(_T("filemaskexclude"))); if (parser.HasVal(_T("replacewith"))) searchDlg.SetReplaceWith(parser.GetVal(_T("replacewith"))); + if (parser.HasVal(_T("preset"))) + searchDlg.SetPreset(parser.GetVal(_T("preset"))); if (parser.HasVal(_T("i"))) searchDlg.SetCaseSensitive(_tcsicmp(parser.GetVal(_T("i")), _T("yes"))!=0); diff --git a/grepWinNP3/src/last/version.h b/grepWinNP3/src/last/version.h index b27cde216..d77cfe17f 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, 0, 9 -#define PRODUCTVER 2, 1, 0, 9 -#define STRFILEVER "2.1.0.9\0" -#define STRPRODUCTVER "2.1.0.9\0" +#define FILEVER 2, 1, 0, 10 +#define PRODUCTVER 2, 1, 0, 10 +#define STRFILEVER "2.1.0.10\0" +#define STRPRODUCTVER "2.1.0.10\0" #define GREPWIN_VERMAJOR 2 #define GREPWIN_VERMINOR 1 #define GREPWIN_VERMICRO 0 -#define GREPWIN_VERBUILD 9 -#define GREPWIN_VERDATE "2020-05-05" +#define GREPWIN_VERBUILD 10 +#define GREPWIN_VERDATE "2020-05-17" diff --git a/grepWinNP3/src/resource.h b/grepWinNP3/src/resource.h index 20e9be7f8..bb0d53547 100644 --- a/grepWinNP3/src/resource.h +++ b/grepWinNP3/src/resource.h @@ -156,6 +156,8 @@ #define IDC_SPIN_MAXWORKER 1086 #define IDC_MAXNUMWORKER 1087 #define IDC_TEXT_NUMOFWORKER 1088 +#define IDC_BACKUPINFOLDER2 1089 +#define IDC_NOWARNINGIFNOBACKUP 1090 #define ID_REMOVEBOOKMARK 32771 #define ID_DUMMY_RENAMEPRESET 32774 #define ID_RENAMEBOOKMARK 32775 @@ -168,7 +170,7 @@ #define _APS_NO_MFC 1 #define _APS_NEXT_RESOURCE_VALUE 161 #define _APS_NEXT_COMMAND_VALUE 32776 -#define _APS_NEXT_CONTROL_VALUE 1089 +#define _APS_NEXT_CONTROL_VALUE 1091 #define _APS_NEXT_SYMED_VALUE 110 #endif #endif diff --git a/grepWinNP3/translations/Deutsch (Deutschland) [de-DE].lang b/grepWinNP3/translations/Deutsch (Deutschland) [de-DE].lang index feb073cdb..0c3428e3e 100644 --- a/grepWinNP3/translations/Deutsch (Deutschland) [de-DE].lang +++ b/grepWinNP3/translations/Deutsch (Deutschland) [de-DE].lang @@ -271,6 +271,10 @@ msgstr "OK" msgid "Older than" msgstr "Älter als" +#. Resource IDs: (1090) +msgid "Don't warn when replacing without creating backups" +msgstr "Keine Warnung bei Textersetzung ohne Backup" + #. Resource IDs: (1063) msgid "Only one instance" msgstr "Nur eine Instanz" diff --git a/grepWinNP3/translations/English (United Kingdom) [en-GB].lang b/grepWinNP3/translations/English (United Kingdom) [en-GB].lang index 7ea865dd3..82e507bea 100644 --- a/grepWinNP3/translations/English (United Kingdom) [en-GB].lang +++ b/grepWinNP3/translations/English (United Kingdom) [en-GB].lang @@ -271,6 +271,10 @@ msgstr "" msgid "Older than" msgstr "" +#. Resource IDs: (1090) +msgid "Don't warn when replacing without creating backups" +msgstr "" + #. Resource IDs: (1063) msgid "Only one instance" msgstr "" diff --git a/grepWinNP3/translations/English (United States) [en-US].lang b/grepWinNP3/translations/English (United States) [en-US].lang index 09dd0e449..ef3ef84e0 100644 --- a/grepWinNP3/translations/English (United States) [en-US].lang +++ b/grepWinNP3/translations/English (United States) [en-US].lang @@ -9,7 +9,7 @@ # # encoding: UTF-8 # Language: English (United States) resources -# Last-Translator: (en-US) English translation by RaiKoHoff +# Last-Translator: (en-US) English translation by Stefan Kueng # #, fuzzy @@ -271,6 +271,10 @@ msgstr "" msgid "Older than" msgstr "" +#. Resource IDs: (1090) +msgid "Don't warn when replacing without creating backups" +msgstr "" + #. Resource IDs: (1063) msgid "Only one instance" msgstr ""