From 28f238e36b0dab31ee7424c865258ac2a9f1cc49 Mon Sep 17 00:00:00 2001 From: Dick Hollenbeck Date: Mon, 22 Oct 2012 15:41:26 -0500 Subject: [PATCH] pcbnew import footprint fixed for legacy nanometer format --- pcbnew/kicad_plugin.cpp | 37 ++++++++-- pcbnew/kicad_plugin.h | 5 ++ pcbnew/librairi.cpp | 157 ++++++++++++++++++++++++++++++---------- pcbnew/loadcmp.cpp | 1 + pcbnew/pcb_parser.cpp | 7 +- 5 files changed, 159 insertions(+), 48 deletions(-) diff --git a/pcbnew/kicad_plugin.cpp b/pcbnew/kicad_plugin.cpp index 6fcfa699ef..ce35e8a69a 100644 --- a/pcbnew/kicad_plugin.cpp +++ b/pcbnew/kicad_plugin.cpp @@ -82,11 +82,11 @@ class FP_CACHE_ITEM public: FP_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName ); - wxString GetName() const { return m_file_name.GetDirs().Last(); } - wxFileName GetFileName() const { return m_file_name; } - bool IsModified() const; - MODULE* GetModule() const { return m_module.get(); } - void UpdateModificationTime() { m_mod_time = m_file_name.GetModificationTime(); } + wxString GetName() const { return m_file_name.GetDirs().Last(); } + wxFileName GetFileName() const { return m_file_name; } + bool IsModified() const; + MODULE* GetModule() const { return m_module.get(); } + void UpdateModificationTime() { m_mod_time = m_file_name.GetModificationTime(); } }; @@ -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; } diff --git a/pcbnew/kicad_plugin.h b/pcbnew/kicad_plugin.h index 23f92c7d92..67f4865122 100644 --- a/pcbnew/kicad_plugin.h +++ b/pcbnew/kicad_plugin.h @@ -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 diff --git a/pcbnew/librairi.cpp b/pcbnew/librairi.cpp index f6ee71dc5d..b22d493394 100644 --- a/pcbnew/librairi.cpp +++ b/pcbnew/librairi.cpp @@ -4,6 +4,7 @@ */ #include +#include #include #include #include @@ -22,7 +23,8 @@ #include #include #include -#include // temporarily, for LoadMODULE() +#include +#include #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 ); - - // Read header and test file type - reader.ReadLine(); - char* line = reader.Line(); - - bool footprint_Is_GPCB_Format = false; - - if( strnicmp( line, FOOTPRINT_LIBRARY_HEADER, FOOTPRINT_LIBRARY_HEADER_CNT ) != 0 ) { - if( strnicmp( line, "Element", 7 ) == 0 ) + FILE_LINE_READER freader( fp, dlg.GetPath() ); // I own fp, and will close it. + FILTER_READER reader( freader ); // skip blank lines + + reader.ReadLine(); + char* line = reader.Line(); + + if( !strnicmp( line, "(module", 7 ) ) { - footprint_Is_GPCB_Format = true; + // isKicad = true; + } + else if( !strnicmp( line, FOOTPRINT_LIBRARY_HEADER, FOOTPRINT_LIBRARY_HEADER_CNT ) ) + { + isLegacy = true; + + while( reader.ReadLine() ) + { + if( !strnicmp( line, "$MODULE", 7 ) ) + { + 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. - module = lp->LoadMODULE(); + 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; + } + + f.ReadAll( &fcontents ); + + // @todo Fix this. The layernames are missing, and this fails. + module = dynamic_cast( 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." ), - GetChars( dlg.GetTextSelection() ) ); + 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(); } diff --git a/pcbnew/loadcmp.cpp b/pcbnew/loadcmp.cpp index b89c71ed3c..b5d3778a19 100644 --- a/pcbnew/loadcmp.cpp +++ b/pcbnew/loadcmp.cpp @@ -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. diff --git a/pcbnew/pcb_parser.cpp b/pcbnew/pcb_parser.cpp index ccc1965d75..aaf5a32661 100644 --- a/pcbnew/pcb_parser.cpp +++ b/pcbnew/pcb_parser.cpp @@ -677,11 +677,14 @@ void PCB_PARSER::parseLayers() throw( IO_ERROR, PARSE_ERROR ) if( isVisible ) visibleLayers |= 1 << layerIndex; - enum LAYER_T layerType = LAYER::ParseType( TO_UTF8( type ) ); - LAYER layer( name, layerType, isVisible ); + 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 );