Click here to Skip to main content
15,897,891 members
Articles / Programming Languages / C++

ToDoList Add-on

Rate me:
Please Sign up or sign in to vote.
4.69/5 (6 votes)
20 Apr 2002CPOL3 min read 242.6K   2.9K   57  
A Visual Studio add-in to help navigate to TODO:, TASK: etc comments, as well as showing STL containers in debug mode such as std::string, std::list etc
/********************************************************************\
  created:    2001/04/07
  created:    7:4:2001   20:37
  filename:   commands.cpp
  file path:  no matter
  file base:  commands
  file ext:   cpp
  author:     Alex Kucherenko
  
  purpose:  
\********************************************************************/

#include "stdafx.h"
#include "ToDoCached.h"
#include "Commands.h"
#include "comutil.h"

#include "ToDoOptions.h"

#include "CLog.h"
#include "CWinLog.h"
#include "CFileLog.h"
#include "CFuncLog.h"

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

#define MAX_LOG_LEVEL 2
#define LOG_ERROR     0
#define LOG_WARNING   1
#define LOG_INFO      2

#define TRACE_EXCEPTION  log.LogString( LOG_WARNING, log.FormatString( \
    "File : %s : Line(%d) : Exception : %s : More Info : %s\n", \
    __FILE__, \
    __LINE__, \
    ex.GetErrorMessage().c_str( ), \
    ex.GetMoreInfo().c_str( ) ) \
  )

// Disable warning on microsoft specific constractions (look into 'note' comments)
#pragma warning( disable : 4239 )

//////////////////////////////////////////////////////////////////////////
// Reorder all records in registry for fixing order in Options combobox and
// all created std::map's - std::map sort hic records by key value

void CCommands::ReorderRegistry( void )
{
  CFuncLog    log( m_pLog, "CCommands::ReorderRegistry" );

  CString tmpName, tmpTitle;
  
  typedef std::map< string, string > TStrMap;

  TStrMap arrNames;
  long  lCount = 0;
  DWORD lSize;
  char  retValue[ 8192 ];
  string value1, value2;

  value1.reserve( 8192 );
  value2.reserve( 8192 );

  // read all regisatry records into std::map 
  while( 1 )
  {
    lSize = sizeof( retValue );

    tmpName.Format( "Search%d", ++lCount );
    
    if( m_RegistryWork.QueryValue( retValue, tmpName, &lSize ) != ERROR_SUCCESS )
      break;
    else
      value1 = retValue;

    tmpTitle.Format( "Text%d", lCount );
    lSize = sizeof( retValue );

    if( m_RegistryWork.QueryValue( retValue, tmpTitle, &lSize ) != ERROR_SUCCESS )
      break;
    else
      value2 = retValue;

    arrNames.insert( TStrMap::value_type( value1, value2 ) );
  }
  
  TStrMap::iterator k;
  lSize = sizeof( retValue );

  // Correct 'FindWhat' value in registry
  if( m_RegistryWork.QueryValue( retValue, "FindWhat", &lSize ) != ERROR_SUCCESS )
    retValue[0] = '1', retValue[1] = 0;

  tmpName.Format( "Search%s", retValue );
  lSize = sizeof( retValue );

  if( m_RegistryWork.QueryValue( retValue, tmpName, &lSize ) == ERROR_SUCCESS )
  {
    TStrMap::difference_type tmpDiff = 0;
    k = arrNames.find( string( retValue ) );
    
    if( k != arrNames.end() )
      tmpDiff = std::distance( arrNames.begin(), k ) + 1;

    tmpName.Format( "%d", tmpDiff );

    m_RegistryWork.SetValue( tmpName, "FindWhat" );
  }

  // Store sorted array into Registry (while adding records to map 
  // all records in it sorted automaticaly)
  lCount = 0;
  
  for( k = arrNames.begin(); k != arrNames.end() ; k++ )
  {
    tmpName.Format( "Search%d", ++lCount );
    tmpTitle.Format( "Text%d", lCount );

    if( m_RegistryWork.SetValue( k->first.c_str(), tmpName ) == ERROR_SUCCESS )
      m_RegistryWork.SetValue( k->second.c_str(), tmpTitle );
  }
}

