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.

1023 lines
31 KiB

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