48#include <wx/filename.h> 
   49#include <wx/wfstream.h> 
   50#include <boost/ptr_container/ptr_map.hpp> 
   54static inline long parseInt( 
const wxString& aValue, 
double aScalar )
 
   56    double value = std::numeric_limits<double>::max();
 
   79    if( aValue.EndsWith( wxT( 
"mm" ) ) )
 
   81        aScalar *= 100000.0 / 25.4;
 
   83    else if( aValue.EndsWith( wxT( 
"mil" ) ) )
 
   90    aValue.ToCDouble(&value);
 
   92    if( value == std::numeric_limits<double>::max() ) 
 
   94        THROW_IO_ERROR( wxString::Format( 
_( 
"Cannot convert '%s' to an integer." ),
 
   98    return KiROUND( value * aScalar );
 
 
  144    void Remove( 
const wxString& aFootprintName );
 
  152    static long long GetTimestamp( 
const wxString& aLibPath );
 
  172    bool testFlags( 
const wxString& aFlag, 
long aMask, 
const wxChar* aName );
 
 
  223    if( !dir.IsOpened() )
 
  225        THROW_IO_ERROR( wxString::Format( 
_( 
"Footprint library '%s' not found." ),
 
  236    if( !dir.GetFirst( &fullName, fileSpec ) )
 
  239    wxString cacheErrorMsg;
 
  259            if( !cacheErrorMsg.IsEmpty() )
 
  260                cacheErrorMsg += wxT( 
"\n\n" );
 
  262            cacheErrorMsg += ioe.
What();
 
  264    } 
while( dir.GetNext( &fullName ) );
 
  266    if( !cacheErrorMsg.IsEmpty() )
 
 
  273    std::string footprintName = 
TO_UTF8( aFootprintName );
 
  279        THROW_IO_ERROR( wxString::Format( 
_( 
"Library '%s' has no footprint '%s'." ),
 
  281                                          aFootprintName.GetData() ) );
 
  285    wxString fullPath = it->second->GetFileName().GetFullPath();
 
  287    wxRemoveFile( fullPath );
 
 
  309    #define TEXT_DEFAULT_SIZE  ( 40*pcbIUScale.IU_PER_MILS ) 
  310    #define OLD_GPCB_UNIT_CONV pcbIUScale.IU_PER_MILS 
  313    #define NEW_GPCB_UNIT_CONV ( 0.01*pcbIUScale.IU_PER_MILS ) 
  320    wxArrayString              parameters;
 
  321    std::unique_ptr<FOOTPRINT> footprint = std::make_unique<FOOTPRINT>( 
nullptr );
 
  323    if( aLineReader->
ReadLine() == 
nullptr )
 
  325        msg = aLineReader->
GetSource() + wxT( 
": empty file" );
 
  331    paramCnt = parameters.GetCount();
 
  341    if( parameters[0].CmpNoCase( wxT( 
"Element" ) ) != 0 )
 
  343        msg.Printf( 
_( 
"Unknown token '%s'" ), parameters[0] );
 
  348    if( paramCnt < 10 || paramCnt > 14 )
 
  350        msg.Printf( 
_( 
"Element token contains %d parameters." ), paramCnt );
 
  356    if( parameters[1] == wxT( 
"(" ) )
 
  361        footprint->SetLibDescription( parameters[3] );
 
  362        footprint->SetReference( parameters[4] );
 
  366        footprint->SetLibDescription( parameters[2] );
 
  367        footprint->SetReference( parameters[3] );
 
  372        footprint->SetValue( parameters[5] );
 
  376    if( footprint->Value().GetText().IsEmpty() )
 
  377        footprint->Value().SetText( wxT( 
"VAL**" ) );
 
  379    if( footprint->Reference().GetText().IsEmpty() )
 
  380        footprint->Reference().SetText( wxT( 
"REF**" ) );
 
  387        if( parameters.IsEmpty() || parameters[0] == wxT( 
"(" ) )
 
  390        if( parameters[0] == wxT( 
")" ) )
 
  393        paramCnt = parameters.GetCount();
 
  398            if( parameters[1] == wxT( 
"(" ) )
 
  405                    parameters[0], paramCnt );
 
  408        if( parameters[0].CmpNoCase( wxT( 
"ElementLine" ) ) == 0 )
 
  412                msg.Printf( wxT( 
"ElementLine token contains %d parameters." ), paramCnt );
 
  420                                       parseInt( parameters[3], conv_unit ) ) );
 
  422                                     parseInt( parameters[5], conv_unit ) ) );
 
  426            shape->
