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 );
287 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
288 GetTokenString( CurTok() ) );
299 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
300 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
306 wxString unitDisplayName;
308 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
310 symbol->SetUnitCount( 1 );
322 if( !IsSymbol( token ) )
324 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(),
333 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
340 if(
static_cast<int>(
name.size() ) > bad_pos )
342 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
351 CurLineNumber(), CurOffset() );
356 symbol->SetLibId(
id );
358 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
360 if( token != T_LEFT )
380 case T_exclude_from_sim:
381 symbol->SetExcludedFromSim(
parseBool() );
386 symbol->SetExcludedFromBOM( !
parseBool() );
391 symbol->SetExcludedFromBoard( !
parseBool() );
403 if( !IsSymbol( token ) )
406 CurLineNumber(), CurOffset() );
414 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
416 auto it = aSymbolLibMap.find(
name );
418 if( it == aSymbolLibMap.end() )
420 error.Printf(
_(
"No parent for extended symbol %s" ),
name.c_str() );
421 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
424 symbol->SetParent( it->second );
433 if( !IsSymbol( token ) )
436 CurLineNumber(), CurOffset() );
444 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
448 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
449 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
454 wxStringTokenizer tokenizer(
name,
"_" );
456 if( tokenizer.CountTokens() != 2 )
458 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
459 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
462 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
464 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
465 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
468 m_unit =
static_cast<int>( tmp );
470 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
472 error.Printf(
_(
"Invalid symbol convert number %s" ),
name.c_str() );
473 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
479 symbol->SetHasAlternateBodyStyle(
true,
false );
481 if(
m_unit > symbol->GetUnitCount() )
482 symbol->SetUnitCount(
m_unit,
false );
484 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
486 if( token != T_LEFT )
496 if( IsSymbol( token ) )
498 unitDisplayName = FromUTF8();
499 symbol->SetUnitDisplayName(
m_unit, unitDisplayName );
515 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
518 symbol->AddDrawItem( item,
false );
522 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
541 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
544 symbol->AddDrawItem( item,
false );
547 case T_embedded_fonts:
549 symbol->SetAreFontsEmbedded(
parseBool() );
554 case T_embedded_files:
557 embeddedFilesParser.SyncLineReaderWith( *
this );
561 embeddedFilesParser.
ParseEmbedded( symbol->GetEmbeddedFiles() );
565 wxLogError( e.
What() );
568 SyncLineReaderWith( embeddedFilesParser );
573 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
574 "rectangle, or text" );
578 symbol->GetDrawItems().sort();
581 const std::vector<wxString>* embeddedFonts =
582 symbol->GetEmbeddedFiles()->UpdateFontFiles();
584 symbol->RunOnChildren(
588 textItem->ResolveFont( embeddedFonts );
591 return symbol.release();
607 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
621 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
623 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
631 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
633 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
640 strokeParser.SyncLineReaderWith( *
this );
643 SyncLineReaderWith( strokeParser );
649 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
652 aFill.
m_Color = COLOR4D::UNSPECIFIED;
656 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
658 if( token != T_LEFT )
671 case T_none: aFill.
m_FillType = FILL_T::NO_FILL;
break;
672 case T_outline: aFill.
m_FillType = FILL_T::FILLED_SHAPE;
break;
673 case T_background: aFill.
m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR;
break;
674 case T_color: aFill.
m_FillType = FILL_T::FILLED_WITH_COLOR;
break;
675 default: Expecting(
"none, outline, color or background" );
696 Expecting(
"type or color" );
703 bool aEnforceMinTextSize )
705 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
706 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
723 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
725 if( token == T_LEFT )
731 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
733 if( token == T_LEFT )
784 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
791 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
800 case T_mirror:
break;
801 default: Expecting(
"left, right, top, bottom, or mirror" );
810 wxString hyperlink = FromUTF8();
815 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
834 Expecting(
"font, justify, hide or href" );
842 wxCHECK_RET( CurTok() == aHeaderType,
843 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
849 if( tok == T_version )
863 wxCHECK_RET( CurTok() == T_pin_names,
864 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
874 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
877 if( token == T_hide )
879 aSymbol->SetShowPinNames(
false );
883 if( token != T_LEFT )
898 aSymbol->SetShowPinNames( !
parseBool() );
903 Expecting(
"offset or hide" );
911 wxCHECK_RET( CurTok() == T_pin_numbers,
912 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_number token." );
921 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
924 if( token == T_hide )
926 aSymbol->SetShowPinNumbers(
false );
930 if( token != T_LEFT )
940 aSymbol->SetShowPinNumbers( !
parseBool() );
954 wxCHECK_MSG( CurTok() == T_property,
nullptr,
955 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
956 wxCHECK( aSymbol,
nullptr );
960 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(), aSymbol->GetNextAvailableFieldId() );
964 field->SetVisible(
true );
968 if( token == T_private )
970 field->SetPrivate(
true );
974 if( !IsSymbol( token ) )
976 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
984 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
988 field->SetName(
name );
996 field->SetId( fieldId );
1003 if( !IsSymbol( token ) )
1005 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1012 field->SetText( value );
1014 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1016 if( token != T_LEFT )
1017 Expecting( T_LEFT );
1037 field->SetPosition(
parseXY(
true ) );
1054 field->SetNameShown( show );
1058 case T_do_not_autoplace:
1061 field->SetCanAutoplace( !doNotAutoplace );
1066 Expecting(
"id, at, hide, show_name, do_not_autoplace, or effects" );
1074 int nextAvailableId = field->GetId() + 1;
1077 nextAvailableId += 1;
1079 field->SetId( nextAvailableId );
1084 if( field->IsMandatory() )
1086 existingField = aSymbol->GetFieldById( field->GetId() );
1088 *existingField = *field;
1090 return existingField;
1092 else if(
name ==
"ki_keywords" )
1095 aSymbol->SetKeyWords( value );
1099 else if(
name ==
"ki_description" )
1101 aSymbol->SetDescription( value );
1104 else if(
name ==
"ki_fp_filters" )
1107 wxArrayString filters;
1108 wxStringTokenizer tokenizer( value );
1110 while( tokenizer.HasMoreTokens() )
1112 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1113 filters.Add( curr_token );
1116 aSymbol->SetFPFilters( filters );
1119 else if(
name ==
"ki_locked" )
1123 aSymbol->LockUnits(
true );
1129 existingField = aSymbol->FindField( field->GetCanonicalName() );
1140 for(
int ii = 1; ii < 10 && existingField; ii++ )
1142 wxString newname = base_name;
1143 newname <<
'_' << ii;
1145 existingField = aSymbol->FindField( newname );
1147 if( !existingField )
1148 field->SetName( newname );
1152 if( !existingField )
1154 aSymbol->AddDrawItem( field.get(),
false );
1156 return field.release();
1169 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1170 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1176 bool hasMidPoint =
false;
1184 bool hasAngles =
false;
1186 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC,
LAYER_DEVICE );
1193 if( token == T_private )
1195 arc->SetPrivate(
true );
1199 for( ; token != T_RIGHT; token = NextTok() )
1201 if( token != T_LEFT )
1202 Expecting( T_LEFT );
1225 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1227 if( token != T_LEFT )
1228 Expecting( T_LEFT );
1256 Expecting(
"at, length, or angles" );
1264 arc->SetStroke( stroke );
1270 arc->SetFillColor( fill.
m_Color );
1274 Expecting(
"start, mid, end, radius, stroke, or fill" );
1280 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1291 EDA_ANGLE arc_start, arc_end, arc_angle;
1292 arc->CalcArcAngles( arc_start, arc_end );
1293 arc_angle = arc_end - arc_start;
1298 arc->SetStart( endPoint );
1299 arc->SetEnd( startPoint );
1302 arc->SetCenter( new_center );
1308 arc->SetCenter( new_center );
1312 else if( hasAngles )
1314 arc->SetCenter(
center );
1320 arc->SetStart( endPoint );
1321 arc->SetEnd( startPoint );
1325 EDA_ANGLE arc_start, arc_end, arc_angle;
1326 arc->CalcArcAngles( arc_start, arc_end );
1327 arc_angle = arc_end - arc_start;
1333 arc->SetStart( startPoint );
1334 arc->SetEnd( endPoint );
1342 arc->SetStart( startPoint );
1343 arc->SetEnd( endPoint );
1347 arc->SetCenter( new_center );
1353 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1356 return arc.release();
1362 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1363 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1369 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER,
LAYER_DEVICE );
1371 bezier->SetUnit(
m_unit );
1376 if( token == T_private )
1378 bezier->SetPrivate(
true );
1382 for( ; token != T_RIGHT; token = NextTok() )
1384 if( token != T_LEFT )
1385 Expecting( T_LEFT );
1395 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1397 if( token != T_LEFT )
1398 Expecting( T_LEFT );
1407 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1408 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1409 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1410 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1411 default: Unexpected(
"control point" );
break;
1421 bezier->SetStroke( stroke );
1427 bezier->SetFillColor( fill.
m_Color );
1431 Expecting(
"pts, stroke, or fill" );
1435 bezier->RebuildBezierToSegmentsPointsList( bezier->GetPenWidth() / 2 );
1437 return bezier.release();
1443 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1444 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1452 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE,
LAYER_DEVICE );
1454 circle->SetUnit(
m_unit );
1459 if( token == T_private )
1461 circle->SetPrivate(
true );
1465 for( ; token != T_RIGHT; token = NextTok() )
1467 if( token != T_LEFT )
1468 Expecting( T_LEFT );
1486 circle->SetStroke( stroke );
1492 circle->SetFillColor( fill.
m_Color );
1496 Expecting(
"center, radius, stroke, or fill" );
1500 circle->SetCenter(
center );
1503 return circle.release();
1514 case T_input:
return ELECTRICAL_PINTYPE::PT_INPUT;
1515 case T_output:
return ELECTRICAL_PINTYPE::PT_OUTPUT;
1516 case T_bidirectional:
return ELECTRICAL_PINTYPE::PT_BIDI;
1517 case T_tri_state:
return ELECTRICAL_PINTYPE::PT_TRISTATE;
1518 case T_passive:
return ELECTRICAL_PINTYPE::PT_PASSIVE;
1519 case T_unspecified:
return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1520 case T_power_in:
return ELECTRICAL_PINTYPE::PT_POWER_IN;
1521 case T_power_out:
return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1522 case T_open_collector:
return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1523 case T_open_emitter:
return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1525 case T_no_connect:
return ELECTRICAL_PINTYPE::PT_NC;
1526 case T_free:
return ELECTRICAL_PINTYPE::PT_NIC;
1529 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1530 "power_in, power_out, open_collector, open_emitter, free or "
1532 return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1541 case T_line:
return GRAPHIC_PINSHAPE::LINE;
1542 case T_inverted:
return GRAPHIC_PINSHAPE::INVERTED;
1543 case T_clock:
return GRAPHIC_PINSHAPE::CLOCK;
1544 case T_inverted_clock:
return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1545 case T_input_low:
return GRAPHIC_PINSHAPE::INPUT_LOW;
1546 case T_clock_low:
return GRAPHIC_PINSHAPE::CLOCK_LOW;
1547 case T_output_low:
return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1548 case T_edge_clock_high:
return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1549 case T_non_logic:
return GRAPHIC_PINSHAPE::NONLOGIC;
1552 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1553 "output_low, edge_clock_high, non_logic" );
1554 return GRAPHIC_PINSHAPE::LINE;
1558 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1559 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1564 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1571 pin->SetType( parseType( token ) );
1575 pin->SetShape( parseShape( token ) );
1577 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1580 if( token == T_hide )
1582 pin->SetVisible(
false );
1586 if( token != T_LEFT )
1587 Expecting( T_LEFT );
1596 switch(
parseInt(
"pin orientation" ) )
1598 case 0:
pin->SetOrientation( PIN_ORIENTATION::PIN_RIGHT );
break;
1599 case 90:
pin->SetOrientation( PIN_ORIENTATION::PIN_UP );
break;
1600 case 180:
pin->SetOrientation( PIN_ORIENTATION::PIN_LEFT );
break;
1601 case 270:
pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
break;
1602 default: Expecting(
"0, 90, 180, or 270" );
1621 if( !IsSymbol( token ) )
1630 pin->SetName( FromUTF8() );
1634 if( token != T_RIGHT )
1638 if( token == T_effects )
1645 pin->SetNameTextSize(
text.GetTextHeight() );
1650 Expecting(
"effects" );
1659 if( !IsSymbol( token ) )
1662 CurLineNumber(), CurOffset() );
1665 pin->SetNumber( FromUTF8() );
1668 if( token != T_RIGHT )
1672 if( token == T_effects )
1679 pin->SetNumberTextSize(
text.GetTextHeight() );
1684 Expecting(
"effects" );
1696 if( !IsSymbol( token ) )
1699 CurLineNumber(), CurOffset() );
1705 alt.
m_Type = parseType( token );
1708 alt.
m_Shape = parseShape( token );
1710 pin->GetAlternates()[ alt.
m_Name ] = alt;
1717 Expecting(
"at, name, number, hide, length, or alternate" );
1721 return pin.release();
1727 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1728 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1733 std::unique_ptr<SCH_SHAPE> poly = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_DEVICE );
1740 if( token == T_private )
1742 poly->SetPrivate(
true );
1746 for( ; token != T_RIGHT; token = NextTok() )
1748 if( token != T_LEFT )
1749 Expecting( T_LEFT );
1756 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1758 if( token != T_LEFT )
1759 Expecting( T_LEFT );
1766 poly->AddPoint(
parseXY(
true ) );
1775 poly->SetStroke( stroke );
1781 poly->SetFillColor( fill.
m_Color );
1785 Expecting(
"pts, stroke, or fill" );
1789 return poly.release();
1795 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1796 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1801 auto rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE,
LAYER_DEVICE );
1803 rectangle->SetUnit(
m_unit );
1808 if( token == T_private )
1810 rectangle->SetPrivate(
true );
1814 for( ; token != T_RIGHT; token = NextTok() )
1816 if( token != T_LEFT )
1817 Expecting( T_LEFT );
1824 rectangle->SetPosition(
parseXY(
true ) );
1829 rectangle->SetEnd(
parseXY(
true ) );
1835 rectangle->SetStroke( stroke );
1841 rectangle->SetFillColor( fill.
m_Color );
1845 Expecting(
"start, end, stroke, or fill" );
1849 return rectangle.release();
1855 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1856 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1859 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1866 if( token == T_private )
1868 text->SetPrivate(
true );
1872 if( !IsSymbol( token ) )
1874 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1878 text->SetText( FromUTF8() );
1880 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1882 if( token != T_LEFT )
1883 Expecting( T_LEFT );
1901 Expecting(
"at or effects" );
1906 if( !
text->IsVisible() )
1909 return text.release();
1915 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
1916 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
1928 bool foundEnd =
false;
1929 bool foundSize =
false;
1930 bool foundMargins =
false;
1932 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
1934 textBox->SetUnit(
m_unit );
1938 if( token == T_private )
1940 textBox->SetPrivate(
true );
1944 if( !IsSymbol( token ) )
1946 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1950 textBox->SetText( FromUTF8() );
1952 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1954 if( token != T_LEFT )
1955 Expecting( T_LEFT );
1986 textBox->SetStroke( stroke );
1992 textBox->SetFillColor( fill.
m_Color );
1997 textBox->SetMarginLeft(
left );
1998 textBox->SetMarginTop( top );
1999 textBox->SetMarginRight(
right );
2000 textBox->SetMarginBottom( bottom );
2001 foundMargins =
true;
2010 Expecting(
"at, size, stroke, fill or effects" );
2014 textBox->SetPosition( pos );
2017 textBox->SetEnd(
end );
2018 else if( foundSize )
2019 textBox->SetEnd( pos + size );
2021 Expecting(
"size" );
2025 int margin = textBox->GetLegacyTextMargin();
2026 textBox->SetMarginLeft( margin );
2027 textBox->SetMarginTop( margin );
2028 textBox->SetMarginRight( margin );
2029 textBox->SetMarginBottom( margin );
2032 return textBox.release();
2038 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
2039 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
2045 wxString pageType = FromUTF8();
2047 if( !aPageInfo.
SetType( pageType ) )
2049 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
2076 if( token == T_portrait )
2081 else if( token != T_RIGHT )
2083 Expecting(
"portrait" );
2090 wxCHECK_RET( CurTok() == T_title_block,
2091 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
2095 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2097 if( token != T_LEFT )
2098 Expecting( T_LEFT );
2106 aTitleBlock.
SetTitle( FromUTF8() );
2111 aTitleBlock.
SetDate( FromUTF8() );
2126 int commentNumber =
parseInt(
"comment" );
2128 switch( commentNumber )
2177 CurLine(), CurLineNumber(), CurOffset() );
2184 Expecting(
"title, date, rev, company, or comment" );
2194 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2195 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2197 bool is_private =
false;
2199 T token = NextTok();
2201 if( token == T_private )
2207 if( !IsSymbol( token ) )
2209 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2213 wxString
name = FromUTF8();
2215 if(
name.IsEmpty() )
2217 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2223 if( !IsSymbol( token ) )
2225 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2230 wxString value = FromUTF8();
2232 int nextFieldId = 0;
2239 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>(
VECTOR2I( -1, -1 ), nextFieldId,
2241 field->SetText( value );
2242 field->SetVisible(
true );
2243 field->SetPrivate( is_private );
2253 field->SetId( fieldId );
2254 field->SetPrivate(
false );
2265 field->SetId( fieldId );
2266 field->SetPrivate(
false );
2272 if(
name.CmpNoCase( wxT(
"Sheet name" ) ) == 0 )
2274 else if(
name.CmpNoCase( wxT(
"Sheet file" ) ) == 0 )
2278 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2280 if( token != T_LEFT )
2281 Expecting( T_LEFT );
2293 if(
id >= nextFieldId )
2301 field->SetPosition(
parseXY() );
2318 field->SetNameShown( show );
2322 case T_do_not_autoplace:
2325 field->SetCanAutoplace( !doNotAutoplace );
2330 Expecting(
"id, at, hide, show_name, do_not_autoplace or effects" );
2334 return field.release();
2340 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2341 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2342 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2344 T token = NextTok();
2346 if( !IsSymbol( token ) )
2348 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2352 wxString
name = FromUTF8();
2354 if(
name.IsEmpty() )
2356 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2360 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2366 case T_input: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
2367 case T_output: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
2368 case T_bidirectional: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
2369 case T_tri_state: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
2370 case T_passive: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
2372 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2375 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2377 if( token != T_LEFT )
2378 Expecting( T_LEFT );
2386 sheetPin->SetPosition(
parseXY() );
2388 double angle =
parseDouble(
"sheet pin angle (side)" );
2391 sheetPin->SetSide( SHEET_SIDE::RIGHT );
2392 else if( angle == 90.0 )
2393 sheetPin->SetSide( SHEET_SIDE::TOP );
2394 else if( angle == 180.0 )
2395 sheetPin->SetSide( SHEET_SIDE::LEFT );
2396 else if( angle == 270.0 )
2397 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
2399 Expecting(
"0, 90, 180, or 270" );
2416 Expecting(
"at, uuid or effects" );
2420 return sheetPin.release();
2426 wxCHECK_RET( CurTok() == T_sheet_instances,
2427 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2428 wxCHECK( aScreen, );
2432 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2434 if( token != T_LEFT )
2435 Expecting( T_LEFT );
2453 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2455 if( token != T_LEFT )
2456 Expecting( T_LEFT );
2460 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2463 size_t numReplacements = 0;
2481 for(
const wxString& ch : whitespaces )
2482 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2487 if( numReplacements > 0 )
2494 Expecting(
"path or page" );
2499 && ( instance.
m_Path.empty() ) )
2515 Expecting(
"path" );
2523 wxCHECK_RET( CurTok() == T_symbol_instances,
2524 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2525 wxCHECK( aScreen, );
2530 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2532 if( token != T_LEFT )
2533 Expecting( T_LEFT );
2550 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2552 if( token != T_LEFT )
2553 Expecting( T_LEFT );
2572 instance.
m_Value = FromUTF8();
2583 Expecting(
"path, unit, value or footprint" );
2592 Expecting(
"path" );
2601 wxCHECK( aSheet !=
nullptr, );
2605 wxCHECK( screen !=
nullptr, );
2607 if( aIsCopyableOnly )
2610 bool fileHasUuid =
false;
2624 if( !aIsCopyableOnly )
2629 if( CurTok() != T_kicad_sch )
2630 Expecting(
"kicad_sch" );
2646 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2648 if( aIsCopyableOnly && token == T_EOF )
2651 if( token != T_LEFT )
2652 Expecting( T_LEFT );
2682 case T_generator_version:
2708 if( aIsCopyableOnly )
2709 Unexpected( T_paper );
2719 if( aIsCopyableOnly )
2720 Unexpected( T_page );
2724 NeedSYMBOLorNUMBER();
2725 NeedSYMBOLorNUMBER();
2732 if( aIsCopyableOnly )
2733 Unexpected( T_title_block );
2747 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2749 if( token != T_LEFT )
2750 Expecting( T_LEFT );
2763 Expecting(
"symbol" );
2864 case T_netclass_flag:
2869 case T_global_label:
2870 case T_hierarchical_label:
2871 case T_directive_label:
2883 case T_sheet_instances:
2887 case T_symbol_instances:
2892 if( aIsCopyableOnly )
2893 Unexpected( T_bus_alias );
2898 case T_embedded_fonts:
2904 CurLineNumber(), CurOffset() );
2911 case T_embedded_files:
2917 CurLineNumber(), CurOffset() );
2920 embeddedFilesParser.SyncLineReaderWith( *
this );
2928 wxLogError( e.
What() );
2931 SyncLineReaderWith( embeddedFilesParser );
2937 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
2938 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
2939 "sheet, symbol, symbol_instances, text, title_block" );
2958 CurLineNumber(), CurOffset() );
2962 std::vector<std::string> fontNames;
2963 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
2973 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
2974 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
2979 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2981 std::set<int> fieldIDsRead;
2994 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2996 if( token != T_LEFT )
2997 Expecting( T_LEFT );
3009 if( !IsSymbol( token ) )
3012 CurLineNumber(), CurOffset() );
3015 libName = FromUTF8();
3019 libName.Replace(
"{slash}",
"/" );
3029 if( !IsSymbol( token ) && token != T_NUMBER )
3030 Expecting(
"symbol|number" );
3033 wxString
name = FromUTF8();
3037 name.Replace(
"{slash}",
"/" );
3043 if(
static_cast<int>(
name.size() ) > bad_pos )
3045 wxString msg = wxString::Format(
3046 _(
"Symbol %s contains invalid character '%c'" ),
name,
3053 CurLineNumber(), CurOffset() );
3056 symbol->SetLibId( libId );
3062 symbol->SetPosition(
parseXY() );
3064 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3067 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3068 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3069 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3070 default: Expecting(
"0, 90, 180, or 270" );
3073 symbol->SetTransform( transform );
3082 else if( token == T_y )
3085 Expecting(
"x or y" );
3091 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3098 symbol->SetBodyStyleUnconditional(
parseInt(
"symbol body style" ) );
3102 case T_exclude_from_sim:
3103 symbol->SetExcludedFromSim(
parseBool() );
3108 symbol->SetExcludedFromBOM( !
parseBool() );
3113 symbol->SetExcludedFromBoard( !
parseBool() );
3122 case T_fields_autoplaced:
3134 case T_default_instance:
3138 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3140 if( token != T_LEFT )
3141 Expecting( T_LEFT );
3160 symbol->SetValueFieldText( FromUTF8() );
3166 symbol->SetFootprintFieldText( FromUTF8() );
3171 Expecting(
"reference, unit, value or footprint" );
3180 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3182 if( token != T_LEFT )
3183 Expecting( T_LEFT );
3187 if( token != T_project )
3188 Expecting(
"project" );
3192 wxString projectName = FromUTF8();
3194 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3196 if( token != T_LEFT )
3197 Expecting( T_LEFT );
3201 if( token != T_path )
3202 Expecting(
"path" );
3211 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3213 if( token != T_LEFT )
3214 Expecting( T_LEFT );
3233 symbol->SetValueFieldText( FromUTF8() );
3239 symbol->SetFootprintFieldText( FromUTF8() );
3244 Expecting(
"reference, unit, value or footprint" );
3247 symbol->AddHierarchicalReference( instance );
3264 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3271 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3277 int nextAvailableId = field->
GetId() + 1;
3280 nextAvailableId += 1;
3282 field->
SetId( nextAvailableId );
3285 if( symbol->GetFieldById( field->
GetId() ) )
3286 *symbol->GetFieldById( field->
GetId() ) = *field;
3288 symbol->AddField( *field );
3291 symbol->UpdatePrefix();
3306 number = FromUTF8();
3308 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3310 if( token != T_LEFT )
3311 Expecting( T_LEFT );
3335 Expecting(
"alternate or uuid" );
3339 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3345 Expecting(
"lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
3346 "default_instance, property, pin, or instances" );
3350 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3351 symbol->SetSchSymbolLibraryName( libName );
3354 symbol->ClearFlags();
3356 return symbol.release();
3362 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3363 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3366 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3369 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3371 if( token != T_LEFT )
3372 Expecting( T_LEFT );
3379 bitmap->SetPosition(
parseXY() );
3405 data.reserve( 1 << 17 );
3407 while( token != T_RIGHT )
3409 if( !IsSymbol( token ) )
3410 Expecting(
"base64 image data" );
3416 wxMemoryBuffer buffer = wxBase64Decode( data );
3425 Expecting(
"at, scale, uuid or data" );
3438 return bitmap.release();
3444 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3445 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3451 std::vector<SCH_FIELD> fields;
3452 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3453 std::set<int> fieldIDsRead;
3458 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3460 if( token != T_LEFT )
3461 Expecting( T_LEFT );
3468 sheet->SetPosition(
parseXY() );
3477 sheet->SetSize( size );
3482 case T_exclude_from_sim:
3483 sheet->SetExcludedFromSim(
parseBool() );
3488 sheet->SetExcludedFromBOM( !
parseBool() );
3493 sheet->SetExcludedFromBoard( !
parseBool() );
3502 case T_fields_autoplaced:
3510 sheet->SetBorderWidth( stroke.
GetWidth() );
3511 sheet->SetBorderColor( stroke.
GetColor() );
3516 sheet->SetBackgroundColor( fill.
m_Color );
3533 if( fields.empty() )
3547 if( field->
GetId() < 0 )
3550 while( !fieldIDsRead.insert( field->
GetId() ).second )
3553 fields.emplace_back( *field );
3564 std::vector<SCH_SHEET_INSTANCE> instances;
3566 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3568 if( token != T_LEFT )
3569 Expecting( T_LEFT );
3573 if( token != T_project )
3574 Expecting(
"project" );
3578 wxString projectName = FromUTF8();
3580 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3582 if( token != T_LEFT )
3583 Expecting( T_LEFT );
3587 if( token != T_path )
3588 Expecting(
"path" );
3597 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3599 if( token != T_LEFT )
3600 Expecting( T_LEFT );
3620 static std::vector<wxString> whitespaces =
3626 for( wxString ch : whitespaces )
3635 Expecting(
"page" );
3639 instances.emplace_back( instance );
3643 sheet->setInstances( instances );
3648 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3652 sheet->SetFields( fields );
3654 return sheet.release();
3660 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3661 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3664 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3666 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3668 if( token != T_LEFT )
3669 Expecting( T_LEFT );
3676 junction->SetPosition(
parseXY() );
3694 junction->SetColor(
color );
3706 Expecting(
"at, diameter, color or uuid" );
3710 return junction.release();
3716 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3717 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3720 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3722 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3724 if( token != T_LEFT )
3725 Expecting( T_LEFT );
3732 no_connect->SetPosition(
parseXY() );
3743 Expecting(
"at or uuid" );
3747 return no_connect.release();
3753 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3754 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3758 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3760 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3762 if( token != T_LEFT )
3763 Expecting( T_LEFT );
3770 busEntry->SetPosition(
parseXY() );
3780 busEntry->SetSize( size );
3787 busEntry->SetStroke( stroke );
3797 Expecting(
"at, size, uuid or stroke" );
3801 return busEntry.release();
3821 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_NOTES );
3823 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3825 if( token != T_LEFT )
3826 Expecting( T_LEFT );
3833 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3835 if( token != T_LEFT )
3836 Expecting( T_LEFT );
3843 polyline->AddPoint(
parseXY() );
3856 polyline->SetStroke( stroke );
3862 polyline->SetFillColor( fill.
m_Color );
3873 Expecting(
"pts, uuid, stroke, or fill" );
3877 return polyline.release();
3896 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3899 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3901 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3903 if( token != T_LEFT )
3904 Expecting( T_LEFT );
3917 line->SetStartPoint(
parseXY() );
3925 line->SetEndPoint(
parseXY() );
3932 line->SetStroke( stroke );
3942 Expecting(
"at, uuid or stroke" );
3946 return line.release();
3952 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
3953 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
3961 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
3963 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3965 if( token != T_LEFT )
3966 Expecting( T_LEFT );
3989 arc->SetStroke( stroke );
3995 arc->SetFillColor( fill.
m_Color );
4001 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
4006 Expecting(
"start, mid, end, stroke, fill or uuid" );
4010 arc->SetArcGeometry( startPoint, midPoint, endPoint );
4012 return arc.release();
4018 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
4019 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4026 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
4028 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4030 if( token != T_LEFT )
4031 Expecting( T_LEFT );
4049 circle->SetStroke( stroke );
4055 circle->SetFillColor( fill.
m_Color );
4061 const_cast<KIID&
>( circle->m_Uuid ) =
KIID( FromUTF8() );
4066 Expecting(
"center, radius, stroke, fill or uuid" );
4070 circle->SetCenter(
center );
4073 return circle.release();
4079 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4080 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4085 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
4087 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4089 if( token != T_LEFT )
4090 Expecting( T_LEFT );
4097 rectangle->SetPosition(
parseXY() );
4102 rectangle->SetEnd(
parseXY() );
4108 rectangle->SetStroke( stroke );
4114 rectangle->SetFillColor( fill.
m_Color );
4120 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4125 Expecting(
"start, end, stroke, fill or uuid" );
4129 return rectangle.release();
4135 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4136 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4141 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4143 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4145 if( token != T_LEFT )
4146 Expecting( T_LEFT );
4160 ruleArea->SetPolyShape( sch_rule_poly );
4162 ruleArea->SetStroke( poly->GetStroke() );
4163 ruleArea->SetFillMode( poly->GetFillMode() );
4164 ruleArea->SetFillColor( poly->GetFillColor() );
4168 Expecting(
"polyline" );
4172 return ruleArea.release();
4178 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4179 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4184 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
4186 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4188 if( token != T_LEFT )
4189 Expecting( T_LEFT );
4199 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4201 if( token != T_LEFT )
4202 Expecting( T_LEFT );
4211 case 0: bezier->SetStart(
parseXY() );
break;
4212 case 1: bezier->SetBezierC1(
parseXY() );
break;
4213 case 2: bezier->SetBezierC2(
parseXY() );
break;
4214 case 3: bezier->SetEnd(
parseXY() );
break;
4215 default: Unexpected(
"control point" );
break;
4225 bezier->SetStroke( stroke );
4231 bezier->SetFillColor( fill.
m_Color );
4237 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4242 Expecting(
"pts, stroke, fill or uuid" );
4246 bezier->RebuildBezierToSegmentsPointsList( bezier->GetPenWidth() / 2 );
4248 return bezier.release();
4255 std::unique_ptr<SCH_TEXT>
text;
4259 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4260 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4261 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4262 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4263 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4264 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4266 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4274 text->SetText( FromUTF8() );
4276 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4278 if( token != T_LEFT )
4279 Expecting( T_LEFT );
4285 case T_exclude_from_sim:
4296 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4312 Unexpected( T_shape );
4320 case T_input: label->
SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
4321 case T_output: label->
SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
4322 case T_bidirectional: label->
SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
4323 case T_tri_state: label->
SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
4324 case T_passive: label->
SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
4325 case T_dot: label->
SetShape( LABEL_FLAG_SHAPE::F_DOT );
break;
4326 case T_round: label->
SetShape( LABEL_FLAG_SHAPE::F_ROUND );
break;
4327 case T_diamond: label->
SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
break;
4328 case T_rectangle: label->
SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
break;
4330 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4341 Unexpected( T_length );
4350 case T_fields_autoplaced:
4360 text->SetVisible(
true );
4385 Unexpected( T_property );
4412 Expecting(
"at, shape, iref, uuid or effects" );
4418 if( label && label->
GetFields().empty() )
4421 return text.release();
4427 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4428 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4430 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4434 return textBox.release();
4440 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4441 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4443 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4447 return cell.release();
4463 bool foundEnd =
false;
4464 bool foundSize =
false;
4465 bool foundMargins =
false;
4469 aTextBox->
SetText( FromUTF8() );
4471 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4473 if( token != T_LEFT )
4474 Expecting( T_LEFT );
4480 case T_exclude_from_sim:
4511 cell->SetColSpan(
parseInt(
"column span" ) );
4512 cell->SetRowSpan(
parseInt(
"row span" ) );
4516 Expecting(
"at, size, stroke, fill, effects or uuid" );
4540 foundMargins =
true;
4556 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4558 Expecting(
"at, size, stroke, fill, effects or uuid" );
4566 else if( foundSize )
4567 aTextBox->
SetEnd( pos + size );
4569 Expecting(
"size" );
4584 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4585 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4589 STROKE_PARAMS borderStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4590 STROKE_PARAMS separatorsStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4591 std::unique_ptr<SCH_TABLE>
table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4593 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4595 if( token != T_LEFT )
4596 Expecting( T_LEFT );
4602 case T_column_count:
4607 case T_column_widths:
4611 while( ( token = NextTok() ) != T_RIGHT )
4621 while( ( token = NextTok() ) != T_RIGHT )
4628 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4630 if( token != T_LEFT )
4631 Expecting( T_LEFT );
4635 if( token != T_table_cell )
4636 Expecting(
"table_cell" );
4644 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4646 if( token != T_LEFT )
4647 Expecting( T_LEFT );
4665 table->SetBorderStroke( borderStroke );
4669 Expecting(
"external, header or stroke" );
4677 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4679 if( token != T_LEFT )
4680 Expecting( T_LEFT );
4698 table->SetSeparatorsStroke( separatorsStroke );
4702 Expecting(
"rows, cols, or stroke" );
4710 Expecting(
"columns, col_widths, row_heights, border, separators, header or cells" );
4714 return table.release();
4720 wxCHECK_RET( CurTok() == T_bus_alias,
4721 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4722 wxCHECK( aScreen, );
4725 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4736 busAlias->SetName( alias );
4741 if( token != T_members )
4742 Expecting(
"members" );
4746 while( token != T_RIGHT )
4748 if( !IsSymbol( token ) )
4749 Expecting(
"quoted string" );
4751 member = FromUTF8();
4756 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.
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction) override
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()
SCH_ITEM * parseSymbolText()
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)
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.
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslated)
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
@ 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)
@ SHEET_MANDATORY_FIELD_COUNT
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
#define SHEET_MANDATORY_FIELDS
#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_FIELD_COUNT
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT, LIB_PART, and FOOTPRINT constru...
@ 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