Click here to Skip to main content
15,891,136 members
Articles / Desktop Programming / MFC

Notepad RE (Regular Expressions)

Rate me:
Please Sign up or sign in to vote.
4.68/5 (107 votes)
22 Mar 2011CPOL9 min read 842.1K   8.5K   234  
Search and replace text in Notepad RE using Regular Expressions or normal mode. The editor supports drag and drop, file change notifications, and displays the line and column numbers. Unicode support is available too.
// FindReplaceDlg.cpp : implementation file
//

#include "stdafx.h"
#include "notepadre.h"
#include "FindReplaceDlg.h"
#include "enums.h"
#include "messages.h"

#include <htmlhelp.h>

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

/////////////////////////////////////////////////////////////////////////////
// CFindReplaceDlg dialog
CFindReplaceDlg::CFindReplaceDlg () :
	m_pParentWnd (0),
	m_IDD (0),
	m_bInitialWholeWordOnly (false),
	m_bInitialMatchCase (false),
	m_bInitialRegEx (false)
{
}

void CFindReplaceDlg::SetInitial (CWnd *pParentWnd, const int IDD)
{
	m_pParentWnd = pParentWnd;
	m_IDD = IDD;
}

BOOL CFindReplaceDlg::IsRegExSet ()
{
	return m_CheckRegEx.GetCheck () != 0;
}

void CFindReplaceDlg::SetWholeWordOnly (const bool bWholeWordOnly)
{
	m_CheckWholeWordOnly.SetCheck (bWholeWordOnly);
}

void CFindReplaceDlg::SetMatchCase (const bool bMatchCase)
{
	m_CheckMatchCase.SetCheck (bMatchCase);
}

void CFindReplaceDlg::SetRegEx (const bool bRegEx)
{
	m_CheckRegEx.SetCheck (bRegEx);
	OnCheckRegex ();
}

void CFindReplaceDlg::SetSearchUp (const bool bUp)
{
	if (!m_CheckRegEx.GetCheck ())
	{
		m_RadioUp.SetCheck (bUp);
		m_RadioDown.SetCheck (!bUp);
	}
}

void CFindReplaceDlg::SetCloseOnMatch (const bool bCloseOnMatch)
{
	m_CheckCloseOnMatch.SetCheck (bCloseOnMatch);
}

void CFindReplaceDlg::
	SetReplaceAllLikeNotepad (const bool bReplaceAllLikeNotepad)
{
	m_CheckReplaceAllLikeNotepad.SetCheck (bReplaceAllLikeNotepad);
}

const CString &CFindReplaceDlg::GetFindText ()
{
	m_EditFindText.GetWindowText (m_strFindText);
	return m_strFindText;
}

const CString &CFindReplaceDlg::GetReplaceText ()
{
	m_EditReplaceText.GetWindowText (m_strReplaceText);
	return m_strReplaceText;
}

void CFindReplaceDlg::SetFindText (const CString &strFind)
{
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::SetReplaceText (const CString &strReplace)
{
	m_EditReplaceText.SetWindowText (strReplace);
}

void CFindReplaceDlg::DoDataExchange(CDataExchange* pDX)
{
	CDialogBar::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CFindReplaceDlg)
		// NOTE: the ClassWizard will add DDX and DDV calls here
	//}}AFX_DATA_MAP
}

