diff --git a/CHANGELOG.txt b/CHANGELOG.txt index b0388a93a2..3a6f0df390 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,20 @@ KiCad ChangeLog 2010 Please add newer entries at the top, list the date and your name with email address. +2010-Jul-30 UPDATE Dick Hollenbeck +================================================================================ +++eeschema: + * Now link with XML support within wxWidgets. + * Start of export the generic netlist in XML. Still need to rework the chain + loaded netlist plugin. + * OBJ_CMP_TO_LIST class now uses a std::string to hold the 8 bit string m_Ref, + but hides this behind accessors which provide for both Unicode and 8 bit + set and get functions. + * build_BOM.cpp retains the selected filename on subsequent runs as a default. + * Code cleaning, especially in build_BOM.cpp. + * Will work tomorrow also. + + 2010-jul-27, UPDATE Jean-Pierre Charras ================================================================================ ++all: diff --git a/CMakeLists.txt b/CMakeLists.txt index cf37b88391..7b0114ea05 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -134,9 +134,9 @@ check_find_package_result(OPENGL_FOUND "OpenGL") # On Apple only wxwidgets 2.9 or higher doesn't need to find aui part of base if(APPLE) - find_package(wxWidgets COMPONENTS gl adv html core net base QUIET) + find_package(wxWidgets COMPONENTS gl adv html core net base xml QUIET) else(APPLE) - find_package(wxWidgets COMPONENTS gl aui adv html core net base QUIET) + find_package(wxWidgets COMPONENTS gl aui adv html core net base xml QUIET) endif(APPLE) check_find_package_result(wxWidgets_FOUND "wxWidgets") diff --git a/eeschema/annotate.cpp b/eeschema/annotate.cpp index 1880d4d876..8831966dae 100644 --- a/eeschema/annotate.cpp +++ b/eeschema/annotate.cpp @@ -381,8 +381,7 @@ int AddComponentsInSheetToList( std::vector & aComponentsList, if( DrawLibItem->GetRef( aSheet ).IsEmpty() ) DrawLibItem->SetRef( aSheet, wxT( "DefRef?" ) ); - strncpy( new_object.m_Reference, - CONV_TO_UTF8( DrawLibItem->GetRef( aSheet ) ), 32 ); + new_object.SetRef( DrawLibItem->GetRef( aSheet ) ); new_object.m_NumRef = -1; @@ -409,6 +408,7 @@ static void ReAnnotateComponents( std::vector & aComponentsList /* update the reference numbers */ for( unsigned ii = 0; ii < aComponentsList.size(); ii++ ) { +#if 0 char* Text = aComponentsList[ii].m_Reference; SCH_COMPONENT* component = aComponentsList[ii].m_RootCmp; @@ -419,8 +419,23 @@ static void ReAnnotateComponents( std::vector & aComponentsList component->SetRef( &(aComponentsList[ii].m_SheetPath), CONV_FROM_UTF8( Text ) ); +#else + + wxString ref = aComponentsList[ii].GetRef(); + SCH_COMPONENT* component = aComponentsList[ii].m_RootCmp; + + if( aComponentsList[ii].m_NumRef < 0 ) + ref += wxChar( '?' ); + else + ref << aComponentsList[ii].m_NumRef; + + aComponentsList[ii].SetRef( ref ); + + component->SetRef( &aComponentsList[ii].m_SheetPath, ref ); +#endif + component->m_Multi = aComponentsList[ii].m_Unit; - component->SetUnitSelection( &(aComponentsList[ii].m_SheetPath), + component->SetUnitSelection( &aComponentsList[ii].m_SheetPath, aComponentsList[ii].m_Unit ); } } @@ -437,41 +452,57 @@ static void ReAnnotateComponents( std::vector & aComponentsList */ void BreakReference( std::vector & aComponentsList ) { - char* Text; + std::string refText; // construct once outside loop for( unsigned ii = 0; ii < aComponentsList.size(); ii++ ) { aComponentsList[ii].m_NumRef = -1; - Text = aComponentsList[ii].m_Reference; - int ll = strlen( Text ) - 1; - if( Text[ll] == '?' ) + + refText = aComponentsList[ii].GetRefStr(); + + int ll = refText.length() - 1; + + if( refText[ll] == '?' ) + { + aComponentsList[ii].m_IsNew = true; + + if( !aComponentsList[ii].IsPartsLocked() ) + aComponentsList[ii].m_Unit = 0x7FFFFFFF; + + refText.erase(ll); // delete last char + + aComponentsList[ii].SetRefStr( refText ); + } + + else if( isdigit( refText[ll] ) == 0 ) { aComponentsList[ii].m_IsNew = true; if( !aComponentsList[ii].IsPartsLocked() ) aComponentsList[ii].m_Unit = 0x7FFFFFFF; - Text[ll] = 0; - continue; } - if( isdigit( Text[ll] ) == 0 ) + else { - aComponentsList[ii].m_IsNew = true; - if( !aComponentsList[ii].IsPartsLocked() ) - aComponentsList[ii].m_Unit = 0x7FFFFFFF; - continue; - } - - while( ll >= 0 ) - { - if( (Text[ll] <= ' ' ) || isdigit( Text[ll] ) ) - ll--; - else + while( ll >= 0 ) { - if( isdigit( Text[ll + 1] ) ) - aComponentsList[ii].m_NumRef = atoi( &Text[ll + 1] ); - Text[ll + 1] = 0; - break; + if( (refText[ll] <= ' ' ) || isdigit( refText[ll] ) ) + ll--; + else + { + if( isdigit( refText[ll + 1] ) ) + { + // nul terminated C string into cp + const char* cp = refText.c_str() + ll + 1; + + aComponentsList[ii].m_NumRef = atoi( cp ); + } + + refText.erase( ll+1 ); // delete from ll+1 to end + break; + } } + + aComponentsList[ii].SetRefStr( refText ); } } } @@ -490,7 +521,7 @@ static void ComputeReferenceNumber( std::vector & aComponentsLi */ for( unsigned ii = 0; ii < aComponentsList.size(); ii++ ) { - if( aComponentsList[ii].m_Reference[0] == '#' ) + if( aComponentsList[ii].GetRefStr()[0] == '#' ) { aComponentsList[ii].m_IsNew = true; aComponentsList[ii].m_NumRef = 0; @@ -716,9 +747,9 @@ int WinEDA_SchematicFrame::CheckAnnotate( wxArrayString* aMessageList, else Buff = wxT( "?" ); - cmpref = CONV_FROM_UTF8( ComponentsList[ii].m_Reference ); + cmpref = ComponentsList[ii].GetRef(); msg.Printf( _( "item not annotated: %s%s" ), - cmpref.GetData(), Buff.GetData() ); + GetChars( cmpref ), GetChars( Buff ) ); if( ( ComponentsList[ii].m_Unit > 0 ) && ( ComponentsList[ii].m_Unit < 0x7FFFFFFF ) ) @@ -748,9 +779,10 @@ int WinEDA_SchematicFrame::CheckAnnotate( wxArrayString* aMessageList, else Buff = wxT( "?" ); - cmpref = CONV_FROM_UTF8( ComponentsList[ii].m_Reference ); - msg.Printf( _( "Error item %s%s" ), cmpref.GetData(), - Buff.GetData() ); + cmpref = ComponentsList[ii].GetRef(); + + msg.Printf( _( "Error item %s%s" ), GetChars( cmpref ), + GetChars( Buff ) ); Buff.Printf( _( " unit %d and no more than %d parts" ), ComponentsList[ii].m_Unit, @@ -789,9 +821,10 @@ int WinEDA_SchematicFrame::CheckAnnotate( wxArrayString* aMessageList, else Buff = wxT( "?" ); - cmpref = CONV_FROM_UTF8( ComponentsList[ii].m_Reference ); + cmpref = ComponentsList[ii].GetRef(); + msg.Printf( _( "Multiple item %s%s" ), - cmpref.GetData(), Buff.GetData() ); + GetChars( cmpref ), GetChars( Buff ) ); if( ( ComponentsList[ii].m_Unit > 0 ) && ( ComponentsList[ii].m_Unit < 0x7FFFFFFF ) ) @@ -819,9 +852,9 @@ int WinEDA_SchematicFrame::CheckAnnotate( wxArrayString* aMessageList, else Buff = wxT( "?" ); - cmpref = CONV_FROM_UTF8( ComponentsList[ii].m_Reference ); + cmpref = ComponentsList[ii].GetRef(); msg.Printf( _( "Multiple item %s%s" ), - cmpref.GetData(), Buff.GetData() ); + GetChars( cmpref ), GetChars( Buff ) ); if( ( ComponentsList[ii].m_Unit > 0 ) && ( ComponentsList[ii].m_Unit < 0x7FFFFFFF ) ) @@ -846,16 +879,17 @@ int WinEDA_SchematicFrame::CheckAnnotate( wxArrayString* aMessageList, int next = ii + 1; if( ComponentsList[ii].CompareValue( ComponentsList[next] ) != 0 ) { - wxString nextcmpref; - cmpref = CONV_FROM_UTF8( ComponentsList[ii].m_Reference ); - nextcmpref = CONV_FROM_UTF8( ComponentsList[next].m_Reference ); + wxString nextcmpref = ComponentsList[next].GetRef(); + + cmpref = ComponentsList[ii].GetRef(); + #if defined(KICAD_GOST) msg.Printf( _( "Diff values for %s%d.%c (%s) and %s%d.%c (%s)" ), cmpref.GetData(), ComponentsList[ii].m_NumRef, ComponentsList[ii].m_Unit + '1' - 1, - ComponentsList[ii].m_Value->GetData(), - nextcmpref.GetData(), + GetChars( *ComponentsList[ii].m_Value ), + GetChars( nextcmpref ), ComponentsList[next].m_NumRef, ComponentsList[next].m_Unit + '1' - 1, ComponentsList[next].m_Value->GetData() ); @@ -864,11 +898,11 @@ int WinEDA_SchematicFrame::CheckAnnotate( wxArrayString* aMessageList, cmpref.GetData(), ComponentsList[ii].m_NumRef, ComponentsList[ii].m_Unit + 'A' - 1, - ComponentsList[ii].m_Value->GetData(), - nextcmpref.GetData(), + GetChars( *ComponentsList[ii].m_Value ), + GetChars( nextcmpref ), ComponentsList[next].m_NumRef, ComponentsList[next].m_Unit + 'A' - 1, - ComponentsList[next].m_Value->GetData() ); + GetChars( *ComponentsList[next].m_Value ) ); #endif if( aMessageList ) @@ -897,15 +931,19 @@ int WinEDA_SchematicFrame::CheckAnnotate( wxArrayString* aMessageList, /* Same time stamp found. */ wxString nextcmpref; wxString full_path; + full_path.Printf( wxT( "%s%8.8X" ), - ComponentsList[ii].m_SheetPath.Path().GetData(), + GetChars( ComponentsList[ii].m_SheetPath.Path() ), ComponentsList[ii].m_TimeStamp ); - cmpref = CONV_FROM_UTF8( ComponentsList[ii].m_Reference ); - nextcmpref = CONV_FROM_UTF8( ComponentsList[ii + 1].m_Reference ); + + cmpref = ComponentsList[ii].GetRef(); + nextcmpref = ComponentsList[ii + 1].GetRef(); + msg.Printf( _( "duplicate time stamp (%s) for %s%d and %s%d" ), - full_path.GetData(), - cmpref.GetData(), ComponentsList[ii].m_NumRef, - nextcmpref.GetData(), ComponentsList[ii + 1].m_NumRef ); + GetChars( full_path ), + GetChars( cmpref ), ComponentsList[ii].m_NumRef, + GetChars( nextcmpref ), ComponentsList[ii + 1].m_NumRef ); + if( aMessageList ) { aMessageList->Add( msg + wxT( "\n" )); diff --git a/eeschema/build_BOM.cpp b/eeschema/build_BOM.cpp index 1f4613b7b9..0f14387a32 100644 --- a/eeschema/build_BOM.cpp +++ b/eeschema/build_BOM.cpp @@ -32,7 +32,10 @@ * the return value for an error. */ -/* object used in build BOM to handle the list of labels in schematic + +/** + * Class LABEL_OBJECT + * is used in build BOM to handle the list of labels in schematic * because in a complex hierarchy, a label is used more than once, * and had more than one sheet path, so we must create a flat list of labels */ @@ -53,14 +56,9 @@ public: LABEL_OBJECT() }; -// Filename extension for BOM list -static const wxString BomFileExtension( wxT( "lst" ) ); -static const wxString CsvFileExtension( wxT( "csv" ) ); -#define BomFileWildcard _( "Bill of Materials file (*.lst)|*.lst" ) - - static void BuildComponentsListFromSchematic( std::vector & aList ); + static void GenListeGLabels( std::vector & aList ); static bool SortComponentsByReference( const OBJ_CMP_TO_LIST& obj1, const OBJ_CMP_TO_LIST& obj2 ); @@ -73,14 +71,14 @@ static bool SortLabelsBySheet( const LABEL_OBJECT& obj1, static void DeleteSubCmp( std::vector & aList ); static int PrintListeGLabel( FILE* f, std::vector & aList ); -int RefDesStringCompare( const char* obj1, const char* obj2 ); +int RefDesStringCompare( const wxString& lhs, const wxString& rhs ); int SplitString( wxString strToSplit, wxString* strBeginning, wxString* strDigits, wxString* strEnd ); -/* separator used in bom export to spreadsheet */ +// separator used in bom export to spreadsheet static char s_ExportSeparatorSymbol; @@ -89,27 +87,53 @@ void DIALOG_BUILD_BOM::Create_BOM_Lists( int aTypeFile, char aExportSeparatorSymbol, bool aRunBrowser ) { - wxFileName fn; + wxString wildcard; + + static wxFileName fn; + + wxFileName current = g_RootSheet->m_AssociatedScreen->m_FileName; s_ExportSeparatorSymbol = aExportSeparatorSymbol; - m_ListFileName = g_RootSheet->m_AssociatedScreen->m_FileName; - fn = m_ListFileName; - if( aTypeFile == 2 ) - fn.SetExt( CsvFileExtension ); - else - fn.SetExt( BomFileExtension ); + if( !fn.HasName() || fn.GetName()==NAMELESS_PROJECT ) + { + fn.SetName( current.GetName() ); + } + // else use a previous run's name, because fn was set before and user + // is probably just iteratively refining the BOM. - wxFileDialog dlg( this, _( "Bill of Materials" ), fn.GetPath(), - fn.GetFullName(), BomFileWildcard, + if( fn.GetPath().IsEmpty() ) + { + fn.SetPath( current.GetPath() ); + } + // else use a previous run's path, because fn was set before and user + // is probably just iteratively refining the BOM. + + wxString bomDesc = _( "Bill of Materials" ); // translate once, use twice. + + if( aTypeFile == 0 ) + { + fn.SetExt( wxT( "lst" ) ); + wildcard = bomDesc + wxT( " (*.lst)|*.lst" ); + } + else + { + fn.SetExt( wxT( "csv" ) ); + wildcard = bomDesc + wxT( " (*.csv)|*.csv" ); + } + + wxFileDialog dlg( this, bomDesc, fn.GetPath(), + fn.GetFullName(), wildcard, wxFD_SAVE | wxFD_OVERWRITE_PROMPT ); if( dlg.ShowModal() == wxID_CANCEL ) return; + fn = dlg.GetPath(); // remember path+filename+ext for subsequent runs. + m_ListFileName = dlg.GetPath(); - /* Close dialog, then show the list (if so requested) */ + // Close dialog, then show the list (if so requested) switch( aTypeFile ) { @@ -148,6 +172,7 @@ bool DIALOG_BUILD_BOM::IsFieldChecked(int aFieldId) { if( m_AddAllFields->IsChecked() && (aFieldId>= FIELD1) ) return true; + switch ( aFieldId ) { case FIELD1: @@ -173,11 +198,7 @@ bool DIALOG_BUILD_BOM::IsFieldChecked(int aFieldId) return false; } -/* - * Print a list of components, in a form which can be imported by a spreadsheet - * form is: - * cmp value; number of components; ; ; ...; list of references having the same value - */ + void DIALOG_BUILD_BOM::CreatePartsList( const wxString& aFullFileName, bool aIncludeSubComponents ) { FILE* f; @@ -192,16 +213,17 @@ void DIALOG_BUILD_BOM::CreatePartsList( const wxString& aFullFileName, bool aInc } std::vector cmplist; + BuildComponentsListFromSchematic( cmplist ); - /* sort component list by ref and remove sub components*/ + // sort component list by ref and remove sub components if( !aIncludeSubComponents ) { sort( cmplist.begin(), cmplist.end(), SortComponentsByReference ); DeleteSubCmp( cmplist ); } - /* sort component list by value*/ + // sort component list by value sort( cmplist.begin(), cmplist.end(), SortComponentsByValue ); PrintComponentsListByPart( f, cmplist,aIncludeSubComponents ); @@ -231,13 +253,13 @@ void DIALOG_BUILD_BOM::CreateExportList( const wxString& aFullFileName, std::vector cmplist; BuildComponentsListFromSchematic( cmplist ); - /* sort component list */ + // sort component list sort( cmplist.begin(), cmplist.end(), SortComponentsByReference ); if( !aIncludeSubComponents ) DeleteSubCmp( cmplist ); - /* create the file */ + // create the file PrintComponentsListByRef( f, cmplist, TRUE, aIncludeSubComponents ); fclose( f ); @@ -270,13 +292,15 @@ void DIALOG_BUILD_BOM::GenereListeOfItems( const wxString& aFullFileName, itemCount = cmplist.size(); if( itemCount ) { - /* creates the list file */ + // creates the list file DateAndTime( Line ); + wxString Title = wxGetApp().GetAppName() + wxT( " " ) + GetBuildVersion(); + fprintf( f, "%s >> Creation date: %s\n", CONV_TO_UTF8( Title ), Line ); - /* sort component list */ + // sort component list sort( cmplist.begin(), cmplist.end(), SortComponentsByReference ); if( !aIncludeSubComponents ) @@ -296,16 +320,19 @@ void DIALOG_BUILD_BOM::GenereListeOfItems( const wxString& aFullFileName, /* Create list of global labels and pins sheets */ /*************************************************/ std::vector listOfLabels; + GenListeGLabels( listOfLabels ); if( ( itemCount = listOfLabels.size() ) > 0 ) { if( m_GenListLabelsbySheet->GetValue() ) { sort( listOfLabels.begin(), listOfLabels.end(), SortLabelsBySheet ); + msg.Printf( _( - "\n#Global, Hierarchical Labels and PinSheets \ -( order = Sheet Number ) count = %d\n" ), + "\n#Global, Hierarchical Labels and PinSheets " + "( order = Sheet Number ) count = %d\n" ), itemCount ); + fprintf( f, "%s", CONV_TO_UTF8( msg ) ); PrintListeGLabel( f, listOfLabels ); } @@ -315,9 +342,10 @@ void DIALOG_BUILD_BOM::GenereListeOfItems( const wxString& aFullFileName, sort( listOfLabels.begin(), listOfLabels.end(), SortLabelsByValue ); msg.Printf( _( - "\n#Global, Hierarchical Labels and PinSheets ( \ -order = Alphab. ) count = %d\n\n" ), + "\n#Global, Hierarchical Labels and PinSheets ( " + "order = Alphab. ) count = %d\n\n" ), itemCount ); + fprintf( f, "%s", CONV_TO_UTF8( msg ) ); PrintListeGLabel( f, listOfLabels ); } @@ -329,47 +357,43 @@ order = Alphab. ) count = %d\n\n" } -/* Creates the list of components found in the whole schematic +/** + * Function BuildComponentsListFromSchematic + * creates the list of components found in the whole schematic. * - * if List == null, just returns the count. if not, fills the list. - * goes through the sheets, not the screens, so that we account for + * Goes through the 'sheets', not the screens, so that we account for * multiple instances of a given screen. - * Also Initialize m_Father as pointer of the SCH_SCREEN parent */ void BuildComponentsListFromSchematic( std::vector & aList ) { - EDA_BaseStruct* SchItem; - SCH_COMPONENT* DrawLibItem; - SCH_SHEET_PATH* sheetPath; + // Build the sheet list (which is not screen a screen list) + SCH_SHEET_LIST sheetList; // uses a global - /* Build the sheet (not screen) list */ - SCH_SHEET_LIST SheetList; - - for( sheetPath = SheetList.GetFirst(); sheetPath != NULL; sheetPath = SheetList.GetNext() ) + for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext() ) { - for( SchItem = sheetPath->LastDrawList(); SchItem; SchItem = SchItem->Next() ) + for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() ) { - if( SchItem->Type() != TYPE_SCH_COMPONENT ) + if( schItem->Type() != TYPE_SCH_COMPONENT ) continue; - DrawLibItem = (SCH_COMPONENT*) SchItem; - DrawLibItem->SetParent( sheetPath->LastScreen() ); + SCH_COMPONENT* comp = (SCH_COMPONENT*) schItem; + + comp->SetParent( path->LastScreen() ); + OBJ_CMP_TO_LIST item; - item.m_RootCmp = DrawLibItem; - item.m_SheetPath = *sheetPath; - item.m_Unit = DrawLibItem->GetUnitSelection( sheetPath ); - strncpy( item.m_Reference, - CONV_TO_UTF8( DrawLibItem->GetRef( sheetPath ) ), - sizeof( item.m_Reference ) ); + item.m_RootCmp = comp; + item.m_SheetPath = *path; + item.m_Unit = comp->GetUnitSelection( path ); - // Ensure always null terminate m_Ref. - item.m_Reference[sizeof( item.m_Reference ) - 1 ] = 0; - // Skip pseudo components: - // pseudo components have a reference starting by #. Mainly power symbols - if( item.m_Reference[0] == '#' ) + item.SetRef( comp->GetRef( path ) ); + + // skip pseudo components, which have a reference starting + // with #, mainly power symbols + if( item.GetRefStr()[0] == '#' ) continue; - // Real component found, push it in list + + // Real component found, keep it aList.push_back( item ); } } @@ -380,40 +404,37 @@ void BuildComponentsListFromSchematic( std::vector & aList ) */ static void GenListeGLabels( std::vector & aList ) { - SCH_ITEM* DrawList; - SCH_SHEET_PATH* sheetPath; + // Build the sheet list + SCH_SHEET_LIST sheetList; - /* Build the sheet list */ - SCH_SHEET_LIST SheetList; + LABEL_OBJECT lable; - LABEL_OBJECT labet_object; - - for( sheetPath = SheetList.GetFirst(); sheetPath != NULL; sheetPath = SheetList.GetNext() ) + for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext() ) { - DrawList = (SCH_ITEM*) sheetPath->LastDrawList(); + SCH_ITEM* schItem = (SCH_ITEM*) path->LastDrawList(); - while( DrawList ) + while( schItem ) { - switch( DrawList->Type() ) + switch( schItem->Type() ) { case TYPE_SCH_HIERLABEL: case TYPE_SCH_GLOBALLABEL: - labet_object.m_LabelType = DrawList->Type(); - labet_object.m_SheetPath = *sheetPath; - labet_object.m_Label = DrawList; - aList.push_back( labet_object ); + lable.m_LabelType = schItem->Type(); + lable.m_SheetPath = *path; + lable.m_Label = schItem; + aList.push_back( lable ); break; case DRAW_SHEET_STRUCT_TYPE: { - SCH_SHEET* sheet = (SCH_SHEET*) DrawList; + SCH_SHEET* sheet = (SCH_SHEET*) schItem; BOOST_FOREACH( SCH_SHEET_PIN sheetLabel, sheet->GetSheetPins() ) { - labet_object.m_LabelType = DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE; - labet_object.m_SheetPath = *sheetPath; - labet_object.m_Label = &sheetLabel; - aList.push_back( labet_object ); + lable.m_LabelType = DRAW_HIERARCHICAL_PIN_SHEET_STRUCT_TYPE; + lable.m_SheetPath = *path; + lable.m_Label = &sheetLabel; + aList.push_back( lable ); } } break; @@ -422,7 +443,7 @@ static void GenListeGLabels( std::vector & aList ) break; } - DrawList = DrawList->Next(); + schItem = schItem->Next(); } } } @@ -446,7 +467,7 @@ bool SortComponentsByValue( const OBJ_CMP_TO_LIST& obj1, if( ii == 0 ) { - ii = RefDesStringCompare( obj1.m_Reference, obj2.m_Reference ); + ii = RefDesStringCompare( obj1.GetRef(), obj2.GetRef() ); } if( ii == 0 ) @@ -470,7 +491,7 @@ bool SortComponentsByReference( const OBJ_CMP_TO_LIST& obj1, int ii; const wxString* Text1, * Text2; - ii = RefDesStringCompare( obj1.m_Reference, obj2.m_Reference ); + ii = RefDesStringCompare( obj1.GetRef(), obj2.GetRef() ); if( ii == 0 ) { @@ -528,7 +549,6 @@ bool SortLabelsBySheet( const LABEL_OBJECT& obj1, const LABEL_OBJECT& obj2 ) int ii; wxString Text1, Text2; - ii = obj1.m_SheetPath.Cmp( obj2.m_SheetPath ); if( ii == 0 ) @@ -567,7 +587,7 @@ static void DeleteSubCmp( std::vector & aList ) if( libItem == NULL ) continue; - currName = CONV_FROM_UTF8( aList[ii].m_Reference ); + currName = aList[ii].GetRef(); if( !oldName.IsEmpty() ) { @@ -606,6 +626,7 @@ void DIALOG_BUILD_BOM::PrintFieldData( FILE* f, SCH_COMPONENT* DrawLibItem, { if( ! IsFieldChecked( ii ) ) continue; + if( CompactForm ) fprintf( f, "%c%s", s_ExportSeparatorSymbol, CONV_TO_UTF8( DrawLibItem->GetField( ii )->m_Text ) ); @@ -624,10 +645,6 @@ int DIALOG_BUILD_BOM::PrintComponentsListByRef( bool CompactForm, bool aIncludeSubComponents ) { - EDA_BaseStruct* DrawList; - SCH_COMPONENT* DrawLibItem; - LIB_COMPONENT* Entry; - char CmpName[80]; wxString msg; if( CompactForm ) @@ -654,6 +671,7 @@ int DIALOG_BUILD_BOM::PrintComponentsListByRef( continue; msg = _( "Field" ); + fprintf( f, "%c%s%d", s_ExportSeparatorSymbol, CONV_TO_UTF8( msg ), ii - FIELD1 + 1 ); } @@ -666,80 +684,91 @@ int DIALOG_BUILD_BOM::PrintComponentsListByRef( if( aIncludeSubComponents ) msg << _( " (with SubCmp)" ); + fprintf( f, "%s\n", CONV_TO_UTF8( msg ) ); } + std::string CmpName; + wxString subRef; + // Print list of items for( unsigned ii = 0; ii < aList.size(); ii++ ) { - DrawList = aList[ii].m_RootCmp; - - if( DrawList == NULL ) - continue; - if( DrawList->Type() != TYPE_SCH_COMPONENT ) + EDA_BaseStruct* item = aList[ii].m_RootCmp; + if( item == NULL ) continue; - DrawLibItem = (SCH_COMPONENT*) DrawList; + if( item->Type() != TYPE_SCH_COMPONENT ) + continue; + + SCH_COMPONENT* comp = (SCH_COMPONENT*) item; bool isMulti = false; - wxString subRef; - Entry = CMP_LIBRARY::FindLibraryComponent( DrawLibItem->m_ChipName ); - if( Entry ) - isMulti = Entry->IsMulti(); + + LIB_COMPONENT* entry = CMP_LIBRARY::FindLibraryComponent( comp->m_ChipName ); + if( entry ) + isMulti = entry->IsMulti(); if( isMulti && aIncludeSubComponents ) subRef = LIB_COMPONENT::ReturnSubReference( aList[ii].m_Unit ); else subRef.Empty(); - sprintf( CmpName, "%s", aList[ii].m_Reference ); + CmpName = aList[ii].GetRefStr(); + if( !CompactForm ) - sprintf( CmpName + strlen( CmpName ), "%s", CONV_TO_UTF8(subRef) ); + CmpName += CONV_TO_UTF8(subRef); if( CompactForm ) #if defined(KICAD_GOST) - fprintf( f, "%s%c%s%c%s", CmpName, s_ExportSeparatorSymbol, - CONV_TO_UTF8( DrawLibItem->GetField( + fprintf( f, "%s%c%s%c%s", CmpName.c_str(), s_ExportSeparatorSymbol, + CONV_TO_UTF8( comp->GetField( VALUE )->m_Text ), s_ExportSeparatorSymbol, - CONV_TO_UTF8( DrawLibItem->GetField( DATASHEET )->m_Text ) ); + CONV_TO_UTF8( comp->GetField( DATASHEET )->m_Text ) ); #else - fprintf( f, "%s%c%s", CmpName, s_ExportSeparatorSymbol, - CONV_TO_UTF8( DrawLibItem->GetField( VALUE )->m_Text ) ); + fprintf( f, "%s%c%s", CmpName.c_str(), s_ExportSeparatorSymbol, + CONV_TO_UTF8( comp->GetField( VALUE )->m_Text ) ); #endif else #if defined(KICAD_GOST) - fprintf( f, "| %-10s %-12s %-20s", CmpName, - CONV_TO_UTF8( DrawLibItem->GetField( VALUE )->m_Text ), - CONV_TO_UTF8( DrawLibItem->GetField( DATASHEET )->m_Text ) ); + fprintf( f, "| %-10s %-12s %-20s", CmpName.c_str(), + CONV_TO_UTF8( comp->GetField( VALUE )->m_Text ), + CONV_TO_UTF8( comp->GetField( DATASHEET )->m_Text ) ); #else - fprintf( f, "| %-10s %-12s", CmpName, - CONV_TO_UTF8( DrawLibItem->GetField( VALUE )->m_Text ) ); + fprintf( f, "| %-10s %-12s", CmpName.c_str(), + CONV_TO_UTF8( comp->GetField( VALUE )->m_Text ) ); #endif + if( aIncludeSubComponents ) { msg = aList[ii].m_SheetPath.PathHumanReadable(); + if( CompactForm ) { fprintf( f, "%c%s", s_ExportSeparatorSymbol, CONV_TO_UTF8( msg ) ); + msg = m_Parent->GetXYSheetReferences( - (BASE_SCREEN*) DrawLibItem->GetParent(), - DrawLibItem->m_Pos ); + (BASE_SCREEN*) comp->GetParent(), + comp->m_Pos ); + fprintf( f, "%c%s)", s_ExportSeparatorSymbol, CONV_TO_UTF8( msg ) ); } else { fprintf( f, " (Sheet %s)", CONV_TO_UTF8( msg ) ); + msg = m_Parent->GetXYSheetReferences( - (BASE_SCREEN*) DrawLibItem->GetParent(), - DrawLibItem->m_Pos ); + (BASE_SCREEN*) comp->GetParent(), + comp->m_Pos ); + fprintf( f, " (loc %s)", CONV_TO_UTF8( msg ) ); } } - PrintFieldData( f, DrawLibItem, CompactForm ); + PrintFieldData( f, comp, CompactForm ); fprintf( f, "\n" ); } @@ -771,18 +800,20 @@ int DIALOG_BUILD_BOM::PrintComponentsListByPart( bool aIncludeSubComponents) { int qty = 0; - wxString RefName; + wxString refName; wxString fullRefName; // reference + part Id (for multiple parts per package - wxString ValName; - wxString RNames; + wxString valName; + wxString refNames; wxString lastRef; wxString unitId; - SCH_COMPONENT* currCmp, *nextCmp; - SCH_COMPONENT dummyCmp; // A dummy component, to store fields + SCH_COMPONENT* currCmp; + SCH_COMPONENT* nextCmp; + SCH_COMPONENT dummyCmp; // A dummy component, to store fields for( unsigned ii = 0; ii < aList.size(); ii++ ) { currCmp = (SCH_COMPONENT*) aList[ii].m_RootCmp; + if( ii < aList.size() -1 ) nextCmp = aList[ii+1].m_RootCmp; else @@ -791,48 +822,53 @@ int DIALOG_BUILD_BOM::PrintComponentsListByPart( // Store fields. Store non empty fields only. for( int jj = FOOTPRINT; jj < currCmp->GetFieldCount(); jj++ ) { - //Ensure fields exists in dummy component + // Ensure fields exists in dummy component if( dummyCmp.GetFieldCount() <= jj ) dummyCmp.AddField( *currCmp->GetField( jj ) ); + // store useful data if( !currCmp->GetField( jj )->m_Text.IsEmpty() ) dummyCmp.GetField( jj )->m_Text = currCmp->GetField( jj )->m_Text; } - RefName = CONV_FROM_UTF8( aList[ii].m_Reference ); - ValName = currCmp->GetField( VALUE )->m_Text; + refName = aList[ii].GetRef(); + valName = currCmp->GetField( VALUE )->m_Text; int multi = 0; if( aIncludeSubComponents ) { - LIB_COMPONENT* Entry = CMP_LIBRARY::FindLibraryComponent( currCmp->m_ChipName ); - if( Entry ) - multi = Entry->GetPartCount(); + LIB_COMPONENT* entry = CMP_LIBRARY::FindLibraryComponent( currCmp->m_ChipName ); + if( entry ) + multi = entry->GetPartCount(); if ( multi <= 1 ) multi = 0; } if ( multi && aList[ii].m_Unit > 0 ) - unitId.Printf(wxT("%c"), 'A' -1 + aList[ii].m_Unit); - else unitId.Empty(); - fullRefName = RefName + unitId; - - if( RNames.IsEmpty() ) - RNames = fullRefName; + unitId.Printf( wxT("%c"), 'A' -1 + aList[ii].m_Unit ); else - RNames << wxT( ", " ) << fullRefName; + unitId.Empty(); + + fullRefName = refName + unitId; + + if( refNames.IsEmpty() ) + refNames = fullRefName; + else + refNames << wxT( ", " ) << fullRefName; + // In multi parts per package, we have the reference more than once // but we must count only one package - if( lastRef != RefName ) + if( lastRef != refName ) qty++; - lastRef = RefName; + + lastRef = refName; // if the next cmoponent has same value the line will be printed after. - if( nextCmp && nextCmp->GetField( VALUE )->m_Text.CmpNoCase( ValName ) == 0 ) + if( nextCmp && nextCmp->GetField( VALUE )->m_Text.CmpNoCase( valName ) == 0 ) continue; // Print line for the current component value: - fprintf( f, "%15s%c%3d", CONV_TO_UTF8( ValName ), s_ExportSeparatorSymbol, qty ); + fprintf( f, "%15s%c%3d", CONV_TO_UTF8( valName ), s_ExportSeparatorSymbol, qty ); if( IsFieldChecked(FOOTPRINT ) ) fprintf( f, "%c%15s", s_ExportSeparatorSymbol, @@ -840,17 +876,20 @@ int DIALOG_BUILD_BOM::PrintComponentsListByPart( #if defined(KICAD_GOST) fprintf( f, "%c%20s", s_ExportSeparatorSymbol, - CONV_TO_UTF8( currCmp->GetField( DATASHEET) ->m_Text ) ); + CONV_TO_UTF8( currCmp->GetField( DATASHEET )->m_Text ) ); #endif - fprintf( f, "%c%s", s_ExportSeparatorSymbol, - CONV_TO_UTF8( RNames ) ); + // wrap the field in quotes, since it has commas in it. + fprintf( f, "%c\"%s\"", s_ExportSeparatorSymbol, + CONV_TO_UTF8( refNames ) ); // print fields, on demand int last_nonempty_field_idx = 0; + for( int jj = FOOTPRINT; jj < dummyCmp.GetFieldCount(); jj++ ) if ( !dummyCmp.GetField( jj )->m_Text.IsEmpty() ) last_nonempty_field_idx = jj; + for( int jj = FIELD1; jj <= last_nonempty_field_idx ; jj++ ) { if ( IsFieldChecked( jj ) ) @@ -862,7 +901,8 @@ int DIALOG_BUILD_BOM::PrintComponentsListByPart( // Clear strings and values, to prepare next component qty = 0; - RNames.Empty(); + refNames.Empty(); + for( int jj = FOOTPRINT; jj < dummyCmp.GetFieldCount(); jj++ ) dummyCmp.GetField( jj )->m_Text.Empty(); } @@ -876,10 +916,10 @@ int DIALOG_BUILD_BOM::PrintComponentsListByVal( std::vector & aList, bool aIncludeSubComponents ) { - EDA_BaseStruct* DrawList; + EDA_BaseStruct* schItem; SCH_COMPONENT* DrawLibItem; - LIB_COMPONENT* Entry; - char CmpName[80]; + LIB_COMPONENT* entry; + std::string CmpName; wxString msg; msg = _( "\n#Cmp ( order = Value )" ); @@ -887,24 +927,25 @@ int DIALOG_BUILD_BOM::PrintComponentsListByVal( if( aIncludeSubComponents ) msg << _( " (with SubCmp)" ); msg << wxT( "\n" ); + fputs( CONV_TO_UTF8( msg ), f ); for( unsigned ii = 0; ii < aList.size(); ii++ ) { - DrawList = aList[ii].m_RootCmp; + schItem = aList[ii].m_RootCmp; - if( DrawList == NULL ) + if( schItem == NULL ) continue; - if( DrawList->Type() != TYPE_SCH_COMPONENT ) + if( schItem->Type() != TYPE_SCH_COMPONENT ) continue; - DrawLibItem = (SCH_COMPONENT*) DrawList; + DrawLibItem = (SCH_COMPONENT*) schItem; bool isMulti = false; - Entry = CMP_LIBRARY::FindLibraryComponent( DrawLibItem->m_ChipName ); - if( Entry ) - isMulti = Entry->IsMulti(); + entry = CMP_LIBRARY::FindLibraryComponent( DrawLibItem->m_ChipName ); + if( entry ) + isMulti = entry->IsMulti(); wxString subRef; if( isMulti && aIncludeSubComponents ) @@ -912,11 +953,12 @@ int DIALOG_BUILD_BOM::PrintComponentsListByVal( else subRef.Empty(); - sprintf( CmpName, "%s%s", aList[ii].m_Reference, CONV_TO_UTF8(subRef) ); + CmpName = aList[ii].GetRefStr(); + CmpName += CONV_TO_UTF8(subRef); fprintf( f, "| %-12s %-10s", CONV_TO_UTF8( DrawLibItem->GetField( VALUE )->m_Text ), - CmpName ); + CmpName.c_str() ); // print the sheet path if( aIncludeSubComponents ) @@ -962,9 +1004,9 @@ static int PrintListeGLabel( FILE* f, std::vector & aList ) sheetpath = aList[ii].m_SheetPath.PathHumanReadable(); msg.Printf( _( "> %-28.28s %s (Sheet %s) pos: %3.3f, %3.3f\n" ), - DrawTextItem->m_Text.GetData(), - labeltype.GetData(), - sheetpath.GetData(), + GetChars( DrawTextItem->m_Text ), + GetChars( labeltype ), + GetChars( sheetpath ), (float) DrawTextItem->m_Pos.x / 1000, (float) DrawTextItem->m_Pos.y / 1000 ); @@ -975,18 +1017,23 @@ static int PrintListeGLabel( FILE* f, std::vector & aList ) { DrawSheetLabel = (SCH_SHEET_PIN*) aList[ii].m_Label; int jj = DrawSheetLabel->m_Shape; + if( jj < 0 ) jj = NET_TMAX; + if( jj > NET_TMAX ) jj = 4; + wxString labtype = CONV_FROM_UTF8( SheetLabelType[jj] ); + msg.Printf( _( "> %-28.28s PinSheet %-7.7s (Sheet %s) pos: %3.3f, %3.3f\n" ), - DrawSheetLabel->m_Text.GetData(), - labtype.GetData(), - aList[ii].m_SheetPath.PathHumanReadable().GetData(), + GetChars( DrawSheetLabel->m_Text ), + GetChars( labtype ), + GetChars( aList[ii].m_SheetPath.PathHumanReadable()), (float) DrawSheetLabel->m_Pos.x / 1000, (float) DrawSheetLabel->m_Pos.y / 1000 ); + fputs( CONV_TO_UTF8( msg ), f ); } break; @@ -1008,35 +1055,27 @@ static int PrintListeGLabel( FILE* f, std::vector & aList ) * return 0 if the strings are equal * return 1 if the first string is greater than the second */ -int RefDesStringCompare( const char* obj1, const char* obj2 ) +int RefDesStringCompare( const wxString& strFWord, const wxString& strSWord ) { - /* The strings we are going to compare */ - wxString strFWord; - wxString strSWord; - - /* The different sections of the first string */ + // The different sections of the first string wxString strFWordBeg, strFWordMid, strFWordEnd; - /* The different sections of the second string */ + // The different sections of the second string wxString strSWordBeg, strSWordMid, strSWordEnd; - int isEqual = 0; /* The numerical results of a string compare */ - int iReturn = 0; /* The variable that is being returned */ + int isEqual = 0; // The numerical results of a string compare + int iReturn = 0; // The variable that is being returned long lFirstDigit = 0; /* The converted middle section of the first *string */ long lSecondDigit = 0; /* The converted middle section of the second *string */ - /* Since m_Ref is a char * it is ASCII */ - strFWord = wxString::FromAscii( obj1 ); - strSWord = wxString::FromAscii( obj2 ); - - /* Split the two string into separate parts */ + // Split the two string into separate parts SplitString( strFWord, &strFWordBeg, &strFWordMid, &strFWordEnd ); SplitString( strSWord, &strSWordBeg, &strSWordMid, &strSWordEnd ); - /* Compare the Beginning section of the strings */ + // Compare the Beginning section of the strings isEqual = strFWordBeg.CmpNoCase( strSWordBeg ); if( isEqual > 0 ) iReturn = 1; @@ -1044,17 +1083,19 @@ int RefDesStringCompare( const char* obj1, const char* obj2 ) iReturn = -1; else { - /* If the first sections are equal compare there digits */ + // If the first sections are equal compare there digits strFWordMid.ToLong( &lFirstDigit ); strSWordMid.ToLong( &lSecondDigit ); + if( lFirstDigit > lSecondDigit ) iReturn = 1; else if( lFirstDigit < lSecondDigit ) iReturn = -1; else { - /* If the first two sections are equal compare the endings */ + // If the first two sections are equal compare the endings isEqual = strFWordEnd.CmpNoCase( strSWordEnd ); + if( isEqual > 0 ) iReturn = 1; else if( isEqual < 0 ) @@ -1079,16 +1120,16 @@ int SplitString( wxString strToSplit, wxString* strDigits, wxString* strEnd ) { - /* Clear all the return strings */ + // Clear all the return strings strBeginning->Clear(); strDigits->Clear(); strEnd->Clear(); - /* There no need to do anything if the string is empty */ + // There no need to do anything if the string is empty if( strToSplit.length() == 0 ) return 0; - /* Starting at the end of the string look for the first digit */ + // Starting at the end of the string look for the first digit int ii; for( ii = (strToSplit.length() - 1); ii >= 0; ii-- ) { @@ -1096,15 +1137,15 @@ int SplitString( wxString strToSplit, break; } - /* If there were no digits then just set the single string */ + // If there were no digits then just set the single string if( ii < 0 ) *strBeginning = strToSplit; else { - /* Since there is at least one digit this is the trailing string */ + // Since there is at least one digit this is the trailing string *strEnd = strToSplit.substr( ii + 1 ); - /* Go to the end of the digits */ + // Go to the end of the digits int position = ii + 1; for( ; ii >= 0; ii-- ) { @@ -1112,7 +1153,7 @@ int SplitString( wxString strToSplit, break; } - /* If all that was left was digits, then just set the digits string */ + // If all that was left was digits, then just set the digits string if( ii < 0 ) *strDigits = strToSplit.substr( 0, position ); diff --git a/eeschema/class_drawsheetpath.cpp b/eeschema/class_drawsheetpath.cpp index 8c06b6283f..5d44ded807 100644 --- a/eeschema/class_drawsheetpath.cpp +++ b/eeschema/class_drawsheetpath.cpp @@ -477,12 +477,6 @@ SCH_SHEET_PATH* SCH_SHEET_LIST::GetSheet( int aIndex ) } -/** Function BuildSheetList - * Build the list of sheets and their sheet path from the aSheet sheet - * if aSheet = g_RootSheet, the full sheet path list (and full sheet list) is - * built - * @param aSheet = the starting sheet to build list - */ void SCH_SHEET_LIST::BuildSheetList( SCH_SHEET* aSheet ) { if( m_List == NULL ) diff --git a/eeschema/class_drawsheetpath.h b/eeschema/class_drawsheetpath.h index 5cb7d2a4f4..b7582d2434 100644 --- a/eeschema/class_drawsheetpath.h +++ b/eeschema/class_drawsheetpath.h @@ -53,18 +53,15 @@ class SCH_MARKER; -/****************************************/ -/* class to handle and access to a sheet */ -/* a 'path' so to speak.. */ -/****************************************/ - -/* +/** + * Class SCH_SHEET_PATH + * handles access to a sheet by way of a path. + *

