Click here to Skip to main content
15,888,579 members
Articles / Programming Languages / C++

GrepWrap -- A Windows Wrapper for GNU Grep

Rate me:
Please Sign up or sign in to vote.
4.78/5 (14 votes)
1 Mar 2010CPOL10 min read 72.8K   914   47  
A GUI wrapper for the GNU command-line tool, Grep, used to search folders of text/code files
// GrepWrapView.h : interface of the CGrepWrapView class
//
#pragma once
#include "afxcmn.h"
#include "Process.h"
#include "RichEditCtrlEx.h"
#include "RegExp.h"		/* regular expression stuff */
#include "afxcoll.h"

/// arcane program for opening a file with Visual Studio
extern bool visual_studio_open_file(char const *executable, char const *filename, unsigned int line);

class CGrepWrapView : public CFormView
{
//lint --e{1768}	Virtual function has an access different from the access in the base class
protected: // create from serialization only
	CGrepWrapView();
	DECLARE_DYNCREATE(CGrepWrapView)

public:
	enum{ IDD = IDD_GREPWRAP_FORM };

// Attributes
public:
	CGrepWrapDoc* GetDocument() const;

// Operations
public:

// Overrides
public:
	virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
protected:
	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
	virtual void OnInitialUpdate(); // called first time after construct

// Implementation
public:
	virtual ~CGrepWrapView();
#ifdef _DEBUG
	virtual void AssertValid() const;
	virtual void Dump(CDumpContext& dc) const;
#endif

protected:

// Generated message map functions
protected:
	afx_msg void OnRButtonUp(UINT nFlags, CPoint point);	// these 2 are used for handling context menu
	afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
	afx_msg void OnLButtonDown(UINT nFlags, CPoint point);	// used for drag and drop of file to another application
	DECLARE_MESSAGE_MAP()
public:
	afx_msg void OnBnClickedSelectFolderBtn();
	//afx_msg void OnBnClickedRecurseChk(); no longer used--recursion on always
	afx_msg void OnBnClickedCaselessChk();
	afx_msg void OnBnClickedInvertChk();
	afx_msg void OnBnClickedNoWordLineRadio();
	afx_msg void OnBnClickedWholeWordRadio();
	afx_msg void OnBnClickedWholeLineRadio();
	afx_msg void OnSize(UINT nType, int cx, int cy);
	afx_msg void OnBnClickedSearchBtn();

	// These are handlers for menus using the standard Edit commands. These can be invoked from
	// several menus, not just the main menu.
	afx_msg void OnEditCopy();
	afx_msg void OnEditPaste();
	afx_msg void OnEditUndo();
	afx_msg void OnEditCut();
	afx_msg void OnEditSelectAll();

	// These are the "enabler" handlers. Before a menu item is displayed, the OnUpdate* function is called
	// to determine if it is dimmed or normal display. If there is no such function, or if there is not a
	// handler (such as OnEditCopy()) then the item is dimmed.	
	afx_msg void OnUpdateEditSelectAll(CCmdUI *pCmdUI);
	afx_msg void OnUpdateEditCopy(CCmdUI *pCmdUI);
	afx_msg void OnUpdateEditPaste(CCmdUI *pCmdUI);
	afx_msg void OnUpdateEditUndo(CCmdUI *pCmdUI);
	afx_msg void OnUpdateEditCut(CCmdUI *pCmdUI);

	// These are handlers for menu items on the context menu used for lines within the richedit
	// control. See IDR_POPUP_MENU and OnRButtonUp() for more information.
	afx_msg void OnEditOpenSystemDefault();
	afx_msg void OnEditOpenXEmacs();
	afx_msg void OnEditOpenUltraEdit();
	afx_msg void OnEditOpenNotepad();
	afx_msg void OnEditOpenUsingCodeWright();

	afx_msg void OnUpdateEditOpenSystemDefault(CCmdUI *pCmdUI);
	afx_msg void OnUpdateEditOpenXEmacs(CCmdUI *pCmdUI);
	afx_msg void OnUpdateEditOpenUltraEdit(CCmdUI *pCmdUI);
	afx_msg void OnUpdateEditOpenNotepad(CCmdUI *pCmdUI);
	afx_msg void OnUpdateEditOpenUsingCodeWright(CCmdUI *pCmdUI);

	// See Help on "Handling TTN_NEEDTEXT Notification for Tool Tips"
	afx_msg BOOL OnTtnNeedText(UINT id, NMHDR *pNMHDR, LRESULT *pResult);

	/// Needed to maintain the hourglass cursor. See also m_BusyCursor
	afx_msg BOOL OnSetCursor(CWnd* pWnd, UINT nHitTest, UINT message);

	// these are used to handle output from grep process using User defined messages. See Process.cpp/h for more info.
	afx_msg LRESULT OnLine(WPARAM wParam, LPARAM lParam);
	afx_msg LRESULT OnFinished(WPARAM wParam, LPARAM lParam);
	
	/// This is the handler for a message from the richedit control when there is a left double-click
	afx_msg LRESULT OnRichEditLDblClick(WPARAM wParam, LPARAM lParam);	// wParam = nFlags, lParam = char index into richeditctl

	afx_msg void OnHelpRegularExpressionsWikipediaIntro();
	afx_msg void OnHelpRegularExpressionsWikipediaRegularExpressionExamples();
	afx_msg void OnHelpRegularExpressionsCheatsheet();

