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 )
549 field = aSymbol->GetFieldById(
id );
558 id = aSymbol->GetNextAvailableFieldId();
559 field =
new SCH_FIELD( aSymbol.get(),
id );
560 aSymbol->AddDrawItem( field,
false );
564 while( *line !=
'"' && *line != 0 )
579 if(
text.size() == 1 &&
text[0] ==
'~' )
580 field->
SetText( wxEmptyString );
595 char textOrient =
parseChar( aReader, line, &line );
597 if( textOrient ==
'H' )
599 else if( textOrient ==
'V' )
602 SCH_PARSE_ERROR(
"invalid field text orientation parameter", aReader, line );
604 char textVisible =
parseChar( aReader, line, &line );
606 if( textVisible ==
'V' )
608 else if ( textVisible ==
'I' )
611 SCH_PARSE_ERROR(
"invalid field text visibility parameter", aReader, line );
617 if( *line != 0 && *line !=
'"' )
619 char textHJustify =
parseChar( aReader, line, &line );
621 if( textHJustify ==
'C' )
623 else if( textHJustify ==
'L' )
625 else if( textHJustify ==
'R' )
628 SCH_PARSE_ERROR(
"invalid field text horizontal justification", aReader, line );
634 size_t attrSize = attributes.size();
636 if( !(attrSize == 3 || attrSize == 1 ) )
637 SCH_PARSE_ERROR(
"invalid field text attributes size", aReader, line );
639 switch( (wxChar) attributes[0] )
644 default:
SCH_PARSE_ERROR(
"invalid field text vertical justification", aReader, line );
649 wxChar attr_1 = attributes[1];
650 wxChar attr_2 = attributes[2];
654 else if( attr_1 !=
'N' )
655 SCH_PARSE_ERROR(
"invalid field text italic parameter", aReader, line );
659 else if( attr_2 !=
'N' )
675 field->
SetText( aSymbol->GetName() );
679 wxString fieldName = wxEmptyString;
682 if( fieldName.IsEmpty() )
685 wxString candidateFieldName = fieldName;
689 while( aSymbol->FindField( candidateFieldName ) !=
nullptr )
690 candidateFieldName = wxString::Format(
"%s_%d", fieldName, ++suffix );
692 field->
SetName( candidateFieldName );
702 const char* line = aReader.
Line();
704 wxCHECK_RET(
strCompare(
"DRAW", line, &line ),
"Invalid DRAW section" );
712 aSymbol->GetDrawItems().sort();
719 aSymbol->AddDrawItem(
loadArc( aReader ),
false );
723 aSymbol->AddDrawItem(
loadCircle( aReader ),
false );
727 aSymbol->AddDrawItem(
loadText( aReader, aMajorVersion, aMinorVersion ),
false );
731 aSymbol->AddDrawItem(
loadRect( aReader ),
false );
735 aSymbol->AddDrawItem(
loadPin( aSymbol, aReader ),
false );
743 aSymbol->AddDrawItem(
loadBezier( aReader ),
false );
759 SCH_PARSE_ERROR(
"File ended prematurely loading symbol draw element.", aReader, line );
764 const char** aOutput )
766 switch (
parseChar( aReader, aLine, aOutput ) )
768 case 'F':
return FILL_T::FILLED_SHAPE;
769 case 'f':
return FILL_T::FILLED_WITH_BG_BODYCOLOR;
770 case 'N':
return FILL_T::NO_FILL;
774 SCH_PARSE_ERROR(
"invalid fill type, expected f, F, or N", aReader, aLine );
784 auto DECIDEG2RAD = [](
double deg ) ->
double
786 return deg * M_PI / 1800.0;
793 delta = *aAngle2 - *aAngle1;
801 x = cos( DECIDEG2RAD( *aAngle1 ) );
802 y = -sin( DECIDEG2RAD( *aAngle1 ) );
805 x = cos( DECIDEG2RAD( *aAngle2 ) );
806 y = -sin( DECIDEG2RAD( *aAngle2 ) );
812 if( *aAngle2 < *aAngle1 )
815 if( *aAngle2 - *aAngle1 > 1800 )
817 angle = ( *aAngle1 );
818 *aAngle1 = ( *aAngle2 );
824 if( *aAngle2 < *aAngle1 )
842 const char* line = aReader.
Line();
844 wxCHECK_MSG(
strCompare(
"A", line, &line ),
nullptr,
"Invalid arc definition" );
856 int angle1 =
parseInt( aReader, line, &line );
857 int angle2 =
parseInt( aReader, line, &line );
923 const char* line = aReader.
Line();
925 wxCHECK_MSG(
strCompare(
"C", line, &line ),
nullptr,
"Invalid circle definition" );
954 int aMajorVersion,
int aMinorVersion )
956 const char* line = aReader.
Line();
958 wxCHECK_MSG(
strCompare(
"T", line, &line ),
nullptr,
"Invalid SCH_TEXT definition" );
960 double angleInTenths;
968 angleInTenths =
parseInt( aReader, line, &line );
973 visible = !
parseInt( aReader, line, &line );
974 unit =
parseInt( aReader, line, &line );
975 bodyStyle =
parseInt( aReader, line, &line );
989 str.Replace(
"~",
" " );
995 str.Replace(
"''",
"\"" );
1000 text->SetTextSize( size );
1001 text->SetVisible( visible );
1002 text->SetUnit( unit );
1003 text->SetBodyStyle( bodyStyle );
1012 if(
LIB_VERSION( aMajorVersion, aMinorVersion ) > 0
1017 text->SetItalicFlag(
true );
1018 else if( !
strCompare(
"Normal", line, &line ) )
1019 SCH_PARSE_ERROR(
"invalid text stype, expected 'Normal' or 'Italic'", aReader, line );
1021 if(
parseInt( aReader, line, &line ) > 0 )
1022 text->SetBoldFlag(
true );
1027 switch(
parseChar( aReader, line, &line ) )
1032 default:
SCH_PARSE_ERROR(
"invalid horizontal text justication; expected L, C, or R",
1036 switch(
parseChar( aReader, line, &line ) )
1041 default:
SCH_PARSE_ERROR(
"invalid vertical text justication; expected T, C, or B",
1053 const char* line = aReader.
Line();
1055 wxCHECK_MSG(
strCompare(
"S", line, &line ),
nullptr,
"Invalid rectangle definition" );
1069 rectangle->
SetEnd( end );
1075 LINE_STYLE::SOLID );
1090 const char* line = aReader.
Line();
1092 wxCHECK_MSG(
strCompare(
"X", line, &line ),
nullptr,
"Invalid SCH_PIN definition" );
1099 wxString utf8Line = wxString::FromUTF8( line );
1100 wxStringTokenizer tokens( utf8Line,
" \r\n\t" );
1102 if( tokens.CountTokens() < 11 )
1105 tmp = tokens.GetNextToken();
1107 pos += tmp.size() + 1;
1109 tmp = tokens.GetNextToken();
1111 pos += tmp.size() + 1;
1116 tmp = tokens.GetNextToken();
1118 if( !tmp.ToLong( &num ) )
1124 pos += tmp.size() + 1;
1127 tmp = tokens.GetNextToken();
1129 if( !tmp.ToLong( &num ) )
1135 pos += tmp.size() + 1;
1138 tmp = tokens.GetNextToken();
1140 if( !tmp.ToLong( &num ) )
1146 pos += tmp.size() + 1;
1150 tmp = tokens.GetNextToken();
1152 if( tmp.size() > 1 )
1158 pos += tmp.size() + 1;
1162 switch(
static_cast<char>( tmp[0] ) )
1164 case 'U': orientation = PIN_ORIENTATION::PIN_UP;
break;
1165 case 'D': orientation = PIN_ORIENTATION::PIN_DOWN;
break;
1166 case 'L': orientation = PIN_ORIENTATION::PIN_LEFT;
break;
1168 default: orientation = PIN_ORIENTATION::PIN_RIGHT;
break;
1171 tmp = tokens.GetNextToken();
1173 if( !tmp.ToLong( &num ) )
1179 pos += tmp.size() + 1;
1182 tmp = tokens.GetNextToken();
1184 if( !tmp.ToLong( &num ) )
1190 pos += tmp.size() + 1;
1193 tmp = tokens.GetNextToken();
1195 if( !tmp.ToLong( &num ) )
1201 pos += tmp.size() + 1;
1202 int unit = (int) num;
1204 tmp = tokens.GetNextToken();
1206 if( !tmp.ToLong( &num ) )
1212 pos += tmp.size() + 1;
1215 tmp = tokens.GetNextToken();
1217 if( tmp.size() != 1 )
1223 pos += tmp.size() + 1;
1229 case 'I': pinType = ELECTRICAL_PINTYPE::PT_INPUT;
break;
1230 case 'O': pinType = ELECTRICAL_PINTYPE::PT_OUTPUT;
break;
1231 case 'B': pinType = ELECTRICAL_PINTYPE::PT_BIDI;
break;
1232 case 'T': pinType = ELECTRICAL_PINTYPE::PT_TRISTATE;
break;
1233 case 'P': pinType = ELECTRICAL_PINTYPE::PT_PASSIVE;
break;
1234 case 'U': pinType = ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
break;
1235 case 'W': pinType = ELECTRICAL_PINTYPE::PT_POWER_IN;
break;
1236 case 'w': pinType = ELECTRICAL_PINTYPE::PT_POWER_OUT;
break;
1237 case 'C': pinType = ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
break;
1238 case 'E': pinType = ELECTRICAL_PINTYPE::PT_OPENEMITTER;
break;
1239 case 'N': pinType = ELECTRICAL_PINTYPE::PT_NC;
break;
1258 if( tokens.HasMoreTokens() )
1260 tmp = tokens.GetNextToken();
1266 LOWLEVEL_IN = 1 << 2,
1267 LOWLEVEL_OUT = 1 << 3,
1268 FALLING_EDGE = 1 << 4,
1274 for(
int j = (
int) tmp.size(); j > 0; )
1276 switch( tmp[--j].GetValue() )
1279 case 'N':
pin->SetVisible(
false );
break;
1280 case 'I': flags |=
INVERTED;
break;
1281 case 'C': flags |=
CLOCK;
break;
1282 case 'L': flags |= LOWLEVEL_IN;
break;
1283 case 'V': flags |= LOWLEVEL_OUT;
break;
1284 case 'F': flags |= FALLING_EDGE;
break;
1285 case 'X': flags |=
NONLOGIC;
break;
1295 case 0:
pin->SetShape( GRAPHIC_PINSHAPE::LINE );
break;
1296 case INVERTED:
pin->SetShape( GRAPHIC_PINSHAPE::INVERTED );
break;
1297 case CLOCK:
pin->SetShape( GRAPHIC_PINSHAPE::CLOCK );
break;
1298 case INVERTED |
CLOCK:
pin->SetShape( GRAPHIC_PINSHAPE::INVERTED_CLOCK );
break;
1299 case LOWLEVEL_IN:
pin->SetShape( GRAPHIC_PINSHAPE::INPUT_LOW );
break;
1300 case LOWLEVEL_IN |
CLOCK:
pin->SetShape( GRAPHIC_PINSHAPE::CLOCK_LOW );
break;
1301 case LOWLEVEL_OUT:
pin->SetShape( GRAPHIC_PINSHAPE::OUTPUT_LOW );
break;
1302 case FALLING_EDGE:
pin->SetShape( GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK );
break;
1303 case NONLOGIC:
pin->SetShape( GRAPHIC_PINSHAPE::NONLOGIC );
break;
1305 SCH_PARSE_ERROR(
"pin attributes do not define a valid pin shape", aReader, line );
1315 const char* line = aReader.
Line();
1317 wxCHECK_MSG(
strCompare(
"P", line, &line ),
nullptr,
"Invalid poly definition" );
1321 int points =
parseInt( aReader, line, &line );
1326 LINE_STYLE::SOLID );
1332 for(
int i = 0; i < points; i++ )
1348 const char* line = aReader.
Line();
1350 wxCHECK_MSG(
strCompare(
"B", line, &line ),
nullptr,
"Invalid Bezier definition" );
1352 int points =
parseInt( aReader, line, &line );
1354 wxCHECK_MSG( points == 4, NULL,
"Invalid Bezier curve definition" );
1362 LINE_STYLE::SOLID );
1396 const char* line = aReader.
Line();
1398 wxCHECK_RET(
strCompare(
"$FPLIST", line, &line ),
"Invalid footprint filter list" );
1402 wxArrayString footprintFilters;
1406 if(
strCompare(
"$ENDFPLIST", line, &line ) )
1408 aSymbol->SetFPFilters( footprintFilters );
1415 footprintFilters.Add( footprint );
1419 SCH_PARSE_ERROR(
"File ended prematurely while loading footprint filters.", aReader, line );
1427 bool doSaveDocFile = *aOpt;
1435 auto formatter = std::make_unique<FILE_OUTPUTFORMATTER>( fn.GetFullPath() );
1437 formatter->Print( 0,
"#encoding utf-8\n");
1441 if( !it->second->IsRoot() )
1447 formatter->Print( 0,
"#\n#End Library\n" );
1467 wxCHECK_RET( aSymbol && aSymbol->
IsRoot(),
"Invalid LIB_SYMBOL pointer." );
1471 wxArrayString aliasNames;
1475 for(
auto& entry : *aMap )
1480 aliasNames.Add( symbol->
GetName() );
1490 aFormatter.
Print( 0,
"DEF" );
1495 if( !reference.
GetText().IsEmpty() )
1498 aFormatter.
Print( 0,
" ~" );
1500 aFormatter.
Print( 0,
" %d %d %c %c %d %c %c\n",
1505 aSymbol->
IsPower() ?
'P' :
'N' );
1509 if( dateModified != 0 )
1511 int sec = dateModified & 63;
1512 int min = ( dateModified >> 6 ) & 63;
1513 int hour = ( dateModified >> 12 ) & 31;
1514 int day = ( dateModified >> 17 ) & 31;
1515 int mon = ( dateModified >> 22 ) & 15;
1516 int year = ( dateModified >> 26 ) + 1990;
1518 aFormatter.
Print( 0,
"Ti %d/%d/%d %d:%d:%d\n", year, mon, day, hour, min, sec );
1521 std::vector<SCH_FIELD*> fields;
1540 if( !fields[i]->GetText().IsEmpty() )
1542 fields[i]->SetId( fieldId++ );
1548 if( !aliasNames.IsEmpty() )
1550 aFormatter.
Print( 0,
"ALIAS" );
1552 for(
unsigned i = 0; i < aliasNames.GetCount(); i++ )
1553 aFormatter.
Print( 0,
" %s",
TO_UTF8( aliasNames[i] ) );
1555 aFormatter.
Print( 0,
"\n" );
1561 if( footprints.GetCount() != 0 )
1563 aFormatter.
Print( 0,
"$FPLIST\n" );
1565 for(
unsigned i = 0; i < footprints.GetCount(); i++ )
1566 aFormatter.
Print( 0,
" %s\n",
TO_UTF8( footprints[i] ) );
1568 aFormatter.
Print( 0,
"$ENDFPLIST\n" );
1577 aFormatter.
Print( 0,
"DRAW\n" );
1581 switch( item.Type() )
1597 case SHAPE_T::ARC:
saveArc( &shape, aFormatter );
break;
1598 case SHAPE_T::BEZIER:
saveBezier( &shape, aFormatter );
break;
1599 case SHAPE_T::CIRCLE:
saveCircle( &shape, aFormatter );
break;
1600 case SHAPE_T::POLY:
savePolyLine( &shape, aFormatter );
break;
1601 case SHAPE_T::RECTANGLE:
saveRectangle( &shape, aFormatter );
break;
1613 aFormatter.
Print( 0,
"ENDDRAW\n" );
1616 aFormatter.
Print( 0,
"ENDDEF\n" );
1622 wxCHECK_RET( aArc && aArc->
GetShape() == SHAPE_T::ARC,
"Invalid ARC object." );
1630 aFormatter.
Print( 0,
"A %d %d %d %d %d %d %d %d %c %d %d %d %d\n",
1649 wxCHECK_RET( aBezier && aBezier->
GetShape() == SHAPE_T::BEZIER,
"Invalid BEZIER object." );
1651 aFormatter.
Print( 0,
"B 4 %d %d %d",
1656 aFormatter.
Print( 0,
" %d %d %d %d %d %d %d %d",
1672 wxCHECK_RET( aCircle && aCircle->
GetShape() == SHAPE_T::CIRCLE,
"Invalid CIRCLE object." );
1674 aFormatter.
Print( 0,
"C %d %d %d %d %d %d %c\n",
1688 wxCHECK_RET( aField && aField->
Type() ==
SCH_FIELD_T,
"Invalid SCH_FIELD object." );
1690 int hjustify, vjustify;
1691 int id = aField->
GetId();
1708 aFormatter.
Print( 0,
"F%d %s %d %d %d %c %c %c %c%c%c",
1718 aField->
IsBold() ?
'B' :
'N' );
1730 aFormatter.
Print( 0,
"\n" );
1736 wxCHECK_RET( aPin && aPin->
Type() ==
SCH_PIN_T,
"Invalid SCH_PIN object." );
1743 case ELECTRICAL_PINTYPE::PT_INPUT: Etype =
'I';
break;
1744 case ELECTRICAL_PINTYPE::PT_OUTPUT: Etype =
'O';
break;
1745 case ELECTRICAL_PINTYPE::PT_BIDI: Etype =
'B';
break;
1746 case ELECTRICAL_PINTYPE::PT_TRISTATE: Etype =
'T';
break;
1747 case ELECTRICAL_PINTYPE::PT_PASSIVE: Etype =
'P';
break;
1748 case ELECTRICAL_PINTYPE::PT_UNSPECIFIED: Etype =
'U';
break;
1749 case ELECTRICAL_PINTYPE::PT_POWER_IN: Etype =
'W';
break;
1750 case ELECTRICAL_PINTYPE::PT_POWER_OUT: Etype =
'w';
break;
1751 case ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR: Etype =
'C';
break;
1752 case ELECTRICAL_PINTYPE::PT_OPENEMITTER: Etype =
'E';
break;
1753 case ELECTRICAL_PINTYPE::PT_NC: Etype =
'N';
break;
1756 if( !aPin->
GetName().IsEmpty() )
1759 aFormatter.
Print( 0,
"X ~" );
1761 int pin_orient =
'L';
1765 case PIN_ORIENTATION::PIN_RIGHT: pin_orient =
'R';
break;
1766 case PIN_ORIENTATION::PIN_LEFT: pin_orient =
'L';
break;
1767 case PIN_ORIENTATION::PIN_UP: pin_orient =
'U';
break;
1768 case PIN_ORIENTATION::PIN_DOWN: pin_orient =
'D';
break;
1769 case PIN_ORIENTATION::INHERIT: pin_orient =
'L';
break;
1772 aFormatter.
Print( 0,
" %s %d %d %d %c %d %d %d %d %c",
1785 aFormatter.
Print( 0,
" " );
1788 aFormatter.
Print( 0,
"N" );
1792 case GRAPHIC_PINSHAPE::LINE:
break;
1793 case GRAPHIC_PINSHAPE::INVERTED: aFormatter.
Print( 0,
"I" );
break;
1794 case GRAPHIC_PINSHAPE::CLOCK: aFormatter.
Print( 0,
"C" );
break;
1795 case GRAPHIC_PINSHAPE::INVERTED_CLOCK: aFormatter.
Print( 0,
"IC" );
break;
1796 case GRAPHIC_PINSHAPE::INPUT_LOW: aFormatter.
Print( 0,
"L" );
break;
1797 case GRAPHIC_PINSHAPE::CLOCK_LOW: aFormatter.
Print( 0,
"CL" );
break;
1798 case GRAPHIC_PINSHAPE::OUTPUT_LOW: aFormatter.
Print( 0,
"V" );
break;
1799 case GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK: aFormatter.
Print( 0,
"F" );
break;
1800 case GRAPHIC_PINSHAPE::NONLOGIC: aFormatter.
Print( 0,
"X" );
break;
1801 default: wxFAIL_MSG(
"Invalid pin shape" );
1804 aFormatter.
Print( 0,
"\n" );
1813 wxCHECK_RET( aPolyLine && aPolyLine->
GetShape() == SHAPE_T::POLY,
"Invalid POLY object." );
1815 aFormatter.
Print( 0,
"P %d %d %d %d",
1831 wxCHECK_RET( aRectangle && aRectangle->
GetShape() == SHAPE_T::RECTANGLE,
1832 "Invalid RECT object." );
1834 aFormatter.
Print( 0,
"S %d %d %d %d %d %d %d %c\n",
1848 wxCHECK_RET( aText && aText->
Type() ==
SCH_TEXT_T,
"Invalid SCH_TEXT object." );
1852 if(
text.Contains( wxT(
" " ) ) ||
text.Contains( wxT(
"~" ) ) ||
text.Contains( wxT(
"\"" ) ) )
1855 text.Replace( wxT(
"\"" ), wxT(
"''" ) );
1856 text = wxT(
"\"" ) +
text + wxT(
"\"" );
1859 aFormatter.
Print( 0,
"T %g %d %d %d %d %d %d %s",
1869 aFormatter.
Print( 0,
" %s %d", aText->
IsItalic() ?
"Italic" :
"Normal", aText->
IsBold() );
1871 char hjustify =
'C';
1878 char vjustify =
'C';
1885 aFormatter.
Print( 0,
" %c %c\n", hjustify, vjustify );
1906 wxString description = it->second->GetDescription();
1907 wxString keyWords = it->second->GetKeyWords();
1908 wxString docFileName = it->second->GetDatasheetField().GetText();
1910 if( description.IsEmpty() && keyWords.IsEmpty() && docFileName.IsEmpty() )
1913 formatter.
Print( 0,
"#\n$CMP %s\n",
TO_UTF8( it->second->GetName() ) );
1915 if( !description.IsEmpty() )
1916 formatter.
Print( 0,
"D %s\n",
TO_UTF8( description ) );
1918 if( !keyWords.IsEmpty() )
1921 if( !docFileName.IsEmpty() )
1922 formatter.
Print( 0,
"F %s\n",
TO_UTF8( docFileName ) );
1924 formatter.
Print( 0,
"$ENDCMP\n" );
1927 formatter.
Print( 0,
"#\n#End Doc Library\n" );
1933 LIB_SYMBOL_MAP::iterator it =
m_symbols.find( aSymbolName );
1936 THROW_IO_ERROR( wxString::Format(
_(
"library %s does not contain a symbol named %s" ),
1948 LIB_SYMBOL_MAP::iterator it1 =
m_symbols.begin();
1952 if( it1->second->IsAlias()
1953 && it1->second->GetParent().lock() == rootSymbol->
SharedPtr() )
constexpr EDA_IU_SCALE schIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
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
SHAPE_POLY_SET & GetPolyShape()
void CalcArcAngles(EDA_ANGLE &aStartAngle, EDA_ANGLE &aEndAngle) const
Calc arc start and end angles such that aStartAngle < aEndAngle.
void RebuildBezierToSegmentsPointsList(int aMaxError)
Rebuild the m_bezierPoints vertex list that approximate the Bezier curve by a list of segments.
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)
Set only the italic flag, without changing the font.
virtual void SetVisible(bool aVisible)
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
GR_TEXT_V_ALIGN_T GetVertJustify() const
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
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.
@ DESCRIPTION_FIELD
Field Description of part, i.e. "1/4W 1% Metal Film Resistor".
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)
VECTOR2< int32_t > VECTOR2I
Definition of file extensions used in Kicad.