//////////////////////////////////////////////////////////////////////////
// Recover all registry keys to default value if no registry values found

void CCommands::RecoverRegistryDefault( void )
{
  CFuncLog    log( m_pLog, "RecoverRegistryDefault" );

  // Create key
  if( m_RegistryWork.Create( HKEY_LOCAL_MACHINE,
    TEXT( "SOFTWARE\\AlexKucherenko\\TODOList Add-in\\Debug" ) ) != ERROR_SUCCESS )
  {
    ::MessageBox( NULL, 
      TEXT( "Error cannot create registry key" ), 
      TEXT( "Fatal Error" ), 
      MB_OK | MB_ICONERROR );
    
    return;
  }

  m_RegistryWork.SetValue( TEXT( "c:\\todolist.log" ), TEXT( "LogToFile" ) );
  m_RegistryWork.SetValue( TEXT( "0" ), TEXT( "LogInWindow" ) );

  m_RegistryWork.Create( HKEY_LOCAL_MACHINE, 
    TEXT( "SOFTWARE\\AlexKucherenko\\TODOList Add-in" ) );

  m_RegistryWork.SetValue( TEXT( "0" ), TEXT( "FindWhat" ) );
  m_RegistryWork.SetValue( TEXT( "0" ), TEXT( "ParseOnlyActiveProject" ) );
  m_RegistryWork.SetValue( TEXT( ".cpp;.hpp;.hxx;.cxx;.c;.h;" ), TEXT( "FileExtensions" ) );
  
  m_RegistryWork.SetValue( TEXT( "// DONE: " ), TEXT( "Search1" ) );
  m_RegistryWork.SetValue( TEXT( "-= DONE =-" ), TEXT( "Text1" ) );
  
  m_RegistryWork.SetValue( TEXT( "// NOTE: " ), TEXT( "Search2" ) );
  m_RegistryWork.SetValue( TEXT( "-= NOTE =-" ), TEXT( "Text2" ) );
  
  m_RegistryWork.SetValue( TEXT( "// TEST: " ), TEXT( "Search3" ) );
  m_RegistryWork.SetValue( TEXT( "-= TEST =-" ), TEXT( "Text3" ) );

  m_RegistryWork.SetValue( TEXT( "// TODO: " ), TEXT( "Search4" ) );
  m_RegistryWork.SetValue( TEXT( "-= TODO =-" ), TEXT( "Text4" ) );
}

/////////////////////////////////////////////////////////////////////////////
// Constructor

CCommands::CCommands( ) :
  m_bFirstRun( FALSE )
  , m_pWorkSpace( NULL )
  , m_hSyncHandle( NULL )
  , m_hThread( NULL )
  , m_hTimeOut( NULL )
  , m_tid( 0 )
  , m_dTid( 0 )
  , m_pApplication( NULL )
  , m_pApplicationEventsObj( NULL )
  , m_pDebuggerEventsObj( NULL )
  , m_pLog( NULL )
{
  // try to open registry key with parser options
  if( m_RegistryWork.Open( HKEY_LOCAL_MACHINE, 
      TEXT( "SOFTWARE\\AlexKucherenko\\TODOList Add-in" ) ) != ERROR_SUCCESS
    )
  {
    RecoverRegistryDefault();
  }
  else
  {
    ReorderRegistry();
  }

#ifdef _DEBUG
  char  tmpVal[8192];
  DWORD tmpSize = sizeof( tmpVal );
  LONG  errCode = 0;

  CRegKey RegDebug;

  errCode = RegDebug.Create( HKEY_LOCAL_MACHINE, 
    TEXT( "SOFTWARE\\AlexKucherenko\\TODOList Add-in\\Debug" ) );

  errCode = RegDebug.QueryValue( tmpVal, "LogInWindow", &tmpSize );

  if( errCode == ERROR_SUCCESS )
    if( atol( tmpVal ) > 0 )
    {
      m_pLog = new CLog( new CWinLog( ), MAX_LOG_LEVEL );
    }
    else
    {
      tmpSize = sizeof( tmpVal );

      errCode = RegDebug.QueryValue( tmpVal, "LogToFile", &tmpSize );

      if( errCode == ERROR_SUCCESS )
      {
        m_pLog = new CLog( new CFileLog( tmpVal ), MAX_LOG_LEVEL );
        
        // uncomment next string if you don't want to see log data immediately 
        // ( greatly increase perfomance )
        // m_pLog->SetAutoFlush( false );
      }
    }
#endif // _DEBUG

}

