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

Include File Hierarchy Viewer

Rate me:
Please Sign up or sign in to vote.
4.84/5 (108 votes)
29 Jul 2003CPOL8 min read 383K   4.5K   151  
A tool to view the include file hierarchy of your source code.
//====================================================================
// Although great care has gone into developing this software,
// it is provided without any guarantee of reliability, accuracy
// of information, or correctness of operation.  I am not responsible
// for any damages that may occur as a result of using this software.
// Use this software entirely at your own risk.
// Copyright 2003, Chris Richardson
//
// Description: Directory search options page.
//
//====================================================================

#include "stdafx.h"
#include "incfinder.h"
#include "DirectorySearchPage.h"

#include "Settings.h"

#include "FileIterator.h"
#include "Parser.h"

#include "DSObjects.h"

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

/////////////////////////////////////////////////////////////////////////////
// CDirectoryFileIterator Implementation.
/////////////////////////////////////////////////////////////////////////////

class CDirectoryFileIterator : public CFileIterator
{
public:
   CDirectoryFileIterator();
   virtual ~CDirectoryFileIterator();

   void                 ParseOptions( const TCHAR * p_pszDirectories,
                                      const TCHAR * p_pszFileMasks,
                                      const TCHAR * p_pszIncludeDirs,
                                      BOOL          p_bRecurseSubDirectories );

   virtual void         Prepare( HANDLE p_hEvent,
                                 CParser * p_poParser );
   virtual bool         GetNextFile( CTCharString & p_rsFile );

protected:
   CStdStringArray      c_oSearchDirectories;
   CStdStringArray      c_oFileMasks;
   CDSParsedSettings    c_oSettings;
   BOOL                 c_bRecurseSubDirectories;
   
   int                  c_iCurrentDirectory;
   int                  c_iCurrentMask;
   bool                 c_bFoundLastFile;

   CStdStringArray      c_oFullDirectoryList;
   
   CFileFind            c_oFileFind;

   void                 GetDirectoryList( const TCHAR * p_pszDir, CStdStringArray & p_roDirs );
};

