Commit 28f238e3 authored by Dick Hollenbeck's avatar Dick Hollenbeck
Browse files

pcbnew import footprint fixed for legacy nanometer format

parent c7718114
Loading
Loading
Loading
Loading
+30 −7
Original line number Diff line number Diff line
@@ -332,6 +332,18 @@ void PCB_IO::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProper
}


BOARD_ITEM* PCB_IO::Parse( const wxString& aClipboardSourceInput ) throw( IO_ERROR, PARSE_ERROR )
{
    std::string input = TO_UTF8( aClipboardSourceInput );

    STRING_LINE_READER  reader( input, wxT( "clipboard" ) );

    PCB_PARSER  parser( &reader );

    return parser.Parse();
}


void PCB_IO::Format( BOARD_ITEM* aItem, int aNestLevel ) const
    throw( IO_ERROR )
{
@@ -1058,7 +1070,7 @@ void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const
    m_out->Print( 0, ")\n" );

    // Unconnected pad is default net so don't save it.
    if( aPad->GetNet() != 0 )
    if( !(m_ctl & CTL_CLIPBOARD) && aPad->GetNet() != 0 )
    {
        m_out->Print( aNestLevel+1, "(net %d %s)\n",
                      aPad->GetNet(), m_out->Quotew( aPad->GetNetname() ).c_str() );
@@ -1452,8 +1464,19 @@ void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const


PCB_IO::PCB_IO() :
    m_cache( 0 )
    m_cache( 0 ),
    m_ctl( 0 )
{
    init( 0 );
    m_out = &m_sf;
}


PCB_IO::PCB_IO( int aControlFlags ) :
    m_cache( 0 ),
    m_ctl( aControlFlags )
{
    init( 0 );
    m_out = &m_sf;
}

+5 −0
Original line number Diff line number Diff line
@@ -89,6 +89,8 @@ public:

    PCB_IO();

    PCB_IO( int aControlFlags );

    ~PCB_IO();

    /**
@@ -113,6 +115,9 @@ public:

    void SetOutputFormatter( OUTPUTFORMATTER* aFormatter ) { m_out = aFormatter; }

    BOARD_ITEM* Parse( const wxString& aClipboardSourceInput )
        throw( IO_ERROR, PARSE_ERROR );

protected:

    wxString        m_error;        ///< for throwing exceptions
+116 −37
Original line number Diff line number Diff line
@@ -4,6 +4,7 @@
 */

#include <fctsys.h>
#include <wx/ffile.h>
#include <appl_wxstruct.h>
#include <class_drawpanel.h>
#include <confirm.h>
@@ -22,7 +23,8 @@
#include <pcbnew.h>
#include <module_editor_frame.h>
#include <wildcards_and_files_ext.h>
#include <legacy_plugin.h>              // temporarily, for LoadMODULE()
#include <kicad_plugin.h>
#include <legacy_plugin.h>


#define BACKUP_EXT                 wxT( "bak" )
@@ -54,12 +56,10 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module()
    if( dlg.ShowModal() == wxID_CANCEL )
        return NULL;

    FILE* file = wxFopen( dlg.GetPath(), wxT( "rt" ) );

    if( file == NULL )
    FILE* fp = wxFopen( dlg.GetPath(), wxT( "rt" ) );
    if( !fp )
    {
        wxString msg;
        msg.Printf( _( "File <%s> not found" ), GetChars( dlg.GetPath() ) );
        wxString msg = wxString::Format( _( "File <%s> not found" ), GetChars( dlg.GetPath() ) );
        DisplayError( this, msg );
        return NULL;
    }
@@ -70,60 +70,114 @@ MODULE* FOOTPRINT_EDIT_FRAME::Import_Module()
        config->Write( EXPORT_IMPORT_LASTPATH_KEY, lastOpenedPathForLoading );
    }

    LOCALE_IO   toggle;
    wxString    moduleName;

    FILE_LINE_READER fileReader( file, dlg.GetPath() );
    bool    isGeda   = false;
    bool    isLegacy = false;

    FILTER_READER reader( fileReader );
    {
        FILE_LINE_READER    freader( fp, dlg.GetPath() );   // I own fp, and will close it.
        FILTER_READER       reader( freader );              // skip blank lines

    // Read header and test file type
        reader.ReadLine();
        char* line = reader.Line();

    bool      footprint_Is_GPCB_Format = false;
        if( !strnicmp( line, "(module", 7 ) )
        {
            // isKicad = true;
        }
        else if( !strnicmp( line, FOOTPRINT_LIBRARY_HEADER, FOOTPRINT_LIBRARY_HEADER_CNT ) )
        {
            isLegacy = true;

    if( strnicmp( line, FOOTPRINT_LIBRARY_HEADER, FOOTPRINT_LIBRARY_HEADER_CNT ) != 0 )
            while( reader.ReadLine() )
            {
        if( strnicmp( line, "Element", 7 ) == 0 )
                if( !strnicmp( line, "$MODULE", 7 ) )
                {
            footprint_Is_GPCB_Format = true;
                    moduleName = FROM_UTF8( StrPurge( line + sizeof( "$MODULE" ) -1 ) );
                    break;
                }
            }
        }
        else if( !strnicmp( line, "Element", 7 ) )
        {
            isGeda = true;
        }
        else
        {
            DisplayError( this, _( "Not a module file" ) );
            return NULL;
        }
    }

    // Read file: Search the description starting line (skip lib header)
    if( !footprint_Is_GPCB_Format )
    {
        while( reader.ReadLine() )
        {
            if( strnicmp( line, "$MODULE", 7 ) == 0 )
                break;
        }
        // fp is closed here by ~FILE_LINE_READER()
    }

    MODULE*   module;

    if( footprint_Is_GPCB_Format )
    if( isGeda )
    {
        LOCALE_IO   toggle;

        // @todo GEDA plugin
        module = new MODULE( GetBoard() );
        module->Read_GPCB_Descr( dlg.GetPath() );
    }
    else
    else if( isLegacy )
    {
        try
        {
            PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) );

            LEGACY_PLUGIN*  lp = (LEGACY_PLUGIN*)(PLUGIN*)pi;
            module = pi->FootprintLoad( dlg.GetPath(), moduleName );

            lp->SetReader( &reader );
            if( !module )
            {
                wxString msg = wxString::Format(
                    _( "Unable to find or load footprint '%s' from lib path '%s'" ),
                    GetChars( moduleName ), GetChars( dlg.GetPath() ) );
                DisplayError( this, msg );
                return NULL;
            }
        }
        catch( IO_ERROR ioe )
        {
            DisplayError( this, ioe.errorText );
            return NULL;
        }
    }
    else    //  if( isKicad )
    {
        try
        {
            // This technique was chosen to create an example of how reading
            // the s-expression format from clipboard could be done.

            wxString    fcontents;
            PCB_IO      pcb_io( CTL_CLIPBOARD );
            wxFFile     f( TO_UTF8( dlg.GetPath() ) );

            if( !f.IsOpened() )
            {
                wxString msg = wxString::Format(
                    _( "Unable to find or load footprint from path '%s'" ),
                    GetChars( dlg.GetPath() ) );
                DisplayError( this, msg );
                return NULL;
            }

            module = lp->LoadMODULE();
            f.ReadAll( &fcontents );

            // @todo Fix this. The layernames are missing, and this fails.
            module = dynamic_cast<MODULE*>( pcb_io.Parse( fcontents ) );

            if( !module )
            {
                wxString msg = wxString::Format(
                    _( "Unable to find or load footprint from lib path '%s'" ),
                    GetChars( dlg.GetPath() ) );
                DisplayError( this, msg );
                return NULL;
            }
        }
        catch( IO_ERROR ioe )
        {
@@ -186,8 +240,31 @@ void FOOTPRINT_EDIT_FRAME::Export_Module( MODULE* aModule, bool aCreateSysLib )

    try
    {
        // @todo : hard code this as IO_MGR::KICAD plugin, what would be the reason to "export"
        // any other single footprint type, with clipboard support coming?
#if 0   // This *.kicad_mod export works fine.  It is the import which is still broken.
        // The function PCB_PARSER::Parse() fails with due to the m_layerName[] table
        // being empty.

        // @todo, enable this code asap.

        // Export as *.kicad_pcb format, using a strategy which is specifically chosen
        // as an example on how it could also be used to send it to the system clipboard.

        PCB_IO  pcb_io( CTL_CLIPBOARD );

        /*  This module should *already* be "normalized" in a way such that
            orientation is zero, etc., since it came from module editor.

            module->SetTimeStamp( 0 );
            module->SetParent( 0 );
            module->SetOrientation( 0 );
        */

        pcb_io.Format( aModule );

        FILE* fp = wxFopen( dlg.GetPath(), wxT( "wt" ) );
        fprintf( fp, "%s", pcb_io.GetStringOutput( false ).c_str() );
        fclose( fp );
#else
        // Use IO_MGR::LEGACY for now, until the IO_MGR::KICAD plugin is ready.
        PLUGIN::RELEASER pi( IO_MGR::PluginFind( IO_MGR::LEGACY ) );

@@ -205,6 +282,8 @@ void FOOTPRINT_EDIT_FRAME::Export_Module( MODULE* aModule, bool aCreateSysLib )

        pi->FootprintLibCreate( libPath );
        pi->FootprintSave( libPath, aModule );
#endif

    }
    catch( IO_ERROR ioe )
    {
@@ -501,8 +580,6 @@ MODULE* PCB_BASE_FRAME::Create_1_Module( const wxString& aModuleName )

void FOOTPRINT_EDIT_FRAME::Select_Active_Library()
{
    wxString msg;

    if( g_LibraryNames.GetCount() == 0 )
        return;

@@ -521,8 +598,10 @@ void FOOTPRINT_EDIT_FRAME::Select_Active_Library()
    }
    else
    {
        msg.Printf( _( "The footprint library <%s> could not be found in any of the search paths." ),
        wxString msg = wxString::Format(
                        _( "The footprint library <%s> could not be found in any of the search paths." ),
                        GetChars( dlg.GetTextSelection() ) );

        DisplayError( this, msg );
        m_CurrentLib.Empty();
    }
+1 −0
Original line number Diff line number Diff line
@@ -257,6 +257,7 @@ MODULE* PCB_BASE_FRAME::Load_Module_From_Library( const wxString& aLibrary,
    return module;
}


/* scans active libraries to find and load aFootprintName.
 * If found  the module is added to the BOARD, just for good measure.
 *  aLibraryPath is the full/short name of the library.
+5 −2
Original line number Diff line number Diff line
@@ -679,9 +679,12 @@ void PCB_PARSER::parseLayers() throw( IO_ERROR, PARSE_ERROR )

        enum LAYER_T    layerType = LAYER::ParseType( TO_UTF8( type ) );
        LAYER           layer( name, layerType, isVisible );

        layer.SetFixedListIndex( layerIndex );
        m_board->SetLayer( layerIndex, layer );

        m_layerMap[ name ] = layerIndex;

        wxLogDebug( wxT( "Mapping layer %s index index %d" ),
                    GetChars( name ), layerIndex );