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