Click here to Skip to main content
11,637,662 members (75,255 online)
Click here to Skip to main content
Add your own
alternative version

Include File Hierarchy Viewer

, 29 Jul 2003 CPOL 262.2K 3.3K 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)

Share

About the Author

Chris Richardson
Software Developer (Senior)
United States United States
I like to program, I like to sail.

You may also be interested in...

| Advertise | Privacy | Terms of Use | Mobile
Web02 | 2.8.150728.1 | Last Updated 30 Jul 2003
Article Copyright 2003 by Chris Richardson
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid