Commit 5cda6bc1 authored by Dick Hollenbeck's avatar Dick Hollenbeck

eagle plugin first work

parent ea467e67
......@@ -117,6 +117,7 @@ set(PCB_COMMON_SRCS
../pcbnew/sel_layer.cpp
../pcbnew/pcb_plot_params.cpp
../pcbnew/io_mgr.cpp
../pcbnew/eagle_plugin.cpp
../pcbnew/legacy_plugin.cpp
../pcbnew/kicad_plugin.cpp
pcb_plot_params_keywords.cpp
......
......@@ -110,7 +110,6 @@ set(PCBNEW_SRCS
drc.cpp
drc_clearance_test_functions.cpp
drc_marker_functions.cpp
eagle_plugin.cpp
edgemod.cpp
edit.cpp
editedge.cpp
......
......@@ -232,7 +232,7 @@ public:
unsigned m_RatsnestEndIdx; // Ending point of ratsnests of this net
// (excluded) in this buffer
NETINFO_ITEM( BOARD_ITEM* aParent );
NETINFO_ITEM( BOARD_ITEM* aParent, const wxString& aNetName = NETCLASS::Default, int aNetCode = 0 );
~NETINFO_ITEM();
/**
......
......@@ -22,9 +22,9 @@
/* class NETINFO_ITEM: handle data relative to a given net */
/*********************************************************/
NETINFO_ITEM::NETINFO_ITEM( BOARD_ITEM* aParent )
NETINFO_ITEM::NETINFO_ITEM( BOARD_ITEM* aParent, const wxString& aNetName, int aNetCode )
{
SetNet( 0 );
SetNet( aNetCode );
m_NbNodes = 0;
m_NbLink = 0;
m_NbNoconn = 0;
......@@ -33,7 +33,7 @@ NETINFO_ITEM::NETINFO_ITEM( BOARD_ITEM* aParent )
// general buffer of ratsnest
m_RatsnestEndIdx = 0; // Ending point of ratsnests of this net
m_NetClassName = NETCLASS::Default;
m_NetClassName = aNetName;
m_NetClass = 0;
}
......
......@@ -82,7 +82,7 @@ void NETINFO_LIST::buildListOfNets()
// Create and add the "unconnected net", always existing,
// used to handle pads and tracks that are not member of a "real" net
net_item = new NETINFO_ITEM( (BOARD_ITEM*) m_Parent );
net_item = new NETINFO_ITEM( m_Parent );
AppendNet( net_item );
// Build the PAD list, sorted by net
......@@ -108,15 +108,15 @@ void NETINFO_LIST::buildListOfNets()
if( last_pad == NULL || ( pad->GetNetname() != last_pad->GetNetname() ) )
{
netcode++;
net_item = new NETINFO_ITEM( (BOARD_ITEM*)m_Parent );
net_item->SetNet( netcode );
net_item->SetNetname( pad->GetNetname() );
net_item = new NETINFO_ITEM( m_Parent, pad->GetNetname(), netcode );
AppendNet( net_item );
}
pad->SetNet( netcode );
net_item->m_PadInNetList.push_back( pad );
nodes_count ++;
nodes_count++;
last_pad = pad;
}
......
......@@ -24,148 +24,534 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <wx/string.h>
#include <io_mgr.h>
#include <boost/property_tree/xml_parser.hpp>
/*
class EAGLE_PLUGIN : public PLUGIN
{
public:
Pcbnew PLUGIN for Eagle 6.x XML *.brd and footprint format.
//-----<PUBLIC PLUGIN API>-------------------------------------------------
const wxString& PluginName();
XML parsing and converting:
Getting line numbers and byte offsets from the source XML file is not
possible using currently available XML libraries within KiCad project:
wxXmlDocument and boost::property_tree.
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties = NULL );
property_tree will give line numbers but no byte offsets, and only during
document loading. This means that if we have a problem after the document is
successfully loaded, there is no way to correlate back to line number and byte
offset of the problem. So a different approach is taken, one which relies on the
XML elements themselves using an XPATH type of reporting mechanism. The path to
the problem is reported in the error messages. This means keeping track of that
path as we traverse the XML document for the sole purpose of accurate error
reporting.
void Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProperties = NULL );
User can load the source XML file into firefox or other xml browser and follow
our error message.
wxArrayString FootprintEnumerate( const wxString& aLibraryPath, PROPERTIES* aProperties = NULL);
*/
MODULE* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName, PROPERTIES* aProperties = NULL );
#include <errno.h>
void FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint, PROPERTIES* aProperties = NULL );
#include <wx/string.h>
#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/xml_parser.hpp>
void FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName );
#include <eagle_plugin.h>
void FootprintLibCreate( const wxString& aLibraryPath, PROPERTIES* aProperties = NULL );
#include <common.h>
#include <macros.h>
#include <fctsys.h>
#include <class_board.h>
#include <class_module.h>
#include <class_track.h>
#include <class_edge_mod.h>
void FootprintLibDelete( const wxString& aLibraryPath, PROPERTIES* aProperties = NULL );
bool IsFootprintLibWritable( const wxString& aLibraryPath );
using namespace boost::property_tree;
typedef EAGLE_PLUGIN::BIU BIU;
typedef PTREE::const_assoc_iterator CA_ITER;
typedef PTREE::const_iterator CITER;
#if 0
typedef MODULE_MAP::iterator MODULE_ITER;
typedef MODULE_MAP::const_iterator MODULE_CITER;
const wxString& GetFileExtension() const = 0;
#endif
};
static inline std::string makePkgKey( const std::string& aLibName, const std::string& aPkgName )
{
// The MODULE factory key is a simple concatonation of library name and
// package name, using '\x02' as a separator.
std::string key = aLibName + '\x02' + aPkgName;
return key;
}
const wxString& EAGLE_PLUGIN::PluginName()
EAGLE_PLUGIN::EAGLE_PLUGIN()
{
static const wxString name = wxT( "Eagle" );
return name;
init( NULL );
}
BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties )
EAGLE_PLUGIN::~EAGLE_PLUGIN()
{
return aAppendToMe;
}
void EAGLE_PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProperties )
const wxString& EAGLE_PLUGIN::PluginName() const
{
static const wxString name = wxT( "Eagle" );
return name;
}
wxArrayString EAGLE_PLUGIN::FootprintEnumerate( const wxString& aLibraryPath, PROPERTIES* aProperties )
const wxString& EAGLE_PLUGIN::GetFileExtension() const
{
return wxArrayString();
static const wxString extension = wxT( "brd" );
return extension;
}
MODULE* EAGLE_PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName, PROPERTIES* aProperties )
int inline EAGLE_PLUGIN::kicad( double d ) const
{
return NULL;
return KiROUND( biu_per_mm * d );
}
void EAGLE_PLUGIN::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint, PROPERTIES* aProperties )
BOARD* EAGLE_PLUGIN::Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties )
{
LOCALE_IO toggle; // toggles on, then off, the C locale.
PTREE doc;
init( aProperties );
m_board = aAppendToMe ? aAppendToMe : new BOARD();
// delete on exception, iff I own m_board, according to aAppendToMe
auto_ptr<BOARD> deleter( aAppendToMe ? NULL : m_board );
try
{
// 8 bit filename should be encoded in current locale, not necessarily utf8.
std::string filename = (const char*) aFileName.fn_str();
read_xml( filename, doc, xml_parser::trim_whitespace | xml_parser::no_comments );
std::string xpath = "eagle.drawing.board";
CPTREE& brd = doc.get_child( xpath );
loadAllSections( brd, xpath, bool( aAppendToMe ) );
}
// Class ptree_error is a base class for xml_parser_error & file_parser_error,
// so one catch should be OK for all errors.
catch( ptree_error pte )
{
// for xml_parser_error, what() has the line number in it,
// but no byte offset. That should be an adequate error message.
THROW_IO_ERROR( pte.what() );
}
// IO_ERROR exceptions are left uncaught, they pass upwards from here.
deleter.release();
return m_board;
}
void EAGLE_PLUGIN::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName )
void EAGLE_PLUGIN::Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProperties )
{
}
void EAGLE_PLUGIN::FootprintLibCreate( const wxString& aLibraryPath, PROPERTIES* aProperties )
void EAGLE_PLUGIN::init( PROPERTIES* aProperties )
{
}
m_modules.clear();
m_board = NULL;
m_props = aProperties;
void EAGLE_PLUGIN::FootprintLibDelete( const wxString& aLibraryPath, PROPERTIES* aProperties )
mm_per_biu = 1/IU_PER_MM;
biu_per_mm = IU_PER_MM;
}
/*
int EAGLE_PLUGIN::biuSprintf( char* buf, BIU aValue ) const
{
double engUnits = mm_per_biu * aValue;
int len;
if( engUnits != 0.0 && fabs( engUnits ) <= 0.0001 )
{
// printf( "f: " );
len = sprintf( buf, "%.10f", engUnits );
while( --len > 0 && buf[len] == '0' )
buf[len] = '\0';
++len;
}
else
{
// printf( "g: " );
len = sprintf( buf, "%.10g", engUnits );
}
return len;
}
bool EAGLE_PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath )
std::string EAGLE_PLUGIN::fmtBIU( BIU aValue ) const
{
return true;
char temp[50];
int len = biuSprintf( temp, aValue );
return std::string( temp, len );
}
double EAGLE_PLUGIN::dblParse( const char* aValue, const std::string& aXpath )
{
char* nptr;
errno = 0;
double fval = strtod( aValue, &nptr );
if( errno )
{
wxString emsg = wxString::Format(
_( "invalid float number:'%s' in XML document at '%s'" ),
aValue, aXpath.c_str() );
THROW_IO_ERROR( emsg );
}
if( aValue == nptr )
{
wxString emsg = wxString::Format(
_( "missing float number:'%s' in XML document at '%s'" ),
aValue, aXpath.c_str() );
THROW_IO_ERROR( emsg );
}
#if 0
return fval;
}
wxXmlDocument xml;
xml.SetFileEncoding( wxT( "UTF-8" ) );
BIU EAGLE_PLUGIN::biuParse( const char* aValue, const std::string& aXpath )
{
double mm = dblParse( aValue, aXpath );
return BIU( KiROUND( mm * biu_per_mm ) );
}
if( !xml.Load( dlg.GetFilename() ) )
return;
*/
XNODE *macrosNode = (XNODE*) xml.GetRoot()->GetChildren();
void EAGLE_PLUGIN::loadAllSections( CPTREE& aEagleBoard, const std::string& aXpath, bool aAppendToMe )
{
std::string xpath;
while( macrosNode )
{
int number = -1;
xpath = aXpath + '.' + "libraries";
CPTREE& libs = aEagleBoard.get_child( "libraries" );
loadModules( libs, xpath );
}
if( macrosNode->GetName() == wxT( "macros" ) )
// assume that MODULE_MAP is already loaded.
{
number = wxAtoi( macrosNode->GetAttribute( wxT( "number" ), wxT( "-1" ) ) );
xpath = aXpath + '.' + "signals";
CPTREE& signals = aEagleBoard.get_child( "signals" );
loadNetsAndTracks( signals, xpath );
}
;
}
void EAGLE_PLUGIN::loadModules( CPTREE& aLibs, const std::string& aXpath )
{
m_modules.clear();
if( number >= 0 && number < 10 )
for( CITER library = aLibs.begin(); library != aLibs.end(); ++library )
{
m_Macros[number].m_Record.clear();
const std::string& lib_name = library->second.get<std::string>( "<xmlattr>.name" );
XNODE *hotkeyNode = (XNODE*) macrosNode->GetChildren();
// library will have <xmlattr> node, skip that and get the packages node
CPTREE& packages = library->second.get_child( "packages" );
while( hotkeyNode )
// Create a MODULE for all the eagle packages, for use later via a copy constructor
// to instantiate needed MODULES in our BOARD. Save the MODULE templates in
// a MODULE_MAP using a single lookup key consisting of libname+pkgname.
for( CITER package = packages.begin(); package != packages.end(); ++package )
{
if( hotkeyNode->GetName() == wxT( "hotkey" ) )
const std::string& pack_name = package->second.get<std::string>( "<xmlattr>.name" );
std::string key = makePkgKey( lib_name, pack_name );
MODULE* m = makeModule( package->second, pack_name );
// add the templating MODULE to the MODULE template factory "m_modules"
std::pair<MODULE_ITER, bool> r = m_modules.insert( key, m );
if( !r.second )
{
int x = wxAtoi( hotkeyNode->GetAttribute( wxT( "x" ), wxT( "0" ) ) );
int y = wxAtoi( hotkeyNode->GetAttribute( wxT( "y" ), wxT( "0" ) ) );
int hk = wxAtoi( hotkeyNode->GetAttribute( wxT( "hkcode" ), wxT( "0" ) ) );
MACROS_RECORD macros_record;
macros_record.m_HotkeyCode = hk;
macros_record.m_Position.x = x;
macros_record.m_Position.y = y;
m_Macros[number].m_Record.push_back( macros_record );
wxString lib = FROM_UTF8( lib_name.c_str() );
wxString pkg = FROM_UTF8( pack_name.c_str() );
wxString emsg = wxString::Format(
_( "<package> name:'%s' duplicated in eagle <library>:'%s'" ),
GetChars( lib ),
GetChars( pkg )
);
THROW_IO_ERROR( emsg );
}
hotkeyNode = (XNODE*) hotkeyNode->GetNext();
}
}
}
EWIRE EAGLE_PLUGIN::wire( CPTREE aWire ) const
{
EWIRE w;
CPTREE& attribs = aWire.get_child( "<xmlattr>" );
w.x1 = attribs.get<double>( "x1" );
w.y1 = attribs.get<double>( "y1" );
w.x2 = attribs.get<double>( "x2" );
w.y2 = attribs.get<double>( "y2" );
w.width = attribs.get<double>( "width" );
w.layer = attribs.get<int>( "layer" );
return w;
}
MODULE* EAGLE_PLUGIN::makeModule( CPTREE& aPackage, const std::string& aPkgName ) const
{
std::auto_ptr<MODULE> m( new MODULE( NULL ) );
m->SetLibRef( FROM_UTF8( aPkgName.c_str() ) );
boost::optional<std::string> description = aPackage.get_optional<std::string>( "description" );
if( description )
m->SetDescription( FROM_UTF8( description->c_str() ) );
for( CITER it = aPackage.begin(); it != aPackage.end(); ++it )
{
CPTREE& t = it->second;
if( !it->first.compare( "wire " ) )
packageWire( m.get(), t );
else if( !it->first.compare( "pad" ) )
packagePad( m.get(), t );
else if( !it->first.compare( "text" ) )
packageText( m.get(), t );
else if( !it->first.compare( "rectangle" ) )
packageRectangle( m.get(), t );
else if( !it->first.compare( "polygon" ) )
packagePolygon( m.get(), t );
else if( !it->first.compare( "circle" ) )
packageCircle( m.get(), t );
else if( !it->first.compare( "hole" ) )
packageHole( m.get(), t );
else if( !it->first.compare( "smd" ) )
packageSMD( m.get(), t );
}
macrosNode = (XNODE*) macrosNode->GetNext();
return m.release();
}
void EAGLE_PLUGIN::packageWire( MODULE* aModule, CPTREE aTree ) const
{
EWIRE w = wire( aTree );
int layer = kicad_layer( w.layer );
wxPoint start( kicad_x( w.x1 ), kicad_y( w.y1 ) );
wxPoint end( kicad_x( w.x2 ), kicad_y( w.x2 ) );
int width = kicad( w.width );
EDGE_MODULE* dwg = new EDGE_MODULE( aModule, S_SEGMENT );
aModule->m_Drawings.PushBack( dwg );
dwg->SetStart0( start );
dwg->SetEnd0( end );
dwg->SetLayer( layer );
dwg->SetWidth( width );
}
void EAGLE_PLUGIN::packagePad( MODULE* aModule, CPTREE aTree ) const
{
CPTREE attrs = aTree.get_child( "<xmlattr>" );
}
void EAGLE_PLUGIN::packageText( MODULE* aModule, CPTREE aTree ) const
{
CPTREE attrs = aTree.get_child( "<xmlattr>" );
}
void EAGLE_PLUGIN::packageRectangle( MODULE* aModule, CPTREE aTree ) const
{
CPTREE attrs = aTree.get_child( "<xmlattr>" );
}
void EAGLE_PLUGIN::packagePolygon( MODULE* aModule, CPTREE aTree ) const
{
CPTREE attrs = aTree.get_child( "<xmlattr>" );
}
void EAGLE_PLUGIN::packageCircle( MODULE* aModule, CPTREE aTree ) const
{
CPTREE attrs = aTree.get_child( "<xmlattr>" );
}
void EAGLE_PLUGIN::packageHole( MODULE* aModule, CPTREE aTree ) const
{
CPTREE attrs = aTree.get_child( "<xmlattr>" );
}
void EAGLE_PLUGIN::packageSMD( MODULE* aModule, CPTREE aTree ) const
{
CPTREE attrs = aTree.get_child( "<xmlattr>" );
}
/*
<package name="2X03">
<description>&lt;b&gt;PIN HEADER&lt;/b&gt;</description>
<wire x1="-3.81" y1="-1.905" x2="-3.175" y2="-2.54" width="0.1524" layer="21"/>
<wire x1="-1.905" y1="-2.54" x2="-1.27" y2="-1.905" width="0.1524" layer="21"/>
<wire x1="-1.27" y1="-1.905" x2="-0.635" y2="-2.54" width="0.1524" layer="21"/>
<wire x1="0.635" y1="-2.54" x2="1.27" y2="-1.905" width="0.1524" layer="21"/>
<wire x1="-3.81" y1="-1.905" x2="-3.81" y2="1.905" width="0.1524" layer="21"/>
<wire x1="-3.81" y1="1.905" x2="-3.175" y2="2.54" width="0.1524" layer="21"/>
<wire x1="-3.175" y1="2.54" x2="-1.905" y2="2.54" width="0.1524" layer="21"/>
<wire x1="-1.905" y1="2.54" x2="-1.27" y2="1.905" width="0.1524" layer="21"/>
<wire x1="-1.27" y1="1.905" x2="-0.635" y2="2.54" width="0.1524" layer="21"/>
<wire x1="-0.635" y1="2.54" x2="0.635" y2="2.54" width="0.1524" layer="21"/>
<wire x1="0.635" y1="2.54" x2="1.27" y2="1.905" width="0.1524" layer="21"/>
<wire x1="-1.27" y1="1.905" x2="-1.27" y2="-1.905" width="0.1524" layer="21"/>
<wire x1="1.27" y1="1.905" x2="1.27" y2="-1.905" width="0.1524" layer="21"/>
<wire x1="-0.635" y1="-2.54" x2="0.635" y2="-2.54" width="0.1524" layer="21"/>
<wire x1="-3.175" y1="-2.54" x2="-1.905" y2="-2.54" width="0.1524" layer="21"/>
<wire x1="1.27" y1="-1.905" x2="1.905" y2="-2.54" width="0.1524" layer="21"/>
<wire x1="3.175" y1="-2.54" x2="3.81" y2="-1.905" width="0.1524" layer="21"/>
<wire x1="1.27" y1="1.905" x2="1.905" y2="2.54" width="0.1524" layer="21"/>
<wire x1="1.905" y1="2.54" x2="3.175" y2="2.54" width="0.1524" layer="21"/>
<wire x1="3.175" y1="2.54" x2="3.81" y2="1.905" width="0.1524" layer="21"/>
<wire x1="3.81" y1="1.905" x2="3.81" y2="-1.905" width="0.1524" layer="21"/>
<wire x1="1.905" y1="-2.54" x2="3.175" y2="-2.54" width="0.1524" layer="21"/>
<pad name="1" x="-2.54" y="-1.27" drill="1.016" shape="octagon"/>
<pad name="2" x="-2.54" y="1.27" drill="1.016" shape="octagon"/>
<pad name="3" x="0" y="-1.27" drill="1.016" shape="octagon"/>
<pad name="4" x="0" y="1.27" drill="1.016" shape="octagon"/>
<pad name="5" x="2.54" y="-1.27" drill="1.016" shape="octagon"/>
<pad name="6" x="2.54" y="1.27" drill="1.016" shape="octagon"/>
<text x="-3.81" y="3.175" size="1.27" layer="25" ratio="10">&gt;NAME</text>
<text x="-3.81" y="-4.445" size="1.27" layer="27">&gt;VALUE</text>
<rectangle x1="-2.794" y1="-1.524" x2="-2.286" y2="-1.016" layer="51"/>
<rectangle x1="-2.794" y1="1.016" x2="-2.286" y2="1.524" layer="51"/>
<rectangle x1="-0.254" y1="1.016" x2="0.254" y2="1.524" layer="51"/>
<rectangle x1="-0.254" y1="-1.524" x2="0.254" y2="-1.016" layer="51"/>
<rectangle x1="2.286" y1="1.016" x2="2.794" y2="1.524" layer="51"/>
<rectangle x1="2.286" y1="-1.524" x2="2.794" y2="-1.016" layer="51"/>
</package>
*/
void EAGLE_PLUGIN::loadNetsAndTracks( CPTREE& aSignals, const std::string& aXpath )
{
int netCode = 1;
time_t now = time( NULL );
for( CITER nit = aSignals.begin(); nit != aSignals.end(); ++nit, ++netCode )
{
wxString netName = FROM_UTF8( nit->second.get<std::string>( "<xmlattr>.name" ).c_str() );
m_board->AppendNet( new NETINFO_ITEM( m_board, netName, netCode ) );
std::pair<CA_ITER, CA_ITER> wires = nit->second.equal_range( "wire" );
for( CA_ITER wit = wires.first; wit != wires.second; ++wit )
{
EWIRE w = wire( wit->second );
TRACK* t = new TRACK( m_board );
t->SetTimeStamp( now );
t->SetPosition( wxPoint( kicad_x( w.x1 ), kicad_y( w.y1 ) ) );
t->SetEnd( wxPoint( kicad_x( w.x2 ), kicad_y( w.y2 ) ) );
t->SetWidth( kicad( w.width ) );
t->SetLayer( kicad_layer( w.layer ) );
t->SetNet( netCode );
m_board->m_Track.Insert( t, NULL );
D(printf("wire:%s\n", wit->first.c_str() );)
}
}
}
int EAGLE_PLUGIN::kicad_layer( int aLayer ) const
{
return aLayer;
}
wxArrayString EAGLE_PLUGIN::FootprintEnumerate( const wxString& aLibraryPath, PROPERTIES* aProperties )
{
return wxArrayString();
}
MODULE* EAGLE_PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName, PROPERTIES* aProperties )
{
return NULL;
}
void EAGLE_PLUGIN::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint, PROPERTIES* aProperties )
{
}
void EAGLE_PLUGIN::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName )
{
}
void EAGLE_PLUGIN::FootprintLibCreate( const wxString& aLibraryPath, PROPERTIES* aProperties )
{
}
void EAGLE_PLUGIN::FootprintLibDelete( const wxString& aLibraryPath, PROPERTIES* aProperties )
{
}
bool EAGLE_PLUGIN::IsFootprintLibWritable( const wxString& aLibraryPath )
{
return true;
}
#endif
#ifndef EAGLE_PLUGIN_H_
#define EAGLE_PLUGIN_H_
/*
* This program source code file is part of KiCad, a free EDA CAD application.
*
* Copyright (C) 2012 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2012 KiCad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <io_mgr.h>
// forward declaration on ptree template so we can confine use of big boost
// headers to only the implementation *.cpp file.
#include <boost/property_tree/ptree_fwd.hpp>
#include <boost/ptr_container/ptr_map.hpp>
class MODULE;
typedef boost::ptr_map< std::string, MODULE > MODULE_MAP;
/*
#include
namespace boost {
namespace property_tree
{
template < class Key, class Data, class KeyCompare = std::less<Key> >
class basic_ptree;
typedef basic_ptree< std::string, std::string > ptree;
}
}
*/
typedef boost::property_tree::ptree PTREE;
typedef const PTREE CPTREE;
struct EWIRE ///< Eagle wire
{
double x1;
double y1;
double x2;
double y2;
double width;
int layer;
};
/**
* Class EAGLE_PLUGIN
* works with Eagle 6.x XML board files and footprints.
*/
class EAGLE_PLUGIN : public PLUGIN
{
public:
//-----<PUBLIC PLUGIN API>--------------------------------------------------
const wxString& PluginName() const;
BOARD* Load( const wxString& aFileName, BOARD* aAppendToMe, PROPERTIES* aProperties = NULL );
void Save( const wxString& aFileName, BOARD* aBoard, PROPERTIES* aProperties = NULL );
wxArrayString FootprintEnumerate( const wxString& aLibraryPath, PROPERTIES* aProperties = NULL);
MODULE* FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName, PROPERTIES* aProperties = NULL );
void FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint, PROPERTIES* aProperties = NULL );
void FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName );
void FootprintLibCreate( const wxString& aLibraryPath, PROPERTIES* aProperties = NULL );
void FootprintLibDelete( const wxString& aLibraryPath, PROPERTIES* aProperties = NULL );
bool IsFootprintLibWritable( const wxString& aLibraryPath );
const wxString& GetFileExtension() const;
//-----</PUBLIC PLUGIN API>-------------------------------------------------
typedef int BIU;
EAGLE_PLUGIN();
~EAGLE_PLUGIN();
private:
MODULE_MAP m_modules; ///< is a factory by use of MODULE copy constructor,
///< lookup is based on libname.packagename
PROPERTIES* m_props; ///< passed via Save() or Load(), no ownership, may be NULL.
BOARD* m_board; ///< which BOARD, no ownership here
double mm_per_biu; ///< how many mm in each BIU
double biu_per_mm; ///< how many bius in a mm
/// initialize PLUGIN like a constructor would, and futz with fresh BOARD if needed.
void init( PROPERTIES* aProperties );
int kicad( double d ) const;
int kicad_y( double y ) const { return kicad( y ); }
int kicad_x( double x ) const { return kicad( x ); }
int kicad_layer( int aLayer ) const;
double eagle( BIU d ) const { return mm_per_biu * d; }
double eagle_x( BIU x ) const { return eagle( x ); }
double eagle_y( BIU y ) const { return eagle( y ); }
#if 0
/**
* Function dblParse
* parses an ASCII decimal floating point value and reports any error by throwing
* an exception using the xpath in the error message text.
*
* @param aValue is the ASCII value in C locale form with possible leading whitespace
*
* @param aXpath tells where the value is within the XML document.
*
* @return double - aValue in binary, not scaled.
*/
static double dblParse( const char* aValue, const std::string& aXpath );
/**
* Function biuParse
* parses an ASCII decimal floating point value and scales it into a BIU
* according to the current mm_per_biu. This fuction is the complement of
* fmtBIU(). One has to know what the other is doing.
*
* @param aValue is the ASCII value in C locale form with possible leading whitespace
*
* @param aXpath tells where the value is within the XML document.
*
* @return BIU - the converted Board Internal Unit.
*/
BIU biuParse( const char* aValue, const std::string& aXpath );
/**
* Function degParse
* parses an ASCII decimal floating point value which is certainly an angle. This
* is a dedicated function for encapsulating support for the migration from
* tenths of degrees to degrees in floating point. This function is the complement of
* fmtDEG(). One has to know what the other is doing.
*
* @param aValue is the ASCII value in C locale form with possible leading whitespace
*
* @param nptrptr may be NULL, but if not, then it tells where to put a
* pointer to the next unconsumed input text. See "man strtod" for more information.
*
* @return double - the string converted to a primitive double type
*/
double degParse( const char* aValue, const char** nptrptr = NULL );
/// encapsulate the BIU formatting tricks in one place.
int biuSprintf( char* buf, BIU aValue ) const;
/**
* Function fmtBIU
* converts a BIU to engineering units by scaling and formatting to ASCII.
* This function is the complement of biuParse(). One has to know what the
* other is doing.
*/
std::string fmtBIU( BIU aValue ) const;
std::string fmtBIUPair( BIU first, BIU second ) const;
std::string fmtBIUPoint( const wxPoint& aPoint ) const
{
return fmtBIUPair( aPoint.x, aPoint.y );
}
std::string fmtBIUSize( const wxSize& aSize ) const
{
return fmtBIUPair( aSize.x, aSize.y );
}
#endif
// all these loadXXX() throw IO_ERROR or ptree_error exceptions:
void loadAllSections( CPTREE& aEagleBoard, const std::string& aXpath, bool aAppendToMe );
void loadNetsAndTracks( CPTREE& aSignals, const std::string& aXpath );
void loadModules( CPTREE& aLibs, const std::string& aXpath );
/**
* Function wire
* converts a <wire>'s xml attributes to binary without additional conversion.
* @return EWIRE - an Eagle <wire> object in binary.
*/
EWIRE wire( CPTREE aWire ) const;
/**
* Function fmtDEG
* formats an angle in a way particular to a board file format. This function
* is the opposite or complement of degParse(). One has to know what the
* other is doing.
*/
std::string fmtDEG( double aAngle ) const;
/**
* Function makeModule
* creates a MODULE from an Eagle package.
*/
MODULE* makeModule( CPTREE& aPackage, const std::string& aPkgName ) const;
void packageWire( MODULE* aModule, CPTREE aTree ) const;
void packagePad( MODULE* aModule, CPTREE aTree ) const;
void packageText( MODULE* aModule, CPTREE aTree ) const;
void packageRectangle( MODULE* aModule, CPTREE aTree ) const;
void packagePolygon( MODULE* aModule, CPTREE aTree ) const;
void packageCircle( MODULE* aModule, CPTREE aTree ) const;
void packageHole( MODULE* aModule, CPTREE aTree ) const;
void packageSMD( MODULE* aModule, CPTREE aTree ) const;
};
#endif // EAGLE_PLUGIN_H_
......@@ -26,6 +26,7 @@
#include <io_mgr.h>
#include <legacy_plugin.h>
#include <kicad_plugin.h>
#include <eagle_plugin.h>
#define FMT_UNIMPLEMENTED _( "Plugin '%s' does not implement the '%s' function." )
......@@ -60,10 +61,8 @@ PLUGIN* IO_MGR::PluginFind( PCB_FILE_T aFileType )
case KICAD:
return new PCB_IO();
/*
case EAGLE:
return &eagle_plugin;
*/
return new EAGLE_PLUGIN();
}
return NULL;
......
......@@ -50,10 +50,10 @@ public:
{
LEGACY, //< Legacy Pcbnew file formats prior to s-expression.
KICAD, //< S-expression Pcbnew file format.
EAGLE,
// add your type here.
// EAGLE,
// ALTIUM,
// etc.
};
......
......@@ -88,11 +88,17 @@
#include <wx/ffile.h>
typedef LEGACY_PLUGIN::BIU BIU;
#define VERSION_ERROR_FORMAT _( "File '%s' is format version: %d.\nI only support format version <= %d.\nPlease upgrade Pcbnew to load this file." )
#define UNKNOWN_GRAPHIC_FORMAT _( "unknown graphic type: %d")
#define UNKNOWN_PAD_FORMAT _( "unknown pad type: %d")
#define UNKNOWN_PAD_ATTRIBUTE _( "unknown pad attribute: %d" )
// Old internal units definition (UI = decimil)
#define PCB_LEGACY_INTERNAL_UNIT 10000
......@@ -3729,7 +3735,7 @@ void LEGACY_PLUGIN::savePCB_TEXT( const TEXTE_PCB* me ) const
#include <boost/ptr_container/ptr_map.hpp>
#include <wx/filename.h>
typedef boost::ptr_map< wxString, MODULE > MODULE_MAP;
typedef boost::ptr_map< std::string, MODULE > MODULE_MAP;
typedef MODULE_MAP::iterator MODULE_ITER;
typedef MODULE_MAP::const_iterator MODULE_CITER;
......@@ -3912,8 +3918,7 @@ void FPL_CACHE::LoadModules( LINE_READER* aReader )
{
MODULE* m = m_owner->LoadMODULE();
// wxString footprintName = m->GetReference();
wxString footprintName = m->GetLibRef();
std::string footprintName = TO_UTF8( m->GetLibRef() );
/*
......@@ -3944,11 +3949,15 @@ void FPL_CACHE::LoadModules( LINE_READER* aReader )
{
bool nameOK = false;
int version = 2;
char buf[48];
while( !nameOK )
{
wxString newName = footprintName;
newName << wxT( "_v" ) << version++;
std::string newName = footprintName;
newName += "_v";
sprintf( buf, "%d", version++ );
newName += buf;
it = m_modules.find( newName );
......@@ -3956,7 +3965,7 @@ void FPL_CACHE::LoadModules( LINE_READER* aReader )
{
nameOK = true;
m->SetLibRef( newName );
m->SetLibRef( FROM_UTF8( newName.c_str() ) );
std::pair<MODULE_ITER, bool> r = m_modules.insert( newName, m );
wxASSERT_MSG( r.second, wxT( "error doing cache insert using guaranteed unique name" ) );
......@@ -4035,7 +4044,7 @@ void FPL_CACHE::SaveIndex( FILE* aFile )
for( MODULE_CITER it = m_modules.begin(); it != m_modules.end(); ++it )
{
fprintf( aFile, "%s\n", TO_UTF8( it->first ) );
fprintf( aFile, "%s\n", it->first.c_str() );
}
fprintf( aFile, "$EndINDEX\n" );
......@@ -4081,7 +4090,7 @@ wxArrayString LEGACY_PLUGIN::FootprintEnumerate( const wxString& aLibraryPath, P
for( MODULE_CITER it = mods.begin(); it != mods.end(); ++it )
{
ret.Add( it->first );
ret.Add( FROM_UTF8( it->first.c_str() ) );
}
return ret;
......@@ -4099,7 +4108,7 @@ MODULE* LEGACY_PLUGIN::FootprintLoad( const wxString& aLibraryPath, const wxStri
const MODULE_MAP& mods = m_cache->m_modules;
MODULE_CITER it = mods.find( aFootprintName );
MODULE_CITER it = mods.find( TO_UTF8( aFootprintName ) );
if( it == mods.end() )
{
......@@ -4129,7 +4138,7 @@ void LEGACY_PLUGIN::FootprintSave( const wxString& aLibraryPath, const MODULE* a
THROW_IO_ERROR( wxString::Format( _( "Library '%s' is read only" ), aLibraryPath.GetData() ) );
}
wxString footprintName = aFootprint->GetLibRef();
std::string footprintName = TO_UTF8( aFootprint->GetLibRef() );
MODULE_MAP& mods = m_cache->m_modules;
......@@ -4173,7 +4182,9 @@ void LEGACY_PLUGIN::FootprintDelete( const wxString& aLibraryPath, const wxStrin
THROW_IO_ERROR( wxString::Format( _( "Library '%s' is read only" ), aLibraryPath.GetData() ) );
}
size_t erasedCount = m_cache->m_modules.erase( aFootprintName );
std::string footprintName = TO_UTF8( aFootprintName );
size_t erasedCount = m_cache->m_modules.erase( footprintName );
if( erasedCount != 1 )
{
......
......@@ -32,7 +32,6 @@
#define FOOTPRINT_LIBRARY_HEADER "PCBNEW-LibModule-V1"
#define FOOTPRINT_LIBRARY_HEADER_CNT 18
typedef int BIU;
class PCB_TARGET;
class MODULE;
......@@ -62,6 +61,7 @@ class LEGACY_PLUGIN : public PLUGIN
{
public:
//-----<PLUGIN IMPLEMENTATION>----------------------------------------------
const wxString& PluginName() const
......@@ -98,6 +98,8 @@ public:
//-----</PLUGIN IMPLEMENTATION>---------------------------------------------
typedef int BIU;
LEGACY_PLUGIN();
~LEGACY_PLUGIN();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment