KiCad PCB EDA Suite
kicad_plugin.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2012 CERN
5  * Copyright (C) 1992-2017 KiCad Developers, see AUTHORS.txt for contributors.
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, you may find one here:
19  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
20  * or you may search the http://www.gnu.org website for the version 2 license,
21  * or you may write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
23  */
24 
25 #include <fctsys.h>
26 #include <kicad_string.h>
27 #include <common.h>
28 #include <build_version.h> // LEGACY_BOARD_FILE_VERSION
29 #include <macros.h>
31 #include <base_units.h>
32 
33 #include <class_board.h>
34 #include <class_module.h>
35 #include <class_pcb_text.h>
36 #include <class_dimension.h>
37 #include <class_track.h>
38 #include <class_zone.h>
39 #include <class_drawsegment.h>
40 #include <class_mire.h>
41 #include <class_edge_mod.h>
42 #include <pcb_plot_params.h>
43 #include <zones.h>
44 #include <kicad_plugin.h>
45 #include <pcb_parser.h>
46 
47 #include <wx/dir.h>
48 #include <wx/filename.h>
49 #include <wx/wfstream.h>
50 #include <boost/ptr_container/ptr_map.hpp>
51 #include <memory.h>
52 #include <connectivity.h>
53 
54 using namespace PCB_KEYS_T;
55 
56 #define FMTIU BOARD_ITEM::FormatInternalUnits
57 
62 static const wxString traceFootprintLibrary( wxT( "KicadFootprintLib" ) );
63 
65 void filterNetClass( const BOARD& aBoard, NETCLASS& aNetClass )
66 {
67  auto connectivity = aBoard.GetConnectivity();
68 
69  for( NETCLASS::iterator it = aNetClass.begin(); it != aNetClass.end(); )
70  {
71  NETINFO_ITEM* netinfo = aBoard.FindNet( *it );
72 
73  if( netinfo && connectivity->GetNodeCount( netinfo->GetNet() ) <= 0 ) // hopefully there are no nets with negative
74  aNetClass.Remove( it++ ); // node count, but you never know..
75  else
76  ++it;
77  }
78 }
79 
90 {
91  wxFileName m_file_name;
92  wxDateTime m_mod_time;
93  std::unique_ptr<MODULE> m_module;
94 
95 public:
96  FP_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName );
97 
98  wxString GetName() const { return m_file_name.GetDirs().Last(); }
99  wxFileName GetFileName() const { return m_file_name; }
100 
102  bool IsModified() const;
103 
104  MODULE* GetModule() const { return m_module.get(); }
105  void UpdateModificationTime() { m_mod_time = m_file_name.GetModificationTime(); }
106 };
107 
108 
109 FP_CACHE_ITEM::FP_CACHE_ITEM( MODULE* aModule, const wxFileName& aFileName ) :
110  m_module( aModule )
111 {
112  m_file_name = aFileName;
113 
114  if( m_file_name.FileExists() )
115  m_mod_time = m_file_name.GetModificationTime();
116  else
117  m_mod_time.Now();
118 }
119 
120 
122 {
123  if( !m_file_name.FileExists() )
124  return false;
125 
126  wxLogTrace( traceFootprintLibrary, wxT( "File '%s', m_mod_time %s-%s, file mod time: %s-%s." ),
127  GetChars( m_file_name.GetFullPath() ),
128  GetChars( m_mod_time.FormatDate() ), GetChars( m_mod_time.FormatTime() ),
129  GetChars( m_file_name.GetModificationTime().FormatDate() ),
130  GetChars( m_file_name.GetModificationTime().FormatTime() ) );
131 
132  return m_file_name.GetModificationTime() != m_mod_time;
133 }
134 
135 
136 typedef boost::ptr_map< wxString, FP_CACHE_ITEM > MODULE_MAP;
137 typedef MODULE_MAP::iterator MODULE_ITER;
138 typedef MODULE_MAP::const_iterator MODULE_CITER;
139 
140 
141 class FP_CACHE
142 {
144  wxFileName m_lib_path;
145  wxDateTime m_mod_time;
146  MODULE_MAP m_modules;
147 
148 public:
149  FP_CACHE( PCB_IO* aOwner, const wxString& aLibraryPath );
150 
151  wxString GetPath() const { return m_lib_path.GetPath(); }
152  wxDateTime GetLastModificationTime() const { return m_mod_time; }
153  bool IsWritable() const { return m_lib_path.IsOk() && m_lib_path.IsDirWritable(); }
154  MODULE_MAP& GetModules() { return m_modules; }
155 
156  // Most all functions in this class throw IO_ERROR exceptions. There are no
157  // error codes nor user interface calls from here, nor in any PLUGIN.
158  // Catch these exceptions higher up please.
159 
161  void Save();
162 
163  void Load();
164 
165  void Remove( const wxString& aFootprintName );
166 
167  wxDateTime GetLibModificationTime() const;
168 
180  bool IsModified( const wxString& aLibPath,
181  const wxString& aFootprintName = wxEmptyString ) const;
182 
195  bool IsPath( const wxString& aPath ) const;
196 };
197 
198 
199 FP_CACHE::FP_CACHE( PCB_IO* aOwner, const wxString& aLibraryPath )
200 {
201  m_owner = aOwner;
202  m_lib_path.SetPath( aLibraryPath );
203 }
204 
205 
207 {
208  return m_lib_path.GetModificationTime();
209 }
210 
211 
213 {
214  if( !m_lib_path.DirExists() && !m_lib_path.Mkdir() )
215  {
216  THROW_IO_ERROR( wxString::Format( _( "Cannot create footprint library path '%s'" ),
217  m_lib_path.GetPath().GetData() ) );
218  }
219 
220  if( !m_lib_path.IsDirWritable() )
221  {
222  THROW_IO_ERROR( wxString::Format( _( "Footprint library path '%s' is read only" ),
223  GetChars( m_lib_path.GetPath() ) ) );
224  }
225 
226  for( MODULE_ITER it = m_modules.begin(); it != m_modules.end(); ++it )
227  {
228  wxFileName fn = it->second->GetFileName();
229 
230  if( fn.FileExists() && !it->second->IsModified() )
231  continue;
232 
233  wxString tempFileName =
234 #ifdef USE_TMP_FILE
235  fn.CreateTempFileName( fn.GetPath() );
236 #else
237  fn.GetFullPath();
238 #endif
239  // Allow file output stream to go out of scope to close the file stream before
240  // renaming the file.
241  {
242  wxLogTrace( traceFootprintLibrary, wxT( "Creating temporary library file %s" ),
243  GetChars( tempFileName ) );
244 
245  FILE_OUTPUTFORMATTER formatter( tempFileName );
246 
247  m_owner->SetOutputFormatter( &formatter );
248  m_owner->Format( (BOARD_ITEM*) it->second->GetModule() );
249  }
250 
251 #ifdef USE_TMP_FILE
252  wxRemove( fn.GetFullPath() ); // it is not an error if this does not exist
253 
254  // Even on linux you can see an _intermittent_ error when calling wxRename(),
255  // and it is fully inexplicable. See if this dodges the error.
256  wxMilliSleep( 250L );
257 
258  if( !wxRenameFile( tempFileName, fn.GetFullPath() ) )
259  {
260  wxString msg = wxString::Format(
261  _( "Cannot rename temporary file '%s' to footprint library file '%s'" ),
262  GetChars( tempFileName ),
263  GetChars( fn.GetFullPath() )
264  );
265  THROW_IO_ERROR( msg );
266  }
267 #endif
268  it->second->UpdateModificationTime();
270  }
271 }
272 
273 
275 {
276  wxDir dir( m_lib_path.GetPath() );
277 
278  if( !dir.IsOpened() )
279  {
280  wxString msg = wxString::Format(
281  _( "Footprint library path '%s' does not exist" ),
282  GetChars( m_lib_path.GetPath() )
283  );
284 
285  THROW_IO_ERROR( msg );
286  }
287 
288  wxString fpFileName;
289  wxString wildcard = wxT( "*." ) + KiCadFootprintFileExtension;
290 
291  if( dir.GetFirst( &fpFileName, wildcard, wxDIR_FILES ) )
292  {
293  wxString cacheError;
294 
295  do
296  {
297  // prepend the libpath into fullPath
298  wxFileName fullPath( m_lib_path.GetPath(), fpFileName );
299 
300  // Queue I/O errors so only files that fail to parse don't get loaded.
301  try
302  {
303  FILE_LINE_READER reader( fullPath.GetFullPath() );
304 
305  m_owner->m_parser->SetLineReader( &reader );
306 
307  MODULE* footprint = (MODULE*) m_owner->m_parser->Parse();
308 
309  // The footprint name is the file name without the extension.
310  wxString fpName = fullPath.GetName();
311 
312  footprint->SetFPID( LIB_ID( fpName ) );
313  m_modules.insert( fpName, new FP_CACHE_ITEM( footprint, fullPath ) );
314  }
315  catch( const IO_ERROR& ioe )
316  {
317  if( !cacheError.IsEmpty() )
318  cacheError += "\n\n";
319 
320  cacheError += ioe.What();
321  }
322  } while( dir.GetNext( &fpFileName ) );
323 
324  // Remember the file modification time of library file when the
325  // cache snapshot was made, so that in a networked environment we will
326  // reload the cache as needed.
328 
329  if( !cacheError.IsEmpty() )
330  THROW_IO_ERROR( cacheError );
331  }
332 }
333 
334 
335 void FP_CACHE::Remove( const wxString& aFootprintName )
336 {
337  MODULE_CITER it = m_modules.find( aFootprintName );
338 
339  if( it == m_modules.end() )
340  {
341  wxString msg = wxString::Format(
342  _( "library '%s' has no footprint '%s' to delete" ),
343  GetChars( m_lib_path.GetPath() ),
344  GetChars( aFootprintName )
345  );
346  THROW_IO_ERROR( msg );
347  }
348 
349  // Remove the module from the cache and delete the module file from the library.
350  wxString fullPath = it->second->GetFileName().GetFullPath();
351  m_modules.erase( aFootprintName );
352  wxRemoveFile( fullPath );
353 }
354 
355 
356 bool FP_CACHE::IsPath( const wxString& aPath ) const
357 {
358  // Converts path separators to native path separators
359  wxFileName newPath;
360  newPath.AssignDir( aPath );
361 
362  return m_lib_path == newPath;
363 }
364 
365 
366 bool FP_CACHE::IsModified( const wxString& aLibPath, const wxString& aFootprintName ) const
367 {
368  // The library is modified if the library path got deleted or changed.
369  if( !m_lib_path.DirExists() || !IsPath( aLibPath ) )
370  return true;
371 
372  // If no footprint was specified, check every file modification time against the time
373  // it was loaded.
374  if( aFootprintName.IsEmpty() )
375  {
376  for( MODULE_CITER it = m_modules.begin(); it != m_modules.end(); ++it )
377  {
378  wxFileName fn = m_lib_path;
379 
380  fn.SetName( it->second->GetFileName().GetName() );
381  fn.SetExt( KiCadFootprintFileExtension );
382 
383  if( !fn.FileExists() )
384  {
385  wxLogTrace( traceFootprintLibrary,
386  wxT( "Footprint cache file '%s' does not exist." ),
387  fn.GetFullPath().GetData() );
388  return true;
389  }
390 
391  if( it->second->IsModified() )
392  {
393  wxLogTrace( traceFootprintLibrary,
394  wxT( "Footprint cache file '%s' has been modified." ),
395  fn.GetFullPath().GetData() );
396  return true;
397  }
398  }
399  }
400  else
401  {
402  MODULE_CITER it = m_modules.find( aFootprintName );
403 
404  if( it == m_modules.end() || it->second->IsModified() )
405  return true;
406  }
407 
408  return false;
409 }
410 
411 
412 void PCB_IO::Save( const wxString& aFileName, BOARD* aBoard, const PROPERTIES* aProperties )
413 {
414  LOCALE_IO toggle; // toggles on, then off, the C locale.
415 
416  init( aProperties );
417 
418  m_board = aBoard; // after init()
419 
420  // Prepare net mapping that assures that net codes saved in a file are consecutive integers
421  m_mapping->SetBoard( aBoard );
422 
423  FILE_OUTPUTFORMATTER formatter( aFileName );
424 
425  m_out = &formatter; // no ownership
426 
427  m_out->Print( 0, "(kicad_pcb (version %d) (host pcbnew %s)\n", SEXPR_BOARD_FILE_VERSION,
428  formatter.Quotew( GetBuildVersion() ).c_str() );
429 
430  Format( aBoard, 1 );
431 
432  m_out->Print( 0, ")\n" );
433 }
434 
435 
436 BOARD_ITEM* PCB_IO::Parse( const wxString& aClipboardSourceInput )
437 {
438  std::string input = TO_UTF8( aClipboardSourceInput );
439 
440  STRING_LINE_READER reader( input, wxT( "clipboard" ) );
441 
442  m_parser->SetLineReader( &reader );
443 
444  try
445  {
446  return m_parser->Parse();
447  }
448  catch( const PARSE_ERROR& parse_error )
449  {
450  if( m_parser->IsTooRecent() )
451  throw FUTURE_FORMAT_ERROR( parse_error, m_parser->GetRequiredVersion() );
452  else
453  throw;
454  }
455 }
456 
457 
458 void PCB_IO::Format( BOARD_ITEM* aItem, int aNestLevel ) const
459 {
460  LOCALE_IO toggle; // public API function, perform anything convenient for caller
461 
462  switch( aItem->Type() )
463  {
464  case PCB_T:
465  format( static_cast<BOARD*>( aItem ), aNestLevel );
466  break;
467 
468  case PCB_DIMENSION_T:
469  format( static_cast<DIMENSION*>( aItem ), aNestLevel );
470  break;
471 
472  case PCB_LINE_T:
473  format( static_cast<DRAWSEGMENT*>( aItem ), aNestLevel );
474  break;
475 
476  case PCB_MODULE_EDGE_T:
477  format( static_cast<EDGE_MODULE*>( aItem ), aNestLevel );
478  break;
479 
480  case PCB_TARGET_T:
481  format( static_cast<PCB_TARGET*>( aItem ), aNestLevel );
482  break;
483 
484  case PCB_MODULE_T:
485  format( static_cast<MODULE*>( aItem ), aNestLevel );
486  break;
487 
488  case PCB_PAD_T:
489  format( static_cast<D_PAD*>( aItem ), aNestLevel );
490  break;
491 
492  case PCB_TEXT_T:
493  format( static_cast<TEXTE_PCB*>( aItem ), aNestLevel );
494  break;
495 
496  case PCB_MODULE_TEXT_T:
497  format( static_cast<TEXTE_MODULE*>( aItem ), aNestLevel );
498  break;
499 
500  case PCB_TRACE_T:
501  case PCB_VIA_T:
502  format( static_cast<TRACK*>( aItem ), aNestLevel );
503  break;
504 
505  case PCB_ZONE_AREA_T:
506  format( static_cast<ZONE_CONTAINER*>( aItem ), aNestLevel );
507  break;
508 
509  default:
510  wxFAIL_MSG( wxT( "Cannot format item " ) + aItem->GetClass() );
511  }
512 }
513 
514 
515 void PCB_IO::formatLayer( const BOARD_ITEM* aItem ) const
516 {
517  if( m_ctl & CTL_STD_LAYER_NAMES )
518  {
519  PCB_LAYER_ID layer = aItem->GetLayer();
520 
521  // English layer names should never need quoting.
522  m_out->Print( 0, " (layer %s)", TO_UTF8( BOARD::GetStandardLayerName( layer ) ) );
523  }
524  else
525  m_out->Print( 0, " (layer %s)", m_out->Quotew( aItem->GetLayerName() ).c_str() );
526 }
527 
528 
529 void PCB_IO::format( BOARD* aBoard, int aNestLevel ) const
530 {
531  const BOARD_DESIGN_SETTINGS& dsnSettings = aBoard->GetDesignSettings();
532 
533  m_out->Print( 0, "\n" );
534 
535  m_out->Print( aNestLevel, "(general\n" );
536 
537  // Write Bounding box info
538  m_out->Print( aNestLevel+1, "(thickness %s)\n",
539  FMTIU( dsnSettings.GetBoardThickness() ).c_str() );
540 
541  m_out->Print( aNestLevel+1, "(drawings %d)\n", aBoard->Drawings().Size() );
542  m_out->Print( aNestLevel+1, "(tracks %d)\n", aBoard->GetNumSegmTrack() );
543  m_out->Print( aNestLevel+1, "(zones %d)\n", aBoard->GetNumSegmZone() );
544  m_out->Print( aNestLevel+1, "(modules %d)\n", aBoard->m_Modules.GetCount() );
545  m_out->Print( aNestLevel+1, "(nets %d)\n", m_mapping->GetSize() );
546  m_out->Print( aNestLevel, ")\n\n" );
547 
548  aBoard->GetPageSettings().Format( m_out, aNestLevel, m_ctl );
549  aBoard->GetTitleBlock().Format( m_out, aNestLevel, m_ctl );
550 
551  // Layers.
552  m_out->Print( aNestLevel, "(layers\n" );
553 
554  // Save only the used copper layers from front to back.
555  LSET visible_layers = aBoard->GetVisibleLayers();
556 
557  for( LSEQ cu = aBoard->GetEnabledLayers().CuStack(); cu; ++cu )
558  {
559  PCB_LAYER_ID layer = *cu;
560 
561  m_out->Print( aNestLevel+1, "(%d %s %s", layer,
562  m_out->Quotew( aBoard->GetLayerName( layer ) ).c_str(),
563  LAYER::ShowType( aBoard->GetLayerType( layer ) ) );
564 
565  if( !visible_layers[layer] )
566  m_out->Print( 0, " hide" );
567 
568  m_out->Print( 0, ")\n" );
569  }
570 
571  // Save used non-copper layers in the order they are defined.
572  // desired sequence for non Cu BOARD layers.
573  static const PCB_LAYER_ID non_cu[] = {
574  B_Adhes, // 32
575  F_Adhes,
576  B_Paste,
577  F_Paste,
578  B_SilkS,
579  F_SilkS,
580  B_Mask,
581  F_Mask,
582  Dwgs_User,
583  Cmts_User,
584  Eco1_User,
585  Eco2_User,
586  Edge_Cuts,
587  Margin,
588  B_CrtYd,
589  F_CrtYd,
590  B_Fab,
591  F_Fab
592  };
593 
594  for( LSEQ seq = aBoard->GetEnabledLayers().Seq( non_cu, DIM( non_cu ) ); seq; ++seq )
595  {
596  PCB_LAYER_ID layer = *seq;
597 
598  m_out->Print( aNestLevel+1, "(%d %s user", layer,
599  m_out->Quotew( aBoard->GetLayerName( layer ) ).c_str() );
600 
601  if( !visible_layers[layer] )
602  m_out->Print( 0, " hide" );
603 
604  m_out->Print( 0, ")\n" );
605  }
606 
607  m_out->Print( aNestLevel, ")\n\n" );
608 
609  // Setup
610  m_out->Print( aNestLevel, "(setup\n" );
611 
612  // Save current default track width, for compatibility with older Pcbnew version;
613  m_out->Print( aNestLevel+1, "(last_trace_width %s)\n",
614  FMTIU( dsnSettings.GetCurrentTrackWidth() ).c_str() );
615 
616  // Save custom tracks width list (the first is not saved here: this is the netclass value
617  for( unsigned ii = 1; ii < dsnSettings.m_TrackWidthList.size(); ii++ )
618  m_out->Print( aNestLevel+1, "(user_trace_width %s)\n",
619  FMTIU( dsnSettings.m_TrackWidthList[ii] ).c_str() );
620 
621  m_out->Print( aNestLevel+1, "(trace_clearance %s)\n",
622  FMTIU( dsnSettings.GetDefault()->GetClearance() ).c_str() );
623 
624  // ZONE_SETTINGS
625  m_out->Print( aNestLevel+1, "(zone_clearance %s)\n",
626  FMTIU( aBoard->GetZoneSettings().m_ZoneClearance ).c_str() );
627  m_out->Print( aNestLevel+1, "(zone_45_only %s)\n",
628  aBoard->GetZoneSettings().m_Zone_45_Only ? "yes" : "no" );
629 
630  m_out->Print( aNestLevel+1, "(trace_min %s)\n",
631  FMTIU( dsnSettings.m_TrackMinWidth ).c_str() );
632 
633  m_out->Print( aNestLevel+1, "(segment_width %s)\n",
634  FMTIU( dsnSettings.m_DrawSegmentWidth ).c_str() );
635  m_out->Print( aNestLevel+1, "(edge_width %s)\n",
636  FMTIU( dsnSettings.m_EdgeSegmentWidth ).c_str() );
637 
638  // Save current default via size, for compatibility with older Pcbnew version;
639  m_out->Print( aNestLevel+1, "(via_size %s)\n",
640  FMTIU( dsnSettings.GetDefault()->GetViaDiameter() ).c_str() );
641  m_out->Print( aNestLevel+1, "(via_drill %s)\n",
642  FMTIU( dsnSettings.GetDefault()->GetViaDrill() ).c_str() );
643  m_out->Print( aNestLevel+1, "(via_min_size %s)\n",
644  FMTIU( dsnSettings.m_ViasMinSize ).c_str() );
645  m_out->Print( aNestLevel+1, "(via_min_drill %s)\n",
646  FMTIU( dsnSettings.m_ViasMinDrill ).c_str() );
647 
648  // Save custom vias diameters list (the first is not saved here: this is
649  // the netclass value
650  for( unsigned ii = 1; ii < dsnSettings.m_ViasDimensionsList.size(); ii++ )
651  m_out->Print( aNestLevel+1, "(user_via %s %s)\n",
652  FMTIU( dsnSettings.m_ViasDimensionsList[ii].m_Diameter ).c_str(),
653  FMTIU( dsnSettings.m_ViasDimensionsList[ii].m_Drill ).c_str() );
654 
655  // for old versions compatibility:
656  if( dsnSettings.m_BlindBuriedViaAllowed )
657  m_out->Print( aNestLevel+1, "(blind_buried_vias_allowed yes)\n" );
658 
659  m_out->Print( aNestLevel+1, "(uvia_size %s)\n",
660  FMTIU( dsnSettings.GetDefault()->GetuViaDiameter() ).c_str() );
661  m_out->Print( aNestLevel+1, "(uvia_drill %s)\n",
662  FMTIU( dsnSettings.GetDefault()->GetuViaDrill() ).c_str() );
663  m_out->Print( aNestLevel+1, "(uvias_allowed %s)\n",
664  ( dsnSettings.m_MicroViasAllowed ) ? "yes" : "no" );
665  m_out->Print( aNestLevel+1, "(uvia_min_size %s)\n",
666  FMTIU( dsnSettings.m_MicroViasMinSize ).c_str() );
667  m_out->Print( aNestLevel+1, "(uvia_min_drill %s)\n",
668  FMTIU( dsnSettings.m_MicroViasMinDrill ).c_str() );
669 
670  m_out->Print( aNestLevel+1, "(pcb_text_width %s)\n",
671  FMTIU( dsnSettings.m_PcbTextWidth ).c_str() );
672  m_out->Print( aNestLevel+1, "(pcb_text_size %s %s)\n",
673  FMTIU( dsnSettings.m_PcbTextSize.x ).c_str(),
674  FMTIU( dsnSettings.m_PcbTextSize.y ).c_str() );
675 
676  m_out->Print( aNestLevel+1, "(mod_edge_width %s)\n",
677  FMTIU( dsnSettings.m_ModuleSegmentWidth ).c_str() );
678  m_out->Print( aNestLevel+1, "(mod_text_size %s %s)\n",
679  FMTIU( dsnSettings.m_ModuleTextSize.x ).c_str(),
680  FMTIU( dsnSettings.m_ModuleTextSize.y ).c_str() );
681  m_out->Print( aNestLevel+1, "(mod_text_width %s)\n",
682  FMTIU( dsnSettings.m_ModuleTextWidth ).c_str() );
683 
684  m_out->Print( aNestLevel+1, "(pad_size %s %s)\n",
685  FMTIU( dsnSettings.m_Pad_Master.GetSize().x ).c_str(),
686  FMTIU( dsnSettings.m_Pad_Master.GetSize().y ).c_str() );
687  m_out->Print( aNestLevel+1, "(pad_drill %s)\n",
688  FMTIU( dsnSettings.m_Pad_Master.GetDrillSize().x ).c_str() );
689 
690  m_out->Print( aNestLevel+1, "(pad_to_mask_clearance %s)\n",
691  FMTIU( dsnSettings.m_SolderMaskMargin ).c_str() );
692 
693  if( dsnSettings.m_SolderMaskMinWidth )
694  m_out->Print( aNestLevel+1, "(solder_mask_min_width %s)\n",
695  FMTIU( dsnSettings.m_SolderMaskMinWidth ).c_str() );
696 
697  if( dsnSettings.m_SolderPasteMargin != 0 )
698  m_out->Print( aNestLevel+1, "(pad_to_paste_clearance %s)\n",
699  FMTIU( dsnSettings.m_SolderPasteMargin ).c_str() );
700 
701  if( dsnSettings.m_SolderPasteMarginRatio != 0 )
702  m_out->Print( aNestLevel+1, "(pad_to_paste_clearance_ratio %s)\n",
703  Double2Str( dsnSettings.m_SolderPasteMarginRatio ).c_str() );
704 
705  m_out->Print( aNestLevel+1, "(aux_axis_origin %s %s)\n",
706  FMTIU( aBoard->GetAuxOrigin().x ).c_str(),
707  FMTIU( aBoard->GetAuxOrigin().y ).c_str() );
708 
709  if( aBoard->GetGridOrigin().x || aBoard->GetGridOrigin().y )
710  m_out->Print( aNestLevel+1, "(grid_origin %s %s)\n",
711  FMTIU( aBoard->GetGridOrigin().x ).c_str(),
712  FMTIU( aBoard->GetGridOrigin().y ).c_str() );
713 
714  m_out->Print( aNestLevel+1, "(visible_elements %X)\n",
715  dsnSettings.GetVisibleElements() );
716 
717  aBoard->GetPlotOptions().Format( m_out, aNestLevel+1 );
718 
719  m_out->Print( aNestLevel, ")\n\n" );
720 
721  // Save net codes and names
722  for( NETINFO_MAPPING::iterator net = m_mapping->begin(), netEnd = m_mapping->end();
723  net != netEnd; ++net )
724  {
725  m_out->Print( aNestLevel, "(net %d %s)\n",
726  m_mapping->Translate( net->GetNet() ),
727  m_out->Quotew( net->GetNetname() ).c_str() );
728  }
729 
730  m_out->Print( 0, "\n" );
731 
732  // Save the default net class first.
733  NETCLASS defaultNC = *dsnSettings.GetDefault();
734  filterNetClass( *aBoard, defaultNC ); // Remove empty nets (from a copy of a netclass)
735  defaultNC.Format( m_out, aNestLevel, m_ctl );
736 
737  // Save the rest of the net classes alphabetically.
738  for( NETCLASSES::const_iterator it = dsnSettings.m_NetClasses.begin();
739  it != dsnSettings.m_NetClasses.end();
740  ++it )
741  {
742  NETCLASS netclass = *it->second;
743  filterNetClass( *aBoard, netclass ); // Remove empty nets (from a copy of a netclass)
744  netclass.Format( m_out, aNestLevel, m_ctl );
745  }
746 
747  // Save the modules.
748  for( MODULE* module = aBoard->m_Modules; module; module = module->Next() )
749  {
750  Format( module, aNestLevel );
751  m_out->Print( 0, "\n" );
752  }
753 
754  // Save the graphical items on the board (not owned by a module)
755  for( auto item : aBoard->Drawings() )
756  Format( item, aNestLevel );
757 
758  if( aBoard->Drawings().Size() )
759  m_out->Print( 0, "\n" );
760 
761  // Do not save MARKER_PCBs, they can be regenerated easily.
762 
763  // Save the tracks and vias.
764  for( TRACK* track = aBoard->m_Track; track; track = track->Next() )
765  Format( track, aNestLevel );
766 
767  if( aBoard->m_Track.GetCount() )
768  m_out->Print( 0, "\n" );
769 
772 
773  // Save the polygon (which are the newer technology) zones.
774  for( int i = 0; i < aBoard->GetAreaCount(); ++i )
775  Format( aBoard->GetArea( i ), aNestLevel );
776 }
777 
778 
779 void PCB_IO::format( DIMENSION* aDimension, int aNestLevel ) const
780 {
781  m_out->Print( aNestLevel, "(dimension %s (width %s)",
782  FMT_IU( aDimension->GetValue() ).c_str(),
783  FMT_IU( aDimension->GetWidth() ).c_str() );
784 
785  formatLayer( aDimension );
786 
787  if( aDimension->GetTimeStamp() )
788  m_out->Print( 0, " (tstamp %lX)", (unsigned long)aDimension->GetTimeStamp() );
789 
790  m_out->Print( 0, "\n" );
791 
792  Format( &aDimension->Text(), aNestLevel+1 );
793 
794  m_out->Print( aNestLevel+1, "(feature1 (pts (xy %s %s) (xy %s %s)))\n",
795  FMT_IU( aDimension->m_featureLineDO.x ).c_str(),
796  FMT_IU( aDimension->m_featureLineDO.y ).c_str(),
797  FMT_IU( aDimension->m_featureLineDF.x ).c_str(),
798  FMT_IU( aDimension->m_featureLineDF.y ).c_str() );
799 
800  m_out->Print( aNestLevel+1, "(feature2 (pts (xy %s %s) (xy %s %s)))\n",
801  FMT_IU( aDimension->m_featureLineGO.x ).c_str(),
802  FMT_IU( aDimension->m_featureLineGO.y ).c_str(),
803  FMT_IU( aDimension->m_featureLineGF.x ).c_str(),
804  FMT_IU( aDimension->m_featureLineGF.y ).c_str() );
805 
806  m_out->Print( aNestLevel+1, "(crossbar (pts (xy %s %s) (xy %s %s)))\n",
807  FMT_IU( aDimension->m_crossBarO.x ).c_str(),
808  FMT_IU( aDimension->m_crossBarO.y ).c_str(),
809  FMT_IU( aDimension->m_crossBarF.x ).c_str(),
810  FMT_IU( aDimension->m_crossBarF.y ).c_str() );
811 
812  m_out->Print( aNestLevel+1, "(arrow1a (pts (xy %s %s) (xy %s %s)))\n",
813  FMT_IU( aDimension->m_crossBarF.x ).c_str(),
814  FMT_IU( aDimension->m_crossBarF.y ).c_str(),
815  FMT_IU( aDimension->m_arrowD1F.x ).c_str(),
816  FMT_IU( aDimension->m_arrowD1F.y ).c_str() );
817 
818  m_out->Print( aNestLevel+1, "(arrow1b (pts (xy %s %s) (xy %s %s)))\n",
819  FMT_IU( aDimension->m_crossBarF.x ).c_str(),
820  FMT_IU( aDimension->m_crossBarF.y ).c_str(),
821  FMT_IU( aDimension->m_arrowD2F.x ).c_str(),
822  FMT_IU( aDimension->m_arrowD2F.y ).c_str() );
823 
824  m_out->Print( aNestLevel+1, "(arrow2a (pts (xy %s %s) (xy %s %s)))\n",
825  FMT_IU( aDimension->m_crossBarO.x ).c_str(),
826  FMT_IU( aDimension->m_crossBarO.y ).c_str(),
827  FMT_IU( aDimension->m_arrowG1F.x ).c_str(),
828  FMT_IU( aDimension->m_arrowG1F.y ).c_str() );
829 
830  m_out->Print( aNestLevel+1, "(arrow2b (pts (xy %s %s) (xy %s %s)))\n",
831  FMT_IU( aDimension->m_crossBarO.x ).c_str(),
832  FMT_IU( aDimension->m_crossBarO.y ).c_str(),
833  FMT_IU( aDimension->m_arrowG2F.x ).c_str(),
834  FMT_IU( aDimension->m_arrowG2F.y ).c_str() );
835 
836  m_out->Print( aNestLevel, ")\n" );
837 }
838 
839 
840 void PCB_IO::format( DRAWSEGMENT* aSegment, int aNestLevel ) const
841 {
842  unsigned i;
843 
844  switch( aSegment->GetShape() )
845  {
846  case S_SEGMENT: // Line
847  m_out->Print( aNestLevel, "(gr_line (start %s) (end %s)",
848  FMT_IU( aSegment->GetStart() ).c_str(),
849  FMT_IU( aSegment->GetEnd() ).c_str() );
850 
851  if( aSegment->GetAngle() != 0.0 )
852  m_out->Print( 0, " (angle %s)", FMT_ANGLE( aSegment->GetAngle() ).c_str() );
853 
854  break;
855 
856  case S_CIRCLE: // Circle
857  m_out->Print( aNestLevel, "(gr_circle (center %s) (end %s)",
858  FMT_IU( aSegment->GetStart() ).c_str(),
859  FMT_IU( aSegment->GetEnd() ).c_str() );
860  break;
861 
862  case S_ARC: // Arc
863  m_out->Print( aNestLevel, "(gr_arc (start %s) (end %s) (angle %s)",
864  FMT_IU( aSegment->GetStart() ).c_str(),
865  FMT_IU( aSegment->GetEnd() ).c_str(),
866  FMT_ANGLE( aSegment->GetAngle() ).c_str() );
867  break;
868 
869  case S_POLYGON: // Polygon
870  m_out->Print( aNestLevel, "(gr_poly (pts" );
871 
872  for( i = 0; i < aSegment->GetPolyPoints().size(); ++i )
873  m_out->Print( 0, " (xy %s)", FMT_IU( aSegment->GetPolyPoints()[i] ).c_str() );
874 
875  m_out->Print( 0, ")" );
876  break;
877 
878  case S_CURVE: // Bezier curve
879  m_out->Print( aNestLevel, "(gr_curve (pts (xy %s) (xy %s) (xy %s) (xy %s))",
880  FMT_IU( aSegment->GetStart() ).c_str(),
881  FMT_IU( aSegment->GetBezControl1() ).c_str(),
882  FMT_IU( aSegment->GetBezControl2() ).c_str(),
883  FMT_IU( aSegment->GetEnd() ).c_str() );
884  break;
885 
886  default:
887  wxFAIL_MSG( wxT( "Cannot format invalid DRAWSEGMENT type." ) );
888  };
889 
890  formatLayer( aSegment );
891 
892  if( aSegment->GetWidth() != 0 )
893  m_out->Print( 0, " (width %s)", FMT_IU( aSegment->GetWidth() ).c_str() );
894 
895  if( aSegment->GetTimeStamp() )
896  m_out->Print( 0, " (tstamp %lX)", (unsigned long)aSegment->GetTimeStamp() );
897 
898  if( aSegment->GetStatus() )
899  m_out->Print( 0, " (status %X)", aSegment->GetStatus() );
900 
901  m_out->Print( 0, ")\n" );
902 }
903 
904 
905 void PCB_IO::format( EDGE_MODULE* aModuleDrawing, int aNestLevel ) const
906 {
907  switch( aModuleDrawing->GetShape() )
908  {
909  case S_SEGMENT: // Line
910  m_out->Print( aNestLevel, "(fp_line (start %s) (end %s)",
911  FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
912  FMT_IU( aModuleDrawing->GetEnd0() ).c_str() );
913  break;
914 
915  case S_CIRCLE: // Circle
916  m_out->Print( aNestLevel, "(fp_circle (center %s) (end %s)",
917  FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
918  FMT_IU( aModuleDrawing->GetEnd0() ).c_str() );
919  break;
920 
921  case S_ARC: // Arc
922  m_out->Print( aNestLevel, "(fp_arc (start %s) (end %s) (angle %s)",
923  FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
924  FMT_IU( aModuleDrawing->GetEnd0() ).c_str(),
925  FMT_ANGLE( aModuleDrawing->GetAngle() ).c_str() );
926  break;
927 
928  case S_POLYGON: // Polygon
929  m_out->Print( aNestLevel, "(fp_poly (pts" );
930 
931  for( unsigned i = 0; i < aModuleDrawing->GetPolyPoints().size(); ++i )
932  {
933  int nestLevel = 0;
934 
935  if( i && !(i%4) ) // newline every 4(pts)
936  {
937  nestLevel = aNestLevel + 1;
938  m_out->Print( 0, "\n" );
939  }
940 
941  m_out->Print( nestLevel, "%s(xy %s)",
942  nestLevel ? "" : " ",
943  FMT_IU( aModuleDrawing->GetPolyPoints()[i] ).c_str() );
944  }
945  m_out->Print( 0, ")" );
946  break;
947 
948  case S_CURVE: // Bezier curve
949  m_out->Print( aNestLevel, "(fp_curve (pts (xy %s) (xy %s) (xy %s) (xy %s))",
950  FMT_IU( aModuleDrawing->GetStart0() ).c_str(),
951  FMT_IU( aModuleDrawing->GetBezControl1() ).c_str(),
952  FMT_IU( aModuleDrawing->GetBezControl2() ).c_str(),
953  FMT_IU( aModuleDrawing->GetEnd0() ).c_str() );
954  break;
955 
956  default:
957  wxFAIL_MSG( wxT( "Cannot format invalid DRAWSEGMENT type." ) );
958  };
959 
960  formatLayer( aModuleDrawing );
961 
962  m_out->Print( 0, " (width %s)", FMT_IU( aModuleDrawing->GetWidth() ).c_str() );
963 
964  m_out->Print( 0, ")\n" );
965 }
966 
967 
968 void PCB_IO::format( PCB_TARGET* aTarget, int aNestLevel ) const
969 {
970  m_out->Print( aNestLevel, "(target %s (at %s) (size %s)",
971  ( aTarget->GetShape() ) ? "x" : "plus",
972  FMT_IU( aTarget->GetPosition() ).c_str(),
973  FMT_IU( aTarget->GetSize() ).c_str() );
974 
975  if( aTarget->GetWidth() != 0 )
976  m_out->Print( 0, " (width %s)", FMT_IU( aTarget->GetWidth() ).c_str() );
977 
978  formatLayer( aTarget );
979 
980  if( aTarget->GetTimeStamp() )
981  m_out->Print( 0, " (tstamp %lX)", (unsigned long)aTarget->GetTimeStamp() );
982 
983  m_out->Print( 0, ")\n" );
984 }
985 
986 
987 void PCB_IO::format( MODULE* aModule, int aNestLevel ) const
988 {
989  if( !( m_ctl & CTL_OMIT_INITIAL_COMMENTS ) )
990  {
991  const wxArrayString* initial_comments = aModule->GetInitialComments();
992 
993  if( initial_comments )
994  {
995  for( unsigned i=0; i<initial_comments->GetCount(); ++i )
996  m_out->Print( aNestLevel, "%s\n", TO_UTF8( (*initial_comments)[i] ) );
997 
998  m_out->Print( 0, "\n" ); // improve readability?
999  }
1000  }
1001 
1002  m_out->Print( aNestLevel, "(module %s",
1003  m_out->Quotes( aModule->GetFPID().Format() ).c_str() );
1004 
1005  if( aModule->IsLocked() )
1006  m_out->Print( 0, " locked" );
1007 
1008  if( aModule->IsPlaced() )
1009  m_out->Print( 0, " placed" );
1010 
1011  formatLayer( aModule );
1012 
1013  m_out->Print( 0, " (tedit %lX)", (unsigned long)aModule->GetLastEditTime() );
1014 
1015  if( !( m_ctl & CTL_OMIT_TSTAMPS ) )
1016  {
1017  m_out->Print( 0, " (tstamp %lX)\n", (unsigned long)aModule->GetTimeStamp() );
1018  }
1019  else
1020  m_out->Print( 0, "\n" );
1021 
1022  if( !( m_ctl & CTL_OMIT_AT ) )
1023  {
1024  m_out->Print( aNestLevel+1, "(at %s", FMT_IU( aModule->GetPosition() ).c_str() );
1025 
1026  if( aModule->GetOrientation() != 0.0 )
1027  m_out->Print( 0, " %s", FMT_ANGLE( aModule->GetOrientation() ).c_str() );
1028 
1029  m_out->Print( 0, ")\n" );
1030  }
1031 
1032  if( !aModule->GetDescription().IsEmpty() )
1033  m_out->Print( aNestLevel+1, "(descr %s)\n",
1034  m_out->Quotew( aModule->GetDescription() ).c_str() );
1035 
1036  if( !aModule->GetKeywords().IsEmpty() )
1037  m_out->Print( aNestLevel+1, "(tags %s)\n",
1038  m_out->Quotew( aModule->GetKeywords() ).c_str() );
1039 
1040  if( !( m_ctl & CTL_OMIT_PATH ) && !!aModule->GetPath() )
1041  m_out->Print( aNestLevel+1, "(path %s)\n",
1042  m_out->Quotew( aModule->GetPath() ).c_str() );
1043 
1044  if( aModule->GetPlacementCost90() != 0 )
1045  m_out->Print( aNestLevel+1, "(autoplace_cost90 %d)\n", aModule->GetPlacementCost90() );
1046 
1047  if( aModule->GetPlacementCost180() != 0 )
1048  m_out->Print( aNestLevel+1, "(autoplace_cost180 %d)\n", aModule->GetPlacementCost180() );
1049 
1050  if( aModule->GetLocalSolderMaskMargin() != 0 )
1051  m_out->Print( aNestLevel+1, "(solder_mask_margin %s)\n",
1052  FMT_IU( aModule->GetLocalSolderMaskMargin() ).c_str() );
1053 
1054  if( aModule->GetLocalSolderPasteMargin() != 0 )
1055  m_out->Print( aNestLevel+1, "(solder_paste_margin %s)\n",
1056  FMT_IU( aModule->GetLocalSolderPasteMargin() ).c_str() );
1057 
1058  if( aModule->GetLocalSolderPasteMarginRatio() != 0 )
1059  m_out->Print( aNestLevel+1, "(solder_paste_ratio %s)\n",
1060  Double2Str( aModule->GetLocalSolderPasteMarginRatio() ).c_str() );
1061 
1062  if( aModule->GetLocalClearance() != 0 )
1063  m_out->Print( aNestLevel+1, "(clearance %s)\n",
1064  FMT_IU( aModule->GetLocalClearance() ).c_str() );
1065 
1066  if( aModule->GetZoneConnection() != PAD_ZONE_CONN_INHERITED )
1067  m_out->Print( aNestLevel+1, "(zone_connect %d)\n", aModule->GetZoneConnection() );
1068 
1069  if( aModule->GetThermalWidth() != 0 )
1070  m_out->Print( aNestLevel+1, "(thermal_width %s)\n",
1071  FMT_IU( aModule->GetThermalWidth() ).c_str() );
1072 
1073  if( aModule->GetThermalGap() != 0 )
1074  m_out->Print( aNestLevel+1, "(thermal_gap %s)\n",
1075  FMT_IU( aModule->GetThermalGap() ).c_str() );
1076 
1077  // Attributes
1078  if( aModule->GetAttributes() != MOD_DEFAULT )
1079  {
1080  m_out->Print( aNestLevel+1, "(attr" );
1081 
1082  if( aModule->GetAttributes() & MOD_CMS )
1083  m_out->Print( 0, " smd" );
1084 
1085  if( aModule->GetAttributes() & MOD_VIRTUAL )
1086  m_out->Print( 0, " virtual" );
1087 
1088  m_out->Print( 0, ")\n" );
1089  }
1090 
1091  Format( (BOARD_ITEM*) &aModule->Reference(), aNestLevel+1 );
1092  Format( (BOARD_ITEM*) &aModule->Value(), aNestLevel+1 );
1093 
1094  // Save drawing elements.
1095  for( BOARD_ITEM* gr = aModule->GraphicalItemsList(); gr; gr = gr->Next() )
1096  Format( gr, aNestLevel+1 );
1097 
1098  // Save pads.
1099  for( D_PAD* pad = aModule->PadsList(); pad; pad = pad->Next() )
1100  format( pad, aNestLevel+1 );
1101 
1102  // Save 3D info.
1103  std::list<S3D_INFO>::const_iterator bs3D = aModule->Models().begin();
1104  std::list<S3D_INFO>::const_iterator es3D = aModule->Models().end();
1105 
1106  while( bs3D != es3D )
1107  {
1108  if( !bs3D->m_Filename.IsEmpty() )
1109  {
1110  m_out->Print( aNestLevel+1, "(model %s\n",
1111  m_out->Quotew( bs3D->m_Filename ).c_str() );
1112 
1113  m_out->Print( aNestLevel+2, "(at (xyz %s %s %s))\n",
1114  Double2Str( bs3D->m_Offset.x ).c_str(),
1115  Double2Str( bs3D->m_Offset.y ).c_str(),
1116  Double2Str( bs3D->m_Offset.z ).c_str() );
1117 
1118  m_out->Print( aNestLevel+2, "(scale (xyz %s %s %s))\n",
1119  Double2Str( bs3D->m_Scale.x ).c_str(),
1120  Double2Str( bs3D->m_Scale.y ).c_str(),
1121  Double2Str( bs3D->m_Scale.z ).c_str() );
1122 
1123  m_out->Print( aNestLevel+2, "(rotate (xyz %s %s %s))\n",
1124  Double2Str( bs3D->m_Rotation.x ).c_str(),
1125  Double2Str( bs3D->m_Rotation.y ).c_str(),
1126  Double2Str( bs3D->m_Rotation.z ).c_str() );
1127 
1128  m_out->Print( aNestLevel+1, ")\n" );
1129  }
1130  ++bs3D;
1131  }
1132 
1133  m_out->Print( aNestLevel, ")\n" );
1134 }
1135 
1136 
1137 void PCB_IO::formatLayers( LSET aLayerMask, int aNestLevel ) const
1138 {
1139  std::string output;
1140 
1141  if( aNestLevel == 0 )
1142  output += ' ';
1143 
1144  output += "(layers";
1145 
1146  static const LSET cu_all( LSET::AllCuMask() );
1147  static const LSET fr_bk( 2, B_Cu, F_Cu );
1148  static const LSET adhes( 2, B_Adhes, F_Adhes );
1149  static const LSET paste( 2, B_Paste, F_Paste );
1150  static const LSET silks( 2, B_SilkS, F_SilkS );
1151  static const LSET mask( 2, B_Mask, F_Mask );
1152  static const LSET crt_yd(2, B_CrtYd, F_CrtYd );
1153  static const LSET fab( 2, B_Fab, F_Fab );
1154 
1155  LSET cu_mask = cu_all;
1156 
1157  if( m_board )
1158  cu_mask &= m_board->GetEnabledLayers();
1159 
1160  // output copper layers first, then non copper
1161 
1162  if( ( aLayerMask & cu_mask ) == cu_mask )
1163  {
1164  output += " *.Cu";
1165  aLayerMask &= ~cu_all; // clear bits, so they are not output again below
1166  }
1167  else if( ( aLayerMask & cu_mask ) == fr_bk )
1168  {
1169  output += " F&B.Cu";
1170  aLayerMask &= ~fr_bk;
1171  }
1172 
1173  if( ( aLayerMask & adhes ) == adhes )
1174  {
1175  output += " *.Adhes";
1176  aLayerMask &= ~adhes;
1177  }
1178 
1179  if( ( aLayerMask & paste ) == paste )
1180  {
1181  output += " *.Paste";
1182  aLayerMask &= ~paste;
1183  }
1184 
1185  if( ( aLayerMask & silks ) == silks )
1186  {
1187  output += " *.SilkS";
1188  aLayerMask &= ~silks;
1189  }
1190 
1191  if( ( aLayerMask & mask ) == mask )
1192  {
1193  output += " *.Mask";
1194  aLayerMask &= ~mask;
1195  }
1196 
1197  if( ( aLayerMask & crt_yd ) == crt_yd )
1198  {
1199  output += " *.CrtYd";
1200  aLayerMask &= ~crt_yd;
1201  }
1202 
1203  if( ( aLayerMask & fab ) == fab )
1204  {
1205  output += " *.Fab";
1206  aLayerMask &= ~fab;
1207  }
1208 
1209  // output any individual layers not handled in wildcard combos above
1210 
1211  if( m_board )
1212  aLayerMask &= m_board->GetEnabledLayers();
1213 
1214  wxString layerName;
1215 
1216  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
1217  {
1218  if( aLayerMask[layer] )
1219  {
1220  if( m_board && !( m_ctl & CTL_STD_LAYER_NAMES ) )
1221  layerName = m_board->GetLayerName( PCB_LAYER_ID( layer ) );
1222 
1223  else // I am being called from FootprintSave()
1224  layerName = BOARD::GetStandardLayerName( PCB_LAYER_ID( layer ) );
1225 
1226  output += ' ';
1227  output += m_out->Quotew( layerName );
1228  }
1229  }
1230 
1231  m_out->Print( aNestLevel, "%s)", output.c_str() );
1232 }
1233 
1234 
1235 void PCB_IO::format( D_PAD* aPad, int aNestLevel ) const
1236 {
1237  const char* shape;
1238 
1239  switch( aPad->GetShape() )
1240  {
1241  case PAD_SHAPE_CIRCLE: shape = "circle"; break;
1242  case PAD_SHAPE_RECT: shape = "rect"; break;
1243  case PAD_SHAPE_OVAL: shape = "oval"; break;
1244  case PAD_SHAPE_TRAPEZOID: shape = "trapezoid"; break;
1245  case PAD_SHAPE_ROUNDRECT: shape = "roundrect"; break;
1246 
1247  default:
1248  THROW_IO_ERROR( wxString::Format( _( "unknown pad type: %d"), aPad->GetShape() ) );
1249  }
1250 
1251  const char* type;
1252 
1253  switch( aPad->GetAttribute() )
1254  {
1255  case PAD_ATTRIB_STANDARD: type = "thru_hole"; break;
1256  case PAD_ATTRIB_SMD: type = "smd"; break;
1257  case PAD_ATTRIB_CONN: type = "connect"; break;
1258  case PAD_ATTRIB_HOLE_NOT_PLATED: type = "np_thru_hole"; break;
1259 
1260  default:
1261  THROW_IO_ERROR( wxString::Format( _( "unknown pad attribute: %d" ),
1262  aPad->GetAttribute() ) );
1263  }
1264 
1265  m_out->Print( aNestLevel, "(pad %s %s %s",
1266  m_out->Quotew( aPad->GetPadName() ).c_str(),
1267  type, shape );
1268  m_out->Print( 0, " (at %s", FMT_IU( aPad->GetPos0() ).c_str() );
1269 
1270  if( aPad->GetOrientation() != 0.0 )
1271  m_out->Print( 0, " %s", FMT_ANGLE( aPad->GetOrientation() ).c_str() );
1272 
1273  m_out->Print( 0, ")" );
1274  m_out->Print( 0, " (size %s)", FMT_IU( aPad->GetSize() ).c_str() );
1275 
1276  if( (aPad->GetDelta().GetWidth()) != 0 || (aPad->GetDelta().GetHeight() != 0 ) )
1277  m_out->Print( 0, " (rect_delta %s )", FMT_IU( aPad->GetDelta() ).c_str() );
1278 
1279  wxSize sz = aPad->GetDrillSize();
1280  wxPoint shapeoffset = aPad->GetOffset();
1281 
1282  if( (sz.GetWidth() > 0) || (sz.GetHeight() > 0) ||
1283  (shapeoffset.x != 0) || (shapeoffset.y != 0) )
1284  {
1285  m_out->Print( 0, " (drill" );
1286 
1287  if( aPad->GetDrillShape() == PAD_DRILL_SHAPE_OBLONG )
1288  m_out->Print( 0, " oval" );
1289 
1290  if( sz.GetWidth() > 0 )
1291  m_out->Print( 0, " %s", FMT_IU( sz.GetWidth() ).c_str() );
1292 
1293  if( sz.GetHeight() > 0 && sz.GetWidth() != sz.GetHeight() )
1294  m_out->Print( 0, " %s", FMT_IU( sz.GetHeight() ).c_str() );
1295 
1296  if( (shapeoffset.x != 0) || (shapeoffset.y != 0) )
1297  m_out->Print( 0, " (offset %s)", FMT_IU( aPad->GetOffset() ).c_str() );
1298 
1299  m_out->Print( 0, ")" );
1300  }
1301 
1302  formatLayers( aPad->GetLayerSet(), 0 );
1303 
1304  // Output the radius ratio for rounded rect pads
1305  if( aPad->GetShape() == PAD_SHAPE_ROUNDRECT )
1306  {
1307  m_out->Print( 0, "(roundrect_rratio %s)",
1308  Double2Str( aPad->GetRoundRectRadiusRatio() ).c_str() );
1309  }
1310 
1311  std::string output;
1312 
1313  // Unconnected pad is default net so don't save it.
1314  if( !( m_ctl & CTL_OMIT_NETS ) && aPad->GetNetCode() != NETINFO_LIST::UNCONNECTED )
1315  StrPrintf( &output, " (net %d %s)", m_mapping->Translate( aPad->GetNetCode() ),
1316  m_out->Quotew( aPad->GetNetname() ).c_str() );
1317 
1318  if( aPad->GetPadToDieLength() != 0 )
1319  StrPrintf( &output, " (die_length %s)", FMT_IU( aPad->GetPadToDieLength() ).c_str() );
1320 
1321  if( aPad->GetLocalSolderMaskMargin() != 0 )
1322  StrPrintf( &output, " (solder_mask_margin %s)", FMT_IU( aPad->GetLocalSolderMaskMargin() ).c_str() );
1323 
1324  if( aPad->GetLocalSolderPasteMargin() != 0 )
1325  StrPrintf( &output, " (solder_paste_margin %s)", FMT_IU( aPad->GetLocalSolderPasteMargin() ).c_str() );
1326 
1327  if( aPad->GetLocalSolderPasteMarginRatio() != 0 )
1328  StrPrintf( &output, " (solder_paste_margin_ratio %s)",
1329  Double2Str( aPad->GetLocalSolderPasteMarginRatio() ).c_str() );
1330 
1331  if( aPad->GetLocalClearance() != 0 )
1332  StrPrintf( &output, " (clearance %s)", FMT_IU( aPad->GetLocalClearance() ).c_str() );
1333 
1335  StrPrintf( &output, " (zone_connect %d)", aPad->GetZoneConnection() );
1336 
1337  if( aPad->GetThermalWidth() != 0 )
1338  StrPrintf( &output, " (thermal_width %s)", FMT_IU( aPad->GetThermalWidth() ).c_str() );
1339 
1340  if( aPad->GetThermalGap() != 0 )
1341  StrPrintf( &output, " (thermal_gap %s)", FMT_IU( aPad->GetThermalGap() ).c_str() );
1342 
1343  if( output.size() )
1344  {
1345  m_out->Print( 0, "\n" );
1346  m_out->Print( aNestLevel+1, "%s", output.c_str()+1 ); // +1 skips 1st space on 1st element
1347  }
1348 
1349  m_out->Print( 0, ")\n" );
1350 }
1351 
1352 
1353 void PCB_IO::format( TEXTE_PCB* aText, int aNestLevel ) const
1354 {
1355  m_out->Print( aNestLevel, "(gr_text %s (at %s",
1356  m_out->Quotew( aText->GetText() ).c_str(),
1357  FMT_IU( aText->GetTextPos() ).c_str() );
1358 
1359  if( aText->GetTextAngle() != 0.0 )
1360  m_out->Print( 0, " %s", FMT_ANGLE( aText->GetTextAngle() ).c_str() );
1361 
1362  m_out->Print( 0, ")" );
1363 
1364  formatLayer( aText );
1365 
1366  if( aText->GetTimeStamp() )
1367  m_out->Print( 0, " (tstamp %lX)", (unsigned long)aText->GetTimeStamp() );
1368 
1369  m_out->Print( 0, "\n" );
1370 
1371  aText->EDA_TEXT::Format( m_out, aNestLevel, m_ctl );
1372 
1373  m_out->Print( aNestLevel, ")\n" );
1374 }
1375 
1376 
1377 void PCB_IO::format( TEXTE_MODULE* aText, int aNestLevel ) const
1378 {
1379  wxString type;
1380 
1381  switch( aText->GetType() )
1382  {
1383  case TEXTE_MODULE::TEXT_is_REFERENCE: type = "reference"; break;
1384  case TEXTE_MODULE::TEXT_is_VALUE: type = "value"; break;
1385  case TEXTE_MODULE::TEXT_is_DIVERS: type = "user";
1386  }
1387 
1388  m_out->Print( aNestLevel, "(fp_text %s %s (at %s",
1389  m_out->Quotew( type ).c_str(),
1390  m_out->Quotew( aText->GetText() ).c_str(),
1391  FMT_IU( aText->GetPos0() ).c_str() );
1392 
1393  // Due to Pcbnew history, fp_text angle is saved as an absolute on screen angle,
1394  // but internally the angle is held relative to its parent footprint. parent
1395  // may be NULL when saving a footprint outside a BOARD.
1396  double orient = aText->GetTextAngle();
1397  MODULE* parent = (MODULE*) aText->GetParent();
1398 
1399  if( parent )
1400  {
1401  // GetTextAngle() is always in -360..+360 range because of
1402  // TEXTE_MODULE::SetTextAngle(), but summing that angle with an
1403  // additional board angle could kick sum up >= 360 or <= -360, so to have
1404  // consistent results, normalize again for the BOARD save. A footprint
1405  // save does not use this code path since parent is NULL.
1406 #if 0
1407  // This one could be considered reasonable if you like positive angles
1408  // in your board text.
1409  orient = NormalizeAnglePos( orient + parent->GetOrientation() );
1410 #else
1411  // Choose compatibility for now, even though this is only a 720 degree clamp
1412  // with two possible values for every angle.
1413  orient = NormalizeAngle360( orient + parent->GetOrientation() );
1414 #endif
1415  }
1416 
1417  if( orient != 0.0 )
1418  m_out->Print( 0, " %s", FMT_ANGLE( orient ).c_str() );
1419 
1420  m_out->Print( 0, ")" );
1421  formatLayer( aText );
1422 
1423  if( !aText->IsVisible() )
1424  m_out->Print( 0, " hide" );
1425 
1426  m_out->Print( 0, "\n" );
1427 
1428  aText->EDA_TEXT::Format( m_out, aNestLevel, m_ctl | CTL_OMIT_HIDE );
1429 
1430  m_out->Print( aNestLevel, ")\n" );
1431 }
1432 
1433 
1434 void PCB_IO::format( TRACK* aTrack, int aNestLevel ) const
1435 {
1436  if( aTrack->Type() == PCB_VIA_T )
1437  {
1438  PCB_LAYER_ID layer1, layer2;
1439 
1440  const VIA* via = static_cast<const VIA*>(aTrack);
1441  BOARD* board = (BOARD*) via->GetParent();
1442 
1443  wxCHECK_RET( board != 0, wxT( "Via " ) + via->GetSelectMenuText() +
1444  wxT( " has no parent." ) );
1445 
1446  m_out->Print( aNestLevel, "(via" );
1447 
1448  via->LayerPair( &layer1, &layer2 );
1449 
1450  switch( via->GetViaType() )
1451  {
1452  case VIA_THROUGH: // Default shape not saved.
1453  break;
1454 
1455  case VIA_BLIND_BURIED:
1456  m_out->Print( 0, " blind" );
1457  break;
1458 
1459  case VIA_MICROVIA:
1460  m_out->Print( 0, " micro" );
1461  break;
1462 
1463  default:
1464  THROW_IO_ERROR( wxString::Format( _( "unknown via type %d" ), via->GetViaType() ) );
1465  }
1466 
1467  m_out->Print( 0, " (at %s) (size %s)",
1468  FMT_IU( aTrack->GetStart() ).c_str(),
1469  FMT_IU( aTrack->GetWidth() ).c_str() );
1470 
1471  if( via->GetDrill() != UNDEFINED_DRILL_DIAMETER )
1472  m_out->Print( 0, " (drill %s)", FMT_IU( via->GetDrill() ).c_str() );
1473 
1474  m_out->Print( 0, " (layers %s %s)",
1475  m_out->Quotew( m_board->GetLayerName( layer1 ) ).c_str(),
1476  m_out->Quotew( m_board->GetLayerName( layer2 ) ).c_str() );
1477  }
1478  else
1479  {
1480  m_out->Print( aNestLevel, "(segment (start %s) (end %s) (width %s)",
1481  FMT_IU( aTrack->GetStart() ).c_str(), FMT_IU( aTrack->GetEnd() ).c_str(),
1482  FMT_IU( aTrack->GetWidth() ).c_str() );
1483 
1484  m_out->Print( 0, " (layer %s)", m_out->Quotew( aTrack->GetLayerName() ).c_str() );
1485  }
1486 
1487  m_out->Print( 0, " (net %d)", m_mapping->Translate( aTrack->GetNetCode() ) );
1488 
1489  if( aTrack->GetTimeStamp() != 0 )
1490  m_out->Print( 0, " (tstamp %lX)", (unsigned long)aTrack->GetTimeStamp() );
1491 
1492  if( aTrack->GetStatus() != 0 )
1493  m_out->Print( 0, " (status %X)", aTrack->GetStatus() );
1494 
1495  m_out->Print( 0, ")\n" );
1496 }
1497 
1498 
1499 void PCB_IO::format( ZONE_CONTAINER* aZone, int aNestLevel ) const
1500 {
1501  // Save the NET info; For keepout zones, net code and net name are irrelevant
1502  // so be sure a dummy value is stored, just for ZONE_CONTAINER compatibility
1503  // (perhaps netcode and netname should be not stored)
1504  m_out->Print( aNestLevel, "(zone (net %d) (net_name %s)",
1505  aZone->GetIsKeepout() ? 0 : m_mapping->Translate( aZone->GetNetCode() ),
1506  m_out->Quotew( aZone->GetIsKeepout() ? wxT("") : aZone->GetNetname() ).c_str() );
1507 
1508  formatLayer( aZone );
1509 
1510  m_out->Print( 0, " (tstamp %lX)", (unsigned long) aZone->GetTimeStamp() );
1511 
1512  // Save the outline aux info
1513  std::string hatch;
1514 
1515  switch( aZone->GetHatchStyle() )
1516  {
1517  default:
1518  case ZONE_CONTAINER::NO_HATCH: hatch = "none"; break;
1519  case ZONE_CONTAINER::DIAGONAL_EDGE: hatch = "edge"; break;
1520  case ZONE_CONTAINER::DIAGONAL_FULL: hatch = "full"; break;
1521  }
1522 
1523  m_out->Print( 0, " (hatch %s %s)\n", hatch.c_str(),
1524  FMT_IU( aZone->GetHatchPitch() ).c_str() );
1525 
1526  if( aZone->GetPriority() > 0 )
1527  m_out->Print( aNestLevel+1, "(priority %d)\n", aZone->GetPriority() );
1528 
1529  m_out->Print( aNestLevel+1, "(connect_pads" );
1530 
1531  switch( aZone->GetPadConnection() )
1532  {
1533  default:
1534  case PAD_ZONE_CONN_THERMAL: // Default option not saved or loaded.
1535  break;
1536 
1538  m_out->Print( 0, " thru_hole_only" );
1539  break;
1540 
1541  case PAD_ZONE_CONN_FULL:
1542  m_out->Print( 0, " yes" );
1543  break;
1544 
1545  case PAD_ZONE_CONN_NONE:
1546  m_out->Print( 0, " no" );
1547  break;
1548  }
1549 
1550  m_out->Print( 0, " (clearance %s))\n",
1551  FMT_IU( aZone->GetZoneClearance() ).c_str() );
1552 
1553  m_out->Print( aNestLevel+1, "(min_thickness %s)\n",
1554  FMT_IU( aZone->GetMinThickness() ).c_str() );
1555 
1556  if( aZone->GetIsKeepout() )
1557  {
1558  m_out->Print( aNestLevel+1, "(keepout (tracks %s) (vias %s) (copperpour %s))\n",
1559  aZone->GetDoNotAllowTracks() ? "not_allowed" : "allowed",
1560  aZone->GetDoNotAllowVias() ? "not_allowed" : "allowed",
1561  aZone->GetDoNotAllowCopperPour() ? "not_allowed" : "allowed" );
1562  }
1563 
1564  m_out->Print( aNestLevel+1, "(fill" );
1565 
1566  // Default is not filled.
1567  if( aZone->IsFilled() )
1568  m_out->Print( 0, " yes" );
1569 
1570  // Default is polygon filled.
1571  if( aZone->GetFillMode() )
1572  m_out->Print( 0, " (mode segment)" );
1573 
1574  m_out->Print( 0, " (arc_segments %d) (thermal_gap %s) (thermal_bridge_width %s)",
1575  aZone->GetArcSegmentCount(),
1576  FMT_IU( aZone->GetThermalReliefGap() ).c_str(),
1577  FMT_IU( aZone->GetThermalReliefCopperBridge() ).c_str() );
1578 
1580  {
1581  m_out->Print( 0, " (smoothing" );
1582 
1583  switch( aZone->GetCornerSmoothingType() )
1584  {
1586  m_out->Print( 0, " chamfer" );
1587  break;
1588 
1590  m_out->Print( 0, " fillet" );
1591  break;
1592 
1593  default:
1594  THROW_IO_ERROR( wxString::Format( _( "unknown zone corner smoothing type %d" ),
1595  aZone->GetCornerSmoothingType() ) );
1596  }
1597  m_out->Print( 0, ")" );
1598 
1599  if( aZone->GetCornerRadius() != 0 )
1600  m_out->Print( 0, " (radius %s)",
1601  FMT_IU( aZone->GetCornerRadius() ).c_str() );
1602  }
1603 
1604  m_out->Print( 0, ")\n" );
1605 
1606  int newLine = 0;
1607 
1608  if( aZone->GetNumCorners() )
1609  {
1610  bool new_polygon = true;
1611  bool is_closed = false;
1612 
1613  for( auto iterator = aZone->IterateWithHoles(); iterator; iterator++ )
1614  {
1615  if( new_polygon )
1616  {
1617  newLine = 0;
1618  m_out->Print( aNestLevel+1, "(polygon\n" );
1619  m_out->Print( aNestLevel+2, "(pts\n" );
1620  new_polygon = false;
1621  is_closed = false;
1622  }
1623 
1624  if( newLine == 0 )
1625  m_out->Print( aNestLevel+3, "(xy %s %s)",
1626  FMT_IU( iterator->x ).c_str(), FMT_IU( iterator->y ).c_str() );
1627  else
1628  m_out->Print( 0, " (xy %s %s)",
1629  FMT_IU( iterator->x ).c_str(), FMT_IU( iterator->y ).c_str() );
1630 
1631  if( newLine < 4 )
1632  {
1633  newLine += 1;
1634  }
1635  else
1636  {
1637  newLine = 0;
1638  m_out->Print( 0, "\n" );
1639  }
1640 
1641  if( iterator.IsEndContour() )
1642  {
1643  is_closed = true;
1644 
1645  if( newLine != 0 )
1646  m_out->Print( 0, "\n" );
1647 
1648  m_out->Print( aNestLevel+2, ")\n" );
1649  m_out->Print( aNestLevel+1, ")\n" );
1650  new_polygon = true;
1651  }
1652  }
1653 
1654  if( !is_closed ) // Should not happen, but...
1655  m_out->Print( aNestLevel+1, ")\n" );
1656 
1657  }
1658 
1659  // Save the PolysList (filled areas)
1660  const SHAPE_POLY_SET& fv = aZone->GetFilledPolysList();
1661  newLine = 0;
1662 
1663  if( !fv.IsEmpty() )
1664  {
1665  bool new_polygon = true;
1666  bool is_closed = false;
1667 
1668  for( auto it = fv.CIterate(); it; ++it )
1669  {
1670  if( new_polygon )
1671  {
1672  newLine = 0;
1673  m_out->Print( aNestLevel+1, "(filled_polygon\n" );
1674  m_out->Print( aNestLevel+2, "(pts\n" );
1675  new_polygon = false;
1676  is_closed = false;
1677  }
1678 
1679  if( newLine == 0 )
1680  m_out->Print( aNestLevel+3, "(xy %s %s)",
1681  FMT_IU( it->x ).c_str(), FMT_IU( it->y ).c_str() );
1682  else
1683  m_out->Print( 0, " (xy %s %s)",
1684  FMT_IU( it->x ) .c_str(), FMT_IU( it->y ).c_str() );
1685 
1686  if( newLine < 4 )
1687  {
1688  newLine += 1;
1689  }
1690  else
1691  {
1692  newLine = 0;
1693  m_out->Print( 0, "\n" );
1694  }
1695 
1696  if( it.IsEndContour() )
1697  {
1698  is_closed = true;
1699 
1700  if( newLine != 0 )
1701  m_out->Print( 0, "\n" );
1702 
1703  m_out->Print( aNestLevel+2, ")\n" );
1704  m_out->Print( aNestLevel+1, ")\n" );
1705  new_polygon = true;
1706  }
1707  }
1708 
1709  if( !is_closed ) // Should not happen, but...
1710  m_out->Print( aNestLevel+1, ")\n" );
1711  }
1712 
1713  // Save the filling segments list
1714  const std::vector< SEGMENT >& segs = aZone->FillSegments();
1715 
1716  if( segs.size() )
1717  {
1718  m_out->Print( aNestLevel+1, "(fill_segments\n" );
1719 
1720  for( std::vector< SEGMENT >::const_iterator it = segs.begin(); it != segs.end(); ++it )
1721  {
1722  m_out->Print( aNestLevel+2, "(pts (xy %s) (xy %s))\n",
1723  FMT_IU( it->m_Start ).c_str(),
1724  FMT_IU( it->m_End ).c_str() );
1725  }
1726 
1727  m_out->Print( aNestLevel+1, ")\n" );
1728  }
1729 
1730  m_out->Print( aNestLevel, ")\n" );
1731 }
1732 
1733 
1734 PCB_IO::PCB_IO( int aControlFlags ) :
1735  m_cache( 0 ),
1736  m_ctl( aControlFlags ),
1737  m_parser( new PCB_PARSER() ),
1738  m_mapping( new NETINFO_MAPPING() )
1739 {
1740  init( 0 );
1741  m_out = &m_sf;
1742 }
1743 
1744 
1746 {
1747  delete m_cache;
1748  delete m_parser;
1749  delete m_mapping;
1750 }
1751 
1752 
1753 BOARD* PCB_IO::Load( const wxString& aFileName, BOARD* aAppendToMe, const PROPERTIES* aProperties )
1754 {
1755  FILE_LINE_READER reader( aFileName );
1756 
1757  init( aProperties );
1758 
1759  m_parser->SetLineReader( &reader );
1760  m_parser->SetBoard( aAppendToMe );
1761 
1762  BOARD* board;
1763 
1764  try
1765  {
1766  board = dynamic_cast<BOARD*>( m_parser->Parse() );
1767  }
1768  catch( const FUTURE_FORMAT_ERROR& )
1769  {
1770  // Don't wrap a FUTURE_FORMAT_ERROR in another
1771  throw;
1772  }
1773  catch( const PARSE_ERROR& parse_error )
1774  {
1775  if( m_parser->IsTooRecent() )
1776  throw FUTURE_FORMAT_ERROR( parse_error, m_parser->GetRequiredVersion() );
1777  else
1778  throw;
1779  }
1780 
1781  if( !board )
1782  {
1783  // The parser loaded something that was valid, but wasn't a board.
1784  THROW_PARSE_ERROR( _( "this file does not contain a PCB" ),
1787  }
1788 
1789  // Give the filename to the board if it's new
1790  if( !aAppendToMe )
1791  board->SetFileName( aFileName );
1792 
1793  return board;
1794 }
1795 
1796 
1797 void PCB_IO::init( const PROPERTIES* aProperties )
1798 {
1799  m_board = NULL;
1800  m_reader = NULL;
1802  m_props = aProperties;
1803 }
1804 
1805 
1806 void PCB_IO::cacheLib( const wxString& aLibraryPath, const wxString& aFootprintName )
1807 {
1808  if( !m_cache || m_cache->IsModified( aLibraryPath, aFootprintName ) )
1809  {
1810  // a spectacular episode in memory management:
1811  delete m_cache;
1812  m_cache = new FP_CACHE( this, aLibraryPath );
1813  m_cache->Load();
1814  }
1815 }
1816 
1817 
1818 void PCB_IO::FootprintEnumerate( wxArrayString& aFootprintNames,
1819  const wxString& aLibraryPath,
1820  const PROPERTIES* aProperties )
1821 {
1822  LOCALE_IO toggle; // toggles on, then off, the C locale.
1823  wxDir dir( aLibraryPath );
1824 
1825  if( !dir.IsOpened() )
1826  {
1827  THROW_IO_ERROR( wxString::Format( _( "footprint library path '%s' does not exist" ),
1828  GetChars( aLibraryPath ) ) );
1829  }
1830 
1831  init( aProperties );
1832 
1833  wxString errorMsg;
1834 
1835  // Some of the files may have been parsed correctly so we want to add the valid files to
1836  // the library.
1837  try
1838  {
1839  cacheLib( aLibraryPath );
1840  }
1841  catch( const IO_ERROR& ioe )
1842  {
1843  errorMsg = ioe.What();
1844  }
1845 
1846  const MODULE_MAP& mods = m_cache->GetModules();
1847 
1848  for( MODULE_CITER it = mods.begin(); it != mods.end(); ++it )
1849  {
1850  aFootprintNames.Add( it->first );
1851  }
1852 
1853  if( !errorMsg.IsEmpty() )
1854  THROW_IO_ERROR( errorMsg );
1855 }
1856 
1857 
1858 MODULE* PCB_IO::FootprintLoad( const wxString& aLibraryPath, const wxString& aFootprintName,
1859  const PROPERTIES* aProperties )
1860 {
1861  LOCALE_IO toggle; // toggles on, then off, the C locale.
1862 
1863  init( aProperties );
1864 
1865  cacheLib( aLibraryPath, aFootprintName );
1866 
1867  const MODULE_MAP& mods = m_cache->GetModules();
1868 
1869  MODULE_CITER it = mods.find( aFootprintName );
1870 
1871  if( it == mods.end() )
1872  {
1873  return NULL;
1874  }
1875 
1876  // copy constructor to clone the already loaded MODULE
1877  return new MODULE( *it->second->GetModule() );
1878 }
1879 
1880 
1881 void PCB_IO::FootprintSave( const wxString& aLibraryPath, const MODULE* aFootprint,
1882  const PROPERTIES* aProperties )
1883 {
1884  LOCALE_IO toggle; // toggles on, then off, the C locale.
1885 
1886  init( aProperties );
1887 
1888  // In this public PLUGIN API function, we can safely assume it was
1889  // called for saving into a library path.
1891 
1892  cacheLib( aLibraryPath );
1893 
1894  if( !m_cache->IsWritable() )
1895  {
1896  wxString msg = wxString::Format(
1897  _( "Library '%s' is read only" ),
1898  GetChars( aLibraryPath )
1899  );
1900 
1901  THROW_IO_ERROR( msg );
1902  }
1903 
1904  wxString footprintName = aFootprint->GetFPID().GetLibItemName();
1905 
1906  MODULE_MAP& mods = m_cache->GetModules();
1907 
1908  // Quietly overwrite module and delete module file from path for any by same name.
1909  wxFileName fn( aLibraryPath, aFootprint->GetFPID().GetLibItemName(),
1911 
1912  if( !fn.IsOk() )
1913  {
1914  THROW_IO_ERROR( wxString::Format( _( "Footprint file name '%s' is not valid." ),
1915  GetChars( fn.GetFullPath() ) ) );
1916  }
1917 
1918  if( fn.FileExists() && !fn.IsFileWritable() )
1919  {
1920  THROW_IO_ERROR( wxString::Format( _( "user does not have write permission to delete file '%s' " ),
1921  GetChars( fn.GetFullPath() ) ) );
1922  }
1923 
1924  MODULE_CITER it = mods.find( footprintName );
1925 
1926  if( it != mods.end() )
1927  {
1928  wxLogTrace( traceFootprintLibrary, wxT( "Removing footprint library file '%s'." ),
1929  fn.GetFullPath().GetData() );
1930  mods.erase( footprintName );
1931  wxRemoveFile( fn.GetFullPath() );
1932  }
1933 
1934  // I need my own copy for the cache
1935  MODULE* module = new MODULE( *aFootprint );
1936 
1937  // and it's time stamp must be 0, it should have no parent, orientation should
1938  // be zero, and it should be on the front layer.
1939  module->SetTimeStamp( 0 );
1940  module->SetParent( 0 );
1941  module->SetOrientation( 0 );
1942 
1943  if( module->GetLayer() != F_Cu )
1944  module->Flip( module->GetPosition() );
1945 
1946  wxLogTrace( traceFootprintLibrary, wxT( "Creating s-expression footprint file: %s." ),
1947  fn.GetFullPath().GetData() );
1948  mods.insert( footprintName, new FP_CACHE_ITEM( module, fn ) );
1949  m_cache->Save();
1950 }
1951 
1952 
1953 void PCB_IO::FootprintDelete( const wxString& aLibraryPath, const wxString& aFootprintName, const PROPERTIES* aProperties )
1954 {
1955  LOCALE_IO toggle; // toggles on, then off, the C locale.
1956 
1957  init( aProperties );
1958 
1959  cacheLib( aLibraryPath );
1960 
1961  if( !m_cache->IsWritable() )
1962  {
1963  THROW_IO_ERROR( wxString::Format( _( "Library '%s' is read only" ),
1964  aLibraryPath.GetData() ) );
1965  }
1966 
1967  m_cache->Remove( aFootprintName );
1968 }
1969 
1970 
1971 void PCB_IO::FootprintLibCreate( const wxString& aLibraryPath, const PROPERTIES* aProperties )
1972 {
1973  if( wxDir::Exists( aLibraryPath ) )
1974  {
1975  THROW_IO_ERROR( wxString::Format( _( "cannot overwrite library path '%s'" ),
1976  aLibraryPath.GetData() ) );
1977  }
1978 
1979  LOCALE_IO toggle;
1980 
1981  init( aProperties );
1982 
1983  delete m_cache;
1984  m_cache = new FP_CACHE( this, aLibraryPath );
1985  m_cache->Save();
1986 }
1987 
1988 
1989 bool PCB_IO::FootprintLibDelete( const wxString& aLibraryPath, const PROPERTIES* aProperties )
1990 {
1991  wxFileName fn;
1992  fn.SetPath( aLibraryPath );
1993 
1994  // Return if there is no library path to delete.
1995  if( !fn.DirExists() )
1996  return false;
1997 
1998  if( !fn.IsDirWritable() )
1999  {
2000  THROW_IO_ERROR( wxString::Format( _( "user does not have permission to delete directory '%s'" ),
2001  aLibraryPath.GetData() ) );
2002  }
2003 
2004  wxDir dir( aLibraryPath );
2005 
2006  if( dir.HasSubDirs() )
2007  {
2008  THROW_IO_ERROR( wxString::Format( _( "library directory '%s' has unexpected sub-directories" ),
2009  aLibraryPath.GetData() ) );
2010  }
2011 
2012  // All the footprint files must be deleted before the directory can be deleted.
2013  if( dir.HasFiles() )
2014  {
2015  unsigned i;
2016  wxFileName tmp;
2017  wxArrayString files;
2018 
2019  wxDir::GetAllFiles( aLibraryPath, &files );
2020 
2021  for( i = 0; i < files.GetCount(); i++ )
2022  {
2023  tmp = files[i];
2024 
2025  if( tmp.GetExt() != KiCadFootprintFileExtension )
2026  {
2027  THROW_IO_ERROR( wxString::Format( _( "unexpected file '%s' was found in library path '%s'" ),
2028  files[i].GetData(), aLibraryPath.GetData() ) );
2029  }
2030  }
2031 
2032  for( i = 0; i < files.GetCount(); i++ )
2033  {
2034  wxRemoveFile( files[i] );
2035  }
2036  }
2037 
2038  wxLogTrace( traceFootprintLibrary, wxT( "Removing footprint library '%s'" ),
2039  aLibraryPath.GetData() );
2040 
2041  // Some of the more elaborate wxRemoveFile() crap puts up its own wxLog dialog
2042  // we don't want that. we want bare metal portability with no UI here.
2043  if( !wxRmdir( aLibraryPath ) )
2044  {
2045  THROW_IO_ERROR( wxString::Format( _( "footprint library '%s' cannot be deleted" ),
2046  aLibraryPath.GetData() ) );
2047  }
2048 
2049  // For some reason removing a directory in Windows is not immediately updated. This delay
2050  // prevents an error when attempting to immediately recreate the same directory when over
2051  // writing an existing library.
2052 #ifdef __WINDOWS__
2053  wxMilliSleep( 250L );
2054 #endif
2055 
2056  if( m_cache && !m_cache->IsPath( aLibraryPath ) )
2057  {
2058  delete m_cache;
2059  m_cache = NULL;
2060  }
2061 
2062  return true;
2063 }
2064 
2065 
2066 bool PCB_IO::IsFootprintLibWritable( const wxString& aLibraryPath )
2067 {
2068  LOCALE_IO toggle;
2069 
2070  init( NULL );
2071 
2072  cacheLib( aLibraryPath );
2073 
2074  return m_cache->IsWritable();
2075 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:639
friend class FP_CACHE
KICAD_T Type() const
Function Type()
Definition: base_struct.h:198
wxString GetPath() const
#define DIM(x)
of elements in an array
Definition: macros.h:98
int m_SolderMaskMargin
Solder mask margin.
BOARD_ITEM_CONTAINER * GetParent() const
const wxString KiCadFootprintFileExtension
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:78
iterator begin() const
Function begin() Returns iterator to the first entry in the mapping.
OUTPUTFORMATTER * m_out
output any Format()s to this, no ownership
LINE_READER * m_reader
no ownership here.
TEXTE_MODULE & Reference()
Definition: class_module.h:463
std::unique_ptr< MODULE > m_module
const ZONE_SETTINGS & GetZoneSettings() const
Definition: class_board.h:556
int GetVisibleElements() const
Function GetVisibleElements returns a bit-mask of all the element categories that are visible...
Definition: typeinfo.h:97
#define CTL_OMIT_AT
Omit position and rotation.
int GetThermalGap() const
Definition: class_module.h:195
BOARD_ITEM * Parse(const wxString &aClipboardSourceInput)
const wxPoint & GetBezControl2() const
PCB_TARGET class definition.
Class PCB_IO is a PLUGIN derivation for saving and loading Pcbnew s-expression formatted files...
BOARD * Load(const wxString &aFileName, BOARD *aAppendToMe, const PROPERTIES *aProperties=NULL) override
Function Load loads information from some input file format that this PLUGIN implementation knows abo...
NETCLASSPTR GetDefault() const
Function GetDefault.
int GetNumCorners(void) const
Access to m_Poly parameters.
Definition: class_zone.h:465
time_t GetLastEditTime() const
Definition: class_module.h:284
PAD_ATTR_T GetAttribute() const
Definition: class_pad.h:238
TEXTE_PCB class definition.
const wxPoint & GetTextPos() const
Definition: eda_text.h:224
const wxPoint & GetGridOrigin() const
Definition: class_board.h:350
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:63
int m_SolderPasteMargin
Solder paste margin absolute value.
Class LOCALE_IO is a class that can be instantiated within a scope in which you are expecting excepti...
Definition: common.h:166
wxFileName m_lib_path
Plugin object that owns the cache.
Implementation of conversion functions that require both schematic and board internal units...
int GetMinThickness() const
Definition: class_zone.h:209
wxPoint m_crossBarF
int GetWidth() const
Definition: class_mire.h:72
int m_ModuleTextWidth
Default footprint texts thickness.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class...
bool GetDoNotAllowCopperPour() const
Definition: class_zone.h:655
int GetLocalClearance() const
Definition: class_module.h:179
std::vector< int > m_TrackWidthList
Track width list.
int m_ModuleSegmentWidth
Default width for all graphic lines.
wxPoint m_arrowD1F
TEXT_TYPE GetType() const
FP_CACHE * m_cache
Footprint library cache.
int GetArcSegmentCount() const
Definition: class_zone.h:198
const wxPoint & GetPos0() const
Class PCB_PARSER reads a Pcbnew s-expression formatted LINE_READER object and returns the appropriate...
Definition: pcb_parser.h:66
int m_PcbTextWidth
current Pcb (not module) Text width
const PROPERTIES * m_props
passed via Save() or Load(), no ownership, may be NULL.
void Flip(const wxPoint &aCentre) override
Function Flip Flip this object, i.e.
int GetWidth() const
LSEQ CuStack() const
Function CuStack returns a sequence of copper layers in starting from the front/top and extending to ...
Definition: lset.cpp:147
int GetPadToDieLength() const
Definition: class_pad.h:241
Class BOARD to handle a board.
void init(const PROPERTIES *aProperties)
const wxPoint & GetPosition() const override
Definition: class_module.h:155
bool IsFilled() const
Definition: class_zone.h:200
polygon (not yet used for tracks, but could be in microwave apps)
int GetLocalSolderMaskMargin() const
Definition: class_pad.h:243
MODULE * Next() const
Definition: class_module.h:100
const wxPoint & GetEnd0() const
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:59
CONST_ITERATOR CIterate(int aFirst, int aLast, bool aIterateHoles=false) const
class ZONE_CONTAINER, a zone area
Definition: typeinfo.h:114
void formatLayer(const BOARD_ITEM *aItem) const
Set for modules listed in the automatic insertion list (usually SMD footprints)
Definition: class_module.h:77
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
class TEXTE_PCB, text on a layer
Definition: typeinfo.h:104
void FootprintEnumerate(wxArrayString &aFootprintNames, const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL) override
Return a list of footprint names contained within the library at aLibraryPath.
wxString GetName() const
Classes to handle copper zones.
const wxPoint & GetPos0() const
Definition: class_pad.h:176
int GetCornerSmoothingType() const
Definition: class_zone.h:612
PAD_DRILL_SHAPE_T GetDrillShape() const
Definition: class_pad.h:221
bool IsFootprintLibWritable(const wxString &aLibraryPath) override
Function IsFootprintLibWritable returns true iff the library at aLibraryPath is writable.
usual segment : line with rounded ends
class D_PAD, a pad in a footprint
Definition: typeinfo.h:102
iterator end()
std::string Double2Str(double aValue)
Helper function Double2Str to print a float number without using scientific notation and no trailing ...
Definition: base_units.cpp:60
const std::vector< wxPoint > & GetPolyPoints() const
bool IsModified(const wxString &aLibPath, const wxString &aFootprintName=wxEmptyString) const
Function IsModified check if the footprint cache has been modified relative to aLibPath and aFootprin...
wxPoint m_featureLineDF
ZoneConnection GetZoneConnection() const
Definition: class_module.h:189
wxFileName GetFileName() const
std::list< S3D_INFO > & Models()
Definition: class_module.h:150
const wxSize & GetDrillSize() const
Definition: class_pad.h:188
int GetPlacementCost90() const
Definition: class_module.h:533
Class LIB_ID.
Definition: lib_id.h:56
STATUS_FLAGS GetStatus() const
Definition: base_struct.h:250
wxSize m_ModuleTextSize
Default footprint texts size.
Class PROPERTIES is a name/value tuple with unique names and optional values.
Definition: properties.h:34
#define cu(a)
Definition: auxiliary.h:88
int GetThermalReliefCopperBridge(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:472
PAD_SHAPE_T GetShape() const
Function GetShape.
Definition: class_pad.h:166
int GetDrill() const
Function GetDrill returns the local drill setting for this VIA.
Definition: class_track.h:454
LSET GetEnabledLayers() const
Function GetEnabledLayers is a proxy function that calls the corresponding function in m_BoardSetting...
unsigned int GetCornerRadius() const
Definition: class_zone.h:616
wxString GetLayerName() const
Function GetLayerName returns the name of the PCB layer on which the item resides.
class EDGE_MODULE, a footprint edge
Definition: typeinfo.h:106
double GetLocalSolderPasteMarginRatio() const
Definition: class_module.h:185
NETCLASS_MAP::const_iterator const_iterator
FP_CACHE_ITEM(MODULE *aModule, const wxFileName &aFileName)
const wxPoint & GetEnd() const
Definition: class_track.h:118
iterator begin()
void SetTimeStamp(time_t aNewTimeStamp)
Definition: base_struct.h:203
double GetTextAngle() const
Definition: eda_text.h:164
Functions relatives to tracks, vias and segments used to fill zones.
iterator end() const
Function end() Returns iterator to the last entry in the mapping.
class TRACK, a track segment (segment on a copper layer)
Definition: typeinfo.h:107
void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControlBits) const
Function Format outputs the net class to aFormatter in s-expression form.
This file contains miscellaneous commonly used macros and functions.
static const char * ShowType(LAYER_T aType)
Function ShowType converts a LAYER_T enum to a const char*.
const wxString & CurSource()
Function CurFilename returns the current LINE_READER source.
Definition: dsnlexer.h:528
void UpdateModificationTime()
void SetOutputFormatter(OUTPUTFORMATTER *aFormatter)
void SetBoard(const BOARD *aBoard)
Function SetBoard Sets a BOARD object that is used to prepare the net code map.
Pads are not covered.
Definition: zones.h:57
wxPoint m_featureLineGO
bool GetIsKeepout() const
Accessors to parameters used in Keepout zones:
Definition: class_zone.h:654
LSEQ Seq(const PCB_LAYER_ID *aWishListSequence, unsigned aCount) const
Function Seq returns an LSEQ from the union of this LSET and a desired sequence.
Definition: lset.cpp:337
int StrPrintf(std::string *result, const char *format,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:75
BOARD_ITEM * Next() const
MODULE * GetModule() const
const LIB_ID & GetFPID() const
Definition: class_module.h:164
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes...
Definition: macros.h:47
std::vector< SEGMENT > & FillSegments()
Definition: class_zone.h:244
DIMENSION class definition.
MODULE_MAP m_modules
Footprint library path modified time stamp.
class MODULE, a footprint
Definition: typeinfo.h:101
void Remove(const wxString &aFootprintName)
MODULE_MAP::const_iterator MODULE_CITER
PCB_IO(int aControlFlags=CTL_FOR_BOARD)
boost::ptr_map< wxString, FP_CACHE_ITEM > MODULE_MAP
STRINGSET::iterator iterator
PCB_LAYER_ID
A quick note on layer IDs:
Class FILE_LINE_READER is a LINE_READER that reads from an open file.
Definition: richio.h:180
STROKE_T GetShape() const
wxString GetRequiredVersion()
Return a string representing the version of kicad required to open this file.
Definition: pcb_parser.cpp:182
int GetShape() const
Definition: class_mire.h:66
void FootprintLibCreate(const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL) override
Function FootprintLibCreate creates a new empty footprint library at aLibraryPath empty...
Class LSET is a set of PCB_LAYER_IDs.
iterator begin()
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:133
ZoneConnection GetPadConnection(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:820
void SetBoard(BOARD *aBoard)
Definition: pcb_parser.h:303
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
int GetSize() const
Function GetSize.
VIATYPE_T GetViaType() const
Definition: class_track.h:439
void FootprintSave(const wxString &aLibraryPath, const MODULE *aFootprint, const PROPERTIES *aProperties=NULL) override
Function FootprintSave will write aModule to an existing library located at aLibraryPath.
iterator end()
wxString GetBuildVersion()
Function GetBuildVersion Return the build version string.
bool IsPath(const wxString &aPath) const
Function IsPath checks if aPath is the same as the current cache path.
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:213
wxFileName m_file_name
The the full file name and path of the footprint to cache.
int Translate(int aNetCode) const
Function Translate Translates net number according to the map prepared by Update() function...
double GetOrientation() const
Definition: class_module.h:160
Class SHAPE_POLY_SET.
TEXTE_MODULE & Value()
read/write accessors:
Definition: class_module.h:462
wxSize m_PcbTextSize
current Pcb (not module) Text size
MODULE * FootprintLoad(const wxString &aLibraryPath, const wxString &aFootprintName, const PROPERTIES *aProperties=NULL) override
Function FootprintLoad loads a footprint having aFootprintName from the aLibraryPath containing a lib...
C++ does not put enum values in separate namespaces unless the enum itself is in a separate namespace...
Definition: pcb_lexer.h:23
const UTF8 & GetLibItemName() const
Function GetLibItemName.
Definition: lib_id.h:129
const wxPoint & GetStart() const
Definition: class_track.h:121
int m_TrackMinWidth
track min value for width ((min copper size value
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:130
Arcs (with rounded ends)
wxDateTime m_mod_time
The path of the library.
static const wxString traceFootprintLibrary(wxT("KicadFootprintLib"))
Definition for enabling and disabling footprint library trace output.
int m_ViasMinSize
vias (not micro vias) min diameter
int m_loading_format_version
which SEXPR_BOARD_FILE_VERSION should be Load()ed?
Class NETCLASS handles a collection of nets and the parameters used to route or test these nets...
ZoneConnection GetZoneConnection() const
Definition: class_pad.cpp:610
LSET GetLayerSet() const override
Function GetLayerSet returns a "layer mask", which is a bitmap of all layers on which the TRACK segme...
Definition: class_pad.h:235
wxPoint m_arrowG1F
int GetThermalReliefGap(D_PAD *aPad=NULL) const
Definition: class_zone.cpp:463
const wxString GetLayerName(PCB_LAYER_ID aLayer) const
Function GetLayerName returns the name of a layer given by aLayer.
int m_DrawSegmentWidth
current graphic line width (not EDGE layer)
wxPoint m_arrowD2F
wxPoint m_arrowG2F
int GetThermalWidth() const
Definition: class_pad.cpp:621
bool IsModified() const
Tell if the disk content or the lib_path has changed.
int m_ViasMinDrill
vias (not micro vias) min drill diameter
D_PAD * Next() const
Definition: class_pad.h:106
int CurOffset()
Function CurOffset returns the byte offset within the current line, using a 1 based index...
Definition: dsnlexer.h:538
int GetThermalGap() const
Definition: class_pad.cpp:632
The common library.
const PCB_PLOT_PARAMS & GetPlotOptions() const
Definition: class_board.h:550
const wxSize & GetSize() const
Definition: class_pad.h:182
#define FMT_IU
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:532
int m_ZoneClearance
Clearance value.
int GetAttributes() const
Definition: class_module.h:197
virtual void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControlBits) const
Function Format outputs the object to aFormatter in s-expression form.
Definition: worksheet.cpp:245
PCB_IO * m_owner
const wxString & GetKeywords() const
Definition: class_module.h:170
const wxPoint & GetBezControl1() const
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
int GetLocalSolderPasteMargin() const
Definition: class_pad.h:249
std::string Quotew(const wxString &aWrapee)
Definition: richio.cpp:486
int GetAreaCount() const
Function GetAreaCount.
Definition: class_board.h:1011
void SetFileName(const wxString &aFileName)
Definition: class_board.h:232
Bezier Curve.
#define UNDEFINED_DRILL_DIAMETER
Definition: class_track.h:58
PCB_PARSER * m_parser
int GetNet() const
Function GetNet.
int GetLocalSolderMaskMargin() const
Definition: class_module.h:176
#define CTL_OMIT_NETS
Omit pads net names (useless in library)
Wrapper class, so you can iterate through NETINFO_ITEM*s, not std::pair
BOARD_ITEM * Parse()
Definition: pcb_parser.cpp:405
#define CTL_OMIT_PATH
Omit component sheet time stamp (useless in library)
Class FP_CACHE_ITEM is helper class for creating a footprint library cache.
int m_MicroViasMinSize
micro vias (not vias) min diameter
void Format(BOARD_ITEM *aItem, int aNestLevel=0) const
Function Format outputs aItem to aFormatter in s-expression format.
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:60
class DIMENSION, a dimension (graphic item)
Definition: typeinfo.h:112
bool IsLocked() const override
Function IsLocked.
Definition: class_module.h:236
NETINFO_MAPPING * m_mapping
mapping for net codes, so only not empty net codes are stored with consecutive integers as net codes ...
bool IsWritable() const
const SHAPE_POLY_SET & GetFilledPolysList() const
Function GetFilledPolysList returns a reference to the list of filled polygons.
Definition: class_zone.h:582
int GetNumSegmTrack() const
Functions to get some items count.
Thermal relief only for THT pads.
Definition: zones.h:60
Class LSEQ is a sequence (and therefore also a set) of PCB_LAYER_IDs.
const PAGE_INFO & GetPageSettings() const
Definition: class_board.h:547
int GetLocalClearance() const
Definition: class_pad.h:246
LINE_READER * SetLineReader(LINE_READER *aReader)
Function SetLineReader sets aLineReader into the parser, and returns the previous one...
Definition: pcb_parser.h:296
class PCB_TARGET, a target (graphic item)
Definition: typeinfo.h:113
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
int GetLocalSolderPasteMargin() const
Definition: class_module.h:182
time_t GetTimeStamp() const
Definition: base_struct.h:204
double GetLocalSolderPasteMarginRatio() const
Definition: class_pad.h:252
void FootprintDelete(const wxString &aLibraryPath, const wxString &aFootprintName, const PROPERTIES *aProperties=NULL) override
Function FootprintDelete deletes aFootprintName from the library at aLibraryPath. ...
default
Definition: class_module.h:76
int GetNetCode() const
Function GetNetCode.
const char * CurLine()
Function CurLine returns the current line of text, from which the CurText() would return its token...
Definition: dsnlexer.h:517
class TEXTE_MODULE, text in a footprint
Definition: typeinfo.h:105
const wxPoint & GetAuxOrigin() const
Definition: class_board.h:343
wxDateTime m_mod_time
The last file modified time stamp.
virtual std::string Quotes(const std::string &aWrapee)
Function Quotes checks aWrapee input string for a need to be quoted (e.g.
Definition: richio.cpp:437
wxString GetSelectMenuText() const override
Function GetSelectMenuText returns the text to display to be used in the selection clarification cont...
void Load()
Class NETINFO_ITEM handles the data for a net.
Definition: class_netinfo.h:69
PCB_LAYER_ID GetLayer() const
Function GetLayer returns the primary layer this item is on.
bool IsTooRecent()
Return whether a version number, if any was parsed, was too recent.
Definition: pcb_parser.h:314
void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControlBits) const
Function GetStandardSizes returns the standard page types, such as "A4", "A3", etc.
virtual const wxString What() const
A composite of Problem() and Where()
Definition: exceptions.cpp:33
void Remove(iterator aName)
Function Remove will remove NET name aName from the collection of members.
Struct PARSE_ERROR contains a filename or source description, a problem input line, a line number, a byte offset, and an error message which contains the the caller's report and his call site information: CPP source file, function, and line number.
Definition: ki_exception.h:94
bool GetDoNotAllowTracks() const
Definition: class_zone.h:657
STRING_FORMATTER m_sf
#define CTL_FOR_LIBRARY
Format output for a footprint library instead of clipboard or BOARD.
const wxPoint & GetPosition() const override
Definition: class_mire.h:63
TRACK * Next() const
Definition: class_track.h:98
void Save()
save the entire legacy library to m_lib_name;
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
double GetAngle() const
virtual wxString GetClass() const =0
Function GetClass returns the class name.
TITLE_BLOCK & GetTitleBlock()
Definition: class_board.h:553
const wxString & GetNetname() const
Function GetNetname.
ZONE_CONTAINER * GetArea(int index) const
Function GetArea returns the Area (Zone Container) at a given index.
Definition: class_board.h:982
int GetFillMode() const
Definition: class_zone.h:186
double GetRoundRectRadiusRatio() const
has meaning only for rounded rect pads
Definition: class_pad.h:450
Class to handle a graphic segment.
const wxPoint & GetStart0() const
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
const wxString & GetDescription() const
Definition: class_module.h:167
bool GetDoNotAllowVias() const
Definition: class_zone.h:656
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:169
DLIST< MODULE > m_Modules
Definition: class_board.h:245
bool IsVisible() const
Definition: eda_text.h:176
int GetWidth() const
Definition: class_track.h:115
void SetOrientation(double newangle)
SHAPE_POLY_SET::ITERATOR IterateWithHoles()
Function IterateWithHoles returns an iterator to visit all points of the zone's main outline with hol...
Definition: class_zone.h:485
Virtual component: when created by copper shapes on board (Like edge card connectors, mounting hole...)
Definition: class_module.h:79
#define CTL_OMIT_TSTAMPS
Omit component time stamp (useless in library)
T NormalizeAnglePos(T Angle)
Normalize angle to be in the 0.0 .
Definition: trigo.h:214
TEXTE_PCB & Text()
LSET GetVisibleLayers() const
Function GetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
#define CTL_STD_LAYER_NAMES
Use English Standard layer names.
double GetOrientation() const
Function GetOrientation returns the rotation angle of the pad in tenths of degrees, but soon degrees.
Definition: class_pad.h:214
D_PAD m_Pad_Master
A dummy pad to store all default parameters.
int GetNumSegmZone() const
Calculate the zone segment count.
void format(BOARD *aBoard, int aNestLevel=0) const
BOARD * m_board
which BOARD, no ownership here
const wxSize & GetDelta() const
Definition: class_pad.h:185
Usual pad.
Definition: pad_shapes.h:58
HATCH_STYLE GetHatchStyle() const
Definition: class_zone.h:549
int CurLineNumber()
Function CurLineNumber returns the current line number within my LINE_READER.
Definition: dsnlexer.h:507
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
The common library.
int GetWidth() const
std::vector< VIA_DIMENSION > m_ViasDimensionsList
Vias size and drill list.
UTF8 Format() const
Function Format.
Definition: lib_id.cpp:263
Class FILE_OUTPUTFORMATTER may be used for text file output.
Definition: richio.h:492
int GetSize() const
Definition: class_mire.h:69
unsigned GetCount() const
Function GetCount returns the number of elements in the list.
Definition: dlist.h:126
void formatLayers(LSET aLayerMask, int aNestLevel=0) const
wxPoint m_crossBarO
wxDateTime GetLastModificationTime() const
DLIST< BOARD_ITEM > & GraphicalItemsList()
Definition: class_module.h:137
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:108
wxString GetPadName() const
Definition: class_pad.cpp:433
Pcbnew s-expression file format parser definition.
DLIST< D_PAD > & PadsList()
Definition: class_module.h:134
DLIST< TRACK > m_Track
Definition: class_board.h:246
int GetHatchPitch() const
Hatch related methods.
Definition: class_zone.cpp:920
void filterNetClass(const BOARD &aBoard, NETCLASS &aNetClass)
Removes empty nets (i.e. with node count equal zero) from net classes
Struct FUTURE_FORMAT_ERROR variant of PARSE_ERROR indicating that a syntax or related error was likel...
Definition: ki_exception.h:143
FP_CACHE(PCB_IO *aOwner, const wxString &aLibraryPath)
Map of footprint file name per MODULE*.
Module description (excepted pads)
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
bool m_MicroViasAllowed
true to allow micro vias
int GetValue() const
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
void Format(OUTPUTFORMATTER *aFormatter, int aNestLevel, int aControl=0) const
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Function Print formats and writes text to the output stream.
Definition: richio.cpp:408
#define CTL_OMIT_INITIAL_COMMENTS
omit MODULE initial comments
MODULE_MAP::iterator MODULE_ITER
const wxString & GetPath() const
Definition: class_module.h:173
int m_EdgeSegmentWidth
current graphic line width (EDGE layer only)
double m_SolderPasteMarginRatio
Solder pask margin ratio value of pad size The final margin is the sum of these 2 values...
unsigned GetPriority() const
Function GetPriority.
Definition: class_zone.h:119
int GetCurrentTrackWidth() const
Function GetCurrentTrackWidth.
EDGE_MODULE class definition.
class DRAWSEGMENT, a segment not on copper layers
Definition: typeinfo.h:103
bool FootprintLibDelete(const wxString &aLibraryPath, const PROPERTIES *aProperties=NULL) override
Function FootprintLibDelete deletes an existing footprint library and returns true, or if library does not exist returns false, or throws an exception if library exists but is read only or cannot be deleted for some other reason.
const wxArrayString * GetInitialComments() const
Return the initial comments block or NULL if none, without transfer of ownership. ...
Definition: class_module.h:648
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
#define FMT_ANGLE
Class STRING_LINE_READER is a LINE_READER that reads from a multiline 8 bit wide std::string.
Definition: richio.h:254
#define CTL_OMIT_HIDE
Definition: eda_text.h:42
bool IsPlaced() const
Definition: class_module.h:254
wxPoint m_featureLineDO
#define FMTIU
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Struct IO_ERROR is a class used to hold an error message and may be used when throwing exceptions con...
Definition: ki_exception.h:47
int GetPlacementCost180() const
Definition: class_module.h:530
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
LAYER_T GetLayerType(PCB_LAYER_ID aLayer) const
Function GetLayerType returns the type of the copper layer given by aLayer.
void SetFPID(const LIB_ID &aFPID)
Definition: class_module.h:165
Use thermal relief for pads.
Definition: zones.h:58
std::shared_ptr< CONNECTIVITY_DATA > GetConnectivity() const
Function GetConnectivity() returns list of missing connections between components/tracks.
Definition: class_board.h:290
void cacheLib(const wxString &aLibraryPath, const wxString &aFootprintName=wxEmptyString)
we only cache one footprint library, this determines which one.
Class DIMENSION.
int GetZoneClearance() const
Definition: class_zone.h:203
const wxPoint & GetOffset() const
Definition: class_pad.h:191
int GetThermalWidth() const
Definition: class_module.h:192
MODULE_MAP & GetModules()
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:251
void Save(const wxString &aFileName, BOARD *aBoard, const PROPERTIES *aProperties=NULL) override
Function Save will write aBoard to a storage file in a format that this PLUGIN implementation knows a...
NETCLASSES m_NetClasses
List of current netclasses. There is always the default netclass.
int m_SolderMaskMinWidth
Solder mask min width.
T NormalizeAngle360(T Angle)
Normalize angle to be in the -360.0 .. 360.0:
Definition: trigo.h:202
static wxString GetStandardLayerName(PCB_LAYER_ID aLayerId)
Function GetStandardLayerName returns an "English Standard" name of a PCB layer when given aLayerNumb...
Definition: class_board.h:647
wxDateTime GetLibModificationTime() const
pads are covered by copper
Definition: zones.h:59
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
wxPoint m_featureLineGF