31#include <fmt/format.h>
35#include <wx/mstream.h>
36#include <wx/tokenzr.h>
69using namespace TSCHEMATIC_T;
74 unsigned aLineCount,
SCH_SHEET* aRootSheet,
76 SCHEMATIC_LEXER( aLineReader ),
77 m_requiredVersion( 0 ),
80 m_appending( aIsAppending ),
81 m_progressReporter( aProgressReporter ),
82 m_lineReader( aLineReader ),
83 m_lastProgressLine( 0 ),
84 m_lineCount( aLineCount ),
85 m_rootSheet( aRootSheet )
92 const unsigned PROGRESS_DELTA = 500;
114 KIID id( FromUTF8() );
131 else if( token == T_no )
134 Expecting(
"yes or no" );
145 bool ret = aDefaultValue;
147 if( PrevTok() == T_LEFT )
152 if(
static_cast<int>( token ) ==
DSN_RIGHT )
153 return aDefaultValue;
157 else if( token == T_no )
160 Expecting(
"yes or no" );
167 return aDefaultValue;
182 bool versionChecked =
false;
193 versionChecked =
true;
196 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
198 if( token != T_LEFT )
224 case T_generator_version:
244 aSymbolLibMap[symbol->
GetName()] = symbol;
249 Expecting(
"symbol, generator, or generator_version" );
263 if( CurTok() == T_LEFT )
267 if( CurTok() == T_symbol )
274 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
275 GetTokenString( CurTok() ) );
283 std::get<2>( params ),
293 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
294 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
300 wxString unitDisplayName;
302 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
304 symbol->SetUnitCount( 1 );
316 if( !IsSymbol( token ) )
318 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(),
327 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
334 if(
static_cast<int>(
name.size() ) > bad_pos )
336 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
345 CurLineNumber(), CurOffset() );
350 symbol->SetLibId(
id );
352 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
354 if( token != T_LEFT )
373 if( token != T_hide )
376 symbol->SetShowPinNumbers(
false );
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 return symbol.release();
597 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
611 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
613 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
621 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
623 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
630 strokeParser.SyncLineReaderWith( *
this );
633 SyncLineReaderWith( strokeParser );
639 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
642 aFill.
m_Color = COLOR4D::UNSPECIFIED;
646 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
648 if( token != T_LEFT )
661 case T_none: aFill.
m_FillType = FILL_T::NO_FILL;
break;
662 case T_outline: aFill.
m_FillType = FILL_T::FILLED_SHAPE;
break;
663 case T_background: aFill.
m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR;
break;
664 case T_color: aFill.
m_FillType = FILL_T::FILLED_WITH_COLOR;
break;
665 default: Expecting(
"none, outline, color or background" );
686 Expecting(
"type or color" );
693 bool aEnforceMinTextSize )
695 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
696 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
714 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
716 if( token == T_LEFT )
722 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
724 if( token == T_LEFT )
731 faceName = FromUTF8();
775 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
779 if( !faceName.IsEmpty() )
785 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
794 case T_mirror:
break;
795 default: Expecting(
"left, right, top, bottom, or mirror" );
804 wxString hyperlink = FromUTF8();
809 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
828 Expecting(
"font, justify, hide or href" );
836 wxCHECK_RET( CurTok() == aHeaderType,
837 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
843 if( tok == T_version )
857 wxCHECK_RET( CurTok() == T_pin_names,
858 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
862 if( token == T_LEFT )
866 if( token != T_offset )
867 Expecting(
"offset" );
874 if( token == T_hide )
876 aSymbol->SetShowPinNames(
false );
879 else if( token != T_RIGHT )
882 CurLineNumber(), CurOffset() );
889 wxCHECK_MSG( CurTok() == T_property,
nullptr,
890 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
891 wxCHECK( aSymbol,
nullptr );
895 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(),
MANDATORY_FIELDS );
899 field->SetVisible(
true );
903 if( !IsSymbol( token ) )
905 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
913 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
917 field->SetName(
name );
932 if( !IsSymbol( token ) )
934 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
941 field->SetText( value );
943 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
945 if( token != T_LEFT )
966 field->SetPosition(
parseXY(
true ) );
978 field->SetNameShown( show );
982 case T_do_not_autoplace:
985 field->SetCanAutoplace( !doNotAutoplace );
990 Expecting(
"id, at, show_name, do_not_autoplace, or effects" );
998 int nextAvailableId = field->GetId() + 1;
1001 nextAvailableId += 1;
1003 field->SetId( nextAvailableId );
1008 if( field->IsMandatory() )
1010 existingField = aSymbol->GetFieldById( field->GetId() );
1012 *existingField = *field;
1014 return existingField;
1016 else if(
name ==
"ki_keywords" )
1019 aSymbol->SetKeyWords( value );
1023 else if(
name ==
"ki_description" )
1025 aSymbol->SetDescription( value );
1028 else if(
name ==
"ki_fp_filters" )
1031 wxArrayString filters;
1032 wxStringTokenizer tokenizer( value );
1034 while( tokenizer.HasMoreTokens() )
1036 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1037 filters.Add( curr_token );
1040 aSymbol->SetFPFilters( filters );
1043 else if(
name ==
"ki_locked" )
1047 aSymbol->LockUnits(
true );
1053 existingField = aSymbol->FindField( field->GetCanonicalName() );
1064 for(
int ii = 1; ii < 10 && existingField; ii++ )
1066 wxString newname = base_name;
1067 newname <<
'_' << ii;
1069 existingField = aSymbol->FindField( newname );
1071 if( !existingField )
1072 field->SetName( newname );
1076 if( !existingField )
1078 aSymbol->AddDrawItem( field.get(),
false );
1080 return field.release();
1093 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1094 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1100 bool hasMidPoint =
false;
1108 bool hasAngles =
false;
1110 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC,
LAYER_DEVICE );
1117 if( token == T_private )
1119 arc->SetPrivate(
true );
1123 for( ; token != T_RIGHT; token = NextTok() )
1125 if( token != T_LEFT )
1126 Expecting( T_LEFT );
1149 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1151 if( token != T_LEFT )
1152 Expecting( T_LEFT );
1180 Expecting(
"at, length, or angles" );
1188 arc->SetStroke( stroke );
1194 arc->SetFillColor( fill.
m_Color );
1198 Expecting(
"start, mid, end, radius, stroke, or fill" );
1204 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1215 EDA_ANGLE arc_start, arc_end, arc_angle;
1216 arc->CalcArcAngles( arc_start, arc_end );
1217 arc_angle = arc_end - arc_start;
1222 arc->SetStart( endPoint );
1223 arc->SetEnd( startPoint );
1226 arc->SetCenter( new_center );
1232 arc->SetCenter( new_center );
1236 else if( hasAngles )
1238 arc->SetCenter( center );
1244 arc->SetStart( endPoint );
1245 arc->SetEnd( startPoint );
1249 EDA_ANGLE arc_start, arc_end, arc_angle;
1250 arc->CalcArcAngles( arc_start, arc_end );
1251 arc_angle = arc_end - arc_start;
1257 arc->SetStart( startPoint );
1258 arc->SetEnd( endPoint );
1262 arc->SetStart( startPoint );
1263 arc->SetEnd( endPoint );
1266 arc->SetCenter( new_center );
1271 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1274 return arc.release();
1280 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1281 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1287 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER,
LAYER_DEVICE );
1289 bezier->SetUnit(
m_unit );
1294 if( token == T_private )
1296 bezier->SetPrivate(
true );
1300 for( ; token != T_RIGHT; token = NextTok() )
1302 if( token != T_LEFT )
1303 Expecting( T_LEFT );
1313 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1315 if( token != T_LEFT )
1316 Expecting( T_LEFT );
1325 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1326 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1327 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1328 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1329 default: Unexpected(
"control point" );
break;
1339 bezier->SetStroke( stroke );
1345 bezier->SetFillColor( fill.
m_Color );
1349 Expecting(
"pts, stroke, or fill" );
1353 bezier->RebuildBezierToSegmentsPointsList( bezier->GetPenWidth() / 2 );
1355 return bezier.release();
1361 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1362 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1370 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE,
LAYER_DEVICE );
1372 circle->SetUnit(
m_unit );
1377 if( token == T_private )
1379 circle->SetPrivate(
true );
1383 for( ; token != T_RIGHT; token = NextTok() )
1385 if( token != T_LEFT )
1386 Expecting( T_LEFT );
1404 circle->SetStroke( stroke );
1410 circle->SetFillColor( fill.
m_Color );
1414 Expecting(
"center, radius, stroke, or fill" );
1418 circle->SetCenter( center );
1419 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
1421 return circle.release();
1432 case T_input:
return ELECTRICAL_PINTYPE::PT_INPUT;
1433 case T_output:
return ELECTRICAL_PINTYPE::PT_OUTPUT;
1434 case T_bidirectional:
return ELECTRICAL_PINTYPE::PT_BIDI;
1435 case T_tri_state:
return ELECTRICAL_PINTYPE::PT_TRISTATE;
1436 case T_passive:
return ELECTRICAL_PINTYPE::PT_PASSIVE;
1437 case T_unspecified:
return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1438 case T_power_in:
return ELECTRICAL_PINTYPE::PT_POWER_IN;
1439 case T_power_out:
return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1440 case T_open_collector:
return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1441 case T_open_emitter:
return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1443 case T_no_connect:
return ELECTRICAL_PINTYPE::PT_NC;
1444 case T_free:
return ELECTRICAL_PINTYPE::PT_NIC;
1447 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1448 "power_in, power_out, open_collector, open_emitter, free or "
1450 return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1459 case T_line:
return GRAPHIC_PINSHAPE::LINE;
1460 case T_inverted:
return GRAPHIC_PINSHAPE::INVERTED;
1461 case T_clock:
return GRAPHIC_PINSHAPE::CLOCK;
1462 case T_inverted_clock:
return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1463 case T_input_low:
return GRAPHIC_PINSHAPE::INPUT_LOW;
1464 case T_clock_low:
return GRAPHIC_PINSHAPE::CLOCK_LOW;
1465 case T_output_low:
return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1466 case T_edge_clock_high:
return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1467 case T_non_logic:
return GRAPHIC_PINSHAPE::NONLOGIC;
1470 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1471 "output_low, edge_clock_high, non_logic" );
1472 return GRAPHIC_PINSHAPE::LINE;
1476 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1477 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1482 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1489 pin->SetType( parseType( token ) );
1493 pin->SetShape( parseShape( token ) );
1495 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1497 if( token == T_hide )
1499 pin->SetVisible(
false );
1503 if( token != T_LEFT )
1504 Expecting( T_LEFT );
1513 switch(
parseInt(
"pin orientation" ) )
1515 case 0:
pin->SetOrientation( PIN_ORIENTATION::PIN_RIGHT );
break;
1516 case 90:
pin->SetOrientation( PIN_ORIENTATION::PIN_UP );
break;
1517 case 180:
pin->SetOrientation( PIN_ORIENTATION::PIN_LEFT );
break;
1518 case 270:
pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
break;
1519 default: Expecting(
"0, 90, 180, or 270" );
1533 if( !IsSymbol( token ) )
1542 pin->SetName( FromUTF8() );
1546 if( token != T_RIGHT )
1550 if( token == T_effects )
1557 pin->SetNameTextSize(
text.GetTextHeight() );
1562 Expecting(
"effects" );
1571 if( !IsSymbol( token ) )
1574 CurLineNumber(), CurOffset() );
1577 pin->SetNumber( FromUTF8() );
1580 if( token != T_RIGHT )
1584 if( token == T_effects )
1591 pin->SetNumberTextSize(
text.GetTextHeight() );
1596 Expecting(
"effects" );
1608 if( !IsSymbol( token ) )
1611 CurLineNumber(), CurOffset() );
1617 alt.
m_Type = parseType( token );
1620 alt.
m_Shape = parseShape( token );
1622 pin->GetAlternates()[ alt.
m_Name ] = alt;
1629 Expecting(
"at, name, number, length, or alternate" );
1633 return pin.release();
1639 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1640 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1645 std::unique_ptr<SCH_SHAPE> poly = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_DEVICE );
1652 if( token == T_private )
1654 poly->SetPrivate(
true );
1658 for( ; token != T_RIGHT; token = NextTok() )
1660 if( token != T_LEFT )
1661 Expecting( T_LEFT );
1668 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1670 if( token != T_LEFT )
1671 Expecting( T_LEFT );
1678 poly->AddPoint(
parseXY(
true ) );
1687 poly->SetStroke( stroke );
1693 poly->SetFillColor( fill.
m_Color );
1697 Expecting(
"pts, stroke, or fill" );
1701 return poly.release();
1707 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1708 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1713 auto rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE,
LAYER_DEVICE );
1715 rectangle->SetUnit(
m_unit );
1720 if( token == T_private )
1722 rectangle->SetPrivate(
true );
1726 for( ; token != T_RIGHT; token = NextTok() )
1728 if( token != T_LEFT )
1729 Expecting( T_LEFT );
1736 rectangle->SetPosition(
parseXY(
true ) );
1741 rectangle->SetEnd(
parseXY(
true ) );
1747 rectangle->SetStroke( stroke );
1753 rectangle->SetFillColor( fill.
m_Color );
1757 Expecting(
"start, end, stroke, or fill" );
1761 return rectangle.release();
1767 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1768 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1771 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1778 if( token == T_private )
1780 text->SetPrivate(
true );
1784 if( !IsSymbol( token ) )
1786 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1790 text->SetText( FromUTF8() );
1792 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1794 if( token != T_LEFT )
1795 Expecting( T_LEFT );
1813 Expecting(
"at or effects" );
1817 return text.release();
1823 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
1824 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
1836 bool foundEnd =
false;
1837 bool foundSize =
false;
1838 bool foundMargins =
false;
1840 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
1842 textBox->SetUnit(
m_unit );
1846 if( token == T_private )
1848 textBox->SetPrivate(
true );
1852 if( !IsSymbol( token ) )
1854 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1858 textBox->SetText( FromUTF8() );
1860 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1862 if( token != T_LEFT )
1863 Expecting( T_LEFT );
1894 textBox->SetStroke( stroke );
1900 textBox->SetFillColor( fill.
m_Color );
1905 textBox->SetMarginLeft(
left );
1906 textBox->SetMarginTop( top );
1907 textBox->SetMarginRight(
right );
1908 textBox->SetMarginBottom( bottom );
1909 foundMargins =
true;
1918 Expecting(
"at, size, stroke, fill or effects" );
1922 textBox->SetPosition( pos );
1925 textBox->SetEnd( end );
1926 else if( foundSize )
1927 textBox->SetEnd( pos + size );
1929 Expecting(
"size" );
1933 int margin = textBox->GetLegacyTextMargin();
1934 textBox->SetMarginLeft( margin );
1935 textBox->SetMarginTop( margin );
1936 textBox->SetMarginRight( margin );
1937 textBox->SetMarginBottom( margin );
1940 return textBox.release();
1946 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
1947 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1953 wxString pageType = FromUTF8();
1955 if( !aPageInfo.
SetType( pageType ) )
1957 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
1984 if( token == T_portrait )
1989 else if( token != T_RIGHT )
1991 Expecting(
"portrait" );
1998 wxCHECK_RET( CurTok() == T_title_block,
1999 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
2003 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2005 if( token != T_LEFT )
2006 Expecting( T_LEFT );
2014 aTitleBlock.
SetTitle( FromUTF8() );
2019 aTitleBlock.
SetDate( FromUTF8() );
2034 int commentNumber =
parseInt(
"comment" );
2036 switch( commentNumber )
2085 CurLine(), CurLineNumber(), CurOffset() );
2092 Expecting(
"title, date, rev, company, or comment" );
2102 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2103 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2105 T token = NextTok();
2107 if( !IsSymbol( token ) )
2109 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2113 wxString
name = FromUTF8();
2115 if(
name.IsEmpty() )
2117 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2123 if( !IsSymbol( token ) )
2125 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2130 wxString value = FromUTF8();
2132 int mandatoryFieldCount = 0;
2139 std::unique_ptr<SCH_FIELD> field =
2140 std::make_unique<SCH_FIELD>(
VECTOR2I( -1, -1 ), mandatoryFieldCount, aParent,
name );
2141 field->SetText( value );
2142 field->SetVisible(
true );
2167 else if( !
name.CmpNoCase( wxT(
"Sheet name" ) ) )
2172 else if( !
name.CmpNoCase( wxT(
"Sheet file" ) ) )
2180 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2182 if( token != T_LEFT )
2183 Expecting( T_LEFT );
2194 if(
id >= mandatoryFieldCount )
2201 field->SetPosition(
parseXY() );
2213 field->SetNameShown( show );
2217 case T_do_not_autoplace:
2220 field->SetCanAutoplace( !doNotAutoplace );
2225 Expecting(
"id, at, show_name, do_not_autoplace or effects" );
2229 return field.release();
2235 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2236 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2237 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2239 T token = NextTok();
2241 if( !IsSymbol( token ) )
2243 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2247 wxString
name = FromUTF8();
2249 if(
name.IsEmpty() )
2251 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2255 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2261 case T_input: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
2262 case T_output: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
2263 case T_bidirectional: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
2264 case T_tri_state: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
2265 case T_passive: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
2267 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2270 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2272 if( token != T_LEFT )
2273 Expecting( T_LEFT );
2281 sheetPin->SetPosition(
parseXY() );
2283 double angle =
parseDouble(
"sheet pin angle (side)" );
2286 sheetPin->SetSide( SHEET_SIDE::RIGHT );
2287 else if( angle == 90.0 )
2288 sheetPin->SetSide( SHEET_SIDE::TOP );
2289 else if( angle == 180.0 )
2290 sheetPin->SetSide( SHEET_SIDE::LEFT );
2291 else if( angle == 270.0 )
2292 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
2294 Expecting(
"0, 90, 180, or 270" );
2311 Expecting(
"at, uuid or effects" );
2315 return sheetPin.release();
2321 wxCHECK_RET( CurTok() == T_sheet_instances,
2322 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2323 wxCHECK( aScreen, );
2327 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2329 if( token != T_LEFT )
2330 Expecting( T_LEFT );
2348 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2350 if( token != T_LEFT )
2351 Expecting( T_LEFT );
2355 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2358 size_t numReplacements = 0;
2376 for(
const wxString& ch : whitespaces )
2377 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2382 if( numReplacements > 0 )
2389 Expecting(
"path or page" );
2394 && ( instance.
m_Path.empty() ) )
2410 Expecting(
"path" );
2418 wxCHECK_RET( CurTok() == T_symbol_instances,
2419 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2420 wxCHECK( aScreen, );
2425 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2427 if( token != T_LEFT )
2428 Expecting( T_LEFT );
2445 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2447 if( token != T_LEFT )
2448 Expecting( T_LEFT );
2467 instance.
m_Value = FromUTF8();
2478 Expecting(
"path, unit, value or footprint" );
2487 Expecting(
"path" );
2496 wxCHECK( aSheet !=
nullptr, );
2500 wxCHECK( screen !=
nullptr, );
2502 if( aIsCopyableOnly )
2505 bool fileHasUuid =
false;
2519 if( !aIsCopyableOnly )
2524 if( CurTok() != T_kicad_sch )
2525 Expecting(
"kicad_sch" );
2541 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2543 if( aIsCopyableOnly && token == T_EOF )
2546 if( token != T_LEFT )
2547 Expecting( T_LEFT );
2577 case T_generator_version:
2603 if( aIsCopyableOnly )
2604 Unexpected( T_paper );
2614 if( aIsCopyableOnly )
2615 Unexpected( T_page );
2619 NeedSYMBOLorNUMBER();
2620 NeedSYMBOLorNUMBER();
2627 if( aIsCopyableOnly )
2628 Unexpected( T_title_block );
2642 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2644 if( token != T_LEFT )
2645 Expecting( T_LEFT );
2658 Expecting(
"symbol" );
2759 case T_netclass_flag:
2764 case T_global_label:
2765 case T_hierarchical_label:
2766 case T_directive_label:
2778 case T_sheet_instances:
2782 case T_symbol_instances:
2787 if( aIsCopyableOnly )
2788 Unexpected( T_bus_alias );
2793 case T_embedded_fonts:
2799 CurLineNumber(), CurOffset() );
2806 case T_embedded_files:
2812 CurLineNumber(), CurOffset() );
2815 embeddedFilesParser.SyncLineReaderWith( *
this );
2823 wxLogError( e.
What() );
2826 SyncLineReaderWith( embeddedFilesParser );
2832 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
2833 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
2834 "sheet, symbol, symbol_instances, text, title_block" );
2853 CurLineNumber(), CurOffset() );
2858 std::get<2>( params ),
2864 std::vector<std::string> fontNames;
2865 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
2875 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
2876 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
2881 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2883 std::set<int> fieldIDsRead;
2886 symbol->ClearFieldsAutoplaced();
2896 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2898 if( token != T_LEFT )
2899 Expecting( T_LEFT );
2911 if( !IsSymbol( token ) )
2914 CurLineNumber(), CurOffset() );
2917 libName = FromUTF8();
2921 libName.Replace(
"{slash}",
"/" );
2931 if( !IsSymbol( token ) && token != T_NUMBER )
2932 Expecting(
"symbol|number" );
2935 wxString
name = FromUTF8();
2939 name.Replace(
"{slash}",
"/" );
2945 if(
static_cast<int>(
name.size() ) > bad_pos )
2947 wxString msg = wxString::Format(
2948 _(
"Symbol %s contains invalid character '%c'" ),
name,
2955 CurLineNumber(), CurOffset() );
2958 symbol->SetLibId( libId );
2964 symbol->SetPosition(
parseXY() );
2966 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
2969 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
2970 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
2971 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
2972 default: Expecting(
"0, 90, 180, or 270" );
2975 symbol->SetTransform( transform );
2984 else if( token == T_y )
2987 Expecting(
"x or y" );
2993 symbol->SetUnit(
parseInt(
"symbol unit" ) );
2998 symbol->SetBodyStyle(
parseInt(
"symbol body style" ) );
3002 case T_exclude_from_sim:
3003 symbol->SetExcludedFromSim(
parseBool() );
3008 symbol->SetExcludedFromBOM( !
parseBool() );
3013 symbol->SetExcludedFromBoard( !
parseBool() );
3022 case T_fields_autoplaced:
3024 symbol->SetFieldsAutoplaced();
3034 case T_default_instance:
3038 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3040 if( token != T_LEFT )
3041 Expecting( T_LEFT );
3060 symbol->SetValueFieldText( FromUTF8() );
3066 symbol->SetFootprintFieldText( FromUTF8() );
3071 Expecting(
"reference, unit, value or footprint" );
3080 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3082 if( token != T_LEFT )
3083 Expecting( T_LEFT );
3087 if( token != T_project )
3088 Expecting(
"project" );
3092 wxString projectName = FromUTF8();
3094 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3096 if( token != T_LEFT )
3097 Expecting( T_LEFT );
3101 if( token != T_path )
3102 Expecting(
"path" );
3111 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3113 if( token != T_LEFT )
3114 Expecting( T_LEFT );
3133 symbol->SetValueFieldText( FromUTF8() );
3139 symbol->SetFootprintFieldText( FromUTF8() );
3144 Expecting(
"reference, unit, value or footprint" );
3147 symbol->AddHierarchicalReference( instance );
3164 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3171 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3177 int nextAvailableId = field->
GetId() + 1;
3180 nextAvailableId += 1;
3182 field->
SetId( nextAvailableId );
3185 if( symbol->GetFieldById( field->
GetId() ) )
3186 *symbol->GetFieldById( field->
GetId() ) = *field;
3188 symbol->AddField( *field );
3191 symbol->UpdatePrefix();
3206 number = FromUTF8();
3208 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3210 if( token != T_LEFT )
3211 Expecting( T_LEFT );
3235 Expecting(
"alternate or uuid" );
3239 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3245 Expecting(
"lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
3246 "default_instance, property, pin, or instances" );
3250 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3251 symbol->SetSchSymbolLibraryName( libName );
3254 symbol->ClearFlags();
3256 return symbol.release();
3262 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3263 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3266 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3268 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3270 if( token != T_LEFT )
3271 Expecting( T_LEFT );
3278 bitmap->SetPosition(
parseXY() );
3283 bitmap->GetImage()->SetScale(
parseDouble(
"image scale factor" ) );
3285 if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
3286 bitmap->GetImage()->SetScale( 1.0 );
3305 data.reserve( 1 << 17 );
3307 while( token != T_RIGHT )
3309 if( !IsSymbol( token ) )
3310 Expecting(
"base64 image data" );
3316 wxMemoryBuffer buffer = wxBase64Decode( data );
3318 if( !bitmap->GetImage()->ReadImageFile( buffer ) )
3325 Expecting(
"at, scale, uuid or data" );
3340 return bitmap.release();
3346 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3347 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3353 std::vector<SCH_FIELD> fields;
3354 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3355 std::set<int> fieldIDsRead;
3358 sheet->ClearFieldsAutoplaced();
3360 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3362 if( token != T_LEFT )
3363 Expecting( T_LEFT );
3370 sheet->SetPosition(
parseXY() );
3379 sheet->SetSize( size );
3384 case T_exclude_from_sim:
3385 sheet->SetExcludedFromSim(
parseBool() );
3390 sheet->SetExcludedFromBOM( !
parseBool() );
3395 sheet->SetExcludedFromBoard( !
parseBool() );
3404 case T_fields_autoplaced:
3406 sheet->SetFieldsAutoplaced();
3412 sheet->SetBorderWidth( stroke.
GetWidth() );
3413 sheet->SetBorderColor( stroke.
GetColor() );
3418 sheet->SetBackgroundColor( fill.
m_Color );
3435 if( fields.empty() )
3449 if( field->
GetId() < 0 )
3452 while( !fieldIDsRead.insert( field->
GetId() ).second )
3455 fields.emplace_back( *field );
3465 std::vector<SCH_SHEET_INSTANCE> instances;
3467 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3469 if( token != T_LEFT )
3470 Expecting( T_LEFT );
3474 if( token != T_project )
3475 Expecting(
"project" );
3479 wxString projectName = FromUTF8();
3481 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3483 if( token != T_LEFT )
3484 Expecting( T_LEFT );
3488 if( token != T_path )
3489 Expecting(
"path" );
3498 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3500 if( token != T_LEFT )
3501 Expecting( T_LEFT );
3521 static std::vector<wxString> whitespaces =
3527 for( wxString ch : whitespaces )
3536 Expecting(
"page" );
3540 instances.emplace_back( instance );
3544 sheet->setInstances( instances );
3549 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3553 sheet->SetFields( fields );
3555 return sheet.release();
3561 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3562 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3565 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3567 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3569 if( token != T_LEFT )
3570 Expecting( T_LEFT );
3577 junction->SetPosition(
parseXY() );
3595 junction->SetColor(
color );
3607 Expecting(
"at, diameter, color or uuid" );
3611 return junction.release();
3617 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3618 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3621 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3623 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3625 if( token != T_LEFT )
3626 Expecting( T_LEFT );
3633 no_connect->SetPosition(
parseXY() );
3644 Expecting(
"at or uuid" );
3648 return no_connect.release();
3654 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3655 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3659 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3661 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3663 if( token != T_LEFT )
3664 Expecting( T_LEFT );
3671 busEntry->SetPosition(
parseXY() );
3681 busEntry->SetSize( size );
3688 busEntry->SetStroke( stroke );
3698 Expecting(
"at, size, uuid or stroke" );
3702 return busEntry.release();
3712 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_NOTES );
3714 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3716 if( token != T_LEFT )
3717 Expecting( T_LEFT );
3724 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3726 if( token != T_LEFT )
3727 Expecting( T_LEFT );
3734 polyline->AddPoint(
parseXY() );
3747 polyline->SetStroke( stroke );
3753 polyline->SetFillColor( fill.
m_Color );
3763 Expecting(
"pts, uuid, stroke, or fill" );
3767 return polyline.release();
3786 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3789 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3791 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3793 if( token != T_LEFT )
3794 Expecting( T_LEFT );
3807 line->SetStartPoint(
parseXY() );
3815 line->SetEndPoint(
parseXY() );
3822 line->SetStroke( stroke );
3832 Expecting(
"at, uuid or stroke" );
3836 return line.release();
3842 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
3843 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
3851 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
3853 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3855 if( token != T_LEFT )
3856 Expecting( T_LEFT );
3879 arc->SetStroke( stroke );
3885 arc->SetFillColor( fill.
m_Color );
3890 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
3895 Expecting(
"start, mid, end, stroke, fill or uuid" );
3899 arc->SetArcGeometry( startPoint, midPoint, endPoint );
3901 return arc.release();
3907 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
3908 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
3915 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
3917 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3919 if( token != T_LEFT )
3920 Expecting( T_LEFT );
3938 circle->SetStroke( stroke );
3944 circle->SetFillColor( fill.
m_Color );
3949 const_cast<KIID&
>( circle->m_Uuid ) =
KIID( FromUTF8() );
3954 Expecting(
"center, radius, stroke, fill or uuid" );
3958 circle->SetCenter( center );
3959 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
3961 return circle.release();
3967 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
3968 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
3973 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
3975 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3977 if( token != T_LEFT )
3978 Expecting( T_LEFT );
3985 rectangle->SetPosition(
parseXY() );
3990 rectangle->SetEnd(
parseXY() );
3996 rectangle->SetStroke( stroke );
4002 rectangle->SetFillColor( fill.
m_Color );
4007 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4012 Expecting(
"start, end, stroke, fill or uuid" );
4016 return rectangle.release();
4022 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4023 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4028 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4030 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4032 if( token != T_LEFT )
4033 Expecting( T_LEFT );
4047 ruleArea->SetPolyShape( sch_rule_poly );
4049 ruleArea->SetStroke( poly->GetStroke() );
4050 ruleArea->SetFillMode( poly->GetFillMode() );
4051 ruleArea->SetFillColor( poly->GetFillColor() );
4055 Expecting(
"polyline" );
4059 return ruleArea.release();
4065 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4066 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4071 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
4073 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4075 if( token != T_LEFT )
4076 Expecting( T_LEFT );
4086 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4088 if( token != T_LEFT )
4089 Expecting( T_LEFT );
4098 case 0: bezier->SetStart(
parseXY() );
break;
4099 case 1: bezier->SetBezierC1(
parseXY() );
break;
4100 case 2: bezier->SetBezierC2(
parseXY() );
break;
4101 case 3: bezier->SetEnd(
parseXY() );
break;
4102 default: Unexpected(
"control point" );
break;
4112 bezier->SetStroke( stroke );
4118 bezier->SetFillColor( fill.
m_Color );
4123 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4128 Expecting(
"pts, stroke, fill or uuid" );
4132 return bezier.release();
4139 std::unique_ptr<SCH_TEXT>
text;
4143 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4144 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4145 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4146 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4147 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4148 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4150 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4154 text->ClearFieldsAutoplaced();
4158 text->SetText( FromUTF8() );
4160 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4162 if( token != T_LEFT )
4163 Expecting( T_LEFT );
4169 case T_exclude_from_sim:
4180 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4196 Unexpected( T_shape );
4204 case T_input: label->
SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
4205 case T_output: label->
SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
4206 case T_bidirectional: label->
SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
4207 case T_tri_state: label->
SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
4208 case T_passive: label->
SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
4209 case T_dot: label->
SetShape( LABEL_FLAG_SHAPE::F_DOT );
break;
4210 case T_round: label->
SetShape( LABEL_FLAG_SHAPE::F_ROUND );
break;
4211 case T_diamond: label->
SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
break;
4212 case T_rectangle: label->
SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
break;
4214 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4225 Unexpected( T_length );
4234 case T_fields_autoplaced:
4236 text->SetFieldsAutoplaced();
4266 Unexpected( T_property );
4293 Expecting(
"at, shape, iref, uuid or effects" );
4299 if( label && label->
GetFields().empty() )
4302 return text.release();
4308 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4309 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4311 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4315 return textBox.release();
4321 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4322 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4324 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4328 return cell.release();
4344 bool foundEnd =
false;
4345 bool foundSize =
false;
4346 bool foundMargins =
false;
4350 aTextBox->
SetText( FromUTF8() );
4352 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4354 if( token != T_LEFT )
4355 Expecting( T_LEFT );
4361 case T_exclude_from_sim:
4392 cell->SetColSpan(
parseInt(
"column span" ) );
4393 cell->SetRowSpan(
parseInt(
"row span" ) );
4397 Expecting(
"at, size, stroke, fill, effects or uuid" );
4420 foundMargins =
true;
4436 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4438 Expecting(
"at, size, stroke, fill, effects or uuid" );
4446 else if( foundSize )
4447 aTextBox->
SetEnd( pos + size );
4449 Expecting(
"size" );
4464 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4465 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4469 STROKE_PARAMS borderStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4470 STROKE_PARAMS separatorsStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4471 std::unique_ptr<SCH_TABLE> table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4473 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4475 if( token != T_LEFT )
4476 Expecting( T_LEFT );
4482 case T_column_count:
4483 table->SetColCount(
parseInt(
"column count" ) );
4487 case T_column_widths:
4491 while( ( token = NextTok() ) != T_RIGHT )
4501 while( ( token = NextTok() ) != T_RIGHT )
4508 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4510 if( token != T_LEFT )
4511 Expecting( T_LEFT );
4515 if( token != T_table_cell )
4516 Expecting(
"table_cell" );
4524 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4526 if( token != T_LEFT )
4527 Expecting( T_LEFT );
4534 table->SetStrokeExternal(
parseBool() );
4545 table->SetBorderStroke( borderStroke );
4549 Expecting(
"external, header or stroke" );
4557 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4559 if( token != T_LEFT )
4560 Expecting( T_LEFT );
4578 table->SetSeparatorsStroke( separatorsStroke );
4582 Expecting(
"rows, cols, or stroke" );
4590 Expecting(
"columns, col_widths, row_heights, border, separators, header or cells" );
4594 return table.release();
4600 wxCHECK_RET( CurTok() == T_bus_alias,
4601 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4602 wxCHECK( aScreen, );
4605 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4616 busAlias->SetName( alias );
4621 if( token != T_members )
4622 Expecting(
"members" );
4626 while( token != T_RIGHT )
4628 if( !IsSymbol( token ) )
4629 Expecting(
"quoted string" );
4631 member = FromUTF8();
4636 busAlias->Members().emplace_back( member );
constexpr EDA_IU_SCALE schIUScale
void SetContentModified(bool aModified=true)
This class handle bitmap images in KiCad.
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)
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 SetHyperlink(wxString aLink)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetItalic(bool aItalic)
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)
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).
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)
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()
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.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
constexpr T Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.
VECTOR2< int32_t > VECTOR2I