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