Rotate( { 0, 0 }, footprint->GetOrientation() );
 
  427            shape->
Move( footprint->GetPosition() );
 
  429            footprint->Add( shape );
 
  434        if( parameters[0].CmpNoCase( wxT( 
"ElementArc" ) ) == 0 )
 
  438                msg.Printf( wxT( 
"ElementArc token contains %d parameters." ), paramCnt );
 
  446            footprint->Add( shape );
 
  450                                parseInt( parameters[5], conv_unit ) ) / 2;
 
  453                             parseInt( parameters[3], conv_unit ) );
 
  475                shape->
SetStart( arcStart + centre );
 
  484            shape->
Rotate( { 0, 0 }, footprint->GetOrientation() );
 
  485            shape->
Move( footprint->GetPosition() );
 
  494        if( parameters[0].CmpNoCase( wxT( 
"Pad" ) ) == 0 )
 
  496            if( paramCnt < 10 || paramCnt > 13 )
 
  498                msg.Printf( wxT( 
"Pad token contains %d parameters." ), paramCnt );
 
  503            std::unique_ptr<PAD> 
pad = std::make_unique<PAD>( footprint.get() );
 
  510            pad->SetLayerSet( pad_front );
 
  512            if( 
testFlags( parameters[paramCnt-2], 0x0080, wxT( 
"onsolder" ) ) )
 
  513                pad->SetLayerSet( pad_back );
 
  523            pad->SetNumber( parameters[paramCnt-3] );
 
  525            int x1 = 
parseInt( parameters[2], conv_unit );
 
  526            int x2 = 
parseInt( parameters[4], conv_unit );
 
  527            int y1 = 
parseInt( parameters[3], conv_unit );
 
  528            int y2 = 
parseInt( parameters[5], conv_unit );
 
  529            int width = 
parseInt( parameters[6], conv_unit );
 
  531            double angle = atan2( (
double)
delta.y, (
double)
delta.x );
 
  545                int maskMargin = 
parseInt( parameters[8], conv_unit );
 
  546                maskMargin = ( maskMargin - width ) / 2;
 
  547                pad->SetLocalSolderMaskMargin( maskMargin );
 
  552            pad->SetOrientation( orient );
 
  554            VECTOR2I padPos( ( x1 + x2 ) / 2, ( y1 + y2 ) / 2 );
 
  558            padPos += footprint->GetPosition();
 
  559            pad->SetPosition( padPos );
 
  561            if( !
testFlags( parameters[paramCnt-2], 0x0100, wxT( 
"square" ) ) )
 
  569            if( 
pad->GetSizeX() > 0 && 
pad->GetSizeY() > 0 )
 
  571                footprint->Add( 
pad.release() );
 
  575                wxLogError( 
_( 
"Invalid zero-sized pad ignored in\nfile: %s" ),
 
  588        if( parameters[0].CmpNoCase( wxT( 
"Pin" ) ) == 0 )
 
  590            if( paramCnt < 8 || paramCnt > 12 )
 
  592                msg.Printf( wxT( 
"Pin token contains %d parameters." ), paramCnt );
 
  603            pad->SetLayerSet( pad_set );
 
  605            if( 
testFlags( parameters[paramCnt-2], 0x0100, wxT( 
"square" ) ) )
 
  612            pad->SetNumber( parameters[paramCnt-3] );
 
  615                             parseInt( parameters[3], conv_unit ) );
 
  617            int padSize = 
