void DIALOG_SYMBOL_REMAP::remapSymbolsToLibTable( REPORTER& aReporter )
{
    wxString msg;
    SCH_SCREENS schematic;
    SCH_COMPONENT* symbol;
    SCH_ITEM* item;
    SCH_ITEM* nextItem;
    SCH_SCREEN* screen;

    for( screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
    {
        for( item = screen->GetDrawItems(); item; item = nextItem )
        {
            nextItem = item->Next();

            if( item->Type() != SCH_COMPONENT_T )
                continue;

            symbol = dynamic_cast< SCH_COMPONENT* >( item );

            if( !remapSymbolToLibTable( symbol ) )
            {
                msg.Printf( _( "No symbol \"%s\" found in symbol library table." ),
                            symbol->GetLibId().GetLibItemName().wx_str() );
                aReporter.Report( msg, REPORTER::RPT_WARNING );
            }
            else
            {
                msg.Printf( _( "Symbol \"%s\" mapped to symbol library \"%s\"." ),
                            symbol->GetLibId().GetLibItemName().wx_str(),
                            symbol->GetLibId().GetLibNickname().wx_str() );
                aReporter.Report( msg, REPORTER::RPT_ACTION );
                screen->SetModify();
            }
        }
    }

    aReporter.Report( _( "Symbol library table mapping complete!" ), REPORTER::RPT_INFO );
    schematic.UpdateSymbolLinks( true );
}
bool DIALOG_SYMBOL_REMAP::backupProject( REPORTER& aReporter )
{
    static wxString backupFolder = "rescue-backup";

    wxString tmp;
    wxString errorMsg;
    wxFileName srcFileName;
    wxFileName destFileName;
    wxFileName backupPath;
    SCH_SCREENS schematic;

    // Copy backup files to different folder so as not to pollute the project folder.
    destFileName.SetPath( Prj().GetProjectPath() );
    destFileName.AppendDir( backupFolder );
    backupPath = destFileName;

    if( !destFileName.DirExists() )
    {
        if( !destFileName.Mkdir() )
        {
            errorMsg.Printf( _( "Cannot create project remap back up folder \"%s\"." ),
                             destFileName.GetPath() );

            wxMessageDialog dlg( this, errorMsg, _( "Backup Error" ),
                                 wxYES_NO | wxCENTRE | wxRESIZE_BORDER | wxICON_QUESTION );
            dlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Continue with Rescue" ) ),
                                wxMessageDialog::ButtonLabel( _( "Abort Rescue" ) ) );

            if( dlg.ShowModal() == wxID_NO )
                return false;
        }
    }

    // Time stamp to append to file name in case multiple remappings are performed.
    wxString timeStamp = wxDateTime::Now().Format( "-%Y-%m-%d-%H-%M-%S" );

    // Back up symbol library table.
    srcFileName.SetPath( Prj().GetProjectPath() );
    srcFileName.SetName( SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );
    destFileName = srcFileName;
    destFileName.AppendDir( backupFolder );
    destFileName.SetName( destFileName.GetName() + timeStamp );

    tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ),
                srcFileName.GetFullPath(), destFileName.GetFullPath() );
    aReporter.Report( tmp, REPORTER::RPT_INFO );

    if( wxFileName::Exists( srcFileName.GetFullPath() )
      && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) )
    {
        tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() );
        errorMsg += tmp;
    }

    // Back up the schematic files.
    for( SCH_SCREEN* screen = schematic.GetFirst(); screen; screen = schematic.GetNext() )
    {
        destFileName = screen->GetFileName();
        destFileName.SetName( destFileName.GetName() + timeStamp );

        // Check for nest hierarchical schematic paths.
        if( destFileName.GetPath() != backupPath.GetPath() )
        {
            destFileName.SetPath( backupPath.GetPath() );

            wxArrayString srcDirs = wxFileName( screen->GetFileName() ).GetDirs();
            wxArrayString destDirs = wxFileName( Prj().GetProjectPath() ).GetDirs();

            for( size_t i = destDirs.GetCount(); i < srcDirs.GetCount(); i++ )
                destFileName.AppendDir( srcDirs[i] );
        }
        else
        {
            destFileName.AppendDir( backupFolder );
        }

        tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ),
                    screen->GetFileName(), destFileName.GetFullPath() );
        aReporter.Report( tmp, REPORTER::RPT_INFO );

        if( !destFileName.DirExists() && !destFileName.Mkdir( wxS_DIR_DEFAULT, wxPATH_MKDIR_FULL ) )
        {
            tmp.Printf( _( "Failed to create backup folder \"%s\"\n" ), destFileName.GetPath() );
            errorMsg += tmp;
            continue;
        }

        if( wxFileName::Exists( screen->GetFileName() )
          && !wxCopyFile( screen->GetFileName(), destFileName.GetFullPath() ) )
        {
            tmp.Printf( _( "Failed to back up file \"%s\".\n" ), screen->GetFileName() );
            errorMsg += tmp;
        }
    }

    // Back up the project file.
    destFileName = Prj().GetProjectFullName();
    destFileName.SetName( destFileName.GetName() + timeStamp );
    destFileName.AppendDir( backupFolder );

    tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ),
                   Prj().GetProjectFullName(), destFileName.GetFullPath() );
    aReporter.Report( tmp, REPORTER::RPT_INFO );

    if( wxFileName::Exists( Prj().GetProjectFullName() )
      && !wxCopyFile( Prj().GetProjectFullName(), destFileName.GetFullPath() ) )
    {
        tmp.Printf( _( "Failed to back up file \"%s\".\n" ), Prj().GetProjectFullName() );
        errorMsg += tmp;
    }

    // Back up the cache library.
    srcFileName.SetPath( Prj().GetProjectPath() );
    srcFileName.SetName( Prj().GetProjectName() + "-cache" );
    srcFileName.SetExt( SchematicLibraryFileExtension );

    destFileName = srcFileName;
    destFileName.SetName( destFileName.GetName() + timeStamp );
    destFileName.AppendDir( backupFolder );

    tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ),
                srcFileName.GetFullPath(), destFileName.GetFullPath() );
    aReporter.Report( tmp, REPORTER::RPT_INFO );

    if( srcFileName.Exists()
      && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) )
    {
        tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() );
        errorMsg += tmp;
    }

    // Back up the rescue symbol library if it exists.
    srcFileName.SetName( Prj().GetProjectName() + "-rescue" );
    destFileName.SetName( srcFileName.GetName() + timeStamp );

    tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ),
                srcFileName.GetFullPath(), destFileName.GetFullPath() );
    aReporter.Report( tmp, REPORTER::RPT_INFO );

    if( srcFileName.Exists()
      && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) )
    {
        tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() );
        errorMsg += tmp;
    }

    // Back up the rescue symbol library document file if it exists.
    srcFileName.SetExt( "dcm" );
    destFileName.SetExt( srcFileName.GetExt() );

    tmp.Printf( _( "Backing up file \"%s\" to file \"%s\"." ),
                srcFileName.GetFullPath(), destFileName.GetFullPath() );
    aReporter.Report( tmp, REPORTER::RPT_INFO );

    if( srcFileName.Exists()
      && !wxCopyFile( srcFileName.GetFullPath(), destFileName.GetFullPath() ) )
    {
        tmp.Printf( _( "Failed to back up file \"%s\".\n" ), srcFileName.GetFullPath() );
        errorMsg += tmp;
    }

    if( !errorMsg.IsEmpty() )
    {
        wxMessageDialog dlg( this, _( "Some of the project files could not be backed up." ),
                             _( "Backup Error" ),
                             wxYES_NO | wxCENTRE | wxRESIZE_BORDER | wxICON_QUESTION );
        errorMsg.Trim();
        dlg.SetExtendedMessage( errorMsg );
        dlg.SetYesNoLabels( wxMessageDialog::ButtonLabel( _( "Continue with Rescue" ) ),
                            wxMessageDialog::ButtonLabel( _( "Abort Rescue" ) ) );

        if( dlg.ShowModal() == wxID_NO )
            return false;
    }

    return true;
}
void DIALOG_SYMBOL_REMAP::createProjectSymbolLibTable( REPORTER& aReporter )
{
    wxString msg;
    std::vector< PART_LIB* > libs;

    if( getLibsNotInGlobalSymbolLibTable( libs ) )
    {
        SYMBOL_LIB_TABLE prjLibTable;
        std::vector< wxString > libNames = SYMBOL_LIB_TABLE::GetGlobalLibTable().GetLogicalLibs();

        for( auto lib : libs )
        {
            wxString libName = lib->GetName();
            int libNameInc = 1;
            int libNameLen = libName.Length();

            // Spaces in the file name will break the symbol name because they are not
            // quoted in the symbol library file format.
            libName.Replace( " ", "-" );

            // Don't create duplicate table entries.
            while( std::find( libNames.begin(), libNames.end(), libName ) != libNames.end() )
            {
                libName = libName.Left( libNameLen );
                libName << libNameInc;
                libNameInc++;
            }

            wxString pluginType = SCH_IO_MGR::ShowType( SCH_IO_MGR::SCH_LEGACY );
            wxFileName fn = lib->GetFullFileName();

            // Use environment variable substitution where possible.  This is based solely
            // on the internal user environment variable list.  Checking against all of the
            // system wide environment variables is probably not a good idea.
            wxString fullFileName = NormalizePath( fn, &Pgm().GetLocalEnvVariables(), &Prj() );

            // Fall back to the absolute library path.
            if( fullFileName.IsEmpty() )
                fullFileName = lib->GetFullFileName();

            wxFileName tmpFn = fullFileName;

            // Don't add symbol libraries that do not exist.
            if( tmpFn.Normalize() && tmpFn.FileExists() )
            {
                msg.Printf( _( "Adding library \"%s\", file \"%s\" to project symbol library table." ),
                            libName, fullFileName );
                aReporter.Report( msg, REPORTER::RPT_INFO );

                prjLibTable.InsertRow( new SYMBOL_LIB_TABLE_ROW( libName, fullFileName,
                                                                 pluginType ) );
            }
            else
            {
                msg.Printf( _( "Library \"%s\" not found." ), fullFileName );
                aReporter.Report( msg, REPORTER::RPT_WARNING );
            }
        }

        // Don't save empty project symbol library table.
        if( !prjLibTable.IsEmpty() )
        {
            wxFileName fn( Prj().GetProjectPath(), SYMBOL_LIB_TABLE::GetSymbolLibTableFileName() );

            try
            {
                FILE_OUTPUTFORMATTER formatter( fn.GetFullPath() );
                prjLibTable.Format( &formatter, 0 );
            }
            catch( const IO_ERROR& ioe )
            {
                msg.Printf( _( "Failed to write project symbol library table. Error:\n  %s" ),
                            ioe.What() );
                aReporter.ReportTail( msg, REPORTER::RPT_ERROR );
            }

            aReporter.ReportTail( _( "Created project symbol library table.\n" ), REPORTER::RPT_INFO );
        }
    }
}
int SCH_REFERENCE_LIST::CheckAnnotation( REPORTER& aReporter )
{
    int            error = 0;
    wxString       tmp;
    wxString       msg;

    SortByRefAndValue();

    // Spiit reference designators into name (prefix) and number: IC1 becomes IC, and 1.
    SplitReferences();

    // count not yet annotated items or annotation error.
    for( unsigned ii = 0; ii < componentFlatList.size(); ii++ )
    {
        msg.Empty();
        tmp.Empty();

        if( componentFlatList[ii].m_IsNew )    // Not yet annotated
        {
            if( componentFlatList[ii].m_NumRef >= 0 )
                tmp << componentFlatList[ii].m_NumRef;
            else
                tmp = wxT( "?" );


            if(  ( componentFlatList[ii].m_Unit > 0 )
              && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF )  )
            {
                msg.Printf( _( "Item not annotated: %s%s (unit %d)\n" ),
                            GetChars( componentFlatList[ii].GetRef() ),
                            GetChars( tmp ),
                            componentFlatList[ii].m_Unit );
            }
            else
            {
                msg.Printf( _( "Item not annotated: %s%s\n" ),
                            GetChars( componentFlatList[ii].GetRef() ),
                            GetChars( tmp ) );
            }

            aReporter.Report( msg, REPORTER::RPT_WARNING );
            error++;
            break;
        }

        // Error if unit number selected does not exist ( greater than the  number of
        // parts in the component ).  This can happen if a component has changed in a
        // library after a previous annotation.
        if( std::max( componentFlatList[ii].GetLibPart()->GetUnitCount(), 1 )
          < componentFlatList[ii].m_Unit )
        {
            if( componentFlatList[ii].m_NumRef >= 0 )
                tmp << componentFlatList[ii].m_NumRef;
            else
                tmp = wxT( "?" );

            msg.Printf( _( "Error: symbol %s%s unit %d and symbol has only %d units defined\n" ),
                        GetChars( componentFlatList[ii].GetRef() ),
                        GetChars( tmp ),
                        componentFlatList[ii].m_Unit,
                        componentFlatList[ii].GetLibPart()->GetUnitCount() );

            aReporter.Report( msg, REPORTER::RPT_ERROR );
            error++;
            break;
        }
    }

    if( error )
        return error;

    // count the duplicated elements (if all are annotated)
    int imax = componentFlatList.size() - 1;

    for( int ii = 0; (ii < imax) && (error < 4); ii++ )
    {
        msg.Empty();
        tmp.Empty();

        if(  ( componentFlatList[ii].CompareRef( componentFlatList[ii + 1] ) != 0 )
          || ( componentFlatList[ii].m_NumRef != componentFlatList[ii + 1].m_NumRef )  )
            continue;

        // Same reference found. If same unit, error!
        if( componentFlatList[ii].m_Unit == componentFlatList[ii + 1].m_Unit )
        {
            if( componentFlatList[ii].m_NumRef >= 0 )
                tmp << componentFlatList[ii].m_NumRef;
            else
                tmp = wxT( "?" );

            if( ( componentFlatList[ii].m_Unit > 0 )
             && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) )
            {
                msg.Printf( _( "Multiple item %s%s (unit %d)\n" ),
                            GetChars( componentFlatList[ii].GetRef() ),
                            GetChars( tmp ),
                            componentFlatList[ii].m_Unit );
            }
            else
            {
                msg.Printf( _( "Multiple item %s%s\n" ),
                            GetChars( componentFlatList[ii].GetRef() ),
                            GetChars( tmp ) );
            }

            aReporter.Report( msg, REPORTER::RPT_ERROR );
            error++;
            continue;
        }

        /* Test error if units are different but number of parts per package
         * too high (ex U3 ( 1 part) and we find U3B this is an error) */
        if(  componentFlatList[ii].GetLibPart()->GetUnitCount()
          != componentFlatList[ii + 1].GetLibPart()->GetUnitCount()  )
        {
            if( componentFlatList[ii].m_NumRef >= 0 )
                tmp << componentFlatList[ii].m_NumRef;
            else
                tmp = wxT( "?" );

            if( ( componentFlatList[ii].m_Unit > 0 )
             && ( componentFlatList[ii].m_Unit < 0x7FFFFFFF ) )
            {
                msg.Printf( _( "Multiple item %s%s (unit %d)\n" ),
                            GetChars( componentFlatList[ii].GetRef() ),
                            GetChars( tmp ),
                            componentFlatList[ii].m_Unit );
            }
            else
            {
                msg.Printf( _( "Multiple item %s%s\n" ),
                            GetChars( componentFlatList[ii].GetRef() ),
                            GetChars( tmp ) );
            }

            aReporter.Report( msg, REPORTER::RPT_ERROR );
            error++;
        }

        // Error if values are different between units, for the same reference
        int next = ii + 1;

        if( componentFlatList[ii].CompareValue( componentFlatList[next] ) != 0 )
        {
            msg.Printf( _( "Different values for %s%d%s (%s) and %s%d%s (%s)" ),
                        GetChars( componentFlatList[ii].GetRef() ),
                        componentFlatList[ii].m_NumRef,
                        GetChars( LIB_PART::SubReference(
                                  componentFlatList[ii].m_Unit ) ),
                        GetChars( componentFlatList[ii].m_Value->GetText() ),
                        GetChars( componentFlatList[next].GetRef() ),
                        componentFlatList[next].m_NumRef,
                        GetChars( LIB_PART::SubReference(
                                  componentFlatList[next].m_Unit ) ),
                        GetChars( componentFlatList[next].m_Value->GetText() ) );

            aReporter.Report( msg, REPORTER::RPT_ERROR );
            error++;
        }
    }

    // count the duplicated time stamps
    SortByTimeStamp();

    for( int ii = 0; ( ii < imax ) && ( error < 4 ); ii++ )
    {
        if(  ( componentFlatList[ii].m_TimeStamp != componentFlatList[ii + 1].m_TimeStamp )
          || ( componentFlatList[ii].GetSheetPath() != componentFlatList[ii + 1].GetSheetPath() )  )
            continue;

        // Same time stamp found.
        wxString full_path;

        full_path.Printf( wxT( "%s%8.8X" ),
                          GetChars( componentFlatList[ii].GetSheetPath().Path() ),
                          componentFlatList[ii].m_TimeStamp );

        msg.Printf( _( "Duplicate time stamp (%s) for %s%d and %s%d" ),
                    GetChars( full_path ),
                    GetChars( componentFlatList[ii].GetRef() ), componentFlatList[ii].m_NumRef,
                    GetChars( componentFlatList[ii + 1].GetRef() ),
                    componentFlatList[ii + 1].m_NumRef );

        aReporter.Report( msg, REPORTER::RPT_WARNING );
        error++;
    }

    return error;
}
bool DIALOG_GEN_MODULE_POSITION::CreateFiles()
{
    BOARD * brd = m_parent->GetBoard();
    wxFileName  fn;
    wxString    msg;
    bool singleFile = OneFileOnly();
    int fullcount = 0;

    // Count the footprints to place, do not yet create a file
    int fpcount = m_parent->DoGenFootprintsPositionFile( wxEmptyString, UnitsMM(),
                  ForceAllSmd(), 2 );
    if( fpcount == 0)
    {
        wxMessageBox( _( "No modules for automated placement." ) );
        return false;
    }

    // Create output directory if it does not exist (also transform it in
    // absolute form). Bail if it fails
    wxFileName  outputDir = wxFileName::DirName( m_plotOpts.GetOutputDirectory() );
    wxString    boardFilename = m_parent->GetBoard()->GetFileName();

    m_reporter = &m_messagesPanel->Reporter();

    if( !EnsureFileDirectoryExists( &outputDir, boardFilename, m_reporter ) )
    {
        msg.Printf( _( "Could not write plot files to folder \"%s\"." ),
                    GetChars( outputDir.GetPath() ) );
        DisplayError( this, msg );
        return false;
    }

    fn = m_parent->GetBoard()->GetFileName();
    fn.SetPath( outputDir.GetPath() );

    // Create the the Front or Top side placement file,
    // or the single file
    int side = 1;

    if( singleFile )
    {
        side = 2;
        fn.SetName( fn.GetName() + wxT( "-" ) + wxT("all") );
    }
    else
        fn.SetName( fn.GetName() + wxT( "-" ) + frontSideName );

    fn.SetExt( FootprintPlaceFileExtension );

    fpcount = m_parent->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(),
              ForceAllSmd(), side );
    if( fpcount < 0 )
    {
        msg.Printf( _( "Unable to create '%s'." ), GetChars( fn.GetFullPath() ) );
        wxMessageBox( msg );
        m_reporter->Report( msg, REPORTER::RPT_ERROR );
        return false;
    }

    if( singleFile  )
        msg.Printf( _( "Place file: '%s'." ), GetChars( fn.GetFullPath() ) );
    else
        msg.Printf( _( "Front side (top side) place file: '%s'." ),
                    GetChars( fn.GetFullPath() ) );
    m_reporter->Report( msg, REPORTER::RPT_INFO );

    msg.Printf( _( "Component count: %d." ), fpcount );
    m_reporter->Report( msg, REPORTER::RPT_INFO );

    if( singleFile  )
    {
        m_reporter->Report( _( "Componment Placement File generation OK." ), REPORTER::RPT_ACTION );
        return true;
    }

    // Create the Back or Bottom side placement file
    fullcount = fpcount;
    side = 0;
    fn = brd->GetFileName();
    fn.SetPath( outputDir.GetPath() );
    fn.SetName( fn.GetName() + wxT( "-" ) + backSideName );
    fn.SetExt( wxT( "pos" ) );

    fpcount = m_parent->DoGenFootprintsPositionFile( fn.GetFullPath(), UnitsMM(),
              ForceAllSmd(), side );

    if( fpcount < 0 )
    {
        msg.Printf( _( "Unable to create file '%s'." ), GetChars( fn.GetFullPath() ) );
        m_reporter->Report( msg, REPORTER::RPT_ERROR );
        wxMessageBox( msg );
        return false;
    }

    // Display results
    if( !singleFile )
    {
        msg.Printf( _( "Back side (bottom side) place file: '%s'." ), GetChars( fn.GetFullPath() ) );
        m_reporter->Report( msg, REPORTER::RPT_INFO );

        msg.Printf( _( "Component count: %d." ), fpcount );

        m_reporter->Report( msg, REPORTER::RPT_INFO );
    }

    if( !singleFile )
    {
        fullcount += fpcount;
        msg.Printf( _( "Full component count: %d\n" ), fullcount );
        m_reporter->Report( msg, REPORTER::RPT_INFO );
    }

    m_reporter->Report( _( "Componment Placement File generation OK." ), REPORTER::RPT_ACTION );

    return true;
}
示例#6
0
void SCH_EDIT_FRAME::AnnotateComponents( bool              aAnnotateSchematic,
                                         ANNOTATE_ORDER_T  aSortOption,
                                         ANNOTATE_OPTION_T aAlgoOption,
                                         int               aStartNumber,
                                         bool              aResetAnnotation,
                                         bool              aRepairTimestamps,
                                         bool              aLockUnits,
                                         REPORTER&         aReporter )
{
    SCH_REFERENCE_LIST references;

    SCH_SCREENS screens;

    // Build the sheet list.
    SCH_SHEET_LIST sheets( g_RootSheet );

    // Map of locked components
    SCH_MULTI_UNIT_REFERENCE_MAP lockedComponents;

    // Map of previous annotation for building info messages
    std::map<timestamp_t, wxString> previousAnnotation;

    // Test for and replace duplicate time stamps in components and sheets.  Duplicate
    // time stamps can happen with old schematics, schematic conversions, or manual
    // editing of files.
    if( aRepairTimestamps )
    {
        int count = screens.ReplaceDuplicateTimeStamps();

        if( count )
        {
            wxString msg;
            msg.Printf( _( "%d duplicate time stamps were found and replaced." ), count );
            aReporter.ReportTail( msg, REPORTER::RPT_WARNING );
        }
    }

    // If units must be locked, collect all the sets that must be annotated together.
    if( aLockUnits )
    {
        if( aAnnotateSchematic )
        {
            sheets.GetMultiUnitComponents( lockedComponents );
        }
        else
        {
            m_CurrentSheet->GetMultiUnitComponents( lockedComponents );
        }
    }

    // Store previous annotations for building info messages
    mapExistingAnnotation( previousAnnotation );

    // If it is an annotation for all the components, reset previous annotation.
    if( aResetAnnotation )
        DeleteAnnotation( !aAnnotateSchematic );

    // Set sheet number and number of sheets.
    SetSheetNumberAndCount();

    // Build component list
    if( aAnnotateSchematic )
    {
        sheets.GetComponents( references );
    }
    else
    {
        m_CurrentSheet->GetComponents( references );
    }

    // Break full components reference in name (prefix) and number:
    // example: IC1 become IC, and 1
    references.SplitReferences();

    switch( aSortOption )
    {
    default:
    case SORT_BY_X_POSITION:
        references.SortByXCoordinate();
        break;

    case SORT_BY_Y_POSITION:
        references.SortByYCoordinate();
        break;
    }

    bool useSheetNum = false;
    int idStep = 100;

    switch( aAlgoOption )
    {
    default:
    case INCREMENTAL_BY_REF:
        break;

    case SHEET_NUMBER_X_100:
        useSheetNum = true;
        break;

    case SHEET_NUMBER_X_1000:
        useSheetNum = true;
        idStep = 1000;
        break;
    }

    // Recalculate and update reference numbers in schematic
    references.Annotate( useSheetNum, idStep, aStartNumber, lockedComponents );
    references.UpdateAnnotation();

    for( size_t i = 0; i < references.GetCount(); i++ )
    {
        SCH_COMPONENT* comp = references[ i ].GetComp();
        wxString       prevRef = previousAnnotation[ comp->GetTimeStamp() ];
        wxString       newRef  = comp->GetField( REFERENCE )->GetFullyQualifiedText();
        wxString       msg;

        if( prevRef.Length() )
        {
            if( newRef == prevRef )
                continue;

            if( comp->GetUnitCount() > 1 )
                msg.Printf( _( "Updated %s (unit %s) from %s to %s" ),
                            GetChars( comp->GetField( VALUE )->GetShownText() ),
                            LIB_PART::SubReference( comp->GetUnit(), false ),
                            GetChars( prevRef ),
                            GetChars( newRef ) );
            else
                msg.Printf( _( "Updated %s from %s to %s" ),
                            GetChars( comp->GetField( VALUE )->GetShownText() ),
                            GetChars( prevRef ),
                            GetChars( newRef ) );
        }
        else
        {
            if( comp->GetUnitCount() > 1 )
                msg.Printf( _( "Annotated %s (unit %s) as %s" ),
                            GetChars( comp->GetField( VALUE )->GetShownText() ),
                            LIB_PART::SubReference( comp->GetUnit(), false ),
                            GetChars( newRef ) );
            else
                msg.Printf( _( "Annotated %s as %s" ),
                            GetChars( comp->GetField( VALUE )->GetShownText() ),
                            GetChars( newRef ) );
        }

        aReporter.Report( msg, REPORTER::RPT_ACTION );
    }

    // Final control (just in case ... ).
    if( !CheckAnnotate( aReporter, !aAnnotateSchematic ) )
        aReporter.ReportTail( _( "Annotation complete." ), REPORTER::RPT_ACTION );

    // Update on screen references, that can be modified by previous calculations:
    m_CurrentSheet->UpdateAllScreenReferences();
    SetSheetNumberAndCount();

    SyncView();
    GetCanvas()->Refresh();
    OnModify();
}