808 lines
26 KiB
C++
808 lines
26 KiB
C++
/**************************************/
|
||
/* annotate.cpp: component annotation */
|
||
/**************************************/
|
||
|
||
/* Local Variable */
|
||
static bool AnnotProject = true;
|
||
static bool SortByPosition = true;
|
||
|
||
#include "annotate_dialog.cpp"
|
||
|
||
#include "netlist.h"
|
||
#include "protos.h"
|
||
|
||
/* Local Functions*/
|
||
static int ListeComposants( CmpListStruct* BaseListeCmp, SCH_SCREEN* screen, int NumSheet );
|
||
static int AnnotTriComposant( const void* o1, const void* o2 );
|
||
static void BreakReference( CmpListStruct* BaseListeCmp, int NbOfCmp );
|
||
static void ReAnnotateComponents( CmpListStruct* BaseListeCmp, int NbOfCmp );
|
||
static void ComputeReferenceNumber( CmpListStruct* BaseListeCmp, int NbOfCmp );
|
||
static int GetLastReferenceNumber( CmpListStruct* Objet, CmpListStruct* BaseListeCmp,
|
||
int NbOfCmp );
|
||
static int ExistUnit( CmpListStruct* Objet, int Unit,
|
||
CmpListStruct* BaseListeCmp, int NbOfCmp );
|
||
|
||
|
||
/**************************************/
|
||
void ReAnnotatePowerSymbolsOnly( void )
|
||
/**************************************/
|
||
|
||
/* Used to reannotate the power symbols, before testing erc or computing netlist
|
||
* when a true component reannotation is not necessary
|
||
*
|
||
* In order to avoid conflicts the ref number starts with a 0:
|
||
* PWR with id 12 is named PWR12 in global annotation and PWR012 by the Power annotation
|
||
*/
|
||
{
|
||
/* Build the screen list */
|
||
EDA_ScreenList ScreenList( NULL );
|
||
|
||
/* Update the sheet number, sheet count and date */
|
||
ScreenList.UpdateSheetNumberAndDate();
|
||
|
||
SCH_SCREEN* screen;
|
||
int CmpNumber = 1;
|
||
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
|
||
{
|
||
EDA_BaseStruct* DrawList = screen->EEDrawList;
|
||
for( ; DrawList != NULL; DrawList = DrawList->Pnext )
|
||
{
|
||
if( DrawList->Type() != DRAW_LIB_ITEM_STRUCT_TYPE )
|
||
continue;
|
||
EDA_SchComponentStruct* DrawLibItem = (EDA_SchComponentStruct*) DrawList;
|
||
EDA_LibComponentStruct* Entry =
|
||
FindLibPart( DrawLibItem->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
|
||
if( (Entry == NULL) || (Entry->m_Options != ENTRY_POWER) )
|
||
continue;
|
||
DrawLibItem->ClearAnnotation();
|
||
DrawLibItem->m_RefIdNumber = CmpNumber;
|
||
DrawLibItem->m_Field[REFERENCE].m_Text.RemoveLast(); // Remove the '?'
|
||
DrawLibItem->m_Field[REFERENCE].m_Text << wxT( "0" ) << CmpNumber;
|
||
CmpNumber++;
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/***********************************************************************/
|
||
void InstallAnnotateFrame( WinEDA_SchematicFrame* parent, wxPoint& pos )
|
||
/***********************************************************************/
|
||
|
||
/** Function InstallAnnotateFrame
|
||
* Install the annotate dialog frame
|
||
*/
|
||
{
|
||
WinEDA_AnnotateFrame* frame = new WinEDA_AnnotateFrame( parent );
|
||
|
||
frame->ShowModal();
|
||
frame->Destroy();
|
||
}
|
||
|
||
|
||
/******************************************************************/
|
||
void WinEDA_AnnotateFrame::AnnotateComponents( wxCommandEvent& event )
|
||
/******************************************************************/
|
||
|
||
/** Function WinEDA_AnnotateFrame::AnnotateComponents
|
||
* Compute the annotation of the components for the whole projeect, or the current sheet only.
|
||
* All the components or the new ones only will be annotated.
|
||
*/
|
||
{
|
||
int NbSheet, ii, NbOfCmp;
|
||
SCH_SCREEN* screen;
|
||
CmpListStruct* BaseListeCmp;
|
||
|
||
wxBusyCursor dummy;
|
||
|
||
AnnotProject = (m_AnnotProjetCtrl->GetSelection() == 0) ? true : FALSE;
|
||
SortByPosition = (m_AnnotSortCmpCtrl->GetSelection() == 0) ? true : FALSE;
|
||
|
||
/* If it is an annotation for all the components, reset previous annotation: */
|
||
if( m_AnnotNewCmpCtrl->GetSelection() == 0 )
|
||
DeleteAnnotation( event );
|
||
if( m_Abort )
|
||
return;
|
||
|
||
|
||
/* Build the screen list */
|
||
EDA_ScreenList ScreenList( NULL );
|
||
|
||
NbSheet = ScreenList.GetCount();
|
||
|
||
/* Update the sheet number, sheet count and date */
|
||
ScreenSch->SetModify();
|
||
ScreenList.UpdateSheetNumberAndDate();
|
||
|
||
/* First pass: Component counting */
|
||
screen = (SCH_SCREEN*) m_Parent->m_CurrentScreen;
|
||
if( AnnotProject == true )
|
||
{
|
||
NbOfCmp = 0;
|
||
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
|
||
{
|
||
NbOfCmp += ListeComposants( NULL, screen, screen->m_SheetNumber );
|
||
}
|
||
}
|
||
else
|
||
NbOfCmp = ListeComposants( NULL, screen, screen->m_SheetNumber );
|
||
|
||
if( NbOfCmp == 0 )
|
||
return;
|
||
|
||
ii = sizeof(CmpListStruct) * NbOfCmp;
|
||
BaseListeCmp = (CmpListStruct*) MyZMalloc( ii );
|
||
|
||
/* Second pass : Int data tables */
|
||
screen = (SCH_SCREEN*) m_Parent->m_CurrentScreen;
|
||
if( AnnotProject == true )
|
||
{
|
||
ii = 0;
|
||
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
|
||
{
|
||
ii += ListeComposants( BaseListeCmp + ii,
|
||
screen, screen->m_SheetNumber );
|
||
}
|
||
}
|
||
else
|
||
ii = ListeComposants( BaseListeCmp, screen, screen->m_SheetNumber );
|
||
|
||
if( ii != NbOfCmp )
|
||
DisplayError( this, wxT( "Internal error in AnnotateComponents()" ) );
|
||
|
||
/* Break full components reference in name (prefix) and number: example: IC1 become IC, and 1 */
|
||
BreakReference( BaseListeCmp, NbOfCmp );
|
||
|
||
qsort( BaseListeCmp, NbOfCmp, sizeof(CmpListStruct),
|
||
( int( * ) ( const void*, const void* ) )AnnotTriComposant );
|
||
|
||
/* Recalculate reference numbers */
|
||
ComputeReferenceNumber( BaseListeCmp, NbOfCmp );
|
||
ReAnnotateComponents( BaseListeCmp, NbOfCmp );
|
||
|
||
MyFree( BaseListeCmp ); BaseListeCmp = NULL;
|
||
|
||
/* Final control */
|
||
CheckAnnotate( m_Parent, AnnotProject ? FALSE : true );
|
||
|
||
m_Parent->DrawPanel->Refresh( true ); /* Refresh screen */
|
||
EndModal( 1 );
|
||
}
|
||
|
||
|
||
/********************************************************************/
|
||
void WinEDA_AnnotateFrame::DeleteAnnotation( wxCommandEvent& event )
|
||
/********************************************************************/
|
||
|
||
/* Clear the current annotation for the whole project or only for the current sheet
|
||
* Update sheet number and number of sheets
|
||
*/
|
||
{
|
||
int NbSheet;
|
||
SCH_SCREEN* screen;
|
||
EDA_SchComponentStruct* DrawLibItem;
|
||
|
||
if( !IsOK( this, _( "Previous Annotation will be deleted. Continue ?" ) ) )
|
||
{
|
||
m_Abort = true; return;
|
||
}
|
||
|
||
AnnotProject = (m_AnnotProjetCtrl->GetSelection() == 0) ? true : FALSE;
|
||
m_Abort = FALSE;
|
||
|
||
/* Build the screen list */
|
||
EDA_ScreenList ScreenList( NULL );
|
||
|
||
NbSheet = ScreenList.GetCount();
|
||
|
||
/* Update the sheet number, sheet count and date */
|
||
ScreenList.UpdateSheetNumberAndDate();
|
||
|
||
ScreenSch->SetModify();
|
||
|
||
if( AnnotProject == true )
|
||
screen = ScreenList.GetFirst();
|
||
else
|
||
screen = (SCH_SCREEN*) m_Parent->m_CurrentScreen;
|
||
|
||
for( ; screen != NULL; screen = ScreenList.GetNext() )
|
||
{
|
||
EDA_BaseStruct* DrawList = screen->EEDrawList;
|
||
for( ; DrawList != NULL; DrawList = DrawList->Pnext )
|
||
{
|
||
if( DrawList->Type() == DRAW_LIB_ITEM_STRUCT_TYPE )
|
||
{
|
||
DrawLibItem = (EDA_SchComponentStruct*) DrawList;
|
||
DrawLibItem->ClearAnnotation();
|
||
}
|
||
}
|
||
|
||
if( !AnnotProject )
|
||
break;
|
||
}
|
||
|
||
m_Parent->DrawPanel->Refresh( true );
|
||
EndModal( 0 );
|
||
}
|
||
|
||
|
||
/************************************************************************************/
|
||
int ListeComposants( CmpListStruct* BaseListeCmp, SCH_SCREEN* screen, int NumSheet )
|
||
/***********************************************************************************/
|
||
|
||
/* if BaseListeCmp == NULL : Components counting
|
||
* else update data table BaseListeCmp
|
||
*/
|
||
{
|
||
int NbrCmp = 0;
|
||
EDA_BaseStruct* DrawList = screen->EEDrawList;
|
||
EDA_SchComponentStruct* DrawLibItem;
|
||
EDA_LibComponentStruct* Entry;
|
||
|
||
DrawList = screen->EEDrawList;
|
||
for( ; DrawList; DrawList = DrawList->Pnext )
|
||
{
|
||
switch( DrawList->Type() )
|
||
{
|
||
case DRAW_SEGMENT_STRUCT_TYPE:
|
||
case DRAW_JUNCTION_STRUCT_TYPE:
|
||
case DRAW_TEXT_STRUCT_TYPE:
|
||
case DRAW_LABEL_STRUCT_TYPE:
|
||
case DRAW_GLOBAL_LABEL_STRUCT_TYPE:
|
||
break;
|
||
|
||
case DRAW_LIB_ITEM_STRUCT_TYPE:
|
||
DrawLibItem = (EDA_SchComponentStruct*) DrawList;
|
||
Entry = FindLibPart( DrawLibItem->m_ChipName.GetData(), wxEmptyString, FIND_ROOT );
|
||
if( Entry == NULL )
|
||
break;
|
||
|
||
if( BaseListeCmp == NULL ) /* Items counting only */
|
||
{
|
||
NbrCmp++;
|
||
break;
|
||
}
|
||
|
||
BaseListeCmp[NbrCmp].m_Cmp = DrawLibItem;
|
||
BaseListeCmp[NbrCmp].m_NbParts = Entry->m_UnitCount;
|
||
BaseListeCmp[NbrCmp].m_Unit = DrawLibItem->m_Multi;
|
||
BaseListeCmp[NbrCmp].m_PartsLocked = Entry->m_UnitSelectionLocked;
|
||
BaseListeCmp[NbrCmp].m_Sheet = NumSheet;
|
||
BaseListeCmp[NbrCmp].m_IsNew = FALSE;
|
||
BaseListeCmp[NbrCmp].m_Pos = DrawLibItem->m_Pos;
|
||
BaseListeCmp[NbrCmp].m_TimeStamp = DrawLibItem->m_TimeStamp;
|
||
|
||
if( DrawLibItem->m_Field[REFERENCE].m_Text.IsEmpty() )
|
||
DrawLibItem->m_Field[REFERENCE].m_Text = wxT( "DefRef?" );
|
||
|
||
strncpy( BaseListeCmp[NbrCmp].m_TextRef,
|
||
CONV_TO_UTF8( DrawLibItem->m_Field[REFERENCE].m_Text ), 32 );
|
||
|
||
BaseListeCmp[NbrCmp].m_NumRef = -1;
|
||
|
||
if( DrawLibItem->m_Field[VALUE].m_Text.IsEmpty() )
|
||
DrawLibItem->m_Field[VALUE].m_Text = wxT( "~" );
|
||
|
||
strncpy( BaseListeCmp[NbrCmp].m_TextValue,
|
||
CONV_TO_UTF8( DrawLibItem->m_Field[VALUE].m_Text ), 32 );
|
||
NbrCmp++;
|
||
break;
|
||
|
||
case DRAW_PICK_ITEM_STRUCT_TYPE:
|
||
case DRAW_POLYLINE_STRUCT_TYPE:
|
||
case DRAW_BUSENTRY_STRUCT_TYPE:
|
||
case DRAW_SHEET_STRUCT_TYPE:
|
||
case DRAW_SHEETLABEL_STRUCT_TYPE:
|
||
case DRAW_MARKER_STRUCT_TYPE:
|
||
case DRAW_NOCONNECT_STRUCT_TYPE:
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
}
|
||
|
||
return NbrCmp;
|
||
}
|
||
|
||
|
||
/*****************************************************************/
|
||
int AnnotTriComposant( const void* o1, const void* o2 )
|
||
/****************************************************************/
|
||
|
||
/* function used par qsort() for sorting the list
|
||
* Composants are sorted
|
||
* by reference
|
||
* if same reference: by value
|
||
* if same value: by unit number
|
||
* if same unit number, by sheet
|
||
* if same sheet, by time stamp
|
||
**/
|
||
{
|
||
CmpListStruct* Objet1 = (CmpListStruct*) o1;
|
||
CmpListStruct* Objet2 = (CmpListStruct*) o2;
|
||
|
||
int ii = strnicmp( Objet1->m_TextRef, Objet2->m_TextRef, 32 );
|
||
|
||
if( SortByPosition == true )
|
||
{
|
||
if( ii == 0 )
|
||
ii = Objet1->m_Sheet - Objet2->m_Sheet;
|
||
if( ii == 0 )
|
||
ii = Objet1->m_Pos.x - Objet2->m_Pos.x;
|
||
if( ii == 0 )
|
||
ii = Objet1->m_Pos.y - Objet2->m_Pos.y;
|
||
}
|
||
else // Sort by value
|
||
{
|
||
if( ii == 0 )
|
||
ii = strnicmp( Objet1->m_TextValue, Objet2->m_TextValue, 32 );
|
||
if( ii == 0 )
|
||
ii = Objet1->m_Unit - Objet2->m_Unit;
|
||
if( ii == 0 )
|
||
ii = Objet1->m_Sheet - Objet2->m_Sheet;
|
||
if( ii == 0 )
|
||
ii = Objet1->m_Pos.x - Objet2->m_Pos.x;
|
||
if( ii == 0 )
|
||
ii = Objet1->m_Pos.y - Objet2->m_Pos.y;
|
||
}
|
||
|
||
if( ii == 0 )
|
||
ii = Objet1->m_TimeStamp - Objet2->m_TimeStamp;
|
||
|
||
return ii;
|
||
}
|
||
|
||
|
||
/********************************************************************/
|
||
static void ReAnnotateComponents( CmpListStruct* BaseListeCmp, int NbOfCmp )
|
||
/********************************************************************/
|
||
|
||
/* Update the reference component for the schematic project (or the current sheet)
|
||
*/
|
||
{
|
||
int ii;
|
||
char* Text;
|
||
EDA_SchComponentStruct* DrawLibItem;
|
||
|
||
/* Reattribution des numeros */
|
||
for( ii = 0; ii < NbOfCmp; ii++ )
|
||
{
|
||
Text = BaseListeCmp[ii].m_TextRef;
|
||
DrawLibItem = BaseListeCmp[ii].m_Cmp;
|
||
|
||
if( BaseListeCmp[ii].m_NumRef < 0 )
|
||
strcat( Text, "?" );
|
||
else
|
||
sprintf( Text + strlen( Text ), "%d", BaseListeCmp[ii].m_NumRef );
|
||
|
||
DrawLibItem->m_Field[REFERENCE].m_Text = CONV_FROM_UTF8( Text );
|
||
DrawLibItem->m_Multi = BaseListeCmp[ii].m_Unit;
|
||
DrawLibItem->m_RefIdNumber = BaseListeCmp[ii].m_NumRef;
|
||
if( DrawLibItem->m_RefIdNumber < 0 )
|
||
DrawLibItem->m_RefIdNumber = 0;
|
||
}
|
||
}
|
||
|
||
|
||
/**************************************************************/
|
||
void BreakReference( CmpListStruct* BaseListeCmp, int NbOfCmp )
|
||
/**************************************************************/
|
||
|
||
/** BreakReference
|
||
* Break full components reference in name (prefix) and number: example: IC1 become IC, and 1 in .m_NumRef
|
||
* For multi part per package components not already annotated, set .m_Unit to a max value (0x7FFFFFFF)
|
||
* @param BaseListeCmp = list of component
|
||
* @param NbOfCmp = item count in the list
|
||
*/
|
||
{
|
||
int ii, ll;
|
||
char* Text;
|
||
|
||
for( ii = 0; ii < NbOfCmp; ii++ )
|
||
{
|
||
BaseListeCmp[ii].m_NumRef = -1;
|
||
Text = BaseListeCmp[ii].m_TextRef;
|
||
ll = strlen( Text ) - 1;
|
||
if( Text[ll] == '?' )
|
||
{
|
||
BaseListeCmp[ii].m_IsNew = true;
|
||
if( !BaseListeCmp[ii].m_PartsLocked )
|
||
BaseListeCmp[ii].m_Unit = 0x7FFFFFFF;
|
||
Text[ll] = 0;
|
||
continue;
|
||
}
|
||
|
||
if( isdigit( Text[ll] ) == 0 )
|
||
{
|
||
BaseListeCmp[ii].m_IsNew = true;
|
||
if( !BaseListeCmp[ii].m_PartsLocked )
|
||
BaseListeCmp[ii].m_Unit = 0x7FFFFFFF;
|
||
continue;
|
||
}
|
||
|
||
while( ll >= 0 )
|
||
{
|
||
if( (Text[ll] <= ' ' ) || isdigit( Text[ll] ) )
|
||
ll--;
|
||
else
|
||
{
|
||
if( isdigit( Text[ll + 1] ) )
|
||
BaseListeCmp[ii].m_NumRef = atoi( &Text[ll + 1] );
|
||
Text[ll + 1] = 0;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*****************************************************************************/
|
||
static void ComputeReferenceNumber( CmpListStruct* BaseListeCmp, int NbOfCmp )
|
||
/*****************************************************************************/
|
||
|
||
/* Compute the reference number for components without reference number
|
||
* Compute .m_NumRef member
|
||
*/
|
||
{
|
||
int ii, jj, LastReferenceNumber, NumberOfUnits, Unit;
|
||
const char* Text, * RefText, * ValText;
|
||
CmpListStruct* ObjRef, * ObjToTest;
|
||
|
||
/* Components with an invisible reference (power...) always are re-annotated */
|
||
for( ii = 0; ii < NbOfCmp; ii++ )
|
||
{
|
||
Text = BaseListeCmp[ii].m_TextRef;
|
||
if( *Text == '#' )
|
||
{
|
||
BaseListeCmp[ii].m_IsNew = true;
|
||
BaseListeCmp[ii].m_NumRef = 0;
|
||
}
|
||
}
|
||
|
||
ValText = RefText = ""; LastReferenceNumber = 1;
|
||
for( ii = 0; ii < NbOfCmp; ii++ )
|
||
{
|
||
ObjRef = &BaseListeCmp[ii];
|
||
if( BaseListeCmp[ii].m_Flag )
|
||
continue;
|
||
|
||
Text = BaseListeCmp[ii].m_TextRef;
|
||
if( strnicmp( RefText, Text, 32 ) != 0 ) /* Nouveau Identificateur */
|
||
{
|
||
RefText = BaseListeCmp[ii].m_TextRef;
|
||
LastReferenceNumber = GetLastReferenceNumber( BaseListeCmp + ii, BaseListeCmp, NbOfCmp );
|
||
}
|
||
|
||
/* Annotation of one part per package components (trivial case)*/
|
||
if( BaseListeCmp[ii].m_NbParts <= 1 )
|
||
{
|
||
if( BaseListeCmp[ii].m_IsNew )
|
||
{
|
||
LastReferenceNumber++;
|
||
BaseListeCmp[ii].m_NumRef = LastReferenceNumber;
|
||
}
|
||
BaseListeCmp[ii].m_Unit = 1;
|
||
BaseListeCmp[ii].m_Flag = 1;
|
||
BaseListeCmp[ii].m_IsNew = FALSE;
|
||
continue;
|
||
}
|
||
|
||
/* Annotation of multi-part components ( n parts per package ) (complex case) */
|
||
ValText = BaseListeCmp[ii].m_TextValue;
|
||
NumberOfUnits = BaseListeCmp[ii].m_NbParts;
|
||
|
||
if( BaseListeCmp[ii].m_IsNew )
|
||
{
|
||
LastReferenceNumber++; BaseListeCmp[ii].m_NumRef = LastReferenceNumber;
|
||
if( !BaseListeCmp[ii].m_PartsLocked )
|
||
BaseListeCmp[ii].m_Unit = 1;
|
||
BaseListeCmp[ii].m_Flag = 1;
|
||
}
|
||
|
||
for( Unit = 1; Unit <= NumberOfUnits; Unit++ )
|
||
{
|
||
if( BaseListeCmp[ii].m_Unit == Unit )
|
||
continue;
|
||
jj = ExistUnit( BaseListeCmp + ii, Unit, BaseListeCmp, NbOfCmp );
|
||
if( jj >= 0 )
|
||
continue; /* Unit exists for this reference */
|
||
|
||
/* Search a component to annotate ( same prefix, same value) */
|
||
for( jj = ii + 1; jj < NbOfCmp; jj++ )
|
||
{
|
||
ObjToTest = &BaseListeCmp[jj];
|
||
if( BaseListeCmp[jj].m_Flag )
|
||
continue;
|
||
Text = BaseListeCmp[jj].m_TextRef;
|
||
if( strnicmp( RefText, Text, 32 ) != 0 )
|
||
continue; // references are different
|
||
Text = BaseListeCmp[jj].m_TextValue;
|
||
if( strnicmp( ValText, Text, 32 ) != 0 )
|
||
continue; // values are different
|
||
if( !BaseListeCmp[jj].m_IsNew )
|
||
{
|
||
continue;
|
||
}
|
||
/* Component without reference number found, annotate it if possible */
|
||
if( !BaseListeCmp[jj].m_PartsLocked || (BaseListeCmp[jj].m_Unit == Unit) )
|
||
{
|
||
BaseListeCmp[jj].m_NumRef = BaseListeCmp[ii].m_NumRef;
|
||
BaseListeCmp[jj].m_Unit = Unit;
|
||
BaseListeCmp[jj].m_Flag = 1;
|
||
BaseListeCmp[jj].m_IsNew = FALSE;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
/*************************************************************************************************/
|
||
static int GetLastReferenceNumber( CmpListStruct* Objet, CmpListStruct* BaseListeCmp, int NbOfCmp )
|
||
/*************************************************************************************************/
|
||
|
||
/** Function GetLastReferenceNumber
|
||
* Search the last (bigger) reference number in the component list
|
||
* for the prefix reference given by Objet
|
||
* The component list must be sorted
|
||
* @param Objet = reference item ( Objet->m_TextRef is the search pattern)
|
||
* @param BaseListeCmp = list of items
|
||
* @param NbOfCmp = items count in list of items
|
||
*/
|
||
{
|
||
CmpListStruct* LastObjet = BaseListeCmp + NbOfCmp;
|
||
int LastNumber = 0;
|
||
const char* RefText;
|
||
|
||
RefText = Objet->m_TextRef;
|
||
for( ; Objet < LastObjet; Objet++ )
|
||
{
|
||
if( strnicmp( RefText, Objet->m_TextRef, 32 ) != 0 ) /* Nouveau Identificateur */
|
||
break;
|
||
if( LastNumber < Objet->m_NumRef )
|
||
LastNumber = Objet->m_NumRef;
|
||
}
|
||
|
||
return LastNumber;
|
||
}
|
||
|
||
|
||
/*****************************************************************/
|
||
static int ExistUnit( CmpListStruct* Objet, int Unit,
|
||
CmpListStruct* BaseListeCmp, int NbOfCmp )
|
||
/****************************************************************/
|
||
|
||
/* Recherche dans la liste triee des composants, pour les composants
|
||
* multiples s'il existe pour le composant de reference Objet,
|
||
* une unite de numero Unit
|
||
* Retourne index dans BaseListeCmp si oui
|
||
* retourne -1 si non
|
||
*/
|
||
{
|
||
CmpListStruct* EndList = BaseListeCmp + NbOfCmp;
|
||
char* RefText, * ValText;
|
||
int NumRef, ii;
|
||
CmpListStruct* ItemToTest;
|
||
|
||
RefText = Objet->m_TextRef;
|
||
ValText = Objet->m_TextValue;
|
||
NumRef = Objet->m_NumRef;
|
||
for( ItemToTest = BaseListeCmp, ii = 0; ItemToTest < EndList; ItemToTest++, ii++ )
|
||
{
|
||
if( Objet == ItemToTest )
|
||
continue;
|
||
if( ItemToTest->m_IsNew )
|
||
continue; /* non affecte */
|
||
if( ItemToTest->m_NumRef != NumRef )
|
||
continue;
|
||
if( strnicmp( RefText, ItemToTest->m_TextRef, 32 ) != 0 ) /* Nouveau Identificateur */
|
||
continue;
|
||
if( ItemToTest->m_Unit == Unit )
|
||
{
|
||
return ii;
|
||
}
|
||
}
|
||
|
||
return -1;
|
||
}
|
||
|
||
|
||
/******************************************************************/
|
||
int CheckAnnotate( WinEDA_SchematicFrame* frame, bool OneSheetOnly )
|
||
/******************************************************************/
|
||
|
||
/** Function CheckAnnotate
|
||
* @return composent count ( which are not annotated or have the same reference (duplicates))
|
||
* @param OneSheetOnly : true = search is made only in the current sheet
|
||
* false = search in whole hierarchy (usual search).
|
||
*/
|
||
{
|
||
int NbSheet, ii, NumSheet = 1, error, NbOfCmp;
|
||
SCH_SCREEN* screen;
|
||
CmpListStruct* ListeCmp = NULL;
|
||
wxString Buff;
|
||
wxString msg, cmpref;
|
||
|
||
/* build the screen list */
|
||
EDA_ScreenList ScreenList( NULL );
|
||
|
||
NbSheet = ScreenList.GetCount();
|
||
|
||
/* Update the sheet number, sheet count and date */
|
||
ScreenSch->SetModify();
|
||
ScreenList.UpdateSheetNumberAndDate();
|
||
|
||
/* first pass : count composents */
|
||
screen = (SCH_SCREEN*) frame->m_CurrentScreen;
|
||
if( !OneSheetOnly )
|
||
{
|
||
NbOfCmp = 0;
|
||
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
|
||
{
|
||
NbOfCmp += ListeComposants( NULL, screen, NumSheet );
|
||
}
|
||
}
|
||
else
|
||
NbOfCmp = ListeComposants( NULL, screen, NumSheet );
|
||
|
||
if( NbOfCmp == 0 )
|
||
{
|
||
wxBell();
|
||
return 0;
|
||
}
|
||
|
||
|
||
/* Second pass : create the list of components */
|
||
ii = sizeof(CmpListStruct) * NbOfCmp;
|
||
ListeCmp = (CmpListStruct*) MyZMalloc( ii );
|
||
|
||
if( OneSheetOnly == 0 )
|
||
{
|
||
ii = 0;
|
||
screen = ScreenSch;
|
||
for( screen = ScreenList.GetFirst(); screen != NULL; screen = ScreenList.GetNext() )
|
||
{
|
||
ii += ListeComposants( ListeCmp + ii, screen, NumSheet );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
screen = (SCH_SCREEN*) frame->m_CurrentScreen;
|
||
ListeComposants( ListeCmp, screen, NumSheet );
|
||
}
|
||
|
||
qsort( ListeCmp, NbOfCmp, sizeof(CmpListStruct), AnnotTriComposant );
|
||
|
||
/* Break full components reference in name (prefix) and number: example: IC1 become IC, and 1 */
|
||
BreakReference( ListeCmp, NbOfCmp );
|
||
|
||
/* count not yet annotated items */
|
||
error = 0;
|
||
for( ii = 0; ii < NbOfCmp - 1; ii++ )
|
||
{
|
||
msg.Empty();
|
||
Buff.Empty();
|
||
|
||
if( ListeCmp[ii].m_IsNew )
|
||
{
|
||
if( ListeCmp[ii].m_NumRef >= 0 )
|
||
Buff << ListeCmp[ii].m_NumRef;
|
||
else
|
||
Buff = wxT( "?" );
|
||
|
||
cmpref = CONV_FROM_UTF8( ListeCmp[ii].m_TextRef );
|
||
msg.Printf( _( "item not annotated: %s%s" ), cmpref.GetData(), Buff.GetData() );
|
||
|
||
if( (ListeCmp[ii].m_Unit > 0) && (ListeCmp[ii].m_Unit < 0x7FFFFFFF) )
|
||
{
|
||
Buff.Printf( _( "( unit %d)" ), ListeCmp[ii].m_Unit );
|
||
msg << Buff;
|
||
}
|
||
DisplayError( NULL, msg );
|
||
error++;
|
||
break;
|
||
}
|
||
|
||
if( MAX( ListeCmp[ii].m_NbParts, 1 ) < ListeCmp[ii].m_Unit ) // Annotate error
|
||
{
|
||
if( ListeCmp[ii].m_NumRef >= 0 )
|
||
Buff << ListeCmp[ii].m_NumRef;
|
||
else
|
||
Buff = wxT( "?" );
|
||
|
||
cmpref = CONV_FROM_UTF8( ListeCmp[ii].m_TextRef );
|
||
msg.Printf( _( "Error item %s%s" ), cmpref.GetData(), Buff.GetData() );
|
||
|
||
Buff.Printf( _( " unit %d and no more than %d parts" ),
|
||
ListeCmp[ii].m_Unit, ListeCmp[ii].m_NbParts );
|
||
msg << Buff;
|
||
DisplayError( frame, msg );
|
||
error++;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if( error )
|
||
return error;
|
||
|
||
// count the duplicated elements (if all are annotated)
|
||
for( ii = 0; (ii < NbOfCmp - 1) && (error < 4); ii++ )
|
||
{
|
||
msg.Empty();
|
||
Buff.Empty();
|
||
|
||
if( (stricmp( ListeCmp[ii].m_TextRef, ListeCmp[ii + 1].m_TextRef ) != 0)
|
||
|| ( ListeCmp[ii].m_NumRef != ListeCmp[ii + 1].m_NumRef ) )
|
||
continue;
|
||
|
||
/* Same reference found */
|
||
|
||
/* If same unit, error ! */
|
||
if( ListeCmp[ii].m_Unit == ListeCmp[ii + 1].m_Unit )
|
||
{
|
||
if( ListeCmp[ii].m_NumRef >= 0 )
|
||
Buff << ListeCmp[ii].m_NumRef;
|
||
else
|
||
Buff = wxT( "?" );
|
||
|
||
cmpref = CONV_FROM_UTF8( ListeCmp[ii].m_TextRef );
|
||
msg.Printf( _( "Multiple item %s%s" ),
|
||
cmpref.GetData(), Buff.GetData() );
|
||
|
||
if( (ListeCmp[ii].m_Unit > 0) && (ListeCmp[ii].m_Unit < 0x7FFFFFFF) )
|
||
{
|
||
Buff.Printf( _( " (unit %d)" ), ListeCmp[ii].m_Unit );
|
||
msg << Buff;
|
||
}
|
||
DisplayError( frame, msg );
|
||
error++;
|
||
continue;
|
||
}
|
||
|
||
/* Test error if units are different but number of parts per package too hight
|
||
* (ex U3 ( 1 part) and we find U3B the is an error) */
|
||
if( ListeCmp[ii].m_NbParts != ListeCmp[ii + 1].m_NbParts )
|
||
{
|
||
if( ListeCmp[ii].m_NumRef >= 0 )
|
||
Buff << ListeCmp[ii].m_NumRef;
|
||
else
|
||
Buff = wxT( "?" );
|
||
|
||
cmpref = CONV_FROM_UTF8( ListeCmp[ii].m_TextRef );
|
||
msg.Printf( _( "Multiple item %s%s" ), cmpref.GetData(), Buff.GetData() );
|
||
|
||
if( (ListeCmp[ii].m_Unit > 0) && (ListeCmp[ii].m_Unit < 0x7FFFFFFF) )
|
||
{
|
||
Buff.Printf( _( " (unit %d)" ), ListeCmp[ii].m_Unit );
|
||
msg << Buff;
|
||
}
|
||
|
||
DisplayError( frame, msg );
|
||
error++;
|
||
}
|
||
|
||
/* Error if values are diff<66>rent between units, for the same reference */
|
||
if( stricmp( ListeCmp[ii].m_TextValue, ListeCmp[ii + 1].m_TextValue ) != 0 )
|
||
{
|
||
wxString nextcmpref, cmpvalue, nextcmpvalue;
|
||
cmpref = CONV_FROM_UTF8( ListeCmp[ii].m_TextRef );
|
||
nextcmpref = CONV_FROM_UTF8( ListeCmp[ii + 1].m_TextRef );
|
||
cmpvalue = CONV_FROM_UTF8( ListeCmp[ii].m_TextValue );
|
||
nextcmpvalue = CONV_FROM_UTF8( ListeCmp[ii + 1].m_TextValue );
|
||
msg.Printf( _( "Diff values for %s%d%c (%s) and %s%d%c (%s)" ),
|
||
cmpref.GetData(), ListeCmp[ii].m_NumRef, ListeCmp[ii].m_Unit + 'A' - 1,
|
||
cmpvalue.GetData(), nextcmpref.GetData(),
|
||
ListeCmp[ii + 1].m_NumRef,
|
||
ListeCmp[ii + 1].m_Unit + 'A' - 1,
|
||
nextcmpvalue.GetData() );
|
||
|
||
DisplayError( frame, msg );
|
||
error++;
|
||
}
|
||
}
|
||
|
||
MyFree( ListeCmp );
|
||
return error;
|
||
}
|