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