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
21 /**
22 * @file cadstar_archive_parser.cpp
23 * @brief Helper functions and common defines between schematic and PCB Archive files
24 */
25 #include <wx/filename.h>
26 #include <wx/log.h>
27 #include <wx/xml/xml.h>
28
29 #include <dsnlexer.h>
30 #include <plugins/cadstar/cadstar_archive_parser.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>
43 CADSTAR_ARCHIVE_PARSER::CADSTAR_TO_KICAD_FIELDS =
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)60 void CADSTAR_ARCHIVE_PARSER::FORMAT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)70 void CADSTAR_ARCHIVE_PARSER::TIMESTAMP::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)84 void CADSTAR_ARCHIVE_PARSER::HEADER::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)141 void CADSTAR_ARCHIVE_PARSER::VARIANT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)161 void CADSTAR_ARCHIVE_PARSER::VARIANT_HIERARCHY::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)183 void CADSTAR_ARCHIVE_PARSER::LINECODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)228 void CADSTAR_ARCHIVE_PARSER::HATCH::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)244 void CADSTAR_ARCHIVE_PARSER::HATCHCODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)266 void CADSTAR_ARCHIVE_PARSER::FONT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)290 void CADSTAR_ARCHIVE_PARSER::TEXTCODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)313 void CADSTAR_ARCHIVE_PARSER::ROUTEREASSIGN::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)340 void CADSTAR_ARCHIVE_PARSER::ROUTECODE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
GetDouble()384 double CADSTAR_ARCHIVE_PARSER::EVALUE::GetDouble()
385 {
386 return Base * std::pow( 10.0, Exponent );
387 }
388
389
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)390 void CADSTAR_ARCHIVE_PARSER::EVALUE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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" ),
398 wxString::Format(
399 "%s->%s", aNode->GetParent()->GetName(), aNode->GetParent()->GetName() ) );
400 }
401 }
402
403
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)404 void CADSTAR_ARCHIVE_PARSER::POINT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
405 {
406 wxASSERT( aNode->GetName() == wxT( "PT" ) );
407
408 x = GetXmlAttributeIDLong( aNode, 0 );
409 y = GetXmlAttributeIDLong( aNode, 1 );
410 }
411
412
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)413 void CADSTAR_ARCHIVE_PARSER::LONGPOINT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
414 {
415 wxASSERT( aNode->GetName() == wxT( "PT" ) );
416
417 x = GetXmlAttributeIDLong( aNode, 0 );
418 y = GetXmlAttributeIDLong( aNode, 1 );
419 }
420
421
IsVertex(XNODE * aNode)422 bool CADSTAR_ARCHIVE_PARSER::VERTEX::IsVertex( XNODE* aNode )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)438 void CADSTAR_ARCHIVE_PARSER::VERTEX::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
439 {
440 wxASSERT( IsVertex( aNode ) );
441
442 wxString aNodeName = aNode->GetName();
443
444 if( aNodeName == wxT( "PT" ) )
445 {
446 Type = VERTEX_TYPE::POINT;
447 Center.x = UNDEFINED_VALUE;
448 Center.y = UNDEFINED_VALUE;
449 End.Parse( aNode, aContext );
450 }
451 else if( aNodeName == wxT( "ACWARC" ) || aNodeName == wxT( "CWARC" ) )
452 {
453 if( aNodeName == wxT( "ACWARC" ) )
454 Type = VERTEX_TYPE::ANTICLOCKWISE_ARC;
455 else
456 Type = VERTEX_TYPE::CLOCKWISE_ARC;
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" ) )
466 Type = VERTEX_TYPE::ANTICLOCKWISE_SEMICIRCLE;
467 else
468 Type = VERTEX_TYPE::CLOCKWISE_SEMICIRCLE;
469
470 Center.x = UNDEFINED_VALUE;
471 Center.y = UNDEFINED_VALUE;
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)484 void CADSTAR_ARCHIVE_PARSER::CUTOUT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
485 {
486 wxASSERT( aNode->GetName() == wxT( "CUTOUT" ) );
487
488 Vertices = ParseAllChildVertices( aNode, aContext, true );
489 }
490
491
IsShape(XNODE * aNode)492 bool CADSTAR_ARCHIVE_PARSER::SHAPE::IsShape( XNODE* aNode )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)508 void CADSTAR_ARCHIVE_PARSER::SHAPE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
ParseUnits(XNODE * aNode)549 CADSTAR_ARCHIVE_PARSER::UNITS CADSTAR_ARCHIVE_PARSER::ParseUnits( XNODE* aNode )
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
ParseAngunits(XNODE * aNode)576 CADSTAR_ARCHIVE_PARSER::ANGUNITS CADSTAR_ARCHIVE_PARSER::ParseAngunits( XNODE* aNode )
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
IsGrid(XNODE * aNode)593 bool CADSTAR_ARCHIVE_PARSER::GRID::IsGrid( XNODE* aNode )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)604 void CADSTAR_ARCHIVE_PARSER::GRID::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
605 {
606 wxASSERT( IsGrid( aNode ) );
607
608 wxString aNodeName = aNode->GetName();
609
610 if( aNodeName == wxT( "FRACTIONALGRID" ) )
611 Type = GRID_TYPE::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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)623 void CADSTAR_ARCHIVE_PARSER::GRIDS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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 {
639 THROW_UNKNOWN_NODE_IO_ERROR(
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 {
653 THROW_UNKNOWN_NODE_IO_ERROR(
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
ParseSubNode(XNODE * aChildNode,PARSER_CONTEXT * aContext)671 bool CADSTAR_ARCHIVE_PARSER::SETTINGS::ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)725 void CADSTAR_ARCHIVE_PARSER::SETTINGS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
ParseTextFields(const wxString & aTextString,PARSER_CONTEXT * aContext)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
794 TEXT_FIELD_NAME foundField = TEXT_FIELD_NAME::NONE;
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 {
854 case TEXT_FIELD_NAME::DESIGN_TITLE:
855 case TEXT_FIELD_NAME::SHORT_JOBNAME:
856 case TEXT_FIELD_NAME::LONG_JOBNAME:
857 case TEXT_FIELD_NAME::VARIANT_NAME:
858 case TEXT_FIELD_NAME::VARIANT_DESCRIPTION:
859 case TEXT_FIELD_NAME::REG_USER:
860 case TEXT_FIELD_NAME::COMPANY_NAME:
861 case TEXT_FIELD_NAME::CURRENT_USER:
862 case TEXT_FIELD_NAME::DATE:
863 case TEXT_FIELD_NAME::TIME:
864 case TEXT_FIELD_NAME::MACHINE_NAME:
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
876 KI_FALLTHROUGH;
877
878 case TEXT_FIELD_NAME::NUM_OF_SHEETS:
879 case TEXT_FIELD_NAME::SHEET_NUMBER:
880 case TEXT_FIELD_NAME::SHEET_NAME:
881 returnStr += wxT( "${" ) + CADSTAR_TO_KICAD_FIELDS.at( foundField ) + wxT( "}" );
882 break;
883
884 case TEXT_FIELD_NAME::DISTANCE:
885 case TEXT_FIELD_NAME::UNITS_SHORT:
886 case TEXT_FIELD_NAME::UNITS_ABBREV:
887 case TEXT_FIELD_NAME::UNITS_FULL:
888 // Just flatten the text for distances
889 returnStr += fieldValue;
890 break;
891
892 case TEXT_FIELD_NAME::FROM_FILE:
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
914 case TEXT_FIELD_NAME::HYPERLINK:
915 {
916 aContext->TextToHyperlinksMap[fieldValue] = address;
917 returnStr += ParseTextFields( fieldValue, aContext );
918 }
919 break;
920
921 case TEXT_FIELD_NAME::NONE:
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
ParseAlignment(XNODE * aNode)937 CADSTAR_ARCHIVE_PARSER::ALIGNMENT CADSTAR_ARCHIVE_PARSER::ParseAlignment( XNODE* aNode )
938 {
939 wxASSERT( aNode->GetName() == wxT( "ALIGN" ) );
940
941 wxString alignmentStr = GetXmlAttributeIDString( aNode, 0 );
942
943 if( alignmentStr == wxT( "BOTTOMCENTER" ) )
944 return ALIGNMENT::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" ) )
950 return ALIGNMENT::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
965 return ALIGNMENT::NO_ALIGNMENT;
966 }
967
968
ParseJustification(XNODE * aNode)969 CADSTAR_ARCHIVE_PARSER::JUSTIFICATION CADSTAR_ARCHIVE_PARSER::ParseJustification( XNODE* aNode )
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
ParseReadability(XNODE * aNode)988 CADSTAR_ARCHIVE_PARSER::READABILITY CADSTAR_ARCHIVE_PARSER::ParseReadability( XNODE* aNode )
989 {
990 wxASSERT( aNode->GetName() == wxT( "READABILITY" ) );
991
992 wxString readabilityStr = GetXmlAttributeIDString( aNode, 0 );
993
994 if( readabilityStr == wxT( "BOTTOM_TO_TOP" ) )
995 return READABILITY::BOTTOM_TO_TOP;
996 else if( readabilityStr == wxT( "TOP_TO_BOTTOM" ) )
997 return READABILITY::TOP_TO_BOTTOM;
998 else
999 THROW_UNKNOWN_PARAMETER_IO_ERROR( readabilityStr, wxT( "READABILITY" ) );
1000
1001 return READABILITY::BOTTOM_TO_TOP;
1002 }
1003
1004
ParseIdentifiers(XNODE * aNode,PARSER_CONTEXT * aContext)1005 void CADSTAR_ARCHIVE_PARSER::ATTRIBUTE_LOCATION::ParseIdentifiers( XNODE* aNode,
1006 PARSER_CONTEXT* aContext )
1007 {
1008 TextCodeID = GetXmlAttributeIDString( aNode, 0 );
1009 LayerID = GetXmlAttributeIDString( aNode, 1 );
1010 }
1011
1012
ParseSubNode(XNODE * aChildNode,PARSER_CONTEXT * aContext)1013 bool CADSTAR_ARCHIVE_PARSER::ATTRIBUTE_LOCATION::ParseSubNode( XNODE* aChildNode,
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1037 void CADSTAR_ARCHIVE_PARSER::ATTRIBUTE_LOCATION::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1059 void CADSTAR_ARCHIVE_PARSER::ATTRNAME::COLUMNORDER::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1070 void CADSTAR_ARCHIVE_PARSER::ATTRNAME::COLUMNWIDTH::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1081 void CADSTAR_ARCHIVE_PARSER::ATTRNAME::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1183 void CADSTAR_ARCHIVE_PARSER::ATTRIBUTE_VALUE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1211 void CADSTAR_ARCHIVE_PARSER::TEXT_LOCATION::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1308 void CADSTAR_ARCHIVE_PARSER::CADSTAR_NETCLASS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1336 void CADSTAR_ARCHIVE_PARSER::SPCCLASSNAME::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
1337 {
1338 wxASSERT( aNode->GetName() == wxT( "SPCCLASSNAME" ) );
1339
1340 ID = GetXmlAttributeIDString( aNode, 0 );
1341 Name = GetXmlAttributeIDString( aNode, 1 );
1342 }
1343
1344
ParseSubNode(XNODE * aChildNode,PARSER_CONTEXT * aContext)1345 bool CADSTAR_ARCHIVE_PARSER::CODEDEFS::ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext )
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
ParseSwapRule(XNODE * aNode)1400 CADSTAR_ARCHIVE_PARSER::SWAP_RULE CADSTAR_ARCHIVE_PARSER::ParseSwapRule( XNODE* aNode )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1418 void CADSTAR_ARCHIVE_PARSER::REUSEBLOCK::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
IsEmpty()1442 bool CADSTAR_ARCHIVE_PARSER::REUSEBLOCKREF::IsEmpty()
1443 {
1444 return ReuseBlockID == wxEmptyString && ItemReference == wxEmptyString;
1445 }
1446
1447
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1448 void CADSTAR_ARCHIVE_PARSER::REUSEBLOCKREF::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1459 void CADSTAR_ARCHIVE_PARSER::GROUP::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1486 void CADSTAR_ARCHIVE_PARSER::FIGURE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1541 void CADSTAR_ARCHIVE_PARSER::TEXT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
1542 {
1543 Parse( aNode, aContext, true );
1544 }
1545
1546
Parse(XNODE * aNode,PARSER_CONTEXT * aContext,bool aParseFields)1547 void CADSTAR_ARCHIVE_PARSER::TEXT::Parse( XNODE* aNode, PARSER_CONTEXT* aContext,
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
ParseIdentifiers(XNODE * aNode,PARSER_CONTEXT * aContext)1594 void CADSTAR_ARCHIVE_PARSER::SYMDEF::ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext )
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
ParseSubNode(XNODE * aChildNode,PARSER_CONTEXT * aContext)1604 bool CADSTAR_ARCHIVE_PARSER::SYMDEF::ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1653 void CADSTAR_ARCHIVE_PARSER::PART::DEFINITION::GATE::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
GetPinType(XNODE * aNode)1666 CADSTAR_ARCHIVE_PARSER::PART::PIN_TYPE CADSTAR_ARCHIVE_PARSER::PART::GetPinType( XNODE* aNode )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1688 void CADSTAR_ARCHIVE_PARSER::PART::DEFINITION::PIN::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1741 void CADSTAR_ARCHIVE_PARSER::PART::PART_PIN::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1765 void CADSTAR_ARCHIVE_PARSER::PART::DEFINITION::PIN_EQUIVALENCE::Parse( XNODE* aNode,
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1789 void CADSTAR_ARCHIVE_PARSER::PART::DEFINITION::SWAP_GATE::Parse( XNODE* aNode,
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1813 void CADSTAR_ARCHIVE_PARSER::PART::DEFINITION::SWAP_GROUP::Parse( XNODE* aNode,
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1844 void CADSTAR_ARCHIVE_PARSER::PART::DEFINITION::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1902 void CADSTAR_ARCHIVE_PARSER::PART::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)1947 void CADSTAR_ARCHIVE_PARSER::PARTS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
ParseIdentifiers(XNODE * aNode,PARSER_CONTEXT * aContext)1973 void CADSTAR_ARCHIVE_PARSER::NET::JUNCTION::ParseIdentifiers( XNODE* aNode,
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
ParseSubNode(XNODE * aChildNode,PARSER_CONTEXT * aContext)1983 bool CADSTAR_ARCHIVE_PARSER::NET::JUNCTION::ParseSubNode( XNODE* aChildNode,
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)2003 void CADSTAR_ARCHIVE_PARSER::NET::JUNCTION::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
ParseIdentifiers(XNODE * aNode,PARSER_CONTEXT * aContext)2018 void CADSTAR_ARCHIVE_PARSER::NET::CONNECTION::ParseIdentifiers( XNODE* aNode,
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
ParseSubNode(XNODE * aChildNode,PARSER_CONTEXT * aContext)2029 bool CADSTAR_ARCHIVE_PARSER::NET::CONNECTION::ParseSubNode( XNODE* aChildNode,
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
ParseIdentifiers(XNODE * aNode,PARSER_CONTEXT * aContext)2065 void CADSTAR_ARCHIVE_PARSER::NET::ParseIdentifiers( XNODE* aNode, PARSER_CONTEXT* aContext )
2066 {
2067 wxASSERT( aNode->GetName() == wxT( "NET" ) );
2068
2069 ID = GetXmlAttributeIDString( aNode, 0 );
2070 }
2071
2072
ParseSubNode(XNODE * aChildNode,PARSER_CONTEXT * aContext)2073 bool CADSTAR_ARCHIVE_PARSER::NET::ParseSubNode( XNODE* aChildNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)2122 void CADSTAR_ARCHIVE_PARSER::DOCUMENTATION_SYMBOL::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)2188 void CADSTAR_ARCHIVE_PARSER::DFLTSETTINGS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)2212 void CADSTAR_ARCHIVE_PARSER::ATTRCOL::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)2241 void CADSTAR_ARCHIVE_PARSER::ATTRCOLORS::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
Parse(XNODE * aNode,PARSER_CONTEXT * aContext)2269 void CADSTAR_ARCHIVE_PARSER::PARTNAMECOL::Parse( XNODE* aNode, PARSER_CONTEXT* aContext )
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
InsertAttributeAtEnd(XNODE * aNode,wxString aValue)2297 void CADSTAR_ARCHIVE_PARSER::InsertAttributeAtEnd( XNODE* aNode, wxString aValue )
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
LoadArchiveFile(const wxString & aFileName,const wxString & aFileTypeIdentifier,PROGRESS_REPORTER * aProgressReporter)2318 XNODE* CADSTAR_ARCHIVE_PARSER::LoadArchiveFile( const wxString& aFileName,
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
IsValidAttribute(wxXmlAttribute * aAttribute)2422 bool CADSTAR_ARCHIVE_PARSER::IsValidAttribute( wxXmlAttribute* aAttribute )
2423 {
2424 return aAttribute->GetName() != wxT( "numAttributes" );
2425 }
2426
2427
GetXmlAttributeIDString(XNODE * aNode,unsigned int aID,bool aIsRequired)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
GetXmlAttributeIDLong(XNODE * aNode,unsigned int aID,bool aIsRequired)2447 long CADSTAR_ARCHIVE_PARSER::GetXmlAttributeIDLong( XNODE* aNode, unsigned int aID,
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
CheckNoChildNodes(XNODE * aNode)2465 void CADSTAR_ARCHIVE_PARSER::CheckNoChildNodes( XNODE* aNode )
2466 {
2467 if( aNode && aNode->GetChildren() )
2468 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetChildren()->GetName(), aNode->GetName() );
2469 }
2470
2471
CheckNoNextNodes(XNODE * aNode)2472 void CADSTAR_ARCHIVE_PARSER::CheckNoNextNodes( XNODE* aNode )
2473 {
2474 if( aNode && aNode->GetNext() )
2475 THROW_UNKNOWN_NODE_IO_ERROR( aNode->GetNext()->GetName(), aNode->GetParent()->GetName() );
2476 }
2477
2478
ParseChildEValue(XNODE * aNode,PARSER_CONTEXT * aContext,EVALUE & aValueToParse)2479 void CADSTAR_ARCHIVE_PARSER::ParseChildEValue( XNODE* aNode, PARSER_CONTEXT* aContext,
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
ParseAllChildPoints(XNODE * aNode,PARSER_CONTEXT * aContext,bool aTestAllChildNodes,int aExpectedNumPoints)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 {
2514 THROW_IO_ERROR( wxString::Format(
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
ParseAllChildVertices(XNODE * aNode,PARSER_CONTEXT * aContext,bool aTestAllChildNodes)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
ParseAllChildCutouts(XNODE * aNode,PARSER_CONTEXT * aContext,bool aTestAllChildNodes)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
GetNumberOfChildNodes(XNODE * aNode)2575 long CADSTAR_ARCHIVE_PARSER::GetNumberOfChildNodes( XNODE* aNode )
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
GetNumberOfStepsForReporting(XNODE * aRootNode,std::vector<wxString> aSubNodeChildrenToCount)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
HandleTextOverbar(wxString aCadstarString)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
FixTextPositionNoAlignment(EDA_TEXT * aKiCadTextItem)2617 void CADSTAR_ARCHIVE_PARSER::FixTextPositionNoAlignment( EDA_TEXT* aKiCadTextItem )
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
checkPoint()2645 void CADSTAR_ARCHIVE_PARSER::checkPoint()
2646 {
2647 if( m_progressReporter )
2648 {
2649 m_progressReporter->AdvanceProgress();
2650
2651 if( !m_progressReporter->KeepRefreshing() )
2652 THROW_IO_ERROR( _( "File import cancelled by user." ) );
2653 }
2654 }
2655
2656