KiCad PCB EDA Suite
load_one_schematic_file.cpp
Go to the documentation of this file.
1 /*
2  * This program source code file is part of KiCad, a free EDA CAD application.
3  *
4  * Copyright (C) 2004 Jean-Pierre Charras, jean-pierre.charras@gipsa-lab.inpg.fr
5  * Copyright (C) 2008 Wayne Stambaugh <stambaughw@verizon.net>
6  * Copyright (C) 1992-2011 KiCad Developers, see AUTHORS.txt for contributors.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * as published by the Free Software Foundation; either version 2
11  * of the License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, you may find one here:
20  * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
21  * or you may search the http://www.gnu.org website for the version 2 license,
22  * or you may write to the Free Software Foundation, Inc.,
23  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
24  */
25 
31 #include <fctsys.h>
32 #include <confirm.h>
33 #include <kicad_string.h>
34 #include <schframe.h>
35 #include <richio.h>
36 #include <project.h>
37 
38 #include <general.h>
39 #include <sch_bus_entry.h>
40 #include <sch_marker.h>
41 #include <sch_junction.h>
42 #include <sch_line.h>
43 #include <sch_no_connect.h>
44 #include <sch_component.h>
45 #include <sch_text.h>
46 #include <sch_sheet.h>
47 #include <sch_bitmap.h>
49 
50 
51 bool ReadSchemaDescr( LINE_READER* aLine, wxString& aMsgDiag, SCH_SCREEN* Window );
52 
53 
54 bool SCH_EDIT_FRAME::LoadOneEEFile( SCH_SCREEN* aScreen, const wxString& aFullFileName, bool append )
55 {
56  char name1[256];
57  bool itemLoaded = false;
58  SCH_ITEM* item;
59  wxString msgDiag; // Error and log messages
60  char* line;
61  wxFileName fn;
62 
63  if( aScreen == NULL )
64  return false;
65 
66  if( aFullFileName.IsEmpty() )
67  return false;
68 
69  // Place the undo limit into the screen
71 
72  // If path is relative, this expands it from the project directory.
73  wxString fname = Prj().AbsolutePath( aFullFileName );
74 
75 #ifdef __WINDOWS__
76  fname.Replace( wxT("/"), wxT("\\") );
77 #else
78  fname.Replace( wxT("\\"), wxT("/") );
79 #endif
80 
81  fn = fname;
83 
84  wxLogTrace( traceAutoSave, wxT( "Loading schematic file " ) + aFullFileName );
85 
86  aScreen->SetCurItem( NULL );
87  if( !append )
88  aScreen->SetFileName( aFullFileName );
89 
90  FILE* f = wxFopen( fname, wxT( "rt" ) );
91 
92  if( !f )
93  {
94  msgDiag.Printf( _( "Failed to open '%s'" ), GetChars( aFullFileName ) );
95  DisplayError( this, msgDiag );
96  return false;
97  }
98 
99  // reader now owns the open FILE.
100  FILE_LINE_READER reader( f, aFullFileName );
101 
102  msgDiag.Printf( _( "Loading '%s'" ), GetChars( aScreen->GetFileName() ) );
103  PrintMsg( msgDiag );
104 
105  if( !reader.ReadLine()
106  || strncmp( (char*)reader + 9, SCHEMATIC_HEAD_STRING,
107  sizeof( SCHEMATIC_HEAD_STRING ) - 1 ) != 0 )
108  {
109  msgDiag.Printf( _( "'%s' is NOT an Eeschema file!" ), GetChars( aFullFileName ) );
110  DisplayError( this, msgDiag );
111  return false;
112  }
113 
114  line = reader.Line();
115 
116  // get the file version here.
117  char *strversion = line + 9 + sizeof( SCHEMATIC_HEAD_STRING );
118 
119  // Skip blanks
120  while( *strversion && *strversion < '0' )
121  strversion++;
122 
123  int version = atoi( strversion );
124 
125  if( version > EESCHEMA_VERSION )
126  {
127  msgDiag.Printf( _(
128  "'%s' was created by a more recent version of Eeschema and may not"
129  " load correctly. Please consider updating!" ),
130  GetChars( aFullFileName )
131  );
132  DisplayInfoMessage( this, msgDiag );
133  }
134 
135 #if 0
136  // Compile it if the new version is unreadable by previous Eeschema versions
137  else if( version < EESCHEMA_VERSION )
138  {
139  MsgDiag = aFullFileName + _( " was created by an older version of \
140 Eeschema. It will be stored in the new file format when you save this file \
141 again." );
142 
143  DisplayInfoMessage( this, MsgDiag );
144  }
145 #endif
146 
147  // The next lines are the lib list section, and are mainly comments, like:
148  // LIBS:power
149  // the lib list is not used, but is in schematic file just in case.
150  // It is usually not empty, but we accept empty list.
151  // If empty, there is a legacy section, not used
152  // EELAYER i j
153  // and the last line is
154  // EELAYER END
155  // Skip all lines until the end of header "EELAYER END" is found
156  while( reader.ReadLine() )
157  {
158  line = reader.Line();
159 
160  while( *line == ' ' )
161  line++;
162 
163  if( strncasecmp( line, "EELAYER END", 11 ) == 0 )
164  break; // end of not used header found
165  }
166 
167  while( reader.ReadLine() )
168  {
169  itemLoaded = false;
170  line = reader.Line();
171 
172  item = NULL;
173 
174  char* sline = line;
175 
176  while( (*sline != ' ' ) && *sline )
177  sline++;
178 
179  switch( line[0] )
180  {
181  case '$': // identification block
182  if( line[1] == 'C' )
183  item = new SCH_COMPONENT();
184  else if( line[1] == 'S' )
185  item = new SCH_SHEET();
186  else if( line[1] == 'D' )
187  itemLoaded = ReadSchemaDescr( &reader, msgDiag, aScreen );
188  else if( line[1] == 'B' )
189  item = new SCH_BITMAP();
190  else if( line[1] == 'E' )
191  itemLoaded = true; // The EOF marker
192  break;
193 
194  case 'L': // Its a library item.
195  item = new SCH_COMPONENT();
196  break;
197 
198  case 'W': // Its a Segment (WIRE or BUS) item.
199  item = new SCH_LINE();
200  break;
201 
202  case 'E': // Its a WIRE or BUS item.
203  /* The bus entry can be represented by two different
204  * classes, so we need a factory function */
205  itemLoaded = SCH_BUS_ENTRY_BASE::Load( reader, msgDiag, &item );
206  break;
207 
208  case 'C': // It is a connection item.
209  item = new SCH_JUNCTION();
210  break;
211 
212  case 'K': // It is a Marker item.
213  // Markers are no more read from file. they are only created on
214  // demand in schematic
215  itemLoaded = true; // Just skip descr and disable err message
216  break;
217 
218  case 'N': // It is a NoConnect item.
219  item = new SCH_NO_CONNECT();
220  break;
221 
222  case 'T': // It is a text item.
223  if( sscanf( sline, "%255s", name1 ) != 1 )
224  {
225  msgDiag.Printf( _( "Eeschema file text load error at line %d" ),
226  reader.LineNumber() );
227  itemLoaded = false;
228  }
229  else if( name1[0] == 'L' )
230  item = new SCH_LABEL();
231  else if( name1[0] == 'G' && version > 1 )
232  item = new SCH_GLOBALLABEL();
233  else if( (name1[0] == 'H') || (name1[0] == 'G' && version == 1) )
234  item = new SCH_HIERLABEL();
235  else
236  item = new SCH_TEXT();
237  break;
238 
239  default:
240  itemLoaded = false;
241  msgDiag.Printf( _( "Eeschema file undefined object at line %d, aborted" ),
242  reader.LineNumber() );
243  msgDiag << wxT( "\n" ) << FROM_UTF8( line );
244  }
245 
246  if( item )
247  {
248  // Load it if it wasn't by a factory
249  if( !itemLoaded )
250  itemLoaded = item->Load( reader, msgDiag );
251 
252  if( !itemLoaded )
253  {
254  delete item;
255  }
256  else
257  {
258  aScreen->Append( item );
259  }
260  }
261 
262  if( !itemLoaded )
263  {
264  msgDiag.Printf( _( "Eeschema file object not loaded at line %d, aborted" ),
265  reader.LineNumber() );
266  msgDiag << wxT( "\n" ) << FROM_UTF8( line );
267  DisplayError( this, msgDiag );
268  break;
269  }
270  }
271 
272 #if 0 && defined (DEBUG)
273  aScreen->Show( 0, std::cout );
274 #endif
275 
276  // Build links between each components and its part lib LIB_PART
277  aScreen->CheckComponentsToPartsLinks();
278 
279  aScreen->TestDanglingEnds();
280 
281  msgDiag.Printf( _( "Done Loading <%s>" ), GetChars( aScreen->GetFileName() ) );
282  PrintMsg( msgDiag );
283 
284  return true; // Although it may be that file is only partially loaded.
285 }
286 
287 
289 #define SZ( x ) (sizeof(x)-1)
290 
291 static const char delims[] = " \t\r\n";
292 
293 /* Read the schematic header. */
294 bool ReadSchemaDescr( LINE_READER* aLine, wxString& aMsgDiag, SCH_SCREEN* aScreen )
295 {
296  char* line = aLine->Line();
297 
298  char* pageType = strtok( line + SZ( "$Descr" ), delims );
299  char* width = strtok( NULL, delims );
300  char* height = strtok( NULL, delims );
301  char* orient = strtok( NULL, delims );
302 
303  wxString pagename = FROM_UTF8( pageType );
304 
305  PAGE_INFO pageInfo;
306  TITLE_BLOCK tb;
307 
308  if( !pageInfo.SetType( pagename ) )
309  {
310  aMsgDiag.Printf( _( "Eeschema file dimension definition error line %d,"
311  "\nAbort reading file.\n" ),
312  aLine->LineNumber() );
313  aMsgDiag << FROM_UTF8( line );
314  }
315 
316  if( pagename == PAGE_INFO::Custom )
317  {
318  if( width && height )
319  {
320  int w = atoi( width );
321  int h = atoi( height );
322 
323  pageInfo.SetWidthMils( w );
324  pageInfo.SetHeightMils( h );
325  }
326  }
327 
328  // non custom size, set portrait if its present
329  else if( orient && !strcmp( orient, "portrait" ) )
330  {
331  pageInfo.SetPortrait( true );
332  }
333 
334  aScreen->SetPageSettings( pageInfo );
335 
336  for(;;)
337  {
338  char buf[1024];
339 
340  if( !aLine->ReadLine() )
341  return true;
342 
343  line = aLine->Line();
344 
345  if( strncasecmp( line, "$End", 4 ) == 0 )
346  {
347  aScreen->SetTitleBlock( tb );
348  break;
349  }
350 
351  if( strncasecmp( line, "Sheet", 2 ) == 0 )
352  sscanf( line + 5, " %d %d",
353  &aScreen->m_ScreenNumber, &aScreen->m_NumberOfScreens );
354 
355  if( strncasecmp( line, "Title", 2 ) == 0 )
356  {
357  ReadDelimitedText( buf, line, 256 );
358  tb.SetTitle( FROM_UTF8( buf ) );
359  continue;
360  }
361 
362  if( strncasecmp( line, "Date", 2 ) == 0 )
363  {
364  ReadDelimitedText( buf, line, 256 );
365  tb.SetDate( FROM_UTF8( buf ) );
366  continue;
367  }
368 
369  if( strncasecmp( line, "Rev", 2 ) == 0 )
370  {
371  ReadDelimitedText( buf, line, 256 );
372  tb.SetRevision( FROM_UTF8( buf ) );
373  continue;
374  }
375 
376  if( strncasecmp( line, "Comp", 4 ) == 0 )
377  {
378  ReadDelimitedText( buf, line, 256 );
379  tb.SetCompany( FROM_UTF8( buf ) );
380  continue;
381  }
382 
383  if( strncasecmp( line, "Comment1", 8 ) == 0 )
384  {
385  ReadDelimitedText( buf, line, 256 );
386  tb.SetComment1( FROM_UTF8( buf ) );
387  continue;
388  }
389 
390  if( strncasecmp( line, "Comment2", 8 ) == 0 )
391  {
392  ReadDelimitedText( buf, line, 256 );
393  tb.SetComment2( FROM_UTF8( buf ) );
394  continue;
395  }
396 
397  if( strncasecmp( line, "Comment3", 8 ) == 0 )
398  {
399  ReadDelimitedText( buf, line, 256 );
400  tb.SetComment3( FROM_UTF8( buf ) );
401  continue;
402  }
403 
404  if( strncasecmp( line, "Comment4", 8 ) == 0 )
405  {
406  ReadDelimitedText( buf, line, 256 );
407  tb.SetComment4( FROM_UTF8( buf ) );
408  continue;
409  }
410  }
411 
412  return true;
413 }
void SetComment1(const wxString &aComment)
Definition of the SCH_SHEET class for Eeschema.
void CheckForAutoSaveFile(const wxFileName &aFileName, const wxString &aBackupFileExtension)
Function CheckForAutoSaveFile checks if an auto save file exists for aFileName and takes the appropri...
Definition: basicframe.cpp:597
void PrintMsg(const wxString &text)
Definition: basicframe.cpp:401
Class LINE_READER is an abstract class from which implementation specific LINE_READERs may be derived...
Definition: richio.h:81
char * ReadLine() override
Function ReadLine reads a line of text into the buffer and increments the line number counter...
Definition: richio.cpp:196
virtual unsigned LineNumber() const
Function Line Number returns the line number of the last line read from this LINE_READER.
Definition: richio.h:159
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes...
Definition: macros.h:53
virtual bool Load(LINE_READER &aLine, wxString &aErrorMsg)
Function Load reads a schematic item from aLine in a .sch file.
This file is part of the common library.
void SetRevision(const wxString &aRevision)
const wxString & GetFileName() const
void SetDate(const wxString &aDate)
Function SetDate sets the date field, and defaults to the current time and date.
void SetPageSettings(const PAGE_INFO &aPageSettings)
static const wxChar Custom[]
"User" defined page type
Class TITLE_BLOCK holds the information shown in the lower right corner of a plot, printout, or editing view.
void SetComment4(const wxString &aComment)
#define SCHEMATIC_HEAD_STRING
Definition: general.h:41
PROJECT & Prj() const
Function Prj returns a reference to the PROJECT "associated with" this KIWAY.
#define EESCHEMA_VERSION
Definition: general.h:40
Class FILE_LINE_READER is a LINE_READER that reads from an open file.
Definition: richio.h:180
Class PAGE_INFO describes the page size and margins of a paper page on which to eventually print or p...
char * Line() const
Function Line returns a pointer to the last line that was read in.
Definition: richio.h:139
#define SZ(x)
Get the length of a string constant, at compile time.
VTBL_ENTRY const wxString AbsolutePath(const wxString &aFileName) const
Function AbsolutePath fixes up aFileName if it is relative to the project's directory to be an absolu...
Definition: project.cpp:371
void SetCompany(const wxString &aCompany)
The common library.
void DisplayInfoMessage(wxWindow *aParent, const wxString &aMessage, const wxString aExtraInfo)
Function DisplayInfoMessage displays an informational message box with aMessage.
Definition: confirm.cpp:102
bool SetType(const wxString &aStandardPageDescriptionName, bool IsPortrait=false)
Function SetType sets the name of the page type and also the sizes and margins commonly associated wi...
int m_UndoRedoCountMax
default Undo/Redo command Max depth, to be handed
Definition: draw_frame.h:89
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
void SetTitle(const wxString &aTitle)
void SetPortrait(bool isPortrait)
Function SetPortrait will rotate the paper page 90 degrees.
void SetHeightMils(int aHeightInMils)
static bool Load(LINE_READER &aLine, wxString &aErrorMsg, SCH_ITEM **out)
Class SCH_SHEET is the sheet symbol placed in a schematic, and is the entry point for a sub schematic...
Definition: sch_sheet.h:216
Definition the SCH_COMPONENT class for Eeschema.
void SetComment2(const wxString &aComment)
virtual char * ReadLine()=0
Function ReadLine reads a line of text into the buffer and increments the line number counter...
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
bool ReadSchemaDescr(LINE_READER *aLine, wxString &aMsgDiag, SCH_SCREEN *Window)
Class SCH_LINE is a segment description base class to describe items which have 2 end points (track...
Definition: sch_line.h:42
const wxString SchematicBackupFileExtension
void Append(SCH_ITEM *aItem)
bool LoadOneEEFile(SCH_SCREEN *aScreen, const wxString &aFullFileName, bool append=false)
Function LoadOneEEFile loads the schematic (.sch) file aFullFileName into aScreen.
bool TestDanglingEnds()
Function TestDanglingEnds tests all of the connectible objects in the schematic for unused connection...
Definition: sch_screen.cpp:915
void SetCurItem(SCH_ITEM *aItem)
Function SetCurItem sets the currently selected object, m_CurrentItem.
void SetWidthMils(int aWidthInMils)
void CheckComponentsToPartsLinks()
Function CheckComponentsToPartsLink initializes or reinitializes the weak reference to the LIB_PART f...
Definition: sch_screen.cpp:532
Class SCH_COMPONENT describes a real schematic component.
Definition: sch_component.h:69
void SetMaxUndoItems(int aMax)
void SetComment3(const wxString &aComment)
void SetFileName(const wxString &aFileName)
int ReadDelimitedText(wxString *aDest, const char *aSource)
Function ReadDelimitedText copies bytes from aSource delimited string segment to aDest wxString...
Definition: string.cpp:43
static const char delims[]
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:71
Class SCH_ITEM is a base class for any item which can be embedded within the SCHEMATIC container clas...
Implementation of the label properties dialog.
const wxChar traceAutoSave[]
Flag to enable auto save feature debug tracing.
Definition: basicframe.cpp:53