Commit 8cad403d authored by Wayne Stambaugh's avatar Wayne Stambaugh
Browse files

Use line reader to load component library files and objects.

parent d5ea4750
Loading
Loading
Loading
Loading
+97 −102
Original line number Diff line number Diff line
/*************************/
/*  class_libentry.cpp   */
/*************************/
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
 * Copyright (C) 2008-2011 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

/**
 * @file class_libentry.cpp
 */

#include "fctsys.h"
#include "macros.h"
@@ -9,6 +34,7 @@
#include "plot_common.h"
#include "gr_basic.h"
#include "class_sch_screen.h"
#include "richio.h"

#include "general.h"
#include "protos.h"
@@ -27,7 +53,7 @@
#include <boost/foreach.hpp>


// Set this to 1 to print debugging ouput in alias and component destructors to verify
// Set this to 1 to print debugging output in alias and component destructors to verify
// objects get cleaned up properly.
#if defined( TRACE_DESTRUCTOR )
#undef TRACE_DESTRUCTOR
@@ -36,19 +62,6 @@
#define TRACE_DESTRUCTOR 0


/*******************************/
/* class LIB_ALIAS */
/*******************************/

/* Class to define an alias of a component
 *  An alias uses the component definition (graphic, pins...)
 *  but has its own name, keywords and documentation.
 *  Therefore, when the component is modified, alias of this component are
 *   modified.
 *  This is a simple method to create components with differs very few
 *  (like 74LS00, 74HC00 ... and many op amps )
 */