//////////////////////////////////////////////////////////////////////////
// Destructor 

CCommands::~CCommands( )
{
  ASSERT( m_pApplication != NULL );

  m_pApplication->Release( );

  if( m_pWorkSpace != NULL ) 
    delete m_pWorkSpace, m_pWorkSpace = NULL;

  if( m_hThread != NULL )
    ::TerminateThread( m_hThread, ( DWORD )-1 );

  if( m_hTimeOut != NULL )
    ::TerminateThread( m_hTimeOut, ( DWORD )-1 );

  if( m_pLog != NULL )
    delete m_pLog, m_pLog = NULL;
}

//////////////////////////////////////////////////////////////////////////
//  

void CCommands::SetApplicationObject( IApplication* pApplication )
{
  CFuncLog    log( m_pLog, "CCommands::SetApplicationObject" );

  m_pApplication = pApplication;

  // Create Application event handlers
  XApplicationEventsObj::CreateInstance(&m_pApplicationEventsObj);
  m_pApplicationEventsObj->AddRef( );
  m_pApplicationEventsObj->Connect(m_pApplication);
  m_pApplicationEventsObj->m_pCommands = this;

  // Create Debugger event handler
  CComPtr<IDispatch> pDebugger;
  if (SUCCEEDED(m_pApplication->get_Debugger(&pDebugger) ) 
    && pDebugger != NULL)
  {
    XDebuggerEventsObj::CreateInstance(&m_pDebuggerEventsObj);
    m_pDebuggerEventsObj->AddRef( );
    m_pDebuggerEventsObj->Connect(pDebugger);
    m_pDebuggerEventsObj->m_pCommands = this;
  }
}

//////////////////////////////////////////////////////////////////////////
//  

void CCommands::UnadviseFromEvents( )
{
  CFuncLog    log( m_pLog, "CCommands::UnadviseFromEvents" );

  ASSERT (m_pApplicationEventsObj != NULL);
  m_pApplicationEventsObj->Disconnect(m_pApplication);
  m_pApplicationEventsObj->Release( );
  m_pApplicationEventsObj = NULL;

  if (m_pDebuggerEventsObj != NULL)
  {
    CComPtr<IDispatch> pDebugger;
    VERIFY_OK(m_pApplication->get_Debugger(&pDebugger) );
    ASSERT (pDebugger != NULL);
    m_pDebuggerEventsObj->Disconnect(pDebugger);
    m_pDebuggerEventsObj->Release( );
    m_pDebuggerEventsObj = NULL;
  }
}