CDirectoryFileIterator::CDirectoryFileIterator() :
   c_bRecurseSubDirectories( FALSE ),
   c_iCurrentDirectory( -1 ),
   c_iCurrentMask( 0 ),
   c_bFoundLastFile( true )
{
}
//
// ------------------------------------------------------------------
//
CDirectoryFileIterator::~CDirectoryFileIterator()
{
}
//
// ------------------------------------------------------------------
//
void CDirectoryFileIterator::ParseOptions( const TCHAR * p_pszDirectories,
                                           const TCHAR * p_pszFileMasks,
                                           const TCHAR * p_pszIncludeDirs,
                                           BOOL          p_bRecurseSubDirectories )
{
   c_bRecurseSubDirectories = p_bRecurseSubDirectories;

   c_iCurrentDirectory = -1;
   c_iCurrentMask = 0;
   c_bFoundLastFile = false;

   c_oSearchDirectories.clear();
   c_oSettings.Clear();
   c_oFileMasks.clear();

   // Parse the directories into a list.
   ParseSeparatedList( p_pszDirectories, _T(";"), c_oSearchDirectories );

   // Parse file masks into a list..
   ParseSeparatedList( p_pszFileMasks, _T(";"), c_oFileMasks );
   
   // Parse include dirs into a temporary list.
   CStdStringArray a_oTempIncludeDirs;
   ParseSeparatedList( p_pszIncludeDirs, _T(";"), a_oTempIncludeDirs );
   
   CStdStringArray & a_roIncludeDirs = c_oSettings.GetIncludes();
   // Expand include directory environment strings.
   for( int dir = 0; dir<a_oTempIncludeDirs.size(); ++dir )
   {
      CTCharString a_sTemp = a_oTempIncludeDirs[dir];
      if( a_sTemp[0] == _T('%') )
      {
         // Remove the '%'.
         a_sTemp.erase( a_sTemp.begin() );
         
         // Get the number of chars required to store the environment variable.
         DWORD a_dwChars = GetEnvironmentVariable( a_sTemp.c_str(), NULL, 0 );
         if( a_dwChars != 0 )
         {
            // Lookup the environment variable.
            TCHAR * a_pszTemp = new TCHAR[a_dwChars + 1];
            memset( a_pszTemp, 0, sizeof( TCHAR ) * (a_dwChars + 1) );
            GetEnvironmentVariable( a_sTemp.c_str(), a_pszTemp, a_dwChars );
            
            // Parse the environment variable into an array of strings.
            CStdStringArray a_oExpandedDirectories;
            ParseSeparatedList( a_pszTemp, _T(";"), a_oExpandedDirectories );
            
            // Insert the directories of the environment variable into the include directory list.
            a_roIncludeDirs.insert( a_roIncludeDirs.end(), a_oExpandedDirectories.begin(), a_oExpandedDirectories.end() );

            delete [] a_pszTemp;
         }
      }
      else
         // It's not an environment string, just insert it as a regular path.
         a_roIncludeDirs.push_back( a_sTemp );
   }
}
//
// ------------------------------------------------------------------
//
void CDirectoryFileIterator::GetDirectoryList( const TCHAR * p_pszDir, CStdStringArray & p_roDirs )
{
   TCHAR a_szDirectory[MAX_PATH + 1] = {0};
   _tcscpy( a_szDirectory, p_pszDir );
   int a_iLen = _tcslen( a_szDirectory );
   if( a_szDirectory[a_iLen] != _T('\\') && a_szDirectory[a_iLen] != _T('/') )
      _tcscat( a_szDirectory, _T("\\") );
   
   // This doesn't quite get the job done.  It doesn't find directories with dashes or dots in their name.
   // How to fix without having to iterate all the files in each directory as well?
   //_tcscat( a_szDirectory, _T("*..") );
   _tcscat( a_szDirectory, _T("*.*") );
   
   // Find all the subdirectories of p_pszDir.
   CStdStringArray a_oDirectories;
   CFileFind a_oFileFind;
   BOOL a_bStop = FALSE;
   if( a_oFileFind.FindFile( a_szDirectory ) )
   {
      while( 1 )
      {
         unsigned long a_ulResult = WaitForSingleObject( c_hStopEvent, 0 );
         if( a_ulResult != WAIT_TIMEOUT )
         {
            a_bStop = TRUE;
            break;
         }
         
         BOOL a_bBreak = !a_oFileFind.FindNextFile();
         //TRACE( _T("%s\n"), (LPCTSTR)a_oFileFind.GetFilePath() );
         if( a_oFileFind.IsDirectory() && !a_oFileFind.IsDots() )
            a_oDirectories.push_back( (LPCTSTR)a_oFileFind.GetFilePath() );

         if( a_bBreak )
            break;
      }
   }
   
   if( a_bStop )
      return;

   p_roDirs.insert( p_roDirs.end(), a_oDirectories.begin(), a_oDirectories.end() );

   for( int i = 0; i<a_oDirectories.size(); ++i )
   {
      // Recursively find more subdirectories.
      GetDirectoryList( a_oDirectories[i].c_str(), p_roDirs );
   }
}
//
// ------------------------------------------------------------------
//
void CDirectoryFileIterator::Prepare( HANDLE p_hEvent,
                                      CParser * p_poParser )
{
   CFileIterator::Prepare( p_hEvent, p_poParser );

   c_oFullDirectoryList.clear();   

   c_oFullDirectoryList.insert( c_oFullDirectoryList.end(), c_oSearchDirectories.begin(), c_oSearchDirectories.end() );

   if( c_bRecurseSubDirectories )
   {
      for( int dir = 0; dir<c_oSearchDirectories.size(); ++dir )
      {
         // Build a list of all the sub-directories.
         GetDirectoryList( c_oSearchDirectories[dir].c_str(), c_oFullDirectoryList );

         unsigned long a_ulResult = WaitForSingleObject( c_hStopEvent, 1 );
         if( a_ulResult != WAIT_TIMEOUT )
            break;
      }
   }
}
//
// ------------------------------------------------------------------
//
bool CDirectoryFileIterator::GetNextFile( CTCharString & p_rsFile )
{
   bool a_bStartFind = false;
   if( c_iCurrentDirectory == -1 )
   {
      a_bStartFind = TRUE;
      c_iCurrentDirectory = 0;
      c_bFoundLastFile = false;
   }

   while( 1 )
   {
      if( !a_bStartFind && !c_bFoundLastFile )
      {
         BOOL a_bResult = c_oFileFind.FindNextFile();
         if( !a_bResult )
         {
            c_iCurrentMask++;
            if( c_iCurrentMask >= c_oFileMasks.size() )
            {
               c_iCurrentMask = 0;
               c_iCurrentDirectory++;
            }
            
            a_bStartFind = TRUE;
            
            c_bFoundLastFile = true;
         }
         
         p_rsFile = c_oFileFind.GetFilePath();
         c_poParser->SetSettings( c_oSettings );
         return true;
      }

      if( c_iCurrentDirectory >= c_oFullDirectoryList.size() )
         return false;
   
      TCHAR a_szDirectory[MAX_PATH + 1] = {0};
      _tcscpy( a_szDirectory, c_oFullDirectoryList[c_iCurrentDirectory].c_str() );
      int a_iLen = _tcslen( a_szDirectory );
      if( a_szDirectory[a_iLen] != _T('\\') && a_szDirectory[a_iLen] != _T('/') )
         _tcscat( a_szDirectory, _T("\\") );
      
      CTCharString a_sMask = c_oFileMasks[c_iCurrentMask];
      
      // Build a file spec of the current directory plus the current file mask.
      TCHAR a_szFullSpec[MAX_PATH + 1] = {0};
      _stprintf( a_szFullSpec, _T("%s%s"), a_szDirectory, a_sMask.c_str() );
      
      if( c_oFileFind.FindFile( a_szFullSpec ) )
      {
         a_bStartFind = false;
         c_bFoundLastFile = false;
         continue;
      }
      else
      {
         c_iCurrentMask++;
         if( c_iCurrentMask == c_oFileMasks.size() )
         {
            c_iCurrentMask = 0;
            c_iCurrentDirectory++;
         }
      }
   }

   return false;
}
//
// ------------------------------------------------------------------
//

