20#include <magic_enum.hpp>
38#define LIB_VERSION_MAJOR 2
39#define LIB_VERSION_MINOR 4
41#define LIB_VERSION( major, minor ) ( major * 100 + minor )
44#define LIBFILE_IDENT "EESchema-LIBRARY Version"
47#define DOCFILE_IDENT "EESchema-DOCLIB Version 2.0"
55#define USE_OLD_DOC_FILE_FORMAT( major, minor ) \
56 ( LIB_VERSION( major, minor ) <= LIB_VERSION( 2, 4 ) )
79 wxString::Format(
"Cannot use relative file paths in legacy plugin to "
90 const char* line = reader.
Line();
92 if( !
strCompare(
"EESchema-LIBRARY Version", line, &line ) )
96 if( !
strCompare(
"EESchema-LIB Version", line, &line ) )
97 SCH_PARSE_ERROR(
"file is not a valid symbol or symbol library file", reader, line );
113 SCH_PARSE_ERROR(
"invalid file version formatting in header", reader, line );
120 if(
m_versionMajor < 1 || m_versionMinor < 0 || m_versionMinor > 99 )
139 line = reader.
Line();
141 if( *line ==
'#' || isspace( *line ) )
180 if( !fn.FileExists() )
183 if( !fn.IsFileReadable() )
185 THROW_IO_ERROR( wxString::Format(
_(
"Insufficient permissions to read library '%s'." ),
186 fn.GetFullPath() ) );
198 SCH_PARSE_ERROR(
"invalid document library file version formatting in header",
204 line = reader.
Line();
212 aliasName = wxString::FromUTF8( line );
215 LIB_SYMBOL_MAP::iterator it =
m_symbols.find( aliasName );
218 wxLogWarning(
"Symbol '%s' not found in library:\n\n"
219 "'%s'\n\nat line %d offset %d", aliasName, fn.GetFullPath(),
229 line = reader.
Line();
266 SCH_PARSE_ERROR(
"expected token in symbol definition", reader, line );
275 const char* line = aReader.
Line();
277 wxASSERT(
strCompare(
"$HEADER", line, &line ) );
281 line = (
char*) aReader;
287 else if(
strCompare(
"$ENDHEADER", line, &line ) )
298 const char* line = aReader.
Line();
300 while( *line ==
'#' )
308 wxString utf8Line = wxString::FromUTF8( line );
309 wxStringTokenizer tokens( utf8Line,
" \r\n\t" );
311 if( tokens.CountTokens() < 8 )
315 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
317 wxString
name, prefix, tmp;
319 name = tokens.GetNextToken();
326 pos +=
name.size() + 1;
328 prefix = tokens.GetNextToken();
329 pos += prefix.size() + 1;
331 tmp = tokens.GetNextToken();
332 pos += tmp.size() + 1;
334 tmp = tokens.GetNextToken();
336 if( !tmp.ToLong( &num ) )
342 pos += tmp.size() + 1;
345 tmp = tokens.GetNextToken();
347 if( !( tmp ==
"Y" || tmp ==
"N") )
351 pos += tmp.size() + 1;
352 symbol->SetShowPinNumbers( ( tmp ==
"N" ) ?
false :
true );
354 tmp = tokens.GetNextToken();
356 if( !( tmp ==
"Y" || tmp ==
"N") )
362 pos += tmp.size() + 1;
363 symbol->SetShowPinNames( ( tmp ==
"N" ) ?
false :
true );
365 tmp = tokens.GetNextToken();
367 if( !tmp.ToLong( &num ) )
373 pos += tmp.size() + 1;
374 symbol->SetUnitCount( (
int)num );
377 if( symbol->GetUnitCount() < 1 )
378 symbol->SetUnitCount( 1 );
385 symbol->SetName(
"~" );
387 else if(
name[0] !=
'~' )
389 symbol->SetName(
name );
393 symbol->SetName(
name.Right(
name.Length() - 1 ) );
394 symbol->GetValueField().SetVisible(
false );
398 symbol->SetLibId(
LIB_ID( wxEmptyString, symbol->GetName() ) );
400 SCH_FIELD& reference = symbol->GetReferenceField();
414 if(
LIB_VERSION( aMajorVersion, aMinorVersion ) > 0
419 tmp = tokens.GetNextToken();
420 pos += tmp.size() + 1;
424 tmp = tokens.GetNextToken();
427 symbol->LockUnits(
true );
428 else if( tmp ==
"F" || tmp ==
"0" )
429 symbol->LockUnits(
false );
434 pos += tmp.size() + 1;
438 if( tokens.HasMoreTokens() )
440 tmp = tokens.GetNextToken();
444 else if( tmp ==
"N" )
462 else if( *line ==
'F' )
466 else if(
strCompare(
"$FPLIST", line, &line ) )
468 else if(
strCompare(
"ENDDEF", line, &line ) )
470 return symbol.release();
484 wxString newAliasName;
485 const char* line = aReader.
Line();
487 wxCHECK_RET(
strCompare(
"ALIAS", line, &line ),
"Invalid ALIAS section" );
489 wxString utf8Line = wxString::FromUTF8( line );
490 wxStringTokenizer tokens( utf8Line,
" \r\n\t" );
493 while( tokens.HasMoreTokens() )
495 newAliasName = tokens.GetNextToken();
509 SCH_FIELD* parentField = aSymbol->GetFieldById(
id );
511 wxASSERT( parentField );
513 *field = *parentField;
516 field->
SetText( newAliasName );
524 (*aMap)[ newSymbol->
GetName() ] = newSymbol;
533 const char* line = aReader.
Line();
535 wxCHECK_RET( *line ==
'F',
"Invalid field line" );
540 if( sscanf( line + 1,
"%d", &
id ) != 1 ||
id < 0 )
547 field = aSymbol->GetFieldById(
id );
556 field =
new SCH_FIELD( aSymbol.get(),
id );
557 aSymbol->AddDrawItem( field,
false );
561 while( *line !=
'"' && *line != 0 )
576 if(
text.size() == 1 &&
text[0] ==
'~' )
577 field->
SetText( wxEmptyString );
592 char textOrient =
parseChar( aReader, line, &line );
594 if( textOrient ==
'H' )
596 else if( textOrient ==
'V' )
599 SCH_PARSE_ERROR(
"invalid field text orientation parameter", aReader, line );
601 char textVisible =
parseChar( aReader, line, &line );
603 if( textVisible ==
'V' )
605 else if ( textVisible ==
'I' )
608 SCH_PARSE_ERROR(
"invalid field text visibility parameter", aReader, line );
614 if( *line != 0 && *line !=
'"' )
616 char textHJustify =
parseChar( aReader, line, &line );
618 if( textHJustify ==
'C' )
620 else if( textHJustify ==
'L' )
622 else if( textHJustify ==
'R' )
625 SCH_PARSE_ERROR(
"invalid field text horizontal justification", aReader, line );
631 size_t attrSize = attributes.size();
633 if( !(attrSize == 3 || attrSize == 1 ) )
634 SCH_PARSE_ERROR(
"invalid field text attributes size", aReader, line );
636 switch( (wxChar) attributes[0] )
641 default:
SCH_PARSE_ERROR(
"invalid field text vertical justification", aReader, line );
646 wxChar attr_1 = attributes[1];
647 wxChar attr_2 = attributes[2];
651 else if( attr_1 !=
'N' )
652 SCH_PARSE_ERROR(
"invalid field text italic parameter", aReader, line );
656 else if( attr_2 !=
'N' )
672 field->
SetText( aSymbol->GetName() );
676 wxString fieldName = wxEmptyString;
679 if( fieldName.IsEmpty() )
682 wxString candidateFieldName = fieldName;
686 while( aSymbol->FindField( candidateFieldName ) !=
nullptr )
687 candidateFieldName = wxString::Format(
"%s_%d", fieldName, ++suffix );
689 field->
SetName( candidateFieldName );
699 const char* line = aReader.
Line();
701 wxCHECK_RET(
strCompare(
"DRAW", line, &line ),
"Invalid DRAW section" );
709 aSymbol->GetDrawItems().sort();
716 aSymbol->AddDrawItem(
loadArc( aReader ),
false );
720 aSymbol->AddDrawItem(
loadCircle( aReader ),
false );
724 aSymbol->AddDrawItem(
loadText( aReader, aMajorVersion, aMinorVersion ),
false );
728 aSymbol->AddDrawItem(
loadRect( aReader ),
false );
732 aSymbol->AddDrawItem(
loadPin( aSymbol, aReader ),
false );
740 aSymbol->AddDrawItem(
loadBezier( aReader ),
false );
756 SCH_PARSE_ERROR(
"File ended prematurely loading symbol draw element.", aReader, line );
761 const char** aOutput )
763 switch (
parseChar( aReader, aLine, aOutput ) )
765 case 'F':
return FILL_T::FILLED_SHAPE;
766 case 'f':
return FILL_T::FILLED_WITH_BG_BODYCOLOR;
767 case 'N':
return FILL_T::NO_FILL;
771 SCH_PARSE_ERROR(
"invalid fill type, expected f, F, or N", aReader, aLine );
781 auto DECIDEG2RAD = [](
double deg ) ->
double
783 return deg * M_PI / 1800.0;
790 delta = *aAngle2 - *aAngle1;
798 x = cos( DECIDEG2RAD( *aAngle1 ) );
799 y = -sin( DECIDEG2RAD( *aAngle1 ) );
802 x = cos( DECIDEG2RAD( *aAngle2 ) );
803 y = -sin( DECIDEG2RAD( *aAngle2 ) );
809 if( *aAngle2 < *aAngle1 )
812 if( *aAngle2 - *aAngle1 > 1800 )
814 angle = ( *aAngle1 );
815 *aAngle1 = ( *aAngle2 );
821 if( *aAngle2 < *aAngle1 )
839 const char* line = aReader.
Line();
841 wxCHECK_MSG(
strCompare(
"A", line, &line ),
nullptr,
"Invalid arc definition" );
853 int angle1 =
parseInt( aReader, line, &line );
854 int angle2 =
parseInt( aReader, line, &line );
920 const char* line = aReader.
Line();
922 wxCHECK_MSG(
strCompare(
"C", line, &line ),
nullptr,
"Invalid circle definition" );
951 int aMajorVersion,
int aMinorVersion )
953 const char* line = aReader.
Line();
955 wxCHECK_MSG(
strCompare(
"T", line, &line ),
nullptr,
"Invalid SCH_TEXT definition" );
957 double angleInTenths;
965 angleInTenths =
parseInt( aReader, line, &line );
970 visible = !
parseInt( aReader, line, &line );
971 unit =
parseInt( aReader, line, &line );
972 bodyStyle =
parseInt( aReader, line, &line );
986 str.Replace(
"~",
" " );
992 str.Replace(
"''",
"\"" );
997 text->SetTextSize( size );
998 text->SetVisible( visible );
999 text->SetUnit( unit );
1000 text->SetBodyStyle( bodyStyle );
1009 if(
LIB_VERSION( aMajorVersion, aMinorVersion ) > 0
1014 text->SetItalic(
true );
1015 else if( !
strCompare(
"Normal", line, &line ) )
1016 SCH_PARSE_ERROR(
"invalid text stype, expected 'Normal' or 'Italic'", aReader, line );
1018 if(
parseInt( aReader, line, &line ) > 0 )
1019 text->SetBoldFlag(
true );
1024 switch(
parseChar( aReader, line, &line ) )
1029 default:
SCH_PARSE_ERROR(
"invalid horizontal text justication; expected L, C, or R",
1033 switch(
parseChar( aReader, line, &line ) )
1038 default:
SCH_PARSE_ERROR(
"invalid vertical text justication; expected T, C, or B",
1050 const char* line = aReader.
Line();
1052 wxCHECK_MSG(
strCompare(
"S", line, &line ),
nullptr,
"Invalid rectangle definition" );
1066 rectangle->
SetEnd( end );
1072 LINE_STYLE::SOLID );
1087 const char* line = aReader.
Line();
1089 wxCHECK_MSG(
strCompare(
"X", line, &line ),
nullptr,
"Invalid SCH_PIN definition" );
1096 wxString utf8Line = wxString::FromUTF8( line );
1097 wxStringTokenizer tokens( utf8Line,
" \r\n\t" );
1099 if( tokens.CountTokens() < 11 )
1102 tmp = tokens.GetNextToken();
1104 pos += tmp.size() + 1;
1106 tmp = tokens.GetNextToken();
1108 pos += tmp.size() + 1;
1113 tmp = tokens.GetNextToken();
1115 if( !tmp.ToLong( &num ) )
1121 pos += tmp.size() + 1;
1124 tmp = tokens.GetNextToken();
1126 if( !tmp.ToLong( &num ) )
1132 pos += tmp.size() + 1;
1135 tmp = tokens.GetNextToken();
1137 if( !tmp.ToLong( &num ) )
1143 pos += tmp.size() + 1;
1147 tmp = tokens.GetNextToken();
1149 if( tmp.size() > 1 )
1155 pos += tmp.size() + 1;
1158 std::optional<PIN_ORIENTATION> optVal = magic_enum::enum_cast<PIN_ORIENTATION>( tmp[0] );
1160 if( optVal.has_value() )
1161 orientation = optVal.value();
1163 tmp = tokens.GetNextToken();
1165 if( !tmp.ToLong( &num ) )
1171 pos += tmp.size() + 1;
1174 tmp = tokens.GetNextToken();
1176 if( !tmp.ToLong( &num ) )
1182 pos += tmp.size() + 1;
1185 tmp = tokens.GetNextToken();
1187 if( !tmp.ToLong( &num ) )
1193 pos += tmp.size() + 1;
1194 int unit = (int) num;
1196 tmp = tokens.GetNextToken();
1198 if( !tmp.ToLong( &num ) )
1204 pos += tmp.size() + 1;
1207 tmp = tokens.GetNextToken();
1209 if( tmp.size() != 1 )
1215 pos += tmp.size() + 1;
1221 case 'I': pinType = ELECTRICAL_PINTYPE::PT_INPUT;
break;
1222 case 'O': pinType = ELECTRICAL_PINTYPE::PT_OUTPUT;
break;
1223 case 'B': pinType = ELECTRICAL_PINTYPE::PT_BIDI;
break;
1224 case 'T': pinType = ELECTRICAL_PINTYPE::PT_TRISTATE;
break;
1225 case 'P': pinType = ELECTRICAL_PINTYPE::PT_PASSIVE;
break;
1226 case 'U': pinType = ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
break;
1227 case 'W': pinType = ELECTRICAL_PINTYPE::PT_POWER_IN;
break;
1228 case 'w': pinType = ELECTRICAL_PINTYPE::PT_POWER_OUT;
break;
1229 case 'C': pinType = ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
break;
1230 case 'E': pinType = ELECTRICAL_PINTYPE::PT_OPENEMITTER;
break;
1231 case 'N': pinType = ELECTRICAL_PINTYPE::PT_NC;
break;
1250 if( tokens.HasMoreTokens() )
1252 tmp = tokens.GetNextToken();
1258 LOWLEVEL_IN = 1 << 2,
1259 LOWLEVEL_OUT = 1 << 3,
1260 FALLING_EDGE = 1 << 4,
1266 for(
int j = (
int) tmp.size(); j > 0; )
1268 switch( tmp[--j].GetValue() )
1271 case 'N':
pin->SetVisible(
false );
break;
1272 case 'I': flags |=
INVERTED;
break;
1273 case 'C': flags |=
CLOCK;
break;
1274 case 'L': flags |= LOWLEVEL_IN;
break;
1275 case 'V': flags |= LOWLEVEL_OUT;
break;
1276 case 'F': flags |= FALLING_EDGE;
break;
1277 case 'X': flags |=
NONLOGIC;
break;
1287 case 0:
pin->SetShape( GRAPHIC_PINSHAPE::LINE );
break;
1288 case INVERTED:
pin->SetShape( GRAPHIC_PINSHAPE::INVERTED );
break;
1289 case CLOCK:
pin->SetShape( GRAPHIC_PINSHAPE::CLOCK );
break;
1290 case INVERTED |
CLOCK:
pin->SetShape( GRAPHIC_PINSHAPE::INVERTED_CLOCK );
break;
1291 case LOWLEVEL_IN:
pin->SetShape( GRAPHIC_PINSHAPE::INPUT_LOW );
break;
1292 case LOWLEVEL_IN |
CLOCK:
pin->SetShape( GRAPHIC_PINSHAPE::CLOCK_LOW );
break;
1293 case LOWLEVEL_OUT:
pin->SetShape( GRAPHIC_PINSHAPE::OUTPUT_LOW );
break;
1294 case FALLING_EDGE:
pin->SetShape( GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK );
break;
1295 case NONLOGIC:
pin->SetShape( GRAPHIC_PINSHAPE::NONLOGIC );
break;
1297 SCH_PARSE_ERROR(
"pin attributes do not define a valid pin shape", aReader, line );
1307 const char* line = aReader.
Line();
1309 wxCHECK_MSG(
strCompare(
"P", line, &line ),
nullptr,
"Invalid poly definition" );
1313 int points =
parseInt( aReader, line, &line );
1318 LINE_STYLE::SOLID );
1324 for(
int i = 0; i < points; i++ )
1340 const char* line = aReader.
Line();
1342 wxCHECK_MSG(
strCompare(
"B", line, &line ),
nullptr,
"Invalid Bezier definition" );
1344 int points =
parseInt( aReader, line, &line );
1346 wxCHECK_MSG( points == 4, NULL,
"Invalid Bezier curve definition" );
1354 LINE_STYLE::SOLID );
1388 const char* line = aReader.
Line();
1390 wxCHECK_RET(
strCompare(
"$FPLIST", line, &line ),
"Invalid footprint filter list" );
1394 wxArrayString footprintFilters;
1398 if(
strCompare(
"$ENDFPLIST", line, &line ) )
1400 aSymbol->SetFPFilters( footprintFilters );
1407 footprintFilters.Add( footprint );
1411 SCH_PARSE_ERROR(
"File ended prematurely while loading footprint filters.", aReader, line );
1419 bool doSaveDocFile = *aOpt;
1427 auto formatter = std::make_unique<FILE_OUTPUTFORMATTER>( fn.GetFullPath() );
1429 formatter->Print( 0,
"#encoding utf-8\n");
1433 if( !it->second->IsRoot() )
1439 formatter->Print( 0,
"#\n#End Library\n" );
1459 wxCHECK_RET( aSymbol && aSymbol->
IsRoot(),
"Invalid LIB_SYMBOL pointer." );
1463 wxArrayString aliasNames;
1467 for(
auto& entry : *aMap )
1472 aliasNames.Add( symbol->
GetName() );
1482 aFormatter.
Print( 0,
"DEF" );
1487 if( !reference.
GetText().IsEmpty() )
1490 aFormatter.
Print( 0,
" ~" );
1492 aFormatter.
Print( 0,
" %d %d %c %c %d %c %c\n",
1497 aSymbol->
IsPower() ?
'P' :
'N' );
1501 if( dateModified != 0 )
1503 int sec = dateModified & 63;
1504 int min = ( dateModified >> 6 ) & 63;
1505 int hour = ( dateModified >> 12 ) & 31;
1506 int day = ( dateModified >> 17 ) & 31;
1507 int mon = ( dateModified >> 22 ) & 15;
1508 int year = ( dateModified >> 26 ) + 1990;
1510 aFormatter.
Print( 0,
"Ti %d/%d/%d %d:%d:%d\n", year, mon, day, hour, min, sec );
1513 std::vector<SCH_FIELD*> fields;
1532 if( !fields[i]->GetText().IsEmpty() )
1534 fields[i]->SetId( fieldId++ );
1540 if( !aliasNames.IsEmpty() )
1542 aFormatter.
Print( 0,
"ALIAS" );
1544 for(
unsigned i = 0; i < aliasNames.GetCount(); i++ )
1545 aFormatter.
Print( 0,
" %s",
TO_UTF8( aliasNames[i] ) );
1547 aFormatter.
Print( 0,
"\n" );
1553 if( footprints.GetCount() != 0 )
1555 aFormatter.
Print( 0,
"$FPLIST\n" );
1557 for(
unsigned i = 0; i < footprints.GetCount(); i++ )
1558 aFormatter.
Print( 0,
" %s\n",
TO_UTF8( footprints[i] ) );
1560 aFormatter.
Print( 0,
"$ENDFPLIST\n" );
1569 aFormatter.
Print( 0,
"DRAW\n" );
1573 switch( item.Type() )
1589 case SHAPE_T::ARC:
saveArc( &shape, aFormatter );
break;
1590 case SHAPE_T::BEZIER:
saveBezier( &shape, aFormatter );
break;
1591 case SHAPE_T::CIRCLE:
saveCircle( &shape, aFormatter );
break;
1592 case SHAPE_T::POLY:
savePolyLine( &shape, aFormatter );
break;
1593 case SHAPE_T::RECTANGLE:
saveRectangle( &shape, aFormatter );
break;
1605 aFormatter.
Print( 0,
"ENDDRAW\n" );
1608 aFormatter.
Print( 0,
"ENDDEF\n" );
1614 wxCHECK_RET( aArc && aArc->
GetShape() == SHAPE_T::ARC,
"Invalid ARC object." );
1622 aFormatter.
Print( 0,
"A %d %d %d %d %d %d %d %d %c %d %d %d %d\n",
1641 wxCHECK_RET( aBezier && aBezier->
GetShape() == SHAPE_T::BEZIER,
"Invalid BEZIER object." );
1643 aFormatter.
Print( 0,
"B 4 %d %d %d",
1648 aFormatter.
Print( 0,
" %d %d %d %d %d %d %d %d",
1664 wxCHECK_RET( aCircle && aCircle->
GetShape() == SHAPE_T::CIRCLE,
"Invalid CIRCLE object." );
1666 aFormatter.
Print( 0,
"C %d %d %d %d %d %d %c\n",
1680 wxCHECK_RET( aField && aField->
Type() ==
SCH_FIELD_T,
"Invalid SCH_FIELD object." );
1682 int hjustify, vjustify;
1683 int id = aField->
GetId();
1700 aFormatter.
Print( 0,
"F%d %s %d %d %d %c %c %c %c%c%c",
1710 aField->
IsBold() ?
'B' :
'N' );
1722 aFormatter.
Print( 0,
"\n" );
1728 wxCHECK_RET( aPin && aPin->
Type() ==
SCH_PIN_T,
"Invalid SCH_PIN object." );
1735 case ELECTRICAL_PINTYPE::PT_INPUT: Etype =
'I';
break;
1736 case ELECTRICAL_PINTYPE::PT_OUTPUT: Etype =
'O';
break;
1737 case ELECTRICAL_PINTYPE::PT_BIDI: Etype =
'B';
break;
1738 case ELECTRICAL_PINTYPE::PT_TRISTATE: Etype =
'T';
break;
1739 case ELECTRICAL_PINTYPE::PT_PASSIVE: Etype =
'P';
break;
1740 case ELECTRICAL_PINTYPE::PT_UNSPECIFIED: Etype =
'U';
break;
1741 case ELECTRICAL_PINTYPE::PT_POWER_IN: Etype =
'W';
break;
1742 case ELECTRICAL_PINTYPE::PT_POWER_OUT: Etype =
'w';
break;
1743 case ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR: Etype =
'C';
break;
1744 case ELECTRICAL_PINTYPE::PT_OPENEMITTER: Etype =
'E';
break;
1745 case ELECTRICAL_PINTYPE::PT_NC: Etype =
'N';
break;
1748 if( !aPin->
GetName().IsEmpty() )
1751 aFormatter.
Print( 0,
"X ~" );
1753 aFormatter.
Print( 0,
" %s %d %d %d %c %d %d %d %d %c",
1766 aFormatter.
Print( 0,
" " );
1769 aFormatter.
Print( 0,
"N" );
1773 case GRAPHIC_PINSHAPE::LINE:
break;
1774 case GRAPHIC_PINSHAPE::INVERTED: aFormatter.
Print( 0,
"I" );
break;
1775 case GRAPHIC_PINSHAPE::CLOCK: aFormatter.
Print( 0,
"C" );
break;
1776 case GRAPHIC_PINSHAPE::INVERTED_CLOCK: aFormatter.
Print( 0,
"IC" );
break;
1777 case GRAPHIC_PINSHAPE::INPUT_LOW: aFormatter.
Print( 0,
"L" );
break;
1778 case GRAPHIC_PINSHAPE::CLOCK_LOW: aFormatter.
Print( 0,
"CL" );
break;
1779 case GRAPHIC_PINSHAPE::OUTPUT_LOW: aFormatter.
Print( 0,
"V" );
break;
1780 case GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK: aFormatter.
Print( 0,
"F" );
break;
1781 case GRAPHIC_PINSHAPE::NONLOGIC: aFormatter.
Print( 0,
"X" );
break;
1782 default: wxFAIL_MSG(
"Invalid pin shape" );
1785 aFormatter.
Print( 0,
"\n" );
1794 wxCHECK_RET( aPolyLine && aPolyLine->
GetShape() == SHAPE_T::POLY,
"Invalid POLY object." );
1796 aFormatter.
Print( 0,
"P %d %d %d %d",
1812 wxCHECK_RET( aRectangle && aRectangle->
GetShape() == SHAPE_T::RECTANGLE,
1813 "Invalid RECT object." );
1815 aFormatter.
Print( 0,
"S %d %d %d %d %d %d %d %c\n",
1829 wxCHECK_RET( aText && aText->
Type() ==
SCH_TEXT_T,
"Invalid SCH_TEXT object." );
1833 if(
text.Contains( wxT(
" " ) ) ||
text.Contains( wxT(
"~" ) ) ||
text.Contains( wxT(
"\"" ) ) )
1836 text.Replace( wxT(
"\"" ), wxT(
"''" ) );
1837 text = wxT(
"\"" ) +
text + wxT(
"\"" );
1840 aFormatter.
Print( 0,
"T %g %d %d %d %d %d %d %s",
1850 aFormatter.
Print( 0,
" %s %d", aText->
IsItalic() ?
"Italic" :
"Normal", aText->
IsBold() );
1852 char hjustify =
'C';
1859 char vjustify =
'C';
1866 aFormatter.
Print( 0,
" %c %c\n", hjustify, vjustify );
1887 wxString description = it->second->GetDescription();
1888 wxString keyWords = it->second->GetKeyWords();
1889 wxString docFileName = it->second->GetDatasheetField().GetText();
1891 if( description.IsEmpty() && keyWords.IsEmpty() && docFileName.IsEmpty() )
1894 formatter.
Print( 0,
"#\n$CMP %s\n",
TO_UTF8( it->second->GetName() ) );
1896 if( !description.IsEmpty() )
1897 formatter.
Print( 0,
"D %s\n",
TO_UTF8( description ) );
1899 if( !keyWords.IsEmpty() )
1902 if( !docFileName.IsEmpty() )
1903 formatter.
Print( 0,
"F %s\n",
TO_UTF8( docFileName ) );
1905 formatter.
Print( 0,
"$ENDCMP\n" );
1908 formatter.
Print( 0,
"#\n#End Doc Library\n" );
1914 LIB_SYMBOL_MAP::iterator it =
m_symbols.find( aSymbolName );
1917 THROW_IO_ERROR( wxString::Format(
_(
"library %s does not contain a symbol named %s" ),
1929 LIB_SYMBOL_MAP::iterator it1 =
m_symbols.begin();
1933 if( it1->second->IsAlias()
1934 && it1->second->GetParent().lock() == rootSymbol->
SharedPtr() )
constexpr EDA_IU_SCALE schIUScale
int AsTenthsOfADegree() const
bool IsHorizontal() const
KICAD_T Type() const
Returns the type of object.
virtual void SetParent(EDA_ITEM *aParent)
const VECTOR2I & GetBezierC2() const
void SetBezierC2(const VECTOR2I &aPt)
FILL_T GetFillMode() const
void RebuildBezierToSegmentsPointsList(int aMinSegLen)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
SHAPE_POLY_SET & GetPolyShape()
void CalcArcAngles(EDA_ANGLE &aStartAngle, EDA_ANGLE &aEndAngle) const
Calc arc start and end angles such that aStartAngle < aEndAngle.
const VECTOR2I & GetEnd() const
Return the ending point of the graphic.
void SetStart(const VECTOR2I &aStart)
const VECTOR2I & GetStart() const
Return the starting point of the graphic.
void SetEnd(const VECTOR2I &aEnd)
void SetBezierC1(const VECTOR2I &aPt)
const VECTOR2I & GetBezierC1() const
virtual int GetWidth() const
void SetFillMode(FILL_T aFill)
const VECTOR2I & GetTextPos() const
const EDA_ANGLE & GetTextAngle() const
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
virtual const wxString & GetText() const
Return the string associated with the text object.
virtual bool IsVisible() const
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
GR_TEXT_H_ALIGN_T GetHorizJustify() const
void SetBoldFlag(bool aBold)
virtual void SetVisible(bool aVisible)
GR_TEXT_V_ALIGN_T GetVertJustify() const
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetItalic(bool aItalic)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
A LINE_READER that reads from an open file.
char * ReadLine() override
Read a line of text into the buffer and increments the line number counter.
A logical library item identifier and consists of various portions much like a URI.
Define a library symbol object.
bool IsPower() const override
bool UnitsLocked() const
Check whether symbol units are interchangeable.
void GetFields(std::vector< SCH_FIELD * > &aList)
Return a list of fields within this symbol.
bool IsRoot() const override
For symbols derived from other symbols, IsRoot() indicates no derivation.
SCH_FIELD & GetValueField() const
Return reference to the value field.
timestamp_t GetLastModDate() const
SCH_FIELD * GetFieldById(int aId) const
Return pointer to the requested field.
LIB_ITEMS_CONTAINER & GetDrawItems()
Return a reference to the draw item list.
void SetParent(LIB_SYMBOL *aParent=nullptr)
wxString GetName() const override
void SetDescription(const wxString &aDescription)
Gets the Description field text value */.
void SetKeyWords(const wxString &aKeyWords)
SCH_FIELD & GetReferenceField() const
Return reference to the reference designator field.
wxArrayString GetFPFilters() const
LIB_SYMBOL_SPTR SharedPtr() const
int GetUnitCount() const override
LIB_SYMBOL_REF & GetParent()
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
virtual char * ReadLine()=0
Read a line of text into the buffer and increments the line number counter.
virtual const wxString & GetSource() const
Returns the name of the source of the lines in an abstract sense.
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
char * Line() const
Return a pointer to the last line that was read in.
bool empty(int aType=UNDEFINED_TYPE) const
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
void SetPosition(const VECTOR2I &aPosition) override
void SetName(const wxString &aName)
void SetText(const wxString &aText) override
SCH_IO_KICAD_LEGACY_LIB_CACHE(const wxString &aLibraryPath)
static void loadDrawEntries(std::unique_ptr< LIB_SYMBOL > &aSymbol, LINE_READER &aReader, int aMajorVersion, int aMinorVersion)
void loadHeader(FILE_LINE_READER &aReader)
static SCH_SHAPE * loadBezier(LINE_READER &aReader)
static void saveArc(SCH_SHAPE *aArc, OUTPUTFORMATTER &aFormatter)
static void saveCircle(SCH_SHAPE *aCircle, OUTPUTFORMATTER &aFormatter)
static SCH_SHAPE * loadArc(LINE_READER &aReader)
static void loadField(std::unique_ptr< LIB_SYMBOL > &aSymbol, LINE_READER &aReader)
static void saveField(const SCH_FIELD *aField, OUTPUTFORMATTER &aFormatter)
static LIB_SYMBOL * LoadPart(LINE_READER &aReader, int aMajorVersion, int aMinorVersion, LIB_SYMBOL_MAP *aMap=nullptr)
static void savePolyLine(SCH_SHAPE *aPolyLine, OUTPUTFORMATTER &aFormatter)
static SCH_SHAPE * loadPolyLine(LINE_READER &aReader)
static void saveBezier(SCH_SHAPE *aBezier, OUTPUTFORMATTER &aFormatter)
static SCH_SHAPE * loadCircle(LINE_READER &aReader)
void Save(const std::optional< bool > &aOpt) override
Save the entire library to file m_libFileName;.
static SCH_SHAPE * loadRect(LINE_READER &aReader)
static void loadAliases(std::unique_ptr< LIB_SYMBOL > &aSymbol, LINE_READER &aReader, LIB_SYMBOL_MAP *aMap=nullptr)
static void loadFootprintFilters(std::unique_ptr< LIB_SYMBOL > &aSymbol, LINE_READER &aReader)
static SCH_TEXT * loadText(LINE_READER &aReader, int aMajorVersion, int aMinorVersion)
void DeleteSymbol(const wxString &aName) override
static void savePin(const SCH_PIN *aPin, OUTPUTFORMATTER &aFormatter)
static SCH_PIN * loadPin(std::unique_ptr< LIB_SYMBOL > &aSymbol, LINE_READER &aReader)
static FILL_T parseFillMode(LINE_READER &aReader, const char *aLine, const char **aOutput)
static void saveRectangle(SCH_SHAPE *aRectangle, OUTPUTFORMATTER &aFormatter)
static void SaveSymbol(LIB_SYMBOL *aSymbol, OUTPUTFORMATTER &aFormatter, LIB_SYMBOL_MAP *aMap=nullptr)
static void saveText(const SCH_TEXT *aText, OUTPUTFORMATTER &aFormatter)
A base cache assistant implementation for the symbol library portion of the SCH_IO API.
wxDateTime GetLibModificationTime()
wxFileName GetRealFile() const
void IncrementModifyHash()
Base class for any item which can be embedded within the SCHEMATIC container class,...
virtual void SetBodyStyle(int aBodyStyle)
virtual void SetUnit(int aUnit)
int GetNumberTextSize() const
const wxString & GetName() const
PIN_ORIENTATION GetOrientation() const
VECTOR2I GetPosition() const override
int GetNameTextSize() const
const wxString & GetNumber() const
GRAPHIC_PINSHAPE GetShape() const
ELECTRICAL_PINTYPE GetType() const
void SetPosition(const VECTOR2I &aPos) override
void SetStroke(const STROKE_PARAMS &aStroke) override
VECTOR2I GetCenter() const
void AddPoint(const VECTOR2I &aPosition)
VECTOR2I GetPosition() const override
virtual size_t GetPointCount() const override
const std::vector< VECTOR2I > & CPoints() const
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
Simple container to manage line stroke parameters.
int GetPinNameOffset() const
virtual bool GetShowPinNames() const
virtual bool GetShowPinNumbers() const
static constexpr EDA_ANGLE ANGLE_VERTICAL
static constexpr EDA_ANGLE ANGLE_HORIZONTAL
#define IS_CHANGED
Item was edited, and modified.
static const std::string LegacySymbolDocumentFileExtension
const wxChar *const traceSchLegacyPlugin
Flag to enable legacy schematic plugin debug output.
std::chrono::steady_clock CLOCK
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
uint32_t timestamp_t
timestamp_t is our type to represent unique IDs for all kinds of elements; historically simply the ti...
This file contains miscellaneous commonly used macros and functions.
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
PIN_ORIENTATION
The symbol library pin object orientations.
int parseInt(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parse an ASCII integer string with possible leading whitespace into an integer and updates the pointe...
bool strCompare(const char *aString, const char *aLine, const char **aOutput)
Compare aString to the string starting at aLine and advances the character point to the end of String...
void parseQuotedString(wxString &aString, LINE_READER &aReader, const char *aCurrentToken, const char **aNextToken, bool aCanBeEmpty)
Parse an quoted ASCII utf8 and updates the pointer at aOutput if it is not NULL.
void parseUnquotedString(wxString &aString, LINE_READER &aReader, const char *aCurrentToken, const char **aNextToken, bool aCanBeEmpty)
Parse an unquoted utf8 string and updates the pointer at aOutput if it is not NULL.
char parseChar(LINE_READER &aReader, const char *aCurrentToken, const char **aNextToken)
Parse a single ASCII character and updates the pointer at aOutput if it is not NULL.
#define SCH_PARSE_ERROR(text, reader, pos)
static bool MapAnglesV6(int *aAngle1, int *aAngle2)
This function based on version 6.0 is required for reading legacy arcs.
#define LIB_VERSION_MINOR
Legacy symbol library minor version.
#define LIBFILE_IDENT
Legacy symbol library (.lib) file header.
#define USE_OLD_DOC_FILE_FORMAT(major, minor)
Library versions 2.4 and lower use the old separate library (.lib) and document (....
#define LIB_VERSION(major, minor)
#define DOCFILE_IDENT
Legacy symbol library document (.dcm) file header.
#define LIB_VERSION_MAJOR
Legacy symbol library major version.
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString UnescapeString(const wxString &aSource)
wxString From_UTF8(const char *cstring)
std::string EscapedUTF8(const wxString &aString)
Return an 8 bit UTF8 string given aString in Unicode form.
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
#define TO_UTF8(wxstring)
Convert a wxString to a UTF8 encoded C string for all wxWidgets build modes.
constexpr int IUToMils(int iu) const
constexpr int MilsToIU(int mils) const
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslateForHI=false)
Return a default symbol field name for field aFieldNdx for all components.
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP
wxString GetCanonicalFieldName(int idx)
@ DATASHEET_FIELD
name of datasheet
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ MANDATORY_FIELDS
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
wxLogTrace helper definitions.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
void NORMALIZE_ANGLE_POS(T &Angle)
double RAD2DECIDEG(double rad)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition of file extensions used in Kicad.