初步修复
This commit is contained in:
parent
8fc4357cc6
commit
e4714f3f0e
46705 changed files with 12004901 additions and 0 deletions
440
Third/XTToolkitPro/Samples/Utilities/Grep/SearchThread.cpp
Normal file
440
Third/XTToolkitPro/Samples/Utilities/Grep/SearchThread.cpp
Normal file
|
|
@ -0,0 +1,440 @@
|
|||
// SearchThread.cpp : implementation file
|
||||
//
|
||||
|
||||
#include "stdafx.h"
|
||||
#include "grep.h"
|
||||
#include "SearchThread.h"
|
||||
#include "SearchOptions.h"
|
||||
#include "MainFrm.h"
|
||||
#include "GrepView.h"
|
||||
|
||||
|
||||
#ifdef _DEBUG
|
||||
#define new DEBUG_NEW
|
||||
#undef THIS_FILE
|
||||
static char THIS_FILE[] = __FILE__;
|
||||
#endif
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CSearchThread
|
||||
|
||||
IMPLEMENT_DYNCREATE(CSearchThread, CWinThread)
|
||||
|
||||
|
||||
long GetLineNumber(TCHAR* lpszFileBuffer, int nIndex)
|
||||
{
|
||||
long nLine = 1;
|
||||
while (nIndex--)
|
||||
{
|
||||
if (*lpszFileBuffer == _T('\n')) nLine++;
|
||||
lpszFileBuffer++;
|
||||
}
|
||||
|
||||
return nLine;
|
||||
}
|
||||
|
||||
void CSearchThread::AddRecord(CXTPReportControl& wndControl, TCHAR* lpszFileBuffer, TCHAR* lpszEndBuffer, long nIndex, long nLength,
|
||||
CString strMatch, CString strReplace, CString strPath, CFileFind& finder)
|
||||
{
|
||||
USES_CONVERSION;
|
||||
|
||||
TCHAR* lpszMatch = lpszFileBuffer + nIndex;
|
||||
TCHAR* lpszMatchBeginLine = lpszMatch;
|
||||
TCHAR* lpszMatchEndLine = lpszMatchBeginLine + nLength;
|
||||
|
||||
int nMaxPreview = 80;
|
||||
|
||||
while (nMaxPreview-- && lpszMatchBeginLine != lpszFileBuffer && *(lpszMatchBeginLine - 1) != '\n')
|
||||
lpszMatchBeginLine--;
|
||||
|
||||
if (*lpszMatchEndLine != '\n')
|
||||
{
|
||||
nMaxPreview = 80;
|
||||
|
||||
while (nMaxPreview-- && lpszMatchEndLine != lpszEndBuffer && *(lpszMatchEndLine + 1) != '\n' )
|
||||
lpszMatchEndLine++;
|
||||
}
|
||||
TCHAR tchEndLine = *lpszMatchEndLine;
|
||||
*lpszMatchEndLine = '\0';
|
||||
|
||||
|
||||
CString strBeginLine;
|
||||
long nBeginLineLength = long(lpszMatch - lpszMatchBeginLine);
|
||||
STRNCPY_S(strBeginLine.GetBufferSetLength(nBeginLineLength), nBeginLineLength + 1, lpszMatchBeginLine, nBeginLineLength);
|
||||
|
||||
|
||||
CString strEndLine;
|
||||
long nEndLineLength = long(lpszMatchEndLine - lpszMatch - nLength);
|
||||
STRNCPY_S(strEndLine.GetBufferSetLength(nEndLineLength), nEndLineLength + 1, lpszMatch + nLength, nEndLineLength);
|
||||
|
||||
wndControl.AddRecord(new CGrepRecord
|
||||
(finder.GetFilePath(), strPath, finder.GetFileName(), strMatch,
|
||||
GetLineNumber(lpszFileBuffer, nIndex),
|
||||
strBeginLine + strMatch + strEndLine,
|
||||
strBeginLine + strReplace + strEndLine, nIndex, nLength, strReplace));
|
||||
|
||||
*lpszMatchEndLine = tchEndLine;
|
||||
|
||||
m_searchResult.nMatchingLines++;
|
||||
}
|
||||
|
||||
void CSearchThread::SetMessageText()
|
||||
{
|
||||
CString strMessage;
|
||||
strMessage.Format(_T("Matching lines: %i Matching files: %i Total files searched: %i"),
|
||||
m_searchResult.nMatchingLines, m_searchResult.nMatchingFiles, m_searchResult.nTotalFiles);
|
||||
|
||||
m_pMainFrame->SetMessageText(strMessage);
|
||||
m_pMainFrame->DelayPopulate();
|
||||
}
|
||||
|
||||
#ifdef _UNICODE
|
||||
#define CT2BSTR(x) (BSTR)(LPCWSTR)x
|
||||
#else
|
||||
#define CT2BSTR(x) (BSTR)A2CW(x)
|
||||
#endif
|
||||
|
||||
int FindNext(const CString& str, const CString& strFind, int nIndex, CSearchOptions* pOptions)
|
||||
{
|
||||
nIndex = FIND_S(str, strFind, nIndex);
|
||||
|
||||
if (!pOptions->m_bMatchWholeWords)
|
||||
return nIndex;
|
||||
|
||||
static LPCTSTR szSeps = _T("() \t<>{}:;,.=%\"'!@#$^&*-\\|[]/?\r\n");
|
||||
|
||||
|
||||
while (nIndex != -1)
|
||||
{
|
||||
|
||||
BOOL bSepAfter = FALSE;
|
||||
BOOL bSepBefore = FALSE;
|
||||
|
||||
if (nIndex + strFind.GetLength() >= str.GetLength())
|
||||
bSepAfter = TRUE;
|
||||
else
|
||||
bSepAfter = (_tcschr(szSeps, str[nIndex + strFind.GetLength()]) != 0);
|
||||
|
||||
if (nIndex == 0)
|
||||
bSepBefore = TRUE;
|
||||
else
|
||||
bSepBefore = (_tcschr(szSeps, str[nIndex - 1]) != 0);
|
||||
|
||||
if (bSepAfter && bSepBefore)
|
||||
return nIndex;
|
||||
|
||||
nIndex = FIND_S(str, strFind, nIndex + 1);
|
||||
|
||||
}
|
||||
return nIndex;
|
||||
}
|
||||
|
||||
BOOL CSearchThread::ProcessFile(CString strPath, CFileFind& finder)
|
||||
{
|
||||
USES_CONVERSION;
|
||||
|
||||
if (!m_pReportControl)
|
||||
return FALSE;
|
||||
|
||||
CSearchOptions* pOptions = GetSearchOptions();
|
||||
ASSERT(pOptions);
|
||||
|
||||
CFile file;
|
||||
if (!file.Open(finder.GetFilePath(), CFile::modeRead))
|
||||
return TRUE;
|
||||
|
||||
DWORD dwCount = (DWORD)file.GetLength();
|
||||
|
||||
char* pchData = new char[dwCount + 1];
|
||||
file.Read(pchData, dwCount);
|
||||
pchData[dwCount] = 0;
|
||||
|
||||
#ifdef _UNICODE
|
||||
TCHAR* lpszFileBuffer = new TCHAR[dwCount + 1];
|
||||
_mbstowcsz(lpszFileBuffer, pchData, dwCount+1);
|
||||
#else
|
||||
char* lpszFileBuffer = pchData;
|
||||
#endif
|
||||
|
||||
|
||||
file.Close();
|
||||
TCHAR* lpszEndBuffer = lpszFileBuffer + dwCount;
|
||||
|
||||
|
||||
BOOL bContinue = TRUE;
|
||||
|
||||
|
||||
if (!pOptions->pRegExp)
|
||||
{
|
||||
CString str(lpszFileBuffer);
|
||||
CString strFind = pOptions->m_strFind;
|
||||
|
||||
if (!pOptions->m_bMatchCase)
|
||||
{
|
||||
str.MakeLower();
|
||||
strFind.MakeLower();
|
||||
}
|
||||
|
||||
int nLength = strFind.GetLength();
|
||||
int nIndex = FindNext(str, strFind, 0, pOptions);
|
||||
|
||||
if (nIndex != -1)
|
||||
{
|
||||
m_searchResult.nMatchingFiles++;
|
||||
}
|
||||
|
||||
while (nIndex != -1)
|
||||
{
|
||||
CString strMatch;
|
||||
STRNCPY_S(strMatch.GetBufferSetLength(nLength), nLength + 1, lpszFileBuffer + nIndex, nLength);
|
||||
|
||||
if (m_bCancel)
|
||||
{
|
||||
bContinue = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
CString strReplace = pOptions->m_strReplace;
|
||||
AddRecord(*m_pReportControl, lpszFileBuffer, lpszEndBuffer, nIndex, nLength,
|
||||
strMatch, strReplace, strPath, finder);
|
||||
|
||||
nIndex = FindNext(str, strFind, nIndex + 1, pOptions);
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
try
|
||||
{
|
||||
#ifndef _UNICODE
|
||||
BSTR bstrBuffer = new WCHAR[dwCount + 1];
|
||||
_mbstowcsz(bstrBuffer, lpszFileBuffer, dwCount+1);
|
||||
#else
|
||||
BSTR bstrBuffer = (BSTR)lpszFileBuffer;
|
||||
#endif
|
||||
IMatchCollectionPtr MatchesPtr = pOptions->pRegExp->Execute(bstrBuffer);
|
||||
|
||||
int nCount = MatchesPtr.GetInterfacePtr()? MatchesPtr->Count: 0;
|
||||
|
||||
if (nCount > 0)
|
||||
{
|
||||
m_searchResult.nMatchingFiles++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nCount; i++)
|
||||
{
|
||||
IMatchPtr MatchPtr = MatchesPtr->Item[i];
|
||||
|
||||
int nIndex = MatchPtr->FirstIndex;
|
||||
int nLength =MatchPtr->Length;
|
||||
|
||||
CString strMatch;
|
||||
STRNCPY_S(strMatch.GetBufferSetLength(nLength), nLength + 1, lpszFileBuffer + nIndex, nLength);
|
||||
|
||||
_bstr_t bstrResult =pOptions->pRegExp->Replace(CT2BSTR(strMatch), CT2BSTR(pOptions->m_strReplace));
|
||||
CString strReplace = (LPCWSTR)bstrResult;
|
||||
|
||||
if (m_bCancel)
|
||||
{
|
||||
bContinue = FALSE;
|
||||
break;
|
||||
}
|
||||
|
||||
AddRecord(*m_pReportControl, lpszFileBuffer, lpszEndBuffer, nIndex, nLength,
|
||||
strMatch, strReplace, strPath, finder);
|
||||
|
||||
}
|
||||
#ifndef _UNICODE
|
||||
delete[] bstrBuffer;
|
||||
#endif
|
||||
|
||||
}
|
||||
catch (_com_error& e)
|
||||
{
|
||||
CString strDescription(BSTR(e.Description()));
|
||||
if (strDescription.IsEmpty())
|
||||
strDescription = _T("Error in regular expression.");
|
||||
strDescription += " Continue?";
|
||||
|
||||
bContinue = AfxMessageBox(strDescription, MB_YESNO) == IDNO? FALSE: TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
delete[] lpszFileBuffer;
|
||||
|
||||
#ifdef _UNICODE
|
||||
delete[] pchData;
|
||||
#endif
|
||||
|
||||
if (bContinue)
|
||||
{
|
||||
SetMessageText();
|
||||
}
|
||||
|
||||
return bContinue;
|
||||
|
||||
}
|
||||
|
||||
BOOL MatchFileType(CString strFileName, CString strMask)
|
||||
{
|
||||
if (strMask == _T("*.*"))
|
||||
return TRUE;
|
||||
|
||||
strMask.MakeLower();
|
||||
strFileName.MakeLower();
|
||||
|
||||
strFileName += _T(";");
|
||||
strMask += _T(";");
|
||||
|
||||
CString str = strMask;
|
||||
while (str != _T(";") && str != _T(""))
|
||||
{
|
||||
int nIndex = str.Find(_T(';'));
|
||||
if (nIndex != -1)
|
||||
{
|
||||
strMask = str.Mid(nIndex + 1);
|
||||
str = str.Left(nIndex + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
strMask.Empty();
|
||||
}
|
||||
|
||||
REPLACE_S(str, _T("*;"), _T(""));
|
||||
REPLACE_S(str, _T(";*"), _T(""));
|
||||
REPLACE_S(str, _T("*"), _T(""));
|
||||
|
||||
if (strFileName.Find(str) >= 0)
|
||||
return TRUE;
|
||||
|
||||
str = strMask;
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
|
||||
BOOL CSearchThread::ProcessPath(CString strPath)
|
||||
{
|
||||
CFileFind finder;
|
||||
|
||||
CString strWildcard = strPath + _T("\\*.*") ;
|
||||
|
||||
// start working for files
|
||||
BOOL bWorking = finder.FindFile(strWildcard);
|
||||
|
||||
while (bWorking)
|
||||
{
|
||||
bWorking = finder.FindNextFile();
|
||||
|
||||
// skip . and .. files; otherwise, we'd
|
||||
// recur infinitely!
|
||||
|
||||
if (finder.IsDots())
|
||||
continue;
|
||||
|
||||
// if it's a directory, recursively search it
|
||||
|
||||
if (finder.IsDirectory())
|
||||
{
|
||||
if (GetSearchOptions()->m_bIncludeSubFolders)
|
||||
{
|
||||
if (GetSearchOptions()->m_bFindInHiddenFiles || !finder.IsHidden())
|
||||
{
|
||||
if (!ProcessPath(finder.GetFilePath()))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (MatchFileType(finder.GetFileName(), GetSearchOptions()->m_strFileTypes))
|
||||
{
|
||||
if (GetSearchOptions()->m_bFindInHiddenFiles || !finder.IsHidden())
|
||||
{
|
||||
m_searchResult.nTotalFiles++;
|
||||
|
||||
if (!ProcessFile(strPath, finder))
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_bCancel)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
finder.Close();
|
||||
|
||||
return TRUE;
|
||||
|
||||
}
|
||||
|
||||
CSearchThread::CSearchThread()
|
||||
{
|
||||
m_pMainFrame = NULL;
|
||||
m_pReportControl = NULL;
|
||||
m_bAutoDelete = TRUE;
|
||||
m_bCancel = FALSE;
|
||||
|
||||
ZeroMemory(&m_searchResult, sizeof(SEARCH_RESULT));
|
||||
}
|
||||
|
||||
CSearchThread::~CSearchThread()
|
||||
{
|
||||
}
|
||||
|
||||
BOOL CSearchThread::InitInstance()
|
||||
{
|
||||
USES_CONVERSION;
|
||||
|
||||
AfxOleInit();
|
||||
|
||||
IRegExpPtr regExp;
|
||||
|
||||
CSearchOptions* pOptions = GetSearchOptions();
|
||||
ASSERT(pOptions);
|
||||
|
||||
|
||||
if (pOptions->m_bRegularExpressions)
|
||||
{
|
||||
HRESULT hr = regExp.CreateInstance(__uuidof(RegExp));
|
||||
|
||||
if (FAILED(hr))
|
||||
{
|
||||
AfxMessageBox(_T("RegExp not found"));
|
||||
}
|
||||
else
|
||||
{
|
||||
pOptions->pRegExp = regExp;
|
||||
regExp->Global = VARIANT_TRUE;
|
||||
regExp->IgnoreCase = pOptions->m_bMatchCase? VARIANT_FALSE: VARIANT_TRUE;
|
||||
regExp->Pattern = _bstr_t(CT2BSTR(pOptions->m_strFind));
|
||||
}
|
||||
}
|
||||
|
||||
ProcessPath(pOptions->m_strPath);
|
||||
|
||||
pOptions->pRegExp = 0;
|
||||
|
||||
// TODO: perform and per-thread initialization here
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
int CSearchThread::ExitInstance()
|
||||
{
|
||||
m_pMainFrame->PostMessage(WM_SEARCHFINISHED);
|
||||
|
||||
// TODO: perform any per-thread cleanup here
|
||||
return CWinThread::ExitInstance();
|
||||
}
|
||||
|
||||
BEGIN_MESSAGE_MAP(CSearchThread, CWinThread)
|
||||
//{{AFX_MSG_MAP(CSearchThread)
|
||||
// NOTE - the ClassWizard will add and remove mapping macros here.
|
||||
//}}AFX_MSG_MAP
|
||||
END_MESSAGE_MAP()
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// CSearchThread message handlers
|
||||
Loading…
Add table
Add a link
Reference in a new issue