bool BOARD_NETLIST_UPDATER::deleteUnusedComponents( NETLIST& aNetlist )
{
    wxString msg;
    MODULE* nextModule;
    const COMPONENT* component;

    for( MODULE* module = m_board->m_Modules; module != NULL; module = nextModule )
    {
        nextModule = module->Next();

        if( m_lookupByTimestamp )
            component = aNetlist.GetComponentByTimeStamp( module->GetPath() );
        else
            component = aNetlist.GetComponentByReference( module->GetReference() );

        if( component == NULL )
        {
            if( module->IsLocked() )
            {
                msg.Printf( _( "Component %s is locked, skipping removal.\n" ),
                            GetChars( module->GetReference() ) );
                m_reporter->Report( msg, REPORTER::RPT_INFO );
                continue;
            }

            msg.Printf( _( "Remove component %s." ),
                        GetChars( module->GetReference() ) );
            m_reporter->Report( msg, REPORTER::RPT_ACTION );

            msg.Printf( _( "Removing unused component \"%s:%s\".\n" ),
                        GetChars( module->GetReference() ),
                        GetChars( module->GetPath() ) );
            m_reporter->Report( msg, REPORTER::RPT_INFO );

            if( !m_isDryRun )
                m_commit.Remove( module );
        }
    }

    return true;
}
bool DIALOG_NETLIST::verifyFootprints( const wxString&         aNetlistFilename,
                                       const wxString &        aCmpFilename,
                                       std::vector< MODULE* >& aDuplicates,
                                       wxArrayString&          aMissing,
                                       std::vector< MODULE* >& aNotInNetlist )
{
    wxString        msg;
    MODULE*         module;
    MODULE*         nextModule;
    NETLIST         netlist;
    wxBusyCursor    dummy;           // Shows an hourglass while calculating.
    NETLIST_READER* netlistReader;
    COMPONENT*      component;

    try
    {
        netlistReader = NETLIST_READER::GetNetlistReader( &netlist, aNetlistFilename,
                        aCmpFilename );

        if( netlistReader == NULL )
        {
            msg.Printf( _( "Cannot open netlist file \"%s\"." ), GetChars( aNetlistFilename ) );
            wxMessageBox( msg, _( "Netlist Load Error." ), wxOK | wxICON_ERROR );
            return false;
        }

        std::auto_ptr< NETLIST_READER > nlr( netlistReader );
        netlistReader->LoadNetlist();
    }
    catch( const IO_ERROR& ioe )
    {
        msg.Printf( _( "Error loading netlist file:\n%s" ), ioe.errorText.GetData() );
        wxMessageBox( msg, _( "Netlist Load Error" ), wxOK | wxICON_ERROR );
        return false;
    }

    BOARD* pcb = m_parent->GetBoard();

    // Search for duplicate footprints.
    module = pcb->m_Modules;

    for( ; module != NULL; module = module->Next() )
    {
        nextModule = module->Next();

        for( ; nextModule != NULL; nextModule = nextModule->Next() )
        {
            if( module->GetReference().CmpNoCase( nextModule->GetReference() ) == 0 )
            {
                aDuplicates.push_back( module );
                break;
            }
        }
    }

    // Search for component footprints in the netlist but not on the board.
    for( unsigned ii = 0; ii < netlist.GetCount(); ii++ )
    {
        component = netlist.GetComponent( ii );

        module = pcb->FindModuleByReference( component->GetReference() );

        if( module == NULL )
        {
            aMissing.Add( component->GetReference() );
            aMissing.Add( component->GetValue() );
        }
    }

    // Search for component footprints found on board but not in netlist.
    module = pcb->m_Modules;

    for( ; module != NULL; module = module->Next() )
    {

        component = netlist.GetComponentByReference( module->GetReference() );

        if( component == NULL )
            aNotInNetlist.push_back( module );
    }

    return true;
}