/////////////////////////////////////////////////////////////////////////////
// CDirectorySearchPage Implementation.
/////////////////////////////////////////////////////////////////////////////

IMPLEMENT_DYNCREATE(CDirectorySearchPage, CSearchPropertyPage)

CDirectorySearchPage::CDirectorySearchPage() : CSearchPropertyPage(CDirectorySearchPage::IDD)
{
	//{{AFX_DATA_INIT(CDirectorySearchPage)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
   
   c_poIterator = new CDirectoryFileIterator;
}
//
// ------------------------------------------------------------------
//
CDirectorySearchPage::~CDirectorySearchPage()
{
   if( c_poIterator )
   {
      delete c_poIterator;
      c_poIterator = NULL;
   }
}
//
// ------------------------------------------------------------------
//
void CDirectorySearchPage::DoDataExchange(CDataExchange* pDX)
{
	CSearchPropertyPage::DoDataExchange(pDX);
	//{{AFX_DATA_MAP(CDirectorySearchPage)
	DDX_Control(pDX, IDC_SUB_DIRECTORIES, c_oSubDirectories);
	DDX_Control(pDX, IDC_INCLUDE_DIRS, c_oIncludeDirs);
	DDX_Control(pDX, IDC_BROWSE_DIRECTORY, c_oBrowseDirectory);
	DDX_Control(pDX, IDC_FILE_MASK, c_oFileMask);
	DDX_Control(pDX, IDC_SEARCH_DIRECTORY, c_oSearchDirectory);
	//}}AFX_DATA_MAP
}


BEGIN_MESSAGE_MAP(CDirectorySearchPage, CSearchPropertyPage)
	//{{AFX_MSG_MAP(CDirectorySearchPage)
	ON_WM_SIZE()
	ON_WM_DESTROY()
	ON_BN_CLICKED(IDC_BROWSE_DIRECTORY, OnBrowseDirectory)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()

/////////////////////////////////////////////////////////////////////////////
// CDirectorySearchPage non-message handlers
/////////////////////////////////////////////////////////////////////////////

CFileIterator * CDirectorySearchPage::PrepareToStart()
{
   CString a_sSearchPath;
   HandleComboBox( &c_oSearchDirectory, a_sSearchPath );

   CString a_sFileMask;
   HandleComboBox( &c_oFileMask, a_sFileMask );
   
   CString a_sIncludeDirs;
   c_oIncludeDirs.GetWindowText( a_sIncludeDirs );

   c_poIterator->ParseOptions( a_sSearchPath,
                               a_sFileMask,
                               a_sIncludeDirs,
                               (c_oSubDirectories.GetCheck() == 1) );
   return c_poIterator;
}
//
// ------------------------------------------------------------------
//
void CDirectorySearchPage::SearchStopped()
{
}
//
// ------------------------------------------------------------------
//

/////////////////////////////////////////////////////////////////////////////
// CDirectorySearchPage message handlers
/////////////////////////////////////////////////////////////////////////////

