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 )
277 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
278 GetTokenString( CurTok() ) );
286 std::get<2>( params ),
296 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
297 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
303 wxString unitDisplayName;
305 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
307 symbol->SetUnitCount( 1 );
319 if( !IsSymbol( token ) )
321 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(),
330 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
337 if(
static_cast<int>(
name.size() ) > bad_pos )
339 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
348 CurLineNumber(), CurOffset() );
353 symbol->SetLibId(
id );
355 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
357 if( token != T_LEFT )
377 case T_exclude_from_sim:
378 symbol->SetExcludedFromSim(
parseBool() );
383 symbol->SetExcludedFromBOM( !
parseBool() );
388 symbol->SetExcludedFromBoard( !
parseBool() );
400 if( !IsSymbol( token ) )
403 CurLineNumber(), CurOffset() );
411 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
413 auto it = aSymbolLibMap.find(
name );
415 if( it == aSymbolLibMap.end() )
417 error.Printf(
_(
"No parent for extended symbol %s" ),
name.c_str() );
418 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
421 symbol->SetParent( it->second );
430 if( !IsSymbol( token ) )
433 CurLineNumber(), CurOffset() );
441 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
445 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
446 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
451 wxStringTokenizer tokenizer(
name,
"_" );
453 if( tokenizer.CountTokens() != 2 )
455 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
456 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
459 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
461 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
462 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
465 m_unit =
static_cast<int>( tmp );
467 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
469 error.Printf(
_(
"Invalid symbol convert number %s" ),
name.c_str() );
470 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
476 symbol->SetHasAlternateBodyStyle(
true,
false );
478 if(
m_unit > symbol->GetUnitCount() )
479 symbol->SetUnitCount(
m_unit,
false );
481 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
483 if( token != T_LEFT )
493 if( IsSymbol( token ) )
495 unitDisplayName = FromUTF8();
496 symbol->SetUnitDisplayName(
m_unit, unitDisplayName );
512 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
515 symbol->AddDrawItem( item,
false );
519 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
538 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
541 symbol->AddDrawItem( item,
false );
544 case T_embedded_fonts:
546 symbol->SetAreFontsEmbedded(
parseBool() );
551 case T_embedded_files:
554 embeddedFilesParser.SyncLineReaderWith( *
this );
558 embeddedFilesParser.
ParseEmbedded( symbol->GetEmbeddedFiles() );
562 wxLogError( e.
What() );
565 SyncLineReaderWith( embeddedFilesParser );
570 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
571 "rectangle, or text" );
575 symbol->GetDrawItems().sort();
578 return symbol.release();
594 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
608 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
610 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
618 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
620 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
627 strokeParser.SyncLineReaderWith( *
this );
630 SyncLineReaderWith( strokeParser );
636 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
639 aFill.
m_Color = COLOR4D::UNSPECIFIED;
643 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
645 if( token != T_LEFT )
658 case T_none: aFill.
m_FillType = FILL_T::NO_FILL;
break;
659 case T_outline: aFill.
m_FillType = FILL_T::FILLED_SHAPE;
break;
660 case T_background: aFill.
m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR;
break;
661 case T_color: aFill.
m_FillType = FILL_T::FILLED_WITH_COLOR;
break;
662 default: Expecting(
"none, outline, color or background" );
683 Expecting(
"type or color" );
690 bool aEnforceMinTextSize )
692 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
693 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
711 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
713 if( token == T_LEFT )
719 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
721 if( token == T_LEFT )
728 faceName = FromUTF8();
772 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
776 if( !faceName.IsEmpty() )
782 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
791 case T_mirror:
break;
792 default: Expecting(
"left, right, top, bottom, or mirror" );
801 wxString hyperlink = FromUTF8();
806 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
825 Expecting(
"font, justify, hide or href" );
833 wxCHECK_RET( CurTok() == aHeaderType,
834 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
840 if( tok == T_version )
854 wxCHECK_RET( CurTok() == T_pin_names,
855 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
865 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
868 if( token == T_hide )
870 aSymbol->SetShowPinNames(
false );
874 if( token != T_LEFT )
889 aSymbol->SetShowPinNames( !
parseBool() );
894 Expecting(
"offset or hide" );
902 wxCHECK_RET( CurTok() == T_pin_numbers,
903 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_number token." );
912 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
915 if( token == T_hide )
917 aSymbol->SetShowPinNumbers(
false );
921 if( token != T_LEFT )
931 aSymbol->SetShowPinNumbers( !
parseBool() );
945 wxCHECK_MSG( CurTok() == T_property,
nullptr,
946 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
947 wxCHECK( aSymbol,
nullptr );
951 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(),
MANDATORY_FIELDS );
955 field->SetVisible(
true );
959 if( token == T_private )
961 field->SetPrivate(
true );
965 if( !IsSymbol( token ) )
967 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
975 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
979 field->SetName(
name );
994 if( !IsSymbol( token ) )
996 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1003 field->SetText( value );
1005 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1007 if( token != T_LEFT )
1008 Expecting( T_LEFT );
1028 field->SetPosition(
parseXY(
true ) );
1040 field->SetNameShown( show );
1044 case T_do_not_autoplace:
1047 field->SetCanAutoplace( !doNotAutoplace );
1052 Expecting(
"id, at, show_name, do_not_autoplace, or effects" );
1060 int nextAvailableId = field->GetId() + 1;
1063 nextAvailableId += 1;
1065 field->SetId( nextAvailableId );
1070 if( field->IsMandatory() )
1072 existingField = aSymbol->GetFieldById( field->GetId() );
1074 *existingField = *field;
1076 return existingField;
1078 else if(
name ==
"ki_keywords" )
1081 aSymbol->SetKeyWords( value );
1085 else if(
name ==
"ki_description" )
1087 aSymbol->SetDescription( value );
1090 else if(
name ==
"ki_fp_filters" )
1093 wxArrayString filters;
1094 wxStringTokenizer tokenizer( value );
1096 while( tokenizer.HasMoreTokens() )
1098 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1099 filters.Add( curr_token );
1102 aSymbol->SetFPFilters( filters );
1105 else if(
name ==
"ki_locked" )
1109 aSymbol->LockUnits(
true );
1115 existingField = aSymbol->FindField( field->GetCanonicalName() );
1126 for(
int ii = 1; ii < 10 && existingField; ii++ )
1128 wxString newname = base_name;
1129 newname <<
'_' << ii;
1131 existingField = aSymbol->FindField( newname );
1133 if( !existingField )
1134 field->SetName( newname );
1138 if( !existingField )
1140 aSymbol->AddDrawItem( field.get(),
false );
1142 return field.release();
1155 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1156 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1162 bool hasMidPoint =
false;
1170 bool hasAngles =
false;
1172 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC,
LAYER_DEVICE );
1179 if( token == T_private )
1181 arc->SetPrivate(
true );
1185 for( ; token != T_RIGHT; token = NextTok() )
1187 if( token != T_LEFT )
1188 Expecting( T_LEFT );
1211 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1213 if( token != T_LEFT )
1214 Expecting( T_LEFT );
1242 Expecting(
"at, length, or angles" );
1250 arc->SetStroke( stroke );
1256 arc->SetFillColor( fill.
m_Color );
1260 Expecting(
"start, mid, end, radius, stroke, or fill" );
1266 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1277 EDA_ANGLE arc_start, arc_end, arc_angle;
1278 arc->CalcArcAngles( arc_start, arc_end );
1279 arc_angle = arc_end - arc_start;
1284 arc->SetStart( endPoint );
1285 arc->SetEnd( startPoint );
1288 arc->SetCenter( new_center );
1294 arc->SetCenter( new_center );
1298 else if( hasAngles )
1300 arc->SetCenter( center );
1306 arc->SetStart( endPoint );
1307 arc->SetEnd( startPoint );
1311 EDA_ANGLE arc_start, arc_end, arc_angle;
1312 arc->CalcArcAngles( arc_start, arc_end );
1313 arc_angle = arc_end - arc_start;
1319 arc->SetStart( startPoint );
1320 arc->SetEnd( endPoint );
1324 arc->SetStart( startPoint );
1325 arc->SetEnd( endPoint );
1328 arc->SetCenter( new_center );
1333 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1336 return arc.release();
1342 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1343 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1349 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER,
LAYER_DEVICE );
1351 bezier->SetUnit(
m_unit );
1356 if( token == T_private )
1358 bezier->SetPrivate(
true );
1362 for( ; token != T_RIGHT; token = NextTok() )
1364 if( token != T_LEFT )
1365 Expecting( T_LEFT );
1375 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1377 if( token != T_LEFT )
1378 Expecting( T_LEFT );
1387 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1388 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1389 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1390 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1391 default: Unexpected(
"control point" );
break;
1401 bezier->SetStroke( stroke );
1407 bezier->SetFillColor( fill.
m_Color );
1411 Expecting(
"pts, stroke, or fill" );
1415 bezier->RebuildBezierToSegmentsPointsList( bezier->GetPenWidth() / 2 );
1417 return bezier.release();
1423 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1424 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1432 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE,
LAYER_DEVICE );
1434 circle->SetUnit(
m_unit );
1439 if( token == T_private )
1441 circle->SetPrivate(
true );
1445 for( ; token != T_RIGHT; token = NextTok() )
1447 if( token != T_LEFT )
1448 Expecting( T_LEFT );
1466 circle->SetStroke( stroke );
1472 circle->SetFillColor( fill.
m_Color );
1476 Expecting(
"center, radius, stroke, or fill" );
1480 circle->SetCenter( center );
1481 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
1483 return circle.release();
1494 case T_input:
return ELECTRICAL_PINTYPE::PT_INPUT;
1495 case T_output:
return ELECTRICAL_PINTYPE::PT_OUTPUT;
1496 case T_bidirectional:
return ELECTRICAL_PINTYPE::PT_BIDI;
1497 case T_tri_state:
return ELECTRICAL_PINTYPE::PT_TRISTATE;
1498 case T_passive:
return ELECTRICAL_PINTYPE::PT_PASSIVE;
1499 case T_unspecified:
return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1500 case T_power_in:
return ELECTRICAL_PINTYPE::PT_POWER_IN;
1501 case T_power_out:
return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1502 case T_open_collector:
return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1503 case T_open_emitter:
return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1505 case T_no_connect:
return ELECTRICAL_PINTYPE::PT_NC;
1506 case T_free:
return ELECTRICAL_PINTYPE::PT_NIC;
1509 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1510 "power_in, power_out, open_collector, open_emitter, free or "
1512 return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1521 case T_line:
return GRAPHIC_PINSHAPE::LINE;
1522 case T_inverted:
return GRAPHIC_PINSHAPE::INVERTED;
1523 case T_clock:
return GRAPHIC_PINSHAPE::CLOCK;
1524 case T_inverted_clock:
return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1525 case T_input_low:
return GRAPHIC_PINSHAPE::INPUT_LOW;
1526 case T_clock_low:
return GRAPHIC_PINSHAPE::CLOCK_LOW;
1527 case T_output_low:
return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1528 case T_edge_clock_high:
return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1529 case T_non_logic:
return GRAPHIC_PINSHAPE::NONLOGIC;
1532 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1533 "output_low, edge_clock_high, non_logic" );
1534 return GRAPHIC_PINSHAPE::LINE;
1538 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1539 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1544 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1551 pin->SetType( parseType( token ) );
1555 pin->SetShape( parseShape( token ) );
1557 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1560 if( token == T_hide )
1562 pin->SetVisible(
false );
1566 if( token != T_LEFT )
1567 Expecting( T_LEFT );
1576 switch(
parseInt(
"pin orientation" ) )
1578 case 0:
pin->SetOrientation( PIN_ORIENTATION::PIN_RIGHT );
break;
1579 case 90:
pin->SetOrientation( PIN_ORIENTATION::PIN_UP );
break;
1580 case 180:
pin->SetOrientation( PIN_ORIENTATION::PIN_LEFT );
break;
1581 case 270:
pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
break;
1582 default: Expecting(
"0, 90, 180, or 270" );
1601 if( !IsSymbol( token ) )
1610 pin->SetName( FromUTF8() );
1614 if( token != T_RIGHT )
1618 if( token == T_effects )
1625 pin->SetNameTextSize(
text.GetTextHeight() );
1630 Expecting(
"effects" );
1639 if( !IsSymbol( token ) )
1642 CurLineNumber(), CurOffset() );
1645 pin->SetNumber( FromUTF8() );
1648 if( token != T_RIGHT )
1652 if( token == T_effects )
1659 pin->SetNumberTextSize(
text.GetTextHeight() );
1664 Expecting(
"effects" );
1676 if( !IsSymbol( token ) )
1679 CurLineNumber(), CurOffset() );
1685 alt.
m_Type = parseType( token );
1688 alt.
m_Shape = parseShape( token );
1690 pin->GetAlternates()[ alt.
m_Name ] = alt;
1697 Expecting(
"at, name, number, hide, length, or alternate" );
1701 return pin.release();
1707 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1708 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1713 std::unique_ptr<SCH_SHAPE> poly = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_DEVICE );
1720 if( token == T_private )
1722 poly->SetPrivate(
true );
1726 for( ; token != T_RIGHT; token = NextTok() )
1728 if( token != T_LEFT )
1729 Expecting( T_LEFT );
1736 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1738 if( token != T_LEFT )
1739 Expecting( T_LEFT );
1746 poly->AddPoint(
parseXY(
true ) );
1755 poly->SetStroke( stroke );
1761 poly->SetFillColor( fill.
m_Color );
1765 Expecting(
"pts, stroke, or fill" );
1769 return poly.release();
1775 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1776 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1781 auto rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE,
LAYER_DEVICE );
1783 rectangle->SetUnit(
m_unit );
1788 if( token == T_private )
1790 rectangle->SetPrivate(
true );
1794 for( ; token != T_RIGHT; token = NextTok() )
1796 if( token != T_LEFT )
1797 Expecting( T_LEFT );
1804 rectangle->SetPosition(
parseXY(
true ) );
1809 rectangle->SetEnd(
parseXY(
true ) );
1815 rectangle->SetStroke( stroke );
1821 rectangle->SetFillColor( fill.
m_Color );
1825 Expecting(
"start, end, stroke, or fill" );
1829 return rectangle.release();
1835 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1836 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1839 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1846 if( token == T_private )
1848 text->SetPrivate(
true );
1852 if( !IsSymbol( token ) )
1854 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1858 text->SetText( FromUTF8() );
1860 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1862 if( token != T_LEFT )
1863 Expecting( T_LEFT );
1881 Expecting(
"at or effects" );
1885 return text.release();
1891 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
1892 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
1904 bool foundEnd =
false;
1905 bool foundSize =
false;
1906 bool foundMargins =
false;
1908 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
1910 textBox->SetUnit(
m_unit );
1914 if( token == T_private )
1916 textBox->SetPrivate(
true );
1920 if( !IsSymbol( token ) )
1922 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1926 textBox->SetText( FromUTF8() );
1928 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1930 if( token != T_LEFT )
1931 Expecting( T_LEFT );
1962 textBox->SetStroke( stroke );
1968 textBox->SetFillColor( fill.
m_Color );
1973 textBox->SetMarginLeft(
left );
1974 textBox->SetMarginTop( top );
1975 textBox->SetMarginRight(
right );
1976 textBox->SetMarginBottom( bottom );
1977 foundMargins =
true;
1986 Expecting(
"at, size, stroke, fill or effects" );
1990 textBox->SetPosition( pos );
1993 textBox->SetEnd( end );
1994 else if( foundSize )
1995 textBox->SetEnd( pos + size );
1997 Expecting(
"size" );
2001 int margin = textBox->GetLegacyTextMargin();
2002 textBox->SetMarginLeft( margin );
2003 textBox->SetMarginTop( margin );
2004 textBox->SetMarginRight( margin );
2005 textBox->SetMarginBottom( margin );
2008 return textBox.release();
2014 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
2015 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
2021 wxString pageType = FromUTF8();
2023 if( !aPageInfo.
SetType( pageType ) )
2025 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
2052 if( token == T_portrait )
2057 else if( token != T_RIGHT )
2059 Expecting(
"portrait" );
2066 wxCHECK_RET( CurTok() == T_title_block,
2067 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
2071 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2073 if( token != T_LEFT )
2074 Expecting( T_LEFT );
2082 aTitleBlock.
SetTitle( FromUTF8() );
2087 aTitleBlock.
SetDate( FromUTF8() );
2102 int commentNumber =
parseInt(
"comment" );
2104 switch( commentNumber )
2153 CurLine(), CurLineNumber(), CurOffset() );
2160 Expecting(
"title, date, rev, company, or comment" );
2170 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2171 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2173 bool is_private =
false;
2175 T token = NextTok();
2177 if( token == T_private )
2183 if( !IsSymbol( token ) )
2185 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2189 wxString
name = FromUTF8();
2191 if(
name.IsEmpty() )
2193 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2199 if( !IsSymbol( token ) )
2201 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2206 wxString value = FromUTF8();
2208 int mandatoryFieldCount = 0;
2215 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>(
VECTOR2I( -1, -1 ),
2216 mandatoryFieldCount,
2218 field->SetText( value );
2219 field->SetVisible(
true );
2220 field->SetPrivate( is_private );
2245 else if( !
name.CmpNoCase( wxT(
"Sheet name" ) ) )
2250 else if( !
name.CmpNoCase( wxT(
"Sheet file" ) ) )
2258 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2260 if( token != T_LEFT )
2261 Expecting( T_LEFT );
2272 if(
id >= mandatoryFieldCount )
2279 field->SetPosition(
parseXY() );
2291 field->SetNameShown( show );
2295 case T_do_not_autoplace:
2298 field->SetCanAutoplace( !doNotAutoplace );
2303 Expecting(
"id, at, show_name, do_not_autoplace or effects" );
2307 return field.release();
2313 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2314 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2315 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2317 T token = NextTok();
2319 if( !IsSymbol( token ) )
2321 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2325 wxString
name = FromUTF8();
2327 if(
name.IsEmpty() )
2329 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2333 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2339 case T_input: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
2340 case T_output: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
2341 case T_bidirectional: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
2342 case T_tri_state: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
2343 case T_passive: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
2345 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2348 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2350 if( token != T_LEFT )
2351 Expecting( T_LEFT );
2359 sheetPin->SetPosition(
parseXY() );
2361 double angle =
parseDouble(
"sheet pin angle (side)" );
2364 sheetPin->SetSide( SHEET_SIDE::RIGHT );
2365 else if( angle == 90.0 )
2366 sheetPin->SetSide( SHEET_SIDE::TOP );
2367 else if( angle == 180.0 )
2368 sheetPin->SetSide( SHEET_SIDE::LEFT );
2369 else if( angle == 270.0 )
2370 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
2372 Expecting(
"0, 90, 180, or 270" );
2389 Expecting(
"at, uuid or effects" );
2393 return sheetPin.release();
2399 wxCHECK_RET( CurTok() == T_sheet_instances,
2400 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2401 wxCHECK( aScreen, );
2405 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2407 if( token != T_LEFT )
2408 Expecting( T_LEFT );
2426 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2428 if( token != T_LEFT )
2429 Expecting( T_LEFT );
2433 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2436 size_t numReplacements = 0;
2454 for(
const wxString& ch : whitespaces )
2455 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2460 if( numReplacements > 0 )
2467 Expecting(
"path or page" );
2472 && ( instance.
m_Path.empty() ) )
2488 Expecting(
"path" );
2496 wxCHECK_RET( CurTok() == T_symbol_instances,
2497 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2498 wxCHECK( aScreen, );
2503 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2505 if( token != T_LEFT )
2506 Expecting( T_LEFT );
2523 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2525 if( token != T_LEFT )
2526 Expecting( T_LEFT );
2545 instance.
m_Value = FromUTF8();
2556 Expecting(
"path, unit, value or footprint" );
2565 Expecting(
"path" );
2574 wxCHECK( aSheet !=
nullptr, );
2578 wxCHECK( screen !=
nullptr, );
2580 if( aIsCopyableOnly )
2583 bool fileHasUuid =
false;
2597 if( !aIsCopyableOnly )
2602 if( CurTok() != T_kicad_sch )
2603 Expecting(
"kicad_sch" );
2619 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2621 if( aIsCopyableOnly && token == T_EOF )
2624 if( token != T_LEFT )
2625 Expecting( T_LEFT );
2655 case T_generator_version:
2681 if( aIsCopyableOnly )
2682 Unexpected( T_paper );
2692 if( aIsCopyableOnly )
2693 Unexpected( T_page );
2697 NeedSYMBOLorNUMBER();
2698 NeedSYMBOLorNUMBER();
2705 if( aIsCopyableOnly )
2706 Unexpected( T_title_block );
2720 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2722 if( token != T_LEFT )
2723 Expecting( T_LEFT );
2736 Expecting(
"symbol" );
2837 case T_netclass_flag:
2842 case T_global_label:
2843 case T_hierarchical_label:
2844 case T_directive_label:
2856 case T_sheet_instances:
2860 case T_symbol_instances:
2865 if( aIsCopyableOnly )
2866 Unexpected( T_bus_alias );
2871 case T_embedded_fonts:
2877 CurLineNumber(), CurOffset() );
2884 case T_embedded_files:
2890 CurLineNumber(), CurOffset() );
2893 embeddedFilesParser.SyncLineReaderWith( *
this );
2901 wxLogError( e.
What() );
2904 SyncLineReaderWith( embeddedFilesParser );
2910 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
2911 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
2912 "sheet, symbol, symbol_instances, text, title_block" );
2931 CurLineNumber(), CurOffset() );
2936 std::get<2>( params ),
2942 std::vector<std::string> fontNames;
2943 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
2953 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
2954 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
2959 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2961 std::set<int> fieldIDsRead;
2964 symbol->ClearFieldsAutoplaced();
2974 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2976 if( token != T_LEFT )
2977 Expecting( T_LEFT );
2989 if( !IsSymbol( token ) )
2992 CurLineNumber(), CurOffset() );
2995 libName = FromUTF8();
2999 libName.Replace(
"{slash}",
"/" );
3009 if( !IsSymbol( token ) && token != T_NUMBER )
3010 Expecting(
"symbol|number" );
3013 wxString
name = FromUTF8();
3017 name.Replace(
"{slash}",
"/" );
3023 if(
static_cast<int>(
name.size() ) > bad_pos )
3025 wxString msg = wxString::Format(
3026 _(
"Symbol %s contains invalid character '%c'" ),
name,
3033 CurLineNumber(), CurOffset() );
3036 symbol->SetLibId( libId );
3042 symbol->SetPosition(
parseXY() );
3044 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3047 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3048 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3049 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3050 default: Expecting(
"0, 90, 180, or 270" );
3053 symbol->SetTransform( transform );
3062 else if( token == T_y )
3065 Expecting(
"x or y" );
3071 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3078 symbol->SetBodyStyleUnconditional(
parseInt(
"symbol body style" ) );
3082 case T_exclude_from_sim:
3083 symbol->SetExcludedFromSim(
parseBool() );
3088 symbol->SetExcludedFromBOM( !
parseBool() );
3093 symbol->SetExcludedFromBoard( !
parseBool() );
3102 case T_fields_autoplaced:
3104 symbol->SetFieldsAutoplaced();
3114 case T_default_instance:
3118 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3120 if( token != T_LEFT )
3121 Expecting( T_LEFT );
3140 symbol->SetValueFieldText( FromUTF8() );
3146 symbol->SetFootprintFieldText( FromUTF8() );
3151 Expecting(
"reference, unit, value or footprint" );
3160 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3162 if( token != T_LEFT )
3163 Expecting( T_LEFT );
3167 if( token != T_project )
3168 Expecting(
"project" );
3172 wxString projectName = FromUTF8();
3174 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3176 if( token != T_LEFT )
3177 Expecting( T_LEFT );
3181 if( token != T_path )
3182 Expecting(
"path" );
3191 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3193 if( token != T_LEFT )
3194 Expecting( T_LEFT );
3213 symbol->SetValueFieldText( FromUTF8() );
3219 symbol->SetFootprintFieldText( FromUTF8() );
3224 Expecting(
"reference, unit, value or footprint" );
3227 symbol->AddHierarchicalReference( instance );
3244 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3251 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3257 int nextAvailableId = field->
GetId() + 1;
3260 nextAvailableId += 1;
3262 field->
SetId( nextAvailableId );
3265 if( symbol->GetFieldById( field->
GetId() ) )
3266 *symbol->GetFieldById( field->
GetId() ) = *field;
3268 symbol->AddField( *field );
3273 symbol->UpdatePrefix();
3288 number = FromUTF8();
3290 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3292 if( token != T_LEFT )
3293 Expecting( T_LEFT );
3317 Expecting(
"alternate or uuid" );
3321 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3327 Expecting(
"lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
3328 "default_instance, property, pin, or instances" );
3332 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3333 symbol->SetSchSymbolLibraryName( libName );
3336 symbol->ClearFlags();
3338 return symbol.release();
3344 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3345 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3348 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3351 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3353 if( token != T_LEFT )
3354 Expecting( T_LEFT );
3361 bitmap->SetPosition(
parseXY() );
3387 data.reserve( 1 << 17 );
3389 while( token != T_RIGHT )
3391 if( !IsSymbol( token ) )
3392 Expecting(
"base64 image data" );
3398 wxMemoryBuffer buffer = wxBase64Decode( data );
3407 Expecting(
"at, scale, uuid or data" );
3420 return bitmap.release();
3426 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3427 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3433 std::vector<SCH_FIELD> fields;
3434 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3435 std::set<int> fieldIDsRead;
3438 sheet->ClearFieldsAutoplaced();
3440 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3442 if( token != T_LEFT )
3443 Expecting( T_LEFT );
3450 sheet->SetPosition(
parseXY() );
3459 sheet->SetSize( size );
3464 case T_exclude_from_sim:
3465 sheet->SetExcludedFromSim(
parseBool() );
3470 sheet->SetExcludedFromBOM( !
parseBool() );
3475 sheet->SetExcludedFromBoard( !
parseBool() );
3484 case T_fields_autoplaced:
3486 sheet->SetFieldsAutoplaced();
3492 sheet->SetBorderWidth( stroke.
GetWidth() );
3493 sheet->SetBorderColor( stroke.
GetColor() );
3498 sheet->SetBackgroundColor( fill.
m_Color );
3515 if( fields.empty() )
3529 if( field->
GetId() < 0 )
3532 while( !fieldIDsRead.insert( field->
GetId() ).second )
3535 fields.emplace_back( *field );
3552 std::vector<SCH_SHEET_INSTANCE> instances;
3554 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3556 if( token != T_LEFT )
3557 Expecting( T_LEFT );
3561 if( token != T_project )
3562 Expecting(
"project" );
3566 wxString projectName = FromUTF8();
3568 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3570 if( token != T_LEFT )
3571 Expecting( T_LEFT );
3575 if( token != T_path )
3576 Expecting(
"path" );
3585 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3587 if( token != T_LEFT )
3588 Expecting( T_LEFT );
3608 static std::vector<wxString> whitespaces =
3614 for( wxString ch : whitespaces )
3623 Expecting(
"page" );
3627 instances.emplace_back( instance );
3631 sheet->setInstances( instances );
3636 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3640 sheet->SetFields( fields );
3642 return sheet.release();
3648 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3649 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3652 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3654 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3656 if( token != T_LEFT )
3657 Expecting( T_LEFT );
3664 junction->SetPosition(
parseXY() );
3682 junction->SetColor(
color );
3694 Expecting(
"at, diameter, color or uuid" );
3698 return junction.release();
3704 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3705 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3708 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3710 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3712 if( token != T_LEFT )
3713 Expecting( T_LEFT );
3720 no_connect->SetPosition(
parseXY() );
3731 Expecting(
"at or uuid" );
3735 return no_connect.release();
3741 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3742 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3746 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3748 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3750 if( token != T_LEFT )
3751 Expecting( T_LEFT );
3758 busEntry->SetPosition(
parseXY() );
3768 busEntry->SetSize( size );
3775 busEntry->SetStroke( stroke );
3785 Expecting(
"at, size, uuid or stroke" );
3789 return busEntry.release();
3799 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_NOTES );
3801 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3803 if( token != T_LEFT )
3804 Expecting( T_LEFT );
3811 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3813 if( token != T_LEFT )
3814 Expecting( T_LEFT );
3821 polyline->AddPoint(
parseXY() );
3834 polyline->SetStroke( stroke );
3840 polyline->SetFillColor( fill.
m_Color );
3850 Expecting(
"pts, uuid, stroke, or fill" );
3854 return polyline.release();
3873 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3876 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3878 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3880 if( token != T_LEFT )
3881 Expecting( T_LEFT );
3894 line->SetStartPoint(
parseXY() );
3902 line->SetEndPoint(
parseXY() );
3909 line->SetStroke( stroke );
3919 Expecting(
"at, uuid or stroke" );
3923 return line.release();
3929 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
3930 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
3938 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
3940 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3942 if( token != T_LEFT )
3943 Expecting( T_LEFT );
3966 arc->SetStroke( stroke );
3972 arc->SetFillColor( fill.
m_Color );
3977 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
3982 Expecting(
"start, mid, end, stroke, fill or uuid" );
3986 arc->SetArcGeometry( startPoint, midPoint, endPoint );
3988 return arc.release();
3994 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
3995 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4002 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
4004 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4006 if( token != T_LEFT )
4007 Expecting( T_LEFT );
4025 circle->SetStroke( stroke );
4031 circle->SetFillColor( fill.
m_Color );
4036 const_cast<KIID&
>( circle->m_Uuid ) =
KIID( FromUTF8() );
4041 Expecting(
"center, radius, stroke, fill or uuid" );
4045 circle->SetCenter( center );
4046 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
4048 return circle.release();
4054 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4055 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4060 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
4062 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4064 if( token != T_LEFT )
4065 Expecting( T_LEFT );
4072 rectangle->SetPosition(
parseXY() );
4077 rectangle->SetEnd(
parseXY() );
4083 rectangle->SetStroke( stroke );
4089 rectangle->SetFillColor( fill.
m_Color );
4094 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4099 Expecting(
"start, end, stroke, fill or uuid" );
4103 return rectangle.release();
4109 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4110 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4115 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4117 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4119 if( token != T_LEFT )
4120 Expecting( T_LEFT );
4134 ruleArea->SetPolyShape( sch_rule_poly );
4136 ruleArea->SetStroke( poly->GetStroke() );
4137 ruleArea->SetFillMode( poly->GetFillMode() );
4138 ruleArea->SetFillColor( poly->GetFillColor() );
4142 Expecting(
"polyline" );
4146 return ruleArea.release();
4152 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4153 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4158 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
4160 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4162 if( token != T_LEFT )
4163 Expecting( T_LEFT );
4173 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4175 if( token != T_LEFT )
4176 Expecting( T_LEFT );
4185 case 0: bezier->SetStart(
parseXY() );
break;
4186 case 1: bezier->SetBezierC1(
parseXY() );
break;
4187 case 2: bezier->SetBezierC2(
parseXY() );
break;
4188 case 3: bezier->SetEnd(
parseXY() );
break;
4189 default: Unexpected(
"control point" );
break;
4199 bezier->SetStroke( stroke );
4205 bezier->SetFillColor( fill.
m_Color );
4210 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4215 Expecting(
"pts, stroke, fill or uuid" );
4219 bezier->RebuildBezierToSegmentsPointsList( bezier->GetPenWidth() / 2 );
4221 return bezier.release();
4228 std::unique_ptr<SCH_TEXT>
text;
4232 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4233 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4234 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4235 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4236 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4237 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4239 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4243 text->ClearFieldsAutoplaced();
4247 text->SetText( FromUTF8() );
4249 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4251 if( token != T_LEFT )
4252 Expecting( T_LEFT );
4258 case T_exclude_from_sim:
4269 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4285 Unexpected( T_shape );
4293 case T_input: label->
SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
4294 case T_output: label->
SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
4295 case T_bidirectional: label->
SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
4296 case T_tri_state: label->
SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
4297 case T_passive: label->
SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
4298 case T_dot: label->
SetShape( LABEL_FLAG_SHAPE::F_DOT );
break;
4299 case T_round: label->
SetShape( LABEL_FLAG_SHAPE::F_ROUND );
break;
4300 case T_diamond: label->
SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
break;
4301 case T_rectangle: label->
SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
break;
4303 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4314 Unexpected( T_length );
4323 case T_fields_autoplaced:
4325 text->SetFieldsAutoplaced();
4355 Unexpected( T_property );
4385 Expecting(
"at, shape, iref, uuid or effects" );
4391 if( label && label->
GetFields().empty() )
4394 return text.release();
4400 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4401 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4403 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4407 return textBox.release();
4413 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4414 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4416 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4420 return cell.release();
4436 bool foundEnd =
false;
4437 bool foundSize =
false;
4438 bool foundMargins =
false;
4442 aTextBox->
SetText( FromUTF8() );
4444 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4446 if( token != T_LEFT )
4447 Expecting( T_LEFT );
4453 case T_exclude_from_sim:
4484 cell->SetColSpan(
parseInt(
"column span" ) );
4485 cell->SetRowSpan(
parseInt(
"row span" ) );
4489 Expecting(
"at, size, stroke, fill, effects or uuid" );
4512 foundMargins =
true;
4528 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4530 Expecting(
"at, size, stroke, fill, effects or uuid" );
4538 else if( foundSize )
4539 aTextBox->
SetEnd( pos + size );
4541 Expecting(
"size" );
4556 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4557 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4561 STROKE_PARAMS borderStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4562 STROKE_PARAMS separatorsStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4563 std::unique_ptr<SCH_TABLE> table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4565 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4567 if( token != T_LEFT )
4568 Expecting( T_LEFT );
4574 case T_column_count:
4575 table->SetColCount(
parseInt(
"column count" ) );
4579 case T_column_widths:
4583 while( ( token = NextTok() ) != T_RIGHT )
4593 while( ( token = NextTok() ) != T_RIGHT )
4600 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4602 if( token != T_LEFT )
4603 Expecting( T_LEFT );
4607 if( token != T_table_cell )
4608 Expecting(
"table_cell" );
4616 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4618 if( token != T_LEFT )
4619 Expecting( T_LEFT );
4626 table->SetStrokeExternal(
parseBool() );
4637 table->SetBorderStroke( borderStroke );
4641 Expecting(
"external, header or stroke" );
4649 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4651 if( token != T_LEFT )
4652 Expecting( T_LEFT );
4670 table->SetSeparatorsStroke( separatorsStroke );
4674 Expecting(
"rows, cols, or stroke" );
4682 Expecting(
"columns, col_widths, row_heights, border, separators, header or cells" );
4686 return table.release();
4692 wxCHECK_RET( CurTok() == T_bus_alias,
4693 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4694 wxCHECK( aScreen, );
4697 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4708 busAlias->SetName( alias );
4713 if( token != T_members )
4714 Expecting(
"members" );
4718 while( token != T_RIGHT )
4720 if( !IsSymbol( token ) )
4721 Expecting(
"quoted string" );
4723 member = FromUTF8();
4728 busAlias->Members().emplace_back( member );
4741 bool aReplaceInList )
4748 if( aReplaceInList )
4755 std::get<1>( it->second ),
4756 std::get<2>( it->second ) ) );
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)
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)
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 italic 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 SetFont(KIFONT::FONT *aFont)
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()
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
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
int UpdateFieldOrdinals()
Order optional field indices.
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)
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
const wxString & GetInternalName()
Get the initial name of the field set at creation (or set by SetName()).
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()
PROGRESS_REPORTER * m_progressReporter
void parseFill(FILL_PARAMS &aFill)
SCH_TEXTBOX * parseSymbolTextBox()
void parseBusAlias(SCH_SCREEN *aScreen)
std::set< int > m_fieldIDsRead
Field IDs that have been read so far for the current symbol.
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)
std::map< EDA_TEXT *, std::tuple< wxString, bool, bool > > m_fontTextMap
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()
void removeEntryInFontTextMap(EDA_TEXT *aEntry, EDA_TEXT *aCandidate, bool aReplaceInList)
Remove aEntry from m_fontTextMap.
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_TEXT * parseSymbolText()
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()
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.
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslated=true)
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
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
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 ...
@ SHEET_MANDATORY_FIELDS
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
#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
wxString GetCanonicalFieldName(int idx)
@ 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.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
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