LIB_ALIAS::LIB_ALIAS( const wxString& aName, LIB_COMPONENT* aRootComponent ):
    EDA_ITEM( LIB_ALIAS_T )
{
@@ -71,7 +84,7 @@ LIB_ALIAS::LIB_ALIAS( const LIB_ALIAS& aAlias, LIB_COMPONENT* aRootComponent ) :
LIB_ALIAS::~LIB_ALIAS()
{
#if TRACE_DESTRUCTOR
    wxLogDebug( wxT( "Destroying alias \"%s\" of component \"%s\" with alais list count %d." ),
    wxLogDebug( wxT( "Destroying alias \"%s\" of component \"%s\" with alias list count %d." ),
                GetChars( name ), GetChars( root->GetName() ), root->m_aliases.size() );
#endif
}
@@ -97,14 +110,6 @@ CMP_LIBRARY* LIB_ALIAS::GetLibrary()
}


/**
 * Function SaveDoc
 * writes the doc info out to a FILE in "*.dcm" format.
 * Only non empty fields are written.
 * If all fields are empty, does not write anything
 * @param aFile The FILE to write to.
 * @return bool - true if success writing else false.
 */
bool LIB_ALIAS::SaveDoc( FILE* aFile )
{
    if( description.IsEmpty() && keyWords.IsEmpty() && docFileName.IsEmpty() )
@@ -150,17 +155,6 @@ int LibraryEntryCompare( const LIB_ALIAS* aItem1, const LIB_ALIAS* aItem2 )
}


/***********************/
/* class LIB_COMPONENT */
/***********************/

/**
 * Library component object definition.
 *
 * A library component object is typically saved and loaded
 * in a component library file (.lib).
 * Library components are different from schematic components.
 */
LIB_COMPONENT::LIB_COMPONENT( const wxString& aName, CMP_LIBRARY* aLibrary ) :
    EDA_ITEM( LIB_COMPONENT_T )
{
@@ -174,7 +168,7 @@ LIB_COMPONENT::LIB_COMPONENT( const wxString& aName, CMP_LIBRARY* aLibrary ) :
    m_showPinNumbers      = true;
    m_showPinNames        = true;

    // Create the default alias if the name paremeter is not empty.
    // Create the default alias if the name parameter is not empty.
    if( !aName.IsEmpty() )
        m_aliases.push_back( new LIB_ALIAS( aName, this ) );

@@ -256,12 +250,6 @@ wxString LIB_COMPONENT::GetLibraryName()
}


/**
 * Function ReturnSubReference
 * @return the sub reference for component having multiple parts per package.
 * The sub reference identify the part (or unit)
 * @param aUnit = the part identifier ( 1 to 26)
 */
wxString LIB_COMPONENT::ReturnSubReference( int aUnit )
{
    wxString subRef;
@@ -397,6 +385,7 @@ void LIB_COMPONENT::Plot( PLOTTER* aPlotter, int aUnit, int aConvert,
    {
        if( aUnit && item.m_Unit && ( item.m_Unit != aUnit ) )
            continue;

        if( aConvert && item.m_Convert && ( item.m_Convert != aConvert ) )
            continue;

@@ -467,6 +456,7 @@ LIB_ITEM* LIB_COMPONENT::GetNextDrawItem( LIB_ITEM* aItem, KICAD_T aType )

    // Search for last item
    size_t idx = 0;

    if( aItem )
    {
        for( ; idx < drawings.size(); idx++ )
@@ -612,6 +602,7 @@ bool LIB_COMPONENT::Save( FILE* aFile )
        if( !fields[i].m_Text.IsEmpty() )
        {
            fields[i].SetId( fieldId++ );

            if( !fields[i].Save( aFile ) )
                return false;
        }
@@ -681,21 +672,25 @@ bool LIB_COMPONENT::Save( FILE* aFile )
}


bool LIB_COMPONENT::Load( FILE* aFile, char* aLine, int* aLineNum, wxString& aErrorMsg )
bool LIB_COMPONENT::Load( LINE_READER& aLineReader, wxString& aErrorMsg )
{
    int      unused;
    char*    p;
    char*    componentName;
    char*    prefix = NULL;
    char*    line;

    bool     Res;
    wxString Msg;

    p = strtok( aLine, " \t\r\n" );
    line = aLineReader.Line();

    p = strtok( line, " \t\r\n" );

    if( strcmp( p, "DEF" ) != 0 )
    {
        aErrorMsg.Printf( wxT( "DEF command expected in line %d, aborted." ), *aLineNum );
        aErrorMsg.Printf( wxT( "DEF command expected in line %d, aborted." ),
                          aLineReader.LineNumber() );
        return false;
    }

@@ -716,10 +711,15 @@ bool LIB_COMPONENT::Load( FILE* aFile, char* aLine, int* aLineNum, wxString& aEr
        || ( p = strtok( NULL, " \t\n" ) ) == NULL           /* m_unitCount: */
        || sscanf( p, "%d", &m_unitCount ) != 1 )
    {
        aErrorMsg.Printf( wxT( "Wrong DEF format in line %d, skipped." ), *aLineNum );
        while( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) )
        aErrorMsg.Printf( wxT( "Wrong DEF format in line %d, skipped." ),
                          aLineReader.LineNumber() );

        while( aLineReader.ReadLine() )
        {
            p = strtok( aLine, " \t\n" );
            line = aLineReader.Line();

            p = strtok( line, " \t\n" );

            if( stricmp( p, "ENDDEF" ) == 0 )
                break;
        }
@@ -738,6 +738,7 @@ bool LIB_COMPONENT::Load( FILE* aFile, char* aLine, int* aLineNum, wxString& aEr
    LIB_FIELD& value = GetValueField();

    strupper( componentName );

    if( componentName[0] != '~' )
    {
        m_name = value.m_Text = FROM_UTF8( componentName );
@@ -766,41 +767,45 @@ bool LIB_COMPONENT::Load( FILE* aFile, char* aLine, int* aLineNum, wxString& aEr
    // Copy optional infos
    if( ( p = strtok( NULL, " \t\n" ) ) != NULL && *p == 'L' )
        m_unitsLocked = true;

    if( ( p = strtok( NULL, " \t\n" ) ) != NULL  && *p == 'P' )
        m_options = ENTRY_POWER;

    /* Read next lines */
    while( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) )
    while( aLineReader.ReadLine() )
    {
        p = strtok( aLine, " \t\n" );
        line = aLineReader.Line();

        p = strtok( line, " \t\r\n" );

        /* This is the error flag ( if an error occurs, Res = FALSE) */
        Res = true;

        if( (aLine[0] == 'T') && (aLine[1] == 'i') )
            Res = LoadDateAndTime( aLine );
        else if( aLine[0] == 'F' )
            Res = LoadField( aLine, Msg );
        if( (*line == 'T') && (*(line + 1) == 'i') )
            Res = LoadDateAndTime( aLineReader );
        else if( *line == 'F' )
            Res = LoadField( aLineReader, Msg );
        else if( strcmp( p, "ENDDEF" ) == 0 )
            break;
        else if( strcmp( p, "DRAW" ) == 0 )
            Res = LoadDrawEntries( aFile, aLine, aLineNum, Msg );
            Res = LoadDrawEntries( aLineReader, Msg );
        else if( strncmp( p, "ALIAS", 5 ) == 0 )
        {
            p = strtok( NULL, "\r\n" );
            Res = LoadAliases( p, aErrorMsg );
        }
        else if( strncmp( p, "$FPLIST", 5 ) == 0 )
            Res = LoadFootprints( aFile, aLine, aLineNum, Msg );
            Res = LoadFootprints( aLineReader, Msg );

        /* End line or block analysis: test for an error */
        if( !Res )
        {
            if( Msg.IsEmpty() )
                aErrorMsg.Printf( wxT( "error occurred at line %d " ), *aLineNum );
                aErrorMsg.Printf( wxT( "error occurred at line %d " ), aLineReader.LineNumber() );
            else
                aErrorMsg.Printf( wxT( "error <%s> occurred at line %d " ),
                                  GetChars( Msg ), *aLineNum );
                                  GetChars( Msg ), aLineReader.LineNumber() );

            return false;
        }
    }
@@ -812,25 +817,27 @@ bool LIB_COMPONENT::Load( FILE* aFile, char* aLine, int* aLineNum, wxString& aEr
}


bool LIB_COMPONENT::LoadDrawEntries( FILE* aFile, char* aLine,
                                     int* aLineNum, wxString& aErrorMsg )
bool LIB_COMPONENT::LoadDrawEntries( LINE_READER& aLineReader, wxString& aErrorMsg )
{
    char* line;
    LIB_ITEM* newEntry = NULL;

    while( true )
    {
        if( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) == NULL )
        if( !aLineReader.ReadLine() )
        {
            aErrorMsg = wxT( "file ended prematurely loading component draw element" );
            return false;
        }

        if( strncmp( aLine, "ENDDRAW", 7 ) == 0 )
        line = aLineReader.Line();

        if( strncmp( line, "ENDDRAW", 7 ) == 0 )
            break;

        newEntry = NULL;

        switch( aLine[0] )
        switch( line[0] )
        {
        case 'A':    /* Arc */
            newEntry = ( LIB_ITEM* ) new LIB_ARC( this );
@@ -861,26 +868,26 @@ bool LIB_COMPONENT::LoadDrawEntries( FILE* aFile, char* aLine,
            break;

        default:
            aErrorMsg.Printf( wxT( "undefined DRAW command %c" ), aLine[0] );
            aErrorMsg.Printf( wxT( "undefined DRAW command %c" ), line[0] );
            return false;
        }

        if( !newEntry->Load( aLine, aErrorMsg ) )
        if( !newEntry->Load( aLineReader, aErrorMsg ) )
        {
            aErrorMsg.Printf( wxT( "error <%s> in DRAW command %c" ),
                              GetChars( aErrorMsg ), aLine[0] );
                              GetChars( aErrorMsg ), line[0] );
            SAFE_DELETE( newEntry );

            /* Flush till end of draw section */
            do
            {
                if( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) == NULL )
                if( !aLineReader.ReadLine() )
                {
                    aErrorMsg = wxT( "file ended prematurely while attempting \
to flush to end of drawing section." );
                    return false;
                }
            } while( strncmp( aLine, "ENDDRAW", 7 ) != 0 );
            } while( strncmp( line, "ENDDRAW", 7 ) != 0 );

            return false;
        }
@@ -908,11 +915,11 @@ bool LIB_COMPONENT::LoadAliases( char* aLine, wxString& aErrorMsg )
}


bool LIB_COMPONENT::LoadField( char* aLine, wxString& aErrorMsg )
bool LIB_COMPONENT::LoadField( LINE_READER& aLineReader, wxString& aErrorMsg )
{
    LIB_FIELD* field = new LIB_FIELD( this );

    if( !field->Load( aLine, aErrorMsg ) )
    if( !field->Load( aLineReader, aErrorMsg ) )
    {
        SAFE_DELETE( field );
        return false;
@@ -943,33 +950,32 @@ bool LIB_COMPONENT::LoadField( char* aLine, wxString& aErrorMsg )
}


bool LIB_COMPONENT::LoadFootprints( FILE* aFile, char* aLine,
                                    int* aLineNum, wxString& aErrorMsg )
bool LIB_COMPONENT::LoadFootprints( LINE_READER& aLineReader, wxString& aErrorMsg )
{
    char* line;
    char* p;

    while( true )
    {
        if( GetLine( aFile, aLine, aLineNum, LINE_BUFFER_LEN_LARGE ) == NULL )
        if( !aLineReader.ReadLine() )
        {
            aErrorMsg = wxT( "file ended prematurely while loading footprints" );
            return false;
        }

        if( stricmp( aLine, "$ENDFPLIST" ) == 0 )
        line = aLineReader.Line();
        p = strtok( line, " \t\r\n" );

        if( stricmp( p, "$ENDFPLIST" ) == 0 )
            break;

        m_FootprintList.Add( FROM_UTF8( aLine + 1 ) );
        m_FootprintList.Add( FROM_UTF8( p ) );
    }

    return true;
}

/* Return the component boundary box ( in user coordinates )
 * aUnit = unit selection = 0, or 1..n
 * aConvert = 0, 1 or 2
 *  If aUnit == 0, unit is not used
 *  if aConvert == 0 Convert is non used
 *  Invisible fields are not taken in account
 **/

EDA_RECT LIB_COMPONENT::GetBoundingBox( int aUnit, int aConvert ) const
{
    EDA_RECT bBox( wxPoint( 0, 0 ), wxSize( 0, 0 ) );
@@ -993,13 +999,6 @@ EDA_RECT LIB_COMPONENT::GetBoundingBox( int aUnit, int aConvert ) const
}


/* Return the component boundary box ( in user coordinates )
 * aUnit = unit selection = 0, or 1..n
 * aConvert = 0, 1 or 2
 *  If aUnit == 0, unit is not used
 *  if aConvert == 0 Convert is non used
 *  Fields are not take in account
 **/
EDA_RECT LIB_COMPONENT::GetBodyBoundingBox( int aUnit, int aConvert ) const
{
    EDA_RECT bBox( wxPoint( 0, 0 ), wxSize( 0, 0 ) );
@@ -1085,6 +1084,7 @@ void LIB_COMPONENT::GetFields( LIB_FIELDS& aList )
            continue;

        field = ( LIB_FIELD* ) &item;

        if( (unsigned) field->GetId() < MANDATORY_FIELDS )
            continue;  // was added above

@@ -1143,10 +1143,6 @@ LIB_FIELD& LIB_COMPONENT::GetReferenceField()
}


/*
 * Read date and time of component in the format:
 *  "Ti yy/mm/jj hh:mm:ss"
 */
bool LIB_COMPONENT::SaveDateAndTime( FILE* aFile )
{
    int year, mon, day, hour, min, sec;
@@ -1167,9 +1163,6 @@ bool LIB_COMPONENT::SaveDateAndTime( FILE* aFile )
    return true;
}

/* lit date et time de modif composant sous le format:
 *  "Ti yy/mm/jj hh:mm:ss"
 */
bool LIB_COMPONENT::LoadDateAndTime( char* aLine )
{
    int   year, mon, day, hour, min, sec;
@@ -1316,6 +1309,7 @@ void LIB_COMPONENT::CopySelectedItems( const wxPoint& aOffset )
     * a memory reallocation can happen and will break pointers
     */
    unsigned icnt = drawings.size();

    for( unsigned ii = 0; ii < icnt; ii++  )
    {
        LIB_ITEM& item = drawings[ii];
@@ -1448,6 +1442,7 @@ void LIB_COMPONENT::SetPartCount( int aCount )
        // the buffer can be reallocated, that change the previous value of
        // .begin() and .end() iterators and invalidate others iterators
        unsigned imax = drawings.size();

        for( unsigned ii = 0; ii < imax; ii++ )
        {
            if( drawings[ii].m_Unit != 1 )
@@ -1476,12 +1471,12 @@ void LIB_COMPONENT::SetConversion( bool aSetConvert )
    // Duplicate items to create the converted shape
    if( aSetConvert )
    {

        BOOST_FOREACH( LIB_ITEM& item, drawings )
        {
            /* Only pins are duplicated. */
            if( item.Type() != LIB_PIN_T )
                continue;

            if( item.m_Convert == 1 )
            {
                LIB_ITEM* newItem = (LIB_ITEM*) item.Clone();
+52 −15
Original line number Diff line number Diff line
/******************************************/
/*  Library component object definitions. */
/******************************************/
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
 * Copyright (C) 2008-2011 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

/**
 * @file class_libentry.h
 */

#ifndef CLASS_LIBENTRY_H
#define CLASS_LIBENTRY_H
@@ -12,6 +37,7 @@
#include <map>


class LINE_READER;
class CMP_LIBRARY;
class LIB_ALIAS;
class LIB_COMPONENT;
@@ -45,8 +71,11 @@ enum LibrEntryOptions
/**
 * Component library alias object definition.
 *
 * Component aliases are not really components.  They are references
 * to an actual component object.
 * Component aliases are not really components.  An alias uses the component definition
 * (graphic, pins...)  but has its own name, keywords and documentation.  Therefore, when
 * the component is modified, alias of this component are modified.  This is a simple
 * method to create components that have the same physical layout with different names
 * such as 74LS00, 74HC00 ... and many op amps.
 */
class LIB_ALIAS : public EDA_ITEM
{
@@ -144,7 +173,8 @@ extern int LibraryEntryCompare( const LIB_ALIAS* aItem1, const LIB_ALIAS* aItem2


/**
 * Library component object definition.
 * Class LIB_COMPONENT
 * defines a library component object.
 *
 * A library component object is typically saved and loaded in a component library file (.lib).
 * Library components are different from schematic components.
@@ -207,7 +237,7 @@ public:
     * Add an alias \a aName to the component.
     *
     * Duplicate alias names are not added to the alias list.  Debug builds will raise an
     * assertion.  Release builds will fail silenetly.
     * assertion.  Release builds will fail silently.
     *
     * @param aName - Name of alias to add.
     */
@@ -255,7 +285,16 @@ public:
     **/
    EDA_RECT GetBodyBoundingBox( int aUnit, int aConvert ) const;

    /**
     * Function SaveDateAndTime
     * write the date and time of component to \a aFile in the format:
     * "Ti yy/mm/jj hh:mm:ss"
     *
     * @param aFile A point to a FILE object containing the file to write to.
     * @return True if the date and time were successfully written to \a aFile.
     */
    bool SaveDateAndTime( FILE* aFile );

    bool LoadDateAndTime( char* aLine );

    /**
@@ -267,19 +306,17 @@ public:
    bool Save( FILE* aFile );

    /**
     * Load component definition from \a aFile.
     * Load component definition from \a aReader.
     *
     * @param aFile - File descriptor of file to load form.
     * @param aLine - The first line of the component definition.
     * @param aLineNum - The current line number in the file.
     * @param aReader A LINE_READER object to load file from.
     * @param aErrorMsg - Description of error on load failure.
     * @return True if the load was successful, false if there was an error.
     */
    bool Load( FILE* aFile, char* aLine, int* aLineNum, wxString& aErrorMsg );
    bool LoadField( char* aLine, wxString& aErrorMsg );
    bool LoadDrawEntries( FILE* aFile, char* aLine, int* aLineNum, wxString& aErrorMsg );
    bool Load( LINE_READER& aReader, wxString& aErrorMsg );
    bool LoadField( LINE_READER& aReader, wxString& aErrorMsg );
    bool LoadDrawEntries( LINE_READER& aReader, wxString& aErrorMsg );
    bool LoadAliases( char* aLine, wxString& aErrorMsg );
    bool LoadFootprints( FILE* aFile, char* aLine, int* aLineNum, wxString& aErrorMsg );
    bool LoadFootprints( LINE_READER& aReader, wxString& aErrorMsg );

    bool IsPower() { return m_options == ENTRY_POWER; }
    bool IsNormal() { return m_options == ENTRY_NORMAL; }
+54 −33
Original line number Diff line number Diff line
/*
 * This program source code file is part of KiCad, a free EDA CAD application.
 *
 * Copyright (C) 2004 Jean-Pierre Charras, jaen-pierre.charras@gipsa-lab.inpg.com
 * Copyright (C) 2008-2011 Wayne Stambaugh <stambaughw@verizon.net>
 * Copyright (C) 2004-2011 KiCad Developers, see change_log.txt for contributors.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, you may find one here:
 * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
 * or you may search the http://www.gnu.org website for the version 2 license,
 * or you may write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA
 */

/**
 * @file class_library.cpp
 */
@@ -10,6 +35,7 @@
#include "gestfich.h"
#include "eda_doc.h"
#include "wxstruct.h"
#include "richio.h"

#include "general.h"
#include "protos.h"
@@ -129,6 +155,7 @@ void CMP_LIBRARY::SearchEntryNames( wxArrayString& aNames,
    {
        if( !aKeySearch.IsEmpty() && KeyWordOk( aKeySearch, (*it).second->GetKeyWords() ) )
            aNames.Add( (*it).first );

        if( !aNameSearch.IsEmpty() && WildCompareString( aNameSearch,
                                                         (*it).second->GetName(), false ) )
            aNames.Add( (*it).first );
@@ -186,10 +213,6 @@ LIB_ALIAS* CMP_LIBRARY::FindEntry( const wxChar* aName )
}


/**
 * Return the first entry in the library.
 * @return The first entry or NULL if the library has no entries.
 */
LIB_ALIAS* CMP_LIBRARY::GetFirstEntry()
{
    if( aliases.size() )
@@ -198,6 +221,7 @@ LIB_ALIAS* CMP_LIBRARY::GetFirstEntry()
        return NULL;
}


LIB_COMPONENT* CMP_LIBRARY::FindComponent( const wxChar* aName )
{
    LIB_COMPONENT* component = NULL;
@@ -279,7 +303,7 @@ LIB_ALIAS* CMP_LIBRARY::RemoveEntry( LIB_ALIAS* aEntry )
        return NULL;

    // If the entry pointer doesn't match the name it is mapped to in the library, we
    // have done someething terribly wrong.
    // have done something terribly wrong.
    wxCHECK_MSG( (*it).second == aEntry, NULL,
                 wxT( "Pointer mismatch while attempting to remove entry <" ) +
                 aEntry->GetName() + wxT( "> from library <" ) + GetName() + wxT( ">." ) );
@@ -380,8 +404,7 @@ LIB_ALIAS* CMP_LIBRARY::GetPreviousEntry( const wxChar* aName )
bool CMP_LIBRARY::Load( wxString& aErrorMsg )
{
    FILE*          file;
    int            lineNumber = 0;
    char           line[LINE_BUFFER_LEN_LARGE];  // Use a very large buffer to load data
    char*          line;
    LIB_COMPONENT* libEntry;
    wxString       msg;

@@ -399,10 +422,11 @@ bool CMP_LIBRARY::Load( wxString& aErrorMsg )
        return false;
    }

    if( GetLine( file, line, &lineNumber, sizeof( line ) ) == NULL )
    FILE_LINE_READER reader( file, fileName.GetFullPath() );

    if( !reader.ReadLine() )
    {
        aErrorMsg = _( "The file is empty!" );
        fclose( file );
        return false;
    }

@@ -411,6 +435,8 @@ bool CMP_LIBRARY::Load( wxString& aErrorMsg )
    {
        wxString tmp;

        line = reader.Line();

        header = FROM_UTF8( line );

        wxStringTokenizer tkn( header );
@@ -426,21 +452,18 @@ bool CMP_LIBRARY::Load( wxString& aErrorMsg )
            || !tkn.GetNextToken().Upper().StartsWith(wxT( "EESCHEMA-LIB" ) ) )
        {
            aErrorMsg = _( "The file is NOT an Eeschema library!" );
            fclose( file );
            return false;
        }

        if( !tkn.HasMoreTokens() )
        {
            aErrorMsg = _( "The file header is missing version and time stamp information." );
            fclose( file );
            return false;
        }

        if( tkn.GetNextToken() != wxT( "Version" ) || !tkn.HasMoreTokens() )
        {
            aErrorMsg = wxT( "The file header version information is invalid." );
            fclose( file );
            return false;
        }

@@ -466,19 +489,18 @@ the current schematic." ),
        {
            versionMajor = (int) major;
            versionMinor = (int) minor;
//            wxLogDebug( wxT( "Component library <%s> is version %d.%d." ),
//                        GetChars( GetName() ), versionMajor, versionMinor );
        }
    }

    while( GetLine( file, line, &lineNumber, sizeof( line ) ) )
    while( reader.ReadLine() )
    {
        line = reader.Line();

        if( type == LIBRARY_TYPE_EESCHEMA && strnicmp( line, "$HEADER", 7 ) == 0 )
        {
            if( !LoadHeader( file, &lineNumber ) )
            if( !LoadHeader( reader ) )
            {
                aErrorMsg = _( "An error occurred attempting to read the header." );
                fclose( file );
                return false;
            }

@@ -490,7 +512,7 @@ the current schematic." ),
            /* Read one DEF/ENDDEF part entry from library: */
            libEntry = new LIB_COMPONENT( wxEmptyString, this );

            if( libEntry->Load( file, line, &lineNumber, msg ) )
            if( libEntry->Load( reader, msg ) )
            {
                /* Check for duplicate entry names and warn the user about
                 * the potential conflict.
@@ -516,8 +538,6 @@ the current schematic." ),
        }
    }

    fclose( file );

    return true;
}

@@ -542,13 +562,15 @@ void CMP_LIBRARY::LoadAliases( LIB_COMPONENT* component )
}


bool CMP_LIBRARY::LoadHeader( FILE* libfile, int* LineNum )
bool CMP_LIBRARY::LoadHeader( LINE_READER& aLineReader )
{
    char Line[LINE_BUFFER_LEN], * text, * data;
    char* line, * text, * data;

    while( GetLine( libfile, Line, LineNum, sizeof(Line) ) )
    while( aLineReader.ReadLine() )
    {
        text = strtok( Line, " \t\r\n" );
        line = (char*) aLineReader;

        text = strtok( line, " \t\r\n" );
        data = strtok( NULL, " \t\r\n" );

        if( stricmp( text, "TimeStamp" ) == 0 )
@@ -558,7 +580,7 @@ bool CMP_LIBRARY::LoadHeader( FILE* libfile, int* LineNum )
            return true;
    }

    return FALSE;
    return false;
}


@@ -618,6 +640,7 @@ bool CMP_LIBRARY::LoadDocs( wxString& aErrorMsg )
        {
            if( strncmp( line, "$ENDCMP", 7 ) == 0 )
                break;

            text = strtok( line + 2, "\n\r" );

            if( entry )
@@ -680,6 +703,7 @@ bool CMP_LIBRARY::Save( const wxString& aFullFileName, bool aOldDocFormat )
    isModified = false;

    timeStamp = GetTimeStamp();

    if( !SaveHeader( libfile ) )
    {
        fclose( libfile );
@@ -745,6 +769,7 @@ bool CMP_LIBRARY::SaveDocFile( const wxString& aFullFileName )
    }

    char line[256];

    if( fprintf( docfile, "%s  Date: %s\n", DOCFILE_IDENT, DateAndTime( line ) ) < 0 )
    {
        fclose( docfile );
@@ -774,6 +799,7 @@ bool CMP_LIBRARY::SaveHeader( FILE* aFile )
    bool succes = true;

    DateAndTime( BufLine );

    if( fprintf( aFile, "%s %d.%d  Date: %s\n", LIBFILE_IDENT,
                 LIB_VERSION_MAJOR, LIB_VERSION_MINOR, BufLine ) < 0 )
        succes = false;
@@ -884,11 +910,6 @@ void CMP_LIBRARY::RemoveLibrary( const wxString& aName )
}


 /**
 * Test for an existing library.
 * @param aLibptr - aLibptr.
 * @return true found.  false if not found.
 */
bool CMP_LIBRARY::LibraryExists( const CMP_LIBRARY* aLibptr )
{
    BOOST_FOREACH( CMP_LIBRARY& lib, libraryList )
Loading