parseInt( parameters[4], conv_unit );
 
  635                int maskMargin = 
parseInt( parameters[6], conv_unit );
 
  636                maskMargin = ( maskMargin - padSize ) / 2;
 
  637                pad->SetLocalSolderMaskMargin( maskMargin );
 
  639                drillSize = 
parseInt( parameters[7], conv_unit );
 
  643                drillSize = 
parseInt( parameters[5], conv_unit );
 
  646            pad->SetDrillSize( 
VECTOR2I( drillSize, drillSize ) );
 
  648            padPos += footprint->GetPosition();
 
  649            pad->SetPosition( padPos );
 
  657            footprint->Add( 
pad );
 
  662    footprint->AutoPositionFields();
 
  664    return footprint.release();
 
 
  672    char*    line = aLineReader->
Line();
 
  686                aParameterList.Add( tmp );
 
  691            aParameterList.Add( tmp );
 
  696            if( aParameterList.GetCount() == 1 )
 
  708                aParameterList.Add( tmp );
 
  713            aParameterList.Add( tmp );
 
  727                aParameterList.Add( tmp );
 
  739                aParameterList.Add( wxEmptyString );
 
  750                    aParameterList.Add( tmp );
 
 
  778    if( aFlag.StartsWith( wxT( 
"0x" ), &number ) || aFlag.StartsWith( wxT( 
"0X" ), &number ) )
 
  782        if( number.ToLong( &lflags, 16 ) && ( lflags & aMask ) )
 
  785    else if( aFlag.Contains( aName ) )
 
 
  805    m_ctl( aControlFlags )
 
 
  837                                         wxString&              aFootprintNameOut,
 
  838                                         const std::map<std::string, UTF8>* aProperties )
 
  840    wxFileName fn( aFootprintPath );
 
  846    char* line = reader.
Line();
 
  851    if( strncasecmp( line, 
"Element", strlen( 
"Element" ) ) != 0 )
 
  854    aFootprintNameOut = fn.GetName();
 
 
  861                                      bool aBestEfforts, 
const std::map<std::string, UTF8>* aProperties )
 
  863    wxDir     dir( aLibraryPath );
 
  866    if( !dir.IsOpened() )
 
  871            THROW_IO_ERROR( wxString::Format( 
_( 
"Footprint library '%s' not found." ), aLibraryPath ) );
 
  882        errorMsg = ioe.
What();
 
  888    for( 
const auto& footprint : 
m_cache->GetFootprints() )
 
  889        aFootprintNames.Add( 
From_UTF8( footprint.first.c_str() ) );
 
  891    if( !errorMsg.IsEmpty() && !aBestEfforts )
 
 
  897                                            const wxString& aFootprintName,
 
  898                                            const std::map<std::string, UTF8>* aProperties,
 
  905    auto it = 
