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( std::clamp( retval, -int_limit, int_limit ) );
621 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
623 return KiROUND( std::clamp( retval, -int_limit, 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" ) );
3000 symbol->SetBodyStyleUnconditional(
parseInt(
"symbol body style" ) );
3004 case T_exclude_from_sim:
3005 symbol->SetExcludedFromSim(
parseBool() );
3010 symbol->SetExcludedFromBOM( !
parseBool() );
3015 symbol->SetExcludedFromBoard( !
parseBool() );
3024 case T_fields_autoplaced:
3026 symbol->SetFieldsAutoplaced();
3036 case T_default_instance:
3040 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3042 if( token != T_LEFT )
3043 Expecting( T_LEFT );
3062 symbol->SetValueFieldText( FromUTF8() );
3068 symbol->SetFootprintFieldText( FromUTF8() );
3073 Expecting(
"reference, unit, value or footprint" );
3082 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3084 if( token != T_LEFT )
3085 Expecting( T_LEFT );
3089 if( token != T_project )
3090 Expecting(
"project" );
3094 wxString projectName = FromUTF8();
3096 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3098 if( token != T_LEFT )
3099 Expecting( T_LEFT );
3103 if( token != T_path )
3104 Expecting(
"path" );
3113 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3115 if( token != T_LEFT )
3116 Expecting( T_LEFT );
3135 symbol->SetValueFieldText( FromUTF8() );
3141 symbol->SetFootprintFieldText( FromUTF8() );
3146 Expecting(
"reference, unit, value or footprint" );
3149 symbol->AddHierarchicalReference( instance );
3166 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3173 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3179 int nextAvailableId = field->
GetId() + 1;
3182 nextAvailableId += 1;
3184 field->
SetId( nextAvailableId );
3187 if( symbol->GetFieldById( field->
GetId() ) )
3188 *symbol->GetFieldById( field->
GetId() ) = *field;
3190 symbol->AddField( *field );
3193 symbol->UpdatePrefix();
3208 number = FromUTF8();
3210 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3212 if( token != T_LEFT )
3213 Expecting( T_LEFT );
3237 Expecting(
"alternate or uuid" );
3241 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3247 Expecting(
"lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
3248 "default_instance, property, pin, or instances" );
3252 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3253 symbol->SetSchSymbolLibraryName( libName );
3256 symbol->ClearFlags();
3258 return symbol.release();
3264 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3265 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3268 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3270 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3272 if( token != T_LEFT )
3273 Expecting( T_LEFT );
3280 bitmap->SetPosition(
parseXY() );
3285 bitmap->GetImage()->SetScale(
parseDouble(
"image scale factor" ) );
3287 if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
3288 bitmap->GetImage()->SetScale( 1.0 );
3307 data.reserve( 1 << 17 );
3309 while( token != T_RIGHT )
3311 if( !IsSymbol( token ) )
3312 Expecting(
"base64 image data" );
3318 wxMemoryBuffer buffer = wxBase64Decode( data );
3320 if( !bitmap->GetImage()->ReadImageFile( buffer ) )
3327 Expecting(
"at, scale, uuid or data" );
3342 return bitmap.release();
3348 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3349 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3355 std::vector<SCH_FIELD> fields;
3356 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3357 std::set<int> fieldIDsRead;
3360 sheet->ClearFieldsAutoplaced();
3362 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3364 if( token != T_LEFT )
3365 Expecting( T_LEFT );
3372 sheet->SetPosition(
parseXY() );
3381 sheet->SetSize( size );
3386 case T_exclude_from_sim:
3387 sheet->SetExcludedFromSim(
parseBool() );
3392 sheet->SetExcludedFromBOM( !
parseBool() );
3397 sheet->SetExcludedFromBoard( !
parseBool() );
3406 case T_fields_autoplaced:
3408 sheet->SetFieldsAutoplaced();
3414 sheet->SetBorderWidth( stroke.
GetWidth() );
3415 sheet->SetBorderColor( stroke.
GetColor() );
3420 sheet->SetBackgroundColor( fill.
m_Color );
3437 if( fields.empty() )
3451 if( field->
GetId() < 0 )
3454 while( !fieldIDsRead.insert( field->
GetId() ).second )
3457 fields.emplace_back( *field );
3467 std::vector<SCH_SHEET_INSTANCE> instances;
3469 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3471 if( token != T_LEFT )
3472 Expecting( T_LEFT );
3476 if( token != T_project )
3477 Expecting(
"project" );
3481 wxString projectName = FromUTF8();
3483 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3485 if( token != T_LEFT )
3486 Expecting( T_LEFT );
3490 if( token != T_path )
3491 Expecting(
"path" );
3500 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3502 if( token != T_LEFT )
3503 Expecting( T_LEFT );
3523 static std::vector<wxString> whitespaces =
3529 for( wxString ch : whitespaces )
3538 Expecting(
"page" );
3542 instances.emplace_back( instance );
3546 sheet->setInstances( instances );
3551 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3555 sheet->SetFields( fields );
3557 return sheet.release();
3563 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3564 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3567 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3569 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3571 if( token != T_LEFT )
3572 Expecting( T_LEFT );
3579 junction->SetPosition(
parseXY() );
3597 junction->SetColor(
color );
3609 Expecting(
"at, diameter, color or uuid" );
3613 return junction.release();
3619 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3620 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3623 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3625 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3627 if( token != T_LEFT )
3628 Expecting( T_LEFT );
3635 no_connect->SetPosition(
parseXY() );
3646 Expecting(
"at or uuid" );
3650 return no_connect.release();
3656 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3657 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3661 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3663 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3665 if( token != T_LEFT )
3666 Expecting( T_LEFT );
3673 busEntry->SetPosition(
parseXY() );
3683 busEntry->SetSize( size );
3690 busEntry->SetStroke( stroke );
3700 Expecting(
"at, size, uuid or stroke" );
3704 return busEntry.release();
3714 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_NOTES );
3716 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3718 if( token != T_LEFT )
3719 Expecting( T_LEFT );
3726 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3728 if( token != T_LEFT )
3729 Expecting( T_LEFT );
3736 polyline->AddPoint(
parseXY() );
3749 polyline->SetStroke( stroke );
3755 polyline->SetFillColor( fill.
m_Color );
3765 Expecting(
"pts, uuid, stroke, or fill" );
3769 return polyline.release();
3788 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3791 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3793 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3795 if( token != T_LEFT )
3796 Expecting( T_LEFT );
3809 line->SetStartPoint(
parseXY() );
3817 line->SetEndPoint(
parseXY() );
3824 line->SetStroke( stroke );
3834 Expecting(
"at, uuid or stroke" );
3838 return line.release();
3844 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
3845 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
3853 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
3855 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3857 if( token != T_LEFT )
3858 Expecting( T_LEFT );
3881 arc->SetStroke( stroke );
3887 arc->SetFillColor( fill.
m_Color );
3892 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
3897 Expecting(
"start, mid, end, stroke, fill or uuid" );
3901 arc->SetArcGeometry( startPoint, midPoint, endPoint );
3903 return arc.release();
3909 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
3910 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
3917 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
3919 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3921 if( token != T_LEFT )
3922 Expecting( T_LEFT );
3940 circle->SetStroke( stroke );
3946 circle->SetFillColor( fill.
m_Color );
3951 const_cast<KIID&
>( circle->m_Uuid ) =
KIID( FromUTF8() );
3956 Expecting(
"center, radius, stroke, fill or uuid" );
3960 circle->SetCenter( center );
3961 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
3963 return circle.release();
3969 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
3970 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
3975 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
3977 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3979 if( token != T_LEFT )
3980 Expecting( T_LEFT );
3987 rectangle->SetPosition(
parseXY() );
3992 rectangle->SetEnd(
parseXY() );
3998 rectangle->SetStroke( stroke );
4004 rectangle->SetFillColor( fill.
m_Color );
4009 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4014 Expecting(
"start, end, stroke, fill or uuid" );
4018 return rectangle.release();
4024 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4025 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4030 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4032 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4034 if( token != T_LEFT )
4035 Expecting( T_LEFT );
4049 ruleArea->SetPolyShape( sch_rule_poly );
4051 ruleArea->SetStroke( poly->GetStroke() );
4052 ruleArea->SetFillMode( poly->GetFillMode() );
4053 ruleArea->SetFillColor( poly->GetFillColor() );
4057 Expecting(
"polyline" );
4061 return ruleArea.release();
4067 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4068 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4073 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
4075 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4077 if( token != T_LEFT )
4078 Expecting( T_LEFT );
4088 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4090 if( token != T_LEFT )
4091 Expecting( T_LEFT );
4100 case 0: bezier->SetStart(
parseXY() );
break;
4101 case 1: bezier->SetBezierC1(
parseXY() );
break;
4102 case 2: bezier->SetBezierC2(
parseXY() );
break;
4103 case 3: bezier->SetEnd(
parseXY() );
break;
4104 default: Unexpected(
"control point" );
break;
4114 bezier->SetStroke( stroke );
4120 bezier->SetFillColor( fill.
m_Color );
4125 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4130 Expecting(
"pts, stroke, fill or uuid" );
4134 return bezier.release();
4141 std::unique_ptr<SCH_TEXT>
text;
4145 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4146 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4147 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4148 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4149 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4150 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4152 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4156 text->ClearFieldsAutoplaced();
4160 text->SetText( FromUTF8() );
4162 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4164 if( token != T_LEFT )
4165 Expecting( T_LEFT );
4171 case T_exclude_from_sim:
4182 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4198 Unexpected( T_shape );
4206 case T_input: label->
SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
4207 case T_output: label->
SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
4208 case T_bidirectional: label->
SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
4209 case T_tri_state: label->
SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
4210 case T_passive: label->
SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
4211 case T_dot: label->
SetShape( LABEL_FLAG_SHAPE::F_DOT );
break;
4212 case T_round: label->
SetShape( LABEL_FLAG_SHAPE::F_ROUND );
break;
4213 case T_diamond: label->
SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
break;
4214 case T_rectangle: label->
SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
break;
4216 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4227 Unexpected( T_length );
4236 case T_fields_autoplaced:
4238 text->SetFieldsAutoplaced();
4268 Unexpected( T_property );
4295 Expecting(
"at, shape, iref, uuid or effects" );
4301 if( label && label->
GetFields().empty() )
4304 return text.release();
4310 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4311 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4313 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4317 return textBox.release();
4323 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4324 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4326 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4330 return cell.release();
4346 bool foundEnd =
false;
4347 bool foundSize =
false;
4348 bool foundMargins =
false;
4352 aTextBox->
SetText( FromUTF8() );
4354 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4356 if( token != T_LEFT )
4357 Expecting( T_LEFT );
4363 case T_exclude_from_sim:
4394 cell->SetColSpan(
parseInt(
"column span" ) );
4395 cell->SetRowSpan(
parseInt(
"row span" ) );
4399 Expecting(
"at, size, stroke, fill, effects or uuid" );
4422 foundMargins =
true;
4438 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4440 Expecting(
"at, size, stroke, fill, effects or uuid" );
4448 else if( foundSize )
4449 aTextBox->
SetEnd( pos + size );
4451 Expecting(
"size" );
4466 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4467 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4471 STROKE_PARAMS borderStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4472 STROKE_PARAMS separatorsStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4473 std::unique_ptr<SCH_TABLE> table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4475 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4477 if( token != T_LEFT )
4478 Expecting( T_LEFT );
4484 case T_column_count:
4485 table->SetColCount(
parseInt(
"column count" ) );
4489 case T_column_widths:
4493 while( ( token = NextTok() ) != T_RIGHT )
4503 while( ( token = NextTok() ) != T_RIGHT )
4510 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4512 if( token != T_LEFT )
4513 Expecting( T_LEFT );
4517 if( token != T_table_cell )
4518 Expecting(
"table_cell" );
4526 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4528 if( token != T_LEFT )
4529 Expecting( T_LEFT );
4536 table->SetStrokeExternal(
parseBool() );
4547 table->SetBorderStroke( borderStroke );
4551 Expecting(
"external, header or stroke" );
4559 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4561 if( token != T_LEFT )
4562 Expecting( T_LEFT );
4580 table->SetSeparatorsStroke( separatorsStroke );
4584 Expecting(
"rows, cols, or stroke" );
4592 Expecting(
"columns, col_widths, row_heights, border, separators, header or cells" );
4596 return table.release();
4602 wxCHECK_RET( CurTok() == T_bus_alias,
4603 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4604 wxCHECK( aScreen, );
4607 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4618 busAlias->SetName( alias );
4623 if( token != T_members )
4624 Expecting(
"members" );
4628 while( token != T_RIGHT )
4630 if( !IsSymbol( token ) )
4631 Expecting(
"quoted string" );
4633 member = FromUTF8();
4638 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, bool aQuiet=false)
Round a floating point number to an integer using "round halfway cases away from zero".
VECTOR2< int32_t > VECTOR2I