KiCad PCB EDA Suite
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 (C) 2020-2021 KiCad Developers, see AUTHORS.txt for contributors.
6 *
7 * This program is free software: you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program. If not, see <http://www.gnu.org/licenses/>.
19 */
20
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// Ratio derived from CADSTAR default font. See doxygen comment in cadstar_archive_parser.h
40const double CADSTAR_ARCHIVE_PARSER::TXT_HEIGHT_RATIO = ( 24.0 - 5.0 ) / 24.0;
41
42// Cadstar fields and their KiCad equivalent
43const std::map<CADSTAR_ARCHIVE_PARSER::TEXT_FIELD_NAME, wxString>
45 { { TEXT_FIELD_NAME::DESIGN_TITLE, wxT( "DESIGN_TITLE" ) },
46 { TEXT_FIELD_NAME::SHORT_JOBNAME, wxT( "SHORT_JOBNAME" ) },
47 { TEXT_FIELD_NAME::LONG_JOBNAME, wxT( "LONG_JOBNAME" ) },
48 { TEXT_FIELD_NAME::NUM_OF_SHEETS, wxT( "##" ) },
49 { TEXT_FIELD_NAME::SHEET_NUMBER, wxT( "#" ) },
50 { TEXT_FIELD_NAME::SHEET_NAME, wxT( "SHEETNAME" ) },
51 { TEXT_FIELD_NAME::VARIANT_NAME, wxT( "VARIANT_NAME" ) },
52 { TEXT_FIELD_NAME::VARIANT_DESCRIPTION, wxT( "VARIANT_DESCRIPTION" ) },
53 { TEXT_FIELD_NAME::REG_USER, wxT( "REG_USER" ) },
54 { TEXT_FIELD_NAME::COMPANY_NAME, wxT( "COMPANY_NAME" ) },
55 { TEXT_FIELD_NAME::CURRENT_USER, wxT( "CURRENT_USER" ) },
56 { TEXT_FIELD_NAME::DATE, wxT( "DATE" ) },
57 { TEXT_FIELD_NAME::TIME, wxT( "TIME" ) },
58 { TEXT_FIELD_NAME::MACHINE_NAME, wxT( "MACHINE_NAME" ) } };
59
60
62{
63 wxASSERT( aNode->GetName() == wxT( "FORMAT" ) );
64
65 Type = GetXmlAttributeIDString( aNode, 0 );
66 SomeInt = GetXmlAttributeIDLong( aNode, 1 );
67 Version = GetXmlAttributeIDLong( aNode, 2 );
68}
69
70
72{
73 wxASSERT( aNode->GetName() == wxT( "TIMESTAMP" ) );
74
75 if( !GetXmlAttributeIDString( aNode, 0 ).ToLong( &Year )
76 || !GetXmlAttributeIDString( aNode, 1 ).ToLong( &Month )
77 || !GetXmlAttributeIDString( aNode, 2 ).ToLong( &Day )
78 || !GetXmlAttributeIDString( aNode, 3 ).ToLong( &Hour )
79 || !GetXmlAttributeIDString( aNode, 4 ).ToLong( &Minute )
80 || !GetXmlAttributeIDString( aNode, 5 ).ToLong( &Second ) )
81 THROW_PARSING_IO_ERROR( wxT( "TIMESTAMP" ), wxString::Format( "HEADER" ) );
82}
83
84
86{
87 wxASSERT( aNode->GetName() == wxT( "HEADER" ) );
88
89 XNODE* cNode = aNode->GetChildren();
90
91 for( ; cNode; cNode = cNode->GetNext() )
92 {
93 wxString nodeName = cNode->GetName();
94
95 if( nodeName == wxT( "FORMAT" ) )
96 {
97 Format.Parse( cNode, aContext );
98 }
99 else if( nodeName == wxT( "JOBFILE" ) )
100 {
101 JobFile = GetXmlAttributeIDString( cNode, 0 );
102 }
103 else if( nodeName == wxT( "JOBTITLE" ) )
104 {
105 JobTitle = GetXmlAttributeIDString( cNode, 0 );
106 }
107 else if( nodeName == wxT( "GENERATOR" ) )
108 {
109 Generator = GetXmlAttributeIDString( cNode, 0 );
110 }
111 else if( nodeName == wxT( "RESOLUTION" ) )
112 {
113 XNODE* subNode = cNode->GetChildren();
114
115 if( ( subNode->GetName() == wxT( "METRIC" ) )
116 && ( GetXmlAttributeIDString( subNode, 0 ) == wxT( "HUNDREDTH" ) )
117 && ( GetXmlAttributeIDString( subNode, 1 ) == wxT( "MICRON" ) ) )
118 {
119 Resolution = RESOLUTION::HUNDREDTH_MICRON;
120 }
121 else
122 {
123 // TODO Need to find out if there are other possible resolutions. Logically
124 // there must be other base units that could be used, such as "IMPERIAL INCH"
125 // or "METRIC MM" but so far none of settings in CADSTAR generated a different
126 // output resolution to "HUNDREDTH MICRON"
127 THROW_UNKNOWN_NODE_IO_ERROR( subNode->GetName(), wxT( "HEADER->RESOLUTION" ) );
128 }
129 }
130 else if( nodeName == wxT( "TIMESTAMP" ) )
131 {
132 Timestamp.Parse( cNode, aContext );
133 }
134 else
135 {
136 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "HEADER" ) );
137 }
138 }
139}
140
141
143{
144 wxASSERT( aNode->GetName() == wxT( "VMASTER" ) || aNode->GetName() == wxT( "VARIANT" ) );
145
146 ID = GetXmlAttributeIDString( aNode, 0 );
147
148 if( aNode->GetName() == wxT( "VMASTER" ) )
149 {
150 Name = GetXmlAttributeIDString( aNode, 1 );
151 Description = GetXmlAttributeIDString( aNode, 2 );
152 }
153 else
154 {
155 ParentID = GetXmlAttributeIDString( aNode, 1 );
156 Name = GetXmlAttributeIDString( aNode, 2 );
157 Description = GetXmlAttributeIDString( aNode, 3 );
158 }
159}
160
161
163{
164 wxASSERT( aNode->GetName() == wxT( "VHIERARCHY" ) );
165
166 XNODE* cNode = aNode->GetChildren();
167
168 for( ; cNode; cNode = cNode->GetNext() )
169 {
170 if( cNode->GetName() == wxT( "VMASTER" ) || cNode->GetName() == wxT( "VARIANT" ) )
171 {
172 VARIANT variant;
173 variant.Parse( cNode, aContext );
174 Variants.insert( std::make_pair( variant.ID, variant ) );
175 }
176 else
177 {
178 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), cNode->GetName() );
179 }
180 }
181}
182
183
185{
186 wxASSERT( aNode->GetName() == wxT( "LINECODE" ) );
187
188 ID = GetXmlAttributeIDString( aNode, 0 );
189 Name = GetXmlAttributeIDString( aNode, 1 );
190
191 if( !GetXmlAttributeIDString( aNode, 2 ).ToLong( &Width ) )
192 THROW_PARSING_IO_ERROR( wxT( "Line Width" ), wxString::Format( "LINECODE -> %s", Name ) );
193
194 XNODE* cNode = aNode->GetChildren();
195
196 if( cNode->GetName() != wxT( "STYLE" ) )
197 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxString::Format( "LINECODE -> %s", Name ) );
198
199 wxString styleStr = GetXmlAttributeIDString( cNode, 0 );
200
201 if( styleStr == wxT( "SOLID" ) )
202 {
203 Style = LINESTYLE::SOLID;
204 }
205 else if( styleStr == wxT( "DASH" ) )
206 {
207 Style = LINESTYLE::DASH;
208 }
209 else if( styleStr == wxT( "DASHDOT" ) )
210 {
211 Style = LINESTYLE::DASHDOT;
212 }
213 else if( styleStr == wxT( "DASHDOTDOT" ) )
214 {
215 Style = LINESTYLE::DASHDOTDOT;
216 }
217 else if( styleStr == wxT( "DOT" ) )
218 {
219 Style = LINESTYLE::DOT;
220 }
221 else
222 {
223 THROW_UNKNOWN_PARAMETER_IO_ERROR( wxString::Format( "STYLE %s", styleStr ),
224 wxString::Format( "LINECODE -> %s", Name ) );
225 }
226}
227
228
230{
231 wxASSERT( aNode->GetName() == wxT( "HATCH" ) );
232
233 Step = GetXmlAttributeIDLong( aNode, 0 );
234 LineWidth = GetXmlAttributeIDLong( aNode, 2 );
235
236 XNODE* cNode = aNode->GetChildren();
237
238 if( !cNode || cNode->GetName() != wxT( "ORIENT" ) )
239 THROW_MISSING_NODE_IO_ERROR( wxT( "ORIENT" ), wxT( "HATCH" ) );
240
241 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
242}
243
244
246{
247 wxASSERT( aNode->GetName() == wxT( "HATCHCODE" ) );
248
249 ID = GetXmlAttributeIDString( aNode, 0 );
250 Name = GetXmlAttributeIDString( aNode, 1 );
251
252 XNODE* cNode = aNode->GetChildren();
253 wxString location = wxString::Format( "HATCHCODE -> %s", Name );
254
255 for( ; cNode; cNode = cNode->GetNext() )
256 {
257 if( cNode->GetName() != wxT( "HATCH" ) )
258 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), location );
259
260 HATCH hatch;
261 hatch.Parse( cNode, aContext );
262 Hatches.push_back( hatch );
263 }
264}
265
266
268{
269 wxASSERT( aNode->GetName() == wxT( "FONT" ) );
270
271 Name = GetXmlAttributeIDString( aNode, 0 );
272 Modifier1 = GetXmlAttributeIDLong( aNode, 1 );
273 Modifier2 = GetXmlAttributeIDLong( aNode, 2 );
274
275 XNODE* cNode = aNode->GetChildren();
276
277 for( ; cNode; cNode = cNode->GetNext() )
278 {
279 wxString cNodeName = cNode->GetName();
280
281 if( cNodeName == wxT( "ITALIC" ) )
282 Italic = true;
283 else if( cNodeName == wxT( "KERNING" ) )
284 KerningPairs = true;
285 else
286 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
287 }
288}
289
290
292{
293 wxASSERT( aNode->GetName() == wxT( "TEXTCODE" ) );
294
295 ID = GetXmlAttributeIDString( aNode, 0 );
296 Name = GetXmlAttributeIDString( aNode, 1 );
297
298 LineWidth = GetXmlAttributeIDLong( aNode, 2 );
299 Height = GetXmlAttributeIDLong( aNode, 3 );
300 Width = GetXmlAttributeIDLong( aNode, 4 );
301
302 XNODE* cNode = aNode->GetChildren();
303
304 if( cNode )
305 {
306 if( cNode->GetName() == wxT( "FONT" ) )
307 Font.Parse( cNode, aContext );
308 else
309 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
310 }
311}
312
313
315{
316 wxASSERT( aNode->GetName() == wxT( "ROUTEREASSIGN" ) );
317
318 LayerID = GetXmlAttributeIDString( aNode, 0 );
319 OptimalWidth = GetXmlAttributeIDLong( aNode, 1, false );
320
321 XNODE* cNode = aNode->GetChildren();
322
323 for( ; cNode; cNode = cNode->GetNext() )
324 {
325 wxString cNodeName = cNode->GetName();
326
327 if( cNodeName == wxT( "NECKWIDTH" ) )
328 NeckedWidth = GetXmlAttributeIDLong( cNode, 0 );
329 else if( cNodeName == wxT( "SROUTEWIDTH" ) )
330 OptimalWidth = GetXmlAttributeIDLong( cNode, 0 );
331 else if( cNodeName == wxT( "MINWIDTH" ) )
332 MinWidth = GetXmlAttributeIDLong( cNode, 0 );
333 else if( cNodeName == wxT( "MAXWIDTH" ) )
334 MaxWidth = GetXmlAttributeIDLong( cNode, 0 );
335 else
336 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
337 }
338}
339
340
342{
343 wxASSERT( aNode->GetName() == wxT( "ROUTECODE" ) );
344
345 ID = GetXmlAttributeIDString( aNode, 0 );
346 Name = GetXmlAttributeIDString( aNode, 1 );
347 OptimalWidth = GetXmlAttributeIDLong( aNode, 2, false );
348
349 XNODE* cNode = aNode->GetChildren();
350
351 for( ; cNode; cNode = cNode->GetNext() )
352 {
353 wxString cNodeName = cNode->GetName();
354
355 if( cNodeName == wxT( "NECKWIDTH" ) )
356 {
357 NeckedWidth = GetXmlAttributeIDLong( cNode, 0 );
358 }
359 else if( cNodeName == wxT( "SROUTEWIDTH" ) )
360 {
361 OptimalWidth = GetXmlAttributeIDLong( cNode, 0 );
362 }
363 else if( cNodeName == wxT( "MINWIDTH" ) )
364 {
365 MinWidth = GetXmlAttributeIDLong( cNode, 0 );
366 }
367 else if( cNodeName == wxT( "MAXWIDTH" ) )
368 {
369 MaxWidth = GetXmlAttributeIDLong( cNode, 0 );
370 }
371 else if( cNodeName == wxT( "ROUTEREASSIGN" ) )
372 {
373 ROUTEREASSIGN routereassign;
374 routereassign.Parse( cNode, aContext );
375 RouteReassigns.push_back( routereassign );
376 }
377 else
378 {
379 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
380 }
381 }
382}
383
384
386{
387 return Base * std::pow( 10.0, Exponent );
388}
389
390
392{
393 wxASSERT( aNode->GetName() == wxT( "E" ) );
394
395 if( ( !GetXmlAttributeIDString( aNode, 0 ).ToLong( &Base ) )
396 || ( !GetXmlAttributeIDString( aNode, 1 ).ToLong( &Exponent ) ) )
397 {
398 THROW_PARSING_IO_ERROR( wxT( "Base and Exponent" ),
400 "%s->%s", aNode->GetParent()->GetName(), aNode->GetParent()->GetName() ) );
401 }
402}
403
404
406{
407 wxASSERT( aNode->GetName() == wxT( "PT" ) );
408
409 x = GetXmlAttributeIDLong( aNode, 0 );
410 y = GetXmlAttributeIDLong( aNode, 1 );
411}
412
413
415{
416 wxASSERT( aNode->GetName() == wxT( "PT" ) );
417
418 x = GetXmlAttributeIDLong( aNode, 0 );
419 y = GetXmlAttributeIDLong( aNode, 1 );
420}
421
422
424{
425 wxString aNodeName = aNode->GetName();
426
427 if( aNodeName == wxT( "PT" ) || aNodeName == wxT( "ACWARC" ) || aNodeName == wxT( "CWARC" )
428 || aNodeName == wxT( "CWSEMI" ) || aNodeName == wxT( "ACWSEMI" ) )
429 {
430 return true;
431 }
432 else
433 {
434 return false;
435 }
436}
437
438
440{
441 wxASSERT( IsVertex( aNode ) );
442
443 wxString aNodeName = aNode->GetName();
444
445 if( aNodeName == wxT( "PT" ) )
446 {
447 Type = VERTEX_TYPE::POINT;
450 End.Parse( aNode, aContext );
451 }
452 else if( aNodeName == wxT( "ACWARC" ) || aNodeName == wxT( "CWARC" ) )
453 {
454 if( aNodeName == wxT( "ACWARC" ) )
456 else
458
459 std::vector<POINT> pts = ParseAllChildPoints( aNode, aContext, true, 2 );
460
461 Center = pts[0];
462 End = pts[1];
463 }
464 else if( aNodeName == wxT( "ACWSEMI" ) || aNodeName == wxT( "CWSEMI" ) )
465 {
466 if( aNodeName == wxT( "ACWSEMI" ) )
468 else
470
473
474 std::vector<POINT> pts = ParseAllChildPoints( aNode, aContext, true, 1 );
475
476 End = pts[0];
477 }
478 else
479 {
480 wxASSERT_MSG( true, wxT( "Unknown VERTEX type" ) );
481 }
482}
483
484
486 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
487 double aAccuracy ) const
488{
489 VECTOR2I endPoint = aCadstarToKicadPointCallback( End );
490
491 if( Type == VERTEX_TYPE::POINT )
492 {
493 aChainToAppendTo->Append( endPoint );
494 return;
495 }
496
497 wxCHECK_MSG( aChainToAppendTo->PointCount() > 0, /*void*/,
498 "Can't append an arc to vertex to an empty chain" );
499
500 VECTOR2I startPoint = aChainToAppendTo->GetPoint( -1 );
501 VECTOR2I centerPoint;
502
504 centerPoint = ( startPoint / 2 ) + ( endPoint / 2 );
505 else
506 centerPoint = aCadstarToKicadPointCallback( Center );
507
508 bool clockwise = Type == VERTEX_TYPE::CLOCKWISE_ARC
510
511 // A bit of a hack to figure out if we need to invert clockwise due to the transform
512 VECTOR2I transform = aCadstarToKicadPointCallback( { 500, 500 } )
513 - aCadstarToKicadPointCallback( { 0, 0 } );
514
515 if( ( transform.x > 0 && transform.y < 0 ) || ( transform.x < 0 && transform.y > 0 ) )
516 clockwise = !clockwise;
517
518 SHAPE_ARC arc;
519 arc.ConstructFromStartEndCenter( startPoint, endPoint, centerPoint, clockwise );
520
521 aChainToAppendTo->Append( arc, aAccuracy );
522}
523
524
526{
527 wxASSERT( aNode->GetName() == wxT( "CUTOUT" ) );
528
529 Vertices = ParseAllChildVertices( aNode, aContext, true );
530}
531
532
534{
535 wxString aNodeName = aNode->GetName();
536
537 if( aNodeName == wxT( "OPENSHAPE" ) || aNodeName == wxT( "OUTLINE" )
538 || aNodeName == wxT( "SOLID" ) || aNodeName == wxT( "HATCHED" ) )
539 {
540 return true;
541 }
542 else
543 {
544 return false;
545 }
546}
547
548
550{
551 wxASSERT( IsShape( aNode ) );
552
553 wxString aNodeName = aNode->GetName();
554
555 if( aNodeName == wxT( "OPENSHAPE" ) )
556 {
558 Vertices = ParseAllChildVertices( aNode, aContext, true );
559 Cutouts.clear();
560 HatchCodeID = wxEmptyString;
561 }
562 else if( aNodeName == wxT( "OUTLINE" ) )
563 {
564 Type = SHAPE_TYPE::OUTLINE;
565 Vertices = ParseAllChildVertices( aNode, aContext, false );
566 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
567 HatchCodeID = wxEmptyString;
568 }
569 else if( aNodeName == wxT( "SOLID" ) )
570 {
571 Type = SHAPE_TYPE::SOLID;
572 Vertices = ParseAllChildVertices( aNode, aContext, false );
573 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
574 HatchCodeID = wxEmptyString;
575 }
576 else if( aNodeName == wxT( "HATCHED" ) )
577 {
578 Type = SHAPE_TYPE::HATCHED;
579 Vertices = ParseAllChildVertices( aNode, aContext, false );
580 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
581 HatchCodeID = GetXmlAttributeIDString( aNode, 0 );
582 }
583 else
584 {
585 wxASSERT_MSG( true, wxT( "Unknown SHAPE type" ) );
586 }
587}
588
590 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
591 double aAccuracy ) const
592{
593 SHAPE_LINE_CHAIN outline;
594
595 if( Vertices.size() == 0 )
596 return outline;
597
598 for( const auto& vertex : Vertices )
599 vertex.AppendToChain( &outline, aCadstarToKicadPointCallback, aAccuracy );
600
601 if( Type != SHAPE_TYPE::OPENSHAPE )
602 {
603 outline.SetClosed( true );
604
605 // Append after closing, to ensre first and last point remain the same
606 Vertices.at( 0 ).AppendToChain( &outline, aCadstarToKicadPointCallback, aAccuracy );
607 }
608
609 return outline;
610}
611
612
614 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
615 double aAccuracy ) const
616{
617 SHAPE_POLY_SET polyset;
618
619 wxCHECK( Type != SHAPE_TYPE::OPENSHAPE, polyset ); // We shouldn't convert openshapes to polyset!
620
621 polyset.AddOutline( OutlineAsChain( aCadstarToKicadPointCallback, aAccuracy ) );
622
623 for( const auto& cutout : Cutouts )
624 {
625 SHAPE_LINE_CHAIN hole;
626
627 if( cutout.Vertices.size() == 0 )
628 continue;
629
630 for( const auto& cutoutVertex : cutout.Vertices )
631 cutoutVertex.AppendToChain( &hole, aCadstarToKicadPointCallback, aAccuracy );
632
633 hole.SetClosed( true );
634
635 // Append after closing, to ensre first and last point remain the same
636 cutout.Vertices.at( 0 ).AppendToChain( &hole, aCadstarToKicadPointCallback, aAccuracy );
637
638 polyset.AddHole( hole );
639 }
640
641 return polyset;
642}
643
644
646{
647 wxASSERT( aNode->GetName() == wxT( "UNITS" ) );
648
649 wxString unit = GetXmlAttributeIDString( aNode, 0 );
650
651 if( unit == wxT( "CENTIMETER" ) )
652 return UNITS::CENTIMETER;
653 else if( unit == wxT( "INCH" ) )
654 return UNITS::INCH;
655 else if( unit == wxT( "METER" ) )
656 return UNITS::METER;
657 else if( unit == wxT( "MICROMETRE" ) )
658 return UNITS::MICROMETRE;
659 else if( unit == wxT( "MM" ) )
660 return UNITS::MM;
661 else if( unit == wxT( "THOU" ) )
662 return UNITS::THOU;
663 else if( unit == wxT( "DESIGN" ) )
664 return UNITS::DESIGN;
665 else
666 THROW_UNKNOWN_PARAMETER_IO_ERROR( unit, wxT( "UNITS" ) );
667
668 return UNITS();
669}
670
671
673{
674 wxASSERT( aNode->GetName() == wxT( "ANGUNITS" ) );
675
676 wxString angUnitStr = GetXmlAttributeIDString( aNode, 0 );
677
678 if( angUnitStr == wxT( "DEGREES" ) )
679 return ANGUNITS::DEGREES;
680 else if( angUnitStr == wxT( "RADIANS" ) )
681 return ANGUNITS::RADIANS;
682 else
683 THROW_UNKNOWN_PARAMETER_IO_ERROR( angUnitStr, aNode->GetName() );
684
685 return ANGUNITS();
686}
687
688
690{
691 wxString aNodeName = aNode->GetName();
692
693 if( aNodeName == wxT( "FRACTIONALGRID" ) || aNodeName == wxT( "STEPGRID" ) )
694 return true;
695 else
696 return false;
697}
698
699
701{
702 wxASSERT( IsGrid( aNode ) );
703
704 wxString aNodeName = aNode->GetName();
705
706 if( aNodeName == wxT( "FRACTIONALGRID" ) )
708 else if( aNodeName == wxT( "STEPGRID" ) )
709 Type = GRID_TYPE::STEPGRID;
710 else
711 wxASSERT_MSG( true, wxT( "Unknown Grid Type" ) );
712
713 Name = GetXmlAttributeIDString( aNode, 0 );
714 Param1 = GetXmlAttributeIDLong( aNode, 1 );
715 Param2 = GetXmlAttributeIDLong( aNode, 2 );
716}
717
718
720{
721 wxASSERT( aNode->GetName() == wxT( "GRIDS" ) );
722
723 XNODE* cNode = aNode->GetChildren();
724
725 for( ; cNode; cNode = cNode->GetNext() )
726 {
727 wxString cNodeName = cNode->GetName();
728
729 if( cNodeName == wxT( "WORKINGGRID" ) )
730 {
731 XNODE* workingGridNode = cNode->GetChildren();
732
733 if( !GRID::IsGrid( workingGridNode ) )
734 {
736 workingGridNode->GetName(), wxT( "GRIDS -> WORKINGGRID" ) );
737 }
738 else
739 {
740 WorkingGrid.Parse( workingGridNode, aContext );
741 }
742 }
743 else if( cNodeName == wxT( "SCREENGRID" ) )
744 {
745 XNODE* screenGridNode = cNode->GetChildren();
746
747 if( !GRID::IsGrid( screenGridNode ) )
748 {
750 screenGridNode->GetName(), wxT( "GRIDS -> SCREENGRID" ) );
751 }
752 else
753 {
754 ScreenGrid.Parse( screenGridNode, aContext );
755 }
756 }
757 else if( GRID::IsGrid( cNode ) )
758 {
759 GRID userGrid;
760 userGrid.Parse( cNode, aContext );
761 UserGrids.push_back( userGrid );
762 }
763 }
764}
765
766
768{
769 wxString cNodeName = aChildNode->GetName();
770
771 if( cNodeName == wxT( "UNITS" ) )
772 {
773 Units = ParseUnits( aChildNode );
774 }
775 else if( cNodeName == wxT( "UNITSPRECISION" ) )
776 {
777 UnitDisplPrecision = GetXmlAttributeIDLong( aChildNode, 0 );
778 }
779 else if( cNodeName == wxT( "INTERLINEGAP" ) )
780 {
781 InterlineGap = GetXmlAttributeIDLong( aChildNode, 0 );
782 }
783 else if( cNodeName == wxT( "BARLINEGAP" ) )
784 {
785 BarlineGap = GetXmlAttributeIDLong( aChildNode, 0 );
786 }
787 else if( cNodeName == wxT( "ALLOWBARTEXT" ) )
788 {
789 AllowBarredText = true;
790 }
791 else if( cNodeName == wxT( "ANGULARPRECISION" ) )
792 {
793 AngularPrecision = GetXmlAttributeIDLong( aChildNode, 0 );
794 }
795 else if( cNodeName == wxT( "DESIGNORIGIN" ) )
796 {
797 DesignOrigin.Parse( aChildNode->GetChildren(), aContext );
798 }
799 else if( cNodeName == wxT( "DESIGNAREA" ) )
800 {
801 std::vector<POINT> pts = ParseAllChildPoints( aChildNode, aContext, true, 2 );
802 DesignArea = std::make_pair( pts[0], pts[1] );
803 }
804 else if( cNodeName == wxT( "DESIGNREF" ) )
805 {
806 DesignOrigin.Parse( aChildNode->GetChildren(), aContext );
807 }
808 else if( cNodeName == wxT( "DESIGNLIMIT" ) )
809 {
810 DesignLimit.Parse( aChildNode->GetChildren(), aContext );
811 }
812 else
813 {
814 return false;
815 }
816
817 return true;
818}
819
820
822{
823 wxASSERT( aNode->GetName() == wxT( "SETTINGS" ) );
824
825 XNODE* cNode = aNode->GetChildren();
826
827 for( ; cNode; cNode = cNode->GetNext() )
828 {
829 wxString cNodeName = cNode->GetName();
830
831 if( ParseSubNode( cNode, aContext ) )
832 continue;
833 else
834 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "SETTINGS" ) );
835 }
836}
837
838
839wxString CADSTAR_ARCHIVE_PARSER::ParseTextFields( const wxString& aTextString,
840 PARSER_CONTEXT* aContext )
841{
842 static const std::map<TEXT_FIELD_NAME, wxString> txtTokens =
843 {
844 { TEXT_FIELD_NAME::DESIGN_TITLE, wxT( "DESIGN TITLE" ) },
845 { TEXT_FIELD_NAME::SHORT_JOBNAME, wxT( "SHORT_JOBNAME" ) },
846 { TEXT_FIELD_NAME::LONG_JOBNAME, wxT( "LONG_JOBNAME" ) },
847 { TEXT_FIELD_NAME::NUM_OF_SHEETS, wxT( "NUM_OF_SHEETS" ) },
848 { TEXT_FIELD_NAME::SHEET_NUMBER, wxT( "SHEET_NUMBER" ) },
849 { TEXT_FIELD_NAME::SHEET_NAME, wxT( "SHEET_NAME" ) },
850 { TEXT_FIELD_NAME::VARIANT_NAME, wxT( "VARIANT_NAME" ) },
851 { TEXT_FIELD_NAME::VARIANT_DESCRIPTION, wxT( "VARIANT_DESCRIPTION" ) },
852 { TEXT_FIELD_NAME::REG_USER, wxT( "REG_USER" ) },
853 { TEXT_FIELD_NAME::COMPANY_NAME, wxT( "COMPANY_NAME" ) },
854 { TEXT_FIELD_NAME::CURRENT_USER, wxT( "CURRENT_USER" ) },
855 { TEXT_FIELD_NAME::DATE, wxT( "DATE" ) },
856 { TEXT_FIELD_NAME::TIME, wxT( "TIME" ) },
857 { TEXT_FIELD_NAME::MACHINE_NAME, wxT( "MACHINE_NAME" ) },
858 { TEXT_FIELD_NAME::FROM_FILE, wxT( "FROM_FILE" ) },
859 { TEXT_FIELD_NAME::DISTANCE, wxT( "DISTANCE" ) },
860 { TEXT_FIELD_NAME::UNITS_SHORT, wxT( "UNITS SHORT" ) },
861 { TEXT_FIELD_NAME::UNITS_ABBREV, wxT( "UNITS ABBREV" ) },
862 { TEXT_FIELD_NAME::UNITS_FULL, wxT( "UNITS FULL" ) },
863 { TEXT_FIELD_NAME::HYPERLINK, wxT( "HYPERLINK" ) }
864 };
865
866 wxString remainingStr = aTextString;
867 wxString returnStr;
868
869 while( remainingStr.size() > 0 )
870 {
871 //Find the start token
872 size_t startpos = remainingStr.Find( wxT( "<@" ) );
873
874 if( static_cast<int>( startpos ) == wxNOT_FOUND )
875 {
876 // No more fields to parse, add to return string
877 returnStr += remainingStr;
878 break;
879 }
880
881 if( startpos > 0 )
882 returnStr += remainingStr.SubString( 0, startpos - 1 );
883
884 if( ( startpos + 2 ) >= remainingStr.size() )
885 break;
886
887 remainingStr = remainingStr.Mid( startpos + 2 );
888
889 //Find the expected token for the field
891
892 for( std::pair<TEXT_FIELD_NAME, wxString> txtF : txtTokens )
893 {
894 if( remainingStr.StartsWith( txtF.second ) )
895 {
896 foundField = txtF.first;
897 break;
898 }
899 }
900
901 if( foundField == TEXT_FIELD_NAME::NONE )
902 {
903 // Not a valid field, lets keep looking
904 returnStr += wxT( "<@" );
905 continue;
906 }
907
908 //Now lets find the end token
909 size_t endpos = remainingStr.Find( wxT( "@>" ) );
910
911 if( static_cast<int>( endpos ) == wxNOT_FOUND )
912 {
913 // The field we found isn't valid as it doesn't have a termination
914 // Lets append the whole thing as plain text
915 returnStr += wxT( "<@" ) + remainingStr;
916 break;
917 }
918
919 size_t valueStart = txtTokens.at( foundField ).size();
920 wxString fieldValue = remainingStr.SubString( valueStart, endpos - 1 );
921 wxString address;
922
923 if( foundField == TEXT_FIELD_NAME::FROM_FILE || foundField == TEXT_FIELD_NAME::HYPERLINK )
924 {
925 // The first character should always be a double quotation mark
926 wxASSERT_MSG( fieldValue.at( 0 ) == '"', "Expected '\"' as the first character" );
927
928 size_t splitPos = fieldValue.find_first_of( '"', 1 );
929 address = fieldValue.SubString( 1, splitPos - 1 );
930
931 if( foundField == TEXT_FIELD_NAME::HYPERLINK )
932 {
933 // Assume the last two characters are "@>"
934 wxASSERT_MSG( remainingStr.EndsWith( wxT( "@>" ) ),
935 "Expected '@>' at the end of a hyperlink" );
936
937 fieldValue = remainingStr.SubString( valueStart + splitPos + 1,
938 remainingStr.Length() - 3 );
939
940 remainingStr = wxEmptyString;
941 }
942 else
943 {
944 fieldValue = fieldValue.Mid( splitPos + 1 );
945 }
946 }
947
948 switch( foundField )
949 {
961
962 if( aContext->TextFieldToValuesMap.find( foundField )
963 != aContext->TextFieldToValuesMap.end() )
964 {
965 aContext->InconsistentTextFields.insert( foundField );
966 }
967 else
968 {
969 aContext->TextFieldToValuesMap.insert( { foundField, fieldValue } );
970 }
971
973
977 returnStr += wxT( "${" ) + CADSTAR_TO_KICAD_FIELDS.at( foundField ) + wxT( "}" );
978 break;
979
984 // Just flatten the text for distances
985 returnStr += fieldValue;
986 break;
987
989 {
990 wxFileName fn( address );
991 wxString fieldFmt = wxT( "FROM_FILE_%s_%s" );
992 wxString fieldName = wxString::Format( fieldFmt, fn.GetName(), fn.GetExt() );
993
994 int version = 1;
995
996 while(
997 aContext->FilenamesToTextMap.find( fieldName )
998 != aContext->FilenamesToTextMap.end()
999 && aContext->FilenamesToTextMap.at( fieldName ) != fieldValue )
1000 {
1001 fieldName = wxString::Format( fieldFmt, fn.GetName(), fn.GetExt() )
1002 + wxString::Format( wxT( "_%d" ), version++ );
1003 }
1004
1005 aContext->FilenamesToTextMap[fieldName] = fieldValue;
1006 returnStr += wxT( "${" ) + fieldName + wxT( "}" );
1007 }
1008 break;
1009
1011 {
1012 aContext->TextToHyperlinksMap[fieldValue] = address;
1013 returnStr += ParseTextFields( fieldValue, aContext );
1014 }
1015 break;
1016
1018 wxFAIL_MSG( "We should have already covered this scenario above" );
1019 break;
1020 }
1021
1022
1023 if( ( endpos + 2 ) >= remainingStr.size() )
1024 break;
1025
1026 remainingStr = remainingStr.Mid( endpos + 2 );
1027 }
1028
1029 return returnStr;
1030}
1031
1032
1034{
1035 wxASSERT( aNode->GetName() == wxT( "ALIGN" ) );
1036
1037 wxString alignmentStr = GetXmlAttributeIDString( aNode, 0 );
1038
1039 if( alignmentStr == wxT( "BOTTOMCENTER" ) )
1041 else if( alignmentStr == wxT( "BOTTOMLEFT" ) )
1042 return ALIGNMENT::BOTTOMLEFT;
1043 else if( alignmentStr == wxT( "BOTTOMRIGHT" ) )
1045 else if( alignmentStr == wxT( "CENTERCENTER" ) )
1047 else if( alignmentStr == wxT( "CENTERLEFT" ) )
1048 return ALIGNMENT::CENTERLEFT;
1049 else if( alignmentStr == wxT( "CENTERRIGHT" ) )
1051 else if( alignmentStr == wxT( "TOPCENTER" ) )
1052 return ALIGNMENT::TOPCENTER;
1053 else if( alignmentStr == wxT( "TOPLEFT" ) )
1054 return ALIGNMENT::TOPLEFT;
1055 else if( alignmentStr == wxT( "TOPRIGHT" ) )
1056 return ALIGNMENT::TOPRIGHT;
1057 else
1058 THROW_UNKNOWN_PARAMETER_IO_ERROR( alignmentStr, wxT( "ALIGN" ) );
1059
1060 //shouldn't be here but avoids compiler warning
1062}
1063
1064
1066{
1067 wxASSERT( aNode->GetName() == wxT( "JUSTIFICATION" ) );
1068
1069 wxString justificationStr = GetXmlAttributeIDString( aNode, 0 );
1070
1071 if( justificationStr == wxT( "LEFT" ) )
1072 return JUSTIFICATION::LEFT;
1073 else if( justificationStr == wxT( "RIGHT" ) )
1074 return JUSTIFICATION::RIGHT;
1075 else if( justificationStr == wxT( "CENTER" ) )
1076 return JUSTIFICATION::CENTER;
1077 else
1078 THROW_UNKNOWN_PARAMETER_IO_ERROR( justificationStr, wxT( "JUSTIFICATION" ) );
1079
1080 return JUSTIFICATION::LEFT;
1081}
1082
1083
1085{
1086 wxASSERT( aNode->GetName() == wxT( "READABILITY" ) );
1087
1088 wxString readabilityStr = GetXmlAttributeIDString( aNode, 0 );
1089
1090 if( readabilityStr == wxT( "BOTTOM_TO_TOP" ) )
1092 else if( readabilityStr == wxT( "TOP_TO_BOTTOM" ) )
1094 else
1095 THROW_UNKNOWN_PARAMETER_IO_ERROR( readabilityStr, wxT( "READABILITY" ) );
1096
1098}
1099
1100
1102 PARSER_CONTEXT* aContext )
1103{
1104 TextCodeID = GetXmlAttributeIDString( aNode, 0 );
1105 LayerID = GetXmlAttributeIDString( aNode, 1 );
1106}
1107
1108
1110 PARSER_CONTEXT* aContext )
1111{
1112 wxString cNodeName = aChildNode->GetName();
1113
1114 if( cNodeName == wxT( "PT" ) )
1115 Position.Parse( aChildNode, aContext );
1116 else if( cNodeName == wxT( "ORIENT" ) )
1117 OrientAngle = GetXmlAttributeIDLong( aChildNode, 0 );
1118 else if( cNodeName == wxT( "MIRROR" ) )
1119 Mirror = true;
1120 else if( cNodeName == wxT( "FIX" ) )
1121 Fixed = true;
1122 else if( cNodeName == wxT( "ALIGN" ) )
1123 Alignment = ParseAlignment( aChildNode );
1124 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1125 Justification = ParseJustification( aChildNode );
1126 else
1127 return false;
1128
1129 return true;
1130}
1131
1132
1134{
1135 wxASSERT( aNode->GetName() == wxT( "ATTRLOC" ) );
1136
1137 ParseIdentifiers( aNode, aContext );
1138
1139 //Parse child nodes
1140 XNODE* cNode = aNode->GetChildren();
1141
1142 for( ; cNode; cNode = cNode->GetNext() )
1143 {
1144 if( ParseSubNode( cNode, aContext ) )
1145 continue;
1146 else
1147 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "ATTRLOC" ) );
1148 }
1149
1150 if( !Position.IsFullySpecified() )
1151 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "ATTRLOC" ) );
1152}
1153
1154
1156{
1157 wxASSERT( aNode->GetName() == wxT( "COLUMNORDER" ) );
1158
1159 ID = GetXmlAttributeIDLong( aNode, 0 );
1160 Order = GetXmlAttributeIDLong( aNode, 1 );
1161
1162 CheckNoChildNodes( aNode );
1163}
1164
1165
1167{
1168 wxASSERT( aNode->GetName() == wxT( "COLUMNWIDTH" ) );
1169
1170 ID = GetXmlAttributeIDLong( aNode, 0 );
1171 Width = GetXmlAttributeIDLong( aNode, 1 );
1172
1173 CheckNoChildNodes( aNode );
1174}
1175
1176
1178{
1179 wxASSERT( aNode->GetName() == wxT( "ATTRNAME" ) );
1180
1181 ID = GetXmlAttributeIDString( aNode, 0 );
1182 Name = GetXmlAttributeIDString( aNode, 1 );
1183
1184 XNODE* cNode = aNode->GetChildren();
1185 wxString location = wxString::Format( "ATTRNAME -> %s", Name );
1186
1187 for( ; cNode; cNode = cNode->GetNext() )
1188 {
1189 wxString cNodeName = cNode->GetName();
1190
1191 if( cNodeName == wxT( "ATTROWNER" ) )
1192 {
1193 wxString attOwnerVal = GetXmlAttributeIDString( cNode, 0 );
1194
1195 if( attOwnerVal == wxT( "ALL_ITEMS" ) )
1196 AttributeOwner = ATTROWNER::ALL_ITEMS;
1197 else if( attOwnerVal == wxT( "AREA" ) )
1198 AttributeOwner = ATTROWNER::AREA;
1199 else if( attOwnerVal == wxT( "BOARD" ) )
1200 AttributeOwner = ATTROWNER::BOARD;
1201 else if( attOwnerVal == wxT( "COMPONENT" ) )
1202 AttributeOwner = ATTROWNER::COMPONENT;
1203 else if( attOwnerVal == wxT( "CONNECTION" ) )
1204 AttributeOwner = ATTROWNER::CONNECTION;
1205 else if( attOwnerVal == wxT( "COPPER" ) )
1206 AttributeOwner = ATTROWNER::COPPER;
1207 else if( attOwnerVal == wxT( "DOCSYMBOL" ) )
1208 AttributeOwner = ATTROWNER::DOCSYMBOL;
1209 else if( attOwnerVal == wxT( "FIGURE" ) )
1210 AttributeOwner = ATTROWNER::FIGURE;
1211 else if( attOwnerVal == wxT( "NET" ) )
1212 AttributeOwner = ATTROWNER::NET;
1213 else if( attOwnerVal == wxT( "NETCLASS" ) )
1214 AttributeOwner = ATTROWNER::NETCLASS;
1215 else if( attOwnerVal == wxT( "PART" ) )
1216 AttributeOwner = ATTROWNER::PART;
1217 else if( attOwnerVal == wxT( "PART_DEFINITION" ) )
1218 AttributeOwner = ATTROWNER::PART_DEFINITION;
1219 else if( attOwnerVal == wxT( "PIN" ) )
1220 AttributeOwner = ATTROWNER::PIN;
1221 else if( attOwnerVal == wxT( "SIGNALREF" ) )
1222 AttributeOwner = ATTROWNER::SIGNALREF;
1223 else if( attOwnerVal == wxT( "SYMBOL" ) )
1224 AttributeOwner = ATTROWNER::SYMBOL;
1225 else if( attOwnerVal == wxT( "SYMDEF" ) )
1226 AttributeOwner = ATTROWNER::SYMDEF;
1227 else if( attOwnerVal == wxT( "TEMPLATE" ) )
1228 AttributeOwner = ATTROWNER::TEMPLATE;
1229 else if( attOwnerVal == wxT( "TESTPOINT" ) )
1230 AttributeOwner = ATTROWNER::TESTPOINT;
1231 else
1232 THROW_UNKNOWN_PARAMETER_IO_ERROR( attOwnerVal, location );
1233 }
1234 else if( cNodeName == wxT( "ATTRUSAGE" ) )
1235 {
1236 wxString attUsageVal = GetXmlAttributeIDString( cNode, 0 );
1237
1238 if( attUsageVal == wxT( "BOTH" ) )
1239 AttributeUsage = ATTRUSAGE::BOTH;
1240 else if( attUsageVal == wxT( "COMPONENT" ) )
1241 AttributeUsage = ATTRUSAGE::COMPONENT;
1242 else if( attUsageVal == wxT( "PART_DEFINITION" ) )
1243 AttributeUsage = ATTRUSAGE::PART_DEFINITION;
1244 else if( attUsageVal == wxT( "PART_LIBRARY" ) )
1245 AttributeUsage = ATTRUSAGE::PART_LIBRARY;
1246 else if( attUsageVal == wxT( "SYMBOL" ) )
1247 AttributeUsage = ATTRUSAGE::SYMBOL;
1248 else
1249 THROW_UNKNOWN_PARAMETER_IO_ERROR( attUsageVal, location );
1250 }
1251 else if( cNodeName == wxT( "NOTRANSFER" ) )
1252 {
1253 NoTransfer = true;
1254 }
1255 else if( cNodeName == wxT( "COLUMNORDER" ) )
1256 {
1257 COLUMNORDER cOrder;
1258 cOrder.Parse( cNode, aContext );
1259 ColumnOrders.push_back( cOrder );
1260 }
1261 else if( cNodeName == wxT( "COLUMNWIDTH" ) )
1262 {
1263 COLUMNWIDTH cWidth;
1264 cWidth.Parse( cNode, aContext );
1265 ColumnWidths.push_back( cWidth );
1266 }
1267 else if( cNodeName == wxT( "COLUMNINVISIBLE" ) )
1268 {
1269 ColumnInvisible = true;
1270 }
1271 else
1272 {
1273 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
1274 }
1275 }
1276}
1277
1278
1280{
1281 wxASSERT( aNode->GetName() == wxT( "ATTR" ) );
1282
1283 AttributeID = GetXmlAttributeIDString( aNode, 0 );
1284 Value = GetXmlAttributeIDString( aNode, 1 );
1285
1286 XNODE* cNode = aNode->GetChildren();
1287
1288 for( ; cNode; cNode = cNode->GetNext() )
1289 {
1290 if( cNode->GetName() == wxT( "READONLY" ) )
1291 {
1292 ReadOnly = true;
1293 }
1294 else if( cNode->GetName() == wxT( "ATTRLOC" ) )
1295 {
1296 AttributeLocation.Parse( cNode, aContext );
1297 HasLocation = true;
1298 }
1299 else
1300 {
1301 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "ATTR" ) );
1302 }
1303 }
1304}
1305
1306
1308{
1309 wxASSERT( aNode->GetName() == wxT( "TEXTLOC" ) );
1310
1311 wxString attributeStr = GetXmlAttributeIDString( aNode, 0 );
1312 bool attributeIDisSet = false;
1313
1314 if( attributeStr == wxT( "PART_NAME" ) )
1315 {
1316 AttributeID = PART_NAME_ATTRID;
1317 attributeIDisSet = true;
1318 }
1319 else if( attributeStr == wxT( "COMP_NAME" ) )
1320 {
1321 AttributeID = COMPONENT_NAME_ATTRID;
1322 attributeIDisSet = true;
1323 }
1324 else if( attributeStr == wxT( "COMP_NAME2" ) )
1325 {
1326 AttributeID = COMPONENT_NAME_2_ATTRID;
1327 attributeIDisSet = true;
1328 }
1329 else if( attributeStr == wxT( "SYMBOL_NAME" ) )
1330 {
1331 AttributeID = SYMBOL_NAME_ATTRID;
1332 attributeIDisSet = true;
1333 }
1334 else if( attributeStr == wxT( "LINK_ORIGIN" ) )
1335 {
1336 AttributeID = LINK_ORIGIN_ATTRID;
1337 attributeIDisSet = true;
1338 }
1339 else if( attributeStr == wxT( "SIGNALNAME_ORIGIN" ) )
1340 {
1341 AttributeID = SIGNALNAME_ORIGIN_ATTRID;
1342 attributeIDisSet = true;
1343 }
1344 else if( attributeStr == wxT( "ATTRREF" ) )
1345 {
1346 //We will initialise when we parse all child nodes
1347 attributeIDisSet = false;
1348 }
1349 else
1350 {
1351 THROW_UNKNOWN_PARAMETER_IO_ERROR( attributeStr, wxT( "TEXTLOC" ) );
1352 }
1353
1354 TextCodeID = GetXmlAttributeIDString( aNode, 1 );
1355 LayerID = GetXmlAttributeIDString( aNode, 2, false );
1356
1357 //Parse child nodes
1358 XNODE* cNode = aNode->GetChildren();
1359
1360 for( ; cNode; cNode = cNode->GetNext() )
1361 {
1362 wxString cNodeName = cNode->GetName();
1363
1364 if( ParseSubNode( cNode, aContext ) )
1365 {
1366 continue;
1367 }
1368 else if( !attributeIDisSet && cNodeName == wxT( "ATTRREF" ) )
1369 {
1370 AttributeID = GetXmlAttributeIDString( cNode, 0 );
1371 attributeIDisSet = true;
1372 }
1373 else if( cNodeName == wxT( "ORIENT" ) )
1374 {
1375 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1376 }
1377 else if( cNodeName == wxT( "MIRROR" ) )
1378 {
1379 Mirror = true;
1380 }
1381 else if( cNodeName == wxT( "FIX" ) )
1382 {
1383 Fixed = true;
1384 }
1385 else if( cNodeName == wxT( "ALIGN" ) )
1386 {
1387 Alignment = ParseAlignment( cNode );
1388 }
1389 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1390 {
1391 Justification = ParseJustification( cNode );
1392 }
1393 else
1394 {
1395 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEXTLOC" ) );
1396 }
1397 }
1398
1399 if( !Position.IsFullySpecified() )
1400 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "TEXTLOC" ) );
1401}
1402
1403
1405{
1406 wxASSERT( aNode->GetName() == wxT( "NETCLASS" ) );
1407
1408 ID = GetXmlAttributeIDString( aNode, 0 );
1409 Name = GetXmlAttributeIDString( aNode, 1 );
1410
1411 XNODE* cNode = aNode->GetChildren();
1412 wxString location = wxString::Format( "NETCLASS -> %s", Name );
1413
1414 for( ; cNode; cNode = cNode->GetNext() )
1415 {
1416 wxString cNodeName = cNode->GetName();
1417
1418 if( cNodeName == wxT( "ATTR" ) )
1419 {
1420 ATTRIBUTE_VALUE attribute_val;
1421 attribute_val.Parse( cNode, aContext );
1422 Attributes.push_back( attribute_val );
1423 }
1424 else
1425 {
1426 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
1427 }
1428 }
1429}
1430
1431
1433{
1434 wxASSERT( aNode->GetName() == wxT( "SPCCLASSNAME" ) );
1435
1436 ID = GetXmlAttributeIDString( aNode, 0 );
1437 Name = GetXmlAttributeIDString( aNode, 1 );
1438}
1439
1440
1442{
1443 wxString nodeName = aChildNode->GetName();
1444
1445 if( nodeName == wxT( "LINECODE" ) )
1446 {
1447 LINECODE linecode;
1448 linecode.Parse( aChildNode, aContext );
1449 LineCodes.insert( std::make_pair( linecode.ID, linecode ) );
1450 }
1451 else if( nodeName == wxT( "HATCHCODE" ) )
1452 {
1453 HATCHCODE hatchcode;
1454 hatchcode.Parse( aChildNode, aContext );
1455 HatchCodes.insert( std::make_pair( hatchcode.ID, hatchcode ) );
1456 }
1457 else if( nodeName == wxT( "TEXTCODE" ) )
1458 {
1459 TEXTCODE textcode;
1460 textcode.Parse( aChildNode, aContext );
1461 TextCodes.insert( std::make_pair( textcode.ID, textcode ) );
1462 }
1463 else if( nodeName == wxT( "ROUTECODE" ) )
1464 {
1465 ROUTECODE routecode;
1466 routecode.Parse( aChildNode, aContext );
1467 RouteCodes.insert( std::make_pair( routecode.ID, routecode ) );
1468 }
1469 else if( nodeName == wxT( "ATTRNAME" ) )
1470 {
1471 ATTRNAME attrname;
1472 attrname.Parse( aChildNode, aContext );
1473 AttributeNames.insert( std::make_pair( attrname.ID, attrname ) );
1474 }
1475 else if( nodeName == wxT( "NETCLASS" ) )
1476 {
1477 CADSTAR_NETCLASS netclass;
1478 netclass.Parse( aChildNode, aContext );
1479 NetClasses.insert( std::make_pair( netclass.ID, netclass ) );
1480 }
1481 else if( nodeName == wxT( "SPCCLASSNAME" ) )
1482 {
1483 SPCCLASSNAME spcclassname;
1484 spcclassname.Parse( aChildNode, aContext );
1485 SpacingClassNames.insert( std::make_pair( spcclassname.ID, spcclassname ) );
1486 }
1487 else
1488 {
1489 return false;
1490 }
1491
1492 return true;
1493}
1494
1495
1497{
1498 wxASSERT( aNode->GetName() == wxT( "SWAPRULE" ) );
1499
1500 SWAP_RULE retval;
1501 wxString swapRuleStr = GetXmlAttributeIDString( aNode, 0 );
1502
1503 if( swapRuleStr == wxT( "NO_SWAP" ) )
1504 retval = SWAP_RULE::NO_SWAP;
1505 else if( swapRuleStr == wxT( "USE_SWAP_LAYER" ) )
1507 else
1508 THROW_UNKNOWN_PARAMETER_IO_ERROR( swapRuleStr, wxT( "SWAPRULE" ) );
1509
1510 return retval;
1511}
1512
1513
1515{
1516 wxASSERT( aNode->GetName() == wxT( "REUSEBLOCK" ) );
1517
1518 ID = GetXmlAttributeIDString( aNode, 0 );
1519 Name = GetXmlAttributeIDString( aNode, 1 );
1520 FileName = GetXmlAttributeIDString( aNode, 2 );
1521
1522 XNODE* cNode = aNode->GetChildren();
1523
1524 for( ; cNode; cNode = cNode->GetNext() )
1525 {
1526 wxString cNodeName = cNode->GetName();
1527
1528 if( cNodeName == wxT( "MIRROR" ) )
1529 Mirror = true;
1530 else if( cNodeName == wxT( "ORIENT" ) )
1531 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1532 else
1533 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "REUSEBLOCK" ) );
1534 }
1535}
1536
1537
1539{
1540 return ReuseBlockID == wxEmptyString && ItemReference == wxEmptyString;
1541}
1542
1543
1545{
1546 wxASSERT( aNode->GetName() == wxT( "REUSEBLOCKREF" ) );
1547
1548 ReuseBlockID = GetXmlAttributeIDString( aNode, 0 );
1549 ItemReference = GetXmlAttributeIDString( aNode, 1 );
1550
1551 CheckNoChildNodes( aNode );
1552}
1553
1554
1556{
1557 wxASSERT( aNode->GetName() == wxT( "GROUP" ) );
1558
1559 ID = GetXmlAttributeIDString( aNode, 0 );
1560 Name = GetXmlAttributeIDString( aNode, 1 );
1561
1562 XNODE* cNode = aNode->GetChildren();
1563
1564 for( ; cNode; cNode = cNode->GetNext() )
1565 {
1566 wxString cNodeName = cNode->GetName();
1567
1568 if( cNodeName == wxT( "FIX" ) )
1569 Fixed = true;
1570 else if( cNodeName == wxT( "TRANSFER" ) )
1571 Transfer = true;
1572 else if( cNodeName == wxT( "GROUPREF" ) )
1573 GroupID = GetXmlAttributeIDString( cNode, 0 );
1574 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1575 ReuseBlockRef.Parse( cNode, aContext );
1576 else
1577 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "GROUP" ) );
1578 }
1579}
1580
1581
1583{
1584 wxASSERT( aNode->GetName() == wxT( "FIGURE" ) );
1585
1586 ID = GetXmlAttributeIDString( aNode, 0 );
1587 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1588 LayerID = GetXmlAttributeIDString( aNode, 2 );
1589
1590 XNODE* cNode = aNode->GetChildren();
1591 bool shapeIsInitialised = false; // Stop more than one Shape Object
1592 wxString location = wxString::Format( "Figure %s", ID );
1593
1594 if( !cNode )
1595 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1596
1597 for( ; cNode; cNode = cNode->GetNext() )
1598 {
1599 wxString cNodeName = cNode->GetName();
1600
1601 if( !shapeIsInitialised && Shape.IsShape( cNode ) )
1602 {
1603 Shape.Parse( cNode, aContext );
1604 shapeIsInitialised = true;
1605 }
1606 else if( cNodeName == wxT( "SWAPRULE" ) )
1607 {
1608 SwapRule = ParseSwapRule( cNode );
1609 }
1610 else if( cNodeName == wxT( "FIX" ) )
1611 {
1612 Fixed = true;
1613 }
1614 else if( cNodeName == wxT( "GROUPREF" ) )
1615 {
1616
1617 GroupID = GetXmlAttributeIDString( cNode, 0 );
1618 }
1619 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1620 {
1621 ReuseBlockRef.Parse( cNode, aContext );
1622 }
1623 else if( cNodeName == wxT( "ATTR" ) )
1624 {
1625 ATTRIBUTE_VALUE attr;
1626 attr.Parse( cNode, aContext );
1627 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1628 }
1629 else
1630 {
1631 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, location );
1632 }
1633 }
1634}
1635
1636
1638{
1639 Parse( aNode, aContext, true );
1640}
1641
1642
1644 bool aParseFields )
1645{
1646 wxASSERT( aNode->GetName() == wxT( "TEXT" ) );
1647
1648 ID = GetXmlAttributeIDString( aNode, 0 );
1649 Text = GetXmlAttributeIDString( aNode, 1 );
1650
1651 if( aParseFields )
1652 Text = ParseTextFields( Text, aContext );
1653
1654 TextCodeID = GetXmlAttributeIDString( aNode, 2 );
1655 LayerID = GetXmlAttributeIDString( aNode, 3 );
1656
1657 XNODE* cNode = aNode->GetChildren();
1658
1659 if( !cNode )
1660 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "TEXT" ) );
1661
1662 for( ; cNode; cNode = cNode->GetNext() )
1663 {
1664 wxString cNodeName = cNode->GetName();
1665
1666 if( cNodeName == wxT( "PT" ) )
1667 Position.Parse( cNode, aContext );
1668 else if( cNodeName == wxT( "ORIENT" ) )
1669 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1670 else if( cNodeName == wxT( "MIRROR" ) )
1671 Mirror = true;
1672 else if( cNodeName == wxT( "FIX" ) )
1673 Fixed = true;
1674 else if( cNodeName == wxT( "SWAPRULE" ) )
1675 SwapRule = ParseSwapRule( cNode );
1676 else if( cNodeName == wxT( "ALIGN" ) )
1677 Alignment = ParseAlignment( cNode );
1678 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1679 Justification = ParseJustification( cNode );
1680 else if( cNodeName == wxT( "GROUPREF" ) )
1681 GroupID = GetXmlAttributeIDString( cNode, 0 );
1682 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1683 ReuseBlockRef.Parse( cNode, aContext );
1684 else
1685 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEXT" ) );
1686 }
1687}
1688
1689
1691{
1692 wxASSERT( aNode->GetName() == wxT( "SYMDEF" ) );
1693
1694 ID = GetXmlAttributeIDString( aNode, 0 );
1695 ReferenceName = GetXmlAttributeIDString( aNode, 1 );
1696 Alternate = GetXmlAttributeIDString( aNode, 2 );
1697}
1698
1699
1701{
1702 wxString cNodeName = aChildNode->GetName();
1703
1704 if( cNodeName == wxT( "PT" ) )
1705 {
1706 Origin.Parse( aChildNode, aContext );
1707 }
1708 else if( cNodeName == wxT( "STUB" ) )
1709 {
1710 Stub = true;
1711 }
1712 else if( cNodeName == wxT( "VERSION" ) )
1713 {
1714 Version = GetXmlAttributeIDLong( aChildNode, 0 );
1715 }
1716 else if( cNodeName == wxT( "FIGURE" ) )
1717 {
1718 FIGURE figure;
1719 figure.Parse( aChildNode, aContext );
1720 Figures.insert( std::make_pair( figure.ID, figure ) );
1721 }
1722 else if( cNodeName == wxT( "TEXT" ) )
1723 {
1724 TEXT txt;
1725 txt.Parse( aChildNode, aContext );
1726 Texts.insert( std::make_pair( txt.ID, txt ) );
1727 }
1728 else if( cNodeName == wxT( "TEXTLOC" ) )
1729 {
1730 TEXT_LOCATION textloc;
1731 textloc.Parse( aChildNode, aContext );
1732 TextLocations.insert( std::make_pair( textloc.AttributeID, textloc ) );
1733 }
1734 else if( cNodeName == wxT( "ATTR" ) )
1735 {
1736 ATTRIBUTE_VALUE attrVal;
1737 attrVal.Parse( aChildNode, aContext );
1738 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1739 }
1740 else
1741 {
1742 return false;
1743 }
1744
1745 return true;
1746}
1747
1748
1750{
1751 wxASSERT( aNode->GetName() == wxT( "GATEDEFINITION" ) );
1752
1753 ID = GetXmlAttributeIDString( aNode, 0 );
1754 Name = GetXmlAttributeIDString( aNode, 1 );
1755 Alternate = GetXmlAttributeIDString( aNode, 2 );
1756 PinCount = GetXmlAttributeIDLong( aNode, 3 );
1757
1758 CheckNoChildNodes( aNode );
1759}
1760
1761
1763{
1764 wxASSERT( aNode->GetName() == wxT( "PINTYPE" ) );
1765
1766 wxString pinTypeStr = GetXmlAttributeIDString( aNode, 0 );
1767
1768 std::map<wxString, PIN_TYPE> pinTypeMap = { { wxT( "INPUT" ), PIN_TYPE::INPUT },
1769 { wxT( "OUTPUT_OR" ), PIN_TYPE::OUTPUT_OR },
1770 { wxT( "OUTPUT_NOT_OR" ), PIN_TYPE::OUTPUT_NOT_OR },
1771 { wxT( "OUTPUT_NOT_NORM_OR" ), PIN_TYPE::OUTPUT_NOT_NORM_OR },
1772 { wxT( "POWER" ), PIN_TYPE::POWER }, { wxT( "GROUND" ), PIN_TYPE::GROUND },
1773 { wxT( "TRISTATE_BIDIR" ), PIN_TYPE::TRISTATE_BIDIR },
1774 { wxT( "TRISTATE_INPUT" ), PIN_TYPE::TRISTATE_INPUT },
1775 { wxT( "TRISTATE_DRIVER" ), PIN_TYPE::TRISTATE_DRIVER } };
1776
1777 if( pinTypeMap.find( pinTypeStr ) == pinTypeMap.end() )
1778 THROW_UNKNOWN_PARAMETER_IO_ERROR( pinTypeStr, aNode->GetName() );
1779
1780 return pinTypeMap[pinTypeStr];
1781}
1782
1783
1785{
1786 wxASSERT( aNode->GetName() == wxT( "PARTDEFINITIONPIN" ) );
1787
1788 ID = GetXmlAttributeIDLong( aNode, 0 );
1789
1790 XNODE* cNode = aNode->GetChildren();
1791
1792 for( ; cNode; cNode = cNode->GetNext() )
1793 {
1794 wxString cNodeName = cNode->GetName();
1795
1796 if( cNodeName == wxT( "PINNAME" ) )
1797 {
1798 Name = GetXmlAttributeIDString( cNode, 0 );
1799 }
1800 else if( cNodeName == wxT( "PINLABEL" ) )
1801 {
1802 Label = GetXmlAttributeIDString( cNode, 0 );
1803 }
1804 else if( cNodeName == wxT( "PINSIGNAL" ) )
1805 {
1806 Signal = GetXmlAttributeIDString( cNode, 0 );
1807 }
1808 else if( cNodeName == wxT( "PINTERM" ) )
1809 {
1810 TerminalGate = GetXmlAttributeIDString( cNode, 0 );
1811 TerminalPin = GetXmlAttributeIDLong( cNode, 1 );
1812 }
1813 else if( cNodeName == wxT( "PINTYPE" ) )
1814 {
1815 Type = GetPinType( cNode );
1816 }
1817 else if( cNodeName == wxT( "PINLOAD" ) )
1818 {
1819 Load = GetXmlAttributeIDLong( cNode, 0 );
1820 }
1821 else if( cNodeName == wxT( "PINPOSITION" ) )
1822 {
1823 Position = (POSITION) GetXmlAttributeIDLong( cNode, 0 );
1824 }
1825 else if( cNodeName == wxT( "PINIDENTIFIER" ) )
1826 {
1827 Identifier = GetXmlAttributeIDString( cNode, 0 );
1828 }
1829 else
1830 {
1831 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1832 }
1833 }
1834}
1835
1836
1838{
1839 wxASSERT( aNode->GetName() == wxT( "PARTPIN" ) );
1840
1841 ID = GetXmlAttributeIDLong( aNode, 0 );
1842
1843 XNODE* cNode = aNode->GetChildren();
1844
1845 for( ; cNode; cNode = cNode->GetNext() )
1846 {
1847 wxString cNodeName = cNode->GetName();
1848
1849 if( cNodeName == wxT( "PINNAME" ) )
1850 Name = GetXmlAttributeIDString( cNode, 0 );
1851 else if( cNodeName == wxT( "PINTYPE" ) )
1852 Type = GetPinType( cNode );
1853 else if( cNodeName == wxT( "PINIDENTIFIER" ) )
1854 Identifier = GetXmlAttributeIDString( cNode, 0 );
1855 else
1856 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1857 }
1858}
1859
1860
1862 PARSER_CONTEXT* aContext )
1863{
1864 wxASSERT( aNode->GetName() == wxT( "PINEQUIVALENCE" ) );
1865
1866 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1867
1868 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1869 {
1870 if( !IsValidAttribute( xmlAttribute ) )
1871 continue;
1872
1873 long pinId;
1874
1875 if( !xmlAttribute->GetValue().ToLong( &pinId ) )
1876 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), aNode->GetName() );
1877
1878 PinIDs.push_back( (PART_DEFINITION_PIN_ID) pinId );
1879 }
1880
1881 CheckNoChildNodes( aNode );
1882}
1883
1884
1886 PARSER_CONTEXT* aContext )
1887{
1888 wxASSERT( aNode->GetName() == wxT( "SWAPGATE" ) );
1889
1890 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1891
1892 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1893 {
1894 if( !IsValidAttribute( xmlAttribute ) )
1895 continue;
1896
1897 long pinId;
1898
1899 if( !xmlAttribute->GetValue().ToLong( &pinId ) )
1900 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), aNode->GetName() );
1901
1902 PinIDs.push_back( (PART_DEFINITION_PIN_ID) pinId );
1903 }
1904
1905 CheckNoChildNodes( aNode );
1906}
1907
1908
1910 PARSER_CONTEXT* aContext )
1911{
1912 wxASSERT( aNode->GetName() == wxT( "SWAPGROUP" ) );
1913
1914 GateName = GetXmlAttributeIDString( aNode, 0 );
1915
1916 XNODE* cNode = aNode->GetChildren();
1917
1918 for( ; cNode; cNode = cNode->GetNext() )
1919 {
1920 wxString cNodeName = cNode->GetName();
1921
1922 if( cNodeName == wxT( "EXTERNAL" ) )
1923 {
1924 External = true;
1925 }
1926 else if( cNodeName == wxT( "SWAPGATE" ) )
1927 {
1928 SWAP_GATE swapGate;
1929 swapGate.Parse( cNode, aContext );
1930 SwapGates.push_back( swapGate );
1931 }
1932 else
1933 {
1934 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1935 }
1936 }
1937}
1938
1939
1941{
1942 wxASSERT( aNode->GetName() == wxT( "PARTDEFINITION" ) );
1943
1944 Name = GetXmlAttributeIDString( aNode, 0 );
1945
1946 XNODE* cNode = aNode->GetChildren();
1947
1948 for( ; cNode; cNode = cNode->GetNext() )
1949 {
1950 wxString cNodeName = cNode->GetName();
1951
1952 if( cNodeName == wxT( "HIDEPINNAMES" ) )
1953 {
1954 HidePinNames = true;
1955 }
1956 else if( cNodeName == wxT( "MAXPIN" ) )
1957 {
1958 MaxPinCount = GetXmlAttributeIDLong( cNode, 0 );
1959 }
1960 else if( cNodeName == wxT( "GATEDEFINITION" ) )
1961 {
1962 GATE gate;
1963 gate.Parse( cNode, aContext );
1964 GateSymbols.insert( std::make_pair( gate.ID, gate ) );
1965 }
1966 else if( cNodeName == wxT( "PARTDEFINITIONPIN" ) )
1967 {
1968 PIN pin;
1969 pin.Parse( cNode, aContext );
1970 Pins.insert( std::make_pair( pin.ID, pin ) );
1971 }
1972 else if( cNodeName == wxT( "ATTR" ) )
1973 {
1974 ATTRIBUTE_VALUE attr;
1975 attr.Parse( cNode, aContext );
1976 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1977 }
1978 else if( cNodeName == wxT( "PINEQUIVALENCE" ) )
1979 {
1980 PIN_EQUIVALENCE pinEq;
1981 pinEq.Parse( cNode, aContext );
1982 PinEquivalences.push_back( pinEq );
1983 }
1984 else if( cNodeName == wxT( "SWAPGROUP" ) )
1985 {
1986 SWAP_GROUP swapGroup;
1987 swapGroup.Parse( cNode, aContext );
1988 SwapGroups.push_back( swapGroup );
1989 }
1990 else
1991 {
1992 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1993 }
1994 }
1995}
1996
1997
1999{
2000 wxASSERT( aNode->GetName() == wxT( "PART" ) );
2001
2002 ID = GetXmlAttributeIDString( aNode, 0 );
2003 Name = GetXmlAttributeIDString( aNode, 1 );
2004
2005 XNODE* cNode = aNode->GetChildren();
2006
2007 for( ; cNode; cNode = cNode->GetNext() )
2008 {
2009 wxString cNodeName = cNode->GetName();
2010
2011 if( cNodeName == wxT( "VERSION" ) )
2012 {
2013 Version = GetXmlAttributeIDLong( cNode, 0 );
2014 }
2015 else if( cNodeName == wxT( "HIDEPINNAMES" ) )
2016 {
2017 HidePinNames = true;
2018 }
2019 else if( cNodeName == wxT( "PARTDEFINITION" ) )
2020 {
2021 Definition.Parse( cNode, aContext );
2022 }
2023 else if( cNodeName == wxT( "PARTPIN" ) )
2024 {
2025 PART_PIN pin;
2026 pin.Parse( cNode, aContext );
2027 PartPins.insert( std::make_pair( pin.ID, pin ) );
2028 }
2029 else if( cNodeName == wxT( "ATTR" ) )
2030 {
2031 ATTRIBUTE_VALUE attr;
2032 attr.Parse( cNode, aContext );
2033 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2034 }
2035 else
2036 {
2037 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2038 }
2039 }
2040}
2041
2042
2044{
2045 wxASSERT( aNode->GetName() == wxT( "PARTS" ) );
2046
2047 XNODE* cNode = aNode->GetChildren();
2048
2049 for( ; cNode; cNode = cNode->GetNext() )
2050 {
2051 wxString cNodeName = cNode->GetName();
2052
2053 if( cNodeName == wxT( "PART" ) )
2054 {
2055 PART part;
2056 part.Parse( cNode, aContext );
2057 PartDefinitions.insert( std::make_pair( part.ID, part ) );
2058 }
2059 else
2060 {
2061 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2062 }
2063
2064 aContext->CheckPointCallback();
2065 }
2066}
2067
2068
2070 PARSER_CONTEXT* aContext )
2071{
2072 wxASSERT( aNode->GetName() == wxT( "JPT" ) );
2073
2074 ID = GetXmlAttributeIDString( aNode, 0 );
2075 LayerID = GetXmlAttributeIDString( aNode, 1 );
2076}
2077
2078
2080 PARSER_CONTEXT* aContext )
2081{
2082 wxString cNodeName = aChildNode->GetName();
2083
2084 if( cNodeName == wxT( "PT" ) )
2085 Location.Parse( aChildNode, aContext );
2086 else if( cNodeName == wxT( "FIX" ) )
2087 Fixed = true;
2088 else if( cNodeName == wxT( "GROUPREF" ) )
2089 GroupID = GetXmlAttributeIDString( aChildNode, 0 );
2090 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2091 ReuseBlockRef.Parse( aChildNode, aContext );
2092 else
2093 return false;
2094
2095 return true;
2096}
2097
2098
2100{
2101 ParseIdentifiers( aNode, aContext );
2102 XNODE* cNode = aNode->GetChildren();
2103
2104 for( ; cNode; cNode = cNode->GetNext() )
2105 {
2106 if( ParseSubNode( cNode, aContext ) )
2107 continue;
2108 else
2109 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2110 }
2111}
2112
2113
2115 PARSER_CONTEXT* aContext )
2116{
2117 wxASSERT( aNode->GetName() == wxT( "CONN" ) );
2118
2119 StartNode = GetXmlAttributeIDString( aNode, 0 );
2120 EndNode = GetXmlAttributeIDString( aNode, 1 );
2121 RouteCodeID = GetXmlAttributeIDString( aNode, 2 );
2122}
2123
2124
2126 PARSER_CONTEXT* aContext )
2127{
2128 wxString cNodeName = aChildNode->GetName();
2129
2130 if( cNodeName == wxT( "FIX" ) )
2131 {
2132 Fixed = true;
2133 }
2134 else if( cNodeName == wxT( "HIDDEN" ) )
2135 {
2136 Hidden = true;
2137 }
2138 else if( cNodeName == wxT( "GROUPREF" ) )
2139 {
2140 GroupID = GetXmlAttributeIDString( aChildNode, 0 );
2141 }
2142 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2143 {
2144 ReuseBlockRef.Parse( aChildNode, aContext );
2145 }
2146 else if( cNodeName == wxT( "ATTR" ) )
2147 {
2148 ATTRIBUTE_VALUE attrVal;
2149 attrVal.Parse( aChildNode, aContext );
2150 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
2151 }
2152 else
2153 {
2154 return false;
2155 }
2156
2157 return true;
2158}
2159
2160
2162{
2163 wxASSERT( aNode->GetName() == wxT( "NET" ) );
2164
2165 ID = GetXmlAttributeIDString( aNode, 0 );
2166}
2167
2168
2170{
2171 wxString cNodeName = aChildNode->GetName();
2172
2173 if( cNodeName == wxT( "NETCODE" ) )
2174 {
2175 RouteCodeID = GetXmlAttributeIDString( aChildNode, 0 );
2176 }
2177 else if( cNodeName == wxT( "SIGNAME" ) )
2178 {
2179 Name = GetXmlAttributeIDString( aChildNode, 0 );
2180 }
2181 else if( cNodeName == wxT( "SIGNUM" ) )
2182 {
2183 SignalNum = GetXmlAttributeIDLong( aChildNode, 0 );
2184 }
2185 else if( cNodeName == wxT( "HIGHLIT" ) )
2186 {
2187 Highlight = true;
2188 }
2189 else if( cNodeName == wxT( "JPT" ) )
2190 {
2191 JUNCTION jpt;
2192 jpt.Parse( aChildNode, aContext );
2193 Junctions.insert( std::make_pair( jpt.ID, jpt ) );
2194 }
2195 else if( cNodeName == wxT( "NETCLASSREF" ) )
2196 {
2197 NetClassID = GetXmlAttributeIDString( aChildNode, 0 );
2198 }
2199 else if( cNodeName == wxT( "SPACINGCLASS" ) )
2200 {
2201 SpacingClassID = GetXmlAttributeIDString( aChildNode, 0 );
2202 }
2203 else if( cNodeName == wxT( "ATTR" ) )
2204 {
2205 ATTRIBUTE_VALUE attrVal;
2206 attrVal.Parse( aChildNode, aContext );
2207 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
2208 }
2209 else
2210 {
2211 return false;
2212 }
2213
2214 return true;
2215}
2216
2217
2219{
2220 wxASSERT( aNode->GetName() == wxT( "DOCSYMBOL" ) );
2221
2222 ID = GetXmlAttributeIDString( aNode, 0 );
2223 SymdefID = GetXmlAttributeIDString( aNode, 1 );
2224 LayerID = GetXmlAttributeIDString( aNode, 2 );
2225
2226 XNODE* cNode = aNode->GetChildren();
2227 bool originParsed = false;
2228
2229 for( ; cNode; cNode = cNode->GetNext() )
2230 {
2231 wxString cNodeName = cNode->GetName();
2232
2233 if( !originParsed && cNodeName == wxT( "PT" ) )
2234 {
2235 Origin.Parse( cNode, aContext );
2236 originParsed = true;
2237 }
2238 else if( cNodeName == wxT( "GROUPREF" ) )
2239 {
2240 GroupID = GetXmlAttributeIDString( cNode, 0 );
2241 }
2242 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2243 {
2244 ReuseBlockRef.Parse( cNode, aContext );
2245 }
2246 else if( cNodeName == wxT( "FIX" ) )
2247 {
2248 Fixed = true;
2249 }
2250 else if( cNodeName == wxT( "MIRROR" ) )
2251 {
2252 Mirror = true;
2253 }
2254 else if( cNodeName == wxT( "READABILITY" ) )
2255 {
2256 Readability = ParseReadability( cNode );
2257 }
2258 else if( cNodeName == wxT( "ORIENT" ) )
2259 {
2260 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
2261 }
2262 else if( cNodeName == wxT( "ATTR" ) )
2263 {
2264 ATTRIBUTE_VALUE attr;
2265 attr.Parse( cNode, aContext );
2266 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2267 }
2268 else if( cNodeName == wxT( "SCALE" ) )
2269 {
2270 ScaleRatioNumerator = GetXmlAttributeIDLong( cNode, 0 );
2271 ScaleRatioDenominator = GetXmlAttributeIDLong( cNode, 1 );
2272 }
2273 else
2274 {
2275 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2276 }
2277 }
2278
2279 if( !originParsed )
2280 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
2281}
2282
2283
2285{
2286 wxASSERT( aNode->GetName() == wxT( "DFLTSETTINGS" ) );
2287
2288 Color = GetXmlAttributeIDString( aNode, 0 );
2289
2290 XNODE* cNode = aNode->GetChildren();
2291
2292 for( ; cNode; cNode = cNode->GetNext() )
2293 {
2294 wxString cNodeName = cNode->GetName();
2295
2296 if( cNodeName == wxT( "INVISIBLE" ) )
2297 {
2298 IsVisible = false;
2299 }
2300 else
2301 {
2302 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2303 }
2304 }
2305}
2306
2307
2309{
2310 wxASSERT( aNode->GetName() == wxT( "ATTRCOL" ) );
2311
2312 AttributeID = GetXmlAttributeIDString( aNode, 0 );
2313 Color = GetXmlAttributeIDString( aNode, 1 );
2314
2315 XNODE* cNode = aNode->GetChildren();
2316
2317 for( ; cNode; cNode = cNode->GetNext() )
2318 {
2319 wxString cNodeName = cNode->GetName();
2320
2321 if( cNodeName == wxT( "INVISIBLE" ) )
2322 {
2323 IsVisible = false;
2324 }
2325 else if( cNodeName == wxT( "NOTPICKABLE" ) )
2326 {
2327 IsPickable = false;
2328 }
2329 else
2330 {
2331 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2332 }
2333 }
2334}
2335
2336
2338{
2339 wxASSERT( aNode->GetName() == wxT( "ATTRCOLORS" ) );
2340
2341 XNODE* cNode = aNode->GetChildren();
2342
2343 for( ; cNode; cNode = cNode->GetNext() )
2344 {
2345 wxString cNodeName = cNode->GetName();
2346
2347 if( cNodeName == wxT( "DFLTSETTINGS" ) )
2348 {
2349 DefaultSettings.Parse( cNode, aContext );
2350 }
2351 else if( cNodeName == wxT( "ATTRCOL" ) )
2352 {
2353 ATTRCOL attrcol;
2354 attrcol.Parse( cNode, aContext );
2355 AttributeColors.insert( { attrcol.AttributeID, attrcol } );
2356 }
2357 else if( cNodeName == wxT( "INVISIBLE" ) )
2358 {
2359 IsVisible = false;
2360 }
2361 else
2362 {
2363 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2364 }
2365 }
2366}
2367
2368
2370{
2371 wxASSERT( aNode->GetName() == wxT( "PARTNAMECOL" ) );
2372
2373 Color = GetXmlAttributeIDString( aNode, 0 );
2374
2375 XNODE* cNode = aNode->GetChildren();
2376
2377 for( ; cNode; cNode = cNode->GetNext() )
2378 {
2379 wxString cNodeName = cNode->GetName();
2380
2381 if( cNodeName == wxT( "INVISIBLE" ) )
2382 {
2383 IsVisible = false;
2384 }
2385 else if( cNodeName == wxT( "NOTPICKABLE" ) )
2386 {
2387 IsPickable = false;
2388 }
2389 else
2390 {
2391 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2392 }
2393 }
2394}
2395
2396
2398{
2399 wxString result;
2400 int numAttributes = 0;
2401
2402 if( aNode->GetAttribute( wxT( "numAttributes" ), &result ) )
2403 {
2404 numAttributes = wxAtoi( result );
2405 aNode->DeleteAttribute( wxT( "numAttributes" ) );
2406 ++numAttributes;
2407 }
2408
2409 aNode->AddAttribute( wxT( "numAttributes" ), wxString::Format( wxT( "%i" ), numAttributes ) );
2410
2411 wxString paramName = wxT( "attr" );
2412 paramName << numAttributes;
2413
2414 aNode->AddAttribute( paramName, aValue );
2415}
2416
2417
2419 const wxString& aFileTypeIdentifier, PROGRESS_REPORTER* aProgressReporter )
2420{
2421 KEYWORD emptyKeywords[1] = {};
2422 XNODE * iNode = nullptr, *cNode = nullptr;
2423 int tok;
2424 bool cadstarFileCheckDone = false;
2425 wxString str;
2426 wxCSConv win1252( wxT( "windows-1252" ) );
2427 wxMBConv* conv = &win1252; // Initial testing suggests file encoding to be Windows-1252
2428 // More samples required.
2429
2430 // Open the file and get the file size
2431 FILE* fp = wxFopen( aFileName, wxT( "rt" ) );
2432
2433 if( !fp )
2434 THROW_IO_ERROR( wxString::Format( _( "Cannot open file '%s'" ), aFileName ) );
2435
2436 fseek( fp, 0L, SEEK_END );
2437 long fileSize = ftell( fp );
2438 rewind( fp );
2439
2440 DSNLEXER lexer( emptyKeywords, 0, nullptr, fp, aFileName );
2441
2442 auto currentProgress = [&]() -> double
2443 {
2444 return static_cast<double>( ftell( fp ) ) / fileSize;
2445 };
2446
2447 double previousReportedProgress = -1.0;
2448
2449 while( ( tok = lexer.NextTok() ) != DSN_EOF )
2450 {
2451 if( aProgressReporter && ( currentProgress() - previousReportedProgress ) > 0.01 )
2452 {
2453 if( !aProgressReporter->KeepRefreshing() )
2454 THROW_IO_ERROR( _( "File import cancelled by user." ) );
2455
2456 aProgressReporter->SetCurrentProgress( currentProgress() );
2457 previousReportedProgress = currentProgress();
2458 }
2459
2460 if( tok == DSN_RIGHT )
2461 {
2462 cNode = iNode;
2463 if( cNode )
2464 {
2465 iNode = cNode->GetParent();
2466 }
2467 else
2468 {
2469 //too many closing brackets
2470 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2471 }
2472 }
2473 else if( tok == DSN_LEFT )
2474 {
2475 tok = lexer.NextTok();
2476 str = wxString( lexer.CurText(), *conv );
2477 cNode = new XNODE( wxXML_ELEMENT_NODE, str );
2478
2479 if( iNode )
2480 {
2481 //we will add it as attribute as well as child node
2482 InsertAttributeAtEnd( iNode, str );
2483 iNode->AddChild( cNode );
2484 }
2485 else if( !cadstarFileCheckDone )
2486 {
2487 if( cNode->GetName() != aFileTypeIdentifier )
2488 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2489
2490 cadstarFileCheckDone = true;
2491 }
2492
2493 iNode = cNode;
2494 }
2495 else if( iNode )
2496 {
2497 str = wxString( lexer.CurText(), *conv );
2498 //Insert even if string is empty
2499 InsertAttributeAtEnd( iNode, str );
2500 }
2501 else
2502 {
2503 //not enough closing brackets
2504 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2505 }
2506 }
2507
2508 // Not enough closing brackets
2509 if( iNode != nullptr )
2510 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2511
2512 // Throw if no data was parsed
2513 if( cNode )
2514 return cNode;
2515 else
2516 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2517
2518 return nullptr;
2519}
2520
2521
2522bool CADSTAR_ARCHIVE_PARSER::IsValidAttribute( wxXmlAttribute* aAttribute )
2523{
2524 return aAttribute->GetName() != wxT( "numAttributes" );
2525}
2526
2527
2529 bool aIsRequired )
2530{
2531 wxString attrName, retVal;
2532 attrName = "attr";
2533 attrName << aID;
2534
2535 if( !aNode->GetAttribute( attrName, &retVal ) )
2536 {
2537 if( aIsRequired )
2538 THROW_MISSING_PARAMETER_IO_ERROR( std::to_string( aID ), aNode->GetName() );
2539 else
2540 return wxEmptyString;
2541 }
2542
2543 return retVal;
2544}
2545
2546
2548 bool aIsRequired )
2549{
2550 long retVal;
2551 bool success = GetXmlAttributeIDString( aNode, aID, aIsRequired ).ToLong( &retVal );
2552
2553 if( !success )
2554 {
2555 if( aIsRequired )
2556 THROW_PARSING_IO_ERROR( std::to_string( aID ), aNode->GetName() );
2557 else
2558 return UNDEFINED_VALUE;
2559 }
2560
2561 return retVal;
2562}
2563
2564
2566{
2567 if( aNode && aNode->GetChildren() )
2568 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
2569}
2570
2571
2573{
2574 if( aNode && aNode->GetNext() )
2575 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetNext()->GetName(), aNode->GetParent()->GetName() );
2576}
2577
2578
2580 EVALUE& aValueToParse )
2581{
2582 if( aNode->GetChildren()->GetName() == wxT( "E" ) )
2583 aValueToParse.Parse( aNode->GetChildren(), aContext );
2584 else
2585 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
2586}
2587
2588
2589std::vector<CADSTAR_ARCHIVE_PARSER::POINT> CADSTAR_ARCHIVE_PARSER::ParseAllChildPoints(
2590 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes, int aExpectedNumPoints )
2591{
2592 std::vector<POINT> retVal;
2593
2594 XNODE* cNode = aNode->GetChildren();
2595
2596 for( ; cNode; cNode = cNode->GetNext() )
2597 {
2598 if( cNode->GetName() == wxT( "PT" ) )
2599 {
2600 POINT pt;
2601 //TODO try.. catch + throw again with more detailed error information
2602 pt.Parse( cNode, aContext );
2603 retVal.push_back( pt );
2604 }
2605 else if( aTestAllChildNodes )
2606 {
2607 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2608 }
2609 }
2610
2611 if( aExpectedNumPoints != UNDEFINED_VALUE
2612 && retVal.size() != static_cast<size_t>( aExpectedNumPoints ) )
2613 {
2615 _( "Unexpected number of points in '%s'. Found %d but expected %d." ),
2616 aNode->GetName(), retVal.size(), aExpectedNumPoints ) );
2617 }
2618
2619 return retVal;
2620}
2621
2622
2623std::vector<CADSTAR_ARCHIVE_PARSER::VERTEX> CADSTAR_ARCHIVE_PARSER::ParseAllChildVertices(
2624 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes )
2625{
2626 std::vector<VERTEX> retVal;
2627
2628 XNODE* cNode = aNode->GetChildren();
2629
2630 for( ; cNode; cNode = cNode->GetNext() )
2631 {
2632 if( VERTEX::IsVertex( cNode ) )
2633 {
2634 VERTEX vertex;
2635 //TODO try.. catch + throw again with more detailed error information
2636 vertex.Parse( cNode, aContext );
2637 retVal.push_back( vertex );
2638 }
2639 else if( aTestAllChildNodes )
2640 {
2641 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2642 }
2643 }
2644
2645 return retVal;
2646}
2647
2648
2649std::vector<CADSTAR_ARCHIVE_PARSER::CUTOUT> CADSTAR_ARCHIVE_PARSER::ParseAllChildCutouts(
2650 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes )
2651{
2652 std::vector<CUTOUT> retVal;
2653
2654 XNODE* cNode = aNode->GetChildren();
2655
2656 for( ; cNode; cNode = cNode->GetNext() )
2657 {
2658 if( cNode->GetName() == wxT( "CUTOUT" ) )
2659 {
2660 CUTOUT cutout;
2661 //TODO try.. catch + throw again with more detailed error information
2662 cutout.Parse( cNode, aContext );
2663 retVal.push_back( cutout );
2664 }
2665 else if( aTestAllChildNodes )
2666 {
2667 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2668 }
2669 }
2670
2671 return retVal;
2672}
2673
2674
2676{
2677 XNODE* childNodes = aNode->GetChildren();
2678 long retval = 0;
2679
2680 for( ; childNodes; childNodes = childNodes->GetNext() )
2681 retval++;
2682
2683 return retval;
2684}
2685
2686
2687long CADSTAR_ARCHIVE_PARSER::GetNumberOfStepsForReporting( XNODE* aRootNode, std::vector<wxString> aSubNodeChildrenToCount )
2688{
2689 XNODE* level1Node = aRootNode->GetChildren();
2690 long retval = 0;
2691
2692 for( ; level1Node; level1Node = level1Node->GetNext() )
2693 {
2694 for( wxString childNodeName : aSubNodeChildrenToCount )
2695 {
2696 if( level1Node->GetName() == childNodeName )
2697 retval += GetNumberOfChildNodes( level1Node );
2698 }
2699
2700 retval++;
2701 }
2702
2703 return retval;
2704}
2705
2706
2707wxString CADSTAR_ARCHIVE_PARSER::HandleTextOverbar( wxString aCadstarString )
2708{
2709 wxString escapedText = aCadstarString;
2710
2711 escapedText.Replace( wxT( "'" ), wxT( "~" ) );
2712
2713 return ConvertToNewOverbarNotation( escapedText );
2714}
2715
2716
2718{
2719 if( !aKiCadTextItem->GetText().IsEmpty() )
2720 {
2721 VECTOR2I positionOffset( 0, aKiCadTextItem->GetInterline() );
2722 RotatePoint( positionOffset, aKiCadTextItem->GetTextAngle() );
2723
2724 EDA_ITEM* textEdaItem = dynamic_cast<EDA_ITEM*>( aKiCadTextItem );
2725
2726 if( textEdaItem &&
2727 ( textEdaItem->Type() == LIB_TEXT_T || textEdaItem->Type() == LIB_FIELD_T ) )
2728 {
2729 // Y coordinate increases upwards in the symbol editor
2730 positionOffset.y = -positionOffset.y;
2731 }
2732
2733 //Count num of additional lines
2734 wxString text = aKiCadTextItem->GetText();
2735 int numExtraLines = text.Replace( "\n", "\n" );
2736 numExtraLines -= text.at( text.size() - 1 ) == '\n'; // Ignore new line character at end
2737 positionOffset.x *= numExtraLines;
2738 positionOffset.y *= numExtraLines;
2739
2740 aKiCadTextItem->Offset( positionOffset );
2741 }
2742}
2743
2745{
2746 if( m_progressReporter )
2747 {
2749
2751 THROW_IO_ERROR( _( "File import cancelled by user." ) );
2752 }
2753}
2754
KICAD_PLUGIN_EXPORT SCENEGRAPH * Load(char const *aFileName)
reads a model file and creates a generic display structure
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 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 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.
@ USE_SWAP_LAYER
Display when Mirrored.
@ NO_SWAP
Display when Unmirrored.
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 const long UNDEFINED_VALUE
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)
Corrects 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.
@ OUTLINE
Unfilled closed shape.
@ 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 cancelled.
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.
@ PART
Only library Attributes.
Implement a lexical analyzer for the SPECCTRA DSN file format.
Definition: dsnlexer.h:79
const char * CurText() const
Return a pointer to the current token's text.
Definition: dsnlexer.h:398
int NextTok()
Return the next token found in the input file or DSN_EOF when reaching the end of file.
Definition: dsnlexer.cpp:519
A base class for most all the KiCad significant classes used in schematics and boards.
Definition: eda_item.h:85
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:72
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:120
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:87
int GetInterline() const
Return the distance between two lines of text.
Definition: eda_text.cpp:497
void Offset(const VECTOR2I &aOffset)
Definition: eda_text.cpp:389
A progress reporter interface for use in multi-threaded environments.
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void AdvanceProgress()=0
Increment the progress bar length (inside the current virtual zone).
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.
Definition: shape_arc.cpp:209
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.
Represent a set of closed polygons.
int AddOutline(const SHAPE_LINE_CHAIN &aOutline)
Adds a new hole to the given outline (default: last) and returns its index.
int AddHole(const SHAPE_LINE_CHAIN &aHole, int aOutline=-1)
Return the area of this poly set.
Hold an XML or S-expression element.
Definition: xnode.h:44
XNODE * GetParent() const
Definition: xnode.h:72
XNODE * GetChildren() const
Definition: xnode.h:62
XNODE * GetNext() const
Definition: xnode.h:67
@ DSN_LEFT
Definition: dsnlexer.h:67
@ DSN_RIGHT
Definition: dsnlexer.h:66
@ DSN_EOF
Definition: dsnlexer.h:69
#define _(s)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
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:83
PARSE_RESULT Parse(const std::string &aString, NOTATION aNotation=NOTATION::SI, SIM_VALUE::TYPE aValueType=SIM_VALUE::TYPE_FLOAT)
Definition: sim_value.cpp:189
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
virtual void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
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...
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
Represents a cutout in a closed shape (e.g.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
Represents a floating value in E notation.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
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.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
static bool IsGrid(XNODE *aNode)
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
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
virtual void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
NETELEMENT_ID ID
First character is "J".
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
std::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
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
POSITION
Positioning of pin names can be in one of four quadrants.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
< "SWAPGATE" Node name (represents an "Element")
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
static PIN_TYPE GetPinType(XNODE *aNode)
Represents a point in x,y coordinates.
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool IsEmpty()
Determines if this is empty (i.e. no design reuse associated)
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
virtual void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
SHAPE_POLY_SET ConvertToPolySet(const std::function< VECTOR2I(const VECTOR2I &)> aCadstarToKicadPointCallback, double aAccuracy) const
SHAPE_LINE_CHAIN OutlineAsChain(const std::function< VECTOR2I(const VECTOR2I &)> aCadstarToKicadPointCallback, double aAccuracy) const
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
bool ParseSubNode(XNODE *aChildNode, PARSER_CONTEXT *aContext)
void ParseIdentifiers(XNODE *aNode, PARSER_CONTEXT *aContext)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
Corresponds to CADSTAR "origin".
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
< Nodename = "VARIANT" or "VMASTER" (master variant
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
Represents a vertex in a shape.
void AppendToChain(SHAPE_LINE_CHAIN *aChainToAppendTo, const std::function< VECTOR2I(const VECTOR2I &)> aCadstarToKicadPointCallback, double aAccuracy) const
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
Hold a keyword string and its unique integer token.
Definition: dsnlexer.h:40
void RotatePoint(int *pX, int *pY, const EDA_ANGLE &aAngle)
Definition: trigo.cpp:183
@ LIB_TEXT_T
Definition: typeinfo.h:200
@ LIB_FIELD_T
Definition: typeinfo.h:208
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618