You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

400 lines
11 KiB

15 years ago
15 years ago
15 years ago
15 years ago
18 years ago
18 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
15 years ago
  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. /**
  26. * @file load_one_schematic_file.cpp
  27. * @brief Code to load and save Eeschema files.
  28. */
  29. #include <fctsys.h>
  30. #include <confirm.h>
  31. #include <kicad_string.h>
  32. #include <wxEeschemaStruct.h>
  33. #include <richio.h>
  34. #include <general.h>
  35. #include <sch_bus_entry.h>
  36. #include <sch_marker.h>
  37. #include <sch_junction.h>
  38. #include <sch_line.h>
  39. #include <sch_no_connect.h>
  40. #include <sch_component.h>
  41. #include <sch_polyline.h>
  42. #include <sch_text.h>
  43. #include <sch_sheet.h>
  44. #include <sch_bitmap.h>
  45. #include <wildcards_and_files_ext.h>
  46. bool ReadSchemaDescr( LINE_READER* aLine, wxString& aMsgDiag, SCH_SCREEN* Window );
  47. static void LoadLayers( LINE_READER* aLine );
  48. bool SCH_EDIT_FRAME::LoadOneEEFile( SCH_SCREEN* aScreen, const wxString& aFullFileName )
  49. {
  50. char name1[256];
  51. bool itemLoaded = false;
  52. SCH_ITEM* item;
  53. wxString msgDiag; // Error and log messages
  54. char* line;
  55. wxFileName fn;
  56. if( aScreen == NULL )
  57. return false;
  58. if( aFullFileName.IsEmpty() )
  59. return false;
  60. fn = aFullFileName;
  61. CheckForAutoSaveFile( fn, SchematicBackupFileExtension );
  62. wxLogTrace( traceAutoSave, wxT( "Loading schematic file " ) + aFullFileName );
  63. aScreen->SetCurItem( NULL );
  64. aScreen->SetFileName( aFullFileName );
  65. FILE* f;
  66. wxString fname = aFullFileName;
  67. #ifdef __WINDOWS__
  68. fname.Replace( wxT("/"), wxT("\\") );
  69. #else
  70. fname.Replace( wxT("\\"), wxT("/") );
  71. #endif
  72. if( ( f = wxFopen( fname, wxT( "rt" ) ) ) == NULL )
  73. {
  74. msgDiag = _( "Failed to open " ) + aFullFileName;
  75. DisplayError( this, msgDiag );
  76. return false;
  77. }
  78. // reader now owns the open FILE.
  79. FILE_LINE_READER reader( f, aFullFileName );
  80. msgDiag = _( "Loading " ) + aScreen->GetFileName();
  81. PrintMsg( msgDiag );
  82. if( !reader.ReadLine()
  83. || strncmp( (char*)reader + 9, SCHEMATIC_HEAD_STRING,
  84. sizeof( SCHEMATIC_HEAD_STRING ) - 1 ) != 0 )
  85. {
  86. msgDiag = aFullFileName + _( " is NOT an Eeschema file!" );
  87. DisplayError( this, msgDiag );
  88. return false;
  89. }
  90. line = reader.Line();
  91. // get the file version here.
  92. char *strversion = line + 9 + sizeof( SCHEMATIC_HEAD_STRING );
  93. // Skip blanks
  94. while( *strversion && *strversion < '0' )
  95. strversion++;
  96. int version = atoi( strversion );
  97. if( version > EESCHEMA_VERSION )
  98. {
  99. msgDiag = aFullFileName + _( " was created by a more recent \
  100. version of Eeschema and may not load correctly. Please consider updating!" );
  101. DisplayInfoMessage( this, msgDiag );
  102. }
  103. #if 0
  104. // Compile it if the new version is unreadable by previous Eeschema versions
  105. else if( version < EESCHEMA_VERSION )
  106. {
  107. MsgDiag = aFullFileName + _( " was created by an older version of \
  108. Eeschema. It will be stored in the new file format when you save this file \
  109. again." );
  110. DisplayInfoMessage( this, MsgDiag );
  111. }
  112. #endif
  113. if( !reader.ReadLine() || strncmp( reader, "LIBS:", 5 ) != 0 )
  114. {
  115. msgDiag = aFullFileName + _( " is NOT an Eeschema file!" );
  116. DisplayError( this, msgDiag );
  117. return false;
  118. }
  119. LoadLayers( &reader );
  120. while( reader.ReadLine() )
  121. {
  122. line = reader.Line();
  123. item = NULL;
  124. char* sline = line;
  125. while( (*sline != ' ' ) && *sline )
  126. sline++;
  127. switch( line[0] )
  128. {
  129. case '$': // identification block
  130. if( line[1] == 'C' )
  131. item = new SCH_COMPONENT();
  132. else if( line[1] == 'S' )
  133. item = new SCH_SHEET();
  134. else if( line[1] == 'D' )
  135. itemLoaded = ReadSchemaDescr( &reader, msgDiag, aScreen );
  136. else if( line[1] == 'B' )
  137. item = new SCH_BITMAP();
  138. break;
  139. case 'L': // Its a library item.
  140. item = new SCH_COMPONENT();
  141. break;
  142. case 'W': // Its a Segment (WIRE or BUS) item.
  143. item = new SCH_LINE();
  144. break;
  145. case 'E': // Its a WIRE or BUS item.
  146. item = new SCH_BUS_ENTRY();
  147. break;
  148. case 'P': // Its a polyline item.
  149. item = new SCH_POLYLINE();
  150. break;
  151. case 'C': // It is a connection item.
  152. item = new SCH_JUNCTION();
  153. break;
  154. case 'K': // It is a Marker item.
  155. // Markers are no more read from file. they are only created on
  156. // demand in schematic
  157. break;
  158. case 'N': // It is a NoConnect item.
  159. item = new SCH_NO_CONNECT();
  160. break;
  161. case 'T': // It is a text item.
  162. if( sscanf( sline, "%s", name1 ) != 1 )
  163. {
  164. msgDiag.Printf( _( "Eeschema file text load error at line %d" ),
  165. reader.LineNumber() );
  166. itemLoaded = false;
  167. }
  168. else if( name1[0] == 'L' )
  169. item = new SCH_LABEL();
  170. else if( name1[0] == 'G' && version > 1 )
  171. item = new SCH_GLOBALLABEL();
  172. else if( (name1[0] == 'H') || (name1[0] == 'G' && version == 1) )
  173. item = new SCH_HIERLABEL();
  174. else
  175. item = new SCH_TEXT();
  176. break;
  177. default:
  178. itemLoaded = false;
  179. msgDiag.Printf( _( "Eeschema file undefined object at line %d, aborted" ),
  180. reader.LineNumber() );
  181. msgDiag << wxT( "\n" ) << FROM_UTF8( line );
  182. }
  183. if( item )
  184. {
  185. itemLoaded = item->Load( reader, msgDiag );
  186. if( !itemLoaded )
  187. {
  188. SAFE_DELETE( item );
  189. }
  190. else
  191. {
  192. aScreen->Append( item );
  193. }
  194. }
  195. if( !itemLoaded )
  196. {
  197. DisplayError( this, msgDiag );
  198. break;
  199. }
  200. }
  201. #if 0 && defined (DEBUG)
  202. aScreen->Show( 0, std::cout );
  203. #endif
  204. aScreen->TestDanglingEnds();
  205. msgDiag = _( "Done Loading " ) + aScreen->GetFileName();
  206. PrintMsg( msgDiag );
  207. return true; // Although it may be that file is only partially loaded.
  208. }
  209. static void LoadLayers( LINE_READER* aLine )
  210. {
  211. /* read the layer descr
  212. * legacy code, not actually used, so this section is just skipped
  213. * read lines like
  214. * EELAYER 25 0
  215. * EELAYER END
  216. */
  217. while( aLine->ReadLine() )
  218. {
  219. if( strnicmp( *aLine, "EELAYER END", 11 ) == 0 )
  220. break;
  221. }
  222. }
  223. /// Get the length of a string constant, at compile time
  224. #define SZ( x ) (sizeof(x)-1)
  225. static const char delims[] = " \t\r\n";
  226. /* Read the schematic header. */
  227. bool ReadSchemaDescr( LINE_READER* aLine, wxString& aMsgDiag, SCH_SCREEN* aScreen )
  228. {
  229. char* line = aLine->Line();
  230. char* pageType = strtok( line + SZ( "$Descr" ), delims );
  231. char* width = strtok( NULL, delims );
  232. char* height = strtok( NULL, delims );
  233. char* orient = strtok( NULL, delims );
  234. wxString pagename = FROM_UTF8( pageType );
  235. PAGE_INFO pageInfo;
  236. TITLE_BLOCK tb;
  237. if( !pageInfo.SetType( pagename ) )
  238. {
  239. aMsgDiag.Printf( _( "Eeschema file dimension definition error \
  240. line %d,\nAbort reading file.\n" ),
  241. aLine->LineNumber() );
  242. aMsgDiag << FROM_UTF8( line );
  243. }
  244. if( pagename == PAGE_INFO::Custom )
  245. {
  246. if( width && height )
  247. {
  248. int w = atoi( width );
  249. int h = atoi( height );
  250. pageInfo.SetWidthMils( w );
  251. pageInfo.SetHeightMils( h );
  252. }
  253. }
  254. // non custom size, set portrait if its present
  255. else if( orient && !strcmp( orient, "portrait" ) )
  256. {
  257. pageInfo.SetPortrait( true );
  258. }
  259. aScreen->SetPageSettings( pageInfo );
  260. for(;;)
  261. {
  262. char buf[1024];
  263. if( !aLine->ReadLine() )
  264. return true;
  265. line = aLine->Line();
  266. if( strnicmp( line, "$End", 4 ) == 0 )
  267. {
  268. aScreen->SetTitleBlock( tb );
  269. break;
  270. }
  271. if( strnicmp( line, "Sheet", 2 ) == 0 )
  272. sscanf( line + 5, " %d %d",
  273. &aScreen->m_ScreenNumber, &aScreen->m_NumberOfScreens );
  274. if( strnicmp( line, "Title", 2 ) == 0 )
  275. {
  276. ReadDelimitedText( buf, line, 256 );
  277. tb.SetTitle( FROM_UTF8( buf ) );
  278. continue;
  279. }
  280. if( strnicmp( line, "Date", 2 ) == 0 )
  281. {
  282. ReadDelimitedText( buf, line, 256 );
  283. tb.SetDate( FROM_UTF8( buf ) );
  284. continue;
  285. }
  286. if( strnicmp( line, "Rev", 2 ) == 0 )
  287. {
  288. ReadDelimitedText( buf, line, 256 );
  289. tb.SetRevision( FROM_UTF8( buf ) );
  290. continue;
  291. }
  292. if( strnicmp( line, "Comp", 4 ) == 0 )
  293. {
  294. ReadDelimitedText( buf, line, 256 );
  295. tb.SetCompany( FROM_UTF8( buf ) );
  296. continue;
  297. }
  298. if( strnicmp( line, "Comment1", 8 ) == 0 )
  299. {
  300. ReadDelimitedText( buf, line, 256 );
  301. tb.SetComment1( FROM_UTF8( buf ) );
  302. continue;
  303. }
  304. if( strnicmp( line, "Comment2", 8 ) == 0 )
  305. {
  306. ReadDelimitedText( buf, line, 256 );
  307. tb.SetComment2( FROM_UTF8( buf ) );
  308. continue;
  309. }
  310. if( strnicmp( line, "Comment3", 8 ) == 0 )
  311. {
  312. ReadDelimitedText( buf, line, 256 );
  313. tb.SetComment3( FROM_UTF8( buf ) );
  314. continue;
  315. }
  316. if( strnicmp( line, "Comment4", 8 ) == 0 )
  317. {
  318. ReadDelimitedText( buf, line, 256 );
  319. tb.SetComment4( FROM_UTF8( buf ) );
  320. continue;
  321. }
  322. }
  323. return true;
  324. }