/////////////////////////////////////////////////////////////////////////////
// Event handlers                                                          //
// Application events                                                      //
/////////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::BeforeBuildStart( )
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog    log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::BeforeBuildStart" );

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::BuildFinish(long /*nNumErrors*/, long /*nNumWarnings*/)
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog  log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::BuildFinish" );

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::BeforeApplicationShutDown( )
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog  log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::BeforeApplicationShutDown" );

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::DocumentOpen(IDispatch* /*theDocument*/)
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog    log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::DocumentOpen" );

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::BeforeDocumentClose(IDispatch* /*theDocument*/)
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog    log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::BeforeDocumentClose" );

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::DocumentSave( IDispatch* theDocument )
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  
  CFuncLog    log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::DocumentSave" );

  CComQIPtr< IGenericDocument, &IID_IGenericDocument> pDoc( theDocument );
  CComBSTR  strFullName;
  
  pDoc->get_FullName( &strFullName );
  
  bstr_t tmpName( ( BSTR )strFullName );
  string strProjectFile = (char *)tmpName;

  string strProject =  m_pCommands->GetActiveProject();

  try
  {
    if( m_pCommands->m_pWorkSpace != NULL )
      m_pCommands->m_pWorkSpace->ReparseFile( strProject.c_str( ), strProjectFile.c_str( ) );
  }
  catch( CToDoNoElements ex )
  {
    TRACE_EXCEPTION;
  }
  
  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::NewDocument(IDispatch* /*theDocument*/)
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog    log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::NewDocument" );

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::WindowActivate(IDispatch* /*theWindow*/)
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog    log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::WindowActivate" );

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::WindowDeactivate(IDispatch* /*theWindow*/)
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog    log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::WindowDeactivate" );

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::WorkspaceOpen( )
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog    log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::WorkspaceOpen" );

  m_pCommands->m_bFirstRun = FALSE;

  if( m_pCommands->m_pWorkSpace != NULL )
    delete m_pCommands->m_pWorkSpace, m_pCommands->m_pWorkSpace = NULL;

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::WorkspaceClose( )
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog    log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::WorkspaceClose" );

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XApplicationEvents::NewWorkspace( )
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog    log( m_pCommands->m_pLog, "CCommands::XApplicationEvents::NewWorkspace" );

  m_pCommands->m_bFirstRun = FALSE;

  if( m_pCommands->m_pWorkSpace != NULL )
    delete m_pCommands->m_pWorkSpace, m_pCommands->m_pWorkSpace = NULL;

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
// Debugger event                                                       //
//////////////////////////////////////////////////////////////////////////

//////////////////////////////////////////////////////////////////////////
//  

HRESULT CCommands::XDebuggerEvents::BreakpointHit(IDispatch* /*pBreakpoint*/)
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );
  
  CFuncLog    log( m_pCommands->m_pLog, "CCommands::XDebuggerEvents::BreakpointHit" );
  
  return S_OK;
}

/////////////////////////////////////////////////////////////////////////////
// Parser caller 

STDMETHODIMP CCommands::ToDoCachedCommandMethod( ) 
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) );

  CFuncLog    log( m_pLog, "CCommands::ToDoCachedCommandMethod" );

  // VSBUG: Don't remove bFirstLogo part code. It's fix Visual Studio bug.
  // I'm seriously! If Macro output window not created before our output 
  // then we have error NULL pointer exception. It's very strange behaviour 
  // of Visual Studio. I think this was fixed in lates VS SP.

  static bool bFirstLogo = true;

  if( bFirstLogo )
  {
    bFirstLogo = false;
    m_pApplication->PrintToOutputWindow( L"ToDoList Add-on Logo" );
  }

  if( m_bFirstRun == FALSE )
  {
    m_bFirstRun = TRUE;
    ParseProject( );
  }
  
  if( m_hSyncHandle != NULL )
  {
    m_hThread = ::CreateThread( NULL, 0,
      (LPTHREAD_START_ROUTINE)ShowCategory, this, 0, &m_tid );

    if( m_hThread == NULL )
      return S_FALSE;

    m_hTimeOut = ::CreateThread( NULL, 0,
      ( LPTHREAD_START_ROUTINE )TimeOutThread, this, 0, &m_dTid );
  }
  
  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
// Function set internal var m_bFirstRun. On next call ToDoListCommandMethod
// project will be reparsed fully. This function needed only if all comments
// in project not found automaticaly.  

STDMETHODIMP CCommands::ReparseWorkspace( )
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) )

  CFuncLog    log( m_pLog, "CCommands::ReparseWorkspace" );

  m_bFirstRun = FALSE;

  if( m_pWorkSpace != NULL )
    delete m_pWorkSpace, m_pWorkSpace = NULL;

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
// Function call option dilog for setting registry keys for our parser 

