/************************************/ /* 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(void){}; MODULEtoLOAD * Next(void) { 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();; } } Affiche_Infos_Status_Pcb(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(void) /*****************************************************/ /* 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ées sur le PCB 2 - des empreintes manquantes par rapport a la netliste 3 - des empreintes supplé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é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é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; }