KiCad PCB EDA Suite
class_libentry.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) 2004-2015 Jean-Pierre Charras, jp.charras at wanadoo.fr
5  * Copyright (C) 2008 Wayne Stambaugh <stambaughw@gmail.com>
6  * Copyright (C) 2004-2017 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
30 #include <fctsys.h>
31 #include <macros.h>
32 #include <kicad_string.h>
33 #include <class_drawpanel.h>
34 #include <plot_common.h>
35 #include <gr_basic.h>
36 #include <class_sch_screen.h>
37 #include <richio.h>
38 
39 #include <general.h>
40 #include <template_fieldnames.h>
41 #include <transform.h>
42 #include <class_library.h>
43 #include <class_libentry.h>
44 #include <lib_pin.h>
45 #include <lib_arc.h>
46 #include <lib_bezier.h>
47 #include <lib_circle.h>
48 #include <lib_polyline.h>
49 #include <lib_rectangle.h>
50 #include <lib_text.h>
51 
52 
53 // the separator char between the subpart id and the reference
54 // 0 (no separator) or '.' or some other character
56 
57 // the ascii char value to calculate the subpart symbol id from the part number:
58 // 'A' or '1' usually. (to print U1.A or U1.1)
59 // if this a a digit, a number is used as id symbol
61 
62 
63 const wxChar traceSchLibMem[] = wxT( "KICAD_TRACE_SCH_LIB_MEM" ); // public
64 
65 
66 LIB_ALIAS::LIB_ALIAS( const wxString& aName, LIB_PART* aRootPart ):
68  shared( aRootPart )
69 {
70  name = aName;
71 }
72 
73 
74 LIB_ALIAS::LIB_ALIAS( const LIB_ALIAS& aAlias, LIB_PART* aRootPart ) :
75  EDA_ITEM( aAlias ),
76  shared( aRootPart )
77 {
78  name = aAlias.name;
79 
80  description = aAlias.description;
81  keyWords = aAlias.keyWords;
82  docFileName = aAlias.docFileName;
83 }
84 
85 
87 {
88  wxASSERT_MSG( shared, wxT( "~LIB_ALIAS() without a LIB_PART" ) );
89 
90  wxLogTrace( traceSchLibMem,
91  wxT( "%s: destroying alias:'%s' of part:'%s'." ),
92  GetChars( wxString::FromAscii( __WXFUNCTION__ ) ), GetChars( name ),
93  GetChars( shared->GetName() ) );
94 
95  if( shared )
96  shared->RemoveAlias( this );
97 }
98 
99 
101 {
102  wxASSERT_MSG( shared, wxT( "LIB_ALIAS without a LIB_PART" ) );
103 
104  if( shared )
105  return shared->GetLibraryName();
106 
107  return wxString( _( "none" ) );
108 }
109 
110 
111 bool LIB_ALIAS::IsRoot() const
112 {
113  return name == shared->GetName();
114 }
115 
116 
118 {
119  return shared->GetLib();
120 }
121 
122 
124 {
125  if( description.IsEmpty() && keyWords.IsEmpty() && docFileName.IsEmpty() )
126  return true;
127 
128  try
129  {
130  aFormatter.Print( 0, "#\n$CMP %s\n", TO_UTF8( name ) );
131 
132  if( !description.IsEmpty() )
133  aFormatter.Print( 0, "D %s\n", TO_UTF8( description ) );
134 
135  if( !keyWords.IsEmpty() )
136  aFormatter.Print( 0, "K %s\n", TO_UTF8( keyWords ) );
137 
138  if( !docFileName.IsEmpty() )
139  aFormatter.Print( 0, "F %s\n", TO_UTF8( docFileName ) );
140 
141  aFormatter.Print( 0, "$ENDCMP\n" );
142  }
143  catch( const IO_ERROR& )
144  {
145  return false;
146  }
147 
148  return true;
149 }
150 
151 
152 bool LIB_ALIAS::operator==( const wxChar* aName ) const
153 {
154  return name == aName;
155 }
156 
157 
158 bool operator<( const LIB_ALIAS& aItem1, const LIB_ALIAS& aItem2 )
159 {
160  return aItem1.GetName() < aItem2.GetName();
161 }
162 
163 
164 int LibraryEntryCompare( const LIB_ALIAS* aItem1, const LIB_ALIAS* aItem2 )
165 {
166  return aItem1->GetName().Cmp( aItem2->GetName() );
167 }
168 
169 
172 {
173  void operator()(void const *) const
174  {
175  }
176 };
177 
178 
179 LIB_PART::LIB_PART( const wxString& aName, PART_LIB* aLibrary ) :
180  EDA_ITEM( LIB_PART_T ),
181  m_me( this, null_deleter() )
182 {
183  m_name = aName;
184  m_library = aLibrary;
185  m_dateModified = 0;
186  m_unitCount = 1;
187  m_pinNameOffset = 40;
189  m_unitsLocked = false;
190  m_showPinNumbers = true;
191  m_showPinNames = true;
192 
193  // Create the default alias if the name parameter is not empty.
194  if( !aName.IsEmpty() )
195  m_aliases.push_back( new LIB_ALIAS( aName, this ) );
196 
197  // Add the MANDATORY_FIELDS in RAM only. These are assumed to be present
198  // when the field editors are invoked.
199  LIB_FIELD* value = new LIB_FIELD( this, VALUE );
200  value->SetText( aName );
201  m_drawings[LIB_FIELD_T].push_back( value );
202 
206 }
207 
208 
209 LIB_PART::LIB_PART( LIB_PART& aPart, PART_LIB* aLibrary ) :
210  EDA_ITEM( aPart ),
211  m_me( this, null_deleter() )
212 {
213  LIB_ITEM* newItem;
214 
215  m_library = aLibrary;
216  m_name = aPart.m_name;
218  m_unitCount = aPart.m_unitCount;
224  m_options = aPart.m_options;
225 
226  for( LIB_ITEM& oldItem : aPart.m_drawings )
227  {
228  if( oldItem.IsNew() )
229  continue;
230 
231  newItem = (LIB_ITEM*) oldItem.Clone();
232  newItem->SetParent( this );
233  m_drawings.push_back( newItem );
234  }
235 
236  for( size_t i = 0; i < aPart.m_aliases.size(); i++ )
237  {
238  LIB_ALIAS* alias = new LIB_ALIAS( *aPart.m_aliases[i], this );
239  m_aliases.push_back( alias );
240  }
241 }
242 
243 
245 {
246  wxLogTrace( traceSchLibMem,
247  wxT( "%s: destroying part '%s' with alias list count of %llu." ),
248  GetChars( wxString::FromAscii( __WXFUNCTION__ ) ), GetChars( GetName() ),
249  (long long unsigned) m_aliases.size() );
250 
251  // If the part is being deleted directly rather than through the library,
252  // delete all of the aliases.
253  while( m_aliases.size() )
254  {
255  LIB_ALIAS* alias = m_aliases.back();
256  m_aliases.pop_back();
257  delete alias;
258  }
259 }
260 
261 
262 const wxString LIB_PART::GetLibraryName()
263 {
264  if( m_library )
265  return m_library->GetName();
266 
267  return wxString( _( "none" ) );
268 }
269 
270 
271 wxString LIB_PART::SubReference( int aUnit, bool aAddSeparator )
272 {
273  wxString subRef;
274 
275  if( m_subpartIdSeparator != 0 && aAddSeparator )
276  subRef << wxChar( m_subpartIdSeparator );
277 
278  if( m_subpartFirstId >= '0' && m_subpartFirstId <= '9' )
279  subRef << aUnit;
280  else
281  {
282  // use letters as notation. To allow more than 26 units, the sub ref
283  // use one letter if letter = A .. Z or a ... z, and 2 letters otherwise
284  // first letter is expected to be 'A' or 'a' (i.e. 26 letters are available)
285  int u;
286  aUnit -= 1; // Unit number starts to 1. now to 0.
287 
288  while( aUnit >= 26 ) // more than one letter are needed
289  {
290  u = aUnit / 26;
291  subRef << wxChar( m_subpartFirstId + u -1 );
292  aUnit %= 26;
293  }
294 
295  u = m_subpartFirstId + aUnit;
296  subRef << wxChar( u );
297  }
298 
299  return subRef;
300 }
301 
302 
303 void LIB_PART::SetName( const wxString& aName )
304 {
305  m_name = aName;
306  GetValueField().SetText( aName );
307 
308  // The LIB_ALIAS that is the LIB_PART name has to be created so create it.
309  if( m_aliases.size() == 0 )
310  m_aliases.push_back( new LIB_ALIAS( aName, this ) );
311  else
312  m_aliases[0]->SetName( aName );
313 }
314 
315 
316 void LIB_PART::Draw( EDA_DRAW_PANEL* aPanel, wxDC* aDc, const wxPoint& aOffset,
317  int aMulti, int aConvert, const PART_DRAW_OPTIONS& aOpts )
318 {
319  BASE_SCREEN* screen = aPanel ? aPanel->GetScreen() : NULL;
320 
321  GRSetDrawMode( aDc, aOpts.draw_mode );
322 
323  /* draw background for filled items using background option
324  * Solid lines will be drawn after the background
325  * Note also, background is not drawn when:
326  * printing in black and white
327  * If the color is not the default color (aColor != -1 )
328  */
329  if( ! ( screen && screen->m_IsPrinting && GetGRForceBlackPenState() )
330  && ( aOpts.color == COLOR4D::UNSPECIFIED ) )
331  {
332  for( LIB_ITEM& drawItem : m_drawings )
333  {
334  if( drawItem.m_Fill != FILLED_WITH_BG_BODYCOLOR )
335  continue;
336 
337  if( aOpts.only_selected && !drawItem.IsSelected() )
338  continue;
339 
340  // Do not draw an item while moving (the cursor handler does that)
341  if( drawItem.m_Flags & IS_MOVED )
342  continue;
343 
344  // Do not draw items not attached to the current part
345  if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) )
346  continue;
347 
348  if( aConvert && drawItem.m_Convert && ( drawItem.m_Convert != aConvert ) )
349  continue;
350 
351  if( drawItem.Type() == LIB_FIELD_T )
352  continue;
353 
354  if( drawItem.Type() == LIB_FIELD_T ) // TODO dead code?
355  {
356  drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
357  aOpts.draw_mode, (void*) NULL, aOpts.transform );
358  }
359 
360  // Now, draw only the background for items with
361  // m_Fill == FILLED_WITH_BG_BODYCOLOR:
362  drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
363  aOpts.draw_mode, (void*) false, aOpts.transform );
364  }
365  }
366 
367  // Track the index into the dangling pins list
368  size_t pin_index = 0;
369 
370  for( LIB_ITEM& drawItem : m_drawings )
371  {
372  if( aOpts.only_selected && !drawItem.IsSelected() )
373  continue;
374 
375  // Do not draw an item while moving (the cursor handler does that)
376  if( drawItem.m_Flags & IS_MOVED )
377  continue;
378 
379  // Do not draw items not attached to the current part
380  if( aMulti && drawItem.m_Unit && ( drawItem.m_Unit != aMulti ) )
381  continue;
382 
383  if( aConvert && drawItem.m_Convert && ( drawItem.m_Convert != aConvert ) )
384  continue;
385 
386  if( drawItem.Type() == LIB_FIELD_T )
387  {
388  LIB_FIELD& field = dynamic_cast<LIB_FIELD&>( drawItem );
389 
390  if( field.IsVisible() && !aOpts.draw_visible_fields )
391  continue;
392 
393  if( !field.IsVisible() && !aOpts.draw_hidden_fields )
394  continue;
395  }
396 
397  if( drawItem.Type() == LIB_PIN_T )
398  {
399  LIB_PIN& pin = dynamic_cast<LIB_PIN&>( drawItem );
400 
401  uintptr_t flags = 0;
402  if( aOpts.show_pin_text )
403  flags |= PIN_DRAW_TEXTS;
404 
405  if( aOpts.show_elec_type )
407 
408  if( aOpts.PinIsDangling( pin_index ) )
409  flags |= PIN_DRAW_DANGLING;
410 
411  if( pin.IsPowerConnection() && IsPower() )
412  flags |= PIN_DANGLING_HIDDEN;
413 
414  drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
415  aOpts.draw_mode, (void*) flags, aOpts.transform );
416 
417  ++pin_index;
418  }
419  else if( drawItem.Type() == LIB_FIELD_T )
420  {
421  drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
422  aOpts.draw_mode, (void*) NULL, aOpts.transform );
423  }
424  else
425  {
426  bool forceNoFill = drawItem.m_Fill == FILLED_WITH_BG_BODYCOLOR;
427  drawItem.Draw( aPanel, aDc, aOffset, aOpts.color,
428  aOpts.draw_mode, (void*) forceNoFill,
429  aOpts.transform );
430  }
431  }
432 
433  // Enable this to draw the anchor of the component.
434 #if 0
435  int len = aDc->DeviceToLogicalXRel( 3 );
436  EDA_RECT* const clipbox = aPanel ? aPanel->GetClipBox() : NULL;
437 
438  GRLine( clipbox, aDc, aOffset.x, aOffset.y - len, aOffset.x,
439  aOffset.y + len, 0, aOpts.color );
440  GRLine( clipbox, aDc, aOffset.x - len, aOffset.y, aOffset.x + len,
441  aOffset.y, 0, aOpts.color );
442 #endif
443 
444  /* Enable this to draw the bounding box around the component to validate
445  * the bounding box calculations. */
446 #if 0
447  EDA_RECT bBox = GetUnitBoundingBox( aMulti, aConvert );
448  bBox.RevertYAxis();
449  bBox = aOpts.transform.TransformCoordinate( bBox );
450  bBox.Move( aOffset );
451  GRRect( aPanel ? aPanel->GetClipBox() : NULL, aDc, bBox, 0, LIGHTMAGENTA );
452 #endif
453 }
454 
455 
456 void LIB_PART::Plot( PLOTTER* aPlotter, int aUnit, int aConvert,
457  const wxPoint& aOffset, const TRANSFORM& aTransform )
458 {
459  wxASSERT( aPlotter != NULL );
460 
461  aPlotter->SetColor( GetLayerColor( LAYER_DEVICE ) );
462  bool fill = aPlotter->GetColorMode();
463 
464  // draw background for filled items using background option
465  // Solid lines will be drawn after the background
466  for( LIB_ITEM& item : m_drawings )
467  {
468  // Lib Fields are not plotted here, because this plot function
469  // is used to plot schematic items, which have they own fields
470  if( item.Type() == LIB_FIELD_T )
471  continue;
472 
473  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
474  continue;
475 
476  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
477  continue;
478 
479  if( item.m_Fill == FILLED_WITH_BG_BODYCOLOR )
480  item.Plot( aPlotter, aOffset, fill, aTransform );
481  }
482 
483  // Not filled items and filled shapes are now plotted
484  // (plot only items which are not already plotted)
485  for( LIB_ITEM& item : m_drawings )
486  {
487  if( item.Type() == LIB_FIELD_T )
488  continue;
489 
490  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
491  continue;
492 
493  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
494  continue;
495 
496  if( item.m_Fill != FILLED_WITH_BG_BODYCOLOR )
497  item.Plot( aPlotter, aOffset, fill, aTransform );
498  }
499 }
500 
501 void LIB_PART::PlotLibFields( PLOTTER* aPlotter, int aUnit, int aConvert,
502  const wxPoint& aOffset, const TRANSFORM& aTransform )
503 {
504  wxASSERT( aPlotter != NULL );
505 
506  aPlotter->SetColor( GetLayerColor( LAYER_FIELDS ) );
507  bool fill = aPlotter->GetColorMode();
508 
509  for( LIB_ITEM& item : m_drawings )
510  {
511  if( item.Type() != LIB_FIELD_T )
512  continue;
513 
514  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
515  continue;
516 
517  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
518  continue;
519 
520  // The reference is a special case: we should change the basic text
521  // to add '?' and the part id
522  LIB_FIELD& field = (LIB_FIELD&) item;
523  wxString tmp = field.GetShownText();
524  if( field.GetId() == REFERENCE )
525  {
526  wxString text = field.GetFullText( aUnit );
527  field.SetText( text );
528  }
529  item.Plot( aPlotter, aOffset, fill, aTransform );
530  field.SetText( tmp );
531  }
532 }
533 
534 
535 void LIB_PART::RemoveDrawItem( LIB_ITEM* aItem, EDA_DRAW_PANEL* aPanel, wxDC* aDc )
536 {
537  wxASSERT( aItem != NULL );
538 
539  // none of the MANDATORY_FIELDS may be removed in RAM, but they may be
540  // omitted when saving to disk.
541  if( aItem->Type() == LIB_FIELD_T )
542  {
543  LIB_FIELD* field = (LIB_FIELD*) aItem;
544 
545  if( field->GetId() < MANDATORY_FIELDS )
546  {
547  wxLogWarning( _(
548  "An attempt was made to remove the %s field from component %s in library %s." ),
549  GetChars( field->GetName() ), GetChars( GetName() ),
550  GetChars( GetLibraryName() ) );
551  return;
552  }
553  }
554 
555  LIB_ITEMS& items = m_drawings[ aItem->Type() ];
556 
557  for( LIB_ITEMS::iterator i = items.begin(); i != items.end(); i++ )
558  {
559  if( *i == aItem )
560  {
561  if( aDc != NULL )
562  aItem->Draw( aPanel, aDc, wxPoint( 0, 0 ), COLOR4D::UNSPECIFIED,
563  g_XorMode, NULL, DefaultTransform );
564 
565  items.erase( i );
566  SetModified();
567  break;
568  }
569  }
570 }
571 
572 
574 {
575  wxASSERT( aItem != NULL );
576 
577  m_drawings.push_back( aItem );
578 }
579 
580 
582 {
583  if( m_drawings.empty( aType ) )
584  return NULL;
585 
586  if( aItem == NULL )
587  return &( *( m_drawings.begin( aType ) ) );
588 
589  // Search for the last item, assume aItem is of type aType
590  wxASSERT( ( aType == TYPE_NOT_INIT ) || ( aType == aItem->Type() ) );
592 
593  while( ( it != m_drawings.end( aType ) ) && ( aItem != &( *it ) ) )
594  ++it;
595 
596  // Search the next item
597  if( it != m_drawings.end( aType ) )
598  {
599  ++it;
600 
601  if( it != m_drawings.end( aType ) )
602  return &( *it );
603  }
604 
605  return NULL;
606 }
607 
608 
609 void LIB_PART::GetPins( LIB_PINS& aList, int aUnit, int aConvert )
610 {
611  if( m_drawings.empty( LIB_PIN_T ) )
612  return;
613 
614  /* Notes:
615  * when aUnit == 0: no unit filtering
616  * when aConvert == 0: no convert (shape selection) filtering
617  * when .m_Unit == 0, the body item is common to units
618  * when .m_Convert == 0, the body item is common to shapes
619  */
620  for( LIB_ITEM& item : m_drawings[ LIB_PIN_T ] )
621  {
622  // Unit filtering:
623  if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
624  continue;
625 
626  // Shape filtering:
627  if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
628  continue;
629 
630  aList.push_back( (LIB_PIN*) &item );
631  }
632 }
633 
634 
635 LIB_PIN* LIB_PART::GetPin( const wxString& aNumber, int aUnit, int aConvert )
636 {
637  LIB_PINS pinList;
638 
639  GetPins( pinList, aUnit, aConvert );
640 
641  for( size_t i = 0; i < pinList.size(); i++ )
642  {
643  wxASSERT( pinList[i]->Type() == LIB_PIN_T );
644 
645  if( aNumber == pinList[i]->GetNumber() )
646  return pinList[i];
647  }
648 
649  return NULL;
650 }
651 
652 
653 bool LIB_PART::PinsConflictWith( LIB_PART& aOtherPart, bool aTestNums, bool aTestNames,
654  bool aTestType, bool aTestOrientation, bool aTestLength )
655 {
656  LIB_PINS thisPinList;
657  GetPins( thisPinList, /* aUnit */ 0, /* aConvert */ 0 );
658 
659  for( LIB_PIN* eachThisPin : thisPinList )
660  {
661  wxASSERT( eachThisPin );
662  LIB_PINS otherPinList;
663  aOtherPart.GetPins( otherPinList, /* aUnit */ 0, /* aConvert */ 0 );
664  bool foundMatch = false;
665 
666  for( LIB_PIN* eachOtherPin : otherPinList )
667  {
668  wxASSERT( eachOtherPin );
669  // Same position?
670  if( eachThisPin->GetPosition() != eachOtherPin->GetPosition() )
671  continue;
672 
673  // Same number?
674  if( aTestNums && ( eachThisPin->GetNumber() != eachOtherPin->GetNumber() ))
675  continue;
676 
677  // Same name?
678  if( aTestNames && ( eachThisPin->GetName() != eachOtherPin->GetName() ))
679  continue;
680 
681  // Same electrical type?
682  if( aTestType && ( eachThisPin->GetType() != eachOtherPin->GetType() ))
683  continue;
684 
685  // Same orientation?
686  if( aTestOrientation && ( eachThisPin->GetOrientation() != eachOtherPin->GetOrientation() ))
687  continue;
688 
689  // Same length?
690  if( aTestLength && ( eachThisPin->GetLength() != eachOtherPin->GetLength() ))
691  continue;
692 
693  foundMatch = true;
694  }
695 
696  if( !foundMatch )
697  {
698  // This means there was not an identical (according to the arguments)
699  // pin at the same position in the other component.
700  return true;
701  }
702  }
703 
704  // The loop never gave up, so no conflicts were found.
705  return false;
706 }
707 
708 
709 bool LIB_PART::Save( OUTPUTFORMATTER& aFormatter )
710 {
711  LIB_FIELD& value = GetValueField();
712 
713  // First line: it s a comment (component name for readers)
714  aFormatter.Print( 0, "#\n# %s\n#\n", TO_UTF8( value.GetText() ) );
715 
716  // Save data
717  aFormatter.Print( 0, "DEF" );
718 
719  if( value.IsVisible() )
720  {
721  aFormatter.Print( 0, " %s", TO_UTF8( value.GetText() ) );
722  }
723  else
724  {
725  aFormatter.Print( 0, " ~%s", TO_UTF8( value.GetText() ) );
726  }
727 
728  LIB_FIELD& reference = GetReferenceField();
729 
730  if( !reference.GetText().IsEmpty() )
731  {
732  aFormatter.Print( 0, " %s", TO_UTF8( reference.GetText() ) );
733  }
734  else
735  {
736  aFormatter.Print( 0, " ~" );
737  }
738 
739  aFormatter.Print( 0, " %d %d %c %c %d %c %c\n",
740  0, m_pinNameOffset,
741  m_showPinNumbers ? 'Y' : 'N',
742  m_showPinNames ? 'Y' : 'N',
743  m_unitCount, m_unitsLocked ? 'L' : 'F',
744  m_options == ENTRY_POWER ? 'P' : 'N' );
745 
746  if( !SaveDateAndTime( aFormatter ) )
747  return false;
748 
749  LIB_FIELDS fields;
750  GetFields( fields );
751 
752  // Mandatory fields:
753  // may have their own save policy so there is a separate loop for them.
754  // Empty fields are saved, because the user may have set visibility,
755  // size and orientation
756  for( int i = 0; i < MANDATORY_FIELDS; ++i )
757  {
758  if( !fields[i].Save( aFormatter ) )
759  return false;
760  }
761 
762  // User defined fields:
763  // may have their own save policy so there is a separate loop for them.
764 
765  int fieldId = MANDATORY_FIELDS; // really wish this would go away.
766 
767  for( unsigned i = MANDATORY_FIELDS; i < fields.size(); ++i )
768  {
769  // There is no need to save empty fields, i.e. no reason to preserve field
770  // names now that fields names come in dynamically through the template
771  // fieldnames.
772  if( !fields[i].GetText().IsEmpty() )
773  {
774  fields[i].SetId( fieldId++ );
775 
776  if( !fields[i].Save( aFormatter ) )
777  return false;
778  }
779  }
780 
781  // Save the alias list: a line starting by "ALIAS". The first alias is the root
782  // and has the same name as the component. In the old library file format this
783  // alias does not get added to the alias list.
784  if( m_aliases.size() > 1 )
785  {
786  aFormatter.Print( 0, "ALIAS" );
787 
788  for( unsigned i = 1; i < m_aliases.size(); i++ )
789  {
790  aFormatter.Print( 0, " %s", TO_UTF8( m_aliases[i]->GetName() ) );
791  }
792 
793  aFormatter.Print( 0, "\n" );
794  }
795 
796  // Write the footprint filter list
797  if( m_FootprintList.GetCount() != 0 )
798  {
799  aFormatter.Print( 0, "$FPLIST\n" );
800 
801  for( unsigned i = 0; i < m_FootprintList.GetCount(); i++ )
802  {
803  aFormatter.Print( 0, " %s\n", TO_UTF8( m_FootprintList[i] ) );
804  }
805 
806  aFormatter.Print( 0, "$ENDFPLIST\n" );
807  }
808 
809  // Save graphics items (including pins)
810  if( !m_drawings.empty() )
811  {
812  /* we sort the draw items, in order to have an edition more easy,
813  * when a file editing "by hand" is made */
814  m_drawings.sort();
815 
816  aFormatter.Print( 0, "DRAW\n" );
817 
818  for( LIB_ITEM& item : m_drawings )
819  {
820  if( item.Type() == LIB_FIELD_T )
821  continue;
822 
823  if( !item.Save( aFormatter ) )
824  return false;
825  }
826 
827  aFormatter.Print( 0, "ENDDRAW\n" );
828  }
829 
830  aFormatter.Print( 0, "ENDDEF\n" );
831 
832  return true;
833 }
834 
835 
836 bool LIB_PART::Load( LINE_READER& aLineReader, wxString& aErrorMsg )
837 {
838  int unused;
839  char* p;
840  char* componentName;
841  char* prefix = NULL;
842  char* line;
843 
844  bool result;
845  wxString Msg;
846 
847  line = aLineReader.Line();
848 
849  p = strtok( line, " \t\r\n" );
850 
851  if( strcmp( p, "DEF" ) != 0 )
852  {
853  aErrorMsg.Printf( wxT( "DEF command expected in line %d, aborted." ),
854  aLineReader.LineNumber() );
855  return false;
856  }
857 
858  // Read DEF line:
859  char drawnum = 0;
860  char drawname = 0;
861 
862  if( ( componentName = strtok( NULL, " \t\n" ) ) == NULL // Part name:
863  || ( prefix = strtok( NULL, " \t\n" ) ) == NULL // Prefix name:
864  || ( p = strtok( NULL, " \t\n" ) ) == NULL // NumOfPins:
865  || sscanf( p, "%d", &unused ) != 1
866  || ( p = strtok( NULL, " \t\n" ) ) == NULL // TextInside:
867  || sscanf( p, "%d", &m_pinNameOffset ) != 1
868  || ( p = strtok( NULL, " \t\n" ) ) == NULL // DrawNums:
869  || sscanf( p, "%c", &drawnum ) != 1
870  || ( p = strtok( NULL, " \t\n" ) ) == NULL // DrawNums:
871  || sscanf( p, "%c", &drawname ) != 1
872  || ( p = strtok( NULL, " \t\n" ) ) == NULL // m_unitCount:
873  || sscanf( p, "%d", &m_unitCount ) != 1 )
874  {
875  aErrorMsg.Printf( wxT( "Wrong DEF format in line %d, skipped." ),
876  aLineReader.LineNumber() );
877 
878  while( (line = aLineReader.ReadLine()) != NULL )
879  {
880  p = strtok( line, " \t\n" );
881 
882  if( p && strcasecmp( p, "ENDDEF" ) == 0 )
883  break;
884  }
885 
886  return false;
887  }
888 
889  // Ensure m_unitCount is >= 1 (could be read as 0 in old libraries)
890  if( m_unitCount < 1 )
891  m_unitCount = 1;
892 
893  m_showPinNumbers = ( drawnum == 'N' ) ? false : true;
894  m_showPinNames = ( drawname == 'N' ) ? false : true;
895 
896  // Copy part name and prefix.
897  LIB_FIELD& value = GetValueField();
898 
899  if( componentName[0] != '~' )
900  {
901  m_name = FROM_UTF8( componentName );
902  value.SetText( m_name );
903  }
904  else
905  {
906  m_name = FROM_UTF8( &componentName[1] );
907  value.SetText( m_name );
908  value.SetVisible( false );
909  }
910 
911  // Add the root alias to the alias list.
912  m_aliases.push_back( new LIB_ALIAS( m_name, this ) );
913 
914  LIB_FIELD& reference = GetReferenceField();
915 
916  if( strcmp( prefix, "~" ) == 0 )
917  {
918  reference.Empty();
919  reference.SetVisible( false );
920  }
921  else
922  {
923  reference.SetText( FROM_UTF8( prefix ) );
924  }
925 
926  // Copy optional infos
927  if( ( p = strtok( NULL, " \t\n" ) ) != NULL && *p == 'L' )
928  m_unitsLocked = true;
929 
930  if( ( p = strtok( NULL, " \t\n" ) ) != NULL && *p == 'P' )
932 
933  // Read next lines, until "ENDDEF" is found
934  while( ( line = aLineReader.ReadLine() ) != NULL )
935  {
936  p = strtok( line, " \t\r\n" );
937 
938  // This is the error flag ( if an error occurs, result = false)
939  result = true;
940 
941  if( *line == '#' ) // a comment
942  continue;
943 
944  if( p == NULL ) // empty line
945  continue;
946 
947  if( line[0] == 'T' && line[1] == 'i' )
948  result = LoadDateAndTime( aLineReader );
949  else if( *line == 'F' )
950  result = LoadField( aLineReader, Msg );
951  else if( strcmp( p, "ENDDEF" ) == 0 ) // End of component description
952  goto ok;
953  else if( strcmp( p, "DRAW" ) == 0 )
954  result = LoadDrawEntries( aLineReader, Msg );
955  else if( strncmp( p, "ALIAS", 5 ) == 0 )
956  {
957  p = strtok( NULL, "\r\n" );
958  result = LoadAliases( p, aErrorMsg );
959  }
960  else if( strncmp( p, "$FPLIST", 5 ) == 0 )
961  result = LoadFootprints( aLineReader, Msg );
962 
963  // End line or block analysis: test for an error
964  if( !result )
965  {
966  if( Msg.IsEmpty() )
967  aErrorMsg.Printf( wxT( "error occurred at line %d " ), aLineReader.LineNumber() );
968  else
969  aErrorMsg.Printf( wxT( "error <%s> occurred at line %d " ),
970  GetChars( Msg ), aLineReader.LineNumber() );
971 
972  return false;
973  }
974  }
975 
976  return false;
977 
978 ok:
979  // If we are here, this part is O.k. - put it in:
980 
981  return true;
982 }
983 
984 
985 bool LIB_PART::LoadDrawEntries( LINE_READER& aLineReader, wxString& aErrorMsg )
986 {
987  char* line;
988  LIB_ITEM* newEntry = NULL;
989 
990  while( true )
991  {
992  if( !( line = aLineReader.ReadLine() ) )
993  {
994  aErrorMsg = wxT( "file ended prematurely loading component draw element" );
995  return false;
996  }
997 
998  if( strncmp( line, "ENDDRAW", 7 ) == 0 )
999  break;
1000 
1001  newEntry = NULL;
1002 
1003  switch( line[0] )
1004  {
1005  case 'A': // Arc
1006  newEntry = ( LIB_ITEM* ) new LIB_ARC( this );
1007  break;
1008 
1009  case 'C': // Circle
1010  newEntry = ( LIB_ITEM* ) new LIB_CIRCLE( this );
1011  break;
1012 
1013  case 'T': // Text
1014  newEntry = ( LIB_ITEM* ) new LIB_TEXT( this );
1015  break;
1016 
1017  case 'S': // Square
1018  newEntry = ( LIB_ITEM* ) new LIB_RECTANGLE( this );
1019  break;
1020 
1021  case 'X': // Pin Description
1022  newEntry = ( LIB_ITEM* ) new LIB_PIN( this );
1023  break;
1024 
1025  case 'P': // Polyline
1026  newEntry = ( LIB_ITEM* ) new LIB_POLYLINE( this );
1027  break;
1028 
1029  case 'B': // Bezier Curves
1030  newEntry = ( LIB_ITEM* ) new LIB_BEZIER( this );
1031  break;
1032 
1033  case '#': // Comment
1034  continue;
1035 
1036  case '\n':
1037  case '\r':
1038  case 0: // empty line
1039  continue;
1040 
1041  default:
1042  aErrorMsg.Printf( wxT( "undefined DRAW command %c" ), line[0] );
1043  return false;
1044  }
1045 
1046  if( !newEntry->Load( aLineReader, aErrorMsg ) )
1047  {
1048  aErrorMsg.Printf( wxT( "error '%s' in DRAW command %c" ),
1049  GetChars( aErrorMsg ), line[0] );
1050  delete newEntry;
1051 
1052  // Flush till end of draw section
1053  do
1054  {
1055  if( !aLineReader.ReadLine() )
1056  {
1057  aErrorMsg = wxT( "file ended prematurely while attempting "
1058  "to flush to end of drawing section." );
1059  return false;
1060  }
1061  } while( strncmp( line, "ENDDRAW", 7 ) != 0 );
1062 
1063  return false;
1064  }
1065  else
1066  {
1067  m_drawings.push_back( newEntry );
1068  }
1069  }
1070 
1071  return true;
1072 }
1073 
1074 
1075 bool LIB_PART::LoadAliases( char* aLine, wxString& aErrorMsg )
1076 {
1077  char* text = strtok( aLine, " \t\r\n" );
1078 
1079  while( text )
1080  {
1081  m_aliases.push_back( new LIB_ALIAS( FROM_UTF8( text ), this ) );
1082  text = strtok( NULL, " \t\r\n" );
1083  }
1084 
1085  return true;
1086 }
1087 
1088 
1089 bool LIB_PART::LoadField( LINE_READER& aLineReader, wxString& aErrorMsg )
1090 {
1091  LIB_FIELD* field = new LIB_FIELD( this );
1092 
1093  if( !field->Load( aLineReader, aErrorMsg ) )
1094  {
1095  delete field;
1096  return false;
1097  }
1098 
1099  if( field->GetId() < MANDATORY_FIELDS )
1100  {
1101  LIB_FIELD* fixedField = GetField( field->GetId() );
1102 
1103  // this will fire only if somebody broke a constructor or editor.
1104  // MANDATORY_FIELDS are always present in ram resident components, no
1105  // exceptions, and they always have their names set, even fixed fields.
1106  wxASSERT( fixedField );
1107 
1108  *fixedField = *field;
1109 
1110  if( field->GetId() == VALUE )
1111  m_name = field->GetText();
1112 
1113  delete field;
1114  }
1115  else
1116  {
1117  m_drawings.push_back( field );
1118  }
1119 
1120  return true;
1121 }
1122 
1123 
1124 bool LIB_PART::LoadFootprints( LINE_READER& aLineReader, wxString& aErrorMsg )
1125 {
1126  char* line;
1127  char* p;
1128 
1129  while( true )
1130  {
1131  if( !( line = aLineReader.ReadLine() ) )
1132  {
1133  aErrorMsg = wxT( "file ended prematurely while loading footprints" );
1134  return false;
1135  }
1136 
1137  p = strtok( line, " \t\r\n" );
1138 
1139  if( strcasecmp( p, "$ENDFPLIST" ) == 0 )
1140  break;
1141 
1142  m_FootprintList.Add( FROM_UTF8( p ) );
1143  }
1144 
1145  return true;
1146 }
1147 
1148 
1149 const EDA_RECT LIB_PART::GetUnitBoundingBox( int aUnit, int aConvert ) const
1150 {
1151  EDA_RECT bBox;
1152  bool initialized = false;
1153 
1154  for( const LIB_ITEM& item : m_drawings )
1155  {
1156  if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
1157  && ( aUnit != item.m_Unit ) ) )
1158  continue;
1159 
1160  if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) )
1161  continue;
1162 
1163  if ( ( item.Type() == LIB_FIELD_T ) && !( ( LIB_FIELD& ) item ).IsVisible() )
1164  continue;
1165 
1166  if( initialized )
1167  bBox.Merge( item.GetBoundingBox() );
1168  else
1169  {
1170  bBox = item.GetBoundingBox();
1171  initialized = true;
1172  }
1173  }
1174 
1175  return bBox;
1176 }
1177 
1178 
1179 const EDA_RECT LIB_PART::GetBodyBoundingBox( int aUnit, int aConvert ) const
1180 {
1181  EDA_RECT bBox;
1182  bool initialized = false;
1183 
1184  for( const LIB_ITEM& item : m_drawings )
1185  {
1186  if( ( item.m_Unit > 0 ) && ( ( m_unitCount > 1 ) && ( aUnit > 0 )
1187  && ( aUnit != item.m_Unit ) ) )
1188  continue;
1189 
1190  if( item.m_Convert > 0 && ( ( aConvert > 0 ) && ( aConvert != item.m_Convert ) ) )
1191  continue;
1192 
1193  if( item.Type() == LIB_FIELD_T )
1194  continue;
1195 
1196  if( initialized )
1197  bBox.Merge( item.GetBoundingBox() );
1198  else
1199  {
1200  bBox = item.GetBoundingBox();
1201  initialized = true;
1202  }
1203  }
1204 
1205  return bBox;
1206 }
1207 
1208 
1210 {
1211  m_drawings[ LIB_FIELD_T ].clear();
1212 }
1213 
1214 
1215 void LIB_PART::SetFields( const std::vector <LIB_FIELD>& aFields )
1216 {
1217  deleteAllFields();
1218 
1219  for( unsigned i=0; i<aFields.size(); ++i )
1220  {
1221  // drawings is a ptr_vector, new and copy an object on the heap.
1222  LIB_FIELD* field = new LIB_FIELD( aFields[i] );
1223 
1224  field->SetParent( this );
1225  m_drawings.push_back( field );
1226  }
1227 }
1228 
1229 
1231 {
1232  LIB_FIELD* field;
1233 
1234  // The only caller of this function is the library field editor, so it
1235  // establishes policy here.
1236 
1237  // Grab the MANDATORY_FIELDS first, in expected order given by
1238  // enum NumFieldType
1239  for( int id=0; id<MANDATORY_FIELDS; ++id )
1240  {
1241  field = GetField( id );
1242 
1243  // the MANDATORY_FIELDS are exactly that in RAM.
1244  wxASSERT( field );
1245 
1246  aList.push_back( *field );
1247  }
1248 
1249  // Now grab all the rest of fields.
1250  for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
1251  {
1252  field = ( LIB_FIELD* ) &item;
1253 
1254  if( (unsigned) field->GetId() < MANDATORY_FIELDS )
1255  continue; // was added above
1256 
1257  aList.push_back( *field );
1258  }
1259 }
1260 
1261 
1263 {
1264  for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
1265  {
1266  LIB_FIELD* field = ( LIB_FIELD* ) &item;
1267 
1268  if( field->GetId() == aId )
1269  return field;
1270  }
1271 
1272  return NULL;
1273 }
1274 
1275 
1276 LIB_FIELD* LIB_PART::FindField( const wxString& aFieldName )
1277 {
1278  for( LIB_ITEM& item : m_drawings[ LIB_FIELD_T ] )
1279  {
1280  LIB_FIELD* field = ( LIB_FIELD* ) &item;
1281 
1282  if( field->GetName() == aFieldName )
1283  return field;
1284  }
1285 
1286  return NULL;
1287 }
1288 
1289 
1291 {
1292  LIB_FIELD* field = GetField( VALUE );
1293  wxASSERT( field != NULL );
1294  return *field;
1295 }
1296 
1297 
1299 {
1300  LIB_FIELD* field = GetField( REFERENCE );
1301  wxASSERT( field != NULL );
1302  return *field;
1303 }
1304 
1305 
1307 {
1308  LIB_FIELD* field = GetField( FOOTPRINT );
1309  wxASSERT( field != NULL );
1310  return *field;
1311 }
1312 
1313 
1315 {
1316  int year, mon, day, hour, min, sec;
1317 
1318  if( m_dateModified == 0 )
1319  return true;
1320 
1321  sec = m_dateModified & 63;
1322  min = ( m_dateModified >> 6 ) & 63;
1323  hour = ( m_dateModified >> 12 ) & 31;
1324  day = ( m_dateModified >> 17 ) & 31;
1325  mon = ( m_dateModified >> 22 ) & 15;
1326  year = ( m_dateModified >> 26 ) + 1990;
1327 
1328  aFormatter.Print( 0, "Ti %d/%d/%d %d:%d:%d\n", year, mon, day, hour, min, sec );
1329 
1330  return true;
1331 }
1332 
1333 
1334 bool LIB_PART::LoadDateAndTime( char* aLine )
1335 {
1336  int year, mon, day, hour, min, sec;
1337 
1338  year = mon = day = hour = min = sec = 0;
1339  strtok( aLine, " \r\t\n" );
1340  strtok( NULL, " \r\t\n" );
1341 
1342  if( sscanf( aLine, "%d/%d/%d %d:%d:%d", &year, &mon, &day, &hour, &min, &sec ) != 6 )
1343  return false;
1344 
1345  m_dateModified = ( sec & 63 ) + ( ( min & 63 ) << 6 ) +
1346  ( ( hour & 31 ) << 12 ) + ( ( day & 31 ) << 17 ) +
1347  ( ( mon & 15 ) << 22 ) + ( ( year - 1990 ) << 26 );
1348 
1349  return true;
1350 }
1351 
1352 
1353 void LIB_PART::SetOffset( const wxPoint& aOffset )
1354 {
1355  for( LIB_ITEM& item : m_drawings )
1356  item.SetOffset( aOffset );
1357 }
1358 
1359 
1361 {
1362  m_drawings.unique();
1363 }
1364 
1365 
1367 {
1368  for( const LIB_ITEM& item : m_drawings )
1369  {
1370  if( item.m_Convert > 1 )
1371  return true;
1372  }
1373 
1374  return false;
1375 }
1376 
1377 
1379 {
1380  for( LIB_ITEM& item : m_drawings )
1381  {
1382  item.m_Flags = 0;
1383  }
1384 }
1385 
1386 
1387 int LIB_PART::SelectItems( EDA_RECT& aRect, int aUnit, int aConvert, bool aEditPinByPin )
1388 {
1389  int itemCount = 0;
1390 
1391  for( LIB_ITEM& item : m_drawings )
1392  {
1393  item.ClearFlags( SELECTED );
1394 
1395  if( ( item.m_Unit && item.m_Unit != aUnit )
1396  || ( item.m_Convert && item.m_Convert != aConvert ) )
1397  {
1398  if( item.Type() != LIB_PIN_T )
1399  continue;
1400 
1401  // Specific rules for pins.
1402  if( aEditPinByPin || m_unitsLocked
1403  || ( item.m_Convert && item.m_Convert != aConvert ) )
1404  continue;
1405  }
1406 
1407  if( item.Inside( aRect ) )
1408  {
1409  item.SetFlags( SELECTED );
1410  itemCount++;
1411  }
1412  }
1413 
1414  return itemCount;
1415 }
1416 
1417 
1418 void LIB_PART::MoveSelectedItems( const wxPoint& aOffset )
1419 {
1420  for( LIB_ITEM& item : m_drawings )
1421  {
1422  if( !item.IsSelected() )
1423  continue;
1424 
1425  item.SetOffset( aOffset );
1426  item.m_Flags = 0;
1427  }
1428 }
1429 
1430 
1432 {
1433  for( LIB_ITEM& item : m_drawings )
1434  {
1435  item.m_Flags = 0;
1436  }
1437 }
1438 
1439 
1441 {
1443 
1444  // We *do not* remove the 2 mandatory fields: reference and value
1445  // so skip them (do not remove) if they are flagged selected.
1446  // Skip also not visible items.
1447  // But I think fields must not be deleted by a block delete command or other global command
1448  // because they are not really graphic items
1449  while( item != m_drawings.end() )
1450  {
1451  if( item->Type() == LIB_FIELD_T )
1452  {
1453 #if 0 // Set to 1 to allows fields deletion on block delete or other global command
1454  LIB_FIELD& field = ( LIB_FIELD& ) *item;
1455 
1456  if( (field.GetId() == REFERENCE) || (field.m_FieldId == VALUE) ||
1457  (field.m_Attributs & TEXT_NO_VISIBLE) )
1458 #endif
1459  item->ClearFlags( SELECTED );
1460  }
1461 
1462  if( !item->IsSelected() )
1463  ++item;
1464  else
1465  item = m_drawings.erase( item );
1466  }
1467 }
1468 
1469 
1470 void LIB_PART::CopySelectedItems( const wxPoint& aOffset )
1471 {
1472  std::vector< LIB_ITEM* > tmp;
1473 
1474  for( LIB_ITEM& item : m_drawings )
1475  {
1476  // We *do not* copy fields because they are unique for the whole component
1477  // so skip them (do not duplicate) if they are flagged selected.
1478  if( item.Type() == LIB_FIELD_T )
1479  item.ClearFlags( SELECTED );
1480 
1481  if( !item.IsSelected() )
1482  continue;
1483 
1484  item.ClearFlags( SELECTED );
1485  LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
1486  newItem->SetFlags( SELECTED );
1487 
1488  // When push_back elements in buffer, a memory reallocation can happen
1489  // and will break pointers.
1490  // So, push_back later.
1491  tmp.push_back( newItem );
1492  }
1493 
1494  for( auto item : tmp )
1495  m_drawings.push_back( item );
1496 
1497  MoveSelectedItems( aOffset );
1498 }
1499 
1500 
1502 {
1503  for( LIB_ITEM& item : m_drawings )
1504  {
1505  if( !item.IsSelected() )
1506  continue;
1507 
1508  item.MirrorHorizontal( aCenter );
1509  item.m_Flags = 0;
1510  }
1511 }
1512 
1513 
1515 {
1516  for( LIB_ITEM& item : m_drawings )
1517  {
1518  if( !item.IsSelected() )
1519  continue;
1520 
1521  item.MirrorVertical( aCenter );
1522  item.m_Flags = 0;
1523  }
1524 }
1525 
1526 
1528 {
1529  for( LIB_ITEM& item : m_drawings )
1530  {
1531  if( !item.IsSelected() )
1532  continue;
1533 
1534  item.Rotate( aCenter );
1535  item.m_Flags = 0;
1536  }
1537 }
1538 
1539 
1540 LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert,
1541  KICAD_T aType, const wxPoint& aPoint )
1542 {
1543  for( LIB_ITEM& item : m_drawings )
1544  {
1545  if( ( aUnit && item.m_Unit && ( aUnit != item.m_Unit) )
1546  || ( aConvert && item.m_Convert && ( aConvert != item.m_Convert ) )
1547  || ( ( item.Type() != aType ) && ( aType != TYPE_NOT_INIT ) ) )
1548  continue;
1549 
1550  if( item.HitTest( aPoint ) )
1551  return &item;
1552  }
1553 
1554  return NULL;
1555 }
1556 
1557 
1558 LIB_ITEM* LIB_PART::LocateDrawItem( int aUnit, int aConvert, KICAD_T aType,
1559  const wxPoint& aPoint, const TRANSFORM& aTransform )
1560 {
1561  /* we use LocateDrawItem( int aUnit, int convert, KICAD_T type, const
1562  * wxPoint& pt ) to search items.
1563  * because this function uses DefaultTransform as orient/mirror matrix
1564  * we temporary copy aTransform in DefaultTransform
1565  */
1566  LIB_ITEM* item;
1567  TRANSFORM transform = DefaultTransform;
1568  DefaultTransform = aTransform;
1569 
1570  item = LocateDrawItem( aUnit, aConvert, aType, aPoint );
1571 
1572  // Restore matrix
1573  DefaultTransform = transform;
1574 
1575  return item;
1576 }
1577 
1578 
1579 void LIB_PART::SetUnitCount( int aCount )
1580 {
1581  if( m_unitCount == aCount )
1582  return;
1583 
1584  if( aCount < m_unitCount )
1585  {
1587 
1588  while( i != m_drawings.end() )
1589  {
1590  if( i->m_Unit > aCount )
1591  i = m_drawings.erase( i );
1592  else
1593  ++i;
1594  }
1595  }
1596  else
1597  {
1598  int prevCount = m_unitCount;
1599 
1600  // Temporary storage for new items, as adding new items directly to
1601  // m_drawings may cause the buffer reallocation which invalidates the
1602  // iterators
1603  std::vector< LIB_ITEM* > tmp;
1604 
1605  for( LIB_ITEM& item : m_drawings )
1606  {
1607  if( item.m_Unit != 1 )
1608  continue;
1609 
1610  for( int j = prevCount + 1; j <= aCount; j++ )
1611  {
1612  LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
1613  newItem->m_Unit = j;
1614  tmp.push_back( newItem );
1615  }
1616  }
1617 
1618  for( auto item : tmp )
1619  m_drawings.push_back( item );
1620  }
1621 
1622  m_unitCount = aCount;
1623 }
1624 
1625 
1626 void LIB_PART::SetConversion( bool aSetConvert )
1627 {
1628  if( aSetConvert == HasConversion() )
1629  return;
1630 
1631  // Duplicate items to create the converted shape
1632  if( aSetConvert )
1633  {
1634  std::vector< LIB_ITEM* > tmp; // Temporarily store the duplicated pins here.
1635 
1636  for( LIB_ITEM& item : m_drawings )
1637  {
1638  // Only pins are duplicated.
1639  if( item.Type() != LIB_PIN_T )
1640  continue;
1641 
1642  if( item.m_Convert == 1 )
1643  {
1644  LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
1645  newItem->m_Convert = 2;
1646  tmp.push_back( newItem );
1647  }
1648  }
1649 
1650  // Transfer the new pins to the LIB_PART.
1651  for( unsigned i = 0; i < tmp.size(); i++ )
1652  m_drawings.push_back( tmp[i] );
1653  }
1654  else
1655  {
1656  // Delete converted shape items because the converted shape does
1657  // not exist
1659 
1660  while( i != m_drawings.end() )
1661  {
1662  if( i->m_Convert > 1 )
1663  i = m_drawings.erase( i );
1664  else
1665  ++i;
1666  }
1667  }
1668 }
1669 
1670 
1671 wxArrayString LIB_PART::GetAliasNames( bool aIncludeRoot ) const
1672 {
1673  wxArrayString names;
1674 
1675  LIB_ALIASES::const_iterator it;
1676 
1677  for( it=m_aliases.begin(); it != m_aliases.end(); ++it )
1678  {
1679  if( !aIncludeRoot && (*it)->IsRoot() )
1680  continue;
1681 
1682  names.Add( (*it)->GetName() );
1683  }
1684 
1685  return names;
1686 }
1687 
1688 
1689 bool LIB_PART::HasAlias( const wxString& aName ) const
1690 {
1691  wxCHECK2_MSG( !aName.IsEmpty(), return false,
1692  wxT( "Cannot get alias with an empty name, bad programmer." ) );
1693 
1694  for( size_t i = 0; i < m_aliases.size(); i++ )
1695  {
1696  if( aName == m_aliases[i]->GetName() )
1697  return true;
1698  }
1699 
1700  return false;
1701 }
1702 
1703 
1704 void LIB_PART::SetAliases( const wxArrayString& aAliasList )
1705 {
1706  wxCHECK_RET( !m_library,
1707  wxT( "Part aliases cannot be changed when they are owned by a library." ) );
1708 
1709  if( aAliasList == GetAliasNames() )
1710  return;
1711 
1712  // Add names not existing in the current component alias list.
1713  for( size_t i = 0; i < aAliasList.GetCount(); i++ )
1714  {
1715  if( HasAlias( aAliasList[ i ] ) )
1716  continue;
1717 
1718  m_aliases.push_back( new LIB_ALIAS( aAliasList[ i ], this ) );
1719  }
1720 
1721  // Remove names in the current component that are not in the new alias list.
1722  LIB_ALIASES::iterator it = m_aliases.begin();
1723 
1724  while( it != m_aliases.end() )
1725  {
1726  int index = aAliasList.Index( (*it)->GetName(), false );
1727 
1728  if( index != wxNOT_FOUND || (*it)->IsRoot() )
1729  ++it;
1730  else
1731  it = m_aliases.erase( it );
1732  }
1733 }
1734 
1735 
1736 #if 0 // this version looked suspect to me, it did not rename a deleted root
1737 
1738 void LIB_PART::RemoveAlias( const wxString& aName )
1739 {
1740  wxCHECK_RET( m_library == NULL,
1741  wxT( "Part aliases cannot be changed when they are owned by a library." ) );
1742  wxCHECK_RET( !aName.IsEmpty(), wxT( "Cannot get alias with an empty name." ) );
1743 
1744  LIB_ALIASES::iterator it;
1745 
1746  for( it = m_aliases.begin(); it != m_aliases.end(); it++ )
1747  {
1748  if( aName == (*it)->GetName() )
1749  {
1750  m_aliases.erase( it );
1751  break;
1752  }
1753  }
1754 }
1755 
1756 #else
1757 void LIB_PART::RemoveAlias( const wxString& aName )
1758 {
1759  LIB_ALIAS* a = GetAlias( aName );
1760 
1761  if( a )
1762  RemoveAlias( a );
1763 }
1764 #endif
1765 
1766 
1768 {
1769  wxCHECK_MSG( aAlias, NULL, wxT( "Cannot remove alias by NULL pointer." ) );
1770 
1771  LIB_ALIAS* nextAlias = NULL;
1772 
1773  LIB_ALIASES::iterator it = find( m_aliases.begin(), m_aliases.end(), aAlias );
1774 
1775  if( it != m_aliases.end() )
1776  {
1777  bool rename = aAlias->IsRoot();
1778 
1779  wxLogTrace( traceSchLibMem,
1780  wxT( "%s: part:'%s', alias:'%s', alias count %llu, reference count %ld." ),
1781  GetChars( wxString::FromAscii( __WXFUNCTION__ ) ),
1782  GetChars( m_name ),
1783  GetChars( aAlias->GetName() ),
1784  (long long unsigned) m_aliases.size(),
1785  m_me.use_count() );
1786 
1787  it = m_aliases.erase( it );
1788 
1789  if( !m_aliases.empty() )
1790  {
1791  if( it == m_aliases.end() )
1792  it = m_aliases.begin();
1793 
1794  nextAlias = *it;
1795 
1796  if( rename )
1797  SetName( nextAlias->GetName() );
1798  }
1799  }
1800 
1801  return nextAlias;
1802 }
1803 
1804 
1806 {
1807  // Remove all of the aliases except the root alias.
1808  while( m_aliases.size() > 1 )
1809  m_aliases.pop_back();
1810 }
1811 
1812 
1813 LIB_ALIAS* LIB_PART::GetAlias( const wxString& aName )
1814 {
1815  wxCHECK2_MSG( !aName.IsEmpty(), return NULL,
1816  wxT( "Cannot get alias with an empty name. Bad programmer!" ) );
1817 
1818  for( size_t i = 0; i < m_aliases.size(); i++ )
1819  {
1820  if( aName == m_aliases[i]->GetName() )
1821  return m_aliases[i];
1822  }
1823 
1824  return NULL;
1825 }
1826 
1827 
1829 {
1830  wxCHECK2_MSG( aIndex < m_aliases.size(), return NULL,
1831  wxT( "Illegal alias list index, bad programmer." ) );
1832 
1833  return m_aliases[aIndex];
1834 }
1835 
1836 
1837 void LIB_PART::AddAlias( const wxString& aName )
1838 {
1839  wxCHECK_RET( !HasAlias( aName ),
1840  wxT( "Part <" ) + GetName() + wxT( "> already has an alias <" ) +
1841  aName + wxT( ">. Bad programmer." ) );
1842 
1843  m_aliases.push_back( new LIB_ALIAS( aName, this ) );
1844 }
1845 
1846 
1847 void LIB_PART::SetSubpartIdNotation( int aSep, int aFirstId )
1848 {
1849  m_subpartFirstId = 'A';
1851 
1852  if( aSep == '.' || aSep == '-' || aSep == '_' )
1853  m_subpartIdSeparator = aSep;
1854 
1855  if( aFirstId == '1' && aSep != 0 )
1856  m_subpartFirstId = aFirstId;
1857 }
LIB_ALIASES m_aliases
List of alias object pointers associated with the part.
PART_LIB * GetLib()
virtual ~LIB_ALIAS()
LIB_FIELD & GetFootprintField()
Return reference to the footprint field.
GR_DRAWMODE g_XorMode
Definition: gr_basic.cpp:51
KICAD_T Type() const
Function Type()
Definition: base_struct.h:212
LIB_FIELD * GetField(int aId)
Return pointer to the requested field.
bool PinsConflictWith(LIB_PART &aOtherPart, bool aTestNums, bool aTestNames, bool aTestType, bool aTestOrientation, bool aTestLength)
Function PinsConflictWith returns true if this part's pins do not match another part's pins...
void SetModified()
static int m_subpartIdSeparator
the separator char between the subpart id and the reference like U1A ( m_subpartIdSeparator = 0 ) or ...
Class LINE_READER is an abstract class from which implementation specific LINE_READERs may be derived...
Definition: richio.h:81
void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDc, const wxPoint &aOffset, int aMulti, int aConvert, const PART_DRAW_OPTIONS &aOpts)
Draw part.
const EDA_RECT GetUnitBoundingBox(int aUnit, int aConvert) const
Function GetBoundingBox.
Part library alias object definition.
ITERATOR begin(int aType=UNDEFINED_TYPE)
Definition: multivector.h:183
bool PinIsDangling(size_t aPin) const
void Move(const wxPoint &aMoveVector)
Function Move moves the rectangle by the aMoveVector.
void SetConversion(bool aSetConvert)
Set or clear the alternate body style (DeMorgan) for the part.
virtual ~LIB_PART()
name of datasheet
virtual unsigned LineNumber() const
Function Line Number returns the line number of the last line read from this LINE_READER.
Definition: richio.h:159
void Merge(const EDA_RECT &aRect)
Function Merge modifies the position and size of the rectangle in order to contain aRect...
bool LoadFootprints(LINE_READER &aReader, wxString &aErrorMsg)
bool Load(LINE_READER &aLineReader, wxString &errorMsg) override
Definition: lib_field.cpp:157
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
bool Load(LINE_READER &aReader, wxString &aErrorMsg)
Load part definition from aReader.
bool HasConversion() const
Test if part has more than one body conversion type (DeMorgan).
bool m_showPinNumbers
Determines if part pin numbers are visible.
void GRSetDrawMode(wxDC *DC, GR_DRAWMODE draw_mode)
Definition: gr_basic.cpp:290
wxString description
documentation for info
int LibraryEntryCompare(const LIB_ALIAS *aItem1, const LIB_ALIAS *aItem2)
bool IsPower() const
LIB_ALIAS * GetAlias(size_t aIndex)
bool IsNew() const
Definition: base_struct.h:230
Class LIB_TEXT defines a component library graphical text item.
Definition: lib_text.h:45
virtual void SetColor(COLOR4D color)=0
virtual EDA_ITEM * Clone() const
Function Clone creates a duplicate of this item with linked list members set to NULL.
void GRLine(EDA_RECT *ClipBox, wxDC *DC, int x1, int y1, int x2, int y2, int width, COLOR4D Color)
Definition: gr_basic.cpp:352
int m_unitCount
Number of units (parts) per package.
const wxString GetLibraryName()
LIB_ITEM * GetNextDrawItem(LIB_ITEM *aItem=NULL, KICAD_T aType=TYPE_NOT_INIT)
Return the next draw object pointer.
PART_LIB * m_library
Library the part belongs to if any.
bool empty(int aType=UNDEFINED_TYPE)
Definition: multivector.h:224
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors...
Class LIB_FIELD is used in symbol libraries.
Definition: lib_field.h:60
static int m_subpartFirstId
the ascii char value to calculate the subpart symbol id from the part number: only 'A'...
void unique()
Remove duplicate elements in list.
Definition: multivector.h:238
const EDA_RECT GetBodyBoundingBox(int aUnit, int aConvert) const
Function GetBodyBoundingBox.
bool HasAlias(const wxString &aName) const
Test if alias aName is in part alias list.
void SetVisible(bool aVisible)
Definition: eda_text.h:175
LIB_ITEMS_CONTAINER m_drawings
Drawing items of this part.
void sort()
Definition: multivector.h:229
bool LoadDrawEntries(LINE_READER &aReader, wxString &aErrorMsg)
LIB_FIELD & GetValueField()
Return reference to the value field.
int m_Unit
Unit identification for multiple parts per package.
Class OUTPUTFORMATTER is an important interface (abstract class) used to output 8 bit text in a conve...
Definition: richio.h:327
LIB_ALIAS(const wxString &aName, LIB_PART *aRootComponent)
wxString GetFullText(int unit=1) const
Return the text of a field.
Definition: lib_field.cpp:529
void ClearSelectedItems()
Clears all the draw items marked by a block select.
void AddAlias(const wxString &aName)
Function AddAlias.
LIBRENTRYOPTIONS m_options
Special part features such as POWER or NORMAL.)
COLOR4D GetLayerColor(SCH_LAYER_ID aLayer)
Definition: eeschema.cpp:167
PART_LIB * GetLib()
void RevertYAxis()
Function RevertYAxis Mirror the rectangle from the X axis (negate Y pos and size) ...
void operator()(void const *) const
Field Name Module PCB, i.e. "16DIP300".
Field Reference of part, i.e. "IC21".
bool draw_hidden_fields
Whether to draw "hidden" fields.
KICAD_T
Enum KICAD_T is the set of class identification values, stored in EDA_ITEM::m_StructType.
Definition: typeinfo.h:90
bool m_unitsLocked
True if part has multiple units and changing one unit does not automatically change another unit...
Class LIB_ITEM is the base class for drawable items used by schematic library components.
Definition: lib_draw_item.h:67
LIB_ITEMS_CONTAINER::ITEM_PTR_VECTOR LIB_ITEMS
void MirrorSelectedItemsH(const wxPoint &aCenter)
Horizontally (X axis) mirror selected draw items about a point.
This file contains miscellaneous commonly used macros and functions.
wxString name
void PlotLibFields(PLOTTER *aPlotter, int aUnit, int aConvert, const wxPoint &aOffset, const TRANSFORM &aTransform)
Plot Lib Fields only of the part to plotter.
void SetOffset(const wxPoint &aOffset)
Move the part aOffset.
void MirrorSelectedItemsV(const wxPoint &aCenter)
Vertically (Y axis) mirror selected draw items about a point.
bool LoadDateAndTime(char *aLine)
ITERATOR end(int aType=UNDEFINED_TYPE)
Definition: multivector.h:189
void AddDrawItem(LIB_ITEM *aItem)
Add a new draw aItem to the draw object list.
virtual wxString GetShownText() const
Returns the string actually shown after processing of the base text.
Definition: eda_text.h:135
int m_pinNameOffset
The offset in mils to draw the pin name.
void GetPins(LIB_PINS &aList, int aUnit=0, int aConvert=0)
Return a list of pin object pointers from the draw item list.
wxPoint TransformCoordinate(const wxPoint &aPoint) const
Calculate a new coordinate according to the mirror/rotation transform.
Definition: transform.cpp:41
#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
void deleteAllFields()
#define SELECTED
Definition: base_struct.h:134
bool IsRoot() const
void GRRect(EDA_RECT *aClipBox, wxDC *aDC, int x1, int y1, int x2, int y2, COLOR4D aColor)
Definition: gr_basic.cpp:1077
bool LoadField(LINE_READER &aReader, wxString &aErrorMsg)
Class for tranforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
LIB_FIELD & GetReferenceField()
Return reference to the reference designator field.
void Plot(PLOTTER *aPlotter, int aUnit, int aConvert, const wxPoint &aOffset, const TRANSFORM &aTransform)
Plot lib part to plotter.
void SetFlags(STATUS_FLAGS aMask)
Definition: base_struct.h:267
LIB_FIELD * FindField(const wxString &aFieldName)
Function FindField finds a field within this part matching aFieldName and returns it or NULL if not f...
wxString m_name
void SetText(const wxString &aText) override
Sets the field text to aText.
Definition: lib_field.cpp:675
bool Save(OUTPUTFORMATTER &aFormatter)
Function Save writes the data structures out to aFormatter in the part library "*.lib" format.
void SetUnitCount(int count)
Set the units per part count.
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:227
int GetId() const
Definition: lib_field.h:136
wxString docFileName
Associate doc file name.
void CopySelectedItems(const wxPoint &aOffset)
Make a copy of the selected draw items marked by a block select.
Definitions for the Eeschema program SCH_SCREEN class.
const wxString & GetName() const
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
LIB_PART * shared
Actual LIB_PART referenced by [multiple] aliases.
void RotateSelectedItems(const wxPoint &aCenter)
Rotate CCW selected draw items about a point.
Class BASE_SCREEN handles how to draw a screen (a board, a schematic ...)
void push_back(T *aItem)
Definition: multivector.h:169
Class LIB_ITEM definition.
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:130
const wxString GetName() const
Return the file name without path or extension.
void Empty()
Definition: eda_text.h:231
bool operator==(const wxChar *aName) const
KEEPCASE sensitive comparison of the part entry name.
Class LIB_PART defines a library part object.
EDA_RECT * GetClipBox()
Common plot library Plot settings, and plotting engines (Postscript, Gerber, HPGL and DXF) ...
wxString GetText(GRAPHIC_PINSHAPE shape)
Definition: pin_shape.cpp:33
void RemoveDuplicateDrawItems()
Remove duplicate draw items from list.
bool operator<(const LIB_ALIAS &aItem1, const LIB_ALIAS &aItem2)
wxArrayString m_FootprintList
List of suitable footprint names for the part (wild card names accepted).
bool GetColorMode() const
Definition: plot_common.h:121
LIB_PART(const wxString &aName, PART_LIB *aLibrary=NULL)
wxString GetName(bool aTranslate=true) const
Returns the field name.
Definition: lib_field.cpp:605
const wxString GetLibraryName()
ITERATOR erase(const ITERATOR &aIterator)
Definition: multivector.h:174
http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared ...
ITERATOR_BASE< LIB_ITEM, MULTIVECTOR< LIB_ITEM, FIRST_TYPE_VAL, LAST_TYPE_VAL >, typename ITEM_PTR_VECTOR::iterator > ITERATOR
The non-const iterator
Definition: multivector.h:160
Field Value of part, i.e. "3.3K".
Base plotter engine class.
Definition: plot_common.h:86
void SetAliases(const wxArrayString &aAliasList)
std::vector< LIB_PIN * > LIB_PINS
Helper for defining a list of pin object pointers.
Definition: lib_draw_item.h:60
bool LoadAliases(char *aLine, wxString &aErrorMsg)
bool SaveDoc(OUTPUTFORMATTER &aFormatter)
Function SaveDocs write the entry document information to aFormatter in "*.dcm" format.
void ClearStatus()
Clears the status flag all draw objects in this part.
virtual char * ReadLine()=0
Function ReadLine reads a line of text into the buffer and increments the line number counter...
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
TRANSFORM DefaultTransform
Definition: eeschema.cpp:58
GR_DRAWMODE draw_mode
Device context drawing mode, see wxDC.
int SelectItems(EDA_RECT &aRect, int aUnit, int aConvert, bool aEditPinByPin)
Checks all draw objects of part to see if they are with block.
COLOR4D color
Color to draw part in.
void RemoveAlias(const wxString &aName)
void RemoveAllAliases()
virtual void Draw(EDA_DRAW_PANEL *aPanel, wxDC *aDC, const wxPoint &aOffset, COLOR4D aColor, GR_DRAWMODE aDrawMode, void *aData, const TRANSFORM &aTransform)
Draw an item.
const wxChar traceSchLibMem[]
Flag to enable schematic library memory deletion debug output.
const wxString & GetName() const
virtual bool Load(LINE_READER &aLine, wxString &aErrorMsg)=0
bool IsVisible() const
Function IsVisible.
Definition: lib_field.h:168
static void SetSubpartIdNotation(int aSep, int aFirstId)
Set the separator char between the subpart id and the reference 0 (no separator) or '...
std::vector< LIB_FIELD > LIB_FIELDS
Definition: lib_field.h:261
wxArrayString GetAliasNames(bool aIncludeRoot=true) const
Class EDA_RECT handles the component boundary box.
static wxString SubReference(int aUnit, bool aAddSeparator=true)
Function SubReference.
bool show_pin_text
Whether to show pin texts.
BASE_SCREEN * GetScreen()
Definition: draw_panel.cpp:187
void RemoveDrawItem(LIB_ITEM *aItem, EDA_DRAW_PANEL *aPanel=NULL, wxDC *aDc=NULL)
Remove draw aItem from list.
friend class LIB_ALIAS
bool only_selected
Draws only the body items that are selected, for block moves.
Class EDA_ITEM is a base class for most all the KiCad significant classes, used in schematics and boa...
Definition: base_struct.h:165
bool show_elec_type
Whether to show the pin electrical type.
int m_Convert
Shape identification for alternate body styles.
long m_dateModified
Date the part was last modified.
void ClearFlags(STATUS_FLAGS aMask=EDA_ITEM_ALL_FLAGS)
Definition: base_struct.h:268
void MoveSelectedItems(const wxPoint &aOffset)
Move the selected draw items marked by a block select.
bool IsPowerConnection() const
Return whether this pin forms an implicit power connection: i.e., is hidden and of type POWER_IN...
Definition: lib_pin.h:365
LIB_ITEM * LocateDrawItem(int aUnit, int aConvert, KICAD_T aType, const wxPoint &aPoint)
Locate a draw object.
virtual void SetName(const wxString &aName)
Definition for part library class.
bool draw_visible_fields
Whether to draw "visible" fields.
int PRINTF_FUNC Print(int nestLevel, const char *fmt,...)
Function Print formats and writes text to the output stream.
Definition: richio.cpp:408
bool GetGRForceBlackPenState(void)
Function GetGRForceBlackPenState.
Definition: gr_basic.cpp:281
void DeleteSelectedItems()
Deletes the select draw items marked by a block select.
bool m_showPinNames
Determines if part pin names are visible.
void SetFields(const std::vector< LIB_FIELD > &aFieldsList)
Function SetFields overwrites all the existing in this part with fields supplied in aFieldsList...
Class PART_LIB is used to load, save, search, and otherwise manipulate part library files...
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
TRANSFORM transform
Coordinate adjustment settings.
wxString keyWords
keyword list (used for search for parts by keyword)
void GetFields(LIB_FIELDS &aList)
Function GetFields returns a list of fields withing this part.
LIB_PIN * GetPin(const wxString &aNumber, int aUnit=0, int aConvert=0)
Return pin object with the requested pin aNumber.
#define min(a, b)
Definition: auxiliary.h:85
bool SaveDateAndTime(OUTPUTFORMATTER &aFormatter)
Function SaveDateAndTime write the date and time of part to aFile in the format: "Ti yy/mm/jj hh:mm:s...
Class LIB_BEZIER defines bezier curve graphic body item.
Definition: lib_bezier.h:39
#define IS_MOVED
Item being moved.
Definition: base_struct.h:126
PART_SPTR m_me
http://www.boost.org/doc/libs/1_55_0/libs/smart_ptr/sp_techniques.html#weak_without_shared ...