STDMETHODIMP CCommands::OptionsForParsing( )
{
  AFX_MANAGE_STATE( AfxGetStaticModuleState( ) )

  CFuncLog    log( m_pLog, "CCommands::OptionsForParsing" );

  // If project never parsed before
  if( m_bFirstRun == FALSE || m_pWorkSpace == NULL )
  {
    m_bFirstRun = TRUE;
    ParseProject( );

    DWORD retValue = ::WaitForSingleObject( m_hSyncHandle, DEF_TIMEOUT_THREAD_PARSE );

    if( retValue == WAIT_TIMEOUT ) return S_OK;
  }

  CToDoOptions dlg;
  dlg.InitMap( m_pWorkSpace );
  dlg.DoModal();

  // Change order of records in registry if option dialog something change
  ReorderRegistry();

  // Project must be fully reparsed if options in dialog changed
  m_bFirstRun = FALSE;

  if( m_pWorkSpace != NULL )
    delete m_pWorkSpace, m_pWorkSpace = NULL;

  return S_OK;
}

//////////////////////////////////////////////////////////////////////////
// Function parse project 

void CCommands::ParseProject( void )
{
  CFuncLog    log( m_pLog, "CCommands::ParseProject" );

  LONG      tmpRet = 0;
  long      lCounter = 0;
  CComPtr<IDispatch> pProjectsDisp;
 
  // Create list of all projects in workspace
  m_pApplication->get_Projects( &pProjectsDisp );
  CComQIPtr< IProjects, &IID_IProjects > pProjects( pProjectsDisp );

  // Get quantity of projects in workspace
  pProjects->get_Count( &lCounter );
  m_arrAllProjects.clear();

  for( long i=0 ; i<lCounter ; i++ )
  {
    string strProjectFile;

    {
      // Extract project file name from BSTR string
      CComBSTR  tmpFullName;
      {
        CComPtr<IGenericProject> pProject;
        variant_t Index( ( long )( i+1 ) );
      
        pProjects->Item( Index.Detach( ), &pProject );
        pProject->get_FullName( &tmpFullName );
      }
    
      bstr_t tmpName( ( BSTR )tmpFullName );
      strProjectFile = (char *)tmpName;
    } /* Delete all automatic vars */

    strlwr( ( char * ) strProjectFile.c_str( ) );

    m_arrAllProjects.push_back( string( strProjectFile.c_str( ) ) );
  }
  
  // Create search list of words
  {
    string   _tmpKey;
    char     _tmpName[8192];
    DWORD    _tmpSize = 8192;
  
    m_arrSearchWords.clear( );

    for( i=0 ; TRUE ; ++i )
    {
      sprintf( _tmpName, "Search%d", i+1 );
      _tmpKey = _tmpName;
    
      tmpRet = m_RegistryWork.QueryValue( _tmpName, _tmpKey.c_str( ), &_tmpSize );

      if( tmpRet != ERROR_SUCCESS ) break;

      m_arrSearchWords.push_back( string( _tmpName ) );
      _tmpSize = sizeof(_tmpName);
    }
  }
  
  // Recover registry if nothing found in list
  if( m_arrSearchWords.empty( ) )
    RecoverRegistryDefault( );

  if( m_pWorkSpace == NULL )
    m_pWorkSpace = new CToDoWorkSpace( m_arrAllProjects, m_arrSearchWords );

  m_hSyncHandle = ( HANDLE )m_pWorkSpace->StartParsing( );
}

//////////////////////////////////////////////////////////////////////////
// Thread waiting for Parse and Output thread and if they doesn't finish it's 
// work in time then terminate threads

DWORD CCommands::TimeOutThread( CCommands *pThis )
{
  CFuncLog    log( pThis->m_pLog, "CCommands::TimeOutThread" );

  if( pThis->m_hThread == NULL )
    return (DWORD)-1;
  
  DWORD retSync = 0;

  ::GetExitCodeThread( pThis->m_hThread, &retSync );
  
  // By default we Wait 20 seconds
  DWORD retValue = ::WaitForSingleObject( pThis->m_hThread, DEF_TIMEOUT_THREAD_SHOW ); 

  if( retValue == WAIT_TIMEOUT )
  {
    // Ignore any returned codes
    ::TerminateThread( pThis->m_hSyncHandle, ( DWORD )-1 );
    ::TerminateThread( pThis->m_hThread, ( DWORD )-1 );
  }

  // Set handle to NULL when thread is finished
  pThis->m_hTimeOut = NULL;

  return 0;
}

