Eeschema: implement s-expression schematic file format parser.

Fix a few issues with the s-expression schematic file formatter.
This commit is contained in:
Wayne Stambaugh 2020-03-25 11:27:15 -04:00
parent 9b4b85bb7d
commit 2f682b6c5f
10 changed files with 1313 additions and 311 deletions

View File

@ -22,7 +22,6 @@ F0 "#PWR" 0 -40 30 H I C CNN
F1 "video_schlib_+3.3V" 0 110 30 H V C CNN
F2 "" 0 0 60 H V C CNN
F3 "" 0 0 60 H V C CNN
ALIAS +3,3V
DRAW
C 0 60 20 0 1 0 N
P 3 0 1 0 0 0 0 40 0 40 N
@ -65,7 +64,6 @@ F0 "U" 150 350 60 H V C CNN
F1 "video_schlib_24C16" 200 -350 60 H V C CNN
F2 "" 0 0 60 H V C CNN
F3 "" 0 0 60 H V C CNN
ALIAS 24C512
DRAW
S -400 -300 400 300 1 1 0 N
X GND 4 0 -500 200 U 60 60 0 0 W
@ -118,7 +116,6 @@ F0 "U" 100 575 50 H V L BNN
F1 "video_schlib_74LS245" 50 -575 50 H V L TNN
F2 "" 50 -650 30 H V L CNN
F3 "" 100 575 30 H V C CNN
ALIAS 74HC245
DRAW
S -400 550 400 -550 0 1 0 N
P 3 0 1 0 50 100 0 -100 -100 -100 N
@ -188,7 +185,6 @@ F0 "U" 0 100 70 H V C CNN
F1 "video_schlib_BT253" 0 -100 70 H V C CNN
F2 "" 0 0 60 H V C CNN
F3 "" 0 0 60 H V C CNN
ALIAS BT254
DRAW
S -750 -2600 750 2600 0 1 0 N
X VAA 1 -50 2900 300 D 60 60 1 1 I
@ -510,135 +506,6 @@ X D6 99 -2050 -1800 300 R 60 60 1 1 T
ENDDRAW
ENDDEF
#
# video_schlib_BUSPCI-5V
#
DEF video_schlib_BUSPCI-5V J 0 30 Y Y 1 F N
F0 "J" 0 3200 60 H V C CNN
F1 "video_schlib_BUSPCI-5V" 0 -3200 60 H V C CNN
F2 "" 0 0 60 H V C CNN
F3 "" 0 0 60 H V C CNN
ALIAS BUSPCI-5V
DRAW
S -750 3150 750 -3150 0 1 0 N
X TRST# A1 1100 3050 350 L 60 60 1 1 O I
X VIO A10 1100 2150 350 L 60 60 1 1 W
X RESERVED A11 1100 2050 350 L 60 60 1 1 P
X 3.3VAUX A14 1100 1750 350 L 60 60 1 1 P
X RST# A15 1100 1650 350 L 60 60 1 1 O I
X VIO A16 1100 1550 350 L 60 60 1 1 W
X GNT# A17 1100 1450 350 L 60 60 1 1 B I
X GND A18 1100 1350 350 L 60 60 1 1 W
X PME# A19 1100 1250 350 L 60 60 1 1 P
X +12V A2 1100 2950 350 L 60 60 1 1 W
X AD[30] A20 1100 1150 350 L 60 60 1 1 B
X +3.3V A21 1100 1050 350 L 60 60 1 1 W
X AD[28] A22 1100 950 350 L 60 60 1 1 B
X AD[26] A23 1100 850 350 L 60 60 1 1 B
X GND A24 1100 750 350 L 60 60 1 1 W
X AD[24] A25 1100 650 350 L 60 60 1 1 B
X IDSEL A26 1100 550 350 L 60 60 1 1 O
X +3.3V A27 1100 450 350 L 60 60 1 1 W
X AD[22] A28 1100 350 350 L 60 60 1 1 B
X AD[20] A29 1100 250 350 L 60 60 1 1 B
X TMS A3 1100 2850 350 L 60 60 1 1 O
X GND A30 1100 150 350 L 60 60 1 1 W
X AD[18] A31 1100 50 350 L 60 60 1 1 B
X AD[16] A32 1100 -50 350 L 60 60 1 1 B
X +3.3V A33 1100 -150 350 L 60 60 1 1 W
X FRAME# A34 1100 -250 350 L 60 60 1 1 B I
X GND A35 1100 -350 350 L 60 60 1 1 W
X TRDY# A36 1100 -450 350 L 60 60 1 1 B I
X GND A37 1100 -550 350 L 60 60 1 1 W
X STOP# A38 1100 -650 350 L 60 60 1 1 B I
X +3.3V A39 1100 -750 350 L 60 60 1 1 W
X TDI A4 1100 2750 350 L 60 60 1 1 O
X RESERVED A40 1100 -850 350 L 60 60 1 1 B
X RESERVED A41 1100 -950 350 L 60 60 1 1 B
X GND A42 1100 -1050 350 L 60 60 1 1 W
X PAR A43 1100 -1150 350 L 60 60 1 1 B
X AD[15] A44 1100 -1250 350 L 60 60 1 1 B
X +3.3V A45 1100 -1350 350 L 60 60 1 1 W
X AD[13] A46 1100 -1450 350 L 60 60 1 1 B
X AD[11] A47 1100 -1550 350 L 60 60 1 1 B
X GND A48 1100 -1650 350 L 60 60 1 1 W
X AD[09] A49 1100 -1750 350 L 60 60 1 1 B
X +5V A5 1100 2650 350 L 60 60 1 1 W
X C/BE#[0] A52 1100 -2050 350 L 60 60 1 1 B I
X +3.3V A53 1100 -2150 350 L 60 60 1 1 W
X AD[06] A54 1100 -2250 350 L 60 60 1 1 B
X AD[04] A55 1100 -2350 350 L 60 60 1 1 B
X GND A56 1100 -2450 350 L 60 60 1 1 W
X AD[02] A57 1100 -2550 350 L 60 60 1 1 B
X AD[00] A58 1100 -2650 350 L 60 60 1 1 B
X VIO A59 1100 -2750 350 L 60 60 1 1 W
X INTA# A6 1100 2550 350 L 60 60 1 1 I I
X REQ64# A60 1100 -2850 350 L 60 60 1 1 B I
X +5V A61 1100 -2950 350 L 60 60 1 1 W
X +5V A62 1100 -3050 350 L 60 60 1 1 W
X INTC# A7 1100 2450 350 L 60 60 1 1 I I
X +5V A8 1100 2350 350 L 60 60 1 1 W
X RESERVED A9 1100 2250 350 L 60 60 1 1 P
X -12V B1 -1100 3050 350 R 60 60 1 1 W
X RESERVED B10 -1100 2150 350 R 60 60 1 1 P
X PRSNT2# B11 -1100 2050 350 R 60 60 1 1 I I
X RESERVED B14 -1100 1750 350 R 60 60 1 1 P
X GND B15 -1100 1650 350 R 60 60 1 1 W
X CLK B16 -1100 1550 350 R 60 60 1 1 O
X GND B17 -1100 1450 350 R 60 60 1 1 W
X REQ# B18 -1100 1350 350 R 60 60 1 1 B I
X VIO B19 -1100 1250 350 R 60 60 1 1 W
X TCK B2 -1100 2950 350 R 60 60 1 1 O
X AD[31] B20 -1100 1150 350 R 60 60 1 1 B
X AD[29] B21 -1100 1050 350 R 60 60 1 1 B
X GND B22 -1100 950 350 R 60 60 1 1 W
X AD[27] B23 -1100 850 350 R 60 60 1 1 B
X AD[25] B24 -1100 750 350 R 60 60 1 1 B
X +3.3V B25 -1100 650 350 R 60 60 1 1 W
X C/BE#[3] B26 -1100 550 350 R 60 60 1 1 B
X AD[23] B27 -1100 450 350 R 60 60 1 1 B
X GND B28 -1100 350 350 R 60 60 1 1 W
X AD[21] B29 -1100 250 350 R 60 60 1 1 B
X GND B3 -1100 2850 350 R 60 60 1 1 I
X AD[19] B30 -1100 150 350 R 60 60 1 1 B
X +3.3V B31 -1100 50 350 R 60 60 1 1 W
X AD[17] B32 -1100 -50 350 R 60 60 1 1 B
X C/BE#[2] B33 -1100 -150 350 R 60 60 1 1 B I
X GND B34 -1100 -250 350 R 60 60 1 1 W
X IRDY# B35 -1100 -350 350 R 60 60 1 1 B I
X +3.3V B36 -1100 -450 350 R 60 60 1 1 W
X DEVSEL# B37 -1100 -550 350 R 60 60 1 1 B I
X GND B38 -1100 -650 350 R 60 60 1 1 W
X LOCK# B39 -1100 -750 350 R 60 60 1 1 B I
X TDO B4 -1100 2750 350 R 60 60 1 1 I
X PERR# B40 -1100 -850 350 R 60 60 1 1 B I
X +3.3V B41 -1100 -950 350 R 60 60 1 1 W
X SERR# B42 -1100 -1050 350 R 60 60 1 1 I I
X +3.3V B43 -1100 -1150 350 R 60 60 1 1 W
X C/BE#[1] B44 -1100 -1250 350 R 60 60 1 1 B I
X AD[14] B45 -1100 -1350 350 R 60 60 1 1 B
X GND B46 -1100 -1450 350 R 60 60 1 1 W
X AD[12] B47 -1100 -1550 350 R 60 60 1 1 B
X AD[10] B48 -1100 -1650 350 R 60 60 1 1 B
X M66EN B49 -1100 -1750 350 R 60 60 1 1 W
X +5V B5 -1100 2650 350 R 60 60 1 1 W
X AD[08] B52 -1100 -2050 350 R 60 60 1 1 B
X AD[07] B53 -1100 -2150 350 R 60 60 1 1 B
X +3.3V B54 -1100 -2250 350 R 60 60 1 1 I
X AD[05] B55 -1100 -2350 350 R 60 60 1 1 B
X AD[03] B56 -1100 -2450 350 R 60 60 1 1 B
X GND B57 -1100 -2550 350 R 60 60 1 1 W
X AD[01] B58 -1100 -2650 350 R 60 60 1 1 B
X VIO B59 -1100 -2750 350 R 60 60 1 1 W
X +5V B6 -1100 2550 350 R 60 60 1 1 W
X ACK64# B60 -1100 -2850 350 R 60 60 1 1 B I
X +5V B61 -1100 -2950 350 R 60 60 1 1 W
X +5V B62 -1100 -3050 350 R 60 60 1 1 W
X INTB# B7 -1100 2450 350 R 60 60 1 1 I I
X INTD# B8 -1100 2350 350 R 60 60 1 1 I I
X PRSNT1# B9 -1100 2250 350 R 60 60 1 1 I I
ENDDRAW
ENDDEF
#
# video_schlib_C
#
DEF video_schlib_C C 0 10 N Y 1 F N
@ -711,7 +578,6 @@ F0 "C" 50 100 40 H V L CNN
F1 "video_schlib_CP" 50 -100 40 H V L CNN
F2 "" 100 -150 30 H V C CNN
F3 "" 50 100 30 H V C CNN
ALIAS CAPAPOL
$FPLIST
CP*
SM*

