31#include <fmt/format.h>
35#include <wx/mstream.h>
36#include <wx/tokenzr.h>
72using namespace TSCHEMATIC_T;
77 unsigned aLineCount,
SCH_SHEET* aRootSheet,
79 SCHEMATIC_LEXER( aLineReader ),
80 m_requiredVersion( 0 ),
83 m_appending( aIsAppending ),
84 m_progressReporter( aProgressReporter ),
85 m_lineReader( aLineReader ),
86 m_lastProgressLine( 0 ),
87 m_lineCount( aLineCount ),
88 m_rootSheet( aRootSheet )
95 const unsigned PROGRESS_DELTA = 500;
117 KIID id( FromUTF8() );
134 else if( token == T_no )
137 Expecting(
"yes or no" );
148 bool ret = aDefaultValue;
150 if( PrevTok() == T_LEFT )
155 if(
static_cast<int>( token ) ==
DSN_RIGHT )
156 return aDefaultValue;
160 else if( token == T_no )
163 Expecting(
"yes or no" );
170 return aDefaultValue;
185 bool versionChecked =
false;
196 versionChecked =
true;
199 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
201 if( token != T_LEFT )
227 case T_generator_version:
247 aSymbolLibMap[symbol->
GetName()] = symbol;
252 Expecting(
"symbol, generator, or generator_version" );
266 if( CurTok() == T_LEFT )
270 if( CurTok() == T_symbol )
277 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
278 GetTokenString( CurTok() ) );
286 std::get<2>( params ),
296 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
297 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
303 wxString unitDisplayName;
305 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
307 symbol->SetUnitCount( 1 );
319 if( !IsSymbol( token ) )
321 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(),
330 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
337 if(
static_cast<int>(
name.size() ) > bad_pos )
339 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
348 CurLineNumber(), CurOffset() );
353 symbol->SetLibId(
id );
355 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
357 if( token != T_LEFT )
377 case T_exclude_from_sim:
378 symbol->SetExcludedFromSim(
parseBool() );
383 symbol->SetExcludedFromBOM( !
parseBool() );
388 symbol->SetExcludedFromBoard( !
parseBool() );
400 if( !IsSymbol( token ) )
403 CurLineNumber(), CurOffset() );
411 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
413 auto it = aSymbolLibMap.find(
name );
415 if( it == aSymbolLibMap.end() )
417 error.Printf(
_(
"No parent for extended symbol %s" ),
name.c_str() );
418 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
421 symbol->SetParent( it->second );
430 if( !IsSymbol( token ) )
433 CurLineNumber(), CurOffset() );
441 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
445 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
446 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
451 wxStringTokenizer tokenizer(
name,
"_" );
453 if( tokenizer.CountTokens() != 2 )
455 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
456 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
459 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
461 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
462 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
465 m_unit =
static_cast<int>( tmp );
467 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
469 error.Printf(
_(
"Invalid symbol convert number %s" ),
name.c_str() );
470 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
476 symbol->SetHasAlternateBodyStyle(
true,
false );
478 if(
m_unit > symbol->GetUnitCount() )
479 symbol->SetUnitCount(
m_unit,
false );
481 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
483 if( token != T_LEFT )
493 if( IsSymbol( token ) )
495 unitDisplayName = FromUTF8();
496 symbol->SetUnitDisplayName(
m_unit, unitDisplayName );
512 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
515 symbol->AddDrawItem( item,
false );
519 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
538 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
541 symbol->AddDrawItem( item,
false );
544 case T_embedded_fonts:
546 symbol->SetAreFontsEmbedded(
parseBool() );
551 case T_embedded_files:
554 embeddedFilesParser.SyncLineReaderWith( *
this );
558 embeddedFilesParser.
ParseEmbedded( symbol->GetEmbeddedFiles() );
562 wxLogError( e.
What() );
565 SyncLineReaderWith( embeddedFilesParser );
570 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
571 "rectangle, or text" );
575 symbol->GetDrawItems().sort();
578 return symbol.release();
594 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
608 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
610 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
618 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
620 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
627 strokeParser.SyncLineReaderWith( *
this );
630 SyncLineReaderWith( strokeParser );
636 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
639 aFill.
m_Color = COLOR4D::UNSPECIFIED;
643 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
645 if( token != T_LEFT )
658 case T_none: aFill.
m_FillType = FILL_T::NO_FILL;
break;
659 case T_outline: aFill.
m_FillType = FILL_T::FILLED_SHAPE;
break;
660 case T_background: aFill.
m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR;
break;
661 case T_color: aFill.
m_FillType = FILL_T::FILLED_WITH_COLOR;
break;
662 default: Expecting(
"none, outline, color or background" );
683 Expecting(
"type or color" );
690 bool aEnforceMinTextSize )
692 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
693 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
711 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
713 if( token == T_LEFT )
719 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
721 if( token == T_LEFT )
728 faceName = FromUTF8();
772 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
776 if( !faceName.IsEmpty() )
782 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
791 case T_mirror:
break;
792 default: Expecting(
"left, right, top, bottom, or mirror" );
801 wxString hyperlink = FromUTF8();
806 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
825 Expecting(
"font, justify, hide or href" );
833 wxCHECK_RET( CurTok() == aHeaderType,
834 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
840 if( tok == T_version )
854 wxCHECK_RET( CurTok() == T_pin_names,
855 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
865 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
868 if( token == T_hide )
870 aSymbol->SetShowPinNames(
false );
874 if( token != T_LEFT )
889 aSymbol->SetShowPinNames( !
parseBool() );
894 Expecting(
"offset or hide" );
902 wxCHECK_RET( CurTok() == T_pin_numbers,
903 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_number token." );
912 for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
915 if( token == T_hide )
917 aSymbol->SetShowPinNumbers(
false );
921 if( token != T_LEFT )
931 aSymbol->SetShowPinNumbers( !
parseBool() );
945 wxCHECK_MSG( CurTok() == T_property,
nullptr,
946 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
947 wxCHECK( aSymbol,
nullptr );
951 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(),
MANDATORY_FIELDS );
955 field->SetVisible(
true );
959 if( !IsSymbol( token ) )
961 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
969 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
973 field->SetName(
name );
988 if( !IsSymbol( token ) )
990 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
997 field->SetText( value );
999 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1001 if( token != T_LEFT )
1002 Expecting( T_LEFT );
1022 field->SetPosition(
parseXY(
true ) );
1034 field->SetNameShown( show );
1038 case T_do_not_autoplace:
1041 field->SetCanAutoplace( !doNotAutoplace );
1046 Expecting(
"id, at, show_name, do_not_autoplace, or effects" );
1054 int nextAvailableId = field->GetId() + 1;
1057 nextAvailableId += 1;
1059 field->SetId( nextAvailableId );
1064 if( field->IsMandatory() )
1066 existingField = aSymbol->GetFieldById( field->GetId() );
1068 *existingField = *field;
1070 return existingField;
1072 else if(
name ==
"ki_keywords" )
1075 aSymbol->SetKeyWords( value );
1079 else if(
name ==
"ki_description" )
1081 aSymbol->SetDescription( value );
1084 else if(
name ==
"ki_fp_filters" )
1087 wxArrayString filters;
1088 wxStringTokenizer tokenizer( value );
1090 while( tokenizer.HasMoreTokens() )
1092 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1093 filters.Add( curr_token );
1096 aSymbol->SetFPFilters( filters );
1099 else if(
name ==
"ki_locked" )
1103 aSymbol->LockUnits(
true );
1109 existingField = aSymbol->FindField( field->GetCanonicalName() );
1120 for(
int ii = 1; ii < 10 && existingField; ii++ )
1122 wxString newname = base_name;
1123 newname <<
'_' << ii;
1125 existingField = aSymbol->FindField( newname );
1127 if( !existingField )
1128 field->SetName( newname );
1132 if( !existingField )
1134 aSymbol->AddDrawItem( field.get(),
false );
1136 return field.release();
1149 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1150 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1156 bool hasMidPoint =
false;
1164 bool hasAngles =
false;
1166 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC,
LAYER_DEVICE );
1173 if( token == T_private )
1175 arc->SetPrivate(
true );
1179 for( ; token != T_RIGHT; token = NextTok() )
1181 if( token != T_LEFT )
1182 Expecting( T_LEFT );
1205 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1207 if( token != T_LEFT )
1208 Expecting( T_LEFT );
1236 Expecting(
"at, length, or angles" );
1244 arc->SetStroke( stroke );
1250 arc->SetFillColor( fill.
m_Color );
1254 Expecting(
"start, mid, end, radius, stroke, or fill" );
1260 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1271 EDA_ANGLE arc_start, arc_end, arc_angle;
1272 arc->CalcArcAngles( arc_start, arc_end );
1273 arc_angle = arc_end - arc_start;
1278 arc->SetStart( endPoint );
1279 arc->SetEnd( startPoint );
1282 arc->SetCenter( new_center );
1288 arc->SetCenter( new_center );
1292 else if( hasAngles )
1294 arc->SetCenter( center );
1300 arc->SetStart( endPoint );
1301 arc->SetEnd( startPoint );
1305 EDA_ANGLE arc_start, arc_end, arc_angle;
1306 arc->CalcArcAngles( arc_start, arc_end );
1307 arc_angle = arc_end - arc_start;
1313 arc->SetStart( startPoint );
1314 arc->SetEnd( endPoint );
1318 arc->SetStart( startPoint );
1319 arc->SetEnd( endPoint );
1322 arc->SetCenter( new_center );
1327 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1330 return arc.release();
1336 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1337 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1343 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER,
LAYER_DEVICE );
1345 bezier->SetUnit(
m_unit );
1350 if( token == T_private )
1352 bezier->SetPrivate(
true );
1356 for( ; token != T_RIGHT; token = NextTok() )
1358 if( token != T_LEFT )
1359 Expecting( T_LEFT );
1369 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1371 if( token != T_LEFT )
1372 Expecting( T_LEFT );
1381 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1382 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1383 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1384 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1385 default: Unexpected(
"control point" );
break;
1395 bezier->SetStroke( stroke );
1401 bezier->SetFillColor( fill.
m_Color );
1405 Expecting(
"pts, stroke, or fill" );
1409 bezier->RebuildBezierToSegmentsPointsList( bezier->GetPenWidth() / 2 );
1411 return bezier.release();
1417 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1418 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1426 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE,
LAYER_DEVICE );
1428 circle->SetUnit(
m_unit );
1433 if( token == T_private )
1435 circle->SetPrivate(
true );
1439 for( ; token != T_RIGHT; token = NextTok() )
1441 if( token != T_LEFT )
1442 Expecting( T_LEFT );
1460 circle->SetStroke( stroke );
1466 circle->SetFillColor( fill.
m_Color );
1470 Expecting(
"center, radius, stroke, or fill" );
1474 circle->SetCenter( center );
1475 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
1477 return circle.release();
1488 case T_input:
return ELECTRICAL_PINTYPE::PT_INPUT;
1489 case T_output:
return ELECTRICAL_PINTYPE::PT_OUTPUT;
1490 case T_bidirectional:
return ELECTRICAL_PINTYPE::PT_BIDI;
1491 case T_tri_state:
return ELECTRICAL_PINTYPE::PT_TRISTATE;
1492 case T_passive:
return ELECTRICAL_PINTYPE::PT_PASSIVE;
1493 case T_unspecified:
return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1494 case T_power_in:
return ELECTRICAL_PINTYPE::PT_POWER_IN;
1495 case T_power_out:
return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1496 case T_open_collector:
return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1497 case T_open_emitter:
return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1499 case T_no_connect:
return ELECTRICAL_PINTYPE::PT_NC;
1500 case T_free:
return ELECTRICAL_PINTYPE::PT_NIC;
1503 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1504 "power_in, power_out, open_collector, open_emitter, free or "
1506 return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1515 case T_line:
return GRAPHIC_PINSHAPE::LINE;
1516 case T_inverted:
return GRAPHIC_PINSHAPE::INVERTED;
1517 case T_clock:
return GRAPHIC_PINSHAPE::CLOCK;
1518 case T_inverted_clock:
return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1519 case T_input_low:
return GRAPHIC_PINSHAPE::INPUT_LOW;
1520 case T_clock_low:
return GRAPHIC_PINSHAPE::CLOCK_LOW;
1521 case T_output_low:
return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1522 case T_edge_clock_high:
return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1523 case T_non_logic:
return GRAPHIC_PINSHAPE::NONLOGIC;
1526 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1527 "output_low, edge_clock_high, non_logic" );
1528 return GRAPHIC_PINSHAPE::LINE;
1532 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1533 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1538 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1545 pin->SetType( parseType( token ) );
1549 pin->SetShape( parseShape( token ) );
1551 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1554 if( token == T_hide )
1556 pin->SetVisible(
false );
1560 if( token != T_LEFT )
1561 Expecting( T_LEFT );
1570 switch(
parseInt(
"pin orientation" ) )
1572 case 0:
pin->SetOrientation( PIN_ORIENTATION::PIN_RIGHT );
break;
1573 case 90:
pin->SetOrientation( PIN_ORIENTATION::PIN_UP );
break;
1574 case 180:
pin->SetOrientation( PIN_ORIENTATION::PIN_LEFT );
break;
1575 case 270:
pin->SetOrientation( PIN_ORIENTATION::PIN_DOWN );
break;
1576 default: Expecting(
"0, 90, 180, or 270" );
1595 if( !IsSymbol( token ) )
1604 pin->SetName( FromUTF8() );
1608 if( token != T_RIGHT )
1612 if( token == T_effects )
1619 pin->SetNameTextSize(
text.GetTextHeight() );
1624 Expecting(
"effects" );
1633 if( !IsSymbol( token ) )
1636 CurLineNumber(), CurOffset() );
1639 pin->SetNumber( FromUTF8() );
1642 if( token != T_RIGHT )
1646 if( token == T_effects )
1653 pin->SetNumberTextSize(
text.GetTextHeight() );
1658 Expecting(
"effects" );
1670 if( !IsSymbol( token ) )
1673 CurLineNumber(), CurOffset() );
1679 alt.
m_Type = parseType( token );
1682 alt.
m_Shape = parseShape( token );
1684 pin->GetAlternates()[ alt.
m_Name ] = alt;
1691 Expecting(
"at, name, number, hide, length, or alternate" );
1695 return pin.release();
1701 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1702 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1707 std::unique_ptr<SCH_SHAPE> poly = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_DEVICE );
1714 if( token == T_private )
1716 poly->SetPrivate(
true );
1720 for( ; token != T_RIGHT; token = NextTok() )
1722 if( token != T_LEFT )
1723 Expecting( T_LEFT );
1730 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1732 if( token != T_LEFT )
1733 Expecting( T_LEFT );
1740 poly->AddPoint(
parseXY(
true ) );
1749 poly->SetStroke( stroke );
1755 poly->SetFillColor( fill.
m_Color );
1759 Expecting(
"pts, stroke, or fill" );
1763 return poly.release();
1769 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1770 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1775 auto rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE,
LAYER_DEVICE );
1777 rectangle->SetUnit(
m_unit );
1782 if( token == T_private )
1784 rectangle->SetPrivate(
true );
1788 for( ; token != T_RIGHT; token = NextTok() )
1790 if( token != T_LEFT )
1791 Expecting( T_LEFT );
1798 rectangle->SetPosition(
parseXY(
true ) );
1803 rectangle->SetEnd(
parseXY(
true ) );
1809 rectangle->SetStroke( stroke );
1815 rectangle->SetFillColor( fill.
m_Color );
1819 Expecting(
"start, end, stroke, or fill" );
1823 return rectangle.release();
1829 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1830 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1833 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1840 if( token == T_private )
1842 text->SetPrivate(
true );
1846 if( !IsSymbol( token ) )
1848 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1852 text->SetText( FromUTF8() );
1854 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1856 if( token != T_LEFT )
1857 Expecting( T_LEFT );
1875 Expecting(
"at or effects" );
1879 return text.release();
1885 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
1886 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
1898 bool foundEnd =
false;
1899 bool foundSize =
false;
1900 bool foundMargins =
false;
1902 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
1904 textBox->SetUnit(
m_unit );
1908 if( token == T_private )
1910 textBox->SetPrivate(
true );
1914 if( !IsSymbol( token ) )
1916 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1920 textBox->SetText( FromUTF8() );
1922 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1924 if( token != T_LEFT )
1925 Expecting( T_LEFT );
1956 textBox->SetStroke( stroke );
1962 textBox->SetFillColor( fill.
m_Color );
1967 textBox->SetMarginLeft(
left );
1968 textBox->SetMarginTop( top );
1969 textBox->SetMarginRight(
right );
1970 textBox->SetMarginBottom( bottom );
1971 foundMargins =
true;
1980 Expecting(
"at, size, stroke, fill or effects" );
1984 textBox->SetPosition( pos );
1987 textBox->SetEnd( end );
1988 else if( foundSize )
1989 textBox->SetEnd( pos + size );
1991 Expecting(
"size" );
1995 int margin = textBox->GetLegacyTextMargin();
1996 textBox->SetMarginLeft( margin );
1997 textBox->SetMarginTop( margin );
1998 textBox->SetMarginRight( margin );
1999 textBox->SetMarginBottom( margin );
2002 return textBox.release();
2008 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
2009 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
2015 wxString pageType = FromUTF8();
2017 if( !aPageInfo.
SetType( pageType ) )
2019 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
2046 if( token == T_portrait )
2051 else if( token != T_RIGHT )
2053 Expecting(
"portrait" );
2060 wxCHECK_RET( CurTok() == T_title_block,
2061 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
2065 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2067 if( token != T_LEFT )
2068 Expecting( T_LEFT );
2076 aTitleBlock.
SetTitle( FromUTF8() );
2081 aTitleBlock.
SetDate( FromUTF8() );
2096 int commentNumber =
parseInt(
"comment" );
2098 switch( commentNumber )
2147 CurLine(), CurLineNumber(), CurOffset() );
2154 Expecting(
"title, date, rev, company, or comment" );
2164 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2165 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2167 T token = NextTok();
2169 if( !IsSymbol( token ) )
2171 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2175 wxString
name = FromUTF8();
2177 if(
name.IsEmpty() )
2179 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2185 if( !IsSymbol( token ) )
2187 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2192 wxString value = FromUTF8();
2194 int mandatoryFieldCount = 0;
2201 std::unique_ptr<SCH_FIELD> field =
2202 std::make_unique<SCH_FIELD>(
VECTOR2I( -1, -1 ), mandatoryFieldCount, aParent,
name );
2203 field->SetText( value );
2204 field->SetVisible(
true );
2229 else if( !
name.CmpNoCase( wxT(
"Sheet name" ) ) )
2234 else if( !
name.CmpNoCase( wxT(
"Sheet file" ) ) )
2242 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2244 if( token != T_LEFT )
2245 Expecting( T_LEFT );
2256 if(
id >= mandatoryFieldCount )
2263 field->SetPosition(
parseXY() );
2275 field->SetNameShown( show );
2279 case T_do_not_autoplace:
2282 field->SetCanAutoplace( !doNotAutoplace );
2287 Expecting(
"id, at, show_name, do_not_autoplace or effects" );
2291 return field.release();
2297 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2298 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2299 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2301 T token = NextTok();
2303 if( !IsSymbol( token ) )
2305 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2309 wxString
name = FromUTF8();
2311 if(
name.IsEmpty() )
2313 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2317 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2323 case T_input: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
2324 case T_output: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
2325 case T_bidirectional: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
2326 case T_tri_state: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
2327 case T_passive: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
2329 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2332 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2334 if( token != T_LEFT )
2335 Expecting( T_LEFT );
2343 sheetPin->SetPosition(
parseXY() );
2345 double angle =
parseDouble(
"sheet pin angle (side)" );
2348 sheetPin->SetSide( SHEET_SIDE::RIGHT );
2349 else if( angle == 90.0 )
2350 sheetPin->SetSide( SHEET_SIDE::TOP );
2351 else if( angle == 180.0 )
2352 sheetPin->SetSide( SHEET_SIDE::LEFT );
2353 else if( angle == 270.0 )
2354 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
2356 Expecting(
"0, 90, 180, or 270" );
2373 Expecting(
"at, uuid or effects" );
2377 return sheetPin.release();
2383 wxCHECK_RET( CurTok() == T_sheet_instances,
2384 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2385 wxCHECK( aScreen, );
2389 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2391 if( token != T_LEFT )
2392 Expecting( T_LEFT );
2410 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2412 if( token != T_LEFT )
2413 Expecting( T_LEFT );
2417 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2420 size_t numReplacements = 0;
2438 for(
const wxString& ch : whitespaces )
2439 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2444 if( numReplacements > 0 )
2451 Expecting(
"path or page" );
2456 && ( instance.
m_Path.empty() ) )
2472 Expecting(
"path" );
2480 wxCHECK_RET( CurTok() == T_symbol_instances,
2481 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2482 wxCHECK( aScreen, );
2487 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2489 if( token != T_LEFT )
2490 Expecting( T_LEFT );
2507 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2509 if( token != T_LEFT )
2510 Expecting( T_LEFT );
2529 instance.
m_Value = FromUTF8();
2540 Expecting(
"path, unit, value or footprint" );
2549 Expecting(
"path" );
2558 wxCHECK( aSheet !=
nullptr, );
2562 wxCHECK( screen !=
nullptr, );
2564 if( aIsCopyableOnly )
2567 bool fileHasUuid =
false;
2581 if( !aIsCopyableOnly )
2586 if( CurTok() != T_kicad_sch )
2587 Expecting(
"kicad_sch" );
2603 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2605 if( aIsCopyableOnly && token == T_EOF )
2608 if( token != T_LEFT )
2609 Expecting( T_LEFT );
2639 case T_generator_version:
2665 if( aIsCopyableOnly )
2666 Unexpected( T_paper );
2676 if( aIsCopyableOnly )
2677 Unexpected( T_page );
2681 NeedSYMBOLorNUMBER();
2682 NeedSYMBOLorNUMBER();
2689 if( aIsCopyableOnly )
2690 Unexpected( T_title_block );
2704 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2706 if( token != T_LEFT )
2707 Expecting( T_LEFT );
2720 Expecting(
"symbol" );
2821 case T_netclass_flag:
2826 case T_global_label:
2827 case T_hierarchical_label:
2828 case T_directive_label:
2840 case T_sheet_instances:
2844 case T_symbol_instances:
2849 if( aIsCopyableOnly )
2850 Unexpected( T_bus_alias );
2855 case T_embedded_fonts:
2861 CurLineNumber(), CurOffset() );
2868 case T_embedded_files:
2874 CurLineNumber(), CurOffset() );
2877 embeddedFilesParser.SyncLineReaderWith( *
this );
2885 wxLogError( e.
What() );
2888 SyncLineReaderWith( embeddedFilesParser );
2894 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
2895 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
2896 "sheet, symbol, symbol_instances, text, title_block" );
2915 CurLineNumber(), CurOffset() );
2920 std::get<2>( params ),
2926 std::vector<std::string> fontNames;
2927 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
2937 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
2938 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
2943 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2945 std::set<int> fieldIDsRead;
2948 symbol->ClearFieldsAutoplaced();
2958 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2960 if( token != T_LEFT )
2961 Expecting( T_LEFT );
2973 if( !IsSymbol( token ) )
2976 CurLineNumber(), CurOffset() );
2979 libName = FromUTF8();
2983 libName.Replace(
"{slash}",
"/" );
2993 if( !IsSymbol( token ) && token != T_NUMBER )
2994 Expecting(
"symbol|number" );
2997 wxString
name = FromUTF8();
3001 name.Replace(
"{slash}",
"/" );
3007 if(
static_cast<int>(
name.size() ) > bad_pos )
3009 wxString msg = wxString::Format(
3010 _(
"Symbol %s contains invalid character '%c'" ),
name,
3017 CurLineNumber(), CurOffset() );
3020 symbol->SetLibId( libId );
3026 symbol->SetPosition(
parseXY() );
3028 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3031 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3032 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3033 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3034 default: Expecting(
"0, 90, 180, or 270" );
3037 symbol->SetTransform( transform );
3046 else if( token == T_y )
3049 Expecting(
"x or y" );
3055 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3062 symbol->SetBodyStyleUnconditional(
parseInt(
"symbol body style" ) );
3066 case T_exclude_from_sim:
3067 symbol->SetExcludedFromSim(
parseBool() );
3072 symbol->SetExcludedFromBOM( !
parseBool() );
3077 symbol->SetExcludedFromBoard( !
parseBool() );
3086 case T_fields_autoplaced:
3088 symbol->SetFieldsAutoplaced();
3098 case T_default_instance:
3102 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3104 if( token != T_LEFT )
3105 Expecting( T_LEFT );
3124 symbol->SetValueFieldText( FromUTF8() );
3130 symbol->SetFootprintFieldText( FromUTF8() );
3135 Expecting(
"reference, unit, value or footprint" );
3144 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3146 if( token != T_LEFT )
3147 Expecting( T_LEFT );
3151 if( token != T_project )
3152 Expecting(
"project" );
3156 wxString projectName = FromUTF8();
3158 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3160 if( token != T_LEFT )
3161 Expecting( T_LEFT );
3165 if( token != T_path )
3166 Expecting(
"path" );
3175 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3177 if( token != T_LEFT )
3178 Expecting( T_LEFT );
3197 symbol->SetValueFieldText( FromUTF8() );
3203 symbol->SetFootprintFieldText( FromUTF8() );
3208 Expecting(
"reference, unit, value or footprint" );
3211 symbol->AddHierarchicalReference( instance );
3228 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3235 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3241 int nextAvailableId = field->
GetId() + 1;
3244 nextAvailableId += 1;
3246 field->
SetId( nextAvailableId );
3249 if( symbol->GetFieldById( field->
GetId() ) )
3250 *symbol->GetFieldById( field->
GetId() ) = *field;
3252 symbol->AddField( *field );
3255 symbol->UpdatePrefix();
3270 number = FromUTF8();
3272 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3274 if( token != T_LEFT )
3275 Expecting( T_LEFT );
3299 Expecting(
"alternate or uuid" );
3303 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3309 Expecting(
"lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
3310 "default_instance, property, pin, or instances" );
3314 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3315 symbol->SetSchSymbolLibraryName( libName );
3318 symbol->ClearFlags();
3320 return symbol.release();
3326 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3327 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3330 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3333 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3335 if( token != T_LEFT )
3336 Expecting( T_LEFT );
3343 bitmap->SetPosition(
parseXY() );
3369 data.reserve( 1 << 17 );
3371 while( token != T_RIGHT )
3373 if( !IsSymbol( token ) )
3374 Expecting(
"base64 image data" );
3380 wxMemoryBuffer buffer = wxBase64Decode( data );
3389 Expecting(
"at, scale, uuid or data" );
3402 return bitmap.release();
3408 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3409 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3415 std::vector<SCH_FIELD> fields;
3416 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3417 std::set<int> fieldIDsRead;
3420 sheet->ClearFieldsAutoplaced();
3422 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3424 if( token != T_LEFT )
3425 Expecting( T_LEFT );
3432 sheet->SetPosition(
parseXY() );
3441 sheet->SetSize( size );
3446 case T_exclude_from_sim:
3447 sheet->SetExcludedFromSim(
parseBool() );
3452 sheet->SetExcludedFromBOM( !
parseBool() );
3457 sheet->SetExcludedFromBoard( !
parseBool() );
3466 case T_fields_autoplaced:
3468 sheet->SetFieldsAutoplaced();
3474 sheet->SetBorderWidth( stroke.
GetWidth() );
3475 sheet->SetBorderColor( stroke.
GetColor() );
3480 sheet->SetBackgroundColor( fill.
m_Color );
3497 if( fields.empty() )
3511 if( field->
GetId() < 0 )
3514 while( !fieldIDsRead.insert( field->
GetId() ).second )
3517 fields.emplace_back( *field );
3527 std::vector<SCH_SHEET_INSTANCE> instances;
3529 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3531 if( token != T_LEFT )
3532 Expecting( T_LEFT );
3536 if( token != T_project )
3537 Expecting(
"project" );
3541 wxString projectName = FromUTF8();
3543 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3545 if( token != T_LEFT )
3546 Expecting( T_LEFT );
3550 if( token != T_path )
3551 Expecting(
"path" );
3560 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3562 if( token != T_LEFT )
3563 Expecting( T_LEFT );
3583 static std::vector<wxString> whitespaces =
3589 for( wxString ch : whitespaces )
3598 Expecting(
"page" );
3602 instances.emplace_back( instance );
3606 sheet->setInstances( instances );
3611 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3615 sheet->SetFields( fields );
3617 return sheet.release();
3623 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3624 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3627 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3629 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3631 if( token != T_LEFT )
3632 Expecting( T_LEFT );
3639 junction->SetPosition(
parseXY() );
3657 junction->SetColor(
color );
3669 Expecting(
"at, diameter, color or uuid" );
3673 return junction.release();
3679 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3680 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3683 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3685 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3687 if( token != T_LEFT )
3688 Expecting( T_LEFT );
3695 no_connect->SetPosition(
parseXY() );
3706 Expecting(
"at or uuid" );
3710 return no_connect.release();
3716 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3717 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3721 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3723 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3725 if( token != T_LEFT )
3726 Expecting( T_LEFT );
3733 busEntry->SetPosition(
parseXY() );
3743 busEntry->SetSize( size );
3750 busEntry->SetStroke( stroke );
3760 Expecting(
"at, size, uuid or stroke" );
3764 return busEntry.release();
3774 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_NOTES );
3776 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3778 if( token != T_LEFT )
3779 Expecting( T_LEFT );
3786 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3788 if( token != T_LEFT )
3789 Expecting( T_LEFT );
3796 polyline->AddPoint(
parseXY() );
3809 polyline->SetStroke( stroke );
3815 polyline->SetFillColor( fill.
m_Color );
3825 Expecting(
"pts, uuid, stroke, or fill" );
3829 return polyline.release();
3848 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3851 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3853 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3855 if( token != T_LEFT )
3856 Expecting( T_LEFT );
3869 line->SetStartPoint(
parseXY() );
3877 line->SetEndPoint(
parseXY() );
3884 line->SetStroke( stroke );
3894 Expecting(
"at, uuid or stroke" );
3898 return line.release();
3904 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
3905 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
3913 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
3915 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3917 if( token != T_LEFT )
3918 Expecting( T_LEFT );
3941 arc->SetStroke( stroke );
3947 arc->SetFillColor( fill.
m_Color );
3952 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
3957 Expecting(
"start, mid, end, stroke, fill or uuid" );
3961 arc->SetArcGeometry( startPoint, midPoint, endPoint );
3963 return arc.release();
3969 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
3970 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
3977 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
3979 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3981 if( token != T_LEFT )
3982 Expecting( T_LEFT );
4000 circle->SetStroke( stroke );
4006 circle->SetFillColor( fill.
m_Color );
4011 const_cast<KIID&
>( circle->m_Uuid ) =
KIID( FromUTF8() );
4016 Expecting(
"center, radius, stroke, fill or uuid" );
4020 circle->SetCenter( center );
4021 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
4023 return circle.release();
4029 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4030 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4035 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
4037 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4039 if( token != T_LEFT )
4040 Expecting( T_LEFT );
4047 rectangle->SetPosition(
parseXY() );
4052 rectangle->SetEnd(
parseXY() );
4058 rectangle->SetStroke( stroke );
4064 rectangle->SetFillColor( fill.
m_Color );
4069 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4074 Expecting(
"start, end, stroke, fill or uuid" );
4078 return rectangle.release();
4084 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4085 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4090 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4092 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4094 if( token != T_LEFT )
4095 Expecting( T_LEFT );
4109 ruleArea->SetPolyShape( sch_rule_poly );
4111 ruleArea->SetStroke( poly->GetStroke() );
4112 ruleArea->SetFillMode( poly->GetFillMode() );
4113 ruleArea->SetFillColor( poly->GetFillColor() );
4117 Expecting(
"polyline" );
4121 return ruleArea.release();
4127 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4128 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4133 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
4135 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4137 if( token != T_LEFT )
4138 Expecting( T_LEFT );
4148 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4150 if( token != T_LEFT )
4151 Expecting( T_LEFT );
4160 case 0: bezier->SetStart(
parseXY() );
break;
4161 case 1: bezier->SetBezierC1(
parseXY() );
break;
4162 case 2: bezier->SetBezierC2(
parseXY() );
break;
4163 case 3: bezier->SetEnd(
parseXY() );
break;
4164 default: Unexpected(
"control point" );
break;
4174 bezier->SetStroke( stroke );
4180 bezier->SetFillColor( fill.
m_Color );
4185 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4190 Expecting(
"pts, stroke, fill or uuid" );
4194 return bezier.release();
4201 std::unique_ptr<SCH_TEXT>
text;
4205 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4206 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4207 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4208 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4209 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4210 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4212 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4216 text->ClearFieldsAutoplaced();
4220 text->SetText( FromUTF8() );
4222 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4224 if( token != T_LEFT )
4225 Expecting( T_LEFT );
4231 case T_exclude_from_sim:
4242 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4258 Unexpected( T_shape );
4266 case T_input: label->
SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
4267 case T_output: label->
SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
4268 case T_bidirectional: label->
SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
4269 case T_tri_state: label->
SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
4270 case T_passive: label->
SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
4271 case T_dot: label->
SetShape( LABEL_FLAG_SHAPE::F_DOT );
break;
4272 case T_round: label->
SetShape( LABEL_FLAG_SHAPE::F_ROUND );
break;
4273 case T_diamond: label->
SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
break;
4274 case T_rectangle: label->
SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
break;
4276 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4287 Unexpected( T_length );
4296 case T_fields_autoplaced:
4298 text->SetFieldsAutoplaced();
4328 Unexpected( T_property );
4355 Expecting(
"at, shape, iref, uuid or effects" );
4361 if( label && label->
GetFields().empty() )
4364 return text.release();
4370 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4371 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4373 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4377 return textBox.release();
4383 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4384 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4386 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4390 return cell.release();
4406 bool foundEnd =
false;
4407 bool foundSize =
false;
4408 bool foundMargins =
false;
4412 aTextBox->
SetText( FromUTF8() );
4414 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4416 if( token != T_LEFT )
4417 Expecting( T_LEFT );
4423 case T_exclude_from_sim:
4454 cell->SetColSpan(
parseInt(
"column span" ) );
4455 cell->SetRowSpan(
parseInt(
"row span" ) );
4459 Expecting(
"at, size, stroke, fill, effects or uuid" );
4482 foundMargins =
true;
4498 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4500 Expecting(
"at, size, stroke, fill, effects or uuid" );
4508 else if( foundSize )
4509 aTextBox->
SetEnd( pos + size );
4511 Expecting(
"size" );
4526 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4527 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4531 STROKE_PARAMS borderStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4532 STROKE_PARAMS separatorsStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4533 std::unique_ptr<SCH_TABLE> table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4535 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4537 if( token != T_LEFT )
4538 Expecting( T_LEFT );
4544 case T_column_count:
4545 table->SetColCount(
parseInt(
"column count" ) );
4549 case T_column_widths:
4553 while( ( token = NextTok() ) != T_RIGHT )
4563 while( ( token = NextTok() ) != T_RIGHT )
4570 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4572 if( token != T_LEFT )
4573 Expecting( T_LEFT );
4577 if( token != T_table_cell )
4578 Expecting(
"table_cell" );
4586 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4588 if( token != T_LEFT )
4589 Expecting( T_LEFT );
4596 table->SetStrokeExternal(
parseBool() );
4607 table->SetBorderStroke( borderStroke );
4611 Expecting(
"external, header or stroke" );
4619 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4621 if( token != T_LEFT )
4622 Expecting( T_LEFT );
4640 table->SetSeparatorsStroke( separatorsStroke );
4644 Expecting(
"rows, cols, or stroke" );
4652 Expecting(
"columns, col_widths, row_heights, border, separators, header or cells" );
4656 return table.release();
4662 wxCHECK_RET( CurTok() == T_bus_alias,
4663 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4664 wxCHECK( aScreen, );
4667 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4678 busAlias->SetName( alias );
4683 if( token != T_members )
4684 Expecting(
"members" );
4688 while( token != T_RIGHT )
4690 if( !IsSymbol( token ) )
4691 Expecting(
"quoted string" );
4693 member = FromUTF8();
4698 busAlias->Members().emplace_back( member );
constexpr EDA_IU_SCALE schIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
void SetContentModified(bool aModified=true)
KICAD_T Type() const
Returns the type of object.
virtual void SetParent(EDA_ITEM *aParent)
SHAPE_POLY_SET & GetPolyShape()
void SetFillColor(const COLOR4D &aColor)
int GetPointCount() const
void SetEnd(const VECTOR2I &aEnd)
void SetFillMode(FILL_T aFill)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
void SetTextColor(const COLOR4D &aColor)
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetTextPos(const VECTOR2I &aPoint)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
Set only the italic flag, without changing the font.
virtual void SetVisible(bool aVisible)
void SetLineSpacing(double aLineSpacing)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
static bool ValidateHyperlink(const wxString &aURL)
Check if aURL is a valid hyperlink.
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
void SetHyperlink(wxString aLink)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void ParseEmbedded(EMBEDDED_FILES *aFiles)
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
const std::vector< wxString > * GetFontFiles() const
If we just need the cached version of the font files, we can use this function which is const and wil...
void SetAreFontsEmbedded(bool aEmbedFonts)
Simple container to manage fill parameters.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
A color representation with 4 components: red, green, blue, alpha.
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Define a library symbol object.
wxString GetName() const override
int UpdateFieldOrdinals()
Order optional field indices.
EMBEDDED_FILES * GetEmbeddedFiles() override
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
static const wxChar Custom[]
"User" defined page type
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
const BITMAP_BASE & GetImage() const
Get the underlying image.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
Holds all the data relating to one schematic.
EMBEDDED_FILES * GetEmbeddedFiles() override
Object to handle a bitmap image that can be inserted in a schematic.
Class for a wire to bus entry.
void SetPinLength(int aLength)
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
const wxString & GetInternalName()
Get the initial name of the field set at creation (or set by SetName()).
SCH_ITEM * ParseSymbolDrawItem()
SCH_SHAPE * parseSymbolPolyLine()
SCH_TABLE * parseSchTable()
bool m_appending
Appending load status.
unsigned m_lastProgressLine
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
SCH_SHAPE * parseSchCircle()
SCH_TEXT * parseSchText()
SCH_TABLECELL * parseSchTableCell()
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
void parsePinNumbers(std::unique_ptr< LIB_SYMBOL > &aSymbol)
LIB_SYMBOL * parseLibSymbol(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_RULE_AREA * parseSchRuleArea()
PROGRESS_REPORTER * m_progressReporter
void parseFill(FILL_PARAMS &aFill)
SCH_TEXTBOX * parseSymbolTextBox()
void parseBusAlias(SCH_SCREEN *aScreen)
std::set< int > m_fieldIDsRead
Field IDs that have been read so far for the current symbol.
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.
int m_unit
The current unit being parsed.
SCH_SHAPE * parseSymbolBezier()
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax, bool aEnforceMinTextSize=true)
SCH_TEXTBOX * parseSchTextBox()
SCH_SHEET * m_rootSheet
The rootsheet for full project loads or null for importing a schematic.
SCH_SHAPE * parseSchArc()
SCH_SHAPE * parseSchPolyLine()
SCH_BITMAP * parseImage()
SCH_SHAPE * parseSymbolCircle()
wxString m_generatorVersion
void ParseLib(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_PIN * parseSymbolPin()
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
std::map< EDA_TEXT *, std::tuple< wxString, bool, bool > > m_fontTextMap
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
wxString m_symbolName
The current symbol name.
VECTOR2I parseXY(bool aInvertY=false)
SCH_SHAPE * parseSymbolRectangle()
void parsePinNames(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SHAPE * parseSchBezier()
SCH_JUNCTION * parseJunction()
void ParseSchematic(SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Parse the internal LINE_READER object into aSheet.
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
int m_bodyStyle
The current body style being parsed.
SCH_NO_CONNECT * parseNoConnect()
SCH_TEXT * parseSymbolText()
SCH_SHAPE * parseSymbolArc()
SCH_BUS_WIRE_ENTRY * parseBusEntry()
SCH_SHAPE * parseSchRectangle()
SCH_FIELD * parseProperty(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SYMBOL * parseSchematicSymbol()
void parseSchTextBoxContent(SCH_TEXTBOX *aTextBox)
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
int m_requiredVersion
Set to the symbol library file version required.
const LINE_READER * m_lineReader
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
Parse internal LINE_READER object into symbols and return all found.
void parseSchSheetInstances(SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
SCH_IO_KICAD_SEXPR_PARSER(LINE_READER *aLineReader=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, unsigned aLineCount=0, SCH_SHEET *aRootSheet=nullptr, bool aIsAppending=false)
Base class for any item which can be embedded within the SCHEMATIC container class,...
void SetFieldsAutoplaced()
void SetShape(LABEL_FLAG_SHAPE aShape)
std::vector< SCH_FIELD > & GetFields()
Segment description base class to describe items which have 2 end points (track, wire,...
void SetStartPoint(const VECTOR2I &aPosition)
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
void SetEndPoint(const VECTOR2I &aPosition)
void SetFileFormatVersionAtLoad(int aVersion)
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).
void SetPageSettings(const PAGE_INFO &aPageSettings)
const KIID & GetUuid() const
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
SCHEMATIC * Schematic() const
void FixupEmbeddedData()
After loading a file from disk, the library symbols do not yet contain the full data for their embedd...
int GetFileFormatVersionAtLoad() const
KIID m_uuid
A unique identifier for each schematic file.
std::vector< SCH_SYMBOL_INSTANCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
void SetPosition(const VECTOR2I &aPos) override
void SetStroke(const STROKE_PARAMS &aStroke) override
STROKE_PARAMS GetStroke() const override
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslated=true)
SCH_SCREEN * GetScreen() const
void SetMarginBottom(int aBottom)
int GetLegacyTextMargin() const
void SetMarginLeft(int aLeft)
void SetMarginRight(int aRight)
void SetMarginTop(int aTop)
void SetExcludedFromSim(bool aExclude) override
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetLineStyle(LINE_STYLE aLineStyle)
LINE_STYLE GetLineStyle() const
KIGFX::COLOR4D GetColor() const
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_360
static constexpr EDA_ANGLE ANGLE_180
FONTCONFIG * Fontconfig()
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
#define MAX_PAGE_SIZE_EESCHEMA_MM
#define MIN_PAGE_SIZE_MM
Min and max page sizes for clamping, in mm.
PGM_BASE & Pgm()
The global Program "get" accessor.
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
@ SHEET_MANDATORY_FIELDS
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
#define SIM_LEGACY_ENABLE_FIELD
#define SIM_LEGACY_ENABLE_FIELD_V7
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString UnescapeString(const wxString &aSource)
constexpr int MilsToIU(int mils) const
A filename or source description, a problem input line, a line number, a byte offset,...
ELECTRICAL_PINTYPE m_Type
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP
wxString GetCanonicalFieldName(int idx)
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ MANDATORY_FIELDS
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
VECTOR2< int32_t > VECTOR2I