You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2565 lines
76 KiB

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