1 /* 2 * This program source code file is part of KiCad, a free EDA CAD application. 3 * 4 * Copyright (C) 2020-2021 Roberto Fernandez Bautista <roberto.fer.bau@gmail.com> 5 * Copyright (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors. 6 * 7 * This program is free software: you can redistribute it and/or modify it 8 * under the terms of the GNU General Public License as published by the 9 * Free Software Foundation, either version 3 of the License, or (at your 10 * option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, but 13 * WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License along 18 * with this program. If not, see <http://www.gnu.org/licenses/>. 19 */ 20 21 /** 22 * @file cadstar_archive_parser.h 23 * @brief Helper functions and common defines between schematic and PCB Archive files 24 */ 25 26 #ifndef CADSTAR_ARCHIVE_PARSER_H_ 27 #define CADSTAR_ARCHIVE_PARSER_H_ 28 29 #include <richio.h> 30 #include <wx/gdicmn.h> 31 #include <functional> 32 #include <map> 33 #include <set> 34 #include <vector> 35 #include <xnode.h> 36 37 // THROW_IO_ERROR definitions to ensure consistent wording is used in the error messages 38 39 #define THROW_MISSING_NODE_IO_ERROR( nodename, location ) \ 40 THROW_IO_ERROR( wxString::Format( _( "Missing node '%s' in '%s'" ), nodename, location ) ) 41 42 #define THROW_UNKNOWN_NODE_IO_ERROR( nodename, location ) \ 43 THROW_IO_ERROR( wxString::Format( _( "Unknown node '%s' in '%s'" ), nodename, location ) ) 44 45 #define THROW_MISSING_PARAMETER_IO_ERROR( param, location ) \ 46 THROW_IO_ERROR( wxString::Format( _( "Missing Parameter '%s' in '%s'" ), param, location ) ) 47 48 #define THROW_UNKNOWN_PARAMETER_IO_ERROR( param, location ) \ 49 THROW_IO_ERROR( wxString::Format( _( "Unknown Parameter '%s' in '%s'" ), param, location ) ) 50 51 #define THROW_PARSING_IO_ERROR( param, location ) \ 52 THROW_IO_ERROR( wxString::Format( _( "Unable to parse '%s' in '%s'" ), param, location ) ) 53 54 //================================= 55 // MACRO DEFINITIONS 56 //================================= 57 #define UNDEFINED_LAYER_ID ( LAYER_ID ) wxEmptyString 58 59 60 /** 61 * Component Name Attribute ID - typically used for placement of designators on silk screen. 62 */ 63 #define COMPONENT_NAME_ATTRID ( ATTRIBUTE_ID ) wxT( "__COMPONENT_NAME__" ) 64 65 /** 66 * Component Name 2 Attribute ID - typically used for indicating the placement of designators in 67 * placement drawings. 68 */ 69 #define COMPONENT_NAME_2_ATTRID ( ATTRIBUTE_ID ) wxT( "__COMPONENT_NAME_2__" ) 70 71 /** 72 * Symbol Name attribute ID - used for placement of designators on the schematic 73 */ 74 #define SYMBOL_NAME_ATTRID ( ATTRIBUTE_ID ) wxT( "__SYMBOL_NAME__" ) 75 #define LINK_ORIGIN_ATTRID ( ATTRIBUTE_ID ) wxT( "__LINK_ORIGIN__" ) 76 #define SIGNALNAME_ORIGIN_ATTRID ( ATTRIBUTE_ID ) wxT( "__SIGNALNAME_ORIGIN__" ) 77 #define PART_NAME_ATTRID ( ATTRIBUTE_ID ) wxT( "__PART_NAME__" ) 78 79 class EDA_TEXT; 80 class wxXmlAttribute; 81 class PROGRESS_REPORTER; 82 83 /** 84 * @brief Helper functions and common structures for CADSTAR PCB and Schematic archive files. 85 */ 86 class CADSTAR_ARCHIVE_PARSER 87 { 88 public: CADSTAR_ARCHIVE_PARSER()89 CADSTAR_ARCHIVE_PARSER() { m_progressReporter = nullptr; } 90 91 92 typedef wxString LINECODE_ID; 93 typedef wxString HATCHCODE_ID; 94 typedef wxString ROUTECODE_ID; 95 typedef wxString NETCLASS_ID; 96 typedef wxString SPACING_CLASS_ID; 97 typedef wxString TEXTCODE_ID; 98 typedef wxString LAYER_ID; ///< ID of a Sheet (if schematic) or board Layer (if PCB) 99 typedef wxString VARIANT_ID; 100 typedef wxString ATTRIBUTE_ID; 101 typedef wxString SYMDEF_ID; 102 typedef wxString PART_ID; 103 typedef wxString GATE_ID; 104 typedef long TERMINAL_ID; ///< Terminal is the pin identifier in the schematic 105 typedef long PART_DEFINITION_PIN_ID; ///< Pin identifier in the part definition 106 typedef long PART_PIN_ID; ///< Pin identifier in the part 107 typedef wxString TEXT_ID; 108 typedef wxString FIGURE_ID; 109 typedef wxString GROUP_ID; 110 typedef wxString REUSEBLOCK_ID; 111 typedef wxString NET_ID; 112 typedef wxString NETELEMENT_ID; 113 typedef wxString DOCUMENTATION_SYMBOL_ID; 114 typedef wxString COLOR_ID; 115 116 static const long UNDEFINED_VALUE = -1; 117 118 /** 119 * CADSTAR fonts are drawn on a 24x24 integer matrix, where the each axis goes from 0 to 24. 120 * The characters can each specify a width of between 12 and 24, but the height is fixed at 24. 121 * 122 * The default CADSTAR font uses y=5 as the starting point for capital letters, leaving space 123 * for the tails of letters such as "g", "p", "y", "q", etc. 124 * 125 * The font height in CADSTAR corresponds to the full 24 point height. In KiCad it only 126 * corresponds to the height above the guide line, meaning the overall text height will be 127 * larger in KiCad. 128 */ 129 static const double TXT_HEIGHT_RATIO; 130 131 /** 132 * These are special fields in text objects enclosed between the tokens '<@' and '@>' such as 133 * <@[FIELD_NAME][FIELD_VALUE]@>. For example: "<@DESIGN TITLEProject Title@>" 134 */ 135 enum class TEXT_FIELD_NAME 136 { 137 DESIGN_TITLE, 138 SHORT_JOBNAME, 139 LONG_JOBNAME, 140 NUM_OF_SHEETS, 141 SHEET_NUMBER, 142 SHEET_NAME, 143 VARIANT_NAME, 144 VARIANT_DESCRIPTION, 145 REG_USER, 146 COMPANY_NAME, 147 CURRENT_USER, 148 DATE, 149 TIME, 150 MACHINE_NAME, 151 FROM_FILE, 152 DISTANCE, 153 UNITS_SHORT, 154 UNITS_ABBREV, 155 UNITS_FULL, 156 HYPERLINK, 157 NONE ///< Synthetic for flagging 158 }; 159 160 /** 161 * Map between CADSTAR fields and KiCad text variables. This is used as a lookup table when 162 * parsing CADSTAR text fields. Most variables have a similar name in KiCad as in CADSTAR. 163 */ 164 static const std::map<TEXT_FIELD_NAME, wxString> CADSTAR_TO_KICAD_FIELDS; 165 166 167 struct PARSER_CONTEXT 168 { 169 /** 170 * CADSTAR doesn't have user defined text fields but does allow loading text from a 171 * file. This map stores all the text items that exist in the original CADSTAR design. They 172 * will be replaced by a text variable of the form ${FROM_FILE_[filename]_[extension]} 173 */ 174 std::map<wxString, wxString> FilenamesToTextMap; 175 176 /** 177 * KiCad doesn't support hyperlinks but we use this map to display warning messages 178 * after import. First element = Display Text. Second element = Hyperlink 179 */ 180 std::map<wxString, wxString> TextToHyperlinksMap; 181 182 /** 183 * Values for the text field elements used in the CADSTAR design extracted from the 184 * text element instances 185 */ 186 std::map<TEXT_FIELD_NAME, wxString> TextFieldToValuesMap; 187 188 /** 189 * Text fields need to be updated in CADSTAR and it is possible that they are not 190 * consistent across text elements. 191 */ 192 std::set<TEXT_FIELD_NAME> InconsistentTextFields; 193 194 /** 195 * Callback function to report progress 196 */ 197 std::function<void()> CheckPointCallback = []() {}; 198 }; 199 200 /** 201 * @brief Replaces CADSTAR fields for the equivalent in KiCad and stores the field values 202 * in aParserContext 203 * @param aTextString Text string to parse 204 * @param aParserContext PARSER_CONTEXT in which to store the values of the found fields 205 * @return 206 */ 207 static wxString ParseTextFields( const wxString& aTextString, PARSER_CONTEXT* aParserContext ); 208 209 210 struct PARSER 211 { 212 virtual void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) = 0; 213 ~PARSERPARSER214 virtual ~PARSER() {}; 215 }; 216 217 218 struct FORMAT : PARSER 219 { 220 wxString Type; 221 long SomeInt; ///< It is unclear what this parameter is used for 222 long Version; ///< Archive version number (e.g. for PCB: 19=> CADSTAR 17.0 archive, 223 ///< 20=> CADSTAR 18.0 archive, 21 => CADSTAR 2018.0 / 2019.0 / 2020.0, 224 ///< etc.) 225 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 226 }; 227 228 229 struct TIMESTAMP : PARSER 230 { 231 long Year; 232 long Month; 233 long Day; 234 long Hour; 235 long Minute; 236 long Second; 237 238 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 239 }; 240 241 //Note: there are possibly several other resolutions, but HUNDREDTH MICRON is only one known 242 enum class RESOLUTION 243 { 244 HUNDREDTH_MICRON 245 }; 246 247 248 struct HEADER : PARSER 249 { 250 FORMAT Format; 251 wxString JobFile; 252 wxString JobTitle; 253 wxString Generator; 254 RESOLUTION Resolution; 255 TIMESTAMP Timestamp; 256 257 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 258 }; 259 260 261 struct VARIANT : PARSER ///< Nodename = "VARIANT" or "VMASTER" (master variant 262 { 263 VARIANT_ID ID = wxEmptyString; 264 VARIANT_ID ParentID = wxEmptyString; ///< if empty, then this one is the master 265 wxString Name = wxEmptyString; 266 wxString Description = wxEmptyString; 267 268 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 269 }; 270 271 272 struct VARIANT_HIERARCHY : PARSER 273 { 274 std::map<VARIANT_ID, VARIANT> Variants; 275 276 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 277 }; 278 279 280 enum class LINESTYLE 281 { 282 SOLID, 283 DASH, 284 DASHDOT, 285 DASHDOTDOT, 286 DOT 287 }; 288 289 290 struct LINECODE : PARSER 291 { 292 LINECODE_ID ID; 293 wxString Name; 294 long Width; 295 LINESTYLE Style; 296 297 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 298 }; 299 300 301 struct HATCH : PARSER 302 { 303 long Step; 304 long LineWidth; 305 long OrientAngle; ///< 1/1000 of a Degree 306 307 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 308 }; 309 310 311 struct HATCHCODE : PARSER 312 { 313 HATCHCODE_ID ID; 314 wxString Name; 315 std::vector<HATCH> Hatches; 316 317 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 318 }; 319 320 321 static const long FONT_NORMAL = 400; 322 static const long FONT_BOLD = 700; 323 324 325 struct FONT : PARSER 326 { 327 wxString Name = wxT( "CADSTAR" ); 328 long Modifier1 = FONT_NORMAL; ///< It seems this is related to weight. 400=Normal, 700=Bold. 329 long Modifier2 = 0; ///< It seems this is always 0 regardless of settings 330 bool KerningPairs = 331 false; ///< From CADSTAR Help: "Kerning Pairs is for causing the system to 332 ///< automatically reduce the spacing between certain pairs of 333 ///< characters in order to improve the appearance of the text" 334 bool Italic = false; 335 336 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 337 }; 338 339 340 struct TEXTCODE : PARSER 341 { 342 TEXTCODE_ID ID; 343 wxString Name; 344 long LineWidth; 345 long Height; 346 long Width; ///< Defaults to 0 if using system fonts or, if using CADSTAR font, default to 347 ///< equal height (1:1 aspect ratio). Allows for system fonts to be rendered in 348 ///< a different aspect ratio. 349 FONT Font; 350 351 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 352 }; 353 354 355 struct ROUTEREASSIGN : PARSER 356 { 357 LAYER_ID LayerID; 358 long OptimalWidth; 359 long MinWidth; 360 long MaxWidth; 361 long NeckedWidth; 362 363 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 364 }; 365 366 367 struct ROUTECODE : PARSER 368 { 369 ROUTECODE_ID ID; 370 wxString Name; 371 long OptimalWidth; 372 long MinWidth; 373 long MaxWidth; 374 long NeckedWidth; 375 376 std::vector<ROUTEREASSIGN> RouteReassigns; 377 378 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 379 }; 380 381 382 /** 383 * @brief Represents a floating value in E notation 384 */ 385 struct EVALUE : PARSER 386 { 387 long Base = 0; 388 long Exponent = 0; 389 390 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 391 double GetDouble(); 392 }; 393 394 /** 395 * @brief Represents a point in x,y coordinates 396 */ 397 struct POINT : wxPoint, PARSER 398 { POINTPOINT399 POINT() : wxPoint( UNDEFINED_VALUE, UNDEFINED_VALUE ) 400 { 401 } 402 403 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 404 }; 405 406 407 struct LONGPOINT : PARSER 408 { 409 long x = UNDEFINED_VALUE; 410 long y = UNDEFINED_VALUE; 411 412 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 413 }; 414 415 416 enum class VERTEX_TYPE 417 { 418 POINT, 419 CLOCKWISE_ARC, 420 CLOCKWISE_SEMICIRCLE, 421 ANTICLOCKWISE_ARC, 422 ANTICLOCKWISE_SEMICIRCLE 423 }; 424 425 /** 426 * @brief Represents a vertex in a shape. E.g. A circle is made by two semicircles with the same 427 * center point. 428 */ 429 struct VERTEX : PARSER 430 { 431 VERTEX_TYPE Type; 432 POINT Center; 433 POINT End; 434 435 static bool IsVertex( XNODE* aNode ); 436 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 437 }; 438 439 /** 440 * @brief Represents a cutout in a closed shape (e.g. OUTLINE) 441 */ 442 struct CUTOUT : PARSER 443 { 444 std::vector<VERTEX> Vertices; 445 446 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 447 }; 448 449 450 enum class SHAPE_TYPE 451 { 452 OPENSHAPE, ///< Unfilled open shape. Cannot have cutouts. 453 OUTLINE, ///< Unfilled closed shape. 454 SOLID, ///< Filled closed shape (solid fill). 455 HATCHED ///< Filled closed shape (hatch fill). 456 }; 457 458 459 struct SHAPE : PARSER 460 { 461 SHAPE_TYPE Type; 462 std::vector<VERTEX> Vertices; 463 std::vector<CUTOUT> Cutouts; ///< Not Applicable to OPENSHAPE Type 464 wxString HatchCodeID; ///< Only Applicable for HATCHED Type 465 466 static bool IsShape( XNODE* aNode ); 467 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 468 }; 469 470 471 enum class UNITS 472 { 473 DESIGN, ///< Inherits from design units (assumed Assignments->Technology->Units) 474 THOU, 475 INCH, 476 MICROMETRE, 477 MM, 478 CENTIMETER, 479 METER 480 }; 481 482 483 static UNITS ParseUnits( XNODE* aNode ); 484 485 486 enum class ANGUNITS 487 { 488 DEGREES, 489 RADIANS 490 }; 491 492 493 static ANGUNITS ParseAngunits( XNODE* aNode ); 494 495 496 enum class GRID_TYPE 497 { 498 FRACTIONALGRID, ///< Param1 = Units, Param2 = Divisor. The grid is equal in X and Y 499 ///< dimensions with a step size equal to Param1/Param2 500 STEPGRID ///< Param1 = X Step, Param2 = Y Step. A standard x,y grid. 501 }; 502 503 504 struct GRID : PARSER 505 { 506 GRID_TYPE Type; 507 wxString Name; 508 long Param1; ///< Either Units or X step, depending on Type (see GRID_TYPE for 509 ///< more details) 510 long Param2; ///< Either Divisor or Y step, depending on Type (see GRID_TYPE for 511 ///< more details) 512 513 static bool IsGrid( XNODE* aNode ); 514 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 515 }; 516 517 518 struct GRIDS : PARSER 519 { 520 GRID WorkingGrid; 521 GRID ScreenGrid; ///< From CADSTAR Help: "There is one Screen Grid, which is 522 ///< visible as dots on the screen. You cannot specify your 523 ///< own name for the Screen Grid. The visibility and colour 524 ///< of the dots representing the Screen Grid is set up by 525 ///< the Highlight category on the Colours dialog. 526 ///< 527 ///< The type of Screen grid displayed(Lined or Points) is 528 ///< set up on the Display dialog within Options(File menu)." 529 std::vector<GRID> UserGrids; ///< List of predefined grids created by the user 530 531 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 532 }; 533 534 535 struct SETTINGS : PARSER 536 { 537 UNITS Units; ///< Units to display for linear dimensions 538 long UnitDisplPrecision; ///< Number of decimal points to display for linear dimensions 539 long InterlineGap; ///< For CADSTAR font only, distance between lines of text, 540 ///< expressed as a percentage of the text height (accepted 541 ///< values are 0-100) 542 long BarlineGap; ///< For CADSTAR font only, distance between top bar and 543 ///< character, expressed as a percentage of the text height 544 ///< (accepted values are 0-100) 545 bool AllowBarredText = false; ///< Specifies if barring is allowed in the design 546 long AngularPrecision; ///< Number of decimal points to display for angular dimensions 547 548 LONGPOINT DesignOrigin; 549 std::pair<POINT, POINT> DesignArea; 550 LONGPOINT DesignRef; ///< Appears to be 0,0 always 551 LONGPOINT DesignLimit; 552 553 bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext ); 554 virtual void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 555 }; 556 557 558 559 /** 560 * @brief From CADSTAR Help: "Text Alignment enables you to define the position of an alignment 561 * origin for all text items in CADSTAR. The alignment origin is a point on or within the text 562 * boundary and defines how the text is displayed. 563 * 564 * For example, with an alignment of bottom-right the origin will be positioned at the bottom 565 * right of the text boundary. This makes it easier to right-align several text items 566 * regardless of the length of text displayed. 567 * 568 * Text Alignment applies to all CADSTAR text. [...] 569 * 570 * Note: Unaligned text operates in the way CADSTAR text always has. In most cases this behaves 571 * as Bottom Left alignment, but there are a few exceptions, e.g. pin names. Also unaligned 572 * multiline text has an origin Bottom Left of the first line." 573 * 574 * See also JUSTIFICATION 575 */ 576 enum class ALIGNMENT 577 { 578 NO_ALIGNMENT, ///< NO_ALIGNMENT has different meaning depending on the object type 579 TOPLEFT, 580 TOPCENTER, 581 TOPRIGHT, 582 CENTERLEFT, 583 CENTERCENTER, 584 CENTERRIGHT, 585 BOTTOMLEFT, 586 BOTTOMCENTER, 587 BOTTOMRIGHT 588 }; 589 590 591 static ALIGNMENT ParseAlignment( XNODE* aNode ); 592 593 /** 594 * @brief From CADSTAR Help: "Multi Line Text can also be justified as Left, Centre or Right. 595 * This does not affect the text alignment. Note: Justification of single line text has no 596 * effect." 597 * 598 * This only affects multiline text 599 * 600 * See also ALIGNMENT 601 */ 602 enum class JUSTIFICATION 603 { 604 LEFT, 605 CENTER, 606 RIGHT 607 }; 608 609 610 static JUSTIFICATION ParseJustification( XNODE* aNode ); 611 612 /** 613 * @brief Sets the readability direction of text. From CADSTAR Help: "Horizontal text will 614 * always be displayed from left to right (i.e. never upside down). Vertical text can be set as 615 * readable from either the left or right edge of the design." 616 * 617 * I.e. Vertical text can either be rotated 90 degrees clockwise or 90 degrees anticlockwise from 618 * horizontal. This does not impact vertical text 619 */ 620 enum class READABILITY 621 { 622 BOTTOM_TO_TOP, ///< When text is vertical, show it rotated 90 degrees anticlockwise 623 TOP_TO_BOTTOM ///< When text is vertical, show it rotated 90 degrees clockwise 624 }; 625 626 627 static READABILITY ParseReadability( XNODE* aNode ); 628 629 630 enum class ATTROWNER 631 { 632 ALL_ITEMS, 633 AREA, 634 BOARD, 635 COMPONENT, 636 CONNECTION, 637 COPPER, 638 DOCSYMBOL, 639 FIGURE, 640 NET, 641 NETCLASS, 642 PART, ///< Only library Attributes 643 PART_DEFINITION, ///< Only library Attributes 644 PIN, 645 SIGNALREF, 646 SYMBOL, 647 SYMDEF, 648 TEMPLATE, 649 TESTPOINT 650 }; 651 652 653 enum class ATTRUSAGE 654 { 655 BOTH, ///< From CADSTAR Help: Assigned to both Schematic symbols and PCB components, 656 ///< and displayed on Schematic and PCB designs. 657 COMPONENT, ///< From CADSTAR Help: Assigned to PCB components and displayed on PCB designs 658 PART_DEFINITION, ///< From CADSTAR Help: Assigned to Parts library Definitions and displayed 659 ///< by the Library searcher 660 PART_LIBRARY, ///< From CADSTAR Help: Only used by non-Cadstar applications 661 SYMBOL, ///< From CADSTAR Help: Assigned to Schematic Symbols and displayed on 662 ///< Schematic Designs 663 UNDEFINED ///< Note: It seems that some attribute have no "ATTRUSAGE" defined. It appears 664 ///< that the attributes that fall under this category are the ones associated 665 ///< with the design itself (i.e. not inherited from the library) 666 }; 667 668 669 struct ATTRIBUTE_LOCATION : PARSER 670 { 671 TEXTCODE_ID TextCodeID; 672 LAYER_ID LayerID; 673 POINT Position; 674 long OrientAngle = 0; 675 bool Mirror = false; 676 bool Fixed = false; 677 JUSTIFICATION Justification = 678 JUSTIFICATION::LEFT; ///< Note: Justification has no effect on single lines of text 679 ALIGNMENT Alignment = ALIGNMENT:: 680 NO_ALIGNMENT; ///< In CADSTAR The default alignment for a TEXT object (when 681 ///< "(No Alignment()" is selected) Bottom Left of the *first line*. 682 ///< Note that this is different from BOTTOM_LEFT (which is bottom 683 ///< left of the whole text block) 684 685 void ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext ); 686 bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext ); 687 virtual void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 688 }; 689 690 691 /** 692 * @brief NOTE from CADSTAR help: To convert a Part Definition Attribute into a hyperlink, prefix 693 * the attribute name with "Link " 694 */ 695 struct ATTRNAME : PARSER 696 { 697 struct COLUMNORDER : PARSER 698 { 699 long ID; 700 long Order; 701 702 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 703 }; 704 705 706 struct COLUMNWIDTH : PARSER 707 { 708 long ID; 709 long Width; 710 711 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 712 }; 713 714 ATTRIBUTE_ID ID; 715 wxString Name; ///< Parenthesis aren't permitted in user attributes in CADSTAR. Any 716 ///< Attributes in Parenthesis indicate an internal CADSTAR attribute 717 ///< Examples: "(PartDescription)" "(PartDefinitionNameStem)",etc. 718 ///TODO: create a list of all CADSTAR internal attribute names. 719 ATTROWNER AttributeOwner = ATTROWNER::ALL_ITEMS; 720 ATTRUSAGE AttributeUsage = ATTRUSAGE::UNDEFINED; 721 bool NoTransfer = false; ///< True="All Design Types", False="Current Design Type" 722 ///< "All Design Types" Description from CADSTAR Help: 723 ///< "The selected attribute name will be available when 724 ///< any design is displayed" 725 ///< "Current Design Type" From CADSTAR Help: This 726 ///< restricts the availability of the selected attribute 727 ///< name to the current design. 728 std::vector<COLUMNORDER> ColumnOrders; 729 std::vector<COLUMNWIDTH> ColumnWidths; 730 bool ColumnInvisible = false; 731 732 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 733 }; 734 735 736 struct ATTRIBUTE_VALUE : PARSER 737 { 738 ATTRIBUTE_ID AttributeID; 739 wxString Value; 740 bool ReadOnly = false; 741 bool HasLocation = false; ///< Flag to know if this ATTRIBUTE_VALUE has a location 742 ///< i.e. is displayed 743 ATTRIBUTE_LOCATION AttributeLocation; 744 745 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 746 }; 747 748 749 /** 750 * @brief Corresponds to CADSTAR "origin". This is used for setting a location of an attribute 751 * e.g. Designator (called Component Name in CADSTAR), Part Name (name of component in the 752 * library), etc. The atom identifier is "TEXTLOC" 753 */ 754 struct TEXT_LOCATION : ATTRIBUTE_LOCATION 755 { TEXT_LOCATIONTEXT_LOCATION756 TEXT_LOCATION() 757 { 758 // The default alignment for TEXT_LOCATION (when "NO_ALIGNMENT" is selected) is 759 // Bottom left, matching CADSTAR's default behaviour 760 Alignment = ALIGNMENT::BOTTOMLEFT; 761 } 762 ATTRIBUTE_ID AttributeID; 763 764 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 765 }; 766 767 768 struct CADSTAR_NETCLASS : PARSER 769 { 770 NETCLASS_ID ID; 771 wxString Name; 772 std::vector<ATTRIBUTE_VALUE> Attributes; 773 774 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 775 }; 776 777 778 struct SPCCLASSNAME : PARSER 779 { 780 SPACING_CLASS_ID ID; 781 wxString Name; 782 783 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 784 }; 785 786 787 struct CODEDEFS : PARSER 788 { 789 std::map<LINECODE_ID, LINECODE> LineCodes; 790 std::map<HATCHCODE_ID, HATCHCODE> HatchCodes; 791 std::map<TEXTCODE_ID, TEXTCODE> TextCodes; 792 std::map<ROUTECODE_ID, ROUTECODE> RouteCodes; 793 std::map<ATTRIBUTE_ID, ATTRNAME> AttributeNames; 794 std::map<NETCLASS_ID, CADSTAR_NETCLASS> NetClasses; 795 std::map<SPACING_CLASS_ID, SPCCLASSNAME> SpacingClassNames; 796 797 bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext ); 798 }; 799 800 /** 801 * @brief Corresponds to "Display when" Item property. From CADSTAR 802 * Help: "This parameter enables you to make the visibility of 803 * a component outline/area (or an area of component copper, or 804 * a string of component text) dependent on the current mirror 805 * status of the component. 806 * 807 * For example, you may require a string of component text to 808 * be displayed only when the component is mirrored." 809 */ 810 enum class SWAP_RULE 811 { 812 NO_SWAP, ///< Display when Unmirrored 813 USE_SWAP_LAYER, ///< Display when Mirrored 814 BOTH ///< Always display (Mirrored and Unmirrored) 815 }; 816 817 818 static SWAP_RULE ParseSwapRule( XNODE* aNode ); 819 820 821 struct REUSEBLOCK : PARSER 822 { 823 REUSEBLOCK_ID ID; 824 wxString Name; 825 wxString FileName; ///< Filename of the reuse block (usually a .pcb). Used for reloading 826 bool Mirror = false; 827 long OrientAngle = 0; 828 829 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 830 }; 831 832 833 /** 834 * @brief References an element from a design reuse block 835 */ 836 struct REUSEBLOCKREF : PARSER 837 { 838 REUSEBLOCK_ID ReuseBlockID = wxEmptyString; 839 wxString ItemReference = wxEmptyString; ///< For Components, this references the designator 840 ///< in the reuse file. 841 ///< For net elements (such as vias, routes, etc.), 842 ///< coppers and templates, this parameter is blank. 843 844 bool IsEmpty(); ///< Determines if this is empty (i.e. no design reuse associated) 845 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 846 }; 847 848 849 struct GROUP : PARSER 850 { 851 GROUP_ID ID; 852 wxString Name; 853 bool Fixed = false; 854 bool Transfer = false; ///< If true, the group is transferred to PCB 855 GROUP_ID GroupID = wxEmptyString; ///< If not empty, this GROUP 856 ///< is part of another GROUP 857 REUSEBLOCKREF ReuseBlockRef; 858 859 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 860 }; 861 862 863 struct FIGURE : PARSER 864 { 865 FIGURE_ID ID; 866 LINECODE_ID LineCodeID; 867 LAYER_ID LayerID; 868 SHAPE Shape; //< Uses the component's coordinate frame if within a component 869 //< definition, otherwise uses the design's coordinate frame. 870 GROUP_ID GroupID = wxEmptyString; ///< If not empty, this FIGURE is part of a group 871 REUSEBLOCKREF ReuseBlockRef; 872 SWAP_RULE SwapRule = SWAP_RULE::BOTH; ///< Only applicable to Figures in Components 873 bool Fixed = false; 874 std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues; 875 876 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 877 }; 878 879 880 struct TEXT : PARSER 881 { 882 TEXT_ID ID; 883 wxString Text; //TODO: Need to lex/parse to identify design fields and hyperlinks 884 TEXTCODE_ID TextCodeID; 885 LAYER_ID LayerID; 886 POINT Position; 887 long OrientAngle = 0; 888 bool Mirror = false; 889 bool Fixed = false; 890 SWAP_RULE SwapRule = SWAP_RULE::BOTH; 891 JUSTIFICATION Justification = 892 JUSTIFICATION::LEFT; ///< Note: Justification has no effect on single lines of text 893 ALIGNMENT Alignment = ALIGNMENT:: 894 NO_ALIGNMENT; ///< In CADSTAR The default alignment for a TEXT object (when 895 ///< "(No Alignment()" is selected) Bottom Left of the *first line*. 896 ///< Note that this is different from BOTTOM_LEFT (which is bottom 897 ///< left of the whole text block) 898 GROUP_ID GroupID = wxEmptyString; ///< If not empty, this FIGURE is part of a group 899 REUSEBLOCKREF ReuseBlockRef; 900 901 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 902 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext, bool aParseFields ); 903 }; 904 905 906 struct SYMDEF : PARSER 907 { 908 SYMDEF_ID ID; 909 wxString ReferenceName; ///< This is the name which identifies the symbol in the library 910 ///< Multiple components may exist with the same ReferenceName. 911 wxString Alternate; ///< This is in addition to ReferenceName. It allows defining 912 ///< different versions, views etc. of the same basic symbol. 913 POINT Origin; ///< Origin of the component (this is used as the reference point 914 ///< when placing the component in the design) 915 bool Stub = false; ///< When the CADSTAR Archive file is exported without the 916 ///< component library, if components on the board are still 917 ///< exported, the Reference and Alternate names will still be 918 ///< exported but the content is replaced with a "STUB" atom, 919 ///< requiring access to the original library for component 920 ///< definition. 921 long Version = UNDEFINED_VALUE; ///< Version is a sequential integer number to identify 922 ///< discrepancies between the library and the design. 923 924 std::map<FIGURE_ID, FIGURE> Figures; 925 std::map<TEXT_ID, TEXT> Texts; 926 std::map<ATTRIBUTE_ID, TEXT_LOCATION> TextLocations; ///< This contains location of 927 ///< any attributes, including 928 ///< designator position 929 std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues; ///< These attributes might also 930 ///< have a location 931 932 void ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext ); 933 bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext ); 934 }; 935 936 937 struct PART : PARSER 938 { 939 enum class PIN_TYPE 940 { 941 UNCOMMITTED, ///< Uncommitted pin (default) 942 INPUT, ///< Input pin 943 OUTPUT_OR, ///< Output pin OR tieable 944 OUTPUT_NOT_OR, ///< Output pin not OR tieable 945 OUTPUT_NOT_NORM_OR, ///< Output pin not normally OR tieable 946 POWER, ///< Power pin 947 GROUND, ///< Ground pin 948 TRISTATE_BIDIR, ///< Tristate bi-directional driver pin 949 TRISTATE_INPUT, ///< Tristate input pin 950 TRISTATE_DRIVER ///< Tristate output pin 951 }; 952 953 954 static PIN_TYPE GetPinType( XNODE* aNode ); 955 956 957 struct DEFINITION : PARSER ///< "PARTDEFINITION" node name 958 { 959 struct GATE : PARSER ///< "GATEDEFINITION" node name 960 { 961 GATE_ID ID; ///< Usually "A", "B", "C", etc. 962 wxString Name; ///< Symbol name in the symbol library 963 wxString Alternate; ///< Symbol alternate name in the symbol library 964 long PinCount; ///< Number of pins (terminals) in the symbol 965 966 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 967 }; 968 969 970 struct PIN : PARSER ///< "PARTDEFINITIONPIN" node name 971 { 972 /** 973 * @brief Positioning of pin names can be in one of four quadrants 974 */ 975 enum class POSITION 976 { 977 TOP_RIGHT = 0, ///< Default 978 TOP_LEFT = 1, 979 BOTTOM_LEFT = 2, 980 BOTTOM_RIGHT = 3 981 }; 982 983 PART_DEFINITION_PIN_ID ID = UNDEFINED_VALUE; 984 985 wxString Identifier = wxEmptyString; ///< This should match a pad identifier 986 ///< in the component footprint 987 ///< subnode="PINIDENTIFIER". It is assumed 988 ///< that this could be empty in earlier 989 ///< versions of CADSTAR 990 wxString Name = wxEmptyString; ///< Can be empty. If empty the pin name 991 ///< displayed wil be Identifier 992 ///< (subnode="PINNAME") 993 ///< This seems to be equivalent to "Pin 994 ///< Number" in KiCad. 995 wxString Label = wxEmptyString; ///< This Can be empty (subnode= 996 ///< "PINLABEL") 997 ///< From CADSTAR Help: "Pin 998 ///< Labels are an optional replacement 999 ///< for the free text sometimes placed 1000 ///< in schematic symbols. Using Pin 1001 ///< Labels instead has the advantage of 1002 ///< associating each piece of label 1003 ///< text with a particular pin. This 1004 ///< means that the text remains 1005 ///< correctly placed after any Gate and 1006 ///< Pin Swaps are Back Annotated to the 1007 ///< Schematic design." 1008 ///< This seems to be equivalent to "Pin 1009 ///< Name" in KiCad. 1010 wxString Signal = wxEmptyString; ///< Usually for Power/Ground pins, 1011 ///< (subnode="PINSIGNAL") 1012 GATE_ID TerminalGate; ///< (subnode="PINTERM", param0) 1013 TERMINAL_ID TerminalPin; ///< (subnode="PINTERM", param1) 1014 PIN_TYPE Type = PIN_TYPE::UNCOMMITTED; ///< subnode="PINTYPE" 1015 long Load = UNDEFINED_VALUE; ///< The electrical current expected on 1016 ///< the pin (It is unclear what the units 1017 ///< are, but only accepted values are 1018 ///< integers) subnode ="PINLOAD" 1019 POSITION Position = 1020 POSITION::TOP_RIGHT; ///< The pin names will use these positions when 1021 ///< the symbol is added to a schematic design 1022 ///< subnode="PINPOSITION" 1023 1024 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1025 }; 1026 1027 1028 struct PIN_EQUIVALENCE : PARSER ///< "PINEQUIVALENCE" Node name 1029 { 1030 std::vector<PART_DEFINITION_PIN_ID> PinIDs; ///< All the pins in this vector are 1031 ///< equivalent and can be swapped with 1032 ///< each other 1033 1034 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1035 }; 1036 1037 1038 struct SWAP_GATE : PARSER ///< "SWAPGATE" Node name (represents an "Element") 1039 { 1040 std::vector<PART_DEFINITION_PIN_ID> PinIDs; ///< The pins in this vector 1041 ///< describe a "gate" 1042 1043 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1044 }; 1045 1046 1047 struct SWAP_GROUP : PARSER 1048 { 1049 wxString GateName = 1050 wxEmptyString; ///< Optional. If not empty, should match the Name 1051 ///< attribute of one of the gates defined in the 1052 ///< part definition 1053 1054 bool External = false; ///< Determines if this swap group is external (and internal) 1055 ///< or internal only. External Gate swapping allows Gates on 1056 ///< different components with the same Part Definition to 1057 ///< swap with one another. 1058 ///< 1059 ///< The external swapping groups must be at the root level 1060 ///< (i.e. they cannot be contained by other swapping groups) 1061 1062 std::vector<SWAP_GATE> SwapGates; ///< Each of the elements in this vector can be 1063 ///< swapped with each other - i.e. *all* of the 1064 ///< pins in each swap gate can be swapped with 1065 ///< *all* in another swap gate defined in this 1066 ///< vector 1067 1068 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1069 }; 1070 1071 wxString Name; ///< This name can be different to the PART name 1072 bool HidePinNames = 1073 false; ///< Specifies whether to display the pin names/identifier in 1074 ///< the schematic symbol or not. E.g. it is useful to display 1075 ///< pin name information for integrated circuits but less so 1076 ///< for resistors and capacitors. (subnode HIDEPINNAMES) 1077 1078 long MaxPinCount = 1079 UNDEFINED_VALUE; ///< Optional parameter which is used for specifying the number 1080 ///< of electrical pins on the PCB component symbol to be 1081 ///< used in the part definition (this should not include 1082 ///< mechanical pins for fixing etc.). This value must be less 1083 ///< than or equal to than the number of pins on the PCB 1084 ///< Component symbol. 1085 1086 std::map<GATE_ID, GATE> GateSymbols; 1087 std::map<PART_DEFINITION_PIN_ID, PIN> Pins; 1088 std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues; ///< Some attributes are 1089 ///< defined within the part 1090 ///< definition, whilst others 1091 ///< are defined in the part 1092 std::vector<PIN_EQUIVALENCE> PinEquivalences; 1093 std::vector<SWAP_GROUP> SwapGroups; 1094 1095 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1096 }; 1097 1098 1099 struct PART_PIN : PARSER ///< "PARTPIN" node name 1100 { 1101 PART_PIN_ID ID; 1102 wxString Name = wxEmptyString; 1103 PIN_TYPE Type = PIN_TYPE::UNCOMMITTED; 1104 wxString Identifier = wxEmptyString; 1105 1106 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1107 }; 1108 1109 1110 PART_ID ID; 1111 wxString Name; 1112 long Version; 1113 DEFINITION Definition; 1114 std::map<PART_PIN_ID, PART_PIN> PartPins; ///< It is unclear why there are two "Pin" 1115 ///< structures in CPA files... PART_PIN seems to 1116 ///< be a reduced version of PART::DEFINITION::PIN 1117 ///< Therefore, PART_PIN is only included for 1118 ///< completeness of the parser, but won't be used 1119 1120 bool HidePinNames = false; ///< This seems to be a duplicate of DEFINITION::HidePinNames 1121 ///< Possibly only used in older file formats? 1122 1123 std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues; ///< Some attributes are defined 1124 ///< within the part definition, 1125 ///< whilst others are defined in 1126 ///< the part itself 1127 1128 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1129 }; 1130 1131 1132 struct PARTS : PARSER 1133 { 1134 std::map<PART_ID, PART> PartDefinitions; 1135 1136 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1137 }; 1138 1139 1140 struct NET : PARSER 1141 { 1142 struct JUNCTION : PARSER ///< "JPT" nodename. 1143 { 1144 NETELEMENT_ID ID; ///< First character is "J" 1145 LAYER_ID LayerID; 1146 POINT Location; 1147 GROUP_ID GroupID = wxEmptyString; ///< If not empty, this JUCTION is part of a 1148 ///< group 1149 REUSEBLOCKREF ReuseBlockRef; 1150 bool Fixed = false; 1151 1152 void ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext ); 1153 bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext ); 1154 virtual void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1155 }; 1156 1157 1158 struct CONNECTION : PARSER ///< "CONN" nodename 1159 { 1160 NETELEMENT_ID StartNode; 1161 NETELEMENT_ID EndNode; 1162 ROUTECODE_ID RouteCodeID; 1163 1164 bool Fixed = false; 1165 bool Hidden = false; 1166 GROUP_ID GroupID = wxEmptyString; ///< If not empty, this connection is part of a group 1167 REUSEBLOCKREF ReuseBlockRef; 1168 1169 std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues; ///< It is possible to add 1170 ///< attributes solely to a 1171 ///< particular connection 1172 void ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext ); 1173 bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext ); 1174 ~CONNECTIONNET::CONNECTION1175 virtual ~CONNECTION() {} 1176 }; 1177 1178 NET_ID ID; 1179 ROUTECODE_ID RouteCodeID = wxEmptyString; ///< "NETCODE" subnode 1180 long SignalNum = UNDEFINED_VALUE; ///< This is undefined if the net has been 1181 ///< given a name. "SIGNUM" subnode. 1182 wxString Name = wxEmptyString; ///< This is undefined (wxEmptyString) if the net 1183 ///< is unnamed. "SIGNAME" subnode 1184 bool Highlight = false; 1185 1186 std::map<NETELEMENT_ID, JUNCTION> Junctions; 1187 std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues; 1188 1189 NETCLASS_ID NetClassID = 1190 wxEmptyString; ///< The net might not have a net class, in which case it will be 1191 ///< wxEmptyString ("NETCLASSREF" subnode) 1192 SPACING_CLASS_ID SpacingClassID = 1193 wxEmptyString; ///< The net might not have a spacing class, in which case it will 1194 ///< be wxEmptyString ("SPACINGCLASS" subnode) 1195 1196 void ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext ); 1197 bool ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext ); 1198 }; 1199 1200 1201 struct DOCUMENTATION_SYMBOL : PARSER 1202 { 1203 DOCUMENTATION_SYMBOL_ID ID; 1204 1205 SYMDEF_ID SymdefID; ///< Normally documentation symbols only have TEXT, FIGURE and 1206 ///< TEXT_LOCATION objects which are all drawn on the "(Undefined)" 1207 ///< Layer. When used in the design, the user has to specify which 1208 ///< layer to draw it on. 1209 LAYER_ID LayerID; ///< Move all objects in the Symdef to this layer. 1210 POINT Origin; ///< Origin of the component (this is used as the reference point 1211 ///< when placing the component in the design) 1212 1213 GROUP_ID GroupID = wxEmptyString; ///< If not empty, this component is part of a group 1214 REUSEBLOCKREF ReuseBlockRef; 1215 long OrientAngle = 0; 1216 bool Mirror = false; 1217 bool Fixed = false; 1218 READABILITY Readability = READABILITY::BOTTOM_TO_TOP; 1219 1220 long ScaleRatioNumerator = 1; ///< Documentation symbols can be arbitrarily scaled when 1221 ///< added to a design 1222 long ScaleRatioDenominator = 1; ///< Documentation symbols can be arbitrarily scaled when 1223 ///< added to a design 1224 1225 std::map<ATTRIBUTE_ID, ATTRIBUTE_VALUE> AttributeValues; 1226 1227 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1228 }; 1229 1230 1231 struct DFLTSETTINGS : PARSER 1232 { 1233 COLOR_ID Color; 1234 bool IsVisible = true; 1235 1236 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1237 }; 1238 1239 1240 struct ATTRCOL : PARSER 1241 { 1242 ATTRIBUTE_ID AttributeID; 1243 COLOR_ID Color; 1244 bool IsVisible = true; 1245 bool IsPickable = true; 1246 1247 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1248 }; 1249 1250 1251 struct ATTRCOLORS : PARSER 1252 { 1253 DFLTSETTINGS DefaultSettings; 1254 std::map<ATTRIBUTE_ID, ATTRCOL> AttributeColors; 1255 1256 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1257 }; 1258 1259 1260 struct PARTNAMECOL : PARSER 1261 { 1262 COLOR_ID Color; 1263 bool IsVisible = true; 1264 bool IsPickable = true; 1265 1266 void Parse( XNODE* aNode, PARSER_CONTEXT* aContext ) override; 1267 }; 1268 1269 /////////////////////// 1270 // HELPER FUNCTIONS: // 1271 /////////////////////// 1272 1273 1274 static void InsertAttributeAtEnd( XNODE* aNode, wxString aValue ); 1275 1276 /** 1277 * @brief Reads a CADSTAR Archive file (S-parameter format) 1278 * @param aFileName 1279 * @param aFileTypeIdentifier Identifier of the first node in the file to check against. 1280 E.g. "CADSTARPCB" 1281 * @param aProgressReporter Pointer to a Progress Reporter to report progress to. 1282 * @return XNODE pointing to the top of the tree for further parsing. Each node has the first 1283 * element as the node's name and subsequent elements as node attributes ("attr0", 1284 * "attr1", "attr2", etc.). Caller is responsible for deleting to avoid memory leaks. 1285 * @throws IO_ERROR 1286 */ 1287 static XNODE* LoadArchiveFile( const wxString& aFileName, const wxString& aFileTypeIdentifier, 1288 PROGRESS_REPORTER* aProgressReporter = nullptr ); 1289 1290 /** 1291 * @brief 1292 * @param aAttribute 1293 * @return 1294 */ 1295 static bool IsValidAttribute( wxXmlAttribute* aAttribute ); 1296 1297 /** 1298 * @brief 1299 * @param aNode 1300 * @param aID 1301 * @param aIsRequired Prevents exception throwing if false. 1302 * @return returns the value (wxString) of attribute "attrX" in aNode where 'X' is aID 1303 * @throws IO_ERROR if attribute does not exist 1304 */ 1305 static wxString GetXmlAttributeIDString( 1306 XNODE* aNode, unsigned int aID, bool aIsRequired = true ); 1307 1308 /** 1309 * @brief 1310 * @param aNode 1311 * @param aID 1312 * @param aIsRequired Prevents exception throwing if false. 1313 * @return returns the value (long) of attribute "attrX" in aNode where 'X' is aID 1314 * @throws IO_ERROR if attribute does not exist 1315 */ 1316 static long GetXmlAttributeIDLong( XNODE* aNode, unsigned int aID, bool aIsRequired = true ); 1317 1318 /** 1319 * @brief 1320 * @param aNode 1321 * @throw IO_ERROR if a child node was found 1322 */ 1323 static void CheckNoChildNodes( XNODE* aNode ); 1324 1325 /** 1326 * @brief 1327 * @param aNode 1328 * @throw IO_ERROR if a node adjacent to aNode was found 1329 */ 1330 static void CheckNoNextNodes( XNODE* aNode ); 1331 1332 /** 1333 * @brief 1334 * @param aNode with a child node containing an EVALUE 1335 * @param aValueToParse 1336 * @throw IO_ERROR if unable to parse or node is not an EVALUE 1337 */ 1338 static void ParseChildEValue( XNODE* aNode, PARSER_CONTEXT* aContext, EVALUE& aValueToParse ); 1339 1340 /** 1341 * @brief if no children are present, it just returns an empty 1342 * vector (without throwing an exception) 1343 * @param aNode containing a series of POINT objects 1344 * @param aTestAllChildNodes 1345 * @param aExpectedNumPoints if UNDEFINED_VALUE (i.e. -1), this is check is disabled 1346 * @return std::vector containing all POINT objects 1347 * @throw IO_ERROR if one of the following: 1348 * - Unable to parse a POINT object 1349 * - aTestAllChildNodes is true and one of the child nodes is not a valid POINT object 1350 * - aExpectedNumPoints is non-negative and the number of POINT objects found is different 1351 */ 1352 static std::vector<POINT> ParseAllChildPoints( XNODE* aNode, PARSER_CONTEXT* aContext, 1353 bool aTestAllChildNodes = false, int aExpectedNumPoints = UNDEFINED_VALUE ); 1354 1355 /** 1356 * @brief if no children are present, it just returns an empty 1357 * vector (without throwing an exception) 1358 * @param aNode containing a series of VERTEX objects 1359 * @param aTestAllChildNodes 1360 * @param aExpectedNumPoints if -1, this is check is disabled 1361 * @return std::vector containing all VERTEX objects 1362 * @throw IO_ERROR if one of the following: 1363 * - Unable to parse a VERTEX object 1364 * - aTestAllChildNodes is true and one of the child nodes is not a valid VERTEX object 1365 */ 1366 static std::vector<VERTEX> ParseAllChildVertices( 1367 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes = false ); 1368 1369 /** 1370 * @brief if no children are present, it just returns an empty 1371 * vector (without throwing an exception) 1372 * @param aNode containing a series of CUTOUT objects 1373 * @param aTestAllChildNodes 1374 * @param aExpectedNumPoints if -1, this is check is disabled 1375 * @return std::vector containing all CUTOUT objects 1376 * @throw IO_ERROR if one of the following: 1377 * - Unable to parse a CUTOUT object 1378 * - aTestAllChildNodes is true and one of the child nodes is not a valid CUTOUT object 1379 */ 1380 static std::vector<CUTOUT> ParseAllChildCutouts( 1381 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes = false ); 1382 1383 static long GetNumberOfChildNodes( XNODE* aNode ); 1384 1385 static long GetNumberOfStepsForReporting( XNODE* aRootNode, 1386 std::vector<wxString> aSubNodeChildrenToCount ); 1387 1388 /** 1389 * @brief Convert a string with CADSTAR overbar characters to equivalent in KiCad 1390 * @param aCadstarString Input string 1391 * @return KiCad string with overbar characters 1392 */ 1393 static wxString HandleTextOverbar( wxString aCadstarString ); 1394 1395 /** 1396 * Corrects the position of a text element that had NO_ALIGNMENT in CADSTAR. Assumes that the 1397 * provided text element has been initialised with a position and orientation. 1398 * @param aKiCadTextItem a Kicad item to correct 1399 */ 1400 static void FixTextPositionNoAlignment( EDA_TEXT* aKiCadTextItem ); 1401 generateLibName(const wxString & aRefName,const wxString & aAlternateName)1402 static wxString generateLibName( const wxString& aRefName, const wxString& aAlternateName ) 1403 { 1404 return aRefName 1405 + ( ( aAlternateName.size() > 0 ) ? ( wxT( " (" ) + aAlternateName + wxT( ")" ) ) 1406 : wxT( "" ) ); 1407 } 1408 1409 1410 protected: 1411 void checkPoint(); ///< Updates m_progressReporter or throws if user cancelled 1412 1413 PARSER_CONTEXT m_context; 1414 PROGRESS_REPORTER* m_progressReporter; // optional; may be nullptr 1415 1416 1417 }; // class CADSTAR_ARCHIVE_PARSER 1418 1419 #endif // CADSTAR_ARCHIVE_PARSER_H_ 1420