Skip to content

Commit

Permalink
add helper dialog to convert newlines in the multiline edit dialog to…
Browse files Browse the repository at this point in the history
… regex newlines

closes #522
  • Loading branch information
stefankueng committed Nov 16, 2024
1 parent cb5e0ac commit cff8ba6
Show file tree
Hide file tree
Showing 9 changed files with 382 additions and 94 deletions.
78 changes: 78 additions & 0 deletions src/MultiLineEditDlg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,36 @@
#include "stdafx.h"
#include "resource.h"
#include "MultiLineEditDlg.h"

#include "NewlinesDlg.h"
#include "Theme.h"
#include "../sktoolslib/StringUtils.h"

#include <string>
#include <Richedit.h>
#include <boost/regex.hpp>

CMultiLineEditDlg::CMultiLineEditDlg(HWND hParent)
: m_hParent(hParent)
, m_themeCallbackId(0)
, m_forReplace(false)
, m_forRegex(false)
{
}

CMultiLineEditDlg::~CMultiLineEditDlg()
{
}

void CMultiLineEditDlg::setForReplace()
{
m_forReplace = true;
}
void CMultiLineEditDlg::setForRegex()
{
m_forRegex = true;
}

LRESULT CMultiLineEditDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
Expand All @@ -50,13 +65,33 @@ LRESULT CMultiLineEditDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARA
InitDialog(hwndDlg, IDI_GREPWIN);
CLanguage::Instance().TranslateWindow(*this);
// initialize the controls
if (!m_forRegex)
{
ShowWindow(GetDlgItem(hwndDlg, IDC_CONVERTNEWLINES_BTN), SW_HIDE);
ShowWindow(GetDlgItem(hwndDlg, IDC_INFOLABEL), SW_HIDE);
}
else
{
// does the string already contain newlines?
if (m_regexText.find(L"\n") == std::wstring::npos)
{
// use boost regex to append all \\r\\n, \\r, \\n with newlines, but only if they're not already followed by newlines
m_regexText = boost::regex_replace(m_regexText, boost::wregex(L"(\\\\r\\\\n)(?!\\r|\\n|\\||\\))"), L"\\\\r\\\\n\\r\\n");
m_regexText = boost::regex_replace(m_regexText, boost::wregex(L"(\\\\r)(?!\\\\n|\\r|\\n|\\||\\))"), L"\\\\r\\r\\n");
m_regexText = boost::regex_replace(m_regexText, boost::wregex(L"(\\\\n)(?!\\r|\\n|\\||\\))"), L"\\\\n\\r\\n");
m_regexText = boost::regex_replace(m_regexText, boost::wregex(L"(\\(\\\\r\\\\n\\|\\\\r\\|\\\\n\\))(?!\\r|\\n|\\||\\))"), L"\\(\\\\r\\\\n\\|\\\\r\\|\\\\n\\)\\r\\n");
}
}

SetDlgItemText(hwndDlg, IDC_TEXTCONTENT, m_regexText.c_str());

SetFocus(GetDlgItem(hwndDlg, IDC_TEXTCONTENT));

m_resizer.Init(hwndDlg);
m_resizer.UseSizeGrip(!CTheme::Instance().IsDarkTheme());
m_resizer.AddControl(hwndDlg, IDC_TEXTCONTENT, RESIZER_TOPLEFTBOTTOMRIGHT);
m_resizer.AddControl(hwndDlg, IDC_INFOLABEL, RESIZER_BOTTOMLEFTRIGHT);
m_resizer.AddControl(hwndDlg, IDC_CONVERTNEWLINES_BTN, RESIZER_BOTTOMLEFT);
m_resizer.AddControl(hwndDlg, IDOK, RESIZER_BOTTOMRIGHT);
m_resizer.AddControl(hwndDlg, IDCANCEL, RESIZER_BOTTOMRIGHT);

Expand Down Expand Up @@ -95,6 +130,12 @@ LRESULT CMultiLineEditDlg::DoCommand(int id, int msg)
{
auto buf = GetDlgItemText(IDC_TEXTCONTENT);
m_regexText = std::wstring(buf.get());
if (m_forRegex)
{
// remove formatting newlines
SearchReplace(m_regexText, L"\n", L"");
SearchReplace(m_regexText, L"\r", L"");
}
}
[[fallthrough]];
case IDCANCEL:
Expand All @@ -109,6 +150,43 @@ LRESULT CMultiLineEditDlg::DoCommand(int id, int msg)
}
}
break;
case IDC_CONVERTNEWLINES_BTN:
CNewlinesDlg newLinesDlg(*this);
newLinesDlg.setShowBoth(!m_forReplace);
if (newLinesDlg.DoModal(hResource, IDD_NEWLINESDLG, *this) == IDOK)
{
auto buf = GetDlgItemText(IDC_TEXTCONTENT);
m_regexText = std::wstring(buf.get());
// normalize newlines
SearchReplace(m_regexText, L"\r\n", L"\n");
SearchReplace(m_regexText, L"\r", L"\n");

switch (newLinesDlg.getNewLines())
{
case eNewlines::Linux:
{
// convert newlines to regex newlines
SearchReplace(m_regexText, L"\n", L"\\n\r\n");
}
break;
case eNewlines::Windows:
{
// convert newlines to regex newlines
SearchReplace(m_regexText, L"\n", L"\\r\\n\r\n");
}
break;
case eNewlines::Both:
{
// convert newlines to regex newlines
SearchReplace(m_regexText, L"\n", L"(\\r\\n|\\r|\\n)\r\n");
}
break;
default:
break;
}
SetDlgItemText(*this, IDC_TEXTCONTENT, m_regexText.c_str());
}
break;
}
return 1;
}
6 changes: 5 additions & 1 deletion src/MultiLineEditDlg.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// grepWin - regex search and replace for Windows

