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 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 || 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" ),
399 wxString::Format( "%s->%s", aNode->GetParent()->GetName(),
400 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;
448 Center.x = UNDEFINED_VALUE;
449 Center.y = UNDEFINED_VALUE;
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
471 Center.x = UNDEFINED_VALUE;
472 Center.y = UNDEFINED_VALUE;
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 if( Type == VERTEX_TYPE::POINT )
490 {
491 aChainToAppendTo->Append( aCadstarToKicadPointCallback( End ) );
492 return;
493 }
494
495 wxCHECK_MSG( aChainToAppendTo->PointCount() > 0, /*void*/,
496 "Can't append an arc to vertex to an empty chain" );
497
498 aChainToAppendTo->Append( BuildArc( aChainToAppendTo->GetPoint( -1 ),
499 aCadstarToKicadPointCallback ),
500 aAccuracy );
501}
502
503
505 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback ) const
506{
507 wxCHECK_MSG( Type != VERTEX_TYPE::POINT, SHAPE_ARC(),
508 "Can't build an arc for a straight segment!" );
509
510 VECTOR2I startPoint = aPrevPoint;
511 VECTOR2I endPoint = aCadstarToKicadPointCallback( End );
512 VECTOR2I centerPoint;
513
515 centerPoint = ( startPoint / 2 ) + ( endPoint / 2 );
516 else
517 centerPoint = aCadstarToKicadPointCallback( Center );
518
519 bool clockwise = Type == VERTEX_TYPE::CLOCKWISE_ARC
521
522 // A bit of a hack to figure out if we need to invert clockwise due to the transform
523 VECTOR2I transform = aCadstarToKicadPointCallback( { 500, 500 } )
524 - aCadstarToKicadPointCallback( { 0, 0 } );
525
526 if( ( transform.x > 0 && transform.y < 0 ) || ( transform.x < 0 && transform.y > 0 ) )
527 clockwise = !clockwise;
528
529 SHAPE_ARC arc;
530
531 return arc.ConstructFromStartEndCenter( startPoint, endPoint, centerPoint, clockwise );
532}
533
534
536{
537 wxASSERT( aNode->GetName() == wxT( "CUTOUT" ) );
538
539 Vertices = ParseAllChildVertices( aNode, aContext, true );
540}
541
542
544{
545 wxString aNodeName = aNode->GetName();
546
547 if( aNodeName == wxT( "OPENSHAPE" ) || aNodeName == wxT( "OUTLINE" )
548 || aNodeName == wxT( "SOLID" ) || aNodeName == wxT( "HATCHED" ) )
549 {
550 return true;
551 }
552 else
553 {
554 return false;
555 }
556}
557
558
560{
561 wxASSERT( IsShape( aNode ) );
562
563 wxString aNodeName = aNode->GetName();
564
565 if( aNodeName == wxT( "OPENSHAPE" ) )
566 {
568 Vertices = ParseAllChildVertices( aNode, aContext, true );
569 Cutouts.clear();
570 HatchCodeID = wxEmptyString;
571 }
572 else if( aNodeName == wxT( "OUTLINE" ) )
573 {
574 Type = SHAPE_TYPE::OUTLINE;
575 Vertices = ParseAllChildVertices( aNode, aContext, false );
576 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
577 HatchCodeID = wxEmptyString;
578 }
579 else if( aNodeName == wxT( "SOLID" ) )
580 {
581 Type = SHAPE_TYPE::SOLID;
582 Vertices = ParseAllChildVertices( aNode, aContext, false );
583 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
584 HatchCodeID = wxEmptyString;
585 }
586 else if( aNodeName == wxT( "HATCHED" ) )
587 {
588 Type = SHAPE_TYPE::HATCHED;
589 Vertices = ParseAllChildVertices( aNode, aContext, false );
590 Cutouts = ParseAllChildCutouts( aNode, aContext, false );
591 HatchCodeID = GetXmlAttributeIDString( aNode, 0 );
592 }
593 else
594 {
595 wxASSERT_MSG( true, wxT( "Unknown SHAPE type" ) );
596 }
597}
598
600 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
601 double aAccuracy ) const
602{
603 SHAPE_LINE_CHAIN outline;
604
605 if( Vertices.size() == 0 )
606 return outline;
607
608 for( const auto& vertex : Vertices )
609 vertex.AppendToChain( &outline, aCadstarToKicadPointCallback, aAccuracy );
610
611 if( Type != SHAPE_TYPE::OPENSHAPE )
612 {
613 outline.SetClosed( true );
614
615 // Append after closing, to ensre first and last point remain the same
616 outline.Append( outline.CPoint( 0 ), true );
617 }
618
619 return outline;
620}
621
622
624 const std::function<VECTOR2I( const VECTOR2I& )> aCadstarToKicadPointCallback,
625 double aAccuracy ) const
626{
627 SHAPE_POLY_SET polyset;
628
629 // We shouldn't convert openshapes to polyset!
630 wxCHECK( Type != SHAPE_TYPE::OPENSHAPE, polyset );
631
632 polyset.AddOutline( OutlineAsChain( aCadstarToKicadPointCallback, aAccuracy ) );
633
634 for( const auto& cutout : Cutouts )
635 {
636 SHAPE_LINE_CHAIN hole;
637
638 if( cutout.Vertices.size() == 0 )
639 continue;
640
641 for( const auto& cutoutVertex : cutout.Vertices )
642 cutoutVertex.AppendToChain( &hole, aCadstarToKicadPointCallback, aAccuracy );
643
644 hole.SetClosed( true );
645
646 // Append after closing, to ensre first and last point remain the same
647 cutout.Vertices.at( 0 ).AppendToChain( &hole, aCadstarToKicadPointCallback, aAccuracy );
648
649 polyset.AddHole( hole );
650 }
651
652 return polyset;
653}
654
655
657{
658 wxASSERT( aNode->GetName() == wxT( "UNITS" ) );
659
660 wxString unit = GetXmlAttributeIDString( aNode, 0 );
661
662 if( unit == wxT( "CENTIMETER" ) )
663 return UNITS::CENTIMETER;
664 else if( unit == wxT( "INCH" ) )
665 return UNITS::INCH;
666 else if( unit == wxT( "METER" ) )
667 return UNITS::METER;
668 else if( unit == wxT( "MICROMETRE" ) )
669 return UNITS::MICROMETRE;
670 else if( unit == wxT( "MM" ) )
671 return UNITS::MM;
672 else if( unit == wxT( "THOU" ) )
673 return UNITS::THOU;
674 else if( unit == wxT( "DESIGN" ) )
675 return UNITS::DESIGN;
676 else
677 THROW_UNKNOWN_PARAMETER_IO_ERROR( unit, wxT( "UNITS" ) );
678
679 return UNITS();
680}
681
682
684{
685 wxASSERT( aNode->GetName() == wxT( "ANGUNITS" ) );
686
687 wxString angUnitStr = GetXmlAttributeIDString( aNode, 0 );
688
689 if( angUnitStr == wxT( "DEGREES" ) )
690 return ANGUNITS::DEGREES;
691 else if( angUnitStr == wxT( "RADIANS" ) )
692 return ANGUNITS::RADIANS;
693 else
694 THROW_UNKNOWN_PARAMETER_IO_ERROR( angUnitStr, aNode->GetName() );
695
696 return ANGUNITS();
697}
698
699
701{
702 wxString aNodeName = aNode->GetName();
703
704 if( aNodeName == wxT( "FRACTIONALGRID" ) || aNodeName == wxT( "STEPGRID" ) )
705 return true;
706 else
707 return false;
708}
709
710
712{
713 wxASSERT( IsGrid( aNode ) );
714
715 wxString aNodeName = aNode->GetName();
716
717 if( aNodeName == wxT( "FRACTIONALGRID" ) )
719 else if( aNodeName == wxT( "STEPGRID" ) )
720 Type = GRID_TYPE::STEPGRID;
721 else
722 wxASSERT_MSG( true, wxT( "Unknown Grid Type" ) );
723
724 Name = GetXmlAttributeIDString( aNode, 0 );
725 Param1 = GetXmlAttributeIDLong( aNode, 1 );
726 Param2 = GetXmlAttributeIDLong( aNode, 2 );
727}
728
729
731{
732 wxASSERT( aNode->GetName() == wxT( "GRIDS" ) );
733
734 XNODE* cNode = aNode->GetChildren();
735
736 for( ; cNode; cNode = cNode->GetNext() )
737 {
738 wxString cNodeName = cNode->GetName();
739
740 if( cNodeName == wxT( "WORKINGGRID" ) )
741 {
742 XNODE* workingGridNode = cNode->GetChildren();
743
744 if( !GRID::IsGrid( workingGridNode ) )
745 {
747 workingGridNode->GetName(), wxT( "GRIDS -> WORKINGGRID" ) );
748 }
749 else
750 {
751 WorkingGrid.Parse( workingGridNode, aContext );
752 }
753 }
754 else if( cNodeName == wxT( "SCREENGRID" ) )
755 {
756 XNODE* screenGridNode = cNode->GetChildren();
757
758 if( !GRID::IsGrid( screenGridNode ) )
759 {
761 screenGridNode->GetName(), wxT( "GRIDS -> SCREENGRID" ) );
762 }
763 else
764 {
765 ScreenGrid.Parse( screenGridNode, aContext );
766 }
767 }
768 else if( GRID::IsGrid( cNode ) )
769 {
770 GRID userGrid;
771 userGrid.Parse( cNode, aContext );
772 UserGrids.push_back( userGrid );
773 }
774 }
775}
776
777
779{
780 wxString cNodeName = aChildNode->GetName();
781
782 if( cNodeName == wxT( "UNITS" ) )
783 {
784 Units = ParseUnits( aChildNode );
785 }
786 else if( cNodeName == wxT( "UNITSPRECISION" ) )
787 {
788 UnitDisplPrecision = GetXmlAttributeIDLong( aChildNode, 0 );
789 }
790 else if( cNodeName == wxT( "INTERLINEGAP" ) )
791 {
792 InterlineGap = GetXmlAttributeIDLong( aChildNode, 0 );
793 }
794 else if( cNodeName == wxT( "BARLINEGAP" ) )
795 {
796 BarlineGap = GetXmlAttributeIDLong( aChildNode, 0 );
797 }
798 else if( cNodeName == wxT( "ALLOWBARTEXT" ) )
799 {
800 AllowBarredText = true;
801 }
802 else if( cNodeName == wxT( "ANGULARPRECISION" ) )
803 {
804 AngularPrecision = GetXmlAttributeIDLong( aChildNode, 0 );
805 }
806 else if( cNodeName == wxT( "DESIGNORIGIN" ) )
807 {
808 DesignOrigin.Parse( aChildNode->GetChildren(), aContext );
809 }
810 else if( cNodeName == wxT( "DESIGNAREA" ) )
811 {
812 std::vector<POINT> pts = ParseAllChildPoints( aChildNode, aContext, true, 2 );
813 DesignArea = std::make_pair( pts[0], pts[1] );
814 }
815 else if( cNodeName == wxT( "DESIGNREF" ) )
816 {
817 DesignOrigin.Parse( aChildNode->GetChildren(), aContext );
818 }
819 else if( cNodeName == wxT( "DESIGNLIMIT" ) )
820 {
821 DesignLimit.Parse( aChildNode->GetChildren(), aContext );
822 }
823 else if( cNodeName == wxT( "PINNOOFFSET" ) )
824 {
825 PinNoOffset = GetXmlAttributeIDLong( aChildNode, 0 );
826 }
827 else if( cNodeName == wxT( "PINNOANGLE" ) )
828 {
829 PinNoAngle = GetXmlAttributeIDLong( aChildNode, 0 );
830 }
831 else
832 {
833 return false;
834 }
835
836 return true;
837}
838
839
841{
842 wxASSERT( aNode->GetName() == wxT( "SETTINGS" ) );
843
844 XNODE* cNode = aNode->GetChildren();
845
846 for( ; cNode; cNode = cNode->GetNext() )
847 {
848 wxString cNodeName = cNode->GetName();
849
850 if( ParseSubNode( cNode, aContext ) )
851 continue;
852 else
853 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "SETTINGS" ) );
854 }
855}
856
857
858wxString CADSTAR_ARCHIVE_PARSER::ParseTextFields( const wxString& aTextString,
859 PARSER_CONTEXT* aContext )
860{
861 static const std::map<TEXT_FIELD_NAME, wxString> txtTokens =
862 {
863 { TEXT_FIELD_NAME::DESIGN_TITLE, wxT( "DESIGN TITLE" ) },
864 { TEXT_FIELD_NAME::SHORT_JOBNAME, wxT( "SHORT_JOBNAME" ) },
865 { TEXT_FIELD_NAME::LONG_JOBNAME, wxT( "LONG_JOBNAME" ) },
866 { TEXT_FIELD_NAME::NUM_OF_SHEETS, wxT( "NUM_OF_SHEETS" ) },
867 { TEXT_FIELD_NAME::SHEET_NUMBER, wxT( "SHEET_NUMBER" ) },
868 { TEXT_FIELD_NAME::SHEET_NAME, wxT( "SHEET_NAME" ) },
869 { TEXT_FIELD_NAME::VARIANT_NAME, wxT( "VARIANT_NAME" ) },
870 { TEXT_FIELD_NAME::VARIANT_DESCRIPTION, wxT( "VARIANT_DESCRIPTION" ) },
871 { TEXT_FIELD_NAME::REG_USER, wxT( "REG_USER" ) },
872 { TEXT_FIELD_NAME::COMPANY_NAME, wxT( "COMPANY_NAME" ) },
873 { TEXT_FIELD_NAME::CURRENT_USER, wxT( "CURRENT_USER" ) },
874 { TEXT_FIELD_NAME::DATE, wxT( "DATE" ) },
875 { TEXT_FIELD_NAME::TIME, wxT( "TIME" ) },
876 { TEXT_FIELD_NAME::MACHINE_NAME, wxT( "MACHINE_NAME" ) },
877 { TEXT_FIELD_NAME::FROM_FILE, wxT( "FROM_FILE" ) },
878 { TEXT_FIELD_NAME::DISTANCE, wxT( "DISTANCE" ) },
879 { TEXT_FIELD_NAME::UNITS_SHORT, wxT( "UNITS SHORT" ) },
880 { TEXT_FIELD_NAME::UNITS_ABBREV, wxT( "UNITS ABBREV" ) },
881 { TEXT_FIELD_NAME::UNITS_FULL, wxT( "UNITS FULL" ) },
882 { TEXT_FIELD_NAME::HYPERLINK, wxT( "HYPERLINK" ) }
883 };
884
885 wxString remainingStr = aTextString;
886 wxString returnStr;
887
888 while( remainingStr.size() > 0 )
889 {
890 // Find the start token
891 size_t startpos = remainingStr.Find( wxT( "<@" ) );
892
893 if( static_cast<int>( startpos ) == wxNOT_FOUND )
894 {
895 // No more fields to parse, add to return string
896 returnStr += remainingStr;
897 break;
898 }
899
900 if( startpos > 0 )
901 returnStr += remainingStr.SubString( 0, startpos - 1 );
902
903 if( ( startpos + 2 ) >= remainingStr.size() )
904 break;
905
906 remainingStr = remainingStr.Mid( startpos + 2 );
907
908 //Find the expected token for the field
910
911 for( std::pair<TEXT_FIELD_NAME, wxString> txtF : txtTokens )
912 {
913 if( remainingStr.StartsWith( txtF.second ) )
914 {
915 foundField = txtF.first;
916 break;
917 }
918 }
919
920 if( foundField == TEXT_FIELD_NAME::NONE )
921 {
922 // Not a valid field, lets keep looking
923 returnStr += wxT( "<@" );
924 continue;
925 }
926
927 //Now lets find the end token
928 size_t endpos = remainingStr.Find( wxT( "@>" ) );
929
930 if( static_cast<int>( endpos ) == wxNOT_FOUND )
931 {
932 // The field we found isn't valid as it doesn't have a termination
933 // Lets append the whole thing as plain text
934 returnStr += wxT( "<@" ) + remainingStr;
935 break;
936 }
937
938 size_t valueStart = txtTokens.at( foundField ).size();
939 wxString fieldValue = remainingStr.SubString( valueStart, endpos - 1 );
940 wxString address;
941
942 if( foundField == TEXT_FIELD_NAME::FROM_FILE || foundField == TEXT_FIELD_NAME::HYPERLINK )
943 {
944 // The first character should always be a double quotation mark
945 wxASSERT_MSG( fieldValue.at( 0 ) == '"', "Expected '\"' as the first character" );
946
947 size_t splitPos = fieldValue.find_first_of( '"', 1 );
948 address = fieldValue.SubString( 1, splitPos - 1 );
949
950 if( foundField == TEXT_FIELD_NAME::HYPERLINK )
951 {
952 // Assume the last two characters are "@>"
953 wxASSERT_MSG( remainingStr.EndsWith( wxT( "@>" ) ),
954 "Expected '@>' at the end of a hyperlink" );
955
956 fieldValue = remainingStr.SubString( valueStart + splitPos + 1,
957 remainingStr.Length() - 3 );
958
959 remainingStr = wxEmptyString;
960 }
961 else
962 {
963 fieldValue = fieldValue.Mid( splitPos + 1 );
964 }
965 }
966
967 switch( foundField )
968 {
980
981 if( aContext->TextFieldToValuesMap.find( foundField )
982 != aContext->TextFieldToValuesMap.end() )
983 {
984 aContext->InconsistentTextFields.insert( foundField );
985 }
986 else
987 {
988 aContext->TextFieldToValuesMap.insert( { foundField, fieldValue } );
989 }
990
992
996 returnStr += wxT( "${" ) + CADSTAR_TO_KICAD_FIELDS.at( foundField ) + wxT( "}" );
997 break;
998
1003 // Just flatten the text for distances
1004 returnStr += fieldValue;
1005 break;
1006
1008 {
1009 wxFileName fn( address );
1010 wxString fieldFmt = wxT( "FROM_FILE_%s_%s" );
1011 wxString fieldName = wxString::Format( fieldFmt, fn.GetName(), fn.GetExt() );
1012
1013 int version = 1;
1014
1015 while(
1016 aContext->FilenamesToTextMap.find( fieldName )
1017 != aContext->FilenamesToTextMap.end()
1018 && aContext->FilenamesToTextMap.at( fieldName ) != fieldValue )
1019 {
1020 fieldName = wxString::Format( fieldFmt, fn.GetName(), fn.GetExt() )
1021 + wxString::Format( wxT( "_%d" ), version++ );
1022 }
1023
1024 aContext->FilenamesToTextMap[fieldName] = fieldValue;
1025 returnStr += wxT( "${" ) + fieldName + wxT( "}" );
1026 }
1027 break;
1028
1030 {
1031 aContext->TextToHyperlinksMap[fieldValue] = address;
1032 returnStr += ParseTextFields( fieldValue, aContext );
1033 }
1034 break;
1035
1037 wxFAIL_MSG( "We should have already covered this scenario above" );
1038 break;
1039 }
1040
1041
1042 if( ( endpos + 2 ) >= remainingStr.size() )
1043 break;
1044
1045 remainingStr = remainingStr.Mid( endpos + 2 );
1046 }
1047
1048 return returnStr;
1049}
1050
1051
1053{
1054 wxASSERT( aNode->GetName() == wxT( "ALIGN" ) );
1055
1056 wxString alignmentStr = GetXmlAttributeIDString( aNode, 0 );
1057
1058 if( alignmentStr == wxT( "BOTTOMCENTER" ) )
1060 else if( alignmentStr == wxT( "BOTTOMLEFT" ) )
1061 return ALIGNMENT::BOTTOMLEFT;
1062 else if( alignmentStr == wxT( "BOTTOMRIGHT" ) )
1064 else if( alignmentStr == wxT( "CENTERCENTER" ) )
1066 else if( alignmentStr == wxT( "CENTERLEFT" ) )
1067 return ALIGNMENT::CENTERLEFT;
1068 else if( alignmentStr == wxT( "CENTERRIGHT" ) )
1070 else if( alignmentStr == wxT( "TOPCENTER" ) )
1071 return ALIGNMENT::TOPCENTER;
1072 else if( alignmentStr == wxT( "TOPLEFT" ) )
1073 return ALIGNMENT::TOPLEFT;
1074 else if( alignmentStr == wxT( "TOPRIGHT" ) )
1075 return ALIGNMENT::TOPRIGHT;
1076 else
1077 THROW_UNKNOWN_PARAMETER_IO_ERROR( alignmentStr, wxT( "ALIGN" ) );
1078
1079 //shouldn't be here but avoids compiler warning
1081}
1082
1083
1085{
1086 wxASSERT( aNode->GetName() == wxT( "JUSTIFICATION" ) );
1087
1088 wxString justificationStr = GetXmlAttributeIDString( aNode, 0 );
1089
1090 if( justificationStr == wxT( "LEFT" ) )
1091 return JUSTIFICATION::LEFT;
1092 else if( justificationStr == wxT( "RIGHT" ) )
1093 return JUSTIFICATION::RIGHT;
1094 else if( justificationStr == wxT( "CENTER" ) )
1095 return JUSTIFICATION::CENTER;
1096 else
1097 THROW_UNKNOWN_PARAMETER_IO_ERROR( justificationStr, wxT( "JUSTIFICATION" ) );
1098
1099 return JUSTIFICATION::LEFT;
1100}
1101
1102
1104{
1105 wxASSERT( aNode->GetName() == wxT( "READABILITY" ) );
1106
1107 wxString readabilityStr = GetXmlAttributeIDString( aNode, 0 );
1108
1109 if( readabilityStr == wxT( "BOTTOM_TO_TOP" ) )
1111 else if( readabilityStr == wxT( "TOP_TO_BOTTOM" ) )
1113 else
1114 THROW_UNKNOWN_PARAMETER_IO_ERROR( readabilityStr, wxT( "READABILITY" ) );
1115
1117}
1118
1119
1121 PARSER_CONTEXT* aContext )
1122{
1123 TextCodeID = GetXmlAttributeIDString( aNode, 0 );
1124 LayerID = GetXmlAttributeIDString( aNode, 1 );
1125}
1126
1127
1129 PARSER_CONTEXT* aContext )
1130{
1131 wxString cNodeName = aChildNode->GetName();
1132
1133 if( cNodeName == wxT( "PT" ) )
1134 Position.Parse( aChildNode, aContext );
1135 else if( cNodeName == wxT( "ORIENT" ) )
1136 OrientAngle = GetXmlAttributeIDLong( aChildNode, 0 );
1137 else if( cNodeName == wxT( "MIRROR" ) )
1138 Mirror = true;
1139 else if( cNodeName == wxT( "FIX" ) )
1140 Fixed = true;
1141 else if( cNodeName == wxT( "ALIGN" ) )
1142 Alignment = ParseAlignment( aChildNode );
1143 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1144 Justification = ParseJustification( aChildNode );
1145 else
1146 return false;
1147
1148 return true;
1149}
1150
1151
1153{
1154 wxASSERT( aNode->GetName() == wxT( "ATTRLOC" ) );
1155
1156 ParseIdentifiers( aNode, aContext );
1157
1158 //Parse child nodes
1159 XNODE* cNode = aNode->GetChildren();
1160
1161 for( ; cNode; cNode = cNode->GetNext() )
1162 {
1163 if( ParseSubNode( cNode, aContext ) )
1164 continue;
1165 else
1166 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "ATTRLOC" ) );
1167 }
1168
1169 if( Position.x == UNDEFINED_VALUE || Position.y == UNDEFINED_VALUE )
1170 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "ATTRLOC" ) );
1171}
1172
1173
1175{
1176 wxASSERT( aNode->GetName() == wxT( "COLUMNORDER" ) );
1177
1178 ID = GetXmlAttributeIDLong( aNode, 0 );
1179 Order = GetXmlAttributeIDLong( aNode, 1 );
1180
1181 CheckNoChildNodes( aNode );
1182}
1183
1184
1186{
1187 wxASSERT( aNode->GetName() == wxT( "COLUMNWIDTH" ) );
1188
1189 ID = GetXmlAttributeIDLong( aNode, 0 );
1190 Width = GetXmlAttributeIDLong( aNode, 1 );
1191
1192 CheckNoChildNodes( aNode );
1193}
1194
1195
1197{
1198 wxASSERT( aNode->GetName() == wxT( "ATTRNAME" ) );
1199
1200 ID = GetXmlAttributeIDString( aNode, 0 );
1201 Name = GetXmlAttributeIDString( aNode, 1 );
1202
1203 XNODE* cNode = aNode->GetChildren();
1204 wxString location = wxString::Format( "ATTRNAME -> %s", Name );
1205
1206 for( ; cNode; cNode = cNode->GetNext() )
1207 {
1208 wxString cNodeName = cNode->GetName();
1209
1210 if( cNodeName == wxT( "ATTROWNER" ) )
1211 {
1212 wxString attOwnerVal = GetXmlAttributeIDString( cNode, 0 );
1213
1214 if( attOwnerVal == wxT( "ALL_ITEMS" ) )
1215 AttributeOwner = ATTROWNER::ALL_ITEMS;
1216 else if( attOwnerVal == wxT( "AREA" ) )
1217 AttributeOwner = ATTROWNER::AREA;
1218 else if( attOwnerVal == wxT( "BOARD" ) )
1219 AttributeOwner = ATTROWNER::BOARD;
1220 else if( attOwnerVal == wxT( "COMPONENT" ) )
1221 AttributeOwner = ATTROWNER::COMPONENT;
1222 else if( attOwnerVal == wxT( "CONNECTION" ) )
1223 AttributeOwner = ATTROWNER::CONNECTION;
1224 else if( attOwnerVal == wxT( "COPPER" ) )
1225 AttributeOwner = ATTROWNER::COPPER;
1226 else if( attOwnerVal == wxT( "DOCSYMBOL" ) )
1227 AttributeOwner = ATTROWNER::DOCSYMBOL;
1228 else if( attOwnerVal == wxT( "FIGURE" ) )
1229 AttributeOwner = ATTROWNER::FIGURE;
1230 else if( attOwnerVal == wxT( "NET" ) )
1231 AttributeOwner = ATTROWNER::NET;
1232 else if( attOwnerVal == wxT( "NETCLASS" ) )
1233 AttributeOwner = ATTROWNER::NETCLASS;
1234 else if( attOwnerVal == wxT( "PART" ) )
1235 AttributeOwner = ATTROWNER::PART;
1236 else if( attOwnerVal == wxT( "PART_DEFINITION" ) )
1237 AttributeOwner = ATTROWNER::PART_DEFINITION;
1238 else if( attOwnerVal == wxT( "PIN" ) )
1239 AttributeOwner = ATTROWNER::PIN;
1240 else if( attOwnerVal == wxT( "SIGNALREF" ) )
1241 AttributeOwner = ATTROWNER::SIGNALREF;
1242 else if( attOwnerVal == wxT( "SYMBOL" ) )
1243 AttributeOwner = ATTROWNER::SYMBOL;
1244 else if( attOwnerVal == wxT( "SYMDEF" ) )
1245 AttributeOwner = ATTROWNER::SYMDEF;
1246 else if( attOwnerVal == wxT( "TEMPLATE" ) )
1247 AttributeOwner = ATTROWNER::TEMPLATE;
1248 else if( attOwnerVal == wxT( "TESTPOINT" ) )
1249 AttributeOwner = ATTROWNER::TESTPOINT;
1250 else
1252 }
1253 else if( cNodeName == wxT( "ATTRUSAGE" ) )
1254 {
1255 wxString attUsageVal = GetXmlAttributeIDString( cNode, 0 );
1256
1257 if( attUsageVal == wxT( "BOTH" ) )
1258 AttributeUsage = ATTRUSAGE::BOTH;
1259 else if( attUsageVal == wxT( "COMPONENT" ) )
1260 AttributeUsage = ATTRUSAGE::COMPONENT;
1261 else if( attUsageVal == wxT( "PART_DEFINITION" ) )
1262 AttributeUsage = ATTRUSAGE::PART_DEFINITION;
1263 else if( attUsageVal == wxT( "PART_LIBRARY" ) )
1264 AttributeUsage = ATTRUSAGE::PART_LIBRARY;
1265 else if( attUsageVal == wxT( "SYMBOL" ) )
1266 AttributeUsage = ATTRUSAGE::SYMBOL;
1267 else
1269 }
1270 else if( cNodeName == wxT( "NOTRANSFER" ) )
1271 {
1272 NoTransfer = true;
1273 }
1274 else if( cNodeName == wxT( "COLUMNORDER" ) )
1275 {
1276 COLUMNORDER cOrder;
1277 cOrder.Parse( cNode, aContext );
1278 ColumnOrders.push_back( cOrder );
1279 }
1280 else if( cNodeName == wxT( "COLUMNWIDTH" ) )
1281 {
1282 COLUMNWIDTH cWidth;
1283 cWidth.Parse( cNode, aContext );
1284 ColumnWidths.push_back( cWidth );
1285 }
1286 else if( cNodeName == wxT( "COLUMNINVISIBLE" ) )
1287 {
1288 ColumnInvisible = true;
1289 }
1290 else
1291 {
1293 }
1294 }
1295}
1296
1297
1299{
1300 wxASSERT( aNode->GetName() == wxT( "ATTR" ) );
1301
1302 AttributeID = GetXmlAttributeIDString( aNode, 0 );
1303 Value = GetXmlAttributeIDString( aNode, 1 );
1304
1305 XNODE* cNode = aNode->GetChildren();
1306
1307 for( ; cNode; cNode = cNode->GetNext() )
1308 {
1309 if( cNode->GetName() == wxT( "READONLY" ) )
1310 {
1311 ReadOnly = true;
1312 }
1313 else if( cNode->GetName() == wxT( "ATTRLOC" ) )
1314 {
1315 AttributeLocation.Parse( cNode, aContext );
1316 HasLocation = true;
1317 }
1318 else
1319 {
1320 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), wxT( "ATTR" ) );
1321 }
1322 }
1323}
1324
1325
1327{
1328 wxASSERT( aNode->GetName() == wxT( "TEXTLOC" ) );
1329
1330 wxString attributeStr = GetXmlAttributeIDString( aNode, 0 );
1331 bool attributeIDisSet = false;
1332
1333 if( attributeStr == wxT( "PART_NAME" ) )
1334 {
1335 AttributeID = PART_NAME_ATTRID;
1336 attributeIDisSet = true;
1337 }
1338 else if( attributeStr == wxT( "COMP_NAME" ) )
1339 {
1340 AttributeID = COMPONENT_NAME_ATTRID;
1341 attributeIDisSet = true;
1342 }
1343 else if( attributeStr == wxT( "COMP_NAME2" ) )
1344 {
1345 AttributeID = COMPONENT_NAME_2_ATTRID;
1346 attributeIDisSet = true;
1347 }
1348 else if( attributeStr == wxT( "SYMBOL_NAME" ) )
1349 {
1350 AttributeID = SYMBOL_NAME_ATTRID;
1351 attributeIDisSet = true;
1352 }
1353 else if( attributeStr == wxT( "LINK_ORIGIN" ) )
1354 {
1355 AttributeID = LINK_ORIGIN_ATTRID;
1356 attributeIDisSet = true;
1357 }
1358 else if( attributeStr == wxT( "SIGNALNAME_ORIGIN" ) )
1359 {
1360 AttributeID = SIGNALNAME_ORIGIN_ATTRID;
1361 attributeIDisSet = true;
1362 }
1363 else if( attributeStr == wxT( "ATTRREF" ) )
1364 {
1365 //We will initialise when we parse all child nodes
1366 attributeIDisSet = false;
1367 }
1368 else
1369 {
1370 THROW_UNKNOWN_PARAMETER_IO_ERROR( attributeStr, wxT( "TEXTLOC" ) );
1371 }
1372
1373 TextCodeID = GetXmlAttributeIDString( aNode, 1 );
1374 LayerID = GetXmlAttributeIDString( aNode, 2, false );
1375
1376 //Parse child nodes
1377 XNODE* cNode = aNode->GetChildren();
1378
1379 for( ; cNode; cNode = cNode->GetNext() )
1380 {
1381 wxString cNodeName = cNode->GetName();
1382
1383 if( ParseSubNode( cNode, aContext ) )
1384 {
1385 continue;
1386 }
1387 else if( !attributeIDisSet && cNodeName == wxT( "ATTRREF" ) )
1388 {
1389 AttributeID = GetXmlAttributeIDString( cNode, 0 );
1390 attributeIDisSet = true;
1391 }
1392 else if( cNodeName == wxT( "ORIENT" ) )
1393 {
1394 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1395 }
1396 else if( cNodeName == wxT( "MIRROR" ) )
1397 {
1398 Mirror = true;
1399 }
1400 else if( cNodeName == wxT( "FIX" ) )
1401 {
1402 Fixed = true;
1403 }
1404 else if( cNodeName == wxT( "ALIGN" ) )
1405 {
1406 Alignment = ParseAlignment( cNode );
1407 }
1408 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1409 {
1410 Justification = ParseJustification( cNode );
1411 }
1412 else
1413 {
1414 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEXTLOC" ) );
1415 }
1416 }
1417
1418 if( Position.x == UNDEFINED_VALUE || Position.y == UNDEFINED_VALUE )
1419 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "TEXTLOC" ) );
1420}
1421
1422
1424{
1425 wxASSERT( aNode->GetName() == wxT( "NETCLASS" ) );
1426
1427 ID = GetXmlAttributeIDString( aNode, 0 );
1428 Name = GetXmlAttributeIDString( aNode, 1 );
1429
1430 XNODE* cNode = aNode->GetChildren();
1431 wxString location = wxString::Format( "NETCLASS -> %s", Name );
1432
1433 for( ; cNode; cNode = cNode->GetNext() )
1434 {
1435 wxString cNodeName = cNode->GetName();
1436
1437 if( cNodeName == wxT( "ATTR" ) )
1438 {
1439 ATTRIBUTE_VALUE attribute_val;
1440 attribute_val.Parse( cNode, aContext );
1441 Attributes.push_back( attribute_val );
1442 }
1443 else
1444 {
1446 }
1447 }
1448}
1449
1450
1452{
1453 wxASSERT( aNode->GetName() == wxT( "SPCCLASSNAME" ) );
1454
1455 ID = GetXmlAttributeIDString( aNode, 0 );
1456 Name = GetXmlAttributeIDString( aNode, 1 );
1457}
1458
1459
1461{
1462 wxString nodeName = aChildNode->GetName();
1463
1464 if( nodeName == wxT( "LINECODE" ) )
1465 {
1466 LINECODE linecode;
1467 linecode.Parse( aChildNode, aContext );
1468 LineCodes.insert( std::make_pair( linecode.ID, linecode ) );
1469 }
1470 else if( nodeName == wxT( "HATCHCODE" ) )
1471 {
1472 HATCHCODE hatchcode;
1473 hatchcode.Parse( aChildNode, aContext );
1474 HatchCodes.insert( std::make_pair( hatchcode.ID, hatchcode ) );
1475 }
1476 else if( nodeName == wxT( "TEXTCODE" ) )
1477 {
1478 TEXTCODE textcode;
1479 textcode.Parse( aChildNode, aContext );
1480 TextCodes.insert( std::make_pair( textcode.ID, textcode ) );
1481 }
1482 else if( nodeName == wxT( "ROUTECODE" ) )
1483 {
1484 ROUTECODE routecode;
1485 routecode.Parse( aChildNode, aContext );
1486 RouteCodes.insert( std::make_pair( routecode.ID, routecode ) );
1487 }
1488 else if( nodeName == wxT( "ATTRNAME" ) )
1489 {
1490 ATTRNAME attrname;
1491 attrname.Parse( aChildNode, aContext );
1492 AttributeNames.insert( std::make_pair( attrname.ID, attrname ) );
1493 }
1494 else if( nodeName == wxT( "NETCLASS" ) )
1495 {
1496 CADSTAR_NETCLASS netclass;
1497 netclass.Parse( aChildNode, aContext );
1498 NetClasses.insert( std::make_pair( netclass.ID, netclass ) );
1499 }
1500 else if( nodeName == wxT( "SPCCLASSNAME" ) )
1501 {
1502 SPCCLASSNAME spcclassname;
1503 spcclassname.Parse( aChildNode, aContext );
1504 SpacingClassNames.insert( std::make_pair( spcclassname.ID, spcclassname ) );
1505 }
1506 else
1507 {
1508 return false;
1509 }
1510
1511 return true;
1512}
1513
1514
1516{
1517 wxASSERT( aNode->GetName() == wxT( "SWAPRULE" ) );
1518
1519 SWAP_RULE retval;
1520 wxString swapRuleStr = GetXmlAttributeIDString( aNode, 0 );
1521
1522 if( swapRuleStr == wxT( "NO_SWAP" ) )
1523 retval = SWAP_RULE::NO_SWAP;
1524 else if( swapRuleStr == wxT( "USE_SWAP_LAYER" ) )
1526 else
1527 THROW_UNKNOWN_PARAMETER_IO_ERROR( swapRuleStr, wxT( "SWAPRULE" ) );
1528
1529 return retval;
1530}
1531
1532
1534{
1535 wxASSERT( aNode->GetName() == wxT( "REUSEBLOCK" ) );
1536
1537 ID = GetXmlAttributeIDString( aNode, 0 );
1538 Name = GetXmlAttributeIDString( aNode, 1 );
1539 FileName = GetXmlAttributeIDString( aNode, 2 );
1540
1541 XNODE* cNode = aNode->GetChildren();
1542
1543 for( ; cNode; cNode = cNode->GetNext() )
1544 {
1545 wxString cNodeName = cNode->GetName();
1546
1547 if( cNodeName == wxT( "MIRROR" ) )
1548 Mirror = true;
1549 else if( cNodeName == wxT( "ORIENT" ) )
1550 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1551 else
1552 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "REUSEBLOCK" ) );
1553 }
1554}
1555
1556
1558{
1559 return ReuseBlockID == wxEmptyString && ItemReference == wxEmptyString;
1560}
1561
1562
1564{
1565 wxASSERT( aNode->GetName() == wxT( "REUSEBLOCKREF" ) );
1566
1567 ReuseBlockID = GetXmlAttributeIDString( aNode, 0 );
1568 ItemReference = GetXmlAttributeIDString( aNode, 1 );
1569
1570 CheckNoChildNodes( aNode );
1571}
1572
1573
1575{
1576 wxASSERT( aNode->GetName() == wxT( "GROUP" ) );
1577
1578 ID = GetXmlAttributeIDString( aNode, 0 );
1579 Name = GetXmlAttributeIDString( aNode, 1 );
1580
1581 XNODE* cNode = aNode->GetChildren();
1582
1583 for( ; cNode; cNode = cNode->GetNext() )
1584 {
1585 wxString cNodeName = cNode->GetName();
1586
1587 if( cNodeName == wxT( "FIX" ) )
1588 Fixed = true;
1589 else if( cNodeName == wxT( "TRANSFER" ) )
1590 Transfer = true;
1591 else if( cNodeName == wxT( "GROUPREF" ) )
1592 GroupID = GetXmlAttributeIDString( cNode, 0 );
1593 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1594 ReuseBlockRef.Parse( cNode, aContext );
1595 else
1596 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "GROUP" ) );
1597 }
1598}
1599
1600
1602{
1603 wxASSERT( aNode->GetName() == wxT( "FIGURE" ) );
1604
1605 ID = GetXmlAttributeIDString( aNode, 0 );
1606 LineCodeID = GetXmlAttributeIDString( aNode, 1 );
1607 LayerID = GetXmlAttributeIDString( aNode, 2 );
1608
1609 XNODE* cNode = aNode->GetChildren();
1610 bool shapeIsInitialised = false; // Stop more than one Shape Object
1611 wxString location = wxString::Format( "Figure %s", ID );
1612
1613 if( !cNode )
1614 THROW_MISSING_NODE_IO_ERROR( wxT( "Shape" ), location );
1615
1616 for( ; cNode; cNode = cNode->GetNext() )
1617 {
1618 wxString cNodeName = cNode->GetName();
1619
1620 if( !shapeIsInitialised && Shape.IsShape( cNode ) )
1621 {
1622 Shape.Parse( cNode, aContext );
1623 shapeIsInitialised = true;
1624 }
1625 else if( cNodeName == wxT( "SWAPRULE" ) )
1626 {
1627 SwapRule = ParseSwapRule( cNode );
1628 }
1629 else if( cNodeName == wxT( "FIX" ) )
1630 {
1631 Fixed = true;
1632 }
1633 else if( cNodeName == wxT( "GROUPREF" ) )
1634 {
1635
1636 GroupID = GetXmlAttributeIDString( cNode, 0 );
1637 }
1638 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1639 {
1640 ReuseBlockRef.Parse( cNode, aContext );
1641 }
1642 else if( cNodeName == wxT( "ATTR" ) )
1643 {
1644 ATTRIBUTE_VALUE attr;
1645 attr.Parse( cNode, aContext );
1646 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
1647 }
1648 else
1649 {
1651 }
1652 }
1653}
1654
1655
1657{
1658 Parse( aNode, aContext, true );
1659}
1660
1661
1663 bool aParseFields )
1664{
1665 wxASSERT( aNode->GetName() == wxT( "TEXT" ) );
1666
1667 ID = GetXmlAttributeIDString( aNode, 0 );
1668 Text = GetXmlAttributeIDString( aNode, 1 );
1669
1670 if( aParseFields )
1671 Text = ParseTextFields( Text, aContext );
1672
1673 TextCodeID = GetXmlAttributeIDString( aNode, 2 );
1674 LayerID = GetXmlAttributeIDString( aNode, 3 );
1675
1676 XNODE* cNode = aNode->GetChildren();
1677
1678 if( !cNode )
1679 THROW_MISSING_NODE_IO_ERROR( wxT( "PT" ), wxT( "TEXT" ) );
1680
1681 for( ; cNode; cNode = cNode->GetNext() )
1682 {
1683 wxString cNodeName = cNode->GetName();
1684
1685 if( cNodeName == wxT( "PT" ) )
1686 Position.Parse( cNode, aContext );
1687 else if( cNodeName == wxT( "ORIENT" ) )
1688 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
1689 else if( cNodeName == wxT( "MIRROR" ) )
1690 Mirror = true;
1691 else if( cNodeName == wxT( "FIX" ) )
1692 Fixed = true;
1693 else if( cNodeName == wxT( "SWAPRULE" ) )
1694 SwapRule = ParseSwapRule( cNode );
1695 else if( cNodeName == wxT( "ALIGN" ) )
1696 Alignment = ParseAlignment( cNode );
1697 else if( cNodeName == wxT( "JUSTIFICATION" ) )
1698 Justification = ParseJustification( cNode );
1699 else if( cNodeName == wxT( "GROUPREF" ) )
1700 GroupID = GetXmlAttributeIDString( cNode, 0 );
1701 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
1702 ReuseBlockRef.Parse( cNode, aContext );
1703 else
1704 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, wxT( "TEXT" ) );
1705 }
1706}
1707
1708
1710{
1711 return generateLibName( ReferenceName, Alternate );
1712}
1713
1714
1716{
1717 wxASSERT( aNode->GetName() == wxT( "SYMDEF" ) );
1718
1719 ID = GetXmlAttributeIDString( aNode, 0 );
1720 ReferenceName = GetXmlAttributeIDString( aNode, 1 );
1721 Alternate = GetXmlAttributeIDString( aNode, 2 );
1722}
1723
1724
1726{
1727 wxString cNodeName = aChildNode->GetName();
1728
1729 if( cNodeName == wxT( "PT" ) )
1730 {
1731 Origin.Parse( aChildNode, aContext );
1732 }
1733 else if( cNodeName == wxT( "STUB" ) )
1734 {
1735 Stub = true;
1736 }
1737 else if( cNodeName == wxT( "VERSION" ) )
1738 {
1739 Version = GetXmlAttributeIDLong( aChildNode, 0 );
1740 }
1741 else if( cNodeName == wxT( "FIGURE" ) )
1742 {
1743 FIGURE figure;
1744 figure.Parse( aChildNode, aContext );
1745 Figures.insert( std::make_pair( figure.ID, figure ) );
1746 }
1747 else if( cNodeName == wxT( "TEXT" ) )
1748 {
1749 TEXT txt;
1750 txt.Parse( aChildNode, aContext );
1751 Texts.insert( std::make_pair( txt.ID, txt ) );
1752 }
1753 else if( cNodeName == wxT( "TEXTLOC" ) )
1754 {
1755 TEXT_LOCATION textloc;
1756 textloc.Parse( aChildNode, aContext );
1757 TextLocations.insert( std::make_pair( textloc.AttributeID, textloc ) );
1758 }
1759 else if( cNodeName == wxT( "ATTR" ) )
1760 {
1761 ATTRIBUTE_VALUE attrVal;
1762 attrVal.Parse( aChildNode, aContext );
1763 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
1764 }
1765 else
1766 {
1767 return false;
1768 }
1769
1770 return true;
1771}
1772
1773
1775{
1776 wxASSERT( aNode->GetName() == wxT( "GATEDEFINITION" ) );
1777
1778 ID = GetXmlAttributeIDString( aNode, 0 );
1779 Name = GetXmlAttributeIDString( aNode, 1 );
1780 Alternate = GetXmlAttributeIDString( aNode, 2 );
1781 PinCount = GetXmlAttributeIDLong( aNode, 3 );
1782
1783 CheckNoChildNodes( aNode );
1784}
1785
1786
1788{
1789 wxASSERT( aNode->GetName() == wxT( "PINTYPE" ) );
1790
1791 wxString pinTypeStr = GetXmlAttributeIDString( aNode, 0 );
1792
1793 std::map<wxString, CADSTAR_PIN_TYPE> pinTypeMap = {
1794 { wxT( "INPUT" ), CADSTAR_PIN_TYPE::INPUT },
1795 { wxT( "OUTPUT_OR" ), CADSTAR_PIN_TYPE::OUTPUT_OR },
1796 { wxT( "OUTPUT_NOT_OR" ), CADSTAR_PIN_TYPE::OUTPUT_NOT_OR },
1797 { wxT( "OUTPUT_NOT_NORM_OR" ), CADSTAR_PIN_TYPE::OUTPUT_NOT_NORM_OR },
1798 { wxT( "POWER" ), CADSTAR_PIN_TYPE::POWER },
1799 { wxT( "GROUND" ), CADSTAR_PIN_TYPE::GROUND },
1800 { wxT( "TRISTATE_BIDIR" ), CADSTAR_PIN_TYPE::TRISTATE_BIDIR },
1801 { wxT( "TRISTATE_INPUT" ), CADSTAR_PIN_TYPE::TRISTATE_INPUT },
1802 { wxT( "TRISTATE_DRIVER" ), CADSTAR_PIN_TYPE::TRISTATE_DRIVER } };
1803
1804 if( pinTypeMap.find( pinTypeStr ) == pinTypeMap.end() )
1805 THROW_UNKNOWN_PARAMETER_IO_ERROR( pinTypeStr, aNode->GetName() );
1806
1807 return pinTypeMap[pinTypeStr];
1808}
1809
1810
1812{
1813 wxASSERT( aNode->GetName() == wxT( "PARTDEFINITIONPIN" ) );
1814
1815 ID = GetXmlAttributeIDLong( aNode, 0 );
1816
1817 XNODE* cNode = aNode->GetChildren();
1818
1819 for( ; cNode; cNode = cNode->GetNext() )
1820 {
1821 wxString cNodeName = cNode->GetName();
1822
1823 if( cNodeName == wxT( "PINNAME" ) )
1824 {
1825 Name = GetXmlAttributeIDString( cNode, 0 );
1826 }
1827 else if( cNodeName == wxT( "PINLABEL" ) )
1828 {
1829 Label = GetXmlAttributeIDString( cNode, 0 );
1830 }
1831 else if( cNodeName == wxT( "PINSIGNAL" ) )
1832 {
1833 Signal = GetXmlAttributeIDString( cNode, 0 );
1834 }
1835 else if( cNodeName == wxT( "PINTERM" ) )
1836 {
1837 TerminalGate = GetXmlAttributeIDString( cNode, 0 );
1838 TerminalPin = GetXmlAttributeIDLong( cNode, 1 );
1839 }
1840 else if( cNodeName == wxT( "PINTYPE" ) )
1841 {
1842 Type = GetPinType( cNode );
1843 }
1844 else if( cNodeName == wxT( "PINLOAD" ) )
1845 {
1846 Load = GetXmlAttributeIDLong( cNode, 0 );
1847 }
1848 else if( cNodeName == wxT( "PINPOSITION" ) )
1849 {
1850 Position = CADSTAR_PIN_POSITION( GetXmlAttributeIDLong( cNode, 0 ) );
1851 }
1852 else if( cNodeName == wxT( "PINIDENTIFIER" ) )
1853 {
1854 Identifier = GetXmlAttributeIDString( cNode, 0 );
1855 }
1856 else
1857 {
1858 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1859 }
1860 }
1861}
1862
1863
1865{
1866 wxASSERT( aNode->GetName() == wxT( "PARTPIN" ) );
1867
1868 ID = GetXmlAttributeIDLong( aNode, 0 );
1869
1870 XNODE* cNode = aNode->GetChildren();
1871
1872 for( ; cNode; cNode = cNode->GetNext() )
1873 {
1874 wxString cNodeName = cNode->GetName();
1875
1876 if( cNodeName == wxT( "PINNAME" ) )
1877 Name = GetXmlAttributeIDString( cNode, 0 );
1878 else if( cNodeName == wxT( "PINTYPE" ) )
1879 Type = GetPinType( cNode );
1880 else if( cNodeName == wxT( "PINIDENTIFIER" ) )
1881 Identifier = GetXmlAttributeIDString( cNode, 0 );
1882 else
1883 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1884 }
1885}
1886
1887
1889 PARSER_CONTEXT* aContext )
1890{
1891 wxASSERT( aNode->GetName() == wxT( "PINEQUIVALENCE" ) );
1892
1893 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1894
1895 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1896 {
1897 if( !IsValidAttribute( xmlAttribute ) )
1898 continue;
1899
1900 long pinId;
1901
1902 if( !xmlAttribute->GetValue().ToLong( &pinId ) )
1903 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), aNode->GetName() );
1904
1905 PinIDs.push_back( (PART_DEFINITION_PIN_ID) pinId );
1906 }
1907
1908 CheckNoChildNodes( aNode );
1909}
1910
1911
1913 PARSER_CONTEXT* aContext )
1914{
1915 wxASSERT( aNode->GetName() == wxT( "SWAPGATE" ) );
1916
1917 wxXmlAttribute* xmlAttribute = aNode->GetAttributes();
1918
1919 for( ; xmlAttribute; xmlAttribute = xmlAttribute->GetNext() )
1920 {
1921 if( !IsValidAttribute( xmlAttribute ) )
1922 continue;
1923
1924 long pinId;
1925
1926 if( !xmlAttribute->GetValue().ToLong( &pinId ) )
1927 THROW_UNKNOWN_PARAMETER_IO_ERROR( xmlAttribute->GetValue(), aNode->GetName() );
1928
1929 PinIDs.push_back( (PART_DEFINITION_PIN_ID) pinId );
1930 }
1931
1932 CheckNoChildNodes( aNode );
1933}
1934
1935
1937 PARSER_CONTEXT* aContext )
1938{
1939 wxASSERT( aNode->GetName() == wxT( "SWAPGROUP" ) );
1940
1941 GateName = GetXmlAttributeIDString( aNode, 0 );
1942
1943 XNODE* cNode = aNode->GetChildren();
1944
1945 for( ; cNode; cNode = cNode->GetNext() )
1946 {
1947 wxString cNodeName = cNode->GetName();
1948
1949 if( cNodeName == wxT( "EXTERNAL" ) )
1950 {
1951 External = true;
1952 }
1953 else if( cNodeName == wxT( "SWAPGATE" ) )
1954 {
1955 SWAP_GATE swapGate;
1956 swapGate.Parse( cNode, aContext );
1957 SwapGates.push_back( swapGate );
1958 }
1959 else
1960 {
1961 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
1962 }
1963 }
1964}
1965
1966
1968{
1969 wxASSERT( aNode->GetName() == wxT( "PARTDEFINITION" ) );
1970
1971 Name = GetXmlAttributeIDString( aNode, 0 );
1972
1973 XNODE* cNode = aNode->GetChildren();
1974
1975 for( ; cNode; cNode = cNode->GetNext() )
1976 {
1977 wxString cNodeName = cNode->GetName();
1978
1979 if( cNodeName == wxT( "HIDEPINNAMES" ) )
1980 {
1981 HidePinNames = true;
1982 }
1983 else if( cNodeName == wxT( "MAXPIN" ) )
1984 {
1985 MaxPinCount = GetXmlAttributeIDLong( cNode, 0 );
1986 }
1987 else if( cNodeName == wxT( "GATEDEFINITION" ) )
1988 {
1989 GATE gate;
1990 gate.Parse( cNode, aContext );
1991 GateSymbols.insert( std::make_pair( gate.ID, gate ) );
1992 }
1993 else if( cNodeName == wxT( "PARTDEFINITIONPIN" ) )
1994 {
1995 PIN pin;
1996 pin.Parse( cNode, aContext );
1997 Pins.insert( std::make_pair( pin.ID, pin ) );
1998 }
1999 else if( cNodeName == wxT( "ATTR" ) )
2000 {
2001 ATTRIBUTE_VALUE attr;
2002 attr.Parse( cNode, aContext );
2003 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2004 }
2005 else if( cNodeName == wxT( "PINEQUIVALENCE" ) )
2006 {
2007 PIN_EQUIVALENCE pinEq;
2008 pinEq.Parse( cNode, aContext );
2009 PinEquivalences.push_back( pinEq );
2010 }
2011 else if( cNodeName == wxT( "SWAPGROUP" ) )
2012 {
2013 SWAP_GROUP swapGroup;
2014 swapGroup.Parse( cNode, aContext );
2015 SwapGroups.push_back( swapGroup );
2016 }
2017 else
2018 {
2019 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2020 }
2021 }
2022}
2023
2024
2026{
2027 wxASSERT( aNode->GetName() == wxT( "PART" ) );
2028
2029 ID = GetXmlAttributeIDString( aNode, 0 );
2030 Name = GetXmlAttributeIDString( aNode, 1 );
2031
2032 XNODE* cNode = aNode->GetChildren();
2033
2034 for( ; cNode; cNode = cNode->GetNext() )
2035 {
2036 wxString cNodeName = cNode->GetName();
2037
2038 if( cNodeName == wxT( "VERSION" ) )
2039 {
2040 Version = GetXmlAttributeIDLong( cNode, 0 );
2041 }
2042 else if( cNodeName == wxT( "HIDEPINNAMES" ) )
2043 {
2044 HidePinNames = true;
2045 }
2046 else if( cNodeName == wxT( "PARTDEFINITION" ) )
2047 {
2048 Definition.Parse( cNode, aContext );
2049 }
2050 else if( cNodeName == wxT( "PARTPIN" ) )
2051 {
2052 PART_PIN pin;
2053 pin.Parse( cNode, aContext );
2054 PartPins.insert( std::make_pair( pin.ID, pin ) );
2055 }
2056 else if( cNodeName == wxT( "ATTR" ) )
2057 {
2058 ATTRIBUTE_VALUE attr;
2059 attr.Parse( cNode, aContext );
2060 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2061 }
2062 else
2063 {
2064 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2065 }
2066 }
2067}
2068
2069
2071{
2072 wxASSERT( aNode->GetName() == wxT( "PARTS" ) );
2073
2074 XNODE* cNode = aNode->GetChildren();
2075
2076 for( ; cNode; cNode = cNode->GetNext() )
2077 {
2078 wxString cNodeName = cNode->GetName();
2079
2080 if( cNodeName == wxT( "PART" ) )
2081 {
2082 PART part;
2083 part.Parse( cNode, aContext );
2084 PartDefinitions.insert( std::make_pair( part.ID, part ) );
2085 }
2086 else
2087 {
2088 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2089 }
2090
2091 aContext->CheckPointCallback();
2092 }
2093}
2094
2095
2097 PARSER_CONTEXT* aContext )
2098{
2099 wxASSERT( aNode->GetName() == wxT( "JPT" ) );
2100
2101 ID = GetXmlAttributeIDString( aNode, 0 );
2102 LayerID = GetXmlAttributeIDString( aNode, 1 );
2103}
2104
2105
2107 PARSER_CONTEXT* aContext )
2108{
2109 wxString cNodeName = aChildNode->GetName();
2110
2111 if( cNodeName == wxT( "PT" ) )
2112 Location.Parse( aChildNode, aContext );
2113 else if( cNodeName == wxT( "FIX" ) )
2114 Fixed = true;
2115 else if( cNodeName == wxT( "GROUPREF" ) )
2116 GroupID = GetXmlAttributeIDString( aChildNode, 0 );
2117 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2118 ReuseBlockRef.Parse( aChildNode, aContext );
2119 else
2120 return false;
2121
2122 return true;
2123}
2124
2125
2127{
2128 ParseIdentifiers( aNode, aContext );
2129 XNODE* cNode = aNode->GetChildren();
2130
2131 for( ; cNode; cNode = cNode->GetNext() )
2132 {
2133 if( ParseSubNode( cNode, aContext ) )
2134 continue;
2135 else
2136 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2137 }
2138}
2139
2140
2142 PARSER_CONTEXT* aContext )
2143{
2144 wxASSERT( aNode->GetName() == wxT( "CONN" ) );
2145
2146 StartNode = GetXmlAttributeIDString( aNode, 0 );
2147 EndNode = GetXmlAttributeIDString( aNode, 1 );
2148 RouteCodeID = GetXmlAttributeIDString( aNode, 2 );
2149}
2150
2151
2153 PARSER_CONTEXT* aContext )
2154{
2155 wxString cNodeName = aChildNode->GetName();
2156
2157 if( cNodeName == wxT( "FIX" ) )
2158 {
2159 Fixed = true;
2160 }
2161 else if( cNodeName == wxT( "HIDDEN" ) )
2162 {
2163 Hidden = true;
2164 }
2165 else if( cNodeName == wxT( "GROUPREF" ) )
2166 {
2167 GroupID = GetXmlAttributeIDString( aChildNode, 0 );
2168 }
2169 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2170 {
2171 ReuseBlockRef.Parse( aChildNode, aContext );
2172 }
2173 else if( cNodeName == wxT( "ATTR" ) )
2174 {
2175 ATTRIBUTE_VALUE attrVal;
2176 attrVal.Parse( aChildNode, aContext );
2177 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
2178 }
2179 else
2180 {
2181 return false;
2182 }
2183
2184 return true;
2185}
2186
2187
2189{
2190 wxASSERT( aNode->GetName() == wxT( "NET" ) );
2191
2192 ID = GetXmlAttributeIDString( aNode, 0 );
2193}
2194
2195
2197{
2198 wxString cNodeName = aChildNode->GetName();
2199
2200 if( cNodeName == wxT( "NETCODE" ) )
2201 {
2202 RouteCodeID = GetXmlAttributeIDString( aChildNode, 0 );
2203 }
2204 else if( cNodeName == wxT( "SIGNAME" ) )
2205 {
2206 Name = GetXmlAttributeIDString( aChildNode, 0 );
2207 }
2208 else if( cNodeName == wxT( "SIGNUM" ) )
2209 {
2210 SignalNum = GetXmlAttributeIDLong( aChildNode, 0 );
2211 }
2212 else if( cNodeName == wxT( "HIGHLIT" ) )
2213 {
2214 Highlight = true;
2215 }
2216 else if( cNodeName == wxT( "JPT" ) )
2217 {
2218 JUNCTION jpt;
2219 jpt.Parse( aChildNode, aContext );
2220 Junctions.insert( std::make_pair( jpt.ID, jpt ) );
2221 }
2222 else if( cNodeName == wxT( "NETCLASSREF" ) )
2223 {
2224 NetClassID = GetXmlAttributeIDString( aChildNode, 0 );
2225 }
2226 else if( cNodeName == wxT( "SPACINGCLASS" ) )
2227 {
2228 SpacingClassID = GetXmlAttributeIDString( aChildNode, 0 );
2229 }
2230 else if( cNodeName == wxT( "ATTR" ) )
2231 {
2232 ATTRIBUTE_VALUE attrVal;
2233 attrVal.Parse( aChildNode, aContext );
2234 AttributeValues.insert( std::make_pair( attrVal.AttributeID, attrVal ) );
2235 }
2236 else
2237 {
2238 return false;
2239 }
2240
2241 return true;
2242}
2243
2244
2246{
2247 wxASSERT( aNode->GetName() == wxT( "DOCSYMBOL" ) );
2248
2249 ID = GetXmlAttributeIDString( aNode, 0 );
2250 SymdefID = GetXmlAttributeIDString( aNode, 1 );
2251 LayerID = GetXmlAttributeIDString( aNode, 2 );
2252
2253 XNODE* cNode = aNode->GetChildren();
2254 bool originParsed = false;
2255
2256 for( ; cNode; cNode = cNode->GetNext() )
2257 {
2258 wxString cNodeName = cNode->GetName();
2259
2260 if( !originParsed && cNodeName == wxT( "PT" ) )
2261 {
2262 Origin.Parse( cNode, aContext );
2263 originParsed = true;
2264 }
2265 else if( cNodeName == wxT( "GROUPREF" ) )
2266 {
2267 GroupID = GetXmlAttributeIDString( cNode, 0 );
2268 }
2269 else if( cNodeName == wxT( "REUSEBLOCKREF" ) )
2270 {
2271 ReuseBlockRef.Parse( cNode, aContext );
2272 }
2273 else if( cNodeName == wxT( "FIX" ) )
2274 {
2275 Fixed = true;
2276 }
2277 else if( cNodeName == wxT( "MIRROR" ) )
2278 {
2279 Mirror = true;
2280 }
2281 else if( cNodeName == wxT( "READABILITY" ) )
2282 {
2283 Readability = ParseReadability( cNode );
2284 }
2285 else if( cNodeName == wxT( "ORIENT" ) )
2286 {
2287 OrientAngle = GetXmlAttributeIDLong( cNode, 0 );
2288 }
2289 else if( cNodeName == wxT( "ATTR" ) )
2290 {
2291 ATTRIBUTE_VALUE attr;
2292 attr.Parse( cNode, aContext );
2293 AttributeValues.insert( std::make_pair( attr.AttributeID, attr ) );
2294 }
2295 else if( cNodeName == wxT( "SCALE" ) )
2296 {
2297 ScaleRatioNumerator = GetXmlAttributeIDLong( cNode, 0 );
2298 ScaleRatioDenominator = GetXmlAttributeIDLong( cNode, 1 );
2299 }
2300 else
2301 {
2302 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2303 }
2304 }
2305
2306 if( !originParsed )
2307 THROW_MISSING_PARAMETER_IO_ERROR( wxT( "PT" ), aNode->GetName() );
2308}
2309
2310
2312{
2313 wxASSERT( aNode->GetName() == wxT( "DFLTSETTINGS" ) );
2314
2315 Color = GetXmlAttributeIDString( aNode, 0 );
2316
2317 XNODE* cNode = aNode->GetChildren();
2318
2319 for( ; cNode; cNode = cNode->GetNext() )
2320 {
2321 wxString cNodeName = cNode->GetName();
2322
2323 if( cNodeName == wxT( "INVISIBLE" ) )
2324 {
2325 IsVisible = false;
2326 }
2327 else
2328 {
2329 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2330 }
2331 }
2332}
2333
2334
2336{
2337 wxASSERT( aNode->GetName() == wxT( "ATTRCOL" ) );
2338
2339 AttributeID = GetXmlAttributeIDString( aNode, 0 );
2340 Color = GetXmlAttributeIDString( aNode, 1 );
2341
2342 XNODE* cNode = aNode->GetChildren();
2343
2344 for( ; cNode; cNode = cNode->GetNext() )
2345 {
2346 wxString cNodeName = cNode->GetName();
2347
2348 if( cNodeName == wxT( "INVISIBLE" ) )
2349 {
2350 IsVisible = false;
2351 }
2352 else if( cNodeName == wxT( "NOTPICKABLE" ) )
2353 {
2354 IsPickable = false;
2355 }
2356 else
2357 {
2358 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2359 }
2360 }
2361}
2362
2363
2365{
2366 wxASSERT( aNode->GetName() == wxT( "ATTRCOLORS" ) );
2367
2368 XNODE* cNode = aNode->GetChildren();
2369
2370 for( ; cNode; cNode = cNode->GetNext() )
2371 {
2372 wxString cNodeName = cNode->GetName();
2373
2374 if( cNodeName == wxT( "DFLTSETTINGS" ) )
2375 {
2376 DefaultSettings.Parse( cNode, aContext );
2377 }
2378 else if( cNodeName == wxT( "ATTRCOL" ) )
2379 {
2380 ATTRCOL attrcol;
2381 attrcol.Parse( cNode, aContext );
2382 AttributeColors.insert( { attrcol.AttributeID, attrcol } );
2383 }
2384 else if( cNodeName == wxT( "INVISIBLE" ) )
2385 {
2386 IsVisible = false;
2387 }
2388 else
2389 {
2390 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2391 }
2392 }
2393}
2394
2395
2397{
2398 wxASSERT( aNode->GetName() == wxT( "PARTNAMECOL" ) );
2399
2400 Color = GetXmlAttributeIDString( aNode, 0 );
2401
2402 XNODE* cNode = aNode->GetChildren();
2403
2404 for( ; cNode; cNode = cNode->GetNext() )
2405 {
2406 wxString cNodeName = cNode->GetName();
2407
2408 if( cNodeName == wxT( "INVISIBLE" ) )
2409 {
2410 IsVisible = false;
2411 }
2412 else if( cNodeName == wxT( "NOTPICKABLE" ) )
2413 {
2414 IsPickable = false;
2415 }
2416 else
2417 {
2418 THROW_UNKNOWN_NODE_IO_ERROR( cNodeName, aNode->GetName() );
2419 }
2420 }
2421}
2422
2423
2425{
2426 static const wxString c_numAttributes = wxT( "numAttributes" );
2427
2428 wxString result;
2429 long numAttributes = 0;
2430
2431 if( aNode->GetAttribute( c_numAttributes, &result ) )
2432 {
2433 numAttributes = wxAtol( result );
2434 aNode->DeleteAttribute( c_numAttributes );
2435 ++numAttributes;
2436 }
2437
2438#if wxUSE_UNICODE_WCHAR
2439 std::wstring numAttrStr = std::to_wstring( numAttributes );
2440#else
2441 std::string numAttrStr = std::to_string( numAttributes );
2442#endif
2443
2444 aNode->AddAttribute( c_numAttributes, numAttrStr );
2445
2446 wxString paramName = wxT( "attr" );
2447 paramName << numAttrStr;
2448
2449 aNode->AddAttribute( paramName, aValue );
2450}
2451
2452
2454 const wxString& aFileTypeIdentifier,
2455 PROGRESS_REPORTER* aProgressReporter )
2456{
2457 KEYWORD emptyKeywords[1] = {};
2458 XNODE* rootNode = nullptr;
2459 XNODE* cNode = nullptr;
2460 XNODE* iNode = nullptr;
2461 int tok;
2462 bool cadstarFileCheckDone = false;
2463 wxString str;
2464 wxCSConv win1252( wxT( "windows-1252" ) );
2465 wxMBConv* conv = &win1252; // Initial testing suggests file encoding to be Windows-1252
2466 // More samples required.
2467
2468 // Open the file and get the file size
2469 FILE* fp = wxFopen( aFileName, wxT( "rt" ) );
2470
2471 if( !fp )
2472 THROW_IO_ERROR( wxString::Format( _( "Cannot open file '%s'" ), aFileName ) );
2473
2474 fseek( fp, 0L, SEEK_END );
2475 long fileSize = ftell( fp );
2476 rewind( fp );
2477
2478 DSNLEXER lexer( emptyKeywords, 0, nullptr, fp, aFileName );
2479
2480 auto currentProgress = [&]() -> double
2481 {
2482 return static_cast<double>( ftell( fp ) ) / fileSize;
2483 };
2484
2485 double previousReportedProgress = -1.0;
2486
2487 while( ( tok = lexer.NextTok() ) != DSN_EOF )
2488 {
2489 if( aProgressReporter && ( currentProgress() - previousReportedProgress ) > 0.01 )
2490 {
2491 if( !aProgressReporter->KeepRefreshing() )
2492 {
2493 delete rootNode;
2494
2495 // @spellingerror
2496 THROW_IO_ERROR( _( "File import cancelled by user." ) );
2497 }
2498
2499 aProgressReporter->SetCurrentProgress( currentProgress() );
2500 previousReportedProgress = currentProgress();
2501 }
2502
2503 if( tok == DSN_RIGHT )
2504 {
2505 cNode = iNode;
2506 if( cNode )
2507 {
2508 iNode = cNode->GetParent();
2509 }
2510 else
2511 {
2512 //too many closing brackets
2513 delete rootNode;
2514 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2515 }
2516 }
2517 else if( tok == DSN_LEFT )
2518 {
2519 tok = lexer.NextTok();
2520 str = wxString( lexer.CurText(), *conv );
2521 cNode = new XNODE( wxXML_ELEMENT_NODE, str );
2522
2523 if( !rootNode )
2524 rootNode = cNode;
2525
2526 if( iNode )
2527 {
2528 //we will add it as attribute as well as child node
2529 InsertAttributeAtEnd( iNode, str );
2530 iNode->AddChild( cNode );
2531 }
2532 else if( !cadstarFileCheckDone )
2533 {
2534 if( cNode->GetName() != aFileTypeIdentifier )
2535 {
2536 delete rootNode;
2537 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2538 }
2539
2540 cadstarFileCheckDone = true;
2541 }
2542
2543 iNode = cNode;
2544 }
2545 else if( iNode )
2546 {
2547 str = wxString( lexer.CurText(), *conv );
2548 //Insert even if string is empty
2549 InsertAttributeAtEnd( iNode, str );
2550 }
2551 else
2552 {
2553 //not enough closing brackets
2554 delete rootNode;
2555 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2556 }
2557 }
2558
2559 // Not enough closing brackets
2560 if( iNode != nullptr )
2561 {
2562 delete rootNode;
2563 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2564 }
2565
2566 // Throw if no data was parsed
2567 if( rootNode )
2568 {
2569 return rootNode;
2570 }
2571 else
2572 {
2573 delete rootNode;
2574 THROW_IO_ERROR( _( "The selected file is not valid or might be corrupt!" ) );
2575 }
2576
2577 return nullptr;
2578}
2579
2580
2581bool CADSTAR_ARCHIVE_PARSER::IsValidAttribute( wxXmlAttribute* aAttribute )
2582{
2583 return aAttribute->GetName() != wxT( "numAttributes" );
2584}
2585
2586
2588 bool aIsRequired )
2589{
2590#if wxUSE_UNICODE_WCHAR
2591 std::wstring idStr = std::to_wstring( aID );
2592#else
2593 std::string idStr = std::to_string( aID );
2594#endif
2595
2596 wxString attrName = wxS( "attr" );
2597 attrName << idStr;
2598
2599 wxString retVal;
2600
2601 if( !aNode->GetAttribute( attrName, &retVal ) )
2602 {
2603 if( aIsRequired )
2604 THROW_MISSING_PARAMETER_IO_ERROR( std::to_string( aID ), aNode->GetName() );
2605 else
2606 return wxEmptyString;
2607 }
2608
2609 return retVal;
2610}
2611
2612
2614 bool aIsRequired )
2615{
2616 long retVal;
2617 bool success = GetXmlAttributeIDString( aNode, aID, aIsRequired ).ToLong( &retVal );
2618
2619 if( !success )
2620 {
2621 if( aIsRequired )
2622 THROW_PARSING_IO_ERROR( std::to_string( aID ), aNode->GetName() );
2623 else
2624 return UNDEFINED_VALUE;
2625 }
2626
2627 return retVal;
2628}
2629
2630
2632{
2633 if( aNode && aNode->GetChildren() )
2634 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
2635}
2636
2637
2639{
2640 if( aNode && aNode->GetNext() )
2641 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetNext()->GetName(), aNode->GetParent()->GetName() );
2642}
2643
2644
2646 EVALUE& aValueToParse )
2647{
2648 if( aNode->GetChildren()->GetName() == wxT( "E" ) )
2649 aValueToParse.Parse( aNode->GetChildren(), aContext );
2650 else
2651 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
2652}
2653
2654
2655std::vector<CADSTAR_ARCHIVE_PARSER::POINT> CADSTAR_ARCHIVE_PARSER::ParseAllChildPoints(
2656 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes, int aExpectedNumPoints )
2657{
2658 std::vector<POINT> retVal;
2659
2660 XNODE* cNode = aNode->GetChildren();
2661
2662 for( ; cNode; cNode = cNode->GetNext() )
2663 {
2664 if( cNode->GetName() == wxT( "PT" ) )
2665 {
2666 POINT pt;
2667 //TODO try.. catch + throw again with more detailed error information
2668 pt.Parse( cNode, aContext );
2669 retVal.push_back( pt );
2670 }
2671 else if( aTestAllChildNodes )
2672 {
2673 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2674 }
2675 }
2676
2677 if( aExpectedNumPoints != UNDEFINED_VALUE
2678 && retVal.size() != static_cast<size_t>( aExpectedNumPoints ) )
2679 {
2680 THROW_IO_ERROR( wxString::Format(
2681 _( "Unexpected number of points in '%s'. Found %d but expected %d." ),
2682 aNode->GetName(), retVal.size(), aExpectedNumPoints ) );
2683 }
2684
2685 return retVal;
2686}
2687
2688
2689std::vector<CADSTAR_ARCHIVE_PARSER::VERTEX> CADSTAR_ARCHIVE_PARSER::ParseAllChildVertices(
2690 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes )
2691{
2692 std::vector<VERTEX> retVal;
2693
2694 XNODE* cNode = aNode->GetChildren();
2695
2696 for( ; cNode; cNode = cNode->GetNext() )
2697 {
2698 if( VERTEX::IsVertex( cNode ) )
2699 {
2700 VERTEX vertex;
2701 //TODO try.. catch + throw again with more detailed error information
2702 vertex.Parse( cNode, aContext );
2703 retVal.push_back( vertex );
2704 }
2705 else if( aTestAllChildNodes )
2706 {
2707 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2708 }
2709 }
2710
2711 return retVal;
2712}
2713
2714
2715std::vector<CADSTAR_ARCHIVE_PARSER::CUTOUT> CADSTAR_ARCHIVE_PARSER::ParseAllChildCutouts(
2716 XNODE* aNode, PARSER_CONTEXT* aContext, bool aTestAllChildNodes )
2717{
2718 std::vector<CUTOUT> retVal;
2719
2720 XNODE* cNode = aNode->GetChildren();
2721
2722 for( ; cNode; cNode = cNode->GetNext() )
2723 {
2724 if( cNode->GetName() == wxT( "CUTOUT" ) )
2725 {
2726 CUTOUT cutout;
2727 //TODO try.. catch + throw again with more detailed error information
2728 cutout.Parse( cNode, aContext );
2729 retVal.push_back( cutout );
2730 }
2731 else if( aTestAllChildNodes )
2732 {
2733 THROW_UNKNOWN_NODE_IO_ERROR( cNode->GetName(), aNode->GetName() );
2734 }
2735 }
2736
2737 return retVal;
2738}
2739
2740
2742{
2743 XNODE* childNodes = aNode->GetChildren();
2744 long retval = 0;
2745
2746 for( ; childNodes; childNodes = childNodes->GetNext() )
2747 retval++;
2748
2749 return retval;
2750}
2751
2752
2754 XNODE* aRootNode, std::vector<wxString> aSubNodeChildrenToCount )
2755{
2756 XNODE* level1Node = aRootNode->GetChildren();
2757 long retval = 0;
2758
2759 for( ; level1Node; level1Node = level1Node->GetNext() )
2760 {
2761 for( wxString childNodeName : aSubNodeChildrenToCount )
2762 {
2763 if( level1Node->GetName() == childNodeName )
2764 retval += GetNumberOfChildNodes( level1Node );
2765 }
2766
2767 retval++;
2768 }
2769
2770 return retval;
2771}
2772
2773
2774wxString CADSTAR_ARCHIVE_PARSER::HandleTextOverbar( wxString aCadstarString )
2775{
2776 wxString escapedText = aCadstarString;
2777
2778 escapedText.Replace( wxT( "'" ), wxT( "~" ) );
2779
2780 return ConvertToNewOverbarNotation( escapedText );
2781}
2782
2783
2785{
2786 if( !aKiCadTextItem->GetText().IsEmpty() )
2787 {
2788 VECTOR2I positionOffset( 0, aKiCadTextItem->GetInterline() );
2789 RotatePoint( positionOffset, aKiCadTextItem->GetTextAngle() );
2790
2791 //Count num of additional lines
2792 wxString text = aKiCadTextItem->GetText();
2793 int numExtraLines = text.Replace( "\n", "\n" );
2794 numExtraLines -= text.at( text.size() - 1 ) == '\n'; // Ignore new line character at end
2795 positionOffset.x *= numExtraLines;
2796 positionOffset.y *= numExtraLines;
2797
2798 aKiCadTextItem->Offset( positionOffset );
2799 }
2800}
2801
2802
2803wxString CADSTAR_ARCHIVE_PARSER::generateLibName( const wxString& aRefName,
2804 const wxString& aAlternateName )
2805{
2806 if( aAlternateName.IsEmpty() )
2807 return EscapeString( aRefName, CTX_LIBID );
2808 else
2809 return EscapeString( aRefName + wxT( " (" ) + aAlternateName + wxT( ")" ), CTX_LIBID );
2810}
2811
2812
2814{
2815 if( m_progressReporter )
2816 {
2818
2820 THROW_IO_ERROR( _( "File import cancelled by user." ) );
2821 }
2822}
2823
KICAD_PLUGIN_EXPORT SCENEGRAPH * Load(char const *aFileName)
Read a model file and creates a generic display structure.
CADSTAR_PIN_POSITION
Positioning of pin names can be in one of four quadrants.
CADSTAR_PIN_TYPE
file: cadstar_archive_objects.h Contains common object definitions
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 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.
@ 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 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.
@ PART
Only library Attributes.
Implement a lexical analyzer for the SPECCTRA DSN file format.
Definition: dsnlexer.h:81
const char * CurText() const
Return a pointer to the current token's text.
Definition: dsnlexer.h:407
int NextTok()
Return the next token found in the input file or DSN_EOF when reaching the end of file.
Definition: dsnlexer.cpp:530
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:80
const EDA_ANGLE & GetTextAngle() const
Definition: eda_text.h:134
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:98
int GetInterline() const
Return the distance between two lines of text.
Definition: eda_text.cpp:715
void Offset(const VECTOR2I &aOffset)
Definition: eda_text.cpp:587
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:213
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.
Hold an XML or S-expression element.
Definition: xnode.h:43
XNODE * GetParent() const
Definition: xnode.h:71
XNODE * GetChildren() const
Definition: xnode.h:61
XNODE * GetNext() const
Definition: xnode.h:66
@ DSN_LEFT
Definition: dsnlexer.h:69
@ DSN_RIGHT
Definition: dsnlexer.h:68
@ DSN_EOF
Definition: dsnlexer.h:71
#define _(s)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:39
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
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:198
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
Definition: string_utils.h:54
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)
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
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
Represent 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
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
static CADSTAR_PIN_TYPE GetPinType(XNODE *aNode)
void Parse(XNODE *aNode, PARSER_CONTEXT *aContext) override
Represent 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.
SHAPE_ARC BuildArc(const VECTOR2I &aPrevPoint, const std::function< VECTOR2I(const VECTOR2I &)> aCadstarToKicadPointCallback) const
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:41
VECTOR2I location
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:229
VECTOR2< int32_t > VECTOR2I
Definition: vector2d.h:695