1032 lines
30 KiB
C++
1032 lines
30 KiB
C++
/************************************/
|
||
/* PCBNEW: traitement des netlistes */
|
||
/************************************/
|
||
|
||
/* Fichier NETLIST.CPP */
|
||
|
||
/*
|
||
* Fonction de lecture de la netliste pour:
|
||
* - Chargement modules et nouvelles connexions
|
||
* - Test des modules (modules manquants ou en trop
|
||
* - Recalcul du chevelu
|
||
*
|
||
* Remarque importante:
|
||
* Lors de la lecture de la netliste pour Chargement modules
|
||
* et nouvelles connexions, l'identification des modules peut se faire selon
|
||
* 2 criteres:
|
||
* - la reference (U2, R5 ..): c'est le mode normal
|
||
* - le Time Stamp (Signature Temporelle), a utiliser apres reannotation
|
||
* d'un schema, donc apres modification des references sans pourtant
|
||
* avoir reellement modifie le schema
|
||
*/
|
||
#include "fctsys.h"
|
||
#include "gr_basic.h"
|
||
#include "common.h"
|
||
#include "pcbnew.h"
|
||
#include "autorout.h"
|
||
|
||
#include "protos.h"
|
||
|
||
#define TESTONLY 1 /* ctes utilisees lors de l'appel a */
|
||
#define READMODULE 0 /* ReadNetModuleORCADPCB */
|
||
|
||
/* Structures locales */
|
||
class MODULEtoLOAD : public EDA_BaseStruct
|
||
{
|
||
public:
|
||
wxString m_LibName;
|
||
wxString m_CmpName;
|
||
|
||
public:
|
||
MODULEtoLOAD( const wxString& libname, const wxString& cmpname, int timestamp );
|
||
~MODULEtoLOAD() { };
|
||
MODULEtoLOAD* Next() { return (MODULEtoLOAD*) Pnext; }
|
||
};
|
||
|
||
/* Fonctions locales : */
|
||
static void SortListModulesToLoadByLibname( int NbModules );
|
||
|
||
|
||
/* Variables locales */
|
||
static int s_NbNewModules;
|
||
static MODULEtoLOAD* s_ModuleToLoad_List;
|
||
FILE* source;
|
||
static bool ChangeExistantModule;
|
||
static bool DisplayWarning = TRUE;
|
||
static int DisplayWarningCount;
|
||
|
||
/*****************************/
|
||
/* class WinEDA_NetlistFrame */
|
||
/*****************************/
|
||
#include "dialog_netlist.cpp"
|
||
|
||
|
||
/*************************************************************************/
|
||
void WinEDA_PcbFrame::InstallNetlistFrame( wxDC* DC, const wxPoint& pos )
|
||
/*************************************************************************/
|
||
{
|
||
WinEDA_NetlistFrame* frame = new WinEDA_NetlistFrame( this, DC );
|
||
|
||
frame->ShowModal(); frame->Destroy();
|
||
}
|
||
|
||
|
||
/***************************************************************/
|
||
bool WinEDA_NetlistFrame::OpenNetlistFile( wxCommandEvent& event )
|
||
/***************************************************************/
|
||
|
||
/*
|
||
* routine de selection et d'ouverture du fichier Netlist
|
||
*/
|
||
{
|
||
wxString FullFileName;
|
||
wxString msg;
|
||
|
||
if( NetNameBuffer.IsEmpty() ) /* Pas de nom specifie */
|
||
Set_NetlisteName( event );
|
||
|
||
if( NetNameBuffer.IsEmpty() )
|
||
return FALSE; /* toujours Pas de nom specifie */
|
||
|
||
FullFileName = NetNameBuffer;
|
||
|
||
source = wxFopen( FullFileName, wxT( "rt" ) );
|
||
if( source == 0 )
|
||
{
|
||
msg.Printf( _( "Netlist file %s not found" ), FullFileName.GetData() );
|
||
DisplayError( this, msg );
|
||
return FALSE;
|
||
}
|
||
|
||
msg = wxT( "Netlist " ); msg << FullFileName;
|
||
SetTitle( msg );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/**************************************************************/
|
||
void WinEDA_NetlistFrame::ReadPcbNetlist( wxCommandEvent& event )
|
||
/**************************************************************/
|
||
|
||
/* mise a jour des empreintes :
|
||
* corrige les Net Names, les textes, les "TIME STAMP"
|
||
*
|
||
* Analyse les lignes:
|
||
# EESchema Netlist Version 1.0 generee le 18/5/2005-12:30:22
|
||
* (
|
||
* ( 40C08647 $noname R20 4,7K {Lib=R}
|
||
* ( 1 VCC )
|
||
* ( 2 MODB_1 )
|
||
* )
|
||
* ( 40C0863F $noname R18 4,7_k {Lib=R}
|
||
* ( 1 VCC )
|
||
* ( 2 MODA_1 )
|
||
* )
|
||
* }
|
||
#End
|
||
*/
|
||
{
|
||
int LineNum, State, Comment;
|
||
MODULE* Module = NULL;
|
||
D_PAD* PtPad;
|
||
char Line[256], * Text;
|
||
int UseFichCmp = 1;
|
||
wxString msg;
|
||
|
||
ChangeExistantModule = m_ChangeExistantModuleCtrl->GetSelection() == 1 ? TRUE : FALSE;
|
||
DisplayWarning = m_DisplayWarningCtrl->GetValue();
|
||
if( DisplayWarning )
|
||
DisplayWarningCount = 8;
|
||
else
|
||
DisplayWarningCount = 0;
|
||
|
||
if( !OpenNetlistFile( event ) )
|
||
return;
|
||
|
||
msg = _( "Read Netlist " ) + NetNameBuffer;
|
||
m_MessageWindow->AppendText( msg );
|
||
|
||
m_Parent->m_CurrentScreen->SetModify();
|
||
m_Parent->m_Pcb->m_Status_Pcb = 0; State = 0; LineNum = 0; Comment = 0;
|
||
s_NbNewModules = 0;
|
||
|
||
/* Premiere lecture de la netliste: etablissement de la liste
|
||
* des modules a charger
|
||
*/
|
||
while( GetLine( source, Line, &LineNum ) )
|
||
{
|
||
Text = StrPurge( Line );
|
||
|
||
if( Comment ) /* Commentaires en cours */
|
||
{
|
||
if( ( Text = strchr( Text, '}' ) ) == NULL )
|
||
continue;
|
||
Comment = 0;
|
||
}
|
||
if( *Text == '{' ) /* Commentaires */
|
||
{
|
||
Comment = 1;
|
||
if( ( Text = strchr( Text, '}' ) ) == NULL )
|
||
continue;
|
||
}
|
||
|
||
if( *Text == '(' )
|
||
State++;
|
||
if( *Text == ')' )
|
||
State--;
|
||
|
||
if( State == 2 )
|
||
{
|
||
Module = ReadNetModule( Text, &UseFichCmp, TESTONLY );
|
||
continue;
|
||
}
|
||
|
||
if( State >= 3 ) /* la ligne de description d'un pad est ici non analysee */
|
||
{
|
||
State--;
|
||
}
|
||
}
|
||
|
||
/* Chargement des nouveaux modules */
|
||
if( s_NbNewModules )
|
||
{
|
||
LoadListeModules( m_DC );
|
||
|
||
// Free module list:
|
||
MODULEtoLOAD* item, * next_item;
|
||
for( item = s_ModuleToLoad_List; item != NULL; item = next_item )
|
||
{
|
||
next_item = item->Next();
|
||
delete item;
|
||
}
|
||
|
||
s_ModuleToLoad_List = NULL;
|
||
}
|
||
|
||
/* Relecture de la netliste, tous les modules sont ici charges */
|
||
fseek( source, 0, SEEK_SET ); LineNum = 0;
|
||
while( GetLine( source, Line, &LineNum ) )
|
||
{
|
||
Text = StrPurge( Line );
|
||
|
||
if( Comment ) /* Commentaires en cours */
|
||
{
|
||
if( ( Text = strchr( Text, '}' ) ) == NULL )
|
||
continue;
|
||
Comment = 0;
|
||
}
|
||
if( *Text == '{' ) /* Commentaires */
|
||
{
|
||
Comment = 1;
|
||
if( ( Text = strchr( Text, '}' ) ) == NULL )
|
||
continue;
|
||
}
|
||
|
||
if( *Text == '(' )
|
||
State++;
|
||
if( *Text == ')' )
|
||
State--;
|
||
|
||
if( State == 2 )
|
||
{
|
||
Module = ReadNetModule( Text, &UseFichCmp, READMODULE );
|
||
if( Module == NULL )
|
||
{ /* empreinte non trouvee dans la netliste */
|
||
continue;
|
||
}
|
||
else /* Raz netnames sur pads */
|
||
{
|
||
PtPad = Module->m_Pads;
|
||
for( ; PtPad != NULL; PtPad = (D_PAD*) PtPad->Pnext )
|
||
{
|
||
PtPad->m_Netname = wxEmptyString;
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if( State >= 3 )
|
||
{
|
||
if( Module )
|
||
{
|
||
SetPadNetName( Text, Module );
|
||
}
|
||
State--;
|
||
}
|
||
}
|
||
|
||
fclose( source );
|
||
|
||
/* Mise a jour et Cleanup du circuit imprime: */
|
||
m_Parent->Compile_Ratsnest( m_DC, TRUE );
|
||
|
||
if( m_Parent->m_Pcb->m_Track )
|
||
{
|
||
if( m_DeleteBadTracks->GetSelection() == 1 )
|
||
{
|
||
wxBeginBusyCursor();;
|
||
Netliste_Controle_piste( m_Parent, m_DC, TRUE );
|
||
m_Parent->Compile_Ratsnest( m_DC, TRUE );
|
||
wxEndBusyCursor();;
|
||
}
|
||
}
|
||
|
||
m_Parent->m_Pcb->Display_Infos( m_Parent );
|
||
}
|
||
|
||
|
||
/****************************************************************************/
|
||
MODULE* WinEDA_NetlistFrame::ReadNetModule( char* Text, int* UseFichCmp,
|
||
int TstOnly )
|
||
/****************************************************************************/
|
||
|
||
/* charge la description d'une empreinte ,netliste type PCBNEW
|
||
* et met a jour le module correspondant
|
||
*
|
||
* Si TstOnly == 0 si le module n'existe pas, il est charge
|
||
* Si TstOnly != 0 si le module n'existe pas, il est ajoute a la liste des
|
||
* modules a charger
|
||
* Text contient la premiere ligne de la description
|
||
* UseFichCmp est un flag
|
||
* si != 0, le fichier des composants .CMP sera utilise
|
||
* est remis a 0 si le fichier n'existe pas
|
||
*
|
||
* Analyse les lignes type:
|
||
* ( 40C08647 $noname R20 4,7K {Lib=R}
|
||
* ( 1 VCC )
|
||
* ( 2 MODB_1 )
|
||
*/
|
||
{
|
||
MODULE* Module;
|
||
char* text;
|
||
wxString TextTimeStamp;
|
||
wxString TextNameLibMod;
|
||
wxString TextValeur;
|
||
wxString TextCmpName;
|
||
wxString NameLibCmp;
|
||
unsigned long TimeStamp = 0;
|
||
int Error = 0;
|
||
char Line[1024];
|
||
bool Found;
|
||
|
||
strcpy( Line, Text );
|
||
|
||
TextValeur = wxT( "~" );
|
||
if( ( text = strtok( Line, " ()\t\n" ) ) == NULL )
|
||
Error = 1;
|
||
else
|
||
TextTimeStamp = CONV_FROM_UTF8( text );
|
||
if( ( text = strtok( NULL, " ()\t\n" ) ) == NULL )
|
||
Error = 1;
|
||
else
|
||
TextNameLibMod = CONV_FROM_UTF8( text );
|
||
if( ( text = strtok( NULL, " ()\t\n" ) ) == NULL )
|
||
Error = 1;
|
||
else
|
||
TextCmpName = CONV_FROM_UTF8( text );
|
||
if( ( text = strtok( NULL, " ()\t\n" ) ) == NULL )
|
||
Error = -1;
|
||
else
|
||
TextValeur = CONV_FROM_UTF8( text );
|
||
|
||
if( Error > 0 )
|
||
return NULL;
|
||
|
||
TextTimeStamp.ToULong( &TimeStamp, 16 );
|
||
|
||
/* Tst si composant deja charge */
|
||
Module = (MODULE*) m_Parent->m_Pcb->m_Modules;
|
||
MODULE* NextModule;
|
||
for( Found = FALSE; Module != NULL; Module = NextModule )
|
||
{
|
||
NextModule = (MODULE*) Module->Pnext;
|
||
if( m_Select_By_Timestamp->GetSelection() == 1 ) /* Reconnaissance par signature temporelle */
|
||
{
|
||
if( TimeStamp == Module->m_TimeStamp )
|
||
Found = TRUE;
|
||
}
|
||
else /* Reconnaissance par Reference */
|
||
{
|
||
if( TextCmpName.CmpNoCase( Module->m_Reference->m_Text ) == 0 )
|
||
Found = TRUE;
|
||
}
|
||
if( Found ) // Test si module (m_LibRef) et module specifie en netlist concordent
|
||
{
|
||
if( TstOnly != TESTONLY )
|
||
{
|
||
NameLibCmp = TextNameLibMod;
|
||
if( *UseFichCmp )
|
||
{
|
||
if( m_Select_By_Timestamp->GetSelection() == 1 )
|
||
{ /* Reconnaissance par signature temporelle */
|
||
*UseFichCmp = ReadListeModules( NULL, TimeStamp, NameLibCmp );
|
||
}
|
||
else /* Reconnaissance par Reference */
|
||
{
|
||
*UseFichCmp = ReadListeModules( &TextCmpName, 0l, NameLibCmp );
|
||
}
|
||
}
|
||
if( Module->m_LibRef.CmpNoCase( NameLibCmp ) != 0 )
|
||
{ // Module Mismatch: Current module and module specified in netlist are diff.
|
||
if( ChangeExistantModule )
|
||
{
|
||
MODULE* NewModule =
|
||
m_Parent->Get_Librairie_Module( this, wxEmptyString, NameLibCmp, TRUE );
|
||
if( NewModule ) /* Nouveau module trouve : changement de module */
|
||
Module = m_Parent->Exchange_Module( this, Module, NewModule );
|
||
}
|
||
else
|
||
{
|
||
wxString msg;
|
||
msg.Printf(
|
||
_( "Cmp %s: Mismatch! module is [%s] and netlist said [%s]\n" ),
|
||
TextCmpName.GetData(), Module->m_LibRef.GetData(),
|
||
NameLibCmp.GetData() );
|
||
m_MessageWindow->AppendText( msg );
|
||
if( DisplayWarningCount > 0 )
|
||
{
|
||
DisplayError( this, msg, 2 );
|
||
DisplayWarningCount--;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
break;
|
||
}
|
||
}
|
||
|
||
if( Module == NULL ) /* Module a charger */
|
||
{
|
||
NameLibCmp = TextNameLibMod;
|
||
|
||
if( *UseFichCmp )
|
||
{
|
||
if( m_Select_By_Timestamp->GetSelection() == 1 )
|
||
{ /* Reconnaissance par signature temporelle */
|
||
*UseFichCmp = ReadListeModules( NULL, TimeStamp, NameLibCmp );
|
||
}
|
||
else /* Reconnaissance par Reference */
|
||
{
|
||
*UseFichCmp = ReadListeModules( &TextCmpName, 0l, NameLibCmp );
|
||
}
|
||
}
|
||
|
||
|
||
if( TstOnly == TESTONLY )
|
||
AddToList( NameLibCmp, TextCmpName, TimeStamp );
|
||
else
|
||
{
|
||
wxString msg;
|
||
msg.Printf( _( "Component [%s] not found" ), TextCmpName.GetData() );
|
||
m_MessageWindow->AppendText( msg + wxT( "\n" ) );
|
||
if( DisplayWarningCount> 0 )
|
||
{
|
||
DisplayError( this, msg, 2 );
|
||
DisplayWarningCount--;
|
||
}
|
||
}
|
||
return NULL; /* Le module n'avait pas pu etre charge */
|
||
}
|
||
|
||
/* mise a jour des reperes ( nom et ref "Time Stamp") si module charge */
|
||
Module->m_Reference->m_Text = TextCmpName;
|
||
Module->m_Value->m_Text = TextValeur;
|
||
Module->m_TimeStamp = TimeStamp;
|
||
|
||
return Module; /* composant trouve */
|
||
}
|
||
|
||
|
||
/********************************************************************/
|
||
int WinEDA_NetlistFrame::SetPadNetName( char* Text, MODULE* Module )
|
||
/********************************************************************/
|
||
|
||
/*
|
||
* Met a jour le netname de 1 pastille, Netliste ORCADPCB
|
||
* entree :
|
||
* Text = ligne de netliste lue ( (pad = net) )
|
||
* Module = adresse de la structure MODULE a qui appartient les pads
|
||
*/
|
||
{
|
||
D_PAD* pad;
|
||
char* TextPinName, * TextNetName;
|
||
int Error = 0;
|
||
bool trouve;
|
||
char Line[256];
|
||
wxString Msg;
|
||
|
||
if( Module == NULL )
|
||
return 0;
|
||
|
||
strcpy( Line, Text );
|
||
|
||
if( ( TextPinName = strtok( Line, " ()\t\n" ) ) == NULL )
|
||
Error = 1;
|
||
if( ( TextNetName = strtok( NULL, " ()\t\n" ) ) == NULL )
|
||
Error = 1;
|
||
if( Error )
|
||
return 0;
|
||
|
||
/* recherche du pad */
|
||
pad = Module->m_Pads; trouve = FALSE;
|
||
for( ; pad != NULL; pad = (D_PAD*) pad->Pnext )
|
||
{
|
||
if( strnicmp( TextPinName, pad->m_Padname, 4 ) == 0 )
|
||
{ /* trouve */
|
||
trouve = TRUE;
|
||
if( *TextNetName != '?' )
|
||
pad->m_Netname = CONV_FROM_UTF8( TextNetName );
|
||
else
|
||
pad->m_Netname.Empty();
|
||
}
|
||
}
|
||
|
||
if( !trouve && (DisplayWarningCount > 0) )
|
||
{
|
||
wxString pin_name = CONV_FROM_UTF8( TextPinName );
|
||
Msg.Printf( _( "Module [%s]: Pad [%s] not found" ),
|
||
Module->m_Reference->m_Text.GetData(), pin_name.GetData() );
|
||
DisplayError( this, Msg, 1 );
|
||
DisplayWarningCount--;
|
||
}
|
||
|
||
return trouve;
|
||
}
|
||
|
||
|
||
/*****************************************************/
|
||
MODULE* WinEDA_PcbFrame::ListAndSelectModuleName()
|
||
/*****************************************************/
|
||
|
||
/* liste les noms des modules du PCB
|
||
* Retourne:
|
||
* un pointeur sur le module selectionne
|
||
* NULL si pas de selection
|
||
*/
|
||
{
|
||
int ii, jj, nb_empr;
|
||
MODULE* Module;
|
||
WinEDAListBox* ListBox;
|
||
const wxChar** ListNames = NULL;
|
||
|
||
if( m_Pcb->m_Modules == NULL )
|
||
{
|
||
DisplayError( this, _( "No Modules" ) ); return 0;
|
||
}
|
||
|
||
/* Calcul du nombre des modules */
|
||
nb_empr = 0; Module = (MODULE*) m_Pcb->m_Modules;
|
||
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
|
||
nb_empr++;
|
||
|
||
ListNames = (const wxChar**) MyZMalloc( (nb_empr + 1) * sizeof(wxChar *) );
|
||
Module = (MODULE*) m_Pcb->m_Modules;
|
||
for( ii = 0; Module != NULL; Module = (MODULE*) Module->Pnext, ii++ )
|
||
{
|
||
ListNames[ii] = Module->m_Reference->m_Text.GetData();
|
||
}
|
||
|
||
ListBox = new WinEDAListBox( this, _( "Components" ),
|
||
ListNames, wxEmptyString );
|
||
ii = ListBox->ShowModal(); ListBox->Destroy();
|
||
|
||
|
||
if( ii < 0 ) /* Pas de selection */
|
||
{
|
||
Module = NULL;
|
||
}
|
||
else /* Recherche du module selectionne */
|
||
{
|
||
Module = (MODULE*) m_Pcb->m_Modules;
|
||
for( jj = 0; Module != NULL; Module = (MODULE*) Module->Pnext, jj++ )
|
||
{
|
||
if( Module->m_Reference->m_Text.Cmp( ListNames[ii] ) == 0 )
|
||
break;
|
||
}
|
||
}
|
||
|
||
free( ListNames );
|
||
return Module;
|
||
}
|
||
|
||
|
||
/***************************************************************/
|
||
void WinEDA_NetlistFrame::ModulesControle( wxCommandEvent& event )
|
||
/***************************************************************/
|
||
|
||
/* donne la liste :
|
||
* 1 - des empreintes doubl<62>es sur le PCB
|
||
* 2 - des empreintes manquantes par rapport a la netliste
|
||
* 3 - des empreintes suppl<70>mentaires par rapport a la netliste
|
||
*/
|
||
#define MAX_LEN_TXT 32
|
||
{
|
||
int ii, NbModulesPcb;
|
||
MODULE* Module, * pt_aux;
|
||
int NbModulesNetListe, nberr = 0;
|
||
WinEDA_TextFrame* List;
|
||
wxArrayString ModuleListFromNetlist;
|
||
|
||
/* determination du nombre des modules du PCB*/
|
||
NbModulesPcb = 0; Module = (MODULE*) m_Parent->m_Pcb->m_Modules;
|
||
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
|
||
NbModulesPcb++;
|
||
|
||
if( NbModulesPcb == 0 )
|
||
{
|
||
DisplayError( this, _( "No modules" ), 10 ); return;
|
||
}
|
||
|
||
/* Construction de la liste des references des modules de la netliste */
|
||
NbModulesNetListe = BuildListeNetModules( event, ModuleListFromNetlist );
|
||
if( NbModulesNetListe < 0 )
|
||
return; /* fichier non trouve */
|
||
|
||
if( NbModulesNetListe == 0 )
|
||
{
|
||
DisplayError( this, _( "No modules in NetList" ), 10 ); return;
|
||
}
|
||
|
||
List = new WinEDA_TextFrame( this, _( "Check Modules" ) );
|
||
|
||
/* recherche des doubles */
|
||
List->Append( _( "Duplicates" ) );
|
||
|
||
Module = (MODULE*) m_Parent->m_Pcb->m_Modules;
|
||
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
|
||
{
|
||
pt_aux = (MODULE*) Module->Pnext;
|
||
for( ; pt_aux != NULL; pt_aux = (MODULE*) pt_aux->Pnext )
|
||
{
|
||
if( Module->m_Reference->m_Text.CmpNoCase( pt_aux->m_Reference->m_Text ) == 0 )
|
||
{
|
||
List->Append( Module->m_Reference->m_Text );
|
||
nberr++;
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
/* recherche des manquants par rapport a la netliste*/
|
||
List->Append( _( "Lack:" ) );
|
||
|
||
for( ii = 0; ii < NbModulesNetListe; ii++ )
|
||
{
|
||
Module = (MODULE*) m_Parent->m_Pcb->m_Modules;
|
||
for( ; Module != NULL; Module = (MODULE*) Module->Pnext )
|
||
{
|
||
if( Module->m_Reference->m_Text.CmpNoCase(
|
||
ModuleListFromNetlist[ii] ) == 0 )
|
||
{
|
||
break;
|
||
}
|
||
}
|
||
|
||
if( Module == NULL ) // Module missing, not found in board
|
||
{
|
||
List->Append( ModuleListFromNetlist[ii] );
|
||
nberr++;
|
||
}
|
||
}
|
||
|
||
/* recherche des modules supplementaires (i.e. Non en Netliste) */
|
||
List->Append( _( "Not in Netlist:" ) );
|
||
|
||
Module = (MODULE*) m_Parent->m_Pcb->m_Modules;
|
||
for( ; Module != NULL; Module = Module->Next() )
|
||
{
|
||
for( ii = 0; ii < NbModulesNetListe; ii++ )
|
||
{
|
||
if( Module->m_Reference->m_Text.CmpNoCase(
|
||
ModuleListFromNetlist[ii] ) == 0 )
|
||
{
|
||
break;/* Module trouve en netliste */
|
||
}
|
||
}
|
||
|
||
if( ii == NbModulesNetListe ) /* Module not found in netlist */
|
||
{
|
||
List->Append( Module->m_Reference->m_Text );
|
||
nberr++;
|
||
}
|
||
}
|
||
|
||
List->ShowModal(); List->Destroy();
|
||
}
|
||
|
||
|
||
/**************************************************************************************************/
|
||
int WinEDA_NetlistFrame::BuildListeNetModules( wxCommandEvent& event, wxArrayString& BufName )
|
||
/**************************************************************************************************/
|
||
|
||
/*
|
||
* charge en BufName la liste des noms des modules de la netliste,
|
||
* retourne le nombre des modules cit<69>s dans la netliste
|
||
*/
|
||
{
|
||
int textlen;
|
||
int nb_modules_lus;
|
||
int State, LineNum, Comment;
|
||
char Line[1024], * Text, * LibModName;
|
||
|
||
if( !OpenNetlistFile( event ) )
|
||
return -1;
|
||
|
||
State = 0; LineNum = 0; Comment = 0;
|
||
nb_modules_lus = 0;
|
||
textlen = MAX_LEN_TXT;
|
||
|
||
while( GetLine( source, Line, &LineNum ) )
|
||
{
|
||
Text = StrPurge( Line );
|
||
if( Comment ) /* Commentaires en cours */
|
||
{
|
||
if( ( Text = strchr( Text, '}' ) ) == NULL )
|
||
continue;
|
||
Comment = 0;
|
||
}
|
||
if( *Text == '{' ) /* Commentaires */
|
||
{
|
||
Comment = 1;
|
||
if( ( Text = strchr( Text, '}' ) ) == NULL )
|
||
continue;
|
||
}
|
||
|
||
if( *Text == '(' )
|
||
State++;
|
||
if( *Text == ')' )
|
||
State--;
|
||
|
||
if( State == 2 )
|
||
{
|
||
int Error = 0;
|
||
if( strtok( Line, " ()\t\n" ) == NULL )
|
||
Error = 1; /* TimeStamp */
|
||
if( ( LibModName = strtok( NULL, " ()\t\n" ) ) == NULL )
|
||
Error = 1; /* nom Lib */
|
||
/* Lecture du nom (reference) du composant: */
|
||
if( ( Text = strtok( NULL, " ()\t\n" ) ) == NULL )
|
||
Error = 1;
|
||
nb_modules_lus++;
|
||
BufName.Add( CONV_FROM_UTF8( Text ) );
|
||
continue;
|
||
}
|
||
|
||
if( State >= 3 )
|
||
{
|
||
State--; /* Lecture 1 ligne relative au Pad */
|
||
}
|
||
}
|
||
|
||
fclose( source );
|
||
return nb_modules_lus;
|
||
}
|
||
|
||
|
||
/*****************************************************************************************/
|
||
int WinEDA_NetlistFrame::ReadListeModules( const wxString* RefCmp, long TimeStamp,
|
||
wxString& NameModule )
|
||
/*****************************************************************************************/
|
||
|
||
/*
|
||
* Lit le fichier .CMP donnant l'equivalence Modules / Composants
|
||
* Retourne:
|
||
* Si ce fichier existe:
|
||
* 1 et le nom module dans NameModule
|
||
* -1 si module non trouve en fichier
|
||
* sinon 0;
|
||
*
|
||
* parametres d'appel:
|
||
* RefCmp (NULL si selection par TimeStamp)
|
||
* TimeStamp (signature temporelle si elle existe, NULL sinon)
|
||
* pointeur sur le buffer recevant le nom du module
|
||
*
|
||
* Exemple de fichier:
|
||
*
|
||
* Cmp-Mod V01 Genere par PcbNew le 29/10/2003-13:11:6
|
||
*
|
||
* BeginCmp
|
||
* TimeStamp = 322D3011;
|
||
* Reference = BUS1;
|
||
* ValeurCmp = BUSPC;
|
||
* IdModule = BUS_PC;
|
||
* EndCmp
|
||
*
|
||
* BeginCmp
|
||
* TimeStamp = 32307DE2;
|
||
* Reference = C1;
|
||
* ValeurCmp = 47uF;
|
||
* IdModule = CP6;
|
||
* EndCmp
|
||
*
|
||
*/
|
||
{
|
||
wxString CmpFullFileName;
|
||
wxString refcurrcmp, idmod;
|
||
char ia[1024];
|
||
int timestamp;
|
||
char* ptcar;
|
||
FILE* FichCmp;
|
||
|
||
if( (RefCmp == NULL) && (TimeStamp == 0) )
|
||
return 0;
|
||
|
||
CmpFullFileName = NetNameBuffer;
|
||
ChangeFileNameExt( CmpFullFileName, NetCmpExtBuffer );
|
||
|
||
FichCmp = wxFopen( CmpFullFileName, wxT( "rt" ) );
|
||
if( FichCmp == NULL )
|
||
{
|
||
wxString msg;
|
||
msg.Printf( _( "File <%s> not found, use Netlist for lib module selection" ),
|
||
CmpFullFileName.GetData() );
|
||
DisplayError( this, msg, 20 );
|
||
return 0;
|
||
}
|
||
|
||
while( fgets( ia, sizeof(ia), FichCmp ) != NULL )
|
||
{
|
||
if( strnicmp( ia, "BeginCmp", 8 ) != 0 )
|
||
continue;
|
||
|
||
/* Ici une description de 1 composant commence */
|
||
refcurrcmp.Empty();
|
||
idmod.Empty();
|
||
timestamp = -1;
|
||
while( fgets( ia, sizeof(ia), FichCmp ) != NULL )
|
||
{
|
||
if( strnicmp( ia, "EndCmp", 6 ) == 0 )
|
||
break;
|
||
|
||
if( strnicmp( ia, "Reference =", 11 ) == 0 )
|
||
{
|
||
ptcar = ia + 11;
|
||
ptcar = strtok( ptcar, " =;\t\n" );
|
||
if( ptcar )
|
||
refcurrcmp = CONV_FROM_UTF8( ptcar );
|
||
continue;
|
||
}
|
||
|
||
if( strnicmp( ia, "IdModule =", 11 ) == 0 )
|
||
{
|
||
ptcar = ia + 11;
|
||
ptcar = strtok( ptcar, " =;\t\n" );
|
||
if( ptcar )
|
||
idmod = CONV_FROM_UTF8( ptcar );
|
||
continue;
|
||
}
|
||
if( strnicmp( ia, "TimeStamp =", 11 ) == 0 )
|
||
{
|
||
ptcar = ia + 11;
|
||
ptcar = strtok( ptcar, " =;\t\n" );
|
||
if( ptcar )
|
||
sscanf( ptcar, "%X", ×tamp );
|
||
}
|
||
}
|
||
|
||
/* Fin lecture 1 descr composant */
|
||
|
||
/* Test du Composant lu en fichier: est-il le bon */
|
||
if( RefCmp )
|
||
{
|
||
if( RefCmp->CmpNoCase( refcurrcmp ) == 0 )
|
||
{
|
||
fclose( FichCmp );
|
||
NameModule = idmod;
|
||
return 1;
|
||
}
|
||
}
|
||
else if( TimeStamp != -1 )
|
||
{
|
||
if( TimeStamp == timestamp )
|
||
{
|
||
fclose( FichCmp );
|
||
NameModule = idmod;
|
||
return 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
fclose( FichCmp );
|
||
return -1;
|
||
}
|
||
|
||
|
||
/***************************************************************/
|
||
void WinEDA_NetlistFrame::Set_NetlisteName( wxCommandEvent& event )
|
||
/***************************************************************/
|
||
|
||
/* Selection un nouveau nom de netliste
|
||
* Affiche la liste des fichiers netlistes pour selection sur liste
|
||
*/
|
||
{
|
||
wxString fullfilename, mask( wxT( "*" ) );
|
||
|
||
mask += NetExtBuffer;
|
||
|
||
fullfilename = EDA_FileSelector( _( "Netlist Selection:" ),
|
||
wxEmptyString, /* Chemin par defaut */
|
||
NetNameBuffer, /* nom fichier par defaut */
|
||
NetExtBuffer, /* extension par defaut */
|
||
mask, /* Masque d'affichage */
|
||
this,
|
||
0,
|
||
TRUE
|
||
);
|
||
|
||
if( fullfilename.IsEmpty() )
|
||
return;
|
||
NetNameBuffer = fullfilename;
|
||
SetTitle( fullfilename );
|
||
}
|
||
|
||
|
||
/***********************************************************************************/
|
||
void WinEDA_NetlistFrame::AddToList( const wxString& NameLibCmp, const wxString& CmpName,
|
||
int TimeStamp )
|
||
/************************************************************************************/
|
||
|
||
/* Fontion copiant en memoire de travail les caracteristiques
|
||
* des nouveaux modules
|
||
*/
|
||
{
|
||
MODULEtoLOAD* NewMod;
|
||
|
||
NewMod = new MODULEtoLOAD( NameLibCmp, CmpName, TimeStamp );
|
||
NewMod->Pnext = s_ModuleToLoad_List;
|
||
s_ModuleToLoad_List = NewMod;
|
||
s_NbNewModules++;
|
||
}
|
||
|
||
|
||
/***************************************************************/
|
||
void WinEDA_NetlistFrame::LoadListeModules( wxDC* DC )
|
||
/***************************************************************/
|
||
|
||
/* Routine de chargement des nouveaux modules en une seule lecture des
|
||
* librairies
|
||
* Si un module vient d'etre charge il est duplique, ce qui evite une lecture
|
||
* inutile de la librairie
|
||
*/
|
||
{
|
||
MODULEtoLOAD* ref, * cmp;
|
||
int ii;
|
||
MODULE* Module = NULL;
|
||
wxPoint OldPos = m_Parent->m_CurrentScreen->m_Curseur;
|
||
|
||
if( s_NbNewModules == 0 )
|
||
return;
|
||
|
||
SortListModulesToLoadByLibname( s_NbNewModules );
|
||
ref = cmp = s_ModuleToLoad_List;
|
||
|
||
// Calcul de la coordonn<6E>e de placement des modules:
|
||
if( m_Parent->SetBoardBoundaryBoxFromEdgesOnly() )
|
||
{
|
||
m_Parent->m_CurrentScreen->m_Curseur.x = m_Parent->m_Pcb->m_BoundaryBox.GetRight() + 5000;
|
||
m_Parent->m_CurrentScreen->m_Curseur.y = m_Parent->m_Pcb->m_BoundaryBox.GetBottom() +
|
||
10000;
|
||
}
|
||
else
|
||
{
|
||
m_Parent->m_CurrentScreen->m_Curseur = wxPoint( 0, 0 );
|
||
}
|
||
|
||
for( ii = 0; ii < s_NbNewModules; ii++, cmp = cmp->Next() )
|
||
{
|
||
if( (ii == 0) || ( ref->m_LibName != cmp->m_LibName) )
|
||
{ /* Nouveau Module a charger */
|
||
Module = m_Parent->Get_Librairie_Module( this, wxEmptyString, cmp->m_LibName, FALSE );
|
||
ref = cmp;
|
||
if( Module == NULL )
|
||
{
|
||
wxString msg;
|
||
msg.Printf( _( "Component [%s]: footprint <%s> not found" ),
|
||
cmp->m_CmpName.GetData(), cmp->m_LibName.GetData() );
|
||
DisplayError( this, msg );
|
||
continue;
|
||
}
|
||
m_Parent->Place_Module( Module, DC );
|
||
|
||
/* mise a jour des reperes ( nom et ref "Time Stamp")
|
||
* si module charge */
|
||
Module->m_Reference->m_Text = cmp->m_CmpName;
|
||
Module->m_TimeStamp = cmp->m_TimeStamp;
|
||
}
|
||
else
|
||
{
|
||
/* module deja charge, on peut le dupliquer */
|
||
MODULE* newmodule;
|
||
if( Module == NULL )
|
||
continue; /* module non existant en libr */
|
||
newmodule = new MODULE( m_Parent->m_Pcb );
|
||
newmodule->Copy( Module );
|
||
newmodule->AddToChain( Module );
|
||
Module = newmodule;
|
||
Module->m_Reference->m_Text = cmp->m_CmpName;
|
||
Module->m_TimeStamp = cmp->m_TimeStamp;
|
||
}
|
||
}
|
||
|
||
m_Parent->m_CurrentScreen->m_Curseur = OldPos;
|
||
}
|
||
|
||
|
||
/* Routine utilisee par qsort pour le tri des modules a charger
|
||
*/
|
||
static int SortByLibName( MODULEtoLOAD** ref, MODULEtoLOAD** cmp )
|
||
{
|
||
int ii = (*ref)->m_LibName.CmpNoCase( (*cmp)->m_LibName );
|
||
|
||
return ii;
|
||
}
|
||
|
||
|
||
/*************************************************/
|
||
void SortListModulesToLoadByLibname( int NbModules )
|
||
/**************************************************/
|
||
|
||
/* Rearrage la liste des modules List par ordre alphabetique des noms lib des modules
|
||
*/
|
||
{
|
||
MODULEtoLOAD** base_list, * item;
|
||
int ii;
|
||
|
||
base_list = (MODULEtoLOAD**) MyMalloc( NbModules * sizeof(MODULEtoLOAD *) );
|
||
|
||
for( ii = 0, item = s_ModuleToLoad_List; ii < NbModules; ii++ )
|
||
{
|
||
base_list[ii] = item;
|
||
item = item->Next();
|
||
}
|
||
|
||
qsort( base_list, NbModules, sizeof(MODULEtoLOAD *),
|
||
( int( * ) ( const void*, const void* ) )SortByLibName );
|
||
|
||
// Reconstruction du chainage:
|
||
s_ModuleToLoad_List = *base_list;
|
||
for( ii = 0; ii < NbModules - 1; ii++ )
|
||
{
|
||
item = base_list[ii];
|
||
item->Pnext = base_list[ii + 1];
|
||
}
|
||
|
||
// Dernier item: Pnext = NULL:
|
||
item = base_list[ii];
|
||
item->Pnext = NULL;
|
||
|
||
free( base_list );
|
||
}
|
||
|
||
|
||
/*****************************************************************************/
|
||
MODULEtoLOAD::MODULEtoLOAD( const wxString& libname, const wxString& cmpname,
|
||
int timestamp ) : EDA_BaseStruct( TYPE_NOT_INIT )
|
||
/*****************************************************************************/
|
||
{
|
||
m_LibName = libname;
|
||
m_CmpName = cmpname;
|
||
m_TimeStamp = timestamp;
|
||
}
|