//////////////////////////////////////////////////////////////////////////
// Function show all finded useful comments into Macro Output window
// ( Function select active project or all projets )

DWORD CCommands::ShowCategory( CCommands *pThis)
{
  CFuncLog    log( pThis->m_pLog, "CCommands::ShowCategory" );

  char    _tmpValue[8192];
  DWORD   _tmpSize = sizeof(_tmpValue);
  long    lAllPtojects = 0;
  
  pThis->m_RegistryWork.QueryValue( _tmpValue, TEXT("ParseOnlyActiveProject"), &_tmpSize );
  lAllPtojects = atol( _tmpValue );

  DWORD retSync = 0;

  // Check that we have first thread handle
  if( pThis->m_hSyncHandle == NULL )
    return (DWORD)-1;

  GetExitCodeThread( pThis->m_hSyncHandle, &retSync );
  
  if( retSync == STILL_ACTIVE )
  {
    retSync = ::WaitForSingleObject( pThis->m_hSyncHandle, DEF_TIMEOUT_THREAD_PARSE );
    
    if( retSync == WAIT_TIMEOUT )
      return (DWORD)-1;
  }

  if( lAllPtojects == 0 ) 
  {
    // Parse all projects in workspace
    try
    {
      TWorkSpaceIter k, tmpIter = *pThis->m_pWorkSpace->Last();

      for(  k = *pThis->m_pWorkSpace->First( ) ; 
            k != tmpIter ; 
            k = *pThis->m_pWorkSpace->Next( ) )
        pThis->ShowProjectText( k->second );
    }
    catch( CToDoException ex )
    { 
      TRACE_EXCEPTION;
    }
  }
  else
  {
    //  Parse only active project in workspace 
    string strProjectFile = pThis->GetActiveProject();

    try
    {
      TWorkSpaceIter k = *pThis->m_pWorkSpace->Find( strProjectFile.c_str( ) );
      pThis->ShowProjectText( k->second );
    }
    catch( CToDoNoElements ex )
    { 
      TRACE_EXCEPTION;
    }
  }

  // Set handle to NULL when thread is finished
  pThis->m_hThread = NULL;

  return 0;
}

//////////////////////////////////////////////////////////////////////////
// Function selct from project  
// (select search word or all search words)

void CCommands::ShowProjectText( TProject &tmpProject )
{
  CFuncLog    log( m_pLog, "CCommands::ShowProjectText" );

  // Show all files from project
  TProjectIter k;

  for( k = tmpProject.begin( ) ; k != tmpProject.end( ) ; k++ )
  {
    log.LogString( LOG_INFO, log.FormatString( "file : %s\n", k->first.c_str( ) ) );

    ShowMultiParseText( k->second );
  }
}

//////////////////////////////////////////////////////////////////////////
//  

void CCommands::ShowMultiParseText( CToDoMultiParse &tmpMulParse )
{
  CFuncLog    log( m_pLog, "CCommands::ShowMultiParseText" );

  string    strFindWhat;
  char      _tmpValue[8192];
  DWORD     _tmpSize = sizeof( _tmpValue );
  long      _tmpFindWhat = 0;
  
  m_RegistryWork.QueryValue( _tmpValue, "FindWhat", &_tmpSize );
  _tmpFindWhat = atol( _tmpValue );

  if( _tmpFindWhat == 0 ) 
  {
    // Show all search categories from file
    try
    {
      TMultiIter k, tmpIter = *tmpMulParse.Last();

      for( k = *tmpMulParse.First( ) ; k != tmpIter ; k = *tmpMulParse.Next( ) )
      {
        // NOTE: Here used Microsoft compiler specific construction. For more info 
        // look into 'warning C4239' help
        if( strcmp( k->first.c_str(), "// " ) != 0 )
          OutputSingleText( tmpMulParse.CreateMultiLine( k->first, "// " ) );
      }
    }
    catch( CToDoException ex )
    { 
      TRACE_EXCEPTION;
    }
  }
  else
  {
    // Show only one search category from file
    long i = _tmpFindWhat;
    
    try
    {
      TMultiIter k = *tmpMulParse.First( );
      
      for( i = _tmpFindWhat ; i >= 1 ; --i ) 
        k = *tmpMulParse.Next( );
      
      // NOTE: Here used Microsoft compiler specific construction. For more info 
      // look into 'warning C4239' help
      if( strcmp( k->first.c_str(), "// " ) != 0 )
        OutputSingleText( tmpMulParse.CreateMultiLine( k->first, "// " ) );
    }
    catch( CToDoException ex )
    {
      TRACE_EXCEPTION;
    }
  }
}