View File

@ -485,7 +485,7 @@ make_lexer(
schematic.keywords
schematic_lexer.h
schematic_keywords.cpp
TSYMBOL_LIB_T
TSCHEMATIC_T
)
add_subdirectory( plugins )

View File

@ -197,10 +197,12 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
{
// implement the pseudo code from KIWAY_PLAYER.h:
wxString msg;
// This is for python:
if( aFileSet.size() != 1 )
{
UTF8 msg = StrPrintf( "Eeschema:%s() takes only a single filename.", __func__ );
msg.Printf( "Eeschema:%s() takes only a single filename.", __WXFUNCTION__ );
DisplayError( this, msg );
return false;
}
@ -212,8 +214,7 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
if( !LockFile( fullFileName ) )
{
wxString msg = wxString::Format( _( "Schematic file \"%s\" is already open." ),
fullFileName );
msg.Printf( _( "Schematic file \"%s\" is already open." ), fullFileName );
DisplayError( this, msg );
return false;
}
@ -230,9 +231,10 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
if( is_new && !( aCtl & KICTL_CREATE ) )
{
// notify user that fullFileName does not exist, ask if user wants to create it.
wxString ask = wxString::Format( _( "Schematic \"%s\" does not exist. Do you wish to create it?" ),
msg.Printf( _( "Schematic \"%s\" does not exist. Do you wish to create it?" ),
fullFileName );
if( !IsOK( this, ask ) )
if( !IsOK( this, msg ) )
return false;
}
@ -240,8 +242,10 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
{
SetScreen( nullptr );
delete g_RootSheet;
if( g_CurrentSheet )
g_CurrentSheet->clear();
g_RootSheet = nullptr;
CreateScreens();
@ -295,7 +299,9 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
delete g_RootSheet; // Delete the current project.
g_RootSheet = NULL; // Force CreateScreens() to build new empty project on load failure.
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( SCH_IO_MGR::FindPlugin( SCH_IO_MGR::SCH_LEGACY ) );
SCH_IO_MGR::SCH_FILE_T schFileType = SCH_IO_MGR::GuessPluginTypeFromSchPath( fullFileName );
SCH_PLUGIN* plugin = SCH_IO_MGR::FindPlugin( schFileType );
SCH_PLUGIN::SCH_PLUGIN_RELEASER pi( plugin );
// This will rename the file if there is an autosave and the user want to recover
CheckForAutoSaveFile( fullFileName );
@ -324,7 +330,6 @@ bool SCH_EDIT_FRAME::OpenProjectFiles( const std::vector<wxString>& aFileSet, in
CreateScreens();
m_toolManager->RunAction( ACTIONS::zoomFitScreen, true );
wxString msg;
msg.Printf( _( "Error loading schematic file \"%s\".\n%s" ),
GetChars( fullFileName ), GetChars( ioe.What() ) );
DisplayError( this, msg );

View File

@ -780,9 +780,12 @@ void SCH_EDIT_FRAME::NewProject()
void SCH_EDIT_FRAME::LoadProject()
{
wxString pro_dir = m_mruPath;
wxString wildcards = LegacySchematicFileWildcard();
wildcards += "|" + KiCadSchematicFileWildcard();
wxFileDialog dlg( this, _( "Open Schematic" ), pro_dir, wxEmptyString,
LegacySchematicFileWildcard(), wxFD_OPEN | wxFD_FILE_MUST_EXIST );
wildcards, wxFD_OPEN | wxFD_FILE_MUST_EXIST );
if( dlg.ShowModal() != wxID_CANCEL )
{

File diff suppressed because it is too large Load Diff

View File

@ -35,6 +35,7 @@
#include <math/util.h> // KiROUND, Clamp
#include <class_library.h>
#include <general.h>
#include <schematic_lexer.h>
@ -45,8 +46,45 @@ class LIB_ITEM;
class LIB_PIN;
class LIB_POLYLINE;
class LIB_TEXT;
class PAGE_INFO;
class SCH_BITMAP;
class SCH_BUS_WIRE_ENTRY;
class SCH_COMPONENT;
class SCH_FIELD;
class SCH_JUNCTION;
class SCH_LINE;
class SCH_NO_CONNECT;
class SCH_SCREEN;
class SCH_SHEET;
class SCH_SHEET_PIN;
class SCH_TEXT;
class TITLE_BLOCK;
/**
* Simple container to manage line stroke parameters.
*/
class STROKE_PARAMS
{
public:
int m_Width;
PLOT_DASH_TYPE m_Type;
COLOR4D m_Color;
STROKE_PARAMS( int aWidth = GetDefaultLineThickness(),
PLOT_DASH_TYPE aType = PLOT_DASH_TYPE::DEFAULT,
const COLOR4D& aColor = COLOR4D::UNSPECIFIED ) :
m_Width( aWidth ),
m_Type( aType ),
m_Color( aColor )
{
}
};
/**
* Object to parser s-expression symbol library and schematic file formats.
*/
class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
{
int m_requiredVersion; ///< Set to the symbol library file version required.
@ -55,7 +93,13 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
int m_convert; ///< The current body style being parsed.
wxString m_symbolName; ///< The current symbol name.
void parseHeader();
void parseHeader( TSCHEMATIC_T::T aHeaderType, int aFileVersion );
inline long parseHex()
{
NextTok();
return strtol( CurText(), NULL, 16 );
}
inline int parseInt()
{
@ -83,7 +127,7 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
return parseDouble();
}
inline double parseDouble( TSYMBOL_LIB_T::T aToken )
inline double parseDouble( TSCHEMATIC_T::T aToken )
{
return parseDouble( GetTokenText( aToken ) );
}
@ -109,7 +153,7 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
}
inline int parseInternalUnits( TSYMBOL_LIB_T::T aToken )
inline int parseInternalUnits( TSCHEMATIC_T::T aToken )
{
return parseInternalUnits( GetTokenText( aToken ) );
}
@ -124,6 +168,13 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
return xy;
}
/**
* Parse stroke definition \a aStroke.
*
* @param aStrokeDef A reference to the #STROKE_PARAMS structure to write to.
*/
void parseStroke( STROKE_PARAMS& aStroke );
FILL_T parseFillMode();
void parseEDA_TEXT( EDA_TEXT* aText );
@ -139,6 +190,21 @@ class SCH_SEXPR_PARSER : public SCHEMATIC_LEXER
LIB_RECTANGLE* parseRectangle();
LIB_TEXT* parseText();
void parsePAGE_INFO( PAGE_INFO& aPageInfo );
void parseTITLE_BLOCK( TITLE_BLOCK& aTitleBlock );
void parseSchSymbolInstances( std::unique_ptr<SCH_COMPONENT>& aSymbol );
SCH_SHEET_PIN* parseSchSheetPin( SCH_SHEET* aSheet );
SCH_FIELD* parseSchField();
SCH_COMPONENT* parseSchematicSymbol();
SCH_BITMAP* parseImage();
SCH_SHEET* parseSheet();
SCH_JUNCTION* parseJunction();
SCH_NO_CONNECT* parseNoConnect();
SCH_BUS_WIRE_ENTRY* parseBusEntry();
SCH_LINE* parseLine();
SCH_TEXT* parseSchText();
public:
SCH_SEXPR_PARSER( LINE_READER* aLineReader = nullptr );
@ -148,6 +214,15 @@ public:
LIB_ITEM* ParseDrawItem();
/**
* Parse a single schematic file into \a aScreen.
*
* @note This does not load any sub-sheets or decent complex sheet hierarchies.
*
* @param aScreen The #SCH_SCREEN object to store the parsed schematic file.
*/
void ParseSchematic( SCH_SCREEN* aScreen );
/**
* Return whether a version number, if any was parsed, was too recent
*/

View File

@ -75,7 +75,7 @@
#include <confirm.h>
#include <tool/selection.h>
using namespace TSYMBOL_LIB_T;
using namespace TSCHEMATIC_T;
#define SCH_PARSE_ERROR( text, reader, pos ) \
@ -560,105 +560,9 @@ void SCH_SEXPR_PLUGIN::loadFile( const wxString& aFileName, SCH_SCREEN* aScreen
{
FILE_LINE_READER reader( aFileName );
loadHeader( reader, aScreen );
SCH_SEXPR_PARSER parser( &reader );
LoadContent( reader, aScreen, m_version );
}
void SCH_SEXPR_PLUGIN::LoadContent( LINE_READER& aReader, SCH_SCREEN* aScreen, int version )
{
m_version = version;
}
void SCH_SEXPR_PLUGIN::loadHeader( LINE_READER& aReader, SCH_SCREEN* aScreen )
{
}
void SCH_SEXPR_PLUGIN::loadPageSettings( LINE_READER& aReader, SCH_SCREEN* aScreen )
{
wxASSERT( aScreen != NULL );
wxString buf;
PAGE_INFO pageInfo;
TITLE_BLOCK tb;
}
SCH_SHEET* SCH_SEXPR_PLUGIN::loadSheet( LINE_READER& aReader )
{
std::unique_ptr< SCH_SHEET > sheet( new SCH_SHEET() );
// Timesheet time stamps are now automatically generated.
return sheet.release();
}
SCH_BITMAP* SCH_SEXPR_PLUGIN::loadBitmap( LINE_READER& aReader )
{
std::unique_ptr< SCH_BITMAP > bitmap( new SCH_BITMAP );
return bitmap.release();
}
SCH_JUNCTION* SCH_SEXPR_PLUGIN::loadJunction( LINE_READER& aReader )
{
std::unique_ptr< SCH_JUNCTION > junction( new SCH_JUNCTION );
return junction.release();
}
SCH_NO_CONNECT* SCH_SEXPR_PLUGIN::loadNoConnect( LINE_READER& aReader )
{
std::unique_ptr< SCH_NO_CONNECT > no_connect( new SCH_NO_CONNECT );
return no_connect.release();
}
SCH_LINE* SCH_SEXPR_PLUGIN::loadWire( LINE_READER& aReader )
{
std::unique_ptr< SCH_LINE > wire( new SCH_LINE );
return wire.release();
}
SCH_BUS_ENTRY_BASE* SCH_SEXPR_PLUGIN::loadBusEntry( LINE_READER& aReader )
{
std::unique_ptr< SCH_BUS_ENTRY_BASE > busEntry;
return busEntry.release();
}
SCH_TEXT* SCH_SEXPR_PLUGIN::loadText( LINE_READER& aReader )
{
std::unique_ptr< SCH_TEXT> text;
return text.release();
}
SCH_COMPONENT* SCH_SEXPR_PLUGIN::loadComponent( LINE_READER& aReader )
{
std::unique_ptr< SCH_COMPONENT > component( new SCH_COMPONENT() );
return component.release();
}
std::shared_ptr<BUS_ALIAS> SCH_SEXPR_PLUGIN::loadBusAlias( LINE_READER& aReader,
SCH_SCREEN* aScreen )
{
auto busAlias = std::make_shared< BUS_ALIAS >( aScreen );
return busAlias;
parser.ParseSchematic( aScreen );
}
@ -716,8 +620,9 @@ void SCH_SEXPR_PLUGIN::Format( SCH_SCREEN* aScreen )
save_map.insert( item );
KICAD_T itemType = TYPE_NOT_INIT;
SCH_LAYER_ID layer = SCH_LAYER_ID_START;
for( auto& item : save_map )
for( SCH_ITEM* item : save_map )
{
if( itemType != item->Type() )
{
@ -735,32 +640,53 @@ void SCH_SEXPR_PLUGIN::Format( SCH_SCREEN* aScreen )
m_out->Print( 0, "\n" );
saveSymbol( static_cast<SCH_COMPONENT*>( item ), 1 );
break;
case SCH_BITMAP_T:
saveBitmap( static_cast<SCH_BITMAP*>( item ), 1 );
break;
case SCH_SHEET_T:
m_out->Print( 0, "\n" );
saveSheet( static_cast<SCH_SHEET*>( item ), 1 );
break;
case SCH_JUNCTION_T:
saveJunction( static_cast<SCH_JUNCTION*>( item ), 1 );
break;
case SCH_NO_CONNECT_T:
saveNoConnect( static_cast<SCH_NO_CONNECT*>( item ), 1 );
break;
case SCH_BUS_WIRE_ENTRY_T:
case SCH_BUS_BUS_ENTRY_T:
saveBusEntry( static_cast<SCH_BUS_ENTRY_BASE*>( item ), 1 );
break;
case SCH_LINE_T:
if( layer != item->GetLayer() )
{
if( layer == SCH_LAYER_ID_START )
{
layer = item->GetLayer();
}
else
{
layer = item->GetLayer();
m_out->Print( 0, "\n" );
}
}
saveLine( static_cast<SCH_LINE*>( item ), 1 );
break;
case SCH_TEXT_T:
case SCH_LABEL_T:
case SCH_GLOBAL_LABEL_T:
case SCH_HIER_LABEL_T:
saveText( static_cast<SCH_TEXT*>( item ), 1 );
break;
default:
wxASSERT( "Unexpected schematic object type in SCH_SEXPR_PLUGIN::Format()" );
}
@ -783,31 +709,39 @@ void SCH_SEXPR_PLUGIN::Format( SELECTION* aSelection, OUTPUTFORMATTER* aFormatte
case SCH_COMPONENT_T:
saveSymbol( static_cast< SCH_COMPONENT* >( item ), 0 );
break;
case SCH_BITMAP_T:
saveBitmap( static_cast< SCH_BITMAP* >( item ), 0 );
break;
case SCH_SHEET_T:
saveSheet( static_cast< SCH_SHEET* >( item ), 0 );
break;
case SCH_JUNCTION_T:
saveJunction( static_cast< SCH_JUNCTION* >( item ), 0 );
break;
case SCH_NO_CONNECT_T:
saveNoConnect( static_cast< SCH_NO_CONNECT* >( item ), 0 );
break;
case SCH_BUS_WIRE_ENTRY_T:
case SCH_BUS_BUS_ENTRY_T:
saveBusEntry( static_cast< SCH_BUS_ENTRY_BASE* >( item ), 0 );
break;
case SCH_LINE_T:
saveLine( static_cast< SCH_LINE* >( item ), 0 );
break;
case SCH_TEXT_T:
case SCH_LABEL_T:
case SCH_GLOBAL_LABEL_T:
case SCH_HIER_LABEL_T:
saveText( static_cast< SCH_TEXT* >( item ), 0 );
break;
default:
wxASSERT( "Unexpected schematic object type in SCH_SEXPR_PLUGIN::Format()" );
}
@ -819,35 +753,20 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_COMPONENT* aSymbol, int aNestLevel )
{
wxCHECK_RET( aSymbol != nullptr && m_out != nullptr, "" );
std::string name1;
std::string name2;
std::string libName;
wxArrayString reference_fields;
static wxString delimiters( wxT( " " ) );
// This is redundant with the AR entries below, but it makes the files backwards-compatible.
if( aSymbol->GetInstanceReferences().size() > 0 )
{
const COMPONENT_INSTANCE_REFERENCE& instance = aSymbol->GetInstanceReferences()[0];
name1 = toUTFTildaText( instance.m_Reference );
}
else
{
if( aSymbol->GetField( REFERENCE )->GetText().IsEmpty() )
name1 = toUTFTildaText( aSymbol->GetPrefix() );
else
name1 = toUTFTildaText( aSymbol->GetField( REFERENCE )->GetText() );
}
wxString part_name = aSymbol->GetLibId().Format();
if( part_name.size() )
{
name2 = toUTFTildaText( part_name );
libName = toUTFTildaText( part_name );
}
else
{
name2 = "_NONAME_";
libName = "_NONAME_";
}
double angle;
@ -858,20 +777,22 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_COMPONENT* aSymbol, int aNestLevel )
else if( orientation == CMP_ORIENT_180 )
angle = 180.0;
else if( orientation == CMP_ORIENT_270 )
angle = 270;
angle = 270.0;
else
angle = 0.0;
m_out->Print( aNestLevel, "(symbol %s is %s (at %d %d %g)",
m_out->Quotew( name1 ).c_str(), m_out->Quotew( name2 ).c_str(),
aSymbol->GetPosition().x, aSymbol->GetPosition().y, angle );
m_out->Print( aNestLevel, "(symbol (lib_id %s) (at %s %s %s)",
m_out->Quotew( libName ).c_str(),
FormatInternalUnits( aSymbol->GetPosition().x ).c_str(),
FormatInternalUnits( aSymbol->GetPosition().y ).c_str(),
FormatAngle( angle * 10.0 ).c_str() );
bool mirrorX = aSymbol->GetOrientation() & CMP_MIRROR_X;
bool mirrorY = aSymbol->GetOrientation() & CMP_MIRROR_Y;
if( mirrorX || mirrorY )
{
m_out->Print( 0, "(mirror" );
m_out->Print( 0, " (mirror" );
if( mirrorX )
m_out->Print( 0, " x" );
@ -879,12 +800,13 @@ void SCH_SEXPR_PLUGIN::saveSymbol( SCH_COMPONENT* aSymbol, int aNestLevel )
if( mirrorY )
m_out->Print( 0, " y" );
m_out->Print( 0, ")\n" );
m_out->Print( 0, ")" );
}
if( !( aSymbol->GetInstanceReferences().size() > 1 ) )
m_out->Print( 0, " (unit %d)\n", aSymbol->GetUnit() );
else
{
m_out->Print( 0, "\n" );
}
// @todo Convert to full UUID if current UUID is a legacy time stamp.
m_out->Print( aNestLevel + 1, "(uuid %s)\n",
@ -945,18 +867,21 @@ void SCH_SEXPR_PLUGIN::saveField( SCH_FIELD* aField, int aNestLevel )
wxString fieldName;
// For some reason (bug in legacy parser?) the field ID for non-mandatory fields is -1 so
// check for this in order to correctly use the field name.
if( aField->GetId() >= 0 && aField->GetId() < MANDATORY_FIELDS )
fieldName = "ki_" + TEMPLATE_FIELDNAME::GetDefaultFieldName( aField->GetId() ).Lower();
else
fieldName = aField->GetName();
m_out->Print( aNestLevel, "(property %s %s (at %d %d %g)",
m_out->Print( aNestLevel, "(property %s %s (at %s %s %s)",
m_out->Quotew( fieldName ).c_str(),
m_out->Quotew( aField->GetText() ).c_str(),
aField->GetPosition().x, aField->GetPosition().y,
aField->GetTextAngleDegrees() );
FormatInternalUnits( aField->GetPosition().x ).c_str(),
FormatInternalUnits( aField->GetPosition().y ).c_str(),
FormatAngle( aField->GetTextAngleDegrees() * 10.0 ).c_str() );
if( !aField->IsDefaultFormatting() )
if( !aField->IsDefaultFormatting() || ( aField->GetTextHeight() != GetDefaultTextSize() ) )
{
m_out->Print( 0, "\n" );
aField->Format( m_out, aNestLevel, 0 );
@ -977,8 +902,9 @@ void SCH_SEXPR_PLUGIN::saveBitmap( SCH_BITMAP* aBitmap, int aNestLevel )
wxCHECK_RET( image != NULL, "wxImage* is NULL" );
m_out->Print( aNestLevel, "(image (at %d %d)",
aBitmap->GetPosition().x, aBitmap->GetPosition().y );
m_out->Print( aNestLevel, "(image (at %s %s)",
FormatInternalUnits( aBitmap->GetPosition().x ).c_str(),
FormatInternalUnits( aBitmap->GetPosition().y ).c_str() );
if( aBitmap->GetImage()->GetScale() != 1.0 )
m_out->Print( 0, " (scale %g)", aBitmap->GetImage()->GetScale() );
@ -996,19 +922,20 @@ void SCH_SEXPR_PLUGIN::saveBitmap( SCH_BITMAP* aBitmap, int aNestLevel )
for( int ii = 0; begin < buffer->GetBufferEnd(); begin++, ii++ )
{
if( ii % 32 )
if( ii % 16 )
{
m_out->Print( 0, " %2.2X ", *begin & 0xFF );
m_out->Print( 0, " 0x%2.2X", *begin & 0xFF );
}
else
{
ii = 0;
m_out->Print( 0, "\n" );
m_out->Print( aNestLevel + 2, "%2.2X ", *begin & 0xFF );
m_out->Print( aNestLevel + 2, "0x%2.2X", *begin & 0xFF );
}
}
m_out->Print( 0, "\n" );
m_out->Print( aNestLevel + 1, ")\n" ); // Closes data token.
m_out->Print( aNestLevel, ")\n" ); // Closes image token.
}
@ -1018,13 +945,13 @@ void SCH_SEXPR_PLUGIN::saveSheet( SCH_SHEET* aSheet, int aNestLevel )
{
wxCHECK_RET( aSheet != nullptr && m_out != nullptr, "" );
m_out->Print( aNestLevel, "(sheet (start %s %s) (end %s %s)",
m_out->Print( aNestLevel, "(sheet (at %s %s) (size %s %s)",
FormatInternalUnits( aSheet->GetPosition().x ).c_str(),
FormatInternalUnits( aSheet->GetPosition().y ).c_str(),
FormatInternalUnits( aSheet->GetSize().GetWidth() ).c_str(),
FormatInternalUnits( aSheet->GetSize().GetHeight() ).c_str() );
if( aSheet->UsesDefaultStroke() )
if( !aSheet->UsesDefaultStroke() )
{
m_out->Print( 0, " " );
formatStroke( m_out, 0, aSheet->GetBorderWidth(), PLOT_DASH_TYPE::SOLID,
@ -1037,19 +964,26 @@ void SCH_SEXPR_PLUGIN::saveSheet( SCH_SHEET* aSheet, int aNestLevel )
for( auto field : aSheet->GetFields() )
{
saveField( &field, aNestLevel + 1 );
SCH_FIELD tmp = field;
if( field.GetId() == SHEETNAME )
tmp.SetName( "ki_sheet_name" );
else if( field.GetId() == SHEETFILENAME )
tmp.SetName( "ki_sheet_file" );
saveField( &tmp, aNestLevel + 1 );
}
for( const auto pin : aSheet->GetPins() )
{
m_out->Print( aNestLevel + 1, "(pin %s %s at( %s %s %g)",
m_out->Print( aNestLevel + 1, "(pin %s %s (at %s %s %s)",
EscapedUTF8( pin->GetText() ).c_str(),
getSheetPinShapeToken( pin->GetShape() ),
FormatInternalUnits( pin->GetPosition().x ).c_str(),
FormatInternalUnits( pin->GetPosition().y ).c_str(),
getSheetPinAngle( pin->GetEdge() ) );
FormatAngle( getSheetPinAngle( pin->GetEdge() ) * 10.0 ).c_str() );
if( !pin->IsDefaultFormatting() )
if( !pin->IsDefaultFormatting() || ( pin->GetTextHeight() != GetDefaultTextSize() ) )
{
m_out->Print( 0, "\n" );
pin->Format( m_out, aNestLevel + 1, 0 );
@ -1099,11 +1033,11 @@ void SCH_SEXPR_PLUGIN::saveBusEntry( SCH_BUS_ENTRY_BASE* aBusEntry, int aNestLev
}
else
{
m_out->Print( aNestLevel, "(bus_entry (start %s %s) (end %s %s))\n",
m_out->Print( aNestLevel, "(bus_entry (at %s %s) (size %s %s))\n",
FormatInternalUnits( aBusEntry->GetPosition().x ).c_str(),
FormatInternalUnits( aBusEntry->GetPosition().y ).c_str(),
FormatInternalUnits( aBusEntry->m_End().x ).c_str(),
FormatInternalUnits( aBusEntry->m_End().y ).c_str() );
FormatInternalUnits( aBusEntry->GetSize().GetWidth() ).c_str(),
FormatInternalUnits( aBusEntry->GetSize().GetHeight() ).c_str() );
}
}
@ -1144,19 +1078,30 @@ void SCH_SEXPR_PLUGIN::saveText( SCH_TEXT* aText, int aNestLevel )
{
wxCHECK_RET( aText != nullptr && m_out != nullptr, "" );
double angle;
switch( aText->GetLabelSpinStyle() )
{
case LABEL_SPIN_STYLE::RIGHT: angle = 0.0; break;
case LABEL_SPIN_STYLE::UP: angle = 90.0; break;
case LABEL_SPIN_STYLE::LEFT: angle = 180.0; break;
case LABEL_SPIN_STYLE::BOTTOM: angle = 270.0; break;
default: wxFAIL; angle = 0.0; break;
}
m_out->Print( aNestLevel, "(%s %s",
getTextTypeToken( aText->Type() ),
m_out->Quotew( aText->GetText() ).c_str() );
if( ( aText->Type() == SCH_GLOBAL_LABEL_T ) || ( aText->Type() == SCH_HIER_LABEL_T ) )
m_out->Print( 0, " %s", getSheetPinShapeToken( aText->GetShape() ) );
m_out->Print( 0, " (shape %s)", getSheetPinShapeToken( aText->GetShape() ) );
if( aText->GetText().Length() < 50 )
{
m_out->Print( 0, " (at %s %s %s)",
FormatInternalUnits( aText->GetPosition().x ).c_str(),
FormatInternalUnits( aText->GetPosition().y ).c_str(),
FormatAngle( aText->GetTextAngle() ).c_str() );
FormatAngle( angle * 10.0 ).c_str() );
}
else
{
@ -1167,7 +1112,7 @@ void SCH_SEXPR_PLUGIN::saveText( SCH_TEXT* aText, int aNestLevel )
FormatAngle( aText->GetTextAngle() ).c_str() );
}
if( !aText->IsDefaultFormatting() )
if( !aText->IsDefaultFormatting() || ( aText->GetTextHeight() != GetDefaultTextSize() ) )
{
m_out->Print( 0, "\n" );
aText->Format( m_out, aNestLevel + 1, 0 );

View File

@ -127,18 +127,7 @@ public:
private:
void loadHierarchy( SCH_SHEET* aSheet );
void loadHeader( LINE_READER& aReader, SCH_SCREEN* aScreen );
void loadPageSettings( LINE_READER& aReader, SCH_SCREEN* aScreen );
void loadFile( const wxString& aFileName, SCH_SCREEN* aScreen );
SCH_SHEET* loadSheet( LINE_READER& aReader );
SCH_BITMAP* loadBitmap( LINE_READER& aReader );
SCH_JUNCTION* loadJunction( LINE_READER& aReader );
SCH_NO_CONNECT* loadNoConnect( LINE_READER& aReader );
SCH_LINE* loadWire( LINE_READER& aReader );
SCH_BUS_ENTRY_BASE* loadBusEntry( LINE_READER& aReader );
SCH_TEXT* loadText( LINE_READER& aReader );
SCH_COMPONENT* loadComponent( LINE_READER& aReader );
std::shared_ptr<BUS_ALIAS> loadBusAlias( LINE_READER& aReader, SCH_SCREEN* aScreen );
void saveSymbol( SCH_COMPONENT* aComponent, int aNestLevel );
void saveField( SCH_FIELD* aField, int aNestLevel );

View File

@ -228,6 +228,7 @@ void SCH_SHEET::AddPin( SCH_SHEET_PIN* aSheetPin )
wxASSERT( aSheetPin != NULL );
wxASSERT( aSheetPin->Type() == SCH_SHEET_PIN_T );
aSheetPin->SetParent( this );
m_pins.push_back( aSheetPin );
renumberPins();
}

View File

@ -7,13 +7,23 @@ atomic
background
bezier
bidirectional
bitmap
bold
bottom
bus
bus_entry
center
circle
clock
clock_low
color
comment
company
dash
dash_dot
data
date
dot
edge_clock_high
effects
end
@ -25,21 +35,26 @@ hide
hierarchical_label
hint_alt_swap
hint_pin_swap
image
input
input_low
instances
inverted
inverted_clock
italic
junction
justify
kicad_sch
kicad_symbol_lib
label
left
length
lib_id
line
mid
mirror
name
no_connect
non_logic
none
number
@ -50,7 +65,9 @@ outline
output_low
unconnected
output
page
passive
path
pin
pin_del
pin_names
@ -58,6 +75,7 @@ pin_numbers
pin_merge
pin_rename
polyline
portrait
power
power_in
power_out
@ -66,20 +84,31 @@ property_del
pts
radius
rectangle
reference
required
rev
right
scale
shape
sheet
size
solid
start
stroke
symbol
text
thickness
title
title_block
top
tri_state
type
unit
unspecified
uuid
version
width
wire
xy
x
y