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.

987 lines
30 KiB

  1. // Name: build_BOM.cpp
  2. // Purpose:
  3. // Author: jean-pierre Charras
  4. // Licence: GPL license
  5. /////////////////////////////////////////////////////////////////////////////
  6. #include <algorithm> // to use sort vector
  7. #include <vector>
  8. #include "fctsys.h"
  9. #include "common.h"
  10. #include "confirm.h"
  11. #include "kicad_string.h"
  12. #include "gestfich.h"
  13. #include "program.h"
  14. #include "libcmp.h"
  15. #include "general.h"
  16. #include "netlist.h"
  17. #include "dialog_build_BOM.h"
  18. #include "protos.h"
  19. /* object used in build BOM to handle the list of labels in schematic
  20. * because in a complex hierarchy, a label is used more than once,
  21. * and had more than one sheet path, so we must create a flat list of labels
  22. */
  23. class LABEL_OBJECT
  24. {
  25. public:
  26. int m_LabelType;
  27. SCH_ITEM* m_Label;
  28. //have to store it here since the object references will be duplicated.
  29. DrawSheetPath m_SheetPath; //composed of UIDs
  30. public:
  31. LABEL_OBJECT()
  32. {
  33. m_Label = NULL;
  34. m_LabelType = 0;
  35. }
  36. };
  37. // Filename extension for BOM list
  38. #define EXT_LIST wxT( ".lst" )
  39. /* Local functions */
  40. static void BuildComponentsListFromSchematic( std::vector <OBJ_CMP_TO_LIST>& aList );
  41. static void GenListeGLabels( std::vector <LABEL_OBJECT>& aList );
  42. static bool SortComponentsByReference( const OBJ_CMP_TO_LIST& obj1, const OBJ_CMP_TO_LIST& obj2 );
  43. static bool SortComponentsByValue( const OBJ_CMP_TO_LIST& obj1, const OBJ_CMP_TO_LIST& obj2 );
  44. static bool SortLabelsByValue( const LABEL_OBJECT& obj1, const LABEL_OBJECT& obj2 );
  45. static bool SortLabelsBySheet( const LABEL_OBJECT& obj1, const LABEL_OBJECT& obj2 );
  46. static void DeleteSubCmp( std::vector <OBJ_CMP_TO_LIST>& aList );
  47. static int PrintListeGLabel( FILE* f, std::vector <LABEL_OBJECT>& aList );
  48. int RefDesStringCompare( const char* obj1, const char* obj2 );
  49. int SplitString( wxString strToSplit,
  50. wxString* strBeginning,
  51. wxString* strDigits,
  52. wxString* strEnd );
  53. /* Local variables */
  54. /* separator used in bom export to spreadsheet */
  55. static char s_ExportSeparatorSymbol;
  56. /**************************************************************************/
  57. void DIALOG_BUILD_BOM::Create_BOM_Lists( bool aTypeFileIsExport,
  58. bool aIncludeSubComponents,
  59. char aExportSeparatorSymbol,
  60. bool aRunBrowser )
  61. /**************************************************************************/
  62. {
  63. wxString mask, filename;
  64. s_ExportSeparatorSymbol = aExportSeparatorSymbol;
  65. m_ListFileName = g_RootSheet->m_AssociatedScreen->m_FileName;
  66. ChangeFileNameExt( m_ListFileName, EXT_LIST );
  67. //need to get rid of the path.
  68. m_ListFileName = m_ListFileName.AfterLast( '/' );
  69. mask = wxT( "*" );
  70. mask += EXT_LIST;
  71. filename = EDA_FileSelector( _( "Bill of materials:" ),
  72. wxEmptyString, /* Chemin par defaut (ici dir courante) */
  73. m_ListFileName, /* nom fichier par defaut, et resultat */
  74. EXT_LIST, /* extension par defaut */
  75. mask, /* Masque d'affichage */
  76. this,
  77. wxFD_SAVE,
  78. TRUE
  79. );
  80. if( filename.IsEmpty() )
  81. return;
  82. else
  83. m_ListFileName = filename;
  84. /* Close dialog, then show the list (if so requested) */
  85. if( aTypeFileIsExport )
  86. CreateExportList( m_ListFileName, aIncludeSubComponents );
  87. else
  88. GenereListeOfItems( m_ListFileName, aIncludeSubComponents );
  89. EndModal( 1 );
  90. if( aRunBrowser )
  91. {
  92. wxString editorname = GetEditorName();
  93. AddDelimiterString( filename );
  94. ExecuteFile( this, editorname, filename );
  95. }
  96. }
  97. /****************************************************************************/
  98. void DIALOG_BUILD_BOM::CreateExportList( const wxString& aFullFileName,
  99. bool aIncludeSubComponents )
  100. /****************************************************************************/
  101. /*
  102. * Print a list of components, in a form which can be imported by a spreadsheet
  103. * form is:
  104. * cmp name; cmp val; fields;
  105. */
  106. {
  107. FILE* f;
  108. wxString msg;
  109. /* Creation de la liste des elements */
  110. if( ( f = wxFopen( aFullFileName, wxT( "wt" ) ) ) == NULL )
  111. {
  112. msg = _( "Failed to open file " );
  113. msg << aFullFileName;
  114. DisplayError( this, msg );
  115. return;
  116. }
  117. std::vector <OBJ_CMP_TO_LIST> cmplist;
  118. BuildComponentsListFromSchematic( cmplist );
  119. /* sort component list */
  120. sort( cmplist.begin(), cmplist.end(), SortComponentsByReference );
  121. if( !aIncludeSubComponents )
  122. DeleteSubCmp( cmplist );
  123. /* create the file */
  124. PrintComponentsListByRef( f, cmplist, TRUE, aIncludeSubComponents );
  125. fclose( f );
  126. }
  127. /****************************************************************************/
  128. void DIALOG_BUILD_BOM::GenereListeOfItems( const wxString& aFullFileName,
  129. bool aIncludeSubComponents )
  130. /****************************************************************************/
  131. /** GenereListeOfItems()
  132. * Main function to create the list of components and/or labels
  133. * (global labels and pin sheets" )
  134. */
  135. {
  136. FILE* f;
  137. int itemCount;
  138. char Line[1024];
  139. wxString msg;
  140. if( ( f = wxFopen( aFullFileName, wxT( "wt" ) ) ) == NULL )
  141. {
  142. msg = _( "Failed to open file " );
  143. msg << aFullFileName;
  144. DisplayError( this, msg );
  145. return;
  146. }
  147. std::vector <OBJ_CMP_TO_LIST> cmplist;
  148. BuildComponentsListFromSchematic( cmplist );
  149. itemCount = cmplist.size();
  150. if( itemCount )
  151. {
  152. /* creates the list file */
  153. DateAndTime( Line );
  154. wxString Title = g_Main_Title + wxT( " " ) + GetBuildVersion();
  155. fprintf( f, "%s >> Creation date: %s\n", CONV_TO_UTF8( Title ), Line );
  156. /* sort component list */
  157. sort( cmplist.begin(), cmplist.end(), SortComponentsByReference );
  158. if( !aIncludeSubComponents )
  159. DeleteSubCmp( cmplist );
  160. if( m_ListCmpbyRefItems->GetValue() )
  161. PrintComponentsListByRef( f, cmplist, false, aIncludeSubComponents );
  162. if( m_ListCmpbyValItems->GetValue() )
  163. {
  164. sort( cmplist.begin(), cmplist.end(), SortComponentsByValue );
  165. PrintComponentsListByVal( f, cmplist, aIncludeSubComponents );
  166. }
  167. }
  168. /*************************************************/
  169. /* Create list of global labels and pins sheets */
  170. /*************************************************/
  171. std::vector <LABEL_OBJECT> listOfLabels;
  172. GenListeGLabels( listOfLabels );
  173. if( ( itemCount = listOfLabels.size() ) > 0 )
  174. {
  175. if( m_GenListLabelsbySheet->GetValue() )
  176. {
  177. sort( listOfLabels.begin(), listOfLabels.end(), SortLabelsBySheet );
  178. msg.Printf( _(
  179. "\n#Global, Hierarchical Labels and PinSheets ( order = Sheet Number ) count = %d\n" ),
  180. itemCount );
  181. fprintf( f, "%s", CONV_TO_UTF8( msg ) );
  182. PrintListeGLabel( f, listOfLabels );
  183. }
  184. if( m_GenListLabelsbyVal->GetValue() )
  185. {
  186. sort( listOfLabels.begin(), listOfLabels.end(), SortLabelsByValue );
  187. msg.Printf( _(
  188. "\n#Global, Hierarchical Labels and PinSheets ( order = Alphab. ) count = %d\n\n" ),
  189. itemCount );
  190. fprintf( f, "%s", CONV_TO_UTF8( msg ) );
  191. PrintListeGLabel( f, listOfLabels );
  192. }
  193. }
  194. msg = _( "\n#End List\n" );
  195. fprintf( f, "%s", CONV_TO_UTF8( msg ) );
  196. fclose( f );
  197. }
  198. /***************************************************************************/
  199. void BuildComponentsListFromSchematic( std::vector <OBJ_CMP_TO_LIST>& aList )
  200. /***************************************************************************/
  201. /* Creates the list of components found in the whole schematic
  202. *
  203. * if List == null, just returns the count. if not, fills the list.
  204. * goes through the sheets, not the screens, so that we account for
  205. * multiple instances of a given screen.
  206. * Also Initialise m_Father as pointerof the SCH_SCREN parent
  207. */
  208. {
  209. EDA_BaseStruct* SchItem;
  210. SCH_COMPONENT* DrawLibItem;
  211. DrawSheetPath* sheet;
  212. /* Build the sheet (not screen) list */
  213. EDA_SheetList SheetList;
  214. for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
  215. {
  216. for( SchItem = sheet->LastDrawList(); SchItem; SchItem = SchItem->Next() )
  217. {
  218. if( SchItem->Type() != TYPE_SCH_COMPONENT )
  219. continue;
  220. DrawLibItem = (SCH_COMPONENT*) SchItem;
  221. DrawLibItem->SetParent( sheet->LastScreen() );
  222. OBJ_CMP_TO_LIST item;
  223. item.m_RootCmp = DrawLibItem;
  224. item.m_SheetPath = *sheet;
  225. item.m_Unit = DrawLibItem->GetUnitSelection( sheet );
  226. strncpy( item.m_Reference,
  227. CONV_TO_UTF8( DrawLibItem->GetRef( sheet ) ),
  228. sizeof( item.m_Reference ) );
  229. // Ensure always nul terminate m_Ref.
  230. item.m_Reference[sizeof( item.m_Reference ) - 1 ] = 0;
  231. aList.push_back( item );
  232. }
  233. }
  234. }
  235. /****************************************************************/
  236. static void GenListeGLabels( std::vector <LABEL_OBJECT>& aList )
  237. /****************************************************************/
  238. /* Fill aList with Glabel info
  239. */
  240. {
  241. SCH_ITEM* DrawList;
  242. Hierarchical_PIN_Sheet_Struct* PinLabel;
  243. DrawSheetPath* sheet;
  244. /* Build the sheet list */
  245. EDA_SheetList SheetList;
  246. LABEL_OBJECT labet_object;
  247. for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
  248. {
  249. DrawList = (SCH_ITEM*) sheet->LastDrawList();
  250. while( DrawList )
  251. {
  252. switch( DrawList->Type() )
  253. {
  254. case TYPE_SCH_HIERLABEL:
  255. case TYPE_SCH_GLOBALLABEL:
  256. labet_object.m_LabelType = DrawList->Type();
  257. labet_object.m_SheetPath = *sheet;
  258. labet_object.m_Label = DrawList;
  259. aList.push_back( labet_object );
  260. break;
  261. case DRAW_SHEET_STRUCT_TYPE:
  262. {
  263. PinLabel = ( (DrawSheetStruct*) DrawList )->m_Label;
  264. while( PinLabel != NULL )
  265. {
  266. labet_object.m_LabelType = DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE;
  267. labet_object.m_SheetPath = *sheet;
  268. labet_object.m_Label = PinLabel;
  269. aList.push_back( labet_object );
  270. PinLabel = PinLabel->Next();
  271. }
  272. }
  273. break;
  274. default:
  275. break;
  276. }
  277. DrawList = DrawList->Next();
  278. }
  279. }
  280. }
  281. /************************************************************************************/
  282. bool SortComponentsByValue( const OBJ_CMP_TO_LIST& obj1, const OBJ_CMP_TO_LIST& obj2 )
  283. /************************************************************************************/
  284. /* Compare fuinction for sort()
  285. * components are sorted
  286. * by value
  287. * if same value: by reference
  288. * if same reference: by unit number
  289. */
  290. {
  291. int ii;
  292. const wxString* Text1, * Text2;
  293. Text1 = &(obj1.m_RootCmp->GetField( VALUE )->m_Text);
  294. Text2 = &(obj2.m_RootCmp->GetField( VALUE )->m_Text);
  295. ii = Text1->CmpNoCase( *Text2 );
  296. if( ii == 0 )
  297. {
  298. ii = RefDesStringCompare( obj1.m_Reference, obj2.m_Reference );
  299. }
  300. if( ii == 0 )
  301. {
  302. ii = obj1.m_Unit - obj2.m_Unit;
  303. }
  304. return ii < 0;
  305. }
  306. /***************************************************************************************/
  307. bool SortComponentsByReference( const OBJ_CMP_TO_LIST& obj1, const OBJ_CMP_TO_LIST& obj2 )
  308. /***************************************************************************************/
  309. /* compare function for sorting
  310. * components are sorted
  311. * by reference
  312. * if same reference: by value
  313. * if same value: by unit number
  314. */
  315. {
  316. int ii;
  317. const wxString* Text1, * Text2;
  318. ii = RefDesStringCompare( obj1.m_Reference, obj2.m_Reference );
  319. if( ii == 0 )
  320. {
  321. Text1 = &( obj1.m_RootCmp->GetField( VALUE )->m_Text );
  322. Text2 = &( obj2.m_RootCmp->GetField( VALUE )->m_Text );
  323. ii = Text1->CmpNoCase( *Text2 );
  324. }
  325. if( ii == 0 )
  326. {
  327. ii = obj1.m_Unit - obj2.m_Unit;
  328. }
  329. return ii < 0;
  330. }
  331. /******************************************************************/
  332. bool SortLabelsByValue( const LABEL_OBJECT& obj1, const LABEL_OBJECT& obj2 )
  333. /*******************************************************************/
  334. /* compare function for sorting labels
  335. * sort by
  336. * value
  337. * if same value: by sheet
  338. */
  339. {
  340. int ii;
  341. wxString* Text1, * Text2;
  342. if( obj1.m_LabelType == DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE )
  343. Text1 = &( (Hierarchical_PIN_Sheet_Struct*)(obj1.m_Label) )->m_Text;
  344. else
  345. Text1 = &( (SCH_TEXT*)(obj1.m_Label) )->m_Text;
  346. if( obj2.m_LabelType == DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE )
  347. Text2 = &( (Hierarchical_PIN_Sheet_Struct*)(obj2.m_Label) )->m_Text;
  348. else
  349. Text2 = &( (SCH_TEXT*)(obj2.m_Label) )->m_Text;
  350. ii = Text1->CmpNoCase( *Text2 );
  351. if( ii == 0 )
  352. {
  353. ii = obj1.m_SheetPath.Cmp( obj2.m_SheetPath );
  354. }
  355. return ii < 0;
  356. }
  357. /*************************************************************************************/
  358. bool SortLabelsBySheet( const LABEL_OBJECT& obj1, const LABEL_OBJECT& obj2 )
  359. /*************************************************************************************/
  360. /* compare function for sorting labels
  361. * by sheet
  362. * in a sheet, by alphabetic order
  363. */
  364. {
  365. int ii;
  366. wxString Text1, Text2;
  367. ii = obj1.m_SheetPath.Cmp( obj2.m_SheetPath );
  368. if( ii == 0 )
  369. {
  370. if( obj1.m_LabelType == DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE )
  371. Text1 = ( (Hierarchical_PIN_Sheet_Struct*) obj1.m_Label )->m_Text;
  372. else
  373. Text1 = ( (SCH_TEXT*) obj1.m_Label )->m_Text;
  374. if( obj2.m_LabelType == DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE )
  375. Text2 = ( (Hierarchical_PIN_Sheet_Struct*) obj2.m_Label )->m_Text;
  376. else
  377. Text2 = ( (SCH_TEXT*) obj2.m_Label )->m_Text;
  378. ii = Text1.CmpNoCase( Text2 );
  379. }
  380. return ii < 0;
  381. }
  382. /**************************************************************/
  383. static void DeleteSubCmp( std::vector <OBJ_CMP_TO_LIST>& aList )
  384. /**************************************************************/
  385. /* Remove sub components from the list, when multiples parts per package are found in this list
  386. * The component list **MUST** be sorted by reference and by unit number
  387. */
  388. {
  389. SCH_COMPONENT* libItem;
  390. wxString oldName;
  391. wxString currName;
  392. for( unsigned ii = 0; ii < aList.size(); ii++ )
  393. {
  394. libItem = aList[ii].m_RootCmp;
  395. if( libItem == NULL )
  396. continue;
  397. currName = CONV_FROM_UTF8( aList[ii].m_Reference );
  398. if( !oldName.IsEmpty() )
  399. {
  400. if( oldName == currName ) // currName is a subpart of oldName: remove it
  401. {
  402. aList.erase( aList.begin() + ii );
  403. ii--;
  404. }
  405. }
  406. oldName = currName;
  407. }
  408. }
  409. /*******************************************************************************************/
  410. void DIALOG_BUILD_BOM::PrintFieldData( FILE* f, SCH_COMPONENT* DrawLibItem,
  411. bool CompactForm )
  412. /*******************************************************************************************/
  413. {
  414. // @todo make this variable length
  415. static const wxCheckBox* FieldListCtrl[] = {
  416. m_AddField1,
  417. m_AddField2,
  418. m_AddField3,
  419. m_AddField4,
  420. m_AddField5,
  421. m_AddField6,
  422. m_AddField7,
  423. m_AddField8
  424. };
  425. int ii;
  426. const wxCheckBox* FieldCtrl = FieldListCtrl[0];
  427. if( m_AddFootprintField->IsChecked() )
  428. {
  429. if( CompactForm )
  430. {
  431. fprintf( f, "%c%s", s_ExportSeparatorSymbol,
  432. CONV_TO_UTF8( DrawLibItem->GetField( FOOTPRINT )->m_Text ) );
  433. }
  434. else
  435. fprintf( f, "; %-12s", CONV_TO_UTF8( DrawLibItem->GetField( FOOTPRINT )->m_Text ) );
  436. }
  437. for( ii = FIELD1; ii < DrawLibItem->GetFieldCount(); ii++ )
  438. {
  439. if ( ii <= FIELD8 ) // see users fields 1 to 8
  440. {
  441. FieldCtrl = FieldListCtrl[ii - FIELD1];
  442. if( FieldCtrl == NULL )
  443. continue;
  444. if( !FieldCtrl->IsChecked() && !m_AddAllFields->IsChecked() )
  445. continue;
  446. }
  447. if( ! m_AddAllFields->IsChecked() )
  448. break;
  449. if( CompactForm )
  450. fprintf( f, "%c%s", s_ExportSeparatorSymbol,
  451. CONV_TO_UTF8( DrawLibItem->GetField( ii )->m_Text ) );
  452. else
  453. fprintf( f, "; %-12s", CONV_TO_UTF8( DrawLibItem->GetField( ii )->m_Text ) );
  454. }
  455. }
  456. /*********************************************************************************************/
  457. int DIALOG_BUILD_BOM::PrintComponentsListByRef(
  458. FILE* f,
  459. std::vector <OBJ_CMP_TO_LIST>& aList,
  460. bool CompactForm,
  461. bool
  462. aIncludeSubComponents )
  463. /*********************************************************************************************/
  464. /* Print the B.O.M sorted by reference
  465. */
  466. {
  467. int Multi, Unit;
  468. EDA_BaseStruct* DrawList;
  469. SCH_COMPONENT* DrawLibItem;
  470. EDA_LibComponentStruct* Entry;
  471. char CmpName[80];
  472. wxString msg;
  473. if( CompactForm )
  474. {
  475. // @todo make this variable length
  476. static const wxCheckBox* FieldListCtrl[FIELD8 - FIELD1 + 1] = {
  477. m_AddField1,
  478. m_AddField2,
  479. m_AddField3,
  480. m_AddField4,
  481. m_AddField5,
  482. m_AddField6,
  483. m_AddField7,
  484. m_AddField8
  485. };
  486. // Print comment line:
  487. fprintf( f, "ref%cvalue", s_ExportSeparatorSymbol );
  488. if( aIncludeSubComponents )
  489. {
  490. fprintf( f, "%csheet path", s_ExportSeparatorSymbol );
  491. fprintf( f, "%clocation", s_ExportSeparatorSymbol );
  492. }
  493. if( m_AddFootprintField->IsChecked() )
  494. fprintf( f, "%cfootprint", s_ExportSeparatorSymbol );
  495. for( int ii = FIELD1; ii <= FIELD8; ii++ )
  496. {
  497. const wxCheckBox* FieldCtrl = FieldListCtrl[ii - FIELD1];
  498. if( FieldCtrl == NULL )
  499. continue;
  500. if( !FieldCtrl->IsChecked() )
  501. continue;
  502. msg = _( "Field" );
  503. fprintf( f, "%c%s%d", s_ExportSeparatorSymbol, CONV_TO_UTF8( msg ), ii - FIELD1 + 1 );
  504. }
  505. fprintf( f, "\n" );
  506. }
  507. else
  508. {
  509. msg = _( "\n#Cmp ( order = Reference )" );
  510. if( aIncludeSubComponents )
  511. msg << _( " (with SubCmp)" );
  512. fprintf( f, "%s\n", CONV_TO_UTF8( msg ) );
  513. }
  514. // Print list of items
  515. for( unsigned ii = 0; ii < aList.size(); ii++ )
  516. {
  517. DrawList = aList[ii].m_RootCmp;
  518. if( DrawList == NULL )
  519. continue;
  520. if( DrawList->Type() != TYPE_SCH_COMPONENT )
  521. continue;
  522. DrawLibItem = (SCH_COMPONENT*) DrawList;
  523. if( aList[ii].m_Reference[0] == '#' )
  524. continue;
  525. Multi = 0;
  526. Unit = ' ';
  527. Entry = FindLibPart( DrawLibItem->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
  528. if( Entry )
  529. Multi = Entry->m_UnitCount;
  530. if( ( Multi > 1 ) && aIncludeSubComponents )
  531. #if defined (KICAD_GOST)
  532. Unit = aList[ii].m_Unit + '1' - 1;
  533. #else
  534. Unit = aList[ii].m_Unit + 'A' - 1;
  535. #endif
  536. sprintf( CmpName, "%s", aList[ii].m_Reference );
  537. if( !CompactForm || Unit != ' ' )
  538. sprintf( CmpName + strlen( CmpName ), "%c", Unit );
  539. if( CompactForm )
  540. fprintf( f, "%s%c%s", CmpName, s_ExportSeparatorSymbol,
  541. CONV_TO_UTF8( DrawLibItem->GetField( VALUE )->m_Text ) );
  542. else
  543. fprintf( f, "| %-10s %-12s", CmpName,
  544. CONV_TO_UTF8( DrawLibItem->GetField( VALUE )->m_Text ) );
  545. if( aIncludeSubComponents )
  546. {
  547. msg = aList[ii].m_SheetPath.PathHumanReadable();
  548. if( CompactForm )
  549. {
  550. fprintf( f, "%c%s", s_ExportSeparatorSymbol, CONV_TO_UTF8( msg ) );
  551. msg = m_Parent->GetXYSheetReferences(
  552. (BASE_SCREEN*) DrawLibItem->GetParent(), DrawLibItem->m_Pos );
  553. fprintf( f, "%c%s)", s_ExportSeparatorSymbol, CONV_TO_UTF8( msg ) );
  554. }
  555. else
  556. {
  557. fprintf( f, " (Sheet %s)", CONV_TO_UTF8( msg ) );
  558. msg = m_Parent->GetXYSheetReferences(
  559. (BASE_SCREEN*) DrawLibItem->GetParent(), DrawLibItem->m_Pos );
  560. fprintf( f, " (loc %s)", CONV_TO_UTF8( msg ) );
  561. }
  562. }
  563. PrintFieldData( f, DrawLibItem, CompactForm );
  564. fprintf( f, "\n" );
  565. }
  566. if( !CompactForm )
  567. {
  568. msg = _( "#End Cmp\n" );
  569. fprintf( f, CONV_TO_UTF8( msg ) );
  570. }
  571. return 0;
  572. }
  573. /*********************************************************************************************/
  574. int DIALOG_BUILD_BOM::PrintComponentsListByVal(
  575. FILE* f,
  576. std::vector <OBJ_CMP_TO_LIST>& aList,
  577. bool
  578. aIncludeSubComponents )
  579. /**********************************************************************************************/
  580. {
  581. int Multi;
  582. wxChar Unit;
  583. EDA_BaseStruct* DrawList;
  584. SCH_COMPONENT* DrawLibItem;
  585. EDA_LibComponentStruct* Entry;
  586. char CmpName[80];
  587. wxString msg;
  588. msg = _( "\n#Cmp ( order = Value )" );
  589. if( aIncludeSubComponents )
  590. msg << _( " (with SubCmp)" );
  591. msg << wxT( "\n" );
  592. fprintf( f, CONV_TO_UTF8( msg ) );
  593. for( unsigned ii = 0; ii < aList.size(); ii++ )
  594. {
  595. DrawList = aList[ii].m_RootCmp;
  596. if( DrawList == NULL )
  597. continue;
  598. if( DrawList->Type() != TYPE_SCH_COMPONENT )
  599. continue;
  600. DrawLibItem = (SCH_COMPONENT*) DrawList;
  601. if( aList[ii].m_Reference[0] == '#' )
  602. continue;
  603. Multi = 0;
  604. Unit = ' ';
  605. Entry = FindLibPart( DrawLibItem->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
  606. if( Entry )
  607. Multi = Entry->m_UnitCount;
  608. if( ( Multi > 1 ) && aIncludeSubComponents )
  609. {
  610. #if defined(KICAD_GOST)
  611. Unit = aList[ii].m_Unit + '1' - 1;
  612. }
  613. sprintf( CmpName, "%s.%c", aList[ii].m_Reference, Unit );
  614. #else
  615. Unit = aList[ii].m_Unit + 'A' - 1;
  616. }
  617. sprintf( CmpName, "%s%c", aList[ii].m_Reference, Unit );
  618. #endif
  619. fprintf( f, "| %-12s %-10s", CONV_TO_UTF8( DrawLibItem->GetField(
  620. VALUE )->m_Text ), CmpName );
  621. // print the sheet path
  622. if( aIncludeSubComponents )
  623. {
  624. msg = aList[ii].m_SheetPath.PathHumanReadable();
  625. fprintf( f, " (Sheet %s)", CONV_TO_UTF8( msg ) );
  626. msg = m_Parent->GetXYSheetReferences(
  627. (BASE_SCREEN*) DrawLibItem->GetParent(), DrawLibItem->m_Pos );
  628. fprintf( f, " (loc %s)", CONV_TO_UTF8( msg ) );
  629. }
  630. PrintFieldData( f, DrawLibItem );
  631. fprintf( f, "\n" );
  632. }
  633. msg = _( "#End Cmp\n" );
  634. fprintf( f, CONV_TO_UTF8( msg ) );
  635. return 0;
  636. }
  637. /************************************************************************/
  638. static int PrintListeGLabel( FILE* f, std::vector <LABEL_OBJECT>& aList )
  639. /************************************************************************/
  640. {
  641. SCH_LABEL* DrawTextItem;
  642. Hierarchical_PIN_Sheet_Struct* DrawSheetLabel;
  643. wxString msg, sheetpath;
  644. wxString labeltype;
  645. for( unsigned ii = 0; ii < aList.size(); ii++ )
  646. {
  647. switch( aList[ii].m_LabelType )
  648. {
  649. case TYPE_SCH_HIERLABEL:
  650. case TYPE_SCH_GLOBALLABEL:
  651. DrawTextItem = (SCH_LABEL*)(aList[ii].m_Label);
  652. if( aList[ii].m_LabelType == TYPE_SCH_HIERLABEL )
  653. labeltype = wxT( "Hierarchical" );
  654. else
  655. labeltype = wxT( "Global " );
  656. sheetpath = aList[ii].m_SheetPath.PathHumanReadable();
  657. msg.Printf(
  658. _( "> %-28.28s %s (Sheet %s) pos: %3.3f, %3.3f\n" ),
  659. DrawTextItem->m_Text.GetData(),
  660. labeltype.GetData(),
  661. sheetpath.GetData(),
  662. (float) DrawTextItem->m_Pos.x / 1000,
  663. (float) DrawTextItem->m_Pos.y / 1000 );
  664. fprintf( f, CONV_TO_UTF8( msg ) );
  665. break;
  666. case DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE:
  667. {
  668. DrawSheetLabel = (Hierarchical_PIN_Sheet_Struct*) aList[ii].m_Label;
  669. int jj = DrawSheetLabel->m_Shape;
  670. if( jj < 0 )
  671. jj = NET_TMAX;
  672. if( jj > NET_TMAX )
  673. jj = 4;
  674. wxString labtype = CONV_FROM_UTF8( SheetLabelType[jj] );
  675. msg.Printf(
  676. _( "> %-28.28s PinSheet %-7.7s (Sheet %s) pos: %3.3f, %3.3f\n" ),
  677. DrawSheetLabel->m_Text.GetData(),
  678. labtype.GetData(),
  679. aList[ii].m_SheetPath.PathHumanReadable().GetData(),
  680. (float) DrawSheetLabel->m_Pos.x / 1000,
  681. (float) DrawSheetLabel->m_Pos.y / 1000 );
  682. fprintf( f, CONV_TO_UTF8( msg ) );
  683. }
  684. break;
  685. default:
  686. break;
  687. }
  688. }
  689. msg = _( "#End labels\n" );
  690. fprintf( f, CONV_TO_UTF8( msg ) );
  691. return 0;
  692. }
  693. /********************************************/
  694. int RefDesStringCompare( const char* obj1, const char* obj2 )
  695. /********************************************/
  696. /* This function will act just like the strcmp function but correctly sort
  697. * the numerical order in the string
  698. * return -1 if first string is less than the second
  699. * return 0 if the strings are equal
  700. * return 1 if the first string is greater than the second
  701. */
  702. {
  703. /* The strings we are going to compare */
  704. wxString strFWord;
  705. wxString strSWord;
  706. /* The different sections of the first string */
  707. wxString strFWordBeg, strFWordMid, strFWordEnd;
  708. /* The different sections of the second string */
  709. wxString strSWordBeg, strSWordMid, strSWordEnd;
  710. int isEqual = 0; /* The numerical results of a string compare */
  711. int iReturn = 0; /* The variable that is being returned */
  712. long lFirstDigit = 0; /* The converted middle section of the first string */
  713. long lSecondDigit = 0; /* The converted middle section of the second string */
  714. /* Since m_Ref is a char * it is ASCII */
  715. strFWord = wxString::FromAscii( obj1 );
  716. strSWord = wxString::FromAscii( obj2 );
  717. /* Split the two string into seperate parts */
  718. SplitString( strFWord, &strFWordBeg, &strFWordMid, &strFWordEnd );
  719. SplitString( strSWord, &strSWordBeg, &strSWordMid, &strSWordEnd );
  720. /* Compare the Beginning section of the strings */
  721. isEqual = strFWordBeg.CmpNoCase( strSWordBeg );
  722. if( isEqual > 0 )
  723. iReturn = 1;
  724. else if( isEqual < 0 )
  725. iReturn = -1;
  726. else
  727. {
  728. /* If the first sections are equal compare there digits */
  729. strFWordMid.ToLong( &lFirstDigit );
  730. strSWordMid.ToLong( &lSecondDigit );
  731. if( lFirstDigit > lSecondDigit )
  732. iReturn = 1;
  733. else if( lFirstDigit < lSecondDigit )
  734. iReturn = -1;
  735. else
  736. {
  737. /* If the first two sections are equal compare the endings */
  738. isEqual = strFWordEnd.CmpNoCase( strSWordEnd );
  739. if( isEqual > 0 )
  740. iReturn = 1;
  741. else if( isEqual < 0 )
  742. iReturn = -1;
  743. else
  744. iReturn = 0;
  745. }
  746. }
  747. return iReturn;
  748. }
  749. /**************************************************************************************************/
  750. int SplitString( wxString strToSplit,
  751. wxString* strBeginning,
  752. wxString* strDigits,
  753. wxString* strEnd )
  754. /**************************************************************************************************/
  755. /* This is the function that breaks a string into three parts.
  756. * The alphabetic preamble
  757. * The numeric part
  758. * Any alphabetic ending
  759. * For example C10A is split to C 10 A
  760. */
  761. {
  762. /* Clear all the return strings */
  763. strBeginning->Clear();
  764. strDigits->Clear();
  765. strEnd->Clear();
  766. /* There no need to do anything if the string is empty */
  767. if( strToSplit.length() == 0 )
  768. return 0;
  769. /* Starting at the end of the string look for the first digit */
  770. int ii;
  771. for( ii = (strToSplit.length() - 1); ii >= 0; ii-- )
  772. {
  773. if( isdigit( strToSplit[ii] ) )
  774. break;
  775. }
  776. /* If there were no digits then just set the single string */
  777. if( ii < 0 )
  778. *strBeginning = strToSplit;
  779. else
  780. {
  781. /* Since there is at least one digit this is the trailing string */
  782. *strEnd = strToSplit.substr( ii + 1 );
  783. /* Go to the end of the digits */
  784. int position = ii + 1;
  785. for( ; ii >= 0; ii-- )
  786. {
  787. if( !isdigit( strToSplit[ii] ) )
  788. break;
  789. }
  790. /* If all that was left was digits, then just set the digits string */
  791. if( ii < 0 )
  792. *strDigits = strToSplit.substr( 0, position );
  793. /* We were only looking for the last set of digits everything else is part of the preamble */
  794. else
  795. {
  796. *strDigits = strToSplit.substr( ii + 1, position - ii - 1 );
  797. *strBeginning = strToSplit.substr( 0, ii + 1 );
  798. }
  799. }
  800. return 0;
  801. }