m_cache->GetFootprints().find( 
TO_UTF8( aFootprintName ) );
 
  907    if( it == 
m_cache->GetFootprints().end() )
 
  910    return it->second->GetFootprint().get();
 
 
  915                                       const wxString& aFootprintName,
 
  917                                       const std::map<std::string, UTF8>* aProperties )
 
  926        copy->SetParent( 
nullptr );
 
 
  935                                   const std::map<std::string, UTF8>* aProperties )
 
  944                                          aLibraryPath.GetData() ) );
 
  947    m_cache->Remove( aFootprintName );
 
 
  954    fn.SetPath( aLibraryPath );
 
  957    if( !fn.DirExists() )
 
  960    if( !fn.IsDirWritable() )
 
  962        THROW_IO_ERROR( wxString::Format( 
_( 
"Insufficient permissions to delete folder '%s'." ),
 
  963                                          aLibraryPath.GetData() ) );
 
  966    wxDir dir( aLibraryPath );
 
  968    if( dir.HasSubDirs() )
 
  970        THROW_IO_ERROR( wxString::Format( 
_( 
"Library folder '%s' has unexpected sub-folders." ),
 
  971                                          aLibraryPath.GetData() ) );
 
  981        wxDir::GetAllFiles( aLibraryPath, &files );
 
  983        for( i = 0;  i < files.GetCount();  i++ )
 
  989                THROW_IO_ERROR( wxString::Format( 
_( 
"Unexpected file '%s' found in library '%s'." ),
 
  991                                                  aLibraryPath.GetData() ) );
 
  995        for( i = 0;  i < files.GetCount();  i++ )
 
  997            wxRemoveFile( files[i] );
 
 1002                aLibraryPath.GetData() );
 
 1006    if( !wxRmdir( aLibraryPath ) )
 
 1008        THROW_IO_ERROR( wxString::Format( 
_( 
"Footprint library '%s' cannot be deleted." ),
 
 1009                                          aLibraryPath.GetData() ) );
 
 1016    wxMilliSleep( 250L );
 
 
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
 
void SetCenter(const VECTOR2I &aCenter)
 
void SetStart(const VECTOR2I &aStart)
 
void SetShape(SHAPE_T aShape)
 
void SetEnd(const VECTOR2I &aEnd)
 
void SetArcAngleAndEnd(const EDA_ANGLE &aAngle, bool aCheckNegativeAngle=false)
Set the end point from the angle center and start.
 
A LINE_READER that reads from an open file.
 
helper class for creating a footprint library cache.
 
std::unique_ptr< FOOTPRINT > m_footprint
 
WX_FILENAME GetFileName() const
 
std::unique_ptr< FOOTPRINT > & GetFootprint()
 
WX_FILENAME m_filename
The full file name and path of the footprint to cache.
 
GPCB_FPL_CACHE_ENTRY(FOOTPRINT *aFootprint, const WX_FILENAME &aFileName)
 
FOOTPRINT * parseFOOTPRINT(LINE_READER *aLineReader)
 
void Remove(const wxString &aFootprintName)
 
boost::ptr_map< std::string, GPCB_FPL_CACHE_ENTRY > & GetFootprints()
 
GPCB_FPL_CACHE(PCB_IO_GEDA *aOwner, const wxString &aLibraryPath)
 
bool IsModified()
Return true if the cache is not up-to-date.
 
static long long GetTimestamp(const wxString &aLibPath)
Generate a timestamp representing all source files in the cache (including the parent directory).
 
PCB_IO_GEDA * m_owner
Plugin object that owns the cache.
 
boost::ptr_map< std::string, GPCB_FPL_CACHE_ENTRY > m_footprints
Map of footprint filename to cache entries.
 
void parseParameters(wxArrayString &aParameterList, LINE_READER *aLineReader)
Extract parameters and tokens from aLineReader and adds them to aParameterList.
 
long long m_cache_timestamp
A hash of the timestamps for all the footprint files.
 
wxFileName m_lib_path
The path of the library.
 
bool m_cache_dirty
Stored separately because it's expensive to check m_cache_timestamp against all the files.
 
void Load()
Save not implemented for the Geda PCB footprint library format.
 
bool testFlags(const wxString &aFlag, long aMask, const wxChar *aName)
Test aFlag for aMask or aName.
 
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
 
virtual const wxString What() const
A composite of Problem() and Where()
 
A logical library item identifier and consists of various portions much like a URI.
 
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
 
virtual char * ReadLine()=0
Read a line of text into the buffer and increments the line number counter.
 
virtual const wxString & GetSource() const
Returns the name of the source of the lines in an abstract sense.
 
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
 
char * Line() const
Return a pointer to the last line that was read in.
 
LSET is a set of PCB_LAYER_IDs.
 
static LSET AllCuMask()
return AllCuMask( MAX_CU_LAYERS );
 
static constexpr PCB_LAYER_ID ALL_LAYERS
! Temporary layer identifier to identify code that is not padstack-aware
 
