30#include <wx/translation.h> 
   44        std::vector<wxString> subNodeChildrenToCount = { wxT( 
"LIBRARY" ), wxT( 
"PARTS" ),
 
   58    for( ; cNode; cNode = cNode->
GetNext() )
 
   60        if( cNode->GetName() == wxT( 
"HEADER" ) )
 
   64            switch( 
Header.Resolution )
 
   71                wxASSERT_MSG( 
true, wxT( 
"Unknown File Resolution" ) );
 
   75            if( aLibrary && 
Header.Format.Type != wxT( 
"LIBRARY" ) )
 
   77                THROW_IO_ERROR( wxT( 
"The selected file is not a valid CADSTAR library file." ) );
 
   79            else if( !aLibrary && 
Header.Format.Type != wxT( 
"LAYOUT" ) )
 
   81                if( 
Header.Format.Type == wxT( 
"LIBRARY" ) )
 
   84                            wxT( 
"The selected file is a CADSTAR library file (as opposed " 
   85                                 "to a layout file). You can import this library by adding it " 
   86                                 "to the library table." ) );
 
   90                    THROW_IO_ERROR( wxT( 
"The selected file is an unknown CADSTAR format so " 
   91                                         "cannot be imported into KiCad." ) );
 
   95        else if( cNode->GetName() == wxT( 
"ASSIGNMENTS" ) )
 
   99        else if( cNode->GetName() == wxT( 
"LIBRARY" ) )
 
  103        else if( cNode->GetName() == wxT( 
"DEFAULTS" ) )
 
  109        else if( cNode->GetName() == wxT( 
"PARTS" ) )
 
  113        else if( cNode->GetName() == wxT( 
"LAYOUT" ) )
 
  117        else if( cNode->GetName() == wxT( 
"DISPLAY" ) )
 
 
  138    wxASSERT( aNode->GetName() == wxT( 
"ASSIGNMENTS" ) );
 
  145    for( ; cNode; cNode = cNode->
GetNext() )
 
  147        if( cNode->GetName() == wxT( 
"LAYERDEFS" ) )
 
  149        else if( cNode->GetName() == wxT( 
"CODEDEFS" ) )
 
  151        else if( cNode->GetName() == wxT( 
"TECHNOLOGY" ) )
 
  153        else if( cNode->GetName() == wxT( 
"GRIDS" ) )
 
  154            Grids.Parse( cNode, aContext );
 
  155        else if( cNode->GetName() == wxT( 
"NETCLASSEDITATTRIBSETTINGS" ) )
 
  157        else if( cNode->GetName() == wxT( 
"SPCCLASSEDITATTRIBSETTINGS" ) )
 
 
  167    wxASSERT( aNode->GetName() == wxT( 
"LAYERDEFS" ) );
 
  169    wxXmlAttribute* xmlAttribute = 
nullptr;
 
  176    for( ; cNode; cNode = cNode->
GetNext() )
 
  178        wxString nodeName = cNode->GetName();
 
  180        if( nodeName == wxT( 
"LAYERSTACK" ) )
 
  182            xmlAttribute = cNode->GetAttributes();
 
  184            for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
 
  194        else if( nodeName == wxT( 
"MATERIAL" ) )
 
  197            material.
Parse( cNode, aContext );
 
  198            Materials.insert( std::make_pair( material.
ID, material ) );
 
  200        else if( nodeName == wxT( 
"LAYER" ) )
 
  203            layer.
Parse( cNode, aContext );
 
  204            Layers.insert( std::make_pair( layer.
ID, layer ) );
 
  206        else if( nodeName == wxT( 
"SWAPPAIR" ) )
 
  211            Layers[layerId].SwapLayerID = swapLayerId;
 
 
  223    wxASSERT( aNode->GetName() == wxT( 
"RULESET" ) );
 
  230    for( ; cNode; cNode = cNode->
GetNext() )
 
  232        wxString nodeName = cNode->GetName();
 
  234        if( nodeName == wxT( 
"ROUCODEREF" ) )
 
  238        else if( nodeName == wxT( 
"VIACODEREF" ) )
 
  242        else if( nodeName == wxT( 
"SPACINGCODE" ) )
 
  245            spacingcode.
Parse( cNode, aContext );
 
  246            SpacingCodes.insert( std::make_pair( spacingcode.
ID, spacingcode ) );
 
 
  258    wxASSERT( aNode->GetName() == wxT( 
"CODEDEFS" ) );
 
  262    for( ; cNode; cNode = cNode->
GetNext() )
 
  264        wxString nodeName = cNode->GetName();
 
  269        else if( nodeName == wxT( 
"COPPERCODE" ) )
 
  272            coppercode.
Parse( cNode, aContext );
 
  273            CopperCodes.insert( std::make_pair( coppercode.
ID, coppercode ) );
 
  275        else if( nodeName == wxT( 
"SPACINGCODE" ) )
 
  278            spacingcode.
Parse( cNode, aContext );
 
  279            SpacingCodes.insert( std::make_pair( spacingcode.
ID, spacingcode ) );
 
  281        else if( nodeName == wxT( 
"RULESET" ) )
 
  284            ruleset.
Parse( cNode, aContext );
 
  285            Rulesets.insert( std::make_pair( ruleset.
ID, ruleset ) );
 
  287        else if( nodeName == wxT( 
"PADCODE" ) )
 
  290            padcode.
Parse( cNode, aContext );
 
  291            PadCodes.insert( std::make_pair( padcode.
ID, padcode ) );
 
  293        else if( nodeName == wxT( 
"VIACODE" ) )
 
  296            viacode.
Parse( cNode, aContext );
 
  297            ViaCodes.insert( std::make_pair( viacode.
ID, viacode ) );
 
  299        else if( nodeName == wxT( 
"LAYERPAIR" ) )
 
  302            layerpair.
Parse( cNode, aContext );
 
  303            LayerPairs.insert( std::make_pair( layerpair.
ID, layerpair ) );
 
  305        else if( nodeName == wxT( 
"SPCCLASSSPACE" ) )
 
  308            spcclassspace.
