1281 lines
38 KiB
C++
1281 lines
38 KiB
C++
/***********************************************************/
|
||
/* Module to handle libraries (first part - file and io). */
|
||
/***********************************************************/
|
||
|
||
#include "fctsys.h"
|
||
#include "gr_basic.h"
|
||
|
||
#include "common.h"
|
||
#include "trigo.h"
|
||
#include "program.h"
|
||
#include "libcmp.h"
|
||
#include "general.h"
|
||
|
||
#include "protos.h"
|
||
|
||
/* Variables Locales */
|
||
|
||
/* Fonctions locales */
|
||
/* pour librairies de composants */
|
||
static LibEDA_BaseStruct* GetDrawEntry( WinEDA_DrawFrame* frame, FILE* f,
|
||
char* Line, int* LineNum );
|
||
static bool GetLibEntryField( EDA_LibComponentStruct* LibEntry, char* line );
|
||
static bool AddAliasNames( EDA_LibComponentStruct* LibEntry, char* line );
|
||
static void InsertAlias( PriorQue** PQ,
|
||
EDA_LibComponentStruct* LibEntry, int* NumOfParts );
|
||
static bool ReadLibEntryDateAndTime( EDA_LibComponentStruct* LibEntry, char* Line );
|
||
static int AddFootprintFilterList( EDA_LibComponentStruct* LibEntryLibEntry,
|
||
FILE* f, char* Line, int* LineNum );
|
||
|
||
/* pour doc librairies */
|
||
|
||
|
||
/****************************************************/
|
||
/* Routines de lecture des librairies de composants */
|
||
/****************************************************/
|
||
|
||
|
||
/*****************************************************************************
|
||
* Routine to load the given library name. FullLibName should hold full path *
|
||
* of file name to open, while LibName should hold only its name. *
|
||
* IF library already exists, it is NOT reloaded. *
|
||
* return: new lib or NULL *
|
||
*****************************************************************************/
|
||
LibraryStruct* LoadLibraryName( WinEDA_DrawFrame* frame,
|
||
const wxString& FullLibName, const wxString& LibName )
|
||
{
|
||
int NumOfParts;
|
||
FILE* f;
|
||
LibraryStruct* NewLib;
|
||
PriorQue* Entries;
|
||
wxString FullFileName;
|
||
|
||
if( ( NewLib = FindLibrary( LibName ) ) != NULL )
|
||
{
|
||
if( NewLib->m_FullFileName == FullLibName )
|
||
return NewLib;
|
||
FreeCmpLibrary( frame, LibName );
|
||
}
|
||
|
||
NewLib = NULL;
|
||
|
||
f = wxFopen( FullLibName, wxT( "rt" ) );
|
||
if( f == NULL )
|
||
{
|
||
wxString msg;
|
||
msg.Printf( _( "Library <%s> not found" ), FullLibName.GetData() );
|
||
DisplayError( frame, msg );
|
||
return NULL;
|
||
}
|
||
|
||
NewLib = new LibraryStruct( LIBRARY_TYPE_EESCHEMA, LibName, FullLibName );
|
||
|
||
Entries = LoadLibraryAux( frame, NewLib, f, &NumOfParts );
|
||
if( Entries != NULL )
|
||
{
|
||
NewLib->m_Entries = Entries;
|
||
NewLib->m_NumOfParts = NumOfParts;
|
||
|
||
if( g_LibraryList == NULL )
|
||
g_LibraryList = NewLib;
|
||
else
|
||
{
|
||
LibraryStruct* tmplib = g_LibraryList;
|
||
while( tmplib->m_Pnext )
|
||
tmplib = tmplib->m_Pnext;
|
||
|
||
tmplib->m_Pnext = NewLib;
|
||
}
|
||
|
||
FullFileName = FullLibName;
|
||
ChangeFileNameExt( FullFileName, DOC_EXT );
|
||
LoadDocLib( frame, FullFileName, NewLib->m_Name );
|
||
}
|
||
else
|
||
delete NewLib;
|
||
|
||
fclose( f );
|
||
return NewLib;
|
||
}
|
||
|
||
|
||
/******************************************/
|
||
void LoadLibraries( WinEDA_DrawFrame* frame )
|
||
/******************************************/
|
||
|
||
/* Delete toutes les librairies chargees et recree toutes les librairies
|
||
* donnes dans la liste g_LibName_List
|
||
*/
|
||
{
|
||
wxString FullLibName, msg;
|
||
wxString LibName;
|
||
unsigned ii, iimax = g_LibName_List.GetCount();
|
||
|
||
frame->PrintMsg( _( "Start loading schematic libs" ) );
|
||
|
||
// Free the unwanted libraries (i.e. not in list) but keep the .cache lib
|
||
LibraryStruct* nextlib, * lib = g_LibraryList;
|
||
for( ; lib != NULL; lib = nextlib )
|
||
{
|
||
nextlib = lib->m_Pnext;
|
||
if( lib->m_IsLibCache )
|
||
continue;
|
||
|
||
wxString libname = lib->m_Name;
|
||
|
||
// is this library in "wanted list" g_LibName_List ?
|
||
int test = g_LibName_List.Index( libname );
|
||
if( test == wxNOT_FOUND )
|
||
FreeCmpLibrary( frame, libname );
|
||
}
|
||
|
||
// Load missing libraries (if any)
|
||
for( ii = 0; ii < iimax; ii++ )
|
||
{
|
||
LibName = g_LibName_List[ii];
|
||
|
||
if( LibName.IsEmpty() )
|
||
continue;
|
||
FullLibName = MakeFileName( g_RealLibDirBuffer, LibName, g_LibExtBuffer );
|
||
msg = wxT( "Loading " ) + FullLibName;
|
||
if( LoadLibraryName( frame, FullLibName, LibName ) )
|
||
msg += wxT( " OK" );
|
||
else
|
||
msg += wxT( " ->Error" );
|
||
frame->PrintMsg( msg );
|
||
}
|
||
|
||
// reorder the linked list to match the order filename list:
|
||
int NumOfLibs;
|
||
for( NumOfLibs = 0, lib = g_LibraryList; lib != NULL; lib = lib->m_Pnext )
|
||
{
|
||
lib->m_Flags = 0;
|
||
NumOfLibs++;
|
||
}
|
||
|
||
if( NumOfLibs == 0 )
|
||
return;
|
||
|
||
LibraryStruct** libs =
|
||
(LibraryStruct**) MyZMalloc( sizeof(LibraryStruct *) * (NumOfLibs + 2) );
|
||
|
||
int jj = 0;
|
||
for( ii = 0; ii < g_LibName_List.GetCount(); ii++ )
|
||
{
|
||
if( jj >= NumOfLibs )
|
||
break;
|
||
lib = FindLibrary( g_LibName_List[ii] );
|
||
if( lib )
|
||
{
|
||
lib->m_Flags = 1;
|
||
libs[jj++] = lib;
|
||
}
|
||
}
|
||
|
||
/* Put lib cache at end of list */
|
||
for( lib = g_LibraryList; lib != NULL; lib = lib->m_Pnext )
|
||
{
|
||
if( lib->m_Flags == 0 )
|
||
libs[jj++] = lib;
|
||
}
|
||
|
||
libs[jj] = NULL;
|
||
|
||
/* Change the linked list pointers */
|
||
for( ii = 0; libs[ii] != NULL; ii++ )
|
||
libs[ii]->m_Pnext = libs[ii + 1];
|
||
|
||
g_LibraryList = libs[0];
|
||
|
||
MyFree( libs );
|
||
|
||
for( lib = g_LibraryList; lib != NULL; lib = lib->m_Pnext )
|
||
lib->m_Flags = 0;
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
* Routine to free a library from the current loaded libraries. *
|
||
*****************************************************************************/
|
||
void FreeCmpLibrary( wxWindow* frame, const wxString& LibName )
|
||
{
|
||
int NumOfLibs = NumOfLibraries();
|
||
LibraryStruct* Lib, * TempLib;
|
||
|
||
if( NumOfLibs == 0 )
|
||
{
|
||
DisplayError( frame, wxT( "No libraries are loaded" ), 20 );
|
||
return;
|
||
}
|
||
|
||
/* Search for this library name: */
|
||
for( Lib = g_LibraryList; Lib != NULL; Lib = Lib->m_Pnext )
|
||
{
|
||
if( LibName == Lib->m_Name )
|
||
break;
|
||
}
|
||
|
||
if( Lib == NULL )
|
||
return;
|
||
|
||
if( Lib == g_LibraryList )
|
||
g_LibraryList = Lib->m_Pnext;
|
||
else
|
||
{
|
||
for( TempLib = g_LibraryList; TempLib->m_Pnext != Lib; TempLib = TempLib->m_Pnext )
|
||
;
|
||
|
||
TempLib->m_Pnext = TempLib->m_Pnext->m_Pnext;
|
||
}
|
||
|
||
delete Lib;
|
||
|
||
/* La librairie supprimee est peut etre celle selectee dans libedit */
|
||
if( Lib == CurrentLib )
|
||
CurrentLib = NULL;
|
||
}
|
||
|
||
|
||
/******************************/
|
||
const wxChar** GetLibNames( void )
|
||
/******************************/
|
||
|
||
/* Routine to return pointers to all library names.
|
||
* User is responsible to deallocate memory
|
||
*/
|
||
{
|
||
int ii, NumOfLibs = NumOfLibraries();
|
||
const wxChar** Names;
|
||
LibraryStruct* Lib;
|
||
|
||
Names = (const wxChar**) MyZMalloc( sizeof(wxChar *) * (NumOfLibs + 1) );
|
||
for( ii = 0, Lib = g_LibraryList; Lib != NULL; Lib = Lib->m_Pnext, ii++ )
|
||
{
|
||
Names[ii] = Lib->m_Name.GetData();
|
||
}
|
||
|
||
Names[ii] = NULL;
|
||
|
||
return Names;
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
* Routine to compare two EDA_LibComponentStruct for the PriorQue module. *
|
||
* Comparison (insensitive case) is based on Part name. *
|
||
*****************************************************************************/
|
||
int LibraryEntryCompare( EDA_LibComponentStruct* LE1, EDA_LibComponentStruct* LE2 )
|
||
{
|
||
return LE1->m_Name.m_Text.CmpNoCase( LE2->m_Name.m_Text );
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
* Routine to load a library from given open file. *
|
||
*****************************************************************************/
|
||
PriorQue* LoadLibraryAux( WinEDA_DrawFrame* frame, LibraryStruct* Library, FILE* libfile,
|
||
int* NumOfParts )
|
||
{
|
||
int LineNum = 0;
|
||
char Line[1024];
|
||
PriorQue* PQ = NULL;
|
||
EDA_LibComponentStruct* LibEntry;
|
||
wxString msg;
|
||
|
||
wxBusyCursor ShowWait; // Display a Busy Cursor..
|
||
|
||
*NumOfParts = 0;
|
||
|
||
if( GetLine( libfile, Line, &LineNum, sizeof(Line) ) == NULL )
|
||
{
|
||
msg = _( "File <" ) + Library->m_Name + _( "> is empty!" );
|
||
DisplayError( frame, msg );
|
||
return NULL;
|
||
}
|
||
|
||
if( strnicmp( Line, LIBFILE_IDENT, 10 ) != 0 )
|
||
{
|
||
msg = _( "File <" ) + Library->m_Name + _( "> is NOT EESCHEMA library!" );
|
||
DisplayError( frame, msg );
|
||
return NULL;
|
||
}
|
||
|
||
if( Library )
|
||
Library->m_Header = CONV_FROM_UTF8( Line );
|
||
|
||
PQInit( &PQ );
|
||
PQCompFunc( (PQCompFuncType) LibraryEntryCompare );
|
||
|
||
while( GetLine( libfile, Line, &LineNum, sizeof(Line) ) )
|
||
{
|
||
if( strnicmp( Line, "$HEADER", 7 ) == 0 )
|
||
{
|
||
if( Library )
|
||
{
|
||
if( !Library->ReadHeader( libfile, &LineNum ) )
|
||
{
|
||
msg = _( "Library <" ) + Library->m_Name + _( "> header read error" );
|
||
DisplayError( frame, msg, 30 );
|
||
}
|
||
}
|
||
continue;
|
||
}
|
||
|
||
if( strnicmp( Line, "DEF", 3 ) == 0 )
|
||
{
|
||
/* Read one DEF/ENDDEF part entry from library: */
|
||
LibEntry = Read_Component_Definition( frame, Line, libfile, &LineNum );
|
||
if( LibEntry )
|
||
{
|
||
/* If we are here, this part is O.k. - put it in: */
|
||
++ * NumOfParts;
|
||
PQInsert( &PQ, LibEntry );
|
||
InsertAlias( &PQ, LibEntry, NumOfParts );
|
||
}
|
||
}
|
||
}
|
||
|
||
return PQ;
|
||
}
|
||
|
||
|
||
/*********************************************************************************************/
|
||
EDA_LibComponentStruct* Read_Component_Definition( WinEDA_DrawFrame* frame, char* Line,
|
||
FILE* f, int* LineNum )
|
||
/*********************************************************************************************/
|
||
|
||
/* Routine to Read a DEF/ENDDEF part entry from given open file.
|
||
*/
|
||
{
|
||
int unused;
|
||
char* p, * Name, * Prefix = NULL;
|
||
EDA_LibComponentStruct* LibEntry = NULL;
|
||
bool Res;
|
||
wxString Msg;
|
||
|
||
p = strtok( Line, " \t\r\n" );
|
||
|
||
if( strcmp( p, "DEF" ) != 0 )
|
||
{
|
||
Msg.Printf( wxT( "DEF command expected in line %d, aborted." ), *LineNum );
|
||
DisplayError( frame, Msg );
|
||
return NULL;
|
||
}
|
||
|
||
/* Read DEF line: */
|
||
char drawnum = 0, drawname = 0;
|
||
LibEntry = new EDA_LibComponentStruct( NULL );
|
||
|
||
if( ( Name = strtok( NULL, " \t\n" ) ) == NULL /* Part name: */
|
||
|| ( Prefix = strtok( NULL, " \t\n" ) ) == NULL /* Prefix name: */
|
||
|| ( p = strtok( NULL, " \t\n" ) ) == NULL /* NumOfPins: */
|
||
|| sscanf( p, "%d", &unused ) != 1
|
||
|| ( p = strtok( NULL, " \t\n" ) ) == NULL /* TextInside: */
|
||
|| sscanf( p, "%d", &LibEntry->m_TextInside ) != 1
|
||
|| ( p = strtok( NULL, " \t\n" ) ) == NULL /* DrawNums: */
|
||
|| sscanf( p, "%c", &drawnum ) != 1
|
||
|| ( p = strtok( NULL, " \t\n" ) ) == NULL /* DrawNums: */
|
||
|| sscanf( p, "%c", &drawname ) != 1
|
||
|| ( p = strtok( NULL, " \t\n" ) ) == NULL /* m_UnitCount: */
|
||
|| sscanf( p, "%d", &LibEntry->m_UnitCount ) != 1 )
|
||
{
|
||
Msg.Printf( wxT( "Wrong DEF format in line %d, skipped." ), *LineNum );
|
||
DisplayError( frame, Msg );
|
||
while( GetLine( f, Line, LineNum, 1024 ) )
|
||
{
|
||
p = strtok( Line, " \t\n" );
|
||
if( stricmp( p, "ENDDEF" ) == 0 )
|
||
break;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
else /* Mise a jour des infos de la ligne "DEF" */
|
||
{
|
||
LibEntry->m_DrawPinNum = (drawnum == 'N') ? FALSE : TRUE;
|
||
LibEntry->m_DrawPinName = (drawname == 'N') ? FALSE : TRUE;
|
||
/* Copy part name and prefix. */
|
||
strupper( Name );
|
||
if( Name[0] != '~' )
|
||
LibEntry->m_Name.m_Text = CONV_FROM_UTF8( Name );
|
||
else
|
||
{
|
||
LibEntry->m_Name.m_Text = CONV_FROM_UTF8( &Name[1] );
|
||
LibEntry->m_Name.m_Attributs |= TEXT_NO_VISIBLE;
|
||
}
|
||
|
||
if( strcmp( Prefix, "~" ) == 0 )
|
||
{
|
||
LibEntry->m_Prefix.m_Text.Empty();
|
||
LibEntry->m_Prefix.m_Attributs |= TEXT_NO_VISIBLE;
|
||
}
|
||
else
|
||
LibEntry->m_Prefix.m_Text = CONV_FROM_UTF8( Prefix );
|
||
|
||
// Copy optional infos
|
||
if( ( p = strtok( NULL, " \t\n" ) ) != NULL ) // m_UnitSelectionLocked param
|
||
{
|
||
if( *p == 'L' )
|
||
LibEntry->m_UnitSelectionLocked = TRUE;
|
||
}
|
||
if( ( p = strtok( NULL, " \t\n" ) ) != NULL ) /* Type Of Component */
|
||
{
|
||
if( *p == 'P' )
|
||
LibEntry->m_Options = ENTRY_POWER;
|
||
}
|
||
}
|
||
|
||
/* Analyse lignes suivantes */
|
||
while( GetLine( f, Line, LineNum, 1024 ) )
|
||
{
|
||
p = strtok( Line, " \t\n" );
|
||
Res = TRUE; /* Pour test d'erreur (Res = FALSE = erreur) */
|
||
|
||
if( (Line[0] == 'T') && (Line[1] == 'i') )
|
||
{
|
||
Res = ReadLibEntryDateAndTime( LibEntry, Line );
|
||
}
|
||
else if( Line[0] == 'F' )
|
||
{
|
||
Res = GetLibEntryField( LibEntry, Line );
|
||
}
|
||
else if( strcmp( p, "ENDDEF" ) == 0 )
|
||
{
|
||
break;
|
||
}
|
||
else if( strcmp( p, "DRAW" ) == 0 )
|
||
{
|
||
LibEntry->m_Drawings = GetDrawEntry( frame, f, Line, LineNum );
|
||
}
|
||
else if( strncmp( p, "ALIAS", 5 ) == 0 )
|
||
{
|
||
p = strtok( NULL, "\r\n" );
|
||
Res = AddAliasNames( LibEntry, p );
|
||
}
|
||
else if( strncmp( p, "$FPLIST", 5 ) == 0 )
|
||
{
|
||
Res = AddFootprintFilterList( LibEntry, f, Line, LineNum );
|
||
}
|
||
else
|
||
{
|
||
Msg.Printf( wxT( "Undefined command \"%s\" in line %d, skipped." ), p, *LineNum );
|
||
frame->PrintMsg( Msg );
|
||
}
|
||
|
||
/* Fin analyse de la ligne ou block: test de l'info lue */
|
||
if( !Res )
|
||
{ /* Something went wrong there. */
|
||
Msg.Printf( wxT( " Error Line %d, Library not loaded" ), *LineNum );
|
||
DisplayError( frame, Msg );
|
||
delete LibEntry;
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
/* If we are here, this part is O.k. - put it in: */
|
||
LibEntry->SortDrawItems();
|
||
return LibEntry;
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
* Routine to load a DRAW definition from given file. Note "DRAW" line has *
|
||
* been read already. Reads upto and include ENDDRAW, or an error (NULL ret). *
|
||
*****************************************************************************/
|
||
|
||
static LibEDA_BaseStruct* GetDrawEntry( WinEDA_DrawFrame* frame, FILE* f, char* Line, int* LineNum )
|
||
{
|
||
int i = 0, jj, ll, Unit, Convert, size1, size2;
|
||
char* p, Buffer[1024], BufName[256],
|
||
PinNum[256],
|
||
chartmp[256], chartmp1[256];
|
||
wxString MsgLine;
|
||
bool Error = FALSE;
|
||
LibEDA_BaseStruct* Tail = NULL,
|
||
* New = NULL,
|
||
* Head = NULL;
|
||
|
||
while( TRUE )
|
||
{
|
||
if( GetLine( f, Line, LineNum, 1024 ) == NULL )
|
||
{
|
||
DisplayError( frame, wxT( "File ended prematurely" ) );
|
||
return Head;
|
||
}
|
||
|
||
if( strncmp( Line, "ENDDRAW", 7 ) == 0 )
|
||
{
|
||
break;
|
||
}
|
||
|
||
New = NULL;
|
||
|
||
switch( Line[0] )
|
||
{
|
||
case 'A': /* Arc */
|
||
{
|
||
int startx, starty, endx, endy;
|
||
LibDrawArc* Arc = new LibDrawArc();
|
||
|
||
New = Arc;
|
||
ll = 0;
|
||
int nbarg = sscanf( &Line[2], "%d %d %d %d %d %d %d %d %s %d %d %d %d",
|
||
&Arc->m_Pos.x, &Arc->m_Pos.y, &Arc->m_Rayon,
|
||
&Arc->t1, &Arc->t2, &Unit, &Convert,
|
||
&Arc->m_Width, chartmp, &startx, &starty, &endx, &endy );
|
||
if( nbarg < 8 )
|
||
Error = TRUE;
|
||
Arc->m_Unit = Unit; Arc->m_Convert = Convert;
|
||
if( chartmp[0] == 'F' )
|
||
Arc->m_Fill = FILLED_SHAPE;
|
||
if( chartmp[0] == 'f' )
|
||
Arc->m_Fill = FILLED_WITH_BG_BODYCOLOR;
|
||
|
||
NORMALIZE_ANGLE( Arc->t1 );
|
||
NORMALIZE_ANGLE( Arc->t2 );
|
||
|
||
if( nbarg >= 13 ) // Coord reelles des extremites de l'arc lues
|
||
{
|
||
Arc->m_ArcStart.x = startx; Arc->m_ArcStart.y = starty;
|
||
Arc->m_ArcEnd.x = endx; Arc->m_ArcEnd.y = endy;
|
||
}
|
||
else
|
||
{
|
||
Arc->m_ArcStart.x = Arc->m_Rayon; Arc->m_ArcStart.y = 0;
|
||
Arc->m_ArcEnd.x = Arc->m_Rayon; Arc->m_ArcEnd.y = 0;
|
||
RotatePoint( &Arc->m_ArcStart.x, &Arc->m_ArcStart.y, -Arc->t1 );
|
||
Arc->m_ArcStart.x += Arc->m_Pos.x; Arc->m_ArcStart.y += Arc->m_Pos.y;
|
||
RotatePoint( &Arc->m_ArcEnd.x, &Arc->m_ArcEnd.y, -Arc->t2 );
|
||
Arc->m_ArcEnd.x += Arc->m_Pos.x; Arc->m_ArcEnd.y += Arc->m_Pos.y;
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'C': /* Circle */
|
||
{
|
||
LibDrawCircle* Circle = new LibDrawCircle();
|
||
|
||
New = Circle; ll = 0;
|
||
Error = sscanf( &Line[2], "%d %d %d %d %d %d %s",
|
||
&Circle->m_Pos.x, &Circle->m_Pos.y, &Circle->m_Rayon,
|
||
&Unit, &Convert, &Circle->m_Width, chartmp ) < 6;
|
||
Circle->m_Unit = Unit;
|
||
Circle->m_Convert = Convert;
|
||
if( chartmp[0] == 'F' )
|
||
Circle->m_Fill = FILLED_SHAPE;
|
||
if( chartmp[0] == 'f' )
|
||
Circle->m_Fill = FILLED_WITH_BG_BODYCOLOR;
|
||
}
|
||
break;
|
||
|
||
case 'T': /* Text */
|
||
{
|
||
LibDrawText* Text = new LibDrawText();
|
||
|
||
New = Text;
|
||
Buffer[0] = 0;
|
||
Error = sscanf( &Line[2], "%d %d %d %d %d %d %d %s",
|
||
&Text->m_Horiz,
|
||
&Text->m_Pos.x, &Text->m_Pos.y,
|
||
&Text->m_Size.x, &Text->m_Type,
|
||
&Unit, &Convert, Buffer ) != 8;
|
||
|
||
Text->m_Unit = Unit; Text->m_Convert = Convert;
|
||
Text->m_Size.y = Text->m_Size.x;
|
||
if( !Error )
|
||
{ /* Convert '~' to spaces. */
|
||
Text->m_Text = CONV_FROM_UTF8( Buffer );
|
||
Text->m_Text.Replace( wxT( "~" ), wxT( " " ) ); // Les espaces sont restitu<74>s
|
||
}
|
||
}
|
||
break;
|
||
|
||
case 'S': /* Square */
|
||
{
|
||
LibDrawSquare* Square = new LibDrawSquare();
|
||
|
||
New = Square; ll = 0;
|
||
Error = sscanf( &Line[2], "%d %d %d %d %d %d %d %s",
|
||
&Square->m_Pos.x, &Square->m_Pos.y,
|
||
&Square->m_End.x, &Square->m_End.y,
|
||
&Unit, &Convert, &Square->m_Width, chartmp ) < 7;
|
||
Square->m_Unit = Unit; Square->m_Convert = Convert;
|
||
if( chartmp[0] == 'F' )
|
||
Square->m_Fill = FILLED_SHAPE;
|
||
if( chartmp[0] == 'f' )
|
||
Square->m_Fill = FILLED_WITH_BG_BODYCOLOR;
|
||
}
|
||
break;
|
||
|
||
case 'X': /* Pin Description */
|
||
{
|
||
*Buffer = 0;
|
||
LibDrawPin* Pin = new LibDrawPin();
|
||
|
||
New = Pin;
|
||
i = sscanf( Line + 2, "%s %s %d %d %d %s %d %d %d %d %s %s",
|
||
BufName, PinNum,
|
||
&Pin->m_Pos.x, &Pin->m_Pos.y,
|
||
&ll, chartmp1,
|
||
&size1, &size2,
|
||
&Unit, &Convert, chartmp, Buffer );
|
||
|
||
Pin->m_PinNumSize = size1; /* Parametres type short */
|
||
Pin->m_PinNameSize = size2;
|
||
Pin->m_PinLen = ll;
|
||
Pin->m_Orient = chartmp1[0] & 255;
|
||
|
||
Pin->m_Unit = Unit; Pin->m_Convert = Convert;
|
||
strncpy( (char*) &Pin->m_PinNum, PinNum, 4 );
|
||
Error = (i != 11 && i != 12);
|
||
|
||
Pin->m_PinName = CONV_FROM_UTF8( BufName );
|
||
|
||
jj = *chartmp & 255;
|
||
|
||
switch( jj )
|
||
{
|
||
case 'I':
|
||
Pin->m_PinType = PIN_INPUT; break;
|
||
|
||
case 'O':
|
||
Pin->m_PinType = PIN_OUTPUT; break;
|
||
|
||
case 'B':
|
||
Pin->m_PinType = PIN_BIDI; break;
|
||
|
||
case 'T':
|
||
Pin->m_PinType = PIN_TRISTATE; break;
|
||
|
||
case 'P':
|
||
Pin->m_PinType = PIN_PASSIVE; break;
|
||
|
||
case 'U':
|
||
Pin->m_PinType = PIN_UNSPECIFIED; break;
|
||
|
||
case 'W':
|
||
Pin->m_PinType = PIN_POWER_IN; break;
|
||
|
||
case 'w':
|
||
Pin->m_PinType = PIN_POWER_OUT; break;
|
||
|
||
case 'C':
|
||
Pin->m_PinType = PIN_OPENCOLLECTOR; break;
|
||
|
||
case 'E':
|
||
Pin->m_PinType = PIN_OPENEMITTER; break;
|
||
|
||
default:
|
||
MsgLine.Printf( wxT( "Unknown Pin Type [%c] line %d" ),
|
||
jj, *LineNum );
|
||
DisplayError( frame, MsgLine );
|
||
}
|
||
|
||
if( i == 12 ) /* Special Symbole defined */
|
||
for( jj = strlen( Buffer ); jj > 0; )
|
||
{
|
||
switch( Buffer[--jj] )
|
||
{
|
||
case '~':
|
||
break;
|
||
|
||
case 'N':
|
||
Pin->m_Attributs |= PINNOTDRAW; break;
|
||
|
||
case 'I':
|
||
Pin->m_PinShape |= INVERT; break;
|
||
|
||
case 'C':
|
||
Pin->m_PinShape |= CLOCK; break;
|
||
|
||
case 'L':
|
||
Pin->m_PinShape |= LOWLEVEL_IN; break;
|
||
|
||
case 'V':
|
||
Pin->m_PinShape |= LOWLEVEL_OUT; break;
|
||
|
||
default:
|
||
MsgLine.Printf( wxT( "Unknown Pin Shape [%c] line %d" ),
|
||
Buffer[jj], *LineNum );
|
||
DisplayError( frame, MsgLine ); break;
|
||
}
|
||
}
|
||
|
||
}
|
||
break;
|
||
|
||
case 'P': /* Polyline */
|
||
{
|
||
LibDrawPolyline* Polyl = new LibDrawPolyline();
|
||
|
||
New = Polyl;
|
||
|
||
if( sscanf( &Line[2], "%d %d %d %d",
|
||
&Polyl->n, &Unit, &Convert,
|
||
&Polyl->m_Width ) == 4
|
||
&& Polyl->n > 0 )
|
||
{
|
||
Polyl->m_Unit = Unit; Polyl->m_Convert = Convert;
|
||
|
||
Polyl->PolyList = (int*)
|
||
MyZMalloc( sizeof(int) * Polyl->n * 2 );
|
||
|
||
p = strtok( &Line[2], " \t\n" );
|
||
p = strtok( NULL, " \t\n" );
|
||
p = strtok( NULL, " \t\n" );
|
||
p = strtok( NULL, " \t\n" );
|
||
|
||
for( i = 0; i < Polyl->n * 2 && !Error; i++ )
|
||
{
|
||
p = strtok( NULL, " \t\n" );
|
||
Error = sscanf( p, "%d", &Polyl->PolyList[i] ) != 1;
|
||
}
|
||
|
||
Polyl->m_Fill = NO_FILL;
|
||
if( ( p = strtok( NULL, " \t\n" ) ) != NULL )
|
||
{
|
||
if( p[0] == 'F' )
|
||
Polyl->m_Fill = FILLED_SHAPE;
|
||
if( p[0] == 'f' )
|
||
Polyl->m_Fill = FILLED_WITH_BG_BODYCOLOR;
|
||
}
|
||
}
|
||
else
|
||
Error = TRUE;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
MsgLine.Printf( wxT( "Undefined DRAW command in line %d, aborted." ),
|
||
*LineNum );
|
||
DisplayError( frame, MsgLine );
|
||
return Head;
|
||
}
|
||
|
||
if( Error )
|
||
{
|
||
MsgLine.Printf( wxT( "Error in %c DRAW command in line %d, aborted." ),
|
||
Line[0], *LineNum );
|
||
DisplayError( frame, MsgLine );
|
||
delete New;
|
||
|
||
/* FLush till end of draw: */
|
||
do {
|
||
if( GetLine( f, Line, LineNum, 1024 ) == NULL )
|
||
{
|
||
DisplayError( frame, wxT( "File ended prematurely" ) );
|
||
return Head;
|
||
}
|
||
} while( strncmp( Line, "ENDDRAW", 7 ) != 0 );
|
||
|
||
return Head;
|
||
}
|
||
else
|
||
{
|
||
if( Head == NULL )
|
||
Head = Tail = New;
|
||
else
|
||
{
|
||
Tail->Pnext = New; Tail = New;
|
||
}
|
||
}
|
||
}
|
||
|
||
return Head;
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
* Routine to find the library given its name. *
|
||
*****************************************************************************/
|
||
LibraryStruct* FindLibrary( const wxString& Name )
|
||
{
|
||
LibraryStruct* Lib = g_LibraryList;
|
||
|
||
while( Lib )
|
||
{
|
||
if( Lib->m_Name == Name )
|
||
return Lib;
|
||
Lib = Lib->m_Pnext;
|
||
}
|
||
|
||
return NULL;
|
||
}
|
||
|
||
|
||
/*****************************************************************************
|
||
* Routine to find the number of libraries currently loaded. *
|
||
*****************************************************************************/
|
||
int NumOfLibraries( void )
|
||
{
|
||
int ii;
|
||
LibraryStruct* Lib = g_LibraryList;
|
||
|
||
for( ii = 0; Lib != NULL; Lib = Lib->m_Pnext )
|
||
ii++;
|
||
|
||
return ii;
|
||
}
|
||
|
||
|
||
/*****************************************************************************/
|
||
static bool GetLibEntryField( EDA_LibComponentStruct* LibEntry, char* line )
|
||
/*****************************************************************************/
|
||
|
||
/* Analyse la ligne de description du champ de la forme:
|
||
* Fn "CA3130" 150 -200 50 H V
|
||
* ou n = 0 (REFERENCE), 1 (VALUE) , 2 .. 11 = autres champs, facultatifs
|
||
*/
|
||
{
|
||
int posx, posy, size, orient, hjustify, vjustify;
|
||
bool draw;
|
||
char* Text,
|
||
Char1[256], Char2[256],
|
||
Char3[256], Char4[256],
|
||
FieldUserName[1024];
|
||
int NumOfField, nbparam;
|
||
LibDrawField* Field = NULL;
|
||
|
||
if( sscanf( line + 1, "%d", &NumOfField ) != 1 )
|
||
return 0;
|
||
|
||
/* Recherche du debut des donnees (debut du texte suivant) */
|
||
while( *line != 0 )
|
||
line++;
|
||
|
||
while( *line == 0 )
|
||
line++;
|
||
|
||
/* recherche du texte */
|
||
while( *line && (*line != '"') )
|
||
line++;
|
||
|
||
if( *line == 0 )
|
||
return 0;
|
||
line++; Text = line;
|
||
|
||
/* recherche fin de texte */
|
||
while( *line && (*line != '"') )
|
||
line++;
|
||
|
||
if( *line == 0 )
|
||
return 0;
|
||
*line = 0; line++;
|
||
|
||
FieldUserName[0] = 0;
|
||
nbparam = sscanf( line, " %d %d %d %c %c %c %c",
|
||
&posx, &posy, &size, Char1, Char2, Char3, Char4 );
|
||
orient = TEXT_ORIENT_HORIZ; if( Char1[0] == 'V' )
|
||
orient = TEXT_ORIENT_VERT;
|
||
draw = TRUE; if( Char2[0] == 'I' )
|
||
draw = FALSE;
|
||
hjustify = GR_TEXT_HJUSTIFY_CENTER;
|
||
vjustify = GR_TEXT_VJUSTIFY_CENTER;
|
||
if( nbparam >= 6 )
|
||
{
|
||
if( *Char3 == 'L' )
|
||
hjustify = GR_TEXT_HJUSTIFY_LEFT;
|
||
else if( *Char3 == 'R' )
|
||
hjustify = GR_TEXT_HJUSTIFY_RIGHT;
|
||
if( *Char4 == 'B' )
|
||
vjustify = GR_TEXT_VJUSTIFY_BOTTOM;
|
||
else if( *Char4 == 'T' )
|
||
vjustify = GR_TEXT_VJUSTIFY_TOP;
|
||
}
|
||
|
||
switch( NumOfField )
|
||
{
|
||
case REFERENCE:
|
||
Field = &LibEntry->m_Prefix;
|
||
Field->m_FieldId = REFERENCE;
|
||
break;
|
||
|
||
case VALUE:
|
||
Field = &LibEntry->m_Name;
|
||
Field->m_FieldId = VALUE;
|
||
break;
|
||
|
||
default:
|
||
if( NumOfField >= NUMBER_OF_FIELDS )
|
||
break;
|
||
Field = new LibDrawField( NumOfField );
|
||
|
||
Field->Pnext = LibEntry->Fields;
|
||
LibEntry->Fields = Field;
|
||
break;
|
||
}
|
||
|
||
if( Field == NULL )
|
||
return FALSE;
|
||
|
||
Field->m_Pos.x = posx; Field->m_Pos.y = posy;
|
||
Field->m_Orient = orient;
|
||
if( draw == FALSE )
|
||
Field->m_Attributs |= TEXT_NO_VISIBLE;
|
||
Field->m_Size.x = Field->m_Size.y = size;
|
||
Field->m_Text = CONV_FROM_UTF8( Text );
|
||
if( NumOfField >= FIELD1 )
|
||
{
|
||
ReadDelimitedText( FieldUserName, line, sizeof(FieldUserName) );
|
||
Field->m_Name = CONV_FROM_UTF8( FieldUserName );
|
||
}
|
||
Field->m_HJustify = hjustify;
|
||
Field->m_VJustify = vjustify;
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/********************************************************************/
|
||
static bool AddAliasNames( EDA_LibComponentStruct* LibEntry, char* line )
|
||
/********************************************************************/
|
||
|
||
/* Read the alias names (in buffer line) and add them in alias list
|
||
* names are separated by spaces
|
||
*/
|
||
{
|
||
char* text;
|
||
wxString name;
|
||
|
||
text = strtok( line, " \t\r\n" );
|
||
|
||
while( text )
|
||
{
|
||
name = CONV_FROM_UTF8( text );
|
||
LibEntry->m_AliasList.Add( name );
|
||
text = strtok( NULL, " \t\r\n" );
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/********************************************************************/
|
||
static void InsertAlias( PriorQue** PQ, EDA_LibComponentStruct* LibEntry,
|
||
int* NumOfParts )
|
||
/********************************************************************/
|
||
/* create in library (in list PQ) aliases of the "root" component LibEntry*/
|
||
{
|
||
EDA_LibCmpAliasStruct* AliasEntry;
|
||
unsigned ii;
|
||
|
||
if( LibEntry->m_AliasList.GetCount() == 0 )
|
||
return;/* No alias for this component */
|
||
|
||
for( ii = 0; ii < LibEntry->m_AliasList.GetCount(); ii++ )
|
||
{
|
||
AliasEntry = new EDA_LibCmpAliasStruct( LibEntry->m_AliasList[ii],
|
||
LibEntry->m_Name.m_Text.GetData() );
|
||
|
||
++ * NumOfParts;
|
||
PQInsert( PQ, AliasEntry );
|
||
}
|
||
}
|
||
|
||
|
||
/*******************************************************/
|
||
/* Routines de lecture des Documentation de composants */
|
||
/*******************************************************/
|
||
|
||
/**********************************************************************************************/
|
||
int LoadDocLib( WinEDA_DrawFrame* frame, const wxString& FullDocLibName, const wxString& Libname )
|
||
/**********************************************************************************************/
|
||
/* Routine to load a library from given open file.*/
|
||
{
|
||
int LineNum = 0;
|
||
char Line[1024], * Name, * Text;
|
||
EDA_LibComponentStruct* Entry;
|
||
FILE* f;
|
||
wxString msg;
|
||
|
||
f = wxFopen( FullDocLibName, wxT( "rt" ) );
|
||
if( f == NULL )
|
||
return 0;
|
||
|
||
if( GetLine( f, Line, &LineNum, sizeof(Line) ) == NULL )
|
||
{ /* pas de lignes utiles */
|
||
fclose( f );
|
||
return 0;
|
||
}
|
||
|
||
if( strnicmp( Line, DOCFILE_IDENT, 10 ) != 0 )
|
||
{
|
||
DisplayError( frame, wxT( "File is NOT EESCHEMA doclib!" ) );
|
||
fclose( f );
|
||
return 0;
|
||
}
|
||
|
||
while( GetLine( f, Line, &LineNum, sizeof(Line) ) )
|
||
{
|
||
if( strncmp( Line, "$CMP", 4 ) != 0 )
|
||
{
|
||
msg.Printf( wxT( "$CMP command expected in line %d, aborted." ), LineNum );
|
||
DisplayError( frame, msg );
|
||
fclose( f );
|
||
return 0;
|
||
}
|
||
|
||
/* Read one $CMP/$ENDCMP part entry from library: */
|
||
Name = strtok( Line + 5, "\n\r" );
|
||
wxString cmpname; cmpname = CONV_FROM_UTF8( Name );
|
||
Entry = FindLibPart( cmpname.GetData(), Libname, FIND_ALIAS );
|
||
while( GetLine( f, Line, &LineNum, sizeof(Line) ) )
|
||
{
|
||
if( strncmp( Line, "$ENDCMP", 7 ) == 0 )
|
||
break;
|
||
Text = strtok( Line + 2, "\n\r" );
|
||
|
||
switch( Line[0] )
|
||
{
|
||
case 'D':
|
||
if( Entry )
|
||
Entry->m_Doc = CONV_FROM_UTF8( Text );
|
||
break;
|
||
|
||
case 'K':
|
||
if( Entry )
|
||
Entry->m_KeyWord = CONV_FROM_UTF8( Text );
|
||
break;
|
||
|
||
case 'F':
|
||
if( Entry )
|
||
Entry->m_DocFile = CONV_FROM_UTF8( Text );
|
||
break;
|
||
}
|
||
}
|
||
}
|
||
|
||
fclose( f );
|
||
return 1;
|
||
}
|
||
|
||
|
||
/*********************************************************************************/
|
||
static bool ReadLibEntryDateAndTime( EDA_LibComponentStruct* LibEntry, char* Line )
|
||
/*********************************************************************************/
|
||
|
||
/* lit date et time de modif composant sous le format:
|
||
* "Ti yy/mm/jj hh:mm:ss"
|
||
*/
|
||
{
|
||
int year, mon, day, hour, min, sec;
|
||
char* text;
|
||
|
||
year = mon = day = hour = min = sec = 0;
|
||
text = strtok( Line, " \r\t\n" );
|
||
text = strtok( NULL, " \r\t\n" ); // text pointe donnees utiles
|
||
|
||
sscanf( Line, "%d/%d/%d %d:%d:%d", &year, &mon, &day, &hour, &min, &sec );
|
||
|
||
LibEntry->m_LastDate = (sec & 63)
|
||
+ ( (min & 63) << 6 )
|
||
+ ( (hour & 31) << 12 )
|
||
+ ( (day & 31) << 17 )
|
||
+ ( (mon & 15) << 22 )
|
||
+ ( (year - 1990) << 26 );
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
|
||
/*******************************************/
|
||
static int SortItemsFct( const void* ref, const void* item );
|
||
|
||
void EDA_LibComponentStruct::SortDrawItems( void )
|
||
/*******************************************/
|
||
|
||
/* Trie les <20>l<EFBFBD>ments graphiques d'un composant lib pour am<61>liorer
|
||
* le trac<61>:
|
||
* items remplis en premier, pins en dernier
|
||
* En cas de superposition d'items, c'est plus lisible
|
||
*/
|
||
{
|
||
LibEDA_BaseStruct** Bufentry, ** BufentryBase, * Entry = m_Drawings;
|
||
int ii, nbitems;
|
||
|
||
if( Entry == NULL )
|
||
return; /* Pas d'alias pour ce composant */
|
||
/* calcul du nombre d'items */
|
||
for( nbitems = 0; Entry != NULL; Entry = Entry->Next() )
|
||
nbitems++;
|
||
|
||
BufentryBase =
|
||
(LibEDA_BaseStruct**) MyZMalloc( (nbitems + 1) * sizeof(LibEDA_BaseStruct *) );
|
||
/* memorisation du chainage : */
|
||
for( Entry = m_Drawings, ii = 0; Entry != NULL; Entry = Entry->Next() )
|
||
BufentryBase[ii++] = Entry;
|
||
|
||
/* Tri du chainage */
|
||
qsort( BufentryBase, nbitems, sizeof(LibEDA_BaseStruct *), SortItemsFct );
|
||
|
||
/* Mise a jour du chainage. Remarque:
|
||
* le dernier element de BufEntryBase (BufEntryBase[nbitems]) est NULL*/
|
||
m_Drawings = *BufentryBase;
|
||
Bufentry = BufentryBase;
|
||
for( ii = 0; ii < nbitems; ii++ )
|
||
{
|
||
(*Bufentry)->Pnext = *(Bufentry + 1);
|
||
Bufentry++;
|
||
}
|
||
|
||
MyFree( BufentryBase );
|
||
}
|
||
|
||
|
||
int SortItemsFct( const void* ref, const void* item )
|
||
{
|
||
#define Ref ( *(LibEDA_BaseStruct**) (ref) )
|
||
#define Item ( *(LibEDA_BaseStruct**) (item) )
|
||
#define BEFORE -1
|
||
#define AFTER 1
|
||
|
||
int fill_ref = 0, fill_item = 0;
|
||
|
||
switch( Ref->m_StructType )
|
||
{
|
||
case COMPONENT_ARC_DRAW_TYPE:
|
||
{
|
||
const LibDrawArc* draw = (const LibDrawArc*) Ref;
|
||
fill_ref = draw->m_Fill;
|
||
break;
|
||
}
|
||
|
||
case COMPONENT_CIRCLE_DRAW_TYPE:
|
||
{
|
||
const LibDrawCircle* draw = (const LibDrawCircle*) Ref;
|
||
fill_ref = draw->m_Fill;
|
||
break;
|
||
}
|
||
|
||
case COMPONENT_RECT_DRAW_TYPE:
|
||
{
|
||
const LibDrawSquare* draw = (const LibDrawSquare*) Ref;
|
||
fill_ref = draw->m_Fill;
|
||
break;
|
||
}
|
||
|
||
case COMPONENT_POLYLINE_DRAW_TYPE:
|
||
{
|
||
const LibDrawPolyline* draw = (const LibDrawPolyline*) Ref;
|
||
fill_ref = draw->m_Fill;
|
||
break;
|
||
}
|
||
|
||
case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE:
|
||
if( Item->m_StructType == COMPONENT_PIN_DRAW_TYPE )
|
||
return BEFORE;
|
||
if( Item->m_StructType == COMPONENT_GRAPHIC_TEXT_DRAW_TYPE )
|
||
return 0;
|
||
return 1;
|
||
break;
|
||
|
||
case COMPONENT_PIN_DRAW_TYPE:
|
||
if( Item->m_StructType == COMPONENT_PIN_DRAW_TYPE )
|
||
{
|
||
int ii;
|
||
|
||
// We sort the pins by orientation
|
||
ii = ( (LibDrawPin*) Ref )->m_Orient - ( (LibDrawPin*) Item )->m_Orient;
|
||
if( ii )
|
||
return ii;
|
||
|
||
/* We sort the pins by position (x or y).
|
||
* note: at this point, most of pins have same x pos or y pos,
|
||
* because they are sorted by orientation and generally are vertically or
|
||
* horizontally aligned */
|
||
wxPoint pos_ref, pos_tst;
|
||
pos_ref = ( (LibDrawPin*) Ref )->m_Pos;
|
||
pos_tst = ( (LibDrawPin*) Item )->m_Pos;
|
||
if( (ii = pos_ref.x - pos_tst.x) )
|
||
return ii;
|
||
ii = pos_ref.y - pos_tst.y;
|
||
return ii;
|
||
}
|
||
else
|
||
return AFTER;
|
||
break;
|
||
|
||
default:
|
||
;
|
||
}
|
||
|
||
/* Test de l'item */
|
||
switch( Item->m_StructType )
|
||
{
|
||
case COMPONENT_ARC_DRAW_TYPE:
|
||
{
|
||
const LibDrawArc* draw = (const LibDrawArc*) Item;
|
||
fill_item = draw->m_Fill;
|
||
break;
|
||
}
|
||
|
||
case COMPONENT_CIRCLE_DRAW_TYPE:
|
||
{
|
||
const LibDrawCircle* draw = (const LibDrawCircle*) Item;
|
||
fill_item = draw->m_Fill;
|
||
break;
|
||
}
|
||
|
||
case COMPONENT_RECT_DRAW_TYPE:
|
||
{
|
||
const LibDrawSquare* draw = (const LibDrawSquare*) Item;
|
||
fill_item = draw->m_Fill;
|
||
break;
|
||
}
|
||
|
||
case COMPONENT_POLYLINE_DRAW_TYPE:
|
||
{
|
||
const LibDrawPolyline* draw = (const LibDrawPolyline*) Item;
|
||
fill_item = draw->m_Fill;
|
||
break;
|
||
}
|
||
|
||
case COMPONENT_GRAPHIC_TEXT_DRAW_TYPE:
|
||
return BEFORE;
|
||
break;
|
||
|
||
case COMPONENT_PIN_DRAW_TYPE:
|
||
return BEFORE;
|
||
break;
|
||
|
||
default:
|
||
;
|
||
}
|
||
|
||
if( fill_ref & fill_item )
|
||
return 0;
|
||
if( fill_ref )
|
||
return BEFORE;
|
||
return AFTER;
|
||
}
|
||
|
||
|
||
/*****************************************************************************/
|
||
int AddFootprintFilterList( EDA_LibComponentStruct* LibEntryLibEntry, FILE* f,
|
||
char* Line, int* LineNum )
|
||
/******************************************************************************/
|
||
|
||
/* read the FootprintFilter List stating with:
|
||
* FPLIST
|
||
* and ending with:
|
||
* ENDFPLIST
|
||
*/
|
||
{
|
||
for( ; ; )
|
||
{
|
||
if( GetLine( f, Line, LineNum, 1024 ) == NULL )
|
||
{
|
||
DisplayError( NULL, wxT( "File ended prematurely" ) );
|
||
return 0;
|
||
}
|
||
|
||
if( stricmp( Line, "$ENDFPLIST" ) == 0 )
|
||
{
|
||
break; /*normal exit on end of list */
|
||
}
|
||
|
||
LibEntryLibEntry->m_FootprintList.Add( CONV_FROM_UTF8( Line + 1 ) );
|
||
}
|
||
|
||
return 1;
|
||
}
|