31#include <fmt/format.h>
35#include <wx/mstream.h>
36#include <wx/tokenzr.h>
72using namespace TSCHEMATIC_T;
77 unsigned aLineCount,
SCH_SHEET* aRootSheet,
79 SCHEMATIC_LEXER( aLineReader ),
80 m_requiredVersion( 0 ),
83 m_appending( aIsAppending ),
84 m_progressReporter( aProgressReporter ),
85 m_lineReader( aLineReader ),
86 m_lastProgressLine( 0 ),
87 m_lineCount( aLineCount ),
88 m_rootSheet( aRootSheet )
95 const unsigned PROGRESS_DELTA = 500;
117 KIID id( FromUTF8() );
134 else if( token == T_no )
137 Expecting(
"yes or no" );
148 bool ret = aDefaultValue;
150 if( PrevTok() == T_LEFT )
155 if(
static_cast<int>( token ) ==
DSN_RIGHT )
156 return aDefaultValue;
160 else if( token == T_no )
163 Expecting(
"yes or no" );
170 return aDefaultValue;
185 bool versionChecked =
false;
196 versionChecked =
true;
199 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
201 if( token != T_LEFT )
227 case T_generator_version:
247 aSymbolLibMap[symbol->
GetName()] = symbol;
252 Expecting(
"symbol, generator, or generator_version" );
266 if( CurTok() == T_LEFT )
270 if( CurTok() == T_symbol )
275 const std::vector<wxString>* embeddedFonts =
282 textItem->ResolveFont( embeddedFonts );
284 RECURSE_MODE::NO_RECURSE );
288 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
289 GetTokenString( CurTok() ) );
300 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
301 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
307 wxString unitDisplayName;
309 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
311 symbol->SetUnitCount( 1 );
315 if( !IsSymbol( token ) )
317 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(),
326 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
333 if(
static_cast<int>(
name.size() ) > bad_pos )
335 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
344 CurLineNumber(), CurOffset() );
349 symbol->SetLibId(
id );
351 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
353 if( token != T_LEFT )
361 symbol->SetGlobalPower();
364 if( token == T_RIGHT )
367 if( token == T_local )
368 symbol->SetLocalPower();
369 else if( token != T_global )
370 Expecting(
"global or local" );
383 case T_exclude_from_sim:
384 symbol->SetExcludedFromSim(
parseBool() );
389 symbol->SetExcludedFromBOM( !
parseBool() );
394 symbol->SetExcludedFromBoard( !
parseBool() );
398 case T_duplicate_pin_numbers_are_jumpers:
399 symbol->SetDuplicatePinNumbersAreJumpers(
parseBool() );
403 case T_jumper_pin_groups:
406 std::vector<std::set<wxString>>& groups = symbol->JumperPinGroups();
407 std::set<wxString>* currentGroup =
nullptr;
409 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
411 switch(
static_cast<int>( token ) )
414 currentGroup = &groups.emplace_back();
418 currentGroup->insert( FromUTF8() );
422 currentGroup =
nullptr;
426 Expecting(
"list of pin names" );
441 if( !IsSymbol( token ) )
444 CurLineNumber(), CurOffset() );
452 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
454 auto it = aSymbolLibMap.find(
name );
456 if( it == aSymbolLibMap.end() )
458 error.Printf(
_(
"No parent for extended symbol %s" ),
name.c_str() );
459 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
462 symbol->SetParent( it->second );
471 if( !IsSymbol( token ) )
474 CurLineNumber(), CurOffset() );
482 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
486 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
487 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
492 wxStringTokenizer tokenizer(
name,
"_" );
494 if( tokenizer.CountTokens() != 2 )
496 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
497 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
500 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
502 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
503 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
506 m_unit =
static_cast<int>( tmp );
508 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
510 error.Printf(
_(
"Invalid symbol convert number %s" ),
name.c_str() );
511 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
517 symbol->SetHasAlternateBodyStyle(
true,
false );
519 if(
m_unit > symbol->GetUnitCount() )
520 symbol->SetUnitCount(
m_unit,
false );
522 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
524 if( token != T_LEFT )
534 if( IsSymbol( token ) )
536 unitDisplayName = FromUTF8();
537 symbol->SetUnitDisplayName(
m_unit, unitDisplayName );
553 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
556 symbol->AddDrawItem( item,
false );
560 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
579 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
582 symbol->AddDrawItem( item,
false );
585 case T_embedded_fonts:
587 symbol->SetAreFontsEmbedded(
parseBool() );
592 case T_embedded_files:
595 embeddedFilesParser.SyncLineReaderWith( *
this );
599 embeddedFilesParser.
ParseEmbedded( symbol->GetEmbeddedFiles() );
603 wxLogError( e.
What() );
606 SyncLineReaderWith( embeddedFilesParser );
611 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
612 "rectangle, or text" );
616 symbol->GetDrawItems().sort();
619 const std::vector<wxString>* embeddedFonts =
620 symbol->GetEmbeddedFiles()->UpdateFontFiles();
622 symbol->RunOnChildren(
626 textItem->ResolveFont( embeddedFonts );
628 RECURSE_MODE::NO_RECURSE );
630 return symbol.release();
646 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
660 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
662 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
670 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
672 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
679 strokeParser.SyncLineReaderWith( *
this );
682 SyncLineReaderWith( strokeParser );
688 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
691 aFill.
m_Color = COLOR4D::UNSPECIFIED;
695 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
697 if( token != T_LEFT )
710 case T_none: aFill.
m_FillType = FILL_T::NO_FILL;
break;
711 case T_outline: aFill.
m_FillType = FILL_T::FILLED_SHAPE;
break;
712 case T_background: aFill.
m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR;
break;
713 case T_color: aFill.
m_FillType = FILL_T::FILLED_WITH_COLOR;
break;
714 case T_hatch: aFill.
m_FillType = FILL_T::HATCH;
break;
715 case T_reverse_hatch: aFill.
m_FillType = FILL_T::REVERSE_HATCH;
break;
716 case T_cross_hatch: aFill.
m_FillType = FILL_T::CROSS_HATCH;
break;
717 default: Expecting(
"none, outline, hatch, reverse_hatch, "
718 "cross_hatch, color or background" );
739 Expecting(
"type or color" );
746 bool aEnforceMinTextSize )
748 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
749 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
766 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
768 if( token == T_LEFT )
774 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
776 if( token == T_LEFT )
827 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
834 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
843 case T_mirror:
break;
844 default: Expecting(
"left, right, top, bottom, or mirror" );
853 wxString hyperlink = FromUTF8();
858 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
877 Expecting(
"font, justify, hide or href" );
885 wxCHECK_RET( CurTok() == aHeaderType,
886 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
892 if( tok == T_version )
906 wxCHECK_RET( CurTok() == T_pin_names,
907 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
917 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
920 if( token == T_hide )
922 aSymbol->SetShowPinNames(
false );
926 if( token != T_LEFT )
941 aSymbol->SetShowPinNames( !
parseBool() );
946 Expecting(
"offset or hide" );
954 wxCHECK_RET( CurTok() == T_pin_numbers,
955 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_number token." );
964 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
967 if( token == T_hide )
969 aSymbol->SetShowPinNumbers(
false );
973 if( token != T_LEFT )
983 aSymbol->SetShowPinNumbers( !
parseBool() );
997 wxCHECK_MSG( CurTok() == T_property,
nullptr,
998 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
999 wxCHECK( aSymbol,
nullptr );
1001 FIELD_T fieldId = FIELD_T::USER;
1004 bool isPrivate =
false;
1005 bool isVisible =
true;
1007 T token = NextTok();
1009 if( token == T_private )
1015 if( !IsSymbol( token ) )
1017 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
1023 if(
name.IsEmpty() )
1025 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
1039 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(), fieldId,
name );
1040 field->SetPrivate( isPrivate );
1041 field->SetVisible( isVisible );
1045 if( !IsSymbol( token ) )
1047 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1054 value = wxEmptyString;
1058 field->SetText( value );
1060 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1062 if( token != T_LEFT )
1063 Expecting( T_LEFT );
1075 field->SetPosition(
parseXY(
true ) );
1087 field->GetId() == FIELD_T::VALUE );
1093 field->SetNameShown( show );
1097 case T_do_not_autoplace:
1100 field->SetCanAutoplace( !doNotAutoplace );
1105 Expecting(
"id, at, hide, show_name, do_not_autoplace, or effects" );
1111 if( field->IsMandatory() )
1113 existingField = aSymbol->GetField( field->GetId() );
1115 *existingField = *field;
1116 return existingField;
1118 else if(
name ==
"ki_keywords" )
1121 aSymbol->SetKeyWords( value );
1125 else if(
name ==
"ki_description" )
1127 aSymbol->SetDescription( value );
1130 else if(
name ==
"ki_fp_filters" )
1133 wxArrayString filters;
1134 wxStringTokenizer tokenizer( value );
1136 while( tokenizer.HasMoreTokens() )
1138 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1139 filters.Add( curr_token );
1142 aSymbol->SetFPFilters( filters );
1145 else if(
name ==
"ki_locked" )
1149 aSymbol->LockUnits(
true );
1155 existingField = aSymbol->GetField( field->GetCanonicalName() );
1166 for(
int ii = 1; ii < 10 && existingField; ii++ )
1168 wxString newname = base_name;
1169 newname <<
'_' << ii;
1171 existingField = aSymbol->GetField( newname );
1173 if( !existingField )
1174 field->SetName( newname );
1178 if( !existingField )
1180 aSymbol->AddDrawItem( field.get(),
false );
1181 return field.release();
1194 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1195 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1201 bool hasMidPoint =
false;
1209 bool hasAngles =
false;
1211 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC,
LAYER_DEVICE );
1218 if( token == T_private )
1220 arc->SetPrivate(
true );
1224 for( ; token != T_RIGHT; token = NextTok() )
1226 if( token != T_LEFT )
1227 Expecting( T_LEFT );
1250 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1252 if( token != T_LEFT )
1253 Expecting( T_LEFT );
1281 Expecting(
"at, length, or angles" );
1289 arc->SetStroke( stroke );
1295 arc->SetFillColor( fill.
m_Color );
1299 Expecting(
"start, mid, end, radius, stroke, or fill" );
1305 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1316 EDA_ANGLE arc_start, arc_end, arc_angle;
1317 arc->CalcArcAngles( arc_start, arc_end );
1318 arc_angle = arc_end - arc_start;
1323 arc->SetStart( endPoint );
1324 arc->SetEnd( startPoint );
1327 arc->SetCenter( new_center );
1333 arc->SetCenter( new_center );
1337 else if( hasAngles )
1339 arc->SetCenter(
center );
1345 arc->SetStart( endPoint );
1346 arc->SetEnd( startPoint );
1350 EDA_ANGLE arc_start, arc_end, arc_angle;
1351 arc->CalcArcAngles( arc_start, arc_end );
1352 arc_angle = arc_end - arc_start;
1358 arc->SetStart( startPoint );
1359 arc->SetEnd( endPoint );
1367 arc->SetStart( startPoint );
1368 arc->SetEnd( endPoint );
1372 arc->SetCenter( new_center );
1378 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1381 return arc.release();
1387 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1388 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1394 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER,
LAYER_DEVICE );
1396 bezier->SetUnit(
m_unit );
1401 if( token == T_private )
1403 bezier->SetPrivate(
true );
1407 for( ; token != T_RIGHT; token = NextTok() )
1409 if( token != T_LEFT )
1410 Expecting( T_LEFT );
1420 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1422 if( token != T_LEFT )
1423 Expecting( T_LEFT );
1432 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1433 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1434 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1435 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1436 default: Unexpected(
"control point" );
break;
1446 bezier->SetStroke( stroke );
1452 bezier->SetFillColor( fill.
m_Color );
1456 Expecting(
"pts, stroke, or fill" );
1460 bezier->RebuildBezierToSegmentsPointsList( bezier->GetPenWidth() / 2 );
1462 return bezier.release();
1468 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1469 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1477 std::unique_ptr<SCH_SHAPE>
circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE,
LAYER_DEVICE );
1484 if( token == T_private )
1486 circle->SetPrivate(
true );
1490 for( ; token != T_RIGHT; token = NextTok() )
1492 if( token != T_LEFT )
1493 Expecting( T_LEFT );
1511 circle->SetStroke( stroke );
1521 Expecting(
"center, radius, stroke, or fill" );
1539 case T_input:
return ELECTRICAL_PINTYPE::PT_INPUT;
1540 case T_output:
return ELECTRICAL_PINTYPE::PT_OUTPUT;
1541 case T_bidirectional:
return ELECTRICAL_PINTYPE::PT_BIDI;
1542 case T_tri_state:
return ELECTRICAL_PINTYPE::PT_TRISTATE;
1543 case T_passive:
return ELECTRICAL_PINTYPE::PT_PASSIVE;
1544 case T_unspecified:
return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1545 case T_power_in:
return ELECTRICAL_PINTYPE::PT_POWER_IN;
1546 case T_power_out:
return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1547 case T_open_collector:
return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1548 case T_open_emitter:
return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1550 case T_no_connect:
return ELECTRICAL_PINTYPE::PT_NC;
1551 case T_free:
return ELECTRICAL_PINTYPE::PT_NIC;
1554 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1555 "power_in, power_out, open_collector, open_emitter, free or "
1557 return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1566 case T_line:
return GRAPHIC_PINSHAPE::LINE;
1567 case T_inverted:
return GRAPHIC_PINSHAPE::INVERTED;
1568 case T_clock:
return GRAPHIC_PINSHAPE::CLOCK;
1569 case T_inverted_clock:
return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1570 case T_input_low:
return GRAPHIC_PINSHAPE::INPUT_LOW;
1571 case T_clock_low:
return GRAPHIC_PINSHAPE::CLOCK_LOW;
1572 case T_output_low:
return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1573 case T_edge_clock_high:
return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1574 case T_non_logic:
return GRAPHIC_PINSHAPE::NONLOGIC;
1577 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1578 "output_low, edge_clock_high, non_logic" );
1579 return GRAPHIC_PINSHAPE::LINE;
1583 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1584 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1589 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1596 pin->SetType( parseType( token ) );
1600 pin->SetShape( parseShape( token ) );
1602 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1605 if( token == T_hide )
1607 pin->SetVisible(
false );
1611 if( token != T_LEFT )
1612 Expecting( T_LEFT );
1621 switch(
parseInt(
"pin orientation" ) )
1623 case 0:
pin->SetOrientation( PIN_ORIENTATION::PIN_RIGHT );
break;
1624 case 90:
pin->SetOrientation( PIN_ORIENTATION::PIN_UP );
break;
1625 case 180:
pin->SetOrientation( PIN_ORIENTATION::PIN_LEFT );
break;
1626 case 270:
pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
break;
1627 default: Expecting(
"0, 90, 180, or 270" );
1646 if( !IsSymbol( token ) )
1653 pin->SetName( wxEmptyString );
1657 pin->SetName( FromUTF8() );
1661 if( token != T_RIGHT )
1665 if( token == T_effects )
1672 pin->SetNameTextSize(
text.GetTextHeight() );
1677 Expecting(
"effects" );
1686 if( !IsSymbol( token ) )
1689 CurLineNumber(), CurOffset() );
1693 pin->SetNumber( wxEmptyString );
1697 pin->SetNumber( FromUTF8() );
1701 if( token != T_RIGHT )
1705 if( token == T_effects )
1712 pin->SetNumberTextSize(
text.GetTextHeight() );
1717 Expecting(
"effects" );
1729 if( !IsSymbol( token ) )
1732 CurLineNumber(), CurOffset() );
1738 alt.
m_Type = parseType( token );
1741 alt.
m_Shape = parseShape( token );
1743 pin->GetAlternates()[ alt.
m_Name ] = alt;
1750 Expecting(
"at, name, number, hide, length, or alternate" );
1754 return pin.release();
1760 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1761 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1766 std::unique_ptr<SCH_SHAPE> poly = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_DEVICE );
1773 if( token == T_private )
1775 poly->SetPrivate(
true );
1779 for( ; token != T_RIGHT; token = NextTok() )
1781 if( token != T_LEFT )
1782 Expecting( T_LEFT );
1789 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1791 if( token != T_LEFT )
1792 Expecting( T_LEFT );
1799 poly->AddPoint(
parseXY(
true ) );
1808 poly->SetStroke( stroke );
1814 poly->SetFillColor( fill.
m_Color );
1818 Expecting(
"pts, stroke, or fill" );
1822 return poly.release();
1828 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1829 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1834 auto rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE,
LAYER_DEVICE );
1836 rectangle->SetUnit(
m_unit );
1841 if( token == T_private )
1843 rectangle->SetPrivate(
true );
1847 for( ; token != T_RIGHT; token = NextTok() )
1849 if( token != T_LEFT )
1850 Expecting( T_LEFT );
1857 rectangle->SetPosition(
parseXY(
true ) );
1862 rectangle->SetEnd(
parseXY(
true ) );
1868 rectangle->SetStroke( stroke );
1874 rectangle->SetFillColor( fill.
m_Color );
1878 Expecting(
"start, end, stroke, or fill" );
1882 return rectangle.release();
1888 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1889 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1892 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1899 if( token == T_private )
1901 text->SetPrivate(
true );
1905 if( !IsSymbol( token ) )
1907 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1911 text->SetText( FromUTF8() );
1913 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1915 if( token != T_LEFT )
1916 Expecting( T_LEFT );
1934 Expecting(
"at or effects" );
1939 if( !
text->IsVisible() )
1942 return text.release();
1948 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
1949 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
1961 bool foundEnd =
false;
1962 bool foundSize =
false;
1963 bool foundMargins =
false;
1965 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
1967 textBox->SetUnit(
m_unit );
1971 if( token == T_private )
1973 textBox->SetPrivate(
true );
1977 if( !IsSymbol( token ) )
1979 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1983 textBox->SetText( FromUTF8() );
1985 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1987 if( token != T_LEFT )
1988 Expecting( T_LEFT );
2019 textBox->SetStroke( stroke );
2025 textBox->SetFillColor( fill.
m_Color );
2030 textBox->SetMarginLeft(
left );
2031 textBox->SetMarginTop( top );
2032 textBox->SetMarginRight(
right );
2033 textBox->SetMarginBottom( bottom );
2034 foundMargins =
true;
2043 Expecting(
"at, size, stroke, fill or effects" );
2047 textBox->SetPosition( pos );
2050 textBox->SetEnd(
end );
2051 else if( foundSize )
2052 textBox->SetEnd( pos + size );
2054 Expecting(
"size" );
2058 int margin = textBox->GetLegacyTextMargin();
2059 textBox->SetMarginLeft( margin );
2060 textBox->SetMarginTop( margin );
2061 textBox->SetMarginRight( margin );
2062 textBox->SetMarginBottom( margin );
2065 return textBox.release();
2071 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
2072 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
2078 wxString pageType = FromUTF8();
2080 if( !aPageInfo.
SetType( pageType ) )
2082 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
2109 if( token == T_portrait )
2114 else if( token != T_RIGHT )
2116 Expecting(
"portrait" );
2123 wxCHECK_RET( CurTok() == T_title_block,
2124 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
2128 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2130 if( token != T_LEFT )
2131 Expecting( T_LEFT );
2139 aTitleBlock.
SetTitle( FromUTF8() );
2144 aTitleBlock.
SetDate( FromUTF8() );
2159 int commentNumber =
parseInt(
"comment" );
2161 switch( commentNumber )
2210 CurLine(), CurLineNumber(), CurOffset() );
2217 Expecting(
"title, date, rev, company, or comment" );
2227 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2228 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2230 bool is_private =
false;
2232 T token = NextTok();
2234 if( token == T_private )
2240 if( !IsSymbol( token ) )
2242 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2246 wxString
name = FromUTF8();
2248 if(
name.IsEmpty() )
2250 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2256 if( !IsSymbol( token ) )
2258 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2266 value = wxEmptyString;
2270 FIELD_T fieldId = FIELD_T::USER;
2296 if(
name.CmpNoCase( wxT(
"Sheet name" ) ) == 0 )
2297 fieldId = FIELD_T::SHEET_NAME;
2298 else if(
name.CmpNoCase( wxT(
"Sheet file" ) ) == 0 )
2299 fieldId = FIELD_T::SHEET_FILENAME;
2313 if(
name.CmpNoCase( wxT(
"Intersheet References" ) ) == 0 )
2314 fieldId = FIELD_T::INTERSHEET_REFS;
2317 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>(
VECTOR2I( -1, -1 ), fieldId,
2319 field->SetText( value );
2320 field->SetVisible(
true );
2322 if( fieldId == FIELD_T::USER )
2323 field->SetPrivate( is_private );
2325 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2327 if( token != T_LEFT )
2328 Expecting( T_LEFT );
2340 field->SetPosition(
parseXY() );
2352 field->GetId() == FIELD_T::VALUE );
2358 field->SetNameShown( show );
2362 case T_do_not_autoplace:
2365 field->SetCanAutoplace( !doNotAutoplace );
2370 Expecting(
"id, at, hide, show_name, do_not_autoplace or effects" );
2374 return field.release();
2380 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2381 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2382 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2384 T token = NextTok();
2386 if( !IsSymbol( token ) )
2388 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2392 wxString
name = FromUTF8();
2394 if(
name.IsEmpty() )
2396 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2400 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2406 case T_input: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
2407 case T_output: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
2408 case T_bidirectional: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
2409 case T_tri_state: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
2410 case T_passive: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
2412 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2415 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2417 if( token != T_LEFT )
2418 Expecting( T_LEFT );
2426 sheetPin->SetPosition(
parseXY() );
2428 double angle =
parseDouble(
"sheet pin angle (side)" );
2431 sheetPin->SetSide( SHEET_SIDE::RIGHT );
2432 else if( angle == 90.0 )
2433 sheetPin->SetSide( SHEET_SIDE::TOP );
2434 else if( angle == 180.0 )
2435 sheetPin->SetSide( SHEET_SIDE::LEFT );
2436 else if( angle == 270.0 )
2437 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
2439 Expecting(
"0, 90, 180, or 270" );
2456 Expecting(
"at, uuid or effects" );
2460 return sheetPin.release();
2466 wxCHECK_RET( CurTok() == T_sheet_instances,
2467 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2468 wxCHECK( aScreen, );
2472 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2474 if( token != T_LEFT )
2475 Expecting( T_LEFT );
2493 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2495 if( token != T_LEFT )
2496 Expecting( T_LEFT );
2500 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2503 size_t numReplacements = 0;
2521 for(
const wxString& ch : whitespaces )
2522 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2527 if( numReplacements > 0 )
2534 Expecting(
"path or page" );
2539 && ( instance.
m_Path.empty() ) )
2555 Expecting(
"path" );
2563 wxCHECK_RET( CurTok() == T_symbol_instances,
2564 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2565 wxCHECK( aScreen, );
2570 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2572 if( token != T_LEFT )
2573 Expecting( T_LEFT );
2590 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2592 if( token != T_LEFT )
2593 Expecting( T_LEFT );
2614 instance.
m_Value = wxEmptyString;
2616 instance.
m_Value = FromUTF8();
2633 Expecting(
"path, unit, value or footprint" );
2642 Expecting(
"path" );
2651 wxCHECK( aSheet !=
nullptr, );
2655 wxCHECK( screen !=
nullptr, );
2657 if( aIsCopyableOnly )
2660 bool fileHasUuid =
false;
2674 if( !aIsCopyableOnly )
2679 if( CurTok() != T_kicad_sch )
2680 Expecting(
"kicad_sch" );
2696 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2698 if( aIsCopyableOnly && token == T_EOF )
2701 if( token != T_LEFT )
2702 Expecting( T_LEFT );
2732 case T_generator_version:
2758 if( aIsCopyableOnly )
2759 Unexpected( T_paper );
2769 if( aIsCopyableOnly )
2770 Unexpected( T_page );
2774 NeedSYMBOLorNUMBER();
2775 NeedSYMBOLorNUMBER();
2782 if( aIsCopyableOnly )
2783 Unexpected( T_title_block );
2797 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2799 if( token != T_LEFT )
2800 Expecting( T_LEFT );
2812 Expecting(
"symbol" );
2913 case T_netclass_flag:
2918 case T_global_label:
2919 case T_hierarchical_label:
2920 case T_directive_label:
2932 case T_sheet_instances:
2936 case T_symbol_instances:
2941 if( aIsCopyableOnly )
2942 Unexpected( T_bus_alias );
2947 case T_embedded_fonts:
2953 CurLineNumber(), CurOffset() );
2960 case T_embedded_files:
2966 CurLineNumber(), CurOffset() );
2969 embeddedFilesParser.SyncLineReaderWith( *
this );
2977 wxLogError( e.
What() );
2980 SyncLineReaderWith( embeddedFilesParser );
2986 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
2987 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
2988 "sheet, symbol, symbol_instances, text, title_block" );
3007 CurLineNumber(), CurOffset() );
3011 std::vector<std::string> fontNames;
3012 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
3022 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
3023 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
3028 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
3030 std::set<int> fieldIDsRead;
3035 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3037 if( token != T_LEFT )
3038 Expecting( T_LEFT );
3050 if( !IsSymbol( token ) )
3053 CurLineNumber(), CurOffset() );
3056 libName = FromUTF8();
3060 libName.Replace(
"{slash}",
"/" );
3070 if( !IsSymbol( token ) && token != T_NUMBER )
3071 Expecting(
"symbol|number" );
3074 wxString
name = FromUTF8();
3078 name.Replace(
"{slash}",
"/" );
3084 if(
static_cast<int>(
name.size() ) > bad_pos )
3086 wxString msg = wxString::Format(
3087 _(
"Symbol %s contains invalid character '%c'" ),
name,
3094 CurLineNumber(), CurOffset() );
3097 symbol->SetLibId( libId );
3103 symbol->SetPosition(
parseXY() );
3105 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3108 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3109 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3110 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3111 default: Expecting(
"0, 90, 180, or 270" );
3114 symbol->SetTransform( transform );
3123 else if( token == T_y )
3126 Expecting(
"x or y" );
3132 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3139 symbol->SetBodyStyleUnconditional(
parseInt(
"symbol body style" ) );
3143 case T_exclude_from_sim:
3144 symbol->SetExcludedFromSim(
parseBool() );
3149 symbol->SetExcludedFromBOM( !
parseBool() );
3154 symbol->SetExcludedFromBoard( !
parseBool() );
3163 case T_fields_autoplaced:
3175 case T_default_instance:
3179 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3181 if( token != T_LEFT )
3182 Expecting( T_LEFT );
3203 symbol->SetValueFieldText( wxEmptyString );
3205 symbol->SetValueFieldText( FromUTF8() );
3214 symbol->SetFootprintFieldText( wxEmptyString );
3216 symbol->SetFootprintFieldText( FromUTF8() );
3222 Expecting(
"reference, unit, value or footprint" );
3231 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3233 if( token != T_LEFT )
3234 Expecting( T_LEFT );
3238 if( token != T_project )
3239 Expecting(
"project" );
3243 wxString projectName = FromUTF8();
3245 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3247 if( token != T_LEFT )
3248 Expecting( T_LEFT );
3252 if( token != T_path )
3253 Expecting(
"path" );
3262 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3264 if( token != T_LEFT )
3265 Expecting( T_LEFT );
3286 symbol->SetValueFieldText( wxEmptyString );
3288 symbol->SetValueFieldText( FromUTF8() );
3297 symbol->SetFootprintFieldText( wxEmptyString );
3299 symbol->SetFootprintFieldText( FromUTF8() );
3305 Expecting(
"reference, unit, value or footprint" );
3308 symbol->AddHierarchicalReference( instance );
3325 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3332 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3339 existing = symbol->GetField( field->
GetId() );
3341 existing = symbol->GetField( field->
GetName() );
3346 symbol->AddField( *field );
3348 if( field->
GetId() == FIELD_T::REFERENCE )
3349 symbol->UpdatePrefix();
3362 number = FromUTF8();
3364 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3366 if( token != T_LEFT )
3367 Expecting( T_LEFT );
3391 Expecting(
"alternate or uuid" );
3395 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3401 Expecting(
"lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
3402 "default_instance, property, pin, or instances" );
3406 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3407 symbol->SetSchSymbolLibraryName( libName );
3410 symbol->ClearFlags();
3412 return symbol.release();
3418 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3419 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3422 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3425 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3427 if( token != T_LEFT )
3428 Expecting( T_LEFT );
3435 bitmap->SetPosition(
parseXY() );
3461 data.reserve( 1 << 17 );
3463 while( token != T_RIGHT )
3465 if( !IsSymbol( token ) )
3466 Expecting(
"base64 image data" );
3472 wxMemoryBuffer buffer = wxBase64Decode( data );
3481 Expecting(
"at, scale, uuid or data" );
3494 return bitmap.release();
3500 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3501 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3507 std::vector<SCH_FIELD> fields;
3508 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3509 std::set<int> fieldIDsRead;
3514 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3516 if( token != T_LEFT )
3517 Expecting( T_LEFT );
3524 sheet->SetPosition(
parseXY() );
3533 sheet->SetSize( size );
3538 case T_exclude_from_sim:
3539 sheet->SetExcludedFromSim(
parseBool() );
3544 sheet->SetExcludedFromBOM( !
parseBool() );
3549 sheet->SetExcludedFromBoard( !
parseBool() );
3558 case T_fields_autoplaced:
3566 sheet->SetBorderWidth( stroke.
GetWidth() );
3567 sheet->SetBorderColor( stroke.
GetColor() );
3572 sheet->SetBackgroundColor( fill.
m_Color );
3589 if( fields.empty() )
3590 field->
setId( FIELD_T::SHEET_NAME );
3592 field->
setId( FIELD_T::SHEET_FILENAME );
3595 fields.emplace_back( *field );
3606 std::vector<SCH_SHEET_INSTANCE> instances;
3608 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3610 if( token != T_LEFT )
3611 Expecting( T_LEFT );
3615 if( token != T_project )
3616 Expecting(
"project" );
3620 wxString projectName = FromUTF8();
3622 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3624 if( token != T_LEFT )
3625 Expecting( T_LEFT );
3629 if( token != T_path )
3630 Expecting(
"path" );
3639 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3641 if( token != T_LEFT )
3642 Expecting( T_LEFT );
3662 static std::vector<wxString> whitespaces =
3668 for( wxString ch : whitespaces )
3677 Expecting(
"page" );
3681 instances.emplace_back( instance );
3685 sheet->setInstances( instances );
3690 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3694 sheet->SetFields( fields );
3696 return sheet.release();
3702 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3703 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3706 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3708 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3710 if( token != T_LEFT )
3711 Expecting( T_LEFT );
3718 junction->SetPosition(
parseXY() );
3736 junction->SetColor(
color );
3748 Expecting(
"at, diameter, color or uuid" );
3752 return junction.release();
3758 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3759 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3762 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3764 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3766 if( token != T_LEFT )
3767 Expecting( T_LEFT );
3774 no_connect->SetPosition(
parseXY() );
3785 Expecting(
"at or uuid" );
3789 return no_connect.release();
3795 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3796 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3800 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3802 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3804 if( token != T_LEFT )
3805 Expecting( T_LEFT );
3812 busEntry->SetPosition(
parseXY() );
3822 busEntry->SetSize( size );
3829 busEntry->SetStroke( stroke );
3839 Expecting(
"at, size, uuid or stroke" );
3843 return busEntry.release();
3863 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_NOTES );
3865 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3867 if( token != T_LEFT )
3868 Expecting( T_LEFT );
3875 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3877 if( token != T_LEFT )
3878 Expecting( T_LEFT );
3885 polyline->AddPoint(
parseXY() );
3898 polyline->SetStroke( stroke );
3904 polyline->SetFillColor( fill.
m_Color );
3915 Expecting(
"pts, uuid, stroke, or fill" );
3919 return polyline.release();
3938 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3941 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3943 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3945 if( token != T_LEFT )
3946 Expecting( T_LEFT );
3959 line->SetStartPoint(
parseXY() );
3967 line->SetEndPoint(
parseXY() );
3974 line->SetStroke( stroke );
3984 Expecting(
"at, uuid or stroke" );
3988 return line.release();
3994 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
3995 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
4003 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
4005 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4007 if( token != T_LEFT )
4008 Expecting( T_LEFT );
4031 arc->SetStroke( stroke );
4037 arc->SetFillColor( fill.
m_Color );
4043 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
4048 Expecting(
"start, mid, end, stroke, fill or uuid" );
4052 arc->SetArcGeometry( startPoint, midPoint, endPoint );
4054 return arc.release();
4060 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
4061 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4068 std::unique_ptr<SCH_SHAPE>
circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
4070 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4072 if( token != T_LEFT )
4073 Expecting( T_LEFT );
4091 circle->SetStroke( stroke );
4108 Expecting(
"center, radius, stroke, fill or uuid" );
4121 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4122 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4127 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
4129 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4131 if( token != T_LEFT )
4132 Expecting( T_LEFT );
4139 rectangle->SetPosition(
parseXY() );
4144 rectangle->SetEnd(
parseXY() );
4150 rectangle->SetStroke( stroke );
4156 rectangle->SetFillColor( fill.
m_Color );
4162 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4167 Expecting(
"start, end, stroke, fill or uuid" );
4171 return rectangle.release();
4177 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4178 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4183 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4185 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4187 if( token != T_LEFT )
4188 Expecting( T_LEFT );
4202 ruleArea->SetPolyShape( sch_rule_poly );
4204 ruleArea->SetStroke( poly->GetStroke() );
4205 ruleArea->SetFillMode( poly->GetFillMode() );
4206 ruleArea->SetFillColor( poly->GetFillColor() );
4210 Expecting(
"polyline" );
4214 return ruleArea.release();
4220 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4221 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4226 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
4228 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4230 if( token != T_LEFT )
4231 Expecting( T_LEFT );
4241 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4243 if( token != T_LEFT )
4244 Expecting( T_LEFT );
4253 case 0: bezier->SetStart(
parseXY() );
break;
4254 case 1: bezier->SetBezierC1(
parseXY() );
break;
4255 case 2: bezier->SetBezierC2(
parseXY() );
break;
4256 case 3: bezier->SetEnd(
parseXY() );
break;
4257 default: Unexpected(
"control point" );
break;
4267 bezier->SetStroke( stroke );
4273 bezier->SetFillColor( fill.
m_Color );
4279 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4284 Expecting(
"pts, stroke, fill or uuid" );
4288 bezier->RebuildBezierToSegmentsPointsList( bezier->GetPenWidth() / 2 );
4290 return bezier.release();
4297 std::unique_ptr<SCH_TEXT>
text;
4301 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4302 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4303 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4304 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4305 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4306 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4308 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4316 text->SetText( FromUTF8() );
4318 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4320 if( token != T_LEFT )
4321 Expecting( T_LEFT );
4327 case T_exclude_from_sim:
4338 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4354 Unexpected( T_shape );
4362 case T_input: label->
SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
4363 case T_output: label->
SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
4364 case T_bidirectional: label->
SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
4365 case T_tri_state: label->
SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
4366 case T_passive: label->
SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
4367 case T_dot: label->
SetShape( LABEL_FLAG_SHAPE::F_DOT );
break;
4368 case T_round: label->
SetShape( LABEL_FLAG_SHAPE::F_ROUND );
break;
4369 case T_diamond: label->
SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
break;
4370 case T_rectangle: label->
SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
break;
4372 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4383 Unexpected( T_length );
4392 case T_fields_autoplaced:
4402 text->SetVisible(
true );
4427 Unexpected( T_property );
4447 Expecting(
"at, shape, iref, uuid or effects" );
4453 if( label && label->
GetFields().empty() )
4456 return text.release();
4462 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4463 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4465 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4469 return textBox.release();
4475 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4476 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4478 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4482 return cell.release();
4498 bool foundEnd =
false;
4499 bool foundSize =
false;
4500 bool foundMargins =
false;
4504 aTextBox->
SetText( FromUTF8() );
4506 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4508 if( token != T_LEFT )
4509 Expecting( T_LEFT );
4515 case T_exclude_from_sim:
4546 cell->SetColSpan(
parseInt(
"column span" ) );
4547 cell->SetRowSpan(
parseInt(
"row span" ) );
4551 Expecting(
"at, size, stroke, fill, effects or uuid" );
4575 foundMargins =
true;
4591 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4593 Expecting(
"at, size, stroke, fill, effects or uuid" );
4601 else if( foundSize )
4602 aTextBox->
SetEnd( pos + size );
4604 Expecting(
"size" );
4619 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4620 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4624 STROKE_PARAMS borderStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4625 STROKE_PARAMS separatorsStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4626 std::unique_ptr<SCH_TABLE>
table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4628 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4630 if( token != T_LEFT )
4631 Expecting( T_LEFT );
4637 case T_column_count:
4642 case T_column_widths:
4646 while( ( token = NextTok() ) != T_RIGHT )
4656 while( ( token = NextTok() ) != T_RIGHT )
4663 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4665 if( token != T_LEFT )
4666 Expecting( T_LEFT );
4670 if( token != T_table_cell )
4671 Expecting(
"table_cell" );
4679 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4681 if( token != T_LEFT )
4682 Expecting( T_LEFT );
4700 table->SetBorderStroke( borderStroke );
4704 Expecting(
"external, header or stroke" );
4712 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4714 if( token != T_LEFT )
4715 Expecting( T_LEFT );
4733 table->SetSeparatorsStroke( separatorsStroke );
4737 Expecting(
"rows, cols, or stroke" );
4745 Expecting(
"columns, col_widths, row_heights, border, separators, header or cells" );
4749 return table.release();
4755 wxCHECK_RET( CurTok() == T_bus_alias,
4756 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4757 wxCHECK( aScreen, );
4760 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4771 busAlias->SetName( alias );
4776 if( token != T_members )
4777 Expecting(
"members" );
4781 while( token != T_RIGHT )
4783 if( !IsSymbol( token ) )
4784 Expecting(
"quoted string" );
4786 member = FromUTF8();
4791 busAlias->Members().emplace_back( member );
constexpr EDA_IU_SCALE schIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
void SetContentModified(bool aModified=true)
KICAD_T Type() const
Returns the type of object.
virtual void SetParent(EDA_ITEM *aParent)
FILL_T GetFillMode() const
SHAPE_POLY_SET & GetPolyShape()
void SetFillColor(const COLOR4D &aColor)
int GetPointCount() const
void SetEnd(const VECTOR2I &aEnd)
void SetFillMode(FILL_T aFill)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
void SetTextColor(const COLOR4D &aColor)
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetUnresolvedFontName(const wxString &aFontName)
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetTextPos(const VECTOR2I &aPoint)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
Set only the bold flag, without changing the font.
virtual void SetVisible(bool aVisible)
void SetLineSpacing(double aLineSpacing)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
static bool ValidateHyperlink(const wxString &aURL)
Check if aURL is a valid hyperlink.
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
void SetHyperlink(wxString aLink)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void ParseEmbedded(EMBEDDED_FILES *aFiles)
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
const std::vector< wxString > * GetFontFiles() const
If we just need the cached version of the font files, we can use this function which is const and wil...
void SetAreFontsEmbedded(bool aEmbedFonts)
Simple container to manage fill parameters.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Define a library symbol object.
wxString GetName() const override
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
EMBEDDED_FILES * GetEmbeddedFiles() override
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
static const wxChar Custom[]
"User" defined page type
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
const BITMAP_BASE & GetImage() const
Get the underlying image.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
Holds all the data relating to one schematic.
EMBEDDED_FILES * GetEmbeddedFiles() override
Object to handle a bitmap image that can be inserted in a schematic.
Class for a wire to bus entry.
void SetPinLength(int aLength)
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this label.
SCH_ITEM * ParseSymbolDrawItem()
SCH_SHAPE * parseSymbolPolyLine()
SCH_TABLE * parseSchTable()
bool m_appending
Appending load status.
unsigned m_lastProgressLine
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
SCH_SHAPE * parseSchCircle()
SCH_TEXT * parseSchText()
SCH_TABLECELL * parseSchTableCell()
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
void parsePinNumbers(std::unique_ptr< LIB_SYMBOL > &aSymbol)
LIB_SYMBOL * parseLibSymbol(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_RULE_AREA * parseSchRuleArea()
SCH_ITEM * parseSymbolText()
PROGRESS_REPORTER * m_progressReporter
void parseFill(FILL_PARAMS &aFill)
SCH_TEXTBOX * parseSymbolTextBox()
void parseBusAlias(SCH_SCREEN *aScreen)
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.
int m_unit
The current unit being parsed.
SCH_SHAPE * parseSymbolBezier()
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax, bool aEnforceMinTextSize=true)
SCH_TEXTBOX * parseSchTextBox()
SCH_SHEET * m_rootSheet
The rootsheet for full project loads or null for importing a schematic.
SCH_SHAPE * parseSchArc()
SCH_SHAPE * parseSchPolyLine()
SCH_BITMAP * parseImage()
SCH_SHAPE * parseSymbolCircle()
wxString m_generatorVersion
void ParseLib(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_PIN * parseSymbolPin()
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
wxString m_symbolName
The current symbol name.
VECTOR2I parseXY(bool aInvertY=false)
SCH_SHAPE * parseSymbolRectangle()
void parsePinNames(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SHAPE * parseSchBezier()
SCH_JUNCTION * parseJunction()
void ParseSchematic(SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Parse the internal LINE_READER object into aSheet.
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
int m_bodyStyle
The current body style being parsed.
SCH_NO_CONNECT * parseNoConnect()
SCH_SHAPE * parseSymbolArc()
SCH_BUS_WIRE_ENTRY * parseBusEntry()
SCH_SHAPE * parseSchRectangle()
SCH_FIELD * parseProperty(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SYMBOL * parseSchematicSymbol()
void parseSchTextBoxContent(SCH_TEXTBOX *aTextBox)
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
int m_requiredVersion
Set to the symbol library file version required.
const LINE_READER * m_lineReader
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
Parse internal LINE_READER object into symbols and return all found.
void parseSchSheetInstances(SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
SCH_IO_KICAD_SEXPR_PARSER(LINE_READER *aLineReader=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, unsigned aLineCount=0, SCH_SHEET *aRootSheet=nullptr, bool aIsAppending=false)
Base class for any item which can be embedded within the SCHEMATIC container class,...
void SetFieldsAutoplaced(AUTOPLACE_ALGO aAlgo)
void SetShape(LABEL_FLAG_SHAPE aShape)
std::vector< SCH_FIELD > & GetFields()
Segment description base class to describe items which have 2 end points (track, wire,...
void SetStartPoint(const VECTOR2I &aPosition)
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
void SetEndPoint(const VECTOR2I &aPosition)
void SetFileFormatVersionAtLoad(int aVersion)
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).
void SetPageSettings(const PAGE_INFO &aPageSettings)
const KIID & GetUuid() const
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
SCHEMATIC * Schematic() const
void FixupEmbeddedData()
After loading a file from disk, the library symbols do not yet contain the full data for their embedd...
int GetFileFormatVersionAtLoad() const
KIID m_uuid
A unique identifier for each schematic file.
std::vector< SCH_SYMBOL_INSTANCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
void SetPosition(const VECTOR2I &aPos) override
void SetStroke(const STROKE_PARAMS &aStroke) override
STROKE_PARAMS GetStroke() const override
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
SCH_SCREEN * GetScreen() const
void SetMarginBottom(int aBottom)
int GetLegacyTextMargin() const
void SetMarginLeft(int aLeft)
void SetMarginRight(int aRight)
void SetMarginTop(int aTop)
void SetExcludedFromSim(bool aExclude) override
void SetCenter(const VECTOR2I &aCenter)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetLineStyle(LINE_STYLE aLineStyle)
LINE_STYLE GetLineStyle() const
KIGFX::COLOR4D GetColor() const
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_360
static constexpr EDA_ANGLE ANGLE_180
@ FILLED_SHAPE
Fill with object color.
FONTCONFIG * Fontconfig()
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
#define MAX_PAGE_SIZE_EESCHEMA_MM
#define MIN_PAGE_SIZE_MM
Min and max page sizes for clamping, in mm.
PGM_BASE & Pgm()
The global program "get" accessor.
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
void fixupSchFillMode(SCH_SHAPE *aShape)
#define SIM_LEGACY_ENABLE_FIELD
#define SIM_LEGACY_ENABLE_FIELD_V7
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString UnescapeString(const wxString &aSource)
constexpr int MilsToIU(int mils) const
A filename or source description, a problem input line, a line number, a byte offset,...
ELECTRICAL_PINTYPE m_Type
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
#define SHEET_MANDATORY_FIELDS
#define GLOBALLABEL_MANDATORY_FIELDS
wxString GetCanonicalFieldName(FIELD_T aFieldType)
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
VECTOR2< int32_t > VECTOR2I