Parse( cNode, aContext );
 
 
  321    wxASSERT( aNode->GetName() == wxT( 
"MATERIAL" ) );
 
  328    if( sType == wxT( 
"CONSTRUCTION" ) )
 
  332    else if( sType == wxT( 
"ELECTRICAL" ) )
 
  336    else if( sType == wxT( 
"NONELEC" ) )
 
  350                                          wxString::Format( wxT( 
"MATERIAL %s" ), 
Name ) );
 
  353    for( ; iNode; iNode = iNode->
GetNext() )
 
  355        wxString nodeName = iNode->GetName();
 
  357        if( nodeName == wxT( 
"RELPERMIT" ) )
 
  361        else if( nodeName == wxT( 
"LOSSTANGENT" ) )
 
  365        else if( nodeName == wxT( 
"RESISTIVITY" ) )
 
 
  379    wxASSERT( aNode->GetName() == wxT( 
"LAYER" ) );
 
  385    auto   processLayerMaterialDetails = [&]() {
 
  387        for( ; tempNode; tempNode = tempNode->
GetNext() )
 
  389            wxString tempNodeName = tempNode->GetName();
 
  391            if( tempNodeName == wxT( 
"MAKE" ) || tempNodeName == wxT( 
"LAYERHEIGHT" ) )
 
  393                if( tempNodeName == wxT( 
"LAYERHEIGHT" ) )
 
  405                if( childOfTempNode )
 
  407                    if( childOfTempNode->GetName() == wxT( 
"EMBEDS" ) )
 
  411                        if( embedsValue == wxT( 
"UPWARDS" ) )
 
  415                        else if( embedsValue == wxT( 
"DOWNWARDS" ) )
 
  422                                                              wxString::Format( wxT( 
"LAYER %s -> EMBEDS" ),
 
  429                                                     wxString::Format( wxT( 
"LAYER %s->MAKE" ),
 
  434            else if( tempNodeName == wxT( 
"BIAS" ) )
 
  438                if( bias == wxT( 
"X_BIASED" ) )
 
  442                else if( bias == wxT( 
"Y_BIASED" ) )
 
  446                else if( bias == wxT( 
"ANTITRACK" ) )
 
  450                else if( bias == wxT( 
"OBSTACLE" ) )
 
  454                else if( bias == wxT( 
"UNBIASED" ) )
 
  461                                                      wxString::Format( wxT( 
"LAYER %s -> BIAS" ),
 
  473    for( ; cNode; cNode = cNode->
GetNext() )
 
  475        wxString cNodeName = cNode->GetName();
 
  477        if( cNodeName == wxT( 
"ALLDOC" ) )
 
  481        else if( cNodeName == wxT( 
"ALLELEC" ) )
 
  485        else if( cNodeName == wxT( 
"ALLLAYER" ) )
 
  489        else if( cNodeName == wxT( 
"ASSCOMPCOPP" ) )
 
  493        else if( cNodeName == wxT( 
"JUMPERLAYER" ) )
 
  497        else if( cNodeName == wxT( 
"NOLAYER" ) )
 
  501        else if( cNodeName == wxT( 
"POWER" ) )
 
  505            processLayerMaterialDetails();
 
  507        else if( cNodeName == wxT( 
"DOC" ) )
 
  511        else if( cNodeName == wxT( 
"CONSTRUCTION" ) )
 
  514            processLayerMaterialDetails();
 
  516        else if( cNodeName == wxT( 
"ELEC" ) )
 
  520            processLayerMaterialDetails();
 
  522        else if( cNodeName == wxT( 
"NONELEC" ) )
 
  526            processLayerMaterialDetails();
 
  528        else if( cNodeName == wxT( 
"DESCRIPTION" ) )
 
  532        else if( cNodeName == wxT( 
"REFPLANE" ) )
 
  536        else if( cNodeName == wxT( 
"VLAYER" ) )
 
  540        else if( cNodeName == wxT( 
"LASUBTYP" ) )
 
  545            if( sSubType == wxT( 
"LAYERSUBTYPE_ASSEMBLY" ) )
 
  549            else if( sSubType == wxT( 
"LAYERSUBTYPE_PASTE" ) )
 
  553            else if( sSubType == wxT( 
"LAYERSUBTYPE_PLACEMENT" ) )
 
  557            else if( sSubType == wxT( 
"LAYERSUBTYPE_SILKSCREEN" ) )
 
  561            else if( sSubType == wxT( 
"LAYERSUBTYPE_SOLDERRESIST" ) )
 
  565            else if( sSubType == wxT( 
"LAYERSUBTYPE_CLEARANCE" ) )
 
  569            else if( sSubType == wxT( 
"LAYERSUBTYPE_ROUT" ) )
 
 
  589    wxASSERT( aNode->GetName() == wxT( 
"COPREASSIGN" ) );
 
 
  599    wxASSERT( aNode->GetName() == wxT( 
"COPPERCODE" ) );
 
  608    for( ; cNode; cNode = cNode->
GetNext() )
 
  610        if( cNode->GetName() == wxT( 
"COPREASSIGN" ) )
 
  613            reassign.
Parse( cNode, aContext );
 
 
  627    wxASSERT( aNode->GetName() == wxT( 
"SPACEREASSIGN" ) );
 
 
  638    wxASSERT( aNode->GetName() == wxT( 
"SPACINGCODE" ) );
 
  645    for( ; cNode; cNode = cNode->
GetNext() )
 
  647        wxString cNodeName = cNode->GetName();
 
  649        if( cNodeName == wxT( 
"SPACEREASSIGN" ) )
 
  652            reassign.
Parse( cNode, aContext );
 
 
  665    wxString aNodeName = aNode->GetName();
 
  667    if( aNodeName == wxT( 
"ANNULUS" ) || aNodeName == wxT( 
"BULLET" ) || aNodeName == wxT( 
"ROUND" )
 
  668            || aNodeName == wxT( 
"DIAMOND" ) || aNodeName == wxT( 
"FINGER" )
 
  669            || aNodeName == wxT( 
"OCTAGON" ) || aNodeName == wxT( 
"RECTANGLE" )
 
  670            || aNodeName == wxT( 
"ROUNDED" ) || aNodeName == wxT( 
"SQUARE" ) )
 
 
  685    wxString aNodeName = aNode->GetName();
 
  687    if( aNodeName == wxT( 
"ANNULUS" ) )
 
  689    else if( aNodeName == wxT( 
"BULLET" ) )
 
  691    else if( aNodeName == wxT( 
"ROUND" ) )
 
  693    else if( aNodeName == wxT( 
"DIAMOND" ) )
 
  695    else if( aNodeName == wxT( 
"FINGER" ) )
 
  697    else if( aNodeName == wxT( 
"OCTAGON" ) )
 
  699    else if( aNodeName == wxT( 
"RECTANGLE" ) )
 
  701    else if( aNodeName == wxT( 
"ROUNDED" ) )
 
  703    else if( aNodeName == wxT( 
"SQUARE" ) )
 
  732            if( aNode->
GetChildren()->GetName() == wxT( 
"ORIENT" ) )
 
 
  754    wxASSERT( aNode->GetName() == wxT( 
"PADREASSIGN" ) );
 
 
  769    wxASSERT( aNode->GetName() == wxT( 
"PADCODE" ) );
 
  775    wxString 
location = wxString::Format( wxT( 
"PADCODE -> %s" ), 
Name );
 
  777    for( ; cNode; cNode = cNode->
GetNext() )
 
  779        wxString cNodeName = cNode->GetName();
 
  783            Shape.Parse( cNode, aContext );
 
  785        else if( cNodeName == wxT( 
"CLEARANCE" ) )
 
  789        else if( cNodeName == wxT( 
"RELIEFWIDTH" ) )
 
  793        else if( cNodeName == wxT( 
"DRILL" ) )
 
  798            for( ; subNode; subNode = subNode->
GetNext() )
 
  800                wxString subNodeName = subNode->GetName();
 
  802                if( subNodeName == wxT( 
"NONPLATED" ) )
 
  804                else if( subNodeName == wxT( 
"OVERSIZE" ) )
 
  810        else if( cNodeName == wxT( 
"DRILLLENGTH" ) )
 
  814        else if( cNodeName == wxT( 
"DRILLORIENTATION" ) )
 
  818        else if( cNodeName == wxT( 
"DRILLXOFFSET" ) )
 
  822        else if( cNodeName == wxT( 
"DRILLYOFFSET" ) )
 
  826        else if( cNodeName == wxT( 
"PADREASSIGN" ) )
 
  829            reassign.
Parse( cNode, aContext );
 
 
  842    wxASSERT( aNode->GetName() == wxT( 
"VIAREASSIGN" ) );
 
 
  857    wxASSERT( aNode->GetName() == wxT( 
"VIACODE" ) );
 
  863    wxString 
location = wxString::Format( wxT( 
"VIACODE -> %s" ), 
Name );
 
  865    for( ; cNode; cNode = cNode->
GetNext() )
 
  867        wxString cNodeName = cNode->GetName();
 
  871            Shape.Parse( cNode, aContext );
 
  873        else if( cNodeName == wxT( 
"CLEARANCE" ) )
 
  877        else if( cNodeName == wxT( 
"RELIEFWIDTH" ) )
 
  881        else if( cNodeName == wxT( 
"DRILL" ) )
 
  886            for( ; subNode; subNode = subNode->
GetNext() )
 
  888                wxString subNodeName = subNode->GetName();
 
  890                if( subNodeName == wxT( 
"OVERSIZE" ) )
 
  896        else if( cNodeName == wxT( 
"VIAREASSIGN" ) )
 
  899            reassign.
Parse( cNode, aContext );
 
 
  912    wxASSERT( aNode->GetName() == wxT( 
"LAYERPAIR" ) );
 
  920    wxString 
location = wxString::Format( wxT( 
"LAYERPAIR -> %s" ), 
Name );
 
  924        if( aNode->
GetChildren()->GetName() == wxT( 
"VIACODEREF" ) )
 
 
  940    wxASSERT( aNode->GetName() == wxT( 
"SPCCLASSSPACE" ) );
 
 
  951    wxASSERT( aNode->GetName() == wxT( 
"TECHNOLOGY" ) );
 
  955    for( ; cNode; cNode = cNode->
GetNext() )
 
  957        wxString cNodeName = cNode->GetName();
 
  962        else if( cNodeName == wxT( 
"MINROUTEWIDTH" ) )
 
  966        else if( cNodeName == wxT( 
"MINNECKED" ) )
 
  970        else if( cNodeName == wxT( 
"MINUNNECKED" ) )
 
  974        else if( cNodeName == wxT( 
"MINMITER" ) )
 
  978        else if( cNodeName == wxT( 
"MAXMITER" ) )
 
  982        else if( cNodeName == wxT( 
"MAXPHYSLAYER" ) )
 
  986        else if( cNodeName == wxT( 
"TRACKGRID" ) )
 
  990        else if( cNodeName == wxT( 
"VIAGRID" ) )
 
  994        else if( cNodeName == wxT( 
"BACKOFFJCTS" ) )
 
  998        else if( cNodeName == wxT( 
"BCKOFFWIDCHANGE" ) )
 
 
 1011        const wxString& aPadSideString )
 
 1013    if( aPadSideString == wxT( 
"THRU" ) )
 
 1015    else if( aPadSideString == wxT( 
"BOTTOM" ) )
 
 1017    else if( aPadSideString == wxT( 
"TOP" ) )
 
 
 1026    wxASSERT( aNode->GetName() == wxT( 
"COMPCOPPER" ) );
 
 1032    bool     shapeIsInitialised = 
false; 
 
 1033    wxString 
location           = wxT( 
"COMPCOPPER" );
 
 1038    for( ; cNode; cNode = cNode->
GetNext() )
 
 1040        wxString cNodeName = cNode->GetName();
 
 1042        if( !shapeIsInitialised && 
Shape.IsShape( cNode ) )
 
 1044            Shape.Parse( cNode, aContext );
 
 1045            shapeIsInitialised = 
true;
 
 1047        else if( cNodeName == wxT( 
"SWAPRULE" ) )
 
 1051        else if( cNodeName == wxT( 
"ASSOCPIN" ) )
 
 1053            wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
 
 1055            for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
 
 1062                if( !xmlAttribute->GetValue().ToLong( &padId ) )
 
 
 1080    wxASSERT( aNode->GetName() == wxT( 
"COMPAREA" ) );
 
 1087    bool     shapeIsInitialised = 
false; 
 
 1088    wxString 
location           = wxString::Format( wxT( 
"COMPAREA %s" ), 
ID );
 
 1093    for( ; cNode; cNode = cNode->
GetNext() )
 
 1095        wxString cNodeName = cNode->GetName();
 
 1097        if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
 
 1099            Shape.Parse( cNode, aContext );
 
 1100            shapeIsInitialised = 
true;
 
 1102        else if( cNodeName == wxT( 
"SWAPRULE" ) )
 
 1106        else if( cNodeName == wxT( 
"USAGE" ) )
 
 1108            wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
 
 1110            for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
 
 1115                if( xmlAttribute->GetValue() == wxT( 
"NO_TRACKS" ) )
 
 1117                else if( xmlAttribute->GetValue() == wxT( 
"NO_VIAS" ) )
 
 
 1135    wxASSERT( aNode->GetName() == wxT( 
"EXITS" ) );
 
 1137    wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
 
 1139    for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
 
 1144        if( xmlAttribute->GetValue() == wxT( 
"FREE" ) )
 
 1146        else if( xmlAttribute->GetValue() == wxT( 
"N" ) )
 
 1148        else if( xmlAttribute->GetValue() == wxT( 
"S" ) )
 
 1150        else if( xmlAttribute->GetValue() == wxT( 
"E" ) )
 
 1152        else if( xmlAttribute->GetValue() == wxT( 
"W" ) )
 
 1154        else if( xmlAttribute->GetValue() == wxT( 
"NE" ) )
 
 1156        else if( xmlAttribute->GetValue() == wxT( 
"NW" ) )
 
 1158        else if( xmlAttribute->GetValue() == wxT( 
"SE" ) )
 
 1160        else if( xmlAttribute->GetValue() == wxT( 
"SW" ) )
 
 
 1172    wxASSERT( aNode->GetName() == wxT( 
"PAD" ) );
 
 1179    wxString 
location = wxString::Format( wxT( 
"PAD %ld" ), 
ID );
 
 1184    for( ; cNode; cNode = cNode->
GetNext() )
 
 1186        wxString cNodeName = cNode->GetName();
 
 1188        if( cNodeName == wxT( 
"ORIENT" ) )
 
 1190        else if( cNodeName == wxT( 
"FIRSTPAD" ) )
 
 1192        else if( cNodeName == wxT( 
"EXITS" ) )
 
 1193            Exits.Parse( cNode, aContext );
 
 1194        else if( cNodeName == wxT( 
"PADIDENTIFIER" ) )
 
 1196        else if( cNodeName == wxT( 
"PCBONLYPAD" ) )
 
 1198        else if( cNodeName == wxT( 
"PT" ) )
 
 
 1208    wxASSERT( aNode->GetName() == wxT( 
"DIMARROW" ) );
 
 1209    bool arrowStyleInitialised = 
false;
 
 1210    bool upperAngleInitialised = 
false;
 
 1211    bool lowerAngleInitialised = 
false;
 
 1218    for( ; cNode; cNode = cNode->
GetNext() )
 
 1220        wxString cNodeName = cNode->GetName();
 
 1222        if( cNodeName == wxT( 
"ARROWSTYLE" ) )
 
 1225            arrowStyleInitialised  = 
true;
 
 1227            if( arrowStyleStr == wxT( 
"DIMENSION_ARROWOPEN" ) )
 
 1229            else if( arrowStyleStr == wxT( 
"DIMENSION_ARROWCLOSED" ) )
 
 1231            else if( arrowStyleStr == wxT( 
"DIMENSION_ARROWCLEAR" ) )
 
 1233            else if( arrowStyleStr == wxT( 
"DIMENSION_ARROWCLOSEDFILLED" ) )
 
 1238        else if( cNodeName == wxT( 
"ARROWANGLEA" ) )
 
 1241            upperAngleInitialised = 
true;
 
 1243        else if( cNodeName == wxT( 
"ARROWANGLEB" ) )
 
 1246            lowerAngleInitialised = 
true;
 
 1254    if( !arrowStyleInitialised )
 
 1257    if( !upperAngleInitialised )
 
 1260    if( !lowerAngleInitialised )
 
 
 1268    wxASSERT( aNode->GetName() == wxT( 
"DIMTEXT" ) );
 
 1275    if( !cNode || cNode->GetName() != wxT( 
"TXTSTYLE" ) )
 
 1280    if( styleStr == wxT( 
"DIMENSION_INTERNAL" ) )
 
 1282    else if( styleStr == wxT( 
"DIMENSION_EXTERNAL" ) )
 
 
 1294    wxASSERT( aNode->GetName() == wxT( 
"EXTLINE" ) );
 
 1303    for( ; cNode; cNode = cNode->
GetNext() )
 
 1305        wxString cNodeName = cNode->GetName();
 
 1307        if( noOfPoints < 2 && cNodeName == wxT( 
"PT" ) )
 
 1311            if( noOfPoints == 1 )
 
 1312                Start.Parse( cNode, aContext );
 
 1314                End.Parse( cNode, aContext );
 
 1316        else if( cNodeName == wxT( 
"SUPPRESSFIRST" ) )
 
 1326    if( noOfPoints != 2 )
 
 
 1333    if( aNode->GetName() == wxT( 
"LEADERLINE" ) || aNode->GetName() == wxT( 
"LINEARLINE" )
 
 1334            || aNode->GetName() == wxT( 
"ANGULARLINE" ) )
 
 
 1347    wxASSERT( 
IsLine( aNode ) );
 
 1349    if( aNode->GetName() == wxT( 
"LINEARLINE" ) )
 
 1350        Type = TYPE::LINEARLINE;
 
 1351    else if( aNode->GetName() == wxT( 
"LEADERLINE" ) )
 
 1352        Type = TYPE::LEADERLINE;
 
 1353    else if( aNode->GetName() == wxT( 
"ANGULARLINE" ) )
 
 1354        Type = TYPE::ANGULARLINE;
 
 1356        wxASSERT_MSG( 
true, wxT( 
"Not a valid type. What happened to the node Name?" ) );
 
 1360    if( 
Type == TYPE::LEADERLINE )
 
 1368    int    requiredNoOfPoints = 2;
 
 1370    if( 
Type == TYPE::ANGULARLINE )
 
 1371        requiredNoOfPoints = 3;
 
 1373    for( ; cNode; cNode = cNode->
GetNext() )
 
 1375        wxString cNodeName = cNode->GetName();
 
 1377        if( cNodeName == wxT( 
"DIMLINETYPE" ) )
 
 1381            if( styleStr == wxT( 
"DIMENSION_INTERNAL" ) )
 
 1383            else if( styleStr == wxT( 
"DIMENSION_EXTERNAL" ) )
 
 1388        else if( noOfPoints < requiredNoOfPoints && cNodeName == wxT( 
"PT" ) )
 
 1392            if( noOfPoints == 1 )
 
 1393                Start.Parse( cNode, aContext );
 
 1394            else if( noOfPoints == 2 )
 
 1395                End.Parse( cNode, aContext );
 
 1397                Centre.Parse( cNode, aContext );
 
 1399        else if( 
Type == TYPE::LEADERLINE && cNodeName == wxT( 
"LEADERANG" ) )
 
 1409    if( noOfPoints != requiredNoOfPoints )
 
 
 1416    if( aNode->GetName() == wxT( 
"LINEARDIM" ) || aNode->GetName() == wxT( 
"LEADERDIM" )
 
 1417            || aNode->GetName() == wxT( 
"ANGLEDIM" ) )
 
 
 1432    std::map<wxString, TYPE> typeMap = { { wxT( 
"LINEARDIM" ), TYPE::LINEARDIM },
 
 1433        { wxT( 
"LEADERDIM" ), TYPE::LEADERDIM }, { wxT( 
"ANGLEDIM" ), TYPE::ANGLEDIM } };
 
 1436    wxASSERT_MSG( typeMap.find( aNode->GetName() ) != typeMap.end(),
 
 1437                  wxT( 
"Not a valid type. What happened to the node Name?" ) );
 
 1439    Type                = typeMap[aNode->GetName()];
 
 1443    std::map<wxString, SUBTYPE> subTypeMap = {
 
 1451    if( subTypeMap.find( subTypeStr ) == subTypeMap.end() )
 
 1454    Subtype   = subTypeMap[subTypeStr];
 
 1459    bool idParsed         = 
false;
 
 1460    bool unitsParsed      = 
false; 
 
 1461    bool arrowParsed      = 
false;
 
 1462    bool textFormatParsed = 
false;
 
 1463    bool extLineParsed    = 
false;
 
 1464    bool lineParsed       = 
false;
 
 1465    bool textParsed       = 
false;
 
 1467    for( ; cNode; cNode = cNode->
GetNext() )
 
 1469        wxString cNodeName = cNode->GetName();
 
 1471        if( !idParsed && cNodeName == wxT( 
"DIMREF" ) )
 
 1476        else if( !unitsParsed && cNodeName == wxT( 
"UNITS" ) )
 
 1481        else if( !unitsParsed && cNodeName == wxT( 
"ANGUNITS" ) )
 
 1486        else if( !arrowParsed && cNodeName == wxT( 
"DIMARROW" ) )
 
 1488            Arrow.Parse( cNode, aContext );
 
 1491        else if( !textFormatParsed && cNodeName == wxT( 
"DIMTEXT" ) )
 
 1494            textFormatParsed = 
true;
 
 1496        else if( !extLineParsed && cNodeName == wxT( 
"EXTLINE" ) )
 
 1499            extLineParsed = 
true;
 
 1503            Line.Parse( cNode, aContext );
 
 1506        else if( !textParsed && cNodeName == wxT( 
"TEXT" ) )
 
 1509            Text.Parse( cNode, aContext, 
false );
 
 1512        else if( cNodeName == wxT( 
"FIX" ) )
 
 1516        else if( cNodeName == wxT( 
"GROUPREF" ) )
 
 1520        else if( cNodeName == wxT( 
"REUSEBLOCKREF" ) )
 
 
 1534    wxASSERT( aNode->GetName() == wxT( 
"SYMDEF" ) );
 
 1542    else if( 
ReferenceName.StartsWith( wxT( 
"STARPOINTNF" ), &rest ) )
 
 1551    for( ; cNode; cNode = cNode->
GetNext() )
 
 1553        wxString cNodeName = cNode->GetName();
 
 1559        else if( cNodeName == wxT( 
"SYMHEIGHT" ) )
 
 1563        else if( cNodeName == wxT( 
"COMPCOPPER" ) )
 
 1566            compcopper.
Parse( cNode, aContext );
 
 1569        else if( cNodeName == wxT( 
"COMPAREA" ) )
 
 1572            area.
Parse( cNode, aContext );
 
 1575        else if( cNodeName == wxT( 
"PAD" ) )
 
 1578            pad.Parse( cNode, aContext );
 
 1581        else if( cNodeName == wxT( 
"DIMENSIONS" ) )
 
 1585            for( ; dimensionNode; dimensionNode = dimensionNode->
GetNext() )
 
 1590                    dim.
Parse( dimensionNode, aContext );
 
 
 1612    wxASSERT( aNode->GetName() == wxT( 
"LIBRARY" ) );
 
 1616    for( ; cNode; cNode = cNode->
GetNext() )
 
 1618        wxString cNodeName = cNode->GetName();
 
 1620        if( cNodeName == wxT( 
"SYMDEF" ) )
 
 1623            symdef.
Parse( cNode, aContext );
 
 1626        else if( cNodeName == wxT( 
"HIERARCHY" ) )
 
 
 1646    wxASSERT( aNode->GetName() == wxT( 
"BOARD" ) );
 
 1652    bool     shapeIsInitialised = 
false; 
 
 1653    wxString 
location           = wxString::Format( wxT( 
"BOARD %s" ), 
ID );
 
 1658    for( ; cNode; cNode = cNode->
GetNext() )
 
 1660        wxString cNodeName = cNode->GetName();
 
 1662        if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
 
 1664            Shape.Parse( cNode, aContext );
 
 1665            shapeIsInitialised = 
true;
 
 1667        else if( cNodeName == wxT( 
"ATTR" ) )
 
 1670            attr.
Parse( cNode, aContext );
 
 1673        else if( cNodeName == wxT( 
"FIX" ) )
 
 1677        else if( cNodeName == wxT( 
"GROUPREF" ) )
 
 1681        else if( cNodeName == wxT( 
"REUSEBLOCKREF" ) )
 
 
 1695    wxASSERT( aNode->GetName() == wxT( 
"AREA" ) );
 
 1703    bool     shapeIsInitialised = 
false; 
 
 1704    wxString 
location           = wxString::Format( wxT( 
"AREA %s" ), 
ID );
 
 1709    for( ; cNode; cNode = cNode->
GetNext() )
 
 1711        wxString cNodeName = cNode->GetName();
 
 1713        if( !shapeIsInitialised && SHAPE::IsShape( cNode ) )
 
 1715            Shape.Parse( cNode, aContext );
 
 1716            shapeIsInitialised = 
true;
 
 1718        else if( cNodeName == wxT( 
"FIX" ) )
 
 1722        else if( cNodeName == wxT( 
"USAGE" ) )
 
 1724            wxXmlAttribute* xmlAttribute = cNode->GetAttributes();
 
 1726            for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
 
 1731                if( xmlAttribute->GetValue() == wxT( 
"PLACEMENT" ) )
 
 1733                else if( xmlAttribute->GetValue() == wxT( 
"ROUTING" ) )
 
 1735                else if( xmlAttribute->GetValue() == wxT( 
"KEEPOUT" ) )
 
 1737                else if( xmlAttribute->GetValue() == wxT( 
"NO_TRACKS" ) )
 
 1739                else if( xmlAttribute->GetValue() == wxT( 
"NO_VIAS" ) )
 
 1747        else if( cNodeName == wxT( 
"AREAHEIGHT" ) )
 
 1751        else if( cNodeName == wxT( 
"GROUPREF" ) )
 
 1755        else if( cNodeName == wxT( 
"REUSEBLOCKREF" ) )
 
 1759        else if( cNodeName == wxT( 
"ATTR" ) )
 
 1762            attr.
Parse( cNode, aContext );
 
 
 1775    wxASSERT( aNode->GetName() == wxT( 
"PINATTR" ) );
 
 1781    for( ; cNode; cNode = cNode->
GetNext() )
 
 1783        wxString cNodeName = cNode->GetName();
 
 1785        if( cNodeName == wxT( 
"ATTR" ) )
 
 1788            attrVal.
Parse( cNode, aContext );
 
 1791        else if( cNodeName == wxT( 
"TESTLAND" ) )
 
 
 1805    wxASSERT( aNode->GetName() == wxT( 
"PADEXCEPTION" ) );
 
 1811    for( ; cNode; cNode = cNode->
GetNext() )
 
 1813        wxString cNodeName = cNode->GetName();
 
 1815        if( cNodeName == wxT( 
"PADCODEREF" ) )
 
 1819        else if( cNodeName == wxT( 
"EXITS" ) )
 
 1822            Exits.Parse( cNode, aContext );
 
 1824        else if( cNodeName == wxT( 
"SIDE" ) )
 
 1829        else if( cNodeName == wxT( 
"ORIENT" ) )
 
 
 1844    wxASSERT( aNode->GetName() == wxT( 
"COMP" ) );
 
 1852    bool   originParsed = 
false;
 
 1854    for( ; cNode; cNode = cNode->
GetNext() )
 
 1856        wxString cNodeName = cNode->GetName();
 
 1858        if( !originParsed && cNodeName == wxT( 
"PT" ) )
 
 1860            Origin.Parse( cNode, aContext );
 
 1861            originParsed = 
true;
 
 1863        else if( cNodeName == wxT( 
"GROUPREF" ) )
 
 1867        else if( cNodeName == wxT( 
"REUSEBLOCKREF" ) )
 
 1871        else if( cNodeName == wxT( 
"TESTPOINT" ) )
 
 1875        else if( cNodeName == wxT( 
"FIX" ) )
 
 1879        else if( cNodeName == wxT( 
"MIRROR" ) )
 
 1883        else if( cNodeName == wxT( 
"READABILITY" ) )
 
 1887        else if( cNodeName == wxT( 
"ORIENT" ) )
 
 1891        else if( cNodeName == wxT( 
"VCOMPMASTER" ) )
 
 1896        else if( cNodeName == wxT( 
"TEXTLOC" ) )
 
 1899            textloc.
Parse( cNode, aContext );
 
 1902        else if( cNodeName == wxT( 
"ATTR" ) )
 
 1905            attrVal.
Parse( cNode, aContext );
 
 1908        else if( cNodeName == wxT( 
"PINATTR" ) )
 
 1911            pinAttr.
Parse( cNode, aContext );
 
 1914        else if( cNodeName == wxT( 
"COMPPINLABEL" ) )
 
 1918            PinLabels.insert( std::make_pair( pinID, pinLabel ) );
 
 1920        else if( cNodeName == wxT( 
"PADEXCEPTION" ) )
 
 1923            padExcept.
Parse( cNode, aContext );
 
 
 1940    wxASSERT( aNode->GetName() == wxT( 
"TESTLAND" ) );
 
 1944    if( side == wxT( 
"MIN_SIDE" ) )
 
 1946    else if( side == wxT( 
"MAX_SIDE" ) )
 
 1948    else if( side == wxT( 
"BOTH_SIDES" ) )
 
 
 1959    wxASSERT( aNode->GetName() == wxT( 
"TRUNK" ) );
 
 
 1968    wxASSERT( aNode->GetName() == wxT( 
"PIN" ) );
 
 
 1983    for( ; cNode; cNode = cNode->
GetNext() )
 
 1987        else if( cNode->GetName() == wxT( 
"TRUNKREF" ) )
 
 
 1997    wxASSERT( aNode->GetName() == wxT( 
"VIA" ) );
 
 2005    for( ; cNode; cNode = cNode->
GetNext() )
 
 2007        wxString cNodeName = cNode->GetName();
 
 2009        if( cNodeName == wxT( 
"PT" ) )
 
 2011        else if( cNodeName == wxT( 
"FIX" ) )
 
 2013        else if( cNodeName == wxT( 
"GROUPREF" ) )
 
 2015        else if( cNodeName == wxT( 
"REUSEBLOCKREF" ) )
 
 2017        else if( cNodeName == wxT( 
"TESTLAND" ) )
 
 2019        else if( cNode->GetName() == wxT( 
"TRUNKREF" ) )
 
 
 2030    wxASSERT( aNode->GetName() == wxT( 
"COPTERM" ) );
 
 
 2041    wxASSERT( aNode->GetName() == wxT( 
"ROUTEWIDTH" ) );
 
 2044    XNODE* prevNode = aNode;
 
 2047    for( ; nextNode; nextNode = nextNode->
GetNext() )
 
 2049        if( nextNode->GetName() == wxT( 
"FIX" ) )
 
 2053        else if( nextNode->GetName() == wxT( 
"TDROPATSTART" ) )
 
 2058        else if( nextNode->GetName() == wxT( 
"TDROPATEND" ) )
 
 2063        else if( VERTEX::IsVertex( nextNode ) )
 
 2065            Vertex.Parse( nextNode, aContext );
 
 2067        else if( nextNode->GetName() == wxT( 
"ROUTEWIDTH" ) )
 
 2076        prevNode = nextNode;
 
 
 2085    wxASSERT( aNode->GetName() == wxT( 
"ROUTE" ) );
 
 2091    bool   startPointParsed = 
false;
 
 2093    for( ; cNode; cNode = cNode->
GetNext() )
 
 2095        wxString cNodeName = cNode->GetName();
 
 2097        if( !startPointParsed && cNodeName == wxT( 
"PT" ) )
 
 2099            startPointParsed = 
true;
 
 2102        else if( cNodeName == wxT( 
"ROUTEWIDTH" ) )
 
 2105            cNode = rtVert.
Parse( cNode, aContext );
 
 2108            assert( cNode != 
nullptr );
 
 
 2125    bool   routeParsed = 
false; 
 
 2127    for( ; cNode; cNode = cNode->
GetNext() )
 
 2129        wxString cNodeName = cNode->GetName();
 
 2135        else if( !
Unrouted && !routeParsed && cNodeName == wxT( 
"ROUTE" ) )
 
 2137            Route.Parse( cNode, aContext );
 
 2140        else if( !routeParsed && cNodeName == wxT( 
"UNROUTE" ) )
 
 2145        else if( cNode->GetName() == wxT( 
"TRUNKREF" ) )
 
 
 2164    for( ; cNode; cNode = cNode->
GetNext() )
 
 2166        wxString cNodeName = cNode->GetName();
 
 2168        if( cNodeName == wxT( 
"JPT" ) )
 
 2171            jpt.
Parse( cNode, aContext );
 
 2172            Junctions.insert( std::make_pair( jpt.
ID, jpt ) );
 
 2178        else if( cNodeName == wxT( 
"PIN" ) )
 
 2181            pin.Parse( cNode, aContext );
 
 2182            Pins.insert( std::make_pair( 
pin.ID, 
pin ) );
 
 2184        else if( cNodeName == wxT( 
"VIA" ) )
 
 2187            via.Parse( cNode, aContext );
 
 2188            Vias.insert( std::make_pair( 
via.ID, 
via ) );
 
 2190        else if( cNodeName == wxT( 
"COPTERM" ) )
 
 2193            cterm.
Parse( cNode, aContext );
 
 2196        else if( cNodeName == wxT( 
"CONN" ) )
 
 2199            conn.
Parse( cNode, aContext );
 
 
 2212    wxASSERT( aNode->GetName() == wxT( 
"POURING" ) );
 
 2224    if( MinIsolCopStr == wxT( 
"NONE" ) )
 
 2231    if( MinDisjCopStr == wxT( 
"NONE" ) )
 
 2238    for( ; cNode; cNode = cNode->
GetNext() )
 
 2240        wxString cNodeName = cNode->GetName();
 
 2242        if( cNodeName == wxT( 
"NOPINRELIEF" ) )
 
 2246        else if( cNodeName == wxT( 
"NOVIARELIEF" ) )
 
 2250        else if( cNodeName == wxT( 
"IGNORETRN" ) )
 
 2254        else if( cNodeName == wxT( 
"BOXPINS" ) )
 
 2258        else if( cNodeName == wxT( 
"REGENERATE" ) )
 
 2262        else if( cNodeName == wxT( 
"AUTOROUTETARGET" ) )
 
 2266        else if( cNodeName == wxT( 
"THERMALCUTOUT" ) )
 
 2270        else if( cNodeName == wxT( 
"FILLED" ) )
 
 2274        else if( cNodeName == wxT( 
"HATCHCODEREF" ) )
 
 
 2289    wxASSERT( aNode->GetName() == wxT( 
"TEMPLATE" ) );
 
 2298    bool   shapeParsed   = 
false;
 
 2299    bool   pouringParsed = 
false;
 
 2301    for( ; cNode; cNode = cNode->
GetNext() )
 
 2303        wxString cNodeName = cNode->GetName();
 
 2305        if( !shapeParsed && SHAPE::IsShape( cNode ) )
 
 2307            Shape.Parse( cNode, aContext );
 
 2310        else if( !pouringParsed && cNodeName == wxT( 
"POURING" ) )
 
 2312            Pouring.Parse( cNode, aContext );
 
 2313            pouringParsed = 
true;
 
 2315        else if( cNodeName == wxT( 
"FIX" ) )
 
 2319        else if( cNodeName == wxT( 
"GROUPREF" ) )
 
 2323        else if( cNodeName == wxT( 
"REUSEBLOCKREF" ) )
 
 2327        else if( cNodeName == wxT( 
"ATTR" ) )
 
 2330            attr.
Parse( cNode, aContext );
 
 
 2344    wxASSERT( aNode->GetName() == wxT( 
"TERM" ) );
 
 2349    bool   locationParsed = 
false;
 
 2351    for( ; cNode; cNode = cNode->
GetNext() )
 
 2353        wxString cNodeName = cNode->GetName();
 
 2355        if( !locationParsed && cNodeName == wxT( 
"PT" ) )
 
 2358            locationParsed = 
true;
 
 2360        else if( cNodeName == wxT( 
"FIX" ) )
 
 
 2374    wxASSERT( aNode->GetName() == wxT( 
"NETREF" ) );
 
 2380    for( ; cNode; cNode = cNode->
GetNext() )
 
 2382        wxString cNodeName = cNode->GetName();
 
 2384        if( cNodeName == wxT( 
"TERM" ) )
 
 2387            term.
Parse( cNode, aContext );
 
 2390        else if( cNodeName == wxT( 
"FIX" ) )
 
 
 2404    wxASSERT( aNode->GetName() == wxT( 
"COPPER" ) );
 
 2411    bool   shapeParsed  = 
false;
 
 2412    bool   netRefParsed = 
false;
 
 2414    for( ; cNode; cNode = cNode->
GetNext() )
 
 2416        wxString cNodeName = cNode->GetName();
 
 2418        if( !shapeParsed && SHAPE::IsShape( cNode ) )
 
 2420            Shape.Parse( cNode, aContext );
 
 2423        else if( !netRefParsed && cNodeName == wxT( 
"NETREF" ) )
 
 2425            NetRef.Parse( cNode, aContext );
 
 2426            netRefParsed = 
true;
 
 2428        else if( cNodeName == wxT( 
"FIX" ) )
 
 2432        else if( cNodeName == wxT( 
"GROUPREF" ) )
 
 2436        else if( cNodeName == wxT( 
"REUSEBLOCKREF" ) )
 
 2440        else if( cNodeName == wxT( 
"POURED" ) )
 
 2444        else if( cNodeName == wxT( 
"ATTR" ) )
 
 2447            attr.
Parse( cNode, aContext );
 
 
 2460    wxASSERT( aNode->GetName() == wxT( 
"DRILLTABLE" ) );
 
 2466    bool   positionParsed = 
false;
 
 2468    for( ; cNode; cNode = cNode->
GetNext() )
 
 2470        wxString cNodeName = cNode->GetName();
 
 2472        if( !positionParsed && cNodeName == wxT( 
"PT" ) )
 
 2475            positionParsed = 
true;
 
 2477        else if( cNodeName == wxT( 
"ORIENT" ) )
 
 2481        else if( cNodeName == wxT( 
"MIRROR" ) )
 
 2485        else if( cNodeName == wxT( 
"FIX" ) )
 
 2489        else if( cNodeName == wxT( 
"READABILITY" ) )
 
 2493        else if( cNodeName == wxT( 
"GROUPREF" ) )
 
 2497        else if( cNodeName == wxT( 
"REUSEBLOCKREF" ) )
 
 
 2511    wxASSERT( aNode->GetName() == wxT( 
"LAYOUT" ) );
 
 2514    bool   netSynchParsed   = 
false;
 
 2515    bool   dimensionsParsed = 
false;
 
 2517    for( ; cNode; cNode = cNode->
GetNext() )
 
 2519        wxString cNodeName = cNode->GetName();
 
 2521        if( !netSynchParsed && cNodeName == wxT( 
"NETSYNCH" ) )
 
 2523            std::map<wxString, NETSYNCH> netSynchMap = { { wxT( 
"WARNING" ), 
NETSYNCH::WARNING },
 
 2528            if( netSynchMap.find( nsString ) == netSynchMap.end() )
 
 2532            netSynchParsed = 
true;
 
 2534        else if( cNodeName == wxT( 
"GROUP" ) )
 
 2537            group.Parse( cNode, aContext );
 
 2540        else if( cNodeName == wxT( 
"REUSEBLOCK" ) )
 
 2543            reuseblock.
Parse( cNode, aContext );
 
 2544            ReuseBlocks.insert( std::make_pair( reuseblock.
ID, reuseblock ) );
 
 2546        else if( cNodeName == wxT( 
"BOARD" ) )
 
 2549            board.
Parse( cNode, aContext );
 
 2550            Boards.insert( std::make_pair( board.
ID, board ) );
 
 2552        else if( cNodeName == wxT( 
"FIGURE" ) )
 
 2555            figure.
Parse( cNode, aContext );
 
 2556            Figures.insert( std::make_pair( figure.
ID, figure ) );
 
 2558        else if( cNodeName == wxT( 
"AREA" ) )
 
 2561            area.
Parse( cNode, aContext );
 
 2562            Areas.insert( std::make_pair( area.
ID, area ) );
 
 2564        else if( cNodeName == wxT( 
"COMP" ) )
 
 2567            comp.
Parse( cNode, aContext );
 
 2570        else if( cNodeName == wxT( 
"TRUNK" ) )
 
 2573            trunk.
Parse( cNode, aContext );
 
 2574            Trunks.insert( std::make_pair( trunk.
ID, trunk ) );
 
 2576        else if( cNodeName == wxT( 
"NET" ) )
 
 2579            net.
Parse( cNode, aContext );
 
 2580            Nets.insert( std::make_pair( net.
ID, net ) );
 
 2582        else if( cNodeName == wxT( 
"TEMPLATE" ) )
 
 2585            temp.
Parse( cNode, aContext );
 
 2586            Templates.insert( std::make_pair( temp.
ID, temp ) );
 
 2588        else if( cNodeName == wxT( 
"COPPER" ) )
 
 2591            copper.
Parse( cNode, aContext );
 
 2592            Coppers.insert( std::make_pair( copper.
ID, copper ) );
 
 2594        else if( cNodeName == wxT( 
"TEXT" ) )
 
 2597            txt.
Parse( cNode, aContext );
 
 2598            Texts.insert( std::make_pair( txt.
ID, txt ) );
 
 2600        else if( cNodeName == wxT( 
"DOCSYMBOL" ) )
 
 2603            docsym.
Parse( cNode, aContext );
 
 2606        else if( !dimensionsParsed && cNodeName == wxT( 
"DIMENSIONS" ) )
 
 2610            for( ; dimensionNode; dimensionNode = dimensionNode->
GetNext() )
 
 2615                    dim.
Parse( dimensionNode, aContext );
 
 2624            dimensionsParsed = 
true;
 
 2626        else if( cNodeName == wxT( 
"DRILLTABLE" ) )
 
 2629            drilltable.
Parse( cNode, aContext );
 
 2630            DrillTables.insert( std::make_pair( drilltable.
ID, drilltable ) );
 
 2632        else if( cNodeName == wxT( 
"VHIERARCHY" ) )
 
 2636        else if( cNodeName == wxT( 
"ERRORMARK" ) )
 
 
constexpr double PCB_IU_PER_MM
Pcbnew IU is 1 nanometer.
 
#define THROW_MISSING_NODE_IO_ERROR(nodename, location)
 
#define THROW_UNKNOWN_NODE_IO_ERROR(nodename, location)
 
#define THROW_UNKNOWN_PARAMETER_IO_ERROR(param, location)
 
#define THROW_MISSING_PARAMETER_IO_ERROR(param, location)
 
#define THROW_PARSING_IO_ERROR(param, location)
 
static UNITS ParseUnits(XNODE *aNode)
 
static SWAP_RULE ParseSwapRule(XNODE *aNode)
 
static const long UNDEFINED_VALUE
 
static void CheckNoNextNodes(XNODE *aNode)
 
static XNODE * LoadArchiveFile(const wxString &aFileName, const wxString &aFileTypeIdentifier, PROGRESS_REPORTER *aProgressReporter=nullptr)
Reads a CADSTAR Archive file (S-parameter format).
 
wxString LAYER_ID
ID of a Sheet (if schematic) or board Layer (if PCB)
 
static ANGUNITS ParseAngunits(XNODE *aNode)
 
long PART_DEFINITION_PIN_ID
Pin identifier in the part definition.
 
static wxString GetXmlAttributeIDString(XNODE *aNode, unsigned int aID, bool aIsRequired=true)
 
void checkPoint()
Updates m_progressReporter or throws if user canceled.
 
static bool IsValidAttribute(wxXmlAttribute *aAttribute)
 
static READABILITY ParseReadability(XNODE *aNode)
 
static void CheckNoChildNodes(XNODE *aNode)
 
static long GetXmlAttributeIDLong(XNODE *aNode, unsigned int aID, bool aIsRequired=true)
 
static void ParseChildEValue(XNODE *aNode, PARSER_CONTEXT *aContext, EVALUE &aValueToParse)
 
static long GetNumberOfStepsForReporting(XNODE *aRootNode, std::vector< wxString > aSubNodeChildrenToCount)
 
PROGRESS_REPORTER * m_progressReporter
 
static TESTLAND_SIDE ParseTestlandSide(XNODE *aNode)
 
@ STARPOINT
From CADSTAR Help: "Starpoints are special symbols/components that can be used to electrically connec...
 
@ JUMPER
From CADSTAR Help: "Jumpers are components used primarily for the purpose of routing.
 
@ COMPONENT
Standard PCB Component definition.
 
@ TESTPOINT
From CADSTAR Help: "A testpoint is an area of copper connected to a net.
 
@ ANTI_ROUTE
Keyword "ANTITRACK".
 
@ OBSTACLE
Keyword "OBSTACLE".
 
@ UNBIASED
Keyword "UNBIASED" (default)
 
long PAD_ID
Pad identifier (pin) in the PCB.
 
@ LAYERSUBTYPE_SOLDERRESIST
 
@ LAYERSUBTYPE_SILKSCREEN
 
void Parse(bool aLibrary=false)
Parses the file.
 
int KiCadUnitMultiplier
Use this value to convert units in this CPA file to KiCad units.
 
@ ALLELEC
Inbuilt layer type (cannot be assigned to user layers)
 
@ ALLDOC
Inbuilt layer type (cannot be assigned to user layers)
 
@ NONELEC
This type has subtypes.
 
@ NOLAYER
Inbuilt layer type (cannot be assigned to user layers)
 
@ JUMPERLAYER
Inbuilt layer type (cannot be assigned to user layers)
 
@ ALLLAYER
Inbuilt layer type (cannot be assigned to user layers)
 
@ ASSCOMPCOPP
Inbuilt layer type (cannot be assigned to user layers)
 
@ ROUNDED_RECT
Keyword "ROUNDED".
 
@ MAX
The highest PHYSICAL_LAYER_ID currently defined (i.e. back / bottom side).
 
@ MIN
The lowest PHYSICAL_LAYER_ID currently defined (i.e. front / top side).
 
static PAD_SIDE GetPadSide(const wxString &aPadSideString)
 
PAD_SIDE
From CADSTAR Help: "This parameter indicates the physical layers on which the selected pad is placed.
 
@ MAXIMUM
The highest PHYSICAL_LAYER_ID currently defined (i.e.
 
@ MINIMUM
PHYSICAL_LAYER_ID 1 (i.e.
 
@ THROUGH_HOLE
All physical layers currently defined.
 
An extension of wxXmlNode that can format its contents as KiCad-style s-expressions.
 
XNODE * GetChildren() const
 
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
 
This file contains miscellaneous commonly used macros and functions.
 
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
 
DOCUMENTATION_SYMBOL_ID ID
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
 
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
 
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
 
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
 
NETELEMENT_ID ID
First character is "J".
 
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
 
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
 
std::function< void()> CheckPointCallback
Callback function to report progress.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
 
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
 
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
 
bool Stub
When the CADSTAR Archive file is exported without the component library, if components on the board a...
 
wxString ReferenceName
This is the name which identifies the symbol in the library Multiple components may exist with the sa...
 
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
 
Corresponds to CADSTAR "origin".
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
From CADSTAR Help: "Area is for creating areas within which, and nowhere else, certain operations are...
 
GROUP_ID GroupID
If not empty, this AREA is part of a group.
 
bool Keepout
From CADSTAR Help: "Auto Placement cannot place components within this area.
 
bool Placement
From CADSTAR Help: "Auto Placement can place components within this area.
 
bool NoVias
From CADSTAR Help: "No vias will be placed within this area by the automatic router.
 
REUSEBLOCKREF ReuseBlockRef
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
long AreaHeight
From CADSTAR Help: "The Height value specified for the PCB component is checked against the Height va...
 
bool Routing
From CADSTAR Help: "Area can be used to place routes during Automatic Routing.
 
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
 
bool NoTracks
From CADSTAR Help: "Area cannot be used to place routes during automatic routing.
 
TECHNOLOGY_SECTION Technology
 
bool SpacingclassEditAttributeSettings
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
bool NetclassEditAttributeSettings
 
GROUP_ID GroupID
Normally CADSTAR_BOARD cannot be part of a reuseblock, but included for completeness.
 
bool Fixed
If not empty, this CADSTAR_BOARD is part of a group.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
REUSEBLOCKREF ReuseBlockRef
 
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
 
long OrientAngle
1/1000 of a Degree
 
static bool IsPadShape(XNODE *aNode)
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::map< COPPERCODE_ID, COPPERCODE > CopperCodes
 
std::map< PADCODE_ID, PADCODE > PadCodes
 
std::map< RULESET_ID, RULESET > Rulesets
Used for area design rules.
 
std::vector< SPCCLASSSPACE > SpacingClasses
 
std::map< VIACODE_ID, VIACODE > ViaCodes
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::map< SPACINGCODE_ID, SPACINGCODE > SpacingCodes
Spacing Design Rules.
 
std::map< LAYERPAIR_ID, LAYERPAIR > LayerPairs
Default vias to use between pairs of layers.
 
From CADSTAR Help: "Area is for creating areas within which, and nowhere else, certain operations are...
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
bool NoVias
From CADSTAR Help: "Check this button to specify that any area created by the Rectangle,...
 
bool NoTracks
From CADSTAR Help: "Check this button to specify that any area created by the Rectangle,...
 
A shape of copper in the component footprint.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::vector< PAD_ID > AssociatedPadIDs
 
COPPERCODE_ID CopperCodeID
 
bool PCBonlyPad
From CADSTAR Help: "The PCB Only Pad property can be used to stop ECO Update, Back Annotation,...
 
PAD_EXITS Exits
See PAD_EXITS.
 
POINT Position
Pad position within the component's coordinate frame.
 
wxString Identifier
This is an identifier that is displayed to the user.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
PAD_SIDE Side
See PAD_SIDE.
 
bool FirstPad
From CADSTAR Help: "Only one pad can have this property; if an existing pad in the design already has...
 
wxString Name
Designator e.g. "C1", "R1", etc.
 
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
 
bool TestPoint
Indicates whether this component should be treated as a testpoint.
 
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
 
std::map< PAD_ID, PADEXCEPTION > PadExceptions
Override pad definitions for this instance.
 
std::map< ATTRIBUTE_ID, TEXT_LOCATION > TextLocations
This contains location of any attributes, including designator position.
 
std::map< PART_DEFINITION_PIN_ID, PIN_ATTRIBUTE > PinAttributes
 
REUSEBLOCKREF ReuseBlockRef
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
GROUP_ID GroupID
If not empty, this component is part of a group.
 
COMPONENT_ID VariantParentComponentID
 
std::map< PART_DEFINITION_PIN_ID, wxString > PinLabels
This is inherited from the PARTS library but is allowed to be out of sync.
 
std::vector< COPREASSIGN > Reassigns
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::map< COPPER_TERM_ID, COPPER_TERM > CopperTerminals
 
GROUP_ID GroupID
If not empty, this COPPER is part of a group.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
REUSEBLOCKREF ReuseBlockRef
 
COPPERCODE_ID CopperCodeID
 
TEMPLATE_ID PouredTemplateID
If not empty, it means this COPPER is part of a poured template.
 
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
@ CLOSED
The arrow head is made up of two angled lines either side of main line plus two other lines perpendic...
 
@ CLEAR
Same as closed but the main line finishes at the start of the perpendicular lines.
 
@ CLOSED_FILLED
The same as CLOSED or CLEAR arrows, but with a solid fill "DIMENSION_ARROWCLOSEDFILLED".
 
@ OPEN
The arrow head is made up of two angled lines either side of main line.
 
long ArrowLength
The length of the angled lines that make up the arrow head.
 
STYLE ArrowStyle
Subnode="ARROWSTYLE".
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
long UpperAngle
token="ARROWANGLEA"
 
long Offset
Offset from the measurement point.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
bool SuppressFirst
If true, excludes the first extension line (only shows extension line at end)
 
long Overshoot
Overshoot of the extension line past the arrow line.
 
@ INTERNAL
The lines are placed inside the measurement token=DIMENSION_INTERNAL.
 
@ EXTERNAL
The lines are placed outside the measurement (typically used when limited space) token=DIMENSION_EXTE...
 
long LeaderLineExtensionLength
Only for TYPE=LEADERLINE Length of the horizontal part of the leader line [param6].
 
LINECODE_ID LineCodeID
param0
 
static bool IsLine(XNODE *aNode)
 
long LeaderLineLength
Only for TYPE=LEADERLINE Length of the angled part of the leader line [param5].
 
long LeaderAngle
Only for TYPE=LEADERLINE subnode "LEADERANG".
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
POINT Centre
Only for TYPE=ANGULARLINE [point3].
 
STYLE Style
Subnode="DIMLINETYPE".
 
long TextGap
Specifies the gap between the text and the end of the line.
 
long TextOffset
Specifies how far above the line the text is (doesn't have an effect on actual position!...
 
@ INSIDE
Embedded with the line (the Gap parameter specifies the gap between the text and the end of the line)...
 
@ OUTSIDE
Above the line (the Offset parameter specifies how far above the line the text is) DIMENSION_EXTERNAL...
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
Linear, leader (radius/diameter) or angular dimension.
 
LAYER_ID LayerID
ID on which to draw this [param1].
 
static bool IsDimension(XNODE *aNode)
 
@ DIAMETER
token=DIMENSION_DIAMETER
 
@ DIRECT
A linear dimension parallel to measurement with perpendicular extension lines token=DIMENSION_DIRECT.
 
@ ANGULAR
token=DIMENSION_ANGULAR
 
@ RADIUS
token=DIMENSION_RADIUS
 
@ ORTHOGONAL
An orthogonal dimension (either x or y measurement) token=DIMENSION_ORTHOGONAL.
 
@ ANGLED
A linear dimension parallel to measurement but with orthogonal extension lines (i....
 
GROUP_ID GroupID
If not empty, this DIMENSION is part of a group.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
EXTENSION_LINE ExtensionLineParams
Not applicable to TYPE=LEADERDIM.
 
DIMENSION_ID ID
Some ID (doesn't seem to be used) subnode="DIMREF".
 
REUSEBLOCKREF ReuseBlockRef
 
long Precision
Number of decimal points to display in the measurement [param3].
 
ANGUNITS AngularUnits
Only Applicable to TYPE=ANGLEDIM.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
GROUP_ID GroupID
If not empty, this DRILL_TABLE is part of a group.
 
REUSEBLOCKREF ReuseBlockRef
 
std::vector< LAYER_ID > LayerStack
 
std::map< MATERIAL_ID, MATERIAL > Materials
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::map< LAYER_ID, LAYER > Layers
 
PHYSICAL_LAYER_ID PhysicalLayerStart
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
PHYSICAL_LAYER_ID PhysicalLayerEnd
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
PHYSICAL_LAYER_ID PhysicalLayer
If UNDEFINED, no physical layer is assigned (e.g.
 
long Thickness
Note: Units of length are defined in file header.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::map< TEMPLATE_ID, TEMPLATE > Templates
 
std::map< BOARD_ID, CADSTAR_BOARD > Boards
Normally CADSTAR only allows one board but.
 
std::map< TEXT_ID, TEXT > Texts
 
std::map< NET_ID, NET_PCB > Nets
Contains tracks and vias.
 
std::map< FIGURE_ID, FIGURE > Figures
 
VARIANT_HIERARCHY VariantHierarchy
 
std::map< COMPONENT_ID, COMPONENT > Components
 
std::map< COPPER_ID, COPPER > Coppers
 
std::map< DOCUMENTATION_SYMBOL_ID, DOCUMENTATION_SYMBOL > DocumentationSymbols
 
std::map< TRUNK_ID, TRUNK > Trunks
 
std::map< DIMENSION_ID, DIMENSION > Dimensions
 
std::map< REUSEBLOCK_ID, REUSEBLOCK > ReuseBlocks
 
std::map< AREA_ID, AREA > Areas
 
std::map< DRILL_TABLE_ID, DRILL_TABLE > DrillTables
 
std::map< GROUP_ID, GROUP > Groups
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::map< SYMDEF_ID, SYMDEF_PCB > ComponentDefinitions
 
EVALUE Resistivity
x10^-8 ohm*metre
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
LAYER_ID UnrouteLayerID
See Unrouted member variable.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
TRUNK_ID TrunkID
TRUNKREF Statements.
 
bool Unrouted
Instead of a ROUTE, the CONNECTION might have an "UNROUTE" token.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
COPPER_TERM_ID CopperTermNum
 
NETELEMENT_ID ID
First two character are "CT".
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
TRUNK_ID TrunkID
TRUNKREF Statements.
 
< "PIN" nodename (represents a PAD in a PCB component)
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
NETELEMENT_ID ID
First character is "P".
 
< Two sibbling nodes: first node being "ROUTEWIDTH" and next node being a VERTEX (e....
 
XNODE * Parse(XNODE *aNode, PARSER_CONTEXT *aContext)
 
long TeardropAtStartAngle
 
VERTEX Vertex
Returns a pointer to the last node.
 
std::vector< ROUTE_VERTEX > RouteVertices
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
TESTLAND_SIDE TestlandSide
 
REUSEBLOCKREF ReuseBlockRef
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
GROUP_ID GroupID
If not empty, this VIA is part of a group.
 
TRUNK_ID TrunkID
TRUNKREF Statements.
 
NETELEMENT_ID ID
First character is "V".
 
std::vector< CONNECTION_PCB > Connections
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::map< NETELEMENT_ID, COPPER_TERMINAL > CopperTerminals
 
std::map< NETELEMENT_ID, VIA > Vias
 
std::map< NETELEMENT_ID, PIN > Pins
 
std::map< NETELEMENT_ID, JUNCTION_PCB > Junctions
 
long ReliefWidth
if undefined inherits from design
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::map< LAYER_ID, CADSTAR_PAD_SHAPE > Reassigns
 
long ReliefClearance
if undefined inherits from design
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
PADCODE_ID PadCode
If not empty, override padcode.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
 
TESTLAND_SIDE TestlandSide
 
PART_DEFINITION_PIN_ID Pin
 
ROUTECODE_ID AreaRouteCodeID
For assigning a net route code to a rule set.
 
VIACODE_ID AreaViaCodeID
For assigning a via code to a rule set.
 
std::map< SPACINGCODE_ID, SPACINGCODE > SpacingCodes
Overrides these spacing rules in the specific area.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::vector< REASSIGN > Reassigns
Can have different spacings on different layers.
 
SPACINGCODE_ID ID
Possible spacing rules:
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
SPACING_CLASS_ID SpacingClassID1
 
LAYER_ID LayerID
Normally LAY0, which corresponds to (All Layers)
 
SPACING_CLASS_ID SpacingClassID2
 
std::map< PAD_ID, COMPONENT_PAD > ComponentPads
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
std::map< DIMENSION_ID, DIMENSION > Dimensions
inside "DIMENSIONS" subnode
 
std::vector< COMPONENT_COPPER > ComponentCoppers
 
long SymHeight
The Height of the component (3D height in z direction)
 
std::map< COMP_AREA_ID, COMPONENT_AREA > ComponentAreas
 
long MinRouteWidth
Manufacturing Design Rule. Corresponds to "Thin Route Width".
 
long TrackGrid
Grid for Routes (equal X and Y steps)
 
long MinNeckedLength
Manufacturing Design Rule.
 
long MaxPhysicalLayer
Should equal number of copper layers.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
long MinUnneckedLength
Manufacturing Design Rule.
 
long MaxMitre
Manufacturing Design Rule. Corresponds to "Maximum Mitre".
 
long ViaGrid
Grid for Vias (equal X and Y steps)
 
long MinMitre
Manufacturing Design Rule. Corresponds to "Minimum Mitre".
 
long AdditionalIsolation
This is the gap to apply in routes and pads in addition to the existing pad-to-copper or route-to-cop...
 
bool TargetForAutorouting
true when subnode "AUTOROUTETARGET" is present
 
bool ThermalReliefOnVias
false when subnode "NOVIARELIEF" is present
 
@ CUTOUTS
This method uses four cutouts in the copper to leave the reliefs required.
 
HATCHCODE_ID HatchCodeID
Only for FillType = HATCHED.
 
bool ThermalReliefOnPads
false when subnode "NOPINRELIEF" is present
 
long ThermalReliefPadsAngle
Orientation for the thermal reliefs.
 
@ HATCHED
This is a user defined HATCHCODE_ID.
 
long MinDisjointCopper
The value is the length of one side of a notional square.
 
bool AutomaticRepour
true when subnode "REGENERATE" is present
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
bool AllowInNoRouting
true when subnode "IGNORETRN" is present
 
bool BoxIsolatedPins
true when subnode "BOXPINS" is present
 
long ClearanceWidth
Specifies the space around pads when pouring (i.e.
 
COPPERCODE_ID ReliefCopperCodeID
From CADSTAR Help: "Relief Copper Code is forselecting the width of line used to draw thethermal reli...
 
COPPER_FILL_TYPE FillType
Assume solid fill.
 
RELIEF_TYPE ReliefType
See RELIEF_TYPE.
 
COPPERCODE_ID CopperCodeID
From CADSTAR Help: "Copper Code is for selecting the width of the line used to draw the outline and f...
 
long ThermalReliefViasAngle
Disabled when !ThermalReliefOnVias (param6)
 
long MinIsolatedCopper
The value is the length of one side of a notional square.
 
long SliverWidth
Minimum width of copper that may be created.
 
Templates are CADSTAR's equivalent to a "filled zone".
 
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
 
POURING Pouring
Copper pour settings (e.g. relief / hatching /etc.)
 
REUSEBLOCKREF ReuseBlockRef
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
GROUP_ID GroupID
If not empty, this TEMPLATE is part of a group.
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
long ReliefClearance
if undefined inherits from design
 
long ReliefWidth
if undefined inherits from design
 
std::map< LAYER_ID, CADSTAR_PAD_SHAPE > Reassigns
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
 
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override