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