Commit 78670eeb authored by jean-pierre charras's avatar jean-pierre charras
Browse files

Pcbnew: Fix a crash on exit when an item was previously deleted. Fix not...

Pcbnew: Fix a crash on exit when an item was previously deleted. Fix not working footprint exchange functions
parent 44bb2e6d
Loading
Loading
Loading
Loading
+10 −0
Original line number Original line Diff line number Diff line
@@ -127,6 +127,16 @@ public:


    ~PCB_BASE_FRAME();
    ~PCB_BASE_FRAME();


    /**
     * Function LoadFootprint
     * attempts to load \a aFootprintId from the footprint library table.
     *
     * @param aFootprintId is the #FPID of component footprint to load.
     * @return the #MODULE if found or NULL if \a aFootprintId not found in any of the
     *         libraries in #m_footprintLibTable.
     */
    MODULE* LoadFootprint( const FPID& aFootprintId );

    /**
    /**
     * Function GetBoardBoundingBox
     * Function GetBoardBoundingBox
     * calculates the bounding box containing all board items (or board edge segments).
     * calculates the bounding box containing all board items (or board edge segments).
+36 −1
Original line number Original line Diff line number Diff line
@@ -336,7 +336,22 @@ MODULE* PCB_BASE_FRAME::loadFootprintFromLibrary( const wxString& aLibraryPath,
    {
    {
        PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) );
        PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) );


        wxString libPath = wxGetApp().FindLibraryPath( aLibraryPath );
        // Ensure the library name has the right extension
        // (sometimes the name is given without ext)
        wxString libname = aLibraryPath;

        if( !libname.EndsWith( wxT(".") + LegacyFootprintLibPathExtension) )
            libname <<  wxT(".") << LegacyFootprintLibPathExtension;

        wxString libPath = wxGetApp().FindLibraryPath( libname );

        if( libPath.IsEmpty() )
        {
            wxString msg = wxString::Format( _( "Library '%s' not found." ),
                                             libname.GetData() );
            DisplayError( NULL, msg );
            return NULL;
        }


        MODULE* footprint = pi->FootprintLoad( libPath, aFootprintName );
        MODULE* footprint = pi->FootprintLoad( libPath, aFootprintName );


@@ -429,6 +444,26 @@ MODULE* PCB_BASE_FRAME::loadFootprintFromLibraries(
    return NULL;
    return NULL;
}
}


/* attempts to load aFootprintId from the footprint library table.
 * return the #MODULE if found or NULL if not found or error.
 */
MODULE* PCB_BASE_FRAME::LoadFootprint( const FPID& aFootprintId )
{
    MODULE* module = NULL;

    try
    {
        module = loadFootprint( aFootprintId );
    }
    catch( IO_ERROR ioe )
    {
        wxLogDebug( wxT( "An error occurred attemping to load footprint '%s'.\n\nError: %s" ),
                    aFootprintId.Format().c_str(), GetChars( ioe.errorText ) );
    }

    return module;
}



MODULE* PCB_BASE_FRAME::loadFootprint( const FPID& aFootprintId )
MODULE* PCB_BASE_FRAME::loadFootprint( const FPID& aFootprintId )
    throw( IO_ERROR, PARSE_ERROR )
    throw( IO_ERROR, PARSE_ERROR )
+7 −3
Original line number Original line Diff line number Diff line
@@ -598,6 +598,10 @@ void PCB_EDIT_FRAME::OnCloseWindow( wxCloseEvent& Event )


    SaveSettings();
    SaveSettings();


    // Delete board structs and undo/redo lists, to avoid crash on exit
    // when deleting some structs (mainly in undo/redo lists) too late
    Clear_Pcb( false );

    // do not show the window because ScreenPcb will be deleted and we do not
    // do not show the window because ScreenPcb will be deleted and we do not
    // want any paint event
    // want any paint event
    Show( false );
    Show( false );
