diff options
Diffstat (limited to 'eeschema/load_one_schematic_file.cpp')
-rw-r--r-- | eeschema/load_one_schematic_file.cpp | 413 |
1 files changed, 413 insertions, 0 deletions
diff --git a/eeschema/load_one_schematic_file.cpp b/eeschema/load_one_schematic_file.cpp new file mode 100644 index 0000000..5d4e345 --- /dev/null +++ b/eeschema/load_one_schematic_file.cpp @@ -0,0 +1,413 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr + * Copyright (C) 2008 Wayne Stambaugh <stambaughw@verizon.net> + * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.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 load_one_schematic_file.cpp + * @brief Code to load and save Eeschema files. + */ + +#include <fctsys.h> +#include <confirm.h> +#include <kicad_string.h> +#include <schframe.h> +#include <richio.h> +#include <project.h> + +#include <general.h> +#include <sch_bus_entry.h> +#include <sch_marker.h> +#include <sch_junction.h> +#include <sch_line.h> +#include <sch_no_connect.h> +#include <sch_component.h> +#include <sch_text.h> +#include <sch_sheet.h> +#include <sch_bitmap.h> +#include <wildcards_and_files_ext.h> + + +bool ReadSchemaDescr( LINE_READER* aLine, wxString& aMsgDiag, SCH_SCREEN* Window ); + + +bool SCH_EDIT_FRAME::LoadOneEEFile( SCH_SCREEN* aScreen, const wxString& aFullFileName, bool append ) +{ + char name1[256]; + bool itemLoaded = false; + SCH_ITEM* item; + wxString msgDiag; // Error and log messages + char* line; + wxFileName fn; + + if( aScreen == NULL ) + return false; + + if( aFullFileName.IsEmpty() ) + return false; + + // Place the undo limit into the screen + aScreen->SetMaxUndoItems( m_UndoRedoCountMax ); + + // If path is relative, this expands it from the project directory. + wxString fname = Prj().AbsolutePath( aFullFileName ); + +#ifdef __WINDOWS__ + fname.Replace( wxT("/"), wxT("\\") ); +#else + fname.Replace( wxT("\\"), wxT("/") ); +#endif + + fn = fname; + CheckForAutoSaveFile( fn, SchematicBackupFileExtension ); + + wxLogTrace( traceAutoSave, wxT( "Loading schematic file " ) + aFullFileName ); + + aScreen->SetCurItem( NULL ); + if( !append ) + aScreen->SetFileName( aFullFileName ); + + FILE* f = wxFopen( fname, wxT( "rt" ) ); + + if( !f ) + { + msgDiag.Printf( _( "Failed to open '%s'" ), GetChars( aFullFileName ) ); + DisplayError( this, msgDiag ); + return false; + } + + // reader now owns the open FILE. + FILE_LINE_READER reader( f, aFullFileName ); + + msgDiag.Printf( _( "Loading '%s'" ), GetChars( aScreen->GetFileName() ) ); + PrintMsg( msgDiag ); + + if( !reader.ReadLine() + || strncmp( (char*)reader + 9, SCHEMATIC_HEAD_STRING, + sizeof( SCHEMATIC_HEAD_STRING ) - 1 ) != 0 ) + { + msgDiag.Printf( _( "'%s' is NOT an Eeschema file!" ), GetChars( aFullFileName ) ); + DisplayError( this, msgDiag ); + return false; + } + + line = reader.Line(); + + // get the file version here. + char *strversion = line + 9 + sizeof( SCHEMATIC_HEAD_STRING ); + + // Skip blanks + while( *strversion && *strversion < '0' ) + strversion++; + + int version = atoi( strversion ); + + if( version > EESCHEMA_VERSION ) + { + msgDiag.Printf( _( + "'%s' was created by a more recent version of Eeschema and may not" + " load correctly. Please consider updating!" ), + GetChars( aFullFileName ) + ); + DisplayInfoMessage( this, msgDiag ); + } + +#if 0 + // Compile it if the new version is unreadable by previous Eeschema versions + else if( version < EESCHEMA_VERSION ) + { + MsgDiag = aFullFileName + _( " was created by an older version of \ +Eeschema. It will be stored in the new file format when you save this file \ +again." ); + + DisplayInfoMessage( this, MsgDiag ); + } +#endif + + // The next lines are the lib list section, and are mainly comments, like: + // LIBS:power + // the lib list is not used, but is in schematic file just in case. + // It is usually not empty, but we accept empty list. + // If empty, there is a legacy section, not used + // EELAYER i j + // and the last line is + // EELAYER END + // Skip all lines until the end of header "EELAYER END" is found + while( reader.ReadLine() ) + { + line = reader.Line(); + + while( *line == ' ' ) + line++; + + if( strnicmp( line, "EELAYER END", 11 ) == 0 ) + break; // end of not used header found + } + + while( reader.ReadLine() ) + { + itemLoaded = false; + line = reader.Line(); + + item = NULL; + + char* sline = line; + + while( (*sline != ' ' ) && *sline ) + sline++; + + switch( line[0] ) + { + case '$': // identification block + if( line[1] == 'C' ) + item = new SCH_COMPONENT(); + else if( line[1] == 'S' ) + item = new SCH_SHEET(); + else if( line[1] == 'D' ) + itemLoaded = ReadSchemaDescr( &reader, msgDiag, aScreen ); + else if( line[1] == 'B' ) + item = new SCH_BITMAP(); + else if( line[1] == 'E' ) + itemLoaded = true; // The EOF marker + break; + + case 'L': // Its a library item. + item = new SCH_COMPONENT(); + break; + + case 'W': // Its a Segment (WIRE or BUS) item. + item = new SCH_LINE(); + break; + + case 'E': // Its a WIRE or BUS item. + /* The bus entry can be represented by two different + * classes, so we need a factory function */ + itemLoaded = SCH_BUS_ENTRY_BASE::Load( reader, msgDiag, &item ); + break; + + case 'C': // It is a connection item. + item = new SCH_JUNCTION(); + break; + + case 'K': // It is a Marker item. + // Markers are no more read from file. they are only created on + // demand in schematic + itemLoaded = true; // Just skip descr and disable err message + break; + + case 'N': // It is a NoConnect item. + item = new SCH_NO_CONNECT(); + break; + + case 'T': // It is a text item. + if( sscanf( sline, "%255s", name1 ) != 1 ) + { + msgDiag.Printf( _( "Eeschema file text load error at line %d" ), + reader.LineNumber() ); + itemLoaded = false; + } + else if( name1[0] == 'L' ) + item = new SCH_LABEL(); + else if( name1[0] == 'G' && version > 1 ) + item = new SCH_GLOBALLABEL(); + else if( (name1[0] == 'H') || (name1[0] == 'G' && version == 1) ) + item = new SCH_HIERLABEL(); + else + item = new SCH_TEXT(); + break; + + default: + itemLoaded = false; + msgDiag.Printf( _( "Eeschema file undefined object at line %d, aborted" ), + reader.LineNumber() ); + msgDiag << wxT( "\n" ) << FROM_UTF8( line ); + } + + if( item ) + { + // Load it if it wasn't by a factory + if( !itemLoaded ) + itemLoaded = item->Load( reader, msgDiag ); + + if( !itemLoaded ) + { + delete item; + } + else + { + aScreen->Append( item ); + } + } + + if( !itemLoaded ) + { + msgDiag.Printf( _( "Eeschema file object not loaded at line %d, aborted" ), + reader.LineNumber() ); + msgDiag << wxT( "\n" ) << FROM_UTF8( line ); + DisplayError( this, msgDiag ); + break; + } + } + +#if 0 && defined (DEBUG) + aScreen->Show( 0, std::cout ); +#endif + + // Build links between each components and its part lib LIB_PART + aScreen->CheckComponentsToPartsLinks(); + + aScreen->TestDanglingEnds(); + + msgDiag.Printf( _( "Done Loading <%s>" ), GetChars( aScreen->GetFileName() ) ); + PrintMsg( msgDiag ); + + return true; // Although it may be that file is only partially loaded. +} + + +/// Get the length of a string constant, at compile time +#define SZ( x ) (sizeof(x)-1) + +static const char delims[] = " \t\r\n"; + +/* Read the schematic header. */ +bool ReadSchemaDescr( LINE_READER* aLine, wxString& aMsgDiag, SCH_SCREEN* aScreen ) +{ + char* line = aLine->Line(); + + char* pageType = strtok( line + SZ( "$Descr" ), delims ); + char* width = strtok( NULL, delims ); + char* height = strtok( NULL, delims ); + char* orient = strtok( NULL, delims ); + + wxString pagename = FROM_UTF8( pageType ); + + PAGE_INFO pageInfo; + TITLE_BLOCK tb; + + if( !pageInfo.SetType( pagename ) ) + { + aMsgDiag.Printf( _( "Eeschema file dimension definition error line %d," + "\nAbort reading file.\n" ), + aLine->LineNumber() ); + aMsgDiag << FROM_UTF8( line ); + } + + if( pagename == PAGE_INFO::Custom ) + { + if( width && height ) + { + int w = atoi( width ); + int h = atoi( height ); + + pageInfo.SetWidthMils( w ); + pageInfo.SetHeightMils( h ); + } + } + + // non custom size, set portrait if its present + else if( orient && !strcmp( orient, "portrait" ) ) + { + pageInfo.SetPortrait( true ); + } + + aScreen->SetPageSettings( pageInfo ); + + for(;;) + { + char buf[1024]; + + if( !aLine->ReadLine() ) + return true; + + line = aLine->Line(); + + if( strnicmp( line, "$End", 4 ) == 0 ) + { + aScreen->SetTitleBlock( tb ); + break; + } + + if( strnicmp( line, "Sheet", 2 ) == 0 ) + sscanf( line + 5, " %d %d", + &aScreen->m_ScreenNumber, &aScreen->m_NumberOfScreens ); + + if( strnicmp( line, "Title", 2 ) == 0 ) + { + ReadDelimitedText( buf, line, 256 ); + tb.SetTitle( FROM_UTF8( buf ) ); + continue; + } + + if( strnicmp( line, "Date", 2 ) == 0 ) + { + ReadDelimitedText( buf, line, 256 ); + tb.SetDate( FROM_UTF8( buf ) ); + continue; + } + + if( strnicmp( line, "Rev", 2 ) == 0 ) + { + ReadDelimitedText( buf, line, 256 ); + tb.SetRevision( FROM_UTF8( buf ) ); + continue; + } + + if( strnicmp( line, "Comp", 4 ) == 0 ) + { + ReadDelimitedText( buf, line, 256 ); + tb.SetCompany( FROM_UTF8( buf ) ); + continue; + } + + if( strnicmp( line, "Comment1", 8 ) == 0 ) + { + ReadDelimitedText( buf, line, 256 ); + tb.SetComment1( FROM_UTF8( buf ) ); + continue; + } + + if( strnicmp( line, "Comment2", 8 ) == 0 ) + { + ReadDelimitedText( buf, line, 256 ); + tb.SetComment2( FROM_UTF8( buf ) ); + continue; + } + + if( strnicmp( line, "Comment3", 8 ) == 0 ) + { + ReadDelimitedText( buf, line, 256 ); + tb.SetComment3( FROM_UTF8( buf ) ); + continue; + } + + if( strnicmp( line, "Comment4", 8 ) == 0 ) + { + ReadDelimitedText( buf, line, 256 ); + tb.SetComment4( FROM_UTF8( buf ) ); + continue; + } + } + + return true; +} |