// Copyright (C) 2011-2013, 2019-2021 - Stefan Kueng
// Copyright (C) 2011-2013, 2019-2021, 2024 - Stefan Kueng

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
Expand Down Expand Up @@ -34,6 +34,8 @@ class CMultiLineEditDlg : public CDialog

void SetString(const std::wstring& search) { m_regexText = search; }
std::wstring GetSearchString() const { return m_regexText; }
void setForReplace();
void setForRegex();

protected:
LRESULT CALLBACK DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
Expand All @@ -44,4 +46,6 @@ class CMultiLineEditDlg : public CDialog
std::wstring m_regexText;
int m_themeCallbackId;
CDlgResizer m_resizer;
bool m_forReplace;
bool m_forRegex;
};
120 changes: 120 additions & 0 deletions src/NewlinesDlg.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
// grepWin - regex search and replace for Windows

// Copyright (C) 2024 - Stefan Kueng

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
#include "stdafx.h"
#include "resource.h"
#include "NewlinesDlg.h"
#include "Theme.h"
#include <boost/regex.hpp>

CNewlinesDlg::CNewlinesDlg(HWND hParent)
: m_hParent(hParent)
, m_themeCallbackId(0)
, m_newLines(eNewlines::None)
{
}

CNewlinesDlg::~CNewlinesDlg()
{
}
void CNewlinesDlg::setNewLines(eNewlines nl)
{
m_newLines = nl;
}
eNewlines CNewlinesDlg::getNewLines() const
{
return m_newLines;
}
void CNewlinesDlg::setShowBoth(bool show)
{
m_showBoth = show;
}

LRESULT CNewlinesDlg::DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (uMsg)
{
case WM_INITDIALOG:
{
m_themeCallbackId = CTheme::Instance().RegisterThemeChangeCallback(
[this]() {
CTheme::Instance().SetThemeForDialog(*this, CTheme::Instance().IsDarkTheme());
});
CTheme::Instance().SetThemeForDialog(*this, CTheme::Instance().IsDarkTheme());

InitDialog(hwndDlg, IDI_GREPWIN);
CLanguage::Instance().TranslateWindow(*this);
// initialize the controls
switch (m_newLines)
{
case eNewlines::None:
CheckRadioButton(hwndDlg, IDC_CRLF, IDC_BOTH, IDC_CRLF);

break;
case eNewlines::Linux:
CheckRadioButton(hwndDlg, IDC_CRLF, IDC_BOTH, IDC_LF);
break;
case eNewlines::Windows:
CheckRadioButton(hwndDlg, IDC_CRLF, IDC_BOTH, IDC_CRLF);
break;
case eNewlines::Both:
CheckRadioButton(hwndDlg, IDC_CRLF, IDC_BOTH, IDC_BOTH);
break;
}
if (!m_showBoth)
{
ShowWindow(GetDlgItem(hwndDlg, IDC_BOTH), SW_HIDE);
}
}
return FALSE;
case WM_COMMAND:
return DoCommand(LOWORD(wParam), HIWORD(wParam));
case WM_CLOSE:
CTheme::Instance().RemoveRegisteredCallback(m_themeCallbackId);
break;
default:
return FALSE;
}
return FALSE;
}

LRESULT CNewlinesDlg::DoCommand(int id, int /*msg*/)
{
switch (id)
{
case IDOK:
if (IsDlgButtonChecked(*this, IDC_LF) == BST_CHECKED)
{
m_newLines = eNewlines::Linux;
}
else if (IsDlgButtonChecked(*this, IDC_CRLF) == BST_CHECKED)
{
m_newLines = eNewlines::Windows;
}
else if (IsDlgButtonChecked(*this, IDC_BOTH) == BST_CHECKED)
{
m_newLines = eNewlines::Both;
}
[[fallthrough]];
case IDCANCEL:
EndDialog(*this, id);
break;
}
return 1;
}
49 changes: 49 additions & 0 deletions src/NewlinesDlg.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// grepWin - regex search and replace for Windows

// Copyright (C) 2024 - Stefan Kueng

// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2
// of the License, or (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software Foundation,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
#pragma once
#include "BaseDialog.h"

enum class eNewlines
{
None,
Linux,
Windows,
Both,
};

class CNewlinesDlg : public CDialog
{
public:
CNewlinesDlg(HWND hParent);
~CNewlinesDlg() override;

void setNewLines(eNewlines nl);
eNewlines getNewLines() const;
void setShowBoth(bool show);

protected:
LRESULT CALLBACK DlgFunc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) override;
LRESULT DoCommand(int id, int msg);

private:
HWND m_hParent;
int m_themeCallbackId;
eNewlines m_newLines;
bool m_showBoth;
};
Loading

0 comments on commit cff8ba6

Please sign in to comment.