// NOTE: Command handlers needed in Mainfrm.cpp to enable buttons!
BEGIN_MESSAGE_MAP(CFindReplaceDlg, CDialogBar)
	//{{AFX_MSG_MAP(CFindReplaceDlg)
	ON_WM_HELPINFO()
	ON_BN_CLICKED(IDC_BUTTON_REGEX, OnButtonRegEx)
	ON_COMMAND(ID_ANY_CHARACTER, OnAnyCharacter)
	ON_COMMAND(ID_CHAR_IN_RANGE, OnCharInRange)
	ON_COMMAND(ID_CHAR_NOT_IN_RANGE, OnCharNotInRange)
	ON_COMMAND(ID_BEGINNING_OF_LINE, OnBeginningOfLine)
	ON_COMMAND(ID_END_OF_LINE, OnEndOfLine)
	ON_COMMAND(ID_OR, OnOr)
	ON_COMMAND(ID_OPTIONAL, OnOptional)
	ON_COMMAND(ID_ZERO_OR_MORE, OnZeroOrMore)
	ON_COMMAND(ID_ONE_OR_MORE, OnOneOrMore)
	ON_COMMAND(ID_RANGE, OnRange)
	ON_COMMAND(ID_WHITESPACE, OnWhitespace)
	ON_COMMAND(ID_ALPHANUMERIC, OnAlphaNumeric)
	ON_COMMAND(ID_ALPHABETIC, OnAlphabetic)
	ON_COMMAND(ID_DECIMAL_DIGIT, OnDecimalDigit)
	ON_COMMAND(ID_HEXADECIMAL_NUMBER, OnHexadecimalNumber)
	ON_COMMAND(ID_NUMBER, OnNumber)
	ON_COMMAND(ID_INTEGER, OnInteger)
	ON_COMMAND(ID_ALPHABETIC_STRING, OnAlphabeticString)
	ON_COMMAND(ID_QUOTED_STRING, OnQuotedString)
	ON_BN_CLICKED(IDC_CHECK_WHOLE_WORD, OnCheckWholeWord)
	ON_BN_CLICKED(IDC_CHECK_MATCH_CASE, OnCheckMatchCase)
	ON_BN_CLICKED(IDC_CHECK_REGEX, OnCheckRegex)
	ON_BN_CLICKED(IDC_CHECK_LIKE_NOTEPAD, OnCheckLikeNotepad)
	ON_BN_CLICKED(IDC_RADIO_UP, OnRadioUp)
	ON_BN_CLICKED(IDC_RADIO_DOWN, OnRadioDown)
	ON_BN_CLICKED(IDC_CHECK_CLOSE_ON_MATCH, OnCheckCloseOnMatch)
	ON_BN_CLICKED(IDOK, OnOk)
	ON_BN_CLICKED(IDC_BUTTON_REPLACE, OnButtonReplace)
	ON_BN_CLICKED(IDC_BUTTON_REPLACE_ALL, OnButtonReplaceAll)
	ON_BN_CLICKED(IDC_BUTTON_HELP, OnButtonHelp)
	ON_BN_CLICKED(IDCANCEL, OnCancel)
	ON_MESSAGE(WM_INITDIALOG, OnInitDialog)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CFindReplaceDlg message handlers

LONG CFindReplaceDlg::OnInitDialog (UINT wParam, LONG lParam)
{
	BOOL bRet = HandleInitDialog (wParam, lParam);

	m_CheckWholeWordOnly.SubclassDlgItem (IDC_CHECK_WHOLE_WORD, this);
	m_CheckWholeWordOnly.SetCheck (m_bInitialWholeWordOnly);
	m_CheckMatchCase.SubclassDlgItem (IDC_CHECK_MATCH_CASE, this);
	m_CheckMatchCase.SetCheck (m_bInitialMatchCase);
	m_CheckRegEx.SubclassDlgItem (IDC_CHECK_REGEX, this);
	m_CheckRegEx.SetCheck (m_bInitialRegEx);
	m_ButtonRegex.SubclassDlgItem (IDC_BUTTON_REGEX, this);
	m_ButtonRegex.SetIcon (AfxGetApp ()->LoadIcon (IDI_RIGHT));

	if (m_IDD == IDD_FIND)
	{
		m_RadioUp.SubclassDlgItem (IDC_RADIO_UP, this);
		m_RadioDown.SubclassDlgItem (IDC_RADIO_DOWN, this);
		m_RadioDown.SetCheck (TRUE);

		if (m_bInitialRegEx) m_RadioUp.EnableWindow (FALSE);

		m_CheckCloseOnMatch.SubclassDlgItem (IDC_CHECK_CLOSE_ON_MATCH, this);
	}
	else
	{
		m_EditReplaceText.SubclassDlgItem (IDC_EDIT_REPLACE, this);
		m_CheckReplaceAllLikeNotepad.SubclassDlgItem (IDC_CHECK_LIKE_NOTEPAD,
			this);
	}

	m_EditFindText.SubclassDlgItem (IDC_EDIT_FIND, this);
	m_EditFindText.SetWindowText (m_strInitialFind);
	m_ButtonReplace.SubclassDlgItem (IDC_BUTTON_REPLACE, this);

	if (m_IDD == IDD_FIND)
	{
		SetWindowText (_T("Find"));
	}
	else
	{
		SetWindowText (_T("Replace"));
	}

	return bRet;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}