BOOL CDirectorySearchPage::OnInitDialog() 
{
	CSearchPropertyPage::OnInitDialog();
	
   CSettings & a_roSettings = CSettings::GetSettings();
   // Load the previous directories and masks from the settings.
   int i = 0;
   for( i = 0; i<a_roSettings.c_oDirectories.size(); ++i )
   {
      c_oSearchDirectory.AddString( a_roSettings.c_oDirectories[i].c_str() );
   }
   c_oSearchDirectory.SetCurSel( 0 );

   for( i = 0; i<a_roSettings.c_oFileMasks.size(); ++i )
   {
      c_oFileMask.AddString( a_roSettings.c_oFileMasks[i].c_str() );
   }
   c_oFileMask.SetCurSel( 0 );

   c_oIncludeDirs.SetWindowText( a_roSettings.c_sIncludeDirs.c_str() );

   c_oSubDirectories.SetCheck( a_roSettings.c_bRecurse != 0 );
	
	return TRUE;  // return TRUE unless you set the focus to a control
	              // EXCEPTION: OCX Property Pages should return FALSE
}
//
// ------------------------------------------------------------------
//
void CDirectorySearchPage::OnSize(UINT nType, int cx, int cy) 
{
	CSearchPropertyPage::OnSize(nType, cx, cy);
	
	if( !IsWindow( c_oSearchDirectory ) )
      // Our controls haven't been subclassed yet.
      return;

   // Resize our controls.
   //
   
   int a_iBigBorder = 0;
   CRect a_oRect;

   c_oSearchDirectory.GetWindowRect( &a_oRect );
   ScreenToClient( &a_oRect );
   a_iBigBorder = a_oRect.top;

   c_oBrowseDirectory.GetWindowRect( &a_oRect );
   ScreenToClient( &a_oRect );
   c_oBrowseDirectory.MoveWindow( cx - a_oRect.Width() - a_iBigBorder,
                                  a_oRect.top,
                                  a_oRect.Width(),
                                  a_oRect.Height() );
   c_oBrowseDirectory.GetWindowRect( &a_oRect );
   ScreenToClient( &a_oRect );
   
   int a_iComboRightEdge = a_oRect.left;

   c_oSearchDirectory.GetWindowRect( &a_oRect );
   ScreenToClient( &a_oRect );
   c_oSearchDirectory.MoveWindow( a_oRect.left,
                                  a_oRect.top,
                                  a_iComboRightEdge - a_oRect.left,
                                  a_oRect.Height() );
   
   c_oFileMask.GetWindowRect( &a_oRect );
   ScreenToClient( &a_oRect );
   c_oFileMask.MoveWindow( a_oRect.left,
                           a_oRect.top,
                           a_iComboRightEdge - a_oRect.left,
                           a_oRect.Height() );

   c_oIncludeDirs.GetWindowRect( &a_oRect );
   ScreenToClient( &a_oRect );
   c_oIncludeDirs.MoveWindow( a_oRect.left,
                              a_oRect.top,
                              a_iComboRightEdge - a_oRect.left,
                              a_oRect.Height() );
}
//
// ------------------------------------------------------------------
//
void CDirectorySearchPage::OnDestroy() 
{
	CSearchPropertyPage::OnDestroy();
	
   // Save the directories and masks to the settings.
   CSettings & a_roSettings = CSettings::GetSettings();

   a_roSettings.c_oDirectories.clear();
   int i = 0;
   for( i = 0; i<c_oSearchDirectory.GetCount(); ++i )
   {
      CString a_sTemp;
      c_oSearchDirectory.GetLBText( i, a_sTemp );
      a_roSettings.c_oDirectories.push_back( (LPCTSTR)a_sTemp );
   }

   a_roSettings.c_oFileMasks.clear();
   for( i = 0; i<c_oFileMask.GetCount(); ++i )
   {
      CString a_sTemp;
      c_oFileMask.GetLBText( i, a_sTemp );
      a_roSettings.c_oFileMasks.push_back( (LPCTSTR)a_sTemp );
   }
   
   CString a_sTemp;
   c_oIncludeDirs.GetWindowText( a_sTemp );
   a_roSettings.c_sIncludeDirs = a_sTemp;

   a_roSettings.c_bRecurse = c_oSubDirectories.GetCheck() != 0;
}
//
// ------------------------------------------------------------------
//
void CDirectorySearchPage::OnBrowseDirectory() 
{
   // Let the user browse for a folder.
	TCHAR a_szDisplayName[MAX_PATH] = {0};
	BROWSEINFO a_stBrowseInfo;
	memset( &a_stBrowseInfo, 0, sizeof( a_stBrowseInfo ) );
	a_stBrowseInfo.hwndOwner = NULL;
	a_stBrowseInfo.pszDisplayName = a_szDisplayName;
	CString a_sTitle( (LPCTSTR)IDS_STR_DIRECTORY );
   a_stBrowseInfo.lpszTitle = a_sTitle;
	a_stBrowseInfo.ulFlags = BIF_RETURNONLYFSDIRS;
	LPITEMIDLIST a_poItemIDList = SHBrowseForFolder( &a_stBrowseInfo );
	if( a_poItemIDList )
	{
		IMalloc * a_poMalloc = NULL;
		SHGetMalloc( &a_poMalloc );
		TCHAR a_szPath[MAX_PATH] = {0};
		SHGetPathFromIDList( a_poItemIDList, a_szPath );

      c_oSearchDirectory.SetWindowText( a_szPath );

      a_poMalloc->Free( a_poItemIDList );
		a_poMalloc->Release();
   }
}
//
// ------------------------------------------------------------------
//

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 States United States
I like to program, I like to sail.

Comments and Discussions