KiCad PCB EDA Suite
Loading...
Searching...
No Matches
cadstar_archive_parser.cpp
Go to the documentation of this file.
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 <[email protected]>
5 * Copyright The 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
18 * along with this program. If not, see <https://www.gnu.org/licenses/>.
19 */
20
25#include <wx/filename.h>
26#include <wx/log.h>
27#include <wx/xml/xml.h>
28
29#include <dsnlexer.h>
32#include <eda_item.h>
33#include <eda_text.h>
34#include <macros.h>
35#include <progress_reporter.h>
36#include <string_utils.h>
37#include <trigo.h>
38
39// Re-throw a child-node parse failure with the enclosing element added to the message. The
40// leaf error only names the offending node type (e.g. "PT"), which is ambiguous in a large
41// archive; prefixing the specific child and its parent section locates the failure.
42[[noreturn]] static void reThrowWithParentContext( const IO_ERROR& aError, XNODE* aChildNode,
43 XNODE* aParentNode )
44{
45 // TRANSLATORS: %s are, in order, the underlying error message, the child XML node name,
46 // and the enclosing (parent) XML node name.
47 THROW_IO_ERROR( wxString::Format( _( "%s (whilst parsing '%s' in '%s')" ), aError.Problem(),
48 aChildNode->GetName(), aParentNode->GetName() ) );
49}
50
51
52// Ratio derived from CADSTAR default font. See doxygen comment in cadstar_archive_parser.h
53const double CADSTAR_ARCHIVE_PARSER::TXT_HEIGHT_RATIO = ( 24.0 - 5.0 ) / 24.0;
54
55// Cadstar fields and their KiCad equivalent
56const std::map<CADSTAR_ARCHIVE_PARSER::TEXT_FIELD_NAME, wxString>
58 { { TEXT_FIELD_NAME::DESIGN_TITLE, wxT( "DESIGN_TITLE" ) },
59 { TEXT_FIELD_NAME::SHORT_JOBNAME, wxT( "SHORT_JOBNAME" ) },
60 { TEXT_FIELD_NAME::LONG_JOBNAME, wxT( "LONG_JOBNAME" ) },
61 { TEXT_FIELD_NAME::NUM_OF_SHEETS, wxT( "##" ) },
62 { TEXT_FIELD_NAME::SHEET_NUMBER, wxT( "#" ) },
63 { TEXT_FIELD_NAME::SHEET_NAME, wxT( "SHEETNAME" ) },
64 { TEXT_FIELD_NAME::VARIANT_NAME, wxT( "VARIANT_NAME" ) },
65 { TEXT_FIELD_NAME::VARIANT_DESCRIPTION, wxT( "VARIANT_DESCRIPTION" ) },
66 { TEXT_FIELD_NAME::REG_USER, wxT( "REG_USER" ) },
67 { TEXT_FIELD_NAME::COMPANY_NAME, wxT( "COMPANY_NAME" ) },
68 { TEXT_FIELD_NAME::CURRENT_USER, wxT( "CURRENT_USER" ) },
69 { TEXT_FIELD_NAME::DATE, wxT( "DATE" ) },
70 { TEXT_FIELD_NAME::TIME, wxT( "TIME" ) },
71 { TEXT_FIELD_NAME::MACHINE_NAME, wxT( "MACHINE_NAME" ) } };
72
73
75{
76 wxASSERT( aNode->GetName() == wxT( "FORMAT" ) );
77
78 Type = GetXmlAttributeIDString( aNode, 0 );
79 SomeInt = GetXmlAttributeIDLong( aNode, 1 );
80 Version = GetXmlAttributeIDLong( aNode, 2 );
81}
82
83
85{
86 wxASSERT( aNode->GetName() == wxT( "TIMESTAMP" ) );
87
88 if( !GetXmlAttributeIDString( aNode, 0 ).ToLong( &Year )
89 || !GetXmlAttributeIDString( aNode, 1 ).ToLong( &Month )
90 || !GetXmlAttributeIDString( aNode, 2 ).ToLong( &Day )
91 || !GetXmlAttributeIDString( aNode, 3 ).ToLong( &Hour )
92 || !GetXmlAttributeIDString( aNode, 4 ).ToLong( &Minute )
93 || !GetXmlAttributeIDString( aNode, 5 ).ToLong( &Second ) )
94 THROW_PARSING_IO_ERROR( wxT( "TIMESTAMP" ), wxString::Format( "HEADER" ) );
95}
96
97
99{
100 wxASSERT( aNode->GetName() == wxT( "HEADER" ) );
101
102 XNODE* cNode = aNode->GetChildren();
103
104 for( ; cNode; cNode = cNode->GetNext() )
105 {
106 wxString nodeName = cNode->GetName();
107
108 if( nodeName == wxT( "FORMAT" ) )
109 {
110 Format.Parse( cNode, aContext );
111 }
112 else if( nodeName == wxT( "JOBFILE" ) )
113 {
114 JobFile = GetXmlAttributeIDString( cNode, 0 );
115 }
116 else if( nodeName == wxT( "JOBTITLE" ) )
117 {
118 JobTitle = GetXmlAttributeIDString( cNode, 0 );
119 }
120 else if( nodeName == wxT( "GENERATOR" ) )
121 {
123 }
124 else if( nodeName == wxT( "RESOLUTION" ) )
125 {
126 XNODE* subNode = cNode->GetChildren();
127
128 if( ( subNode->GetName() == wxT( "METRIC" ) )
129 && ( GetXmlAttributeIDString( subNode, 0 ) == wxT( "HUNDREDTH" ) )
130 && ( GetXmlAttributeIDString( subNode, 1 ) == wxT( "MICRON" ) ) )
131 {
133 }
134 else
135 {
136 // TODO Need to find out if there are other possible resolutions. Logically
137 // there must be other base units that could be used, such as "IMPERIAL INCH"
138 // or "METRIC MM" but so far none of settings in CADSTAR generated a different
139 // output resolution to "HUNDREDTH MICRON"
140 WARN_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), wxT( "HEADER->RESOLUTION" ) );
141 }
142 }
143 else if( nodeName == wxT( "TIMESTAMP" ) )
144 {
145 Timestamp.Parse( cNode, aContext );
146 }
147 else
148 {
149 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "HEADER" ) );
150 }
151 }
152}
153
154
156{
157 wxASSERT( aNode->GetName() == wxT( "VMASTER" ) || aNode->GetName() == wxT( "VARIANT" ) );
158
159 ID = GetXmlAttributeIDString( aNode, 0 );
160
161 if( aNode->GetName() == wxT( "VMASTER" ) )
162 {
163 Name = GetXmlAttributeIDString( aNode, 1 );
165 }
166 else
167 {
168 ParentID = GetXmlAttributeIDString( aNode, 1 );
169 Name = GetXmlAttributeIDString( aNode, 2 );
171 }
172}
173
174
176{
177 wxASSERT( aNode->GetName() == wxT( "VHIERARCHY" ) );
178
179 XNODE* cNode = aNode->GetChildren();
180
181 for( ; cNode; cNode = cNode->GetNext() )
182 {
183 if( cNode->GetName() == wxT( "VMASTER" ) || cNode->GetName() == wxT( "VARIANT" ) )
184 {
185 VARIANT variant;
186 variant.Parse( cNode, aContext );
187 Variants.insert( std::make_pair( variant.ID, variant ) );
188 }
189 else
190 {
191 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), cNode->GetName() );
192 }
193 }
194}
195
196
198{
199 wxASSERT( aNode->GetName() == wxT( "LINECODE" ) );
200
201 ID = GetXmlAttributeIDString( aNode, 0 );
202 Name = GetXmlAttributeIDString( aNode, 1 );
203
204 if( !GetXmlAttributeIDString( aNode, 2 ).ToLong( &Width ) )
205 THROW_PARSING_IO_ERROR( wxT( "Line Width" ), wxString::Format( "LINECODE -> %s", Name ) );
206
207 XNODE* cNode = aNode->GetChildren();
208
209 if( !cNode || cNode->GetName() != wxT( "STYLE" ) )
210 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxString::Format( "LINECODE -> %s", Name ) );
211
212 wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
213
214 if( styleStr == wxT( "SOLID" ) )
215 {
217 }
218 else if( styleStr == wxT( "DASH" ) )
219 {
221 }
222 else if( styleStr == wxT( "DASHDOT" ) )
223 {
225 }
226 else if( styleStr == wxT( "DASHDOTDOT" ) )
227 {
229 }
230 else if( styleStr == wxT( "DOT" ) )
231 {
233 }
234 else
235 {
236 WARN_UNKNOWN_PARAMETER_IO_ERROR( wxString::Format( "STYLE %s", styleStr ),
237 wxString::Format( "LINECODE -> %s", Name ) );
238 }
239}
240
241
243{
244 wxASSERT( aNode->GetName() == wxT( "HATCH" ) );
245
246 Step = GetXmlAttributeIDLong( aNode, 0 );
247 LineWidth = GetXmlAttributeIDLong( aNode, 2 );
248
249 XNODE* cNode = aNode->GetChildren();
250
251 if( !cNode || cNode->GetName() != wxT( "ORIENT" ) )
252 THROW_MISSING_NODE_IO_ERROR( wxT( "ORIENT" ), wxT( "HATCH" ) );
253
255}
256
257
259{
260 wxASSERT( aNode->GetName() == wxT( "HATCHCODE" ) );
261
262 ID = GetXmlAttributeIDString( aNode, 0 );
263 Name = GetXmlAttributeIDString( aNode, 1 );
264
265 XNODE* cNode = aNode->GetChildren();
266 wxString location = wxString::Format( "HATCHCODE -> %s", Name );
267
268 for( ; cNode; cNode = cNode->GetNext() )
269 {
270 if( cNode->GetName() != wxT( "HATCH" ) )
271 {
272 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), location );
273 continue;
274 }
275
276 HATCH hatch;
277 hatch.Parse( cNode, aContext );
278 Hatches.push_back( hatch );
279 }
280}
281
282
284{
285 wxASSERT( aNode->GetName() == wxT( "FONT" ) );
286
287 Name = GetXmlAttributeIDString( aNode, 0 );
288 Modifier1 = GetXmlAttributeIDLong( aNode, 1 );
289 Modifier2 = GetXmlAttributeIDLong( aNode, 2 );
290
291 XNODE* cNode = aNode->GetChildren();
292
293 for( ; cNode; cNode = cNode->GetNext() )
294 {
295 wxString cNodeName = cNode->GetName();
296
297 if( cNodeName == wxT( "ITALIC" ) )
298 Italic = true;
299 else if( cNodeName == wxT( "KERNING" ) )
300 KerningPairs = true;
301 else
302 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
303 }
304}
305
306
308{
309 wxASSERT( aNode->GetName() == wxT( "TEXTCODE" ) );
310
311 ID = GetXmlAttributeIDString( aNode, 0 );
312 Name = GetXmlAttributeIDString( aNode, 1 );
313
314 LineWidth = GetXmlAttributeIDLong( aNode, 2 );
315 Height = GetXmlAttributeIDLong( aNode, 3 );
316 Width = GetXmlAttributeIDLong( aNode, 4 );
317
318 XNODE* cNode = aNode->GetChildren();
319
320 if( cNode )
321 {
322 if( cNode->GetName() == wxT( "FONT" ) )
323 Font.Parse( cNode, aContext );
324 else
325 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
326 }
327}
328
329
331{
332 wxASSERT( aNode->GetName() == wxT( "ROUTEREASSIGN" ) );
333
334 LayerID = GetXmlAttributeIDString( aNode, 0 );
335 OptimalWidth = GetXmlAttributeIDLong( aNode, 1, false );
336
337 XNODE* cNode = aNode->GetChildren();
338
339 for( ; cNode; cNode = cNode->GetNext() )
340 {
341 wxString cNodeName = cNode->GetName();
342
343 if( cNodeName == wxT( "NECKWIDTH" ) )
345 else if( cNodeName == wxT( "SROUTEWIDTH" ) )
347 else if( cNodeName == wxT( "MINWIDTH" ) )
348 MinWidth = GetXmlAttributeIDLong( cNode, 0 );
349 else if( cNodeName == wxT( "MAXWIDTH" ) )
350 MaxWidth = GetXmlAttributeIDLong( cNode, 0 );
351 else
352 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
353 }
354}
355
356
358{
359 wxASSERT( aNode->GetName() == wxT( "ROUTECODE" ) );
360
361 ID = GetXmlAttributeIDString( aNode, 0 );
362 Name = GetXmlAttributeIDString( aNode, 1 );
363 OptimalWidth = GetXmlAttributeIDLong( aNode, 2, false );
364
365 XNODE* cNode = aNode->GetChildren();
366
367 for( ; cNode; cNode = cNode->GetNext() )
368 {
369 wxString cNodeName = cNode->GetName();
370
371 if( cNodeName == wxT( "NECKWIDTH" ) )
372 {
374 }
375 else if( cNodeName == wxT( "SROUTEWIDTH" ) )
376 {
378 }
379 else if( cNodeName == wxT( "MINWIDTH" ) )
380 {
381 MinWidth = GetXmlAttributeIDLong( cNode, 0 );
382 }
383 else if( cNodeName == wxT( "MAXWIDTH" ) )
384 {
385 MaxWidth = GetXmlAttributeIDLong( cNode, 0 );
386 }
387 else if( cNodeName == wxT( "ROUTEREASSIGN" ) )
388 {
389 ROUTEREASSIGN routereassign;
390 routereassign.Parse( cNode, aContext );
391 RouteReassigns.push_back( routereassign );
392 }
393 else
394 {
395 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
396 }
397 }
398}
399
400
402{
403 return Base * std::pow( 10.0, Exponent );
404}
405
406
408{
409 wxASSERT( aNode->GetName() == wxT( "E" ) );
410
411 if( ( !GetXmlAttributeIDString( aNode, 0 ).ToLong( &Base ) )
412 || ( !GetXmlAttributeIDString( aNode, 1 ).ToLong( &Exponent ) ) )
413 {
414 THROW_PARSING_IO_ERROR( wxT( "Base and Exponent" ),
415 wxString::Format( "%s->%s", aNode->GetParent()->GetName(),
416 aNode->GetParent()->GetName() ) );
417 }
418}
419
420
422{
423 wxASSERT( aNode->GetName() == wxT( "PT" ) );
424
425 x = GetXmlAttributeIDLong( aNode, 0 );
426 y = GetXmlAttributeIDLong( aNode, 1 );
427}
428
429
431{
432 wxASSERT( aNode->GetName() == wxT( "PT" ) );
433
434 x = GetXmlAttributeIDLong( aNode, 0 );
435 y = GetXmlAttributeIDLong( aNode, 1 );
436}
437
438
440{
441 wxString aNodeName = aNode->GetName();
442
443 if( aNodeName == wxT( "PT" ) || aNodeName == wxT( "ACWARC" ) || aNodeName == wxT( "CWARC" )
444 || aNodeName == wxT( "CWSEMI" ) || aNodeName == wxT( "ACWSEMI" ) )
445 {
446 return true;
447 }
448 else
449 {
450 return false;
451 }
452}
453
454
456{
457 wxASSERT( IsVertex( aNode ) );
458
459 wxString aNodeName = aNode->GetName();
460
461 if( aNodeName == wxT( "PT" ) )
462 {
466 End.Parse( aNode, aContext );
467 }
468 else if( aNodeName == wxT( "ACWARC" ) || aNodeName == wxT( "CWARC" ) )
469 {
470 if( aNodeName == wxT( "ACWARC" ) )
472 else
474
475 std::vector<POINT> pts = ParseAllChildPoints( aNode, aContext, true, 2 );
476
477 Center = pts[0];
478 End = pts[1];
479 }
480 else if( aNodeName == wxT( "ACWSEMI" ) || aNodeName == wxT( "CWSEMI" ) )
481 {
482 if( aNodeName == wxT( "ACWSEMI" ) )
484 else
486
489
490 std::vector<POINT> pts = ParseAllChildPoints( aNode, aContext, true, 1 );
491
492 End = pts[0];
493 }
494 else
495 {
496 wxASSERT_MSG( true, wxT( "Unknown VERTEX type" ) );
497 }
498}
499
500
502 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
503 int aAccuracy ) const
504{
506 {
507 aChainToAppendTo->Append( aCadstarToKicadPointCallback( End ) );
508 return;
509 }
510
511 wxCHECK_MSG( aChainToAppendTo->PointCount() > 0, /*void*/,
512 "Can't append an arc to vertex to an empty chain" );
513
514 aChainToAppendTo->Append( BuildArc( aChainToAppendTo->GetPoint( -1 ),
515 aCadstarToKicadPointCallback ),
516 aAccuracy );
517}
518
519
521 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback ) const
522{
523 wxCHECK_MSG( Type != VERTEX_TYPE::VT_POINT, SHAPE_ARC(),
524 "Can't build an arc for a straight segment!" );
525
526 VECTOR2I startPoint = aPrevPoint;
527 VECTOR2I endPoint = aCadstarToKicadPointCallback( End );
528 VECTOR2I centerPoint;
529
531 centerPoint = ( startPoint / 2 ) + ( endPoint / 2 );
532 else
533 centerPoint = aCadstarToKicadPointCallback( Center );
534
535 bool clockwise = Type == VERTEX_TYPE::CLOCKWISE_ARC
537
538 // A bit of a hack to figure out if we need to invert clockwise due to the transform
539 VECTOR2I transform = aCadstarToKicadPointCallback( { 500, 500 } )
540 - aCadstarToKicadPointCallback( { 0, 0 } );
541
542 if( ( transform.x > 0 && transform.y < 0 ) || ( transform.x < 0 && transform.y > 0 ) )
543 clockwise = !clockwise;
544
545 SHAPE_ARC arc;
546
547 return arc.ConstructFromStartEndCenter( startPoint, endPoint, centerPoint, clockwise );
548}
549
550
552{
553 wxASSERT( aNode->GetName() == wxT( "CUTOUT" ) );
554
555 Vertices = ParseAllChildVertices( aNode, aContext, true );
556}
557
558
560{
561 wxString aNodeName = aNode->GetName();
562
563 if( aNodeName == wxT( "OPENSHAPE" ) || aNodeName == wxT( "OUTLINE" )
564 || aNodeName == wxT( "SOLID" ) || aNodeName == wxT( "HATCHED" ) )
565 {
566 return true;
567 }
568 else
569 {
570 return false;
571 }
572}
573
574
576{
577 wxASSERT( IsShape( aNode ) );
578
579 wxString aNodeName = aNode->GetName();
580
581 if( aNodeName == wxT( "OPENSHAPE" ) )
582 {
584 Vertices = ParseAllChildVertices( aNode, aContext, true );
585 Cutouts.clear();
586 HatchCodeID = wxEmptyString;
587 }
588 else if( aNodeName == wxT( "OUTLINE" ) )
589 {
591 Vertices = ParseAllChildVertices( aNode, aContext, false );
592 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
593 HatchCodeID = wxEmptyString;
594 }
595 else if( aNodeName == wxT( "SOLID" ) )
596 {
598 Vertices = ParseAllChildVertices( aNode, aContext, false );
599 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
600 HatchCodeID = wxEmptyString;
601 }
602 else if( aNodeName == wxT( "HATCHED" ) )
603 {
605 Vertices = ParseAllChildVertices( aNode, aContext, false );
606 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
608 }
609 else
610 {
611 wxASSERT_MSG( true, wxT( "Unknown SHAPE type" ) );
612 }
613}
614
616 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
617 int aMaxError ) const
618{
619 SHAPE_LINE_CHAIN outline;
620
621 if( Vertices.size() == 0 )
622 return outline;
623
624 for( const auto& vertex : Vertices )
625 vertex.AppendToChain( &outline, aCadstarToKicadPointCallback, aMaxError );
626
628 {
629 outline.SetClosed( true );
630
631 // Append after closing, to ensre first and last point remain the same
632 outline.Append( outline.CPoint( 0 ), true );
633 }
634
635 return outline;
636}
637
638
640 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
641 int aMaxError ) const
642{
643 SHAPE_POLY_SET polyset;
644
645 // We shouldn't convert openshapes to polyset!
646 wxCHECK( Type != SHAPE_TYPE::OPENSHAPE, polyset );
647
648 polyset.AddOutline( OutlineAsChain( aCadstarToKicadPointCallback, aMaxError ) );
649
650 for( const auto& cutout : Cutouts )
651 {
652 SHAPE_LINE_CHAIN hole;
653
654 if( cutout.Vertices.size() == 0 )
655 continue;
656
657 for( const auto& cutoutVertex : cutout.Vertices )
658 cutoutVertex.AppendToChain( &hole, aCadstarToKicadPointCallback, aMaxError );
659
660 hole.SetClosed( true );
661
662 // Append after closing, to ensre first and last point remain the same
663 cutout.Vertices.at( 0 ).AppendToChain( &hole, aCadstarToKicadPointCallback, aMaxError );
664
665 polyset.AddHole( hole );
666 }
667
668 return polyset;
669}
670
671
673{
674 wxASSERT( aNode->GetName() == wxT( "UNITS" ) );
675
676 wxString unit = GetXmlAttributeIDString( aNode, 0 );
677
678 if( unit == wxT( "CENTIMETER" ) )
679 return UNITS::CENTIMETER;
680 else if( unit == wxT( "INCH" ) )
681 return UNITS::INCH;
682 else if( unit == wxT( "METER" ) )
683 return UNITS::METER;
684 else if( unit == wxT( "MICROMETRE" ) )
685 return UNITS::MICROMETRE;
686 else if( unit == wxT( "MM" ) )
687 return UNITS::MM;
688 else if( unit == wxT( "THOU" ) )
689 return UNITS::THOU;
690 else if( unit == wxT( "DESIGN" ) )
691 return UNITS::DESIGN;
692 else
693 WARN_UNKNOWN_PARAMETER_IO_ERROR( unit, wxT( "UNITS" ) );
694
695 return UNITS::DESIGN;
696}
697
698
700{
701 wxASSERT( aNode->GetName() == wxT( "ANGUNITS" ) );
702
703 wxString angUnitStr = GetXmlAttributeIDString( aNode, 0 );
704
705 if( angUnitStr == wxT( "DEGREES" ) )
706 return ANGUNITS::DEGREES;
707 else if( angUnitStr == wxT( "RADIANS" ) )
708 return ANGUNITS::RADIANS;
709 else
710 WARN_UNKNOWN_PARAMETER_IO_ERROR( angUnitStr, aNode->GetName() );
711
712 return ANGUNITS::DEGREES;
713}
714
715
717{
718 if( !aNode )
719 return false;
720
721 wxString aNodeName = aNode->GetName();
722
723 if( aNodeName == wxT( "FRACTIONALGRID" ) || aNodeName == wxT( "STEPGRID" ) )
724 return true;
725 else
726 return false;
727}
728
729
731{
732 wxASSERT( IsGrid( aNode ) );
733
734 wxString aNodeName = aNode->GetName();
735
736 if( aNodeName == wxT( "FRACTIONALGRID" ) )
738 else if( aNodeName == wxT( "STEPGRID" ) )
740 else
741 wxASSERT_MSG( true, wxT( "Unknown Grid Type" ) );
742
743 Name = GetXmlAttributeIDString( aNode, 0 );
744 Param1 = GetXmlAttributeIDLong( aNode, 1 );
745 Param2 = GetXmlAttributeIDLong( aNode, 2 );
746}
747
748
750{
751 wxASSERT( aNode->GetName() == wxT( "GRIDS" ) );
752
753 XNODE* cNode = aNode->GetChildren();
754
755 for( ; cNode; cNode = cNode->GetNext() )
756 {
757 wxString cNodeName = cNode->GetName();
758
759 if( cNodeName == wxT( "WORKINGGRID" ) )
760 {
761 XNODE* workingGridNode = cNode->GetChildren();
762
763 if( !GRID::IsGrid( workingGridNode ) )
764 {
765 wxString found = workingGridNode ? workingGridNode->GetName() : wxString( "(empty)" );
766 WARN_UNKNOWN_NODE_IO_ERROR( found, wxT( "GRIDS -> WORKINGGRID" ) );
767 }
768 else
769 {
770 WorkingGrid.Parse( workingGridNode, aContext );
771 }
772 }
773 else if( cNodeName == wxT( "SCREENGRID" ) )
774 {
775 XNODE* screenGridNode = cNode->GetChildren();
776
777 if( !GRID::IsGrid( screenGridNode ) )
778 {
779 wxString found = screenGridNode ? screenGridNode->GetName() : wxString( "(empty)" );
780 WARN_UNKNOWN_NODE_IO_ERROR( found, wxT( "GRIDS -> SCREENGRID" ) );
781 }
782 else
783 {
784 ScreenGrid.Parse( screenGridNode, aContext );
785 }
786 }
787 else if( GRID::IsGrid( cNode ) )
788 {
789 GRID userGrid;
790 userGrid.Parse( cNode, aContext );
791 UserGrids.push_back( userGrid );
792 }
793 else
794 {
795 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "GRIDS" ) );
796 }
797 }
798}
799
800
802{
803 wxString cNodeName = aChildNode->GetName();
804
805 if( cNodeName == wxT( "UNITS" ) )
806 {
807 Units = ParseUnits( aChildNode );
808 }
809 else if( cNodeName == wxT( "UNITSPRECISION" ) )
810 {
811 UnitDisplPrecision = GetXmlAttributeIDLong( aChildNode, 0 );
812 }
813 else if( cNodeName == wxT( "INTERLINEGAP" ) )
814 {
815 InterlineGap = GetXmlAttributeIDLong( aChildNode, 0 );
816 }
817 else if( cNodeName == wxT( "BARLINEGAP" ) )
818 {
819 BarlineGap = GetXmlAttributeIDLong( aChildNode, 0 );
820 }
821 else if( cNodeName == wxT( "ALLOWBARTEXT" ) )
822 {
823 AllowBarredText = true;
824 }
825 else if( cNodeName == wxT( "ANGULARPRECISION" ) )
826 {
827 AngularPrecision = GetXmlAttributeIDLong( aChildNode, 0 );
828 }
829 else if( cNodeName == wxT( "DESIGNORIGIN" ) )
830 {
831 DesignOrigin.Parse( aChildNode->GetChildren(), aContext );
832 }
833 else if( cNodeName == wxT( "DESIGNAREA" ) )
834 {
835 std::vector<POINT> pts = ParseAllChildPoints( aChildNode, aContext, true, 2 );
836 DesignArea = std::make_pair( pts[0], pts[1] );
837 }
838 else if( cNodeName == wxT( "DESIGNREF" ) )
839 {
840 DesignOrigin.Parse( aChildNode->GetChildren(), aContext );
841 }
842 else if( cNodeName == wxT( "DESIGNLIMIT" ) )
843 {
844 DesignLimit.Parse( aChildNode->GetChildren(), aContext );
845 }
846 else if( cNodeName == wxT( "PINNOOFFSET" ) )
847 {
848 PinNoOffset = GetXmlAttributeIDLong( aChildNode, 0 );
849 }
850 else if( cNodeName == wxT( "PINNOANGLE" ) )
851 {
852 PinNoAngle = GetXmlAttributeIDLong( aChildNode, 0 );
853 }
854 else
855 {
856 return false;
857 }
858
859 return true;
860}
861
862
864{
865 wxASSERT( aNode->GetName() == wxT( "SETTINGS" ) );
866
867 XNODE* cNode = aNode->GetChildren();
868
869 for( ; cNode; cNode = cNode->GetNext() )
870 {
871 wxString cNodeName = cNode->GetName();
872
873 if( ParseSubNode( cNode, aContext ) )
874 continue;
875 else
876 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "SETTINGS" ) );
877 }
878}
879
880
881wxString CADSTAR_ARCHIVE_PARSER::ParseTextFields( const wxString& aTextString,
882 PARSER_CONTEXT* aContext )
883{
884 static const std::map<TEXT_FIELD_NAME, wxString> txtTokens =
885 {
886 { TEXT_FIELD_NAME::DESIGN_TITLE, wxT( "DESIGN TITLE" ) },
887 { TEXT_FIELD_NAME::SHORT_JOBNAME, wxT( "SHORT_JOBNAME" ) },
888 { TEXT_FIELD_NAME::LONG_JOBNAME, wxT( "LONG_JOBNAME" ) },
889 { TEXT_FIELD_NAME::NUM_OF_SHEETS, wxT( "NUM_OF_SHEETS" ) },
890 { TEXT_FIELD_NAME::SHEET_NUMBER, wxT( "SHEET_NUMBER" ) },
891 { TEXT_FIELD_NAME::SHEET_NAME, wxT( "SHEET_NAME" ) },
892 { TEXT_FIELD_NAME::VARIANT_NAME, wxT( "VARIANT_NAME" ) },
893 { TEXT_FIELD_NAME::VARIANT_DESCRIPTION, wxT( "VARIANT_DESCRIPTION" ) },
894 { TEXT_FIELD_NAME::REG_USER, wxT( "REG_USER" ) },
895 { TEXT_FIELD_NAME::COMPANY_NAME, wxT( "COMPANY_NAME" ) },
896 { TEXT_FIELD_NAME::CURRENT_USER, wxT( "CURRENT_USER" ) },
897 { TEXT_FIELD_NAME::DATE, wxT( "DATE" ) },
898 { TEXT_FIELD_NAME::TIME, wxT( "TIME" ) },
899 { TEXT_FIELD_NAME::MACHINE_NAME, wxT( "MACHINE_NAME" ) },
900 { TEXT_FIELD_NAME::FROM_FILE, wxT( "FROM_FILE" ) },
901 { TEXT_FIELD_NAME::DISTANCE, wxT( "DISTANCE" ) },
902 { TEXT_FIELD_NAME::UNITS_SHORT, wxT( "UNITS SHORT" ) },
903 { TEXT_FIELD_NAME::UNITS_ABBREV, wxT( "UNITS ABBREV" ) },
904 { TEXT_FIELD_NAME::UNITS_FULL, wxT( "UNITS FULL" ) },
905 { TEXT_FIELD_NAME::HYPERLINK, wxT( "HYPERLINK" ) }
906 };
907
908 wxString remainingStr = aTextString;
909 wxString returnStr;
910
911 while( remainingStr.size() > 0 )
912 {
913 // Find the start token
914 size_t startpos = remainingStr.Find( wxT( "<@" ) );
915
916 if( static_cast<int>( startpos ) == wxNOT_FOUND )
917 {
918 // No more fields to parse, add to return string
919 returnStr += remainingStr;
920 break;
921 }
922
923 if( startpos > 0 )
924 returnStr += remainingStr.SubString( 0, startpos - 1 );
925
926 if( ( startpos + 2 ) >= remainingStr.size() )
927 break;
928
929 remainingStr = remainingStr.Mid( startpos + 2 );
930
931 //Find the expected token for the field
933
934 for( std::pair<TEXT_FIELD_NAME, wxString> txtF : txtTokens )
935 {
936 if( remainingStr.StartsWith( txtF.second ) )
937 {
938 foundField = txtF.first;
939 break;
940 }
941 }
942
943 if( foundField == TEXT_FIELD_NAME::NONE )
944 {
945 // Not a valid field, lets keep looking
946 returnStr += wxT( "<@" );
947 continue;
948 }
949
950 //Now lets find the end token
951 size_t endpos = remainingStr.Find( wxT( "@>" ) );
952
953 if( static_cast<int>( endpos ) == wxNOT_FOUND )
954 {
955 // The field we found isn't valid as it doesn't have a termination
956 // Lets append the whole thing as plain text
957 returnStr += wxT( "<@" ) + remainingStr;
958 break;
959 }
960
961 size_t valueStart = txtTokens.at( foundField ).size();
962 wxString fieldValue = remainingStr.SubString( valueStart, endpos - 1 );
963 wxString address;
964
965 if( foundField == TEXT_FIELD_NAME::FROM_FILE || foundField == TEXT_FIELD_NAME::HYPERLINK )
966 {
967 // The first character should always be a double quotation mark
968 wxASSERT_MSG( fieldValue.at( 0 ) == '"', "Expected '\"' as the first character" );
969
970 size_t splitPos = fieldValue.find_first_of( '"', 1 );
971 address = fieldValue.SubString( 1, splitPos - 1 );
972
973 if( foundField == TEXT_FIELD_NAME::HYPERLINK )
974 {
975 // Assume the last two characters are "@>"
976 wxASSERT_MSG( remainingStr.EndsWith( wxT( "@>" ) ),
977 "Expected '@>' at the end of a hyperlink" );
978
979 fieldValue = remainingStr.SubString( valueStart + splitPos + 1,
980 remainingStr.Length() - 3 );
981
982 remainingStr = wxEmptyString;
983 }
984 else
985 {
986 fieldValue = fieldValue.Mid( splitPos + 1 );
987 }
988 }
989
990 switch( foundField )
991 {
1003
1004 if( aContext->TextFieldToValuesMap.find( foundField )
1005 != aContext->TextFieldToValuesMap.end() )
1006 {
1007 aContext->InconsistentTextFields.insert( foundField );
1008 }
1009 else
1010 {
1011 aContext->TextFieldToValuesMap.insert( { foundField, fieldValue } );
1012 }
1013
1015
1019 returnStr += wxT( "${" ) + CADSTAR_TO_KICAD_FIELDS.at( foundField ) + wxT( "}" );
1020 break;
1021
1026 // Just flatten the text for distances
1027 returnStr += fieldValue;
1028 break;
1029
1031 {
1032 wxFileName fn( address );
1033 wxString fieldFmt = wxT( "FROM_FILE_%s_%s" );
1034 wxString fieldName = wxString::Format( fieldFmt, fn.GetName(), fn.GetExt() );
1035
1036 int version = 1;
1037
1038 while(
1039 aContext->FilenamesToTextMap.find( fieldName )
1040 != aContext->FilenamesToTextMap.end()
1041 && aContext->FilenamesToTextMap.at( fieldName ) != fieldValue )
1042 {
1043 fieldName = wxString::Format( fieldFmt, fn.GetName(), fn.GetExt() )
1044 + wxString::Format( wxT( "_%d" ), version++ );
1045 }
1046
1047 aContext->FilenamesToTextMap[fieldName] = fieldValue;
1048 returnStr += wxT( "${" ) + fieldName + wxT( "}" );
1049 }
1050 break;
1051
1053 {
1054 aContext->TextToHyperlinksMap[fieldValue] = address;
1055 returnStr += ParseTextFields( fieldValue, aContext );
1056 }
1057 break;
1058
1060 wxFAIL_MSG( "We should have already covered this scenario above" );
1061 break;
1062 }
1063
1064
1065 if( ( endpos + 2 ) >= remainingStr.size() )
1066 break;
1067
1068 remainingStr = remainingStr.Mid( endpos + 2 );
1069 }
1070
1071 return returnStr;
1072}
1073
1074
1076{
1077 wxASSERT( aNode->GetName() == wxT( "ALIGN" ) );
1078
1079 wxString alignmentStr = GetXmlAttributeIDString( aNode, 0 );
1080
1081 if( alignmentStr == wxT( "BOTTOMCENTER" ) )
1083 else if( alignmentStr == wxT( "BOTTOMLEFT" ) )
1084 return ALIGNMENT::BOTTOMLEFT;
1085 else if( alignmentStr == wxT( "BOTTOMRIGHT" ) )
1087 else if( alignmentStr == wxT( "CENTERCENTER" ) )
1089 else if( alignmentStr == wxT( "CENTERLEFT" ) )
1090 return ALIGNMENT::CENTERLEFT;
1091 else if( alignmentStr == wxT( "CENTERRIGHT" ) )
1093 else if( alignmentStr == wxT( "TOPCENTER" ) )
1094 return ALIGNMENT::TOPCENTER;
1095 else if( alignmentStr == wxT( "TOPLEFT" ) )
1096 return ALIGNMENT::TOPLEFT;
1097 else if( alignmentStr == wxT( "TOPRIGHT" ) )
1098 return ALIGNMENT::TOPRIGHT;
1099 else
1100 WARN_UNKNOWN_PARAMETER_IO_ERROR( alignmentStr, wxT( "ALIGN" ) );
1101
1102 //shouldn't be here but avoids compiler warning
1104}
1105
1106
1108{
1109 wxASSERT( aNode->GetName() == wxT( "JUSTIFICATION" ) );
1110
1111 wxString justificationStr = GetXmlAttributeIDString( aNode, 0 );
1112
1113 if( justificationStr == wxT( "LEFT" ) )
1114 return JUSTIFICATION::LEFT;
1115 else if( justificationStr == wxT( "RIGHT" ) )
1116 return JUSTIFICATION::RIGHT;
1117 else if( justificationStr == wxT( "CENTER" ) )
1118 return JUSTIFICATION::CENTER;
1119 else
1120 WARN_UNKNOWN_PARAMETER_IO_ERROR( justificationStr, wxT( "JUSTIFICATION" ) );
1121
1122 return JUSTIFICATION::LEFT;
1123}
1124
1125
1127{
1128 wxASSERT( aNode->GetName() == wxT( "READABILITY" ) );
1129
1130 wxString readabilityStr = GetXmlAttributeIDString( aNode, 0 );
1131
1132 if( readabilityStr == wxT( "BOTTOM_TO_TOP" ) )
1134 else if( readabilityStr == wxT( "TOP_TO_BOTTOM" ) )
1136 else
1137 WARN_UNKNOWN_PARAMETER_IO_ERROR( readabilityStr, wxT( "READABILITY" ) );
1138
1140}
1141
1142
1149
1150
1152 PARSER_CONTEXT* aContext )
1153{
1154 wxString cNodeName = aChildNode->GetName();
1155
1156 if( cNodeName == wxT( "PT" ) )
1157 Position.Parse( aChildNode, aContext );
1158 else if( cNodeName == wxT( "ORIENT" ) )
1159 OrientAngle = GetXmlAttributeIDLong( aChildNode, 0 );
1160 else if( cNodeName == wxT( "MIRROR" ) )
1161 Mirror = true;
1162 else if( cNodeName == wxT( "FIX" ) )
1163 Fixed = true;
1164 else if( cNodeName == wxT( "ALIGN" ) )
1165 Alignment = ParseAlignment( aChildNode );
1166 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1167 Justification = ParseJustification( aChildNode );
1168 else
1169 return false;
1170
1171 return true;
1172}
1173
1174
1176{
1177 wxASSERT( aNode->GetName() == wxT( "ATTRLOC" ) );
1178
1179 ParseIdentifiers( aNode, aContext );
1180
1181 //Parse child nodes
1182 XNODE* cNode = aNode->GetChildren();
1183
1184 for( ; cNode; cNode = cNode->GetNext() )
1185 {
1186 if( ParseSubNode( cNode, aContext ) )
1187 continue;
1188 else
1189 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "ATTRLOC" ) );
1190 }
1191
1193 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "ATTRLOC" ) );
1194}
1195
1196
1198{
1199 wxASSERT( aNode->GetName() == wxT( "COLUMNORDER" ) );
1200
1201 ID = GetXmlAttributeIDLong( aNode, 0 );
1202 Order = GetXmlAttributeIDLong( aNode, 1 );
1203
1204 CheckNoChildNodes( aNode );
1205}
1206
1207
1209{
1210 wxASSERT( aNode->GetName() == wxT( "COLUMNWIDTH" ) );
1211
1212 ID = GetXmlAttributeIDLong( aNode, 0 );
1213 Width = GetXmlAttributeIDLong( aNode, 1 );
1214
1215 CheckNoChildNodes( aNode );
1216}
1217
1218
1220{
1221 wxASSERT( aNode->GetName() == wxT( "ATTRNAME" ) );
1222
1223 ID = GetXmlAttributeIDString( aNode, 0 );
1224 Name = GetXmlAttributeIDString( aNode, 1 );
1225
1226 XNODE* cNode = aNode->GetChildren();
1227 wxString location = wxString::Format( "ATTRNAME -> %s", Name );
1228
1229 for( ; cNode; cNode = cNode->GetNext() )
1230 {
1231 wxString cNodeName = cNode->GetName();
1232
1233 if( cNodeName == wxT( "ATTROWNER" ) )
1234 {
1235 wxString attOwnerVal = GetXmlAttributeIDString( cNode, 0 );
1236
1237 if( attOwnerVal == wxT( "ALL_ITEMS" ) )
1239 else if( attOwnerVal == wxT( "AREA" ) )
1241 else if( attOwnerVal == wxT( "BOARD" ) )
1243 else if( attOwnerVal == wxT( "COMPONENT" ) )
1245 else if( attOwnerVal == wxT( "CONNECTION" ) )
1247 else if( attOwnerVal == wxT( "COPPER" ) )
1249 else if( attOwnerVal == wxT( "DOCSYMBOL" ) )
1251 else if( attOwnerVal == wxT( "FIGURE" ) )
1253 else if( attOwnerVal == wxT( "NET" ) )
1255 else if( attOwnerVal == wxT( "NETCLASS" ) )
1257 else if( attOwnerVal == wxT( "PART" ) )
1259 else if( attOwnerVal == wxT( "PART_DEFINITION" ) )
1261 else if( attOwnerVal == wxT( "PIN" ) )
1263 else if( attOwnerVal == wxT( "SIGNALREF" ) )
1265 else if( attOwnerVal == wxT( "SYMBOL" ) )
1267 else if( attOwnerVal == wxT( "SYMDEF" ) )
1269 else if( attOwnerVal == wxT( "TEMPLATE" ) )
1271 else if( attOwnerVal == wxT( "TESTPOINT" ) )
1273 else
1275 }
1276 else if( cNodeName == wxT( "ATTRUSAGE" ) )
1277 {
1278 wxString attUsageVal = GetXmlAttributeIDString( cNode, 0 );
1279
1280 if( attUsageVal == wxT( "BOTH" ) )
1282 else if( attUsageVal == wxT( "COMPONENT" ) )
1284 else if( attUsageVal == wxT( "PART_DEFINITION" ) )
1286 else if( attUsageVal == wxT( "PART_LIBRARY" ) )
1288 else if( attUsageVal == wxT( "SYMBOL" ) )
1290 else
1292 }
1293 else if( cNodeName == wxT( "NOTRANSFER" ) )
1294 {
1295 NoTransfer = true;
1296 }
1297 else if( cNodeName == wxT( "COLUMNORDER" ) )
1298 {
1299 COLUMNORDER cOrder;
1300 cOrder.Parse( cNode, aContext );
1301 ColumnOrders.push_back( cOrder );
1302 }
1303 else if( cNodeName == wxT( "COLUMNWIDTH" ) )
1304 {
1305 COLUMNWIDTH cWidth;
1306 cWidth.Parse( cNode, aContext );
1307 ColumnWidths.push_back( cWidth );
1308 }
1309 else if( cNodeName == wxT( "COLUMNINVISIBLE" ) )
1310 {
1311 ColumnInvisible = true;
1312 }
1313 else
1314 {
1316 }
1317 }
1318}
1319
1320
1322{
1323 wxASSERT( aNode->GetName() == wxT( "ATTR" ) );
1324
1326 Value = GetXmlAttributeIDString( aNode, 1 );
1327
1328 XNODE* cNode = aNode->GetChildren();
1329
1330 for( ; cNode; cNode = cNode->GetNext() )
1331 {
1332 if( cNode->GetName() == wxT( "READONLY" ) )
1333 {
1334 ReadOnly = true;
1335 }
1336 else if( cNode->GetName() == wxT( "ATTRLOC" ) )
1337 {
1338 AttributeLocation.Parse( cNode, aContext );
1339 HasLocation = true;
1340 }
1341 else
1342 {
1343 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "ATTR" ) );
1344 }
1345 }
1346}
1347
1348
1350{
1351 wxASSERT( aNode->GetName() == wxT( "TEXTLOC" ) );
1352
1353 wxString attributeStr = GetXmlAttributeIDString( aNode, 0 );
1354 bool attributeIDisSet = false;
1355
1356 if( attributeStr == wxT( "PART_NAME" ) )
1357 {
1359 attributeIDisSet = true;
1360 }
1361 else if( attributeStr == wxT( "COMP_NAME" ) )
1362 {
1364 attributeIDisSet = true;
1365 }
1366 else if( attributeStr == wxT( "COMP_NAME2" ) )
1367 {
1369 attributeIDisSet = true;
1370 }
1371 else if( attributeStr == wxT( "SYMBOL_NAME" ) )
1372 {
1374 attributeIDisSet = true;
1375 }
1376 else if( attributeStr == wxT( "LINK_ORIGIN" ) )
1377 {
1379 attributeIDisSet = true;
1380 }
1381 else if( attributeStr == wxT( "SIGNALNAME_ORIGIN" ) )
1382 {
1384 attributeIDisSet = true;
1385 }
1386 else if( attributeStr == wxT( "ATTRREF" ) )
1387 {
1388 //We will initialise when we parse all child nodes
1389 attributeIDisSet = false;
1390 }
1391 else
1392 {
1393 WARN_UNKNOWN_PARAMETER_IO_ERROR( attributeStr, wxT( "TEXTLOC" ) );
1394 }
1395
1396 TextCodeID = GetXmlAttributeIDString( aNode, 1 );
1397 LayerID = GetXmlAttributeIDString( aNode, 2, false );
1398
1399 //Parse child nodes
1400 XNODE* cNode = aNode->GetChildren();
1401
1402 for( ; cNode; cNode = cNode->GetNext() )
1403 {
1404 wxString cNodeName = cNode->GetName();
1405
1406 if( ParseSubNode( cNode, aContext ) )
1407 {
1408 continue;
1409 }
1410 else if( !attributeIDisSet && cNodeName == wxT( "ATTRREF" ) )
1411 {
1413 attributeIDisSet = true;
1414 }
1415 else if( cNodeName == wxT( "ORIENT" ) )
1416 {
1417 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1418 }
1419 else if( cNodeName == wxT( "MIRROR" ) )
1420 {
1421 Mirror = true;
1422 }
1423 else if( cNodeName == wxT( "FIX" ) )
1424 {
1425 Fixed = true;
1426 }
1427 else if( cNodeName == wxT( "ALIGN" ) )
1428 {
1429 Alignment = ParseAlignment( cNode );
1430 }
1431 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1432 {
1434 }
1435 else
1436 {
1437 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEXTLOC" ) );
1438 }
1439 }
1440
1442 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "TEXTLOC" ) );
1443}
1444
1445
1447{
1448 wxASSERT( aNode->GetName() == wxT( "NETCLASS" ) );
1449
1450 ID = GetXmlAttributeIDString( aNode, 0 );
1451 Name = GetXmlAttributeIDString( aNode, 1 );
1452
1453 XNODE* cNode = aNode->GetChildren();
1454 wxString location = wxString::Format( "NETCLASS -> %s", Name );
1455
1456 for( ; cNode; cNode = cNode->GetNext() )
1457 {
1458 wxString cNodeName = cNode->GetName();
1459
1460 if( cNodeName == wxT( "ATTR" ) )
1461 {
1462 ATTRIBUTE_VALUE attribute_val;
1463 attribute_val.Parse( cNode, aContext );
1464 Attributes.push_back( attribute_val );
1465 }
1466 else
1467 {
1469 }
1470 }
1471}
1472
1473
1475{
1476 wxASSERT( aNode->GetName() == wxT( "SPCCLASSNAME" ) );
1477
1478 ID = GetXmlAttributeIDString( aNode, 0 );
1479 Name = GetXmlAttributeIDString( aNode, 1 );
1480}
1481
1482
1484{
1485 wxString nodeName = aChildNode->GetName();
1486
1487 if( nodeName == wxT( "LINECODE" ) )
1488 {
1489 LINECODE linecode;
1490 linecode.Parse( aChildNode, aContext );
1491 LineCodes.insert( std::make_pair( linecode.ID, linecode ) );
1492 }
1493 else if( nodeName == wxT( "HATCHCODE" ) )
1494 {
1495 HATCHCODE hatchcode;
1496 hatchcode.Parse( aChildNode, aContext );
1497 HatchCodes.insert( std::make_pair( hatchcode.ID, hatchcode ) );
1498 }
1499 else if( nodeName == wxT( "TEXTCODE" ) )
1500 {
1501 TEXTCODE textcode;
1502 textcode.Parse( aChildNode, aContext );
1503 TextCodes.insert( std::make_pair( textcode.ID, textcode ) );
1504 }
1505 else if( nodeName == wxT( "ROUTECODE" ) )
1506 {
1507 ROUTECODE routecode;
1508 routecode.Parse( aChildNode, aContext );
1509 RouteCodes.insert( std::make_pair( routecode.ID, routecode ) );
1510 }
1511 else if( nodeName == wxT( "ATTRNAME" ) )
1512 {
1513 ATTRNAME attrname;
1514 attrname.Parse( aChildNode, aContext );
1515 AttributeNames.insert( std::make_pair( attrname.ID, attrname ) );
1516 }
1517 else if( nodeName == wxT( "NETCLASS" ) )
1518 {
1519 CADSTAR_NETCLASS netclass;
1520 netclass.Parse( aChildNode, aContext );
1521 NetClasses.insert( std::make_pair( netclass.ID, netclass ) );
1522 }
1523 else if( nodeName == wxT( "SPCCLASSNAME" ) )
1524 {
1525 SPCCLASSNAME spcclassname;
1526 spcclassname.Parse( aChildNode, aContext );
1527 SpacingClassNames.insert( std::make_pair( spcclassname.ID, spcclassname ) );
1528 }
1529 else
1530 {
1531 return false;
1532 }
1533
1534 return true;
1535}
1536
1537
1539{
1540 wxASSERT( aNode->GetName() == wxT( "SWAPRULE" ) );
1541
1543 wxString swapRuleStr = GetXmlAttributeIDString( aNode, 0 );
1544
1545 if( swapRuleStr == wxT( "NO_SWAP" ) )
1546 retval = SWAP_RULE::NO_SWAP;
1547 else if( swapRuleStr == wxT( "USE_SWAP_LAYER" ) )
1549 else
1550 WARN_UNKNOWN_PARAMETER_IO_ERROR( swapRuleStr, wxT( "SWAPRULE" ) );
1551
1552 return retval;
1553}
1554
1555
1557{
1558 wxASSERT( aNode->GetName() == wxT( "REUSEBLOCK" ) );
1559
1560 ID = GetXmlAttributeIDString( aNode, 0 );
1561 Name = GetXmlAttributeIDString( aNode, 1 );
1562 FileName = GetXmlAttributeIDString( aNode, 2 );
1563
1564 XNODE* cNode = aNode->GetChildren();
1565
1566 for( ; cNode; cNode = cNode->GetNext() )
1567 {
1568 wxString cNodeName = cNode->GetName();
1569
1570 if( cNodeName == wxT( "MIRROR" ) )
1571 Mirror = true;
1572 else if( cNodeName == wxT( "ORIENT" ) )
1573 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1574 else
1575 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "REUSEBLOCK" ) );
1576 }
1577}
1578
1579
1581{
1582 return ReuseBlockID == wxEmptyString && ItemReference == wxEmptyString;
1583}
1584
1585
1587{
1588 wxASSERT( aNode->GetName() == wxT( "REUSEBLOCKREF" ) );
1589
1592
1593 CheckNoChildNodes( aNode );
1594}
1595
1596
1598{
1599 wxASSERT( aNode->GetName() == wxT( "GROUP" ) );
1600
1601 ID = GetXmlAttributeIDString( aNode, 0 );
1602 Name = GetXmlAttributeIDString( aNode, 1 );
1603
1604 XNODE* cNode = aNode->GetChildren();
1605
1606 for( ; cNode; cNode = cNode->GetNext() )
1607 {
1608 wxString cNodeName = cNode->GetName();
1609
1610 if( cNodeName == wxT( "FIX" ) )
1611 Fixed = true;
1612 else if( cNodeName == wxT( "TRANSFER" ) )
1613 Transfer = true;
1614 else if( cNodeName == wxT( "GROUPREF" ) )
1615 GroupID = GetXmlAttributeIDString( cNode, 0 );
1616 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1617 ReuseBlockRef.Parse( cNode, aContext );
1618 else
1619 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "GROUP" ) );
1620 }
1621}
1622
1623
1625{
1626 wxASSERT( aNode->GetName() == wxT( "FIGURE" ) );
1627
1628 ID = GetXmlAttributeIDString( aNode, 0 );
1629 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1630 LayerID = GetXmlAttributeIDString( aNode, 2 );
1631
1632 XNODE* cNode = aNode->GetChildren();
1633 bool shapeIsInitialised = false; // Stop more than one Shape Object
1634 wxString location = wxString::Format( "Figure %s", ID );
1635
1636 if( !cNode )
1637 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1638
1639 for( ; cNode; cNode = cNode->GetNext() )
1640 {
1641 wxString cNodeName = cNode->GetName();
1642
1643 if( !shapeIsInitialised && Shape.IsShape( cNode ) )
1644 {
1645 Shape.Parse( cNode, aContext );
1646 shapeIsInitialised = true;
1647 }
1648 else if( cNodeName == wxT( "SWAPRULE" ) )
1649 {
1650 SwapRule = ParseSwapRule( cNode );
1651 }
1652 else if( cNodeName == wxT( "FIX" ) )
1653 {
1654 Fixed = true;
1655 }
1656 else if( cNodeName == wxT( "GROUPREF" ) )
1657 {
1658
1659 GroupID = GetXmlAttributeIDString( cNode, 0 );
1660 }
1661 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1662 {
1663 ReuseBlockRef.Parse( cNode, aContext );
1664 }
1665 else if( cNodeName == wxT( "ATTR" ) )
1666 {
1667 ATTRIBUTE_VALUE attr;
1668 attr.Parse( cNode, aContext );
1669 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1670 }
1671 else
1672 {
1674 }
1675 }
1676}
1677
1678
1680{
1681 Parse( aNode, aContext, true );
1682}
1683
1684
1686 bool aParseFields )
1687{
1688 wxASSERT( aNode->GetName() == wxT( "TEXT" ) );
1689
1690 ID = GetXmlAttributeIDString( aNode, 0 );
1691 Text = GetXmlAttributeIDString( aNode, 1 );
1692
1693 if( aParseFields )
1694 Text = ParseTextFields( Text, aContext );
1695
1696 TextCodeID = GetXmlAttributeIDString( aNode, 2 );
1697 LayerID = GetXmlAttributeIDString( aNode, 3 );
1698
1699 XNODE* cNode = aNode->GetChildren();
1700
1701 if( !cNode )
1702 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "TEXT" ) );
1703
1704 for( ; cNode; cNode = cNode->GetNext() )
1705 {
1706 wxString cNodeName = cNode->GetName();
1707
1708 if( cNodeName == wxT( "PT" ) )
1709 Position.Parse( cNode, aContext );
1710 else if( cNodeName == wxT( "ORIENT" ) )
1711 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1712 else if( cNodeName == wxT( "MIRROR" ) )
1713 Mirror = true;
1714 else if( cNodeName == wxT( "FIX" ) )
1715 Fixed = true;
1716 else if( cNodeName == wxT( "SWAPRULE" ) )
1717 SwapRule = ParseSwapRule( cNode );
1718 else if( cNodeName == wxT( "ALIGN" ) )
1719 Alignment = ParseAlignment( cNode );
1720 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1722 else if( cNodeName == wxT( "GROUPREF" ) )
1723 GroupID = GetXmlAttributeIDString( cNode, 0 );
1724 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1725 ReuseBlockRef.Parse( cNode, aContext );
1726 else
1727 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEXT" ) );
1728 }
1729}
1730
1731
1736
1737
1739{
1740 wxASSERT( aNode->GetName() == wxT( "SYMDEF" ) );
1741
1742 ID = GetXmlAttributeIDString( aNode, 0 );
1744 Alternate = GetXmlAttributeIDString( aNode, 2 );
1745}
1746
1747
1749{
1750 wxString cNodeName = aChildNode->GetName();
1751
1752 if( cNodeName == wxT( "PT" ) )
1753 {
1754 Origin.Parse( aChildNode, aContext );
1755 }
1756 else if( cNodeName == wxT( "STUB" ) )
1757 {
1758 Stub = true;
1759 }
1760 else if( cNodeName == wxT( "VERSION" ) )
1761 {
1762 Version = GetXmlAttributeIDLong( aChildNode, 0 );
1763 }
1764 else if( cNodeName == wxT( "FIGURE" ) )
1765 {
1766 FIGURE figure;
1767 figure.Parse( aChildNode, aContext );
1768 Figures.insert( std::make_pair( figure.ID, figure ) );
1769 }
1770 else if( cNodeName == wxT( "TEXT" ) )
1771 {
1772 TEXT txt;
1773 txt.Parse( aChildNode, aContext );
1774 Texts.insert( std::make_pair( txt.ID, txt ) );
1775 }
1776 else if( cNodeName == wxT( "TEXTLOC" ) )
1777 {
1778 TEXT_LOCATION textloc;
1779 textloc.Parse( aChildNode, aContext );
1780 TextLocations.insert( std::make_pair( textloc.AttributeID, textloc ) );
1781 }
1782 else if( cNodeName == wxT( "ATTR" ) )
1783 {
1784 ATTRIBUTE_VALUE attrVal;
1785 attrVal.Parse( aChildNode, aContext );
1786 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1787 }
1788 else
1789 {
1790 return false;
1791 }
1792
1793 return true;
1794}
1795
1796
1798{
1799 wxASSERT( aNode->GetName() == wxT( "GATEDEFINITION" ) );
1800
1801 ID = GetXmlAttributeIDString( aNode, 0 );
1802 Name = GetXmlAttributeIDString( aNode, 1 );
1803 Alternate = GetXmlAttributeIDString( aNode, 2 );
1804 PinCount = GetXmlAttributeIDLong( aNode, 3 );
1805
1806 CheckNoChildNodes( aNode );
1807}
1808
1809
1811{
1812 wxASSERT( aNode->GetName() == wxT( "PINTYPE" ) );
1813
1814 wxString pinTypeStr = GetXmlAttributeIDString( aNode, 0 );
1815
1816 std::map<wxString, CADSTAR_PIN_TYPE> pinTypeMap = {
1817 { wxT( "INPUT" ), CADSTAR_PIN_TYPE::PIN_INPUT },
1818 { wxT( "OUTPUT_OR" ), CADSTAR_PIN_TYPE::OUTPUT_OR },
1819 { wxT( "OUTPUT_NOT_OR" ), CADSTAR_PIN_TYPE::OUTPUT_NOT_OR },
1820 { wxT( "OUTPUT_NOT_NORM_OR" ), CADSTAR_PIN_TYPE::OUTPUT_NOT_NORM_OR },
1821 { wxT( "POWER" ), CADSTAR_PIN_TYPE::POWER },
1822 { wxT( "GROUND" ), CADSTAR_PIN_TYPE::GROUND },
1823 { wxT( "TRISTATE_BIDIR" ), CADSTAR_PIN_TYPE::TRISTATE_BIDIR },
1824 { wxT( "TRISTATE_INPUT" ), CADSTAR_PIN_TYPE::TRISTATE_INPUT },
1825 { wxT( "TRISTATE_DRIVER" ), CADSTAR_PIN_TYPE::TRISTATE_DRIVER } };
1826
1827 if( pinTypeMap.find( pinTypeStr ) == pinTypeMap.end() )
1828 {
1829 WARN_UNKNOWN_PARAMETER_IO_ERROR( pinTypeStr, aNode->GetName() );
1831 }
1832
1833 return pinTypeMap[pinTypeStr];
1834}
1835
1836
1838{
1839 wxASSERT( aNode->GetName() == wxT( "PARTDEFINITIONPIN" ) );
1840
1841 ID = GetXmlAttributeIDLong( aNode, 0 );
1842
1843 XNODE* cNode = aNode->GetChildren();
1844
1845 for( ; cNode; cNode = cNode->GetNext() )
1846 {
1847 wxString cNodeName = cNode->GetName();
1848
1849 if( cNodeName == wxT( "PINNAME" ) )
1850 {
1851 Name = GetXmlAttributeIDString( cNode, 0 );
1852 }
1853 else if( cNodeName == wxT( "PINLABEL" ) )
1854 {
1855 Label = GetXmlAttributeIDString( cNode, 0 );
1856 }
1857 else if( cNodeName == wxT( "PINSIGNAL" ) )
1858 {
1859 Signal = GetXmlAttributeIDString( cNode, 0 );
1860 }
1861 else if( cNodeName == wxT( "PINTERM" ) )
1862 {
1864 TerminalPin = GetXmlAttributeIDLong( cNode, 1 );
1865 }
1866 else if( cNodeName == wxT( "PINTYPE" ) )
1867 {
1868 Type = GetPinType( cNode );
1869 }
1870 else if( cNodeName == wxT( "PINLOAD" ) )
1871 {
1872 Load = GetXmlAttributeIDLong( cNode, 0 );
1873 }
1874 else if( cNodeName == wxT( "PINPOSITION" ) )
1875 {
1877 }
1878 else if( cNodeName == wxT( "PINIDENTIFIER" ) )
1879 {
1880 Identifier = GetXmlAttributeIDString( cNode, 0 );
1881 }
1882 else
1883 {
1884 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1885 }
1886 }
1887}
1888
1889
1891{
1892 wxASSERT( aNode->GetName() == wxT( "PARTPIN" ) );
1893
1894 ID = GetXmlAttributeIDLong( aNode, 0 );
1895
1896 XNODE* cNode = aNode->GetChildren();
1897
1898 for( ; cNode; cNode = cNode->GetNext() )
1899 {
1900 wxString cNodeName = cNode->GetName();
1901
1902 if( cNodeName == wxT( "PINNAME" ) )
1903 Name = GetXmlAttributeIDString( cNode, 0 );
1904 else if( cNodeName == wxT( "PINTYPE" ) )
1905 Type = GetPinType( cNode );
1906 else if( cNodeName == wxT( "PINIDENTIFIER" ) )
1907 Identifier = GetXmlAttributeIDString( cNode, 0 );
1908 else
1909 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1910 }
1911}
1912
1913
1915 PARSER_CONTEXT* aContext )
1916{
1917 wxASSERT( aNode->GetName() == wxT( "PINEQUIVALENCE" ) );
1918
1919 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1920
1921 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1922 {
1923 if( !IsValidAttribute( xmlAttribute ) )
1924 continue;
1925
1926 long pinId;
1927
1928 if( !xmlAttribute->GetValue().ToLong( &pinId ) )
1929 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), aNode->GetName() );
1930
1931 PinIDs.push_back( (PART_DEFINITION_PIN_ID) pinId );
1932 }
1933
1934 CheckNoChildNodes( aNode );
1935}
1936
1937
1939 PARSER_CONTEXT* aContext )
1940{
1941 wxASSERT( aNode->GetName() == wxT( "SWAPGATE" ) );
1942
1943 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1944
1945 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1946 {
1947 if( !IsValidAttribute( xmlAttribute ) )
1948 continue;
1949
1950 long pinId;
1951
1952 if( !xmlAttribute->GetValue().ToLong( &pinId ) )
1953 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), aNode->GetName() );
1954
1955 PinIDs.push_back( (PART_DEFINITION_PIN_ID) pinId );
1956 }
1957
1958 CheckNoChildNodes( aNode );
1959}
1960
1961
1963 PARSER_CONTEXT* aContext )
1964{
1965 wxASSERT( aNode->GetName() == wxT( "SWAPGROUP" ) );
1966
1967 GateName = GetXmlAttributeIDString( aNode, 0 );
1968
1969 XNODE* cNode = aNode->GetChildren();
1970
1971 for( ; cNode; cNode = cNode->GetNext() )
1972 {
1973 wxString cNodeName = cNode->GetName();
1974
1975 if( cNodeName == wxT( "EXTERNAL" ) )
1976 {
1977 External = true;
1978 }
1979 else if( cNodeName == wxT( "SWAPGATE" ) )
1980 {
1981 SWAP_GATE swapGate;
1982 swapGate.Parse( cNode, aContext );
1983 SwapGates.push_back( swapGate );
1984 }
1985 else
1986 {
1987 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1988 }
1989 }
1990}
1991
1992
1994{
1995 wxASSERT( aNode->GetName() == wxT( "PARTDEFINITION" ) );
1996
1997 Name = GetXmlAttributeIDString( aNode, 0 );
1998
1999 XNODE* cNode = aNode->GetChildren();
2000
2001 for( ; cNode; cNode = cNode->GetNext() )
2002 {
2003 wxString cNodeName = cNode->GetName();
2004
2005 if( cNodeName == wxT( "HIDEPINNAMES" ) )
2006 {
2007 HidePinNames = true;
2008 }
2009 else if( cNodeName == wxT( "MAXPIN" ) )
2010 {
2011 MaxPinCount = GetXmlAttributeIDLong( cNode, 0 );
2012 }
2013 else if( cNodeName == wxT( "GATEDEFINITION" ) )
2014 {
2015 GATE gate;
2016 gate.Parse( cNode, aContext );
2017 GateSymbols.insert( std::make_pair( gate.ID, gate ) );
2018 }
2019 else if( cNodeName == wxT( "PARTDEFINITIONPIN" ) )
2020 {
2021 PIN pin;
2022 pin.Parse( cNode, aContext );
2023 Pins.insert( std::make_pair( pin.ID, pin ) );
2024 }
2025 else if( cNodeName == wxT( "ATTR" ) )
2026 {
2027 ATTRIBUTE_VALUE attr;
2028 attr.Parse( cNode, aContext );
2029 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2030 }
2031 else if( cNodeName == wxT( "PINEQUIVALENCE" ) )
2032 {
2033 PIN_EQUIVALENCE pinEq;
2034 pinEq.Parse( cNode, aContext );
2035 PinEquivalences.push_back( pinEq );
2036 }
2037 else if( cNodeName == wxT( "SWAPGROUP" ) )
2038 {
2039 SWAP_GROUP swapGroup;
2040 swapGroup.Parse( cNode, aContext );
2041 SwapGroups.push_back( swapGroup );
2042 }
2043 else
2044 {
2045 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2046 }
2047 }
2048}
2049
2050
2052{
2053 wxASSERT( aNode->GetName() == wxT( "PART" ) );
2054
2055 ID = GetXmlAttributeIDString( aNode, 0 );
2056 Name = GetXmlAttributeIDString( aNode, 1 );
2057
2058 XNODE* cNode = aNode->GetChildren();
2059
2060 for( ; cNode; cNode = cNode->GetNext() )
2061 {
2062 wxString cNodeName = cNode->GetName();
2063
2064 if( cNodeName == wxT( "VERSION" ) )
2065 {
2066 Version = GetXmlAttributeIDLong( cNode, 0 );
2067 }
2068 else if( cNodeName == wxT( "HIDEPINNAMES" ) )
2069 {
2070 HidePinNames = true;
2071 }
2072 else if( cNodeName == wxT( "PARTDEFINITION" ) )
2073 {
2074 Definition.Parse( cNode, aContext );
2075 }
2076 else if( cNodeName == wxT( "PARTPIN" ) )
2077 {
2078 PART_PIN pin;
2079 pin.Parse( cNode, aContext );
2080 PartPins.insert( std::make_pair( pin.ID, pin ) );
2081 }
2082 else if( cNodeName == wxT( "ATTR" ) )
2083 {
2084 ATTRIBUTE_VALUE attr;
2085 attr.Parse( cNode, aContext );
2086 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2087 }
2088 else
2089 {
2090 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2091 }
2092 }
2093}
2094
2095
2097{
2098 wxASSERT( aNode->GetName() == wxT( "PARTS" ) );
2099
2100 XNODE* cNode = aNode->GetChildren();
2101
2102 for( ; cNode; cNode = cNode->GetNext() )
2103 {
2104 wxString cNodeName = cNode->GetName();
2105
2106 if( cNodeName == wxT( "PART" ) )
2107 {
2108 PART part;
2109 part.Parse( cNode, aContext );
2110 PartDefinitions.insert( std::make_pair( part.ID, part ) );
2111 }
2112 else
2113 {
2114 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2115 }
2116
2117 aContext->CheckPointCallback();
2118 }
2119}
2120
2121
2123 PARSER_CONTEXT* aContext )
2124{
2125 wxASSERT( aNode->GetName() == wxT( "JPT" ) );
2126
2127 ID = GetXmlAttributeIDString( aNode, 0 );
2128 LayerID = GetXmlAttributeIDString( aNode, 1 );
2129}
2130
2131
2133 PARSER_CONTEXT* aContext )
2134{
2135 wxString cNodeName = aChildNode->GetName();
2136
2137 if( cNodeName == wxT( "PT" ) )
2138 Location.Parse( aChildNode, aContext );
2139 else if( cNodeName == wxT( "FIX" ) )
2140 Fixed = true;
2141 else if( cNodeName == wxT( "GROUPREF" ) )
2142 GroupID = GetXmlAttributeIDString( aChildNode, 0 );
2143 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2144 ReuseBlockRef.Parse( aChildNode, aContext );
2145 else
2146 return false;
2147
2148 return true;
2149}
2150
2151
2153{
2154 ParseIdentifiers( aNode, aContext );
2155 XNODE* cNode = aNode->GetChildren();
2156
2157 for( ; cNode; cNode = cNode->GetNext() )
2158 {
2159 if( ParseSubNode( cNode, aContext ) )
2160 continue;
2161 else
2162 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2163 }
2164}
2165
2166
2168 PARSER_CONTEXT* aContext )
2169{
2170 wxASSERT( aNode->GetName() == wxT( "CONN" ) );
2171
2172 StartNode = GetXmlAttributeIDString( aNode, 0 );
2173 EndNode = GetXmlAttributeIDString( aNode, 1 );
2175}
2176
2177
2179 PARSER_CONTEXT* aContext )
2180{
2181 wxString cNodeName = aChildNode->GetName();
2182
2183 if( cNodeName == wxT( "FIX" ) )
2184 {
2185 Fixed = true;
2186 }
2187 else if( cNodeName == wxT( "HIDDEN" ) )
2188 {
2189 Hidden = true;
2190 }
2191 else if( cNodeName == wxT( "GROUPREF" ) )
2192 {
2193 GroupID = GetXmlAttributeIDString( aChildNode, 0 );
2194 }
2195 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2196 {
2197 ReuseBlockRef.Parse( aChildNode, aContext );
2198 }
2199 else if( cNodeName == wxT( "ATTR" ) )
2200 {
2201 ATTRIBUTE_VALUE attrVal;
2202 attrVal.Parse( aChildNode, aContext );
2203 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
2204 }
2205 else
2206 {
2207 return false;
2208 }
2209
2210 return true;
2211}
2212
2213
2215{
2216 wxASSERT( aNode->GetName() == wxT( "NET" ) );
2217
2218 ID = GetXmlAttributeIDString( aNode, 0 );
2219}
2220
2221
2223{
2224 wxString cNodeName = aChildNode->GetName();
2225
2226 if( cNodeName == wxT( "NETCODE" ) )
2227 {
2228 RouteCodeID = GetXmlAttributeIDString( aChildNode, 0 );
2229 }
2230 else if( cNodeName == wxT( "SIGNAME" ) )
2231 {
2232 Name = GetXmlAttributeIDString( aChildNode, 0 );
2233 }
2234 else if( cNodeName == wxT( "SIGNUM" ) )
2235 {
2236 SignalNum = GetXmlAttributeIDLong( aChildNode, 0 );
2237 }
2238 else if( cNodeName == wxT( "HIGHLIT" ) )
2239 {
2240 Highlight = true;
2241 }
2242 else if( cNodeName == wxT( "JPT" ) )
2243 {
2244 JUNCTION jpt;
2245 jpt.Parse( aChildNode, aContext );
2246 Junctions.insert( std::make_pair( jpt.ID, jpt ) );
2247 }
2248 else if( cNodeName == wxT( "NETCLASSREF" ) )
2249 {
2250 NetClassID = GetXmlAttributeIDString( aChildNode, 0 );
2251 }
2252 else if( cNodeName == wxT( "SPACINGCLASS" ) )
2253 {
2254 SpacingClassID = GetXmlAttributeIDString( aChildNode, 0 );
2255 }
2256 else if( cNodeName == wxT( "ATTR" ) )
2257 {
2258 ATTRIBUTE_VALUE attrVal;
2259 attrVal.Parse( aChildNode, aContext );
2260 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
2261 }
2262 else
2263 {
2264 return false;
2265 }
2266
2267 return true;
2268}
2269
2270
2272{
2273 wxASSERT( aNode->GetName() == wxT( "DOCSYMBOL" ) );
2274
2275 ID = GetXmlAttributeIDString( aNode, 0 );
2276 SymdefID = GetXmlAttributeIDString( aNode, 1 );
2277 LayerID = GetXmlAttributeIDString( aNode, 2 );
2278
2279 XNODE* cNode = aNode->GetChildren();
2280 bool originParsed = false;
2281
2282 for( ; cNode; cNode = cNode->GetNext() )
2283 {
2284 wxString cNodeName = cNode->GetName();
2285
2286 if( !originParsed && cNodeName == wxT( "PT" ) )
2287 {
2288 Origin.Parse( cNode, aContext );
2289 originParsed = true;
2290 }
2291 else if( cNodeName == wxT( "GROUPREF" ) )
2292 {
2293 GroupID = GetXmlAttributeIDString( cNode, 0 );
2294 }
2295 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2296 {
2297 ReuseBlockRef.Parse( cNode, aContext );
2298 }
2299 else if( cNodeName == wxT( "FIX" ) )
2300 {
2301 Fixed = true;
2302 }
2303 else if( cNodeName == wxT( "MIRROR" ) )
2304 {
2305 Mirror = true;
2306 }
2307 else if( cNodeName == wxT( "READABILITY" ) )
2308 {
2309 Readability = ParseReadability( cNode );
2310 }
2311 else if( cNodeName == wxT( "ORIENT" ) )
2312 {
2313 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
2314 }
2315 else if( cNodeName == wxT( "ATTR" ) )
2316 {
2317 ATTRIBUTE_VALUE attr;
2318 attr.Parse( cNode, aContext );
2319 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2320 }
2321 else if( cNodeName == wxT( "SCALE" ) )
2322 {
2325 }
2326 else
2327 {
2328 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2329 }
2330 }
2331
2332 if( !originParsed )
2333 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
2334}
2335
2336
2338{
2339 wxASSERT( aNode->GetName() == wxT( "DFLTSETTINGS" ) );
2340
2341 Color = GetXmlAttributeIDString( aNode, 0 );
2342
2343 XNODE* cNode = aNode->GetChildren();
2344
2345 for( ; cNode; cNode = cNode->GetNext() )
2346 {
2347 wxString cNodeName = cNode->GetName();
2348
2349 if( cNodeName == wxT( "INVISIBLE" ) )
2350 {
2351 IsVisible = false;
2352 }
2353 else
2354 {
2355 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2356 }
2357 }
2358}
2359
2360
2362{
2363 wxASSERT( aNode->GetName() == wxT( "ATTRCOL" ) );
2364
2366 Color = GetXmlAttributeIDString( aNode, 1 );
2367
2368 XNODE* cNode = aNode->GetChildren();
2369
2370 for( ; cNode; cNode = cNode->GetNext() )
2371 {
2372 wxString cNodeName = cNode->GetName();
2373
2374 if( cNodeName == wxT( "INVISIBLE" ) )
2375 {
2376 IsVisible = false;
2377 }
2378 else if( cNodeName == wxT( "NOTPICKABLE" ) )
2379 {
2380 IsPickable = false;
2381 }
2382 else
2383 {
2384 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2385 }
2386 }
2387}
2388
2389
2391{
2392 wxASSERT( aNode->GetName() == wxT( "ATTRCOLORS" ) );
2393
2394 XNODE* cNode = aNode->GetChildren();
2395
2396 for( ; cNode; cNode = cNode->GetNext() )
2397 {
2398 wxString cNodeName = cNode->GetName();
2399
2400 if( cNodeName == wxT( "DFLTSETTINGS" ) )
2401 {
2402 DefaultSettings.Parse( cNode, aContext );
2403 }
2404 else if( cNodeName == wxT( "ATTRCOL" ) )
2405 {
2406 ATTRCOL attrcol;
2407 attrcol.Parse( cNode, aContext );
2408 AttributeColors.insert( { attrcol.AttributeID, attrcol } );
2409 }
2410 else if( cNodeName == wxT( "INVISIBLE" ) )
2411 {
2412 IsVisible = false;
2413 }
2414 else
2415 {
2416 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2417 }
2418 }
2419}
2420
2421
2423{
2424 wxASSERT( aNode->GetName() == wxT( "PARTNAMECOL" ) );
2425
2426 Color = GetXmlAttributeIDString( aNode, 0 );
2427
2428 XNODE* cNode = aNode->GetChildren();
2429
2430 for( ; cNode; cNode = cNode->GetNext() )
2431 {
2432 wxString cNodeName = cNode->GetName();
2433
2434 if( cNodeName == wxT( "INVISIBLE" ) )
2435 {
2436 IsVisible = false;
2437 }
2438 else if( cNodeName == wxT( "NOTPICKABLE" ) )
2439 {
2440 IsPickable = false;
2441 }
2442 else
2443 {
2444 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2445 }
2446 }
2447}
2448
2449
2451{
2452 static const wxString c_numAttributes = wxT( "numAttributes" );
2453
2454 wxString result;
2455 long numAttributes = 0;
2456
2457 if( aNode->GetAttribute( c_numAttributes, &result ) )
2458 {
2459 numAttributes = wxAtol( result );
2460 aNode->DeleteAttribute( c_numAttributes );
2461 ++numAttributes;
2462 }
2463
2464#if wxUSE_UNICODE_WCHAR
2465 std::wstring numAttrStr = std::to_wstring( numAttributes );
2466#else
2467 std::string numAttrStr = std::to_string( numAttributes );
2468#endif
2469
2470 aNode->AddAttribute( c_numAttributes, numAttrStr );
2471
2472 wxString paramName = wxT( "attr" );
2473 paramName << numAttrStr;
2474
2475 aNode->AddAttribute( paramName, aValue );
2476}
2477
2478
2480 const wxString& aFileTypeIdentifier,
2481 PROGRESS_REPORTER* aProgressReporter )
2482{
2483 KEYWORD emptyKeywords[1] = {};
2484 XNODE* rootNode = nullptr;
2485 XNODE* cNode = nullptr;
2486 XNODE* iNode = nullptr;
2487 int tok;
2488 bool cadstarFileCheckDone = false;
2489 wxString str;
2490 wxCSConv win1252( wxT( "windows-1252" ) );
2491 wxMBConv* conv = &win1252; // Initial testing suggests file encoding to be Windows-1252
2492 // More samples required.
2493
2494 // Open the file and get the file size
2495 FILE* fp = wxFopen( aFileName, wxT( "rt" ) );
2496
2497 if( !fp )
2498 THROW_IO_ERROR( wxString::Format( _( "Cannot open file '%s'" ), aFileName ) );
2499
2500 fseek( fp, 0L, SEEK_END );
2501 long fileSize = ftell( fp );
2502 rewind( fp );
2503
2504 DSNLEXER lexer( emptyKeywords, 0, nullptr, fp, aFileName );
2505
2506 auto currentProgress = [&]() -> double
2507 {
2508 return static_cast<double>( ftell( fp ) ) / fileSize;
2509 };
2510
2511 double previousReportedProgress = -1.0;
2512
2513 while( ( tok = lexer.NextTok() ) != DSN_EOF )
2514 {
2515 if( aProgressReporter && ( currentProgress() - previousReportedProgress ) > 0.01 )
2516 {
2517 if( !aProgressReporter->KeepRefreshing() )
2518 {
2519 delete rootNode;
2520
2521 THROW_IO_ERROR( _( "File import canceled by user." ) );
2522 }
2523
2524 aProgressReporter->SetCurrentProgress( currentProgress() );
2525 previousReportedProgress = currentProgress();
2526 }
2527
2528 if( tok == DSN_RIGHT )
2529 {
2530 cNode = iNode;
2531 if( cNode )
2532 {
2533 iNode = cNode->GetParent();
2534 }
2535 else
2536 {
2537 //too many closing brackets
2538 delete rootNode;
2539 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2540 }
2541 }
2542 else if( tok == DSN_LEFT )
2543 {
2544 tok = lexer.NextTok();
2545 str = wxString( lexer.CurText(), *conv );
2546 cNode = new XNODE( wxXML_ELEMENT_NODE, str );
2547
2548 if( !rootNode )
2549 rootNode = cNode;
2550
2551 if( iNode )
2552 {
2553 //we will add it as attribute as well as child node
2554 InsertAttributeAtEnd( iNode, str );
2555 iNode->AddChild( cNode );
2556 }
2557 else if( !cadstarFileCheckDone )
2558 {
2559 if( cNode->GetName() != aFileTypeIdentifier )
2560 {
2561 delete rootNode;
2562 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2563 }
2564
2565 cadstarFileCheckDone = true;
2566 }
2567
2568 iNode = cNode;
2569 }
2570 else if( iNode )
2571 {
2572 str = wxString( lexer.CurText(), *conv );
2573 //Insert even if string is empty
2574 InsertAttributeAtEnd( iNode, str );
2575 }
2576 else
2577 {
2578 //not enough closing brackets
2579 delete rootNode;
2580 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2581 }
2582 }
2583
2584 // Not enough closing brackets
2585 if( iNode != nullptr )
2586 {
2587 delete rootNode;
2588 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2589 }
2590
2591 // Throw if no data was parsed
2592 if( rootNode )
2593 {
2594 return rootNode;
2595 }
2596 else
2597 {
2598 delete rootNode;
2599 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2600 }
2601
2602 return nullptr;
2603}
2604
2605
2606bool CADSTAR_ARCHIVE_PARSER::IsValidAttribute( wxXmlAttribute* aAttribute )
2607{
2608 return aAttribute->GetName() != wxT( "numAttributes" );
2609}
2610
2611
2613 bool aIsRequired )
2614{
2615#if wxUSE_UNICODE_WCHAR
2616 std::wstring idStr = std::to_wstring( aID );
2617#else
2618 std::string idStr = std::to_string( aID );
2619#endif
2620
2621 wxString attrName = wxS( "attr" );
2622 attrName << idStr;
2623
2624 wxString retVal;
2625
2626 if( !aNode->GetAttribute( attrName, &retVal ) )
2627 {
2628 if( aIsRequired )
2629 THROW_MISSING_PARAMETER_IO_ERROR( std::to_string( aID ), aNode->GetName() );
2630 else
2631 return wxEmptyString;
2632 }
2633
2634 return retVal;
2635}
2636
2637
2639 bool aIsRequired )
2640{
2641 long retVal;
2642 bool success = GetXmlAttributeIDString( aNode, aID, aIsRequired ).ToLong( &retVal );
2643
2644 if( !success )
2645 {
2646 if( aIsRequired )
2647 THROW_PARSING_IO_ERROR( std::to_string( aID ), aNode->GetName() );
2648 else
2649 return UNDEFINED_VALUE;
2650 }
2651
2652 return retVal;
2653}
2654
2655
2657{
2658 if( aNode && aNode->GetChildren() )
2659 WARN_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
2660}
2661
2662
2664{
2665 if( aNode && aNode->GetNext() )
2666 WARN_UNKNOWN_NODE_IO_ERROR( aNode->GetNext()->GetName(), aNode->GetParent()->GetName() );
2667}
2668
2669
2671 EVALUE& aValueToParse )
2672{
2673 if( aNode->GetChildren()->GetName() == wxT( "E" ) )
2674 aValueToParse.Parse( aNode->GetChildren(), aContext );
2675 else
2676 WARN_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
2677}
2678
2679
2680std::vector<CADSTAR_ARCHIVE_PARSER::POINT> CADSTAR_ARCHIVE_PARSER::ParseAllChildPoints(
2681 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes, int aExpectedNumPoints )
2682{
2683 std::vector<POINT> retVal;
2684
2685 XNODE* cNode = aNode->GetChildren();
2686
2687 for( ; cNode; cNode = cNode->GetNext() )
2688 {
2689 if( cNode->GetName() == wxT( "PT" ) )
2690 {
2691 POINT pt;
2692
2693 try
2694 {
2695 pt.Parse( cNode, aContext );
2696 }
2697 catch( const IO_ERROR& e )
2698 {
2699 reThrowWithParentContext( e, cNode, aNode );
2700 }
2701
2702 retVal.push_back( pt );
2703 }
2704 else if( aTestAllChildNodes )
2705 {
2706 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2707 }
2708 }
2709
2710 if( aExpectedNumPoints != UNDEFINED_VALUE
2711 && retVal.size() != static_cast<size_t>( aExpectedNumPoints ) )
2712 {
2713 THROW_IO_ERROR( wxString::Format(
2714 _( "Unexpected number of points in '%s'. Found %d but expected %d." ),
2715 aNode->GetName(), retVal.size(), aExpectedNumPoints ) );
2716 }
2717
2718 return retVal;
2719}
2720
2721
2722std::vector<CADSTAR_ARCHIVE_PARSER::VERTEX> CADSTAR_ARCHIVE_PARSER::ParseAllChildVertices(
2723 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes )
2724{
2725 std::vector<VERTEX> retVal;
2726
2727 XNODE* cNode = aNode->GetChildren();
2728
2729 for( ; cNode; cNode = cNode->GetNext() )
2730 {
2731 if( VERTEX::IsVertex( cNode ) )
2732 {
2733 VERTEX vertex;
2734
2735 try
2736 {
2737 vertex.Parse( cNode, aContext );
2738 }
2739 catch( const IO_ERROR& e )
2740 {
2741 reThrowWithParentContext( e, cNode, aNode );
2742 }
2743
2744 retVal.push_back( vertex );
2745 }
2746 else if( aTestAllChildNodes )
2747 {
2748 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2749 }
2750 }
2751
2752 return retVal;
2753}
2754
2755
2756std::vector<CADSTAR_ARCHIVE_PARSER::CUTOUT> CADSTAR_ARCHIVE_PARSER::ParseAllChildCutouts(
2757 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes )
2758{
2759 std::vector<CUTOUT> retVal;
2760
2761 XNODE* cNode = aNode->GetChildren();
2762
2763 for( ; cNode; cNode = cNode->GetNext() )
2764 {
2765 if( cNode->GetName() == wxT( "CUTOUT" ) )
2766 {
2767 CUTOUT cutout;
2768
2769 try
2770 {
2771 cutout.Parse( cNode, aContext );
2772 }
2773 catch( const IO_ERROR& e )
2774 {
2775 reThrowWithParentContext( e, cNode, aNode );
2776 }
2777
2778 retVal.push_back( cutout );
2779 }
2780 else if( aTestAllChildNodes )
2781 {
2782 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2783 }
2784 }
2785
2786 return retVal;
2787}
2788
2789
2791{
2792 XNODE* childNodes = aNode->GetChildren();
2793 long retval = 0;
2794
2795 for( ; childNodes; childNodes = childNodes->GetNext() )
2796 retval++;
2797
2798 return retval;
2799}
2800
2801
2803 XNODE* aRootNode, std::vector<wxString> aSubNodeChildrenToCount )
2804{
2805 XNODE* level1Node = aRootNode->GetChildren();
2806 long retval = 0;
2807
2808 for( ; level1Node; level1Node = level1Node->GetNext() )
2809 {
2810 for( wxString childNodeName : aSubNodeChildrenToCount )
2811 {
2812 if( level1Node->GetName() == childNodeName )
2813 retval += GetNumberOfChildNodes( level1Node );
2814 }
2815
2816 retval++;
2817 }
2818
2819 return retval;
2820}
2821
2822
2823wxString CADSTAR_ARCHIVE_PARSER::HandleTextOverbar( wxString aCadstarString )
2824{
2825 wxString escapedText = aCadstarString;
2826
2827 escapedText.Replace( wxT( "'" ), wxT( "~" ) );
2828
2829 return ConvertToNewOverbarNotation( escapedText );
2830}
2831
2832
2834{
2835 if( !aKiCadTextItem->GetText().IsEmpty() )
2836 {
2837 VECTOR2I positionOffset( 0, aKiCadTextItem->GetInterline( nullptr ) );
2838 RotatePoint( positionOffset, aKiCadTextItem->GetTextAngle() );
2839
2840 //Count num of additional lines
2841 wxString text = aKiCadTextItem->GetText();
2842 int numExtraLines = text.Replace( "\n", "\n" );
2843 numExtraLines -= text.at( text.size() - 1 ) == '\n'; // Ignore new line character at end
2844 positionOffset.x *= numExtraLines;
2845 positionOffset.y *= numExtraLines;
2846
2847 aKiCadTextItem->Offset( positionOffset );
2848 }
2849}
2850
2851
2852wxString CADSTAR_ARCHIVE_PARSER::generateLibName( const wxString& aRefName,
2853 const wxString& aAlternateName )
2854{
2855 if( aAlternateName.IsEmpty() )
2856 return EscapeString( aRefName, CTX_LIBID );
2857 else
2858 return EscapeString( aRefName + wxT( " (" ) + aAlternateName + wxT( ")" ), CTX_LIBID );
2859}
2860
2861
2863{
2864 if( m_progressReporter )
2865 {
2866 m_progressReporter->AdvanceProgress();
2867
2868 if( !m_progressReporter->KeepRefreshing() )
2869 THROW_IO_ERROR( _( "File import canceled by user." ) );
2870 }
2871}
2872
CADSTAR_PIN_POSITION
Positioning of pin names can be in one of four quadrants.
CADSTAR_PIN_TYPE
file: cadstar_archive_objects.h Contains common object definitions
@ OUTPUT_NOT_OR
Output pin not OR tieable.
@ TRISTATE_DRIVER
Tristate output pin.
@ OUTPUT_OR
Output pin OR tieable.
@ UNCOMMITTED
Uncommitted pin (default)
@ TRISTATE_INPUT
Tristate input pin.
@ TRISTATE_BIDIR
Tristate bi-directional driver pin.
@ OUTPUT_NOT_NORM_OR
Output pin not normally OR tieable.
static void reThrowWithParentContext(const IO_ERROR &aError, XNODE *aChildNode, XNODE *aParentNode)
Helper functions and common defines between schematic and PCB Archive files.
#define SYMBOL_NAME_ATTRID
Symbol Name attribute ID - used for placement of designators on the schematic.
#define SIGNALNAME_ORIGIN_ATTRID
#define WARN_UNKNOWN_NODE_IO_ERROR(nodename, location)
#define THROW_MISSING_NODE_IO_ERROR(nodename, location)
#define THROW_UNKNOWN_NODE_IO_ERROR(nodename, location)
#define LINK_ORIGIN_ATTRID
#define COMPONENT_NAME_2_ATTRID
Component Name 2 Attribute ID - typically used for indicating the placement of designators in placeme...
#define THROW_UNKNOWN_PARAMETER_IO_ERROR(param, location)
#define COMPONENT_NAME_ATTRID
Component Name Attribute ID - typically used for placement of designators on silk screen.
#define PART_NAME_ATTRID
#define WARN_UNKNOWN_PARAMETER_IO_ERROR(param, location)
#define THROW_MISSING_PARAMETER_IO_ERROR(param, location)
#define THROW_PARSING_IO_ERROR(param, location)
READABILITY
Sets the readability direction of text.
@ BOTTOM_TO_TOP
When text is vertical, show it rotated 90 degrees anticlockwise.
@ TOP_TO_BOTTOM
When text is vertical, show it rotated 90 degrees clockwise.
@ STEPGRID
Param1 = X Step, Param2 = Y Step. A standard x,y grid.
@ FRACTIONALGRID
Param1 = Units, Param2 = Divisor.
SWAP_RULE
Corresponds to "Display when" Item property.
static UNITS ParseUnits(XNODE *aNode)
static ALIGNMENT ParseAlignment(XNODE *aNode)
static const std::map< TEXT_FIELD_NAME, wxString > CADSTAR_TO_KICAD_FIELDS
Map between CADSTAR fields and KiCad text variables.
TEXT_FIELD_NAME
These are special fields in text objects enclosed between the tokens '<@' and '>' such as <@[FIELD_NA...
static SWAP_RULE ParseSwapRule(XNODE *aNode)
ALIGNMENT
From CADSTAR Help: "Text Alignment enables you to define the position of an alignment origin for all ...
@ NO_ALIGNMENT
NO_ALIGNMENT has different meaning depending on the object type.
static wxString generateLibName(const wxString &aRefName, const wxString &aAlternateName)
static void CheckNoNextNodes(XNODE *aNode)
static std::vector< CUTOUT > ParseAllChildCutouts(XNODE *aNode, PARSER_CONTEXT *aContext, bool aTestAllChildNodes=false)
If no children are present, it just returns an empty vector (without throwing an exception).
static XNODE * LoadArchiveFile(const wxString &aFileName, const wxString &aFileTypeIdentifier, PROGRESS_REPORTER *aProgressReporter=nullptr)
Reads a CADSTAR Archive file (S-parameter format).
static JUSTIFICATION ParseJustification(XNODE *aNode)
static wxString ParseTextFields(const wxString &aTextString, PARSER_CONTEXT *aParserContext)
Replaces CADSTAR fields for the equivalent in KiCad and stores the field values in aParserContext.
@ PART_DEFINITION
From CADSTAR Help: Assigned to Parts library Definitions and displayed by the Library searcher.
@ BOTH
From CADSTAR Help: Assigned to both Schematic symbols and PCB components, and displayed on Schematic ...
@ COMPONENT
From CADSTAR Help: Assigned to PCB components and displayed on PCB designs.
@ SYMBOL
From CADSTAR Help: Assigned to Schematic Symbols and displayed on Schematic Designs.
@ PART_LIBRARY
From CADSTAR Help: Only used by non-Cadstar applications.
static std::vector< VERTEX > ParseAllChildVertices(XNODE *aNode, PARSER_CONTEXT *aContext, bool aTestAllChildNodes=false)
If no children are present, it just returns an empty vector (without throwing an exception).
static void FixTextPositionNoAlignment(EDA_TEXT *aKiCadTextItem)
Correct the position of a text element that had NO_ALIGNMENT in CADSTAR.
static ANGUNITS ParseAngunits(XNODE *aNode)
long PART_DEFINITION_PIN_ID
Pin identifier in the part definition.
@ OPENSHAPE
Unfilled open shape. Cannot have cutouts.
@ SOLID
Filled closed shape (solid fill).
@ HATCHED
Filled closed shape (hatch fill).
static const double TXT_HEIGHT_RATIO
CADSTAR fonts are drawn on a 24x24 integer matrix, where the each axis goes from 0 to 24.
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 std::vector< POINT > ParseAllChildPoints(XNODE *aNode, PARSER_CONTEXT *aContext, bool aTestAllChildNodes=false, int aExpectedNumPoints=UNDEFINED_VALUE)
If no children are present, it just returns an empty vector (without throwing an exception).
@ DESIGN
Inherits from design units (assumed Assignments->Technology->Units)
static wxString HandleTextOverbar(wxString aCadstarString)
Convert a string with CADSTAR overbar characters to equivalent in KiCad.
static void CheckNoChildNodes(XNODE *aNode)
static long GetXmlAttributeIDLong(XNODE *aNode, unsigned int aID, bool aIsRequired=true)
JUSTIFICATION
From CADSTAR Help: "Multi Line Text can also be justified as Left, Centre or Right.
static void ParseChildEValue(XNODE *aNode, PARSER_CONTEXT *aContext, EVALUE &aValueToParse)
static long GetNumberOfStepsForReporting(XNODE *aRootNode, std::vector< wxString > aSubNodeChildrenToCount)
PROGRESS_REPORTER * m_progressReporter
static long GetNumberOfChildNodes(XNODE *aNode)
static void InsertAttributeAtEnd(XNODE *aNode, wxString aValue)
@ PART_DEFINITION
Only library Attributes.
Implement a lexical analyzer for the SPECCTRA DSN file format.
Definition dsnlexer.h:75
const char * CurText() const
Return a pointer to the current token's text.
Definition dsnlexer.h:411
int NextTok()
Return the next token found in the input file or DSN_EOF when reaching the end of file.
Definition dsnlexer.cpp:537
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:89
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:110
virtual void Offset(const VECTOR2I &aOffset)
Definition eda_text.cpp:595
virtual EDA_ANGLE GetTextAngle() const
Definition eda_text.h:168
int GetInterline(const RENDER_SETTINGS *aSettings) const
Return the distance between two lines of text.
Definition eda_text.cpp:767
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString Problem() const
what was the problem?
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
SHAPE_ARC & ConstructFromStartEndCenter(const VECTOR2I &aStart, const VECTOR2I &aEnd, const VECTOR2I &aCenter, bool aClockwise=false, double aWidth=0)
Constructs this arc from the given start, end and center.
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
virtual const VECTOR2I GetPoint(int aIndex) const override
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
int PointCount() const
Return the number of points (vertices) in this line chain.
void Append(int aX, int aY, bool aAllowDuplication=false)
Append a new point at the end of the line chain.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new outline to the set and returns its index.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Adds a new hole to the given outline (default: last) and returns its index.
An extension of wxXmlNode that can format its contents as KiCad-style s-expressions.
Definition xnode.h:67
XNODE * GetParent() const
Definition xnode.h:107
XNODE * GetChildren() const
Definition xnode.h:97
XNODE * GetNext() const
Definition xnode.h:102
void AddAttribute(const wxString &aName, const wxString &aValue) override
Definition xnode.cpp:88
@ DSN_LEFT
Definition dsnlexer.h:63
@ DSN_RIGHT
Definition dsnlexer.h:62
@ DSN_EOF
Definition dsnlexer.h:65
#define _(s)
#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 ...
Definition macros.h:79
static wxString nodeName(const wxString &aSymbolPin)
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString EscapeString(const wxString &aSource, ESCAPE_CONTEXT aContext)
The Escape/Unescape routines use HTML-entity-reference-style encoding to handle characters which are:...
@ CTX_LIBID
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< ATTRIBUTE_ID, ATTRCOL > AttributeColors
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
virtual void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
JUSTIFICATION Justification
Note: Justification has no effect on single lines of text.
ALIGNMENT Alignment
In CADSTAR The default alignment for a TEXT object (when "(No Alignment()" is selected) Bottom Left o...
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool HasLocation
Flag to know if this ATTRIBUTE_VALUE has a location i.e.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
NOTE from CADSTAR help: To convert a Part Definition Attribute into a hyperlink, prefix the attribute...
std::vector< COLUMNWIDTH > ColumnWidths
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool NoTransfer
True="All Design Types", False="Current Design Type" "All Design Types" Description from CADSTAR Help...
std::vector< COLUMNORDER > ColumnOrders
wxString Name
Parenthesis aren't permitted in user attributes in CADSTAR.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< SPACING_CLASS_ID, SPCCLASSNAME > SpacingClassNames
std::map< LINECODE_ID, LINECODE > LineCodes
std::map< NETCLASS_ID, CADSTAR_NETCLASS > NetClasses
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
std::map< HATCHCODE_ID, HATCHCODE > HatchCodes
std::map< ATTRIBUTE_ID, ATTRNAME > AttributeNames
std::map< ROUTECODE_ID, ROUTECODE > RouteCodes
std::map< TEXTCODE_ID, TEXTCODE > TextCodes
Represent a cutout in a closed shape (e.g.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
long ScaleRatioNumerator
Documentation symbols can be arbitrarily scaled when added to a design.
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
long ScaleRatioDenominator
Documentation symbols can be arbitrarily scaled when added to a design.
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
GROUP_ID GroupID
If not empty, this component is part of a group.
LAYER_ID LayerID
Move all objects in the Symdef to this layer.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
SYMDEF_ID SymdefID
Normally documentation symbols only have TEXT, FIGURE and TEXT_LOCATION objects which are all drawn o...
Represent a floating value in E notation.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
If not empty, this FIGURE is part of a group.
SWAP_RULE SwapRule
Only applicable to Figures in Components.
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
long Modifier2
It seems this is always 0 regardless of settings.
bool KerningPairs
From CADSTAR Help: "Kerning Pairs is for causing the system to automatically reduce the spacing...
long Modifier1
It seems this is related to weight. 400=Normal, 700=Bold.
long Version
Archive version number (e.g.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
long SomeInt
It is unclear what this parameter is used for.
GRID ScreenGrid
From CADSTAR Help: "There is one Screen Grid, which is visible as dots on the screen.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::vector< GRID > UserGrids
List of predefined grids created by the user.
long Param1
Either Units or X step, depending on Type (see GRID_TYPE for more details)
long Param2
Either Divisor or Y step, depending on Type (see GRID_TYPE for more details)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
GROUP_ID GroupID
If not empty, this GROUP is part of another GROUP.
bool Transfer
If true, the group is transferred to PCB.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
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
It is possible to add attributes solely to a particular connection.
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
GROUP_ID GroupID
If not empty, this connection is part of a group.
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
GROUP_ID GroupID
If not empty, this JUNCTION is part of a group.
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
virtual void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
NETELEMENT_ID ID
First character is "J".
ROUTECODE_ID RouteCodeID
"NETCODE" subnode
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
wxString Name
This is undefined (wxEmptyString) if the net is unnamed.
std::map< NETELEMENT_ID, JUNCTION > Junctions
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
NETCLASS_ID NetClassID
The net might not have a net class, in which case it will be wxEmptyString ("NETCLASSREF" subnode)
SPACING_CLASS_ID SpacingClassID
The net might not have a spacing class, in which case it will be wxEmptyString ("SPACINGCLASS" subnod...
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
long SignalNum
This is undefined if the net has been given a name.
std::map< TEXT_FIELD_NAME, wxString > TextFieldToValuesMap
Values for the text field elements used in the CADSTAR design extracted from the text element instanc...
std::map< wxString, wxString > FilenamesToTextMap
CADSTAR doesn't have user defined text fields but does allow loading text from a file.
std::map< wxString, wxString > TextToHyperlinksMap
KiCad doesn't support hyperlinks but we use this map to display warning messages after import.
std::set< TEXT_FIELD_NAME > InconsistentTextFields
Text fields need to be updated in CADSTAR and it is possible that they are not consistent across text...
std::function< void()> CheckPointCallback
Callback function to report progress.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< PART_ID, PART > PartDefinitions
long PinCount
Number of pins (terminals) in the symbol.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
wxString Alternate
Symbol alternate name in the symbol library.
wxString Name
Symbol name in the symbol library.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::vector< PART_DEFINITION_PIN_ID > PinIDs
All the pins in this vector are equivalent and can be swapped with each other.
wxString Label
This Can be empty (subnode= "PINLABEL") From CADSTAR Help: "Pin Labels are an optional replacement fo...
long Load
The electrical current expected on the pin (It is unclear what the units are, but only accepted value...
CADSTAR_PIN_POSITION Position
The pin names will use these positions when the symbol is added to a design subnode="PINPOSITION".
TERMINAL_ID TerminalPin
(subnode="PINTERM", param1)
wxString Identifier
This should match a pad identifier in the component footprint subnode="PINIDENTIFIER".
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
wxString Signal
Usually for Power/Ground pins, (subnode="PINSIGNAL")
< "SWAPGATE" Node name (represents an "Element")
std::vector< PART_DEFINITION_PIN_ID > PinIDs
The pins in this vector describe a "gate".
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::vector< SWAP_GATE > SwapGates
Each of the elements in this vector can be swapped with each other - i.e.
bool External
Determines if this swap group is external (and internal) or internal only.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool HidePinNames
Specifies whether to display the pin names/identifier in the schematic symbol or not.
wxString Name
This name can be different to the PART name.
long MaxPinCount
Optional parameter which is used for specifying the number of electrical pins on the PCB component sy...
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
Some attributes are defined within the part definition, whilst others are defined in the part.
std::map< PART_DEFINITION_PIN_ID, PIN > Pins
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
static CADSTAR_PIN_TYPE GetPinType(XNODE *aNode)
std::map< PART_PIN_ID, PART_PIN > PartPins
It is unclear why there are two "Pin" structures in CPA files... PART_PIN seems to be a reduced versi...
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
Some attributes are defined within the part definition, whilst others are defined in the part itself.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool HidePinNames
This seems to be a duplicate of DEFINITION::HidePinNames Possibly only used in older file formats?
Represent a point in x,y coordinates.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
wxString ItemReference
For Components, this references the designator in the reuse file.
bool IsEmpty()
Determines if this is empty (i.e. no design reuse associated)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
wxString FileName
Filename of the reuse block (usually a .pcb). Used for reloading.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::vector< ROUTEREASSIGN > RouteReassigns
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
UNITS Units
Units to display for linear dimensions.
long PinNoAngle
The angle at which the Pin ID is positioned relative to a terminal.
long InterlineGap
For CADSTAR font only, distance between lines of text, expressed as a percentage of the text height (...
long BarlineGap
For CADSTAR font only, distance between top bar and character, expressed as a percentage of the text ...
virtual void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool AllowBarredText
Specifies if barring is allowed in the design.
long AngularPrecision
Number of decimal points to display for angular dimensions.
long UnitDisplPrecision
Number of decimal points to display for linear dimensions.
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
long PinNoOffset
The distance, of a Pin Name/Identifier from its parent terminal.
SHAPE_POLY_SET ConvertToPolySet(const std::function< VECTOR2I(const VECTOR2I &)> aCadstarToKicadPointCallback, int aAccuracy) const
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
wxString HatchCodeID
Only Applicable for HATCHED Type.
std::vector< CUTOUT > Cutouts
Not Applicable to OPENSHAPE Type.
SHAPE_LINE_CHAIN OutlineAsChain(const std::function< VECTOR2I(const VECTOR2I &)> aCadstarToKicadPointCallback, int aAccuracy) const
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
std::map< FIGURE_ID, FIGURE > Figures
std::map< ATTRIBUTE_ID, TEXT_LOCATION > TextLocations
This contains location of any attributes, including designator position.
POINT Origin
Origin of the component (this is used as the reference point when placing the component in the design...
wxString Alternate
This is in addition to ReferenceName.
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)
std::map< ATTRIBUTE_ID, ATTRIBUTE_VALUE > AttributeValues
These attributes might also have a location.
long Version
Version is a sequential integer number to identify discrepancies between the library and the design.
long Width
Defaults to 0 if using system fonts or, if using CADSTAR font, default to equal height (1:1 aspect ra...
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
ALIGNMENT Alignment
In CADSTAR The default alignment for a TEXT object (when "(No Alignment)" is selected) Bottom Left of...
JUSTIFICATION Justification
Note: has no effect on single lines of text.
GROUP_ID GroupID
If not empty, this FIGURE is part of a group.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
< Nodename = "VARIANT" or "VMASTER" (master variant
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
VARIANT_ID ParentID
if empty, then this one is the master
Represents a vertex in a shape.
SHAPE_ARC BuildArc(const VECTOR2I &aPrevPoint, const std::function< VECTOR2I(const VECTOR2I &)> aCadstarToKicadPointCallback) const
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void AppendToChain(SHAPE_LINE_CHAIN *aChainToAppendTo, const std::function< VECTOR2I(const VECTOR2I &)> aCadstarToKicadPointCallback, int aAccuracy) const
Hold a keyword string and its unique integer token.
Definition dsnlexer.h:36
KIBIS_PIN * pin
VECTOR2I location
wxString result
Test unit parsing edge cases and error handling.
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Calculate the new point of coord coord pX, pY, for a rotation center 0, 0.
Definition trigo.cpp:225
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:683