void NETLIST_OBJECT_LIST::sheetLabelConnect( NETLIST_OBJECT* SheetLabel ) { if( SheetLabel->GetNet() == 0 ) return; for( unsigned ii = 0; ii < size(); ii++ ) { NETLIST_OBJECT* ObjetNet = GetItem( ii ); if( ObjetNet->m_SheetPath != SheetLabel->m_SheetPathInclude ) continue; //use SheetInclude, not the sheet!! if( (ObjetNet->m_Type != NET_HIERLABEL ) && (ObjetNet->m_Type != NET_HIERBUSLABELMEMBER ) ) continue; if( ObjetNet->GetNet() == SheetLabel->GetNet() ) continue; //already connected. if( ObjetNet->m_Label != SheetLabel->m_Label ) continue; //different names. // Propagate Netcode having all the objects of the same Netcode. if( ObjetNet->GetNet() ) propagateNetCode( ObjetNet->GetNet(), SheetLabel->GetNet(), IS_WIRE ); else ObjetNet->SetNet( SheetLabel->GetNet() ); } }
void NETLIST_OBJECT_LIST::propagateNetCode( int aOldNetCode, int aNewNetCode, bool aIsBus ) { if( aOldNetCode == aNewNetCode ) return; if( aIsBus == false ) // Propagate NetCode { for( unsigned jj = 0; jj < size(); jj++ ) { NETLIST_OBJECT* object = GetItem( jj ); if( object->GetNet() == aOldNetCode ) object->SetNet( aNewNetCode ); } } else // Propagate BusNetCode { for( unsigned jj = 0; jj < size(); jj++ ) { NETLIST_OBJECT* object = GetItem( jj ); if( object->m_BusNetCode == aOldNetCode ) object->m_BusNetCode = aNewNetCode; } } }
void NETLIST_OBJECT_LIST::segmentToPointConnect( NETLIST_OBJECT* aJonction, bool aIsBus, int aIdxStart ) { for( unsigned i = aIdxStart; i < size(); i++ ) { NETLIST_OBJECT* segment = GetItem( i ); // if different sheets, obviously no physical connection between elements. if( segment->m_SheetPath != aJonction->m_SheetPath ) continue; if( aIsBus == IS_WIRE ) { if( segment->m_Type != NET_SEGMENT ) continue; } else { if( segment->m_Type != NET_BUS ) continue; } if( IsPointOnSegment( segment->m_Start, segment->m_End, aJonction->m_Start ) ) { // Propagation Netcode has all the objects of the same Netcode. if( aIsBus == IS_WIRE ) { if( segment->GetNet() ) propagateNetCode( segment->GetNet(), aJonction->GetNet(), aIsBus ); else segment->SetNet( aJonction->GetNet() ); } else { if( segment->m_BusNetCode ) propagateNetCode( segment->m_BusNetCode, aJonction->m_BusNetCode, aIsBus ); else segment->m_BusNetCode = aJonction->m_BusNetCode; } } } }
void NETLIST_OBJECT_LIST::labelConnect( NETLIST_OBJECT* aLabelRef ) { if( aLabelRef->GetNet() == 0 ) return; for( unsigned i = 0; i < size(); i++ ) { NETLIST_OBJECT* item = GetItem( i ); if( item->GetNet() == aLabelRef->GetNet() ) continue; if( item->m_SheetPath != aLabelRef->m_SheetPath ) { if( item->m_Type != NET_PINLABEL && item->m_Type != NET_GLOBLABEL && item->m_Type != NET_GLOBBUSLABELMEMBER ) continue; if( (item->m_Type == NET_GLOBLABEL || item->m_Type == NET_GLOBBUSLABELMEMBER) && item->m_Type != aLabelRef->m_Type ) //global labels only connect other global labels. continue; } // NET_HIERLABEL are used to connect sheets. // NET_LABEL are local to a sheet // NET_GLOBLABEL are global. // NET_PINLABEL is a kind of global label (generated by a power pin invisible) if( item->IsLabelType() ) { if( item->m_Label != aLabelRef->m_Label ) continue; if( item->GetNet() ) propagateNetCode( item->GetNet(), aLabelRef->GetNet(), IS_WIRE ); else item->SetNet( aLabelRef->GetNet() ); } } }
void NETLIST_OBJECT_LIST::connectBusLabels() { // Propagate the net code between all bus label member objects connected by they name. // If the net code is not yet existing, a new one is created // Search is done in the entire list for( unsigned ii = 0; ii < size(); ii++ ) { NETLIST_OBJECT* Label = GetItem( ii ); if( Label->IsLabelBusMemberType() ) { if( Label->GetNet() == 0 ) { // Not yet existiing net code: create a new one. Label->SetNet( m_lastNetCode ); m_lastNetCode++; } for( unsigned jj = ii + 1; jj < size(); jj++ ) { NETLIST_OBJECT* LabelInTst = GetItem( jj ); if( LabelInTst->IsLabelBusMemberType() ) { if( LabelInTst->m_BusNetCode != Label->m_BusNetCode ) continue; if( LabelInTst->m_Member != Label->m_Member ) continue; if( LabelInTst->GetNet() == 0 ) // Append this object to the current net LabelInTst->SetNet( Label->GetNet() ); else // Merge the 2 net codes, they are connected. propagateNetCode( LabelInTst->GetNet(), Label->GetNet(), IS_WIRE ); } } } } }
void NETLIST_OBJECT_LIST::connectBusLabels() { for( unsigned ii = 0; ii < size(); ii++ ) { NETLIST_OBJECT* Label = GetItem( ii ); if( (Label->m_Type == NET_SHEETBUSLABELMEMBER) || (Label->m_Type == NET_BUSLABELMEMBER) || (Label->m_Type == NET_HIERBUSLABELMEMBER) ) { if( Label->GetNet() == 0 ) { Label->SetNet( m_lastNetCode ); m_lastNetCode++; } for( unsigned jj = ii + 1; jj < size(); jj++ ) { NETLIST_OBJECT* LabelInTst = GetItem( jj ); if( (LabelInTst->m_Type == NET_SHEETBUSLABELMEMBER) || (LabelInTst->m_Type == NET_BUSLABELMEMBER) || (LabelInTst->m_Type == NET_HIERBUSLABELMEMBER) ) { if( LabelInTst->m_BusNetCode != Label->m_BusNetCode ) continue; if( LabelInTst->m_Member != Label->m_Member ) continue; if( LabelInTst->GetNet() == 0 ) LabelInTst->SetNet( Label->GetNet() ); else propageNetCode( LabelInTst->GetNet(), Label->GetNet(), IS_WIRE ); } } } } }
XNODE* NETLIST_EXPORTER_GENERIC::makeListOfNets() { XNODE* xnets = node( wxT( "nets" ) ); // auto_ptr if exceptions ever get used. wxString netCodeTxt; wxString netName; wxString ref; wxString sNet = wxT( "net" ); wxString sName = wxT( "name" ); wxString sCode = wxT( "code" ); wxString sRef = wxT( "ref" ); wxString sPin = wxT( "pin" ); wxString sNode = wxT( "node" ); wxString sFmtd = wxT( "%d" ); XNODE* xnet = 0; int netCode; int lastNetCode = -1; int sameNetcodeCount = 0; /* output: <net code="123" name="/cfcard.sch/WAIT#"> <node ref="R23" pin="1"/> <node ref="U18" pin="12"/> </net> */ m_LibParts.clear(); // must call this function before using m_LibParts. for( unsigned ii = 0; ii < m_masterList->size(); ii++ ) { NETLIST_OBJECT* nitem = m_masterList->GetItem( ii ); SCH_COMPONENT* comp; // New net found, write net id; if( ( netCode = nitem->GetNet() ) != lastNetCode ) { sameNetcodeCount = 0; // item count for this net netName = nitem->GetNetName(); lastNetCode = netCode; } if( nitem->m_Type != NET_PIN ) continue; if( nitem->m_Flag != 0 ) // Redundant pin, skip it continue; comp = nitem->GetComponentParent(); // Get the reference for the net name and the main parent component ref = comp->GetRef( &nitem->m_SheetPath ); if( ref[0] == wxChar( '#' ) ) continue; if( ++sameNetcodeCount == 1 ) { xnets->AddChild( xnet = node( sNet ) ); netCodeTxt.Printf( sFmtd, netCode ); xnet->AddAttribute( sCode, netCodeTxt ); xnet->AddAttribute( sName, netName ); } XNODE* xnode; xnet->AddChild( xnode = node( sNode ) ); xnode->AddAttribute( sRef, ref ); xnode->AddAttribute( sPin, nitem->GetPinNumText() ); } return xnets; }
void NETLIST_OBJECT_LIST::setUnconnectedFlag() { NETLIST_OBJECT* NetItemRef; unsigned NetStart, NetEnd; NET_CONNECTION_T StateFlag; NetStart = NetEnd = 0; StateFlag = UNCONNECTED; for( unsigned ii = 0; ii < size(); ii++ ) { NetItemRef = GetItem( ii ); if( NetItemRef->m_Type == NET_NOCONNECT && StateFlag != PAD_CONNECT ) StateFlag = NOCONNECT_SYMBOL_PRESENT; // Analysis of current net. unsigned idxtoTest = ii + 1; if( ( idxtoTest >= size() ) || ( NetItemRef->GetNet() != GetItem( idxtoTest )->GetNet() ) ) { // Net analysis to update m_ConnectionType NetEnd = idxtoTest; /* set m_ConnectionType member to StateFlag for all items of * this net: */ for( unsigned kk = NetStart; kk < NetEnd; kk++ ) GetItem( kk )->m_ConnectionType = StateFlag; if( idxtoTest >= size() ) return; // Start Analysis next Net StateFlag = UNCONNECTED; NetStart = idxtoTest; continue; } /* test the current item: if this is a pin and if the reference item * is also a pin, then 2 pins are connected, so set StateFlag to * PAD_CONNECT (can be already done) Of course, if the current * item is a no connect symbol, set StateFlag to * NOCONNECT_SYMBOL_PRESENT to inhibit error diags. However if * StateFlag is already set to PAD_CONNECT this state is kept (the * no connect symbol was surely an error and an ERC will report this) */ for( ; ; idxtoTest++ ) { if( ( idxtoTest >= size() ) || ( NetItemRef->GetNet() != GetItem( idxtoTest )->GetNet() ) ) break; switch( GetItem( idxtoTest )->m_Type ) { case NET_ITEM_UNSPECIFIED: wxMessageBox( wxT( "BuildNetListBase() error" ) ); break; case NET_SEGMENT: case NET_LABEL: case NET_HIERLABEL: case NET_GLOBLABEL: case NET_SHEETLABEL: case NET_PINLABEL: case NET_BUS: case NET_BUSLABELMEMBER: case NET_SHEETBUSLABELMEMBER: case NET_HIERBUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: case NET_JUNCTION: break; case NET_PIN: if( NetItemRef->m_Type == NET_PIN ) StateFlag = PAD_CONNECT; break; case NET_NOCONNECT: if( StateFlag != PAD_CONNECT ) StateFlag = NOCONNECT_SYMBOL_PRESENT; break; } } } }
void NETLIST_OBJECT_LIST::pointToPointConnect( NETLIST_OBJECT* aRef, bool aIsBus, int start ) { int netCode; if( aIsBus == false ) // Objects other than BUS and BUSLABELS { netCode = aRef->GetNet(); for( unsigned i = start; i < size(); i++ ) { NETLIST_OBJECT* item = GetItem( i ); if( item->m_SheetPath != aRef->m_SheetPath ) //used to be > (why?) continue; switch( item->m_Type ) { case NET_SEGMENT: case NET_PIN: case NET_LABEL: case NET_HIERLABEL: case NET_GLOBLABEL: case NET_SHEETLABEL: case NET_PINLABEL: case NET_JUNCTION: case NET_NOCONNECT: if( aRef->m_Start == item->m_Start || aRef->m_Start == item->m_End || aRef->m_End == item->m_Start || aRef->m_End == item->m_End ) { if( item->GetNet() == 0 ) item->SetNet( netCode ); else propagateNetCode( item->GetNet(), netCode, IS_WIRE ); } break; case NET_BUS: case NET_BUSLABELMEMBER: case NET_SHEETBUSLABELMEMBER: case NET_HIERBUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: case NET_ITEM_UNSPECIFIED: break; } } } else // Object type BUS, BUSLABELS, and junctions. { netCode = aRef->m_BusNetCode; for( unsigned i = start; i < size(); i++ ) { NETLIST_OBJECT* item = GetItem( i ); if( item->m_SheetPath != aRef->m_SheetPath ) continue; switch( item->m_Type ) { case NET_ITEM_UNSPECIFIED: case NET_SEGMENT: case NET_PIN: case NET_LABEL: case NET_HIERLABEL: case NET_GLOBLABEL: case NET_SHEETLABEL: case NET_PINLABEL: case NET_NOCONNECT: break; case NET_BUS: case NET_BUSLABELMEMBER: case NET_SHEETBUSLABELMEMBER: case NET_HIERBUSLABELMEMBER: case NET_GLOBBUSLABELMEMBER: case NET_JUNCTION: if( aRef->m_Start == item->m_Start || aRef->m_Start == item->m_End || aRef->m_End == item->m_Start || aRef->m_End == item->m_End ) { if( item->m_BusNetCode == 0 ) item->m_BusNetCode = netCode; else propagateNetCode( item->m_BusNetCode, netCode, IS_BUS ); } break; } } } }
void NETLIST_OBJECT_LIST::findBestNetNameForEachNet() { // Important note: NET_SHEETLABEL items of sheet items should *NOT* be considered, // because they live in a sheet but their names are actually used in the subsheet. // Moreover, in the parent sheet, the name of NET_SHEETLABEL can be not unique, // ( for instance when 2 different sheets share the same schematic in complex hierarchies // and 2 identical NET_SHEETLABEL labels can be connected to 2 different nets int netcode = 0; // current netcode for tested items unsigned idxstart = 0; // index of the first item of this net NETLIST_OBJECT* item; NETLIST_OBJECT* candidate; // Pass 1: find the best name for labelled nets: candidate = NULL; for( unsigned ii = 0; ii <= size(); ii++ ) { if( ii == size() ) // last item already tested item = NULL; else item = GetItem( ii ); if( !item || netcode != item->GetNet() ) // End of net found { if( candidate ) // One or more labels exists, find the best { for (unsigned jj = idxstart; jj < ii; jj++ ) GetItem( jj )->SetNetNameCandidate( candidate ); } if( item == NULL ) // End of list break; // Prepare next net analysis: netcode = item->GetNet(); candidate = NULL; idxstart = ii; } switch( item->m_Type ) { case NET_HIERLABEL: case NET_LABEL: case NET_PINLABEL: case NET_GLOBLABEL: case NET_GLOBBUSLABELMEMBER: // A candidate is found: select the better between the previous // and this one if( candidate == NULL ) candidate = item; else { if( evalLabelsPriority( item, candidate ) ) // item has a highter priority than candidate // so update the best candidate candidate = item; } break; default: break; } } // Pass 2: find the best name for not labelled nets: // The "default" net name is Net-<<Ref cmp>_Pad<num pad>> // (see NETLIST_OBJECT::GetShortNetName()) // therefore the "best" is the short net name alphabetically classed first // (to avoid net names changes when the net is not modified, // even if components are moved or deleted and undelete or replaced, as long // the reference is kept) // Build a list of items with no net names NETLIST_OBJECTS list; // no ownership of elements being pointed at for( unsigned ii = 0; ii < size(); ii++ ) { item = GetItem( ii ); if( !item->HasNetNameCandidate() ) list.push_back( item ); } if( list.size() == 0 ) return; idxstart = 0; candidate = NULL; netcode = list[0]->GetNet(); for( unsigned ii = 0; ii <= list.size(); ii++ ) { if( ii < list.size() ) item = list[ii]; else item = NULL; if( !item || netcode != item->GetNet() ) // End of net found { if( candidate ) { for (unsigned jj = idxstart; jj < ii; jj++ ) { NETLIST_OBJECT* obj = list[jj]; obj->SetNetNameCandidate( candidate ); } } if( !item ) break; netcode = item->GetNet(); candidate = NULL; idxstart = ii; } // Examine all pins of the net to find the best candidate, // i.e. the first net name candidate, by alphabetic order // the net names are built by GetShortNetName // (Net-<{reference}-Pad{pad number}> like Net-<U3-Pad5> // Not named nets do not have usually a lot of members. // Many have only 2 members(a pad and a non connection symbol) if( item->m_Type == NET_PIN ) { // A candidate is found, however components which are not in // netlist are not candidate because some have their reference // changed each time the netlist is built (power components) // and anyway obviously they are not a good candidate SCH_COMPONENT* link = item->GetComponentParent(); if( link && link->IsInNetlist() ) { // select the better between the previous and this one item->SetNetNameCandidate( item ); // Needed to calculate GetShortNetName if( candidate == NULL ) candidate = item; else { if( item->GetShortNetName().Cmp( candidate->GetShortNetName() ) < 0 ) candidate = item; } } } } }
bool NETLIST_EXPORTER_CADSTAR::writeListOfNets( FILE* f ) { int ret = 0; wxString InitNetDesc = StartLine + wxT( "ADD_TER" ); wxString StartNetDesc = StartLine + wxT( "TER" ); wxString netcodeName, InitNetDescLine; unsigned ii; int print_ter = 0; int NetCode, lastNetCode = -1; SCH_COMPONENT* Cmp; wxString netName; for( ii = 0; ii < m_masterList->size(); ii++ ) { NETLIST_OBJECT* nitem = m_masterList->GetItem( ii ); // Get the NetName of the current net : if( ( NetCode = nitem->GetNet() ) != lastNetCode ) { netName = nitem->GetNetName(); netcodeName = wxT( "\"" ); if( !netName.IsEmpty() ) netcodeName << netName; else // this net has no name: create a default name $<net number> netcodeName << wxT( "$" ) << NetCode; netcodeName += wxT( "\"" ); lastNetCode = NetCode; print_ter = 0; } if( nitem->m_Type != NET_PIN ) continue; if( nitem->m_Flag != 0 ) continue; Cmp = nitem->GetComponentParent(); wxString refstr = Cmp->GetRef( &nitem->m_SheetPath ); if( refstr[0] == '#' ) continue; // Power supply symbols. switch( print_ter ) { case 0: { char buf[5]; wxString str_pinnum; strncpy( buf, (char*) &nitem->m_PinNum, 4 ); buf[4] = 0; str_pinnum = FROM_UTF8( buf ); InitNetDescLine.Printf( wxT( "\n%s %s %.4s %s" ), GetChars( InitNetDesc ), GetChars( refstr ), GetChars( str_pinnum ), GetChars( netcodeName ) ); } print_ter++; break; case 1: ret |= fprintf( f, "%s\n", TO_UTF8( InitNetDescLine ) ); ret |= fprintf( f, "%s %s %.4s\n", TO_UTF8( StartNetDesc ), TO_UTF8( refstr ), (char*) &nitem->m_PinNum ); print_ter++; break; default: ret |= fprintf( f, " %s %.4s\n", TO_UTF8( refstr ), (char*) &nitem->m_PinNum ); break; } nitem->m_Flag = 1; } return ret >= 0; }
bool NETLIST_EXPORTER_GENERIC::writeListOfNets( 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]; for( unsigned ii = 0; ii < aObjectsList.size(); ii++ ) { SCH_COMPONENT* comp; NETLIST_OBJECT* nitem = aObjectsList[ii]; // New net found, write net id; if( ( netCode = nitem->GetNet() ) != lastNetCode ) { sameNetcodeCount = 0; // Items count for this net netName = nitem->GetNetName(); netcodeName.Printf( wxT( "Net %d " ), netCode ); netcodeName << wxT( "\"" ) << netName << wxT( "\"" ); // Add the netname without prefix, in cases we need only the // "short" netname netcodeName += wxT( " \"" ) + nitem->GetShortNetName() + wxT( "\"" ); lastNetCode = netCode; } if( nitem->m_Type != NET_PIN ) continue; if( nitem->m_Flag != 0 ) // Redundant pin, skip it continue; comp = nitem->GetComponentParent(); // Get the reference for the net name and the main parent component ref = comp->GetRef( &nitem->m_SheetPath ); if( ref[0] == wxChar( '#' ) ) continue; // Pseudo component (Like Power symbol) // 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 ) { snprintf( firstItemInNet, sizeof(firstItemInNet), " %s %.4s\n", TO_UTF8( ref ), (const char*) &aObjectsList[ii]->m_PinNum ); } // Second item for this net found, print the Net name, and the // first item if( sameNetcodeCount == 2 ) { ret |= fprintf( f, "%s\n", TO_UTF8( netcodeName ) ); ret |= fputs( firstItemInNet, f ); } if( sameNetcodeCount >= 2 ) ret |= fprintf( f, " %s %.4s\n", TO_UTF8( ref ), (const char*) &nitem->m_PinNum ); } return ret >= 0; }
/** * Function findBestNetNameForEachNet * fill the .m_NetNameCandidate member of each item of aNetItemBuffer * with a reference to the "best" NETLIST_OBJECT usable to give a name to the net * If no suitable object found, .m_NetNameCandidate is filled with 0. * The "best" NETLIST_OBJECT is a NETLIST_OBJECT that have the type label * and by priority order: * the label is global or local * the label is in the first sheet in a hierarchy (the root sheet has the most priority) * alphabetic order. */ void NETLIST_OBJECT_LIST::findBestNetNameForEachNet() { int netcode = 0; // current netcode for tested items unsigned idxstart = 0; // index of the first item of this net NETLIST_OBJECT* item; NETLIST_OBJECT* candidate; // Pass 1: find the best name for labelled nets: item = NULL; candidate = NULL; for( unsigned ii = 0; ii <= size(); ii++ ) { if( ii == size() ) // last item already found netcode = -2; else item = GetItem( ii ); if( netcode != item->GetNet() ) // End of net found { if( candidate ) // One or more labels exists, find the best { for (unsigned jj = idxstart; jj < ii; jj++ ) GetItem( jj )->SetNetNameCandidate( candidate ); } if( netcode == -2 ) break; netcode = item->GetNet(); candidate = NULL; idxstart = ii; } switch( item->m_Type ) { case NET_HIERLABEL: case NET_LABEL: case NET_PINLABEL: case NET_GLOBLABEL: // A candidate is found: select the better between the previous // and this one if( candidate == NULL ) candidate = item; else { if( evalLabelsPriority( item, candidate ) ) // item has a highter priority than candidate // so update the best candidate candidate = item; } break; default: break; } } // Pass 2: find the best name for not labelled nets: // The "default" net name is Net-<<Ref cmp>_Pad<num pad>> // (see NETLIST_OBJECT::GetShortNetName()) // therefore the "best" is the short net name alphabetically classed first // (to avoid net names changes when the net is not modified, // even if components are moved or deleted and undelete or replaced, as long // the reference is kept) // Build the list of items with no net names NETLIST_OBJECT_LIST list; for( unsigned ii = 0; ii < size(); ii++ ) { item = GetItem( ii ); if( !item->HasNetNameCandidate() ) list.push_back( item ); } if( list.size() == 0 ) return; idxstart = 0; candidate = NULL; netcode = list.GetItemNet( 0 ); for( unsigned ii = 0; ii <= list.size(); ii++ ) { if( ii < list.size() ) item = list.GetItem( ii ); if( netcode != item->GetNet() || ii >= list.size() ) // End of net found { if( candidate ) { for (unsigned jj = idxstart; jj < ii; jj++ ) { NETLIST_OBJECT* obj = list.GetItem( jj ); obj->SetNetNameCandidate( candidate ); } } if( ii >= list.size() ) break; netcode = item->GetNet(); candidate = NULL; idxstart = ii; } // Examine all pins of the net to find the best candidate, // i.e. the first net name candidate, by alphabetic order // the net names are names bu_ilt by GetShortNetName // (Net-<{reference}-Pad{pad number}> like Net-<U3-Pad5> // Not named nets do not have usually a lot of members. // Many have only 2 members(a pad and a non connection symbol) if( item->m_Type == NET_PIN ) { // A candidate is found, however components which are not in // netlist are not candidate because some have their reference // changed each time the netlist is built (power components) // and anyway obviously they are not a good candidate SCH_COMPONENT* link = item->GetComponentParent(); if( link && link->IsInNetlist() ) { // select the better between the previous and this one item->SetNetNameCandidate( item ); // Needed to calculate GetShortNetName if( candidate == NULL ) candidate = item; else { if( item->GetShortNetName().Cmp( candidate->GetShortNetName() ) < 0 ) candidate = item; } } } } }