A #PLUGIN derivation for saving and loading Geda PCB files.
 
void FootprintDelete(const wxString &aLibraryPath, const wxString &aFootprintName, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Delete aFootprintName from the library at aLibraryPath.
 
bool IsLibraryWritable(const wxString &aLibraryPath) override
Return true if the library at aLibraryPath is writable.
 
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, bool aBestEfforts, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Return a list of footprint names contained within the library at aLibraryPath.
 
long long GetLibraryTimestamp(const wxString &aLibraryPath) const override
Generate a timestamp representing all the files in the library (including the library directory).
 
bool DeleteLibrary(const wxString &aLibraryPath, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Delete an existing library and returns true, or if library does not exist returns false,...
 
FOOTPRINT * FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, bool aKeepUUID=false, const std::map< std::string, UTF8 > *aProperties=nullptr) override
Load a footprint having aFootprintName from the aLibraryPath containing a library format that this PC...
 
void init(const std::map< std::string, UTF8 > *aProperties)
 
GPCB_FPL_CACHE * m_cache
Footprint library cache.
 
void validateCache(const wxString &aLibraryPath, bool checkModified=true)
 
LINE_READER * m_reader
no ownership here.
 
friend class GPCB_FPL_CACHE
 
FOOTPRINT * ImportFootprint(const wxString &aFootprintPath, wxString &aFootprintNameOut, const std::map< std::string, UTF8 > *aProperties) override
Load a single footprint from aFootprintPath and put its name in aFootprintNameOut.
 
const FOOTPRINT * getFootprint(const wxString &aLibraryPath, const wxString &aFootprintName, const std::map< std::string, UTF8 > *aProperties, bool checkModified)
 
PCB_IO(const wxString &aName)
 
const std::map< std::string, UTF8 > * m_props
Properties passed via Save() or Load(), no ownership, may be NULL.
 
void Rotate(const VECTOR2I &aRotCentre, const EDA_ANGLE &aAngle) override
Rotate this object.
 
void SetLayer(PCB_LAYER_ID aLayer) override
Set the layer this item is on.
 
void Move(const VECTOR2I &aMoveVector) override
Move this object.
 
void SetStroke(const STROKE_PARAMS &aStroke) override
 
Simple container to manage line stroke parameters.
 
Read lines of text from another LINE_READER but only returns non-comment lines and non-blank lines wi...
 
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
 
A wrapper around a wxFileName which is much more performant with a subset of the API.
 
void SetFullName(const wxString &aFileNameAndExtension)
 
wxString GetFullPath() const
 
static void SetReporter(REPORTER *aReporter)
Set the reporter to use for reporting font substitution warnings.
 
long long TimestampDir(const wxString &aDirPath, const wxString &aFilespec)
A copy of ConvertFileTimeToWx() because wxWidgets left it as a static function private to src/common/...
 
static constexpr EDA_ANGLE ANGLE_360
 
static constexpr EDA_ANGLE ANGLE_180
 
#define IGNORE_PARENT_GROUP
 
static const std::string GedaPcbFootprintLibFileExtension
 
static const std::string KiCadFootprintFileExtension
 
const wxChar *const traceGedaPcbPlugin
Flag to enable GEDA PCB plugin debug output.
 
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
 
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
 
This file contains miscellaneous commonly used macros and functions.
 
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
 
@ SMD
Smd pad, appears on the solder paste layer (default)
 
static long parseInt(const wxString &aValue, double aScalar)
 
#define NEW_GPCB_UNIT_CONV
 
#define OLD_GPCB_UNIT_CONV
 
wxString From_UTF8(const char *cstring)
 
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
 
wxString dump(const wxArrayString &aArray)
Debug helper for printing wxArrayString contents.
 
wxLogTrace helper definitions.
 
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
 
VECTOR2< int32_t > VECTOR2I
 
Definition of file extensions used in Kicad.