+149 −151
Original line number Original line Diff line number Diff line
@@ -5,8 +5,10 @@
/*
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 *
 * Copyright (C) 2012 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
 * Copyright (C) 2013 Jean-Pierre Charras, jean-pierre.charras@ujf-grenoble.fr
 * Copyright (C) 1992-2012 KiCad Developers, see AUTHORS.txt for contributors.
 * Copyright (C) 2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
 * Copyright (C) 2013 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 1992-2013 KiCad Developers, see AUTHORS.txt for contributors.
 *
 *
 * This program is free software; you can redistribute it and/or
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * modify it under the terms of the GNU General Public License
@@ -43,15 +45,15 @@


static char*  quiet_gcc_4_4_3;      // GCC 4.4.3 and next ..
static char*  quiet_gcc_4_4_3;      // GCC 4.4.3 and next ..


int s_SelectionMode = 0;    // Remember the last exchange option, when exit dialog.
static bool RecreateCmpFile( BOARD * aBrd, const wxString& aFullCmpFileName );




class DIALOG_EXCHANGE_MODULE : public DIALOG_EXCHANGE_MODULE_BASE
class DIALOG_EXCHANGE_MODULE : public DIALOG_EXCHANGE_MODULE_BASE
{
{
private:
private:

    PCB_EDIT_FRAME* m_parent;
    PCB_EDIT_FRAME* m_Parent;
    MODULE*         m_currentModule;
    MODULE*         m_CurrentModule;
    static int      m_selectionMode;    // Remember the last exchange option


public:
public:
    DIALOG_EXCHANGE_MODULE( PCB_EDIT_FRAME* aParent, MODULE* aModule );
    DIALOG_EXCHANGE_MODULE( PCB_EDIT_FRAME* aParent, MODULE* aModule );
@@ -62,26 +64,27 @@ private:
    void OnOkClick( wxCommandEvent& event );
    void OnOkClick( wxCommandEvent& event );
    void OnQuit( wxCommandEvent& event );
    void OnQuit( wxCommandEvent& event );
    void BrowseAndSelectFootprint( wxCommandEvent& event );
    void BrowseAndSelectFootprint( wxCommandEvent& event );
    void Init();
    void init();


    void Change_Current_Module();
    void ChangeCurrentFootprint();
    void Change_ModuleId( bool aUseValue );
    void ChangeSameFootprints( bool aUseValue );
    void Change_ModuleAll();
    void ChangeAllFootprints();
    int  Maj_ListeCmp( const wxString& reference, const FPID& old_name,
    int  Maj_ListeCmp( const wxString& aReference, const FPID& aOldFootprintFPID,
                       const FPID& new_name, bool ShowError );
                       const FPID& aNewFootprintFPID, bool aShowError );
    bool Change_1_Module( MODULE*            Module,
    bool Change_1_Module( MODULE*            aModule,
                          const FPID&        new_module,
                          const FPID&        aNewFootprintFPID,
                          PICKED_ITEMS_LIST* aUndoPickList,
                          PICKED_ITEMS_LIST* aUndoPickList,
                          bool               ShowError );
                          bool               eShowError );
};
};


int DIALOG_EXCHANGE_MODULE::m_selectionMode = 0;


DIALOG_EXCHANGE_MODULE::DIALOG_EXCHANGE_MODULE( PCB_EDIT_FRAME* parent, MODULE* Module ) :
DIALOG_EXCHANGE_MODULE::DIALOG_EXCHANGE_MODULE( PCB_EDIT_FRAME* parent, MODULE* Module ) :
    DIALOG_EXCHANGE_MODULE_BASE( parent )
    DIALOG_EXCHANGE_MODULE_BASE( parent )
{
{
    m_Parent = parent;
    m_parent = parent;
    m_CurrentModule = Module;
    m_currentModule = Module;
    Init();
    init();
    GetSizer()->Fit( this );
    GetSizer()->Fit( this );
    GetSizer()->SetSizeHints( this );
    GetSizer()->SetSizeHints( this );
}
}
@@ -97,19 +100,19 @@ void PCB_EDIT_FRAME::InstallExchangeModuleFrame( MODULE* Module )


void DIALOG_EXCHANGE_MODULE::OnQuit( wxCommandEvent& event )
void DIALOG_EXCHANGE_MODULE::OnQuit( wxCommandEvent& event )
{
{
    s_SelectionMode = m_Selection->GetSelection();
    m_selectionMode = m_Selection->GetSelection();
    EndModal( 0 );
    EndModal( 0 );
}
}




void DIALOG_EXCHANGE_MODULE::Init()
void DIALOG_EXCHANGE_MODULE::init()
{
{
    SetFocus();
    SetFocus();


    m_OldModule->AppendText( FROM_UTF8( m_CurrentModule->GetFPID().Format().c_str() ) );
    m_OldModule->AppendText( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) );
    m_NewModule->AppendText( FROM_UTF8( m_CurrentModule->GetFPID().Format().c_str() ) );
    m_NewModule->AppendText( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) );
    m_OldValue->AppendText( m_CurrentModule->GetValue() );
    m_OldValue->AppendText( m_currentModule->GetValue() );
    m_Selection->SetSelection( s_SelectionMode );
    m_Selection->SetSelection( m_selectionMode );


    // Enable/disable widgets:
    // Enable/disable widgets:
    wxCommandEvent event;
    wxCommandEvent event;
@@ -119,23 +122,23 @@ void DIALOG_EXCHANGE_MODULE::Init()


void DIALOG_EXCHANGE_MODULE::OnOkClick( wxCommandEvent& event )
void DIALOG_EXCHANGE_MODULE::OnOkClick( wxCommandEvent& event )
{
{
    s_SelectionMode = m_Selection->GetSelection();
    m_selectionMode = m_Selection->GetSelection();
    switch( m_Selection->GetSelection() )
    switch( m_Selection->GetSelection() )
    {
    {
    case 0:
    case 0:
        Change_Current_Module();
        ChangeCurrentFootprint();
        break;
        break;


    case 1:
    case 1:
        Change_ModuleId( false );
        ChangeSameFootprints( false );
        break;
        break;


    case 2:
    case 2:
        Change_ModuleId( true );
        ChangeSameFootprints( true );
        break;
        break;


    case 3:
    case 3:
        Change_ModuleAll();
        ChangeAllFootprints();
        break;
        break;
    }
    }
}
}
@@ -167,10 +170,10 @@ void DIALOG_EXCHANGE_MODULE::OnSelectionClicked( wxCommandEvent& event )
 * If ShowError! = 0 displays error message if the file. Cmp is not found.
 * If ShowError! = 0 displays error message if the file. Cmp is not found.
 * Return 1 if error
 * Return 1 if error
 */
 */
