31#include <fmt/format.h>
35#include <wx/mstream.h>
36#include <wx/tokenzr.h>
73using namespace TSCHEMATIC_T;
78 unsigned aLineCount,
SCH_SHEET* aRootSheet,
80 SCHEMATIC_LEXER( aLineReader ),
99 unsigned progressDelta = std::max( 50u,
m_lineCount / 10 );
118 KIID id( FromUTF8() );
135 else if( token == T_no )
138 Expecting(
"yes or no" );
149 bool ret = aDefaultValue;
151 if( PrevTok() == T_LEFT )
156 if(
static_cast<int>( token ) ==
DSN_RIGHT )
157 return aDefaultValue;
161 else if( token == T_no )
164 Expecting(
"yes or no" );
171 return aDefaultValue;
189 bool versionChecked =
false;
200 versionChecked =
true;
203 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
205 if( token != T_LEFT )
231 case T_generator_version:
254 aSymbolLibMap[symbol->
GetName()] = symbol;
259 wxString warning = wxString::Format(
260 _(
"Error parsing symbol at line %d: %s\nSkipping symbol and continuing." ),
261 CurLineNumber(), e.
What() );
273 Expecting(
"symbol, generator, or generator_version" );
287 if( CurTok() == T_LEFT )
291 if( CurTok() == T_symbol )
296 const std::vector<wxString>* embeddedFonts =
303 textItem->ResolveFont( embeddedFonts );
309 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
310 GetTokenString( CurTok() ) );
321 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
322 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
329 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
331 symbol->SetUnitCount( 1,
true );
335 if( !IsSymbol( token ) )
336 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
343 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
350 if(
static_cast<int>(
name.size() ) > bad_pos )
352 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
361 CurLineNumber(), CurOffset() );
366 symbol->SetLibId(
id );
368 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
370 if( token != T_LEFT )
378 symbol->SetGlobalPower();
381 if( token == T_RIGHT )
384 if( token == T_local )
385 symbol->SetLocalPower();
386 else if( token != T_global )
387 Expecting(
"global or local" );
404 case T_exclude_from_sim:
405 symbol->SetExcludedFromSim(
parseBool() );
410 symbol->SetExcludedFromBOM( !
parseBool() );
415 symbol->SetExcludedFromBoard( !
parseBool() );
420 symbol->SetExcludedFromPosFiles( !
parseBool() );
424 case T_duplicate_pin_numbers_are_jumpers:
425 symbol->SetDuplicatePinNumbersAreJumpers(
parseBool() );
429 case T_jumper_pin_groups:
431 std::vector<std::set<wxString>>& groups = symbol->JumperPinGroups();
432 std::set<wxString>* currentGroup =
nullptr;
434 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
436 switch(
static_cast<int>( token ) )
439 currentGroup = &groups.emplace_back();
443 currentGroup->insert( FromUTF8() );
447 currentGroup =
nullptr;
451 Expecting(
"list of pin names" );
466 if( !IsSymbol( token ) )
469 CurLineNumber(), CurOffset() );
477 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
479 symbol->SetParentName(
name );
488 if( !IsSymbol( token ) )
491 CurLineNumber(), CurOffset() );
499 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
503 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
504 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
509 wxStringTokenizer tokenizer(
name,
"_" );
511 if( tokenizer.CountTokens() != 2 )
513 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
514 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
517 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
519 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
520 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
523 m_unit =
static_cast<int>( tmp );
525 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
527 error.Printf(
_(
"Invalid symbol body style number %s" ),
name.c_str() );
528 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
534 symbol->SetBodyStyleCount(
m_bodyStyle,
false,
false );
536 if(
m_unit > symbol->GetUnitCount() )
537 symbol->SetUnitCount(
m_unit,
false );
539 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
541 if( token != T_LEFT )
551 if( IsSymbol( token ) )
552 symbol->GetUnitDisplayNames()[
m_unit] = FromUTF8();
567 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
570 symbol->AddDrawItem( item,
false );
574 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
593 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
596 symbol->AddDrawItem( item,
false );
599 case T_embedded_fonts:
601 symbol->SetAreFontsEmbedded(
parseBool() );
606 case T_embedded_files:
609 embeddedFilesParser.SyncLineReaderWith( *
this );
613 embeddedFilesParser.
ParseEmbedded( symbol->GetEmbeddedFiles() );
621 for(
int tok = embeddedFilesParser.NextTok();
623 tok = embeddedFilesParser.NextTok() )
627 else if( tok ==
DSN_RIGHT && --depth < 0 )
632 SyncLineReaderWith( embeddedFilesParser );
637 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
638 "rectangle, or text" );
642 symbol->GetDrawItems().sort();
645 const std::vector<wxString>* embeddedFonts = symbol->GetEmbeddedFiles()->UpdateFontFiles();
647 symbol->RunOnChildren(
651 textItem->ResolveFont( embeddedFonts );
658 symbol->SetHasDeMorganBodyStyles( symbol->HasLegacyAlternateBodyStyle() );
660 symbol->RefreshLibraryTreeCaches();
662 return symbol.release();
678 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
692 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
694 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
702 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
704 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
711 strokeParser.SyncLineReaderWith( *
this );
714 SyncLineReaderWith( strokeParser );
720 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
727 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
729 if( token != T_LEFT )
749 default: Expecting(
"none, outline, hatch, reverse_hatch, "
750 "cross_hatch, color or background" );
764 color.
a = std::clamp(
parseDouble(
"alpha" ), 0.0, 1.0 );
771 Expecting(
"type or color" );
778 bool aEnforceMinTextSize )
780 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
781 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
798 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
800 if( token == T_LEFT )
806 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
808 if( token == T_LEFT )
848 color.
a = std::clamp(
parseDouble(
"alpha" ), 0.0, 1.0 );
859 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
866 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
875 case T_mirror:
break;
876 default: Expecting(
"left, right, top, bottom, or mirror" );
885 wxString hyperlink = FromUTF8();
890 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
909 Expecting(
"font, justify, hide or href" );
917 if( CurTok() != aHeaderType )
920 GetTokenString( CurTok() ) ),
921 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
928 if( tok == T_version )
942 wxCHECK_RET( CurTok() == T_body_styles,
943 "Cannot parse " + GetTokenString( CurTok() ) +
" as a body_styles token." );
945 std::vector<wxString> names;
947 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
949 if( token == T_demorgan )
951 aSymbol->SetHasDeMorganBodyStyles(
true );
954 else if( !IsSymbol( token ) )
956 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
960 names.push_back( FromUTF8() );
964 aSymbol->SetBodyStyleNames( names );
970 wxCHECK_RET( CurTok() == T_pin_names,
971 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
981 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
984 if( token == T_hide )
986 aSymbol->SetShowPinNames(
false );
990 if( token != T_LEFT )
1005 aSymbol->SetShowPinNames( !
parseBool() );
1010 Expecting(
"offset or hide" );
1018 wxCHECK_RET( CurTok() == T_pin_numbers,
1019 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_number token." );
1028 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
1031 if( token == T_hide )
1033 aSymbol->SetShowPinNumbers(
false );
1037 if( token != T_LEFT )
1039 Expecting( T_LEFT );
1047 aSymbol->SetShowPinNumbers( !
parseBool() );
1052 Expecting(
"hide" );
1061 wxCHECK_MSG( CurTok() == T_property,
nullptr,
1062 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
1063 wxCHECK( aSymbol,
nullptr );
1068 bool isPrivate =
false;
1069 bool isVisible =
true;
1071 T token = NextTok();
1073 if( token == T_private )
1079 if( !IsSymbol( token ) )
1081 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
1087 if(
name.IsEmpty() )
1089 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
1103 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(), fieldId,
name );
1104 field->SetPrivate( isPrivate );
1105 field->SetVisible( isVisible );
1109 if( !IsSymbol( token ) )
1111 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1118 value = wxEmptyString;
1122 field->SetText( value );
1124 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1126 if( token != T_LEFT )
1127 Expecting( T_LEFT );
1139 field->SetPosition(
parseXY(
true ) );
1157 field->SetNameShown( show );
1161 case T_do_not_autoplace:
1164 field->SetCanAutoplace( !doNotAutoplace );
1169 Expecting(
"id, at, hide, show_name, do_not_autoplace, or effects" );
1175 if( field->IsMandatory() )
1177 existingField = aSymbol->GetField( field->GetId() );
1179 *existingField = *field;
1180 return existingField;
1182 else if(
name ==
"ki_keywords" )
1185 aSymbol->SetKeyWords( value );
1189 else if(
name ==
"ki_description" )
1191 aSymbol->SetDescription( value );
1194 else if(
name ==
"ki_fp_filters" )
1197 wxArrayString filters;
1198 wxStringTokenizer tokenizer( value,
" \t\r\n", wxTOKEN_STRTOK );
1200 while( tokenizer.HasMoreTokens() )
1202 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1203 filters.Add( curr_token );
1206 aSymbol->SetFPFilters( filters );
1209 else if(
name ==
"ki_locked" )
1213 aSymbol->LockUnits(
true );
1219 existingField = aSymbol->GetField( field->GetCanonicalName() );
1227 wxString base_name = field->GetCanonicalName();
1230 for(
int ii = 1; ii < 10 && existingField; ii++ )
1232 wxString newname = base_name;
1233 newname <<
'_' << ii;
1235 existingField = aSymbol->GetField( newname );
1237 if( !existingField )
1238 field->SetName( newname );
1242 if( !existingField )
1244 aSymbol->AddDrawItem( field.get(),
false );
1245 return field.release();
1258 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1259 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1265 bool hasMidPoint =
false;
1273 bool hasAngles =
false;
1282 if( token == T_private )
1284 arc->SetPrivate(
true );
1288 for( ; token != T_RIGHT; token = NextTok() )
1290 if( token != T_LEFT )
1291 Expecting( T_LEFT );
1314 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1316 if( token != T_LEFT )
1317 Expecting( T_LEFT );
1345 Expecting(
"at, length, or angles" );
1353 arc->SetStroke( stroke );
1359 arc->SetFillColor( fill.
m_Color );
1363 Expecting(
"start, mid, end, radius, stroke, or fill" );
1369 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1380 EDA_ANGLE arc_start, arc_end, arc_angle;
1381 arc->CalcArcAngles( arc_start, arc_end );
1382 arc_angle = arc_end - arc_start;
1387 arc->SetStart( endPoint );
1388 arc->SetEnd( startPoint );
1391 arc->SetCenter( new_center );
1397 arc->SetCenter( new_center );
1401 else if( hasAngles )
1403 arc->SetCenter(
center );
1409 arc->SetStart( endPoint );
1410 arc->SetEnd( startPoint );
1414 EDA_ANGLE arc_start, arc_end, arc_angle;
1415 arc->CalcArcAngles( arc_start, arc_end );
1416 arc_angle = arc_end - arc_start;
1422 arc->SetStart( startPoint );
1423 arc->SetEnd( endPoint );
1431 arc->SetStart( startPoint );
1432 arc->SetEnd( endPoint );
1436 arc->SetCenter( new_center );
1442 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1445 return arc.release();
1451 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1452 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1460 bezier->SetUnit(
m_unit );
1465 if( token == T_private )
1467 bezier->SetPrivate(
true );
1471 for( ; token != T_RIGHT; token = NextTok() )
1473 if( token != T_LEFT )
1474 Expecting( T_LEFT );
1484 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1486 if( token != T_LEFT )
1487 Expecting( T_LEFT );
1496 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1497 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1498 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1499 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1500 default: Unexpected(
"control point" );
break;
1510 bezier->SetStroke( stroke );
1516 bezier->SetFillColor( fill.
m_Color );
1520 Expecting(
"pts, stroke, or fill" );
1524 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
1526 return bezier.release();
1532 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1533 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1548 if( token == T_private )
1550 circle->SetPrivate(
true );
1554 for( ; token != T_RIGHT; token = NextTok() )
1556 if( token != T_LEFT )
1557 Expecting( T_LEFT );
1575 circle->SetStroke( stroke );
1585 Expecting(
"center, radius, stroke, or fill" );
1618 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1619 "power_in, power_out, open_collector, open_emitter, free or "
1641 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1642 "output_low, edge_clock_high, non_logic" );
1647 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1648 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1651 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1658 pin->SetType( parseType( token ) );
1662 pin->SetShape( parseShape( token ) );
1664 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1667 if( token == T_hide )
1669 pin->SetVisible(
false );
1673 if( token != T_LEFT )
1674 Expecting( T_LEFT );
1683 switch(
parseInt(
"pin orientation" ) )
1689 default: Expecting(
"0, 90, 180, or 270" );
1708 if( !IsSymbol( token ) )
1715 pin->SetName( wxEmptyString );
1719 pin->SetName( FromUTF8() );
1723 if( token != T_RIGHT )
1727 if( token == T_effects )
1734 pin->SetNameTextSize(
text.GetTextHeight() );
1739 Expecting(
"effects" );
1748 if( !IsSymbol( token ) )
1751 CurLineNumber(), CurOffset() );
1755 pin->SetNumber( wxEmptyString );
1759 pin->SetNumber( FromUTF8() );
1763 if( token != T_RIGHT )
1767 if( token == T_effects )
1774 pin->SetNumberTextSize(
text.GetTextHeight() );
1779 Expecting(
"effects" );
1791 if( !IsSymbol( token ) )
1794 CurLineNumber(), CurOffset() );
1800 alt.
m_Type = parseType( token );
1803 alt.
m_Shape = parseShape( token );
1805 pin->GetAlternates()[ alt.
m_Name ] = alt;
1812 Expecting(
"at, name, number, hide, length, or alternate" );
1816 return pin.release();
1822 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1823 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1835 if( token == T_private )
1837 poly->SetPrivate(
true );
1841 for( ; token != T_RIGHT; token = NextTok() )
1843 if( token != T_LEFT )
1844 Expecting( T_LEFT );
1851 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1853 if( token != T_LEFT )
1854 Expecting( T_LEFT );
1861 poly->AddPoint(
parseXY(
true ) );
1870 poly->SetStroke( stroke );
1876 poly->SetFillColor( fill.
m_Color );
1880 Expecting(
"pts, stroke, or fill" );
1884 return poly.release();
1890 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1891 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1898 rectangle->SetUnit(
m_unit );
1903 if( token == T_private )
1905 rectangle->SetPrivate(
true );
1909 for( ; token != T_RIGHT; token = NextTok() )
1911 if( token != T_LEFT )
1912 Expecting( T_LEFT );
1919 rectangle->SetPosition(
parseXY(
true ) );
1924 rectangle->SetEnd(
parseXY(
true ) );
1935 rectangle->SetStroke( stroke );
1941 rectangle->SetFillColor( fill.
m_Color );
1945 Expecting(
"start, end, stroke, or fill" );
1949 return rectangle.release();
1955 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1956 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1959 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1966 if( token == T_private )
1968 text->SetPrivate(
true );
1972 if( !IsSymbol( token ) )
1974 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1978 text->SetText( FromUTF8() );
1980 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1982 if( token != T_LEFT )
1983 Expecting( T_LEFT );
2001 Expecting(
"at or effects" );
2006 if( !
text->IsVisible() )
2009 return text.release();
2015 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
2016 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
2028 bool foundEnd =
false;
2029 bool foundSize =
false;
2030 bool foundMargins =
false;
2032 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
2034 textBox->SetUnit(
m_unit );
2038 if( token == T_private )
2040 textBox->SetPrivate(
true );
2044 if( !IsSymbol( token ) )
2046 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
2050 textBox->SetText( FromUTF8() );
2052 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2054 if( token != T_LEFT )
2055 Expecting( T_LEFT );
2086 textBox->SetStroke( stroke );
2092 textBox->SetFillColor( fill.
m_Color );
2097 textBox->SetMarginLeft(
left );
2098 textBox->SetMarginTop(
top );
2099 textBox->SetMarginRight(
right );
2100 textBox->SetMarginBottom( bottom );
2101 foundMargins =
true;
2110 Expecting(
"at, size, stroke, fill or effects" );
2114 textBox->SetPosition( pos );
2117 textBox->SetEnd(
end );
2118 else if( foundSize )
2119 textBox->SetEnd( pos + size );
2121 Expecting(
"size" );
2125 int margin = textBox->GetLegacyTextMargin();
2126 textBox->SetMarginLeft( margin );
2127 textBox->SetMarginTop( margin );
2128 textBox->SetMarginRight( margin );
2129 textBox->SetMarginBottom( margin );
2132 return textBox.release();
2138 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
2139 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
2145 wxString pageType = FromUTF8();
2147 if( !aPageInfo.
SetType( pageType ) )
2149 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
2176 if( token == T_portrait )
2181 else if( token != T_RIGHT )
2183 Expecting(
"portrait" );
2190 wxCHECK_RET( CurTok() == T_title_block,
2191 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
2195 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2197 if( token != T_LEFT )
2198 Expecting( T_LEFT );
2206 aTitleBlock.
SetTitle( FromUTF8() );
2211 aTitleBlock.
SetDate( FromUTF8() );
2226 int commentNumber =
parseInt(
"comment" );
2228 switch( commentNumber )
2277 CurLine(), CurLineNumber(), CurOffset() );
2284 Expecting(
"title, date, rev, company, or comment" );
2294 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2295 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2297 bool is_private =
false;
2299 T token = NextTok();
2301 if( token == T_private )
2307 if( !IsSymbol( token ) )
2309 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2313 wxString
name = FromUTF8();
2315 if(
name.IsEmpty() )
2317 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2323 if( !IsSymbol( token ) )
2325 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2333 value = wxEmptyString;
2365 if(
name.CmpNoCase( wxT(
"Sheet name" ) ) == 0 )
2367 else if(
name.CmpNoCase( wxT(
"Sheet file" ) ) == 0 )
2382 if(
name.CmpNoCase( wxT(
"Intersheet References" ) ) == 0 )
2386 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( aParent, fieldId,
name );
2387 field->SetText( value );
2390 field->SetPrivate( is_private );
2392 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2394 if( token != T_LEFT )
2395 Expecting( T_LEFT );
2407 field->SetPosition(
parseXY() );
2425 field->SetNameShown( show );
2429 case T_do_not_autoplace:
2432 field->SetCanAutoplace( !doNotAutoplace );
2437 Expecting(
"id, at, hide, show_name, do_not_autoplace or effects" );
2441 return field.release();
2447 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2448 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2449 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2451 T token = NextTok();
2453 if( !IsSymbol( token ) )
2455 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2459 wxString
name = FromUTF8();
2461 if(
name.IsEmpty() )
2463 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2467 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2479 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2482 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2484 if( token != T_LEFT )
2485 Expecting( T_LEFT );
2493 sheetPin->SetPosition(
parseXY() );
2495 double angle =
parseDouble(
"sheet pin angle (side)" );
2499 else if( angle == 90.0 )
2501 else if( angle == 180.0 )
2503 else if( angle == 270.0 )
2506 Expecting(
"0, 90, 180, or 270" );
2523 Expecting(
"at, uuid or effects" );
2527 return sheetPin.release();
2533 wxCHECK_RET( CurTok() == T_sheet_instances,
2534 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2535 wxCHECK( aScreen, );
2539 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2541 if( token != T_LEFT )
2542 Expecting( T_LEFT );
2560 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2562 if( token != T_LEFT )
2563 Expecting( T_LEFT );
2567 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2570 size_t numReplacements = 0;
2588 for(
const wxString& ch : whitespaces )
2589 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2594 if( numReplacements > 0 )
2601 Expecting(
"path or page" );
2606 && ( instance.
m_Path.empty() ) )
2622 Expecting(
"path" );
2630 wxCHECK_RET( CurTok() == T_symbol_instances,
2631 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2632 wxCHECK( aScreen, );
2637 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2639 if( token != T_LEFT )
2640 Expecting( T_LEFT );
2657 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2659 if( token != T_LEFT )
2660 Expecting( T_LEFT );
2681 instance.
m_Value = wxEmptyString;
2683 instance.
m_Value = FromUTF8();
2700 Expecting(
"path, unit, value or footprint" );
2709 Expecting(
"path" );
2718 wxCHECK( aSheet !=
nullptr, );
2722 wxCHECK( screen !=
nullptr, );
2725 m_maxError = schematic->Settings().m_MaxError;
2727 if( aIsCopyableOnly )
2730 bool fileHasUuid =
false;
2744 if( !aIsCopyableOnly )
2749 if( CurTok() != T_kicad_sch )
2750 Expecting(
"kicad_sch" );
2769 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2771 if( aIsCopyableOnly && token == T_EOF )
2774 if( token != T_LEFT )
2775 Expecting( T_LEFT );
2809 case T_generator_version:
2835 if( aIsCopyableOnly )
2836 Unexpected( T_paper );
2846 if( aIsCopyableOnly )
2847 Unexpected( T_page );
2851 NeedSYMBOLorNUMBER();
2852 NeedSYMBOLorNUMBER();
2859 if( aIsCopyableOnly )
2860 Unexpected( T_title_block );
2874 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2876 if( token != T_LEFT )
2877 Expecting( T_LEFT );
2889 Expecting(
"symbol" );
2946 THROW_PARSE_ERROR(
_(
"Schematic polyline has too few points" ), CurSource(), CurLine(),
2947 CurLineNumber(), CurOffset() );
2997 case T_netclass_flag:
3002 case T_global_label:
3003 case T_hierarchical_label:
3004 case T_directive_label:
3016 case T_sheet_instances:
3020 case T_symbol_instances:
3025 if( aIsCopyableOnly )
3026 Unexpected( T_bus_alias );
3031 case T_embedded_fonts:
3037 CurLineNumber(), CurOffset() );
3044 case T_embedded_files:
3050 CurLineNumber(), CurOffset() );
3053 embeddedFilesParser.SyncLineReaderWith( *
this );
3065 for(
int tok = embeddedFilesParser.NextTok();
3067 tok = embeddedFilesParser.NextTok() )
3071 else if( tok ==
DSN_RIGHT && --depth < 0 )
3076 SyncLineReaderWith( embeddedFilesParser );
3082 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
3083 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
3084 "sheet, symbol, symbol_instances, text, title_block" );
3105 CurLineNumber(), CurOffset() );
3109 std::vector<std::string> fontNames;
3110 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
3120 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
3121 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
3126 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
3128 std::set<int> fieldIDsRead;
3133 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3135 if( token != T_LEFT )
3136 Expecting( T_LEFT );
3148 if( !IsSymbol( token ) )
3151 CurLineNumber(), CurOffset() );
3154 libName = FromUTF8();
3158 libName.Replace(
"{slash}",
"/" );
3168 if( !IsSymbol( token ) && token != T_NUMBER )
3169 Expecting(
"symbol|number" );
3172 wxString
name = FromUTF8();
3176 name.Replace(
"{slash}",
"/" );
3182 if(
static_cast<int>(
name.size() ) > bad_pos )
3184 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
3192 CurLineNumber(), CurOffset() );
3195 symbol->SetLibId( libId );
3201 symbol->SetPosition(
parseXY() );
3203 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3206 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3207 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3208 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3209 default: Expecting(
"0, 90, 180, or 270" );
3212 symbol->SetTransform( transform );
3221 else if( token == T_y )
3224 Expecting(
"x or y" );
3230 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3236 symbol->SetBodyStyle(
parseInt(
"symbol body style" ) );
3240 case T_exclude_from_sim:
3241 symbol->SetExcludedFromSim(
parseBool() );
3246 symbol->SetExcludedFromBOM( !
parseBool() );
3251 symbol->SetExcludedFromBoard( !
parseBool() );
3255 case T_in_pos_files:
3256 symbol->SetExcludedFromPosFiles( !
parseBool() );
3270 case T_fields_autoplaced:
3282 case T_default_instance:
3286 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3288 if( token != T_LEFT )
3289 Expecting( T_LEFT );
3310 symbol->SetValueFieldText( wxEmptyString );
3312 symbol->SetValueFieldText( FromUTF8() );
3321 symbol->SetFootprintFieldText( wxEmptyString );
3323 symbol->SetFootprintFieldText( FromUTF8() );
3329 Expecting(
"reference, unit, value or footprint" );
3338 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3340 if( token != T_LEFT )
3341 Expecting( T_LEFT );
3345 if( token != T_project )
3346 Expecting(
"project" );
3350 wxString projectName = FromUTF8();
3352 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3354 if( token != T_LEFT )
3355 Expecting( T_LEFT );
3359 if( token != T_path )
3360 Expecting(
"path" );
3369 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3371 if( token != T_LEFT )
3372 Expecting( T_LEFT );
3393 symbol->SetValueFieldText( wxEmptyString );
3395 symbol->SetValueFieldText( FromUTF8() );
3404 symbol->SetFootprintFieldText( wxEmptyString );
3406 symbol->SetFootprintFieldText( FromUTF8() );
3417 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3419 if( token != T_LEFT )
3420 Expecting( T_LEFT );
3428 variant.
m_Name = FromUTF8();
3437 case T_exclude_from_sim:
3459 case T_in_pos_files:
3467 wxString fieldValue;
3469 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3471 if( token != T_LEFT )
3472 Expecting( T_LEFT );
3480 fieldName = FromUTF8();
3486 fieldValue = FromUTF8();
3491 Expecting(
"name or value" );
3495 variant.
m_Fields[fieldName] = fieldValue;
3500 Expecting(
"dnp, exclude_from_sim, field, in_bom, in_pos_files, name, or on_board" );
3510 Expecting(
"reference, unit, value, footprint, or variant" );
3514 symbol->AddHierarchicalReference( instance );
3530 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3538 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3546 existing = symbol->GetField( field->
GetId() );
3548 existing = symbol->GetField( field->
GetName() );
3553 symbol->AddField( *field );
3556 symbol->UpdatePrefix();
3569 number = FromUTF8();
3571 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3573 if( token != T_LEFT )
3574 Expecting( T_LEFT );
3598 Expecting(
"alternate or uuid" );
3602 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3608 Expecting(
"lib_id, lib_name, at, mirror, uuid, exclude_from_sim, on_board, in_bom, dnp, "
3609 "default_instance, property, pin, or instances" );
3613 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3614 symbol->SetSchSymbolLibraryName( libName );
3617 symbol->ClearFlags();
3619 return symbol.release();
3625 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3626 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3629 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3632 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3634 if( token != T_LEFT )
3635 Expecting( T_LEFT );
3642 bitmap->SetPosition(
parseXY() );
3668 data.reserve( 1 << 17 );
3670 while( token != T_RIGHT )
3672 if( !IsSymbol( token ) )
3673 Expecting(
"base64 image data" );
3679 wxMemoryBuffer buffer = wxBase64Decode( data );
3693 Expecting(
"at, scale, uuid, data or locked" );
3706 return bitmap.release();
3712 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3713 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3719 std::vector<SCH_FIELD> fields;
3720 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3721 std::set<int> fieldIDsRead;
3726 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3728 if( token != T_LEFT )
3729 Expecting( T_LEFT );
3736 sheet->SetPosition(
parseXY() );
3745 sheet->SetSize( size );
3750 case T_exclude_from_sim:
3751 sheet->SetExcludedFromSim(
parseBool() );
3756 sheet->SetExcludedFromBOM( !
parseBool() );
3761 sheet->SetExcludedFromBoard( !
parseBool() );
3775 case T_fields_autoplaced:
3783 sheet->SetBorderWidth( stroke.
GetWidth() );
3784 sheet->SetBorderColor( stroke.
GetColor() );
3789 sheet->SetBackgroundColor( fill.
m_Color );
3806 if( fields.empty() )
3812 fields.emplace_back( *field );
3823 std::vector<SCH_SHEET_INSTANCE> instances;
3825 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3827 if( token != T_LEFT )
3828 Expecting( T_LEFT );
3832 if( token != T_project )
3833 Expecting(
"project" );
3837 wxString projectName = FromUTF8();
3839 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3841 if( token != T_LEFT )
3842 Expecting( T_LEFT );
3846 if( token != T_path )
3847 Expecting(
"path" );
3856 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3858 if( token != T_LEFT )
3859 Expecting( T_LEFT );
3879 static std::vector<wxString> whitespaces =
3885 for( wxString ch : whitespaces )
3898 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3900 if( token != T_LEFT )
3901 Expecting( T_LEFT );
3909 variant.
m_Name = FromUTF8();
3918 case T_exclude_from_sim:
3940 case T_in_pos_files:
3948 wxString fieldValue;
3950 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3952 if( token != T_LEFT )
3953 Expecting( T_LEFT );
3961 fieldName = FromUTF8();
3967 fieldValue = FromUTF8();
3972 Expecting(
"name or value" );
3976 variant.
m_Fields[fieldName] = fieldValue;
3981 Expecting(
"dnp, exclude_from_sim, field, in_bom, in_pos_files, name, or on_board" );
3991 Expecting(
"page or variant" );
3995 instances.emplace_back( instance );
3999 sheet->setInstances( instances );
4004 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
4008 sheet->SetFields( fields );
4013 CurLineNumber(), CurOffset() );
4019 CurLineNumber(), CurOffset() );
4022 return sheet.release();
4028 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
4029 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
4032 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
4034 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4036 if( token != T_LEFT )
4037 Expecting( T_LEFT );
4044 junction->SetPosition(
parseXY() );
4060 color.
a = std::clamp(
parseDouble(
"alpha" ), 0.0, 1.0 );
4062 junction->SetColor( color );
4079 Expecting(
"at, diameter, color, uuid or locked" );
4083 return junction.release();
4089 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
4090 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
4093 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
4095 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4097 if( token != T_LEFT )
4098 Expecting( T_LEFT );
4105 no_connect->SetPosition(
parseXY() );
4121 Expecting(
"at, uuid or locked" );
4125 return no_connect.release();
4131 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
4132 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
4136 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
4138 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4140 if( token != T_LEFT )
4141 Expecting( T_LEFT );
4148 busEntry->SetPosition(
parseXY() );
4158 busEntry->SetSize( size );
4165 busEntry->SetStroke( stroke );
4180 Expecting(
"at, size, uuid, stroke or locked" );
4184 return busEntry.release();
4206 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4208 if( token != T_LEFT )
4209 Expecting( T_LEFT );
4216 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4218 if( token != T_LEFT )
4219 Expecting( T_LEFT );
4226 polyline->AddPoint(
parseXY() );
4239 polyline->SetStroke( stroke );
4245 polyline->SetFillColor( fill.
m_Color );
4261 Expecting(
"pts, uuid, stroke, fill or locked" );
4265 return polyline.release();
4284 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
4287 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
4289 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4291 if( token != T_LEFT )
4292 Expecting( T_LEFT );
4305 line->SetStartPoint(
parseXY() );
4313 line->SetEndPoint(
parseXY() );
4320 line->SetStroke( stroke );
4335 Expecting(
"pts, uuid, stroke or locked" );
4339 return line.release();
4345 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
4346 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
4354 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>(
SHAPE_T::ARC );
4356 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4358 if( token != T_LEFT )
4359 Expecting( T_LEFT );
4382 arc->SetStroke( stroke );
4388 arc->SetFillColor( fill.
m_Color );
4394 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
4404 Expecting(
"start, mid, end, stroke, fill, uuid or locked" );
4408 arc->SetArcGeometry( startPoint, midPoint, endPoint );
4410 return arc.release();
4416 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
4417 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4426 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4428 if( token != T_LEFT )
4429 Expecting( T_LEFT );
4447 circle->SetStroke( stroke );
4469 Expecting(
"center, radius, stroke, fill, uuid or locked" );
4482 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4483 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4488 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>(
SHAPE_T::RECTANGLE );
4490 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4492 if( token != T_LEFT )
4493 Expecting( T_LEFT );
4500 rectangle->SetPosition(
parseXY() );
4505 rectangle->SetEnd(
parseXY() );
4516 rectangle->SetStroke( stroke );
4522 rectangle->SetFillColor( fill.
m_Color );
4528 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4538 Expecting(
"start, end, stroke, fill, uuid or locked" );
4542 return rectangle.release();
4548 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4549 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4554 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4556 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4558 if( token != T_LEFT )
4559 Expecting( T_LEFT );
4573 ruleArea->SetPolyShape( sch_rule_poly );
4575 ruleArea->SetStroke( poly->GetStroke() );
4576 ruleArea->SetFillMode( poly->GetFillMode() );
4577 ruleArea->SetFillColor( poly->GetFillColor() );
4580 const_cast<KIID&
>( ruleArea->m_Uuid ) = poly->m_Uuid;
4584 case T_exclude_from_sim:
4585 ruleArea->SetExcludedFromSim(
parseBool() );
4590 ruleArea->SetExcludedFromBOM( !
parseBool() );
4595 ruleArea->SetExcludedFromBoard( !
parseBool() );
4610 Expecting(
"exclude_from_sim, on_board, in_bom, dnp, locked, or polyline" );
4614 return ruleArea.release();
4620 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4621 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4626 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>(
SHAPE_T::BEZIER );
4628 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4630 if( token != T_LEFT )
4631 Expecting( T_LEFT );
4641 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4643 if( token != T_LEFT )
4644 Expecting( T_LEFT );
4653 case 0: bezier->SetStart(
parseXY() );
break;
4654 case 1: bezier->SetBezierC1(
parseXY() );
break;
4655 case 2: bezier->SetBezierC2(
parseXY() );
break;
4656 case 3: bezier->SetEnd(
parseXY() );
break;
4657 default: Unexpected(
"control point" );
break;
4667 bezier->SetStroke( stroke );
4673 bezier->SetFillColor( fill.
m_Color );
4679 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4689 Expecting(
"pts, stroke, fill, uuid or locked" );
4693 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
4695 return bezier.release();
4702 std::unique_ptr<SCH_TEXT>
text;
4706 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4707 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4708 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4709 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4710 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4711 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4713 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4721 text->SetText( FromUTF8() );
4723 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4725 if( token != T_LEFT )
4726 Expecting( T_LEFT );
4732 case T_exclude_from_sim:
4743 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4759 Unexpected( T_shape );
4777 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4788 Unexpected( T_length );
4797 case T_fields_autoplaced:
4807 text->SetVisible(
true );
4832 Unexpected( T_property );
4857 Expecting(
"at, shape, iref, uuid, effects or locked" );
4863 if( label && label->
GetFields().empty() )
4866 return text.release();
4872 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4873 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4875 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4879 return textBox.release();
4885 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4886 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4888 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4892 return cell.release();
4908 bool foundEnd =
false;
4909 bool foundSize =
false;
4910 bool foundMargins =
false;
4914 aTextBox->
SetText( FromUTF8() );
4916 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4918 if( token != T_LEFT )
4919 Expecting( T_LEFT );
4925 case T_exclude_from_sim:
4956 cell->SetColSpan(
parseInt(
"column span" ) );
4957 cell->SetRowSpan(
parseInt(
"row span" ) );
4961 Expecting(
"at, size, stroke, fill, effects or uuid" );
4985 foundMargins =
true;
5006 Expecting(
"at, size, stroke, fill, effects, span, uuid or locked" );
5008 Expecting(
"at, size, stroke, fill, effects, uuid or locked" );
5016 else if( foundSize )
5017 aTextBox->
SetEnd( pos + size );
5019 Expecting(
"size" );
5034 wxCHECK_MSG( CurTok() == T_table,
nullptr,
5035 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
5041 std::unique_ptr<SCH_TABLE>
table = std::make_unique<SCH_TABLE>( defaultLineWidth );
5043 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5045 if( token != T_LEFT )
5046 Expecting( T_LEFT );
5052 case T_column_count:
5057 case T_column_widths:
5061 while( ( token = NextTok() ) != T_RIGHT )
5071 while( ( token = NextTok() ) != T_RIGHT )
5078 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5080 if( token != T_LEFT )
5081 Expecting( T_LEFT );
5085 if( token != T_table_cell )
5086 Expecting(
"table_cell" );
5094 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5096 if( token != T_LEFT )
5097 Expecting( T_LEFT );
5115 table->SetBorderStroke( borderStroke );
5119 Expecting(
"external, header or stroke" );
5127 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
5129 if( token != T_LEFT )
5130 Expecting( T_LEFT );
5148 table->SetSeparatorsStroke( separatorsStroke );
5152 Expecting(
"rows, cols, or stroke" );
5171 Expecting(
"columns, col_widths, row_heights, border, separators, uuid, locked, header or cells" );
5175 if( !
table->GetCell( 0, 0 ) )
5177 THROW_PARSE_ERROR(
_(
"Invalid table: no cells defined" ), CurSource(), CurLine(), CurLineNumber(),
5181 return table.release();
5187 wxCHECK_RET( CurTok() == T_bus_alias,
5188 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
5189 wxCHECK( aScreen, );
5192 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>();
5203 busAlias->SetName( alias );
5208 if( token != T_members )
5209 Expecting(
"members" );
5213 while( token != T_RIGHT )
5215 if( !IsSymbol( token ) )
5216 Expecting(
"quoted string" );
5218 member = FromUTF8();
5223 busAlias->AddMember( member );
5238 while( ( token = NextTok() ) != T_RIGHT )
5243 KIID uuid( CurStr() );
5251 wxCHECK_RET( CurTok() == T_group,
5252 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
5259 while( ( token = NextTok() ) != T_LEFT )
5261 if( token == T_STRING )
5262 groupInfo.
name = FromUTF8();
5264 Expecting(
"group name or locked" );
5267 for( ; token != T_RIGHT; token = NextTok() )
5269 if( token != T_LEFT )
5270 Expecting( T_LEFT );
5286 if( !IsSymbol( token ) && token != T_NUMBER )
5287 Expecting(
"symbol|number" );
5290 wxString
name = FromUTF8();
5294 name.Replace(
"{slash}",
"/" );
5300 if(
static_cast<int>(
name.size() ) > bad_pos )
5302 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
name,
5308 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
5327 Expecting(
"uuid, lib_id, members, locked" );
5339 [&](
const KIID& aId )
5345 if( item->m_Uuid == aId )
5364 group->SetName( groupInfo.name );
5366 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo.uuid;
5368 if( groupInfo.libId.IsValid() )
5369 group->SetDesignBlockLibId( groupInfo.libId );
5371 group->SetLocked( groupInfo.locked );
5382 for(
const KIID& aUuid : groupInfo.memberUuids )
5384 if(
SCH_ITEM* gItem = getItem( aUuid ) )
5385 group->AddItem( gItem );
5400 T token = NextTok();
5402 if( token == T_EOF )
5404 else if( token == T_LEFT )
5406 else if( token == T_RIGHT )
constexpr EDA_IU_SCALE schIUScale
constexpr double ARC_LOW_DEF_MM
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
void SetContentModified(bool aModified=true)
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
KICAD_T Type() const
Returns the type of object.
EDA_ITEM * GetParent() const
virtual void SetParent(EDA_ITEM *aParent)
FILL_T GetFillMode() const
SHAPE_POLY_SET & GetPolyShape()
void SetFillColor(const COLOR4D &aColor)
int GetPointCount() const
void SetEnd(const VECTOR2I &aEnd)
void SetFillMode(FILL_T aFill)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
void SetTextColor(const COLOR4D &aColor)
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetUnresolvedFontName(const wxString &aFontName)
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetTextPos(const VECTOR2I &aPoint)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
Set only the bold flag, without changing the font.
virtual void SetVisible(bool aVisible)
void SetLineSpacing(double aLineSpacing)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
static bool ValidateHyperlink(const wxString &aURL)
Check if aURL is a valid hyperlink.
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
void SetHyperlink(wxString aLink)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void ParseEmbedded(EMBEDDED_FILES *aFiles)
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
const std::vector< wxString > * GetFontFiles() const
If we just need the cached version of the font files, we can use this function which is const and wil...
void SetAreFontsEmbedded(bool aEmbedFonts)
Simple container to manage fill parameters.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Define a library symbol object.
wxString GetName() const override
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
EMBEDDED_FILES * GetEmbeddedFiles() override
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
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.
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
const PAGE_SIZE_TYPE & GetType() const
A progress reporter interface for use in multi-threaded environments.
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)
virtual const wxString & GetText() const override
Return the string associated with the text object.
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this label.
A set of SCH_ITEMs (i.e., without duplicates).
SCH_ITEM * ParseSymbolDrawItem()
SCH_SHAPE * parseSymbolPolyLine()
SCH_TABLE * parseSchTable()
bool m_appending
Appending load status.
unsigned m_lastProgressLine
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
SCH_SHAPE * parseSchCircle()
SCH_TEXT * parseSchText()
SCH_TABLECELL * parseSchTableCell()
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
void parsePinNumbers(std::unique_ptr< LIB_SYMBOL > &aSymbol)
LIB_SYMBOL * parseLibSymbol(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_RULE_AREA * parseSchRuleArea()
SCH_ITEM * parseSymbolText()
PROGRESS_REPORTER * m_progressReporter
void parseFill(FILL_PARAMS &aFill)
SCH_TEXTBOX * parseSymbolTextBox()
void parseBusAlias(SCH_SCREEN *aScreen)
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
void parseGroupMembers(GROUP_INFO &aGroupInfo)
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()
void resolveGroups(SCH_SCREEN *aParent)
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()
std::vector< GROUP_INFO > m_groupInfos
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
void parseBodyStyles(std::unique_ptr< LIB_SYMBOL > &aSymbol)
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()
std::vector< wxString > m_parseWarnings
Non-fatal warnings collected during parsing.
SCH_JUNCTION * parseJunction()
void ParseSchematic(SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Parse the internal LINE_READER object into aSheet.
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
int m_bodyStyle
The current body style being parsed.
SCH_NO_CONNECT * parseNoConnect()
SCH_SHAPE * parseSymbolArc()
SCH_BUS_WIRE_ENTRY * parseBusEntry()
SCH_SHAPE * parseSchRectangle()
SCH_FIELD * parseProperty(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SYMBOL * parseSchematicSymbol()
void parseSchTextBoxContent(SCH_TEXTBOX *aTextBox)
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
int m_requiredVersion
Set to the symbol library file version required.
int m_maxError
Max deviation allowed when approximating bezier curves.
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 skipToBlockEnd(int aDepth=1)
Skip tokens until we reach the end of the current S-expression block.
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 SetLocked(bool aLocked) override
bool IsLocked() const override
void SetFieldsAutoplaced(AUTOPLACE_ALGO aAlgo)
void SetShape(LABEL_FLAG_SHAPE aShape)
std::vector< SCH_FIELD > & GetFields()
Segment description base class to describe items which have 2 end points (track, wire,...
void SetStartPoint(const VECTOR2I &aPosition)
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
void SetEndPoint(const VECTOR2I &aPosition)
void SetFileFormatVersionAtLoad(int aVersion)
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition.
void SetPageSettings(const PAGE_INFO &aPageSettings)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
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
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
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.
Variant information for a schematic sheet.
void InitializeAttributes(const SCH_SHEET &aSheet)
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
SCH_SCREEN * GetScreen() const
Variant information for a schematic symbol.
void InitializeAttributes(const SCH_SYMBOL &aSymbol)
void SetMarginBottom(int aBottom)
int GetLegacyTextMargin() const
void SetMarginLeft(int aLeft)
void SetMarginRight(int aRight)
void SetExcludedFromSim(bool aExclude, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
void SetMarginTop(int aTop)
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.
std::map< wxString, wxString > m_Fields
bool m_ExcludedFromPosFiles
#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
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ FILLED_WITH_BG_BODYCOLOR
@ FILLED_SHAPE
Fill with object color.
FONTCONFIG * Fontconfig()
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#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.
@ PT_INPUT
usual pin input: must be connected
@ PT_NC
not connected (must be left open)
@ PT_TRISTATE
tri state bus pin
@ PT_NIC
not internally connected (may be connected to anything)
@ PT_BIDI
input or output (like port for a microprocessor)
@ PT_OPENEMITTER
pin type open emitter
@ PT_POWER_OUT
output of a regulator: intended to be connected to power input pins
@ PT_OPENCOLLECTOR
pin type open collector
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin.
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
@ PIN_RIGHT
The pin extends rightwards from the connection point.
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
const SCH_FIELD * FindField(const std::vector< SCH_FIELD > &aFields, FIELD_T aFieldId)
#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.
Class to handle a set of SCH_ITEMs.
double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
void fixupSchFillMode(SCH_SHAPE *aShape)
#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)
A filename or source description, a problem input line, a line number, a byte offset,...
std::vector< KIID > memberUuids
ELECTRICAL_PINTYPE m_Type
A simple container for sheet instance information.
std::map< wxString, SCH_SHEET_VARIANT > m_Variants
A list of sheet variants.
A simple container for schematic symbol instance information.
std::map< wxString, SCH_SYMBOL_VARIANT > m_Variants
A list of symbol variants.
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ USER
The field ID hasn't been set yet; field is invalid.
@ INTERSHEET_REFS
Global label cross-reference page numbers.
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
#define SHEET_MANDATORY_FIELDS
#define GLOBALLABEL_MANDATORY_FIELDS
wxString GetCanonicalFieldName(FIELD_T aFieldType)
KIBIS top(path, &reporter)
std::vector< std::vector< std::string > > table
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
static constexpr double IU_PER_MM
Mock up a conversion function.
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