BOOL CFindReplaceDlg::OnHelpInfo(HELPINFO* pHelpInfo)
{
	BOOL bRet = TRUE;
	RECT rect;
	HH_POPUP popup;
	CString strArial8;

	switch (pHelpInfo->iCtrlId)
	{
		case IDC_EDIT_FIND :
			m_EditFindText.GetWindowRect (&rect);
			popup.idString = IDS_FIND_WHAT;
			break;
		case IDC_BUTTON_REGEX:
			m_ButtonRegex.GetWindowRect (&rect);
			popup.idString = IDS_BUTTON_REGEX;
			break;
		case IDC_EDIT_REPLACE :
			m_EditReplaceText.GetWindowRect (&rect);
			popup.idString = IDS_REPLACE_WHAT;
			break;
		case IDC_CHECK_WHOLE_WORD :
			m_CheckWholeWordOnly.GetWindowRect (&rect);
			popup.idString = IDS_WHOLE_WORD_ONLY;
			break;
		case IDC_CHECK_MATCH_CASE :
			m_CheckMatchCase.GetWindowRect (&rect);
			popup.idString = IDS_MATCH_CASE;
			break;
		case IDC_CHECK_REGEX :
			m_CheckRegEx.GetWindowRect (&rect);
			popup.idString = IDS_REGULAR_EXPRESSION;
			break;
		case IDC_CHECK_LIKE_NOTEPAD :
			m_CheckReplaceAllLikeNotepad.GetWindowRect (&rect);
			popup.idString = IDS_LIKE_NOTEPAD;
			break;
		case IDC_RADIO_UP :
			m_RadioUp.GetWindowRect (&rect);
			popup.idString = IDS_UP;
			break;
		case IDC_RADIO_DOWN :
			m_RadioDown.GetWindowRect (&rect);
			popup.idString = IDS_DOWN;
			break;
		case IDC_CHECK_CLOSE_ON_MATCH :
			m_CheckCloseOnMatch.GetWindowRect (&rect);
			popup.idString = IDS_CLOSE_ON_MATCH;
			break;
		case IDOK :
			GetDlgItem (IDOK)->GetWindowRect (&rect);
			popup.idString = IDS_FIND_NEXT;
			break;
		case IDC_BUTTON_REPLACE :
			GetDlgItem (IDC_BUTTON_REPLACE)->GetWindowRect (&rect);
			popup.idString = IDS_REPLACE;
			break;
		case IDC_BUTTON_REPLACE_ALL :
			GetDlgItem (IDC_BUTTON_REPLACE_ALL)->GetWindowRect (&rect);
			popup.idString = IDS_REPLACE_ALL;
			break;
		case IDCANCEL :
			GetDlgItem (IDCANCEL)->GetWindowRect (&rect);
			popup.idString = IDS_CANCEL;
			break;
		case IDC_BUTTON_HELP :
			GetDlgItem (IDC_BUTTON_HELP)->GetWindowRect (&rect);
			popup.idString = IDS_HELP;
			break;
		default:
			ASSERT (0);
			break;
	}

	popup.cbStruct = sizeof (popup);
	popup.hinst = AfxGetResourceHandle ();
	popup.pszText = 0;
	popup.pt.x = rect.left;
	popup.pt.y = rect.top;
	popup.clrForeground = -1;
	popup.clrBackground = -1;
	popup.rcMargins.top = 7;
	popup.rcMargins.left = 20;
	popup.rcMargins.bottom = 7;
	popup.rcMargins.right = 7;
	strArial8.LoadString (IDS_ARIAL_8);
	popup.pszFont = strArial8;
	::HtmlHelp (0, 0, HH_DISPLAY_TEXT_POPUP,
		(DWORD) &popup);
	return bRet;
}

