diff --git a/common/string.cpp b/common/string.cpp index ea64a5a15e..ece3be9e78 100644 --- a/common/string.cpp +++ b/common/string.cpp @@ -320,3 +320,113 @@ char* strupper( char* Text ) return Text; } + + +int RefDesStringCompare( const wxString& strFWord, const wxString& strSWord ) +{ + // The different sections of the first string + wxString strFWordBeg, strFWordMid, strFWordEnd; + + // 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 + + long lFirstDigit = 0; /* The converted middle section of the first + *string */ + long lSecondDigit = 0; /* The converted middle section of the second + *string */ + + // Split the two strings into separate parts + SplitString( strFWord, &strFWordBeg, &strFWordMid, &strFWordEnd ); + SplitString( strSWord, &strSWordBeg, &strSWordMid, &strSWordEnd ); + + // Compare the Beginning section of the strings + isEqual = strFWordBeg.CmpNoCase( strSWordBeg ); + + if( isEqual > 0 ) + iReturn = 1; + else if( isEqual < 0 ) + iReturn = -1; + else + { + // If the first sections are equal compare their 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 + isEqual = strFWordEnd.CmpNoCase( strSWordEnd ); + + if( isEqual > 0 ) + iReturn = 1; + else if( isEqual < 0 ) + iReturn = -1; + else + iReturn = 0; + } + } + + return iReturn; +} + + +int SplitString( wxString strToSplit, + wxString* strBeginning, + wxString* strDigits, + wxString* strEnd ) +{ + // Clear all the return strings + strBeginning->Empty(); + strDigits->Empty(); + strEnd->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 + int ii; + for( ii = (strToSplit.length() - 1); ii >= 0; ii-- ) + { + if( isdigit( strToSplit[ii] ) ) + break; + } + + // 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 + *strEnd = strToSplit.substr( ii + 1 ); + + // Go to the end of the digits + int position = ii + 1; + for( ; ii >= 0; ii-- ) + { + if( !isdigit( strToSplit[ii] ) ) + break; + } + + // If all that was left was digits, then just set the digits string + if( ii < 0 ) + *strDigits = strToSplit.substr( 0, position ); + + /* We were only looking for the last set of digits everything else is + *part of the preamble */ + else + { + *strDigits = strToSplit.substr( ii + 1, position - ii - 1 ); + *strBeginning = strToSplit.substr( 0, ii + 1 ); + } + } + + return 0; +} diff --git a/eeschema/build_BOM.cpp b/eeschema/build_BOM.cpp index 0f14387a32..035c284028 100644 --- a/eeschema/build_BOM.cpp +++ b/eeschema/build_BOM.cpp @@ -71,12 +71,6 @@ static bool SortLabelsBySheet( const LABEL_OBJECT& obj1, static void DeleteSubCmp( std::vector & aList ); static int PrintListeGLabel( FILE* f, std::vector & aList ); -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 static char s_ExportSeparatorSymbol; @@ -1049,122 +1043,3 @@ static int PrintListeGLabel( FILE* f, std::vector & aList ) } -/* This function will act just like the strcmp function but correctly sort - * the numerical order in the string - * return -1 if first string is less than the second - * return 0 if the strings are equal - * return 1 if the first string is greater than the second - */ -int RefDesStringCompare( const wxString& strFWord, const wxString& strSWord ) -{ - // The different sections of the first string - wxString strFWordBeg, strFWordMid, strFWordEnd; - - // 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 - - long lFirstDigit = 0; /* The converted middle section of the first - *string */ - long lSecondDigit = 0; /* The converted middle section of the second - *string */ - - // Split the two string into separate parts - SplitString( strFWord, &strFWordBeg, &strFWordMid, &strFWordEnd ); - SplitString( strSWord, &strSWordBeg, &strSWordMid, &strSWordEnd ); - - // Compare the Beginning section of the strings - isEqual = strFWordBeg.CmpNoCase( strSWordBeg ); - if( isEqual > 0 ) - iReturn = 1; - else if( isEqual < 0 ) - iReturn = -1; - else - { - // 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 - isEqual = strFWordEnd.CmpNoCase( strSWordEnd ); - - if( isEqual > 0 ) - iReturn = 1; - else if( isEqual < 0 ) - iReturn = -1; - else - iReturn = 0; - } - } - - return iReturn; -} - - -/* This is the function that breaks a string into three parts. - * The alphabetic preamble - * The numeric part - * Any alphabetic ending - * For example C10A is split to C 10 A - */ -int SplitString( wxString strToSplit, - wxString* strBeginning, - wxString* strDigits, - wxString* strEnd ) -{ - // Clear all the return strings - strBeginning->Clear(); - strDigits->Clear(); - strEnd->Clear(); - - // 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 - int ii; - for( ii = (strToSplit.length() - 1); ii >= 0; ii-- ) - { - if( isdigit( strToSplit[ii] ) ) - break; - } - - // 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 - *strEnd = strToSplit.substr( ii + 1 ); - - // Go to the end of the digits - int position = ii + 1; - for( ; ii >= 0; ii-- ) - { - if( !isdigit( strToSplit[ii] ) ) - break; - } - - // If all that was left was digits, then just set the digits string - if( ii < 0 ) - *strDigits = strToSplit.substr( 0, position ); - - /* We were only looking for the last set of digits everything else is - *part of the preamble */ - else - { - *strDigits = strToSplit.substr( ii + 1, position - ii - 1 ); - *strBeginning = strToSplit.substr( 0, ii + 1 ); - } - } - - return 0; -} diff --git a/eeschema/class_drawsheetpath.cpp b/eeschema/class_drawsheetpath.cpp index 5d44ded807..6bf79b4bd6 100644 --- a/eeschema/class_drawsheetpath.cpp +++ b/eeschema/class_drawsheetpath.cpp @@ -220,7 +220,7 @@ wxString SCH_SHEET_PATH::Path() * (the "normal" path uses the time stamps which do not changes even when * editing sheet parameters) */ -wxString SCH_SHEET_PATH::PathHumanReadable() +wxString SCH_SHEET_PATH::PathHumanReadable() const { wxString s, t; @@ -355,6 +355,7 @@ SCH_ITEM* SCH_SHEET_PATH::MatchNextItem( wxFindReplaceData& aSearchData, bool SCH_SHEET_PATH::operator=( const SCH_SHEET_PATH& d1 ) { m_numSheets = d1.m_numSheets; + unsigned i; for( i = 0; i < m_numSheets; i++ ) { @@ -370,10 +371,11 @@ bool SCH_SHEET_PATH::operator=( const SCH_SHEET_PATH& d1 ) } -bool SCH_SHEET_PATH::operator==( const SCH_SHEET_PATH& d1 ) +bool SCH_SHEET_PATH::operator==( const SCH_SHEET_PATH& d1 ) const { if( m_numSheets != d1.m_numSheets ) return false; + for( unsigned i = 0; i < m_numSheets; i++ ) { if( m_sheets[i] != d1.m_sheets[i] ) @@ -384,14 +386,23 @@ bool SCH_SHEET_PATH::operator==( const SCH_SHEET_PATH& d1 ) } -bool SCH_SHEET_PATH::operator!=( const SCH_SHEET_PATH& d1 ) +bool SCH_SHEET_PATH::operator!=( const SCH_SHEET_PATH& d1 ) const { if( m_numSheets != d1.m_numSheets ) return true; + for( unsigned i = 0; i < m_numSheets; i++ ) { if( m_sheets[i] != d1.m_sheets[i] ) + { + /* + printf( "micompare this:'%s' d1:'%s'\n", + CONV_TO_UTF8( PathHumanReadable() ), + CONV_TO_UTF8( d1.PathHumanReadable() ) ); + */ + return true; + } } return false; diff --git a/eeschema/class_drawsheetpath.h b/eeschema/class_drawsheetpath.h index ab850be3ad..ebb966fe98 100644 --- a/eeschema/class_drawsheetpath.h +++ b/eeschema/class_drawsheetpath.h @@ -150,7 +150,7 @@ public: * stamps in the path. (Time stamps do not change even when editing * sheet parameters). */ - wxString PathHumanReadable(); + wxString PathHumanReadable() const; /** Function BuildSheetPathInfoFromSheetPathValue * Fill this with data to access to the hierarchical sheet known by its @@ -207,9 +207,9 @@ public: bool operator=( const SCH_SHEET_PATH& d1 ); - bool operator==( const SCH_SHEET_PATH& d1 ); + bool operator==( const SCH_SHEET_PATH& d1 ) const; - bool operator!=( const SCH_SHEET_PATH& d1 ); + bool operator!=( const SCH_SHEET_PATH& d1 ) const; }; diff --git a/eeschema/class_netlist_object.cpp b/eeschema/class_netlist_object.cpp index 28cda6b3e3..e710ff07ef 100644 --- a/eeschema/class_netlist_object.cpp +++ b/eeschema/class_netlist_object.cpp @@ -10,7 +10,6 @@ #include "class_netlist_object.h" - #if defined(DEBUG) #include const char* ShowType( NetObjetType aType ) @@ -134,3 +133,4 @@ NETLIST_OBJECT::NETLIST_OBJECT( NETLIST_OBJECT& aSource ) NETLIST_OBJECT::~NETLIST_OBJECT() { } + diff --git a/eeschema/class_netlist_object.h b/eeschema/class_netlist_object.h index 5f79de5e66..def2be394a 100644 --- a/eeschema/class_netlist_object.h +++ b/eeschema/class_netlist_object.h @@ -6,6 +6,9 @@ #ifndef _CLASS_NETLIST_OBJECT_H_ #define _CLASS_NETLIST_OBJECT_H_ +#include "class_pin.h" // LIB_PIN::ReturnPinStringNum( m_PinNum ) + + /* Type of Net objects (wires, labels, pins...) */ enum NetObjetType { NET_ITEM_UNSPECIFIED, // only for not yet initialized instances @@ -105,6 +108,17 @@ public: void SetNet( int aNetCode ) { m_NetCode = aNetCode; } int GetNet() const { return m_NetCode; } + + /** + * Function GetPinNum + * returns a pin number in wxString form. Pin numbers are not always + * numbers. "A23" would be a valid pin number. + */ + wxString GetPinNumText() + { + // hide the ugliness in here, but do it inline. + return LIB_PIN::ReturnPinStringNum( m_PinNum ); + } }; #endif // _CLASS_NETLIST_OBJECT_H_ diff --git a/eeschema/class_pin.cpp b/eeschema/class_pin.cpp index 7548913a0e..ed0ee68029 100644 --- a/eeschema/class_pin.cpp +++ b/eeschema/class_pin.cpp @@ -1485,12 +1485,6 @@ wxString LIB_PIN::ReturnPinStringNum( long aPinNum ) } -wxString LIB_PIN::GetNumber( void ) -{ - return ReturnPinStringNum( m_PinNum ); -} - - /** Function LIB_PIN::SetPinNumFromString() * fill the buffer with pin num as a wxString * Pin num is coded as a long diff --git a/eeschema/class_pin.h b/eeschema/class_pin.h index c6318d7a23..ee9aee4196 100644 --- a/eeschema/class_pin.h +++ b/eeschema/class_pin.h @@ -7,6 +7,7 @@ #ifndef CLASS_PIN_H #define CLASS_PIN_H +#include "classes_body_items.h" #define TARGET_PIN_DIAM 12 /* Circle diameter drawn at the active end of * pins */ @@ -159,7 +160,12 @@ public: */ void ReturnPinStringNum( wxString& aStringBuffer ) const; - wxString GetNumber(); + + wxString GetNumber() + { + return ReturnPinStringNum( m_PinNum ); + } + /** Function ReturnPinStringNum (static function) * Pin num is coded as a long or 4 ascii chars diff --git a/eeschema/classes_body_items.h b/eeschema/classes_body_items.h index ba1a07bb1b..41d471381c 100644 --- a/eeschema/classes_body_items.h +++ b/eeschema/classes_body_items.h @@ -7,6 +7,8 @@ #ifndef CLASSES_BODY_ITEMS_H #define CLASSES_BODY_ITEMS_H +#include "base_struct.h" + class LIB_COMPONENT; class PLOTTER; diff --git a/eeschema/netform.cpp b/eeschema/netform.cpp index f0763a3b94..517fcf31c0 100644 --- a/eeschema/netform.cpp +++ b/eeschema/netform.cpp @@ -48,51 +48,22 @@ #include "build_version.h" +#include + /** * @bug - Every place in this file where fprintf() is used and the return * is not checked is a bug. The fprintf() function can fail and * returns a value less than 0 when it does. */ -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 bool WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ); -static bool WriteGENERICListOfNets( wxXmlNode* aNode, NETLIST_OBJECT_LIST& aObjectsList ); - -static void AddPinToComponentPinList( SCH_COMPONENT* Component, - SCH_SHEET_PATH* sheet, - LIB_PIN* PinEntry ); - -static void FindAllInstancesOfComponent( SCH_COMPONENT* Component, - 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 NETLIST_OBJECT_LIST s_SortedComponentPinList; - - -#include /** * Class UNIQUE_STRINGS - * will keep track of unique wxStrings and is useful in telling if a string + * tracks 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: @@ -119,8 +90,77 @@ bool UNIQUE_STRINGS::Lookup( const wxString& aString ) return ret; } -/// Used for multi part per package components, avoids using a component more than once. -static UNIQUE_STRINGS s_ReferencesAlreadyFound; + +/** + * Class NETLIST_HELP + * is a private implementation class used in this source file to keep track + * of and recycle datastructures used in the generation of various exported netlist + * files. Since it is private it is not in a header file. + */ +class NETLIST_HELP +{ + NETLIST_OBJECT_LIST m_SortedComponentPinList; + + /// Used for "multi parts per package" components, avoids processing a lib component more than once. + UNIQUE_STRINGS m_ReferencesAlreadyFound; + + + /** + * Function sprintPinNetName + * formats the net name for \a aPin using \a aNetNameFormat into \a aResult. + *

+ * Net name is: + *

    + *
  • "?" if pin not connected + *
  • "netname" for global net (like gnd, vcc .. + *
  • "netname_sheetnumber" for the usual nets + *
+ */ + static void sprintPinNetName( wxString* aResult, const wxString& aNetNameFormat, NETLIST_OBJECT* aPin ); + + /** + * Function findNextComponentAndCreatePinList + * finds a "suitable" component from the DrawList and optionally builds + * its pin list int m_SortedComponentPinList. The list is sorted by pin num. + * A suitable component is a "new" real component (power symbols are not + * considered). + */ + SCH_COMPONENT* findNextComponentAndCreatPinList( EDA_BaseStruct* aItem, + SCH_SHEET_PATH* aSheetPath ); + +public: + bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName ); + + /** + * Function WriteNetListPCBNEW + * generates a net list file (Format 2 improves ORCAD PCB) + * = TRUE if with_pcbnew + * Format Pcbnew (OrcadPcb2 + reviews and lists of net) + * = FALSE if with_pcbnew + * Format ORCADPCB2 strict + */ + bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, + bool with_pcbnew ); + + void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ); + void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ); + + void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, + bool use_netnames ); + + bool WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ); + bool WriteGENERICListOfNets( wxXmlNode* aNode, NETLIST_OBJECT_LIST& aObjectsList ); + + bool AddPinToComponentPinList( SCH_COMPONENT* Component, + SCH_SHEET_PATH* sheet, + LIB_PIN* PinEntry ); + + void FindAllInstancesOfComponent( SCH_COMPONENT* Component, + LIB_COMPONENT* aEntry, + SCH_SHEET_PATH* Sheet_in ); + + void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList ); +}; /** @@ -136,8 +176,9 @@ static UNIQUE_STRINGS s_ReferencesAlreadyFound; bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFullFileName, bool aUse_netnames ) { - bool ret = true; - FILE* f = NULL; + bool ret = true; + FILE* f = NULL; + NETLIST_HELP helper; if( aFormat < NET_TYPE_CUSTOM1 ) { @@ -154,22 +195,22 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull switch( aFormat ) { case NET_TYPE_PCBNEW: - ret = WriteNetListPCBNEW( this, f, TRUE ); + ret = helper.WriteNetListPCBNEW( this, f, TRUE ); fclose( f ); break; case NET_TYPE_ORCADPCB2: - ret = WriteNetListPCBNEW( this, f, FALSE ); + ret = helper.WriteNetListPCBNEW( this, f, FALSE ); fclose( f ); break; case NET_TYPE_CADSTAR: - WriteNetListCADSTAR( this, f ); + helper.WriteNetListCADSTAR( this, f ); fclose( f ); break; case NET_TYPE_SPICE: - WriteNetListPspice( this, f, aUse_netnames ); + helper.WriteNetListPspice( this, f, aUse_netnames ); fclose( f ); break; @@ -178,7 +219,7 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull wxFileName tmpFile = aFullFileName; tmpFile.SetExt( wxT( "tmp" ) ); - ret = Write_GENERIC_NetList( this, tmpFile.GetFullPath() ); + ret = helper.Write_GENERIC_NetList( this, tmpFile.GetFullPath() ); if( !ret ) break; @@ -210,31 +251,76 @@ bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFull } -/* Find a "suitable" component from the DrawList - * build its pin list s_SortedComponentPinList. - * The list is sorted by pin num - * A suitable component is a "new" real component (power symbols are not - * considered) - * Must be deallocated by the user +/* + * Comparison routine for sorting by pin numbers. */ -static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item, - SCH_SHEET_PATH* path ) +static bool sortPinsByNum( NETLIST_OBJECT* Pin1, NETLIST_OBJECT* Pin2 ) { - s_SortedComponentPinList.clear(); + // return "lhs < rhs" + return RefDesStringCompare( Pin1->GetPinNumText(), Pin2->GetPinNumText() ) < 0; +} - // continue searching from the middle of a linked list - for( ; item; item = item->Next() ) + +void NETLIST_HELP::sprintPinNetName( wxString* aResult, + const wxString& aNetNameFormat, NETLIST_OBJECT* aPin ) +{ + int netcode = aPin->GetNet(); + + // Not wxString::Clear(), which would free memory. We want the worst + // case wxString memory to grow to avoid reallocation from within the + // caller's loop. + aResult->Empty(); + + if( netcode != 0 && aPin->m_FlagOfConnection == PAD_CONNECT ) { - if( item->Type() != TYPE_SCH_COMPONENT ) + NETLIST_OBJECT* netref = aPin->m_NetNameCandidate; + if( netref ) + *aResult = netref->m_Label; + + if( !aResult->IsEmpty() ) + { + // prefix non global label names with the sheet path, to avoid name collisions + if( netref->m_Type != NET_PINLABEL && netref->m_Type != NET_GLOBLABEL ) + { + wxString lnet = *aResult; + + *aResult = netref->m_SheetList.PathHumanReadable(); + + // If sheet path is too long, use the time stamp name instead + if( aResult->Length() > 32 ) + *aResult = netref->m_SheetList.Path(); + + *aResult += lnet; + } + } + else + { + aResult->Printf( aNetNameFormat.GetData(), netcode ); + } + } +} + + +SCH_COMPONENT* NETLIST_HELP::findNextComponentAndCreatPinList( EDA_BaseStruct* aItem, + SCH_SHEET_PATH* aSheetPath ) +{ + wxString ref; + + m_SortedComponentPinList.clear(); + + // continue searching from the middle of a linked list (the draw list) + for( ; aItem; aItem = aItem->Next() ) + { + if( aItem->Type() != TYPE_SCH_COMPONENT ) continue; // found next component - SCH_COMPONENT* comp = (SCH_COMPONENT*) item; + SCH_COMPONENT* comp = (SCH_COMPONENT*) aItem; // 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 + ref = comp->GetRef( aSheetPath ); + if( ref[0] == wxChar( '#' ) ) continue; // if( Component->m_FlagControlMulti == 1 ) @@ -247,22 +333,28 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item, if( !entry ) continue; - // If Multi parts per package + // If component is a "multi parts per package" type if( entry->GetPartCount() > 1 ) { // test if already visited, and if so skip - if( s_ReferencesAlreadyFound.Lookup( ref ) ) + if( m_ReferencesAlreadyFound.Lookup( ref ) ) continue; - // Collect all parts and pins for this first occurance of reference - FindAllInstancesOfComponent( comp, entry, path ); + // Collect all parts and pins for this first occurance of reference. + // This is only done once, it would be too expensive otherwise. + FindAllInstancesOfComponent( comp, entry, aSheetPath ); + + if( ref == wxString( wxT("U1") ) ) + { + printf("U1 m_SortedComponentPinList.size():%zu\n", m_SortedComponentPinList.size() ); + } } else // entry->GetPartCount() <= 1 means one part per package { - LIB_PIN_LIST pins; + LIB_PIN_LIST pins; // constructed once here - entry->GetPins( pins, comp->GetUnitSelection( path ), comp->m_Convert ); + entry->GetPins( pins, comp->GetUnitSelection( aSheetPath ), comp->m_Convert ); for( size_t i = 0; i < pins.size(); i++ ) { @@ -270,16 +362,16 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item, wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE ); - AddPinToComponentPinList( comp, path, pin ); + AddPinToComponentPinList( comp, aSheetPath, pin ); } } - // Sort pins in s_SortedComponentPinList by pin number - sort( s_SortedComponentPinList.begin(), - s_SortedComponentPinList.end(), SortPinsByNum ); + // Sort pins in m_SortedComponentPinList by pin number + sort( m_SortedComponentPinList.begin(), + m_SortedComponentPinList.end(), sortPinsByNum ); - // Remove duplicate Pins in s_SortedComponentPinList - EraseDuplicatePins( s_SortedComponentPinList ); + // Remove duplicate Pins in m_SortedComponentPinList + EraseDuplicatePins( m_SortedComponentPinList ); return comp; } @@ -288,48 +380,6 @@ static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item, } -/* Return the net name for the pin Pin. - * Net name is: - * "?" if pin not connected - * "netname" for global net (like gnd, vcc .. - * "netname_sheetnumber" for the usual nets - */ -static wxString ReturnPinNetName( NETLIST_OBJECT* Pin, const wxString& DefaultFormatNetname ) -{ - int netcode = Pin->GetNet(); - wxString NetName; - - if( ( netcode == 0 ) || ( Pin->m_FlagOfConnection != PAD_CONNECT ) ) - return NetName; - - NETLIST_OBJECT* netref = Pin->m_NetNameCandidate; - if( netref ) - NetName = netref->m_Label; - - if( !NetName.IsEmpty() ) - { - // prefix non global labels names by the sheet path, to avoid names collisions - if( ( netref->m_Type != NET_PINLABEL ) - && ( netref->m_Type != NET_GLOBLABEL ) ) - { - wxString lnet = NetName; - NetName = netref->m_SheetList.PathHumanReadable(); - - // If sheet path is too long, use the time stamp name instead - if( NetName.Length() > 32 ) - NetName = netref->m_SheetList.Path(); - NetName += lnet; - } - } - else - { - NetName.Printf( DefaultFormatNetname.GetData(), netcode ); - } - - return NetName; -} - - /** * Function Node * is a convenience function that creates a new wxXmlNode with an optional textual child. @@ -353,7 +403,7 @@ static wxXmlNode* Node( const wxString& aName, const wxString& aTextualContent = * creates a generic netlist, now in XML. * @return bool - true if there were no errors, else false. */ -bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName ) +bool NETLIST_HELP::Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName ) { #if 1 // output the XML format netlist. @@ -391,7 +441,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi const wxString sPart = wxT( "part" ); const wxString sNames = wxT( "names" ); - s_ReferencesAlreadyFound.Clear(); + m_ReferencesAlreadyFound.Clear(); xdoc.SetRoot( xroot = Node( wxT( "netlist" ) ) ); xroot->AddProperty( wxT( "version" ), wxT( "B" ) ); @@ -406,7 +456,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi { for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() ) { - SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( schItem, path ); + SCH_COMPONENT* comp = findNextComponentAndCreatPinList( schItem, path ); if( !comp ) break; // No component left @@ -497,7 +547,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi return false; } - s_ReferencesAlreadyFound.Clear(); + m_ReferencesAlreadyFound.Clear(); ret |= fprintf( out, "$BeginNetlist\n" ); @@ -510,7 +560,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi { for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() ) { - SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( schItem, path ); + SCH_COMPONENT* comp = findNextComponentAndCreatPinList( schItem, path ); if( !comp ) break; // No component left @@ -541,9 +591,9 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi // Write pin list: ret |= fprintf( out, "$BeginPinList\n" ); - for( unsigned ii = 0; ii < s_SortedComponentPinList.size(); ii++ ) + for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ ) { - NETLIST_OBJECT* Pin = s_SortedComponentPinList[ii]; + NETLIST_OBJECT* Pin = m_SortedComponentPinList[ii]; if( !Pin ) continue; @@ -586,7 +636,7 @@ bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFi * [.-] Or PSpice gnucap are beginning * + + Gnucap and PSpice are ultimately NetList */ -static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_netnames ) +void NETLIST_HELP::WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_netnames ) { char Line[1024]; SCH_SHEET_PATH* sheet; @@ -596,6 +646,7 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_ wxString text; wxArrayString SpiceCommandAtBeginFile, SpiceCommandAtEndFile; wxString msg; + wxString netName; #define BUFYPOS_LEN 4 wxChar bufnum[BUFYPOS_LEN + 1]; @@ -623,12 +674,15 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_ wxChar ident; if( DrawList->Type() != TYPE_SCH_TEXT ) continue; + #define DRAWTEXT ( (SCH_TEXT*) DrawList ) text = DRAWTEXT->m_Text; if( text.IsEmpty() ) continue; + ident = text.GetChar( 0 ); if( ident != '.' && ident != '-' && ident != '+' ) continue; + text.Remove( 0, 1 ); // Remove the first char. text.Remove( 6 ); // text contains 6 char. text.MakeLower(); @@ -673,34 +727,37 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_ // Create component list - s_ReferencesAlreadyFound.Clear(); + m_ReferencesAlreadyFound.Clear(); for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) { for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() ) { - DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet ); + DrawList = Component = findNextComponentAndCreatPinList( DrawList, sheet ); if( Component == NULL ) break; fprintf( f, "%s ", CONV_TO_UTF8( Component->GetRef( sheet ) ) ); // Write pin list: - for( unsigned ii = 0; ii < s_SortedComponentPinList.size(); ii++ ) + for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ ) { - NETLIST_OBJECT* Pin = s_SortedComponentPinList[ii]; + NETLIST_OBJECT* Pin = m_SortedComponentPinList[ii]; if( !Pin ) continue; - wxString NetName = ReturnPinNetName( Pin, wxT( "N-%.6d" ) ); - if( NetName.IsEmpty() ) - NetName = wxT( "?" ); + + sprintPinNetName( &netName , wxT( "N-%.6d" ), Pin ); + + if( netName.IsEmpty() ) + netName = wxT( "?" ); + if( use_netnames ) - fprintf( f, " %s", CONV_TO_UTF8( NetName ) ); + fprintf( f, " %s", CONV_TO_UTF8( netName ) ); else // Use number for net names (with net number = 0 for // "GND" { // NetName = "0" is "GND" net for Spice - if( NetName == wxT( "0" ) || NetName == wxT( "GND" ) ) + if( netName == wxT( "0" ) || netName == wxT( "GND" ) ) fprintf( f, " 0" ); else fprintf( f, " %d", Pin->GetNet() ); @@ -712,7 +769,7 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_ } } - s_SortedComponentPinList.clear(); + m_SortedComponentPinList.clear(); /* Print texts starting by [+]pspice , ou [+]gnucap */ nbitems = SpiceCommandAtEndFile.GetCount(); @@ -733,18 +790,13 @@ static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_ } -/* Generate net list file (Format 2 improves ORCAD PCB) - * = TRUE if with_pcbnew - * Format Pcbnew (OrcadPcb2 + reviews and lists of net) - * = FALSE if with_pcbnew - * Format ORCADPCB2 strict - */ -static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew ) +bool NETLIST_HELP::WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew ) { wxString field; wxString footprint; char dateBuf[256]; int ret = 0; // zero now, OR in the sign bit on error + wxString netName; std::vector cmpList; @@ -757,7 +809,7 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with // Create netlist module section - s_ReferencesAlreadyFound.Clear(); + m_ReferencesAlreadyFound.Clear(); SCH_SHEET_LIST sheetList; @@ -765,7 +817,7 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with { for( EDA_BaseStruct* item = path->LastDrawList(); item; item = item->Next() ) { - SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( item, path ); + SCH_COMPONENT* comp = findNextComponentAndCreatPinList( item, path ); if( !comp ) break; @@ -815,21 +867,24 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with } ret |= fprintf( f, "\n" ); + printf( "%-10s pincount:%zu\n", CONV_TO_UTF8( comp->GetRef( path ) ), + m_SortedComponentPinList.size() ); + // Write pin list: - for( unsigned ii = 0; ii < s_SortedComponentPinList.size(); ii++ ) + for( unsigned ii = 0; ii < m_SortedComponentPinList.size(); ii++ ) { - NETLIST_OBJECT* pin = s_SortedComponentPinList[ii]; + NETLIST_OBJECT* pin = m_SortedComponentPinList[ii]; if( !pin ) continue; - wxString netname = ReturnPinNetName( pin, wxT( "N-%.6d" ) ); - if( netname.IsEmpty() ) - netname = wxT( "?" ); + sprintPinNetName( &netName, wxT( "N-%.6d" ), pin ); + if( netName.IsEmpty() ) + netName = wxT( "?" ); - netname.Replace( wxT( " " ), wxT( "_" ) ); + netName.Replace( wxT( " " ), wxT( "_" ) ); ret |= fprintf( f, " ( %4.4s %s )\n", (char*) &pin->m_PinNum, - CONV_TO_UTF8( netname ) ); + CONV_TO_UTF8( netName ) ); } ret |= fprintf( f, " )\n" ); @@ -838,7 +893,7 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with ret |= fprintf( f, ")\n*\n" ); - s_SortedComponentPinList.clear(); + m_SortedComponentPinList.clear(); // Write the allowed footprint list for each component if( with_pcbnew && cmpList.size() ) @@ -887,34 +942,43 @@ static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with /* - * Add a new pin description in the pin list s_SortedComponentPinList + * Add a new pin description in the pin list m_SortedComponentPinList * a pin description is a pointer to the corresponding structure * created by BuildNetList() in the table g_NetObjectslist */ -static void AddPinToComponentPinList( SCH_COMPONENT* Component, - SCH_SHEET_PATH* sheetlist, LIB_PIN* Pin ) +bool NETLIST_HELP::AddPinToComponentPinList( SCH_COMPONENT* aComponent, + SCH_SHEET_PATH* aSheetPath, LIB_PIN* aPin ) { // 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 ) - continue; - if( g_NetObjectslist[ii]->m_Link != Component ) - continue; - if( g_NetObjectslist[ii]->m_SheetList != *sheetlist ) - continue; - if( g_NetObjectslist[ii]->m_PinNum != Pin->m_PinNum ) + NETLIST_OBJECT* pin = g_NetObjectslist[ii]; + + if( pin->m_Type != NET_PIN ) continue; - s_SortedComponentPinList.push_back( g_NetObjectslist[ii] ); + if( pin->m_Link != aComponent ) + continue; - if( s_SortedComponentPinList.size() >= MAXPIN ) + if( pin->m_PinNum != aPin->m_PinNum ) + continue; + + // most expensive test at the end. + if( pin->m_SheetList != *aSheetPath ) + continue; + + m_SortedComponentPinList.push_back( pin ); + + if( m_SortedComponentPinList.size() >= MAXPIN ) { // Log message for Internal error DisplayError( NULL, wxT( "AddPinToComponentPinList err: MAXPIN reached" ) ); - return; } + + return true; // we're done, we appended. } + + return false; } @@ -932,7 +996,7 @@ static void AddPinToComponentPinList( SCH_COMPONENT* Component, * given component. * Note: this list *MUST* be sorted by pin number (.m_PinNum member value) */ -static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList ) +void NETLIST_HELP::EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList ) { if( aPinList.size() == 0 ) // Trivial case: component with no pin return; @@ -959,6 +1023,7 @@ static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList ) // other pin num end of duplicate list. if( aPinList[idxref]->m_PinNum != aPinList[jj]->m_PinNum ) break; + if( aPinList[idxref]->m_FlagOfConnection == PAD_CONNECT ) aPinList[jj] = NULL; else /* the reference pin is not connected: remove this pin if the @@ -980,81 +1045,83 @@ static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList ) /** * Function FindAllInstancesOfComponent - * is used for multiple parts per package components. + * is used for "multiple parts per package" components. * * Search all instances of Component_in, * Calls AddPinToComponentPinList() to and pins founds to the current * component pin list */ -static void FindAllInstancesOfComponent( SCH_COMPONENT* Component_in, - LIB_COMPONENT* aEntry, - SCH_SHEET_PATH* Sheet_in ) +void NETLIST_HELP::FindAllInstancesOfComponent( SCH_COMPONENT* aComponent, + LIB_COMPONENT* aEntry, + SCH_SHEET_PATH* aSheetPath ) { - EDA_BaseStruct* SchItem; - SCH_COMPONENT* Component2; - LIB_PIN* pin; - SCH_SHEET_PATH* sheet; - wxString str, Reference = Component_in->GetRef( Sheet_in ); + wxString ref = aComponent->GetRef( aSheetPath ); + wxString ref2; - SCH_SHEET_LIST SheetList; + SCH_SHEET_LIST sheetList; - for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) + for( SCH_SHEET_PATH* sheet = sheetList.GetFirst(); sheet; sheet = sheetList.GetNext() ) { - for( SchItem = sheet->LastDrawList(); SchItem; SchItem = SchItem->Next() ) + for( EDA_BaseStruct* schItem = sheet->LastDrawList(); schItem; schItem = schItem->Next() ) { - if( SchItem->Type() != TYPE_SCH_COMPONENT ) + if( schItem->Type() != TYPE_SCH_COMPONENT ) continue; - Component2 = (SCH_COMPONENT*) SchItem; + SCH_COMPONENT* comp2 = (SCH_COMPONENT*) schItem; - str = Component2->GetRef( sheet ); - if( str.CmpNoCase( Reference ) != 0 ) + ref2 = comp2->GetRef( sheet ); + if( ref2.CmpNoCase( ref ) != 0 ) continue; if( aEntry == NULL ) continue; - for( pin = aEntry->GetNextPin(); pin != NULL; pin = aEntry->GetNextPin( pin ) ) + for( LIB_PIN* pin = aEntry->GetNextPin(); pin; pin = aEntry->GetNextPin( pin ) ) { wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE ); - if( pin->m_Unit - && ( pin->m_Unit != Component2->GetUnitSelection( sheet ) ) ) + if( pin->m_Unit && pin->m_Unit != comp2->GetUnitSelection( aSheetPath ) ) continue; - if( pin->m_Convert - && ( pin->m_Convert != Component2->m_Convert ) ) + if( pin->m_Convert && pin->m_Convert != comp2->m_Convert ) continue; - // A suitable pin in found: add it to the current list - AddPinToComponentPinList( Component2, sheet, pin ); +#if defined(DEBUG) + printf( "AddPin %s %s\n", CONV_TO_UTF8(ref), CONV_TO_UTF8( pin->GetNumber() ) ); + + if( ref == wxString( wxT("U1") ) && pin->GetNumber() == wxString( wxT("A1") ) ) + { + int debug = 1; + } + + bool rc = +#endif + + // A suitable pin is found: add it to the current list + AddPinToComponentPinList( comp2, aSheetPath, pin ); + +#if defined(DEBUG) + if( !rc ) + { + printf("skipped pin %s %s\n", + CONV_TO_UTF8(ref), + CONV_TO_UTF8( pin->GetNumber() ) ); + + printf( "g_NetObjectslist.size():%zu\n", + g_NetObjectslist.size() ); + } +#endif + } } } } -/* - * Comparison routine for sorting by pin numbers. - */ -static bool SortPinsByNum( NETLIST_OBJECT* Pin1, NETLIST_OBJECT* Pin2 ) -{ - int Num1, Num2; - char Line[5]; - - Num1 = Pin1->m_PinNum; - Num2 = Pin2->m_PinNum; - Line[4] = 0; - memcpy( Line, &Num1, 4 ); Num1 = atoi( Line ); - memcpy( Line, &Num2, 4 ); Num2 = atoi( Line ); - return Num1 < Num2; -} - - /* Written in the file / net list (ranked by Netcode), and elements that are * connected */ -static bool WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) +bool NETLIST_HELP::WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) { int ret = 0; int netCode; @@ -1144,7 +1211,7 @@ static bool WriteGENERICListOfNetsTxt( FILE* f, NETLIST_OBJECT_LIST& aObjectsLis * Function WriteGENERICListOfNets * saves a netlist in xml format. */ -static bool WriteGENERICListOfNets( wxXmlNode* aNode, NETLIST_OBJECT_LIST& aObjectsList ) +bool NETLIST_HELP::WriteGENERICListOfNets( wxXmlNode* aNode, NETLIST_OBJECT_LIST& aObjectsList ) { wxString netCodeTxt; wxString netName; @@ -1255,7 +1322,7 @@ wxString StartLine( wxT( "." ) ); * .. B * T3 1 *U1 * 14 */ -static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) +void NETLIST_HELP::WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) { wxString StartCmpDesc = StartLine + wxT( "ADD_COM" ); wxString msg; @@ -1274,7 +1341,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) fprintf( f, "\n" ); // Create netlist module section - s_ReferencesAlreadyFound.Clear(); + m_ReferencesAlreadyFound.Clear(); SCH_SHEET_LIST SheetList; @@ -1282,7 +1349,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) { for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() ) { - DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet ); + DrawList = Component = findNextComponentAndCreatPinList( DrawList, sheet ); if( Component == NULL ) break; @@ -1310,7 +1377,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) fprintf( f, "\n" ); - s_SortedComponentPinList.clear(); + m_SortedComponentPinList.clear(); WriteListOfNetsCADSTAR( f, g_NetObjectslist ); @@ -1326,7 +1393,7 @@ static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f ) *. B U1 100 * 6 CA */ -static void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) +void NETLIST_HELP::WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList ) { wxString InitNetDesc = StartLine + wxT( "ADD_TER" ); wxString StartNetDesc = StartLine + wxT( "TER" ); diff --git a/eeschema/netlist.cpp b/eeschema/netlist.cpp index e2af3fd5bb..f9a1dc7b0c 100644 --- a/eeschema/netlist.cpp +++ b/eeschema/netlist.cpp @@ -18,7 +18,7 @@ // Buffer to build the list of items used in netlist and erc calculations NETLIST_OBJECT_LIST g_NetObjectslist; -//#define NETLIST_DEBUG +#define NETLIST_DEBUG static void PropageNetCode( int OldNetCode, int NewNetCode, int IsBus ); static void SheetLabelConnect( NETLIST_OBJECT* SheetLabel ); diff --git a/include/common.h b/include/common.h index 1953d5c344..2d53cea399 100644 --- a/include/common.h +++ b/include/common.h @@ -382,4 +382,4 @@ void MyFree( void* pt_mem ); void* MyZMalloc( size_t nb_octets ); void* MyMalloc( size_t nb_octets ); -#endif /* __INCLUDE__COMMON_H__ */ +#endif // __INCLUDE__COMMON_H__ diff --git a/include/kicad_string.h b/include/kicad_string.h index e89bc168a6..acc9f82a99 100644 --- a/include/kicad_string.h +++ b/include/kicad_string.h @@ -79,5 +79,27 @@ bool WildCompareString( const wxString& pattern, */ char* to_point( char* Text ); +/** + * Function RefDesStringCompare + * acts just like the strcmp function but treats numbers within the string text + * correctly for sorting. eg. A10 > A2 + * return -1 if first string is less than the second + * return 0 if the strings are equal + * return 1 if the first string is greater than the second + */ +int RefDesStringCompare( const wxString& lhs, const wxString& rhs ); -#endif /* __INCLUDE__KICAD_STRING_H__ */ +/** + * Function SplitString + * breaks a string into three parts. + * The alphabetic preamble + * The numeric part + * Any alphabetic ending + * For example C10A is split to C 10 A + */ +int SplitString( wxString strToSplit, + wxString* strBeginning, + wxString* strDigits, + wxString* strEnd ); + +#endif // __INCLUDE__KICAD_STRING_H__ diff --git a/include/macros.h b/include/macros.h index 0c7b5fd9c3..5c38c3f00c 100644 --- a/include/macros.h +++ b/include/macros.h @@ -16,20 +16,22 @@ /** * Function GetChars - * returns a pointer to the actual character data, either 8 or - * 16 bits wide, depending on how the wxWidgets library was compiled. + * returns a wxChar* to the actual character data within a wxString, and is + * helpful for passing strings to wxString::Printf(wxT("%s"), GetChars(wxString) ) + *

+ * wxChar is defined to be

    + *
  • standard C style char when wxUSE_UNICODE==0
  • + *
  • wchar_t when wxUSE_UNICODE==1 (the default).
  • + *
      + * i.e. it depends on how the wxWidgets library was compiled. There was a period + * during the development of wxWidgets 2.9 when GetData() was missing, so this + * function was used to provide insulation from that design change. It may + * no longer be needed, and is harmless. GetData() seems to be an acceptable + * alternative in all cases now. */ -static inline const wxChar* GetChars( wxString s ) +static inline const wxChar* GetChars( const wxString& s ) { #if wxCHECK_VERSION( 2, 9, 0 ) - -/* To be Fixed: - * Currently, access to the actual character data in