kicad/eeschema/netform.cpp

1284 lines
41 KiB
C++
Raw Normal View History

/*****************************/
/* Net list generation code. */
/*****************************/
#include "fctsys.h"
#include <wx/xml/xml.h>
#include "gr_basic.h"
#include "common.h"
#include "confirm.h"
#include "kicad_string.h"
#include "gestfich.h"
#include "appl_wxstruct.h"
#include "program.h"
#include "general.h"
#include "netlist.h"
#include "protos.h"
#include "class_library.h"
#include "class_pin.h"
#include "build_version.h"
/**
* @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,
2007-09-21 13:23:51 +00:00
bool with_pcbnew );
2007-09-21 13:23:51 +00:00
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 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* 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 <set>
/**
* 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<wxString> 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
* 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
* if false, use net numbers (net codes)
* bool aUse_netnames is used only for Spice netlist
* @return true if success.
2007-09-21 13:23:51 +00:00
*/
bool WinEDA_SchematicFrame::WriteNetListFile( int aFormat, const wxString& aFullFileName,
bool aUse_netnames )
{
bool ret = true;
FILE* f = NULL;
2007-09-21 13:23:51 +00:00
if( aFormat < NET_TYPE_CUSTOM1 )
2007-09-21 13:23:51 +00:00
{
if( ( f = wxFopen( aFullFileName, wxT( "wt" ) ) ) == NULL )
2007-09-21 13:23:51 +00:00
{
wxString msg = _( "Failed to create file " ) + aFullFileName;
DisplayError( this, msg );
return false;
2007-09-21 13:23:51 +00:00
}
}
wxBusyCursor Busy;
switch( aFormat )
2007-09-21 13:23:51 +00:00
{
case NET_TYPE_PCBNEW:
ret = WriteNetListPCBNEW( this, f, TRUE );
2007-09-21 13:23:51 +00:00
fclose( f );
break;
case NET_TYPE_ORCADPCB2:
ret = WriteNetListPCBNEW( this, f, FALSE );
2007-09-21 13:23:51 +00:00
fclose( f );
break;
case NET_TYPE_CADSTAR:
WriteNetListCADSTAR( this, f );
2007-09-21 13:23:51 +00:00
fclose( f );
break;
case NET_TYPE_SPICE:
WriteNetListPspice( this, f, aUse_netnames );
2007-09-21 13:23:51 +00:00
fclose( f );
break;
default:
{
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() );
}
2007-09-21 13:23:51 +00:00
break;
}
return ret;
}
/* Find a "suitable" component from the DrawList
2007-09-21 13:23:51 +00:00
* 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)
2007-09-21 13:23:51 +00:00
* Must be deallocated by the user
*/
static SCH_COMPONENT* FindNextComponentAndCreatPinList( EDA_BaseStruct* item,
SCH_SHEET_PATH* path )
{
s_SortedComponentPinList.clear();
// continue searching from the middle of a linked list
for( ; item; item = item->Next() )
2007-09-21 13:23:51 +00:00
{
if( item->Type() != TYPE_SCH_COMPONENT )
2007-09-21 13:23:51 +00:00
continue;
// 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 */
2008-03-20 01:50:21 +00:00
// removed because with multiple instances of one schematic
// (several sheets pointing to 1 screen), this will be erroneously be
// toggled.
2007-09-21 13:23:51 +00:00
LIB_COMPONENT* entry = CMP_LIBRARY::FindLibraryComponent( comp->m_ChipName );
if( !entry )
2007-09-21 13:23:51 +00:00
continue;
// Multi parts per package: test if already visited:
if( entry->GetPartCount() > 1 )
{
if( s_ReferencesAlreadyFound.Lookup( ref ) )
continue;
}
if( entry->GetPartCount() <= 1 ) // One part per package
2007-09-21 13:23:51 +00:00
{
LIB_PIN_LIST pins;
entry->GetPins( pins, comp->GetUnitSelection( path ), comp->m_Convert );
for( size_t i = 0; i < pins.size(); i++ )
2007-09-21 13:23:51 +00:00
{
LIB_PIN* pin = pins[i];
wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE );
AddPinToComponentPinList( comp, path, pin );
2007-09-21 13:23:51 +00:00
}
}
else // Multiple parts per package: Collect all parts and pins for
// this reference
FindAllsInstancesOfComponent( comp, entry, path );
2007-09-21 13:23:51 +00:00
// Sort pins in s_SortedComponentPinList by pin number
sort( s_SortedComponentPinList.begin(),
s_SortedComponentPinList.end(), SortPinsByNum );
2007-09-21 13:23:51 +00:00
// Remove duplicate Pins in s_SortedComponentPinList
EraseDuplicatePins( s_SortedComponentPinList );
2007-09-21 13:23:51 +00:00
return comp;
2007-09-21 13:23:51 +00:00
}
return NULL;
}
2007-09-21 13:23:51 +00:00
/* Return the net name for the pin Pin.
2007-09-21 13:23:51 +00:00
* 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 )
{
2007-10-13 06:18:44 +00:00
int netcode = Pin->GetNet();
2007-09-21 13:23:51 +00:00
wxString NetName;
if( ( netcode == 0 ) || ( Pin->m_FlagOfConnection != PAD_CONNECT ) )
2007-09-21 13:23:51 +00:00
return NetName;
NETLIST_OBJECT* netref = Pin->m_NetNameCandidate;
if( netref )
NetName = netref->m_Label;
2007-09-21 13:23:51 +00:00
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 ) )
2007-09-21 13:23:51 +00:00
{
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;
2007-09-21 13:23:51 +00:00
}
}
else
{
NetName.Printf( DefaultFormatNetname.GetData(), netcode );
}
2007-09-21 13:23:51 +00:00
return NetName;
}
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
2007-09-21 13:23:51 +00:00
* to change the netlist syntax and create the file
*/
bool Write_GENERIC_NetList( WinEDA_SchematicFrame* frame, const wxString& aOutFileName )
{
#if 1
// output the XML format netlist.
wxXmlDocument xdoc;
// tree markers or walkers
wxXmlNode* xroot; // root node
wxXmlNode* xcomps; // start of components
wxString timeStamp;
// 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() )
{
for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() )
{
SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( schItem, path );
if( !comp )
break; // No component left
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 )
{
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 );
}
}
// @todo add: libsource + sheetpath
}
}
// @todo generate the nested <libpart> s
xroot->AddChild( Node( wxT("libparts") ) );
2007-09-21 13:23:51 +00:00
// @todo generate the nested <net>s
xroot->AddChild( Node( wxT("nets") ) );
2007-09-21 13:23:51 +00:00
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 )
2007-09-21 13:23:51 +00:00
{
wxString msg = _( "Failed to create file " ) + aOutFileName;
2007-09-21 13:23:51 +00:00
DisplayError( frame, msg );
return false;
2007-09-21 13:23:51 +00:00
}
s_ReferencesAlreadyFound.Clear();
2007-09-21 13:23:51 +00:00
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() )
2008-03-20 01:50:21 +00:00
{
for( EDA_BaseStruct* schItem = path->LastDrawList(); schItem; schItem = schItem->Next() )
2008-03-20 01:50:21 +00:00
{
SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( schItem, path );
if( !comp )
break; // No component left
2007-09-21 13:23:51 +00:00
schItem = comp;
footprint.Empty();
if( !comp->GetField( FOOTPRINT )->IsVoid() )
2007-09-21 13:23:51 +00:00
{
footprint = comp->GetField( FOOTPRINT )->m_Text;
footprint.Replace( wxT( " " ), wxT( "_" ) );
2007-09-21 13:23:51 +00:00
}
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 ) );
2007-09-21 13:23:51 +00:00
field = wxT( "Reference=" ) + comp->GetRef( path ) + wxT( "\n" );
field.Replace( wxT( " " ), wxT( "_" ) );
ret |= fputs( CONV_TO_UTF8( field ), out );
2007-09-21 13:23:51 +00:00
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 ) );
2007-09-21 13:23:51 +00:00
// Write pin list:
ret |= fprintf( out, "$BeginPinList\n" );
for( unsigned ii = 0; ii < s_SortedComponentPinList.size(); ii++ )
2007-09-21 13:23:51 +00:00
{
NETLIST_OBJECT* Pin = s_SortedComponentPinList[ii];
2007-09-21 13:23:51 +00:00
if( !Pin )
continue;
2007-09-21 13:23:51 +00:00
netname = ReturnPinNetName( Pin, wxT( "$-%.6d" ) );
if( netname.IsEmpty() )
netname = wxT( "?" );
ret |= fprintf( out, "%.4s=%s\n", (char*) &Pin->m_PinNum, CONV_TO_UTF8( netname ) );
2007-09-21 13:23:51 +00:00
}
ret |= fprintf( out, "$EndPinList\n" );
ret |= fprintf( out, "$EndComponent\n" );
2007-09-21 13:23:51 +00:00
}
}
ret |= fprintf( out, "$EndComponentList\n" );
2007-09-21 13:23:51 +00:00
ret |= fprintf( out, "\n$BeginNets\n" );
2007-09-21 13:23:51 +00:00
if( !WriteGENERICListOfNets( out, g_NetObjectslist ) )
ret = -1;
2007-09-21 13:23:51 +00:00
ret |= fprintf( out, "$EndNets\n" );
2007-09-21 13:23:51 +00:00
ret |= fprintf( out, "\n$EndNetlist\n" );
ret |= fclose( out );
2007-09-21 13:23:51 +00:00
return ret >= 0;
#endif
}
2007-09-21 13:23:51 +00:00
/* Routine generation of the netlist file (Format PSPICE)
* = TRUE if use_netnames
* Nodes are identified by the netname
* If the nodes are identified by the netnumber
2008-03-20 01:50:21 +00:00
*
* All graphics text commentary by a [.-+] PSpice or [.-+] gnucap
* Are considered in placing orders in the netlist
* [.-] Or PSpice gnucap are beginning
* + + Gnucap and PSpice are ultimately NetList
2007-09-21 13:23:51 +00:00
*/
static void WriteNetListPspice( WinEDA_SchematicFrame* frame, FILE* f, bool use_netnames )
{
char Line[1024];
SCH_SHEET_PATH* sheet;
EDA_BaseStruct* DrawList;
SCH_COMPONENT* Component;
int nbitems;
wxString text;
wxArrayString SpiceCommandAtBeginFile, SpiceCommandAtEndFile;
wxString msg;
2007-09-21 13:23:51 +00:00
#define BUFYPOS_LEN 4
wxChar bufnum[BUFYPOS_LEN + 1];
2007-09-21 13:23:51 +00:00
DateAndTime( Line );
fprintf( f,
"* %s (Spice format) creation date: %s\n\n",
NETLIST_HEAD_STRING,
Line );
/* Create text list starting by [.-]pspice , or [.-]gnucap (simulator
* commands) and create text list starting by [+]pspice , or [+]gnucap
* (simulator commands) */
2007-09-21 13:23:51 +00:00
bufnum[BUFYPOS_LEN] = 0;
SCH_SHEET_LIST SheetList;
2007-09-21 13:23:51 +00:00
for( sheet = SheetList.GetFirst();
sheet != NULL;
sheet = SheetList.GetNext() )
2007-09-21 13:23:51 +00:00
{
for( DrawList = sheet->LastDrawList();
DrawList != NULL;
DrawList = DrawList->Next() )
2007-09-21 13:23:51 +00:00
{
wxChar ident;
2008-03-20 01:50:21 +00:00
if( DrawList->Type() != TYPE_SCH_TEXT )
2007-09-21 13:23:51 +00:00
continue;
2008-03-20 01:50:21 +00:00
#define DRAWTEXT ( (SCH_TEXT*) DrawList )
text = DRAWTEXT->m_Text; if( text.IsEmpty() )
2007-09-21 13:23:51 +00:00
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.
2008-06-18 09:18:51 +00:00
text.MakeLower();
2007-09-21 13:23:51 +00:00
if( ( text == wxT( "pspice" ) ) || ( text == wxT( "gnucap" ) ) )
{
/* Put the Y position as an ascii string, for sort by vertical
* position, using usual sort string by alphabetic value */
2007-09-21 13:23:51 +00:00
int ypos = DRAWTEXT->m_Pos.y;
for( int ii = 0; ii < BUFYPOS_LEN; ii++ )
2007-09-21 13:23:51 +00:00
{
bufnum[BUFYPOS_LEN - 1 -
ii] = (ypos & 63) + ' '; ypos >>= 6;
2007-09-21 13:23:51 +00:00
}
text = DRAWTEXT->m_Text.AfterFirst( ' ' );
// First BUFYPOS_LEN char are the Y position.
msg.Printf( wxT( "%s %s" ), bufnum, text.GetData() );
2007-09-21 13:23:51 +00:00
if( ident == '+' )
SpiceCommandAtEndFile.Add( msg );
else
SpiceCommandAtBeginFile.Add( msg );
}
}
}
/* Print texts starting by [.-]pspice , ou [.-]gnucap (of course, without
* the Y position string)*/
2007-09-21 13:23:51 +00:00
nbitems = SpiceCommandAtBeginFile.GetCount();
if( nbitems )
{
SpiceCommandAtBeginFile.Sort();
for( int ii = 0; ii < nbitems; ii++ )
2007-09-21 13:23:51 +00:00
{
SpiceCommandAtBeginFile[ii].Remove( 0, BUFYPOS_LEN );
SpiceCommandAtBeginFile[ii].Trim( TRUE );
SpiceCommandAtBeginFile[ii].Trim( FALSE );
fprintf( f, "%s\n", CONV_TO_UTF8( SpiceCommandAtBeginFile[ii] ) );
}
}
fprintf( f, "\n" );
// Create component list
s_ReferencesAlreadyFound.Clear();
2007-09-21 13:23:51 +00:00
for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
2007-09-21 13:23:51 +00:00
{
for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() )
2007-09-21 13:23:51 +00:00
{
DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet );
2007-09-21 13:23:51 +00:00
if( Component == NULL )
break;
fprintf( f, "%s ", CONV_TO_UTF8( Component->GetRef( sheet ) ) );
2007-09-21 13:23:51 +00:00
// Write pin list:
for( unsigned ii = 0; ii < s_SortedComponentPinList.size(); ii++ )
2007-09-21 13:23:51 +00:00
{
NETLIST_OBJECT* Pin = s_SortedComponentPinList[ii];
2007-09-21 13:23:51 +00:00
if( !Pin )
continue;
wxString NetName = ReturnPinNetName( Pin, wxT( "N-%.6d" ) );
2007-09-21 13:23:51 +00:00
if( NetName.IsEmpty() )
NetName = wxT( "?" );
if( use_netnames )
fprintf( f, " %s", CONV_TO_UTF8( NetName ) );
else // Use number for net names (with net number = 0 for
// "GND"
2007-09-21 13:23:51 +00:00
{
// NetName = "0" is "GND" net for Spice
if( NetName == wxT( "0" ) || NetName == wxT( "GND" ) )
fprintf( f, " 0" );
else
2007-10-13 06:18:44 +00:00
fprintf( f, " %d", Pin->GetNet() );
2007-09-21 13:23:51 +00:00
}
}
fprintf( f, " %s\n",
CONV_TO_UTF8( Component->GetField( VALUE )->m_Text ) );
2007-09-21 13:23:51 +00:00
}
}
s_SortedComponentPinList.clear();
2007-09-21 13:23:51 +00:00
/* Print texts starting by [+]pspice , ou [+]gnucap */
nbitems = SpiceCommandAtEndFile.GetCount();
if( nbitems )
{
fprintf( f, "\n" );
SpiceCommandAtEndFile.Sort();
for( int ii = 0; ii < nbitems; ii++ )
2007-09-21 13:23:51 +00:00
{
SpiceCommandAtEndFile[ii].Remove( 0, +BUFYPOS_LEN );
SpiceCommandAtEndFile[ii].Trim( TRUE );
SpiceCommandAtEndFile[ii].Trim( FALSE );
fprintf( f, "%s\n", CONV_TO_UTF8( SpiceCommandAtEndFile[ii] ) );
}
}
fprintf( f, "\n.end\n" );
}
2007-09-21 13:23:51 +00:00
/* 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
2007-09-21 13:23:51 +00:00
*/
static bool WriteNetListPCBNEW( WinEDA_SchematicFrame* frame, FILE* f, bool with_pcbnew )
{
wxString Line;
wxString footprint;
char dateBuf[256];
int ret = 0; // zero now, OR in the sign bit on error
std::vector<OBJ_CMP_TO_LIST> cmpList;
DateAndTime( dateBuf );
2007-09-21 13:23:51 +00:00
if( with_pcbnew )
ret |= fprintf( f, "# %s created %s\n(\n", NETLIST_HEAD_STRING, dateBuf );
2007-09-21 13:23:51 +00:00
else
ret |= fprintf( f, "( { %s created %s }\n", NETLIST_HEAD_STRING, dateBuf );
2007-09-21 13:23:51 +00:00
// Create netlist module section
2007-09-21 13:23:51 +00:00
s_ReferencesAlreadyFound.Clear();
2007-09-21 13:23:51 +00:00
SCH_SHEET_LIST sheetList;
2007-09-21 13:23:51 +00:00
for( SCH_SHEET_PATH* path = sheetList.GetFirst(); path; path = sheetList.GetNext() )
2007-09-21 13:23:51 +00:00
{
for( EDA_BaseStruct* item = path->LastDrawList(); item; item = item->Next() )
2007-09-21 13:23:51 +00:00
{
SCH_COMPONENT* comp = FindNextComponentAndCreatPinList( item, path );
if( !comp )
2007-09-21 13:23:51 +00:00
break;
item = comp;
// 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 )
2007-09-21 13:23:51 +00:00
{
if( entry->m_FootprintList.GetCount() != 0 ) // Put in list
2007-09-21 13:23:51 +00:00
{
cmpList.push_back( OBJ_CMP_TO_LIST() );
cmpList.back().m_RootCmp = comp;
cmpList.back().SetRef( comp->GetRef( path ) );
2007-09-21 13:23:51 +00:00
}
}
if( !comp->GetField( FOOTPRINT )->IsVoid() )
2007-09-21 13:23:51 +00:00
{
footprint = comp->GetField( FOOTPRINT )->m_Text;
footprint.Replace( wxT( " " ), wxT( "_" ) );
2007-09-21 13:23:51 +00:00
}
else
footprint = wxT( "$noname" );
2007-09-21 13:23:51 +00:00
Line = comp->GetRef( path );
2007-09-21 13:23:51 +00:00
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;
2007-09-21 13:23:51 +00:00
Line.Replace( wxT( " " ), wxT( "_" ) );
ret |= fprintf( f, " %s", CONV_TO_UTF8( Line ) );
2007-09-21 13:23:51 +00:00
if( with_pcbnew ) // Add the lib name for this component
{
Line = comp->m_ChipName;
2007-09-21 13:23:51 +00:00
Line.Replace( wxT( " " ), wxT( "_" ) );
ret |= fprintf( f, " {Lib=%s}", CONV_TO_UTF8( Line ) );
2007-09-21 13:23:51 +00:00
}
ret |= fprintf( f, "\n" );
2007-09-21 13:23:51 +00:00
// Write pin list:
for( unsigned ii = 0; ii < s_SortedComponentPinList.size(); ii++ )
2007-09-21 13:23:51 +00:00
{
NETLIST_OBJECT* pin = s_SortedComponentPinList[ii];
if( !pin )
2007-09-21 13:23:51 +00:00
continue;
wxString netname = ReturnPinNetName( pin, wxT( "N-%.6d" ) );
2007-09-21 13:23:51 +00:00
if( netname.IsEmpty() )
netname = wxT( "?" );
netname.Replace( wxT( " " ), wxT( "_" ) );
ret |= fprintf( f, " ( %4.4s %s )\n", (char*) &pin->m_PinNum,
CONV_TO_UTF8( netname ) );
2007-09-21 13:23:51 +00:00
}
ret |= fprintf( f, " )\n" );
2007-09-21 13:23:51 +00:00
}
}
ret |= fprintf( f, ")\n*\n" );
2007-09-21 13:23:51 +00:00
s_SortedComponentPinList.clear();
2007-09-21 13:23:51 +00:00
// Write the allowed footprint list for each component
if( with_pcbnew && cmpList.size() )
2007-09-21 13:23:51 +00:00
{
wxString ref;
ret |= fprintf( f, "{ Allowed footprints by component:\n" );
for( unsigned ii = 0; ii < cmpList.size(); ii++ )
2007-09-21 13:23:51 +00:00
{
SCH_COMPONENT* comp = cmpList[ii].m_RootCmp;
LIB_COMPONENT* entry = CMP_LIBRARY::FindLibraryComponent( comp->m_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++ )
2007-09-21 13:23:51 +00:00
{
ret |= fprintf( f, " %s\n",
CONV_TO_UTF8( entry->m_FootprintList[jj] ) );
2007-09-21 13:23:51 +00:00
}
ret |= fprintf( f, "$endlist\n" );
2007-09-21 13:23:51 +00:00
}
ret |= fprintf( f, "$endfootprintlist\n}\n" );
2007-09-21 13:23:51 +00:00
}
if( with_pcbnew )
{
ret |= fprintf( f, "{ Pin List by Nets\n" );
if( !WriteGENERICListOfNets( f, g_NetObjectslist ) )
ret = -1;
ret |= fprintf( f, "}\n" );
ret |= fprintf( f, "#End\n" );
2007-09-21 13:23:51 +00:00
}
return ret >= 0;
}
/*
* Add a new pin description in the pin list s_SortedComponentPinList
* a pin description is a pointer to the corresponding structure
* created by BuildNetList() in the table g_NetObjectslist
*/
2008-03-20 01:50:21 +00:00
static void AddPinToComponentPinList( SCH_COMPONENT* Component,
SCH_SHEET_PATH* sheetlist, LIB_PIN* Pin )
{
// Search the PIN description for Pin in g_NetObjectslist
for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ )
2007-09-21 13:23:51 +00:00
{
if( g_NetObjectslist[ii]->m_Type != NET_PIN )
2007-09-21 13:23:51 +00:00
continue;
if( g_NetObjectslist[ii]->m_Link != Component )
2007-09-21 13:23:51 +00:00
continue;
if( g_NetObjectslist[ii]->m_SheetList != *sheetlist )
2008-03-20 01:50:21 +00:00
continue;
if( g_NetObjectslist[ii]->m_PinNum != Pin->m_PinNum )
2007-09-21 13:23:51 +00:00
continue;
s_SortedComponentPinList.push_back( g_NetObjectslist[ii] );
if( s_SortedComponentPinList.size() >= MAXPIN )
2007-09-21 13:23:51 +00:00
{
// Log message for Internal error
DisplayError( NULL, wxT( "AddPinToComponentPinList err: MAXPIN reached" ) );
return;
2007-09-21 13:23:51 +00:00
}
}
}
/** Function EraseDuplicatePins
* Function to remove duplicate Pins in the TabPin pin list
* (This is a list of pins found in the whole schematic, for a given
* component)
* These duplicate pins were put in list because some pins (powers... )
* are found more than one time when we have a multiple parts per package
* component
* for instance, a 74ls00 has 4 parts, and therefore the VCC pin and GND pin
* appears 4 times
* in the list.
* @param aPinList = a NETLIST_OBJECT_LIST that contains the list of pins for a
* given component.
* Note: this list *MUST* be sorted by pin number (.m_PinNum member value)
2007-09-21 13:23:51 +00:00
*/
static void EraseDuplicatePins( NETLIST_OBJECT_LIST& aPinList )
{
if( aPinList.size() == 0 ) // Trivial case: component with no pin
return;
for( unsigned ii = 0; ii < aPinList.size(); ii++ )
2007-09-21 13:23:51 +00:00
{
if( aPinList[ii] == NULL ) /* already deleted */
2007-09-21 13:23:51 +00:00
continue;
/* Search for duplicated pins
* If found, remove duplicates. The priority is to keep connected pins
* and remove unconnected
* - So this allows (for instance when using multi op amps per package
* - to connect only one op amp to power
* Because the pin list is sorted by m_PinNum value, duplicated pins
* are necessary successive in list
*/
int idxref = ii;
for( unsigned jj = ii + 1; jj < aPinList.size(); jj++ )
2007-09-21 13:23:51 +00:00
{
if( aPinList[jj] == NULL ) // Already removed
continue;
// other pin num end of duplicate list.
if( aPinList[idxref]->m_PinNum != aPinList[jj]->m_PinNum )
2007-09-21 13:23:51 +00:00
break;
if( aPinList[idxref]->m_FlagOfConnection == PAD_CONNECT )
aPinList[jj] = NULL;
else /* the reference pin is not connected: remove this pin if the
* other pin is connected */
{
if( aPinList[jj]->m_FlagOfConnection == PAD_CONNECT )
{
aPinList[idxref] = NULL;
idxref = jj;
}
else // the 2 pins are not connected: remove the tested pin,
// and continue ...
aPinList[jj] = NULL;
}
2007-09-21 13:23:51 +00:00
}
}
}
/**
* 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
2007-09-21 13:23:51 +00:00
*/
static void FindAllsInstancesOfComponent( SCH_COMPONENT* Component_in,
LIB_COMPONENT* aEntry,
SCH_SHEET_PATH* Sheet_in )
{
EDA_BaseStruct* SchItem;
2008-03-20 01:50:21 +00:00
SCH_COMPONENT* Component2;
LIB_PIN* pin;
SCH_SHEET_PATH* sheet;
wxString str, Reference = Component_in->GetRef( Sheet_in );
2007-09-21 13:23:51 +00:00
SCH_SHEET_LIST SheetList;
for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
2007-09-21 13:23:51 +00:00
{
for( SchItem = sheet->LastDrawList(); SchItem; SchItem = SchItem->Next() )
2007-09-21 13:23:51 +00:00
{
if( SchItem->Type() != TYPE_SCH_COMPONENT )
continue;
2007-09-21 13:23:51 +00:00
Component2 = (SCH_COMPONENT*) SchItem;
2008-03-20 01:50:21 +00:00
str = Component2->GetRef( sheet );
if( str.CmpNoCase( Reference ) != 0 )
continue;
2007-09-21 13:23:51 +00:00
if( aEntry == NULL )
continue;
for( pin = aEntry->GetNextPin(); pin != NULL; pin = aEntry->GetNextPin( pin ) )
{
wxASSERT( pin->Type() == COMPONENT_PIN_DRAW_TYPE );
if( pin->m_Unit
&& ( pin->m_Unit != Component2->GetUnitSelection( sheet ) ) )
continue;
if( pin->m_Convert
&& ( pin->m_Convert != Component2->m_Convert ) )
continue;
// A suitable pin in found: add it to the current list
AddPinToComponentPinList( Component2, sheet, pin );
2007-09-21 13:23:51 +00:00
}
}
}
}
/*
* Comparison routine for sorting by pin numbers.
2007-09-21 13:23:51 +00:00
*/
static bool SortPinsByNum( NETLIST_OBJECT* Pin1, NETLIST_OBJECT* Pin2 )
{
2007-09-21 13:23:51 +00:00
int Num1, Num2;
char Line[5];
Num1 = Pin1->m_PinNum;
Num2 = Pin2->m_PinNum;
Line[4] = 0;
memcpy( Line, &Num1, 4 ); Num1 = atoi( Line );
2007-09-21 13:23:51 +00:00
memcpy( Line, &Num2, 4 ); Num2 = atoi( Line );
return Num1 < Num2;
}
2007-09-21 13:23:51 +00:00
/* Written in the file / net list (ranked by Netcode), and elements that are
* connected
2007-09-21 13:23:51 +00:00
*/
static bool WriteGENERICListOfNets( FILE* f, NETLIST_OBJECT_LIST& aObjectsList )
{
int ret = 0;
int netCode;
int lastNetCode = -1;
int sameNetcodeCount = 0;
wxString netName;
wxString ref;
wxString netcodeName;
char firstItemInNet[256];
2007-09-21 13:23:51 +00:00
for( unsigned ii = 0; ii < aObjectsList.size(); ii++ )
2007-09-21 13:23:51 +00:00
{
SCH_COMPONENT* comp;
// New net found, write net id;
if( ( netCode = aObjectsList[ii]->GetNet() ) != lastNetCode )
2007-09-21 13:23:51 +00:00
{
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;
2007-09-21 13:23:51 +00:00
netcodeName.Printf( wxT( "Net %d " ), netCode );
netcodeName += wxT( "\"" );
if( !netName.IsEmpty() )
2007-09-21 13:23:51 +00:00
{
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();
2008-03-20 01:50:21 +00:00
}
netcodeName += netName;
2007-09-21 13:23:51 +00:00
}
netcodeName += wxT( "\"" );
// Add the netname without prefix, in cases we need only the
// "short" netname
netcodeName += wxT( " \"" ) + netName + wxT( "\"" );
lastNetCode = netCode;
2007-09-21 13:23:51 +00:00
}
if( aObjectsList[ii]->m_Type != NET_PIN )
2007-09-21 13:23:51 +00:00
continue;
comp = (SCH_COMPONENT*) aObjectsList[ii]->m_Link;
// Get the reference for the net name and the main parent component
ref = comp->GetRef( &aObjectsList[ii]->m_SheetList );
if( ref[0] == wxChar( '#' ) )
continue; // Pseudo component (Like Power symbol)
2007-09-21 13:23:51 +00:00
// 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 )
2007-09-21 13:23:51 +00:00
{
snprintf( firstItemInNet, sizeof(firstItemInNet), " %s %.4s\n",
CONV_TO_UTF8( ref ),
(const char*) &aObjectsList[ii]->m_PinNum );
2007-09-21 13:23:51 +00:00
}
// Second item for this net found, print the Net name, and the
// first item
if( sameNetcodeCount == 2 )
2007-09-21 13:23:51 +00:00
{
ret |= fprintf( f, "%s\n", CONV_TO_UTF8( netcodeName ) );
ret |= fputs( firstItemInNet, f );
2007-09-21 13:23:51 +00:00
}
if( sameNetcodeCount >= 2 )
ret |= fprintf( f, " %s %.4s\n", CONV_TO_UTF8( ref ),
(const char*) &aObjectsList[ii]->m_PinNum );
2007-09-21 13:23:51 +00:00
}
return ret >= 0;
}
/* Generate CADSTAR net list. */
2007-09-21 13:23:51 +00:00
wxString StartLine( wxT( "." ) );
/* Routine generation of the netlist file (CADSTAR Format)
* Header:
* HEA ..
* TIM .. 2004 07 29 16 22 17
* APA .. "Cadstar RINF Output - Version 6.0.2.3"
* INCH UNI .. 1000.0 in
* FULL TYP ..
2008-03-20 01:50:21 +00:00
*
* List of components:
* .. ADD_COM X1 "CNT D41612 (48pts CONTOUR TM)"
* .. ADD_COM U2 "74HCT245D" "74HCT245D"
2008-03-20 01:50:21 +00:00
*
* Connections:
* .. ADD_TER RR2 * 6 "$ 42"
* .. B U1 100
* 6 CA
2008-03-20 01:50:21 +00:00
*
* ADD_TER .. U2 * 6 "$ 59"
* .. B * U7 39
* U6 17
* U1 * 122
2008-03-20 01:50:21 +00:00
*
* .. ADD_TER P2 * 1 "$ 9"
* .. B * T3 1
*U1 * 14
2007-09-21 13:23:51 +00:00
*/
static void WriteNetListCADSTAR( WinEDA_SchematicFrame* frame, FILE* f )
{
2007-09-21 13:23:51 +00:00
wxString StartCmpDesc = StartLine + wxT( "ADD_COM" );
wxString msg;
wxString footprint;
2007-09-21 13:23:51 +00:00
char Line[1024];
SCH_SHEET_PATH* sheet;
2007-09-21 13:23:51 +00:00
EDA_BaseStruct* DrawList;
2008-03-20 01:50:21 +00:00
SCH_COMPONENT* Component;
wxString Title = wxGetApp().GetAppName() + wxT( " " ) + GetBuildVersion();
2007-09-21 13:23:51 +00:00
fprintf( f, "%sHEA\n", CONV_TO_UTF8( StartLine ) );
DateAndTime( Line );
fprintf( f, "%sTIM %s\n", CONV_TO_UTF8( StartLine ), Line );
fprintf( f, "%sAPP ", CONV_TO_UTF8( StartLine ) );
fprintf( f, "\"%s\"\n", CONV_TO_UTF8( Title ) );
fprintf( f, "\n" );
// Create netlist module section
s_ReferencesAlreadyFound.Clear();
SCH_SHEET_LIST SheetList;
2007-09-21 13:23:51 +00:00
for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() )
2007-09-21 13:23:51 +00:00
{
for( DrawList = sheet->LastDrawList(); DrawList != NULL; DrawList = DrawList->Next() )
2007-09-21 13:23:51 +00:00
{
DrawList = Component = FindNextComponentAndCreatPinList( DrawList, sheet );
2007-09-21 13:23:51 +00:00
if( Component == NULL )
break;
/*
doing nothing with footprint
if( !Component->GetField( FOOTPRINT )->IsVoid() )
2007-09-21 13:23:51 +00:00
{
footprint = Component->GetField( FOOTPRINT )->m_Text;
footprint.Replace( wxT( " " ), wxT( "_" ) );
2007-09-21 13:23:51 +00:00
}
else
footprint = wxT( "$noname" );
*/
2007-09-21 13:23:51 +00:00
msg = Component->GetRef( sheet );
2007-09-21 13:23:51 +00:00
fprintf( f, "%s ", CONV_TO_UTF8( StartCmpDesc ) );
fprintf( f, "%s", CONV_TO_UTF8( msg ) );
msg = Component->GetField( VALUE )->m_Text;
2007-09-21 13:23:51 +00:00
msg.Replace( wxT( " " ), wxT( "_" ) );
fprintf( f, " \"%s\"", CONV_TO_UTF8( msg ) );
fprintf( f, "\n" );
}
}
fprintf( f, "\n" );
s_SortedComponentPinList.clear();
2007-09-21 13:23:51 +00:00
WriteListOfNetsCADSTAR( f, g_NetObjectslist );
2007-09-21 13:23:51 +00:00
fprintf( f, "\n%sEND\n", CONV_TO_UTF8( StartLine ) );
}
2007-09-21 13:23:51 +00:00
/*
* Written in the file / net list (ranked by Netcode), and
* Pins connected to it
* Format:
*. ADD_TER RR2 6 "$ 42"
*. B U1 100
* 6 CA
2007-09-21 13:23:51 +00:00
*/
static void WriteListOfNetsCADSTAR( FILE* f, NETLIST_OBJECT_LIST& aObjectsList )
{
2007-09-21 13:23:51 +00:00
wxString InitNetDesc = StartLine + wxT( "ADD_TER" );
wxString StartNetDesc = StartLine + wxT( "TER" );
wxString netcodeName, InitNetDescLine;
unsigned ii;
int print_ter = 0;
int NetCode, lastNetCode = -1;
2008-03-20 01:50:21 +00:00
SCH_COMPONENT* Cmp;
2007-09-21 13:23:51 +00:00
wxString NetName;
for( ii = 0; ii < aObjectsList.size(); ii++ )
aObjectsList[ii]->m_Flag = 0;
2007-09-21 13:23:51 +00:00
for( ii = 0; ii < g_NetObjectslist.size(); ii++ )
2007-09-21 13:23:51 +00:00
{
// Get the NetName of the current net :
if( ( NetCode = aObjectsList[ii]->GetNet() ) != lastNetCode )
2007-09-21 13:23:51 +00:00
{
NetName.Empty();
NETLIST_OBJECT* netref;
netref = aObjectsList[ii]->m_NetNameCandidate;
if( netref )
NetName = netref->m_Label;
2007-09-21 13:23:51 +00:00
netcodeName = wxT( "\"" );
2007-09-21 13:23:51 +00:00
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();
2008-03-20 01:50:21 +00:00
}
netcodeName += NetName;
2007-09-21 13:23:51 +00:00
}
else // this net has no name: create a default name $<net number>
netcodeName << wxT( "$" ) << NetCode;
netcodeName += wxT( "\"" );
lastNetCode = NetCode;
2007-09-21 13:23:51 +00:00
print_ter = 0;
}
if( aObjectsList[ii]->m_Type != NET_PIN )
2007-09-21 13:23:51 +00:00
continue;
if( aObjectsList[ii]->m_Flag != 0 )
2007-09-21 13:23:51 +00:00
continue;
Cmp = (SCH_COMPONENT*) aObjectsList[ii]->m_Link;
wxString refstr = Cmp->GetRef( &(aObjectsList[ii]->m_SheetList) );
if( refstr[0] == '#' )
continue; // Power supply symbols.
2007-09-21 13:23:51 +00:00
switch( print_ter )
{
case 0:
{
char buf[5];
wxString str_pinnum;
strncpy( buf, (char*) &aObjectsList[ii]->m_PinNum, 4 );
buf[4] = 0;
2007-09-21 13:23:51 +00:00
str_pinnum = CONV_FROM_UTF8( buf );
InitNetDescLine.Printf( wxT( "\n%s %s %.4s %s" ),
GetChars( InitNetDesc ),
GetChars( refstr ),
GetChars( str_pinnum ),
GetChars( netcodeName ) );
2007-09-21 13:23:51 +00:00
}
print_ter++;
break;
case 1:
fprintf( f, "%s\n", CONV_TO_UTF8( InitNetDescLine ) );
fprintf( f, "%s %s %.4s\n",
CONV_TO_UTF8( StartNetDesc ),
CONV_TO_UTF8( refstr ),
(char*) &aObjectsList[ii]->m_PinNum );
2007-09-21 13:23:51 +00:00
print_ter++;
break;
default:
fprintf( f, " %s %.4s\n",
CONV_TO_UTF8( refstr ),
(char*) &aObjectsList[ii]->m_PinNum );
2007-09-21 13:23:51 +00:00
break;
}
aObjectsList[ii]->m_Flag = 1;
2007-09-21 13:23:51 +00:00
// Search for redundant pins to avoid generation of the same connection
// more than once.
for( unsigned jj = ii + 1; jj < aObjectsList.size(); jj++ )
2007-09-21 13:23:51 +00:00
{
if( aObjectsList[jj]->GetNet() != NetCode )
2007-09-21 13:23:51 +00:00
break;
if( aObjectsList[jj]->m_Type != NET_PIN )
2007-09-21 13:23:51 +00:00
continue;
2008-03-20 01:50:21 +00:00
SCH_COMPONENT* tstcmp =
(SCH_COMPONENT*) aObjectsList[jj]->m_Link;
wxString p = Cmp->GetPath( &( aObjectsList[ii]->m_SheetList ) );
wxString tstp = tstcmp->GetPath( &( aObjectsList[jj]->m_SheetList ) );
if( p.Cmp( tstp ) != 0 )
2007-09-21 13:23:51 +00:00
continue;
if( aObjectsList[jj]->m_PinNum == aObjectsList[ii]->m_PinNum )
aObjectsList[jj]->m_Flag = 1;
2007-09-21 13:23:51 +00:00
}
}
}