void CFindReplaceDlg::OnButtonRegEx ()
{
	CMenu menu;
	CRect rect;

	m_ButtonRegex.GetWindowRect (&rect);
	menu.LoadMenu (IDR_MENU_REGEX_SYNTAX);
	menu.GetSubMenu (0)->TrackPopupMenu (TPM_LEFTALIGN | TPM_RIGHTBUTTON,
		rect.right, rect.top, this, NULL);
}

void CFindReplaceDlg::OnAnyCharacter ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += '.';
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnCharInRange ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "[]";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnCharNotInRange ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "[^]";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnBeginningOfLine ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += '^';
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnEndOfLine ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += '$';
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnOr ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += '|';
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnOptional ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += '?';
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnZeroOrMore ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += '*';
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnOneOrMore ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += '+';
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnRange ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "{n,m}";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnWhitespace ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "\\s+";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnAlphaNumeric ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "[[:alnum:]]";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnAlphabetic ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "[[:alpha:]]";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnDecimalDigit ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "\\d";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnHexadecimalNumber ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "[\\da-fA-F]+";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnNumber ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "[-+]?(\\d*[.]\\d+|\\d+[.]?)";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnInteger ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "[-+]?\\d+";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnAlphabeticString ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "[[:alpha:]]+";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnQuotedString ()
{
	CString strFind;

	m_EditFindText.GetWindowText (strFind);
	strFind += "\"([^\"\\\\]|\\\\.)*\"";
	m_EditFindText.SetWindowText (strFind);
}

void CFindReplaceDlg::OnCheckWholeWord ()
{
	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eWholeWordOnly,
		m_CheckWholeWordOnly.GetCheck ());
}

void CFindReplaceDlg::OnCheckMatchCase ()
{
	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eMatchCase,
		m_CheckMatchCase.GetCheck ());
}

void CFindReplaceDlg::OnCheckRegex ()
{
	const bool bRegEx = m_CheckRegEx.GetCheck () != 0;

	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eRegEx, bRegEx);

	if (bRegEx)
	{
		m_CheckWholeWordOnly.SetCheck (FALSE);
		OnCheckWholeWord ();
	}

	if (m_IDD == IDD_FIND)
	{
		if (bRegEx)
		{
			m_RadioUp.SetCheck (FALSE);
			m_RadioDown.SetCheck (TRUE);
			OnRadioDown ();
		}

		m_RadioUp.EnableWindow (!bRegEx);
	}
}

void CFindReplaceDlg::OnCheckLikeNotepad ()
{
	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eReplaceAllLikeNotepad,
		m_CheckReplaceAllLikeNotepad.GetCheck ());
}

void CFindReplaceDlg::OnRadioUp ()
{
	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eUp, 0);
}

void CFindReplaceDlg::OnRadioDown ()
{
	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eDown, 0);
}

void CFindReplaceDlg::OnCheckCloseOnMatch ()
{
	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eCloseOnMatch,
		m_CheckCloseOnMatch.GetCheck ());
}

void CFindReplaceDlg::OnOk ()
{
	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eFind,
		reinterpret_cast<LPARAM> (this));
}

void CFindReplaceDlg::OnButtonReplace ()
{
	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eReplace,
		reinterpret_cast<LPARAM> (this));
}

void CFindReplaceDlg::OnButtonReplaceAll ()
{
	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eReplaceAll,
		reinterpret_cast<LPARAM> (this));
}

void CFindReplaceDlg::OnCancel ()
{
	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eClose, 0);
}

void CFindReplaceDlg::OnButtonHelp ()
{
	m_pParentWnd->PostMessage (WM_NOTIFY_FIND_REPLACE, eHelp, 0);
}

By viewing downloads associated with this article you agree to the Terms of Service and the article's licence.

If a file you wish to view isn't highlighted, and is a text file (not binary), please let us know and we'll add colourisation support for it.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United Kingdom United Kingdom
I started programming in 1983 using Sinclair BASIC, then moved on to Z80 machine code and assembler. In 1988 I programmed 68000 assembler on the ATARI ST and it was 1990 when I started my degree in Computing Systems where I learnt Pascal, C and C++ as well as various academic programming languages (ML, LISP etc.)

I have been developing commercial software for Windows using C++ since 1994.

Comments and Discussions