* The member m_sheets stores the list of sheets from the first (usually - * g_RootSheet) - * to a given sheet in last position. - * The last sheet is usually the sheet we want to select or reach. So Last() - * return this last sheet - * Others sheets are the "path" from the first to the last sheet + * g_RootSheet) to a given sheet in last position. + * The _last_ sheet is usually the sheet we want to select or reach (which is + * what the function Last() returns). + * Others sheets constitute the "path" from the first to the last sheet. */ class SCH_SHEET_PATH { @@ -77,7 +74,7 @@ public: public: SCH_SHEET_PATH(); - ~SCH_SHEET_PATH() { }; + // ~SCH_SHEET_PATH() { }; void Clear() { @@ -137,7 +134,7 @@ public: * Pop is used when leaving a sheet after a selection or analyze * This is like cd .. in directories navigation */ - SCH_SHEET* Pop(); + SCH_SHEET* Pop(); /** Function Path * the path uses the time stamps which do not changes even when editing @@ -215,15 +212,14 @@ public: }; -/*******************************************************/ -/* Class to handle the list of *Sheets* in a hierarchy */ -/*******************************************************/ - -/* sheets are not unique - can have many sheets with the same +/** + * Class SCH_SHEET_LIST + * handles the list of Sheets in a hiearchy. + * Sheets are not unique, there can be many sheets with the same * filename and the same SCH_SCREEN reference. - * the schematic (SCH_SCREEN) is shared between these sheets, + * The schematic (SCH_SCREEN) is shared between these sheets, * and component references are specific to a sheet path. - * When a sheet is entered, component references and sheet number are updated + * When a sheet is entered, component references and sheet number are updated. */ class SCH_SHEET_LIST { @@ -243,9 +239,12 @@ private: SCH_SHEET_PATH m_currList; public: - /* The constructor: build the list of sheets from aSheet. - * If aSheet == NULL (default) build the whole list of sheets in hierarchy - * So usually call it with no param. + + /** + * Constructor + * builds the list of sheets from aSheet. + * If aSheet == NULL (default) build the whole list of sheets in hierarchy. + * So usually call it with no parameter. */ SCH_SHEET_LIST( SCH_SHEET* aSheet = NULL ); @@ -256,48 +255,54 @@ public: m_List = NULL; } - - /** Function GetCount() + /** + * Function GetCount() * @return the number of sheets in list: * usually the number of sheets found in the whole hierarchy */ int GetCount() { return m_count; } - /** Function GetFirst - * @return the first item (sheet) in m_List and prepare calls to GetNext() + /** + * Function GetFirst + * @return the first item (sheet) in m_List and prepare calls to GetNext() */ SCH_SHEET_PATH* GetFirst(); - /** Function GetNext - * @return the next item (sheet) in m_List or NULL if no more item in + /** + * Function GetNext + * @return the next item (sheet) in m_List or NULL if no more item in * sheet list */ SCH_SHEET_PATH* GetNext(); /** - * Get the last sheet in the sheet list. + * Function GetLast + * returns the last sheet in the sheet list. * * @return Last sheet in the list or NULL if sheet list is empty. */ SCH_SHEET_PATH* GetLast(); /** - * Get the previous sheet in the sheet list. + * Function GetPrevious + * returns the previous sheet in the sheet list. * * @return The previous sheet in the sheet list or NULL if already at the * beginning of the list. */ SCH_SHEET_PATH* GetPrevious(); - /** Function GetSheet - * @return the item (sheet) in aIndex position in m_List or NULL if less + /** + * Function GetSheet + * @return the item (sheet) in aIndex position in m_List or NULL if less * than index items * @param aIndex = index in sheet list to get the sheet */ SCH_SHEET_PATH* GetSheet( int aIndex ); /** - * Search the entire schematic for the next schematic object. + * Function FindNextItem + * searches the entire schematic for the next schematic object. * * @param aType - The type of schematic item to find. * @param aSheetFound - The sheet the item was found in. NULL if the next item @@ -310,7 +315,8 @@ public: SCH_ITEM* aLastItem = NULL, bool aWrap = true ); /** - * Search the entire schematic for the previous schematic item. + * Function FindPreviousItem + * searches the entire schematic for the previous schematic item. * * @param aType - The type of schematic item to find. * @param aSheetFound - The sheet the item was found in. NULL if the previous item @@ -323,7 +329,8 @@ public: SCH_ITEM* aLastItem = NULL, bool aWrap = true ); /** - * Search the entire schematic for the next item that matches the search criteria. + * Function MatchNextItem + * searches the entire schematic for the next item that matches the search criteria. * * @param aSearchData - Criteria to search item against. * @param aSheetFound - The sheet the item was found in. NULL if the next item @@ -337,12 +344,15 @@ public: private: - /** Function BuildSheetList - * Build the list of sheets and their sheet path from the aSheet sheet - * if aSheet = g_RootSheet, the full sheet path and sheet list is built - * @param aSheet = the starting sheet from the built is made + /** + * Function BuildSheetList + * builds the list of sheets and their sheet path from \a aSheet. + * If aSheet = g_RootSheet, the full sheet path and sheet list is built + * + * @param aSheet is the starting sheet from which the list is built, + * or NULL indicating that g_RootSheet should be used. */ void BuildSheetList( SCH_SHEET* sheet ); }; -#endif /* CLASS_DRAWSHEET_PATH_H */ +#endif // CLASS_DRAWSHEET_PATH_H diff --git a/eeschema/class_sch_cmp_field.cpp b/eeschema/class_sch_cmp_field.cpp index 889d2e7f66..89883be890 100644 --- a/eeschema/class_sch_cmp_field.cpp +++ b/eeschema/class_sch_cmp_field.cpp @@ -216,18 +216,6 @@ void SCH_FIELD::SwapData( SCH_FIELD* copyitem ) } -/** - * return True if the field is void, i.e.: - * contains "~" or "" - */ -bool SCH_FIELD::IsVoid() -{ - if( m_Text.IsEmpty() || m_Text == wxT( "~" ) ) - return true; - return false; -} - - /** * Function GetBoundaryBox() * @return an EDA_Rect contains the real (user coordinates) boundary box for diff --git a/eeschema/class_sch_cmp_field.h b/eeschema/class_sch_cmp_field.h index 48935d8766..870ae61b6a 100644 --- a/eeschema/class_sch_cmp_field.h +++ b/eeschema/class_sch_cmp_field.h @@ -47,11 +47,20 @@ public: return wxT( "SCH_FIELD" ); } - void Place( WinEDA_SchematicFrame* frame, wxDC* DC ); EDA_Rect GetBoundaryBox() const; - bool IsVoid(); + + /** + * Function IsVoid + * returns true if the field is either empty or holds "~". + */ + bool IsVoid() + { + size_t len = m_Text.Len(); + return len == 0 || ( len == 1 && m_Text[0] == wxChar( '~' ) ); + } + void SwapData( SCH_FIELD* copyitem ); /** Function ImportValues diff --git a/eeschema/class_sch_component.h b/eeschema/class_sch_component.h index b2b630ebe1..e3ee560a87 100644 --- a/eeschema/class_sch_component.h +++ b/eeschema/class_sch_component.h @@ -78,7 +78,7 @@ private: * multi = part selection in multi parts per package (0 or 1 for one part * per package) */ - wxArrayString m_PathsAndReferences; + wxArrayString m_PathsAndReferences; void Init( const wxPoint& pos = wxPoint( 0, 0 ) ); diff --git a/eeschema/dialog_build_BOM.h b/eeschema/dialog_build_BOM.h index b16f389703..68a21d9100 100644 --- a/eeschema/dialog_build_BOM.h +++ b/eeschema/dialog_build_BOM.h @@ -9,12 +9,13 @@ #include "dialog_build_BOM_base.h" + class DIALOG_BUILD_BOM : public DIALOG_BUILD_BOM_BASE { private: - WinEDA_DrawFrame * m_Parent; - wxConfig* m_Config; - wxString m_ListFileName; + WinEDA_DrawFrame * m_Parent; + wxConfig* m_Config; + wxString m_ListFileName; private: void OnRadioboxSelectFormatSelected( wxCommandEvent& event ); @@ -22,30 +23,41 @@ private: void OnCancelClick( wxCommandEvent& event ); void SavePreferences(); - void Init( ); + void Init(); void Create_BOM_Lists(int aTypeFile, bool aIncludeSubComponents, char aExportSeparatorSymbol, bool aRunBrowser); + void GenereListeOfItems(const wxString & FullFileName, bool aIncludeSubComponents ); void CreateExportList(const wxString & FullFileName, bool aIncludeSubComponents); - void CreatePartsList(const wxString & FullFileName, bool aIncludeSubComponents); + + /** + * Function CreateParstList + * prints a list of components, in a form which can be imported by a + * spreadsheet. Form is: + * cmp value; number of components; ; ; ...; + * list of references having the same value + */ + void CreatePartsList( const wxString& aFullFileName, bool aIncludeSubComponents ); + int PrintComponentsListByRef( FILE * f, std::vector & aList, bool CompactForm, bool aIncludeSubComponents ); + int PrintComponentsListByVal( FILE *f, std::vector & aList, bool aIncludeSubComponents); + int PrintComponentsListByPart( FILE *f, std::vector & aList, bool aIncludeSubComponents); - void PrintFieldData(FILE * f, SCH_COMPONENT * DrawLibItem, bool CompactForm = FALSE); - bool IsFieldChecked(int aFieldId); + void PrintFieldData(FILE * f, SCH_COMPONENT * DrawLibItem, bool CompactForm = FALSE); + + bool IsFieldChecked(int aFieldId); public: DIALOG_BUILD_BOM( WinEDA_DrawFrame* parent ); - ~DIALOG_BUILD_BOM() {}; - + // ~DIALOG_BUILD_BOM() {}; }; +#endif // _DIALOG_BUILD_BOM_H_ -#endif - // _DIALOG_BUILD_BOM_H_ diff --git a/eeschema/netform.cpp b/eeschema/netform.cpp index 38e6008b72..043451521c 100644 --- a/eeschema/netform.cpp +++ b/eeschema/netform.cpp @@ -3,6 +3,9 @@ /*****************************/ #include "fctsys.h" + +#include + #include "gr_basic.h" #include "common.h" #include "confirm.h" @@ -25,37 +28,77 @@ * returns a value less than 0 when it does. */ -static void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, - const wxString& FullFileName ); -static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, +static bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName ); + +static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew ); + static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ); static void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ); + static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_netnames ); -static void WriteGENERICListOfNets( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ); +static bool WriteGENERICListOfNets( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ); + static void AddPinToComponentPinList( SCH_COMPONENT* Component, SCH_SHEET_PATH* sheet, LIB_PIN* PinEntry ); + static void FindAllsInstancesOfComponent( SCH_COMPONENT* Component, - LIB_COMPONENT* Entry, + LIB_COMPONENT* aEntry, SCH_SHEET_PATH* Sheet_in ); + static bool SortPinsByNum( NETLIST_OBJECT* Pin1, NETLIST_OBJECT* Pin2 ); static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList ); -static void ClearUsedFlags( void ); - static NETLIST_OBJECT_LIST s_SortedComponentPinList; -// list of references already found for multi part per packages components -// (used to avoid to used more than one time a component) -static wxArrayString s_ReferencesAlreadyFound; + +#include + +/** + * Class UNIQUE_STRINGS + * will keep track of unique wxStrings and is useful in telling if a string + * has been seen before. + */ +class UNIQUE_STRINGS +{ +private: + std::set m_set; ///< set of wxStrings already found + +public: + /** + * Function Clear + * erases the record. + */ + void Clear() { m_set.clear(); } + + /** + * Function Lookup + * returns true if \a aString already exists in the set, otherwise returns + * false and adds \a aString to the set for next time. + */ + bool Lookup( const wxString& aString ); +}; + +bool UNIQUE_STRINGS::Lookup( const wxString& aString ) +{ + bool ret = ( m_set.find( aString ) != m_set.end() ); + if( !ret ) + m_set.insert( aString ); + + return ret; +} + +/// Used for multi part per package components, avoids using a component more than once. +static UNIQUE_STRINGS s_ReferencesAlreadyFound; -/** function WriteNetListFile - * Create the netlist file. Netlist info must be existing +/** + * Function WriteNetListFile + * creates the netlist file. Netlist info must be existing * @param aFormat = netlist format (NET_TYPE_PCBNEW ...) * @param aFullFileName = full netlist file name * @param aUse_netnames = bool. if true, use net names from labels in schematic @@ -66,7 +109,8 @@ static wxArrayString s_ReferencesAlreadyFound; bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFullFileName, bool aUse_netnames ) { - FILE* f = NULL; + bool ret = true; + FILE* f = NULL; if( aFormat < NET_TYPE_CUSTOM1 ) { @@ -83,12 +127,12 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull switch( aFormat ) { case NET_TYPE_PCBNEW: - WriteNetListPCBNEW( this, f, TRUE ); + ret = WriteNetListPCBNEW( this, f, TRUE ); fclose( f ); break; case NET_TYPE_ORCADPCB2: - WriteNetListPCBNEW( this, f, FALSE ); + ret = WriteNetListPCBNEW( this, f, FALSE ); fclose( f ); break; @@ -103,11 +147,39 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull break; default: - Write_GENERIC_NetList( this, aFullFileName ); + { + wxFileName tmpFile = aFullFileName; + tmpFile.SetExt( wxT( "tmp" ) ); + + ret = Write_GENERIC_NetList( this, tmpFile.GetFullPath() ); + if( !ret ) + break; + + // Call the external module (plug in ) + if( g_NetListerCommandLine.IsEmpty() ) + break; + + wxString commandLine; + + if( wxIsAbsolutePath( g_NetListerCommandLine ) ) + commandLine = g_NetListerCommandLine; + else + commandLine = FindKicadFile( g_NetListerCommandLine ); + + // this is the input file to the plugin + commandLine += wxT( " " ) + tmpFile.GetFullPath(); + + // this is the output file to the plugin + commandLine += wxT( " " ) + aFullFileName; + + ProcessExecute( commandLine, wxEXEC_SYNC ); + + // ::wxRemoveFile( tmpFile.GetFullPath() ); + } break; } - return true; + return ret; } @@ -118,87 +190,70 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull * considered) * Must be deallocated by the user */ -static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* DrawList, - SCH_SHEET_PATH* sheet ) +static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item, + SCH_SHEET_PATH* path ) { - SCH_COMPONENT* Component = NULL; - LIB_COMPONENT* Entry; - LIB_PIN* Pin; - s_SortedComponentPinList.clear(); - for( ; DrawList != NULL; DrawList = DrawList->Next() ) + + // continue searching from the middle of a linked list + for( ; item; item = item->Next() ) { - if( DrawList->Type() != TYPE_SCH_COMPONENT ) - continue; - Component = (SCH_COMPONENT*) DrawList; - - /* Power symbol and other component which have the reference starting - * by "#" are not included in netlist (pseudo or virtual components) */ - wxString str = Component->GetRef( sheet ); - if( str[0] == '#' ) // ignore it + if( item->Type() != TYPE_SCH_COMPONENT ) continue; - //if( Component->m_FlagControlMulti == 1 ) + // found next component + SCH_COMPONENT* comp = (SCH_COMPONENT*) item; + + // Power symbols and other components which have the reference starting + // with "#" are not included in netlist (pseudo or virtual components) + wxString ref = comp->GetRef( path ); + if( ref[0] == wxChar( '#' ) ) // ignore it + continue; + + // if( Component->m_FlagControlMulti == 1 ) // continue; /* yes */ // removed because with multiple instances of one schematic // (several sheets pointing to 1 screen), this will be erroneously be // toggled. - Entry = CMP_LIBRARY::FindLibraryComponent( Component->m_ChipName ); - - if( Entry == NULL ) + LIB_COMPONENT* entry = CMP_LIBRARY::FindLibraryComponent( comp->m_ChipName ); + if( !entry ) continue; // Multi parts per package: test if already visited: - if( Entry->GetPartCount() > 1 ) + if( entry->GetPartCount() > 1 ) { - bool found = false; - for( unsigned jj = 0; - jj < s_ReferencesAlreadyFound.GetCount(); - jj++ ) - { - if( str == s_ReferencesAlreadyFound[jj] ) // Already visited - { - found = true; - break; - } - } - - if( found ) + if( s_ReferencesAlreadyFound.Lookup( ref ) ) continue; - else - { - s_ReferencesAlreadyFound.Add( str ); // Mark as visited - } } - if( Entry->GetPartCount() <= 1 ) // One part per package + if( entry->GetPartCount() <= 1 ) // One part per package { LIB_PIN_LIST pins; - Entry->GetPins( pins, Component->GetUnitSelection( sheet ), Component->m_Convert ); + entry->GetPins( pins, comp->GetUnitSelection( path ), comp->m_Convert ); for( size_t i = 0; i < pins.size(); i++ ) { - Pin = pins[i]; + LIB_PIN* pin = pins[i]; - wxASSERT( Pin->Type() == COMPONENT_PIN_DRAW_TYPE ); + wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE ); - AddPinToComponentPinList( Component, sheet, Pin ); + AddPinToComponentPinList( comp, path, pin ); } } - else // Multiple parts per package: Collect all parts ans pins for + else // Multiple parts per package: Collect all parts and pins for // this reference - FindAllsInstancesOfComponent( Component, Entry, sheet ); + FindAllsInstancesOfComponent( comp, entry, path ); - /* Sort Pins in s_SortedComponentPinList by pin number */ + // Sort pins in s_SortedComponentPinList by pin number sort( s_SortedComponentPinList.begin(), s_SortedComponentPinList.end(), SortPinsByNum ); - /* Remove duplicate Pins in s_SortedComponentPinList */ + // Remove duplicate Pins in s_SortedComponentPinList EraseDuplicatePins( s_SortedComponentPinList ); - return Component; + return comp; } return NULL; @@ -247,115 +302,205 @@ static wxString ReturnPinNetName( NETLIST_OBJECT* Pin, const wxString& DefaultFo } +static wxXmlNode* Node( const wxString& name, const wxString& content=wxEmptyString ) +{ + wxXmlNode* n = new wxXmlNode( 0, wxXML_ELEMENT_NODE, name ); + + if( content.Len() > 0 ) // excludes wxEmptyString + n->AddChild( new wxXmlNode( 0, wxXML_TEXT_NODE, wxEmptyString, content ) ); + + return n; +} + + /* Create a generic netlist, and call an external netlister * to change the netlist syntax and create the file */ -void Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& FullFileName ) +bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName ) { - wxString Line, FootprintName; - SCH_SHEET_PATH* sheet; - EDA_BaseStruct* SchItem; - SCH_COMPONENT* Component; - wxString netname; - FILE* tmpfile; - wxFileName fn = FullFileName; +#if 1 + // output the XML format netlist. + wxXmlDocument xdoc; + // tree markers or walkers + wxXmlNode* xroot; // root node + wxXmlNode* xcomps; // start of components - fn.SetExt( wxT( "tmp" ) ); + wxString timeStamp; - if( ( tmpfile = wxFopen( fn.GetFullPath(), wxT( "wt" ) ) ) == NULL ) + // some strings we need many times, but don't want to construct more + // than once for performance. These are used within loops so the + // enclosing wxString constructor would fire on each usage. + const wxString sFields = wxT("fields"); + const wxString sField = wxT("field"); + const wxString sComponent = wxT("comp"); // use "part" ? + const wxString sName = wxT("name"); + const wxString sRef = wxT("ref"); + const wxString sPins = wxT("pins"); + const wxString sPin = wxT("pin"); + const wxString sValue = wxT("value"); + const wxString sFootprint = wxT("footprint"); + const wxString sDatasheet = wxT("datasheet"); + const wxString sTStamp = wxT("tstamp"); + const wxString sTSFmt = wxT("%8.8lX"); // comp->m_TimeStamp + + s_ReferencesAlreadyFound.Clear(); + + xdoc.SetRoot( xroot = Node( wxT("netlist") ) ); + xroot->AddProperty( wxT("version"), wxT("B") ); + + xroot->AddChild( xcomps = Node( wxT("components") ) ); + + SCH_SHEET_LIST sheetList; + + // output is xml, so there is no reason to remove spaces from the field values. + + for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext() ) { - wxString msg = _( "Failed to create file " ) + fn.GetFullPath(); - DisplayError( frame, msg ); - return; - } - - ClearUsedFlags(); /* Reset the flags FlagControlMulti in all schematic - * files*/ - fprintf( tmpfile, "$BeginNetlist\n" ); - - /* Create netlist module section */ - fprintf( tmpfile, "$BeginComponentList\n" ); - SCH_SHEET_LIST SheetList; - - for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) - { - for( SchItem = sheet->LastDrawList(); SchItem != NULL; SchItem = SchItem->Next() ) + for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() ) { - SchItem = Component = FindNextComponentAndCreatPinList( SchItem, sheet ); - - if( Component == NULL ) + SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( schItem, path ); + if( !comp ) break; // No component left - FootprintName.Empty(); - if( !Component->GetField( FOOTPRINT )->IsVoid() ) + schItem = comp; + + // current component being constructed + wxXmlNode* xcomp = Node( sComponent ); + xcomps->AddChild( xcomp ); + xcomp->AddProperty( sRef, comp->GetRef( path ) ); + + xcomp->AddChild( Node( sValue, comp->GetField( VALUE )->m_Text ) ); + + timeStamp.Printf( sTSFmt, comp->m_TimeStamp ); + + xcomp->AddChild( Node( sTStamp, timeStamp ) ); + + if( !comp->GetField( FOOTPRINT )->m_Text.IsEmpty() ) + xcomp->AddChild( Node( sFootprint, comp->GetField( FOOTPRINT )->m_Text ) ); + + if( !comp->GetField( DATASHEET )->m_Text.IsEmpty() ) + xcomp->AddChild( Node( sDatasheet, comp->GetField( DATASHEET )->m_Text ) ); + + // all fields within the component, starting with the MANDATORY_FIELDS + if( comp->GetFieldCount() > MANDATORY_FIELDS ) { - FootprintName = Component->GetField( FOOTPRINT )->m_Text; - FootprintName.Replace( wxT( " " ), wxT( "_" ) ); + wxXmlNode* xfields = Node( sFields ); + xcomp->AddChild( xfields ); + + for( int fldNdx = MANDATORY_FIELDS; fldNdx < comp->GetFieldCount(); ++fldNdx ) + { + SCH_FIELD* f = comp->GetField( fldNdx ); + wxXmlNode* xfield = Node( sField, f->m_Text ); + + xfield->AddProperty( sName, f->m_Name ); + xfields->AddChild( xfield ); + } } - fprintf( tmpfile, "\n$BeginComponent\n" ); - fprintf( tmpfile, "TimeStamp=%8.8lX\n", Component->m_TimeStamp ); - fprintf( tmpfile, "Footprint=%s\n", CONV_TO_UTF8( FootprintName ) ); - Line = wxT( "Reference=" ) + Component->GetRef( sheet ) + wxT( "\n" ); - Line.Replace( wxT( " " ), wxT( "_" ) ); - fputs( CONV_TO_UTF8( Line ), tmpfile ); + // @todo add: libsource + sheetpath + } + } - Line = Component->GetField( VALUE )->m_Text; - Line.Replace( wxT( " " ), wxT( "_" ) ); - fprintf( tmpfile, "Value=%s\n", CONV_TO_UTF8( Line ) ); + // @todo generate the nested s + xroot->AddChild( Node( wxT("libparts") ) ); - Line = Component->m_ChipName; - Line.Replace( wxT( " " ), wxT( "_" ) ); - fprintf( tmpfile, "Libref=%s\n", CONV_TO_UTF8( Line ) ); + // @todo generate the nested s + xroot->AddChild( Node( wxT("nets") ) ); + + return xdoc.Save( aOutFileName, 2 /* indent bug, today was ignored by wxXml lib */ ); + +#else + + // ouput the well established/old net list format + wxString field; + wxString footprint; + wxString netname; + FILE* out; + int ret = 0; // OR on each call, test sign bit at very end. + + if( ( out = wxFopen( aOutFileName, wxT( "wt" ) ) ) == NULL ) + { + wxString msg = _( "Failed to create file " ) + aOutFileName; + DisplayError( frame, msg ); + return false; + } + + s_ReferencesAlreadyFound.Clear(); + + ret |= fprintf( out, "$BeginNetlist\n" ); + + // Create netlist module section + ret |= fprintf( out, "$BeginComponentList\n" ); + + SCH_SHEET_LIST sheetList; + + for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext() ) + { + for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() ) + { + SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( schItem, path ); + if( !comp ) + break; // No component left + + schItem = comp; + + footprint.Empty(); + if( !comp->GetField( FOOTPRINT )->IsVoid() ) + { + footprint = comp->GetField( FOOTPRINT )->m_Text; + footprint.Replace( wxT( " " ), wxT( "_" ) ); + } + + ret |= fprintf( out, "\n$BeginComponent\n" ); + ret |= fprintf( out, "TimeStamp=%8.8lX\n", comp->m_TimeStamp ); + ret |= fprintf( out, "Footprint=%s\n", CONV_TO_UTF8( footprint ) ); + + field = wxT( "Reference=" ) + comp->GetRef( path ) + wxT( "\n" ); + field.Replace( wxT( " " ), wxT( "_" ) ); + ret |= fputs( CONV_TO_UTF8( field ), out ); + + field = comp->GetField( VALUE )->m_Text; + field.Replace( wxT( " " ), wxT( "_" ) ); + ret |= fprintf( out, "Value=%s\n", CONV_TO_UTF8( field ) ); + + field = comp->m_ChipName; + field.Replace( wxT( " " ), wxT( "_" ) ); + ret |= fprintf( out, "Libref=%s\n", CONV_TO_UTF8( field ) ); // Write pin list: - fprintf( tmpfile, "$BeginPinList\n" ); + ret |= fprintf( out, "$BeginPinList\n" ); for( unsigned ii = 0; ii < s_SortedComponentPinList.size(); ii++ ) { NETLIST_OBJECT* Pin = s_SortedComponentPinList[ii]; if( !Pin ) continue; + netname = ReturnPinNetName( Pin, wxT( "$-%.6d" ) ); if( netname.IsEmpty() ) netname = wxT( "?" ); - fprintf( tmpfile, "%.4s=%s\n", (char*) &Pin->m_PinNum, CONV_TO_UTF8( netname ) ); + + ret |= fprintf( out, "%.4s=%s\n", (char*) &Pin->m_PinNum, CONV_TO_UTF8( netname ) ); } - fprintf( tmpfile, "$EndPinList\n" ); - fprintf( tmpfile, "$EndComponent\n" ); + ret |= fprintf( out, "$EndPinList\n" ); + ret |= fprintf( out, "$EndComponent\n" ); } } - fprintf( tmpfile, "$EndComponentList\n" ); + ret |= fprintf( out, "$EndComponentList\n" ); - fprintf( tmpfile, "\n$BeginNets\n" ); - WriteGENERICListOfNets( tmpfile, g_NetObjectslist ); - fprintf( tmpfile, "$EndNets\n" ); - fprintf( tmpfile, "\n$EndNetlist\n" ); - fclose( tmpfile ); + ret |= fprintf( out, "\n$BeginNets\n" ); - // Call the external module (plug in ) + if( !WriteGENERICListOfNets( out, g_NetObjectslist ) ) + ret = -1; - if( g_NetListerCommandLine.IsEmpty() ) - return; + ret |= fprintf( out, "$EndNets\n" ); - wxString CommandFile; - if( wxIsAbsolutePath( g_NetListerCommandLine ) ) - CommandFile = g_NetListerCommandLine; - else - CommandFile = FindKicadFile( g_NetListerCommandLine ); + ret |= fprintf( out, "\n$EndNetlist\n" ); + ret |= fclose( out ); - CommandFile += wxT( " " ) + fn.GetFullPath(); - CommandFile += wxT( " " ) + FullFileName; - - ProcessExecute( CommandFile, wxEXEC_SYNC ); -} - - -/* Clear flag list, used in netlist generation */ -static void ClearUsedFlags( void ) -{ - s_ReferencesAlreadyFound.Clear(); + return ret >= 0; +#endif } @@ -454,10 +599,10 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_ } fprintf( f, "\n" ); + // Create component list + + s_ReferencesAlreadyFound.Clear(); - /* Create component list */ - ClearUsedFlags(); /* Reset the flags FlagControlMulti in all schematic - * files*/ for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) { for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() ) @@ -522,159 +667,150 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_ * = FALSE if with_pcbnew * Format ORCADPCB2 strict */ -static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew ) +static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew ) { - wxString Line, FootprintName; - char Buf[256]; - SCH_SHEET_PATH* sheet; - EDA_BaseStruct* DrawList; - SCH_COMPONENT* Component; - OBJ_CMP_TO_LIST* CmpList = NULL; - int CmpListCount = 0, CmpListSize = 1000; + wxString Line; + wxString footprint; + char dateBuf[256]; + int ret = 0; // zero now, OR in the sign bit on error + + std::vector cmpList; + + DateAndTime( dateBuf ); - DateAndTime( Buf ); if( with_pcbnew ) - fprintf( f, "# %s created %s\n(\n", NETLIST_HEAD_STRING, Buf ); + ret |= fprintf( f, "# %s created %s\n(\n", NETLIST_HEAD_STRING, dateBuf ); else - fprintf( f, "( { %s created %s }\n", NETLIST_HEAD_STRING, Buf ); + ret |= fprintf( f, "( { %s created %s }\n", NETLIST_HEAD_STRING, dateBuf ); + // Create netlist module section - /* Create netlist module section */ - ClearUsedFlags(); /* Reset the flags FlagControlMulti in all schematic - * files*/ + s_ReferencesAlreadyFound.Clear(); - SCH_SHEET_LIST SheetList; + SCH_SHEET_LIST sheetList; - for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) + for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext() ) { - for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() ) + for( EDA_BaseStruct* item = path->LastDrawList(); item; item = item->Next() ) { - DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet ); - if( Component == NULL ) + SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( item, path ); + if( !comp ) break; - /* Get the Component FootprintFilter and put the component in - * CmpList if filter is not void */ - LIB_COMPONENT* Entry = - CMP_LIBRARY::FindLibraryComponent( Component->m_ChipName ); + item = comp; - if( Entry != NULL ) + // Get the Component FootprintFilter and put the component in + // cmpList if filter is present + LIB_COMPONENT* entry = + CMP_LIBRARY::FindLibraryComponent( comp->m_ChipName ); + + if( entry ) { - if( Entry->m_FootprintList.GetCount() != 0 ) /* Put in list */ + if( entry->m_FootprintList.GetCount() != 0 ) // Put in list { - if( CmpList == NULL ) - { - CmpList = (OBJ_CMP_TO_LIST*) - MyZMalloc( sizeof(OBJ_CMP_TO_LIST) * CmpListSize ); - } - if( CmpListCount >= CmpListSize ) - { - CmpListSize += 1000; - CmpList = - (OBJ_CMP_TO_LIST*) realloc( CmpList, - sizeof(OBJ_CMP_TO_LIST) - * CmpListSize ); - } - CmpList[CmpListCount].m_RootCmp = Component; - strcpy( CmpList[CmpListCount].m_Reference, - Component->GetRef( sheet ).mb_str() ); - CmpListCount++; + cmpList.push_back( OBJ_CMP_TO_LIST() ); + + cmpList.back().m_RootCmp = comp; + cmpList.back().SetRef( comp->GetRef( path ) ); } } - if( !Component->GetField( FOOTPRINT )->IsVoid() ) + if( !comp->GetField( FOOTPRINT )->IsVoid() ) { - FootprintName = Component->GetField( FOOTPRINT )->m_Text; - FootprintName.Replace( wxT( " " ), wxT( "_" ) ); + footprint = comp->GetField( FOOTPRINT )->m_Text; + footprint.Replace( wxT( " " ), wxT( "_" ) ); } else - FootprintName = wxT( "$noname" ); + footprint = wxT( "$noname" ); - Line = Component->GetRef( sheet ); - fprintf( f, " ( %s %s", - CONV_TO_UTF8( Component->GetPath( sheet ) ), - CONV_TO_UTF8( FootprintName ) ); - fprintf( f, " %s", CONV_TO_UTF8( Line ) ); + Line = comp->GetRef( path ); - Line = Component->GetField( VALUE )->m_Text; + ret |= fprintf( f, " ( %s %s", + CONV_TO_UTF8( comp->GetPath( path ) ), + CONV_TO_UTF8( footprint ) ); + + ret |= fprintf( f, " %s", CONV_TO_UTF8( Line ) ); + + Line = comp->GetField( VALUE )->m_Text; Line.Replace( wxT( " " ), wxT( "_" ) ); - fprintf( f, " %s", CONV_TO_UTF8( Line ) ); + ret |= fprintf( f, " %s", CONV_TO_UTF8( Line ) ); if( with_pcbnew ) // Add the lib name for this component { - Line = Component->m_ChipName; + Line = comp->m_ChipName; Line.Replace( wxT( " " ), wxT( "_" ) ); - fprintf( f, " {Lib=%s}", CONV_TO_UTF8( Line ) ); + ret |= fprintf( f, " {Lib=%s}", CONV_TO_UTF8( Line ) ); } - fprintf( f, "\n" ); + ret |= fprintf( f, "\n" ); // Write pin list: for( unsigned ii = 0; ii < s_SortedComponentPinList.size(); ii++ ) { - NETLIST_OBJECT* Pin = s_SortedComponentPinList[ii]; - if( !Pin ) + NETLIST_OBJECT* pin = s_SortedComponentPinList[ii]; + if( !pin ) continue; - wxString netname = ReturnPinNetName( Pin, wxT( "N-%.6d" ) ); + + wxString netname = ReturnPinNetName( pin, wxT( "N-%.6d" ) ); if( netname.IsEmpty() ) netname = wxT( "?" ); + netname.Replace( wxT( " " ), wxT( "_" ) ); - fprintf( f, " ( %4.4s %s )\n", (char*) &Pin->m_PinNum, + ret |= fprintf( f, " ( %4.4s %s )\n", (char*) &pin->m_PinNum, CONV_TO_UTF8( netname ) ); } - fprintf( f, " )\n" ); + ret |= fprintf( f, " )\n" ); } } - fprintf( f, ")\n*\n" ); + ret |= fprintf( f, ")\n*\n" ); s_SortedComponentPinList.clear(); - /* Write the allowed footprint list for each component */ - if( with_pcbnew && CmpList ) + // Write the allowed footprint list for each component + if( with_pcbnew && cmpList.size() ) { - fprintf( f, "{ Allowed footprints by component:\n" ); - LIB_COMPONENT* Entry; - for( int ii = 0; ii < CmpListCount; ii++ ) + wxString ref; + + ret |= fprintf( f, "{ Allowed footprints by component:\n" ); + for( unsigned ii = 0; ii < cmpList.size(); ii++ ) { - Component = CmpList[ii].m_RootCmp; - Entry = CMP_LIBRARY::FindLibraryComponent( Component->m_ChipName ); + SCH_COMPONENT* comp = cmpList[ii].m_RootCmp; - //Line.Printf(_("%s"), CmpList[ii].m_Ref); - //Line.Replace( wxT( " " ), wxT( "_" ) ); - for( unsigned nn = 0; - nnm_ChipName ); + + ref = cmpList[ii].GetRef(); + + ref.Replace( wxT( " " ), wxT( "_" ) ); + + ret |= fprintf( f, "$component %s\n", CONV_TO_UTF8( ref ) ); + + // Write the footprint list + for( unsigned jj = 0; jj < entry->m_FootprintList.GetCount(); jj++ ) { - if( CmpList[ii].m_Reference[nn] == ' ' ) - CmpList[ii].m_Reference[nn] = '_'; + ret |= fprintf( f, " %s\n", + CONV_TO_UTF8( entry->m_FootprintList[jj] ) ); } - fprintf( f, "$component %s\n", CmpList[ii].m_Reference ); - /* Write the footprint list */ - for( unsigned jj = 0; jj < Entry->m_FootprintList.GetCount(); jj++ ) - { - fprintf( f, " %s\n", - CONV_TO_UTF8( Entry->m_FootprintList[jj] ) ); - } - - fprintf( f, "$endlist\n" ); + ret |= fprintf( f, "$endlist\n" ); } - fprintf( f, "$endfootprintlist\n}\n" ); + ret |= fprintf( f, "$endfootprintlist\n}\n" ); } - if( CmpList ) - free( CmpList ); if( with_pcbnew ) { - fprintf( f, "{ Pin List by Nets\n" ); - WriteGENERICListOfNets( f, g_NetObjectslist ); - fprintf( f, "}\n" ); - fprintf( f, "#End\n" ); + ret |= fprintf( f, "{ Pin List by Nets\n" ); + + if( !WriteGENERICListOfNets( f, g_NetObjectslist ) ) + ret = -1; + + ret |= fprintf( f, "}\n" ); + ret |= fprintf( f, "#End\n" ); } + + return ret >= 0; } @@ -686,7 +822,7 @@ static void WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with static void AddPinToComponentPinList( SCH_COMPONENT* Component, SCH_SHEET_PATH* sheetlist, LIB_PIN* Pin ) { - /* Search the PIN description for Pin in g_NetObjectslist*/ + // Search the PIN description for Pin in g_NetObjectslist for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ ) { if( g_NetObjectslist[ii]->m_Type != NET_PIN ) @@ -699,9 +835,10 @@ static void AddPinToComponentPinList( SCH_COMPONENT* Component, continue; s_SortedComponentPinList.push_back( g_NetObjectslist[ii] ); + if( s_SortedComponentPinList.size() >= MAXPIN ) { - /* Log message for Internal error */ + // Log message for Internal error DisplayError( NULL, wxT( "AddPinToComponentPinList err: MAXPIN reached" ) ); return; } @@ -777,7 +914,7 @@ static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList ) * component pin list */ static void FindAllsInstancesOfComponent( SCH_COMPONENT* Component_in, - LIB_COMPONENT* Entry, + LIB_COMPONENT* aEntry, SCH_SHEET_PATH* Sheet_in ) { EDA_BaseStruct* SchItem; @@ -801,10 +938,10 @@ static void FindAllsInstancesOfComponent( SCH_COMPONENT* Component_in, if( str.CmpNoCase( Reference ) != 0 ) continue; - if( Entry == NULL ) + if( aEntry == NULL ) continue; - for( pin = Entry->GetNextPin(); pin != NULL; pin = Entry->GetNextPin( pin ) ) + for( pin = aEntry->GetNextPin(); pin != NULL; pin = aEntry->GetNextPin( pin ) ) { wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE ); @@ -844,81 +981,89 @@ static bool SortPinsByNum( NETLIST_OBJECT* Pin1, NETLIST_OBJECT* Pin2 ) /* Written in the file / net list (ranked by Netcode), and elements that are * connected */ -static void WriteGENERICListOfNets( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) +static bool WriteGENERICListOfNets( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) { - int NetCode, LastNetCode = -1; - int SameNetcodeCount = 0; - SCH_COMPONENT* Cmp; - wxString NetName, CmpRef; - wxString NetcodeName; - char FirstItemInNet[1024]; + int ret = 0; + int netCode; + int lastNetCode = -1; + int sameNetcodeCount = 0; + wxString netName; + wxString ref; + wxString netcodeName; + char firstItemInNet[256]; for( unsigned ii = 0; ii < aObjectsList.size(); ii++ ) { + SCH_COMPONENT* comp; + // New net found, write net id; - if( ( NetCode = aObjectsList[ii]->GetNet() ) != LastNetCode ) + if( ( netCode = aObjectsList[ii]->GetNet() ) != lastNetCode ) { - SameNetcodeCount = 0; // Items count for this net - NetName.Empty(); + sameNetcodeCount = 0; // Items count for this net + netName.Empty(); // Find a label (if exists) for this net. NETLIST_OBJECT* netref; netref = aObjectsList[ii]->m_NetNameCandidate; if( netref ) - NetName = netref->m_Label; + netName = netref->m_Label; - NetcodeName.Printf( wxT( "Net %d " ), NetCode ); - NetcodeName += wxT( "\"" ); - if( !NetName.IsEmpty() ) + netcodeName.Printf( wxT( "Net %d " ), netCode ); + netcodeName += wxT( "\"" ); + if( !netName.IsEmpty() ) { if( ( netref->m_Type != NET_PINLABEL ) && ( netref->m_Type != NET_GLOBLABEL ) ) { // usual net name, prefix it by the sheet path - NetcodeName += netref->m_SheetList.PathHumanReadable(); + netcodeName += netref->m_SheetList.PathHumanReadable(); } - NetcodeName += NetName; + netcodeName += netName; } - NetcodeName += wxT( "\"" ); + netcodeName += wxT( "\"" ); // Add the netname without prefix, in cases we need only the // "short" netname - NetcodeName += wxT( " \"" ) + NetName + wxT( "\"" ); - LastNetCode = NetCode; + netcodeName += wxT( " \"" ) + netName + wxT( "\"" ); + lastNetCode = netCode; } if( aObjectsList[ii]->m_Type != NET_PIN ) continue; - Cmp = (SCH_COMPONENT*) aObjectsList[ii]->m_Link; + comp = (SCH_COMPONENT*) aObjectsList[ii]->m_Link; // Get the reference for the net name and the main parent component - CmpRef = Cmp->GetRef( &aObjectsList[ii]->m_SheetList ); - if( CmpRef.StartsWith( wxT( "#" ) ) ) + ref = comp->GetRef( &aObjectsList[ii]->m_SheetList ); + if( ref[0] == wxChar( '#' ) ) continue; // Pseudo component (Like Power symbol) - // Print the pin list for this net, if 2 or more items are connected: - SameNetcodeCount++; - if( SameNetcodeCount == 1 ) /* first item for this net found, - * Print this connection, when a - * second item will be found */ + // Print the pin list for this net, use special handling if + // 2 or more items are connected: + + // if first item for this net found, defer printing this connection + // until a second item will is found + if( ++sameNetcodeCount == 1 ) { - sprintf( FirstItemInNet, " %s %.4s\n", CONV_TO_UTF8( CmpRef ), - (const char*) &aObjectsList[ii]->m_PinNum ); + snprintf( firstItemInNet, sizeof(firstItemInNet), " %s %.4s\n", + CONV_TO_UTF8( ref ), + (const char*) &aObjectsList[ii]->m_PinNum ); } - // Second item for this net found, Print the Net name, and the + // Second item for this net found, print the Net name, and the // first item - if( SameNetcodeCount == 2 ) + if( sameNetcodeCount == 2 ) { - fprintf( f, "%s\n", CONV_TO_UTF8( NetcodeName ) ); - fputs( FirstItemInNet, f ); + ret |= fprintf( f, "%s\n", CONV_TO_UTF8( netcodeName ) ); + ret |= fputs( firstItemInNet, f ); } - if( SameNetcodeCount >= 2 ) - fprintf( f, " %s %.4s\n", CONV_TO_UTF8( CmpRef ), + if( sameNetcodeCount >= 2 ) + ret |= fprintf( f, " %s %.4s\n", CONV_TO_UTF8( ref ), (const char*) &aObjectsList[ii]->m_PinNum ); } + + return ret >= 0; } @@ -956,7 +1101,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) { wxString StartCmpDesc = StartLine + wxT( "ADD_COM" ); wxString msg; - wxString FootprintName; + wxString footprint; char Line[1024]; SCH_SHEET_PATH* sheet; EDA_BaseStruct* DrawList; @@ -970,9 +1115,9 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) fprintf( f, "\"%s\"\n", CONV_TO_UTF8( Title ) ); fprintf( f, "\n" ); - /* Create netlist module section */ - ClearUsedFlags(); /* Reset the flags FlagControlMulti in all schematic - *files*/ + // Create netlist module section + s_ReferencesAlreadyFound.Clear(); + SCH_SHEET_LIST SheetList; for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) @@ -983,13 +1128,16 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) if( Component == NULL ) break; + /* + doing nothing with footprint if( !Component->GetField( FOOTPRINT )->IsVoid() ) { - FootprintName = Component->GetField( FOOTPRINT )->m_Text; - FootprintName.Replace( wxT( " " ), wxT( "_" ) ); + footprint = Component->GetField( FOOTPRINT )->m_Text; + footprint.Replace( wxT( " " ), wxT( "_" ) ); } else - FootprintName = wxT( "$noname" ); + footprint = wxT( "$noname" ); + */ msg = Component->GetRef( sheet ); fprintf( f, "%s ", CONV_TO_UTF8( StartCmpDesc ) ); @@ -1024,10 +1172,10 @@ static void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) { wxString InitNetDesc = StartLine + wxT( "ADD_TER" ); wxString StartNetDesc = StartLine + wxT( "TER" ); - wxString NetcodeName, InitNetDescLine; + wxString netcodeName, InitNetDescLine; unsigned ii; int print_ter = 0; - int NetCode, LastNetCode = -1; + int NetCode, lastNetCode = -1; SCH_COMPONENT* Cmp; wxString NetName; @@ -1037,7 +1185,7 @@ static void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) for( ii = 0; ii < g_NetObjectslist.size(); ii++ ) { // Get the NetName of the current net : - if( ( NetCode = aObjectsList[ii]->GetNet() ) != LastNetCode ) + if( ( NetCode = aObjectsList[ii]->GetNet() ) != lastNetCode ) { NetName.Empty(); @@ -1046,22 +1194,22 @@ static void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) if( netref ) NetName = netref->m_Label; - NetcodeName = wxT( "\"" ); + netcodeName = wxT( "\"" ); if( !NetName.IsEmpty() ) { if( ( netref->m_Type != NET_PINLABEL ) && ( netref->m_Type != NET_GLOBLABEL ) ) { // usual net name, prefix it by the sheet path - NetcodeName += + netcodeName += netref->m_SheetList.PathHumanReadable(); } - NetcodeName += NetName; + netcodeName += NetName; } else // this net has no name: create a default name $ - NetcodeName << wxT( "$" ) << NetCode; - NetcodeName += wxT( "\"" ); - LastNetCode = NetCode; + netcodeName << wxT( "$" ) << NetCode; + netcodeName += wxT( "\"" ); + lastNetCode = NetCode; print_ter = 0; } @@ -1090,7 +1238,7 @@ static void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) GetChars( InitNetDesc ), GetChars( refstr ), GetChars( str_pinnum ), - GetChars( NetcodeName ) ); + GetChars( netcodeName ) ); } print_ter++; break; diff --git a/eeschema/netlist.h b/eeschema/netlist.h index 99204b4cbd..cf7cc49a86 100644 --- a/eeschema/netlist.h +++ b/eeschema/netlist.h @@ -45,6 +45,11 @@ enum TypeNetForm { */ class OBJ_CMP_TO_LIST { +private: + /// Component reference prefix, without number (for IC1, this is IC) ) + std::string m_Ref; // it's private, use the accessors please + + public: SCH_COMPONENT* m_RootCmp; // the component in schematic LIB_COMPONENT* m_Entry; // the source component in library @@ -57,8 +62,6 @@ public: * components */ wxString* m_Value; /* Component value (same for all * instances) */ - char m_Reference[32]; /* Component reference prefix, without - * number (for IC1, this is IC) ) */ int m_NumRef; /* Reference number (for IC1, this is * 1) ) depending on sheet path*/ int m_Flag; /* flag for computations */ @@ -73,11 +76,32 @@ public: m_TimeStamp = 0; m_IsNew = false; m_Value = NULL; - m_Reference[0] = 0; m_NumRef = 0; m_Flag = 0; } + /* Some accessors which hide the strategy of how the reference is stored, + thereby making it easy to change that strategy. + */ + + + void SetRef( const wxString& aReference ) + { + m_Ref = CONV_TO_UTF8( aReference ); + } + wxString GetRef() const + { + return CONV_FROM_UTF8( m_Ref.c_str() ); + } + void SetRefStr( const std::string& aReference ) + { + m_Ref = aReference; + } + const char* GetRefStr() const + { + return m_Ref.c_str(); + } + int CompareValue( const OBJ_CMP_TO_LIST& item ) const { @@ -87,7 +111,7 @@ public: int CompareRef( const OBJ_CMP_TO_LIST& item ) const { - return strnicmp( m_Reference, item.m_Reference, 32 ); + return m_Ref.compare( item.m_Ref ); }