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 );
3534 std::vector<SCH_SHEET_INSTANCE> instances;
3536 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3538 if( token != T_LEFT )
3539 Expecting( T_LEFT );
3543 if( token != T_project )
3544 Expecting(
"project" );
3548 wxString projectName = FromUTF8();
3550 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3552 if( token != T_LEFT )
3553 Expecting( T_LEFT );
3557 if( token != T_path )
3558 Expecting(
"path" );
3567 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3569 if( token != T_LEFT )
3570 Expecting( T_LEFT );
3590 static std::vector<wxString> whitespaces =
3596 for( wxString ch : whitespaces )
3605 Expecting(
"page" );
3609 instances.emplace_back( instance );
3613 sheet->setInstances( instances );
3618 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3622 sheet->SetFields( fields );
3624 return sheet.release();
3630 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3631 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3634 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3636 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3638 if( token != T_LEFT )
3639 Expecting( T_LEFT );
3646 junction->SetPosition(
parseXY() );
3664 junction->SetColor(
color );
3676 Expecting(
"at, diameter, color or uuid" );
3680 return junction.release();
3686 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3687 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3690 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3692 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3694 if( token != T_LEFT )
3695 Expecting( T_LEFT );
3702 no_connect->SetPosition(
parseXY() );
3713 Expecting(
"at or uuid" );
3717 return no_connect.release();
3723 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3724 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3728 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3730 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3732 if( token != T_LEFT )
3733 Expecting( T_LEFT );
3740 busEntry->SetPosition(
parseXY() );
3750 busEntry->SetSize( size );
3757 busEntry->SetStroke( stroke );
3767 Expecting(
"at, size, uuid or stroke" );
3771 return busEntry.release();
3781 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY,
LAYER_NOTES );
3783 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3785 if( token != T_LEFT )
3786 Expecting( T_LEFT );
3793 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3795 if( token != T_LEFT )
3796 Expecting( T_LEFT );
3803 polyline->AddPoint(
parseXY() );
3816 polyline->SetStroke( stroke );
3822 polyline->SetFillColor( fill.
m_Color );
3832 Expecting(
"pts, uuid, stroke, or fill" );
3836 return polyline.release();
3855 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
3858 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
3860 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3862 if( token != T_LEFT )
3863 Expecting( T_LEFT );
3876 line->SetStartPoint(
parseXY() );
3884 line->SetEndPoint(
parseXY() );
3891 line->SetStroke( stroke );
3901 Expecting(
"at, uuid or stroke" );
3905 return line.release();
3911 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
3912 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
3920 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
3922 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3924 if( token != T_LEFT )
3925 Expecting( T_LEFT );
3948 arc->SetStroke( stroke );
3954 arc->SetFillColor( fill.
m_Color );
3959 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
3964 Expecting(
"start, mid, end, stroke, fill or uuid" );
3968 arc->SetArcGeometry( startPoint, midPoint, endPoint );
3970 return arc.release();
3976 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
3977 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
3984 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
3986 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3988 if( token != T_LEFT )
3989 Expecting( T_LEFT );
4007 circle->SetStroke( stroke );
4013 circle->SetFillColor( fill.
m_Color );
4018 const_cast<KIID&
>( circle->m_Uuid ) =
KIID( FromUTF8() );
4023 Expecting(
"center, radius, stroke, fill or uuid" );
4027 circle->SetCenter( center );
4028 circle->SetEnd(
VECTOR2I( center.
x + radius, center.
y ) );
4030 return circle.release();
4036 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4037 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4042 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECTANGLE );
4044 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4046 if( token != T_LEFT )
4047 Expecting( T_LEFT );
4054 rectangle->SetPosition(
parseXY() );
4059 rectangle->SetEnd(
parseXY() );
4065 rectangle->SetStroke( stroke );
4071 rectangle->SetFillColor( fill.
m_Color );
4076 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4081 Expecting(
"start, end, stroke, fill or uuid" );
4085 return rectangle.release();
4091 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4092 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4097 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4099 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4101 if( token != T_LEFT )
4102 Expecting( T_LEFT );
4116 ruleArea->SetPolyShape( sch_rule_poly );
4118 ruleArea->SetStroke( poly->GetStroke() );
4119 ruleArea->SetFillMode( poly->GetFillMode() );
4120 ruleArea->SetFillColor( poly->GetFillColor() );
4124 Expecting(
"polyline" );
4128 return ruleArea.release();
4134 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4135 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4140 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
4142 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4144 if( token != T_LEFT )
4145 Expecting( T_LEFT );
4155 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4157 if( token != T_LEFT )
4158 Expecting( T_LEFT );
4167 case 0: bezier->SetStart(
parseXY() );
break;
4168 case 1: bezier->SetBezierC1(
parseXY() );
break;
4169 case 2: bezier->SetBezierC2(
parseXY() );
break;
4170 case 3: bezier->SetEnd(
parseXY() );
break;
4171 default: Unexpected(
"control point" );
break;
4181 bezier->SetStroke( stroke );
4187 bezier->SetFillColor( fill.
m_Color );
4192 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4197 Expecting(
"pts, stroke, fill or uuid" );
4201 return bezier.release();
4208 std::unique_ptr<SCH_TEXT>
text;
4212 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4213 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4214 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4215 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4216 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4217 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4219 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4223 text->ClearFieldsAutoplaced();
4227 text->SetText( FromUTF8() );
4229 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4231 if( token != T_LEFT )
4232 Expecting( T_LEFT );
4238 case T_exclude_from_sim:
4249 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4265 Unexpected( T_shape );
4273 case T_input: label->
SetShape( LABEL_FLAG_SHAPE::L_INPUT );
break;
4274 case T_output: label->
SetShape( LABEL_FLAG_SHAPE::L_OUTPUT );
break;
4275 case T_bidirectional: label->
SetShape( LABEL_FLAG_SHAPE::L_BIDI );
break;
4276 case T_tri_state: label->
SetShape( LABEL_FLAG_SHAPE::L_TRISTATE );
break;
4277 case T_passive: label->
SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED );
break;
4278 case T_dot: label->
SetShape( LABEL_FLAG_SHAPE::F_DOT );
break;
4279 case T_round: label->
SetShape( LABEL_FLAG_SHAPE::F_ROUND );
break;
4280 case T_diamond: label->
SetShape( LABEL_FLAG_SHAPE::F_DIAMOND );
break;
4281 case T_rectangle: label->
SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE );
break;
4283 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4294 Unexpected( T_length );
4303 case T_fields_autoplaced:
4305 text->SetFieldsAutoplaced();
4335 Unexpected( T_property );
4362 Expecting(
"at, shape, iref, uuid or effects" );
4368 if( label && label->
GetFields().empty() )
4371 return text.release();
4377 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4378 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4380 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4384 return textBox.release();
4390 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4391 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4393 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4397 return cell.release();
4413 bool foundEnd =
false;
4414 bool foundSize =
false;
4415 bool foundMargins =
false;
4419 aTextBox->
SetText( FromUTF8() );
4421 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4423 if( token != T_LEFT )
4424 Expecting( T_LEFT );
4430 case T_exclude_from_sim:
4461 cell->SetColSpan(
parseInt(
"column span" ) );
4462 cell->SetRowSpan(
parseInt(
"row span" ) );
4466 Expecting(
"at, size, stroke, fill, effects or uuid" );
4489 foundMargins =
true;
4505 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4507 Expecting(
"at, size, stroke, fill, effects or uuid" );
4515 else if( foundSize )
4516 aTextBox->
SetEnd( pos + size );
4518 Expecting(
"size" );
4533 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4534 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4538 STROKE_PARAMS borderStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4539 STROKE_PARAMS separatorsStroke( defaultLineWidth, LINE_STYLE::DEFAULT );
4540 std::unique_ptr<SCH_TABLE> table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4542 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4544 if( token != T_LEFT )
4545 Expecting( T_LEFT );
4551 case T_column_count:
4552 table->SetColCount(
parseInt(
"column count" ) );
4556 case T_column_widths:
4560 while( ( token = NextTok() ) != T_RIGHT )
4570 while( ( token = NextTok() ) != T_RIGHT )
4577 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4579 if( token != T_LEFT )
4580 Expecting( T_LEFT );
4584 if( token != T_table_cell )
4585 Expecting(
"table_cell" );
4593 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4595 if( token != T_LEFT )
4596 Expecting( T_LEFT );
4603 table->SetStrokeExternal(
parseBool() );
4614 table->SetBorderStroke( borderStroke );
4618 Expecting(
"external, header or stroke" );
4626 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4628 if( token != T_LEFT )
4629 Expecting( T_LEFT );
4647 table->SetSeparatorsStroke( separatorsStroke );
4651 Expecting(
"rows, cols, or stroke" );
4659 Expecting(
"columns, col_widths, row_heights, border, separators, header or cells" );
4663 return table.release();
4669 wxCHECK_RET( CurTok() == T_bus_alias,
4670 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4671 wxCHECK( aScreen, );
4674 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
4685 busAlias->SetName( alias );
4690 if( token != T_members )
4691 Expecting(
"members" );
4695 while( token != T_RIGHT )
4697 if( !IsSymbol( token ) )
4698 Expecting(
"quoted string" );
4700 member = FromUTF8();
4705 busAlias->Members().emplace_back( member );
4718 bool aReplaceInList )
4725 if( aReplaceInList )
4732 std::get<1>( it->second ),
4733 std::get<2>( it->second ) ) );
constexpr EDA_IU_SCALE schIUScale
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
void SetContentModified(bool aModified=true)
KICAD_T Type() const
Returns the type of object.
virtual void SetParent(EDA_ITEM *aParent)
SHAPE_POLY_SET & GetPolyShape()
void SetFillColor(const COLOR4D &aColor)
int GetPointCount() const
void SetEnd(const VECTOR2I &aEnd)
void SetFillMode(FILL_T aFill)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
void SetTextColor(const COLOR4D &aColor)
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetTextPos(const VECTOR2I &aPoint)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
Set only the italic flag, without changing the font.
virtual void SetVisible(bool aVisible)
void SetLineSpacing(double aLineSpacing)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
static bool ValidateHyperlink(const wxString &aURL)
Check if aURL is a valid hyperlink.
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
void SetHyperlink(wxString aLink)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetFont(KIFONT::FONT *aFont)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void ParseEmbedded(EMBEDDED_FILES *aFiles)
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
const std::vector< wxString > * GetFontFiles() const
If we just need the cached version of the font files, we can use this function which is const and wil...
void SetAreFontsEmbedded(bool aEmbedFonts)
Simple container to manage fill parameters.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false, const std::vector< wxString > *aEmbeddedFiles=nullptr, bool aForDrawingSheet=false)
A color representation with 4 components: red, green, blue, alpha.
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Define a library symbol object.
wxString GetName() const override
int UpdateFieldOrdinals()
Order optional field indices.
EMBEDDED_FILES * GetEmbeddedFiles() override
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
static const wxChar Custom[]
"User" defined page type
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
const BITMAP_BASE & GetImage() const
Get the underlying image.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
Holds all the data relating to one schematic.
EMBEDDED_FILES * GetEmbeddedFiles() override
Object to handle a bitmap image that can be inserted in a schematic.
Class for a wire to bus entry.
void SetPinLength(int aLength)
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
const wxString & GetInternalName()
Get the initial name of the field set at creation (or set by SetName()).
SCH_ITEM * ParseSymbolDrawItem()
SCH_SHAPE * parseSymbolPolyLine()
SCH_TABLE * parseSchTable()
bool m_appending
Appending load status.
unsigned m_lastProgressLine
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
SCH_SHAPE * parseSchCircle()
SCH_TEXT * parseSchText()
SCH_TABLECELL * parseSchTableCell()
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
void parsePinNumbers(std::unique_ptr< LIB_SYMBOL > &aSymbol)
LIB_SYMBOL * parseLibSymbol(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_RULE_AREA * parseSchRuleArea()
PROGRESS_REPORTER * m_progressReporter
void parseFill(FILL_PARAMS &aFill)
SCH_TEXTBOX * parseSymbolTextBox()
void parseBusAlias(SCH_SCREEN *aScreen)
std::set< int > m_fieldIDsRead
Field IDs that have been read so far for the current symbol.
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.
int m_unit
The current unit being parsed.
SCH_SHAPE * parseSymbolBezier()
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax, bool aEnforceMinTextSize=true)
SCH_TEXTBOX * parseSchTextBox()
SCH_SHEET * m_rootSheet
The rootsheet for full project loads or null for importing a schematic.
SCH_SHAPE * parseSchArc()
SCH_SHAPE * parseSchPolyLine()
SCH_BITMAP * parseImage()
SCH_SHAPE * parseSymbolCircle()
wxString m_generatorVersion
void ParseLib(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_PIN * parseSymbolPin()
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
std::map< EDA_TEXT *, std::tuple< wxString, bool, bool > > m_fontTextMap
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
wxString m_symbolName
The current symbol name.
VECTOR2I parseXY(bool aInvertY=false)
SCH_SHAPE * parseSymbolRectangle()
void parsePinNames(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SHAPE * parseSchBezier()
void removeEntryInFontTextMap(EDA_TEXT *aEntry, EDA_TEXT *aCandidate, bool aReplaceInList)
Remove aEntry from m_fontTextMap.
SCH_JUNCTION * parseJunction()
void ParseSchematic(SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Parse the internal LINE_READER object into aSheet.
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
int m_bodyStyle
The current body style being parsed.
SCH_NO_CONNECT * parseNoConnect()
SCH_TEXT * parseSymbolText()
SCH_SHAPE * parseSymbolArc()
SCH_BUS_WIRE_ENTRY * parseBusEntry()
SCH_SHAPE * parseSchRectangle()
SCH_FIELD * parseProperty(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SYMBOL * parseSchematicSymbol()
void parseSchTextBoxContent(SCH_TEXTBOX *aTextBox)
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
int m_requiredVersion
Set to the symbol library file version required.
const LINE_READER * m_lineReader
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
Parse internal LINE_READER object into symbols and return all found.
void parseSchSheetInstances(SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
SCH_IO_KICAD_SEXPR_PARSER(LINE_READER *aLineReader=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, unsigned aLineCount=0, SCH_SHEET *aRootSheet=nullptr, bool aIsAppending=false)
Base class for any item which can be embedded within the SCHEMATIC container class,...
void SetFieldsAutoplaced()
void SetShape(LABEL_FLAG_SHAPE aShape)
std::vector< SCH_FIELD > & GetFields()
Segment description base class to describe items which have 2 end points (track, wire,...
void SetStartPoint(const VECTOR2I &aPosition)
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
void SetEndPoint(const VECTOR2I &aPosition)
void SetFileFormatVersionAtLoad(int aVersion)
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).
void SetPageSettings(const PAGE_INFO &aPageSettings)
const KIID & GetUuid() const
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
SCHEMATIC * Schematic() const
void FixupEmbeddedData()
After loading a file from disk, the library symbols do not yet contain the full data for their embedd...
int GetFileFormatVersionAtLoad() const
KIID m_uuid
A unique identifier for each schematic file.
std::vector< SCH_SYMBOL_INSTANCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
void SetPosition(const VECTOR2I &aPos) override
void SetStroke(const STROKE_PARAMS &aStroke) override
STROKE_PARAMS GetStroke() const override
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslated=true)
SCH_SCREEN * GetScreen() const
void SetMarginBottom(int aBottom)
int GetLegacyTextMargin() const
void SetMarginLeft(int aLeft)
void SetMarginRight(int aRight)
void SetMarginTop(int aTop)
void SetExcludedFromSim(bool aExclude) override
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetLineStyle(LINE_STYLE aLineStyle)
LINE_STYLE GetLineStyle() const
KIGFX::COLOR4D GetColor() const
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_360
static constexpr EDA_ANGLE ANGLE_180
FONTCONFIG * Fontconfig()
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
#define MAX_PAGE_SIZE_EESCHEMA_MM
#define MIN_PAGE_SIZE_MM
Min and max page sizes for clamping, in mm.
PGM_BASE & Pgm()
The global Program "get" accessor.
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
@ SHEET_MANDATORY_FIELDS
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
#define SIM_LEGACY_ENABLE_FIELD
#define SIM_LEGACY_ENABLE_FIELD_V7
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString UnescapeString(const wxString &aSource)
constexpr int MilsToIU(int mils) const
A filename or source description, a problem input line, a line number, a byte offset,...
ELECTRICAL_PINTYPE m_Type
A simple container for sheet instance information.
A simple container for schematic symbol instance information.
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP
wxString GetCanonicalFieldName(int idx)
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ MANDATORY_FIELDS
The first 5 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
VECTOR2< int32_t > VECTOR2I