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 {
95 THROW_PARSING_IO_ERROR( wxT( "TIMESTAMP" ), wxString::Format( "HEADER" ) );
96 }
97}
98
99
101{
102 wxASSERT( aNode->GetName() == wxT( "HEADER" ) );
103
104 XNODE* cNode = aNode->GetChildren();
105
106 for( ; cNode; cNode = cNode->GetNext() )
107 {
108 wxString nodeName = cNode->GetName();
109
110 if( nodeName == wxT( "FORMAT" ) )
111 {
112 Format.Parse( cNode, aContext );
113 }
114 else if( nodeName == wxT( "JOBFILE" ) )
115 {
116 JobFile = GetXmlAttributeIDString( cNode, 0 );
117 }
118 else if( nodeName == wxT( "JOBTITLE" ) )
119 {
120 JobTitle = GetXmlAttributeIDString( cNode, 0 );
121 }
122 else if( nodeName == wxT( "GENERATOR" ) )
123 {
125 }
126 else if( nodeName == wxT( "RESOLUTION" ) )
127 {
128 XNODE* subNode = cNode->GetChildren();
129
130 if( ( subNode->GetName() == wxT( "METRIC" ) )
131 && ( GetXmlAttributeIDString( subNode, 0 ) == wxT( "HUNDREDTH" ) )
132 && ( GetXmlAttributeIDString( subNode, 1 ) == wxT( "MICRON" ) ) )
133 {
135 }
136 else
137 {
138 // TODO Need to find out if there are other possible resolutions. Logically
139 // there must be other base units that could be used, such as "IMPERIAL INCH"
140 // or "METRIC MM" but so far none of settings in CADSTAR generated a different
141 // output resolution to "HUNDREDTH MICRON"
142 WARN_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), wxT( "HEADER->RESOLUTION" ) );
143 }
144 }
145 else if( nodeName == wxT( "TIMESTAMP" ) )
146 {
147 Timestamp.Parse( cNode, aContext );
148 }
149 else
150 {
151 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "HEADER" ) );
152 }
153 }
154}
155
156
158{
159 wxASSERT( aNode->GetName() == wxT( "VMASTER" ) || aNode->GetName() == wxT( "VARIANT" ) );
160
161 ID = GetXmlAttributeIDString( aNode, 0 );
162
163 if( aNode->GetName() == wxT( "VMASTER" ) )
164 {
165 Name = GetXmlAttributeIDString( aNode, 1 );
167 }
168 else
169 {
170 ParentID = GetXmlAttributeIDString( aNode, 1 );
171 Name = GetXmlAttributeIDString( aNode, 2 );
173 }
174}
175
176
178{
179 wxASSERT( aNode->GetName() == wxT( "VHIERARCHY" ) );
180
181 XNODE* cNode = aNode->GetChildren();
182
183 for( ; cNode; cNode = cNode->GetNext() )
184 {
185 if( cNode->GetName() == wxT( "VMASTER" ) || cNode->GetName() == wxT( "VARIANT" ) )
186 {
187 VARIANT variant;
188 variant.Parse( cNode, aContext );
189 Variants.insert( std::make_pair( variant.ID, variant ) );
190 }
191 else
192 {
193 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), cNode->GetName() );
194 }
195 }
196}
197
198
200{
201 wxASSERT( aNode->GetName() == wxT( "LINECODE" ) );
202
203 ID = GetXmlAttributeIDString( aNode, 0 );
204 Name = GetXmlAttributeIDString( aNode, 1 );
205
206 if( !GetXmlAttributeIDString( aNode, 2 ).ToLong( &Width ) )
207 THROW_PARSING_IO_ERROR( wxT( "Line Width" ), wxString::Format( "LINECODE -> %s", Name ) );
208
209 XNODE* cNode = aNode->GetChildren();
210
211 if( !cNode || cNode->GetName() != wxT( "STYLE" ) )
212 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxString::Format( "LINECODE -> %s", Name ) );
213
214 wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
215
216 if( styleStr == wxT( "SOLID" ) )
217 {
219 }
220 else if( styleStr == wxT( "DASH" ) )
221 {
223 }
224 else if( styleStr == wxT( "DASHDOT" ) )
225 {
227 }
228 else if( styleStr == wxT( "DASHDOTDOT" ) )
229 {
231 }
232 else if( styleStr == wxT( "DOT" ) )
233 {
235 }
236 else
237 {
238 WARN_UNKNOWN_PARAMETER_IO_ERROR( wxString::Format( "STYLE %s", styleStr ),
239 wxString::Format( "LINECODE -> %s", Name ) );
240 }
241}
242
243
245{
246 wxASSERT( aNode->GetName() == wxT( "HATCH" ) );
247
248 Step = GetXmlAttributeIDLong( aNode, 0 );
249 LineWidth = GetXmlAttributeIDLong( aNode, 2 );
250
251 XNODE* cNode = aNode->GetChildren();
252
253 if( !cNode || cNode->GetName() != wxT( "ORIENT" ) )
254 THROW_MISSING_NODE_IO_ERROR( wxT( "ORIENT" ), wxT( "HATCH" ) );
255
257}
258
259
261{
262 wxASSERT( aNode->GetName() == wxT( "HATCHCODE" ) );
263
264 ID = GetXmlAttributeIDString( aNode, 0 );
265 Name = GetXmlAttributeIDString( aNode, 1 );
266
267 XNODE* cNode = aNode->GetChildren();
268 wxString location = wxString::Format( "HATCHCODE -> %s", Name );
269
270 for( ; cNode; cNode = cNode->GetNext() )
271 {
272 if( cNode->GetName() != wxT( "HATCH" ) )
273 {
274 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), location );
275 continue;
276 }
277
278 HATCH hatch;
279 hatch.Parse( cNode, aContext );
280 Hatches.push_back( hatch );
281 }
282}
283
284
286{
287 wxASSERT( aNode->GetName() == wxT( "FONT" ) );
288
289 Name = GetXmlAttributeIDString( aNode, 0 );
290 Modifier1 = GetXmlAttributeIDLong( aNode, 1 );
291 Modifier2 = GetXmlAttributeIDLong( aNode, 2 );
292
293 XNODE* cNode = aNode->GetChildren();
294
295 for( ; cNode; cNode = cNode->GetNext() )
296 {
297 wxString cNodeName = cNode->GetName();
298
299 if( cNodeName == wxT( "ITALIC" ) )
300 Italic = true;
301 else if( cNodeName == wxT( "KERNING" ) )
302 KerningPairs = true;
303 else
304 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
305 }
306}
307
308
310{
311 wxASSERT( aNode->GetName() == wxT( "TEXTCODE" ) );
312
313 ID = GetXmlAttributeIDString( aNode, 0 );
314 Name = GetXmlAttributeIDString( aNode, 1 );
315
316 LineWidth = GetXmlAttributeIDLong( aNode, 2 );
317 Height = GetXmlAttributeIDLong( aNode, 3 );
318 Width = GetXmlAttributeIDLong( aNode, 4 );
319
320 XNODE* cNode = aNode->GetChildren();
321
322 if( cNode )
323 {
324 if( cNode->GetName() == wxT( "FONT" ) )
325 Font.Parse( cNode, aContext );
326 else
327 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
328 }
329}
330
331
333{
334 wxASSERT( aNode->GetName() == wxT( "ROUTEREASSIGN" ) );
335
336 LayerID = GetXmlAttributeIDString( aNode, 0 );
337 OptimalWidth = GetXmlAttributeIDLong( aNode, 1, false );
338
339 XNODE* cNode = aNode->GetChildren();
340
341 for( ; cNode; cNode = cNode->GetNext() )
342 {
343 wxString cNodeName = cNode->GetName();
344
345 if( cNodeName == wxT( "NECKWIDTH" ) )
347 else if( cNodeName == wxT( "SROUTEWIDTH" ) )
349 else if( cNodeName == wxT( "MINWIDTH" ) )
350 MinWidth = GetXmlAttributeIDLong( cNode, 0 );
351 else if( cNodeName == wxT( "MAXWIDTH" ) )
352 MaxWidth = GetXmlAttributeIDLong( cNode, 0 );
353 else
354 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
355 }
356}
357
358
360{
361 wxASSERT( aNode->GetName() == wxT( "ROUTECODE" ) );
362
363 ID = GetXmlAttributeIDString( aNode, 0 );
364 Name = GetXmlAttributeIDString( aNode, 1 );
365 OptimalWidth = GetXmlAttributeIDLong( aNode, 2, false );
366
367 XNODE* cNode = aNode->GetChildren();
368
369 for( ; cNode; cNode = cNode->GetNext() )
370 {
371 wxString cNodeName = cNode->GetName();
372
373 if( cNodeName == wxT( "NECKWIDTH" ) )
374 {
376 }
377 else if( cNodeName == wxT( "SROUTEWIDTH" ) )
378 {
380 }
381 else if( cNodeName == wxT( "MINWIDTH" ) )
382 {
383 MinWidth = GetXmlAttributeIDLong( cNode, 0 );
384 }
385 else if( cNodeName == wxT( "MAXWIDTH" ) )
386 {
387 MaxWidth = GetXmlAttributeIDLong( cNode, 0 );
388 }
389 else if( cNodeName == wxT( "ROUTEREASSIGN" ) )
390 {
391 ROUTEREASSIGN routereassign;
392 routereassign.Parse( cNode, aContext );
393 RouteReassigns.push_back( routereassign );
394 }
395 else
396 {
397 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
398 }
399 }
400}
401
402
404{
405 return Base * std::pow( 10.0, Exponent );
406}
407
408
410{
411 wxASSERT( aNode->GetName() == wxT( "E" ) );
412
413 if( ( !GetXmlAttributeIDString( aNode, 0 ).ToLong( &Base ) )
414 || ( !GetXmlAttributeIDString( aNode, 1 ).ToLong( &Exponent ) ) )
415 {
416 THROW_PARSING_IO_ERROR( wxT( "Base and Exponent" ),
417 wxString::Format( "%s->%s", aNode->GetParent()->GetName(),
418 aNode->GetParent()->GetName() ) );
419 }
420}
421
422
424{
425 wxASSERT( aNode->GetName() == wxT( "PT" ) );
426
427 x = GetXmlAttributeIDLong( aNode, 0 );
428 y = GetXmlAttributeIDLong( aNode, 1 );
429}
430
431
433{
434 wxASSERT( aNode->GetName() == wxT( "PT" ) );
435
436 x = GetXmlAttributeIDLong( aNode, 0 );
437 y = GetXmlAttributeIDLong( aNode, 1 );
438}
439
440
442{
443 wxString aNodeName = aNode->GetName();
444
445 if( aNodeName == wxT( "PT" ) || aNodeName == wxT( "ACWARC" ) || aNodeName == wxT( "CWARC" )
446 || aNodeName == wxT( "CWSEMI" ) || aNodeName == wxT( "ACWSEMI" ) )
447 {
448 return true;
449 }
450 else
451 {
452 return false;
453 }
454}
455
456
458{
459 wxASSERT( IsVertex( aNode ) );
460
461 wxString aNodeName = aNode->GetName();
462
463 if( aNodeName == wxT( "PT" ) )
464 {
468 End.Parse( aNode, aContext );
469 }
470 else if( aNodeName == wxT( "ACWARC" ) || aNodeName == wxT( "CWARC" ) )
471 {
472 if( aNodeName == wxT( "ACWARC" ) )
474 else
476
477 std::vector<POINT> pts = ParseAllChildPoints( aNode, aContext, true, 2 );
478
479 Center = pts[0];
480 End = pts[1];
481 }
482 else if( aNodeName == wxT( "ACWSEMI" ) || aNodeName == wxT( "CWSEMI" ) )
483 {
484 if( aNodeName == wxT( "ACWSEMI" ) )
486 else
488
491
492 std::vector<POINT> pts = ParseAllChildPoints( aNode, aContext, true, 1 );
493
494 End = pts[0];
495 }
496 else
497 {
498 wxASSERT_MSG( true, wxT( "Unknown VERTEX type" ) );
499 }
500}
501
502
504 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
505 int aAccuracy ) const
506{
508 {
509 aChainToAppendTo->Append( aCadstarToKicadPointCallback( End ) );
510 return;
511 }
512
513 wxCHECK_MSG( aChainToAppendTo->PointCount() > 0, /*void*/,
514 "Can't append an arc to vertex to an empty chain" );
515
516 aChainToAppendTo->Append( BuildArc( aChainToAppendTo->GetPoint( -1 ),
517 aCadstarToKicadPointCallback ),
518 aAccuracy );
519}
520
521
523 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback ) const
524{
525 wxCHECK_MSG( Type != VERTEX_TYPE::VT_POINT, SHAPE_ARC(),
526 "Can't build an arc for a straight segment!" );
527
528 VECTOR2I startPoint = aPrevPoint;
529 VECTOR2I endPoint = aCadstarToKicadPointCallback( End );
530 VECTOR2I centerPoint;
531
533 centerPoint = ( startPoint / 2 ) + ( endPoint / 2 );
534 else
535 centerPoint = aCadstarToKicadPointCallback( Center );
536
537 bool clockwise = Type == VERTEX_TYPE::CLOCKWISE_ARC
539
540 // A bit of a hack to figure out if we need to invert clockwise due to the transform
541 VECTOR2I transform = aCadstarToKicadPointCallback( { 500, 500 } )
542 - aCadstarToKicadPointCallback( { 0, 0 } );
543
544 if( ( transform.x > 0 && transform.y < 0 ) || ( transform.x < 0 && transform.y > 0 ) )
545 clockwise = !clockwise;
546
547 SHAPE_ARC arc;
548
549 return arc.ConstructFromStartEndCenter( startPoint, endPoint, centerPoint, clockwise );
550}
551
552
554{
555 wxASSERT( aNode->GetName() == wxT( "CUTOUT" ) );
556
557 Vertices = ParseAllChildVertices( aNode, aContext, true );
558}
559
560
562{
563 wxString aNodeName = aNode->GetName();
564
565 if( aNodeName == wxT( "OPENSHAPE" ) || aNodeName == wxT( "OUTLINE" )
566 || aNodeName == wxT( "SOLID" ) || aNodeName == wxT( "HATCHED" ) )
567 {
568 return true;
569 }
570 else
571 {
572 return false;
573 }
574}
575
576
578{
579 wxASSERT( IsShape( aNode ) );
580
581 wxString aNodeName = aNode->GetName();
582
583 if( aNodeName == wxT( "OPENSHAPE" ) )
584 {
586 Vertices = ParseAllChildVertices( aNode, aContext, true );
587 Cutouts.clear();
588 HatchCodeID = wxEmptyString;
589 }
590 else if( aNodeName == wxT( "OUTLINE" ) )
591 {
593 Vertices = ParseAllChildVertices( aNode, aContext, false );
594 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
595 HatchCodeID = wxEmptyString;
596 }
597 else if( aNodeName == wxT( "SOLID" ) )
598 {
600 Vertices = ParseAllChildVertices( aNode, aContext, false );
601 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
602 HatchCodeID = wxEmptyString;
603 }
604 else if( aNodeName == wxT( "HATCHED" ) )
605 {
607 Vertices = ParseAllChildVertices( aNode, aContext, false );
608 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
610 }
611 else
612 {
613 wxASSERT_MSG( true, wxT( "Unknown SHAPE type" ) );
614 }
615}
616
618 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
619 int aMaxError ) const
620{
621 SHAPE_LINE_CHAIN outline;
622
623 if( Vertices.size() == 0 )
624 return outline;
625
626 for( const auto& vertex : Vertices )
627 vertex.AppendToChain( &outline, aCadstarToKicadPointCallback, aMaxError );
628
630 {
631 outline.SetClosed( true );
632
633 // Append after closing, to ensre first and last point remain the same
634 outline.Append( outline.CPoint( 0 ), true );
635 }
636
637 return outline;
638}
639
640
642 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
643 int aMaxError ) const
644{
645 SHAPE_POLY_SET polyset;
646
647 // We shouldn't convert openshapes to polyset!
648 wxCHECK( Type != SHAPE_TYPE::OPENSHAPE, polyset );
649
650 polyset.AddOutline( OutlineAsChain( aCadstarToKicadPointCallback, aMaxError ) );
651
652 for( const auto& cutout : Cutouts )
653 {
654 SHAPE_LINE_CHAIN hole;
655
656 if( cutout.Vertices.size() == 0 )
657 continue;
658
659 for( const auto& cutoutVertex : cutout.Vertices )
660 cutoutVertex.AppendToChain( &hole, aCadstarToKicadPointCallback, aMaxError );
661
662 hole.SetClosed( true );
663
664 // Append after closing, to ensre first and last point remain the same
665 cutout.Vertices.at( 0 ).AppendToChain( &hole, aCadstarToKicadPointCallback, aMaxError );
666
667 polyset.AddHole( hole );
668 }
669
670 return polyset;
671}
672
673
675{
676 wxASSERT( aNode->GetName() == wxT( "UNITS" ) );
677
678 wxString unit = GetXmlAttributeIDString( aNode, 0 );
679
680 if( unit == wxT( "CENTIMETER" ) )
681 return UNITS::CENTIMETER;
682 else if( unit == wxT( "INCH" ) )
683 return UNITS::INCH;
684 else if( unit == wxT( "METER" ) )
685 return UNITS::METER;
686 else if( unit == wxT( "MICROMETRE" ) )
687 return UNITS::MICROMETRE;
688 else if( unit == wxT( "MM" ) )
689 return UNITS::MM;
690 else if( unit == wxT( "THOU" ) )
691 return UNITS::THOU;
692 else if( unit == wxT( "DESIGN" ) )
693 return UNITS::DESIGN;
694 else
695 WARN_UNKNOWN_PARAMETER_IO_ERROR( unit, wxT( "UNITS" ) );
696
697 return UNITS::DESIGN;
698}
699
700
702{
703 wxASSERT( aNode->GetName() == wxT( "ANGUNITS" ) );
704
705 wxString angUnitStr = GetXmlAttributeIDString( aNode, 0 );
706
707 if( angUnitStr == wxT( "DEGREES" ) )
708 return ANGUNITS::DEGREES;
709 else if( angUnitStr == wxT( "RADIANS" ) )
710 return ANGUNITS::RADIANS;
711 else
712 WARN_UNKNOWN_PARAMETER_IO_ERROR( angUnitStr, aNode->GetName() );
713
714 return ANGUNITS::DEGREES;
715}
716
717
719{
720 if( !aNode )
721 return false;
722
723 wxString aNodeName = aNode->GetName();
724
725 if( aNodeName == wxT( "FRACTIONALGRID" ) || aNodeName == wxT( "STEPGRID" ) )
726 return true;
727 else
728 return false;
729}
730
731
733{
734 wxASSERT( IsGrid( aNode ) );
735
736 wxString aNodeName = aNode->GetName();
737
738 if( aNodeName == wxT( "FRACTIONALGRID" ) )
740 else if( aNodeName == wxT( "STEPGRID" ) )
742 else
743 wxASSERT_MSG( true, wxT( "Unknown Grid Type" ) );
744
745 Name = GetXmlAttributeIDString( aNode, 0 );
746 Param1 = GetXmlAttributeIDLong( aNode, 1 );
747 Param2 = GetXmlAttributeIDLong( aNode, 2 );
748}
749
750
752{
753 wxASSERT( aNode->GetName() == wxT( "GRIDS" ) );
754
755 XNODE* cNode = aNode->GetChildren();
756
757 for( ; cNode; cNode = cNode->GetNext() )
758 {
759 wxString cNodeName = cNode->GetName();
760
761 if( cNodeName == wxT( "WORKINGGRID" ) )
762 {
763 XNODE* workingGridNode = cNode->GetChildren();
764
765 if( !GRID::IsGrid( workingGridNode ) )
766 {
767 wxString found = workingGridNode ? workingGridNode->GetName() : wxString( "(empty)" );
768 WARN_UNKNOWN_NODE_IO_ERROR( found, wxT( "GRIDS -> WORKINGGRID" ) );
769 }
770 else
771 {
772 WorkingGrid.Parse( workingGridNode, aContext );
773 }
774 }
775 else if( cNodeName == wxT( "SCREENGRID" ) )
776 {
777 XNODE* screenGridNode = cNode->GetChildren();
778
779 if( !GRID::IsGrid( screenGridNode ) )
780 {
781 wxString found = screenGridNode ? screenGridNode->GetName() : wxString( "(empty)" );
782 WARN_UNKNOWN_NODE_IO_ERROR( found, wxT( "GRIDS -> SCREENGRID" ) );
783 }
784 else
785 {
786 ScreenGrid.Parse( screenGridNode, aContext );
787 }
788 }
789 else if( GRID::IsGrid( cNode ) )
790 {
791 GRID userGrid;
792 userGrid.Parse( cNode, aContext );
793 UserGrids.push_back( userGrid );
794 }
795 else
796 {
797 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "GRIDS" ) );
798 }
799 }
800}
801
802
804{
805 wxString cNodeName = aChildNode->GetName();
806
807 if( cNodeName == wxT( "UNITS" ) )
808 {
809 Units = ParseUnits( aChildNode );
810 }
811 else if( cNodeName == wxT( "UNITSPRECISION" ) )
812 {
813 UnitDisplPrecision = GetXmlAttributeIDLong( aChildNode, 0 );
814 }
815 else if( cNodeName == wxT( "INTERLINEGAP" ) )
816 {
817 InterlineGap = GetXmlAttributeIDLong( aChildNode, 0 );
818 }
819 else if( cNodeName == wxT( "BARLINEGAP" ) )
820 {
821 BarlineGap = GetXmlAttributeIDLong( aChildNode, 0 );
822 }
823 else if( cNodeName == wxT( "ALLOWBARTEXT" ) )
824 {
825 AllowBarredText = true;
826 }
827 else if( cNodeName == wxT( "ANGULARPRECISION" ) )
828 {
829 AngularPrecision = GetXmlAttributeIDLong( aChildNode, 0 );
830 }
831 else if( cNodeName == wxT( "DESIGNORIGIN" ) )
832 {
833 DesignOrigin.Parse( aChildNode->GetChildren(), aContext );
834 }
835 else if( cNodeName == wxT( "DESIGNAREA" ) )
836 {
837 std::vector<POINT> pts = ParseAllChildPoints( aChildNode, aContext, true, 2 );
838 DesignArea = std::make_pair( pts[0], pts[1] );
839 }
840 else if( cNodeName == wxT( "DESIGNREF" ) )
841 {
842 DesignOrigin.Parse( aChildNode->GetChildren(), aContext );
843 }
844 else if( cNodeName == wxT( "DESIGNLIMIT" ) )
845 {
846 DesignLimit.Parse( aChildNode->GetChildren(), aContext );
847 }
848 else if( cNodeName == wxT( "PINNOOFFSET" ) )
849 {
850 PinNoOffset = GetXmlAttributeIDLong( aChildNode, 0 );
851 }
852 else if( cNodeName == wxT( "PINNOANGLE" ) )
853 {
854 PinNoAngle = GetXmlAttributeIDLong( aChildNode, 0 );
855 }
856 else
857 {
858 return false;
859 }
860
861 return true;
862}
863
864
866{
867 wxASSERT( aNode->GetName() == wxT( "SETTINGS" ) );
868
869 XNODE* cNode = aNode->GetChildren();
870
871 for( ; cNode; cNode = cNode->GetNext() )
872 {
873 wxString cNodeName = cNode->GetName();
874
875 if( ParseSubNode( cNode, aContext ) )
876 continue;
877 else
878 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "SETTINGS" ) );
879 }
880}
881
882
883wxString CADSTAR_ARCHIVE_PARSER::ParseTextFields( const wxString& aTextString,
884 PARSER_CONTEXT* aContext )
885{
886 static const std::map<TEXT_FIELD_NAME, wxString> txtTokens =
887 {
888 { TEXT_FIELD_NAME::DESIGN_TITLE, wxT( "DESIGN TITLE" ) },
889 { TEXT_FIELD_NAME::SHORT_JOBNAME, wxT( "SHORT_JOBNAME" ) },
890 { TEXT_FIELD_NAME::LONG_JOBNAME, wxT( "LONG_JOBNAME" ) },
891 { TEXT_FIELD_NAME::NUM_OF_SHEETS, wxT( "NUM_OF_SHEETS" ) },
892 { TEXT_FIELD_NAME::SHEET_NUMBER, wxT( "SHEET_NUMBER" ) },
893 { TEXT_FIELD_NAME::SHEET_NAME, wxT( "SHEET_NAME" ) },
894 { TEXT_FIELD_NAME::VARIANT_NAME, wxT( "VARIANT_NAME" ) },
895 { TEXT_FIELD_NAME::VARIANT_DESCRIPTION, wxT( "VARIANT_DESCRIPTION" ) },
896 { TEXT_FIELD_NAME::REG_USER, wxT( "REG_USER" ) },
897 { TEXT_FIELD_NAME::COMPANY_NAME, wxT( "COMPANY_NAME" ) },
898 { TEXT_FIELD_NAME::CURRENT_USER, wxT( "CURRENT_USER" ) },
899 { TEXT_FIELD_NAME::DATE, wxT( "DATE" ) },
900 { TEXT_FIELD_NAME::TIME, wxT( "TIME" ) },
901 { TEXT_FIELD_NAME::MACHINE_NAME, wxT( "MACHINE_NAME" ) },
902 { TEXT_FIELD_NAME::FROM_FILE, wxT( "FROM_FILE" ) },
903 { TEXT_FIELD_NAME::DISTANCE, wxT( "DISTANCE" ) },
904 { TEXT_FIELD_NAME::UNITS_SHORT, wxT( "UNITS SHORT" ) },
905 { TEXT_FIELD_NAME::UNITS_ABBREV, wxT( "UNITS ABBREV" ) },
906 { TEXT_FIELD_NAME::UNITS_FULL, wxT( "UNITS FULL" ) },
907 { TEXT_FIELD_NAME::HYPERLINK, wxT( "HYPERLINK" ) }
908 };
909
910 wxString remainingStr = aTextString;
911 wxString returnStr;
912
913 while( remainingStr.size() > 0 )
914 {
915 // Find the start token
916 size_t startpos = remainingStr.Find( wxT( "<@" ) );
917
918 if( static_cast<int>( startpos ) == wxNOT_FOUND )
919 {
920 // No more fields to parse, add to return string
921 returnStr += remainingStr;
922 break;
923 }
924
925 if( startpos > 0 )
926 returnStr += remainingStr.SubString( 0, startpos - 1 );
927
928 if( ( startpos + 2 ) >= remainingStr.size() )
929 break;
930
931 remainingStr = remainingStr.Mid( startpos + 2 );
932
933 //Find the expected token for the field
935
936 for( std::pair<TEXT_FIELD_NAME, wxString> txtF : txtTokens )
937 {
938 if( remainingStr.StartsWith( txtF.second ) )
939 {
940 foundField = txtF.first;
941 break;
942 }
943 }
944
945 if( foundField == TEXT_FIELD_NAME::NONE )
946 {
947 // Not a valid field, lets keep looking
948 returnStr += wxT( "<@" );
949 continue;
950 }
951
952 //Now lets find the end token
953 size_t endpos = remainingStr.Find( wxT( "@>" ) );
954
955 if( static_cast<int>( endpos ) == wxNOT_FOUND )
956 {
957 // The field we found isn't valid as it doesn't have a termination
958 // Lets append the whole thing as plain text
959 returnStr += wxT( "<@" ) + remainingStr;
960 break;
961 }
962
963 size_t valueStart = txtTokens.at( foundField ).size();
964 wxString fieldValue = remainingStr.SubString( valueStart, endpos - 1 );
965 wxString address;
966
967 if( foundField == TEXT_FIELD_NAME::FROM_FILE || foundField == TEXT_FIELD_NAME::HYPERLINK )
968 {
969 // The first character should always be a double quotation mark
970 wxASSERT_MSG( fieldValue.at( 0 ) == '"', "Expected '\"' as the first character" );
971
972 size_t splitPos = fieldValue.find_first_of( '"', 1 );
973 address = fieldValue.SubString( 1, splitPos - 1 );
974
975 if( foundField == TEXT_FIELD_NAME::HYPERLINK )
976 {
977 // Assume the last two characters are "@>"
978 wxASSERT_MSG( remainingStr.EndsWith( wxT( "@>" ) ),
979 "Expected '@>' at the end of a hyperlink" );
980
981 fieldValue = remainingStr.SubString( valueStart + splitPos + 1,
982 remainingStr.Length() - 3 );
983
984 remainingStr = wxEmptyString;
985 }
986 else
987 {
988 fieldValue = fieldValue.Mid( splitPos + 1 );
989 }
990 }
991
992 switch( foundField )
993 {
1005
1006 if( aContext->TextFieldToValuesMap.find( foundField )
1007 != aContext->TextFieldToValuesMap.end() )
1008 {
1009 aContext->InconsistentTextFields.insert( foundField );
1010 }
1011 else
1012 {
1013 aContext->TextFieldToValuesMap.insert( { foundField, fieldValue } );
1014 }
1015
1017
1021 returnStr += wxT( "${" ) + CADSTAR_TO_KICAD_FIELDS.at( foundField ) + wxT( "}" );
1022 break;
1023
1028 // Just flatten the text for distances
1029 returnStr += fieldValue;
1030 break;
1031
1033 {
1034 wxFileName fn( address );
1035 wxString fieldFmt = wxT( "FROM_FILE_%s_%s" );
1036 wxString fieldName = wxString::Format( fieldFmt, fn.GetName(), fn.GetExt() );
1037
1038 int version = 1;
1039
1040 while(
1041 aContext->FilenamesToTextMap.find( fieldName )
1042 != aContext->FilenamesToTextMap.end()
1043 && aContext->FilenamesToTextMap.at( fieldName ) != fieldValue )
1044 {
1045 fieldName = wxString::Format( fieldFmt, fn.GetName(), fn.GetExt() )
1046 + wxString::Format( wxT( "_%d" ), version++ );
1047 }
1048
1049 aContext->FilenamesToTextMap[fieldName] = fieldValue;
1050 returnStr += wxT( "${" ) + fieldName + wxT( "}" );
1051 }
1052 break;
1053
1055 {
1056 aContext->TextToHyperlinksMap[fieldValue] = address;
1057 returnStr += ParseTextFields( fieldValue, aContext );
1058 }
1059 break;
1060
1062 wxFAIL_MSG( "We should have already covered this scenario above" );
1063 break;
1064 }
1065
1066
1067 if( ( endpos + 2 ) >= remainingStr.size() )
1068 break;
1069
1070 remainingStr = remainingStr.Mid( endpos + 2 );
1071 }
1072
1073 return returnStr;
1074}
1075
1076
1078{
1079 wxASSERT( aNode->GetName() == wxT( "ALIGN" ) );
1080
1081 wxString alignmentStr = GetXmlAttributeIDString( aNode, 0 );
1082
1083 if( alignmentStr == wxT( "BOTTOMCENTER" ) )
1085 else if( alignmentStr == wxT( "BOTTOMLEFT" ) )
1086 return ALIGNMENT::BOTTOMLEFT;
1087 else if( alignmentStr == wxT( "BOTTOMRIGHT" ) )
1089 else if( alignmentStr == wxT( "CENTERCENTER" ) )
1091 else if( alignmentStr == wxT( "CENTERLEFT" ) )
1092 return ALIGNMENT::CENTERLEFT;
1093 else if( alignmentStr == wxT( "CENTERRIGHT" ) )
1095 else if( alignmentStr == wxT( "TOPCENTER" ) )
1096 return ALIGNMENT::TOPCENTER;
1097 else if( alignmentStr == wxT( "TOPLEFT" ) )
1098 return ALIGNMENT::TOPLEFT;
1099 else if( alignmentStr == wxT( "TOPRIGHT" ) )
1100 return ALIGNMENT::TOPRIGHT;
1101 else
1102 WARN_UNKNOWN_PARAMETER_IO_ERROR( alignmentStr, wxT( "ALIGN" ) );
1103
1104 //shouldn't be here but avoids compiler warning
1106}
1107
1108
1110{
1111 wxASSERT( aNode->GetName() == wxT( "JUSTIFICATION" ) );
1112
1113 wxString justificationStr = GetXmlAttributeIDString( aNode, 0 );
1114
1115 if( justificationStr == wxT( "LEFT" ) )
1116 return JUSTIFICATION::LEFT;
1117 else if( justificationStr == wxT( "RIGHT" ) )
1118 return JUSTIFICATION::RIGHT;
1119 else if( justificationStr == wxT( "CENTER" ) )
1120 return JUSTIFICATION::CENTER;
1121 else
1122 WARN_UNKNOWN_PARAMETER_IO_ERROR( justificationStr, wxT( "JUSTIFICATION" ) );
1123
1124 return JUSTIFICATION::LEFT;
1125}
1126
1127
1129{
1130 wxASSERT( aNode->GetName() == wxT( "READABILITY" ) );
1131
1132 wxString readabilityStr = GetXmlAttributeIDString( aNode, 0 );
1133
1134 if( readabilityStr == wxT( "BOTTOM_TO_TOP" ) )
1136 else if( readabilityStr == wxT( "TOP_TO_BOTTOM" ) )
1138 else
1139 WARN_UNKNOWN_PARAMETER_IO_ERROR( readabilityStr, wxT( "READABILITY" ) );
1140
1142}
1143
1144
1151
1152
1154 PARSER_CONTEXT* aContext )
1155{
1156 wxString cNodeName = aChildNode->GetName();
1157
1158 if( cNodeName == wxT( "PT" ) )
1159 Position.Parse( aChildNode, aContext );
1160 else if( cNodeName == wxT( "ORIENT" ) )
1161 OrientAngle = GetXmlAttributeIDLong( aChildNode, 0 );
1162 else if( cNodeName == wxT( "MIRROR" ) )
1163 Mirror = true;
1164 else if( cNodeName == wxT( "FIX" ) )
1165 Fixed = true;
1166 else if( cNodeName == wxT( "ALIGN" ) )
1167 Alignment = ParseAlignment( aChildNode );
1168 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1169 Justification = ParseJustification( aChildNode );
1170 else
1171 return false;
1172
1173 return true;
1174}
1175
1176
1178{
1179 wxASSERT( aNode->GetName() == wxT( "ATTRLOC" ) );
1180
1181 ParseIdentifiers( aNode, aContext );
1182
1183 //Parse child nodes
1184 XNODE* cNode = aNode->GetChildren();
1185
1186 for( ; cNode; cNode = cNode->GetNext() )
1187 {
1188 if( ParseSubNode( cNode, aContext ) )
1189 continue;
1190 else
1191 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "ATTRLOC" ) );
1192 }
1193
1195 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "ATTRLOC" ) );
1196}
1197
1198
1200{
1201 wxASSERT( aNode->GetName() == wxT( "COLUMNORDER" ) );
1202
1203 ID = GetXmlAttributeIDLong( aNode, 0 );
1204 Order = GetXmlAttributeIDLong( aNode, 1 );
1205
1206 CheckNoChildNodes( aNode );
1207}
1208
1209
1211{
1212 wxASSERT( aNode->GetName() == wxT( "COLUMNWIDTH" ) );
1213
1214 ID = GetXmlAttributeIDLong( aNode, 0 );
1215 Width = GetXmlAttributeIDLong( aNode, 1 );
1216
1217 CheckNoChildNodes( aNode );
1218}
1219
1220
1222{
1223 wxASSERT( aNode->GetName() == wxT( "ATTRNAME" ) );
1224
1225 ID = GetXmlAttributeIDString( aNode, 0 );
1226 Name = GetXmlAttributeIDString( aNode, 1 );
1227
1228 XNODE* cNode = aNode->GetChildren();
1229 wxString location = wxString::Format( "ATTRNAME -> %s", Name );
1230
1231 for( ; cNode; cNode = cNode->GetNext() )
1232 {
1233 wxString cNodeName = cNode->GetName();
1234
1235 if( cNodeName == wxT( "ATTROWNER" ) )
1236 {
1237 wxString attOwnerVal = GetXmlAttributeIDString( cNode, 0 );
1238
1239 if( attOwnerVal == wxT( "ALL_ITEMS" ) )
1241 else if( attOwnerVal == wxT( "AREA" ) )
1243 else if( attOwnerVal == wxT( "BOARD" ) )
1245 else if( attOwnerVal == wxT( "COMPONENT" ) )
1247 else if( attOwnerVal == wxT( "CONNECTION" ) )
1249 else if( attOwnerVal == wxT( "COPPER" ) )
1251 else if( attOwnerVal == wxT( "DOCSYMBOL" ) )
1253 else if( attOwnerVal == wxT( "FIGURE" ) )
1255 else if( attOwnerVal == wxT( "NET" ) )
1257 else if( attOwnerVal == wxT( "NETCLASS" ) )
1259 else if( attOwnerVal == wxT( "PART" ) )
1261 else if( attOwnerVal == wxT( "PART_DEFINITION" ) )
1263 else if( attOwnerVal == wxT( "PIN" ) )
1265 else if( attOwnerVal == wxT( "SIGNALREF" ) )
1267 else if( attOwnerVal == wxT( "SYMBOL" ) )
1269 else if( attOwnerVal == wxT( "SYMDEF" ) )
1271 else if( attOwnerVal == wxT( "TEMPLATE" ) )
1273 else if( attOwnerVal == wxT( "TESTPOINT" ) )
1275 else
1277 }
1278 else if( cNodeName == wxT( "ATTRUSAGE" ) )
1279 {
1280 wxString attUsageVal = GetXmlAttributeIDString( cNode, 0 );
1281
1282 if( attUsageVal == wxT( "BOTH" ) )
1284 else if( attUsageVal == wxT( "COMPONENT" ) )
1286 else if( attUsageVal == wxT( "PART_DEFINITION" ) )
1288 else if( attUsageVal == wxT( "PART_LIBRARY" ) )
1290 else if( attUsageVal == wxT( "SYMBOL" ) )
1292 else
1294 }
1295 else if( cNodeName == wxT( "NOTRANSFER" ) )
1296 {
1297 NoTransfer = true;
1298 }
1299 else if( cNodeName == wxT( "COLUMNORDER" ) )
1300 {
1301 COLUMNORDER cOrder;
1302 cOrder.Parse( cNode, aContext );
1303 ColumnOrders.push_back( cOrder );
1304 }
1305 else if( cNodeName == wxT( "COLUMNWIDTH" ) )
1306 {
1307 COLUMNWIDTH cWidth;
1308 cWidth.Parse( cNode, aContext );
1309 ColumnWidths.push_back( cWidth );
1310 }
1311 else if( cNodeName == wxT( "COLUMNINVISIBLE" ) )
1312 {
1313 ColumnInvisible = true;
1314 }
1315 else
1316 {
1318 }
1319 }
1320}
1321
1322
1324{
1325 wxASSERT( aNode->GetName() == wxT( "ATTR" ) );
1326
1328 Value = GetXmlAttributeIDString( aNode, 1 );
1329
1330 XNODE* cNode = aNode->GetChildren();
1331
1332 for( ; cNode; cNode = cNode->GetNext() )
1333 {
1334 if( cNode->GetName() == wxT( "READONLY" ) )
1335 {
1336 ReadOnly = true;
1337 }
1338 else if( cNode->GetName() == wxT( "ATTRLOC" ) )
1339 {
1340 AttributeLocation.Parse( cNode, aContext );
1341 HasLocation = true;
1342 }
1343 else
1344 {
1345 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "ATTR" ) );
1346 }
1347 }
1348}
1349
1350
1352{
1353 wxASSERT( aNode->GetName() == wxT( "TEXTLOC" ) );
1354
1355 wxString attributeStr = GetXmlAttributeIDString( aNode, 0 );
1356 bool attributeIDisSet = false;
1357
1358 if( attributeStr == wxT( "PART_NAME" ) )
1359 {
1361 attributeIDisSet = true;
1362 }
1363 else if( attributeStr == wxT( "COMP_NAME" ) )
1364 {
1366 attributeIDisSet = true;
1367 }
1368 else if( attributeStr == wxT( "COMP_NAME2" ) )
1369 {
1371 attributeIDisSet = true;
1372 }
1373 else if( attributeStr == wxT( "SYMBOL_NAME" ) )
1374 {
1376 attributeIDisSet = true;
1377 }
1378 else if( attributeStr == wxT( "LINK_ORIGIN" ) )
1379 {
1381 attributeIDisSet = true;
1382 }
1383 else if( attributeStr == wxT( "SIGNALNAME_ORIGIN" ) )
1384 {
1386 attributeIDisSet = true;
1387 }
1388 else if( attributeStr == wxT( "ATTRREF" ) )
1389 {
1390 //We will initialise when we parse all child nodes
1391 attributeIDisSet = false;
1392 }
1393 else
1394 {
1395 WARN_UNKNOWN_PARAMETER_IO_ERROR( attributeStr, wxT( "TEXTLOC" ) );
1396 }
1397
1398 TextCodeID = GetXmlAttributeIDString( aNode, 1 );
1399 LayerID = GetXmlAttributeIDString( aNode, 2, false );
1400
1401 //Parse child nodes
1402 XNODE* cNode = aNode->GetChildren();
1403
1404 for( ; cNode; cNode = cNode->GetNext() )
1405 {
1406 wxString cNodeName = cNode->GetName();
1407
1408 if( ParseSubNode( cNode, aContext ) )
1409 {
1410 continue;
1411 }
1412 else if( !attributeIDisSet && cNodeName == wxT( "ATTRREF" ) )
1413 {
1415 attributeIDisSet = true;
1416 }
1417 else if( cNodeName == wxT( "ORIENT" ) )
1418 {
1419 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1420 }
1421 else if( cNodeName == wxT( "MIRROR" ) )
1422 {
1423 Mirror = true;
1424 }
1425 else if( cNodeName == wxT( "FIX" ) )
1426 {
1427 Fixed = true;
1428 }
1429 else if( cNodeName == wxT( "ALIGN" ) )
1430 {
1431 Alignment = ParseAlignment( cNode );
1432 }
1433 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1434 {
1436 }
1437 else
1438 {
1439 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEXTLOC" ) );
1440 }
1441 }
1442
1444 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "TEXTLOC" ) );
1445}
1446
1447
1449{
1450 wxASSERT( aNode->GetName() == wxT( "NETCLASS" ) );
1451
1452 ID = GetXmlAttributeIDString( aNode, 0 );
1453 Name = GetXmlAttributeIDString( aNode, 1 );
1454
1455 XNODE* cNode = aNode->GetChildren();
1456 wxString location = wxString::Format( "NETCLASS -> %s", Name );
1457
1458 for( ; cNode; cNode = cNode->GetNext() )
1459 {
1460 wxString cNodeName = cNode->GetName();
1461
1462 if( cNodeName == wxT( "ATTR" ) )
1463 {
1464 ATTRIBUTE_VALUE attribute_val;
1465 attribute_val.Parse( cNode, aContext );
1466 Attributes.push_back( attribute_val );
1467 }
1468 else
1469 {
1471 }
1472 }
1473}
1474
1475
1477{
1478 wxASSERT( aNode->GetName() == wxT( "SPCCLASSNAME" ) );
1479
1480 ID = GetXmlAttributeIDString( aNode, 0 );
1481 Name = GetXmlAttributeIDString( aNode, 1 );
1482}
1483
1484
1486{
1487 wxString nodeName = aChildNode->GetName();
1488
1489 if( nodeName == wxT( "LINECODE" ) )
1490 {
1491 LINECODE linecode;
1492 linecode.Parse( aChildNode, aContext );
1493 LineCodes.insert( std::make_pair( linecode.ID, linecode ) );
1494 }
1495 else if( nodeName == wxT( "HATCHCODE" ) )
1496 {
1497 HATCHCODE hatchcode;
1498 hatchcode.Parse( aChildNode, aContext );
1499 HatchCodes.insert( std::make_pair( hatchcode.ID, hatchcode ) );
1500 }
1501 else if( nodeName == wxT( "TEXTCODE" ) )
1502 {
1503 TEXTCODE textcode;
1504 textcode.Parse( aChildNode, aContext );
1505 TextCodes.insert( std::make_pair( textcode.ID, textcode ) );
1506 }
1507 else if( nodeName == wxT( "ROUTECODE" ) )
1508 {
1509 ROUTECODE routecode;
1510 routecode.Parse( aChildNode, aContext );
1511 RouteCodes.insert( std::make_pair( routecode.ID, routecode ) );
1512 }
1513 else if( nodeName == wxT( "ATTRNAME" ) )
1514 {
1515 ATTRNAME attrname;
1516 attrname.Parse( aChildNode, aContext );
1517 AttributeNames.insert( std::make_pair( attrname.ID, attrname ) );
1518 }
1519 else if( nodeName == wxT( "NETCLASS" ) )
1520 {
1521 CADSTAR_NETCLASS netclass;
1522 netclass.Parse( aChildNode, aContext );
1523 NetClasses.insert( std::make_pair( netclass.ID, netclass ) );
1524 }
1525 else if( nodeName == wxT( "SPCCLASSNAME" ) )
1526 {
1527 SPCCLASSNAME spcclassname;
1528 spcclassname.Parse( aChildNode, aContext );
1529 SpacingClassNames.insert( std::make_pair( spcclassname.ID, spcclassname ) );
1530 }
1531 else
1532 {
1533 return false;
1534 }
1535
1536 return true;
1537}
1538
1539
1541{
1542 wxASSERT( aNode->GetName() == wxT( "SWAPRULE" ) );
1543
1545 wxString swapRuleStr = GetXmlAttributeIDString( aNode, 0 );
1546
1547 if( swapRuleStr == wxT( "NO_SWAP" ) )
1548 retval = SWAP_RULE::NO_SWAP;
1549 else if( swapRuleStr == wxT( "USE_SWAP_LAYER" ) )
1551 else
1552 WARN_UNKNOWN_PARAMETER_IO_ERROR( swapRuleStr, wxT( "SWAPRULE" ) );
1553
1554 return retval;
1555}
1556
1557
1559{
1560 wxASSERT( aNode->GetName() == wxT( "REUSEBLOCK" ) );
1561
1562 ID = GetXmlAttributeIDString( aNode, 0 );
1563 Name = GetXmlAttributeIDString( aNode, 1 );
1564 FileName = GetXmlAttributeIDString( aNode, 2 );
1565
1566 XNODE* cNode = aNode->GetChildren();
1567
1568 for( ; cNode; cNode = cNode->GetNext() )
1569 {
1570 wxString cNodeName = cNode->GetName();
1571
1572 if( cNodeName == wxT( "MIRROR" ) )
1573 Mirror = true;
1574 else if( cNodeName == wxT( "ORIENT" ) )
1575 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1576 else
1577 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "REUSEBLOCK" ) );
1578 }
1579}
1580
1581
1583{
1584 return ReuseBlockID == wxEmptyString && ItemReference == wxEmptyString;
1585}
1586
1587
1589{
1590 wxASSERT( aNode->GetName() == wxT( "REUSEBLOCKREF" ) );
1591
1594
1595 CheckNoChildNodes( aNode );
1596}
1597
1598
1600{
1601 wxASSERT( aNode->GetName() == wxT( "GROUP" ) );
1602
1603 ID = GetXmlAttributeIDString( aNode, 0 );
1604 Name = GetXmlAttributeIDString( aNode, 1 );
1605
1606 XNODE* cNode = aNode->GetChildren();
1607
1608 for( ; cNode; cNode = cNode->GetNext() )
1609 {
1610 wxString cNodeName = cNode->GetName();
1611
1612 if( cNodeName == wxT( "FIX" ) )
1613 Fixed = true;
1614 else if( cNodeName == wxT( "TRANSFER" ) )
1615 Transfer = true;
1616 else if( cNodeName == wxT( "GROUPREF" ) )
1617 GroupID = GetXmlAttributeIDString( cNode, 0 );
1618 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1619 ReuseBlockRef.Parse( cNode, aContext );
1620 else
1621 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "GROUP" ) );
1622 }
1623}
1624
1625
1627{
1628 wxASSERT( aNode->GetName() == wxT( "FIGURE" ) );
1629
1630 ID = GetXmlAttributeIDString( aNode, 0 );
1631 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1632 LayerID = GetXmlAttributeIDString( aNode, 2 );
1633
1634 XNODE* cNode = aNode->GetChildren();
1635 bool shapeIsInitialised = false; // Stop more than one Shape Object
1636 wxString location = wxString::Format( "Figure %s", ID );
1637
1638 if( !cNode )
1639 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1640
1641 for( ; cNode; cNode = cNode->GetNext() )
1642 {
1643 wxString cNodeName = cNode->GetName();
1644
1645 if( !shapeIsInitialised && Shape.IsShape( cNode ) )
1646 {
1647 Shape.Parse( cNode, aContext );
1648 shapeIsInitialised = true;
1649 }
1650 else if( cNodeName == wxT( "SWAPRULE" ) )
1651 {
1652 SwapRule = ParseSwapRule( cNode );
1653 }
1654 else if( cNodeName == wxT( "FIX" ) )
1655 {
1656 Fixed = true;
1657 }
1658 else if( cNodeName == wxT( "GROUPREF" ) )
1659 {
1660
1661 GroupID = GetXmlAttributeIDString( cNode, 0 );
1662 }
1663 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1664 {
1665 ReuseBlockRef.Parse( cNode, aContext );
1666 }
1667 else if( cNodeName == wxT( "ATTR" ) )
1668 {
1669 ATTRIBUTE_VALUE attr;
1670 attr.Parse( cNode, aContext );
1671 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1672 }
1673 else
1674 {
1676 }
1677 }
1678}
1679
1680
1682{
1683 Parse( aNode, aContext, true );
1684}
1685
1686
1688 bool aParseFields )
1689{
1690 wxASSERT( aNode->GetName() == wxT( "TEXT" ) );
1691
1692 ID = GetXmlAttributeIDString( aNode, 0 );
1693 Text = GetXmlAttributeIDString( aNode, 1 );
1694
1695 if( aParseFields )
1696 Text = ParseTextFields( Text, aContext );
1697
1698 TextCodeID = GetXmlAttributeIDString( aNode, 2 );
1699 LayerID = GetXmlAttributeIDString( aNode, 3 );
1700
1701 XNODE* cNode = aNode->GetChildren();
1702
1703 if( !cNode )
1704 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "TEXT" ) );
1705
1706 for( ; cNode; cNode = cNode->GetNext() )
1707 {
1708 wxString cNodeName = cNode->GetName();
1709
1710 if( cNodeName == wxT( "PT" ) )
1711 Position.Parse( cNode, aContext );
1712 else if( cNodeName == wxT( "ORIENT" ) )
1713 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1714 else if( cNodeName == wxT( "MIRROR" ) )
1715 Mirror = true;
1716 else if( cNodeName == wxT( "FIX" ) )
1717 Fixed = true;
1718 else if( cNodeName == wxT( "SWAPRULE" ) )
1719 SwapRule = ParseSwapRule( cNode );
1720 else if( cNodeName == wxT( "ALIGN" ) )
1721 Alignment = ParseAlignment( cNode );
1722 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1724 else if( cNodeName == wxT( "GROUPREF" ) )
1725 GroupID = GetXmlAttributeIDString( cNode, 0 );
1726 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1727 ReuseBlockRef.Parse( cNode, aContext );
1728 else
1729 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEXT" ) );
1730 }
1731}
1732
1733
1738
1739
1741{
1742 wxASSERT( aNode->GetName() == wxT( "SYMDEF" ) );
1743
1744 ID = GetXmlAttributeIDString( aNode, 0 );
1746 Alternate = GetXmlAttributeIDString( aNode, 2 );
1747}
1748
1749
1751{
1752 wxString cNodeName = aChildNode->GetName();
1753
1754 if( cNodeName == wxT( "PT" ) )
1755 {
1756 Origin.Parse( aChildNode, aContext );
1757 }
1758 else if( cNodeName == wxT( "STUB" ) )
1759 {
1760 Stub = true;
1761 }
1762 else if( cNodeName == wxT( "VERSION" ) )
1763 {
1764 Version = GetXmlAttributeIDLong( aChildNode, 0 );
1765 }
1766 else if( cNodeName == wxT( "FIGURE" ) )
1767 {
1768 FIGURE figure;
1769 figure.Parse( aChildNode, aContext );
1770 Figures.insert( std::make_pair( figure.ID, figure ) );
1771 }
1772 else if( cNodeName == wxT( "TEXT" ) )
1773 {
1774 TEXT txt;
1775 txt.Parse( aChildNode, aContext );
1776 Texts.insert( std::make_pair( txt.ID, txt ) );
1777 }
1778 else if( cNodeName == wxT( "TEXTLOC" ) )
1779 {
1780 TEXT_LOCATION textloc;
1781 textloc.Parse( aChildNode, aContext );
1782 TextLocations.insert( std::make_pair( textloc.AttributeID, textloc ) );
1783 }
1784 else if( cNodeName == wxT( "ATTR" ) )
1785 {
1786 ATTRIBUTE_VALUE attrVal;
1787 attrVal.Parse( aChildNode, aContext );
1788 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1789 }
1790 else
1791 {
1792 return false;
1793 }
1794
1795 return true;
1796}
1797
1798
1800{
1801 wxASSERT( aNode->GetName() == wxT( "GATEDEFINITION" ) );
1802
1803 ID = GetXmlAttributeIDString( aNode, 0 );
1804 Name = GetXmlAttributeIDString( aNode, 1 );
1805 Alternate = GetXmlAttributeIDString( aNode, 2 );
1806 PinCount = GetXmlAttributeIDLong( aNode, 3, true /* is required */ );
1807
1808 CheckNoChildNodes( aNode );
1809}
1810
1811
1813{
1814 wxASSERT( aNode->GetName() == wxT( "PINTYPE" ) );
1815
1816 wxString pinTypeStr = GetXmlAttributeIDString( aNode, 0 );
1817
1818 std::map<wxString, CADSTAR_PIN_TYPE> pinTypeMap = {
1819 { wxT( "INPUT" ), CADSTAR_PIN_TYPE::PIN_INPUT },
1820 { wxT( "OUTPUT_OR" ), CADSTAR_PIN_TYPE::OUTPUT_OR },
1821 { wxT( "OUTPUT_NOT_OR" ), CADSTAR_PIN_TYPE::OUTPUT_NOT_OR },
1822 { wxT( "OUTPUT_NOT_NORM_OR" ), CADSTAR_PIN_TYPE::OUTPUT_NOT_NORM_OR },
1823 { wxT( "POWER" ), CADSTAR_PIN_TYPE::POWER },
1824 { wxT( "GROUND" ), CADSTAR_PIN_TYPE::GROUND },
1825 { wxT( "TRISTATE_BIDIR" ), CADSTAR_PIN_TYPE::TRISTATE_BIDIR },
1826 { wxT( "TRISTATE_INPUT" ), CADSTAR_PIN_TYPE::TRISTATE_INPUT },
1827 { wxT( "TRISTATE_DRIVER" ), CADSTAR_PIN_TYPE::TRISTATE_DRIVER } };
1828
1829 if( pinTypeMap.find( pinTypeStr ) == pinTypeMap.end() )
1830 {
1831 WARN_UNKNOWN_PARAMETER_IO_ERROR( pinTypeStr, aNode->GetName() );
1833 }
1834
1835 return pinTypeMap[pinTypeStr];
1836}
1837
1838
1840{
1841 wxASSERT( aNode->GetName() == wxT( "PARTDEFINITIONPIN" ) );
1842
1843 ID = GetXmlAttributeIDLong( aNode, 0 );
1844
1845 XNODE* cNode = aNode->GetChildren();
1846
1847 for( ; cNode; cNode = cNode->GetNext() )
1848 {
1849 wxString cNodeName = cNode->GetName();
1850
1851 if( cNodeName == wxT( "PINNAME" ) )
1852 {
1853 Name = GetXmlAttributeIDString( cNode, 0 );
1854 }
1855 else if( cNodeName == wxT( "PINLABEL" ) )
1856 {
1857 Label = GetXmlAttributeIDString( cNode, 0 );
1858 }
1859 else if( cNodeName == wxT( "PINSIGNAL" ) )
1860 {
1861 Signal = GetXmlAttributeIDString( cNode, 0 );
1862 }
1863 else if( cNodeName == wxT( "PINTERM" ) )
1864 {
1866 TerminalPin = GetXmlAttributeIDLong( cNode, 1 );
1867 }
1868 else if( cNodeName == wxT( "PINTYPE" ) )
1869 {
1870 Type = GetPinType( cNode );
1871 }
1872 else if( cNodeName == wxT( "PINLOAD" ) )
1873 {
1874 Load = GetXmlAttributeIDLong( cNode, 0 );
1875 }
1876 else if( cNodeName == wxT( "PINPOSITION" ) )
1877 {
1879 }
1880 else if( cNodeName == wxT( "PINIDENTIFIER" ) )
1881 {
1882 Identifier = GetXmlAttributeIDString( cNode, 0 );
1883 }
1884 else
1885 {
1886 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1887 }
1888 }
1889}
1890
1891
1893{
1894 wxASSERT( aNode->GetName() == wxT( "PARTPIN" ) );
1895
1896 ID = GetXmlAttributeIDLong( aNode, 0 );
1897
1898 XNODE* cNode = aNode->GetChildren();
1899
1900 for( ; cNode; cNode = cNode->GetNext() )
1901 {
1902 wxString cNodeName = cNode->GetName();
1903
1904 if( cNodeName == wxT( "PINNAME" ) )
1905 Name = GetXmlAttributeIDString( cNode, 0 );
1906 else if( cNodeName == wxT( "PINTYPE" ) )
1907 Type = GetPinType( cNode );
1908 else if( cNodeName == wxT( "PINIDENTIFIER" ) )
1909 Identifier = GetXmlAttributeIDString( cNode, 0 );
1910 else
1911 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1912 }
1913}
1914
1915
1917 PARSER_CONTEXT* aContext )
1918{
1919 wxASSERT( aNode->GetName() == wxT( "PINEQUIVALENCE" ) );
1920
1921 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1922
1923 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1924 {
1925 if( !IsValidAttribute( xmlAttribute ) )
1926 continue;
1927
1928 long pinId;
1929
1930 if( !xmlAttribute->GetValue().ToLong( &pinId ) )
1931 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), aNode->GetName() );
1932
1933 PinIDs.push_back( (PART_DEFINITION_PIN_ID) pinId );
1934 }
1935
1936 CheckNoChildNodes( aNode );
1937}
1938
1939
1941 PARSER_CONTEXT* aContext )
1942{
1943 wxASSERT( aNode->GetName() == wxT( "SWAPGATE" ) );
1944
1945 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1946
1947 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1948 {
1949 if( !IsValidAttribute( xmlAttribute ) )
1950 continue;
1951
1952 long pinId;
1953
1954 if( !xmlAttribute->GetValue().ToLong( &pinId ) )
1955 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), aNode->GetName() );
1956
1957 PinIDs.push_back( (PART_DEFINITION_PIN_ID) pinId );
1958 }
1959
1960 CheckNoChildNodes( aNode );
1961}
1962
1963
1965 PARSER_CONTEXT* aContext )
1966{
1967 wxASSERT( aNode->GetName() == wxT( "SWAPGROUP" ) );
1968
1969 GateName = GetXmlAttributeIDString( aNode, 0 );
1970
1971 XNODE* cNode = aNode->GetChildren();
1972
1973 for( ; cNode; cNode = cNode->GetNext() )
1974 {
1975 wxString cNodeName = cNode->GetName();
1976
1977 if( cNodeName == wxT( "EXTERNAL" ) )
1978 {
1979 External = true;
1980 }
1981 else if( cNodeName == wxT( "SWAPGATE" ) )
1982 {
1983 SWAP_GATE swapGate;
1984 swapGate.Parse( cNode, aContext );
1985 SwapGates.push_back( swapGate );
1986 }
1987 else
1988 {
1989 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1990 }
1991 }
1992}
1993
1994
1996{
1997 wxASSERT( aNode->GetName() == wxT( "PARTDEFINITION" ) );
1998
1999 Name = GetXmlAttributeIDString( aNode, 0 );
2000
2001 XNODE* cNode = aNode->GetChildren();
2002
2003 for( ; cNode; cNode = cNode->GetNext() )
2004 {
2005 wxString cNodeName = cNode->GetName();
2006
2007 if( cNodeName == wxT( "HIDEPINNAMES" ) )
2008 {
2009 HidePinNames = true;
2010 }
2011 else if( cNodeName == wxT( "MAXPIN" ) )
2012 {
2013 MaxPinCount = GetXmlAttributeIDLong( cNode, 0 );
2014 }
2015 else if( cNodeName == wxT( "GATEDEFINITION" ) )
2016 {
2017 GATE gate;
2018 gate.Parse( cNode, aContext );
2019 GateSymbols.insert( std::make_pair( gate.ID, gate ) );
2020 }
2021 else if( cNodeName == wxT( "PARTDEFINITIONPIN" ) )
2022 {
2023 PIN pin;
2024 pin.Parse( cNode, aContext );
2025 Pins.insert( std::make_pair( pin.ID, pin ) );
2026 }
2027 else if( cNodeName == wxT( "ATTR" ) )
2028 {
2029 ATTRIBUTE_VALUE attr;
2030 attr.Parse( cNode, aContext );
2031 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2032 }
2033 else if( cNodeName == wxT( "PINEQUIVALENCE" ) )
2034 {
2035 PIN_EQUIVALENCE pinEq;
2036 pinEq.Parse( cNode, aContext );
2037 PinEquivalences.push_back( pinEq );
2038 }
2039 else if( cNodeName == wxT( "SWAPGROUP" ) )
2040 {
2041 SWAP_GROUP swapGroup;
2042 swapGroup.Parse( cNode, aContext );
2043 SwapGroups.push_back( swapGroup );
2044 }
2045 else
2046 {
2047 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2048 }
2049 }
2050}
2051
2052
2054{
2055 wxASSERT( aNode->GetName() == wxT( "PART" ) );
2056
2057 ID = GetXmlAttributeIDString( aNode, 0 );
2058 Name = GetXmlAttributeIDString( aNode, 1 );
2059
2060 XNODE* cNode = aNode->GetChildren();
2061
2062 for( ; cNode; cNode = cNode->GetNext() )
2063 {
2064 wxString cNodeName = cNode->GetName();
2065
2066 if( cNodeName == wxT( "VERSION" ) )
2067 {
2068 Version = GetXmlAttributeIDLong( cNode, 0 );
2069 }
2070 else if( cNodeName == wxT( "HIDEPINNAMES" ) )
2071 {
2072 HidePinNames = true;
2073 }
2074 else if( cNodeName == wxT( "PARTDEFINITION" ) )
2075 {
2076 Definition.Parse( cNode, aContext );
2077 }
2078 else if( cNodeName == wxT( "PARTPIN" ) )
2079 {
2080 PART_PIN pin;
2081 pin.Parse( cNode, aContext );
2082 PartPins.insert( std::make_pair( pin.ID, pin ) );
2083 }
2084 else if( cNodeName == wxT( "ATTR" ) )
2085 {
2086 ATTRIBUTE_VALUE attr;
2087 attr.Parse( cNode, aContext );
2088 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2089 }
2090 else
2091 {
2092 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2093 }
2094 }
2095}
2096
2097
2099{
2100 wxASSERT( aNode->GetName() == wxT( "PARTS" ) );
2101
2102 XNODE* cNode = aNode->GetChildren();
2103
2104 for( ; cNode; cNode = cNode->GetNext() )
2105 {
2106 wxString cNodeName = cNode->GetName();
2107
2108 if( cNodeName == wxT( "PART" ) )
2109 {
2110 PART part;
2111 part.Parse( cNode, aContext );
2112 PartDefinitions.insert( std::make_pair( part.ID, part ) );
2113 }
2114 else
2115 {
2116 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2117 }
2118
2119 aContext->CheckPointCallback();
2120 }
2121}
2122
2123
2125 PARSER_CONTEXT* aContext )
2126{
2127 wxASSERT( aNode->GetName() == wxT( "JPT" ) );
2128
2129 ID = GetXmlAttributeIDString( aNode, 0 );
2130 LayerID = GetXmlAttributeIDString( aNode, 1 );
2131}
2132
2133
2135 PARSER_CONTEXT* aContext )
2136{
2137 wxString cNodeName = aChildNode->GetName();
2138
2139 if( cNodeName == wxT( "PT" ) )
2140 Location.Parse( aChildNode, aContext );
2141 else if( cNodeName == wxT( "FIX" ) )
2142 Fixed = true;
2143 else if( cNodeName == wxT( "GROUPREF" ) )
2144 GroupID = GetXmlAttributeIDString( aChildNode, 0 );
2145 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2146 ReuseBlockRef.Parse( aChildNode, aContext );
2147 else
2148 return false;
2149
2150 return true;
2151}
2152
2153
2155{
2156 ParseIdentifiers( aNode, aContext );
2157 XNODE* cNode = aNode->GetChildren();
2158
2159 for( ; cNode; cNode = cNode->GetNext() )
2160 {
2161 if( ParseSubNode( cNode, aContext ) )
2162 continue;
2163 else
2164 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2165 }
2166}
2167
2168
2170 PARSER_CONTEXT* aContext )
2171{
2172 wxASSERT( aNode->GetName() == wxT( "CONN" ) );
2173
2174 StartNode = GetXmlAttributeIDString( aNode, 0 );
2175 EndNode = GetXmlAttributeIDString( aNode, 1 );
2177}
2178
2179
2181 PARSER_CONTEXT* aContext )
2182{
2183 wxString cNodeName = aChildNode->GetName();
2184
2185 if( cNodeName == wxT( "FIX" ) )
2186 {
2187 Fixed = true;
2188 }
2189 else if( cNodeName == wxT( "HIDDEN" ) )
2190 {
2191 Hidden = true;
2192 }
2193 else if( cNodeName == wxT( "GROUPREF" ) )
2194 {
2195 GroupID = GetXmlAttributeIDString( aChildNode, 0 );
2196 }
2197 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2198 {
2199 ReuseBlockRef.Parse( aChildNode, aContext );
2200 }
2201 else if( cNodeName == wxT( "ATTR" ) )
2202 {
2203 ATTRIBUTE_VALUE attrVal;
2204 attrVal.Parse( aChildNode, aContext );
2205 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
2206 }
2207 else
2208 {
2209 return false;
2210 }
2211
2212 return true;
2213}
2214
2215
2217{
2218 wxASSERT( aNode->GetName() == wxT( "NET" ) );
2219
2220 ID = GetXmlAttributeIDString( aNode, 0 );
2221}
2222
2223
2225{
2226 wxString cNodeName = aChildNode->GetName();
2227
2228 if( cNodeName == wxT( "NETCODE" ) )
2229 {
2230 RouteCodeID = GetXmlAttributeIDString( aChildNode, 0 );
2231 }
2232 else if( cNodeName == wxT( "SIGNAME" ) )
2233 {
2234 Name = GetXmlAttributeIDString( aChildNode, 0 );
2235 }
2236 else if( cNodeName == wxT( "SIGNUM" ) )
2237 {
2238 SignalNum = GetXmlAttributeIDLong( aChildNode, 0 );
2239 }
2240 else if( cNodeName == wxT( "HIGHLIT" ) )
2241 {
2242 Highlight = true;
2243 }
2244 else if( cNodeName == wxT( "JPT" ) )
2245 {
2246 JUNCTION jpt;
2247 jpt.Parse( aChildNode, aContext );
2248 Junctions.insert( std::make_pair( jpt.ID, jpt ) );
2249 }
2250 else if( cNodeName == wxT( "NETCLASSREF" ) )
2251 {
2252 NetClassID = GetXmlAttributeIDString( aChildNode, 0 );
2253 }
2254 else if( cNodeName == wxT( "SPACINGCLASS" ) )
2255 {
2256 SpacingClassID = GetXmlAttributeIDString( aChildNode, 0 );
2257 }
2258 else if( cNodeName == wxT( "ATTR" ) )
2259 {
2260 ATTRIBUTE_VALUE attrVal;
2261 attrVal.Parse( aChildNode, aContext );
2262 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
2263 }
2264 else
2265 {
2266 return false;
2267 }
2268
2269 return true;
2270}
2271
2272
2274{
2275 wxASSERT( aNode->GetName() == wxT( "DOCSYMBOL" ) );
2276
2277 ID = GetXmlAttributeIDString( aNode, 0 );
2278 SymdefID = GetXmlAttributeIDString( aNode, 1 );
2279 LayerID = GetXmlAttributeIDString( aNode, 2 );
2280
2281 XNODE* cNode = aNode->GetChildren();
2282 bool originParsed = false;
2283
2284 for( ; cNode; cNode = cNode->GetNext() )
2285 {
2286 wxString cNodeName = cNode->GetName();
2287
2288 if( !originParsed && cNodeName == wxT( "PT" ) )
2289 {
2290 Origin.Parse( cNode, aContext );
2291 originParsed = true;
2292 }
2293 else if( cNodeName == wxT( "GROUPREF" ) )
2294 {
2295 GroupID = GetXmlAttributeIDString( cNode, 0 );
2296 }
2297 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2298 {
2299 ReuseBlockRef.Parse( cNode, aContext );
2300 }
2301 else if( cNodeName == wxT( "FIX" ) )
2302 {
2303 Fixed = true;
2304 }
2305 else if( cNodeName == wxT( "MIRROR" ) )
2306 {
2307 Mirror = true;
2308 }
2309 else if( cNodeName == wxT( "READABILITY" ) )
2310 {
2311 Readability = ParseReadability( cNode );
2312 }
2313 else if( cNodeName == wxT( "ORIENT" ) )
2314 {
2315 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
2316 }
2317 else if( cNodeName == wxT( "ATTR" ) )
2318 {
2319 ATTRIBUTE_VALUE attr;
2320 attr.Parse( cNode, aContext );
2321 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2322 }
2323 else if( cNodeName == wxT( "SCALE" ) )
2324 {
2327 }
2328 else
2329 {
2330 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2331 }
2332 }
2333
2334 if( !originParsed )
2335 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
2336}
2337
2338
2340{
2341 wxASSERT( aNode->GetName() == wxT( "DFLTSETTINGS" ) );
2342
2343 Color = GetXmlAttributeIDString( aNode, 0 );
2344
2345 XNODE* cNode = aNode->GetChildren();
2346
2347 for( ; cNode; cNode = cNode->GetNext() )
2348 {
2349 wxString cNodeName = cNode->GetName();
2350
2351 if( cNodeName == wxT( "INVISIBLE" ) )
2352 {
2353 IsVisible = false;
2354 }
2355 else
2356 {
2357 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2358 }
2359 }
2360}
2361
2362
2364{
2365 wxASSERT( aNode->GetName() == wxT( "ATTRCOL" ) );
2366
2368 Color = GetXmlAttributeIDString( aNode, 1 );
2369
2370 XNODE* cNode = aNode->GetChildren();
2371
2372 for( ; cNode; cNode = cNode->GetNext() )
2373 {
2374 wxString cNodeName = cNode->GetName();
2375
2376 if( cNodeName == wxT( "INVISIBLE" ) )
2377 {
2378 IsVisible = false;
2379 }
2380 else if( cNodeName == wxT( "NOTPICKABLE" ) )
2381 {
2382 IsPickable = false;
2383 }
2384 else
2385 {
2386 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2387 }
2388 }
2389}
2390
2391
2393{
2394 wxASSERT( aNode->GetName() == wxT( "ATTRCOLORS" ) );
2395
2396 XNODE* cNode = aNode->GetChildren();
2397
2398 for( ; cNode; cNode = cNode->GetNext() )
2399 {
2400 wxString cNodeName = cNode->GetName();
2401
2402 if( cNodeName == wxT( "DFLTSETTINGS" ) )
2403 {
2404 DefaultSettings.Parse( cNode, aContext );
2405 }
2406 else if( cNodeName == wxT( "ATTRCOL" ) )
2407 {
2408 ATTRCOL attrcol;
2409 attrcol.Parse( cNode, aContext );
2410 AttributeColors.insert( { attrcol.AttributeID, attrcol } );
2411 }
2412 else if( cNodeName == wxT( "INVISIBLE" ) )
2413 {
2414 IsVisible = false;
2415 }
2416 else
2417 {
2418 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2419 }
2420 }
2421}
2422
2423
2425{
2426 wxASSERT( aNode->GetName() == wxT( "PARTNAMECOL" ) );
2427
2428 Color = GetXmlAttributeIDString( aNode, 0 );
2429
2430 XNODE* cNode = aNode->GetChildren();
2431
2432 for( ; cNode; cNode = cNode->GetNext() )
2433 {
2434 wxString cNodeName = cNode->GetName();
2435
2436 if( cNodeName == wxT( "INVISIBLE" ) )
2437 {
2438 IsVisible = false;
2439 }
2440 else if( cNodeName == wxT( "NOTPICKABLE" ) )
2441 {
2442 IsPickable = false;
2443 }
2444 else
2445 {
2446 WARN_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2447 }
2448 }
2449}
2450
2451
2453{
2454 static const wxString c_numAttributes = wxT( "numAttributes" );
2455
2456 wxString result;
2457 long numAttributes = 0;
2458
2459 if( aNode->GetAttribute( c_numAttributes, &result ) )
2460 {
2461 numAttributes = wxAtol( result );
2462 aNode->DeleteAttribute( c_numAttributes );
2463 ++numAttributes;
2464 }
2465
2466#if wxUSE_UNICODE_WCHAR
2467 std::wstring numAttrStr = std::to_wstring( numAttributes );
2468#else
2469 std::string numAttrStr = std::to_string( numAttributes );
2470#endif
2471
2472 aNode->AddAttribute( c_numAttributes, numAttrStr );
2473
2474 wxString paramName = wxT( "attr" );
2475 paramName << numAttrStr;
2476
2477 aNode->AddAttribute( paramName, aValue );
2478}
2479
2480
2482 const wxString& aFileTypeIdentifier,
2483 PROGRESS_REPORTER* aProgressReporter )
2484{
2485 KEYWORD emptyKeywords[1] = {};
2486 XNODE* rootNode = nullptr;
2487 XNODE* cNode = nullptr;
2488 XNODE* iNode = nullptr;
2489 int tok;
2490 bool cadstarFileCheckDone = false;
2491 wxString str;
2492 wxCSConv win1252( wxT( "windows-1252" ) );
2493 wxMBConv* conv = &win1252; // Initial testing suggests file encoding to be Windows-1252
2494 // More samples required.
2495
2496 // Open the file and get the file size
2497 FILE* fp = wxFopen( aFileName, wxT( "rt" ) );
2498
2499 if( !fp )
2500 THROW_IO_ERRORF( _( "Cannot open file '%s'" ), aFileName );
2501
2502 fseek( fp, 0L, SEEK_END );
2503 long fileSize = ftell( fp );
2504 rewind( fp );
2505
2506 DSNLEXER lexer( emptyKeywords, 0, nullptr, fp, aFileName );
2507
2508 auto currentProgress =
2509 [&]() -> double
2510 {
2511 return static_cast<double>( ftell( fp ) ) / fileSize;
2512 };
2513
2514 double previousReportedProgress = -1.0;
2515
2516 while( ( tok = lexer.NextTok() ) != DSN_EOF )
2517 {
2518 if( aProgressReporter && ( currentProgress() - previousReportedProgress ) > 0.01 )
2519 {
2520 if( !aProgressReporter->KeepRefreshing() )
2521 {
2522 delete rootNode;
2523
2525 }
2526
2527 aProgressReporter->SetCurrentProgress( currentProgress() );
2528 previousReportedProgress = currentProgress();
2529 }
2530
2531 if( tok == DSN_RIGHT )
2532 {
2533 cNode = iNode;
2534 if( cNode )
2535 {
2536 iNode = cNode->GetParent();
2537 }
2538 else
2539 {
2540 //too many closing brackets
2541 delete rootNode;
2542 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2543 }
2544 }
2545 else if( tok == DSN_LEFT )
2546 {
2547 tok = lexer.NextTok();
2548 str = wxString( lexer.CurText(), *conv );
2549 cNode = new XNODE( wxXML_ELEMENT_NODE, str );
2550
2551 if( !rootNode )
2552 rootNode = cNode;
2553
2554 if( iNode )
2555 {
2556 //we will add it as attribute as well as child node
2557 InsertAttributeAtEnd( iNode, str );
2558 iNode->AddChild( cNode );
2559 }
2560 else if( !cadstarFileCheckDone )
2561 {
2562 if( cNode->GetName() != aFileTypeIdentifier )
2563 {
2564 delete rootNode;
2565 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2566 }
2567
2568 cadstarFileCheckDone = true;
2569 }
2570
2571 iNode = cNode;
2572 }
2573 else if( iNode )
2574 {
2575 str = wxString( lexer.CurText(), *conv );
2576 //Insert even if string is empty
2577 InsertAttributeAtEnd( iNode, str );
2578 }
2579 else
2580 {
2581 //not enough closing brackets
2582 delete rootNode;
2583 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2584 }
2585 }
2586
2587 // Not enough closing brackets
2588 if( iNode != nullptr )
2589 {
2590 delete rootNode;
2591 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2592 }
2593
2594 // Throw if no data was parsed
2595 if( rootNode )
2596 {
2597 return rootNode;
2598 }
2599 else
2600 {
2601 delete rootNode;
2602 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2603 }
2604
2605 return nullptr;
2606}
2607
2608
2609bool CADSTAR_ARCHIVE_PARSER::IsValidAttribute( wxXmlAttribute* aAttribute )
2610{
2611 return aAttribute->GetName() != wxT( "numAttributes" );
2612}
2613
2614
2616 bool aIsRequired )
2617{
2618#if wxUSE_UNICODE_WCHAR
2619 std::wstring idStr = std::to_wstring( aID );
2620#else
2621 std::string idStr = std::to_string( aID );
2622#endif
2623
2624 wxString attrName = wxS( "attr" );
2625 attrName << idStr;
2626
2627 wxString retVal;
2628
2629 if( !aNode->GetAttribute( attrName, &retVal ) )
2630 {
2631 if( aIsRequired )
2632 THROW_MISSING_PARAMETER_IO_ERROR( std::to_string( aID ), aNode->GetName() );
2633 else
2634 return wxEmptyString;
2635 }
2636
2637 return retVal;
2638}
2639
2640
2641long CADSTAR_ARCHIVE_PARSER::GetXmlAttributeIDLong( XNODE* aNode, unsigned int aID, bool aIsRequired )
2642{
2643 long retVal;
2644 bool success = GetXmlAttributeIDString( aNode, aID, aIsRequired ).ToLong( &retVal );
2645
2646 if( !success )
2647 {
2648 if( aIsRequired )
2649 THROW_PARSING_IO_ERROR( std::to_string( aID ), aNode->GetName() );
2650 else
2651 return UNDEFINED_VALUE;
2652 }
2653
2654 return retVal;
2655}
2656
2657
2659{
2660 if( aNode && aNode->GetChildren() )
2661 WARN_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
2662}
2663
2664
2666{
2667 if( aNode && aNode->GetNext() )
2668 WARN_UNKNOWN_NODE_IO_ERROR( aNode->GetNext()->GetName(), aNode->GetParent()->GetName() );
2669}
2670
2671
2673 EVALUE& aValueToParse )
2674{
2675 if( aNode->GetChildren()->GetName() == wxT( "E" ) )
2676 aValueToParse.Parse( aNode->GetChildren(), aContext );
2677 else
2678 WARN_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
2679}
2680
2681
2682std::vector<CADSTAR_ARCHIVE_PARSER::POINT> CADSTAR_ARCHIVE_PARSER::ParseAllChildPoints(
2683 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes, int aExpectedNumPoints )
2684{
2685 std::vector<POINT> retVal;
2686
2687 XNODE* cNode = aNode->GetChildren();
2688
2689 for( ; cNode; cNode = cNode->GetNext() )
2690 {
2691 if( cNode->GetName() == wxT( "PT" ) )
2692 {
2693 POINT pt;
2694
2695 try
2696 {
2697 pt.Parse( cNode, aContext );
2698 }
2699 catch( const IO_ERROR& e )
2700 {
2701 reThrowWithParentContext( e, cNode, aNode );
2702 }
2703
2704 retVal.push_back( pt );
2705 }
2706 else if( aTestAllChildNodes )
2707 {
2708 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2709 }
2710 }
2711
2712 if( aExpectedNumPoints != UNDEFINED_VALUE && retVal.size() != static_cast<size_t>( aExpectedNumPoints ) )
2713 {
2714 THROW_IO_ERRORF( _( "Unexpected number of points in '%s'. Found %d but expected %d." ),
2715 aNode->GetName(),
2716 retVal.size(),
2717 aExpectedNumPoints );
2718 }
2719
2720 return retVal;
2721}
2722
2723
2724std::vector<CADSTAR_ARCHIVE_PARSER::VERTEX> CADSTAR_ARCHIVE_PARSER::ParseAllChildVertices(
2725 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes )
2726{
2727 std::vector<VERTEX> retVal;
2728
2729 XNODE* cNode = aNode->GetChildren();
2730
2731 for( ; cNode; cNode = cNode->GetNext() )
2732 {
2733 if( VERTEX::IsVertex( cNode ) )
2734 {
2735 VERTEX vertex;
2736
2737 try
2738 {
2739 vertex.Parse( cNode, aContext );
2740 }
2741 catch( const IO_ERROR& e )
2742 {
2743 reThrowWithParentContext( e, cNode, aNode );
2744 }
2745
2746 retVal.push_back( vertex );
2747 }
2748 else if( aTestAllChildNodes )
2749 {
2750 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2751 }
2752 }
2753
2754 return retVal;
2755}
2756
2757
2758std::vector<CADSTAR_ARCHIVE_PARSER::CUTOUT> CADSTAR_ARCHIVE_PARSER::ParseAllChildCutouts(
2759 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes )
2760{
2761 std::vector<CUTOUT> retVal;
2762
2763 XNODE* cNode = aNode->GetChildren();
2764
2765 for( ; cNode; cNode = cNode->GetNext() )
2766 {
2767 if( cNode->GetName() == wxT( "CUTOUT" ) )
2768 {
2769 CUTOUT cutout;
2770
2771 try
2772 {
2773 cutout.Parse( cNode, aContext );
2774 }
2775 catch( const IO_ERROR& e )
2776 {
2777 reThrowWithParentContext( e, cNode, aNode );
2778 }
2779
2780 retVal.push_back( cutout );
2781 }
2782 else if( aTestAllChildNodes )
2783 {
2784 WARN_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2785 }
2786 }
2787
2788 return retVal;
2789}
2790
2791
2793{
2794 XNODE* childNodes = aNode->GetChildren();
2795 long retval = 0;
2796
2797 for( ; childNodes; childNodes = childNodes->GetNext() )
2798 retval++;
2799
2800 return retval;
2801}
2802
2803
2805 XNODE* aRootNode, std::vector<wxString> aSubNodeChildrenToCount )
2806{
2807 XNODE* level1Node = aRootNode->GetChildren();
2808 long retval = 0;
2809
2810 for( ; level1Node; level1Node = level1Node->GetNext() )
2811 {
2812 for( wxString childNodeName : aSubNodeChildrenToCount )
2813 {
2814 if( level1Node->GetName() == childNodeName )
2815 retval += GetNumberOfChildNodes( level1Node );
2816 }
2817
2818 retval++;
2819 }
2820
2821 return retval;
2822}
2823
2824
2825wxString CADSTAR_ARCHIVE_PARSER::HandleTextOverbar( wxString aCadstarString )
2826{
2827 wxString escapedText = aCadstarString;
2828
2829 escapedText.Replace( wxT( "'" ), wxT( "~" ) );
2830
2831 return ConvertToNewOverbarNotation( escapedText );
2832}
2833
2834
2836{
2837 if( !aKiCadTextItem->GetText().IsEmpty() )
2838 {
2839 VECTOR2I positionOffset( 0, aKiCadTextItem->GetInterline( nullptr ) );
2840 RotatePoint( positionOffset, aKiCadTextItem->GetTextAngle() );
2841
2842 //Count num of additional lines
2843 wxString text = aKiCadTextItem->GetText();
2844 int numExtraLines = text.Replace( "\n", "\n" );
2845 numExtraLines -= text.at( text.size() - 1 ) == '\n'; // Ignore new line character at end
2846 positionOffset.x *= numExtraLines;
2847 positionOffset.y *= numExtraLines;
2848
2849 aKiCadTextItem->Offset( positionOffset );
2850 }
2851}
2852
2853
2854wxString CADSTAR_ARCHIVE_PARSER::generateLibName( const wxString& aRefName,
2855 const wxString& aAlternateName )
2856{
2857 if( aAlternateName.IsEmpty() )
2858 return EscapeString( aRefName, CTX_LIBID );
2859 else
2860 return EscapeString( aRefName + wxT( " (" ) + aAlternateName + wxT( ")" ), CTX_LIBID );
2861}
2862
2863
2865{
2866 if( m_progressReporter )
2867 {
2868 m_progressReporter->AdvanceProgress();
2869
2870 if( !m_progressReporter->KeepRefreshing() )
2872 }
2873}
CADSTAR_PIN_POSITION
Positioning of pin names can be in one of four quadrants.
@ 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:415
int NextTok()
Return the next token found in the input file or DSN_EOF when reaching the end of file.
Definition dsnlexer.cpp:544
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition eda_text.h:94
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition eda_text.h:118
virtual void Offset(const VECTOR2I &aOffset)
Definition eda_text.cpp:575
virtual EDA_ANGLE GetTextAngle() const
Definition eda_text.h:178
int GetInterline(const RENDER_SETTINGS *aSettings) const
Return the distance between two lines of text.
Definition eda_text.cpp:747
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
#define THROW_IO_ERRORF(msg,...)
#define THROW_IO_CANCELLED()
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)
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
SHAPE Shape
Uses the component's coordinate frame if within a component definition, otherwise uses the design's c...
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.
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 subnode="NETCLASSREF".
SPACING_CLASS_ID SpacingClassID
The net might not have a spacing class, in which case it will be wxEmptyString subnode="SPACINGCLASS"...
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.
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.
TERMINAL_ID TerminalPin
(subnode="PINTERM", param1)
wxString Identifier
This should match a pad identifier in the component footprint.
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.
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, defaults to equal height (1:1 aspect r...
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:227
VECTOR2< int32_t > VECTOR2I
Definition vector2d.h:708