committed
This commit is contained in:
commit
26be6d0152
|
@ -680,7 +680,11 @@ bool WinEDA_App::SetLanguage( bool first_time )
|
|||
delete m_Locale;
|
||||
m_Locale = new wxLocale;
|
||||
|
||||
#if wxCHECK_VERSION( 2, 9, 0 )
|
||||
if( !m_Locale->Init( m_LanguageId ) )
|
||||
#else
|
||||
if( !m_Locale->Init( m_LanguageId, wxLOCALE_CONV_ENCODING ) )
|
||||
#endif
|
||||
{
|
||||
wxLogDebug( wxT("This language is not supported by the system.") );
|
||||
|
||||
|
|
|
@ -19,14 +19,11 @@
|
|||
#include "sch_component.h"
|
||||
#include "lib_pin.h"
|
||||
|
||||
//#define USE_OLD_ALGO
|
||||
|
||||
static void BreakReference( SCH_REFERENCE_LIST& aComponentsList );
|
||||
static void ReAnnotateComponents( SCH_REFERENCE_LIST& aComponentsList );
|
||||
static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aUseSheetNum );
|
||||
static int GetLastReferenceNumber( int aObjet,SCH_REFERENCE_LIST& aComponentsList );
|
||||
static int ExistUnit( int aObjet, int aUnit, SCH_REFERENCE_LIST& aComponentList );
|
||||
|
||||
|
||||
/**
|
||||
* Function DeleteAnnotation
|
||||
* Remove current component annotations
|
||||
|
@ -109,7 +106,7 @@ void SCH_EDIT_FRAME::AnnotateComponents(
|
|||
// Update the screen date.
|
||||
screens.SetDate( GenDate() );
|
||||
|
||||
// Set sheet number and total sheet counts.
|
||||
// Set sheet number and number of sheets.
|
||||
SetSheetNumberAndCount();
|
||||
|
||||
/* Build component list */
|
||||
|
@ -124,7 +121,7 @@ void SCH_EDIT_FRAME::AnnotateComponents(
|
|||
|
||||
/* Break full components reference in name (prefix) and number:
|
||||
* example: IC1 become IC, and 1 */
|
||||
BreakReference( references );
|
||||
references.SplitReferences( );
|
||||
|
||||
bool useSheetNum = false;
|
||||
switch( sortOption )
|
||||
|
@ -152,36 +149,126 @@ void SCH_EDIT_FRAME::AnnotateComponents(
|
|||
break;
|
||||
}
|
||||
|
||||
/* Recalculate reference numbers */
|
||||
// Recalculate and update reference numbers in schematic
|
||||
ComputeReferenceNumber( references, useSheetNum );
|
||||
ReAnnotateComponents( references );
|
||||
references.UpdateAnnotation();
|
||||
|
||||
/* Final control (just in case ... )*/
|
||||
CheckAnnotate( NULL, !annotateSchematic );
|
||||
OnModify();
|
||||
|
||||
// Update on screen refences, that can be modified by previous calculations:
|
||||
m_CurrentSheet->UpdateAllScreenReferences();
|
||||
SetSheetNumberAndCount();
|
||||
|
||||
DrawPanel->Refresh( true );
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Update the reference component for the schematic project (or the current sheet)
|
||||
#ifdef USE_OLD_ALGO
|
||||
/** helper function
|
||||
* Search the last used (greatest) reference number in the component list
|
||||
* for the prefix reference given by Objet
|
||||
* The component list must be sorted.
|
||||
*
|
||||
* @param aObjet = reference item ( aComponentsList[aObjet].m_TextRef is
|
||||
* the search pattern)
|
||||
* @param aComponentsList = list of items
|
||||
* @param aMinValue = min value for the current search
|
||||
*/
|
||||
static void ReAnnotateComponents( SCH_REFERENCE_LIST& aComponentList )
|
||||
static int GetLastNumberInReference( int aObjet,SCH_REFERENCE_LIST& aComponentsList,
|
||||
int aMinValue )
|
||||
{
|
||||
/* update the reference numbers */
|
||||
for( unsigned ii = 0; ii < aComponentList.GetCount(); ii++ )
|
||||
int lastNumber = aMinValue;
|
||||
|
||||
for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
|
||||
{
|
||||
aComponentList[ii].Annotate();
|
||||
// search only for the current reference prefix:
|
||||
if( aComponentsList[aObjet].CompareRef( aComponentsList[ii] ) != 0 )
|
||||
continue;
|
||||
|
||||
// update max value for the current reference prefix
|
||||
if( lastNumber < aComponentsList[ii].m_NumRef )
|
||||
lastNumber = aComponentsList[ii].m_NumRef;
|
||||
}
|
||||
|
||||
return lastNumber;
|
||||
}
|
||||
|
||||
#else
|
||||
/**
|
||||
* helper function BuildRefIdInUseList
|
||||
* creates the list of reference numbers in use for a given reference prefix.
|
||||
* @param aObjet = the current component index to use for reference prefix filtering.
|
||||
* @param aComponentsList = the full list of components
|
||||
* @param aIdList = the buffer to fill
|
||||
* @param aMinRefId = the min id value to store. all values < aMinRefId are ignored
|
||||
*/
|
||||
static void BuildRefIdInUseList( int aObjet,SCH_REFERENCE_LIST& aComponentsList,
|
||||
std::vector<int>& aIdList, int aMinRefId )
|
||||
{
|
||||
aIdList.clear();
|
||||
|
||||
for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
|
||||
{
|
||||
if( ( aComponentsList[aObjet].CompareRef( aComponentsList[ii] ) == 0 )
|
||||
&& ( aComponentsList[ii].m_NumRef >= aMinRefId ) )
|
||||
aIdList.push_back( aComponentsList[ii].m_NumRef );
|
||||
}
|
||||
sort( aIdList.begin(), aIdList.end() );
|
||||
|
||||
// Ensure each reference Id appears only once
|
||||
// If there are multiple parts per package the same Id will be stored for each part.
|
||||
for( unsigned ii = 1; ii < aIdList.size(); ii++ )
|
||||
{
|
||||
if( aIdList[ii] != aIdList[ii-1] )
|
||||
continue;
|
||||
aIdList.erase(aIdList.begin() + ii );
|
||||
ii--;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void BreakReference( SCH_REFERENCE_LIST& aComponentsList )
|
||||
/**
|
||||
* helper function CreateFirstFreeRefId
|
||||
* Search for a free ref Id inside a list of reference numbers in use.
|
||||
* This list is expected sorted by increasing values, and each value stored only once
|
||||
* @see BuildRefIdInUseList to prepare this list
|
||||
* @param aIdList = the buffer that contains Ids in use
|
||||
* @param aFirstValue = the first expected free value
|
||||
* @return a free (not yet used) Id
|
||||
* and this new id is added in list
|
||||
*/
|
||||
static int CreateFirstFreeRefId( std::vector<int>& aIdList, int aFirstValue )
|
||||
{
|
||||
for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
|
||||
aComponentsList[ii].Split();
|
||||
}
|
||||
int expectedId = aFirstValue;
|
||||
|
||||
// We search for expectedId a value >= aFirstValue.
|
||||
// Skip existing Id < aFirstValue
|
||||
unsigned ii = 0;
|
||||
for( ; ii < aIdList.size(); ii++ )
|
||||
{
|
||||
if( expectedId <= aIdList[ii] )
|
||||
break;
|
||||
}
|
||||
|
||||
// Ids are sorted by increasing value, from aFirstValue
|
||||
// So we search from aFirstValue the first not used value, i.e. the first hole in list.
|
||||
for(; ii < aIdList.size(); ii++ )
|
||||
{
|
||||
if( expectedId != aIdList[ii] ) // This id is not yet used.
|
||||
{
|
||||
// Insert this free Id, in order to keep list sorted
|
||||
aIdList.insert(aIdList.begin() + ii, expectedId);
|
||||
return expectedId;
|
||||
}
|
||||
expectedId++;
|
||||
}
|
||||
|
||||
// All existing Id are tested, and all values are found in use.
|
||||
// So Create a new one.
|
||||
aIdList.push_back( expectedId );
|
||||
return expectedId;
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Compute the reference number for components without reference number
|
||||
|
@ -189,7 +276,11 @@ void BreakReference( SCH_REFERENCE_LIST& aComponentsList )
|
|||
*/
|
||||
static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aUseSheetNum )
|
||||
{
|
||||
int LastReferenceNumber, NumberOfUnits, Unit;
|
||||
if ( aComponentsList.GetCount() == 0 )
|
||||
return;
|
||||
|
||||
int LastReferenceNumber = 0;
|
||||
int NumberOfUnits, Unit;
|
||||
|
||||
/* Components with an invisible reference (power...) always are
|
||||
* re-annotated. So set their .m_IsNew member to true
|
||||
|
@ -209,33 +300,59 @@ static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aU
|
|||
* IC .. will be set to IC4, IC4, IC5 ...
|
||||
*/
|
||||
unsigned first = 0;
|
||||
|
||||
/* calculate the last used number for this reference prefix: */
|
||||
LastReferenceNumber = GetLastReferenceNumber( first, aComponentsList );
|
||||
#ifdef USE_OLD_ALGO
|
||||
int minRefId = 0;
|
||||
// when using sheet number, ensure ref number >= sheet number* 100
|
||||
if( aUseSheetNum )
|
||||
minRefId = aComponentsList[first].m_SheetNum * 100;
|
||||
LastReferenceNumber = GetLastNumberInReference( first, aComponentsList, minRefId );
|
||||
#else
|
||||
int minRefId = 1;
|
||||
// when using sheet number, ensure ref number >= sheet number* 100
|
||||
if( aUseSheetNum )
|
||||
minRefId = aComponentsList[first].m_SheetNum * 100 + 1;
|
||||
// This is the list of all Id already in use for a given reference prefix.
|
||||
// Will be refilled for each new reference prefix.
|
||||
std::vector<int>idList;
|
||||
BuildRefIdInUseList( first, aComponentsList, idList, minRefId );
|
||||
#endif
|
||||
for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
|
||||
{
|
||||
if( aComponentsList[ii].m_Flag )
|
||||
continue;
|
||||
|
||||
if( aComponentsList[first].CompareRef( aComponentsList[ii] ) != 0 )
|
||||
if( ( aComponentsList[first].CompareRef( aComponentsList[ii] ) != 0 ) ||
|
||||
( aUseSheetNum && ( aComponentsList[first].m_SheetNum != aComponentsList[ii].m_SheetNum ) )
|
||||
)
|
||||
{
|
||||
/* New reference found: we need a new ref number for this
|
||||
* reference */
|
||||
first = ii;
|
||||
LastReferenceNumber = GetLastReferenceNumber( ii, aComponentsList );
|
||||
}
|
||||
// when using sheet number, ensure annot number >= sheet number* 100
|
||||
if( aUseSheetNum )
|
||||
{
|
||||
int min_num = aComponentsList[ii].m_SheetNum * 100;
|
||||
if( LastReferenceNumber < min_num )
|
||||
LastReferenceNumber = min_num;
|
||||
#ifdef USE_OLD_ALGO
|
||||
minRefId = 0;
|
||||
// when using sheet number, ensure ref number >= sheet number* 100
|
||||
if( aUseSheetNum )
|
||||
minRefId = aComponentsList[ii].m_SheetNum * 100;
|
||||
LastReferenceNumber = GetLastNumberInReference( ii, aComponentsList, minRefId);
|
||||
#else
|
||||
minRefId = 1;
|
||||
// when using sheet number, ensure ref number >= sheet number* 100
|
||||
if( aUseSheetNum )
|
||||
minRefId = aComponentsList[ii].m_SheetNum * 100 + 1;
|
||||
BuildRefIdInUseList( first, aComponentsList, idList, minRefId );
|
||||
#endif
|
||||
}
|
||||
/* Annotation of one part per package components (trivial case)*/
|
||||
if( aComponentsList[ii].m_Entry->GetPartCount() <= 1 )
|
||||
{
|
||||
if( aComponentsList[ii].m_IsNew )
|
||||
{
|
||||
#ifdef USE_OLD_ALGO
|
||||
LastReferenceNumber++;
|
||||
#else
|
||||
LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
|
||||
#endif
|
||||
aComponentsList[ii].m_NumRef = LastReferenceNumber;
|
||||
}
|
||||
|
||||
|
@ -251,7 +368,11 @@ static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aU
|
|||
|
||||
if( aComponentsList[ii].m_IsNew )
|
||||
{
|
||||
#ifdef USE_OLD_ALGO
|
||||
LastReferenceNumber++;
|
||||
#else
|
||||
LastReferenceNumber = CreateFirstFreeRefId( idList, minRefId );
|
||||
#endif
|
||||
aComponentsList[ii].m_NumRef = LastReferenceNumber;
|
||||
|
||||
if( !aComponentsList[ii].IsPartsLocked() )
|
||||
|
@ -307,33 +428,6 @@ static void ComputeReferenceNumber( SCH_REFERENCE_LIST& aComponentsList, bool aU
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Search the last used (greatest) reference number in the component list
|
||||
* for the prefix reference given by Objet
|
||||
* The component list must be sorted.
|
||||
*
|
||||
* @param aObjet = reference item ( aComponentsList[aObjet].m_TextRef is
|
||||
* the search pattern)
|
||||
* @param aComponentsList = list of items
|
||||
*/
|
||||
int GetLastReferenceNumber( int aObjet,SCH_REFERENCE_LIST& aComponentsList )
|
||||
{
|
||||
int LastNumber = 0;
|
||||
|
||||
for( unsigned ii = 0; ii < aComponentsList.GetCount(); ii++ )
|
||||
{
|
||||
/* New identifier. */
|
||||
if( aComponentsList[aObjet].CompareRef( aComponentsList[ii] ) != 0 )
|
||||
continue;
|
||||
|
||||
if( LastNumber < aComponentsList[ii].m_NumRef )
|
||||
LastNumber = aComponentsList[ii].m_NumRef;
|
||||
}
|
||||
|
||||
return LastNumber;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Search in the sorted list of components, for a given component an other
|
||||
* component with the same reference and a given part unit. Mainly used to
|
||||
|
@ -391,7 +485,7 @@ static int ExistUnit( int aObjet, int Unit, SCH_REFERENCE_LIST& aComponentsList
|
|||
*/
|
||||
int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOnly )
|
||||
{
|
||||
int error;
|
||||
int error = 0;
|
||||
wxString Buff;
|
||||
wxString msg, cmpref;
|
||||
|
||||
|
@ -410,18 +504,15 @@ int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOn
|
|||
|
||||
/* Break full components reference in name (prefix) and number: example:
|
||||
* IC1 become IC, and 1 */
|
||||
BreakReference( ComponentsList );
|
||||
ComponentsList.SplitReferences();
|
||||
|
||||
/* count not yet annotated items */
|
||||
error = 0;
|
||||
int imax = ComponentsList.GetCount() - 1;
|
||||
|
||||
for( int ii = 0; ii < imax; ii++ )
|
||||
/* count not yet annotated items or annottaion error*/
|
||||
for( unsigned ii = 0; ii < ComponentsList.GetCount(); ii++ )
|
||||
{
|
||||
msg.Empty();
|
||||
Buff.Empty();
|
||||
|
||||
if( ComponentsList[ii].m_IsNew )
|
||||
if( ComponentsList[ii].m_IsNew ) // Not yet annotated
|
||||
{
|
||||
if( ComponentsList[ii].m_NumRef >= 0 )
|
||||
Buff << ComponentsList[ii].m_NumRef;
|
||||
|
@ -446,7 +537,8 @@ int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOn
|
|||
break;
|
||||
}
|
||||
|
||||
// Annotate error
|
||||
// Annotate error if unit selected does not exist ( i.e. > number of parts )
|
||||
// Can happen if a component has changed in a lib, after a previous annotation
|
||||
if( MAX( ComponentsList[ii].m_Entry->GetPartCount(), 1 ) < ComponentsList[ii].m_Unit )
|
||||
{
|
||||
if( ComponentsList[ii].m_NumRef >= 0 )
|
||||
|
@ -477,6 +569,7 @@ int SCH_EDIT_FRAME::CheckAnnotate( wxArrayString* aMessageList, bool aOneSheetOn
|
|||
return error;
|
||||
|
||||
// count the duplicated elements (if all are annotated)
|
||||
int imax = ComponentsList.GetCount() - 1;
|
||||
for( int ii = 0; (ii < imax) && (error < 4); ii++ )
|
||||
{
|
||||
msg.Empty();
|
||||
|
|
|
@ -226,6 +226,39 @@ public:
|
|||
* When annotating, some or all components are not annotated,
|
||||
* i.e. ref is only U or R, with no number.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* Function SplitReferences
|
||||
* attempts to split all reference designators into a name (U) and number (1). If the
|
||||
* last character is '?' or not a digit, the reference is tagged as not annotated.
|
||||
* For components with multiple parts per package that are not already annotated, set
|
||||
* m_Unit to a max value (0x7FFFFFFF).
|
||||
* @see SCH_REFERENCE::Split()
|
||||
*/
|
||||
void SplitReferences()
|
||||
{
|
||||
for( unsigned ii = 0; ii < GetCount(); ii++ )
|
||||
componentFlatList[ii].Split();
|
||||
}
|
||||
|
||||
/**
|
||||
* function UpdateAnnotation
|
||||
* Update the reference components for the schematic project (or the current sheet)
|
||||
* Note: this function does not calculate the reference numbers
|
||||
* stored in m_NumRef
|
||||
* So, it must be called after calcultaion of new reference numbers
|
||||
* @see SCH_REFERENCE::Annotate()
|
||||
*/
|
||||
void UpdateAnnotation()
|
||||
{
|
||||
/* update the reference numbers */
|
||||
for( unsigned ii = 0; ii < GetCount(); ii++ )
|
||||
{
|
||||
componentFlatList[ii].Annotate();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Function SortCmpByXCoordinate
|
||||
* sort the flat list by X coordinates.
|
||||
|
|
|
@ -459,8 +459,12 @@ void DIR_LIB_SOURCE::GetRevisions( STRINGS* aResults, const STRING& aPartName )
|
|||
PN_ITER it = partnames.upper_bound( partName +'/' );
|
||||
PN_ITER end = partnames.lower_bound( partName + char( '/' +1 ) );
|
||||
|
||||
while( it != end )
|
||||
aResults->push_back( *it++ );
|
||||
for( ; it != end; ++it )
|
||||
{
|
||||
const char* rev = endsWithRev( *it );
|
||||
assert( rev );
|
||||
aResults->push_back( it->substr( rev - it->c_str() ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
100
new/sch_lib.cpp
100
new/sch_lib.cpp
|
@ -39,13 +39,12 @@
|
|||
|
||||
/*
|
||||
|
||||
The LIB part cache consist of a std::map of partnames without revisions at the top level.
|
||||
Each top level map entry can point to another std::map which it owns and holds all the revisions
|
||||
for that part name. At any point in the tree, there can be NULL pointers which
|
||||
allow for lazy loading, including the very top most root pointer itself, which
|
||||
is PARTS* parts. We use the key to hold the partName at one level, and revision
|
||||
at the deeper nested level, and that key information may not be present within
|
||||
right hand side of the map tuple.
|
||||
The LIB part cache consists of a std::map of partnames without revisions at the
|
||||
top level. Each top level map entry can point to another std::map which it owns
|
||||
and which holds all the revisions for that part name. At any point in the tree,
|
||||
there can be NULL pointers which allow for lazy loading, including the very top
|
||||
most root pointer itself, which is PARTS* parts. We use the key to hold the
|
||||
partName at one level, and revision at the deeper nested level.
|
||||
|
||||
1) Only things which are asked for are done.
|
||||
2) Anything we learn we remember.
|
||||
|
@ -54,10 +53,31 @@ right hand side of the map tuple.
|
|||
|
||||
namespace SCH {
|
||||
|
||||
class PART_REVS : public std::map< STRING, PART* >
|
||||
{
|
||||
// @todo provide an integer sort on revN.. strings here.
|
||||
|
||||
/**
|
||||
* Struct LTREV
|
||||
* is for PART_REVS, and provides a custom way to compare rev STRINGs.
|
||||
* Namely, the revN[N..] string if present, is collated according to a
|
||||
* 'higher revision first'.
|
||||
*/
|
||||
struct LTREV
|
||||
{
|
||||
bool operator() ( const STRING& s1, const STRING& s2 ) const
|
||||
{
|
||||
return RevCmp( s1.c_str(), s2.c_str() ) < 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class PART_REVS
|
||||
* contains the collection of revisions for a particular part name, in the
|
||||
* form of cached PARTs. The tuple consists of a rev string and a PART pointer.
|
||||
* The rev string is like "rev1", the PART pointer will be NULL until the PART
|
||||
* gets loaded, lazily.
|
||||
*/
|
||||
class PART_REVS : public std::map< STRING, PART*, LTREV >
|
||||
{
|
||||
public:
|
||||
~PART_REVS()
|
||||
{
|
||||
|
@ -68,6 +88,15 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Class PARTS
|
||||
* contains the collection of PART_REVS for all PARTs in the lib.
|
||||
* The tuple consists of a part name and a PART_REVS pointer.
|
||||
* The part name does not have the revision attached (of course this is understood
|
||||
* by definition of "part name"). The PART_REVS pointer will be NULL until a client
|
||||
* askes about the revisions for a part name, so the loading is done lazily.
|
||||
*/
|
||||
class PARTS : public std::map< STRING, PART_REVS* >
|
||||
{
|
||||
public:
|
||||
|
@ -126,7 +155,7 @@ LIB::~LIB()
|
|||
}
|
||||
|
||||
|
||||
const PART* LIB::findPart( const LPID& aLPID ) throw( IO_ERROR )
|
||||
const PART* LIB::lookupPart( const LPID& aLPID ) throw( IO_ERROR )
|
||||
{
|
||||
if( !parts )
|
||||
{
|
||||
|
@ -137,7 +166,7 @@ const PART* LIB::findPart( const LPID& aLPID ) throw( IO_ERROR )
|
|||
// insert a PART_REVS for each part name
|
||||
for( STRINGS::const_iterator it = vfetch.begin(); it!=vfetch.end(); ++it )
|
||||
{
|
||||
// D(printf("findPart:%s\n", it->c_str() );)
|
||||
D(printf("lookupPart:%s\n", it->c_str() );)
|
||||
(*parts)[*it] = new PART_REVS;
|
||||
}
|
||||
}
|
||||
|
@ -152,44 +181,46 @@ const PART* LIB::findPart( const LPID& aLPID ) throw( IO_ERROR )
|
|||
// if the key for parts has no aLPID.GetPartName() the part is not in this lib
|
||||
if( revs )
|
||||
{
|
||||
if( revs->size() == 0 )
|
||||
if( revs->size() == 0 ) // assume rev list has not been loaded yet
|
||||
{
|
||||
// load all the revisions for this part.
|
||||
source->GetRevisions( &vfetch, aLPID.GetPartName() );
|
||||
|
||||
// creat a PART_REV entry for revision, but leave the PART* NULL
|
||||
// create a PART_REV entry for each revision, but leave the PART* NULL
|
||||
for( STRINGS::const_iterator it = vfetch.begin(); it!=vfetch.end(); ++it )
|
||||
{
|
||||
// D(printf("findPartRev:%s\n", it->c_str() );)
|
||||
D(printf("lookupPartRev:%s\n", it->c_str() );)
|
||||
(*revs)[*it] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
PART_REVS::iterator result = revs->find( aLPID.GetPartNameAndRev() );
|
||||
|
||||
if( result != revs->end() )
|
||||
{
|
||||
if( !result->second ) // the PART has never been loaded before
|
||||
{
|
||||
result->second = new PART( this, aLPID.GetPartNameAndRev() );
|
||||
}
|
||||
|
||||
return result->second;
|
||||
}
|
||||
PART_REVS::iterator rev;
|
||||
|
||||
// If caller did not say what revision, find the highest numbered one and return that.
|
||||
// Otherwise he knew what he wanted specifically, and we do not have it.
|
||||
if( !aLPID.GetRevision().size() && revs->size() )
|
||||
{
|
||||
result = revs->begin(); // sort order has highest rev first
|
||||
rev = revs->begin(); // sort order has highest rev first
|
||||
|
||||
if( !result->second ) // the PART has never been loaded before
|
||||
if( !rev->second ) // the PART has never been instantiated before
|
||||
{
|
||||
result->second = new PART( this, LPID::Format( "", aLPID.GetPartName(), result->first ) );
|
||||
rev->second = new PART( this, LPID::Format( "", aLPID.GetPartName(), rev->first ) );
|
||||
}
|
||||
|
||||
return result->second;
|
||||
D(printf("lookupPartLatestRev:%s\n", rev->second->partNameAndRev.c_str() );)
|
||||
return rev->second;
|
||||
}
|
||||
else
|
||||
{
|
||||
rev = revs->find( aLPID.GetRevision() );
|
||||
|
||||
if( rev != revs->end() )
|
||||
{
|
||||
if( !rev->second ) // the PART has never been instantiated before
|
||||
{
|
||||
rev->second = new PART( this, aLPID.GetPartNameAndRev() );
|
||||
}
|
||||
return rev->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,7 +230,7 @@ const PART* LIB::findPart( const LPID& aLPID ) throw( IO_ERROR )
|
|||
|
||||
PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR )
|
||||
{
|
||||
PART* part = (PART*) findPart( aLPID );
|
||||
PART* part = (PART*) lookupPart( aLPID );
|
||||
|
||||
if( !part ) // part does not exist in this lib
|
||||
{
|
||||
|
@ -221,7 +252,8 @@ PART* LIB::LookupPart( const LPID& aLPID, LIB_TABLE* aLibTable ) throw( IO_ERROR
|
|||
printf( "\n" );
|
||||
#endif
|
||||
|
||||
SWEET_LEXER sw( part->body, wxString::FromUTF8("body") /* @todo have ReadPart give better source */ );
|
||||
// @todo consider changing ReadPart to return a "source"
|
||||
SWEET_LEXER sw( part->body, wxString::FromUTF8( aLPID.Format().c_str() ) );
|
||||
|
||||
part->Parse( &sw, aLibTable );
|
||||
}
|
||||
|
|
|
@ -343,14 +343,17 @@ protected:
|
|||
PARTS* parts;
|
||||
|
||||
/**
|
||||
* Function findPart
|
||||
* finds a PART, returns NULL if cannot find.
|
||||
* Function lookupPart
|
||||
* looks up a PART, returns NULL if cannot find in source. Does not parse
|
||||
* the part. Does not even load the part's Sweet string. No ownership
|
||||
* is given to the PART, it stays in the cache that is this LIB.
|
||||
*
|
||||
* @throw IO_ERROR if there is some kind of communications error reading
|
||||
* the original list of parts.
|
||||
*
|
||||
* @return PART* - the cached PART, or NULL if not found. No ownership transferred.
|
||||
*/
|
||||
const PART* findPart( const LPID& aLPID ) throw( IO_ERROR );
|
||||
|
||||
|
||||
const PART* lookupPart( const LPID& aLPID ) throw( IO_ERROR );
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -58,6 +58,20 @@ const char* EndsWithRev( const char* start, const char* tail, char separator )
|
|||
return 0;
|
||||
}
|
||||
|
||||
int RevCmp( const char* s1, const char* s2 )
|
||||
{
|
||||
int r = strncmp( s1, s2, 3 );
|
||||
|
||||
if( r || strlen(s1)<4 || strlen(s2)<4 )
|
||||
{
|
||||
return r;
|
||||
}
|
||||
|
||||
int rnum1 = atoi( s1+3 );
|
||||
int rnum2 = atoi( s2+3 );
|
||||
|
||||
return -(rnum1 - rnum2); // swap the sign, higher revs first
|
||||
}
|
||||
|
||||
//----<Policy and field test functions>-------------------------------------
|
||||
|
||||
|
@ -94,7 +108,7 @@ static int okRevision( const STRING& aField )
|
|||
{
|
||||
char rev[32]; // C string for speed
|
||||
|
||||
if( aField.size() >= 4 && aField.size() <= sizeof(rev)-3 )
|
||||
if( aField.size() >= 4 )
|
||||
{
|
||||
strcpy( rev, "x/" );
|
||||
strcat( rev, aField.c_str() );
|
||||
|
|
|
@ -228,4 +228,16 @@ static inline const char* EndsWithRev( const STRING& aPartName, char separator =
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Function RevCmp
|
||||
* compares two rev strings in a way like strcmp() except that the highest numbered
|
||||
* revision is considered first in the sort order. The function probably won't work
|
||||
* unless you give it two rev strings.
|
||||
* @param s1 is a rev string like "rev10"
|
||||
* @param s2 is a rev string like "rev1".
|
||||
* @return int - either negative, zero, or positive depending on whether the revision
|
||||
* is greater, equal, or less on the left hand side.
|
||||
*/
|
||||
int RevCmp( const char* s1, const char* s2 );
|
||||
|
||||
#endif // SCH_LPID_H_
|
||||
|
|
|
@ -38,6 +38,11 @@ using namespace SCH;
|
|||
struct XY {};
|
||||
struct AT {};
|
||||
|
||||
class POLY_LINE
|
||||
{
|
||||
|
||||
};
|
||||
|
||||
|
||||
//-----</temporary home for PART sub objects, move after stable>-----------------
|
||||
|
||||
|
@ -135,19 +140,28 @@ public:
|
|||
/// @param me = ja mir, the object getting stuffed, from its perspective
|
||||
void parsePart( PART* me )
|
||||
{
|
||||
PART_T tok = in->NextTok();
|
||||
PART_T tok;
|
||||
|
||||
#if 0
|
||||
// Be flexible regarding the starting point of the stream.
|
||||
// Caller may not have read the first two tokens out of the
|
||||
// stream: T_LEFT and T_part, so ignore them if seen here.
|
||||
// The 1st two tokens T_LEFT and T_part are then optional in the grammar.
|
||||
|
||||
if( tok == T_LEFT )
|
||||
if( (tok = in->NextTok() ) == T_LEFT )
|
||||
{
|
||||
if( ( tok = in->NextTok() ) != T_part )
|
||||
in->Expecting( T_part );
|
||||
}
|
||||
|
||||
#else
|
||||
// "( part" are not optional
|
||||
in->NeedLEFT();
|
||||
|
||||
if( ( tok = in->NextTok() ) != T_part )
|
||||
in->Expecting( T_part );
|
||||
#endif
|
||||
|
||||
in->NeedSYMBOLorNUMBER(); // read in part NAME_HINT, and toss
|
||||
tok = in->NextTok();
|
||||
|
||||
|
@ -187,6 +201,11 @@ public:
|
|||
contains |= PB(ANCHOR);
|
||||
break;
|
||||
|
||||
case T_line:
|
||||
|
||||
break;
|
||||
|
||||
|
||||
/*
|
||||
case T_value:
|
||||
if( contains & PB(VALUE) )
|
||||
|
@ -236,9 +255,6 @@ public:
|
|||
case T_polyline:
|
||||
break;
|
||||
|
||||
case T_line:
|
||||
break;
|
||||
|
||||
case T_rectangle:
|
||||
break;
|
||||
|
||||
|
@ -267,7 +283,7 @@ public:
|
|||
|
||||
contains |= PB(PARSED);
|
||||
|
||||
this->contains |= contains;
|
||||
me->contains |= contains;
|
||||
}
|
||||
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue