/**************************************/ /* 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, DrawSheetList* sheet ); 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 (screen, not sheet) */ EDA_SheetList SheetList( NULL ); /* Update the screen number, sheet count and date */ //ScreenList.UpdateScreenNumberAndDate(); DrawSheetList* sheet; int CmpNumber = 1; for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext()) { EDA_BaseStruct* DrawList = sheet->LastDrawList(); 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(sheet); this clears all annotation :( wxString refstr = DrawLibItem->m_PrefixString; //str will be "C?" or so after the ClearAnnotation call. while(refstr.Last() == '?') refstr.RemoveLast(); if(!refstr.StartsWith(wxT("#"))) refstr = wxT("#") + refstr; refstr << wxT( "0" ) << CmpNumber; DrawLibItem->SetRef(sheet, refstr); CmpNumber++; } } } /***********************************************************************/ CmpListStruct* AllocateCmpListStrct(int numcomponents ) /***********************************************************************/ { int ii = numcomponents * sizeof(CmpListStruct); CmpListStruct* list = (CmpListStruct*) MyZMalloc( ii ); //fill this memory with zeros. char* cptr = (char*)list; for(int i=0; iShowModal(); frame->Destroy(); } /******************************************************************/ void WinEDA_AnnotateFrame::AnnotateComponents( wxCommandEvent& event ) /******************************************************************/ /** Function WinEDA_AnnotateFrame::AnnotateComponents * Compute the annotation of the components for the whole project, or the current sheet only. * All the components or the new ones only will be annotated. */ { int ii, NbOfCmp; DrawSheetList* sheet; 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 sheet list */ EDA_SheetList SheetList( g_RootSheet ); /* Update the sheet number */ ii = 0; /* First pass: Component counting */ sheet = m_Parent->GetSheet(); if( AnnotProject == true ){ NbOfCmp = 0; for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) NbOfCmp += ListeComposants( NULL, sheet ); } else NbOfCmp = ListeComposants( NULL, sheet ); if( NbOfCmp == 0 ) return; BaseListeCmp = AllocateCmpListStrct(NbOfCmp); /* Second pass : Int data tables */ if( AnnotProject == true ) { ii = 0; for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) ii += ListeComposants( BaseListeCmp + ii, sheet); } else ii = ListeComposants( BaseListeCmp, sheet); 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 */ { DrawSheetStruct* sheet; //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; if( AnnotProject == true ) sheet = g_RootSheet; else sheet = m_Parent->GetSheet()->Last(); sheet->DeleteAnnotation( AnnotProject ); /* 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; } */ g_RootSheet->m_s->SetModify(); m_Parent->DrawPanel->Refresh( true ); //EndModal( 0 ); } /************************************************************************************/ int ListeComposants( CmpListStruct* BaseListeCmp, DrawSheetList* sheet) /***********************************************************************************/ /* if BaseListeCmp == NULL : count components * else update data table BaseListeCmp */ { int NbrCmp = 0; EDA_BaseStruct* DrawList = sheet->LastDrawList(); EDA_SchComponentStruct* DrawLibItem; EDA_LibComponentStruct* Entry; 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: case DRAW_HIER_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_SheetList = *sheet; BaseListeCmp[NbrCmp].m_IsNew = FALSE; BaseListeCmp[NbrCmp].m_Pos = DrawLibItem->m_Pos; BaseListeCmp[NbrCmp].m_TimeStamp = DrawLibItem->m_TimeStamp; if( DrawLibItem->GetRef(sheet).IsEmpty() ) DrawLibItem->SetRef( sheet, wxT( "DefRef?" ) ); strncpy( BaseListeCmp[NbrCmp].m_TextRef, CONV_TO_UTF8(DrawLibItem->GetRef(sheet)), 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_SheetList.Cmp(Objet2->m_SheetList); 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_SheetList.Cmp(Objet2->m_SheetList); 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->SetRef(&(BaseListeCmp[ii].m_SheetList), CONV_FROM_UTF8( Text ) ); DrawLibItem->m_Multi = BaseListeCmp[ii].m_Unit; } } /**************************************************************/ 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; } } /*printf("BreakReference(): %s number found: %d\n", BaseListeCmp[ii].m_TextRef, BaseListeCmp[ii].m_NumRef); */ } } /*****************************************************************************/ 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 ii, error, NbOfCmp; DrawSheetList* sheet; CmpListStruct* ListeCmp = NULL; wxString Buff; wxString msg, cmpref; /* build the screen list */ EDA_SheetList SheetList( NULL ); g_RootSheet->m_s->SetModify(); ii = 0; /* first pass : count composents */ if( !OneSheetOnly ){ NbOfCmp = 0; for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) NbOfCmp += ListeComposants( NULL, sheet ); } else NbOfCmp = ListeComposants( NULL, frame->GetSheet() ); if( NbOfCmp == 0 ) { wxBell(); return 0; } /* Second pass : create the list of components */ ListeCmp = AllocateCmpListStrct(NbOfCmp); printf("CheckAnnotate() listing all components:\n"); if( !OneSheetOnly ){ ii = 0; for( sheet = SheetList.GetFirst(); sheet != NULL; sheet = SheetList.GetNext() ) ii += ListeComposants( ListeCmp + ii, sheet ); } else ListeComposants( ListeCmp, frame->GetSheet() ); printf("CheckAnnotate() done:\n"); 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�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; }