//////////////////////////////////////////////////////////////////////////
// Function realy print message into macro window output. All text for output
// are formated here. 

void CCommands::OutputSingleText( CToDoSingleParse &tmpSinParse )
{
  CFuncLog    log( m_pLog, "CCommands::OutputSingleText" );

  TLineMapperIter k;

  try
  {
    k = *tmpSinParse.First();
    
    for( int i = 0; i < tmpSinParse.GetElementsQuantity() ; i++ )
    {
      char tmpOutput[ TODO_STRING_RESERVE ];
      CString MultiComment( k->second.c_str( ) );

      MultiComment.Replace( "\t", " " );
      MultiComment.Replace( "\r", " " );
      MultiComment.Replace( "\n", " " );
      MultiComment.Replace( "  ", " " );

      sprintf( tmpOutput,  "%s(%d): %s : %s", 
        tmpSinParse.GetFileName().c_str(),  
        k->first, 
        tmpSinParse.GetSearchWord().c_str(), 
        MultiComment );
      
      CComBSTR tmpOut( tmpOutput );
      
      m_pApplication->PrintToOutputWindow( tmpOut.Detach() );

      k = *tmpSinParse.Next();
    }
  }    
  catch( CToDoException ex ) 
  { 
    TRACE_EXCEPTION;   
  };
  
}

//////////////////////////////////////////////////////////////////////////
// Function return full path to active project 

string CCommands::GetActiveProject()
{
  CFuncLog    log( m_pLog, "CCommands::GetActiveProject" );

  CComBSTR  tmpFullName;
  CComPtr< IDispatch > iDispProject;
  
  m_pApplication->get_ActiveProject( &iDispProject );
  
  CComQIPtr< IGenericProject, &IID_IGenericProject > pProject( iDispProject );
  
  // If no project opened
  if( pProject == NULL ) return "";

  pProject->get_FullName( &tmpFullName );
  
  bstr_t tmpName( ( BSTR )tmpFullName );
  string strProjectFile = (char *)tmpName;
  
  strlwr( ( char * )strProjectFile.c_str( ) );
  
  return string( strProjectFile.c_str( ) );
}

//:> End of file

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
CEO ArtfulBits Inc.
Ukraine Ukraine
Name:Kucherenko Oleksandr

Born:September 20, 1979

Platforms: Win32, Linux; - well known and MS-DOS; Win16; OS/2 - old time not touched;

Hardware: IBM PC

Programming Languages: Assembler (for Intel 80386); Borland C/C++; Borland Pascal; Object Pascal; Borland C++Builder; Delphi; Perl; Java; Visual C++; Visual J++; UML; XML/XSL; C#; VB.NET; T-SQL; PL/SQL; and etc.

Development Environments: MS Visual Studio 2001-2008; MS Visual C++; Borland Delphi; Borland C++Builder; C/C++ any; Rational Rose; GDPro; Together and etc.

Libraries: STL, ATL, WTL, MFC, NuMega Driver Works, VCL; .NET 1.0, 1.1, 2.0, 3.5; and etc.

Technologies: Client/Server; COM; DirectX; DirectX Media; BDE; HTML/DHTML; ActiveX; Java Servlets; DCOM; COM+; ADO; CORBA; .NET; Windows Forms; GDI/GDI+; and etc.

Application Skills: Databases - design and maintain, support, programming; GUI Design; System Programming, Security; Business Software Development. Win/Web Services development and etc.

Comments and Discussions