int DIALOG_EXCHANGE_MODULE::Maj_ListeCmp( const wxString& reference,
int DIALOG_EXCHANGE_MODULE::Maj_ListeCmp( const wxString& aReference,
                                          const FPID&     old_name,
                                          const FPID&     aOldFootprintFPID,
                                          const FPID&     new_name,
                                          const FPID&     aNewFootprintFPID,
                                          bool            ShowError )
                                          bool            aShowError )
{
{
    wxFileName  fn;
    wxFileName  fn;
    wxFileName  tmpFileName;
    wxFileName  tmpFileName;
@@ -178,18 +181,18 @@ int DIALOG_EXCHANGE_MODULE::Maj_ListeCmp( const wxString& reference,
    char        line[1024];
    char        line[1024];
    wxString    msg;
    wxString    msg;


    if( old_name == new_name )
    if( aOldFootprintFPID == aNewFootprintFPID )
        return 0;
        return 0;


    // Build CMP file name by changing the extension of NetList filename
    // Build CMP file name by changing the extension of NetList filename
    fn = m_Parent->GetBoard()->GetFileName();
    fn = m_parent->GetBoard()->GetFileName();
    fn.SetExt( ComponentFileExtension );
    fn.SetExt( ComponentFileExtension );


    FichCmp = wxFopen( fn.GetFullPath(), wxT( "rt" ) );
    FichCmp = wxFopen( fn.GetFullPath(), wxT( "rt" ) );


    if( FichCmp == NULL )
    if( FichCmp == NULL )
    {
    {
        if( ShowError )
        if( aShowError )
        {
        {
            msg.Printf( _( "file <%s> not found" ), GetChars( fn.GetFullPath() ) );
            msg.Printf( _( "file <%s> not found" ), GetChars( fn.GetFullPath() ) );
            m_WinMessages->AppendText( msg );
            m_WinMessages->AppendText( msg );
@@ -204,7 +207,7 @@ int DIALOG_EXCHANGE_MODULE::Maj_ListeCmp( const wxString& reference,


    if( NewFile == NULL )
    if( NewFile == NULL )
    {
    {
        if( ShowError )
        if( aShowError )
        {
        {
            msg.Printf( _( "Unable to create file <%s>" ),
            msg.Printf( _( "Unable to create file <%s>" ),
                        GetChars( tmpFileName.GetFullPath() ) );
                        GetChars( tmpFileName.GetFullPath() ) );
@@ -228,7 +231,7 @@ int DIALOG_EXCHANGE_MODULE::Maj_ListeCmp( const wxString& reference,
            strcpy( buf, line + 12 );
            strcpy( buf, line + 12 );
            strtok( buf, ";\n\r" );
            strtok( buf, ";\n\r" );


            if( stricmp( buf, TO_UTF8( reference ) ) == 0 )
            if( stricmp( buf, TO_UTF8( aReference ) ) == 0 )
            {
            {
                start_descr = true;
                start_descr = true;
            }
            }
@@ -241,7 +244,7 @@ int DIALOG_EXCHANGE_MODULE::Maj_ListeCmp( const wxString& reference,


        if( start_descr && strnicmp( line, "IdModule", 8 ) == 0 )
        if( start_descr && strnicmp( line, "IdModule", 8 ) == 0 )
        {
        {
            sprintf( line + 8, "  = %s;\n", new_name.Format().c_str() );
            sprintf( line + 8, "  = %s;\n", aNewFootprintFPID.Format().c_str() );


            msg = wxT( " * in <" ) + fn.GetFullPath() + wxT( ">.\n" );
            msg = wxT( " * in <" ) + fn.GetFullPath() + wxT( ">.\n" );
            m_WinMessages->AppendText( msg );
            m_WinMessages->AppendText( msg );
@@ -260,14 +263,13 @@ int DIALOG_EXCHANGE_MODULE::Maj_ListeCmp( const wxString& reference,
}
}




/* Change the module at the current cursor position.
/* Change the current footprint at the current cursor position.
 * Retains the following:
 * Retains the following:
 * - Same direction
 * - position, orientation and side
 * - Same position
 * - value and ref
 * - Same text value and ref
 * - pads net names
 * - Same NetNames for pads same name
 */
 */
void DIALOG_EXCHANGE_MODULE::Change_Current_Module()
void DIALOG_EXCHANGE_MODULE::ChangeCurrentFootprint()
{
{
    wxString newmodulename = m_NewModule->GetValue();
    wxString newmodulename = m_NewModule->GetValue();


@@ -276,31 +278,31 @@ void DIALOG_EXCHANGE_MODULE::Change_Current_Module()


    PICKED_ITEMS_LIST pickList;
    PICKED_ITEMS_LIST pickList;


    if( Change_1_Module( m_CurrentModule, newmodulename, &pickList, true ) )
    if( Change_1_Module( m_currentModule, newmodulename, &pickList, true ) )
    {
    {
        if( m_Parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) )
        if( m_parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) )
            m_Parent->Compile_Ratsnest( NULL, true );
            m_parent->Compile_Ratsnest( NULL, true );


        m_Parent->GetCanvas()->Refresh();
        m_parent->GetCanvas()->Refresh();
    }
    }


    if( pickList.GetCount() )
    if( pickList.GetCount() )
        m_Parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED );
        m_parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED );
}
}




/*
/*
 * Change of all modules with the same name as that lib
 * Change all footprints having the same fpid by a new one from lib
 * Retains:
 * Retains:
 * - Same direction
 * - direction, position, side
 * - Same position
 * - value and ref
 * - Same text value and ref
 * - pads net names
 * - Same NetNames for pads same name
 * Note: m_currentModule is no longer the current footprint
 * And replacing the old module with the new module
 * Note: m_CurrentModule no longer on the module reference
 * since it has been changed!
 * since it has been changed!
 * if aUseValue is true, footprints having the same fpid should
 * also have the same value
 */
 */
void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue )
void DIALOG_EXCHANGE_MODULE::ChangeSameFootprints( bool aUseValue )
{
{
    wxString msg;
    wxString msg;
    MODULE*  Module, * PtBack;
    MODULE*  Module, * PtBack;
@@ -311,22 +313,22 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue )
    bool     check_module_value = false;
    bool     check_module_value = false;
    int      ShowErr = 3;           // Post 3 error messages max.
    int      ShowErr = 3;           // Post 3 error messages max.


    if( m_Parent->GetBoard()->m_Modules == NULL )
    if( m_parent->GetBoard()->m_Modules == NULL )
        return;
        return;


    if( newmodulename == wxEmptyString )
    if( newmodulename == wxEmptyString )
        return;
        return;


    lib_reference = m_CurrentModule->GetFPID();
    lib_reference = m_currentModule->GetFPID();


    if( aUseValue )
    if( aUseValue )
    {
    {
        check_module_value = true;
        check_module_value = true;
        value = m_CurrentModule->GetValue();
        value = m_currentModule->GetValue();
        msg.Printf( _( "Change modules %s -> %s (for value = %s)?" ),
        msg.Printf( _( "Change modules %s -> %s (for value = %s)?" ),
                    GetChars( FROM_UTF8( m_CurrentModule->GetFPID().Format().c_str() ) ),
                    GetChars( FROM_UTF8( m_currentModule->GetFPID().Format().c_str() ) ),
                    GetChars( newmodulename ),
                    GetChars( newmodulename ),
                    GetChars( m_CurrentModule->GetValue() ) );
                    GetChars( m_currentModule->GetValue() ) );
    }
    }
    else
    else
    {
    {
@@ -338,15 +340,15 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue )
    if( !IsOK( this, msg ) )
    if( !IsOK( this, msg ) )
        return;
        return;


    /* The change is done from the last module for the routine
    /* The change is done from the last module because
     * Change_1_Module () modifies the last module in the list.
     * Change_1_Module () modifies the last item in the list.
     */
     */
    PICKED_ITEMS_LIST pickList;
    PICKED_ITEMS_LIST pickList;


    /* note: for the first module in chain (the last here), Module->Back()
    /* note: for the first module in chain (the last here), Module->Back()
     * points the board or is NULL
     * points the board or is NULL
     */
     */
    Module = m_Parent->GetBoard()->m_Modules.GetLast();
    Module = m_parent->GetBoard()->m_Modules.GetLast();


    for( ; Module && ( Module->Type() == PCB_MODULE_T ); Module = PtBack )
    for( ; Module && ( Module->Type() == PCB_MODULE_T ); Module = PtBack )
    {
    {
@@ -369,32 +371,31 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleId( bool aUseValue )


    if( change )
    if( change )
    {
    {
        if( m_Parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) )
        if( m_parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) )
            m_Parent->Compile_Ratsnest( NULL, true );
            m_parent->Compile_Ratsnest( NULL, true );


        m_Parent->GetCanvas()->Refresh();
        m_parent->GetCanvas()->Refresh();
    }
    }


    if( pickList.GetCount() )
    if( pickList.GetCount() )
        m_Parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED );
        m_parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED );
}
}




/*
/*
 * Change all modules with module of the same name in library.
 * Change all modules with module of the same name in library.
 * Maintains:
 * Maintains:
 * - Same direction
 * - direction, position, side
 * - Same position
 * - value and ref
 * - Same text value and ref
 * - pads net names
 * - Same NetNames for pads same name
 */
 */
void DIALOG_EXCHANGE_MODULE::Change_ModuleAll()
void DIALOG_EXCHANGE_MODULE::ChangeAllFootprints()
{
{
    MODULE* Module, * PtBack;
    MODULE* Module, * PtBack;
    bool    change  = false;
    bool    change  = false;
    int     ShowErr = 3;              // Post 3 error messages max.
    int     ShowErr = 3;              // Post 3 error max.


    if( m_Parent->GetBoard()->m_Modules == NULL )
    if( m_parent->GetBoard()->m_Modules == NULL )
        return;
        return;


    if( !IsOK( this, _( "Change ALL modules ?" ) ) )
    if( !IsOK( this, _( "Change ALL modules ?" ) ) )
@@ -408,7 +409,7 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleAll()
    /* note: for the first module in chain (the last here), Module->Back()
    /* note: for the first module in chain (the last here), Module->Back()
     * points the board or is NULL
     * points the board or is NULL
     */
     */
    Module = m_Parent->GetBoard()->m_Modules.GetLast();
    Module = m_parent->GetBoard()->m_Modules.GetLast();


    for( ; Module && ( Module->Type() == PCB_MODULE_T ); Module = PtBack )
    for( ; Module && ( Module->Type() == PCB_MODULE_T ); Module = PtBack )
    {
    {
@@ -422,72 +423,74 @@ void DIALOG_EXCHANGE_MODULE::Change_ModuleAll()


    if( change )
    if( change )
    {
    {
        if( m_Parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) )
        if( m_parent->GetBoard()->IsElementVisible( RATSNEST_VISIBLE ) )
            m_Parent->Compile_Ratsnest( NULL, true );
            m_parent->Compile_Ratsnest( NULL, true );


        m_Parent->GetCanvas()->Refresh();
        m_parent->GetCanvas()->Refresh();
    }
    }


    if( pickList.GetCount() )
    if( pickList.GetCount() )
        m_Parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED );
        m_parent->SaveCopyInUndoList( pickList, UR_UNSPECIFIED );
}
}




/*
/*
 * Change the number empr module with the module name new_module
 * Change aModule to a new, fresh one from lib
 * - Same direction
 * Retains
 * - Same position
 * - direction, position, side
 * - Same text value and ref
 * - value and ref
 * - Same NetNames for pads same name
 * - pads net names
 * Returns:
 * Returns: false if no change (if the new module is not found)
 * False if no change (if the new module is not free)
 * true if OK
 * True if OK
 * Ratsnest must be recalculated after module exchange
 */
 */
bool DIALOG_EXCHANGE_MODULE::Change_1_Module( MODULE*            Module,
bool DIALOG_EXCHANGE_MODULE::Change_1_Module( MODULE*            aModule,
                                              const FPID&        new_module,
                                              const FPID&        aNewFootprintFPID,
                                              PICKED_ITEMS_LIST* aUndoPickList,
                                              PICKED_ITEMS_LIST* aUndoPickList,
                                              bool               ShowError )
                                              bool               aShowError )
{
{
    FPID namecmp, oldnamecmp;
    MODULE*  newModule;
    MODULE*  NewModule;
    wxString line;
    wxString line;


    if( Module == NULL )
    if( aModule == NULL )
        return false;
        return false;


    wxBusyCursor dummy;
    wxBusyCursor dummy;


    // Copy parameters from the old module.
    // Copy parameters from the old module.
    oldnamecmp = Module->GetFPID();
    FPID  oldFootprintFPID = aModule->GetFPID();
    namecmp    = new_module;


    // Load module.
    // Load module.
    line.Printf( _( "Change module %s (from %s)  " ),
    line.Printf( _( "Change module %s (from %s)  " ),
                 GetChars( Module->GetReference() ),
                 GetChars( aModule->GetReference() ),
                 oldnamecmp.Format().c_str() );
                 oldFootprintFPID.Format().c_str() );
    m_WinMessages->AppendText( line );
    m_WinMessages->AppendText( line );


    NewModule = m_Parent->GetModuleLibrary( FROM_UTF8( namecmp.GetLibNickname().c_str() ),
    wxString moduleName = FROM_UTF8( aNewFootprintFPID.GetFootprintName().c_str() );
                                            FROM_UTF8( namecmp.GetFootprintName().c_str() ),
    wxString libName = FROM_UTF8( aNewFootprintFPID.GetLibNickname().c_str() );
                                            ShowError );


    if( NewModule == NULL )  // New module not found, redraw the old one.
#if !defined( USE_FP_LIB_TABLE )
    newModule = m_parent->GetModuleLibrary( libName, moduleName, aShowError );
#else
    newModule = m_parent->LoadFootprint( aNewFootprintFPID );
#endif

    if( newModule == NULL )  // New module not found, redraw the old one.
    {
    {
        m_WinMessages->AppendText( wxT( "No\n" ) );
        m_WinMessages->AppendText( wxT( "No\n" ) );
        return false;
        return false;
    }
    }


    m_Parent->GetBoard()->Add( NewModule, ADD_APPEND );
    m_parent->GetBoard()->Add( newModule, ADD_APPEND );


    if( Module == m_CurrentModule )
    if( aModule == m_currentModule )
        m_CurrentModule = NewModule;
        m_currentModule = newModule;


    m_WinMessages->AppendText( wxT( "OK\n" ) );
    m_WinMessages->AppendText( wxT( "OK\n" ) );


    m_Parent->Exchange_Module( Module, NewModule, aUndoPickList );
    m_parent->Exchange_Module( aModule, newModule, aUndoPickList );


    Maj_ListeCmp( NewModule->GetReference(), oldnamecmp, namecmp, ShowError );
    Maj_ListeCmp( newModule->GetReference(),
                  oldFootprintFPID, aNewFootprintFPID, aShowError );


    return true;
    return true;
}
}
@@ -497,24 +500,13 @@ void PCB_EDIT_FRAME::Exchange_Module( MODULE* aOldModule,
                                      MODULE*            aNewModule,
                                      MODULE*            aNewModule,
                                      PICKED_ITEMS_LIST* aUndoPickList )
                                      PICKED_ITEMS_LIST* aUndoPickList )
{
{
    wxPoint oldpos;
    D_PAD*  pad, * old_pad;

    if( ( aOldModule->Type() != PCB_MODULE_T ) || ( aNewModule->Type() != PCB_MODULE_T ) )
    {
        wxMessageBox( wxT( "PCB_EDIT_FRAME::Exchange_Module() StuctType error" ) );
        return;
    }

    aNewModule->SetParent( GetBoard() );
    aNewModule->SetParent( GetBoard() );


    GetBoard()->m_Status_Pcb = 0;
    oldpos = GetCrossHairPosition();
    SetCrossHairPosition( aOldModule->GetPosition(), false );

    /* place module without ratsnest refresh: this will be made later
    /* place module without ratsnest refresh: this will be made later
     * when all modules are on board
     * when all modules are on board
     */
     */
    wxPoint oldpos = GetCrossHairPosition();
    SetCrossHairPosition( aOldModule->GetPosition(), false );
    PlaceModule( aNewModule, NULL, true );
    PlaceModule( aNewModule, NULL, true );
    SetCrossHairPosition( oldpos, false );
    SetCrossHairPosition( oldpos, false );


@@ -539,13 +531,11 @@ void PCB_EDIT_FRAME::Exchange_Module( MODULE* aOldModule,
    aNewModule->SetPath( aOldModule->GetPath() );
    aNewModule->SetPath( aOldModule->GetPath() );


    // Update pad netnames ( when possible)
    // Update pad netnames ( when possible)
    pad = aNewModule->Pads();
    for( D_PAD* pad = aNewModule->Pads(); pad != NULL; pad = pad->Next() )

    for( ; pad != NULL; pad = pad->Next() )
    {
    {
        pad->SetNetname( wxEmptyString );
        pad->SetNetname( wxEmptyString );
        pad->SetNet( 0 );
        pad->SetNet( 0 );
        old_pad = aOldModule->Pads();
        D_PAD*  old_pad = aOldModule->Pads();


        for( ; old_pad != NULL; old_pad = old_pad->Next() )
        for( ; old_pad != NULL; old_pad = old_pad->Next() )
        {
        {
@@ -583,8 +573,8 @@ void DIALOG_EXCHANGE_MODULE::BrowseAndSelectFootprint( wxCommandEvent& event )
{
{
    wxString newname;
    wxString newname;


    newname = m_Parent->SelectFootprint( m_Parent, wxEmptyString, wxEmptyString, wxEmptyString,
    newname = m_parent->SelectFootprint( m_parent, wxEmptyString, wxEmptyString, wxEmptyString,
                                         m_Parent->GetFootprintLibraryTable() );
                                         m_parent->GetFootprintLibraryTable() );


    if( newname != wxEmptyString )
    if( newname != wxEmptyString )
        m_NewModule->SetValue( newname );
        m_NewModule->SetValue( newname );
@@ -594,8 +584,6 @@ void DIALOG_EXCHANGE_MODULE::BrowseAndSelectFootprint( wxCommandEvent& event )
void PCB_EDIT_FRAME::RecreateCmpFileFromBoard( wxCommandEvent& aEvent )
void PCB_EDIT_FRAME::RecreateCmpFileFromBoard( wxCommandEvent& aEvent )
{
{
    wxFileName  fn;
    wxFileName  fn;
    FILE*       FichCmp;
    char        line[1024];
    MODULE*     Module = GetBoard()->m_Modules;
    MODULE*     Module = GetBoard()->m_Modules;
    wxString    msg;
    wxString    msg;
    wxString    wildcard;
    wxString    wildcard;
@@ -620,33 +608,43 @@ void PCB_EDIT_FRAME::RecreateCmpFileFromBoard( wxCommandEvent& aEvent )


    fn = dlg.GetPath();
    fn = dlg.GetPath();


    FichCmp = wxFopen( fn.GetFullPath(), wxT( "wt" ) );
    if( ! RecreateCmpFile( GetBoard(), fn.GetFullPath() ) )

    if( FichCmp == NULL )
    {
    {
        msg = _( "Unable to create file " ) + fn.GetFullPath();
        msg = _( "Unable to create file " ) + fn.GetFullPath();
        DisplayError( this, msg );
        DisplayError( this, msg );
        return;
        return;
    }
    }
}


    quiet_gcc_4_4_3 = fgets( line, sizeof(line), FichCmp );
bool RecreateCmpFile( BOARD * aBrd, const wxString& aFullCmpFileName )
    fprintf( FichCmp, "Cmp-Mod V01 Genere par PcbNew le %s\n", TO_UTF8( DateAndTime() ) );
{
    FILE* cmpFile;


    for( ; Module != NULL; Module = Module->Next() )
    cmpFile = wxFopen( aFullCmpFileName, wxT( "wt" ) );

    if( cmpFile == NULL )
        return false;

    fprintf( cmpFile, "Cmp-Mod V01 Genere par PcbNew le %s\n", TO_UTF8( DateAndTime() ) );

    MODULE* module = aBrd->m_Modules;
    for( ; module != NULL; module = module->Next() )
    {
    {
        fprintf( FichCmp, "\nBeginCmp\n" );
        fprintf( cmpFile, "\nBeginCmp\n" );
        fprintf( FichCmp, "TimeStamp = %8.8lX\n", Module->GetTimeStamp() );
        fprintf( cmpFile, "TimeStamp = %8.8lX\n", module->GetTimeStamp() );
        fprintf( FichCmp, "Path = %s\n", TO_UTF8( Module->GetPath() ) );
        fprintf( cmpFile, "Path = %s\n", TO_UTF8( module->GetPath() ) );
        fprintf( FichCmp, "Reference = %s;\n",
        fprintf( cmpFile, "Reference = %s;\n",
                 !Module->GetReference().IsEmpty() ?
                 !module->GetReference().IsEmpty() ?
                 TO_UTF8( Module->GetReference() ) : "[NoRef]" );
                 TO_UTF8( module->GetReference() ) : "[NoRef]" );
        fprintf( FichCmp, "ValeurCmp = %s;\n",
        fprintf( cmpFile, "ValeurCmp = %s;\n",
                 !Module->GetValue().IsEmpty() ?
                 !module->GetValue().IsEmpty() ?
                 TO_UTF8( Module->GetValue() ) : "[NoVal]" );
                 TO_UTF8( module->GetValue() ) : "[NoVal]" );
        fprintf( FichCmp, "IdModule  = %s;\n", Module->GetFPID().Format().c_str() );
        fprintf( cmpFile, "IdModule  = %s;\n", module->GetFPID().Format().c_str() );
        fprintf( FichCmp, "EndCmp\n" );
        fprintf( cmpFile, "EndCmp\n" );
    }
    }


    fprintf( FichCmp, "\nEndListe\n" );
    fprintf( cmpFile, "\nEndListe\n" );
    fclose( FichCmp );
    fclose( cmpFile );

    return true;
}
}