#include "stdafx.h"
#include "resource.h"
#include "SearchInterface.h"
#include "FileFindRecursive.h"
#include "SBDestination.h"
#include "DlgRegDefinitions.h"
#include <afxpriv.h>
CSearchBar::CSearchBar()
:m_bCanceled(true),m_bQuit(false)
{
}
void CSearchBar::RegisterFileProcessor(CFileProcessor* pFileProcessor)
{
struct RegDefinition{
const char* pcszName;
const char* pcszExpr;
}regDefs[]={
{"$Blank", "[ \\t\\r\\n\\v]"},
{"$Beg", "[\\n]"},
{"$End", "\\r\\n"},
{"$Int", "[0-9]+"},
{"$Frac", "\\.[0-9]+"},
{"$Exp", "[Ee](\\+|-)?[0-9]+"},
{"$CIdent", "[A-Za-z_][A-Za-z_0-9]+"},
{"$String", "\"([^\"\\\\]|\\\\.)*\""},
{"$CComment", "/\\*([^*]|\\*/)*\\*/"},
{"$CPComment", "//[^\\n]*\\n"},
{"$Hex", "[0-9A-Fa-f]"},
{"$Hex4", "[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]"},
{"$Hex8", "$Hex4 $Hex4"},
{"$Hex12", "$Hex8 $Hex4"}
};
for(int i=0;i<sizeof(regDefs)/sizeof(RegDefinition);i++){
pFileProcessor->AddRegDefinition(regDefs[i].pcszName,regDefs[i].pcszExpr);
m_vecDefs.push_back( make_pair(regDefs[i].pcszName,regDefs[i].pcszExpr));
}
m_vecFileProcessors.push_back(pFileProcessor);
}
IMPLEMENT_DYNCREATE(CSearchBar, CDialogBar)
BEGIN_MESSAGE_MAP(CSearchBar, CDialogBar)
//{{AFX_MSG_MAP(CSearchBar)
ON_UPDATE_COMMAND_UI(ID_SEARCH, OnUpdateSearch)
ON_UPDATE_COMMAND_UI(IDC_BUTTON_DIRBROWSE,OnUpdateButtonDirBrowse)
ON_UPDATE_COMMAND_UI(IDC_BUTTON_DEF,OnUpdateButtonDef)
ON_BN_CLICKED(IDC_BUTTON_DIRBROWSE, OnButtonDirBrowse)
ON_BN_CLICKED(IDC_BUTTON_REGHELP, OnButtonReghelp)
ON_UPDATE_COMMAND_UI(IDC_BUTTON_REGHELP,OnUpdateButtonReghelp)
ON_BN_CLICKED(ID_SEARCH, OnSearch)
ON_BN_CLICKED(IDC_BUTTON_DEF, OnButtonDef)
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
void CSearchBar::DoDataExchange(CDataExchange* pDX)
{
DDX_Control(pDX,IDC_COMBO_WHAT,m_cmbSearch);
DDX_Control(pDX,IDC_COMBO_DIRECTORY,m_cmbDir);
DDX_Control(pDX,IDC_COMBO_TYP,m_cmbWildCards);
DDX_Control(pDX,ID_SEARCH,m_btnSearch);
DDX_Control(pDX,IDC_BUTTON_DIRBROWSE,m_btnDirBrowse);
DDX_Control(pDX,IDC_PROGRESS,m_progress);
DDX_Control(pDX,IDC_STATIC_COMMENT,m_static);
}
void CSearchBar::ShowDialog()
{
CFrameWnd* pMain= (CFrameWnd*)AfxGetMainWnd();
if( pMain ){
if(!IsWindow(m_hWnd)){
if( Create(pMain,IDD_DLG_SEARCHBAR,CBRS_BOTTOM|CBRS_TOOLTIPS|CBRS_FLYBY,AFX_IDW_CONTROLBAR_FIRST+32) ){
UpdateData(false);
EnableDocking(CBRS_ALIGN_TOP|CBRS_ALIGN_BOTTOM);
pMain->DockControlBar(this,AFX_IDW_DOCKBAR_TOP);
m_cmbWildCards.SetCurSel(0);
m_cmbSearch.SetCurSel(0);
m_progress.ShowWindow(SW_HIDE);
}
}
}
}
void CSearchBar::OnUpdateSearch(CCmdUI* pCmdUI)
{
pCmdUI->Enable( CheckSearchEnableThis(m_cmbSearch)
&& CheckSearchEnableThis(m_cmbWildCards)
&& CheckSearchEnableThis(m_cmbDir));
}
void CSearchBar::OnUpdateButtonDef(CCmdUI* pCmdUI)
{
pCmdUI->Enable(true);
}
BOOL CSearchBar::PumpMessage()
{
MSG msgCur;
if (!::GetMessage(&msgCur, NULL, NULL, NULL))
{
return FALSE;
}
if (msgCur.message != WM_KICKIDLE && !AfxGetApp()->PreTranslateMessage(&msgCur))
{
::TranslateMessage(&msgCur);
::DispatchMessage(&msgCur);
}
return TRUE;
}
void CSearchBar::DoMessageLoop()
{
bool bDoingBackgroundProcessing= true;
int nOfLoops=0;
while ( bDoingBackgroundProcessing && ++nOfLoops< 2)
{
MSG msg;
while ( ::PeekMessage( &msg, NULL, 0, 0, PM_NOREMOVE ) )
{
if ( !PumpMessage( ) )
{
bDoingBackgroundProcessing = FALSE;
::PostQuitMessage(0);
m_bQuit= true;
break;
}
}
// let MFC do its idle processing
LONG lIdle = 0;
while ( AfxGetApp()->OnIdle(lIdle++ ) )
;
}
}
bool CSearchBar::FindInThisFile(const char* pcszPathName,const char* pcszFileName,void* pThis)
{
CSearchResult result;
CSearchBar* pSB= ((CSearchBar*)pThis);
pSB->DoMessageLoop();
if( pSB->m_bCanceled ){
return false;
}
pSB->m_progress.StepIt();
pSB->NotifyProcessors(pcszPathName,pcszFileName,result);
pSB->NotifyPresenters(result);
pSB->m_nOccurences+= result.vecSearchInfo.size();
if(pSB->m_nOccurences>=2000){
AfxMessageBox(_T("Too many matches!"));
pSB->m_bCanceled= true;
return false;
}
return true;
}
bool CSearchBar::SetRegexp(CString strRegexp)
{
for(int i=0;i<m_vecFileProcessors.size();i++){
REXI_DefErr defErr= m_vecFileProcessors[i]->SetRegExpression((LPCSTR)strRegexp);
if( defErr.eErrCode!=REXI_DefErr::eNoErr ){
CString strFormat;
if( defErr.nErrOffset < 0 || defErr.nErrOffset >= strRegexp.GetLength() ){
defErr.nErrOffset= strRegexp.GetLength()-1;
}
strFormat.Format("%s; at '%s'",defErr.strErrMsg.c_str(),
(LPCSTR)strRegexp.Left(defErr.nErrOffset+1));
AfxMessageBox(strFormat);
return false;
}
}
return true;
}
void CSearchBar::OnCancelSearch()
{
if(!m_bCanceled){
m_bCanceled= true;
}
}
void CSearchBar::OnSearch()
{
if(!m_bCanceled){
m_bCanceled= true;
return;
}
CString strStartDirectory;
m_cmbDir.GetWindowText(strStartDirectory);
if( strStartDirectory.GetLength()>2&&strStartDirectory.Right(2)==_T(":\\") ){
strStartDirectory= strStartDirectory.Left(strStartDirectory.GetLength()-1);
}
CFileFind findFile;
if( !findFile.FindFile(strStartDirectory+"\\*.*") ){
CString strMsg;
strMsg.LoadString(IDS_FOLDER_NOTEXISTS);
CString str;
str.Format(IDS_FOLDER_NOTEXISTS,strStartDirectory);
AfxMessageBox(str);
m_cmbDir.SetFocus();
return;
}
CString strWithComment;
CString str;
m_cmbSearch.GetWindowText(strWithComment);
str= strWithComment;
int nInd= -1;
int nPos= -1;
while( (nInd=str.Find("//<",nPos+1))!=-1 ){
nPos= nInd;
}
if(nPos!=-1){
str= str.Left(nPos);
}
if(!SetRegexp(str)){
return;
}
InsertIntoCmbList(m_cmbSearch,strWithComment);
m_nPieceNo=0;
m_nOccurences=0;
for(int i=0;i<m_vecSearchPresenters.size();i++){
m_vecSearchPresenters[i]->Init();
}
m_bCanceled= false;
m_btnSearch.SetWindowText(_T("Cancel"));
m_progress.ShowWindow(SW_SHOW);
m_progress.SetRange(0,1000);
m_progress.SetPos(0);
m_static.ShowWindow(SW_HIDE);
CString strWildCards;
m_cmbWildCards.GetWindowText(strWildCards);
CFileFindRecursive oFind(strStartDirectory,strWildCards,FindInThisFile,this);
if( m_bQuit ){
m_bCanceled= true;
return;
}
m_progress.ShowWindow(SW_HIDE);
m_btnSearch.SetWindowText(_T("&Find"));
CString strComment;
strComment.Format(_T("%d Occurrence(s) have been found"),m_nOccurences);
m_static.SetWindowText(strComment);
m_static.ShowWindow(SW_SHOW);
m_bCanceled= true;
}
void CSearchBar::NotifyProcessors(const char* pcszPathName,
const char* pcszFileName,CSearchResult& result)
{
for(int i=0;i<m_vecFileProcessors.size();i++){
m_vecFileProcessors[i]->ProcessFile(result,pcszPathName,pcszFileName,true,true);
}
}
void CSearchBar::NotifyPresenters(const CSearchResult& result)
{
for(int i=0;i<m_vecSearchPresenters.size();i++){
m_vecSearchPresenters[i]->PresentSearch(result,m_nPieceNo++);
}
}
void CSearchBar::OnUpdateButtonDirBrowse(CCmdUI* pCmdUI)
{
pCmdUI->Enable(true);
}
void CSearchBar::OnUpdateCancel(CCmdUI* pCmdUI)
{
pCmdUI->Enable(true);
}
void CSearchBar::InsertIntoCmbList(CComboBox& rCmb,CString strToInsert)
{
int nInd;
if( (nInd=rCmb.FindStringExact(-1,strToInsert))==-1 ){
rCmb.AddString(strToInsert);
nInd= rCmb.GetCount()-1;
}
rCmb.SetCurSel(nInd);
}
void CSearchBar::OnButtonDirBrowse()
{
CSBDestination sb(this->m_hWnd, IDS_BFF_TITLE);
sb.SetFlags(BIF_RETURNONLYFSDIRS | BIF_STATUSTEXT);
CString str;
m_cmbDir.GetWindowText(str);
sb.SetInitialSelection(str);
if (sb.SelectFolder())
{
InsertIntoCmbList(m_cmbDir,sb.GetSelectedFolder());
}
}
void CSearchBar::OnUpdateButtonReghelp(CCmdUI* pCmdUI)
{
pCmdUI->Enable();
}
void CSearchBar::OnButtonReghelp()
{
CMenu menu;
menu.LoadMenu(IDR_MENU_REGCONTEXT);
CRect rect;
GetDlgItem(IDC_BUTTON_REGHELP)->GetWindowRect(&rect);
menu.GetSubMenu(0)->TrackPopupMenu(TPM_LEFTALIGN |TPM_RIGHTBUTTON, rect.TopLeft().x+rect.Width(),
rect.TopLeft().y, AfxGetMainWnd());
}
bool CSearchBar::CheckSearchEnableThis(CWnd& rWnd)
{
CString str;
rWnd.GetWindowText(str);
str.TrimLeft();
str.TrimRight();
return !str.IsEmpty();
}
void CSearchBar::Resize(int cx,int cy)
{
const cnMargin= 40;
if( ::IsWindow(m_btnSearch.m_hWnd) ){
if( cx>0 && cy>0){
CRect rect;
m_cmbSearch.GetWindowRect(rect);
ScreenToClient(&rect);
m_cmbSearch.SetWindowPos(NULL,0,0, cx-cnMargin-rect.left,rect.Height(),
SWP_NOMOVE|SWP_NOZORDER);
m_cmbDir.SetWindowPos(NULL,0,0,cx-cnMargin-rect.left,rect.Height(),
SWP_NOMOVE|SWP_NOZORDER);
m_cmbWildCards.SetWindowPos(NULL,0,0,cx-cnMargin-rect.left,rect.Height(),
SWP_NOMOVE|SWP_NOZORDER);
m_progress.SetWindowPos(NULL,0,0,cx-(cnMargin+40)-rect.left,rect.Height()/2,
SWP_NOMOVE|SWP_NOZORDER);
m_btnDirBrowse.GetWindowRect(rect);
ScreenToClient(&rect);
m_btnDirBrowse.SetWindowPos(NULL,cx-cnMargin+5,rect.top,0,0,
SWP_NOSIZE|SWP_NOZORDER);
}
}
}
void CSearchBar::CmbContentSerialize(CComboBox& rCmb,CArchive& ar)
{
if( ar.IsStoring() ){
ar << rCmb.GetCurSel();
ar << rCmb.GetCount();
for(int i=0;i<rCmb.GetCount();i++){
CString str;
rCmb.GetLBText(i,str);
ar << str;
}
}else{
rCmb.ResetContent();
int nCount;
int nSel;
ar >> nSel;
ar >> nCount;
for(int i=0;i<nCount;i++){
CString str;
ar >> str;
rCmb.AddString(str);
}
rCmb.SetCurSel(nSel);
}
}
void CSearchBar::Serialize(CArchive& ar)
{
CmbContentSerialize(m_cmbSearch, ar);
CmbContentSerialize(m_cmbWildCards, ar);
CmbContentSerialize(m_cmbDir, ar);
}
void CSearchBar::OnButtonDef()
{
CDlgRegDefinitions dlgDefs(m_vecDefs);
if(dlgDefs.DoModal()==IDOK){
m_vecDefs= dlgDefs.m_vecDefs;
}
}