	afx_msg void OnUpdateHelpOnRegularExpressions(CCmdUI *pCmdUI);

	// Utility function to get filename, linenumber, full pathname to executable, and basename of executable
	// Returns true if everything OK, false otherwise (no file, no execName, etc.). Used by the OnUpdate* functions
	// for the context menu as well as the menu item handlers.
	bool m_GetExecParameters(CString & filename, int & linenum, CString & execName, CString & baseName, CString & fileBase);
	
	/// run ShellExec(). If cmdName is NULL, use the filename only.
	bool m_RunShellExec(const CString &filename, LPCTSTR cmdName = NULL, LPCTSTR params = NULL);

	CButton m_Search_Btn;			///< Perform the search (grep)
	//CButton m_Recurse_Check;		// This has gone away
	CButton m_Caseless_Check;		///< ignore case in the search
	CButton m_InvertMatch_Check;	///< respond with lines that do NOT match pattern

	const char *EmptyToken;		///< used to marked an empty value in the registry
	int m_WordLine_Radio;		///< Currently selected match extension, should be one of the IDC_*_RADIO values
	Process *m_GrepProcess;		///< Encapsulation of Grep program for line-by-line monitoring of output (and clean process abort)
	bool m_BusyCursor;			///< used by OnSetCursor() when running the grep process
	CString m_GrepFolderBase;	///< Unix-style base folder name (as issued from grep) with trailing '/' char
	int m_matchingLinesFound;	///< progress mark for statusbar to keep user happy
	int m_ResultsPosition;		///< Location (char and line offset) in m_Results_Ctl when Right Mouse button is released (or left double-clicked)

	// configurable pathnames for common programs to open a file. These show up in the context menu
	CString m_grepPath;
	CString m_xemacsPath;
	CString m_ultraeditPath;
	CString m_notepadPath;
	CString m_codewrightPath;

	// These need to be here so we don't have constant new/delete and crash the stack. Without these,
	// we apparently can overflow the stack after processing only a few hundred lines of grep output.
	// I suspect a COM problem, this is an easy enough solution.
	RegExp *m_dashRe;			///< used in OnLine() for parsing a response from grep
	RegExp *m_lineRe;			///< used in OnLine() for parsing a response from grep
	RegExp *m_colRe;			///< used in OnLine() for parsing a response from grep
	RegExp *m_pgmRe;			///< used to extract the basename from a full pathname

	CHARFORMAT2 m_DefaultCharFormat;	///< used to hold initial character format, just in case

	// Results of the grep.
	//
	// A call to AfxInitRichEdit2() must be in CMainFrame::OnCreate() or you get
	// an error message of "Failed to create empty document" when the program starts.
	CRichEditCtrlEx m_Results_Ctl;		// Display of results (with color-coded matches)
	CStringArray    m_Results_Strings;	// line-by-line contents of the results control for each parsing

	/// Name of the folder where the Grep will start (Windows Style)
	CComboBox m_Root_Folder;

	/// Pattern that grep uses for searching
	CComboBox m_Pattern;
	
	/// Select a folder for starting the grep search (can be invoked with the Browse button)
	bool GetFolderName(CString &selectedFolder, CString initialFolder, CString caption = "", HWND hOwner = NULL);

	/// Updates the list of entries in the registry. Intended for use with m_Pattern, m_Include_Files,
	/// and m_Exclude_Files. RegEntry is the String name in the Registry and title is the human
	/// friendly name of the combobox (Search Pattern, Exclude Files, ...);
	void SavePatterns(const char *RegEntry, CComboBox &cbox, const char *title);
	int  LoadPatterns(const char *RegEntry, CComboBox &cbox, const char *defValue = "<Empty>");	// returns number of patterns

	/// Windows file pattern for file patterns to search (*.h;*.c;*.cpp for example)
	CComboBox m_Include_Files;

	/// Windows file pattern of files to exclude from search (*.html;*.lnt for example)
	CComboBox m_Exclude_Files;

	/// Windows file pattern of directories to NOT recurse into (Debug, Release, etc.)
	CComboBox m_Exclude_Dirs;

	/// returns pointer to current Edit control, if any
	CEdit *GetFocusedEdit(void);

	/// returns pointer to current RichEdit control, if any	
	CRichEditCtrl *GetFocusedRichEdit(void);
	
	/// Get reference to application statusbar (for progress messages and the like)
	CMFCStatusBar & GetStatusBar(void);

	/// list of application templates ("pathname-to-program $n $f" where $n is linenumber, $f is filename)
	CStringArray m_AppArray;
public:
	afx_msg void OnProgramsSetGrepLocation();
	afx_msg void OnUpdateProgramsSetGrepLocation(CCmdUI *pCmdUI);

	/// If set, display the grep command line at the top of the search window
	BOOL m_ShowCommand;
	afx_msg void OnViewDisplayGrepCommandLine(void);
	afx_msg void OnUpdateViewDisplayGrepCommandLine(CCmdUI *pCmdUI);
};

#ifndef _DEBUG  // debug version in GrepWrapView.cpp
//lint -e{1763}		Member function marked as const indirectly modifies class
inline CGrepWrapDoc* CGrepWrapView::GetDocument() const
   { return reinterpret_cast<CGrepWrapDoc*>(m_pDocument); }
#endif

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) Thales Visionix
United States United States
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions